Repository navigation
(fix) Roll back partial installs on failure (closes #59) - #101
Merged
Merged
Conversation
If any package installation were to fail via 'draft', 'substitute' and/or 'update' commands, B.A.L.L.E.R rolls back to the last version you installed. An additional command is provided for you to manually roll back packages when installations from source fail unexpectedly. New installs and/or installs before this change are unaffected for the first time.
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.
Description
draft,substituteandupdateinstall a plan as separate persisted steps (extract → link → record) with no transaction around them, and none of them undid those steps on a failure (#59). A failure partway through the plan, such as a 404 download, a missing binary or a vetoing pre-hook, left the earlier packages linked and on the roster.This PR adds
src/commands/rollback.rs, aSessionin which each command records every step as it goes (beginbefore a package's first change, thendownloaded/linked/recorded). On an error the command unwinds the session newest-first and then returns the original error:draft --forcereinstall, a dependency thatsubstitutere-fetches (resolve_deps_with_rootreturns installed dependencies andsubstitutedoesn't skip them), and the packageupdateis upgrading. Their roster row andpackage_dependenciesrows are written back, and the link points at the old binary again. Deleting them, as the issue's suggested fix would, uninstalls packages that worked before the run.updateprunes the old extract dir only after the new release is linked and recorded. A rollback therefore never needs files that were already deleted, and no backup/rename step is needed.substitutealso rolls back when the old package can't be unlinked or removed. If its roster row can't be deleted, it puts the old package's link back; the previous partial rollback left that link removed.The install loops move into
install_plan(draft),install_replacement(substitute) andinstall_update(update). The caller does the rollback.Behaviour changes
Rolled back undid this run's changes to <names>. It is a warning, so-qand--jsonhide it;-vshows each step.updateprunes the old extract dir after the new version is committed, not before.--jsondocuments are unchanged.draft'sinstalledstill lists what this run recorded.Unchanged by design
Known limitations
cargo installor a hook did. A warning says when a system or cargo package stays installed with only its roster entry removed.installed_atis reset to the time of the rollback.--forcereinstall whose own download fails partway has already re-extracted over the existing tree. That is existingdownload_and_extractbehaviour: rollback doesn't make it worse, but can't bring those files back.Found while testing, not fixed here: under
-q/--json, a failed download leaves a 0-byte file at the archive's cache path, andcached_downloadthen treats it as cached. Every retry fails withtar.gz extraction: failed to iterate over archiveuntilballer sweep. The bug is inDownloader::download_archiveand probably deserves its own issue.Docs:
docs/commands.md,docs/error-handling.md(which already described adraft/substituterollback that didn't exist) anddocs/architecture.md. CHANGELOG entry is under Unreleased → Fixed.Type of Change
Platform
Testing
New tests
src/commands/rollback.rs:user_installed, dependency rows, old tree kept, new tree purged)tests/rollback.rs: 8 end-to-end tests that drive the real binary against an in-process mock registry. Each case gets its own config dir andHOME/LOCALAPPDATA.pre_installhook does the same. A faileddraft --forcerestores a reinstalled dependency's old version, link anduser_installedflag.pre_updatehook does the same. A successful update still prunes the old extract dir.draft --jsonstill reportsinstalledin install order.<name>.exealike.BALLER_TEST_BINoverrides the binary, as injson_output.rs.Results
cargo build --all-targets,cargo clippy --all-targets -- -D warningsandcargo fmt --checkare clean.cargo testpasses all suites: 807, 837, 17 and 8 tests.Restricted),x86_64-pc-windows-gnucross-buildjson_output17/17. Windows-target clippy is clean, with 0 build warnings.powershellis a stub that exits 0. The full suites show only the known Wine-only failures (core::hooks×3,test_utils_symlink_integration,json_output's hook test).Manual run with a fresh
HOME: adraftwhose root 404s after its dependency was installed prints the rollback warning and exits 1. No link, roster row, extract dir or archive is left for the dependency.Checklist
Related Issues
Closes #59
Screenshots/Videos
N/A: this is a CLI change. The test results are summarised above.