test: gate the cache-name conflict, and say so where it happens (#706) - #727
Merged
Merged
Conversation
The normaliser reports a `[conflict]` when both casings of a cache name exist as distinct files and refuses to choose -- picking between two fetches of the same reference is not a script's call. But the recipes discard its exit code, on purpose: normalising must not turn a failing validation green (#697). So the condition was one line in the middle of a long validation log and nothing else. Two changes, and the first matters more than the issue suggested. **The committed tree is now gated on every machine.** `test_reference_cache_names_are_case_exact.py` reads `os.listdir(REFERENCES_CACHE)` -- the filesystem. macOS cannot hold `DOI_x.md` and `doi_x.md` at once, so on a developer machine the pair is invisible and the divergence appears only on Linux. That is #690's lesson stated as a test: a green local run is not a green CI run. The new check reads GIT'S INDEX instead, which records the name it was told regardless of what the filesystem will store, so the clash is caught everywhere. Mutation-checked by staging a clashing name directly into the index with `git update-index --cacheinfo` -- a state macOS cannot represent on disk, which is exactly why the index is the right thing to read. **A conflict is announced rather than buried.** The script prints a trailing banner naming the count and what a human has to decide. The exit code is deliberately left as it was: the recipes' `exit $code` is the validator's, and that is correct. The banner is tested by stubbing `rename`, because the real conflict needs two files whose names differ only by case -- the filesystem, not the code, is what makes it unreachable here. Both directions: a conflict prints it, no conflict does not, and removing the banner reds the first. Co-Authored-By: Claude Opus 5 <noreply@anthropic.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 #706.
What the issue asked, and what I found instead
#706 asked whether the normaliser's discarded exit code should fail a recipe. Working it, the exit code turns out to be the least of it — and correctly left alone.
The committed tree was only gated on Linux.
test_reference_cache_names_are_case_exact.pyreadsos.listdir(REFERENCES_CACHE)— the filesystem. macOS cannot holdDOI_x.mdanddoi_x.mdat once, so on a developer machine the pair is invisible, and the divergence appears only in CI.That is #690's lesson stated as a test: a green local run is not a green CI run. The new check reads git's index, which records the name it was told regardless of what the filesystem will store, so the clash is caught everywhere.
Mutation-checked by staging a clashing name straight into the index:
A state macOS cannot represent on disk — which is precisely why the index is the right thing to read.
The exit code, deliberately unchanged
The recipes'
exit $codeis the validator's, and that is right: normalising must never turn a failing validation green (#697). So the exit code cannot be the signal. Instead the script prints a trailing banner naming the count and what a human has to decide, so a conflict is not one line lost in a long validation log.Tested by stubbing
rename, because the real conflict needs two files whose names differ only by case — the filesystem, not the code, is what makes it unreachable here. Both directions asserted: a conflict prints it, no conflict does not, and removing the banner reds the first.Known unrelated failure:
test_no_snippet_stops_mid_word, from an untracked local cache on a record this PR does not touch.Not done
Making
just qccarry the conflict, one of the issue's suggested alternatives. It is unnecessary now: the committed tree is gated by a test that runs invalidate-strict, which is a blocking lane, andqc-referencesis explicitly not a CI gate.