wac_cli/commands/
resolve.rs1use crate::{fmt_err, PackageResolver};
2use anyhow::{Context, Result};
3use clap::Args;
4use std::{fs, path::PathBuf};
5use wac_parser::Document;
6
7fn parse<T, U>(s: &str) -> Result<(T, U)>
8where
9 T: std::str::FromStr,
10 T::Err: Into<anyhow::Error>,
11 U: std::str::FromStr,
12 U::Err: Into<anyhow::Error>,
13{
14 let (k, v) = s.split_once('=').context("value does not contain `=`")?;
15
16 Ok((
17 k.trim().parse().map_err(Into::into)?,
18 v.trim().parse().map_err(Into::into)?,
19 ))
20}
21
22#[derive(Args)]
24#[clap(disable_version_flag = true)]
25pub struct ResolveCommand {
26 #[clap(long, value_name = "PATH", default_value = "deps")]
28 pub deps_dir: PathBuf,
29
30 #[clap(long = "dep", short, value_name = "PKG=PATH", value_parser = parse::<String, PathBuf>)]
32 pub deps: Vec<(String, PathBuf)>,
33
34 #[cfg(feature = "registry")]
36 #[clap(long, value_name = "URL")]
37 pub registry: Option<String>,
38
39 #[clap(value_name = "PATH")]
41 pub path: PathBuf,
42}
43
44impl ResolveCommand {
45 pub async fn exec(self) -> Result<()> {
47 log::debug!("executing resolve command");
48
49 let contents = fs::read_to_string(&self.path)
50 .with_context(|| format!("failed to read file `{path}`", path = self.path.display()))?;
51
52 let document = Document::parse(&contents).map_err(|e| fmt_err(e, &self.path, &contents))?;
53
54 let mut resolver = PackageResolver::new(
55 self.deps_dir,
56 self.deps.into_iter().collect(),
57 #[cfg(feature = "registry")]
58 self.registry.as_deref(),
59 )
60 .await?;
61
62 let packages = resolver
63 .resolve(&document)
64 .await
65 .map_err(|e| fmt_err(e, &self.path, &contents))?;
66
67 let resolution = document
68 .resolve(packages)
69 .map_err(|e| fmt_err(e, &self.path, &contents))?;
70
71 print!("{:?}", resolution.into_graph());
72
73 Ok(())
74 }
75}