Skip to Content
Nextra 2 Alpha
ExamplesLock File Operations

Lock File Operations

This example demonstrates how to use Rhema’s foundational lock file operations for managing dependency locks and ensuring reproducible builds.

Context

Lock files are essential for:

  • Deterministic builds - Ensuring the same dependencies are used across environments
  • Dependency tracking - Managing complex dependency graphs with version constraints
  • Integrity verification - Detecting when source files have changed
  • Conflict resolution - Handling dependency conflicts in multi-scope projects

Basic Lock File Operations

Creating a New Lock File

use rhema_core::{LockFileOps, RhemaLock, LockedScope, LockedDependency, DependencyType}; use std::path::Path; fn create_basic_lock_file() -> Result<(), Box<dyn std::error::Error>> { let lock_path = Path::new("rhema.lock"); // Create a new lock file let lock_data = LockFileOps::create_lock_file(lock_path, "rhema")?; println!("Created lock file with {} scopes", lock_data.scopes.len()); println!("Generated by: {}", lock_data.generated_by); println!("Checksum: {}", lock_data.checksum); Ok(()) }

Reading and Validating a Lock File

use rhema_core::{LockFileOps, ValidationResult}; fn validate_existing_lock_file() -> Result<(), Box<dyn std::error::Error>> { let lock_path = Path::new("rhema.lock"); // Read the lock file let lock_data = LockFileOps::read_lock_file(lock_path)?; println!("Lock file contains {} scopes", lock_data.scopes.len()); // Validate integrity let validation_result = LockFileOps::validate_lock_file_integrity(lock_path)?; if validation_result.is_valid { println!("✅ Lock file is valid"); } else { println!("❌ Lock file validation failed:"); for message in &validation_result.messages { println!(" - {}", message); } } println!("Validation took {}ms", validation_result.validation_time_ms); Ok(()) }

Adding Scopes and Dependencies

use rhema_core::{LockFileOps, RhemaLock, LockedScope, LockedDependency, DependencyType}; use chrono::Utc; fn add_scope_with_dependencies() -> Result<(), Box<dyn std::error::Error>> { let lock_path = Path::new("rhema.lock"); // Create a new scope let mut scope = LockedScope::new("1.0.0", "/api/service"); scope.has_circular_dependencies = false; // Add dependencies to the scope let dep1 = LockedDependency::new("2.1.0", "/shared/utils", DependencyType::Required); let dep2 = LockedDependency::new("1.5.0", "/database", DependencyType::Required); scope.add_dependency("utils".to_string(), dep1); scope.add_dependency("db".to_string(), dep2); // Update the lock file let _lock_data = LockFileOps::update_lock_file_scope(lock_path, "/api/service", scope)?; println!("Added scope /api/service with 2 dependencies"); Ok(()) }

Checking if Lock File is Outdated

use rhema_core::LockFileOps; use std::path::PathBuf; fn check_lock_file_freshness() -> Result<(), Box<dyn std::error::Error>> { let lock_path = Path::new("rhema.lock"); let source_paths = vec![ PathBuf::from("src/main.rs"), PathBuf::from("Cargo.toml"), PathBuf::from("rhema.yaml"), ]; let is_outdated = LockFileOps::is_lock_file_outdated(lock_path, &source_paths)?; if is_outdated { println!("⚠️ Lock file is outdated - source files have changed"); println!("Run 'rhema lock update' to regenerate the lock file"); } else { println!("✅ Lock file is up to date"); } Ok(()) }

Merging Multiple Lock Files

use rhema_core::{LockFileOps, ConflictResolution}; use std::path::PathBuf; fn merge_lock_files() -> Result<(), Box<dyn std::error::Error>> { let lock_files = vec![ PathBuf::from("frontend/rhema.lock"), PathBuf::from("backend/rhema.lock"), PathBuf::from("shared/rhema.lock"), ]; let output_path = PathBuf::from("merged.lock"); // Merge with automatic conflict resolution let merged_lock = LockFileOps::merge_lock_files( &output_path, &lock_files, ConflictResolution::Automatic, )?; println!("Merged {} lock files into {}", lock_files.len(), output_path.display()); println!("Total scopes: {}", merged_lock.scopes.len()); println!("Total dependencies: {}", merged_lock.metadata.total_dependencies); Ok(()) }

Backup and Restore Operations

use rhema_core::LockFileOps; fn backup_and_restore() -> Result<(), Box<dyn std::error::Error>> { let lock_path = Path::new("rhema.lock"); // Create a backup let backup_path = LockFileOps::backup_lock_file(lock_path)?; println!("Created backup: {}", backup_path.display()); // Simulate some changes to the lock file // ... (modify lock file) ... // Restore from backup LockFileOps::restore_lock_file(&backup_path, lock_path)?; println!("Restored lock file from backup"); Ok(()) }

Getting Lock File Statistics

use rhema_core::{LockFileOps, LockFileStats}; fn analyze_lock_file() -> Result<(), Box<dyn std::error::Error>> { let lock_path = Path::new("rhema.lock"); let stats = LockFileStats::from_lock_file(lock_path)?; println!("Lock File Analysis:"); println!(" Total scopes: {}", stats.total_scopes); println!(" Total dependencies: {}", stats.total_dependencies); println!(" Circular dependencies: {}", stats.circular_dependencies); println!(" File size: {} bytes", stats.file_size_bytes); println!(" Last modified: {}", stats.last_modified); println!(" Generation time: {}ms", stats.generation_time_ms); Ok(()) }

Advanced Usage

Custom Checksum Calculation

use rhema_core::LockFileOps; fn custom_checksum_operations() -> Result<(), Box<dyn std::error::Error>> { // Calculate checksum for a file let file_path = Path::new("src/main.rs"); let file_checksum = LockFileOps::calculate_file_checksum(file_path)?; println!("File checksum: {}", file_checksum); // Calculate checksum for content let content = "Hello, Rhema!"; let content_checksum = LockFileOps::calculate_content_checksum(content); println!("Content checksum: {}", content_checksum); Ok(()) }

Generating Lock File from Source

use rhema_core::{LockFileOps, LockedScope}; use std::collections::HashMap; fn generate_lock_from_source() -> Result<(), Box<dyn std::error::Error>> { let lock_path = Path::new("rhema.lock"); // Collect scopes from source files let mut scopes = HashMap::new(); // Add scopes discovered from source let api_scope = LockedScope::new("1.0.0", "/api"); let web_scope = LockedScope::new("2.0.0", "/web"); scopes.insert("/api".to_string(), api_scope); scopes.insert("/web".to_string(), web_scope); // Generate the lock file let lock_data = LockFileOps::generate_lock_file(lock_path, "rhema-scanner", scopes)?; println!("Generated lock file with {} scopes", lock_data.scopes.len()); println!("Generation time: {}ms", lock_data.metadata.performance_metrics .as_ref() .map(|m| m.generation_time_ms) .unwrap_or(0) ); Ok(()) }

Expected Output

When running these examples, you should see output similar to:

Created lock file with 0 scopes Generated by: rhema Checksum: checksum_1703123456 Lock file contains 3 scopes ✅ Lock file is valid Validation took 5ms Added scope /api/service with 2 dependencies ✅ Lock file is up to date Merged 3 lock files into merged.lock Total scopes: 8 Total dependencies: 24 Created backup: rhema.lock.backup.20231220123456 Restored lock file from backup Lock File Analysis: Total scopes: 3 Total dependencies: 12 Circular dependencies: 0 File size: 2048 bytes Last modified: 2023-12-20 12:34:56 UTC Generation time: 150ms

Best Practices

  1. Always validate lock files before using them in production
  2. Use backups before making significant changes to lock files
  3. Check freshness regularly to ensure lock files reflect current source
  4. Handle conflicts appropriately when merging lock files
  5. Monitor performance metrics to optimize lock file operations
  6. Use meaningful generated_by values for audit trails

Error Handling

The lock file operations return RhemaResult<T> which can contain various error types:

  • FileNotFound - Lock file or source files don’t exist
  • ValidationError - Lock file validation failed
  • LockError - Lock file operation failed
  • IoError - File system operations failed

Always handle these errors appropriately in your applications.

Integration with Rhema CLI

These lock file operations are integrated into the Rhema CLI:

# Generate a new lock file rhema lock generate # Validate existing lock file rhema lock validate # Update lock file from source rhema lock update # Merge multiple lock files rhema lock merge frontend/rhema.lock backend/rhema.lock # Show lock file statistics rhema lock stats

This provides a comprehensive foundation for managing dependency locks in Rhema projects.

Last updated on