diff --git a/application/Info.plist b/application/Info.plist index b97e21c9..df6f5dfe 100644 --- a/application/Info.plist +++ b/application/Info.plist @@ -17,7 +17,7 @@ CFBundlePackageType APPL CFBundleShortVersionString - 1.0.0 + $(DEFAULT_VERSION_SEMVER) CFBundleVersion $(CURRENT_PROJECT_VERSION) LSApplicationCategoryType diff --git a/application/main.swift b/application/main.swift index cb4e4b84..1f98020c 100644 --- a/application/main.swift +++ b/application/main.swift @@ -45,19 +45,20 @@ let formatter: NumberFormatter = { return formatter }() +extension SemVer : Hashable { + public var hashValue: Int { + return self.description.hashValue + } +} + +public func ==(left: SemVer, right: SemVer) -> Bool { + return left.major == right.major && left.minor == right.minor && left.patch == right.patch +} enum Stage : CustomStringConvertible { + static let all : Set = [.alpha, .beta, .production] case alpha, beta, production - public static func current (for version: Version) -> Stage { - let result = self.minimumBuildVersions.filter{ - $0.value < version.build - }.max(by: {$0.value < $1.value}) - return result?.key ?? .alpha - } - - static let minimumBuildVersions : [Stage: UInt8] = [.beta : 15, .production : 17] - var description: String { switch self { case .alpha: @@ -69,11 +70,68 @@ enum Stage : CustomStringConvertible { } } - var minimumBuildVersion : UInt8? { - return type(of: self).minimumBuildVersions[self] + init?(string: String) { + for stage in Stage.all { + if string.compare(stage.description, options: String.CompareOptions.caseInsensitive, range: nil, locale: nil) == ComparisonResult.orderedSame { + self = stage + return + } + } + return nil + } + + public static let dictionary: StageBuildDictionaryProtocol! = { + guard let url = Bundle.main.url(forResource: "versions", withExtension: "plist") else { + return StageBuildDictionary(dictionary: StageBuildDictionaryBase()) + } + + let data = try! Data(contentsOf: url) + let plistObj = try! PropertyListSerialization.propertyList(from: data, options: PropertyListSerialization.ReadOptions(), format: nil) + let plist = plistObj as! [String : [String : Int]] + let dictionary = plist.reduce(StageBuildDictionaryBase(), { (previous, pair) -> StageBuildDictionaryBase in + var mutable = previous + mutable[SemVer(versionString: pair.key)!] = pair.value.reduce( + [Stage : UInt8](), + {(previous, pair) -> [Stage : UInt8] in + + var mutable = previous + mutable[Stage(string: pair.key)!] = UInt8(pair.value) + return mutable + }) + return mutable + }) + + return StageBuildDictionary(dictionary: dictionary) + }() +} + +struct StageBuildDictionary : StageBuildDictionaryProtocol { + + let dictionary : StageBuildDictionaryBase + + func stage(withBuildForVersion version: Version) -> StageBuild? { + let result = self.dictionary[version.semver]?.filter{ + $0.value <= version.build + }.max(by: {$0.value < $1.value}) + if let result = result { + return (stage: result.key, minimum: result.value) + } else { + return nil + } + } + + public init (dictionary: StageBuildDictionaryBase) { + self.dictionary = dictionary } } +typealias StageBuildDictionaryBase = [SemVer : [Stage : UInt8]] +typealias StageBuild = (stage: Stage, minimum: UInt8) + +protocol StageBuildDictionaryProtocol { + func stage (withBuildForVersion version: Version) -> StageBuild? +} + func -(a: UInt8?, b: UInt8?) -> UInt8? { guard let a = a, let b = b else { return nil @@ -81,6 +139,8 @@ func -(a: UInt8?, b: UInt8?) -> UInt8? { return a - b } + + extension Version : CustomStringConvertible { public var extra:Double { if let extraString = self.versionControl?.EXTRA { @@ -89,19 +149,36 @@ extension Version : CustomStringConvertible { return 0 } } - public var description:String { - let suffix = (Double(self.build) + (Double(self.versionControl?.TICK ?? 0) + self.extra/1000.0)/10000.0)/100.0 - let suffixString = formatter.string(for: suffix)!.components(separatedBy: ".")[1] - return "\(self.semver)\(suffixString)" - } - func descriptionWithStage (_ stage: Stage) -> String { + + var shortDescription:String { + let stage:Stage + let build:UInt8? + if let stagebuild = Stage.dictionary.stage(withBuildForVersion: self) { + stage = stagebuild.stage + build = stagebuild.minimum + } else { + stage = .production + build = nil + } switch stage { case .production: return self.semver.description default: - return "\(self.semver)-\(stage)\(self.build - ((stage.minimumBuildVersion - 1) ?? 0))" + return "\(self.semver)-\(stage)\(self.build - ((build - 1) ?? 0))" } + + } + + var fullDescription:String { + let suffix = (Double(self.build) + (Double(self.versionControl?.TICK ?? 0) + self.extra/1000.0)/10000.0)/100.0 + let suffixString = formatter.string(for: suffix)!.components(separatedBy: ".")[1] + return "\(self.semver)\(suffixString)" } + + public var description:String { + return self.fullDescription + } + } public enum CommandLineParameter : String { @@ -114,6 +191,7 @@ extension Array: SpeculidArgumentsProtocol { Speculid.begin(withArguments: CommandLine.arguments,{ (speculid) in + let helpText = try! String(contentsOf: Bundle.main.bundlePath.url(forResource: "help", withExtension: "txt")!) let output = FileHandle.standardOutput @@ -148,7 +226,8 @@ Speculid.begin(withArguments: CommandLine.arguments,{ if let param = CommandLineParameter(rawValue: parameter.substring(with: rangeIndex!)) { switch param { case .Version : - print("Speculid v\(speculid.version.descriptionWithStage(Stage.current(for: speculid.version))) [\(speculid.version)]") + + print("Speculid v\(speculid.version.shortDescription) [\(speculid.version)]") break default: print(helpText) diff --git a/application/versions.plist b/application/versions.plist new file mode 100644 index 00000000..f569df20 --- /dev/null +++ b/application/versions.plist @@ -0,0 +1,13 @@ + + + + + 1.0.1 + + beta + 4 + production + 5 + + + diff --git a/examples/Assets/Assets.xcassets/ImageSetScaled.imageset/Contents.json b/examples/Assets/Assets.xcassets/ImageSetScaled.imageset/Contents.json new file mode 100644 index 00000000..d8d3232a --- /dev/null +++ b/examples/Assets/Assets.xcassets/ImageSetScaled.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "geometry.1x~universal.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "geometry.2x~universal.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "geometry.3x~universal.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/Assets/Image Set (Scaled).speculid b/examples/Assets/Image Set (Scaled).speculid new file mode 100644 index 00000000..55065dee --- /dev/null +++ b/examples/Assets/Image Set (Scaled).speculid @@ -0,0 +1,5 @@ +{ +"set" : "Assets.xcassets/ImageSetScaled.imageset", +"source" : "geometry.svg", +"geometry" : "25" +} diff --git a/examples/examples.xcodeproj/project.pbxproj b/examples/examples.xcodeproj/project.pbxproj index 2d9ccc09..afae83da 100644 --- a/examples/examples.xcodeproj/project.pbxproj +++ b/examples/examples.xcodeproj/project.pbxproj @@ -85,6 +85,7 @@ B3AF65CE1DA3F6F900BD008B /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = B38F73D01DA2B600008469FE /* Assets.xcassets */; }; B3AF65CF1DA3F6F900BD008B /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = B38F73D01DA2B600008469FE /* Assets.xcassets */; }; B3AF65D01DA3F6FA00BD008B /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = B38F73D01DA2B600008469FE /* Assets.xcassets */; }; + B3D744331DF8ED18007A1216 /* Image Set (Scaled).speculid in Resources */ = {isa = PBXBuildFile; fileRef = B3D744321DF8ED18007A1216 /* Image Set (Scaled).speculid */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -190,6 +191,7 @@ B38F73D01DA2B600008469FE /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; B38F73D51DA2C1AB008469FE /* macOS AppIcon.speculid */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "macOS AppIcon.speculid"; sourceTree = ""; }; B38F73D71DA2C1F1008469FE /* geometry.svg */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = geometry.svg; sourceTree = ""; }; + B3D744321DF8ED18007A1216 /* Image Set (Scaled).speculid */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "Image Set (Scaled).speculid"; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -292,6 +294,7 @@ B38F73D41DA2C149008469FE /* Assets */ = { isa = PBXGroup; children = ( + B3D744321DF8ED18007A1216 /* Image Set (Scaled).speculid */, B38DDF3A1DA2E5AE005AA837 /* iOS AppIcon.speculid */, B38F73D71DA2C1F1008469FE /* geometry.svg */, B38F73D51DA2C1AB008469FE /* macOS AppIcon.speculid */, @@ -458,6 +461,7 @@ buildActionMask = 2147483647; files = ( B30005CB1DB54EB1000A8166 /* Image Set.speculid in Resources */, + B3D744331DF8ED18007A1216 /* Image Set (Scaled).speculid in Resources */, B38F73D11DA2B600008469FE /* Assets.xcassets in Resources */, B38F73641DA2B358008469FE /* MainMenu.xib in Resources */, B38DDF3C1DA2E5AE005AA837 /* iOS AppIcon.speculid in Resources */, diff --git a/examples/shasum b/examples/shasum index ce30f5e9..d5bee608 100644 --- a/examples/shasum +++ b/examples/shasum @@ -1 +1 @@ -35388c0230c3c15943e465c507c90b048bf2904aa5bbe8685817787992f3325401784a7eaa782d705583b9f877fe0f02217064a8dbb82b27e169f72df00efec7 - +d8d65120ef77d026a965b4515fd8aa53681b7e45e9580add63e832367d0cd79e6b3e01b1415d34fbbbd9e68ac8b281ef389914ed4c86250b50e4aceb7fccbb58 - diff --git a/framework/Builders/SVGImageConversionBuilder.swift b/framework/Builders/SVGImageConversionBuilder.swift index b387fefa..f817e4d6 100644 --- a/framework/Builders/SVGImageConversionBuilder.swift +++ b/framework/Builders/SVGImageConversionBuilder.swift @@ -29,16 +29,16 @@ public struct SVGImageConversionBuilder : ImageConversionBuilderProtocol { arguments.append(contentsOf: [specifications.contentsDirectoryURL.appendingPathComponent(specifications.destination(forImage: imageSpecification)).path,dimension,"\(length)", specifications.sourceImageURL.absoluteURL.path]) } else if let geometryValue = specifications.geometry?.value { let dimension: String - let length: Int + let length: CGFloat switch geometryValue { case .Width(let value): dimension = "-w" - length = value + length = CGFloat(value) * scale case .Height(let value): dimension = "-h" - length = value + length = CGFloat(value) * scale } - arguments.append(contentsOf: [specifications.contentsDirectoryURL.appendingPathComponent(specifications.destination(forImage: imageSpecification)).path,dimension,"\(length)", specifications.sourceImageURL.absoluteURL.path]) + arguments.append(contentsOf: [specifications.contentsDirectoryURL.appendingPathComponent(specifications.destination(forImage: imageSpecification)).path,dimension,"\(Int(length))", specifications.sourceImageURL.absoluteURL.path]) } else { // convert to arguments.append(contentsOf: [specifications.contentsDirectoryURL.appendingPathComponent(specifications.destination(forImage: imageSpecification)).path, "-d", "\(90*scale)" ,specifications.sourceImageURL.absoluteURL.path]) diff --git a/framework/Controllers/Speculid.swift b/framework/Controllers/Speculid.swift index d870c8dc..2d13c994 100644 --- a/framework/Controllers/Speculid.swift +++ b/framework/Controllers/Speculid.swift @@ -29,6 +29,7 @@ public struct Speculid { public static func begin (withArguments arguments: SpeculidArgumentsProtocol, _ callback: @escaping (SpeculidApplicationProtocol) -> Void) { let operatingSystem = ProcessInfo.processInfo.operatingSystemVersionString + let analyticsConfiguration = AnalyticsConfiguration(trackingIdentifier: "UA-33667276-6", applicationName: "speculid", applicationVersion : String(describing: self.version), customParameters : [.operatingSystemVersion : operatingSystem]) let tracker = AnalyticsTracker(configuration: analyticsConfiguration, sessionManager: AnalyticsSessionManager()) NSSetUncaughtExceptionHandler(exceptionHandlerMethod) diff --git a/framework/Info.plist b/framework/Info.plist index 20b05ecd..10e19d54 100644 --- a/framework/Info.plist +++ b/framework/Info.plist @@ -15,7 +15,7 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 1.0.0 + $(DEFAULT_VERSION_SEMVER) CFBundleVersion $(CURRENT_PROJECT_VERSION) NSPrincipalClass diff --git a/framework/VCS.swift b/framework/VCS.swift index a51d22e1..31744b3f 100644 --- a/framework/VCS.swift +++ b/framework/VCS.swift @@ -3,16 +3,16 @@ let VCS_TYPE = "git" let VCS_BASENAME = "speculid" let VCS_UUID: String? = "b6fd659a7d2088d5420f962a307b1f7f7e5d0604" -let VCS_NUM: Int = 428 -let VCS_DATE = "2016-10-20T14:54:01Z" -let VCS_BRANCH: String = "release/1.0.0" -let VCS_TAG: String? = "1.0.0-beta2" -let VCS_TICK: Int? = 5 -let VCS_EXTRA: String? = "11" +let VCS_NUM: Int = 448 +let VCS_DATE = "2016-12-09T16:31:53Z" +let VCS_BRANCH: String = "release/1.0.1" +let VCS_TAG: String? = "1.0.1-alpha3" +let VCS_TICK: Int? = 1 +let VCS_EXTRA: String? = "35" -let VCS_ACTION_STAMP: String? = "2016-10-20T14:54:01Z!leogdion@brightdigit.com" -let VCS_FULL_HASH: String = "1fb2d82ba3ebff406f51a14ecc14bbcd65267a28" -let VCS_SHORT_HASH: String = "1fb2d82" +let VCS_ACTION_STAMP: String? = "2016-12-09T16:31:53Z!leogdion@brightdigit.com" +let VCS_FULL_HASH: String = "39c7134a41040511e13464206b68ea1e47771b5f" +let VCS_SHORT_HASH: String = "39c7134" let VCS_WC_MODIFIED: Bool = true diff --git a/speculid.xcodeproj/project.pbxproj b/speculid.xcodeproj/project.pbxproj index dd74e216..167bd5f3 100644 --- a/speculid.xcodeproj/project.pbxproj +++ b/speculid.xcodeproj/project.pbxproj @@ -56,6 +56,7 @@ B36AD1C21DB6C3AB00D33AD7 /* ApplicationPathDictionary.swift in Sources */ = {isa = PBXBuildFile; fileRef = B36AD1C11DB6C3AB00D33AD7 /* ApplicationPathDictionary.swift */; }; B36AD1C41DB6C3C100D33AD7 /* ApplicationPath.swift in Sources */ = {isa = PBXBuildFile; fileRef = B36AD1C31DB6C3C100D33AD7 /* ApplicationPath.swift */; }; B36AD1C71DB6E9DF00D33AD7 /* PDFConversionBuilderTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = B36AD1C61DB6E9DF00D33AD7 /* PDFConversionBuilderTest.swift */; }; + B370914C1DFB020E007DD54C /* versions.plist in Resources */ = {isa = PBXBuildFile; fileRef = B370914B1DFB020E007DD54C /* versions.plist */; }; B37996B91DB7E36C00B8CA3B /* SearchApplicationPathDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = B37996B81DB7E36C00B8CA3B /* SearchApplicationPathDataSource.swift */; }; B38086001D9AA76E000BC05A /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = B38085FF1D9AA76E000BC05A /* Assets.xcassets */; }; B38086091D9AA78E000BC05A /* main.swift in Sources */ = {isa = PBXBuildFile; fileRef = B38086081D9AA78E000BC05A /* main.swift */; }; @@ -175,6 +176,7 @@ B36AD1C11DB6C3AB00D33AD7 /* ApplicationPathDictionary.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ApplicationPathDictionary.swift; sourceTree = ""; }; B36AD1C31DB6C3C100D33AD7 /* ApplicationPath.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ApplicationPath.swift; sourceTree = ""; }; B36AD1C61DB6E9DF00D33AD7 /* PDFConversionBuilderTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = PDFConversionBuilderTest.swift; path = Builders/PDFConversionBuilderTest.swift; sourceTree = ""; }; + B370914B1DFB020E007DD54C /* versions.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = versions.plist; sourceTree = ""; }; B37996B81DB7E36C00B8CA3B /* SearchApplicationPathDataSource.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SearchApplicationPathDataSource.swift; sourceTree = ""; }; B38085F91D9AA76E000BC05A /* Speculid.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Speculid.app; sourceTree = BUILT_PRODUCTS_DIR; }; B38085FF1D9AA76E000BC05A /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; @@ -331,6 +333,7 @@ B38086041D9AA76E000BC05A /* Info.plist */, B38086081D9AA78E000BC05A /* main.swift */, B33C70361DA6E72D002BC291 /* help.txt */, + B370914B1DFB020E007DD54C /* versions.plist */, ); path = application; sourceTree = ""; @@ -593,6 +596,7 @@ buildActionMask = 2147483647; files = ( B38086001D9AA76E000BC05A /* Assets.xcassets in Resources */, + B370914C1DFB020E007DD54C /* versions.plist in Resources */, B33C70371DA6E72D002BC291 /* help.txt in Resources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -850,7 +854,8 @@ CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CURRENT_PROJECT_VERSION = 18; + CURRENT_PROJECT_VERSION = 5; + DEFAULT_VERSION_SEMVER = 1.0.1; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; GCC_NO_COMMON_BLOCKS = YES; @@ -878,7 +883,8 @@ CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CURRENT_PROJECT_VERSION = 18; + CURRENT_PROJECT_VERSION = 5; + DEFAULT_VERSION_SEMVER = 1.0.1; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; @@ -1011,7 +1017,6 @@ isa = XCBuildConfiguration; baseConfigurationReference = 2DB7226F66B034963BD7F05D /* Pods-SpeculidTests.debug.xcconfig */; buildSettings = { - ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; @@ -1066,7 +1071,6 @@ isa = XCBuildConfiguration; baseConfigurationReference = 3B8747C1F338E0ADE9DFD69B /* Pods-SpeculidTests.release.xcconfig */; buildSettings = { - ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; @@ -1114,7 +1118,6 @@ isa = XCBuildConfiguration; baseConfigurationReference = 407E8C50424541751746E1EB /* Pods-Speculid-App.debug.xcconfig */; buildSettings = { - ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; ALWAYS_SEARCH_USER_PATHS = NO; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ANALYZER_NONNULL = YES; @@ -1154,7 +1157,6 @@ isa = XCBuildConfiguration; baseConfigurationReference = 4931B3201EAC0FD92C614AF8 /* Pods-Speculid-App.release.xcconfig */; buildSettings = { - ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; ALWAYS_SEARCH_USER_PATHS = NO; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ANALYZER_NONNULL = YES;