diff --git a/crates/composefs-oci/src/lib.rs b/crates/composefs-oci/src/lib.rs index 65f1a837..362d49ed 100644 --- a/crates/composefs-oci/src/lib.rs +++ b/crates/composefs-oci/src/lib.rs @@ -17,6 +17,9 @@ pub mod oci_image; pub mod skopeo; pub mod tar; +// Re-export the composefs crate for consumers who only need composefs-oci +pub use composefs; + use std::{collections::HashMap, sync::Arc}; use anyhow::{bail, ensure, Context, Result}; @@ -55,6 +58,11 @@ pub struct ImportStats { } impl ImportStats { + /// Total number of objects processed (new + already present). + pub fn total_objects(&self) -> u64 { + self.objects_copied + self.objects_already_present + } + /// Merge another `ImportStats` into this one. pub fn merge(&mut self, other: &ImportStats) { self.objects_copied += other.objects_copied; @@ -84,6 +92,19 @@ impl ImportStats { } } +impl std::fmt::Display for ImportStats { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!( + f, + "{} new + {} already present objects; {} stored, {} inlined", + self.objects_copied, + self.objects_already_present, + indicatif::HumanBytes(self.bytes_copied), + indicatif::HumanBytes(self.bytes_inlined), + ) + } +} + /// Result of a pull operation. #[derive(Debug)] pub struct PullResult { @@ -469,4 +490,26 @@ mod test { let result = open_config::(&repo, &config_digest, None); assert!(result.is_ok()); } + + #[test] + fn test_import_stats_display() { + let stats = ImportStats { + objects_copied: 42, + objects_already_present: 100, + bytes_copied: 1_500_000, + bytes_inlined: 800, + }; + assert_eq!( + stats.to_string(), + "42 new + 100 already present objects; 1.43 MiB stored, 800 B inlined" + ); + + let empty = ImportStats::default(); + assert_eq!( + empty.to_string(), + "0 new + 0 already present objects; 0 B stored, 0 B inlined" + ); + assert_eq!(empty.total_objects(), 0); + assert_eq!(stats.total_objects(), 142); + } }