Skip to content

fix(worktree): speed up worktree list and stop leaking branch=… lines#42

Merged
mswdev merged 1 commit intodevelopfrom
fix/worktree-list-perf
May 5, 2026
Merged

fix(worktree): speed up worktree list and stop leaking branch=… lines#42
mswdev merged 1 commit intodevelopfrom
fix/worktree-list-perf

Conversation

@mswdev
Copy link
Copy Markdown
Owner

@mswdev mswdev commented May 4, 2026

Summary

Two bugs in ckipper worktree list fixed together because they surface in the same command's output.

1. Slow scan — ≈25× faster. find recursed unbounded under $CKIPPER_WORKTREES_DIR with only */node_modules/* excluded, so heavy build/cache trees (dist, .next, target, __pycache__, etc.) were walked in full. On a 6 GB / 380k-file worktrees tree the scan took ~700 ms. Pruning the known-heavy directory names brings it to ~30 ms. Bounding by depth was not viable because branches contain slashes (e.g. feature/OGD-320-…).

2. Spurious branch='…' lines. local branch (no =value) inside the per-iteration loop body behaves like typeset -p branch once the variable already carries a value from a prior iteration, leaking literal lines under each bullet. Hoisted the loop locals above the while to match the existing precedent for the same hazard in lib/account/sync/preview.zsh.

Before / after on the author's tree

# before
$ time ckipper worktree list
...real 0m0.726s

# after
$ time ckipper worktree list
...real 0m0.033s

Test plan

  • bats lib/worktree/worktree_test.bats — 15/15 pass, including 3 new regressions
  • make test-unit — 504/504 shell tests pass
  • make lint-shell lint-zsh lint-fmt lint-merge-guards — all clean
  • Manual: zsh -f -c '… ckipper worktree list' shows no branch= lines and is visibly instant

Two bugs surface together in `ckipper worktree list`:

1. Slow scan. `find` recursed unbounded under $CKIPPER_WORKTREES_DIR with
   only `*/node_modules/*` excluded, so the heavy build/cache trees
   (`dist`, `.next`, `target`, `__pycache__`, etc.) were walked in full.
   On a 6 GB / 380k-file worktrees tree the scan took ~700 ms. Pruning
   the known-heavy directory names brings it to ~30 ms (≈25× faster);
   bounding by depth was not viable because branches contain slashes
   (e.g. `feature/OGD-320-…`).

2. Spurious `branch='…'` lines under each bullet. `local branch` (no
   `=value`) inside the per-iteration loop body behaves like
   `typeset -p branch` once the variable already carries a value from a
   prior iteration. Hoist `branch` (and the other loop locals) above the
   `while` and assign without `local` inside, matching the existing
   precedent in lib/account/sync/preview.zsh.

Adds three regression tests:
- pruning skips `.git` files inside node_modules / dist / __pycache__
- branches with slashes still resolve (no depth bound)
- output never contains literal `branch=` lines
@mswdev
Copy link
Copy Markdown
Owner Author

mswdev commented May 4, 2026

Folding into #41 per request — both fixes shipping in one PR.

@mswdev mswdev closed this May 4, 2026
@mswdev mswdev deleted the fix/worktree-list-perf branch May 4, 2026 21:37
@mswdev mswdev restored the fix/worktree-list-perf branch May 5, 2026 00:03
@mswdev mswdev reopened this May 5, 2026
@mswdev mswdev marked this pull request as ready for review May 5, 2026 00:15
@mswdev mswdev merged commit bf60408 into develop May 5, 2026
2 checks passed
@mswdev mswdev deleted the fix/worktree-list-perf branch May 5, 2026 00:16
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.

1 participant