From b3ccc77dcbfe19cd91aadc86befd12bbe24b29ce Mon Sep 17 00:00:00 2001 From: Sho Ikeda Date: Sat, 23 Sep 2017 10:20:37 +0900 Subject: [PATCH] [gardening] Extract Dependency into its own file --- Carthage.xcodeproj/project.pbxproj | 4 + Source/CarthageKit/Cartfile.swift | 196 --------------------------- Source/CarthageKit/Dependency.swift | 197 ++++++++++++++++++++++++++++ 3 files changed, 201 insertions(+), 196 deletions(-) create mode 100644 Source/CarthageKit/Dependency.swift diff --git a/Carthage.xcodeproj/project.pbxproj b/Carthage.xcodeproj/project.pbxproj index 8bce3f4214..65f57a75e7 100644 --- a/Carthage.xcodeproj/project.pbxproj +++ b/Carthage.xcodeproj/project.pbxproj @@ -53,6 +53,7 @@ CDB099241E6DC2D40030B4A8 /* ScannableError.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDB099231E6DC2D40030B4A8 /* ScannableError.swift */; }; CDBE654C1F4BF0040060D94E /* Submodule.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDBE654B1F4BF0040060D94E /* Submodule.swift */; }; CDCE1CC41C170E8A00B2ED88 /* TestResolvedCartfile.resolved in Resources */ = {isa = PBXBuildFile; fileRef = CDCE1CC21C170E8100B2ED88 /* TestResolvedCartfile.resolved */; }; + CDD7CF791F75ED88000E0EA5 /* Dependency.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDD7CF781F75ED88000E0EA5 /* Dependency.swift */; }; CDE559291E12263A00ED7F5F /* BuildSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDE559281E12263A00ED7F5F /* BuildSettings.swift */; }; CDF94D951E71144300200486 /* DuplicateDependency.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDF94D941E71144300200486 /* DuplicateDependency.swift */; }; CDF9D3711CF1E54200DF5A6F /* BuildOptions.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDF9D3701CF1E54200DF5A6F /* BuildOptions.swift */; }; @@ -214,6 +215,7 @@ CDB099231E6DC2D40030B4A8 /* ScannableError.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ScannableError.swift; sourceTree = ""; }; CDBE654B1F4BF0040060D94E /* Submodule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Submodule.swift; sourceTree = ""; }; CDCE1CC21C170E8100B2ED88 /* TestResolvedCartfile.resolved */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = TestResolvedCartfile.resolved; sourceTree = ""; }; + CDD7CF781F75ED88000E0EA5 /* Dependency.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Dependency.swift; sourceTree = ""; }; CDE559281E12263A00ED7F5F /* BuildSettings.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BuildSettings.swift; sourceTree = ""; }; CDF94D941E71144300200486 /* DuplicateDependency.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DuplicateDependency.swift; sourceTree = ""; }; CDF9D3701CF1E54200DF5A6F /* BuildOptions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BuildOptions.swift; sourceTree = ""; }; @@ -496,6 +498,7 @@ D0D1218F19E88A15005E4BAA /* Cartfile.swift */, CD43D9D91F41640E00CD60F6 /* CarthageKitVersion.swift */, A1411ED51EFC1BFD0060461F /* Constants.swift */, + CDD7CF781F75ED88000E0EA5 /* Dependency.swift */, CDF94D941E71144300200486 /* DuplicateDependency.swift */, D0AAAB4919FAEDB4007B24B3 /* Errors.swift */, D074EDC41A049283001DE082 /* FrameworkExtensions.swift */, @@ -813,6 +816,7 @@ D0AAAB4A19FAEDB4007B24B3 /* Errors.swift in Sources */, D0DE89441A0F2D9B0030A3EC /* Scannable.swift in Sources */, F162F3421D63D8A900809D7E /* VersionFile.swift in Sources */, + CDD7CF791F75ED88000E0EA5 /* Dependency.swift in Sources */, BF7A1A0B1E3A7AE9008CBCC5 /* BinaryProject.swift in Sources */, D01D82D71A10160700F0DD94 /* Resolver.swift in Sources */, CDB099241E6DC2D40030B4A8 /* ScannableError.swift in Sources */, diff --git a/Source/CarthageKit/Cartfile.swift b/Source/CarthageKit/Cartfile.swift index ab50d9f83d..6a4507963e 100644 --- a/Source/CarthageKit/Cartfile.swift +++ b/Source/CarthageKit/Cartfile.swift @@ -1,7 +1,5 @@ import Foundation import Result -import ReactiveSwift -import Tentacle /// The relative path to a project's checked out dependencies. public let carthageProjectCheckoutsPath = "Carthage/Checkouts" @@ -164,197 +162,3 @@ extension ResolvedCartfile: CustomStringConvertible { .joined(separator: "") } } - -/// Uniquely identifies a project that can be used as a dependency. -public enum Dependency { - /// A repository hosted on GitHub.com or GitHub Enterprise. - case gitHub(Server, Repository) - - /// An arbitrary Git repository. - case git(GitURL) - - /// A binary-only framework - case binary(URL) - - /// The unique, user-visible name for this project. - public var name: String { - switch self { - case let .gitHub(_, repo): - return repo.name - - case let .git(url): - return url.name ?? url.urlString - - case let .binary(url): - return url.lastPathComponent.stripping(suffix: ".json") - } - } - - /// The path at which this project will be checked out, relative to the - /// working directory of the main project. - public var relativePath: String { - return (carthageProjectCheckoutsPath as NSString).appendingPathComponent(name) - } -} - -extension Dependency { - fileprivate init(gitURL: GitURL) { - let githubHostIdentifier = "github.com" - let urlString = gitURL.urlString - - if urlString.contains(githubHostIdentifier) { - let gitbubHostScanner = Scanner(string: urlString) - - gitbubHostScanner.scanUpTo(githubHostIdentifier, into:nil) - gitbubHostScanner.scanString(githubHostIdentifier, into: nil) - - // find an SCP or URL path separator - let separatorFound = (gitbubHostScanner.scanString("/", into: nil) || gitbubHostScanner.scanString(":", into: nil)) && !gitbubHostScanner.isAtEnd - - let startOfOwnerAndNameSubstring = gitbubHostScanner.scanLocation - - if separatorFound && startOfOwnerAndNameSubstring <= urlString.utf16.count { - let ownerAndNameSubstring = urlString[urlString.index(urlString.startIndex, offsetBy: startOfOwnerAndNameSubstring).. Bool { - switch (lhs, rhs) { - case let (.gitHub(left), .gitHub(right)): - return left == right - - case let (.git(left), .git(right)): - return left == right - - case let (.binary(left), .binary(right)): - return left == right - - default: - return false - } - } - - public static func < (_ lhs: Dependency, _ rhs: Dependency) -> Bool { - return lhs.name.caseInsensitiveCompare(rhs.name) == .orderedAscending - } -} - -extension Dependency: Hashable { - public var hashValue: Int { - switch self { - case let .gitHub(server, repo): - return server.hashValue ^ repo.hashValue - - case let .git(url): - return url.hashValue - - case let .binary(url): - return url.hashValue - } - } -} - -extension Dependency: Scannable { - /// Attempts to parse a Dependency. - public static func from(_ scanner: Scanner) -> Result { - let parser: (String) -> Result - - if scanner.scanString("github", into: nil) { - parser = { repoIdentifier in - return Repository.fromIdentifier(repoIdentifier).map { self.gitHub($0, $1) } - } - } else if scanner.scanString("git", into: nil) { - parser = { urlString in - - return .success(Dependency(gitURL: GitURL(urlString))) - } - } else if scanner.scanString("binary", into: nil) { - parser = { urlString in - if let url = URL(string: urlString) { - if url.scheme == "https" || url.scheme == "file" { - return .success(self.binary(url)) - } else { - return .failure(ScannableError(message: "non-https, non-file URL found for dependency type `binary`", currentLine: scanner.currentLine)) - } - } else { - return .failure(ScannableError(message: "invalid URL found for dependency type `binary`", currentLine: scanner.currentLine)) - } - } - } else { - return .failure(ScannableError(message: "unexpected dependency type", currentLine: scanner.currentLine)) - } - - if !scanner.scanString("\"", into: nil) { - return .failure(ScannableError(message: "expected string after dependency type", currentLine: scanner.currentLine)) - } - - var address: NSString? - if !scanner.scanUpTo("\"", into: &address) || !scanner.scanString("\"", into: nil) { - return .failure(ScannableError(message: "empty or unterminated string after dependency type", currentLine: scanner.currentLine)) - } - - if let address = address { - return parser(address as String) - } else { - return .failure(ScannableError(message: "empty string after dependency type", currentLine: scanner.currentLine)) - } - } -} - -extension Dependency: CustomStringConvertible { - public var description: String { - switch self { - case let .gitHub(server, repo): - let repoDescription: String - switch server { - case .dotCom: - repoDescription = "\(repo.owner)/\(repo.name)" - - case .enterprise: - repoDescription = "\(server.url(for: repo))" - } - return "github \"\(repoDescription)\"" - - case let .git(url): - return "git \"\(url)\"" - - case let .binary(url): - return "binary \"\(url.absoluteString)\"" - } - } -} - -extension Dependency { - /// Returns the URL that the dependency's remote repository exists at. - func gitURL(preferHTTPS: Bool) -> GitURL? { - switch self { - case let .gitHub(server, repository): - if preferHTTPS { - return server.httpsURL(for: repository) - } else { - return server.sshURL(for: repository) - } - - case let .git(url): - return url - - case .binary: - return nil - } - } -} diff --git a/Source/CarthageKit/Dependency.swift b/Source/CarthageKit/Dependency.swift new file mode 100644 index 0000000000..73502a47e4 --- /dev/null +++ b/Source/CarthageKit/Dependency.swift @@ -0,0 +1,197 @@ +import Foundation +import Result +import Tentacle + +/// Uniquely identifies a project that can be used as a dependency. +public enum Dependency { + /// A repository hosted on GitHub.com or GitHub Enterprise. + case gitHub(Server, Repository) + + /// An arbitrary Git repository. + case git(GitURL) + + /// A binary-only framework + case binary(URL) + + /// The unique, user-visible name for this project. + public var name: String { + switch self { + case let .gitHub(_, repo): + return repo.name + + case let .git(url): + return url.name ?? url.urlString + + case let .binary(url): + return url.lastPathComponent.stripping(suffix: ".json") + } + } + + /// The path at which this project will be checked out, relative to the + /// working directory of the main project. + public var relativePath: String { + return (carthageProjectCheckoutsPath as NSString).appendingPathComponent(name) + } +} + +extension Dependency { + fileprivate init(gitURL: GitURL) { + let githubHostIdentifier = "github.com" + let urlString = gitURL.urlString + + if urlString.contains(githubHostIdentifier) { + let gitbubHostScanner = Scanner(string: urlString) + + gitbubHostScanner.scanUpTo(githubHostIdentifier, into:nil) + gitbubHostScanner.scanString(githubHostIdentifier, into: nil) + + // find an SCP or URL path separator + let separatorFound = (gitbubHostScanner.scanString("/", into: nil) || gitbubHostScanner.scanString(":", into: nil)) && !gitbubHostScanner.isAtEnd + + let startOfOwnerAndNameSubstring = gitbubHostScanner.scanLocation + + if separatorFound && startOfOwnerAndNameSubstring <= urlString.utf16.count { + let ownerAndNameSubstring = urlString[urlString.index(urlString.startIndex, offsetBy: startOfOwnerAndNameSubstring).. Bool { + switch (lhs, rhs) { + case let (.gitHub(left), .gitHub(right)): + return left == right + + case let (.git(left), .git(right)): + return left == right + + case let (.binary(left), .binary(right)): + return left == right + + default: + return false + } + } + + public static func < (_ lhs: Dependency, _ rhs: Dependency) -> Bool { + return lhs.name.caseInsensitiveCompare(rhs.name) == .orderedAscending + } +} + +extension Dependency: Hashable { + public var hashValue: Int { + switch self { + case let .gitHub(server, repo): + return server.hashValue ^ repo.hashValue + + case let .git(url): + return url.hashValue + + case let .binary(url): + return url.hashValue + } + } +} + +extension Dependency: Scannable { + /// Attempts to parse a Dependency. + public static func from(_ scanner: Scanner) -> Result { + let parser: (String) -> Result + + if scanner.scanString("github", into: nil) { + parser = { repoIdentifier in + return Repository.fromIdentifier(repoIdentifier).map { self.gitHub($0, $1) } + } + } else if scanner.scanString("git", into: nil) { + parser = { urlString in + + return .success(Dependency(gitURL: GitURL(urlString))) + } + } else if scanner.scanString("binary", into: nil) { + parser = { urlString in + if let url = URL(string: urlString) { + if url.scheme == "https" || url.scheme == "file" { + return .success(self.binary(url)) + } else { + return .failure(ScannableError(message: "non-https, non-file URL found for dependency type `binary`", currentLine: scanner.currentLine)) + } + } else { + return .failure(ScannableError(message: "invalid URL found for dependency type `binary`", currentLine: scanner.currentLine)) + } + } + } else { + return .failure(ScannableError(message: "unexpected dependency type", currentLine: scanner.currentLine)) + } + + if !scanner.scanString("\"", into: nil) { + return .failure(ScannableError(message: "expected string after dependency type", currentLine: scanner.currentLine)) + } + + var address: NSString? + if !scanner.scanUpTo("\"", into: &address) || !scanner.scanString("\"", into: nil) { + return .failure(ScannableError(message: "empty or unterminated string after dependency type", currentLine: scanner.currentLine)) + } + + if let address = address { + return parser(address as String) + } else { + return .failure(ScannableError(message: "empty string after dependency type", currentLine: scanner.currentLine)) + } + } +} + +extension Dependency: CustomStringConvertible { + public var description: String { + switch self { + case let .gitHub(server, repo): + let repoDescription: String + switch server { + case .dotCom: + repoDescription = "\(repo.owner)/\(repo.name)" + + case .enterprise: + repoDescription = "\(server.url(for: repo))" + } + return "github \"\(repoDescription)\"" + + case let .git(url): + return "git \"\(url)\"" + + case let .binary(url): + return "binary \"\(url.absoluteString)\"" + } + } +} + +extension Dependency { + /// Returns the URL that the dependency's remote repository exists at. + func gitURL(preferHTTPS: Bool) -> GitURL? { + switch self { + case let .gitHub(server, repository): + if preferHTTPS { + return server.httpsURL(for: repository) + } else { + return server.sshURL(for: repository) + } + + case let .git(url): + return url + + case .binary: + return nil + } + } +}