feat: add --diff <ref>, a baseline taken from git instead of a file - #1
Open
hamodywe wants to merge 1 commit into
Open
feat: add --diff <ref>, a baseline taken from git instead of a file#1hamodywe wants to merge 1 commit into
hamodywe wants to merge 1 commit into
Conversation
A baseline is a file someone has to keep up to date. Most of the time the question is simpler: what does this branch add that main did not already have? `--diff <ref>` checks out the merge base of <ref> and HEAD into a temporary worktree, runs the same command with the same thresholds over it, and uses what it reports as the baseline for the working copy. The worktree is removed before the report prints. The merge base rather than the tip of <ref>, because a fix that landed on main after the branch was cut is not something the branch removed, and a finding main gained since is not something the branch added. A test builds exactly that history and asserts the branch is not blamed for it. The baseline machinery is reused rather than duplicated: the comparison run produces the JSON documents `--json` would print and `Baseline` reads them, so "already known" means the same thing whichever way the baseline arrived. `--diff` and `--baseline` combine through `Baseline::merge`, which keeps the worse reading of a finding both record. The note at the end of the report now names what hid the findings and the merge base. Also rejects `--baseline` and `--diff` on `cost` and `why`, which have no findings to hide: the flag was accepted and changed nothing, and a flag that silently does nothing is worse than one that is not accepted. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Signed-off-by: hamodywe <iosapk.org@gmail.com>
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.
Closes the first item under Next in ROADMAP.md.
What
Report only what the working copy adds relative to a git ref, with no baseline file to keep up to date. The tree at the merge base of
<ref>andHEADis checked out into a temporary worktree, analysed with the same command and the same thresholds, and whatever it reports becomes the baseline for the run over the working copy. The worktree is removed before the report prints.Why the merge base, not the tip
A fix that landed on
mainafter the branch was cut is not something the branch removed, and a findingmaingained since is not something the branch added. Comparing against the point where the histories diverged judges a branch on its own changes and nothing else.diff_compares_against_the_merge_base_not_the_tipbuilds exactly that history — crash onmain, branch cut,mainfixes it, branch still carries it — and asserts the branch is not blamed for it.Design
--jsonwould print, andBaseline::from_partsreads them. So a finding is "already there" under exactly the rules--baselineuses: same cycle key (member set, order-independent), same "worse than known is still reported" rule, same amplification slack. There is one place that decides what "known" means.--diffand--baselinecombine.Baseline::mergekeeps the worse reading where both record the same finding, because "not worse than what was known" has to mean the most that was known. The note names both:hidden by the baseline and --diff main (merge base …).PATHexits 2 before any graph is built. The ref is verified withrev-parse --verify <ref>^{commit}so--diff typosays so rather than failing insidemerge-base.--rootinside a subdirectory works.rev-parse --show-prefixmaps the root into the checkout; if the directory did not exist at the merge base, everything is new and the run says nothing was hidden.--entryand--tsconfigare carried across only where they exist. An entry file that did not exist at the merge base is simply not an entry there — not an error, and not silently re-pointed at another file.Drop.git worktree remove --force, falling back toremove_dir_all+worktree pruneso a failed removal never leaves a dangling registration. Every--difftest assertsgit worktree listis back to one entry.--baseline(and--diff) are now rejected oncostandwhy. Neither has findings a baseline can hide, so the flag was accepted and did nothing — the rule the other flags already follow is that a flag that silently does nothing is worse than one that is not accepted.Tests
Five new process-level tests in
tests/cli.rsbuild a real repository in a temp dir (identity andcommit.gpgsign=falseset per call, so nothing depends on the machine):diff_reports_only_what_the_working_copy_addshidden by --diff HEAD (merge base …),no new import cycles, worktree gonediff_compares_against_the_merge_base_not_the_tipdiff_treats_a_finding_that_got_worse_as_new--fail-on any; the crashing version of it is reporteddiff_names_an_unknown_ref_and_a_missing_repositorydiff_and_a_baseline_file_both_hide_findingsPlus unit tests for
Baseline::merge(both orders keep the worse reading),from_parts(&[]), the CLI parse/validate paths, andComparison::checkoutoutside a repository.scripts/ci.shgained a behaviour check that--diff HEADon a committed fixture is quiet and leaves no worktree behind.sh scripts/ci.sh— fmt, clippy (pedantic,-D warnings), 34 + 30 + 25 tests, MSRV 1.95 build, node fixture verification, behaviour checks — passes on this machine.Not in this PR
--baselineeither; adding them is a separate, additive change to the documented contract.node_modulesis never there either, and resolution already degrades to counting externals at the boundary, so this matches how a fresh checkout is analysed.