Skip to content

Commit 442a0ab

Browse files
committed
Process: .currentDirectoryURL and .executableURL fixes
- currentDirectoryURL should be of type URL? - Disallow setting either property to nil or a non-File URL, to match Darwin. - PWD environment variable should be set to the current directory of the parent, to match Darwin.
1 parent f62c026 commit 442a0ab

File tree

3 files changed

+75
-9
lines changed

3 files changed

+75
-9
lines changed

Foundation/Process.swift

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -232,8 +232,28 @@ open class Process: NSObject {
232232
}
233233

234234
// These properties can only be set before a launch.
235-
open var executableURL: URL?
236-
open var currentDirectoryURL = URL(fileURLWithPath: FileManager.default.currentDirectoryPath, isDirectory: true)
235+
private var _executable: URL?
236+
open var executableURL: URL? {
237+
get { _executable }
238+
set {
239+
guard let url = newValue, url.isFileURL else {
240+
fatalError("must provide a launch path")
241+
}
242+
_executable = url
243+
}
244+
}
245+
246+
private var _currentDirectoryURL: URL? = URL(fileURLWithPath: FileManager.default.currentDirectoryPath, isDirectory: true)
247+
open var currentDirectoryURL: URL? {
248+
get { _currentDirectoryURL }
249+
set {
250+
guard let url = newValue, url.isFileURL else {
251+
fatalError("non-file URL argument")
252+
}
253+
_currentDirectoryURL = url
254+
}
255+
}
256+
237257
open var arguments: [String]?
238258
open var environment: [String : String]? // if not set, use current
239259

@@ -245,7 +265,7 @@ open class Process: NSObject {
245265

246266
@available(*, deprecated, renamed: "currentDirectoryURL")
247267
open var currentDirectoryPath: String {
248-
get { return currentDirectoryURL.path }
268+
get { return currentDirectoryURL!.path }
249269
set { currentDirectoryURL = URL(fileURLWithPath: newValue) }
250270
}
251271

@@ -478,8 +498,8 @@ open class Process: NSObject {
478498
if let env = self.environment {
479499
environment = env
480500
} else {
481-
environment = ProcessInfo.processInfo.environment
482-
environment["PWD"] = currentDirectoryURL.path
501+
environment = ProcessInfo.processInfo.environment
502+
environment["PWD"] = FileManager.default.currentDirectoryPath
483503
}
484504

485505
// On Windows, the PATH is required in order to locate dlls needed by
@@ -658,7 +678,7 @@ open class Process: NSObject {
658678
env = e
659679
} else {
660680
env = ProcessInfo.processInfo.environment
661-
env["PWD"] = currentDirectoryURL.path
681+
env["PWD"] = FileManager.default.currentDirectoryPath
662682
}
663683

664684
let nenv = env.count
@@ -839,7 +859,7 @@ open class Process: NSObject {
839859

840860
let fileManager = FileManager()
841861
let previousDirectoryPath = fileManager.currentDirectoryPath
842-
if !fileManager.changeCurrentDirectoryPath(currentDirectoryURL.path) {
862+
if let dir = currentDirectoryURL?.path, !fileManager.changeCurrentDirectoryPath(dir) {
843863
throw _NSErrorWithErrno(errno, reading: true, url: currentDirectoryURL)
844864
}
845865

TestFoundation/TestProcess.swift

Lines changed: 42 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -265,7 +265,7 @@ class TestProcess : XCTestCase {
265265
do {
266266
let (pwd, _) = try runTask([xdgTestHelperURL().path, "--getcwd"], currentDirectoryPath: tmpDir)
267267
// Check the sub-process used the correct directory
268-
XCTAssertEqual(pwd.trimmingCharacters(in: .newlines), tmpDir)
268+
XCTAssertEqual(pwd.trimmingCharacters(in: .newlines).standardizePath(), tmpDir.standardizePath())
269269
} catch {
270270
XCTFail("Test failed: \(error)")
271271
}
@@ -274,7 +274,9 @@ class TestProcess : XCTestCase {
274274
do {
275275
let (pwd, _) = try runTask([xdgTestHelperURL().path, "--echo-PWD"], currentDirectoryPath: tmpDir)
276276
// Check the sub-process used the correct directory
277-
XCTAssertEqual(pwd.trimmingCharacters(in: .newlines), tmpDir)
277+
let cwd = FileManager.default.currentDirectoryPath
278+
XCTAssertNotEqual(tmpDir, cwd)
279+
XCTAssertEqual(pwd.trimmingCharacters(in: .newlines), cwd)
278280
} catch {
279281
XCTFail("Test failed: \(error)")
280282
}
@@ -566,6 +568,42 @@ class TestProcess : XCTestCase {
566568
}
567569

568570

571+
func test_currentDirectory() throws {
572+
573+
let process = Process()
574+
XCTAssertNil(process.executableURL)
575+
XCTAssertNotNil(process.currentDirectoryURL)
576+
process.executableURL = URL(fileURLWithPath: "/some_file_that_doesnt_exist", isDirectory: false)
577+
XCTAssertThrowsError(try process.run()) {
578+
let code = CocoaError.Code(rawValue: ($0 as? NSError)!.code)
579+
XCTAssertEqual(code, .fileReadNoSuchFile)
580+
}
581+
582+
do {
583+
let (stdout, _) = try runTask([xdgTestHelperURL().path, "--getcwd"], currentDirectoryPath: "/")
584+
XCTAssertEqual(stdout.trimmingCharacters(in: CharacterSet(["\n", "\r"])), "/")
585+
}
586+
587+
do {
588+
XCTAssertNotEqual("/", FileManager.default.currentDirectoryPath)
589+
XCTAssertNotEqual(FileManager.default.currentDirectoryPath, "/")
590+
let (stdout, _) = try runTask([xdgTestHelperURL().path, "--echo-PWD"], currentDirectoryPath: "/")
591+
let directory = stdout.trimmingCharacters(in: CharacterSet(["\n", "\r"]))
592+
XCTAssertEqual(directory, FileManager.default.currentDirectoryPath)
593+
XCTAssertNotEqual(directory, "/")
594+
}
595+
596+
do {
597+
try runTask([xdgTestHelperURL().path, "--getcwd"], currentDirectoryPath: "/some_directory_that_doesnt_exsit")
598+
} catch {
599+
let code = CocoaError.Code(rawValue: (error as? NSError)!.code)
600+
XCTAssertEqual(code, .fileReadNoSuchFile)
601+
return
602+
}
603+
XCTFail("Failed to catch error")
604+
}
605+
606+
569607
static var allTests: [(String, (TestProcess) -> () throws -> Void)] {
570608
var tests = [
571609
("test_exit0" , test_exit0),
@@ -592,6 +630,7 @@ class TestProcess : XCTestCase {
592630
("test_redirect_all_using_null", test_redirect_all_using_null),
593631
("test_redirect_all_using_nil", test_redirect_all_using_nil),
594632
("test_plutil", test_plutil),
633+
("test_currentDirectory", test_currentDirectory),
595634
]
596635

597636
#if !os(Windows)
@@ -690,6 +729,7 @@ class _SignalHelperRunner {
690729
}
691730
}
692731

732+
@discardableResult
693733
internal func runTask(_ arguments: [String], environment: [String: String]? = nil, currentDirectoryPath: String? = nil) throws -> (String, String) {
694734
let process = Process()
695735

TestFoundation/Utilities.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -621,6 +621,12 @@ extension XCTest {
621621
}
622622
}
623623

624+
extension String {
625+
public func standardizePath() -> String {
626+
URL(fileURLWithPath: self).resolvingSymlinksInPath().path
627+
}
628+
}
629+
624630
extension FileHandle: TextOutputStream {
625631
public func write(_ string: String) {
626632
write(Data(string.utf8))

0 commit comments

Comments
 (0)