22import { spawn } from "node:child_process" ;
33import { accessSync , closeSync , constants , openSync , readSync , statSync } from "node:fs" ;
44import path from "node:path" ;
5- import { buildCmdExeCommandLine } from "./windows-cmd-helpers.mjs" ;
5+ import { buildCmdExeCommandLine , resolvePathEnvKey } from "./windows-cmd-helpers.mjs" ;
66
77function getPortableBasename ( value ) {
88 return value . split ( / [ / \\ ] / ) . at ( - 1 ) ?? value ;
@@ -55,22 +55,47 @@ function isFile(value) {
5555 }
5656}
5757
58- function findExecutableOnPath ( command , envPath ) {
58+ function findExecutableOnPath ( command , envPath , platform , env , cwd ) {
5959 if ( typeof envPath !== "string" || envPath . length === 0 ) {
6060 return null ;
6161 }
62- for ( const directory of envPath . split ( path . delimiter ) ) {
62+ const extensions =
63+ platform === "win32"
64+ ? ( env [ Object . keys ( env ) . find ( ( key ) => key . toLowerCase ( ) === "pathext" ) ?? "PATHEXT" ] ??
65+ ".COM;.EXE;.BAT;.CMD" )
66+ . split ( ";" )
67+ . filter ( Boolean )
68+ . map ( ( extension ) => extension . toLowerCase ( ) )
69+ : [ "" ] ;
70+ const pathDelimiter = platform === "win32" ? ";" : path . delimiter ;
71+ for ( const directory of envPath . split ( pathDelimiter ) ) {
6372 if ( ! directory ) {
6473 continue ;
6574 }
66- const candidate = path . join ( directory , command ) ;
67- if ( isExecutableFile ( candidate ) ) {
68- return candidate ;
75+ const resolvedDirectory = path . isAbsolute ( directory ) ? directory : path . resolve ( cwd , directory ) ;
76+ for ( const extension of extensions ) {
77+ const candidate = path . join ( resolvedDirectory , `${ command } ${ extension } ` ) ;
78+ if ( ( platform === "win32" ? isFile ( candidate ) : isExecutableFile ( candidate ) ) ) {
79+ return candidate ;
80+ }
6981 }
7082 }
7183 return null ;
7284}
7385
86+ function createWindowsRunner ( command , args , comSpec ) {
87+ const extension = getPortableExtension ( command ) ;
88+ if ( extension === ".cmd" || extension === ".bat" ) {
89+ return {
90+ command : comSpec ,
91+ args : [ "/d" , "/s" , "/c" , buildCmdExeCommandLine ( command , args ) ] ,
92+ shell : false ,
93+ windowsVerbatimArguments : true ,
94+ } ;
95+ }
96+ return { command, args, shell : false } ;
97+ }
98+
7499function isNodeRunnablePnpmExecPath ( value ) {
75100 if ( ! isPnpmExecPath ( value ) ) {
76101 return false ;
@@ -95,7 +120,9 @@ export function resolvePnpmRunner(params = {}) {
95120 const nodeExecPath = params . nodeExecPath ?? process . execPath ;
96121 const platform = params . platform ?? process . platform ;
97122 const comSpec = params . comSpec ?? process . env . ComSpec ?? "cmd.exe" ;
98- const envPath = params . env ?. PATH ?? process . env . PATH ;
123+ const env = params . env ?? process . env ;
124+ const envPath = env [ platform === "win32" ? resolvePathEnvKey ( env ) : "PATH" ] ;
125+ const cwd = params . cwd ?? process . cwd ( ) ;
99126
100127 if ( typeof npmExecPath === "string" && npmExecPath . length > 0 && isPnpmExecPath ( npmExecPath ) ) {
101128 if ( isNodeRunnablePnpmExecPath ( npmExecPath ) ) {
@@ -131,30 +158,22 @@ export function resolvePnpmRunner(params = {}) {
131158 }
132159 }
133160
134- if ( platform === "win32" ) {
135- return {
136- command : comSpec ,
137- args : [ "/d" , "/s" , "/c" , buildCmdExeCommandLine ( "pnpm.cmd" , pnpmArgs ) ] ,
138- shell : false ,
139- windowsVerbatimArguments : true ,
140- } ;
141- }
142-
143- const pnpmPath = findExecutableOnPath ( "pnpm" , envPath ) ;
161+ const pnpmPath = findExecutableOnPath ( "pnpm" , envPath , platform , env , cwd ) ;
144162 if ( pnpmPath ) {
145- return {
146- command : pnpmPath ,
147- args : pnpmArgs ,
148- shell : false ,
149- } ;
163+ return platform === "win32"
164+ ? createWindowsRunner ( pnpmPath , pnpmArgs , comSpec )
165+ : { command : pnpmPath , args : pnpmArgs , shell : false } ;
150166 }
151- const corepackPath = findExecutableOnPath ( "corepack" , envPath ) ;
167+ const corepackPath = findExecutableOnPath ( "corepack" , envPath , platform , env , cwd ) ;
152168 if ( corepackPath ) {
153- return {
154- command : corepackPath ,
155- args : [ "pnpm" , ...pnpmArgs ] ,
156- shell : false ,
157- } ;
169+ const args = [ "pnpm" , ...pnpmArgs ] ;
170+ return platform === "win32"
171+ ? createWindowsRunner ( corepackPath , args , comSpec )
172+ : { command : corepackPath , args, shell : false } ;
173+ }
174+
175+ if ( platform === "win32" ) {
176+ return createWindowsRunner ( "pnpm.cmd" , pnpmArgs , comSpec ) ;
158177 }
159178
160179 return {
0 commit comments