apt-tx/docs/rollbacks.md
robojerk 2daad2837d Major improvements: rollbacks, testing, docs, and code quality
- 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
2025-09-13 11:21:35 -07:00

89 lines
2.8 KiB
Markdown

# 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 transaction
- **`upgraded`**: Packages that were upgraded, with their previous versions stored
### Two-Phase Rollback
When `rollback()` is called, it performs two phases:
1. **Phase 1 - Remove New Packages**: Uses `apt remove -y` to remove all packages in `newly_installed`
2. **Phase 2 - Downgrade Upgraded Packages**: Uses `apt install -y package=oldversion` to restore previous versions
### Example Usage
```rust
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](rollbacks-not-featured.md).
## Implementation Details
### Data Structures
```rust
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 transaction
- `commit()`: Installs packages and categorizes them as new vs upgraded
- `rollback()`: Performs the two-phase rollback process
- `changed_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.