wasmer_cli/commands/run/
package_source.rs

1use std::{
2    path::{Path, PathBuf},
3    sync::Arc,
4};
5
6use anyhow::Error;
7use indicatif::ProgressBar;
8use wasmer_config::package::PackageSource;
9use wasmer_wasix::{
10    Runtime, bin_factory::BinaryPackage, runtime::task_manager::VirtualTaskManagerExt as _,
11};
12
13use super::ExecutableTarget;
14
15/// CLI representation of a target to execute.
16#[derive(Debug, Clone, PartialEq)]
17pub enum CliPackageSource {
18    /// A file on disk (`*.wasm`, `*.webc`, etc.).
19    File(PathBuf),
20    /// A directory containing a `wasmer.toml` file
21    Dir(PathBuf),
22    /// A package to be downloaded (a URL, package name, etc.)
23    Package(PackageSource),
24}
25
26impl CliPackageSource {
27    pub fn infer(s: &str) -> Result<CliPackageSource, Error> {
28        let path = Path::new(s);
29        if path.is_file() {
30            return Ok(Self::File(path.to_path_buf()));
31        } else if path.is_dir() {
32            return Ok(Self::Dir(path.to_path_buf()));
33        }
34
35        if let Ok(pkg) = s.parse::<PackageSource>() {
36            return Ok(Self::Package(pkg));
37        }
38
39        Err(anyhow::anyhow!(
40            "Unable to resolve \"{s}\" as a URL, package name, or file on disk"
41        ))
42    }
43
44    /// Try to resolve the [`PackageSource`] to an executable artifact.
45    ///
46    /// This will try to automatically download and cache any resources from the
47    /// internet.
48    #[tracing::instrument(level = "debug", skip_all)]
49    pub fn resolve_target(
50        &self,
51        rt: &Arc<dyn Runtime + Send + Sync>,
52        pb: &ProgressBar,
53    ) -> Result<ExecutableTarget, Error> {
54        match self {
55            Self::File(path) => ExecutableTarget::from_file(path, rt, pb),
56            Self::Dir(d) => ExecutableTarget::from_dir(d, rt, pb),
57            Self::Package(pkg) => {
58                pb.set_message("Loading from the registry");
59                let inner_pck = pkg.clone();
60                let inner_rt = rt.clone();
61                let pkg = rt.task_manager().spawn_and_block_on(async move {
62                    BinaryPackage::from_registry(&inner_pck, inner_rt.as_ref()).await
63                })??;
64                Ok(ExecutableTarget::Package(Box::new(pkg)))
65            }
66        }
67    }
68}
69
70impl std::fmt::Display for CliPackageSource {
71    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
72        match self {
73            Self::File(path) | Self::Dir(path) => {
74                write!(f, "{}", path.display())
75            }
76            Self::Package(p) => write!(f, "{p}"),
77        }
78    }
79}