Skip to content

Commit a79476b

Browse files
committed
fixup
1 parent 21331b6 commit a79476b

File tree

1 file changed

+148
-33
lines changed

1 file changed

+148
-33
lines changed

Sources/TSCBasic/Process.swift

Lines changed: 148 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -204,22 +204,65 @@ public final class Process {
204204
/// Typealias for stdout/stderr output closure.
205205
public typealias OutputClosure = ([UInt8]) -> Void
206206

207-
/// Global default setting for verbose.
207+
/// Typealias for logging handling closure
208+
public typealias LoggingHandler = (String) -> Void
209+
210+
private static var _loggingHandler: LoggingHandler?
211+
private static let loggingHandlerLock = Lock()
212+
213+
/// Global logging handler. Use with care! preferably use instance level instead of setting one globally.
214+
public static var loggingHandler: LoggingHandler? {
215+
get {
216+
Self.loggingHandlerLock.withLock {
217+
self._loggingHandler
218+
}
219+
} set {
220+
Self.loggingHandlerLock.withLock {
221+
self._loggingHandler = newValue
222+
}
223+
}
224+
}
225+
226+
// deprecated 2/2022, remove once client migrate to logging handler
208227
@available(*, deprecated)
209228
public static var verbose: Bool {
210-
Self.loggingHandler != nil
229+
get {
230+
Self.loggingHandler != nil
231+
} set {
232+
Self.loggingHandler = newValue ? Self.logToStdout: .none
233+
}
211234
}
212235

213-
public static var loggingHandler: ((String) -> Void)? = nil
236+
private var _loggingHandler: LoggingHandler?
237+
238+
// the log and setter are only required to backward support verbose setter.
239+
// remove and make loggingHandler a let property once verbose is deprecated
240+
private let loggingHandlerLock = Lock()
241+
public private(set) var loggingHandler: LoggingHandler? {
242+
get {
243+
self.loggingHandlerLock.withLock {
244+
self._loggingHandler
245+
}
246+
}
247+
set {
248+
self.loggingHandlerLock.withLock {
249+
self._loggingHandler = newValue
250+
}
251+
}
252+
}
214253

215-
/// If true, prints the subprocess arguments before launching it.
254+
// deprecated 2/2022, remove once client migrate to logging handler
255+
// also simplify loggingHandler (see above) once this is removed
216256
@available(*, deprecated)
217257
public var verbose: Bool {
218-
self.loggingHandler != nil
258+
get {
259+
self.loggingHandler != nil
260+
}
261+
set {
262+
self.loggingHandler = newValue ? Self.logToStdout : .none
263+
}
219264
}
220265

221-
private let loggingHandler: ((String) -> Void)?
222-
223266
/// The current environment.
224267
@available(*, deprecated, message: "use ProcessEnv.vars instead")
225268
static public var env: [String: String] {
@@ -248,6 +291,7 @@ public final class Process {
248291
// process execution mutable state
249292
private var state: State = .idle
250293
private let stateLock = Lock()
294+
251295
private static let sharedCompletionQueue = DispatchQueue(label: "org.swift.tools-support-core.process-completion")
252296
private var completionQueue = Process.sharedCompletionQueue
253297

@@ -307,14 +351,14 @@ public final class Process {
307351
workingDirectory: AbsolutePath,
308352
outputRedirection: OutputRedirection = .collect,
309353
startNewProcessGroup: Bool = true,
310-
loggingHandler: ((String) -> Void)? = Process.loggingHandler
354+
loggingHandler: LoggingHandler? = .none
311355
) {
312356
self.arguments = arguments
313357
self.environment = environment
314358
self.workingDirectory = workingDirectory
315359
self.outputRedirection = outputRedirection
316360
self.startNewProcessGroup = startNewProcessGroup
317-
self.loggingHandler = loggingHandler
361+
self.loggingHandler = loggingHandler ?? Process.loggingHandler
318362
}
319363

320364
// deprecated 2/2022
@@ -352,19 +396,20 @@ public final class Process {
352396
/// - verbose: If true, launch() will print the arguments of the subprocess before launching it.
353397
/// - startNewProcessGroup: If true, a new progress group is created for the child making it
354398
/// continue running even if the parent is killed or interrupted. Default value is true.
399+
/// - loggingHandler: Handler for logging messages
355400
public init(
356401
arguments: [String],
357402
environment: [String: String] = ProcessEnv.vars,
358403
outputRedirection: OutputRedirection = .collect,
359404
startNewProcessGroup: Bool = true,
360-
loggingHandler: ((String) -> Void)? = Process.loggingHandler
405+
loggingHandler: LoggingHandler? = .none
361406
) {
362407
self.arguments = arguments
363408
self.environment = environment
364409
self.workingDirectory = nil
365410
self.outputRedirection = outputRedirection
366411
self.startNewProcessGroup = startNewProcessGroup
367-
self.loggingHandler = loggingHandler
412+
self.loggingHandler = loggingHandler ?? Process.loggingHandler
368413
}
369414

370415
@_disfavoredOverload
@@ -381,10 +426,21 @@ public final class Process {
381426
environment: environment,
382427
outputRedirection: outputRedirection,
383428
startNewProcessGroup: startNewProcessGroup,
384-
loggingHandler: verbose ? { message in
385-
stdoutStream <<< message <<< "\n"
386-
stdoutStream.flush()
387-
} : nil
429+
loggingHandler: verbose ? Self.logToStdout : .none
430+
)
431+
}
432+
433+
public convenience init(
434+
args: String...,
435+
environment: [String: String] = ProcessEnv.vars,
436+
outputRedirection: OutputRedirection = .collect,
437+
loggingHandler: LoggingHandler? = .none
438+
) {
439+
self.init(
440+
arguments: args,
441+
environment: environment,
442+
outputRedirection: outputRedirection,
443+
loggingHandler: loggingHandler
388444
)
389445
}
390446

@@ -452,8 +508,6 @@ public final class Process {
452508
// Print the arguments if we are verbose.
453509
if let loggingHandler = self.loggingHandler {
454510
loggingHandler(arguments.map({ $0.spm_shellEscaped() }).joined(separator: " "))
455-
//stdoutStream <<< arguments.map({ $0.spm_shellEscaped() }).joined(separator: " ") <<< "\n"
456-
//stdoutStream.flush()
457511
}
458512

459513
// Look for executable.
@@ -890,11 +944,23 @@ extension Process {
890944
/// - arguments: The arguments for the subprocess.
891945
/// - environment: The environment to pass to subprocess. By default the current process environment
892946
/// will be inherited.
893-
/// - Returns: The process result.
894-
static public func popen(arguments: [String], environment: [String: String] = ProcessEnv.vars,
895-
queue: DispatchQueue? = nil, completion: @escaping (Result<ProcessResult, Swift.Error>) -> Void) {
947+
/// - loggingHandler: Handler for logging messages
948+
/// - queue: Queue to use for callbacks
949+
/// - completion: A completion handler to return the process result
950+
static public func popen(
951+
arguments: [String],
952+
environment: [String: String] = ProcessEnv.vars,
953+
loggingHandler: LoggingHandler? = .none,
954+
queue: DispatchQueue? = nil,
955+
completion: @escaping (Result<ProcessResult, Swift.Error>) -> Void
956+
) {
896957
do {
897-
let process = Process(arguments: arguments, environment: environment, outputRedirection: .collect)
958+
let process = Process(
959+
arguments: arguments,
960+
environment: environment,
961+
outputRedirection: .collect,
962+
loggingHandler: loggingHandler
963+
)
898964
process.completionQueue = queue ?? Self.sharedCompletionQueue
899965
try process.launch()
900966
process.waitUntilExit(completion)
@@ -909,17 +975,39 @@ extension Process {
909975
/// - arguments: The arguments for the subprocess.
910976
/// - environment: The environment to pass to subprocess. By default the current process environment
911977
/// will be inherited.
978+
/// - loggingHandler: Handler for logging messages
912979
/// - Returns: The process result.
913980
@discardableResult
914-
static public func popen(arguments: [String], environment: [String: String] = ProcessEnv.vars) throws -> ProcessResult {
915-
let process = Process(arguments: arguments, environment: environment, outputRedirection: .collect)
981+
static public func popen(
982+
arguments: [String],
983+
environment: [String: String] = ProcessEnv.vars,
984+
loggingHandler: LoggingHandler? = .none
985+
) throws -> ProcessResult {
986+
let process = Process(
987+
arguments: arguments,
988+
environment: environment,
989+
outputRedirection: .collect,
990+
loggingHandler: loggingHandler
991+
)
916992
try process.launch()
917993
return try process.waitUntilExit()
918994
}
919995

996+
/// Execute a subprocess and block until it finishes execution
997+
///
998+
/// - Parameters:
999+
/// - args: The arguments for the subprocess.
1000+
/// - environment: The environment to pass to subprocess. By default the current process environment
1001+
/// will be inherited.
1002+
/// - loggingHandler: Handler for logging messages
1003+
/// - Returns: The process result.
9201004
@discardableResult
921-
static public func popen(args: String..., environment: [String: String] = ProcessEnv.vars) throws -> ProcessResult {
922-
return try Process.popen(arguments: args, environment: environment)
1005+
static public func popen(
1006+
args: String...,
1007+
environment: [String: String] = ProcessEnv.vars,
1008+
loggingHandler: LoggingHandler? = .none
1009+
) throws -> ProcessResult {
1010+
return try Process.popen(arguments: args, environment: environment, loggingHandler: loggingHandler)
9231011
}
9241012

9251013
/// Execute a subprocess and get its (UTF-8) output if it has a non zero exit.
@@ -928,10 +1016,20 @@ extension Process {
9281016
/// - arguments: The arguments for the subprocess.
9291017
/// - environment: The environment to pass to subprocess. By default the current process environment
9301018
/// will be inherited.
1019+
/// - loggingHandler: Handler for logging messages
9311020
/// - Returns: The process output (stdout + stderr).
9321021
@discardableResult
933-
static public func checkNonZeroExit(arguments: [String], environment: [String: String] = ProcessEnv.vars) throws -> String {
934-
let process = Process(arguments: arguments, environment: environment, outputRedirection: .collect)
1022+
static public func checkNonZeroExit(
1023+
arguments: [String],
1024+
environment: [String: String] = ProcessEnv.vars,
1025+
loggingHandler: LoggingHandler? = .none
1026+
) throws -> String {
1027+
let process = Process(
1028+
arguments: arguments,
1029+
environment: environment,
1030+
outputRedirection: .collect,
1031+
loggingHandler: loggingHandler
1032+
)
9351033
try process.launch()
9361034
let result = try process.waitUntilExit()
9371035
// Throw if there was a non zero termination.
@@ -941,13 +1039,21 @@ extension Process {
9411039
return try result.utf8Output()
9421040
}
9431041

1042+
/// Execute a subprocess and get its (UTF-8) output if it has a non zero exit.
1043+
///
1044+
/// - Parameters:
1045+
/// - arguments: The arguments for the subprocess.
1046+
/// - environment: The environment to pass to subprocess. By default the current process environment
1047+
/// will be inherited.
1048+
/// - loggingHandler: Handler for logging messages
1049+
/// - Returns: The process output (stdout + stderr).
9441050
@discardableResult
945-
static public func checkNonZeroExit(args: String..., environment: [String: String] = ProcessEnv.vars) throws -> String {
946-
return try checkNonZeroExit(arguments: args, environment: environment)
947-
}
948-
949-
public convenience init(args: String..., environment: [String: String] = ProcessEnv.vars, outputRedirection: OutputRedirection = .collect) {
950-
self.init(arguments: args, environment: environment, outputRedirection: outputRedirection)
1051+
static public func checkNonZeroExit(
1052+
args: String...,
1053+
environment: [String: String] = ProcessEnv.vars,
1054+
loggingHandler: LoggingHandler? = .none
1055+
) throws -> String {
1056+
return try checkNonZeroExit(arguments: args, environment: environment, loggingHandler: loggingHandler)
9511057
}
9521058
}
9531059

@@ -1090,3 +1196,12 @@ extension FileHandle: WritableByteStream {
10901196
}
10911197
}
10921198
#endif
1199+
1200+
1201+
extension Process {
1202+
@available(*, deprecated)
1203+
fileprivate static func logToStdout(_ message: String) {
1204+
stdoutStream <<< message <<< "\n"
1205+
stdoutStream.flush()
1206+
}
1207+
}

0 commit comments

Comments
 (0)