Skip to content

Commit d5f8c2b

Browse files
committed
Revert "[Wrangle] Revert noasync annotation. (#392)"
This reverts commit f0e80d1.
1 parent add9e15 commit d5f8c2b

File tree

5 files changed

+243
-6
lines changed

5 files changed

+243
-6
lines changed

Diff for: Sources/TSCBasic/Await.swift

+6
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,16 @@
1414
/// should be passed to the async method's completion handler.
1515
/// - Returns: The value wrapped by the async method's result.
1616
/// - Throws: The error wrapped by the async method's result
17+
#if compiler(>=5.8)
18+
@available(*, noasync)
19+
#endif
1720
public func tsc_await<T, ErrorType>(_ body: (@escaping (Result<T, ErrorType>) -> Void) -> Void) throws -> T {
1821
return try tsc_await(body).get()
1922
}
2023

24+
#if compiler(>=5.8)
25+
@available(*, noasync)
26+
#endif
2127
public func tsc_await<T>(_ body: (@escaping (T) -> Void) -> Void) -> T {
2228
let condition = Condition()
2329
var result: T? = nil

Diff for: Sources/TSCBasic/Process.swift

+131-4
Original file line numberDiff line numberDiff line change
@@ -21,18 +21,20 @@ import Foundation
2121
import TSCLibc
2222
import Dispatch
2323

24+
import _Concurrency
25+
2426
/// Process result data which is available after process termination.
25-
public struct ProcessResult: CustomStringConvertible {
27+
public struct ProcessResult: CustomStringConvertible, Sendable {
2628

27-
public enum Error: Swift.Error {
29+
public enum Error: Swift.Error, Sendable {
2830
/// The output is not a valid UTF8 sequence.
2931
case illegalUTF8Sequence
3032

3133
/// The process had a non zero exit.
3234
case nonZeroExit(ProcessResult)
3335
}
3436

35-
public enum ExitStatus: Equatable {
37+
public enum ExitStatus: Equatable, Sendable {
3638
/// The process was terminated normally with a exit code.
3739
case terminated(code: Int32)
3840
#if os(Windows)
@@ -125,12 +127,18 @@ public struct ProcessResult: CustomStringConvertible {
125127
}
126128
}
127129

130+
#if swift(<5.6)
131+
extension Process: UnsafeSendable {}
132+
#else
133+
extension Process: @unchecked Sendable {}
134+
#endif
135+
128136
/// Process allows spawning new subprocesses and working with them.
129137
///
130138
/// Note: This class is thread safe.
131139
public final class Process {
132140
/// Errors when attempting to invoke a process
133-
public enum Error: Swift.Error {
141+
public enum Error: Swift.Error, Sendable {
134142
/// The program requested to be executed cannot be found on the existing search paths, or is not executable.
135143
case missingExecutableProgram(program: String)
136144

@@ -807,7 +815,29 @@ public final class Process {
807815
#endif // POSIX implementation
808816
}
809817

818+
/// Executes the process I/O state machine, returning the result when finished.
819+
@available(macOS 10.15, iOS 13.0, tvOS 13.0, watchOS 6.0, *)
820+
@discardableResult
821+
public func waitUntilExit() async throws -> ProcessResult {
822+
#if compiler(>=5.6)
823+
return try await withCheckedThrowingContinuation { continuation in
824+
waitUntilExit(continuation.resume(with:))
825+
}
826+
#else
827+
if #available(macOS 12.0, iOS 15.0, tvOS 15.0, watchOS 8.0, *) {
828+
return try await withCheckedThrowingContinuation { continuation in
829+
waitUntilExit(continuation.resume(with:))
830+
}
831+
} else {
832+
preconditionFailure("Unsupported with Swift 5.5 on this OS version")
833+
}
834+
#endif
835+
}
836+
810837
/// Blocks the calling process until the subprocess finishes execution.
838+
#if compiler(>=5.8)
839+
@available(*, noasync)
840+
#endif
811841
@discardableResult
812842
public func waitUntilExit() throws -> ProcessResult {
813843
let group = DispatchGroup()
@@ -938,6 +968,88 @@ public final class Process {
938968
}
939969
}
940970

971+
extension Process {
972+
/// Execute a subprocess and returns the result when it finishes execution
973+
///
974+
/// - Parameters:
975+
/// - arguments: The arguments for the subprocess.
976+
/// - environment: The environment to pass to subprocess. By default the current process environment
977+
/// will be inherited.
978+
/// - loggingHandler: Handler for logging messages
979+
@available(macOS 10.15, *)
980+
static public func popen(
981+
arguments: [String],
982+
environment: [String: String] = ProcessEnv.vars,
983+
loggingHandler: LoggingHandler? = .none
984+
) async throws -> ProcessResult {
985+
let process = Process(
986+
arguments: arguments,
987+
environment: environment,
988+
outputRedirection: .collect,
989+
loggingHandler: loggingHandler
990+
)
991+
try process.launch()
992+
return try await process.waitUntilExit()
993+
}
994+
995+
/// Execute a subprocess and returns the result when it finishes execution
996+
///
997+
/// - Parameters:
998+
/// - args: The arguments for the subprocess.
999+
/// - environment: The environment to pass to subprocess. By default the current process environment
1000+
/// will be inherited.
1001+
/// - loggingHandler: Handler for logging messages
1002+
@available(macOS 10.15, *)
1003+
static public func popen(
1004+
args: String...,
1005+
environment: [String: String] = ProcessEnv.vars,
1006+
loggingHandler: LoggingHandler? = .none
1007+
) async throws -> ProcessResult {
1008+
try await popen(arguments: args, environment: environment, loggingHandler: loggingHandler)
1009+
}
1010+
1011+
/// Execute a subprocess and get its (UTF-8) output if it has a non zero exit.
1012+
///
1013+
/// - Parameters:
1014+
/// - arguments: The arguments for the subprocess.
1015+
/// - environment: The environment to pass to subprocess. By default the current process environment
1016+
/// will be inherited.
1017+
/// - loggingHandler: Handler for logging messages
1018+
/// - Returns: The process output (stdout + stderr).
1019+
@available(macOS 10.15, *)
1020+
@discardableResult
1021+
static public func checkNonZeroExit(
1022+
arguments: [String],
1023+
environment: [String: String] = ProcessEnv.vars,
1024+
loggingHandler: LoggingHandler? = .none
1025+
) async throws -> String {
1026+
let result = try await popen(arguments: arguments, environment: environment, loggingHandler: loggingHandler)
1027+
// Throw if there was a non zero termination.
1028+
guard result.exitStatus == .terminated(code: 0) else {
1029+
throw ProcessResult.Error.nonZeroExit(result)
1030+
}
1031+
return try result.utf8Output()
1032+
}
1033+
1034+
/// Execute a subprocess and get its (UTF-8) output if it has a non zero exit.
1035+
///
1036+
/// - Parameters:
1037+
/// - args: The arguments for the subprocess.
1038+
/// - environment: The environment to pass to subprocess. By default the current process environment
1039+
/// will be inherited.
1040+
/// - loggingHandler: Handler for logging messages
1041+
/// - Returns: The process output (stdout + stderr).
1042+
@available(macOS 10.15, *)
1043+
@discardableResult
1044+
static public func checkNonZeroExit(
1045+
args: String...,
1046+
environment: [String: String] = ProcessEnv.vars,
1047+
loggingHandler: LoggingHandler? = .none
1048+
) async throws -> String {
1049+
try await checkNonZeroExit(arguments: args, environment: environment, loggingHandler: loggingHandler)
1050+
}
1051+
}
1052+
9411053
extension Process {
9421054
/// Execute a subprocess and calls completion block when it finishes execution
9431055
///
@@ -948,6 +1060,9 @@ extension Process {
9481060
/// - loggingHandler: Handler for logging messages
9491061
/// - queue: Queue to use for callbacks
9501062
/// - completion: A completion handler to return the process result
1063+
#if compiler(>=5.8)
1064+
@available(*, noasync)
1065+
#endif
9511066
static public func popen(
9521067
arguments: [String],
9531068
environment: [String: String] = ProcessEnv.vars,
@@ -982,6 +1097,9 @@ extension Process {
9821097
/// will be inherited.
9831098
/// - loggingHandler: Handler for logging messages
9841099
/// - Returns: The process result.
1100+
#if compiler(>=5.8)
1101+
@available(*, noasync)
1102+
#endif
9851103
@discardableResult
9861104
static public func popen(
9871105
arguments: [String],
@@ -1006,6 +1124,9 @@ extension Process {
10061124
/// will be inherited.
10071125
/// - loggingHandler: Handler for logging messages
10081126
/// - Returns: The process result.
1127+
#if compiler(>=5.8)
1128+
@available(*, noasync)
1129+
#endif
10091130
@discardableResult
10101131
static public func popen(
10111132
args: String...,
@@ -1023,6 +1144,9 @@ extension Process {
10231144
/// will be inherited.
10241145
/// - loggingHandler: Handler for logging messages
10251146
/// - Returns: The process output (stdout + stderr).
1147+
#if compiler(>=5.8)
1148+
@available(*, noasync)
1149+
#endif
10261150
@discardableResult
10271151
static public func checkNonZeroExit(
10281152
arguments: [String],
@@ -1052,6 +1176,9 @@ extension Process {
10521176
/// will be inherited.
10531177
/// - loggingHandler: Handler for logging messages
10541178
/// - Returns: The process output (stdout + stderr).
1179+
#if compiler(>=5.8)
1180+
@available(*, noasync)
1181+
#endif
10551182
@discardableResult
10561183
static public func checkNonZeroExit(
10571184
args: String...,

Diff for: Sources/TSCBasic/ProcessSet.swift

+3
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,9 @@ public final class ProcessSet {
6464
/// Terminate all the processes. This method blocks until all processes in the set are terminated.
6565
///
6666
/// A process set cannot be used once it has been asked to terminate.
67+
#if compiler(>=5.8)
68+
@available(*, noasync)
69+
#endif
6770
public func terminate() {
6871
// Mark a process set as cancelled.
6972
serialQueue.sync {

Diff for: Sources/TSCBasic/WritableByteStream.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -349,7 +349,7 @@ public final class ThreadSafeOutputByteStream: WritableByteStream {
349349
}
350350

351351

352-
#if swift(<5.7)
352+
#if swift(<5.6)
353353
extension ThreadSafeOutputByteStream: UnsafeSendable {}
354354
#else
355355
extension ThreadSafeOutputByteStream: @unchecked Sendable {}

0 commit comments

Comments
 (0)