diff --git a/.gitignore b/.gitignore index 5e5d5ce..e302df2 100644 --- a/.gitignore +++ b/.gitignore @@ -36,6 +36,7 @@ playground.xcworkspace # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies. # Packages/ .build/ +.swiftpm/xcode # CocoaPods # diff --git a/.swift-version b/.swift-version index bf77d54..ef425ca 100644 --- a/.swift-version +++ b/.swift-version @@ -1 +1 @@ -4.2 +5.2 diff --git a/.travis.yml b/.travis.yml index 7b96a34..9e71e0f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,5 @@ language: objective-c -osx_image: xcode10.1 +osx_image: xcode11.3 branches: only: - master @@ -8,19 +8,19 @@ xcode_workspace: Tentacle.xcworkspace matrix: include: - xcode_scheme: Tentacle-OSX - name: Xcode 10.1 / macOS + name: Xcode 11.3 / macOS env: XCODE_ACTION="build-for-testing test-without-building" - xcode_scheme: Tentacle-iOS - name: Xcode 10.1 / iOS + name: Xcode 11.3 / iOS env: XCODE_ACTION="build-for-testing test-without-building" - xcode_scheme: Tentacle-OSX - name: Xcode 10.2 / macOS + name: Xcode 11.4 / macOS env: XCODE_ACTION="build-for-testing test-without-building" - osx_image: xcode10.2 + osx_image: xcode11.4 - xcode_scheme: Tentacle-iOS - name: Xcode 10.2 / iOS + name: Xcode 11.4 / iOS env: XCODE_ACTION="build-for-testing test-without-building" - osx_image: xcode10.2 + osx_image: xcode11.4 - xcode_scheme: update-test-fixtures env: XCODE_ACTION=build - git: @@ -28,6 +28,7 @@ matrix: script: - swift build - swift test + osx_image: xcode11.4 env: - JOB=SWIFTPM_DARWIN notifications: diff --git a/Cartfile b/Cartfile index e6233eb..fe0cec3 100644 --- a/Cartfile +++ b/Cartfile @@ -1 +1 @@ -github "ReactiveCocoa/ReactiveSwift" ~> 5.0 +github "ReactiveCocoa/ReactiveSwift" ~> 6.2 diff --git a/Cartfile.resolved b/Cartfile.resolved index 8695ba4..f3eabfc 100644 --- a/Cartfile.resolved +++ b/Cartfile.resolved @@ -1,2 +1 @@ -github "ReactiveCocoa/ReactiveSwift" "5.0.0" -github "antitypical/Result" "4.1.0" +github "ReactiveCocoa/ReactiveSwift" "6.2.1" diff --git a/Carthage/Checkouts/ReactiveSwift b/Carthage/Checkouts/ReactiveSwift index e285cea..e27ccdb 160000 --- a/Carthage/Checkouts/ReactiveSwift +++ b/Carthage/Checkouts/ReactiveSwift @@ -1 +1 @@ -Subproject commit e285cea17cca8e23928d1e85a235638184e39ac9 +Subproject commit e27ccdbf4ec36f154b60b91a0d7e0110c4e882cb diff --git a/Package.resolved b/Package.resolved index ccb75a4..501005a 100644 --- a/Package.resolved +++ b/Package.resolved @@ -24,17 +24,8 @@ "repositoryURL": "https://github.com/ReactiveCocoa/ReactiveSwift.git", "state": { "branch": null, - "revision": "e285cea17cca8e23928d1e85a235638184e39ac9", - "version": "5.0.0" - } - }, - { - "package": "Result", - "repositoryURL": "https://github.com/antitypical/Result.git", - "state": { - "branch": null, - "revision": "2ca499ba456795616fbc471561ff1d963e6ae160", - "version": "4.1.0" + "revision": "e27ccdbf4ec36f154b60b91a0d7e0110c4e882cb", + "version": "6.2.1" } } ] diff --git a/Package.swift b/Package.swift index aa37be2..3360a84 100644 --- a/Package.swift +++ b/Package.swift @@ -1,4 +1,4 @@ -// swift-tools-version:4.2 +// swift-tools-version:5.2 import PackageDescription let package = Package( @@ -7,11 +7,11 @@ let package = Package( .library(name: "Tentacle", targets: ["Tentacle"]), ], dependencies: [ - .package(url: "https://github.com/ReactiveCocoa/ReactiveSwift.git", from: "5.0.0"), + .package(url: "https://github.com/ReactiveCocoa/ReactiveSwift.git", from: "6.0.0"), ], targets: [ .target(name: "Tentacle", dependencies: ["ReactiveSwift"]), .testTarget(name: "TentacleTests", dependencies: ["Tentacle"]), ], - swiftLanguageVersions: [.v4_2] + swiftLanguageVersions: [.v5] ) diff --git a/Sources/Tentacle/Client.swift b/Sources/Tentacle/Client.swift index d66897b..f82e86c 100644 --- a/Sources/Tentacle/Client.swift +++ b/Sources/Tentacle/Client.swift @@ -8,7 +8,6 @@ import Foundation import ReactiveSwift -import Result extension URL { internal func url(with queryItems: [URLQueryItem]) -> URL { @@ -34,7 +33,7 @@ extension URL { extension URLSession { /// Returns a producer that will download a file using the given request. The file will be /// deleted after the producer terminates. - internal func downloadFile(_ request: URLRequest) -> SignalProducer { + internal func downloadFile(_ request: URLRequest) -> SignalProducer { return SignalProducer { observer, lifetime in let serialDisposable = SerialDisposable() let handle = lifetime += serialDisposable @@ -47,7 +46,7 @@ extension URLSession { observer.send(value: url) observer.sendCompleted() } else if let error = error { - observer.send(error: AnyError(error)) + observer.send(error: error) } else { fatalError("Request neither succeeded nor failed: \(String(describing: request.url))") } @@ -151,7 +150,7 @@ public final class Client { public func download(asset: Release.Asset) -> SignalProducer { return urlSession .downloadFile(urlRequest(for: asset.apiURL, contentType: Client.DownloadContentType)) - .mapError { Error.networkError($0.error) } + .mapError { Error.networkError($0) } } /// Create a `URLRequest` for the given URL with the given content type. @@ -185,7 +184,7 @@ public final class Client { return urlSession .reactive .data(with: urlRequest(for: request, page: page, perPage: perPage)) - .mapError { Error.networkError($0.error) } + .mapError { Error.networkError($0) } .flatMap(.concat) { data, response -> SignalProducer<(Response, Data), Error> in let response = response as! HTTPURLResponse let headers = response.allHeaderFields as! [String:String] diff --git a/Sources/Tentacle/JSONExtensions.swift b/Sources/Tentacle/JSONExtensions.swift index 48bf90c..dadd9fc 100644 --- a/Sources/Tentacle/JSONExtensions.swift +++ b/Sources/Tentacle/JSONExtensions.swift @@ -7,22 +7,21 @@ // import Foundation -import Result internal func decode(_ payload: Data) -> Result { - return Result(catching: { () -> T in + Result { let decoder = JSONDecoder() decoder.dateDecodingStrategy = .formatted(DateFormatter.iso8601) return try decoder.decode(T.self, from: payload) - }) + }.mapError { $0 as! DecodingError } } internal func decodeList(_ payload: Data) -> Result<[T], DecodingError> { - return Result(catching: { () -> [T] in + Result { () -> [T] in let decoder = JSONDecoder() decoder.dateDecodingStrategy = .formatted(DateFormatter.iso8601) return try decoder.decode([T].self, from: payload) - }) + }.mapError { $0 as! DecodingError } } extension DecodingError.Context: Equatable { diff --git a/Tentacle.xcodeproj/project.pbxproj b/Tentacle.xcodeproj/project.pbxproj index 3fb3621..0b64321 100644 --- a/Tentacle.xcodeproj/project.pbxproj +++ b/Tentacle.xcodeproj/project.pbxproj @@ -150,11 +150,9 @@ 928DF21F1E0E693000E6DE35 /* create-file-sample-response.data in Resources */ = {isa = PBXBuildFile; fileRef = 928DF21D1E0E692600E6DE35 /* create-file-sample-response.data */; }; 928DF2201E0E693100E6DE35 /* create-file-sample-response.data in Resources */ = {isa = PBXBuildFile; fileRef = 928DF21D1E0E692600E6DE35 /* create-file-sample-response.data */; }; 928DF22A1E0E6A1200E6DE35 /* ReactiveSwift.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 928DF2241E0E6A1200E6DE35 /* ReactiveSwift.framework */; }; - 928DF22B1E0E6A1200E6DE35 /* Result.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 928DF2251E0E6A1200E6DE35 /* Result.framework */; }; 928DF22D1E0E6A8000E6DE35 /* FileResponseTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 928DF21B1E0E68D300E6DE35 /* FileResponseTests.swift */; }; 928DF22E1E0E6A8100E6DE35 /* FileResponseTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 928DF21B1E0E68D300E6DE35 /* FileResponseTests.swift */; }; 928DF2381E0E95B600E6DE35 /* ReactiveSwift.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 928DF2321E0E95B600E6DE35 /* ReactiveSwift.framework */; }; - 928DF2391E0E95B600E6DE35 /* Result.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 928DF2331E0E95B600E6DE35 /* Result.framework */; }; 928DF23E1E1117D600E6DE35 /* Sha.swift in Sources */ = {isa = PBXBuildFile; fileRef = 928DF23D1E1117D600E6DE35 /* Sha.swift */; }; 928DF23F1E11187C00E6DE35 /* Sha.swift in Sources */ = {isa = PBXBuildFile; fileRef = 928DF23D1E1117D600E6DE35 /* Sha.swift */; }; 92F0C2BA1E391088004A9889 /* FileTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 92F0C2B91E391088004A9889 /* FileTests.swift */; }; @@ -302,9 +300,7 @@ 928DF21B1E0E68D300E6DE35 /* FileResponseTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FileResponseTests.swift; sourceTree = ""; }; 928DF21D1E0E692600E6DE35 /* create-file-sample-response.data */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "create-file-sample-response.data"; sourceTree = ""; }; 928DF2241E0E6A1200E6DE35 /* ReactiveSwift.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ReactiveSwift.framework; path = "../../../Library/Developer/Xcode/DerivedData/Tentacle-bqioixzqvwloakfnodqjigugjqbv/Build/Products/Debug-iphonesimulator/ReactiveSwift.framework"; sourceTree = ""; }; - 928DF2251E0E6A1200E6DE35 /* Result.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Result.framework; path = "../../../Library/Developer/Xcode/DerivedData/Tentacle-bqioixzqvwloakfnodqjigugjqbv/Build/Products/Debug-iphonesimulator/Result.framework"; sourceTree = ""; }; 928DF2321E0E95B600E6DE35 /* ReactiveSwift.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ReactiveSwift.framework; path = Carthage/Checkouts/ReactiveSwift/build/Debug/ReactiveSwift.framework; sourceTree = SOURCE_ROOT; }; - 928DF2331E0E95B600E6DE35 /* Result.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Result.framework; path = "../../../Library/Developer/Xcode/DerivedData/Tentacle-bqioixzqvwloakfnodqjigugjqbv/Build/Products/Debug/Result.framework"; sourceTree = ""; }; 928DF23D1E1117D600E6DE35 /* Sha.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Sha.swift; sourceTree = ""; }; 92F0C2B91E391088004A9889 /* FileTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FileTests.swift; sourceTree = ""; }; BE0F409F1C89098E00E3B11A /* Fixture.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Fixture.swift; path = Tests/TentacleTests/Fixture.swift; sourceTree = SOURCE_ROOT; }; @@ -351,7 +347,6 @@ buildActionMask = 2147483647; files = ( 928DF22A1E0E6A1200E6DE35 /* ReactiveSwift.framework in Frameworks */, - 928DF22B1E0E6A1200E6DE35 /* Result.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -368,7 +363,6 @@ buildActionMask = 2147483647; files = ( 928DF2381E0E95B600E6DE35 /* ReactiveSwift.framework in Frameworks */, - 928DF2391E0E95B600E6DE35 /* Result.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -513,11 +507,14 @@ BE88E8001C88C6B30034A112 /* Tests */ = { isa = PBXGroup; children = ( + 7A8A9D641E5547F50009DA9E /* BranchTests.swift */, BE2B6A6B1C8B854F0080BFEB /* ClientTests.swift */, 7A1F20EF1D3E86D900F275F8 /* ColorTests.swift */, 7A27887B1D49223B007AC936 /* CommentsTests.swift */, 7A072D8D1DED11C900CFE58F /* ContentTests.swift */, 7A22EDBB1E47CB8900524539 /* EndpointTests.swift */, + 928DF21B1E0E68D300E6DE35 /* FileResponseTests.swift */, + 92F0C2B91E391088004A9889 /* FileTests.swift */, BE0F409F1C89098E00E3B11A /* Fixture.swift */, BE0F40961C8908CB00E3B11A /* Fixtures */, BEB0765E1C8A019A00ABD373 /* GitHubErrorTests.swift */, @@ -529,11 +526,8 @@ BEA86F9C1C9F7E1E0049360B /* RepositoryTests.swift */, BE1E036A1C9AD87F001296C2 /* ResponseTests.swift */, BEA86F991C9F7C230049360B /* ServerTests.swift */, - BECB8AA11CBDDF0F005D70A6 /* UserTests.swift */, - 928DF21B1E0E68D300E6DE35 /* FileResponseTests.swift */, - 92F0C2B91E391088004A9889 /* FileTests.swift */, - 7A8A9D641E5547F50009DA9E /* BranchTests.swift */, BF01A2601EAA63100028ECFC /* TreeTests.swift */, + BECB8AA11CBDDF0F005D70A6 /* UserTests.swift */, ); name = Tests; path = Tests/TentacleTests; @@ -543,9 +537,7 @@ isa = PBXGroup; children = ( 928DF2321E0E95B600E6DE35 /* ReactiveSwift.framework */, - 928DF2331E0E95B600E6DE35 /* Result.framework */, 928DF2241E0E6A1200E6DE35 /* ReactiveSwift.framework */, - 928DF2251E0E6A1200E6DE35 /* Result.framework */, ); name = Frameworks; path = Tentacle; @@ -1027,7 +1019,6 @@ PRODUCT_NAME = Tentacle; SDKROOT = iphoneos; SKIP_INSTALL = YES; - SWIFT_SWIFT3_OBJC_INFERENCE = On; TARGETED_DEVICE_FAMILY = "1,2"; }; name = Debug; @@ -1049,7 +1040,6 @@ SDKROOT = iphoneos; SKIP_INSTALL = YES; SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; - SWIFT_SWIFT3_OBJC_INFERENCE = On; TARGETED_DEVICE_FAMILY = "1,2"; VALIDATE_PRODUCT = YES; }; @@ -1065,7 +1055,6 @@ PRODUCT_BUNDLE_IDENTIFIER = com.diephouse.matt.TentacleiOSTests; PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = iphoneos; - SWIFT_SWIFT3_OBJC_INFERENCE = On; }; name = Debug; }; @@ -1080,7 +1069,6 @@ PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = iphoneos; SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; - SWIFT_SWIFT3_OBJC_INFERENCE = On; VALIDATE_PRODUCT = YES; }; name = Release; diff --git a/Tentacle.xcodeproj/xcshareddata/xcschemes/Tentacle-OSX.xcscheme b/Tentacle.xcodeproj/xcshareddata/xcschemes/Tentacle-OSX.xcscheme index 105973e..9e7a757 100644 --- a/Tentacle.xcodeproj/xcshareddata/xcschemes/Tentacle-OSX.xcscheme +++ b/Tentacle.xcodeproj/xcshareddata/xcschemes/Tentacle-OSX.xcscheme @@ -20,48 +20,6 @@ ReferencedContainer = "container:Tentacle.xcodeproj"> - - - - - - - - - - - - - - - - - - - - + + + + @@ -123,17 +62,6 @@ - - - - - - - - - - - - + + + + @@ -81,17 +76,6 @@ - - - - - - - - - - - - + + - - - - diff --git a/Tests/TentacleTests/ClientTests.swift b/Tests/TentacleTests/ClientTests.swift index 05a809e..d7c5e13 100644 --- a/Tests/TentacleTests/ClientTests.swift +++ b/Tests/TentacleTests/ClientTests.swift @@ -7,34 +7,9 @@ // import ReactiveSwift -import Result import Tentacle import XCTest -public func == (left: Result<[T], Error>, right: Result<[T], Error>) -> Bool { - if let left = left.value, let right = right.value { - return left == right - } else if let left = left.error, let right = right.error { - return left == right - } - return false -} - -public func == (left: Result<[[T]], Error>, right: Result<[[T]], Error>) -> Bool { - if let left = left.value, let right = right.value { - guard left.count == right.count else { return false } - for idx in left.indices { - if left[idx] != right[idx] { - return false - } - } - return true - } else if let left = left.error, let right = right.error { - return left == right - } - return false -} - func ExpectResult (_ producer: SignalProducer<(Response, O), Client.Error>, _ result: Result<[O], Client.Error>, file: StaticString = #file, line: UInt = #line) @@ -156,7 +131,7 @@ class ClientTests: XCTestCase { ) } - func testDownloadAsset() { + func testDownloadAsset() throws { let release: Release = Fixture.Release.MDPSplitView1_0_2.decode()! let asset = release.assets .first { $0.name == "MDPSplitView.framework.zip" }! @@ -167,7 +142,8 @@ class ClientTests: XCTestCase { return try! Data(contentsOf: url) } .single()! - XCTAssertEqual(result.value, Fixture.Release.Asset.MDPSplitView_framework_zip.data) + + XCTAssertEqual(try result.get(), Fixture.Release.Asset.MDPSplitView_framework_zip.data) } func testUserWithLogin() { diff --git a/Tests/TentacleTests/GitHubErrorTests.swift b/Tests/TentacleTests/GitHubErrorTests.swift index 641681a..d2a385a 100644 --- a/Tests/TentacleTests/GitHubErrorTests.swift +++ b/Tests/TentacleTests/GitHubErrorTests.swift @@ -6,7 +6,6 @@ // Copyright © 2016 Matt Diephouse. All rights reserved. // -import Result @testable import Tentacle import XCTest diff --git a/script/cibuild b/script/cibuild index 8477925..f6c5843 100755 --- a/script/cibuild +++ b/script/cibuild @@ -9,7 +9,7 @@ my $buildSettings = qx{xcodebuild -workspace "$WORKSPACE" -scheme "$SCHEME" -sho my @args = ("-workspace", $WORKSPACE, "-scheme", $SCHEME, "-configuration", "Release", split(/\s+/, $ACTION), "CODE_SIGNING_REQUIRED=NO", "CODE_SIGN_IDENTITY=", "ENABLE_TESTABILITY=YES"); if ($buildSettings =~ /\bPLATFORM_NAME = iphoneos/i) { - unshift @args, "-destination", "name=iPhone 6s"; + unshift @args, "-destination", "name=iPhone 11"; unshift @args, "-sdk", "iphonesimulator"; } diff --git a/update-test-fixtures/main.swift b/update-test-fixtures/main.swift index e5d489b..d8a4a19 100644 --- a/update-test-fixtures/main.swift +++ b/update-test-fixtures/main.swift @@ -11,7 +11,6 @@ import Foundation import ReactiveSwift -import Result @testable import Tentacle let baseURL = URL(fileURLWithPath: CommandLine.arguments[1]) @@ -19,8 +18,8 @@ let baseURL = URL(fileURLWithPath: CommandLine.arguments[1]) let fileManager = FileManager.default let client = Client(.dotCom) let session = URLSession.shared -let result = SignalProducer(Fixture.allFixtures) - .flatMap(.concat) { fixture -> SignalProducer<(), AnyError> in +let result = SignalProducer(Fixture.allFixtures) + .flatMap(.concat) { fixture -> SignalProducer<(), Error> in let request = client.urlRequest(for: fixture.url, contentType: fixture.contentType) let dataURL = baseURL.appendingPathComponent(fixture.dataFilename) let responseURL = baseURL.appendingPathComponent(fixture.responseFilename) @@ -55,6 +54,9 @@ let result = SignalProducer(Fixture.allFixtures) } .wait() -if let error = result.error { +switch result { +case .success: + print("Successfully updated text fixtures") +case let .failure(error): print("Error updating fixtures: \(error)") }