Repository navigation
Canonicalize benchmark fixtures and variants - #3761
Conversation
worktrunk-bot
left a comment
There was a problem hiding this comment.
Folding the canonical worktree rotation into the Imported base makes prune_large_repository's fixture check fail: wt-0003 is created at the base tip with no commits of its own, so the prune overlay's squash commits turn it into an integrated candidate. add_history_spread_branches was given its own commit for exactly this reason — the worktree side needs the same treatment (or verify_candidates needs to stop asserting an exact total). Details and a reproduction are in the inline comment on benches/prune.rs.
The same mechanism makes the documented manual-repro commands build a different fixture than the benchmark they're meant to attribute phases for — setup generated --prune-candidates 4 --prune-backdrop 8 lists 34 candidates where prune_e2e asserts 8, because the default 50 br-NNNN branches include 25 that are ancestors of main. Inline suggestions add the explicit 0 0 populations that generated_prune_fixture() uses.
Not approving: per the repo's review guidance the diff edits two files on the deletion surface — benches/remove.rs (wt remove --yes --force) and tests/helpers/wt-perf/src/lib.rs (remove_dir_all via remove_dir_if_exists). Nothing in the diff changes what either one targets — both stay on tempdir fixtures and target/wt-perf/bench-repos/ — but the verdict is a human call regardless.
Everything else read clean: the Generated/Imported split, the prune-overlay extraction, the #[cfg(test)] SimpleRepoConfig demotion, and the new history_spread_branches_do_not_become_prune_candidates guard.
Verification notes
The multi-gigabyte Imported fixture can't be built in this sandbox, so the mechanism was reproduced on the identical add_heterogeneous_worktrees code path with a generated base at the same population:
$ wt-perf setup generated 7 0 --prune-candidates 12 --prune-backdrop 24 --path <p>
$ wt -C <p> step prune --dry-run --min-age 0s --format json | jq length
25 # IMPORTED_PRUNE_CANDIDATE_PAIRS * 2 == 24
The extra entry is wt-0003. wt-0001/2/5/6 also sit on the base tip but carry working-tree dirt, so prune's dirty filter drops them (verified separately: adding an untracked file to wt-0003 takes the count back to 24). wt-0000 and wt-0004 are the j % 4 == 0 state and carry their own commits.
The documented manual repro on the generated base:
$ wt-perf setup generated --prune-candidates 4 --prune-backdrop 8 --path <p>
$ wt -C <p> step prune --dry-run --min-age 0s --format json | jq length
34 # verify_candidates(dry_fixture.path(), MERGED * 2) asserts 8
$ wt-perf setup generated 0 0 --prune-candidates 4 --prune-backdrop 8 --path <p2>
$ wt -C <p2> step prune --dry-run --min-age 0s --format json | jq length
8
br-NNNN states i % 4 == 0 (behind) and i % 4 == 3 (identical to tip) are both ancestors of main, which is 25 of the 50 default branches.
worktrunk-bot
left a comment
There was a problem hiding this comment.
Both findings from the previous review are fixed. I verified the arithmetic on the identical add_heterogeneous_worktrees code path (the imported corpus is still too large for this sandbox): with wt-0003 carrying its own commit the dry-run lists exactly 24, matching verify_candidates(repo, IMPORTED_PRUNE_CANDIDATE_PAIRS * 2), and the documented manual repro with the explicit 0 0 populations lists 8, matching prune_e2e's MERGED * 2. cargo test -p wt-perf --lib imported_populations_do_not_become_prune_candidates passes.
One new thing, inline: the doc comment on add_imported_linked_worktrees claims more than the code delivers.
Not approving — the deletion-surface hold from the previous review still stands, and nothing in this commit changes it.
Verification
$ wt-perf setup generated 7 0 --prune-candidates 12 --prune-backdrop 24 --path <p>
$ wt -C <p> step prune --dry-run --min-age 0s --format json | jq length
25 # merged-br-0..11, merged-wt-0..11, and wt-0003
# Apply the commit add_imported_linked_worktrees now makes:
$ cd <p>.wt-0003 && echo … > imported_wt_3.txt && git add imported_wt_3.txt && git commit -m …
$ wt -C <p> step prune --dry-run --min-age 0s --format json | jq length
24
Documented manual repro, with the 0 0 this commit adds:
$ wt-perf setup generated 0 0 --prune-candidates 4 --prune-backdrop 8 --path <p2>
$ wt -C <p2> step prune --dry-run --min-age 0s --format json | jq length
8
Integration state of the base worktree population at that fixture — git merge-base --is-ancestor <b> main and git status --porcelain in each worktree, after the prune overlay:
| worktree | rotation state | ancestor of main | dirty entries |
|---|---|---|---|
| wt-0000 | 0 (own commits) | no | 0 |
| wt-0001 | 1 (unstaged edit) | yes | 1 |
| wt-0002 | 2 (staged + unstaged + untracked) | yes | 3 |
| wt-0003 | 3 (clean) | no, after the new commit | 0 |
| wt-0004 | 0 (own commits) | no | 0 |
| wt-0005 | 1 | yes | 1 |
| wt-0006 | 2 | yes | 3 |
worktrunk 0.73.0 Created-by: HarmonybrewBot Commit-by: HarmonybrewBot Merged-by: HarmonybrewBot Description: Created by `brew bump` --- Created with `brew bump-formula-pr`.<details> <summary>release notes</summary> <pre>## Release Notes ### Fixed - **`wt remove` refuses a registered path that now holds a different repository**: A clone made at a stale registration's path was removed whole, uncommitted work included — and wt routed the user there, since the dirty gate read the occupant's files as this worktree's and offered `--force` as the cure. Removal now compares the directory's git dir against this repository's; `--force` waives uncommitted changes, not the check for whose directory it is. ([#3785](max-sixty/worktrunk#3785)) - **The Nix flake names three systems, dropping Intel macOS**: nixpkgs drops `x86_64-darwin` in 26.11, so the flake would stop evaluating there once `flake.lock` advances past it. (Breaking: `nix build`, `nix run`, and the home-manager module no longer resolve on Intel macOS. Release binaries are unaffected and still ship for it.) ([#3776](max-sixty/worktrunk#3776)) - **`NO_COLOR` and a redirected stream reach every surface**: Escapes still landed in progressive `wt list`, `-v` diagnostics, clap's error tips, and parts of stderr — the deprecation warning, the `wt config update` preview, the `[y/N]` prompt — so a redirected log carried escapes on one line and not the next. Color now resolves in one place. ([#3777](max-sixty/worktrunk#3777), [#3771](max-sixty/worktrunk#3771)) - **A trailing separator no longer hides the branch**: Git's ref format forbids a name ending in `/`, and shell completion produces exactly that spelling whenever a `docs` directory sits beside the branch, so `wt switch docs/` never had a candidate. Selectors are normalized before resolution now — `wt remove`, merge targets, `--base`, and the `pre-switch` hook's `target` alike. ([#3785](max-sixty/worktrunk#3785)) - **A path holding no worktree is reported as a path**: `wt remove ../repo.ghost` answered `No branch named …` and pointed at a listing it could never appear in; `wt switch` and `wt merge` offered `--create <path>`, which git rejects; and `wt config state marker set --branch <path>` silently stored state keyed by a path. ([#3773](max-sixty/worktrunk#3773), thanks @judewang for reporting) - **A failed GitLab project lookup carries `glab`'s own verdict**: `wt switch mr:<n>` on a fork MR answered a 401, a 404, and a network failure with the same `Failed to fetch project 456`, swallowing the output every other `remote_ref` failure path forwards. A non-project response body now says so too. ([#3799](max-sixty/worktrunk#3799)) - **A deleted-and-recreated worktree directory is reported, not leaked as git's exit 128**: An `rm -rf` followed by a `mkdir` passes the `Path::exists()` probe, so `wt switch`, `wt merge`, `wt step push`, and `wt remove` walked into a raw git failure. All four now name the missing worktree and the `git worktree prune` that clears it. ([#3785](max-sixty/worktrunk#3785)) ### Internal - **Library API rework** (Breaking library API): `cargo-semver-checks` fails four lints — `GitError` gained `WorktreeNotFoundAtPath` and `WorktreePathNotOurs`, shifting seven later discriminants, its `DetachedHead` variant gained a `worktree` field, `ResolvedWorktree` gained `NoWorktreeAtPath`, and `Repository::resolve_worktree_name` was removed. ([#3785](max-sixty/worktrunk#3785), [#3773](max-sixty/worktrunk#3773)) - **Tests and benches spawn a pinned `wt` binary**: a concurrent `cargo` removes and recreates `target/debug/wt` as it uplifts, so spawns hit a one-off `NotFound`; every spawn now routes through a hardlinked pin. ([#3784](max-sixty/worktrunk#3784), [#3792](max-sixty/worktrunk#3792)) - **The nix devShell and `task setup-web` install what the test suite drives**: both were missing `nushell`, `pwsh`, and `jq`, which `--features shell-integration-tests` shells out to. ([#3768](max-sixty/worktrunk#3768), [#3776](max-sixty/worktrunk#3776)) - **Benchmark fixtures reduced to two provenance-based bases**: `Generated` builds a repository locally and `Imported` copies the pinned `rust-lang/rust` corpus, with worktree, branch, and remote-ref populations as parameters. ([#3761](max-sixty/worktrunk#3761)) ## Install worktrunk 0.73.0 ### Install prebuilt binaries via shell script ```sh curl --proto '=https' --tlsv1.2 -LsSf https://github.com/max-sixty/worktrunk/releases/download/v0.73.0/worktrunk-installer.sh | sh && wt config shell install ``` ### Install prebuilt binaries via powershell script ```sh powershell -ExecutionPolicy Bypass -c "irm https://github.com/max-sixty/worktrunk/releases/download/v0.73.0/worktrunk-installer.ps1 | iex"; git-wt config shell install ``` ### Install prebuilt binaries via Homebrew ```sh brew install worktrunk && wt config shell install ``` ## Download worktrunk 0.73.0 | File | Platform | Checksum | |--------|----------|----------| | [worktrunk-aarch64-apple-darwin.tar.xz](https://github.com/max-sixty/worktrunk/releases/download/v0.73.0/worktrunk-aarch64-apple-darwin.tar.xz) | Apple Silicon macOS | [checksum](https://github.com/max-sixty/worktrunk/releases/download/v0.73.0/worktrunk-aarch64-apple-darwin.tar.xz.sha256) | | [worktrunk-x86_64-apple-darwin.tar.xz](https://github.com/max-sixty/worktrunk/releases/download/v0.73.0/worktrunk-x86_64-apple-darwin.tar.xz) | Intel macOS | [checksum](https://github.com/max-sixty/worktrunk/releases/download/v0.73.0/worktrunk-x86_64-apple-darwin.tar.xz.sha256) | | [worktrunk-x86_64-pc-windows-msvc.zip](https://github.com/max-sixty/worktrunk/releases/download/v0.73.0/worktrunk-x86_64-pc-windows-msvc.zip) | x64 Windows | [checksum](https://github.com/max-sixty/worktrunk/releases/download/v0.73.0/worktrunk-x86_64-pc-windows-msvc.zip.sha256) | | [worktrunk-aarch64-unknown-linux-musl.tar.xz](https://github.com/max-sixty/worktrunk/releases/download/v0.73.0/worktrunk-aarch64-unknown-linux-musl.tar.xz) | ARM64 MUSL Linux | [checksum](https://github.com/max-sixty/worktrunk/releases/download/v0.73.0/worktrunk-aarch64-unknown-linux-musl.tar.xz.sha256) | | [worktrunk-x86_64-unknown-linux-musl.tar.xz](https://github.com/max-sixty/worktrunk/releases/download/v0.73.0/worktrunk-x86_64-unknown-linux-musl.tar.xz) | x64 MUSL Linux | [checksum](https://github.com/max-sixty/worktrunk/releases/download/v0.73.0/worktrunk-x86_64-unknown-linux-musl.tar.xz.sha256) | ### Install via Cargo ```sh cargo install worktrunk && wt config shell install ``` ### Install via Winget (Windows) ```sh winget install max-sixty.worktrunk && git-wt config shell install ``` ### Install via AUR (Arch Linux) ```sh paru worktrunk-bin && wt config shell install ``` </pre> <p>View the full release notes at <a href="https://github.com/max-sixty/worktrunk/releases/tag/v0.73.0">https://github.com/max-sixty/worktrunk/releases/tag/v0.73.0</a>.</p> </details> <hr> See merge request: Harmonybrew/homebrew-core!16463
Benchmark fixtures still encoded the benchmark that first needed each repository state, which left overlapping recipes and variants after the earlier harness consolidation. This change reduces the fixture catalog to two provenance-based bases:
Generatedbuilds an ordinary Git repository locally, whileImportedcopies the pinnedrust-lang/rustcorpus. Worktree, branch, and remote-ref populations remain parameters onGenerated; prune candidates and backdrop are overlays that work with either base.The generated base deliberately combines heterogeneous worktree states, history-spread branches, and optional remote refs so ordinary list, completion, picker, first-output, alias, remove, and prune benchmarks can share it. Imported history-spread branches and clean base-tip worktrees carry their own commits, preserving the base populations without making them incidental prune candidates when overlays advance the default branch.
The benchmark matrix now keeps single-factor contrasts: list scaling uses the 1- and 8-worktree endpoints; alias dispatch has a startup floor, two population endpoints, and one warm/cold variable-resolution pair; completion keeps one full-surface case; remove and prune vary cache or hook state only where the command exercises it. Historical recipes, redundant cache rows, and intermediate scaling points are removed. Manual setup paths live under
target/, and the benchmark guide documents the resulting fixture and cache model.Tests:
cargo run -- hook pre-merge --yesafter merging currentmain(4,571 tests); targeted Criterion test-mode runs;cargo test -p wt-perf; benchmark check, clippy, formatting, and diff checks.