Skip to content

Commit e872f47

Browse files
authored
Merge pull request #2525 from spevans/pr_process_current_directory
2 parents 7019717 + 2427fb2 commit e872f47

File tree

4 files changed

+77
-10
lines changed

4 files changed

+77
-10
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: 44 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -262,17 +262,18 @@ class TestProcess : XCTestCase {
262262
if (dir.hasSuffix("/") && dir != "/") || dir.hasSuffix("\\") {
263263
dir.removeLast()
264264
}
265-
return dir
265+
return dir.standardizePath()
266266
}()
267267

268268
let fm = FileManager.default
269269
let previousWorkingDirectory = fm.currentDirectoryPath
270+
XCTAssertNotEqual(previousWorkingDirectory.standardizePath(), tmpDir)
270271

271272
// Test that getcwd() returns the currentDirectoryPath
272273
do {
273274
let (pwd, _) = try runTask([xdgTestHelperURL().path, "--getcwd"], currentDirectoryPath: tmpDir)
274275
// Check the sub-process used the correct directory
275-
XCTAssertEqual(pwd.trimmingCharacters(in: .newlines), tmpDir)
276+
XCTAssertEqual(pwd.trimmingCharacters(in: .newlines).standardizePath(), tmpDir)
276277
} catch {
277278
XCTFail("Test failed: \(error)")
278279
}
@@ -281,7 +282,9 @@ class TestProcess : XCTestCase {
281282
do {
282283
let (pwd, _) = try runTask([xdgTestHelperURL().path, "--echo-PWD"], currentDirectoryPath: tmpDir)
283284
// Check the sub-process used the correct directory
284-
XCTAssertEqual(pwd.trimmingCharacters(in: .newlines), tmpDir)
285+
let cwd = FileManager.default.currentDirectoryPath.standardizePath()
286+
XCTAssertNotEqual(cwd, tmpDir)
287+
XCTAssertNotEqual(pwd.trimmingCharacters(in: .newlines).standardizePath(), tmpDir)
285288
} catch {
286289
XCTFail("Test failed: \(error)")
287290
}
@@ -584,6 +587,42 @@ class TestProcess : XCTestCase {
584587
}
585588

586589

590+
func test_currentDirectory() throws {
591+
592+
let process = Process()
593+
XCTAssertNil(process.executableURL)
594+
XCTAssertNotNil(process.currentDirectoryURL)
595+
process.executableURL = URL(fileURLWithPath: "/some_file_that_doesnt_exist", isDirectory: false)
596+
XCTAssertThrowsError(try process.run()) {
597+
let code = CocoaError.Code(rawValue: ($0 as? NSError)!.code)
598+
XCTAssertEqual(code, .fileReadNoSuchFile)
599+
}
600+
601+
do {
602+
let (stdout, _) = try runTask([xdgTestHelperURL().path, "--getcwd"], currentDirectoryPath: "/")
603+
XCTAssertEqual(stdout.trimmingCharacters(in: CharacterSet(["\n", "\r"])), "/")
604+
}
605+
606+
do {
607+
XCTAssertNotEqual("/", FileManager.default.currentDirectoryPath)
608+
XCTAssertNotEqual(FileManager.default.currentDirectoryPath, "/")
609+
let (stdout, _) = try runTask([xdgTestHelperURL().path, "--echo-PWD"], currentDirectoryPath: "/")
610+
let directory = stdout.trimmingCharacters(in: CharacterSet(["\n", "\r"]))
611+
XCTAssertEqual(directory, ProcessInfo.processInfo.environment["PWD"])
612+
XCTAssertNotEqual(directory, "/")
613+
}
614+
615+
do {
616+
try runTask([xdgTestHelperURL().path, "--getcwd"], currentDirectoryPath: "/some_directory_that_doesnt_exsit")
617+
} catch {
618+
let code = CocoaError.Code(rawValue: (error as? NSError)!.code)
619+
XCTAssertEqual(code, .fileReadNoSuchFile)
620+
return
621+
}
622+
XCTFail("Failed to catch error")
623+
}
624+
625+
587626
static var allTests: [(String, (TestProcess) -> () throws -> Void)] {
588627
var tests = [
589628
("test_exit0" , test_exit0),
@@ -610,6 +649,7 @@ class TestProcess : XCTestCase {
610649
("test_redirect_all_using_null", test_redirect_all_using_null),
611650
("test_redirect_all_using_nil", test_redirect_all_using_nil),
612651
("test_plutil", test_plutil),
652+
("test_currentDirectory", test_currentDirectory),
613653
]
614654

615655
#if !os(Windows)
@@ -708,6 +748,7 @@ class _SignalHelperRunner {
708748
}
709749
}
710750

751+
@discardableResult
711752
internal func runTask(_ arguments: [String], environment: [String: String]? = nil, currentDirectoryPath: String? = nil) throws -> (String, String) {
712753
let process = Process()
713754

TestFoundation/Utilities.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -625,6 +625,12 @@ extension XCTest {
625625
}
626626
}
627627

628+
extension String {
629+
public func standardizePath() -> String {
630+
URL(fileURLWithPath: self).resolvingSymlinksInPath().path
631+
}
632+
}
633+
628634
extension FileHandle: TextOutputStream {
629635
public func write(_ string: String) {
630636
write(Data(string.utf8))

0 commit comments

Comments
 (0)