mirror of
https://github.com/f-droid/fdroidclient.git
synced 2026-04-20 06:47:06 -04:00
[app] Add ContentProviderMigrator to migrate old repos to new DB
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
apply plugin: 'com.android.application'
|
||||
apply plugin: 'kotlin-android'
|
||||
apply plugin: 'checkstyle'
|
||||
apply plugin: 'pmd'
|
||||
|
||||
|
||||
@@ -57,6 +57,7 @@ import org.fdroid.database.Repository;
|
||||
import org.fdroid.fdroid.Preferences.ChangeListener;
|
||||
import org.fdroid.fdroid.Preferences.Theme;
|
||||
import org.fdroid.fdroid.data.App;
|
||||
import org.fdroid.fdroid.data.ContentProviderMigrator;
|
||||
import org.fdroid.fdroid.data.DBHelper;
|
||||
import org.fdroid.fdroid.installer.ApkFileProvider;
|
||||
import org.fdroid.fdroid.installer.InstallHistoryService;
|
||||
@@ -414,6 +415,17 @@ public class FDroidApp extends Application implements androidx.work.Configuratio
|
||||
if (Preferences.get().isScanRemovableStorageEnabled()) {
|
||||
SDCardScannerService.scan(this);
|
||||
}
|
||||
|
||||
// Migrate repos from old content providers to new Room-based DB.
|
||||
// Added end of 2022 for alphas, can be removed after sufficient time has passed.
|
||||
Utils.runOffUiThread(() -> {
|
||||
ContentProviderMigrator migrator = ContentProviderMigrator.INSTANCE;
|
||||
if (migrator.needsMigration(this)) {
|
||||
migrator.migrateOldRepos(this, db);
|
||||
migrator.removeOldDb(this);
|
||||
UpdateService.forceUpdateRepo(this);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -406,11 +406,7 @@ public class UpdateService extends JobIntentService {
|
||||
}
|
||||
} else if ((manualUpdate || forcedUpdate) && fdroidPrefs.isOnDemandDownloadAllowed()) {
|
||||
Utils.debugLog(TAG, "manually requested or forced update");
|
||||
if (forcedUpdate) {
|
||||
DBHelper.resetRepos(this);
|
||||
// TODO check if we still need something like this:
|
||||
// InstalledAppProviderService.compareToPackageManager(this);
|
||||
}
|
||||
if (forcedUpdate) DBHelper.resetTransient(this);
|
||||
} else if (!fdroidPrefs.isBackgroundDownloadAllowed() && !fdroidPrefs.isOnDemandDownloadAllowed()) {
|
||||
Utils.debugLog(TAG, "don't run update");
|
||||
return;
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
package org.fdroid.fdroid.data
|
||||
|
||||
import android.content.Context
|
||||
import android.database.sqlite.SQLiteDatabase
|
||||
import android.database.sqlite.SQLiteOpenHelper
|
||||
import org.fdroid.database.FDroidDatabase
|
||||
import org.fdroid.database.InitialRepository
|
||||
|
||||
object ContentProviderMigrator {
|
||||
|
||||
private const val OLD_DB_NAME = "fdroid"
|
||||
|
||||
fun needsMigration(context: Context): Boolean {
|
||||
return context.databaseList().contains(OLD_DB_NAME)
|
||||
}
|
||||
|
||||
fun migrateOldRepos(context: Context, db: FDroidDatabase) {
|
||||
val repoDao = db.getRepositoryDao()
|
||||
val repos = repoDao.getRepositories()
|
||||
var weight = repos.last().weight
|
||||
ContentProviderDbHelper(context).readableDatabase.use { oldDb ->
|
||||
val projection = arrayOf("address", "pubkey", "inuse", "userMirrors", "disabledMirrors")
|
||||
oldDb.query("fdroid_repo", projection, null, null, null, null, null).use { c ->
|
||||
while (c.moveToNext()) {
|
||||
val address = c.getString(c.getColumnIndexOrThrow("address"))
|
||||
val certificate = c.getString(c.getColumnIndexOrThrow("pubkey"))
|
||||
?.lowercase() ?: continue
|
||||
val enabled = c.getInt(c.getColumnIndexOrThrow("inuse")) == 1
|
||||
val userMirrors = c.getString(c.getColumnIndexOrThrow("userMirrors"))
|
||||
?.split(',')
|
||||
val disabledMirrors = c.getString(c.getColumnIndexOrThrow("disabledMirrors"))
|
||||
?.split(',')
|
||||
// find existing repos by address, because F-Droid archive re-uses certificate
|
||||
val repo = repos.find { it.address == address }
|
||||
if (repo == null) { // new repo to be added to new DB
|
||||
val newRepo = InitialRepository(
|
||||
name = "",
|
||||
address = address,
|
||||
description = "",
|
||||
certificate = certificate,
|
||||
version = 0,
|
||||
enabled = enabled,
|
||||
weight = ++weight,
|
||||
)
|
||||
repoDao.insert(newRepo)
|
||||
} else { // old repo that may need an update for the new DB
|
||||
if (repo.certificate != certificate) {
|
||||
continue // don't update with certificate does not match
|
||||
}
|
||||
if (repo.enabled != enabled) {
|
||||
repoDao.setRepositoryEnabled(repo.repoId, enabled)
|
||||
}
|
||||
if (!userMirrors.isNullOrEmpty()) {
|
||||
repoDao.updateUserMirrors(repo.repoId, userMirrors)
|
||||
}
|
||||
if (!disabledMirrors.isNullOrEmpty()) {
|
||||
repoDao.updateDisabledMirrors(repo.repoId, disabledMirrors)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun removeOldDb(context: Context) {
|
||||
context.deleteDatabase(OLD_DB_NAME)
|
||||
}
|
||||
|
||||
private class ContentProviderDbHelper(
|
||||
context: Context,
|
||||
) : SQLiteOpenHelper(context, OLD_DB_NAME, null, 85) {
|
||||
override fun onCreate(db: SQLiteDatabase) {}
|
||||
override fun onUpgrade(db: SQLiteDatabase, oldVersion: Int, newVersion: Int) {}
|
||||
}
|
||||
}
|
||||
@@ -81,6 +81,16 @@ public class DBHelper {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all index data related to apps from the DB.
|
||||
* Leaves repositories, their preferences as well as app preferences in place.
|
||||
*/
|
||||
@AnyThread
|
||||
public static void resetTransient(Context context) {
|
||||
FDroidDatabase db = getDb(context);
|
||||
Utils.runOffUiThread(() -> db.getAppDao().clearAll());
|
||||
}
|
||||
|
||||
@AnyThread
|
||||
public static void resetRepos(Context context) {
|
||||
FDroidDatabase db = getDb(context);
|
||||
|
||||
Reference in New Issue
Block a user