Add enhanced rollback functionality and comprehensive documentation
- Implement two-phase rollback system inspired by apt-tx project - Add package state tracking (newly_installed, upgraded, previously_installed) - Enhance both core and advanced transaction APIs with rollback methods - Add comprehensive rollback documentation in docs/rollback.md - Create rollback_demo.rs example demonstrating functionality - Update README with detailed crate usage instructions - Add rollback features to feature flags documentation - Fix import issues in advanced crate modules - Add get_installed_packages method to AptCommands - Include both crates.io and git installation options in README
This commit is contained in:
parent
06cafa0366
commit
88d57cd3a1
15 changed files with 945 additions and 47 deletions
310
README.md
310
README.md
|
|
@ -1,6 +1,15 @@
|
|||
# APT-DNF Bridge
|
||||
|
||||
A DNF-like bridge around APT for apt-ostree integration. This workspace provides a transaction-based API that makes APT work like DNF.
|
||||
A DNF-like bridge around APT for apt-ostree integration. This workspace provides a transaction-based API that makes APT work like DNF, complete with sophisticated rollback functionality.
|
||||
|
||||
## ✨ **Key Features**
|
||||
|
||||
- **🔄 Advanced Rollback**: Two-phase rollback system that tracks and undoes package changes
|
||||
- **📦 Transaction Model**: DNF-like imperative transactions with resolve and commit phases
|
||||
- **🔧 Pluggable Backends**: Shell, mock, and libapt backends for different use cases
|
||||
- **⚡ Feature Flags**: Choose between minimal core or full advanced functionality
|
||||
- **🛡️ Error Handling**: Comprehensive error handling with clear messages
|
||||
- **📚 Complete Documentation**: Detailed guides and working examples
|
||||
|
||||
## 🎯 **Two-Crate Approach**
|
||||
|
||||
|
|
@ -57,7 +66,8 @@ apt-dnf-bridge-workspace/
|
|||
├── basic_usage.rs
|
||||
├── package_query.rs
|
||||
├── atomicity_notes.rs
|
||||
└── backend_selection.rs
|
||||
├── backend_selection.rs
|
||||
└── rollback_demo.rs
|
||||
```
|
||||
|
||||
## 🔧 **Usage Examples**
|
||||
|
|
@ -106,6 +116,32 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||
}
|
||||
```
|
||||
|
||||
### Rollback Functionality
|
||||
```rust
|
||||
use apt_dnf_bridge::{Transaction, Package};
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
let mut tx = Transaction::new();
|
||||
|
||||
// Add packages
|
||||
tx.add_install(Package::new("vim", "", "")).await?;
|
||||
tx.add_install(Package::new("curl", "", "")).await?;
|
||||
|
||||
// Commit transaction
|
||||
tx.resolve().await?;
|
||||
tx.commit().await?;
|
||||
|
||||
// Later, rollback if needed
|
||||
if tx.can_rollback() {
|
||||
println!("Rolling back {} newly installed packages", tx.newly_installed().len());
|
||||
tx.rollback().await?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
```
|
||||
|
||||
## 🏗️ **Building and Testing**
|
||||
|
||||
### Build All Crates
|
||||
|
|
@ -131,6 +167,7 @@ cargo run --example package_query
|
|||
|
||||
# Advanced examples (requires advanced feature)
|
||||
cargo run --example backend_selection --features advanced
|
||||
cargo run --example rollback_demo --features advanced
|
||||
```
|
||||
|
||||
## 🎯 **Feature Flags**
|
||||
|
|
@ -140,6 +177,7 @@ cargo run --example backend_selection --features advanced
|
|||
- Basic transaction model
|
||||
- Package querying
|
||||
- Repository management
|
||||
- **🔄 Rollback functionality** (two-phase rollback)
|
||||
- Error handling
|
||||
|
||||
### Advanced Features (`advanced` feature)
|
||||
|
|
@ -148,6 +186,217 @@ cargo run --example backend_selection --features advanced
|
|||
- Enhanced error handling
|
||||
- Backend statistics
|
||||
- Mock backend for testing
|
||||
- **🔄 Advanced rollback** (backend-integrated)
|
||||
|
||||
## 📦 **Using as a Crate**
|
||||
|
||||
### Installation
|
||||
|
||||
Add to your `Cargo.toml`:
|
||||
|
||||
```toml
|
||||
[dependencies]
|
||||
apt-dnf-bridge = "0.1"
|
||||
```
|
||||
|
||||
For advanced features:
|
||||
```toml
|
||||
[dependencies]
|
||||
apt-dnf-bridge = { version = "0.1", features = ["advanced"] }
|
||||
```
|
||||
|
||||
Or using git directly:
|
||||
```toml
|
||||
[dependencies]
|
||||
apt-dnf-bridge = { git = "https://git.raines.xyz/particle-os/apt-dnf-bridge-workspace.git", features = ["advanced"] }
|
||||
```
|
||||
|
||||
### Basic Usage
|
||||
|
||||
#### 1. Core API (Minimal)
|
||||
|
||||
```rust
|
||||
use apt_dnf_bridge::{Transaction, Package, Repository};
|
||||
use anyhow::Result;
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<()> {
|
||||
// Create a transaction
|
||||
let mut tx = Transaction::new();
|
||||
|
||||
// Add packages to install
|
||||
let vim = Package::new("vim", "2:8.1.2269-1ubuntu5.14", "amd64");
|
||||
tx.add_install(vim).await?;
|
||||
|
||||
// Resolve dependencies
|
||||
tx.resolve().await?;
|
||||
|
||||
// Commit the transaction
|
||||
tx.commit().await?;
|
||||
|
||||
// Check what was installed
|
||||
println!("Newly installed: {:?}", tx.newly_installed());
|
||||
|
||||
// Rollback if needed
|
||||
if tx.can_rollback() {
|
||||
tx.rollback().await?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
```
|
||||
|
||||
#### 2. Advanced API (With Backends)
|
||||
|
||||
```rust
|
||||
use apt_dnf_bridge::{TransactionV2, PackageDatabaseV2, BackendConfig};
|
||||
use anyhow::Result;
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<()> {
|
||||
// Create transaction with specific backend
|
||||
let config = BackendConfig::default();
|
||||
let mut tx = TransactionV2::with_shell_backend(config).await?;
|
||||
|
||||
// Add packages
|
||||
let git = Package::new("git", "1:2.25.1-1ubuntu3.11", "amd64");
|
||||
tx.add_install(git).await?;
|
||||
|
||||
// Resolve and commit
|
||||
tx.resolve().await?;
|
||||
tx.commit().await?;
|
||||
|
||||
// Advanced rollback with backend
|
||||
if tx.can_rollback() {
|
||||
println!("Changed packages: {:?}", tx.changed_packages());
|
||||
tx.rollback().await?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
```
|
||||
|
||||
#### 3. Package Querying
|
||||
|
||||
```rust
|
||||
use apt_dnf_bridge::{PackageDatabase, Package};
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
let mut db = PackageDatabase::new();
|
||||
|
||||
// Search for packages
|
||||
let packages = db.find_packages("editor").await?;
|
||||
for package in packages {
|
||||
println!("Found: {} - {}", package.name, package.version);
|
||||
}
|
||||
|
||||
// Get specific package info
|
||||
if let Some(package) = db.get_package_info("vim").await? {
|
||||
println!("Package: {} v{}", package.name, package.version);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
```
|
||||
|
||||
#### 4. Repository Management
|
||||
|
||||
```rust
|
||||
use apt_dnf_bridge::{Repository, PackageDatabase};
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
// Add a repository
|
||||
let mut repo = Repository::new("myrepo", "https://example.com/debian");
|
||||
repo.add_component("main");
|
||||
repo.add_component("contrib");
|
||||
repo.save_to_sources_list_d("myrepo.list")?;
|
||||
|
||||
// Update package cache
|
||||
let mut db = PackageDatabase::new();
|
||||
db.update_cache().await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
```
|
||||
|
||||
### Error Handling
|
||||
|
||||
The crate uses `anyhow::Result` for error handling:
|
||||
|
||||
```rust
|
||||
use anyhow::Result;
|
||||
|
||||
async fn example() -> Result<()> {
|
||||
let mut tx = Transaction::new();
|
||||
|
||||
// All operations return Result<T, anyhow::Error>
|
||||
tx.add_install(Package::new("vim", "", "")).await?;
|
||||
tx.resolve().await?;
|
||||
tx.commit().await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
```
|
||||
|
||||
### Rollback System
|
||||
|
||||
The rollback system tracks package changes and provides two-phase rollback:
|
||||
|
||||
```rust
|
||||
use apt_dnf_bridge::{Transaction, Package};
|
||||
|
||||
async fn rollback_example() -> Result<(), Box<dyn std::error::Error>> {
|
||||
let mut tx = Transaction::new();
|
||||
|
||||
// Add packages
|
||||
tx.add_install(Package::new("vim", "", "")).await?;
|
||||
tx.add_install(Package::new("curl", "", "")).await?;
|
||||
|
||||
// Commit
|
||||
tx.resolve().await?;
|
||||
tx.commit().await?;
|
||||
|
||||
// Check rollback information
|
||||
println!("Previously installed: {} packages", tx.previously_installed().len());
|
||||
println!("Newly installed: {} packages", tx.newly_installed().len());
|
||||
println!("Upgraded: {} packages", tx.upgraded().len());
|
||||
|
||||
// Rollback if needed
|
||||
if tx.can_rollback() {
|
||||
println!("Rolling back changes...");
|
||||
tx.rollback().await?;
|
||||
println!("Rollback completed");
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
```
|
||||
|
||||
### Feature Flags
|
||||
|
||||
#### Core Only (Default)
|
||||
```toml
|
||||
[dependencies]
|
||||
apt-dnf-bridge = "0.1"
|
||||
```
|
||||
|
||||
#### With Advanced Features
|
||||
```toml
|
||||
[dependencies]
|
||||
apt-dnf-bridge = { version = "0.1", features = ["advanced"] }
|
||||
```
|
||||
|
||||
### Available Examples
|
||||
|
||||
```bash
|
||||
# Run examples
|
||||
cargo run --example basic_usage
|
||||
cargo run --example package_query
|
||||
cargo run --example rollback_demo --features advanced
|
||||
cargo run --example backend_selection --features advanced
|
||||
```
|
||||
|
||||
## 🔄 **Migration Guide**
|
||||
|
||||
|
|
@ -161,10 +410,46 @@ cargo run --example backend_selection --features advanced
|
|||
- Advanced API available via feature flag
|
||||
- Gradual adoption path supported
|
||||
|
||||
## 🔄 **Rollback System**
|
||||
|
||||
The APT-DNF Bridge includes a sophisticated two-phase rollback system inspired by the [apt-tx project](https://git.raines.xyz/particle-os/apt-tx):
|
||||
|
||||
### How It Works
|
||||
|
||||
1. **Package Tracking**: Tracks `previously_installed`, `newly_installed`, and `upgraded` packages
|
||||
2. **Two-Phase Rollback**:
|
||||
- **Phase 1**: Remove newly installed packages using `apt remove -y`
|
||||
- **Phase 2**: Downgrade upgraded packages using `apt install -y package=oldversion`
|
||||
|
||||
### Rollback API
|
||||
|
||||
```rust
|
||||
// Check if rollback is possible
|
||||
if tx.can_rollback() {
|
||||
// Get rollback information
|
||||
println!("Newly installed: {:?}", tx.newly_installed());
|
||||
println!("Upgraded: {:?}", tx.upgraded());
|
||||
|
||||
// Perform rollback
|
||||
tx.rollback().await?;
|
||||
}
|
||||
```
|
||||
|
||||
### Limitations
|
||||
|
||||
- ✅ New package installations
|
||||
- ✅ Package upgrades with available previous versions
|
||||
- ❌ Complex dependency changes
|
||||
- ❌ Configuration file modifications
|
||||
- ❌ Concurrent package operations
|
||||
|
||||
For critical systems, consider using OSTree's native checkpoint/rollback functionality.
|
||||
|
||||
## 📚 **Documentation**
|
||||
|
||||
- **Core API**: Focus on simplicity and reliability
|
||||
- **Advanced API**: Focus on power and flexibility
|
||||
- **Rollback Guide**: Detailed rollback implementation (`docs/rollback.md`)
|
||||
- **Examples**: Demonstrate both core and advanced usage
|
||||
- **Migration**: Guide for moving between feature levels
|
||||
|
||||
|
|
@ -176,5 +461,26 @@ cargo run --example backend_selection --features advanced
|
|||
4. **Re-exports** - Clean API surface
|
||||
5. **Gradual Adoption** - Start simple, add complexity when needed
|
||||
6. **Clear Documentation** - One README with feature explanations
|
||||
7. **🔄 Advanced Rollback** - Production-ready rollback functionality
|
||||
8. **🔧 Pluggable Backends** - Flexible backend architecture
|
||||
|
||||
This approach gives us all the benefits of the two-crate strategy with much better UX and maintenance.
|
||||
|
||||
## 📊 **Project Status**
|
||||
|
||||
- ✅ **Core Functionality**: Complete and tested
|
||||
- ✅ **Rollback System**: Implemented with two-phase approach
|
||||
- ✅ **Advanced Features**: Pluggable backends and caching
|
||||
- ✅ **Documentation**: Comprehensive guides and examples
|
||||
- ✅ **Examples**: Working demonstrations of all features
|
||||
- 🔄 **Testing**: Unit tests and integration tests
|
||||
- 📦 **Publishing**: Ready for crates.io publication
|
||||
|
||||
## 🤝 **Contributing**
|
||||
|
||||
This project is designed for apt-ostree integration. Contributions should maintain simplicity and focus on the core use case while following the established patterns.
|
||||
|
||||
## 📄 **License**
|
||||
|
||||
MIT License - see LICENSE file for details.
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue