Skip to content

refactor: remove redundant per-repository work and make output testable - #56

Merged
bircni merged 3 commits into
mainfrom
refactor/simplify-scan-and-printer
Aug 23, 2026
Merged

refactor: remove redundant per-repository work and make output testable#56
bircni merged 3 commits into
mainfrom
refactor/simplify-scan-and-printer

Conversation

@bircni

@bircni bircni commented Aug 23, 2026

Copy link
Copy Markdown
Owner

What

Three kinds of cleanup, all behaviour-preserving.

Redundant work removed

  • Status::new walked the index and working directory twice for every
    dirty repository — once to decide clean-vs-dirty, then again through
    get_changed_count to reach a number it had already seen. It now counts
    in the pass it already makes.
  • 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. Removed,
    along with the duplicated stat calls per walked directory.
  • The remote was resolved up to three times per repository.
  • The unchanging scan root was canonicalized once per repository.
  • A String was allocated for every walked directory and discarded 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 — dropping the locks, the Arc, the clones, and the
    parking_lot dependency.
  • The scanning closure is split out as scan_entry; the error it previously
    discarded unlogged is now logged like its sibling branch.
  • RepoInfo::new took three consecutive positional bools, with nothing at
    the call site preventing a swap. It now takes &Args.

Output is now testable

run accepted a writer it only used for completions — every printer function
wrote to println!. The writer is now threaded through, so run's signature
is 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.rs goes
from 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

  • Merging get_ahead_behind_and_local_status with get_branch_push_status.
    They overlap, but use different notions of upstream (branch.upstream() vs
    a literal refs/remotes/{remote}/{branch} lookup) and can legitimately
    disagree — unifying them changes behaviour and deserves its own PR.
  • Moving find_repositories out of cli.rs into a scan module.
  • Removing the derived has_unpushed field — it is part of the JSON output.

bircni added 3 commits August 23, 2026 16:02
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
@bircni
bircni merged commit a4052bb into main Aug 23, 2026
9 checks passed
@bircni
bircni deleted the refactor/simplify-scan-and-printer branch August 23, 2026 20:31
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