5
5
@preconcurrency import class Foundation. FileManager
6
6
@preconcurrency import struct Foundation. URL
7
7
@preconcurrency import struct Foundation. Data
8
+ @preconcurrency import struct Foundation. ObjCBool
8
9
@preconcurrency import func Foundation. kill
9
10
@preconcurrency import var Foundation. SIGINT
10
11
@preconcurrency import var Foundation. SIGTERM
11
12
import protocol Dispatch. DispatchSourceSignal
12
13
import class Dispatch. DispatchSource
13
14
14
15
internal func which( _ executable: String ) throws -> URL {
16
+ func checkCandidate( _ candidate: URL ) -> Bool {
17
+ var isDirectory : ObjCBool = false
18
+ let fileExists = FileManager . default. fileExists ( atPath: candidate. path, isDirectory: & isDirectory)
19
+ return fileExists && !isDirectory. boolValue && FileManager . default. isExecutableFile ( atPath: candidate. path)
20
+ }
15
21
do {
16
22
// Check overriding environment variable
17
23
let envVariable = executable. uppercased ( ) . replacingOccurrences ( of: " - " , with: " _ " ) + " _PATH "
18
24
if let path = ProcessInfo . processInfo. environment [ envVariable] {
19
25
let url = URL ( fileURLWithPath: path) . appendingPathComponent ( executable)
20
- if FileManager . default . isExecutableFile ( atPath : url. path ) {
26
+ if checkCandidate ( url) {
21
27
return url
22
28
}
23
29
}
@@ -31,7 +37,7 @@ internal func which(_ executable: String) throws -> URL {
31
37
let paths = ProcessInfo . processInfo. environment [ " PATH " ] !. split ( separator: pathSeparator)
32
38
for path in paths {
33
39
let url = URL ( fileURLWithPath: String ( path) ) . appendingPathComponent ( executable)
34
- if FileManager . default . isExecutableFile ( atPath : url. path ) {
40
+ if checkCandidate ( url) {
35
41
return url
36
42
}
37
43
}
0 commit comments