# 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, 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** This workspace implements the refined two-crate approach with feature flags: - **`apt-dnf-bridge-core`** - Minimal shell-out implementation - **`apt-dnf-bridge`** - Main crate that re-exports core + optional advanced features - **`apt-dnf-bridge-advanced`** - Pluggable backends, caching, and enhanced features ## 🚀 **Quick Start** ### Core (Minimal) ```toml [dependencies] apt-dnf-bridge = "0.1" ``` ### Advanced Features ```toml [dependencies] apt-dnf-bridge = { version = "0.1", features = ["advanced"] } ``` ## 📁 **Workspace Structure** ``` apt-dnf-bridge-workspace/ ├── Cargo.toml # Workspace root ├── apt-dnf-bridge-core/ # Minimal implementation │ ├── Cargo.toml │ └── src/ │ ├── lib.rs │ ├── command.rs │ ├── error.rs │ ├── package.rs │ ├── repository.rs │ └── transaction.rs ├── apt-dnf-bridge/ # Main public crate │ ├── Cargo.toml │ └── src/ │ └── lib.rs ├── apt-dnf-bridge-advanced/ # Advanced features │ ├── Cargo.toml │ └── src/ │ ├── lib.rs │ ├── backend.rs │ ├── package_v2.rs │ ├── transaction_v2.rs │ └── backend/ │ ├── shell_backend.rs │ ├── mock_backend.rs │ └── libapt_backend.rs └── examples/ # Shared examples ├── basic_usage.rs ├── package_query.rs ├── atomicity_notes.rs ├── backend_selection.rs └── rollback_demo.rs ``` ## 🔧 **Usage Examples** ### Basic Usage (Core Only) ```rust use apt_dnf_bridge::{Transaction, Package, Repository}; #[tokio::main] async fn main() -> Result<(), Box> { // 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 (APT handles automatically) tx.resolve().await?; // Commit the transaction tx.commit().await?; Ok(()) } ``` ### Advanced Usage (With Backends) ```rust use apt_dnf_bridge::{TransactionV2, PackageDatabaseV2, BackendFactory}; #[tokio::main] async fn main() -> Result<(), Box> { // Create transaction with auto-detected backend let mut tx = TransactionV2::new().await?; // Add packages let vim = Package::new("vim", "2:8.1.2269-1ubuntu5.14", "amd64"); tx.add_install(vim).await?; // Resolve and commit tx.resolve().await?; tx.commit().await?; Ok(()) } ``` ### Rollback Functionality ```rust use apt_dnf_bridge::{Transaction, Package}; #[tokio::main] async fn main() -> Result<(), Box> { 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 ```bash cargo build ``` ### Test Core Features ```bash cargo test -p apt-dnf-bridge-core ``` ### Test Advanced Features ```bash cargo test -p apt-dnf-bridge-advanced ``` ### Run Examples ```bash # Core examples cargo run --example basic_usage 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** ### Core Features (Default) - Shell-out APT commands - Basic transaction model - Package querying - Repository management - **🔄 Rollback functionality** (two-phase rollback) - Error handling ### Advanced Features (`advanced` feature) - Pluggable backends (shell, mock, libapt) - Caching system - 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> { 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> { // 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 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> { 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** ### From Single Crate to Workspace 1. **Core users**: No changes needed - same API 2. **Advanced users**: Add `features = ["advanced"]` to Cargo.toml 3. **New users**: Start with core, add advanced when needed ### API Compatibility - Core API remains unchanged - 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 ## 🚀 **Benefits of This Approach** 1. **Single Crate** - No confusion about which to use 2. **Feature Flags** - Users choose complexity level 3. **Workspace** - Easy version coordination 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.