diff --git a/Brief/Updater.swift b/Brief/Updater.swift
index a4a524f..010cb14 100644
--- a/Brief/Updater.swift
+++ b/Brief/Updater.swift
@@ -45,26 +45,15 @@ extension Updater {
func evaluate(release: Release) {
guard !userIgnored(release: release) else { return }
guard !release.prerelease else { return }
- let latestVersion = semVer(from: release.name)
- let currentVersion = semVer(from: Bundle.main.infoDictionary!["CFBundleShortVersionString"] as! String)
- for (latest, current) in zip(latestVersion, currentVersion) {
- if latest > current {
- DispatchQueue.main.async {
- self.update = release
- }
- return
+ let latestVersion = SemVer(release.name)
+ let currentVersion = SemVer(Bundle.main.infoDictionary!["CFBundleShortVersionString"] as! String)
+ if latestVersion > currentVersion {
+ DispatchQueue.main.async {
+ self.update = release
}
}
}
- func semVer(from stringVersion: String) -> [Int] {
- var split = stringVersion.split(separator: ".").compactMap { Int($0) }
- while split.count < 3 {
- split.append(0)
- }
- return split
- }
-
func userIgnored(release: Release) -> Bool {
guard !release.critical else { return false }
return defaults.bool(forKey: release.name)
@@ -75,6 +64,38 @@ extension Updater {
}
}
+struct SemVer {
+
+ let versionNumbers: [Int]
+
+ init(_ version: String) {
+ // Betas have the format 1.2.3_beta1
+ let strippedBeta = version.split(separator: "_").first!
+ var split = strippedBeta.split(separator: ".").compactMap { Int($0) }
+ while split.count < 3 {
+ split.append(0)
+ }
+ versionNumbers = split
+ }
+
+}
+
+extension SemVer: Comparable {
+
+ static func < (lhs: SemVer, rhs: SemVer) -> Bool {
+ for (latest, current) in zip(lhs.versionNumbers, rhs.versionNumbers) {
+ if latest < current {
+ return true
+ } else if latest > current {
+ return false
+ }
+ }
+ return false
+ }
+
+
+}
+
extension Updater {
enum Constants {
diff --git a/BriefTests/BriefTests.swift b/BriefTests/BriefTests.swift
new file mode 100644
index 0000000..79a4be1
--- /dev/null
+++ b/BriefTests/BriefTests.swift
@@ -0,0 +1,30 @@
+import XCTest
+@testable import Brief
+
+class SemVerTests: XCTestCase {
+
+ func testEqual() {
+ let current = SemVer("1.0.2")
+ let old = SemVer("1.0.2")
+ XCTAssert(!(current > old))
+ }
+
+ func testPatchGreaterButMinorLess() {
+ let current = SemVer("1.1.0")
+ let old = SemVer("1.0.2")
+ XCTAssert(current > old)
+ }
+
+ func testMajorSameMinorGreater() {
+ let current = SemVer("1.0.2")
+ let new = SemVer("1.0.3")
+ XCTAssert(current < new)
+ }
+
+ func testBeta() {
+ let current = SemVer("1.0.2")
+ let new = SemVer("1.1.0_beta1")
+ XCTAssert(current < new)
+ }
+
+}
diff --git a/BriefTests/Info.plist b/BriefTests/Info.plist
new file mode 100644
index 0000000..64d65ca
--- /dev/null
+++ b/BriefTests/Info.plist
@@ -0,0 +1,22 @@
+
+
+
+
+ CFBundleDevelopmentRegion
+ $(DEVELOPMENT_LANGUAGE)
+ CFBundleExecutable
+ $(EXECUTABLE_NAME)
+ CFBundleIdentifier
+ $(PRODUCT_BUNDLE_IDENTIFIER)
+ CFBundleInfoDictionaryVersion
+ 6.0
+ CFBundleName
+ $(PRODUCT_NAME)
+ CFBundlePackageType
+ $(PRODUCT_BUNDLE_PACKAGE_TYPE)
+ CFBundleShortVersionString
+ 1.0
+ CFBundleVersion
+ 1
+
+
diff --git a/Config/Secretive.xctestplan b/Config/Secretive.xctestplan
index 25eec62..1ec79fb 100644
--- a/Config/Secretive.xctestplan
+++ b/Config/Secretive.xctestplan
@@ -36,6 +36,14 @@
"identifier" : "50617D9323FCE48E0099B055",
"name" : "SecretiveTests"
}
+ },
+ {
+ "parallelizable" : true,
+ "target" : {
+ "containerPath" : "container:Secretive.xcodeproj",
+ "identifier" : "5091D31E2519D56D0049FD9B",
+ "name" : "BriefTests"
+ }
}
],
"version" : 1
diff --git a/Secretive.xcodeproj/project.pbxproj b/Secretive.xcodeproj/project.pbxproj
index cdc7716..21bb736 100644
--- a/Secretive.xcodeproj/project.pbxproj
+++ b/Secretive.xcodeproj/project.pbxproj
@@ -62,6 +62,8 @@
508A5911241EF09C0069DC07 /* SecretAgentKit.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = 5099A06C240242BA0062B6F2 /* SecretAgentKit.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
508A5913241EF0B20069DC07 /* SecretKit.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = 50617DA823FCE4AB0099B055 /* SecretKit.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
5091D2BC25183B830049FD9B /* ApplicationDirectoryController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5091D2BB25183B830049FD9B /* ApplicationDirectoryController.swift */; };
+ 5091D3222519D56D0049FD9B /* BriefTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5091D3212519D56D0049FD9B /* BriefTests.swift */; };
+ 5091D3242519D56D0049FD9B /* Brief.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 506772FB2426F3F400034DED /* Brief.framework */; };
5099A02423FD2AAA0062B6F2 /* CreateSecretView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5099A02323FD2AAA0062B6F2 /* CreateSecretView.swift */; };
5099A02723FE34FA0062B6F2 /* SmartCard.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5099A02623FE34FA0062B6F2 /* SmartCard.swift */; };
5099A02923FE35240062B6F2 /* SmartCardStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5099A02823FE35240062B6F2 /* SmartCardStore.swift */; };
@@ -141,6 +143,13 @@
remoteGlobalIDString = 50617DA723FCE4AB0099B055;
remoteInfo = SecretKit;
};
+ 5091D3252519D56D0049FD9B /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 50617D7723FCE48D0099B055 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 506772FA2426F3F400034DED;
+ remoteInfo = Brief;
+ };
5099A076240242BA0062B6F2 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 50617D7723FCE48D0099B055 /* Project object */;
@@ -266,6 +275,9 @@
508A58B4241ED48F0069DC07 /* PreviewAgentStatusChecker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PreviewAgentStatusChecker.swift; sourceTree = ""; };
508A590F241EEF6D0069DC07 /* Secretive.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; path = Secretive.xctestplan; sourceTree = ""; };
5091D2BB25183B830049FD9B /* ApplicationDirectoryController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ApplicationDirectoryController.swift; sourceTree = ""; };
+ 5091D31F2519D56D0049FD9B /* BriefTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = BriefTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
+ 5091D3212519D56D0049FD9B /* BriefTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BriefTests.swift; sourceTree = ""; };
+ 5091D3232519D56D0049FD9B /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
5099A02323FD2AAA0062B6F2 /* CreateSecretView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CreateSecretView.swift; sourceTree = ""; };
5099A02623FE34FA0062B6F2 /* SmartCard.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SmartCard.swift; sourceTree = ""; };
5099A02823FE35240062B6F2 /* SmartCardStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SmartCardStore.swift; sourceTree = ""; };
@@ -331,6 +343,14 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
+ 5091D31C2519D56D0049FD9B /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 5091D3242519D56D0049FD9B /* Brief.framework in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
5099A069240242BA0062B6F2 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
@@ -380,6 +400,7 @@
5099A07A240242BA0062B6F2 /* SecretAgentKitTests */,
508A58AF241E144C0069DC07 /* Config */,
506772FC2426F3F400034DED /* Brief */,
+ 5091D3202519D56D0049FD9B /* BriefTests */,
50617D8023FCE48E0099B055 /* Products */,
5099A08B240243730062B6F2 /* Frameworks */,
);
@@ -396,6 +417,7 @@
5099A074240242BA0062B6F2 /* SecretAgentKitTests.xctest */,
50A3B78A24026B7500D209EA /* SecretAgent.app */,
506772FB2426F3F400034DED /* Brief.framework */,
+ 5091D31F2519D56D0049FD9B /* BriefTests.xctest */,
);
name = Products;
sourceTree = "";
@@ -535,6 +557,15 @@
path = Controllers;
sourceTree = "";
};
+ 5091D3202519D56D0049FD9B /* BriefTests */ = {
+ isa = PBXGroup;
+ children = (
+ 5091D3212519D56D0049FD9B /* BriefTests.swift */,
+ 5091D3232519D56D0049FD9B /* Info.plist */,
+ );
+ path = BriefTests;
+ sourceTree = "";
+ };
5099A02523FE34DE0062B6F2 /* SmartCard */ = {
isa = PBXGroup;
children = (
@@ -737,6 +768,24 @@
productReference = 506772FB2426F3F400034DED /* Brief.framework */;
productType = "com.apple.product-type.framework";
};
+ 5091D31E2519D56D0049FD9B /* BriefTests */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 5091D32A2519D56D0049FD9B /* Build configuration list for PBXNativeTarget "BriefTests" */;
+ buildPhases = (
+ 5091D31B2519D56D0049FD9B /* Sources */,
+ 5091D31C2519D56D0049FD9B /* Frameworks */,
+ 5091D31D2519D56D0049FD9B /* Resources */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ 5091D3262519D56D0049FD9B /* PBXTargetDependency */,
+ );
+ name = BriefTests;
+ productName = BriefTests;
+ productReference = 5091D31F2519D56D0049FD9B /* BriefTests.xctest */;
+ productType = "com.apple.product-type.bundle.unit-test";
+ };
5099A06B240242BA0062B6F2 /* SecretAgentKit */ = {
isa = PBXNativeTarget;
buildConfigurationList = 5099A083240242BA0062B6F2 /* Build configuration list for PBXNativeTarget "SecretAgentKit" */;
@@ -802,7 +851,7 @@
50617D7723FCE48D0099B055 /* Project object */ = {
isa = PBXProject;
attributes = {
- LastSwiftUpdateCheck = 1140;
+ LastSwiftUpdateCheck = 1220;
LastUpgradeCheck = 1130;
ORGANIZATIONNAME = "Max Goedjen";
TargetAttributes = {
@@ -824,6 +873,9 @@
CreatedOnToolsVersion = 11.4;
LastSwiftMigration = 1140;
};
+ 5091D31E2519D56D0049FD9B = {
+ CreatedOnToolsVersion = 12.2;
+ };
5099A06B240242BA0062B6F2 = {
CreatedOnToolsVersion = 11.4;
LastSwiftMigration = 1140;
@@ -857,6 +909,7 @@
5099A06B240242BA0062B6F2 /* SecretAgentKit */,
5099A073240242BA0062B6F2 /* SecretAgentKitTests */,
506772FA2426F3F400034DED /* Brief */,
+ 5091D31E2519D56D0049FD9B /* BriefTests */,
);
};
/* End PBXProject section */
@@ -900,6 +953,13 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
+ 5091D31D2519D56D0049FD9B /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
5099A06A240242BA0062B6F2 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
@@ -1001,6 +1061,14 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
+ 5091D31B2519D56D0049FD9B /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 5091D3222519D56D0049FD9B /* BriefTests.swift in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
5099A068240242BA0062B6F2 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
@@ -1078,6 +1146,11 @@
target = 50617DA723FCE4AB0099B055 /* SecretKit */;
targetProxy = 507CE4F12420A6B50029F750 /* PBXContainerItemProxy */;
};
+ 5091D3262519D56D0049FD9B /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 506772FA2426F3F400034DED /* Brief */;
+ targetProxy = 5091D3252519D56D0049FD9B /* PBXContainerItemProxy */;
+ };
5099A077240242BA0062B6F2 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 5099A06B240242BA0062B6F2 /* SecretAgentKit */;
@@ -1729,6 +1802,64 @@
};
name = Test;
};
+ 5091D3272519D56D0049FD9B /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
+ CODE_SIGN_STYLE = Automatic;
+ COMBINE_HIDPI_IMAGES = YES;
+ DEVELOPMENT_TEAM = Z72PRUAWF6;
+ INFOPLIST_FILE = BriefTests/Info.plist;
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/../Frameworks",
+ "@loader_path/../Frameworks",
+ );
+ PRODUCT_BUNDLE_IDENTIFIER = com.maxgoedjen.BriefTests;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SWIFT_VERSION = 5.0;
+ };
+ name = Debug;
+ };
+ 5091D3282519D56D0049FD9B /* Test */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
+ CODE_SIGN_STYLE = Manual;
+ COMBINE_HIDPI_IMAGES = YES;
+ DEVELOPMENT_TEAM = "";
+ INFOPLIST_FILE = BriefTests/Info.plist;
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/../Frameworks",
+ "@loader_path/../Frameworks",
+ );
+ PRODUCT_BUNDLE_IDENTIFIER = com.maxgoedjen.BriefTests;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ PROVISIONING_PROFILE_SPECIFIER = "";
+ SWIFT_VERSION = 5.0;
+ };
+ name = Test;
+ };
+ 5091D3292519D56D0049FD9B /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
+ CODE_SIGN_STYLE = Automatic;
+ COMBINE_HIDPI_IMAGES = YES;
+ DEVELOPMENT_TEAM = Z72PRUAWF6;
+ INFOPLIST_FILE = BriefTests/Info.plist;
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/../Frameworks",
+ "@loader_path/../Frameworks",
+ );
+ PRODUCT_BUNDLE_IDENTIFIER = com.maxgoedjen.BriefTests;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SWIFT_VERSION = 5.0;
+ };
+ name = Release;
+ };
5099A084240242BA0062B6F2 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
@@ -1941,6 +2072,16 @@
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
+ 5091D32A2519D56D0049FD9B /* Build configuration list for PBXNativeTarget "BriefTests" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 5091D3272519D56D0049FD9B /* Debug */,
+ 5091D3282519D56D0049FD9B /* Test */,
+ 5091D3292519D56D0049FD9B /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
5099A083240242BA0062B6F2 /* Build configuration list for PBXNativeTarget "SecretAgentKit" */ = {
isa = XCConfigurationList;
buildConfigurations = (