Skip to content

Commit

Permalink
[gardening] Extract Dependency into its own file
Browse files Browse the repository at this point in the history
  • Loading branch information
ikesyo committed Sep 23, 2017
1 parent 1cae9ac commit b3ccc77
Show file tree
Hide file tree
Showing 3 changed files with 201 additions and 196 deletions.
4 changes: 4 additions & 0 deletions Carthage.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -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 */; };
Expand Down Expand Up @@ -214,6 +215,7 @@
CDB099231E6DC2D40030B4A8 /* ScannableError.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ScannableError.swift; sourceTree = "<group>"; };
CDBE654B1F4BF0040060D94E /* Submodule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Submodule.swift; sourceTree = "<group>"; };
CDCE1CC21C170E8100B2ED88 /* TestResolvedCartfile.resolved */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = TestResolvedCartfile.resolved; sourceTree = "<group>"; };
CDD7CF781F75ED88000E0EA5 /* Dependency.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Dependency.swift; sourceTree = "<group>"; };
CDE559281E12263A00ED7F5F /* BuildSettings.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BuildSettings.swift; sourceTree = "<group>"; };
CDF94D941E71144300200486 /* DuplicateDependency.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DuplicateDependency.swift; sourceTree = "<group>"; };
CDF9D3701CF1E54200DF5A6F /* BuildOptions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BuildOptions.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -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 */,
Expand Down Expand Up @@ -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 */,
Expand Down
196 changes: 0 additions & 196 deletions Source/CarthageKit/Cartfile.swift
Original file line number Diff line number Diff line change
@@ -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"
Expand Down Expand Up @@ -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)..<urlString.endIndex]

switch Repository.fromIdentifier(ownerAndNameSubstring as String) {
case .success(let server, let repository):
self = Dependency.gitHub(server, repository)

default:
self = Dependency.git(gitURL)
}

return
}
}

self = Dependency.git(gitURL)
}
}

extension Dependency: Comparable {
public static func == (_ lhs: Dependency, _ rhs: Dependency) -> 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<Dependency, ScannableError> {
let parser: (String) -> Result<Dependency, ScannableError>

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
}
}
}
Loading

0 comments on commit b3ccc77

Please sign in to comment.