greentic_component/cmd/
store.rs

1use 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 a component from a source and write the wasm bytes to disk
12    Fetch(StoreFetchArgs),
13}
14
15#[derive(Args, Debug, Clone)]
16pub struct StoreFetchArgs {
17    /// Filesystem path to a component directory containing component.manifest.json
18    #[arg(long, value_name = "PATH", conflicts_with = "oci")]
19    pub fs: Option<PathBuf>,
20    /// OCI reference to a published component (requires the `oci` feature)
21    #[arg(long, value_name = "REF", conflicts_with = "fs")]
22    pub oci: Option<String>,
23    /// Destination path to write the fetched component bytes
24    #[arg(long, value_name = "PATH")]
25    pub output: PathBuf,
26    /// Optional cache directory for fetched components
27    #[arg(long, value_name = "DIR")]
28    pub cache_dir: Option<PathBuf>,
29    /// Source identifier to register inside the store
30    #[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}