diff --git a/Cargo.lock b/Cargo.lock index 41e9e34fea..be431a5252 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7526,6 +7526,7 @@ dependencies = [ "clap_complete", "crossterm", "directories", + "flate2", "futures", "indexmap", "indicatif", @@ -7535,6 +7536,7 @@ dependencies = [ "serde", "serde_json", "serial_test", + "tar", "tempfile", "thiserror 2.0.18", "tokio", diff --git a/crates/vite_global_cli/Cargo.toml b/crates/vite_global_cli/Cargo.toml index ab914d5911..656558b306 100644 --- a/crates/vite_global_cli/Cargo.toml +++ b/crates/vite_global_cli/Cargo.toml @@ -17,10 +17,12 @@ clap = { workspace = true, features = ["derive"] } clap_complete = { workspace = true, features = ["unstable-dynamic"] } directories = { workspace = true } futures = { workspace = true } +flate2 = { workspace = true } serde = { workspace = true } serde_json = { workspace = true } node-semver = { workspace = true } thiserror = { workspace = true } +tar = { workspace = true } tokio = { workspace = true, features = ["full"] } tracing = { workspace = true } owo-colors = { workspace = true } diff --git a/crates/vite_global_cli/src/cli.rs b/crates/vite_global_cli/src/cli.rs index a0f4e0abfa..741c3e9a9a 100644 --- a/crates/vite_global_cli/src/cli.rs +++ b/crates/vite_global_cli/src/cli.rs @@ -671,7 +671,8 @@ async fn managed_update( continue; } - let (package_name, _) = global::parse_package_spec(package); + // It is not a local package, so `parse_package_spec` there won't return `Err()` + let (package_name, _) = global::parse_package_spec(package).unwrap(); if PackageMetadata::load(&package_name).await?.is_some() { managed_specs.push(package.clone()); } else { diff --git a/crates/vite_global_cli/src/commands/global/install.rs b/crates/vite_global_cli/src/commands/global/install.rs index b28bdc39e2..aa8a6639e8 100644 --- a/crates/vite_global_cli/src/commands/global/install.rs +++ b/crates/vite_global_cli/src/commands/global/install.rs @@ -26,7 +26,7 @@ use crate::{ }, package_metadata::PackageMetadata, }, - global::{CORE_SHIMS, parse_package_spec}, + global::{CORE_SHIMS, is_local_package_spec, parse_package_spec}, }, error::Error, }; @@ -105,7 +105,11 @@ pub async fn install( let mut packages = IndexMap::::new(); for package_spec in package_specs { // Parse package spec (e.g., "typescript", "typescript@5.0.0", "@scope/pkg") - let (package_name, _version_spec) = parse_package_spec(package_spec); + + let (package_name, _version_spec) = match parse_package_spec(package_spec) { + Ok(result) => result, + Err(error) => return Err((Some(package_spec.clone()), error)), + }; packages.insert(package_name, Package { spec: package_spec, staging_dir: None }); } let packages_count = packages.len(); @@ -395,7 +399,18 @@ async fn install_one( /// 1. Try to use PackageMetadata for binary list /// 2. Fallback to scanning BinConfig files for orphaned binaries pub async fn uninstall(package_name: &str, dry_run: bool) -> Result<(), Error> { - let (package_name, _) = parse_package_spec(package_name); + if is_local_package_spec(package_name) { + // We can't resolve local packages for uninstall, follow npm's behavior + return Err(Error::ConfigError( + format!( + "Local path {} can't be resolved, please enter a package name instead", + package_name + ) + .into(), + )); + } + + let (package_name, _) = parse_package_spec(package_name).unwrap(); // Phase 1: Try to use PackageMetadata for binary list let bins = if let Some(metadata) = PackageMetadata::load(&package_name).await? { @@ -881,28 +896,28 @@ mod tests { #[test] fn test_parse_package_spec_simple() { - let (name, version) = parse_package_spec("typescript"); + let (name, version) = parse_package_spec("typescript").unwrap(); assert_eq!(name, "typescript"); assert_eq!(version, None); } #[test] fn test_parse_package_spec_with_version() { - let (name, version) = parse_package_spec("typescript@5.0.0"); + let (name, version) = parse_package_spec("typescript@5.0.0").unwrap(); assert_eq!(name, "typescript"); assert_eq!(version, Some("5.0.0".to_string())); } #[test] fn test_parse_package_spec_scoped() { - let (name, version) = parse_package_spec("@types/node"); + let (name, version) = parse_package_spec("@types/node").unwrap(); assert_eq!(name, "@types/node"); assert_eq!(version, None); } #[test] fn test_parse_package_spec_scoped_with_version() { - let (name, version) = parse_package_spec("@types/node@20.0.0"); + let (name, version) = parse_package_spec("@types/node@20.0.0").unwrap(); assert_eq!(name, "@types/node"); assert_eq!(version, Some("20.0.0".to_string())); } diff --git a/crates/vite_global_cli/src/commands/global/mod.rs b/crates/vite_global_cli/src/commands/global/mod.rs index 4915a68d37..5d9234c131 100644 --- a/crates/vite_global_cli/src/commands/global/mod.rs +++ b/crates/vite_global_cli/src/commands/global/mod.rs @@ -1,9 +1,17 @@ //! Managed global package utilities. -use std::{collections::HashMap, io::IsTerminal, process::Stdio, time::Duration}; - +use std::{ + collections::HashMap, + fs::File, + io::{IsTerminal, Read}, + process::Stdio, + time::Duration, +}; + +use flate2::read::GzDecoder; use futures::{StreamExt, stream::FuturesUnordered}; use indicatif::{ProgressBar, ProgressDrawTarget, ProgressStyle}; +use tar::Archive; use tokio::process::Command; use vite_path::{AbsolutePathBuf, current_dir}; use vite_shared::format_path_prepended; @@ -48,23 +56,34 @@ impl NpmRegistry { } async fn latest_package_version(&self, package_spec: &str) -> Result { - let output = Command::new(self.npm_path.as_path()) - .args(["view", package_spec, "version", "--json"]) - .env("PATH", format_path_prepended(self.node_bin_dir.as_path())) - .stdout(Stdio::piped()) - .stderr(Stdio::piped()) - .output() - .await?; - - if !output.status.success() { - let stderr = String::from_utf8_lossy(&output.stderr).trim().to_string(); - return Err(Error::ConfigError( - format!("npm view failed for {package_spec}: {stderr}").into(), - )); - } + let output = npm_view(&self.npm_path, &self.node_bin_dir, package_spec, "version").await?; + + parse_npm_view_version(&output) + } +} + +async fn npm_view( + npm_path: &AbsolutePathBuf, + node_bin_dir: &AbsolutePathBuf, + package_spec: &str, + field: &str, +) -> Result, Error> { + let output = Command::new(npm_path.as_path()) + .args(["view", package_spec, field, "--json"]) + .env("PATH", format_path_prepended(node_bin_dir.as_path())) + .stdout(Stdio::piped()) + .stderr(Stdio::piped()) + .output() + .await?; - parse_npm_view_version(&output.stdout) + if !output.status.success() { + let stderr = String::from_utf8_lossy(&output.stderr).trim().to_string(); + return Err(Error::ConfigError( + format!("npm view failed for {package_spec}: {stderr}").into(), + )); } + + Ok(output.stdout) } pub(crate) async fn latest_package_versions( @@ -133,20 +152,117 @@ pub(crate) fn is_local_package_spec(spec: &str) -> bool { } /// Parse package spec into name and optional version. -pub(crate) fn parse_package_spec(spec: &str) -> (String, Option) { - if spec.starts_with('@') { - if let Some(idx) = spec[1..].find('@') { - let idx = idx + 1; - return (spec[..idx].to_string(), Some(spec[idx + 1..].to_string())); +/// For local packages, read package.json from a directory or package tarball. +/// +/// It will never return an `Err()` if it is not a local package +pub(crate) fn parse_package_spec(spec: &str) -> Result<(String, Option), Error> { + if is_local_package_spec(spec) { + let package_json = read_local_package_json(spec)?; + let Some(package_name) = package_json.get("name").and_then(|name| name.as_str()) else { + return Err(Error::ConfigError( + format!("Local package {spec} must have a string name in package.json").into(), + )); + }; + + Ok((package_name.to_string(), None)) + } else { + if spec.starts_with('@') { + if let Some(idx) = spec[1..].find('@') { + let idx = idx + 1; + return Ok((spec[..idx].to_string(), Some(spec[idx + 1..].to_string()))); + } + return Ok((spec.to_string(), None)); } - return (spec.to_string(), None); + + if let Some(idx) = spec.find('@') { + return Ok((spec[..idx].to_string(), Some(spec[idx + 1..].to_string()))); + } + + Ok((spec.to_string(), None)) } +} - if let Some(idx) = spec.find('@') { - return (spec[..idx].to_string(), Some(spec[idx + 1..].to_string())); +fn resolve_local_package_path(spec: &str) -> Result { + let path_spec = spec.strip_prefix("file:").unwrap_or(spec); + let path = std::path::Path::new(path_spec); + if path.is_absolute() { + AbsolutePathBuf::new(path.to_path_buf()) + .ok_or_else(|| Error::ConfigError(format!("Invalid local package path {spec}").into())) + } else { + Ok(current_dir() + .map_err(|error| { + Error::ConfigError(format!("Cannot get current directory: {error}").into()) + })? + .join(path)) + } +} + +fn read_local_package_json(spec: &str) -> Result { + let package_path = resolve_local_package_path(spec)?; + if package_path.as_path().is_file() && is_package_tarball(package_path.as_path()) { + return read_package_json_from_tarball(spec, &package_path); + } + + let package_json_path = package_path.join("package.json"); + let package_json_content = + std::fs::read_to_string(package_json_path.as_path()).map_err(|error| { + Error::ConfigError( + format!( + "Failed to read package.json for local package {spec} at {}: {error}", + package_json_path.as_path().display() + ) + .into(), + ) + })?; + serde_json::from_str(&package_json_content).map_err(Error::JsonError) +} + +fn is_package_tarball(path: &std::path::Path) -> bool { + let path = path.to_string_lossy(); + path.ends_with(".tgz") || path.ends_with(".tar.gz") +} + +fn read_package_json_from_tarball( + spec: &str, + package_path: &AbsolutePathBuf, +) -> Result { + let file = File::open(package_path.as_path()).map_err(|error| { + Error::ConfigError( + format!( + "Failed to read package tarball {spec} at {}: {error}", + package_path.as_path().display() + ) + .into(), + ) + })?; + let decoder = GzDecoder::new(file); + let mut archive = Archive::new(decoder); + + for entry in archive.entries().map_err(|error| { + Error::ConfigError(format!("Failed to read package tarball {spec}: {error}").into()) + })? { + let mut entry = entry.map_err(|error| { + Error::ConfigError(format!("Failed to read package tarball {spec}: {error}").into()) + })?; + let path = entry.path().map_err(|error| { + Error::ConfigError(format!("Failed to read package tarball {spec}: {error}").into()) + })?; + if path.as_ref() != std::path::Path::new("package/package.json") { + continue; + } + + let mut package_json_content = String::new(); + entry.read_to_string(&mut package_json_content).map_err(|error| { + Error::ConfigError( + format!("Failed to read package.json from package tarball {spec}: {error}").into(), + ) + })?; + return serde_json::from_str(&package_json_content).map_err(Error::JsonError); } - (spec.to_string(), None) + Err(Error::ConfigError( + format!("Package tarball {spec} must contain package/package.json").into(), + )) } fn parse_npm_view_version(stdout: &[u8]) -> Result { diff --git a/crates/vite_global_cli/src/commands/global/outdated.rs b/crates/vite_global_cli/src/commands/global/outdated.rs index 233473caf0..e8b65d83a7 100644 --- a/crates/vite_global_cli/src/commands/global/outdated.rs +++ b/crates/vite_global_cli/src/commands/global/outdated.rs @@ -50,7 +50,10 @@ pub async fn get_outdated_packages( let installed = if !packages.is_empty() { let mut installed = Vec::new(); for package in packages { - let (package_name, _) = parse_package_spec(package); + let Ok((package_name, _)) = parse_package_spec(package) else { + // Silently skip, follow npm's behavior + continue; + }; if let Some(metadata) = PackageMetadata::load(&package_name).await? { installed.push((metadata, Some(package.clone()))); } diff --git a/packages/cli/snap-tests-global/command-env-install-conflict/snap.txt b/packages/cli/snap-tests-global/command-env-install-conflict/snap.txt index dd89567f74..200704587c 100644 --- a/packages/cli/snap-tests-global/command-env-install-conflict/snap.txt +++ b/packages/cli/snap-tests-global/command-env-install-conflict/snap.txt @@ -1,7 +1,7 @@ > vp install -g ./conflict-pkg # Install package with conflicting binary name (uses cwd version) info: Installing 1 global package with Node.js -warn: Package './conflict-pkg' provides 'node' binary, but it conflicts with a core shim. Skipping. -✓ Installed ./conflict-pkg +warn: Package 'conflict-pkg' provides 'node' binary, but it conflicts with a core shim. Skipping. +✓ Installed conflict-pkg Bins: conflict-cli, node > vp remove -g conflict-pkg # Cleanup @@ -9,8 +9,8 @@ Uninstalled conflict-pkg > vp install -g --node 20 ./conflict-pkg # Install with specific Node.js version info: Installing 1 global package with Node.js -warn: Package './conflict-pkg' provides 'node' binary, but it conflicts with a core shim. Skipping. -✓ Installed ./conflict-pkg +warn: Package 'conflict-pkg' provides 'node' binary, but it conflicts with a core shim. Skipping. +✓ Installed conflict-pkg Bins: conflict-cli, node > vp remove -g conflict-pkg # Cleanup diff --git a/packages/cli/snap-tests-global/command-env-install-global-local/another-package.tgz b/packages/cli/snap-tests-global/command-env-install-global-local/another-package.tgz new file mode 100644 index 0000000000..306df43273 Binary files /dev/null and b/packages/cli/snap-tests-global/command-env-install-global-local/another-package.tgz differ diff --git a/packages/cli/snap-tests-global/command-env-install-global-local/bin.js b/packages/cli/snap-tests-global/command-env-install-global-local/bin.js new file mode 100644 index 0000000000..09a50e9911 --- /dev/null +++ b/packages/cli/snap-tests-global/command-env-install-global-local/bin.js @@ -0,0 +1 @@ +console.log('The package is installed successfully'); diff --git a/packages/cli/snap-tests-global/command-env-install-global-local/package.json b/packages/cli/snap-tests-global/command-env-install-global-local/package.json new file mode 100644 index 0000000000..ce66fe0be3 --- /dev/null +++ b/packages/cli/snap-tests-global/command-env-install-global-local/package.json @@ -0,0 +1,7 @@ +{ + "name": "just-a-normal-package", + "version": "0.0.0", + "bin": { + "just-a-normal-package": "./bin.js" + } +} diff --git a/packages/cli/snap-tests-global/command-env-install-global-local/snap.txt b/packages/cli/snap-tests-global/command-env-install-global-local/snap.txt new file mode 100644 index 0000000000..45da4b38d4 --- /dev/null +++ b/packages/cli/snap-tests-global/command-env-install-global-local/snap.txt @@ -0,0 +1,19 @@ +> vp install -g . +info: Installing 1 global package with Node.js +✓ Installed just-a-normal-package + Bins: just-a-normal-package + +> vp install -g ./another-package.tgz +info: Installing 1 global package with Node.js +✓ Installed another-normal-package + Bins: another-normal-package + +> vp list -g just-a-normal-package +Package Node version Binaries +--- --- --- +just-a-normal-package@ just-a-normal-package + +> vp list -g another-normal-package +Package Node version Binaries +--- --- --- +another-normal-package@ another-normal-package diff --git a/packages/cli/snap-tests-global/command-env-install-global-local/steps.json b/packages/cli/snap-tests-global/command-env-install-global-local/steps.json new file mode 100644 index 0000000000..4377b56a05 --- /dev/null +++ b/packages/cli/snap-tests-global/command-env-install-global-local/steps.json @@ -0,0 +1,9 @@ +{ + "commands": [ + "vp install -g .", + "vp install -g ./another-package.tgz", + "vp list -g just-a-normal-package", + "vp list -g another-normal-package" + ], + "after": ["vp remove -g just-a-normal-package another-normal-package"] +} diff --git a/packages/cli/snap-tests-global/command-env-install-node-version/snap.txt b/packages/cli/snap-tests-global/command-env-install-node-version/snap.txt index 40f1c040a8..a24c129abd 100644 --- a/packages/cli/snap-tests-global/command-env-install-node-version/snap.txt +++ b/packages/cli/snap-tests-global/command-env-install-node-version/snap.txt @@ -1,6 +1,6 @@ > vp install -g --node 22 ./command-env-install-node-version-pkg # Install with Node.js 22 info: Installing 1 global package with Node.js -✓ Installed ./command-env-install-node-version-pkg +✓ Installed command-env-install-node-version-pkg Bins: command-env-install-node-version-pkg-cli > cat $VP_HOME/bins/command-env-install-node-version-pkg-cli.json | node -e "const d=JSON.parse(require('fs').readFileSync(0,'utf8')); console.log('Node major:', d.nodeVersion.split('.')[0])" # Verify Node 22 @@ -11,7 +11,7 @@ Uninstalled command-env-install-node-version-pkg > vp install -g --node 20 ./command-env-install-node-version-pkg # Install with Node.js 20 info: Installing 1 global package with Node.js -✓ Installed ./command-env-install-node-version-pkg +✓ Installed command-env-install-node-version-pkg Bins: command-env-install-node-version-pkg-cli > cat $VP_HOME/bins/command-env-install-node-version-pkg-cli.json | node -e "const d=JSON.parse(require('fs').readFileSync(0,'utf8')); console.log('Node major:', d.nodeVersion.split('.')[0])" # Verify Node 20 diff --git a/packages/cli/snap-tests-global/command-env-install-parallel/snap.txt b/packages/cli/snap-tests-global/command-env-install-parallel/snap.txt index 721dd1d80b..4dcf1fbef2 100644 --- a/packages/cli/snap-tests-global/command-env-install-parallel/snap.txt +++ b/packages/cli/snap-tests-global/command-env-install-parallel/snap.txt @@ -1,9 +1,9 @@ > vp install -g --concurrency 1 ./parallel-pkg-a ./parallel-pkg-b # Install multiple global packages info: Installing 2 global packages with Node.js -✓ Installed ./parallel-pkg-a +✓ Installed parallel-pkg-a Bins: parallel-a -✓ Installed ./parallel-pkg-b +✓ Installed parallel-pkg-b Bins: parallel-b > parallel-a && parallel-b # Both binaries should be callable diff --git a/packages/cli/snap-tests-global/command-env-install-version-alias/snap.txt b/packages/cli/snap-tests-global/command-env-install-version-alias/snap.txt index 58510ae5c6..c8152d1d73 100644 --- a/packages/cli/snap-tests-global/command-env-install-version-alias/snap.txt +++ b/packages/cli/snap-tests-global/command-env-install-version-alias/snap.txt @@ -1,6 +1,6 @@ > vp install -g --node lts ./command-env-install-version-alias-pkg # Install with LTS alias info: Installing 1 global package with Node.js -✓ Installed ./command-env-install-version-alias-pkg +✓ Installed command-env-install-version-alias-pkg Bins: command-env-install-version-alias-pkg-cli > cat $VP_HOME/bins/command-env-install-version-alias-pkg-cli.json | node -e "const d=JSON.parse(require('fs').readFileSync(0,'utf8')); const v=parseInt(d.nodeVersion.split('.')[0]); console.log('LTS major >= 20:', v >= 20)" # Verify LTS version @@ -11,7 +11,7 @@ Uninstalled command-env-install-version-alias-pkg > vp install -g --node latest ./command-env-install-version-alias-pkg # Install with latest alias info: Installing 1 global package with Node.js -✓ Installed ./command-env-install-version-alias-pkg +✓ Installed command-env-install-version-alias-pkg Bins: command-env-install-version-alias-pkg-cli > cat $VP_HOME/bins/command-env-install-version-alias-pkg-cli.json | node -e "const d=JSON.parse(require('fs').readFileSync(0,'utf8')); const v=parseInt(d.nodeVersion.split('.')[0]); console.log('Latest major >= 20:', v >= 20)" # Verify latest version diff --git a/packages/cli/snap-tests-global/env-install-binary-conflict/snap.txt b/packages/cli/snap-tests-global/env-install-binary-conflict/snap.txt index 185390d749..3355ed668a 100644 --- a/packages/cli/snap-tests-global/env-install-binary-conflict/snap.txt +++ b/packages/cli/snap-tests-global/env-install-binary-conflict/snap.txt @@ -1,41 +1,41 @@ > vp install -g ./env-binary-conflict-pkg-a # Install pkg-a which provides env-binary-conflict-cli binary info: Installing 1 global package with Node.js -✓ Installed ./env-binary-conflict-pkg-a +✓ Installed env-binary-conflict-pkg-a Bins: env-binary-conflict-cli > cat $VP_HOME/bins/env-binary-conflict-cli.json # Bin config should point to pkg-a { "name": "env-binary-conflict-cli", - "package": "./env-binary-conflict-pkg-a", + "package": "env-binary-conflict-pkg-a", "version": "1.0.0", "nodeVersion": "22.22.0", "source": "vp" } [1]> vp install -g ./env-binary-conflict-pkg-b # Try to install pkg-b without force - should fail info: Installing 1 global package with Node.js -error: Failed to install ./env-binary-conflict-pkg-b: Executable 'env-binary-conflict-cli' is already installed by ./env-binary-conflict-pkg-a +error: Failed to install env-binary-conflict-pkg-b: Executable 'env-binary-conflict-cli' is already installed by env-binary-conflict-pkg-a -Please remove ./env-binary-conflict-pkg-a before installing ./env-binary-conflict-pkg-b, or use --force to auto-replace +Please remove env-binary-conflict-pkg-a before installing env-binary-conflict-pkg-b, or use --force to auto-replace > cat $VP_HOME/bins/env-binary-conflict-cli.json # Bin config should still point to pkg-a { "name": "env-binary-conflict-cli", - "package": "./env-binary-conflict-pkg-a", + "package": "env-binary-conflict-pkg-a", "version": "1.0.0", "nodeVersion": "22.22.0", "source": "vp" } > vp install -g --force ./env-binary-conflict-pkg-b # Force install pkg-b - should auto-uninstall pkg-a info: Installing 1 global package with Node.js -Uninstalling ./env-binary-conflict-pkg-a (conflicts with ./env-binary-conflict-pkg-b)... -Uninstalled ./env-binary-conflict-pkg-a -✓ Installed ./env-binary-conflict-pkg-b +Uninstalling env-binary-conflict-pkg-a (conflicts with env-binary-conflict-pkg-b)... +Uninstalled env-binary-conflict-pkg-a +✓ Installed env-binary-conflict-pkg-b Bins: env-binary-conflict-cli > cat $VP_HOME/bins/env-binary-conflict-cli.json # Bin config should now point to pkg-b { "name": "env-binary-conflict-cli", - "package": "./env-binary-conflict-pkg-b", + "package": "env-binary-conflict-pkg-b", "version": "2.0.0", "nodeVersion": "22.22.0", "source": "vp" diff --git a/packages/cli/snap-tests-global/npm-global-install-already-linked/snap.txt b/packages/cli/snap-tests-global/npm-global-install-already-linked/snap.txt index 9650a8d433..57a939d2c4 100644 --- a/packages/cli/snap-tests-global/npm-global-install-already-linked/snap.txt +++ b/packages/cli/snap-tests-global/npm-global-install-already-linked/snap.txt @@ -3,7 +3,7 @@ > vp install -g ./npm-global-linked-pkg # First install via vp (creates managed shim) info: Installing 1 global package with Node.js -✓ Installed ./npm-global-linked-pkg +✓ Installed npm-global-linked-pkg Bins: npm-global-linked-cli > npm-global-linked-cli # Should be callable via the link @@ -12,7 +12,7 @@ npm-global-linked-cli works > npm install -g ./npm-global-linked-pkg # Should NOT show hint (binary already exists) added 1 package in ms -Skipped 'npm-global-linked-cli': managed by `vp install -g ./npm-global-linked-pkg`. Run `vp uninstall -g ./npm-global-linked-pkg` to remove it first. +Skipped 'npm-global-linked-cli': managed by `vp install -g npm-global-linked-pkg`. Run `vp uninstall -g npm-global-linked-pkg` to remove it first. > vp remove -g npm-global-linked-pkg # Cleanup Uninstalled npm-global-linked-pkg diff --git a/packages/cli/snap-tests-global/npm-global-uninstall-vp-managed/snap.txt b/packages/cli/snap-tests-global/npm-global-uninstall-vp-managed/snap.txt index 6d08f8a9a5..6fe653db93 100644 --- a/packages/cli/snap-tests-global/npm-global-uninstall-vp-managed/snap.txt +++ b/packages/cli/snap-tests-global/npm-global-uninstall-vp-managed/snap.txt @@ -1,12 +1,12 @@ > vp install -g ./npm-global-vp-managed-pkg # Install via vp (creates managed shim) info: Installing 1 global package with Node.js -✓ Installed ./npm-global-vp-managed-pkg +✓ Installed npm-global-vp-managed-pkg Bins: npm-global-vp-managed-cli > npm install -g ./npm-global-vp-managed-pkg # npm install (should warn about conflict) added 1 package in ms -Skipped 'npm-global-vp-managed-cli': managed by `vp install -g ./npm-global-vp-managed-pkg`. Run `vp uninstall -g ./npm-global-vp-managed-pkg` to remove it first. +Skipped 'npm-global-vp-managed-cli': managed by `vp install -g npm-global-vp-managed-pkg`. Run `vp uninstall -g npm-global-vp-managed-pkg` to remove it first. > npm uninstall -g npm-global-vp-managed-pkg # npm uninstall should NOT remove the vp-managed shim diff --git a/packages/cli/snap-tests-global/shim-recursive-package-binary/snap.txt b/packages/cli/snap-tests-global/shim-recursive-package-binary/snap.txt index a8a56719e0..8744528a8a 100644 --- a/packages/cli/snap-tests-global/shim-recursive-package-binary/snap.txt +++ b/packages/cli/snap-tests-global/shim-recursive-package-binary/snap.txt @@ -1,6 +1,6 @@ > vp install -g ./recursive-cli-pkg # Install test package info: Installing 1 global package with Node.js -✓ Installed ./recursive-cli-pkg +✓ Installed recursive-cli-pkg Bins: recursive-cli > recursive-cli # Outer call triggers recursive inner call through shim