Skip to content

--purge-old deleted a file whose re-fetch never got a response - #765

Merged
xroche merged 8 commits into
masterfrom
fix/failed-refetch-keeps-copy
Jul 27, 2026
Merged

--purge-old deleted a file whose re-fetch never got a response#765
xroche merged 8 commits into
masterfrom
fix/failed-refetch-keeps-copy

Conversation

@xroche

@xroche xroche commented Jul 27, 2026

Copy link
Copy Markdown
Owner

A re-fetch that fails never touches the mirrored file, but back_finalize() returned without noting the surviving copy, so the URL fell out of new.lst and the end-of-update purge deleted it as if the page had vanished from the site. Same family as #562 and #584, which covered the short-body path; a fetch that dies before a usable response takes a different exit and was still losing files.

The fix notes the copy for any failure except the codes meaning the engine passed the resource over on purpose (too big, MIME-excluded, link test). That is wider than the reported case needs, deliberately: a malformed status line and an oversized declared length both surface as STATUSCODE_INVALID and lose the file the same way. An HTTP error on an update already masks itself as a 304 and keeps its copy, which is what this brings failures in line with.

Test 96 now runs its update pass with purging on, and fails without the fix.

Closes #746

xroche and others added 5 commits July 27, 2026 08:59
… debris

A transfer that dies before a complete response has no body, yet the save path
still consulted r.adr, which at that point holds whatever the aborted header
read left behind: raw status-line bytes, or an empty buffer that truncated the
file to zero on macOS. Require a successful transfer, as the empty-body half of
the condition already did.

Closes #748

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Signed-off-by: Xavier Roche <roche@httrack.com>
Test 93 filtered reset.bin out of its bucket lists because a connection killed
before the status line surfaced differently per platform. It no longer does, so
assert the resource like any other: unchanged, with the bytes pass 1 mirrored.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Signed-off-by: Xavier Roche <roche@httrack.com>
The new test passed with no second pass at all, so a regression that stopped
re-fetching would have looked green. Assert the failure the fixture provokes,
give stay.bin a fresh pass-2 body so a fix that stopped overwriting anything
fails, and compare reset.bin by checksum rather than by length.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Signed-off-by: Xavier Roche <roche@httrack.com>
A transfer that dies on the wire leaves the previously mirrored copy in place,
but back_finalize() returned without noting it, so the URL fell out of new.lst
and the end-of-update purge treated the file like a page that had vanished from
the site. Note the surviving copy, the way the incomplete-transfer branch above
already does, for the connection-level failures htsparse.c retries on. A
deliberate skip (too big, MIME-excluded, cancelled) keeps its current fate.

Closes #746

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Signed-off-by: Xavier Roche <roche@httrack.com>
A malformed status line, an oversized declared length or a mid-flight abort all
land on STATUSCODE_INVALID, outside the retryable set, and the purge still ate
the file. Invert the test: any failure keeps the copy except the codes that
mean the engine passed the resource over on purpose.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Signed-off-by: Xavier Roche <roche@httrack.com>
@xroche
xroche force-pushed the fix/failed-refetch-keeps-copy branch from 2f8a07a to 14cc7a1 Compare July 27, 2026 07:23
xroche and others added 2 commits July 27, 2026 09:25
The message a cut connection produces depends on whether any bytes arrived, so
matching it would fail on a runner that sees none.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Signed-off-by: Xavier Roche <roche@httrack.com>
Signed-off-by: Xavier Roche <roche@httrack.com>

# Conflicts:
#	tests/96_local-refetch-keep.test
@xroche
xroche changed the base branch from fix/refetch-debris to master July 27, 2026 07:47
Signed-off-by: Xavier Roche <roche@httrack.com>

# Conflicts:
#	src/htsback.c
#	tests/96_local-refetch-keep.test
@xroche
xroche merged commit 1f9728d into master Jul 27, 2026
22 checks passed
xroche added a commit that referenced this pull request Jul 27, 2026
Under `set -e` a failing command in an EXIT trap becomes the script's exit status, so a hiccup while tearing down fixtures fails a test whose assertions all passed. That is what turned `57_local-proxy-connect.test` red on the Windows x64 leg of #765: five OK lines, no FAIL, exit 1. Every EXIT trap in the suite now runs teardown with errexit off, and the signal traps keep their own `trap` line, since sharing `set +e` with HUP/INT/QUIT/PIPE/TERM would leave errexit off for the rest of a signalled run and let a torn-down test still report success.

A `|| true` on the `rm` would have been smaller, but it throws away the only diagnostic, and the evidence does not say which teardown command failed: a blocked `rm -rf` on the Windows runner exits 1 and prints "Device or resource busy", while the log shows exit 1 and nothing at all. The sharing violation in the issue is the plausible mechanism rather than a confirmed one, so whatever it really is now prints its own error.

`99_teardown-status.test` pins the semantics both ways and scans the suite so a new test cannot reintroduce the shape, the leaky combined trap included. The `return 0` that three `cleanup()` bodies ended with never protected anything, since errexit fires at the failing command before it is reached.

Closes #773

Signed-off-by: Xavier Roche <roche@httrack.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@xroche
xroche deleted the fix/failed-refetch-keeps-copy branch July 27, 2026 18:25
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.

--purge-old deletes a mirrored file when the connection drops before the response

1 participant