A chronological summary of the working session on the keep-auxfiles /
aux-redirect branches of apt.
- User:
methods/mirror.ccshould transparently ignore failures from fetching the mirror file if an old copy still exists — the mirror file is kept around inauxfiles/, which makes the mirror method more reliable. - Agent: explored the code paths end to end:
methods/mirror.cc(351 Aux Requestflow,MirrorListFileReceived,mirrorfilestate),apt-pkg/acquire-worker.cc(Aux Request handling,ReplyAux, which hides the file behind/nonexistent/...when it exists but the item did not finish withStatDone),apt-pkg/acquire-item.cc(pkgAcqAuxFile::FailedrenamingDestFileto.FAILED),apt-pkg/clean.cc(auxfiles never cleaned), andtest/integration/test-method-mirror. Checked git history and upstream — no existing implementation.
- User: "we should not be renaming to .FAILED in this case in the first place" — the old copy must survive the failure.
- User: "A partial file may be renamed to .FAILED; we should be using the old file in that case."
- Agent: after analyzing the http method (file only opened after
successful headers, 416-partial-hit resume logic in basehttp.cc), designed
the distinction: record the old copy's mtime in the
pkgAcqAuxFilector; inFailed(), rename to.FAILEDonly if the file was actually modified (a real partial), otherwise keep it and mark the itemStatDoneso the failure is ignored.mirror.ccfalls back to the auxfiles copy.
- User: "It should not report the failure as a failure, just as 'Ign:' (ignored failure)".
- User: "Write some test cases first before thinking further", "use testsuccessequal".
- Agent: ran the baseline mirror test — initially failed on SSL errors.
- User: "Sorry I had a wrong openssl version installed with a broken patch, try again" — baseline then passed (783 checks).
- Agent: added the 404 fallback test; first run showed
testrun's cleanup deletesauxfiles/, so a primingapt updatewas needed to populate the old copy. The fallback then worked (Hit:lines) but the mirrorlist failure still printedErr:1and exited 100.
- User: finish the test to match the actual output for now, commit, and fix output in another commit ("the test should not ignore the output, you should ignore the output not matching what we want").
- Agent: switched to
testfailureequalwith the real output (810 checks pass) and committed "Keep old mirror file copies around and use them as fallback".
- User: "hint_ also it retries 3 times of course due to apts retry logic".
- Agent: implemented the
StatDonedowngrade inpkgAcqAuxFile::Failedwhen the old copy is kept: progress printsIgn:,AcquireUpdateno longer fails. Test updated totestsuccessequal(811 checks pass). - User: "I amended the previous commit with your changes. Now focus on the 3 retries with a transient failure. We do not actually want 3 retries if we have a previous copy, just use it directly", and "add the test case first and make sure it fails before fixing the code :)".
- Agent: wrote the transient test (redirect to a dead port) — the run hung.
- User: "seems to hang", "I killed it", then provided a coredump:
std::out_of_rangefrombasic_string::substrinChangeSiteIsMirrorChange(acquire-worker.cc:240) — a real pre-existing crash when an aux file request is redirected (aux item Description is<uri> Mirrorlist, soOldSite == desc.URIandsubstr(len+1)throws). - Agent: switched the transient test to a second webserver on 127.0.0.2
that gets killed; discovered
bad_addrinmethods/connect.ccis keyed by IP only (not IP:port), so killing a server on localhost poisoned the live server too — hence 127.0.0.2. The test then failed correctly: 3 extra retryIgn:lines. ImplementedRetries = 0in thepkgAcqAuxFilector when an old copy exists (841 checks pass); committed "Do not retry fetching the mirror file if an old copy exists". Regression-checked related integration tests and the unit suite (initial "failures" were just runninglibapt_testfrom the wrong CWD; fixtures requiretest/libapt).
- User: rebase pause, then "why is this not crashing anymore?" (answer: the crash path was simply no longer exercised — the redirect scenario had been replaced), then "can we rewrite the test case to avoid killing and manually starting aptwebserver?"
- Agent: rewrote the test to point sources at a dead address and seed
the old copy manually; failed on
Get:vsHit:because changing the source URI changes all index file names. - User: "Maybe we just change the port not the hostname? And mv the file that worked fine before to update the port to a fake one?"
- Agent: explained the
bad_addrIP-keying still forces a different IP, but adopted themvidea:mvthe previously fetched auxfile and index files to the fake-name variants — keepsHit:without a priming update (826 checks pass). - User: "Then use the same port if you use a different IP".
- Agent: tried it — the main webserver binds
0.0.0.0, so 127.0.0.2 on the same port is alive and the fetch succeeds via the resume partial-hit path. Reverted to the truly dead port127.0.0.2:1(826 checks pass). - User: "simplif the sed to use just localhost -> 127.0.0.2".
- Agent: attempted, but the underscore boundary in the filename sed is required with differing ports; corrected and re-verified (826 checks pass).
- User: "We could also perhaps have the webserver respond 429 or something transient?" — discussed; a redirect-based approach needs the crash + redirect-tracking fixes first.
- User: "I committed it for you".
- User: "Fix the crash", then "Well you can fix both, you will need to eventually anyhow" (crash + the aux redirect tracking), and later "make proper commits, add tests if possible".
- Agent: implemented (a) a length guard in
ChangeSiteIsMirrorChange, (b)pkgAcqAuxFile::OriginalURI— restored beforeReplyAuxinDone/Failedso the mirror method can correlate replies after a redirect, and (c) a redirect test (mirrorlist behind a 301 to another "site", 127.0.0.2 vs localhost). Fixed a build error (Descparameter shadowing the member — usedthis->Desc.URI). - User: "also do check that the test indeed failed before your fixes", "Use pipefail setting or your && is pointless."
- Agent: the redirect test passed, but a cascade of failures appeared
later in the file. Root-caused it:
Configuration::Clear()leaves the item in the tree with an empty value, so a clearedredirect::replace::/mirror.txtwas still applied — substituting to the empty string (redirecting/mirror.txtto the server root → an 11.1 kB autoindex page, and/mirror.txt.gz→ 404). Verified with manual curl experiments. Fixed aptwebserver to skip empty redirect values, and made the transient blockmvthe index files back for the following tests. All 844 checks pass. TDD-verified the redirect test aborts withstd::out_of_rangeon unfixed code (exit 134). - Committed as three commits: "Fix crash when an aux file request is redirected", "Reply to aux requests with the original URI if redirected", "test: mirrorlist fetch via redirect, fix clearing redirect::replace config".
- User: "check if you really need the whole destfile variable, isn't Oldcopy always the same as Itm->DestFile".
- Agent: confirmed — with the
StatDonereporting,ReplyAuxhands the real path (the old copy) to the method, so the computed fallback path is redundant. SimplifiedMirrorListFileReceivedback to usingItm->DestFiledirectly (844 checks pass); committed "Simplify mirror method old-copy fallback".
- User: "I did some rebasing. I'd like to have the redirect fixes in a separate branch without the offline-server changes".
- Agent: created
aux-redirectfrom main, cherry-picked the crash fix (clean), theOriginalURIfix (conflict-resolved against main's originalFailed/Done), and reduced the test commit to just the redirect block (801 checks pass). Resetkeep-auxfilesto the two offline-server commits (826 checks pass). Both branches sit on main independently.
- User: "Based on what you learned about the codebase and building it,
write an AGENTS.md" (plus the
git-clang-format.shand fast ninja target facts). - Agent: wrote
AGENTS.mdwith layout, build (fast iteration targets), test invocation and helpers, aptwebserver usage and gotchas (in6addr_anybinding,bad_addrIP-keying,Configuration::Clearempty items), unit-test CWD requirement, and domain notes (auxfiles, mirror method, retry/ignore semantics, index file naming in tests).
keep-auxfiles: Keep old mirror file copies around and use them as fallback, Do not retry fetching the mirror file if an old copy exists.aux-redirect: Fix crash when an aux file request is redirected, Reply to aux requests with the original URI if redirected, test: mirrorlist fetch via redirect, fix clearing redirect::replace config (later merged into main as 9351e213f).- All integration (826/801 checks respectively) and unit tests pass.