Add Version type

This commit is contained in:
Yonas Kolb
2017-12-26 17:36:41 +08:00
parent a1e46eb05a
commit 4a90d33951
8 changed files with 134 additions and 32 deletions
+21 -13
View File
@@ -11,19 +11,19 @@ import JSONUtilities
public struct PlatformVersions: Equatable {
public var iOS: String?
public var tvOS: String?
public var watchOS: String?
public var macOS: String?
public var iOS: Version?
public var tvOS: Version?
public var watchOS: Version?
public var macOS: Version?
public init(iOS: String? = nil, tvOS: String? = nil, watchOS: String? = nil, macOS: String? = nil) {
public init(iOS: Version? = nil, tvOS: Version? = nil, watchOS: Version? = nil, macOS: Version? = nil) {
self.iOS = iOS
self.tvOS = tvOS
self.watchOS = watchOS
self.macOS = macOS
}
public func version(for platform: Platform) -> String? {
public func version(for platform: Platform) -> Version? {
switch platform {
case .iOS: return iOS
case .tvOS: return tvOS
@@ -52,23 +52,31 @@ extension Platform {
}
}
extension Version {
/// doesn't print patch
public var platformVersion: String {
return "\(major).\(minor)\(patch > 0 ? ".\(patch)" : "")"
}
}
extension PlatformVersions: JSONObjectConvertible {
public init(jsonDictionary: JSONDictionary) throws {
func parseVersion(_ platform: String) -> String? {
func parseVersion(_ platform: String) throws -> Version? {
if let string: String = jsonDictionary.json(atKeyPath: .key(platform)) {
return string
return try Version(string)
} else if let double: Double = jsonDictionary.json(atKeyPath: .key(platform)) {
return String(double)
return try Version(double)
} else {
return nil
}
}
iOS = parseVersion("iOS")
tvOS = parseVersion("tvOS")
watchOS = parseVersion("watchOS")
macOS = parseVersion("macOS")
iOS = try parseVersion("iOS")
tvOS = try parseVersion("tvOS")
watchOS = try parseVersion("watchOS")
macOS = try parseVersion("macOS")
}
}
@@ -5,6 +5,7 @@ public enum SpecParsingError: Error, CustomStringConvertible {
case unknownTargetPlatform(String)
case invalidDependency([String: Any])
case unknownSourceBuildPhase(String)
case invalidVersion(String)
public var description: String {
switch self {
@@ -12,6 +13,7 @@ public enum SpecParsingError: Error, CustomStringConvertible {
case let .unknownTargetPlatform(platform): return "Unknown Target platform: \(platform)"
case let .invalidDependency(dependency): return "Unknown Target dependency: \(dependency)"
case let .unknownSourceBuildPhase(buildPhase): return "Unknown Source Build Phase: \(buildPhase)"
case let .invalidVersion(version): return "Invalid version: \(version)"
}
}
}
+4 -4
View File
@@ -30,7 +30,7 @@ public struct Target {
public var configFiles: [String: String]
public var scheme: TargetScheme?
public var legacy: LegacyTarget?
public var platformVersion: String?
public var platformVersion: Version?
public var isLegacy: Bool {
return legacy != nil
@@ -44,7 +44,7 @@ public struct Target {
return name
}
public init(name: String, type: PBXProductType, platform: Platform, platformVersion: String? = nil, settings: Settings = .empty, configFiles: [String: String] = [:], sources: [TargetSource] = [], dependencies: [Dependency] = [], prebuildScripts: [BuildScript] = [], postbuildScripts: [BuildScript] = [], scheme: TargetScheme? = nil, legacy: LegacyTarget? = nil) {
public init(name: String, type: PBXProductType, platform: Platform, platformVersion: Version? = nil, settings: Settings = .empty, configFiles: [String: String] = [:], sources: [TargetSource] = [], dependencies: [Dependency] = [], prebuildScripts: [BuildScript] = [], postbuildScripts: [BuildScript] = [], scheme: TargetScheme? = nil, legacy: LegacyTarget? = nil) {
self.name = name
self.type = type
self.platform = platform
@@ -212,9 +212,9 @@ extension Target: NamedJSONDictionaryConvertible {
}
if let string: String = jsonDictionary.json(atKeyPath: "platformVersion") {
platformVersion = string
platformVersion = try Version(string)
} else if let double: Double = jsonDictionary.json(atKeyPath: "platformVersion") {
platformVersion = String(double)
platformVersion = try Version(double)
} else {
platformVersion = nil
}
+56
View File
@@ -0,0 +1,56 @@
import Foundation
public struct Version: CustomStringConvertible, Equatable {
public var major: UInt
public var minor: UInt
public var patch: UInt
public init(_ string: String) throws {
let components = try string.split(separator: ".").map { (componentString) -> UInt in
guard let uint = UInt(componentString) else {
throw SpecParsingError.invalidVersion(string)
}
return uint
}
major = components[0]
minor = (components.count >= 2) ? components[1] : 0
patch = (components.count == 3) ? components[2] : 0
}
public init(_ double: Double) throws {
try self.init(String(double))
}
public init(major: UInt, minor: UInt? = 0, patch: UInt? = 0) {
self.major = major
self.minor = minor ?? 0
self.patch = patch ?? 0
}
public var string: String {
return "\(major).\(minor).\(patch)"
}
public var description: String {
return string
}
public func bumpingMajor() -> Version {
return Version(major: major + 1, minor: 0, patch: 0)
}
public func bumpingMinor() -> Version {
return Version(major: major, minor: minor + 1, patch: 0)
}
public func bumpingPatch() -> Version {
return Version(major: major, minor: minor, patch: patch + 1)
}
public static func ==(lhs: Version, rhs: Version) -> Bool {
return lhs.major == rhs.major &&
lhs.minor == rhs.minor &&
lhs.patch == rhs.patch
}
}
+2 -2
View File
@@ -18,7 +18,7 @@ extension ProjectSpec {
// apply custom platform version
for platform in Platform.all {
if let version = options.platformVersions.version(for: platform) {
buildSettings[platform.versionBuildSetting] = version
buildSettings[platform.versionBuildSetting] = version.platformVersion
}
}
@@ -43,7 +43,7 @@ extension ProjectSpec {
// apply custom platform version
if let version = target.platformVersion {
buildSettings[target.platform.versionBuildSetting] = version
buildSettings[target.platform.versionBuildSetting] = version.platformVersion
}
// Prevent setting presets from overrwriting settings in target xcconfig files
+34 -11
View File
@@ -14,17 +14,6 @@ func projectSpecTests() {
let dynamicLibrary = Target(name: "MyDynamicLibrary", type: .dynamicLibrary, platform: .iOS,
settings: Settings(buildSettings: ["SETTING_2": "VALUE"]))
$0.describe("Types") {
$0.it("is a framework when it has the right extension") {
try expect(framework.type.isFramework).to.beTrue()
}
$0.it("is a library when it has the right type") {
try expect(staticLibrary.type.isLibrary).to.beTrue()
try expect(dynamicLibrary.type.isLibrary).to.beTrue()
}
}
func expectValidationError(_ spec: ProjectSpec, _ expectedError: SpecValidationError.ValidationError) throws {
do {
try spec.validate()
@@ -39,6 +28,40 @@ func projectSpecTests() {
throw failure("Supposed to fail with \"\(expectedError)\"")
}
$0.describe("Types") {
$0.it("is a framework when it has the right extension") {
try expect(framework.type.isFramework).to.beTrue()
}
$0.it("is a library when it has the right type") {
try expect(staticLibrary.type.isLibrary).to.beTrue()
try expect(dynamicLibrary.type.isLibrary).to.beTrue()
}
}
$0.describe("Deployment Version") {
$0.it("has correct build setting") {
try expect(Platform.iOS.versionBuildSetting) == "IPHONEOS_DEPLOYMENT_TARGET"
try expect(Platform.tvOS.versionBuildSetting) == "TVOS_DEPLOYMENT_TARGET"
try expect(Platform.watchOS.versionBuildSetting) == "WATCHOS_DEPLOYMENT_TARGET"
try expect(Platform.macOS.versionBuildSetting) == "MACOSX_DEPLOYMENT_TARGET"
}
$0.it("parses versions correctly") {
try expect(Version("2").platformVersion) == "2.0"
try expect(Version("2.0").platformVersion) == "2.0"
try expect(Version("2.1").platformVersion) == "2.1"
try expect(Version("2.1.0").platformVersion) == "2.1"
try expect(Version("2.12.0").platformVersion) == "2.12"
try expect(Version("2.1.2").platformVersion) == "2.1.2"
try expect(Version("2.0.2").platformVersion) == "2.0.2"
try expect(Version(2).platformVersion) == "2.0"
try expect(Version(2.0).platformVersion) == "2.0"
try expect(Version(2.1).platformVersion) == "2.1"
}
}
$0.describe("Validation") {
let baseSpec = ProjectSpec(basePath: "", name: "", configs: [Config(name: "invalid")])
@@ -230,14 +230,18 @@ func specLoadingTests() {
createIntermediateGroups: true,
bundleIdPrefix: "com.test",
developmentLanguage: "ja",
platformVersions: PlatformVersions(iOS: "11.1", tvOS: "10.0", watchOS: "3.0", macOS: "10.12"))
platformVersions: PlatformVersions(
iOS: "11.1",
tvOS: "10.0",
watchOS: "3.0",
macOS: "10.12.1"))
let expected = ProjectSpec(basePath: "", name: "test", options: options)
let dictionary: [String: Any] = ["options": [
"carthageBuildPath": "../Carthage/Build",
"bundleIdPrefix": "com.test",
"createIntermediateGroups": true,
"developmentLanguage": "ja",
"platformVersions": ["iOS": 11.1, "tvOS": 10.0, "watchOS": "3.0", "macOS": "10.12" ]
"platformVersions": ["iOS": 11.1, "tvOS": 10.0, "watchOS": "3", "macOS": "10.12.1" ]
]]
let parsedSpec = try getProjectSpec(dictionary)
try expect(parsedSpec) == expected
+9
View File
@@ -1,6 +1,7 @@
import Foundation
import Spectre
import xcproj
import ProjectSpec
func expectError<T: Error>(_ expectedError: T, _ closure: () throws -> Void) throws where T: CustomStringConvertible {
do {
@@ -88,3 +89,11 @@ public protocol Named {
extension XCBuildConfiguration: Named {}
extension PBXNativeTarget: Named {}
extension XCScheme: Named {}
extension Version: ExpressibleByStringLiteral {
/// Will return nil literal not Semver
public init(stringLiteral value: String) {
try! self.init(value)
}
}