greentic_component/cmd/
hash.rs1use std::fs;
2use std::path::{Path, PathBuf};
3
4use anyhow::{Context, Result};
5use clap::{Args, Parser};
6use serde_json::Value;
7
8#[derive(Args, Debug, Clone)]
9#[command(about = "Recompute the wasm hash inside component.manifest.json")]
10pub struct HashArgs {
11 #[arg(default_value = "component.manifest.json")]
13 pub manifest: PathBuf,
14 #[arg(long)]
16 pub wasm: Option<PathBuf>,
17}
18
19#[derive(Parser, Debug)]
20struct HashCli {
21 #[command(flatten)]
22 args: HashArgs,
23}
24
25pub fn parse_from_cli() -> HashArgs {
26 HashCli::parse().args
27}
28
29pub fn run(args: HashArgs) -> Result<()> {
30 let manifest_path = args.manifest;
31 let manifest_text = fs::read_to_string(&manifest_path)
32 .with_context(|| format!("failed to read {}", manifest_path.display()))?;
33 let mut manifest: Value = serde_json::from_str(&manifest_text)
34 .with_context(|| format!("invalid json: {}", manifest_path.display()))?;
35 let wasm_path = resolve_wasm_path(&manifest, args.wasm.as_deref(), &manifest_path)?;
36 let wasm_bytes = fs::read(&wasm_path)
37 .with_context(|| format!("failed to read wasm at {}", wasm_path.display()))?;
38 let digest = blake3::hash(&wasm_bytes).to_hex().to_string();
39 manifest["hashes"]["component_wasm"] = Value::String(format!("blake3:{digest}"));
40 let formatted = serde_json::to_string_pretty(&manifest)?;
41 fs::write(&manifest_path, formatted + "\n")
42 .with_context(|| format!("failed to write {}", manifest_path.display()))?;
43 println!(
44 "Updated {} with hash of {}",
45 manifest_path.display(),
46 wasm_path.display()
47 );
48 Ok(())
49}
50
51fn resolve_wasm_path(
52 manifest: &Value,
53 override_path: Option<&Path>,
54 manifest_path: &Path,
55) -> Result<PathBuf> {
56 if let Some(path) = override_path {
57 return Ok(path.to_path_buf());
58 }
59 let artifact = manifest
60 .get("artifacts")
61 .and_then(|art| art.get("component_wasm"))
62 .and_then(Value::as_str)
63 .ok_or_else(|| anyhow::anyhow!("manifest is missing artifacts.component_wasm"))?;
64 let root = manifest_path
65 .parent()
66 .map(Path::to_path_buf)
67 .unwrap_or_else(|| PathBuf::from("."));
68 Ok(root.join(artifact))
69}