Merge pull request #364 from rpassis/bugfix/CoreDataVersioning

Improvements to determining the current version of a versioned CoreData model
This commit is contained in:
Yonas Kolb 2018-08-02 22:37:35 +10:00 committed by GitHub
commit 907e276394
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 61 additions and 8 deletions

View File

@ -130,11 +130,15 @@ class SourceGenerator {
let lastKnownFileType = lastKnownFileType ?? PBXFileReference.fileType(path: path)
if path.extension == "xcdatamodeld" {
let models = (try? path.children()) ?? []
let modelFileReference = models
let versionedModels = (try? path.children()) ?? []
// Sort the versions alphabetically
let sortedPaths = versionedModels
.filter { $0.extension == "xcdatamodel" }
.sorted { $0.string.localizedStandardCompare($1.string) == .orderedAscending }
.map { path in
let modelFileReference =
sortedPaths.map { path in
createObject(
id: path.byRemovingBase(path: project.basePath).string,
PBXFileReference(
@ -144,8 +148,15 @@ class SourceGenerator {
)
)
}
// If no current version path is found we fall back to alphabetical
// order by taking the last item in the sortedPaths array
let currentVersionPath = findCurrentCoreDataModelVersionPath(using: versionedModels) ?? sortedPaths.last
let currentVersion: ObjectReference<PBXFileReference>? = {
guard let indexOf = sortedPaths.index(where: { $0 == currentVersionPath }) else { return nil }
return modelFileReference[indexOf]
}()
let versionGroup = addObject(id: fileReferencePath.string, XCVersionGroup(
currentVersion: modelFileReference.last?.reference,
currentVersion: currentVersion?.reference,
path: fileReferencePath.string,
sourceTree: sourceTree,
versionGroupType: "wrapper.xcdatamodel",
@ -154,6 +165,7 @@ class SourceGenerator {
fileReferencesByPath[fileReferenceKey] = versionGroup
return versionGroup
} else {
// For all extensions other than `xcdatamodeld`
let fileReference = createObject(
id: path.byRemovingBase(path: project.basePath).string,
PBXFileReference(
@ -506,4 +518,16 @@ class SourceGenerator {
createIntermediaGroups(for: parentGroup.reference, at: parentPath)
}
}
private func findCurrentCoreDataModelVersionPath(using versionedModels: [Path]) -> Path? {
// Find and parse the current version model stored in the .xccurrentversion file
guard
let versionPath = versionedModels.first(where: { $0.lastComponent == ".xccurrentversion" }),
let data = try? versionPath.read(),
let plist = try? PropertyListSerialization.propertyList(from: data, options: [], format: nil) as? [String: Any],
let versionString = plist?["_XCCurrentVersionName"] as? String else {
return nil
}
return versionedModels.first(where: { $0.lastComponent == versionString })
}
}

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>_XCCurrentVersionName</key>
<string>Model 2.xcdatamodel</string>
</dict>
</plist>

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<model type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="13772" systemVersion="17D47" minimumToolsVersion="Automatic" sourceLanguage="Swift" userDefinedModelVersionIdentifier="">
<entity name="Entity" representedClassName="Entity" syncable="YES" codeGenerationType="class"/>
<elements>
<element name="Entity" positionX="-63" positionY="-18" width="128" height="45"/>
</elements>
</model>

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<model type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="13772" systemVersion="17D47" minimumToolsVersion="Automatic" sourceLanguage="Swift" userDefinedModelVersionIdentifier="">
<entity name="Entity" representedClassName="Entity" syncable="YES" codeGenerationType="class"/>
<elements>
<element name="Entity" positionX="-63" positionY="-18" width="128" height="45"/>
</elements>
</model>

View File

@ -300,6 +300,7 @@
FR_256263906698 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
FR_257073931060 /* ResourceFolder */ = {isa = PBXFileReference; lastKnownFileType = folder; name = ResourceFolder; path = Resources/ResourceFolder; sourceTree = SOURCE_ROOT; };
FR_257516580010 /* Alamofire.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = Alamofire.framework; sourceTree = "<group>"; };
FR_263408310401 /* Model 3.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = "Model 3.xcdatamodel"; sourceTree = "<group>"; };
FR_264279911176 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Interface.storyboard; sourceTree = "<group>"; };
FR_293137352077 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
FR_304712043717 /* NotificationController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationController.swift; sourceTree = "<group>"; };
@ -344,6 +345,7 @@
FR_771029596306 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Localizable.strings; sourceTree = "<group>"; };
FR_775316160345 /* SomeFile */ = {isa = PBXFileReference; path = SomeFile; sourceTree = "<group>"; };
FR_783122899910 /* App_iOS_Tests.xctest */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = wrapper.cfbundle; path = App_iOS_Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
FR_796781152159 /* Model 2.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = "Model 2.xcdatamodel"; sourceTree = "<group>"; };
FR_815403394914 /* Headers */ = {isa = PBXFileReference; lastKnownFileType = folder; path = Headers; sourceTree = SOURCE_ROOT; };
FR_825232110500 /* App_iOS.app */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = wrapper.application; path = App_iOS.app; sourceTree = BUILT_PRODUCTS_DIR; };
FR_830053537293 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
@ -3406,9 +3408,11 @@
VG_229021855709 /* Model.xcdatamodeld */ = {
isa = XCVersionGroup;
children = (
FR_796781152159 /* Model 2.xcdatamodel */,
FR_263408310401 /* Model 3.xcdatamodel */,
FR_570918052822 /* Model.xcdatamodel */,
);
currentVersion = FR_570918052822 /* Model.xcdatamodel */;
currentVersion = FR_796781152159 /* Model 2.xcdatamodel */;
path = Model.xcdatamodeld;
sourceTree = "<group>";
versionGroupType = wrapper.xcdatamodel;

View File

@ -101,7 +101,10 @@ class SourceGeneratorTests: XCTestCase {
let directories = """
Sources:
model.xcdatamodeld:
- .xccurrentversion
- model.xcdatamodel
- model1.xcdatamodel
- model2.xcdatamodel
"""
try createDirectories(directories)
@ -109,16 +112,16 @@ class SourceGeneratorTests: XCTestCase {
let project = Project(basePath: directoryPath, name: "Test", targets: [target])
let pbxProj = try project.generatePbxProj()
guard let fileReference = pbxProj.objects.fileReferences.first(where: { $0.value.nameOrPath == "model.xcdatamodel" }) else {
guard let fileReference = pbxProj.objects.fileReferences.first(where: { $0.value.nameOrPath == "model2.xcdatamodel" }) else {
throw failure("Couldn't find model file reference")
}
guard let versionGroup = pbxProj.objects.versionGroups.values.first else {
throw failure("Couldn't find version group")
}
try expect(versionGroup.currentVersion) == fileReference.key
try expect(versionGroup.children) == [fileReference.key]
try expect(versionGroup.children.count) == 3
try expect(versionGroup.path) == "model.xcdatamodeld"
try expect(fileReference.value.path) == "model.xcdatamodel"
try expect(fileReference.value.path) == "model2.xcdatamodel"
}
$0.it("handles duplicate names") {