fix: download termux-packages during build instead of storing them in assets (#545)

This commit is contained in:
Akash Yadav
2024-01-01 22:15:41 +05:30
parent 062d240e95
commit 415a0f2a7d
8 changed files with 202 additions and 4 deletions
@@ -0,0 +1,78 @@
/*
* This file is part of AndroidIDE.
*
* AndroidIDE is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* AndroidIDE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with AndroidIDE. If not, see <https://www.gnu.org/licenses/>.
*/
package com.itsaky.androidide.plugins
import com.android.build.api.variant.ApplicationAndroidComponentsExtension
import com.itsaky.androidide.plugins.tasks.TerminalBootstrapDownloadTask
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.tasks.Delete
import org.gradle.api.tasks.compile.JavaCompile
/**
* Gradle plugin which downloads the bootstrap packages for the terminal.
*
* @author Akash Yadav
*/
class TerminalBootstrapPackagesPlugin : Plugin<Project> {
companion object {
/**
* The bootstrap packages, mapped with the CPU ABI as the key and the ZIP file's sha256sum as the value.
*/
private val BOOTSTRAP_PACKAGES = mapOf(
"aarch64" to "68da03ed270d59cafcd37981b00583c713b42cb440adf03d1bf980f39a55181d",
"arm" to "f3d9f2da7338bd00b02a8df192bdc22ad431a5eef413cecf4cd78d7a54ffffbf",
"x86_64" to "6e4e50a206c3384c36f141b2496c1a7c69d30429e4e20268c51a84143530af67"
)
/**
* The bootstrap packages version, basically the tag name of the GitHub release.
*/
private const val BOOTSTRAP_PACKAGES_VERSION = "16.12.2023"
}
override fun apply(target: Project) {
target.run {
val downloadTask = tasks.register("downloadBootstrapPackages",
TerminalBootstrapDownloadTask::class.java) {
packages.set(BOOTSTRAP_PACKAGES)
version.set(BOOTSTRAP_PACKAGES_VERSION)
}
val cleanTask = tasks.register("deleteBootstrapPackages", Delete::class.java) {
doLast {
fileTree("src/main/cpp").apply {
include("bootstrap-*.zip")
}.forEach { file ->
file.delete()
}
}
}
tasks.withType(JavaCompile::class.java).configureEach {
dependsOn(downloadTask)
}
tasks.named("clean").configure {
dependsOn(cleanTask)
}
}
}
}
@@ -0,0 +1,115 @@
/*
* This file is part of AndroidIDE.
*
* AndroidIDE is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* AndroidIDE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with AndroidIDE. If not, see <https://www.gnu.org/licenses/>.
*/
package com.itsaky.androidide.plugins.tasks
import org.gradle.api.DefaultTask
import org.gradle.api.GradleException
import org.gradle.api.provider.MapProperty
import org.gradle.api.provider.Property
import org.gradle.api.tasks.Input
import org.gradle.api.tasks.TaskAction
import java.math.BigInteger
import java.net.HttpURLConnection
import java.net.URL
import java.security.DigestInputStream
import java.security.MessageDigest
/**
* @author Akash Yadav
*/
abstract class TerminalBootstrapDownloadTask : DefaultTask() {
companion object {
private const val PACKAGES_DOWNLOAD_URL = "https://github.com/AndroidIDEOfficial/terminal-packages/releases/download/bootstrap-%1\$s/bootstrap-%2\$s.zip"
}
/**
* The bootstrap packages to download. The keys in this map are supported the CPU ABIs and
* the values are the `sha256sum` of the bootstrap packages.
*/
@get:Input
abstract val packages: MapProperty<String, String>
/**
* Version of the bootstrap packages. This is basically the tag name of the GitHub release.
*/
@get:Input
abstract val version: Property<String>
@TaskAction
fun downloadBootstrap() {
val packages = this.packages.get()
val version = this.version.get()
if (packages.isEmpty() || version.isNullOrBlank()) {
throw GradleException("Packages map is empty!")
}
packages.forEach { (arch, sha256) ->
doDownload(arch, sha256, version)
}
}
private fun doDownload(arch: String, expectedChecksum: String, version: String) {
val digest = MessageDigest.getInstance("SHA-256")
val localPath = "src/main/cpp/bootstrap-${arch}.zip"
val file = project.file(localPath)
if (file.exists()) {
digest.update(file.readBytes())
var checksum = BigInteger(1, digest.digest()).toString(16)
while (checksum.length < 64) {
checksum = "0$checksum"
}
if (checksum == expectedChecksum) {
logger.info("$localPath is already downloaded and valid. Skipping download.")
return
} else {
logger.info(
"Deleting old bootstrap package with invalid checksum: $checksum expected: $expectedChecksum file: $localPath")
file.delete()
}
}
val remoteUrl = PACKAGES_DOWNLOAD_URL.format(version, arch)
logger.info("Downloading ${remoteUrl}...")
file.parentFile.mkdirs()
val connection = URL(remoteUrl).openConnection() as HttpURLConnection
connection.instanceFollowRedirects = true
file.outputStream().use { out ->
DigestInputStream(connection.inputStream, digest).transferTo(out.buffered())
}
connection.inputStream.buffered().transferTo(file.outputStream())
var checksum = BigInteger(1, digest.digest()).toString(16)
while (checksum.length < 64) {
checksum = "0$checksum"
}
if (checksum != expectedChecksum) {
file.delete()
throw GradleException(
"Wrong checksum for $remoteUrl: expected: $expectedChecksum, actual: $checksum")
}
}
}
@@ -17,12 +17,9 @@
package com.itsaky.androidide.app;
import android.app.Application;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.content.ActivityNotFoundException;
import android.content.Intent;
import android.net.Uri;
import androidx.core.app.NotificationManagerCompat;
import com.blankj.utilcode.util.ThrowableUtils;
import com.itsaky.androidide.buildinfo.BuildInfo;
import com.itsaky.androidide.common.R;
@@ -42,7 +39,8 @@ public class BaseApplication extends Application {
public static final String TELEGRAM_CHANNEL_URL = "https://t.me/AndroidIDEOfficial";
public static final String SPONSOR_URL = BuildInfo.PROJECT_SITE + "/donate";
public static final String DOCS_URL = "https://docs.androidide.com";
public static final String CONTRIBUTOR_GUIDE_URL = BuildInfo.REPO_URL + "/blob/dev/CONTRIBUTING.md";
public static final String CONTRIBUTOR_GUIDE_URL =
BuildInfo.REPO_URL + "/blob/dev/CONTRIBUTING.md";
public static final String EMAIL = "contact@androidide.com";
private static BaseApplication instance;
private PreferenceManager mPrefsManager;
+6
View File
@@ -1,10 +1,16 @@
@file:Suppress("UnstableApiUsage")
import com.itsaky.androidide.plugins.TerminalBootstrapPackagesPlugin
plugins {
id("com.android.library")
id("kotlin-android")
}
apply {
plugin(TerminalBootstrapPackagesPlugin::class.java)
}
val packageVariant = System.getenv("TERMUX_PACKAGE_VARIANT") ?: "apt-android-7" // Default: "apt-android-7"
android {
@@ -0,0 +1 @@
bootstrap-*
Binary file not shown.
Binary file not shown.
Binary file not shown.