Skip to content

Commit

Permalink
Merge #3416
Browse files Browse the repository at this point in the history
3416: Download and install packages via .tar.gz URLs and improve installation error message r=fschutt a=fschutt

Fixes #3404.

Co-authored-by: Felix Schütt <felix@wasmer.io>
Co-authored-by: Felix Schütt <12084016+fschutt@users.noreply.github.com>
  • Loading branch information
3 people authored Dec 12, 2022
2 parents 2d17aa9 + f093658 commit 0e9d02b
Show file tree
Hide file tree
Showing 13 changed files with 842 additions and 1,097 deletions.
15 changes: 13 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -549,7 +549,7 @@ test-examples:
$(CARGO_BINARY) test $(CARGO_TARGET) --release $(compiler_features) --features wasi --examples

test-integration-cli:
$(CARGO_BINARY) test $(CARGO_TARGET) --features webc_runner --no-fail-fast -p wasmer-integration-tests-cli -- --nocapture
$(CARGO_BINARY) test $(CARGO_TARGET) --features webc_runner --no-fail-fast -p wasmer-integration-tests-cli -- --nocapture --test-threads=1

test-integration-ios:
$(CARGO_BINARY) test $(CARGO_TARGET) --features webc_runner -p wasmer-integration-tests-ios
Expand Down
1 change: 1 addition & 0 deletions lib/cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ webc = { version = "3.0.1", optional = true }
isatty = "0.1.9"
dialoguer = "0.10.2"
tldextract = "0.6.0"
hex = "0.4.3"

[build-dependencies]
chrono = { version = "^0.4", default-features = false, features = [ "std", "clock" ] }
Expand Down
210 changes: 0 additions & 210 deletions lib/cli/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ use crate::commands::{
};
use crate::error::PrettyError;
use clap::{CommandFactory, ErrorKind, Parser};
use std::{fmt, str::FromStr};

#[derive(Parser, Debug)]
#[cfg_attr(
Expand Down Expand Up @@ -243,218 +242,9 @@ fn wasmer_main_inner() -> Result<(), anyhow::Error> {
}
};

// Check if the file is a package name
if let WasmerCLIOptions::Run(r) = &options {
#[cfg(not(feature = "debug"))]
let debug = false;
#[cfg(feature = "debug")]
let debug = r.options.debug;
return crate::commands::try_run_package_or_file(&args, r, debug);
}

options.execute()
}

#[derive(Debug, Clone, PartialEq, Default)]
pub(crate) struct SplitVersion {
pub(crate) original: String,
pub(crate) registry: Option<String>,
pub(crate) package: String,
pub(crate) version: Option<String>,
pub(crate) command: Option<String>,
}

impl fmt::Display for SplitVersion {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let version = self.version.as_deref().unwrap_or("latest");
let command = self
.command
.as_ref()
.map(|s| format!(":{s}"))
.unwrap_or_default();
write!(f, "{}@{version}{command}", self.package)
}
}

#[test]
fn test_split_version() {
assert_eq!(
SplitVersion::parse("registry.wapm.io/graphql/python/python").unwrap(),
SplitVersion {
original: "registry.wapm.io/graphql/python/python".to_string(),
registry: Some("https://registry.wapm.io/graphql".to_string()),
package: "python/python".to_string(),
version: None,
command: None,
}
);
assert_eq!(
SplitVersion::parse("registry.wapm.io/python/python").unwrap(),
SplitVersion {
original: "registry.wapm.io/python/python".to_string(),
registry: Some("https://registry.wapm.io/graphql".to_string()),
package: "python/python".to_string(),
version: None,
command: None,
}
);
assert_eq!(
SplitVersion::parse("namespace/name@version:command").unwrap(),
SplitVersion {
original: "namespace/name@version:command".to_string(),
registry: None,
package: "namespace/name".to_string(),
version: Some("version".to_string()),
command: Some("command".to_string()),
}
);
assert_eq!(
SplitVersion::parse("namespace/name@version").unwrap(),
SplitVersion {
original: "namespace/name@version".to_string(),
registry: None,
package: "namespace/name".to_string(),
version: Some("version".to_string()),
command: None,
}
);
assert_eq!(
SplitVersion::parse("namespace/name").unwrap(),
SplitVersion {
original: "namespace/name".to_string(),
registry: None,
package: "namespace/name".to_string(),
version: None,
command: None,
}
);
assert_eq!(
SplitVersion::parse("registry.wapm.io/namespace/name").unwrap(),
SplitVersion {
original: "registry.wapm.io/namespace/name".to_string(),
registry: Some("https://registry.wapm.io/graphql".to_string()),
package: "namespace/name".to_string(),
version: None,
command: None,
}
);
assert_eq!(
format!("{}", SplitVersion::parse("namespace").unwrap_err()),
"Invalid package version: \"namespace\"".to_string(),
);
}

impl SplitVersion {
pub fn parse(s: &str) -> Result<SplitVersion, anyhow::Error> {
s.parse()
}
}

impl FromStr for SplitVersion {
type Err = anyhow::Error;

fn from_str(s: &str) -> Result<Self, Self::Err> {
let command = WasmerCLIOptions::command();
let mut prohibited_package_names = command.get_subcommands().map(|s| s.get_name());

let re1 = regex::Regex::new(r#"(.*)/(.*)@(.*):(.*)"#).unwrap();
let re2 = 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) {
re1.captures(s)
.map(|c| {
c.iter()
.flatten()
.map(|m| m.as_str().to_owned())
.collect::<Vec<_>>()
})
.unwrap_or_default()
} else if re2.is_match(s) {
re2.captures(s)
.map(|c| {
c.iter()
.flatten()
.map(|m| m.as_str().to_owned())
.collect::<Vec<_>>()
})
.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) {
re3.captures(s)
.map(|c| {
c.iter()
.flatten()
.map(|m| m.as_str().to_owned())
.collect::<Vec<_>>()
})
.unwrap_or_default()
} else {
return Err(anyhow::anyhow!("Invalid package version: {s:?}"));
};

let mut namespace = match captures.get(1).cloned() {
Some(s) => s,
None => {
return Err(anyhow::anyhow!(
"Invalid package version: {s:?}: no namespace"
))
}
};

let name = match captures.get(2).cloned() {
Some(s) => s,
None => return Err(anyhow::anyhow!("Invalid package version: {s:?}: no name")),
};

let mut registry = None;
if namespace.contains('/') {
let (r, n) = namespace.rsplit_once('/').unwrap();
let mut real_registry = r.to_string();
if !real_registry.ends_with("graphql") {
real_registry = format!("{real_registry}/graphql");
}
if !real_registry.contains("://") {
real_registry = format!("https://{real_registry}");
}
registry = Some(real_registry);
namespace = n.to_string();
}

let sv = SplitVersion {
original: s.to_string(),
registry,
package: format!("{namespace}/{name}"),
version: if no_version {
None
} else {
captures.get(3).cloned()
},
command: captures.get(if no_version { 3 } else { 4 }).cloned(),
};

let svp = sv.package.clone();
anyhow::ensure!(
!prohibited_package_names.any(|s| s == sv.package.trim()),
"Invalid package name {svp:?}"
);

Ok(sv)
}
}

fn print_help(verbose: bool) -> Result<(), anyhow::Error> {
let mut cmd = WasmerCLIOptions::command();
if verbose {
Expand Down
8 changes: 3 additions & 5 deletions lib/cli/src/commands/add.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@ use anyhow::{Context, Error};
use clap::Parser;
use wasmer_registry::{Bindings, PartialWapmConfig, ProgrammingLanguage};

use crate::cli::SplitVersion;

/// Add a WAPM package's bindings to your application.
#[derive(Debug, Parser)]
pub struct Add {
Expand All @@ -26,7 +24,7 @@ pub struct Add {
pip: bool,
/// The packages to add (e.g. "wasmer/wasmer-pack@0.5.0" or "python/python")
#[clap(parse(try_from_str))]
packages: Vec<SplitVersion>,
packages: Vec<wasmer_registry::Package>,
}

impl Add {
Expand Down Expand Up @@ -103,11 +101,11 @@ impl Add {

fn lookup_bindings_for_package(
registry: &str,
pkg: &SplitVersion,
pkg: &wasmer_registry::Package,
language: &ProgrammingLanguage,
) -> Result<Bindings, Error> {
let all_bindings =
wasmer_registry::list_bindings(registry, &pkg.package, pkg.version.as_deref())?;
wasmer_registry::list_bindings(registry, &pkg.package(), pkg.version.as_deref())?;

match all_bindings.iter().find(|b| b.language == *language) {
Some(b) => {
Expand Down
4 changes: 2 additions & 2 deletions lib/cli/src/commands/list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@ impl List {
pub fn execute(&self) -> Result<(), anyhow::Error> {
use prettytable::{format, row, Table};

let rows = wasmer_registry::get_all_local_packages(None)
let rows = wasmer_registry::get_all_local_packages()
.into_iter()
.filter_map(|pkg| {
let package_root_path = pkg.get_path().ok()?;
let package_root_path = pkg.path;
let (manifest, _) =
wasmer_registry::get_executable_file_from_path(&package_root_path, None)
.ok()?;
Expand Down
Loading

0 comments on commit 0e9d02b

Please sign in to comment.