mirror of
https://github.com/mii443/wasmer.git
synced 2025-12-09 22:28:21 +00:00
Fix issue when running wasmer/wit-pack and wabt
Fixed duplicated mapped directories when running the .wasm file
This commit is contained in:
@@ -14,6 +14,7 @@ use crate::commands::{Cache, Config, Inspect, Run, RunWithoutFile, SelfUpdate, V
|
|||||||
use crate::error::PrettyError;
|
use crate::error::PrettyError;
|
||||||
use clap::{CommandFactory, ErrorKind, Parser};
|
use clap::{CommandFactory, ErrorKind, Parser};
|
||||||
use spinner::SpinnerHandle;
|
use spinner::SpinnerHandle;
|
||||||
|
use std::fmt;
|
||||||
use wasmer_registry::{get_all_local_packages, PackageDownloadInfo};
|
use wasmer_registry::{get_all_local_packages, PackageDownloadInfo};
|
||||||
|
|
||||||
#[derive(Parser, Debug)]
|
#[derive(Parser, Debug)]
|
||||||
@@ -37,7 +38,6 @@ use wasmer_registry::{get_all_local_packages, PackageDownloadInfo};
|
|||||||
)]
|
)]
|
||||||
/// The options for the wasmer Command Line Interface
|
/// The options for the wasmer Command Line Interface
|
||||||
enum WasmerCLIOptions {
|
enum WasmerCLIOptions {
|
||||||
|
|
||||||
/// List all locally installed packages
|
/// List all locally installed packages
|
||||||
#[clap(name = "list")]
|
#[clap(name = "list")]
|
||||||
List,
|
List,
|
||||||
@@ -253,10 +253,40 @@ fn try_run_package_or_file(args: &[String], r: &Run) -> Result<(), anyhow::Error
|
|||||||
|
|
||||||
let package = format!("{}", r.path.display());
|
let package = format!("{}", r.path.display());
|
||||||
|
|
||||||
|
let mut is_fake_sv = false;
|
||||||
let mut sv = match split_version(&package) {
|
let mut sv = match split_version(&package) {
|
||||||
Ok(o) => o,
|
Ok(o) => o,
|
||||||
Err(_) => return r.execute(),
|
Err(_) => {
|
||||||
|
let mut fake_sv = SplitVersion {
|
||||||
|
package: package.to_string(),
|
||||||
|
version: None,
|
||||||
|
command: None,
|
||||||
};
|
};
|
||||||
|
is_fake_sv = true;
|
||||||
|
match try_lookup_command(&mut fake_sv) {
|
||||||
|
Ok(o) => SplitVersion {
|
||||||
|
package: o.package,
|
||||||
|
version: Some(o.version),
|
||||||
|
command: r.command_name.clone(),
|
||||||
|
},
|
||||||
|
Err(e) => {
|
||||||
|
return Err(
|
||||||
|
anyhow::anyhow!("No package for command {package:?} found, file {package:?} not found either")
|
||||||
|
.context(e)
|
||||||
|
.context(anyhow::anyhow!("{}", r.path.display()))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if sv.command.is_none() {
|
||||||
|
sv.command = r.command_name.clone();
|
||||||
|
}
|
||||||
|
|
||||||
|
if sv.command.is_none() && is_fake_sv {
|
||||||
|
sv.command = Some(package.to_string());
|
||||||
|
}
|
||||||
|
|
||||||
let mut package_download_info = None;
|
let mut package_download_info = None;
|
||||||
if !sv.package.contains('/') {
|
if !sv.package.contains('/') {
|
||||||
@@ -289,7 +319,7 @@ fn try_lookup_command(sv: &mut SplitVersion) -> Result<PackageDownloadInfo, anyh
|
|||||||
}
|
}
|
||||||
|
|
||||||
sp.close();
|
sp.close();
|
||||||
Err(anyhow::anyhow!("command {sv:?} not found"))
|
Err(anyhow::anyhow!("command {sv} not found"))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn try_execute_local_package(args: &[String], sv: &SplitVersion) -> Result<(), anyhow::Error> {
|
fn try_execute_local_package(args: &[String], sv: &SplitVersion) -> Result<(), anyhow::Error> {
|
||||||
@@ -303,6 +333,7 @@ fn try_execute_local_package(args: &[String], sv: &SplitVersion) -> Result<(), a
|
|||||||
&package.registry,
|
&package.registry,
|
||||||
&package.name,
|
&package.name,
|
||||||
&package.version,
|
&package.version,
|
||||||
|
sv.command.as_ref().map(|s| s.as_str()),
|
||||||
)
|
)
|
||||||
.map_err(|e| anyhow!("{e}"))?;
|
.map_err(|e| anyhow!("{e}"))?;
|
||||||
|
|
||||||
@@ -310,11 +341,22 @@ fn try_execute_local_package(args: &[String], sv: &SplitVersion) -> Result<(), a
|
|||||||
let mut args_without_package = args.to_vec();
|
let mut args_without_package = args.to_vec();
|
||||||
args_without_package.remove(1);
|
args_without_package.remove(1);
|
||||||
|
|
||||||
let mut run_args = RunWithoutFile::try_parse_from(args_without_package.iter())?;
|
if args_without_package.get(1) == Some(&sv.package)
|
||||||
run_args.command_name = sv.command.clone();
|
|| args_without_package.get(1) == sv.command.as_ref()
|
||||||
run_args
|
{
|
||||||
.into_run_args(local_package_wasm_path, Some(package.manifest))
|
args_without_package.remove(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if args_without_package.get(0) == Some(&sv.package)
|
||||||
|
|| args_without_package.get(0) == sv.command.as_ref()
|
||||||
|
{
|
||||||
|
args_without_package.remove(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
RunWithoutFile::try_parse_from(args_without_package.iter())?
|
||||||
|
.into_run_args(local_package_wasm_path.clone(), Some(package.manifest))
|
||||||
.execute()
|
.execute()
|
||||||
|
.map_err(|e| e.context(anyhow::anyhow!("{}", local_package_wasm_path.display())))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn try_autoinstall_package(
|
fn try_autoinstall_package(
|
||||||
@@ -362,6 +404,22 @@ struct SplitVersion {
|
|||||||
command: Option<String>,
|
command: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for SplitVersion {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
let version = self
|
||||||
|
.version
|
||||||
|
.as_ref()
|
||||||
|
.map(|s| s.as_str())
|
||||||
|
.unwrap_or("latest");
|
||||||
|
let command = self
|
||||||
|
.command
|
||||||
|
.as_ref()
|
||||||
|
.map(|s| format!(":{s}"))
|
||||||
|
.unwrap_or_default();
|
||||||
|
write!(f, "{}@{version}{command}", self.package)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_split_version() {
|
fn test_split_version() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
@@ -401,6 +459,9 @@ fn split_version(s: &str) -> Result<SplitVersion, anyhow::Error> {
|
|||||||
let re1 = regex::Regex::new(r#"(.*)/(.*)@(.*):(.*)"#).unwrap();
|
let re1 = regex::Regex::new(r#"(.*)/(.*)@(.*):(.*)"#).unwrap();
|
||||||
let re2 = regex::Regex::new(r#"(.*)/(.*)@(.*)"#).unwrap();
|
let re2 = regex::Regex::new(r#"(.*)/(.*)@(.*)"#).unwrap();
|
||||||
let re3 = regex::Regex::new(r#"(.*)/(.*)"#).unwrap();
|
let re3 = regex::Regex::new(r#"(.*)/(.*)"#).unwrap();
|
||||||
|
let re4 = regex::Regex::new(r#"(.*)/(.*):(.*)"#).unwrap();
|
||||||
|
|
||||||
|
let mut no_version = false;
|
||||||
|
|
||||||
let captures = if re1.is_match(s) {
|
let captures = if re1.is_match(s) {
|
||||||
re1.captures(s)
|
re1.captures(s)
|
||||||
@@ -420,6 +481,16 @@ fn split_version(s: &str) -> Result<SplitVersion, anyhow::Error> {
|
|||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
})
|
})
|
||||||
.unwrap_or_default()
|
.unwrap_or_default()
|
||||||
|
} else if re4.is_match(s) {
|
||||||
|
no_version = true;
|
||||||
|
re4.captures(s)
|
||||||
|
.map(|c| {
|
||||||
|
c.iter()
|
||||||
|
.flatten()
|
||||||
|
.map(|m| m.as_str().to_owned())
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
})
|
||||||
|
.unwrap_or_default()
|
||||||
} else if re3.is_match(s) {
|
} else if re3.is_match(s) {
|
||||||
re3.captures(s)
|
re3.captures(s)
|
||||||
.map(|c| {
|
.map(|c| {
|
||||||
@@ -449,8 +520,12 @@ fn split_version(s: &str) -> Result<SplitVersion, anyhow::Error> {
|
|||||||
|
|
||||||
let sv = SplitVersion {
|
let sv = SplitVersion {
|
||||||
package: format!("{namespace}/{name}"),
|
package: format!("{namespace}/{name}"),
|
||||||
version: captures.get(3).cloned(),
|
version: if no_version {
|
||||||
command: captures.get(4).cloned(),
|
None
|
||||||
|
} else {
|
||||||
|
captures.get(3).cloned()
|
||||||
|
},
|
||||||
|
command: captures.get(if no_version { 3 } else { 4 }).cloned(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let svp = sv.package.clone();
|
let svp = sv.package.clone();
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ use crate::store::{CompilerType, StoreOptions};
|
|||||||
use crate::suggestions::suggest_function_exports;
|
use crate::suggestions::suggest_function_exports;
|
||||||
use crate::warning;
|
use crate::warning;
|
||||||
use anyhow::{anyhow, Context, Result};
|
use anyhow::{anyhow, Context, Result};
|
||||||
|
use std::collections::BTreeMap;
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
@@ -81,6 +82,9 @@ pub struct RunWithoutFile {
|
|||||||
impl RunWithoutFile {
|
impl RunWithoutFile {
|
||||||
/// Given a local path, returns the `Run` command (overriding the `--path` argument).
|
/// Given a local path, returns the `Run` command (overriding the `--path` argument).
|
||||||
pub fn into_run_args(mut self, pathbuf: PathBuf, manifest: Option<wapm_toml::Manifest>) -> Run {
|
pub fn into_run_args(mut self, pathbuf: PathBuf, manifest: Option<wapm_toml::Manifest>) -> Run {
|
||||||
|
#[cfg(feature = "wasi")]
|
||||||
|
let mut wasi_map_dir = Vec::new();
|
||||||
|
|
||||||
#[cfg(feature = "wasi")]
|
#[cfg(feature = "wasi")]
|
||||||
{
|
{
|
||||||
let pkg_fs = match pathbuf.parent() {
|
let pkg_fs = match pathbuf.parent() {
|
||||||
@@ -92,13 +96,13 @@ impl RunWithoutFile {
|
|||||||
.and_then(|m| m.package.pkg_fs_mount_point.clone())
|
.and_then(|m| m.package.pkg_fs_mount_point.clone())
|
||||||
{
|
{
|
||||||
if m == "." {
|
if m == "." {
|
||||||
self.wasi.map_dir("/", pkg_fs);
|
wasi_map_dir.push(("/".to_string(), pkg_fs));
|
||||||
} else {
|
} else {
|
||||||
if m.starts_with('.') {
|
if m.starts_with('.') {
|
||||||
m = format!("{}{}", pkg_fs.display(), &m[1..]);
|
m = format!("{}{}", pkg_fs.display(), &m[1..]);
|
||||||
}
|
}
|
||||||
let path = std::path::Path::new(&m).to_path_buf();
|
let path = std::path::Path::new(&m).to_path_buf();
|
||||||
self.wasi.map_dir("/", path);
|
wasi_map_dir.push(("/".to_string(), path));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -123,7 +127,7 @@ impl RunWithoutFile {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
let alias_pathbuf = std::path::Path::new(&real_dir).to_path_buf();
|
let alias_pathbuf = std::path::Path::new(&real_dir).to_path_buf();
|
||||||
self.wasi.map_dir(alias, alias_pathbuf.clone());
|
wasi_map_dir.push((alias.to_string(), alias_pathbuf.clone()));
|
||||||
|
|
||||||
fn is_dir(e: &walkdir::DirEntry) -> bool {
|
fn is_dir(e: &walkdir::DirEntry) -> bool {
|
||||||
let meta = match e.metadata() {
|
let meta = match e.metadata() {
|
||||||
@@ -142,12 +146,34 @@ impl RunWithoutFile {
|
|||||||
let pathbuf = entry.path().canonicalize().unwrap();
|
let pathbuf = entry.path().canonicalize().unwrap();
|
||||||
let path = format!("{}", pathbuf.display());
|
let path = format!("{}", pathbuf.display());
|
||||||
let relativepath = path.replacen(&root_display, "", 1);
|
let relativepath = path.replacen(&root_display, "", 1);
|
||||||
self.wasi
|
wasi_map_dir.push((format!("/{alias}{relativepath}"), pathbuf));
|
||||||
.map_dir(&format!("/{alias}{relativepath}"), pathbuf);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If a directory is mapped twice, the WASI runtime will throw an error
|
||||||
|
// We need to calculate the "key" path, then deduplicate the mapping
|
||||||
|
#[cfg(feature = "wasi")]
|
||||||
|
{
|
||||||
|
let parent = match pathbuf.parent() {
|
||||||
|
Some(parent) => parent.to_path_buf(),
|
||||||
|
None => pathbuf.clone(),
|
||||||
|
};
|
||||||
|
let mut wasi_map = BTreeMap::new();
|
||||||
|
for (k, v) in wasi_map_dir {
|
||||||
|
let path_v = v.canonicalize().unwrap_or(v.clone());
|
||||||
|
let mut k_path = std::path::Path::new(&k).to_path_buf();
|
||||||
|
if k_path.is_relative() {
|
||||||
|
k_path = parent.join(&k);
|
||||||
|
}
|
||||||
|
let key = format!("{}", k_path.canonicalize().unwrap_or(k_path).display());
|
||||||
|
wasi_map.insert(key, (k, path_v));
|
||||||
|
}
|
||||||
|
for (_, (k, v)) in wasi_map {
|
||||||
|
self.wasi.map_dir(&k, v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Run {
|
Run {
|
||||||
path: pathbuf,
|
path: pathbuf,
|
||||||
options: RunWithoutFile {
|
options: RunWithoutFile {
|
||||||
@@ -155,7 +181,10 @@ impl RunWithoutFile {
|
|||||||
#[cfg(feature = "cache")]
|
#[cfg(feature = "cache")]
|
||||||
disable_cache: self.disable_cache,
|
disable_cache: self.disable_cache,
|
||||||
invoke: self.invoke,
|
invoke: self.invoke,
|
||||||
command_name: self.command_name,
|
// If the RunWithoutFile was constructed via a package name,
|
||||||
|
// the correct syntax is "package:command-name" (--command-name would be
|
||||||
|
// interpreted as a CLI argument for the .wasm file)
|
||||||
|
command_name: None,
|
||||||
#[cfg(feature = "cache")]
|
#[cfg(feature = "cache")]
|
||||||
cache_key: self.cache_key,
|
cache_key: self.cache_key,
|
||||||
store: self.store,
|
store: self.store,
|
||||||
|
|||||||
@@ -561,6 +561,7 @@ pub fn get_package_local_wasm_file(
|
|||||||
registry_host: &str,
|
registry_host: &str,
|
||||||
name: &str,
|
name: &str,
|
||||||
version: &str,
|
version: &str,
|
||||||
|
command: Option<&str>,
|
||||||
) -> Result<PathBuf, String> {
|
) -> Result<PathBuf, String> {
|
||||||
let dir = get_package_local_dir(registry_host, name, version)?;
|
let dir = get_package_local_dir(registry_host, name, version)?;
|
||||||
let wapm_toml_path = dir.join("wapm.toml");
|
let wapm_toml_path = dir.join("wapm.toml");
|
||||||
@@ -570,14 +571,17 @@ pub fn get_package_local_wasm_file(
|
|||||||
.map_err(|e| format!("cannot parse wapm.toml for {name}@{version}: {e}"))?;
|
.map_err(|e| format!("cannot parse wapm.toml for {name}@{version}: {e}"))?;
|
||||||
|
|
||||||
// TODO: this will just return the path for the first command, so this might not be correct
|
// TODO: this will just return the path for the first command, so this might not be correct
|
||||||
let module_name = wapm
|
let module_name = match command {
|
||||||
|
Some(s) => s.to_string(),
|
||||||
|
None => wapm
|
||||||
.command
|
.command
|
||||||
.unwrap_or_default()
|
.unwrap_or_default()
|
||||||
.first()
|
.first()
|
||||||
.map(|m| m.get_module())
|
.map(|m| m.get_module())
|
||||||
.ok_or_else(|| {
|
.ok_or_else(|| {
|
||||||
format!("cannot get entrypoint for {name}@{version}: package has no commands")
|
format!("cannot get entrypoint for {name}@{version}: package has no commands")
|
||||||
})?;
|
})?,
|
||||||
|
};
|
||||||
|
|
||||||
let wasm_file_name = wapm
|
let wasm_file_name = wapm
|
||||||
.module
|
.module
|
||||||
|
|||||||
Reference in New Issue
Block a user