From 8076807f225280e4aecb0da01c96f077a49f6169 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?c=C4=83t=C4=83lin?= Date: Wed, 4 Sep 2024 18:57:27 +0200 Subject: [PATCH] feat: add `git push` subcommand --- README.md | 1 - halig/__version__.py | 2 +- halig/commands/git/base.py | 28 +++++++++++++++++++++ halig/commands/git/commit.py | 29 ++-------------------- halig/commands/git/push.py | 12 +++++++++ halig/literals.py | 3 ++- halig/main.py | 10 ++++++++ tests/commands/test_git/test_push.py | 37 ++++++++++++++++++++++++++++ 8 files changed, 92 insertions(+), 30 deletions(-) create mode 100644 halig/commands/git/base.py create mode 100644 halig/commands/git/push.py create mode 100644 tests/commands/test_git/test_push.py diff --git a/README.md b/README.md index 7d520f8..affa8dc 100644 --- a/README.md +++ b/README.md @@ -51,6 +51,5 @@ halig edit some_notebook # edit today's note relative to /some_notebook/foo.age halig notebooks # list current notebooks halig git commit -halig git pull halig git push ``` diff --git a/halig/__version__.py b/halig/__version__.py index dd9b22c..c366355 100644 --- a/halig/__version__.py +++ b/halig/__version__.py @@ -1 +1 @@ -__version__ = "0.5.1" +__version__ = "0.5.1a2" diff --git a/halig/commands/git/base.py b/halig/commands/git/base.py new file mode 100644 index 0000000..f2ba8bc --- /dev/null +++ b/halig/commands/git/base.py @@ -0,0 +1,28 @@ +from pathlib import Path + +from git import Repo +from rich import print + +from halig.commands.base import BaseCommand +from halig.encryption import Encryptor +from halig.settings import Settings + + +class GitBaseCommand(BaseCommand): + @staticmethod + def __init_repo(repo_path: Path) -> Repo: + """Check if `repo_path` is a git repo. If not, initialize it""" + + if not (repo_path / ".git").is_dir(): + print(f"[yellow] {repo_path} is not a git repo, initializing ...") + Repo.init(repo_path) + return Repo(repo_path) + + return Repo(repo_path) + + def __init__(self, settings: Settings, message: str | None = None): + super().__init__(settings) + self.settings = settings + self.encryptor = Encryptor(self.settings) + self.message = message or self.settings.default_commit_message + self.repo = self.__init_repo(self.settings.notebooks_root_path) diff --git a/halig/commands/git/commit.py b/halig/commands/git/commit.py index d8ba4b6..56ae67a 100644 --- a/halig/commands/git/commit.py +++ b/halig/commands/git/commit.py @@ -1,32 +1,7 @@ -from pathlib import Path - -from git import Repo -from rich import print - -from halig.commands.base import BaseCommand -from halig.encryption import Encryptor -from halig.settings import Settings +from halig.commands.git.base import GitBaseCommand -class GitCommitCommand(BaseCommand): - @staticmethod - def __init_repo(repo_path: Path) -> Repo: - """Check if `repo_path` is a git repo. If not, initialize it""" - - if not (repo_path / ".git").is_dir(): - print(f"[yellow] {repo_path} is not a git repo, initializing ...") - Repo.init(repo_path) - return Repo(repo_path) - - return Repo(repo_path) - - def __init__(self, settings: Settings, message: str | None = None): - super().__init__(settings) - self.settings = settings - self.encryptor = Encryptor(self.settings) - self.message = message or self.settings.default_commit_message - self.repo = self.__init_repo(self.settings.notebooks_root_path) - +class GitCommitCommand(GitBaseCommand): def run(self): """Add all .age files to git and commit them using gitpython""" self.repo.index.add( diff --git a/halig/commands/git/push.py b/halig/commands/git/push.py new file mode 100644 index 0000000..0ef9b2b --- /dev/null +++ b/halig/commands/git/push.py @@ -0,0 +1,12 @@ +from halig.commands.git.base import GitBaseCommand + + +class GitPushCommand(GitBaseCommand): + def run(self, remotes: list[str] | None = None): + """Push all changes to the remote git repo""" + if not remotes: + self.repo.remotes.origin.push() + return + + for remote in remotes: + self.repo.remotes[remote].push() diff --git a/halig/literals.py b/halig/literals.py index 0bbf9ad..4cb6b4d 100644 --- a/halig/literals.py +++ b/halig/literals.py @@ -12,7 +12,8 @@ which are indexed into a SQLite FTS5 database located at `~/.cache/halig/halig.d COMMANDS_REENCRYPT_HELP = """Reencrypt all available notes. This operation is useful when new public keys have been added to the config file and you want the notes to be seen by the new pairing private keys""" -COMMANDS_GIT_COMMIT_HELP = """Commit all .age files to git""" +COMMANDS_GIT_COMMIT_HELP = "Commit all .age files to git" +COMMANDS_GIT_PUSH_HELP = "Push all .age files to git" # OPTIONS OPTION_CONFIG_HELP = "Configuration file. Must be YAML and schema compatible" diff --git a/halig/main.py b/halig/main.py index 3abb344..47c0ce0 100644 --- a/halig/main.py +++ b/halig/main.py @@ -10,6 +10,7 @@ from halig import literals from halig.__version__ import __version__ from halig.commands.edit import EditCommand from halig.commands.git.commit import GitCommitCommand +from halig.commands.git.push import GitPushCommand from halig.commands.import_unencrypted import ImportCommand from halig.commands.notebooks import NotebooksCommand from halig.commands.reencrypt import ReencryptCommand @@ -165,6 +166,15 @@ def git_commit( command.run() +@git_app.command(name="push", help=literals.COMMANDS_GIT_PUSH_HELP) +def git_push( + config: Path | None = config_option, +): + settings = load_from_file(config) + command = GitPushCommand(settings=settings) + command.run() + + @app.command(help=literals.COMMANDS_VERSION) @capture def version(): diff --git a/tests/commands/test_git/test_push.py b/tests/commands/test_git/test_push.py new file mode 100644 index 0000000..a560c67 --- /dev/null +++ b/tests/commands/test_git/test_push.py @@ -0,0 +1,37 @@ +import shutil + +import pytest + +from halig.commands.git.commit import GitCommitCommand +from halig.commands.git.push import GitPushCommand + + +@pytest.fixture +def command(settings, faker): + """Configure a local remote for testing""" + commit_command = GitCommitCommand(settings) + new_path = shutil.copytree(settings.notebooks_root_path , settings.notebooks_root_path / "../remote") + new_path = new_path.resolve() + for _ in range(10): + random_age_file = settings.notebooks_root_path / f"{faker.word()}.age" + random_age_file.touch() + commit_command.run() + + push_command = GitPushCommand(settings) + + push_command.repo.create_remote("origin", str(new_path)) + + return push_command + + +def test_push_to_origin(settings, command): + """Test that the command pushes to the origin remote""" + command.run() + +def test_push_to_custom_remote(settings, command): + """Test that the command pushes to a custom remote""" + + remote_path = settings.notebooks_root_path / "../remote" + command.repo.create_remote("custom", str(remote_path.resolve())) + + command.run(remotes=["custom"]) \ No newline at end of file