Skip to content

Commit

Permalink
Do validation in install command.
Browse files Browse the repository at this point in the history
Rather than as a "type" to the parser. This means any resultant
CommandErrors are caught and presented properly, rather than a
stack dump.
  • Loading branch information
powlo committed Feb 6, 2025
1 parent c4f1e39 commit afbbd40
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 24 deletions.
40 changes: 19 additions & 21 deletions src/django_nomad/management/commands/nomad.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,22 +11,6 @@
from django.db.migrations.loader import MigrationLoader


def valid_path_for_hooks(path):
# A validator that ensures the given path is a git repo with hooks,
# but does not contain a post-checkout script.
path = Path(path)
git_path = path / ".git"
githooks_path = git_path / "hooks"
post_checkout_file = githooks_path / "post-checkout"
if not git_path.is_dir():
raise CommandError(f"'{path}' does not appear to contain a git repo.")
elif not githooks_path:
raise CommandError(f"'{path}' does not contain a 'hooks' directory.")
elif post_checkout_file.is_file():
raise CommandError(f"'{path}' already contains a post-checkout hook.")
return path


def stage_one():
base_path = Path(".")
filename = base_path / ".nomad" / "nodes.json"
Expand Down Expand Up @@ -88,7 +72,7 @@ def add_arguments(self, parser):
help="Installs the command to run in a 'post-checkout' git hook.",
)
install_parser.set_defaults(method=self.install)
install_parser.add_argument("dest", type=valid_path_for_hooks)
install_parser.add_argument("dest")

migrate_parser = subparsers.add_parser(
"migrate",
Expand All @@ -101,13 +85,27 @@ def handle(self, *args, method, **options):
method(*args, **options)

def install(self, *args, **options):
git_hooks_path = options["dest"] / ".git" / "hooks"
post_checkout_file = (
path = Path(options["dest"])
git_path = path / ".git"

# Validate the given destination.
if not git_path.is_dir():
raise CommandError(f"'{path}' does not appear to contain a git repo.")

dest_git_hooks_path = path / ".git" / "hooks"
if not dest_git_hooks_path:
raise CommandError(f"'{path}' does not contain a 'hooks' directory.")

dest_post_checkout_file = dest_git_hooks_path / "post-checkout"
if dest_post_checkout_file.is_file():
raise CommandError(f"'{path}' already contains a post-checkout hook.")

src_post_checkout_file = (
resources.files("django_nomad") / "hook_templates" / "post-checkout"
)

shutil.copy(post_checkout_file, git_hooks_path)
self.stdout.write(f"git hook created: {post_checkout_file}")
shutil.copy(src_post_checkout_file, dest_git_hooks_path)
self.stdout.write(f"git hook created: {dest_post_checkout_file}")

def migrate(self, *args, **options):
DJANGO_NOMAD_STAGE = os.environ.get("DJANGO_NOMAD_STAGE")
Expand Down
8 changes: 5 additions & 3 deletions tests/test_command.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,16 +89,18 @@ def call_command(self, *args, **kwargs):
)
return out.getvalue(), err.getvalue()

@mock.patch("django_nomad.management.commands.nomad.valid_path_for_hooks")
@mock.patch(
"django_nomad.management.commands.nomad.Path",
get_mock_path(is_dir=True, is_true=True, is_file=False),
)
@mock.patch("django_nomad.management.commands.nomad.shutil.copy")
def test_install(self, mock_copy, mock_valid_path_for_hooks):
def test_install(self, mock_copy):
out, err = self.call_command("install", "/a/destination/")

self.assertTrue(out.startswith("git hook created: "))
self.assertEqual(err, "")

mock_copy.assert_called_once()
mock_valid_path_for_hooks.assert_called_once()

@mock.patch("django_nomad.management.commands.nomad.stage_one")
def test_migrate_stage_one(self, mock_stage_one):
Expand Down

0 comments on commit afbbd40

Please # to comment.