fix: per-file fix reporting, BOM-safe contents insertion, stale-offset guard - #419
Merged
Conversation
A write failure partway through a multi-file run used to return before the report was rendered, leaving the files fixed before it on disk and nothing but a bare error line behind. apply() now records a per-file failure and continues with the remaining files; the CLI turns each failure into a note on the report and exits with the failed code, so the reader sees exactly which files changed and which did not. Fixes #227
with_contents() read the file's first line as the literal text with the mark, so a UTF-8 BOM kept the title line from matching and the Contents block was spliced in above the mark and the title it belongs under. The first line is now scanned past the mark — the same tolerance the parser applies to frontmatter — and the mark's bytes stay on disk untouched. Fixes #230
A fix is a byte range into the text it was measured against, but apply_to_file() re-read the file and trusted the offsets blindly — a file rewritten between the lint pass and the fix pass, even to the same length, had the fix spliced into bytes nobody measured. The report now records a fingerprint (length plus a cheap hash) of every fixable file's text when it is read, and apply() re-checks the file against it before writing: a mismatch skips that file with a note saying why, the same channel the failed-write report speaks through. Fixes #234 Fixes #247
Pins both halves of the behaviour: a read-only file is still fixable, because the replacement asks the directory for room rather than the file for permission and keeps the mode it had; and when the directory refuses too, the run reports the failed write and still fixes the other files. Red at c226adf (before the per-file failure reporting), green at HEAD.
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.
Summary
A cluster of correctness/atomicity fixes around
--fix:fix::applynow records a per-file failure (Applied::failed) and continues with the remaining files; the CLI turns each failure into a note on the report and exits with the failed code (3), so the reader sees exactly which files changed and which did not.with_contents()read the file's first line with a UTF-8 BOM attached, so the title never matched and the Contents block was spliced in above the mark and the title it belongs under. The first line is now scanned past the mark — the same toleranceskill.rsapplies to frontmatter — and the mark's bytes stay on disk untouched.apply_to_file()re-read the file and trusted the offsets blindly — a file rewritten between the lint pass and the fix pass (even to the same length) had the fix spliced into bytes nobody measured. The report now records a fingerprint (length + cheap hash) of each fixable file's text when it is read, andapply()re-checks before writing: a mismatch skips that file with a note instead of corrupting it.--fixbehaviour on a read-onlySKILL.md— it is still fixable by replacement (rename asks the directory for room, and keeps the mode), and when the directory refuses too, the failure is reported and other files still get fixed.Fixes #227
Fixes #230
Fixes #234
Fixes #247
Fixes #277
Test plan
test: reproduce #227— e2e: multi-file--fixwith one unwritable directory failed before the fix (no report on stdout); passes aftertest: reproduce #230— BOM'd long reference put## Contentsabove the title; passes aftertest: reproduce #234/#247— same-length rewrite between compute and apply corrupted the file (fix applied to wrong bytes); skipped with a note aftertest: cover #277— verified red at c226adf (before the --fix: a write failure partway through a multi-file run leaves earlier files already mutated on disk, with no report printed and no indication of what was changed #227 fix), green at HEAD-D warnings,cargo test --workspace,cargo deny check, no-todos, rules-json, MSRVcargo check --lockedNote:
a_later_path_with_its_own_config_is_named_when_the_first_path_governsis a pre-existing flake reproducible onorigin/main(XDG_CONFIG_HOME env mutation racing parallel tests); it is unrelated to this diff.