@@ -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
383389where
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
390403fn 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