fix(worktrees): reuse project root for current branch (#77)

This commit is contained in:
banteg
2026-01-10 01:23:01 +04:00
committed by GitHub
parent 81618e48e4
commit 31f84c0a4e
2 changed files with 41 additions and 2 deletions
+18 -2
View File
@@ -4,7 +4,13 @@ from pathlib import Path
from .config import ProjectConfig, ProjectsConfig from .config import ProjectConfig, ProjectsConfig
from .context import RunContext from .context import RunContext
from .utils.git import git_is_worktree, git_ok, git_run, resolve_default_base from .utils.git import (
git_is_worktree,
git_ok,
git_run,
git_stdout,
resolve_default_base,
)
class WorktreeError(RuntimeError): class WorktreeError(RuntimeError):
@@ -23,7 +29,10 @@ def resolve_run_cwd(
raise WorktreeError(f"unknown project {context.project!r}") raise WorktreeError(f"unknown project {context.project!r}")
if context.branch is None: if context.branch is None:
return project.path return project.path
return ensure_worktree(project, context.branch) branch = _sanitize_branch(context.branch)
if _matches_project_branch(project.path, branch):
return project.path
return ensure_worktree(project, branch)
def ensure_worktree(project: ProjectConfig, branch: str) -> Path: def ensure_worktree(project: ProjectConfig, branch: str) -> Path:
@@ -112,6 +121,13 @@ def _sanitize_branch(branch: str) -> str:
return cleaned return cleaned
def _matches_project_branch(root: Path, branch: str) -> bool:
current = git_stdout(["branch", "--show-current"], cwd=root)
if not current:
return False
return current == branch
def _ensure_within_root(root: Path, path: Path) -> None: def _ensure_within_root(root: Path, path: Path) -> None:
root_resolved = root.resolve(strict=False) root_resolved = root.resolve(strict=False)
path_resolved = path.resolve(strict=False) path_resolved = path.resolve(strict=False)
+23
View File
@@ -34,6 +34,29 @@ def test_resolve_run_cwd_rejects_invalid_branch(tmp_path: Path) -> None:
resolve_run_cwd(ctx, projects=projects) resolve_run_cwd(ctx, projects=projects)
def test_resolve_run_cwd_uses_root_when_branch_matches(
monkeypatch, tmp_path: Path
) -> None:
projects = _projects_config(tmp_path)
def _fake_stdout(args, **_kwargs):
if args == ["branch", "--show-current"]:
return "main"
return None
def _unexpected(*_args, **_kwargs):
raise AssertionError("unexpected")
monkeypatch.setattr("takopi.worktrees.git_stdout", _fake_stdout)
monkeypatch.setattr(
"takopi.worktrees.ensure_worktree",
_unexpected,
)
ctx = RunContext(project="z80", branch="main")
assert resolve_run_cwd(ctx, projects=projects) == tmp_path
def test_ensure_worktree_creates_from_base(monkeypatch, tmp_path: Path) -> None: def test_ensure_worktree_creates_from_base(monkeypatch, tmp_path: Path) -> None:
project = ProjectConfig( project = ProjectConfig(
alias="z80", alias="z80",