Skip to content
This repository has been archived by the owner on May 10, 2024. It is now read-only.

Fix #195 Added Migration code for sqlite files from Document to Application Support folder #1026

Merged
merged 5 commits into from
Aug 5, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Client/Application/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UIViewControllerRestorati

updateShortcutItems(application)

Migration.moveDatabaseToApplicationDirectory()
// Passcode checking, must happen on immediate launch
if !DataController.shared.storeExists() {
// Since passcode is stored in keychain it persists between installations.
Expand Down
5 changes: 5 additions & 0 deletions Client/Application/Migration.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@ class Migration {
Preferences.Migration.syncOrderCompleted.value = true
}
}

static func moveDatabaseToApplicationDirectory() {
//Moves Coredata sqlite file from Documents dir to application support dir.
DataController.shared.migrateToNewPathIfNeeded()
}
}

fileprivate extension Preferences {
Expand Down
42 changes: 41 additions & 1 deletion Data/models/DataController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,24 @@ public class DataController: NSObject {
return FileManager.default.fileExists(atPath: storeURL.path)
}

public func migrateToNewPathIfNeeded() {
func sqliteFiles(from url: URL, dbName: String) throws -> [URL] {
return try FileManager.default.contentsOfDirectory(at: url, includingPropertiesForKeys: nil, options: []).filter({$0.lastPathComponent.hasPrefix(dbName)})
}
if FileManager.default.fileExists(atPath: oldStoreURL.path) && !storeExists() {
do {
try migrationContainer.persistentStoreCoordinator.addPersistentStore(ofType: NSSQLiteStoreType, configurationName: nil, at: oldStoreURL, options: nil)
if let oldStore = migrationContainer.persistentStoreCoordinator.persistentStore(for: oldStoreURL) {
try migrationContainer.persistentStoreCoordinator.migratePersistentStore(oldStore, to: storeURL, options: nil, withType: NSSQLiteStoreType)
try migrationContainer.persistentStoreCoordinator.destroyPersistentStore(at: oldStoreURL, ofType: NSSQLiteStoreType, options: nil)
try sqliteFiles(from: oldStoreURL.deletingLastPathComponent(), dbName: DataController.databaseName).forEach(FileManager.default.removeItem)
}
} catch {
log.error(error)
}
}
}

// MARK: - Data framework interface

static func perform(context: WriteContext = .new(inMemory: false), save: Bool = true,
Expand Down Expand Up @@ -105,6 +123,17 @@ public class DataController: NSObject {
}

// MARK: - Private
private lazy var migrationContainer: NSPersistentContainer = {

let modelName = "Model"
guard let modelURL = Bundle(for: DataController.self).url(forResource: modelName, withExtension: "momd") else {
fatalError("Error loading model from bundle")
}
guard let mom = NSManagedObjectModel(contentsOf: modelURL) else {
fatalError("Error initializing managed object model from: \(modelURL)")
}
return NSPersistentContainer(name: modelName, managedObjectModel: mom)
}()

private lazy var container: NSPersistentContainer = {

Expand Down Expand Up @@ -137,7 +166,8 @@ public class DataController: NSObject {
return queue
}()

private let storeURL: URL = {
/// Warning! Please use storeURL. oldStoreURL is for migration purpose only.
private let oldStoreURL: URL = {
let urls = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
guard let docURL = urls.last else {
log.error("Could not load url at document directory")
Expand All @@ -147,6 +177,16 @@ public class DataController: NSObject {
return docURL.appendingPathComponent(DataController.databaseName)
}()

private let storeURL: URL = {
let urls = FileManager.default.urls(for: .applicationSupportDirectory, in: .userDomainMask)
guard let docURL = urls.last else {
log.error("Could not load url at application support directory")
fatalError()
}

return docURL.appendingPathComponent(DataController.databaseName)
}()

private static func newBackgroundContext() -> NSManagedObjectContext {
let backgroundContext = DataController.shared.container.newBackgroundContext()
// In theory, the merge policy should not matter
Expand Down