mirror of
https://github.com/JohnEstropia/CoreStore.git
synced 2026-03-27 03:41:29 +01:00
assert migration chain when creating a data stack
This commit is contained in:
@@ -31,25 +31,6 @@ import CoreData
|
|||||||
|
|
||||||
public struct MigrationChain: NilLiteralConvertible, StringLiteralConvertible, DictionaryLiteralConvertible, ArrayLiteralConvertible {
|
public struct MigrationChain: NilLiteralConvertible, StringLiteralConvertible, DictionaryLiteralConvertible, ArrayLiteralConvertible {
|
||||||
|
|
||||||
// MARK: Public
|
|
||||||
|
|
||||||
public func contains(version: String) -> Bool {
|
|
||||||
|
|
||||||
return self.rootVersions.contains(version)
|
|
||||||
|| self.leafVersions.contains(version)
|
|
||||||
|| self.versionTree[version] != nil
|
|
||||||
}
|
|
||||||
|
|
||||||
public func nextVersionFrom(version: String) -> String? {
|
|
||||||
|
|
||||||
if let nextVersion = self.versionTree[version] where nextVersion != version {
|
|
||||||
|
|
||||||
return nextVersion
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// MARK: NilLiteralConvertible
|
// MARK: NilLiteralConvertible
|
||||||
|
|
||||||
public init(nilLiteral: ()) {
|
public init(nilLiteral: ()) {
|
||||||
@@ -57,6 +38,7 @@ public struct MigrationChain: NilLiteralConvertible, StringLiteralConvertible, D
|
|||||||
self.versionTree = [:]
|
self.versionTree = [:]
|
||||||
self.rootVersions = []
|
self.rootVersions = []
|
||||||
self.leafVersions = []
|
self.leafVersions = []
|
||||||
|
self.valid = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -67,6 +49,7 @@ public struct MigrationChain: NilLiteralConvertible, StringLiteralConvertible, D
|
|||||||
self.versionTree = [:]
|
self.versionTree = [:]
|
||||||
self.rootVersions = [value]
|
self.rootVersions = [value]
|
||||||
self.leafVersions = [value]
|
self.leafVersions = [value]
|
||||||
|
self.valid = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -77,6 +60,7 @@ public struct MigrationChain: NilLiteralConvertible, StringLiteralConvertible, D
|
|||||||
self.versionTree = [:]
|
self.versionTree = [:]
|
||||||
self.rootVersions = [value]
|
self.rootVersions = [value]
|
||||||
self.leafVersions = [value]
|
self.leafVersions = [value]
|
||||||
|
self.valid = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -87,6 +71,7 @@ public struct MigrationChain: NilLiteralConvertible, StringLiteralConvertible, D
|
|||||||
self.versionTree = [:]
|
self.versionTree = [:]
|
||||||
self.rootVersions = [value]
|
self.rootVersions = [value]
|
||||||
self.leafVersions = [value]
|
self.leafVersions = [value]
|
||||||
|
self.valid = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -94,9 +79,13 @@ public struct MigrationChain: NilLiteralConvertible, StringLiteralConvertible, D
|
|||||||
|
|
||||||
public init(dictionaryLiteral elements: (String, String)...) {
|
public init(dictionaryLiteral elements: (String, String)...) {
|
||||||
|
|
||||||
|
var valid = true
|
||||||
let versionTree = elements.reduce([String: String]()) { (var versionTree, tuple: (String, String)) -> [String: String] in
|
let versionTree = elements.reduce([String: String]()) { (var versionTree, tuple: (String, String)) -> [String: String] in
|
||||||
|
|
||||||
versionTree[tuple.0] = tuple.1
|
if let _ = versionTree.updateValue(tuple.1, forKey: tuple.0) {
|
||||||
|
|
||||||
|
valid = false
|
||||||
|
}
|
||||||
return versionTree
|
return versionTree
|
||||||
}
|
}
|
||||||
let leafVersions = Set(
|
let leafVersions = Set(
|
||||||
@@ -110,6 +99,7 @@ public struct MigrationChain: NilLiteralConvertible, StringLiteralConvertible, D
|
|||||||
self.versionTree = versionTree
|
self.versionTree = versionTree
|
||||||
self.rootVersions = Set(versionTree.keys).subtract(versionTree.values)
|
self.rootVersions = Set(versionTree.keys).subtract(versionTree.values)
|
||||||
self.leafVersions = leafVersions
|
self.leafVersions = leafVersions
|
||||||
|
self.valid = valid
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -121,11 +111,15 @@ public struct MigrationChain: NilLiteralConvertible, StringLiteralConvertible, D
|
|||||||
|
|
||||||
var lastVersion: String?
|
var lastVersion: String?
|
||||||
var versionTree = [String: String]()
|
var versionTree = [String: String]()
|
||||||
|
var valid = true
|
||||||
for version in elements {
|
for version in elements {
|
||||||
|
|
||||||
if let lastVersion = lastVersion {
|
if let lastVersion = lastVersion {
|
||||||
|
|
||||||
versionTree[lastVersion] = version
|
if let _ = versionTree.updateValue(version, forKey: lastVersion) {
|
||||||
|
|
||||||
|
valid = false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
lastVersion = version
|
lastVersion = version
|
||||||
}
|
}
|
||||||
@@ -133,6 +127,7 @@ public struct MigrationChain: NilLiteralConvertible, StringLiteralConvertible, D
|
|||||||
self.versionTree = versionTree
|
self.versionTree = versionTree
|
||||||
self.rootVersions = Set([elements.first].flatMap { $0 == nil ? [] : [$0!] })
|
self.rootVersions = Set([elements.first].flatMap { $0 == nil ? [] : [$0!] })
|
||||||
self.leafVersions = Set([elements.last].flatMap { $0 == nil ? [] : [$0!] })
|
self.leafVersions = Set([elements.last].flatMap { $0 == nil ? [] : [$0!] })
|
||||||
|
self.valid = valid
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -140,9 +135,54 @@ public struct MigrationChain: NilLiteralConvertible, StringLiteralConvertible, D
|
|||||||
|
|
||||||
internal let rootVersions: Set<String>
|
internal let rootVersions: Set<String>
|
||||||
internal let leafVersions: Set<String>
|
internal let leafVersions: Set<String>
|
||||||
|
internal let valid: Bool
|
||||||
|
|
||||||
|
internal func contains(version: String) -> Bool {
|
||||||
|
|
||||||
|
return self.rootVersions.contains(version)
|
||||||
|
|| self.leafVersions.contains(version)
|
||||||
|
|| self.versionTree[version] != nil
|
||||||
|
}
|
||||||
|
|
||||||
|
internal func nextVersionFrom(version: String) -> String? {
|
||||||
|
|
||||||
|
if let nextVersion = self.versionTree[version] where nextVersion != version {
|
||||||
|
|
||||||
|
return nextVersion
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// MARK: Private
|
// MARK: Private
|
||||||
|
|
||||||
private let versionTree: [String: String]
|
private let versionTree: [String: String]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// MARK: - MigrationChain: CustomDebugStringConvertible
|
||||||
|
|
||||||
|
extension MigrationChain: CustomDebugStringConvertible {
|
||||||
|
|
||||||
|
public var debugDescription: String {
|
||||||
|
|
||||||
|
guard self.valid else {
|
||||||
|
|
||||||
|
return "<invalid migration chain>"
|
||||||
|
}
|
||||||
|
|
||||||
|
var paths = [String]()
|
||||||
|
for var version in self.rootVersions {
|
||||||
|
|
||||||
|
var steps = [version]
|
||||||
|
while let nextVersion = self.nextVersionFrom(version) {
|
||||||
|
|
||||||
|
steps.append(nextVersion)
|
||||||
|
version = nextVersion
|
||||||
|
}
|
||||||
|
paths.append(" → ".join(steps))
|
||||||
|
}
|
||||||
|
|
||||||
|
return "[" + "], [".join(paths) + "]"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -53,14 +53,17 @@ public final class DataStack {
|
|||||||
*/
|
*/
|
||||||
public required init(modelName: String = applicationName, bundle: NSBundle = NSBundle.mainBundle(), migrationChain: MigrationChain = nil) {
|
public required init(modelName: String = applicationName, bundle: NSBundle = NSBundle.mainBundle(), migrationChain: MigrationChain = nil) {
|
||||||
|
|
||||||
|
CoreStore.assert(
|
||||||
|
migrationChain.valid,
|
||||||
|
"Invalid migration chain passed to the \(typeName(DataStack)). Check that the model versions' order is correct and that no repetitions or ambiguities exist."
|
||||||
|
)
|
||||||
|
|
||||||
let model = NSManagedObjectModel.fromBundle(
|
let model = NSManagedObjectModel.fromBundle(
|
||||||
bundle,
|
bundle,
|
||||||
modelName: modelName,
|
modelName: modelName,
|
||||||
modelVersion: migrationChain.leafVersions.first
|
modelVersion: migrationChain.leafVersions.first
|
||||||
)
|
)
|
||||||
|
|
||||||
// TODO: assert existence of all model versions in the migrationChain
|
|
||||||
|
|
||||||
self.coordinator = NSPersistentStoreCoordinator(managedObjectModel: model)
|
self.coordinator = NSPersistentStoreCoordinator(managedObjectModel: model)
|
||||||
self.rootSavingContext = NSManagedObjectContext.rootSavingContextForCoordinator(self.coordinator)
|
self.rootSavingContext = NSManagedObjectContext.rootSavingContextForCoordinator(self.coordinator)
|
||||||
self.mainContext = NSManagedObjectContext.mainContextForRootContext(self.rootSavingContext)
|
self.mainContext = NSManagedObjectContext.mainContextForRootContext(self.rootSavingContext)
|
||||||
|
|||||||
Reference in New Issue
Block a user