Free the space left by a failed NUP unpack #1393
No reviewers
Labels
No labels
accessibility
autorelease: pending
autorelease: tagged
bug
dependencies
documentation
duplicate
enhancement
github_actions
good first issue
help wanted
invalid
question
testing wanted
wontfix
No milestone
No assignees
1 participant
Due date
No due date set.
Dependencies
No dependencies set
Reference
MagicBeanDev/Hookshot!1393
Loading…
Reference in a new issue
No description provided.
Delete branch "fix/builder-discard-failed-unpack"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
When a fresh NUP unpack fails, the Builder leaves its partially written
.gamedirectory in the output folder. The next attempt deletes that staging directory before unpacking anyway.Remove the staging directory when extraction or validation fails, before the previous game cache is replaced. Keep the original build error and log the staging path if cleanup also fails.
The game-free regression simulates the Builder error from a disk-full unpack and checks that the partial data is gone and the previous cache and save are intact. It also covers a missing ROMFS and an unsupported build. The three cleanup assertions fail on
mainand pass with this change. The cache, missing-input, and output regression suites passed on Windows and Linux, and the NUP path suite passed on Linux.Related to #1388, which was closed with disk-space guidance. #1391 measures free space on the destination volume. This change frees the Builder staging space after an unsuccessful unpack.
Compatibility check: tested a clean combined tree with #1391 (destination free-space reporting) and #1395 (interrupted ROMFS copies). The cache, missing-input and output suites passed on Windows and Linux. The NUP path suite also passed on Linux.
This landed in the v2.0.12 branch (merged there for testing; it reaches
mainwith that release), so closing. Thanks!Reopened: closing this was a mistake on my side. It was tested in the v2.0.12 branch, and it will be merged into main here, so it shows as merged. Sorry for the noise.
Looks good to me. Cleanup is scoped to the staging dir and the original error is preserved.
What I checked:
game(<out>/.game), whichcheck_cache_pathsalready resolved and rejected if it was a link/reparse point before this branch runs.shutil.rmtreedoesn't follow links inside the tree, so a planted symlink or junction in the extraction is unlinked, not followed. Same target the oldrmtree(game, ignore_errors=True)at the start already used, so no new reach. The previousromfs/.hookshot_romfs/keptcache is untouched because the cleanup only happens before the swap.run()waits for nup.py to exit before we get toexcept, so there's no handle of ours left open. If AV/indexer still holds a file,rmtreeraisesOSError, which you log with the path and then re-raise the original error, so the real failure is never masked and the next run's start-of-runrmtreeretries. Good. (Ctrl-C isn't caught, so that case still relies on the start-of-run cleanup; fine.)tests/test_make_game_cache.py, no new file, so nothing to register inrun_all.py. Faking the failure withmake_game.fail(...)plus a stray.partfile exercises the realSystemExitpath.Overlap with the siblings: #1412 (clean up the
.partof a failed member inside nup.py) and this PR touch different files and don't conflict textually. They're complementary rather than competing: for the Builder, this PR is the one that actually frees the space (it drops the whole.game, which includes the.partand any completed members), so #1412's.partunlink is redundant on that path. #1412 still has value for runningnup.py --extractdirectly and for retry-in-place, and it keeps the previous destination file intact. I'd merge both; if only one, this one fixes the reported disk-space symptom. #1391 and #1395 are different areas (reporting free space, ROMFS copy), and the PR notes a clean combined tree.Nits, none blocking:
check()(the--only exefsprobe) has the same shape:check_modulesfailing leaveswork/probebehind. It's small (exefs only), so optional.except OSErrorhalf isn't covered by a test (onlySystemExitis). Fine to leave.CI was still pending when I looked (Python source checks on Windows and the Windows Vulkan link check already pass).