Skip to content

Commit edc19d3

Browse files
authored
Merge pull request #18 from hartbit/sync-it-up
Sync with SwiftPM trunk
2 parents a7654db + 15d4526 commit edc19d3

File tree

5 files changed

+61
-161
lines changed

5 files changed

+61
-161
lines changed

Sources/TSCBasic/Process.swift

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -47,11 +47,11 @@ public struct ProcessResult: CustomStringConvertible {
4747

4848
/// The output bytes of the process. Available only if the process was
4949
/// asked to redirect its output and no stdout output closure was set.
50-
public let output: Result<[UInt8], AnyError>
50+
public let output: Result<[UInt8], Swift.Error>
5151

5252
/// The output bytes of the process. Available only if the process was
5353
/// asked to redirect its output and no stderr output closure was set.
54-
public let stderrOutput: Result<[UInt8], AnyError>
54+
public let stderrOutput: Result<[UInt8], Swift.Error>
5555

5656
/// Create an instance using a POSIX process exit status code and output result.
5757
///
@@ -60,8 +60,8 @@ public struct ProcessResult: CustomStringConvertible {
6060
arguments: [String],
6161
environment: [String: String],
6262
exitStatusCode: Int32,
63-
output: Result<[UInt8], AnyError>,
64-
stderrOutput: Result<[UInt8], AnyError>
63+
output: Result<[UInt8], Swift.Error>,
64+
stderrOutput: Result<[UInt8], Swift.Error>
6565
) {
6666
let exitStatus: ExitStatus
6767
#if os(Windows)
@@ -83,8 +83,8 @@ public struct ProcessResult: CustomStringConvertible {
8383
arguments: [String],
8484
environment: [String: String],
8585
exitStatus: ExitStatus,
86-
output: Result<[UInt8], AnyError>,
87-
stderrOutput: Result<[UInt8], AnyError>
86+
output: Result<[UInt8], Swift.Error>,
87+
stderrOutput: Result<[UInt8], Swift.Error>
8888
) {
8989
self.arguments = arguments
9090
self.environment = environment
@@ -207,10 +207,10 @@ public final class Process: ObjectIdentifierProtocol {
207207
#endif
208208

209209
/// If redirected, stdout result and reference to the thread reading the output.
210-
private var stdout: (result: Result<[UInt8], AnyError>, thread: Thread?) = (.success([]), nil)
210+
private var stdout: (result: Result<[UInt8], Swift.Error>, thread: Thread?) = (.success([]), nil)
211211

212212
/// If redirected, stderr result and reference to the thread reading the output.
213-
private var stderr: (result: Result<[UInt8], AnyError>, thread: Thread?) = (.success([]), nil)
213+
private var stderr: (result: Result<[UInt8], Swift.Error>, thread: Thread?) = (.success([]), nil)
214214

215215
/// Queue to protect concurrent reads.
216216
private let serialQueue = DispatchQueue(label: "org.swift.swiftpm.process")
@@ -449,6 +449,7 @@ public final class Process: ObjectIdentifierProtocol {
449449

450450
let executionResult = ProcessResult(
451451
arguments: arguments,
452+
environment: environment,
452453
exitStatusCode: p.terminationStatus,
453454
output: stdout.result,
454455
stderrOutput: stderr.result
@@ -495,7 +496,7 @@ public final class Process: ObjectIdentifierProtocol {
495496
/// Reads the given fd and returns its result.
496497
///
497498
/// Closes the fd before returning.
498-
private func readOutput(onFD fd: Int32, outputClosure: OutputClosure?) -> Result<[UInt8], AnyError> {
499+
private func readOutput(onFD fd: Int32, outputClosure: OutputClosure?) -> Result<[UInt8], Swift.Error> {
499500
// Read all of the data from the output pipe.
500501
let N = 4096
501502
var buf = [UInt8](repeating: 0, count: N + 1)
@@ -526,7 +527,7 @@ public final class Process: ObjectIdentifierProtocol {
526527
// Close the read end of the output pipe.
527528
close(fd)
528529
// Construct the output result.
529-
return error.map(Result.init) ?? .success(out)
530+
return error.map(Result.failure) ?? .success(out)
530531
}
531532
#endif
532533

Sources/TSCBasic/Result.swift

Lines changed: 7 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -8,22 +8,13 @@
88
See http://swift.org/CONTRIBUTORS.txt for Swift project authors
99
*/
1010

11-
/// A type erased error enum.
12-
public struct AnyError: Swift.Error, CustomStringConvertible {
13-
/// The underlying error.
14-
public let underlyingError: Swift.Error
15-
16-
public init(_ error: Swift.Error) {
17-
// If we already have any error, don't nest it.
18-
if case let error as AnyError = error {
19-
self = error
20-
} else {
21-
self.underlyingError = error
22-
}
23-
}
24-
25-
public var description: String {
26-
return String(describing: underlyingError)
11+
extension Result where Failure == Error {
12+
public func tryMap<NewSuccess>(_ closure: (Success) throws -> NewSuccess) -> Result<NewSuccess, Error> {
13+
flatMap({ value in
14+
Result<NewSuccess, Error>(catching: {
15+
try closure(value)
16+
})
17+
})
2718
}
2819
}
2920

@@ -39,39 +30,6 @@ public struct StringError: Equatable, Codable, CustomStringConvertible, Error {
3930
}
4031
}
4132

42-
// AnyError specific helpers.
43-
extension Result where Failure == AnyError {
44-
/// Initialise with something that throws AnyError.
45-
public init(anyError body: () throws -> Success) {
46-
do {
47-
self = .success(try body())
48-
} catch {
49-
self = .failure(AnyError(error))
50-
}
51-
}
52-
53-
/// Initialise with an error, it will be automatically converted to AnyError.
54-
public init(_ error: Swift.Error) {
55-
self = .failure(AnyError(error))
56-
}
57-
58-
/// Evaluates the given throwing closure when this Result instance has a value.
59-
///
60-
/// The final result will either be the transformed value or any error thrown by the closure.
61-
public func mapAny<U>(_ transform: (Success) throws -> U) -> Result<U, AnyError> {
62-
switch self {
63-
case .success(let value):
64-
do {
65-
return Result<U, AnyError>.success(try transform(value))
66-
} catch {
67-
return Result<U, AnyError>(error)
68-
}
69-
case .failure(let error):
70-
return Result<U, AnyError>(error)
71-
}
72-
}
73-
}
74-
7533
extension Result where Failure == StringError {
7634
/// Create an instance of Result<Value, StringError>.
7735
///

Tests/TSCBasicTests/AwaitTests.swift

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,15 @@ class AwaitTests: XCTestCase {
1919
case error
2020
}
2121

22-
func async(_ param: String, _ completion: @escaping (Result<String, AnyError>) -> Void) {
22+
func async(_ param: String, _ completion: @escaping (Result<String, Error>) -> Void) {
2323
DispatchQueue.global().async {
2424
completion(.success(param))
2525
}
2626
}
2727

28-
func throwingAsync(_ param: String, _ completion: @escaping (Result<String, AnyError>) -> Void) {
28+
func throwingAsync(_ param: String, _ completion: @escaping (Result<String, Error>) -> Void) {
2929
DispatchQueue.global().async {
30-
completion(Result(DummyError.error))
30+
completion(.failure(DummyError.error))
3131
}
3232
}
3333

@@ -38,8 +38,8 @@ class AwaitTests: XCTestCase {
3838
do {
3939
let value = try await { throwingAsync("Hi", $0) }
4040
XCTFail("Unexpected success \(value)")
41-
} catch let error as AnyError {
42-
XCTAssertEqual(error.underlyingError as? DummyError, DummyError.error)
41+
} catch {
42+
XCTAssertEqual(error as? DummyError, DummyError.error)
4343
}
4444
}
4545
}

Tests/TSCBasicTests/ResultTests.swift

Lines changed: 37 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -13,113 +13,55 @@ import XCTest
1313
import TSCBasic
1414
import TSCTestSupport
1515

16-
private enum DummyError: Swift.Error {
16+
private enum DummyError: Error, Equatable {
1717
case somethingWentWrong
1818
}
1919

20-
private enum OtherDummyError: Swift.Error {
20+
private enum OtherDummyError: Error, Equatable {
2121
case somethingElseWentWrong
2222
case andYetAnotherThingToGoWrong
2323
}
2424

2525
class ResultTests: XCTestCase {
26-
27-
func testAnyError() {
28-
func doSomething(right: Bool) -> Result<String, AnyError> {
29-
if right {
30-
return .success("All OK.")
31-
}
32-
return Result(DummyError.somethingWentWrong)
33-
}
34-
35-
// Success.
36-
switch doSomething(right: true) {
37-
case .success(let string):
38-
XCTAssertEqual(string, "All OK.")
39-
case .failure(let error):
40-
XCTFail("Unexpected failure: \(error)")
41-
}
42-
43-
// Error.
44-
switch doSomething(right: false) {
45-
case .success(let string):
46-
XCTFail("Unexpected success: \(string)")
47-
case .failure(let error):
48-
XCTAssertEqual(error.underlyingError as? DummyError, DummyError.somethingWentWrong)
49-
}
50-
51-
do {
52-
// Create an any error and check it doesn't nest.
53-
let error = AnyError(DummyError.somethingWentWrong)
54-
XCTAssertEqual(error.underlyingError as? DummyError, DummyError.somethingWentWrong)
55-
let nested = AnyError(error)
56-
XCTAssertEqual(nested.underlyingError as? DummyError, DummyError.somethingWentWrong)
57-
58-
// Check can create result directly from error.
59-
let result: Result<String, AnyError> = Result(DummyError.somethingWentWrong)
60-
if case let .failure(resultError) = result {
61-
XCTAssertEqual(resultError.underlyingError as? DummyError, DummyError.somethingWentWrong)
62-
} else {
63-
XCTFail("Wrong result value \(result)")
64-
}
65-
}
66-
67-
do {
68-
// Check any error closure initializer.
69-
func throwing() throws -> String {
70-
throw DummyError.somethingWentWrong
71-
}
72-
let result = Result(anyError: { try throwing() })
73-
if case let .failure(resultError) = result {
74-
XCTAssertEqual(resultError.underlyingError as? DummyError, DummyError.somethingWentWrong)
75-
} else {
76-
XCTFail("Wrong result value \(result)")
77-
}
78-
}
26+
func testTryMap() {
27+
let result1 = Result<Int, Error>.success(1).tryMap({ $0 + 1 })
28+
XCTAssertEqual(result1.success, 2)
29+
30+
let result2 = Result<Int, Error>.failure(DummyError.somethingWentWrong).tryMap({ (value: Int) -> Int in
31+
XCTFail("should not reach here")
32+
return value
33+
})
34+
XCTAssertEqual(result2.failure as? DummyError, DummyError.somethingWentWrong)
35+
36+
let result3 = Result<Int, Error>.success(1).tryMap({ (value: Int) -> Int in
37+
throw OtherDummyError.somethingElseWentWrong
38+
})
39+
XCTAssertEqual(result3.failure as? OtherDummyError, OtherDummyError.somethingElseWentWrong)
40+
41+
let result4 = Result<Int, Error>.failure(DummyError.somethingWentWrong).tryMap({ (value: Int) -> Int in
42+
XCTFail("should not reach here")
43+
throw OtherDummyError.somethingElseWentWrong
44+
})
45+
XCTAssertEqual(result4.failure as? DummyError, DummyError.somethingWentWrong)
7946
}
47+
}
8048

81-
func testMapAny() throws {
82-
func throwing(_ shouldThrow: Bool) throws -> String {
83-
if shouldThrow {
84-
throw DummyError.somethingWentWrong
85-
}
86-
return " World"
87-
}
88-
89-
// We should be able to map when we have value in result and our closure doesn't throw.
90-
let success = Result<String, AnyError>.success("Hello").mapAny { value -> String in
91-
let second = try throwing(false)
92-
return value + second
93-
}
94-
XCTAssertEqual(try success.get(), "Hello World")
95-
96-
// We don't have a value, closure shouldn't matter.
97-
let failure1 = Result<String, AnyError>(DummyError.somethingWentWrong).mapAny { value -> String in
98-
let second = try throwing(false)
99-
return value + second
100-
}
101-
XCTAssertThrowsAny(DummyError.somethingWentWrong) {
102-
_ = try failure1.get()
103-
}
104-
105-
// We have a value, but our closure throws.
106-
let failure2 = Result<String, AnyError>.success("Hello").mapAny { value -> String in
107-
let second = try throwing(true)
108-
return value + second
109-
}
110-
XCTAssertThrowsAny(DummyError.somethingWentWrong) {
111-
_ = try failure2.get()
49+
extension Result {
50+
var success: Success? {
51+
switch self {
52+
case .success(let success):
53+
return success
54+
case .failure:
55+
return nil
11256
}
11357
}
114-
}
11558

116-
public func XCTAssertThrowsAny<T: Swift.Error>(_ expectedError: T, file: StaticString = #file, line: UInt = #line, _ body: () throws -> ()) where T: Equatable {
117-
do {
118-
try body()
119-
XCTFail("body completed successfully", file: file, line: line)
120-
} catch let error as AnyError {
121-
XCTAssertEqual(error.underlyingError as? T, expectedError, file: file, line: line)
122-
} catch {
123-
XCTFail("unexpected error thrown", file: file, line: line)
59+
var failure: Failure? {
60+
switch self {
61+
case .success:
62+
return nil
63+
case .failure(let error):
64+
return error
65+
}
12466
}
12567
}

Tests/TSCBasicTests/XCTestManifests.swift

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -343,8 +343,7 @@ extension ResultTests {
343343
// `swift test --generate-linuxmain`
344344
// to regenerate.
345345
static let __allTests__ResultTests = [
346-
("testAnyError", testAnyError),
347-
("testMapAny", testMapAny),
346+
("testTryMap", testTryMap),
348347
]
349348
}
350349

0 commit comments

Comments
 (0)