core: support down migrations to allow reverting to the previous version (#2072)

* core: support down migrations to allow reverting to the previous version

* update schema

* update simplexmq

* rename errors

* remove unused functions

* migration UI, test migration

* update migration UI

* return current migrations in CRVersionInfo

* update simplexmq

* test down migrations

* cleanup ios

* show migrations in log
This commit is contained in:
Evgeny Poberezkin
2023-03-27 18:34:48 +01:00
committed by GitHub
parent f5c11b8faf
commit c96ba30018
26 changed files with 365 additions and 222 deletions
+34 -4
View File
@@ -17,7 +17,7 @@ public func getChatCtrl(_ useKey: String? = nil) -> chat_ctrl {
fatalError("chat controller not initialized")
}
public func chatMigrateInit(_ useKey: String? = nil) -> (Bool, DBMigrationResult) {
public func chatMigrateInit(_ useKey: String? = nil, confirmMigrations: MigrationConfirmation? = nil) -> (Bool, DBMigrationResult) {
if let res = migrationResult { return res }
let dbPath = getAppDatabasePath().path
var dbKey = ""
@@ -34,12 +34,14 @@ public func chatMigrateInit(_ useKey: String? = nil) -> (Bool, DBMigrationResult
dbKey = key
}
}
logger.debug("chatMigrateInit DB path: \(dbPath)")
let confirm = confirmMigrations ?? defaultMigrationConfirmation()
logger.debug("chatMigrateInit DB path: \(dbPath), confirm: \(confirm.rawValue)")
// logger.debug("chatMigrateInit DB key: \(dbKey)")
var cPath = dbPath.cString(using: .utf8)!
var cKey = dbKey.cString(using: .utf8)!
var cConfirm = confirm.rawValue.cString(using: .utf8)!
// the last parameter of chat_migrate_init is used to return the pointer to chat controller
let cjson = chat_migrate_init(&cPath, &cKey, &chatController)!
let cjson = chat_migrate_init(&cPath, &cKey, &cConfirm, &chatController)!
let dbRes = dbMigrationResult(fromCString(cjson))
let encrypted = dbKey != ""
let keychainErr = dbRes == .ok && useKeychain && encrypted && !setDatabaseKey(dbKey)
@@ -207,12 +209,40 @@ func chatErrorString(_ err: ChatError) -> String {
public enum DBMigrationResult: Decodable, Equatable {
case ok
case invalidConfirmation
case errorNotADatabase(dbFile: String)
case error(dbFile: String, migrationError: String)
case errorMigration(dbFile: String, migrationError: MigrationError)
case errorSQL(dbFile: String, migrationSQLError: String)
case errorKeychain
case unknown(json: String)
}
public enum MigrationConfirmation: String {
case yesUp
case yesUpDown
case error
}
public func defaultMigrationConfirmation() -> MigrationConfirmation {
confirmDBUpgradesGroupDefault.get() ? .error : .yesUp
}
public enum MigrationError: Decodable, Equatable {
case upgrade(upMigrations: [UpMigration])
case downgrade(downMigrations: [String])
case migrationError(mtrError: MTRError)
}
public struct UpMigration: Decodable, Equatable {
public var upName: String
// public var withDown: Bool
}
public enum MTRError: Decodable, Equatable {
case noDown(dbMigrations: [String])
case different(appMigration: String, dbMigration: String)
}
func dbMigrationResult(_ s: String) -> DBMigrationResult {
let d = s.data(using: .utf8)!
// TODO is there a way to do it without copying the data? e.g: