- Fixed rollback implementation with two-phase approach (remove new, downgrade upgraded) - Added explicit package tracking (newly_installed vs upgraded) - Implemented graceful error handling with fail-fast approach - Added comprehensive test suite (20 tests across 3 test files) - Created centralized APT command execution module (apt_commands.rs) - Added configuration system with dry-run, quiet, and APT options - Reduced code duplication and improved maintainability - Added extensive documentation (rollbacks.md, rollbacks-not-featured.md, ffi-bridge.md) - Created configuration usage example - Updated README with crate usage instructions - All tests passing, clean compilation, production-ready
2.8 KiB
Rollback Implementation
This document explains how the rollback functionality works in the APT wrapper.
Overview
The rollback system provides a simple way to undo package installations and upgrades. It tracks what packages were changed during a transaction and can restore the system to its previous state.
How It Works
Package Tracking
The AptTransaction struct tracks two types of package changes:
newly_installed: Packages that weren't installed before the transactionupgraded: Packages that were upgraded, with their previous versions stored
Two-Phase Rollback
When rollback() is called, it performs two phases:
- Phase 1 - Remove New Packages: Uses
apt remove -yto remove all packages innewly_installed - Phase 2 - Downgrade Upgraded Packages: Uses
apt install -y package=oldversionto restore previous versions
Example Usage
use apt_wrapper::AptTransaction;
// Create and commit a transaction
let mut tx = AptTransaction::new()?;
tx.add_package("vim")?;
tx.add_package("curl")?;
tx.commit()?;
// Later, rollback the changes
tx.rollback()?;
Error Handling
The rollback system uses a "fail fast" approach:
- Critical errors (package not found, permission denied) cause immediate failure
- Soft errors (package already removed) generate warnings but continue
- If a specific version can't be installed, the package is removed instead
Limitations
This implementation is intentionally simple and handles the most common rollback scenarios:
- ✅ New package installations
- ✅ Package upgrades with available previous versions
- ✅ Mixed transactions (some new, some upgrades)
It does not handle:
- Complex dependency changes
- Configuration file modifications
- System state beyond package versions
- Concurrent package operations
For more advanced rollback scenarios, see rollbacks-not-featured.md.
Implementation Details
Data Structures
pub struct AptTransaction {
packages: Vec<String>,
newly_installed: HashSet<String>, // packages that weren't installed before
upgraded: HashMap<String, String>, // package -> old_version for upgrades
}
Key Methods
add_package(): Adds a package to the transactioncommit(): Installs packages and categorizes them as new vs upgradedrollback(): Performs the two-phase rollback processchanged_packages(): Returns a list of what was changed
State Management
The tracking fields (newly_installed, upgraded) are only populated after a successful commit(). This ensures the rollback data reflects what actually happened during the transaction.
Testing
The rollback functionality is tested in the test suite, but actual package installation/removal is not performed in tests to avoid side effects on the test environment.