refactor: remove redundant per-repository work and make output testable - #56
Merged
Conversation
The same git and filesystem work was being done two and three times for every repository scanned, and the printer wrote straight to stdout while `run` accepted a writer it never used for anything but completions. Redundant work: - `Status::new` walked the index and working directory once to decide clean-vs-dirty and then again, through `get_changed_count`, purely to reach the count it had already seen. It now counts in the pass it already makes, which halves the dominant cost for every dirty repository. - `is_git_worktree` was strictly narrower than `is_git_directory` (a worktree's `.git` is a file, and `exists()` is true for files), so `a.is_git_directory() || a.is_git_worktree()` was only ever `a`. It is gone, along with the duplicated stat calls it cost per directory. - The remote was resolved up to three times per repository; `get_repo_name` now goes through `get_remote_url`. - The unchanging scan root was canonicalized once per repository rather than once per scan. - A `String` was allocated for every walked directory and thrown away on the two most common paths. Structure: - `find_repositories` collected into `Arc<RwLock<Vec<_>>>` and then deep cloned both vectors out from under a held read guard. It now collects with rayon and partitions, which drops the locks, the `Arc`, the clones and the `parking_lot` dependency. - The scanning closure is split out as `scan_entry`, and the error it previously discarded unlogged is logged like its sibling branch. - `RepoInfo::new` took three consecutive positional bools; it now takes `&Args`. Its doc comment described a parameter that did not exist. Output: - Every printer function now writes to the caller's writer instead of `println!`, so `run`'s existing signature is honest and the tests can assert on what is actually rendered. The printer tests were smoke calls with comments standing in for assertions; they now check real output. Behaviour is unchanged: a binary built from the previous commit and this one produce byte-identical output across the flag matrix on a fixture covering clean, dirty, detached, local-only, unpushed, stashed, worktree, nested, unreadable and subdir repositories.
`cargo clippy -- -D warnings` leaves the test modules outside the lint scope, which is most of the code in this repository. The wider scope is already clean, so this only keeps it that way.
Deleting well-covered dead code lowers a line-ratio gate mechanically, so the refactor left the tarpaulin threshold short despite adding assertions elsewhere. These cover paths that were never exercised: - a bare handle on a `.git` directory, which has no working directory and must report the checkout rather than the bookkeeping directory - a symbolic remote-tracking ref, which carries no target of its own and makes the branch unpublished rather than an error - a symbolic branch ref, which has no commits to walk and an unknown push status - a repository that opens but whose history cannot be read, which must be reported as failed rather than silently dropped from the scan
This was referenced Aug 23, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Three kinds of cleanup, all behaviour-preserving.
Redundant work removed
Status::newwalked the index and working directory twice for everydirty repository — once to decide clean-vs-dirty, then again through
get_changed_countto reach a number it had already seen. It now countsin the pass it already makes.
is_git_worktreewas strictly narrower thanis_git_directory(aworktree's
.gitis a file, andexists()is true for files), soa.is_git_directory() || a.is_git_worktree()was only evera. Removed,along with the duplicated stat calls per walked directory.
Stringwas allocated for every walked directory and discarded on thetwo most common paths.
Structure
find_repositoriescollected intoArc<RwLock<Vec<_>>>and then deepcloned both vectors out from under a held read guard. It now collects with
rayon and partitions — dropping the locks, the
Arc, the clones, and theparking_lotdependency.scan_entry; the error it previouslydiscarded unlogged is now logged like its sibling branch.
RepoInfo::newtook three consecutive positional bools, with nothing atthe call site preventing a swap. It now takes
&Args.Output is now testable
runaccepted a writer it only used for completions — every printer functionwrote to
println!. The writer is now threaded through, sorun's signatureis honest and the tests assert on what is actually rendered. The printer tests
were smoke calls with comments standing in for assertions (
// Assert that the table is printed correctly); they now check real output.printer.rsgoesfrom largely unverified to fully covered.
Compatibility
Output is unchanged. A binary built from the parent commit and one built from
this branch produce byte-identical output across the flag matrix, on a fixture
covering clean, dirty, detached, local-only, unpushed, stashed, worktree,
nested, unreadable and subdir repositories.
Two duplicate tests were removed, and the wall-clock assertions in the smoke
tests were relaxed from 2s to a deliberately generous bound — they exist to
catch a pathological regression, not to fail on a loaded CI runner.
Deliberately not included
get_ahead_behind_and_local_statuswithget_branch_push_status.They overlap, but use different notions of upstream (
branch.upstream()vsa literal
refs/remotes/{remote}/{branch}lookup) and can legitimatelydisagree — unifying them changes behaviour and deserves its own PR.
find_repositoriesout ofcli.rsinto ascanmodule.has_unpushedfield — it is part of the JSON output.