Skip to content

Commit 56fc8a0

Browse files
committed
fix global install local path package names
1 parent 558a9c9 commit 56fc8a0

File tree

3 files changed

+65
-2
lines changed
  • crates/vite_global_cli/src/commands/env
  • packages/cli/snap-tests-global
    • npm-global-install-already-linked
    • npm-global-uninstall-vp-managed

3 files changed

+65
-2
lines changed

crates/vite_global_cli/src/commands/env/global_install.rs

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
use std::{
44
collections::HashSet,
55
io::{Read, Write},
6+
path::Path,
67
process::Stdio,
78
};
89

@@ -269,6 +270,10 @@ pub async fn uninstall(package_name: &str, dry_run: bool) -> Result<(), Error> {
269270

270271
/// Parse package spec into name and optional version.
271272
fn parse_package_spec(spec: &str) -> (String, Option<String>) {
273+
if is_local_path_spec(spec) {
274+
return (resolve_local_package_name(spec).unwrap_or_else(|| spec.to_string()), None);
275+
}
276+
272277
// Handle scoped packages: @scope/name@version
273278
if spec.starts_with('@') {
274279
// Find the second @ for version
@@ -287,6 +292,27 @@ fn parse_package_spec(spec: &str) -> (String, Option<String>) {
287292
(spec.to_string(), None)
288293
}
289294

295+
fn is_local_path_spec(spec: &str) -> bool {
296+
spec == "."
297+
|| spec == ".."
298+
|| spec.starts_with("./")
299+
|| spec.starts_with("../")
300+
|| spec.starts_with(".\\")
301+
|| spec.starts_with("..\\")
302+
|| Path::new(spec).is_absolute()
303+
}
304+
305+
fn resolve_local_package_name(spec: &str) -> Option<String> {
306+
let package_dir = if Path::new(spec).is_absolute() {
307+
Path::new(spec).to_path_buf()
308+
} else {
309+
std::env::current_dir().ok()?.join(spec)
310+
};
311+
let package_json = std::fs::read_to_string(package_dir.join("package.json")).ok()?;
312+
let json: serde_json::Value = serde_json::from_str(&package_json).ok()?;
313+
json.get("name").and_then(|value| value.as_str()).map(str::to_string)
314+
}
315+
290316
/// Binary info extracted from package.json.
291317
struct BinaryInfo {
292318
/// Binary name (the command users will run)
@@ -470,6 +496,22 @@ async fn remove_package_shim(
470496
mod tests {
471497
use super::*;
472498

499+
struct CurrentDirGuard(std::path::PathBuf);
500+
501+
impl CurrentDirGuard {
502+
fn change_to(path: &std::path::Path) -> Self {
503+
let previous = std::env::current_dir().unwrap();
504+
std::env::set_current_dir(path).unwrap();
505+
Self(previous)
506+
}
507+
}
508+
509+
impl Drop for CurrentDirGuard {
510+
fn drop(&mut self) {
511+
std::env::set_current_dir(&self.0).unwrap();
512+
}
513+
}
514+
473515
/// RAII guard that sets `VP_TRAMPOLINE_PATH` to a fake binary on creation
474516
/// and clears it on drop. Ensures cleanup even on test panics.
475517
#[cfg(windows)]
@@ -729,6 +771,27 @@ mod tests {
729771
assert_eq!(version, Some("20.0.0".to_string()));
730772
}
731773

774+
#[test]
775+
#[serial_test::serial]
776+
fn test_parse_package_spec_local_path_uses_package_name() {
777+
use tempfile::TempDir;
778+
779+
let temp_dir = TempDir::new().unwrap();
780+
let _cwd_guard = CurrentDirGuard::change_to(temp_dir.path());
781+
let package_dir = temp_dir.path().join("fixture-pkg");
782+
783+
std::fs::create_dir_all(&package_dir).unwrap();
784+
std::fs::write(
785+
package_dir.join("package.json"),
786+
r#"{ "name": "resolved-local-package", "version": "1.0.0" }"#,
787+
)
788+
.unwrap();
789+
790+
let (name, version) = parse_package_spec("./fixture-pkg");
791+
assert_eq!(name, "resolved-local-package");
792+
assert_eq!(version, None);
793+
}
794+
732795
#[test]
733796
fn test_is_javascript_binary_with_js_extension() {
734797
use tempfile::TempDir;

packages/cli/snap-tests-global/npm-global-install-already-linked/snap.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ npm-global-linked-cli works
1414
> npm install -g ./npm-global-linked-pkg # Should NOT show hint (binary already exists)
1515

1616
added 1 package in <variable>ms
17-
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.
17+
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.
1818

1919
> vp remove -g npm-global-linked-pkg # Cleanup
2020
Uninstalled npm-global-linked-pkg

packages/cli/snap-tests-global/npm-global-uninstall-vp-managed/snap.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ Binaries: npm-global-vp-managed-cli
88
> npm install -g ./npm-global-vp-managed-pkg # npm install (should warn about conflict)
99

1010
added 1 package in <variable>ms
11-
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.
11+
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.
1212

1313
> npm uninstall -g npm-global-vp-managed-pkg # npm uninstall should NOT remove the vp-managed shim
1414

0 commit comments

Comments
 (0)