mirror of
https://github.com/JohnEstropia/CoreStore.git
synced 2026-05-07 16:34:16 +02:00
WIP: allow migrations for CoreStoreObjects
This commit is contained in:
@@ -218,7 +218,7 @@ public extension DataStack {
|
||||
|
||||
try storage.eraseStorageAndWait(
|
||||
metadata: metadata,
|
||||
soureModelHint: self.model[metadata]
|
||||
soureModelHint: self.schemaHistory.schema(for: metadata)?.rawModel()
|
||||
)
|
||||
_ = try self.addStorageAndWait(storage)
|
||||
|
||||
@@ -382,7 +382,9 @@ public extension DataStack {
|
||||
at: cacheFileURL,
|
||||
options: storeOptions
|
||||
)
|
||||
_ = try self.model[metadata].flatMap(storage.eraseStorageAndWait)
|
||||
_ = try self.schemaHistory
|
||||
.schema(for: metadata)
|
||||
.flatMap({ try storage.eraseStorageAndWait(soureModel: $0.rawModel()) })
|
||||
_ = try self.createPersistentStoreFromStorage(
|
||||
storage,
|
||||
finalURL: cacheFileURL,
|
||||
@@ -497,7 +499,7 @@ public extension DataStack {
|
||||
|
||||
let error = CoreStoreError.mappingModelNotFound(
|
||||
localStoreURL: fileURL,
|
||||
targetModel: self.model,
|
||||
targetModel: self.schemaHistory.rawModel,
|
||||
targetModelVersion: self.modelVersion
|
||||
)
|
||||
CoreStore.log(
|
||||
@@ -545,12 +547,12 @@ public extension DataStack {
|
||||
|
||||
let error = CoreStoreError.mappingModelNotFound(
|
||||
localStoreURL: storage.fileURL,
|
||||
targetModel: self.model,
|
||||
targetModel: self.schemaHistory.rawModel,
|
||||
targetModelVersion: self.modelVersion
|
||||
)
|
||||
CoreStore.log(
|
||||
error,
|
||||
"Failed to find migration steps from \(cs_typeName(storage)) at URL \"\(storage.fileURL)\" to version model \"\(self.model)\"."
|
||||
"Failed to find migration steps from \(cs_typeName(storage)) at URL \"\(storage.fileURL)\" to version model \"\(self.schemaHistory.rawModel)\"."
|
||||
)
|
||||
|
||||
DispatchQueue.main.async {
|
||||
@@ -592,7 +594,7 @@ public extension DataStack {
|
||||
let progress = Progress(parent: nil, userInfo: nil)
|
||||
progress.totalUnitCount = numberOfMigrations
|
||||
|
||||
for (sourceModel, destinationModel, mappingModel, _) in migrationSteps {
|
||||
for (sourceModel, destinationModel, mappingModel, migrationType) in migrationSteps {
|
||||
|
||||
progress.becomeCurrent(withPendingUnitCount: 1)
|
||||
|
||||
@@ -620,8 +622,13 @@ public extension DataStack {
|
||||
)
|
||||
}
|
||||
catch {
|
||||
|
||||
migrationResult = MigrationResult(error)
|
||||
|
||||
let migrationError = CoreStoreError(error)
|
||||
CoreStore.log(
|
||||
migrationError,
|
||||
"Failed to migrate version model \"\(migrationType.sourceVersion)\" to version \"\(migrationType.destinationVersion)\"."
|
||||
)
|
||||
migrationResult = MigrationResult(migrationError)
|
||||
cancelled = true
|
||||
}
|
||||
}
|
||||
@@ -658,28 +665,27 @@ public extension DataStack {
|
||||
|
||||
private func computeMigrationFromStorage<T: LocalStorage>(_ storage: T, metadata: [String: Any]) -> [(sourceModel: NSManagedObjectModel, destinationModel: NSManagedObjectModel, mappingModel: NSMappingModel, migrationType: MigrationType)]? {
|
||||
|
||||
let model = self.model
|
||||
if model.isConfiguration(withName: storage.configuration, compatibleWithStoreMetadata: metadata) {
|
||||
let schemaHistory = self.schemaHistory
|
||||
if schemaHistory.rawModel.isConfiguration(withName: storage.configuration, compatibleWithStoreMetadata: metadata) {
|
||||
|
||||
return []
|
||||
}
|
||||
|
||||
guard let initialModel = model[metadata],
|
||||
var currentVersion = initialModel.currentModelVersion else {
|
||||
|
||||
return nil
|
||||
guard let initialSchema = schemaHistory.schema(for: metadata) else {
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
let migrationChain: MigrationChain = self.migrationChain.empty
|
||||
? [currentVersion: model.currentModelVersion!]
|
||||
: self.migrationChain
|
||||
var currentVersion = initialSchema.modelVersion
|
||||
let migrationChain: MigrationChain = schemaHistory.migrationChain.isEmpty
|
||||
? [currentVersion: schemaHistory.currentModelVersion]
|
||||
: schemaHistory.migrationChain
|
||||
|
||||
var migrationSteps = [(sourceModel: NSManagedObjectModel, destinationModel: NSManagedObjectModel, mappingModel: NSMappingModel, migrationType: MigrationType)]()
|
||||
|
||||
while let nextVersion = migrationChain.nextVersionFrom(currentVersion),
|
||||
let sourceModel = model[currentVersion],
|
||||
sourceModel != model,
|
||||
let destinationModel = model[nextVersion] {
|
||||
let sourceModel = schemaHistory.rawModel(for: currentVersion),
|
||||
sourceModel != schemaHistory.rawModel,
|
||||
let destinationModel = schemaHistory.rawModel(for: nextVersion) {
|
||||
|
||||
if let mappingModel = NSMappingModel(
|
||||
from: storage.mappingModelBundles,
|
||||
@@ -727,7 +733,7 @@ public extension DataStack {
|
||||
currentVersion = nextVersion
|
||||
}
|
||||
|
||||
if migrationSteps.last?.destinationModel == model {
|
||||
if migrationSteps.last?.destinationModel == schemaHistory.rawModel {
|
||||
|
||||
return migrationSteps
|
||||
}
|
||||
@@ -775,21 +781,8 @@ public extension DataStack {
|
||||
}
|
||||
catch {
|
||||
|
||||
do {
|
||||
|
||||
try fileManager.removeItem(at: temporaryFileURL)
|
||||
}
|
||||
catch _ { }
|
||||
|
||||
let sourceVersion = migrationManager.sourceModel.currentModelVersion ?? "???"
|
||||
let destinationVersion = migrationManager.destinationModel.currentModelVersion ?? "???"
|
||||
let migrationError = CoreStoreError(error)
|
||||
CoreStore.log(
|
||||
migrationError,
|
||||
"Failed to migrate from version model \"\(sourceVersion)\" to version model \"\(destinationVersion)\"."
|
||||
)
|
||||
|
||||
throw migrationError
|
||||
_ = try? fileManager.removeItem(at: temporaryFileURL)
|
||||
throw CoreStoreError(error)
|
||||
}
|
||||
|
||||
do {
|
||||
@@ -806,21 +799,8 @@ public extension DataStack {
|
||||
}
|
||||
catch {
|
||||
|
||||
do {
|
||||
|
||||
try fileManager.removeItem(at: temporaryFileURL)
|
||||
}
|
||||
catch _ { }
|
||||
|
||||
let sourceVersion = migrationManager.sourceModel.currentModelVersion ?? "???"
|
||||
let destinationVersion = migrationManager.destinationModel.currentModelVersion ?? "???"
|
||||
let fileError = CoreStoreError(error)
|
||||
CoreStore.log(
|
||||
fileError,
|
||||
"Failed to save store after migrating from version model \"\(sourceVersion)\" to version model \"\(destinationVersion)\"."
|
||||
)
|
||||
|
||||
throw fileError
|
||||
_ = try? fileManager.removeItem(at: temporaryFileURL)
|
||||
throw CoreStoreError(error)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -70,7 +70,7 @@ public struct MigrationChain: ExpressibleByNilLiteral, ExpressibleByStringLitera
|
||||
self.versionTree = [:]
|
||||
self.rootVersions = []
|
||||
self.leafVersions = []
|
||||
self.valid = true
|
||||
self.isValid = true
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -81,7 +81,7 @@ public struct MigrationChain: ExpressibleByNilLiteral, ExpressibleByStringLitera
|
||||
self.versionTree = [:]
|
||||
self.rootVersions = [value]
|
||||
self.leafVersions = [value]
|
||||
self.valid = true
|
||||
self.isValid = true
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -93,13 +93,13 @@ public struct MigrationChain: ExpressibleByNilLiteral, ExpressibleByStringLitera
|
||||
|
||||
var lastVersion: String?
|
||||
var versionTree = [String: String]()
|
||||
var valid = true
|
||||
var isValid = true
|
||||
for version in elements {
|
||||
|
||||
if let lastVersion = lastVersion,
|
||||
let _ = versionTree.updateValue(version, forKey: lastVersion) {
|
||||
|
||||
valid = false
|
||||
isValid = false
|
||||
}
|
||||
lastVersion = version
|
||||
}
|
||||
@@ -107,7 +107,7 @@ public struct MigrationChain: ExpressibleByNilLiteral, ExpressibleByStringLitera
|
||||
self.versionTree = versionTree
|
||||
self.rootVersions = Set(elements.prefix(1))
|
||||
self.leafVersions = Set(elements.suffix(1))
|
||||
self.valid = valid
|
||||
self.isValid = isValid
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -115,7 +115,7 @@ public struct MigrationChain: ExpressibleByNilLiteral, ExpressibleByStringLitera
|
||||
*/
|
||||
public init(_ elements: [(String, String)]) {
|
||||
|
||||
var valid = true
|
||||
var isValid = true
|
||||
var versionTree = [String: String]()
|
||||
elements.forEach { (sourceVersion, destinationVersion) in
|
||||
|
||||
@@ -126,7 +126,7 @@ public struct MigrationChain: ExpressibleByNilLiteral, ExpressibleByStringLitera
|
||||
|
||||
CoreStore.assert(false, "\(cs_typeName(MigrationChain.self))'s migration chain could not be created due to ambiguous version paths.")
|
||||
|
||||
valid = false
|
||||
isValid = false
|
||||
}
|
||||
let leafVersions = Set(
|
||||
elements
|
||||
@@ -156,7 +156,7 @@ public struct MigrationChain: ExpressibleByNilLiteral, ExpressibleByStringLitera
|
||||
self.versionTree = versionTree
|
||||
self.rootVersions = Set(versionTree.keys).subtracting(versionTree.values)
|
||||
self.leafVersions = leafVersions
|
||||
self.valid = valid && Set(versionTree.keys).union(versionTree.values).filter { isVersionAmbiguous($0) }.count <= 0
|
||||
self.isValid = isValid && Set(versionTree.keys).union(versionTree.values).filter { isVersionAmbiguous($0) }.count <= 0
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -223,7 +223,7 @@ public struct MigrationChain: ExpressibleByNilLiteral, ExpressibleByStringLitera
|
||||
return lhs.versionTree == rhs.versionTree
|
||||
&& lhs.rootVersions == rhs.rootVersions
|
||||
&& lhs.leafVersions == rhs.leafVersions
|
||||
&& lhs.valid == rhs.valid
|
||||
&& lhs.isValid == rhs.isValid
|
||||
}
|
||||
|
||||
|
||||
@@ -231,9 +231,9 @@ public struct MigrationChain: ExpressibleByNilLiteral, ExpressibleByStringLitera
|
||||
|
||||
internal let rootVersions: Set<String>
|
||||
internal let leafVersions: Set<String>
|
||||
internal let valid: Bool
|
||||
internal let isValid: Bool
|
||||
|
||||
internal var empty: Bool {
|
||||
internal var isEmpty: Bool {
|
||||
|
||||
return self.versionTree.count <= 0
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user