89 lines
3.3 KiB
Swift
89 lines
3.3 KiB
Swift
//
|
|
// MergePolicy.swift
|
|
// AltStore
|
|
//
|
|
// Created by Riley Testut on 7/23/19.
|
|
// Copyright © 2019 Riley Testut. All rights reserved.
|
|
//
|
|
|
|
import CoreData
|
|
|
|
import Roxas
|
|
|
|
open class MergePolicy: RSTRelationshipPreservingMergePolicy
|
|
{
|
|
open override func resolve(constraintConflicts conflicts: [NSConstraintConflict]) throws
|
|
{
|
|
guard conflicts.allSatisfy({ $0.databaseObject != nil }) else {
|
|
for conflict in conflicts
|
|
{
|
|
switch conflict.conflictingObjects.first
|
|
{
|
|
case is StoreApp where conflict.conflictingObjects.count == 2:
|
|
// Modified cached StoreApp while replacing it with new one, causing context-level conflict.
|
|
// Most likely, we set up a relationship between the new StoreApp and a NewsItem,
|
|
// causing cached StoreApp to delete it's NewsItem relationship, resulting in (resolvable) conflict.
|
|
|
|
if let previousApp = conflict.conflictingObjects.first(where: { !$0.isInserted }) as? StoreApp
|
|
{
|
|
// Delete previous permissions (same as below).
|
|
for permission in previousApp.permissions
|
|
{
|
|
permission.managedObjectContext?.delete(permission)
|
|
}
|
|
}
|
|
|
|
default:
|
|
// Unknown context-level conflict.
|
|
assertionFailure("MergePolicy is only intended to work with database-level conflicts.")
|
|
}
|
|
}
|
|
|
|
try super.resolve(constraintConflicts: conflicts)
|
|
|
|
return
|
|
}
|
|
|
|
for conflict in conflicts
|
|
{
|
|
switch conflict.databaseObject
|
|
{
|
|
case let databaseObject as StoreApp:
|
|
// Delete previous permissions
|
|
for permission in databaseObject.permissions
|
|
{
|
|
permission.managedObjectContext?.delete(permission)
|
|
}
|
|
|
|
case let databaseObject as Source:
|
|
guard let conflictedObject = conflict.conflictingObjects.first as? Source else { break }
|
|
|
|
let bundleIdentifiers = Set(conflictedObject.apps.map { $0.bundleIdentifier })
|
|
let newsItemIdentifiers = Set(conflictedObject.newsItems.map { $0.identifier })
|
|
|
|
for app in databaseObject.apps
|
|
{
|
|
if !bundleIdentifiers.contains(app.bundleIdentifier)
|
|
{
|
|
// No longer listed in Source, so remove it from database.
|
|
app.managedObjectContext?.delete(app)
|
|
}
|
|
}
|
|
|
|
for newsItem in databaseObject.newsItems
|
|
{
|
|
if !newsItemIdentifiers.contains(newsItem.identifier)
|
|
{
|
|
// No longer listed in Source, so remove it from database.
|
|
newsItem.managedObjectContext?.delete(newsItem)
|
|
}
|
|
}
|
|
|
|
default: break
|
|
}
|
|
}
|
|
|
|
try super.resolve(constraintConflicts: conflicts)
|
|
}
|
|
}
|