greentic_component/cmd/
store.rs1use std::fs;
2use std::path::PathBuf;
3
4use anyhow::{Context, Result, bail};
5use clap::{Args, Subcommand};
6
7use crate::store::{CompatPolicy, ComponentStore};
8
9#[derive(Subcommand, Debug, Clone)]
10pub enum StoreCommand {
11 Fetch(StoreFetchArgs),
13}
14
15#[derive(Args, Debug, Clone)]
16pub struct StoreFetchArgs {
17 #[arg(long, value_name = "PATH", conflicts_with = "oci")]
19 pub fs: Option<PathBuf>,
20 #[arg(long, value_name = "REF", conflicts_with = "fs")]
22 pub oci: Option<String>,
23 #[arg(long, value_name = "PATH")]
25 pub output: PathBuf,
26 #[arg(long, value_name = "DIR")]
28 pub cache_dir: Option<PathBuf>,
29 #[arg(long, value_name = "ID", default_value = "default")]
31 pub source: String,
32}
33
34pub fn run(command: StoreCommand) -> Result<()> {
35 match command {
36 StoreCommand::Fetch(args) => fetch(args),
37 }
38}
39
40fn fetch(args: StoreFetchArgs) -> Result<()> {
41 let mut store = ComponentStore::with_cache_dir(args.cache_dir.clone(), CompatPolicy::default());
42 match (&args.fs, &args.oci) {
43 (Some(path), None) => {
44 store.add_fs(&args.source, path);
45 }
46 (None, Some(reference)) => {
47 store.add_oci(&args.source, reference);
48 }
49 _ => bail!("specify exactly one of --fs or --oci"),
50 }
51 let rt = tokio::runtime::Runtime::new().context("failed to create async runtime")?;
52 let bytes = rt
53 .block_on(async { store.get(&args.source).await })
54 .context("store fetch failed")?;
55 fs::write(&args.output, &bytes.bytes)?;
56 println!(
57 "Wrote {} ({} bytes) for source {}",
58 args.output.display(),
59 bytes.bytes.len(),
60 args.source
61 );
62 Ok(())
63}