forked from Carthage/Carthage
-
Notifications
You must be signed in to change notification settings - Fork 0
/
XCDBLDExtensions.swift
111 lines (103 loc) · 4.07 KB
/
XCDBLDExtensions.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
import Foundation
import ReactiveSwift
import ReactiveTask
import Result
import XCDBLD
extension MachOType {
/// Attempts to parse a Mach-O type from a string returned from `xcodebuild`.
public static func from(string: String) -> Result<MachOType, CarthageError> {
return Result(self.init(rawValue: string), failWith: .parseError(description: "unexpected Mach-O type \"\(string)\""))
}
}
extension SDK {
/// The relative path at which binaries corresponding to this platform will
/// be stored.
public var relativePath: String {
let subfolderName = self.platformSimulatorlessFromHeuristic
return (Constants.binariesFolderPath as NSString).appendingPathComponent(subfolderName)
}
/// The relative URL at which binaries corresponding to this platform will
/// be stored.
public var relativeURL: URL? {
let subfolderName = self.platformSimulatorlessFromHeuristic
return URL(string: Constants.binariesFolderPath)?.appendingPathComponent(subfolderName, isDirectory: true)
}
}
extension ProjectLocator {
/// Attempts to locate projects and workspaces within the given directory.
///
/// Sends all matches in preferential order.
public static func locate(in directoryURL: URL) -> SignalProducer<ProjectLocator, CarthageError> {
let enumerationOptions: FileManager.DirectoryEnumerationOptions = [ .skipsHiddenFiles, .skipsPackageDescendants ]
return gitmodulesEntriesInRepository(directoryURL, revision: nil)
.map { directoryURL.appendingPathComponent($0.path) }
.concat(value: directoryURL.appendingPathComponent(Constants.checkoutsFolderPath))
.collect()
.flatMap(.merge) { directoriesToSkip -> SignalProducer<URL, CarthageError> in
return FileManager.default.reactive
.enumerator(at: directoryURL.resolvingSymlinksInPath(), includingPropertiesForKeys: [ .typeIdentifierKey ], options: enumerationOptions, catchErrors: true)
.map { _, url in url }
.filter { url in
return !directoriesToSkip.contains { $0.hasSubdirectory(url) }
}
}
.filterMap { url -> ProjectLocator? in
if let uti = url.typeIdentifier.value {
if UTTypeConformsTo(uti as CFString, "com.apple.dt.document.workspace" as CFString) {
return .workspace(url)
} else if UTTypeConformsTo(uti as CFString, "com.apple.xcode.project" as CFString) {
return .projectFile(url)
}
}
return nil
}
.collect()
.map { $0.sorted() }
.flatMap(.merge) { SignalProducer<ProjectLocator, CarthageError>($0) }
}
/// Sends each scheme found in the receiver.
public func schemes() -> SignalProducer<Scheme, CarthageError> {
let task = xcodebuildTask("-list", BuildArguments(project: self))
return task.launch()
.ignoreTaskData()
.mapError(CarthageError.taskError)
// xcodebuild has a bug where xcodebuild -list can sometimes hang
// indefinitely on projects that don't share any schemes, so
// automatically bail out if it looks like that's happening.
.timeout(after: 60, raising: .xcodebuildTimeout(self), on: QueueScheduler())
.retry(upTo: 2)
.map { data in
return String(data: data, encoding: .utf8)!
}
.flatMap(.merge) { string in
return string.linesProducer
}
.flatMap(.merge) { line -> SignalProducer<String, CarthageError> in
// Matches one of these two possible messages:
//
// ' This project contains no schemes.'
// 'There are no schemes in workspace "Carthage".'
if line.hasSuffix("contains no schemes.") || line.hasPrefix("There are no schemes") {
return SignalProducer(error: .noSharedSchemes(self, nil))
} else {
return SignalProducer(value: line)
}
}
.skip { line in !line.hasSuffix("Schemes:") }
.skip(first: 1)
.take { line in !line.isEmpty }
.map { line in
let trimmed = line.trimmingCharacters(in: .whitespaces)
return Scheme(trimmed)
}
}
}
extension SDK {
/// Split the given SDKs into simulator ones and device ones.
internal static func splitSDKs<S: Sequence>(_ sdks: S) -> (simulators: [SDK], devices: [SDK]) where S.Iterator.Element == SDK {
return (
simulators: sdks.filter { $0.isSimulator },
devices: sdks.filter { !$0.isSimulator }
)
}
}