diff --git a/lib/src/cli.rs b/lib/src/cli.rs index af78d3dd..d89a58ea 100644 --- a/lib/src/cli.rs +++ b/lib/src/cli.rs @@ -10,7 +10,7 @@ use camino::{Utf8Path, Utf8PathBuf}; use cap_std::fs::Dir; use cap_std_ext::cap_std; use cap_std_ext::prelude::CapStdExtDirExt; -use clap::{Parser, Subcommand}; +use clap::{Parser, Subcommand, builder::ArgPredicate}; use fn_error_context::context; use io_lifetimes::AsFd; use ostree::{gio, glib}; @@ -178,6 +178,10 @@ pub(crate) enum ContainerOpts { /// Image reference, e.g. ostree-remote-image:someremote:registry:quay.io/exampleos/exampleos:latest #[clap(value_parser = parse_imgref)] imgref_new: OstreeImageReference, + + /// Use JSON as output format. + #[clap(long)] + json: bool, }, } @@ -234,6 +238,10 @@ pub(crate) enum ContainerImageOpts { /// the new manifest. #[clap(long)] check: Option, + + /// Use JSON as output format. Only applies to the --check option. + #[clap(long, requires_if(ArgPredicate::IsPresent, "check"))] + json: bool, }, /// Output metadata about an already stored container image. @@ -717,6 +725,7 @@ async fn container_store( proxyopts: ContainerProxyOpts, quiet: bool, check: Option, + json: bool ) -> Result<()> { let mut imp = ImageImporter::new(repo, imgref, proxyopts.into()).await?; let prep = match imp.prepare().await? { @@ -739,7 +748,7 @@ async fn container_store( } if let Some(previous_state) = prep.previous_state.as_ref() { let diff = ManifestDiff::new(&previous_state.manifest, &prep.manifest); - diff.print(); + diff.print(json); } print_layer_status(&prep); let printer = (!quiet).then(|| { @@ -965,9 +974,10 @@ async fn run_from_opt(opt: Opt) -> Result<()> { proxyopts, quiet, check, + json, } => { let repo = parse_repo(&repo)?; - container_store(&repo, &imgref, proxyopts, quiet, check).await + container_store(&repo, &imgref, proxyopts, quiet, check, json).await } ContainerImageOpts::History { repo, imgref } => { let repo = parse_repo(&repo)?; @@ -1177,12 +1187,13 @@ async fn run_from_opt(opt: Opt) -> Result<()> { ContainerOpts::Compare { imgref_old, imgref_new, + json, } => { let (manifest_old, _) = crate::container::fetch_manifest(&imgref_old).await?; let (manifest_new, _) = crate::container::fetch_manifest(&imgref_new).await?; let manifest_diff = crate::container::ManifestDiff::new(&manifest_old, &manifest_new); - manifest_diff.print(); + manifest_diff.print(json); Ok(()) } }, diff --git a/lib/src/container/mod.rs b/lib/src/container/mod.rs index f34f085c..819ef368 100644 --- a/lib/src/container/mod.rs +++ b/lib/src/container/mod.rs @@ -376,16 +376,34 @@ impl<'a> ManifestDiff<'a> { impl<'a> ManifestDiff<'a> { /// Prints the total, removed and added content between two OCI images - pub fn print(&self) { - let print_total = self.total; - let print_total_size = glib::format_size(self.total_size); - let print_n_removed = self.n_removed; - let print_removed_size = glib::format_size(self.removed_size); - let print_n_added = self.n_added; - let print_added_size = glib::format_size(self.added_size); - println!("Total new layers: {print_total:<4} Size: {print_total_size}"); - println!("Removed layers: {print_n_removed:<4} Size: {print_removed_size}"); - println!("Added layers: {print_n_added:<4} Size: {print_added_size}"); + pub fn print(&self, json: bool) { + if json { + // TODO: Convert that to a proper JSON object + println!("{{"); + println!(" \"total\": {{"); + println!(" \"count\": \"{{self.total}}\","); + println!(" \"size\": \"{{self.total_size}}\""); + println!(" }},"); + println!(" \"removed\": {{"); + println!(" \"count\": \"{{self.n_removed}}\","); + println!(" \"size\": \"{{self.removed_size}}\""); + println!(" }},"); + println!(" \"added\": {{"); + println!(" \"count\": \"{{self.n_added}}\","); + println!(" \"size\": \"{{self.added_size}}\""); + println!(" }}"); + println!("}}"); + } else { + let print_total = self.total; + let print_total_size = glib::format_size(self.total_size); + let print_n_removed = self.n_removed; + let print_removed_size = glib::format_size(self.removed_size); + let print_n_added = self.n_added; + let print_added_size = glib::format_size(self.added_size); + println!("Total new layers: {print_total:<4} Size: {print_total_size}"); + println!("Removed layers: {print_n_removed:<4} Size: {print_removed_size}"); + println!("Added layers: {print_n_added:<4} Size: {print_added_size}"); + } } }