Skip to content

Commit 49f825e

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. - Dont set PWD environment variable, it should just be copied from the current environment, to match Darwin.
1 parent f62c026 commit 49f825e

File tree

4 files changed

+76
-9
lines changed

4 files changed

+76
-9
lines changed

Foundation/Process.swift

Lines changed: 25 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,7 @@ 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
483502
}
484503

485504
// On Windows, the PATH is required in order to locate dlls needed by
@@ -658,7 +677,6 @@ open class Process: NSObject {
658677
env = e
659678
} else {
660679
env = ProcessInfo.processInfo.environment
661-
env["PWD"] = currentDirectoryURL.path
662680
}
663681

664682
let nenv = env.count
@@ -839,7 +857,7 @@ open class Process: NSObject {
839857

840858
let fileManager = FileManager()
841859
let previousDirectoryPath = fileManager.currentDirectoryPath
842-
if !fileManager.changeCurrentDirectoryPath(currentDirectoryURL.path) {
860+
if let dir = currentDirectoryURL?.path, !fileManager.changeCurrentDirectoryPath(dir) {
843861
throw _NSErrorWithErrno(errno, reading: true, url: currentDirectoryURL)
844862
}
845863

TestFoundation/TestFileManager.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ class TestFileManager : XCTestCase {
9999

100100
func test_creatingDirectoryWithShortIntermediatePath() {
101101
let fileManager = FileManager.default
102+
let cwd = fileManager.currentDirectoryPath
102103
fileManager.changeCurrentDirectoryPath(NSTemporaryDirectory())
103104

104105
let relativePath = NSUUID().uuidString
@@ -109,6 +110,7 @@ class TestFileManager : XCTestCase {
109110
} catch {
110111
XCTFail("Failed to create and clean up directory")
111112
}
113+
fileManager.changeCurrentDirectoryPath(cwd)
112114
}
113115

114116
func test_moveFile() {

TestFoundation/TestProcess.swift

Lines changed: 43 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -260,12 +260,13 @@ class TestProcess : XCTestCase {
260260

261261
let fm = FileManager.default
262262
let previousWorkingDirectory = fm.currentDirectoryPath
263+
XCTAssertNotEqual(previousWorkingDirectory.standardizePath(), tmpDir.standardizePath())
263264

264265
// Test that getcwd() returns the currentDirectoryPath
265266
do {
266267
let (pwd, _) = try runTask([xdgTestHelperURL().path, "--getcwd"], currentDirectoryPath: tmpDir)
267268
// Check the sub-process used the correct directory
268-
XCTAssertEqual(pwd.trimmingCharacters(in: .newlines), tmpDir)
269+
XCTAssertEqual(pwd.trimmingCharacters(in: .newlines).standardizePath(), tmpDir.standardizePath())
269270
} catch {
270271
XCTFail("Test failed: \(error)")
271272
}
@@ -274,7 +275,9 @@ class TestProcess : XCTestCase {
274275
do {
275276
let (pwd, _) = try runTask([xdgTestHelperURL().path, "--echo-PWD"], currentDirectoryPath: tmpDir)
276277
// Check the sub-process used the correct directory
277-
XCTAssertEqual(pwd.trimmingCharacters(in: .newlines), tmpDir)
278+
let cwd = FileManager.default.currentDirectoryPath
279+
XCTAssertNotEqual(tmpDir, cwd)
280+
XCTAssertEqual(pwd.trimmingCharacters(in: .newlines), cwd)
278281
} catch {
279282
XCTFail("Test failed: \(error)")
280283
}
@@ -566,6 +569,42 @@ class TestProcess : XCTestCase {
566569
}
567570

568571

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

597637
#if !os(Windows)
@@ -690,6 +730,7 @@ class _SignalHelperRunner {
690730
}
691731
}
692732

733+
@discardableResult
693734
internal func runTask(_ arguments: [String], environment: [String: String]? = nil, currentDirectoryPath: String? = nil) throws -> (String, String) {
694735
let process = Process()
695736

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)