From 62bfd6a4f7d02bf665a89a8d49f0f682198d02df Mon Sep 17 00:00:00 2001 From: Luna712 <142361265+Luna712@users.noreply.github.com> Date: Mon, 1 Dec 2025 18:57:51 -0700 Subject: [PATCH 1/5] Add true configuration cache support for git commit hash --- app/build.gradle.kts | 65 ++++++++++++------- .../ui/settings/SettingsFragment.kt | 6 +- .../lagradost/cloudstream3/utils/GitInfo.kt | 20 ++++++ .../cloudstream3/utils/InAppUpdater.kt | 10 +-- app/src/main/res/layout/main_settings.xml | 7 +- 5 files changed, 72 insertions(+), 36 deletions(-) create mode 100644 app/src/main/java/com/lagradost/cloudstream3/utils/GitInfo.kt diff --git a/app/build.gradle.kts b/app/build.gradle.kts index e2bdb20792e..2cc8bb53268 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -1,4 +1,5 @@ import com.android.build.gradle.internal.cxx.configure.gradleLocalProperties +import com.android.build.gradle.tasks.MergeSourceSetFolders import org.jetbrains.dokka.gradle.engine.parameters.KotlinPlatform import org.jetbrains.dokka.gradle.engine.parameters.VisibilityModifier import org.jetbrains.kotlin.gradle.dsl.JvmDefaultMode @@ -15,23 +16,44 @@ val javaTarget = JvmTarget.fromTarget(libs.versions.jvmTarget.get()) val tmpFilePath = System.getProperty("user.home") + "/work/_temp/keystore/" val prereleaseStoreFile: File? = File(tmpFilePath).listFiles()?.first() -fun getGitCommitHash(): String { - return try { - val headFile = file("${project.rootDir}/.git/HEAD") - - // Read the commit hash from .git/HEAD - if (headFile.exists()) { - val headContent = headFile.readText().trim() - if (headContent.startsWith("ref:")) { - val refPath = headContent.substring(5) // e.g., refs/heads/main - val commitFile = file("${project.rootDir}/.git/$refPath") - if (commitFile.exists()) commitFile.readText().trim() else "" - } else headContent // If it's a detached HEAD (commit hash directly) - } else { - "" // If .git/HEAD doesn't exist - }.take(7) // Return the short commit hash - } catch (_: Throwable) { - "" // Just return an empty string if any exception occurs +tasks.register("generateGitHash") { + val gitHashDir = layout.buildDirectory.dir("generated/git") + val rootDir = project.rootDir + outputs.dir(gitHashDir) + + doLast { + val hash = try { + // Read the commit hash from .git/HEAD + val headFile = File(rootDir, ".git/HEAD") + if (headFile.exists()) { + val headContent = headFile.readText().trim() + if (headContent.startsWith("ref:")) { + val refPath = headContent.substring(5) // e.g., refs/heads/main + val commitFile = File(rootDir, ".git/$refPath") + if (commitFile.exists()) commitFile.readText().trim() else "" + } else headContent // If it's a detached HEAD (commit hash directly) + } else "" // If .git/HEAD doesn't exist + } catch (_: Throwable) { + "" // Just set to an empty string if any exception occurs + }.take(7) // Get the short commit hash + + val outFile = gitHashDir.get().file("git-hash.txt").asFile + outFile.parentFile.mkdirs() + outFile.writeText(hash) + } +} + +tasks.withType { + if (name.contains("Assets", ignoreCase = true)) { + dependsOn("generateGitHash") + val gitHashDir = layout.buildDirectory.dir("generated/git") + + doLast { + val assetsDir = outputs.files.singleFile + val gitHashFile = gitHashDir.get().file("git-hash.txt").asFile + val outFile = File(assetsDir, "git-hash.txt") + gitHashFile.copyTo(outFile, overwrite = true) + } } } @@ -66,7 +88,6 @@ android { versionName = "4.6.1" resValue("string", "app_version", "${defaultConfig.versionName}${versionNameSuffix ?: ""}") - resValue("string", "commit_hash", getGitCommitHash()) resValue("bool", "is_prerelease", "false") manifestPlaceholders["target_sdk_version"] = libs.versions.targetSdk.get() @@ -140,11 +161,11 @@ android { } java { - // Use Java 17 toolchain even if a higher JDK runs the build. + // Use Java 17 toolchain even if a higher JDK runs the build. // We still use Java 8 for now which higher JDKs have deprecated. - toolchain { - languageVersion.set(JavaLanguageVersion.of(libs.versions.jdkToolchain.get())) - } + toolchain { + languageVersion.set(JavaLanguageVersion.of(libs.versions.jdkToolchain.get())) + } } lint { diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/settings/SettingsFragment.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/settings/SettingsFragment.kt index c2d5e43e954..32e77c3a3ce 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/settings/SettingsFragment.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/settings/SettingsFragment.kt @@ -27,6 +27,7 @@ import com.lagradost.cloudstream3.ui.settings.Globals.TV import com.lagradost.cloudstream3.ui.settings.Globals.isLandscape import com.lagradost.cloudstream3.ui.settings.Globals.isLayout import com.lagradost.cloudstream3.utils.DataStoreHelper +import com.lagradost.cloudstream3.utils.GitInfo.currentCommitHash import com.lagradost.cloudstream3.utils.ImageLoader.loadImage import com.lagradost.cloudstream3.utils.UIHelper.clipboardHelper import com.lagradost.cloudstream3.utils.UIHelper.fixSystemBarsPadding @@ -247,15 +248,16 @@ class SettingsFragment : BaseFragment( } val appVersion = getString(R.string.app_version) - val commitInfo = getString(R.string.commit_hash) + val commitHash = activity?.currentCommitHash() ?: "" val buildTimestamp = SimpleDateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG, Locale.getDefault() ).apply { timeZone = TimeZone.getTimeZone("UTC") }.format(Date(BuildConfig.BUILD_DATE)).replace("UTC", "") binding.buildDate.text = buildTimestamp + binding.commitHash.text = commitHash binding.appVersionInfo.setOnLongClickListener { - clipboardHelper(txt(R.string.extension_version), "$appVersion $commitInfo $buildTimestamp") + clipboardHelper(txt(R.string.extension_version), "$appVersion $commitHash $buildTimestamp") true } } diff --git a/app/src/main/java/com/lagradost/cloudstream3/utils/GitInfo.kt b/app/src/main/java/com/lagradost/cloudstream3/utils/GitInfo.kt new file mode 100644 index 00000000000..58ff44bb257 --- /dev/null +++ b/app/src/main/java/com/lagradost/cloudstream3/utils/GitInfo.kt @@ -0,0 +1,20 @@ +package com.lagradost.cloudstream3.utils + +import android.content.Context + +/** + * Simple helper to get the short commit hash from assets. + * The hash is generated at build and stored as an asset + * that can be accessed at runtime for Gradle + * configuration cache support. + */ +object GitInfo { + fun Context.currentCommitHash(): String = try { + assets.open("git-hash.txt") + .bufferedReader() + .readText() + .trim() + } catch (_: Exception) { + "" + } +} diff --git a/app/src/main/java/com/lagradost/cloudstream3/utils/InAppUpdater.kt b/app/src/main/java/com/lagradost/cloudstream3/utils/InAppUpdater.kt index 12befafe02e..2b1d29adca4 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/utils/InAppUpdater.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/utils/InAppUpdater.kt @@ -16,6 +16,7 @@ import com.lagradost.cloudstream3.CommonActivity.showToast import com.lagradost.cloudstream3.mvvm.logError import com.lagradost.cloudstream3.utils.AppUtils.parseJson import com.lagradost.cloudstream3.utils.Coroutines.ioSafe +import com.lagradost.cloudstream3.utils.GitInfo.currentCommitHash import kotlinx.coroutines.sync.Mutex import kotlinx.coroutines.sync.withLock import okio.BufferedSink @@ -180,14 +181,7 @@ class InAppUpdater { Log.d(LOG_TAG, "Fetched GitHub tag: ${tagResponse.githubObject.sha.take(7)}") - val shouldUpdate = - (getString(R.string.commit_hash) - .trim { c -> c.isWhitespace() } - .take(7) - != - tagResponse.githubObject.sha - .trim { c -> c.isWhitespace() } - .take(7)) + val shouldUpdate = currentCommitHash() != tagResponse.githubObject.sha.trim().take(7) return if (foundAsset != null) { Update( diff --git a/app/src/main/res/layout/main_settings.xml b/app/src/main/res/layout/main_settings.xml index 0b931843dd1..3442fce8e41 100644 --- a/app/src/main/res/layout/main_settings.xml +++ b/app/src/main/res/layout/main_settings.xml @@ -134,8 +134,8 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:padding="10dp" - android:text="@string/commit_hash" - android:textColor="?attr/textColor" /> + android:textColor="?attr/textColor" + tools:text="1234567" /> + tools:text="21/03/2024 09:02 pm" /> - \ No newline at end of file From ebca8df28f77ad1ac90a59b88a9cf3a211b25b7c Mon Sep 17 00:00:00 2001 From: Luna712 <142361265+Luna712@users.noreply.github.com> Date: Sat, 28 Mar 2026 13:26:01 -0600 Subject: [PATCH 2/5] Apply suggestions from code review Co-authored-by: firelight <147925818+fire-light42@users.noreply.github.com> --- app/build.gradle.kts | 60 ++++++++++++++++++++++++++------------------ 1 file changed, 36 insertions(+), 24 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 8ae06e36428..521cde7635c 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -16,45 +16,50 @@ val javaTarget = JvmTarget.fromTarget(libs.versions.jvmTarget.get()) val tmpFilePath = System.getProperty("user.home") + "/work/_temp/keystore/" val prereleaseStoreFile: File? = File(tmpFilePath).listFiles()?.first() -tasks.register("generateGitHash") { - val gitHashDir = layout.buildDirectory.dir("generated/git") - val rootDir = project.rootDir - outputs.dir(gitHashDir) +abstract class GenerateGitHashTask : DefaultTask() { + + @get:InputFile + @get:PathSensitive(PathSensitivity.RELATIVE) + abstract val headFile: RegularFileProperty + + @get:InputDirectory + @get:PathSensitive(PathSensitivity.RELATIVE) + abstract val headsDir: DirectoryProperty + + @get:OutputDirectory + abstract val outputDir: DirectoryProperty + + @TaskAction + fun generate() { + val head = headFile.get().asFile - doLast { val hash = try { - // Read the commit hash from .git/HEAD - val headFile = File(rootDir, ".git/HEAD") - if (headFile.exists()) { - val headContent = headFile.readText().trim() + if (head.exists()) { + // Read the commit hash from .git/HEAD + val headContent = head.readText().trim() if (headContent.startsWith("ref:")) { val refPath = headContent.substring(5) // e.g., refs/heads/main - val commitFile = File(rootDir, ".git/$refPath") + val commitFile = File(head.parentFile, refPath) if (commitFile.exists()) commitFile.readText().trim() else "" } else headContent // If it's a detached HEAD (commit hash directly) - } else "" // If .git/HEAD doesn't exist + } else "" // If .git/HEAD doesn't exist } catch (_: Throwable) { "" // Just set to an empty string if any exception occurs }.take(7) // Get the short commit hash - val outFile = gitHashDir.get().file("git-hash.txt").asFile + val outFile = outputDir.file("git-hash.txt").get().asFile outFile.parentFile.mkdirs() outFile.writeText(hash) } } -tasks.withType { - if (name.contains("Assets", ignoreCase = true)) { - dependsOn("generateGitHash") - val gitHashDir = layout.buildDirectory.dir("generated/git") +val generateGitHash = tasks.register("generateGitHash") { + val gitDir = layout.projectDirectory.dir("../.git") - doLast { - val assetsDir = outputs.files.singleFile - val gitHashFile = gitHashDir.get().file("git-hash.txt").asFile - val outFile = File(assetsDir, "git-hash.txt") - gitHashFile.copyTo(outFile, overwrite = true) - } - } + headFile.set(gitDir.file("HEAD")) + headsDir.set(gitDir.dir("refs/heads")) + + outputDir.set(layout.buildDirectory.dir("generated/git")) } android { @@ -66,7 +71,14 @@ android { viewBinding { enable = true } - + androidComponents { + onVariants { variant -> + variant.sources.assets?.addGeneratedSourceDirectory( + generateGitHash, + GenerateGitHashTask::outputDir + ) + } + } signingConfigs { if (prereleaseStoreFile != null) { create("prerelease") { From 7030e708814dd752bff4218dd2b04a8ba21aff0f Mon Sep 17 00:00:00 2001 From: Luna712 <142361265+Luna712@users.noreply.github.com> Date: Sat, 28 Mar 2026 13:26:33 -0600 Subject: [PATCH 3/5] - --- app/build.gradle.kts | 1 - 1 file changed, 1 deletion(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 521cde7635c..4fa28ca1e86 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -1,5 +1,4 @@ import com.android.build.gradle.internal.cxx.configure.gradleLocalProperties -import com.android.build.gradle.tasks.MergeSourceSetFolders import org.jetbrains.dokka.gradle.engine.parameters.KotlinPlatform import org.jetbrains.dokka.gradle.engine.parameters.VisibilityModifier import org.jetbrains.kotlin.gradle.dsl.JvmDefaultMode From 2361282a5cbfeb08009c338b5d3afafadcca30f8 Mon Sep 17 00:00:00 2001 From: Luna712 <142361265+Luna712@users.noreply.github.com> Date: Sat, 28 Mar 2026 13:28:42 -0600 Subject: [PATCH 4/5] - --- app/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 4fa28ca1e86..79e8b26c3d0 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -41,7 +41,7 @@ abstract class GenerateGitHashTask : DefaultTask() { val commitFile = File(head.parentFile, refPath) if (commitFile.exists()) commitFile.readText().trim() else "" } else headContent // If it's a detached HEAD (commit hash directly) - } else "" // If .git/HEAD doesn't exist + } else "" // If .git/HEAD doesn't exist } catch (_: Throwable) { "" // Just set to an empty string if any exception occurs }.take(7) // Get the short commit hash From 3aee2a0e04444713a472f579746110ac8a101105 Mon Sep 17 00:00:00 2001 From: Luna712 <142361265+Luna712@users.noreply.github.com> Date: Sun, 29 Mar 2026 12:45:51 -0600 Subject: [PATCH 5/5] Minor formatting --- app/build.gradle.kts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 79e8b26c3d0..cef0ec3c272 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -70,6 +70,7 @@ android { viewBinding { enable = true } + androidComponents { onVariants { variant -> variant.sources.assets?.addGeneratedSourceDirectory( @@ -78,6 +79,7 @@ android { ) } } + signingConfigs { if (prereleaseStoreFile != null) { create("prerelease") {