From 2f1851751060ef1f733eacf6debe918652d3c230 Mon Sep 17 00:00:00 2001 From: Yuta Saito Date: Sat, 2 Aug 2025 20:51:13 +0900 Subject: [PATCH] Fix `which` not to return directories emsdk includes `node` directory but the `which` function returned it as a valid executable. --- Plugins/BridgeJS/Sources/TS2Skeleton/TS2Skeleton.swift | 10 ++++++++-- Plugins/PackageToJS/Sources/PackageToJS.swift | 9 +++++++-- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/Plugins/BridgeJS/Sources/TS2Skeleton/TS2Skeleton.swift b/Plugins/BridgeJS/Sources/TS2Skeleton/TS2Skeleton.swift index 46b58e01..262393c4 100644 --- a/Plugins/BridgeJS/Sources/TS2Skeleton/TS2Skeleton.swift +++ b/Plugins/BridgeJS/Sources/TS2Skeleton/TS2Skeleton.swift @@ -5,6 +5,7 @@ @preconcurrency import class Foundation.FileManager @preconcurrency import struct Foundation.URL @preconcurrency import struct Foundation.Data +@preconcurrency import struct Foundation.ObjCBool @preconcurrency import func Foundation.kill @preconcurrency import var Foundation.SIGINT @preconcurrency import var Foundation.SIGTERM @@ -12,12 +13,17 @@ import protocol Dispatch.DispatchSourceSignal import class Dispatch.DispatchSource internal func which(_ executable: String) throws -> URL { + func checkCandidate(_ candidate: URL) -> Bool { + var isDirectory: ObjCBool = false + let fileExists = FileManager.default.fileExists(atPath: candidate.path, isDirectory: &isDirectory) + return fileExists && !isDirectory.boolValue && FileManager.default.isExecutableFile(atPath: candidate.path) + } do { // Check overriding environment variable let envVariable = executable.uppercased().replacingOccurrences(of: "-", with: "_") + "_PATH" if let path = ProcessInfo.processInfo.environment[envVariable] { let url = URL(fileURLWithPath: path).appendingPathComponent(executable) - if FileManager.default.isExecutableFile(atPath: url.path) { + if checkCandidate(url) { return url } } @@ -31,7 +37,7 @@ internal func which(_ executable: String) throws -> URL { let paths = ProcessInfo.processInfo.environment["PATH"]!.split(separator: pathSeparator) for path in paths { let url = URL(fileURLWithPath: String(path)).appendingPathComponent(executable) - if FileManager.default.isExecutableFile(atPath: url.path) { + if checkCandidate(url) { return url } } diff --git a/Plugins/PackageToJS/Sources/PackageToJS.swift b/Plugins/PackageToJS/Sources/PackageToJS.swift index 48f84e54..a3083089 100644 --- a/Plugins/PackageToJS/Sources/PackageToJS.swift +++ b/Plugins/PackageToJS/Sources/PackageToJS.swift @@ -317,12 +317,17 @@ final class DefaultPackagingSystem: PackagingSystem { } internal func which(_ executable: String) throws -> URL { + func checkCandidate(_ candidate: URL) -> Bool { + var isDirectory: ObjCBool = false + let fileExists = FileManager.default.fileExists(atPath: candidate.path, isDirectory: &isDirectory) + return fileExists && !isDirectory.boolValue && FileManager.default.isExecutableFile(atPath: candidate.path) + } do { // Check overriding environment variable let envVariable = executable.uppercased().replacingOccurrences(of: "-", with: "_") + "_PATH" if let path = ProcessInfo.processInfo.environment[envVariable] { let url = URL(fileURLWithPath: path).appendingPathComponent(executable) - if FileManager.default.isExecutableFile(atPath: url.path) { + if checkCandidate(url) { return url } } @@ -336,7 +341,7 @@ internal func which(_ executable: String) throws -> URL { let paths = ProcessInfo.processInfo.environment["PATH"]!.split(separator: pathSeparator) for path in paths { let url = URL(fileURLWithPath: String(path)).appendingPathComponent(executable) - if FileManager.default.isExecutableFile(atPath: url.path) { + if checkCandidate(url) { return url } }