tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

ConfigPlugin.kt (7814B)


      1 /* This Source Code Form is subject to the terms of the Mozilla Public
      2 * License, v. 2.0. If a copy of the MPL was not distributed with this
      3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      4 
      5 import org.gradle.api.Plugin
      6 import org.gradle.api.Project
      7 import org.gradle.api.provider.ProviderFactory
      8 import org.gradle.kotlin.dsl.extra
      9 import org.gradle.process.ExecOutput
     10 import java.nio.file.Paths
     11 import java.text.SimpleDateFormat
     12 import java.time.LocalDateTime
     13 import java.util.Date
     14 import java.util.Locale
     15 
     16 class ConfigPlugin : Plugin<Project> {
     17    override fun apply(project: Project) = Unit
     18 }
     19 
     20 object Config {
     21 
     22    @JvmStatic
     23    private fun generateDebugVersionName(): String {
     24        val today = if (System.getenv("MOZ_BUILD_DATE") != null) {
     25            val format = SimpleDateFormat("yyyyMMddHHmmss", Locale.US)
     26            format.parse(System.getenv("MOZ_BUILD_DATE"))
     27        } else {
     28            Date()
     29        }
     30        // Append the year (2 digits) and week in year (2 digits). This will make it easier to distinguish versions and
     31        // identify ancient versions when debugging issues. However this will still keep the same version number during
     32        // the week so that we do not end up with a lot of versions in tools like Sentry. As an extra this matches the
     33        // sections we use in the changelog (weeks).
     34        return SimpleDateFormat("1.0.yyww", Locale.US).format(today)
     35    }
     36 
     37    @JvmStatic
     38    fun releaseVersionName(project: Project): String? {
     39        // Note: release builds must have the `versionName` set. However, the gradle ecosystem makes this hard to
     40        // ergonomically validate (sometimes IDEs default to a release variant and mysteriously fail due to the
     41        // validation, sometimes devs just need a release build and specifying project properties is annoying in IDEs),
     42        // so instead we'll allow the `versionName` to silently default to an empty string.
     43        return if (project.hasProperty("versionName")) project.property("versionName").toString() else null
     44    }
     45 
     46    @JvmStatic
     47    fun nightlyVersionName(project: Project): String {
     48        // Nightly versions will use the version from "version.txt".
     49        return readVersionFromFile(project)
     50    }
     51 
     52    @JvmStatic
     53    fun readVersionFromFile(project: Project): String {
     54        var mozconfig = project.gradle.extensions.extraProperties.get("mozconfig") as Map<*, *>;
     55        var topsrcdir = mozconfig.get("topsrcdir") as String;
     56        var versionPath = Paths.get(topsrcdir, "mobile/android/version.txt");
     57        return project.file(versionPath).useLines { it.firstOrNull() ?: "" }
     58    }
     59 
     60    @JvmStatic
     61    fun majorVersion(project: Project): String {
     62        return readVersionFromFile(project).split(".")[0]
     63    }
     64 
     65    private val fennecBaseVersionCode by lazy {
     66        val format = SimpleDateFormat("yyyyMMddHHmmss", Locale.US)
     67        val cutoff = format.parse("20141228000000")
     68        val build = if (System.getenv("MOZ_BUILD_DATE") != null) format.parse(System.getenv("MOZ_BUILD_DATE")) else Date()
     69 
     70        Math.floor((build.time - cutoff.time) / (1000.0 * 60.0 * 60.0)).toInt()
     71    }
     72 
     73    /**
     74     * Generates a versionCode that follows the same rules like legacy Fennec builds.
     75     * Adapted from:
     76     * https://searchfox.org/mozilla-central/rev/34cb8d0a2a324043bcfc2c56f37b31abe7fb23a8/python/mozbuild/mozbuild/android_version_code.py
     77     *
     78     * There is a discrepancy between the epoch date used here (20141228)
     79     * and the epoch used in Fennec (20150801) for historical reasons. We keep
     80     * this discrepancy to avoid having Fenix version codes decrease.
     81     * Note that the original Fennec implementation also had an inconsistency in
     82     * the documented epoch date (20150901) and the effective epoch date (20150801).
     83     */
     84    @JvmStatic
     85    fun generateFennecVersionCode(abi: String): Int {
     86        // The important consideration is that version codes be monotonically
     87        // increasing (per Android package name) for all published builds.  The input
     88        // build IDs are based on timestamps and hence are always monotonically
     89        // increasing.
     90        //
     91        //         The generated v1 version codes look like (in binary):
     92        //
     93        // 0111 1000 0010 tttt tttt tttt tttt txpg
     94        //
     95        // The 17 bits labelled 't' represent the number of hours since midnight on
     96        // December 28, 2014.  (2014122800 in yyyyMMddHH format.)  This yields a
     97        // little under 15 years worth of hourly build identifiers, since 2**17 / (366
     98        //         * 24) =~ 14.92.
     99        //
    100        //         The bits labelled 'x', 'p', and 'g' are feature flags.
    101        //
    102        // The bit labelled 'x' is 1 if the build is for an x86 or x86-64 architecture,
    103        // and 0 otherwise, which means the build is for an ARM or ARM64 architecture.
    104        // (Fennec no longer supports ARMv6, so ARM is equivalent to ARMv7.
    105        //
    106        //         ARM64 is also known as AArch64; it is logically ARMv8.)
    107        //
    108        // For the same release, x86 and x86_64 builds have higher version codes and
    109        // take precedence over ARM builds, so that they are preferred over ARM on
    110        // devices that have ARM emulation.
    111        //
    112        // The bit labelled 'p' is 1 if the build is for a 64-bit architecture (x86-64
    113        //         or ARM64), and 0 otherwise, which means the build is for a 32-bit
    114        // architecture (x86 or ARM). 64-bit builds have higher version codes so
    115        // they take precedence over 32-bit builds on devices that support 64-bit.
    116        //
    117        // The bit labelled 'g' was once used for APK splits. Today, it is 0 for
    118        // APK builds, or 1 for AAB/Universal builds.
    119        //
    120        // We throw an explanatory exception when we are within one calendar year of
    121        // running out of build events.  This gives lots of time to update the version
    122        // scheme.  The responsible individual should then bump the range (to allow
    123        //         builds to continue) and use the time remaining to update the version scheme
    124        // via the reserved high order bits.
    125        //
    126        //         N.B.: the reserved 0 bit to the left of the highest order 't' bit can,
    127        //         sometimes, be used to bump the version scheme.  In addition, by reducing the
    128        // granularity of the build identifiers (for example, moving to identifying
    129        // builds every 2 or 4 hours), the version scheme may be adjusted further still
    130        // without losing a (valuable) high order bit.
    131 
    132        val base = fennecBaseVersionCode
    133 
    134        when {
    135            base < 0 -> throw RuntimeException("Cannot calculate versionCode. Hours underflow.")
    136            base > 0x20000 /* 2^17 */ -> throw RuntimeException("Cannot calculate versionCode. Hours overflow.")
    137            base > 0x20000 - (366 * 24) ->
    138                // You have one year to update the version scheme...
    139                throw RuntimeException("Running out of low order bits calculating versionCode.")
    140        }
    141 
    142        var version = 0x78200000 // 1111000001000000000000000000000
    143        // We reserve 1 "middle" high order bit for the future, and 3 low order bits
    144        // for architecture and APK splits.
    145        version = version or (base shl 3)
    146 
    147        // 'x' bit is 1 for x86/x86-64 architectures
    148        if (abi == "universal" || abi == "x86_64" || abi == "x86") {
    149            version = version or (1 shl 2)
    150        }
    151 
    152        // 'p' bit is 1 for 64-bit architectures.
    153        if (abi == "universal" || abi == "arm64-v8a" || abi == "x86_64") {
    154            version = version or (1 shl 1)
    155        }
    156 
    157        // 'g' bit is 0 for APK, 1 for AAB/Universal
    158        if (abi == "universal") {
    159            version = version or (1 shl 0)
    160        }
    161 
    162        return version
    163    }
    164 }