Skip to content

Commit ef57ea7

Browse files
committed
Don't intercept npm commands with prefix flag
1 parent 7eb56c3 commit ef57ea7

File tree

1 file changed

+63
-7
lines changed

1 file changed

+63
-7
lines changed

crates/volta-core/src/run/parser.rs

Lines changed: 63 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ impl<'a> CommandArg<'a> {
5151
// then we treat the command not a global and allow npm to handle any error messages.
5252
match positionals.next() {
5353
Some(cmd) if NPM_INSTALL_ALIASES.iter().any(|a| a == &cmd) => {
54-
if has_global_flag(args) {
54+
if has_global_without_prefix(args) {
5555
let tools: Vec<_> = positionals.collect();
5656

5757
if tools.is_empty() {
@@ -72,7 +72,7 @@ impl<'a> CommandArg<'a> {
7272
}
7373
}
7474
Some(cmd) if NPM_UNINSTALL_ALIASES.iter().any(|a| a == &cmd) => {
75-
if has_global_flag(args) {
75+
if has_global_without_prefix(args) {
7676
let tools: Vec<_> = positionals.collect();
7777

7878
if tools.is_empty() {
@@ -90,7 +90,7 @@ impl<'a> CommandArg<'a> {
9090
if tools.is_empty() {
9191
// `npm unlink` without any arguments is used to unlink the current project
9292
CommandArg::Intercepted(InterceptedCommand::Unlink)
93-
} else if has_global_flag(args) {
93+
} else if has_global_without_prefix(args) {
9494
// With arguments, `npm unlink` is an alias of `npm remove`
9595
CommandArg::Global(GlobalCommand::Uninstall(UninstallArgs { tools }))
9696
} else {
@@ -106,7 +106,7 @@ impl<'a> CommandArg<'a> {
106106
CommandArg::Intercepted(InterceptedCommand::Link(LinkArgs { common_args, tools }))
107107
}
108108
Some(cmd) if NPM_UPDATE_ALIASES.iter().any(|a| a == &cmd) => {
109-
if has_global_flag(args) {
109+
if has_global_without_prefix(args) {
110110
// Once again, the common args are the command combined with any flags
111111
let mut common_args = vec![cmd];
112112
common_args.extend(args.iter().filter(is_flag).map(AsRef::as_ref));
@@ -379,12 +379,25 @@ impl<'a> LinkArgs<'a> {
379379
}
380380
}
381381

382-
fn has_global_flag<A>(args: &[A]) -> bool
382+
/// Check if the provided argument list includes a global flag and _doesn't_ have a prefix setting
383+
///
384+
/// For our interception, we only want to intercept global commands. Additionally, if the user
385+
/// passes a prefix setting, that will override the logic we use to redirect the install, so our
386+
/// process won't work and will cause an error. We should avoid intercepting in those cases since
387+
/// a command with an explicit prefix is something beyond the "standard" global install anyway.
388+
fn has_global_without_prefix<A>(args: &[A]) -> bool
383389
where
384390
A: AsRef<OsStr>,
385391
{
386-
args.iter()
387-
.any(|arg| arg.as_ref() == "-g" || arg.as_ref() == "--global")
392+
let (has_global, has_prefix) = args.iter().fold((false, false), |(global, prefix), arg| {
393+
match arg.as_ref().to_str() {
394+
Some("-g") | Some("--global") => (true, prefix),
395+
Some(pre) if pre.starts_with("--prefix") => (global, true),
396+
_ => (global, prefix),
397+
}
398+
});
399+
400+
has_global && !has_prefix
388401
}
389402

390403
fn is_flag<A>(arg: &A) -> bool
@@ -685,6 +698,49 @@ mod tests {
685698
_ => panic!("Doesn't parse uninstall with extra flags as a global"),
686699
}
687700
}
701+
702+
#[test]
703+
fn skips_commands_with_prefix() {
704+
match CommandArg::for_npm(&arg_list(&["install", "-g", "--prefix", "~/", "ember"])) {
705+
CommandArg::Standard => {}
706+
_ => panic!("Parsed command with prefix as a global"),
707+
}
708+
709+
match CommandArg::for_npm(&arg_list(&["install", "-g", "--prefix=~/", "ember"])) {
710+
CommandArg::Standard => {}
711+
_ => panic!("Parsed command with prefix as a global"),
712+
}
713+
714+
match CommandArg::for_npm(&arg_list(&["uninstall", "-g", "--prefix", "~/", "ember"])) {
715+
CommandArg::Standard => {}
716+
_ => panic!("Parsed command with prefix as a global"),
717+
}
718+
719+
match CommandArg::for_npm(&arg_list(&["uninstall", "-g", "--prefix=~/", "ember"])) {
720+
CommandArg::Standard => {}
721+
_ => panic!("Parsed command with prefix as a global"),
722+
}
723+
724+
match CommandArg::for_npm(&arg_list(&["unlink", "-g", "--prefix", "~/", "ember"])) {
725+
CommandArg::Standard => {}
726+
_ => panic!("Parsed command with prefix as a global"),
727+
}
728+
729+
match CommandArg::for_npm(&arg_list(&["unlink", "-g", "--prefix=~/", "ember"])) {
730+
CommandArg::Standard => {}
731+
_ => panic!("Parsed command with prefix as a global"),
732+
}
733+
734+
match CommandArg::for_npm(&arg_list(&["update", "-g", "--prefix", "~/"])) {
735+
CommandArg::Standard => {}
736+
_ => panic!("Parsed command with prefix as a global"),
737+
}
738+
739+
match CommandArg::for_npm(&arg_list(&["update", "-g", "--prefix=~/"])) {
740+
CommandArg::Standard => {}
741+
_ => panic!("Parsed command with prefix as a global"),
742+
}
743+
}
688744
}
689745

690746
mod yarn {

0 commit comments

Comments
 (0)