From 4e2a09fc7f74a5566f146c29f68a4786b09fb22a Mon Sep 17 00:00:00 2001 From: Xavier Ducrohet Date: Fri, 8 Dec 2023 09:32:37 -0800 Subject: [PATCH] Make Kotlin version per AGP This includes reading the kotlin version from version_mappings.txt and some refactoring here and there to make reading it and using it simpler. Also added a 3rd AGP to test (8.2), and some work to make older AGP and older Kotlin versions available as targets Still need to figure out the target issue in the bazel macro. Bug: N/A Test: tested via the recipes themselves Change-Id: Ibf9029291d54ebd66e1988dce9c95fdf6fab049f --- BUILD | 15 ++ .../converter/converters/Converter.kt | 49 ++++-- .../converter/converters/ConverterUtils.kt | 58 ++++--- .../converter/converters/RecipeConverter.kt | 41 ++--- .../converter/converters/ReleaseConverter.kt | 109 ++++--------- .../converter/converters/SourceConverter.kt | 21 +-- .../converters/WorkingCopyConverter.kt | 144 ++++++------------ .../validators/MinMaxCurrentAgpValidator.kt | 4 +- recipes.bzl | 34 ++++- version_mappings.txt | 13 +- 10 files changed, 218 insertions(+), 270 deletions(-) diff --git a/BUILD b/BUILD index 1f1aea6e..2a40f669 100644 --- a/BUILD +++ b/BUILD @@ -1,4 +1,6 @@ load("//tools/base/bazel:kotlin.bzl", "kotlin_library") +load("//tools/base/bazel:maven.bzl", "maven_repository") +load("//tools/base/build-system/integration-test:common-dependencies.bzl", "KGP_1_8_10", "KGP_1_9_20") load(":recipes.bzl", "recipe_test") kotlin_library( @@ -28,6 +30,19 @@ kotlin_library( ], ) +# for testing against older KGP +maven_repository( + name = "kotlin_1_9_20", + artifacts = KGP_1_9_20, + visibility = [":__subpackages__"], +) + +maven_repository( + name = "kotlin_1_8_10", + artifacts = KGP_1_8_10, + visibility = [":__subpackages__"], +) + recipe_test( name = "addBuildTypeUsingDslFinalize", ) diff --git a/convert-tool/app/src/main/kotlin/com/google/android/gradle_recipe/converter/converters/Converter.kt b/convert-tool/app/src/main/kotlin/com/google/android/gradle_recipe/converter/converters/Converter.kt index b5863ea5..cabb1588 100644 --- a/convert-tool/app/src/main/kotlin/com/google/android/gradle_recipe/converter/converters/Converter.kt +++ b/convert-tool/app/src/main/kotlin/com/google/android/gradle_recipe/converter/converters/Converter.kt @@ -17,7 +17,9 @@ package com.google.android.gradle_recipe.converter.converters import com.google.android.gradle_recipe.converter.recipe.Recipe +import com.google.android.gradle_recipe.converter.recipe.toMajorMinor import java.nio.file.Path +import kotlin.io.path.isDirectory /** The position of the gradle-resources folder * to take the Gradle wrapper @@ -28,21 +30,21 @@ const val GRADLE_RESOURCES_FOLDER = "gradle-resources" * The objects are created and called from the RecipeConverter class, * using a Template Method pattern. */ -interface Converter { +abstract class Converter( + protected val branchRoot: Path +) { + + var recipe: Recipe? = null + /** Can converter convert this recipe */ - fun isConversionCompliant(recipe: Recipe): Boolean - - /** Sets the recipe to convert, before the conversion - */ - fun setRecipe(recipe: Recipe) { - } + abstract fun isConversionCompliant(recipe: Recipe): Boolean /** * Converts build.gradle */ - fun convertBuildGradle(source: Path, target: Path) + abstract fun convertBuildGradle(source: Path, target: Path) /** * Converts build.gradle.kts ==> same as build.gradle @@ -54,7 +56,7 @@ interface Converter { /** * Converts settings.gradle */ - fun convertSettingsGradle(source: Path, target: Path) + abstract fun convertSettingsGradle(source: Path, target: Path) /** * Converts settings.gradle.kts ==> same as settings.gradle @@ -66,11 +68,36 @@ interface Converter { /** * Converts the version catalog file */ - fun convertVersionCatalog(source: Path, target: Path) + abstract fun convertVersionCatalog(source: Path, target: Path) /** * Copies the gradle folder from the GRADLE_RESOURCES_FOLDER * to dest. */ - fun copyGradleFolder(dest: Path) + fun copyGradleFolder(dest: Path) { + val source = branchRoot.resolve(GRADLE_RESOURCES_FOLDER) + if (!source.isDirectory()) { + throw RuntimeException("Unable to find gradle resources at $source") + } + + dest.mkdirs() + + source.toFile().copyRecursively(target = dest.toFile()) + + processGradleWrapperProperties( + dest.resolve("gradle").resolve("wrapper").resolve("gradle-wrapper.properties") + ) + + } + + open fun processGradleWrapperProperties(file: Path) { } + + protected fun getMinAgp(): String = recipe?.minAgpVersion + ?: error("min Agp version is badly specified in the metadata") + + protected fun getVersionInfoFromAgp(agpVersion: String): VersionInfo { + val agp = agpVersion.toMajorMinor() + return getVersionsFromAgp(branchRoot, agp) + ?: throw RuntimeException("Unable to fetch VersionInfo for AGP $agp") + } } \ No newline at end of file diff --git a/convert-tool/app/src/main/kotlin/com/google/android/gradle_recipe/converter/converters/ConverterUtils.kt b/convert-tool/app/src/main/kotlin/com/google/android/gradle_recipe/converter/converters/ConverterUtils.kt index f743261f..880ee416 100644 --- a/convert-tool/app/src/main/kotlin/com/google/android/gradle_recipe/converter/converters/ConverterUtils.kt +++ b/convert-tool/app/src/main/kotlin/com/google/android/gradle_recipe/converter/converters/ConverterUtils.kt @@ -52,8 +52,8 @@ fun Path.mkdirs(): Boolean { * id 'com.android.application' version $AGP_VERSION apply false * and replaces the $AGP_VERSION */ -fun wrapGradlePlaceholdersWithInlineValue(originalLines: List, from: String, to: String): List { - return wrapPlaceholdersWithInlineValue(originalLines, from, to, "// ") +fun List.wrapGradlePlaceholdersWithInlineValue(from: String, to: String): List { + return wrapPlaceholdersWithInlineValue(from, to, "// ") } /** @@ -63,56 +63,55 @@ fun wrapGradlePlaceholdersWithInlineValue(originalLines: List, from: Str * * with lists of relevant repositories */ -fun wrapGradlePlaceholdersWithList(originalLines: List, from: String, to: List): List { - return wrapPlaceholdersWithList(originalLines, from, to, "// ") +fun List.wrapGradlePlaceholdersWithList(from: String, to: List): List { + return wrapPlaceholdersWithList(from, to, "// ") } /** * for build.gradle[.kts] , settings.gradle[.kts] ==> removes all working copy blocks * and generated lines */ -fun unwrapGradlePlaceholders(originalLines: List): List { - return unwrapPlaceholders(originalLines, "// ") +fun List.unwrapGradlePlaceholders(): List { + return unwrapPlaceholders("// ") } /** * for gradle.wrapper.properties ==> wraps $GRADLE_LOCATION */ -fun wrapGradleWrapperPlaceholders(originalLines: List, from: String, to: String): List { - return wrapPlaceholdersWithInlineValue(originalLines, from, to, "# ") +fun List.wrapGradleWrapperPlaceholders(from: String, to: String): List { + return wrapPlaceholdersWithInlineValue(from, to, "# ") } /** * for libs.versions.toml ==> unwraps all converter placeholders */ -fun unwrapVersionCatalogPlaceholders(originalLines: List): List { - return unwrapPlaceholders(originalLines, "# ") +fun List.unwrapVersionCatalogPlaceholders(): List { + return unwrapPlaceholders( "# ") } /** * for libs.versions.toml ==> wraps all converter placeholders */ -fun wrapVersionCatalogPlaceholders(originalLines: List, from: String, to: String): List { - return wrapPlaceholdersWithInlineValue(originalLines, from, to, "# ") +fun List.wrapVersionCatalogPlaceholders(from: String, to: String): List { + return wrapPlaceholdersWithInlineValue(from, to, "# ") } /** * for libs.versions.toml ==> replace all converter placeholders */ -fun replaceVersionCatalogPlaceholders(originalLines: List, from: String, to: String): List { - return replaceGradlePlaceholdersWithInlineValue(originalLines, from, to) +fun List.replaceVersionCatalogPlaceholders(from: String, to: String): List { + return replaceGradlePlaceholdersWithInlineValue(from, to) } /** * replaces placeholders inside line */ -fun replaceGradlePlaceholdersWithInlineValue( - originalLines: List, +fun List.replaceGradlePlaceholdersWithInlineValue( from: String, to: String, ): List { val result = buildList { - for (line in originalLines) { + for (line: String in this@replaceGradlePlaceholdersWithInlineValue) { if (line.contains(from)) { if (to.isNotEmpty()) { val newLine: String = line.replace(from, to) @@ -130,17 +129,16 @@ fun replaceGradlePlaceholdersWithInlineValue( /** * replaces placeholders with a code line */ -fun replacePlaceHolderWithLine(originalLines: List, placeHolder: String, value: String): List { - return replacePlaceHolderWithList(originalLines, placeHolder, if (value.isEmpty()) listOf() else listOf(value)) +fun List.replacePlaceHolderWithLine(placeHolder: String, value: String): List { + return replacePlaceHolderWithList(placeHolder, if (value.isEmpty()) listOf() else listOf(value)) } -fun replacePlaceHolderWithList( - originalLines: List, +fun List.replacePlaceHolderWithList( placeHolder: String, values: List, ): List { val result = buildList { - for (line in originalLines) { + for (line in this@replacePlaceHolderWithList) { if (line.contains(placeHolder)) { for (toLine in values) { add(toLine) @@ -157,14 +155,13 @@ fun replacePlaceHolderWithList( /** wraps placeholders, and replaces the placeholder inline * */ -private fun wrapPlaceholdersWithInlineValue( - originalLines: List, +private fun List.wrapPlaceholdersWithInlineValue( from: String, to: String, commentOut: String, ): List { val result = buildList { - for (line in originalLines) { + for (line in this@wrapPlaceholdersWithInlineValue) { if (line.contains(from)) { add("$commentOut$START_WORKING_COPY_BLOCK") add("$commentOut$line") @@ -187,14 +184,13 @@ private fun wrapPlaceholdersWithInlineValue( /** wraps placeholders, and replaces the placeholder with * a list */ -private fun wrapPlaceholdersWithList( - originalLines: List, +private fun List.wrapPlaceholdersWithList( from: String, to: List, commentOut: String, ): List { val result = buildList { - for (line in originalLines) { + for (line in this@wrapPlaceholdersWithList) { if (line.contains(from)) { add("$commentOut$START_WORKING_COPY_BLOCK") add("$commentOut$line") @@ -214,15 +210,15 @@ private fun wrapPlaceholdersWithList( /** * unwraps both gradle and properties with commentOut */ -private fun unwrapPlaceholders(originalLines: List, commentOut: String): List { +private fun List.unwrapPlaceholders(commentOut: String): List { var insideWorkBlock = false val result = buildList { - for (line in originalLines) { + for (line in this@unwrapPlaceholders) { if (line == "$commentOut$START_WORKING_COPY_BLOCK") { insideWorkBlock = true } else if (insideWorkBlock) { if (line != "$commentOut$END_WORKING_COPY_BLOCK") { - if (line.startsWith("$commentOut")) { + if (line.startsWith(commentOut)) { add(line.substring(commentOut.length)) } diff --git a/convert-tool/app/src/main/kotlin/com/google/android/gradle_recipe/converter/converters/RecipeConverter.kt b/convert-tool/app/src/main/kotlin/com/google/android/gradle_recipe/converter/converters/RecipeConverter.kt index 352dc7e5..ee7b43df 100644 --- a/convert-tool/app/src/main/kotlin/com/google/android/gradle_recipe/converter/converters/RecipeConverter.kt +++ b/convert-tool/app/src/main/kotlin/com/google/android/gradle_recipe/converter/converters/RecipeConverter.kt @@ -30,13 +30,19 @@ import kotlin.io.path.readLines private const val VERSION_MAPPING = "version_mappings.txt" -private lateinit var agpToGradleMap: Map +data class VersionInfo( + val agp: String, + val gradle: String, + val kotlin: String +) + +private lateinit var agpToVersionsMap: Map private lateinit var maxAgp: String -fun getGradleFromAgp(branchRoot: Path, agp: String): String? { +fun getVersionsFromAgp(branchRoot: Path, agp: String): VersionInfo? { initAgpToGradleMap(branchRoot) - return agpToGradleMap[agp].also { + return agpToVersionsMap[agp].also { if (it == null) { - println(agpToGradleMap.entries) + println(agpToVersionsMap.entries) } } } @@ -48,7 +54,7 @@ fun getMaxAgp(branchRoot: Path): String { @Synchronized private fun initAgpToGradleMap(branchRoot: Path) { - if (!::agpToGradleMap.isInitialized) { + if (!::agpToVersionsMap.isInitialized) { val file = branchRoot.resolve(VERSION_MAPPING) if (!file.isRegularFile()) { throw RuntimeException("Missing AGP version mapping file at $file") @@ -59,23 +65,20 @@ private fun initAgpToGradleMap(branchRoot: Path) { .asSequence() .filter { !it.startsWith("#") } - agpToGradleMap = lines + agpToVersionsMap = lines .map { - val pair = it.split(";") - pair[0].toMajorMinor() to pair[1] + val values = it.split(";") + values[0].toMajorMinor() to VersionInfo( + agp = values[0], + gradle = values[1], + kotlin = values[2] + ) }.toMap() maxAgp = lines.map { it.split(";")[0] }.max() } } - -/** - * Current supported Kotlin plugin, later we add a - * CLI argument to support more versions - */ -const val kotlinPluginVersion = "2.0.0-Beta1" - /** * The compile SDK version for recipes */ @@ -96,7 +99,7 @@ class RecipeConverter( repoLocation: String?, gradleVersion: String?, gradlePath: String?, - mode: Mode, + private val mode: Mode, private val overwrite: Boolean, branchRoot: Path, private val generateWrapper: Boolean = true, @@ -134,7 +137,7 @@ class RecipeConverter( } Mode.SOURCE -> { - SourceConverter() + SourceConverter(branchRoot) } Mode.RELEASE -> { @@ -172,7 +175,7 @@ class RecipeConverter( ) val success = if (converter.isConversionCompliant(recipe)) { - converter.setRecipe(recipe) + converter.recipe = recipe Files.walkFileTree(source, object : SimpleFileVisitor() { @Throws(IOException::class) @@ -226,7 +229,7 @@ class RecipeConverter( } }) - if (generateWrapper) { + if (generateWrapper && mode != Mode.SOURCE) { converter.copyGradleFolder(destination) } diff --git a/convert-tool/app/src/main/kotlin/com/google/android/gradle_recipe/converter/converters/ReleaseConverter.kt b/convert-tool/app/src/main/kotlin/com/google/android/gradle_recipe/converter/converters/ReleaseConverter.kt index 3e7b14ae..2f1e6f78 100644 --- a/convert-tool/app/src/main/kotlin/com/google/android/gradle_recipe/converter/converters/ReleaseConverter.kt +++ b/convert-tool/app/src/main/kotlin/com/google/android/gradle_recipe/converter/converters/ReleaseConverter.kt @@ -17,11 +17,8 @@ package com.google.android.gradle_recipe.converter.converters import com.google.android.gradle_recipe.converter.recipe.Recipe -import java.io.File -import java.io.IOException import java.nio.file.Files import java.nio.file.Path -import kotlin.io.path.isDirectory import kotlin.io.path.writeLines /** This mode is for a recipe that has no placeholders. @@ -32,8 +29,8 @@ class ReleaseConverter( gradleVersion: String?, repoLocation: String?, gradlePath: String?, - private val branchRoot: Path, -) : Converter { + branchRoot: Path, +) : Converter(branchRoot) { private var pathToGradle: String = "" private var pathToAgpRepo: String = "" @@ -61,101 +58,57 @@ class ReleaseConverter( } override fun convertBuildGradle(source: Path, target: Path) { - val originalLines = Files.readAllLines(source) - val agpVersionReplaced = replaceGradlePlaceholdersWithInlineValue( - originalLines, - "\$AGP_VERSION", - "\"$agpVersion\"" - ) - - val kotlinAndAgpVersionReplaced = - replaceGradlePlaceholdersWithInlineValue( - agpVersionReplaced, + val convertedText = Files.readAllLines(source) + .replaceGradlePlaceholdersWithInlineValue( + "\$AGP_VERSION", + "\"$agpVersion\"" + ).replaceGradlePlaceholdersWithInlineValue( "\$KOTLIN_VERSION", - "\"$kotlinPluginVersion\"" - ) - - val kotlinAndAgpCompileSdkVersionReplaced = - replaceGradlePlaceholdersWithInlineValue( - kotlinAndAgpVersionReplaced, + "\"${getVersionInfoFromAgp(agpVersion).kotlin}\"" + ).replaceGradlePlaceholdersWithInlineValue( "\$COMPILE_SDK", - "$compileSdkVersion" - ) - - val kotlinAndAgpCompileSdkMinimumSdkVersionReplaced = - replaceGradlePlaceholdersWithInlineValue( - kotlinAndAgpCompileSdkVersionReplaced, + compileSdkVersion + ).replaceGradlePlaceholdersWithInlineValue( "\$MINIMUM_SDK", - "$minimumSdkVersion" + minimumSdkVersion ) - target.writeLines(kotlinAndAgpCompileSdkMinimumSdkVersionReplaced, Charsets.UTF_8) + target.writeLines(convertedText, Charsets.UTF_8) } override fun convertSettingsGradle(source: Path, target: Path) { - val originalLines = Files.readAllLines(source) - - val agpRepoConverted = - replacePlaceHolderWithLine( - originalLines, + val convertedText = Files.readAllLines(source) + .replacePlaceHolderWithLine( "\$AGP_REPOSITORY", "$pathToAgpRepo" - ) - - val agpAndPluginRepoConverted = replacePlaceHolderWithList( - agpRepoConverted, "\$PLUGIN_REPOSITORIES", + ).replacePlaceHolderWithList( + "\$PLUGIN_REPOSITORIES", pluginRepo - ) - - val agpAndPluginAndDependencyRepoConverted = replacePlaceHolderWithList( - agpAndPluginRepoConverted, "\$DEPENDENCY_REPOSITORIES", + ).replacePlaceHolderWithList( + "\$DEPENDENCY_REPOSITORIES", dependencyRepo ) - target.writeLines(agpAndPluginAndDependencyRepoConverted, Charsets.UTF_8) + target.writeLines(convertedText, Charsets.UTF_8) } override fun convertVersionCatalog(source: Path, target: Path) { - val originalLines = Files.readAllLines(source) - - val agpVersionReplaced = replaceVersionCatalogPlaceholders( - originalLines, - "\$AGP_VERSION", - "\"$agpVersion\"" - ) - - val kotlinAndAgpVersionReplaced = - replaceGradlePlaceholdersWithInlineValue( - agpVersionReplaced, + val convertedText = Files.readAllLines(source) + .replaceVersionCatalogPlaceholders( + "\$AGP_VERSION", + "\"$agpVersion\"" + ).replaceGradlePlaceholdersWithInlineValue( "\$KOTLIN_VERSION", - "\"$kotlinPluginVersion\"" + "\"${getVersionInfoFromAgp(agpVersion).kotlin}\"" ) - target.writeLines(kotlinAndAgpVersionReplaced, Charsets.UTF_8) - } - - override fun copyGradleFolder(dest: Path) { - val source = branchRoot.resolve(GRADLE_RESOURCES_FOLDER) - if (!source.isDirectory()) { - throw RuntimeException("Unable to find gradle resources at $source") - } - - dest.mkdirs() - - source.toFile().copyRecursively(target = dest.toFile()) - val gradleWrapperPropertiesPath = - dest.resolve("gradle").resolve("wrapper").resolve("gradle-wrapper.properties") - if (Files.exists(gradleWrapperPropertiesPath)) { - convertGradleWrapper(gradleWrapperPropertiesPath, gradleWrapperPropertiesPath) - } + target.writeLines(convertedText, Charsets.UTF_8) } - private fun convertGradleWrapper(source: Path, target: Path) { - val originalLines = Files.readAllLines(source) - val resultLines = replaceGradlePlaceholdersWithInlineValue( - originalLines, "\$GRADLE_LOCATION", "$pathToGradle" - ) + override fun processGradleWrapperProperties(file: Path) { + val resultLines = + Files.readAllLines(file).replaceGradlePlaceholdersWithInlineValue("\$GRADLE_LOCATION", pathToGradle) - target.writeLines(resultLines, Charsets.UTF_8) + file.writeLines(resultLines, Charsets.UTF_8) } } \ No newline at end of file diff --git a/convert-tool/app/src/main/kotlin/com/google/android/gradle_recipe/converter/converters/SourceConverter.kt b/convert-tool/app/src/main/kotlin/com/google/android/gradle_recipe/converter/converters/SourceConverter.kt index 7ccd8b8e..bd3d2e55 100644 --- a/convert-tool/app/src/main/kotlin/com/google/android/gradle_recipe/converter/converters/SourceConverter.kt +++ b/convert-tool/app/src/main/kotlin/com/google/android/gradle_recipe/converter/converters/SourceConverter.kt @@ -24,33 +24,20 @@ import kotlin.io.path.writeLines /** This mode has the placeholders ($AGP_VERSION etc') and * this is how we store the recipes in the dev branch */ -class SourceConverter : Converter { +class SourceConverter(branchRoot: Path) : Converter(branchRoot) { override fun isConversionCompliant(recipe: Recipe): Boolean { return true } override fun convertBuildGradle(source: Path, target: Path) { - val originalLines = Files.readAllLines(source) - val resultLines: List = unwrapGradlePlaceholders(originalLines) - - target.writeLines(resultLines, Charsets.UTF_8) + target.writeLines(Files.readAllLines(source).unwrapGradlePlaceholders(), Charsets.UTF_8) } override fun convertSettingsGradle(source: Path, target: Path) { - val originalLines = Files.readAllLines(source) - val resultLines: List = unwrapGradlePlaceholders(originalLines) - - target.writeLines(resultLines, Charsets.UTF_8) + target.writeLines(Files.readAllLines(source).unwrapGradlePlaceholders(), Charsets.UTF_8) } override fun convertVersionCatalog(source: Path, target: Path) { - val originalLines = Files.readAllLines(source) - val resultLines: List = unwrapVersionCatalogPlaceholders(originalLines) - - target.writeLines(resultLines, Charsets.UTF_8) - } - - override fun copyGradleFolder(dest: Path) { - + target.writeLines(Files.readAllLines(source).unwrapVersionCatalogPlaceholders(), Charsets.UTF_8) } } \ No newline at end of file diff --git a/convert-tool/app/src/main/kotlin/com/google/android/gradle_recipe/converter/converters/WorkingCopyConverter.kt b/convert-tool/app/src/main/kotlin/com/google/android/gradle_recipe/converter/converters/WorkingCopyConverter.kt index 5dca79ff..05ea9d58 100644 --- a/convert-tool/app/src/main/kotlin/com/google/android/gradle_recipe/converter/converters/WorkingCopyConverter.kt +++ b/convert-tool/app/src/main/kotlin/com/google/android/gradle_recipe/converter/converters/WorkingCopyConverter.kt @@ -17,145 +17,87 @@ package com.google.android.gradle_recipe.converter.converters import com.google.android.gradle_recipe.converter.recipe.Recipe -import com.google.android.gradle_recipe.converter.recipe.toMajorMinor import java.nio.file.Files import java.nio.file.Path -import kotlin.io.path.isDirectory import kotlin.io.path.writeLines /** * This is the working copy where the recipe has static values for $AGP_VERSION, etc... * but markers to revert them back to placeholders. */ -class WorkingCopyConverter( - private val branchRoot: Path, -) : Converter { - private var recipe: Recipe? = null +class WorkingCopyConverter(branchRoot: Path) : Converter(branchRoot) { + override fun isConversionCompliant(recipe: Recipe): Boolean { return true } - override fun setRecipe(recipe: Recipe) { - this.recipe = recipe - } - override fun convertBuildGradle(source: Path, target: Path) { val agpVersion = recipe?.minAgpVersion ?: error("min Agp version is badly specified in the metadata") - val originalLines = Files.readAllLines(source) - - val agpVersionWrapped = wrapGradlePlaceholdersWithInlineValue( - originalLines, "\$AGP_VERSION", "\"$agpVersion\"" - ) - val kotlinAndAgpVersionWrapped = - wrapGradlePlaceholdersWithInlineValue( - agpVersionWrapped, + val convertedText = Files.readAllLines(source) + .wrapGradlePlaceholdersWithInlineValue( + "\$AGP_VERSION", + "\"$agpVersion\"" + ).wrapGradlePlaceholdersWithInlineValue( "\$KOTLIN_VERSION", - "\"$kotlinPluginVersion\"" - ) - - val kotlinAndAgpCompileSdkVersionWrapped = - wrapGradlePlaceholdersWithInlineValue( - kotlinAndAgpVersionWrapped, + "\"${getVersionInfoFromAgp(agpVersion).kotlin}\"" + ).wrapGradlePlaceholdersWithInlineValue( "\$COMPILE_SDK", - "$compileSdkVersion" - ) - - val kotlinAndAgpCompileSdkMinimumSdkVersionWrapped = - wrapGradlePlaceholdersWithInlineValue( - kotlinAndAgpCompileSdkVersionWrapped, + compileSdkVersion + ).wrapGradlePlaceholdersWithInlineValue( "\$MINIMUM_SDK", - "$minimumSdkVersion" + minimumSdkVersion ) - target.writeLines( - kotlinAndAgpCompileSdkMinimumSdkVersionWrapped, - Charsets.UTF_8 - ) + target.writeLines(convertedText, Charsets.UTF_8) } override fun convertSettingsGradle(source: Path, target: Path) { - val originalLines = Files.readAllLines(source) - - val agpConverted = wrapGradlePlaceholdersWithInlineValue( - originalLines, - "\$AGP_REPOSITORY", - "" - ) - val agpAndPluginRepoConverted = wrapGradlePlaceholdersWithList( - agpConverted, "\$PLUGIN_REPOSITORIES", - listOf( - " gradlePluginPortal()", - " google()", - " mavenCentral()" - ) - ) - - val agpAndPluginRepoAndDepsRepoConverted = - wrapGradlePlaceholdersWithList( - agpAndPluginRepoConverted, "\$DEPENDENCY_REPOSITORIES", + val convertedText = Files.readAllLines(source) + .wrapGradlePlaceholdersWithInlineValue( + "\$AGP_REPOSITORY", + "" + ).wrapGradlePlaceholdersWithList( + "\$PLUGIN_REPOSITORIES", + listOf( + " gradlePluginPortal()", + " google()", + " mavenCentral()" + ) + ).wrapGradlePlaceholdersWithList( + "\$DEPENDENCY_REPOSITORIES", listOf(" google()", " mavenCentral()") ) - target.writeLines(agpAndPluginRepoAndDepsRepoConverted, Charsets.UTF_8) + target.writeLines(convertedText, Charsets.UTF_8) } override fun convertVersionCatalog(source: Path, target: Path) { - val agpVersion = recipe?.minAgpVersion - ?: error("min Agp version is badly specified in the metadata") - val originalLines = Files.readAllLines(source) - - val agpVersionWrapped = wrapVersionCatalogPlaceholders( - originalLines, - "\$AGP_VERSION", - "\"$agpVersion\"" - ) + val agpVersion = getMinAgp() - val kotlinAndAgpVersionWrapped = - wrapVersionCatalogPlaceholders( - agpVersionWrapped, + val convertedText = Files.readAllLines(source) + .wrapVersionCatalogPlaceholders( + "\$AGP_VERSION", + "\"$agpVersion\"" + ).wrapVersionCatalogPlaceholders( "\$KOTLIN_VERSION", - "\"$kotlinPluginVersion\"" + "\"${getVersionInfoFromAgp(agpVersion).kotlin}\"" ) - target.writeLines(kotlinAndAgpVersionWrapped, Charsets.UTF_8) + target.writeLines(convertedText, Charsets.UTF_8) } - override fun copyGradleFolder(dest: Path) { - val source = branchRoot.resolve(GRADLE_RESOURCES_FOLDER) - if (!source.isDirectory()) { - throw RuntimeException("Unable to find gradle resources at $source") - } - - dest.mkdirs() - - source.toFile().copyRecursively(target = dest.toFile()) - - convertGradleWrapper( - dest.resolve("gradle").resolve("wrapper") - .resolve("gradle-wrapper.properties"), - dest.resolve("gradle").resolve("wrapper") - .resolve("gradle-wrapper.properties") - ) - } - - private fun convertGradleWrapper(source: Path, target: Path) { + override fun processGradleWrapperProperties(file: Path) { // building the line // distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-bin.zip - val agpVersion = recipe?.minAgpVersion - ?: error("min Agp version is badly specified in the metadata") - - val agpVersionMajorMinor = agpVersion.toMajorMinor() - val gradleVersion = getGradleFromAgp(branchRoot, agpVersionMajorMinor) - ?: error("Can't deduce the gradle version from the recipe metadata") - - val originalLines = Files.readAllLines(source) - val resultLines = wrapGradleWrapperPlaceholders( - originalLines, - "\$GRADLE_LOCATION", - "https\\://services.gradle.org/distributions/gradle-$gradleVersion-bin.zip" + file.writeLines( + Files.readAllLines(file) + .wrapGradleWrapperPlaceholders( + "\$GRADLE_LOCATION", + "https\\://services.gradle.org/distributions/gradle-${getVersionInfoFromAgp(getMinAgp()).gradle}-bin.zip" + ), + Charsets.UTF_8 ) - target.writeLines(resultLines, Charsets.UTF_8) } } \ No newline at end of file diff --git a/convert-tool/app/src/main/kotlin/com/google/android/gradle_recipe/converter/validators/MinMaxCurrentAgpValidator.kt b/convert-tool/app/src/main/kotlin/com/google/android/gradle_recipe/converter/validators/MinMaxCurrentAgpValidator.kt index 551d214c..efb962a2 100644 --- a/convert-tool/app/src/main/kotlin/com/google/android/gradle_recipe/converter/validators/MinMaxCurrentAgpValidator.kt +++ b/convert-tool/app/src/main/kotlin/com/google/android/gradle_recipe/converter/validators/MinMaxCurrentAgpValidator.kt @@ -18,8 +18,8 @@ package com.google.android.gradle_recipe.converter.validators import com.google.android.gradle_recipe.converter.converters.RecipeConverter import com.google.android.gradle_recipe.converter.converters.RecipeConverter.Mode -import com.google.android.gradle_recipe.converter.converters.getGradleFromAgp import com.google.android.gradle_recipe.converter.converters.getMaxAgp +import com.google.android.gradle_recipe.converter.converters.getVersionsFromAgp import com.google.android.gradle_recipe.converter.recipe.RecipeMetadataParser import com.google.android.gradle_recipe.converter.recipe.toMajorMinor import java.nio.file.Path @@ -48,7 +48,7 @@ class MinMaxCurrentAgpValidator( from: Path, agpVersion: String, ) { - val gradleVersion = getGradleFromAgp(branchRoot, agpVersion.toMajorMinor()) + val gradleVersion = getVersionsFromAgp(branchRoot, agpVersion.toMajorMinor())?.gradle ?: throw RuntimeException("Unable to find Gradle version for AGP version $agpVersion - Make sure it's present in version_mappings.txt") val recipeConverter = RecipeConverter( diff --git a/recipes.bzl b/recipes.bzl index 3b3750b2..6e27b53b 100644 --- a/recipes.bzl +++ b/recipes.bzl @@ -15,38 +15,62 @@ def recipe_test( """ # Test scenarios keyed by AGP version. Keep in chronological order, with "ToT" (tip of tree) last. + test_scenarios = { "8.1.0": { "name": name + "_8_1_0", - "gradle_path": "$(location //tools/base/build-system:gradle-distrib-8.1)", - "manifest_repos": ["//tools/base/build-system/previous-versions:8.1.0"], + "gradle_path": "$(location //tools/base/build-system:gradle-distrib-8.0)", + "manifest_repos": [ + "//tools/base/build-system/previous-versions:8.1.0", + ":kotlin_1_8_10", + ], "zip_repos": [], "data": [ "//prebuilts/studio/sdk:build-tools/33.0.1", "//tools/base/build-system:android_platform_for_tests", - "//tools/base/build-system:gradle-distrib-8.1", + "//tools/base/build-system:gradle-distrib-8.0", + "version_mappings.txt", + ], + }, + "8.2.0": { + "name": name + "_8_2_0", + "gradle_path": "$(location //tools/base/build-system:gradle-distrib-8.2)", + "manifest_repos": [ + "//tools/base/build-system/previous-versions:8.2.0", + ":kotlin_1_8_10", + ], + "zip_repos": [], + "data": [ + "//prebuilts/studio/sdk:build-tools/34.0.0", + "//tools/base/build-system:android_platform_for_tests", + "//tools/base/build-system:gradle-distrib-8.2", "version_mappings.txt", ], }, "ToT": { "name": name, "gradle_path": "$(location //tools/base/build-system:gradle-distrib)", - "manifest_repos": [], + "manifest_repos": [ + "//tools/base/build-system/integration-test:kotlin_gradle_plugin_prebuilts", + ":kotlin_1_9_20", + ], "zip_repos": ["//tools/base/build-system:android_gradle_plugin"], "data": [ "//prebuilts/studio/sdk:build-tools/33.0.1", "//prebuilts/studio/sdk:build-tools/latest", "//tools/base/build-system:android_platform_for_tests", "//tools/base/build-system:gradle-distrib", + "//tools/base/build-system:gradle-distrib-8.0", "//tools/base/build-system:gradle-distrib-8.1", + "//tools/base/build-system:gradle-distrib-8.2", "version_mappings.txt", + ":kotlin_1_8_10", ], }, } for agp_version in test_scenarios: manifest_repos = [ - "//tools/base/build-system/integration-test:kotlin_gradle_plugin_prebuilts", "//tools/base/build-system:android_gradle_plugin_runtime_dependencies", ] + test_scenarios[agp_version]["manifest_repos"] zip_repos = test_scenarios[agp_version]["zip_repos"] diff --git a/version_mappings.txt b/version_mappings.txt index 6cba1aec..e1b02bf1 100644 --- a/version_mappings.txt +++ b/version_mappings.txt @@ -1,6 +1,7 @@ -# mapping of AGP versions to Gradle Versions, separated by ';' -# Note: For AGP 8.1, minimum required Gradle version is 8.0, but because of -# https://github.com/gradle/gradle/issues/21436, we need to use Gradle 8.1 to be able to run against -# KGP 2.0+. -8.1.0;8.1 -8.2.0;8.2 +# mapping of AGP versions to Gradle and Kotlin Versions, separated by ';' +8.1.0;8.0;1.8.10 +8.2.0;8.2;1.8.10 +# wait until we have beta1 in the previous version +#8.3.0-beta01;8.4;1.9.20 +8.4.0-alpha01;8.4;1.9.20 +#8.4.0-alpha01;8.4;2.0.0-Beta1