Skip to content

Comments

feat: detect bare repositories and model 4-state RepoContext#136

Merged
k1LoW merged 3 commits intok1LoW:mainfrom
usadamasa:assert-bare
Feb 14, 2026
Merged

feat: detect bare repositories and model 4-state RepoContext#136
k1LoW merged 3 commits intok1LoW:mainfrom
usadamasa:assert-bare

Conversation

@usadamasa
Copy link
Contributor

@usadamasa usadamasa commented Feb 13, 2026

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:

Bare Worktree Meaning
false false Main working tree of a normal repository
false true Linked worktree of a normal repository
true false Bare repository root
true true Linked worktree created from a bare repository

Detection strategy

  • Bare: Checks whether the first entry in git worktree list --porcelain contains a bare line. git rev-parse --is-bare-repository is unsuitable because it reports false when run from a worktree created from a bare repository.
  • Worktree: For bare repos, git rev-parse --show-toplevel fails 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 states
  • TestIsBareRepository / TestAssertNotBareRepository — guard function tests
  • TestE2E_BareRepository — 6 cases: direct bare and worktree-from-bare × list/add/delete
  • go test ./... passes, go vet ./... clean

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.
@usadamasa usadamasa marked this pull request as ready for review February 13, 2026 15:08
Copy link
Owner

@k1LoW k1LoW left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 DetectRepoContextgit 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).

@k1LoW k1LoW added enhancement New feature or request tagpr:minor labels Feb 14, 2026
Co-authored-by: Ken’ichiro Oyama <[email protected]>
@usadamasa
Copy link
Contributor Author

usadamasa commented Feb 14, 2026

Thanks for the suggestion! I agree that caching would be very efficient if possible.

However, due to the nature of git-wt, the current working directory may change during execution. To be safe, I’d like to store the directory detected at initialization in RepoContext, and validate it again when retrieving it from context.Context.

I understand that the directory change is currently done within the --init script via cd, but I’d prefer to keep this check as a safety measure.
ee5e87d


btw, Longer term, it might be nice to define an interface that encapsulates repo operations based on the current RepoContext state (e.g., bare repo vs non-bare, initialized vs not).

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]>
@usadamasa usadamasa requested a review from k1LoW February 14, 2026 11:01
@k1LoW
Copy link
Owner

k1LoW commented Feb 14, 2026

However, due to the nature of git-wt, the current working directory may change during execution. To be safe, I’d like to store the directory detected at initialization in RepoContext, and validate it again when retrieving it from context.Context.

There are no os.Chdir calls in the production code (cmd/ or internal/git/).
All Chdir usage is in test files only.
The cd in --init shell integration runs in the shell after the git-wt process exits, so it doesn't affect the running process either.

I understand that the directory change is currently done within the --init script via cd, but I’d prefer to keep this check as a safety measure.

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.
Please note that we may simplify this later in favor of keeping things simple 🙏

@usadamasa
Copy link
Contributor Author

Please note that we may simplify this later in favor of keeping things simple 🙏

sure!

Copy link
Owner

@k1LoW k1LoW left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

GREAT WORK!!! Thank you!!

@k1LoW k1LoW merged commit 23154aa into k1LoW:main Feb 14, 2026
3 checks passed
@github-actions github-actions bot mentioned this pull request Feb 12, 2026
@usadamasa usadamasa deleted the assert-bare branch February 21, 2026 04:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request tagpr:minor

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants