mirror of
https://github.com/Droid-Deck/DroidDeck.git
synced 2026-11-12 19:41:10 +00:00
fix: local builds bundle the addon packs they pin (#1908)
This commit is contained in:
1 parent
8a7022fc14
commit
2ff3ab447d
3 files changed
+57
-1
No files matched your search
@@ -300,6 +300,16 @@ def stageGogNotices = tasks.register('stageGogNotices', Copy) {
|
||||
android.sourceSets.main.assets.srcDir(layout.buildDirectory.dir('gogNotices'))
|
||||
tasks.named('preBuild').configure { dependsOn(stageGogNotices) }
|
||||
|
||||
// CI publishes its packs; a local build pins packs nobody hosts (see addonPacks), so the APK carries them.
|
||||
if (!ciBuild) {
|
||||
def stageLocalPacks = tasks.register('stageLocalPacks', Sync) {
|
||||
from(layout.buildDirectory.dir('packs')) { include '*.tar.zst' }
|
||||
into(layout.buildDirectory.dir('localPackAssets/packs'))
|
||||
}
|
||||
android.sourceSets.main.assets.srcDir(layout.buildDirectory.dir('localPackAssets'))
|
||||
tasks.named('preBuild').configure { dependsOn(stageLocalPacks) }
|
||||
}
|
||||
|
||||
def verifyRuntimeInputs = tasks.register('verifyRuntimeInputs', Exec) {
|
||||
mustRunAfter(stageSessionScripts, stageRuntimeAssets)
|
||||
workingDir rootProject.projectDir
|
||||
|
||||
@@ -22,6 +22,7 @@ import java.io.FileInputStream
|
||||
internal class AddonPack(
|
||||
val name: String, private val sha256: String, val size: Long, private val required: List<String>,
|
||||
private val reuseDeviceCopy: Boolean = sha256.isEmpty() && !BuildConfig.CI_BUILD,
|
||||
private val bundle: (Context) -> java.io.InputStream = { it.assets.open("packs/$name.tar.zst") },
|
||||
) {
|
||||
sealed interface State {
|
||||
data object Missing : State
|
||||
@@ -104,7 +105,7 @@ internal class AddonPack(
|
||||
}
|
||||
val root = root(context).apply { mkdirs() }
|
||||
val archive = File(root, "$sha256.tar.zst")
|
||||
val downloaded = urls.any { url ->
|
||||
val downloaded = bundled(context, archive) || urls.any { url ->
|
||||
Downloader.downloadFile(url, archive, true, sha256) { p -> mutableState.value = State.Downloading(p.coerceIn(0f, 1f)) }
|
||||
.also { if (!it) archive.delete() }
|
||||
}
|
||||
@@ -126,6 +127,17 @@ internal class AddonPack(
|
||||
return true
|
||||
}
|
||||
|
||||
// A local build pins the packs it compiled, which no release hosts, so it ships them as assets.
|
||||
internal fun bundled(context: Context, archive: File): Boolean {
|
||||
val copied = runCatching {
|
||||
bundle(context).use { input -> archive.outputStream().use { input.copyTo(it) } }
|
||||
}.isSuccess
|
||||
if (copied && Hashes.sha256(archive).equals(sha256, ignoreCase = true)) return true
|
||||
if (copied) Log.w(TAG, "$name: the bundled pack does not match the pinned digest")
|
||||
archive.delete()
|
||||
return false
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val TAG = "AddonPack"
|
||||
private const val REPO = "Droid-Deck/DroidDeck-Components"
|
||||
|
||||
@@ -2,6 +2,9 @@ package com.droiddeck.launcher.core
|
||||
|
||||
import android.content.Context
|
||||
import androidx.test.core.app.ApplicationProvider
|
||||
import com.github.luben.zstd.ZstdOutputStream
|
||||
import org.apache.commons.compress.archivers.tar.TarArchiveEntry
|
||||
import org.apache.commons.compress.archivers.tar.TarArchiveOutputStream
|
||||
import java.io.File
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Assert.assertFalse
|
||||
@@ -54,4 +57,35 @@ class AddonPackTest {
|
||||
installed("b".repeat(64))
|
||||
assertFalse(AddonPack("sample", "", 0L, listOf("tool"), reuseDeviceCopy = false).installed(context))
|
||||
}
|
||||
|
||||
@Test fun localBuildInstallsTheBundledPackWithoutDownloading() {
|
||||
val archive = tarZst("tool" to "x")
|
||||
val pack = AddonPack("sample", Hashes.sha256(archive), archive.length(), listOf("tool"), bundle = { archive.inputStream() })
|
||||
|
||||
assertTrue(pack.await(context))
|
||||
assertEquals("x", pack.file(context, "tool").readText())
|
||||
}
|
||||
|
||||
@Test fun bundledPackWithTheWrongDigestIsRejected() {
|
||||
val archive = tarZst("tool" to "x")
|
||||
val pack = AddonPack("sample", "a".repeat(64), archive.length(), listOf("tool"),
|
||||
bundle = { archive.inputStream() })
|
||||
|
||||
val copy = File(context.cacheDir, "copy.tar.zst")
|
||||
|
||||
assertFalse(pack.bundled(context, copy))
|
||||
assertFalse(copy.exists())
|
||||
}
|
||||
|
||||
private fun tarZst(vararg files: Pair<String, String>): File =
|
||||
File(context.cacheDir, "sample-${System.nanoTime()}.tar.zst").apply {
|
||||
TarArchiveOutputStream(ZstdOutputStream(outputStream())).use { tar ->
|
||||
for ((path, text) in files) {
|
||||
val bytes = text.toByteArray()
|
||||
tar.putArchiveEntry(TarArchiveEntry(path).apply { size = bytes.size.toLong() })
|
||||
tar.write(bytes)
|
||||
tar.closeArchiveEntry()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user