blob: be4dbff06c54178aaca85ca1a73cb97294d4b304 (
plain) (
blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
|
import Foundation
/// Runs a shell command and returns its stdout as separate lines.
///
/// Blocking — always call from a background context (e.g. `Task.detached`).
enum Runner {
/// Run a command and returns stdout as an array of separated lines.
/// - Parameters:
/// - command: The command to run.
/// - env: An optional dictionary of strings to merge into
/// the process environment.
///
/// - Returns: An array of the text lines printed to stdout.
static func run(_ command: String, env: [String: String] = [:]) -> [String] {
let process = Process()
process.executableURL = URL(fileURLWithPath: "/bin/sh")
process.arguments = ["-c", command]
var environment = ProcessInfo.processInfo.environment
environment.merge(env) { _, new in new }
process.environment = environment
let stdout = Pipe()
let stderr = Pipe()
process.standardOutput = stdout
process.standardError = stderr
guard (try? process.run()) != nil else {
return ["ERROR"]
}
let data = stdout.fileHandleForReading.readDataToEndOfFile()
let errData = stderr.fileHandleForReading.readDataToEndOfFile()
process.waitUntilExit()
guard process.terminationStatus == 0 else {
write(errData, to: .standardError)
return ["ERROR"]
}
guard let string = String(data: data, encoding: .utf8) else {
return [""]
}
return parse(string)
}
/// Split output into lines. A single trailing newline
/// (from a final `\n`) is dropped; blank lines elsewhere
/// are kept so a script can emit intentional gaps.
static func parse(_ text: String) -> [String] {
var lines = text.components(separatedBy: "\n")
if lines.last == "" { lines.removeLast() }
return lines
}
/// Write data to the provided handle.
/// - Parameters:
/// - data: The data to write.
/// - handle: The handle to which data should be written.
static func write(_ data: Data, to handle: FileHandle) {
handle.write(data)
}
/// Write string to the provided handle.
/// - Parameters:
/// - string: The string to write.
/// - handle: The handle to which data should be written.
static func write(_ string: String, to handle: FileHandle) {
write(Data(string.utf8), to: handle)
}
}
|