From 3a3c31b425bd97ddcd9db883ff808429880ff5c3 Mon Sep 17 00:00:00 2001 From: Guillermo Mazzola Date: Fri, 20 Jan 2023 17:17:59 +0100 Subject: [PATCH] Fixed configuration cache compatibility on AGP 7.4.0 --- gradle/libs.versions.toml | 2 +- .../codeowners/CodeOwnersPluginITest.kt | 14 ++++---- .../resources/project/build.gradle.kts | 2 +- .../gmazzo/codeowners/CodeOwnersPlugin.kt | 33 ++++++++----------- .../gmazzo/codeowners/CodeOwnersSourceSet.kt | 4 +-- .../codeowners/CodeOwnersSourceSetImpl.kt | 6 ++-- .../gmazzo/codeowners/CodeOwnersTask.kt | 32 +++++++++--------- 7 files changed, 44 insertions(+), 49 deletions(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 73ab32e..f79bcf9 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -9,7 +9,7 @@ junit-params = { module = "org.junit.jupiter:junit-jupiter-params", version = "j kotlin-test = { module = "org.jetbrains.kotlin:kotlin-test", version.ref = "kotlin" } [plugins] -android = "com.android.application:7.3.1" +android = "com.android.application:7.4.0" buildConfig = "com.github.gmazzo.buildconfig:3.1.0" kotlin = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" } dokka = { id = "org.jetbrains.dokka", version.ref = "kotlin" } diff --git a/plugin/src/integrationTest/kotlin/io/github/gmazzo/codeowners/CodeOwnersPluginITest.kt b/plugin/src/integrationTest/kotlin/io/github/gmazzo/codeowners/CodeOwnersPluginITest.kt index 30de334..6123832 100644 --- a/plugin/src/integrationTest/kotlin/io/github/gmazzo/codeowners/CodeOwnersPluginITest.kt +++ b/plugin/src/integrationTest/kotlin/io/github/gmazzo/codeowners/CodeOwnersPluginITest.kt @@ -53,7 +53,7 @@ class CodeOwnersPluginITest { assertEquals(TaskOutcome.UP_TO_DATE, build.task(":lib1:generateCodeOwnersResources")?.outcome) assertEquals(null, build.task(":lib1:generateTestCodeOwnersResources")?.outcome) - assertEquals(TaskOutcome.SKIPPED, build.task(":lib1:generateIntegrationTestCodeOwnersResources")?.outcome) + assertEquals(TaskOutcome.NO_SOURCE, build.task(":lib1:generateIntegrationTestCodeOwnersResources")?.outcome) lib1BuildPasses = true } @@ -63,9 +63,9 @@ class CodeOwnersPluginITest { fun `lib2 tests passes`() { val build = runBuild(":lib2:test") - assertEquals(TaskOutcome.SKIPPED, build.task(":lib2:generateDebugCodeOwnersResources")?.outcome) + assertEquals(TaskOutcome.NO_SOURCE, build.task(":lib2:generateDebugCodeOwnersResources")?.outcome) assertEquals(null, build.task(":lib2:generateDebugUnitTestCodeOwnersResources")?.outcome) - assertEquals(TaskOutcome.SKIPPED, build.task(":lib2:generateReleaseCodeOwnersResources")?.outcome) + assertEquals(TaskOutcome.NO_SOURCE, build.task(":lib2:generateReleaseCodeOwnersResources")?.outcome) assertEquals(null, build.task(":lib2:generateReleaseUnitTestCodeOwnersResources")?.outcome) lib2TestPasses = true @@ -77,10 +77,10 @@ class CodeOwnersPluginITest { fun `lib2 builds successfully`() { val build = runBuild(":lib2:build", ":lib2:packageDebugAndroidTest") - assertEquals(TaskOutcome.SKIPPED, build.task(":lib2:generateDebugCodeOwnersResources")?.outcome) + assertEquals(TaskOutcome.NO_SOURCE, build.task(":lib2:generateDebugCodeOwnersResources")?.outcome) assertEquals(null, build.task(":lib2:generateDebugUnitTestCodeOwnersResources")?.outcome) - assertEquals(TaskOutcome.SKIPPED, build.task(":lib2:generateDebugAndroidTestCodeOwnersResources")?.outcome) - assertEquals(TaskOutcome.SKIPPED, build.task(":lib2:generateReleaseCodeOwnersResources")?.outcome) + assertEquals(TaskOutcome.NO_SOURCE, build.task(":lib2:generateDebugAndroidTestCodeOwnersResources")?.outcome) + assertEquals(TaskOutcome.NO_SOURCE, build.task(":lib2:generateReleaseCodeOwnersResources")?.outcome) assertEquals(null, build.task(":lib2:generateReleaseUnitTestCodeOwnersResources")?.outcome) lib2BuildPasses = true @@ -122,7 +122,7 @@ class CodeOwnersPluginITest { assertEquals(TaskOutcome.FROM_CACHE, build.task(":app:generateDebugCodeOwnersResources")?.outcome) assertEquals(TaskOutcome.FROM_CACHE, build.task(":lib1:generateCodeOwnersResources")?.outcome) - assertEquals(TaskOutcome.SKIPPED, build.task(":lib2:generateDebugCodeOwnersResources")?.outcome) + assertEquals(TaskOutcome.NO_SOURCE, build.task(":lib2:generateDebugCodeOwnersResources")?.outcome) } } diff --git a/plugin/src/integrationTest/resources/project/build.gradle.kts b/plugin/src/integrationTest/resources/project/build.gradle.kts index 2b7abfc..0fb4219 100644 --- a/plugin/src/integrationTest/resources/project/build.gradle.kts +++ b/plugin/src/integrationTest/resources/project/build.gradle.kts @@ -3,7 +3,7 @@ plugins { if (pluginsClasspath == null) { // meant to allow open this test project as a standalone project - id("com.android.application") version "7.3.1" apply false + id("com.android.application") version "7.4.0" apply false kotlin("jvm") version "1.7.21" apply false id("io.github.gmazzo.codeowners") version "0.0.0-SNAPSHOT" diff --git a/plugin/src/main/kotlin/io/github/gmazzo/codeowners/CodeOwnersPlugin.kt b/plugin/src/main/kotlin/io/github/gmazzo/codeowners/CodeOwnersPlugin.kt index 86f2885..11ddb42 100644 --- a/plugin/src/main/kotlin/io/github/gmazzo/codeowners/CodeOwnersPlugin.kt +++ b/plugin/src/main/kotlin/io/github/gmazzo/codeowners/CodeOwnersPlugin.kt @@ -70,8 +70,6 @@ class CodeOwnersPlugin : Plugin { private fun Project.createSourceSets( extension: CodeOwnersExtension, ) = objects.domainObjectContainer(CodeOwnersSourceSet::class) { name -> - val ss = objects.sourceDirectorySet(name, "$name codeOwners sources") - val prefix = when (name) { SourceSet.MAIN_SOURCE_SET_NAME -> "" else -> name.capitalize() @@ -80,13 +78,10 @@ class CodeOwnersPlugin : Plugin { val generateTask = tasks.register("generate${prefix}CodeOwnersResources") { codeOwners.value(extension.codeOwners) rootDirectory.value(extension.rootDirectory) - sources.from(ss) + outputDirectory.value(layout.buildDirectory.dir("generated/codeOwners/$name")) } - ss.destinationDirectory.value(layout.buildDirectory.dir("generated/codeOwners/${ss.name}")) - ss.compiledBy(generateTask, CodeOwnersTask::outputDirectory) - - objects.newInstance(ss, generateTask).apply { + objects.newInstance(name, generateTask).apply { enabled.convention(true).finalizeValueOnRead() } } @@ -95,15 +90,15 @@ class CodeOwnersPlugin : Plugin { sourceSets: NamedDomainObjectContainer, ) = plugins.withId("java-base") { the().configureEach { ss -> - val sources = sourceSets.maybeCreate(ss.name) - sources.source(ss.allJava) - sources.generateTask { + val extension = sourceSets.maybeCreate(ss.name) + extension.generateTask { + sources.from(provider { ss.allJava.srcDirs }) // will contain srcDirs of groovy, kotlin, etc. too runtimeClasspath.from(configurations[ss.runtimeClasspathConfigurationName].codeOwners) } addCodeDependency(ss.implementationConfigurationName) - ss.extensions.add(CodeOwnersSourceSet::class.java, extensionName, sources) - tasks.named(ss.processResourcesTaskName).addResources(sources) + ss.extensions.add(CodeOwnersSourceSet::class.java, extensionName, extension) + tasks.named(ss.processResourcesTaskName).addResources(extension) } } @@ -116,9 +111,9 @@ class CodeOwnersPlugin : Plugin { component: Component, defaultsTo: CodeOwnersSourceSet? = null, ): CodeOwnersSourceSet { - val sources = sourceSets.maybeCreate(component.name).also(component::codeOwners.setter) - sources.srcDir(listOfNotNull(component.sources.java?.all, component.sources.kotlin?.all)) - sources.generateTask { + val extension = sourceSets.maybeCreate(component.name).also(component::codeOwners.setter) + extension.generateTask { + sources.from(component.sources.java?.all, component.sources.kotlin?.all) runtimeClasspath.from(component.runtimeConfiguration.codeOwners) } addCodeDependency(component.compileConfiguration.name) @@ -127,16 +122,16 @@ class CodeOwnersPlugin : Plugin { // TODO there is no `variant.sources.resources.addGeneratedSourceDirectory` DSL for this? afterEvaluate { tasks.named("process${component.name.capitalize()}JavaRes") - .addResources(sources) + .addResources(extension) } if (defaultsTo != null) { - sources.enabled.convention(defaultsTo.enabled) + extension.enabled.convention(defaultsTo.enabled) } - return sources + return extension } - androidComponents.onVariants { variant -> + androidComponents.onVariants(androidComponents.selector().all()) { variant -> variant.packaging.resources.merges.add("**/*.codeowners") val sources = bind(variant) diff --git a/plugin/src/main/kotlin/io/github/gmazzo/codeowners/CodeOwnersSourceSet.kt b/plugin/src/main/kotlin/io/github/gmazzo/codeowners/CodeOwnersSourceSet.kt index 3fb7b19..9b98eab 100644 --- a/plugin/src/main/kotlin/io/github/gmazzo/codeowners/CodeOwnersSourceSet.kt +++ b/plugin/src/main/kotlin/io/github/gmazzo/codeowners/CodeOwnersSourceSet.kt @@ -1,10 +1,10 @@ package io.github.gmazzo.codeowners -import org.gradle.api.file.SourceDirectorySet +import org.gradle.api.Named import org.gradle.api.provider.Property import org.gradle.api.tasks.TaskProvider -interface CodeOwnersSourceSet : SourceDirectorySet { +interface CodeOwnersSourceSet : Named { /** * If it should compute the code owners for this source set diff --git a/plugin/src/main/kotlin/io/github/gmazzo/codeowners/CodeOwnersSourceSetImpl.kt b/plugin/src/main/kotlin/io/github/gmazzo/codeowners/CodeOwnersSourceSetImpl.kt index 32445e1..a135d4c 100644 --- a/plugin/src/main/kotlin/io/github/gmazzo/codeowners/CodeOwnersSourceSetImpl.kt +++ b/plugin/src/main/kotlin/io/github/gmazzo/codeowners/CodeOwnersSourceSetImpl.kt @@ -1,11 +1,11 @@ package io.github.gmazzo.codeowners -import org.gradle.api.file.SourceDirectorySet +import org.gradle.api.Named import org.gradle.api.tasks.TaskProvider import javax.inject.Inject internal abstract class CodeOwnersSourceSetImpl @Inject constructor( - sources: SourceDirectorySet, + name: String, override val generateTask: TaskProvider, ) : CodeOwnersSourceSet, - SourceDirectorySet by sources + Named by (Named { name }) diff --git a/plugin/src/main/kotlin/io/github/gmazzo/codeowners/CodeOwnersTask.kt b/plugin/src/main/kotlin/io/github/gmazzo/codeowners/CodeOwnersTask.kt index fc8c979..c7e811b 100644 --- a/plugin/src/main/kotlin/io/github/gmazzo/codeowners/CodeOwnersTask.kt +++ b/plugin/src/main/kotlin/io/github/gmazzo/codeowners/CodeOwnersTask.kt @@ -6,7 +6,6 @@ import org.gradle.api.file.ConfigurableFileCollection import org.gradle.api.file.DirectoryProperty import org.gradle.api.file.FileTree import org.gradle.api.provider.Property -import org.gradle.api.provider.SetProperty import org.gradle.api.tasks.* import java.io.File @@ -17,12 +16,27 @@ abstract class CodeOwnersTask : DefaultTask() { @get:Internal abstract val rootDirectory: DirectoryProperty + /** + * Helper input to declare that we only care about paths and not file contents on [rootDirectory] and [sources] + * + * [Incorrect use of the `@Input` annotation](https://docs.gradle.org/7.6/userguide/validation_problems.html#incorrect_use_of_input_annotation) + */ + @get:Input + internal val rootDirectoryPath = + rootDirectory.map { it.asFile.toRelativeString(project.rootDir) } + @get:Input abstract val codeOwners: Property @get:Internal abstract val sources: ConfigurableFileCollection + @get:InputFiles + @get:PathSensitive(PathSensitivity.RELATIVE) + @get:IgnoreEmptyDirectories + @get:SkipWhenEmpty + internal val sourcesFiles: FileTree = sources.asFileTree + @get:Internal abstract val runtimeClasspath: ConfigurableFileCollection @@ -35,22 +49,8 @@ abstract class CodeOwnersTask : DefaultTask() { @get:OutputDirectory abstract val outputDirectory: DirectoryProperty - /** - * Helper input to declare that we only care about paths and not file contents on [rootDirectory] and [sources] - * - * [Incorrect use of the `@Input` annotation](https://docs.gradle.org/7.6/userguide/validation_problems.html#incorrect_use_of_input_annotation) - */ - @get:Input - internal abstract val sourcesPaths: SetProperty - init { outputDirectory.convention(project.layout.dir(project.provider { temporaryDir })) - - sourcesPaths.add(rootDirectory.map { it.asFile.toRelativeString(project.rootDir) }) - sourcesPaths.addAll(sources.asFileTree.asSequence().map { it.toRelativeString(project.rootDir) }.asIterable()) - sourcesPaths.disallowChanges() - - onlyIf { !sources.isEmpty } } @TaskAction @@ -79,7 +79,7 @@ abstract class CodeOwnersTask : DefaultTask() { // process all files/directories and sets their owners logger.info("Processing sources...") - sources.asFileTree.visit { + sourcesFiles.visit { val rootPath = it.file.toRelativeString(root) val (owners) = entries.find { (_, ignore) -> ignore.isMatch(rootPath, it.isDirectory) } ?: return@visit val targetPath =