mirror of
https://github.com/XcodesOrg/XcodesApp.git
synced 2026-03-25 08:55:46 +00:00
Dispatch Process.run work manually instead of using subscribe(on:) and receive(on:)
The previous implementation was doing something weird when it was used during installation in:
verifySecurityAssessment(of: installedXcode)
.combineLatest(self.verifySigningCertificate(of: installedXcode.path.url))
It looks like it would subscribe after the Process.run future had already sent a value, and so it would never finish. This seems weird, and I'm assuming that I'm misunderstanding something about this behaviour, but dispatching manually seems reasonable and works.
This commit is contained in:
parent
bfb3fd9ea5
commit
89143b8751
1 changed files with 41 additions and 30 deletions
|
|
@ -14,41 +14,52 @@ extension Process {
|
|||
static func run(_ executable: URL, workingDirectory: URL? = nil, input: String? = nil, _ arguments: [String]) -> AnyPublisher<ProcessOutput, Error> {
|
||||
Deferred {
|
||||
Future<ProcessOutput, Error> { promise in
|
||||
let process = Process()
|
||||
process.currentDirectoryURL = workingDirectory ?? executable.deletingLastPathComponent()
|
||||
process.executableURL = executable
|
||||
process.arguments = arguments
|
||||
|
||||
let (stdout, stderr) = (Pipe(), Pipe())
|
||||
process.standardOutput = stdout
|
||||
process.standardError = stderr
|
||||
|
||||
if let input = input {
|
||||
let inputPipe = Pipe()
|
||||
process.standardInput = inputPipe.fileHandleForReading
|
||||
inputPipe.fileHandleForWriting.write(Data(input.utf8))
|
||||
inputPipe.fileHandleForWriting.closeFile()
|
||||
}
|
||||
|
||||
do {
|
||||
try process.run()
|
||||
process.waitUntilExit()
|
||||
|
||||
let output = String(data: stdout.fileHandleForReading.readDataToEndOfFile(), encoding: .utf8) ?? ""
|
||||
let error = String(data: stderr.fileHandleForReading.readDataToEndOfFile(), encoding: .utf8) ?? ""
|
||||
DispatchQueue.global().async {
|
||||
let process = Process()
|
||||
process.currentDirectoryURL = workingDirectory ?? executable.deletingLastPathComponent()
|
||||
process.executableURL = executable
|
||||
process.arguments = arguments
|
||||
|
||||
guard process.terminationReason == .exit, process.terminationStatus == 0 else {
|
||||
return promise(.failure(ProcessExecutionError(process: process, standardOutput: output, standardError: error)))
|
||||
let (stdout, stderr) = (Pipe(), Pipe())
|
||||
process.standardOutput = stdout
|
||||
process.standardError = stderr
|
||||
|
||||
if let input = input {
|
||||
let inputPipe = Pipe()
|
||||
process.standardInput = inputPipe.fileHandleForReading
|
||||
inputPipe.fileHandleForWriting.write(Data(input.utf8))
|
||||
inputPipe.fileHandleForWriting.closeFile()
|
||||
}
|
||||
|
||||
do {
|
||||
print("Process.run \(executable), \(input), \(arguments.joined(separator: " "))")
|
||||
try process.run()
|
||||
process.waitUntilExit()
|
||||
|
||||
let output = String(data: stdout.fileHandleForReading.readDataToEndOfFile(), encoding: .utf8) ?? ""
|
||||
let error = String(data: stderr.fileHandleForReading.readDataToEndOfFile(), encoding: .utf8) ?? ""
|
||||
|
||||
dump(process)
|
||||
print(output)
|
||||
print(error)
|
||||
guard process.terminationReason == .exit, process.terminationStatus == 0 else {
|
||||
DispatchQueue.main.async {
|
||||
promise(.failure(ProcessExecutionError(process: process, standardOutput: output, standardError: error)))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
DispatchQueue.main.async {
|
||||
promise(.success((process.terminationStatus, output, error)))
|
||||
}
|
||||
} catch {
|
||||
DispatchQueue.main.async {
|
||||
promise(.failure(error))
|
||||
}
|
||||
}
|
||||
|
||||
promise(.success((process.terminationStatus, output, error)))
|
||||
} catch {
|
||||
promise(.failure(error))
|
||||
}
|
||||
}
|
||||
}
|
||||
.subscribe(on: DispatchQueue.global())
|
||||
.receive(on: DispatchQueue.main)
|
||||
.eraseToAnyPublisher()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue