@@ -315,20 +315,29 @@ public final class Process: ObjectIdentifierProtocol {
315315 /// Returns the path of the the given program if found in the search paths.
316316 ///
317317 /// The program can be executable name, relative path or absolute path.
318- public static func findExecutable( _ program: String ) -> AbsolutePath ? {
318+ public static func findExecutable(
319+ _ program: String ,
320+ workingDirectory: AbsolutePath ? = nil
321+ ) -> AbsolutePath ? {
319322 return Process . executablesQueue. sync {
320323 // Check if we already have a value for the program.
321324 if let value = Process . validatedExecutablesMap [ program] {
322325 return value
323326 }
327+
328+ let cwd = workingDirectory ?? localFileSystem. currentWorkingDirectory
329+
324330 // FIXME: This can be cached.
325331 let envSearchPaths = getEnvSearchPaths (
326332 pathString: ProcessEnv . path,
327- currentWorkingDirectory: localFileSystem . currentWorkingDirectory
333+ currentWorkingDirectory: cwd
328334 )
329335 // Lookup and cache the executable path.
330336 let value = lookupExecutablePath (
331- filename: program, searchPaths: envSearchPaths)
337+ filename: program,
338+ currentWorkingDirectory: cwd,
339+ searchPaths: envSearchPaths
340+ )
332341 Process . validatedExecutablesMap [ program] = value
333342 return value
334343 }
@@ -350,7 +359,7 @@ public final class Process: ObjectIdentifierProtocol {
350359
351360 // Look for executable.
352361 let executable = arguments [ 0 ]
353- guard let executablePath = Process . findExecutable ( executable) else {
362+ guard let executablePath = Process . findExecutable ( executable, workingDirectory : workingDirectory ) else {
354363 throw Process . Error. missingExecutableProgram ( program: executable)
355364 }
356365
@@ -495,7 +504,11 @@ public final class Process: ObjectIdentifierProtocol {
495504 posix_spawn_file_actions_adddup2 ( & fileActions, 2 , 2 )
496505 }
497506
498- let argv = CStringArray ( arguments)
507+ var resolvedArgs = arguments
508+ if workingDirectory != nil {
509+ resolvedArgs [ 0 ] = executablePath. pathString
510+ }
511+ let argv = CStringArray ( resolvedArgs)
499512 let env = CStringArray ( environment. map ( { " \( $0. 0 ) = \( $0. 1 ) " } ) )
500513 let rv = posix_spawnp ( & processID, argv. cArray [ 0 ] !, & fileActions, & attributes, argv. cArray, env. cArray)
501514
0 commit comments