Skip to content

Conversation

@max-sixty
Copy link
Owner

@max-sixty max-sixty commented Jan 10, 2026

Summary

  • Add global cache for merge-base results, keyed by git_common_dir for test isolation
  • Use DashMap for keyed caches (merge_base, worktree_roots, current_branches) with idiomatic entry API
  • Cache is shared across all Repository instances within a process, avoiding redundant git commands during parallel wt list operations

Test plan

  • All 767 integration tests pass
  • Unit tests pass (413 tests)
  • Verified cache isolation works correctly in tests (each test repo gets its own cache)

🤖 Generated with Claude Code

Co-Authored-By: Claude [email protected]

max-sixty and others added 11 commits January 8, 2026 22:12
…nsiveness

On large repos with many branches, `wt select` was slow because git operations
(merge-tree, rev-list, diff) can take 400-1800ms each. This adds a thread-local
command timeout that kills git commands exceeding 500ms.

Architecture:
- Thread-local `COMMAND_TIMEOUT` in shell_exec.rs, checked by `run()`
- `set_command_timeout()` called per-worker in Rayon's thread pool
- Repository and TaskContext stay clean (no timeout fields)
- `wt list` passes None (no timeout), `wt select` passes 500ms

Closes #461

Co-Authored-By: Claude <[email protected]>
Change the global cache from a single RepoCache to a HashMap keyed by
`git_common_dir`. This enables test isolation - each test creates
different repos that need their own cached values.

The cache entries are wrapped in Arc to allow releasing the outer HashMap
lock before accessing cached values, preventing deadlocks when cached
methods call each other (e.g., default_branch -> detect_default_branch
-> primary_remote).

Trade-off documented: every Repository instance must compute
`git rev-parse --git-common-dir` for the lookup. Tests require isolation,
and the HashMap approach is the simplest solution.

Related: #461

Co-Authored-By: Claude <[email protected]>
# Conflicts:
#	src/commands/list/collect_progressive_impl.rs
The cache refactor incorrectly used get_or_init with error-swallowing
fallbacks instead of get_or_try_init with proper error propagation.

This caused several issues:
- Invalid project config was silently ignored instead of reported
- Default branch detection failures returned "main" instead of erroring
- is_bare, worktree_base, project_identifier panicked or silently failed

Fixed by restoring the original get_or_try_init pattern with proper
error propagation using anyhow context.

Co-Authored-By: Claude <[email protected]>
Change get_cache from a method to a free function that takes the key
directly. This more honestly reflects that it operates on global state
rather than instance state.

Co-Authored-By: Claude <[email protected]>
Replace RwLock<HashMap> with DashMap for cleaner, more idiomatic caching:
- merge_base, worktree_roots, current_branches now use DashMap
- entry().or_insert_with() separates caching logic from computation
- Reduces ~15 lines per cached method to ~6 lines

Co-Authored-By: Claude <[email protected]>
@max-sixty max-sixty changed the title feat: add global merge-base cache with timeout for git commands feat: add global merge-base cache for improved wt list performance Jan 10, 2026
@max-sixty max-sixty merged commit efd53f1 into main Jan 10, 2026
27 of 28 checks passed
@max-sixty max-sixty deleted the 461-timeout branch January 10, 2026 02:39
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.

2 participants