Skip to content

Commit 6d9af20

Browse files
authored
Merge pull request #2548 from spevans/pr_process_current_directory2
Process: Match Darwin more closely for handling of .currentDirectoryPath and .currentDirectoryURL
2 parents dcfebec + 171b4e6 commit 6d9af20

File tree

2 files changed

+78
-11
lines changed

2 files changed

+78
-11
lines changed

Foundation/Process.swift

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -243,14 +243,17 @@ open class Process: NSObject {
243243
}
244244
}
245245

246-
private var _currentDirectoryURL: URL? = URL(fileURLWithPath: FileManager.default.currentDirectoryPath, isDirectory: true)
246+
private var _currentDirectoryPath = FileManager.default.currentDirectoryPath
247247
open var currentDirectoryURL: URL? {
248-
get { _currentDirectoryURL }
248+
get { _currentDirectoryPath == "" ? nil : URL(fileURLWithPath: _currentDirectoryPath, isDirectory: true) }
249249
set {
250-
guard let url = newValue, url.isFileURL else {
251-
fatalError("non-file URL argument")
250+
// Setting currentDirectoryURL to nil resets to the current directory
251+
if let url = newValue {
252+
guard url.isFileURL else { fatalError("non-file URL argument") }
253+
_currentDirectoryPath = url.path
254+
} else {
255+
_currentDirectoryPath = FileManager.default.currentDirectoryPath
252256
}
253-
_currentDirectoryURL = url
254257
}
255258
}
256259

@@ -265,8 +268,8 @@ open class Process: NSObject {
265268

266269
@available(*, deprecated, renamed: "currentDirectoryURL")
267270
open var currentDirectoryPath: String {
268-
get { return currentDirectoryURL!.path }
269-
set { currentDirectoryURL = URL(fileURLWithPath: newValue) }
271+
get { _currentDirectoryPath }
272+
set { _currentDirectoryPath = newValue }
270273
}
271274

272275
// Standard I/O channels; could be either a FileHandle or a Pipe
@@ -583,8 +586,9 @@ open class Process: NSObject {
583586
CFSocketCreateRunLoopSource(kCFAllocatorDefault, socket, 0)
584587
CFRunLoopAddSource(managerThreadRunLoop?._cfRunLoop, source, kCFRunLoopDefaultMode)
585588

589+
let workingDirectory = currentDirectoryURL?.path ?? FileManager.default.currentDirectoryPath
586590
try quoteWindowsCommandLine(command).withCString(encodedAs: UTF16.self) { wszCommandLine in
587-
try currentDirectoryURL.path.withCString(encodedAs: UTF16.self) { wszCurrentDirectory in
591+
try workingDirectory.withCString(encodedAs: UTF16.self) { wszCurrentDirectory in
588592
try szEnvironment.withCString(encodedAs: UTF16.self) { wszEnvironment in
589593
if !CreateProcessW(nil, UnsafeMutablePointer<WCHAR>(mutating: wszCommandLine),
590594
nil, nil, true,

TestFoundation/TestProcess.swift

Lines changed: 66 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -596,6 +596,38 @@ class TestProcess : XCTestCase {
596596
let process = Process()
597597
XCTAssertNil(process.executableURL)
598598
XCTAssertNotNil(process.currentDirectoryURL)
599+
600+
// Test currentDirectoryURL cannot be set to nil even though it is a URL?
601+
let cwd = URL(fileURLWithPath: FileManager.default.currentDirectoryPath, isDirectory: true)
602+
process.currentDirectoryURL = nil
603+
XCTAssertNotNil(process.currentDirectoryURL)
604+
XCTAssertEqual(process.currentDirectoryURL, cwd)
605+
606+
let aFileURL = URL(fileURLWithPath: "/a_file", isDirectory: false)
607+
XCTAssertFalse(aFileURL.hasDirectoryPath)
608+
XCTAssertEqual(aFileURL.path, "/a_file")
609+
process.currentDirectoryURL = aFileURL
610+
XCTAssertNotEqual(process.currentDirectoryURL, aFileURL)
611+
XCTAssertEqual(process.currentDirectoryPath, "/a_file")
612+
XCTAssertTrue(try XCTUnwrap(process.currentDirectoryURL).hasDirectoryPath)
613+
XCTAssertEqual(try XCTUnwrap(process.currentDirectoryURL).absoluteString, "file:///a_file/")
614+
615+
let aDirURL = URL(fileURLWithPath: "/a_dir", isDirectory: true)
616+
XCTAssertTrue(aDirURL.hasDirectoryPath)
617+
XCTAssertEqual(aDirURL.path, "/a_dir")
618+
process.currentDirectoryURL = aDirURL
619+
XCTAssertEqual(process.currentDirectoryURL, aDirURL)
620+
XCTAssertEqual(process.currentDirectoryPath, "/a_dir")
621+
XCTAssertTrue(try XCTUnwrap(process.currentDirectoryURL).hasDirectoryPath)
622+
XCTAssertEqual(try XCTUnwrap(process.currentDirectoryURL).absoluteString, "file:///a_dir/")
623+
624+
process.currentDirectoryPath = ""
625+
XCTAssertEqual(process.currentDirectoryPath, "")
626+
XCTAssertNil(process.currentDirectoryURL)
627+
process.currentDirectoryURL = nil
628+
XCTAssertEqual(process.currentDirectoryPath, cwd.path)
629+
630+
599631
process.executableURL = URL(fileURLWithPath: "/some_file_that_doesnt_exist", isDirectory: false)
600632
XCTAssertThrowsError(try process.run()) {
601633
let code = CocoaError.Code(rawValue: ($0 as? NSError)!.code)
@@ -617,13 +649,44 @@ class TestProcess : XCTestCase {
617649
}
618650

619651
do {
620-
try runTask([xdgTestHelperURL().path, "--getcwd"], currentDirectoryPath: "/some_directory_that_doesnt_exsit")
652+
let process = Process()
653+
process.executableURL = xdgTestHelperURL()
654+
process.arguments = [ "--getcwd" ]
655+
process.currentDirectoryPath = ""
656+
657+
let stdoutPipe = Pipe()
658+
process.standardOutput = stdoutPipe
659+
660+
try process.run()
661+
process.waitUntilExit()
662+
663+
guard process.terminationStatus == 0 else {
664+
throw Error.TerminationStatus(process.terminationStatus)
665+
}
666+
667+
var stdoutData = Data()
668+
#if DARWIN_COMPATIBILITY_TESTS
669+
// Use old API for now
670+
stdoutData.append(stdoutPipe.fileHandleForReading.availableData)
671+
#else
672+
if let d = try stdoutPipe.fileHandleForReading.readToEnd() {
673+
stdoutData.append(d)
674+
}
675+
#endif
676+
677+
guard let stdout = String(data: stdoutData, encoding: .utf8) else {
678+
throw Error.UnicodeDecodingError(stdoutData)
679+
}
680+
let directory = stdout.trimmingCharacters(in: CharacterSet(["\n", "\r"]))
681+
XCTAssertEqual(directory, FileManager.default.currentDirectoryPath)
621682
} catch {
683+
XCTFail(String(describing: error))
684+
}
685+
686+
XCTAssertThrowsError(try runTask([xdgTestHelperURL().path, "--getcwd"], currentDirectoryPath: "/some_directory_that_doesnt_exsit")) { error in
622687
let code = CocoaError.Code(rawValue: (error as? NSError)!.code)
623688
XCTAssertEqual(code, .fileReadNoSuchFile)
624-
return
625689
}
626-
XCTFail("Failed to catch error")
627690
}
628691

629692

0 commit comments

Comments
 (0)