diff options
Diffstat (limited to 'buildSrc/src/main')
-rw-r--r-- | buildSrc/src/main/java/BaseProjectConfig.kt | 97 | ||||
-rw-r--r-- | buildSrc/src/main/java/CrowdinDownloadPlugin.kt | 121 | ||||
-rw-r--r-- | buildSrc/src/main/java/CrowdinExtension.kt | 17 | ||||
-rw-r--r-- | buildSrc/src/main/java/KaptConfigs.kt | 34 | ||||
-rw-r--r-- | buildSrc/src/main/java/PasswordStorePlugin.kt | 73 | ||||
-rw-r--r-- | buildSrc/src/main/java/ProductFlavors.kt | 13 | ||||
-rw-r--r-- | buildSrc/src/main/java/PublicSuffixListPlugin.kt | 120 | ||||
-rw-r--r-- | buildSrc/src/main/java/SigningConfig.kt | 40 | ||||
-rw-r--r-- | buildSrc/src/main/java/SlimTests.kt | 42 | ||||
-rw-r--r-- | buildSrc/src/main/java/VersioningPlugin.kt | 106 |
10 files changed, 0 insertions, 663 deletions
diff --git a/buildSrc/src/main/java/BaseProjectConfig.kt b/buildSrc/src/main/java/BaseProjectConfig.kt deleted file mode 100644 index f11b9dec..00000000 --- a/buildSrc/src/main/java/BaseProjectConfig.kt +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright © 2014-2021 The Android Password Store Authors. All Rights Reserved. - * SPDX-License-Identifier: GPL-3.0-only - */ - -import com.android.build.gradle.TestedExtension -import com.android.build.gradle.internal.dsl.BaseAppModuleExtension -import org.gradle.api.JavaVersion -import org.gradle.api.Project -import org.gradle.kotlin.dsl.register -import org.gradle.language.nativeplatform.internal.BuildType - -/** Checks if we're building a snapshot */ -@Suppress("UnstableApiUsage") -fun Project.isSnapshot(): Boolean { - with(project.providers) { - val workflow = environmentVariable("GITHUB_WORKFLOW").forUseAtConfigurationTime() - val snapshot = environmentVariable("SNAPSHOT").forUseAtConfigurationTime() - return workflow.isPresent && snapshot.isPresent - } -} - -/** Apply configurations for app module */ -@Suppress("UnstableApiUsage") -internal fun BaseAppModuleExtension.configureAndroidApplicationOptions(project: Project) { - val minifySwitch = - project.providers.environmentVariable("DISABLE_MINIFY").forUseAtConfigurationTime() - - adbOptions.installOptions("--user 0") - - buildFeatures { - viewBinding = true - buildConfig = true - } - - flavorDimensions.add(FlavorDimensions.FREE) - productFlavors { - register(ProductFlavors.FREE) {} - register(ProductFlavors.NON_FREE) {} - } - - buildTypes { - named(BuildType.RELEASE.name) { - isMinifyEnabled = !minifySwitch.isPresent - setProguardFiles( - listOf( - "proguard-android-optimize.txt", - "proguard-rules.pro", - "proguard-rules-missing-classes.pro", - ) - ) - buildConfigField("boolean", "ENABLE_DEBUG_FEATURES", "${project.isSnapshot()}") - } - named(BuildType.DEBUG.name) { - applicationIdSuffix = ".debug" - versionNameSuffix = "-debug" - isMinifyEnabled = false - buildConfigField("boolean", "ENABLE_DEBUG_FEATURES", "true") - } - } -} - -/** Apply baseline configurations for all Android projects (Application and Library). */ -@Suppress("UnstableApiUsage") -internal fun TestedExtension.configureCommonAndroidOptions() { - setCompileSdkVersion(31) - - defaultConfig { - minSdk = 23 - targetSdk = 29 - } - - sourceSets { - named("main") { java.srcDirs("src/main/kotlin") } - named("test") { java.srcDirs("src/test/kotlin") } - named("androidTest") { java.srcDirs("src/androidTest/kotlin") } - } - - packagingOptions { - resources.excludes.add("**/*.version") - resources.excludes.add("**/*.txt") - resources.excludes.add("**/*.kotlin_module") - resources.excludes.add("**/plugin.properties") - resources.excludes.add("**/META-INF/AL2.0") - resources.excludes.add("**/META-INF/LGPL2.1") - } - - compileOptions { - sourceCompatibility = JavaVersion.VERSION_11 - targetCompatibility = JavaVersion.VERSION_11 - } - - testOptions { - animationsDisabled = true - unitTests.isReturnDefaultValues = true - } -} diff --git a/buildSrc/src/main/java/CrowdinDownloadPlugin.kt b/buildSrc/src/main/java/CrowdinDownloadPlugin.kt deleted file mode 100644 index 4be93885..00000000 --- a/buildSrc/src/main/java/CrowdinDownloadPlugin.kt +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Copyright © 2014-2021 The Android Password Store Authors. All Rights Reserved. - * SPDX-License-Identifier: GPL-3.0-only - */ - -import de.undercouch.gradle.tasks.download.Download -import java.io.File -import javax.xml.parsers.DocumentBuilderFactory -import okhttp3.OkHttpClient -import okhttp3.Request -import org.gradle.api.GradleException -import org.gradle.api.Plugin -import org.gradle.api.Project -import org.gradle.api.tasks.Copy -import org.gradle.kotlin.dsl.create -import org.gradle.kotlin.dsl.register -import org.w3c.dom.Document - -private const val EXCEPTION_MESSAGE = - """Applying `crowdin-plugin` requires a projectName to be configured via the "crowdin" extension.""" -private const val CROWDIN_BUILD_API_URL = - "https://api.crowdin.com/api/project/%s/export?login=%s&account-key=%s" - -class CrowdinDownloadPlugin : Plugin<Project> { - - override fun apply(project: Project) { - with(project) { - val extension = extensions.create<CrowdinExtension>("crowdin") - afterEvaluate { - val projectName = extension.projectName - if (projectName.isEmpty()) { - throw GradleException(EXCEPTION_MESSAGE) - } - tasks.register("buildOnApi") { - doLast { - val login = providers.environmentVariable("CROWDIN_LOGIN").forUseAtConfigurationTime() - val key = - providers.environmentVariable("CROWDIN_PROJECT_KEY").forUseAtConfigurationTime() - if (!login.isPresent) { - throw GradleException("CROWDIN_LOGIN environment variable must be set") - } - if (!key.isPresent) { - throw GradleException("CROWDIN_PROJECT_KEY environment variable must be set") - } - val client = OkHttpClient() - val url = CROWDIN_BUILD_API_URL.format(projectName, login.get(), key.get()) - val request = Request.Builder().url(url).get().build() - client.newCall(request).execute() - } - } - tasks.register<Download>("downloadCrowdin") { - dependsOn("buildOnApi") - src("https://crowdin.com/backend/download/project/$projectName.zip") - dest("$buildDir/translations.zip") - overwrite(true) - } - tasks.register<Copy>("extractCrowdin") { - dependsOn("downloadCrowdin") - doFirst { File(buildDir, "translations").deleteRecursively() } - from(zipTree("$buildDir/translations.zip")) - into("$buildDir/translations") - } - tasks.register<Copy>("extractStrings") { - dependsOn("extractCrowdin") - from("$buildDir/translations/") - into("${projectDir}/src/") - setFinalizedBy(setOf("removeIncompleteStrings")) - } - tasks.register("removeIncompleteStrings") { - doLast { - val sourceSets = arrayOf("main", "nonFree") - for (sourceSet in sourceSets) { - val stringFiles = - File("${projectDir}/src/$sourceSet").walkTopDown().filter { - it.name == "strings.xml" - } - val sourceFile = - stringFiles.firstOrNull { it.path.endsWith("values/strings.xml") } - ?: throw GradleException("No root strings.xml found in '$sourceSet' sourceSet") - val sourceDoc = parseDocument(sourceFile) - val baselineStringCount = countStrings(sourceDoc) - val threshold = 0.80 * baselineStringCount - stringFiles.forEach { file -> - if (file != sourceFile) { - val doc = parseDocument(file) - val stringCount = countStrings(doc) - if (stringCount < threshold) { - file.delete() - } - } - } - } - } - } - tasks.register("crowdin") { - dependsOn("extractStrings") - if (!extension.skipCleanup) { - doLast { - File("$buildDir/translations").deleteRecursively() - File("$buildDir/nonFree-translations").deleteRecursively() - File("$buildDir/translations.zip").delete() - } - } - } - } - } - } - - private fun parseDocument(file: File): Document { - val dbFactory = DocumentBuilderFactory.newInstance() - val documentBuilder = dbFactory.newDocumentBuilder() - return documentBuilder.parse(file) - } - - private fun countStrings(document: Document): Int { - // Normalization is beneficial for us - // https://stackoverflow.com/questions/13786607/normalization-in-dom-parsing-with-java-how-does-it-work - document.documentElement.normalize() - return document.getElementsByTagName("string").length - } -} diff --git a/buildSrc/src/main/java/CrowdinExtension.kt b/buildSrc/src/main/java/CrowdinExtension.kt deleted file mode 100644 index e50d8e5c..00000000 --- a/buildSrc/src/main/java/CrowdinExtension.kt +++ /dev/null @@ -1,17 +0,0 @@ -/* - * Copyright © 2014-2021 The Android Password Store Authors. All Rights Reserved. - * SPDX-License-Identifier: GPL-3.0-only - */ - -open class CrowdinExtension { - - /** Configure the project name on Crowdin */ - open var projectName = "" - - /** - * Don't delete downloaded and extracted translation archives from build directory. - * - * Useful for debugging. - */ - open var skipCleanup = false -} diff --git a/buildSrc/src/main/java/KaptConfigs.kt b/buildSrc/src/main/java/KaptConfigs.kt deleted file mode 100644 index db1c6d5a..00000000 --- a/buildSrc/src/main/java/KaptConfigs.kt +++ /dev/null @@ -1,34 +0,0 @@ -import org.gradle.api.Project -import org.gradle.kotlin.dsl.configure -import org.jetbrains.kotlin.gradle.plugin.KaptExtension - -/** Apply default kapt configs to the [Project]. */ -internal fun Project.configureKapt() { - extensions.configure<KaptExtension> { - javacOptions { - if (hasDaggerCompilerDependency) { - // https://dagger.dev/dev-guide/compiler-options#fastinit-mode - option("-Adagger.fastInit=enabled") - // Enable the better, experimental error messages - // https://github.com/google/dagger/commit/0d2505a727b54f47b8677f42dd4fc5c1924e37f5 - option("-Adagger.experimentalDaggerErrorMessages=enabled") - // Share test components for when we start leveraging Hilt for tests - // https://github.com/google/dagger/releases/tag/dagger-2.34 - option("-Adagger.hilt.shareTestComponents=true") - // KAPT nests errors causing real issues to be suppressed in CI logs - option("-Xmaxerrs", 500) - // Enables per-module validation for faster error detection - // https://github.com/google/dagger/commit/325b516ac6a53d3fc973d247b5231fafda9870a2 - option("-Adagger.moduleBindingValidation=ERROR") - } - } - } - // disable kapt tasks for unit tests - tasks - .matching { it.name.startsWith("kapt") && it.name.endsWith("UnitTestKotlin") } - .configureEach { enabled = false } -} - -private val Project.hasDaggerCompilerDependency: Boolean - get() = - configurations.any { it.dependencies.any { dependency -> dependency.name == "hilt-compiler" } } diff --git a/buildSrc/src/main/java/PasswordStorePlugin.kt b/buildSrc/src/main/java/PasswordStorePlugin.kt deleted file mode 100644 index 926cddbb..00000000 --- a/buildSrc/src/main/java/PasswordStorePlugin.kt +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright © 2014-2021 The Android Password Store Authors. All Rights Reserved. - * SPDX-License-Identifier: GPL-3.0-only - */ - -import com.android.build.gradle.TestedExtension -import com.android.build.gradle.internal.dsl.BaseAppModuleExtension -import com.android.build.gradle.internal.plugins.AppPlugin -import com.android.build.gradle.internal.plugins.LibraryPlugin -import org.gradle.api.Plugin -import org.gradle.api.Project -import org.gradle.api.plugins.JavaLibraryPlugin -import org.gradle.api.plugins.JavaPlugin -import org.gradle.api.tasks.compile.JavaCompile -import org.gradle.kotlin.dsl.configure -import org.gradle.kotlin.dsl.getByType -import org.gradle.kotlin.dsl.withType -import org.gradle.plugins.signing.SigningExtension -import org.gradle.plugins.signing.SigningPlugin -import org.jetbrains.kotlin.gradle.dsl.KotlinProjectExtension -import org.jetbrains.kotlin.gradle.internal.Kapt3GradleSubplugin -import org.jetbrains.kotlin.gradle.plugin.KotlinPluginWrapper -import org.jetbrains.kotlin.gradle.tasks.KotlinCompile - -class PasswordStorePlugin : Plugin<Project> { - - override fun apply(project: Project) { - project.plugins.all { - when (this) { - is JavaPlugin, is JavaLibraryPlugin -> { - project.tasks.withType<JavaCompile> { - options.compilerArgs.add("-Xlint:unchecked") - options.isDeprecation = true - options.isWarnings = true - } - } - is LibraryPlugin -> { - project.extensions.getByType<TestedExtension>().configureCommonAndroidOptions() - project.configureExplicitApi() - project.configureSlimTests() - } - is AppPlugin -> { - project - .extensions - .getByType<BaseAppModuleExtension>() - .configureAndroidApplicationOptions(project) - project.extensions.getByType<BaseAppModuleExtension>().configureBuildSigning(project) - project.extensions.getByType<TestedExtension>().configureCommonAndroidOptions() - project.configureSlimTests() - } - is SigningPlugin -> { - project.extensions.getByType<SigningExtension>().configureBuildSigning() - } - is KotlinPluginWrapper -> { - project.configureExplicitApi() - } - is Kapt3GradleSubplugin -> { - project.configureKapt() - } - } - } - } - - private fun Project.configureExplicitApi() { - val project = this - tasks.withType<KotlinCompile> { - if (!name.contains("test", ignoreCase = true)) { - project.configure<KotlinProjectExtension> { explicitApi() } - kotlinOptions { freeCompilerArgs += listOf("-Xexplicit-api=strict") } - } - } - } -} diff --git a/buildSrc/src/main/java/ProductFlavors.kt b/buildSrc/src/main/java/ProductFlavors.kt deleted file mode 100644 index 5b722a37..00000000 --- a/buildSrc/src/main/java/ProductFlavors.kt +++ /dev/null @@ -1,13 +0,0 @@ -/* - * Copyright © 2014-2021 The Android Password Store Authors. All Rights Reserved. - * SPDX-License-Identifier: GPL-3.0-only - */ - -object FlavorDimensions { - const val FREE = "free" -} - -object ProductFlavors { - const val FREE = "free" - const val NON_FREE = "nonFree" -} diff --git a/buildSrc/src/main/java/PublicSuffixListPlugin.kt b/buildSrc/src/main/java/PublicSuffixListPlugin.kt deleted file mode 100644 index df50f2b4..00000000 --- a/buildSrc/src/main/java/PublicSuffixListPlugin.kt +++ /dev/null @@ -1,120 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -import java.io.File -import java.util.TreeSet -import okhttp3.OkHttpClient -import okhttp3.Request -import okio.ByteString -import okio.ByteString.Companion.encodeUtf8 -import okio.buffer -import okio.sink -import org.gradle.api.Plugin -import org.gradle.api.Project - -/** - * Gradle plugin to update the public suffix list used by the `lib-publicsuffixlist` component. - * - * Base on PublicSuffixListGenerator from OkHttp: - * https://github.com/square/okhttp/blob/master/okhttp/src/test/java/okhttp3/internal/publicsuffix/PublicSuffixListGenerator.java - */ -class PublicSuffixListPlugin : Plugin<Project> { - override fun apply(project: Project) { - project.tasks.register("updatePSL") { - doLast { - val filename = project.projectDir.absolutePath + "/src/main/assets/publicsuffixes" - updatePublicSuffixList(filename) - } - } - } - - private fun updatePublicSuffixList(destination: String) { - val list = fetchPublicSuffixList() - writeListToDisk(destination, list) - } - - private fun writeListToDisk(destination: String, data: PublicSuffixListData) { - val fileSink = File(destination).sink() - - fileSink.buffer().use { sink -> - sink.writeInt(data.totalRuleBytes) - - for (domain in data.sortedRules) { - sink.write(domain).writeByte('\n'.toInt()) - } - - sink.writeInt(data.totalExceptionRuleBytes) - - for (domain in data.sortedExceptionRules) { - sink.write(domain).writeByte('\n'.toInt()) - } - } - } - - private fun fetchPublicSuffixList(): PublicSuffixListData { - val client = OkHttpClient.Builder().build() - - val request = - Request.Builder().url("https://publicsuffix.org/list/public_suffix_list.dat").build() - - client.newCall(request).execute().use { response -> - val source = requireNotNull(response.body).source() - - val data = PublicSuffixListData() - - while (!source.exhausted()) { - val line = source.readUtf8LineStrict() - - if (line.trim { it <= ' ' }.isEmpty() || line.startsWith("//")) { - continue - } - - if (line.contains(WILDCARD_CHAR)) { - assertWildcardRule(line) - } - - var rule = line.encodeUtf8() - - if (rule.startsWith(EXCEPTION_RULE_MARKER)) { - rule = rule.substring(1) - // We use '\n' for end of value. - data.totalExceptionRuleBytes += rule.size + 1 - data.sortedExceptionRules.add(rule) - } else { - data.totalRuleBytes += rule.size + 1 // We use '\n' for end of value. - data.sortedRules.add(rule) - } - } - - return data - } - } - - @Suppress("TooGenericExceptionThrown", "ThrowsCount") - private fun assertWildcardRule(rule: String) { - if (rule.indexOf(WILDCARD_CHAR) != 0) { - throw RuntimeException("Wildcard is not not in leftmost position") - } - - if (rule.indexOf(WILDCARD_CHAR, 1) != -1) { - throw RuntimeException("Rule contains multiple wildcards") - } - - if (rule.length == 1) { - throw RuntimeException("Rule wildcards the first level") - } - } - - companion object { - private const val WILDCARD_CHAR = "*" - private val EXCEPTION_RULE_MARKER = "!".encodeUtf8() - } -} - -data class PublicSuffixListData( - var totalRuleBytes: Int = 0, - var totalExceptionRuleBytes: Int = 0, - val sortedRules: TreeSet<ByteString> = TreeSet(), - val sortedExceptionRules: TreeSet<ByteString> = TreeSet() -) diff --git a/buildSrc/src/main/java/SigningConfig.kt b/buildSrc/src/main/java/SigningConfig.kt deleted file mode 100644 index aa612b35..00000000 --- a/buildSrc/src/main/java/SigningConfig.kt +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright © 2014-2021 The Android Password Store Authors. All Rights Reserved. - * SPDX-License-Identifier: GPL-3.0-only - */ - -import com.android.build.gradle.internal.dsl.BaseAppModuleExtension -import java.util.Properties -import org.gradle.api.Project -import org.gradle.kotlin.dsl.provideDelegate -import org.gradle.plugins.signing.SigningExtension - -private const val KEYSTORE_CONFIG_PATH = "keystore.properties" - -/** Configure signing for all build types. */ -@Suppress("UnstableApiUsage") -internal fun BaseAppModuleExtension.configureBuildSigning(project: Project) { - with(project) { - val keystoreConfigFile = rootProject.layout.projectDirectory.file(KEYSTORE_CONFIG_PATH) - if (!keystoreConfigFile.asFile.exists()) return - val contents = providers.fileContents(keystoreConfigFile).asText.forUseAtConfigurationTime() - val keystoreProperties = Properties() - keystoreProperties.load(contents.get().byteInputStream()) - signingConfigs { - register("release") { - keyAlias = keystoreProperties["keyAlias"] as String - keyPassword = keystoreProperties["keyPassword"] as String - storeFile = rootProject.file(keystoreProperties["storeFile"] as String) - storePassword = keystoreProperties["storePassword"] as String - } - } - val signingConfig = signingConfigs.getByName("release") - buildTypes.all { setSigningConfig(signingConfig) } - } -} - -internal fun SigningExtension.configureBuildSigning() { - val signingKey: String? by project - val signingPassword: String? by project - useInMemoryPgpKeys(signingKey, signingPassword) -} diff --git a/buildSrc/src/main/java/SlimTests.kt b/buildSrc/src/main/java/SlimTests.kt deleted file mode 100644 index 4057032b..00000000 --- a/buildSrc/src/main/java/SlimTests.kt +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright © 2014-2021 The Android Password Store Authors. All Rights Reserved. - * SPDX-License-Identifier: GPL-3.0-only - */ - -import com.android.build.api.variant.ApplicationAndroidComponentsExtension -import com.android.build.api.variant.LibraryAndroidComponentsExtension -import org.gradle.api.Project -import org.gradle.kotlin.dsl.findByType -import org.gradle.language.nativeplatform.internal.BuildType - -/** - * When the "slimTests" project property is provided, disable the unit test tasks on `release` build - * type and `nonFree` product flavor to avoid running the same tests repeatedly in different build - * variants. - * - * Examples: `./gradlew test -PslimTests` will run unit tests for `nonFreeDebug` and `debug` build - * variants in Android App and Library projects, and all tests in JVM projects. - */ -internal fun Project.configureSlimTests() { - if (providers.gradleProperty(SLIM_TESTS_PROPERTY).forUseAtConfigurationTime().isPresent) { - // disable unit test tasks on the release build type for Android Library projects - extensions.findByType<LibraryAndroidComponentsExtension>()?.run { - beforeVariants(selector().withBuildType(BuildType.RELEASE.name)) { - it.enableUnitTest = false - it.enableAndroidTest = false - } - } - - // disable unit test tasks on the release build type and free flavor for Android Application - // projects. - extensions.findByType<ApplicationAndroidComponentsExtension>()?.run { - beforeVariants(selector().withBuildType(BuildType.RELEASE.name)) { it.enableUnitTest = false } - beforeVariants(selector().withFlavor(FlavorDimensions.FREE to ProductFlavors.NON_FREE)) { - it.enableUnitTest = false - it.enableAndroidTest = false - } - } - } -} - -private const val SLIM_TESTS_PROPERTY = "slimTests" diff --git a/buildSrc/src/main/java/VersioningPlugin.kt b/buildSrc/src/main/java/VersioningPlugin.kt deleted file mode 100644 index 1ebbd9b8..00000000 --- a/buildSrc/src/main/java/VersioningPlugin.kt +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright © 2014-2021 The Android Password Store Authors. All Rights Reserved. - * SPDX-License-Identifier: GPL-3.0-only - */ - -import com.android.build.gradle.internal.plugins.AppPlugin -import com.vdurmont.semver4j.Semver -import java.io.OutputStream -import java.util.Properties -import org.gradle.api.Plugin -import org.gradle.api.Project - -private const val VERSIONING_PROP_FILE = "version.properties" -private const val VERSIONING_PROP_VERSION_NAME = "versioning-plugin.versionName" -private const val VERSIONING_PROP_VERSION_CODE = "versioning-plugin.versionCode" -private const val VERSIONING_PROP_COMMENT = - """ -This file was automatically generated by 'versioning-plugin'. DO NOT EDIT MANUALLY. -""" - -/** - * A Gradle [Plugin] that takes a [Project] with the [AppPlugin] applied and dynamically sets the - * versionCode and versionName properties based on values read from a [VERSIONING_PROP_FILE] file in - * the [Project.getBuildDir] directory. It also adds Gradle tasks to bump the major, minor, and - * patch versions along with one to prepare the next snapshot. - */ -@Suppress("UnstableApiUsage", "NAME_SHADOWING") -class VersioningPlugin : Plugin<Project> { - - /** Generate the Android 'versionCode' property */ - private fun Semver.androidCode(): Int { - return major * 1_00_00 + minor * 1_00 + patch - } - - /** Write an Android-specific variant of [this] to [stream] */ - private fun Semver.writeForAndroid(stream: OutputStream) { - val newVersionCode = androidCode() - val props = Properties() - props.setProperty(VERSIONING_PROP_VERSION_CODE, "$newVersionCode") - props.setProperty(VERSIONING_PROP_VERSION_NAME, toString()) - props.store(stream, VERSIONING_PROP_COMMENT) - } - - override fun apply(project: Project) { - with(project) { - val appPlugin = - requireNotNull(plugins.findPlugin(AppPlugin::class.java)) { - "Plugin 'com.android.application' must be applied to use this plugin" - } - val propFile = layout.projectDirectory.file(VERSIONING_PROP_FILE) - require(propFile.asFile.exists()) { - "A 'version.properties' file must exist in the project subdirectory to use this plugin" - } - val contents = providers.fileContents(propFile).asText.forUseAtConfigurationTime() - val versionProps = Properties().also { it.load(contents.get().byteInputStream()) } - val versionName = - requireNotNull(versionProps.getProperty(VERSIONING_PROP_VERSION_NAME)) { - "version.properties must contain a '$VERSIONING_PROP_VERSION_NAME' property" - } - val versionCode = - requireNotNull(versionProps.getProperty(VERSIONING_PROP_VERSION_CODE).toInt()) { - "version.properties must contain a '$VERSIONING_PROP_VERSION_CODE' property" - } - appPlugin.extension.defaultConfig.versionName = versionName - appPlugin.extension.defaultConfig.versionCode = versionCode - afterEvaluate { - val version = Semver(versionName) - tasks.register("clearPreRelease") { - doLast { version.withClearedSuffix().writeForAndroid(propFile.asFile.outputStream()) } - } - tasks.register("bumpMajor") { - doLast { - version - .withIncMajor() - .withClearedSuffix() - .writeForAndroid(propFile.asFile.outputStream()) - } - } - tasks.register("bumpMinor") { - doLast { - version - .withIncMinor() - .withClearedSuffix() - .writeForAndroid(propFile.asFile.outputStream()) - } - } - tasks.register("bumpPatch") { - doLast { - version - .withIncPatch() - .withClearedSuffix() - .writeForAndroid(propFile.asFile.outputStream()) - } - } - tasks.register("bumpSnapshot") { - doLast { - version - .withIncMinor() - .withSuffix("SNAPSHOT") - .writeForAndroid(propFile.asFile.outputStream()) - } - } - } - } - } -} |