- [Fix]: migrations fix for coredata from v11(0.5.9) to v17_1(0.6.1) and v17(0.6.0 to v17_1(0.6.1)

This commit is contained in:
mahee96
2025-03-23 21:44:06 -07:00
parent a7496e08e3
commit a4dfd28a3c
20 changed files with 1962 additions and 1834 deletions

View File

@@ -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">

View File

@@ -108,7 +108,7 @@ class StoreApp11To17MigrationPolicy: NSEntityMigrationPolicy {
// Create a new ReleaseTrack entity
let context = dInstance.managedObjectContext!
let releaseTrack = NSEntityDescription.insertNewObject(forEntityName: ReleaseTrack.entity().name! ?? ReleaseTrack.description(), 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

View File

@@ -1,5 +1,5 @@
//
// AppPermission11To17_1MigrationPolicy.swift
// AppPermission17to17_1MigrationPolicy.swift
// AltStore
//
// Created by Magesh K on 15/03/25.
@@ -9,13 +9,20 @@
import CoreData
@objc(AppPermission11To17_1MigrationPolicy)
class AppPermission11To17_1MigrationPolicy: AppPermission17To17_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 {
override func createRelationships(
forDestination dInstance: NSManagedObject,
in mapping: NSEntityMapping,
manager: NSMigrationManager
) throws {
try super.createRelationships(forDestination: dInstance, in: mapping, manager: manager)
}
}

View File

@@ -9,13 +9,18 @@
import CoreData
@objc(ReleaseTrack11To17_1MigrationPolicy)
class ReleaseTrack11To17_1MigrationPolicy: ReleaseTrack17To17_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 {
override func createRelationships(
forDestination dInstance: NSManagedObject,
in mapping: NSEntityMapping,
manager: NSMigrationManager
) throws {
try super.createRelationships(forDestination: dInstance, in: mapping, manager: manager)
}
}

View File

@@ -1,5 +1,5 @@
//
// Source17To17_1MigrationPolicy.swift
// Source11To17_1MigrationPolicy.swift
// AltStore
//
// Created by Magesh K on 15/03/25.
@@ -12,10 +12,12 @@ import CoreData
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 {
override func createRelationships(forDestination dInstance: NSManagedObject, in mapping: NSEntityMapping, manager: NSMigrationManager) throws
{
try super.createRelationships(forDestination: dInstance, in: mapping, manager: manager)
}
}

View File

@@ -8,14 +8,55 @@
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 {
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))
}
}
}
}

View File

@@ -1,5 +1,5 @@
//
// AppPermission17To17_1MigrationPolicy.swift
// AppPermission17to17_1MigrationPolicy.swift
// AltStore
//
// Created by Magesh K on 15/03/25.
@@ -23,9 +23,12 @@ class AppPermission17To17_1MigrationPolicy: NSEntityMigrationPolicy {
// Extract the type value from source
if let type = sInstance.value(forKey: #keyPath(AppPermission.type)) as? String {
// In the new model, "permission" is the actual permission string, which needs to be derived from the old "type"
let permission = self.derivePermissionFromType(type)
destinationPermission.setValue(permission, forKey: #keyPath(AppPermission._permission))
// 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
@@ -48,16 +51,12 @@ class AppPermission17To17_1MigrationPolicy: NSEntityMigrationPolicy {
in mapping: NSEntityMapping,
manager: NSMigrationManager
) throws {
// Retrieve the corresponding source instance for the destination StoreApp
let sourceInstances = manager.sourceInstances(forEntityMappingName: mapping.name, destinationInstances: [dInstance])
guard let sInstance = sourceInstances.first else {
print("No source instance found for destination: \(dInstance)")
return
}
try super.createRelationships(forDestination: dInstance, in: mapping, manager: manager)
// Retrieve the source storeApp from the source appPermission
guard let storeApp = sInstance.value(forKey: #keyPath(AppPermission.app)) as? NSManagedObject else {
print("Source \(AppPermission.description()) has no storeApp")
guard let storeApp = dInstance.value(forKey: #keyPath(AppPermission.app)) as? NSManagedObject else {
print("Destination \(AppPermission.description()) has no storeApp")
return
}
@@ -73,7 +72,8 @@ class AppPermission17To17_1MigrationPolicy: NSEntityMigrationPolicy {
}
// Helper method to derive permission string from type
private func derivePermissionFromType(_ type: String) -> String {
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"
@@ -93,9 +93,8 @@ class AppPermission17To17_1MigrationPolicy: NSEntityMigrationPolicy {
case "faceID": return "NSFaceIDUsageDescription"
case "siri": return "NSSiriUsageDescription"
case "motion": return "NSMotionUsageDescription"
case "entitlement": return type // For entitlements, we might keep the raw value
case "privacy": return type // For privacy permissions, we might keep the raw value
default: return type // Default fallback
default: return nil // Default fallback
}
}
}

View File

@@ -12,29 +12,7 @@ import CoreData
class ReleaseTrack17To17_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 ReleaseTrack instance")
return
}
if let track = sInstance.value(forKey: #keyPath(ReleaseTrack._track)) as? String {
destinationPermission.setValue(track, forKey: #keyPath(ReleaseTrack._track))
}
// set initial values migrated from source as-is
if let storeApp = sInstance.value(forKey: #keyPath(ReleaseTrack.storeApp)) as? NSManagedObject{
if let appBundle = storeApp.value(forKey: #keyPath(StoreApp.bundleIdentifier)) as? String{
destinationPermission.setValue(appBundle, forKey: #keyPath(ReleaseTrack._appBundleID))
}
if let sourceID = storeApp.value(forKey: #keyPath(StoreApp.sourceIdentifier)) as? String {
destinationPermission.setValue(sourceID, forKey: #keyPath(ReleaseTrack._sourceID))
}
}
}
@@ -43,16 +21,12 @@ class ReleaseTrack17To17_1MigrationPolicy: NSEntityMigrationPolicy {
in mapping: NSEntityMapping,
manager: NSMigrationManager
) throws {
// Retrieve the corresponding source instance for the destination StoreApp
let sourceInstances = manager.sourceInstances(forEntityMappingName: mapping.name, destinationInstances: [dInstance])
guard let sInstance = sourceInstances.first else {
print("No source instance found for destination: \(dInstance)")
return
}
try super.createRelationships(forDestination: dInstance, in: mapping, manager: manager)
// Retrieve the source storeApp from the source ReleaseTrack
guard let storeApp = sInstance.value(forKey: #keyPath(ReleaseTrack.storeApp)) as? NSManagedObject else {
print("Source \(ReleaseTrack.description()) has no storeApp")
guard let storeApp = dInstance.value(forKey: #keyPath(ReleaseTrack.storeApp)) as? NSManagedObject else {
print("Destination \(ReleaseTrack.description()) has no storeApp")
return
}
@@ -66,5 +40,4 @@ class ReleaseTrack17To17_1MigrationPolicy: NSEntityMigrationPolicy {
dInstance.setValue(sourceID, forKey: #keyPath(ReleaseTrack._sourceID))
}
}
}

View File

@@ -156,29 +156,35 @@ class Source17To17_1MigrationPolicy: NSEntityMigrationPolicy
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 version as NSManagedObject in app.storeAppVersions ?? []
{
version.setAppVersionSourceID(sourceID)
}
for case let permission as NSManagedObject in app.storeAppPermissions ?? []
{
permission.setAppPermissionSourceID(sourceID)
}
for case let screenshot as NSManagedObject in app.storeAppScreenshots ?? []
{
screenshot.setAppScreenshotSourceID(sourceID)
}
for case let tracks as NSManagedObject in app.storeAppReleaseTracks ?? []
for case let track as NSManagedObject in app.storeAppReleaseTracks ?? []
{
tracks.setReleaseTracksSourceID(sourceID)
// 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))
}
}
}
}

View File

@@ -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))
}
}
}
}