Skip to content

repair: say when a file had to be rebuilt to be read - #43

Merged
tannevaled merged 1 commit into
mainfrom
say-when-a-file-was-rebuilt
Oct 11, 2026
Merged

tannevaled merged 1 commit into
mainfrom
say-when-a-file-was-rebuilt

Conversation

@tannevaled

Copy link
Copy Markdown
Contributor

Doc.Repaired() reports whether any file this document's pages came from had to be rebuilt before it could be read, and pdfops repair writes the result out. -check answers the question without writing anything.

This closes BentoPDF's repair-pdf.

⛔ The rebuilding is not new, and is not this verb's doing

go-pdfkit/reader repairs a damaged file on its own and quietly, which is the right behaviour for a reader — a caller asking for page three wants page three, not a lecture. What was missing was a way to say it happened and to keep the result. That is the whole of this verb.

It reports on any source, not all: a merged document's pages come from several files, and one damaged source is the answer to "did this need repairing". A true that depended on every source being broken would be false for every real merge — and the test asserts both orders, because "any" is not "the first".

⛔ A positive control comes first

Without it, Repaired() == false would pass on a fixture that was never broken and the whole test would be measuring nothing. The fixture helper also fails loudly if the file it is handed has no startxref to break — the same guard from the other side.

And what comes out is asserted clean: repair -check on the result says there was nothing to do. A repair whose output still needs repairing is not one.

The scope is reader's, and the README says so rather than implying QPDF's

What is recovered is a cross-reference table that is wrong, missing, or points into the middle of something else — the commonest damage, and the kind where the objects are all still there. It is not a general salvage engine, and a file whose objects are themselves truncated may still be unreadable.

A file that did not need repairing is said out loud and is not an error, so that "repair everything in this directory" can be scripted.

Checks

100 % statement coverage on both packages with zero uncovered statements, go vet and gofmt clean. Both branches of the verb have their own save, so both have their own unwritable-output test — a healthy file and a damaged one take different paths, and the first draft covered only one.

🤖 Generated with Claude Code

Doc.Repaired reports whether any file this document's pages came from had to be
rebuilt before it could be read, and `pdfops repair` writes the result out.
-check answers the question without writing anything.

⛔ The rebuilding is not new and is not this verb's doing: go-pdfkit/reader
repairs a damaged file on its own, quietly, which is the right behaviour for a
reader — a caller asking for page three wants page three, not a lecture. What
was missing was a way to SAY it happened and to keep the result. This closes
BentoPDF's repair-pdf, which is a named entry point over exactly that.

It reports on ANY source, not all. A merged document's pages come from several
files, and one damaged source is the answer to "did this need repairing"; a
true that depended on every source being broken would be false for every real
merge. The test asserts both orders, because "any" is not "the first".

⛔ A POSITIVE control comes first: without it, "Repaired() is false" would pass
on a fixture that was never broken and the whole test would measure nothing.
The fixture helper fails loudly if the file it is handed has no startxref to
break, which is the same guard from the other side.

The scope is reader's and the README says so rather than implying QPDF's: what
is recovered is a cross-reference table that is wrong, missing or points into
the middle of something else — the commonest damage, and the kind where the
objects are all still there.

A file that did not need repairing is said out loud and is NOT an error, so
that "repair everything in this directory" can be scripted.

Both branches of the verb have their own save, so both have their own
unwritable-output test: a healthy file and a damaged one take different paths
and the first draft covered only one.

100% statement coverage on both packages with no uncovered statements, go vet
and gofmt clean.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@tannevaled
tannevaled merged commit a376bb2 into main Oct 11, 2026
1 check passed
@tannevaled
tannevaled deleted the say-when-a-file-was-rebuilt branch October 11, 2026 08:43
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