cli: collapse filter_run visit flags and GitResult bool pair into enums - #36760
Conversation
ProcessHandle tracked DFS cycle-detection state as two dependent bools (visited, visiting) where visiting && !visited was unreachable. Replace with a tri-state VisitState enum and an exhaustive match in has_cycle. GitResult carried (ok, spawn_failed) where ok && spawn_failed was impossible; every caller checked spawn_failed then ok. Replace with a three-variant enum whose Ok and ExitError arms carry only the output stream the caller reads on that path. No behavior change.
|
Warning Review limit reachedYou’ve reached a temporary PR review limit under our Fair Usage Limits Policy. Next review available in: 59 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Pro Run ID: 📒 Files selected for processing (2)
Comment |
|
Status: both test suites pass locally ( CI build 87671: the only hard failure is |
There was a problem hiding this comment.
LGTM — mechanical bool-pair → enum refactor with identical control flow.
What was reviewed:
- Traced
has_cycleDFS: the old(visited, visiting)state pairs map exactly ontoUnvisited/Visiting/Visited, including the outer-loop re-entry on already-visited nodes and the early-return-on-cycle path. - Traced all six
run_gitcall sites: eachSpawnFailed/ExitError/Okarm matches the priorspawn_failed→okcascade, including the silentExitError {..} => {}fallthroughs for unstaged/staged/ls-files. - Confirmed
GitResultand the visit fields have no consumers outside these two files; dropping the unreadstdout/stderrper variant is safe.
Extended reasoning...
Overview
Two self-contained type-tightening refactors in CLI code:
-
src/runtime/cli/filter_run.rs: replaces thevisited: bool/visiting: boolpair onProcessHandlewith a tri-stateVisitStateenum. The only consumer ishas_cycle(), a standard DFS three-color cycle detector. I verified the state mapping is exact: old(false,false)→Unvisited,(true,true)→Visiting,(true,false)→Visited; the fourth combination was already unreachable. The outer loop that re-invokeshas_cycleon already-processed handles behaves identically (temporarily re-marks Visiting, deps are all Visited, restores Visited). -
src/runtime/cli/test/ChangedFilesFilter.rs: replaces theGitResult { ok, spawn_failed, stdout, stderr }struct with a three-variant enum carrying only the stream each caller reads. I walked every call site (rev-parse --show-toplevel,diff HEAD, fallbackdiff+diff --cached,diff <since>,ls-files --others) and each match arm is behaviorally identical to the oldif spawn_failed/if okcascade — same error messages, same early returns, same silent fallthroughs on non-fatal exit errors.run_gititself now constructs the variant directly instead of populating unused fields.
Security risks
None. No new inputs, no new external calls, no changes to path handling or validation — the git argv, cwd, and output parsing are untouched.
Level of scrutiny
Low-to-medium. This is a pure refactor of internal control-flow representation with no user-facing surface change. The main risk in bool-pair → enum conversions is misreading which combination maps to which arm; I traced each one explicitly and found no divergence. Grep confirms neither GitResult nor the visit fields are referenced outside these files.
Other factors
- Both relevant test suites (
filter-workspace.test.ts56 pass,test-changed.test.ts20 pass) were run locally per the PR description, covering cycle detection and the git error/subdirectory paths. - The comment-cop bot flagged a long doc comment on
SpawnFailed; the author tightened it to one line in 9329c01 and the thread is resolved. - Net -9 lines, exhaustive matches replace nested conditionals — this is exactly the "simplest honest shape" the review guide asks for.
|
Closing: this is a pure type-tightening refactor with no observable behavior change (both reviews above confirm the control flow is byte-for-byte identical), so there is no test that can fail before and pass after. The existing suites already cover every changed path:
Both pass against this branch. The branch is left in place in case a maintainer wants to land it directly. |
There was a problem hiding this comment.
LGTM — mechanical bool-pair → enum refactor matching the pattern of #36762/#36764/#36765/#36766.
What was reviewed:
- Traced
has_cycleDFS: old(visited, visiting)pair had exactly three reachable states; the newVisitStatematch preserves the check order (Visiting → cycle, Unvisited → recurse, Visited → skip) including when the outer loop re-enters an already-Visited node. - Traced all five
run_gitcall sites: eachSpawnFailed/ExitError/Okarm produces the identical error message and control flow as the oldspawn_failed-then-okchain; the droppedstderr-on-Ok /stdout-on-ExitError were never read. GitResultandvisit_statehave no other consumers in the tree.
Extended reasoning...
Overview
Two independent type-tightening refactors in CLI code, each replacing a pair of dependent bool fields with a small enum:
src/runtime/cli/filter_run.rs:ProcessHandle.visited/visiting→enum VisitState { Unvisited, Visiting, Visited }, withhas_cyclerewritten as an exhaustivematch.src/runtime/cli/test/ChangedFilesFilter.rs:struct GitResult { ok, spawn_failed, stdout, stderr }→enum GitResult { SpawnFailed, ExitError { stderr }, Ok { stdout } }, with all five call sites converted to exhaustivematch.
This is the same pattern landed in the last four merged PRs on main (#36762, #36764, #36765, #36766).
Behavior preservation
I walked every branch:
has_cycle: The old code set both flags on entry and cleared onlyvisitingon exit, so(visiting=true, visited=false)was unreachable. The old dep check testeddep.visitingfirst (→ cycle) then!dep.visited(→ recurse), which is exactlyVisiting/Unvisited/ fall-throughVisited. The outerfor handle in state.handlesloop can callhas_cycleon an already-Visitednode; both old and new re-mark it in-progress, iterate (all depsVisited→ no-op), re-mark done, return false. Identical.GitResult: For each of the five call sites (rev-parse,diff HEAD, innerdiff/diff --cached,diff <since>,ls-files), the newmatcharms line up one-for-one with the oldif spawn_failed/if !ok/if okchains, including which paths print an error vs. silently continue vs. returnGitFailed. Inrun_gititself, both spawn-error paths stillOutput::err_genericbefore returningSpawnFailed, preserving the "already reported" contract in the doc comment. The only data dropped isstderron success andstdouton non-zero exit — neither was ever read.
Grep confirms GitResult and the visit-state fields are used nowhere else in the tree.
Security risks
None. This touches CLI-internal control flow for bun run --filter dependency ordering and bun test --changed git subprocess result handling. No user-input parsing, no auth, no crypto, no memory-safety changes.
Level of scrutiny
Low. Pure refactor with no observable behavior change, following an established batch pattern already merged four times this week. Both covering test suites (filter-workspace.test.ts 56 tests, test-changed.test.ts 20 tests) pass, and CI is green on the changed code paths (the only CI failure is an unrelated R2 outage in s3.test.ts).
Other factors
The comment-cop bot flag on the SpawnFailed doc comment was addressed in 9329c01 (tightened to one line) and the thread is resolved. No outstanding reviewer comments.
|
Nothing to address from this review, and there are no open threads. All test lanes covering the changed paths are green; the remaining red in the aggregate is a pre-existing worker_threads asan failure on main plus per-file flakes that passed alone or on retry, none in these files. No new test because there is no behavior to distinguish (rationale and suite runs in the description, same approach as #36762), so this is ready for a maintainer call. |
Two small type-tightening refactors that replace dependent bool pairs with enums so impossible states are unrepresentable. No behavior change.
ProcessHandle.visited/visiting→VisitStatehas_cycle()insrc/runtime/cli/filter_run.rsis a textbook DFS cycle check that set both flags on entry and cleared onlyvisitingon exit, sovisiting && !visitedwas unreachable. Replaced with:and an exhaustive
matchinhas_cycle.GitResult.ok/spawn_failed→ tri-variant enumIn
src/runtime/cli/test/ChangedFilesFilter.rs, everyrun_gitconstructor produced exactly one of{spawn_failed, !ok, ok};ok && spawn_failedwas impossible and every caller checkedspawn_failedfirst, thenok. Replaced with:Each variant now carries only the output stream the caller actually reads on that path (stderr on error, stdout on success), and call sites became exhaustive matches. Net -9 lines.
Verification
test/cli/run/filter-workspace.test.ts: 56 pass (incl.ignore dependency order on cycle,detect cycle of length > 2,respect dependency order)test/cli/test/test-changed.test.ts: 20 pass (incl.errors helpfully outside a git repo,--changed=<ref>paths, subdirectory/untracked paths)There is no new test because there is no behavior to distinguish: each
run_gitcall site maps one-to-one from the old{ok, spawn_failed}pair to a variant (spawn failure, nonzero exit, success), andhas_cycleperforms the same DFS with the same detection condition (back-edge to a node on the current stack). The suites above exercise every touched path, matching the approach taken in #36762.