Skip to content

Add support for currentDirectoryPath in Process class #1008

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jul 25, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions Foundation/Process.swift
Original file line number Diff line number Diff line change
Expand Up @@ -387,11 +387,30 @@ open class Process: NSObject {
posix(posix_spawn_file_actions_addclose(&fileActions, fd))
}

let fileManager = FileManager()
let previousDirectoryPath = fileManager.currentDirectoryPath
if !fileManager.changeCurrentDirectoryPath(currentDirectoryPath) {
// Foundation throws an NSException when changing the working directory fails,
// and unfortunately launch() is not marked `throws`, so we get away with a
// fatalError.
switch errno {
case ENOENT:
fatalError("Process: The specified working directory does not exist.")
case EACCES:
fatalError("Process: The specified working directory cannot be accessed.")
default:
fatalError("Process: The specified working directory cannot be set.")
}
}

// Launch

var pid = pid_t()
posix(posix_spawn(&pid, launchPath, &fileActions, nil, argv, envp))

// Reset the previous working directory path.
fileManager.changeCurrentDirectoryPath(previousDirectoryPath)

// Close the write end of the input and output pipes.
if let pipe = standardInput as? Pipe {
pipe.fileHandleForReading.closeFile()
Expand Down
20 changes: 19 additions & 1 deletion TestFoundation/TestProcess.swift
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ class TestProcess : XCTestCase {
("test_pipe_stdin", test_pipe_stdin),
("test_pipe_stdout", test_pipe_stdout),
("test_pipe_stderr", test_pipe_stderr),
("test_current_working_directory", test_current_working_directory),
// disabled for now
// ("test_pipe_stdout_and_stderr_same_pipe", test_pipe_stdout_and_stderr_same_pipe),
("test_file_stdout", test_file_stdout),
Expand Down Expand Up @@ -262,6 +263,19 @@ class TestProcess : XCTestCase {
XCTFail("Test failed: \(error)")
}
}

func test_current_working_directory() {
do {
let previousWorkingDirectory = FileManager.default.currentDirectoryPath

// `bash` will not be found if the current working directory is not set correctly.
let _ = try runTask(["bash", "-c", "exit 0"], currentDirectoryPath: "/bin")

XCTAssertEqual(previousWorkingDirectory, FileManager.default.currentDirectoryPath)
} catch let error {
XCTFail("Test failed: \(error)")
}
}
}

private func mkstemp(template: String, body: (FileHandle) throws -> Void) rethrows {
Expand All @@ -284,14 +298,18 @@ private enum Error: Swift.Error {
case InvalidEnvironmentVariable(String)
}

private func runTask(_ arguments: [String], environment: [String: String]? = nil) throws -> String {
private func runTask(_ arguments: [String], environment: [String: String]? = nil, currentDirectoryPath: String? = nil) throws -> String {
let process = Process()

var arguments = arguments
process.launchPath = arguments.removeFirst()
process.arguments = arguments
process.environment = environment

if let directoryPath = currentDirectoryPath {
process.currentDirectoryPath = directoryPath
}

let pipe = Pipe()
process.standardOutput = pipe
process.standardError = pipe
Expand Down