fix: handle git worktrees in GitStore nested repo protection

Treat `.git` files the same as `.git` directories so GitStore refuses to initialize inside git worktrees, and add a focused regression test for that checkout shape.

Made-with: Cursor
This commit is contained in:
Xubin Ren
2026-04-19 03:38:22 +08:00
committed by Xubin Ren
parent ff5b97dc34
commit e08507f3ce
2 changed files with 47 additions and 2 deletions
+5 -2
View File
@@ -180,11 +180,14 @@ class GitStore:
"""Check if self._workspace is already inside a git repository.
Walks up from self._workspace to the filesystem root, returning True
if any parent directory contains a .git directory.
if any parent directory contains a .git entry.
Git worktrees and submodules can use a ``.git`` file instead of a
directory, so we must treat either form as "already inside a repo".
"""
current = self._workspace.resolve()
while current != current.parent:
if (current / ".git").is_dir():
if (current / ".git").exists():
return True
current = current.parent
return False
+42
View File
@@ -1,5 +1,6 @@
"""Tests for GitStore — line_ages() and core git operations."""
import subprocess
import time
from datetime import datetime, timedelta, timezone
from unittest.mock import patch
@@ -172,3 +173,44 @@ class TestNestedRepoProtection:
assert result is True
assert (workspace / ".git").is_dir()
def test_init_refuses_inside_git_worktree(self, tmp_path):
"""init() should refuse when the parent checkout is a git worktree."""
repo = tmp_path / "repo"
repo.mkdir()
subprocess.run(["git", "init", "-q", str(repo)], check=True)
(repo / "README.md").write_text("x\n", encoding="utf-8")
subprocess.run(["git", "-C", str(repo), "add", "README.md"], check=True)
subprocess.run(
[
"git",
"-C",
str(repo),
"-c",
"user.name=test",
"-c",
"user.email=test@example.com",
"commit",
"-q",
"-m",
"init",
],
check=True,
)
subprocess.run(["git", "-C", str(repo), "branch", "wt-branch"], check=True)
worktree = tmp_path / "worktree"
subprocess.run(
["git", "-C", str(repo), "worktree", "add", "-q", str(worktree), "wt-branch"],
check=True,
)
assert (worktree / ".git").is_file()
workspace = worktree / "workspace"
workspace.mkdir()
g = GitStore(workspace, tracked_files=["MEMORY.md"])
result = g.init()
assert result is False
assert not (workspace / ".git").exists()