pub struct BackupManager { /* private fields */ }Expand description
Manages backup and restoration of AGPM binaries during upgrades.
BackupManager provides comprehensive backup functionality to protect against
failed upgrades and enable rollback capabilities. It creates backups of the
current binary before upgrades and can restore them if needed.
§Safety Features
- Automatic Backup Creation: Creates backups before any binary modification
- Permission Preservation: Maintains file permissions and metadata on Unix systems
- Atomic Operations: Uses file copy operations for reliability
- Retry Logic: Handles Windows file locking issues with automatic retries
- Rollback Support: Enables quick restoration from backups
§Backup Strategy
The backup manager creates a copy of the original binary with a .backup suffix
in the same directory. This approach:
- Keeps backups close to the original for easy access
- Preserves the same file system and permissions context
- Allows for quick restoration without complex path management
- Works consistently across different installation methods
§Cross-Platform Considerations
§Unix Systems (Linux, macOS)
- Preserves executable permissions and ownership
- Uses standard file copy operations
- Handles symbolic links appropriately
§Windows
- Implements retry logic for file locking issues
- Handles executable files that might be in use
- Works with Windows permission models
§Examples
§Basic Backup and Restore
use agpm_cli::upgrade::backup::BackupManager;
use std::path::PathBuf;
let exe_path = PathBuf::from("/usr/local/bin/agpm");
let backup_manager = BackupManager::new(exe_path);
// Create backup before upgrade
backup_manager.create_backup().await?;
// ... perform upgrade ...
// Restore if upgrade failed
let upgrade_failed = false; // Set based on upgrade result
if upgrade_failed {
backup_manager.restore_backup().await?;
} else {
backup_manager.cleanup_backup().await?;
}§Check for Existing Backup
use agpm_cli::upgrade::backup::BackupManager;
use std::path::PathBuf;
let backup_manager = BackupManager::new(PathBuf::from("agpm"));
if backup_manager.backup_exists() {
println!("Backup found at: {}", backup_manager.backup_path().display());
}§Error Handling
All operations return Result<T, anyhow::Error> with detailed error context:
- Permission errors when unable to read/write files
- File system errors during copy operations
- Platform-specific issues (Windows file locking, Unix permissions)
§Implementation Details
- Uses
tokio::fsfor async file operations - Implements platform-specific permission handling
- Provides detailed logging for debugging and monitoring
- Handles edge cases like missing files and permission issues
Implementations§
Source§impl BackupManager
impl BackupManager
Sourcepub fn new(executable_path: PathBuf) -> Self
pub fn new(executable_path: PathBuf) -> Self
Create a new BackupManager for the specified executable.
Automatically determines the backup file path by appending .backup
to the original executable name in the same directory.
§Arguments
executable_path- Full path to the executable binary to manage
§Examples
use agpm_cli::upgrade::backup::BackupManager;
use std::path::PathBuf;
// Unix-style path
let manager = BackupManager::new(PathBuf::from("/usr/local/bin/agpm"));
// Backup will be at /usr/local/bin/agpm.backup
// Windows-style path
let manager = BackupManager::new(PathBuf::from(r"C:\Program Files\agpm\agpm.exe"));
// Backup will be at C:\Program Files\agpm\agpm.exe.backupSourcepub async fn create_backup(&self) -> Result<()>
pub async fn create_backup(&self) -> Result<()>
Create a backup of the original binary.
Copies the current binary to the backup location, preserving permissions and metadata. If a backup already exists, it will be replaced.
§Process
- Validate that the original file exists
- Remove any existing backup file
- Copy the original file to the backup location
- Preserve file permissions on Unix systems
§Returns
Ok(())- Backup created successfullyErr(error)- Backup creation failed
§Errors
This method can fail if:
- The original file doesn’t exist or is not readable
- Insufficient permissions to create the backup file
- File system errors during the copy operation
- Unable to set permissions on the backup file (Unix)
§Examples
use agpm_cli::upgrade::backup::BackupManager;
use std::path::PathBuf;
let manager = BackupManager::new(PathBuf::from("./agpm"));
match manager.create_backup().await {
Ok(()) => println!("Backup created successfully"),
Err(e) => eprintln!("Failed to create backup: {}", e),
}Sourcepub async fn restore_backup(&self) -> Result<()>
pub async fn restore_backup(&self) -> Result<()>
Restore the original binary from backup.
Replaces the current binary with the backup copy, effectively rolling back to the previous version. This operation includes retry logic for Windows systems where the binary might be locked.
§Process
- Validate that a backup file exists
- Remove the current (potentially corrupted) binary
- Copy the backup file back to the original location
- Restore file permissions on Unix systems
- Retry up to 3 times on Windows for file locking issues
§Returns
Ok(())- Backup restored successfullyErr(error)- Restoration failed after all retries
§Errors
This method can fail if:
- No backup file exists at the expected location
- Insufficient permissions to replace the original file
- File locking issues prevent replacement (Windows)
- File system errors during the copy operation
- Unable to restore permissions (Unix)
§Platform Behavior
§Windows
- Implements retry logic with 1-second delays
- Handles file locking from running processes
- Attempts up to 3 times before giving up
§Unix
- Preserves executable permissions and ownership
- Single attempt (usually succeeds immediately)
§Examples
use agpm_cli::upgrade::backup::BackupManager;
use std::path::PathBuf;
let manager = BackupManager::new(PathBuf::from("./agpm"));
if manager.backup_exists() {
match manager.restore_backup().await {
Ok(()) => println!("Successfully restored from backup"),
Err(e) => eprintln!("Failed to restore backup: {}", e),
}
} else {
eprintln!("No backup found to restore");
}Sourcepub async fn cleanup_backup(&self) -> Result<()>
pub async fn cleanup_backup(&self) -> Result<()>
Remove the backup file after a successful upgrade.
Cleans up the backup file once it’s no longer needed, typically after a successful upgrade has been completed and verified.
§Returns
Ok(())- Backup cleaned up successfully or no backup existedErr(error)- Failed to remove the backup file
§Errors
This method can fail if:
- Insufficient permissions to delete the backup file
- File system errors during deletion
- File is locked or in use (rare on most systems)
§Examples
use agpm_cli::upgrade::backup::BackupManager;
use std::path::PathBuf;
let manager = BackupManager::new(PathBuf::from("./agpm"));
// After successful upgrade
manager.cleanup_backup().await?;
println!("Backup cleaned up");§Note
This method silently succeeds if no backup file exists, making it safe to call unconditionally after upgrades.
Sourcepub fn backup_exists(&self) -> bool
pub fn backup_exists(&self) -> bool
Check if a backup file currently exists.
This is a synchronous check that verifies whether a backup file is present at the expected location.
§Returns
true- A backup file exists and can potentially be restoredfalse- No backup file found at the expected location
§Examples
use agpm_cli::upgrade::backup::BackupManager;
use std::path::PathBuf;
let manager = BackupManager::new(PathBuf::from("./agpm"));
if manager.backup_exists() {
println!("Backup available for rollback");
} else {
println!("No backup found");
}§Note
This method only checks for file existence, not validity or integrity
of the backup file. Use restore_backup() to
verify the backup can actually be used.
Sourcepub fn backup_path(&self) -> &Path
pub fn backup_path(&self) -> &Path
Get the path where the backup file is stored.
Returns the full path to the backup file location, which is useful for logging, debugging, or manual backup management.
§Returns
A path reference to the backup file location.
§Examples
use agpm_cli::upgrade::backup::BackupManager;
use std::path::PathBuf;
let manager = BackupManager::new(PathBuf::from("/usr/local/bin/agpm"));
println!("Backup location: {}", manager.backup_path().display());
// Output: Backup location: /usr/local/bin/agpm.backup§Use Cases
- Logging: Include backup location in log messages
- Debugging: Help users locate backup files manually
- Error Messages: Show backup location when operations fail
- Manual Recovery: Allow users to manually restore backups
Auto Trait Implementations§
impl Freeze for BackupManager
impl RefUnwindSafe for BackupManager
impl Send for BackupManager
impl Sync for BackupManager
impl Unpin for BackupManager
impl UnwindSafe for BackupManager
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more