Skip to content

feat(pool): Add .worktreeinclude support#48

Open
nikolauska wants to merge 2 commits into
kunchenguid:mainfrom
nikolauska:feature/worktreeinclude
Open

feat(pool): Add .worktreeinclude support#48
nikolauska wants to merge 2 commits into
kunchenguid:mainfrom
nikolauska:feature/worktreeinclude

Conversation

@nikolauska

Copy link
Copy Markdown

Intent

Resolve #39 by allowing repositories to seed required gitignored files into pooled worktrees through a committed .worktreeinclude manifest.

Changes

  • Copy matching gitignored files on worktree creation and reuse
  • Support .gitignore patterns and negated subtrees
  • Prevent tracked files from being overwritten
  • Preserve copied file permissions
  • Document the feature in README

Risk assessment

Low to moderate.

  • Opt-in: repositories without .worktreeinclude retain existing behavior
  • Tracked files cannot be overwritten
  • Copy failures abort acquisition with an error
  • Main risk is unexpected pattern matching causing additional ignored files to be copied
  • Cross-platform path handling uses Go’s filepath package

Validation

  • make test/lint/build pass
  • Tested locally on the personal project

@mbrookson mbrookson left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Nice implementation — using git ls-files + check-ignore for pattern matching is the right call over rolling our own glob expansion. A few observations from independently building the same feature (closed #50 in favour of this):

Seeding runs inside the state lock

Both call sites invoke SeedWorktree inside the WithStateLock closure, which means the flock is held for the duration of the file copies. For repos with large ignored files this could block concurrent treehouse commands unnecessarily. The post-create hooks already run after the lock is released — seeding feels like it belongs there too, since it's not mutating pool state. Something like:

// after WithStateLock returns, before hooks.Run
if err := git.SeedWorktree(repoRoot, acquired); err != nil {
    fmt.Fprintf(os.Stderr, "warning: .worktreeinclude: %v\n", err)
}

(Whether to warn or hard-fail is a separate question — see below.)

excludedIncludeSubtree only handles !dir/ negations, not !file

The custom parser skips lines matching !<dir>/ but a bare negation like !.env.local won't be excluded. Given the function comment says "Git does not descend into an excluded directory", I think this is intentional — but it's worth a doc comment clarifying that file-level negations aren't supported so users don't write !secrets/prod.json and wonder why it still gets copied.

Seed errors abort acquire for the missing-file case

If .worktreeinclude lists .env but a contributor doesn't have that file locally (common on a fresh clone), git ls-files returns nothing for it and the seed silently skips it — so this is actually fine in practice. The error path that would bite is an OS-level failure mid-copy. Current behaviour (abort acquire) is defensible, though a warning-and-continue would be more resilient. Worth a deliberate decision either way.

Seed acquired worktrees after releasing the pool lock to avoid blocking concurrent
commands during file copies. Treat seeding failures as warnings and document and test
file-negation behavior
@nikolauska

Copy link
Copy Markdown
Author

Thanks for the review. I moved seeding outside the state lock and changed OS-level copy failures to warn without failing the acquire. I also clarified that Git handles file-level negations directly and added coverage for !.env.local.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Feature request: .worktreeinclude manifest for seeding gitignored files into pooled worktrees

2 participants