diff --git a/pkgs/clan-cli/clan_cli/dirs.py b/pkgs/clan-cli/clan_cli/dirs.py index 064f52f..b3d5a2e 100644 --- a/pkgs/clan-cli/clan_cli/dirs.py +++ b/pkgs/clan-cli/clan_cli/dirs.py @@ -6,8 +6,16 @@ from .errors import ClanError def get_clan_flake_toplevel() -> Path: + return find_toplevel([".clan-flake", ".git", ".hg", ".svn", "flake.nix"]) + + +def find_git_repo_root() -> Path: + return find_toplevel([".git"]) + + +def find_toplevel(top_level_files: list[str]) -> Path: """Returns the path to the toplevel of the clan flake""" - for project_file in [".clan-flake", ".git", ".hg", ".svn", "flake.nix"]: + for project_file in top_level_files: initial_path = Path(os.getcwd()) path = Path(initial_path) while path.parent != path: diff --git a/pkgs/clan-cli/clan_cli/git.py b/pkgs/clan-cli/clan_cli/git.py index bb2d7ce..700d0aa 100644 --- a/pkgs/clan-cli/clan_cli/git.py +++ b/pkgs/clan-cli/clan_cli/git.py @@ -2,7 +2,7 @@ import subprocess from pathlib import Path from typing import Optional -from clan_cli.dirs import get_clan_flake_toplevel +from clan_cli.dirs import find_git_repo_root from clan_cli.errors import ClanError from clan_cli.nix import nix_shell @@ -15,7 +15,7 @@ def commit_file( ) -> None: # set default for repo_dir if repo_dir is None: - repo_dir = get_clan_flake_toplevel() + repo_dir = find_git_repo_root() # check that the file is in the git repository and exists if not Path(file_path).resolve().is_relative_to(repo_dir.resolve()): raise ClanError(f"File {file_path} is not in the git repository {repo_dir}") @@ -43,7 +43,10 @@ def _commit_file_to_git(repo_dir: Path, file_path: Path, commit_message: str) -> # add the file to the git index subprocess.run(["git", "add", file_path], cwd=repo_dir, check=True) # commit only that file - cmd = nix_shell(["git"], ["git", "commit", "-m", commit_message, file_path.name]) + cmd = nix_shell( + ["git"], + ["git", "commit", "-m", commit_message, str(file_path.relative_to(repo_dir))], + ) subprocess.run( cmd, cwd=repo_dir, diff --git a/pkgs/clan-cli/tests/test_git.py b/pkgs/clan-cli/tests/test_git.py index 983dd60..fc69c7b 100644 --- a/pkgs/clan-cli/tests/test_git.py +++ b/pkgs/clan-cli/tests/test_git.py @@ -38,3 +38,30 @@ def test_commit_file_not_existing_raises_error(git_repo: Path) -> None: # commit a file that does not exist with pytest.raises(ClanError): git.commit_file(Path("test.txt"), git_repo, "test commit") + + +def test_clan_flake_in_subdir(git_repo: Path, monkeypatch: pytest.MonkeyPatch) -> None: + # create a clan_flake subdirectory + (git_repo / "clan_flake").mkdir() + # create a .clan-flake file + (git_repo / "clan_flake" / ".clan-flake").touch() + # change to the clan_flake subdirectory + monkeypatch.chdir(git_repo / "clan_flake") + # commit files to git + subprocess.run(["git", "add", "."], cwd=git_repo) + subprocess.run(["git", "commit", "-m", "init"], cwd=git_repo) + # add a new file under ./clan_flake + (git_repo / "clan_flake" / "test.txt").touch() + # commit the file + git.commit_file(git_repo / "clan_flake" / "test.txt", git_repo, "test commit") + # check that the repo directory does in fact contain the file + assert (git_repo / "clan_flake" / "test.txt").exists() + # check that the working tree is clean + assert not subprocess.check_output(["git", "status", "--porcelain"], cwd=git_repo) + # check that the latest commit message is correct + assert ( + subprocess.check_output( + ["git", "log", "-1", "--pretty=%B"], cwd=git_repo + ).decode("utf-8") + == "test commit\n\n" + )