[db] Rework AppDao#clearAll() method to fix critical bug

This is a breaking change.

The new method is in FDroidDatabase and called clearAllAppData(). It now also resets repository timestamps, so we will not try to apply a diff when we should use a full index.
This commit is contained in:
Torsten Grote
2023-04-05 17:34:36 -03:00
committed by Hans-Christoph Steiner
parent 9530f51f2c
commit 4d0abde694
4 changed files with 66 additions and 6 deletions

View File

@@ -0,0 +1,44 @@
package org.fdroid.database
import androidx.test.ext.junit.runners.AndroidJUnit4
import org.fdroid.test.TestRepoUtils
import org.junit.Test
import org.junit.runner.RunWith
import kotlin.test.assertEquals
import kotlin.test.assertNotEquals
@RunWith(AndroidJUnit4::class)
internal class FDroidDatabaseTest : AppTest() {
@Test
fun testClearAllAppData() {
// insert three apps in two repos
val repoId2 = repoDao.insertOrReplace(TestRepoUtils.getRandomRepo())
val repoId1 = repoDao.insertOrReplace(TestRepoUtils.getRandomRepo())
appDao.insert(repoId1, packageName1, app1, locales)
appDao.insert(repoId2, packageName2, app2, locales)
appDao.insert(repoId2, packageName3, app3, locales)
// assert that both repos and all three apps made it into the DB
assertEquals(2, repoDao.getRepositories().size)
assertEquals(3, appDao.countApps())
// assert that repo timestamps are recent, not reset
repoDao.getRepositories().forEach { repo ->
assertNotEquals(-1, repo.timestamp)
}
// clear all app data
db.clearAllAppData()
// assert that both repos survived, but all apps are gone
assertEquals(2, repoDao.getRepositories().size)
assertEquals(0, appDao.countApps())
// assert that repo timestamps got reset
repoDao.getRepositories().forEach { repo ->
assertEquals(-1, repo.timestamp)
}
}
}

View File

@@ -111,11 +111,6 @@ public interface AppDao {
public fun getNumberOfAppsInCategory(category: String): Int
public fun getNumberOfAppsInRepository(repoId: Long): Int
/**
* Removes all apps and associated data from all repositories.
*/
public fun clearAll()
}
public enum class AppListSortOrder {
@@ -598,5 +593,5 @@ internal interface AppDaoInt : AppDao {
fun countLocalizedFileLists(): Int
@Query("DELETE FROM ${AppMetadata.TABLE}")
override fun clearAll()
fun clearAll()
}

View File

@@ -69,6 +69,13 @@ internal abstract class FDroidDatabaseInt internal constructor() : RoomDatabase(
fun afterUpdatingRepo(repoId: Long) {
getAppDao().updateCompatibility(repoId)
}
override fun clearAllAppData() {
runInTransaction {
getAppDao().clearAll()
getRepositoryDao().resetTimestamps()
}
}
}
/**
@@ -93,4 +100,11 @@ public interface FDroidDatabase {
* Please run as little code as possible to keep the time the database is blocked minimal.
*/
public fun runInTransaction(body: Runnable)
/**
* Removes all apps and associated data (such as versions) from all repositories.
* The repository data and app preferences are kept as-is.
* Only the timestamp of the last repo update gets reset, so we won't try to apply diffs.
*/
public fun clearAllAppData()
}

View File

@@ -378,6 +378,13 @@ internal interface RepositoryDaoInt : RepositoryDao {
@Query("DELETE FROM ${ReleaseChannel.TABLE} WHERE repoId = :repoId AND id = :id")
fun deleteReleaseChannel(repoId: Long, id: String)
/**
* Resets timestamps for *all* repos in the database.
* This will cause
*/
@Query("UPDATE ${CoreRepository.TABLE} SET timestamp = -1")
fun resetTimestamps()
/**
* Use when replacing an existing repo with a full index.
* This removes all existing index data associated with this repo from the database,