Adds AppVersion Core Data entity

Preserves redundant fields on StoreApp in database model for backwards compatibility.
This commit is contained in:
Riley Testut
2022-09-12 15:42:33 -07:00
committed by Joseph Mattello
parent f472b227bb
commit 5765cb8330
4 changed files with 125 additions and 0 deletions

View File

@@ -320,6 +320,7 @@
BFF0B69A2322D7D0007A79E1 /* UIScreen+CompactHeight.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFF0B6992322D7D0007A79E1 /* UIScreen+CompactHeight.swift */; };
BFF435D8255CBDAB00DD724F /* ALTApplication+AltStoreApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFF435D7255CBDAB00DD724F /* ALTApplication+AltStoreApp.swift */; };
BFF615A82510042B00484D3B /* AltStoreCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BF66EE7E2501AE50007EE018 /* AltStoreCore.framework */; };
D52C08EE28AEC37A006C4AE5 /* AppVersion.swift in Sources */ = {isa = PBXBuildFile; fileRef = D52C08ED28AEC37A006C4AE5 /* AppVersion.swift */; };
D533E8B72727841800A9B5DD /* libAppleArchive.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = D533E8B62727841800A9B5DD /* libAppleArchive.tbd */; settings = {ATTRIBUTES = (Weak, ); }; };
D533E8BE2727BBF800A9B5DD /* libcurl.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D533E8BD2727BBF800A9B5DD /* libcurl.a */; };
D54DED1428CBC44B008B27A0 /* ErrorLogTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D54DED1328CBC44B008B27A0 /* ErrorLogTableViewCell.swift */; };
@@ -818,6 +819,7 @@
BFF7EC4C25081E9300BDE521 /* AltStore 8.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = "AltStore 8.xcdatamodel"; sourceTree = "<group>"; };
BFFCFA45248835530077BFCE /* AltDaemon.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = AltDaemon.entitlements; sourceTree = "<group>"; };
D504F42528AD72C50014BB5D /* ProgressRing.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProgressRing.swift; sourceTree = "<group>"; };
D52C08ED28AEC37A006C4AE5 /* AppVersion.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppVersion.swift; sourceTree = "<group>"; };
D533E8B62727841800A9B5DD /* libAppleArchive.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libAppleArchive.tbd; path = usr/lib/libAppleArchive.tbd; sourceTree = SDKROOT; };
D533E8B82727B61400A9B5DD /* fragmentzip.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = fragmentzip.h; sourceTree = "<group>"; };
D533E8BB2727BBEE00A9B5DD /* libfragmentzip.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libfragmentzip.a; path = Dependencies/fragmentzip/libfragmentzip.a; sourceTree = SOURCE_ROOT; };
@@ -1299,6 +1301,7 @@
BF66EEC92501AECA007EE018 /* Account.swift */,
BF66EEC72501AECA007EE018 /* AppID.swift */,
BF66EEC62501AECA007EE018 /* AppPermission.swift */,
D52C08ED28AEC37A006C4AE5 /* AppVersion.swift */,
BF66EECA2501AECA007EE018 /* DatabaseManager.swift */,
BF66EEC02501AECA007EE018 /* InstalledApp.swift */,
BF66EECB2501AECA007EE018 /* InstalledExtension.swift */,
@@ -2370,6 +2373,7 @@
BFAECC592501B0A400528F27 /* Result+Conveniences.swift in Sources */,
BFAECC542501B0A400528F27 /* NSError+ALTServerError.m in Sources */,
BF66EEE12501AECA007EE018 /* DatabaseManager.swift in Sources */,
D52C08EE28AEC37A006C4AE5 /* AppVersion.swift in Sources */,
BF66EEEA2501AED0007EE018 /* UIColor+Hex.swift in Sources */,
BF66EECC2501AECA007EE018 /* Source.swift in Sources */,
BF66EED72501AECA007EE018 /* InstalledApp.swift in Sources */,

View File

@@ -31,6 +31,26 @@
<attribute name="usageDescription" attributeType="String"/>
<relationship name="app" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="StoreApp" inverseName="permissions" inverseEntity="StoreApp"/>
</entity>
<entity name="AppVersion" representedClassName="AppVersion" syncable="YES">
<attribute name="appBundleID" 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="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"/>
<uniquenessConstraints>
<uniquenessConstraint>
<constraint value="appBundleID"/>
<constraint value="version"/>
<constraint value="sourceID"/>
</uniquenessConstraint>
</uniquenessConstraints>
</entity>
<entity name="InstalledApp" representedClassName="InstalledApp" syncable="YES">
<attribute name="bundleIdentifier" attributeType="String"/>
<attribute name="certificateSerialNumber" optional="YES" attributeType="String"/>
@@ -158,10 +178,12 @@
<attribute name="versionDate" attributeType="Date" usesScalarValueType="NO"/>
<attribute name="versionDescription" optional="YES" attributeType="String"/>
<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" ordered="YES" destinationEntity="AppPermission" inverseName="app" inverseEntity="AppPermission"/>
<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"/>

View File

@@ -0,0 +1,92 @@
//
// AppVersion.swift
// AltStoreCore
//
// Created by Riley Testut on 8/18/22.
// Copyright © 2022 Riley Testut. All rights reserved.
//
import CoreData
@objc(AppVersion)
public class AppVersion: NSManagedObject, Decodable, Fetchable
{
/* Properties */
@NSManaged public var version: String
@NSManaged public var date: Date
@NSManaged public var localizedDescription: String?
@NSManaged public var downloadURL: URL
@NSManaged public var size: Int64
@nonobjc public var minOSVersion: OperatingSystemVersion? {
guard let osVersionString = self._minOSVersion else { return nil }
let osVersion = OperatingSystemVersion(string: osVersionString)
return osVersion
}
@NSManaged @objc(minOSVersion) private var _minOSVersion: String?
@nonobjc public var maxOSVersion: OperatingSystemVersion? {
guard let osVersionString = self._maxOSVersion else { return nil }
let osVersion = OperatingSystemVersion(string: osVersionString)
return osVersion
}
@NSManaged @objc(maxOSVersion) private var _maxOSVersion: String?
@NSManaged public var appBundleID: String
@NSManaged public var sourceID: String?
/* Relationships */
@NSManaged public private(set) var app: StoreApp?
@NSManaged public private(set) var latestVersionApp: StoreApp?
private override init(entity: NSEntityDescription, insertInto context: NSManagedObjectContext?)
{
super.init(entity: entity, insertInto: context)
}
private enum CodingKeys: String, CodingKey
{
case version
case date
case localizedDescription
case downloadURL
case size
case _minOSVersion
case _maxOSVersion
case appBundleID
case sourceID
}
public required init(from decoder: Decoder) throws
{
guard let context = decoder.managedObjectContext else { preconditionFailure("Decoder must have non-nil NSManagedObjectContext.") }
super.init(entity: NewsItem.entity(), insertInto: context)
let container = try decoder.container(keyedBy: CodingKeys.self)
self.version = try container.decode(String.self, forKey: .version)
self.date = try container.decode(Date.self, forKey: .date)
self.localizedDescription = try container.decodeIfPresent(String.self, forKey: .localizedDescription)
self.downloadURL = try container.decode(URL.self, forKey: .downloadURL)
self.size = try container.decode(Int64.self, forKey: .size)
self._minOSVersion = try container.decodeIfPresent(String.self, forKey: ._minOSVersion)
self._maxOSVersion = try container.decodeIfPresent(String.self, forKey: ._maxOSVersion)
self.appBundleID = try container.decode(String.self, forKey: .appBundleID)
self.sourceID = try container.decodeIfPresent(String.self, forKey: .sourceID)
}
}
public extension AppVersion
{
@nonobjc class func fetchRequest() -> NSFetchRequest<AppVersion>
{
return NSFetchRequest<AppVersion>(entityName: "AppVersion")
}
}

View File

@@ -129,6 +129,9 @@ public class StoreApp: NSManagedObject, Decodable, Fetchable
@NSManaged @objc(source) public var _source: Source?
@NSManaged @objc(permissions) public var _permissions: NSOrderedSet
@NSManaged public private(set) var latestVersion: AppVersion?
@NSManaged @objc(versions) public private(set) var _versions: NSOrderedSet
@NSManaged public private(set) var loggedErrors: NSSet /* Set<LoggedError> */ // Use NSSet to avoid eagerly fetching values.
@nonobjc public var source: Source? {
@@ -145,6 +148,10 @@ public class StoreApp: NSManagedObject, Decodable, Fetchable
return self._permissions.array as! [AppPermission]
}
@nonobjc public var versions: [AppVersion] {
return self._versions.array as! [AppVersion]
}
private override init(entity: NSEntityDescription, insertInto context: NSManagedObjectContext?)
{
super.init(entity: entity, insertInto: context)