diff --git a/src/takopi/utils/git.py b/src/takopi/utils/git.py index 75d1028..4279c4f 100644 --- a/src/takopi/utils/git.py +++ b/src/takopi/utils/git.py @@ -40,7 +40,13 @@ def git_ok(args: Sequence[str], *, cwd: Path) -> bool: def git_is_worktree(path: Path) -> bool: - return git_stdout(["rev-parse", "--is-inside-work-tree"], cwd=path) == "true" + top = git_stdout( + ["rev-parse", "--path-format=absolute", "--show-toplevel"], + cwd=path, + ) + if not top: + return False + return Path(top).resolve(strict=False) == path.resolve(strict=False) def resolve_default_base(root: Path) -> str | None: diff --git a/tests/test_worktrees.py b/tests/test_worktrees.py index 33fcfe8..eaf9431 100644 --- a/tests/test_worktrees.py +++ b/tests/test_worktrees.py @@ -54,3 +54,27 @@ def test_ensure_worktree_creates_from_base(monkeypatch, tmp_path: Path) -> None: worktree_path = ensure_worktree(project, "feat/name") assert worktree_path == tmp_path / ".worktrees" / "feat" / "name" assert calls == [["worktree", "add", "-b", "feat/name", str(worktree_path), "main"]] + + +def test_ensure_worktree_rejects_existing_non_worktree( + monkeypatch, tmp_path: Path +) -> None: + project = ProjectConfig( + alias="z80", + path=tmp_path, + worktrees_dir=Path(".worktrees"), + ) + worktree_path = tmp_path / ".worktrees" / "foo" + worktree_path.mkdir(parents=True) + + def _fake_stdout(args, **kwargs): + if args == ["rev-parse", "--is-inside-work-tree"]: + return "true" + if args == ["rev-parse", "--path-format=absolute", "--show-toplevel"]: + return str(tmp_path) + return None + + monkeypatch.setattr("takopi.utils.git.git_stdout", _fake_stdout) + + with pytest.raises(WorktreeError, match="exists but is not a git worktree"): + ensure_worktree(project, "foo")