mirror of
https://github.com/f-droid/fdroidclient.git
synced 2026-04-20 06:47:06 -04:00
[db] explicitly clear repo data before updating with full index
In JSON, keys can come in any order, so we need to handle the case that we receive packages before the repo metadata. Now we explicitly clear data and rename the insert method to insertOrReplace in order to make it clear that data gets replaced. Also, we pass the repoId into the constructor of the DB stream receivers to make clear that one receiver is meant to receive a single pre-existing repo.
This commit is contained in:
@@ -28,7 +28,7 @@ internal class AppTest : DbTest() {
|
||||
|
||||
@Test
|
||||
fun insertGetDeleteSingleApp() {
|
||||
val repoId = repoDao.insert(getRandomRepo())
|
||||
val repoId = repoDao.insertOrReplace(getRandomRepo())
|
||||
val metadataV2 = getRandomMetadataV2()
|
||||
appDao.insert(repoId, packageId, metadataV2)
|
||||
|
||||
@@ -53,7 +53,7 @@ internal class AppTest : DbTest() {
|
||||
|
||||
@Test
|
||||
fun testAppOverViewItem() {
|
||||
val repoId = repoDao.insert(getRandomRepo())
|
||||
val repoId = repoDao.insertOrReplace(getRandomRepo())
|
||||
val packageId1 = getRandomString()
|
||||
val packageId2 = getRandomString()
|
||||
val packageId3 = getRandomString()
|
||||
@@ -90,7 +90,7 @@ internal class AppTest : DbTest() {
|
||||
assertNull(apps3.find { it.packageId == packageId3 })
|
||||
|
||||
// app4 is the same as app1 and thus will not be shown again
|
||||
val repoId2 = repoDao.insert(getRandomRepo())
|
||||
val repoId2 = repoDao.insertOrReplace(getRandomRepo())
|
||||
val app4 = getRandomMetadataV2().copy(name = name2, icon = icons2)
|
||||
appDao.insert(repoId2, packageId1, app4)
|
||||
val apps4 = appDao.getAppOverviewItems().getOrAwaitValue() ?: fail()
|
||||
@@ -99,8 +99,8 @@ internal class AppTest : DbTest() {
|
||||
|
||||
@Test
|
||||
fun testAppByRepoWeight() {
|
||||
val repoId1 = repoDao.insert(getRandomRepo())
|
||||
val repoId2 = repoDao.insert(getRandomRepo())
|
||||
val repoId1 = repoDao.insertOrReplace(getRandomRepo())
|
||||
val repoId2 = repoDao.insertOrReplace(getRandomRepo())
|
||||
val metadata1 = getRandomMetadataV2()
|
||||
val metadata2 = metadata1.copy(lastUpdated = metadata1.lastUpdated + 1)
|
||||
|
||||
|
||||
@@ -6,8 +6,16 @@ import androidx.test.core.app.ApplicationProvider.getApplicationContext
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import kotlinx.serialization.SerializationException
|
||||
import org.apache.commons.io.input.CountingInputStream
|
||||
import org.fdroid.CompatibilityChecker
|
||||
import org.fdroid.index.v1.IndexV1StreamProcessor
|
||||
import org.fdroid.index.v2.IndexStreamProcessor
|
||||
import org.fdroid.index.v1.IndexV1StreamReceiver
|
||||
import org.fdroid.index.v2.AntiFeatureV2
|
||||
import org.fdroid.index.v2.CategoryV2
|
||||
import org.fdroid.index.v2.IndexV2StreamProcessor
|
||||
import org.fdroid.index.v2.MetadataV2
|
||||
import org.fdroid.index.v2.PackageVersionV2
|
||||
import org.fdroid.index.v2.ReleaseChannelV2
|
||||
import org.fdroid.index.v2.RepoV2
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import kotlin.math.roundToInt
|
||||
@@ -25,7 +33,8 @@ internal class IndexV1InsertTest : DbTest() {
|
||||
val fileSize = c.resources.assets.openFd("index-v1.json").use { it.length }
|
||||
val inputStream = CountingInputStream(c.resources.assets.open("index-v1.json"))
|
||||
var currentByteCount: Long = 0
|
||||
val indexProcessor = IndexV1StreamProcessor(DbV1StreamReceiver(db) { true }, null) {
|
||||
val repoId = db.getRepositoryDao().insertEmptyRepo("https://f-droid.org/repo")
|
||||
val streamReceiver = TestStreamReceiver(repoId) {
|
||||
val bytesRead = inputStream.byteCount
|
||||
val bytesSinceLastCall = bytesRead - currentByteCount
|
||||
if (bytesSinceLastCall > 0) {
|
||||
@@ -36,13 +45,12 @@ internal class IndexV1InsertTest : DbTest() {
|
||||
// the stream gets read in big chunks, but ensure they are not too big, e.g. entire file
|
||||
assertTrue(bytesSinceLastCall < 600_000, "$bytesSinceLastCall")
|
||||
currentByteCount = bytesRead
|
||||
bytesRead
|
||||
}
|
||||
val indexProcessor = IndexV1StreamProcessor(streamReceiver, null)
|
||||
|
||||
db.runInTransaction {
|
||||
val repoId = db.getRepositoryDao().insertEmptyRepo("https://f-droid.org/repo")
|
||||
inputStream.use { indexStream ->
|
||||
indexProcessor.process(repoId, indexStream)
|
||||
indexProcessor.process(indexStream)
|
||||
}
|
||||
}
|
||||
assertTrue(repoDao.getRepositories().size == 1)
|
||||
@@ -112,11 +120,11 @@ internal class IndexV1InsertTest : DbTest() {
|
||||
private fun insertV2ForComparison(version: Int) {
|
||||
val c = getApplicationContext<Context>()
|
||||
val inputStream = CountingInputStream(c.resources.assets.open("index-v2.json"))
|
||||
val indexProcessor = IndexStreamProcessor(DbStreamReceiver(db) { true }, null)
|
||||
val repoId = db.getRepositoryDao().insertEmptyRepo("https://f-droid.org/repo")
|
||||
val indexProcessor = IndexV2StreamProcessor(DbV2StreamReceiver(db, { true }, repoId), null)
|
||||
db.runInTransaction {
|
||||
val repoId = db.getRepositoryDao().insertEmptyRepo("https://f-droid.org/repo")
|
||||
inputStream.use { indexStream ->
|
||||
indexProcessor.process(repoId, version, indexStream)
|
||||
indexProcessor.process(version, indexStream)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -125,15 +133,17 @@ internal class IndexV1InsertTest : DbTest() {
|
||||
fun testExceptionWhileStreamingDoesNotSaveIntoDb() {
|
||||
val c = getApplicationContext<Context>()
|
||||
val cIn = CountingInputStream(c.resources.assets.open("index-v1.json"))
|
||||
val indexProcessor = IndexStreamProcessor(DbStreamReceiver(db) { true }, null) {
|
||||
val compatibilityChecker = CompatibilityChecker {
|
||||
if (cIn.byteCount > 824096) throw SerializationException()
|
||||
cIn.byteCount
|
||||
true
|
||||
}
|
||||
val indexProcessor =
|
||||
IndexV2StreamProcessor(DbV2StreamReceiver(db, compatibilityChecker, 1), null)
|
||||
|
||||
assertFailsWith<SerializationException> {
|
||||
db.runInTransaction {
|
||||
cIn.use { indexStream ->
|
||||
indexProcessor.process(1, 42, indexStream)
|
||||
indexProcessor.process(42, indexStream)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -145,4 +155,40 @@ internal class IndexV1InsertTest : DbTest() {
|
||||
assertTrue(versionDao.countVersionedStrings() == 0)
|
||||
}
|
||||
|
||||
inner class TestStreamReceiver(
|
||||
repoId: Long,
|
||||
private val callback: () -> Unit,
|
||||
) : IndexV1StreamReceiver {
|
||||
private val streamReceiver = DbV1StreamReceiver(db, { true }, repoId)
|
||||
override fun receive(repo: RepoV2, version: Int, certificate: String?) {
|
||||
streamReceiver.receive(repo, version, certificate)
|
||||
callback()
|
||||
}
|
||||
|
||||
override fun receive(packageId: String, m: MetadataV2) {
|
||||
streamReceiver.receive(packageId, m)
|
||||
callback()
|
||||
}
|
||||
|
||||
override fun receive(packageId: String, v: Map<String, PackageVersionV2>) {
|
||||
streamReceiver.receive(packageId, v)
|
||||
callback()
|
||||
}
|
||||
|
||||
override fun updateRepo(
|
||||
antiFeatures: Map<String, AntiFeatureV2>,
|
||||
categories: Map<String, CategoryV2>,
|
||||
releaseChannels: Map<String, ReleaseChannelV2>,
|
||||
) {
|
||||
streamReceiver.updateRepo(antiFeatures, categories, releaseChannels)
|
||||
callback()
|
||||
}
|
||||
|
||||
override fun updateAppMetadata(packageId: String, preferredSigner: String?) {
|
||||
streamReceiver.updateAppMetadata(packageId, preferredSigner)
|
||||
callback()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -6,7 +6,8 @@ import androidx.test.core.app.ApplicationProvider.getApplicationContext
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import kotlinx.serialization.SerializationException
|
||||
import org.apache.commons.io.input.CountingInputStream
|
||||
import org.fdroid.index.v2.IndexStreamProcessor
|
||||
import org.fdroid.CompatibilityChecker
|
||||
import org.fdroid.index.v2.IndexV2StreamProcessor
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import kotlin.math.roundToInt
|
||||
@@ -22,7 +23,7 @@ internal class IndexV2InsertTest : DbTest() {
|
||||
val fileSize = c.resources.assets.openFd("index-v2.json").use { it.length }
|
||||
val inputStream = CountingInputStream(c.resources.assets.open("index-v2.json"))
|
||||
var currentByteCount: Long = 0
|
||||
val indexProcessor = IndexStreamProcessor(DbStreamReceiver(db) { true }, null) {
|
||||
val compatibilityChecker = CompatibilityChecker {
|
||||
val bytesRead = inputStream.byteCount
|
||||
val bytesSinceLastCall = bytesRead - currentByteCount
|
||||
if (bytesSinceLastCall > 0) {
|
||||
@@ -33,13 +34,15 @@ internal class IndexV2InsertTest : DbTest() {
|
||||
// the stream gets read in big chunks, but ensure they are not too big, e.g. entire file
|
||||
assertTrue(bytesSinceLastCall < 400_000, "$bytesSinceLastCall")
|
||||
currentByteCount = bytesRead
|
||||
bytesRead
|
||||
true
|
||||
}
|
||||
val repoId = db.getRepositoryDao().insertEmptyRepo("https://f-droid.org/repo")
|
||||
val streamReceiver = DbV2StreamReceiver(db, compatibilityChecker, repoId)
|
||||
val indexProcessor = IndexV2StreamProcessor(streamReceiver, null)
|
||||
|
||||
db.runInTransaction {
|
||||
val repoId = db.getRepositoryDao().insertEmptyRepo("https://f-droid.org/repo")
|
||||
inputStream.use { indexStream ->
|
||||
indexProcessor.process(repoId, 42, indexStream)
|
||||
indexProcessor.process(42, indexStream)
|
||||
}
|
||||
}
|
||||
assertTrue(repoDao.getRepositories().size == 1)
|
||||
@@ -60,15 +63,17 @@ internal class IndexV2InsertTest : DbTest() {
|
||||
fun testExceptionWhileStreamingDoesNotSaveIntoDb() {
|
||||
val c = getApplicationContext<Context>()
|
||||
val cIn = CountingInputStream(c.resources.assets.open("index-v2.json"))
|
||||
val indexProcessor = IndexStreamProcessor(DbStreamReceiver(db) { true }, null) {
|
||||
val compatibilityChecker = CompatibilityChecker {
|
||||
if (cIn.byteCount > 824096) throw SerializationException()
|
||||
cIn.byteCount
|
||||
true
|
||||
}
|
||||
|
||||
assertFailsWith<SerializationException> {
|
||||
db.runInTransaction {
|
||||
val repoId = db.getRepositoryDao().insertEmptyRepo("http://example.org")
|
||||
val streamReceiver = DbV2StreamReceiver(db, compatibilityChecker, repoId)
|
||||
val indexProcessor = IndexV2StreamProcessor(streamReceiver, null)
|
||||
cIn.use { indexStream ->
|
||||
indexProcessor.process(1, 42, indexStream)
|
||||
indexProcessor.process(42, indexStream)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,10 +48,10 @@ internal class RepositoryDiffTest : DbTest() {
|
||||
fun timestampDiffTwoReposInDb() {
|
||||
// insert repo
|
||||
val repo = getRandomRepo()
|
||||
repoDao.insert(repo)
|
||||
repoDao.insertOrReplace(repo)
|
||||
|
||||
// insert another repo before updating
|
||||
repoDao.insert(getRandomRepo())
|
||||
repoDao.insertOrReplace(getRandomRepo())
|
||||
|
||||
// check that the repo got added and retrieved as expected
|
||||
var repos = repoDao.getRepositories().sortedBy { it.repoId }
|
||||
@@ -244,7 +244,7 @@ internal class RepositoryDiffTest : DbTest() {
|
||||
|
||||
private fun testDiff(repo: RepoV2, json: String, repoChecker: (List<Repository>) -> Unit) {
|
||||
// insert repo
|
||||
repoDao.insert(repo)
|
||||
repoDao.insertOrReplace(repo)
|
||||
|
||||
// check that the repo got added and retrieved as expected
|
||||
var repos = repoDao.getRepositories()
|
||||
|
||||
@@ -20,7 +20,7 @@ internal class RepositoryTest : DbTest() {
|
||||
fun insertAndDeleteTwoRepos() {
|
||||
// insert first repo
|
||||
val repo1 = getRandomRepo()
|
||||
val repoId1 = repoDao.insert(repo1)
|
||||
val repoId1 = repoDao.insertOrReplace(repo1)
|
||||
|
||||
// check that first repo got added and retrieved as expected
|
||||
var repos = repoDao.getRepositories()
|
||||
@@ -31,7 +31,7 @@ internal class RepositoryTest : DbTest() {
|
||||
|
||||
// insert second repo
|
||||
val repo2 = getRandomRepo()
|
||||
val repoId2 = repoDao.insert(repo2)
|
||||
val repoId2 = repoDao.insertOrReplace(repo2)
|
||||
|
||||
// check that both repos got added and retrieved as expected
|
||||
repos = repoDao.getRepositories().sortedBy { it.repoId }
|
||||
@@ -58,8 +58,8 @@ internal class RepositoryTest : DbTest() {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun replacingRepoRemovesAllAssociatedData() {
|
||||
val repoId = repoDao.insert(getRandomRepo())
|
||||
fun clearingRepoRemovesAllAssociatedData() {
|
||||
val repoId = repoDao.insertOrReplace(getRandomRepo())
|
||||
val repositoryPreferences = repoDao.getRepositoryPreferences(repoId)
|
||||
val packageId = getRandomString()
|
||||
val versionId = getRandomString()
|
||||
@@ -72,22 +72,20 @@ internal class RepositoryTest : DbTest() {
|
||||
assertEquals(1, versionDao.getAppVersions(repoId, packageId).size)
|
||||
assertTrue(versionDao.getVersionedStrings(repoId, packageId).isNotEmpty())
|
||||
|
||||
val cert = getRandomString()
|
||||
repoDao.replace(repoId, getRandomRepo(), 42, cert)
|
||||
repoDao.clear(repoId)
|
||||
assertEquals(1, repoDao.getRepositories().size)
|
||||
assertEquals(0, appDao.getAppMetadata().size)
|
||||
assertEquals(0, appDao.getLocalizedFiles().size)
|
||||
assertEquals(0, appDao.getLocalizedFileLists().size)
|
||||
assertEquals(0, versionDao.getAppVersions(repoId, packageId).size)
|
||||
assertEquals(0, versionDao.getVersionedStrings(repoId, packageId).size)
|
||||
|
||||
assertEquals(cert, repoDao.getRepository(repoId)?.certificate)
|
||||
// preferences are not touched by clearing
|
||||
assertEquals(repositoryPreferences, repoDao.getRepositoryPreferences(repoId))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun certGetsUpdates() {
|
||||
val repoId = repoDao.insert(getRandomRepo())
|
||||
fun certGetsUpdated() {
|
||||
val repoId = repoDao.insertOrReplace(getRandomRepo())
|
||||
assertEquals(1, repoDao.getRepositories().size)
|
||||
assertEquals(null, repoDao.getRepositories()[0].certificate)
|
||||
|
||||
|
||||
@@ -25,16 +25,16 @@ internal class UpdateCheckerTest : DbTest() {
|
||||
updateChecker = UpdateChecker(db, context.packageManager)
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalTime::class)
|
||||
@Test
|
||||
@OptIn(ExperimentalTime::class)
|
||||
fun testGetUpdates() {
|
||||
val inputStream = CountingInputStream(context.resources.assets.open("index-v1.json"))
|
||||
val indexProcessor = IndexV1StreamProcessor(DbV1StreamReceiver(db) { true }, null)
|
||||
val repoId = db.getRepositoryDao().insertEmptyRepo("https://f-droid.org/repo")
|
||||
val indexProcessor = IndexV1StreamProcessor(DbV1StreamReceiver(db, { true }, repoId), null)
|
||||
|
||||
db.runInTransaction {
|
||||
val repoId = db.getRepositoryDao().insertEmptyRepo("https://f-droid.org/repo")
|
||||
inputStream.use { indexStream ->
|
||||
indexProcessor.process(repoId, indexStream)
|
||||
indexProcessor.process(indexStream)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ internal class VersionTest : DbTest() {
|
||||
|
||||
@Test
|
||||
fun insertGetDeleteSingleVersion() {
|
||||
val repoId = repoDao.insert(getRandomRepo())
|
||||
val repoId = repoDao.insertOrReplace(getRandomRepo())
|
||||
appDao.insert(repoId, packageId, getRandomMetadataV2())
|
||||
val packageVersion = getRandomPackageVersionV2()
|
||||
val isCompatible = Random.nextBoolean()
|
||||
@@ -57,7 +57,7 @@ internal class VersionTest : DbTest() {
|
||||
@Test
|
||||
fun insertGetDeleteTwoVersions() {
|
||||
// insert two versions along with required objects
|
||||
val repoId = repoDao.insert(getRandomRepo())
|
||||
val repoId = repoDao.insertOrReplace(getRandomRepo())
|
||||
appDao.insert(repoId, packageId, getRandomMetadataV2())
|
||||
val packageVersion1 = getRandomPackageVersionV2()
|
||||
val packageVersion2 = getRandomPackageVersionV2()
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
package org.fdroid.database
|
||||
|
||||
import android.content.res.Resources
|
||||
import androidx.core.os.ConfigurationCompat.getLocales
|
||||
import androidx.core.os.LocaleListCompat
|
||||
import org.fdroid.CompatibilityChecker
|
||||
import org.fdroid.index.v2.IndexStreamReceiver
|
||||
import org.fdroid.index.v2.PackageV2
|
||||
import org.fdroid.index.v2.RepoV2
|
||||
|
||||
internal class DbStreamReceiver(
|
||||
private val db: FDroidDatabaseInt,
|
||||
private val compatibilityChecker: CompatibilityChecker,
|
||||
) : IndexStreamReceiver {
|
||||
|
||||
private val locales: LocaleListCompat = getLocales(Resources.getSystem().configuration)
|
||||
|
||||
override fun receive(repoId: Long, repo: RepoV2, version: Int, certificate: String?) {
|
||||
db.getRepositoryDao().replace(repoId, repo, version, certificate)
|
||||
}
|
||||
|
||||
override fun receive(repoId: Long, packageId: String, p: PackageV2) {
|
||||
db.getAppDao().insert(repoId, packageId, p.metadata, locales)
|
||||
db.getVersionDao().insert(repoId, packageId, p.versions) {
|
||||
compatibilityChecker.isCompatible(it.manifest)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onStreamEnded(repoId: Long) {
|
||||
db.afterUpdatingRepo(repoId)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -12,29 +12,35 @@ import org.fdroid.index.v2.PackageVersionV2
|
||||
import org.fdroid.index.v2.ReleaseChannelV2
|
||||
import org.fdroid.index.v2.RepoV2
|
||||
|
||||
/**
|
||||
* Note that this class expects that its [receive] method with [RepoV2] gets called first.
|
||||
* A different order of calls is not supported.
|
||||
*/
|
||||
@Deprecated("Use DbV2StreamReceiver instead")
|
||||
internal class DbV1StreamReceiver(
|
||||
private val db: FDroidDatabaseInt,
|
||||
private val compatibilityChecker: CompatibilityChecker,
|
||||
private val repoId: Long,
|
||||
) : IndexV1StreamReceiver {
|
||||
|
||||
private val locales: LocaleListCompat = getLocales(Resources.getSystem().configuration)
|
||||
|
||||
override fun receive(repoId: Long, repo: RepoV2, version: Int, certificate: String?) {
|
||||
db.getRepositoryDao().replace(repoId, repo, version, certificate)
|
||||
override fun receive(repo: RepoV2, version: Int, certificate: String?) {
|
||||
db.getRepositoryDao().clear(repoId)
|
||||
db.getRepositoryDao().update(repoId, repo, version, certificate)
|
||||
}
|
||||
|
||||
override fun receive(repoId: Long, packageId: String, m: MetadataV2) {
|
||||
override fun receive(packageId: String, m: MetadataV2) {
|
||||
db.getAppDao().insert(repoId, packageId, m, locales)
|
||||
}
|
||||
|
||||
override fun receive(repoId: Long, packageId: String, v: Map<String, PackageVersionV2>) {
|
||||
override fun receive(packageId: String, v: Map<String, PackageVersionV2>) {
|
||||
db.getVersionDao().insert(repoId, packageId, v) {
|
||||
compatibilityChecker.isCompatible(it.manifest)
|
||||
}
|
||||
}
|
||||
|
||||
override fun updateRepo(
|
||||
repoId: Long,
|
||||
antiFeatures: Map<String, AntiFeatureV2>,
|
||||
categories: Map<String, CategoryV2>,
|
||||
releaseChannels: Map<String, ReleaseChannelV2>,
|
||||
@@ -47,7 +53,7 @@ internal class DbV1StreamReceiver(
|
||||
db.afterUpdatingRepo(repoId)
|
||||
}
|
||||
|
||||
override fun updateAppMetadata(repoId: Long, packageId: String, preferredSigner: String?) {
|
||||
override fun updateAppMetadata(packageId: String, preferredSigner: String?) {
|
||||
db.getAppDao().updatePreferredSigner(repoId, packageId, preferredSigner)
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
package org.fdroid.database
|
||||
|
||||
import android.content.res.Resources
|
||||
import androidx.core.os.ConfigurationCompat.getLocales
|
||||
import androidx.core.os.LocaleListCompat
|
||||
import org.fdroid.CompatibilityChecker
|
||||
import org.fdroid.index.v2.IndexV2StreamReceiver
|
||||
import org.fdroid.index.v2.PackageV2
|
||||
import org.fdroid.index.v2.RepoV2
|
||||
|
||||
internal class DbV2StreamReceiver(
|
||||
private val db: FDroidDatabaseInt,
|
||||
private val compatibilityChecker: CompatibilityChecker,
|
||||
private val repoId: Long,
|
||||
) : IndexV2StreamReceiver {
|
||||
|
||||
private val locales: LocaleListCompat = getLocales(Resources.getSystem().configuration)
|
||||
private var clearedRepoData = false
|
||||
|
||||
@Synchronized
|
||||
override fun receive(repo: RepoV2, version: Int, certificate: String?) {
|
||||
clearRepoDataIfNeeded()
|
||||
db.getRepositoryDao().update(repoId, repo, version, certificate)
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
override fun receive(packageId: String, p: PackageV2) {
|
||||
clearRepoDataIfNeeded()
|
||||
db.getAppDao().insert(repoId, packageId, p.metadata, locales)
|
||||
db.getVersionDao().insert(repoId, packageId, p.versions) {
|
||||
compatibilityChecker.isCompatible(it.manifest)
|
||||
}
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
override fun onStreamEnded() {
|
||||
db.afterUpdatingRepo(repoId)
|
||||
}
|
||||
|
||||
/**
|
||||
* As it is a valid index to receive packages before the repo,
|
||||
* we can not clear all repo data when receiving the repo,
|
||||
* but need to do it once at the beginning.
|
||||
*/
|
||||
private fun clearRepoDataIfNeeded() {
|
||||
if (!clearedRepoData) {
|
||||
db.getRepositoryDao().clear(repoId)
|
||||
clearedRepoData = true
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -25,8 +25,15 @@ public interface RepositoryDao {
|
||||
/**
|
||||
* Use when replacing an existing repo with a full index.
|
||||
* This removes all existing index data associated with this repo from the database.
|
||||
* @throws IllegalStateException if no repo with the given [repoId] exists.
|
||||
*/
|
||||
public fun replace(repoId: Long, repository: RepoV2, version: Int, certificate: String?)
|
||||
public fun clear(repoId: Long)
|
||||
|
||||
/**
|
||||
* Updates an existing repo with new data from a full index update.
|
||||
* Call [clear] first to ensure old data was removed.
|
||||
*/
|
||||
public fun update(repoId: Long, repository: RepoV2, version: Int, certificate: String?)
|
||||
|
||||
public fun getRepository(repoId: Long): Repository?
|
||||
public fun insertEmptyRepo(
|
||||
@@ -50,7 +57,10 @@ public interface RepositoryDao {
|
||||
internal interface RepositoryDaoInt : RepositoryDao {
|
||||
|
||||
@Insert(onConflict = REPLACE)
|
||||
fun insert(repository: CoreRepository): Long
|
||||
fun insertOrReplace(repository: CoreRepository): Long
|
||||
|
||||
@Update
|
||||
fun update(repository: CoreRepository)
|
||||
|
||||
@Insert(onConflict = REPLACE)
|
||||
fun insertMirrors(mirrors: List<Mirror>)
|
||||
@@ -78,7 +88,7 @@ internal interface RepositoryDaoInt : RepositoryDao {
|
||||
description = mapOf("en-US" to initialRepo.description),
|
||||
certificate = initialRepo.certificate,
|
||||
)
|
||||
val repoId = insert(repo)
|
||||
val repoId = insertOrReplace(repo)
|
||||
val repositoryPreferences = RepositoryPreferences(
|
||||
repoId = repoId,
|
||||
weight = initialRepo.weight,
|
||||
@@ -102,7 +112,7 @@ internal interface RepositoryDaoInt : RepositoryDao {
|
||||
version = null,
|
||||
certificate = null,
|
||||
)
|
||||
val repoId = insert(repo)
|
||||
val repoId = insertOrReplace(repo)
|
||||
val currentMaxWeight = getMaxRepositoryWeight()
|
||||
val repositoryPreferences = RepositoryPreferences(
|
||||
repoId = repoId,
|
||||
@@ -117,8 +127,8 @@ internal interface RepositoryDaoInt : RepositoryDao {
|
||||
|
||||
@Transaction
|
||||
@VisibleForTesting
|
||||
fun insert(repository: RepoV2): Long {
|
||||
val repoId = insert(repository.toCoreRepository(version = 0))
|
||||
fun insertOrReplace(repository: RepoV2): Long {
|
||||
val repoId = insertOrReplace(repository.toCoreRepository(version = 0))
|
||||
insertRepositoryPreferences(repoId)
|
||||
insertRepoTables(repoId, repository)
|
||||
return repoId
|
||||
@@ -131,9 +141,15 @@ internal interface RepositoryDaoInt : RepositoryDao {
|
||||
}
|
||||
|
||||
@Transaction
|
||||
override fun replace(repoId: Long, repository: RepoV2, version: Int, certificate: String?) {
|
||||
val newRepoId = insert(repository.toCoreRepository(repoId, version, certificate))
|
||||
require(newRepoId == repoId) { "New repoId $newRepoId did not match old $repoId" }
|
||||
override fun clear(repoId: Long) {
|
||||
val repo = getRepository(repoId) ?: error("repo with id $repoId does not exist")
|
||||
// this clears all foreign key associated data since the repo gets replaced
|
||||
insertOrReplace(repo.repository)
|
||||
}
|
||||
|
||||
@Transaction
|
||||
override fun update(repoId: Long, repository: RepoV2, version: Int, certificate: String?) {
|
||||
update(repository.toCoreRepository(repoId, version, certificate))
|
||||
insertRepoTables(repoId, repository)
|
||||
}
|
||||
|
||||
|
||||
@@ -65,9 +65,9 @@ public class IndexV1Updater(
|
||||
db.runInTransaction {
|
||||
val cert = verifier.getStreamAndVerify { inputStream ->
|
||||
updateListener?.onStartProcessing() // TODO maybe do more fine-grained reporting
|
||||
val streamReceiver = DbV1StreamReceiver(db, compatibilityChecker)
|
||||
val streamReceiver = DbV1StreamReceiver(db, compatibilityChecker, repoId)
|
||||
val streamProcessor = IndexV1StreamProcessor(streamReceiver, certificate)
|
||||
streamProcessor.process(repoId, inputStream)
|
||||
streamProcessor.process(inputStream)
|
||||
}
|
||||
// update certificate, if we didn't have any before
|
||||
if (certificate == null) {
|
||||
|
||||
Reference in New Issue
Block a user