mirror of
https://github.com/SideStore/SideStore.git
synced 2026-02-16 02:03:32 +01:00
Compare commits
17 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2b71c36ace | ||
|
|
591913743e | ||
|
|
77d95fe278 | ||
|
|
0cd62d371a | ||
|
|
9771f6bb9a | ||
|
|
e553efbad5 | ||
|
|
a4dfd28a3c | ||
|
|
a7496e08e3 | ||
|
|
2f3be07b5d | ||
|
|
cbde3e6495 | ||
|
|
117f31e158 | ||
|
|
420efcbb11 | ||
|
|
ae8e9a3506 | ||
|
|
4aca1dfa43 | ||
|
|
3785891923 | ||
|
|
e85db67ac7 | ||
|
|
39d0835f5b |
@@ -59,6 +59,15 @@
|
||||
A80D60D32D3DD85100CEF65D /* ReleaseTrack.swift in Sources */ = {isa = PBXBuildFile; fileRef = A80D60D12D3D705F00CEF65D /* ReleaseTrack.swift */; };
|
||||
A80D790D2D2F20AF00A40F40 /* PaginationIntent.swift in Sources */ = {isa = PBXBuildFile; fileRef = A80D790C2D2F20AF00A40F40 /* PaginationIntent.swift */; };
|
||||
A80D790F2D2F217000A40F40 /* PaginationDataHolder.swift in Sources */ = {isa = PBXBuildFile; fileRef = A80D790E2D2F217000A40F40 /* PaginationDataHolder.swift */; };
|
||||
A815AA952D90D2A100929A9E /* StoreApp17To17_1MigrationPolicy.swift in Sources */ = {isa = PBXBuildFile; fileRef = A815AA942D90D2A100929A9E /* StoreApp17To17_1MigrationPolicy.swift */; };
|
||||
A815AA972D90E16400929A9E /* ReleaseTrack17To17_1MigrationPolicy.swift in Sources */ = {isa = PBXBuildFile; fileRef = A815AA962D90E16400929A9E /* ReleaseTrack17To17_1MigrationPolicy.swift */; };
|
||||
A815AA992D90E5E500929A9E /* AltStore17ToAltStore17_1.xcmappingmodel in Sources */ = {isa = PBXBuildFile; fileRef = A815AA982D90E5E500929A9E /* AltStore17ToAltStore17_1.xcmappingmodel */; };
|
||||
A815AA9F2D9104DD00929A9E /* BuildInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = A815AA9E2D9104DD00929A9E /* BuildInfo.swift */; };
|
||||
A815AAA12D9108BC00929A9E /* AltStore11ToAltStore17_1.xcmappingmodel in Sources */ = {isa = PBXBuildFile; fileRef = A815AAA02D9108BC00929A9E /* AltStore11ToAltStore17_1.xcmappingmodel */; };
|
||||
A815AAA72D9108CB00929A9E /* ReleaseTrack11To17_1MigrationPolicy.swift in Sources */ = {isa = PBXBuildFile; fileRef = A815AAA42D9108CB00929A9E /* ReleaseTrack11To17_1MigrationPolicy.swift */; };
|
||||
A815AAA82D9108CB00929A9E /* AppPermission11To17_1MigrationPolicy.swift in Sources */ = {isa = PBXBuildFile; fileRef = A815AAA52D9108CB00929A9E /* AppPermission11To17_1MigrationPolicy.swift */; };
|
||||
A815AAA92D9108CB00929A9E /* Source11To17_1MigrationPolicy.swift in Sources */ = {isa = PBXBuildFile; fileRef = A815AAA22D9108CB00929A9E /* Source11To17_1MigrationPolicy.swift */; };
|
||||
A815AAAA2D9108CB00929A9E /* StoreApp11To17_1MigrationPolicy.swift in Sources */ = {isa = PBXBuildFile; fileRef = A815AAA32D9108CB00929A9E /* StoreApp11To17_1MigrationPolicy.swift */; };
|
||||
A81A8CB92D68B30B0086C96F /* SingletonGenericMap.swift in Sources */ = {isa = PBXBuildFile; fileRef = A868CFE32D319988002F1201 /* SingletonGenericMap.swift */; };
|
||||
A81A8CBA2D68B3110086C96F /* TreeMap.swift in Sources */ = {isa = PBXBuildFile; fileRef = A81A8CB02D68B0320086C96F /* TreeMap.swift */; };
|
||||
A81A8CBD2D68B43F0086C96F /* LinkedHashMap.swift in Sources */ = {isa = PBXBuildFile; fileRef = A81A8CBC2D68B43F0086C96F /* LinkedHashMap.swift */; };
|
||||
@@ -69,6 +78,8 @@
|
||||
A81A8CD12D68BA9B0086C96F /* TreeMap.swift in Sources */ = {isa = PBXBuildFile; fileRef = A81A8CB02D68B0320086C96F /* TreeMap.swift */; };
|
||||
A81A8CD22D68BAA30086C96F /* SingletonGenericMap.swift in Sources */ = {isa = PBXBuildFile; fileRef = A868CFE32D319988002F1201 /* SingletonGenericMap.swift */; };
|
||||
A81A8CD42D68BAFF0086C96F /* DataStructureTests.xctestplan in Resources */ = {isa = PBXBuildFile; fileRef = A81A8CD32D68BAFF0086C96F /* DataStructureTests.xctestplan */; };
|
||||
A81BF9E52D84CB0C00768940 /* AppPermission17To17_1MigrationPolicy.swift in Sources */ = {isa = PBXBuildFile; fileRef = A81BF9E22D84CB0C00768940 /* AppPermission17To17_1MigrationPolicy.swift */; };
|
||||
A81BF9E72D84CB0C00768940 /* Source17To17_1MigrationPolicy.swift in Sources */ = {isa = PBXBuildFile; fileRef = A81BF9E32D84CB0C00768940 /* Source17To17_1MigrationPolicy.swift */; };
|
||||
A82067842D03DC0600645C0D /* OperatingSystemVersion+Comparable.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5708416292448DA00D42D34 /* OperatingSystemVersion+Comparable.swift */; };
|
||||
A82067C42D03E0DE00645C0D /* SemanticVersion in Frameworks */ = {isa = PBXBuildFile; productRef = A82067C32D03E0DE00645C0D /* SemanticVersion */; };
|
||||
A8228B5B2D6E2C0C00F7CE0E /* (null) in Sources */ = {isa = PBXBuildFile; };
|
||||
@@ -77,7 +88,6 @@
|
||||
A859ED5D2D1EE827003DCC58 /* OpenSSL.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = A859ED5B2D1EE80D003DCC58 /* OpenSSL.xcframework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||
A86315DF2D3EB2DE0048FA40 /* ErrorProcessing.swift in Sources */ = {isa = PBXBuildFile; fileRef = A86315DE2D3EB2D80048FA40 /* ErrorProcessing.swift */; };
|
||||
A8696EE42D34512C00E96389 /* RemoveAppExtensionsOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = A8696EE32D34512C00E96389 /* RemoveAppExtensionsOperation.swift */; };
|
||||
A881E7C72D6EF58C00954AD2 /* AltStore11ToAltStore17.xcmappingmodel in Sources */ = {isa = PBXBuildFile; fileRef = A881E7C62D6EF58C00954AD2 /* AltStore11ToAltStore17.xcmappingmodel */; };
|
||||
A881E7CB2D6EF5AB00954AD2 /* StoreApp11To17MigrationPolicy.swift in Sources */ = {isa = PBXBuildFile; fileRef = A881E7CA2D6EF5AB00954AD2 /* StoreApp11To17MigrationPolicy.swift */; };
|
||||
A88B8C492D35AD3200F53F9D /* OperationsLoggingContolView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A88B8C482D35AD3200F53F9D /* OperationsLoggingContolView.swift */; };
|
||||
A88B8C552D35F1EC00F53F9D /* OperationsLoggingControl.swift in Sources */ = {isa = PBXBuildFile; fileRef = A88B8C542D35F1EC00F53F9D /* OperationsLoggingControl.swift */; };
|
||||
@@ -103,6 +113,7 @@
|
||||
A8C6D5142D1EE8D700DF01F1 /* OpenSSL.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = A859ED5B2D1EE80D003DCC58 /* OpenSSL.xcframework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||
A8C6D5172D1EE95B00DF01F1 /* OpenSSL.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = A859ED5B2D1EE80D003DCC58 /* OpenSSL.xcframework */; };
|
||||
A8C6D5182D1EE95B00DF01F1 /* OpenSSL.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = A859ED5B2D1EE80D003DCC58 /* OpenSSL.xcframework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||
A8C924242D8E73B1009D9953 /* AltStore11ToAltStore17.xcmappingmodel in Sources */ = {isa = PBXBuildFile; fileRef = A8C924232D8E73B1009D9953 /* AltStore11ToAltStore17.xcmappingmodel */; };
|
||||
A8D484D82D0CD306002C691D /* AltBackup.ipa in Resources */ = {isa = PBXBuildFile; fileRef = A8D484D72D0CD306002C691D /* AltBackup.ipa */; };
|
||||
A8D49F532D3D2F9400844B92 /* ProcessInfo+AltStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = A8D49F522D3D2F9400844B92 /* ProcessInfo+AltStore.swift */; };
|
||||
A8E2DB312D684E2A009E5D31 /* UITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A8E2DB2E2D684E2A009E5D31 /* UITests.swift */; };
|
||||
@@ -660,6 +671,15 @@
|
||||
A80D60D12D3D705F00CEF65D /* ReleaseTrack.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReleaseTrack.swift; sourceTree = "<group>"; };
|
||||
A80D790C2D2F20AF00A40F40 /* PaginationIntent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PaginationIntent.swift; sourceTree = "<group>"; };
|
||||
A80D790E2D2F217000A40F40 /* PaginationDataHolder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PaginationDataHolder.swift; sourceTree = "<group>"; };
|
||||
A815AA942D90D2A100929A9E /* StoreApp17To17_1MigrationPolicy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StoreApp17To17_1MigrationPolicy.swift; sourceTree = "<group>"; };
|
||||
A815AA962D90E16400929A9E /* ReleaseTrack17To17_1MigrationPolicy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReleaseTrack17To17_1MigrationPolicy.swift; sourceTree = "<group>"; };
|
||||
A815AA982D90E5E500929A9E /* AltStore17ToAltStore17_1.xcmappingmodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcmappingmodel; path = AltStore17ToAltStore17_1.xcmappingmodel; sourceTree = "<group>"; };
|
||||
A815AA9E2D9104DD00929A9E /* BuildInfo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BuildInfo.swift; sourceTree = "<group>"; };
|
||||
A815AAA02D9108BC00929A9E /* AltStore11ToAltStore17_1.xcmappingmodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcmappingmodel; path = AltStore11ToAltStore17_1.xcmappingmodel; sourceTree = "<group>"; };
|
||||
A815AAA22D9108CB00929A9E /* Source11To17_1MigrationPolicy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Source11To17_1MigrationPolicy.swift; sourceTree = "<group>"; };
|
||||
A815AAA32D9108CB00929A9E /* StoreApp11To17_1MigrationPolicy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StoreApp11To17_1MigrationPolicy.swift; sourceTree = "<group>"; };
|
||||
A815AAA42D9108CB00929A9E /* ReleaseTrack11To17_1MigrationPolicy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReleaseTrack11To17_1MigrationPolicy.swift; sourceTree = "<group>"; };
|
||||
A815AAA52D9108CB00929A9E /* AppPermission11To17_1MigrationPolicy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppPermission11To17_1MigrationPolicy.swift; sourceTree = "<group>"; };
|
||||
A81A8CB02D68B0320086C96F /* TreeMap.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TreeMap.swift; sourceTree = "<group>"; };
|
||||
A81A8CB42D68B2180086C96F /* TreeMapTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TreeMapTests.swift; sourceTree = "<group>"; };
|
||||
A81A8CBC2D68B43F0086C96F /* LinkedHashMap.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LinkedHashMap.swift; sourceTree = "<group>"; };
|
||||
@@ -667,6 +687,9 @@
|
||||
A81A8CC52D68BA610086C96F /* DataStructureTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = DataStructureTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
A81A8CC72D68BA610086C96F /* DataStructuresTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DataStructuresTests.swift; sourceTree = "<group>"; };
|
||||
A81A8CD32D68BAFF0086C96F /* DataStructureTests.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; path = DataStructureTests.xctestplan; sourceTree = "<group>"; };
|
||||
A81BF9E12D84C9E900768940 /* AltStore 17_1.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = "AltStore 17_1.xcdatamodel"; sourceTree = "<group>"; };
|
||||
A81BF9E22D84CB0C00768940 /* AppPermission17To17_1MigrationPolicy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppPermission17To17_1MigrationPolicy.swift; sourceTree = "<group>"; };
|
||||
A81BF9E32D84CB0C00768940 /* Source17To17_1MigrationPolicy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Source17To17_1MigrationPolicy.swift; sourceTree = "<group>"; };
|
||||
A859ED5B2D1EE80D003DCC58 /* OpenSSL.xcframework */ = {isa = PBXFileReference; expectedSignature = "AppleDeveloperProgram:67RAULRX93:Marcin Krzyzanowski"; lastKnownFileType = wrapper.xcframework; name = OpenSSL.xcframework; path = SideStore/AltSign/Dependencies/OpenSSL/Frameworks/OpenSSL.xcframework; sourceTree = "<group>"; };
|
||||
A85ACB8E2D1F31C400AA3DE7 /* AltBackup.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = AltBackup.xcconfig; sourceTree = "<group>"; };
|
||||
A85ACB8F2D1F31C400AA3DE7 /* AltStore.debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = AltStore.debug.xcconfig; sourceTree = "<group>"; };
|
||||
@@ -679,7 +702,6 @@
|
||||
A86315DE2D3EB2D80048FA40 /* ErrorProcessing.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ErrorProcessing.swift; sourceTree = "<group>"; };
|
||||
A868CFE32D319988002F1201 /* SingletonGenericMap.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SingletonGenericMap.swift; sourceTree = "<group>"; };
|
||||
A8696EE32D34512C00E96389 /* RemoveAppExtensionsOperation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RemoveAppExtensionsOperation.swift; sourceTree = "<group>"; };
|
||||
A881E7C62D6EF58C00954AD2 /* AltStore11ToAltStore17.xcmappingmodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcmappingmodel; path = AltStore11ToAltStore17.xcmappingmodel; sourceTree = "<group>"; };
|
||||
A881E7CA2D6EF5AB00954AD2 /* StoreApp11To17MigrationPolicy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StoreApp11To17MigrationPolicy.swift; sourceTree = "<group>"; };
|
||||
A881E8562D6FBBAF00954AD2 /* DataStructureTests.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = DataStructureTests.xcconfig; sourceTree = "<group>"; };
|
||||
A88B8C482D35AD3200F53F9D /* OperationsLoggingContolView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OperationsLoggingContolView.swift; sourceTree = "<group>"; };
|
||||
@@ -696,6 +718,7 @@
|
||||
A8C38C2B2D206AD900E83DBD /* AbstractClassError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AbstractClassError.swift; sourceTree = "<group>"; };
|
||||
A8C38C312D206B2500E83DBD /* FileOutputStream.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileOutputStream.swift; sourceTree = "<group>"; };
|
||||
A8C38C372D2084D000E83DBD /* ConsoleLogView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConsoleLogView.swift; sourceTree = "<group>"; };
|
||||
A8C924232D8E73B1009D9953 /* AltStore11ToAltStore17.xcmappingmodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcmappingmodel; path = AltStore11ToAltStore17.xcmappingmodel; sourceTree = "<group>"; };
|
||||
A8D484D72D0CD306002C691D /* AltBackup.ipa */ = {isa = PBXFileReference; lastKnownFileType = file; path = AltBackup.ipa; sourceTree = "<group>"; };
|
||||
A8D49F522D3D2F9400844B92 /* ProcessInfo+AltStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ProcessInfo+AltStore.swift"; sourceTree = "<group>"; };
|
||||
A8E2DB212D684CBD009E5D31 /* UITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = UITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
@@ -1246,6 +1269,17 @@
|
||||
path = Intents;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
A815AAA62D9108CB00929A9E /* v11-to-v17_1 */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
A815AAA22D9108CB00929A9E /* Source11To17_1MigrationPolicy.swift */,
|
||||
A815AAA32D9108CB00929A9E /* StoreApp11To17_1MigrationPolicy.swift */,
|
||||
A815AAA42D9108CB00929A9E /* ReleaseTrack11To17_1MigrationPolicy.swift */,
|
||||
A815AAA52D9108CB00929A9E /* AppPermission11To17_1MigrationPolicy.swift */,
|
||||
);
|
||||
path = "v11-to-v17_1";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
A81A8CB22D68B2030086C96F /* UnitTests */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@@ -1281,6 +1315,26 @@
|
||||
path = xcconfigs;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
A85E43732D8AF82100E89240 /* v11-to-v17 */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D5185B812AE1E71D00646E33 /* Source11To17MigrationPolicy.swift */,
|
||||
A881E7CA2D6EF5AB00954AD2 /* StoreApp11To17MigrationPolicy.swift */,
|
||||
);
|
||||
path = "v11-to-v17";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
A85E43742D8AF84200E89240 /* v17-to-v17_1 */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
A81BF9E32D84CB0C00768940 /* Source17To17_1MigrationPolicy.swift */,
|
||||
A815AA942D90D2A100929A9E /* StoreApp17To17_1MigrationPolicy.swift */,
|
||||
A815AA962D90E16400929A9E /* ReleaseTrack17To17_1MigrationPolicy.swift */,
|
||||
A81BF9E22D84CB0C00768940 /* AppPermission17To17_1MigrationPolicy.swift */,
|
||||
);
|
||||
path = "v17-to-v17_1";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
A86315DD2D3EB2BD0048FA40 /* errors */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@@ -1393,6 +1447,7 @@
|
||||
A8C38C272D206AA500E83DBD /* common */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
A815AA9E2D9104DD00929A9E /* BuildInfo.swift */,
|
||||
A8B516E52D2668020047047C /* DateTimeUtil.swift */,
|
||||
A8C38C282D206AC100E83DBD /* OutputStream.swift */,
|
||||
A8C38C312D206B2500E83DBD /* FileOutputStream.swift */,
|
||||
@@ -1821,10 +1876,11 @@
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
BF66EEAF2501AECA007EE018 /* InstalledAppPolicy.swift */,
|
||||
D5185B812AE1E71D00646E33 /* Source11To17MigrationPolicy.swift */,
|
||||
BF66EEAE2501AECA007EE018 /* StoreAppPolicy.swift */,
|
||||
D5F99A1928D12B1400476A16 /* StoreApp10ToStoreApp11Policy.swift */,
|
||||
A881E7CA2D6EF5AB00954AD2 /* StoreApp11To17MigrationPolicy.swift */,
|
||||
A85E43732D8AF82100E89240 /* v11-to-v17 */,
|
||||
A85E43742D8AF84200E89240 /* v17-to-v17_1 */,
|
||||
A815AAA62D9108CB00929A9E /* v11-to-v17_1 */,
|
||||
);
|
||||
path = Policies;
|
||||
sourceTree = "<group>";
|
||||
@@ -1832,7 +1888,9 @@
|
||||
BF66EEB02501AECA007EE018 /* Mapping Models */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
A881E7C62D6EF58C00954AD2 /* AltStore11ToAltStore17.xcmappingmodel */,
|
||||
A815AAA02D9108BC00929A9E /* AltStore11ToAltStore17_1.xcmappingmodel */,
|
||||
A815AA982D90E5E500929A9E /* AltStore17ToAltStore17_1.xcmappingmodel */,
|
||||
A8C924232D8E73B1009D9953 /* AltStore11ToAltStore17.xcmappingmodel */,
|
||||
D5F99A1728D11DB500476A16 /* AltStore10ToAltStore11.xcmappingmodel */,
|
||||
D5CA0C4D280E249E00469595 /* AltStore9ToAltStore10.xcmappingmodel */,
|
||||
BFBF331A2526762200B7B8C9 /* AltStore8ToAltStore9.xcmappingmodel */,
|
||||
@@ -3098,6 +3156,7 @@
|
||||
A82067842D03DC0600645C0D /* OperatingSystemVersion+Comparable.swift in Sources */,
|
||||
D5FB28EE2ADDF89800A1C337 /* KnownSource.swift in Sources */,
|
||||
BF66EED32501AECA007EE018 /* AltStore2ToAltStore3.xcmappingmodel in Sources */,
|
||||
A815AA972D90E16400929A9E /* ReleaseTrack17To17_1MigrationPolicy.swift in Sources */,
|
||||
BF66EEA52501AEC5007EE018 /* Benefit.swift in Sources */,
|
||||
D52B4ABF2AF183F0005991C3 /* WebViewController.swift in Sources */,
|
||||
BF66EED22501AECA007EE018 /* AltStore4ToAltStore5.xcmappingmodel in Sources */,
|
||||
@@ -3106,17 +3165,26 @@
|
||||
BF66EECD2501AECA007EE018 /* StoreAppPolicy.swift in Sources */,
|
||||
BF66EEE82501AED0007EE018 /* UserDefaults+AltStore.swift in Sources */,
|
||||
BF340E9A250AD39500A192CB /* ViewApp.intentdefinition in Sources */,
|
||||
A8C924242D8E73B1009D9953 /* AltStore11ToAltStore17.xcmappingmodel in Sources */,
|
||||
D552EB062AF453F900A3AB4D /* URL+Normalized.swift in Sources */,
|
||||
BFAECC522501B0A400528F27 /* CodableError.swift in Sources */,
|
||||
A8FD915F2D046F5200322782 /* UserInfoValue.swift in Sources */,
|
||||
D5F9821D2AB900060045751F /* AppScreenshot.swift in Sources */,
|
||||
BF66EE9E2501AEC1007EE018 /* Fetchable.swift in Sources */,
|
||||
BF66EEDF2501AECA007EE018 /* PatreonAccount.swift in Sources */,
|
||||
A815AAA12D9108BC00929A9E /* AltStore11ToAltStore17_1.xcmappingmodel in Sources */,
|
||||
BFAECC532501B0A400528F27 /* ServerProtocol.swift in Sources */,
|
||||
A81BF9E52D84CB0C00768940 /* AppPermission17To17_1MigrationPolicy.swift in Sources */,
|
||||
A81BF9E72D84CB0C00768940 /* Source17To17_1MigrationPolicy.swift in Sources */,
|
||||
BFAECC572501B0A400528F27 /* ConnectionManager.swift in Sources */,
|
||||
BF66EE9D2501AEC1007EE018 /* AppProtocol.swift in Sources */,
|
||||
D519AD46292D665B004B12F9 /* Managed.swift in Sources */,
|
||||
D52A2F972ACB40F700BDF8E3 /* Logger+AltStore.swift in Sources */,
|
||||
A815AA952D90D2A100929A9E /* StoreApp17To17_1MigrationPolicy.swift in Sources */,
|
||||
A815AAA72D9108CB00929A9E /* ReleaseTrack11To17_1MigrationPolicy.swift in Sources */,
|
||||
A815AAA82D9108CB00929A9E /* AppPermission11To17_1MigrationPolicy.swift in Sources */,
|
||||
A815AAA92D9108CB00929A9E /* Source11To17_1MigrationPolicy.swift in Sources */,
|
||||
A815AAAA2D9108CB00929A9E /* StoreApp11To17_1MigrationPolicy.swift in Sources */,
|
||||
BFC712C42512D5F100AB5EBE /* XPCConnection.swift in Sources */,
|
||||
D5CA0C4B280E141900469595 /* ManagedPatron.swift in Sources */,
|
||||
BF66EE8C2501AEB2007EE018 /* Keychain.swift in Sources */,
|
||||
@@ -3179,11 +3247,11 @@
|
||||
BF66EECE2501AECA007EE018 /* InstalledAppPolicy.swift in Sources */,
|
||||
BF1FE359251A9FB000C3CE09 /* NSXPCConnection+MachServices.swift in Sources */,
|
||||
BF66EEA62501AEC5007EE018 /* PatreonAPI.swift in Sources */,
|
||||
A881E7C72D6EF58C00954AD2 /* AltStore11ToAltStore17.xcmappingmodel in Sources */,
|
||||
BF66EED02501AECA007EE018 /* AltStore6ToAltStore7.xcmappingmodel in Sources */,
|
||||
BF66EEDC2501AECA007EE018 /* MergePolicy.swift in Sources */,
|
||||
BF66EEE22501AECA007EE018 /* InstalledExtension.swift in Sources */,
|
||||
BF66EED62501AECA007EE018 /* NewsItem.swift in Sources */,
|
||||
A815AA992D90E5E500929A9E /* AltStore17ToAltStore17_1.xcmappingmodel in Sources */,
|
||||
BF66EEA72501AEC5007EE018 /* Campaign.swift in Sources */,
|
||||
D52C8F032AFC56F000CA0BDD /* StoreCategory.swift in Sources */,
|
||||
BF66EE992501AEBC007EE018 /* ALTSourceUserInfoKey.m in Sources */,
|
||||
@@ -3332,6 +3400,7 @@
|
||||
BF0C4EBD22A1BD8B009A2DD7 /* AppManager.swift in Sources */,
|
||||
BF2901312318F7A800D88A45 /* AppBannerView.swift in Sources */,
|
||||
0EE7FDC42BE8BC7900D1E390 /* ALTLocalizedError.swift in Sources */,
|
||||
A815AA9F2D9104DD00929A9E /* BuildInfo.swift in Sources */,
|
||||
BFF00D342501BDCF00746320 /* IntentHandler.swift in Sources */,
|
||||
BFDBBD80246CB84F004ED2F3 /* RemoveAppBackupOperation.swift in Sources */,
|
||||
A8C38C2A2D206AC100E83DBD /* OutputStream.swift in Sources */,
|
||||
@@ -4340,6 +4409,7 @@
|
||||
BF66EEB72501AECA007EE018 /* AltStore.xcdatamodeld */ = {
|
||||
isa = XCVersionGroup;
|
||||
children = (
|
||||
A81BF9E12D84C9E900768940 /* AltStore 17_1.xcdatamodel */,
|
||||
D51E83802B86926B0092FC61 /* AltStore 17.xcdatamodel */,
|
||||
D52E988928D002D30032BE6B /* AltStore 11.xcdatamodel */,
|
||||
D5CA0C4C280E242500469595 /* AltStore 10.xcdatamodel */,
|
||||
@@ -4353,7 +4423,7 @@
|
||||
BF66EEBD2501AECA007EE018 /* AltStore 2.xcdatamodel */,
|
||||
BF66EEB92501AECA007EE018 /* AltStore.xcdatamodel */,
|
||||
);
|
||||
currentVersion = D51E83802B86926B0092FC61 /* AltStore 17.xcdatamodel */;
|
||||
currentVersion = A81BF9E12D84C9E900768940 /* AltStore 17_1.xcdatamodel */;
|
||||
path = AltStore.xcdatamodeld;
|
||||
sourceTree = "<group>";
|
||||
versionGroupType = wrapper.xcdatamodel;
|
||||
|
||||
@@ -11,6 +11,7 @@ import CoreData
|
||||
|
||||
import AltStoreCore
|
||||
import Roxas
|
||||
import SemanticVersion
|
||||
|
||||
@objc(FetchSourceOperation)
|
||||
final class FetchSourceOperation: ResultOperation<Source>
|
||||
@@ -246,9 +247,20 @@ private extension FetchSourceOperation
|
||||
#endif
|
||||
}
|
||||
|
||||
if let previousSourceID = self.$source.identifier
|
||||
let incomingSourceID = source.identifier
|
||||
if let previousSourceID = self.$source.identifier,
|
||||
incomingSourceID != previousSourceID
|
||||
{
|
||||
guard source.identifier == previousSourceID else { throw SourceError.changedID(source.identifier, previousID: previousSourceID, source: source) }
|
||||
// if let version = BuildInfo().marketing_version,
|
||||
// SemanticVersion(version)! <= SemanticVersion("0.6.1")!
|
||||
// {
|
||||
// // delete the source, so that incoming will be saved.
|
||||
// self.source?.managedObjectContext?.delete(self.source!)
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
throw SourceError.changedID(source.identifier, previousID: self.$source.identifier ?? "nil", source: source)
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -263,50 +263,6 @@ final class SettingsViewController: UITableViewController
|
||||
|
||||
}
|
||||
|
||||
private class BuildInfo{
|
||||
private static let MARKETING_VERSION_TAG = "CFBundleShortVersionString"
|
||||
private static let CURRENT_PROJECT_VERSION_TAG = kCFBundleVersionKey as String
|
||||
|
||||
private static let XCODE_VERSION_TAG = "DTXcode"
|
||||
private static let XCODE_REVISION_TAG = "DTXcodeBuild"
|
||||
|
||||
let bundle: Bundle
|
||||
|
||||
public init(){
|
||||
bundle = Bundle.main
|
||||
}
|
||||
|
||||
enum BundleError: Swift.Error {
|
||||
case invalidURL
|
||||
}
|
||||
|
||||
public init(url: URL) throws {
|
||||
guard let bundle = Bundle(url: url) else {
|
||||
throw BundleError.invalidURL
|
||||
}
|
||||
self.bundle = bundle
|
||||
}
|
||||
|
||||
public lazy var project_version: String? = {
|
||||
let version = bundle.object(forInfoDictionaryKey: Self.CURRENT_PROJECT_VERSION_TAG) as? String
|
||||
return version
|
||||
}()
|
||||
|
||||
public lazy var marketing_version: String? = {
|
||||
let version = bundle.object(forInfoDictionaryKey: Self.MARKETING_VERSION_TAG) as? String
|
||||
return version
|
||||
}()
|
||||
|
||||
public lazy var xcode: String? = {
|
||||
let xcode = bundle.object(forInfoDictionaryKey: Self.XCODE_VERSION_TAG) as? String
|
||||
return xcode
|
||||
}()
|
||||
|
||||
public lazy var xcode_revision: String? = {
|
||||
let revision = bundle.object(forInfoDictionaryKey: Self.XCODE_REVISION_TAG) as? String
|
||||
return revision
|
||||
}()
|
||||
}
|
||||
|
||||
private extension SettingsViewController
|
||||
{
|
||||
@@ -993,7 +949,7 @@ extension SettingsViewController
|
||||
|
||||
// Option 2: Discord
|
||||
alertController.addAction(UIAlertAction(title: "Discord", style: .default) { _ in
|
||||
if let discordURL = URL(string: "https://discord.gg/sidestore") {
|
||||
if let discordURL = URL(string: "https://discord.gg/sidestore-949183273383395328") {
|
||||
let safariViewController = SFSafariViewController(url: discordURL)
|
||||
safariViewController.preferredControlTintColor = .altPrimary
|
||||
self.present(safariViewController, animated: true, completion: nil)
|
||||
|
||||
@@ -514,27 +514,27 @@ extension SourcesViewController: NSFetchedResultsControllerDelegate
|
||||
let context = DatabaseManager.shared.persistentContainer.newBackgroundContext()
|
||||
context.performAndWait {
|
||||
_ = Source.make(name: "OatmealDome's AltStore Source",
|
||||
identifier: "me.oatmealdome.altstore",
|
||||
groupID: "me.oatmealdome.altstore",
|
||||
sourceURL: URL(string: "https://altstore.oatmealdome.me")!,
|
||||
context: context)
|
||||
|
||||
_ = Source.make(name: "UTM Repository",
|
||||
identifier: "com.utmapp.repos.UTM",
|
||||
groupID: "com.utmapp.repos.UTM",
|
||||
sourceURL: URL(string: "https://alt.getutm.app")!,
|
||||
context: context)
|
||||
|
||||
_ = Source.make(name: "Flyinghead",
|
||||
identifier: "com.flyinghead.source",
|
||||
groupID: "com.flyinghead.source",
|
||||
sourceURL: URL(string: "https://flyinghead.github.io/flycast-builds/altstore.json")!,
|
||||
context: context)
|
||||
|
||||
_ = Source.make(name: "Provenance",
|
||||
identifier: "org.provenance-emu.AltStore",
|
||||
groupID: "org.provenance-emu.AltStore",
|
||||
sourceURL: URL(string: "https://provenance-emu.com/apps.json")!,
|
||||
context: context)
|
||||
|
||||
_ = Source.make(name: "PojavLauncher Repository",
|
||||
identifier: "dev.crystall1ne.repos.PojavLauncher",
|
||||
groupID: "dev.crystall1ne.repos.PojavLauncher",
|
||||
sourceURL: URL(string: "http://alt.crystall1ne.dev")!,
|
||||
context: context)
|
||||
|
||||
|
||||
@@ -3,6 +3,6 @@
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>_XCCurrentVersionName</key>
|
||||
<string>AltStore 17.xcdatamodel</string>
|
||||
<string>AltStore 17_1.xcdatamodel</string>
|
||||
</dict>
|
||||
</plist>
|
||||
|
||||
@@ -0,0 +1,315 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<model type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="23605" systemVersion="24D70" minimumToolsVersion="Automatic" sourceLanguage="Swift" userDefinedModelVersionIdentifier="v17.1">
|
||||
<entity name="Account" representedClassName="Account" syncable="YES">
|
||||
<attribute name="appleID" attributeType="String"/>
|
||||
<attribute name="firstName" attributeType="String"/>
|
||||
<attribute name="identifier" attributeType="String"/>
|
||||
<attribute name="isActiveAccount" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
|
||||
<attribute name="lastName" attributeType="String"/>
|
||||
<relationship name="teams" toMany="YES" deletionRule="Cascade" destinationEntity="Team" inverseName="account" inverseEntity="Team"/>
|
||||
<uniquenessConstraints>
|
||||
<uniquenessConstraint>
|
||||
<constraint value="identifier"/>
|
||||
</uniquenessConstraint>
|
||||
</uniquenessConstraints>
|
||||
</entity>
|
||||
<entity name="AppID" representedClassName="AppID" syncable="YES">
|
||||
<attribute name="bundleIdentifier" attributeType="String"/>
|
||||
<attribute name="expirationDate" optional="YES" attributeType="Date" usesScalarValueType="NO"/>
|
||||
<attribute name="features" attributeType="Transformable" valueTransformerName="ALTSecureValueTransformer"/>
|
||||
<attribute name="identifier" attributeType="String"/>
|
||||
<attribute name="name" attributeType="String"/>
|
||||
<relationship name="team" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="Team" inverseName="appIDs" inverseEntity="Team"/>
|
||||
<uniquenessConstraints>
|
||||
<uniquenessConstraint>
|
||||
<constraint value="identifier"/>
|
||||
</uniquenessConstraint>
|
||||
</uniquenessConstraints>
|
||||
</entity>
|
||||
<entity name="AppPermission" representedClassName="AppPermission" syncable="YES">
|
||||
<attribute name="appBundleID" optional="YES" attributeType="String"/>
|
||||
<attribute name="permission" optional="YES" attributeType="String"/>
|
||||
<attribute name="sourceID" optional="YES" attributeType="String"/>
|
||||
<attribute name="type" attributeType="String"/>
|
||||
<attribute name="usageDescription" attributeType="String"/>
|
||||
<relationship name="app" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="StoreApp" inverseName="permissions" inverseEntity="StoreApp"/>
|
||||
<uniquenessConstraints>
|
||||
<uniquenessConstraint>
|
||||
<constraint value="sourceID"/>
|
||||
<constraint value="appBundleID"/>
|
||||
<constraint value="type"/>
|
||||
<constraint value="permission"/>
|
||||
</uniquenessConstraint>
|
||||
</uniquenessConstraints>
|
||||
</entity>
|
||||
<entity name="AppScreenshot" representedClassName="AppScreenshot" syncable="YES">
|
||||
<attribute name="appBundleID" optional="YES" attributeType="String"/>
|
||||
<attribute name="deviceType" attributeType="Integer 16" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="height" optional="YES" attributeType="Integer 16" usesScalarValueType="NO"/>
|
||||
<attribute name="imageURL" attributeType="URI"/>
|
||||
<attribute name="sourceID" optional="YES" attributeType="String"/>
|
||||
<attribute name="width" optional="YES" attributeType="Integer 16" usesScalarValueType="NO"/>
|
||||
<relationship name="app" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="StoreApp" inverseName="screenshots" inverseEntity="StoreApp"/>
|
||||
<uniquenessConstraints>
|
||||
<uniquenessConstraint>
|
||||
<constraint value="sourceID"/>
|
||||
<constraint value="appBundleID"/>
|
||||
<constraint value="imageURL"/>
|
||||
</uniquenessConstraint>
|
||||
</uniquenessConstraints>
|
||||
</entity>
|
||||
<entity name="AppVersion" representedClassName="AppVersion" syncable="YES">
|
||||
<attribute name="appBundleID" optional="YES" attributeType="String"/>
|
||||
<attribute name="buildVersion" optional="YES" attributeType="String"/>
|
||||
<attribute name="channel" optional="YES" attributeType="String"/>
|
||||
<attribute name="date" attributeType="Date" usesScalarValueType="NO"/>
|
||||
<attribute name="downloadURL" attributeType="URI"/>
|
||||
<attribute name="localizedDescription" optional="YES" attributeType="String"/>
|
||||
<attribute name="maxOSVersion" optional="YES" attributeType="String"/>
|
||||
<attribute name="minOSVersion" optional="YES" attributeType="String"/>
|
||||
<attribute name="sha256" optional="YES" attributeType="String"/>
|
||||
<attribute name="size" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="sourceID" optional="YES" attributeType="String"/>
|
||||
<attribute name="version" attributeType="String"/>
|
||||
<relationship name="app" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="StoreApp" inverseName="versions" inverseEntity="StoreApp"/>
|
||||
<relationship name="latestVersionApp" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="StoreApp" inverseName="latestVersion" inverseEntity="StoreApp"/>
|
||||
<relationship name="releaseTrack" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="ReleaseTrack" inverseName="releases" inverseEntity="ReleaseTrack"/>
|
||||
<uniquenessConstraints>
|
||||
<uniquenessConstraint>
|
||||
<constraint value="sourceID"/>
|
||||
<constraint value="appBundleID"/>
|
||||
<constraint value="version"/>
|
||||
<constraint value="buildVersion"/>
|
||||
</uniquenessConstraint>
|
||||
</uniquenessConstraints>
|
||||
</entity>
|
||||
<entity name="InstalledApp" representedClassName="InstalledApp" syncable="YES">
|
||||
<attribute name="buildVersion" optional="YES" attributeType="String"/>
|
||||
<attribute name="bundleIdentifier" attributeType="String"/>
|
||||
<attribute name="certificateSerialNumber" optional="YES" attributeType="String"/>
|
||||
<attribute name="expirationDate" attributeType="Date" usesScalarValueType="NO"/>
|
||||
<attribute name="hasAlternateIcon" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
|
||||
<attribute name="hasUpdate" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
|
||||
<attribute name="installedDate" attributeType="Date" usesScalarValueType="NO"/>
|
||||
<attribute name="isActive" attributeType="Boolean" defaultValueString="YES" usesScalarValueType="YES"/>
|
||||
<attribute name="isRefreshing" transient="YES" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
|
||||
<attribute name="name" attributeType="String"/>
|
||||
<attribute name="needsResign" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
|
||||
<attribute name="refreshedDate" attributeType="Date" usesScalarValueType="NO"/>
|
||||
<attribute name="resignedBundleIdentifier" attributeType="String"/>
|
||||
<attribute name="storeBuildVersion" optional="YES" attributeType="String"/>
|
||||
<attribute name="version" attributeType="String"/>
|
||||
<relationship name="appExtensions" toMany="YES" deletionRule="Cascade" destinationEntity="InstalledExtension" inverseName="parentApp" inverseEntity="InstalledExtension"/>
|
||||
<relationship name="loggedErrors" toMany="YES" deletionRule="Nullify" destinationEntity="LoggedError" inverseName="installedApp" inverseEntity="LoggedError"/>
|
||||
<relationship name="storeApp" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="StoreApp" inverseName="installedApp" inverseEntity="StoreApp"/>
|
||||
<relationship name="team" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="Team" inverseName="installedApps" inverseEntity="Team"/>
|
||||
<uniquenessConstraints>
|
||||
<uniquenessConstraint>
|
||||
<constraint value="bundleIdentifier"/>
|
||||
</uniquenessConstraint>
|
||||
</uniquenessConstraints>
|
||||
</entity>
|
||||
<entity name="InstalledExtension" representedClassName="InstalledExtension" syncable="YES">
|
||||
<attribute name="bundleIdentifier" attributeType="String"/>
|
||||
<attribute name="expirationDate" attributeType="Date" usesScalarValueType="NO"/>
|
||||
<attribute name="installedDate" attributeType="Date" usesScalarValueType="NO"/>
|
||||
<attribute name="name" attributeType="String"/>
|
||||
<attribute name="refreshedDate" attributeType="Date" usesScalarValueType="NO"/>
|
||||
<attribute name="resignedBundleIdentifier" attributeType="String"/>
|
||||
<attribute name="version" attributeType="String"/>
|
||||
<relationship name="parentApp" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="InstalledApp" inverseName="appExtensions" inverseEntity="InstalledApp"/>
|
||||
</entity>
|
||||
<entity name="LoggedError" representedClassName="LoggedError" syncable="YES">
|
||||
<attribute name="appBundleID" attributeType="String"/>
|
||||
<attribute name="appName" attributeType="String"/>
|
||||
<attribute name="code" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="date" attributeType="Date" usesScalarValueType="NO"/>
|
||||
<attribute name="domain" attributeType="String"/>
|
||||
<attribute name="operation" optional="YES" attributeType="String"/>
|
||||
<attribute name="userInfo" attributeType="Transformable" valueTransformerName="ALTSecureValueTransformer"/>
|
||||
<relationship name="installedApp" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="InstalledApp" inverseName="loggedErrors" inverseEntity="InstalledApp"/>
|
||||
<relationship name="storeApp" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="StoreApp" inverseName="loggedErrors" inverseEntity="StoreApp"/>
|
||||
</entity>
|
||||
<entity name="NewsItem" representedClassName="NewsItem" syncable="YES">
|
||||
<attribute name="appID" optional="YES" attributeType="String"/>
|
||||
<attribute name="caption" attributeType="String"/>
|
||||
<attribute name="date" attributeType="Date" usesScalarValueType="NO"/>
|
||||
<attribute name="externalURL" optional="YES" attributeType="URI"/>
|
||||
<attribute name="identifier" attributeType="String"/>
|
||||
<attribute name="imageURL" optional="YES" attributeType="URI"/>
|
||||
<attribute name="isSilent" attributeType="Boolean" defaultValueString="YES" usesScalarValueType="YES"/>
|
||||
<attribute name="sortIndex" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="sourceIdentifier" optional="YES" attributeType="String"/>
|
||||
<attribute name="tintColor" optional="YES" attributeType="Transformable" valueTransformerName="ALTSecureValueTransformer"/>
|
||||
<attribute name="title" attributeType="String"/>
|
||||
<relationship name="source" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="Source" inverseName="newsItems" inverseEntity="Source"/>
|
||||
<relationship name="storeApp" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="StoreApp" inverseName="newsItems" inverseEntity="StoreApp"/>
|
||||
<uniquenessConstraints>
|
||||
<uniquenessConstraint>
|
||||
<constraint value="identifier"/>
|
||||
<constraint value="sourceIdentifier"/>
|
||||
</uniquenessConstraint>
|
||||
</uniquenessConstraints>
|
||||
</entity>
|
||||
<entity name="PatreonAccount" representedClassName="PatreonAccount" syncable="YES">
|
||||
<attribute name="firstName" optional="YES" attributeType="String"/>
|
||||
<attribute name="identifier" attributeType="String"/>
|
||||
<attribute name="isPatron" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
|
||||
<attribute name="name" attributeType="String"/>
|
||||
<relationship name="pledges" toMany="YES" deletionRule="Cascade" destinationEntity="Pledge" inverseName="account" inverseEntity="Pledge"/>
|
||||
<uniquenessConstraints>
|
||||
<uniquenessConstraint>
|
||||
<constraint value="identifier"/>
|
||||
</uniquenessConstraint>
|
||||
</uniquenessConstraints>
|
||||
</entity>
|
||||
<entity name="Patron" representedClassName="ManagedPatron" syncable="YES">
|
||||
<attribute name="identifier" attributeType="String"/>
|
||||
<attribute name="name" attributeType="String"/>
|
||||
<uniquenessConstraints>
|
||||
<uniquenessConstraint>
|
||||
<constraint value="identifier"/>
|
||||
</uniquenessConstraint>
|
||||
</uniquenessConstraints>
|
||||
</entity>
|
||||
<entity name="Pledge" representedClassName="Pledge" syncable="YES">
|
||||
<attribute name="amount" attributeType="Decimal" defaultValueString="0"/>
|
||||
<attribute name="campaignURL" attributeType="URI"/>
|
||||
<attribute name="identifier" attributeType="String"/>
|
||||
<relationship name="account" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="PatreonAccount" inverseName="pledges" inverseEntity="PatreonAccount"/>
|
||||
<relationship name="rewards" optional="YES" toMany="YES" deletionRule="Cascade" destinationEntity="PledgeReward" inverseName="pledge" inverseEntity="PledgeReward"/>
|
||||
<relationship name="tiers" optional="YES" toMany="YES" deletionRule="Cascade" destinationEntity="PledgeTier" inverseName="pledge" inverseEntity="PledgeTier"/>
|
||||
<uniquenessConstraints>
|
||||
<uniquenessConstraint>
|
||||
<constraint value="identifier"/>
|
||||
</uniquenessConstraint>
|
||||
</uniquenessConstraints>
|
||||
</entity>
|
||||
<entity name="PledgeReward" representedClassName="PledgeReward" syncable="YES">
|
||||
<attribute name="identifier" attributeType="String"/>
|
||||
<attribute name="name" attributeType="String"/>
|
||||
<relationship name="pledge" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="Pledge" inverseName="rewards" inverseEntity="Pledge"/>
|
||||
<uniquenessConstraints>
|
||||
<uniquenessConstraint>
|
||||
<constraint value="identifier"/>
|
||||
</uniquenessConstraint>
|
||||
</uniquenessConstraints>
|
||||
</entity>
|
||||
<entity name="PledgeTier" representedClassName="PledgeTier" syncable="YES">
|
||||
<attribute name="amount" attributeType="Decimal" defaultValueString="0.0"/>
|
||||
<attribute name="identifier" attributeType="String"/>
|
||||
<attribute name="name" optional="YES" attributeType="String"/>
|
||||
<relationship name="pledge" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="Pledge" inverseName="tiers" inverseEntity="Pledge"/>
|
||||
<uniquenessConstraints>
|
||||
<uniquenessConstraint>
|
||||
<constraint value="identifier"/>
|
||||
</uniquenessConstraint>
|
||||
</uniquenessConstraints>
|
||||
</entity>
|
||||
<entity name="RefreshAttempt" representedClassName="RefreshAttempt" syncable="YES">
|
||||
<attribute name="date" attributeType="Date" usesScalarValueType="NO"/>
|
||||
<attribute name="errorDescription" optional="YES" attributeType="String"/>
|
||||
<attribute name="identifier" attributeType="String"/>
|
||||
<attribute name="isSuccess" attributeType="Boolean" defaultValueString="YES" usesScalarValueType="YES"/>
|
||||
<uniquenessConstraints>
|
||||
<uniquenessConstraint>
|
||||
<constraint value="identifier"/>
|
||||
</uniquenessConstraint>
|
||||
</uniquenessConstraints>
|
||||
</entity>
|
||||
<entity name="ReleaseTrack" representedClassName="ReleaseTrack" syncable="YES">
|
||||
<attribute name="appBundleID" optional="YES" attributeType="String"/>
|
||||
<attribute name="sourceID" optional="YES" attributeType="String"/>
|
||||
<attribute name="track" attributeType="String"/>
|
||||
<relationship name="releases" optional="YES" toMany="YES" deletionRule="Cascade" ordered="YES" destinationEntity="AppVersion" inverseName="releaseTrack" inverseEntity="AppVersion"/>
|
||||
<relationship name="storeApp" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="StoreApp" inverseName="releaseTracks" inverseEntity="StoreApp"/>
|
||||
<uniquenessConstraints>
|
||||
<uniquenessConstraint>
|
||||
<constraint value="sourceID"/>
|
||||
<constraint value="appBundleID"/>
|
||||
<constraint value="track"/>
|
||||
</uniquenessConstraint>
|
||||
</uniquenessConstraints>
|
||||
</entity>
|
||||
<entity name="Source" representedClassName="Source" syncable="YES">
|
||||
<attribute name="error" optional="YES" attributeType="Transformable" valueTransformerName="ALTSecureValueTransformer"/>
|
||||
<attribute name="featuredSortID" optional="YES" attributeType="String"/>
|
||||
<attribute name="groupID" optional="YES" attributeType="String"/>
|
||||
<attribute name="hasFeaturedApps" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
|
||||
<attribute name="headerImageURL" optional="YES" attributeType="URI"/>
|
||||
<attribute name="iconURL" optional="YES" attributeType="URI"/>
|
||||
<attribute name="identifier" attributeType="String"/>
|
||||
<attribute name="localizedDescription" optional="YES" attributeType="String"/>
|
||||
<attribute name="name" attributeType="String"/>
|
||||
<attribute name="patreonURL" optional="YES" attributeType="URI"/>
|
||||
<attribute name="sourceURL" attributeType="URI"/>
|
||||
<attribute name="subtitle" optional="YES" attributeType="String"/>
|
||||
<attribute name="tintColor" optional="YES" attributeType="Transformable" valueTransformerName="ALTSecureValueTransformer"/>
|
||||
<attribute name="version" attributeType="Integer 64" defaultValueString="1" usesScalarValueType="YES"/>
|
||||
<attribute name="websiteURL" optional="YES" attributeType="URI"/>
|
||||
<relationship name="apps" toMany="YES" deletionRule="Cascade" ordered="YES" destinationEntity="StoreApp" inverseName="source" inverseEntity="StoreApp"/>
|
||||
<relationship name="featuredApps" optional="YES" toMany="YES" deletionRule="Nullify" ordered="YES" destinationEntity="StoreApp" inverseName="featuringSource" inverseEntity="StoreApp"/>
|
||||
<relationship name="newsItems" toMany="YES" deletionRule="Cascade" ordered="YES" destinationEntity="NewsItem" inverseName="source" inverseEntity="NewsItem"/>
|
||||
<uniquenessConstraints>
|
||||
<uniquenessConstraint>
|
||||
<constraint value="identifier"/>
|
||||
</uniquenessConstraint>
|
||||
</uniquenessConstraints>
|
||||
</entity>
|
||||
<entity name="StoreApp" representedClassName="StoreApp" syncable="YES">
|
||||
<attribute name="bundleIdentifier" attributeType="String"/>
|
||||
<attribute name="category" optional="YES" attributeType="String"/>
|
||||
<attribute name="developerName" attributeType="String"/>
|
||||
<attribute name="downloadURL" optional="YES" attributeType="URI"/>
|
||||
<attribute name="featuredSortID" optional="YES" attributeType="String"/>
|
||||
<attribute name="iconURL" attributeType="URI"/>
|
||||
<attribute name="isHiddenWithoutPledge" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
|
||||
<attribute name="isPledged" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
|
||||
<attribute name="isPledgeRequired" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
|
||||
<attribute name="localizedDescription" attributeType="String"/>
|
||||
<attribute name="marketplaceID" optional="YES" attributeType="String"/>
|
||||
<attribute name="name" attributeType="String"/>
|
||||
<attribute name="pledgeAmount" optional="YES" attributeType="Decimal"/>
|
||||
<attribute name="pledgeCurrency" optional="YES" attributeType="String"/>
|
||||
<attribute name="prefersCustomPledge" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||
<attribute name="screenshotURLs" attributeType="Transformable" valueTransformerName="ALTSecureValueTransformer"/>
|
||||
<attribute name="size" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="sortIndex" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="sourceIdentifier" optional="YES" attributeType="String"/>
|
||||
<attribute name="subtitle" optional="YES" attributeType="String"/>
|
||||
<attribute name="tintColor" optional="YES" attributeType="Transformable" valueTransformerName="ALTSecureValueTransformer"/>
|
||||
<attribute name="version" optional="YES" attributeType="String"/>
|
||||
<attribute name="versionDate" optional="YES" attributeType="Date" usesScalarValueType="NO"/>
|
||||
<attribute name="versionDescription" optional="YES" attributeType="String"/>
|
||||
<relationship name="featuringSource" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="Source" inverseName="featuredApps" inverseEntity="Source"/>
|
||||
<relationship name="installedApp" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="InstalledApp" inverseName="storeApp" inverseEntity="InstalledApp"/>
|
||||
<relationship name="latestVersion" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="AppVersion" inverseName="latestVersionApp" inverseEntity="AppVersion"/>
|
||||
<relationship name="loggedErrors" toMany="YES" deletionRule="Nullify" destinationEntity="LoggedError" inverseName="storeApp" inverseEntity="LoggedError"/>
|
||||
<relationship name="newsItems" toMany="YES" deletionRule="Nullify" destinationEntity="NewsItem" inverseName="storeApp" inverseEntity="NewsItem"/>
|
||||
<relationship name="permissions" toMany="YES" deletionRule="Cascade" destinationEntity="AppPermission" inverseName="app" inverseEntity="AppPermission"/>
|
||||
<relationship name="releaseTracks" optional="YES" toMany="YES" deletionRule="Cascade" ordered="YES" destinationEntity="ReleaseTrack" inverseName="storeApp" inverseEntity="ReleaseTrack"/>
|
||||
<relationship name="screenshots" toMany="YES" deletionRule="Cascade" ordered="YES" destinationEntity="AppScreenshot" inverseName="app" inverseEntity="AppScreenshot"/>
|
||||
<relationship name="source" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="Source" inverseName="apps" inverseEntity="Source"/>
|
||||
<relationship name="versions" toMany="YES" deletionRule="Cascade" ordered="YES" destinationEntity="AppVersion" inverseName="app" inverseEntity="AppVersion"/>
|
||||
<uniquenessConstraints>
|
||||
<uniquenessConstraint>
|
||||
<constraint value="sourceIdentifier"/>
|
||||
<constraint value="bundleIdentifier"/>
|
||||
</uniquenessConstraint>
|
||||
</uniquenessConstraints>
|
||||
</entity>
|
||||
<entity name="Team" representedClassName="Team" syncable="YES">
|
||||
<attribute name="identifier" attributeType="String"/>
|
||||
<attribute name="isActiveTeam" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
|
||||
<attribute name="name" attributeType="String"/>
|
||||
<attribute name="type" attributeType="Integer 16" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<relationship name="account" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="Account" inverseName="teams" inverseEntity="Account"/>
|
||||
<relationship name="appIDs" toMany="YES" deletionRule="Cascade" destinationEntity="AppID" inverseName="team" inverseEntity="AppID"/>
|
||||
<relationship name="installedApps" toMany="YES" deletionRule="Nullify" destinationEntity="InstalledApp" inverseName="team" inverseEntity="InstalledApp"/>
|
||||
<uniquenessConstraints>
|
||||
<uniquenessConstraint>
|
||||
<constraint value="identifier"/>
|
||||
</uniquenessConstraint>
|
||||
</uniquenessConstraints>
|
||||
</entity>
|
||||
</model>
|
||||
@@ -33,7 +33,7 @@ public class AppPermission: BaseEntity
|
||||
default: return UnknownAppPermission(rawValue: self._permission)
|
||||
}
|
||||
}
|
||||
@NSManaged @objc(permission) private var _permission: String
|
||||
@NSManaged @objc(permission) private(set) public var _permission: String
|
||||
|
||||
// Set by StoreApp.
|
||||
@NSManaged public var appBundleID: String
|
||||
|
||||
@@ -213,6 +213,7 @@ extension MergePolicy{
|
||||
}
|
||||
|
||||
default:
|
||||
// break
|
||||
// Unknown context-level conflict.
|
||||
// assertionFailure("MergePolicy is only intended to work with database-level conflicts.")
|
||||
assertionFailure("Context Conflict Detected: is there ambigious data in your incoming sources?\nConflict:\(conflict)")
|
||||
|
||||
@@ -505,13 +505,14 @@ cxIAAYagXxAPTlNLZXllZEFyY2hpdmVy0QAIAAlUcm9vdIABrxESLAALAAwAGQA1ADYANwBjAGQAZQBm
|
||||
<relationship name="relationshipmappings" type="0/0" destination="XDDEVRELATIONSHIPMAPPING" idrefs="z142 z119 z223 z116 z229 z139 z236 z136 z214 z216"></relationship>
|
||||
</object>
|
||||
<object type="XDDEVENTITYMAPPING" id="z198">
|
||||
<attribute name="migrationpolicyclassname" type="string"></attribute>
|
||||
<attribute name="sourcename" type="string">AppPermission</attribute>
|
||||
<attribute name="mappingtypename" type="string">Undefined</attribute>
|
||||
<attribute name="mappingnumber" type="int16">17</attribute>
|
||||
<attribute name="destinationname" type="string">AppPermission</attribute>
|
||||
<attribute name="autogenerateexpression" type="bool">1</attribute>
|
||||
<relationship name="mappingmodel" type="1/1" destination="XDDEVMAPPINGMODEL" idrefs="z192"></relationship>
|
||||
<relationship name="attributemappings" type="0/0" destination="XDDEVATTRIBUTEMAPPING" idrefs="z213 z240 z191 z123 z287"></relationship>
|
||||
<relationship name="attributemappings" type="0/0" destination="XDDEVATTRIBUTEMAPPING" idrefs="z123 z213 z287 z240 z191"></relationship>
|
||||
<relationship name="relationshipmappings" type="0/0" destination="XDDEVRELATIONSHIPMAPPING" idrefs="z288"></relationship>
|
||||
</object>
|
||||
<object type="XDDEVENTITYMAPPING" id="z199">
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1,5 +1,5 @@
|
||||
//
|
||||
// SourceMigrationPolicy.swift
|
||||
// Source11To17MigrationPolicy.swift
|
||||
// AltStoreCore
|
||||
//
|
||||
// Created by Riley Testut on 10/19/23.
|
||||
@@ -1,5 +1,5 @@
|
||||
//
|
||||
// StoreAppMigration11To17Policy.swift
|
||||
// StoreApp11To17MigrationPolicy.swift
|
||||
// AltStore
|
||||
//
|
||||
// Created by Magesh K on 25/02/25.
|
||||
@@ -108,7 +108,7 @@ class StoreApp11To17MigrationPolicy: NSEntityMigrationPolicy {
|
||||
|
||||
// Create a new ReleaseTrack entity
|
||||
let context = dInstance.managedObjectContext!
|
||||
let releaseTrack = NSEntityDescription.insertNewObject(forEntityName: ReleaseTrack.entity().name!, into: context)
|
||||
let releaseTrack = NSEntityDescription.insertNewObject(forEntityName: ReleaseTrack.entity().name ?? ReleaseTrack.description(), into: context)
|
||||
releaseTrack.setValue(defaultChannel, forKey: #keyPath(ReleaseTrack._track))
|
||||
|
||||
// Connect the releaseTrack to the destination StoreApp
|
||||
@@ -116,7 +116,7 @@ class StoreApp11To17MigrationPolicy: NSEntityMigrationPolicy {
|
||||
|
||||
|
||||
// Find the mapping name for AppVersion (make sure this exactly matches your mapping model)
|
||||
let appVersionMappingName = findEntityMappingName(for: AppVersion.entity().name!, in: manager)
|
||||
let appVersionMappingName = findEntityMappingName(for: AppVersion.entity().name ?? AppVersion.description(), in: manager)
|
||||
|
||||
// Create a mutable ordered set for the destination AppVersion objects
|
||||
let destinationVersionsSet = NSMutableOrderedSet()
|
||||
@@ -145,5 +145,5 @@ class StoreApp11To17MigrationPolicy: NSEntityMigrationPolicy {
|
||||
// dInstance.setValue(NSOrderedSet(), forKey: #keyPath(StoreApp._versions))
|
||||
dInstance.setValue(nil, forKey: #keyPath(StoreApp._versions))
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
//
|
||||
// AppPermission17to17_1MigrationPolicy.swift
|
||||
// AltStore
|
||||
//
|
||||
// Created by Magesh K on 15/03/25.
|
||||
// Copyright © 2025 SideStore. All rights reserved.
|
||||
//
|
||||
|
||||
import CoreData
|
||||
|
||||
@objc(AppPermission11To17_1MigrationPolicy)
|
||||
class AppPermission11To17_1MigrationPolicy: AppPermission17To17_1MigrationPolicy {
|
||||
|
||||
override func createDestinationInstances(forSource sInstance: NSManagedObject, in mapping: NSEntityMapping, manager: NSMigrationManager) throws {
|
||||
// Let the default implementation create the basic destination AppPermission
|
||||
try super.createDestinationInstances(forSource: sInstance, in: mapping, manager: manager)
|
||||
}
|
||||
|
||||
|
||||
|
||||
override func createRelationships(
|
||||
forDestination dInstance: NSManagedObject,
|
||||
in mapping: NSEntityMapping,
|
||||
manager: NSMigrationManager
|
||||
) throws {
|
||||
try super.createRelationships(forDestination: dInstance, in: mapping, manager: manager)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
//
|
||||
// ReleaseTrack11To17_1MigrationPolicy.swift
|
||||
// AltStore
|
||||
//
|
||||
// Created by Magesh K on 15/03/25.
|
||||
// Copyright © 2025 SideStore. All rights reserved.
|
||||
//
|
||||
|
||||
import CoreData
|
||||
|
||||
@objc(ReleaseTrack11To17_1MigrationPolicy)
|
||||
class ReleaseTrack11To17_1MigrationPolicy: ReleaseTrack17To17_1MigrationPolicy {
|
||||
|
||||
override func createDestinationInstances(forSource sInstance: NSManagedObject, in mapping: NSEntityMapping, manager: NSMigrationManager) throws {
|
||||
try super.createDestinationInstances(forSource: sInstance, in: mapping, manager: manager)
|
||||
}
|
||||
|
||||
|
||||
override func createRelationships(
|
||||
forDestination dInstance: NSManagedObject,
|
||||
in mapping: NSEntityMapping,
|
||||
manager: NSMigrationManager
|
||||
) throws {
|
||||
try super.createRelationships(forDestination: dInstance, in: mapping, manager: manager)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
//
|
||||
// Source11To17_1MigrationPolicy.swift
|
||||
// AltStore
|
||||
//
|
||||
// Created by Magesh K on 15/03/25.
|
||||
// Copyright © 2025 SideStore. All rights reserved.
|
||||
//
|
||||
|
||||
import CoreData
|
||||
|
||||
@objc(Source11To17_1MigrationPolicy)
|
||||
class Source11To17_1MigrationPolicy: Source17To17_1MigrationPolicy
|
||||
{
|
||||
override func createDestinationInstances(forSource sInstance: NSManagedObject, in mapping: NSEntityMapping, manager: NSMigrationManager) throws {
|
||||
// Let the default implementation create the basic destination AppPermission
|
||||
try super.createDestinationInstances(forSource: sInstance, in: mapping, manager: manager)
|
||||
}
|
||||
|
||||
override func createRelationships(forDestination dInstance: NSManagedObject, in mapping: NSEntityMapping, manager: NSMigrationManager) throws
|
||||
{
|
||||
try super.createRelationships(forDestination: dInstance, in: mapping, manager: manager)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
//
|
||||
// StoreApp11To17_1MigrationPolicy.swift
|
||||
// AltStore
|
||||
//
|
||||
// Created by Magesh K on 15/03/25.
|
||||
// Copyright © 2025 SideStore. All rights reserved.
|
||||
//
|
||||
|
||||
import CoreData
|
||||
|
||||
fileprivate extension NSManagedObject
|
||||
{
|
||||
var storeAppReleaseTracks: NSOrderedSet? {
|
||||
let tracks = self.value(forKey: #keyPath(StoreApp._releaseTracks)) as? NSOrderedSet
|
||||
return tracks
|
||||
}
|
||||
}
|
||||
|
||||
@objc(StoreApp11To17_1MigrationPolicy)
|
||||
class StoreApp11To17_1MigrationPolicy: StoreApp11To17MigrationPolicy
|
||||
{
|
||||
override func createDestinationInstances(forSource sInstance: NSManagedObject, in mapping: NSEntityMapping, manager: NSMigrationManager) throws {
|
||||
try super.createDestinationInstances(forSource: sInstance, in: mapping, manager: manager)
|
||||
}
|
||||
|
||||
override func createRelationships(forDestination dInstance: NSManagedObject, in mapping: NSEntityMapping, manager: NSMigrationManager) throws
|
||||
{
|
||||
try super.createRelationships(forDestination: dInstance, in: mapping, manager: manager)
|
||||
|
||||
let appBundleID = dInstance.value(forKey: #keyPath(StoreApp.bundleIdentifier))
|
||||
let sourceID = dInstance.value(forKey: #keyPath(StoreApp.sourceIdentifier))
|
||||
|
||||
for case let track as NSManagedObject in dInstance.storeAppReleaseTracks ?? []
|
||||
{
|
||||
track.setValue(appBundleID, forKey: #keyPath(ReleaseTrack._appBundleID))
|
||||
track.setValue(sourceID, forKey: #keyPath(ReleaseTrack._sourceID))
|
||||
|
||||
guard let releases = track.value(forKey: #keyPath(ReleaseTrack._releases)) as? NSOrderedSet else {
|
||||
continue
|
||||
}
|
||||
|
||||
for case let version as NSManagedObject in releases {
|
||||
version.setValue(appBundleID, forKey: #keyPath(AppVersion.appBundleID))
|
||||
version.setValue(sourceID, forKey: #keyPath(AppVersion.sourceID))
|
||||
}
|
||||
}
|
||||
|
||||
if let permissions = dInstance.value(forKey: #keyPath(StoreApp._permissions)) as? NSSet {
|
||||
for case let permission as NSManagedObject in permissions {
|
||||
permission.setValue(appBundleID, forKey: #keyPath(AppPermission.appBundleID))
|
||||
permission.setValue(sourceID, forKey: #keyPath(AppPermission.sourceID))
|
||||
}
|
||||
}
|
||||
|
||||
if let screenshots = dInstance.value(forKey: #keyPath(StoreApp._screenshots)) as? NSOrderedSet {
|
||||
for case let screenshot as NSManagedObject in screenshots {
|
||||
screenshot.setValue(appBundleID, forKey: #keyPath(AppScreenshot.appBundleID))
|
||||
screenshot.setValue(sourceID, forKey: #keyPath(AppScreenshot.sourceID))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
//
|
||||
// AppPermission17to17_1MigrationPolicy.swift
|
||||
// AltStore
|
||||
//
|
||||
// Created by Magesh K on 15/03/25.
|
||||
// Copyright © 2025 SideStore. All rights reserved.
|
||||
//
|
||||
|
||||
import CoreData
|
||||
|
||||
@objc(AppPermission17To17_1MigrationPolicy)
|
||||
class AppPermission17To17_1MigrationPolicy: NSEntityMigrationPolicy {
|
||||
|
||||
override func createDestinationInstances(forSource sInstance: NSManagedObject, in mapping: NSEntityMapping, manager: NSMigrationManager) throws {
|
||||
// Let the default implementation create the basic destination AppPermission
|
||||
try super.createDestinationInstances(forSource: sInstance, in: mapping, manager: manager)
|
||||
|
||||
// Get the destination AppPermission instance that was created
|
||||
guard let destinationPermission = manager.destinationInstances(forEntityMappingName: mapping.name, sourceInstances: [sInstance]).first else {
|
||||
print("Failed to locate destination AppPermission instance")
|
||||
return
|
||||
}
|
||||
|
||||
// Extract the type value from source
|
||||
if let type = sInstance.value(forKey: #keyPath(AppPermission.type)) as? String {
|
||||
// this is for backwards compatibility <0.5.10
|
||||
// if older type was a valid permission, then consider it as "privacy" in the newer "type".
|
||||
if let permission = self.derivePermissionFromType(type) {
|
||||
destinationPermission.setValue(permission, forKey: #keyPath(AppPermission._permission))
|
||||
destinationPermission.setValue("privacy", forKey: #keyPath(AppPermission.type))
|
||||
}
|
||||
}
|
||||
|
||||
// set initial values copied from source as-is
|
||||
// (will be updated by StoreApp and Source migration policy in its createRelationship() method)
|
||||
if let storeApp = sInstance.value(forKey: #keyPath(AppPermission.app)) as? NSManagedObject{
|
||||
if let appBundle = storeApp.value(forKey: #keyPath(StoreApp.bundleIdentifier)) as? String{
|
||||
destinationPermission.setValue(appBundle, forKey: #keyPath(AppPermission.appBundleID))
|
||||
}
|
||||
|
||||
if let sourceID = storeApp.value(forKey: #keyPath(StoreApp.sourceIdentifier)) as? String {
|
||||
destinationPermission.setValue(sourceID, forKey: #keyPath(AppPermission.sourceID))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
override func createRelationships(
|
||||
forDestination dInstance: NSManagedObject,
|
||||
in mapping: NSEntityMapping,
|
||||
manager: NSMigrationManager
|
||||
) throws {
|
||||
|
||||
try super.createRelationships(forDestination: dInstance, in: mapping, manager: manager)
|
||||
|
||||
// Retrieve the source storeApp from the source appPermission
|
||||
guard let storeApp = dInstance.value(forKey: #keyPath(AppPermission.app)) as? NSManagedObject else {
|
||||
print("Destination \(AppPermission.description()) has no storeApp")
|
||||
return
|
||||
}
|
||||
|
||||
// set initial values copied from source as-is to satisfy unique constraints
|
||||
// (will be updated by StoreApp and Source migration policy in its createRelationship() method)
|
||||
if let appBundle = storeApp.value(forKey: #keyPath(StoreApp.bundleIdentifier)) as? String{
|
||||
dInstance.setValue(appBundle, forKey: #keyPath(AppPermission.appBundleID))
|
||||
}
|
||||
|
||||
if let sourceID = storeApp.value(forKey: #keyPath(StoreApp.sourceIdentifier)) as? String {
|
||||
dInstance.setValue(sourceID, forKey: #keyPath(AppPermission.sourceID))
|
||||
}
|
||||
}
|
||||
|
||||
// Helper method to derive permission string from type
|
||||
private func derivePermissionFromType(_ type: String) -> String? {
|
||||
|
||||
// Based on the code in the documents, we need to map the ALTAppPermissionType to permission strings
|
||||
switch type {
|
||||
case "photos": return "NSPhotosUsageDescription"
|
||||
case "camera": return "NSCameraUsageDescription"
|
||||
case "location": return "NSLocationUsageDescription"
|
||||
case "contacts": return "NSContactsUsageDescription"
|
||||
case "reminders": return "NSRemindersUsageDescription"
|
||||
case "music": return "NSAppleMusicUsageDescription"
|
||||
case "microphone": return "NSMicrophoneUsageDescription"
|
||||
case "speech-recognition": return "NSSpeechRecognitionUsageDescription"
|
||||
case "background-audio": return "NSBackgroundAudioUsageDescription"
|
||||
case "background-fetch": return "NSBackgroundFetchUsageDescription"
|
||||
case "bluetooth": return "NSBluetoothUsageDescription"
|
||||
case "network": return "NSNetworkUsageDescription"
|
||||
case "calendars": return "NSCalendarsUsageDescription"
|
||||
case "touchID": return "NSTouchIDUsageDescription"
|
||||
case "faceID": return "NSFaceIDUsageDescription"
|
||||
case "siri": return "NSSiriUsageDescription"
|
||||
case "motion": return "NSMotionUsageDescription"
|
||||
|
||||
default: return nil // Default fallback
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
//
|
||||
// ReleaseTrack17To17_1MigrationPolicy.swift
|
||||
// AltStore
|
||||
//
|
||||
// Created by Magesh K on 15/03/25.
|
||||
// Copyright © 2025 SideStore. All rights reserved.
|
||||
//
|
||||
|
||||
import CoreData
|
||||
|
||||
@objc(ReleaseTrack17To17_1MigrationPolicy)
|
||||
class ReleaseTrack17To17_1MigrationPolicy: NSEntityMigrationPolicy {
|
||||
|
||||
override func createDestinationInstances(forSource sInstance: NSManagedObject, in mapping: NSEntityMapping, manager: NSMigrationManager) throws {
|
||||
try super.createDestinationInstances(forSource: sInstance, in: mapping, manager: manager)
|
||||
}
|
||||
|
||||
|
||||
override func createRelationships(
|
||||
forDestination dInstance: NSManagedObject,
|
||||
in mapping: NSEntityMapping,
|
||||
manager: NSMigrationManager
|
||||
) throws {
|
||||
|
||||
try super.createRelationships(forDestination: dInstance, in: mapping, manager: manager)
|
||||
|
||||
// Retrieve the source storeApp from the source ReleaseTrack
|
||||
guard let storeApp = dInstance.value(forKey: #keyPath(ReleaseTrack.storeApp)) as? NSManagedObject else {
|
||||
print("Destination \(ReleaseTrack.description()) has no storeApp")
|
||||
return
|
||||
}
|
||||
|
||||
// set initial values copied from source as-is to satisfy unique constraints
|
||||
// (will be updated by StoreApp and Source migration policy in its createRelationship() method)
|
||||
let appBundle = storeApp.value(forKey: #keyPath(StoreApp.bundleIdentifier)) as? String
|
||||
let sourceID = storeApp.value(forKey: #keyPath(StoreApp.sourceIdentifier)) as? String
|
||||
|
||||
if let appBundle {
|
||||
dInstance.setValue(appBundle, forKey: #keyPath(ReleaseTrack._appBundleID))
|
||||
}
|
||||
|
||||
if let sourceID {
|
||||
dInstance.setValue(sourceID, forKey: #keyPath(ReleaseTrack._sourceID))
|
||||
}
|
||||
|
||||
if let releases = dInstance.value(forKey: #keyPath(ReleaseTrack._releases)) as? NSOrderedSet {
|
||||
for case let version as NSManagedObject in releases {
|
||||
if let appBundle {
|
||||
version.setValue(appBundle, forKey: #keyPath(AppVersion.appBundleID))
|
||||
}
|
||||
if let sourceID {
|
||||
version.setValue(sourceID, forKey: #keyPath(AppVersion.sourceID))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,191 @@
|
||||
//
|
||||
// Source17To17_1MigrationPolicy.swift
|
||||
// AltStore
|
||||
//
|
||||
// Created by Magesh K on 15/03/25.
|
||||
// Copyright © 2025 SideStore. All rights reserved.
|
||||
//
|
||||
|
||||
import CoreData
|
||||
|
||||
fileprivate extension NSManagedObject
|
||||
{
|
||||
var sourceSourceURL: URL? {
|
||||
let sourceURL = self.value(forKey: #keyPath(Source.sourceURL)) as? URL
|
||||
return sourceURL
|
||||
}
|
||||
|
||||
var sourceSourceId: String? {
|
||||
let sourceId = self.value(forKey: #keyPath(Source.identifier)) as? String
|
||||
return sourceId
|
||||
}
|
||||
|
||||
var sourceApps: NSOrderedSet? {
|
||||
let apps = self.value(forKey: #keyPath(Source._apps)) as? NSOrderedSet
|
||||
return apps
|
||||
}
|
||||
|
||||
var sourceNewsItems: NSOrderedSet? {
|
||||
let newsItems = self.value(forKey: #keyPath(Source._newsItems)) as? NSOrderedSet
|
||||
return newsItems
|
||||
}
|
||||
}
|
||||
|
||||
fileprivate extension NSManagedObject
|
||||
{
|
||||
func setSourceId(_ sourceID: String)
|
||||
{
|
||||
self.setValue(sourceID, forKey: #keyPath(Source.identifier))
|
||||
}
|
||||
|
||||
func setGroupId(_ groupID: String)
|
||||
{
|
||||
self.setValue(groupID, forKey: #keyPath(Source.groupID))
|
||||
}
|
||||
|
||||
func setSourceSourceUrl(_ sourceURL: URL)
|
||||
{
|
||||
self.setValue(sourceURL, forKey: #keyPath(Source.sourceURL))
|
||||
}
|
||||
|
||||
func setSourceSourceID(_ sourceID: String)
|
||||
{
|
||||
self.setValue(sourceID, forKey: #keyPath(Source.identifier))
|
||||
}
|
||||
|
||||
func setStoreAppSourceID(_ sourceID: String)
|
||||
{
|
||||
self.setValue(sourceID, forKey: #keyPath(StoreApp.sourceIdentifier))
|
||||
}
|
||||
|
||||
func setNewsItemSourceID(_ sourceID: String)
|
||||
{
|
||||
self.setValue(sourceID, forKey: #keyPath(NewsItem.sourceIdentifier))
|
||||
}
|
||||
|
||||
func setAppVersionSourceID(_ sourceID: String)
|
||||
{
|
||||
self.setValue(sourceID, forKey: #keyPath(AppVersion.sourceID))
|
||||
}
|
||||
|
||||
func setAppPermissionSourceID(_ sourceID: String)
|
||||
{
|
||||
self.setValue(sourceID, forKey: #keyPath(AppPermission.sourceID))
|
||||
}
|
||||
|
||||
func setAppScreenshotSourceID(_ sourceID: String)
|
||||
{
|
||||
self.setValue(sourceID, forKey: #keyPath(AppScreenshot.sourceID))
|
||||
}
|
||||
|
||||
func setReleaseTracksSourceID(_ sourceID: String)
|
||||
{
|
||||
self.setValue(sourceID, forKey: #keyPath(ReleaseTrack._sourceID))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fileprivate extension NSManagedObject
|
||||
{
|
||||
var storeAppVersions: NSOrderedSet? {
|
||||
let versions = self.value(forKey: #keyPath(StoreApp._versions)) as? NSOrderedSet
|
||||
return versions
|
||||
}
|
||||
|
||||
var storeAppPermissions: NSSet? {
|
||||
let permissions = self.value(forKey: #keyPath(StoreApp._permissions)) as? NSSet
|
||||
return permissions
|
||||
}
|
||||
|
||||
var storeAppScreenshots: NSOrderedSet? {
|
||||
let screenshots = self.value(forKey: #keyPath(StoreApp._screenshots)) as? NSOrderedSet
|
||||
return screenshots
|
||||
}
|
||||
|
||||
var storeAppReleaseTracks: NSOrderedSet? {
|
||||
let tracks = self.value(forKey: #keyPath(StoreApp._releaseTracks)) as? NSOrderedSet
|
||||
return tracks
|
||||
}
|
||||
}
|
||||
|
||||
@objc(Source17To17_1MigrationPolicy)
|
||||
class Source17To17_1MigrationPolicy: NSEntityMigrationPolicy
|
||||
{
|
||||
override func createDestinationInstances(forSource sInstance: NSManagedObject, in mapping: NSEntityMapping, manager: NSMigrationManager) throws {
|
||||
// Let the default implementation create the basic destination AppPermission
|
||||
try super.createDestinationInstances(forSource: sInstance, in: mapping, manager: manager)
|
||||
|
||||
// Get the destination Source instance that was created
|
||||
guard let dInstance = manager.destinationInstances(forEntityMappingName: mapping.name, sourceInstances: [sInstance]).first else {
|
||||
print("Failed to locate destination Source instance")
|
||||
return
|
||||
}
|
||||
|
||||
// update new fields with initial values
|
||||
if let sourceID = sInstance.value(forKey: #keyPath(Source.identifier)) as? String {
|
||||
dInstance.setValue(sourceID, forKey: #keyPath(Source.groupID))
|
||||
}
|
||||
|
||||
guard var sourceURL = dInstance.sourceSourceURL else {
|
||||
return
|
||||
}
|
||||
|
||||
// sidestore official source has been moved to sidestore.io/apps-v2.json
|
||||
// if we don't switch, users will end up with 2 offical sources
|
||||
let normalizedSourceURL = try? sourceURL.normalized()
|
||||
if normalizedSourceURL == "apps.sidestore.io" // if using old source url (<0.5.9)
|
||||
{
|
||||
sourceURL = Source.altStoreSourceURL // switch to latest
|
||||
dInstance.setSourceSourceUrl(sourceURL) // and use it for current
|
||||
}
|
||||
|
||||
var sourceID = try Source.sourceID(from: sourceURL)
|
||||
dInstance.setSourceId(sourceID)
|
||||
|
||||
// for older versions migrating to current (their sourceID is their groupID)
|
||||
dInstance.setGroupId(sourceID)
|
||||
|
||||
if sourceID == "apps.sidestore.io" {
|
||||
sourceID = Source.altStoreIdentifier
|
||||
dInstance.setSourceId(sourceID)
|
||||
}
|
||||
}
|
||||
|
||||
override func createRelationships(forDestination dInstance: NSManagedObject, in mapping: NSEntityMapping, manager: NSMigrationManager) throws
|
||||
{
|
||||
try super.createRelationships(forDestination: dInstance, in: mapping, manager: manager)
|
||||
|
||||
guard let sourceID = dInstance.sourceSourceId else { return }
|
||||
|
||||
for case let newsItem as NSManagedObject in dInstance.sourceNewsItems ?? []
|
||||
{
|
||||
newsItem.setNewsItemSourceID(sourceID)
|
||||
}
|
||||
|
||||
for case let app as NSManagedObject in dInstance.sourceApps ?? []
|
||||
{
|
||||
app.setStoreAppSourceID(sourceID)
|
||||
|
||||
for case let screenshot as NSManagedObject in app.storeAppScreenshots ?? []
|
||||
{
|
||||
screenshot.setAppScreenshotSourceID(sourceID)
|
||||
}
|
||||
|
||||
for case let track as NSManagedObject in app.storeAppReleaseTracks ?? []
|
||||
{
|
||||
// print("Source_17_1MigrationPolicy: processing track \(track.value(forKey: "track")!)")
|
||||
track.setValue(sourceID, forKey: #keyPath(ReleaseTrack._sourceID))
|
||||
|
||||
guard let releases = track.value(forKey: #keyPath(ReleaseTrack._releases)) as? NSOrderedSet else {
|
||||
// print("Source_17_1MigrationPolicy: releases not found for track: \(track.value(forKey: "track")!)")
|
||||
continue
|
||||
}
|
||||
|
||||
for case let version as NSManagedObject in releases {
|
||||
// print("Source_17_1MigrationPolicy: updating sourceID for version: \(version.value(forKey: "version")!)")
|
||||
version.setValue(sourceID, forKey: #keyPath(AppVersion.sourceID))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
//
|
||||
// StoreApp17To17_1MigrationPolicy.swift
|
||||
// AltStore
|
||||
//
|
||||
// Created by Magesh K on 15/03/25.
|
||||
// Copyright © 2025 SideStore. All rights reserved.
|
||||
//
|
||||
|
||||
import CoreData
|
||||
|
||||
fileprivate extension NSManagedObject
|
||||
{
|
||||
var storeAppReleaseTracks: NSOrderedSet? {
|
||||
let tracks = self.value(forKey: #keyPath(StoreApp._releaseTracks)) as? NSOrderedSet
|
||||
return tracks
|
||||
}
|
||||
}
|
||||
|
||||
@objc(StoreApp17To17_1MigrationPolicy)
|
||||
class StoreApp17To17_1MigrationPolicy: NSEntityMigrationPolicy
|
||||
{
|
||||
override func createDestinationInstances(forSource sInstance: NSManagedObject, in mapping: NSEntityMapping, manager: NSMigrationManager) throws {
|
||||
try super.createDestinationInstances(forSource: sInstance, in: mapping, manager: manager)
|
||||
}
|
||||
|
||||
override func createRelationships(forDestination dInstance: NSManagedObject, in mapping: NSEntityMapping, manager: NSMigrationManager) throws
|
||||
{
|
||||
try super.createRelationships(forDestination: dInstance, in: mapping, manager: manager)
|
||||
|
||||
let appBundleID = dInstance.value(forKey: #keyPath(StoreApp.bundleIdentifier))
|
||||
|
||||
for case let track as NSManagedObject in dInstance.storeAppReleaseTracks ?? []
|
||||
{
|
||||
track.setValue(appBundleID, forKey: #keyPath(ReleaseTrack._appBundleID))
|
||||
|
||||
guard let releases = track.value(forKey: #keyPath(ReleaseTrack._releases)) as? NSOrderedSet else {
|
||||
continue
|
||||
}
|
||||
|
||||
for case let version as NSManagedObject in releases {
|
||||
version.setValue(appBundleID, forKey: #keyPath(AppVersion.appBundleID))
|
||||
}
|
||||
}
|
||||
|
||||
if let permissions = dInstance.value(forKey: #keyPath(StoreApp._permissions)) as? NSSet {
|
||||
for case let permission as NSManagedObject in permissions {
|
||||
permission.setValue(appBundleID, forKey: #keyPath(AppPermission.appBundleID))
|
||||
}
|
||||
}
|
||||
|
||||
if let screenshots = dInstance.value(forKey: #keyPath(StoreApp._screenshots)) as? NSOrderedSet {
|
||||
for case let screenshot as NSManagedObject in screenshots {
|
||||
screenshot.setValue(appBundleID, forKey: #keyPath(AppScreenshot.appBundleID))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -75,6 +75,9 @@ public class NewsItem: BaseEntity, Decodable
|
||||
self.imageURL = try container.decodeIfPresent(URL.self, forKey: .imageURL)
|
||||
self.externalURL = try container.decodeIfPresent(URL.self, forKey: .externalURL)
|
||||
|
||||
// TODO: app specific news should be moved to appEntity (via refactoring)
|
||||
// This can be done by: 1. having two newsItem schema, one for source and one for StoreApp
|
||||
// 2. move this appID field into the newItem schema which is under StoreApp.
|
||||
self.appID = try container.decodeIfPresent(String.self, forKey: .appID)
|
||||
|
||||
let notify = try container.decodeIfPresent(Bool.self, forKey: .notify) ?? false
|
||||
|
||||
@@ -14,7 +14,9 @@ public class ReleaseTrack: BaseEntity, Decodable
|
||||
{
|
||||
// attributes
|
||||
@NSManaged @objc(track) public private(set) var _track: String?
|
||||
|
||||
@NSManaged @objc(appBundleID) public private(set) var _appBundleID: String?
|
||||
@NSManaged @objc(sourceID) public private(set) var _sourceID: String?
|
||||
|
||||
// RelationShips
|
||||
@NSManaged @objc(releases) public private(set) var _releases: NSOrderedSet?
|
||||
@NSManaged public private(set) var storeApp: StoreApp?
|
||||
@@ -89,7 +91,7 @@ public extension ReleaseTrack{
|
||||
}
|
||||
|
||||
// update it into the appVersion
|
||||
_ = version.mutateForData(channel: track, appBundleID: storeApp.bundleIdentifier)
|
||||
_ = version.mutateForData(channel: track, appBundleID: storeApp.bundleIdentifier, sourceID: storeApp.sourceIdentifier)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -109,6 +111,10 @@ public extension ReleaseTrack{
|
||||
if key == NSExpression(forKeyPath: #keyPath(ReleaseTrack.storeApp)).keyPath
|
||||
{
|
||||
updateVersions(for: storeApp)
|
||||
|
||||
// update unique constraint attribs
|
||||
self._appBundleID = storeApp?.bundleIdentifier
|
||||
self._sourceID = storeApp?.sourceIdentifier
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,11 @@ import UIKit
|
||||
|
||||
public extension Source
|
||||
{
|
||||
static let altStoreIdentifier = try! Source.sourceID(from: Source.altStoreSourceURL)
|
||||
#if ALPHA
|
||||
static let altStoreGroupIdentifier = Bundle.Info.appbundleIdentifier
|
||||
#else
|
||||
static let altStoreGroupIdentifier = Bundle.Info.appbundleIdentifier
|
||||
#endif
|
||||
|
||||
#if STAGING
|
||||
|
||||
@@ -24,13 +28,15 @@ public extension Source
|
||||
#else
|
||||
|
||||
#if ALPHA
|
||||
static let altStoreSourceURL = URL(string: "https://apps.sidestore.io/")!
|
||||
static let altStoreSourceURL = URL(string: "https://sidestore.io/apps-v2.json/")!
|
||||
#else
|
||||
// static let altStoreSourceURL = URL(string: "https://apps.sidestore.io/")!
|
||||
static let altStoreSourceURL = URL(string: "https://sidestore.io/apps-v2.json/")! // using v2 for alpha releases
|
||||
static let altStoreSourceURL = URL(string: "https://sidestore.io/apps-v2.json/")!
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
// normalized url is the source identifier (or) p-key!
|
||||
static let altStoreIdentifier = try! Source.sourceID(from: altStoreSourceURL)
|
||||
}
|
||||
|
||||
// public struct AppPermissionFeed: Codable {
|
||||
@@ -205,7 +211,8 @@ public class Source: BaseEntity, Decodable
|
||||
/* Properties */
|
||||
@NSManaged public var version: Int
|
||||
@NSManaged public var name: String
|
||||
@NSManaged public private(set) var identifier: String
|
||||
@NSManaged public private(set) var identifier: String // NOTE: sourceID is just normalized sourceURL
|
||||
@NSManaged public private(set) var groupID: String?
|
||||
@NSManaged public var sourceURL: URL
|
||||
|
||||
/* Source Detail */
|
||||
@@ -280,6 +287,9 @@ public class Source: BaseEntity, Decodable
|
||||
case news
|
||||
case featuredApps
|
||||
case userInfo
|
||||
|
||||
// case identifier
|
||||
case groupID = "identifier"
|
||||
}
|
||||
|
||||
private override init(entity: NSEntityDescription, insertInto context: NSManagedObjectContext?)
|
||||
@@ -359,6 +369,24 @@ public class Source: BaseEntity, Decodable
|
||||
|
||||
// Updates identifier + apps & newsItems
|
||||
try self.setSourceURL(sourceURL)
|
||||
|
||||
|
||||
// NOTE: Source ID is just normalized sourceURL. coz normalized url is the primary key which needs to be unique
|
||||
// Hence if a source's URL changed, then it means it is a different source now.
|
||||
// This also means that the identifier field in the source is irrelevant (if any)
|
||||
|
||||
// if we want grouping of sources from same author or something like that then we should have used groupID (a new field)
|
||||
// shouldn't use the existing "identifier" field, hence the following is commented out
|
||||
|
||||
// // if an explicit identifier is present, then use it
|
||||
// if let identifier = try container.decodeIfPresent(String.self, forKey: .identifier)
|
||||
// {
|
||||
// self.identifier = identifier
|
||||
// }
|
||||
|
||||
// if an explicit (group)identifier is present, then use it as groupID else use sourceID as groupID too
|
||||
self.groupID = try container.decodeIfPresent(String.self, forKey: .groupID) ?? self.identifier
|
||||
|
||||
}
|
||||
catch
|
||||
{
|
||||
@@ -405,7 +433,7 @@ public extension Source
|
||||
|
||||
// TODO: Support alternate URLs
|
||||
let isRecommended = recommendedSources.contains { source in
|
||||
return source.identifier == self.identifier || source.sourceURL?.absoluteString.lowercased() == self.sourceURL.absoluteString
|
||||
return source.identifier == self.identifier || source.sourceURL?.absoluteString.lowercased() == self.sourceURL.absoluteString.lowercased()
|
||||
}
|
||||
return isRecommended
|
||||
}
|
||||
@@ -418,14 +446,17 @@ public extension Source
|
||||
}
|
||||
}
|
||||
|
||||
internal extension Source
|
||||
public extension Source
|
||||
{
|
||||
class func sourceID(from sourceURL: URL) throws -> String
|
||||
{
|
||||
let sourceID = try sourceURL.normalized()
|
||||
return sourceID
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
internal extension Source
|
||||
{
|
||||
func setFeaturedApps(_ featuredApps: [StoreApp]?)
|
||||
{
|
||||
// Explicitly update relationships for all apps to ensure featuredApps merges correctly.
|
||||
@@ -451,17 +482,23 @@ public extension Source
|
||||
{
|
||||
func setSourceURL(_ sourceURL: URL) throws
|
||||
{
|
||||
let identifier = try Source.sourceID(from: sourceURL)
|
||||
|
||||
self.identifier = identifier
|
||||
self.sourceURL = sourceURL
|
||||
|
||||
// update the normalized sourceURL as the identifier
|
||||
let identifier = try Source.sourceID(from: sourceURL)
|
||||
try self.setSourceID(identifier)
|
||||
}
|
||||
|
||||
func setSourceID(_ identifier: String) throws
|
||||
{
|
||||
self.identifier = identifier
|
||||
|
||||
for app in self.apps
|
||||
{
|
||||
app.sourceIdentifier = identifier
|
||||
}
|
||||
|
||||
for newsItem in self.newsItems
|
||||
for newsItem in self.newsItems
|
||||
{
|
||||
newsItem.sourceIdentifier = identifier
|
||||
}
|
||||
@@ -479,6 +516,7 @@ public extension Source
|
||||
{
|
||||
let source = Source(context: context)
|
||||
source.name = "SideStore Offical"
|
||||
source.groupID = Source.altStoreGroupIdentifier
|
||||
source.identifier = Source.altStoreIdentifier
|
||||
try! source.setSourceURL(Source.altStoreSourceURL)
|
||||
|
||||
@@ -491,13 +529,14 @@ public extension Source
|
||||
return source
|
||||
}
|
||||
|
||||
class func make(name: String, identifier: String, sourceURL: URL, context: NSManagedObjectContext) -> Source
|
||||
class func make(name: String, groupID: String, sourceURL: URL, context: NSManagedObjectContext) -> Source
|
||||
{
|
||||
let source = Source(context: context)
|
||||
source.name = name
|
||||
source.identifier = identifier
|
||||
source.sourceURL = sourceURL
|
||||
|
||||
source.sourceURL = sourceURL
|
||||
source.identifier = try! Source.sourceID(from: sourceURL)
|
||||
|
||||
return source
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
// Configuration settings file format documentation can be found at:
|
||||
// https://help.apple.com/xcode/#/dev745c5c974
|
||||
|
||||
MARKETING_VERSION = 0.6.0
|
||||
CURRENT_PROJECT_VERSION = 6000
|
||||
MARKETING_VERSION = 0.6.1
|
||||
CURRENT_PROJECT_VERSION = 0601
|
||||
|
||||
// Vars to be overwritten by `CodeSigning.xcconfig` if exists
|
||||
DEVELOPMENT_TEAM = S32Z3HMYVQ
|
||||
|
||||
@@ -28,7 +28,7 @@ Why iOS 15? Targeting such a recent version of iOS allows us to accelerate devel
|
||||
SideStore is a just regular, sandboxed iOS application. The AltStore app target contains the vast majority of SideStore's functionality, including all the logic for downloading and updating apps through SideStore. SideStore makes heavy use of standard iOS frameworks and technologies most iOS developers are familiar with.
|
||||
|
||||
### EM Proxy
|
||||
[SideServer mobile](https://github.com/jkcoxson/em_proxy) powers the defining feature of SideStore: untethered app installation. By levaraging an App Store app with additional entitlements (WireGuard) to create the VPN tunnel for us, it allows SideStore to take advantage of [Jitterbug](https://github.com/osy/Jitterbug)'s loopback method without requiring a paid developer account.
|
||||
[SideServer mobile](https://github.com/jkcoxson/em_proxy) powers the defining feature of SideStore: untethered app installation. By leveraging an App Store app with additional entitlements (WireGuard or StosVPN) to create the VPN tunnel for us, it allows SideStore to take advantage of [Jitterbug](https://github.com/osy/Jitterbug)'s loopback method without requiring a paid developer account.
|
||||
|
||||
### Minimuxer
|
||||
[Minimuxer](https://github.com/jkcoxson/minimuxer) is a lockdown muxer that can run inside iOS’s sandbox. It replicates Apple’s usbmuxd protocol on MacOS to “discover” devices to interface with wireguard On-Device.
|
||||
|
||||
54
SideStore/Utils/common/BuildInfo.swift
Normal file
54
SideStore/Utils/common/BuildInfo.swift
Normal file
@@ -0,0 +1,54 @@
|
||||
//
|
||||
// BuildInfo.swift
|
||||
// AltStore
|
||||
//
|
||||
// Created by Magesh K on 23/03/25.
|
||||
// Copyright © 2025 SideStore. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
public class BuildInfo{
|
||||
private static let MARKETING_VERSION_TAG = "CFBundleShortVersionString"
|
||||
private static let CURRENT_PROJECT_VERSION_TAG = kCFBundleVersionKey as String
|
||||
|
||||
private static let XCODE_VERSION_TAG = "DTXcode"
|
||||
private static let XCODE_REVISION_TAG = "DTXcodeBuild"
|
||||
|
||||
let bundle: Bundle
|
||||
|
||||
public init(){
|
||||
bundle = Bundle.main
|
||||
}
|
||||
|
||||
enum BundleError: Swift.Error {
|
||||
case invalidURL
|
||||
}
|
||||
|
||||
public init(url: URL) throws {
|
||||
guard let bundle = Bundle(url: url) else {
|
||||
throw BundleError.invalidURL
|
||||
}
|
||||
self.bundle = bundle
|
||||
}
|
||||
|
||||
public lazy var project_version: String? = {
|
||||
let version = bundle.object(forInfoDictionaryKey: Self.CURRENT_PROJECT_VERSION_TAG) as? String
|
||||
return version
|
||||
}()
|
||||
|
||||
public lazy var marketing_version: String? = {
|
||||
let version = bundle.object(forInfoDictionaryKey: Self.MARKETING_VERSION_TAG) as? String
|
||||
return version
|
||||
}()
|
||||
|
||||
public lazy var xcode: String? = {
|
||||
let xcode = bundle.object(forInfoDictionaryKey: Self.XCODE_VERSION_TAG) as? String
|
||||
return xcode
|
||||
}()
|
||||
|
||||
public lazy var xcode_revision: String? = {
|
||||
let revision = bundle.object(forInfoDictionaryKey: Self.XCODE_REVISION_TAG) as? String
|
||||
return revision
|
||||
}()
|
||||
}
|
||||
Reference in New Issue
Block a user