feat: detect bare repositories and model 4-state RepoContext#136
feat: detect bare repositories and model 4-state RepoContext#136k1LoW merged 3 commits intok1LoW:mainfrom
Conversation
Add RepoContext struct with Bare and Worktree fields to distinguish four repository states: normal repo, linked worktree, bare repo root, and worktree-from-bare. DetectRepoContext uses git worktree list porcelain output for bare detection and rev-parse --show-toplevel for worktree detection. IsBareRepository is retained as a convenience wrapper. AssertNotBareRepository guards are added to list, add/switch, and delete operations in cmd/root.go.
k1LoW
left a comment
There was a problem hiding this comment.
The RepoContext approach is really nice!!!
It centralizes repository state detection in one place, and using git worktree list --porcelain correctly handles the case where git rev-parse --is-bare-repository returns false inside a worktree created from a bare repo.
How about taking this a step further and threading it through context.Context in this PR?
Currently, each AssertNotBareRepository call runs DetectRepoContext → git worktree list --porcelain, so computing it once and reusing it would also be a nice efficiency win.
rc, err := git.DetectRepoContext(ctx)
ctx = git.WithRepoContext(ctx, rc)
// In each function:
rc := git.RepoContextFrom(ctx)This would also make it straightforward to integrate bare repo support in the future. Each function can just reference RepoContextFrom(ctx).
Co-authored-by: Ken’ichiro Oyama <[email protected]>
|
Thanks for the suggestion! I agree that caching would be very efficient if possible. However, due to the nature of I understand that the directory change is currently done within the btw, Longer term, it might be nice to define an interface that encapsulates repo operations based on the current But this is probably YAGNI for the current change. |
Store the detected RepoContext in context.Context via WithRepoContext/ RepoContextFrom, so that subsequent calls to DetectRepoContext (through AssertNotBareRepository etc.) reuse the cached result instead of spawning git processes repeatedly. The cache is invalidated when the working directory changes for safety. Co-Authored-By: Claude Opus 4.6 <[email protected]>
There are no
OK! I'll keep the cwd check as a safety measure for now, but since there's currently no case where cwd changes during execution, the os.Getwd() check in RepoContextFrom is effectively dead code. |
sure! |
Summary
Bare repositories have no working tree, so git-wt's core operations (list, add/switch, delete) cannot function correctly in them. This PR detects bare repositories and returns a clear error message pointing to #130.
To prepare for future bare repository support (#130), this PR introduces
RepoContext, which models four distinct repository states:Detection strategy
git worktree list --porcelaincontains abareline.git rev-parse --is-bare-repositoryis unsuitable because it reportsfalsewhen run from a worktree created from a bare repository.git rev-parse --show-toplevelfails at the bare root but succeeds inside a linked worktree. For non-bare repos, the toplevel path is compared against the main worktree path.ref: #130
Test plan
TestDetectRepoContext— verifies all four statesTestIsBareRepository/TestAssertNotBareRepository— guard function testsTestE2E_BareRepository— 6 cases: direct bare and worktree-from-bare × list/add/deletego test ./...passes,go vet ./...clean