From e0857767880a4e482bfd9f18a2bcb197c144a3fe Mon Sep 17 00:00:00 2001 From: "Rodrigo B. de Oliveira" Date: Fri, 14 Dec 2018 15:09:33 -0200 Subject: [PATCH 001/853] Document `PrecompiledScriptPlugins` Including how to control the target and id of a precompiled script plugin. --- .../precompiled/PrecompiledScriptPlugins.kt | 68 ++++++++++++++++++- 1 file changed, 67 insertions(+), 1 deletion(-) diff --git a/subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPlugins.kt b/subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPlugins.kt index 35c70b691ede1..46499cde0e01a 100644 --- a/subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPlugins.kt +++ b/subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPlugins.kt @@ -18,6 +18,9 @@ package org.gradle.kotlin.dsl.plugins.precompiled import org.gradle.api.Plugin import org.gradle.api.Project import org.gradle.api.file.SourceDirectorySet +import org.gradle.api.initialization.Settings +import org.gradle.api.invocation.Gradle + import org.gradle.api.tasks.SourceSet import org.gradle.api.tasks.SourceSetContainer @@ -40,8 +43,71 @@ import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet import org.jetbrains.kotlin.gradle.tasks.KotlinCompile -/* +/** * Exposes `*.gradle.kts` scripts from regular Kotlin source-sets as binary Gradle plugins. + * + * ## Defining the plugin target + * + * Precompiled script plugins can target one of the following Gradle model types, [Gradle], [Settings] or [Project]. + * + * The target of a given script plugin is defined via its file name suffix in the following manner: + * - the `.init.gradle.kts` file name suffix defines a [Gradle] script plugin + * - the `.settings.gradle.kts` file name suffix defines a [Settings] script plugin + * - and finally, the simpler `.gradle.kts` file name suffix defines a [Project] script plugin + * + * ## Definining the plugin id + * + * The Gradle plugin id for a precompiled script plugin is defined via its file name + * plus optional package declaration in the following manner: + * - for a script without a package declaration, the plugin id is simply the file name without the + * related plugin target suffix (see above) + * - for a script containing a package declaration, the plugin id is the declared package name dot the file name without the + * related plugin target suffix (see above) + * + * For a concrete example, take the definition of a precompiled [Project] script plugin id of + * `my.project.plugin`. Given the two rules above, there are two conventional ways to do it: + * * by naming the script `my.project.plugin.gradle.kts` and including no package declaration + * * by naming the script `plugin.gradle.kts` and including a package declaration of `my.project`: + * ```kotlin + * // plugin.gradle.kts + * package my.project + * + * // ... plugin implementation ... + * ``` + * ## Applying plugins + * Precompiled script plugins can apply plugins much in the same way as regular scripts can, using one + * of the many `apply` method overloads or, in the case of [Project] scripts, via the `plugins` block. + * + * And just as regular [Project] scripts can take advantage of + * [type-safe model accessors](https://docs.gradle.org/current/userguide/kotlin_dsl.html#type-safe-accessors) + * to model elements contributed by plugins applied via the `plugins` block, so can precompiled [Project] script plugins: + * ```kotlin + * + * // java7-project.gradle.kts + * + * plugins { + * java + * } + * + * java { // type-safe model accessor to the `java` extension contributed by the `java` plugin + * sourceCompatibility = JavaVersion.VERSION_1_7 + * targetCompatibility = JavaVersion.VERSION_1_7 + * } + * + * ``` + * ## Implementation Notes + * External plugin dependencies are declared as regular artifact dependencies but a more + * semantic preserving model could be introduced in the future. + * ## Todo + * - [ ] type-safe plugin spec accessors for plugins in the precompiled script plugin classpath + * - [ ] limit the set of type-safe accessors visible to a precompiled script plugin to + * those provided by the plugins in its `plugins` block + * - [ ] each set of accessors would be emitted to an internal object to avoid conflicts with + * external plugins + * - [ ] an internal object named against its precompiled script plugin would also let users + * know not to import them + * - [ ] emit error when a precompiled script plugin includes the version of a in its `plugins` block + * - [ ] validate plugin ids against declared plugin dependencies */ class PrecompiledScriptPlugins : Plugin { From c7ccdd8e2ebfc42a9ad94b84720e0e6497ea9132 Mon Sep 17 00:00:00 2001 From: "Rodrigo B. de Oliveira" Date: Tue, 18 Dec 2018 18:17:55 -0200 Subject: [PATCH 002/853] Extract `AbstractPrecompiledScriptPluginTest` test superclass --- .../AbstractPrecompiledScriptPluginTest.kt | 68 +++++++++++++++++++ .../PrecompiledScriptPluginTest.kt | 45 +----------- 2 files changed, 69 insertions(+), 44 deletions(-) create mode 100644 subprojects/plugins/src/test/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/AbstractPrecompiledScriptPluginTest.kt diff --git a/subprojects/plugins/src/test/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/AbstractPrecompiledScriptPluginTest.kt b/subprojects/plugins/src/test/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/AbstractPrecompiledScriptPluginTest.kt new file mode 100644 index 0000000000000..cdaa6552efba8 --- /dev/null +++ b/subprojects/plugins/src/test/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/AbstractPrecompiledScriptPluginTest.kt @@ -0,0 +1,68 @@ +/* + * Copyright 2018 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.kotlin.dsl.plugins.precompiled + +import org.gradle.kotlin.dsl.fixtures.AbstractPluginTest +import org.gradle.kotlin.dsl.fixtures.classLoaderFor + +import org.gradle.testkit.runner.TaskOutcome + +import org.hamcrest.CoreMatchers.equalTo +import org.hamcrest.MatcherAssert.assertThat + + +open class AbstractPrecompiledScriptPluginTest : AbstractPluginTest() { + + protected + fun givenPrecompiledKotlinScript(fileName: String, code: String) { + withKotlinDslPlugin() + withFile("src/main/kotlin/$fileName", code) + compileKotlin() + } + + protected inline fun instantiatePrecompiledScriptOf(target: T, className: String): Any = + loadCompiledKotlinClass(className) + .getConstructor(T::class.java) + .newInstance(target) + + protected + fun loadCompiledKotlinClass(className: String): Class<*> = + classLoaderFor(existing("build/classes/kotlin/main")) + .loadClass(className) + + protected + fun withKotlinDslPlugin() = + withBuildScript(scriptWithKotlinDslPlugin()) + + protected + fun scriptWithKotlinDslPlugin(): String = + """ + plugins { + `kotlin-dsl` + } + + $repositoriesBlock + """ + + protected + fun compileKotlin() { + assertThat( + buildWithPlugin("classes").outcomeOf(":compileKotlin"), + equalTo(TaskOutcome.SUCCESS) + ) + } +} diff --git a/subprojects/plugins/src/test/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPluginTest.kt b/subprojects/plugins/src/test/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPluginTest.kt index 1d5a862583131..04c3317ae9321 100644 --- a/subprojects/plugins/src/test/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPluginTest.kt +++ b/subprojects/plugins/src/test/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPluginTest.kt @@ -13,19 +13,15 @@ import org.gradle.api.invocation.Gradle import org.gradle.api.tasks.TaskContainer import org.gradle.api.tasks.bundling.Jar -import org.gradle.kotlin.dsl.fixtures.AbstractPluginTest import org.gradle.kotlin.dsl.fixtures.assertFailsWith import org.gradle.kotlin.dsl.fixtures.assertInstanceOf import org.gradle.kotlin.dsl.fixtures.assertStandardOutputOf -import org.gradle.kotlin.dsl.fixtures.classLoaderFor import org.gradle.kotlin.dsl.fixtures.withFolders import org.gradle.kotlin.dsl.precompile.PrecompiledInitScript import org.gradle.kotlin.dsl.precompile.PrecompiledProjectScript import org.gradle.kotlin.dsl.precompile.PrecompiledSettingsScript -import org.gradle.testkit.runner.TaskOutcome - import org.hamcrest.CoreMatchers.allOf import org.hamcrest.CoreMatchers.containsString import org.hamcrest.CoreMatchers.equalTo @@ -34,7 +30,7 @@ import org.hamcrest.MatcherAssert.assertThat import org.junit.Test -class PrecompiledScriptPluginTest : AbstractPluginTest() { +class PrecompiledScriptPluginTest : AbstractPrecompiledScriptPluginTest() { @Test fun `Project scripts from regular source-sets are compiled via the PrecompiledProjectScript template`() { @@ -353,43 +349,4 @@ class PrecompiledScriptPluginTest : AbstractPluginTest() { ) } } - - private - fun givenPrecompiledKotlinScript(fileName: String, code: String) { - withKotlinDslPlugin() - withFile("src/main/kotlin/$fileName", code) - compileKotlin() - } - - private - inline fun instantiatePrecompiledScriptOf(target: T, className: String): Any = - loadCompiledKotlinClass(className) - .getConstructor(T::class.java) - .newInstance(target) - - private - fun loadCompiledKotlinClass(className: String) = - classLoaderFor(existing("build/classes/kotlin/main")) - .loadClass(className) - - private - fun withKotlinDslPlugin() = - withBuildScript(scriptWithKotlinDslPlugin()) - - private - fun scriptWithKotlinDslPlugin(): String = - """ - plugins { - `kotlin-dsl` - } - - $repositoriesBlock - """ - - private - fun compileKotlin() { - assertThat( - buildWithPlugin("classes").outcomeOf(":compileKotlin"), - equalTo(TaskOutcome.SUCCESS)) - } } From b7c7d0bab8a14da4b535c237e6435d1cf867dea4 Mon Sep 17 00:00:00 2001 From: "Rodrigo B. de Oliveira" Date: Tue, 18 Dec 2018 18:19:08 -0200 Subject: [PATCH 003/853] Polish `PrecompiledScriptPlugin` Group task operations into a `tasks` block in preparation to introducing new tasks. --- .../precompiled/PrecompiledScriptPlugins.kt | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPlugins.kt b/subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPlugins.kt index 46499cde0e01a..3c8f54fb26427 100644 --- a/subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPlugins.kt +++ b/subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPlugins.kt @@ -212,13 +212,16 @@ fun Project.generatePluginAdaptersFor(scriptPlugins: List) { val generatedSourcesDir = layout.buildDirectory.dir("generated-sources/kotlin-dsl-plugins/kotlin") sourceSets["main"].kotlin.srcDir(generatedSourcesDir) - val generateScriptPluginAdapters by tasks.registering(GenerateScriptPluginAdapters::class) { - plugins = scriptPlugins - outputDirectory.set(generatedSourcesDir) - } + tasks { + + val generateScriptPluginAdapters by registering(GenerateScriptPluginAdapters::class) { + plugins = scriptPlugins + outputDirectory.set(generatedSourcesDir) + } - tasks.named("compileKotlin") { - it.dependsOn(generateScriptPluginAdapters) + "compileKotlin" { + dependsOn(generateScriptPluginAdapters) + } } } From 6f0f9216fc0f22a64d7fe1fd3095287a48227b18 Mon Sep 17 00:00:00 2001 From: "Rodrigo B. de Oliveira" Date: Thu, 20 Dec 2018 18:04:40 -0200 Subject: [PATCH 004/853] Emit type-safe accessors for plugins in the compile classpath --- .../precompiled/GeneratePluginSpecBuilders.kt | 85 +++++ .../precompiled/PrecompiledScriptPlugins.kt | 30 +- .../AbstractPrecompiledScriptPluginTest.kt | 14 +- .../PrecompiledScriptPluginAccessorsTest.kt | 118 ++++++ subprojects/provider/provider.gradle.kts | 2 +- .../dsl/accessors/AccessorsClassPath.kt | 8 +- .../dsl/accessors/PluginAccessorsClassPath.kt | 131 ++++--- .../org/gradle/kotlin/dsl/concurrent/IO.kt | 12 + .../dsl/provider/KotlinScriptEvaluator.kt | 4 +- .../org/gradle/kotlin/dsl/support/zip.kt | 4 +- .../accessors/PluginAccessorsClassPathTest.kt | 25 +- .../ProjectAccessorsClassPathTest.kt | 1 + .../kotlin/dsl/accessors/TestWithClassPath.kt | 2 +- .../kotlin/dsl/fixtures/AbstractPluginTest.kt | 10 +- .../kotlin/dsl/fixtures/TestWithTempFiles.kt | 1 - .../dsl/fixtures/bytecode/AsmExtensions.kt | 335 ++++++++++++++++++ .../gradle/kotlin/dsl/fixtures/zipUtils.kt | 33 +- .../builders/KotlinBuildScriptModelBuilder.kt | 4 +- 18 files changed, 720 insertions(+), 99 deletions(-) create mode 100644 subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/GeneratePluginSpecBuilders.kt create mode 100644 subprojects/plugins/src/test/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPluginAccessorsTest.kt create mode 100644 subprojects/test-fixtures/src/main/kotlin/org/gradle/kotlin/dsl/fixtures/bytecode/AsmExtensions.kt diff --git a/subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/GeneratePluginSpecBuilders.kt b/subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/GeneratePluginSpecBuilders.kt new file mode 100644 index 0000000000000..dea3c7ce486f9 --- /dev/null +++ b/subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/GeneratePluginSpecBuilders.kt @@ -0,0 +1,85 @@ +/* + * Copyright 2018 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.kotlin.dsl.plugins.precompiled + +import org.gradle.api.DefaultTask +import org.gradle.api.file.FileCollection +import org.gradle.api.tasks.CacheableTask +import org.gradle.api.tasks.Classpath +import org.gradle.api.tasks.Internal +import org.gradle.api.tasks.OutputDirectory +import org.gradle.api.tasks.TaskAction + +import org.gradle.internal.classloader.ClasspathHasher +import org.gradle.internal.classpath.ClassPath +import org.gradle.internal.classpath.DefaultClassPath +import org.gradle.internal.hash.HashCode + +import org.gradle.kotlin.dsl.accessors.writeSourceCodeForPluginSpecBuildersFor +import org.gradle.kotlin.dsl.support.serviceOf + + +@CacheableTask +open class GeneratePluginSpecBuilders : DefaultTask() { + + @get:OutputDirectory + var outputDirectory = project.objects.directoryProperty() + + @get:Classpath + lateinit var classPath: FileCollection + + @TaskAction + @Suppress("unused") + internal + fun generate() = + outputDirectory.asFile.get().let { outputDir -> + val classPath = DefaultClassPath.of(classPath.files) + val packageDir = outputDir.resolve(packageName.split('.').joinToString("/")).apply { + mkdirs() + } + val outputFile = packageDir.resolve("PluginAccessors.kt") + writeSourceCodeForPluginSpecBuildersFor( + classPath, + outputFile, + packageName = kotlinPackageName + ) + } + + @get:Internal + internal + val kotlinPackageName by lazy { + kotlinPackageNameFor(packageName) + } + + private + val packageName by lazy { + "gradle-kotlin-dsl.plugin-spec-builders.${'$'}${hashOf(pluginDescriptorClassPath)}" + } + + private + val pluginDescriptorClassPath by lazy { + DefaultClassPath.of(classPath.files) + } + + private + fun hashOf(classPath: ClassPath): HashCode = + project.serviceOf().hash(classPath) + + private + fun kotlinPackageNameFor(packageName: String) = + packageName.split('.').joinToString(".") { "`$it`" } +} diff --git a/subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPlugins.kt b/subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPlugins.kt index 3c8f54fb26427..150585d8b4c81 100644 --- a/subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPlugins.kt +++ b/subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPlugins.kt @@ -130,13 +130,25 @@ fun Project.enableScriptCompilation() { "kotlinCompilerPluginClasspath"(gradleApi()) } - tasks.named("compileKotlin") { - kotlinOptions { - freeCompilerArgs += listOf( - "-script-templates", scriptTemplates, - // Propagate implicit imports and other settings - "-Xscript-resolver-environment=${resolverEnvironment()}" - ) + val generatedPluginSpecBuilders = layout.buildDirectory.dir("generated-sources/kotlin-dsl-plugin-accessors/kotlin") + sourceSets["main"].kotlin.srcDir(generatedPluginSpecBuilders) + + tasks { + + val generatePluginSpecBuilders by registering(GeneratePluginSpecBuilders::class) { + classPath = sourceSets["main"].compileClasspath + outputDirectory.set(generatedPluginSpecBuilders) + } + + named("compileKotlin") { + dependsOn(generatePluginSpecBuilders) + kotlinOptions { + freeCompilerArgs += listOf( + "-script-templates", scriptTemplates, + // Propagate implicit imports and other settings + "-Xscript-resolver-environment=${resolverEnvironment(implicitImports() + (generatePluginSpecBuilders.get().kotlinPackageName + ".*"))}" + ) + } } } } @@ -156,9 +168,9 @@ val scriptTemplates by lazy { private -fun Project.resolverEnvironment() = +fun resolverEnvironment(implicitImports: List) = (PrecompiledScriptDependenciesResolver.EnvironmentProperties.kotlinDslImplicitImports - + "=\"" + implicitImports().joinToString(separator = ":") + "\"") + + "=\"" + implicitImports.joinToString(separator = ":") + "\"") private diff --git a/subprojects/plugins/src/test/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/AbstractPrecompiledScriptPluginTest.kt b/subprojects/plugins/src/test/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/AbstractPrecompiledScriptPluginTest.kt index cdaa6552efba8..f465fb547b73a 100644 --- a/subprojects/plugins/src/test/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/AbstractPrecompiledScriptPluginTest.kt +++ b/subprojects/plugins/src/test/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/AbstractPrecompiledScriptPluginTest.kt @@ -30,11 +30,17 @@ open class AbstractPrecompiledScriptPluginTest : AbstractPluginTest() { protected fun givenPrecompiledKotlinScript(fileName: String, code: String) { withKotlinDslPlugin() - withFile("src/main/kotlin/$fileName", code) + withPrecompiledKotlinScript(fileName, code) compileKotlin() } - protected inline fun instantiatePrecompiledScriptOf(target: T, className: String): Any = + protected + fun withPrecompiledKotlinScript(fileName: String, code: String) { + withFile("src/main/kotlin/$fileName", code) + } + + protected + inline fun instantiatePrecompiledScriptOf(target: T, className: String): Any = loadCompiledKotlinClass(className) .getConstructor(T::class.java) .newInstance(target) @@ -59,9 +65,9 @@ open class AbstractPrecompiledScriptPluginTest : AbstractPluginTest() { """ protected - fun compileKotlin() { + fun compileKotlin(taskName: String = "classes") { assertThat( - buildWithPlugin("classes").outcomeOf(":compileKotlin"), + buildWithPlugin(taskName).outcomeOf(":compileKotlin"), equalTo(TaskOutcome.SUCCESS) ) } diff --git a/subprojects/plugins/src/test/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPluginAccessorsTest.kt b/subprojects/plugins/src/test/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPluginAccessorsTest.kt new file mode 100644 index 0000000000000..edabde6d766cd --- /dev/null +++ b/subprojects/plugins/src/test/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPluginAccessorsTest.kt @@ -0,0 +1,118 @@ +/* + * Copyright 2018 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.kotlin.dsl.plugins.precompiled + +import com.nhaarman.mockito_kotlin.doAnswer +import com.nhaarman.mockito_kotlin.doReturn +import com.nhaarman.mockito_kotlin.inOrder +import com.nhaarman.mockito_kotlin.mock + +import org.gradle.api.Project +import org.gradle.api.plugins.PluginManager + +import org.gradle.kotlin.dsl.fixtures.bytecode.InternalName +import org.gradle.kotlin.dsl.fixtures.bytecode.publicClass +import org.gradle.kotlin.dsl.fixtures.normalisedPath +import org.gradle.kotlin.dsl.fixtures.pluginDescriptorEntryFor +import org.gradle.kotlin.dsl.support.zipTo + +import org.junit.Test +import java.io.File + + +class PrecompiledScriptPluginAccessorsTest : AbstractPrecompiledScriptPluginTest() { + + @Test + fun `can use core plugin spec builders`() { + + givenPrecompiledKotlinScript("java-project.gradle.kts", """ + + plugins { + java + } + + """) + + val (project, pluginManager) = projectAndPluginManagerMocks() + + instantiatePrecompiledScriptOf( + project, + "Java_project_gradle" + ) + + inOrder(pluginManager) { + verify(pluginManager).apply("org.gradle.java") + verifyNoMoreInteractions() + } + } + + @Test + fun `can use plugin spec builders for plugins in the implementation classpath`() { + + // given: + val pluginJar = pluginJarWith( + pluginDescriptorEntryFor("my.plugin", "MyPlugin"), + "MyPlugin.class" to publicClass(InternalName("MyPlugin")) + ) + + withKotlinDslPlugin().appendText(""" + + dependencies { + implementation(files("${pluginJar.normalisedPath}")) + } + + """) + + withPrecompiledKotlinScript("plugin.gradle.kts", """ + + plugins { + my.plugin + } + + """) + + compileKotlin() + + val (project, pluginManager) = projectAndPluginManagerMocks() + + instantiatePrecompiledScriptOf( + project, + "Plugin_gradle" + ) + + inOrder(pluginManager) { + verify(pluginManager).apply("my.plugin") + verifyNoMoreInteractions() + } + } + + private + fun pluginJarWith(vararg entries: Pair): File = + newFile("my.plugin.jar").also { file -> + zipTo(file, entries.asSequence()) + } + + private + fun projectAndPluginManagerMocks(): Pair { + val pluginManager = mock() + val project = mock { + on { getPluginManager() } doReturn pluginManager + on { project } doAnswer { it.mock as Project } + } + return Pair(project, pluginManager) + } +} diff --git a/subprojects/provider/provider.gradle.kts b/subprojects/provider/provider.gradle.kts index eab200abb5876..b1166b8bf35fc 100644 --- a/subprojects/provider/provider.gradle.kts +++ b/subprojects/provider/provider.gradle.kts @@ -27,7 +27,7 @@ dependencies { testImplementation(project(":test-fixtures")) testImplementation("com.tngtech.archunit:archunit:0.8.3") - testImplementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.0.1") + testImplementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.1.0") } // --- Enable automatic generation of API extensions ------------------- diff --git a/subprojects/provider/src/main/kotlin/org/gradle/kotlin/dsl/accessors/AccessorsClassPath.kt b/subprojects/provider/src/main/kotlin/org/gradle/kotlin/dsl/accessors/AccessorsClassPath.kt index 358df55cb3517..c836da3e961ca 100644 --- a/subprojects/provider/src/main/kotlin/org/gradle/kotlin/dsl/accessors/AccessorsClassPath.kt +++ b/subprojects/provider/src/main/kotlin/org/gradle/kotlin/dsl/accessors/AccessorsClassPath.kt @@ -93,7 +93,12 @@ data class AccessorsClassPath(val bin: ClassPath, val src: ClassPath) { internal -fun cachedAccessorsClassPathFor(project: Project, cacheKeySpec: CacheKeySpec, builder: (File, File) -> Unit): AccessorsClassPath { +fun cachedAccessorsClassPathFor( + project: Project, + cacheKeySpec: CacheKeySpec, + builder: (File, File) -> Unit +): AccessorsClassPath { + val cacheDir = scriptCacheOf(project) .cacheDirFor(cacheKeySpec) { baseDir -> @@ -102,6 +107,7 @@ fun cachedAccessorsClassPathFor(project: Project, cacheKeySpec: CacheKeySpec, bu accessorsClassesDir(baseDir) ) } + return AccessorsClassPath( DefaultClassPath.of(accessorsClassesDir(cacheDir)), DefaultClassPath.of(accessorsSourceDir(cacheDir)) diff --git a/subprojects/provider/src/main/kotlin/org/gradle/kotlin/dsl/accessors/PluginAccessorsClassPath.kt b/subprojects/provider/src/main/kotlin/org/gradle/kotlin/dsl/accessors/PluginAccessorsClassPath.kt index d3013656c8a37..c4fb3b9ea0052 100644 --- a/subprojects/provider/src/main/kotlin/org/gradle/kotlin/dsl/accessors/PluginAccessorsClassPath.kt +++ b/subprojects/provider/src/main/kotlin/org/gradle/kotlin/dsl/accessors/PluginAccessorsClassPath.kt @@ -27,9 +27,11 @@ import org.gradle.api.internal.project.ProjectInternal import org.gradle.internal.classpath.ClassPath import org.gradle.kotlin.dsl.codegen.fileHeader +import org.gradle.kotlin.dsl.codegen.fileHeaderFor import org.gradle.kotlin.dsl.codegen.pluginEntriesFrom import org.gradle.kotlin.dsl.concurrent.IO import org.gradle.kotlin.dsl.concurrent.withAsynchronousIO +import org.gradle.kotlin.dsl.concurrent.withSynchronousIO import org.gradle.kotlin.dsl.concurrent.writeFile import org.gradle.kotlin.dsl.provider.kotlinScriptClassPathProviderOf @@ -66,6 +68,7 @@ import org.gradle.plugin.use.PluginDependencySpec import org.jetbrains.org.objectweb.asm.ClassWriter import org.jetbrains.org.objectweb.asm.MethodVisitor +import java.io.BufferedWriter import java.io.File @@ -75,7 +78,7 @@ import java.io.File * * The accessors provide content-assist for plugin ids and quick navigation to the plugin source code. */ -fun pluginAccessorsClassPath(project: Project): AccessorsClassPath = project.rootProject.let { rootProject -> +fun pluginSpecBuildersClassPath(project: Project): AccessorsClassPath = project.rootProject.let { rootProject -> rootProject.getOrCreateProperty("gradleKotlinDsl.pluginAccessorsClassPath") { val buildSrcClassLoaderScope = baseClassLoaderScopeOf(rootProject) @@ -95,6 +98,27 @@ fun pluginAccessorsClassPath(project: Project): AccessorsClassPath = project.roo } +fun writeSourceCodeForPluginSpecBuildersFor( + pluginDescriptorsClassPath: ClassPath, + sourceFile: File, + packageName: String +) { + withSynchronousIO { + writePluginAccessorsSourceCodeTo( + sourceFile, + pluginAccessorsFor(pluginDescriptorsClassPath), + accessibility = "internal ", + header = fileHeaderFor(packageName) + ) + } +} + + +private +fun pluginAccessorsFor(pluginDescriptorsClassPath: ClassPath): List = + pluginAccessorsFor(pluginTreesFrom(pluginDescriptorsClassPath)).toList() + + internal fun IO.buildPluginAccessorsFor( pluginDescriptorsClassPath: ClassPath, @@ -103,12 +127,12 @@ fun IO.buildPluginAccessorsFor( ) { makeAccessorOutputDirs(srcDir, binDir) - val pluginSpecs = pluginSpecsFrom(pluginDescriptorsClassPath) - val pluginTrees = PluginTree.of(pluginSpecs) - val accessorList = pluginAccessorsFor(pluginTrees).toList() + val pluginTrees = pluginTreesFrom(pluginDescriptorsClassPath) + val baseFileName = "$packagePath/PluginAccessors" val sourceFile = srcDir.resolve("$baseFileName.kt") + val accessorList = pluginAccessorsFor(pluginTrees).toList() writePluginAccessorsSourceCodeTo(sourceFile, accessorList) val fileFacadeClassName = InternalName(baseFileName + "Kt") @@ -154,6 +178,11 @@ fun IO.buildPluginAccessorsFor( } +internal +fun pluginTreesFrom(pluginDescriptorsClassPath: ClassPath): Map = + PluginTree.of(pluginSpecsFrom(pluginDescriptorsClassPath)) + + private fun ClassWriter.emitAccessorMethodFor(accessor: PluginAccessor, signature: JvmMethodSignature) { val extension = accessor.extension @@ -180,50 +209,64 @@ fun ClassWriter.emitAccessorMethodFor(accessor: PluginAccessor, signature: JvmMe private -fun IO.writePluginAccessorsSourceCodeTo(sourceFile: File, accessors: List) = io { +fun IO.writePluginAccessorsSourceCodeTo( + sourceFile: File, + accessors: List, + accessibility: String = "", + header: String = fileHeader +) = io { sourceFile.bufferedWriter().useToRun { - appendReproducibleNewLine(fileHeader) + appendReproducibleNewLine(header) + appendSourceCodeForPluginAccessors(accessors, accessibility) + } +} - appendReproducibleNewLine(""" - import ${PluginDependenciesSpec::class.qualifiedName} - import ${PluginDependencySpec::class.qualifiedName} - """.replaceIndent()) - defaultPackageTypesIn(accessors).forEach { - appendReproducibleNewLine("import $it") - } +private +fun BufferedWriter.appendSourceCodeForPluginAccessors( + accessors: List, + accessibility: String = "" +) { - accessors.runEach { - newLine() - newLine() - val extendedType = extension.receiverType.sourceName - val pluginsRef = pluginDependenciesSpecOf(extendedType) - when (this) { - is PluginAccessor.ForPlugin -> { - appendReproducibleNewLine(""" - /** - * The `$id` plugin implemented by [$implementationClass]. - */ - val `$extendedType`.`${extension.name}`: PluginDependencySpec - get() = $pluginsRef.id("$id") - """.replaceIndent()) - } - is PluginAccessor.ForGroup -> { - val groupType = extension.returnType.sourceName - appendReproducibleNewLine(""" - /** - * The `$id` plugin group. - */ - class `$groupType`(internal val plugins: PluginDependenciesSpec) - - - /** - * Plugin ids starting with `$id`. - */ - val `$extendedType`.`${extension.name}`: `$groupType` - get() = `$groupType`($pluginsRef) - """.replaceIndent()) - } + appendReproducibleNewLine(""" + import ${PluginDependenciesSpec::class.qualifiedName} + import ${PluginDependencySpec::class.qualifiedName} + """.replaceIndent()) + + defaultPackageTypesIn(accessors).forEach { + appendReproducibleNewLine("import $it") + } + + accessors.runEach { + newLine() + newLine() + val extendedType = extension.receiverType.sourceName + val pluginsRef = pluginDependenciesSpecOf(extendedType) + when (this) { + is PluginAccessor.ForPlugin -> { + appendReproducibleNewLine(""" + /** + * The `$id` plugin implemented by [$implementationClass]. + */ + ${accessibility}val `$extendedType`.`${extension.name}`: PluginDependencySpec + get() = $pluginsRef.id("$id") + """.replaceIndent()) + } + is PluginAccessor.ForGroup -> { + val groupType = extension.returnType.sourceName + appendReproducibleNewLine(""" + /** + * The `$id` plugin group. + */ + ${accessibility}class `$groupType`(internal val plugins: PluginDependenciesSpec) + + + /** + * Plugin ids starting with `$id`. + */ + ${accessibility}val `$extendedType`.`${extension.name}`: `$groupType` + get() = `$groupType`($pluginsRef) + """.replaceIndent()) } } } diff --git a/subprojects/provider/src/main/kotlin/org/gradle/kotlin/dsl/concurrent/IO.kt b/subprojects/provider/src/main/kotlin/org/gradle/kotlin/dsl/concurrent/IO.kt index 43e1ed48fe30a..3d305b6881772 100644 --- a/subprojects/provider/src/main/kotlin/org/gradle/kotlin/dsl/concurrent/IO.kt +++ b/subprojects/provider/src/main/kotlin/org/gradle/kotlin/dsl/concurrent/IO.kt @@ -74,3 +74,15 @@ inline fun withAsynchronousIO( project: Project, action: IO.() -> T ): T = project.serviceOf().newScope().useToRun(action) + + +internal +inline fun withSynchronousIO(action: IO.() -> Unit) { + action(SynchronousIO) +} + + +internal +object SynchronousIO : IO { + override fun io(action: () -> Unit) = action() +} diff --git a/subprojects/provider/src/main/kotlin/org/gradle/kotlin/dsl/provider/KotlinScriptEvaluator.kt b/subprojects/provider/src/main/kotlin/org/gradle/kotlin/dsl/provider/KotlinScriptEvaluator.kt index f966d465610c3..6d6f1a992733e 100644 --- a/subprojects/provider/src/main/kotlin/org/gradle/kotlin/dsl/provider/KotlinScriptEvaluator.kt +++ b/subprojects/provider/src/main/kotlin/org/gradle/kotlin/dsl/provider/KotlinScriptEvaluator.kt @@ -44,7 +44,7 @@ import org.gradle.internal.operations.CallableBuildOperation import org.gradle.internal.scripts.CompileScriptBuildOperationType.Details import org.gradle.internal.scripts.CompileScriptBuildOperationType.Result -import org.gradle.kotlin.dsl.accessors.pluginAccessorsClassPath +import org.gradle.kotlin.dsl.accessors.pluginSpecBuildersClassPath import org.gradle.kotlin.dsl.cache.ScriptCache @@ -151,7 +151,7 @@ class StandardKotlinScriptEvaluator( override fun pluginAccessorsFor(scriptHost: KotlinScriptHost<*>): ClassPath = (scriptHost.target as? Project)?.let { - pluginAccessorsClassPath(it).bin + pluginSpecBuildersClassPath(it).bin } ?: ClassPath.EMPTY override fun runCompileBuildOperation(scriptPath: String, stage: String, action: () -> String): String = diff --git a/subprojects/provider/src/main/kotlin/org/gradle/kotlin/dsl/support/zip.kt b/subprojects/provider/src/main/kotlin/org/gradle/kotlin/dsl/support/zip.kt index 9e96e582c9a64..d6c3bdf1b0b5e 100644 --- a/subprojects/provider/src/main/kotlin/org/gradle/kotlin/dsl/support/zip.kt +++ b/subprojects/provider/src/main/kotlin/org/gradle/kotlin/dsl/support/zip.kt @@ -46,9 +46,9 @@ fun File.walkReproducibly(): Sequence = sequence { while (directories.isNotEmpty()) { val subDirectories = mutableListOf() directories.forEach { dir -> - dir.listFiles()?.sortedBy(fileName)?.partition { it.isDirectory }?.also { (childDirectories, childFiles) -> + dir.listFiles()?.sortedBy(fileName)?.partition { it.isDirectory }?.let { (childDirectories, childFiles) -> yieldAll(childFiles) - childDirectories.also { + childDirectories.let { yieldAll(it) subDirectories.addAll(it) } diff --git a/subprojects/provider/src/test/kotlin/org/gradle/kotlin/dsl/accessors/PluginAccessorsClassPathTest.kt b/subprojects/provider/src/test/kotlin/org/gradle/kotlin/dsl/accessors/PluginAccessorsClassPathTest.kt index 13e02a803aae6..00883cb4fd62d 100644 --- a/subprojects/provider/src/test/kotlin/org/gradle/kotlin/dsl/accessors/PluginAccessorsClassPathTest.kt +++ b/subprojects/provider/src/test/kotlin/org/gradle/kotlin/dsl/accessors/PluginAccessorsClassPathTest.kt @@ -22,14 +22,14 @@ import com.nhaarman.mockito_kotlin.mock import com.nhaarman.mockito_kotlin.verify import com.nhaarman.mockito_kotlin.verifyNoMoreInteractions -import org.gradle.kotlin.dsl.concurrent.IO +import org.gradle.kotlin.dsl.concurrent.withSynchronousIO import org.gradle.kotlin.dsl.fixtures.classLoaderFor import org.gradle.kotlin.dsl.fixtures.containsMultiLineString +import org.gradle.kotlin.dsl.fixtures.jarWithPluginDescriptors import org.gradle.kotlin.dsl.fixtures.toPlatformLineSeparators import org.gradle.kotlin.dsl.support.useToRun -import org.gradle.kotlin.dsl.support.zipTo import org.gradle.plugin.use.PluginDependenciesSpec import org.gradle.plugin.use.PluginDependencySpec @@ -50,6 +50,7 @@ class PluginAccessorsClassPathTest : TestWithClassPath() { // given: val pluginsJar = jarWithPluginDescriptors( + file("plugins.jar"), "my-plugin" to "MyPlugin", "my.own.plugin" to "my.own.Plugin" ) @@ -146,24 +147,4 @@ class PluginAccessorsClassPathTest : TestWithClassPath() { verifyNoMoreInteractions(plugins) } } - - private - fun jarWithPluginDescriptors(vararg pluginIdsToImplClasses: Pair) = - file("plugins.jar").also { - zipTo(it, pluginIdsToImplClasses.asSequence().map { (id, implClass) -> - "META-INF/gradle-plugins/$id.properties" to "implementation-class=$implClass".toByteArray() - }) - } -} - - -internal -inline fun withSynchronousIO(action: IO.() -> Unit) { - action(SynchronousIO) -} - - -internal -object SynchronousIO : IO { - override fun io(action: () -> Unit) = action() } diff --git a/subprojects/provider/src/test/kotlin/org/gradle/kotlin/dsl/accessors/ProjectAccessorsClassPathTest.kt b/subprojects/provider/src/test/kotlin/org/gradle/kotlin/dsl/accessors/ProjectAccessorsClassPathTest.kt index b21ecd674c502..4b84eaf238746 100644 --- a/subprojects/provider/src/test/kotlin/org/gradle/kotlin/dsl/accessors/ProjectAccessorsClassPathTest.kt +++ b/subprojects/provider/src/test/kotlin/org/gradle/kotlin/dsl/accessors/ProjectAccessorsClassPathTest.kt @@ -49,6 +49,7 @@ import org.gradle.api.tasks.TaskProvider import org.gradle.internal.classpath.ClassPath import org.gradle.internal.classpath.DefaultClassPath +import org.gradle.kotlin.dsl.concurrent.withSynchronousIO import org.gradle.kotlin.dsl.fixtures.AbstractDslTest import org.gradle.kotlin.dsl.fixtures.eval import org.gradle.kotlin.dsl.fixtures.testCompilationClassPath diff --git a/subprojects/provider/src/test/kotlin/org/gradle/kotlin/dsl/accessors/TestWithClassPath.kt b/subprojects/provider/src/test/kotlin/org/gradle/kotlin/dsl/accessors/TestWithClassPath.kt index 4e0240d5e3136..f9a5d2fc9d704 100644 --- a/subprojects/provider/src/test/kotlin/org/gradle/kotlin/dsl/accessors/TestWithClassPath.kt +++ b/subprojects/provider/src/test/kotlin/org/gradle/kotlin/dsl/accessors/TestWithClassPath.kt @@ -113,7 +113,7 @@ fun writeClassFileTo(rootDir: File, className: InternalName, classBytes: ByteArr } -private +internal fun classBytesOf(modifiers: Int, internalName: InternalName): ByteArray = beginClass(modifiers, internalName).run { publicDefaultConstructor() diff --git a/subprojects/test-fixtures/src/main/kotlin/org/gradle/kotlin/dsl/fixtures/AbstractPluginTest.kt b/subprojects/test-fixtures/src/main/kotlin/org/gradle/kotlin/dsl/fixtures/AbstractPluginTest.kt index 66f3be7357761..c59b3f8708344 100644 --- a/subprojects/test-fixtures/src/main/kotlin/org/gradle/kotlin/dsl/fixtures/AbstractPluginTest.kt +++ b/subprojects/test-fixtures/src/main/kotlin/org/gradle/kotlin/dsl/fixtures/AbstractPluginTest.kt @@ -14,6 +14,11 @@ import java.util.* */ open class AbstractPluginTest : AbstractIntegrationTest() { + @Before + fun setUpTestPluginRepository() { + withSettings(pluginManagementBlock) + } + override val defaultSettingsScript: String get() = pluginManagementBlock @@ -80,11 +85,6 @@ open class AbstractPluginTest : AbstractIntegrationTest() { open val testRepositoryPaths: List get() = normalisedPathsOf("build/repository") - @Before - fun setUpTestPluginRepository() { - withSettings(pluginManagementBlock) - } - protected fun buildWithPlugin(vararg arguments: String) = build(*arguments) diff --git a/subprojects/test-fixtures/src/main/kotlin/org/gradle/kotlin/dsl/fixtures/TestWithTempFiles.kt b/subprojects/test-fixtures/src/main/kotlin/org/gradle/kotlin/dsl/fixtures/TestWithTempFiles.kt index 25438a70f4dc6..ac53bf824cfe9 100644 --- a/subprojects/test-fixtures/src/main/kotlin/org/gradle/kotlin/dsl/fixtures/TestWithTempFiles.kt +++ b/subprojects/test-fixtures/src/main/kotlin/org/gradle/kotlin/dsl/fixtures/TestWithTempFiles.kt @@ -20,7 +20,6 @@ abstract class TestWithTempFiles { fun newFolder(): File = tempFolder.newFolder() - protected fun file(fileName: String) = File(root, fileName) diff --git a/subprojects/test-fixtures/src/main/kotlin/org/gradle/kotlin/dsl/fixtures/bytecode/AsmExtensions.kt b/subprojects/test-fixtures/src/main/kotlin/org/gradle/kotlin/dsl/fixtures/bytecode/AsmExtensions.kt new file mode 100644 index 0000000000000..4823f622727c5 --- /dev/null +++ b/subprojects/test-fixtures/src/main/kotlin/org/gradle/kotlin/dsl/fixtures/bytecode/AsmExtensions.kt @@ -0,0 +1,335 @@ +/* + * Copyright 2018 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.kotlin.dsl.fixtures.bytecode + +import org.jetbrains.org.objectweb.asm.ClassVisitor +import org.jetbrains.org.objectweb.asm.ClassWriter +import org.jetbrains.org.objectweb.asm.Label +import org.jetbrains.org.objectweb.asm.MethodVisitor +import org.jetbrains.org.objectweb.asm.Opcodes +import org.jetbrains.org.objectweb.asm.Opcodes.T_BYTE +import org.jetbrains.org.objectweb.asm.Type + +import kotlin.reflect.KClass + + +fun publicClass( + name: InternalName, + superName: InternalName? = null, + interfaces: List? = null, + classBody: ClassWriter.() -> Unit = {} +) = beginPublicClass(name, superName, interfaces).run { + classBody() + endClass() +} + + +internal +fun beginPublicClass(name: InternalName, superName: InternalName? = null, interfaces: List? = null) = + beginClass(Opcodes.ACC_PUBLIC + Opcodes.ACC_FINAL, name, superName, interfaces) + + +internal +fun beginClass( + modifiers: Int, + name: InternalName, + superName: InternalName? = null, + interfaces: List? = null +): ClassWriter = ClassWriter(ClassWriter.COMPUTE_MAXS + ClassWriter.COMPUTE_FRAMES).apply { + visit( + Opcodes.V1_8, + modifiers, + name.value, + null, + (superName ?: InternalNameOf.javaLangObject).value, + interfaces?.map { it.value }?.toTypedArray() + ) +} + + +internal +fun ClassWriter.endClass(): ByteArray { + visitEnd() + return toByteArray() +} + + +internal +fun ClassWriter.publicDefaultConstructor(superName: InternalName = InternalNameOf.javaLangObject) { + publicMethod("", "()V") { + ALOAD(0) + INVOKESPECIAL(superName, "", "()V") + RETURN() + } +} + + +internal +fun ClassVisitor.publicStaticMethod( + name: String, + desc: String, + signature: String? = null, + exceptions: Array? = null, + methodBody: MethodVisitor.() -> Unit +) { + method(Opcodes.ACC_PUBLIC + Opcodes.ACC_STATIC, name, desc, signature, exceptions, methodBody) +} + + +internal +fun ClassVisitor.publicMethod( + name: String, + desc: String, + signature: String? = null, + exceptions: Array? = null, + methodBody: MethodVisitor.() -> Unit +) { + method(Opcodes.ACC_PUBLIC, name, desc, signature, exceptions, methodBody) +} + + +internal +fun ClassVisitor.method( + access: Int, + name: String, + desc: String, + signature: String? = null, + exceptions: Array? = null, + methodBody: MethodVisitor.() -> Unit +) { + visitMethod(access, name, desc, signature, exceptions).apply { + visitCode() + methodBody() + visitMaxs(0, 0) + visitEnd() + } +} + + +internal +fun MethodVisitor.loadByteArray(byteArray: ByteArray) { + LDC(byteArray.size) + NEWARRAY(T_BYTE) + for ((i, byte) in byteArray.withIndex()) { + DUP() + LDC(i) + LDC(byte) + BASTORE() + } +} + + +internal +fun MethodVisitor.NEW(type: InternalName) { + visitTypeInsn(Opcodes.NEW, type) +} + + +internal +fun MethodVisitor.visitTypeInsn(opcode: Int, type: InternalName) { + visitTypeInsn(opcode, type.value) +} + + +internal +fun MethodVisitor.NEWARRAY(primitiveType: Int) { + visitIntInsn(Opcodes.NEWARRAY, primitiveType) +} + + +internal +fun MethodVisitor.LDC(type: InternalName) { + visitLdcInsn(Type.getType("L${type.value};")) +} + + +internal +fun MethodVisitor.LDC(value: Any) { + visitLdcInsn(value) +} + + +internal +fun MethodVisitor.INVOKEVIRTUAL(owner: InternalName, name: String, desc: String, itf: Boolean = false) { + visitMethodInsn_(Opcodes.INVOKEVIRTUAL, owner, name, desc, itf) +} + + +internal +fun MethodVisitor.INVOKESPECIAL(owner: InternalName, name: String, desc: String, itf: Boolean = false) { + visitMethodInsn_(Opcodes.INVOKESPECIAL, owner, name, desc, itf) +} + + +internal +fun MethodVisitor.INVOKEINTERFACE(owner: InternalName, name: String, desc: String, itf: Boolean = true) { + visitMethodInsn_(Opcodes.INVOKEINTERFACE, owner, name, desc, itf) +} + + +internal +fun MethodVisitor.INVOKESTATIC(owner: InternalName, name: String, desc: String) { + visitMethodInsn_(Opcodes.INVOKESTATIC, owner, name, desc, false) +} + + +private +fun MethodVisitor.visitMethodInsn_(opcode: Int, owner: InternalName, name: String, desc: String, itf: Boolean) { + visitMethodInsn(opcode, owner.value, name, desc, itf) +} + + +internal +fun MethodVisitor.BASTORE() { + visitInsn(Opcodes.BASTORE) +} + + +internal +fun MethodVisitor.DUP() { + visitInsn(Opcodes.DUP) +} + + +internal +fun MethodVisitor.ARETURN() { + visitInsn(Opcodes.ARETURN) +} + + +internal +fun MethodVisitor.RETURN() { + visitInsn(Opcodes.RETURN) +} + + +internal +fun MethodVisitor.ALOAD(`var`: Int) { + visitVarInsn(Opcodes.ALOAD, `var`) +} + + +internal +fun MethodVisitor.ASTORE(`var`: Int) { + visitVarInsn(Opcodes.ASTORE, `var`) +} + + +internal +fun MethodVisitor.GOTO(label: Label) { + visitJumpInsn(Opcodes.GOTO, label) +} + + +internal +inline fun MethodVisitor.TRY_CATCH( + noinline tryBlock: MethodVisitor.() -> Unit, + noinline catchBlock: MethodVisitor.() -> Unit +) = + TRY_CATCH(T::class.internalName, tryBlock, catchBlock) + + +internal +fun MethodVisitor.TRY_CATCH( + exceptionType: InternalName, + tryBlock: MethodVisitor.() -> Unit, + catchBlock: MethodVisitor.() -> Unit +) { + + val tryBlockStart = Label() + val tryBlockEnd = Label() + val catchBlockStart = Label() + val catchBlockEnd = Label() + visitTryCatchBlock(tryBlockStart, tryBlockEnd, catchBlockStart, exceptionType.value) + + visitLabel(tryBlockStart) + tryBlock() + GOTO(catchBlockEnd) + visitLabel(tryBlockEnd) + + visitLabel(catchBlockStart) + catchBlock() + visitLabel(catchBlockEnd) +} + + +internal +fun > MethodVisitor.GETSTATIC(field: T) { + val owner = field.declaringClass.internalName + GETSTATIC(owner, field.name, "L$owner;") +} + + +internal +fun MethodVisitor.GETSTATIC(owner: InternalName, name: String, desc: String) { + visitFieldInsn(Opcodes.GETSTATIC, owner.value, name, desc) +} + + +internal +fun MethodVisitor.GETFIELD(owner: InternalName, name: String, desc: String) { + visitFieldInsn(Opcodes.GETFIELD, owner.value, name, desc) +} + + +internal +fun MethodVisitor.PUTFIELD(owner: InternalName, name: String, desc: String) { + visitFieldInsn(Opcodes.PUTFIELD, owner.value, name, desc) +} + + +internal +fun MethodVisitor.CHECKCAST(type: InternalName) { + visitTypeInsn(Opcodes.CHECKCAST, type) +} + + +internal +fun MethodVisitor.ACONST_NULL() { + visitInsn(Opcodes.ACONST_NULL) +} + + +/** + * A JVM internal type name (as in `java/lang/Object` instead of `java.lang.Object`). + */ +@Suppress("experimental_feature_warning") +inline class InternalName(val value: String) { + + companion object { + fun from(sourceName: String) = InternalName(sourceName.replace('.', '/')) + } + + override fun toString() = value +} + + +internal +object InternalNameOf { + + val javaLangObject = InternalName("java/lang/Object") +} + + +internal +val KClass<*>.internalName: InternalName + get() = java.internalName + + +internal +inline val Class<*>.internalName: InternalName + get() = InternalName(Type.getInternalName(this)) diff --git a/subprojects/test-fixtures/src/main/kotlin/org/gradle/kotlin/dsl/fixtures/zipUtils.kt b/subprojects/test-fixtures/src/main/kotlin/org/gradle/kotlin/dsl/fixtures/zipUtils.kt index ae4f059332e2a..f6c2ff5efbdea 100644 --- a/subprojects/test-fixtures/src/main/kotlin/org/gradle/kotlin/dsl/fixtures/zipUtils.kt +++ b/subprojects/test-fixtures/src/main/kotlin/org/gradle/kotlin/dsl/fixtures/zipUtils.kt @@ -1,14 +1,37 @@ package org.gradle.kotlin.dsl.fixtures +import org.gradle.kotlin.dsl.support.zipTo + +import java.io.File + import kotlin.reflect.KClass -fun classEntriesFor(classes: Array>) = - classEntriesFor(*classes.map { it.java }.toTypedArray()) +fun classEntriesFor(classes: Array>): Sequence> = + classes.asSequence().map { classEntryFor(it) } fun classEntriesFor(vararg classes: Class<*>): Sequence> = - classes.asSequence().map { - val classFilePath = it.name.replace('.', '/') + ".class" - classFilePath to it.getResource("/$classFilePath").readBytes() + classes.asSequence().map { classEntryFor(it) } + + +fun classEntryFor(clazz: KClass<*>): Pair = + classEntryFor(clazz.java) + + +fun classEntryFor(clazz: Class<*>): Pair { + val classFilePath = clazz.name.replace('.', '/') + ".class" + return classFilePath to clazz.getResource("/$classFilePath").readBytes() +} + + +fun jarWithPluginDescriptors(file: File, vararg pluginIdsToImplClasses: Pair) = + file.also { + zipTo(it, pluginIdsToImplClasses.asSequence().map { (id, implClass) -> + pluginDescriptorEntryFor(id, implClass) + }) } + + +fun pluginDescriptorEntryFor(id: String, implClass: String) = + "META-INF/gradle-plugins/$id.properties" to "implementation-class=$implClass".toByteArray() diff --git a/subprojects/tooling-builders/src/main/kotlin/org/gradle/kotlin/dsl/tooling/builders/KotlinBuildScriptModelBuilder.kt b/subprojects/tooling-builders/src/main/kotlin/org/gradle/kotlin/dsl/tooling/builders/KotlinBuildScriptModelBuilder.kt index d0b43d744d091..90d3e2c528cba 100644 --- a/subprojects/tooling-builders/src/main/kotlin/org/gradle/kotlin/dsl/tooling/builders/KotlinBuildScriptModelBuilder.kt +++ b/subprojects/tooling-builders/src/main/kotlin/org/gradle/kotlin/dsl/tooling/builders/KotlinBuildScriptModelBuilder.kt @@ -37,7 +37,7 @@ import org.gradle.internal.resource.BasicTextResourceLoader import org.gradle.internal.time.Time.startTimer import org.gradle.kotlin.dsl.accessors.AccessorsClassPath -import org.gradle.kotlin.dsl.accessors.pluginAccessorsClassPath +import org.gradle.kotlin.dsl.accessors.pluginSpecBuildersClassPath import org.gradle.kotlin.dsl.accessors.projectAccessorsClassPath import org.gradle.kotlin.dsl.execution.EvalOption @@ -216,7 +216,7 @@ fun projectScriptModelBuilder( project = project, scriptClassPath = project.scriptCompilationClassPath, accessorsClassPath = { classPath -> - projectAccessorsClassPath(project, classPath) + pluginAccessorsClassPath(project) + projectAccessorsClassPath(project, classPath) + pluginSpecBuildersClassPath(project) }, sourceLookupScriptHandlers = sourceLookupScriptHandlersFor(project), enclosingScriptProjectDir = project.projectDir From c5e3df6998069b26b33d42b8e8b7000cf4a7084a Mon Sep 17 00:00:00 2001 From: "Rodrigo B. de Oliveira" Date: Fri, 11 Jan 2019 10:54:58 -0200 Subject: [PATCH 005/853] Emit plugin spec builders to module with unique name Derived from the compile classpath to avoid conflicts across plugins. --- .../precompiled/GeneratePluginSpecBuilders.kt | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/GeneratePluginSpecBuilders.kt b/subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/GeneratePluginSpecBuilders.kt index dea3c7ce486f9..506feef4971d7 100644 --- a/subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/GeneratePluginSpecBuilders.kt +++ b/subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/GeneratePluginSpecBuilders.kt @@ -47,13 +47,12 @@ open class GeneratePluginSpecBuilders : DefaultTask() { internal fun generate() = outputDirectory.asFile.get().let { outputDir -> - val classPath = DefaultClassPath.of(classPath.files) val packageDir = outputDir.resolve(packageName.split('.').joinToString("/")).apply { mkdirs() } - val outputFile = packageDir.resolve("PluginAccessors.kt") + val outputFile = packageDir.resolve("PluginSpecBuildersFor$$classPathHash.kt") writeSourceCodeForPluginSpecBuildersFor( - classPath, + pluginDescriptorClassPath, outputFile, packageName = kotlinPackageName ) @@ -65,10 +64,15 @@ open class GeneratePluginSpecBuilders : DefaultTask() { kotlinPackageNameFor(packageName) } + // TODO: consider a package name derived from the classpath hash + // "gradle-kotlin-dsl.plugin-spec-builders.$$classPathHash" private - val packageName by lazy { - "gradle-kotlin-dsl.plugin-spec-builders.${'$'}${hashOf(pluginDescriptorClassPath)}" - } + val packageName + get() = "org.gradle.kotlin.dsl" + + private + val classPathHash + get() = hashOf(pluginDescriptorClassPath) private val pluginDescriptorClassPath by lazy { From 2d94e402661b584f2edea011e45cbaa296e7599a Mon Sep 17 00:00:00 2001 From: "Rodrigo B. de Oliveira" Date: Fri, 11 Jan 2019 16:38:06 -0200 Subject: [PATCH 006/853] Prove plugin spec builders work in multi-project setups --- .../AbstractPrecompiledScriptPluginTest.kt | 6 +- .../PrecompiledScriptPluginAccessorsTest.kt | 103 +++++++++++++++++- .../kotlin/dsl/fixtures/FolderBasedTest.kt | 4 +- 3 files changed, 106 insertions(+), 7 deletions(-) diff --git a/subprojects/plugins/src/test/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/AbstractPrecompiledScriptPluginTest.kt b/subprojects/plugins/src/test/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/AbstractPrecompiledScriptPluginTest.kt index f465fb547b73a..c5b44645090c2 100644 --- a/subprojects/plugins/src/test/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/AbstractPrecompiledScriptPluginTest.kt +++ b/subprojects/plugins/src/test/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/AbstractPrecompiledScriptPluginTest.kt @@ -52,7 +52,11 @@ open class AbstractPrecompiledScriptPluginTest : AbstractPluginTest() { protected fun withKotlinDslPlugin() = - withBuildScript(scriptWithKotlinDslPlugin()) + withKotlinDslPluginIn(".") + + protected + fun withKotlinDslPluginIn(baseDir: String) = + withBuildScriptIn(baseDir, scriptWithKotlinDslPlugin()) protected fun scriptWithKotlinDslPlugin(): String = diff --git a/subprojects/plugins/src/test/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPluginAccessorsTest.kt b/subprojects/plugins/src/test/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPluginAccessorsTest.kt index edabde6d766cd..0e2fb7a558643 100644 --- a/subprojects/plugins/src/test/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPluginAccessorsTest.kt +++ b/subprojects/plugins/src/test/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPluginAccessorsTest.kt @@ -24,13 +24,19 @@ import com.nhaarman.mockito_kotlin.mock import org.gradle.api.Project import org.gradle.api.plugins.PluginManager +import org.gradle.kotlin.dsl.fixtures.FoldersDsl import org.gradle.kotlin.dsl.fixtures.bytecode.InternalName import org.gradle.kotlin.dsl.fixtures.bytecode.publicClass import org.gradle.kotlin.dsl.fixtures.normalisedPath import org.gradle.kotlin.dsl.fixtures.pluginDescriptorEntryFor import org.gradle.kotlin.dsl.support.zipTo +import org.hamcrest.CoreMatchers.allOf +import org.hamcrest.CoreMatchers.containsString +import org.hamcrest.MatcherAssert.assertThat + import org.junit.Test + import java.io.File @@ -64,10 +70,7 @@ class PrecompiledScriptPluginAccessorsTest : AbstractPrecompiledScriptPluginTest fun `can use plugin spec builders for plugins in the implementation classpath`() { // given: - val pluginJar = pluginJarWith( - pluginDescriptorEntryFor("my.plugin", "MyPlugin"), - "MyPlugin.class" to publicClass(InternalName("MyPlugin")) - ) + val pluginJar = jarForPlugin("my.plugin", "MyPlugin") withKotlinDslPlugin().appendText(""" @@ -100,6 +103,98 @@ class PrecompiledScriptPluginAccessorsTest : AbstractPrecompiledScriptPluginTest } } + @Test + fun `can use plugin spec builders in multi-project builds with local and external plugins`() { + + withProjectRoot(newDir("external-plugins")) { + withFolders { + "external-foo" { + withKotlinDslPlugin() + withFile("src/main/kotlin/external-foo.gradle.kts", """ + println("*external-foo applied*") + """) + } + "external-bar" { + withKotlinDslPlugin() + withFile("src/main/kotlin/external-bar.gradle.kts", """ + println("*external-bar applied*") + """) + } + withDefaultSettingsIn(relativePath).appendText(""" + include("external-foo", "external-bar") + """) + } + build("assemble") + } + + val externalFoo = existing("external-plugins/external-foo/build/libs/external-foo.jar") + val externalBar = existing("external-plugins/external-bar/build/libs/external-bar.jar") + + withFolders { + "buildSrc" { + "local-foo" { + withFile("src/main/kotlin/local-foo.gradle.kts", """ + plugins { `external-foo` } + """) + withKotlinDslPlugin().appendText(""" + dependencies { + implementation(files("${externalFoo.normalisedPath}")) + } + """) + } + "local-bar" { + withFile("src/main/kotlin/local-bar.gradle.kts", """ + plugins { `external-bar` } + """) + withKotlinDslPlugin().appendText(""" + dependencies { + implementation(files("${externalBar.normalisedPath}")) + } + """) + } + withDefaultSettingsIn(relativePath).appendText(""" + include("local-foo", "local-bar") + """) + withFile("build.gradle.kts", """ + dependencies { + subprojects.forEach { + runtime(project(it.path)) + } + } + """) + } + } + withBuildScript(""" + plugins { + `local-foo` + `local-bar` + } + """) + + assertThat( + build("tasks").output, + allOf( + containsString("*external-foo applied*"), + containsString("*external-bar applied*") + ) + ) + } + + private + fun FoldersDsl.withKotlinDslPlugin(): File = + withKotlinDslPluginIn(relativePath) + + private + val FoldersDsl.relativePath + get() = folder.relativeTo(projectRoot).path + + private + fun jarForPlugin(id: String, implClass: String): File = + pluginJarWith( + pluginDescriptorEntryFor(id, implClass), + "$implClass.class" to publicClass(InternalName(implClass)) + ) + private fun pluginJarWith(vararg entries: Pair): File = newFile("my.plugin.jar").also { file -> diff --git a/subprojects/test-fixtures/src/main/kotlin/org/gradle/kotlin/dsl/fixtures/FolderBasedTest.kt b/subprojects/test-fixtures/src/main/kotlin/org/gradle/kotlin/dsl/fixtures/FolderBasedTest.kt index 84ec4c51b5b66..4b60055777294 100644 --- a/subprojects/test-fixtures/src/main/kotlin/org/gradle/kotlin/dsl/fixtures/FolderBasedTest.kt +++ b/subprojects/test-fixtures/src/main/kotlin/org/gradle/kotlin/dsl/fixtures/FolderBasedTest.kt @@ -38,7 +38,7 @@ fun File.withFolders(folders: FoldersDslExpression) = apply { FoldersDsl(this).folders() } -class FoldersDsl(val root: File) { +class FoldersDsl(val folder: File) { operator fun String.invoke(subFolders: FoldersDslExpression): File = (+this).withFolders(subFolders) @@ -61,5 +61,5 @@ class FoldersDsl(val root: File) { file(fileName).canonicalFile fun file(fileName: String): File = - File(root, fileName) + File(folder, fileName) } From 7caef70fbcf7629e39ccc639eed0720942e43b37 Mon Sep 17 00:00:00 2001 From: "Rodrigo B. de Oliveira" Date: Thu, 17 Jan 2019 01:23:15 -0200 Subject: [PATCH 007/853] Add `GeneratePrecompiledScriptPluginAccessors` task skeleton --- .../ClassPathSensitiveCodeGenerationTask.kt | 55 +++++++ .../precompiled/GeneratePluginSpecBuilders.kt | 41 +---- ...eneratePrecompiledScriptPluginAccessors.kt | 155 ++++++++++++++++++ .../GenerateScriptPluginAdapters.kt | 21 ++- .../precompiled/PrecompiledScriptPlugins.kt | 78 ++++++--- .../PrecompiledScriptPluginAccessorsTest.kt | 75 +++++++++ .../kotlin/dsl/accessors/AccessorFragments.kt | 10 +- .../dsl/accessors/AccessorsClassPath.kt | 16 +- .../gradle/kotlin/dsl/accessors/Emitter.kt | 6 +- .../dsl/accessors/PluginAccessorsClassPath.kt | 7 +- .../kotlin/dsl/codegen/ApiExtensionsJar.kt | 2 +- .../kotlin/dsl/codegen/SourceFileHeader.kt | 8 +- .../org/gradle/kotlin/dsl/concurrent/IO.kt | 3 +- .../PrecompiledScriptDependenciesResolver.kt | 4 +- 14 files changed, 389 insertions(+), 92 deletions(-) create mode 100644 subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/ClassPathSensitiveCodeGenerationTask.kt create mode 100644 subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/GeneratePrecompiledScriptPluginAccessors.kt diff --git a/subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/ClassPathSensitiveCodeGenerationTask.kt b/subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/ClassPathSensitiveCodeGenerationTask.kt new file mode 100644 index 0000000000000..5352ed333dd48 --- /dev/null +++ b/subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/ClassPathSensitiveCodeGenerationTask.kt @@ -0,0 +1,55 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.kotlin.dsl.plugins.precompiled + +import org.gradle.api.DefaultTask +import org.gradle.api.file.FileCollection +import org.gradle.api.tasks.Classpath +import org.gradle.api.tasks.OutputDirectory +import org.gradle.internal.classloader.ClasspathHasher +import org.gradle.internal.classpath.ClassPath +import org.gradle.internal.classpath.DefaultClassPath +import org.gradle.internal.hash.HashCode +import org.gradle.kotlin.dsl.support.serviceOf + + +abstract class ClassPathSensitiveCodeGenerationTask : DefaultTask() { + + @get:OutputDirectory + var sourceCodeOutputDir = project.objects.directoryProperty() + + @get:Classpath + lateinit var classPathFiles: FileCollection + + protected + val classPath by lazy { + DefaultClassPath.of(classPathFiles.files) + } + + protected + val classPathHash + get() = hashOf(classPath) + + private + fun hashOf(classPath: ClassPath): HashCode = + project.serviceOf().hash(classPath) +} + + +internal +fun kotlinPackageNameFor(packageName: String) = + packageName.split('.').joinToString(".") { "`$it`" } diff --git a/subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/GeneratePluginSpecBuilders.kt b/subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/GeneratePluginSpecBuilders.kt index 506feef4971d7..6726fd3a437a6 100644 --- a/subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/GeneratePluginSpecBuilders.kt +++ b/subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/GeneratePluginSpecBuilders.kt @@ -16,43 +16,27 @@ package org.gradle.kotlin.dsl.plugins.precompiled -import org.gradle.api.DefaultTask -import org.gradle.api.file.FileCollection import org.gradle.api.tasks.CacheableTask -import org.gradle.api.tasks.Classpath import org.gradle.api.tasks.Internal -import org.gradle.api.tasks.OutputDirectory import org.gradle.api.tasks.TaskAction -import org.gradle.internal.classloader.ClasspathHasher -import org.gradle.internal.classpath.ClassPath -import org.gradle.internal.classpath.DefaultClassPath -import org.gradle.internal.hash.HashCode - import org.gradle.kotlin.dsl.accessors.writeSourceCodeForPluginSpecBuildersFor -import org.gradle.kotlin.dsl.support.serviceOf @CacheableTask -open class GeneratePluginSpecBuilders : DefaultTask() { - - @get:OutputDirectory - var outputDirectory = project.objects.directoryProperty() - - @get:Classpath - lateinit var classPath: FileCollection +open class GeneratePluginSpecBuilders : ClassPathSensitiveCodeGenerationTask() { @TaskAction @Suppress("unused") internal fun generate() = - outputDirectory.asFile.get().let { outputDir -> + sourceCodeOutputDir.withOutputDirectory { outputDir -> val packageDir = outputDir.resolve(packageName.split('.').joinToString("/")).apply { mkdirs() } val outputFile = packageDir.resolve("PluginSpecBuildersFor$$classPathHash.kt") writeSourceCodeForPluginSpecBuildersFor( - pluginDescriptorClassPath, + classPath, outputFile, packageName = kotlinPackageName ) @@ -64,26 +48,9 @@ open class GeneratePluginSpecBuilders : DefaultTask() { kotlinPackageNameFor(packageName) } - // TODO: consider a package name derived from the classpath hash + // TODO: move to a package name derived from the classpath hash // "gradle-kotlin-dsl.plugin-spec-builders.$$classPathHash" private val packageName get() = "org.gradle.kotlin.dsl" - - private - val classPathHash - get() = hashOf(pluginDescriptorClassPath) - - private - val pluginDescriptorClassPath by lazy { - DefaultClassPath.of(classPath.files) - } - - private - fun hashOf(classPath: ClassPath): HashCode = - project.serviceOf().hash(classPath) - - private - fun kotlinPackageNameFor(packageName: String) = - packageName.split('.').joinToString(".") { "`$it`" } } diff --git a/subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/GeneratePrecompiledScriptPluginAccessors.kt b/subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/GeneratePrecompiledScriptPluginAccessors.kt new file mode 100644 index 0000000000000..c25b135766096 --- /dev/null +++ b/subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/GeneratePrecompiledScriptPluginAccessors.kt @@ -0,0 +1,155 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.kotlin.dsl.plugins.precompiled + +import org.gradle.api.tasks.CacheableTask +import org.gradle.api.tasks.InputFiles +import org.gradle.api.tasks.Internal +import org.gradle.api.tasks.OutputDirectory +import org.gradle.api.tasks.PathSensitive +import org.gradle.api.tasks.PathSensitivity +import org.gradle.api.tasks.TaskAction + +import org.gradle.internal.hash.HashCode +import org.gradle.internal.hash.Hashing + +import org.gradle.kotlin.dsl.accessors.TypedProjectSchema +import org.gradle.kotlin.dsl.accessors.hashCodeFor + +import org.gradle.kotlin.dsl.concurrent.IO +import org.gradle.kotlin.dsl.concurrent.withAsynchronousIO +import org.gradle.kotlin.dsl.concurrent.writeFile + +import java.io.File + + +@CacheableTask +open class GeneratePrecompiledScriptPluginAccessors : ClassPathSensitiveCodeGenerationTask() { + + @get:OutputDirectory + var metadataOutputDir = project.objects.directoryProperty() + + @get:Internal + internal + lateinit var plugins: List + + @get:InputFiles + @get:PathSensitive(PathSensitivity.RELATIVE) + @Suppress("unused") + internal + val scriptFiles: Set + get() = scriptPluginFilesOf(plugins) + + /** + * ## Computation and sharing of type-safe accessors + * 1. Group precompiled script plugins by the set of plugins applied in their `plugins` block. + * 2. For each group, compute the project schema implied by the set of plugins. + * 3. Re-group precompiled script plugins by project schema. + * 4. For each group, emit the type-safe accessors implied by the schema to a package named after the schema + * hash code. + * 5. For each group, for each script plugin in the group, write the generated package name to a file named + * after the contents of the script plugin file. This is so the file can easily be found by + * `PrecompiledScriptDependenciesResolver`. + */ + @TaskAction + fun generate() { + withAsynchronousIO(project) { + plugins.mapNotNull { + scriptWithPluginsBlock(it) + }.groupBy { + it.pluginsBlock.plugins + }.map { + it to HashedProjectSchema(projectSchemaImpliedBy(it.key)) + }.groupBy( + { (_, projectSchema) -> projectSchema }, + { (pluginGroup, _) -> pluginGroup.value } + ).forEach { (projectSchema, pluginGroups) -> + writeTypeSafeAccessorsFor(projectSchema) + for (scriptPlugin in pluginGroups.asIterable().flatten()) { + writeContentAddressableImplicitImportFor(scriptPlugin, projectSchema.packageName) + } + } + } + } + + private + fun IO.writeTypeSafeAccessorsFor(projectSchema: HashedProjectSchema) { + TODO("not implemented") + } + + private + fun IO.writeContentAddressableImplicitImportFor(scriptPlugin: ScriptWithPluginsBlock, packageName: String) { + io { writeFile(implicitImportFileFor(scriptPlugin), "$packageName.*".toByteArray()) } + } + + private + fun implicitImportFileFor(scriptPlugin: ScriptWithPluginsBlock): File = + metadataOutputDir.get().asFile.resolve(hashBytesOf(scriptPlugin.script.scriptFile).toString()) + + private + fun hashBytesOf(file: File) = Hashing.hashBytes(file.readBytes()) + + private + fun scriptWithPluginsBlock(plugin: ScriptPlugin): ScriptWithPluginsBlock? = + null + + private + fun projectSchemaImpliedBy( + plugins: List + ): TypedProjectSchema = TODO() +} + + +internal +data class HashedProjectSchema( + val schema: TypedProjectSchema, + val hash: HashCode = hashCodeFor(schema) +) { + val packageName by lazy { + kotlinPackageNameFor("gradle-kotlin-dsl.type-safe-accessors.$$hash") + } + + override fun hashCode(): Int = hash.hashCode() + + override fun equals(other: Any?): Boolean = other is HashedProjectSchema && hash == other.hash +} + + +internal +data class ScriptWithPluginsBlock( + val script: ScriptPlugin, + val pluginsBlock: PluginsBlock +) + + +internal +data class PluginsBlock( + val lineNumber: Int, + val plugins: List +) + + +internal +data class PluginApplication( + val id: String, + val version: String?, + val apply: Boolean? +) + + +internal +fun scriptPluginFilesOf(list: List) = list.map { it.scriptFile }.toSet() diff --git a/subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/GenerateScriptPluginAdapters.kt b/subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/GenerateScriptPluginAdapters.kt index 1d6c1bda18e87..3ae4de634350c 100644 --- a/subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/GenerateScriptPluginAdapters.kt +++ b/subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/GenerateScriptPluginAdapters.kt @@ -17,6 +17,7 @@ package org.gradle.kotlin.dsl.plugins.precompiled import org.gradle.api.DefaultTask +import org.gradle.api.file.DirectoryProperty import org.gradle.api.tasks.CacheableTask import org.gradle.api.tasks.InputFiles import org.gradle.api.tasks.Internal @@ -33,27 +34,25 @@ import java.io.File @CacheableTask open class GenerateScriptPluginAdapters : DefaultTask() { + @get:OutputDirectory + var outputDirectory = project.objects.directoryProperty() + @get:Internal internal lateinit var plugins: List - @get:OutputDirectory - var outputDirectory = project.objects.directoryProperty() - @get:InputFiles @get:PathSensitive(PathSensitivity.RELATIVE) @Suppress("unused") internal val scriptFiles: Set - get() = plugins.map { it.scriptFile }.toSet() + get() = scriptPluginFilesOf(plugins) @TaskAction @Suppress("unused") internal fun generate() = - outputDirectory.asFile.get().let { outputDir -> - outputDir.deleteRecursively() - outputDir.mkdirs() + outputDirectory.withOutputDirectory { outputDir -> for (scriptPlugin in plugins) { scriptPlugin.writeScriptPluginAdapterTo(outputDir) } @@ -103,6 +102,14 @@ fun packageDir(outputDir: File, packageName: String) = outputDir.mkdir(packageName.replace('.', '/')) +internal +inline fun DirectoryProperty.withOutputDirectory(action: (File) -> T): T = + asFile.get().let { outputDir -> + outputDir.mkdirs() + action(outputDir) + } + + private fun File.mkdir(relative: String) = resolve(relative).apply { mkdirs() } diff --git a/subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPlugins.kt b/subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPlugins.kt index 150585d8b4c81..07fa341180694 100644 --- a/subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPlugins.kt +++ b/subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPlugins.kt @@ -17,12 +17,15 @@ package org.gradle.kotlin.dsl.plugins.precompiled import org.gradle.api.Plugin import org.gradle.api.Project +import org.gradle.api.file.Directory import org.gradle.api.file.SourceDirectorySet import org.gradle.api.initialization.Settings import org.gradle.api.invocation.Gradle +import org.gradle.api.provider.Provider import org.gradle.api.tasks.SourceSet import org.gradle.api.tasks.SourceSetContainer +import org.gradle.api.tasks.TaskProvider import org.gradle.kotlin.dsl.* @@ -98,55 +101,65 @@ import org.jetbrains.kotlin.gradle.tasks.KotlinCompile * ## Implementation Notes * External plugin dependencies are declared as regular artifact dependencies but a more * semantic preserving model could be introduced in the future. + * * ## Todo - * - [ ] type-safe plugin spec accessors for plugins in the precompiled script plugin classpath + * - DONE type-safe plugin spec accessors for plugins in the precompiled script plugin classpath * - [ ] limit the set of type-safe accessors visible to a precompiled script plugin to * those provided by the plugins in its `plugins` block - * - [ ] each set of accessors would be emitted to an internal object to avoid conflicts with - * external plugins - * - [ ] an internal object named against its precompiled script plugin would also let users - * know not to import them - * - [ ] emit error when a precompiled script plugin includes the version of a in its `plugins` block - * - [ ] validate plugin ids against declared plugin dependencies + * - [ ] emit help message when a precompiled script plugin includes a version in its `plugins` block + * - [ ] validate plugin ids against declared plugin dependencies (that comes for free) */ class PrecompiledScriptPlugins : Plugin { override fun apply(project: Project): Unit = project.run { - enableScriptCompilation() + val scriptPlugins = collectScriptPlugins() + + enableScriptCompilationOf(scriptPlugins) plugins.withType { - exposeScriptsAsGradlePlugins() + exposeScriptsAsGradlePlugins(scriptPlugins) } } } private -fun Project.enableScriptCompilation() { +fun Project.enableScriptCompilationOf(scriptPlugins: List) { dependencies { "kotlinCompilerPluginClasspath"(gradleKotlinDslJarsOf(project)) "kotlinCompilerPluginClasspath"(gradleApi()) } - val generatedPluginSpecBuilders = layout.buildDirectory.dir("generated-sources/kotlin-dsl-plugin-accessors/kotlin") - sourceSets["main"].kotlin.srcDir(generatedPluginSpecBuilders) + val generatedPluginSpecBuilders = generatedSourceDirFor("plugin-spec-builders") + + val generatedAccessors = generatedSourceDirFor("accessors") + + val generatedMetadata = layout.buildDirectory.dir("precompiled-script-plugins") tasks { val generatePluginSpecBuilders by registering(GeneratePluginSpecBuilders::class) { - classPath = sourceSets["main"].compileClasspath - outputDirectory.set(generatedPluginSpecBuilders) + classPathFiles = sourceSets["main"].compileClasspath + sourceCodeOutputDir.set(generatedPluginSpecBuilders) + } + + val generatePrecompiledScriptPluginAccessors by registering(GeneratePrecompiledScriptPluginAccessors::class) { + classPathFiles = sourceSets["main"].compileClasspath + sourceCodeOutputDir.set(generatedAccessors) + metadataOutputDir.set(generatedMetadata) + plugins = scriptPlugins } named("compileKotlin") { dependsOn(generatePluginSpecBuilders) + dependsOn(generatePrecompiledScriptPluginAccessors) kotlinOptions { freeCompilerArgs += listOf( "-script-templates", scriptTemplates, // Propagate implicit imports and other settings - "-Xscript-resolver-environment=${resolverEnvironment(implicitImports() + (generatePluginSpecBuilders.get().kotlinPackageName + ".*"))}" + "-Xscript-resolver-environment=${resolverEnvironmentFor(generatePrecompiledScriptPluginAccessors)}" ) } } @@ -154,6 +167,14 @@ fun Project.enableScriptCompilation() { } +private +fun Project.resolverEnvironmentFor( + accessors: TaskProvider +) = resolverEnvironment( + implicitImports() // + (accessors.get().kotlinPackageName + ".*") +) + + private val scriptTemplates by lazy { listOf( @@ -179,14 +200,7 @@ fun Project.implicitImports(): List = private -fun Project.exposeScriptsAsGradlePlugins() { - - val scriptSourceFiles = pluginSourceSet.allSource.matching { - it.include("**/*.gradle.kts") - } - - val scriptPlugins = - scriptSourceFiles.map(::ScriptPlugin) +fun Project.exposeScriptsAsGradlePlugins(scriptPlugins: List) { declareScriptPlugins(scriptPlugins) @@ -194,6 +208,13 @@ fun Project.exposeScriptsAsGradlePlugins() { } +private +fun Project.collectScriptPlugins(): List = + pluginSourceSet.allSource.matching { + it.include("**/*.gradle.kts") + }.map(::ScriptPlugin) + + private val Project.pluginSourceSet get() = gradlePlugin.pluginSourceSet @@ -221,8 +242,7 @@ fun Project.declareScriptPlugins(scriptPlugins: List) { private fun Project.generatePluginAdaptersFor(scriptPlugins: List) { - val generatedSourcesDir = layout.buildDirectory.dir("generated-sources/kotlin-dsl-plugins/kotlin") - sourceSets["main"].kotlin.srcDir(generatedSourcesDir) + val generatedSourcesDir = generatedSourceDirFor("plugins") tasks { @@ -238,6 +258,14 @@ fun Project.generatePluginAdaptersFor(scriptPlugins: List) { } +private +fun Project.generatedSourceDirFor(purpose: String): Provider { + val generatedSourcesDir = layout.buildDirectory.dir("generated-sources/kotlin-dsl-$purpose/kotlin") + sourceSets["main"].kotlin.srcDir(generatedSourcesDir) + return generatedSourcesDir +} + + private val Project.sourceSets get() = project.the() diff --git a/subprojects/plugins/src/test/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPluginAccessorsTest.kt b/subprojects/plugins/src/test/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPluginAccessorsTest.kt index 0e2fb7a558643..79918510bbad6 100644 --- a/subprojects/plugins/src/test/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPluginAccessorsTest.kt +++ b/subprojects/plugins/src/test/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPluginAccessorsTest.kt @@ -42,6 +42,81 @@ import java.io.File class PrecompiledScriptPluginAccessorsTest : AbstractPrecompiledScriptPluginTest() { + @Test + fun `can use type-safe accessors with same name but different meaning in sibling plugins`() { + + withProjectRoot(newDir("external-plugins")) { + withDefaultSettings() + withKotlinDslPlugin() + withFolders { + "src/main/kotlin" { + "extensions" { + withFile("Extensions.kt", """ + class App { var name: String = "app" } + class Lib { var name: String = "lib" } + """) + } + withFile("external-app.gradle.kts", """ + extensions.create("external", App::class) + """) + withFile("external-lib.gradle.kts", """ + extensions.create("external", Lib::class) + """) + } + } + build("assemble") + } + + val externalPlugins = existing("external-plugins/build/libs/external-plugins.jar") + + withFolders { + "buildSrc" { + withDefaultSettingsIn(relativePath) + withKotlinDslPlugin().appendText(""" + dependencies { + implementation(files("${externalPlugins.normalisedPath}")) + } + """) + + withFile("src/main/kotlin/local-app.gradle.kts", """ + plugins { `external-app` } + println("*using " + external.name + " from local-app in " + project.name + "*") + """) + + withFile("src/main/kotlin/local-lib.gradle.kts", """ + plugins { `external-lib` } + println("*using " + external.name + " from local-lib in " + project.name + "*") + """) + } + } + + withDefaultSettings().appendText(""" + include("foo") + include("bar") + """) + + withFolders { + "foo" { + withFile("build.gradle.kts", """ + plugins { `local-app` } + """) + } + "bar" { + withFile("build.gradle.kts", """ + plugins { `local-lib` } + """) + } + } + + assertThat( + build("tasks").output, + allOf( + containsString("*using app from local-app in foo*"), + containsString("*using lib from local-lib in bar*") + ) + ) + } + @Test fun `can use core plugin spec builders`() { diff --git a/subprojects/provider/src/main/kotlin/org/gradle/kotlin/dsl/accessors/AccessorFragments.kt b/subprojects/provider/src/main/kotlin/org/gradle/kotlin/dsl/accessors/AccessorFragments.kt index a7df44d5d4416..1ac353aae5432 100644 --- a/subprojects/provider/src/main/kotlin/org/gradle/kotlin/dsl/accessors/AccessorFragments.kt +++ b/subprojects/provider/src/main/kotlin/org/gradle/kotlin/dsl/accessors/AccessorFragments.kt @@ -25,6 +25,8 @@ import org.gradle.api.reflect.TypeOf import org.gradle.internal.hash.HashUtil +import org.gradle.kotlin.dsl.codegen.kotlinDslPackagePath + import org.gradle.kotlin.dsl.support.bytecode.ALOAD import org.gradle.kotlin.dsl.support.bytecode.ARETURN import org.gradle.kotlin.dsl.support.bytecode.CHECKCAST @@ -66,7 +68,7 @@ private fun fragmentsForConfiguration(accessor: Accessor.ForConfiguration): Fragments = accessor.run { val propertyName = name.original - val className = InternalName("$packagePath/${propertyName.capitalize()}ConfigurationAccessorsKt") + val className = InternalName("$kotlinDslPackagePath/${propertyName.capitalize()}ConfigurationAccessorsKt") className to sequenceOf( AccessorFragment( @@ -801,11 +803,7 @@ val kotlinPrimitiveTypes = primitiveTypeStrings.asSequence().map { (jvmName, kot private fun internalNameForAccessorClassOf(accessorSpec: TypedAccessorSpec): InternalName = - InternalName("$packagePath/Accessors${hashOf(accessorSpec)}Kt") - - -internal -const val packagePath = "org/gradle/kotlin/dsl" + InternalName("$kotlinDslPackagePath/Accessors${hashOf(accessorSpec)}Kt") private diff --git a/subprojects/provider/src/main/kotlin/org/gradle/kotlin/dsl/accessors/AccessorsClassPath.kt b/subprojects/provider/src/main/kotlin/org/gradle/kotlin/dsl/accessors/AccessorsClassPath.kt index c836da3e961ca..588f7ba870cc2 100644 --- a/subprojects/provider/src/main/kotlin/org/gradle/kotlin/dsl/accessors/AccessorsClassPath.kt +++ b/subprojects/provider/src/main/kotlin/org/gradle/kotlin/dsl/accessors/AccessorsClassPath.kt @@ -29,7 +29,8 @@ import org.gradle.internal.hash.Hasher import org.gradle.internal.hash.Hashing import org.gradle.kotlin.dsl.cache.ScriptCache -import org.gradle.kotlin.dsl.codegen.fileHeader +import org.gradle.kotlin.dsl.codegen.fileHeaderFor +import org.gradle.kotlin.dsl.codegen.kotlinDslPackageName import org.gradle.kotlin.dsl.concurrent.IO import org.gradle.kotlin.dsl.concurrent.withAsynchronousIO @@ -478,7 +479,6 @@ fun cacheKeyFor(projectSchema: TypedProjectSchema, classPath: ClassPath): CacheK + classPath) -internal fun hashCodeFor(schema: TypedProjectSchema): HashCode = Hashing.newHasher().run { putAll(schema.extensions) putAll(schema.conventions) @@ -515,9 +515,13 @@ fun enabledJitAccessors(project: Project) = internal -fun IO.writeAccessorsTo(outputFile: File, accessors: List, imports: List = emptyList()) = io { +fun IO.writeAccessorsTo( + outputFile: File, + accessors: List, + imports: List = emptyList() +) = io { outputFile.bufferedWriter().useToRun { - appendReproducibleNewLine(fileHeaderWithImports) + appendReproducibleNewLine(fileHeaderWithImportsFor(/* TODO: accept packageName here */)) if (imports.isNotEmpty()) { imports.forEach { appendReproducibleNewLine("import $it") @@ -533,8 +537,8 @@ fun IO.writeAccessorsTo(outputFile: File, accessors: List, imports: List internal -val fileHeaderWithImports = """ -$fileHeader +fun fileHeaderWithImportsFor(accessorsPackage: String = kotlinDslPackageName) = """ +${fileHeaderFor(accessorsPackage)} import org.gradle.api.Action import org.gradle.api.Incubating diff --git a/subprojects/provider/src/main/kotlin/org/gradle/kotlin/dsl/accessors/Emitter.kt b/subprojects/provider/src/main/kotlin/org/gradle/kotlin/dsl/accessors/Emitter.kt index 92caf9d53a201..cbe5b4415497d 100644 --- a/subprojects/provider/src/main/kotlin/org/gradle/kotlin/dsl/accessors/Emitter.kt +++ b/subprojects/provider/src/main/kotlin/org/gradle/kotlin/dsl/accessors/Emitter.kt @@ -19,6 +19,8 @@ package org.gradle.kotlin.dsl.accessors import org.gradle.api.NamedDomainObjectContainer import org.gradle.api.artifacts.Configuration +import org.gradle.kotlin.dsl.codegen.kotlinDslPackagePath + import org.gradle.kotlin.dsl.concurrent.IO import org.gradle.kotlin.dsl.concurrent.writeFile @@ -40,7 +42,7 @@ fun IO.emitAccessorsFor( binDir: File ): List { - makeAccessorOutputDirs(srcDir, binDir) + makeAccessorOutputDirs(srcDir, binDir, kotlinDslPackagePath) val emittedClassNames = accessorsFor(projectSchema).map { accessor -> @@ -57,7 +59,7 @@ fun IO.emitAccessorsFor( internal -fun IO.makeAccessorOutputDirs(srcDir: File, binDir: File) = io { +fun IO.makeAccessorOutputDirs(srcDir: File, binDir: File, packagePath: String) = io { srcDir.resolve(packagePath).mkdirs() binDir.resolve(packagePath).mkdirs() binDir.resolve("META-INF").mkdir() diff --git a/subprojects/provider/src/main/kotlin/org/gradle/kotlin/dsl/accessors/PluginAccessorsClassPath.kt b/subprojects/provider/src/main/kotlin/org/gradle/kotlin/dsl/accessors/PluginAccessorsClassPath.kt index c4fb3b9ea0052..9d7db9728e97b 100644 --- a/subprojects/provider/src/main/kotlin/org/gradle/kotlin/dsl/accessors/PluginAccessorsClassPath.kt +++ b/subprojects/provider/src/main/kotlin/org/gradle/kotlin/dsl/accessors/PluginAccessorsClassPath.kt @@ -28,6 +28,7 @@ import org.gradle.internal.classpath.ClassPath import org.gradle.kotlin.dsl.codegen.fileHeader import org.gradle.kotlin.dsl.codegen.fileHeaderFor +import org.gradle.kotlin.dsl.codegen.kotlinDslPackagePath import org.gradle.kotlin.dsl.codegen.pluginEntriesFrom import org.gradle.kotlin.dsl.concurrent.IO import org.gradle.kotlin.dsl.concurrent.withAsynchronousIO @@ -125,11 +126,11 @@ fun IO.buildPluginAccessorsFor( srcDir: File, binDir: File ) { - makeAccessorOutputDirs(srcDir, binDir) + makeAccessorOutputDirs(srcDir, binDir, kotlinDslPackagePath) val pluginTrees = pluginTreesFrom(pluginDescriptorsClassPath) - val baseFileName = "$packagePath/PluginAccessors" + val baseFileName = "$kotlinDslPackagePath/PluginAccessors" val sourceFile = srcDir.resolve("$baseFileName.kt") val accessorList = pluginAccessorsFor(pluginTrees).toList() @@ -379,7 +380,7 @@ fun pluginAccessorsFor(pluginTrees: Map, extendedType: TypeS internal fun typeSpecForPluginGroupType(groupType: String) = - TypeSpec(groupType, InternalName("$packagePath/$groupType")) + TypeSpec(groupType, InternalName("$kotlinDslPackagePath/$groupType")) internal diff --git a/subprojects/provider/src/main/kotlin/org/gradle/kotlin/dsl/codegen/ApiExtensionsJar.kt b/subprojects/provider/src/main/kotlin/org/gradle/kotlin/dsl/codegen/ApiExtensionsJar.kt index c52e7f849aee6..7309aeb390fdb 100644 --- a/subprojects/provider/src/main/kotlin/org/gradle/kotlin/dsl/codegen/ApiExtensionsJar.kt +++ b/subprojects/provider/src/main/kotlin/org/gradle/kotlin/dsl/codegen/ApiExtensionsJar.kt @@ -96,7 +96,7 @@ class ApiExtensionsJarGenerator( "$packageDir/$fileName" private - val packageDir = packageName.replace('.', '/') + val packageDir = kotlinDslPackagePath } diff --git a/subprojects/provider/src/main/kotlin/org/gradle/kotlin/dsl/codegen/SourceFileHeader.kt b/subprojects/provider/src/main/kotlin/org/gradle/kotlin/dsl/codegen/SourceFileHeader.kt index bb37f7392185a..dd4bca850ad34 100644 --- a/subprojects/provider/src/main/kotlin/org/gradle/kotlin/dsl/codegen/SourceFileHeader.kt +++ b/subprojects/provider/src/main/kotlin/org/gradle/kotlin/dsl/codegen/SourceFileHeader.kt @@ -19,7 +19,7 @@ package org.gradle.kotlin.dsl.codegen internal val fileHeader: String - get() = fileHeaderFor(packageName) + get() = fileHeaderFor(kotlinDslPackageName) internal @@ -36,7 +36,11 @@ package $packageName internal -const val packageName = "org.gradle.kotlin.dsl" +const val kotlinDslPackageName = "org.gradle.kotlin.dsl" + + +internal +const val kotlinDslPackagePath = "org/gradle/kotlin/dsl" internal diff --git a/subprojects/provider/src/main/kotlin/org/gradle/kotlin/dsl/concurrent/IO.kt b/subprojects/provider/src/main/kotlin/org/gradle/kotlin/dsl/concurrent/IO.kt index 3d305b6881772..e1699f0937f9a 100644 --- a/subprojects/provider/src/main/kotlin/org/gradle/kotlin/dsl/concurrent/IO.kt +++ b/subprojects/provider/src/main/kotlin/org/gradle/kotlin/dsl/concurrent/IO.kt @@ -69,8 +69,7 @@ interface AsyncIOScopeFactory { } -internal -inline fun withAsynchronousIO( +fun withAsynchronousIO( project: Project, action: IO.() -> T ): T = project.serviceOf().newScope().useToRun(action) diff --git a/subprojects/provider/src/main/kotlin/org/gradle/kotlin/dsl/precompile/PrecompiledScriptDependenciesResolver.kt b/subprojects/provider/src/main/kotlin/org/gradle/kotlin/dsl/precompile/PrecompiledScriptDependenciesResolver.kt index 2eb9f1dcd64b7..b6dfb4e8c2079 100644 --- a/subprojects/provider/src/main/kotlin/org/gradle/kotlin/dsl/precompile/PrecompiledScriptDependenciesResolver.kt +++ b/subprojects/provider/src/main/kotlin/org/gradle/kotlin/dsl/precompile/PrecompiledScriptDependenciesResolver.kt @@ -44,7 +44,9 @@ class PrecompiledScriptDependenciesResolver : ScriptDependenciesResolver { KotlinBuildScriptDependencies( imports = implicitImportsFrom(environment), classpath = emptyList(), - sources = emptyList())) + sources = emptyList() + ) + ) private fun implicitImportsFrom(environment: Environment?) = From 49310a4c945f96d4706cc79b7899da053d4fdee4 Mon Sep 17 00:00:00 2001 From: "Rodrigo B. de Oliveira" Date: Thu, 17 Jan 2019 11:46:03 -0200 Subject: [PATCH 008/853] Annotate protected task properties as `@Internal` --- .../precompiled/ClassPathSensitiveCodeGenerationTask.kt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/ClassPathSensitiveCodeGenerationTask.kt b/subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/ClassPathSensitiveCodeGenerationTask.kt index 5352ed333dd48..82b56e3ac66e6 100644 --- a/subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/ClassPathSensitiveCodeGenerationTask.kt +++ b/subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/ClassPathSensitiveCodeGenerationTask.kt @@ -19,6 +19,7 @@ package org.gradle.kotlin.dsl.plugins.precompiled import org.gradle.api.DefaultTask import org.gradle.api.file.FileCollection import org.gradle.api.tasks.Classpath +import org.gradle.api.tasks.Internal import org.gradle.api.tasks.OutputDirectory import org.gradle.internal.classloader.ClasspathHasher import org.gradle.internal.classpath.ClassPath @@ -35,11 +36,13 @@ abstract class ClassPathSensitiveCodeGenerationTask : DefaultTask() { @get:Classpath lateinit var classPathFiles: FileCollection + @get:Internal protected val classPath by lazy { DefaultClassPath.of(classPathFiles.files) } + @get:Internal protected val classPathHash get() = hashOf(classPath) From 247b436c8ceac45bf03d2311c2518f555210cc46 Mon Sep 17 00:00:00 2001 From: "Rodrigo B. de Oliveira" Date: Mon, 4 Feb 2019 15:16:12 -0200 Subject: [PATCH 009/853] WIP: Let precompiled script plugins use plugin spec builders --- ...eneratePrecompiledScriptPluginAccessors.kt | 30 ++++++++++++------- .../precompiled/PrecompiledScriptPlugins.kt | 2 ++ .../dsl/plugins/precompiled/ScriptPlugin.kt | 1 - 3 files changed, 22 insertions(+), 11 deletions(-) diff --git a/subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/GeneratePrecompiledScriptPluginAccessors.kt b/subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/GeneratePrecompiledScriptPluginAccessors.kt index c25b135766096..807b1db763854 100644 --- a/subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/GeneratePrecompiledScriptPluginAccessors.kt +++ b/subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/GeneratePrecompiledScriptPluginAccessors.kt @@ -17,6 +17,7 @@ package org.gradle.kotlin.dsl.plugins.precompiled import org.gradle.api.tasks.CacheableTask +import org.gradle.api.tasks.InputDirectory import org.gradle.api.tasks.InputFiles import org.gradle.api.tasks.Internal import org.gradle.api.tasks.OutputDirectory @@ -34,6 +35,8 @@ import org.gradle.kotlin.dsl.concurrent.IO import org.gradle.kotlin.dsl.concurrent.withAsynchronousIO import org.gradle.kotlin.dsl.concurrent.writeFile +import org.gradle.kotlin.dsl.support.KotlinScriptType + import java.io.File @@ -43,6 +46,9 @@ open class GeneratePrecompiledScriptPluginAccessors : ClassPathSensitiveCodeGene @get:OutputDirectory var metadataOutputDir = project.objects.directoryProperty() + @get:InputDirectory + var pluginSpecBuilders = project.objects.directoryProperty() + @get:Internal internal lateinit var plugins: List @@ -68,24 +74,26 @@ open class GeneratePrecompiledScriptPluginAccessors : ClassPathSensitiveCodeGene @TaskAction fun generate() { withAsynchronousIO(project) { - plugins.mapNotNull { + plugins.asSequence().mapNotNull { scriptWithPluginsBlock(it) }.groupBy { it.pluginsBlock.plugins - }.map { - it to HashedProjectSchema(projectSchemaImpliedBy(it.key)) - }.groupBy( - { (_, projectSchema) -> projectSchema }, - { (pluginGroup, _) -> pluginGroup.value } - ).forEach { (projectSchema, pluginGroups) -> + }.let { + projectSchemaImpliedByPluginGroups(it) + }.forEach { (projectSchema, pluginGroups) -> writeTypeSafeAccessorsFor(projectSchema) - for (scriptPlugin in pluginGroups.asIterable().flatten()) { + for (scriptPlugin in pluginGroups) { writeContentAddressableImplicitImportFor(scriptPlugin, projectSchema.packageName) } } } } + private + fun projectSchemaImpliedByPluginGroups( + pluginGroupsPerPluginsBlock: Map, List> + ): Iterable>> = emptyList() // TODO + private fun IO.writeTypeSafeAccessorsFor(projectSchema: HashedProjectSchema) { TODO("not implemented") @@ -104,8 +112,10 @@ open class GeneratePrecompiledScriptPluginAccessors : ClassPathSensitiveCodeGene fun hashBytesOf(file: File) = Hashing.hashBytes(file.readBytes()) private - fun scriptWithPluginsBlock(plugin: ScriptPlugin): ScriptWithPluginsBlock? = - null + fun scriptWithPluginsBlock(plugin: ScriptPlugin): ScriptWithPluginsBlock? { + if (plugin.scriptType != KotlinScriptType.PROJECT) return null + return null + } private fun projectSchemaImpliedBy( diff --git a/subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPlugins.kt b/subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPlugins.kt index 07fa341180694..b1f2c17ca7da6 100644 --- a/subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPlugins.kt +++ b/subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPlugins.kt @@ -146,9 +146,11 @@ fun Project.enableScriptCompilationOf(scriptPlugins: List) { } val generatePrecompiledScriptPluginAccessors by registering(GeneratePrecompiledScriptPluginAccessors::class) { + dependsOn(generatePluginSpecBuilders) classPathFiles = sourceSets["main"].compileClasspath sourceCodeOutputDir.set(generatedAccessors) metadataOutputDir.set(generatedMetadata) + pluginSpecBuilders.set(generatedPluginSpecBuilders) plugins = scriptPlugins } diff --git a/subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/ScriptPlugin.kt b/subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/ScriptPlugin.kt index 5669bca8c28b2..45d25173125e9 100644 --- a/subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/ScriptPlugin.kt +++ b/subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/ScriptPlugin.kt @@ -75,7 +75,6 @@ data class ScriptPlugin(internal val scriptFile: File) { } } - private val scriptType get() = scriptTypeMatch.scriptType From 629cd2e2a5ecd79854ad0d907e55e297ca343fb0 Mon Sep 17 00:00:00 2001 From: "Rodrigo B. de Oliveira" Date: Mon, 4 Feb 2019 15:26:29 -0200 Subject: [PATCH 010/853] Reintroduce deletion of stale precompiled script plugin adapters --- .../dsl/plugins/precompiled/GenerateScriptPluginAdapters.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/GenerateScriptPluginAdapters.kt b/subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/GenerateScriptPluginAdapters.kt index 3ae4de634350c..f14747defad59 100644 --- a/subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/GenerateScriptPluginAdapters.kt +++ b/subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/GenerateScriptPluginAdapters.kt @@ -105,6 +105,7 @@ fun packageDir(outputDir: File, packageName: String) = internal inline fun DirectoryProperty.withOutputDirectory(action: (File) -> T): T = asFile.get().let { outputDir -> + outputDir.deleteRecursively() outputDir.mkdirs() action(outputDir) } From ce34f5b997fc508f8e3e5b0ca4d918fc80398a66 Mon Sep 17 00:00:00 2001 From: "Rodrigo B. de Oliveira" Date: Mon, 4 Feb 2019 15:39:26 -0200 Subject: [PATCH 011/853] Restore `AbstractPluginTest` --- .../gradle/kotlin/dsl/fixtures/AbstractPluginTest.kt | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/subprojects/test-fixtures/src/main/kotlin/org/gradle/kotlin/dsl/fixtures/AbstractPluginTest.kt b/subprojects/test-fixtures/src/main/kotlin/org/gradle/kotlin/dsl/fixtures/AbstractPluginTest.kt index c59b3f8708344..66f3be7357761 100644 --- a/subprojects/test-fixtures/src/main/kotlin/org/gradle/kotlin/dsl/fixtures/AbstractPluginTest.kt +++ b/subprojects/test-fixtures/src/main/kotlin/org/gradle/kotlin/dsl/fixtures/AbstractPluginTest.kt @@ -14,11 +14,6 @@ import java.util.* */ open class AbstractPluginTest : AbstractIntegrationTest() { - @Before - fun setUpTestPluginRepository() { - withSettings(pluginManagementBlock) - } - override val defaultSettingsScript: String get() = pluginManagementBlock @@ -85,6 +80,11 @@ open class AbstractPluginTest : AbstractIntegrationTest() { open val testRepositoryPaths: List get() = normalisedPathsOf("build/repository") + @Before + fun setUpTestPluginRepository() { + withSettings(pluginManagementBlock) + } + protected fun buildWithPlugin(vararg arguments: String) = build(*arguments) From b7fcaa8e7e81d149b073098a623f7709ef636fe2 Mon Sep 17 00:00:00 2001 From: "Rodrigo B. de Oliveira" Date: Mon, 4 Feb 2019 15:40:47 -0200 Subject: [PATCH 012/853] Restore `FolderBasedTest` --- .../precompiled/PrecompiledScriptPluginAccessorsTest.kt | 2 +- .../kotlin/org/gradle/kotlin/dsl/fixtures/FolderBasedTest.kt | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/subprojects/plugins/src/test/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPluginAccessorsTest.kt b/subprojects/plugins/src/test/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPluginAccessorsTest.kt index 79918510bbad6..b52bbc6ab4c59 100644 --- a/subprojects/plugins/src/test/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPluginAccessorsTest.kt +++ b/subprojects/plugins/src/test/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPluginAccessorsTest.kt @@ -261,7 +261,7 @@ class PrecompiledScriptPluginAccessorsTest : AbstractPrecompiledScriptPluginTest private val FoldersDsl.relativePath - get() = folder.relativeTo(projectRoot).path + get() = root.relativeTo(projectRoot).path private fun jarForPlugin(id: String, implClass: String): File = diff --git a/subprojects/test-fixtures/src/main/kotlin/org/gradle/kotlin/dsl/fixtures/FolderBasedTest.kt b/subprojects/test-fixtures/src/main/kotlin/org/gradle/kotlin/dsl/fixtures/FolderBasedTest.kt index 4b60055777294..84ec4c51b5b66 100644 --- a/subprojects/test-fixtures/src/main/kotlin/org/gradle/kotlin/dsl/fixtures/FolderBasedTest.kt +++ b/subprojects/test-fixtures/src/main/kotlin/org/gradle/kotlin/dsl/fixtures/FolderBasedTest.kt @@ -38,7 +38,7 @@ fun File.withFolders(folders: FoldersDslExpression) = apply { FoldersDsl(this).folders() } -class FoldersDsl(val folder: File) { +class FoldersDsl(val root: File) { operator fun String.invoke(subFolders: FoldersDslExpression): File = (+this).withFolders(subFolders) @@ -61,5 +61,5 @@ class FoldersDsl(val folder: File) { file(fileName).canonicalFile fun file(fileName: String): File = - File(folder, fileName) + File(root, fileName) } From ac8498a020d9a412e5eaa499237fe8ebf7427a3e Mon Sep 17 00:00:00 2001 From: "Rodrigo B. de Oliveira" Date: Mon, 4 Feb 2019 16:04:46 -0200 Subject: [PATCH 013/853] Upgrade `kotlinx-coroutines-core` to 1.1.1 For best Kotlin 1.3.20 compatibility. --- subprojects/provider/provider.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subprojects/provider/provider.gradle.kts b/subprojects/provider/provider.gradle.kts index b1166b8bf35fc..edd1583650999 100644 --- a/subprojects/provider/provider.gradle.kts +++ b/subprojects/provider/provider.gradle.kts @@ -27,7 +27,7 @@ dependencies { testImplementation(project(":test-fixtures")) testImplementation("com.tngtech.archunit:archunit:0.8.3") - testImplementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.1.0") + testImplementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.1.1") } // --- Enable automatic generation of API extensions ------------------- From f43dc446513e736e5528ec1b6f2b2bdce1de8c3f Mon Sep 17 00:00:00 2001 From: "Rodrigo B. de Oliveira" Date: Tue, 5 Feb 2019 11:02:35 -0200 Subject: [PATCH 014/853] Add missing `@PathSensitive` annotation --- .../precompiled/GeneratePrecompiledScriptPluginAccessors.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/GeneratePrecompiledScriptPluginAccessors.kt b/subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/GeneratePrecompiledScriptPluginAccessors.kt index 807b1db763854..6524d4993d893 100644 --- a/subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/GeneratePrecompiledScriptPluginAccessors.kt +++ b/subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/GeneratePrecompiledScriptPluginAccessors.kt @@ -47,6 +47,7 @@ open class GeneratePrecompiledScriptPluginAccessors : ClassPathSensitiveCodeGene var metadataOutputDir = project.objects.directoryProperty() @get:InputDirectory + @get:PathSensitive(PathSensitivity.RELATIVE) var pluginSpecBuilders = project.objects.directoryProperty() @get:Internal From e71dd9bfc2de2ca0ba17b5e318eefab890ed5431 Mon Sep 17 00:00:00 2001 From: "Rodrigo B. de Oliveira" Date: Tue, 5 Feb 2019 11:02:55 -0200 Subject: [PATCH 015/853] Ignore test for work in progress so the branch can be merged As we migrate the codebase to the `gradle/gradle` repository. --- .../plugins/precompiled/PrecompiledScriptPluginAccessorsTest.kt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/subprojects/plugins/src/test/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPluginAccessorsTest.kt b/subprojects/plugins/src/test/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPluginAccessorsTest.kt index b52bbc6ab4c59..7bdabd3745407 100644 --- a/subprojects/plugins/src/test/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPluginAccessorsTest.kt +++ b/subprojects/plugins/src/test/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPluginAccessorsTest.kt @@ -35,6 +35,7 @@ import org.hamcrest.CoreMatchers.allOf import org.hamcrest.CoreMatchers.containsString import org.hamcrest.MatcherAssert.assertThat +import org.junit.Ignore import org.junit.Test import java.io.File @@ -42,6 +43,7 @@ import java.io.File class PrecompiledScriptPluginAccessorsTest : AbstractPrecompiledScriptPluginTest() { + @Ignore("wip") @Test fun `can use type-safe accessors with same name but different meaning in sibling plugins`() { From c52c28e79cd3cd2735ce6acd0094171c0df0f360 Mon Sep 17 00:00:00 2001 From: "Rodrigo B. de Oliveira" Date: Fri, 8 Feb 2019 21:58:02 -0200 Subject: [PATCH 016/853] Wire precompiled script plugin tasks --- .../ClassPathSensitiveCodeGenerationTask.kt | 29 +------ .../precompiled/ClassPathSensitiveTask.kt | 54 +++++++++++++ .../CompilePrecompiledScriptPluginPlugins.kt | 39 ++++++++++ .../ExtractPrecompiledScriptPluginPlugins.kt | 58 ++++++++++++++ ... => GenerateExternalPluginSpecBuilders.kt} | 13 +++- .../GenerateInternalPluginSpecBuilders.kt | 50 ++++++++++++ ...eneratePrecompiledScriptPluginAccessors.kt | 11 ++- .../GenerateScriptPluginAdapters.kt | 10 ++- .../precompiled/PrecompiledScriptPlugins.kt | 77 +++++++++++++++---- .../dsl/plugins/precompiled/ScriptPlugin.kt | 9 +++ 10 files changed, 294 insertions(+), 56 deletions(-) create mode 100644 subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/ClassPathSensitiveTask.kt create mode 100644 subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/CompilePrecompiledScriptPluginPlugins.kt create mode 100644 subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/ExtractPrecompiledScriptPluginPlugins.kt rename subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/{GeneratePluginSpecBuilders.kt => GenerateExternalPluginSpecBuilders.kt} (81%) create mode 100644 subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/GenerateInternalPluginSpecBuilders.kt diff --git a/subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/ClassPathSensitiveCodeGenerationTask.kt b/subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/ClassPathSensitiveCodeGenerationTask.kt index 82b56e3ac66e6..d6113ef3257a6 100644 --- a/subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/ClassPathSensitiveCodeGenerationTask.kt +++ b/subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/ClassPathSensitiveCodeGenerationTask.kt @@ -16,40 +16,13 @@ package org.gradle.kotlin.dsl.plugins.precompiled -import org.gradle.api.DefaultTask -import org.gradle.api.file.FileCollection -import org.gradle.api.tasks.Classpath -import org.gradle.api.tasks.Internal import org.gradle.api.tasks.OutputDirectory -import org.gradle.internal.classloader.ClasspathHasher -import org.gradle.internal.classpath.ClassPath -import org.gradle.internal.classpath.DefaultClassPath -import org.gradle.internal.hash.HashCode -import org.gradle.kotlin.dsl.support.serviceOf -abstract class ClassPathSensitiveCodeGenerationTask : DefaultTask() { +abstract class ClassPathSensitiveCodeGenerationTask : ClassPathSensitiveTask() { @get:OutputDirectory var sourceCodeOutputDir = project.objects.directoryProperty() - - @get:Classpath - lateinit var classPathFiles: FileCollection - - @get:Internal - protected - val classPath by lazy { - DefaultClassPath.of(classPathFiles.files) - } - - @get:Internal - protected - val classPathHash - get() = hashOf(classPath) - - private - fun hashOf(classPath: ClassPath): HashCode = - project.serviceOf().hash(classPath) } diff --git a/subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/ClassPathSensitiveTask.kt b/subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/ClassPathSensitiveTask.kt new file mode 100644 index 0000000000000..9c4737688a8bd --- /dev/null +++ b/subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/ClassPathSensitiveTask.kt @@ -0,0 +1,54 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.kotlin.dsl.plugins.precompiled + +import org.gradle.api.DefaultTask +import org.gradle.api.file.FileCollection +import org.gradle.api.tasks.Classpath +import org.gradle.api.tasks.Internal + +import org.gradle.internal.classloader.ClasspathHasher +import org.gradle.internal.classpath.ClassPath +import org.gradle.internal.classpath.DefaultClassPath + +import org.gradle.internal.hash.HashCode + +import org.gradle.kotlin.dsl.support.serviceOf + + +abstract class ClassPathSensitiveTask : DefaultTask() { + + @get:Classpath + lateinit var classPathFiles: FileCollection + + // Todo: Replaced all of this by HashedClasspath + @get:Internal + protected + val classPath by lazy { + DefaultClassPath.of(classPathFiles.files) + } + + @get:Internal + protected + val classPathHash by lazy { + hashOf(classPath) + } + + private + fun hashOf(classPath: ClassPath): HashCode = + project.serviceOf().hash(classPath) +} diff --git a/subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/CompilePrecompiledScriptPluginPlugins.kt b/subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/CompilePrecompiledScriptPluginPlugins.kt new file mode 100644 index 0000000000000..1ea1728d160ed --- /dev/null +++ b/subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/CompilePrecompiledScriptPluginPlugins.kt @@ -0,0 +1,39 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.kotlin.dsl.plugins.precompiled + +import org.gradle.api.file.Directory +import org.gradle.api.provider.Provider +import org.gradle.api.tasks.CacheableTask +import org.gradle.api.tasks.OutputDirectory +import org.gradle.api.tasks.TaskAction + + +@CacheableTask +open class CompilePrecompiledScriptPluginPlugins : ClassPathSensitiveTask() { + + @get:OutputDirectory + var outputDir = project.objects.directoryProperty() + + @TaskAction + fun compile() { + outputDir.withOutputDirectory { + } + } + + fun sourceDir(dir: Provider) = Unit +} diff --git a/subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/ExtractPrecompiledScriptPluginPlugins.kt b/subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/ExtractPrecompiledScriptPluginPlugins.kt new file mode 100644 index 0000000000000..ae30f91bd9758 --- /dev/null +++ b/subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/ExtractPrecompiledScriptPluginPlugins.kt @@ -0,0 +1,58 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.kotlin.dsl.plugins.precompiled + +import org.gradle.api.DefaultTask +import org.gradle.api.Project +import org.gradle.api.tasks.CacheableTask +import org.gradle.api.tasks.InputFiles +import org.gradle.api.tasks.Internal +import org.gradle.api.tasks.OutputDirectory +import org.gradle.api.tasks.PathSensitive +import org.gradle.api.tasks.PathSensitivity +import org.gradle.api.tasks.TaskAction + +import java.io.File + + +/** + * Extracts the `plugins` block of each precompiled [Project] script plugin + * and writes it to a file with the same name under [outputDir]. + */ +@CacheableTask +open class ExtractPrecompiledScriptPluginPlugins : DefaultTask() { + + @get:OutputDirectory + var outputDir = project.objects.directoryProperty() + + @get:Internal + internal + lateinit var plugins: List + + @get:InputFiles + @get:PathSensitive(PathSensitivity.RELATIVE) + @Suppress("unused") + internal + val scriptFiles: Set + get() = scriptPluginFilesOf(plugins) + + @TaskAction + fun extract() { + outputDir.withOutputDirectory { + } + } +} diff --git a/subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/GeneratePluginSpecBuilders.kt b/subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/GenerateExternalPluginSpecBuilders.kt similarity index 81% rename from subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/GeneratePluginSpecBuilders.kt rename to subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/GenerateExternalPluginSpecBuilders.kt index 6726fd3a437a6..4b6d2adecc67a 100644 --- a/subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/GeneratePluginSpecBuilders.kt +++ b/subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/GenerateExternalPluginSpecBuilders.kt @@ -21,19 +21,18 @@ import org.gradle.api.tasks.Internal import org.gradle.api.tasks.TaskAction import org.gradle.kotlin.dsl.accessors.writeSourceCodeForPluginSpecBuildersFor +import java.io.File @CacheableTask -open class GeneratePluginSpecBuilders : ClassPathSensitiveCodeGenerationTask() { +open class GenerateExternalPluginSpecBuilders : ClassPathSensitiveCodeGenerationTask() { @TaskAction @Suppress("unused") internal fun generate() = sourceCodeOutputDir.withOutputDirectory { outputDir -> - val packageDir = outputDir.resolve(packageName.split('.').joinToString("/")).apply { - mkdirs() - } + val packageDir = createPackageDirIn(outputDir) val outputFile = packageDir.resolve("PluginSpecBuildersFor$$classPathHash.kt") writeSourceCodeForPluginSpecBuildersFor( classPath, @@ -42,6 +41,12 @@ open class GeneratePluginSpecBuilders : ClassPathSensitiveCodeGenerationTask() { ) } + private + fun createPackageDirIn(outputDir: File) = outputDir.resolve(packagePath()).apply { mkdirs() } + + private + fun packagePath() = packageName.split('.').joinToString("/") + @get:Internal internal val kotlinPackageName by lazy { diff --git a/subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/GenerateInternalPluginSpecBuilders.kt b/subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/GenerateInternalPluginSpecBuilders.kt new file mode 100644 index 0000000000000..c6b887c0b437a --- /dev/null +++ b/subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/GenerateInternalPluginSpecBuilders.kt @@ -0,0 +1,50 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.kotlin.dsl.plugins.precompiled + +import org.gradle.api.tasks.CacheableTask +import org.gradle.api.tasks.InputFiles +import org.gradle.api.tasks.Internal +import org.gradle.api.tasks.PathSensitive +import org.gradle.api.tasks.PathSensitivity +import org.gradle.api.tasks.TaskAction + +import java.io.File + + +/** + * Generates plugin spec builders for the _Project_ script plugins defined in the current module. + */ +@CacheableTask +open class GenerateInternalPluginSpecBuilders : ClassPathSensitiveCodeGenerationTask() { + + @get:Internal + internal + lateinit var plugins: List + + @get:InputFiles + @get:PathSensitive(PathSensitivity.RELATIVE) + @Suppress("unused") + internal + val scriptFiles: Set + get() = scriptPluginFilesOf(plugins) + + @TaskAction + fun generate() { + // TODO() + } +} diff --git a/subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/GeneratePrecompiledScriptPluginAccessors.kt b/subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/GeneratePrecompiledScriptPluginAccessors.kt index 6524d4993d893..18020190c0b79 100644 --- a/subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/GeneratePrecompiledScriptPluginAccessors.kt +++ b/subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/GeneratePrecompiledScriptPluginAccessors.kt @@ -26,7 +26,7 @@ import org.gradle.api.tasks.PathSensitivity import org.gradle.api.tasks.TaskAction import org.gradle.internal.hash.HashCode -import org.gradle.internal.hash.Hashing +import org.gradle.internal.hash.Hashing.hashString import org.gradle.kotlin.dsl.accessors.TypedProjectSchema import org.gradle.kotlin.dsl.accessors.hashCodeFor @@ -48,7 +48,7 @@ open class GeneratePrecompiledScriptPluginAccessors : ClassPathSensitiveCodeGene @get:InputDirectory @get:PathSensitive(PathSensitivity.RELATIVE) - var pluginSpecBuilders = project.objects.directoryProperty() + var compiledPluginsBlocksDir = project.objects.directoryProperty() @get:Internal internal @@ -75,6 +75,8 @@ open class GeneratePrecompiledScriptPluginAccessors : ClassPathSensitiveCodeGene @TaskAction fun generate() { withAsynchronousIO(project) { + val metadataOutputDir = metadataOutputDir.get().asFile + io { recreate(metadataOutputDir) } plugins.asSequence().mapNotNull { scriptWithPluginsBlock(it) }.groupBy { @@ -107,10 +109,7 @@ open class GeneratePrecompiledScriptPluginAccessors : ClassPathSensitiveCodeGene private fun implicitImportFileFor(scriptPlugin: ScriptWithPluginsBlock): File = - metadataOutputDir.get().asFile.resolve(hashBytesOf(scriptPlugin.script.scriptFile).toString()) - - private - fun hashBytesOf(file: File) = Hashing.hashBytes(file.readBytes()) + metadataOutputDir.get().asFile.resolve(scriptPlugin.script.hashString) private fun scriptWithPluginsBlock(plugin: ScriptPlugin): ScriptWithPluginsBlock? { diff --git a/subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/GenerateScriptPluginAdapters.kt b/subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/GenerateScriptPluginAdapters.kt index f14747defad59..3578bb0ada9d8 100644 --- a/subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/GenerateScriptPluginAdapters.kt +++ b/subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/GenerateScriptPluginAdapters.kt @@ -105,12 +105,18 @@ fun packageDir(outputDir: File, packageName: String) = internal inline fun DirectoryProperty.withOutputDirectory(action: (File) -> T): T = asFile.get().let { outputDir -> - outputDir.deleteRecursively() - outputDir.mkdirs() + recreate(outputDir) action(outputDir) } +internal +fun recreate(outputDir: File) { + outputDir.deleteRecursively() + outputDir.mkdirs() +} + + private fun File.mkdir(relative: String) = resolve(relative).apply { mkdirs() } diff --git a/subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPlugins.kt b/subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPlugins.kt index b1f2c17ca7da6..9bc9c7597b3af 100644 --- a/subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPlugins.kt +++ b/subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPlugins.kt @@ -85,7 +85,6 @@ import org.jetbrains.kotlin.gradle.tasks.KotlinCompile * [type-safe model accessors](https://docs.gradle.org/current/userguide/kotlin_dsl.html#type-safe-accessors) * to model elements contributed by plugins applied via the `plugins` block, so can precompiled [Project] script plugins: * ```kotlin - * * // java7-project.gradle.kts * * plugins { @@ -96,12 +95,24 @@ import org.jetbrains.kotlin.gradle.tasks.KotlinCompile * sourceCompatibility = JavaVersion.VERSION_1_7 * targetCompatibility = JavaVersion.VERSION_1_7 * } - * * ``` * ## Implementation Notes * External plugin dependencies are declared as regular artifact dependencies but a more * semantic preserving model could be introduced in the future. * + * ### Type-safe accessors + * The process of generating type-safe accessors for precompiled script plugins is carried out by the + * following tasks: + * - [ExtractPrecompiledScriptPluginPlugins] - extracts the `plugins` block of every precompiled script plugin and + * saves it to a file with the same name in the output directory + * - [GenerateInternalPluginSpecBuilders] - generates plugin spec builders for the _Project_ script plugins defined + * in the current module + * - [GenerateExternalPluginSpecBuilders] - generates plugin spec builders for the plugins in the compile classpath + * - [CompilePrecompiledScriptPluginPlugins] - compiles the extracted `plugins` blocks along with the internal + * and external plugin spec builders + * - [GeneratePrecompiledScriptPluginAccessors] - uses the compiled `plugins` block of each precompiled script plugin + * to compute its [HashedProjectSchema] and emit the corresponding type-safe accessors + * * ## Todo * - DONE type-safe plugin spec accessors for plugins in the precompiled script plugin classpath * - [ ] limit the set of type-safe accessors visible to a precompiled script plugin to @@ -132,30 +143,57 @@ fun Project.enableScriptCompilationOf(scriptPlugins: List) { "kotlinCompilerPluginClasspath"(gradleApi()) } - val generatedPluginSpecBuilders = generatedSourceDirFor("plugin-spec-builders") + val extractedPluginsBlocks = buildDir("kotlin-dsl/plugins-blocks/extracted") + + val compiledPluginsBlocks = buildDir("kotlin-dsl/plugins-blocks/compiled") + + val internalPluginSpecBuilders = generatedSourceDirFor("internal-plugin-spec-builders") + + val externalPluginSpecBuilders = generatedSourceDirFor("external-plugin-spec-builders") val generatedAccessors = generatedSourceDirFor("accessors") - val generatedMetadata = layout.buildDirectory.dir("precompiled-script-plugins") + val generatedMetadata = buildDir("precompiled-script-plugins") tasks { - val generatePluginSpecBuilders by registering(GeneratePluginSpecBuilders::class) { - classPathFiles = sourceSets["main"].compileClasspath - sourceCodeOutputDir.set(generatedPluginSpecBuilders) + val extractPrecompiledScriptPluginPlugins by registering(ExtractPrecompiledScriptPluginPlugins::class) { + plugins = scriptPlugins + outputDir.set(extractedPluginsBlocks) + } + + val generateInternalPluginSpecBuilders by registering(GenerateInternalPluginSpecBuilders::class) { + plugins = scriptPlugins + sourceCodeOutputDir.set(internalPluginSpecBuilders) + } + + val compileClasspath = compileClasspath() + + val generateExternalPluginSpecBuilders by registering(GenerateExternalPluginSpecBuilders::class) { + classPathFiles = compileClasspath + sourceCodeOutputDir.set(externalPluginSpecBuilders) + } + + val compilePluginsBlocks by registering(CompilePrecompiledScriptPluginPlugins::class) { + classPathFiles = compileClasspath + outputDir.set(compiledPluginsBlocks) + sourceDir(extractedPluginsBlocks) + sourceDir(internalPluginSpecBuilders) + sourceDir(externalPluginSpecBuilders) } val generatePrecompiledScriptPluginAccessors by registering(GeneratePrecompiledScriptPluginAccessors::class) { - dependsOn(generatePluginSpecBuilders) - classPathFiles = sourceSets["main"].compileClasspath + dependsOn(generateExternalPluginSpecBuilders) + dependsOn(compilePluginsBlocks) + classPathFiles = compileClasspath sourceCodeOutputDir.set(generatedAccessors) metadataOutputDir.set(generatedMetadata) - pluginSpecBuilders.set(generatedPluginSpecBuilders) + compiledPluginsBlocksDir.set(compiledPluginsBlocks) plugins = scriptPlugins } named("compileKotlin") { - dependsOn(generatePluginSpecBuilders) + dependsOn(generateExternalPluginSpecBuilders) dependsOn(generatePrecompiledScriptPluginAccessors) kotlinOptions { freeCompilerArgs += listOf( @@ -169,6 +207,10 @@ fun Project.enableScriptCompilationOf(scriptPlugins: List) { } +private +fun Project.compileClasspath() = sourceSets["main"].compileClasspath + + private fun Project.resolverEnvironmentFor( accessors: TaskProvider @@ -261,11 +303,14 @@ fun Project.generatePluginAdaptersFor(scriptPlugins: List) { private -fun Project.generatedSourceDirFor(purpose: String): Provider { - val generatedSourcesDir = layout.buildDirectory.dir("generated-sources/kotlin-dsl-$purpose/kotlin") - sourceSets["main"].kotlin.srcDir(generatedSourcesDir) - return generatedSourcesDir -} +fun Project.generatedSourceDirFor(purpose: String): Provider = + buildDir("generated-sources/kotlin-dsl-$purpose/kotlin").also { + sourceSets["main"].kotlin.srcDir(it) + } + + +private +fun Project.buildDir(path: String) = layout.buildDirectory.dir(path) private diff --git a/subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/ScriptPlugin.kt b/subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/ScriptPlugin.kt index 45d25173125e9..121026783c98e 100644 --- a/subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/ScriptPlugin.kt +++ b/subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/ScriptPlugin.kt @@ -20,6 +20,7 @@ import org.gradle.api.Plugin import org.gradle.api.Project import org.gradle.api.initialization.Settings import org.gradle.api.invocation.Gradle +import org.gradle.internal.hash.Hashing import org.gradle.kotlin.dsl.support.KotlinScriptType import org.gradle.kotlin.dsl.support.KotlinScriptTypeMatch @@ -98,6 +99,14 @@ data class ScriptPlugin(internal val scriptFile: File) { packageNameOf(scriptFile) } + val hashString by lazy { + hash.toString() + } + + val hash by lazy { + Hashing.hashString(scriptFile.readText()) + } + private fun packagePrefixed(id: String) = packageName?.let { "$it.$id" } ?: id From 7f901db222ba1a15fd69fe0cedb5a6947eea9193 Mon Sep 17 00:00:00 2001 From: "Rodrigo B. de Oliveira" Date: Fri, 8 Feb 2019 22:03:30 -0200 Subject: [PATCH 017/853] Move precompiled script plugin tasks into `tasks` subpackage --- .../precompiled/GenerateExternalPluginSpecBuilders.kt | 2 +- .../dsl/plugins/precompiled/GenerateScriptPluginAdapters.kt | 3 ++- .../dsl/plugins/precompiled/PrecompiledScriptPlugins.kt | 6 ++++++ .../{ => tasks}/ClassPathSensitiveCodeGenerationTask.kt | 2 +- .../precompiled/{ => tasks}/ClassPathSensitiveTask.kt | 2 +- .../{ => tasks}/CompilePrecompiledScriptPluginPlugins.kt | 2 +- .../{ => tasks}/ExtractPrecompiledScriptPluginPlugins.kt | 4 +++- .../{ => tasks}/GenerateInternalPluginSpecBuilders.kt | 3 ++- .../{ => tasks}/GeneratePrecompiledScriptPluginAccessors.kt | 5 +++-- .../kotlin/dsl/plugins/precompiled/ScriptPluginTest.kt | 2 ++ 10 files changed, 22 insertions(+), 9 deletions(-) rename subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/{ => tasks}/ClassPathSensitiveCodeGenerationTask.kt (94%) rename subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/{ => tasks}/ClassPathSensitiveTask.kt (96%) rename subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/{ => tasks}/CompilePrecompiledScriptPluginPlugins.kt (95%) rename subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/{ => tasks}/ExtractPrecompiledScriptPluginPlugins.kt (93%) rename subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/{ => tasks}/GenerateInternalPluginSpecBuilders.kt (92%) rename subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/{ => tasks}/GeneratePrecompiledScriptPluginAccessors.kt (97%) diff --git a/subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/GenerateExternalPluginSpecBuilders.kt b/subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/GenerateExternalPluginSpecBuilders.kt index 4b6d2adecc67a..b484bd61df525 100644 --- a/subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/GenerateExternalPluginSpecBuilders.kt +++ b/subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/GenerateExternalPluginSpecBuilders.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.gradle.kotlin.dsl.plugins.precompiled +package org.gradle.kotlin.dsl.plugins.precompiled.tasks import org.gradle.api.tasks.CacheableTask import org.gradle.api.tasks.Internal diff --git a/subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/GenerateScriptPluginAdapters.kt b/subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/GenerateScriptPluginAdapters.kt index 3578bb0ada9d8..6975f276cce62 100644 --- a/subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/GenerateScriptPluginAdapters.kt +++ b/subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/GenerateScriptPluginAdapters.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.gradle.kotlin.dsl.plugins.precompiled +package org.gradle.kotlin.dsl.plugins.precompiled.tasks import org.gradle.api.DefaultTask import org.gradle.api.file.DirectoryProperty @@ -25,6 +25,7 @@ import org.gradle.api.tasks.PathSensitive import org.gradle.api.tasks.PathSensitivity import org.gradle.api.tasks.OutputDirectory import org.gradle.api.tasks.TaskAction +import org.gradle.kotlin.dsl.plugins.precompiled.ScriptPlugin import org.gradle.kotlin.dsl.support.normaliseLineSeparators diff --git a/subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPlugins.kt b/subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPlugins.kt index 9bc9c7597b3af..e468ce3b63430 100644 --- a/subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPlugins.kt +++ b/subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPlugins.kt @@ -28,6 +28,12 @@ import org.gradle.api.tasks.SourceSetContainer import org.gradle.api.tasks.TaskProvider import org.gradle.kotlin.dsl.* +import org.gradle.kotlin.dsl.plugins.precompiled.tasks.CompilePrecompiledScriptPluginPlugins +import org.gradle.kotlin.dsl.plugins.precompiled.tasks.ExtractPrecompiledScriptPluginPlugins +import org.gradle.kotlin.dsl.plugins.precompiled.tasks.GenerateExternalPluginSpecBuilders +import org.gradle.kotlin.dsl.plugins.precompiled.tasks.GenerateInternalPluginSpecBuilders +import org.gradle.kotlin.dsl.plugins.precompiled.tasks.GeneratePrecompiledScriptPluginAccessors +import org.gradle.kotlin.dsl.plugins.precompiled.tasks.GenerateScriptPluginAdapters import org.gradle.kotlin.dsl.precompile.PrecompiledInitScript import org.gradle.kotlin.dsl.precompile.PrecompiledProjectScript diff --git a/subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/ClassPathSensitiveCodeGenerationTask.kt b/subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/ClassPathSensitiveCodeGenerationTask.kt similarity index 94% rename from subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/ClassPathSensitiveCodeGenerationTask.kt rename to subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/ClassPathSensitiveCodeGenerationTask.kt index d6113ef3257a6..d83df6bda7136 100644 --- a/subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/ClassPathSensitiveCodeGenerationTask.kt +++ b/subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/ClassPathSensitiveCodeGenerationTask.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.gradle.kotlin.dsl.plugins.precompiled +package org.gradle.kotlin.dsl.plugins.precompiled.tasks import org.gradle.api.tasks.OutputDirectory diff --git a/subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/ClassPathSensitiveTask.kt b/subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/ClassPathSensitiveTask.kt similarity index 96% rename from subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/ClassPathSensitiveTask.kt rename to subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/ClassPathSensitiveTask.kt index 9c4737688a8bd..d95607784e877 100644 --- a/subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/ClassPathSensitiveTask.kt +++ b/subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/ClassPathSensitiveTask.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.gradle.kotlin.dsl.plugins.precompiled +package org.gradle.kotlin.dsl.plugins.precompiled.tasks import org.gradle.api.DefaultTask import org.gradle.api.file.FileCollection diff --git a/subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/CompilePrecompiledScriptPluginPlugins.kt b/subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/CompilePrecompiledScriptPluginPlugins.kt similarity index 95% rename from subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/CompilePrecompiledScriptPluginPlugins.kt rename to subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/CompilePrecompiledScriptPluginPlugins.kt index 1ea1728d160ed..c05e11f53fd95 100644 --- a/subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/CompilePrecompiledScriptPluginPlugins.kt +++ b/subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/CompilePrecompiledScriptPluginPlugins.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.gradle.kotlin.dsl.plugins.precompiled +package org.gradle.kotlin.dsl.plugins.precompiled.tasks import org.gradle.api.file.Directory import org.gradle.api.provider.Provider diff --git a/subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/ExtractPrecompiledScriptPluginPlugins.kt b/subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/ExtractPrecompiledScriptPluginPlugins.kt similarity index 93% rename from subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/ExtractPrecompiledScriptPluginPlugins.kt rename to subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/ExtractPrecompiledScriptPluginPlugins.kt index ae30f91bd9758..37e10acb9bf5b 100644 --- a/subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/ExtractPrecompiledScriptPluginPlugins.kt +++ b/subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/ExtractPrecompiledScriptPluginPlugins.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.gradle.kotlin.dsl.plugins.precompiled +package org.gradle.kotlin.dsl.plugins.precompiled.tasks import org.gradle.api.DefaultTask import org.gradle.api.Project @@ -26,6 +26,8 @@ import org.gradle.api.tasks.PathSensitive import org.gradle.api.tasks.PathSensitivity import org.gradle.api.tasks.TaskAction +import org.gradle.kotlin.dsl.plugins.precompiled.ScriptPlugin + import java.io.File diff --git a/subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/GenerateInternalPluginSpecBuilders.kt b/subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/GenerateInternalPluginSpecBuilders.kt similarity index 92% rename from subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/GenerateInternalPluginSpecBuilders.kt rename to subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/GenerateInternalPluginSpecBuilders.kt index c6b887c0b437a..4b8788faf3148 100644 --- a/subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/GenerateInternalPluginSpecBuilders.kt +++ b/subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/GenerateInternalPluginSpecBuilders.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.gradle.kotlin.dsl.plugins.precompiled +package org.gradle.kotlin.dsl.plugins.precompiled.tasks import org.gradle.api.tasks.CacheableTask import org.gradle.api.tasks.InputFiles @@ -22,6 +22,7 @@ import org.gradle.api.tasks.Internal import org.gradle.api.tasks.PathSensitive import org.gradle.api.tasks.PathSensitivity import org.gradle.api.tasks.TaskAction +import org.gradle.kotlin.dsl.plugins.precompiled.ScriptPlugin import java.io.File diff --git a/subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/GeneratePrecompiledScriptPluginAccessors.kt b/subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/GeneratePrecompiledScriptPluginAccessors.kt similarity index 97% rename from subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/GeneratePrecompiledScriptPluginAccessors.kt rename to subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/GeneratePrecompiledScriptPluginAccessors.kt index 18020190c0b79..9c3c988d2b9da 100644 --- a/subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/GeneratePrecompiledScriptPluginAccessors.kt +++ b/subprojects/plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/GeneratePrecompiledScriptPluginAccessors.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.gradle.kotlin.dsl.plugins.precompiled +package org.gradle.kotlin.dsl.plugins.precompiled.tasks import org.gradle.api.tasks.CacheableTask import org.gradle.api.tasks.InputDirectory @@ -26,7 +26,6 @@ import org.gradle.api.tasks.PathSensitivity import org.gradle.api.tasks.TaskAction import org.gradle.internal.hash.HashCode -import org.gradle.internal.hash.Hashing.hashString import org.gradle.kotlin.dsl.accessors.TypedProjectSchema import org.gradle.kotlin.dsl.accessors.hashCodeFor @@ -35,6 +34,8 @@ import org.gradle.kotlin.dsl.concurrent.IO import org.gradle.kotlin.dsl.concurrent.withAsynchronousIO import org.gradle.kotlin.dsl.concurrent.writeFile +import org.gradle.kotlin.dsl.plugins.precompiled.ScriptPlugin + import org.gradle.kotlin.dsl.support.KotlinScriptType import java.io.File diff --git a/subprojects/plugins/src/test/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/ScriptPluginTest.kt b/subprojects/plugins/src/test/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/ScriptPluginTest.kt index d54d4880bf76c..97ccea55393d4 100644 --- a/subprojects/plugins/src/test/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/ScriptPluginTest.kt +++ b/subprojects/plugins/src/test/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/ScriptPluginTest.kt @@ -2,6 +2,8 @@ package org.gradle.kotlin.dsl.plugins.precompiled import org.gradle.kotlin.dsl.fixtures.TestWithTempFiles +import org.gradle.kotlin.dsl.plugins.precompiled.tasks.writeScriptPluginAdapterTo + import org.hamcrest.CoreMatchers.equalTo import org.hamcrest.CoreMatchers.startsWith import org.hamcrest.MatcherAssert.assertThat From a5c883c896b31aa2198ccdd32f325a6f4fc9377e Mon Sep 17 00:00:00 2001 From: "Rodrigo B. de Oliveira" Date: Sat, 9 Feb 2019 13:11:05 -0200 Subject: [PATCH 018/853] Fix merge gone wrong --- .../gradle/kotlin/dsl/accessors/PluginAccessorsClassPathTest.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/subprojects/kotlin-dsl/src/test/kotlin/org/gradle/kotlin/dsl/accessors/PluginAccessorsClassPathTest.kt b/subprojects/kotlin-dsl/src/test/kotlin/org/gradle/kotlin/dsl/accessors/PluginAccessorsClassPathTest.kt index 35a66fc63b731..bb56de9e4b200 100644 --- a/subprojects/kotlin-dsl/src/test/kotlin/org/gradle/kotlin/dsl/accessors/PluginAccessorsClassPathTest.kt +++ b/subprojects/kotlin-dsl/src/test/kotlin/org/gradle/kotlin/dsl/accessors/PluginAccessorsClassPathTest.kt @@ -27,7 +27,6 @@ import org.gradle.kotlin.dsl.concurrent.withSynchronousIO import org.gradle.kotlin.dsl.fixtures.classLoaderFor import org.gradle.kotlin.dsl.fixtures.containsMultiLineString import org.gradle.kotlin.dsl.fixtures.jarWithPluginDescriptors -import org.gradle.kotlin.dsl.fixtures.toPlatformLineSeparators import org.gradle.kotlin.dsl.support.normaliseLineSeparators import org.gradle.kotlin.dsl.support.useToRun From f8d80e444ca6f3876a2e61950678cf83b9bf1b73 Mon Sep 17 00:00:00 2001 From: "Rodrigo B. de Oliveira" Date: Tue, 12 Feb 2019 18:40:57 -0200 Subject: [PATCH 019/853] Let all Kotlin DSL plugin tests have a default `settings.gradle.kts` --- .../precompiled/AbstractPrecompiledScriptPluginTest.kt | 4 +++- .../dsl/plugins/precompiled/PrecompiledScriptPluginTest.kt | 1 - 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/subprojects/kotlin-dsl-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/AbstractPrecompiledScriptPluginTest.kt b/subprojects/kotlin-dsl-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/AbstractPrecompiledScriptPluginTest.kt index 0f5e0b4127471..47c5384ca7315 100644 --- a/subprojects/kotlin-dsl-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/AbstractPrecompiledScriptPluginTest.kt +++ b/subprojects/kotlin-dsl-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/AbstractPrecompiledScriptPluginTest.kt @@ -25,8 +25,10 @@ import org.junit.Before open class AbstractPrecompiledScriptPluginTest : AbstractPluginTest() { @Before - fun setupPluginTest() = + fun setupPluginTest() { requireGradleDistributionOnEmbeddedExecuter() + withDefaultSettings() + } protected fun givenPrecompiledKotlinScript(fileName: String, code: String) { diff --git a/subprojects/kotlin-dsl-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPluginTest.kt b/subprojects/kotlin-dsl-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPluginTest.kt index 91d540feba900..3386577111005 100644 --- a/subprojects/kotlin-dsl-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPluginTest.kt +++ b/subprojects/kotlin-dsl-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPluginTest.kt @@ -98,7 +98,6 @@ class PrecompiledScriptPluginTest : AbstractPrecompiledScriptPluginTest() { // given: val expectedMessage = "Not on my watch!" - withDefaultSettings() withKotlinDslPlugin() withFile("src/main/kotlin/my-project-script.gradle.kts", """ From a77eadf16ab4fe829a0a96cd7efa91124e4cb377 Mon Sep 17 00:00:00 2001 From: "Rodrigo B. de Oliveira" Date: Tue, 12 Feb 2019 19:01:12 -0200 Subject: [PATCH 020/853] Let `AbstractPluginTest` require `future-plugin-versions.properties` In order to avoid hard to detect issues caused by the tests running against the published version of the plugins instead of their local versions. --- .../org/gradle/kotlin/dsl/fixtures/AbstractPluginTest.kt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/subprojects/kotlin-dsl-test-fixtures/src/main/kotlin/org/gradle/kotlin/dsl/fixtures/AbstractPluginTest.kt b/subprojects/kotlin-dsl-test-fixtures/src/main/kotlin/org/gradle/kotlin/dsl/fixtures/AbstractPluginTest.kt index 43ab411fef483..28a8f98b9407c 100644 --- a/subprojects/kotlin-dsl-test-fixtures/src/main/kotlin/org/gradle/kotlin/dsl/fixtures/AbstractPluginTest.kt +++ b/subprojects/kotlin-dsl-test-fixtures/src/main/kotlin/org/gradle/kotlin/dsl/fixtures/AbstractPluginTest.kt @@ -1,9 +1,8 @@ package org.gradle.kotlin.dsl.fixtures import org.gradle.util.TextUtil.normaliseFileSeparators - import java.io.File -import java.util.* +import java.util.Properties /** @@ -54,8 +53,8 @@ open class AbstractPluginTest : AbstractKotlinIntegrationTest() { """ private - val futurePluginRules: String? - get() = futurePluginVersions?.entries?.joinLines { (id, version) -> + val futurePluginRules: String + get() = futurePluginVersions.entries.joinLines { (id, version) -> """ if (requested.id.id == "$id") { useVersion("$version") @@ -66,6 +65,7 @@ open class AbstractPluginTest : AbstractKotlinIntegrationTest() { private val futurePluginVersions by lazy { loadPropertiesFromResource("/future-plugin-versions.properties") + ?: throw IllegalStateException("/future-plugin-versions.properties resource not found. Run intTestImage.") } private From 254670bd3e7dffecff94a2b74e22d6bb9ee350a2 Mon Sep 17 00:00:00 2001 From: "Rodrigo B. de Oliveira" Date: Tue, 12 Feb 2019 19:02:24 -0200 Subject: [PATCH 021/853] Polish `AbstractPluginTest` Declare type explicitly to avoid platform type. --- .../kotlin/org/gradle/kotlin/dsl/fixtures/AbstractPluginTest.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subprojects/kotlin-dsl-test-fixtures/src/main/kotlin/org/gradle/kotlin/dsl/fixtures/AbstractPluginTest.kt b/subprojects/kotlin-dsl-test-fixtures/src/main/kotlin/org/gradle/kotlin/dsl/fixtures/AbstractPluginTest.kt index 28a8f98b9407c..c4622a4d4dd2c 100644 --- a/subprojects/kotlin-dsl-test-fixtures/src/main/kotlin/org/gradle/kotlin/dsl/fixtures/AbstractPluginTest.kt +++ b/subprojects/kotlin-dsl-test-fixtures/src/main/kotlin/org/gradle/kotlin/dsl/fixtures/AbstractPluginTest.kt @@ -87,7 +87,7 @@ open class AbstractPluginTest : AbstractKotlinIntegrationTest() { paths.map(::normalisedPathOf) protected - fun normalisedPathOf(relativePath: String) = + fun normalisedPathOf(relativePath: String): String = normaliseFileSeparators(absolutePathOf(relativePath)) private From 0d2916d67cdcc7e75845852d47e50a0920956337 Mon Sep 17 00:00:00 2001 From: "Rodrigo B. de Oliveira" Date: Tue, 12 Feb 2019 19:06:42 -0200 Subject: [PATCH 022/853] Wire generated source code dirs via `files(...).builtBy(...)` In order to preserve the task association. --- .../precompiled/PrecompiledScriptPlugins.kt | 68 +++++++++++-------- .../GenerateInternalPluginSpecBuilders.kt | 8 ++- 2 files changed, 47 insertions(+), 29 deletions(-) diff --git a/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPlugins.kt b/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPlugins.kt index e468ce3b63430..9f16cfa0bcfb7 100644 --- a/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPlugins.kt +++ b/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPlugins.kt @@ -17,6 +17,7 @@ package org.gradle.kotlin.dsl.plugins.precompiled import org.gradle.api.Plugin import org.gradle.api.Project +import org.gradle.api.Task import org.gradle.api.file.Directory import org.gradle.api.file.SourceDirectorySet import org.gradle.api.initialization.Settings @@ -153,14 +154,10 @@ fun Project.enableScriptCompilationOf(scriptPlugins: List) { val compiledPluginsBlocks = buildDir("kotlin-dsl/plugins-blocks/compiled") - val internalPluginSpecBuilders = generatedSourceDirFor("internal-plugin-spec-builders") - - val externalPluginSpecBuilders = generatedSourceDirFor("external-plugin-spec-builders") - - val generatedAccessors = generatedSourceDirFor("accessors") - val generatedMetadata = buildDir("precompiled-script-plugins") + val compileClasspath = compileClasspath() + tasks { val extractPrecompiledScriptPluginPlugins by registering(ExtractPrecompiledScriptPluginPlugins::class) { @@ -168,19 +165,28 @@ fun Project.enableScriptCompilationOf(scriptPlugins: List) { outputDir.set(extractedPluginsBlocks) } - val generateInternalPluginSpecBuilders by registering(GenerateInternalPluginSpecBuilders::class) { - plugins = scriptPlugins - sourceCodeOutputDir.set(internalPluginSpecBuilders) - } - - val compileClasspath = compileClasspath() + val (generateInternalPluginSpecBuilders, internalPluginSpecBuilders) = + codeGenerationTask( + "internal-plugin-spec-builders", + "generateInternalPluginSpecBuilders" + ) { + plugins = scriptPlugins + sourceCodeOutputDir.set(it) + } - val generateExternalPluginSpecBuilders by registering(GenerateExternalPluginSpecBuilders::class) { - classPathFiles = compileClasspath - sourceCodeOutputDir.set(externalPluginSpecBuilders) - } + val (generateExternalPluginSpecBuilders, externalPluginSpecBuilders) = + codeGenerationTask( + "external-plugin-spec-builders", + "generateExternalPluginSpecBuilders" + ) { + classPathFiles = compileClasspath + sourceCodeOutputDir.set(it) + } val compilePluginsBlocks by registering(CompilePrecompiledScriptPluginPlugins::class) { + dependsOn(extractPrecompiledScriptPluginPlugins) + dependsOn(generateInternalPluginSpecBuilders) + dependsOn(generateExternalPluginSpecBuilders) classPathFiles = compileClasspath outputDir.set(compiledPluginsBlocks) sourceDir(extractedPluginsBlocks) @@ -188,8 +194,8 @@ fun Project.enableScriptCompilationOf(scriptPlugins: List) { sourceDir(externalPluginSpecBuilders) } + val generatedAccessors = generatedSourceDirFor("accessors") val generatePrecompiledScriptPluginAccessors by registering(GeneratePrecompiledScriptPluginAccessors::class) { - dependsOn(generateExternalPluginSpecBuilders) dependsOn(compilePluginsBlocks) classPathFiles = compileClasspath sourceCodeOutputDir.set(generatedAccessors) @@ -199,8 +205,9 @@ fun Project.enableScriptCompilationOf(scriptPlugins: List) { } named("compileKotlin") { - dependsOn(generateExternalPluginSpecBuilders) dependsOn(generatePrecompiledScriptPluginAccessors) + dependsOn(generateInternalPluginSpecBuilders) + dependsOn(generateExternalPluginSpecBuilders) kotlinOptions { freeCompilerArgs += listOf( "-script-templates", scriptTemplates, @@ -292,19 +299,24 @@ fun Project.declareScriptPlugins(scriptPlugins: List) { private fun Project.generatePluginAdaptersFor(scriptPlugins: List) { - val generatedSourcesDir = generatedSourceDirFor("plugins") - - tasks { + codeGenerationTask("plugins", "generateScriptPluginAdapters") { + plugins = scriptPlugins + outputDirectory.set(it) + } +} - val generateScriptPluginAdapters by registering(GenerateScriptPluginAdapters::class) { - plugins = scriptPlugins - outputDirectory.set(generatedSourcesDir) - } - "compileKotlin" { - dependsOn(generateScriptPluginAdapters) - } +private +inline fun Project.codeGenerationTask( + purpose: String, + taskName: String, + noinline configure: T.(Provider) -> Unit +) = buildDir("generated-sources/kotlin-dsl-$purpose/kotlin").let { outputDir -> + val task = tasks.register(taskName, T::class.java) { + it.configure(outputDir) } + sourceSets["main"].kotlin.srcDir(files(outputDir).builtBy(task)) + task to outputDir } diff --git a/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/GenerateInternalPluginSpecBuilders.kt b/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/GenerateInternalPluginSpecBuilders.kt index 4b8788faf3148..a5ca8e06540f3 100644 --- a/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/GenerateInternalPluginSpecBuilders.kt +++ b/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/GenerateInternalPluginSpecBuilders.kt @@ -16,12 +16,15 @@ package org.gradle.kotlin.dsl.plugins.precompiled.tasks +import org.gradle.api.DefaultTask import org.gradle.api.tasks.CacheableTask import org.gradle.api.tasks.InputFiles import org.gradle.api.tasks.Internal +import org.gradle.api.tasks.OutputDirectory import org.gradle.api.tasks.PathSensitive import org.gradle.api.tasks.PathSensitivity import org.gradle.api.tasks.TaskAction + import org.gradle.kotlin.dsl.plugins.precompiled.ScriptPlugin import java.io.File @@ -31,7 +34,7 @@ import java.io.File * Generates plugin spec builders for the _Project_ script plugins defined in the current module. */ @CacheableTask -open class GenerateInternalPluginSpecBuilders : ClassPathSensitiveCodeGenerationTask() { +open class GenerateInternalPluginSpecBuilders : DefaultTask() { @get:Internal internal @@ -44,6 +47,9 @@ open class GenerateInternalPluginSpecBuilders : ClassPathSensitiveCodeGeneration val scriptFiles: Set get() = scriptPluginFilesOf(plugins) + @get:OutputDirectory + var sourceCodeOutputDir = project.objects.directoryProperty() + @TaskAction fun generate() { // TODO() From a8c4f7244872ca8a563e61f52d6845ebfbc2a34d Mon Sep 17 00:00:00 2001 From: Peter Ledbrook Date: Thu, 14 Feb 2019 11:17:32 +0000 Subject: [PATCH 023/853] Fix info about Java Plugin test configurations The chapter erroneously said that the `test` task uses the `testRuntime` and `testRuntimeOnly` configurations, when in fact it specifically uses the `testRuntimeClasspath` one. The chapter now reflects reality. Resolves issue #5681. --- subprojects/docs/src/docs/userguide/java_plugin.adoc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/subprojects/docs/src/docs/userguide/java_plugin.adoc b/subprojects/docs/src/docs/userguide/java_plugin.adoc index fbe79b11cdc68..ff089e8cc7351 100644 --- a/subprojects/docs/src/docs/userguide/java_plugin.adoc +++ b/subprojects/docs/src/docs/userguide/java_plugin.adoc @@ -335,16 +335,16 @@ Additional dependencies only for compiling tests, not used at runtime. Test compile classpath, used when compiling test sources. Used by task `compileTestJava`. [.line-through]#`testRuntime`#(Deprecated) extends `runtime, testCompile`:: -Additional dependencies for running tests only. Used by task `test`. Superseded by `testRuntimeOnly`. +Additional dependencies for running tests only. Superseded by `testRuntimeOnly`. `testRuntimeOnly` extends `runtimeOnly`:: -Runtime only dependencies for running tests. Used by task `test`. +Runtime only dependencies for running tests. `testRuntimeClasspath` extends `testRuntimeOnly, testRuntime, testImplementation`:: -Runtime classpath for running tests. +Runtime classpath for running tests. Used by task `test`. `archives`:: -Artifacts (e.g. jars) produced by this project. Used by tasks `uploadArchives`. +Artifacts (e.g. jars) produced by this project. Used by task `uploadArchives`. `default` extends `runtime`:: The default configuration used by a project dependency on this project. Contains the artifacts and dependencies required by this project at runtime. From 7ab53f4441f08856901081a1214d12decb8307f5 Mon Sep 17 00:00:00 2001 From: "Rodrigo B. de Oliveira" Date: Thu, 14 Feb 2019 18:02:22 -0200 Subject: [PATCH 024/853] Honour Kotlin DSL coding conventions in generated code - Keep visibility modifiers in separate lines --- .../org/gradle/kotlin/dsl/accessors/PluginAccessorsClassPath.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/accessors/PluginAccessorsClassPath.kt b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/accessors/PluginAccessorsClassPath.kt index 9d7db9728e97b..d9f143124fdb4 100644 --- a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/accessors/PluginAccessorsClassPath.kt +++ b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/accessors/PluginAccessorsClassPath.kt @@ -108,7 +108,7 @@ fun writeSourceCodeForPluginSpecBuildersFor( writePluginAccessorsSourceCodeTo( sourceFile, pluginAccessorsFor(pluginDescriptorsClassPath), - accessibility = "internal ", + accessibility = "internal\n", header = fileHeaderFor(packageName) ) } From 66787ddd118968c8a443df48db305cb4c43285ec Mon Sep 17 00:00:00 2001 From: "Rodrigo B. de Oliveira" Date: Thu, 14 Feb 2019 18:04:35 -0200 Subject: [PATCH 025/853] Let `AbstractPluginTest` write default settings file To avoid hard to diagnose situations where the test ends up running against the published version of a plugin instead of its local version. --- .../GradleApiExtensionsIntegrationTest.kt | 15 ++-------- .../PrecompiledScriptPluginIntegrationTest.kt | 5 +--- .../ProjectSchemaAccessorsIntegrationTest.kt | 30 ++++--------------- ...PluginGradlePluginCrossVersionSmokeTest.kt | 1 - .../dsl/plugins/dsl/KotlinDslPluginTest.kt | 7 +---- .../embedded/EmbeddedKotlinPluginTest.kt | 9 ++---- .../AbstractPrecompiledScriptPluginTest.kt | 1 - .../kotlin/dsl/fixtures/AbstractPluginTest.kt | 9 ++++++ 8 files changed, 20 insertions(+), 57 deletions(-) diff --git a/subprojects/kotlin-dsl-integ-tests/src/integTest/kotlin/org/gradle/kotlin/dsl/integration/GradleApiExtensionsIntegrationTest.kt b/subprojects/kotlin-dsl-integ-tests/src/integTest/kotlin/org/gradle/kotlin/dsl/integration/GradleApiExtensionsIntegrationTest.kt index c6a8307916175..b6b7fb7cbbfb2 100644 --- a/subprojects/kotlin-dsl-integ-tests/src/integTest/kotlin/org/gradle/kotlin/dsl/integration/GradleApiExtensionsIntegrationTest.kt +++ b/subprojects/kotlin-dsl-integ-tests/src/integTest/kotlin/org/gradle/kotlin/dsl/integration/GradleApiExtensionsIntegrationTest.kt @@ -44,7 +44,6 @@ class GradleApiExtensionsIntegrationTest : AbstractPluginIntegrationTest() { @Test fun `Kotlin chooses withType extension specialized to container type`() { - withDefaultSettings() withBuildScript(""" open class A @@ -96,7 +95,7 @@ class GradleApiExtensionsIntegrationTest : AbstractPluginIntegrationTest() { } """) - withSettings(""" + withDefaultSettings().appendText(""" buildCache { local(DirectoryBuildCache::class) } @@ -144,15 +143,7 @@ class GradleApiExtensionsIntegrationTest : AbstractPluginIntegrationTest() { requireGradleDistributionOnEmbeddedExecuter() - withDefaultSettingsIn("buildSrc") - - withBuildScriptIn("buildSrc", """ - plugins { - `kotlin-dsl` - } - - $repositoriesBlock - """) + withKotlinBuildSrc() withFile("buildSrc/src/main/kotlin/foo/FooTask.kt", """ package foo @@ -179,7 +170,6 @@ class GradleApiExtensionsIntegrationTest : AbstractPluginIntegrationTest() { tasks.register("foo", FooTask::class) """) - withDefaultSettings() withBuildScript(""" plugins { id("foo.foo") @@ -194,7 +184,6 @@ class GradleApiExtensionsIntegrationTest : AbstractPluginIntegrationTest() { val guh = newDir("guh") - withDefaultSettings() withBuildScript("") executer.withGradleUserHomeDir(guh) diff --git a/subprojects/kotlin-dsl-integ-tests/src/integTest/kotlin/org/gradle/kotlin/dsl/integration/PrecompiledScriptPluginIntegrationTest.kt b/subprojects/kotlin-dsl-integ-tests/src/integTest/kotlin/org/gradle/kotlin/dsl/integration/PrecompiledScriptPluginIntegrationTest.kt index 4d0f40bbabe60..541994d305b3e 100644 --- a/subprojects/kotlin-dsl-integ-tests/src/integTest/kotlin/org/gradle/kotlin/dsl/integration/PrecompiledScriptPluginIntegrationTest.kt +++ b/subprojects/kotlin-dsl-integ-tests/src/integTest/kotlin/org/gradle/kotlin/dsl/integration/PrecompiledScriptPluginIntegrationTest.kt @@ -14,7 +14,6 @@ class PrecompiledScriptPluginIntegrationTest : AbstractPluginIntegrationTest() { @Test fun `generated code follows kotlin-dsl coding conventions`() { - withDefaultSettings() withBuildScript(""" plugins { `kotlin-dsl` @@ -44,9 +43,8 @@ class PrecompiledScriptPluginIntegrationTest : AbstractPluginIntegrationTest() { val secondLocation = "second-location" val cacheDir = newDir("cache-dir") - withSettingsIn(firstLocation, """ + withDefaultSettingsIn(firstLocation).appendText(""" rootProject.name = "test" - $pluginManagementBlock buildCache { local { directory = file("${cacheDir.normalisedPath}") @@ -86,7 +84,6 @@ class PrecompiledScriptPluginIntegrationTest : AbstractPluginIntegrationTest() { @Test fun `precompiled script plugins adapters generation clean stale outputs`() { - withDefaultSettings() withBuildScript(""" plugins { `kotlin-dsl` } repositories { jcenter() } diff --git a/subprojects/kotlin-dsl-integ-tests/src/integTest/kotlin/org/gradle/kotlin/dsl/integration/ProjectSchemaAccessorsIntegrationTest.kt b/subprojects/kotlin-dsl-integ-tests/src/integTest/kotlin/org/gradle/kotlin/dsl/integration/ProjectSchemaAccessorsIntegrationTest.kt index 9e909f732c937..16d8cd99206b2 100644 --- a/subprojects/kotlin-dsl-integ-tests/src/integTest/kotlin/org/gradle/kotlin/dsl/integration/ProjectSchemaAccessorsIntegrationTest.kt +++ b/subprojects/kotlin-dsl-integ-tests/src/integTest/kotlin/org/gradle/kotlin/dsl/integration/ProjectSchemaAccessorsIntegrationTest.kt @@ -40,8 +40,7 @@ class ProjectSchemaAccessorsIntegrationTest : AbstractPluginIntegrationTest() { requireGradleDistributionOnEmbeddedExecuter() - withSettings(""" - $pluginManagementBlock + withDefaultSettings().appendText(""" include(":sub") """) @@ -114,7 +113,6 @@ class ProjectSchemaAccessorsIntegrationTest : AbstractPluginIntegrationTest() { } } - withDefaultSettings() withBuildScript(""" plugins { id("plugin") } @@ -173,7 +171,6 @@ class ProjectSchemaAccessorsIntegrationTest : AbstractPluginIntegrationTest() { } } - withDefaultSettings() withBuildScript(""" plugins { id("plugin") } @@ -211,7 +208,6 @@ class ProjectSchemaAccessorsIntegrationTest : AbstractPluginIntegrationTest() { } } - withDefaultSettings() withBuildScript(""" plugins { id("plugin") } @@ -258,7 +254,6 @@ class ProjectSchemaAccessorsIntegrationTest : AbstractPluginIntegrationTest() { } } - withDefaultSettings() withBuildScript(""" plugins { id("my.plugin") } @@ -326,7 +321,6 @@ class ProjectSchemaAccessorsIntegrationTest : AbstractPluginIntegrationTest() { } } - withDefaultSettings() withBuildScript(""" plugins { id("my.plugin") } @@ -421,8 +415,6 @@ class ProjectSchemaAccessorsIntegrationTest : AbstractPluginIntegrationTest() { plugins { id("app-or-lib") } my { name = "kotlin-dsl" } """) - - withDefaultSettings() } build("tasks", "-Pmy=lib") @@ -446,8 +438,6 @@ class ProjectSchemaAccessorsIntegrationTest : AbstractPluginIntegrationTest() { @Test fun `can configure publishing extension`() { - withDefaultSettings() - withBuildScript(""" plugins { @@ -513,7 +503,6 @@ class ProjectSchemaAccessorsIntegrationTest : AbstractPluginIntegrationTest() { """) } - withDefaultSettings() withBuildScript(""" plugins { @@ -544,7 +533,6 @@ class ProjectSchemaAccessorsIntegrationTest : AbstractPluginIntegrationTest() { @Test fun `can access extensions registered by declared plugins via jit accessor`() { - withDefaultSettings() withBuildScript(""" plugins { application } @@ -564,7 +552,7 @@ class ProjectSchemaAccessorsIntegrationTest : AbstractPluginIntegrationTest() { @Test fun `can access configurations registered by declared plugins via jit accessor`() { - withSettings(""" + withDefaultSettings().appendText(""" include("a", "b", "c") """) @@ -656,7 +644,6 @@ class ProjectSchemaAccessorsIntegrationTest : AbstractPluginIntegrationTest() { } """) - withDefaultSettings() withBuildScript(""" plugins { id("my-plugin") @@ -706,7 +693,9 @@ class ProjectSchemaAccessorsIntegrationTest : AbstractPluginIntegrationTest() { @Test fun `accessors tasks applied in a mixed Groovy-Kotlin multi-project build`() { - withSettings("include(\"a\")") + withDefaultSettings().appendText(""" + include("a") + """) withBuildScriptIn("a", "") val aTasks = build(":a:tasks").output @@ -741,7 +730,6 @@ class ProjectSchemaAccessorsIntegrationTest : AbstractPluginIntegrationTest() { } """) - withDefaultSettings() withBuildScript(""" inline fun typeOf(t: T) = T::class.simpleName @@ -794,7 +782,6 @@ class ProjectSchemaAccessorsIntegrationTest : AbstractPluginIntegrationTest() { } """) - withDefaultSettings() withBuildScript(""" plugins { id("mine") @@ -890,7 +877,6 @@ class ProjectSchemaAccessorsIntegrationTest : AbstractPluginIntegrationTest() { } """) - withDefaultSettings() withBuildScript(""" plugins { id("my-plugin") @@ -960,7 +946,6 @@ class ProjectSchemaAccessorsIntegrationTest : AbstractPluginIntegrationTest() { class MyPrivateConventionImpl : MyConvention """) - withDefaultSettings() withBuildScript(""" plugins { id("my-plugin") @@ -999,7 +984,6 @@ class ProjectSchemaAccessorsIntegrationTest : AbstractPluginIntegrationTest() { @Test fun `accessors to existing configurations`() { - withDefaultSettings() withBuildScript(""" plugins { java @@ -1024,7 +1008,6 @@ class ProjectSchemaAccessorsIntegrationTest : AbstractPluginIntegrationTest() { @Test fun `accessors to existing tasks`() { - withDefaultSettings() withBuildScript(""" plugins { java @@ -1053,7 +1036,6 @@ class ProjectSchemaAccessorsIntegrationTest : AbstractPluginIntegrationTest() { @Test fun `accessors to existing source sets`() { - withDefaultSettings() withBuildScript(""" plugins { java @@ -1093,7 +1075,6 @@ class ProjectSchemaAccessorsIntegrationTest : AbstractPluginIntegrationTest() { @Test fun `accessors to existing elements of extensions that are containers`() { - withDefaultSettings() withBuildScript(""" plugins { distribution @@ -1125,7 +1106,6 @@ class ProjectSchemaAccessorsIntegrationTest : AbstractPluginIntegrationTest() { (dependencies as ExtensionAware).extensions.create("mine") """) - withDefaultSettings() withBuildScript(""" plugins { `my-plugin` diff --git a/subprojects/kotlin-dsl-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/plugins/dsl/KotlinDslPluginGradlePluginCrossVersionSmokeTest.kt b/subprojects/kotlin-dsl-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/plugins/dsl/KotlinDslPluginGradlePluginCrossVersionSmokeTest.kt index c9e8802efa926..e19b4cd6b4d6d 100644 --- a/subprojects/kotlin-dsl-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/plugins/dsl/KotlinDslPluginGradlePluginCrossVersionSmokeTest.kt +++ b/subprojects/kotlin-dsl-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/plugins/dsl/KotlinDslPluginGradlePluginCrossVersionSmokeTest.kt @@ -80,7 +80,6 @@ class KotlinDslPluginGradlePluginCrossVersionSmokeTest( apply() """) - withDefaultSettings() withBuildScript(""" import org.jetbrains.kotlin.config.KotlinCompilerVersion diff --git a/subprojects/kotlin-dsl-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/plugins/dsl/KotlinDslPluginTest.kt b/subprojects/kotlin-dsl-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/plugins/dsl/KotlinDslPluginTest.kt index 81f66c601b7cb..08c8cf827a1af 100644 --- a/subprojects/kotlin-dsl-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/plugins/dsl/KotlinDslPluginTest.kt +++ b/subprojects/kotlin-dsl-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/plugins/dsl/KotlinDslPluginTest.kt @@ -26,7 +26,6 @@ class KotlinDslPluginTest : AbstractPluginTest() { @Test fun `gradle kotlin dsl api dependency is added`() { - withDefaultSettings() withKotlinDslPlugin() withFile("src/main/kotlin/code.kt", """ @@ -47,7 +46,6 @@ class KotlinDslPluginTest : AbstractPluginTest() { @Test fun `gradle kotlin dsl api is available for test implementation`() { - withDefaultSettings() withBuildScript(""" plugins { @@ -102,7 +100,6 @@ class KotlinDslPluginTest : AbstractPluginTest() { @Test fun `gradle kotlin dsl api is available in test-kit injected plugin classpath`() { - withDefaultSettings() withBuildScript(""" plugins { @@ -195,7 +192,6 @@ class KotlinDslPluginTest : AbstractPluginTest() { @Test fun `sam-with-receiver kotlin compiler plugin is applied to production code`() { - withDefaultSettings() withKotlinDslPlugin() withFile("src/main/kotlin/code.kt", """ @@ -290,7 +286,7 @@ class KotlinDslPluginTest : AbstractPluginTest() { private fun withBuildExercisingSamConversionForKotlinFunctions(buildSrcScript: String = "") { - withSettingsIn("buildSrc", pluginManagementBlock) + withDefaultSettingsIn("buildSrc") withBuildScriptIn("buildSrc", """ @@ -327,7 +323,6 @@ class KotlinDslPluginTest : AbstractPluginTest() { } """) - withDefaultSettings() withBuildScript(""" task("test") { diff --git a/subprojects/kotlin-dsl-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/plugins/embedded/EmbeddedKotlinPluginTest.kt b/subprojects/kotlin-dsl-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/plugins/embedded/EmbeddedKotlinPluginTest.kt index 02d4afe14c76b..d2f2d02d7def1 100644 --- a/subprojects/kotlin-dsl-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/plugins/embedded/EmbeddedKotlinPluginTest.kt +++ b/subprojects/kotlin-dsl-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/plugins/embedded/EmbeddedKotlinPluginTest.kt @@ -36,7 +36,6 @@ class EmbeddedKotlinPluginTest : AbstractPluginTest() { @Test fun `applies the kotlin plugin`() { - withDefaultSettings() withBuildScript(""" plugins { @@ -52,7 +51,7 @@ class EmbeddedKotlinPluginTest : AbstractPluginTest() { @Test fun `adds stdlib and reflect as compile only dependencies`() { - withDefaultSettings() + withBuildScript(""" plugins { @@ -80,7 +79,6 @@ class EmbeddedKotlinPluginTest : AbstractPluginTest() { @Test fun `all embedded kotlin dependencies are resolvable without any added repository`() { - withDefaultSettings() withBuildScript(""" plugins { @@ -107,7 +105,6 @@ class EmbeddedKotlinPluginTest : AbstractPluginTest() { @Test fun `sources and javadoc of all embedded kotlin dependencies are resolvable with an added repository`() { - withDefaultSettings() withBuildScript(""" plugins { @@ -165,7 +162,6 @@ class EmbeddedKotlinPluginTest : AbstractPluginTest() { @Test fun `can add embedded dependencies to custom configuration`() { - withDefaultSettings() withBuildScript(""" plugins { @@ -190,8 +186,7 @@ class EmbeddedKotlinPluginTest : AbstractPluginTest() { @LeaksFileHandles("Kotlin Compiler Daemon working directory") fun `can be used with GRADLE_METADATA feature preview enabled`() { - withSettings(""" - $defaultSettingsScript + withDefaultSettings().appendText(""" enableFeaturePreview("GRADLE_METADATA") """) diff --git a/subprojects/kotlin-dsl-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/AbstractPrecompiledScriptPluginTest.kt b/subprojects/kotlin-dsl-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/AbstractPrecompiledScriptPluginTest.kt index 47c5384ca7315..ddf128cfb9275 100644 --- a/subprojects/kotlin-dsl-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/AbstractPrecompiledScriptPluginTest.kt +++ b/subprojects/kotlin-dsl-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/AbstractPrecompiledScriptPluginTest.kt @@ -27,7 +27,6 @@ open class AbstractPrecompiledScriptPluginTest : AbstractPluginTest() { @Before fun setupPluginTest() { requireGradleDistributionOnEmbeddedExecuter() - withDefaultSettings() } protected diff --git a/subprojects/kotlin-dsl-test-fixtures/src/main/kotlin/org/gradle/kotlin/dsl/fixtures/AbstractPluginTest.kt b/subprojects/kotlin-dsl-test-fixtures/src/main/kotlin/org/gradle/kotlin/dsl/fixtures/AbstractPluginTest.kt index c4622a4d4dd2c..45ec6637f57da 100644 --- a/subprojects/kotlin-dsl-test-fixtures/src/main/kotlin/org/gradle/kotlin/dsl/fixtures/AbstractPluginTest.kt +++ b/subprojects/kotlin-dsl-test-fixtures/src/main/kotlin/org/gradle/kotlin/dsl/fixtures/AbstractPluginTest.kt @@ -1,7 +1,11 @@ package org.gradle.kotlin.dsl.fixtures import org.gradle.util.TextUtil.normaliseFileSeparators + +import org.junit.Before + import java.io.File + import java.util.Properties @@ -11,6 +15,11 @@ import java.util.Properties */ open class AbstractPluginTest : AbstractKotlinIntegrationTest() { + @Before + fun setUpDefaultSetttings() { + withDefaultSettings() + } + override val defaultSettingsScript: String get() = pluginManagementBlock From 3ddde5d25ac6befa0c06dfdac6760e66c1343a4a Mon Sep 17 00:00:00 2001 From: "Rodrigo B. de Oliveira" Date: Fri, 15 Feb 2019 06:52:39 -0200 Subject: [PATCH 026/853] Make offending precompiled script plugin test with `LeaksFileHandles` --- .../precompiled/PrecompiledScriptPluginAccessorsTest.kt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/subprojects/kotlin-dsl-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPluginAccessorsTest.kt b/subprojects/kotlin-dsl-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPluginAccessorsTest.kt index 7bdabd3745407..f6a112b2aab21 100644 --- a/subprojects/kotlin-dsl-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPluginAccessorsTest.kt +++ b/subprojects/kotlin-dsl-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPluginAccessorsTest.kt @@ -31,6 +31,8 @@ import org.gradle.kotlin.dsl.fixtures.normalisedPath import org.gradle.kotlin.dsl.fixtures.pluginDescriptorEntryFor import org.gradle.kotlin.dsl.support.zipTo +import org.gradle.test.fixtures.file.LeaksFileHandles + import org.hamcrest.CoreMatchers.allOf import org.hamcrest.CoreMatchers.containsString import org.hamcrest.MatcherAssert.assertThat @@ -143,6 +145,7 @@ class PrecompiledScriptPluginAccessorsTest : AbstractPrecompiledScriptPluginTest } } + @LeaksFileHandles("TDB") @Test fun `can use plugin spec builders for plugins in the implementation classpath`() { From 6ae1f2c931251020043da01eb6e08d8c948491be Mon Sep 17 00:00:00 2001 From: "Rodrigo B. de Oliveira" Date: Tue, 19 Feb 2019 09:34:24 -0300 Subject: [PATCH 027/853] Reuse `newDependencyHandlerMock` in `ScriptHandlerScopeTest` --- .../kotlin/org/gradle/kotlin/dsl/ScriptHandlerScopeTest.kt | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/subprojects/kotlin-dsl/src/test/kotlin/org/gradle/kotlin/dsl/ScriptHandlerScopeTest.kt b/subprojects/kotlin-dsl/src/test/kotlin/org/gradle/kotlin/dsl/ScriptHandlerScopeTest.kt index d80d103f32143..a65e29edcd660 100644 --- a/subprojects/kotlin-dsl/src/test/kotlin/org/gradle/kotlin/dsl/ScriptHandlerScopeTest.kt +++ b/subprojects/kotlin-dsl/src/test/kotlin/org/gradle/kotlin/dsl/ScriptHandlerScopeTest.kt @@ -28,9 +28,7 @@ import org.gradle.api.Action import org.gradle.api.artifacts.DependencyConstraint import org.gradle.api.artifacts.ExternalModuleDependency import org.gradle.api.artifacts.dsl.DependencyConstraintHandler -import org.gradle.api.artifacts.dsl.DependencyHandler import org.gradle.api.initialization.dsl.ScriptHandler -import org.gradle.api.plugins.ExtensionAware import org.gradle.kotlin.dsl.support.configureWith @@ -43,7 +41,7 @@ class ScriptHandlerScopeTest { fun `can exclude modules from classpath dependency`() { val dependency = mock() - val dependencies = mock(arrayOf(ExtensionAware::class)) { + val dependencies = newDependencyHandlerMock { on { create("...") } doReturn dependency } val buildscript = mock { From 91ed97f81ee638a24915bb20a94db1feb3058eb6 Mon Sep 17 00:00:00 2001 From: "Rodrigo B. de Oliveira" Date: Tue, 19 Feb 2019 09:35:41 -0300 Subject: [PATCH 028/853] Polish `PrecompiledScriptPluginTest` - Use `defaultSettingsScript` instead of `pluginManagementBlock` --- .../precompiled/PrecompiledScriptPluginTest.kt | 15 ++++----------- .../kotlin/dsl/fixtures/AbstractPluginTest.kt | 4 ++-- 2 files changed, 6 insertions(+), 13 deletions(-) diff --git a/subprojects/kotlin-dsl-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPluginTest.kt b/subprojects/kotlin-dsl-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPluginTest.kt index 3386577111005..337378986914b 100644 --- a/subprojects/kotlin-dsl-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPluginTest.kt +++ b/subprojects/kotlin-dsl-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPluginTest.kt @@ -185,15 +185,12 @@ class PrecompiledScriptPluginTest : AbstractPrecompiledScriptPluginTest() { """) } - withFile("settings.gradle.kts", """ - - $pluginManagementBlock - - """) + withFile("settings.gradle.kts", defaultSettingsScript) withFile( "build.gradle.kts", - scriptWithKotlinDslPlugin()) + scriptWithKotlinDslPlugin() + ) } } @@ -253,11 +250,7 @@ class PrecompiledScriptPluginTest : AbstractPrecompiledScriptPluginTest() { """) } - withFile("settings.gradle.kts", """ - - $pluginManagementBlock - - """) + withFile("settings.gradle.kts", defaultSettingsScript) withFile("build.gradle.kts", """ diff --git a/subprojects/kotlin-dsl-test-fixtures/src/main/kotlin/org/gradle/kotlin/dsl/fixtures/AbstractPluginTest.kt b/subprojects/kotlin-dsl-test-fixtures/src/main/kotlin/org/gradle/kotlin/dsl/fixtures/AbstractPluginTest.kt index 45ec6637f57da..4aec49ffd9946 100644 --- a/subprojects/kotlin-dsl-test-fixtures/src/main/kotlin/org/gradle/kotlin/dsl/fixtures/AbstractPluginTest.kt +++ b/subprojects/kotlin-dsl-test-fixtures/src/main/kotlin/org/gradle/kotlin/dsl/fixtures/AbstractPluginTest.kt @@ -23,7 +23,7 @@ open class AbstractPluginTest : AbstractKotlinIntegrationTest() { override val defaultSettingsScript: String get() = pluginManagementBlock - protected + private val pluginManagementBlock by lazy { """ pluginManagement { @@ -33,7 +33,7 @@ open class AbstractPluginTest : AbstractKotlinIntegrationTest() { """ } - protected + private val pluginRepositoriesBlock by lazy { """ repositories { From 72804eac6a643b9b5ab45f6ea01de5a6105b0316 Mon Sep 17 00:00:00 2001 From: "Rodrigo B. de Oliveira" Date: Tue, 19 Feb 2019 15:54:32 -0300 Subject: [PATCH 029/853] Temporarily ignore Kotlin DSL cross version tests for Kotlin `1.2.20` For it's leaking files and causing the `verifyTestFileCleanup` step to fail. --- .../dsl/KotlinDslPluginGradlePluginCrossVersionSmokeTest.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/subprojects/kotlin-dsl-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/plugins/dsl/KotlinDslPluginGradlePluginCrossVersionSmokeTest.kt b/subprojects/kotlin-dsl-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/plugins/dsl/KotlinDslPluginGradlePluginCrossVersionSmokeTest.kt index e19b4cd6b4d6d..1e2c310e9d85a 100644 --- a/subprojects/kotlin-dsl-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/plugins/dsl/KotlinDslPluginGradlePluginCrossVersionSmokeTest.kt +++ b/subprojects/kotlin-dsl-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/plugins/dsl/KotlinDslPluginGradlePluginCrossVersionSmokeTest.kt @@ -43,8 +43,8 @@ class KotlinDslPluginGradlePluginCrossVersionSmokeTest( @JvmStatic fun testedKotlinVersions() = listOf( embeddedKotlinVersion, - "1.2.71", - "1.2.20" + "1.2.71" +// "1.2.20" TODO:re-enable 1.2.20 ) } From a065d95cf86d383b7ec93518406de3069cf5e13c Mon Sep 17 00:00:00 2001 From: "Rodrigo B. de Oliveira" Date: Wed, 20 Feb 2019 12:21:08 -0300 Subject: [PATCH 030/853] Extract `plugins` blocks from precompiled script plugins --- ...ptPlugin.kt => PrecompiledScriptPlugin.kt} | 7 +- .../precompiled/PrecompiledScriptPlugins.kt | 12 +- .../ExtractPrecompiledScriptPluginPlugins.kt | 63 ++++++++- .../GenerateInternalPluginSpecBuilders.kt | 4 +- ...eneratePrecompiledScriptPluginAccessors.kt | 10 +- .../tasks/GenerateScriptPluginAdapters.kt | 6 +- .../plugins/precompiled/ScriptPluginTest.kt | 12 +- ...tractPrecompiledScriptPluginPluginsTest.kt | 122 ++++++++++++++++++ .../org/gradle/kotlin/dsl/execution/Lexer.kt | 7 +- .../kotlin/dsl/execution/ProgramParser.kt | 4 +- .../kotlin/dsl/execution/ProgramSource.kt | 5 +- .../dsl/execution/ResidualProgramCompiler.kt | 6 +- .../execution/ResidualProgramCompilerTest.kt | 4 +- 13 files changed, 226 insertions(+), 36 deletions(-) rename subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/{ScriptPlugin.kt => PrecompiledScriptPlugin.kt} (96%) create mode 100644 subprojects/kotlin-dsl-plugins/src/test/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/ExtractPrecompiledScriptPluginPluginsTest.kt diff --git a/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/ScriptPlugin.kt b/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPlugin.kt similarity index 96% rename from subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/ScriptPlugin.kt rename to subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPlugin.kt index 121026783c98e..1e49212d3bb7a 100644 --- a/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/ScriptPlugin.kt +++ b/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPlugin.kt @@ -35,7 +35,7 @@ import java.io.File internal -data class ScriptPlugin(internal val scriptFile: File) { +data class PrecompiledScriptPlugin(internal val scriptFile: File) { val scriptFileName: String = scriptFile.name @@ -104,9 +104,12 @@ data class ScriptPlugin(internal val scriptFile: File) { } val hash by lazy { - Hashing.hashString(scriptFile.readText()) + Hashing.hashString(scriptText) } + val scriptText: String + get() = scriptFile.readText() + private fun packagePrefixed(id: String) = packageName?.let { "$it.$id" } ?: id diff --git a/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPlugins.kt b/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPlugins.kt index 9f16cfa0bcfb7..1ca5492024e40 100644 --- a/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPlugins.kt +++ b/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPlugins.kt @@ -143,7 +143,7 @@ class PrecompiledScriptPlugins : Plugin { private -fun Project.enableScriptCompilationOf(scriptPlugins: List) { +fun Project.enableScriptCompilationOf(scriptPlugins: List) { dependencies { "kotlinCompilerPluginClasspath"(gradleKotlinDslJarsOf(project)) @@ -257,7 +257,7 @@ fun Project.implicitImports(): List = private -fun Project.exposeScriptsAsGradlePlugins(scriptPlugins: List) { +fun Project.exposeScriptsAsGradlePlugins(scriptPlugins: List) { declareScriptPlugins(scriptPlugins) @@ -266,10 +266,10 @@ fun Project.exposeScriptsAsGradlePlugins(scriptPlugins: List) { private -fun Project.collectScriptPlugins(): List = +fun Project.collectScriptPlugins(): List = pluginSourceSet.allSource.matching { it.include("**/*.gradle.kts") - }.map(::ScriptPlugin) + }.map(::PrecompiledScriptPlugin) private @@ -283,7 +283,7 @@ val Project.gradlePlugin private -fun Project.declareScriptPlugins(scriptPlugins: List) { +fun Project.declareScriptPlugins(scriptPlugins: List) { configure { for (scriptPlugin in scriptPlugins) { @@ -297,7 +297,7 @@ fun Project.declareScriptPlugins(scriptPlugins: List) { private -fun Project.generatePluginAdaptersFor(scriptPlugins: List) { +fun Project.generatePluginAdaptersFor(scriptPlugins: List) { codeGenerationTask("plugins", "generateScriptPluginAdapters") { plugins = scriptPlugins diff --git a/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/ExtractPrecompiledScriptPluginPlugins.kt b/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/ExtractPrecompiledScriptPluginPlugins.kt index 37e10acb9bf5b..5b87d08835e54 100644 --- a/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/ExtractPrecompiledScriptPluginPlugins.kt +++ b/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/ExtractPrecompiledScriptPluginPlugins.kt @@ -26,7 +26,15 @@ import org.gradle.api.tasks.PathSensitive import org.gradle.api.tasks.PathSensitivity import org.gradle.api.tasks.TaskAction -import org.gradle.kotlin.dsl.plugins.precompiled.ScriptPlugin +import org.gradle.kotlin.dsl.execution.Program +import org.gradle.kotlin.dsl.execution.ProgramKind +import org.gradle.kotlin.dsl.execution.ProgramParser +import org.gradle.kotlin.dsl.execution.ProgramSource +import org.gradle.kotlin.dsl.execution.ProgramTarget + +import org.gradle.kotlin.dsl.plugins.precompiled.PrecompiledScriptPlugin + +import org.gradle.kotlin.dsl.support.KotlinScriptType import java.io.File @@ -43,7 +51,7 @@ open class ExtractPrecompiledScriptPluginPlugins : DefaultTask() { @get:Internal internal - lateinit var plugins: List + lateinit var plugins: List @get:InputFiles @get:PathSensitive(PathSensitivity.RELATIVE) @@ -55,6 +63,57 @@ open class ExtractPrecompiledScriptPluginPlugins : DefaultTask() { @TaskAction fun extract() { outputDir.withOutputDirectory { + extractPrecompiledScriptPluginPluginsTo(it, plugins) + } + } +} + + +internal +fun extractPrecompiledScriptPluginPluginsTo(outputDir: File, scriptPlugins: List) { + for (scriptPlugin in scriptPlugins) { + pluginsBlockOf(scriptPlugin)?.let { + writePluginsBlockTo(outputDir, scriptPlugin, it) } } } + + +private +fun pluginsBlockOf(scriptPlugin: PrecompiledScriptPlugin): Program.Plugins? = + when (scriptPlugin.scriptType) { + KotlinScriptType.PROJECT -> pluginsBlockOf(parse(scriptPlugin)) + else -> null + } + + +private +fun pluginsBlockOf(program: Program): Program.Plugins? = + when (program) { + is Program.Plugins -> program + is Program.Stage1Sequence -> program.plugins + is Program.Staged -> pluginsBlockOf(program.stage1) + else -> null + } + + +private +fun parse(scriptPlugin: PrecompiledScriptPlugin): Program = ProgramParser.parse( + ProgramSource(scriptPlugin.scriptFileName, scriptPlugin.scriptText), + ProgramKind.TopLevel, + ProgramTarget.Project +) + + +private +fun writePluginsBlockTo(outputDir: File, scriptPlugin: PrecompiledScriptPlugin, program: Program.Plugins) { + outputDir.resolve(scriptPlugin.scriptFileName).writeText( + lineNumberPreservingTextOf(program) + ) +} + + +private +fun lineNumberPreservingTextOf(program: Program.Plugins): String = program.fragment.run { + source.map { it.subText(0..range.endInclusive).preserve(range) } +}.text diff --git a/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/GenerateInternalPluginSpecBuilders.kt b/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/GenerateInternalPluginSpecBuilders.kt index a5ca8e06540f3..5b464200d20bb 100644 --- a/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/GenerateInternalPluginSpecBuilders.kt +++ b/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/GenerateInternalPluginSpecBuilders.kt @@ -25,7 +25,7 @@ import org.gradle.api.tasks.PathSensitive import org.gradle.api.tasks.PathSensitivity import org.gradle.api.tasks.TaskAction -import org.gradle.kotlin.dsl.plugins.precompiled.ScriptPlugin +import org.gradle.kotlin.dsl.plugins.precompiled.PrecompiledScriptPlugin import java.io.File @@ -38,7 +38,7 @@ open class GenerateInternalPluginSpecBuilders : DefaultTask() { @get:Internal internal - lateinit var plugins: List + lateinit var plugins: List @get:InputFiles @get:PathSensitive(PathSensitivity.RELATIVE) diff --git a/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/GeneratePrecompiledScriptPluginAccessors.kt b/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/GeneratePrecompiledScriptPluginAccessors.kt index 9c3c988d2b9da..526078baacf4c 100644 --- a/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/GeneratePrecompiledScriptPluginAccessors.kt +++ b/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/GeneratePrecompiledScriptPluginAccessors.kt @@ -34,7 +34,7 @@ import org.gradle.kotlin.dsl.concurrent.IO import org.gradle.kotlin.dsl.concurrent.withAsynchronousIO import org.gradle.kotlin.dsl.concurrent.writeFile -import org.gradle.kotlin.dsl.plugins.precompiled.ScriptPlugin +import org.gradle.kotlin.dsl.plugins.precompiled.PrecompiledScriptPlugin import org.gradle.kotlin.dsl.support.KotlinScriptType @@ -53,7 +53,7 @@ open class GeneratePrecompiledScriptPluginAccessors : ClassPathSensitiveCodeGene @get:Internal internal - lateinit var plugins: List + lateinit var plugins: List @get:InputFiles @get:PathSensitive(PathSensitivity.RELATIVE) @@ -113,7 +113,7 @@ open class GeneratePrecompiledScriptPluginAccessors : ClassPathSensitiveCodeGene metadataOutputDir.get().asFile.resolve(scriptPlugin.script.hashString) private - fun scriptWithPluginsBlock(plugin: ScriptPlugin): ScriptWithPluginsBlock? { + fun scriptWithPluginsBlock(plugin: PrecompiledScriptPlugin): ScriptWithPluginsBlock? { if (plugin.scriptType != KotlinScriptType.PROJECT) return null return null } @@ -142,7 +142,7 @@ data class HashedProjectSchema( internal data class ScriptWithPluginsBlock( - val script: ScriptPlugin, + val script: PrecompiledScriptPlugin, val pluginsBlock: PluginsBlock ) @@ -163,4 +163,4 @@ data class PluginApplication( internal -fun scriptPluginFilesOf(list: List) = list.map { it.scriptFile }.toSet() +fun scriptPluginFilesOf(list: List) = list.map { it.scriptFile }.toSet() diff --git a/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/GenerateScriptPluginAdapters.kt b/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/GenerateScriptPluginAdapters.kt index 6975f276cce62..736a7b85e3f82 100644 --- a/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/GenerateScriptPluginAdapters.kt +++ b/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/GenerateScriptPluginAdapters.kt @@ -25,7 +25,7 @@ import org.gradle.api.tasks.PathSensitive import org.gradle.api.tasks.PathSensitivity import org.gradle.api.tasks.OutputDirectory import org.gradle.api.tasks.TaskAction -import org.gradle.kotlin.dsl.plugins.precompiled.ScriptPlugin +import org.gradle.kotlin.dsl.plugins.precompiled.PrecompiledScriptPlugin import org.gradle.kotlin.dsl.support.normaliseLineSeparators @@ -40,7 +40,7 @@ open class GenerateScriptPluginAdapters : DefaultTask() { @get:Internal internal - lateinit var plugins: List + lateinit var plugins: List @get:InputFiles @get:PathSensitive(PathSensitivity.RELATIVE) @@ -62,7 +62,7 @@ open class GenerateScriptPluginAdapters : DefaultTask() { internal -fun ScriptPlugin.writeScriptPluginAdapterTo(outputDir: File) { +fun PrecompiledScriptPlugin.writeScriptPluginAdapterTo(outputDir: File) { val (packageDir, packageDeclaration) = packageName?.let { packageName -> diff --git a/subprojects/kotlin-dsl-plugins/src/test/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/ScriptPluginTest.kt b/subprojects/kotlin-dsl-plugins/src/test/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/ScriptPluginTest.kt index 97ccea55393d4..750e3a157eccc 100644 --- a/subprojects/kotlin-dsl-plugins/src/test/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/ScriptPluginTest.kt +++ b/subprojects/kotlin-dsl-plugins/src/test/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/ScriptPluginTest.kt @@ -22,7 +22,7 @@ class ScriptPluginTest : TestWithTempFiles() { newFile("my-script.gradle.kts") assertThat( - ScriptPlugin(script).id, + PrecompiledScriptPlugin(script).id, equalTo("my-script")) } @@ -37,7 +37,7 @@ class ScriptPluginTest : TestWithTempFiles() { """) assertThat( - ScriptPlugin(script).id, + PrecompiledScriptPlugin(script).id, equalTo("org.acme.my-script")) } @@ -59,7 +59,7 @@ class ScriptPluginTest : TestWithTempFiles() { private fun implementationClassForScriptNamed(fileName: String) = - ScriptPlugin(newFile(fileName)).implementationClass + PrecompiledScriptPlugin(newFile(fileName)).implementationClass @Test fun `plugin adapter is written to package sub-dir and starts with correct package declaration`() { @@ -74,7 +74,7 @@ class ScriptPluginTest : TestWithTempFiles() { val outputDir = root.resolve("output") - ScriptPlugin(script) + PrecompiledScriptPlugin(script) .writeScriptPluginAdapterTo(outputDir) val expectedFile = @@ -94,7 +94,7 @@ class ScriptPluginTest : TestWithTempFiles() { val outputDir = root.resolve("output").apply { mkdir() } - ScriptPlugin(script) + PrecompiledScriptPlugin(script) .writeScriptPluginAdapterTo(outputDir) val expectedFile = @@ -119,7 +119,7 @@ class ScriptPluginTest : TestWithTempFiles() { newFile("my-script.gradle.kts", "/*\r\n */\r\npackage org.acme\r\n") assertThat( - ScriptPlugin(script).packageName, + PrecompiledScriptPlugin(script).packageName, equalTo("org.acme")) } diff --git a/subprojects/kotlin-dsl-plugins/src/test/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/ExtractPrecompiledScriptPluginPluginsTest.kt b/subprojects/kotlin-dsl-plugins/src/test/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/ExtractPrecompiledScriptPluginPluginsTest.kt new file mode 100644 index 0000000000000..0d5442d3e3cca --- /dev/null +++ b/subprojects/kotlin-dsl-plugins/src/test/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/ExtractPrecompiledScriptPluginPluginsTest.kt @@ -0,0 +1,122 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.kotlin.dsl.plugins.precompiled.tasks + +import org.gradle.kotlin.dsl.fixtures.TestWithTempFiles +import org.gradle.kotlin.dsl.fixtures.equalToMultiLineString + +import org.gradle.kotlin.dsl.plugins.precompiled.PrecompiledScriptPlugin + +import org.hamcrest.Description +import org.hamcrest.Matcher +import org.hamcrest.MatcherAssert.assertThat +import org.hamcrest.TypeSafeMatcher + +import org.junit.Test + +import java.io.File + + +class ExtractPrecompiledScriptPluginPluginsTest : TestWithTempFiles() { + + @Test + fun `extract plugins blocks and writes them to the output dir`() { + + val scriptPlugins = listOf( + + scriptPlugin("plugins-only.gradle.kts", """ + // this comment will be removed + plugins { + java + } + // and so will the rest of the script + """), + + scriptPlugin("no-plugins.gradle.kts", """ + buildscript {} + """), + + scriptPlugin("empty-plugins.gradle.kts", """ + plugins {} + """), + + // the `buildscript` block is not really valid in precompiled script plugins (causes a runtime error) + // but still worth testing here + scriptPlugin("buildscript-and-plugins.gradle.kts", """ + buildscript {} + plugins { java } + """) + ) + + val outputDir = newFolder("plugins") + extractPrecompiledScriptPluginPluginsTo( + outputDir, + scriptPlugins + ) + + fun outputFile(fileName: String) = outputDir.resolve(fileName) + + assertThat( + outputFile("plugins-only.gradle.kts").readText(), + equalToMultiLineString(""" + ${"// this comment will be removed".replacedBySpaces()} + plugins { + java + }""" + ) + ) + + assertThat( + outputFile("no-plugins.gradle.kts"), + doesNotExist() + ) + + assertThat( + outputFile("empty-plugins.gradle.kts"), + doesNotExist() + ) + + assertThat( + outputFile("buildscript-and-plugins.gradle.kts").readText(), + equalToMultiLineString(""" + ${"buildscript {}".replacedBySpaces()} + plugins { java }""" + ) + ) + } + + private + fun scriptPlugin(fileName: String, text: String) = PrecompiledScriptPlugin(newFile(fileName, text)) + + private + fun String.replacedBySpaces() = repeat(' ', length) +} + + +private +fun repeat(char: Char, count: Int) = String(CharArray(count) { _ -> char }) + + +private +fun doesNotExist(): Matcher = object : TypeSafeMatcher() { + + override fun describeTo(description: Description) { + description.appendText("nonexistent file") + } + + override fun matchesSafely(file: File): Boolean = !file.exists() +} diff --git a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/execution/Lexer.kt b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/execution/Lexer.kt index 518e8f4b7388e..b71aba7925789 100644 --- a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/execution/Lexer.kt +++ b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/execution/Lexer.kt @@ -152,7 +152,10 @@ fun topLevelBlock(identifier: String, identifierRange: IntRange, blockRange: Int internal -data class TopLevelBlock(val identifier: String, val section: ScriptSection) +data class TopLevelBlock(val identifier: String, val section: ScriptSection) { + val range: IntRange + get() = section.wholeRange +} internal @@ -162,6 +165,6 @@ fun List.singleBlockSectionOrNull(): ScriptSection? = 1 -> get(0).section else -> { val unexpectedBlock = get(1) - throw UnexpectedBlock(unexpectedBlock.identifier, unexpectedBlock.section.wholeRange) + throw UnexpectedBlock(unexpectedBlock.identifier, unexpectedBlock.range) } } diff --git a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/execution/ProgramParser.kt b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/execution/ProgramParser.kt index e2788dc61266b..dc93033731898 100644 --- a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/execution/ProgramParser.kt +++ b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/execution/ProgramParser.kt @@ -75,8 +75,8 @@ object ProgramParser { sourceWithoutComments.map { it.erase( listOfNotNull( - buildscriptFragment?.section?.wholeRange, - pluginsFragment?.section?.wholeRange)) + buildscriptFragment?.range, + pluginsFragment?.range)) } val stage2 = remainingSource diff --git a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/execution/ProgramSource.kt b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/execution/ProgramSource.kt index e4e232e55447b..f3703c0975789 100644 --- a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/execution/ProgramSource.kt +++ b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/execution/ProgramSource.kt @@ -94,8 +94,11 @@ data class ProgramSourceFragment( val lineNumber: Int get() = source.contents.lineNumberOf(section.identifier.start) + val range: IntRange + get() = section.wholeRange + override fun toString(): String = - "ProgramSourceFragment(\"${source.text.subSequence(section.wholeRange)}\")" + "ProgramSourceFragment(\"${source.text.subSequence(range)}\")" } diff --git a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/execution/ResidualProgramCompiler.kt b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/execution/ResidualProgramCompiler.kt index 4c47614fa209d..07f670bd56f11 100644 --- a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/execution/ResidualProgramCompiler.kt +++ b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/execution/ResidualProgramCompiler.kt @@ -227,8 +227,8 @@ class ResidualProgramCompiler( compileStage1( plugins.fragment.source.map { it.preserve( - buildscript.fragment.section.wholeRange, - plugins.fragment.section.wholeRange) + buildscript.fragment.range, + plugins.fragment.range) }, buildscriptWithPluginsScriptDefinition, pluginsBlockClassPath @@ -467,7 +467,7 @@ class ResidualProgramCompiler( private fun compilePlugins(program: Program.Plugins) = compileStage1( - program.fragment.source.map { it.preserve(program.fragment.section.wholeRange) }, + program.fragment.source.map { it.preserve(program.fragment.range) }, pluginsScriptDefinition, pluginsBlockClassPath ) diff --git a/subprojects/kotlin-dsl/src/test/kotlin/org/gradle/kotlin/dsl/execution/ResidualProgramCompilerTest.kt b/subprojects/kotlin-dsl/src/test/kotlin/org/gradle/kotlin/dsl/execution/ResidualProgramCompilerTest.kt index 36ec2b795bbf8..b38b04d0b9438 100644 --- a/subprojects/kotlin-dsl/src/test/kotlin/org/gradle/kotlin/dsl/execution/ResidualProgramCompilerTest.kt +++ b/subprojects/kotlin-dsl/src/test/kotlin/org/gradle/kotlin/dsl/execution/ResidualProgramCompilerTest.kt @@ -350,7 +350,7 @@ class ResidualProgramCompilerTest : TestWithTempFiles() { val fragment = source.fragment(0..6, 8..29) val stage1 = Program.Plugins(fragment) - val stage2 = source.map { it.erase(listOf(fragment.section.wholeRange)) } + val stage2 = source.map { it.erase(listOf(fragment.range)) } val stagedProgram = Dynamic( Static(ApplyPluginRequestsOf(stage1), ApplyBasePlugins), stage2 @@ -437,7 +437,7 @@ class ResidualProgramCompilerTest : TestWithTempFiles() { private fun ProgramText.without(buildscript: Program.Buildscript, plugins: Program.Plugins) = - erase(listOf(buildscript.fragment, plugins.fragment).map { it.section.wholeRange }) + erase(listOf(buildscript.fragment, plugins.fragment).map { it.range }) private fun assertStagedTopLevelProjectProgram( From 75112c7c0396c8462d098e4c73bcedaa3db52ef0 Mon Sep 17 00:00:00 2001 From: "Rodrigo B. de Oliveira" Date: Wed, 20 Feb 2019 17:01:38 -0300 Subject: [PATCH 031/853] Rename `PrecompiledScriptPlugin` tests as well In a recent commit, `ScriptPlugin` was renamed to `PrecompiledScriptPlugin` to avoid a naming conflict with the core Gradle API. This commit renames the following test classes to account for the change: - `PrecompiledScriptPluginTest` is renamed to `PrecompiledScriptPluginTemplatesTest` both because that's what it is actually testing and to make the `PrecompiledScriptPluginTest` name available; - `ScriptPluginTest` is renamed `PrecompiledScriptPluginTest` to make the connection with `PrecompiledScriptPlugin` --- ...iptPluginTest.kt => PrecompiledScriptPluginTemplatesTest.kt} | 2 +- .../{ScriptPluginTest.kt => PrecompiledScriptPluginTest.kt} | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) rename subprojects/kotlin-dsl-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/{PrecompiledScriptPluginTest.kt => PrecompiledScriptPluginTemplatesTest.kt} (99%) rename subprojects/kotlin-dsl-plugins/src/test/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/{ScriptPluginTest.kt => PrecompiledScriptPluginTest.kt} (98%) diff --git a/subprojects/kotlin-dsl-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPluginTest.kt b/subprojects/kotlin-dsl-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPluginTemplatesTest.kt similarity index 99% rename from subprojects/kotlin-dsl-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPluginTest.kt rename to subprojects/kotlin-dsl-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPluginTemplatesTest.kt index 337378986914b..6dbb7996f8f6d 100644 --- a/subprojects/kotlin-dsl-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPluginTest.kt +++ b/subprojects/kotlin-dsl-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPluginTemplatesTest.kt @@ -33,7 +33,7 @@ import org.junit.Test @LeaksFileHandles("Kotlin Compiler Daemon working directory") -class PrecompiledScriptPluginTest : AbstractPrecompiledScriptPluginTest() { +class PrecompiledScriptPluginTemplatesTest : AbstractPrecompiledScriptPluginTest() { @Test fun `Project scripts from regular source-sets are compiled via the PrecompiledProjectScript template`() { diff --git a/subprojects/kotlin-dsl-plugins/src/test/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/ScriptPluginTest.kt b/subprojects/kotlin-dsl-plugins/src/test/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPluginTest.kt similarity index 98% rename from subprojects/kotlin-dsl-plugins/src/test/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/ScriptPluginTest.kt rename to subprojects/kotlin-dsl-plugins/src/test/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPluginTest.kt index 750e3a157eccc..55fd02402654e 100644 --- a/subprojects/kotlin-dsl-plugins/src/test/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/ScriptPluginTest.kt +++ b/subprojects/kotlin-dsl-plugins/src/test/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPluginTest.kt @@ -13,7 +13,7 @@ import org.junit.Test import java.io.File -class ScriptPluginTest : TestWithTempFiles() { +class PrecompiledScriptPluginTest : TestWithTempFiles() { @Test fun `plugin id is derived from script file name`() { From 2f7e2205ca64c58bf70abb758899a3578c7301d3 Mon Sep 17 00:00:00 2001 From: Sterling Greene Date: Thu, 21 Feb 2019 13:22:37 -0500 Subject: [PATCH 032/853] Add ReplacedBy attribute to identify properties that are replaced by other properties This is informational only for now. @ReplacedBy is treated like @Internal. --- .../dsl/docbook/ElementWarningsRenderer.java | 8 ++++ .../dsl/docbook/PropertyDetailRenderer.java | 11 +++-- .../dsl/docbook/PropertyTableRenderer.java | 5 +++ .../docs/dsl/docbook/model/BlockDoc.groovy | 9 ++++ .../docs/dsl/docbook/model/ClassDoc.groovy | 9 ++++ .../docs/dsl/docbook/model/DslElementDoc.java | 4 ++ .../docs/dsl/docbook/model/MethodDoc.groovy | 9 ++++ .../docs/dsl/docbook/model/PropertyDoc.groovy | 9 ++++ .../dsl/source/SourceMetaDataVisitor.java | 16 ++++++- .../source/model/AbstractLanguageElement.java | 13 ++++++ .../dsl/source/model/PropertyMetaData.java | 5 +++ .../java/org/gradle/api/tasks/ReplacedBy.java | 43 +++++++++++++++++++ .../properties/DefaultTypeMetadataStore.java | 1 + .../tasks/bundling/AbstractArchiveTask.java | 24 +++++++---- .../scopes/ExecutionGlobalServices.java | 5 +++ ...api.tasks.bundling.AbstractArchiveTask.xml | 8 ++-- .../src/docs/userguide/more_about_tasks.adoc | 4 ++ .../devel/tasks/ValidateTaskProperties.java | 1 + 18 files changed, 166 insertions(+), 18 deletions(-) create mode 100644 subprojects/core-api/src/main/java/org/gradle/api/tasks/ReplacedBy.java diff --git a/buildSrc/subprojects/build/src/main/groovy/org/gradle/build/docs/dsl/docbook/ElementWarningsRenderer.java b/buildSrc/subprojects/build/src/main/groovy/org/gradle/build/docs/dsl/docbook/ElementWarningsRenderer.java index f06f9914d5050..bf1ef2654e1d6 100644 --- a/buildSrc/subprojects/build/src/main/groovy/org/gradle/build/docs/dsl/docbook/ElementWarningsRenderer.java +++ b/buildSrc/subprojects/build/src/main/groovy/org/gradle/build/docs/dsl/docbook/ElementWarningsRenderer.java @@ -48,5 +48,13 @@ public void renderTo(DslElementDoc elementDoc, String type, Element parent) { link.appendChild(document.createTextNode("incubating")); para.appendChild(document.createTextNode(" and may change in a future version of Gradle.")); } + if (elementDoc.isReplaced()) { + Document document = parent.getOwnerDocument(); + Element caution = document.createElement("caution"); + parent.appendChild(caution); + Element para = document.createElement("para"); + caution.appendChild(para); + para.appendChild(document.createTextNode(String.format("Note: This %s has been replaced by %s.", type, elementDoc.getReplacement()))); + } } } diff --git a/buildSrc/subprojects/build/src/main/groovy/org/gradle/build/docs/dsl/docbook/PropertyDetailRenderer.java b/buildSrc/subprojects/build/src/main/groovy/org/gradle/build/docs/dsl/docbook/PropertyDetailRenderer.java index 5f2f52ac5f96d..3cda1b7f2e8c0 100644 --- a/buildSrc/subprojects/build/src/main/groovy/org/gradle/build/docs/dsl/docbook/PropertyDetailRenderer.java +++ b/buildSrc/subprojects/build/src/main/groovy/org/gradle/build/docs/dsl/docbook/PropertyDetailRenderer.java @@ -46,10 +46,13 @@ public void renderTo(PropertyDoc propertyDoc, Element parent) { Element literal = document.createElement("literal"); title.appendChild(literal); literal.appendChild(document.createTextNode(propertyDoc.getName())); - if (!propertyDoc.getMetaData().isWriteable()) { - title.appendChild(document.createTextNode(" (read-only)")); - } else if (!propertyDoc.getMetaData().isReadable()) { - title.appendChild(document.createTextNode(" (write-only)")); + + if (!propertyDoc.getMetaData().isProviderApi()) { + if (!propertyDoc.getMetaData().isWriteable()) { + title.appendChild(document.createTextNode(" (read-only)")); + } else if (!propertyDoc.getMetaData().isReadable()) { + title.appendChild(document.createTextNode(" (write-only)")); + } } warningsRenderer.renderTo(propertyDoc, "property", section); diff --git a/buildSrc/subprojects/build/src/main/groovy/org/gradle/build/docs/dsl/docbook/PropertyTableRenderer.java b/buildSrc/subprojects/build/src/main/groovy/org/gradle/build/docs/dsl/docbook/PropertyTableRenderer.java index acb56c1afdf49..3f878b01b133e 100644 --- a/buildSrc/subprojects/build/src/main/groovy/org/gradle/build/docs/dsl/docbook/PropertyTableRenderer.java +++ b/buildSrc/subprojects/build/src/main/groovy/org/gradle/build/docs/dsl/docbook/PropertyTableRenderer.java @@ -70,6 +70,11 @@ public void renderTo(Iterable properties, Element parent) { td.appendChild(caution); caution.appendChild(document.createTextNode("Incubating")); } + if (propDoc.isReplaced()) { + Element caution = document.createElement("caution"); + td.appendChild(caution); + caution.appendChild(document.createTextNode("Replaced")); + } td.appendChild(document.importNode(propDoc.getDescription(), true)); } } diff --git a/buildSrc/subprojects/build/src/main/groovy/org/gradle/build/docs/dsl/docbook/model/BlockDoc.groovy b/buildSrc/subprojects/build/src/main/groovy/org/gradle/build/docs/dsl/docbook/model/BlockDoc.groovy index 4e4d553c67bfe..5c4f4b2c78e43 100644 --- a/buildSrc/subprojects/build/src/main/groovy/org/gradle/build/docs/dsl/docbook/model/BlockDoc.groovy +++ b/buildSrc/subprojects/build/src/main/groovy/org/gradle/build/docs/dsl/docbook/model/BlockDoc.groovy @@ -67,6 +67,15 @@ class BlockDoc implements DslElementDoc { return blockProperty.incubating || blockMethod.incubating } + boolean isReplaced() { + return blockProperty.replaced + } + + @Override + String getReplacement() { + return blockProperty.replacement + } + PropertyDoc getBlockProperty() { return blockProperty } diff --git a/buildSrc/subprojects/build/src/main/groovy/org/gradle/build/docs/dsl/docbook/model/ClassDoc.groovy b/buildSrc/subprojects/build/src/main/groovy/org/gradle/build/docs/dsl/docbook/model/ClassDoc.groovy index dfefd2317e2fa..ad5acffd6b4c1 100644 --- a/buildSrc/subprojects/build/src/main/groovy/org/gradle/build/docs/dsl/docbook/model/ClassDoc.groovy +++ b/buildSrc/subprojects/build/src/main/groovy/org/gradle/build/docs/dsl/docbook/model/ClassDoc.groovy @@ -73,6 +73,15 @@ class ClassDoc implements DslElementDoc { return classMetaData.incubating } + boolean isReplaced() { + return classMetaData.replaced + } + + @Override + String getReplacement() { + return classMetaData.replacement + } + Collection getClassProperties() { return classProperties } void addClassProperty(PropertyDoc propertyDoc) { diff --git a/buildSrc/subprojects/build/src/main/groovy/org/gradle/build/docs/dsl/docbook/model/DslElementDoc.java b/buildSrc/subprojects/build/src/main/groovy/org/gradle/build/docs/dsl/docbook/model/DslElementDoc.java index 98b0742456db2..7dd325cd13d4f 100644 --- a/buildSrc/subprojects/build/src/main/groovy/org/gradle/build/docs/dsl/docbook/model/DslElementDoc.java +++ b/buildSrc/subprojects/build/src/main/groovy/org/gradle/build/docs/dsl/docbook/model/DslElementDoc.java @@ -30,4 +30,8 @@ public interface DslElementDoc { boolean isDeprecated(); boolean isIncubating(); + + boolean isReplaced(); + + String getReplacement(); } diff --git a/buildSrc/subprojects/build/src/main/groovy/org/gradle/build/docs/dsl/docbook/model/MethodDoc.groovy b/buildSrc/subprojects/build/src/main/groovy/org/gradle/build/docs/dsl/docbook/model/MethodDoc.groovy index 6f685c4f66a5b..c463574d75513 100644 --- a/buildSrc/subprojects/build/src/main/groovy/org/gradle/build/docs/dsl/docbook/model/MethodDoc.groovy +++ b/buildSrc/subprojects/build/src/main/groovy/org/gradle/build/docs/dsl/docbook/model/MethodDoc.groovy @@ -64,6 +64,15 @@ class MethodDoc implements DslElementDoc { return metaData.incubating || metaData.ownerClass.incubating } + boolean isReplaced() { + return metaData.replaced + } + + @Override + String getReplacement() { + return metaData.replacement + } + Element getDescription() { return comment.find { it.nodeName == 'para' } } diff --git a/buildSrc/subprojects/build/src/main/groovy/org/gradle/build/docs/dsl/docbook/model/PropertyDoc.groovy b/buildSrc/subprojects/build/src/main/groovy/org/gradle/build/docs/dsl/docbook/model/PropertyDoc.groovy index 47e6a0ac25873..9ac89ef680f18 100644 --- a/buildSrc/subprojects/build/src/main/groovy/org/gradle/build/docs/dsl/docbook/model/PropertyDoc.groovy +++ b/buildSrc/subprojects/build/src/main/groovy/org/gradle/build/docs/dsl/docbook/model/PropertyDoc.groovy @@ -75,6 +75,15 @@ class PropertyDoc implements DslElementDoc { return metaData.incubating || metaData.ownerClass.incubating } + boolean isReplaced() { + return metaData.replaced + } + + @Override + String getReplacement() { + return metaData.replacement + } + Element getDescription() { return comment.find { it.nodeName == 'para' } } diff --git a/buildSrc/subprojects/build/src/main/groovy/org/gradle/build/docs/dsl/source/SourceMetaDataVisitor.java b/buildSrc/subprojects/build/src/main/groovy/org/gradle/build/docs/dsl/source/SourceMetaDataVisitor.java index 4e5153ef819e3..e949ada6c20ba 100644 --- a/buildSrc/subprojects/build/src/main/groovy/org/gradle/build/docs/dsl/source/SourceMetaDataVisitor.java +++ b/buildSrc/subprojects/build/src/main/groovy/org/gradle/build/docs/dsl/source/SourceMetaDataVisitor.java @@ -28,6 +28,7 @@ import com.github.javaparser.ast.expr.AnnotationExpr; import com.github.javaparser.ast.expr.Expression; import com.github.javaparser.ast.expr.LiteralStringValueExpr; +import com.github.javaparser.ast.expr.SingleMemberAnnotationExpr; import com.github.javaparser.ast.nodeTypes.NodeWithAnnotations; import com.github.javaparser.ast.nodeTypes.NodeWithExtends; import com.github.javaparser.ast.nodeTypes.NodeWithImplements; @@ -35,11 +36,18 @@ import com.github.javaparser.ast.type.ClassOrInterfaceType; import com.github.javaparser.ast.type.Type; import com.github.javaparser.ast.visitor.VoidVisitorAdapter; -import org.gradle.build.docs.dsl.source.model.*; +import org.gradle.build.docs.dsl.source.model.AbstractLanguageElement; +import org.gradle.build.docs.dsl.source.model.ClassMetaData; import org.gradle.build.docs.dsl.source.model.ClassMetaData.MetaType; +import org.gradle.build.docs.dsl.source.model.MethodMetaData; +import org.gradle.build.docs.dsl.source.model.PropertyMetaData; +import org.gradle.build.docs.dsl.source.model.TypeMetaData; import org.gradle.build.docs.model.ClassMetaDataRepository; -import java.util.*; +import java.util.ArrayList; +import java.util.Deque; +import java.util.LinkedList; +import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -149,6 +157,7 @@ public void visit(MethodDeclaration methodDeclaration, ClassMetaDataRepository node, AbstractLanguageElement currentElement) { for (AnnotationExpr child : node.getAnnotations()) { + if (child instanceof SingleMemberAnnotationExpr && child.getNameAsString().endsWith("ReplacedBy")) { + currentElement.setReplacement(((SingleMemberAnnotationExpr) child).getMemberValue().asLiteralStringValueExpr().getValue()); + } currentElement.addAnnotationTypeName(child.getNameAsString()); } } diff --git a/buildSrc/subprojects/build/src/main/groovy/org/gradle/build/docs/dsl/source/model/AbstractLanguageElement.java b/buildSrc/subprojects/build/src/main/groovy/org/gradle/build/docs/dsl/source/model/AbstractLanguageElement.java index dcc0677ba09e7..7c63c8d629195 100644 --- a/buildSrc/subprojects/build/src/main/groovy/org/gradle/build/docs/dsl/source/model/AbstractLanguageElement.java +++ b/buildSrc/subprojects/build/src/main/groovy/org/gradle/build/docs/dsl/source/model/AbstractLanguageElement.java @@ -26,6 +26,7 @@ public abstract class AbstractLanguageElement implements LanguageElement, Serializable { private String rawCommentText; private final List annotationNames = new ArrayList(); + private String replacement; protected AbstractLanguageElement() { } @@ -58,6 +59,18 @@ public boolean isIncubating() { return annotationNames.contains("org.gradle.api.Incubating"); } + public boolean isReplaced() { + return annotationNames.contains("org.gradle.api.tasks.ReplacedBy"); + } + + public String getReplacement() { + return replacement; + } + + public void setReplacement(String replacement) { + this.replacement = replacement; + } + public void resolveTypes(Transformer transformer) { for (int i = 0; i < annotationNames.size(); i++) { annotationNames.set(i, transformer.transform(annotationNames.get(i))); diff --git a/buildSrc/subprojects/build/src/main/groovy/org/gradle/build/docs/dsl/source/model/PropertyMetaData.java b/buildSrc/subprojects/build/src/main/groovy/org/gradle/build/docs/dsl/source/model/PropertyMetaData.java index f2822416dfcbc..a9c195ab03379 100644 --- a/buildSrc/subprojects/build/src/main/groovy/org/gradle/build/docs/dsl/source/model/PropertyMetaData.java +++ b/buildSrc/subprojects/build/src/main/groovy/org/gradle/build/docs/dsl/source/model/PropertyMetaData.java @@ -59,6 +59,11 @@ public boolean isReadable() { return getter != null; } + public boolean isProviderApi() { + // TODO: Crude approximation + return setter == null && (getType().getName().contains("Provider") || getType().getName().contains("Property")); + } + public ClassMetaData getOwnerClass() { return ownerClass; } diff --git a/subprojects/core-api/src/main/java/org/gradle/api/tasks/ReplacedBy.java b/subprojects/core-api/src/main/java/org/gradle/api/tasks/ReplacedBy.java new file mode 100644 index 0000000000000..eeb7c8704f474 --- /dev/null +++ b/subprojects/core-api/src/main/java/org/gradle/api/tasks/ReplacedBy.java @@ -0,0 +1,43 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.api.tasks; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + *

Attached to a task property to indicate that the property has been replaced by another. Like {@link Internal}, the property is ignored during up-to-date checks.

+ * + *

This annotation should be attached to the getter and setter method in Java or the property field in Groovy. You should also consider adding {@link Deprecated} to any replaced property.

+ * + *

This will cause the task not to be considered out-of-date when the property has changed.

+ */ +@Documented +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.METHOD) +public @interface ReplacedBy { + /** + * The Java Bean-style name of the replacement property. + *

+ * If the property has been replaced with a method named {@code getFooBar()}, then this should be {@code fooBar}. + *

+ */ + String value(); +} diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/DefaultTypeMetadataStore.java b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/DefaultTypeMetadataStore.java index 97cc01d3beed0..1820d44860879 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/DefaultTypeMetadataStore.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/DefaultTypeMetadataStore.java @@ -38,6 +38,7 @@ import org.gradle.api.plugins.ExtensionAware; import org.gradle.api.tasks.Optional; import org.gradle.api.tasks.PathSensitive; +import org.gradle.api.tasks.ReplacedBy; import org.gradle.api.tasks.SkipWhenEmpty; import org.gradle.cache.internal.CrossBuildInMemoryCache; import org.gradle.cache.internal.CrossBuildInMemoryCacheFactory; diff --git a/subprojects/core/src/main/java/org/gradle/api/tasks/bundling/AbstractArchiveTask.java b/subprojects/core/src/main/java/org/gradle/api/tasks/bundling/AbstractArchiveTask.java index 8b39a1249ce05..9e9c8cc28cd21 100644 --- a/subprojects/core/src/main/java/org/gradle/api/tasks/bundling/AbstractArchiveTask.java +++ b/subprojects/core/src/main/java/org/gradle/api/tasks/bundling/AbstractArchiveTask.java @@ -29,6 +29,7 @@ import org.gradle.api.tasks.Input; import org.gradle.api.tasks.Internal; import org.gradle.api.tasks.OutputFile; +import org.gradle.api.tasks.ReplacedBy; import org.gradle.internal.nativeplatform.filesystem.FileSystem; import org.gradle.internal.reflect.Instantiator; import org.gradle.util.GUtil; @@ -107,7 +108,7 @@ private static String maybe(@Nullable String prefix, @Nullable String value) { * @deprecated Use {@link #getArchiveFileName()} */ @Deprecated - @Internal("Represented as part of archiveFile") + @ReplacedBy("archiveFileName") public String getArchiveName() { return archiveName.get(); } @@ -119,6 +120,7 @@ public String getArchiveName() { * @deprecated Use {@link #getArchiveFileName()} */ @Deprecated + @ReplacedBy("archiveFileName") public void setArchiveName(String name) { archiveName.set(name); } @@ -142,7 +144,7 @@ public Property getArchiveFileName() { * @deprecated Use {@link #getArchiveFile()} */ @Deprecated - @Internal("Represented as a part of the archiveFile") + @ReplacedBy("archiveFile") public File getArchivePath() { return getArchiveFile().get().getAsFile(); } @@ -175,8 +177,8 @@ public Provider getArchiveFile() { * @return the directory * @deprecated Use {@link #getDestinationDirectory()} */ - @Internal("Represented as part of archiveFile") @Deprecated + @ReplacedBy("destinationDirectory") public File getDestinationDir() { return archiveDestinationDirectory.getAsFile().get(); } @@ -187,6 +189,7 @@ public File getDestinationDir() { * @deprecated Use {@link #getDestinationDirectory()} */ @Deprecated + @ReplacedBy("destinationDirectory") public void setDestinationDir(File destinationDir) { archiveDestinationDirectory.set(destinationDir); } @@ -208,8 +211,8 @@ public DirectoryProperty getDestinationDirectory() { * @deprecated Use {@link #getArchiveBaseName()} */ @Nullable - @Internal("Represented as part of archiveFile") @Deprecated + @ReplacedBy("archiveBaseName") public String getBaseName() { return archiveBaseName.getOrNull(); } @@ -220,6 +223,7 @@ public String getBaseName() { * @deprecated Use {@link #getArchiveBaseName()} */ @Deprecated + @ReplacedBy("archiveBaseName") public void setBaseName(@Nullable String baseName) { this.archiveBaseName.set(baseName); } @@ -242,8 +246,8 @@ public Property getArchiveBaseName() { * @deprecated Use {@link #getArchiveAppendix()} */ @Nullable - @Internal("Represented as part of archiveFile") @Deprecated + @ReplacedBy("archiveAppendix") public String getAppendix() { return archiveAppendix.getOrNull(); } @@ -254,6 +258,7 @@ public String getAppendix() { * @deprecated Use {@link #getArchiveAppendix()} */ @Deprecated + @ReplacedBy("archiveAppendix") public void setAppendix(@Nullable String appendix) { this.archiveAppendix.set(appendix); } @@ -276,8 +281,8 @@ public Property getArchiveAppendix() { * @deprecated Use {@link #getArchiveVersion()} */ @Nullable - @Internal("Represented as part of archiveFile") @Deprecated + @ReplacedBy("archiveVersion") public String getVersion() { return archiveVersion.getOrNull(); } @@ -288,6 +293,7 @@ public String getVersion() { * @deprecated Use {@link #getArchiveVersion()} */ @Deprecated + @ReplacedBy("archiveVersion") public void setVersion(@Nullable String version) { this.archiveVersion.set(version); } @@ -308,8 +314,8 @@ public Property getArchiveVersion() { * @deprecated Use {@link #getArchiveExtension()} */ @Nullable - @Internal("Represented as part of archiveFile") @Deprecated + @ReplacedBy("archiveExtension") public String getExtension() { return archiveExtension.getOrNull(); } @@ -320,6 +326,7 @@ public String getExtension() { * @deprecated Use {@link #getArchiveExtension()} */ @Deprecated + @ReplacedBy("archiveExtension") public void setExtension(@Nullable String extension) { this.archiveExtension.set(extension); } @@ -340,8 +347,8 @@ public Property getArchiveExtension() { * @deprecated Use {@link #getArchiveClassifier()} */ @Nullable - @Internal("Represented as part of archiveFile") @Deprecated + @ReplacedBy("archiveClassifier") public String getClassifier() { return archiveClassifier.getOrNull(); } @@ -352,6 +359,7 @@ public String getClassifier() { * @deprecated Use {@link #getArchiveClassifier()} */ @Deprecated + @ReplacedBy("archiveClassifier") public void setClassifier(@Nullable String classifier) { this.archiveClassifier.set(classifier); } diff --git a/subprojects/core/src/main/java/org/gradle/internal/service/scopes/ExecutionGlobalServices.java b/subprojects/core/src/main/java/org/gradle/internal/service/scopes/ExecutionGlobalServices.java index ca0e2b611aae9..860d45b58a2e6 100644 --- a/subprojects/core/src/main/java/org/gradle/internal/service/scopes/ExecutionGlobalServices.java +++ b/subprojects/core/src/main/java/org/gradle/internal/service/scopes/ExecutionGlobalServices.java @@ -50,6 +50,7 @@ import org.gradle.api.tasks.OutputDirectory; import org.gradle.api.tasks.OutputFile; import org.gradle.api.tasks.OutputFiles; +import org.gradle.api.tasks.ReplacedBy; import org.gradle.api.tasks.options.OptionValues; import org.gradle.cache.internal.CrossBuildInMemoryCacheFactory; import org.gradle.internal.instantiation.InstantiationScheme; @@ -89,6 +90,10 @@ PropertyAnnotationHandler createInternalAnnotationHandler() { return new NoOpPropertyAnnotationHandler(Internal.class); } + PropertyAnnotationHandler createReplacedByAnnotationHandler() { + return new NoOpPropertyAnnotationHandler(ReplacedBy.class); + } + PropertyAnnotationHandler createOptionValuesAnnotationHandler() { return new NoOpPropertyAnnotationHandler(OptionValues.class); } diff --git a/subprojects/docs/src/docs/dsl/org.gradle.api.tasks.bundling.AbstractArchiveTask.xml b/subprojects/docs/src/docs/dsl/org.gradle.api.tasks.bundling.AbstractArchiveTask.xml index 5afc70cf551b5..8d854c17bcaa4 100644 --- a/subprojects/docs/src/docs/dsl/org.gradle.api.tasks.bundling.AbstractArchiveTask.xml +++ b/subprojects/docs/src/docs/dsl/org.gradle.api.tasks.bundling.AbstractArchiveTask.xml @@ -26,11 +26,11 @@ archiveAppendix - null + "" appendix - null + "" baseName @@ -58,11 +58,11 @@ archiveClassifier - null + "" classifier - null + "" destinationDir diff --git a/subprojects/docs/src/docs/userguide/more_about_tasks.adoc b/subprojects/docs/src/docs/userguide/more_about_tasks.adoc index 88db2b988e24a..0bd96884e8edb 100644 --- a/subprojects/docs/src/docs/userguide/more_about_tasks.adoc +++ b/subprojects/docs/src/docs/userguide/more_about_tasks.adoc @@ -643,6 +643,10 @@ Using a file tree turns <> of | Any type | Indicates that the property is used internally but is neither an input nor an output. +| `@link:{javadocPath}/org/gradle/api/tasks/ReplacedBy.html[ReplacedBy]` +| Any type +| Indicates that the property has been replaced by another and should be ignored as an input or output. + | [#skip-when-empty]`@link:{javadocPath}/org/gradle/api/tasks/SkipWhenEmpty.html[SkipWhenEmpty]` | `File`+++*+++ | Used with `@InputFiles` or `@InputDirectory` to tell Gradle to skip the task if the corresponding files or directory are empty, along with all other input files declared with this annotation. Tasks that have been skipped due to all of their input files that were declared with this annotation being empty will result in a distinct “no source” outcome. For example, `NO-SOURCE` will be emitted in the console output. diff --git a/subprojects/plugin-development/src/main/java/org/gradle/plugin/devel/tasks/ValidateTaskProperties.java b/subprojects/plugin-development/src/main/java/org/gradle/plugin/devel/tasks/ValidateTaskProperties.java index 54e0ead044c71..9c299de7e4365 100644 --- a/subprojects/plugin-development/src/main/java/org/gradle/plugin/devel/tasks/ValidateTaskProperties.java +++ b/subprojects/plugin-development/src/main/java/org/gradle/plugin/devel/tasks/ValidateTaskProperties.java @@ -102,6 +102,7 @@ *
  • {@literal @}{@link javax.inject.Inject} marks a Gradle service used by the task.
  • *
  • {@literal @}{@link org.gradle.api.tasks.Console Console} marks a property that only influences the console output of the task.
  • *
  • {@literal @}{@link org.gradle.api.tasks.Internal Internal} mark an internal property of the task.
  • + *
  • {@literal @}{@link org.gradle.api.tasks.ReplacedBy ReplacedBy} mark a property as replaced by another (similar to {@code Internal}).
  • * * * From bf2c0b5eb347e72e7ef81654d3b848517d19014f Mon Sep 17 00:00:00 2001 From: Bo Zhang Date: Fri, 22 Feb 2019 10:48:26 +0800 Subject: [PATCH 033/853] Bump ci-health plugin version to 0.50 See https://github.com/gradle/gradle-private/issues/1820 We used a problematic library in ci-health 0.49. --- build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle.kts b/build.gradle.kts index 25b2d6ac95cf8..d6d8a558440e7 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -32,7 +32,7 @@ plugins { // We have to apply it here at the moment, so that when the build scan plugin is auto-applied via --scan can detect that // the plugin has been already applied. For that the plugin has to be applied with the new plugin DSL syntax. com.gradle.`build-scan` - id("org.gradle.ci.tag-single-build") version("0.49") + id("org.gradle.ci.tag-single-build") version("0.50") } defaultTasks("assemble") From 129d2dbe4a0c5a8ac572987143842cacc47b26fa Mon Sep 17 00:00:00 2001 From: Adam Murdoch Date: Wed, 20 Feb 2019 11:46:58 +1100 Subject: [PATCH 034/853] Add support for using the various `Property` types with a read-only abstract property on a generated type (in addition to the existing `ConfigurableFileCollection` support). --- ...tensionInstantiationIntegrationTest.groovy | 110 +++++++- .../file/DefaultFilePropertyFactory.java | 34 +++ .../file/DefaultProjectLayoutTest.groovy | 22 ++ .../instantiation/AbstractClassGenerator.java | 39 +-- .../AsmBackedClassGenerator.java | 47 +++- .../internal/instantiation/Managed.java | 2 +- ...ackedClassGeneratedManagedStateTest.groovy | 238 ++++++++++++++++++ ...edClassGeneratorInjectDecoratedTest.groovy | 10 - .../AsmBackedClassGeneratorTest.java | 189 +++----------- 9 files changed, 502 insertions(+), 189 deletions(-) create mode 100644 subprojects/model-core/src/test/groovy/org/gradle/internal/instantiation/AsmBackedClassGeneratedManagedStateTest.groovy diff --git a/subprojects/core/src/integTest/groovy/org/gradle/api/ObjectExtensionInstantiationIntegrationTest.groovy b/subprojects/core/src/integTest/groovy/org/gradle/api/ObjectExtensionInstantiationIntegrationTest.groovy index 4deb0e33a24fb..aeaf2af34f507 100644 --- a/subprojects/core/src/integTest/groovy/org/gradle/api/ObjectExtensionInstantiationIntegrationTest.groovy +++ b/subprojects/core/src/integTest/groovy/org/gradle/api/ObjectExtensionInstantiationIntegrationTest.groovy @@ -166,7 +166,7 @@ class ObjectExtensionInstantiationIntegrationTest extends AbstractIntegrationSpe succeeds() } - def "can create instance of interface with read-only FileCollection property"() { + def "can create instance of interface with read-only ConfigurableFileCollection property"() { buildFile << """ interface Thing { ConfigurableFileCollection getValue() @@ -182,6 +182,114 @@ class ObjectExtensionInstantiationIntegrationTest extends AbstractIntegrationSpe succeeds() } + def "can create instance of interface with read-only Property property"() { + buildFile << """ + interface Thing { + Property getValue() + } + + extensions.create("thing", Thing) + assert thing.value.getOrNull() == null + thing { + value = "value" + } + assert thing.value.get() == "value" + """ + + expect: + succeeds() + } + + def "can create instance of interface with read-only RegularFileProperty property"() { + buildFile << """ + interface Thing { + RegularFileProperty getValue() + } + + extensions.create("thing", Thing) + assert thing.value.getOrNull() == null + thing { + value = file("thing.txt") + } + assert thing.value.get() == layout.projectDir.file("thing.txt") + """ + + expect: + succeeds() + } + + def "can create instance of interface with read-only DirectoryProperty property"() { + buildFile << """ + interface Thing { + DirectoryProperty getValue() + } + + extensions.create("thing", Thing) + assert thing.value.getOrNull() == null + thing { + value = file("thing.txt") + } + assert thing.value.get() == layout.projectDir.dir("thing.txt") + """ + + expect: + succeeds() + } + + def "can create instance of interface with read-only ListProperty property"() { + buildFile << """ + interface Thing { + ListProperty getValue() + } + + extensions.create("thing", Thing) + assert thing.value.getOrNull() == [] + thing { + value = ["thing"] + } + assert thing.value.get() == ["thing"] + """ + + expect: + succeeds() + } + + def "can create instance of interface with read-only SetProperty property"() { + buildFile << """ + interface Thing { + SetProperty getValue() + } + + extensions.create("thing", Thing) + assert thing.value.getOrNull() == [] as Set + thing { + value = ["thing"] + } + assert thing.value.get() == ["thing"] as Set + """ + + expect: + succeeds() + } + + def "can create instance of interface with read-only MapProperty property"() { + buildFile << """ + interface Thing { + MapProperty getValue() + } + + extensions.create("thing", Thing) + assert thing.value.getOrNull() == [:] + thing { + value = [a: "b"] + } + assert thing.value.get() == [a: "b"] + """ + + expect: + succeeds() + } + def "can create instance of abstract class with mutable property"() { buildFile << """ abstract class Thing { diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/file/DefaultFilePropertyFactory.java b/subprojects/core/src/main/java/org/gradle/api/internal/file/DefaultFilePropertyFactory.java index dc116e14d9008..b74c149708adc 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/file/DefaultFilePropertyFactory.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/file/DefaultFilePropertyFactory.java @@ -64,6 +64,23 @@ public String toString() { return value.toString(); } + @Override + public boolean equals(Object obj) { + if (obj == this) { + return true; + } + if (obj == null || obj.getClass() != getClass()) { + return false; + } + FixedDirectory other = (FixedDirectory) obj; + return value.equals(other.value); + } + + @Override + public int hashCode() { + return value.hashCode(); + } + @Override public File getAsFile() { return value; @@ -108,6 +125,23 @@ public String toString() { return file.toString(); } + @Override + public boolean equals(Object obj) { + if (obj == this) { + return true; + } + if (obj == null || obj.getClass() != getClass()) { + return false; + } + FixedFile other = (FixedFile) obj; + return other.file.equals(file); + } + + @Override + public int hashCode() { + return file.hashCode(); + } + @Override public File getAsFile() { return file; diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/file/DefaultProjectLayoutTest.groovy b/subprojects/core/src/test/groovy/org/gradle/api/internal/file/DefaultProjectLayoutTest.groovy index 8ff3f6456f14d..ebb38ee2f4c13 100644 --- a/subprojects/core/src/test/groovy/org/gradle/api/internal/file/DefaultProjectLayoutTest.groovy +++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/file/DefaultProjectLayoutTest.groovy @@ -25,6 +25,8 @@ import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider import org.junit.Rule import spock.lang.Specification +import static org.gradle.util.Matchers.strictlyEquals + class DefaultProjectLayoutTest extends Specification { @Rule TestNameTestDirectoryProvider tmpDir = new TestNameTestDirectoryProvider() @@ -560,6 +562,26 @@ class DefaultProjectLayoutTest extends Specification { file2.getAsFile() == projectDir.file("build/b") } + def "directories are equal when their paths are equal"() { + expect: + def dir = layout.projectDirectory.dir("child") + strictlyEquals(dir, layout.projectDirectory.dir("child")) + + dir != layout.projectDirectory.dir("other") + dir != layout.projectDirectory.dir("child/child2") + dir != layout.projectDirectory.file("child") + } + + def "regular files are equal when their paths are equal"() { + expect: + def file = layout.projectDirectory.file("child") + strictlyEquals(file, layout.projectDirectory.file("child")) + + file != layout.projectDirectory.file("other") + file != layout.projectDirectory.file("child/child2") + file != layout.projectDirectory.dir("child") + } + def "can wrap File provider"() { def fileProvider = Stub(ProviderInternal) def file1 = projectDir.file("file1") diff --git a/subprojects/model-core/src/main/java/org/gradle/internal/instantiation/AbstractClassGenerator.java b/subprojects/model-core/src/main/java/org/gradle/internal/instantiation/AbstractClassGenerator.java index cd0bd59807045..5bfb57bb7e4da 100644 --- a/subprojects/model-core/src/main/java/org/gradle/internal/instantiation/AbstractClassGenerator.java +++ b/subprojects/model-core/src/main/java/org/gradle/internal/instantiation/AbstractClassGenerator.java @@ -25,12 +25,16 @@ import org.gradle.api.Action; import org.gradle.api.NonExtensible; import org.gradle.api.file.ConfigurableFileCollection; +import org.gradle.api.file.DirectoryProperty; +import org.gradle.api.file.RegularFileProperty; import org.gradle.api.internal.DynamicObjectAware; import org.gradle.api.internal.IConventionAware; import org.gradle.api.plugins.ExtensionAware; import org.gradle.api.provider.HasMultipleValues; +import org.gradle.api.provider.ListProperty; import org.gradle.api.provider.MapProperty; import org.gradle.api.provider.Property; +import org.gradle.api.provider.SetProperty; import org.gradle.internal.Cast; import org.gradle.internal.extensibility.NoConventionMapping; import org.gradle.internal.logging.text.TreeFormatter; @@ -228,7 +232,7 @@ private void inspectType(Class type, List validators, List type) { } @Override - boolean claimProperty(PropertyMetaData property) { + boolean claimPropertyImplementation(PropertyMetaData property) { if (extensible) { if (property.getName().equals("extensions")) { for (Method getter : property.getOverridableGetters()) { @@ -793,7 +797,7 @@ public void hasFields() { } @Override - boolean claimProperty(PropertyMetaData property) { + boolean claimPropertyImplementation(PropertyMetaData property) { // Skip properties with non-abstract getter or setter implementations for (Method getter : property.getters) { if (!Modifier.isAbstract(getter.getModifiers())) { @@ -808,9 +812,18 @@ boolean claimProperty(PropertyMetaData property) { if (property.getters.isEmpty()) { return false; } + + // Property is readable and all getters and setters are abstract + if (property.setters.isEmpty()) { - if (property.getType().equals(ConfigurableFileCollection.class)) { - // Read-only file collection property + if (property.getType().equals(ConfigurableFileCollection.class) + || property.getType().equals(ListProperty.class) + || property.getType().equals(SetProperty.class) + || property.getType().equals(MapProperty.class) + || property.getType().equals(RegularFileProperty.class) + || property.getType().equals(DirectoryProperty.class) + || property.getType().equals(Property.class)) { + // Read-only property with managed type readOnlyProperties.add(property); return true; } @@ -859,12 +872,10 @@ private static class PropertyTypePropertyHandler extends ClassGenerationHandler private final List propertyTyped = new ArrayList(); @Override - boolean claimProperty(PropertyMetaData property) { + void visitProperty(PropertyMetaData property) { if (property.isReadable() && isModelProperty(property)) { propertyTyped.add(property); - return true; } - return false; } @Override @@ -876,8 +887,8 @@ void applyTo(ClassGenerationVisitor visitor) { private boolean isModelProperty(PropertyMetaData property) { return Property.class.isAssignableFrom(property.getType()) || - HasMultipleValues.class.isAssignableFrom(property.getType()) || - MapProperty.class.isAssignableFrom(property.getType()); + HasMultipleValues.class.isAssignableFrom(property.getType()) || + MapProperty.class.isAssignableFrom(property.getType()); } } @@ -956,7 +967,7 @@ private static class ServicesPropertyHandler extends ClassGenerationHandler { private boolean hasServicesProperty; @Override - public boolean claimProperty(PropertyMetaData property) { + public boolean claimPropertyImplementation(PropertyMetaData property) { if (property.getName().equals("services") && property.isReadable() && ServiceRegistry.class.isAssignableFrom(property.getType())) { hasServicesProperty = true; return true; @@ -981,7 +992,7 @@ public AbstractInjectedPropertyHandler(Class annotation) { } @Override - public boolean claimProperty(PropertyMetaData property) { + public boolean claimPropertyImplementation(PropertyMetaData property) { for (Method method : property.getters) { if (method.getAnnotation(annotation) != null) { serviceInjectionProperties.add(property); diff --git a/subprojects/model-core/src/main/java/org/gradle/internal/instantiation/AsmBackedClassGenerator.java b/subprojects/model-core/src/main/java/org/gradle/internal/instantiation/AsmBackedClassGenerator.java index 6d29a607e47b6..37c839b422bcc 100644 --- a/subprojects/model-core/src/main/java/org/gradle/internal/instantiation/AsmBackedClassGenerator.java +++ b/subprojects/model-core/src/main/java/org/gradle/internal/instantiation/AsmBackedClassGenerator.java @@ -26,6 +26,8 @@ import org.gradle.api.Action; import org.gradle.api.Transformer; import org.gradle.api.file.ConfigurableFileCollection; +import org.gradle.api.file.DirectoryProperty; +import org.gradle.api.file.RegularFileProperty; import org.gradle.api.internal.ConventionMapping; import org.gradle.api.internal.DynamicObjectAware; import org.gradle.api.internal.GeneratedSubclass; @@ -36,6 +38,10 @@ import org.gradle.api.plugins.Convention; import org.gradle.api.plugins.ExtensionAware; import org.gradle.api.plugins.ExtensionContainer; +import org.gradle.api.provider.ListProperty; +import org.gradle.api.provider.MapProperty; +import org.gradle.api.provider.Property; +import org.gradle.api.provider.SetProperty; import org.gradle.internal.UncheckedException; import org.gradle.internal.extensibility.ConventionAwareHelper; import org.gradle.internal.logging.text.TreeFormatter; @@ -64,6 +70,7 @@ import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Modifier; +import java.lang.reflect.ParameterizedType; import java.util.ArrayList; import java.util.Collection; import java.util.List; @@ -943,17 +950,49 @@ public void applyManagedStateToProperty(PropertyMetaData property) { @Override public void applyReadOnlyManagedStateToGetter(PropertyMetaData property, Method getter) { - // GENERATE public () { if ( == null) { = services.get(ObjectFactory.class).fileCollection(); } return } + // GENERATE public () { if ( == null) { = services.get(ObjectFactory.class).(xxx); } return } Type propType = Type.getType(property.getType()); addLazyGetter(getter.getName(), Type.getMethodDescriptor(Type.getType(getter.getReturnType())), null, propFieldName(property), propType, methodVisitor -> { - // GENERATE services.get(ProjectLayout.class) + // GENERATE services.get(ObjectFactory.class) putServiceRegistryOnStack(methodVisitor); methodVisitor.visitLdcInsn(OBJECT_FACTORY_TYPE); methodVisitor.visitMethodInsn(Opcodes.INVOKEINTERFACE, SERVICE_LOOKUP_TYPE.getInternalName(), "get", RETURN_OBJECT_FROM_TYPE, true); methodVisitor.visitTypeInsn(Opcodes.CHECKCAST, OBJECT_FACTORY_TYPE.getInternalName()); - // GENERATE objectFactory.configurableFiles() - methodVisitor.visitMethodInsn(Opcodes.INVOKEINTERFACE, OBJECT_FACTORY_TYPE.getInternalName(), "fileCollection", RETURN_CONFIGURABLE_FILE_COLLECTION, true); + if (property.getType().equals(ConfigurableFileCollection.class)) { + // GENERATE objectFactory.fileCollection() + methodVisitor.visitMethodInsn(Opcodes.INVOKEINTERFACE, OBJECT_FACTORY_TYPE.getInternalName(), "fileCollection", RETURN_CONFIGURABLE_FILE_COLLECTION, true); + } else if (property.getType().equals(RegularFileProperty.class)) { + // GENERATE objectFactory.fileProperty() + methodVisitor.visitMethodInsn(Opcodes.INVOKEINTERFACE, OBJECT_FACTORY_TYPE.getInternalName(), "fileProperty", Type.getMethodDescriptor(Type.getType(RegularFileProperty.class)), true); + } else if (property.getType().equals(DirectoryProperty.class)) { + // GENERATE objectFactory.directoryProperty() + methodVisitor.visitMethodInsn(Opcodes.INVOKEINTERFACE, OBJECT_FACTORY_TYPE.getInternalName(), "directoryProperty", Type.getMethodDescriptor(Type.getType(DirectoryProperty.class)), true); + } else if (property.getType().equals(Property.class)) { + // GENERATE objectFactory.property(type) + Class elementType = (Class) ((ParameterizedType) property.getGenericType()).getActualTypeArguments()[0]; + methodVisitor.visitLdcInsn(Type.getType(elementType)); + methodVisitor.visitMethodInsn(Opcodes.INVOKEINTERFACE, OBJECT_FACTORY_TYPE.getInternalName(), "property", Type.getMethodDescriptor(Type.getType(Property.class), CLASS_TYPE), true); + } else if (property.getType().equals(ListProperty.class)) { + // GENERATE objectFactory.listProperty(type) + Class elementType = (Class) ((ParameterizedType) property.getGenericType()).getActualTypeArguments()[0]; + methodVisitor.visitLdcInsn(Type.getType(elementType)); + methodVisitor.visitMethodInsn(Opcodes.INVOKEINTERFACE, OBJECT_FACTORY_TYPE.getInternalName(), "listProperty", Type.getMethodDescriptor(Type.getType(ListProperty.class), CLASS_TYPE), true); + } else if (property.getType().equals(SetProperty.class)) { + // GENERATE objectFactory.setProperty(type) + Class elementType = (Class) ((ParameterizedType) property.getGenericType()).getActualTypeArguments()[0]; + methodVisitor.visitLdcInsn(Type.getType(elementType)); + methodVisitor.visitMethodInsn(Opcodes.INVOKEINTERFACE, OBJECT_FACTORY_TYPE.getInternalName(), "setProperty", Type.getMethodDescriptor(Type.getType(SetProperty.class), CLASS_TYPE), true); + } else if (property.getType().equals(MapProperty.class)) { + // GENERATE objectFactory.setProperty(type) + Class keyType = (Class) ((ParameterizedType) property.getGenericType()).getActualTypeArguments()[0]; + Class elementType = (Class) ((ParameterizedType) property.getGenericType()).getActualTypeArguments()[1]; + methodVisitor.visitLdcInsn(Type.getType(keyType)); + methodVisitor.visitLdcInsn(Type.getType(elementType)); + methodVisitor.visitMethodInsn(Opcodes.INVOKEINTERFACE, OBJECT_FACTORY_TYPE.getInternalName(), "mapProperty", Type.getMethodDescriptor(Type.getType(MapProperty.class), CLASS_TYPE, CLASS_TYPE), true); + } else { + throw new IllegalArgumentException(); + } }); } diff --git a/subprojects/model-core/src/main/java/org/gradle/internal/instantiation/Managed.java b/subprojects/model-core/src/main/java/org/gradle/internal/instantiation/Managed.java index dfafd0e9ac06a..8ed6dd373241c 100644 --- a/subprojects/model-core/src/main/java/org/gradle/internal/instantiation/Managed.java +++ b/subprojects/model-core/src/main/java/org/gradle/internal/instantiation/Managed.java @@ -17,7 +17,7 @@ package org.gradle.internal.instantiation; /** - * Mixed into each generated class, to mark it as fully managed. + * Mixed into generated classes whose state is fully managed. */ public interface Managed { /** diff --git a/subprojects/model-core/src/test/groovy/org/gradle/internal/instantiation/AsmBackedClassGeneratedManagedStateTest.groovy b/subprojects/model-core/src/test/groovy/org/gradle/internal/instantiation/AsmBackedClassGeneratedManagedStateTest.groovy new file mode 100644 index 0000000000000..f494184e53651 --- /dev/null +++ b/subprojects/model-core/src/test/groovy/org/gradle/internal/instantiation/AsmBackedClassGeneratedManagedStateTest.groovy @@ -0,0 +1,238 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.internal.instantiation + +import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider +import org.gradle.util.TestUtil +import org.junit.ClassRule +import spock.lang.Shared +import spock.lang.Unroll + +import static org.gradle.internal.instantiation.AsmBackedClassGeneratorTest.AbstractBean +import static org.gradle.internal.instantiation.AsmBackedClassGeneratorTest.AbstractBeanWithInheritedFields +import static org.gradle.internal.instantiation.AsmBackedClassGeneratorTest.Bean +import static org.gradle.internal.instantiation.AsmBackedClassGeneratorTest.BeanWithAbstractProperty +import static org.gradle.internal.instantiation.AsmBackedClassGeneratorTest.InterfaceBean +import static org.gradle.internal.instantiation.AsmBackedClassGeneratorTest.InterfaceDirectoryPropertyBean +import static org.gradle.internal.instantiation.AsmBackedClassGeneratorTest.InterfaceFileCollectionBean +import static org.gradle.internal.instantiation.AsmBackedClassGeneratorTest.InterfaceFilePropertyBean +import static org.gradle.internal.instantiation.AsmBackedClassGeneratorTest.InterfaceListPropertyBean +import static org.gradle.internal.instantiation.AsmBackedClassGeneratorTest.InterfaceMapPropertyBean +import static org.gradle.internal.instantiation.AsmBackedClassGeneratorTest.InterfacePropertyBean +import static org.gradle.internal.instantiation.AsmBackedClassGeneratorTest.InterfaceSetPropertyBean +import static org.gradle.internal.instantiation.AsmBackedClassGeneratorTest.InterfaceWithDefaultMethods + +class AsmBackedClassGeneratedManagedStateTest extends AbstractClassGeneratorSpec { + @ClassRule + @Shared + TestNameTestDirectoryProvider tmpDir = new TestNameTestDirectoryProvider() + final ClassGenerator generator = AsmBackedClassGenerator.injectOnly([], []) + + def canConstructInstanceOfAbstractClassWithAbstractPropertyGetterAndSetter() { + def bean = create(BeanWithAbstractProperty) + + expect: + bean.name == null + bean.setName("name") + bean.name == "name" + } + + def canUnpackAndRecreateAbstractClassWithAbstractPropertyGetterAndSetter() { + def bean = create(BeanWithAbstractProperty) + + expect: + bean instanceof Managed + bean.publicType() == BeanWithAbstractProperty + !bean.immutable() + def state = bean.unpackState() + state.length == 1 + state[0] == null + + def copy = bean.managedFactory().fromState(BeanWithAbstractProperty, state) + !copy.is(bean) + copy.name == null + + bean.setName("name") + copy.name == null + + def state2 = bean.unpackState() + state2.length == 1 + state2[0] == "name" + + def copy2 = bean.managedFactory().fromState(BeanWithAbstractProperty, state2) + !copy2.is(bean) + copy2.name == "name" + } + + def canConstructInstanceOfInterfaceWithPropertyGetterAndSetter() { + def bean = create(InterfaceBean) + + expect: + bean.name == null + bean.setName("name") + bean.name == "name" + + bean.numbers == null + bean.setNumbers([12] as Set) + bean.numbers == [12] as Set + } + + def canUnpackAndRecreateInstanceOfInterface() throws Exception { + def bean = create(InterfaceBean.class) + + expect: + bean instanceof Managed + bean.publicType() == InterfaceBean + !bean.immutable() + def state = bean.unpackState() + state.length == 2 + state[0] == null + state[1] == null + + def copy = bean.managedFactory().fromState(InterfaceBean, state) + !copy.is(bean) + copy.name == null + copy.numbers == null + + bean.setName("name") + bean.setNumbers([12] as Set) + copy.name == null + copy.numbers == null + + def state2 = bean.unpackState() + state2.length == 2 + state2[0] == "name" + state2[1] == [12] as Set + + def copy2 = bean.managedFactory().fromState(InterfaceBean, state2) + !copy2.is(bean) + copy2.name == "name" + copy2.numbers == [12] as Set + } + + def canConstructInstanceOfInterfaceWithFileCollectionGetter() { + def projectDir = tmpDir.testDirectory + def bean = create(InterfaceFileCollectionBean, TestUtil.createRootProject(projectDir).services) + + expect: + bean.prop.empty + bean.prop.from("a", "b") + bean.prop.files == [projectDir.file("a"), projectDir.file("b")] as Set + } + + @Unroll + def "canConstructInstanceOfInterfaceWithGetterOfFilePropertyType #type.simpleName"() { + def projectDir = tmpDir.testDirectory + def bean = create(type, TestUtil.createRootProject(projectDir).services) + + expect: + bean.prop.getOrNull() == null + bean.prop.set(projectDir.file("a")) + bean.prop.get().asFile == projectDir.file("a") + + where: + type << [InterfaceFilePropertyBean, InterfaceDirectoryPropertyBean] + } + + @Unroll + def "canConstructInstanceOfInterfaceWithGetterOfMutableType #type.simpleName"() { + def projectDir = tmpDir.testDirectory + def bean = create(type, TestUtil.createRootProject(projectDir).services) + + expect: + bean.prop.getOrNull() == defaultValue + bean.prop.set(newValue) + bean.prop.get() == newValue + + where: + type | defaultValue | newValue + InterfacePropertyBean | null | "value" + InterfaceListPropertyBean | [] | ["a", "b"] + InterfaceSetPropertyBean | [] as Set | ["a", "b"] as Set + InterfaceMapPropertyBean | [:] | [a: 1, b: 12] + } + + @Unroll + def "canUnpackAndRecreateInterfaceWithGetterOfMutableType #type.simpleName"() { + def projectDir = tmpDir.testDirectory + def bean = create(type, TestUtil.createRootProject(projectDir).services) + + expect: + bean instanceof Managed + bean.publicType() == type + !bean.immutable() + def state = bean.unpackState() + state.length == 1 + state[0].is(bean.prop) + + def copy = bean.managedFactory().fromState(type, state) + copy.prop.is(bean.prop) + + where: + type | _ + InterfaceFileCollectionBean | _ + InterfacePropertyBean | _ + InterfaceFilePropertyBean | _ + InterfaceDirectoryPropertyBean | _ + InterfaceListPropertyBean | _ + InterfaceSetPropertyBean | _ + InterfaceMapPropertyBean | _ + } + + def canConstructInstanceOfInterfaceWithDefaultMethodsOnly() { + def bean = create(InterfaceWithDefaultMethods) + + expect: + bean.name == "name" + } + + def canUnpackAndRecreateInstanceOfInterfaceWithDefaultMethodsOnly() { + def bean = create(InterfaceWithDefaultMethods) + + expect: + bean instanceof Managed + bean.publicType() == InterfaceWithDefaultMethods + bean.immutable() + def state = bean.unpackState() + state.length == 0 + + def copy = bean.managedFactory().fromState(InterfaceWithDefaultMethods, state) + !copy.is(bean) + copy.name == "name" + } + + def doesNotMixManagedIntoClassWithFields() { + def bean = create(Bean) + + expect: + !(bean instanceof Managed) + } + + def doesNotMixManagedIntoAbstractClassWithFields() { + def bean = create(AbstractBean, "value") + + expect: + !(bean instanceof Managed) + } + + def doesNotMixManagedIntoClassWithInheritedFields() { + def bean = create(AbstractBeanWithInheritedFields, "value") + + expect: + !(bean instanceof Managed) + } +} diff --git a/subprojects/model-core/src/test/groovy/org/gradle/internal/instantiation/AsmBackedClassGeneratorInjectDecoratedTest.groovy b/subprojects/model-core/src/test/groovy/org/gradle/internal/instantiation/AsmBackedClassGeneratorInjectDecoratedTest.groovy index 3cc9b18de1805..a13ee47cf722a 100644 --- a/subprojects/model-core/src/test/groovy/org/gradle/internal/instantiation/AsmBackedClassGeneratorInjectDecoratedTest.groovy +++ b/subprojects/model-core/src/test/groovy/org/gradle/internal/instantiation/AsmBackedClassGeneratorInjectDecoratedTest.groovy @@ -30,7 +30,6 @@ import java.lang.reflect.ParameterizedType import java.lang.reflect.Type import static org.gradle.internal.instantiation.AsmBackedClassGeneratorTest.FinalInjectBean -import static org.gradle.internal.instantiation.AsmBackedClassGeneratorTest.InjectPropertyBean import static org.gradle.internal.instantiation.AsmBackedClassGeneratorTest.NonGetterInjectBean import static org.gradle.internal.instantiation.AsmBackedClassGeneratorTest.PrivateInjectBean @@ -213,15 +212,6 @@ class AsmBackedClassGeneratorInjectDecoratedTest extends AbstractClassGeneratorS e.cause.message == "Cannot use @Inject annotation on method ExtensibleBeanWithInject.getExtensions()." } - def "cannot attach @Inject annotation to property whose type is Property"() { - when: - generator.generate(InjectPropertyBean) - - then: - def e = thrown(ClassGenerationException) - e.cause.message == "Cannot use @Inject annotation on method InjectPropertyBean.getProp()." - } - def "cannot attach @Inject annotation to final method"() { when: generator.generate(FinalInjectBean) diff --git a/subprojects/model-core/src/test/groovy/org/gradle/internal/instantiation/AsmBackedClassGeneratorTest.java b/subprojects/model-core/src/test/groovy/org/gradle/internal/instantiation/AsmBackedClassGeneratorTest.java index d6c0638ec8ef8..6aefd148b3e34 100755 --- a/subprojects/model-core/src/test/groovy/org/gradle/internal/instantiation/AsmBackedClassGeneratorTest.java +++ b/subprojects/model-core/src/test/groovy/org/gradle/internal/instantiation/AsmBackedClassGeneratorTest.java @@ -21,7 +21,9 @@ import org.gradle.api.Action; import org.gradle.api.NonExtensible; import org.gradle.api.file.ConfigurableFileCollection; +import org.gradle.api.file.DirectoryProperty; import org.gradle.api.file.FileCollection; +import org.gradle.api.file.RegularFileProperty; import org.gradle.api.internal.ConventionMapping; import org.gradle.api.internal.DynamicObjectAware; import org.gradle.api.internal.GeneratedSubclasses; @@ -33,7 +35,10 @@ import org.gradle.api.plugins.Convention; import org.gradle.api.plugins.ExtensionAware; import org.gradle.api.plugins.ExtensionContainer; +import org.gradle.api.provider.ListProperty; +import org.gradle.api.provider.MapProperty; import org.gradle.api.provider.Property; +import org.gradle.api.provider.SetProperty; import org.gradle.api.reflect.HasPublicType; import org.gradle.api.reflect.TypeOf; import org.gradle.internal.extensibility.ConventionAwareHelper; @@ -45,7 +50,6 @@ import org.gradle.internal.reflect.JavaReflectionUtil; import org.gradle.internal.service.DefaultServiceRegistry; import org.gradle.internal.service.ServiceRegistry; -import org.gradle.test.fixtures.file.TestFile; import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider; import org.gradle.util.TestUtil; import org.junit.Rule; @@ -79,9 +83,7 @@ import static org.gradle.util.TestUtil.call; import static org.gradle.util.WrapUtil.toList; import static org.hamcrest.Matchers.equalTo; -import static org.hamcrest.Matchers.hasItems; import static org.hamcrest.Matchers.instanceOf; -import static org.hamcrest.Matchers.not; import static org.hamcrest.Matchers.notNullValue; import static org.hamcrest.Matchers.nullValue; import static org.hamcrest.Matchers.sameInstance; @@ -448,154 +450,6 @@ public void cannotCreateInstanceOfClassWithAbstractSetMethod() throws Exception } } - @Test - public void canConstructInstanceOfAbstractClassWithAbstractPropertyGetterAndSetter() throws Exception { - BeanWithAbstractProperty bean = newInstance(BeanWithAbstractProperty.class); - - assertThat(bean.getName(), nullValue()); - bean.setName("name"); - assertThat(bean.getName(), equalTo("name")); - } - - @Test - public void canUnpackAndRecreateAbstractClassWithAbstractPropertyGetterAndSetter() throws Exception { - BeanWithAbstractProperty bean = newInstance(BeanWithAbstractProperty.class); - assertThat(bean, instanceOf(Managed.class)); - - Managed managed = (Managed) bean; - assertEquals(BeanWithAbstractProperty.class, managed.publicType()); - assertFalse(managed.immutable()); - Object[] state = (Object[]) managed.unpackState(); - assertThat(state.length, equalTo(1)); - assertThat(state[0], equalTo(null)); - - BeanWithAbstractProperty copy = managed.managedFactory().fromState(BeanWithAbstractProperty.class, state); - assertThat(copy, not(sameInstance(bean))); - assertThat(copy.getName(), nullValue()); - - bean.setName("name"); - - state = (Object[]) managed.unpackState(); - assertThat(state.length, equalTo(1)); - assertThat(state[0], equalTo("name")); - - copy = managed.managedFactory().fromState(BeanWithAbstractProperty.class, state); - assertThat(copy, not(sameInstance(bean))); - assertThat(copy.getName(), equalTo("name")); - } - - @Test - public void canConstructInstanceOfInterfaceWithPropertyGetterAndSetter() throws Exception { - InterfaceBean bean = newInstance(InterfaceBean.class); - - assertThat(bean.getName(), nullValue()); - bean.setName("name"); - assertThat(bean.getName(), equalTo("name")); - - assertThat(bean.getNumbers(), nullValue()); - bean.setNumbers(Collections.singleton(12)); - assertThat(bean.getNumbers(), equalTo(Collections.singleton(12))); - } - - @Test - public void canUnpackAndRecreateInstanceOfInterface() throws Exception { - InterfaceBean bean = newInstance(InterfaceBean.class); - assertThat(bean, instanceOf(Managed.class)); - - Managed managed = (Managed) bean; - assertEquals(InterfaceBean.class, managed.publicType()); - assertFalse(managed.immutable()); - Object[] state = (Object[]) managed.unpackState(); - assertThat(state.length, equalTo(2)); - assertThat(state[0], equalTo(null)); - assertThat(state[1], equalTo(null)); - - InterfaceBean copy = managed.managedFactory().fromState(InterfaceBean.class, state); - assertThat(copy.getName(), nullValue()); - assertThat(copy.getNumbers(), nullValue()); - - bean.setName("name"); - bean.setNumbers(Collections.singleton(12)); - - state = (Object[]) managed.unpackState(); - assertThat(state.length, equalTo(2)); - assertThat(state[0], equalTo("name")); - assertThat(state[1], equalTo(Collections.singleton(12))); - - copy = managed.managedFactory().fromState(InterfaceBean.class, state); - assertThat(copy.getName(), equalTo("name")); - assertThat(copy.getNumbers(), equalTo(Collections.singleton(12))); - } - - @Test - public void canConstructInstanceOfInterfaceWithFileCollectionGetter() throws Exception { - TestFile projectDir = tmpDir.getTestDirectory(); - InterfaceFileCollectionBean bean = newInstance(InterfaceFileCollectionBean.class, TestUtil.createRootProject(projectDir).getServices()); - - assertTrue(bean.getFiles().isEmpty()); - - bean.getFiles().from("a", "b"); - - assertThat(bean.getFiles(), hasItems(projectDir.file("a"), projectDir.file("b"))); - } - - @Test - public void canUnpackAndRecreateInterfaceWithFileCollectionGetter() throws Exception { - TestFile projectDir = tmpDir.getTestDirectory(); - InterfaceFileCollectionBean bean = newInstance(InterfaceFileCollectionBean.class, TestUtil.createRootProject(projectDir).getServices()); - assertThat(bean, instanceOf(Managed.class)); - - Managed managed = (Managed) bean; - assertEquals(InterfaceFileCollectionBean.class, managed.publicType()); - assertFalse(managed.immutable()); - Object[] state = (Object[]) managed.unpackState(); - assertEquals(1, state.length); - assertTrue(state[0] instanceof ConfigurableFileCollection); - assertSame(state[0], bean.getFiles()); - - InterfaceFileCollectionBean copy = managed.managedFactory().fromState(InterfaceFileCollectionBean.class, state); - assertTrue(copy.getFiles().isEmpty()); - } - - @Test - public void canConstructInstanceOfInterfaceWithDefaultMethodsOnly() throws Exception { - InterfaceWithDefaultMethods bean = newInstance(InterfaceWithDefaultMethods.class); - - assertThat(bean.getName(), equalTo("name")); - } - - @Test - public void canUnpackAndRecreateInstanceOfInterfaceWithDefaultMethodsOnly() throws Exception { - InterfaceWithDefaultMethods bean = newInstance(InterfaceWithDefaultMethods.class); - assertThat(bean, instanceOf(Managed.class)); - - Managed managed = (Managed) bean; - assertEquals(InterfaceWithDefaultMethods.class, managed.publicType()); - assertTrue(managed.immutable()); // no properties - Object[] state = (Object[]) managed.unpackState(); - assertThat(state.length, equalTo(0)); - - InterfaceWithDefaultMethods copy = managed.managedFactory().fromState(InterfaceWithDefaultMethods.class, state); - assertThat(copy, not(nullValue())); - } - - @Test - public void doesNotMixManagedIntoClassWithFields() throws Exception { - Bean bean = newInstance(Bean.class); - assertThat(bean, not(instanceOf(Managed.class))); - } - - @Test - public void doesNotMixManagedIntoAbstractClassWithFields() throws Exception { - AbstractBean bean = newInstance(AbstractBean.class, "value"); - assertThat(bean, not(instanceOf(Managed.class))); - } - - @Test - public void doesNotMixManagedIntoClassWithInheritedFields() throws Exception { - AbstractBeanWithInheritedFields bean = newInstance(AbstractBeanWithInheritedFields.class, "value"); - assertThat(bean, not(instanceOf(Managed.class))); - } @Test public void cannotCreateInstanceOfInterfaceWithAbstractGetterAndNoSetter() throws Exception { @@ -1818,13 +1672,6 @@ public Property getaProp() { } } - public static class InjectPropertyBean { - @Inject - public Property getProp() { - throw new UnsupportedOperationException(); - } - } - public interface WithProperties { Number getNumber(); } @@ -1891,7 +1738,31 @@ public interface InterfaceBean { } public interface InterfaceFileCollectionBean { - ConfigurableFileCollection getFiles(); + ConfigurableFileCollection getProp(); + } + + public interface InterfacePropertyBean { + Property getProp(); + } + + public interface InterfaceFilePropertyBean { + RegularFileProperty getProp(); + } + + public interface InterfaceDirectoryPropertyBean { + DirectoryProperty getProp(); + } + + public interface InterfaceListPropertyBean { + ListProperty getProp(); + } + + public interface InterfaceSetPropertyBean { + SetProperty getProp(); + } + + public interface InterfaceMapPropertyBean { + MapProperty getProp(); } public interface InterfaceWithDefaultMethods { From 99fcaa133b623bbcd85b45c7ff48b1dcebf5677e Mon Sep 17 00:00:00 2001 From: Adam Murdoch Date: Wed, 20 Feb 2019 17:08:59 +1100 Subject: [PATCH 035/853] Allow various `Property` types to be isolated, so these can be used on artifact transform parameters objects (and everywhere else that isolated values can be used). --- .../scopes/GradleUserHomeScopeServices.java | 3 +- .../org/gradle/util/SnapshotTestUtil.groovy | 4 +- ...sformValuesInjectionIntegrationTest.groovy | 50 +++++ .../steps/IncrementalExecutionTest.groovy | 3 +- .../snapshot/impl/AbstractArraySnapshot.java | 2 +- .../impl/AbstractIsolatableScalarValue.java | 2 +- .../snapshot/impl/AbstractListSnapshot.java | 2 +- .../impl/AbstractManagedTypeSnapshot.java | 2 +- .../snapshot/impl/AbstractMapSnapshot.java | 2 +- .../impl/AbstractScalarValueSnapshot.java | 8 +- .../snapshot/impl/AbstractSetSnapshot.java | 2 +- .../snapshot/impl/ArrayValueSnapshot.java | 2 +- .../impl/AttributeDefinitionSnapshot.java | 2 +- .../snapshot/impl/BooleanValueSnapshot.java | 2 +- .../impl/DefaultValueSnapshotter.java | 45 +++-- .../snapshot/impl/FileValueSnapshot.java | 2 +- .../impl/ImmutableManagedValueSnapshot.java | 2 +- .../snapshot/impl/IntegerValueSnapshot.java | 2 +- .../impl/IsolatableEnumValueSnapshot.java | 2 +- .../snapshot/impl/IsolatedFileCollection.java | 2 +- .../impl/IsolatedImmutableManagedValue.java | 2 +- .../internal/snapshot/impl/IsolatedList.java | 2 +- .../snapshot/impl/IsolatedListProperty.java | 41 ++++ .../impl/IsolatedManagedTypeSnapshot.java | 2 +- .../internal/snapshot/impl/IsolatedMap.java | 2 +- .../snapshot/impl/IsolatedMapProperty.java | 43 +++++ .../snapshot/impl/IsolatedProperty.java | 40 ++++ .../snapshot/impl/IsolatedProvider.java | 54 ++++++ ...a => IsolatedSerializedValueSnapshot.java} | 4 +- .../internal/snapshot/impl/IsolatedSet.java | 2 +- .../snapshot/impl/IsolatedSetProperty.java | 41 ++++ .../snapshot/impl/ListValueSnapshot.java | 2 +- .../snapshot/impl/LongValueSnapshot.java | 2 +- .../snapshot/impl/ManagedTypeSnapshot.java | 2 +- .../snapshot/impl/MapValueSnapshot.java | 2 +- .../snapshot/impl/NullValueSnapshot.java | 2 +- .../snapshot/impl/ProviderSnapshot.java | 64 ------- .../impl/SerializedValueSnapshot.java | 2 +- .../snapshot/impl/SetValueSnapshot.java | 2 +- .../snapshot/impl/ShortValueSnapshot.java | 2 +- .../snapshot/impl/SnapshotSerializer.java | 15 +- .../snapshot/impl/StringValueSnapshot.java | 2 +- .../impl/DefaultValueSnapshotterTest.groovy | 178 +++++++++++++----- .../impl/SnapshotSerializerTest.groovy | 8 - 44 files changed, 478 insertions(+), 179 deletions(-) create mode 100644 subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/IsolatedListProperty.java create mode 100644 subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/IsolatedMapProperty.java create mode 100644 subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/IsolatedProperty.java create mode 100644 subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/IsolatedProvider.java rename subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/{IsolatableSerializedValueSnapshot.java => IsolatedSerializedValueSnapshot.java} (87%) create mode 100644 subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/IsolatedSetProperty.java delete mode 100644 subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/ProviderSnapshot.java diff --git a/subprojects/core/src/main/java/org/gradle/internal/service/scopes/GradleUserHomeScopeServices.java b/subprojects/core/src/main/java/org/gradle/internal/service/scopes/GradleUserHomeScopeServices.java index 96912aab2f4fd..274183ab01026 100644 --- a/subprojects/core/src/main/java/org/gradle/internal/service/scopes/GradleUserHomeScopeServices.java +++ b/subprojects/core/src/main/java/org/gradle/internal/service/scopes/GradleUserHomeScopeServices.java @@ -35,7 +35,6 @@ import org.gradle.api.internal.initialization.loadercache.ClassLoaderCache; import org.gradle.api.internal.initialization.loadercache.DefaultClassLoaderCache; import org.gradle.api.internal.initialization.loadercache.DefaultClasspathHasher; -import org.gradle.api.internal.model.NamedObjectInstantiator; import org.gradle.cache.CacheRepository; import org.gradle.cache.PersistentIndexedCache; import org.gradle.cache.PersistentIndexedCacheParameters; @@ -149,7 +148,7 @@ CrossBuildInMemoryCachingScriptClassCache createCachingScriptCompiler(CrossBuild } DefaultValueSnapshotter createValueSnapshotter(ClassLoaderHierarchyHasher classLoaderHierarchyHasher) { - return new DefaultValueSnapshotter(classLoaderHierarchyHasher, NamedObjectInstantiator.INSTANCE); + return new DefaultValueSnapshotter(classLoaderHierarchyHasher); } ClassLoaderHierarchyHasher createClassLoaderHierarchyHasher(ClassLoaderRegistry registry, ClassLoaderHasher classLoaderHasher) { diff --git a/subprojects/core/src/testFixtures/groovy/org/gradle/util/SnapshotTestUtil.groovy b/subprojects/core/src/testFixtures/groovy/org/gradle/util/SnapshotTestUtil.groovy index 392d50be81e49..20177b36ac85e 100644 --- a/subprojects/core/src/testFixtures/groovy/org/gradle/util/SnapshotTestUtil.groovy +++ b/subprojects/core/src/testFixtures/groovy/org/gradle/util/SnapshotTestUtil.groovy @@ -16,7 +16,7 @@ package org.gradle.util -import org.gradle.api.internal.model.NamedObjectInstantiator + import org.gradle.internal.classloader.ClassLoaderHierarchyHasher import org.gradle.internal.hash.HashCode import org.gradle.internal.snapshot.ValueSnapshotter @@ -29,6 +29,6 @@ class SnapshotTestUtil { HashCode getClassLoaderHash(ClassLoader classLoader) { return HashCode.fromInt(classLoader.hashCode()) } - }, NamedObjectInstantiator.INSTANCE) + }) } } diff --git a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformValuesInjectionIntegrationTest.groovy b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformValuesInjectionIntegrationTest.groovy index da0a1eec1a278..618bef70b00de 100644 --- a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformValuesInjectionIntegrationTest.groovy +++ b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformValuesInjectionIntegrationTest.groovy @@ -94,6 +94,56 @@ class ArtifactTransformValuesInjectionIntegrationTest extends AbstractDependency outputContains("result = [b.jar.green, c.jar.green]") } + @Unroll + def "transform can receive parameter of type #type"() { + settingsFile << """ + include 'a', 'b', 'c' + """ + setupBuildWithColorTransform { + params(""" + prop.set(${value}) + """) + } + buildFile << """ + project(':a') { + dependencies { + implementation project(':b') + implementation project(':c') + } + } + + @AssociatedTransformAction(MakeGreenAction) + interface MakeGreen { + @Input + ${type} getProp() + @Input @Optional + ${type} getOtherProp() + } + + abstract class MakeGreenAction implements TransformAction { + @TransformParameters + abstract MakeGreen getParameters() + + void transform(TransformOutputs outputs) { + println "processing using " + parameters.prop.get() + assert parameters.otherProp.getOrNull() == ${expectedNullValue} + } + } +""" + when: + run("a:resolve") + + then: + outputContains("processing using ${expected}") + + where: + type | value | expected | expectedNullValue + "Property" | "'value'" | 'value' | null + "ListProperty" | "['a', 'b']" | "[a, b]" | "[]" + "SetProperty" | "['a', 'b']" | "[a, b]" | "[] as Set" + "MapProperty" | "[a: 1, b: 2]" | "[a:1, b:2]" | "[:]" + } + def "transform parameters are validated for input output annotations"() { settingsFile << """ include 'a', 'b', 'c' diff --git a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/impl/steps/IncrementalExecutionTest.groovy b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/impl/steps/IncrementalExecutionTest.groovy index 6f9ff7eb15c09..f956ec3710fd9 100644 --- a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/impl/steps/IncrementalExecutionTest.groovy +++ b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/impl/steps/IncrementalExecutionTest.groovy @@ -23,7 +23,6 @@ import org.gradle.api.file.FileCollection import org.gradle.api.internal.cache.StringInterner import org.gradle.api.internal.file.TestFiles import org.gradle.api.internal.file.collections.ImmutableFileCollection -import org.gradle.api.internal.model.NamedObjectInstantiator import org.gradle.caching.internal.CacheableEntity import org.gradle.caching.internal.origin.OriginMetadata import org.gradle.internal.classloader.ClassLoaderHierarchyHasher @@ -95,7 +94,7 @@ class IncrementalExecutionTest extends Specification { return HashCode.fromInt(1234) } } - def valueSnapshotter = new DefaultValueSnapshotter(classloaderHierarchyHasher, new NamedObjectInstantiator()) + def valueSnapshotter = new DefaultValueSnapshotter(classloaderHierarchyHasher) final outputFile = temporaryFolder.file("output-file") final outputDir = temporaryFolder.file("output-dir") diff --git a/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/AbstractArraySnapshot.java b/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/AbstractArraySnapshot.java index 076c453d8b58e..bcee27705252b 100644 --- a/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/AbstractArraySnapshot.java +++ b/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/AbstractArraySnapshot.java @@ -22,7 +22,7 @@ import java.util.List; -public class AbstractArraySnapshot implements Hashable { +class AbstractArraySnapshot implements Hashable { protected final ImmutableList elements; public AbstractArraySnapshot(ImmutableList elements) { diff --git a/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/AbstractIsolatableScalarValue.java b/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/AbstractIsolatableScalarValue.java index 81931e29cc59d..9b4a89efe8534 100644 --- a/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/AbstractIsolatableScalarValue.java +++ b/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/AbstractIsolatableScalarValue.java @@ -26,7 +26,7 @@ * * @param */ -public abstract class AbstractIsolatableScalarValue extends AbstractScalarValueSnapshot implements Isolatable { +abstract class AbstractIsolatableScalarValue extends AbstractScalarValueSnapshot implements Isolatable { public AbstractIsolatableScalarValue(T value) { super(value); } diff --git a/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/AbstractListSnapshot.java b/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/AbstractListSnapshot.java index f997c4f73d075..bdffd902145dd 100644 --- a/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/AbstractListSnapshot.java +++ b/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/AbstractListSnapshot.java @@ -22,7 +22,7 @@ import java.util.List; -public class AbstractListSnapshot implements Hashable { +class AbstractListSnapshot implements Hashable { protected final ImmutableList elements; public AbstractListSnapshot(ImmutableList elements) { diff --git a/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/AbstractManagedTypeSnapshot.java b/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/AbstractManagedTypeSnapshot.java index 267fa5c4da923..71a295deb3ade 100644 --- a/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/AbstractManagedTypeSnapshot.java +++ b/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/AbstractManagedTypeSnapshot.java @@ -19,7 +19,7 @@ import org.gradle.internal.hash.Hashable; import org.gradle.internal.hash.Hasher; -public class AbstractManagedTypeSnapshot implements Hashable { +class AbstractManagedTypeSnapshot implements Hashable { protected final T state; public AbstractManagedTypeSnapshot(T state) { diff --git a/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/AbstractMapSnapshot.java b/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/AbstractMapSnapshot.java index 8dc0ee4b5957f..6998219f95030 100644 --- a/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/AbstractMapSnapshot.java +++ b/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/AbstractMapSnapshot.java @@ -21,7 +21,7 @@ import org.gradle.internal.hash.Hashable; import org.gradle.internal.hash.Hasher; -public class AbstractMapSnapshot implements Hashable { +class AbstractMapSnapshot implements Hashable { protected final ImmutableList> entries; public AbstractMapSnapshot(ImmutableList> entries) { diff --git a/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/AbstractScalarValueSnapshot.java b/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/AbstractScalarValueSnapshot.java index 63a5ee6c40f3f..8eb1e4080899c 100644 --- a/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/AbstractScalarValueSnapshot.java +++ b/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/AbstractScalarValueSnapshot.java @@ -24,7 +24,7 @@ * * @param */ -public abstract class AbstractScalarValueSnapshot implements ValueSnapshot { +abstract class AbstractScalarValueSnapshot implements ValueSnapshot { private final T value; public AbstractScalarValueSnapshot(T value) { @@ -40,7 +40,11 @@ public ValueSnapshot snapshot(Object value, ValueSnapshotter snapshotter) { if (this.value.equals(value)) { return this; } - return snapshotter.snapshot(value); + ValueSnapshot snapshot = snapshotter.snapshot(value); + if (snapshot.equals(this)) { + return this; + } + return snapshot; } @Override diff --git a/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/AbstractSetSnapshot.java b/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/AbstractSetSnapshot.java index e9e003d8704ef..eae45471f7395 100644 --- a/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/AbstractSetSnapshot.java +++ b/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/AbstractSetSnapshot.java @@ -20,7 +20,7 @@ import org.gradle.internal.hash.Hashable; import org.gradle.internal.hash.Hasher; -public class AbstractSetSnapshot implements Hashable { +class AbstractSetSnapshot implements Hashable { protected final ImmutableSet elements; public AbstractSetSnapshot(ImmutableSet elements) { diff --git a/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/ArrayValueSnapshot.java b/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/ArrayValueSnapshot.java index 5de7b2d15ff1b..17b7f617309f3 100644 --- a/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/ArrayValueSnapshot.java +++ b/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/ArrayValueSnapshot.java @@ -20,7 +20,7 @@ import org.gradle.internal.snapshot.ValueSnapshot; import org.gradle.internal.snapshot.ValueSnapshotter; -public class ArrayValueSnapshot extends AbstractArraySnapshot implements ValueSnapshot { +class ArrayValueSnapshot extends AbstractArraySnapshot implements ValueSnapshot { public static final ArrayValueSnapshot EMPTY = new ArrayValueSnapshot(ImmutableList.of()); public ArrayValueSnapshot(ImmutableList elements) { diff --git a/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/AttributeDefinitionSnapshot.java b/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/AttributeDefinitionSnapshot.java index a2e79fd4aa55b..f75cda462eaeb 100644 --- a/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/AttributeDefinitionSnapshot.java +++ b/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/AttributeDefinitionSnapshot.java @@ -20,7 +20,7 @@ import org.gradle.internal.classloader.ClassLoaderHierarchyHasher; import org.gradle.internal.hash.Hasher; -public class AttributeDefinitionSnapshot extends AbstractIsolatableScalarValue> { +class AttributeDefinitionSnapshot extends AbstractIsolatableScalarValue> { private final ClassLoaderHierarchyHasher classLoaderHasher; diff --git a/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/BooleanValueSnapshot.java b/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/BooleanValueSnapshot.java index 898d558a18021..09639e5c2b048 100644 --- a/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/BooleanValueSnapshot.java +++ b/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/BooleanValueSnapshot.java @@ -18,7 +18,7 @@ import org.gradle.internal.hash.Hasher; -public class BooleanValueSnapshot extends AbstractIsolatableScalarValue { +class BooleanValueSnapshot extends AbstractIsolatableScalarValue { public static final BooleanValueSnapshot TRUE = new BooleanValueSnapshot(true); public static final BooleanValueSnapshot FALSE = new BooleanValueSnapshot(false); diff --git a/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/DefaultValueSnapshotter.java b/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/DefaultValueSnapshotter.java index 1afd07c2bffbc..be7103efc252e 100644 --- a/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/DefaultValueSnapshotter.java +++ b/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/DefaultValueSnapshotter.java @@ -21,8 +21,14 @@ import org.gradle.api.UncheckedIOException; import org.gradle.api.attributes.Attribute; import org.gradle.api.file.ConfigurableFileCollection; -import org.gradle.api.internal.model.NamedObjectInstantiator; +import org.gradle.api.internal.provider.CollectionPropertyInternal; +import org.gradle.api.internal.provider.DefaultMapProperty; +import org.gradle.api.internal.provider.ProviderInternal; +import org.gradle.api.provider.ListProperty; +import org.gradle.api.provider.MapProperty; +import org.gradle.api.provider.Property; import org.gradle.api.provider.Provider; +import org.gradle.api.provider.SetProperty; import org.gradle.internal.Cast; import org.gradle.internal.Pair; import org.gradle.internal.classloader.ClassLoaderHierarchyHasher; @@ -47,9 +53,9 @@ public class DefaultValueSnapshotter implements ValueSnapshotter, IsolatableFact private final ValueVisitor valueSnapshotValueVisitor; private final ValueVisitor> isolatableValueVisitor; - public DefaultValueSnapshotter(ClassLoaderHierarchyHasher classLoaderHasher, NamedObjectInstantiator namedObjectInstantiator) { + public DefaultValueSnapshotter(ClassLoaderHierarchyHasher classLoaderHasher) { valueSnapshotValueVisitor = new ValueSnapshotVisitor(classLoaderHasher); - isolatableValueVisitor = new IsolatableVisitor(classLoaderHasher, namedObjectInstantiator); + isolatableValueVisitor = new IsolatableVisitor(classLoaderHasher); } @Override @@ -146,9 +152,9 @@ private T processValue(@Nullable Object value, ValueVisitor visitor) { } if (value instanceof Provider) { Provider provider = (Provider) value; - Object providerValue = provider.get(); + Object providerValue = provider.getOrNull(); T providerValueSnapshot = processValue(providerValue, visitor); - return visitor.provider(providerValue, providerValueSnapshot); + return visitor.provider(provider, providerValueSnapshot); } if (value instanceof Managed) { Managed managed = (Managed) value; @@ -224,7 +230,7 @@ private interface ValueVisitor { T map(ImmutableList> elements); - T provider(Object value, T snapshot); + T provider(Provider provider, T snapshot); T fromFileCollection(ConfigurableFileCollection files); @@ -304,8 +310,8 @@ public ValueSnapshot fromIsolatable(Isolatable value) { } @Override - public ValueSnapshot provider(Object value, ValueSnapshot snapshot) { - return new ProviderSnapshot(snapshot); + public ValueSnapshot provider(Provider provider, ValueSnapshot snapshot) { + return snapshot; } @Override @@ -351,11 +357,9 @@ public ValueSnapshot map(ImmutableList> eleme private static class IsolatableVisitor implements ValueVisitor> { private final ClassLoaderHierarchyHasher classLoaderHasher; - private final NamedObjectInstantiator namedObjectInstantiator; - IsolatableVisitor(ClassLoaderHierarchyHasher classLoaderHasher, NamedObjectInstantiator namedObjectInstantiator) { + IsolatableVisitor(ClassLoaderHierarchyHasher classLoaderHasher) { this.classLoaderHasher = classLoaderHasher; - this.namedObjectInstantiator = namedObjectInstantiator; } @Override @@ -425,12 +429,25 @@ public Isolatable fromIsolatable(Isolatable value) { @Override public Isolatable serialized(Object value, byte[] serializedValue) { - return new IsolatableSerializedValueSnapshot(classLoaderHasher.getClassLoaderHash(value.getClass().getClassLoader()), serializedValue, value.getClass()); + return new IsolatedSerializedValueSnapshot(classLoaderHasher.getClassLoaderHash(value.getClass().getClassLoader()), serializedValue, value.getClass()); } @Override - public Isolatable provider(Object value, Isolatable snapshot) { - throw new IsolationException(value); + public Isolatable provider(Provider provider, Isolatable snapshot) { + if (provider instanceof Property) { + return new IsolatedProperty(((ProviderInternal)provider).getType(), snapshot); + } + if (provider instanceof ListProperty) { + return new IsolatedListProperty(((CollectionPropertyInternal) provider).getElementType(), snapshot); + } + if (provider instanceof SetProperty) { + return new IsolatedSetProperty(((CollectionPropertyInternal) provider).getElementType(), snapshot); + } + if (provider instanceof MapProperty) { + DefaultMapProperty mapProperty = (DefaultMapProperty) provider; + return new IsolatedMapProperty(mapProperty.getKeyType(), mapProperty.getValueType(), snapshot); + } + return new IsolatedProvider(snapshot); } @Override diff --git a/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/FileValueSnapshot.java b/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/FileValueSnapshot.java index 8a7fa4089cea2..3c77241928bcf 100644 --- a/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/FileValueSnapshot.java +++ b/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/FileValueSnapshot.java @@ -24,7 +24,7 @@ import javax.annotation.Nullable; import java.io.File; -public class FileValueSnapshot extends AbstractScalarValueSnapshot implements Isolatable { +class FileValueSnapshot extends AbstractScalarValueSnapshot implements Isolatable { public FileValueSnapshot(File value) { super(value.getPath()); } diff --git a/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/ImmutableManagedValueSnapshot.java b/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/ImmutableManagedValueSnapshot.java index 3e2958c8d5aac..f2839bf85c99e 100644 --- a/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/ImmutableManagedValueSnapshot.java +++ b/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/ImmutableManagedValueSnapshot.java @@ -22,7 +22,7 @@ import javax.annotation.Nullable; -public class ImmutableManagedValueSnapshot implements ValueSnapshot { +class ImmutableManagedValueSnapshot implements ValueSnapshot { private final String className; private final String value; diff --git a/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/IntegerValueSnapshot.java b/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/IntegerValueSnapshot.java index 93dc17a33a07f..118fad5de8de6 100644 --- a/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/IntegerValueSnapshot.java +++ b/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/IntegerValueSnapshot.java @@ -18,7 +18,7 @@ import org.gradle.internal.hash.Hasher; -public class IntegerValueSnapshot extends AbstractIsolatableScalarValue { +class IntegerValueSnapshot extends AbstractIsolatableScalarValue { public IntegerValueSnapshot(Integer value) { super(value); } diff --git a/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/IsolatableEnumValueSnapshot.java b/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/IsolatableEnumValueSnapshot.java index 13fb475b6e966..befcb4b2b6c27 100644 --- a/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/IsolatableEnumValueSnapshot.java +++ b/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/IsolatableEnumValueSnapshot.java @@ -24,7 +24,7 @@ /** * Isolates an Enum value and is a snapshot for that value. */ -public class IsolatableEnumValueSnapshot extends EnumValueSnapshot implements Isolatable { +class IsolatableEnumValueSnapshot extends EnumValueSnapshot implements Isolatable { private final Enum value; public IsolatableEnumValueSnapshot(Enum value) { diff --git a/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/IsolatedFileCollection.java b/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/IsolatedFileCollection.java index 45fe4c9962aa2..c1628e286915c 100644 --- a/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/IsolatedFileCollection.java +++ b/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/IsolatedFileCollection.java @@ -27,7 +27,7 @@ import java.io.File; import java.util.Set; -public class IsolatedFileCollection implements Isolatable { +class IsolatedFileCollection implements Isolatable { private final Set files; public IsolatedFileCollection(ConfigurableFileCollection files) { diff --git a/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/IsolatedImmutableManagedValue.java b/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/IsolatedImmutableManagedValue.java index 548768310407f..562adde8b1b0a 100644 --- a/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/IsolatedImmutableManagedValue.java +++ b/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/IsolatedImmutableManagedValue.java @@ -22,7 +22,7 @@ import javax.annotation.Nullable; -public class IsolatedImmutableManagedValue extends AbstractIsolatableScalarValue { +class IsolatedImmutableManagedValue extends AbstractIsolatableScalarValue { public IsolatedImmutableManagedValue(Managed managed) { super(managed); } diff --git a/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/IsolatedList.java b/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/IsolatedList.java index 09f9ae5b6ecb1..3354d2375e17f 100644 --- a/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/IsolatedList.java +++ b/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/IsolatedList.java @@ -24,7 +24,7 @@ import java.util.ArrayList; import java.util.List; -public class IsolatedList extends AbstractListSnapshot> implements Isolatable> { +class IsolatedList extends AbstractListSnapshot> implements Isolatable> { public static final IsolatedList EMPTY = new IsolatedList(ImmutableList.of()); public IsolatedList(ImmutableList> elements) { diff --git a/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/IsolatedListProperty.java b/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/IsolatedListProperty.java new file mode 100644 index 0000000000000..73656ea84ed66 --- /dev/null +++ b/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/IsolatedListProperty.java @@ -0,0 +1,41 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.internal.snapshot.impl; + +import org.gradle.api.internal.provider.DefaultListProperty; +import org.gradle.api.provider.ListProperty; +import org.gradle.internal.isolation.Isolatable; + +import javax.annotation.Nullable; +import java.util.List; + +class IsolatedListProperty extends IsolatedProvider { + private final Class type; + + public IsolatedListProperty(Class type, Isolatable value) { + super(value); + this.type = type; + } + + @Nullable + @Override + public ListProperty isolate() { + DefaultListProperty property = new DefaultListProperty<>((Class) type); + property.set((List) value.isolate()); + return property; + } +} diff --git a/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/IsolatedManagedTypeSnapshot.java b/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/IsolatedManagedTypeSnapshot.java index 07ba848d42185..fbc1ef140da23 100644 --- a/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/IsolatedManagedTypeSnapshot.java +++ b/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/IsolatedManagedTypeSnapshot.java @@ -22,7 +22,7 @@ import javax.annotation.Nullable; -public class IsolatedManagedTypeSnapshot extends AbstractManagedTypeSnapshot> implements Isolatable { +class IsolatedManagedTypeSnapshot extends AbstractManagedTypeSnapshot> implements Isolatable { private final Managed.Factory factory; private final Class targetType; diff --git a/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/IsolatedMap.java b/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/IsolatedMap.java index cbb1b684608fe..7f742d145d0ec 100644 --- a/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/IsolatedMap.java +++ b/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/IsolatedMap.java @@ -25,7 +25,7 @@ import java.util.LinkedHashMap; import java.util.Map; -public class IsolatedMap extends AbstractMapSnapshot> implements Isolatable> { +class IsolatedMap extends AbstractMapSnapshot> implements Isolatable> { public IsolatedMap(ImmutableList, Isolatable>> entries) { super(entries); } diff --git a/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/IsolatedMapProperty.java b/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/IsolatedMapProperty.java new file mode 100644 index 0000000000000..d4038ca11eefa --- /dev/null +++ b/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/IsolatedMapProperty.java @@ -0,0 +1,43 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.internal.snapshot.impl; + +import org.gradle.api.internal.provider.DefaultMapProperty; +import org.gradle.api.provider.MapProperty; +import org.gradle.internal.isolation.Isolatable; + +import javax.annotation.Nullable; +import java.util.Map; + +class IsolatedMapProperty extends IsolatedProvider { + private final Class keyType; + private final Class valueType; + + public IsolatedMapProperty(Class keyType, Class valueType, Isolatable value) { + super(value); + this.keyType = keyType; + this.valueType = valueType; + } + + @Nullable + @Override + public MapProperty isolate() { + DefaultMapProperty property = new DefaultMapProperty<>((Class) keyType, (Class) valueType); + property.set((Map) value.isolate()); + return property; + } +} diff --git a/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/IsolatedProperty.java b/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/IsolatedProperty.java new file mode 100644 index 0000000000000..6f7362caf369d --- /dev/null +++ b/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/IsolatedProperty.java @@ -0,0 +1,40 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.internal.snapshot.impl; + +import org.gradle.api.internal.provider.DefaultPropertyState; +import org.gradle.api.provider.Property; +import org.gradle.internal.isolation.Isolatable; + +import javax.annotation.Nullable; + +class IsolatedProperty extends IsolatedProvider { + private final Class type; + + public IsolatedProperty(Class type, Isolatable value) { + super(value); + this.type = type; + } + + @Nullable + @Override + public Property isolate() { + DefaultPropertyState property = new DefaultPropertyState<>((Class) type); + property.set(value.isolate()); + return property; + } +} diff --git a/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/IsolatedProvider.java b/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/IsolatedProvider.java new file mode 100644 index 0000000000000..333599a046c61 --- /dev/null +++ b/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/IsolatedProvider.java @@ -0,0 +1,54 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.internal.snapshot.impl; + +import org.gradle.api.internal.provider.Providers; +import org.gradle.internal.hash.Hasher; +import org.gradle.internal.isolation.Isolatable; +import org.gradle.internal.snapshot.ValueSnapshot; + +import javax.annotation.Nullable; + +class IsolatedProvider implements Isolatable { + protected final Isolatable value; + + public IsolatedProvider(Isolatable value) { + this.value = value; + } + + @Override + public ValueSnapshot asSnapshot() { + return value.asSnapshot(); + } + + @Nullable + @Override + public S coerce(Class type) { + return null; + } + + @Nullable + @Override + public Object isolate() { + return Providers.of(value.isolate()); + } + + @Override + public void appendToHasher(Hasher hasher) { + value.appendToHasher(hasher); + } +} diff --git a/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/IsolatableSerializedValueSnapshot.java b/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/IsolatedSerializedValueSnapshot.java similarity index 87% rename from subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/IsolatableSerializedValueSnapshot.java rename to subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/IsolatedSerializedValueSnapshot.java index 0e672504abcc0..4b555fbaa9f2a 100644 --- a/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/IsolatableSerializedValueSnapshot.java +++ b/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/IsolatedSerializedValueSnapshot.java @@ -25,10 +25,10 @@ /** * Isolates a Serialized value and is a snapshot for that value. */ -public class IsolatableSerializedValueSnapshot extends SerializedValueSnapshot implements Isolatable { +class IsolatedSerializedValueSnapshot extends SerializedValueSnapshot implements Isolatable { private final Class originalClass; - public IsolatableSerializedValueSnapshot(HashCode implementationHash, byte[] serializedValue, Class originalClass) { + public IsolatedSerializedValueSnapshot(HashCode implementationHash, byte[] serializedValue, Class originalClass) { super(implementationHash, serializedValue); this.originalClass = originalClass; } diff --git a/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/IsolatedSet.java b/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/IsolatedSet.java index c38c62a6581d5..0ed458136329f 100644 --- a/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/IsolatedSet.java +++ b/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/IsolatedSet.java @@ -24,7 +24,7 @@ import java.util.LinkedHashSet; import java.util.Set; -public class IsolatedSet extends AbstractSetSnapshot> implements Isolatable> { +class IsolatedSet extends AbstractSetSnapshot> implements Isolatable> { public IsolatedSet(ImmutableSet> elements) { super(elements); } diff --git a/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/IsolatedSetProperty.java b/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/IsolatedSetProperty.java new file mode 100644 index 0000000000000..7950e212a75aa --- /dev/null +++ b/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/IsolatedSetProperty.java @@ -0,0 +1,41 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.internal.snapshot.impl; + +import org.gradle.api.internal.provider.DefaultSetProperty; +import org.gradle.api.provider.SetProperty; +import org.gradle.internal.isolation.Isolatable; + +import javax.annotation.Nullable; +import java.util.Set; + +class IsolatedSetProperty extends IsolatedProvider { + private final Class type; + + public IsolatedSetProperty(Class type, Isolatable value) { + super(value); + this.type = type; + } + + @Nullable + @Override + public SetProperty isolate() { + DefaultSetProperty property = new DefaultSetProperty<>((Class) type); + property.set((Set) value.isolate()); + return property; + } +} diff --git a/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/ListValueSnapshot.java b/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/ListValueSnapshot.java index effa869c16822..630e6b5b63e09 100644 --- a/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/ListValueSnapshot.java +++ b/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/ListValueSnapshot.java @@ -22,7 +22,7 @@ import java.util.List; -public class ListValueSnapshot extends AbstractListSnapshot implements ValueSnapshot { +class ListValueSnapshot extends AbstractListSnapshot implements ValueSnapshot { public static final ListValueSnapshot EMPTY = new ListValueSnapshot(ImmutableList.of()); public ListValueSnapshot(ImmutableList elements) { diff --git a/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/LongValueSnapshot.java b/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/LongValueSnapshot.java index 9d6d9868551f6..0922a3a65e6bd 100644 --- a/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/LongValueSnapshot.java +++ b/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/LongValueSnapshot.java @@ -18,7 +18,7 @@ import org.gradle.internal.hash.Hasher; -public class LongValueSnapshot extends AbstractIsolatableScalarValue { +class LongValueSnapshot extends AbstractIsolatableScalarValue { public LongValueSnapshot(Long value) { super(value); } diff --git a/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/ManagedTypeSnapshot.java b/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/ManagedTypeSnapshot.java index aeefa70cb7188..a403944f92aa5 100644 --- a/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/ManagedTypeSnapshot.java +++ b/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/ManagedTypeSnapshot.java @@ -19,7 +19,7 @@ import org.gradle.internal.snapshot.ValueSnapshot; import org.gradle.internal.snapshot.ValueSnapshotter; -public class ManagedTypeSnapshot extends AbstractManagedTypeSnapshot implements ValueSnapshot { +class ManagedTypeSnapshot extends AbstractManagedTypeSnapshot implements ValueSnapshot { private final String className; public ManagedTypeSnapshot(String className, ValueSnapshot state) { diff --git a/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/MapValueSnapshot.java b/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/MapValueSnapshot.java index 6a11e1a153d62..b4100be7a6869 100644 --- a/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/MapValueSnapshot.java +++ b/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/MapValueSnapshot.java @@ -21,7 +21,7 @@ import org.gradle.internal.snapshot.ValueSnapshot; import org.gradle.internal.snapshot.ValueSnapshotter; -public class MapValueSnapshot extends AbstractMapSnapshot implements ValueSnapshot { +class MapValueSnapshot extends AbstractMapSnapshot implements ValueSnapshot { public MapValueSnapshot(ImmutableList> entries) { super(entries); } diff --git a/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/NullValueSnapshot.java b/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/NullValueSnapshot.java index 2854e14bcef1b..f9ec48cf5d299 100644 --- a/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/NullValueSnapshot.java +++ b/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/NullValueSnapshot.java @@ -23,7 +23,7 @@ import javax.annotation.Nullable; -public class NullValueSnapshot implements ValueSnapshot, Isolatable { +class NullValueSnapshot implements ValueSnapshot, Isolatable { public static final NullValueSnapshot INSTANCE = new NullValueSnapshot(); private NullValueSnapshot() { diff --git a/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/ProviderSnapshot.java b/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/ProviderSnapshot.java deleted file mode 100644 index db5c91c73744f..0000000000000 --- a/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/ProviderSnapshot.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright 2017 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.gradle.internal.snapshot.impl; - -import org.gradle.internal.hash.Hasher; -import org.gradle.internal.snapshot.ValueSnapshot; -import org.gradle.internal.snapshot.ValueSnapshotter; - -public class ProviderSnapshot implements ValueSnapshot { - private final ValueSnapshot valueSnapshot; - - ProviderSnapshot(ValueSnapshot valueSnapshot) { - this.valueSnapshot = valueSnapshot; - } - - public ValueSnapshot getValue() { - return valueSnapshot; - } - - @Override - public boolean equals(Object obj) { - if (obj == this) { - return true; - } - if (obj == null || obj.getClass() != getClass()) { - return false; - } - ProviderSnapshot other = (ProviderSnapshot) obj; - return other.valueSnapshot.equals(valueSnapshot); - } - - @Override - public int hashCode() { - return valueSnapshot.hashCode(); - } - - @Override - public ValueSnapshot snapshot(Object value, ValueSnapshotter snapshotter) { - ValueSnapshot snapshot = snapshotter.snapshot(value); - if (equals(snapshot)) { - return this; - } - return snapshot; - } - - @Override - public void appendToHasher(Hasher hasher) { - valueSnapshot.appendToHasher(hasher); - } -} diff --git a/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/SerializedValueSnapshot.java b/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/SerializedValueSnapshot.java index f8a4ce1fa3493..dfaabb7ab368d 100644 --- a/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/SerializedValueSnapshot.java +++ b/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/SerializedValueSnapshot.java @@ -30,7 +30,7 @@ /** * An immutable snapshot of the state of some value. */ -public class SerializedValueSnapshot implements ValueSnapshot { +class SerializedValueSnapshot implements ValueSnapshot { private final HashCode implementationHash; private final byte[] serializedValue; diff --git a/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/SetValueSnapshot.java b/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/SetValueSnapshot.java index f5643cfae4c2c..77a72c8754a37 100644 --- a/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/SetValueSnapshot.java +++ b/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/SetValueSnapshot.java @@ -20,7 +20,7 @@ import org.gradle.internal.snapshot.ValueSnapshot; import org.gradle.internal.snapshot.ValueSnapshotter; -public class SetValueSnapshot extends AbstractSetSnapshot implements ValueSnapshot { +class SetValueSnapshot extends AbstractSetSnapshot implements ValueSnapshot { public SetValueSnapshot(ImmutableSet elements) { super(elements); } diff --git a/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/ShortValueSnapshot.java b/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/ShortValueSnapshot.java index 6c8da356cc04d..2f8908633127b 100644 --- a/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/ShortValueSnapshot.java +++ b/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/ShortValueSnapshot.java @@ -18,7 +18,7 @@ import org.gradle.internal.hash.Hasher; -public class ShortValueSnapshot extends AbstractIsolatableScalarValue { +class ShortValueSnapshot extends AbstractIsolatableScalarValue { public ShortValueSnapshot(Short value) { super(value); } diff --git a/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/SnapshotSerializer.java b/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/SnapshotSerializer.java index 0db590cf9862b..9f5eba51b605c 100644 --- a/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/SnapshotSerializer.java +++ b/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/SnapshotSerializer.java @@ -41,11 +41,10 @@ public class SnapshotSerializer extends AbstractSerializer { private static final int LIST_SNAPSHOT = 12; private static final int SET_SNAPSHOT = 13; private static final int MAP_SNAPSHOT = 14; - private static final int PROVIDER_SNAPSHOT = 15; - private static final int MANAGED_SNAPSHOT = 16; - private static final int IMMUTABLE_MANAGED_SNAPSHOT = 17; - private static final int IMPLEMENTATION_SNAPSHOT = 18; - private static final int DEFAULT_SNAPSHOT = 19; + private static final int MANAGED_SNAPSHOT = 15; + private static final int IMMUTABLE_MANAGED_SNAPSHOT = 16; + private static final int IMPLEMENTATION_SNAPSHOT = 17; + private static final int DEFAULT_SNAPSHOT = 18; private final HashCodeSerializer serializer = new HashCodeSerializer(); private final Serializer implementationSnapshotSerializer = new ImplementationSnapshot.SerializerImpl(); @@ -100,8 +99,6 @@ public ValueSnapshot read(Decoder decoder) throws Exception { mapBuilder.add(Pair.of(read(decoder), read(decoder))); } return new MapValueSnapshot(mapBuilder.build()); - case PROVIDER_SNAPSHOT: - return new ProviderSnapshot(read(decoder)); case MANAGED_SNAPSHOT: className = decoder.readString(); ValueSnapshot state = read(decoder); @@ -211,10 +208,6 @@ public void write(Encoder encoder, ValueSnapshot snapshot) throws Exception { write(encoder, valueSnapshot); } } - } else if (snapshot instanceof ProviderSnapshot) { - encoder.writeSmallInt(PROVIDER_SNAPSHOT); - ProviderSnapshot providerSnapshot = (ProviderSnapshot) snapshot; - write(encoder, providerSnapshot.getValue()); } else if (snapshot instanceof ImmutableManagedValueSnapshot) { encoder.writeSmallInt(IMMUTABLE_MANAGED_SNAPSHOT); ImmutableManagedValueSnapshot valueSnapshot = (ImmutableManagedValueSnapshot) snapshot; diff --git a/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/StringValueSnapshot.java b/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/StringValueSnapshot.java index 81150dac39b07..384824b980ca6 100644 --- a/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/StringValueSnapshot.java +++ b/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/StringValueSnapshot.java @@ -18,7 +18,7 @@ import org.gradle.internal.hash.Hasher; -public class StringValueSnapshot extends AbstractIsolatableScalarValue { +class StringValueSnapshot extends AbstractIsolatableScalarValue { public StringValueSnapshot(String value) { super(value); } diff --git a/subprojects/snapshots/src/test/groovy/org/gradle/internal/snapshot/impl/DefaultValueSnapshotterTest.groovy b/subprojects/snapshots/src/test/groovy/org/gradle/internal/snapshot/impl/DefaultValueSnapshotterTest.groovy index a7722f04238dc..127835159328e 100644 --- a/subprojects/snapshots/src/test/groovy/org/gradle/internal/snapshot/impl/DefaultValueSnapshotterTest.groovy +++ b/subprojects/snapshots/src/test/groovy/org/gradle/internal/snapshot/impl/DefaultValueSnapshotterTest.groovy @@ -19,6 +19,11 @@ package org.gradle.internal.snapshot.impl import org.gradle.api.Named import org.gradle.api.internal.file.TestFiles import org.gradle.api.internal.model.NamedObjectInstantiator +import org.gradle.api.internal.provider.DefaultListProperty +import org.gradle.api.internal.provider.DefaultMapProperty +import org.gradle.api.internal.provider.DefaultPropertyState +import org.gradle.api.internal.provider.DefaultSetProperty +import org.gradle.api.internal.provider.Providers import org.gradle.api.provider.Provider import org.gradle.internal.classloader.ClassLoaderHierarchyHasher import org.gradle.internal.classloader.ClasspathUtil @@ -33,7 +38,7 @@ class DefaultValueSnapshotterTest extends Specification { def classLoaderHasher = Stub(ClassLoaderHierarchyHasher) { getClassLoaderHash(_) >> HashCode.fromInt(123) } - def snapshotter = new DefaultValueSnapshotter(classLoaderHasher, NamedObjectInstantiator.INSTANCE) + def snapshotter = new DefaultValueSnapshotter(classLoaderHasher) def "creates snapshot for string"() { expect: @@ -215,6 +220,7 @@ class DefaultValueSnapshotterTest extends Specification { def "creates isolated null value"() { expect: snapshotter.isolate(null).isolate() == null + snapshotter.isolate(null).is(snapshotter.isolate(null)) } def "can coerce null value"() { @@ -251,15 +257,19 @@ class DefaultValueSnapshotterTest extends Specification { def "creates isolated array"() { expect: - def isolated1 = snapshotter.isolate([] as String[]) + def original1 = [] as String[] + def isolated1 = snapshotter.isolate(original1) isolated1 instanceof IsolatedArray - isolated1.isolate() == [] as String[] + def copy1 = isolated1.isolate() + copy1 == [] as String[] + !copy1.is(original1) - def original = ["123"] as String[] - def isolated2 = snapshotter.isolate(original) + def original2 = ["123"] as String[] + def isolated2 = snapshotter.isolate(original2) isolated2 instanceof IsolatedArray - isolated2.isolate() == ["123"] as String[] - !isolated2.isolate().is(original) + def copy2 = isolated2.isolate() + copy2 == ["123"] as String[] + !copy2.is(original2) } def "creates snapshot for isolated array"() { @@ -287,15 +297,19 @@ class DefaultValueSnapshotterTest extends Specification { def "creates isolated list"() { expect: - def isolated1 = snapshotter.isolate([]) + def original1 = [] + def isolated1 = snapshotter.isolate(original1) isolated1 instanceof IsolatedList - isolated1.isolate() == [] + def copy1 = isolated1.isolate() + copy1 == [] + !copy1.is(original1) - def original = ["123"] - def isolated2 = snapshotter.isolate(original) + def original2 = ["123"] + def isolated2 = snapshotter.isolate(original2) isolated2 instanceof IsolatedList - isolated2.isolate() == ["123"] - !isolated2.isolate().is(original) + def copy2 = isolated2.isolate() + copy2 == ["123"] + !copy2.is(original2) } def "creates snapshot for isolated list"() { @@ -335,15 +349,19 @@ class DefaultValueSnapshotterTest extends Specification { def "creates isolated set"() { expect: - def isolated1 = snapshotter.isolate([] as Set) + def original1 = [] as Set + def isolated1 = snapshotter.isolate(original1) isolated1 instanceof IsolatedSet - isolated1.isolate() == [] as Set + def copy1 = isolated1.isolate() + copy1 == [] as Set + !copy1.is(original1) - def original = ["123"] as Set - def isolated2 = snapshotter.isolate(original) + def original2 = ["123"] as Set + def isolated2 = snapshotter.isolate(original2) isolated2 instanceof IsolatedSet - isolated2.isolate() == ["123"] as Set - !isolated2.isolate().is(original) + def copy2 = isolated2.isolate() + copy2 == ["123"] as Set + !copy2.is(original2) } def "creates snapshot for isolated set"() { @@ -375,15 +393,19 @@ class DefaultValueSnapshotterTest extends Specification { def "creates isolated map"() { expect: - def isolated1 = snapshotter.isolate([:]) + def original1 = [:] + def isolated1 = snapshotter.isolate(original1) isolated1 instanceof IsolatedMap - isolated1.isolate() == [:] + def copy1 = isolated1.isolate() + copy1 == [:] + !copy1.is(original1) - def original = [a: "123"] - def isolated2 = snapshotter.isolate(original) + def original2 = [a: "123"] + def isolated2 = snapshotter.isolate(original2) isolated2 instanceof IsolatedMap - isolated2.isolate() == [a: "123"] - !isolated2.isolate().is(isolated2) + def copy2 = isolated2.isolate() + copy2 == [a: "123"] + !copy2.is(isolated2) } def "creates snapshot for isolated map"() { @@ -480,20 +502,87 @@ class DefaultValueSnapshotterTest extends Specification { def "creates snapshot for provider type"() { def value = Stub(Provider) - value.get() >> "123" + value.getOrNull() >> "123" def value2 = Stub(Provider) - value2.get() >> "123" + value2.getOrNull() >> "123" def value3 = Stub(Provider) - value3.get() >> "12" + value3.getOrNull() >> "12" expect: def snapshot = snapshotter.snapshot(value) - snapshot instanceof ProviderSnapshot + snapshot == snapshotter.snapshot("123") snapshot == snapshotter.snapshot(value) snapshot == snapshotter.snapshot(value2) snapshot != snapshotter.snapshot(value3) } + def "creates isolated provider"() { + def originalValue = "123" + def original = Providers.of(originalValue) + + expect: + def isolated = snapshotter.isolate(original) + isolated instanceof IsolatedProvider + def copy = isolated.isolate() + !copy.is(original) + copy.get().is(originalValue) + } + + def "creates isolated property"() { + def originalValue = "123" + def original = new DefaultPropertyState(String) + original.set(originalValue) + + expect: + def isolated = snapshotter.isolate(original) + isolated instanceof IsolatedProperty + def copy = isolated.isolate() + !copy.is(original) + copy.get().is(originalValue) + } + + def "creates isolated list property"() { + def originalValue = ["123"] + def original = new DefaultListProperty(String) + original.set(originalValue) + + expect: + def isolated = snapshotter.isolate(original) + isolated instanceof IsolatedListProperty + def copy = isolated.isolate() + !copy.is(original) + copy.get() == ["123"] + !copy.get().is(originalValue) + } + + def "creates isolated set property"() { + def originalValue = ["123"] + def original = new DefaultSetProperty(String) + original.set(originalValue) + + expect: + def isolated = snapshotter.isolate(original) + isolated instanceof IsolatedSetProperty + def copy = isolated.isolate() + !copy.is(original) + copy.get() == ["123"] as Set + !copy.get().is(originalValue) + } + + def "creates isolated map property"() { + def originalMap = [a: 1, b: 2] + def original = new DefaultMapProperty(String, Number) + original.set(originalMap) + + expect: + def isolated = snapshotter.isolate(original) + isolated instanceof IsolatedMapProperty + def copy = isolated.isolate() + !copy.is(original) + copy.get() == [a: 1, b: 2] + !copy.get().is(originalMap) + } + def "creates snapshot for named managed type"() { def instantiator = NamedObjectInstantiator.INSTANCE def value = instantiator.named(Thing, "value1") @@ -560,6 +649,7 @@ class DefaultValueSnapshotterTest extends Specification { interface BeanInterface { String getProp1() + void setProp1(String value) } @@ -585,14 +675,14 @@ class DefaultValueSnapshotterTest extends Specification { def "creates isolated managed interface"() { def instantiator = TestUtil.instantiatorFactory().inject() - def value = instantiator.newInstance(BeanInterface) - value.prop1 = "a" + def original = instantiator.newInstance(BeanInterface) + original.prop1 = "a" expect: - def isolated = snapshotter.isolate(value) + def isolated = snapshotter.isolate(original) isolated instanceof IsolatedManagedTypeSnapshot def copy = isolated.isolate() - !copy.is(value) + !copy.is(original) copy.prop1 == "a" } @@ -618,14 +708,14 @@ class DefaultValueSnapshotterTest extends Specification { def "creates isolated managed abstract class"() { def instantiator = TestUtil.instantiatorFactory().inject() - def value = instantiator.newInstance(AbstractBean) - value.prop1 = "a" + def original = instantiator.newInstance(AbstractBean) + original.prop1 = "a" expect: - def isolated = snapshotter.isolate(value) + def isolated = snapshotter.isolate(original) isolated instanceof IsolatedManagedTypeSnapshot def copy = isolated.isolate() - !copy.is(value) + !copy.is(original) copy.prop1 == "a" } @@ -660,7 +750,7 @@ class DefaultValueSnapshotterTest extends Specification { } def "creates isolated serializable type"() { - def value = new Bean(prop: "123") + def original = new Bean(prop: "123") def loader = new GroovyClassLoader(getClass().classLoader) loader.addURL(ClasspathUtil.getClasspathForClass(GroovyObject).toURI().toURL()) @@ -669,11 +759,11 @@ class DefaultValueSnapshotterTest extends Specification { assert cl.name == Bean.name expect: - def isolated = snapshotter.isolate(value) + def isolated = snapshotter.isolate(original) isolated instanceof SerializedValueSnapshot def other = isolated.isolate() other.prop == "123" - !other.is(value) + !other.is(original) def v = isolated.coerce(cl) v.prop == "123" @@ -918,17 +1008,17 @@ class DefaultValueSnapshotterTest extends Specification { def "creates snapshot for provider type from candidate"() { def value = Stub(Provider) - value.get() >> "123" + value.getOrNull() >> "123" def value2 = Stub(Provider) - value2.get() >> "123" + value2.getOrNull() >> "123" def value3 = Stub(Provider) - value3.get() >> "12" + value3.getOrNull() >> "12" expect: def snapshot = snapshotter.snapshot(value) + areTheSame(snapshot, "123") areTheSame(snapshot, value2) areNotTheSame(snapshot, value3) - areNotTheSame(snapshot, "123") } def "creates snapshot for named managed type from candidate"() { diff --git a/subprojects/snapshots/src/test/groovy/org/gradle/internal/snapshot/impl/SnapshotSerializerTest.groovy b/subprojects/snapshots/src/test/groovy/org/gradle/internal/snapshot/impl/SnapshotSerializerTest.groovy index d8c4ca54ffad3..87aa889569979 100644 --- a/subprojects/snapshots/src/test/groovy/org/gradle/internal/snapshot/impl/SnapshotSerializerTest.groovy +++ b/subprojects/snapshots/src/test/groovy/org/gradle/internal/snapshot/impl/SnapshotSerializerTest.groovy @@ -163,14 +163,6 @@ class SnapshotSerializerTest extends Specification { original == written } - def "serializes provider properties"() { - def original = new ProviderSnapshot(string("123")) - write(original) - - expect: - original == written - } - def "serializes managed type properties"() { def original = new ManagedTypeSnapshot("named", integer(123)) write(original) From 780b97da331c94fb8e33b627dba2c2e54629d790 Mon Sep 17 00:00:00 2001 From: Adam Murdoch Date: Thu, 21 Feb 2019 10:57:15 +1100 Subject: [PATCH 036/853] Allow `RegularFileProperty` and `DirectoryProperty` types to be used on artifact transform parameter objects, and take care of fingerprinting and building the files before running the transform. Reuse the mechanism that allows instances of generated classes to describe their state to the isolation infrastructure for other core Gradle types, such as `ConfigurableFileCollection`, `Provider` and `Property` and remove the custom isolation logic for these core types. --- .../org/gradle/api/attributes/Attribute.java | 2 +- .../file/DefaultFilePropertyFactory.java | 101 ++++++++++++++- ...ansformInputArtifactIntegrationTest.groovy | 7 +- ...nsformWithFileInputsIntegrationTest.groovy | 119 +++++++++++++++++- .../transform/DefaultTransformer.java | 2 +- .../DefaultConfigurableFileCollection.java | 33 ++++- .../model/NamedObjectInstantiator.java | 5 +- .../provider/AbstractMinimalProvider.java | 38 +++++- .../provider/DefaultListProperty.java | 22 ++++ .../internal/provider/DefaultMapProperty.java | 21 ++++ .../provider/DefaultPropertyState.java | 21 ++++ .../internal/provider/DefaultSetProperty.java | 22 ++++ .../api/internal/provider/Providers.java | 5 + .../AsmBackedClassGenerator.java | 1 + .../instantiation/ManagedTypeFactory.java | 4 + .../{instantiation => state}/Managed.java | 20 ++- .../model/NamedObjectInstantiatorTest.groovy | 2 +- .../api/internal/provider/PropertySpec.groovy | 27 ++++ .../api/internal/provider/ProviderSpec.groovy | 32 +++++ .../internal/provider/ProvidersTest.groovy | 5 + ...ackedClassGeneratedManagedStateTest.groovy | 1 + ...java => AbstractManagedValueSnapshot.java} | 6 +- .../impl/DefaultValueSnapshotter.java | 63 +--------- .../snapshot/impl/IsolatedFileCollection.java | 64 ---------- .../impl/IsolatedImmutableManagedValue.java | 7 +- .../snapshot/impl/IsolatedListProperty.java | 41 ------ ...napshot.java => IsolatedManagedValue.java} | 13 +- .../snapshot/impl/IsolatedMapProperty.java | 43 ------- .../snapshot/impl/IsolatedProperty.java | 40 ------ .../snapshot/impl/IsolatedProvider.java | 54 -------- .../snapshot/impl/IsolatedSetProperty.java | 41 ------ ...napshot.java => ManagedValueSnapshot.java} | 13 +- .../snapshot/impl/SnapshotSerializer.java | 6 +- .../impl/DefaultValueSnapshotterTest.groovy | 47 +++---- .../impl/SnapshotSerializerTest.groovy | 2 +- 35 files changed, 512 insertions(+), 418 deletions(-) rename subprojects/model-core/src/main/java/org/gradle/internal/{instantiation => state}/Managed.java (64%) rename subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/{AbstractManagedTypeSnapshot.java => AbstractManagedValueSnapshot.java} (86%) delete mode 100644 subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/IsolatedFileCollection.java delete mode 100644 subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/IsolatedListProperty.java rename subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/{IsolatedManagedTypeSnapshot.java => IsolatedManagedValue.java} (71%) delete mode 100644 subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/IsolatedMapProperty.java delete mode 100644 subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/IsolatedProperty.java delete mode 100644 subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/IsolatedProvider.java delete mode 100644 subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/IsolatedSetProperty.java rename subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/{ManagedTypeSnapshot.java => ManagedValueSnapshot.java} (75%) diff --git a/subprojects/core-api/src/main/java/org/gradle/api/attributes/Attribute.java b/subprojects/core-api/src/main/java/org/gradle/api/attributes/Attribute.java index 79d0ef67261ba..d84db6fbd3f49 100644 --- a/subprojects/core-api/src/main/java/org/gradle/api/attributes/Attribute.java +++ b/subprojects/core-api/src/main/java/org/gradle/api/attributes/Attribute.java @@ -49,7 +49,7 @@ public static Attribute of(String name, Class type) { } /** - * Creates a new attribute of the given type, inferring the name of the attribute from the simple type name. + * Creates a new attribute of the given type, inferring the name of the attribute from the simple type name. * This method is useful when there's supposedly only one attribute of a specific type in a container, so there's * no need to distinguish by name (but the returned type doesn't enforce it_. There's no guarantee that subsequent * calls to this method with the same attributes would either return the same instance or different instances diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/file/DefaultFilePropertyFactory.java b/subprojects/core/src/main/java/org/gradle/api/internal/file/DefaultFilePropertyFactory.java index b74c149708adc..4524855cbfda1 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/file/DefaultFilePropertyFactory.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/file/DefaultFilePropertyFactory.java @@ -30,6 +30,7 @@ import org.gradle.api.internal.tasks.TaskDependencyResolveContext; import org.gradle.api.provider.Provider; import org.gradle.internal.file.PathToFileResolver; +import org.gradle.internal.state.Managed; import java.io.File; @@ -50,7 +51,7 @@ public RegularFileProperty newFileProperty() { return new DefaultRegularFileVar(fileResolver); } - static class FixedDirectory implements Directory { + static class FixedDirectory implements Directory, Managed { private final File value; final FileResolver fileResolver; @@ -59,6 +60,34 @@ static class FixedDirectory implements Directory { this.fileResolver = fileResolver; } + @Override + public boolean immutable() { + return true; + } + + @Override + public Class publicType() { + return Directory.class; + } + + @Override + public Factory managedFactory() { + return new Factory() { + @Override + public T fromState(Class type, Object state) { + if (!type.isAssignableFrom(Directory.class)) { + return null; + } + return type.cast(new FixedDirectory((File) state, fileResolver)); + } + }; + } + + @Override + public Object unpackState() { + return value; + } + @Override public String toString() { return value.toString(); @@ -113,13 +142,41 @@ public Provider file(Provider path) { } } - static class FixedFile implements RegularFile { + static class FixedFile implements RegularFile, Managed { private final File file; FixedFile(File file) { this.file = file; } + @Override + public boolean immutable() { + return true; + } + + @Override + public Class publicType() { + return RegularFile.class; + } + + @Override + public Factory managedFactory() { + return new Factory() { + @Override + public T fromState(Class type, Object state) { + if (!type.isAssignableFrom(RegularFile.class)) { + return null; + } + return type.cast(new FixedFile((File) state)); + } + }; + } + + @Override + public Object unpackState() { + return file; + } + @Override public String toString() { return file.toString(); @@ -200,7 +257,7 @@ public void setFromAnyValue(Object object) { public abstract void set(File file); } - static class DefaultRegularFileVar extends AbstractFileVar implements RegularFileProperty { + static class DefaultRegularFileVar extends AbstractFileVar implements RegularFileProperty, Managed { private final PathToFileResolver fileResolver; DefaultRegularFileVar(PathToFileResolver fileResolver) { @@ -208,6 +265,24 @@ static class DefaultRegularFileVar extends AbstractFileVar implemen this.fileResolver = fileResolver; } + @Override + public Class publicType() { + return RegularFileProperty.class; + } + + @Override + public Factory managedFactory() { + return new Factory() { + @Override + public T fromState(Class type, Object state) { + if (!type.isAssignableFrom(RegularFileProperty.class)) { + return null; + } + return type.cast(new DefaultRegularFileVar(fileResolver).value((RegularFile) state)); + } + }; + } + @Override public Provider getAsFile() { return new ToFileProvider(this); @@ -252,7 +327,7 @@ protected Directory map(CharSequence path) { } } - static class DefaultDirectoryVar extends AbstractFileVar implements DirectoryProperty { + static class DefaultDirectoryVar extends AbstractFileVar implements DirectoryProperty, Managed { private final FileResolver resolver; DefaultDirectoryVar(FileResolver resolver) { @@ -266,6 +341,24 @@ static class DefaultDirectoryVar extends AbstractFileVar implements D resolveAndSet(value); } + @Override + public Class publicType() { + return DirectoryProperty.class; + } + + @Override + public Factory managedFactory() { + return new Factory() { + @Override + public T fromState(Class type, Object state) { + if (!type.isAssignableFrom(DirectoryProperty.class)) { + return null; + } + return type.cast(new DefaultDirectoryVar(resolver).value((Directory) state)); + } + }; + } + @Override public FileTree getAsFileTree() { return resolver.resolveFilesAsTree(this); diff --git a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformInputArtifactIntegrationTest.groovy b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformInputArtifactIntegrationTest.groovy index a7543ffb6d8d3..b708b0a831033 100644 --- a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformInputArtifactIntegrationTest.groovy +++ b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformInputArtifactIntegrationTest.groovy @@ -44,6 +44,7 @@ class ArtifactTransformInputArtifactIntegrationTest extends AbstractDependencyRe void transform(TransformOutputs outputs) { println "processing \${input.name}" + assert input.file } } """ @@ -192,7 +193,7 @@ class ArtifactTransformInputArtifactIntegrationTest extends AbstractDependencyRe println "processing missing \${input.name}" } def output = outputs.file(input.name + ".green") - output.text = "green" + output.text = input.list().length + ".green" } } """ @@ -449,7 +450,7 @@ class ArtifactTransformInputArtifactIntegrationTest extends AbstractDependencyRe void transform(TransformOutputs outputs) { println "processing \${input.name}" def output = outputs.file(input.name + ".green") - output.text = "green" + output.text = input.list().length + ".green" } } """ @@ -621,7 +622,7 @@ class ArtifactTransformInputArtifactIntegrationTest extends AbstractDependencyRe void transform(TransformOutputs outputs) { println "processing \${input.name}" def output = outputs.file(input.name + ".green") - output.text = "green" + output.text = input.list().length + ".green" } } """ diff --git a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformWithFileInputsIntegrationTest.groovy b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformWithFileInputsIntegrationTest.groovy index 3b2ecdc63ee10..83ed25ab7334e 100644 --- a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformWithFileInputsIntegrationTest.groovy +++ b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformWithFileInputsIntegrationTest.groovy @@ -18,7 +18,6 @@ package org.gradle.integtests.resolve.transform import org.gradle.api.tasks.PathSensitivity import org.gradle.integtests.fixtures.AbstractDependencyResolutionTest -import org.gradle.util.ToBeImplemented import spock.lang.Unroll class ArtifactTransformWithFileInputsIntegrationTest extends AbstractDependencyResolutionTest implements ArtifactTransformTestFixture { @@ -47,13 +46,14 @@ class ArtifactTransformWithFileInputsIntegrationTest extends AbstractDependencyR void transform(TransformOutputs outputs) { println "processing \${input.name} using \${parameters.someFiles*.name}" def output = outputs.file(input.name + ".green") - output.text = "ok" + def paramContent = parameters.someFiles.collect { it.file ? it.text : it.list().length }.join("") + output.text = input.text + paramContent + ".green" } } """ } - def "transform can receive pre-built file collection via parameter object"() { + def "transform can receive a file collection containing pre-built files via parameter object"() { settingsFile << """ include 'a', 'b', 'c' """ @@ -70,6 +70,8 @@ class ArtifactTransformWithFileInputsIntegrationTest extends AbstractDependencyR } } """ + file('a/a.txt').text = '123' + file('a/b.txt').text = 'abc' when: run(":a:resolve") @@ -257,6 +259,114 @@ class ArtifactTransformWithFileInputsIntegrationTest extends AbstractDependencyR outputContains("result = [b.jar.green, c.jar.green]") } + def "transform can receive a task output file as parameter"() { + settingsFile << """ + include 'a', 'b', 'c', 'd', 'e' + """ + buildFile << """ + allprojects { + task tool(type: FileProducer) { + output = file("build/tool-\${project.name}.jar") + } + ext.inputFile = tool.output + } + """ + setupBuildWithColorTransform { + params(""" + someFile.set(project.inputFile) + """) + } + buildFile << """ + project(':a') { + dependencies { + implementation project(':b') + implementation project(':c') + } + } + + @AssociatedTransformAction(MakeGreenAction) + interface MakeGreen { + @InputFile + RegularFileProperty getSomeFile() + } + + abstract class MakeGreenAction implements TransformAction { + @TransformParameters + abstract MakeGreen getParameters() + @InputArtifact + abstract File getInput() + + void transform(TransformOutputs outputs) { + println "processing \${input.name} using \${parameters.someFile.get().asFile.name}" + def output = outputs.file(input.name + ".green") + output.text = input.text + parameters.someFile.get().asFile.text + ".green" + } + } + """ + + when: + run(":a:resolve") + + then: + result.assertTasksExecuted(":a:tool", ":b:producer", ":c:producer", ":a:resolve") + outputContains("processing b.jar using tool-a.jar") + outputContains("processing c.jar using tool-a.jar") + } + + def "transform can receive a task output directory as parameter"() { + settingsFile << """ + include 'a', 'b', 'c', 'd', 'e' + """ + buildFile << """ + allprojects { + task tool(type: DirProducer) { + output = file("build/tool-\${project.name}-dir") + } + ext.inputDir = tool.output + } + """ + setupBuildWithColorTransform { + params(""" + someDir.set(project.inputDir) + """) + } + buildFile << """ + project(':a') { + dependencies { + implementation project(':b') + implementation project(':c') + } + } + + @AssociatedTransformAction(MakeGreenAction) + interface MakeGreen { + @InputDirectory + DirectoryProperty getSomeDir() + } + + abstract class MakeGreenAction implements TransformAction { + @TransformParameters + abstract MakeGreen getParameters() + @InputArtifact + abstract File getInput() + + void transform(TransformOutputs outputs) { + println "processing \${input.name} using \${parameters.someDir.get().asFile.name}" + def output = outputs.file(input.name + ".green") + output.text = input.text + parameters.someDir.get().asFile.list().length + ".green" + } + } + """ + + when: + run(":a:resolve") + + then: + result.assertTasksExecuted(":a:tool", ":b:producer", ":c:producer", ":a:resolve") + outputContains("processing b.jar using tool-a-dir") + outputContains("processing c.jar using tool-a-dir") + } + def "transform does not execute when file inputs cannot be built"() { settingsFile << """ include 'a', 'b', 'c' @@ -346,7 +456,6 @@ class ArtifactTransformWithFileInputsIntegrationTest extends AbstractDependencyR PathSensitivity.ABSOLUTE | [['first/input', 'foo'], ['first/input', 'foo'], ['third/input', 'foo']] } - @ToBeImplemented def "can use classpath normalization for parameter object"() { settingsFile << """ include 'a', 'b', 'c' @@ -392,8 +501,6 @@ class ArtifactTransformWithFileInputsIntegrationTest extends AbstractDependencyR jarSources.zipTo(inputJar) run(":a:resolve") then: - // TODO: Should not report changes - // outputDoesNotContain("Transform artifact") outputContains("processing b.jar using [${inputDir.name}, ${inputJar.name}]") outputContains("processing c.jar using [${inputDir.name}, ${inputJar.name}]") diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformer.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformer.java index 6dfc968458f75..ebbc4b724a058 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformer.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformer.java @@ -53,7 +53,7 @@ import org.gradle.internal.hash.Hashing; import org.gradle.internal.instantiation.InstanceFactory; import org.gradle.internal.instantiation.InstantiationScheme; -import org.gradle.internal.instantiation.Managed; +import org.gradle.internal.state.Managed; import org.gradle.internal.isolation.Isolatable; import org.gradle.internal.isolation.IsolatableFactory; import org.gradle.internal.reflect.ParameterValidationContext; diff --git a/subprojects/files/src/main/java/org/gradle/api/internal/file/collections/DefaultConfigurableFileCollection.java b/subprojects/files/src/main/java/org/gradle/api/internal/file/collections/DefaultConfigurableFileCollection.java index b36d1da9afee8..1fad1f89c6608 100644 --- a/subprojects/files/src/main/java/org/gradle/api/internal/file/collections/DefaultConfigurableFileCollection.java +++ b/subprojects/files/src/main/java/org/gradle/api/internal/file/collections/DefaultConfigurableFileCollection.java @@ -22,9 +22,11 @@ import org.gradle.api.internal.tasks.TaskDependencyResolveContext; import org.gradle.api.internal.tasks.TaskResolver; import org.gradle.internal.file.PathToFileResolver; +import org.gradle.internal.state.Managed; import org.gradle.util.GUtil; import javax.annotation.Nullable; +import java.io.File; import java.util.Arrays; import java.util.Collection; import java.util.LinkedHashSet; @@ -33,7 +35,7 @@ /** * A {@link org.gradle.api.file.FileCollection} which resolves a set of paths relative to a {@link org.gradle.api.internal.file.FileResolver}. */ -public class DefaultConfigurableFileCollection extends CompositeFileCollection implements ConfigurableFileCollection { +public class DefaultConfigurableFileCollection extends CompositeFileCollection implements ConfigurableFileCollection, Managed { private final Set files; private final String displayName; private final PathToFileResolver resolver; @@ -65,6 +67,35 @@ public DefaultConfigurableFileCollection(String displayName, PathToFileResolver buildDependency = new DefaultTaskDependency(taskResolver); } + @Override + public boolean immutable() { + return false; + } + + @Override + public Class publicType() { + return ConfigurableFileCollection.class; + } + + @Override + public Object unpackState() { + return getFiles(); + } + + @Override + public Factory managedFactory() { + return new Factory() { + @Nullable + @Override + public T fromState(Class type, Object state) { + if (!type.isAssignableFrom(ConfigurableFileCollection.class)) { + return null; + } + return type.cast(new DefaultConfigurableFileCollection(resolver, null, (Set) state)); + } + }; + } + @Override public String getDisplayName() { return displayName; diff --git a/subprojects/model-core/src/main/java/org/gradle/api/internal/model/NamedObjectInstantiator.java b/subprojects/model-core/src/main/java/org/gradle/api/internal/model/NamedObjectInstantiator.java index 4ce1da39faf5a..86200508119ec 100644 --- a/subprojects/model-core/src/main/java/org/gradle/api/internal/model/NamedObjectInstantiator.java +++ b/subprojects/model-core/src/main/java/org/gradle/api/internal/model/NamedObjectInstantiator.java @@ -28,7 +28,7 @@ import org.gradle.internal.Factory; import org.gradle.internal.UncheckedException; import org.gradle.internal.classloader.VisitableURLClassLoader; -import org.gradle.internal.instantiation.Managed; +import org.gradle.internal.state.Managed; import org.gradle.model.internal.asm.AsmClassGenerator; import org.gradle.model.internal.inspect.FormattingValidationProblemCollector; import org.gradle.model.internal.inspect.ValidationProblemCollector; @@ -106,6 +106,9 @@ public T named(final Class type, final String name) throws @Override public T fromState(Class type, Object state) { + if (!Named.class.isAssignableFrom(type)) { + return null; + } return named(Cast.uncheckedCast(type), (String) state); } diff --git a/subprojects/model-core/src/main/java/org/gradle/api/internal/provider/AbstractMinimalProvider.java b/subprojects/model-core/src/main/java/org/gradle/api/internal/provider/AbstractMinimalProvider.java index 1eca309373ce7..68996efd79dbb 100644 --- a/subprojects/model-core/src/main/java/org/gradle/api/internal/provider/AbstractMinimalProvider.java +++ b/subprojects/model-core/src/main/java/org/gradle/api/internal/provider/AbstractMinimalProvider.java @@ -19,12 +19,28 @@ import org.gradle.api.Transformer; import org.gradle.api.internal.tasks.TaskDependencyResolveContext; import org.gradle.api.provider.Provider; +import org.gradle.internal.state.Managed; import org.gradle.util.GUtil; import javax.annotation.Nullable; import java.util.Collection; -public abstract class AbstractMinimalProvider implements ProviderInternal { +public abstract class AbstractMinimalProvider implements ProviderInternal, Managed { + private static final Factory FACTORY = new Factory() { + @Nullable + @Override + public T fromState(Class type, Object state) { + if (!type.isAssignableFrom(Provider.class)) { + return null; + } + if (state == null) { + return type.cast(Providers.notDefined()); + } else { + return type.cast(Providers.of(state)); + } + } + }; + @Override public ProviderInternal map(final Transformer transformer) { return new TransformBackedProvider(transformer, this); @@ -85,6 +101,26 @@ public String toString() { return String.format("provider(%s)", GUtil.elvis(getType(), "?")); } + @Override + public boolean immutable() { + return false; + } + + @Override + public Class publicType() { + return Provider.class; + } + + @Override + public Factory managedFactory() { + return FACTORY; + } + + @Override + public Object unpackState() { + return getOrNull(); + } + private static class FlatMapProvider extends AbstractMinimalProvider { private final Provider provider; private final Transformer, ? super T> transformer; diff --git a/subprojects/model-core/src/main/java/org/gradle/api/internal/provider/DefaultListProperty.java b/subprojects/model-core/src/main/java/org/gradle/api/internal/provider/DefaultListProperty.java index 3015b8b2127fb..483777e0bc098 100644 --- a/subprojects/model-core/src/main/java/org/gradle/api/internal/provider/DefaultListProperty.java +++ b/subprojects/model-core/src/main/java/org/gradle/api/internal/provider/DefaultListProperty.java @@ -20,6 +20,7 @@ import org.gradle.api.provider.ListProperty; import org.gradle.api.provider.Provider; +import javax.annotation.Nullable; import java.util.Collection; import java.util.List; @@ -28,6 +29,27 @@ public DefaultListProperty(Class elementType) { super(List.class, elementType); } + @Override + public Class publicType() { + return ListProperty.class; + } + + @Override + public Factory managedFactory() { + return new Factory() { + @Nullable + @Override + public S fromState(Class type, Object state) { + if (!type.isAssignableFrom(ListProperty.class)) { + return null; + } + DefaultListProperty property = new DefaultListProperty<>(DefaultListProperty.this.getElementType()); + property.set((List) state); + return type.cast(property); + } + }; + } + @Override protected List fromValue(Collection values) { return ImmutableList.copyOf(values); diff --git a/subprojects/model-core/src/main/java/org/gradle/api/internal/provider/DefaultMapProperty.java b/subprojects/model-core/src/main/java/org/gradle/api/internal/provider/DefaultMapProperty.java index 732b51cc28e31..3178fc3daa9c4 100644 --- a/subprojects/model-core/src/main/java/org/gradle/api/internal/provider/DefaultMapProperty.java +++ b/subprojects/model-core/src/main/java/org/gradle/api/internal/provider/DefaultMapProperty.java @@ -72,6 +72,27 @@ public Class getValueType() { return valueType; } + @Override + public Class publicType() { + return MapProperty.class; + } + + @Override + public Factory managedFactory() { + return new Factory() { + @Nullable + @Override + public S fromState(Class type, Object state) { + if (!type.isAssignableFrom(MapProperty.class)) { + return null; + } + DefaultMapProperty property = new DefaultMapProperty<>(DefaultMapProperty.this.keyType, DefaultMapProperty.this.valueType); + property.set((Map) state); + return type.cast(property); + } + }; + } + @Override public boolean isPresent() { beforeRead(); diff --git a/subprojects/model-core/src/main/java/org/gradle/api/internal/provider/DefaultPropertyState.java b/subprojects/model-core/src/main/java/org/gradle/api/internal/provider/DefaultPropertyState.java index 855f31e1988e6..902228d3074e0 100644 --- a/subprojects/model-core/src/main/java/org/gradle/api/internal/provider/DefaultPropertyState.java +++ b/subprojects/model-core/src/main/java/org/gradle/api/internal/provider/DefaultPropertyState.java @@ -20,6 +20,8 @@ import org.gradle.api.provider.Property; import org.gradle.api.provider.Provider; +import javax.annotation.Nullable; + public class DefaultPropertyState extends AbstractProperty implements Property { private final Class type; private final ValueSanitizer sanitizer; @@ -31,6 +33,25 @@ public DefaultPropertyState(Class type) { this.sanitizer = ValueSanitizers.forType(type); } + @Override + public Class publicType() { + return Property.class; + } + + @Override + public Factory managedFactory() { + return new Factory() { + @Nullable + @Override + public S fromState(Class type, Object state) { + if (!type.isAssignableFrom(Property.class)) { + return null; + } + return type.cast(new DefaultPropertyState(DefaultPropertyState.this.type).value((T) state)); + } + }; + } + @Override public Class getType() { return type; diff --git a/subprojects/model-core/src/main/java/org/gradle/api/internal/provider/DefaultSetProperty.java b/subprojects/model-core/src/main/java/org/gradle/api/internal/provider/DefaultSetProperty.java index 9ff99e4b1e572..b7d5ca7ffe5b9 100644 --- a/subprojects/model-core/src/main/java/org/gradle/api/internal/provider/DefaultSetProperty.java +++ b/subprojects/model-core/src/main/java/org/gradle/api/internal/provider/DefaultSetProperty.java @@ -20,6 +20,7 @@ import org.gradle.api.provider.Provider; import org.gradle.api.provider.SetProperty; +import javax.annotation.Nullable; import java.util.Collection; import java.util.Set; @@ -33,6 +34,27 @@ protected Set fromValue(Collection values) { return ImmutableSet.copyOf(values); } + @Override + public Class publicType() { + return SetProperty.class; + } + + @Override + public Factory managedFactory() { + return new Factory() { + @Nullable + @Override + public S fromState(Class type, Object state) { + if (!type.isAssignableFrom(SetProperty.class)) { + return null; + } + DefaultSetProperty property = new DefaultSetProperty<>(DefaultSetProperty.this.getElementType()); + property.set((Set) state); + return type.cast(property); + } + }; + } + @Override public SetProperty empty() { super.empty(); diff --git a/subprojects/model-core/src/main/java/org/gradle/api/internal/provider/Providers.java b/subprojects/model-core/src/main/java/org/gradle/api/internal/provider/Providers.java index 62a36b4d91add..4d72200809d7d 100644 --- a/subprojects/model-core/src/main/java/org/gradle/api/internal/provider/Providers.java +++ b/subprojects/model-core/src/main/java/org/gradle/api/internal/provider/Providers.java @@ -32,6 +32,11 @@ public Object get() { throw new IllegalStateException(NULL_VALUE); } + @Override + public boolean immutable() { + return true; + } + @Nullable @Override public Class getType() { diff --git a/subprojects/model-core/src/main/java/org/gradle/internal/instantiation/AsmBackedClassGenerator.java b/subprojects/model-core/src/main/java/org/gradle/internal/instantiation/AsmBackedClassGenerator.java index 37c839b422bcc..76c8388a25831 100644 --- a/subprojects/model-core/src/main/java/org/gradle/internal/instantiation/AsmBackedClassGenerator.java +++ b/subprojects/model-core/src/main/java/org/gradle/internal/instantiation/AsmBackedClassGenerator.java @@ -52,6 +52,7 @@ import org.gradle.internal.reflect.JavaReflectionUtil; import org.gradle.internal.service.ServiceLookup; import org.gradle.internal.service.ServiceRegistry; +import org.gradle.internal.state.Managed; import org.gradle.model.internal.asm.AsmClassGenerator; import org.gradle.util.CollectionUtils; import org.gradle.util.ConfigureUtil; diff --git a/subprojects/model-core/src/main/java/org/gradle/internal/instantiation/ManagedTypeFactory.java b/subprojects/model-core/src/main/java/org/gradle/internal/instantiation/ManagedTypeFactory.java index eb7880afe75bb..2ee0789dbc753 100644 --- a/subprojects/model-core/src/main/java/org/gradle/internal/instantiation/ManagedTypeFactory.java +++ b/subprojects/model-core/src/main/java/org/gradle/internal/instantiation/ManagedTypeFactory.java @@ -17,6 +17,7 @@ package org.gradle.internal.instantiation; import org.gradle.api.reflect.ObjectInstantiationException; +import org.gradle.internal.state.Managed; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; @@ -31,6 +32,9 @@ public ManagedTypeFactory(Class type) throws NoSuchMethodException { @Override public T fromState(Class type, Object state) { + if (!type.isAssignableFrom(constructor.getDeclaringClass())) { + return null; + } try { return type.cast(constructor.newInstance(state)); } catch (InvocationTargetException e) { diff --git a/subprojects/model-core/src/main/java/org/gradle/internal/instantiation/Managed.java b/subprojects/model-core/src/main/java/org/gradle/internal/state/Managed.java similarity index 64% rename from subprojects/model-core/src/main/java/org/gradle/internal/instantiation/Managed.java rename to subprojects/model-core/src/main/java/org/gradle/internal/state/Managed.java index 8ed6dd373241c..20357989c3efa 100644 --- a/subprojects/model-core/src/main/java/org/gradle/internal/instantiation/Managed.java +++ b/subprojects/model-core/src/main/java/org/gradle/internal/state/Managed.java @@ -14,15 +14,19 @@ * limitations under the License. */ -package org.gradle.internal.instantiation; +package org.gradle.internal.state; + +import javax.annotation.Nullable; /** - * Mixed into generated classes whose state is fully managed. + * Implemented by types whose state is fully managed by Gradle. Mixed into generated classes whose state is fully managed. */ public interface Managed { /** * Returns a snapshot of the current state of this object. This can be passed to the {@link Factory#fromState(Class, Object)} method to recreate this object from the snapshot. * Note that the state may not be immutable, so should be made isolated to reuse in another context. The state can also be fingerprinted to generate a fingerprint of this object. + * + *

    Note that currently the state should reference only JVM and core Gradle types when {@link #immutable()} returns true.

    */ Object unpackState(); @@ -31,11 +35,23 @@ public interface Managed { */ boolean immutable(); + /** + * Returns the public type of this managed instance. Currently is used to identify the implementation. + */ Class publicType(); + /** + * Returns the factory that can be used to create new instances of this type. + */ Factory managedFactory(); interface Factory { + /** + * Creates an instance of the given type from the given state, if possible. + * + * @return null when the given type is not supported. + */ + @Nullable T fromState(Class type, Object state); } } diff --git a/subprojects/model-core/src/test/groovy/org/gradle/api/internal/model/NamedObjectInstantiatorTest.groovy b/subprojects/model-core/src/test/groovy/org/gradle/api/internal/model/NamedObjectInstantiatorTest.groovy index 82467e445f8a6..0f088b36d4934 100644 --- a/subprojects/model-core/src/test/groovy/org/gradle/api/internal/model/NamedObjectInstantiatorTest.groovy +++ b/subprojects/model-core/src/test/groovy/org/gradle/api/internal/model/NamedObjectInstantiatorTest.groovy @@ -18,7 +18,7 @@ package org.gradle.api.internal.model import org.gradle.api.Named import org.gradle.api.reflect.ObjectInstantiationException -import org.gradle.internal.instantiation.Managed +import org.gradle.internal.state.Managed import org.gradle.test.fixtures.concurrent.ConcurrentSpec import org.gradle.util.Matchers import spock.lang.Ignore diff --git a/subprojects/model-core/src/test/groovy/org/gradle/api/internal/provider/PropertySpec.groovy b/subprojects/model-core/src/test/groovy/org/gradle/api/internal/provider/PropertySpec.groovy index 09bf45379f00d..4f56b81a073cb 100644 --- a/subprojects/model-core/src/test/groovy/org/gradle/api/internal/provider/PropertySpec.groovy +++ b/subprojects/model-core/src/test/groovy/org/gradle/api/internal/provider/PropertySpec.groovy @@ -18,6 +18,7 @@ package org.gradle.api.internal.provider import org.gradle.api.Transformer import org.gradle.api.provider.Provider +import org.gradle.internal.state.Managed import java.util.concurrent.Callable @@ -823,5 +824,31 @@ abstract class PropertySpec extends ProviderSpec { property.get() == someValue() } + def "can unpack state and recreate instance"() { + given: + def property = propertyWithNoValue() + + expect: + property instanceof Managed + !property.immutable() + def state = property.unpackState() + def copy = property.managedFactory().fromState(property.publicType(), state) + !copy.is(property) + !copy.present + copy.getOrNull() == null + + property.set(someValue()) + copy.getOrNull() == null + + def state2 = property.unpackState() + def copy2 = property.managedFactory().fromState(property.publicType(), state2) + !copy2.is(property) + copy2.get() == someValue() + + property.set(someOtherValue()) + copy.getOrNull() == null + copy2.get() == someValue() + } + static class Thing {} } diff --git a/subprojects/model-core/src/test/groovy/org/gradle/api/internal/provider/ProviderSpec.groovy b/subprojects/model-core/src/test/groovy/org/gradle/api/internal/provider/ProviderSpec.groovy index 70c4a4281ac16..187a77732e29b 100644 --- a/subprojects/model-core/src/test/groovy/org/gradle/api/internal/provider/ProviderSpec.groovy +++ b/subprojects/model-core/src/test/groovy/org/gradle/api/internal/provider/ProviderSpec.groovy @@ -18,6 +18,7 @@ package org.gradle.api.internal.provider import org.gradle.api.Transformer import org.gradle.api.provider.Provider +import org.gradle.internal.state.Managed import spock.lang.Specification abstract class ProviderSpec extends Specification { @@ -29,6 +30,10 @@ abstract class ProviderSpec extends Specification { abstract T someOtherValue() + boolean isNoValueProviderImmutable() { + return false + } + def "can query value when it has as value"() { given: def provider = providerWithValue(someValue()) @@ -204,4 +209,31 @@ abstract class ProviderSpec extends Specification { t.message == "No value has been specified for this provider." } + def "can unpack state and recreate instance when provider has no value"() { + given: + def provider = providerWithNoValue() + + expect: + provider instanceof Managed + provider.immutable() == noValueProviderImmutable + def state = provider.unpackState() + def copy = provider.managedFactory().fromState(provider.publicType(), state) + !copy.is(provider) || noValueProviderImmutable + !copy.present + copy.getOrNull() == null + } + + def "can unpack state and recreate instance when provider has value"() { + given: + def provider = providerWithValue(someValue()) + + expect: + provider instanceof Managed + !provider.immutable() + def state = provider.unpackState() + def copy = provider.managedFactory().fromState(provider.publicType(), state) + !copy.is(provider) + copy.present + copy.getOrNull() == someValue() + } } diff --git a/subprojects/model-core/src/test/groovy/org/gradle/api/internal/provider/ProvidersTest.groovy b/subprojects/model-core/src/test/groovy/org/gradle/api/internal/provider/ProvidersTest.groovy index 6a963e7d0901b..370991aa7d18c 100644 --- a/subprojects/model-core/src/test/groovy/org/gradle/api/internal/provider/ProvidersTest.groovy +++ b/subprojects/model-core/src/test/groovy/org/gradle/api/internal/provider/ProvidersTest.groovy @@ -40,6 +40,11 @@ class ProvidersTest extends ProviderSpec { return 123 } + @Override + boolean isNoValueProviderImmutable() { + return true + } + def "mapped fixed value provider calculates transformed value lazily and caches the result"() { given: def transform = Mock(Transformer) diff --git a/subprojects/model-core/src/test/groovy/org/gradle/internal/instantiation/AsmBackedClassGeneratedManagedStateTest.groovy b/subprojects/model-core/src/test/groovy/org/gradle/internal/instantiation/AsmBackedClassGeneratedManagedStateTest.groovy index f494184e53651..f4230f24d8d6e 100644 --- a/subprojects/model-core/src/test/groovy/org/gradle/internal/instantiation/AsmBackedClassGeneratedManagedStateTest.groovy +++ b/subprojects/model-core/src/test/groovy/org/gradle/internal/instantiation/AsmBackedClassGeneratedManagedStateTest.groovy @@ -16,6 +16,7 @@ package org.gradle.internal.instantiation +import org.gradle.internal.state.Managed import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider import org.gradle.util.TestUtil import org.junit.ClassRule diff --git a/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/AbstractManagedTypeSnapshot.java b/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/AbstractManagedValueSnapshot.java similarity index 86% rename from subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/AbstractManagedTypeSnapshot.java rename to subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/AbstractManagedValueSnapshot.java index 71a295deb3ade..5cd32881c6018 100644 --- a/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/AbstractManagedTypeSnapshot.java +++ b/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/AbstractManagedValueSnapshot.java @@ -19,10 +19,10 @@ import org.gradle.internal.hash.Hashable; import org.gradle.internal.hash.Hasher; -class AbstractManagedTypeSnapshot implements Hashable { +class AbstractManagedValueSnapshot implements Hashable { protected final T state; - public AbstractManagedTypeSnapshot(T state) { + public AbstractManagedValueSnapshot(T state) { this.state = state; } @@ -38,7 +38,7 @@ public boolean equals(Object obj) { if (obj == null || obj.getClass() != getClass()) { return false; } - AbstractManagedTypeSnapshot other = (AbstractManagedTypeSnapshot) obj; + AbstractManagedValueSnapshot other = (AbstractManagedValueSnapshot) obj; return state.equals(other.state); } diff --git a/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/DefaultValueSnapshotter.java b/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/DefaultValueSnapshotter.java index be7103efc252e..191dd907640f3 100644 --- a/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/DefaultValueSnapshotter.java +++ b/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/DefaultValueSnapshotter.java @@ -20,19 +20,10 @@ import com.google.common.collect.ImmutableSet; import org.gradle.api.UncheckedIOException; import org.gradle.api.attributes.Attribute; -import org.gradle.api.file.ConfigurableFileCollection; -import org.gradle.api.internal.provider.CollectionPropertyInternal; -import org.gradle.api.internal.provider.DefaultMapProperty; -import org.gradle.api.internal.provider.ProviderInternal; -import org.gradle.api.provider.ListProperty; -import org.gradle.api.provider.MapProperty; -import org.gradle.api.provider.Property; -import org.gradle.api.provider.Provider; -import org.gradle.api.provider.SetProperty; import org.gradle.internal.Cast; import org.gradle.internal.Pair; import org.gradle.internal.classloader.ClassLoaderHierarchyHasher; -import org.gradle.internal.instantiation.Managed; +import org.gradle.internal.state.Managed; import org.gradle.internal.isolation.Isolatable; import org.gradle.internal.isolation.IsolatableFactory; import org.gradle.internal.isolation.IsolationException; @@ -150,18 +141,12 @@ private T processValue(@Nullable Object value, ValueVisitor visitor) { if (value instanceof Attribute) { return visitor.attributeValue((Attribute) value); } - if (value instanceof Provider) { - Provider provider = (Provider) value; - Object providerValue = provider.getOrNull(); - T providerValueSnapshot = processValue(providerValue, visitor); - return visitor.provider(provider, providerValueSnapshot); - } if (value instanceof Managed) { Managed managed = (Managed) value; if (managed.immutable()) { return visitor.managedImmutableValue(managed); } else { - // May be mutable - unpack the state + // May (or may not) be mutable - unpack the state T state = processValue(managed.unpackState(), visitor); return visitor.managedValue(managed, state); } @@ -169,9 +154,6 @@ private T processValue(@Nullable Object value, ValueVisitor visitor) { if (value instanceof Isolatable) { return visitor.fromIsolatable((Isolatable) value); } - if (value instanceof ConfigurableFileCollection) { - return visitor.fromFileCollection((ConfigurableFileCollection) value); - } // Fall back to serialization return serialize(value, visitor); @@ -230,10 +212,6 @@ private interface ValueVisitor { T map(ImmutableList> elements); - T provider(Provider provider, T snapshot); - - T fromFileCollection(ConfigurableFileCollection files); - T serialized(Object value, byte[] serializedValue); } @@ -301,7 +279,7 @@ public ValueSnapshot managedImmutableValue(Managed managed) { @Override public ValueSnapshot managedValue(Managed value, ValueSnapshot state) { - return new ManagedTypeSnapshot(value.publicType().getName(), state); + return new ManagedValueSnapshot(value.publicType().getName(), state); } @Override @@ -309,16 +287,6 @@ public ValueSnapshot fromIsolatable(Isolatable value) { return value.asSnapshot(); } - @Override - public ValueSnapshot provider(Provider provider, ValueSnapshot snapshot) { - return snapshot; - } - - @Override - public ValueSnapshot fromFileCollection(ConfigurableFileCollection files) { - throw new UnsupportedOperationException("Not implemented"); - } - @Override public ValueSnapshot serialized(Object value, byte[] serializedValue) { return new SerializedValueSnapshot(classLoaderHasher.getClassLoaderHash(value.getClass().getClassLoader()), serializedValue); @@ -419,7 +387,7 @@ public Isolatable managedImmutableValue(Managed managed) { @Override public Isolatable managedValue(Managed value, Isolatable state) { - return new IsolatedManagedTypeSnapshot(value.publicType(), value.managedFactory(), state); + return new IsolatedManagedValue(value.publicType(), value.managedFactory(), state); } @Override @@ -432,29 +400,6 @@ public Isolatable serialized(Object value, byte[] serializedValue) { return new IsolatedSerializedValueSnapshot(classLoaderHasher.getClassLoaderHash(value.getClass().getClassLoader()), serializedValue, value.getClass()); } - @Override - public Isolatable provider(Provider provider, Isolatable snapshot) { - if (provider instanceof Property) { - return new IsolatedProperty(((ProviderInternal)provider).getType(), snapshot); - } - if (provider instanceof ListProperty) { - return new IsolatedListProperty(((CollectionPropertyInternal) provider).getElementType(), snapshot); - } - if (provider instanceof SetProperty) { - return new IsolatedSetProperty(((CollectionPropertyInternal) provider).getElementType(), snapshot); - } - if (provider instanceof MapProperty) { - DefaultMapProperty mapProperty = (DefaultMapProperty) provider; - return new IsolatedMapProperty(mapProperty.getKeyType(), mapProperty.getValueType(), snapshot); - } - return new IsolatedProvider(snapshot); - } - - @Override - public Isolatable fromFileCollection(ConfigurableFileCollection files) { - return new IsolatedFileCollection(files); - } - @Override public Isolatable emptyArray() { return IsolatedArray.EMPTY; diff --git a/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/IsolatedFileCollection.java b/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/IsolatedFileCollection.java deleted file mode 100644 index c1628e286915c..0000000000000 --- a/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/IsolatedFileCollection.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright 2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.gradle.internal.snapshot.impl; - -import org.gradle.api.file.ConfigurableFileCollection; -import org.gradle.api.internal.file.IdentityFileResolver; -import org.gradle.api.internal.file.collections.DefaultConfigurableFileCollection; -import org.gradle.internal.hash.Hasher; -import org.gradle.internal.isolation.Isolatable; -import org.gradle.internal.snapshot.ValueSnapshot; - -import javax.annotation.Nullable; -import java.io.File; -import java.util.Set; - -class IsolatedFileCollection implements Isolatable { - private final Set files; - - public IsolatedFileCollection(ConfigurableFileCollection files) { - this.files = files.getFiles(); - } - - @Override - public ValueSnapshot asSnapshot() { - throw new UnsupportedOperationException("Not implemented"); - } - - @Override - public void appendToHasher(Hasher hasher) { - hasher.putString("files"); - for (File file : files) { - hasher.putString(file.getAbsolutePath()); - } - } - - @Nullable - @Override - public ConfigurableFileCollection isolate() { - return new DefaultConfigurableFileCollection(new IdentityFileResolver(), null, files); - } - - @Nullable - @Override - public S coerce(Class type) { - if (type.isAssignableFrom(ConfigurableFileCollection.class)) { - return type.cast(isolate()); - } - return null; - } -} diff --git a/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/IsolatedImmutableManagedValue.java b/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/IsolatedImmutableManagedValue.java index 562adde8b1b0a..7b8706bdb63c4 100644 --- a/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/IsolatedImmutableManagedValue.java +++ b/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/IsolatedImmutableManagedValue.java @@ -17,7 +17,7 @@ package org.gradle.internal.snapshot.impl; import org.gradle.internal.hash.Hasher; -import org.gradle.internal.instantiation.Managed; +import org.gradle.internal.state.Managed; import org.gradle.internal.snapshot.ValueSnapshot; import javax.annotation.Nullable; @@ -43,9 +43,6 @@ public S coerce(Class type) { if (type.isInstance(getValue())) { return type.cast(getValue()); } - if (type.getName().equals(getValue().publicType().getName())) { - return type.cast(getValue().managedFactory().fromState(type, getValue().unpackState())); - } - return null; + return type.cast(getValue().managedFactory().fromState(type, getValue().unpackState())); } } diff --git a/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/IsolatedListProperty.java b/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/IsolatedListProperty.java deleted file mode 100644 index 73656ea84ed66..0000000000000 --- a/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/IsolatedListProperty.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright 2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.gradle.internal.snapshot.impl; - -import org.gradle.api.internal.provider.DefaultListProperty; -import org.gradle.api.provider.ListProperty; -import org.gradle.internal.isolation.Isolatable; - -import javax.annotation.Nullable; -import java.util.List; - -class IsolatedListProperty extends IsolatedProvider { - private final Class type; - - public IsolatedListProperty(Class type, Isolatable value) { - super(value); - this.type = type; - } - - @Nullable - @Override - public ListProperty isolate() { - DefaultListProperty property = new DefaultListProperty<>((Class) type); - property.set((List) value.isolate()); - return property; - } -} diff --git a/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/IsolatedManagedTypeSnapshot.java b/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/IsolatedManagedValue.java similarity index 71% rename from subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/IsolatedManagedTypeSnapshot.java rename to subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/IsolatedManagedValue.java index fbc1ef140da23..5428e0d09caf9 100644 --- a/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/IsolatedManagedTypeSnapshot.java +++ b/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/IsolatedManagedValue.java @@ -16,17 +16,17 @@ package org.gradle.internal.snapshot.impl; -import org.gradle.internal.instantiation.Managed; +import org.gradle.internal.state.Managed; import org.gradle.internal.isolation.Isolatable; import org.gradle.internal.snapshot.ValueSnapshot; import javax.annotation.Nullable; -class IsolatedManagedTypeSnapshot extends AbstractManagedTypeSnapshot> implements Isolatable { +class IsolatedManagedValue extends AbstractManagedValueSnapshot> implements Isolatable { private final Managed.Factory factory; private final Class targetType; - public IsolatedManagedTypeSnapshot(Class targetType, Managed.Factory factory, Isolatable state) { + public IsolatedManagedValue(Class targetType, Managed.Factory factory, Isolatable state) { super(state); this.targetType = targetType; this.factory = factory; @@ -34,7 +34,7 @@ public IsolatedManagedTypeSnapshot(Class targetType, Managed.Factory factory, @Override public ValueSnapshot asSnapshot() { - return new ManagedTypeSnapshot(targetType.getName(), state.asSnapshot()); + return new ManagedValueSnapshot(targetType.getName(), state.asSnapshot()); } @Override @@ -48,9 +48,6 @@ public S coerce(Class type) { if (type.isAssignableFrom(targetType)) { return type.cast(isolate()); } - if (targetType.getName().equals(type.getName())) { - return type.cast(factory.fromState(type, state.isolate())); - } - return null; + return type.cast(factory.fromState(type, state.isolate())); } } diff --git a/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/IsolatedMapProperty.java b/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/IsolatedMapProperty.java deleted file mode 100644 index d4038ca11eefa..0000000000000 --- a/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/IsolatedMapProperty.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright 2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.gradle.internal.snapshot.impl; - -import org.gradle.api.internal.provider.DefaultMapProperty; -import org.gradle.api.provider.MapProperty; -import org.gradle.internal.isolation.Isolatable; - -import javax.annotation.Nullable; -import java.util.Map; - -class IsolatedMapProperty extends IsolatedProvider { - private final Class keyType; - private final Class valueType; - - public IsolatedMapProperty(Class keyType, Class valueType, Isolatable value) { - super(value); - this.keyType = keyType; - this.valueType = valueType; - } - - @Nullable - @Override - public MapProperty isolate() { - DefaultMapProperty property = new DefaultMapProperty<>((Class) keyType, (Class) valueType); - property.set((Map) value.isolate()); - return property; - } -} diff --git a/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/IsolatedProperty.java b/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/IsolatedProperty.java deleted file mode 100644 index 6f7362caf369d..0000000000000 --- a/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/IsolatedProperty.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright 2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.gradle.internal.snapshot.impl; - -import org.gradle.api.internal.provider.DefaultPropertyState; -import org.gradle.api.provider.Property; -import org.gradle.internal.isolation.Isolatable; - -import javax.annotation.Nullable; - -class IsolatedProperty extends IsolatedProvider { - private final Class type; - - public IsolatedProperty(Class type, Isolatable value) { - super(value); - this.type = type; - } - - @Nullable - @Override - public Property isolate() { - DefaultPropertyState property = new DefaultPropertyState<>((Class) type); - property.set(value.isolate()); - return property; - } -} diff --git a/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/IsolatedProvider.java b/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/IsolatedProvider.java deleted file mode 100644 index 333599a046c61..0000000000000 --- a/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/IsolatedProvider.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright 2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.gradle.internal.snapshot.impl; - -import org.gradle.api.internal.provider.Providers; -import org.gradle.internal.hash.Hasher; -import org.gradle.internal.isolation.Isolatable; -import org.gradle.internal.snapshot.ValueSnapshot; - -import javax.annotation.Nullable; - -class IsolatedProvider implements Isolatable { - protected final Isolatable value; - - public IsolatedProvider(Isolatable value) { - this.value = value; - } - - @Override - public ValueSnapshot asSnapshot() { - return value.asSnapshot(); - } - - @Nullable - @Override - public S coerce(Class type) { - return null; - } - - @Nullable - @Override - public Object isolate() { - return Providers.of(value.isolate()); - } - - @Override - public void appendToHasher(Hasher hasher) { - value.appendToHasher(hasher); - } -} diff --git a/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/IsolatedSetProperty.java b/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/IsolatedSetProperty.java deleted file mode 100644 index 7950e212a75aa..0000000000000 --- a/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/IsolatedSetProperty.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright 2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.gradle.internal.snapshot.impl; - -import org.gradle.api.internal.provider.DefaultSetProperty; -import org.gradle.api.provider.SetProperty; -import org.gradle.internal.isolation.Isolatable; - -import javax.annotation.Nullable; -import java.util.Set; - -class IsolatedSetProperty extends IsolatedProvider { - private final Class type; - - public IsolatedSetProperty(Class type, Isolatable value) { - super(value); - this.type = type; - } - - @Nullable - @Override - public SetProperty isolate() { - DefaultSetProperty property = new DefaultSetProperty<>((Class) type); - property.set((Set) value.isolate()); - return property; - } -} diff --git a/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/ManagedTypeSnapshot.java b/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/ManagedValueSnapshot.java similarity index 75% rename from subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/ManagedTypeSnapshot.java rename to subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/ManagedValueSnapshot.java index a403944f92aa5..6af5c177edd63 100644 --- a/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/ManagedTypeSnapshot.java +++ b/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/ManagedValueSnapshot.java @@ -19,10 +19,10 @@ import org.gradle.internal.snapshot.ValueSnapshot; import org.gradle.internal.snapshot.ValueSnapshotter; -class ManagedTypeSnapshot extends AbstractManagedTypeSnapshot implements ValueSnapshot { +class ManagedValueSnapshot extends AbstractManagedValueSnapshot implements ValueSnapshot { private final String className; - public ManagedTypeSnapshot(String className, ValueSnapshot state) { + public ManagedValueSnapshot(String className, ValueSnapshot state) { super(state); this.className = className; } @@ -36,7 +36,7 @@ public boolean equals(Object obj) { if (!super.equals(obj)) { return false; } - ManagedTypeSnapshot other = (ManagedTypeSnapshot) obj; + ManagedValueSnapshot other = (ManagedValueSnapshot) obj; return className.equals(other.className); } @@ -48,11 +48,8 @@ public int hashCode() { @Override public ValueSnapshot snapshot(Object value, ValueSnapshotter snapshotter) { ValueSnapshot snapshot = snapshotter.snapshot(value); - if (snapshot instanceof ManagedTypeSnapshot) { - ManagedTypeSnapshot other = (ManagedTypeSnapshot) snapshot; - if (state.equals(other.state)) { - return this; - } + if (snapshot.equals(this)) { + return this; } return snapshot; } diff --git a/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/SnapshotSerializer.java b/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/SnapshotSerializer.java index 9f5eba51b605c..1776bb1ba4e62 100644 --- a/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/SnapshotSerializer.java +++ b/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/SnapshotSerializer.java @@ -102,7 +102,7 @@ public ValueSnapshot read(Decoder decoder) throws Exception { case MANAGED_SNAPSHOT: className = decoder.readString(); ValueSnapshot state = read(decoder); - return new ManagedTypeSnapshot(className, state); + return new ManagedValueSnapshot(className, state); case IMMUTABLE_MANAGED_SNAPSHOT: className = decoder.readString(); String value = decoder.readString(); @@ -213,9 +213,9 @@ public void write(Encoder encoder, ValueSnapshot snapshot) throws Exception { ImmutableManagedValueSnapshot valueSnapshot = (ImmutableManagedValueSnapshot) snapshot; encoder.writeString(valueSnapshot.getClassName()); encoder.writeString(valueSnapshot.getValue()); - } else if (snapshot instanceof ManagedTypeSnapshot) { + } else if (snapshot instanceof ManagedValueSnapshot) { encoder.writeSmallInt(MANAGED_SNAPSHOT); - ManagedTypeSnapshot managedTypeSnapshot = (ManagedTypeSnapshot) snapshot; + ManagedValueSnapshot managedTypeSnapshot = (ManagedValueSnapshot) snapshot; encoder.writeString(managedTypeSnapshot.getClassName()); write(encoder, managedTypeSnapshot.getState()); } else { diff --git a/subprojects/snapshots/src/test/groovy/org/gradle/internal/snapshot/impl/DefaultValueSnapshotterTest.groovy b/subprojects/snapshots/src/test/groovy/org/gradle/internal/snapshot/impl/DefaultValueSnapshotterTest.groovy index 127835159328e..a0b7647c3da22 100644 --- a/subprojects/snapshots/src/test/groovy/org/gradle/internal/snapshot/impl/DefaultValueSnapshotterTest.groovy +++ b/subprojects/snapshots/src/test/groovy/org/gradle/internal/snapshot/impl/DefaultValueSnapshotterTest.groovy @@ -24,7 +24,6 @@ import org.gradle.api.internal.provider.DefaultMapProperty import org.gradle.api.internal.provider.DefaultPropertyState import org.gradle.api.internal.provider.DefaultSetProperty import org.gradle.api.internal.provider.Providers -import org.gradle.api.provider.Provider import org.gradle.internal.classloader.ClassLoaderHierarchyHasher import org.gradle.internal.classloader.ClasspathUtil import org.gradle.internal.classloader.FilteringClassLoader @@ -501,19 +500,16 @@ class DefaultValueSnapshotterTest extends Specification { } def "creates snapshot for provider type"() { - def value = Stub(Provider) - value.getOrNull() >> "123" - def value2 = Stub(Provider) - value2.getOrNull() >> "123" - def value3 = Stub(Provider) - value3.getOrNull() >> "12" + def value = Providers.of("123") + def value2 = Providers.of("123") + def value3 = Providers.of("12") expect: def snapshot = snapshotter.snapshot(value) - snapshot == snapshotter.snapshot("123") snapshot == snapshotter.snapshot(value) snapshot == snapshotter.snapshot(value2) snapshot != snapshotter.snapshot(value3) + snapshot != snapshotter.snapshot("123") } def "creates isolated provider"() { @@ -522,7 +518,7 @@ class DefaultValueSnapshotterTest extends Specification { expect: def isolated = snapshotter.isolate(original) - isolated instanceof IsolatedProvider + isolated instanceof IsolatedManagedValue def copy = isolated.isolate() !copy.is(original) copy.get().is(originalValue) @@ -535,7 +531,7 @@ class DefaultValueSnapshotterTest extends Specification { expect: def isolated = snapshotter.isolate(original) - isolated instanceof IsolatedProperty + isolated instanceof IsolatedManagedValue def copy = isolated.isolate() !copy.is(original) copy.get().is(originalValue) @@ -548,7 +544,7 @@ class DefaultValueSnapshotterTest extends Specification { expect: def isolated = snapshotter.isolate(original) - isolated instanceof IsolatedListProperty + isolated instanceof IsolatedManagedValue def copy = isolated.isolate() !copy.is(original) copy.get() == ["123"] @@ -562,7 +558,7 @@ class DefaultValueSnapshotterTest extends Specification { expect: def isolated = snapshotter.isolate(original) - isolated instanceof IsolatedSetProperty + isolated instanceof IsolatedManagedValue def copy = isolated.isolate() !copy.is(original) copy.get() == ["123"] as Set @@ -576,7 +572,7 @@ class DefaultValueSnapshotterTest extends Specification { expect: def isolated = snapshotter.isolate(original) - isolated instanceof IsolatedMapProperty + isolated instanceof IsolatedManagedValue def copy = isolated.isolate() !copy.is(original) copy.get() == [a: 1, b: 2] @@ -616,7 +612,7 @@ class DefaultValueSnapshotterTest extends Specification { def spec = new FilteringClassLoader.Spec() spec.allowClass(Named) spec.allowPackage("org.gradle.api.internal.model") // mixed into the implementation - spec.allowPackage("org.gradle.internal.instantiation") // mixed into the implementation + spec.allowPackage("org.gradle.internal.state") // mixed into the implementation def filter = new FilteringClassLoader(getClass().classLoader, spec) def loader = new GroovyClassLoader(filter) loader.addURL(ClasspathUtil.getClasspathForClass(GroovyObject).toURI().toURL()) @@ -666,7 +662,7 @@ class DefaultValueSnapshotterTest extends Specification { expect: def snapshot = snapshotter.snapshot(value) - snapshot instanceof ManagedTypeSnapshot + snapshot instanceof ManagedValueSnapshot snapshot == snapshotter.snapshot(value) snapshot == snapshotter.snapshot(value1) snapshot != snapshotter.snapshot(value2) @@ -680,7 +676,7 @@ class DefaultValueSnapshotterTest extends Specification { expect: def isolated = snapshotter.isolate(original) - isolated instanceof IsolatedManagedTypeSnapshot + isolated instanceof IsolatedManagedValue def copy = isolated.isolate() !copy.is(original) copy.prop1 == "a" @@ -699,7 +695,7 @@ class DefaultValueSnapshotterTest extends Specification { expect: def snapshot = snapshotter.snapshot(value) - snapshot instanceof ManagedTypeSnapshot + snapshot instanceof ManagedValueSnapshot snapshot == snapshotter.snapshot(value) snapshot == snapshotter.snapshot(value1) snapshot != snapshotter.snapshot(value2) @@ -713,7 +709,7 @@ class DefaultValueSnapshotterTest extends Specification { expect: def isolated = snapshotter.isolate(original) - isolated instanceof IsolatedManagedTypeSnapshot + isolated instanceof IsolatedManagedValue def copy = isolated.isolate() !copy.is(original) copy.prop1 == "a" @@ -726,13 +722,13 @@ class DefaultValueSnapshotterTest extends Specification { expect: def isolatedEmpty = snapshotter.isolate(empty) - isolatedEmpty instanceof IsolatedFileCollection + isolatedEmpty instanceof IsolatedManagedValue def copyEmpty = isolatedEmpty.isolate() !copyEmpty.is(empty) copyEmpty.files as List == [] def isolated = snapshotter.isolate(files1) - isolated instanceof IsolatedFileCollection + isolated instanceof IsolatedManagedValue def copy = isolated.isolate() !copy.is(files1) copy.files == files1.files @@ -1007,18 +1003,15 @@ class DefaultValueSnapshotterTest extends Specification { } def "creates snapshot for provider type from candidate"() { - def value = Stub(Provider) - value.getOrNull() >> "123" - def value2 = Stub(Provider) - value2.getOrNull() >> "123" - def value3 = Stub(Provider) - value3.getOrNull() >> "12" + def value = Providers.of("123") + def value2 = Providers.of("123") + def value3 = Providers.of("12") expect: def snapshot = snapshotter.snapshot(value) - areTheSame(snapshot, "123") areTheSame(snapshot, value2) areNotTheSame(snapshot, value3) + areNotTheSame(snapshot, "123") } def "creates snapshot for named managed type from candidate"() { diff --git a/subprojects/snapshots/src/test/groovy/org/gradle/internal/snapshot/impl/SnapshotSerializerTest.groovy b/subprojects/snapshots/src/test/groovy/org/gradle/internal/snapshot/impl/SnapshotSerializerTest.groovy index 87aa889569979..e3f663d7631b7 100644 --- a/subprojects/snapshots/src/test/groovy/org/gradle/internal/snapshot/impl/SnapshotSerializerTest.groovy +++ b/subprojects/snapshots/src/test/groovy/org/gradle/internal/snapshot/impl/SnapshotSerializerTest.groovy @@ -164,7 +164,7 @@ class SnapshotSerializerTest extends Specification { } def "serializes managed type properties"() { - def original = new ManagedTypeSnapshot("named", integer(123)) + def original = new ManagedValueSnapshot("named", integer(123)) write(original) expect: From a77395628cbc75148df63c0c1f51172f7ea79a36 Mon Sep 17 00:00:00 2001 From: Adam Murdoch Date: Thu, 21 Feb 2019 15:38:32 +1100 Subject: [PATCH 037/853] Add some more test coverage for using various `Property` types as task properties. --- .../TaskDefinitionIntegrationTest.groovy | 2 +- .../TaskInputPropertiesIntegrationTest.groovy | 65 +++++++++++-------- .../CollectionPropertyIntegrationTest.groovy | 25 +++++++ .../MapPropertyIntegrationTest.groovy | 25 +++++++ .../provider/PropertyIntegrationTest.groovy | 25 +++++++ 5 files changed, 113 insertions(+), 29 deletions(-) diff --git a/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/TaskDefinitionIntegrationTest.groovy b/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/TaskDefinitionIntegrationTest.groovy index f17c9266c7f79..5742961a5d804 100644 --- a/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/TaskDefinitionIntegrationTest.groovy +++ b/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/TaskDefinitionIntegrationTest.groovy @@ -566,7 +566,7 @@ class TaskDefinitionIntegrationTest extends AbstractIntegrationSpec { failure.assertHasCause("Adding a task provider directly to the task container is not supported.") } - def "can define task using abstract FileCollection getter"() { + def "can define task with abstract ConfigurableFileCollection getter"() { given: buildFile << """ abstract class MyTask extends DefaultTask { diff --git a/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/TaskInputPropertiesIntegrationTest.groovy b/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/TaskInputPropertiesIntegrationTest.groovy index 3ee3fae67e867..848264825492f 100644 --- a/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/TaskInputPropertiesIntegrationTest.groovy +++ b/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/TaskInputPropertiesIntegrationTest.groovy @@ -17,7 +17,11 @@ package org.gradle.api.tasks import org.gradle.api.file.FileCollection +import org.gradle.api.provider.ListProperty +import org.gradle.api.provider.MapProperty +import org.gradle.api.provider.Property import org.gradle.api.provider.Provider +import org.gradle.api.provider.SetProperty import org.gradle.integtests.fixtures.AbstractIntegrationSpec import org.gradle.integtests.fixtures.TestBuildCache import org.gradle.internal.Actions @@ -369,7 +373,7 @@ task someTask { } @Unroll - def "task can use property of type #type"() { + def "task can use input property of type #type"() { file("buildSrc/src/main/java/SomeTask.java") << """ import org.gradle.api.DefaultTask; import org.gradle.api.tasks.TaskAction; @@ -379,11 +383,12 @@ import org.gradle.api.tasks.Optional; import java.io.File; public class SomeTask extends DefaultTask { - public $type v; + private $type v; @Input public $type getV() { return v; } + void setV($type v) { this.v = v; } - public File d; + File d; @OutputDirectory public File getD() { return d; } @@ -423,29 +428,33 @@ task someTask(type: SomeTask) { skipped(":someTask") where: - type | initialValue | newValue - "String" | "'value 1'" | "'value 2'" - "java.io.File" | "file('file1')" | "file('file2')" - "boolean" | "true" | "false" - "Boolean" | "Boolean.TRUE" | "Boolean.FALSE" - "int" | "123" | "-45" - "Integer" | "123" | "-45" - "long" | "123" | "-45" - "Long" | "123" | "-45" - "short" | "123" | "-45" - "Short" | "123" | "-45" - "java.math.BigDecimal" | "12.3" | "-45.432" - "java.math.BigInteger" | "12" | "-45" - "java.util.List" | "['value1', 'value2']" | "['value1']" - "java.util.List" | "[]" | "['value1', null, false, 123, 12.4, ['abc'], [true] as Set]" - "String[]" | "new String[0]" | "['abc'] as String[]" - "Object[]" | "[123, 'abc'] as Object[]" | "['abc'] as String[]" - "java.util.Collection" | "['value1', 'value2']" | "['value1'] as SortedSet" - "java.util.Set" | "['value1', 'value2'] as Set" | "['value1'] as Set" - "Iterable" | "[file('1'), file('2')] as Set" | "files('1')" - FileCollection.name | "files('1', '2')" | "configurations.create('empty')" - "java.util.Map" | "[a: true, b: false]" | "[a: true, b: true]" - "${Provider.name}" | "providers.provider { 'a' }" | "providers.provider { 'b' }" + type | initialValue | newValue + "String" | "'value 1'" | "'value 2'" + "java.io.File" | "file('file1')" | "file('file2')" + "boolean" | "true" | "false" + "Boolean" | "Boolean.TRUE" | "Boolean.FALSE" + "int" | "123" | "-45" + "Integer" | "123" | "-45" + "long" | "123" | "-45" + "Long" | "123" | "-45" + "short" | "123" | "-45" + "Short" | "123" | "-45" + "java.math.BigDecimal" | "12.3" | "-45.432" + "java.math.BigInteger" | "12" | "-45" + "java.util.List" | "['value1', 'value2']" | "['value1']" + "java.util.List" | "[]" | "['value1', null, false, 123, 12.4, ['abc'], [true] as Set]" + "String[]" | "new String[0]" | "['abc'] as String[]" + "Object[]" | "[123, 'abc'] as Object[]" | "['abc'] as String[]" + "java.util.Collection" | "['value1', 'value2']" | "['value1'] as SortedSet" + "java.util.Set" | "['value1', 'value2'] as Set" | "['value1'] as Set" + "Iterable" | "[file('1'), file('2')] as Set" | "files('1')" + FileCollection.name | "files('1', '2')" | "configurations.create('empty')" + "java.util.Map" | "[a: true, b: false]" | "[a: true, b: true]" + "${Provider.name}" | "providers.provider { 'a' }" | "providers.provider { 'b' }" + "${Property.name}" | "objects.property(String); v.set('abc')" | "objects.property(String); v.set('123')" + "${ListProperty.name}" | "objects.listProperty(String); v.set(['abc'])" | "objects.listProperty(String); v.set(['123'])" + "${SetProperty.name}" | "objects.setProperty(String); v.set(['abc'])" | "objects.setProperty(String); v.set(['123'])" + "${MapProperty.name}" | "objects.mapProperty(String, Number); v.set([a: 12])" | "objects.mapProperty(String, Number); v.set([a: 10])" } def "null input properties registered via TaskInputs.property are not allowed"() { @@ -708,8 +717,8 @@ task someTask(type: SomeTask) { inputFile.text = "input" def expectedCounts = [inputFile: 3, outputFile: 3, nestedInput: 3, inputValue: 1, nestedInputValue: 1] def expectedUpToDateCounts = [inputFile: 2, outputFile: 2, nestedInput: 3, inputValue: 1, nestedInputValue: 1] - def arguments = ["assertInputCounts"] + expectedCounts.collect { name, count -> "-P${name}Count=${count}"} - def upToDateArguments = ["assertInputCounts"] + expectedUpToDateCounts.collect { name, count -> "-P${name}Count=${count}"} + def arguments = ["assertInputCounts"] + expectedCounts.collect { name, count -> "-P${name}Count=${count}" } + def upToDateArguments = ["assertInputCounts"] + expectedUpToDateCounts.collect { name, count -> "-P${name}Count=${count}" } def localCache = new TestBuildCache(file('cache-dir')) settingsFile << localCache.localCacheConfiguration() diff --git a/subprojects/model-core/src/integTest/groovy/org/gradle/api/provider/CollectionPropertyIntegrationTest.groovy b/subprojects/model-core/src/integTest/groovy/org/gradle/api/provider/CollectionPropertyIntegrationTest.groovy index 3d63928f4151b..ac9d01caaa561 100644 --- a/subprojects/model-core/src/integTest/groovy/org/gradle/api/provider/CollectionPropertyIntegrationTest.groovy +++ b/subprojects/model-core/src/integTest/groovy/org/gradle/api/provider/CollectionPropertyIntegrationTest.groovy @@ -40,6 +40,31 @@ class CollectionPropertyIntegrationTest extends AbstractIntegrationSpec { """ } + def "can define task with abstract ListProperty getter"() { + given: + buildFile << """ + abstract class ATask extends DefaultTask { + @Input + abstract ListProperty getProp() + + @TaskAction + void go() { + println("prop = \${prop.get()}") + } + } + + tasks.create("thing", ATask) { + prop = ["a", "b", "c"] + } + """ + + when: + succeeds("thing") + + then: + outputContains("prop = [a, b, c]") + } + def "can finalize the value of a property using API"() { given: buildFile << """ diff --git a/subprojects/model-core/src/integTest/groovy/org/gradle/api/provider/MapPropertyIntegrationTest.groovy b/subprojects/model-core/src/integTest/groovy/org/gradle/api/provider/MapPropertyIntegrationTest.groovy index 3fb40f12dbfdb..35bd83a30dd23 100644 --- a/subprojects/model-core/src/integTest/groovy/org/gradle/api/provider/MapPropertyIntegrationTest.groovy +++ b/subprojects/model-core/src/integTest/groovy/org/gradle/api/provider/MapPropertyIntegrationTest.groovy @@ -61,6 +61,31 @@ class MapPropertyIntegrationTest extends AbstractIntegrationSpec { ''' } + def "can define task with abstract MapProperty getter"() { + given: + buildFile << """ + abstract class MyTask extends DefaultTask { + @Input + abstract MapProperty getProp() + + @TaskAction + void go() { + println("prop = \${prop.get()}") + } + } + + tasks.create("thing", MyTask) { + prop = [a: 12, b: 4] + } + """ + + when: + succeeds("thing") + + then: + outputContains("prop = [a:12, b:4]") + } + def "can finalize the value of a property using API"() { given: buildFile << ''' diff --git a/subprojects/model-core/src/integTest/groovy/org/gradle/api/provider/PropertyIntegrationTest.groovy b/subprojects/model-core/src/integTest/groovy/org/gradle/api/provider/PropertyIntegrationTest.groovy index a07320aac3931..bd8c3153dfd19 100644 --- a/subprojects/model-core/src/integTest/groovy/org/gradle/api/provider/PropertyIntegrationTest.groovy +++ b/subprojects/model-core/src/integTest/groovy/org/gradle/api/provider/PropertyIntegrationTest.groovy @@ -60,6 +60,31 @@ task thing(type: SomeTask) { skipped(":thing") } + def "can define task with abstract Property getter"() { + given: + buildFile << """ + abstract class MyTask extends DefaultTask { + @Input + abstract Property getProp() + + @TaskAction + void go() { + println("prop = \${prop.get()}") + } + } + + tasks.create("thing", MyTask) { + prop = "abc" + } + """ + + when: + succeeds("thing") + + then: + outputContains("prop = abc") + } + def "can finalize the value of a property using API"() { given: buildFile << """ From e305354f30cbd15771b82dfd2526df9e26aa584a Mon Sep 17 00:00:00 2001 From: Adam Murdoch Date: Thu, 21 Feb 2019 16:54:43 +1100 Subject: [PATCH 038/853] Fix the calculation of the public type for a generated type when the public type is an interface. --- .../api/internal/GeneratedSubclass.java | 1 + .../api/internal/GeneratedSubclasses.java | 10 ++--- .../BuildCacheControllerFactory.java | 2 +- .../transform/DefaultTransformer.java | 5 +-- .../api/internal/plugins/DslObject.java | 14 +++---- .../AsmBackedClassGenerator.java | 41 +++++++++++++------ .../AsmBackedClassGeneratorTest.java | 18 ++++++-- 7 files changed, 56 insertions(+), 35 deletions(-) diff --git a/subprojects/base-services/src/main/java/org/gradle/api/internal/GeneratedSubclass.java b/subprojects/base-services/src/main/java/org/gradle/api/internal/GeneratedSubclass.java index 329b38a62370f..f09154d9ecd9f 100644 --- a/subprojects/base-services/src/main/java/org/gradle/api/internal/GeneratedSubclass.java +++ b/subprojects/base-services/src/main/java/org/gradle/api/internal/GeneratedSubclass.java @@ -20,4 +20,5 @@ * Marker interface for types that are runtime generated subclasses by {@link ClassGenerator} */ public interface GeneratedSubclass { + Class publicType(); } diff --git a/subprojects/base-services/src/main/java/org/gradle/api/internal/GeneratedSubclasses.java b/subprojects/base-services/src/main/java/org/gradle/api/internal/GeneratedSubclasses.java index 5db28b0b7e1dd..24da3b9868e6e 100644 --- a/subprojects/base-services/src/main/java/org/gradle/api/internal/GeneratedSubclasses.java +++ b/subprojects/base-services/src/main/java/org/gradle/api/internal/GeneratedSubclasses.java @@ -21,12 +21,12 @@ public class GeneratedSubclasses { private GeneratedSubclasses() { } - public static Class unpack(Class clazz) { - if (GeneratedSubclass.class.isAssignableFrom(clazz)) { - return unpack(clazz.getSuperclass()); - } else { - return clazz; + public static Class unpack(Object object) { + if (object instanceof GeneratedSubclass) { + GeneratedSubclass generatedSubclass = (GeneratedSubclass) object; + return generatedSubclass.publicType(); } + return object.getClass(); } } diff --git a/subprojects/build-cache/src/main/java/org/gradle/caching/internal/controller/BuildCacheControllerFactory.java b/subprojects/build-cache/src/main/java/org/gradle/caching/internal/controller/BuildCacheControllerFactory.java index 2a8a111e54b23..f741bf808fd06 100644 --- a/subprojects/build-cache/src/main/java/org/gradle/caching/internal/controller/BuildCacheControllerFactory.java +++ b/subprojects/build-cache/src/main/java/org/gradle/caching/internal/controller/BuildCacheControllerFactory.java @@ -204,7 +204,7 @@ private static final class BuildCacheDescription implements FinalizeBuildCacheCo private final ImmutableSortedMap config; private BuildCacheDescription(BuildCache buildCache, String type, ImmutableSortedMap config) { - this.className = GeneratedSubclasses.unpack(buildCache.getClass()).getName(); + this.className = GeneratedSubclasses.unpack(buildCache).getName(); this.push = buildCache.isPush(); this.type = type; this.config = config; diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformer.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformer.java index ebbc4b724a058..a50896ff0161a 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformer.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformer.java @@ -29,6 +29,7 @@ import org.gradle.api.file.FileCollection; import org.gradle.api.internal.attributes.ImmutableAttributes; import org.gradle.api.internal.file.FileCollectionFactory; +import org.gradle.api.internal.plugins.DslObject; import org.gradle.api.internal.project.ProjectStateRegistry; import org.gradle.api.internal.tasks.TaskDependencyResolveContext; import org.gradle.api.internal.tasks.WorkNodeAction; @@ -53,7 +54,6 @@ import org.gradle.internal.hash.Hashing; import org.gradle.internal.instantiation.InstanceFactory; import org.gradle.internal.instantiation.InstantiationScheme; -import org.gradle.internal.state.Managed; import org.gradle.internal.isolation.Isolatable; import org.gradle.internal.isolation.IsolatableFactory; import org.gradle.internal.reflect.ParameterValidationContext; @@ -300,8 +300,7 @@ public void visitInputFileProperty(String propertyName, boolean optional, boolea } private static String getParameterObjectDisplayName(Object parameterObject) { - Class parameterClass = parameterObject instanceof Managed ? ((Managed) parameterObject).publicType() : parameterObject.getClass(); - return ModelType.of(parameterClass).getDisplayName(); + return ModelType.of(new DslObject(parameterObject).getDeclaredType()).getDisplayName(); } private TransformAction newTransformAction(File inputFile, ArtifactTransformDependencies artifactTransformDependencies) { diff --git a/subprojects/model-core/src/main/java/org/gradle/api/internal/plugins/DslObject.java b/subprojects/model-core/src/main/java/org/gradle/api/internal/plugins/DslObject.java index 06b20ca16f522..cfff36c6ad588 100644 --- a/subprojects/model-core/src/main/java/org/gradle/api/internal/plugins/DslObject.java +++ b/subprojects/model-core/src/main/java/org/gradle/api/internal/plugins/DslObject.java @@ -16,17 +16,17 @@ package org.gradle.api.internal.plugins; +import org.gradle.api.internal.ConventionMapping; +import org.gradle.api.internal.DynamicObjectAware; import org.gradle.api.internal.GeneratedSubclasses; import org.gradle.api.internal.HasConvention; +import org.gradle.api.internal.IConventionAware; import org.gradle.api.plugins.Convention; import org.gradle.api.plugins.ExtensionAware; import org.gradle.api.plugins.ExtensionContainer; import org.gradle.api.reflect.HasPublicType; import org.gradle.api.reflect.TypeOf; -import org.gradle.api.internal.ConventionMapping; -import org.gradle.api.internal.IConventionAware; import org.gradle.internal.metaobject.DynamicObject; -import org.gradle.api.internal.DynamicObjectAware; import static org.gradle.internal.Cast.uncheckedCast; @@ -88,15 +88,11 @@ public TypeOf getPublicType() { if (object instanceof HasPublicType) { return uncheckedCast(((HasPublicType) object).getPublicType()); } - return TypeOf.typeOf(firstNonGeneratedClassOf(object.getClass())); + return TypeOf.typeOf(GeneratedSubclasses.unpack(object)); } public Class getImplementationType() { - return firstNonGeneratedClassOf(object.getClass()); - } - - private Class firstNonGeneratedClassOf(Class clazz) { - return GeneratedSubclasses.unpack(clazz); + return GeneratedSubclasses.unpack(object); } private static T toType(Object delegate, Class type) { diff --git a/subprojects/model-core/src/main/java/org/gradle/internal/instantiation/AsmBackedClassGenerator.java b/subprojects/model-core/src/main/java/org/gradle/internal/instantiation/AsmBackedClassGenerator.java index 76c8388a25831..9ed06886fa4c4 100644 --- a/subprojects/model-core/src/main/java/org/gradle/internal/instantiation/AsmBackedClassGenerator.java +++ b/subprojects/model-core/src/main/java/org/gradle/internal/instantiation/AsmBackedClassGenerator.java @@ -307,6 +307,12 @@ private static class ClassBuilderImpl implements ClassGenerationVisitor { private static final Type OBJECT_FACTORY_TYPE = Type.getType(ObjectFactory.class); private static final Type CONFIGURABLE_FILE_COLLECTION_TYPE = Type.getType(ConfigurableFileCollection.class); private static final Type MANAGED_TYPE = Type.getType(Managed.class); + private static final Type REGULAR_FILE_PROPERTY_TYPE = Type.getType(RegularFileProperty.class); + private static final Type DIRECTORY_PROPERTY_TYPE = Type.getType(DirectoryProperty.class); + private static final Type PROPERTY_TYPE = Type.getType(Property.class); + private static final Type LIST_PROPERTY_TYPE = Type.getType(ListProperty.class); + private static final Type SET_PROPERTY_TYPE = Type.getType(SetProperty.class); + private static final Type MAP_PROPERTY = Type.getType(MapProperty.class); private static final String RETURN_VOID_FROM_OBJECT = Type.getMethodDescriptor(Type.VOID_TYPE, OBJECT_TYPE); private static final String RETURN_VOID_FROM_OBJECT_CLASS_DYNAMIC_OBJECT_INSTANTIATOR = Type.getMethodDescriptor(Type.VOID_TYPE, OBJECT_TYPE, CLASS_TYPE, DYNAMIC_OBJECT_TYPE, INSTANTIATOR_TYPE); @@ -334,6 +340,12 @@ private static class ClassBuilderImpl implements ClassGenerationVisitor { private static final String GET_DECLARED_METHOD_DESCRIPTOR = Type.getMethodDescriptor(METHOD_TYPE, STRING_TYPE, CLASS_ARRAY_TYPE); private static final String RETURN_OBJECT_FROM_TYPE = Type.getMethodDescriptor(OBJECT_TYPE, JAVA_LANG_REFLECT_TYPE); private static final String RETURN_CONFIGURABLE_FILE_COLLECTION = Type.getMethodDescriptor(CONFIGURABLE_FILE_COLLECTION_TYPE); + private static final String RETURN_REGULAR_FILE_PROPERTY = Type.getMethodDescriptor(REGULAR_FILE_PROPERTY_TYPE); + private static final String RETURN_DIRECTORY_PROPERTY = Type.getMethodDescriptor(DIRECTORY_PROPERTY_TYPE); + private static final String RETURN_PROPERTY_FROM_CLASS = Type.getMethodDescriptor(PROPERTY_TYPE, CLASS_TYPE); + private static final String RETURN_LIST_PROPERTY_FROM_CLASS = Type.getMethodDescriptor(LIST_PROPERTY_TYPE, CLASS_TYPE); + private static final String RETURN_SET_PROPERTY_FROM_CLASS = Type.getMethodDescriptor(SET_PROPERTY_TYPE, CLASS_TYPE); + private static final String RETURN_MAP_PROPERTY_FROM_CLASS_CLASS = Type.getMethodDescriptor(MAP_PROPERTY, CLASS_TYPE, CLASS_TYPE); private static final String[] EMPTY_STRINGS = new String[0]; private static final Type[] EMPTY_TYPES = new Type[0]; @@ -405,6 +417,7 @@ public void startClass() { if (requiresServicesMethod) { generateServiceRegistrySupportMethods(); } + generatePublicTypeMethod(); } @Override @@ -965,32 +978,32 @@ public void applyReadOnlyManagedStateToGetter(PropertyMetaData property, Method methodVisitor.visitMethodInsn(Opcodes.INVOKEINTERFACE, OBJECT_FACTORY_TYPE.getInternalName(), "fileCollection", RETURN_CONFIGURABLE_FILE_COLLECTION, true); } else if (property.getType().equals(RegularFileProperty.class)) { // GENERATE objectFactory.fileProperty() - methodVisitor.visitMethodInsn(Opcodes.INVOKEINTERFACE, OBJECT_FACTORY_TYPE.getInternalName(), "fileProperty", Type.getMethodDescriptor(Type.getType(RegularFileProperty.class)), true); + methodVisitor.visitMethodInsn(Opcodes.INVOKEINTERFACE, OBJECT_FACTORY_TYPE.getInternalName(), "fileProperty", RETURN_REGULAR_FILE_PROPERTY, true); } else if (property.getType().equals(DirectoryProperty.class)) { // GENERATE objectFactory.directoryProperty() - methodVisitor.visitMethodInsn(Opcodes.INVOKEINTERFACE, OBJECT_FACTORY_TYPE.getInternalName(), "directoryProperty", Type.getMethodDescriptor(Type.getType(DirectoryProperty.class)), true); + methodVisitor.visitMethodInsn(Opcodes.INVOKEINTERFACE, OBJECT_FACTORY_TYPE.getInternalName(), "directoryProperty", RETURN_DIRECTORY_PROPERTY, true); } else if (property.getType().equals(Property.class)) { // GENERATE objectFactory.property(type) Class elementType = (Class) ((ParameterizedType) property.getGenericType()).getActualTypeArguments()[0]; methodVisitor.visitLdcInsn(Type.getType(elementType)); - methodVisitor.visitMethodInsn(Opcodes.INVOKEINTERFACE, OBJECT_FACTORY_TYPE.getInternalName(), "property", Type.getMethodDescriptor(Type.getType(Property.class), CLASS_TYPE), true); + methodVisitor.visitMethodInsn(Opcodes.INVOKEINTERFACE, OBJECT_FACTORY_TYPE.getInternalName(), "property", RETURN_PROPERTY_FROM_CLASS, true); } else if (property.getType().equals(ListProperty.class)) { // GENERATE objectFactory.listProperty(type) Class elementType = (Class) ((ParameterizedType) property.getGenericType()).getActualTypeArguments()[0]; methodVisitor.visitLdcInsn(Type.getType(elementType)); - methodVisitor.visitMethodInsn(Opcodes.INVOKEINTERFACE, OBJECT_FACTORY_TYPE.getInternalName(), "listProperty", Type.getMethodDescriptor(Type.getType(ListProperty.class), CLASS_TYPE), true); + methodVisitor.visitMethodInsn(Opcodes.INVOKEINTERFACE, OBJECT_FACTORY_TYPE.getInternalName(), "listProperty", RETURN_LIST_PROPERTY_FROM_CLASS, true); } else if (property.getType().equals(SetProperty.class)) { // GENERATE objectFactory.setProperty(type) Class elementType = (Class) ((ParameterizedType) property.getGenericType()).getActualTypeArguments()[0]; methodVisitor.visitLdcInsn(Type.getType(elementType)); - methodVisitor.visitMethodInsn(Opcodes.INVOKEINTERFACE, OBJECT_FACTORY_TYPE.getInternalName(), "setProperty", Type.getMethodDescriptor(Type.getType(SetProperty.class), CLASS_TYPE), true); + methodVisitor.visitMethodInsn(Opcodes.INVOKEINTERFACE, OBJECT_FACTORY_TYPE.getInternalName(), "setProperty", RETURN_SET_PROPERTY_FROM_CLASS, true); } else if (property.getType().equals(MapProperty.class)) { // GENERATE objectFactory.setProperty(type) Class keyType = (Class) ((ParameterizedType) property.getGenericType()).getActualTypeArguments()[0]; Class elementType = (Class) ((ParameterizedType) property.getGenericType()).getActualTypeArguments()[1]; methodVisitor.visitLdcInsn(Type.getType(keyType)); methodVisitor.visitLdcInsn(Type.getType(elementType)); - methodVisitor.visitMethodInsn(Opcodes.INVOKEINTERFACE, OBJECT_FACTORY_TYPE.getInternalName(), "mapProperty", Type.getMethodDescriptor(Type.getType(MapProperty.class), CLASS_TYPE, CLASS_TYPE), true); + methodVisitor.visitMethodInsn(Opcodes.INVOKEINTERFACE, OBJECT_FACTORY_TYPE.getInternalName(), "mapProperty", RETURN_MAP_PROPERTY_FROM_CLASS_CLASS, true); } else { throw new IllegalArgumentException(); } @@ -1034,6 +1047,15 @@ private void addSetterForProperty(PropertyMetaData property, Method setter) { methodVisitor.visitEnd(); } + private void generatePublicTypeMethod() { + // Generate: Class publicType() { ... } + MethodVisitor methodVisitor = visitor.visitMethod(ACC_PUBLIC, "publicType", RETURN_CLASS, null, EMPTY_STRINGS); + methodVisitor.visitLdcInsn(superclassType); + methodVisitor.visitInsn(ARETURN); + methodVisitor.visitMaxs(0, 0); + methodVisitor.visitEnd(); + } + @Override public void addManagedMethods(List mutableProperties, List readOnlyProperties) { visitor.visitField(PV_FINAL_STATIC, FACTORY_FIELD, Type.getType(Managed.Factory.class).getDescriptor(), null, null); @@ -1070,13 +1092,6 @@ public void addManagedMethods(List mutableProperties, List && } methodVisitor = visitor.visitMethod(ACC_PUBLIC, "immutable", RETURN_BOOLEAN, null, EMPTY_STRINGS); // Could return true if all of the read only properties point to immutable objects, but at this stage there are no such types supported diff --git a/subprojects/model-core/src/test/groovy/org/gradle/internal/instantiation/AsmBackedClassGeneratorTest.java b/subprojects/model-core/src/test/groovy/org/gradle/internal/instantiation/AsmBackedClassGeneratorTest.java index 6aefd148b3e34..f1ea4c472234b 100755 --- a/subprojects/model-core/src/test/groovy/org/gradle/internal/instantiation/AsmBackedClassGeneratorTest.java +++ b/subprojects/model-core/src/test/groovy/org/gradle/internal/instantiation/AsmBackedClassGeneratorTest.java @@ -26,6 +26,7 @@ import org.gradle.api.file.RegularFileProperty; import org.gradle.api.internal.ConventionMapping; import org.gradle.api.internal.DynamicObjectAware; +import org.gradle.api.internal.GeneratedSubclass; import org.gradle.api.internal.GeneratedSubclasses; import org.gradle.api.internal.HasConvention; import org.gradle.api.internal.IConventionAware; @@ -129,10 +130,19 @@ private T newInstance(Class clazz, ServiceRegistry services, Object... ar } @Test - public void mixesInGeneratedSubclassInterface() { - Class generatedClass = generator.generate(Bean.class).getGeneratedClass(); - assertEquals(GeneratedSubclasses.unpack(generatedClass), Bean.class); - assertEquals(Bean.class, GeneratedSubclasses.unpack(generatedClass)); + public void mixesInGeneratedSubclassInterface() throws Exception { + Bean bean = newInstance(Bean.class); + assertTrue(bean instanceof GeneratedSubclass); + assertEquals(Bean.class, ((GeneratedSubclass)bean).publicType()); + assertEquals(Bean.class, GeneratedSubclasses.unpack(bean)); + } + + @Test + public void mixesInGeneratedSubclassInterfaceToInterface() throws Exception { + InterfaceWithDefaultMethods bean = newInstance(InterfaceWithDefaultMethods.class); + assertTrue(bean instanceof GeneratedSubclass); + assertEquals(InterfaceWithDefaultMethods.class, ((GeneratedSubclass)bean).publicType()); + assertEquals(InterfaceWithDefaultMethods.class, GeneratedSubclasses.unpack(bean)); } @Test From ef35aa2b89a45b5e99a7a4dbf52aaaac3ccd5bad Mon Sep 17 00:00:00 2001 From: Adam Murdoch Date: Thu, 21 Feb 2019 18:16:07 +1100 Subject: [PATCH 039/853] Handle abstract properties with primitive type in generated classes. --- ...tensionInstantiationIntegrationTest.groovy | 23 +++-- .../AsmBackedClassGenerator.java | 87 +++++++++++-------- ...ackedClassGeneratedManagedStateTest.groovy | 14 +++ .../AsmBackedClassGeneratorTest.java | 26 ++++++ 4 files changed, 110 insertions(+), 40 deletions(-) diff --git a/subprojects/core/src/integTest/groovy/org/gradle/api/ObjectExtensionInstantiationIntegrationTest.groovy b/subprojects/core/src/integTest/groovy/org/gradle/api/ObjectExtensionInstantiationIntegrationTest.groovy index aeaf2af34f507..a4fb7e81aec4c 100644 --- a/subprojects/core/src/integTest/groovy/org/gradle/api/ObjectExtensionInstantiationIntegrationTest.groovy +++ b/subprojects/core/src/integTest/groovy/org/gradle/api/ObjectExtensionInstantiationIntegrationTest.groovy @@ -17,6 +17,7 @@ package org.gradle.api import org.gradle.integtests.fixtures.AbstractIntegrationSpec +import spock.lang.Unroll import javax.inject.Inject @@ -147,23 +148,33 @@ class ObjectExtensionInstantiationIntegrationTest extends AbstractIntegrationSpe failure.assertHasCause("Too many parameters provided for constructor for class Thing. Expected 2, received 3.") } - def "can create instance of interface with mutable property"() { + @Unroll + def "can create instance of interface with mutable property of type #type"() { buildFile << """ interface Thing { - String getValue() - void setValue(String value) + ${type} getValue() + void setValue(${type} value) } extensions.create("thing", Thing) - assert thing.value == null + assert thing.value == ${defaultValue} thing { - value = "123" + value = ${newValue} } - assert thing.value == "123" + assert thing.value == ${newValue} """ expect: succeeds() + + where: + type | defaultValue | newValue + "String" | null | "'123'" + "List" | null | "['a', 'b', 'c']" + "boolean" | false | true + "Boolean" | null | true + "int" | 0 | 12 + "Integer" | null | 12 } def "can create instance of interface with read-only ConfigurableFileCollection property"() { diff --git a/subprojects/model-core/src/main/java/org/gradle/internal/instantiation/AsmBackedClassGenerator.java b/subprojects/model-core/src/main/java/org/gradle/internal/instantiation/AsmBackedClassGenerator.java index 9ed06886fa4c4..537110bd3f28b 100644 --- a/subprojects/model-core/src/main/java/org/gradle/internal/instantiation/AsmBackedClassGenerator.java +++ b/subprojects/model-core/src/main/java/org/gradle/internal/instantiation/AsmBackedClassGenerator.java @@ -313,6 +313,7 @@ private static class ClassBuilderImpl implements ClassGenerationVisitor { private static final Type LIST_PROPERTY_TYPE = Type.getType(ListProperty.class); private static final Type SET_PROPERTY_TYPE = Type.getType(SetProperty.class); private static final Type MAP_PROPERTY = Type.getType(MapProperty.class); + private static final Type EXTENSION_CONTAINER_TYPE = Type.getType(ExtensionContainer.class); private static final String RETURN_VOID_FROM_OBJECT = Type.getMethodDescriptor(Type.VOID_TYPE, OBJECT_TYPE); private static final String RETURN_VOID_FROM_OBJECT_CLASS_DYNAMIC_OBJECT_INSTANTIATOR = Type.getMethodDescriptor(Type.VOID_TYPE, OBJECT_TYPE, CLASS_TYPE, DYNAMIC_OBJECT_TYPE, INSTANTIATOR_TYPE); @@ -324,7 +325,7 @@ private static class ClassBuilderImpl implements ClassGenerationVisitor { private static final String RETURN_CONVENTION = Type.getMethodDescriptor(CONVENTION_TYPE); private static final String RETURN_CONVENTION_MAPPING = Type.getMethodDescriptor(CONVENTION_MAPPING_TYPE); private static final String RETURN_OBJECT = Type.getMethodDescriptor(OBJECT_TYPE); - private static final String RETURN_EXTENSION_CONTAINER = Type.getMethodDescriptor(Type.getType(ExtensionContainer.class)); + private static final String RETURN_EXTENSION_CONTAINER = Type.getMethodDescriptor(EXTENSION_CONTAINER_TYPE); private static final String RETURN_OBJECT_FROM_STRING = Type.getMethodDescriptor(OBJECT_TYPE, STRING_TYPE); private static final String RETURN_OBJECT_FROM_STRING_OBJECT = Type.getMethodDescriptor(OBJECT_TYPE, STRING_TYPE, OBJECT_TYPE); private static final String RETURN_VOID_FROM_STRING_OBJECT = Type.getMethodDescriptor(Type.VOID_TYPE, STRING_TYPE, OBJECT_TYPE); @@ -488,7 +489,7 @@ private void initializeFields(MethodVisitor methodVisitor) { public void addExtensionsProperty() { // GENERATE public ExtensionContainer getExtensions() { return getConvention(); } - addGetter("getExtensions", RETURN_EXTENSION_CONTAINER, null, new MethodCodeBody() { + addGetter("getExtensions", EXTENSION_CONTAINER_TYPE, RETURN_EXTENSION_CONTAINER, null, new MethodCodeBody() { public void add(MethodVisitor visitor) { // GENERATE getConvention() @@ -518,7 +519,7 @@ public void mixInDynamicAware() { // GENERATE public Convention getConvention() { return getAsDynamicObject().getConvention(); } - addGetter("getConvention", RETURN_CONVENTION, null, new MethodCodeBody() { + addGetter("getConvention", CONVENTION_TYPE, RETURN_CONVENTION, null, new MethodCodeBody() { public void add(MethodVisitor visitor) { // GENERATE ((MixInExtensibleDynamicObject)getAsDynamicObject()).getConvention() @@ -543,7 +544,7 @@ public void add(MethodVisitor visitor) { // return dynamicObjectHelper; // } - addLazyGetter("getAsDynamicObject", RETURN_DYNAMIC_OBJECT, null, DYNAMIC_OBJECT_HELPER_FIELD, ABSTRACT_DYNAMIC_OBJECT_TYPE, new MethodCodeBody() { + addLazyGetter("getAsDynamicObject", DYNAMIC_OBJECT_TYPE, RETURN_DYNAMIC_OBJECT, null, DYNAMIC_OBJECT_HELPER_FIELD, ABSTRACT_DYNAMIC_OBJECT_TYPE, new MethodCodeBody() { public void add(MethodVisitor visitor) { generateCreateDynamicObject(visitor); } @@ -631,7 +632,7 @@ public void add(MethodVisitor visitor) { } }; - addLazyGetter("getConventionMapping", RETURN_CONVENTION_MAPPING, null, MAPPING_FIELD, CONVENTION_MAPPING_TYPE, initConventionAwareHelper); + addLazyGetter("getConventionMapping", CONVENTION_MAPPING_TYPE, RETURN_CONVENTION_MAPPING, null, MAPPING_FIELD, CONVENTION_MAPPING_TYPE, initConventionAwareHelper); // END } @@ -666,7 +667,7 @@ public void add(MethodVisitor visitor) { } }; - addLazyGetter("getMetaClass", RETURN_META_CLASS, null, META_CLASS_FIELD, META_CLASS_TYPE, initMetaClass); + addLazyGetter("getMetaClass", META_CLASS_TYPE, RETURN_META_CLASS, null, META_CLASS_FIELD, META_CLASS_TYPE, initMetaClass); // END @@ -716,8 +717,8 @@ public void addPropertySetters(PropertyMetaData property, Method getter) { /** * Adds a getter that returns the value of the given field, initializing it if null using the given code. The code should leave the value on the top of the stack. */ - private void addLazyGetter(String methodName, String methodDescriptor, String signature, final String fieldName, final Type fieldType, final MethodCodeBody initializer) { - addGetter(methodName, methodDescriptor, signature, new MethodCodeBody() { + private void addLazyGetter(String methodName, Type returnType, String methodDescriptor, String signature, final String fieldName, final Type fieldType, final MethodCodeBody initializer) { + addGetter(methodName, returnType, methodDescriptor, signature, new MethodCodeBody() { @Override public void add(MethodVisitor visitor) { // var = this. @@ -743,11 +744,11 @@ public void add(MethodVisitor visitor) { /** * Adds a getter that returns the value that the given code leaves on the top of the stack. */ - private void addGetter(String methodName, String methodDescriptor, String signature, MethodCodeBody body) { + private void addGetter(String methodName, Type returnType, String methodDescriptor, String signature, MethodCodeBody body) { MethodVisitor methodVisitor = visitor.visitMethod(Opcodes.ACC_PUBLIC, methodName, methodDescriptor, signature, EMPTY_STRINGS); methodVisitor.visitCode(); body.add(methodVisitor); - methodVisitor.visitInsn(Opcodes.ARETURN); + methodVisitor.visitInsn(returnType.getOpcode(Opcodes.IRETURN)); methodVisitor.visitMaxs(0, 0); methodVisitor.visitEnd(); } @@ -759,7 +760,7 @@ public void addDynamicMethods() { // GENERATE public Object getProperty(String name) { return getAsDynamicObject().getProperty(name); } - addGetter("getProperty", RETURN_OBJECT_FROM_STRING, null, new MethodCodeBody() { + addGetter("getProperty", OBJECT_TYPE, RETURN_OBJECT_FROM_STRING, null, new MethodCodeBody() { public void add(MethodVisitor methodVisitor) { // GENERATE getAsDynamicObject().getProperty(name); @@ -813,7 +814,7 @@ public void add(MethodVisitor methodVisitor) { // GENERATE public Object invokeMethod(String name, Object params) { return getAsDynamicObject().invokeMethod(name, (Object[])params); } - addGetter("invokeMethod", RETURN_OBJECT_FROM_STRING_OBJECT, null, + addGetter("invokeMethod", OBJECT_TYPE, RETURN_OBJECT_FROM_STRING_OBJECT, null, new MethodCodeBody() { public void add(MethodVisitor methodVisitor) { String invokeMethodDesc = Type.getMethodDescriptor(OBJECT_TYPE, STRING_TYPE, OBJECT_ARRAY_TYPE); @@ -895,7 +896,7 @@ public void applyServiceInjectionToGetter(PropertyMetaData property, final Class String propFieldName = propFieldName(property); String signature = signature(getter); - addLazyGetter(getterName, methodDescriptor, signature, propFieldName, serviceType, new MethodCodeBody() { + addLazyGetter(getterName, returnType, methodDescriptor, signature, propFieldName, serviceType, new MethodCodeBody() { @Override public void add(MethodVisitor methodVisitor) { putServiceRegistryOnStack(methodVisitor); @@ -966,7 +967,8 @@ public void applyManagedStateToProperty(PropertyMetaData property) { public void applyReadOnlyManagedStateToGetter(PropertyMetaData property, Method getter) { // GENERATE public () { if ( == null) { = services.get(ObjectFactory.class).(xxx); } return } Type propType = Type.getType(property.getType()); - addLazyGetter(getter.getName(), Type.getMethodDescriptor(Type.getType(getter.getReturnType())), null, propFieldName(property), propType, methodVisitor -> { + Type returnType = Type.getType(getter.getReturnType()); + addLazyGetter(getter.getName(), returnType, Type.getMethodDescriptor(returnType), null, propFieldName(property), propType, methodVisitor -> { // GENERATE services.get(ObjectFactory.class) putServiceRegistryOnStack(methodVisitor); methodVisitor.visitLdcInsn(OBJECT_FACTORY_TYPE); @@ -1016,7 +1018,7 @@ public void applyManagedStateToGetter(PropertyMetaData property, Method getter) Type returnType = Type.getType(getter.getReturnType()); String methodDescriptor = Type.getMethodDescriptor(returnType); String fieldName = propFieldName(property); - addGetter(getter.getName(), methodDescriptor, null, methodVisitor -> { + addGetter(getter.getName(), returnType, methodDescriptor, null, methodVisitor -> { methodVisitor.visitVarInsn(ALOAD, 0); methodVisitor.visitFieldInsn(GETFIELD, generatedType.getInternalName(), fieldName, returnType.getDescriptor()); }); @@ -1038,7 +1040,7 @@ private void addSetterForProperty(PropertyMetaData property, Method setter) { // this.field = value methodVisitor.visitVarInsn(ALOAD, 0); - methodVisitor.visitVarInsn(ALOAD, 1); + methodVisitor.visitVarInsn(fieldType.getOpcode(Opcodes.ILOAD), 1); methodVisitor.visitFieldInsn(PUTFIELD, generatedType.getInternalName(), propFieldName, fieldType.getDescriptor()); // return @@ -1074,7 +1076,7 @@ public void addManagedMethods(List mutableProperties, List mutableProperties, List mutableProperties, List mutableProperties, List targetClass, Type targetType) { + if (targetClass.isPrimitive()) { // Unbox value + Type boxedType = Type.getType(JavaReflectionUtil.getWrapperTypeForPrimitiveType(targetClass)); methodVisitor.visitTypeInsn(Opcodes.CHECKCAST, boxedType.getInternalName()); - String valueMethodDescriptor = Type.getMethodDescriptor(returnType); - methodVisitor.visitMethodInsn(Opcodes.INVOKEVIRTUAL, boxedType.getInternalName(), getter.getReturnType().getName() + "Value", valueMethodDescriptor, false); + String valueMethodDescriptor = Type.getMethodDescriptor(targetType); + methodVisitor.visitMethodInsn(Opcodes.INVOKEVIRTUAL, boxedType.getInternalName(), targetClass.getName() + "Value", valueMethodDescriptor, false); } else { // Cast to return type methodVisitor.visitTypeInsn(Opcodes.CHECKCAST, - getter.getReturnType().isArray() ? "[" + returnType.getElementType().getDescriptor() - : returnType.getInternalName()); + targetClass.isArray() ? "[" + targetType.getElementType().getDescriptor() + : targetType.getInternalName()); } + } - methodVisitor.visitInsn(returnType.getOpcode(IRETURN)); - methodVisitor.visitMaxs(0, 0); - methodVisitor.visitEnd(); + /** + * Boxes the value at the top of the stack, if primitive + */ + private void maybeBox(MethodVisitor methodVisitor, Class valueClass, Type valueType) { + if (valueClass.isPrimitive()) { + // Box value + Type boxedType = Type.getType(JavaReflectionUtil.getWrapperTypeForPrimitiveType(valueClass)); + String valueOfMethodDescriptor = Type.getMethodDescriptor(boxedType, valueType); + methodVisitor.visitMethodInsn(Opcodes.INVOKESTATIC, boxedType.getInternalName(), "valueOf", valueOfMethodDescriptor, false); + } } public void applyConventionMappingToSetter(PropertyMetaData property, Method setter) { diff --git a/subprojects/model-core/src/test/groovy/org/gradle/internal/instantiation/AsmBackedClassGeneratedManagedStateTest.groovy b/subprojects/model-core/src/test/groovy/org/gradle/internal/instantiation/AsmBackedClassGeneratedManagedStateTest.groovy index f4230f24d8d6e..3a44cd5a0f09e 100644 --- a/subprojects/model-core/src/test/groovy/org/gradle/internal/instantiation/AsmBackedClassGeneratedManagedStateTest.groovy +++ b/subprojects/model-core/src/test/groovy/org/gradle/internal/instantiation/AsmBackedClassGeneratedManagedStateTest.groovy @@ -23,6 +23,7 @@ import org.junit.ClassRule import spock.lang.Shared import spock.lang.Unroll +import static org.gradle.internal.instantiation.AsmBackedClassGeneratorTest.* import static org.gradle.internal.instantiation.AsmBackedClassGeneratorTest.AbstractBean import static org.gradle.internal.instantiation.AsmBackedClassGeneratorTest.AbstractBeanWithInheritedFields import static org.gradle.internal.instantiation.AsmBackedClassGeneratorTest.Bean @@ -125,6 +126,19 @@ class AsmBackedClassGeneratedManagedStateTest extends AbstractClassGeneratorSpec copy2.numbers == [12] as Set } + def canConstructInstanceOfInterfaceWithPrimitivePropertyGetterAndSetter() { + def bean = create(InterfacePrimitiveBean) + + expect: + !bean.prop1 + bean.setProp1(true) + bean.prop1 + + bean.prop2 == 0 + bean.setProp2(12) + bean.prop2 == 12 + } + def canConstructInstanceOfInterfaceWithFileCollectionGetter() { def projectDir = tmpDir.testDirectory def bean = create(InterfaceFileCollectionBean, TestUtil.createRootProject(projectDir).services) diff --git a/subprojects/model-core/src/test/groovy/org/gradle/internal/instantiation/AsmBackedClassGeneratorTest.java b/subprojects/model-core/src/test/groovy/org/gradle/internal/instantiation/AsmBackedClassGeneratorTest.java index f1ea4c472234b..683de491370b8 100755 --- a/subprojects/model-core/src/test/groovy/org/gradle/internal/instantiation/AsmBackedClassGeneratorTest.java +++ b/subprojects/model-core/src/test/groovy/org/gradle/internal/instantiation/AsmBackedClassGeneratorTest.java @@ -1747,6 +1747,32 @@ public interface InterfaceBean { void setNumbers(Set values); } + public interface InterfacePrimitiveBean { + boolean isProp1(); + + void setProp1(boolean value); + + int getProp2(); + + void setProp2(int value); + + byte getProp3(); + + void setProp3(byte value); + + short getProp4(); + + void setProp4(short value); + + long getProp5(); + + void setProp5(long value); + + double getProp6(); + + void setProp6(double value); + } + public interface InterfaceFileCollectionBean { ConfigurableFileCollection getProp(); } From 6e1d441187969989f12b544f517a9a4974c7ee61 Mon Sep 17 00:00:00 2001 From: Bo Zhang Date: Fri, 22 Feb 2019 16:32:27 +0800 Subject: [PATCH 040/853] Revert "Revert to older nightly" This reverts commit 0e71a95e72beccb1a56a11fe8f93b7529245ec16. --- gradle/wrapper/gradle-wrapper.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 0d9e4b132016f..b8c688d471fb7 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions-snapshots/gradle-5.3-20190218000054+0000-bin.zip +distributionUrl=https\://services.gradle.org/distributions-snapshots/gradle-5.3-20190220000051+0000-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists From f39f5da6146d38754a2703e5356df92c94bdacfa Mon Sep 17 00:00:00 2001 From: Louis Jacomet Date: Thu, 21 Feb 2019 17:27:40 +0100 Subject: [PATCH 041/853] Test coverage for dependencySubstitution This commit add tests showing the impact of adding all or substitute rules. --- .../DefaultDependencySubstitutionsSpec.groovy | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/dependencysubstitution/DefaultDependencySubstitutionsSpec.groovy b/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/dependencysubstitution/DefaultDependencySubstitutionsSpec.groovy index e03604a18b283..807f378da475b 100644 --- a/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/dependencysubstitution/DefaultDependencySubstitutionsSpec.groovy +++ b/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/dependencysubstitution/DefaultDependencySubstitutionsSpec.groovy @@ -19,6 +19,7 @@ package org.gradle.api.internal.artifacts.ivyservice.dependencysubstitution import org.gradle.api.Action import org.gradle.api.InvalidUserDataException import org.gradle.api.artifacts.component.ComponentSelector +import org.gradle.api.artifacts.component.ProjectComponentSelector import org.gradle.api.internal.artifacts.ComponentSelectorConverter import org.gradle.api.internal.artifacts.DefaultImmutableModuleIdentifierFactory import org.gradle.api.internal.artifacts.DefaultModuleIdentifier @@ -260,4 +261,43 @@ class DefaultDependencySubstitutionsSpec extends Specification { then: 0 * validator.validateMutation(_) } + + def "registering an all rule toggles the hasRule flag"() { + given: + def action = Mock(Action) + + when: + substitutions.all(action) + + then: + substitutions.hasRules() + } + + @Unroll + def "registering a substitute rule with (#from, #to) causes hasRule #result"() { + given: + componentIdentifierFactory.createProjectComponentSelector(_) >> Mock(ProjectComponentSelector) + def fromComponent = createComponent(from) + def toComponent = createComponent(to) + + when: + substitutions.substitute(fromComponent).with(toComponent) + + then: + substitutions.hasRules() == result + + where: + from | to | result + "org:test" | ":foo" | true + ":bar" | "org:test:1.0" | true + "org:test" | "org:foo:1.0" | true + } + + ComponentSelector createComponent(String componentNotation) { + if (componentNotation.startsWith(":")) { + return substitutions.project(componentNotation) + } else { + return substitutions.module(componentNotation) + } + } } From 0b3a9903d3d88b020fcb1954ef17dde1d1b9096f Mon Sep 17 00:00:00 2001 From: Louis Jacomet Date: Thu, 21 Feb 2019 20:38:35 +0100 Subject: [PATCH 042/853] Less build dependencies resolution When substitutions are used, projects dependencies can appear anywhere in the dependency graph. This forces Gradle to resolve the configurations during the build configuration phase. With this commit, substitutions that do not involve a project no longer cause this early resolution. --- ...dencySubstitutionRulesIntegrationTest.groovy | 2 +- .../DefaultDependencySubstitutions.java | 17 +++++++++++++++-- .../DefaultDependencySubstitutionsSpec.groovy | 2 +- 3 files changed, 17 insertions(+), 4 deletions(-) diff --git a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/DependencySubstitutionRulesIntegrationTest.groovy b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/DependencySubstitutionRulesIntegrationTest.groovy index 4cb058ed222e9..a25899434a229 100644 --- a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/DependencySubstitutionRulesIntegrationTest.groovy +++ b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/DependencySubstitutionRulesIntegrationTest.groovy @@ -1052,7 +1052,7 @@ class DependencySubstitutionRulesIntegrationTest extends AbstractIntegrationSpec fails "checkDeps" then: - failure.assertHasCause("Could not resolve all task dependencies for configuration ':conf'.") + failure.assertHasCause("Could not resolve all dependencies for configuration ':conf'.") failure.assertHasCause("Could not find org.utils:api:1.123.15") } diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/dependencysubstitution/DefaultDependencySubstitutions.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/dependencysubstitution/DefaultDependencySubstitutions.java index 1ca8ca290894c..c7cc22743d1df 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/dependencysubstitution/DefaultDependencySubstitutions.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/dependencysubstitution/DefaultDependencySubstitutions.java @@ -104,6 +104,13 @@ public Action getRuleAction() { return Actions.composite(substitutionRules); } + private void addSubstitution(Action rule, boolean projectInvolved) { + addRule(rule); + if (projectInvolved) { + hasDependencySubstitutionRule = true; + } + } + private void addRule(Action rule) { mutationValidator.validateMutation(MutationValidator.MutationType.STRATEGY); substitutionRules.add(rule); @@ -146,6 +153,12 @@ public Substitution because(String description) { public void with(ComponentSelector substitute) { DefaultDependencySubstitution.validateTarget(substitute); + boolean projectInvolved = false; + if (substituted instanceof ProjectComponentSelector || substitute instanceof ProjectComponentSelector) { + // A project is involved, need to be aware of it + projectInvolved = true; + } + if (substituted instanceof UnversionedModuleComponentSelector) { final ModuleIdentifier moduleId = ((UnversionedModuleComponentSelector) substituted).getModuleIdentifier(); if (substitute instanceof ModuleComponentSelector) { @@ -154,9 +167,9 @@ public void with(ComponentSelector substitute) { substitutionReason = substitutionReason.markAsEquivalentToForce(); } } - all(new ModuleMatchDependencySubstitutionAction(substitutionReason, moduleId, substitute)); + addSubstitution(new ModuleMatchDependencySubstitutionAction(substitutionReason, moduleId, substitute), projectInvolved); } else { - all(new ExactMatchDependencySubstitutionAction(substitutionReason, substituted, substitute)); + addSubstitution(new ExactMatchDependencySubstitutionAction(substitutionReason, substituted, substitute), projectInvolved); } } }; diff --git a/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/dependencysubstitution/DefaultDependencySubstitutionsSpec.groovy b/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/dependencysubstitution/DefaultDependencySubstitutionsSpec.groovy index 807f378da475b..be7e5d1320c5e 100644 --- a/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/dependencysubstitution/DefaultDependencySubstitutionsSpec.groovy +++ b/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/dependencysubstitution/DefaultDependencySubstitutionsSpec.groovy @@ -290,7 +290,7 @@ class DefaultDependencySubstitutionsSpec extends Specification { from | to | result "org:test" | ":foo" | true ":bar" | "org:test:1.0" | true - "org:test" | "org:foo:1.0" | true + "org:test" | "org:foo:1.0" | false } ComponentSelector createComponent(String componentNotation) { From a53620d8ed52814018f5283856d23564a83ce3a9 Mon Sep 17 00:00:00 2001 From: Stefan Wolf Date: Fri, 22 Feb 2019 12:53:45 +0100 Subject: [PATCH 043/853] Fix typo --- ...ultExecutionGraphDependenciesResolver.java | 2 +- .../TransformationMatchingSpec.groovy | 26 +++++++++---------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultExecutionGraphDependenciesResolver.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultExecutionGraphDependenciesResolver.java index f615e6354423e..bdbc5bfb592eb 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultExecutionGraphDependenciesResolver.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultExecutionGraphDependenciesResolver.java @@ -45,7 +45,7 @@ public class DefaultExecutionGraphDependenciesResolver implements ExecutionGraph private static final ArtifactTransformDependencies MISSING_DEPENDENCIES = new ArtifactTransformDependencies() { @Override public FileCollection getFiles() { - throw new IllegalStateException("Tranform does not use artifact dependencies."); + throw new IllegalStateException("Transform does not use artifact dependencies."); } @Override diff --git a/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/TransformationMatchingSpec.groovy b/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/TransformationMatchingSpec.groovy index c5ea15dc7e006..95c8976972b91 100644 --- a/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/TransformationMatchingSpec.groovy +++ b/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/TransformationMatchingSpec.groovy @@ -22,8 +22,8 @@ class TransformationMatchingSpec extends Specification { def "different TransformationStep does not contain each other"() { given: - def step1 = new TransformationStep(Mock(Transformer), Mock(TransformerInvoker)) - def step2 = new TransformationStep(Mock(Transformer), Mock(TransformerInvoker)) + def step1 = new TransformationStep(Mock(Transformer), Mock(TransformerInvoker), projectStateHandler) + def step2 = new TransformationStep(Mock(Transformer), Mock(TransformerInvoker), projectStateHandler) expect: !step1.endsWith(step2) @@ -32,7 +32,7 @@ class TransformationMatchingSpec extends Specification { def "TransformationStep contains itself"() { given: - def step = new TransformationStep(Mock(Transformer), Mock(TransformerInvoker)) + def step = new TransformationStep(Mock(Transformer), Mock(TransformerInvoker), projectStateHandler) expect: step.endsWith(step) @@ -40,8 +40,8 @@ class TransformationMatchingSpec extends Specification { def "chain contains its final step"() { given: - def step1 = new TransformationStep(Mock(Transformer), Mock(TransformerInvoker)) - def step2 = new TransformationStep(Mock(Transformer), Mock(TransformerInvoker)) + def step1 = new TransformationStep(Mock(Transformer), Mock(TransformerInvoker), projectStateHandler) + def step2 = new TransformationStep(Mock(Transformer), Mock(TransformerInvoker), projectStateHandler) def chain = new TransformationChain(step1, step2) expect: @@ -54,8 +54,8 @@ class TransformationMatchingSpec extends Specification { def "chain contains itself"() { given: - def step1 = new TransformationStep(Mock(Transformer), Mock(TransformerInvoker)) - def step2 = new TransformationStep(Mock(Transformer), Mock(TransformerInvoker)) + def step1 = new TransformationStep(Mock(Transformer), Mock(TransformerInvoker), projectStateHandler) + def step2 = new TransformationStep(Mock(Transformer), Mock(TransformerInvoker), projectStateHandler) def chain = new TransformationChain(step1, step2) expect: @@ -64,9 +64,9 @@ class TransformationMatchingSpec extends Specification { def "longer chain contains shorter chain"() { given: - def step1 = new TransformationStep(Mock(Transformer), Mock(TransformerInvoker)) - def step2 = new TransformationStep(Mock(Transformer), Mock(TransformerInvoker)) - def step3 = new TransformationStep(Mock(Transformer), Mock(TransformerInvoker)) + def step1 = new TransformationStep(Mock(Transformer), Mock(TransformerInvoker), projectStateHandler) + def step2 = new TransformationStep(Mock(Transformer), Mock(TransformerInvoker), projectStateHandler) + def step3 = new TransformationStep(Mock(Transformer), Mock(TransformerInvoker), projectStateHandler) def subChain = new TransformationChain(step2, step3) def longChain = new TransformationChain(new TransformationChain(step1, step2), step3) @@ -77,9 +77,9 @@ class TransformationMatchingSpec extends Specification { def "different chains do not contain each other"() { given: - def step1 = new TransformationStep(Mock(Transformer), Mock(TransformerInvoker)) - def step2 = new TransformationStep(Mock(Transformer), Mock(TransformerInvoker)) - def step3 = new TransformationStep(Mock(Transformer), Mock(TransformerInvoker)) + def step1 = new TransformationStep(Mock(Transformer), Mock(TransformerInvoker), projectStateHandler) + def step2 = new TransformationStep(Mock(Transformer), Mock(TransformerInvoker), projectStateHandler) + def step3 = new TransformationStep(Mock(Transformer), Mock(TransformerInvoker), projectStateHandler) def chain1 = new TransformationChain(step2, step3) def chain2 = new TransformationChain(step1, step2) def chain3 = new TransformationChain(step1, step3) From 854319d48974b95a95c6006bc453b67b56ebf343 Mon Sep 17 00:00:00 2001 From: Stefan Wolf Date: Fri, 22 Feb 2019 14:21:19 +0100 Subject: [PATCH 044/853] Move isolation orchestration to TransformationStep --- ...aultTransformationRegistrationFactory.java | 5 +- .../transform/DefaultTransformer.java | 52 +++--------------- .../DomainObjectProjectStateHandler.java | 3 +- .../transform/LegacyTransformer.java | 5 ++ .../transform/TransformationStep.java | 55 +++++++++++++++++-- .../artifacts/transform/Transformer.java | 2 + .../DefaultTransformerInvokerTest.groovy | 5 ++ 7 files changed, 76 insertions(+), 51 deletions(-) diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformationRegistrationFactory.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformationRegistrationFactory.java index 209d9a2891cba..d496a3ba64b16 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformationRegistrationFactory.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformationRegistrationFactory.java @@ -131,16 +131,15 @@ public ArtifactTransformRegistration create(ImmutableAttributes from, ImmutableA fileCollectionFactory, fileCollectionFingerprinterRegistry, parametersPropertyWalker, - domainObjectProjectStateHandler, actionInstantiationScheme); - return new DefaultArtifactTransformRegistration(from, to, new TransformationStep(transformer, transformerInvoker)); + return new DefaultArtifactTransformRegistration(from, to, new TransformationStep(transformer, transformerInvoker, domainObjectProjectStateHandler)); } @Override public ArtifactTransformRegistration create(ImmutableAttributes from, ImmutableAttributes to, Class implementation, Object[] params) { Transformer transformer = new LegacyTransformer(implementation, params, legacyActionInstantiationScheme, from, classLoaderHierarchyHasher, isolatableFactory); - return new DefaultArtifactTransformRegistration(from, to, new TransformationStep(transformer, transformerInvoker)); + return new DefaultArtifactTransformRegistration(from, to, new TransformationStep(transformer, transformerInvoker, domainObjectProjectStateHandler)); } private static class DefaultArtifactTransformRegistration implements ArtifactTransformRegistration { diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformer.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformer.java index a50896ff0161a..c58dbeec32d35 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformer.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformer.java @@ -20,7 +20,6 @@ import com.google.common.collect.ImmutableSortedMap; import com.google.common.reflect.TypeToken; import org.gradle.api.InvalidUserDataException; -import org.gradle.api.Project; import org.gradle.api.artifacts.transform.InputArtifact; import org.gradle.api.artifacts.transform.InputArtifactDependencies; import org.gradle.api.artifacts.transform.TransformAction; @@ -30,9 +29,7 @@ import org.gradle.api.internal.attributes.ImmutableAttributes; import org.gradle.api.internal.file.FileCollectionFactory; import org.gradle.api.internal.plugins.DslObject; -import org.gradle.api.internal.project.ProjectStateRegistry; import org.gradle.api.internal.tasks.TaskDependencyResolveContext; -import org.gradle.api.internal.tasks.WorkNodeAction; import org.gradle.api.internal.tasks.properties.DefaultParameterValidationContext; import org.gradle.api.internal.tasks.properties.FileParameterUtils; import org.gradle.api.internal.tasks.properties.InputFilePropertyType; @@ -86,9 +83,6 @@ public class DefaultTransformer extends AbstractTransformer { private final PropertyWalker parameterPropertyWalker; private final boolean requiresDependencies; private final InstanceFactory instanceFactory; - private final DomainObjectProjectStateHandler projectStateHandler; - private final ProjectStateRegistry.SafeExclusiveLock isolationLock; - private final WorkNodeAction isolateAction; private final boolean cacheable; private IsolatableParameters isolatable; @@ -106,7 +100,6 @@ public DefaultTransformer( FileCollectionFactory fileCollectionFactory, FileCollectionFingerprinterRegistry fileCollectionFingerprinterRegistry, PropertyWalker parameterPropertyWalker, - DomainObjectProjectStateHandler projectStateHandler, InstantiationScheme actionInstantiationScheme ) { super(implementationClass, fromAttributes); @@ -122,20 +115,6 @@ public DefaultTransformer( this.instanceFactory = actionInstantiationScheme.forType(implementationClass); this.requiresDependencies = instanceFactory.serviceInjectionTriggeredByAnnotation(InputArtifactDependencies.class); this.cacheable = cacheable; - this.projectStateHandler = projectStateHandler; - this.isolationLock = projectStateHandler.newExclusiveOperationLock(); - this.isolateAction = parameterObject == null ? null : new WorkNodeAction() { - @Nullable - @Override - public Project getProject() { - return projectStateHandler.maybeGetOwningProject(); - } - - @Override - public void run() { - isolateExclusively(); - } - }; } public static void validateInputFileNormalizer(String propertyName, @Nullable Class normalizer, boolean cacheable, ParameterValidationContext parameterValidationContext) { @@ -159,6 +138,11 @@ public Class getInputArtifactDependenciesNormalizer() return dependenciesNormalizer; } + @Override + public boolean isIsolated() { + return isolatable != null; + } + public boolean requiresDependencies() { return requiresDependencies; } @@ -183,9 +167,6 @@ public ImmutableList transform(File inputArtifact, File outputDir, Artifac @Override public void visitDependencies(TaskDependencyResolveContext context) { - if (isolateAction != null) { - context.add(isolateAction); - } if (parameterObject != null) { parameterPropertyWalker.visitProperties(parameterObject, ParameterValidationContext.NOOP, new PropertyVisitor.Adapter() { @Override @@ -198,28 +179,13 @@ public void visitInputFileProperty(String propertyName, boolean optional, boolea @Override public void isolateParameters() { - if (isolatable == null) { - if (!projectStateHandler.hasMutableProjectState()) { - projectStateHandler.withLenientState(this::isolateExclusively); - } else { - isolateExclusively(); - } + try { + isolatable = doIsolateParameters(); + } catch (Exception e) { + throw new VariantTransformConfigurationException(String.format("Cannot isolate parameters %s of artifact transform %s", parameterObject, ModelType.of(getImplementationClass()).getDisplayName()), e); } } - private void isolateExclusively() { - isolationLock.withLock(() -> { - if (isolatable != null) { - return; - } - try { - isolatable = doIsolateParameters(); - } catch (Exception e) { - throw new VariantTransformConfigurationException(String.format("Cannot isolate parameters %s of artifact transform %s", parameterObject, ModelType.of(getImplementationClass()).getDisplayName()), e); - } - }); - } - protected IsolatableParameters doIsolateParameters() { Isolatable isolatableParameterObject = isolatableFactory.isolate(parameterObject); diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DomainObjectProjectStateHandler.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DomainObjectProjectStateHandler.java index 7af30f6bc7525..17e70bc8b0641 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DomainObjectProjectStateHandler.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DomainObjectProjectStateHandler.java @@ -19,6 +19,7 @@ import org.gradle.api.Project; import org.gradle.api.internal.DomainObjectContext; import org.gradle.api.internal.artifacts.dsl.dependencies.ProjectFinder; +import org.gradle.api.internal.project.ProjectInternal; import org.gradle.api.internal.project.ProjectState; import org.gradle.api.internal.project.ProjectStateRegistry; @@ -37,7 +38,7 @@ public DomainObjectProjectStateHandler(ProjectStateRegistry projectStateRegistry } @Nullable - public Project maybeGetOwningProject() { + public ProjectInternal maybeGetOwningProject() { if (domainObjectContext.getProjectPath() != null) { return projectFinder.findProject(domainObjectContext.getProjectPath().getPath()); } else { diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/LegacyTransformer.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/LegacyTransformer.java index 521cf02b80d91..bf855dcaf61fd 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/LegacyTransformer.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/LegacyTransformer.java @@ -93,6 +93,11 @@ public Class getInputArtifactDependenciesNormalizer() return AbsolutePathInputNormalizer.class; } + @Override + public boolean isIsolated() { + return true; + } + @Override public void visitDependencies(TaskDependencyResolveContext context) { } diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/TransformationStep.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/TransformationStep.java index f4c7cb786601d..44998ae8784fe 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/TransformationStep.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/TransformationStep.java @@ -19,12 +19,17 @@ import com.google.common.base.Equivalence; import com.google.common.collect.ImmutableList; import org.gradle.api.Action; +import org.gradle.api.Project; import org.gradle.api.internal.attributes.ImmutableAttributes; +import org.gradle.api.internal.project.ProjectStateRegistry; import org.gradle.api.internal.tasks.TaskDependencyContainer; +import org.gradle.api.internal.tasks.TaskDependencyResolveContext; +import org.gradle.api.internal.tasks.WorkNodeAction; import org.gradle.internal.Try; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import javax.annotation.Nullable; import java.io.File; /** @@ -32,17 +37,33 @@ * * Transforms a subject by invoking a transformer on each of the subjects files. */ -public class TransformationStep implements Transformation { +public class TransformationStep implements Transformation, TaskDependencyContainer { private static final Logger LOGGER = LoggerFactory.getLogger(TransformationStep.class); public static final Equivalence FOR_SCHEDULING = Equivalence.identity(); - private final Transformer transformer; private final TransformerInvoker transformerInvoker; + private final DomainObjectProjectStateHandler projectStateHandler; + private final ProjectStateRegistry.SafeExclusiveLock isolationLock; + private final WorkNodeAction isolateAction; - public TransformationStep(Transformer transformer, TransformerInvoker transformerInvoker) { + public TransformationStep(Transformer transformer, TransformerInvoker transformerInvoker, DomainObjectProjectStateHandler projectStateHandler) { this.transformer = transformer; this.transformerInvoker = transformerInvoker; + this.projectStateHandler = projectStateHandler; + this.isolationLock = projectStateHandler.newExclusiveOperationLock(); + this.isolateAction = transformer.isIsolated() ? null : new WorkNodeAction() { + @Nullable + @Override + public Project getProject() { + return projectStateHandler.maybeGetOwningProject(); + } + + @Override + public void run() { + isolateExclusively(); + } + }; } @Override @@ -61,7 +82,7 @@ public Try transform(TransformationSubject subjectToTrans LOGGER.info("Transforming {} with {}", subjectToTransform.getDisplayName(), transformer.getDisplayName()); } ImmutableList inputArtifacts = subjectToTransform.getFiles(); - transformer.isolateParameters(); + isolateTransformerParameters(); return dependenciesResolver.forTransformer(transformer).flatMap(dependencies -> { ImmutableList.Builder builder = ImmutableList.builder(); for (File inputArtifact : inputArtifacts) { @@ -76,6 +97,24 @@ public Try transform(TransformationSubject subjectToTrans }); } + private void isolateTransformerParameters() { + if (!transformer.isIsolated()) { + if (!projectStateHandler.hasMutableProjectState()) { + projectStateHandler.withLenientState(this::isolateExclusively); + } else { + isolateExclusively(); + } + } + } + + private void isolateExclusively() { + isolationLock.withLock(() -> { + if (!transformer.isIsolated()) { + transformer.isolateParameters(); + } + }); + } + @Override public boolean requiresDependencies() { return transformer.requiresDependencies(); @@ -103,4 +142,12 @@ public String toString() { public TaskDependencyContainer getDependencies() { return transformer; } + + @Override + public void visitDependencies(TaskDependencyResolveContext context) { + if (!transformer.isIsolated()) { + context.add(isolateAction); + } + transformer.visitDependencies(context); + } } diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/Transformer.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/Transformer.java index 96a4ac8384097..ebefd9b24a727 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/Transformer.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/Transformer.java @@ -60,4 +60,6 @@ public interface Transformer extends Describable, TaskDependencyContainer { Class getInputArtifactNormalizer(); Class getInputArtifactDependenciesNormalizer(); + + boolean isIsolated(); } diff --git a/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvokerTest.groovy b/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvokerTest.groovy index 3aafa89d76bc4..351a9680845af 100644 --- a/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvokerTest.groovy +++ b/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvokerTest.groovy @@ -151,6 +151,11 @@ class DefaultTransformerInvokerTest extends AbstractProjectBuilderSpec { return AbsolutePathInputNormalizer } + @Override + boolean isIsolated() { + return true + } + @Override void isolateParameters() { } From 9639cb6016ea9e5e2dd3c3cf3fdb2d80f0f05a18 Mon Sep 17 00:00:00 2001 From: Stefan Wolf Date: Fri, 22 Feb 2019 14:50:56 +0100 Subject: [PATCH 045/853] Pass fingerprinterRegistry into invoker --- .../DefaultDependencyManagementServices.java | 2 -- ...aultTransformationRegistrationFactory.java | 4 +-- .../transform/DefaultTransformerInvoker.java | 13 +++----- .../artifacts/transform/Transformation.java | 5 ++- .../transform/TransformationChain.java | 7 ++-- .../transform/TransformationNode.java | 11 ++++--- .../transform/TransformationNodeExecutor.java | 2 +- .../transform/TransformationOperation.java | 2 +- .../transform/TransformationStep.java | 16 ++++++--- .../transform/TransformerInvoker.java | 3 +- ...efaultVersionedComponentChooserTest.groovy | 2 +- .../transform/ChainedTransformerTest.groovy | 7 ++-- .../ConsumerProvidedVariantFinderTest.groovy | 4 +-- .../DefaultArtifactTransformsTest.groovy | 4 +-- .../DefaultTransformerInvokerTest.groovy | 33 +++++++++---------- .../TransformationMatchingSpec.groovy | 30 +++++++++-------- ...ansformingAsyncArtifactListenerTest.groovy | 2 +- 17 files changed, 79 insertions(+), 68 deletions(-) diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/DefaultDependencyManagementServices.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/DefaultDependencyManagementServices.java index 6d43eafc6760c..72bbdaf2bba57 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/DefaultDependencyManagementServices.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/DefaultDependencyManagementServices.java @@ -258,7 +258,6 @@ TransformerInvoker createTransformerInvoker(WorkExecutor workExe FileSystemSnapshotter fileSystemSnapshotter, ImmutableCachingTransformationWorkspaceProvider transformationWorkspaceProvider, ArtifactTransformListener artifactTransformListener, - FileCollectionFingerprinterRegistry fileCollectionFingerprinterRegistry, FileCollectionFactory fileCollectionFactory, ClassLoaderHierarchyHasher classLoaderHierarchyHasher, ProjectFinder projectFinder, @@ -268,7 +267,6 @@ TransformerInvoker createTransformerInvoker(WorkExecutor workExe fileSystemSnapshotter, artifactTransformListener, transformationWorkspaceProvider, - fileCollectionFingerprinterRegistry, fileCollectionFactory, classLoaderHierarchyHasher, projectFinder, diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformationRegistrationFactory.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformationRegistrationFactory.java index d496a3ba64b16..81ec979dc8851 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformationRegistrationFactory.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformationRegistrationFactory.java @@ -133,13 +133,13 @@ public ArtifactTransformRegistration create(ImmutableAttributes from, ImmutableA parametersPropertyWalker, actionInstantiationScheme); - return new DefaultArtifactTransformRegistration(from, to, new TransformationStep(transformer, transformerInvoker, domainObjectProjectStateHandler)); + return new DefaultArtifactTransformRegistration(from, to, new TransformationStep(transformer, transformerInvoker, domainObjectProjectStateHandler, fileCollectionFingerprinterRegistry)); } @Override public ArtifactTransformRegistration create(ImmutableAttributes from, ImmutableAttributes to, Class implementation, Object[] params) { Transformer transformer = new LegacyTransformer(implementation, params, legacyActionInstantiationScheme, from, classLoaderHierarchyHasher, isolatableFactory); - return new DefaultArtifactTransformRegistration(from, to, new TransformationStep(transformer, transformerInvoker, domainObjectProjectStateHandler)); + return new DefaultArtifactTransformRegistration(from, to, new TransformationStep(transformer, transformerInvoker, domainObjectProjectStateHandler, fileCollectionFingerprinterRegistry)); } private static class DefaultArtifactTransformRegistration implements ArtifactTransformRegistration { diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvoker.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvoker.java index 792dcaa61dbc6..812f0d58b605c 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvoker.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvoker.java @@ -81,9 +81,7 @@ public class DefaultTransformerInvoker implements TransformerInvoker { private final WorkExecutor workExecutor; private final ArtifactTransformListener artifactTransformListener; private final CachingTransformationWorkspaceProvider immutableTransformationWorkspaceProvider; - private final FileCollectionFingerprinterRegistry fileCollectionFingerprinterRegistry; private final FileCollectionFactory fileCollectionFactory; - private final FileCollectionFingerprinter outputFingerprinter; private final ClassLoaderHierarchyHasher classLoaderHierarchyHasher; private final ProjectFinder projectFinder; private final boolean useTransformationWorkspaces; @@ -92,7 +90,6 @@ public DefaultTransformerInvoker(WorkExecutor workExecutor, FileSystemSnapshotter fileSystemSnapshotter, ArtifactTransformListener artifactTransformListener, CachingTransformationWorkspaceProvider immutableTransformationWorkspaceProvider, - FileCollectionFingerprinterRegistry fileCollectionFingerprinterRegistry, FileCollectionFactory fileCollectionFactory, ClassLoaderHierarchyHasher classLoaderHierarchyHasher, ProjectFinder projectFinder, @@ -101,22 +98,20 @@ public DefaultTransformerInvoker(WorkExecutor workExecutor, this.fileSystemSnapshotter = fileSystemSnapshotter; this.artifactTransformListener = artifactTransformListener; this.immutableTransformationWorkspaceProvider = immutableTransformationWorkspaceProvider; - this.fileCollectionFingerprinterRegistry = fileCollectionFingerprinterRegistry; this.fileCollectionFactory = fileCollectionFactory; this.classLoaderHierarchyHasher = classLoaderHierarchyHasher; this.projectFinder = projectFinder; this.useTransformationWorkspaces = useTransformationWorkspaces; - outputFingerprinter = fileCollectionFingerprinterRegistry.getFingerprinter(OutputNormalizer.class); } @Override - public Try> invoke(Transformer transformer, File inputArtifact, ArtifactTransformDependencies dependencies, TransformationSubject subject) { - FileCollectionFingerprinter dependencyFingerprinter = fileCollectionFingerprinterRegistry.getFingerprinter(transformer.getInputArtifactDependenciesNormalizer()); + public Try> invoke(Transformer transformer, File inputArtifact, ArtifactTransformDependencies dependencies, TransformationSubject subject, FileCollectionFingerprinterRegistry fingerprinterRegistry) { + FileCollectionFingerprinter dependencyFingerprinter = fingerprinterRegistry.getFingerprinter(transformer.getInputArtifactDependenciesNormalizer()); CurrentFileCollectionFingerprint dependenciesFingerprint = dependencies.fingerprint(dependencyFingerprinter); ProjectInternal producerProject = determineProducerProject(subject); CachingTransformationWorkspaceProvider workspaceProvider = determineWorkspaceProvider(producerProject); FileSystemLocationSnapshot inputArtifactSnapshot = fileSystemSnapshotter.snapshot(inputArtifact); - FileCollectionFingerprinter inputArtifactFingerprinter = fileCollectionFingerprinterRegistry.getFingerprinter(transformer.getInputArtifactNormalizer()); + FileCollectionFingerprinter inputArtifactFingerprinter = fingerprinterRegistry.getFingerprinter(transformer.getInputArtifactNormalizer()); String normalizedInputPath = inputArtifactFingerprinter.normalizePath(inputArtifactSnapshot); TransformationWorkspaceIdentity identity = getTransformationIdentity(producerProject, inputArtifactSnapshot, normalizedInputPath, transformer, dependenciesFingerprint); return workspaceProvider.withWorkspace(identity, (identityString, workspace) -> { @@ -134,7 +129,7 @@ public Try> invoke(Transformer transformer, File inputArtifa inputArtifactFingerprint, dependencies, dependenciesFingerprint, - outputFingerprinter + fingerprinterRegistry.getFingerprinter(OutputNormalizer.class) ); UpToDateResult outcome = workExecutor.execute(execution); return execution.getResult(outcome); diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/Transformation.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/Transformation.java index 9a7362e059d34..78fc06ffd93cb 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/Transformation.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/Transformation.java @@ -18,8 +18,11 @@ import org.gradle.api.Action; import org.gradle.api.Describable; +import org.gradle.execution.ProjectExecutionServiceRegistry; import org.gradle.internal.Try; +import javax.annotation.Nullable; + /** * The internal API equivalent of {@link org.gradle.api.artifacts.transform.ArtifactTransform}, which is also aware of our cache infrastructure. * @@ -34,7 +37,7 @@ public interface Transformation extends Describable { /** * Transforms the given input subject. May call the underlying transformer(s) or retrieve a cached value. */ - Try transform(TransformationSubject subjectToTransform, ExecutionGraphDependenciesResolver dependenciesResolver); + Try transform(TransformationSubject subjectToTransform, ExecutionGraphDependenciesResolver dependenciesResolver, @Nullable ProjectExecutionServiceRegistry services); /** * Whether the transformation requires dependencies of the transformed artifact to be injected. diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/TransformationChain.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/TransformationChain.java index 1aa66fc8cf815..6e0a371637d79 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/TransformationChain.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/TransformationChain.java @@ -17,6 +17,7 @@ package org.gradle.api.internal.artifacts.transform; import org.gradle.api.Action; +import org.gradle.execution.ProjectExecutionServiceRegistry; import org.gradle.internal.Try; /** @@ -57,9 +58,9 @@ public int stepsCount() { } @Override - public Try transform(TransformationSubject subjectToTransform, ExecutionGraphDependenciesResolver dependenciesResolver) { - return first.transform(subjectToTransform, dependenciesResolver) - .flatMap(intermediateSubject -> second.transform(intermediateSubject, dependenciesResolver)); + public Try transform(TransformationSubject subjectToTransform, ExecutionGraphDependenciesResolver dependenciesResolver, ProjectExecutionServiceRegistry services) { + return first.transform(subjectToTransform, dependenciesResolver, services) + .flatMap(intermediateSubject -> second.transform(intermediateSubject, dependenciesResolver, services)); } @Override diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/TransformationNode.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/TransformationNode.java index f3d9bfa860e18..618889c44ba3b 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/TransformationNode.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/TransformationNode.java @@ -21,6 +21,7 @@ import org.gradle.api.artifacts.ResolveException; import org.gradle.api.internal.artifacts.ivyservice.DefaultLenientConfiguration; import org.gradle.api.internal.artifacts.ivyservice.resolveengine.artifact.ResolvableArtifact; +import org.gradle.execution.ProjectExecutionServiceRegistry; import org.gradle.execution.plan.Node; import org.gradle.execution.plan.TaskDependencyResolver; import org.gradle.internal.Try; @@ -57,7 +58,7 @@ protected TransformationNode(TransformationStep transformationStep, ExecutionGra this.dependenciesResolver = dependenciesResolver; } - public abstract void execute(BuildOperationExecutor buildOperationExecutor, ArtifactTransformListener transformListener); + public abstract void execute(BuildOperationExecutor buildOperationExecutor, ArtifactTransformListener transformListener, ProjectExecutionServiceRegistry services); @Override public boolean isPublicNode() { @@ -135,7 +136,7 @@ public InitialTransformationNode(TransformationStep transformationStep, Resolvab } @Override - public void execute(BuildOperationExecutor buildOperationExecutor, ArtifactTransformListener transformListener) { + public void execute(BuildOperationExecutor buildOperationExecutor, ArtifactTransformListener transformListener, ProjectExecutionServiceRegistry services) { this.transformedSubject = buildOperationExecutor.call(new ArtifactTransformationStepBuildOperation() { @Override protected Try transform() { @@ -150,7 +151,7 @@ protected Try transform() { } TransformationSubject initialArtifactTransformationSubject = TransformationSubject.initial(artifact.getId(), file); - return transformationStep.transform(initialArtifactTransformationSubject, dependenciesResolver); + return transformationStep.transform(initialArtifactTransformationSubject, dependenciesResolver, services); } @Override @@ -177,12 +178,12 @@ public ChainedTransformationNode(TransformationStep transformationStep, Transfor } @Override - public void execute(BuildOperationExecutor buildOperationExecutor, ArtifactTransformListener transformListener) { + public void execute(BuildOperationExecutor buildOperationExecutor, ArtifactTransformListener transformListener, ProjectExecutionServiceRegistry services) { this.transformedSubject = buildOperationExecutor.call(new ArtifactTransformationStepBuildOperation() { @Override protected Try transform() { return previousTransformationNode.getTransformedSubject().flatMap(transformedSubject -> - transformationStep.transform(transformedSubject, dependenciesResolver)); + transformationStep.transform(transformedSubject, dependenciesResolver, services)); } @Override diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/TransformationNodeExecutor.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/TransformationNodeExecutor.java index 9d8a0245da0c5..d6c88eab4a7c3 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/TransformationNodeExecutor.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/TransformationNodeExecutor.java @@ -34,7 +34,7 @@ public TransformationNodeExecutor(BuildOperationExecutor buildOperationExecutor, public boolean execute(Node node, ProjectExecutionServiceRegistry services) { if (node instanceof TransformationNode) { TransformationNode transformationNode = (TransformationNode) node; - transformationNode.execute(buildOperationExecutor, transformListener); + transformationNode.execute(buildOperationExecutor, transformListener, services); return true; } else { return false; diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/TransformationOperation.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/TransformationOperation.java index f2b12cace28ac..bc2944e5b2b66 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/TransformationOperation.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/TransformationOperation.java @@ -38,7 +38,7 @@ class TransformationOperation implements RunnableBuildOperation { @Override public void run(@Nullable BuildOperationContext context) { - result = transformation.transform(subject, dependenciesResolver); + result = transformation.transform(subject, dependenciesResolver, null); } @Override diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/TransformationStep.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/TransformationStep.java index 44998ae8784fe..167186190527c 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/TransformationStep.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/TransformationStep.java @@ -21,11 +21,14 @@ import org.gradle.api.Action; import org.gradle.api.Project; import org.gradle.api.internal.attributes.ImmutableAttributes; +import org.gradle.api.internal.project.ProjectInternal; import org.gradle.api.internal.project.ProjectStateRegistry; import org.gradle.api.internal.tasks.TaskDependencyContainer; import org.gradle.api.internal.tasks.TaskDependencyResolveContext; import org.gradle.api.internal.tasks.WorkNodeAction; +import org.gradle.execution.ProjectExecutionServiceRegistry; import org.gradle.internal.Try; +import org.gradle.internal.fingerprint.FileCollectionFingerprinterRegistry; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -46,17 +49,21 @@ public class TransformationStep implements Transformation, TaskDependencyContain private final DomainObjectProjectStateHandler projectStateHandler; private final ProjectStateRegistry.SafeExclusiveLock isolationLock; private final WorkNodeAction isolateAction; + private final ProjectInternal owningProject; + private final FileCollectionFingerprinterRegistry fileCollectionFingerprinterRegistry; - public TransformationStep(Transformer transformer, TransformerInvoker transformerInvoker, DomainObjectProjectStateHandler projectStateHandler) { + public TransformationStep(Transformer transformer, TransformerInvoker transformerInvoker, DomainObjectProjectStateHandler projectStateHandler, FileCollectionFingerprinterRegistry fileCollectionFingerprinterRegistry) { this.transformer = transformer; this.transformerInvoker = transformerInvoker; this.projectStateHandler = projectStateHandler; + this.fileCollectionFingerprinterRegistry = fileCollectionFingerprinterRegistry; this.isolationLock = projectStateHandler.newExclusiveOperationLock(); + this.owningProject = projectStateHandler.maybeGetOwningProject(); this.isolateAction = transformer.isIsolated() ? null : new WorkNodeAction() { @Nullable @Override public Project getProject() { - return projectStateHandler.maybeGetOwningProject(); + return owningProject; } @Override @@ -77,16 +84,17 @@ public int stepsCount() { } @Override - public Try transform(TransformationSubject subjectToTransform, ExecutionGraphDependenciesResolver dependenciesResolver) { + public Try transform(TransformationSubject subjectToTransform, ExecutionGraphDependenciesResolver dependenciesResolver, @Nullable ProjectExecutionServiceRegistry services) { if (LOGGER.isInfoEnabled()) { LOGGER.info("Transforming {} with {}", subjectToTransform.getDisplayName(), transformer.getDisplayName()); } ImmutableList inputArtifacts = subjectToTransform.getFiles(); + FileCollectionFingerprinterRegistry fingerprinterRegistry = owningProject != null && services != null ? services.getProjectService(owningProject, FileCollectionFingerprinterRegistry.class) : fileCollectionFingerprinterRegistry; isolateTransformerParameters(); return dependenciesResolver.forTransformer(transformer).flatMap(dependencies -> { ImmutableList.Builder builder = ImmutableList.builder(); for (File inputArtifact : inputArtifacts) { - Try> result = transformerInvoker.invoke(transformer, inputArtifact, dependencies, subjectToTransform); + Try> result = transformerInvoker.invoke(transformer, inputArtifact, dependencies, subjectToTransform, fingerprinterRegistry); if (result.getFailure().isPresent()) { return Try.failure(result.getFailure().get()); diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/TransformerInvoker.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/TransformerInvoker.java index 0f21497767913..d2abe8934efda 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/TransformerInvoker.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/TransformerInvoker.java @@ -19,6 +19,7 @@ import com.google.common.collect.ImmutableList; import net.jcip.annotations.ThreadSafe; import org.gradle.internal.Try; +import org.gradle.internal.fingerprint.FileCollectionFingerprinterRegistry; import java.io.File; @@ -27,5 +28,5 @@ public interface TransformerInvoker { /** * Returns the result of applying the given transformer to the given file. */ - Try> invoke(Transformer transformer, File inputArtifact, ArtifactTransformDependencies dependencies, TransformationSubject subject); + Try> invoke(Transformer transformer, File inputArtifact, ArtifactTransformDependencies dependencies, TransformationSubject subject, FileCollectionFingerprinterRegistry fingerprinterRegistry); } diff --git a/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/DefaultVersionedComponentChooserTest.groovy b/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/DefaultVersionedComponentChooserTest.groovy index 425a6062e715a..78f25deef0b67 100644 --- a/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/DefaultVersionedComponentChooserTest.groovy +++ b/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/DefaultVersionedComponentChooserTest.groovy @@ -412,7 +412,7 @@ class DefaultVersionedComponentChooserTest extends Specification { Mock(ComponentMetadataSupplierRuleExecutor) { execute(_, _, _, _, _) >> { args -> def (key, rule, converter, producer, cachePolicy) = args - converter.transform(producer.transform(key, dependenciesProvider), dependenciesProvider) + converter.transform(producer.transform(key, dependenciesProvider, null), dependenciesProvider, null) } } } diff --git a/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/ChainedTransformerTest.groovy b/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/ChainedTransformerTest.groovy index f271a978be379..c98cd9758c423 100644 --- a/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/ChainedTransformerTest.groovy +++ b/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/ChainedTransformerTest.groovy @@ -18,6 +18,7 @@ package org.gradle.api.internal.artifacts.transform import com.google.common.collect.ImmutableList import org.gradle.api.Action +import org.gradle.execution.ProjectExecutionServiceRegistry import org.gradle.internal.Try import spock.lang.Specification @@ -29,13 +30,13 @@ class ChainedTransformerTest extends Specification { def chain = new TransformationChain(new CachingTransformation(), new NonCachingTransformation()) expect: - chain.transform(initialSubject, Mock(ExecutionGraphDependenciesResolver)).get().files == [new File("foo/cached/non-cached")] + chain.transform(initialSubject, Mock(ExecutionGraphDependenciesResolver), null).get().files == [new File("foo/cached/non-cached")] } class CachingTransformation implements Transformation { @Override - Try transform(TransformationSubject subjectToTransform, ExecutionGraphDependenciesResolver dependenciesResolver) { + Try transform(TransformationSubject subjectToTransform, ExecutionGraphDependenciesResolver dependenciesResolver, ProjectExecutionServiceRegistry services) { return Try.successful(subjectToTransform.createSubjectFromResult(ImmutableList.of(new File(subjectToTransform.files.first(), "cached")))) } @@ -68,7 +69,7 @@ class ChainedTransformerTest extends Specification { class NonCachingTransformation implements Transformation { @Override - Try transform(TransformationSubject subjectToTransform, ExecutionGraphDependenciesResolver dependenciesResolver) { + Try transform(TransformationSubject subjectToTransform, ExecutionGraphDependenciesResolver dependenciesResolver, ProjectExecutionServiceRegistry services) { return Try.successful(subjectToTransform.createSubjectFromResult(ImmutableList.of(new File(subjectToTransform.files.first(), "non-cached")))) } diff --git a/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/ConsumerProvidedVariantFinderTest.groovy b/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/ConsumerProvidedVariantFinderTest.groovy index 513f1a32f6fb2..efb48e3b8ff0b 100644 --- a/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/ConsumerProvidedVariantFinderTest.groovy +++ b/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/ConsumerProvidedVariantFinderTest.groovy @@ -203,7 +203,7 @@ class ConsumerProvidedVariantFinderTest extends Specification { 0 * matcher._ when: - def result = transformer.transformation.transform(initialSubject("in.txt"), Mock(ExecutionGraphDependenciesResolver)).get() + def result = transformer.transformation.transform(initialSubject("in.txt"), Mock(ExecutionGraphDependenciesResolver), null).get() then: result.files == [new File("in.txt.2a.5"), new File("in.txt.2b.5")] @@ -287,7 +287,7 @@ class ConsumerProvidedVariantFinderTest extends Specification { 0 * matcher._ when: - def files = result.matches.first().transformation.transform(initialSubject("a"), Mock(ExecutionGraphDependenciesResolver)).get().files + def files = result.matches.first().transformation.transform(initialSubject("a"), Mock(ExecutionGraphDependenciesResolver), null).get().files then: files == [new File("d"), new File("e")] diff --git a/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/DefaultArtifactTransformsTest.groovy b/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/DefaultArtifactTransformsTest.groovy index fbdb00daa9fa0..2623c2e4fe0b3 100644 --- a/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/DefaultArtifactTransformsTest.groovy +++ b/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/DefaultArtifactTransformsTest.groovy @@ -172,9 +172,9 @@ class DefaultArtifactTransformsTest extends Specification { _ * transformation.getDisplayName() >> "transform" _ * transformation.requiresDependencies() >> false - 1 * transformation.transform({ it.files == [sourceArtifactFile]}, _ as ExecutionGraphDependenciesResolver) >> Try.successful(TransformationSubject.initial(sourceArtifactId, sourceArtifactFile).createSubjectFromResult(ImmutableList.of(outFile1, outFile2))) + 1 * transformation.transform({ it.files == [sourceArtifactFile]}, _ as ExecutionGraphDependenciesResolver, _) >> Try.successful(TransformationSubject.initial(sourceArtifactId, sourceArtifactFile).createSubjectFromResult(ImmutableList.of(outFile1, outFile2))) - 1 * transformation.transform({ it.files == [sourceFile] }, _ as ExecutionGraphDependenciesResolver) >> Try.successful(TransformationSubject.initial(sourceFile).createSubjectFromResult(ImmutableList.of(outFile3, outFile4))) + 1 * transformation.transform({ it.files == [sourceFile] }, _ as ExecutionGraphDependenciesResolver, _) >> Try.successful(TransformationSubject.initial(sourceFile).createSubjectFromResult(ImmutableList.of(outFile3, outFile4))) 1 * visitor.visitArtifact(variant1DisplayName, targetAttributes, {it.file == outFile1}) 1 * visitor.visitArtifact(variant1DisplayName, targetAttributes, {it.file == outFile2}) diff --git a/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvokerTest.groovy b/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvokerTest.groovy index 351a9680845af..47fd86b342ef4 100644 --- a/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvokerTest.groovy +++ b/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvokerTest.groovy @@ -63,7 +63,7 @@ class DefaultTransformerInvokerTest extends AbstractProjectBuilderSpec { def artifactTransformListener = Mock(ArtifactTransformListener) def dependencyFingerprinter = new AbsolutePathFileCollectionFingerprinter(fileSystemSnapshotter) def outputFilesFingerprinter = new OutputFileCollectionFingerprinter(fileSystemSnapshotter) - def registry = new DefaultFileCollectionFingerprinterRegistry([dependencyFingerprinter, outputFilesFingerprinter]) + def fingerprinterRegistry = new DefaultFileCollectionFingerprinterRegistry([dependencyFingerprinter, outputFilesFingerprinter]) def classloaderHasher = Stub(ClassLoaderHierarchyHasher) { getClassLoaderHash(_) >> HashCode.fromInt(1234) @@ -91,7 +91,6 @@ class DefaultTransformerInvokerTest extends AbstractProjectBuilderSpec { fileSystemSnapshotter, artifactTransformListener, transformationWorkspaceProvider, - registry, fileCollectionFactory, classloaderHasher, projectFinder, @@ -181,7 +180,7 @@ class DefaultTransformerInvokerTest extends AbstractProjectBuilderSpec { } when: - def result = invoker.invoke(transformer, inputArtifact, dependencies, dependency(transformationType, inputArtifact)) + def result = invoker.invoke(transformer, inputArtifact, dependencies, dependency(transformationType, inputArtifact), fingerprinterRegistry) then: result.get().size() == 1 @@ -204,7 +203,7 @@ class DefaultTransformerInvokerTest extends AbstractProjectBuilderSpec { } when: - invoker.invoke(transformer, inputArtifact, dependencies, TransformationSubject.initial(inputArtifact)) + invoker.invoke(transformer, inputArtifact, dependencies, TransformationSubject.initial(inputArtifact), fingerprinterRegistry) then: transformerInvocations == 1 @@ -212,7 +211,7 @@ class DefaultTransformerInvokerTest extends AbstractProjectBuilderSpec { 1 * artifactTransformListener.afterTransformerInvocation(_, _) when: - invoker.invoke(transformer, inputArtifact, dependencies, TransformationSubject.initial(inputArtifact)) + invoker.invoke(transformer, inputArtifact, dependencies, TransformationSubject.initial(inputArtifact), fingerprinterRegistry) then: transformerInvocations == 1 1 * artifactTransformListener.beforeTransformerInvocation(_, _) @@ -236,7 +235,7 @@ class DefaultTransformerInvokerTest extends AbstractProjectBuilderSpec { } when: - def result = invoker.invoke(transformer, inputArtifact, dependencies, TransformationSubject.initial(inputArtifact)) + def result = invoker.invoke(transformer, inputArtifact, dependencies, TransformationSubject.initial(inputArtifact), fingerprinterRegistry) then: transformerInvocations == 1 @@ -246,7 +245,7 @@ class DefaultTransformerInvokerTest extends AbstractProjectBuilderSpec { wrappedFailure.cause == failure when: - invoker.invoke(transformer, inputArtifact, dependencies, TransformationSubject.initial(inputArtifact)) + invoker.invoke(transformer, inputArtifact, dependencies, TransformationSubject.initial(inputArtifact), fingerprinterRegistry) then: transformerInvocations == 2 1 * artifactTransformListener.beforeTransformerInvocation(_, _) @@ -267,7 +266,7 @@ class DefaultTransformerInvokerTest extends AbstractProjectBuilderSpec { } when: - invoker.invoke(transformer, inputArtifact, dependencies, TransformationSubject.initial(inputArtifact)) + invoker.invoke(transformer, inputArtifact, dependencies, TransformationSubject.initial(inputArtifact), fingerprinterRegistry) then: transformerInvocations == 1 outputFile?.isFile() @@ -276,7 +275,7 @@ class DefaultTransformerInvokerTest extends AbstractProjectBuilderSpec { outputFile.text = "changed" fileSystemMirror.beforeBuildFinished() - invoker.invoke(transformer, inputArtifact, dependencies, TransformationSubject.initial(inputArtifact)) + invoker.invoke(transformer, inputArtifact, dependencies, TransformationSubject.initial(inputArtifact), fingerprinterRegistry) then: transformerInvocations == 2 } @@ -297,8 +296,8 @@ class DefaultTransformerInvokerTest extends AbstractProjectBuilderSpec { def subject = dependency(transformationType, inputArtifact) when: - invoker.invoke(transformer1, inputArtifact, dependencies, subject) - invoker.invoke(transformer2, inputArtifact, dependencies, subject) + invoker.invoke(transformer1, inputArtifact, dependencies, subject, fingerprinterRegistry) + invoker.invoke(transformer2, inputArtifact, dependencies, subject, fingerprinterRegistry) then: workspaces.size() == 2 @@ -322,14 +321,14 @@ class DefaultTransformerInvokerTest extends AbstractProjectBuilderSpec { } def transformer = TestTransformer.create(HashCode.fromInt(1234), transformationAction) when: - invoker.invoke(transformer, inputArtifact1, dependencies, dependency(transformationType, inputArtifact1)) + invoker.invoke(transformer, inputArtifact1, dependencies, dependency(transformationType, inputArtifact1), fingerprinterRegistry) then: workspaces.size() == 1 when: fileSystemMirror.beforeBuildFinished() inputArtifact1.text = "changed" - invoker.invoke(transformer, inputArtifact2, dependencies, dependency(transformationType, inputArtifact2)) + invoker.invoke(transformer, inputArtifact2, dependencies, dependency(transformationType, inputArtifact2), fingerprinterRegistry) then: workspaces.size() == 2 @@ -352,14 +351,14 @@ class DefaultTransformerInvokerTest extends AbstractProjectBuilderSpec { def subject = immutableDependency(inputArtifact) when: - invoker.invoke(transformer, inputArtifact, dependencies, subject) + invoker.invoke(transformer, inputArtifact, dependencies, subject, fingerprinterRegistry) then: workspaces.size() == 1 when: fileSystemMirror.beforeBuildFinished() inputArtifact.text = "changed" - invoker.invoke(transformer, inputArtifact, dependencies, subject) + invoker.invoke(transformer, inputArtifact, dependencies, subject, fingerprinterRegistry) then: workspaces.size() == 2 @@ -379,14 +378,14 @@ class DefaultTransformerInvokerTest extends AbstractProjectBuilderSpec { def subject = mutableDependency(inputArtifact) when: - invoker.invoke(transformer, inputArtifact, dependencies, subject) + invoker.invoke(transformer, inputArtifact, dependencies, subject, fingerprinterRegistry) then: workspaces.size() == 1 when: fileSystemMirror.beforeBuildFinished() inputArtifact.text = "changed" - invoker.invoke(transformer, inputArtifact, dependencies, subject) + invoker.invoke(transformer, inputArtifact, dependencies, subject, fingerprinterRegistry) then: workspaces.size() == 1 diff --git a/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/TransformationMatchingSpec.groovy b/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/TransformationMatchingSpec.groovy index 95c8976972b91..446ff433b3154 100644 --- a/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/TransformationMatchingSpec.groovy +++ b/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/TransformationMatchingSpec.groovy @@ -16,14 +16,18 @@ package org.gradle.api.internal.artifacts.transform +import org.gradle.internal.fingerprint.FileCollectionFingerprinterRegistry import spock.lang.Specification class TransformationMatchingSpec extends Specification { + def projectStateHandler = Mock(DomainObjectProjectStateHandler) + def fileCollectionFingerprinterRegistry = Mock(FileCollectionFingerprinterRegistry) + def "different TransformationStep does not contain each other"() { given: - def step1 = new TransformationStep(Mock(Transformer), Mock(TransformerInvoker), projectStateHandler) - def step2 = new TransformationStep(Mock(Transformer), Mock(TransformerInvoker), projectStateHandler) + def step1 = new TransformationStep(Mock(Transformer), Mock(TransformerInvoker), projectStateHandler, fileCollectionFingerprinterRegistry) + def step2 = new TransformationStep(Mock(Transformer), Mock(TransformerInvoker), projectStateHandler, fileCollectionFingerprinterRegistry) expect: !step1.endsWith(step2) @@ -32,7 +36,7 @@ class TransformationMatchingSpec extends Specification { def "TransformationStep contains itself"() { given: - def step = new TransformationStep(Mock(Transformer), Mock(TransformerInvoker), projectStateHandler) + def step = new TransformationStep(Mock(Transformer), Mock(TransformerInvoker), projectStateHandler, fileCollectionFingerprinterRegistry) expect: step.endsWith(step) @@ -40,8 +44,8 @@ class TransformationMatchingSpec extends Specification { def "chain contains its final step"() { given: - def step1 = new TransformationStep(Mock(Transformer), Mock(TransformerInvoker), projectStateHandler) - def step2 = new TransformationStep(Mock(Transformer), Mock(TransformerInvoker), projectStateHandler) + def step1 = new TransformationStep(Mock(Transformer), Mock(TransformerInvoker), projectStateHandler, fileCollectionFingerprinterRegistry) + def step2 = new TransformationStep(Mock(Transformer), Mock(TransformerInvoker), projectStateHandler, fileCollectionFingerprinterRegistry) def chain = new TransformationChain(step1, step2) expect: @@ -54,8 +58,8 @@ class TransformationMatchingSpec extends Specification { def "chain contains itself"() { given: - def step1 = new TransformationStep(Mock(Transformer), Mock(TransformerInvoker), projectStateHandler) - def step2 = new TransformationStep(Mock(Transformer), Mock(TransformerInvoker), projectStateHandler) + def step1 = new TransformationStep(Mock(Transformer), Mock(TransformerInvoker), projectStateHandler, fileCollectionFingerprinterRegistry) + def step2 = new TransformationStep(Mock(Transformer), Mock(TransformerInvoker), projectStateHandler, fileCollectionFingerprinterRegistry) def chain = new TransformationChain(step1, step2) expect: @@ -64,9 +68,9 @@ class TransformationMatchingSpec extends Specification { def "longer chain contains shorter chain"() { given: - def step1 = new TransformationStep(Mock(Transformer), Mock(TransformerInvoker), projectStateHandler) - def step2 = new TransformationStep(Mock(Transformer), Mock(TransformerInvoker), projectStateHandler) - def step3 = new TransformationStep(Mock(Transformer), Mock(TransformerInvoker), projectStateHandler) + def step1 = new TransformationStep(Mock(Transformer), Mock(TransformerInvoker), projectStateHandler, fileCollectionFingerprinterRegistry) + def step2 = new TransformationStep(Mock(Transformer), Mock(TransformerInvoker), projectStateHandler, fileCollectionFingerprinterRegistry) + def step3 = new TransformationStep(Mock(Transformer), Mock(TransformerInvoker), projectStateHandler, fileCollectionFingerprinterRegistry) def subChain = new TransformationChain(step2, step3) def longChain = new TransformationChain(new TransformationChain(step1, step2), step3) @@ -77,9 +81,9 @@ class TransformationMatchingSpec extends Specification { def "different chains do not contain each other"() { given: - def step1 = new TransformationStep(Mock(Transformer), Mock(TransformerInvoker), projectStateHandler) - def step2 = new TransformationStep(Mock(Transformer), Mock(TransformerInvoker), projectStateHandler) - def step3 = new TransformationStep(Mock(Transformer), Mock(TransformerInvoker), projectStateHandler) + def step1 = new TransformationStep(Mock(Transformer), Mock(TransformerInvoker), projectStateHandler, fileCollectionFingerprinterRegistry) + def step2 = new TransformationStep(Mock(Transformer), Mock(TransformerInvoker), projectStateHandler, fileCollectionFingerprinterRegistry) + def step3 = new TransformationStep(Mock(Transformer), Mock(TransformerInvoker), projectStateHandler, fileCollectionFingerprinterRegistry) def chain1 = new TransformationChain(step2, step3) def chain2 = new TransformationChain(step1, step2) def chain3 = new TransformationChain(step1, step3) diff --git a/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/TransformingAsyncArtifactListenerTest.groovy b/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/TransformingAsyncArtifactListenerTest.groovy index 5aa26394afd62..86abc1c3f0dcf 100644 --- a/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/TransformingAsyncArtifactListenerTest.groovy +++ b/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/TransformingAsyncArtifactListenerTest.groovy @@ -48,6 +48,6 @@ class TransformingAsyncArtifactListenerTest extends Specification { listener.artifactAvailable(artifact) then: - 1 * transformation.transform({ it.files == [artifactFile] }, _ as ExecutionGraphDependenciesResolver) + 1 * transformation.transform({ it.files == [artifactFile] }, _ as ExecutionGraphDependenciesResolver, _) } } From 1b32ad06227f84769ddfeaaaa0fefae77ab0942b Mon Sep 17 00:00:00 2001 From: Stefan Wolf Date: Fri, 22 Feb 2019 16:03:35 +0100 Subject: [PATCH 046/853] Pass fingerprinter registry into transformer (invoker) --- .../ProjectExecutionServiceRegistry.java | 7 +++++- .../org/gradle/execution/plan/ActionNode.java | 9 +++++-- .../execution/plan/WorkNodeExecutor.java | 2 +- ...nsformWithFileInputsIntegrationTest.groovy | 4 +--- .../configurations/DefaultConfiguration.java | 3 ++- ...aultTransformationRegistrationFactory.java | 1 - .../transform/DefaultTransformer.java | 11 ++++----- .../transform/LegacyTransformer.java | 3 ++- .../transform/TransformationStep.java | 24 ++++++++++++------- .../artifacts/transform/Transformer.java | 3 ++- .../ConsumerProvidedVariantFinderTest.groovy | 3 ++- .../DefaultTransformerInvokerTest.groovy | 3 ++- .../TransformationMatchingSpec.groovy | 3 --- .../api/internal/tasks/WorkNodeAction.java | 3 ++- 14 files changed, 46 insertions(+), 33 deletions(-) diff --git a/subprojects/core/src/main/java/org/gradle/execution/ProjectExecutionServiceRegistry.java b/subprojects/core/src/main/java/org/gradle/execution/ProjectExecutionServiceRegistry.java index 7085203bd9bc7..9ef185f824a23 100644 --- a/subprojects/core/src/main/java/org/gradle/execution/ProjectExecutionServiceRegistry.java +++ b/subprojects/core/src/main/java/org/gradle/execution/ProjectExecutionServiceRegistry.java @@ -20,6 +20,7 @@ import com.google.common.cache.CacheLoader; import com.google.common.cache.LoadingCache; import org.gradle.api.internal.project.ProjectInternal; +import org.gradle.internal.service.ServiceRegistry; import javax.annotation.Nonnull; @@ -36,7 +37,11 @@ public ProjectExecutionServices load(@Nonnull ProjectInternal project) { }); public T getProjectService(ProjectInternal project, Class serviceType) { - return projectRegistries.getUnchecked(project).get(serviceType); + return forProject(project).get(serviceType); + } + + public ServiceRegistry forProject(ProjectInternal project) { + return projectRegistries.getUnchecked(project); } @Override diff --git a/subprojects/core/src/main/java/org/gradle/execution/plan/ActionNode.java b/subprojects/core/src/main/java/org/gradle/execution/plan/ActionNode.java index e5880ddff4f2a..ece7e47cd2dd3 100644 --- a/subprojects/core/src/main/java/org/gradle/execution/plan/ActionNode.java +++ b/subprojects/core/src/main/java/org/gradle/execution/plan/ActionNode.java @@ -18,7 +18,10 @@ import org.gradle.api.Action; import org.gradle.api.Project; +import org.gradle.api.internal.project.ProjectInternal; import org.gradle.api.internal.tasks.WorkNodeAction; +import org.gradle.execution.ProjectExecutionServiceRegistry; +import org.gradle.internal.service.ServiceRegistry; import javax.annotation.Nullable; import java.util.Collections; @@ -75,7 +78,9 @@ public Project getProject() { return action.getProject(); } - public void run() { - action.run(); + public void run(ProjectExecutionServiceRegistry services) { + ProjectInternal project = (ProjectInternal) action.getProject(); + ServiceRegistry registry = project == null ? null : services.forProject(project); + action.run(registry); } } diff --git a/subprojects/core/src/main/java/org/gradle/execution/plan/WorkNodeExecutor.java b/subprojects/core/src/main/java/org/gradle/execution/plan/WorkNodeExecutor.java index 2c141e085ab8a..e1bacde4d27d1 100644 --- a/subprojects/core/src/main/java/org/gradle/execution/plan/WorkNodeExecutor.java +++ b/subprojects/core/src/main/java/org/gradle/execution/plan/WorkNodeExecutor.java @@ -24,7 +24,7 @@ public boolean execute(Node node, ProjectExecutionServiceRegistry services) { if (!(node instanceof ActionNode)) { return false; } - ((ActionNode) node).run(); + ((ActionNode) node).run(services); return true; } } diff --git a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformWithFileInputsIntegrationTest.groovy b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformWithFileInputsIntegrationTest.groovy index 83ed25ab7334e..7f4dc908ec0a6 100644 --- a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformWithFileInputsIntegrationTest.groovy +++ b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformWithFileInputsIntegrationTest.groovy @@ -501,9 +501,7 @@ class ArtifactTransformWithFileInputsIntegrationTest extends AbstractDependencyR jarSources.zipTo(inputJar) run(":a:resolve") then: - outputContains("processing b.jar using [${inputDir.name}, ${inputJar.name}]") - outputContains("processing c.jar using [${inputDir.name}, ${inputJar.name}]") - + outputDoesNotContain("processing") outputContains("result = [b.jar.green, c.jar.green]") when: diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/configurations/DefaultConfiguration.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/configurations/DefaultConfiguration.java index b7bfb5c149aed..0a7ef4721f114 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/configurations/DefaultConfiguration.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/configurations/DefaultConfiguration.java @@ -111,6 +111,7 @@ import org.gradle.internal.operations.BuildOperationExecutor; import org.gradle.internal.operations.RunnableBuildOperation; import org.gradle.internal.reflect.Instantiator; +import org.gradle.internal.service.ServiceRegistry; import org.gradle.internal.typeconversion.NotationParser; import org.gradle.util.CollectionUtils; import org.gradle.util.ConfigureUtil; @@ -668,7 +669,7 @@ public Project getProject() { } @Override - public void run() { + public void run(@Nullable ServiceRegistry registry) { resolveExclusively(GRAPH_RESOLVED); } }, fileCollectionFactory); diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformationRegistrationFactory.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformationRegistrationFactory.java index 81ec979dc8851..81eb8fc0fbb35 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformationRegistrationFactory.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformationRegistrationFactory.java @@ -129,7 +129,6 @@ public ArtifactTransformRegistration create(ImmutableAttributes from, ImmutableA isolatableFactory, valueSnapshotter, fileCollectionFactory, - fileCollectionFingerprinterRegistry, parametersPropertyWalker, actionInstantiationScheme); diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformer.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformer.java index c58dbeec32d35..30e9665d66702 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformer.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformer.java @@ -79,7 +79,6 @@ public class DefaultTransformer extends AbstractTransformer { private final IsolatableFactory isolatableFactory; private final ValueSnapshotter valueSnapshotter; private final FileCollectionFactory fileCollectionFactory; - private final FileCollectionFingerprinterRegistry fileCollectionFingerprinterRegistry; private final PropertyWalker parameterPropertyWalker; private final boolean requiresDependencies; private final InstanceFactory instanceFactory; @@ -98,7 +97,6 @@ public DefaultTransformer( IsolatableFactory isolatableFactory, ValueSnapshotter valueSnapshotter, FileCollectionFactory fileCollectionFactory, - FileCollectionFingerprinterRegistry fileCollectionFingerprinterRegistry, PropertyWalker parameterPropertyWalker, InstantiationScheme actionInstantiationScheme ) { @@ -110,7 +108,6 @@ public DefaultTransformer( this.isolatableFactory = isolatableFactory; this.valueSnapshotter = valueSnapshotter; this.fileCollectionFactory = fileCollectionFactory; - this.fileCollectionFingerprinterRegistry = fileCollectionFingerprinterRegistry; this.parameterPropertyWalker = parameterPropertyWalker; this.instanceFactory = actionInstantiationScheme.forType(implementationClass); this.requiresDependencies = instanceFactory.serviceInjectionTriggeredByAnnotation(InputArtifactDependencies.class); @@ -178,15 +175,15 @@ public void visitInputFileProperty(String propertyName, boolean optional, boolea } @Override - public void isolateParameters() { + public void isolateParameters(FileCollectionFingerprinterRegistry fingerprinterRegistry) { try { - isolatable = doIsolateParameters(); + isolatable = doIsolateParameters(fingerprinterRegistry); } catch (Exception e) { throw new VariantTransformConfigurationException(String.format("Cannot isolate parameters %s of artifact transform %s", parameterObject, ModelType.of(getImplementationClass()).getDisplayName()), e); } } - protected IsolatableParameters doIsolateParameters() { + protected IsolatableParameters doIsolateParameters(FileCollectionFingerprinterRegistry fingerprinterRegistry) { Isolatable isolatableParameterObject = isolatableFactory.isolate(parameterObject); Hasher hasher = Hashing.newHasher(); @@ -194,7 +191,7 @@ protected IsolatableParameters doIsolateParameters() { if (parameterObject != null) { // TODO wolfs - schedule fingerprinting separately, it can be done without having the project lock - fingerprintParameters(valueSnapshotter, fileCollectionFingerprinterRegistry, fileCollectionFactory, parameterPropertyWalker, hasher, isolatableParameterObject.isolate(), cacheable); + fingerprintParameters(valueSnapshotter, fingerprinterRegistry, fileCollectionFactory, parameterPropertyWalker, hasher, isolatableParameterObject.isolate(), cacheable); } HashCode secondaryInputsHash = hasher.hash(); return new IsolatableParameters(isolatableParameterObject, secondaryInputsHash); diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/LegacyTransformer.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/LegacyTransformer.java index bf855dcaf61fd..8e0abe1ff88ca 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/LegacyTransformer.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/LegacyTransformer.java @@ -24,6 +24,7 @@ import org.gradle.api.tasks.FileNormalizer; import org.gradle.internal.classloader.ClassLoaderHierarchyHasher; import org.gradle.internal.fingerprint.AbsolutePathInputNormalizer; +import org.gradle.internal.fingerprint.FileCollectionFingerprinterRegistry; import org.gradle.internal.hash.HashCode; import org.gradle.internal.hash.Hasher; import org.gradle.internal.hash.Hashing; @@ -103,7 +104,7 @@ public void visitDependencies(TaskDependencyResolveContext context) { } @Override - public void isolateParameters() { + public void isolateParameters(FileCollectionFingerprinterRegistry fingerprinterRegistry) { } private ArtifactTransform newTransformer() { diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/TransformationStep.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/TransformationStep.java index 167186190527c..3d92fb7608156 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/TransformationStep.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/TransformationStep.java @@ -29,6 +29,7 @@ import org.gradle.execution.ProjectExecutionServiceRegistry; import org.gradle.internal.Try; import org.gradle.internal.fingerprint.FileCollectionFingerprinterRegistry; +import org.gradle.internal.service.ServiceRegistry; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -67,8 +68,9 @@ public Project getProject() { } @Override - public void run() { - isolateExclusively(); + public void run(@Nullable ServiceRegistry registry) { + FileCollectionFingerprinterRegistry fingerprinterRegistry = registry == null ? fileCollectionFingerprinterRegistry : registry.get(FileCollectionFingerprinterRegistry.class); + isolateExclusively(fingerprinterRegistry); } }; } @@ -89,8 +91,8 @@ public Try transform(TransformationSubject subjectToTrans LOGGER.info("Transforming {} with {}", subjectToTransform.getDisplayName(), transformer.getDisplayName()); } ImmutableList inputArtifacts = subjectToTransform.getFiles(); - FileCollectionFingerprinterRegistry fingerprinterRegistry = owningProject != null && services != null ? services.getProjectService(owningProject, FileCollectionFingerprinterRegistry.class) : fileCollectionFingerprinterRegistry; - isolateTransformerParameters(); + FileCollectionFingerprinterRegistry fingerprinterRegistry = getFingerprinterRegistry(services); + isolateTransformerParameters(fingerprinterRegistry); return dependenciesResolver.forTransformer(transformer).flatMap(dependencies -> { ImmutableList.Builder builder = ImmutableList.builder(); for (File inputArtifact : inputArtifacts) { @@ -105,20 +107,24 @@ public Try transform(TransformationSubject subjectToTrans }); } - private void isolateTransformerParameters() { + public FileCollectionFingerprinterRegistry getFingerprinterRegistry(@Nullable ProjectExecutionServiceRegistry services) { + return owningProject != null && services != null ? services.getProjectService(owningProject, FileCollectionFingerprinterRegistry.class) : fileCollectionFingerprinterRegistry; + } + + private void isolateTransformerParameters(FileCollectionFingerprinterRegistry fingerprinterRegistry) { if (!transformer.isIsolated()) { if (!projectStateHandler.hasMutableProjectState()) { - projectStateHandler.withLenientState(this::isolateExclusively); + projectStateHandler.withLenientState(() -> isolateExclusively(fingerprinterRegistry)); } else { - isolateExclusively(); + isolateExclusively(fingerprinterRegistry); } } } - private void isolateExclusively() { + private void isolateExclusively(FileCollectionFingerprinterRegistry fingerprinterRegistry) { isolationLock.withLock(() -> { if (!transformer.isIsolated()) { - transformer.isolateParameters(); + transformer.isolateParameters(fingerprinterRegistry); } }); } diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/Transformer.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/Transformer.java index ebefd9b24a727..5781ae7fe34fe 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/Transformer.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/Transformer.java @@ -22,6 +22,7 @@ import org.gradle.api.internal.attributes.ImmutableAttributes; import org.gradle.api.internal.tasks.TaskDependencyContainer; import org.gradle.api.tasks.FileNormalizer; +import org.gradle.internal.fingerprint.FileCollectionFingerprinterRegistry; import org.gradle.internal.hash.HashCode; import java.io.File; @@ -55,7 +56,7 @@ public interface Transformer extends Describable, TaskDependencyContainer { */ HashCode getSecondaryInputHash(); - void isolateParameters(); + void isolateParameters(FileCollectionFingerprinterRegistry fingerprinterRegistry); Class getInputArtifactNormalizer(); diff --git a/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/ConsumerProvidedVariantFinderTest.groovy b/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/ConsumerProvidedVariantFinderTest.groovy index efb48e3b8ff0b..af1c8f995e18c 100644 --- a/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/ConsumerProvidedVariantFinderTest.groovy +++ b/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/ConsumerProvidedVariantFinderTest.groovy @@ -207,6 +207,7 @@ class ConsumerProvidedVariantFinderTest extends Specification { then: result.files == [new File("in.txt.2a.5"), new File("in.txt.2b.5")] + 0 * _ } def "prefers direct transformation over indirect"() { @@ -443,7 +444,7 @@ class ConsumerProvidedVariantFinderTest extends Specification { reg.from >> from reg.to >> to reg.transformationStep >> Stub(TransformationStep) { - transform(_ as TransformationSubject, _ as ExecutionGraphDependenciesResolver) >> { TransformationSubject subject, ExecutionGraphDependenciesResolver dependenciesResolver -> + _ * transform(_ as TransformationSubject, _ as ExecutionGraphDependenciesResolver, null) >> { TransformationSubject subject, ExecutionGraphDependenciesResolver dependenciesResolver, services -> return Try.successful(subject.createSubjectFromResult(ImmutableList.copyOf(subject.files.collectMany { transformer.transform(it) }))) } } diff --git a/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvokerTest.groovy b/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvokerTest.groovy index 47fd86b342ef4..6cfe28843326d 100644 --- a/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvokerTest.groovy +++ b/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvokerTest.groovy @@ -33,6 +33,7 @@ import org.gradle.internal.component.local.model.ComponentFileArtifactIdentifier import org.gradle.internal.execution.TestExecutionHistoryStore import org.gradle.internal.fingerprint.AbsolutePathInputNormalizer import org.gradle.internal.fingerprint.FileCollectionFingerprinter +import org.gradle.internal.fingerprint.FileCollectionFingerprinterRegistry import org.gradle.internal.fingerprint.impl.AbsolutePathFileCollectionFingerprinter import org.gradle.internal.fingerprint.impl.DefaultFileCollectionFingerprinterRegistry import org.gradle.internal.fingerprint.impl.OutputFileCollectionFingerprinter @@ -156,7 +157,7 @@ class DefaultTransformerInvokerTest extends AbstractProjectBuilderSpec { } @Override - void isolateParameters() { + void isolateParameters(FileCollectionFingerprinterRegistry fingerprinterRegistry) { } @Override diff --git a/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/TransformationMatchingSpec.groovy b/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/TransformationMatchingSpec.groovy index 446ff433b3154..93eaa1d038559 100644 --- a/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/TransformationMatchingSpec.groovy +++ b/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/TransformationMatchingSpec.groovy @@ -95,8 +95,5 @@ class TransformationMatchingSpec extends Specification { !chain3.endsWith(chain1) !chain2.endsWith(chain3) !chain1.endsWith(chain3) - - - } } diff --git a/subprojects/model-core/src/main/java/org/gradle/api/internal/tasks/WorkNodeAction.java b/subprojects/model-core/src/main/java/org/gradle/api/internal/tasks/WorkNodeAction.java index 7ef03e5f5d379..d07b5ca2eb4b7 100644 --- a/subprojects/model-core/src/main/java/org/gradle/api/internal/tasks/WorkNodeAction.java +++ b/subprojects/model-core/src/main/java/org/gradle/api/internal/tasks/WorkNodeAction.java @@ -17,6 +17,7 @@ package org.gradle.api.internal.tasks; import org.gradle.api.Project; +import org.gradle.internal.service.ServiceRegistry; import javax.annotation.Nullable; @@ -33,5 +34,5 @@ public interface WorkNodeAction { /** * Run the action, throwing any failure. */ - void run(); + void run(@Nullable ServiceRegistry registry); } From 6d486ae4d7b4136cfaf78375cb21d2bef28c094a Mon Sep 17 00:00:00 2001 From: Stefan Wolf Date: Fri, 22 Feb 2019 17:49:01 +0100 Subject: [PATCH 047/853] Use same fingerprinter registry for transformation step Make sure to always use the same fingerprinter registry during the lifecycle of a transformation step. --- .../transform/TransformationChain.java | 4 +++- .../transform/TransformationStep.java | 19 ++++++++++++------- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/TransformationChain.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/TransformationChain.java index 6e0a371637d79..2d4bec5ffe840 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/TransformationChain.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/TransformationChain.java @@ -20,6 +20,8 @@ import org.gradle.execution.ProjectExecutionServiceRegistry; import org.gradle.internal.Try; +import javax.annotation.Nullable; + /** * A series of {@link TransformationStep}s. */ @@ -58,7 +60,7 @@ public int stepsCount() { } @Override - public Try transform(TransformationSubject subjectToTransform, ExecutionGraphDependenciesResolver dependenciesResolver, ProjectExecutionServiceRegistry services) { + public Try transform(TransformationSubject subjectToTransform, ExecutionGraphDependenciesResolver dependenciesResolver, @Nullable ProjectExecutionServiceRegistry services) { return first.transform(subjectToTransform, dependenciesResolver, services) .flatMap(intermediateSubject -> second.transform(intermediateSubject, dependenciesResolver, services)); } diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/TransformationStep.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/TransformationStep.java index 3d92fb7608156..880d8993d48c7 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/TransformationStep.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/TransformationStep.java @@ -35,6 +35,7 @@ import javax.annotation.Nullable; import java.io.File; +import java.util.concurrent.atomic.AtomicReference; /** * A single transformation step. @@ -51,13 +52,14 @@ public class TransformationStep implements Transformation, TaskDependencyContain private final ProjectStateRegistry.SafeExclusiveLock isolationLock; private final WorkNodeAction isolateAction; private final ProjectInternal owningProject; - private final FileCollectionFingerprinterRegistry fileCollectionFingerprinterRegistry; + private final FileCollectionFingerprinterRegistry globalFingerprinterRegistry; + private final AtomicReference usedFingerprinterRegistry = new AtomicReference<>(); - public TransformationStep(Transformer transformer, TransformerInvoker transformerInvoker, DomainObjectProjectStateHandler projectStateHandler, FileCollectionFingerprinterRegistry fileCollectionFingerprinterRegistry) { + public TransformationStep(Transformer transformer, TransformerInvoker transformerInvoker, DomainObjectProjectStateHandler projectStateHandler, FileCollectionFingerprinterRegistry globalFingerprinterRegistry) { this.transformer = transformer; this.transformerInvoker = transformerInvoker; this.projectStateHandler = projectStateHandler; - this.fileCollectionFingerprinterRegistry = fileCollectionFingerprinterRegistry; + this.globalFingerprinterRegistry = globalFingerprinterRegistry; this.isolationLock = projectStateHandler.newExclusiveOperationLock(); this.owningProject = projectStateHandler.maybeGetOwningProject(); this.isolateAction = transformer.isIsolated() ? null : new WorkNodeAction() { @@ -69,7 +71,7 @@ public Project getProject() { @Override public void run(@Nullable ServiceRegistry registry) { - FileCollectionFingerprinterRegistry fingerprinterRegistry = registry == null ? fileCollectionFingerprinterRegistry : registry.get(FileCollectionFingerprinterRegistry.class); + FileCollectionFingerprinterRegistry fingerprinterRegistry = getFingerprinterRegistry(registry == null ? null : registry.get(FileCollectionFingerprinterRegistry.class)); isolateExclusively(fingerprinterRegistry); } }; @@ -91,7 +93,9 @@ public Try transform(TransformationSubject subjectToTrans LOGGER.info("Transforming {} with {}", subjectToTransform.getDisplayName(), transformer.getDisplayName()); } ImmutableList inputArtifacts = subjectToTransform.getFiles(); - FileCollectionFingerprinterRegistry fingerprinterRegistry = getFingerprinterRegistry(services); + FileCollectionFingerprinterRegistry fingerprinterRegistry = getFingerprinterRegistry( + owningProject != null && services != null ? services.getProjectService(owningProject, FileCollectionFingerprinterRegistry.class) : null + ); isolateTransformerParameters(fingerprinterRegistry); return dependenciesResolver.forTransformer(transformer).flatMap(dependencies -> { ImmutableList.Builder builder = ImmutableList.builder(); @@ -107,8 +111,9 @@ public Try transform(TransformationSubject subjectToTrans }); } - public FileCollectionFingerprinterRegistry getFingerprinterRegistry(@Nullable ProjectExecutionServiceRegistry services) { - return owningProject != null && services != null ? services.getProjectService(owningProject, FileCollectionFingerprinterRegistry.class) : fileCollectionFingerprinterRegistry; + public FileCollectionFingerprinterRegistry getFingerprinterRegistry(@Nullable FileCollectionFingerprinterRegistry candidate) { + usedFingerprinterRegistry.compareAndSet(null, candidate == null ? globalFingerprinterRegistry : candidate); + return usedFingerprinterRegistry.get(); } private void isolateTransformerParameters(FileCollectionFingerprinterRegistry fingerprinterRegistry) { From 2398acadac2fd65aa38ed01fb7b33e91a85fb88f Mon Sep 17 00:00:00 2001 From: Stefan Wolf Date: Wed, 20 Feb 2019 17:29:46 +0100 Subject: [PATCH 048/853] Migrate packaging transforms to new API --- .../gradlebuild/packaging/MinifyPlugin.kt | 6 +- .../gradlebuild/packaging/MinifyTransform.kt | 50 ++++++++---- .../packaging/ShadeClassesTransform.kt | 81 +++++++++++++------ .../gradle/gradlebuild/packaging/ShadedJar.kt | 4 +- .../gradlebuild/packaging/ShadedJarPlugin.kt | 47 +++++------ 5 files changed, 120 insertions(+), 68 deletions(-) diff --git a/buildSrc/subprojects/packaging/src/main/kotlin/org/gradle/gradlebuild/packaging/MinifyPlugin.kt b/buildSrc/subprojects/packaging/src/main/kotlin/org/gradle/gradlebuild/packaging/MinifyPlugin.kt index 1196525ff8403..32e5c3208aa79 100644 --- a/buildSrc/subprojects/packaging/src/main/kotlin/org/gradle/gradlebuild/packaging/MinifyPlugin.kt +++ b/buildSrc/subprojects/packaging/src/main/kotlin/org/gradle/gradlebuild/packaging/MinifyPlugin.kt @@ -51,7 +51,7 @@ open class MinifyPlugin : Plugin { artifactTypes.getByName("jar") { attributes.attribute(minified, java.lang.Boolean.FALSE) } - registerTransform { + registerTransform(MinifyTransform::class) { /* * TODO Why do I have to add artifactType=jar here? According to * the declaration above, it's the only artifact type for which @@ -60,8 +60,8 @@ open class MinifyPlugin : Plugin { */ from.attribute(minified, false).attribute(artifactType, "jar") to.attribute(minified, true).attribute(artifactType, "jar") - artifactTransform(MinifyTransform::class) { - params(keepPatterns) + parameters { + keepClassesByArtifact = keepPatterns } } } diff --git a/buildSrc/subprojects/packaging/src/main/kotlin/org/gradle/gradlebuild/packaging/MinifyTransform.kt b/buildSrc/subprojects/packaging/src/main/kotlin/org/gradle/gradlebuild/packaging/MinifyTransform.kt index cfbe1eff78028..24ef1e55026cd 100644 --- a/buildSrc/subprojects/packaging/src/main/kotlin/org/gradle/gradlebuild/packaging/MinifyTransform.kt +++ b/buildSrc/subprojects/packaging/src/main/kotlin/org/gradle/gradlebuild/packaging/MinifyTransform.kt @@ -17,30 +17,52 @@ package org.gradle.gradlebuild.packaging import com.google.common.io.Files -import org.gradle.api.artifacts.transform.ArtifactTransform +import org.gradle.api.artifacts.transform.AssociatedTransformAction +import org.gradle.api.artifacts.transform.InputArtifact +import org.gradle.api.artifacts.transform.TransformAction +import org.gradle.api.artifacts.transform.TransformOutputs +import org.gradle.api.artifacts.transform.TransformParameters +import org.gradle.api.tasks.Input +import org.gradle.api.tasks.PathSensitive +import org.gradle.api.tasks.PathSensitivity import java.io.BufferedOutputStream import java.io.File import java.io.FileOutputStream import java.util.jar.JarFile import java.util.jar.JarOutputStream -import javax.inject.Inject -open class MinifyTransform @Inject constructor( - private val keepClassesByArtifact: Map> -) : ArtifactTransform() { +@AssociatedTransformAction(MinifyTransformAction::class) +interface MinifyTransform { + @get:Input + var keepClassesByArtifact: Map> +} + + +abstract class MinifyTransformAction : TransformAction { + @get:TransformParameters + abstract val parameters: MinifyTransform + + @get:PathSensitive(PathSensitivity.NAME_ONLY) + @get:InputArtifact + abstract val artifact: File - override fun transform(artifact: File) = - keepClassesByArtifact.asSequence() - .firstOrNull { (key, _) -> artifact.name.startsWith(key) } - ?.value?.let { keepClasses -> listOf(minify(artifact, keepClasses)) } - ?: listOf(artifact) + override fun transform(outputs: TransformOutputs) { + for (entry in parameters.keepClassesByArtifact) { + if (artifact.name.startsWith(entry.key)) { + val nameWithoutExtension = Files.getNameWithoutExtension(artifact.path) + minify(artifact, entry.value, outputs.file("$nameWithoutExtension-min.jar")) + return + } + } + outputs.file(artifact) + } private - fun minify(artifact: File, keepClasses: Set): File { - val jarFile = outputDirectory.resolve("${Files.getNameWithoutExtension(artifact.path)}-min.jar") - val classesDir = outputDirectory.resolve("classes") - val manifestFile = outputDirectory.resolve("MANIFEST.MF") + fun minify(artifact: File, keepClasses: Set, jarFile: File): File { + val tempDirectory = java.nio.file.Files.createTempDirectory(jarFile.name).toFile() + val classesDir = tempDirectory.resolve("classes") + val manifestFile = tempDirectory.resolve("MANIFEST.MF") val classGraph = JarAnalyzer("", keepClasses, keepClasses, setOf()).analyze(artifact, classesDir, manifestFile) createJar(classGraph, classesDir, manifestFile, jarFile) diff --git a/buildSrc/subprojects/packaging/src/main/kotlin/org/gradle/gradlebuild/packaging/ShadeClassesTransform.kt b/buildSrc/subprojects/packaging/src/main/kotlin/org/gradle/gradlebuild/packaging/ShadeClassesTransform.kt index f1a74eb075f9b..71d7778534353 100644 --- a/buildSrc/subprojects/packaging/src/main/kotlin/org/gradle/gradlebuild/packaging/ShadeClassesTransform.kt +++ b/buildSrc/subprojects/packaging/src/main/kotlin/org/gradle/gradlebuild/packaging/ShadeClassesTransform.kt @@ -17,9 +17,14 @@ package org.gradle.gradlebuild.packaging import com.google.gson.Gson -import org.gradle.api.artifacts.transform.ArtifactTransform +import org.gradle.api.artifacts.transform.AssociatedTransformAction +import org.gradle.api.artifacts.transform.InputArtifact +import org.gradle.api.artifacts.transform.TransformAction +import org.gradle.api.artifacts.transform.TransformOutputs +import org.gradle.api.artifacts.transform.TransformParameters +import org.gradle.api.tasks.Classpath +import org.gradle.api.tasks.Input import java.io.File -import javax.inject.Inject private @@ -38,19 +43,35 @@ private const val manifestFileName = "MANIFEST.MF" -open class ShadeClassesTransform @Inject constructor( - private val shadowPackage: String, - private val keepPackages: Set, - private val unshadedPackages: Set, - private val ignorePackages: Set -) : ArtifactTransform() { +@AssociatedTransformAction(ShadeClassesTransformAction::class) +interface ShadeClassesTransform { + @get:Input + var shadowPackage: String + @get:Input + var keepPackages: Set + @get:Input + var unshadedPackages: Set + @get:Input + var ignoredPackages: Set +} + + +abstract class ShadeClassesTransformAction : TransformAction { - override fun transform(input: File): List { + @get:TransformParameters + abstract val parameters: ShadeClassesTransform + + @get:Classpath + @get:InputArtifact + abstract val input: File + + override fun transform(outputs: TransformOutputs) { + val outputDirectory = outputs.dir("shadedClasses") val classesDir = outputDirectory.resolve(relocatedClassesDirName) classesDir.mkdir() val manifestFile = outputDirectory.resolve(manifestFileName) - val classGraph = JarAnalyzer(shadowPackage, keepPackages, unshadedPackages, ignorePackages).analyze(input, classesDir, manifestFile) + val classGraph = JarAnalyzer(parameters.shadowPackage, parameters.keepPackages, parameters.unshadedPackages, parameters.ignoredPackages).analyze(input, classesDir, manifestFile) outputDirectory.resolve(classTreeFileName).bufferedWriter().use { Gson().toJson(classGraph.getDependencies(), it) @@ -58,36 +79,48 @@ open class ShadeClassesTransform @Inject constructor( outputDirectory.resolve(entryPointsFileName).bufferedWriter().use { Gson().toJson(classGraph.entryPoints.map { it.outputClassFilename }, it) } - - return listOf(outputDirectory) } } -open class FindClassTrees : ArtifactTransform() { - override fun transform(input: File): List { - return listOf(input.resolve(classTreeFileName)) +abstract class FindClassTrees : TransformAction { + @get:InputArtifact + abstract val input: File + + override fun transform(outputs: TransformOutputs) { + outputs.file(input.resolve(classTreeFileName)) } } -open class FindEntryPoints : ArtifactTransform() { - override fun transform(input: File): List { - return listOf(input.resolve(entryPointsFileName)) +abstract class FindEntryPoints : TransformAction { + @get:InputArtifact + abstract val input: File + + override fun transform(outputs: TransformOutputs) { + outputs.file(input.resolve(entryPointsFileName)) } } -open class FindRelocatedClasses : ArtifactTransform() { - override fun transform(input: File): List { - return listOf(input.resolve(relocatedClassesDirName)) +abstract class FindRelocatedClasses : TransformAction { + @get:InputArtifact + abstract val input: File + + override fun transform(outputs: TransformOutputs) { + outputs.dir(input.resolve(relocatedClassesDirName)) } } -open class FindManifests : ArtifactTransform() { - override fun transform(input: File): List { +abstract class FindManifests : TransformAction { + @get:InputArtifact + abstract val input: File + + override fun transform(outputs: TransformOutputs) { val manifest = input.resolve(manifestFileName) - return listOf(manifest).filter { it.exists() } + if (manifest.exists()) { + outputs.file(manifest) + } } } diff --git a/buildSrc/subprojects/packaging/src/main/kotlin/org/gradle/gradlebuild/packaging/ShadedJar.kt b/buildSrc/subprojects/packaging/src/main/kotlin/org/gradle/gradlebuild/packaging/ShadedJar.kt index a484a8cec49cd..c3f33d1fb9931 100644 --- a/buildSrc/subprojects/packaging/src/main/kotlin/org/gradle/gradlebuild/packaging/ShadedJar.kt +++ b/buildSrc/subprojects/packaging/src/main/kotlin/org/gradle/gradlebuild/packaging/ShadedJar.kt @@ -72,7 +72,7 @@ open class ShadedJar : DefaultTask() { val classesToInclude = mutableSetOf() - val queue: Queue = ArrayDeque() + val queue: Queue = ArrayDeque() queue.addAll(entryPoints) while (!queue.isEmpty()) { val className = queue.remove() @@ -120,7 +120,7 @@ internal fun buildClassTrees(individualClassTrees: List>>): Map> = individualClassTrees.flatMap { it.entries } .groupingBy { it.key } - .aggregate>, String, Set> { _, accumulator: Set?, element: Map.Entry>, first -> + .aggregate { _, accumulator: Set?, element: Map.Entry>, first -> if (first) { element.value.toSet() } else { diff --git a/buildSrc/subprojects/packaging/src/main/kotlin/org/gradle/gradlebuild/packaging/ShadedJarPlugin.kt b/buildSrc/subprojects/packaging/src/main/kotlin/org/gradle/gradlebuild/packaging/ShadedJarPlugin.kt index e69ef3cf081bc..24c42fa8f0b6d 100644 --- a/buildSrc/subprojects/packaging/src/main/kotlin/org/gradle/gradlebuild/packaging/ShadedJarPlugin.kt +++ b/buildSrc/subprojects/packaging/src/main/kotlin/org/gradle/gradlebuild/packaging/ShadedJarPlugin.kt @@ -17,13 +17,9 @@ package org.gradle.gradlebuild.packaging import accessors.base -import org.gradle.api.Action -import org.gradle.api.ActionConfiguration import org.gradle.api.Plugin import org.gradle.api.Project import org.gradle.api.artifacts.Configuration -import org.gradle.api.artifacts.dsl.DependencyHandler -import org.gradle.api.artifacts.transform.ArtifactTransform import org.gradle.api.attributes.Usage import org.gradle.api.model.ObjectFactory import org.gradle.api.tasks.Copy @@ -33,7 +29,6 @@ import org.gradle.gradlebuild.packaging.Attributes.artifactType import org.gradle.gradlebuild.packaging.Attributes.minified import org.gradle.kotlin.dsl.* import java.io.File -import java.lang.IllegalArgumentException private @@ -85,27 +80,37 @@ open class ShadedJarPlugin : Plugin { fun Project.registerTransforms(shadedJarExtension: ShadedJarExtension) { afterEvaluate { dependencies { - registerTransform { + registerTransform(ShadeClassesTransform::class) { from .attribute(artifactType, "jar") .attribute(minified, true) to.attribute(artifactType, relocatedClassesAndAnalysisType) - artifactTransform(ShadeClassesTransform::class) { - params( - "org.gradle.internal.impldep", - shadedJarExtension.keepPackages.get(), - shadedJarExtension.unshadedPackages.get(), - shadedJarExtension.ignoredPackages.get() - ) + parameters { + shadowPackage = "org.gradle.internal.impldep" + keepPackages = shadedJarExtension.keepPackages.get() + unshadedPackages = shadedJarExtension.unshadedPackages.get() + ignoredPackages = shadedJarExtension.ignoredPackages.get() } } } } dependencies { - registerArtifactTypeTransform(relocatedClassesAndAnalysisType, relocatedClassesType) - registerArtifactTypeTransform(relocatedClassesAndAnalysisType, entryPointsType) - registerArtifactTypeTransform(relocatedClassesAndAnalysisType, classTreesType) - registerArtifactTypeTransform(relocatedClassesAndAnalysisType, manifestsType) + registerTransformAction(FindRelocatedClasses::class) { + from.attribute(artifactType, relocatedClassesAndAnalysisType) + to.attribute(artifactType, relocatedClassesType) + } + registerTransformAction(FindEntryPoints::class) { + from.attribute(artifactType, relocatedClassesAndAnalysisType) + to.attribute(artifactType, entryPointsType) + } + registerTransformAction(FindClassTrees::class) { + from.attribute(artifactType, relocatedClassesAndAnalysisType) + to.attribute(artifactType, classTreesType) + } + registerTransformAction(FindManifests::class) { + from.attribute(artifactType, relocatedClassesAndAnalysisType) + to.attribute(artifactType, manifestsType) + } } } @@ -173,14 +178,6 @@ open class ShadedJarPlugin : Plugin { fun Configuration.artifactViewForType(artifactTypeName: String) = incoming.artifactView { attributes.attribute(artifactType, artifactTypeName) }.files - - private - inline fun DependencyHandler.registerArtifactTypeTransform(fromType: String, toType: String, action: Action = Action {}) = - registerTransform { - from.attribute(artifactType, fromType) - to.attribute(artifactType, toType) - artifactTransform(T::class, action) - } } From 7864d0ba3d39af5e695e3ff41784035763caa202 Mon Sep 17 00:00:00 2001 From: Stefan Wolf Date: Wed, 20 Feb 2019 17:49:55 +0100 Subject: [PATCH 049/853] Migrate api parameter names transform to new API --- .../build/GradleApiParameterNamesTransform.kt | 66 ++++++++++++------- 1 file changed, 43 insertions(+), 23 deletions(-) diff --git a/buildSrc/subprojects/kotlin-dsl/src/main/kotlin/build/GradleApiParameterNamesTransform.kt b/buildSrc/subprojects/kotlin-dsl/src/main/kotlin/build/GradleApiParameterNamesTransform.kt index 49a818f2ad18d..9bf35ae822874 100644 --- a/buildSrc/subprojects/kotlin-dsl/src/main/kotlin/build/GradleApiParameterNamesTransform.kt +++ b/buildSrc/subprojects/kotlin-dsl/src/main/kotlin/build/GradleApiParameterNamesTransform.kt @@ -17,13 +17,18 @@ package build import accessors.sourceSets -import org.gradle.gradlebuild.PublicApi - import org.gradle.api.Project -import org.gradle.api.artifacts.transform.ArtifactTransform +import org.gradle.api.artifacts.transform.AssociatedTransformAction +import org.gradle.api.artifacts.transform.InputArtifact +import org.gradle.api.artifacts.transform.TransformAction +import org.gradle.api.artifacts.transform.TransformOutputs +import org.gradle.api.artifacts.transform.TransformParameters import org.gradle.api.attributes.Attribute import org.gradle.api.file.RelativePath - +import org.gradle.api.tasks.Input +import org.gradle.api.tasks.PathSensitive +import org.gradle.api.tasks.PathSensitivity +import org.gradle.gradlebuild.PublicApi import org.gradle.kotlin.dsl.* import org.gradle.kotlin.dsl.codegen.ParameterNamesSupplier @@ -37,14 +42,12 @@ import org.objectweb.asm.ClassWriter import org.objectweb.asm.MethodVisitor import org.objectweb.asm.Opcodes.ASM6 import org.objectweb.asm.Type - -import java.io.InputStream import java.io.File +import java.io.InputStream import java.util.Properties import java.util.jar.JarEntry import java.util.jar.JarFile import java.util.zip.ZipOutputStream -import javax.inject.Inject // TODO:kotlin-dsl dedupe, see MinifyPlugin @@ -64,11 +67,12 @@ fun Project.withCompileOnlyGradleApiModulesWithParameterNames(vararg gradleModul } dependencies { - registerTransform { + registerTransform(GradleApiParameterNamesTransform::class) { from.attribute(artifactType, "jar").attribute(minified, true) to.attribute(artifactType, jarWithGradleApiParameterNames) - artifactTransform(GradleApiParameterNamesTransform::class) { - params(PublicApi.includes, PublicApi.excludes) + parameters { + publicApiIncludes = PublicApi.includes + publicApiExcludes = PublicApi.excludes } } @@ -85,21 +89,37 @@ fun Project.withCompileOnlyGradleApiModulesWithParameterNames(vararg gradleModul } +@AssociatedTransformAction(GradleApiParameterNamesTransformAction::class) internal -class GradleApiParameterNamesTransform @Inject constructor( - private val publicApiIncludes: List, - private val publicApiExcludes: List -) : ArtifactTransform() { +interface GradleApiParameterNamesTransform { + @get:Input + var publicApiIncludes: List + @get:Input + var publicApiExcludes: List +} - override fun transform(input: File): MutableList = - if (input.name.startsWith("gradle-")) mutableListOf(outputFileFor(input).also { outputFile -> - transformGradleApiJar(input, outputFile) - }) - else mutableListOf(input) + +internal +abstract class GradleApiParameterNamesTransformAction : TransformAction { + + @get:TransformParameters + abstract val parameters: GradleApiParameterNamesTransform + + @get:PathSensitive(PathSensitivity.NAME_ONLY) + @get:InputArtifact + abstract val input: File + + override fun transform(outputs: TransformOutputs) { + if (input.name.startsWith("gradle-")) { + transformGradleApiJar(input, outputs.file(outputFileNameFor(input))) + } else { + outputs.file(input) + } + } private - fun outputFileFor(input: File) = - outputDirectory.resolve("${input.nameWithoutExtension}-with-parameter-names.jar") + fun outputFileNameFor(input: File) = + "${input.nameWithoutExtension}-with-parameter-names.jar" private fun transformGradleApiJar(inputFile: File, outputFile: File) { @@ -134,8 +154,8 @@ class GradleApiParameterNamesTransform @Inject constructor( } } return GradleApiMetadata( - publicApiIncludes, - publicApiExcludes, + parameters.publicApiIncludes, + parameters.publicApiExcludes, { key: String -> parameterNamesIndex.getProperty(key, null)?.split(",") } ) } From 8c25f0bd2e0cd0ffbd25506cdcd53af3a5b70495 Mon Sep 17 00:00:00 2001 From: Stefan Wolf Date: Wed, 20 Feb 2019 18:25:01 +0100 Subject: [PATCH 050/853] Migrate ExtractGradleSourcesTransform to new API --- .../resolver/ExtractGradleSourcesTransform.kt | 35 ++++++++++++++----- .../resolver/SourceDistributionProvider.kt | 18 ++++++---- 2 files changed, 38 insertions(+), 15 deletions(-) diff --git a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/resolver/ExtractGradleSourcesTransform.kt b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/resolver/ExtractGradleSourcesTransform.kt index 7aa8e0bd8ee14..8aef467b9baee 100644 --- a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/resolver/ExtractGradleSourcesTransform.kt +++ b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/resolver/ExtractGradleSourcesTransform.kt @@ -16,7 +16,11 @@ package org.gradle.kotlin.dsl.resolver -import org.gradle.api.artifacts.transform.ArtifactTransform +import org.gradle.api.artifacts.transform.InputArtifact +import org.gradle.api.artifacts.transform.TransformAction +import org.gradle.api.artifacts.transform.TransformOutputs +import org.gradle.api.tasks.PathSensitive +import org.gradle.api.tasks.PathSensitivity import org.gradle.kotlin.dsl.support.unzipTo @@ -28,20 +32,22 @@ import java.io.File * a downloaded ZIP of the Gradle sources, and will return the list of main sources * subdirectories for all subprojects. */ -class ExtractGradleSourcesTransform : ArtifactTransform() { +abstract class ExtractGradleSourcesTransform : TransformAction { + @get:InputArtifact + abstract val input: File - override fun transform(input: File): List { - unzipTo(outputDirectory, input) - return sourceDirectories() + override fun transform(outputs: TransformOutputs) { + registerSourceDirectories(outputs) } private - fun sourceDirectories() = + fun registerSourceDirectories(outputs: TransformOutputs) { unzippedSubProjectsDir()?.let { subDirsOf(it).flatMap { subProject -> subDirsOf(File(subProject, "src/main")) - } - } ?: emptyList() + }.forEach { outputs.dir(it) } + } + } private fun unzippedSubProjectsDir(): File? = @@ -51,5 +57,16 @@ class ExtractGradleSourcesTransform : ArtifactTransform() { private fun unzippedDistroDir(): File? = - outputDirectory.listFiles().singleOrNull() + input.listFiles().singleOrNull() +} + + +abstract class UnzipDistributionTransform : TransformAction { + @get:PathSensitive(PathSensitivity.NONE) + @get:InputArtifact + abstract val input: File + + override fun transform(outputs: TransformOutputs) { + unzipTo(outputs.dir("unzipped-distribution"), input) + } } diff --git a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/resolver/SourceDistributionProvider.kt b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/resolver/SourceDistributionProvider.kt index 9dc8f6e28dd8e..ab04c30e7398f 100644 --- a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/resolver/SourceDistributionProvider.kt +++ b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/resolver/SourceDistributionProvider.kt @@ -20,7 +20,8 @@ import org.gradle.api.Project import org.gradle.api.artifacts.Dependency import org.gradle.api.artifacts.repositories.ArtifactRepository import org.gradle.api.artifacts.repositories.IvyArtifactRepository -import org.gradle.api.artifacts.transform.VariantTransform +import org.gradle.api.artifacts.transform.TransformAction +import org.gradle.api.artifacts.transform.TransformSpec import org.gradle.api.attributes.Attribute import org.gradle.kotlin.dsl.create @@ -40,6 +41,7 @@ class SourceDistributionResolver(val project: Project) : SourceDistributionProvi companion object { val artifactType = Attribute.of("artifactType", String::class.java) val zipType = "zip" + val unzippedDistributionType = "unzipped-distribution" val sourceDirectory = "src-directory" } @@ -69,12 +71,16 @@ class SourceDistributionResolver(val project: Project) : SourceDistributionProvi } private - fun registerTransforms() = - registerTransform { + fun registerTransforms() { + registerTransformAction { from.attribute(artifactType, zipType) + to.attribute(artifactType, unzippedDistributionType) + } + registerTransformAction { + from.attribute(artifactType, unzippedDistributionType) to.attribute(artifactType, sourceDirectory) - artifactTransform(ExtractGradleSourcesTransform::class.java) } + } private fun transientConfigurationForSourcesDownload() = @@ -147,8 +153,8 @@ class SourceDistributionResolver(val project: Project) : SourceDistributionProvi } private - fun registerTransform(configure: VariantTransform.() -> Unit) = - dependencies.registerTransform { configure(it) } + inline fun registerTransformAction(crossinline configure: TransformSpec.() -> Unit) = + dependencies.registerTransformAction(T::class.java) { configure(it) } private fun ivy(configure: IvyArtifactRepository.() -> Unit) = From b3b85ca57c4022da247519d99b71acb9abec8f25 Mon Sep 17 00:00:00 2001 From: Stefan Wolf Date: Wed, 20 Feb 2019 22:30:26 +0100 Subject: [PATCH 051/853] Migrate binary compat transforms to new API --- .../transforms/ExplodeZipAndFindJars.groovy | 50 +++++++++---------- .../transforms/FindGradleClasspath.groovy | 27 +++++----- .../transforms/FindGradleJar.groovy | 44 +++++++++++----- .../distributions/binary-compatibility.gradle | 12 ++--- 4 files changed, 76 insertions(+), 57 deletions(-) diff --git a/buildSrc/subprojects/binary-compatibility/src/main/groovy/org/gradle/binarycompatibility/transforms/ExplodeZipAndFindJars.groovy b/buildSrc/subprojects/binary-compatibility/src/main/groovy/org/gradle/binarycompatibility/transforms/ExplodeZipAndFindJars.groovy index 36434bad68c10..79c29f4537cf6 100644 --- a/buildSrc/subprojects/binary-compatibility/src/main/groovy/org/gradle/binarycompatibility/transforms/ExplodeZipAndFindJars.groovy +++ b/buildSrc/subprojects/binary-compatibility/src/main/groovy/org/gradle/binarycompatibility/transforms/ExplodeZipAndFindJars.groovy @@ -18,40 +18,40 @@ package org.gradle.binarycompatibility.transforms import groovy.transform.CompileStatic -import org.gradle.api.artifacts.transform.ArtifactTransform +import org.gradle.api.artifacts.transform.InputArtifact +import org.gradle.api.artifacts.transform.TransformAction +import org.gradle.api.artifacts.transform.TransformOutputs +import org.gradle.api.tasks.PathSensitive +import org.gradle.api.tasks.PathSensitivity import java.util.zip.ZipEntry import java.util.zip.ZipInputStream import java.nio.file.Files @CompileStatic -class ExplodeZipAndFindJars extends ArtifactTransform { +abstract class ExplodeZipAndFindJars implements TransformAction { + + @PathSensitive(PathSensitivity.NAME_ONLY) + @InputArtifact + abstract File getArtifact() @Override - List transform(final File file) { - List result = [] - if (outputDirectory.exists() && outputDirectory.listFiles().length == 0) { - File gradleJars = new File(outputDirectory, "gradle-jars") - File dependencies = new File(outputDirectory, "gradle-dependencies") - gradleJars.mkdir() - dependencies.mkdir() - result << gradleJars - result << dependencies - ZipInputStream zin = new ZipInputStream(file.newInputStream()) - ZipEntry zipEntry - while (zipEntry = zin.nextEntry) { - String shortName = zipEntry.name - if (shortName.contains('/')) { - shortName = shortName.substring(shortName.lastIndexOf('/') + 1) - } - if (shortName.endsWith('.jar')) { - def outputDir = shortName.startsWith('gradle-') ? gradleJars : dependencies - def out = new File(outputDir, shortName) - Files.copy(zin, out.toPath()) - zin.closeEntry() - } + void transform(TransformOutputs outputs) { + File gradleJars = outputs.dir("gradle-jars") + File dependencies = outputs.dir("gradle-dependencies") + ZipInputStream zin = new ZipInputStream(artifact.newInputStream()) + ZipEntry zipEntry + while (zipEntry = zin.nextEntry) { + String shortName = zipEntry.name + if (shortName.contains('/')) { + shortName = shortName.substring(shortName.lastIndexOf('/') + 1) + } + if (shortName.endsWith('.jar')) { + def outputDir = shortName.startsWith('gradle-') ? gradleJars : dependencies + def out = new File(outputDir, shortName) + Files.copy(zin, out.toPath()) + zin.closeEntry() } } - result } } diff --git a/buildSrc/subprojects/binary-compatibility/src/main/groovy/org/gradle/binarycompatibility/transforms/FindGradleClasspath.groovy b/buildSrc/subprojects/binary-compatibility/src/main/groovy/org/gradle/binarycompatibility/transforms/FindGradleClasspath.groovy index 7b7456e1b8be6..9563793a3d9d8 100644 --- a/buildSrc/subprojects/binary-compatibility/src/main/groovy/org/gradle/binarycompatibility/transforms/FindGradleClasspath.groovy +++ b/buildSrc/subprojects/binary-compatibility/src/main/groovy/org/gradle/binarycompatibility/transforms/FindGradleClasspath.groovy @@ -14,26 +14,29 @@ * limitations under the License. */ - package org.gradle.binarycompatibility.transforms -import org.gradle.api.artifacts.transform.ArtifactTransform -import javax.inject.Inject +import org.gradle.api.artifacts.transform.InputArtifact +import org.gradle.api.artifacts.transform.TransformAction +import org.gradle.api.artifacts.transform.TransformOutputs +import org.gradle.api.tasks.PathSensitive +import org.gradle.api.tasks.PathSensitivity + import groovy.transform.CompileStatic @CompileStatic -class FindGradleClasspath extends ArtifactTransform { +abstract class FindGradleClasspath implements TransformAction { - @Inject - FindGradleClasspath() { - } + @PathSensitive(PathSensitivity.NAME_ONLY) + @InputArtifact + abstract File getArtifact() @Override - List transform(final File file) { - if (file.name == 'gradle-dependencies') { - (file.listFiles() as List).sort { it.name } - } else { - [] + void transform(TransformOutputs outputs) { + if (artifact.name == 'gradle-dependencies') { + (artifact.listFiles() as List).sort { it.name }.each { + outputs.file(it) + } } } } diff --git a/buildSrc/subprojects/binary-compatibility/src/main/groovy/org/gradle/binarycompatibility/transforms/FindGradleJar.groovy b/buildSrc/subprojects/binary-compatibility/src/main/groovy/org/gradle/binarycompatibility/transforms/FindGradleJar.groovy index 80a362563ad56..3e4bc063d9152 100644 --- a/buildSrc/subprojects/binary-compatibility/src/main/groovy/org/gradle/binarycompatibility/transforms/FindGradleJar.groovy +++ b/buildSrc/subprojects/binary-compatibility/src/main/groovy/org/gradle/binarycompatibility/transforms/FindGradleJar.groovy @@ -17,25 +17,43 @@ package org.gradle.binarycompatibility.transforms -import org.gradle.api.artifacts.transform.ArtifactTransform -import javax.inject.Inject +import org.gradle.api.artifacts.transform.AssociatedTransformAction +import org.gradle.api.artifacts.transform.InputArtifact +import org.gradle.api.artifacts.transform.TransformAction +import org.gradle.api.artifacts.transform.TransformOutputs +import org.gradle.api.artifacts.transform.TransformParameters +import org.gradle.api.tasks.Input +import org.gradle.api.tasks.PathSensitive +import org.gradle.api.tasks.PathSensitivity + import groovy.transform.CompileStatic +@AssociatedTransformAction(FindGradleJarAction) @CompileStatic -class FindGradleJar extends ArtifactTransform { - private final String target +interface FindGradleJar { + @Input + String getTarget() + void setTarget(String target) +} - @Inject - FindGradleJar(String target) { - this.target = target - } +@CompileStatic +abstract class FindGradleJarAction implements TransformAction { + + @TransformParameters + abstract FindGradleJar getParameters() + + @PathSensitive(PathSensitivity.NAME_ONLY) + @InputArtifact + abstract File getArtifact() @Override - List transform(final File file) { - if (file.name == 'gradle-jars') { - (file.listFiles().findAll { it.name.startsWith("gradle-${target}-") } as List).sort { it.name } - } else { - [] + void transform(TransformOutputs outputs) { + if (artifact.name == 'gradle-jars') { + (artifact.listFiles().findAll { + it.name.startsWith("gradle-${parameters.target}-") + } as List).sort { it.name }.each { + outputs.file(it) + } } } } diff --git a/subprojects/distributions/binary-compatibility.gradle b/subprojects/distributions/binary-compatibility.gradle index c3f79f0c04679..259eb72c0e267 100644 --- a/subprojects/distributions/binary-compatibility.gradle +++ b/subprojects/distributions/binary-compatibility.gradle @@ -66,25 +66,23 @@ dependencies { // This transform takes the Gradle zip distribution, // and unzips the Gradle jar files that it contains in a directory - registerTransform { + registerTransformAction(ExplodeZipAndFindJars) { from.attribute(ARTIFACT_TYPE, 'zip') to.attribute(ARTIFACT_TYPE, 'gradle-libs-dir') - artifactTransform(ExplodeZipAndFindJars) } - registerTransform { + registerTransformAction(FindGradleClasspath) { from.attribute(ARTIFACT_TYPE, 'gradle-libs-dir') to.attribute(ARTIFACT_TYPE, 'gradle-classpath') - artifactTransform(FindGradleClasspath) } projects.each { projectName -> // This transform uses the result of the exploded zip extraction // and returns a single jar file based on the lookup project name - registerTransform { + registerTransform(FindGradleJar) { from.attribute(ARTIFACT_TYPE, 'gradle-libs-dir') to.attribute(ARTIFACT_TYPE, projectName) - artifactTransform(FindGradleJar) { - params(projectName) + parameters { + target = projectName } } } From c7d9326e2a032c473526615afe3cdd59ef57e342 Mon Sep 17 00:00:00 2001 From: Gradleware Git Bot Date: Fri, 22 Feb 2019 20:36:19 +0100 Subject: [PATCH 052/853] Publish 5.3-20190222192132+0000 --- released-versions.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/released-versions.json b/released-versions.json index c81416bf1e813..47ca1c112af1e 100644 --- a/released-versions.json +++ b/released-versions.json @@ -1,7 +1,7 @@ { "latestReleaseSnapshot": { - "version": "5.3-20190222020858+0000", - "buildTime": "20190222020858+0000" + "version": "5.3-20190222192132+0000", + "buildTime": "20190222192132+0000" }, "latestRc": { "version": "5.2-rc-1", From e4842f62661eccd8cc6e31e1a8091c1796d71d73 Mon Sep 17 00:00:00 2001 From: Cedric Champeau Date: Tue, 19 Feb 2019 15:30:04 +0100 Subject: [PATCH 053/853] Introduce `TargetJavaPlatform` attribute This commit adds a new Java ecosystem attribute, corresponding to the minimal target platform a producer supports. It's often the case that Java libraries are published with different classifiers for different target platforms. However, a classifier is not enough. With this attribute, we now have a proper model of the producer and consumer side. By default, the producer will not ask for a specific target platform, but will only accept those which are lower than or equal to the current Gradle runtime version. However, if the consumer says something, it will then select the most appropriate variant based on the producer attributes. In the Java world, a consumer can use Java libraries produced for older versions of Java, but not newer versions. This rule is baked in as the default compatibility rule. Disambiguation will then chose the closest version. --- .../attributes/java/TargetJavaPlatform.java | 34 ++++ .../artifacts/JavaEcosystemSupport.java | 84 +++++++++- .../TargetJavaPlatformRulesTest.groovy | 84 ++++++++++ ...ipleVariantSelectionIntegrationTest.groovy | 9 +- .../configurations/ConfigurationInternal.java | 6 + .../configurations/DefaultConfiguration.java | 18 +++ .../parser/ModuleMetadataParser.java | 4 + ...ncyInsightReportTaskIntegrationTest.groovy | 6 + ...ReportVariantDetailsIntegrationTest.groovy | 2 + .../test/fixtures/GradleModuleMetadata.groovy | 4 + .../gradle/VariantMetadataSpec.groovy | 4 + .../test/fixtures/ivy/IvyJavaModule.groovy | 4 +- .../fixtures/maven/MavenJavaModule.groovy | 17 +- ...tionOutgoingVariantsIntegrationTest.groovy | 49 +++--- ...rojectTargetPlatformIntegrationTest.groovy | 124 +++++++++++++++ ...raryOutgoingVariantsIntegrationTest.groovy | 49 +++--- ...lishedTargetPlatformIntegrationTest.groovy | 147 ++++++++++++++++++ ...jectOutgoingVariantsIntegrationTest.groovy | 49 +++--- .../ConfigurationVariantMapping.java | 7 +- .../org/gradle/api/plugins/JavaPlugin.java | 48 +++++- .../DefaultAdhocSoftwareComponent.java | 3 +- .../internal/DefaultJavaFeatureSpec.java | 19 +++ .../internal/ModuleMetadataFileGenerator.java | 3 + .../impl/CoercingStringValueSnapshot.java | 3 + 24 files changed, 692 insertions(+), 85 deletions(-) create mode 100644 subprojects/core-api/src/main/java/org/gradle/api/attributes/java/TargetJavaPlatform.java create mode 100644 subprojects/core/src/test/groovy/org/gradle/api/internal/artifacts/TargetJavaPlatformRulesTest.groovy create mode 100644 subprojects/plugins/src/integTest/groovy/org/gradle/java/JavaLibraryCrossProjectTargetPlatformIntegrationTest.groovy create mode 100644 subprojects/plugins/src/integTest/groovy/org/gradle/java/JavaLibraryPublishedTargetPlatformIntegrationTest.groovy diff --git a/subprojects/core-api/src/main/java/org/gradle/api/attributes/java/TargetJavaPlatform.java b/subprojects/core-api/src/main/java/org/gradle/api/attributes/java/TargetJavaPlatform.java new file mode 100644 index 0000000000000..63442bc0e0016 --- /dev/null +++ b/subprojects/core-api/src/main/java/org/gradle/api/attributes/java/TargetJavaPlatform.java @@ -0,0 +1,34 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.gradle.api.attributes.java; + +import org.gradle.api.Incubating; +import org.gradle.api.attributes.Attribute; + +/** + * Represents the target platform of a Java library or platform. The target level is expected to correspond + * to a Java platform version number (integer). For example, "5" for Java 5, "8" for Java 8, or "11" for Java 11. + * + * @since 5.3 + */ +@Incubating +public interface TargetJavaPlatform { + + /** + * The minimal target platform for a Java library. Any consumer below this version would not be able to consume it. + */ + Attribute MINIMAL_TARGET_PLATFORM_ATTRIBUTE = Attribute.of("org.gradle.java.min.platform", Integer.class); +} diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/artifacts/JavaEcosystemSupport.java b/subprojects/core/src/main/java/org/gradle/api/internal/artifacts/JavaEcosystemSupport.java index c0bcc40fed59a..e9a1c872ad6df 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/artifacts/JavaEcosystemSupport.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/artifacts/JavaEcosystemSupport.java @@ -19,6 +19,7 @@ import com.google.common.collect.ImmutableSet; import org.gradle.api.Action; import org.gradle.api.ActionConfiguration; +import org.gradle.api.JavaVersion; import org.gradle.api.attributes.AttributeCompatibilityRule; import org.gradle.api.attributes.AttributeDisambiguationRule; import org.gradle.api.attributes.AttributeMatchingStrategy; @@ -27,6 +28,7 @@ import org.gradle.api.attributes.MultipleCandidatesDetails; import org.gradle.api.attributes.Usage; import org.gradle.api.attributes.Bundling; +import org.gradle.api.attributes.java.TargetJavaPlatform; import org.gradle.api.internal.ReusableAction; import org.gradle.api.model.ObjectFactory; @@ -35,6 +37,31 @@ public abstract class JavaEcosystemSupport { public static void configureSchema(AttributesSchema attributesSchema, final ObjectFactory objectFactory) { + configureUsage(attributesSchema, objectFactory); + configureBundling(attributesSchema); + configureTargetPlatform(attributesSchema); + } + + private static void configureTargetPlatform(AttributesSchema attributesSchema) { + AttributeMatchingStrategy targetPlatformSchema = attributesSchema.attribute(TargetJavaPlatform.MINIMAL_TARGET_PLATFORM_ATTRIBUTE); + targetPlatformSchema.getCompatibilityRules().add(TargetPlatformCompatibilityRules.class); + targetPlatformSchema.getDisambiguationRules().add(TargetPlatformDisambiguationRules.class, new Action() { + @Override + public void execute(ActionConfiguration config) { + // by default we will reject any producer which version is higher than + // the current Gradle runtime (if the consumer says nothing) + config.params(Integer.valueOf(JavaVersion.current().getMajorVersion())); + } + }); + } + + private static void configureBundling(AttributesSchema attributesSchema) { + AttributeMatchingStrategy bundlingSchema = attributesSchema.attribute(Bundling.BUNDLING_ATTRIBUTE); + bundlingSchema.getCompatibilityRules().add(BundlingCompatibilityRules.class); + bundlingSchema.getDisambiguationRules().add(BundlingDisambiguationRules.class); + } + + private static void configureUsage(AttributesSchema attributesSchema, final ObjectFactory objectFactory) { AttributeMatchingStrategy usageSchema = attributesSchema.attribute(Usage.USAGE_ATTRIBUTE); usageSchema.getCompatibilityRules().add(UsageCompatibilityRules.class); usageSchema.getDisambiguationRules().add(UsageDisambiguationRules.class, new Action() { @@ -49,9 +76,6 @@ public void execute(ActionConfiguration actionConfiguration) { actionConfiguration.params(objectFactory.named(Usage.class, Usage.JAVA_RUNTIME_RESOURCES)); } }); - AttributeMatchingStrategy bundlingSchema = attributesSchema.attribute(Bundling.BUNDLING_ATTRIBUTE); - bundlingSchema.getCompatibilityRules().add(BundlingCompatibilityRules.class); - bundlingSchema.getDisambiguationRules().add(BundlingDisambiguationRules.class); } @VisibleForTesting @@ -270,4 +294,58 @@ public void execute(MultipleCandidatesDetails details) { } } } + + @VisibleForTesting + public static class TargetPlatformCompatibilityRules implements AttributeCompatibilityRule, ReusableAction { + @Override + public void execute(CompatibilityCheckDetails details) { + Integer consumerLevel = details.getConsumerValue(); + Integer producerLevel = details.getProducerValue(); + if (consumerLevel == null || producerLevel == null) { + details.compatible(); + return; + } + if (producerLevel <= consumerLevel) { + details.compatible(); + } else { + details.incompatible(); + } + } + } + + @VisibleForTesting + public static class TargetPlatformDisambiguationRules implements AttributeDisambiguationRule, ReusableAction { + private final int minimalPlatformVersion; + + @Inject + public TargetPlatformDisambiguationRules(int minimalPlatformVersion) { + this.minimalPlatformVersion = minimalPlatformVersion; + } + + @Override + public void execute(MultipleCandidatesDetails details) { + Integer consumerLevel = details.getConsumerValue(); + boolean checkMinimalBound = false; + if (consumerLevel == null) { + consumerLevel = minimalPlatformVersion; + checkMinimalBound = true; + } + int selected = Integer.MAX_VALUE; + int diff = Integer.MAX_VALUE; + for (Integer producerLevel : details.getCandidateValues()) { + if (checkMinimalBound && producerLevel> consumer + 1 * details.getProducerValue() >> producer + + if (compatible) { + 1 * details.compatible() + } else { + 1 * details.incompatible() + } + + where: + consumer | producer | compatible + null | 5 | true + null | 6 | true + null | 11 | true + + 8 | 6 | true + 8 | 7 | true + 8 | 8 | true + 8 | 9 | false + 8 | 10 | false + 8 | 11 | false + } + + @Unroll("disamgiguates when consumer=#consumer and candidates=#candidates chooses=#expected") + def "check disambiguation rules"() { + MultipleCandidatesDetails details = Mock(MultipleCandidatesDetails) + + when: + disambiguationRules.execute(details) + + then: + 1 * details.getConsumerValue() >> consumer + 1 * details.getCandidateValues() >> candidates + 1 * details.closestMatch(expected) + + where: + consumer | candidates | expected + null | [4, 8, 11] | 8 + null | [11, 8] | 8 + + 6 | [6] | 6 + 7 | [6, 7] | 7 + 8 | [6, 7] | 7 + 9 | [6, 7, 9] | 9 + 10 | [6, 7, 9] | 9 + 11 | [6, 7, 9] | 9 + + } +} diff --git a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/attributes/CrossProjectMultipleVariantSelectionIntegrationTest.groovy b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/attributes/CrossProjectMultipleVariantSelectionIntegrationTest.groovy index 4ffd3e899420e..1d324d4ce68ec 100644 --- a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/attributes/CrossProjectMultipleVariantSelectionIntegrationTest.groovy +++ b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/attributes/CrossProjectMultipleVariantSelectionIntegrationTest.groovy @@ -16,6 +16,7 @@ package org.gradle.integtests.resolve.attributes +import org.gradle.api.JavaVersion import org.gradle.integtests.fixtures.AbstractDependencyResolutionTest import org.gradle.integtests.fixtures.resolve.ResolveTestFixture @@ -48,6 +49,7 @@ class CrossProjectMultipleVariantSelectionIntegrationTest extends AbstractDepend attributes { attribute(Usage.USAGE_ATTRIBUTE, project.objects.named(Usage, 'java-api-jars')) attribute(Bundling.BUNDLING_ATTRIBUTE, project.objects.named(Bundling, Bundling.EXTERNAL)) + attribute(TargetJavaPlatform.MINIMAL_TARGET_PLATFORM_ATTRIBUTE, Integer.valueOf(JavaVersion.current().majorVersion)) } outgoing.capability('org:lib-fixtures:1.0') } @@ -79,11 +81,11 @@ class CrossProjectMultipleVariantSelectionIntegrationTest extends AbstractDepend resolve.expectGraph { root(":", ":test:") { project(":lib", "test:lib:") { - variant "apiElements", ['org.gradle.usage':'java-api-jars', 'org.gradle.dependency.bundling':'external'] + variant "apiElements", ['org.gradle.usage':'java-api-jars', 'org.gradle.dependency.bundling':'external', 'org.gradle.java.min.platform': JavaVersion.current().majorVersion] artifact group:'', module:'', version: '', type: '', name: 'main', noType: true } project(":lib", "test:lib:") { - variant "testFixtures", ['org.gradle.usage':'java-api-jars', 'org.gradle.dependency.bundling':'external'] + variant "testFixtures", ['org.gradle.usage':'java-api-jars', 'org.gradle.dependency.bundling':'external', 'org.gradle.java.min.platform': JavaVersion.current().majorVersion] artifact group:'test', module:'lib', version:'unspecified', classifier: 'test-fixtures' } } @@ -102,6 +104,7 @@ class CrossProjectMultipleVariantSelectionIntegrationTest extends AbstractDepend attributes { attribute(Usage.USAGE_ATTRIBUTE, project.objects.named(Usage, 'java-api-jars')) attribute(Bundling.BUNDLING_ATTRIBUTE, project.objects.named(Bundling, Bundling.EXTERNAL)) + attribute(TargetJavaPlatform.MINIMAL_TARGET_PLATFORM_ATTRIBUTE, Integer.valueOf(JavaVersion.current().majorVersion)) } outgoing.capability('test:lib:1.0') outgoing.capability('test:lib-fixtures:1.0') @@ -126,7 +129,7 @@ class CrossProjectMultipleVariantSelectionIntegrationTest extends AbstractDepend resolve.expectGraph { root(":", ":test:") { project(":lib", "test:lib:") { - variant "apiElements", ['org.gradle.usage':'java-api-jars', 'org.gradle.dependency.bundling':'external'] + variant "apiElements", ['org.gradle.usage':'java-api-jars', 'org.gradle.dependency.bundling':'external', 'org.gradle.java.min.platform': JavaVersion.current().majorVersion] artifact group:'', module:'', version: '', type: '', name: 'main', noType: true } } diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/configurations/ConfigurationInternal.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/configurations/ConfigurationInternal.java index 0901dff0d1a19..0558a73d74146 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/configurations/ConfigurationInternal.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/configurations/ConfigurationInternal.java @@ -15,6 +15,7 @@ */ package org.gradle.api.internal.artifacts.configurations; +import org.gradle.api.Action; import org.gradle.api.artifacts.Configuration; import org.gradle.api.artifacts.ExcludeRule; import org.gradle.api.internal.artifacts.ResolveContext; @@ -59,6 +60,11 @@ enum InternalState { */ OutgoingVariant convertToOutgoingVariant(); + /** + * Registers an action to execute before locking for further mutation. + */ + void beforeLocking(Action action); + void preventFromFurtherMutation(); /** diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/configurations/DefaultConfiguration.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/configurations/DefaultConfiguration.java index b7bfb5c149aed..9187c1c8d759e 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/configurations/DefaultConfiguration.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/configurations/DefaultConfiguration.java @@ -96,6 +96,7 @@ import org.gradle.api.tasks.TaskDependency; import org.gradle.configuration.internal.UserCodeApplicationContext; import org.gradle.initialization.ProjectAccessListener; +import org.gradle.internal.Actions; import org.gradle.internal.Cast; import org.gradle.internal.Describables; import org.gradle.internal.DisplayName; @@ -218,6 +219,8 @@ public void validateMutation(MutationType type) { private CollectionCallbackActionDecorator callbackActionDecorator; private UserCodeApplicationContext userCodeApplicationContext; + private Action beforeLocking; + public DefaultConfiguration(DomainObjectContext domainObjectContext, String name, ConfigurationsProvider configurationsProvider, @@ -869,10 +872,25 @@ public OutgoingVariant convertToOutgoingVariant() { return outgoing.convertToOutgoingVariant(); } + @Override + public void beforeLocking(Action action) { + if (canBeMutated) { + if (beforeLocking != null) { + beforeLocking = Actions.composite(beforeLocking, action); + } else { + beforeLocking = action; + } + } + } + @Override public void preventFromFurtherMutation() { // TODO This should use the same `MutationValidator` infrastructure that we use for other mutation types if (canBeMutated) { + if (beforeLocking != null) { + beforeLocking.execute(this); + beforeLocking = null; + } AttributeContainerInternal delegatee = configurationAttributes.asImmutable(); configurationAttributes = new ImmutableAttributeContainerWithErrorMessage(delegatee, this.displayName); outgoing.preventFromFurtherMutation(); diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/parser/ModuleMetadataParser.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/parser/ModuleMetadataParser.java index 0a68f03699960..7fa9be54b5f3a 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/parser/ModuleMetadataParser.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/parser/ModuleMetadataParser.java @@ -51,6 +51,7 @@ import static com.google.gson.stream.JsonToken.BOOLEAN; import static com.google.gson.stream.JsonToken.END_ARRAY; import static com.google.gson.stream.JsonToken.END_OBJECT; +import static com.google.gson.stream.JsonToken.NUMBER; import static org.apache.commons.lang.StringUtils.capitalize; public class ModuleMetadataParser { @@ -390,6 +391,9 @@ private ImmutableAttributes consumeAttributes(JsonReader reader) throws IOExcept if (reader.peek() == BOOLEAN) { boolean attrValue = reader.nextBoolean(); attributes = attributesFactory.concat(attributes, Attribute.of(attrName, Boolean.class), attrValue); + } else if (reader.peek() == NUMBER) { + Integer attrValue = reader.nextInt(); + attributes = attributesFactory.concat(attributes, Attribute.of(attrName, Integer.class), attrValue); } else { String attrValue = reader.nextString(); attributes = attributesFactory.concat(attributes, Attribute.of(attrName, String.class), new CoercingStringValueSnapshot(attrValue, instantiator)); diff --git a/subprojects/diagnostics/src/integTest/groovy/org/gradle/api/tasks/diagnostics/DependencyInsightReportTaskIntegrationTest.groovy b/subprojects/diagnostics/src/integTest/groovy/org/gradle/api/tasks/diagnostics/DependencyInsightReportTaskIntegrationTest.groovy index 0d57b07fe5d27..4e19023f0dd11 100644 --- a/subprojects/diagnostics/src/integTest/groovy/org/gradle/api/tasks/diagnostics/DependencyInsightReportTaskIntegrationTest.groovy +++ b/subprojects/diagnostics/src/integTest/groovy/org/gradle/api/tasks/diagnostics/DependencyInsightReportTaskIntegrationTest.groovy @@ -17,6 +17,7 @@ package org.gradle.api.tasks.diagnostics import groovy.transform.CompileStatic +import org.gradle.api.JavaVersion import org.gradle.integtests.fixtures.AbstractIntegrationSpec import org.gradle.integtests.fixtures.FeaturePreviewsFixture import org.gradle.integtests.fixtures.resolve.ResolveTestFixture @@ -1704,6 +1705,7 @@ project : variant "runtimeElements" [ org.gradle.usage = java-runtime-jars (not requested) org.gradle.dependency.bundling = external (not requested) + org.gradle.java.min.platform = ${JavaVersion.current().majorVersion} (not requested) ] project : @@ -1802,6 +1804,7 @@ project :impl variant "runtimeElements" [ org.gradle.usage = java-runtime-jars (not requested) org.gradle.dependency.bundling = external (not requested) + org.gradle.java.min.platform = ${JavaVersion.current().majorVersion} (not requested) ] project :impl @@ -1968,6 +1971,7 @@ project :api variant "apiElements" [ org.gradle.usage = java-api-jars (compatible with: java-api) org.gradle.dependency.bundling = external + org.gradle.java.min.platform = ${JavaVersion.current().majorVersion} (not requested) ] project :api @@ -1984,6 +1988,7 @@ project :some:deeply:nested variant "apiElements" [ org.gradle.usage = java-api-jars (compatible with: java-api) org.gradle.dependency.bundling = external + org.gradle.java.min.platform = ${JavaVersion.current().majorVersion} (not requested) ] project :some:deeply:nested @@ -1999,6 +2004,7 @@ project :some:deeply:nested variant "apiElements" [ org.gradle.usage = java-api-jars (compatible with: java-api) org.gradle.dependency.bundling = external + org.gradle.java.min.platform = ${JavaVersion.current().majorVersion} (not requested) ] project :some:deeply:nested diff --git a/subprojects/diagnostics/src/integTest/groovy/org/gradle/api/tasks/diagnostics/DependencyInsightReportVariantDetailsIntegrationTest.groovy b/subprojects/diagnostics/src/integTest/groovy/org/gradle/api/tasks/diagnostics/DependencyInsightReportVariantDetailsIntegrationTest.groovy index 945c59e88c47d..56aba0ce74dad 100644 --- a/subprojects/diagnostics/src/integTest/groovy/org/gradle/api/tasks/diagnostics/DependencyInsightReportVariantDetailsIntegrationTest.groovy +++ b/subprojects/diagnostics/src/integTest/groovy/org/gradle/api/tasks/diagnostics/DependencyInsightReportVariantDetailsIntegrationTest.groovy @@ -16,6 +16,7 @@ package org.gradle.api.tasks.diagnostics +import org.gradle.api.JavaVersion import org.gradle.integtests.fixtures.AbstractIntegrationSpec import org.gradle.integtests.fixtures.FeaturePreviewsFixture import org.gradle.integtests.fixtures.resolve.ResolveTestFixture @@ -56,6 +57,7 @@ class DependencyInsightReportVariantDetailsIntegrationTest extends AbstractInteg variant "$expectedVariant" [ $expectedAttributes org.gradle.dependency.bundling = external + org.gradle.java.min.platform = ${JavaVersion.current().majorVersion} (not requested) ] project :$expectedProject diff --git a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/GradleModuleMetadata.groovy b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/GradleModuleMetadata.groovy index 38fd7effdd16f..273ec9ba0a380 100644 --- a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/GradleModuleMetadata.groovy +++ b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/GradleModuleMetadata.groovy @@ -155,6 +155,10 @@ class GradleModuleMetadata { return ref == null ? null : new ModuleReference(ref.group, ref.module, ref.version, ref.url) } + Map getAttributes() { + values.attributes + } + List getDependencies() { if (dependencies == null) { dependencies = (values.dependencies ?: []).collect { diff --git a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/gradle/VariantMetadataSpec.groovy b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/gradle/VariantMetadataSpec.groovy index d5bb981db462e..c0925384e9d00 100644 --- a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/gradle/VariantMetadataSpec.groovy +++ b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/gradle/VariantMetadataSpec.groovy @@ -64,4 +64,8 @@ class VariantMetadataSpec { void constraint(String group, String module, String version, String reason = null, Map attributes=[:]) { dependencyConstraints << new DependencyConstraintSpec(group, module, version, null, null, null, reason, attributes) } + + void artifact(String name) { + artifacts << new FileSpec(name) + } } diff --git a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/ivy/IvyJavaModule.groovy b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/ivy/IvyJavaModule.groovy index 2daa8e46da4c9..c2030e9e033cf 100644 --- a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/ivy/IvyJavaModule.groovy +++ b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/ivy/IvyJavaModule.groovy @@ -16,7 +16,8 @@ package org.gradle.test.fixtures.ivy - +import org.gradle.api.JavaVersion +import org.gradle.api.attributes.java.TargetJavaPlatform import org.gradle.test.fixtures.ModuleArtifact import org.gradle.test.fixtures.PublishedJavaModule import org.gradle.test.fixtures.file.TestFile @@ -29,6 +30,7 @@ class IvyJavaModule extends DelegatingIvyModule implements Publis IvyJavaModule(IvyFileModule backingModule) { super(backingModule) this.backingModule = backingModule + this.backingModule.attributes[TargetJavaPlatform.MINIMAL_TARGET_PLATFORM_ATTRIBUTE.name] = JavaVersion.current().majorVersion } @Override diff --git a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/maven/MavenJavaModule.groovy b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/maven/MavenJavaModule.groovy index 80c5652405dfe..be7151317a08c 100644 --- a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/maven/MavenJavaModule.groovy +++ b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/maven/MavenJavaModule.groovy @@ -16,6 +16,9 @@ package org.gradle.test.fixtures.maven +import org.gradle.api.JavaVersion +import org.gradle.api.attributes.java.Bundling +import org.gradle.api.attributes.java.TargetJavaPlatform import org.gradle.test.fixtures.PublishedJavaModule import org.gradle.util.GUtil @@ -26,6 +29,7 @@ class MavenJavaModule extends DelegatingMavenModule implements MavenJavaModule(MavenFileModule mavenModule) { super(mavenModule) this.mavenModule = mavenModule + this.mavenModule.attributes[TargetJavaPlatform.MINIMAL_TARGET_PLATFORM_ATTRIBUTE.name] = JavaVersion.current().majorVersion } @Override @@ -49,8 +53,17 @@ class MavenJavaModule extends DelegatingMavenModule implements // Verify Gradle metadata particulars assert mavenModule.parsedModuleMetadata.variants*.name as Set == ['apiElements', 'runtimeElements'] as Set - assert mavenModule.parsedModuleMetadata.variant('apiElements').files*.name == [artifact('jar')] - assert mavenModule.parsedModuleMetadata.variant('runtimeElements').files*.name == [artifact('jar')] + def apiElements = mavenModule.parsedModuleMetadata.variant('apiElements') + def runtimeElements = mavenModule.parsedModuleMetadata.variant('runtimeElements') + + assert apiElements.files*.name == [artifact('jar')] + assert runtimeElements.files*.name == [artifact('jar')] + + // Verify it contains some expected attributes + assert apiElements.attributes.containsKey(Bundling.BUNDLING_ATTRIBUTE.name) + assert apiElements.attributes.containsKey(TargetJavaPlatform.MINIMAL_TARGET_PLATFORM_ATTRIBUTE.name) + assert runtimeElements.attributes.containsKey(Bundling.BUNDLING_ATTRIBUTE.name) + assert runtimeElements.attributes.containsKey(TargetJavaPlatform.MINIMAL_TARGET_PLATFORM_ATTRIBUTE.name) // Verify POM particulars assert mavenModule.parsedPom.packaging == null diff --git a/subprojects/plugins/src/integTest/groovy/org/gradle/java/JavaApplicationOutgoingVariantsIntegrationTest.groovy b/subprojects/plugins/src/integTest/groovy/org/gradle/java/JavaApplicationOutgoingVariantsIntegrationTest.groovy index b34f3d3cb5a68..aada3a4458a1b 100644 --- a/subprojects/plugins/src/integTest/groovy/org/gradle/java/JavaApplicationOutgoingVariantsIntegrationTest.groovy +++ b/subprojects/plugins/src/integTest/groovy/org/gradle/java/JavaApplicationOutgoingVariantsIntegrationTest.groovy @@ -16,6 +16,7 @@ package org.gradle.java +import org.gradle.api.JavaVersion import org.gradle.integtests.fixtures.AbstractIntegrationSpec import spock.lang.Unroll @@ -78,8 +79,8 @@ project(':consumer') { outputContains("files: [java.jar, file-dep.jar, compile-1.0.jar, other-java.jar, implementation-1.0.jar, runtime-1.0.jar, runtime-only-1.0.jar]") outputContains("file-dep.jar {artifactType=jar}") outputContains("compile.jar (test:compile:1.0) {artifactType=jar}") - outputContains("other-java.jar (project :other-java) {artifactType=jar, org.gradle.dependency.bundling=external, org.gradle.usage=java-runtime-jars}") - outputContains("java.jar (project :java) {artifactType=jar, org.gradle.dependency.bundling=external, org.gradle.usage=java-runtime-jars}") + outputContains("other-java.jar (project :other-java) {artifactType=jar, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-jars}") + outputContains("java.jar (project :java) {artifactType=jar, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-jars}") when: buildFile << """ @@ -96,8 +97,8 @@ project(':consumer') { outputContains("files: [java.jar, file-dep.jar, compile-1.0.jar, other-java.jar, implementation-1.0.jar, runtime-1.0.jar, runtime-only-1.0.jar]") outputContains("file-dep.jar {artifactType=jar, org.gradle.usage=java-runtime-jars}") outputContains("compile.jar (test:compile:1.0) {artifactType=jar, org.gradle.usage=java-runtime-jars}") - outputContains("other-java.jar (project :other-java) {artifactType=jar, org.gradle.dependency.bundling=external, org.gradle.usage=java-runtime-jars}") - outputContains("java.jar (project :java) {artifactType=jar, org.gradle.dependency.bundling=external, org.gradle.usage=java-runtime-jars}") + outputContains("other-java.jar (project :other-java) {artifactType=jar, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-jars}") + outputContains("java.jar (project :java) {artifactType=jar, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-jars}") } @Unroll @@ -117,8 +118,8 @@ project(':consumer') { outputContains("files: [java.jar, file-dep.jar, compile-1.0.jar, main, runtime-1.0.jar]") outputContains("file-dep.jar {artifactType=jar}") outputContains("compile.jar (test:compile:1.0) {artifactType=jar}") - outputContains("main (project :other-java) {artifactType=java-classes-directory, org.gradle.dependency.bundling=external, org.gradle.usage=java-api-classes}") - outputContains("java.jar (project :java) {artifactType=jar, org.gradle.dependency.bundling=external, org.gradle.usage=java-api-jars}") + outputContains("main (project :other-java) {artifactType=java-classes-directory, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-api-classes}") + outputContains("java.jar (project :java) {artifactType=jar, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-api-jars}") when: buildFile << """ @@ -135,8 +136,8 @@ project(':consumer') { outputContains("files: [java.jar, file-dep.jar, compile-1.0.jar, main, runtime-1.0.jar]") outputContains("file-dep.jar {artifactType=jar, org.gradle.usage=java-runtime-jars}") outputContains("compile.jar (test:compile:1.0) {artifactType=jar, org.gradle.usage=java-runtime-jars}") - outputContains("main (project :other-java) {artifactType=java-classes-directory, org.gradle.dependency.bundling=external, org.gradle.usage=java-api-classes}") - outputContains("java.jar (project :java) {artifactType=jar, org.gradle.dependency.bundling=external, org.gradle.usage=java-api-jars}") + outputContains("main (project :other-java) {artifactType=java-classes-directory, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-api-classes}") + outputContains("java.jar (project :java) {artifactType=jar, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-api-jars}") where: usage | _ @@ -160,8 +161,8 @@ project(':consumer') { outputContains("files: [java.jar, file-dep.jar, compile-1.0.jar, other-java.jar, implementation-1.0.jar, runtime-1.0.jar, runtime-only-1.0.jar]") outputContains("file-dep.jar {artifactType=jar}") outputContains("compile.jar (test:compile:1.0) {artifactType=jar}") - outputContains("other-java.jar (project :other-java) {artifactType=jar, org.gradle.dependency.bundling=external, org.gradle.usage=java-runtime-jars}") - outputContains("java.jar (project :java) {artifactType=jar, org.gradle.dependency.bundling=external, org.gradle.usage=java-runtime-jars}") + outputContains("other-java.jar (project :other-java) {artifactType=jar, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-jars}") + outputContains("java.jar (project :java) {artifactType=jar, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-jars}") when: buildFile << """ @@ -178,8 +179,8 @@ project(':consumer') { outputContains("files: [java.jar, file-dep.jar, compile-1.0.jar, other-java.jar, implementation-1.0.jar, runtime-1.0.jar, runtime-only-1.0.jar]") outputContains("file-dep.jar {artifactType=jar, org.gradle.usage=java-runtime-jars}") outputContains("compile.jar (test:compile:1.0) {artifactType=jar, org.gradle.usage=java-runtime-jars}") - outputContains("other-java.jar (project :other-java) {artifactType=jar, org.gradle.dependency.bundling=external, org.gradle.usage=java-runtime-jars}") - outputContains("java.jar (project :java) {artifactType=jar, org.gradle.dependency.bundling=external, org.gradle.usage=java-runtime-jars}") + outputContains("other-java.jar (project :other-java) {artifactType=jar, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-jars}") + outputContains("java.jar (project :java) {artifactType=jar, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-jars}") where: usage | _ @@ -201,8 +202,8 @@ project(':consumer') { result.assertTasksExecuted(":other-java:compileJava", ":other-java:processResources", ":other-java:classes", ":other-java:jar", ":java:compileJava", ":java:processResources", ":java:classes", ":java:jar", ":consumer:resolve") outputContains("files: [java.jar, file-dep.jar, compile-1.0.jar, other-java.jar, implementation-1.0.jar, runtime-1.0.jar, runtime-only-1.0.jar]") outputContains("file-dep.jar {artifactType=jar}") - outputContains("other-java.jar (project :other-java) {artifactType=jar, org.gradle.dependency.bundling=external, org.gradle.usage=java-runtime-jars}") - outputContains("java.jar (project :java) {artifactType=jar, org.gradle.dependency.bundling=external, org.gradle.usage=java-runtime-jars}") + outputContains("other-java.jar (project :other-java) {artifactType=jar, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-jars}") + outputContains("java.jar (project :java) {artifactType=jar, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-jars}") } def "provides runtime classes variant"() { @@ -221,8 +222,8 @@ project(':consumer') { outputContains("files: [main, file-dep.jar, compile-1.0.jar, main, implementation-1.0.jar, runtime-1.0.jar, runtime-only-1.0.jar]") outputContains("file-dep.jar {artifactType=jar}") outputContains("compile.jar (test:compile:1.0) {artifactType=jar}") - outputContains("main (project :other-java) {artifactType=java-classes-directory, org.gradle.dependency.bundling=external, org.gradle.usage=java-runtime-classes}") - outputContains("main (project :java) {artifactType=java-classes-directory, org.gradle.dependency.bundling=external, org.gradle.usage=java-runtime-classes}") + outputContains("main (project :other-java) {artifactType=java-classes-directory, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-classes}") + outputContains("main (project :java) {artifactType=java-classes-directory, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-classes}") when: buildFile << """ @@ -239,8 +240,8 @@ project(':consumer') { outputContains("files: [main, file-dep.jar, compile-1.0.jar, main, implementation-1.0.jar, runtime-1.0.jar, runtime-only-1.0.jar]") outputContains("file-dep.jar {artifactType=jar, org.gradle.usage=java-runtime-jars}") outputContains("compile.jar (test:compile:1.0) {artifactType=jar, org.gradle.usage=java-runtime-jars}") - outputContains("main (project :other-java) {artifactType=java-classes-directory, org.gradle.dependency.bundling=external, org.gradle.usage=java-runtime-classes}") - outputContains("main (project :java) {artifactType=java-classes-directory, org.gradle.dependency.bundling=external, org.gradle.usage=java-runtime-classes}") + outputContains("main (project :other-java) {artifactType=java-classes-directory, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-classes}") + outputContains("main (project :java) {artifactType=java-classes-directory, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-classes}") } def "provides runtime resources variant"() { @@ -259,8 +260,8 @@ project(':consumer') { outputContains("files: [main, file-dep.jar, compile-1.0.jar, main, implementation-1.0.jar, runtime-1.0.jar, runtime-only-1.0.jar]") outputContains("file-dep.jar {artifactType=jar}") outputContains("compile.jar (test:compile:1.0) {artifactType=jar}") - outputContains("main (project :other-java) {artifactType=java-resources-directory, org.gradle.dependency.bundling=external, org.gradle.usage=java-runtime-resources}") - outputContains("main (project :java) {artifactType=java-resources-directory, org.gradle.dependency.bundling=external, org.gradle.usage=java-runtime-resources}") + outputContains("main (project :other-java) {artifactType=java-resources-directory, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-resources}") + outputContains("main (project :java) {artifactType=java-resources-directory, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-resources}") when: buildFile << """ @@ -277,7 +278,11 @@ project(':consumer') { outputContains("files: [main, file-dep.jar, compile-1.0.jar, main, implementation-1.0.jar, runtime-1.0.jar, runtime-only-1.0.jar]") outputContains("file-dep.jar {artifactType=jar, org.gradle.usage=java-runtime-jars}") outputContains("compile.jar (test:compile:1.0) {artifactType=jar, org.gradle.usage=java-runtime-jars}") - outputContains("main (project :other-java) {artifactType=java-resources-directory, org.gradle.dependency.bundling=external, org.gradle.usage=java-runtime-resources}") - outputContains("main (project :java) {artifactType=java-resources-directory, org.gradle.dependency.bundling=external, org.gradle.usage=java-runtime-resources}") + outputContains("main (project :other-java) {artifactType=java-resources-directory, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-resources}") + outputContains("main (project :java) {artifactType=java-resources-directory, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-resources}") + } + + static String defaultTargetPlatform() { + "org.gradle.java.min.platform=${JavaVersion.current().majorVersion}" } } diff --git a/subprojects/plugins/src/integTest/groovy/org/gradle/java/JavaLibraryCrossProjectTargetPlatformIntegrationTest.groovy b/subprojects/plugins/src/integTest/groovy/org/gradle/java/JavaLibraryCrossProjectTargetPlatformIntegrationTest.groovy new file mode 100644 index 0000000000000..2fb13ce765a00 --- /dev/null +++ b/subprojects/plugins/src/integTest/groovy/org/gradle/java/JavaLibraryCrossProjectTargetPlatformIntegrationTest.groovy @@ -0,0 +1,124 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.java + +import org.gradle.integtests.fixtures.AbstractIntegrationSpec +import org.gradle.integtests.fixtures.resolve.ResolveTestFixture +import spock.lang.Unroll + +class JavaLibraryCrossProjectTargetPlatformIntegrationTest extends AbstractIntegrationSpec { + ResolveTestFixture resolve + + def setup() { + settingsFile << """ + rootProject.name = 'test' + include 'producer' + """ + buildFile << """ + allprojects { + apply plugin: 'java-library' + } + + dependencies { + api project(':producer') + } + """ + resolve = new ResolveTestFixture(buildFile, 'compileClasspath') + resolve.prepare() + } + + def "can fail resolution if producer doesn't have appropriate target version"() { + file('producer/build.gradle') << """ + java { + sourceCompatibility = JavaVersion.VERSION_1_7 + targetCompatibility = JavaVersion.VERSION_1_7 + } + """ + buildFile << """ + configurations.compileClasspath.attributes.attribute(TargetJavaPlatform.MINIMAL_TARGET_PLATFORM_ATTRIBUTE, 6) + """ + + when: + fails ':checkDeps' + + then: + failure.assertHasCause('''Unable to find a matching variant of project :producer: + - Variant 'apiElements' capability test:producer:unspecified: + - Found org.gradle.dependency.bundling 'external' but wasn't required. + - Required org.gradle.java.min.platform '6' and found incompatible value '7'. + - Required org.gradle.usage 'java-api' and found compatible value 'java-api-jars'. + - Variant 'runtimeElements' capability test:producer:unspecified: + - Found org.gradle.dependency.bundling 'external' but wasn't required. + - Required org.gradle.java.min.platform '6' and found incompatible value '7'. + - Required org.gradle.usage 'java-api' and found compatible value 'java-runtime-jars'.''') + } + + @Unroll + def "can select the most appropriate producer variant (#expected) based on target compatibility (#requested)"() { + file('producer/build.gradle') << """ + // avoid test noise so that typically version 8 is not selected when running on JDK 8 + configurations.apiElements.attributes.attribute(TargetJavaPlatform.MINIMAL_TARGET_PLATFORM_ATTRIBUTE, 1000) + + [6, 7, 9].each { v -> + configurations { + "apiElementsJdk\${v}" { + canBeConsumed = true + canBeResolved = false + attributes { + attribute(Usage.USAGE_ATTRIBUTE, objects.named(Usage, 'java-api-jars')) + attribute(Bundling.BUNDLING_ATTRIBUTE, objects.named(Bundling, 'external')) + attribute(TargetJavaPlatform.MINIMAL_TARGET_PLATFORM_ATTRIBUTE, v) + } + } + } + artifacts { + "apiElementsJdk\${v}" file("producer-jdk\${v}.jar") + } + } + """ + buildFile << """ + configurations.compileClasspath.attributes.attribute(TargetJavaPlatform.MINIMAL_TARGET_PLATFORM_ATTRIBUTE, $requested) + """ + + when: + run ':checkDeps' + + then: + resolve.expectGraph { + root(":", ":test:") { + project(':producer', 'test:producer:') { + variant(expected, [ + 'org.gradle.dependency.bundling': 'external', + 'org.gradle.java.min.platform': selected, + 'org.gradle.usage':'java-api-jars' + ]) + artifact(classifier: "jdk${selected}") + } + } + } + + where: + requested | selected + 6 | 6 + 7 | 7 + 8 | 7 + 9 | 9 + 10 | 9 + + expected = "apiElementsJdk$selected" + } +} diff --git a/subprojects/plugins/src/integTest/groovy/org/gradle/java/JavaLibraryOutgoingVariantsIntegrationTest.groovy b/subprojects/plugins/src/integTest/groovy/org/gradle/java/JavaLibraryOutgoingVariantsIntegrationTest.groovy index f890ac6ffb610..d35223c6b6790 100644 --- a/subprojects/plugins/src/integTest/groovy/org/gradle/java/JavaLibraryOutgoingVariantsIntegrationTest.groovy +++ b/subprojects/plugins/src/integTest/groovy/org/gradle/java/JavaLibraryOutgoingVariantsIntegrationTest.groovy @@ -16,6 +16,7 @@ package org.gradle.java +import org.gradle.api.JavaVersion import org.gradle.integtests.fixtures.AbstractIntegrationSpec import spock.lang.Unroll @@ -80,8 +81,8 @@ project(':consumer') { outputContains("files: [java.jar, file-dep.jar, api-1.0.jar, compile-1.0.jar, other-java.jar, implementation-1.0.jar, runtime-1.0.jar, runtime-only-1.0.jar]") outputContains("file-dep.jar {artifactType=jar}") outputContains("compile.jar (test:compile:1.0) {artifactType=jar}") - outputContains("other-java.jar (project :other-java) {artifactType=jar, org.gradle.dependency.bundling=external, org.gradle.usage=java-runtime-jars}") - outputContains("java.jar (project :java) {artifactType=jar, org.gradle.dependency.bundling=external, org.gradle.usage=java-runtime-jars}") + outputContains("other-java.jar (project :other-java) {artifactType=jar, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-jars}") + outputContains("java.jar (project :java) {artifactType=jar, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-jars}") when: buildFile << """ @@ -98,8 +99,8 @@ project(':consumer') { outputContains("files: [java.jar, file-dep.jar, api-1.0.jar, compile-1.0.jar, other-java.jar, implementation-1.0.jar, runtime-1.0.jar, runtime-only-1.0.jar]") outputContains("file-dep.jar {artifactType=jar, org.gradle.usage=java-runtime-jars}") outputContains("compile.jar (test:compile:1.0) {artifactType=jar, org.gradle.usage=java-runtime-jars}") - outputContains("other-java.jar (project :other-java) {artifactType=jar, org.gradle.dependency.bundling=external, org.gradle.usage=java-runtime-jars}") - outputContains("java.jar (project :java) {artifactType=jar, org.gradle.dependency.bundling=external, org.gradle.usage=java-runtime-jars}") + outputContains("other-java.jar (project :other-java) {artifactType=jar, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-jars}") + outputContains("java.jar (project :java) {artifactType=jar, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-jars}") } @Unroll @@ -118,8 +119,8 @@ project(':consumer') { outputContains("files: [main, file-dep.jar, api-1.0.jar, compile-1.0.jar, main, runtime-1.0.jar]") outputContains("file-dep.jar {artifactType=jar}") outputContains("compile.jar (test:compile:1.0) {artifactType=jar}") - outputContains("main (project :other-java) {artifactType=java-classes-directory, org.gradle.dependency.bundling=external, org.gradle.usage=java-api-classes}") - outputContains("main (project :java) {artifactType=java-classes-directory, org.gradle.dependency.bundling=external, org.gradle.usage=java-api-classes}") + outputContains("main (project :other-java) {artifactType=java-classes-directory, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-api-classes}") + outputContains("main (project :java) {artifactType=java-classes-directory, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-api-classes}") when: buildFile << """ @@ -136,8 +137,8 @@ project(':consumer') { outputContains("files: [main, file-dep.jar, api-1.0.jar, compile-1.0.jar, main, runtime-1.0.jar]") outputContains("file-dep.jar {artifactType=jar, org.gradle.usage=java-runtime-jars}") outputContains("compile.jar (test:compile:1.0) {artifactType=jar, org.gradle.usage=java-runtime-jars}") - outputContains("main (project :other-java) {artifactType=java-classes-directory, org.gradle.dependency.bundling=external, org.gradle.usage=java-api-classes}") - outputContains("main (project :java) {artifactType=java-classes-directory, org.gradle.dependency.bundling=external, org.gradle.usage=java-api-classes}") + outputContains("main (project :other-java) {artifactType=java-classes-directory, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-api-classes}") + outputContains("main (project :java) {artifactType=java-classes-directory, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-api-classes}") where: usage | _ @@ -161,8 +162,8 @@ project(':consumer') { outputContains("files: [java.jar, file-dep.jar, api-1.0.jar, compile-1.0.jar, other-java.jar, implementation-1.0.jar, runtime-1.0.jar, runtime-only-1.0.jar]") outputContains("file-dep.jar {artifactType=jar}") outputContains("compile.jar (test:compile:1.0) {artifactType=jar}") - outputContains("java.jar (project :java) {artifactType=jar, org.gradle.dependency.bundling=external, org.gradle.usage=java-runtime-jars}") - outputContains("other-java.jar (project :other-java) {artifactType=jar, org.gradle.dependency.bundling=external, org.gradle.usage=java-runtime-jars}") + outputContains("java.jar (project :java) {artifactType=jar, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-jars}") + outputContains("other-java.jar (project :other-java) {artifactType=jar, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-jars}") when: buildFile << """ @@ -179,8 +180,8 @@ project(':consumer') { outputContains("files: [java.jar, file-dep.jar, api-1.0.jar, compile-1.0.jar, other-java.jar, implementation-1.0.jar, runtime-1.0.jar, runtime-only-1.0.jar]") outputContains("file-dep.jar {artifactType=jar, org.gradle.usage=java-runtime-jars}") outputContains("compile.jar (test:compile:1.0) {artifactType=jar, org.gradle.usage=java-runtime-jars}") - outputContains("java.jar (project :java) {artifactType=jar, org.gradle.dependency.bundling=external, org.gradle.usage=java-runtime-jars}") - outputContains("other-java.jar (project :other-java) {artifactType=jar, org.gradle.dependency.bundling=external, org.gradle.usage=java-runtime-jars}") + outputContains("java.jar (project :java) {artifactType=jar, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-jars}") + outputContains("other-java.jar (project :other-java) {artifactType=jar, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-jars}") where: usage | _ @@ -202,8 +203,8 @@ project(':consumer') { result.assertTasksExecuted(":other-java:compileJava", ":other-java:processResources", ":other-java:classes", ":other-java:jar", ":java:compileJava", ":java:processResources", ":java:classes", ":java:jar", ":consumer:resolve") outputContains("files: [java.jar, file-dep.jar, api-1.0.jar, compile-1.0.jar, other-java.jar, implementation-1.0.jar, runtime-1.0.jar, runtime-only-1.0.jar]") outputContains("file-dep.jar {artifactType=jar}") - outputContains("java.jar (project :java) {artifactType=jar, org.gradle.dependency.bundling=external, org.gradle.usage=java-runtime-jars}") - outputContains("other-java.jar (project :other-java) {artifactType=jar, org.gradle.dependency.bundling=external, org.gradle.usage=java-runtime-jars}") + outputContains("java.jar (project :java) {artifactType=jar, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-jars}") + outputContains("other-java.jar (project :other-java) {artifactType=jar, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-jars}") } def "provides runtime classes variant"() { @@ -222,8 +223,8 @@ project(':consumer') { outputContains("files: [main, file-dep.jar, api-1.0.jar, compile-1.0.jar, main, implementation-1.0.jar, runtime-1.0.jar, runtime-only-1.0.jar]") outputContains("file-dep.jar {artifactType=jar}") outputContains("compile.jar (test:compile:1.0) {artifactType=jar}") - outputContains("main (project :other-java) {artifactType=java-classes-directory, org.gradle.dependency.bundling=external, org.gradle.usage=java-runtime-classes}") - outputContains("main (project :java) {artifactType=java-classes-directory, org.gradle.dependency.bundling=external, org.gradle.usage=java-runtime-classes}") + outputContains("main (project :other-java) {artifactType=java-classes-directory, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-classes}") + outputContains("main (project :java) {artifactType=java-classes-directory, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-classes}") when: buildFile << """ @@ -240,8 +241,8 @@ project(':consumer') { outputContains("files: [main, file-dep.jar, api-1.0.jar, compile-1.0.jar, main, implementation-1.0.jar, runtime-1.0.jar, runtime-only-1.0.jar]") outputContains("file-dep.jar {artifactType=jar, org.gradle.usage=java-runtime-jars}") outputContains("compile.jar (test:compile:1.0) {artifactType=jar, org.gradle.usage=java-runtime-jars}") - outputContains("main (project :other-java) {artifactType=java-classes-directory, org.gradle.dependency.bundling=external, org.gradle.usage=java-runtime-classes}") - outputContains("main (project :java) {artifactType=java-classes-directory, org.gradle.dependency.bundling=external, org.gradle.usage=java-runtime-classes}") + outputContains("main (project :other-java) {artifactType=java-classes-directory, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-classes}") + outputContains("main (project :java) {artifactType=java-classes-directory, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-classes}") } def "provides runtime resources variant"() { @@ -260,8 +261,8 @@ project(':consumer') { outputContains("files: [main, file-dep.jar, api-1.0.jar, compile-1.0.jar, main, implementation-1.0.jar, runtime-1.0.jar, runtime-only-1.0.jar]") outputContains("file-dep.jar {artifactType=jar}") outputContains("compile.jar (test:compile:1.0) {artifactType=jar}") - outputContains("main (project :other-java) {artifactType=java-resources-directory, org.gradle.dependency.bundling=external, org.gradle.usage=java-runtime-resources}") - outputContains("main (project :java) {artifactType=java-resources-directory, org.gradle.dependency.bundling=external, org.gradle.usage=java-runtime-resources}") + outputContains("main (project :other-java) {artifactType=java-resources-directory, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-resources}") + outputContains("main (project :java) {artifactType=java-resources-directory, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-resources}") when: buildFile << """ @@ -278,7 +279,11 @@ project(':consumer') { outputContains("files: [main, file-dep.jar, api-1.0.jar, compile-1.0.jar, main, implementation-1.0.jar, runtime-1.0.jar, runtime-only-1.0.jar]") outputContains("file-dep.jar {artifactType=jar, org.gradle.usage=java-runtime-jars}") outputContains("compile.jar (test:compile:1.0) {artifactType=jar, org.gradle.usage=java-runtime-jars}") - outputContains("main (project :other-java) {artifactType=java-resources-directory, org.gradle.dependency.bundling=external, org.gradle.usage=java-runtime-resources}") - outputContains("main (project :java) {artifactType=java-resources-directory, org.gradle.dependency.bundling=external, org.gradle.usage=java-runtime-resources}") + outputContains("main (project :other-java) {artifactType=java-resources-directory, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-resources}") + outputContains("main (project :java) {artifactType=java-resources-directory, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-resources}") + } + + static String defaultTargetPlatform() { + "org.gradle.java.min.platform=${JavaVersion.current().majorVersion}" } } diff --git a/subprojects/plugins/src/integTest/groovy/org/gradle/java/JavaLibraryPublishedTargetPlatformIntegrationTest.groovy b/subprojects/plugins/src/integTest/groovy/org/gradle/java/JavaLibraryPublishedTargetPlatformIntegrationTest.groovy new file mode 100644 index 0000000000000..401f13aa21555 --- /dev/null +++ b/subprojects/plugins/src/integTest/groovy/org/gradle/java/JavaLibraryPublishedTargetPlatformIntegrationTest.groovy @@ -0,0 +1,147 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.java + +import org.gradle.integtests.fixtures.AbstractHttpDependencyResolutionTest +import org.gradle.integtests.fixtures.resolve.ResolveTestFixture +import org.gradle.test.fixtures.server.http.MavenHttpModule +import spock.lang.Unroll + +class JavaLibraryPublishedTargetPlatformIntegrationTest extends AbstractHttpDependencyResolutionTest { + ResolveTestFixture resolve + MavenHttpModule module + + def setup() { + settingsFile << """ + rootProject.name = 'test' + """ + buildFile << """ + apply plugin: 'java-library' + + repositories { + maven { url '${mavenHttpRepo.uri}' } + } + + dependencies { + api 'org:producer:1.0' + } + """ + + resolve = new ResolveTestFixture(buildFile, 'compileClasspath') + resolve.prepare() + + module = mavenHttpRepo.module('org', 'producer', '1.0') + .withModuleMetadata() + .withGradleMetadataRedirection() + .adhocVariants() + .variant("apiElementsJdk6", [ + 'org.gradle.dependency.bundling': 'external', + 'org.gradle.java.min.platform': '6', + 'org.gradle.usage': 'java-api-jars'], { artifact('producer-1.0-jdk6.jar') }) + .variant("apiElementsJdk7", [ + 'org.gradle.dependency.bundling': 'external', + 'org.gradle.java.min.platform': '7', + 'org.gradle.usage': 'java-api-jars'], { artifact('producer-1.0-jdk7.jar') }) + .variant("apiElementsJdk9", [ + 'org.gradle.dependency.bundling': 'external', + 'org.gradle.java.min.platform': '9', + 'org.gradle.usage': 'java-api-jars'], { artifact('producer-1.0-jdk9.jar') }) + .variant("runtimeElementsJdk6", [ + 'org.gradle.dependency.bundling': 'external', + 'org.gradle.java.min.platform': '6', + 'org.gradle.usage': 'java-runtime-jars'], { artifact('producer-1.0-jdk6.jar') }) + .variant("runtimeElementsJdk7", [ + 'org.gradle.dependency.bundling': 'external', + 'org.gradle.java.min.platform': '7', + 'org.gradle.usage': 'java-runtime-jars'], { artifact('producer-1.0-jdk7.jar') }) + .variant("runtimeElementsJdk9", [ + 'org.gradle.dependency.bundling': 'external', + 'org.gradle.java.min.platform': '9', + 'org.gradle.usage': 'java-runtime-jars'], { artifact('producer-1.0-jdk9.jar') }) + .publish() + + } + + def "can fail resolution if producer doesn't have appropriate target version"() { + buildFile << """ + configurations.compileClasspath.attributes.attribute(TargetJavaPlatform.MINIMAL_TARGET_PLATFORM_ATTRIBUTE, 5) + """ + + when: + module.pom.expectGet() + module.moduleMetadata.expectGet() + + fails ':checkDeps' + + then: + failure.assertHasCause('''Unable to find a matching variant of org:producer:1.0: + - Variant 'apiElementsJdk6' capability org:producer:1.0: + - Found org.gradle.dependency.bundling 'external' but wasn't required. + - Required org.gradle.java.min.platform '5' and found incompatible value '6'. + - Found org.gradle.status 'release' but wasn't required. + - Required org.gradle.usage 'java-api' and found compatible value 'java-api-jars'. + - Variant 'apiElementsJdk7' capability org:producer:1.0: + - Found org.gradle.dependency.bundling 'external' but wasn't required. + - Required org.gradle.java.min.platform '5' and found incompatible value '7'. + - Found org.gradle.status 'release' but wasn't required. + - Required org.gradle.usage 'java-api' and found compatible value 'java-api-jars'. + - Variant 'apiElementsJdk9' capability org:producer:1.0: + - Found org.gradle.dependency.bundling 'external' but wasn't required. + - Required org.gradle.java.min.platform '5' and found incompatible value '9'. + - Found org.gradle.status 'release' but wasn't required. + - Required org.gradle.usage 'java-api' and found compatible value 'java-api-jars'.''') + } + + @Unroll + def "can select the most appropriate producer variant (#expected) based on target compatibility (#requested)"() { + buildFile << """ + configurations.compileClasspath.attributes.attribute(TargetJavaPlatform.MINIMAL_TARGET_PLATFORM_ATTRIBUTE, $requested) + """ + + when: + module.pom.expectGet() + module.moduleMetadata.expectGet() + module.getArtifact(classifier: "jdk${selected}").expectGet() + + run ':checkDeps' + + then: + resolve.expectGraph { + root(":", ":test:") { + module('org:producer:1.0') { + variant(expected, [ + 'org.gradle.dependency.bundling': 'external', + 'org.gradle.java.min.platform': selected, + 'org.gradle.usage': 'java-api-jars', + 'org.gradle.status': 'release' + ]) + artifact(classifier: "jdk${selected}") + } + } + } + + where: + requested | selected + 6 | 6 + 7 | 7 + 8 | 7 + 9 | 9 + 10 | 9 + + expected = "apiElementsJdk$selected" + } +} diff --git a/subprojects/plugins/src/integTest/groovy/org/gradle/java/JavaProjectOutgoingVariantsIntegrationTest.groovy b/subprojects/plugins/src/integTest/groovy/org/gradle/java/JavaProjectOutgoingVariantsIntegrationTest.groovy index cb976980b6a74..012fee166fc93 100644 --- a/subprojects/plugins/src/integTest/groovy/org/gradle/java/JavaProjectOutgoingVariantsIntegrationTest.groovy +++ b/subprojects/plugins/src/integTest/groovy/org/gradle/java/JavaProjectOutgoingVariantsIntegrationTest.groovy @@ -16,6 +16,7 @@ package org.gradle.java +import org.gradle.api.JavaVersion import org.gradle.integtests.fixtures.AbstractIntegrationSpec import spock.lang.Unroll @@ -78,8 +79,8 @@ project(':consumer') { outputContains("files: [java.jar, file-dep.jar, compile-1.0.jar, other-java.jar, implementation-1.0.jar, runtime-1.0.jar, runtime-only-1.0.jar]") outputContains("file-dep.jar {artifactType=jar}") outputContains("compile.jar (test:compile:1.0) {artifactType=jar}") - outputContains("other-java.jar (project :other-java) {artifactType=jar, org.gradle.dependency.bundling=external, org.gradle.usage=java-runtime-jars}") - outputContains("java.jar (project :java) {artifactType=jar, org.gradle.dependency.bundling=external, org.gradle.usage=java-runtime-jars}") + outputContains("other-java.jar (project :other-java) {artifactType=jar, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-jars}") + outputContains("java.jar (project :java) {artifactType=jar, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-jars}") when: buildFile << """ @@ -96,8 +97,8 @@ project(':consumer') { outputContains("files: [java.jar, file-dep.jar, compile-1.0.jar, other-java.jar, implementation-1.0.jar, runtime-1.0.jar, runtime-only-1.0.jar]") outputContains("file-dep.jar {artifactType=jar, org.gradle.usage=java-runtime-jars}") outputContains("compile.jar (test:compile:1.0) {artifactType=jar, org.gradle.usage=java-runtime-jars}") - outputContains("other-java.jar (project :other-java) {artifactType=jar, org.gradle.dependency.bundling=external, org.gradle.usage=java-runtime-jars}") - outputContains("java.jar (project :java) {artifactType=jar, org.gradle.dependency.bundling=external, org.gradle.usage=java-runtime-jars}") + outputContains("other-java.jar (project :other-java) {artifactType=jar, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-jars}") + outputContains("java.jar (project :java) {artifactType=jar, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-jars}") } @Unroll @@ -116,8 +117,8 @@ project(':consumer') { outputContains("files: [java.jar, file-dep.jar, compile-1.0.jar, other-java.jar, runtime-1.0.jar]") outputContains("file-dep.jar {artifactType=jar}") outputContains("compile.jar (test:compile:1.0) {artifactType=jar}") - outputContains("other-java.jar (project :other-java) {artifactType=jar, org.gradle.dependency.bundling=external, org.gradle.usage=java-api-jars}") - outputContains("java.jar (project :java) {artifactType=jar, org.gradle.dependency.bundling=external, org.gradle.usage=java-api-jars}") + outputContains("other-java.jar (project :other-java) {artifactType=jar, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-api-jars}") + outputContains("java.jar (project :java) {artifactType=jar, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-api-jars}") when: buildFile << """ @@ -134,8 +135,8 @@ project(':consumer') { outputContains("files: [java.jar, file-dep.jar, compile-1.0.jar, other-java.jar, runtime-1.0.jar]") outputContains("file-dep.jar {artifactType=jar, org.gradle.usage=java-runtime-jars}") outputContains("compile.jar (test:compile:1.0) {artifactType=jar, org.gradle.usage=java-runtime-jars}") - outputContains("other-java.jar (project :other-java) {artifactType=jar, org.gradle.dependency.bundling=external, org.gradle.usage=java-api-jars}") - outputContains("java.jar (project :java) {artifactType=jar, org.gradle.dependency.bundling=external, org.gradle.usage=java-api-jars}") + outputContains("other-java.jar (project :other-java) {artifactType=jar, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-api-jars}") + outputContains("java.jar (project :java) {artifactType=jar, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-api-jars}") where: usage | _ @@ -160,8 +161,8 @@ project(':consumer') { outputContains("files: [java.jar, file-dep.jar, compile-1.0.jar, other-java.jar, implementation-1.0.jar, runtime-1.0.jar, runtime-only-1.0.jar]") outputContains("file-dep.jar {artifactType=jar}") outputContains("compile.jar (test:compile:1.0) {artifactType=jar}") - outputContains("other-java.jar (project :other-java) {artifactType=jar, org.gradle.dependency.bundling=external, org.gradle.usage=java-runtime-jars}") - outputContains("java.jar (project :java) {artifactType=jar, org.gradle.dependency.bundling=external, org.gradle.usage=java-runtime-jars}") + outputContains("other-java.jar (project :other-java) {artifactType=jar, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-jars}") + outputContains("java.jar (project :java) {artifactType=jar, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-jars}") when: buildFile << """ @@ -178,8 +179,8 @@ project(':consumer') { outputContains("files: [java.jar, file-dep.jar, compile-1.0.jar, other-java.jar, implementation-1.0.jar, runtime-1.0.jar, runtime-only-1.0.jar]") outputContains("file-dep.jar {artifactType=jar, org.gradle.usage=java-runtime-jars}") outputContains("compile.jar (test:compile:1.0) {artifactType=jar, org.gradle.usage=java-runtime-jars}") - outputContains("other-java.jar (project :other-java) {artifactType=jar, org.gradle.dependency.bundling=external, org.gradle.usage=java-runtime-jars}") - outputContains("java.jar (project :java) {artifactType=jar, org.gradle.dependency.bundling=external, org.gradle.usage=java-runtime-jars}") + outputContains("other-java.jar (project :other-java) {artifactType=jar, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-jars}") + outputContains("java.jar (project :java) {artifactType=jar, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-jars}") where: usage | _ @@ -201,8 +202,8 @@ project(':consumer') { result.assertTasksExecuted(":other-java:compileJava", ":other-java:processResources", ":other-java:classes", ":other-java:jar", ":java:compileJava", ":java:processResources", ":java:classes", ":java:jar", ":consumer:resolve") outputContains("files: [java.jar, file-dep.jar, compile-1.0.jar, other-java.jar, implementation-1.0.jar, runtime-1.0.jar, runtime-only-1.0.jar]") outputContains("file-dep.jar {artifactType=jar}") - outputContains("other-java.jar (project :other-java) {artifactType=jar, org.gradle.dependency.bundling=external, org.gradle.usage=java-runtime-jars}") - outputContains("java.jar (project :java) {artifactType=jar, org.gradle.dependency.bundling=external, org.gradle.usage=java-runtime-jars}") + outputContains("other-java.jar (project :other-java) {artifactType=jar, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-jars}") + outputContains("java.jar (project :java) {artifactType=jar, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-jars}") } def "provides runtime classes variant"() { @@ -220,8 +221,8 @@ project(':consumer') { outputContains("files: [main, file-dep.jar, compile-1.0.jar, main, implementation-1.0.jar, runtime-1.0.jar, runtime-only-1.0.jar]") outputContains("file-dep.jar {artifactType=jar}") outputContains("compile.jar (test:compile:1.0) {artifactType=jar}") - outputContains("main (project :other-java) {artifactType=java-classes-directory, org.gradle.dependency.bundling=external, org.gradle.usage=java-runtime-classes}") - outputContains("main (project :java) {artifactType=java-classes-directory, org.gradle.dependency.bundling=external, org.gradle.usage=java-runtime-classes}") + outputContains("main (project :other-java) {artifactType=java-classes-directory, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-classes}") + outputContains("main (project :java) {artifactType=java-classes-directory, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-classes}") when: buildFile << """ @@ -238,8 +239,8 @@ project(':consumer') { outputContains("files: [main, file-dep.jar, compile-1.0.jar, main, implementation-1.0.jar, runtime-1.0.jar, runtime-only-1.0.jar]") outputContains("file-dep.jar {artifactType=jar, org.gradle.usage=java-runtime-jars}") outputContains("compile.jar (test:compile:1.0) {artifactType=jar, org.gradle.usage=java-runtime-jars}") - outputContains("main (project :other-java) {artifactType=java-classes-directory, org.gradle.dependency.bundling=external, org.gradle.usage=java-runtime-classes}") - outputContains("main (project :java) {artifactType=java-classes-directory, org.gradle.dependency.bundling=external, org.gradle.usage=java-runtime-classes}") + outputContains("main (project :other-java) {artifactType=java-classes-directory, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-classes}") + outputContains("main (project :java) {artifactType=java-classes-directory, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-classes}") } def "provides runtime resources variant"() { @@ -258,8 +259,8 @@ project(':consumer') { outputContains("files: [main, file-dep.jar, compile-1.0.jar, main, implementation-1.0.jar, runtime-1.0.jar, runtime-only-1.0.jar]") outputContains("file-dep.jar {artifactType=jar}") outputContains("compile.jar (test:compile:1.0) {artifactType=jar}") - outputContains("main (project :other-java) {artifactType=java-resources-directory, org.gradle.dependency.bundling=external, org.gradle.usage=java-runtime-resources}") - outputContains("main (project :java) {artifactType=java-resources-directory, org.gradle.dependency.bundling=external, org.gradle.usage=java-runtime-resources}") + outputContains("main (project :other-java) {artifactType=java-resources-directory, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-resources}") + outputContains("main (project :java) {artifactType=java-resources-directory, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-resources}") when: buildFile << """ @@ -276,7 +277,11 @@ project(':consumer') { outputContains("files: [main, file-dep.jar, compile-1.0.jar, main, implementation-1.0.jar, runtime-1.0.jar, runtime-only-1.0.jar]") outputContains("file-dep.jar {artifactType=jar, org.gradle.usage=java-runtime-jars}") outputContains("compile.jar (test:compile:1.0) {artifactType=jar, org.gradle.usage=java-runtime-jars}") - outputContains("main (project :other-java) {artifactType=java-resources-directory, org.gradle.dependency.bundling=external, org.gradle.usage=java-runtime-resources}") - outputContains("main (project :java) {artifactType=java-resources-directory, org.gradle.dependency.bundling=external, org.gradle.usage=java-runtime-resources}") + outputContains("main (project :other-java) {artifactType=java-resources-directory, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-resources}") + outputContains("main (project :java) {artifactType=java-resources-directory, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-resources}") + } + + static String defaultTargetPlatform() { + "org.gradle.java.min.platform=${JavaVersion.current().majorVersion}" } } diff --git a/subprojects/plugins/src/main/java/org/gradle/api/internal/java/usagecontext/ConfigurationVariantMapping.java b/subprojects/plugins/src/main/java/org/gradle/api/internal/java/usagecontext/ConfigurationVariantMapping.java index a59c63d1abb30..b5e7e6d3cf428 100644 --- a/subprojects/plugins/src/main/java/org/gradle/api/internal/java/usagecontext/ConfigurationVariantMapping.java +++ b/subprojects/plugins/src/main/java/org/gradle/api/internal/java/usagecontext/ConfigurationVariantMapping.java @@ -23,22 +23,22 @@ import org.gradle.api.InvalidUserDataException; import org.gradle.api.NamedDomainObjectContainer; import org.gradle.api.artifacts.ConfigurablePublishArtifact; -import org.gradle.api.artifacts.Configuration; import org.gradle.api.artifacts.ConfigurationVariant; import org.gradle.api.artifacts.PublishArtifactSet; import org.gradle.api.attributes.AttributeContainer; import org.gradle.api.capabilities.Capability; import org.gradle.api.component.ConfigurationVariantDetails; +import org.gradle.api.internal.artifacts.configurations.ConfigurationInternal; import org.gradle.api.internal.component.UsageContext; import java.util.Collection; import java.util.Set; public class ConfigurationVariantMapping { - private final Configuration outgoingConfiguration; + private final ConfigurationInternal outgoingConfiguration; private final Action action; - public ConfigurationVariantMapping(Configuration outgoingConfiguration, Action action) { + public ConfigurationVariantMapping(ConfigurationInternal outgoingConfiguration, Action action) { this.outgoingConfiguration = outgoingConfiguration; this.action = action; } @@ -109,6 +109,7 @@ public ConfigurationVariant attributes(Action action @Override public AttributeContainer getAttributes() { + outgoingConfiguration.preventFromFurtherMutation(); return outgoingConfiguration.getAttributes(); } } diff --git a/subprojects/plugins/src/main/java/org/gradle/api/plugins/JavaPlugin.java b/subprojects/plugins/src/main/java/org/gradle/api/plugins/JavaPlugin.java index e8ab4dc69c96b..3c1d0a8318fd5 100644 --- a/subprojects/plugins/src/main/java/org/gradle/api/plugins/JavaPlugin.java +++ b/subprojects/plugins/src/main/java/org/gradle/api/plugins/JavaPlugin.java @@ -31,11 +31,14 @@ import org.gradle.api.artifacts.type.ArtifactTypeDefinition; import org.gradle.api.attributes.Usage; import org.gradle.api.attributes.Bundling; +import org.gradle.api.attributes.java.TargetJavaPlatform; import org.gradle.api.component.AdhocComponentWithVariants; import org.gradle.api.component.SoftwareComponentFactory; import org.gradle.api.file.FileCollection; import org.gradle.api.internal.artifacts.ArtifactAttributes; +import org.gradle.api.internal.artifacts.configurations.ConfigurationInternal; import org.gradle.api.internal.artifacts.dsl.LazyPublishArtifact; +import org.gradle.api.internal.attributes.AttributeContainerInternal; import org.gradle.api.internal.component.BuildableJavaComponent; import org.gradle.api.internal.component.ComponentRegistry; import org.gradle.api.internal.java.JavaLibraryPlatform; @@ -116,6 +119,7 @@ public class JavaPlugin implements Plugin { /** * The name of the API configuration, where dependencies exported by a component at compile time should * be declared. + * * @since 3.4 */ public static final String API_CONFIGURATION_NAME = "api"; @@ -123,6 +127,7 @@ public class JavaPlugin implements Plugin { /** * The name of the implementation configuration, where dependencies that are only used internally by * a component should be declared. + * * @since 3.4 */ public static final String IMPLEMENTATION_CONFIGURATION_NAME = "implementation"; @@ -160,12 +165,14 @@ public class JavaPlugin implements Plugin { /** * The name of the runtime only dependencies configuration, used to declare dependencies * that should only be found at runtime. + * * @since 3.4 */ public static final String RUNTIME_ONLY_CONFIGURATION_NAME = "runtimeOnly"; /** * The name of the runtime classpath configuration, used by a component to query its own runtime classpath. + * * @since 3.4 */ public static final String RUNTIME_CLASSPATH_CONFIGURATION_NAME = "runtimeClasspath"; @@ -173,18 +180,21 @@ public class JavaPlugin implements Plugin { /** * The name of the runtime elements configuration, that should be used by consumers * to query the runtime dependencies of a component. + * * @since 3.4 */ public static final String RUNTIME_ELEMENTS_CONFIGURATION_NAME = "runtimeElements"; /** * The name of the compile classpath configuration. + * * @since 3.4 */ public static final String COMPILE_CLASSPATH_CONFIGURATION_NAME = "compileClasspath"; /** * The name of the annotation processor configuration. + * * @since 4.6 */ @Incubating @@ -194,6 +204,7 @@ public class JavaPlugin implements Plugin { /** * The name of the test implementation dependencies configuration. + * * @since 3.4 */ public static final String TEST_IMPLEMENTATION_CONFIGURATION_NAME = "testImplementation"; @@ -214,18 +225,21 @@ public class JavaPlugin implements Plugin { /** * The name of the test runtime only dependencies configuration. + * * @since 3.4 */ public static final String TEST_RUNTIME_ONLY_CONFIGURATION_NAME = "testRuntimeOnly"; /** * The name of the test compile classpath configuration. + * * @since 3.4 */ public static final String TEST_COMPILE_CLASSPATH_CONFIGURATION_NAME = "testCompileClasspath"; /** * The name of the test annotation processor configuration. + * * @since 4.6 */ @Incubating @@ -233,6 +247,7 @@ public class JavaPlugin implements Plugin { /** * The name of the test runtime classpath configuration. + * * @since 3.4 */ public static final String TEST_RUNTIME_CLASSPATH_CONFIGURATION_NAME = "testRuntimeClasspath"; @@ -254,7 +269,7 @@ public void apply(ProjectInternal project) { BuildOutputCleanupRegistry buildOutputCleanupRegistry = project.getServices().get(BuildOutputCleanupRegistry.class); configureSourceSets(javaConvention, buildOutputCleanupRegistry); - configureConfigurations(project); + configureConfigurations(project, javaConvention); configureJavaDoc(javaConvention); configureTest(project, javaConvention); @@ -371,14 +386,14 @@ private void configureBuild(Project project) { @Override public void execute(Task task) { addDependsOnTaskInOtherProjects(task, true, - JavaBasePlugin.BUILD_NEEDED_TASK_NAME, TEST_RUNTIME_CLASSPATH_CONFIGURATION_NAME); + JavaBasePlugin.BUILD_NEEDED_TASK_NAME, TEST_RUNTIME_CLASSPATH_CONFIGURATION_NAME); } }); project.getTasks().named(JavaBasePlugin.BUILD_DEPENDENTS_TASK_NAME, new Action() { @Override public void execute(Task task) { addDependsOnTaskInOtherProjects(task, false, - JavaBasePlugin.BUILD_DEPENDENTS_TASK_NAME, TEST_RUNTIME_CLASSPATH_CONFIGURATION_NAME); + JavaBasePlugin.BUILD_DEPENDENTS_TASK_NAME, TEST_RUNTIME_CLASSPATH_CONFIGURATION_NAME); } }); } @@ -414,7 +429,7 @@ public void execute(Task task) { }); } - private void configureConfigurations(Project project) { + private void configureConfigurations(Project project, final JavaPluginConvention convention) { ConfigurationContainer configurations = project.getConfigurations(); Configuration defaultConfiguration = configurations.getByName(Dependency.DEFAULT_CONFIGURATION); @@ -432,7 +447,7 @@ private void configureConfigurations(Project project) { testRuntimeConfiguration.extendsFrom(runtimeConfiguration); testRuntimeOnlyConfiguration.extendsFrom(runtimeOnlyConfiguration); - Configuration apiElementsConfiguration = configurations.maybeCreate(API_ELEMENTS_CONFIGURATION_NAME); + final Configuration apiElementsConfiguration = configurations.maybeCreate(API_ELEMENTS_CONFIGURATION_NAME); apiElementsConfiguration.setVisible(false); apiElementsConfiguration.setDescription("API elements for main."); apiElementsConfiguration.setCanBeResolved(false); @@ -441,7 +456,7 @@ private void configureConfigurations(Project project) { apiElementsConfiguration.getAttributes().attribute(BUNDLING_ATTRIBUTE, objectFactory.named(Bundling.class, EXTERNAL)); apiElementsConfiguration.extendsFrom(runtimeConfiguration); - Configuration runtimeElementsConfiguration = configurations.maybeCreate(RUNTIME_ELEMENTS_CONFIGURATION_NAME); + final Configuration runtimeElementsConfiguration = configurations.maybeCreate(RUNTIME_ELEMENTS_CONFIGURATION_NAME); runtimeElementsConfiguration.setVisible(false); runtimeElementsConfiguration.setCanBeConsumed(true); runtimeElementsConfiguration.setCanBeResolved(false); @@ -451,6 +466,27 @@ private void configureConfigurations(Project project) { runtimeElementsConfiguration.extendsFrom(implementationConfiguration, runtimeOnlyConfiguration, runtimeConfiguration); defaultConfiguration.extendsFrom(runtimeElementsConfiguration); + + + configureTargetPlatform(apiElementsConfiguration, convention); + configureTargetPlatform(runtimeElementsConfiguration, convention); + } + + /** + * Configures the target platform for an outgoing configuration. + */ + private void configureTargetPlatform(Configuration outgoing, final JavaPluginConvention convention) { + ((ConfigurationInternal)outgoing).beforeLocking(new Action() { + @Override + public void execute(ConfigurationInternal configuration) { + String majorVersion = convention.getTargetCompatibility().getMajorVersion(); + AttributeContainerInternal attributes = configuration.getAttributes(); + // If nobody said anything about this variant's target platform, use whatever the convention says + if (!attributes.contains(TargetJavaPlatform.MINIMAL_TARGET_PLATFORM_ATTRIBUTE)) { + attributes.attribute(TargetJavaPlatform.MINIMAL_TARGET_PLATFORM_ATTRIBUTE, Integer.valueOf(majorVersion)); + } + } + }); } /** diff --git a/subprojects/plugins/src/main/java/org/gradle/api/plugins/internal/DefaultAdhocSoftwareComponent.java b/subprojects/plugins/src/main/java/org/gradle/api/plugins/internal/DefaultAdhocSoftwareComponent.java index a9f08068439f6..60b874beea4f3 100644 --- a/subprojects/plugins/src/main/java/org/gradle/api/plugins/internal/DefaultAdhocSoftwareComponent.java +++ b/subprojects/plugins/src/main/java/org/gradle/api/plugins/internal/DefaultAdhocSoftwareComponent.java @@ -21,6 +21,7 @@ import org.gradle.api.artifacts.Configuration; import org.gradle.api.component.AdhocComponentWithVariants; import org.gradle.api.component.ConfigurationVariantDetails; +import org.gradle.api.internal.artifacts.configurations.ConfigurationInternal; import org.gradle.api.internal.component.SoftwareComponentInternal; import org.gradle.api.internal.component.UsageContext; import org.gradle.api.internal.java.usagecontext.ConfigurationVariantMapping; @@ -43,7 +44,7 @@ public String getName() { @Override public void addVariantsFromConfiguration(Configuration outgoingConfiguration, Action spec) { - variants.add(new ConfigurationVariantMapping(outgoingConfiguration, spec)); + variants.add(new ConfigurationVariantMapping((ConfigurationInternal) outgoingConfiguration, spec)); } @Override diff --git a/subprojects/plugins/src/main/java/org/gradle/api/plugins/internal/DefaultJavaFeatureSpec.java b/subprojects/plugins/src/main/java/org/gradle/api/plugins/internal/DefaultJavaFeatureSpec.java index 75ce66a48d4ad..bbdeaf1c92068 100644 --- a/subprojects/plugins/src/main/java/org/gradle/api/plugins/internal/DefaultJavaFeatureSpec.java +++ b/subprojects/plugins/src/main/java/org/gradle/api/plugins/internal/DefaultJavaFeatureSpec.java @@ -23,11 +23,14 @@ import org.gradle.api.attributes.AttributeContainer; import org.gradle.api.attributes.Usage; import org.gradle.api.attributes.Bundling; +import org.gradle.api.attributes.java.TargetJavaPlatform; import org.gradle.api.capabilities.Capability; import org.gradle.api.component.AdhocComponentWithVariants; import org.gradle.api.component.SoftwareComponent; import org.gradle.api.component.SoftwareComponentContainer; +import org.gradle.api.internal.artifacts.configurations.ConfigurationInternal; import org.gradle.api.internal.artifacts.dsl.LazyPublishArtifact; +import org.gradle.api.internal.attributes.AttributeContainerInternal; import org.gradle.api.model.ObjectFactory; import org.gradle.api.plugins.AppliedPlugin; import org.gradle.api.plugins.BasePlugin; @@ -127,6 +130,8 @@ private void setupConfigurations(SourceSet sourceSet) { configureUsage(runtimeElements, Usage.JAVA_RUNTIME_JARS); configurePacking(apiElements); configurePacking(runtimeElements); + configureTargetPlatform(apiElements); + configureTargetPlatform(runtimeElements); configureCapabilities(apiElements); configureCapabilities(runtimeElements); attachArtifactToConfiguration(apiElements); @@ -154,6 +159,20 @@ public void execute(AppliedPlugin plugin) { }); } + private void configureTargetPlatform(Configuration configuration) { + ((ConfigurationInternal)configuration).beforeLocking(new Action() { + @Override + public void execute(ConfigurationInternal configuration) { + String majorVersion = javaPluginConvention.getTargetCompatibility().getMajorVersion(); + AttributeContainerInternal attributes = configuration.getAttributes(); + // If nobody said anything about this variant's target platform, use whatever the convention says + if (!attributes.contains(TargetJavaPlatform.MINIMAL_TARGET_PLATFORM_ATTRIBUTE)) { + attributes.attribute(TargetJavaPlatform.MINIMAL_TARGET_PLATFORM_ATTRIBUTE, Integer.valueOf(majorVersion)); + } + } + }); + } + private void configurePacking(Configuration configuration) { configuration.getAttributes().attribute(BUNDLING_ATTRIBUTE, objectFactory.named(Bundling.class, EXTERNAL)); } diff --git a/subprojects/publish/src/main/java/org/gradle/api/publish/internal/ModuleMetadataFileGenerator.java b/subprojects/publish/src/main/java/org/gradle/api/publish/internal/ModuleMetadataFileGenerator.java index 416ddd7554dca..20ef852de15c9 100644 --- a/subprojects/publish/src/main/java/org/gradle/api/publish/internal/ModuleMetadataFileGenerator.java +++ b/subprojects/publish/src/main/java/org/gradle/api/publish/internal/ModuleMetadataFileGenerator.java @@ -328,6 +328,9 @@ private void writeAttributes(AttributeContainer attributes, JsonWriter jsonWrite if (value instanceof Boolean) { Boolean b = (Boolean) value; jsonWriter.value(b); + } else if (value instanceof Integer) { + Integer i = (Integer) value; + jsonWriter.value(i); } else if (value instanceof String) { String s = (String) value; jsonWriter.value(s); diff --git a/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/CoercingStringValueSnapshot.java b/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/CoercingStringValueSnapshot.java index 62c0996409b7f..71e4057d78b48 100644 --- a/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/CoercingStringValueSnapshot.java +++ b/subprojects/snapshots/src/main/java/org/gradle/internal/snapshot/impl/CoercingStringValueSnapshot.java @@ -41,6 +41,9 @@ public S coerce(Class type) { if (Named.class.isAssignableFrom(type)) { return type.cast(instantiator.named(type.asSubclass(Named.class), getValue())); } + if (Integer.class.equals(type)) { + return type.cast(Integer.valueOf(getValue())); + } return null; } } From 27e05c67e95c074cf32a34ef336afd712de34eb6 Mon Sep 17 00:00:00 2001 From: Cedric Champeau Date: Wed, 20 Feb 2019 13:35:38 +0100 Subject: [PATCH 054/853] Simplify Java platform compatibility and disambiguation rules We should not assume that because the consumer said nothing, we should reject the producer if it has a higher version than the current Gradle runtime: it actually depends on what the consumer is going to do (it's not necessarily to add to a compile classpath). --- .../artifacts/JavaEcosystemSupport.java | 66 +------------------ .../TargetJavaPlatformRulesTest.groovy | 37 +++++++---- .../DefaultOrderedDisambiguationRule.java | 10 ++- 3 files changed, 30 insertions(+), 83 deletions(-) diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/artifacts/JavaEcosystemSupport.java b/subprojects/core/src/main/java/org/gradle/api/internal/artifacts/JavaEcosystemSupport.java index e9a1c872ad6df..94dec701c28ed 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/artifacts/JavaEcosystemSupport.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/artifacts/JavaEcosystemSupport.java @@ -17,9 +17,9 @@ import com.google.common.annotations.VisibleForTesting; import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Ordering; import org.gradle.api.Action; import org.gradle.api.ActionConfiguration; -import org.gradle.api.JavaVersion; import org.gradle.api.attributes.AttributeCompatibilityRule; import org.gradle.api.attributes.AttributeDisambiguationRule; import org.gradle.api.attributes.AttributeMatchingStrategy; @@ -44,15 +44,8 @@ public static void configureSchema(AttributesSchema attributesSchema, final Obje private static void configureTargetPlatform(AttributesSchema attributesSchema) { AttributeMatchingStrategy targetPlatformSchema = attributesSchema.attribute(TargetJavaPlatform.MINIMAL_TARGET_PLATFORM_ATTRIBUTE); - targetPlatformSchema.getCompatibilityRules().add(TargetPlatformCompatibilityRules.class); - targetPlatformSchema.getDisambiguationRules().add(TargetPlatformDisambiguationRules.class, new Action() { - @Override - public void execute(ActionConfiguration config) { - // by default we will reject any producer which version is higher than - // the current Gradle runtime (if the consumer says nothing) - config.params(Integer.valueOf(JavaVersion.current().getMajorVersion())); - } - }); + targetPlatformSchema.getCompatibilityRules().ordered(Ordering.natural()); + targetPlatformSchema.getDisambiguationRules().pickLast(Ordering.natural()); } private static void configureBundling(AttributesSchema attributesSchema) { @@ -295,57 +288,4 @@ public void execute(MultipleCandidatesDetails details) { } } - @VisibleForTesting - public static class TargetPlatformCompatibilityRules implements AttributeCompatibilityRule, ReusableAction { - @Override - public void execute(CompatibilityCheckDetails details) { - Integer consumerLevel = details.getConsumerValue(); - Integer producerLevel = details.getProducerValue(); - if (consumerLevel == null || producerLevel == null) { - details.compatible(); - return; - } - if (producerLevel <= consumerLevel) { - details.compatible(); - } else { - details.incompatible(); - } - } - } - - @VisibleForTesting - public static class TargetPlatformDisambiguationRules implements AttributeDisambiguationRule, ReusableAction { - private final int minimalPlatformVersion; - - @Inject - public TargetPlatformDisambiguationRules(int minimalPlatformVersion) { - this.minimalPlatformVersion = minimalPlatformVersion; - } - - @Override - public void execute(MultipleCandidatesDetails details) { - Integer consumerLevel = details.getConsumerValue(); - boolean checkMinimalBound = false; - if (consumerLevel == null) { - consumerLevel = minimalPlatformVersion; - checkMinimalBound = true; - } - int selected = Integer.MAX_VALUE; - int diff = Integer.MAX_VALUE; - for (Integer producerLevel : details.getCandidateValues()) { - if (checkMinimalBound && producerLevel compatibilityRules + private DisambiguationRule disambiguationRules + + def setup() { + AttributesSchema schema = new DefaultAttributesSchema(Stub(ComponentAttributeMatcher), TestUtil.instantiatorFactory(), SnapshotTestUtil.valueSnapshotter()) + JavaEcosystemSupport.configureSchema(schema, TestUtil.objectFactory()) + compatibilityRules = schema.compatibilityRules(TargetJavaPlatform.MINIMAL_TARGET_PLATFORM_ATTRIBUTE) + disambiguationRules = schema.disambiguationRules(TargetJavaPlatform.MINIMAL_TARGET_PLATFORM_ATTRIBUTE) + } @Unroll("compatibility consumer=#consumer producer=#producer compatible=#compatible") def "check compatibility rules"() { - CompatibilityCheckDetails details = Mock(CompatibilityCheckDetails) + CompatibilityCheckResult details = Mock(CompatibilityCheckResult) when: compatibilityRules.execute(details) @@ -44,10 +59,6 @@ class TargetJavaPlatformRulesTest extends Specification { where: consumer | producer | compatible - null | 5 | true - null | 6 | true - null | 11 | true - 8 | 6 | true 8 | 7 | true 8 | 8 | true @@ -58,21 +69,19 @@ class TargetJavaPlatformRulesTest extends Specification { @Unroll("disamgiguates when consumer=#consumer and candidates=#candidates chooses=#expected") def "check disambiguation rules"() { - MultipleCandidatesDetails details = Mock(MultipleCandidatesDetails) + MultipleCandidatesResult details = Mock() when: disambiguationRules.execute(details) then: - 1 * details.getConsumerValue() >> consumer 1 * details.getCandidateValues() >> candidates 1 * details.closestMatch(expected) + 1 * details.hasResult() + 0 * details._ where: consumer | candidates | expected - null | [4, 8, 11] | 8 - null | [11, 8] | 8 - 6 | [6] | 6 7 | [6, 7] | 7 8 | [6, 7] | 7 diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/attributes/DefaultOrderedDisambiguationRule.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/attributes/DefaultOrderedDisambiguationRule.java index f99c7cc0c336d..00ddb81b628bd 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/attributes/DefaultOrderedDisambiguationRule.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/attributes/DefaultOrderedDisambiguationRule.java @@ -18,8 +18,8 @@ import org.gradle.api.Action; import org.gradle.api.attributes.MultipleCandidatesDetails; -import java.util.Collection; import java.util.Comparator; +import java.util.Set; public class DefaultOrderedDisambiguationRule implements Action> { private final Comparator comparator; @@ -32,22 +32,20 @@ public DefaultOrderedDisambiguationRule(Comparator comparator, boolea @Override public void execute(MultipleCandidatesDetails details) { - Collection values = details.getCandidateValues(); + Set candidateValues = details.getCandidateValues(); T min = null; T max = null; - for (T value : values) { - + for (T value : candidateValues) { if (min == null || comparator.compare(value, min) < 0) { min = value; } if (max == null || comparator.compare(value, max) > 0) { max = value; } - } T cmp = pickFirst ? min : max; if (cmp != null) { - for (T value : details.getCandidateValues()) { + for (T value : candidateValues) { if (value.equals(cmp)) { details.closestMatch(value); } From 12b91392ac5c71bff351bb4829d484b51af62417 Mon Sep 17 00:00:00 2001 From: Cedric Champeau Date: Wed, 20 Feb 2019 14:02:14 +0100 Subject: [PATCH 055/853] Set the target platform attribute on the consumer side This commit sets a default value for the target platform attribute, whenever the consumer says nothing (which should be the case for all scripts today). The default is the same as with compilation: use whatever `targetCompatibility` says. --- .../artifacts/JavaEcosystemSupport.java | 12 ++++++++ .../initialization/DefaultScriptHandler.java | 3 ++ ...ncyInsightReportTaskIntegrationTest.groovy | 28 +++++++++++++++++-- ...ReportVariantDetailsIntegrationTest.groovy | 8 +++--- .../gradle/api/plugins/JavaBasePlugin.java | 20 +++++++++++-- .../org/gradle/api/plugins/JavaPlugin.java | 10 ++----- 6 files changed, 63 insertions(+), 18 deletions(-) diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/artifacts/JavaEcosystemSupport.java b/subprojects/core/src/main/java/org/gradle/api/internal/artifacts/JavaEcosystemSupport.java index 94dec701c28ed..14c38297ed3eb 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/artifacts/JavaEcosystemSupport.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/artifacts/JavaEcosystemSupport.java @@ -20,16 +20,19 @@ import com.google.common.collect.Ordering; import org.gradle.api.Action; import org.gradle.api.ActionConfiguration; +import org.gradle.api.JavaVersion; import org.gradle.api.attributes.AttributeCompatibilityRule; import org.gradle.api.attributes.AttributeDisambiguationRule; import org.gradle.api.attributes.AttributeMatchingStrategy; import org.gradle.api.attributes.AttributesSchema; import org.gradle.api.attributes.CompatibilityCheckDetails; +import org.gradle.api.attributes.HasAttributes; import org.gradle.api.attributes.MultipleCandidatesDetails; import org.gradle.api.attributes.Usage; import org.gradle.api.attributes.Bundling; import org.gradle.api.attributes.java.TargetJavaPlatform; import org.gradle.api.internal.ReusableAction; +import org.gradle.api.internal.attributes.AttributeContainerInternal; import org.gradle.api.model.ObjectFactory; import javax.inject.Inject; @@ -42,6 +45,15 @@ public static void configureSchema(AttributesSchema attributesSchema, final Obje configureTargetPlatform(attributesSchema); } + public static void configureDefaultTargetPlatform(HasAttributes configuration, JavaVersion version) { + String majorVersion = version.getMajorVersion(); + AttributeContainerInternal attributes = (AttributeContainerInternal) configuration.getAttributes(); + // If nobody said anything about this variant's target platform, use whatever the convention says + if (!attributes.contains(TargetJavaPlatform.MINIMAL_TARGET_PLATFORM_ATTRIBUTE)) { + attributes.attribute(TargetJavaPlatform.MINIMAL_TARGET_PLATFORM_ATTRIBUTE, Integer.valueOf(majorVersion)); + } + } + private static void configureTargetPlatform(AttributesSchema attributesSchema) { AttributeMatchingStrategy targetPlatformSchema = attributesSchema.attribute(TargetJavaPlatform.MINIMAL_TARGET_PLATFORM_ATTRIBUTE); targetPlatformSchema.getCompatibilityRules().ordered(Ordering.natural()); diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/initialization/DefaultScriptHandler.java b/subprojects/core/src/main/java/org/gradle/api/internal/initialization/DefaultScriptHandler.java index 6312470dc029f..6c7b90bd98a09 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/initialization/DefaultScriptHandler.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/initialization/DefaultScriptHandler.java @@ -16,12 +16,14 @@ package org.gradle.api.internal.initialization; import groovy.lang.Closure; +import org.gradle.api.JavaVersion; import org.gradle.api.artifacts.Configuration; import org.gradle.api.artifacts.ConfigurationContainer; import org.gradle.api.artifacts.dsl.DependencyHandler; import org.gradle.api.artifacts.dsl.RepositoryHandler; import org.gradle.api.attributes.Bundling; import org.gradle.api.attributes.Usage; +import org.gradle.api.attributes.java.TargetJavaPlatform; import org.gradle.api.initialization.dsl.ScriptHandler; import org.gradle.api.internal.DynamicObjectAware; import org.gradle.api.internal.artifacts.DependencyResolutionServices; @@ -114,6 +116,7 @@ private void defineConfiguration() { classpathConfiguration = configContainer.create(CLASSPATH_CONFIGURATION); classpathConfiguration.getAttributes().attribute(Usage.USAGE_ATTRIBUTE, NamedObjectInstantiator.INSTANCE.named(Usage.class, Usage.JAVA_RUNTIME)); classpathConfiguration.getAttributes().attribute(Bundling.BUNDLING_ATTRIBUTE, NamedObjectInstantiator.INSTANCE.named(Bundling.class, Bundling.EXTERNAL)); + classpathConfiguration.getAttributes().attribute(TargetJavaPlatform.MINIMAL_TARGET_PLATFORM_ATTRIBUTE, Integer.valueOf(JavaVersion.current().getMajorVersion())); } } diff --git a/subprojects/diagnostics/src/integTest/groovy/org/gradle/api/tasks/diagnostics/DependencyInsightReportTaskIntegrationTest.groovy b/subprojects/diagnostics/src/integTest/groovy/org/gradle/api/tasks/diagnostics/DependencyInsightReportTaskIntegrationTest.groovy index 4e19023f0dd11..6d056cdee62c4 100644 --- a/subprojects/diagnostics/src/integTest/groovy/org/gradle/api/tasks/diagnostics/DependencyInsightReportTaskIntegrationTest.groovy +++ b/subprojects/diagnostics/src/integTest/groovy/org/gradle/api/tasks/diagnostics/DependencyInsightReportTaskIntegrationTest.groovy @@ -1859,6 +1859,7 @@ org:leaf4:1.0 Requested attributes not found in the selected variant: org.gradle.dependency.bundling = external + org.gradle.java.min.platform = ${JavaVersion.current().majorVersion} ] org:leaf4:1.0 @@ -1896,6 +1897,7 @@ org:leaf1:1.0 Requested attributes not found in the selected variant: org.gradle.dependency.bundling = external + org.gradle.java.min.platform = ${JavaVersion.current().majorVersion} ] org:leaf1:1.0 @@ -1915,6 +1917,7 @@ org:leaf2:1.0 Requested attributes not found in the selected variant: org.gradle.dependency.bundling = external + org.gradle.java.min.platform = ${JavaVersion.current().majorVersion} ] org:leaf2:1.0 @@ -1971,7 +1974,7 @@ project :api variant "apiElements" [ org.gradle.usage = java-api-jars (compatible with: java-api) org.gradle.dependency.bundling = external - org.gradle.java.min.platform = ${JavaVersion.current().majorVersion} (not requested) + org.gradle.java.min.platform = ${JavaVersion.current().majorVersion} ] project :api @@ -1988,7 +1991,7 @@ project :some:deeply:nested variant "apiElements" [ org.gradle.usage = java-api-jars (compatible with: java-api) org.gradle.dependency.bundling = external - org.gradle.java.min.platform = ${JavaVersion.current().majorVersion} (not requested) + org.gradle.java.min.platform = ${JavaVersion.current().majorVersion} ] project :some:deeply:nested @@ -2004,7 +2007,7 @@ project :some:deeply:nested variant "apiElements" [ org.gradle.usage = java-api-jars (compatible with: java-api) org.gradle.dependency.bundling = external - org.gradle.java.min.platform = ${JavaVersion.current().majorVersion} (not requested) + org.gradle.java.min.platform = ${JavaVersion.current().majorVersion} ] project :some:deeply:nested @@ -2058,6 +2061,7 @@ org:leaf3:1.0 Requested attributes not found in the selected variant: org.gradle.dependency.bundling = external + org.gradle.java.min.platform = ${JavaVersion.current().majorVersion} ] org:leaf3:1.0 @@ -2161,6 +2165,7 @@ foo:foo:1.0 Requested attributes not found in the selected variant: org.gradle.dependency.bundling = external + org.gradle.java.min.platform = ${JavaVersion.current().majorVersion} ] Selection reasons: - By constraint : $rejected @@ -2216,6 +2221,7 @@ org:foo -> $selected Requested attributes not found in the selected variant: org.gradle.dependency.bundling = external + org.gradle.java.min.platform = ${JavaVersion.current().majorVersion} ] Selection reasons: - By constraint : ${rejected}${reason} @@ -2268,6 +2274,7 @@ org:foo -> $selected Requested attributes not found in the selected variant: org.gradle.dependency.bundling = external + org.gradle.java.min.platform = ${JavaVersion.current().majorVersion} ] Selection reasons: - Was requested : ${rejected}${reason} @@ -2317,6 +2324,7 @@ org:foo:${displayVersion} -> $selected Requested attributes not found in the selected variant: org.gradle.dependency.bundling = external + org.gradle.java.min.platform = ${JavaVersion.current().majorVersion} ] Selection reasons: - Was requested : didn't match versions 2.0, 1.5, 1.4 @@ -2372,6 +2380,7 @@ org:foo:[1.1,1.3] -> 1.3 Requested attributes not found in the selected variant: org.gradle.dependency.bundling = external + org.gradle.java.min.platform = ${JavaVersion.current().majorVersion} ] Selection reasons: - Was requested : rejected versions 1.2, 1.1 @@ -2387,6 +2396,7 @@ org:foo:1.1 Requested attributes not found in the selected variant: org.gradle.dependency.bundling = external + org.gradle.java.min.platform = ${JavaVersion.current().majorVersion} ] Selection reasons: - Was requested : rejected version 1.2 @@ -2446,6 +2456,7 @@ org:bar:1.0 Requested attributes not found in the selected variant: org.gradle.dependency.bundling = external + org.gradle.java.min.platform = ${JavaVersion.current().majorVersion} ] Selection reasons: - Rejection : 1.2 by rule because version 1.2 is bad @@ -2462,6 +2473,7 @@ org:foo:1.1 Requested attributes not found in the selected variant: org.gradle.dependency.bundling = external + org.gradle.java.min.platform = ${JavaVersion.current().majorVersion} ] Selection reasons: - Was requested : rejected version 1.2 @@ -2506,6 +2518,7 @@ org:leaf:1.0 (by constraint) Requested attributes not found in the selected variant: org.gradle.dependency.bundling = external + org.gradle.java.min.platform = ${JavaVersion.current().majorVersion} ] org:leaf:1.0 @@ -2558,6 +2571,7 @@ org.test:leaf:1.0 Requested attributes not found in the selected variant: org.gradle.dependency.bundling = external + org.gradle.java.min.platform = ${JavaVersion.current().majorVersion} ] Selection reasons: - Was requested : first reason @@ -2739,6 +2753,7 @@ org:foo:1.0 Requested attributes not found in the selected variant: org.gradle.dependency.bundling = external + org.gradle.java.min.platform = ${JavaVersion.current().majorVersion} ] Selection reasons: - Was requested : rejected versions 1.2, 1.1 @@ -2795,6 +2810,7 @@ org:foo:{require [1.0,); reject 1.1} -> 1.0 Requested attributes not found in the selected variant: org.gradle.dependency.bundling = external + org.gradle.java.min.platform = ${JavaVersion.current().majorVersion} ] Selection reasons: - Was requested : first reason @@ -2860,15 +2876,18 @@ org:foo:1.0 Requested attributes not found in the selected variant: org.gradle.dependency.bundling = external + org.gradle.java.min.platform = ${JavaVersion.current().majorVersion} ] Selection reasons: - Rejection : version 1.2: - Attribute 'color' didn't match. Requested 'blue', was: 'red' - Attribute 'org.gradle.dependency.bundling' didn't match. Requested 'external', was: not found + - Attribute 'org.gradle.java.min.platform' didn't match. Requested '${JavaVersion.current().majorVersion}', was: not found - Attribute 'org.gradle.usage' didn't match. Requested 'java-api', was: not found - Rejection : version 1.1: - Attribute 'color' didn't match. Requested 'blue', was: 'green' - Attribute 'org.gradle.dependency.bundling' didn't match. Requested 'external', was: not found + - Attribute 'org.gradle.java.min.platform' didn't match. Requested '${JavaVersion.current().majorVersion}', was: not found - Attribute 'org.gradle.usage' didn't match. Requested 'java-api', was: not found org:foo:[1.0,) -> 1.0 @@ -2932,6 +2951,7 @@ planet:mercury:1.0.2 Requested attributes not found in the selected variant: org.gradle.dependency.bundling = external + org.gradle.java.min.platform = ${JavaVersion.current().majorVersion} ] Selection reasons: - By conflict resolution : between versions 1.0.2 and 1.0.1 @@ -2962,6 +2982,7 @@ planet:venus:2.0.1 Requested attributes not found in the selected variant: org.gradle.dependency.bundling = external + org.gradle.java.min.platform = ${JavaVersion.current().majorVersion} ] Selection reasons: - By conflict resolution : between versions 2.0.0, 2.0.1 and 1.0 @@ -2992,6 +3013,7 @@ planet:pluto:1.0.0 Requested attributes not found in the selected variant: org.gradle.dependency.bundling = external + org.gradle.java.min.platform = ${JavaVersion.current().majorVersion} ] planet:pluto:1.0.0 diff --git a/subprojects/diagnostics/src/integTest/groovy/org/gradle/api/tasks/diagnostics/DependencyInsightReportVariantDetailsIntegrationTest.groovy b/subprojects/diagnostics/src/integTest/groovy/org/gradle/api/tasks/diagnostics/DependencyInsightReportVariantDetailsIntegrationTest.groovy index 56aba0ce74dad..1e340df9d5eb4 100644 --- a/subprojects/diagnostics/src/integTest/groovy/org/gradle/api/tasks/diagnostics/DependencyInsightReportVariantDetailsIntegrationTest.groovy +++ b/subprojects/diagnostics/src/integTest/groovy/org/gradle/api/tasks/diagnostics/DependencyInsightReportVariantDetailsIntegrationTest.groovy @@ -56,8 +56,8 @@ class DependencyInsightReportVariantDetailsIntegrationTest extends AbstractInteg outputContains """project :$expectedProject variant "$expectedVariant" [ $expectedAttributes - org.gradle.dependency.bundling = external - org.gradle.java.min.platform = ${JavaVersion.current().majorVersion} (not requested) + org.gradle.dependency.bundling = external (not requested) + org.gradle.java.min.platform = ${JavaVersion.current().majorVersion} ] project :$expectedProject @@ -101,7 +101,7 @@ project :$expectedProject run "dependencyInsight", "--dependency", "leaf" then: - output.contains """org.test:leaf:1.0 + outputContains """org.test:leaf:1.0 variant "api" [ org.gradle.usage = java-api org.gradle.test = published attribute (not requested) @@ -109,7 +109,7 @@ project :$expectedProject Requested attributes not found in the selected variant: org.gradle.dependency.bundling = external - org.gradle.blah = something + org.gradle.java.min.platform = ${JavaVersion.current().majorVersion} ] org.test:leaf:1.0 diff --git a/subprojects/plugins/src/main/java/org/gradle/api/plugins/JavaBasePlugin.java b/subprojects/plugins/src/main/java/org/gradle/api/plugins/JavaBasePlugin.java index 8d64e4b06cbb0..0d6adb8a14bbf 100644 --- a/subprojects/plugins/src/main/java/org/gradle/api/plugins/JavaBasePlugin.java +++ b/subprojects/plugins/src/main/java/org/gradle/api/plugins/JavaBasePlugin.java @@ -32,8 +32,9 @@ import org.gradle.api.file.SourceDirectorySet; import org.gradle.api.internal.ConventionMapping; import org.gradle.api.internal.IConventionAware; -import org.gradle.api.internal.artifacts.dsl.ComponentMetadataHandlerInternal; import org.gradle.api.internal.artifacts.JavaEcosystemSupport; +import org.gradle.api.internal.artifacts.configurations.ConfigurationInternal; +import org.gradle.api.internal.artifacts.dsl.ComponentMetadataHandlerInternal; import org.gradle.api.internal.plugins.DslObject; import org.gradle.api.internal.project.ProjectInternal; import org.gradle.api.model.ObjectFactory; @@ -150,7 +151,7 @@ public void execute(final SourceSet sourceSet) { ConfigurationContainer configurations = project.getConfigurations(); - defineConfigurationsForSourceSet(sourceSet, configurations); + defineConfigurationsForSourceSet(sourceSet, configurations, pluginConvention); definePathsForSourceSet(sourceSet, outputConventionMapping, project); createProcessResourcesTask(sourceSet, sourceSet.getResources(), project); @@ -231,7 +232,7 @@ public Object call() { sourceSet.getResources().srcDir("src/" + sourceSet.getName() + "/resources"); } - private void defineConfigurationsForSourceSet(SourceSet sourceSet, ConfigurationContainer configurations) { + private void defineConfigurationsForSourceSet(SourceSet sourceSet, ConfigurationContainer configurations, final JavaPluginConvention convention) { String compileConfigurationName = sourceSet.getCompileConfigurationName(); String implementationConfigurationName = sourceSet.getImplementationConfigurationName(); String runtimeConfigurationName = sourceSet.getRuntimeConfigurationName(); @@ -241,6 +242,8 @@ private void defineConfigurationsForSourceSet(SourceSet sourceSet, Configuration String annotationProcessorConfigurationName = sourceSet.getAnnotationProcessorConfigurationName(); String runtimeClasspathConfigurationName = sourceSet.getRuntimeClasspathConfigurationName(); String sourceSetName = sourceSet.toString(); + Action configureDefaultTargetPlatform = configureDefaultTargetPlatform(convention); + Configuration compileConfiguration = configurations.maybeCreate(compileConfigurationName); compileConfiguration.setVisible(false); @@ -269,6 +272,7 @@ private void defineConfigurationsForSourceSet(SourceSet sourceSet, Configuration compileClasspathConfiguration.setCanBeConsumed(false); compileClasspathConfiguration.getAttributes().attribute(USAGE_ATTRIBUTE, objectFactory.named(Usage.class, Usage.JAVA_API)); compileClasspathConfiguration.getAttributes().attribute(BUNDLING_ATTRIBUTE, objectFactory.named(Bundling.class, Bundling.EXTERNAL)); + ((ConfigurationInternal)compileClasspathConfiguration).beforeLocking(configureDefaultTargetPlatform); Configuration annotationProcessorConfiguration = configurations.maybeCreate(annotationProcessorConfigurationName); annotationProcessorConfiguration.setVisible(false); @@ -290,12 +294,22 @@ private void defineConfigurationsForSourceSet(SourceSet sourceSet, Configuration runtimeClasspathConfiguration.extendsFrom(runtimeOnlyConfiguration, runtimeConfiguration, implementationConfiguration); runtimeClasspathConfiguration.getAttributes().attribute(USAGE_ATTRIBUTE, objectFactory.named(Usage.class, Usage.JAVA_RUNTIME)); runtimeClasspathConfiguration.getAttributes().attribute(BUNDLING_ATTRIBUTE, objectFactory.named(Bundling.class, Bundling.EXTERNAL)); + ((ConfigurationInternal)runtimeClasspathConfiguration).beforeLocking(configureDefaultTargetPlatform); sourceSet.setCompileClasspath(compileClasspathConfiguration); sourceSet.setRuntimeClasspath(sourceSet.getOutput().plus(runtimeClasspathConfiguration)); sourceSet.setAnnotationProcessorPath(annotationProcessorConfiguration); } + private Action configureDefaultTargetPlatform(final JavaPluginConvention convention) { + return new Action() { + @Override + public void execute(ConfigurationInternal conf) { + JavaEcosystemSupport.configureDefaultTargetPlatform(conf, convention.getTargetCompatibility()); + } + }; + } + private void configureCompileDefaults(final Project project, final JavaPluginConvention javaConvention) { project.getTasks().withType(AbstractCompile.class).configureEach(new Action() { public void execute(final AbstractCompile compile) { diff --git a/subprojects/plugins/src/main/java/org/gradle/api/plugins/JavaPlugin.java b/subprojects/plugins/src/main/java/org/gradle/api/plugins/JavaPlugin.java index 3c1d0a8318fd5..7ca7e867d46bf 100644 --- a/subprojects/plugins/src/main/java/org/gradle/api/plugins/JavaPlugin.java +++ b/subprojects/plugins/src/main/java/org/gradle/api/plugins/JavaPlugin.java @@ -31,14 +31,13 @@ import org.gradle.api.artifacts.type.ArtifactTypeDefinition; import org.gradle.api.attributes.Usage; import org.gradle.api.attributes.Bundling; -import org.gradle.api.attributes.java.TargetJavaPlatform; import org.gradle.api.component.AdhocComponentWithVariants; import org.gradle.api.component.SoftwareComponentFactory; import org.gradle.api.file.FileCollection; import org.gradle.api.internal.artifacts.ArtifactAttributes; +import org.gradle.api.internal.artifacts.JavaEcosystemSupport; import org.gradle.api.internal.artifacts.configurations.ConfigurationInternal; import org.gradle.api.internal.artifacts.dsl.LazyPublishArtifact; -import org.gradle.api.internal.attributes.AttributeContainerInternal; import org.gradle.api.internal.component.BuildableJavaComponent; import org.gradle.api.internal.component.ComponentRegistry; import org.gradle.api.internal.java.JavaLibraryPlatform; @@ -479,12 +478,7 @@ private void configureTargetPlatform(Configuration outgoing, final JavaPluginCon ((ConfigurationInternal)outgoing).beforeLocking(new Action() { @Override public void execute(ConfigurationInternal configuration) { - String majorVersion = convention.getTargetCompatibility().getMajorVersion(); - AttributeContainerInternal attributes = configuration.getAttributes(); - // If nobody said anything about this variant's target platform, use whatever the convention says - if (!attributes.contains(TargetJavaPlatform.MINIMAL_TARGET_PLATFORM_ATTRIBUTE)) { - attributes.attribute(TargetJavaPlatform.MINIMAL_TARGET_PLATFORM_ATTRIBUTE, Integer.valueOf(majorVersion)); - } + JavaEcosystemSupport.configureDefaultTargetPlatform(configuration, convention.getTargetCompatibility()); } }); } From 74eca89e1f0a117ed0174ef0a51f44c65312b7c3 Mon Sep 17 00:00:00 2001 From: Cedric Champeau Date: Wed, 20 Feb 2019 15:19:53 +0100 Subject: [PATCH 056/853] Rename the Java target platform attribute This is to avoid confusion: while "minimal" makes sense from the producer point of view, it reads strange when seen from the consumer side: the "minimal" version here can be higher than what a producer has. So it's now simplified to "target platform". --- .../attributes/java/TargetJavaPlatform.java | 2 +- .../artifacts/JavaEcosystemSupport.java | 6 +-- .../initialization/DefaultScriptHandler.java | 8 +-- .../TargetJavaPlatformRulesTest.groovy | 4 +- .../DefaultScriptHandlerTest.groovy | 13 +++-- ...ipleVariantSelectionIntegrationTest.groovy | 10 ++-- ...ncyInsightReportTaskIntegrationTest.groovy | 54 +++++++++---------- ...ReportVariantDetailsIntegrationTest.groovy | 5 +- .../test/fixtures/ivy/IvyJavaModule.groovy | 2 +- .../fixtures/maven/MavenJavaModule.groovy | 6 +-- ...tionOutgoingVariantsIntegrationTest.groovy | 2 +- ...rojectTargetPlatformIntegrationTest.groovy | 14 ++--- ...raryOutgoingVariantsIntegrationTest.groovy | 2 +- ...lishedTargetPlatformIntegrationTest.groovy | 24 ++++----- ...jectOutgoingVariantsIntegrationTest.groovy | 2 +- .../internal/DefaultJavaFeatureSpec.java | 4 +- 16 files changed, 83 insertions(+), 75 deletions(-) diff --git a/subprojects/core-api/src/main/java/org/gradle/api/attributes/java/TargetJavaPlatform.java b/subprojects/core-api/src/main/java/org/gradle/api/attributes/java/TargetJavaPlatform.java index 63442bc0e0016..54f13e81e6748 100644 --- a/subprojects/core-api/src/main/java/org/gradle/api/attributes/java/TargetJavaPlatform.java +++ b/subprojects/core-api/src/main/java/org/gradle/api/attributes/java/TargetJavaPlatform.java @@ -30,5 +30,5 @@ public interface TargetJavaPlatform { /** * The minimal target platform for a Java library. Any consumer below this version would not be able to consume it. */ - Attribute MINIMAL_TARGET_PLATFORM_ATTRIBUTE = Attribute.of("org.gradle.java.min.platform", Integer.class); + Attribute TARGET_PLATFORM_ATTRIBUTE = Attribute.of("org.gradle.jvm.platform", Integer.class); } diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/artifacts/JavaEcosystemSupport.java b/subprojects/core/src/main/java/org/gradle/api/internal/artifacts/JavaEcosystemSupport.java index 14c38297ed3eb..4d646f7b615c7 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/artifacts/JavaEcosystemSupport.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/artifacts/JavaEcosystemSupport.java @@ -49,13 +49,13 @@ public static void configureDefaultTargetPlatform(HasAttributes configuration, J String majorVersion = version.getMajorVersion(); AttributeContainerInternal attributes = (AttributeContainerInternal) configuration.getAttributes(); // If nobody said anything about this variant's target platform, use whatever the convention says - if (!attributes.contains(TargetJavaPlatform.MINIMAL_TARGET_PLATFORM_ATTRIBUTE)) { - attributes.attribute(TargetJavaPlatform.MINIMAL_TARGET_PLATFORM_ATTRIBUTE, Integer.valueOf(majorVersion)); + if (!attributes.contains(TargetJavaPlatform.TARGET_PLATFORM_ATTRIBUTE)) { + attributes.attribute(TargetJavaPlatform.TARGET_PLATFORM_ATTRIBUTE, Integer.valueOf(majorVersion)); } } private static void configureTargetPlatform(AttributesSchema attributesSchema) { - AttributeMatchingStrategy targetPlatformSchema = attributesSchema.attribute(TargetJavaPlatform.MINIMAL_TARGET_PLATFORM_ATTRIBUTE); + AttributeMatchingStrategy targetPlatformSchema = attributesSchema.attribute(TargetJavaPlatform.TARGET_PLATFORM_ATTRIBUTE); targetPlatformSchema.getCompatibilityRules().ordered(Ordering.natural()); targetPlatformSchema.getDisambiguationRules().pickLast(Ordering.natural()); } diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/initialization/DefaultScriptHandler.java b/subprojects/core/src/main/java/org/gradle/api/internal/initialization/DefaultScriptHandler.java index 6c7b90bd98a09..9352462d79fcd 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/initialization/DefaultScriptHandler.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/initialization/DefaultScriptHandler.java @@ -22,6 +22,7 @@ import org.gradle.api.artifacts.dsl.DependencyHandler; import org.gradle.api.artifacts.dsl.RepositoryHandler; import org.gradle.api.attributes.Bundling; +import org.gradle.api.attributes.AttributeContainer; import org.gradle.api.attributes.Usage; import org.gradle.api.attributes.java.TargetJavaPlatform; import org.gradle.api.initialization.dsl.ScriptHandler; @@ -114,9 +115,10 @@ private void defineConfiguration() { } if (classpathConfiguration == null) { classpathConfiguration = configContainer.create(CLASSPATH_CONFIGURATION); - classpathConfiguration.getAttributes().attribute(Usage.USAGE_ATTRIBUTE, NamedObjectInstantiator.INSTANCE.named(Usage.class, Usage.JAVA_RUNTIME)); - classpathConfiguration.getAttributes().attribute(Bundling.BUNDLING_ATTRIBUTE, NamedObjectInstantiator.INSTANCE.named(Bundling.class, Bundling.EXTERNAL)); - classpathConfiguration.getAttributes().attribute(TargetJavaPlatform.MINIMAL_TARGET_PLATFORM_ATTRIBUTE, Integer.valueOf(JavaVersion.current().getMajorVersion())); + AttributeContainer attributes = classpathConfiguration.getAttributes(); + attributes.attribute(Usage.USAGE_ATTRIBUTE, NamedObjectInstantiator.INSTANCE.named(Usage.class, Usage.JAVA_RUNTIME)); + attributes.attribute(Bundling.BUNDLING_ATTRIBUTE, NamedObjectInstantiator.INSTANCE.named(Bundling.class, Bundling.EXTERNAL)); + attributes.attribute(TargetJavaPlatform.TARGET_PLATFORM_ATTRIBUTE, Integer.valueOf(JavaVersion.current().getMajorVersion())); } } diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/artifacts/TargetJavaPlatformRulesTest.groovy b/subprojects/core/src/test/groovy/org/gradle/api/internal/artifacts/TargetJavaPlatformRulesTest.groovy index 2d5f7f089bd11..112a7c26554c2 100644 --- a/subprojects/core/src/test/groovy/org/gradle/api/internal/artifacts/TargetJavaPlatformRulesTest.groovy +++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/artifacts/TargetJavaPlatformRulesTest.groovy @@ -36,8 +36,8 @@ class TargetJavaPlatformRulesTest extends Specification { def setup() { AttributesSchema schema = new DefaultAttributesSchema(Stub(ComponentAttributeMatcher), TestUtil.instantiatorFactory(), SnapshotTestUtil.valueSnapshotter()) JavaEcosystemSupport.configureSchema(schema, TestUtil.objectFactory()) - compatibilityRules = schema.compatibilityRules(TargetJavaPlatform.MINIMAL_TARGET_PLATFORM_ATTRIBUTE) - disambiguationRules = schema.disambiguationRules(TargetJavaPlatform.MINIMAL_TARGET_PLATFORM_ATTRIBUTE) + compatibilityRules = schema.compatibilityRules(TargetJavaPlatform.TARGET_PLATFORM_ATTRIBUTE) + disambiguationRules = schema.disambiguationRules(TargetJavaPlatform.TARGET_PLATFORM_ATTRIBUTE) } @Unroll("compatibility consumer=#consumer producer=#producer compatible=#compatible") diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/initialization/DefaultScriptHandlerTest.groovy b/subprojects/core/src/test/groovy/org/gradle/api/internal/initialization/DefaultScriptHandlerTest.groovy index fe5f0ef5fcb3a..f8d3d700fca6a 100644 --- a/subprojects/core/src/test/groovy/org/gradle/api/internal/initialization/DefaultScriptHandlerTest.groovy +++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/initialization/DefaultScriptHandlerTest.groovy @@ -22,6 +22,7 @@ import org.gradle.api.artifacts.dsl.RepositoryHandler import org.gradle.api.attributes.AttributesSchema import org.gradle.api.attributes.Bundling import org.gradle.api.attributes.Usage +import org.gradle.api.attributes.java.TargetJavaPlatform import org.gradle.api.internal.artifacts.DependencyResolutionServices import org.gradle.api.internal.attributes.AttributeContainerInternal import org.gradle.groovy.scripts.ScriptSource @@ -54,9 +55,10 @@ class DefaultScriptHandlerTest extends Specification { then: 1 * depMgmtServices.configurationContainer >> configurationContainer 1 * configurationContainer.create('classpath') >> configuration - 2 * configuration.attributes >> attributes + 1 * configuration.attributes >> attributes 1 * attributes.attribute(Usage.USAGE_ATTRIBUTE, _ as Usage) 1 * attributes.attribute(Bundling.BUNDLING_ATTRIBUTE, _ as Bundling) + 1 * attributes.attribute(TargetJavaPlatform.TARGET_PLATFORM_ATTRIBUTE, _) 0 * configurationContainer._ 0 * depMgmtServices._ } @@ -69,9 +71,10 @@ class DefaultScriptHandlerTest extends Specification { then: 1 * depMgmtServices.configurationContainer >> configurationContainer 1 * configurationContainer.create('classpath') >> configuration - 2 * configuration.attributes >> attributes + 1 * configuration.attributes >> attributes 1 * attributes.attribute(Usage.USAGE_ATTRIBUTE, _ as Usage) 1 * attributes.attribute(Bundling.BUNDLING_ATTRIBUTE, _ as Bundling) + 1 * attributes.attribute(TargetJavaPlatform.TARGET_PLATFORM_ATTRIBUTE, _) 1 * depMgmtServices.dependencyHandler >> dependencyHandler 0 * configurationContainer._ 0 * depMgmtServices._ @@ -102,8 +105,9 @@ class DefaultScriptHandlerTest extends Specification { and: 1 * depMgmtServices.configurationContainer >> configurationContainer 1 * configurationContainer.create('classpath') >> configuration - 2 * configuration.attributes >> attributes + 1 * configuration.attributes >> attributes 1 * attributes.attribute(Usage.USAGE_ATTRIBUTE, _ as Usage) + 1 * attributes.attribute(TargetJavaPlatform.TARGET_PLATFORM_ATTRIBUTE, _) 1 * attributes.attribute(Bundling.BUNDLING_ATTRIBUTE, _ as Bundling) 1 * classpathResolver.resolveClassPath(configuration) >> classpath } @@ -132,8 +136,9 @@ class DefaultScriptHandlerTest extends Specification { 1 * depMgmtServices.dependencyHandler >> dependencyHandler 1 * depMgmtServices.configurationContainer >> configurationContainer 1 * configurationContainer.create('classpath') >> configuration - 2 * configuration.attributes >> attributes + 1 * configuration.attributes >> attributes 1 * attributes.attribute(Usage.USAGE_ATTRIBUTE, _ as Usage) + 1 * attributes.attribute(TargetJavaPlatform.TARGET_PLATFORM_ATTRIBUTE, _) 1 * attributes.attribute(Bundling.BUNDLING_ATTRIBUTE, _ as Bundling) 1 * dependencyHandler.add('config', 'dep') } diff --git a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/attributes/CrossProjectMultipleVariantSelectionIntegrationTest.groovy b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/attributes/CrossProjectMultipleVariantSelectionIntegrationTest.groovy index 1d324d4ce68ec..2be6406ddb114 100644 --- a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/attributes/CrossProjectMultipleVariantSelectionIntegrationTest.groovy +++ b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/attributes/CrossProjectMultipleVariantSelectionIntegrationTest.groovy @@ -49,7 +49,7 @@ class CrossProjectMultipleVariantSelectionIntegrationTest extends AbstractDepend attributes { attribute(Usage.USAGE_ATTRIBUTE, project.objects.named(Usage, 'java-api-jars')) attribute(Bundling.BUNDLING_ATTRIBUTE, project.objects.named(Bundling, Bundling.EXTERNAL)) - attribute(TargetJavaPlatform.MINIMAL_TARGET_PLATFORM_ATTRIBUTE, Integer.valueOf(JavaVersion.current().majorVersion)) + attribute(TargetJavaPlatform.TARGET_PLATFORM_ATTRIBUTE, Integer.valueOf(JavaVersion.current().majorVersion)) } outgoing.capability('org:lib-fixtures:1.0') } @@ -81,11 +81,11 @@ class CrossProjectMultipleVariantSelectionIntegrationTest extends AbstractDepend resolve.expectGraph { root(":", ":test:") { project(":lib", "test:lib:") { - variant "apiElements", ['org.gradle.usage':'java-api-jars', 'org.gradle.dependency.bundling':'external', 'org.gradle.java.min.platform': JavaVersion.current().majorVersion] + variant "apiElements", ['org.gradle.usage':'java-api-jars', 'org.gradle.dependency.bundling':'external', 'org.gradle.jvm.platform': JavaVersion.current().majorVersion] artifact group:'', module:'', version: '', type: '', name: 'main', noType: true } project(":lib", "test:lib:") { - variant "testFixtures", ['org.gradle.usage':'java-api-jars', 'org.gradle.dependency.bundling':'external', 'org.gradle.java.min.platform': JavaVersion.current().majorVersion] + variant "testFixtures", ['org.gradle.usage':'java-api-jars', 'org.gradle.dependency.bundling':'external', 'org.gradle.jvm.platform': JavaVersion.current().majorVersion] artifact group:'test', module:'lib', version:'unspecified', classifier: 'test-fixtures' } } @@ -104,7 +104,7 @@ class CrossProjectMultipleVariantSelectionIntegrationTest extends AbstractDepend attributes { attribute(Usage.USAGE_ATTRIBUTE, project.objects.named(Usage, 'java-api-jars')) attribute(Bundling.BUNDLING_ATTRIBUTE, project.objects.named(Bundling, Bundling.EXTERNAL)) - attribute(TargetJavaPlatform.MINIMAL_TARGET_PLATFORM_ATTRIBUTE, Integer.valueOf(JavaVersion.current().majorVersion)) + attribute(TargetJavaPlatform.TARGET_PLATFORM_ATTRIBUTE, Integer.valueOf(JavaVersion.current().majorVersion)) } outgoing.capability('test:lib:1.0') outgoing.capability('test:lib-fixtures:1.0') @@ -129,7 +129,7 @@ class CrossProjectMultipleVariantSelectionIntegrationTest extends AbstractDepend resolve.expectGraph { root(":", ":test:") { project(":lib", "test:lib:") { - variant "apiElements", ['org.gradle.usage':'java-api-jars', 'org.gradle.dependency.bundling':'external', 'org.gradle.java.min.platform': JavaVersion.current().majorVersion] + variant "apiElements", ['org.gradle.usage':'java-api-jars', 'org.gradle.dependency.bundling':'external', 'org.gradle.jvm.platform': JavaVersion.current().majorVersion] artifact group:'', module:'', version: '', type: '', name: 'main', noType: true } } diff --git a/subprojects/diagnostics/src/integTest/groovy/org/gradle/api/tasks/diagnostics/DependencyInsightReportTaskIntegrationTest.groovy b/subprojects/diagnostics/src/integTest/groovy/org/gradle/api/tasks/diagnostics/DependencyInsightReportTaskIntegrationTest.groovy index 6d056cdee62c4..84a60905bb9d2 100644 --- a/subprojects/diagnostics/src/integTest/groovy/org/gradle/api/tasks/diagnostics/DependencyInsightReportTaskIntegrationTest.groovy +++ b/subprojects/diagnostics/src/integTest/groovy/org/gradle/api/tasks/diagnostics/DependencyInsightReportTaskIntegrationTest.groovy @@ -1705,7 +1705,7 @@ project : variant "runtimeElements" [ org.gradle.usage = java-runtime-jars (not requested) org.gradle.dependency.bundling = external (not requested) - org.gradle.java.min.platform = ${JavaVersion.current().majorVersion} (not requested) + org.gradle.jvm.platform = ${JavaVersion.current().majorVersion} (not requested) ] project : @@ -1804,7 +1804,7 @@ project :impl variant "runtimeElements" [ org.gradle.usage = java-runtime-jars (not requested) org.gradle.dependency.bundling = external (not requested) - org.gradle.java.min.platform = ${JavaVersion.current().majorVersion} (not requested) + org.gradle.jvm.platform = ${JavaVersion.current().majorVersion} (not requested) ] project :impl @@ -1859,7 +1859,7 @@ org:leaf4:1.0 Requested attributes not found in the selected variant: org.gradle.dependency.bundling = external - org.gradle.java.min.platform = ${JavaVersion.current().majorVersion} + org.gradle.jvm.platform = ${JavaVersion.current().majorVersion} ] org:leaf4:1.0 @@ -1897,7 +1897,7 @@ org:leaf1:1.0 Requested attributes not found in the selected variant: org.gradle.dependency.bundling = external - org.gradle.java.min.platform = ${JavaVersion.current().majorVersion} + org.gradle.jvm.platform = ${JavaVersion.current().majorVersion} ] org:leaf1:1.0 @@ -1917,7 +1917,7 @@ org:leaf2:1.0 Requested attributes not found in the selected variant: org.gradle.dependency.bundling = external - org.gradle.java.min.platform = ${JavaVersion.current().majorVersion} + org.gradle.jvm.platform = ${JavaVersion.current().majorVersion} ] org:leaf2:1.0 @@ -1974,7 +1974,7 @@ project :api variant "apiElements" [ org.gradle.usage = java-api-jars (compatible with: java-api) org.gradle.dependency.bundling = external - org.gradle.java.min.platform = ${JavaVersion.current().majorVersion} + org.gradle.jvm.platform = ${JavaVersion.current().majorVersion} ] project :api @@ -1991,7 +1991,7 @@ project :some:deeply:nested variant "apiElements" [ org.gradle.usage = java-api-jars (compatible with: java-api) org.gradle.dependency.bundling = external - org.gradle.java.min.platform = ${JavaVersion.current().majorVersion} + org.gradle.jvm.platform = ${JavaVersion.current().majorVersion} ] project :some:deeply:nested @@ -2007,7 +2007,7 @@ project :some:deeply:nested variant "apiElements" [ org.gradle.usage = java-api-jars (compatible with: java-api) org.gradle.dependency.bundling = external - org.gradle.java.min.platform = ${JavaVersion.current().majorVersion} + org.gradle.jvm.platform = ${JavaVersion.current().majorVersion} ] project :some:deeply:nested @@ -2061,7 +2061,7 @@ org:leaf3:1.0 Requested attributes not found in the selected variant: org.gradle.dependency.bundling = external - org.gradle.java.min.platform = ${JavaVersion.current().majorVersion} + org.gradle.jvm.platform = ${JavaVersion.current().majorVersion} ] org:leaf3:1.0 @@ -2165,7 +2165,7 @@ foo:foo:1.0 Requested attributes not found in the selected variant: org.gradle.dependency.bundling = external - org.gradle.java.min.platform = ${JavaVersion.current().majorVersion} + org.gradle.jvm.platform = ${JavaVersion.current().majorVersion} ] Selection reasons: - By constraint : $rejected @@ -2221,7 +2221,7 @@ org:foo -> $selected Requested attributes not found in the selected variant: org.gradle.dependency.bundling = external - org.gradle.java.min.platform = ${JavaVersion.current().majorVersion} + org.gradle.jvm.platform = ${JavaVersion.current().majorVersion} ] Selection reasons: - By constraint : ${rejected}${reason} @@ -2274,7 +2274,7 @@ org:foo -> $selected Requested attributes not found in the selected variant: org.gradle.dependency.bundling = external - org.gradle.java.min.platform = ${JavaVersion.current().majorVersion} + org.gradle.jvm.platform = ${JavaVersion.current().majorVersion} ] Selection reasons: - Was requested : ${rejected}${reason} @@ -2324,7 +2324,7 @@ org:foo:${displayVersion} -> $selected Requested attributes not found in the selected variant: org.gradle.dependency.bundling = external - org.gradle.java.min.platform = ${JavaVersion.current().majorVersion} + org.gradle.jvm.platform = ${JavaVersion.current().majorVersion} ] Selection reasons: - Was requested : didn't match versions 2.0, 1.5, 1.4 @@ -2380,7 +2380,7 @@ org:foo:[1.1,1.3] -> 1.3 Requested attributes not found in the selected variant: org.gradle.dependency.bundling = external - org.gradle.java.min.platform = ${JavaVersion.current().majorVersion} + org.gradle.jvm.platform = ${JavaVersion.current().majorVersion} ] Selection reasons: - Was requested : rejected versions 1.2, 1.1 @@ -2396,7 +2396,7 @@ org:foo:1.1 Requested attributes not found in the selected variant: org.gradle.dependency.bundling = external - org.gradle.java.min.platform = ${JavaVersion.current().majorVersion} + org.gradle.jvm.platform = ${JavaVersion.current().majorVersion} ] Selection reasons: - Was requested : rejected version 1.2 @@ -2456,7 +2456,7 @@ org:bar:1.0 Requested attributes not found in the selected variant: org.gradle.dependency.bundling = external - org.gradle.java.min.platform = ${JavaVersion.current().majorVersion} + org.gradle.jvm.platform = ${JavaVersion.current().majorVersion} ] Selection reasons: - Rejection : 1.2 by rule because version 1.2 is bad @@ -2473,7 +2473,7 @@ org:foo:1.1 Requested attributes not found in the selected variant: org.gradle.dependency.bundling = external - org.gradle.java.min.platform = ${JavaVersion.current().majorVersion} + org.gradle.jvm.platform = ${JavaVersion.current().majorVersion} ] Selection reasons: - Was requested : rejected version 1.2 @@ -2518,7 +2518,7 @@ org:leaf:1.0 (by constraint) Requested attributes not found in the selected variant: org.gradle.dependency.bundling = external - org.gradle.java.min.platform = ${JavaVersion.current().majorVersion} + org.gradle.jvm.platform = ${JavaVersion.current().majorVersion} ] org:leaf:1.0 @@ -2571,7 +2571,7 @@ org.test:leaf:1.0 Requested attributes not found in the selected variant: org.gradle.dependency.bundling = external - org.gradle.java.min.platform = ${JavaVersion.current().majorVersion} + org.gradle.jvm.platform = ${JavaVersion.current().majorVersion} ] Selection reasons: - Was requested : first reason @@ -2753,7 +2753,7 @@ org:foo:1.0 Requested attributes not found in the selected variant: org.gradle.dependency.bundling = external - org.gradle.java.min.platform = ${JavaVersion.current().majorVersion} + org.gradle.jvm.platform = ${JavaVersion.current().majorVersion} ] Selection reasons: - Was requested : rejected versions 1.2, 1.1 @@ -2810,7 +2810,7 @@ org:foo:{require [1.0,); reject 1.1} -> 1.0 Requested attributes not found in the selected variant: org.gradle.dependency.bundling = external - org.gradle.java.min.platform = ${JavaVersion.current().majorVersion} + org.gradle.jvm.platform = ${JavaVersion.current().majorVersion} ] Selection reasons: - Was requested : first reason @@ -2876,18 +2876,18 @@ org:foo:1.0 Requested attributes not found in the selected variant: org.gradle.dependency.bundling = external - org.gradle.java.min.platform = ${JavaVersion.current().majorVersion} + org.gradle.jvm.platform = ${JavaVersion.current().majorVersion} ] Selection reasons: - Rejection : version 1.2: - Attribute 'color' didn't match. Requested 'blue', was: 'red' - Attribute 'org.gradle.dependency.bundling' didn't match. Requested 'external', was: not found - - Attribute 'org.gradle.java.min.platform' didn't match. Requested '${JavaVersion.current().majorVersion}', was: not found + - Attribute 'org.gradle.jvm.platform' didn't match. Requested '${JavaVersion.current().majorVersion}', was: not found - Attribute 'org.gradle.usage' didn't match. Requested 'java-api', was: not found - Rejection : version 1.1: - Attribute 'color' didn't match. Requested 'blue', was: 'green' - Attribute 'org.gradle.dependency.bundling' didn't match. Requested 'external', was: not found - - Attribute 'org.gradle.java.min.platform' didn't match. Requested '${JavaVersion.current().majorVersion}', was: not found + - Attribute 'org.gradle.jvm.platform' didn't match. Requested '${JavaVersion.current().majorVersion}', was: not found - Attribute 'org.gradle.usage' didn't match. Requested 'java-api', was: not found org:foo:[1.0,) -> 1.0 @@ -2951,7 +2951,7 @@ planet:mercury:1.0.2 Requested attributes not found in the selected variant: org.gradle.dependency.bundling = external - org.gradle.java.min.platform = ${JavaVersion.current().majorVersion} + org.gradle.jvm.platform = ${JavaVersion.current().majorVersion} ] Selection reasons: - By conflict resolution : between versions 1.0.2 and 1.0.1 @@ -2982,7 +2982,7 @@ planet:venus:2.0.1 Requested attributes not found in the selected variant: org.gradle.dependency.bundling = external - org.gradle.java.min.platform = ${JavaVersion.current().majorVersion} + org.gradle.jvm.platform = ${JavaVersion.current().majorVersion} ] Selection reasons: - By conflict resolution : between versions 2.0.0, 2.0.1 and 1.0 @@ -3013,7 +3013,7 @@ planet:pluto:1.0.0 Requested attributes not found in the selected variant: org.gradle.dependency.bundling = external - org.gradle.java.min.platform = ${JavaVersion.current().majorVersion} + org.gradle.jvm.platform = ${JavaVersion.current().majorVersion} ] planet:pluto:1.0.0 diff --git a/subprojects/diagnostics/src/integTest/groovy/org/gradle/api/tasks/diagnostics/DependencyInsightReportVariantDetailsIntegrationTest.groovy b/subprojects/diagnostics/src/integTest/groovy/org/gradle/api/tasks/diagnostics/DependencyInsightReportVariantDetailsIntegrationTest.groovy index 1e340df9d5eb4..5363e1d00c6fd 100644 --- a/subprojects/diagnostics/src/integTest/groovy/org/gradle/api/tasks/diagnostics/DependencyInsightReportVariantDetailsIntegrationTest.groovy +++ b/subprojects/diagnostics/src/integTest/groovy/org/gradle/api/tasks/diagnostics/DependencyInsightReportVariantDetailsIntegrationTest.groovy @@ -57,7 +57,7 @@ class DependencyInsightReportVariantDetailsIntegrationTest extends AbstractInteg variant "$expectedVariant" [ $expectedAttributes org.gradle.dependency.bundling = external (not requested) - org.gradle.java.min.platform = ${JavaVersion.current().majorVersion} + org.gradle.jvm.platform = ${JavaVersion.current().majorVersion} ] project :$expectedProject @@ -108,8 +108,9 @@ project :$expectedProject org.gradle.status = release (not requested) Requested attributes not found in the selected variant: + org.gradle.blah = something org.gradle.dependency.bundling = external - org.gradle.java.min.platform = ${JavaVersion.current().majorVersion} + org.gradle.jvm.platform = ${JavaVersion.current().majorVersion} ] org.test:leaf:1.0 diff --git a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/ivy/IvyJavaModule.groovy b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/ivy/IvyJavaModule.groovy index c2030e9e033cf..fcbad596c6251 100644 --- a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/ivy/IvyJavaModule.groovy +++ b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/ivy/IvyJavaModule.groovy @@ -30,7 +30,7 @@ class IvyJavaModule extends DelegatingIvyModule implements Publis IvyJavaModule(IvyFileModule backingModule) { super(backingModule) this.backingModule = backingModule - this.backingModule.attributes[TargetJavaPlatform.MINIMAL_TARGET_PLATFORM_ATTRIBUTE.name] = JavaVersion.current().majorVersion + this.backingModule.attributes[TargetJavaPlatform.TARGET_PLATFORM_ATTRIBUTE.name] = JavaVersion.current().majorVersion } @Override diff --git a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/maven/MavenJavaModule.groovy b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/maven/MavenJavaModule.groovy index be7151317a08c..701228d29b8f1 100644 --- a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/maven/MavenJavaModule.groovy +++ b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/maven/MavenJavaModule.groovy @@ -29,7 +29,7 @@ class MavenJavaModule extends DelegatingMavenModule implements MavenJavaModule(MavenFileModule mavenModule) { super(mavenModule) this.mavenModule = mavenModule - this.mavenModule.attributes[TargetJavaPlatform.MINIMAL_TARGET_PLATFORM_ATTRIBUTE.name] = JavaVersion.current().majorVersion + this.mavenModule.attributes[TargetJavaPlatform.TARGET_PLATFORM_ATTRIBUTE.name] = JavaVersion.current().majorVersion } @Override @@ -61,9 +61,9 @@ class MavenJavaModule extends DelegatingMavenModule implements // Verify it contains some expected attributes assert apiElements.attributes.containsKey(Bundling.BUNDLING_ATTRIBUTE.name) - assert apiElements.attributes.containsKey(TargetJavaPlatform.MINIMAL_TARGET_PLATFORM_ATTRIBUTE.name) + assert apiElements.attributes.containsKey(TargetJavaPlatform.TARGET_PLATFORM_ATTRIBUTE.name) assert runtimeElements.attributes.containsKey(Bundling.BUNDLING_ATTRIBUTE.name) - assert runtimeElements.attributes.containsKey(TargetJavaPlatform.MINIMAL_TARGET_PLATFORM_ATTRIBUTE.name) + assert runtimeElements.attributes.containsKey(TargetJavaPlatform.TARGET_PLATFORM_ATTRIBUTE.name) // Verify POM particulars assert mavenModule.parsedPom.packaging == null diff --git a/subprojects/plugins/src/integTest/groovy/org/gradle/java/JavaApplicationOutgoingVariantsIntegrationTest.groovy b/subprojects/plugins/src/integTest/groovy/org/gradle/java/JavaApplicationOutgoingVariantsIntegrationTest.groovy index aada3a4458a1b..69492b7165577 100644 --- a/subprojects/plugins/src/integTest/groovy/org/gradle/java/JavaApplicationOutgoingVariantsIntegrationTest.groovy +++ b/subprojects/plugins/src/integTest/groovy/org/gradle/java/JavaApplicationOutgoingVariantsIntegrationTest.groovy @@ -283,6 +283,6 @@ project(':consumer') { } static String defaultTargetPlatform() { - "org.gradle.java.min.platform=${JavaVersion.current().majorVersion}" + "org.gradle.jvm.platform=${JavaVersion.current().majorVersion}" } } diff --git a/subprojects/plugins/src/integTest/groovy/org/gradle/java/JavaLibraryCrossProjectTargetPlatformIntegrationTest.groovy b/subprojects/plugins/src/integTest/groovy/org/gradle/java/JavaLibraryCrossProjectTargetPlatformIntegrationTest.groovy index 2fb13ce765a00..be2d0bc15b0fc 100644 --- a/subprojects/plugins/src/integTest/groovy/org/gradle/java/JavaLibraryCrossProjectTargetPlatformIntegrationTest.groovy +++ b/subprojects/plugins/src/integTest/groovy/org/gradle/java/JavaLibraryCrossProjectTargetPlatformIntegrationTest.groovy @@ -49,7 +49,7 @@ class JavaLibraryCrossProjectTargetPlatformIntegrationTest extends AbstractInteg } """ buildFile << """ - configurations.compileClasspath.attributes.attribute(TargetJavaPlatform.MINIMAL_TARGET_PLATFORM_ATTRIBUTE, 6) + configurations.compileClasspath.attributes.attribute(TargetJavaPlatform.TARGET_PLATFORM_ATTRIBUTE, 6) """ when: @@ -59,11 +59,11 @@ class JavaLibraryCrossProjectTargetPlatformIntegrationTest extends AbstractInteg failure.assertHasCause('''Unable to find a matching variant of project :producer: - Variant 'apiElements' capability test:producer:unspecified: - Found org.gradle.dependency.bundling 'external' but wasn't required. - - Required org.gradle.java.min.platform '6' and found incompatible value '7'. + - Required org.gradle.jvm.platform '6' and found incompatible value '7'. - Required org.gradle.usage 'java-api' and found compatible value 'java-api-jars'. - Variant 'runtimeElements' capability test:producer:unspecified: - Found org.gradle.dependency.bundling 'external' but wasn't required. - - Required org.gradle.java.min.platform '6' and found incompatible value '7'. + - Required org.gradle.jvm.platform '6' and found incompatible value '7'. - Required org.gradle.usage 'java-api' and found compatible value 'java-runtime-jars'.''') } @@ -71,7 +71,7 @@ class JavaLibraryCrossProjectTargetPlatformIntegrationTest extends AbstractInteg def "can select the most appropriate producer variant (#expected) based on target compatibility (#requested)"() { file('producer/build.gradle') << """ // avoid test noise so that typically version 8 is not selected when running on JDK 8 - configurations.apiElements.attributes.attribute(TargetJavaPlatform.MINIMAL_TARGET_PLATFORM_ATTRIBUTE, 1000) + configurations.apiElements.attributes.attribute(TargetJavaPlatform.TARGET_PLATFORM_ATTRIBUTE, 1000) [6, 7, 9].each { v -> configurations { @@ -81,7 +81,7 @@ class JavaLibraryCrossProjectTargetPlatformIntegrationTest extends AbstractInteg attributes { attribute(Usage.USAGE_ATTRIBUTE, objects.named(Usage, 'java-api-jars')) attribute(Bundling.BUNDLING_ATTRIBUTE, objects.named(Bundling, 'external')) - attribute(TargetJavaPlatform.MINIMAL_TARGET_PLATFORM_ATTRIBUTE, v) + attribute(TargetJavaPlatform.TARGET_PLATFORM_ATTRIBUTE, v) } } } @@ -91,7 +91,7 @@ class JavaLibraryCrossProjectTargetPlatformIntegrationTest extends AbstractInteg } """ buildFile << """ - configurations.compileClasspath.attributes.attribute(TargetJavaPlatform.MINIMAL_TARGET_PLATFORM_ATTRIBUTE, $requested) + configurations.compileClasspath.attributes.attribute(TargetJavaPlatform.TARGET_PLATFORM_ATTRIBUTE, $requested) """ when: @@ -103,7 +103,7 @@ class JavaLibraryCrossProjectTargetPlatformIntegrationTest extends AbstractInteg project(':producer', 'test:producer:') { variant(expected, [ 'org.gradle.dependency.bundling': 'external', - 'org.gradle.java.min.platform': selected, + 'org.gradle.jvm.platform': selected, 'org.gradle.usage':'java-api-jars' ]) artifact(classifier: "jdk${selected}") diff --git a/subprojects/plugins/src/integTest/groovy/org/gradle/java/JavaLibraryOutgoingVariantsIntegrationTest.groovy b/subprojects/plugins/src/integTest/groovy/org/gradle/java/JavaLibraryOutgoingVariantsIntegrationTest.groovy index d35223c6b6790..68ef2607a496f 100644 --- a/subprojects/plugins/src/integTest/groovy/org/gradle/java/JavaLibraryOutgoingVariantsIntegrationTest.groovy +++ b/subprojects/plugins/src/integTest/groovy/org/gradle/java/JavaLibraryOutgoingVariantsIntegrationTest.groovy @@ -284,6 +284,6 @@ project(':consumer') { } static String defaultTargetPlatform() { - "org.gradle.java.min.platform=${JavaVersion.current().majorVersion}" + "org.gradle.jvm.platform=${JavaVersion.current().majorVersion}" } } diff --git a/subprojects/plugins/src/integTest/groovy/org/gradle/java/JavaLibraryPublishedTargetPlatformIntegrationTest.groovy b/subprojects/plugins/src/integTest/groovy/org/gradle/java/JavaLibraryPublishedTargetPlatformIntegrationTest.groovy index 401f13aa21555..3e24f6a214b79 100644 --- a/subprojects/plugins/src/integTest/groovy/org/gradle/java/JavaLibraryPublishedTargetPlatformIntegrationTest.groovy +++ b/subprojects/plugins/src/integTest/groovy/org/gradle/java/JavaLibraryPublishedTargetPlatformIntegrationTest.groovy @@ -50,27 +50,27 @@ class JavaLibraryPublishedTargetPlatformIntegrationTest extends AbstractHttpDepe .adhocVariants() .variant("apiElementsJdk6", [ 'org.gradle.dependency.bundling': 'external', - 'org.gradle.java.min.platform': '6', + 'org.gradle.jvm.platform': '6', 'org.gradle.usage': 'java-api-jars'], { artifact('producer-1.0-jdk6.jar') }) .variant("apiElementsJdk7", [ 'org.gradle.dependency.bundling': 'external', - 'org.gradle.java.min.platform': '7', + 'org.gradle.jvm.platform': '7', 'org.gradle.usage': 'java-api-jars'], { artifact('producer-1.0-jdk7.jar') }) .variant("apiElementsJdk9", [ 'org.gradle.dependency.bundling': 'external', - 'org.gradle.java.min.platform': '9', + 'org.gradle.jvm.platform': '9', 'org.gradle.usage': 'java-api-jars'], { artifact('producer-1.0-jdk9.jar') }) .variant("runtimeElementsJdk6", [ 'org.gradle.dependency.bundling': 'external', - 'org.gradle.java.min.platform': '6', + 'org.gradle.jvm.platform': '6', 'org.gradle.usage': 'java-runtime-jars'], { artifact('producer-1.0-jdk6.jar') }) .variant("runtimeElementsJdk7", [ 'org.gradle.dependency.bundling': 'external', - 'org.gradle.java.min.platform': '7', + 'org.gradle.jvm.platform': '7', 'org.gradle.usage': 'java-runtime-jars'], { artifact('producer-1.0-jdk7.jar') }) .variant("runtimeElementsJdk9", [ 'org.gradle.dependency.bundling': 'external', - 'org.gradle.java.min.platform': '9', + 'org.gradle.jvm.platform': '9', 'org.gradle.usage': 'java-runtime-jars'], { artifact('producer-1.0-jdk9.jar') }) .publish() @@ -78,7 +78,7 @@ class JavaLibraryPublishedTargetPlatformIntegrationTest extends AbstractHttpDepe def "can fail resolution if producer doesn't have appropriate target version"() { buildFile << """ - configurations.compileClasspath.attributes.attribute(TargetJavaPlatform.MINIMAL_TARGET_PLATFORM_ATTRIBUTE, 5) + configurations.compileClasspath.attributes.attribute(TargetJavaPlatform.TARGET_PLATFORM_ATTRIBUTE, 5) """ when: @@ -91,17 +91,17 @@ class JavaLibraryPublishedTargetPlatformIntegrationTest extends AbstractHttpDepe failure.assertHasCause('''Unable to find a matching variant of org:producer:1.0: - Variant 'apiElementsJdk6' capability org:producer:1.0: - Found org.gradle.dependency.bundling 'external' but wasn't required. - - Required org.gradle.java.min.platform '5' and found incompatible value '6'. + - Required org.gradle.jvm.platform '5' and found incompatible value '6'. - Found org.gradle.status 'release' but wasn't required. - Required org.gradle.usage 'java-api' and found compatible value 'java-api-jars'. - Variant 'apiElementsJdk7' capability org:producer:1.0: - Found org.gradle.dependency.bundling 'external' but wasn't required. - - Required org.gradle.java.min.platform '5' and found incompatible value '7'. + - Required org.gradle.jvm.platform '5' and found incompatible value '7'. - Found org.gradle.status 'release' but wasn't required. - Required org.gradle.usage 'java-api' and found compatible value 'java-api-jars'. - Variant 'apiElementsJdk9' capability org:producer:1.0: - Found org.gradle.dependency.bundling 'external' but wasn't required. - - Required org.gradle.java.min.platform '5' and found incompatible value '9'. + - Required org.gradle.jvm.platform '5' and found incompatible value '9'. - Found org.gradle.status 'release' but wasn't required. - Required org.gradle.usage 'java-api' and found compatible value 'java-api-jars'.''') } @@ -109,7 +109,7 @@ class JavaLibraryPublishedTargetPlatformIntegrationTest extends AbstractHttpDepe @Unroll def "can select the most appropriate producer variant (#expected) based on target compatibility (#requested)"() { buildFile << """ - configurations.compileClasspath.attributes.attribute(TargetJavaPlatform.MINIMAL_TARGET_PLATFORM_ATTRIBUTE, $requested) + configurations.compileClasspath.attributes.attribute(TargetJavaPlatform.TARGET_PLATFORM_ATTRIBUTE, $requested) """ when: @@ -125,7 +125,7 @@ class JavaLibraryPublishedTargetPlatformIntegrationTest extends AbstractHttpDepe module('org:producer:1.0') { variant(expected, [ 'org.gradle.dependency.bundling': 'external', - 'org.gradle.java.min.platform': selected, + 'org.gradle.jvm.platform': selected, 'org.gradle.usage': 'java-api-jars', 'org.gradle.status': 'release' ]) diff --git a/subprojects/plugins/src/integTest/groovy/org/gradle/java/JavaProjectOutgoingVariantsIntegrationTest.groovy b/subprojects/plugins/src/integTest/groovy/org/gradle/java/JavaProjectOutgoingVariantsIntegrationTest.groovy index 012fee166fc93..3cf0f70911946 100644 --- a/subprojects/plugins/src/integTest/groovy/org/gradle/java/JavaProjectOutgoingVariantsIntegrationTest.groovy +++ b/subprojects/plugins/src/integTest/groovy/org/gradle/java/JavaProjectOutgoingVariantsIntegrationTest.groovy @@ -282,6 +282,6 @@ project(':consumer') { } static String defaultTargetPlatform() { - "org.gradle.java.min.platform=${JavaVersion.current().majorVersion}" + "org.gradle.jvm.platform=${JavaVersion.current().majorVersion}" } } diff --git a/subprojects/plugins/src/main/java/org/gradle/api/plugins/internal/DefaultJavaFeatureSpec.java b/subprojects/plugins/src/main/java/org/gradle/api/plugins/internal/DefaultJavaFeatureSpec.java index bbdeaf1c92068..665225519c328 100644 --- a/subprojects/plugins/src/main/java/org/gradle/api/plugins/internal/DefaultJavaFeatureSpec.java +++ b/subprojects/plugins/src/main/java/org/gradle/api/plugins/internal/DefaultJavaFeatureSpec.java @@ -166,8 +166,8 @@ public void execute(ConfigurationInternal configuration) { String majorVersion = javaPluginConvention.getTargetCompatibility().getMajorVersion(); AttributeContainerInternal attributes = configuration.getAttributes(); // If nobody said anything about this variant's target platform, use whatever the convention says - if (!attributes.contains(TargetJavaPlatform.MINIMAL_TARGET_PLATFORM_ATTRIBUTE)) { - attributes.attribute(TargetJavaPlatform.MINIMAL_TARGET_PLATFORM_ATTRIBUTE, Integer.valueOf(majorVersion)); + if (!attributes.contains(TargetJavaPlatform.TARGET_PLATFORM_ATTRIBUTE)) { + attributes.attribute(TargetJavaPlatform.TARGET_PLATFORM_ATTRIBUTE, Integer.valueOf(majorVersion)); } } }); From 91304c4f645406febb221a29e17f6361cfe4584f Mon Sep 17 00:00:00 2001 From: Cedric Champeau Date: Wed, 20 Feb 2019 16:07:36 +0100 Subject: [PATCH 057/853] Fix userguide sample output --- .../runtimeClasspath.out | 3 ++ .../requiring-features/runtimeClasspath.out | 7 +++-- .../dependencyReasonReport.out | 1 + .../dependencyReport.out | 1 + .../UserGuideSamplesIntegrationTest.groovy | 14 +++++---- ...tResolutionOmittingOutputNormalizer.groovy | 5 ++-- .../DependencyInsightOutputNormalizer.groovy | 30 +++++++++++++++++++ .../logging/SampleOutputNormalizer.groovy | 2 ++ 8 files changed, 52 insertions(+), 11 deletions(-) create mode 100644 subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/logging/DependencyInsightOutputNormalizer.groovy diff --git a/subprojects/docs/src/samples/java-feature-variant/requiring-features-external/runtimeClasspath.out b/subprojects/docs/src/samples/java-feature-variant/requiring-features-external/runtimeClasspath.out index b20fa74b5cdfd..273eb3ec0686b 100644 --- a/subprojects/docs/src/samples/java-feature-variant/requiring-features-external/runtimeClasspath.out +++ b/subprojects/docs/src/samples/java-feature-variant/requiring-features-external/runtimeClasspath.out @@ -8,6 +8,7 @@ org.mongodb:bson:3.9.1 Requested attributes not found in the selected variant: org.gradle.dependency.bundling = external + org.gradle.jvm.platform = 11 ] org.mongodb:bson:3.9.1 @@ -25,6 +26,7 @@ org.mongodb:mongodb-driver-core:3.9.1 Requested attributes not found in the selected variant: org.gradle.dependency.bundling = external + org.gradle.jvm.platform = 11 ] org.mongodb:mongodb-driver-core:3.9.1 @@ -40,6 +42,7 @@ org.mongodb:mongodb-driver-sync:3.9.1 Requested attributes not found in the selected variant: org.gradle.dependency.bundling = external + org.gradle.jvm.platform = 11 ] org.mongodb:mongodb-driver-sync:3.9.1 diff --git a/subprojects/docs/src/samples/java-feature-variant/requiring-features/runtimeClasspath.out b/subprojects/docs/src/samples/java-feature-variant/requiring-features/runtimeClasspath.out index 4bd3c76e624ec..1a281143552af 100644 --- a/subprojects/docs/src/samples/java-feature-variant/requiring-features/runtimeClasspath.out +++ b/subprojects/docs/src/samples/java-feature-variant/requiring-features/runtimeClasspath.out @@ -2,11 +2,12 @@ > Task :consumer:dependencyInsight mysql:mysql-connector-java:8.0.14 variant "runtime" [ - org.gradle.status = release (not requested) - org.gradle.usage = java-runtime - org.gradle.component.category = library (not requested) + org.gradle.status = release (not requested) + org.gradle.usage = java-runtime + org.gradle.component.category = library (not requested) Requested attributes not found in the selected variant: + org.gradle.jvm.platform = 11 org.gradle.dependency.bundling = external ] diff --git a/subprojects/docs/src/samples/userguide/dependencyManagement/inspectingDependencies/dependencyReason/dependencyReasonReport.out b/subprojects/docs/src/samples/userguide/dependencyManagement/inspectingDependencies/dependencyReason/dependencyReasonReport.out index e39172615c03f..da5df886664cc 100644 --- a/subprojects/docs/src/samples/userguide/dependencyManagement/inspectingDependencies/dependencyReason/dependencyReasonReport.out +++ b/subprojects/docs/src/samples/userguide/dependencyManagement/inspectingDependencies/dependencyReason/dependencyReasonReport.out @@ -6,6 +6,7 @@ org.ow2.asm:asm:6.0 Requested attributes not found in the selected variant: org.gradle.dependency.bundling = external + org.gradle.jvm.platform = 11 ] Selection reasons: - Was requested : we require a JDK 9 compatible bytecode generator diff --git a/subprojects/docs/src/samples/userguide/dependencyManagement/managingTransitiveDependencies/declaringCapabilities/dependencyReport.out b/subprojects/docs/src/samples/userguide/dependencyManagement/managingTransitiveDependencies/declaringCapabilities/dependencyReport.out index 53282e4a219c8..1ecf036e07814 100644 --- a/subprojects/docs/src/samples/userguide/dependencyManagement/managingTransitiveDependencies/declaringCapabilities/dependencyReport.out +++ b/subprojects/docs/src/samples/userguide/dependencyManagement/managingTransitiveDependencies/declaringCapabilities/dependencyReport.out @@ -25,6 +25,7 @@ org.slf4j:slf4j-log4j12:1.6.1 Requested attributes not found in the selected variant: org.gradle.dependency.bundling = external + org.gradle.jvm.platform = 11 ] org.slf4j:slf4j-log4j12:1.6.1 diff --git a/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/samples/UserGuideSamplesIntegrationTest.groovy b/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/samples/UserGuideSamplesIntegrationTest.groovy index 85b3fa366d260..4c7a3dd50bd38 100644 --- a/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/samples/UserGuideSamplesIntegrationTest.groovy +++ b/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/samples/UserGuideSamplesIntegrationTest.groovy @@ -20,6 +20,7 @@ import org.gradle.cache.internal.DefaultGeneratedGradleJarCache import org.gradle.integtests.fixtures.executer.IntegrationTestBuildContext import org.gradle.integtests.fixtures.executer.MoreMemorySampleModifier import org.gradle.integtests.fixtures.logging.ArtifactResolutionOmittingOutputNormalizer +import org.gradle.integtests.fixtures.logging.DependencyInsightOutputNormalizer import org.gradle.integtests.fixtures.logging.NativeComponentReportOutputNormalizer import org.gradle.integtests.fixtures.logging.PlayComponentReportOutputNormalizer import org.gradle.integtests.fixtures.logging.SampleOutputNormalizer @@ -39,12 +40,13 @@ import org.junit.runner.RunWith @Requires(TestPrecondition.JDK8_OR_LATER) @RunWith(GradleSamplesRunner.class) @SamplesOutputNormalizers([ - JavaObjectSerializationOutputNormalizer.class, - SampleOutputNormalizer.class, - FileSeparatorOutputNormalizer.class, - ArtifactResolutionOmittingOutputNormalizer.class, - NativeComponentReportOutputNormalizer.class, - PlayComponentReportOutputNormalizer.class + JavaObjectSerializationOutputNormalizer, + SampleOutputNormalizer, + FileSeparatorOutputNormalizer, + ArtifactResolutionOmittingOutputNormalizer, + NativeComponentReportOutputNormalizer, + PlayComponentReportOutputNormalizer, + DependencyInsightOutputNormalizer ]) @SampleModifiers([SetMirrorsSampleModifier, MoreMemorySampleModifier]) class UserGuideSamplesIntegrationTest { diff --git a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/logging/ArtifactResolutionOmittingOutputNormalizer.groovy b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/logging/ArtifactResolutionOmittingOutputNormalizer.groovy index 3cdbfdf9c2f63..567767f06464e 100644 --- a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/logging/ArtifactResolutionOmittingOutputNormalizer.groovy +++ b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/logging/ArtifactResolutionOmittingOutputNormalizer.groovy @@ -15,13 +15,14 @@ */ package org.gradle.integtests.fixtures.logging +import groovy.transform.CompileStatic import org.gradle.internal.jvm.Jvm -import org.gradle.samples.test.normalizer.OutputNormalizer import org.gradle.samples.executor.ExecutionMetadata +import org.gradle.samples.test.normalizer.OutputNormalizer import javax.annotation.Nullable - +@CompileStatic class ArtifactResolutionOmittingOutputNormalizer implements OutputNormalizer { @Override String normalize(String commandOutput, @Nullable ExecutionMetadata executionMetadata) { diff --git a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/logging/DependencyInsightOutputNormalizer.groovy b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/logging/DependencyInsightOutputNormalizer.groovy new file mode 100644 index 0000000000000..cc8299778fcad --- /dev/null +++ b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/logging/DependencyInsightOutputNormalizer.groovy @@ -0,0 +1,30 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.integtests.fixtures.logging + +import groovy.transform.CompileStatic +import org.gradle.samples.executor.ExecutionMetadata +import org.gradle.samples.test.normalizer.OutputNormalizer + +@CompileStatic +class DependencyInsightOutputNormalizer implements OutputNormalizer { + + @Override + String normalize(String output, ExecutionMetadata executionMetadata) { + output.replaceAll("org\\.gradle\\.jvm\\.platform[ ]+= [0-9]+", "org.gradle.jvm.platform = 11") + } +} diff --git a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/logging/SampleOutputNormalizer.groovy b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/logging/SampleOutputNormalizer.groovy index 3db3d63b723e6..6810703f613a7 100644 --- a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/logging/SampleOutputNormalizer.groovy +++ b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/logging/SampleOutputNormalizer.groovy @@ -15,6 +15,7 @@ */ package org.gradle.integtests.fixtures.logging +import groovy.transform.CompileStatic import org.gradle.integtests.fixtures.executer.OutputScrapingExecutionResult import org.gradle.internal.logging.ConsoleRenderer import org.gradle.samples.executor.ExecutionMetadata @@ -22,6 +23,7 @@ import org.gradle.samples.test.normalizer.OutputNormalizer import java.util.regex.Pattern +@CompileStatic class SampleOutputNormalizer implements OutputNormalizer { private static final String NORMALIZED_SAMPLES_PATH = "/home/user/gradle/samples" private static final String NORMALIZED_SAMPLES_FILE_URL = "file:///home/user/gradle/samples/" From fa19ab2afedc094bc617ea85fe25794b8f623866 Mon Sep 17 00:00:00 2001 From: Cedric Champeau Date: Wed, 20 Feb 2019 22:04:30 +0100 Subject: [PATCH 058/853] Fix Eclipse project inconsistency --- .../canCreateAndDeleteMetaData/common/build.gradle | 2 +- .../expectedFiles/commonJdt.properties | 6 +++--- .../expectedFiles/commonWtpFacet.xml | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/subprojects/ide/src/integTest/resources/org/gradle/plugins/ide/eclipse/EclipseIntegrationTest/canCreateAndDeleteMetaData/common/build.gradle b/subprojects/ide/src/integTest/resources/org/gradle/plugins/ide/eclipse/EclipseIntegrationTest/canCreateAndDeleteMetaData/common/build.gradle index cdbc5a914a398..93eefc7b2af6d 100644 --- a/subprojects/ide/src/integTest/resources/org/gradle/plugins/ide/eclipse/EclipseIntegrationTest/canCreateAndDeleteMetaData/common/build.gradle +++ b/subprojects/ide/src/integTest/resources/org/gradle/plugins/ide/eclipse/EclipseIntegrationTest/canCreateAndDeleteMetaData/common/build.gradle @@ -1,6 +1,6 @@ apply plugin: 'java' -sourceCompatibility = 1.7 +sourceCompatibility = 1.6 configurations { provided diff --git a/subprojects/ide/src/integTest/resources/org/gradle/plugins/ide/eclipse/EclipseIntegrationTest/canCreateAndDeleteMetaData/expectedFiles/commonJdt.properties b/subprojects/ide/src/integTest/resources/org/gradle/plugins/ide/eclipse/EclipseIntegrationTest/canCreateAndDeleteMetaData/expectedFiles/commonJdt.properties index 7341ab1683c4f..8000cd6ca6142 100644 --- a/subprojects/ide/src/integTest/resources/org/gradle/plugins/ide/eclipse/EclipseIntegrationTest/canCreateAndDeleteMetaData/expectedFiles/commonJdt.properties +++ b/subprojects/ide/src/integTest/resources/org/gradle/plugins/ide/eclipse/EclipseIntegrationTest/canCreateAndDeleteMetaData/expectedFiles/commonJdt.properties @@ -1,11 +1,11 @@ eclipse.preferences.version=1 org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve -org.eclipse.jdt.core.compiler.compliance=1.7 +org.eclipse.jdt.core.compiler.compliance=1.6 org.eclipse.jdt.core.compiler.debug.lineNumber=generate org.eclipse.jdt.core.compiler.debug.localVariable=generate org.eclipse.jdt.core.compiler.debug.sourceFile=generate org.eclipse.jdt.core.compiler.problem.assertIdentifier=error org.eclipse.jdt.core.compiler.problem.enumIdentifier=error -org.eclipse.jdt.core.compiler.source=1.7 +org.eclipse.jdt.core.compiler.source=1.6 diff --git a/subprojects/ide/src/integTest/resources/org/gradle/plugins/ide/eclipse/EclipseIntegrationTest/canCreateAndDeleteMetaData/expectedFiles/commonWtpFacet.xml b/subprojects/ide/src/integTest/resources/org/gradle/plugins/ide/eclipse/EclipseIntegrationTest/canCreateAndDeleteMetaData/expectedFiles/commonWtpFacet.xml index b14a4dc410ccb..fbb5eacc4d7fd 100644 --- a/subprojects/ide/src/integTest/resources/org/gradle/plugins/ide/eclipse/EclipseIntegrationTest/canCreateAndDeleteMetaData/expectedFiles/commonWtpFacet.xml +++ b/subprojects/ide/src/integTest/resources/org/gradle/plugins/ide/eclipse/EclipseIntegrationTest/canCreateAndDeleteMetaData/expectedFiles/commonWtpFacet.xml @@ -1,5 +1,5 @@ - + From 46f86331f6d1409701e9443955261bb0209d3d6d Mon Sep 17 00:00:00 2001 From: Cedric Champeau Date: Wed, 20 Feb 2019 23:32:08 +0100 Subject: [PATCH 059/853] Add an opt-out to automatic target jvm setting Builds like Gradle have "incorrect" module setups: some modules built for Java 6 have dependencies on Java 8 modules. This, in general, shouldn't be allowed. However in Gradle it's "fine" because we know that when we run on Java 6, the classes which actually need Java 8 features or dependencies are not in use. --- .../UnitTestAndCompilePlugin.kt | 11 +++++ ...rojectTargetPlatformIntegrationTest.groovy | 49 +++++++++++++++++++ .../gradle/api/plugins/JavaBasePlugin.java | 4 +- .../api/plugins/JavaPluginConvention.java | 24 +++++++++ .../api/plugins/JavaPluginExtension.java | 13 +++++ .../internal/DefaultJavaPluginConvention.java | 12 +++++ .../internal/DefaultJavaPluginExtension.java | 5 ++ 7 files changed, 117 insertions(+), 1 deletion(-) diff --git a/buildSrc/subprojects/plugins/src/main/kotlin/org/gradle/gradlebuild/unittestandcompile/UnitTestAndCompilePlugin.kt b/buildSrc/subprojects/plugins/src/main/kotlin/org/gradle/gradlebuild/unittestandcompile/UnitTestAndCompilePlugin.kt index 2c11a49ea9b41..b0fb1b5d37493 100644 --- a/buildSrc/subprojects/plugins/src/main/kotlin/org/gradle/gradlebuild/unittestandcompile/UnitTestAndCompilePlugin.kt +++ b/buildSrc/subprojects/plugins/src/main/kotlin/org/gradle/gradlebuild/unittestandcompile/UnitTestAndCompilePlugin.kt @@ -26,6 +26,7 @@ import org.gradle.api.Named import org.gradle.api.Plugin import org.gradle.api.Project import org.gradle.api.internal.tasks.testing.junit.result.TestResultSerializer +import org.gradle.api.plugins.JavaPluginConvention import org.gradle.api.tasks.bundling.Jar import org.gradle.api.tasks.compile.AbstractCompile import org.gradle.api.tasks.compile.CompileOptions @@ -45,6 +46,7 @@ import java.lang.IllegalStateException import java.util.concurrent.Callable import java.util.concurrent.atomic.AtomicInteger import java.util.jar.Attributes +import kotlin.reflect.full.declaredFunctions enum class ModuleType(val compatibility: JavaVersion) { @@ -307,6 +309,7 @@ open class UnitTestAndCompileExtension(val project: Project) { field = value!! project.java.targetCompatibility = value.compatibility project.java.sourceCompatibility = value.compatibility + project.java.disableAutoTargetJvmGradle53() } init { @@ -317,3 +320,11 @@ open class UnitTestAndCompileExtension(val project: Project) { } } } + + +fun JavaPluginConvention.disableAutoTargetJvmGradle53() { + val function = JavaPluginConvention::class.declaredFunctions.find { it.name == "disableAutoTargetJvm" } + function?.also { + it.call(this) + } +} diff --git a/subprojects/plugins/src/integTest/groovy/org/gradle/java/JavaLibraryCrossProjectTargetPlatformIntegrationTest.groovy b/subprojects/plugins/src/integTest/groovy/org/gradle/java/JavaLibraryCrossProjectTargetPlatformIntegrationTest.groovy index be2d0bc15b0fc..8f3d5ec32631f 100644 --- a/subprojects/plugins/src/integTest/groovy/org/gradle/java/JavaLibraryCrossProjectTargetPlatformIntegrationTest.groovy +++ b/subprojects/plugins/src/integTest/groovy/org/gradle/java/JavaLibraryCrossProjectTargetPlatformIntegrationTest.groovy @@ -121,4 +121,53 @@ class JavaLibraryCrossProjectTargetPlatformIntegrationTest extends AbstractInteg expected = "apiElementsJdk$selected" } + + def "can disable automatic setting of target JVM attribute"() { + file("producer/build.gradle") << """ + java { + targetCompatibility = JavaVersion.VERSION_1_7 + } + """ + buildFile << """ + java { + targetCompatibility = JavaVersion.VERSION_1_6 + } + """ + + when: + fails ':checkDeps' + + then: + failure.assertHasCause("""Unable to find a matching variant of project :producer: + - Variant 'apiElements' capability test:producer:unspecified: + - Found org.gradle.dependency.bundling 'external' but wasn't required. + - Required org.gradle.jvm.platform '6' and found incompatible value '7'. + - Required org.gradle.usage 'java-api' and found compatible value 'java-api-jars'. + - Variant 'runtimeElements' capability test:producer:unspecified: + - Found org.gradle.dependency.bundling 'external' but wasn't required. + - Required org.gradle.jvm.platform '6' and found incompatible value '7'. + - Required org.gradle.usage 'java-api' and found compatible value 'java-runtime-jars'.""") + + when: + buildFile << """ + java { + disableAutoTargetJvm() + } + """ + run ':checkDeps' + + then: + resolve.expectGraph { + root(":", ":test:") { + project(':producer', 'test:producer:') { + variant("apiElements", [ + 'org.gradle.dependency.bundling': 'external', + 'org.gradle.jvm.platform': '7', + 'org.gradle.usage':'java-api-jars' + ]) + artifact group:'', module:'', version: '', type: '', name: 'main', noType: true + } + } + } + } } diff --git a/subprojects/plugins/src/main/java/org/gradle/api/plugins/JavaBasePlugin.java b/subprojects/plugins/src/main/java/org/gradle/api/plugins/JavaBasePlugin.java index 0d6adb8a14bbf..ea053c0da690d 100644 --- a/subprojects/plugins/src/main/java/org/gradle/api/plugins/JavaBasePlugin.java +++ b/subprojects/plugins/src/main/java/org/gradle/api/plugins/JavaBasePlugin.java @@ -305,7 +305,9 @@ private Action configureDefaultTargetPlatform(final JavaP return new Action() { @Override public void execute(ConfigurationInternal conf) { - JavaEcosystemSupport.configureDefaultTargetPlatform(conf, convention.getTargetCompatibility()); + if (!convention.isAutoTargetJvmDisabled()) { + JavaEcosystemSupport.configureDefaultTargetPlatform(conf, convention.getTargetCompatibility()); + } } }; } diff --git a/subprojects/plugins/src/main/java/org/gradle/api/plugins/JavaPluginConvention.java b/subprojects/plugins/src/main/java/org/gradle/api/plugins/JavaPluginConvention.java index 2e26f43c657af..3c68f3b9b179a 100644 --- a/subprojects/plugins/src/main/java/org/gradle/api/plugins/JavaPluginConvention.java +++ b/subprojects/plugins/src/main/java/org/gradle/api/plugins/JavaPluginConvention.java @@ -18,6 +18,7 @@ import groovy.lang.Closure; import org.gradle.api.Action; +import org.gradle.api.Incubating; import org.gradle.api.JavaVersion; import org.gradle.api.internal.project.ProjectInternal; import org.gradle.api.java.archives.Manifest; @@ -157,4 +158,27 @@ public abstract class JavaPluginConvention { public abstract SourceSetContainer getSourceSets(); public abstract ProjectInternal getProject(); + + /** + * If this method is called, Gradle will not automatically try to fetch + * dependencies which have a JVM version compatible with this module. + * This should be used whenever the default behavior is not + * applicable, in particular when for some reason it's not possible to split + * a module and that this module only has some classes which require dependencies + * on higher versions. + * + * @since 5.3 + */ + @Incubating + public abstract void disableAutoTargetJvm(); + + /** + * Tells if automatic JVM targetting is enabled. When disabled, Gradle + * will not automatically try to get dependencies corresponding to the + * same (or compatible) level as the target compatibility of this module. + * + * @since 5.3 + */ + @Incubating + public abstract boolean isAutoTargetJvmDisabled(); } diff --git a/subprojects/plugins/src/main/java/org/gradle/api/plugins/JavaPluginExtension.java b/subprojects/plugins/src/main/java/org/gradle/api/plugins/JavaPluginExtension.java index 6c6179ad5e6be..2f53d0ee63326 100644 --- a/subprojects/plugins/src/main/java/org/gradle/api/plugins/JavaPluginExtension.java +++ b/subprojects/plugins/src/main/java/org/gradle/api/plugins/JavaPluginExtension.java @@ -59,4 +59,17 @@ public interface JavaPluginExtension { * @since 5.3 */ void registerFeature(String name, Action configureAction); + + /** + * If this method is called, Gradle will not automatically try to fetch + * dependencies which have a JVM version compatible with the target compatibility + * of this module. This should be used whenever the default behavior is not + * applicable, in particular when for some reason it's not possible to split + * a module and that this module only has some classes which require dependencies + * on higher versions. + * + * @since 5.3 + */ + @Incubating + void disableAutoTargetJvm(); } diff --git a/subprojects/plugins/src/main/java/org/gradle/api/plugins/internal/DefaultJavaPluginConvention.java b/subprojects/plugins/src/main/java/org/gradle/api/plugins/internal/DefaultJavaPluginConvention.java index 6c561c1a4e0df..3a6366186aeb6 100644 --- a/subprojects/plugins/src/main/java/org/gradle/api/plugins/internal/DefaultJavaPluginConvention.java +++ b/subprojects/plugins/src/main/java/org/gradle/api/plugins/internal/DefaultJavaPluginConvention.java @@ -52,6 +52,8 @@ public class DefaultJavaPluginConvention extends JavaPluginConvention implements private JavaVersion srcCompat; private JavaVersion targetCompat; + private boolean autoTargetJvm = true; + public DefaultJavaPluginConvention(ProjectInternal project, ObjectFactory objectFactory) { this.project = project; sourceSets = objectFactory.newInstance(DefaultSourceSetContainer.class); @@ -179,4 +181,14 @@ public SourceSetContainer getSourceSets() { public ProjectInternal getProject() { return project; } + + @Override + public void disableAutoTargetJvm() { + this.autoTargetJvm = false; + } + + @Override + public boolean isAutoTargetJvmDisabled() { + return !autoTargetJvm; + } } diff --git a/subprojects/plugins/src/main/java/org/gradle/api/plugins/internal/DefaultJavaPluginExtension.java b/subprojects/plugins/src/main/java/org/gradle/api/plugins/internal/DefaultJavaPluginExtension.java index 7eda00231853d..28d7b2e7cc7fb 100644 --- a/subprojects/plugins/src/main/java/org/gradle/api/plugins/internal/DefaultJavaPluginExtension.java +++ b/subprojects/plugins/src/main/java/org/gradle/api/plugins/internal/DefaultJavaPluginExtension.java @@ -89,6 +89,11 @@ public void registerFeature(String name, Action configureAc spec.create(); } + @Override + public void disableAutoTargetJvm() { + convention.disableAutoTargetJvm(); + } + private static String validateFeatureName(String name) { if (!VALID_FEATURE_NAME.matcher(name).matches()) { throw new InvalidUserDataException("Invalid feature name '" + name + "'. Must match " + VALID_FEATURE_NAME.pattern()); From 62c81234d97c654c9cab477f9ec851000452ec7f Mon Sep 17 00:00:00 2001 From: Cedric Champeau Date: Thu, 21 Feb 2019 09:51:48 +0100 Subject: [PATCH 060/853] To avoid confusion, remove mention of "platform" from "target Java platform" We already have the "Java Platform" plugin which is something quite different from the concept we want to express when using "target java platform". This is more often known as the "JVM version", or "target Java version". We use "JVM" because this is not specific to Java. --- ...avaPlatform.java => TargetJvmVersion.java} | 8 +-- .../artifacts/JavaEcosystemSupport.java | 8 +-- .../initialization/DefaultScriptHandler.java | 4 +- ...roovy => TargetJvmVersionRulesTest.groovy} | 8 +-- .../DefaultScriptHandlerTest.groovy | 10 ++-- ...ipleVariantSelectionIntegrationTest.groovy | 10 ++-- ...ncyInsightReportTaskIntegrationTest.groovy | 56 +++++++++---------- ...ReportVariantDetailsIntegrationTest.groovy | 4 +- .../runtimeClasspath.out | 6 +- .../requiring-features/runtimeClasspath.out | 2 +- .../dependencyReasonReport.out | 2 +- .../dependencyReport.out | 2 +- .../DependencyInsightOutputNormalizer.groovy | 2 +- .../test/fixtures/ivy/IvyJavaModule.groovy | 4 +- .../fixtures/maven/MavenJavaModule.groovy | 8 +-- ...tionOutgoingVariantsIntegrationTest.groovy | 2 +- ...rojectTargetPlatformIntegrationTest.groovy | 20 +++---- ...raryOutgoingVariantsIntegrationTest.groovy | 2 +- ...lishedTargetPlatformIntegrationTest.groovy | 24 ++++---- ...jectOutgoingVariantsIntegrationTest.groovy | 2 +- .../gradle/api/plugins/JavaBasePlugin.java | 2 +- .../api/plugins/JavaPluginConvention.java | 2 +- .../internal/DefaultJavaFeatureSpec.java | 6 +- .../internal/DefaultJavaPluginConvention.java | 2 +- 24 files changed, 98 insertions(+), 98 deletions(-) rename subprojects/core-api/src/main/java/org/gradle/api/attributes/java/{TargetJavaPlatform.java => TargetJvmVersion.java} (70%) rename subprojects/core/src/test/groovy/org/gradle/api/internal/artifacts/{TargetJavaPlatformRulesTest.groovy => TargetJvmVersionRulesTest.groovy} (92%) diff --git a/subprojects/core-api/src/main/java/org/gradle/api/attributes/java/TargetJavaPlatform.java b/subprojects/core-api/src/main/java/org/gradle/api/attributes/java/TargetJvmVersion.java similarity index 70% rename from subprojects/core-api/src/main/java/org/gradle/api/attributes/java/TargetJavaPlatform.java rename to subprojects/core-api/src/main/java/org/gradle/api/attributes/java/TargetJvmVersion.java index 54f13e81e6748..c3403146756c2 100644 --- a/subprojects/core-api/src/main/java/org/gradle/api/attributes/java/TargetJavaPlatform.java +++ b/subprojects/core-api/src/main/java/org/gradle/api/attributes/java/TargetJvmVersion.java @@ -19,16 +19,16 @@ import org.gradle.api.attributes.Attribute; /** - * Represents the target platform of a Java library or platform. The target level is expected to correspond + * Represents the target version of a Java library or platform. The target level is expected to correspond * to a Java platform version number (integer). For example, "5" for Java 5, "8" for Java 8, or "11" for Java 11. * * @since 5.3 */ @Incubating -public interface TargetJavaPlatform { +public interface TargetJvmVersion { /** - * The minimal target platform for a Java library. Any consumer below this version would not be able to consume it. + * The minimal target version for a Java library. Any consumer below this version would not be able to consume it. */ - Attribute TARGET_PLATFORM_ATTRIBUTE = Attribute.of("org.gradle.jvm.platform", Integer.class); + Attribute TARGET_JVM_VERSION_ATTRIBUTE = Attribute.of("org.gradle.jvm.version", Integer.class); } diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/artifacts/JavaEcosystemSupport.java b/subprojects/core/src/main/java/org/gradle/api/internal/artifacts/JavaEcosystemSupport.java index 4d646f7b615c7..0c044c5b66d20 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/artifacts/JavaEcosystemSupport.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/artifacts/JavaEcosystemSupport.java @@ -30,7 +30,7 @@ import org.gradle.api.attributes.MultipleCandidatesDetails; import org.gradle.api.attributes.Usage; import org.gradle.api.attributes.Bundling; -import org.gradle.api.attributes.java.TargetJavaPlatform; +import org.gradle.api.attributes.java.TargetJvmVersion; import org.gradle.api.internal.ReusableAction; import org.gradle.api.internal.attributes.AttributeContainerInternal; import org.gradle.api.model.ObjectFactory; @@ -49,13 +49,13 @@ public static void configureDefaultTargetPlatform(HasAttributes configuration, J String majorVersion = version.getMajorVersion(); AttributeContainerInternal attributes = (AttributeContainerInternal) configuration.getAttributes(); // If nobody said anything about this variant's target platform, use whatever the convention says - if (!attributes.contains(TargetJavaPlatform.TARGET_PLATFORM_ATTRIBUTE)) { - attributes.attribute(TargetJavaPlatform.TARGET_PLATFORM_ATTRIBUTE, Integer.valueOf(majorVersion)); + if (!attributes.contains(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE)) { + attributes.attribute(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE, Integer.valueOf(majorVersion)); } } private static void configureTargetPlatform(AttributesSchema attributesSchema) { - AttributeMatchingStrategy targetPlatformSchema = attributesSchema.attribute(TargetJavaPlatform.TARGET_PLATFORM_ATTRIBUTE); + AttributeMatchingStrategy targetPlatformSchema = attributesSchema.attribute(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE); targetPlatformSchema.getCompatibilityRules().ordered(Ordering.natural()); targetPlatformSchema.getDisambiguationRules().pickLast(Ordering.natural()); } diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/initialization/DefaultScriptHandler.java b/subprojects/core/src/main/java/org/gradle/api/internal/initialization/DefaultScriptHandler.java index 9352462d79fcd..c0e732d1703c6 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/initialization/DefaultScriptHandler.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/initialization/DefaultScriptHandler.java @@ -24,7 +24,7 @@ import org.gradle.api.attributes.Bundling; import org.gradle.api.attributes.AttributeContainer; import org.gradle.api.attributes.Usage; -import org.gradle.api.attributes.java.TargetJavaPlatform; +import org.gradle.api.attributes.java.TargetJvmVersion; import org.gradle.api.initialization.dsl.ScriptHandler; import org.gradle.api.internal.DynamicObjectAware; import org.gradle.api.internal.artifacts.DependencyResolutionServices; @@ -118,7 +118,7 @@ private void defineConfiguration() { AttributeContainer attributes = classpathConfiguration.getAttributes(); attributes.attribute(Usage.USAGE_ATTRIBUTE, NamedObjectInstantiator.INSTANCE.named(Usage.class, Usage.JAVA_RUNTIME)); attributes.attribute(Bundling.BUNDLING_ATTRIBUTE, NamedObjectInstantiator.INSTANCE.named(Bundling.class, Bundling.EXTERNAL)); - attributes.attribute(TargetJavaPlatform.TARGET_PLATFORM_ATTRIBUTE, Integer.valueOf(JavaVersion.current().getMajorVersion())); + attributes.attribute(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE, Integer.valueOf(JavaVersion.current().getMajorVersion())); } } diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/artifacts/TargetJavaPlatformRulesTest.groovy b/subprojects/core/src/test/groovy/org/gradle/api/internal/artifacts/TargetJvmVersionRulesTest.groovy similarity index 92% rename from subprojects/core/src/test/groovy/org/gradle/api/internal/artifacts/TargetJavaPlatformRulesTest.groovy rename to subprojects/core/src/test/groovy/org/gradle/api/internal/artifacts/TargetJvmVersionRulesTest.groovy index 112a7c26554c2..96b90b291c899 100644 --- a/subprojects/core/src/test/groovy/org/gradle/api/internal/artifacts/TargetJavaPlatformRulesTest.groovy +++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/artifacts/TargetJvmVersionRulesTest.groovy @@ -17,7 +17,7 @@ package org.gradle.api.internal.artifacts import org.gradle.api.attributes.AttributesSchema -import org.gradle.api.attributes.java.TargetJavaPlatform +import org.gradle.api.attributes.java.TargetJvmVersion import org.gradle.api.internal.attributes.CompatibilityCheckResult import org.gradle.api.internal.attributes.CompatibilityRule import org.gradle.api.internal.attributes.DefaultAttributesSchema @@ -29,15 +29,15 @@ import org.gradle.util.TestUtil import spock.lang.Specification import spock.lang.Unroll -class TargetJavaPlatformRulesTest extends Specification { +class TargetJvmVersionRulesTest extends Specification { private CompatibilityRule compatibilityRules private DisambiguationRule disambiguationRules def setup() { AttributesSchema schema = new DefaultAttributesSchema(Stub(ComponentAttributeMatcher), TestUtil.instantiatorFactory(), SnapshotTestUtil.valueSnapshotter()) JavaEcosystemSupport.configureSchema(schema, TestUtil.objectFactory()) - compatibilityRules = schema.compatibilityRules(TargetJavaPlatform.TARGET_PLATFORM_ATTRIBUTE) - disambiguationRules = schema.disambiguationRules(TargetJavaPlatform.TARGET_PLATFORM_ATTRIBUTE) + compatibilityRules = schema.compatibilityRules(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE) + disambiguationRules = schema.disambiguationRules(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE) } @Unroll("compatibility consumer=#consumer producer=#producer compatible=#compatible") diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/initialization/DefaultScriptHandlerTest.groovy b/subprojects/core/src/test/groovy/org/gradle/api/internal/initialization/DefaultScriptHandlerTest.groovy index f8d3d700fca6a..64093b53b4d14 100644 --- a/subprojects/core/src/test/groovy/org/gradle/api/internal/initialization/DefaultScriptHandlerTest.groovy +++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/initialization/DefaultScriptHandlerTest.groovy @@ -22,7 +22,7 @@ import org.gradle.api.artifacts.dsl.RepositoryHandler import org.gradle.api.attributes.AttributesSchema import org.gradle.api.attributes.Bundling import org.gradle.api.attributes.Usage -import org.gradle.api.attributes.java.TargetJavaPlatform +import org.gradle.api.attributes.java.TargetJvmVersion import org.gradle.api.internal.artifacts.DependencyResolutionServices import org.gradle.api.internal.attributes.AttributeContainerInternal import org.gradle.groovy.scripts.ScriptSource @@ -58,7 +58,7 @@ class DefaultScriptHandlerTest extends Specification { 1 * configuration.attributes >> attributes 1 * attributes.attribute(Usage.USAGE_ATTRIBUTE, _ as Usage) 1 * attributes.attribute(Bundling.BUNDLING_ATTRIBUTE, _ as Bundling) - 1 * attributes.attribute(TargetJavaPlatform.TARGET_PLATFORM_ATTRIBUTE, _) + 1 * attributes.attribute(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE, _) 0 * configurationContainer._ 0 * depMgmtServices._ } @@ -74,7 +74,7 @@ class DefaultScriptHandlerTest extends Specification { 1 * configuration.attributes >> attributes 1 * attributes.attribute(Usage.USAGE_ATTRIBUTE, _ as Usage) 1 * attributes.attribute(Bundling.BUNDLING_ATTRIBUTE, _ as Bundling) - 1 * attributes.attribute(TargetJavaPlatform.TARGET_PLATFORM_ATTRIBUTE, _) + 1 * attributes.attribute(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE, _) 1 * depMgmtServices.dependencyHandler >> dependencyHandler 0 * configurationContainer._ 0 * depMgmtServices._ @@ -107,7 +107,7 @@ class DefaultScriptHandlerTest extends Specification { 1 * configurationContainer.create('classpath') >> configuration 1 * configuration.attributes >> attributes 1 * attributes.attribute(Usage.USAGE_ATTRIBUTE, _ as Usage) - 1 * attributes.attribute(TargetJavaPlatform.TARGET_PLATFORM_ATTRIBUTE, _) + 1 * attributes.attribute(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE, _) 1 * attributes.attribute(Bundling.BUNDLING_ATTRIBUTE, _ as Bundling) 1 * classpathResolver.resolveClassPath(configuration) >> classpath } @@ -138,8 +138,8 @@ class DefaultScriptHandlerTest extends Specification { 1 * configurationContainer.create('classpath') >> configuration 1 * configuration.attributes >> attributes 1 * attributes.attribute(Usage.USAGE_ATTRIBUTE, _ as Usage) - 1 * attributes.attribute(TargetJavaPlatform.TARGET_PLATFORM_ATTRIBUTE, _) 1 * attributes.attribute(Bundling.BUNDLING_ATTRIBUTE, _ as Bundling) + 1 * attributes.attribute(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE, _) 1 * dependencyHandler.add('config', 'dep') } } diff --git a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/attributes/CrossProjectMultipleVariantSelectionIntegrationTest.groovy b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/attributes/CrossProjectMultipleVariantSelectionIntegrationTest.groovy index 2be6406ddb114..3968a335e75f1 100644 --- a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/attributes/CrossProjectMultipleVariantSelectionIntegrationTest.groovy +++ b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/attributes/CrossProjectMultipleVariantSelectionIntegrationTest.groovy @@ -49,7 +49,7 @@ class CrossProjectMultipleVariantSelectionIntegrationTest extends AbstractDepend attributes { attribute(Usage.USAGE_ATTRIBUTE, project.objects.named(Usage, 'java-api-jars')) attribute(Bundling.BUNDLING_ATTRIBUTE, project.objects.named(Bundling, Bundling.EXTERNAL)) - attribute(TargetJavaPlatform.TARGET_PLATFORM_ATTRIBUTE, Integer.valueOf(JavaVersion.current().majorVersion)) + attribute(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE, Integer.valueOf(JavaVersion.current().majorVersion)) } outgoing.capability('org:lib-fixtures:1.0') } @@ -81,11 +81,11 @@ class CrossProjectMultipleVariantSelectionIntegrationTest extends AbstractDepend resolve.expectGraph { root(":", ":test:") { project(":lib", "test:lib:") { - variant "apiElements", ['org.gradle.usage':'java-api-jars', 'org.gradle.dependency.bundling':'external', 'org.gradle.jvm.platform': JavaVersion.current().majorVersion] + variant "apiElements", ['org.gradle.usage':'java-api-jars', 'org.gradle.dependency.bundling':'external', 'org.gradle.jvm.version': JavaVersion.current().majorVersion] artifact group:'', module:'', version: '', type: '', name: 'main', noType: true } project(":lib", "test:lib:") { - variant "testFixtures", ['org.gradle.usage':'java-api-jars', 'org.gradle.dependency.bundling':'external', 'org.gradle.jvm.platform': JavaVersion.current().majorVersion] + variant "testFixtures", ['org.gradle.usage':'java-api-jars', 'org.gradle.dependency.bundling':'external', 'org.gradle.jvm.version': JavaVersion.current().majorVersion] artifact group:'test', module:'lib', version:'unspecified', classifier: 'test-fixtures' } } @@ -104,7 +104,7 @@ class CrossProjectMultipleVariantSelectionIntegrationTest extends AbstractDepend attributes { attribute(Usage.USAGE_ATTRIBUTE, project.objects.named(Usage, 'java-api-jars')) attribute(Bundling.BUNDLING_ATTRIBUTE, project.objects.named(Bundling, Bundling.EXTERNAL)) - attribute(TargetJavaPlatform.TARGET_PLATFORM_ATTRIBUTE, Integer.valueOf(JavaVersion.current().majorVersion)) + attribute(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE, Integer.valueOf(JavaVersion.current().majorVersion)) } outgoing.capability('test:lib:1.0') outgoing.capability('test:lib-fixtures:1.0') @@ -129,7 +129,7 @@ class CrossProjectMultipleVariantSelectionIntegrationTest extends AbstractDepend resolve.expectGraph { root(":", ":test:") { project(":lib", "test:lib:") { - variant "apiElements", ['org.gradle.usage':'java-api-jars', 'org.gradle.dependency.bundling':'external', 'org.gradle.jvm.platform': JavaVersion.current().majorVersion] + variant "apiElements", ['org.gradle.usage':'java-api-jars', 'org.gradle.dependency.bundling':'external', 'org.gradle.jvm.version': JavaVersion.current().majorVersion] artifact group:'', module:'', version: '', type: '', name: 'main', noType: true } } diff --git a/subprojects/diagnostics/src/integTest/groovy/org/gradle/api/tasks/diagnostics/DependencyInsightReportTaskIntegrationTest.groovy b/subprojects/diagnostics/src/integTest/groovy/org/gradle/api/tasks/diagnostics/DependencyInsightReportTaskIntegrationTest.groovy index 84a60905bb9d2..b0f1f3d5603e6 100644 --- a/subprojects/diagnostics/src/integTest/groovy/org/gradle/api/tasks/diagnostics/DependencyInsightReportTaskIntegrationTest.groovy +++ b/subprojects/diagnostics/src/integTest/groovy/org/gradle/api/tasks/diagnostics/DependencyInsightReportTaskIntegrationTest.groovy @@ -1705,7 +1705,7 @@ project : variant "runtimeElements" [ org.gradle.usage = java-runtime-jars (not requested) org.gradle.dependency.bundling = external (not requested) - org.gradle.jvm.platform = ${JavaVersion.current().majorVersion} (not requested) + org.gradle.jvm.version = ${JavaVersion.current().majorVersion} (not requested) ] project : @@ -1804,7 +1804,7 @@ project :impl variant "runtimeElements" [ org.gradle.usage = java-runtime-jars (not requested) org.gradle.dependency.bundling = external (not requested) - org.gradle.jvm.platform = ${JavaVersion.current().majorVersion} (not requested) + org.gradle.jvm.version = ${JavaVersion.current().majorVersion} (not requested) ] project :impl @@ -1859,7 +1859,7 @@ org:leaf4:1.0 Requested attributes not found in the selected variant: org.gradle.dependency.bundling = external - org.gradle.jvm.platform = ${JavaVersion.current().majorVersion} + org.gradle.jvm.version = ${JavaVersion.current().majorVersion} ] org:leaf4:1.0 @@ -1897,7 +1897,7 @@ org:leaf1:1.0 Requested attributes not found in the selected variant: org.gradle.dependency.bundling = external - org.gradle.jvm.platform = ${JavaVersion.current().majorVersion} + org.gradle.jvm.version = ${JavaVersion.current().majorVersion} ] org:leaf1:1.0 @@ -1917,7 +1917,7 @@ org:leaf2:1.0 Requested attributes not found in the selected variant: org.gradle.dependency.bundling = external - org.gradle.jvm.platform = ${JavaVersion.current().majorVersion} + org.gradle.jvm.version = ${JavaVersion.current().majorVersion} ] org:leaf2:1.0 @@ -1974,7 +1974,7 @@ project :api variant "apiElements" [ org.gradle.usage = java-api-jars (compatible with: java-api) org.gradle.dependency.bundling = external - org.gradle.jvm.platform = ${JavaVersion.current().majorVersion} + org.gradle.jvm.version = ${JavaVersion.current().majorVersion} ] project :api @@ -1991,7 +1991,7 @@ project :some:deeply:nested variant "apiElements" [ org.gradle.usage = java-api-jars (compatible with: java-api) org.gradle.dependency.bundling = external - org.gradle.jvm.platform = ${JavaVersion.current().majorVersion} + org.gradle.jvm.version = ${JavaVersion.current().majorVersion} ] project :some:deeply:nested @@ -2006,8 +2006,8 @@ project :some:deeply:nested project :some:deeply:nested variant "apiElements" [ org.gradle.usage = java-api-jars (compatible with: java-api) - org.gradle.dependency.bundling = external - org.gradle.jvm.platform = ${JavaVersion.current().majorVersion} + org.gradle.dependency.bundling = external (not requested) + org.gradle.jvm.version = ${JavaVersion.current().majorVersion} ] project :some:deeply:nested @@ -2061,7 +2061,7 @@ org:leaf3:1.0 Requested attributes not found in the selected variant: org.gradle.dependency.bundling = external - org.gradle.jvm.platform = ${JavaVersion.current().majorVersion} + org.gradle.jvm.version = ${JavaVersion.current().majorVersion} ] org:leaf3:1.0 @@ -2165,7 +2165,7 @@ foo:foo:1.0 Requested attributes not found in the selected variant: org.gradle.dependency.bundling = external - org.gradle.jvm.platform = ${JavaVersion.current().majorVersion} + org.gradle.jvm.version = ${JavaVersion.current().majorVersion} ] Selection reasons: - By constraint : $rejected @@ -2221,7 +2221,7 @@ org:foo -> $selected Requested attributes not found in the selected variant: org.gradle.dependency.bundling = external - org.gradle.jvm.platform = ${JavaVersion.current().majorVersion} + org.gradle.jvm.version = ${JavaVersion.current().majorVersion} ] Selection reasons: - By constraint : ${rejected}${reason} @@ -2274,7 +2274,7 @@ org:foo -> $selected Requested attributes not found in the selected variant: org.gradle.dependency.bundling = external - org.gradle.jvm.platform = ${JavaVersion.current().majorVersion} + org.gradle.jvm.version = ${JavaVersion.current().majorVersion} ] Selection reasons: - Was requested : ${rejected}${reason} @@ -2324,7 +2324,7 @@ org:foo:${displayVersion} -> $selected Requested attributes not found in the selected variant: org.gradle.dependency.bundling = external - org.gradle.jvm.platform = ${JavaVersion.current().majorVersion} + org.gradle.jvm.version = ${JavaVersion.current().majorVersion} ] Selection reasons: - Was requested : didn't match versions 2.0, 1.5, 1.4 @@ -2380,7 +2380,7 @@ org:foo:[1.1,1.3] -> 1.3 Requested attributes not found in the selected variant: org.gradle.dependency.bundling = external - org.gradle.jvm.platform = ${JavaVersion.current().majorVersion} + org.gradle.jvm.version = ${JavaVersion.current().majorVersion} ] Selection reasons: - Was requested : rejected versions 1.2, 1.1 @@ -2396,7 +2396,7 @@ org:foo:1.1 Requested attributes not found in the selected variant: org.gradle.dependency.bundling = external - org.gradle.jvm.platform = ${JavaVersion.current().majorVersion} + org.gradle.jvm.version = ${JavaVersion.current().majorVersion} ] Selection reasons: - Was requested : rejected version 1.2 @@ -2456,7 +2456,7 @@ org:bar:1.0 Requested attributes not found in the selected variant: org.gradle.dependency.bundling = external - org.gradle.jvm.platform = ${JavaVersion.current().majorVersion} + org.gradle.jvm.version = ${JavaVersion.current().majorVersion} ] Selection reasons: - Rejection : 1.2 by rule because version 1.2 is bad @@ -2473,7 +2473,7 @@ org:foo:1.1 Requested attributes not found in the selected variant: org.gradle.dependency.bundling = external - org.gradle.jvm.platform = ${JavaVersion.current().majorVersion} + org.gradle.jvm.version = ${JavaVersion.current().majorVersion} ] Selection reasons: - Was requested : rejected version 1.2 @@ -2518,7 +2518,7 @@ org:leaf:1.0 (by constraint) Requested attributes not found in the selected variant: org.gradle.dependency.bundling = external - org.gradle.jvm.platform = ${JavaVersion.current().majorVersion} + org.gradle.jvm.version = ${JavaVersion.current().majorVersion} ] org:leaf:1.0 @@ -2571,7 +2571,7 @@ org.test:leaf:1.0 Requested attributes not found in the selected variant: org.gradle.dependency.bundling = external - org.gradle.jvm.platform = ${JavaVersion.current().majorVersion} + org.gradle.jvm.version = ${JavaVersion.current().majorVersion} ] Selection reasons: - Was requested : first reason @@ -2753,7 +2753,7 @@ org:foo:1.0 Requested attributes not found in the selected variant: org.gradle.dependency.bundling = external - org.gradle.jvm.platform = ${JavaVersion.current().majorVersion} + org.gradle.jvm.version = ${JavaVersion.current().majorVersion} ] Selection reasons: - Was requested : rejected versions 1.2, 1.1 @@ -2810,7 +2810,7 @@ org:foo:{require [1.0,); reject 1.1} -> 1.0 Requested attributes not found in the selected variant: org.gradle.dependency.bundling = external - org.gradle.jvm.platform = ${JavaVersion.current().majorVersion} + org.gradle.jvm.version = ${JavaVersion.current().majorVersion} ] Selection reasons: - Was requested : first reason @@ -2876,18 +2876,18 @@ org:foo:1.0 Requested attributes not found in the selected variant: org.gradle.dependency.bundling = external - org.gradle.jvm.platform = ${JavaVersion.current().majorVersion} + org.gradle.jvm.version = ${JavaVersion.current().majorVersion} ] Selection reasons: - Rejection : version 1.2: - Attribute 'color' didn't match. Requested 'blue', was: 'red' - Attribute 'org.gradle.dependency.bundling' didn't match. Requested 'external', was: not found - - Attribute 'org.gradle.jvm.platform' didn't match. Requested '${JavaVersion.current().majorVersion}', was: not found + - Attribute 'org.gradle.jvm.version' didn't match. Requested '${JavaVersion.current().majorVersion}', was: not found - Attribute 'org.gradle.usage' didn't match. Requested 'java-api', was: not found - Rejection : version 1.1: - Attribute 'color' didn't match. Requested 'blue', was: 'green' - Attribute 'org.gradle.dependency.bundling' didn't match. Requested 'external', was: not found - - Attribute 'org.gradle.jvm.platform' didn't match. Requested '${JavaVersion.current().majorVersion}', was: not found + - Attribute 'org.gradle.jvm.version' didn't match. Requested '${JavaVersion.current().majorVersion}', was: not found - Attribute 'org.gradle.usage' didn't match. Requested 'java-api', was: not found org:foo:[1.0,) -> 1.0 @@ -2951,7 +2951,7 @@ planet:mercury:1.0.2 Requested attributes not found in the selected variant: org.gradle.dependency.bundling = external - org.gradle.jvm.platform = ${JavaVersion.current().majorVersion} + org.gradle.jvm.version = ${JavaVersion.current().majorVersion} ] Selection reasons: - By conflict resolution : between versions 1.0.2 and 1.0.1 @@ -2982,7 +2982,7 @@ planet:venus:2.0.1 Requested attributes not found in the selected variant: org.gradle.dependency.bundling = external - org.gradle.jvm.platform = ${JavaVersion.current().majorVersion} + org.gradle.jvm.version = ${JavaVersion.current().majorVersion} ] Selection reasons: - By conflict resolution : between versions 2.0.0, 2.0.1 and 1.0 @@ -3013,7 +3013,7 @@ planet:pluto:1.0.0 Requested attributes not found in the selected variant: org.gradle.dependency.bundling = external - org.gradle.jvm.platform = ${JavaVersion.current().majorVersion} + org.gradle.jvm.version = ${JavaVersion.current().majorVersion} ] planet:pluto:1.0.0 diff --git a/subprojects/diagnostics/src/integTest/groovy/org/gradle/api/tasks/diagnostics/DependencyInsightReportVariantDetailsIntegrationTest.groovy b/subprojects/diagnostics/src/integTest/groovy/org/gradle/api/tasks/diagnostics/DependencyInsightReportVariantDetailsIntegrationTest.groovy index 5363e1d00c6fd..f5167e976210c 100644 --- a/subprojects/diagnostics/src/integTest/groovy/org/gradle/api/tasks/diagnostics/DependencyInsightReportVariantDetailsIntegrationTest.groovy +++ b/subprojects/diagnostics/src/integTest/groovy/org/gradle/api/tasks/diagnostics/DependencyInsightReportVariantDetailsIntegrationTest.groovy @@ -57,7 +57,7 @@ class DependencyInsightReportVariantDetailsIntegrationTest extends AbstractInteg variant "$expectedVariant" [ $expectedAttributes org.gradle.dependency.bundling = external (not requested) - org.gradle.jvm.platform = ${JavaVersion.current().majorVersion} + org.gradle.jvm.version = ${JavaVersion.current().majorVersion} ] project :$expectedProject @@ -110,7 +110,7 @@ project :$expectedProject Requested attributes not found in the selected variant: org.gradle.blah = something org.gradle.dependency.bundling = external - org.gradle.jvm.platform = ${JavaVersion.current().majorVersion} + org.gradle.jvm.version = ${JavaVersion.current().majorVersion} ] org.test:leaf:1.0 diff --git a/subprojects/docs/src/samples/java-feature-variant/requiring-features-external/runtimeClasspath.out b/subprojects/docs/src/samples/java-feature-variant/requiring-features-external/runtimeClasspath.out index 273eb3ec0686b..85643c2c6a108 100644 --- a/subprojects/docs/src/samples/java-feature-variant/requiring-features-external/runtimeClasspath.out +++ b/subprojects/docs/src/samples/java-feature-variant/requiring-features-external/runtimeClasspath.out @@ -8,7 +8,7 @@ org.mongodb:bson:3.9.1 Requested attributes not found in the selected variant: org.gradle.dependency.bundling = external - org.gradle.jvm.platform = 11 + org.gradle.jvm.version = 11 ] org.mongodb:bson:3.9.1 @@ -26,7 +26,7 @@ org.mongodb:mongodb-driver-core:3.9.1 Requested attributes not found in the selected variant: org.gradle.dependency.bundling = external - org.gradle.jvm.platform = 11 + org.gradle.jvm.version = 11 ] org.mongodb:mongodb-driver-core:3.9.1 @@ -42,7 +42,7 @@ org.mongodb:mongodb-driver-sync:3.9.1 Requested attributes not found in the selected variant: org.gradle.dependency.bundling = external - org.gradle.jvm.platform = 11 + org.gradle.jvm.version = 11 ] org.mongodb:mongodb-driver-sync:3.9.1 diff --git a/subprojects/docs/src/samples/java-feature-variant/requiring-features/runtimeClasspath.out b/subprojects/docs/src/samples/java-feature-variant/requiring-features/runtimeClasspath.out index 1a281143552af..13c8f3b6deeec 100644 --- a/subprojects/docs/src/samples/java-feature-variant/requiring-features/runtimeClasspath.out +++ b/subprojects/docs/src/samples/java-feature-variant/requiring-features/runtimeClasspath.out @@ -7,8 +7,8 @@ mysql:mysql-connector-java:8.0.14 org.gradle.component.category = library (not requested) Requested attributes not found in the selected variant: - org.gradle.jvm.platform = 11 org.gradle.dependency.bundling = external + org.gradle.jvm.version = 11 ] mysql:mysql-connector-java:8.0.14 diff --git a/subprojects/docs/src/samples/userguide/dependencyManagement/inspectingDependencies/dependencyReason/dependencyReasonReport.out b/subprojects/docs/src/samples/userguide/dependencyManagement/inspectingDependencies/dependencyReason/dependencyReasonReport.out index da5df886664cc..0c925d0842563 100644 --- a/subprojects/docs/src/samples/userguide/dependencyManagement/inspectingDependencies/dependencyReason/dependencyReasonReport.out +++ b/subprojects/docs/src/samples/userguide/dependencyManagement/inspectingDependencies/dependencyReason/dependencyReasonReport.out @@ -6,7 +6,7 @@ org.ow2.asm:asm:6.0 Requested attributes not found in the selected variant: org.gradle.dependency.bundling = external - org.gradle.jvm.platform = 11 + org.gradle.jvm.version = 11 ] Selection reasons: - Was requested : we require a JDK 9 compatible bytecode generator diff --git a/subprojects/docs/src/samples/userguide/dependencyManagement/managingTransitiveDependencies/declaringCapabilities/dependencyReport.out b/subprojects/docs/src/samples/userguide/dependencyManagement/managingTransitiveDependencies/declaringCapabilities/dependencyReport.out index 1ecf036e07814..8ac46d8918c93 100644 --- a/subprojects/docs/src/samples/userguide/dependencyManagement/managingTransitiveDependencies/declaringCapabilities/dependencyReport.out +++ b/subprojects/docs/src/samples/userguide/dependencyManagement/managingTransitiveDependencies/declaringCapabilities/dependencyReport.out @@ -25,7 +25,7 @@ org.slf4j:slf4j-log4j12:1.6.1 Requested attributes not found in the selected variant: org.gradle.dependency.bundling = external - org.gradle.jvm.platform = 11 + org.gradle.jvm.version = 11 ] org.slf4j:slf4j-log4j12:1.6.1 diff --git a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/logging/DependencyInsightOutputNormalizer.groovy b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/logging/DependencyInsightOutputNormalizer.groovy index cc8299778fcad..12ee10e424595 100644 --- a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/logging/DependencyInsightOutputNormalizer.groovy +++ b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/logging/DependencyInsightOutputNormalizer.groovy @@ -25,6 +25,6 @@ class DependencyInsightOutputNormalizer implements OutputNormalizer { @Override String normalize(String output, ExecutionMetadata executionMetadata) { - output.replaceAll("org\\.gradle\\.jvm\\.platform[ ]+= [0-9]+", "org.gradle.jvm.platform = 11") + output.replaceAll("org\\.gradle\\.jvm\\.version[ ]+= [0-9]+", "org.gradle.jvm.version = 11") } } diff --git a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/ivy/IvyJavaModule.groovy b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/ivy/IvyJavaModule.groovy index fcbad596c6251..ba5ca08295c3b 100644 --- a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/ivy/IvyJavaModule.groovy +++ b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/ivy/IvyJavaModule.groovy @@ -17,7 +17,7 @@ package org.gradle.test.fixtures.ivy import org.gradle.api.JavaVersion -import org.gradle.api.attributes.java.TargetJavaPlatform +import org.gradle.api.attributes.java.TargetJvmVersion import org.gradle.test.fixtures.ModuleArtifact import org.gradle.test.fixtures.PublishedJavaModule import org.gradle.test.fixtures.file.TestFile @@ -30,7 +30,7 @@ class IvyJavaModule extends DelegatingIvyModule implements Publis IvyJavaModule(IvyFileModule backingModule) { super(backingModule) this.backingModule = backingModule - this.backingModule.attributes[TargetJavaPlatform.TARGET_PLATFORM_ATTRIBUTE.name] = JavaVersion.current().majorVersion + this.backingModule.attributes[TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE.name] = JavaVersion.current().majorVersion } @Override diff --git a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/maven/MavenJavaModule.groovy b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/maven/MavenJavaModule.groovy index 701228d29b8f1..3a38b4aa508f3 100644 --- a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/maven/MavenJavaModule.groovy +++ b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/maven/MavenJavaModule.groovy @@ -18,7 +18,7 @@ package org.gradle.test.fixtures.maven import org.gradle.api.JavaVersion import org.gradle.api.attributes.java.Bundling -import org.gradle.api.attributes.java.TargetJavaPlatform +import org.gradle.api.attributes.java.TargetJvmVersion import org.gradle.test.fixtures.PublishedJavaModule import org.gradle.util.GUtil @@ -29,7 +29,7 @@ class MavenJavaModule extends DelegatingMavenModule implements MavenJavaModule(MavenFileModule mavenModule) { super(mavenModule) this.mavenModule = mavenModule - this.mavenModule.attributes[TargetJavaPlatform.TARGET_PLATFORM_ATTRIBUTE.name] = JavaVersion.current().majorVersion + this.mavenModule.attributes[TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE.name] = JavaVersion.current().majorVersion } @Override @@ -61,9 +61,9 @@ class MavenJavaModule extends DelegatingMavenModule implements // Verify it contains some expected attributes assert apiElements.attributes.containsKey(Bundling.BUNDLING_ATTRIBUTE.name) - assert apiElements.attributes.containsKey(TargetJavaPlatform.TARGET_PLATFORM_ATTRIBUTE.name) + assert apiElements.attributes.containsKey(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE.name) assert runtimeElements.attributes.containsKey(Bundling.BUNDLING_ATTRIBUTE.name) - assert runtimeElements.attributes.containsKey(TargetJavaPlatform.TARGET_PLATFORM_ATTRIBUTE.name) + assert runtimeElements.attributes.containsKey(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE.name) // Verify POM particulars assert mavenModule.parsedPom.packaging == null diff --git a/subprojects/plugins/src/integTest/groovy/org/gradle/java/JavaApplicationOutgoingVariantsIntegrationTest.groovy b/subprojects/plugins/src/integTest/groovy/org/gradle/java/JavaApplicationOutgoingVariantsIntegrationTest.groovy index 69492b7165577..0ed5fdd931ef3 100644 --- a/subprojects/plugins/src/integTest/groovy/org/gradle/java/JavaApplicationOutgoingVariantsIntegrationTest.groovy +++ b/subprojects/plugins/src/integTest/groovy/org/gradle/java/JavaApplicationOutgoingVariantsIntegrationTest.groovy @@ -283,6 +283,6 @@ project(':consumer') { } static String defaultTargetPlatform() { - "org.gradle.jvm.platform=${JavaVersion.current().majorVersion}" + "org.gradle.jvm.version=${JavaVersion.current().majorVersion}" } } diff --git a/subprojects/plugins/src/integTest/groovy/org/gradle/java/JavaLibraryCrossProjectTargetPlatformIntegrationTest.groovy b/subprojects/plugins/src/integTest/groovy/org/gradle/java/JavaLibraryCrossProjectTargetPlatformIntegrationTest.groovy index 8f3d5ec32631f..9f1b69d55fd14 100644 --- a/subprojects/plugins/src/integTest/groovy/org/gradle/java/JavaLibraryCrossProjectTargetPlatformIntegrationTest.groovy +++ b/subprojects/plugins/src/integTest/groovy/org/gradle/java/JavaLibraryCrossProjectTargetPlatformIntegrationTest.groovy @@ -49,7 +49,7 @@ class JavaLibraryCrossProjectTargetPlatformIntegrationTest extends AbstractInteg } """ buildFile << """ - configurations.compileClasspath.attributes.attribute(TargetJavaPlatform.TARGET_PLATFORM_ATTRIBUTE, 6) + configurations.compileClasspath.attributes.attribute(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE, 6) """ when: @@ -59,11 +59,11 @@ class JavaLibraryCrossProjectTargetPlatformIntegrationTest extends AbstractInteg failure.assertHasCause('''Unable to find a matching variant of project :producer: - Variant 'apiElements' capability test:producer:unspecified: - Found org.gradle.dependency.bundling 'external' but wasn't required. - - Required org.gradle.jvm.platform '6' and found incompatible value '7'. + - Required org.gradle.jvm.version '6' and found incompatible value '7'. - Required org.gradle.usage 'java-api' and found compatible value 'java-api-jars'. - Variant 'runtimeElements' capability test:producer:unspecified: - Found org.gradle.dependency.bundling 'external' but wasn't required. - - Required org.gradle.jvm.platform '6' and found incompatible value '7'. + - Required org.gradle.jvm.version '6' and found incompatible value '7'. - Required org.gradle.usage 'java-api' and found compatible value 'java-runtime-jars'.''') } @@ -71,7 +71,7 @@ class JavaLibraryCrossProjectTargetPlatformIntegrationTest extends AbstractInteg def "can select the most appropriate producer variant (#expected) based on target compatibility (#requested)"() { file('producer/build.gradle') << """ // avoid test noise so that typically version 8 is not selected when running on JDK 8 - configurations.apiElements.attributes.attribute(TargetJavaPlatform.TARGET_PLATFORM_ATTRIBUTE, 1000) + configurations.apiElements.attributes.attribute(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE, 1000) [6, 7, 9].each { v -> configurations { @@ -81,7 +81,7 @@ class JavaLibraryCrossProjectTargetPlatformIntegrationTest extends AbstractInteg attributes { attribute(Usage.USAGE_ATTRIBUTE, objects.named(Usage, 'java-api-jars')) attribute(Bundling.BUNDLING_ATTRIBUTE, objects.named(Bundling, 'external')) - attribute(TargetJavaPlatform.TARGET_PLATFORM_ATTRIBUTE, v) + attribute(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE, v) } } } @@ -91,7 +91,7 @@ class JavaLibraryCrossProjectTargetPlatformIntegrationTest extends AbstractInteg } """ buildFile << """ - configurations.compileClasspath.attributes.attribute(TargetJavaPlatform.TARGET_PLATFORM_ATTRIBUTE, $requested) + configurations.compileClasspath.attributes.attribute(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE, $requested) """ when: @@ -103,7 +103,7 @@ class JavaLibraryCrossProjectTargetPlatformIntegrationTest extends AbstractInteg project(':producer', 'test:producer:') { variant(expected, [ 'org.gradle.dependency.bundling': 'external', - 'org.gradle.jvm.platform': selected, + 'org.gradle.jvm.version': selected, 'org.gradle.usage':'java-api-jars' ]) artifact(classifier: "jdk${selected}") @@ -141,11 +141,11 @@ class JavaLibraryCrossProjectTargetPlatformIntegrationTest extends AbstractInteg failure.assertHasCause("""Unable to find a matching variant of project :producer: - Variant 'apiElements' capability test:producer:unspecified: - Found org.gradle.dependency.bundling 'external' but wasn't required. - - Required org.gradle.jvm.platform '6' and found incompatible value '7'. + - Required org.gradle.jvm.version '6' and found incompatible value '7'. - Required org.gradle.usage 'java-api' and found compatible value 'java-api-jars'. - Variant 'runtimeElements' capability test:producer:unspecified: - Found org.gradle.dependency.bundling 'external' but wasn't required. - - Required org.gradle.jvm.platform '6' and found incompatible value '7'. + - Required org.gradle.jvm.version '6' and found incompatible value '7'. - Required org.gradle.usage 'java-api' and found compatible value 'java-runtime-jars'.""") when: @@ -162,7 +162,7 @@ class JavaLibraryCrossProjectTargetPlatformIntegrationTest extends AbstractInteg project(':producer', 'test:producer:') { variant("apiElements", [ 'org.gradle.dependency.bundling': 'external', - 'org.gradle.jvm.platform': '7', + 'org.gradle.jvm.version': '7', 'org.gradle.usage':'java-api-jars' ]) artifact group:'', module:'', version: '', type: '', name: 'main', noType: true diff --git a/subprojects/plugins/src/integTest/groovy/org/gradle/java/JavaLibraryOutgoingVariantsIntegrationTest.groovy b/subprojects/plugins/src/integTest/groovy/org/gradle/java/JavaLibraryOutgoingVariantsIntegrationTest.groovy index 68ef2607a496f..4d4ae775feb2b 100644 --- a/subprojects/plugins/src/integTest/groovy/org/gradle/java/JavaLibraryOutgoingVariantsIntegrationTest.groovy +++ b/subprojects/plugins/src/integTest/groovy/org/gradle/java/JavaLibraryOutgoingVariantsIntegrationTest.groovy @@ -284,6 +284,6 @@ project(':consumer') { } static String defaultTargetPlatform() { - "org.gradle.jvm.platform=${JavaVersion.current().majorVersion}" + "org.gradle.jvm.version=${JavaVersion.current().majorVersion}" } } diff --git a/subprojects/plugins/src/integTest/groovy/org/gradle/java/JavaLibraryPublishedTargetPlatformIntegrationTest.groovy b/subprojects/plugins/src/integTest/groovy/org/gradle/java/JavaLibraryPublishedTargetPlatformIntegrationTest.groovy index 3e24f6a214b79..15e3e6d4b6517 100644 --- a/subprojects/plugins/src/integTest/groovy/org/gradle/java/JavaLibraryPublishedTargetPlatformIntegrationTest.groovy +++ b/subprojects/plugins/src/integTest/groovy/org/gradle/java/JavaLibraryPublishedTargetPlatformIntegrationTest.groovy @@ -50,27 +50,27 @@ class JavaLibraryPublishedTargetPlatformIntegrationTest extends AbstractHttpDepe .adhocVariants() .variant("apiElementsJdk6", [ 'org.gradle.dependency.bundling': 'external', - 'org.gradle.jvm.platform': '6', + 'org.gradle.jvm.version': '6', 'org.gradle.usage': 'java-api-jars'], { artifact('producer-1.0-jdk6.jar') }) .variant("apiElementsJdk7", [ 'org.gradle.dependency.bundling': 'external', - 'org.gradle.jvm.platform': '7', + 'org.gradle.jvm.version': '7', 'org.gradle.usage': 'java-api-jars'], { artifact('producer-1.0-jdk7.jar') }) .variant("apiElementsJdk9", [ 'org.gradle.dependency.bundling': 'external', - 'org.gradle.jvm.platform': '9', + 'org.gradle.jvm.version': '9', 'org.gradle.usage': 'java-api-jars'], { artifact('producer-1.0-jdk9.jar') }) .variant("runtimeElementsJdk6", [ 'org.gradle.dependency.bundling': 'external', - 'org.gradle.jvm.platform': '6', + 'org.gradle.jvm.version': '6', 'org.gradle.usage': 'java-runtime-jars'], { artifact('producer-1.0-jdk6.jar') }) .variant("runtimeElementsJdk7", [ 'org.gradle.dependency.bundling': 'external', - 'org.gradle.jvm.platform': '7', + 'org.gradle.jvm.version': '7', 'org.gradle.usage': 'java-runtime-jars'], { artifact('producer-1.0-jdk7.jar') }) .variant("runtimeElementsJdk9", [ 'org.gradle.dependency.bundling': 'external', - 'org.gradle.jvm.platform': '9', + 'org.gradle.jvm.version': '9', 'org.gradle.usage': 'java-runtime-jars'], { artifact('producer-1.0-jdk9.jar') }) .publish() @@ -78,7 +78,7 @@ class JavaLibraryPublishedTargetPlatformIntegrationTest extends AbstractHttpDepe def "can fail resolution if producer doesn't have appropriate target version"() { buildFile << """ - configurations.compileClasspath.attributes.attribute(TargetJavaPlatform.TARGET_PLATFORM_ATTRIBUTE, 5) + configurations.compileClasspath.attributes.attribute(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE, 5) """ when: @@ -91,17 +91,17 @@ class JavaLibraryPublishedTargetPlatformIntegrationTest extends AbstractHttpDepe failure.assertHasCause('''Unable to find a matching variant of org:producer:1.0: - Variant 'apiElementsJdk6' capability org:producer:1.0: - Found org.gradle.dependency.bundling 'external' but wasn't required. - - Required org.gradle.jvm.platform '5' and found incompatible value '6'. + - Required org.gradle.jvm.version '5' and found incompatible value '6'. - Found org.gradle.status 'release' but wasn't required. - Required org.gradle.usage 'java-api' and found compatible value 'java-api-jars'. - Variant 'apiElementsJdk7' capability org:producer:1.0: - Found org.gradle.dependency.bundling 'external' but wasn't required. - - Required org.gradle.jvm.platform '5' and found incompatible value '7'. + - Required org.gradle.jvm.version '5' and found incompatible value '7'. - Found org.gradle.status 'release' but wasn't required. - Required org.gradle.usage 'java-api' and found compatible value 'java-api-jars'. - Variant 'apiElementsJdk9' capability org:producer:1.0: - Found org.gradle.dependency.bundling 'external' but wasn't required. - - Required org.gradle.jvm.platform '5' and found incompatible value '9'. + - Required org.gradle.jvm.version '5' and found incompatible value '9'. - Found org.gradle.status 'release' but wasn't required. - Required org.gradle.usage 'java-api' and found compatible value 'java-api-jars'.''') } @@ -109,7 +109,7 @@ class JavaLibraryPublishedTargetPlatformIntegrationTest extends AbstractHttpDepe @Unroll def "can select the most appropriate producer variant (#expected) based on target compatibility (#requested)"() { buildFile << """ - configurations.compileClasspath.attributes.attribute(TargetJavaPlatform.TARGET_PLATFORM_ATTRIBUTE, $requested) + configurations.compileClasspath.attributes.attribute(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE, $requested) """ when: @@ -125,7 +125,7 @@ class JavaLibraryPublishedTargetPlatformIntegrationTest extends AbstractHttpDepe module('org:producer:1.0') { variant(expected, [ 'org.gradle.dependency.bundling': 'external', - 'org.gradle.jvm.platform': selected, + 'org.gradle.jvm.version': selected, 'org.gradle.usage': 'java-api-jars', 'org.gradle.status': 'release' ]) diff --git a/subprojects/plugins/src/integTest/groovy/org/gradle/java/JavaProjectOutgoingVariantsIntegrationTest.groovy b/subprojects/plugins/src/integTest/groovy/org/gradle/java/JavaProjectOutgoingVariantsIntegrationTest.groovy index 3cf0f70911946..931a6592bd547 100644 --- a/subprojects/plugins/src/integTest/groovy/org/gradle/java/JavaProjectOutgoingVariantsIntegrationTest.groovy +++ b/subprojects/plugins/src/integTest/groovy/org/gradle/java/JavaProjectOutgoingVariantsIntegrationTest.groovy @@ -282,6 +282,6 @@ project(':consumer') { } static String defaultTargetPlatform() { - "org.gradle.jvm.platform=${JavaVersion.current().majorVersion}" + "org.gradle.jvm.version=${JavaVersion.current().majorVersion}" } } diff --git a/subprojects/plugins/src/main/java/org/gradle/api/plugins/JavaBasePlugin.java b/subprojects/plugins/src/main/java/org/gradle/api/plugins/JavaBasePlugin.java index ea053c0da690d..526b6673798a8 100644 --- a/subprojects/plugins/src/main/java/org/gradle/api/plugins/JavaBasePlugin.java +++ b/subprojects/plugins/src/main/java/org/gradle/api/plugins/JavaBasePlugin.java @@ -305,7 +305,7 @@ private Action configureDefaultTargetPlatform(final JavaP return new Action() { @Override public void execute(ConfigurationInternal conf) { - if (!convention.isAutoTargetJvmDisabled()) { + if (!convention.getAutoTargetJvmDisabled()) { JavaEcosystemSupport.configureDefaultTargetPlatform(conf, convention.getTargetCompatibility()); } } diff --git a/subprojects/plugins/src/main/java/org/gradle/api/plugins/JavaPluginConvention.java b/subprojects/plugins/src/main/java/org/gradle/api/plugins/JavaPluginConvention.java index 3c68f3b9b179a..a602dcda665ac 100644 --- a/subprojects/plugins/src/main/java/org/gradle/api/plugins/JavaPluginConvention.java +++ b/subprojects/plugins/src/main/java/org/gradle/api/plugins/JavaPluginConvention.java @@ -180,5 +180,5 @@ public abstract class JavaPluginConvention { * @since 5.3 */ @Incubating - public abstract boolean isAutoTargetJvmDisabled(); + public abstract boolean getAutoTargetJvmDisabled(); } diff --git a/subprojects/plugins/src/main/java/org/gradle/api/plugins/internal/DefaultJavaFeatureSpec.java b/subprojects/plugins/src/main/java/org/gradle/api/plugins/internal/DefaultJavaFeatureSpec.java index 665225519c328..540b9f72fe496 100644 --- a/subprojects/plugins/src/main/java/org/gradle/api/plugins/internal/DefaultJavaFeatureSpec.java +++ b/subprojects/plugins/src/main/java/org/gradle/api/plugins/internal/DefaultJavaFeatureSpec.java @@ -23,7 +23,7 @@ import org.gradle.api.attributes.AttributeContainer; import org.gradle.api.attributes.Usage; import org.gradle.api.attributes.Bundling; -import org.gradle.api.attributes.java.TargetJavaPlatform; +import org.gradle.api.attributes.java.TargetJvmVersion; import org.gradle.api.capabilities.Capability; import org.gradle.api.component.AdhocComponentWithVariants; import org.gradle.api.component.SoftwareComponent; @@ -166,8 +166,8 @@ public void execute(ConfigurationInternal configuration) { String majorVersion = javaPluginConvention.getTargetCompatibility().getMajorVersion(); AttributeContainerInternal attributes = configuration.getAttributes(); // If nobody said anything about this variant's target platform, use whatever the convention says - if (!attributes.contains(TargetJavaPlatform.TARGET_PLATFORM_ATTRIBUTE)) { - attributes.attribute(TargetJavaPlatform.TARGET_PLATFORM_ATTRIBUTE, Integer.valueOf(majorVersion)); + if (!attributes.contains(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE)) { + attributes.attribute(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE, Integer.valueOf(majorVersion)); } } }); diff --git a/subprojects/plugins/src/main/java/org/gradle/api/plugins/internal/DefaultJavaPluginConvention.java b/subprojects/plugins/src/main/java/org/gradle/api/plugins/internal/DefaultJavaPluginConvention.java index 3a6366186aeb6..91e0335c1a46f 100644 --- a/subprojects/plugins/src/main/java/org/gradle/api/plugins/internal/DefaultJavaPluginConvention.java +++ b/subprojects/plugins/src/main/java/org/gradle/api/plugins/internal/DefaultJavaPluginConvention.java @@ -188,7 +188,7 @@ public void disableAutoTargetJvm() { } @Override - public boolean isAutoTargetJvmDisabled() { + public boolean getAutoTargetJvmDisabled() { return !autoTargetJvm; } } From cbebab05dd11b5f4e278c1aeb63d1f1dd42ee240 Mon Sep 17 00:00:00 2001 From: Cedric Champeau Date: Thu, 21 Feb 2019 17:00:33 +0100 Subject: [PATCH 061/853] Fix rebase glitches --- ...ncyInsightReportTaskIntegrationTest.groovy | 4 +-- ...ReportVariantDetailsIntegrationTest.groovy | 4 +-- .../requiring-features/runtimeClasspath.out | 6 ++--- .../fixtures/maven/MavenJavaModule.groovy | 2 +- ...ectTargetJvmVersionIntegrationTest.groovy} | 10 ++++---- ...hedTargetJvmVersionIntegrationTest.groovy} | 25 +++++++++++++++---- 6 files changed, 33 insertions(+), 18 deletions(-) rename subprojects/plugins/src/integTest/groovy/org/gradle/java/{JavaLibraryCrossProjectTargetPlatformIntegrationTest.groovy => JavaLibraryCrossProjectTargetJvmVersionIntegrationTest.groovy} (92%) rename subprojects/plugins/src/integTest/groovy/org/gradle/java/{JavaLibraryPublishedTargetPlatformIntegrationTest.groovy => JavaLibraryPublishedTargetJvmVersionIntegrationTest.groovy} (77%) diff --git a/subprojects/diagnostics/src/integTest/groovy/org/gradle/api/tasks/diagnostics/DependencyInsightReportTaskIntegrationTest.groovy b/subprojects/diagnostics/src/integTest/groovy/org/gradle/api/tasks/diagnostics/DependencyInsightReportTaskIntegrationTest.groovy index b0f1f3d5603e6..055c55cd5cfd6 100644 --- a/subprojects/diagnostics/src/integTest/groovy/org/gradle/api/tasks/diagnostics/DependencyInsightReportTaskIntegrationTest.groovy +++ b/subprojects/diagnostics/src/integTest/groovy/org/gradle/api/tasks/diagnostics/DependencyInsightReportTaskIntegrationTest.groovy @@ -2006,7 +2006,7 @@ project :some:deeply:nested project :some:deeply:nested variant "apiElements" [ org.gradle.usage = java-api-jars (compatible with: java-api) - org.gradle.dependency.bundling = external (not requested) + org.gradle.dependency.bundling = external org.gradle.jvm.version = ${JavaVersion.current().majorVersion} ] @@ -2221,7 +2221,7 @@ org:foo -> $selected Requested attributes not found in the selected variant: org.gradle.dependency.bundling = external - org.gradle.jvm.version = ${JavaVersion.current().majorVersion} + org.gradle.jvm.version = ${JavaVersion.current().majorVersion} ] Selection reasons: - By constraint : ${rejected}${reason} diff --git a/subprojects/diagnostics/src/integTest/groovy/org/gradle/api/tasks/diagnostics/DependencyInsightReportVariantDetailsIntegrationTest.groovy b/subprojects/diagnostics/src/integTest/groovy/org/gradle/api/tasks/diagnostics/DependencyInsightReportVariantDetailsIntegrationTest.groovy index f5167e976210c..e3faacd973470 100644 --- a/subprojects/diagnostics/src/integTest/groovy/org/gradle/api/tasks/diagnostics/DependencyInsightReportVariantDetailsIntegrationTest.groovy +++ b/subprojects/diagnostics/src/integTest/groovy/org/gradle/api/tasks/diagnostics/DependencyInsightReportVariantDetailsIntegrationTest.groovy @@ -56,7 +56,7 @@ class DependencyInsightReportVariantDetailsIntegrationTest extends AbstractInteg outputContains """project :$expectedProject variant "$expectedVariant" [ $expectedAttributes - org.gradle.dependency.bundling = external (not requested) + org.gradle.dependency.bundling = external org.gradle.jvm.version = ${JavaVersion.current().majorVersion} ] @@ -108,8 +108,8 @@ project :$expectedProject org.gradle.status = release (not requested) Requested attributes not found in the selected variant: - org.gradle.blah = something org.gradle.dependency.bundling = external + org.gradle.blah = something org.gradle.jvm.version = ${JavaVersion.current().majorVersion} ] diff --git a/subprojects/docs/src/samples/java-feature-variant/requiring-features/runtimeClasspath.out b/subprojects/docs/src/samples/java-feature-variant/requiring-features/runtimeClasspath.out index 13c8f3b6deeec..d84a70464a743 100644 --- a/subprojects/docs/src/samples/java-feature-variant/requiring-features/runtimeClasspath.out +++ b/subprojects/docs/src/samples/java-feature-variant/requiring-features/runtimeClasspath.out @@ -2,9 +2,9 @@ > Task :consumer:dependencyInsight mysql:mysql-connector-java:8.0.14 variant "runtime" [ - org.gradle.status = release (not requested) - org.gradle.usage = java-runtime - org.gradle.component.category = library (not requested) + org.gradle.status = release (not requested) + org.gradle.usage = java-runtime + org.gradle.component.category = library (not requested) Requested attributes not found in the selected variant: org.gradle.dependency.bundling = external diff --git a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/maven/MavenJavaModule.groovy b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/maven/MavenJavaModule.groovy index 3a38b4aa508f3..e711eac30a15a 100644 --- a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/maven/MavenJavaModule.groovy +++ b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/maven/MavenJavaModule.groovy @@ -17,7 +17,7 @@ package org.gradle.test.fixtures.maven import org.gradle.api.JavaVersion -import org.gradle.api.attributes.java.Bundling +import org.gradle.api.attributes.Bundling import org.gradle.api.attributes.java.TargetJvmVersion import org.gradle.test.fixtures.PublishedJavaModule import org.gradle.util.GUtil diff --git a/subprojects/plugins/src/integTest/groovy/org/gradle/java/JavaLibraryCrossProjectTargetPlatformIntegrationTest.groovy b/subprojects/plugins/src/integTest/groovy/org/gradle/java/JavaLibraryCrossProjectTargetJvmVersionIntegrationTest.groovy similarity index 92% rename from subprojects/plugins/src/integTest/groovy/org/gradle/java/JavaLibraryCrossProjectTargetPlatformIntegrationTest.groovy rename to subprojects/plugins/src/integTest/groovy/org/gradle/java/JavaLibraryCrossProjectTargetJvmVersionIntegrationTest.groovy index 9f1b69d55fd14..2a1eedd9b1702 100644 --- a/subprojects/plugins/src/integTest/groovy/org/gradle/java/JavaLibraryCrossProjectTargetPlatformIntegrationTest.groovy +++ b/subprojects/plugins/src/integTest/groovy/org/gradle/java/JavaLibraryCrossProjectTargetJvmVersionIntegrationTest.groovy @@ -20,7 +20,7 @@ import org.gradle.integtests.fixtures.AbstractIntegrationSpec import org.gradle.integtests.fixtures.resolve.ResolveTestFixture import spock.lang.Unroll -class JavaLibraryCrossProjectTargetPlatformIntegrationTest extends AbstractIntegrationSpec { +class JavaLibraryCrossProjectTargetJvmVersionIntegrationTest extends AbstractIntegrationSpec { ResolveTestFixture resolve def setup() { @@ -58,11 +58,11 @@ class JavaLibraryCrossProjectTargetPlatformIntegrationTest extends AbstractInteg then: failure.assertHasCause('''Unable to find a matching variant of project :producer: - Variant 'apiElements' capability test:producer:unspecified: - - Found org.gradle.dependency.bundling 'external' but wasn't required. + - Required org.gradle.dependency.bundling 'external' and found compatible value 'external'. - Required org.gradle.jvm.version '6' and found incompatible value '7'. - Required org.gradle.usage 'java-api' and found compatible value 'java-api-jars'. - Variant 'runtimeElements' capability test:producer:unspecified: - - Found org.gradle.dependency.bundling 'external' but wasn't required. + - Required org.gradle.dependency.bundling 'external' and found compatible value 'external'. - Required org.gradle.jvm.version '6' and found incompatible value '7'. - Required org.gradle.usage 'java-api' and found compatible value 'java-runtime-jars'.''') } @@ -140,11 +140,11 @@ class JavaLibraryCrossProjectTargetPlatformIntegrationTest extends AbstractInteg then: failure.assertHasCause("""Unable to find a matching variant of project :producer: - Variant 'apiElements' capability test:producer:unspecified: - - Found org.gradle.dependency.bundling 'external' but wasn't required. + - Required org.gradle.dependency.bundling 'external' and found compatible value 'external'. - Required org.gradle.jvm.version '6' and found incompatible value '7'. - Required org.gradle.usage 'java-api' and found compatible value 'java-api-jars'. - Variant 'runtimeElements' capability test:producer:unspecified: - - Found org.gradle.dependency.bundling 'external' but wasn't required. + - Required org.gradle.dependency.bundling 'external' and found compatible value 'external'. - Required org.gradle.jvm.version '6' and found incompatible value '7'. - Required org.gradle.usage 'java-api' and found compatible value 'java-runtime-jars'.""") diff --git a/subprojects/plugins/src/integTest/groovy/org/gradle/java/JavaLibraryPublishedTargetPlatformIntegrationTest.groovy b/subprojects/plugins/src/integTest/groovy/org/gradle/java/JavaLibraryPublishedTargetJvmVersionIntegrationTest.groovy similarity index 77% rename from subprojects/plugins/src/integTest/groovy/org/gradle/java/JavaLibraryPublishedTargetPlatformIntegrationTest.groovy rename to subprojects/plugins/src/integTest/groovy/org/gradle/java/JavaLibraryPublishedTargetJvmVersionIntegrationTest.groovy index 15e3e6d4b6517..1b79679521a32 100644 --- a/subprojects/plugins/src/integTest/groovy/org/gradle/java/JavaLibraryPublishedTargetPlatformIntegrationTest.groovy +++ b/subprojects/plugins/src/integTest/groovy/org/gradle/java/JavaLibraryPublishedTargetJvmVersionIntegrationTest.groovy @@ -21,7 +21,7 @@ import org.gradle.integtests.fixtures.resolve.ResolveTestFixture import org.gradle.test.fixtures.server.http.MavenHttpModule import spock.lang.Unroll -class JavaLibraryPublishedTargetPlatformIntegrationTest extends AbstractHttpDependencyResolutionTest { +class JavaLibraryPublishedTargetJvmVersionIntegrationTest extends AbstractHttpDependencyResolutionTest { ResolveTestFixture resolve MavenHttpModule module @@ -90,20 +90,35 @@ class JavaLibraryPublishedTargetPlatformIntegrationTest extends AbstractHttpDepe then: failure.assertHasCause('''Unable to find a matching variant of org:producer:1.0: - Variant 'apiElementsJdk6' capability org:producer:1.0: - - Found org.gradle.dependency.bundling 'external' but wasn't required. + - Required org.gradle.dependency.bundling 'external' and found compatible value 'external'. - Required org.gradle.jvm.version '5' and found incompatible value '6'. - Found org.gradle.status 'release' but wasn't required. - Required org.gradle.usage 'java-api' and found compatible value 'java-api-jars'. - Variant 'apiElementsJdk7' capability org:producer:1.0: - - Found org.gradle.dependency.bundling 'external' but wasn't required. + - Required org.gradle.dependency.bundling 'external' and found compatible value 'external'. - Required org.gradle.jvm.version '5' and found incompatible value '7'. - Found org.gradle.status 'release' but wasn't required. - Required org.gradle.usage 'java-api' and found compatible value 'java-api-jars'. - Variant 'apiElementsJdk9' capability org:producer:1.0: - - Found org.gradle.dependency.bundling 'external' but wasn't required. + - Required org.gradle.dependency.bundling 'external' and found compatible value 'external'. - Required org.gradle.jvm.version '5' and found incompatible value '9'. - Found org.gradle.status 'release' but wasn't required. - - Required org.gradle.usage 'java-api' and found compatible value 'java-api-jars'.''') + - Required org.gradle.usage 'java-api' and found compatible value 'java-api-jars'. + - Variant 'runtimeElementsJdk6' capability org:producer:1.0: + - Required org.gradle.dependency.bundling 'external' and found compatible value 'external'. + - Required org.gradle.jvm.version '5' and found incompatible value '6'. + - Found org.gradle.status 'release' but wasn't required. + - Required org.gradle.usage 'java-api' and found compatible value 'java-runtime-jars'. + - Variant 'runtimeElementsJdk7' capability org:producer:1.0: + - Required org.gradle.dependency.bundling 'external' and found compatible value 'external'. + - Required org.gradle.jvm.version '5' and found incompatible value '7'. + - Found org.gradle.status 'release' but wasn't required. + - Required org.gradle.usage 'java-api' and found compatible value 'java-runtime-jars'. + - Variant 'runtimeElementsJdk9' capability org:producer:1.0: + - Required org.gradle.dependency.bundling 'external' and found compatible value 'external'. + - Required org.gradle.jvm.version '5' and found incompatible value '9'. + - Found org.gradle.status 'release' but wasn't required. + - Required org.gradle.usage 'java-api' and found compatible value 'java-runtime-jars'.''') } @Unroll From 2be2f1b696e47cf24422d4406ee69adfcaa837ab Mon Sep 17 00:00:00 2001 From: Cedric Champeau Date: Thu, 21 Feb 2019 18:03:08 +0100 Subject: [PATCH 062/853] Add release notes --- subprojects/docs/src/docs/release/notes.md | 7 ---- .../docs/userguide/upgrading_version_5.adoc | 40 +++++++++++++++++++ 2 files changed, 40 insertions(+), 7 deletions(-) diff --git a/subprojects/docs/src/docs/release/notes.md b/subprojects/docs/src/docs/release/notes.md index c51b8ac9b1d2b..2631a950603ab 100644 --- a/subprojects/docs/src/docs/release/notes.md +++ b/subprojects/docs/src/docs/release/notes.md @@ -100,13 +100,6 @@ The method `ProjectLayout.configurableFiles()` is now deprecated, and will be re ### Breaking changes -#### Bugfixes in platform resolution - -There was a bug from Gradle 5.0 to 5.2.1 (included) where enforced platforms would potentially include dependencies instead of constraints. -This would happen whenever a POM file defined both dependencies and "constraints" (via ``) and that you used `enforcedPlatform`. -Gradle 5.3 fixes this bug, meaning that you might have differences in the resolution result if you relied on this broken behavior. -Similarly, Gradle 5.3 will no longer try to download jars for `platform` and `enforcedPlatform` dependencies (as they should only bring in constraints). - See the [Gradle 5.x upgrade guide](userguide/upgrading_version_5.html#changes_5.3) to learn about breaking changes and considerations when upgrading to Gradle 5.3. diff --git a/subprojects/docs/src/docs/userguide/upgrading_version_5.adoc b/subprojects/docs/src/docs/userguide/upgrading_version_5.adoc index a25148fb7cf89..5e38c34966fbb 100644 --- a/subprojects/docs/src/docs/userguide/upgrading_version_5.adoc +++ b/subprojects/docs/src/docs/userguide/upgrading_version_5.adoc @@ -33,6 +33,46 @@ Some plugins will break with this new version of Gradle, for example because the . Run `gradle wrapper --gradle-version {gradleVersion}` to update the project to {gradleVersion}. . Try to run the project and debug any errors using the <>. +[[changes_5.3]] +== Upgrading from 5.2 and earlier + +=== Potential breaking changes + +==== Bugfixes in platform resolution + +There was a bug from Gradle 5.0 to 5.2.1 (included) where enforced platforms would potentially include dependencies instead of constraints. +This would happen whenever a POM file defined both dependencies and "constraints" (via ``) and that you used `enforcedPlatform`. +Gradle 5.3 fixes this bug, meaning that you might have differences in the resolution result if you relied on this broken behavior. +Similarly, Gradle 5.3 will no longer try to download jars for `platform` and `enforcedPlatform` dependencies (as they should only bring in constraints). + +==== Automatic target JVM version + +If you apply any of the Java plugins, Gradle will now do its best to select dependencies which match the target compatibility of the module being compiled. +What it means, in practice, is that if you have module A built for Java 8, and module B built for Java 8, then there's no change. +However if B is built for Java 9+, then it's not binary compatible anymore, and Gradle would complain with an error message like the following: + +``` +Unable to find a matching variant of project :producer: + - Variant 'apiElements' capability test:producer:unspecified: + - Required org.gradle.dependency.bundling 'external' and found compatible value 'external'. + - Required org.gradle.jvm.version '8' and found incompatible value '9'. + - Required org.gradle.usage 'java-api' and found compatible value 'java-api-jars'. + - Variant 'runtimeElements' capability test:producer:unspecified: + - Required org.gradle.dependency.bundling 'external' and found compatible value 'external'. + - Required org.gradle.jvm.version '8' and found incompatible value '9'. + - Required org.gradle.usage 'java-api' and found compatible value 'java-runtime-jars'. +``` + +In general, this is a sign that your project is misconfigured and that your dependencies are not compatible. +However, there are cases where you still may want to do this, for example when only a _subset_ of classes of your module actually need the Java 9 dependencies, and are not intended to be used on earlier releases. +Java in general doesn't encourage you to do this (you should split your module instead), but if you face this problem, you can workaround by disabling this new behavior on the consumer side: + +``` +java { + disableAutoTargetJvm() +} +``` + [[changes_5.2]] == Upgrading from 5.1 and earlier From b4b060b9ee222033452f5937efff616ec69ee319 Mon Sep 17 00:00:00 2001 From: Cedric Champeau Date: Thu, 21 Feb 2019 20:57:15 +0100 Subject: [PATCH 063/853] Fix test when running on JDK 8 --- ...JavaLibraryCrossProjectTargetJvmVersionIntegrationTest.groovy | 1 + 1 file changed, 1 insertion(+) diff --git a/subprojects/plugins/src/integTest/groovy/org/gradle/java/JavaLibraryCrossProjectTargetJvmVersionIntegrationTest.groovy b/subprojects/plugins/src/integTest/groovy/org/gradle/java/JavaLibraryCrossProjectTargetJvmVersionIntegrationTest.groovy index 2a1eedd9b1702..d15ba6e8bb268 100644 --- a/subprojects/plugins/src/integTest/groovy/org/gradle/java/JavaLibraryCrossProjectTargetJvmVersionIntegrationTest.groovy +++ b/subprojects/plugins/src/integTest/groovy/org/gradle/java/JavaLibraryCrossProjectTargetJvmVersionIntegrationTest.groovy @@ -72,6 +72,7 @@ class JavaLibraryCrossProjectTargetJvmVersionIntegrationTest extends AbstractInt file('producer/build.gradle') << """ // avoid test noise so that typically version 8 is not selected when running on JDK 8 configurations.apiElements.attributes.attribute(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE, 1000) + configurations.runtimeElements.attributes.attribute(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE, 1000) [6, 7, 9].each { v -> configurations { From bce1ed4540a73c4041fe3ada6229e56c2456389e Mon Sep 17 00:00:00 2001 From: Cedric Champeau Date: Fri, 22 Feb 2019 14:30:01 +0100 Subject: [PATCH 064/853] Optimize Java variant derivation Instead of re-creating `DefaultConfigurationMetadata` which is immediately thrown, we now make use of a mutation builder, which allows telling what mutations to perform then does all of them at once. --- .../model/AbstractConfigurationMetadata.java | 1 - .../model/DefaultConfigurationMetadata.java | 81 ++++++++++++++----- ...avaEcosystemVariantDerivationStrategy.java | 15 ++-- .../model/RealisedConfigurationMetadata.java | 8 -- 4 files changed, 71 insertions(+), 34 deletions(-) diff --git a/subprojects/dependency-management/src/main/java/org/gradle/internal/component/external/model/AbstractConfigurationMetadata.java b/subprojects/dependency-management/src/main/java/org/gradle/internal/component/external/model/AbstractConfigurationMetadata.java index a28a72c1008ae..2be6559d63ba5 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/internal/component/external/model/AbstractConfigurationMetadata.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/internal/component/external/model/AbstractConfigurationMetadata.java @@ -176,5 +176,4 @@ protected ModuleComponentIdentifier getComponentId() { return componentId; } - protected abstract ConfigurationMetadata withAttributes(ImmutableAttributes attributes); } diff --git a/subprojects/dependency-management/src/main/java/org/gradle/internal/component/external/model/DefaultConfigurationMetadata.java b/subprojects/dependency-management/src/main/java/org/gradle/internal/component/external/model/DefaultConfigurationMetadata.java index 64d1c68b127f5..27ecde618123b 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/internal/component/external/model/DefaultConfigurationMetadata.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/internal/component/external/model/DefaultConfigurationMetadata.java @@ -22,6 +22,7 @@ import org.gradle.api.capabilities.CapabilitiesMetadata; import org.gradle.api.capabilities.Capability; import org.gradle.api.internal.attributes.ImmutableAttributes; +import org.gradle.internal.Cast; import org.gradle.internal.Factory; import org.gradle.internal.component.model.DependencyMetadata; import org.gradle.internal.component.model.ExcludeMetadata; @@ -156,22 +157,10 @@ public CapabilitiesMetadata getCapabilities() { return computedCapabilities; } - public DefaultConfigurationMetadata withAttributes(ImmutableAttributes attributes) { - return new DefaultConfigurationMetadata(getComponentId(), getName(), isTransitive(), isVisible(), getHierarchy(), getArtifacts(), componentMetadataRules, getExcludes(), attributes, lazyConfigDependencies(), dependencyFilter); - } - - public DefaultConfigurationMetadata withAttributes(String newName, ImmutableAttributes attributes) { - return new DefaultConfigurationMetadata(getComponentId(), newName, isTransitive(), isVisible(), getHierarchy(), getArtifacts(), componentMetadataRules, getExcludes(), attributes, lazyConfigDependencies(), dependencyFilter); - } - public DefaultConfigurationMetadata withoutConstraints() { return new DefaultConfigurationMetadata(getComponentId(), getName(), isTransitive(), isVisible(), getHierarchy(), getArtifacts(), componentMetadataRules, getExcludes(), super.getAttributes(), lazyConfigDependencies(), dependencyFilter.dependenciesOnly()); } - public DefaultConfigurationMetadata withConstraintsOnly() { - return new DefaultConfigurationMetadata(getComponentId(), getName(), isTransitive(), isVisible(), getHierarchy(), ImmutableList.of(), componentMetadataRules, getExcludes(), super.getAttributes(), lazyConfigDependencies(), dependencyFilter.constraintsOnly()); - } - private Factory> lazyConfigDependencies() { return new Factory>() { @Nullable @@ -182,14 +171,6 @@ public List create() { }; } - public DefaultConfigurationMetadata withForcedDependencies() { - return new DefaultConfigurationMetadata(getComponentId(), getName(), isTransitive(), isVisible(), getHierarchy(), getArtifacts(), componentMetadataRules, getExcludes(), componentLevelAttributes, lazyConfigDependencies(), dependencyFilter.forcing()); - } - - public DefaultConfigurationMetadata withCapabilities(List capabilities) { - return new DefaultConfigurationMetadata(getComponentId(), getName(), isTransitive(), isVisible(), getHierarchy(), getArtifacts(), componentMetadataRules, getExcludes(), super.getAttributes(), lazyConfigDependencies(), dependencyFilter, capabilities); - } - private ImmutableList force(ImmutableList configDependencies) { ImmutableList.Builder dependencies = new ImmutableList.Builder(); for (ModuleDependencyMetadata configDependency : configDependencies) { @@ -224,6 +205,10 @@ private ImmutableList withConstraints(boolean constrai return filtered == null ? ImmutableList.of() : filtered.build(); } + Builder mutate() { + return new Builder(); + } + private enum DependencyFilter { ALL, CONSTRAINTS_ONLY, @@ -268,4 +253,60 @@ DependencyFilter constraintsOnly() { throw new IllegalStateException("Cannot set constraints only when dependencies only has already been called"); } } + + class Builder { + private String name = DefaultConfigurationMetadata.this.getName(); + private DependencyFilter dependencyFilter = DefaultConfigurationMetadata.this.dependencyFilter; + private List capabilities; + private ImmutableAttributes attributes; + private ImmutableList artifacts; + + Builder withName(String name) { + this.name = name; + return this; + } + + Builder withAttributes(ImmutableAttributes attributes) { + this.attributes = attributes; + return this; + } + + Builder withoutConstraints() { + dependencyFilter = dependencyFilter.dependenciesOnly(); + return this; + } + + Builder withForcedDependencies() { + dependencyFilter = dependencyFilter.forcing(); + return this; + } + + Builder withConstraintsOnly() { + dependencyFilter = dependencyFilter.constraintsOnly(); + artifacts = ImmutableList.of(); + return this; + } + + Builder withCapabilities(List capabilities) { + this.capabilities = capabilities; + return this; + } + + DefaultConfigurationMetadata build() { + return new DefaultConfigurationMetadata( + getComponentId(), + name, + isTransitive(), + isVisible(), + getHierarchy(), + artifacts == null ? DefaultConfigurationMetadata.this.getArtifacts() : artifacts, + componentMetadataRules, + getExcludes(), + attributes == null ? DefaultConfigurationMetadata.super.getAttributes() : attributes, + lazyConfigDependencies(), + dependencyFilter, + capabilities == null ? Cast.uncheckedCast(DefaultConfigurationMetadata.this.getCapabilities().getCapabilities()) : capabilities + ); + } + } } diff --git a/subprojects/dependency-management/src/main/java/org/gradle/internal/component/external/model/JavaEcosystemVariantDerivationStrategy.java b/subprojects/dependency-management/src/main/java/org/gradle/internal/component/external/model/JavaEcosystemVariantDerivationStrategy.java index f7e392a64d09b..ad4c671ffdf2b 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/internal/component/external/model/JavaEcosystemVariantDerivationStrategy.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/internal/component/external/model/JavaEcosystemVariantDerivationStrategy.java @@ -58,26 +58,31 @@ public ImmutableList derive(ModuleComponentReso private static ConfigurationMetadata libraryWithUsageAttribute(DefaultConfigurationMetadata conf, ImmutableAttributes originAttributes, MavenImmutableAttributesFactory attributesFactory, String usage) { ImmutableAttributes attributes = attributesFactory.libraryWithUsage(originAttributes, usage); - return conf.withAttributes(attributes).withoutConstraints(); + return conf.mutate() + .withAttributes(attributes) + .withoutConstraints() + .build(); } private static ConfigurationMetadata platformWithUsageAttribute(DefaultConfigurationMetadata conf, ImmutableAttributes originAttributes, MavenImmutableAttributesFactory attributesFactory, String usage, boolean enforcedPlatform) { ImmutableAttributes attributes = attributesFactory.platformWithUsage(originAttributes, usage, enforcedPlatform); ModuleComponentIdentifier componentId = conf.getComponentId(); String prefix = enforcedPlatform ? "enforced-platform-" : "platform-"; - DefaultConfigurationMetadata metadata = conf.withAttributes(prefix + conf.getName(), attributes); ImmutableCapability shadowed = new ImmutableCapability( componentId.getGroup(), componentId.getModule(), componentId.getVersion() ); - metadata = metadata + DefaultConfigurationMetadata.Builder builder = conf.mutate() + .withName(prefix + conf.getName()) + .withAttributes(attributes) .withConstraintsOnly() .withCapabilities(Collections.singletonList(new DefaultShadowedCapability(shadowed, "-derived-platform"))); + if (enforcedPlatform) { - metadata = metadata.withForcedDependencies(); + builder = builder.withForcedDependencies(); } - return metadata; + return builder.build(); } } diff --git a/subprojects/dependency-management/src/main/java/org/gradle/internal/component/external/model/RealisedConfigurationMetadata.java b/subprojects/dependency-management/src/main/java/org/gradle/internal/component/external/model/RealisedConfigurationMetadata.java index 7e6d1229bdfbd..2807f7ffeb7ca 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/internal/component/external/model/RealisedConfigurationMetadata.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/internal/component/external/model/RealisedConfigurationMetadata.java @@ -20,7 +20,6 @@ import com.google.common.collect.ImmutableSet; import org.gradle.api.artifacts.component.ModuleComponentIdentifier; import org.gradle.api.internal.attributes.ImmutableAttributes; -import org.gradle.internal.component.model.ConfigurationMetadata; import org.gradle.internal.component.model.DependencyMetadata; import org.gradle.internal.component.model.ExcludeMetadata; @@ -54,13 +53,6 @@ public List getDependencies() { return getConfigDependencies(); } - @Override - public ConfigurationMetadata withAttributes(ImmutableAttributes attributes) { - return new RealisedConfigurationMetadata(getComponentId(), getName(), isTransitive(), isVisible(), - getHierarchy(), ImmutableList.copyOf(getArtifacts()), getExcludes(), attributes, - ImmutableCapabilities.of(getCapabilities().getCapabilities()), getConfigDependencies()); - } - public RealisedConfigurationMetadata withDependencies(ImmutableList dependencies) { return new RealisedConfigurationMetadata( getComponentId(), From 9febfe371ffb4a308a8a4b23600bea4a8ad3c8bc Mon Sep 17 00:00:00 2001 From: Cedric Champeau Date: Fri, 22 Feb 2019 17:19:16 +0100 Subject: [PATCH 065/853] Further optimize variant derivation This commit avoids the creation of multiple shadow capabilities for the same component. We only need one, shared by all variants, because those objects are immutable. --- ...avaEcosystemVariantDerivationStrategy.java | 33 +++++++++++-------- 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/subprojects/dependency-management/src/main/java/org/gradle/internal/component/external/model/JavaEcosystemVariantDerivationStrategy.java b/subprojects/dependency-management/src/main/java/org/gradle/internal/component/external/model/JavaEcosystemVariantDerivationStrategy.java index ad4c671ffdf2b..68441f81f42c8 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/internal/component/external/model/JavaEcosystemVariantDerivationStrategy.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/internal/component/external/model/JavaEcosystemVariantDerivationStrategy.java @@ -18,12 +18,14 @@ import com.google.common.collect.ImmutableList; import org.gradle.api.artifacts.component.ModuleComponentIdentifier; import org.gradle.api.attributes.Usage; +import org.gradle.api.capabilities.Capability; import org.gradle.api.internal.artifacts.repositories.metadata.MavenImmutableAttributesFactory; import org.gradle.api.internal.attributes.ImmutableAttributes; import org.gradle.internal.component.external.model.maven.DefaultMavenModuleResolveMetadata; import org.gradle.internal.component.model.ConfigurationMetadata; import java.util.Collections; +import java.util.List; public class JavaEcosystemVariantDerivationStrategy implements VariantDerivationStrategy { @Override @@ -39,6 +41,8 @@ public ImmutableList derive(ModuleComponentReso MavenImmutableAttributesFactory attributesFactory = (MavenImmutableAttributesFactory) md.getAttributesFactory(); DefaultConfigurationMetadata compileConfiguration = (DefaultConfigurationMetadata) md.getConfiguration("compile"); DefaultConfigurationMetadata runtimeConfiguration = (DefaultConfigurationMetadata) md.getConfiguration("runtime"); + ModuleComponentIdentifier componentId = md.getId(); + List shadowedPlatformCapability = buildShadowPlatformCapability(componentId); return ImmutableList.of( // When deriving variants for the Java ecosystem, we actually have 2 components "mixed together": the library and the platform // and there's no way to figure out what was the intent when it was published. So we derive variants, but we also need @@ -48,14 +52,24 @@ public ImmutableList derive(ModuleComponentReso // component we cannot mix precise usages with more generic ones) libraryWithUsageAttribute(compileConfiguration, attributes, attributesFactory, Usage.JAVA_API), libraryWithUsageAttribute(runtimeConfiguration, attributes, attributesFactory, Usage.JAVA_RUNTIME), - platformWithUsageAttribute(compileConfiguration, attributes, attributesFactory, Usage.JAVA_API, false), - platformWithUsageAttribute(runtimeConfiguration, attributes, attributesFactory, Usage.JAVA_RUNTIME, false), - platformWithUsageAttribute(compileConfiguration, attributes, attributesFactory, Usage.JAVA_API, true), - platformWithUsageAttribute(runtimeConfiguration, attributes, attributesFactory, Usage.JAVA_RUNTIME, true)); + platformWithUsageAttribute(compileConfiguration, attributes, attributesFactory, Usage.JAVA_API, false, shadowedPlatformCapability), + platformWithUsageAttribute(runtimeConfiguration, attributes, attributesFactory, Usage.JAVA_RUNTIME, false, shadowedPlatformCapability), + platformWithUsageAttribute(compileConfiguration, attributes, attributesFactory, Usage.JAVA_API, true, shadowedPlatformCapability), + platformWithUsageAttribute(runtimeConfiguration, attributes, attributesFactory, Usage.JAVA_RUNTIME, true, shadowedPlatformCapability)); } return null; } + private List buildShadowPlatformCapability(ModuleComponentIdentifier componentId) { + return Collections.singletonList( + new DefaultShadowedCapability(new ImmutableCapability( + componentId.getGroup(), + componentId.getModule(), + componentId.getVersion() + ), "-derived-platform") + ); + } + private static ConfigurationMetadata libraryWithUsageAttribute(DefaultConfigurationMetadata conf, ImmutableAttributes originAttributes, MavenImmutableAttributesFactory attributesFactory, String usage) { ImmutableAttributes attributes = attributesFactory.libraryWithUsage(originAttributes, usage); return conf.mutate() @@ -64,21 +78,14 @@ private static ConfigurationMetadata libraryWithUsageAttribute(DefaultConfigurat .build(); } - private static ConfigurationMetadata platformWithUsageAttribute(DefaultConfigurationMetadata conf, ImmutableAttributes originAttributes, MavenImmutableAttributesFactory attributesFactory, String usage, boolean enforcedPlatform) { + private static ConfigurationMetadata platformWithUsageAttribute(DefaultConfigurationMetadata conf, ImmutableAttributes originAttributes, MavenImmutableAttributesFactory attributesFactory, String usage, boolean enforcedPlatform, List shadowedPlatformCapability) { ImmutableAttributes attributes = attributesFactory.platformWithUsage(originAttributes, usage, enforcedPlatform); - ModuleComponentIdentifier componentId = conf.getComponentId(); String prefix = enforcedPlatform ? "enforced-platform-" : "platform-"; - ImmutableCapability shadowed = new ImmutableCapability( - componentId.getGroup(), - componentId.getModule(), - componentId.getVersion() - ); DefaultConfigurationMetadata.Builder builder = conf.mutate() .withName(prefix + conf.getName()) .withAttributes(attributes) .withConstraintsOnly() - .withCapabilities(Collections.singletonList(new DefaultShadowedCapability(shadowed, "-derived-platform"))); - + .withCapabilities(shadowedPlatformCapability); if (enforcedPlatform) { builder = builder.withForcedDependencies(); } From a96e700cde030c2fd3ab31a64e0e8e84585efd48 Mon Sep 17 00:00:00 2001 From: "Rodrigo B. de Oliveira" Date: Fri, 22 Feb 2019 16:20:47 -0300 Subject: [PATCH 066/853] Replace usages of `ASM6` with `ASM_LEVEL` Fixes #8533 Signed-off-by: Rodrigo B. de Oliveira --- .../ProjectSchemaAccessorsIntegrationTest.kt | 68 +++++++++++++++++++ .../kotlin/dsl/accessors/AccessorFragment.kt | 5 +- .../dsl/accessors/AccessorsClassPath.kt | 13 ++-- .../kotlin/dsl/codegen/ApiTypeProvider.kt | 15 ++-- 4 files changed, 87 insertions(+), 14 deletions(-) diff --git a/subprojects/kotlin-dsl-integ-tests/src/integTest/kotlin/org/gradle/kotlin/dsl/integration/ProjectSchemaAccessorsIntegrationTest.kt b/subprojects/kotlin-dsl-integ-tests/src/integTest/kotlin/org/gradle/kotlin/dsl/integration/ProjectSchemaAccessorsIntegrationTest.kt index 9e909f732c937..3b3921c8f20e9 100644 --- a/subprojects/kotlin-dsl-integ-tests/src/integTest/kotlin/org/gradle/kotlin/dsl/integration/ProjectSchemaAccessorsIntegrationTest.kt +++ b/subprojects/kotlin-dsl-integ-tests/src/integTest/kotlin/org/gradle/kotlin/dsl/integration/ProjectSchemaAccessorsIntegrationTest.kt @@ -16,9 +16,12 @@ package org.gradle.kotlin.dsl.integration +import org.gradle.api.JavaVersion + import org.gradle.kotlin.dsl.fixtures.FoldersDsl import org.gradle.kotlin.dsl.fixtures.FoldersDslExpression import org.gradle.kotlin.dsl.fixtures.containsMultiLineString + import org.gradle.test.fixtures.file.LeaksFileHandles import org.hamcrest.CoreMatchers.allOf @@ -26,6 +29,7 @@ import org.hamcrest.CoreMatchers.containsString import org.hamcrest.CoreMatchers.not import org.hamcrest.MatcherAssert.assertThat +import org.junit.Assume.assumeTrue import org.junit.Ignore import org.junit.Test @@ -1141,6 +1145,70 @@ class ProjectSchemaAccessorsIntegrationTest : AbstractPluginIntegrationTest() { } } + @Test + fun `can access project extension of nested type compiled to Java 11`() { + + assumeJava11() + + withFolders { + "buildSrc" { + "src/main/java/build" { + withFile("Java11Plugin.java", """ + package build; + + import org.gradle.api.*; + + public class Java11Plugin implements Plugin { + + public static class Java11Extension {} + + @Override public void apply(Project project) { + project.getExtensions().create("java11", Java11Extension.class); + } + } + """) + } + withFile("settings.gradle.kts") + withFile("build.gradle.kts", """ + plugins { + `java-library` + `java-gradle-plugin` + } + + java { + sourceCompatibility = JavaVersion.VERSION_11 + targetCompatibility = JavaVersion.VERSION_11 + } + + gradlePlugin { + plugins { + register("java11") { + id = "java11" + implementationClass = "build.Java11Plugin" + } + } + } + """) + } + } + + withBuildScript(""" + plugins { id("java11") } + + java11 { println(this.javaClass.name) } + """) + + assertThat( + build("-q").output, + containsString("build.Java11Plugin${'$'}Java11Extension") + ) + } + + private + fun assumeJava11() { + assumeTrue("Test requires Java 11", JavaVersion.current().isJava11Compatible) + } + private fun withBuildSrc(contents: FoldersDslExpression) { withFolders { diff --git a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/accessors/AccessorFragment.kt b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/accessors/AccessorFragment.kt index 60ac7a03de55b..c972dbc38a691 100644 --- a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/accessors/AccessorFragment.kt +++ b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/accessors/AccessorFragment.kt @@ -19,11 +19,12 @@ package org.gradle.kotlin.dsl.accessors import kotlinx.metadata.jvm.JvmMethodSignature import kotlinx.metadata.jvm.KotlinClassMetadata +import org.gradle.internal.classanalysis.AsmConstants.ASM_LEVEL + import org.gradle.kotlin.dsl.support.bytecode.InternalName import org.jetbrains.org.objectweb.asm.ClassVisitor import org.jetbrains.org.objectweb.asm.ClassWriter -import org.jetbrains.org.objectweb.asm.Opcodes internal @@ -43,7 +44,7 @@ internal class BytecodeFragmentScope( val signature: JvmMethodSignature, writer: ClassWriter -) : ClassVisitor(Opcodes.ASM6, writer) +) : ClassVisitor(ASM_LEVEL, writer) internal diff --git a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/accessors/AccessorsClassPath.kt b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/accessors/AccessorsClassPath.kt index 358df55cb3517..5ef29bed50643 100644 --- a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/accessors/AccessorsClassPath.kt +++ b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/accessors/AccessorsClassPath.kt @@ -21,6 +21,8 @@ import org.gradle.api.internal.project.ProjectInternal import org.gradle.cache.internal.CacheKeyBuilder.CacheKeySpec +import org.gradle.internal.classanalysis.AsmConstants.ASM_LEVEL + import org.gradle.internal.classpath.ClassPath import org.gradle.internal.classpath.DefaultClassPath @@ -49,7 +51,6 @@ import org.jetbrains.org.objectweb.asm.ClassReader import org.jetbrains.org.objectweb.asm.ClassVisitor import org.jetbrains.org.objectweb.asm.Opcodes.ACC_PUBLIC import org.jetbrains.org.objectweb.asm.Opcodes.ACC_SYNTHETIC -import org.jetbrains.org.objectweb.asm.Opcodes.ASM6 import org.jetbrains.org.objectweb.asm.signature.SignatureReader import org.jetbrains.org.objectweb.asm.signature.SignatureVisitor @@ -341,13 +342,13 @@ fun classNamesFromTypeString(typeString: String): ClassNamesFromTypeString { private -class HasTypeParameterClassVisitor : ClassVisitor(ASM6) { +class HasTypeParameterClassVisitor : ClassVisitor(ASM_LEVEL) { var hasTypeParameters = false override fun visit(version: Int, access: Int, name: String, signature: String?, superName: String?, interfaces: Array?) { if (signature != null) { - SignatureReader(signature).accept(object : SignatureVisitor(ASM6) { + SignatureReader(signature).accept(object : SignatureVisitor(ASM_LEVEL) { override fun visitFormalTypeParameter(name: String) { hasTypeParameters = true } @@ -358,7 +359,7 @@ class HasTypeParameterClassVisitor : ClassVisitor(ASM6) { private -class KotlinVisibilityClassVisitor : ClassVisitor(ASM6) { +class KotlinVisibilityClassVisitor : ClassVisitor(ASM_LEVEL) { var visibility: Visibility? = null @@ -378,7 +379,7 @@ class KotlinVisibilityClassVisitor : ClassVisitor(ASM6) { private class ClassDataFromKotlinMetadataAnnotationVisitor( private val onClassData: (ProtoBuf.Class) -> Unit -) : AnnotationVisitor(ASM6) { +) : AnnotationVisitor(ASM_LEVEL) { /** * @see kotlin.Metadata.data1 @@ -408,7 +409,7 @@ class ClassDataFromKotlinMetadataAnnotationVisitor( private -class AnnotationValueCollector(val output: MutableList) : AnnotationVisitor(ASM6) { +class AnnotationValueCollector(val output: MutableList) : AnnotationVisitor(ASM_LEVEL) { override fun visit(name: String?, value: Any?) { @Suppress("unchecked_cast") output.add(value as T) diff --git a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/codegen/ApiTypeProvider.kt b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/codegen/ApiTypeProvider.kt index c8b1be3ed45aa..3800a78864029 100644 --- a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/codegen/ApiTypeProvider.kt +++ b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/codegen/ApiTypeProvider.kt @@ -16,10 +16,15 @@ package org.gradle.kotlin.dsl.codegen +import com.google.common.annotations.VisibleForTesting + import org.gradle.api.Incubating +import org.gradle.internal.classanalysis.AsmConstants.ASM_LEVEL + import org.gradle.kotlin.dsl.accessors.contains import org.gradle.kotlin.dsl.accessors.primitiveTypeStrings + import org.gradle.kotlin.dsl.support.ClassBytesRepository import org.gradle.kotlin.dsl.support.classPathBytesRepositoryFor import org.gradle.kotlin.dsl.support.unsafeLazy @@ -36,7 +41,6 @@ import org.jetbrains.org.objectweb.asm.Opcodes.ACC_PUBLIC import org.jetbrains.org.objectweb.asm.Opcodes.ACC_STATIC import org.jetbrains.org.objectweb.asm.Opcodes.ACC_SYNTHETIC import org.jetbrains.org.objectweb.asm.Opcodes.ACC_VARARGS -import org.jetbrains.org.objectweb.asm.Opcodes.ASM6 import org.jetbrains.org.objectweb.asm.Type import org.jetbrains.org.objectweb.asm.TypePath import org.jetbrains.org.objectweb.asm.signature.SignatureReader @@ -45,10 +49,9 @@ import org.jetbrains.org.objectweb.asm.tree.AnnotationNode import org.jetbrains.org.objectweb.asm.tree.ClassNode import org.jetbrains.org.objectweb.asm.tree.MethodNode -import com.google.common.annotations.VisibleForTesting - import java.io.Closeable import java.io.File + import java.util.ArrayDeque import javax.annotation.Nullable @@ -430,7 +433,7 @@ inline fun List?.has() = private -class ApiTypeClassNode : ClassNode(ASM6) { +class ApiTypeClassNode : ClassNode(ASM_LEVEL) { override fun visitSource(file: String?, debug: String?) = Unit override fun visitOuterClass(owner: String?, name: String?, desc: String?) = Unit @@ -442,7 +445,7 @@ class ApiTypeClassNode : ClassNode(ASM6) { private -abstract class BaseSignatureVisitor : SignatureVisitor(ASM6) { +abstract class BaseSignatureVisitor : SignatureVisitor(ASM_LEVEL) { val typeParameters: MutableMap> = LinkedHashMap(1) @@ -486,7 +489,7 @@ class MethodSignatureVisitor : BaseSignatureVisitor() { private -class TypeSignatureVisitor(val variance: Variance = Variance.INVARIANT) : SignatureVisitor(ASM6) { +class TypeSignatureVisitor(val variance: Variance = Variance.INVARIANT) : SignatureVisitor(ASM_LEVEL) { var isArray = false From e9878649fc5ad60a86467bf7c40c84406b3adf92 Mon Sep 17 00:00:00 2001 From: Joe Kutner Date: Tue, 15 Jan 2019 08:19:38 -0600 Subject: [PATCH 067/853] Set Xms when setting to Xmx to prevent JAVA_TOOL_OPTIONS and _JAVA_OPTIONS from defaulting Xms too high Signed-off-by: Joe Kutner --- .../groovy/org/gradle/build/GradleStartScriptGenerator.groovy | 2 +- .../src/main/java/org/gradle/api/tasks/wrapper/Wrapper.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/buildSrc/subprojects/build/src/main/groovy/org/gradle/build/GradleStartScriptGenerator.groovy b/buildSrc/subprojects/build/src/main/groovy/org/gradle/build/GradleStartScriptGenerator.groovy index 2fb3c0878dc55..21d6d31b37534 100644 --- a/buildSrc/subprojects/build/src/main/groovy/org/gradle/build/GradleStartScriptGenerator.groovy +++ b/buildSrc/subprojects/build/src/main/groovy/org/gradle/build/GradleStartScriptGenerator.groovy @@ -62,7 +62,7 @@ class GradleStartScriptGenerator extends DefaultTask { generator.scriptRelPath = 'bin/gradle' generator.classpath = ["lib/${launcherJar.singleFile.name}" as String] generator.appNameSystemProperty = 'org.gradle.appname' - generator.defaultJvmOpts = ["-Xmx64m"] + generator.defaultJvmOpts = ["-Xmx64m", "-Xms64m"] generator.generateUnixScript(shellScript) generator.generateWindowsScript(batchFile) } diff --git a/subprojects/build-init/src/main/java/org/gradle/api/tasks/wrapper/Wrapper.java b/subprojects/build-init/src/main/java/org/gradle/api/tasks/wrapper/Wrapper.java index 3df52e658c8bd..2757c65ed00e0 100644 --- a/subprojects/build-init/src/main/java/org/gradle/api/tasks/wrapper/Wrapper.java +++ b/subprojects/build-init/src/main/java/org/gradle/api/tasks/wrapper/Wrapper.java @@ -131,7 +131,7 @@ void generate() { generator.setExitEnvironmentVar("GRADLE_EXIT_CONSOLE"); generator.setAppNameSystemProperty("org.gradle.appname"); generator.setScriptRelPath(unixScript.getName()); - generator.setDefaultJvmOpts(ImmutableList.of("-Xmx64m")); + generator.setDefaultJvmOpts(ImmutableList.of("-Xmx64m", "-Xms64m")); generator.generateUnixScript(unixScript); generator.generateWindowsScript(getBatchScript()); } From 9fe162659f7ad395aa036d1526d4652b63e035ed Mon Sep 17 00:00:00 2001 From: Joe Kutner Date: Mon, 4 Feb 2019 15:20:32 -0600 Subject: [PATCH 068/853] Set default Xms256m when setting Xmx in DaemonParameters. See #8182 Signed-off-by: Joe Kutner --- .../launcher/daemon/configuration/DaemonParameters.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/configuration/DaemonParameters.java b/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/configuration/DaemonParameters.java index dee2aa6c0fec1..e644fce4ecda1 100644 --- a/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/configuration/DaemonParameters.java +++ b/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/configuration/DaemonParameters.java @@ -35,8 +35,8 @@ public class DaemonParameters { static final int DEFAULT_IDLE_TIMEOUT = 3 * 60 * 60 * 1000; public static final int DEFAULT_PERIODIC_CHECK_INTERVAL_MILLIS = 10 * 1000; - public static final List DEFAULT_JVM_ARGS = ImmutableList.of("-Xmx512m", "-XX:MaxPermSize=256m", "-XX:+HeapDumpOnOutOfMemoryError"); - public static final List DEFAULT_JVM_8_ARGS = ImmutableList.of("-Xmx512m", "-XX:MaxMetaspaceSize=256m", "-XX:+HeapDumpOnOutOfMemoryError"); + public static final List DEFAULT_JVM_ARGS = ImmutableList.of("-Xmx512m", "-Xms256m", "-XX:MaxPermSize=256m", "-XX:+HeapDumpOnOutOfMemoryError"); + public static final List DEFAULT_JVM_8_ARGS = ImmutableList.of("-Xmx512m", "-Xms256m", "-XX:MaxMetaspaceSize=256m", "-XX:+HeapDumpOnOutOfMemoryError"); public static final List ALLOW_ENVIRONMENT_VARIABLE_OVERWRITE = ImmutableList.of("--add-opens", "java.base/java.util=ALL-UNNAMED"); private final File gradleUserHomeDir; From 47f6860e8beed58fc3373d132fdb56b2d6826c86 Mon Sep 17 00:00:00 2001 From: Gary Hale Date: Wed, 20 Feb 2019 09:45:59 -0500 Subject: [PATCH 069/853] Add test for default min/max heap settings --- ...emonSystemPropertiesIntegrationTest.groovy | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/subprojects/launcher/src/integTest/groovy/org/gradle/launcher/daemon/DaemonSystemPropertiesIntegrationTest.groovy b/subprojects/launcher/src/integTest/groovy/org/gradle/launcher/daemon/DaemonSystemPropertiesIntegrationTest.groovy index bf49ed8e6aba1..5b3665bf918df 100644 --- a/subprojects/launcher/src/integTest/groovy/org/gradle/launcher/daemon/DaemonSystemPropertiesIntegrationTest.groovy +++ b/subprojects/launcher/src/integTest/groovy/org/gradle/launcher/daemon/DaemonSystemPropertiesIntegrationTest.groovy @@ -19,6 +19,7 @@ package org.gradle.launcher.daemon import org.gradle.cache.internal.HeapProportionalCacheSizer import org.gradle.integtests.fixtures.daemon.DaemonIntegrationSpec import spock.lang.Issue +import spock.lang.Unroll @Issue("GRADLE-2460") class DaemonSystemPropertiesIntegrationTest extends DaemonIntegrationSpec { @@ -230,6 +231,42 @@ task verify { daemons(gradleVersion).daemons.size() == 2 } + @Unroll + def "uses defaults for max/min heap size when JAVA_TOOL_OPTIONS is set (#javaToolOptions)"() { + setup: + executer.requireGradleDistribution() + + buildScript """ + import java.lang.management.ManagementFactory + import java.lang.management.MemoryMXBean + + println "GRADLE_VERSION: " + gradle.gradleVersion + + task verify { + doFirst { + MemoryMXBean memBean = ManagementFactory.getMemoryMXBean() + println "Initial Heap: " + memBean.heapMemoryUsage.init + assert memBean.heapMemoryUsage.init == 256 * 1024 * 1024 + println " Max Heap: " + memBean.heapMemoryUsage.max + assert memBean.heapMemoryUsage.max == 512 * 1024 * 1024 + } + } + """ + + when: + // This prevents the executer fixture from adding "default" values to the build jvm options + executer.useOnlyRequestedJvmOpts() + executer.withEnvironmentVars(JAVA_TOOL_OPTIONS: javaToolOptions) + run "verify" + + then: + String gradleVersion = (output =~ /GRADLE_VERSION: (.*)/)[0][1] + daemons(gradleVersion).daemons.size() == 1 + + where: + javaToolOptions << ["-Xms513m", "-Xmx255m", "-Xms128m -Xmx256m"] + } + String tempFolder(String folderName) { def dir = temporaryFolder.createDir(folderName) dir.mkdirs(); From 70f216d02fa7bb1188fadff9eeaedadaa4d91761 Mon Sep 17 00:00:00 2001 From: Gary Hale Date: Wed, 20 Feb 2019 15:31:59 -0500 Subject: [PATCH 070/853] Fix heap assertions to handle max reported by Java8 --- .../DaemonSystemPropertiesIntegrationTest.groovy | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/subprojects/launcher/src/integTest/groovy/org/gradle/launcher/daemon/DaemonSystemPropertiesIntegrationTest.groovy b/subprojects/launcher/src/integTest/groovy/org/gradle/launcher/daemon/DaemonSystemPropertiesIntegrationTest.groovy index 5b3665bf918df..03a60a0239cdd 100644 --- a/subprojects/launcher/src/integTest/groovy/org/gradle/launcher/daemon/DaemonSystemPropertiesIntegrationTest.groovy +++ b/subprojects/launcher/src/integTest/groovy/org/gradle/launcher/daemon/DaemonSystemPropertiesIntegrationTest.groovy @@ -16,6 +16,7 @@ package org.gradle.launcher.daemon +import org.gradle.api.JavaVersion import org.gradle.cache.internal.HeapProportionalCacheSizer import org.gradle.integtests.fixtures.daemon.DaemonIntegrationSpec import spock.lang.Issue @@ -235,6 +236,7 @@ task verify { def "uses defaults for max/min heap size when JAVA_TOOL_OPTIONS is set (#javaToolOptions)"() { setup: executer.requireGradleDistribution() + boolean java9orAbove = JavaVersion.current().java9Compatible buildScript """ import java.lang.management.ManagementFactory @@ -248,7 +250,13 @@ task verify { println "Initial Heap: " + memBean.heapMemoryUsage.init assert memBean.heapMemoryUsage.init == 256 * 1024 * 1024 println " Max Heap: " + memBean.heapMemoryUsage.max - assert memBean.heapMemoryUsage.max == 512 * 1024 * 1024 + + // Java 8 does not report max heap size exactly matching the command line setting + if ($java9orAbove) { + assert memBean.heapMemoryUsage.max == 512 * 1024 * 1024 + } else { + assert memBean.heapMemoryUsage.max > 256 * 1024 * 1024 + } } } """ From b3f9768cce6dd5d3a6a91daeec23998130c43898 Mon Sep 17 00:00:00 2001 From: Gary Hale Date: Thu, 21 Feb 2019 10:32:40 -0500 Subject: [PATCH 071/853] Add min heap setting for forked executers --- .../integtests/fixtures/executer/AbstractGradleExecuter.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/AbstractGradleExecuter.java b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/AbstractGradleExecuter.java index be581297b5a4d..17c518eec01b6 100644 --- a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/AbstractGradleExecuter.java +++ b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/AbstractGradleExecuter.java @@ -519,8 +519,10 @@ protected List getImplicitBuildJvmArgs() { } if (isSharedDaemons()) { + buildJvmOpts.add("-Xms256m"); buildJvmOpts.add("-Xmx1024m"); } else { + buildJvmOpts.add("-Xms256m"); buildJvmOpts.add("-Xmx512m"); } if (JVM_VERSION_DETECTOR.getJavaVersion(Jvm.forHome(getJavaHome())).compareTo(JavaVersion.VERSION_1_8) < 0) { From 57e466e3b39e3af9a80daf3cff0e5d39c9f42a1e Mon Sep 17 00:00:00 2001 From: Gary Hale Date: Thu, 21 Feb 2019 11:58:28 -0500 Subject: [PATCH 072/853] Add minimum heap setting for test --- .../launcher/daemon/DaemonReportStatusIntegrationSpec.groovy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subprojects/launcher/src/integTest/groovy/org/gradle/launcher/daemon/DaemonReportStatusIntegrationSpec.groovy b/subprojects/launcher/src/integTest/groovy/org/gradle/launcher/daemon/DaemonReportStatusIntegrationSpec.groovy index 1b0c63c882477..238559a0fd8cc 100644 --- a/subprojects/launcher/src/integTest/groovy/org/gradle/launcher/daemon/DaemonReportStatusIntegrationSpec.groovy +++ b/subprojects/launcher/src/integTest/groovy/org/gradle/launcher/daemon/DaemonReportStatusIntegrationSpec.groovy @@ -53,7 +53,7 @@ task block { block.waitForAllPendingCalls() daemons.daemon.assertBusy() - executer.withBuildJvmOpts('-Xmx128m') + executer.withBuildJvmOpts('-Xms64m', '-Xmx128m') executer.run() when: From 739e70d536f06e2c75f516e8a1cf0a5dca805fa1 Mon Sep 17 00:00:00 2001 From: Gary Hale Date: Fri, 22 Feb 2019 13:10:06 -0500 Subject: [PATCH 073/853] Move test to more appropriate class --- .../DaemonJvmSettingsIntegrationTest.groovy | 45 +++++++++++++++++++ .../DaemonReportStatusIntegrationSpec.groovy | 3 +- ...emonSystemPropertiesIntegrationTest.groovy | 45 ------------------- 3 files changed, 47 insertions(+), 46 deletions(-) diff --git a/subprojects/launcher/src/integTest/groovy/org/gradle/launcher/daemon/DaemonJvmSettingsIntegrationTest.groovy b/subprojects/launcher/src/integTest/groovy/org/gradle/launcher/daemon/DaemonJvmSettingsIntegrationTest.groovy index 20fb4e78b764c..ef79793a1dd5b 100644 --- a/subprojects/launcher/src/integTest/groovy/org/gradle/launcher/daemon/DaemonJvmSettingsIntegrationTest.groovy +++ b/subprojects/launcher/src/integTest/groovy/org/gradle/launcher/daemon/DaemonJvmSettingsIntegrationTest.groovy @@ -16,9 +16,11 @@ package org.gradle.launcher.daemon +import org.gradle.api.JavaVersion import org.gradle.integtests.fixtures.daemon.DaemonIntegrationSpec import org.gradle.util.Requires import org.gradle.util.TestPrecondition +import spock.lang.Unroll @Requires(TestPrecondition.NOT_UNKNOWN_OS) class DaemonJvmSettingsIntegrationTest extends DaemonIntegrationSpec { @@ -34,4 +36,47 @@ assert java.lang.management.ManagementFactory.runtimeMXBean.inputArguments.conta expect: succeeds() } + + @Unroll + def "uses defaults for max/min heap size when JAVA_TOOL_OPTIONS is set (#javaToolOptions)"() { + setup: + executer.requireGradleDistribution() + boolean java9orAbove = JavaVersion.current().java9Compatible + + buildScript """ + import java.lang.management.ManagementFactory + import java.lang.management.MemoryMXBean + + println "GRADLE_VERSION: " + gradle.gradleVersion + + task verify { + doFirst { + MemoryMXBean memBean = ManagementFactory.getMemoryMXBean() + println "Initial Heap: " + memBean.heapMemoryUsage.init + assert memBean.heapMemoryUsage.init == 256 * 1024 * 1024 + println " Max Heap: " + memBean.heapMemoryUsage.max + + // Java 8 does not report max heap size exactly matching the command line setting + if ($java9orAbove) { + assert memBean.heapMemoryUsage.max == 512 * 1024 * 1024 + } else { + assert memBean.heapMemoryUsage.max > 256 * 1024 * 1024 + } + } + } + """ + + when: + // This prevents the executer fixture from adding "default" values to the build jvm options + executer.useOnlyRequestedJvmOpts() + executer.withEnvironmentVars(JAVA_TOOL_OPTIONS: javaToolOptions) + run "verify" + + then: + String gradleVersion = (output =~ /GRADLE_VERSION: (.*)/)[0][1] + daemons(gradleVersion).daemons.size() == 1 + + where: + javaToolOptions << ["-Xms513m", "-Xmx255m", "-Xms128m -Xmx256m"] + } } diff --git a/subprojects/launcher/src/integTest/groovy/org/gradle/launcher/daemon/DaemonReportStatusIntegrationSpec.groovy b/subprojects/launcher/src/integTest/groovy/org/gradle/launcher/daemon/DaemonReportStatusIntegrationSpec.groovy index 238559a0fd8cc..e82c31576fc6f 100644 --- a/subprojects/launcher/src/integTest/groovy/org/gradle/launcher/daemon/DaemonReportStatusIntegrationSpec.groovy +++ b/subprojects/launcher/src/integTest/groovy/org/gradle/launcher/daemon/DaemonReportStatusIntegrationSpec.groovy @@ -53,7 +53,8 @@ task block { block.waitForAllPendingCalls() daemons.daemon.assertBusy() - executer.withBuildJvmOpts('-Xms64m', '-Xmx128m') + executer.useOnlyRequestedJvmOpts() + executer.withBuildJvmOpts('-Xmx128m') executer.run() when: diff --git a/subprojects/launcher/src/integTest/groovy/org/gradle/launcher/daemon/DaemonSystemPropertiesIntegrationTest.groovy b/subprojects/launcher/src/integTest/groovy/org/gradle/launcher/daemon/DaemonSystemPropertiesIntegrationTest.groovy index 03a60a0239cdd..bf49ed8e6aba1 100644 --- a/subprojects/launcher/src/integTest/groovy/org/gradle/launcher/daemon/DaemonSystemPropertiesIntegrationTest.groovy +++ b/subprojects/launcher/src/integTest/groovy/org/gradle/launcher/daemon/DaemonSystemPropertiesIntegrationTest.groovy @@ -16,11 +16,9 @@ package org.gradle.launcher.daemon -import org.gradle.api.JavaVersion import org.gradle.cache.internal.HeapProportionalCacheSizer import org.gradle.integtests.fixtures.daemon.DaemonIntegrationSpec import spock.lang.Issue -import spock.lang.Unroll @Issue("GRADLE-2460") class DaemonSystemPropertiesIntegrationTest extends DaemonIntegrationSpec { @@ -232,49 +230,6 @@ task verify { daemons(gradleVersion).daemons.size() == 2 } - @Unroll - def "uses defaults for max/min heap size when JAVA_TOOL_OPTIONS is set (#javaToolOptions)"() { - setup: - executer.requireGradleDistribution() - boolean java9orAbove = JavaVersion.current().java9Compatible - - buildScript """ - import java.lang.management.ManagementFactory - import java.lang.management.MemoryMXBean - - println "GRADLE_VERSION: " + gradle.gradleVersion - - task verify { - doFirst { - MemoryMXBean memBean = ManagementFactory.getMemoryMXBean() - println "Initial Heap: " + memBean.heapMemoryUsage.init - assert memBean.heapMemoryUsage.init == 256 * 1024 * 1024 - println " Max Heap: " + memBean.heapMemoryUsage.max - - // Java 8 does not report max heap size exactly matching the command line setting - if ($java9orAbove) { - assert memBean.heapMemoryUsage.max == 512 * 1024 * 1024 - } else { - assert memBean.heapMemoryUsage.max > 256 * 1024 * 1024 - } - } - } - """ - - when: - // This prevents the executer fixture from adding "default" values to the build jvm options - executer.useOnlyRequestedJvmOpts() - executer.withEnvironmentVars(JAVA_TOOL_OPTIONS: javaToolOptions) - run "verify" - - then: - String gradleVersion = (output =~ /GRADLE_VERSION: (.*)/)[0][1] - daemons(gradleVersion).daemons.size() == 1 - - where: - javaToolOptions << ["-Xms513m", "-Xmx255m", "-Xms128m -Xmx256m"] - } - String tempFolder(String folderName) { def dir = temporaryFolder.createDir(folderName) dir.mkdirs(); From d373a7ce8ec459076582ea30b22e8cd55d67d6c2 Mon Sep 17 00:00:00 2001 From: Gary Hale Date: Fri, 22 Feb 2019 15:21:12 -0500 Subject: [PATCH 074/853] Mention jkutner in the release notes --- subprojects/docs/src/docs/release/notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/subprojects/docs/src/docs/release/notes.md b/subprojects/docs/src/docs/release/notes.md index 2631a950603ab..d2f77ca4463fe 100644 --- a/subprojects/docs/src/docs/release/notes.md +++ b/subprojects/docs/src/docs/release/notes.md @@ -12,6 +12,7 @@ We would like to thank the following community contributors to this release of G [Kenzie Togami](https://github.com/kenzierocks), [Ricardo Pereira](https://github.com/thc202), [Thad House](https://github.com/ThadHouse), +[Joe Kutner](https://github.com/jkutner), ... TBD ... and [Josh Soref](https://github.com/jsoref). From 964762823ef740f5f3271c39fb8620299326f5e0 Mon Sep 17 00:00:00 2001 From: Stefan Wolf Date: Fri, 22 Feb 2019 22:53:58 +0100 Subject: [PATCH 075/853] Rename all registered types to be without suffix --- ...NamesTransform.kt => AddGradleApiParameterNames.kt} | 10 +++++----- .../packaging/{MinifyTransform.kt => Minify.kt} | 8 ++++---- .../org/gradle/gradlebuild/packaging/MinifyPlugin.kt | 2 +- .../{ShadeClassesTransform.kt => ShadeClasses.kt} | 8 ++++---- .../gradle/gradlebuild/packaging/ShadedJarPlugin.kt | 2 +- gradle/wrapper/gradle-wrapper.properties | 2 +- ...tGradleSourcesTransform.kt => FindGradleSources.kt} | 6 ++---- .../kotlin/dsl/resolver/SourceDistributionProvider.kt | 9 +++------ 8 files changed, 21 insertions(+), 26 deletions(-) rename buildSrc/subprojects/kotlin-dsl/src/main/kotlin/build/{GradleApiParameterNamesTransform.kt => AddGradleApiParameterNames.kt} (96%) rename buildSrc/subprojects/packaging/src/main/kotlin/org/gradle/gradlebuild/packaging/{MinifyTransform.kt => Minify.kt} (95%) rename buildSrc/subprojects/packaging/src/main/kotlin/org/gradle/gradlebuild/packaging/{ShadeClassesTransform.kt => ShadeClasses.kt} (94%) rename subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/resolver/{ExtractGradleSourcesTransform.kt => FindGradleSources.kt} (94%) diff --git a/buildSrc/subprojects/kotlin-dsl/src/main/kotlin/build/GradleApiParameterNamesTransform.kt b/buildSrc/subprojects/kotlin-dsl/src/main/kotlin/build/AddGradleApiParameterNames.kt similarity index 96% rename from buildSrc/subprojects/kotlin-dsl/src/main/kotlin/build/GradleApiParameterNamesTransform.kt rename to buildSrc/subprojects/kotlin-dsl/src/main/kotlin/build/AddGradleApiParameterNames.kt index 9bf35ae822874..60b52596aaa19 100644 --- a/buildSrc/subprojects/kotlin-dsl/src/main/kotlin/build/GradleApiParameterNamesTransform.kt +++ b/buildSrc/subprojects/kotlin-dsl/src/main/kotlin/build/AddGradleApiParameterNames.kt @@ -67,7 +67,7 @@ fun Project.withCompileOnlyGradleApiModulesWithParameterNames(vararg gradleModul } dependencies { - registerTransform(GradleApiParameterNamesTransform::class) { + registerTransform(AddGradleApiParameterNames::class) { from.attribute(artifactType, "jar").attribute(minified, true) to.attribute(artifactType, jarWithGradleApiParameterNames) parameters { @@ -89,9 +89,9 @@ fun Project.withCompileOnlyGradleApiModulesWithParameterNames(vararg gradleModul } -@AssociatedTransformAction(GradleApiParameterNamesTransformAction::class) +@AssociatedTransformAction(AddGradleApiParameterNamesAction::class) internal -interface GradleApiParameterNamesTransform { +interface AddGradleApiParameterNames { @get:Input var publicApiIncludes: List @get:Input @@ -100,10 +100,10 @@ interface GradleApiParameterNamesTransform { internal -abstract class GradleApiParameterNamesTransformAction : TransformAction { +abstract class AddGradleApiParameterNamesAction : TransformAction { @get:TransformParameters - abstract val parameters: GradleApiParameterNamesTransform + abstract val parameters: AddGradleApiParameterNames @get:PathSensitive(PathSensitivity.NAME_ONLY) @get:InputArtifact diff --git a/buildSrc/subprojects/packaging/src/main/kotlin/org/gradle/gradlebuild/packaging/MinifyTransform.kt b/buildSrc/subprojects/packaging/src/main/kotlin/org/gradle/gradlebuild/packaging/Minify.kt similarity index 95% rename from buildSrc/subprojects/packaging/src/main/kotlin/org/gradle/gradlebuild/packaging/MinifyTransform.kt rename to buildSrc/subprojects/packaging/src/main/kotlin/org/gradle/gradlebuild/packaging/Minify.kt index 24ef1e55026cd..d17c6955396ef 100644 --- a/buildSrc/subprojects/packaging/src/main/kotlin/org/gradle/gradlebuild/packaging/MinifyTransform.kt +++ b/buildSrc/subprojects/packaging/src/main/kotlin/org/gradle/gradlebuild/packaging/Minify.kt @@ -32,16 +32,16 @@ import java.util.jar.JarFile import java.util.jar.JarOutputStream -@AssociatedTransformAction(MinifyTransformAction::class) -interface MinifyTransform { +@AssociatedTransformAction(MinifyAction::class) +interface Minify { @get:Input var keepClassesByArtifact: Map> } -abstract class MinifyTransformAction : TransformAction { +abstract class MinifyAction : TransformAction { @get:TransformParameters - abstract val parameters: MinifyTransform + abstract val parameters: Minify @get:PathSensitive(PathSensitivity.NAME_ONLY) @get:InputArtifact diff --git a/buildSrc/subprojects/packaging/src/main/kotlin/org/gradle/gradlebuild/packaging/MinifyPlugin.kt b/buildSrc/subprojects/packaging/src/main/kotlin/org/gradle/gradlebuild/packaging/MinifyPlugin.kt index 32e5c3208aa79..25136dcaba5fd 100644 --- a/buildSrc/subprojects/packaging/src/main/kotlin/org/gradle/gradlebuild/packaging/MinifyPlugin.kt +++ b/buildSrc/subprojects/packaging/src/main/kotlin/org/gradle/gradlebuild/packaging/MinifyPlugin.kt @@ -51,7 +51,7 @@ open class MinifyPlugin : Plugin { artifactTypes.getByName("jar") { attributes.attribute(minified, java.lang.Boolean.FALSE) } - registerTransform(MinifyTransform::class) { + registerTransform(Minify::class) { /* * TODO Why do I have to add artifactType=jar here? According to * the declaration above, it's the only artifact type for which diff --git a/buildSrc/subprojects/packaging/src/main/kotlin/org/gradle/gradlebuild/packaging/ShadeClassesTransform.kt b/buildSrc/subprojects/packaging/src/main/kotlin/org/gradle/gradlebuild/packaging/ShadeClasses.kt similarity index 94% rename from buildSrc/subprojects/packaging/src/main/kotlin/org/gradle/gradlebuild/packaging/ShadeClassesTransform.kt rename to buildSrc/subprojects/packaging/src/main/kotlin/org/gradle/gradlebuild/packaging/ShadeClasses.kt index 71d7778534353..20b3ebcf608d6 100644 --- a/buildSrc/subprojects/packaging/src/main/kotlin/org/gradle/gradlebuild/packaging/ShadeClassesTransform.kt +++ b/buildSrc/subprojects/packaging/src/main/kotlin/org/gradle/gradlebuild/packaging/ShadeClasses.kt @@ -43,8 +43,8 @@ private const val manifestFileName = "MANIFEST.MF" -@AssociatedTransformAction(ShadeClassesTransformAction::class) -interface ShadeClassesTransform { +@AssociatedTransformAction(ShadeClassesAction::class) +interface ShadeClasses { @get:Input var shadowPackage: String @get:Input @@ -56,10 +56,10 @@ interface ShadeClassesTransform { } -abstract class ShadeClassesTransformAction : TransformAction { +abstract class ShadeClassesAction : TransformAction { @get:TransformParameters - abstract val parameters: ShadeClassesTransform + abstract val parameters: ShadeClasses @get:Classpath @get:InputArtifact diff --git a/buildSrc/subprojects/packaging/src/main/kotlin/org/gradle/gradlebuild/packaging/ShadedJarPlugin.kt b/buildSrc/subprojects/packaging/src/main/kotlin/org/gradle/gradlebuild/packaging/ShadedJarPlugin.kt index 24c42fa8f0b6d..8fc85f071a9ca 100644 --- a/buildSrc/subprojects/packaging/src/main/kotlin/org/gradle/gradlebuild/packaging/ShadedJarPlugin.kt +++ b/buildSrc/subprojects/packaging/src/main/kotlin/org/gradle/gradlebuild/packaging/ShadedJarPlugin.kt @@ -80,7 +80,7 @@ open class ShadedJarPlugin : Plugin { fun Project.registerTransforms(shadedJarExtension: ShadedJarExtension) { afterEvaluate { dependencies { - registerTransform(ShadeClassesTransform::class) { + registerTransform(ShadeClasses::class) { from .attribute(artifactType, "jar") .attribute(minified, true) diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 0d9e4b132016f..d2182fd42d64e 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions-snapshots/gradle-5.3-20190218000054+0000-bin.zip +distributionUrl=https\://services.gradle.org/distributions-snapshots/gradle-5.3-20190222192132+0000-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/resolver/ExtractGradleSourcesTransform.kt b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/resolver/FindGradleSources.kt similarity index 94% rename from subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/resolver/ExtractGradleSourcesTransform.kt rename to subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/resolver/FindGradleSources.kt index 8aef467b9baee..1f401e8493f0b 100644 --- a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/resolver/ExtractGradleSourcesTransform.kt +++ b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/resolver/FindGradleSources.kt @@ -21,9 +21,7 @@ import org.gradle.api.artifacts.transform.TransformAction import org.gradle.api.artifacts.transform.TransformOutputs import org.gradle.api.tasks.PathSensitive import org.gradle.api.tasks.PathSensitivity - import org.gradle.kotlin.dsl.support.unzipTo - import java.io.File @@ -32,7 +30,7 @@ import java.io.File * a downloaded ZIP of the Gradle sources, and will return the list of main sources * subdirectories for all subprojects. */ -abstract class ExtractGradleSourcesTransform : TransformAction { +abstract class FindGradleSources : TransformAction { @get:InputArtifact abstract val input: File @@ -61,7 +59,7 @@ abstract class ExtractGradleSourcesTransform : TransformAction { } -abstract class UnzipDistributionTransform : TransformAction { +abstract class UnzipDistribution : TransformAction { @get:PathSensitive(PathSensitivity.NONE) @get:InputArtifact abstract val input: File diff --git a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/resolver/SourceDistributionProvider.kt b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/resolver/SourceDistributionProvider.kt index ab04c30e7398f..1bc431b8ca512 100644 --- a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/resolver/SourceDistributionProvider.kt +++ b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/resolver/SourceDistributionProvider.kt @@ -23,11 +23,8 @@ import org.gradle.api.artifacts.repositories.IvyArtifactRepository import org.gradle.api.artifacts.transform.TransformAction import org.gradle.api.artifacts.transform.TransformSpec import org.gradle.api.attributes.Attribute - -import org.gradle.kotlin.dsl.create - +import org.gradle.kotlin.dsl.* import java.io.File - import java.lang.Integer.max @@ -72,11 +69,11 @@ class SourceDistributionResolver(val project: Project) : SourceDistributionProvi private fun registerTransforms() { - registerTransformAction { + registerTransformAction { from.attribute(artifactType, zipType) to.attribute(artifactType, unzippedDistributionType) } - registerTransformAction { + registerTransformAction { from.attribute(artifactType, unzippedDistributionType) to.attribute(artifactType, sourceDirectory) } From d588d251b6898c6e34895aee93e3b9cc445c7e10 Mon Sep 17 00:00:00 2001 From: Stefan Wolf Date: Fri, 22 Feb 2019 23:05:48 +0100 Subject: [PATCH 076/853] Make ShadeClasses cacheable --- .../kotlin/org/gradle/gradlebuild/packaging/ShadeClasses.kt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/buildSrc/subprojects/packaging/src/main/kotlin/org/gradle/gradlebuild/packaging/ShadeClasses.kt b/buildSrc/subprojects/packaging/src/main/kotlin/org/gradle/gradlebuild/packaging/ShadeClasses.kt index 20b3ebcf608d6..5e99ca1a74e70 100644 --- a/buildSrc/subprojects/packaging/src/main/kotlin/org/gradle/gradlebuild/packaging/ShadeClasses.kt +++ b/buildSrc/subprojects/packaging/src/main/kotlin/org/gradle/gradlebuild/packaging/ShadeClasses.kt @@ -18,6 +18,7 @@ package org.gradle.gradlebuild.packaging import com.google.gson.Gson import org.gradle.api.artifacts.transform.AssociatedTransformAction +import org.gradle.api.artifacts.transform.CacheableTransformAction import org.gradle.api.artifacts.transform.InputArtifact import org.gradle.api.artifacts.transform.TransformAction import org.gradle.api.artifacts.transform.TransformOutputs @@ -56,6 +57,7 @@ interface ShadeClasses { } +@CacheableTransformAction abstract class ShadeClassesAction : TransformAction { @get:TransformParameters From 79a352d1c46a17a694e21617e2c40f202e2e55cc Mon Sep 17 00:00:00 2001 From: Gradleware Git Bot Date: Sat, 23 Feb 2019 02:46:40 +0100 Subject: [PATCH 077/853] Publish 5.3-20190223013127+0000 --- released-versions.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/released-versions.json b/released-versions.json index 47ca1c112af1e..bd1401fef901e 100644 --- a/released-versions.json +++ b/released-versions.json @@ -1,7 +1,7 @@ { "latestReleaseSnapshot": { - "version": "5.3-20190222192132+0000", - "buildTime": "20190222192132+0000" + "version": "5.3-20190223013127+0000", + "buildTime": "20190223013127+0000" }, "latestRc": { "version": "5.2-rc-1", From e53f444b31781bd1fd2399c75ee23f3974d53e8f Mon Sep 17 00:00:00 2001 From: blindpirate Date: Sat, 23 Feb 2019 08:48:22 +0000 Subject: [PATCH 078/853] TeamCity change in 'Gradle / Check / Ready for Release' project: requirements of 'Performance Experiment Coordinator - Linux' build configuration were updated --- ...e_Check_PerformanceExperimentCoordinator.kts | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 .teamcity/Gradle_Check/patches/buildTypes/Gradle_Check_PerformanceExperimentCoordinator.kts diff --git a/.teamcity/Gradle_Check/patches/buildTypes/Gradle_Check_PerformanceExperimentCoordinator.kts b/.teamcity/Gradle_Check/patches/buildTypes/Gradle_Check_PerformanceExperimentCoordinator.kts new file mode 100644 index 0000000000000..f9ac18b26c3fd --- /dev/null +++ b/.teamcity/Gradle_Check/patches/buildTypes/Gradle_Check_PerformanceExperimentCoordinator.kts @@ -0,0 +1,17 @@ +package Gradle_Check.patches.buildTypes + +import jetbrains.buildServer.configs.kotlin.v2018_2.* +import jetbrains.buildServer.configs.kotlin.v2018_2.ui.* + +/* +This patch script was generated by TeamCity on settings change in UI. +To apply the patch, change the buildType with uuid = 'Gradle_Check_PerformanceExperimentCoordinator' (id = 'Gradle_Check_PerformanceExperimentCoordinator') +accordingly, and delete the patch script. +*/ +changeBuildType(uuid("Gradle_Check_PerformanceExperimentCoordinator")) { + requirements { + add { + doesNotContain("teamcity.agent.name", "ec2") + } + } +} From 611346be9533b5ffc4de03234991d9958449aa12 Mon Sep 17 00:00:00 2001 From: blindpirate Date: Sat, 23 Feb 2019 08:53:05 +0000 Subject: [PATCH 079/853] TeamCity change in 'Gradle / Check / Ready for Merge' project: requirements of 'Performance Test Coordinator - Linux' build configuration were updated --- .../Gradle_Check_PerformanceTestCoordinator.kts | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 .teamcity/Gradle_Check/patches/buildTypes/Gradle_Check_PerformanceTestCoordinator.kts diff --git a/.teamcity/Gradle_Check/patches/buildTypes/Gradle_Check_PerformanceTestCoordinator.kts b/.teamcity/Gradle_Check/patches/buildTypes/Gradle_Check_PerformanceTestCoordinator.kts new file mode 100644 index 0000000000000..4fa0aa8b3c17a --- /dev/null +++ b/.teamcity/Gradle_Check/patches/buildTypes/Gradle_Check_PerformanceTestCoordinator.kts @@ -0,0 +1,17 @@ +package Gradle_Check.patches.buildTypes + +import jetbrains.buildServer.configs.kotlin.v2018_2.* +import jetbrains.buildServer.configs.kotlin.v2018_2.ui.* + +/* +This patch script was generated by TeamCity on settings change in UI. +To apply the patch, change the buildType with uuid = 'Gradle_Check_PerformanceTestCoordinator' (id = 'Gradle_Check_PerformanceTestCoordinator') +accordingly, and delete the patch script. +*/ +changeBuildType(uuid("Gradle_Check_PerformanceTestCoordinator")) { + requirements { + add { + doesNotContain("teamcity.agent.name", "ec2") + } + } +} From 7ad290b32f5bd9b55808f638b6238578134f4f49 Mon Sep 17 00:00:00 2001 From: "Rodrigo B. de Oliveira" Date: Sat, 23 Feb 2019 11:46:11 -0300 Subject: [PATCH 080/853] Dedupe `PrecompiledScriptPlugin` creation --- .../PrecompiledScriptPluginTest.kt | 63 +++++++------- ...tractPrecompiledScriptPluginPluginsTest.kt | 85 ++++++++++++------- 2 files changed, 85 insertions(+), 63 deletions(-) diff --git a/subprojects/kotlin-dsl-plugins/src/test/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPluginTest.kt b/subprojects/kotlin-dsl-plugins/src/test/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPluginTest.kt index 55fd02402654e..c2f2492f132ec 100644 --- a/subprojects/kotlin-dsl-plugins/src/test/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPluginTest.kt +++ b/subprojects/kotlin-dsl-plugins/src/test/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPluginTest.kt @@ -18,27 +18,26 @@ class PrecompiledScriptPluginTest : TestWithTempFiles() { @Test fun `plugin id is derived from script file name`() { - val script = - newFile("my-script.gradle.kts") - assertThat( - PrecompiledScriptPlugin(script).id, - equalTo("my-script")) + scriptPlugin("my-script.gradle.kts").id, + equalTo("my-script") + ) } @Test fun `plugin id is prefixed by package name if present`() { - val script = - newFile("my-script.gradle.kts", """ - - package org.acme + assertThat( + scriptPlugin( + "my-script.gradle.kts", + """ - """) + package org.acme - assertThat( - PrecompiledScriptPlugin(script).id, - equalTo("org.acme.my-script")) + """ + ).id, + equalTo("org.acme.my-script") + ) } @Test @@ -59,23 +58,22 @@ class PrecompiledScriptPluginTest : TestWithTempFiles() { private fun implementationClassForScriptNamed(fileName: String) = - PrecompiledScriptPlugin(newFile(fileName)).implementationClass + scriptPlugin(fileName).implementationClass @Test fun `plugin adapter is written to package sub-dir and starts with correct package declaration`() { - val script = - newFile("my-script.gradle.kts", """ - - package org.acme - - """) - val outputDir = root.resolve("output") - PrecompiledScriptPlugin(script) - .writeScriptPluginAdapterTo(outputDir) + scriptPlugin( + "my-script.gradle.kts", + """ + + package org.acme + + """ + ).writeScriptPluginAdapterTo(outputDir) val expectedFile = outputDir.resolve("org/acme/MyScriptPlugin.kt") @@ -88,13 +86,10 @@ class PrecompiledScriptPluginTest : TestWithTempFiles() { @Test fun `given no package declaration, plugin adapter is written directly to output dir`() { - val script = - newFile("my-script.gradle.kts") - val outputDir = root.resolve("output").apply { mkdir() } - PrecompiledScriptPlugin(script) + scriptPlugin("my-script.gradle.kts") .writeScriptPluginAdapterTo(outputDir) val expectedFile = @@ -115,14 +110,18 @@ class PrecompiledScriptPluginTest : TestWithTempFiles() { @Test fun `can extract package name from script with Windows line endings`() { - val script = - newFile("my-script.gradle.kts", "/*\r\n */\r\npackage org.acme\r\n") - assertThat( - PrecompiledScriptPlugin(script).packageName, - equalTo("org.acme")) + scriptPlugin( + "my-script.gradle.kts", + "/*\r\n */\r\npackage org.acme\r\n" + ).packageName, + equalTo("org.acme") + ) } + private + fun scriptPlugin(fileName: String, text: String = "") = PrecompiledScriptPlugin(newFile(fileName, text)) + private fun firstNonBlankLineOf(expectedFile: File) = expectedFile.bufferedReader().useLines { diff --git a/subprojects/kotlin-dsl-plugins/src/test/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/ExtractPrecompiledScriptPluginPluginsTest.kt b/subprojects/kotlin-dsl-plugins/src/test/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/ExtractPrecompiledScriptPluginPluginsTest.kt index 0d5442d3e3cca..30c4bbe72bee5 100644 --- a/subprojects/kotlin-dsl-plugins/src/test/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/ExtractPrecompiledScriptPluginPluginsTest.kt +++ b/subprojects/kotlin-dsl-plugins/src/test/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/ExtractPrecompiledScriptPluginPluginsTest.kt @@ -33,27 +33,42 @@ import java.io.File class ExtractPrecompiledScriptPluginPluginsTest : TestWithTempFiles() { - @Test - fun `extract plugins blocks and writes them to the output dir`() { + private + val outputDir by lazy { + newFolder("plugins") + } - val scriptPlugins = listOf( + @Test + fun `can extract plugins block from script with only plugins`() { - scriptPlugin("plugins-only.gradle.kts", """ + extractPluginsFrom( + scriptPlugin( + "plugins-only.gradle.kts", + """ // this comment will be removed plugins { java } // and so will the rest of the script - """), + """ + ) + ) - scriptPlugin("no-plugins.gradle.kts", """ - buildscript {} - """), + assertThat( + outputFile("plugins-only.gradle.kts").readText(), + equalToMultiLineString(""" + ${"// this comment will be removed".replacedBySpaces()} + plugins { + java + }""" + ) + ) + } - scriptPlugin("empty-plugins.gradle.kts", """ - plugins {} - """), + @Test + fun `can extract plugins block from script with a buildscript block`() { + extractPluginsFrom( // the `buildscript` block is not really valid in precompiled script plugins (causes a runtime error) // but still worth testing here scriptPlugin("buildscript-and-plugins.gradle.kts", """ @@ -62,23 +77,28 @@ class ExtractPrecompiledScriptPluginPluginsTest : TestWithTempFiles() { """) ) - val outputDir = newFolder("plugins") - extractPrecompiledScriptPluginPluginsTo( - outputDir, - scriptPlugins - ) - - fun outputFile(fileName: String) = outputDir.resolve(fileName) - assertThat( - outputFile("plugins-only.gradle.kts").readText(), + outputFile("buildscript-and-plugins.gradle.kts").readText(), equalToMultiLineString(""" - ${"// this comment will be removed".replacedBySpaces()} - plugins { - java - }""" + ${"buildscript {}".replacedBySpaces()} + plugins { java }""" ) ) + } + + @Test + fun `ignores scripts with a nonexistent or empty plugins block`() { + + extractPluginsFrom( + + scriptPlugin("no-plugins.gradle.kts", """ + buildscript {} + """), + + scriptPlugin("empty-plugins.gradle.kts", """ + plugins {} + """) + ) assertThat( outputFile("no-plugins.gradle.kts"), @@ -89,16 +109,19 @@ class ExtractPrecompiledScriptPluginPluginsTest : TestWithTempFiles() { outputFile("empty-plugins.gradle.kts"), doesNotExist() ) + } - assertThat( - outputFile("buildscript-and-plugins.gradle.kts").readText(), - equalToMultiLineString(""" - ${"buildscript {}".replacedBySpaces()} - plugins { java }""" - ) + private + fun extractPluginsFrom(vararg scriptPlugins: PrecompiledScriptPlugin) { + extractPrecompiledScriptPluginPluginsTo( + outputDir, + scriptPlugins.asList() ) } + private + fun outputFile(fileName: String) = outputDir.resolve(fileName) + private fun scriptPlugin(fileName: String, text: String) = PrecompiledScriptPlugin(newFile(fileName, text)) @@ -108,7 +131,7 @@ class ExtractPrecompiledScriptPluginPluginsTest : TestWithTempFiles() { private -fun repeat(char: Char, count: Int) = String(CharArray(count) { _ -> char }) +fun repeat(char: Char, count: Int) = String(CharArray(count) { char }) private From 726e64756d7d9d4e4c087db256f1c47f85cd4289 Mon Sep 17 00:00:00 2001 From: Paul Merlin Date: Wed, 20 Feb 2019 15:19:03 +0100 Subject: [PATCH 081/853] First cut of Kotlin support in incubation report Signed-off-by: Paul Merlin --- .../incubation/IncubatingApiReportTask.kt | 195 ++++++++++++------ .../incubation/IncubationReportPlugin.kt | 16 +- .../kotlin-dsl/kotlin-dsl.gradle.kts | 7 +- .../main/kotlin/parser/KotlinSourceParser.kt | 120 +++++++++++ 4 files changed, 269 insertions(+), 69 deletions(-) create mode 100644 buildSrc/subprojects/kotlin-dsl/src/main/kotlin/parser/KotlinSourceParser.kt diff --git a/buildSrc/subprojects/buildquality/src/main/kotlin/org/gradle/gradlebuild/buildquality/incubation/IncubatingApiReportTask.kt b/buildSrc/subprojects/buildquality/src/main/kotlin/org/gradle/gradlebuild/buildquality/incubation/IncubatingApiReportTask.kt index 00c5eafd9d5b9..c17ca82610f6f 100644 --- a/buildSrc/subprojects/buildquality/src/main/kotlin/org/gradle/gradlebuild/buildquality/incubation/IncubatingApiReportTask.kt +++ b/buildSrc/subprojects/buildquality/src/main/kotlin/org/gradle/gradlebuild/buildquality/incubation/IncubatingApiReportTask.kt @@ -29,13 +29,17 @@ import org.gradle.api.tasks.PathSensitivity import org.gradle.api.tasks.TaskAction import org.gradle.workers.IsolationMode import org.gradle.workers.WorkerExecutor +import org.jetbrains.kotlin.psi.KtCallableDeclaration +import org.jetbrains.kotlin.psi.KtNamedDeclaration +import org.jetbrains.kotlin.psi.psiUtil.collectDescendantsOfType +import parser.KotlinSourceParser import java.io.File import javax.inject.Inject @CacheableTask open class IncubatingApiReportTask - @Inject constructor(private val workerExecutor: WorkerExecutor) : DefaultTask() { +@Inject constructor(private val workerExecutor: WorkerExecutor) : DefaultTask() { @InputFile @PathSensitive(PathSensitivity.RELATIVE) @@ -87,14 +91,17 @@ class Analyzer @Inject constructor( val versionToIncubating = mutableMapOf>() srcDirs.forEach { srcDir -> if (srcDir.exists()) { - val solver = JavaSymbolSolver(CombinedTypeSolver(JavaParserTypeSolver(srcDir), ReflectionTypeSolver())) + val sourceFileParser = CompositeSourceFileParser(listOf( + JavaSourceFileParser(srcDir), + KotlinSourceFileParser(srcDir) + )) srcDir.walkTopDown().forEach { - if (it.name.endsWith(".java")) { - try { - parseJavaFile(it, versionToIncubating, solver) - } catch (e: Exception) { - println("Unable to parse $it: ${e.message}") + try { + sourceFileParser.parseSourceFile(it).forEach { (version, incubating) -> + versionToIncubating.getOrPut(version) { mutableSetOf() }.addAll(incubating) } + } catch (e: Exception) { + throw Exception("Unable to parse $it: ${e.message}") } } } @@ -103,60 +110,6 @@ class Analyzer @Inject constructor( generateHtmlReport(versionToIncubating) } - private - fun parseJavaFile(file: File, versionToIncubating: MutableMap>, solver: JavaSymbolSolver) = - JavaParser.parse(file).run { - solver.inject(this) - findAll(Node::class.java) - .filter { - it is NodeWithAnnotations<*> && - it.annotations.any { it.nameAsString == "Incubating" } - }.map { - val node = it as NodeWithAnnotations<*> - val version = findVersionFromJavadoc(node) - ?: "Not found" - Pair(version, nodeName(it, this, file)) - }.forEach { - versionToIncubating.getOrPut(it.first) { - mutableSetOf() - }.add(it.second) - } - } - - - private - fun findVersionFromJavadoc(node: NodeWithAnnotations<*>): String? = if (node is NodeWithJavadoc<*>) { - node.javadoc.map { - it.blockTags.find { - it.tagName == "since" - }?.content?.elements?.find { - it is JavadocSnippet - }?.toText() - }.orElse(null) - } else { - null - } - - private - fun nodeName(it: Node?, unit: CompilationUnit, file: File) = when (it) { - is EnumDeclaration -> tryResolve({ it.resolve().qualifiedName }) { inferClassName(unit) } - is ClassOrInterfaceDeclaration -> tryResolve({ it.resolve().qualifiedName }) { inferClassName(unit) } - is MethodDeclaration -> tryResolve({ it.resolve().qualifiedSignature }) { inferClassName(unit) } - is AnnotationDeclaration -> tryResolve({ it.resolve().qualifiedName }) { inferClassName(unit) } - is NodeWithSimpleName<*> -> it.nameAsString - else -> unit.primaryTypeName.orElse(file.name) - } - - private - fun inferClassName(unit: CompilationUnit) = "${unit.packageDeclaration.map { it.nameAsString }.orElse("")}.${unit.primaryTypeName.orElse("")}" - - private - inline fun tryResolve(resolver: () -> String, or: () -> String) = try { - resolver() - } catch (e: Throwable) { - or() - } - private fun generateHtmlReport(versionToIncubating: Map>) { htmlReportFile.parentFile.mkdirs() @@ -225,3 +178,123 @@ class Analyzer @Inject constructor( private fun String.escape() = replace("<", "<").replace(">", ">") } + + +private +typealias VersionsToIncubating = Map> + + +private +interface SourceFileParser { + + fun parseSourceFile(sourceFile: File): VersionsToIncubating +} + + +private +class CompositeSourceFileParser(private val sourceFileParsers: List) : SourceFileParser { + + override fun parseSourceFile(sourceFile: File): VersionsToIncubating = + sourceFileParsers.flatMap { it.parseSourceFile(sourceFile).entries }.associate { it.key to it.value } +} + + +private +class JavaSourceFileParser(srcDir: File) : SourceFileParser { + + private + val solver = JavaSymbolSolver(CombinedTypeSolver(JavaParserTypeSolver(srcDir), ReflectionTypeSolver())) + + override fun parseSourceFile(sourceFile: File): VersionsToIncubating { + val versionToIncubating = mutableMapOf>() + if (!sourceFile.name.endsWith(".java")) { + return versionToIncubating + } + JavaParser.parse(sourceFile).run { + solver.inject(this) + findAll(Node::class.java) + .filter { + it is NodeWithAnnotations<*> && + it.annotations.any { it.nameAsString == "Incubating" } + }.map { + val node = it as NodeWithAnnotations<*> + val version = findVersionFromJavadoc(node) + ?: "Not found" + Pair(version, nodeName(it, this, sourceFile)) + }.forEach { + versionToIncubating.getOrPut(it.first) { + mutableSetOf() + }.add(it.second) + } + } + return versionToIncubating + } + + private + fun findVersionFromJavadoc(node: NodeWithAnnotations<*>): String? = if (node is NodeWithJavadoc<*>) { + node.javadoc.map { + it.blockTags.find { + it.tagName == "since" + }?.content?.elements?.find { + it is JavadocSnippet + }?.toText() + }.orElse(null) + } else { + null + } + + private + fun nodeName(it: Node?, unit: CompilationUnit, file: File) = when (it) { + is EnumDeclaration -> tryResolve({ it.resolve().qualifiedName }) { inferClassName(unit) } + is ClassOrInterfaceDeclaration -> tryResolve({ it.resolve().qualifiedName }) { inferClassName(unit) } + is MethodDeclaration -> tryResolve({ it.resolve().qualifiedSignature }) { inferClassName(unit) } + is AnnotationDeclaration -> tryResolve({ it.resolve().qualifiedName }) { inferClassName(unit) } + is NodeWithSimpleName<*> -> it.nameAsString + else -> unit.primaryTypeName.orElse(file.name) + } + + private + fun inferClassName(unit: CompilationUnit) = "${unit.packageDeclaration.map { it.nameAsString }.orElse("")}.${unit.primaryTypeName.orElse("")}" + + private + inline fun tryResolve(resolver: () -> String, or: () -> String) = try { + resolver() + } catch (e: Throwable) { + or() + } +} + + +private +class KotlinSourceFileParser(srcDir: File) : SourceFileParser { + + override fun parseSourceFile(sourceFile: File): VersionsToIncubating { + + val versionToIncubating = mutableMapOf>() + + if (!sourceFile.name.endsWith(".kt")) { + return versionToIncubating + } + + KotlinSourceParser().mapParsedKotlinFiles(sourceFile) { ktFile -> + ktFile.collectDescendantsOfType().forEach { declaration -> + if (declaration.annotationEntries.any { it.shortName?.asString() == "Incubating" }) { + var name = (declaration as? KtCallableDeclaration)?.typeParameterList?.let { "${it.text} " } ?: "" + name += declaration.fqName!!.asString() + if (declaration is KtCallableDeclaration) { + name += declaration.valueParameterList?.text ?: "" + if (declaration.receiverTypeReference != null) { + name += " with ${declaration.receiverTypeReference!!.text} receiver" + } + if (declaration.parent == ktFile) { + name += ", top-level in ${sourceFile.name}" + } + } + val since = declaration.docComment?.getDefaultSection()?.findTagsByName("since")?.singleOrNull()?.getContent() ?: "Not found" + versionToIncubating.getOrPut(since) { mutableSetOf() }.add(name) + } + } + } + return versionToIncubating + } +} diff --git a/buildSrc/subprojects/buildquality/src/main/kotlin/org/gradle/gradlebuild/buildquality/incubation/IncubationReportPlugin.kt b/buildSrc/subprojects/buildquality/src/main/kotlin/org/gradle/gradlebuild/buildquality/incubation/IncubationReportPlugin.kt index af37536b85002..8546ce3ec63d9 100644 --- a/buildSrc/subprojects/buildquality/src/main/kotlin/org/gradle/gradlebuild/buildquality/incubation/IncubationReportPlugin.kt +++ b/buildSrc/subprojects/buildquality/src/main/kotlin/org/gradle/gradlebuild/buildquality/incubation/IncubationReportPlugin.kt @@ -17,23 +17,29 @@ package org.gradle.gradlebuild.buildquality.incubation import accessors.java +import build.kotlin import org.gradle.api.Plugin import org.gradle.api.Project import org.gradle.kotlin.dsl.* class IncubationReportPlugin : Plugin { - override fun apply(project: Project) = project.run { - val reportTask = tasks.register("incubationReport", IncubatingApiReportTask::class) { - val main by java.sourceSets + override fun apply(project: Project): Unit = project.run { + val main by java.sourceSets + val reportTask = tasks.register("incubationReport") { description = "Generates a report of incubating APIS" title.set(project.name) versionFile.set(rootProject.file("version.txt")) releasedVersionsFile.set(rootProject.file("released-versions.json")) - sources.setFrom(main.java.sourceDirectories) + sources.from(main.java.sourceDirectories) htmlReportFile.set(file("$buildDir/reports/incubation/${project.name}.html")) textReportFile.set(file("$buildDir/reports/incubation/${project.name}.txt")) } - tasks.named("check").configure { dependsOn(reportTask) } + plugins.withId("org.jetbrains.kotlin.jvm") { + reportTask { + sources.from(main.kotlin.sourceDirectories) + } + } + tasks.named("check") { dependsOn(reportTask) } } } diff --git a/buildSrc/subprojects/kotlin-dsl/kotlin-dsl.gradle.kts b/buildSrc/subprojects/kotlin-dsl/kotlin-dsl.gradle.kts index ec4c394fd215b..a09beba299e3c 100644 --- a/buildSrc/subprojects/kotlin-dsl/kotlin-dsl.gradle.kts +++ b/buildSrc/subprojects/kotlin-dsl/kotlin-dsl.gradle.kts @@ -3,9 +3,10 @@ dependencies { implementation(project(":configuration")) implementation(project(":build")) - implementation(kotlin("gradle-plugin")) - implementation(kotlin("stdlib-jdk8")) - implementation(kotlin("reflect")) + api(kotlin("gradle-plugin")) + api(kotlin("stdlib-jdk8")) + api(kotlin("reflect")) + api(kotlin("compiler-embeddable")) implementation("org.gradle.kotlin:gradle-kotlin-dsl-conventions:0.2.3") implementation("com.gradle.publish:plugin-publish-plugin:0.10.0") diff --git a/buildSrc/subprojects/kotlin-dsl/src/main/kotlin/parser/KotlinSourceParser.kt b/buildSrc/subprojects/kotlin-dsl/src/main/kotlin/parser/KotlinSourceParser.kt new file mode 100644 index 0000000000000..23d065c5bc324 --- /dev/null +++ b/buildSrc/subprojects/kotlin-dsl/src/main/kotlin/parser/KotlinSourceParser.kt @@ -0,0 +1,120 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package parser + +import org.gradle.api.Action + +import org.gradle.internal.jvm.Jvm + +import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys +import org.jetbrains.kotlin.cli.common.config.addKotlinSourceRoots +import org.jetbrains.kotlin.cli.common.messages.MessageCollector +import org.jetbrains.kotlin.cli.common.messages.MessageRenderer +import org.jetbrains.kotlin.cli.common.messages.PrintingMessageCollector +import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles +import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment +import org.jetbrains.kotlin.cli.jvm.config.addJvmClasspathRoots +import org.jetbrains.kotlin.com.intellij.openapi.Disposable +import org.jetbrains.kotlin.com.intellij.openapi.util.Disposer +import org.jetbrains.kotlin.com.intellij.psi.PsiElement +import org.jetbrains.kotlin.com.intellij.psi.PsiRecursiveElementVisitor +import org.jetbrains.kotlin.config.AnalysisFlags +import org.jetbrains.kotlin.config.ApiVersion +import org.jetbrains.kotlin.config.CommonConfigurationKeys +import org.jetbrains.kotlin.config.CompilerConfiguration +import org.jetbrains.kotlin.config.JVMConfigurationKeys +import org.jetbrains.kotlin.config.JvmTarget +import org.jetbrains.kotlin.config.LanguageFeature +import org.jetbrains.kotlin.config.LanguageVersion +import org.jetbrains.kotlin.config.LanguageVersionSettingsImpl +import org.jetbrains.kotlin.psi.KtFile +import org.jetbrains.kotlin.utils.PathUtil + +import java.io.File + + +class KotlinSourceParser { + + private + val messageCollector: MessageCollector + get() = PrintingMessageCollector(System.out, MessageRenderer.PLAIN_RELATIVE_PATHS, false) + + fun forEachParsedKotlinFile(sourceRoots: List, block: Action) { + } + + fun forEachParsedElementOfType(sourceRoots: List, type: Class, block: Action): Unit = + withParsedKotlinSource(sourceRoots.toList()) { ktFiles -> + ktFiles.forEach { ktFile -> + ktFile.accept(object : PsiRecursiveElementVisitor() { + override fun visitElement(element: PsiElement) { + super.visitElement(element) + if (type.isAssignableFrom(element.javaClass)) { + block.execute(type.cast(element)) + } + } + }) + } + } + + fun mapParsedKotlinFiles(vararg sourceRoots: File, block: (KtFile) -> T): List = + withParsedKotlinSource(sourceRoots.toList()) { ktFiles -> + ktFiles.map(block) + } + + private + fun withParsedKotlinSource(sourceRoots: List, block: (List) -> T) = withRootDisposable { + + // TODO collect errors and react + val configuration = CompilerConfiguration().apply { + + put(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY, messageCollector) + put(JVMConfigurationKeys.RETAIN_OUTPUT_IN_MEMORY, false) + put(CommonConfigurationKeys.MODULE_NAME, "parser") + + // TODO infer from source set configuration? + put(JVMConfigurationKeys.JVM_TARGET, JvmTarget.JVM_1_8) + put(CommonConfigurationKeys.LANGUAGE_VERSION_SETTINGS, LanguageVersionSettingsImpl( + languageVersion = LanguageVersion.KOTLIN_1_3, + apiVersion = ApiVersion.KOTLIN_1_3, + specificFeatures = mapOf( + LanguageFeature.NewInference to LanguageFeature.State.ENABLED, + LanguageFeature.SamConversionForKotlinFunctions to LanguageFeature.State.ENABLED + ), + analysisFlags = mapOf( + AnalysisFlags.skipMetadataVersionCheck to true + ) + )) + + // TODO add source set compile classpath? + addJvmClasspathRoots(PathUtil.getJdkClassesRoots(Jvm.current().javaHome)) + addKotlinSourceRoots(sourceRoots.map { it.canonicalPath }) + } + val environment = KotlinCoreEnvironment.createForProduction(this, configuration, EnvironmentConfigFiles.JVM_CONFIG_FILES) + environment.getSourceFiles().let(block) + } +} + + +internal +inline fun withRootDisposable(action: Disposable.() -> T): T { + val rootDisposable = Disposer.newDisposable() + try { + return action(rootDisposable) + } finally { + Disposer.dispose(rootDisposable) + } +} From 24db94e2dbdce3a81da7b9b716bb1b13f202615b Mon Sep 17 00:00:00 2001 From: Paul Merlin Date: Wed, 20 Feb 2019 15:24:32 +0100 Subject: [PATCH 082/853] Add missing @since on :kotlinDsl @Incubating members Signed-off-by: Paul Merlin --- .../org/gradle/kotlin/dsl/ArtifactHandlerExtensions.kt | 2 ++ .../kotlin/dsl/DependencyConstraintHandlerExtensions.kt | 2 ++ .../gradle/kotlin/dsl/DependencyConstraintHandlerScope.kt | 1 + .../org/gradle/kotlin/dsl/ExtensionContainerExtensions.kt | 5 +++++ .../main/kotlin/org/gradle/kotlin/dsl/ScriptHandlerScope.kt | 2 ++ 5 files changed, 12 insertions(+) diff --git a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/ArtifactHandlerExtensions.kt b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/ArtifactHandlerExtensions.kt index b12da26d58134..97222505c2dae 100644 --- a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/ArtifactHandlerExtensions.kt +++ b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/ArtifactHandlerExtensions.kt @@ -22,6 +22,8 @@ import org.gradle.api.artifacts.dsl.ArtifactHandler /** * Configures the published artifacts for this project. + * + * @since 5.1 */ @Incubating operator fun ArtifactHandler.invoke(configuration: ArtifactHandlerScope.() -> Unit): Unit = diff --git a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/DependencyConstraintHandlerExtensions.kt b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/DependencyConstraintHandlerExtensions.kt index 3a189a5c6b385..2913919346514 100644 --- a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/DependencyConstraintHandlerExtensions.kt +++ b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/DependencyConstraintHandlerExtensions.kt @@ -22,6 +22,8 @@ import org.gradle.api.artifacts.dsl.DependencyConstraintHandler /** * Configures the dependency constraints. + * + * @since 5.0 */ @Incubating operator fun DependencyConstraintHandler.invoke(configuration: DependencyConstraintHandlerScope.() -> Unit) = diff --git a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/DependencyConstraintHandlerScope.kt b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/DependencyConstraintHandlerScope.kt index b937caaac92f4..aae1e8b2066f1 100644 --- a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/DependencyConstraintHandlerScope.kt +++ b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/DependencyConstraintHandlerScope.kt @@ -26,6 +26,7 @@ import org.gradle.api.artifacts.dsl.DependencyConstraintHandler * Receiver for `dependencies.constraints` block providing convenient utilities for configuring dependency constraints. * * @see [DependencyConstraintHandler] + * @since 5.0 */ @Incubating class DependencyConstraintHandlerScope diff --git a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/ExtensionContainerExtensions.kt b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/ExtensionContainerExtensions.kt index 5f3ced2369887..bfee77f897565 100644 --- a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/ExtensionContainerExtensions.kt +++ b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/ExtensionContainerExtensions.kt @@ -73,6 +73,7 @@ inline operator fun ExtensionContainer.getValue(thisRef: Any?, * @throws IllegalArgumentException When an extension with the given name already exists. * * @see [ExtensionContainer.add] + * @since 5.0 */ @Incubating @Suppress("extension_shadowed_by_member") @@ -90,6 +91,7 @@ inline fun ExtensionContainer.add(name: String, extension: T) * @return the created instance * * @see [ExtensionContainer.create] + * @since 5.0 */ @Incubating inline fun ExtensionContainer.create(name: String, vararg constructionArguments: Any): T = @@ -104,6 +106,7 @@ inline fun ExtensionContainer.create(name: String, vararg cons * @throws UnknownDomainObjectException when no matching extension can be found * * @see [ExtensionContainer.getByType] + * @since 5.0 */ @Incubating inline fun ExtensionContainer.getByType(): T = @@ -117,6 +120,7 @@ inline fun ExtensionContainer.getByType(): T = * @return the extension or null if not found * * @see [ExtensionContainer.findByType] + * @since 5.0 */ @Incubating inline fun ExtensionContainer.findByType(): T? = @@ -130,6 +134,7 @@ inline fun ExtensionContainer.findByType(): T? = * @param action the configuration action * * @see [ExtensionContainer.configure] + * @since 5.0 */ @Incubating inline fun ExtensionContainer.configure(noinline action: T.() -> Unit) { diff --git a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/ScriptHandlerScope.kt b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/ScriptHandlerScope.kt index a7e95e5ff6c31..3eb7a53faf91b 100644 --- a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/ScriptHandlerScope.kt +++ b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/ScriptHandlerScope.kt @@ -156,6 +156,7 @@ private constructor( * @return the added dependency constraint * * @see [DependencyConstraintHandler.add] + * @since 5.0 */ @Incubating fun DependencyConstraintHandler.classpath(dependencyConstraintNotation: Any): DependencyConstraint? = @@ -170,6 +171,7 @@ private constructor( * @return the added dependency constraint * * @see [DependencyConstraintHandler.add] + * @since 5.0 */ @Incubating fun DependencyConstraintHandler.classpath(dependencyConstraintNotation: Any, configuration: DependencyConstraint.() -> Unit): DependencyConstraint? = From 4f69e845627e61869a0f59ec68937cbfba254b6f Mon Sep 17 00:00:00 2001 From: Paul Merlin Date: Wed, 20 Feb 2019 15:32:27 +0100 Subject: [PATCH 083/853] Let IncubatingApiAggregateReportTask use NONE worker isolation CLASSLOADER isolation is slower and not required Signed-off-by: Paul Merlin --- .../buildquality/incubation/IncubatingApiAggregateReportTask.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/buildSrc/subprojects/buildquality/src/main/kotlin/org/gradle/gradlebuild/buildquality/incubation/IncubatingApiAggregateReportTask.kt b/buildSrc/subprojects/buildquality/src/main/kotlin/org/gradle/gradlebuild/buildquality/incubation/IncubatingApiAggregateReportTask.kt index 57271ff3f01c0..9d0061ba8c0d6 100644 --- a/buildSrc/subprojects/buildquality/src/main/kotlin/org/gradle/gradlebuild/buildquality/incubation/IncubatingApiAggregateReportTask.kt +++ b/buildSrc/subprojects/buildquality/src/main/kotlin/org/gradle/gradlebuild/buildquality/incubation/IncubatingApiAggregateReportTask.kt @@ -50,7 +50,7 @@ open class IncubatingApiAggregateReportTask @TaskAction fun generateReport() { workerExecutor.submit(GenerateReport::class.java) { - isolationMode = IsolationMode.CLASSLOADER + isolationMode = IsolationMode.NONE params(reports, htmlReportFile.asFile.get()) } } From 4dad7c528dbd2e0f048ac83013ed247c76515b6e Mon Sep 17 00:00:00 2001 From: Paul Merlin Date: Wed, 20 Feb 2019 15:50:58 +0100 Subject: [PATCH 084/853] Tighten KotlinSourceParser removing all unneeded stuff Signed-off-by: Paul Merlin --- .../main/kotlin/parser/KotlinSourceParser.kt | 43 ------------------- 1 file changed, 43 deletions(-) diff --git a/buildSrc/subprojects/kotlin-dsl/src/main/kotlin/parser/KotlinSourceParser.kt b/buildSrc/subprojects/kotlin-dsl/src/main/kotlin/parser/KotlinSourceParser.kt index 23d065c5bc324..96a1b3a119b86 100644 --- a/buildSrc/subprojects/kotlin-dsl/src/main/kotlin/parser/KotlinSourceParser.kt +++ b/buildSrc/subprojects/kotlin-dsl/src/main/kotlin/parser/KotlinSourceParser.kt @@ -16,8 +16,6 @@ package parser -import org.gradle.api.Action - import org.gradle.internal.jvm.Jvm import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys @@ -30,17 +28,9 @@ import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment import org.jetbrains.kotlin.cli.jvm.config.addJvmClasspathRoots import org.jetbrains.kotlin.com.intellij.openapi.Disposable import org.jetbrains.kotlin.com.intellij.openapi.util.Disposer -import org.jetbrains.kotlin.com.intellij.psi.PsiElement -import org.jetbrains.kotlin.com.intellij.psi.PsiRecursiveElementVisitor -import org.jetbrains.kotlin.config.AnalysisFlags -import org.jetbrains.kotlin.config.ApiVersion import org.jetbrains.kotlin.config.CommonConfigurationKeys import org.jetbrains.kotlin.config.CompilerConfiguration import org.jetbrains.kotlin.config.JVMConfigurationKeys -import org.jetbrains.kotlin.config.JvmTarget -import org.jetbrains.kotlin.config.LanguageFeature -import org.jetbrains.kotlin.config.LanguageVersion -import org.jetbrains.kotlin.config.LanguageVersionSettingsImpl import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.utils.PathUtil @@ -53,23 +43,6 @@ class KotlinSourceParser { val messageCollector: MessageCollector get() = PrintingMessageCollector(System.out, MessageRenderer.PLAIN_RELATIVE_PATHS, false) - fun forEachParsedKotlinFile(sourceRoots: List, block: Action) { - } - - fun forEachParsedElementOfType(sourceRoots: List, type: Class, block: Action): Unit = - withParsedKotlinSource(sourceRoots.toList()) { ktFiles -> - ktFiles.forEach { ktFile -> - ktFile.accept(object : PsiRecursiveElementVisitor() { - override fun visitElement(element: PsiElement) { - super.visitElement(element) - if (type.isAssignableFrom(element.javaClass)) { - block.execute(type.cast(element)) - } - } - }) - } - } - fun mapParsedKotlinFiles(vararg sourceRoots: File, block: (KtFile) -> T): List = withParsedKotlinSource(sourceRoots.toList()) { ktFiles -> ktFiles.map(block) @@ -78,28 +51,12 @@ class KotlinSourceParser { private fun withParsedKotlinSource(sourceRoots: List, block: (List) -> T) = withRootDisposable { - // TODO collect errors and react val configuration = CompilerConfiguration().apply { put(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY, messageCollector) put(JVMConfigurationKeys.RETAIN_OUTPUT_IN_MEMORY, false) put(CommonConfigurationKeys.MODULE_NAME, "parser") - // TODO infer from source set configuration? - put(JVMConfigurationKeys.JVM_TARGET, JvmTarget.JVM_1_8) - put(CommonConfigurationKeys.LANGUAGE_VERSION_SETTINGS, LanguageVersionSettingsImpl( - languageVersion = LanguageVersion.KOTLIN_1_3, - apiVersion = ApiVersion.KOTLIN_1_3, - specificFeatures = mapOf( - LanguageFeature.NewInference to LanguageFeature.State.ENABLED, - LanguageFeature.SamConversionForKotlinFunctions to LanguageFeature.State.ENABLED - ), - analysisFlags = mapOf( - AnalysisFlags.skipMetadataVersionCheck to true - ) - )) - - // TODO add source set compile classpath? addJvmClasspathRoots(PathUtil.getJdkClassesRoots(Jvm.current().javaHome)) addKotlinSourceRoots(sourceRoots.map { it.canonicalPath }) } From 6e319757f541bf196e87d7e00c101c983f2271bc Mon Sep 17 00:00:00 2001 From: Paul Merlin Date: Fri, 22 Feb 2019 12:57:02 +0100 Subject: [PATCH 085/853] Refine IncubatingApiReportTask Signed-off-by: Paul Merlin --- .../incubation/IncubatingApiReportTask.kt | 254 +++++++++++------- 1 file changed, 164 insertions(+), 90 deletions(-) diff --git a/buildSrc/subprojects/buildquality/src/main/kotlin/org/gradle/gradlebuild/buildquality/incubation/IncubatingApiReportTask.kt b/buildSrc/subprojects/buildquality/src/main/kotlin/org/gradle/gradlebuild/buildquality/incubation/IncubatingApiReportTask.kt index c17ca82610f6f..282145003029b 100644 --- a/buildSrc/subprojects/buildquality/src/main/kotlin/org/gradle/gradlebuild/buildquality/incubation/IncubatingApiReportTask.kt +++ b/buildSrc/subprojects/buildquality/src/main/kotlin/org/gradle/gradlebuild/buildquality/incubation/IncubatingApiReportTask.kt @@ -15,6 +15,7 @@ import com.github.javaparser.symbolsolver.JavaSymbolSolver import com.github.javaparser.symbolsolver.resolution.typesolvers.CombinedTypeSolver import com.github.javaparser.symbolsolver.resolution.typesolvers.JavaParserTypeSolver import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver + import org.gradle.api.DefaultTask import org.gradle.api.file.ConfigurableFileCollection import org.gradle.api.file.RegularFileProperty @@ -29,17 +30,27 @@ import org.gradle.api.tasks.PathSensitivity import org.gradle.api.tasks.TaskAction import org.gradle.workers.IsolationMode import org.gradle.workers.WorkerExecutor + import org.jetbrains.kotlin.psi.KtCallableDeclaration +import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.psi.KtNamedDeclaration import org.jetbrains.kotlin.psi.psiUtil.collectDescendantsOfType + import parser.KotlinSourceParser + import java.io.File import javax.inject.Inject +import org.gradle.kotlin.dsl.* + @CacheableTask -open class IncubatingApiReportTask -@Inject constructor(private val workerExecutor: WorkerExecutor) : DefaultTask() { +open class IncubatingApiReportTask @Inject constructor( + + private + val workerExecutor: WorkerExecutor + +) : DefaultTask() { @InputFile @PathSensitive(PathSensitivity.RELATIVE) @@ -50,35 +61,53 @@ open class IncubatingApiReportTask val releasedVersionsFile: RegularFileProperty = project.objects.fileProperty() @Input - val title: Property = project.objects.property(String::class.java).also { - it.set(project.provider { project.name }) - } + val title: Property = project.objects.property().convention(project.provider { + project.name + }) @InputFiles @PathSensitive(PathSensitivity.RELATIVE) - val sources: ConfigurableFileCollection = project.files() + val sources: ConfigurableFileCollection = project.objects.fileCollection() @OutputFile - val htmlReportFile: RegularFileProperty = project.objects.fileProperty().also { - it.set(project.layout.buildDirectory.file("reports/incubating.html")) - } + val htmlReportFile: RegularFileProperty = project.objects.fileProperty().convention( + project.layout.buildDirectory.file("reports/incubating.html") + ) @OutputFile - val textReportFile: RegularFileProperty = project.objects.fileProperty().also { - it.set(project.layout.buildDirectory.file("reports/incubating.txt")) - } + val textReportFile: RegularFileProperty = project.objects.fileProperty().convention( + project.layout.buildDirectory.file("reports/incubating.txt") + ) @TaskAction + @Suppress("unused") fun analyze() = workerExecutor.submit(Analyzer::class.java) { isolationMode = IsolationMode.NONE - params(versionFile.asFile.get(), sources.files, htmlReportFile.asFile.get(), textReportFile.asFile.get(), title.get(), releasedVersionsFile.asFile.get()) + params( + sources.files, + htmlReportFile.asFile.get(), + textReportFile.asFile.get(), + title.get(), + releasedVersionsFile.asFile.get() + ) } } +private +typealias Version = String + + +private +typealias IncubatingDescription = String + + +private +typealias VersionsToIncubating = Map> + + open class Analyzer @Inject constructor( - private val versionFile: File, private val srcDirs: Set, private val htmlReportFile: File, private val textReportFile: File, @@ -88,20 +117,20 @@ class Analyzer @Inject constructor( override fun run() { - val versionToIncubating = mutableMapOf>() + val versionToIncubating = mutableMapOf>() srcDirs.forEach { srcDir -> if (srcDir.exists()) { - val sourceFileParser = CompositeSourceFileParser(listOf( - JavaSourceFileParser(srcDir), - KotlinSourceFileParser(srcDir) + val sourceFileParser = CompositeVersionsToIncubatingCollector(listOf( + JavaVersionsToIncubatingCollector(srcDir), + KotlinVersionsToIncubatingCollector(srcDir) )) - srcDir.walkTopDown().forEach { + srcDir.walkTopDown().forEach { sourceFile -> try { - sourceFileParser.parseSourceFile(it).forEach { (version, incubating) -> + sourceFileParser.collectFrom(sourceFile).forEach { (version, incubating) -> versionToIncubating.getOrPut(version) { mutableSetOf() }.addAll(incubating) } } catch (e: Exception) { - throw Exception("Unable to parse $it: ${e.message}") + throw Exception("Unable to parse $sourceFile: ${e.message}") } } } @@ -111,7 +140,7 @@ class Analyzer @Inject constructor( } private - fun generateHtmlReport(versionToIncubating: Map>) { + fun generateHtmlReport(versionToIncubating: VersionsToIncubating) { htmlReportFile.parentFile.mkdirs() htmlReportFile.printWriter(Charsets.UTF_8).use { writer -> writer.println(""" @@ -127,13 +156,13 @@ class Analyzer @Inject constructor(

    Incubating APIs for $title

    """) val versions = versionsDates() - versionToIncubating.toSortedMap().forEach { - writer.println("") - writer.println("

    Incubating since ${it.key} (${versions.get(it.key)?.run { "released on $this" } + versionToIncubating.toSortedMap().forEach { (version, incubatingDescriptions) -> + writer.println("") + writer.println("

    Incubating since $version (${versions[version]?.run { "released on $this" } ?: "unreleased"})

    ") writer.println("
      ") - it.value.sorted().forEach { - writer.println("
    • ${it.escape()}
    • ") + incubatingDescriptions.sorted().forEach { incubating -> + writer.println("
    • ${incubating.escape()}
    • ") } writer.println("
    ") } @@ -142,23 +171,22 @@ class Analyzer @Inject constructor( } private - fun generateTextReport(versionToIncubating: Map>) { + fun generateTextReport(versionToIncubating: VersionsToIncubating) { textReportFile.parentFile.mkdirs() textReportFile.printWriter(Charsets.UTF_8).use { writer -> val versions = versionsDates() - versionToIncubating.toSortedMap().forEach { - val version = it.key - val releaseDate = versions.get(it.key) ?: "unreleased" - it.value.sorted().forEach { - writer.println("$version;$releaseDate;$it") + versionToIncubating.toSortedMap().forEach { (version, incubatingDescriptions) -> + val releaseDate = versions[version] ?: "unreleased" + incubatingDescriptions.sorted().forEach { incubating -> + writer.println("$version;$releaseDate;$incubating") } } } } private - fun versionsDates(): Map { - val versions = mutableMapOf() + fun versionsDates(): Map { + val versions = mutableMapOf() var version: String? = null releasedVersionsFile.forEachLine(Charsets.UTF_8) { val line = it.trim() @@ -168,7 +196,7 @@ class Analyzer @Inject constructor( if (line.startsWith("\"buildTime\"")) { var date = line.substring(line.indexOf("\"", 12) + 1, line.lastIndexOf("\"")) date = date.substring(0, 4) + "-" + date.substring(4, 6) + "-" + date.substring(6, 8) - versions.put(version!!, date) + versions[version!!] = date } } return versions @@ -181,63 +209,75 @@ class Analyzer @Inject constructor( private -typealias VersionsToIncubating = Map> +interface VersionsToIncubatingCollector { + + fun collectFrom(sourceFile: File): VersionsToIncubating +} private -interface SourceFileParser { +class CompositeVersionsToIncubatingCollector( - fun parseSourceFile(sourceFile: File): VersionsToIncubating + private + val collectors: List + +) : VersionsToIncubatingCollector { + + override fun collectFrom(sourceFile: File): VersionsToIncubating = + collectors + .flatMap { it.collectFrom(sourceFile).entries } + .associate { it.key to it.value } } private -class CompositeSourceFileParser(private val sourceFileParsers: List) : SourceFileParser { - - override fun parseSourceFile(sourceFile: File): VersionsToIncubating = - sourceFileParsers.flatMap { it.parseSourceFile(sourceFile).entries }.associate { it.key to it.value } -} +const val versionNotFound = "Not found" private -class JavaSourceFileParser(srcDir: File) : SourceFileParser { +class JavaVersionsToIncubatingCollector(srcDir: File) : VersionsToIncubatingCollector { private val solver = JavaSymbolSolver(CombinedTypeSolver(JavaParserTypeSolver(srcDir), ReflectionTypeSolver())) - override fun parseSourceFile(sourceFile: File): VersionsToIncubating { - val versionToIncubating = mutableMapOf>() + override fun collectFrom(sourceFile: File): VersionsToIncubating { + val versionsToIncubating = mutableMapOf>() if (!sourceFile.name.endsWith(".java")) { - return versionToIncubating + return versionsToIncubating } JavaParser.parse(sourceFile).run { solver.inject(this) - findAll(Node::class.java) - .filter { - it is NodeWithAnnotations<*> && - it.annotations.any { it.nameAsString == "Incubating" } - }.map { - val node = it as NodeWithAnnotations<*> - val version = findVersionFromJavadoc(node) - ?: "Not found" - Pair(version, nodeName(it, this, sourceFile)) - }.forEach { - versionToIncubating.getOrPut(it.first) { - mutableSetOf() - }.add(it.second) + findAllIncubating() + .map { node -> toVersionIncubating(sourceFile, node) } + .forEach { (version, incubating) -> + versionsToIncubating.getOrPut(version) { mutableSetOf() }.add(incubating) } } - return versionToIncubating + return versionsToIncubating } + private + fun CompilationUnit.findAllIncubating() = + findAll(Node::class.java).filter { it.isIncubating } + + private + val Node.isIncubating: Boolean + get() = (this as? NodeWithAnnotations<*>)?.annotations?.any { it.nameAsString == "Incubating" } ?: false + + private + fun CompilationUnit.toVersionIncubating(sourceFile: File, node: Node) = + Pair( + findVersionFromJavadoc(node as NodeWithAnnotations<*>) ?: versionNotFound, + nodeName(node, this, sourceFile) + ) + private fun findVersionFromJavadoc(node: NodeWithAnnotations<*>): String? = if (node is NodeWithJavadoc<*>) { - node.javadoc.map { - it.blockTags.find { - it.tagName == "since" - }?.content?.elements?.find { - it is JavadocSnippet - }?.toText() + node.javadoc.map { javadoc -> + javadoc.blockTags + .find { tag -> tag.tagName == "since" } + ?.content?.elements?.find { description -> description is JavadocSnippet } + ?.toText() }.orElse(null) } else { null @@ -254,7 +294,8 @@ class JavaSourceFileParser(srcDir: File) : SourceFileParser { } private - fun inferClassName(unit: CompilationUnit) = "${unit.packageDeclaration.map { it.nameAsString }.orElse("")}.${unit.primaryTypeName.orElse("")}" + fun inferClassName(unit: CompilationUnit) = + "${unit.packageDeclaration.map { it.nameAsString }.orElse("")}.${unit.primaryTypeName.orElse("")}" private inline fun tryResolve(resolver: () -> String, or: () -> String) = try { @@ -266,35 +307,68 @@ class JavaSourceFileParser(srcDir: File) : SourceFileParser { private -class KotlinSourceFileParser(srcDir: File) : SourceFileParser { +class KotlinVersionsToIncubatingCollector(srcDir: File) : VersionsToIncubatingCollector { - override fun parseSourceFile(sourceFile: File): VersionsToIncubating { + override fun collectFrom(sourceFile: File): VersionsToIncubating { - val versionToIncubating = mutableMapOf>() + val versionsToIncubating = mutableMapOf>() if (!sourceFile.name.endsWith(".kt")) { - return versionToIncubating + return versionsToIncubating } KotlinSourceParser().mapParsedKotlinFiles(sourceFile) { ktFile -> - ktFile.collectDescendantsOfType().forEach { declaration -> - if (declaration.annotationEntries.any { it.shortName?.asString() == "Incubating" }) { - var name = (declaration as? KtCallableDeclaration)?.typeParameterList?.let { "${it.text} " } ?: "" - name += declaration.fqName!!.asString() - if (declaration is KtCallableDeclaration) { - name += declaration.valueParameterList?.text ?: "" - if (declaration.receiverTypeReference != null) { - name += " with ${declaration.receiverTypeReference!!.text} receiver" - } - if (declaration.parent == ktFile) { - name += ", top-level in ${sourceFile.name}" - } - } - val since = declaration.docComment?.getDefaultSection()?.findTagsByName("since")?.singleOrNull()?.getContent() ?: "Not found" - versionToIncubating.getOrPut(since) { mutableSetOf() }.add(name) - } + ktFile.forEachIncubatingDeclaration { declaration -> + versionsToIncubating + .getOrPut(declaration.sinceVersion) { mutableSetOf() } + .add(buildIncubatingDescription(sourceFile, ktFile, declaration)) } } - return versionToIncubating + return versionsToIncubating } + + private + fun buildIncubatingDescription(sourceFile: File, ktFile: KtFile, declaration: KtNamedDeclaration): String { + var incubating = "${declaration.typeParametersString}${declaration.fullyQualifiedName}" + if (declaration is KtCallableDeclaration) { + incubating += declaration.valueParametersString + declaration.receiverTypeString?.let { receiver -> + incubating += " with $receiver receiver" + } + if (declaration.parent == ktFile) { + incubating += ", top-level in ${sourceFile.name}" + } + } + return incubating + } + + private + fun KtFile.forEachIncubatingDeclaration(block: (KtNamedDeclaration) -> Unit) { + collectDescendantsOfType().filter { it.isIncubating }.forEach(block) + } + + private + val KtNamedDeclaration.isIncubating: Boolean + get() = annotationEntries.any { it.shortName?.asString() == "Incubating" } + + private + val KtNamedDeclaration.typeParametersString: String + get() = (this as? KtCallableDeclaration)?.typeParameterList?.let { "${it.text} " } ?: "" + + private + val KtNamedDeclaration.fullyQualifiedName: String + get() = fqName!!.asString() + + private + val KtCallableDeclaration.valueParametersString: String + get() = valueParameterList?.text ?: "" + + private + val KtCallableDeclaration.receiverTypeString: String? + get() = receiverTypeReference?.text + + private + val KtNamedDeclaration.sinceVersion: String + get() = docComment?.getDefaultSection()?.findTagsByName("since")?.singleOrNull()?.getContent() + ?: versionNotFound } From 1822c6227023f4d8f02af057ae0b33a8f68942e9 Mon Sep 17 00:00:00 2001 From: Paul Merlin Date: Sat, 23 Feb 2019 17:00:47 +0100 Subject: [PATCH 086/853] Refine IncubatingApiReportTask Signed-off-by: Paul Merlin --- .../incubation/IncubatingApiReportTask.kt | 26 +++++++------------ 1 file changed, 10 insertions(+), 16 deletions(-) diff --git a/buildSrc/subprojects/buildquality/src/main/kotlin/org/gradle/gradlebuild/buildquality/incubation/IncubatingApiReportTask.kt b/buildSrc/subprojects/buildquality/src/main/kotlin/org/gradle/gradlebuild/buildquality/incubation/IncubatingApiReportTask.kt index 282145003029b..c72d13dc2047e 100644 --- a/buildSrc/subprojects/buildquality/src/main/kotlin/org/gradle/gradlebuild/buildquality/incubation/IncubatingApiReportTask.kt +++ b/buildSrc/subprojects/buildquality/src/main/kotlin/org/gradle/gradlebuild/buildquality/incubation/IncubatingApiReportTask.kt @@ -120,13 +120,13 @@ class Analyzer @Inject constructor( val versionToIncubating = mutableMapOf>() srcDirs.forEach { srcDir -> if (srcDir.exists()) { - val sourceFileParser = CompositeVersionsToIncubatingCollector(listOf( + val collector = CompositeVersionsToIncubatingCollector(listOf( JavaVersionsToIncubatingCollector(srcDir), KotlinVersionsToIncubatingCollector(srcDir) )) srcDir.walkTopDown().forEach { sourceFile -> try { - sourceFileParser.collectFrom(sourceFile).forEach { (version, incubating) -> + collector.collectFrom(sourceFile).forEach { (version, incubating) -> versionToIncubating.getOrPut(version) { mutableSetOf() }.addAll(incubating) } } catch (e: Exception) { @@ -241,10 +241,10 @@ class JavaVersionsToIncubatingCollector(srcDir: File) : VersionsToIncubatingColl val solver = JavaSymbolSolver(CombinedTypeSolver(JavaParserTypeSolver(srcDir), ReflectionTypeSolver())) override fun collectFrom(sourceFile: File): VersionsToIncubating { + + if (!sourceFile.name.endsWith(".java")) return emptyMap() + val versionsToIncubating = mutableMapOf>() - if (!sourceFile.name.endsWith(".java")) { - return versionsToIncubating - } JavaParser.parse(sourceFile).run { solver.inject(this) findAllIncubating() @@ -272,16 +272,13 @@ class JavaVersionsToIncubatingCollector(srcDir: File) : VersionsToIncubatingColl ) private - fun findVersionFromJavadoc(node: NodeWithAnnotations<*>): String? = if (node is NodeWithJavadoc<*>) { - node.javadoc.map { javadoc -> + fun findVersionFromJavadoc(node: NodeWithAnnotations<*>): String? = + (node as? NodeWithJavadoc<*>)?.javadoc?.map { javadoc -> javadoc.blockTags .find { tag -> tag.tagName == "since" } ?.content?.elements?.find { description -> description is JavadocSnippet } ?.toText() - }.orElse(null) - } else { - null - } + }?.orElse(null) private fun nodeName(it: Node?, unit: CompilationUnit, file: File) = when (it) { @@ -311,12 +308,9 @@ class KotlinVersionsToIncubatingCollector(srcDir: File) : VersionsToIncubatingCo override fun collectFrom(sourceFile: File): VersionsToIncubating { - val versionsToIncubating = mutableMapOf>() - - if (!sourceFile.name.endsWith(".kt")) { - return versionsToIncubating - } + if (!sourceFile.name.endsWith(".kt")) return emptyMap() + val versionsToIncubating = mutableMapOf>() KotlinSourceParser().mapParsedKotlinFiles(sourceFile) { ktFile -> ktFile.forEachIncubatingDeclaration { declaration -> versionsToIncubating From eb614eff65b631f51d47cfd4fd536800db22785c Mon Sep 17 00:00:00 2001 From: Gary Hale Date: Sat, 23 Feb 2019 11:40:50 -0500 Subject: [PATCH 087/853] Set min heap for daemon soak tests --- .../daemon/DaemonPerformanceMonitoringSoakTest.groovy | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/subprojects/soak/src/integTest/groovy/org/gradle/launcher/daemon/DaemonPerformanceMonitoringSoakTest.groovy b/subprojects/soak/src/integTest/groovy/org/gradle/launcher/daemon/DaemonPerformanceMonitoringSoakTest.groovy index b9b8f7f2273a5..72fd76d113286 100644 --- a/subprojects/soak/src/integTest/groovy/org/gradle/launcher/daemon/DaemonPerformanceMonitoringSoakTest.groovy +++ b/subprojects/soak/src/integTest/groovy/org/gradle/launcher/daemon/DaemonPerformanceMonitoringSoakTest.groovy @@ -103,7 +103,7 @@ class DaemonPerformanceMonitoringSoakTest extends DaemonMultiJdkIntegrationTest when: leaksWhenIdle() executer.withArguments("-Dorg.gradle.daemon.healthcheckinterval=1000") - executer.withBuildJvmOpts("-D${DaemonMemoryStatus.ENABLE_PERFORMANCE_MONITORING}=true", "-Xmx${heapSize}", "-Dorg.gradle.daemon.performance.logging=true") + executer.withBuildJvmOpts("-D${DaemonMemoryStatus.ENABLE_PERFORMANCE_MONITORING}=true", "-Xms128m", "-Xmx${heapSize}", "-Dorg.gradle.daemon.performance.logging=true") executer.noExtraLogging() run() @@ -145,7 +145,7 @@ class DaemonPerformanceMonitoringSoakTest extends DaemonMultiJdkIntegrationTest when: leaksWithinOneBuild() executer.withArguments("-Dorg.gradle.daemon.healthcheckinterval=1000", "--debug") - executer.withBuildJvmOpts("-D${DaemonMemoryStatus.ENABLE_PERFORMANCE_MONITORING}=true", "-Xmx${heapSize}", "-Dorg.gradle.daemon.performance.logging=true") + executer.withBuildJvmOpts("-D${DaemonMemoryStatus.ENABLE_PERFORMANCE_MONITORING}=true", "-Xms128m", "-Xmx${heapSize}", "-Dorg.gradle.daemon.performance.logging=true") executer.noExtraLogging() GradleHandle gradle = executer.start() @@ -179,7 +179,7 @@ class DaemonPerformanceMonitoringSoakTest extends DaemonMultiJdkIntegrationTest try { for (int i = 0; i < maxBuilds; i++) { executer.noExtraLogging() - executer.withBuildJvmOpts("-D${DaemonMemoryStatus.ENABLE_PERFORMANCE_MONITORING}=true", "-Xmx${heapSize}", "-Dorg.gradle.daemon.performance.logging=true") + executer.withBuildJvmOpts("-D${DaemonMemoryStatus.ENABLE_PERFORMANCE_MONITORING}=true", "-Xms128m", "-Xmx${heapSize}", "-Dorg.gradle.daemon.performance.logging=true") GradleHandle gradle = executer.start() gradle.waitForExit() if (gradle.standardOutput ==~ /(?s).*Starting build in new daemon \[memory: [0-9].*/) { From a9197991f2d83b4f971f9f1b06655041c75cc499 Mon Sep 17 00:00:00 2001 From: Cedric Champeau Date: Sat, 23 Feb 2019 18:56:33 +0100 Subject: [PATCH 088/853] Fix force realize serialization It didn't expect an integer to be a valid attribute type. --- .../caching/DesugaringAttributeContainerSerializer.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/subprojects/dependency-management/src/main/java/org/gradle/internal/resolve/caching/DesugaringAttributeContainerSerializer.java b/subprojects/dependency-management/src/main/java/org/gradle/internal/resolve/caching/DesugaringAttributeContainerSerializer.java index d6c3e959d8465..011ca4b23f940 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/internal/resolve/caching/DesugaringAttributeContainerSerializer.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/internal/resolve/caching/DesugaringAttributeContainerSerializer.java @@ -41,6 +41,7 @@ public class DesugaringAttributeContainerSerializer implements AttributeContaine private static final byte STRING_ATTRIBUTE = 1; private static final byte BOOLEAN_ATTRIBUTE = 2; private static final byte DESUGARED_ATTRIBUTE = 3; + private static final byte INTEGER_ATTRIBUTE = 4; public DesugaringAttributeContainerSerializer(ImmutableAttributesFactory attributesFactory, NamedObjectInstantiator namedObjectInstantiator) { this.attributesFactory = attributesFactory; @@ -59,6 +60,9 @@ public ImmutableAttributes read(Decoder decoder) throws IOException { } else if (type == STRING_ATTRIBUTE){ String value = decoder.readString(); attributes = attributesFactory.concat(attributes, Attribute.of(name, String.class), value); + } else if (type == INTEGER_ATTRIBUTE){ + int value = decoder.readInt(); + attributes = attributesFactory.concat(attributes, Attribute.of(name, Integer.class), value); } else if (type == DESUGARED_ATTRIBUTE) { String value = decoder.readString(); attributes = attributesFactory.concat(attributes, Attribute.of(name, String.class), new CoercingStringValueSnapshot(value, namedObjectInstantiator)); @@ -78,6 +82,9 @@ public void write(Encoder encoder, AttributeContainer container) throws IOExcept } else if (attribute.getType().equals(String.class)){ encoder.writeByte(STRING_ATTRIBUTE); encoder.writeString((String) container.getAttribute(attribute)); + } else if (attribute.getType().equals(Integer.class)){ + encoder.writeByte(INTEGER_ATTRIBUTE); + encoder.writeInt((Integer) container.getAttribute(attribute)); } else { assert Named.class.isAssignableFrom(attribute.getType()); Named attributeValue = (Named) container.getAttribute(attribute); From 7df5e5ea96ca774dd770cf6a7e55d2bbf1dd844d Mon Sep 17 00:00:00 2001 From: Sterling Greene Date: Sat, 23 Feb 2019 04:46:45 -0500 Subject: [PATCH 089/853] Rework daemon GC/memory expiration checks - Do not sniff for VM vendor to figure out which GC strategies may be used - Rename permgen -> non-heap in most places, Java 8+ uses metaspace for this memory pool - Rename tenured -> heap - Only add GarbageCollectionEvents to the observation window when there's been a GC collection - This simplifies the calculation of GC rate - Non-heap memory pools are not GC'd - Re-enable daemon performance soak test --- .../java/org/gradle/internal/time/Clock.java | 2 +- .../OutputScrapingExecutionResult.java | 4 +- .../daemon/server/DaemonServices.java | 4 +- .../server/health/DaemonHealthStats.java | 49 +++--- .../server/health/DaemonMemoryStatus.java | 111 ++++--------- .../health/HealthExpirationStrategy.java | 4 +- ...LowHeapSpaceDaemonExpirationStrategy.java} | 10 +- ...> LowNonHeapDaemonExpirationStrategy.java} | 10 +- .../health/gc/DefaultSlidingWindow.java | 14 +- .../health/gc/GarbageCollectionCheck.java | 53 +++--- .../health/gc/GarbageCollectionEvent.java | 6 +- .../health/gc/GarbageCollectionMonitor.java | 93 +++-------- .../health/gc/GarbageCollectionStats.java | 154 ++++++++--------- .../GarbageCollectorMonitoringStrategy.java | 44 ++--- .../server/health/gc/SlidingWindow.java | 15 +- .../health/DaemonHealthStatsTest.groovy | 26 ++- .../health/DaemonMemoryStatusTest.groovy | 155 +++++++----------- ...pSpaceDaemonExpirationStrategyTest.groovy} | 12 +- ...onHeapDaemonExpirationStrategyTest.groovy} | 12 +- .../gc/GarbageCollectionMonitorTest.groovy | 27 +-- .../gc/GarbageCollectionStatsTest.groovy | 67 ++++++-- ...DaemonPerformanceMonitoringSoakTest.groovy | 2 +- 22 files changed, 385 insertions(+), 489 deletions(-) rename subprojects/launcher/src/main/java/org/gradle/launcher/daemon/server/health/{LowTenuredSpaceDaemonExpirationStrategy.java => LowHeapSpaceDaemonExpirationStrategy.java} (80%) rename subprojects/launcher/src/main/java/org/gradle/launcher/daemon/server/health/{LowPermGenDaemonExpirationStrategy.java => LowNonHeapDaemonExpirationStrategy.java} (79%) rename subprojects/launcher/src/test/groovy/org/gradle/launcher/daemon/server/health/{LowTenuredSpaceDaemonExpirationStrategyTest.groovy => LowHeapSpaceDaemonExpirationStrategyTest.groovy} (74%) rename subprojects/launcher/src/test/groovy/org/gradle/launcher/daemon/server/health/{LowPermGenDaemonExpirationStrategyTest.groovy => LowNonHeapDaemonExpirationStrategyTest.groovy} (76%) diff --git a/subprojects/base-services/src/main/java/org/gradle/internal/time/Clock.java b/subprojects/base-services/src/main/java/org/gradle/internal/time/Clock.java index d043e241d4dcf..ae9d1f5ae8fad 100644 --- a/subprojects/base-services/src/main/java/org/gradle/internal/time/Clock.java +++ b/subprojects/base-services/src/main/java/org/gradle/internal/time/Clock.java @@ -23,7 +23,7 @@ public interface Clock { /** - * The current time. + * The current time in millis. */ long getCurrentTime(); diff --git a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/OutputScrapingExecutionResult.java b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/OutputScrapingExecutionResult.java index d1d463958834e..8a920392162d2 100644 --- a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/OutputScrapingExecutionResult.java +++ b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/OutputScrapingExecutionResult.java @@ -23,7 +23,7 @@ import org.gradle.internal.featurelifecycle.LoggingDeprecatedFeatureHandler; import org.gradle.launcher.daemon.client.DaemonStartupMessage; import org.gradle.launcher.daemon.server.DaemonStateCoordinator; -import org.gradle.launcher.daemon.server.health.LowTenuredSpaceDaemonExpirationStrategy; +import org.gradle.launcher.daemon.server.health.LowHeapSpaceDaemonExpirationStrategy; import org.gradle.util.GUtil; import org.junit.ComparisonFailure; @@ -131,7 +131,7 @@ private String normalize(LogContent output) { } else if (line.contains(DaemonStateCoordinator.DAEMON_WILL_STOP_MESSAGE)) { // Remove the "Daemon will be shut down" message i++; - } else if (line.contains(LowTenuredSpaceDaemonExpirationStrategy.EXPIRE_DAEMON_MESSAGE)) { + } else if (line.contains(LowHeapSpaceDaemonExpirationStrategy.EXPIRE_DAEMON_MESSAGE)) { // Remove the "Expiring Daemon" message i++; } else if (line.contains(LoggingDeprecatedFeatureHandler.WARNING_SUMMARY)) { diff --git a/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/server/DaemonServices.java b/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/server/DaemonServices.java index 333989ec857ed..ffdf85dffbf45 100644 --- a/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/server/DaemonServices.java +++ b/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/server/DaemonServices.java @@ -58,6 +58,7 @@ import org.gradle.launcher.daemon.server.health.DaemonHealthStats; import org.gradle.launcher.daemon.server.health.DaemonMemoryStatus; import org.gradle.launcher.daemon.server.health.HealthExpirationStrategy; +import org.gradle.launcher.daemon.server.health.gc.GarbageCollectorMonitoringStrategy; import org.gradle.launcher.daemon.server.scaninfo.DaemonScanInfo; import org.gradle.launcher.daemon.server.scaninfo.DefaultDaemonScanInfo; import org.gradle.launcher.daemon.server.stats.DaemonRunningStats; @@ -105,7 +106,8 @@ public File getDaemonLogFile() { } protected DaemonMemoryStatus createDaemonMemoryStatus(DaemonHealthStats healthStats) { - return new DaemonMemoryStatus(healthStats); + GarbageCollectorMonitoringStrategy strategy = healthStats.getGcStrategy(); + return new DaemonMemoryStatus(healthStats, strategy.getHeapUsageThreshold(), strategy.getGcRateThreshold(), strategy.getNonHeapUsageThreshold(), strategy.getThrashingThreshold()); } protected DaemonHealthCheck createDaemonHealthCheck(ListenerManager listenerManager, HealthExpirationStrategy healthExpirationStrategy) { diff --git a/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/server/health/DaemonHealthStats.java b/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/server/health/DaemonHealthStats.java index 2b22c88b4552e..b61b4385570fb 100644 --- a/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/server/health/DaemonHealthStats.java +++ b/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/server/health/DaemonHealthStats.java @@ -18,8 +18,8 @@ import com.google.common.annotations.VisibleForTesting; import org.gradle.internal.concurrent.ExecutorFactory; -import org.gradle.internal.concurrent.Stoppable; import org.gradle.internal.concurrent.ManagedScheduledExecutor; +import org.gradle.internal.concurrent.Stoppable; import org.gradle.internal.util.NumberUtil; import org.gradle.launcher.daemon.server.health.gc.GarbageCollectionInfo; import org.gradle.launcher.daemon.server.health.gc.GarbageCollectionMonitor; @@ -58,8 +58,16 @@ public void stop() { } } - GarbageCollectionMonitor getGcMonitor() { - return gcMonitor; + public GarbageCollectorMonitoringStrategy getGcStrategy() { + return gcMonitor.getGcStrategy(); + } + + public GarbageCollectionStats getHeapStats() { + return gcMonitor.getHeapStats(); + } + + public GarbageCollectionStats getNonHeapStats() { + return gcMonitor.getNonHeapStats(); } /** @@ -79,26 +87,23 @@ private String getFirstBuildHealthInfo() { } private String getBuildHealthInfo(int nextBuildNum) { - if (gcMonitor.getGcStrategy() != GarbageCollectorMonitoringStrategy.UNKNOWN) { - GarbageCollectionStats tenuredStats = gcMonitor.getTenuredStats(); - GarbageCollectionStats permgenStats = gcMonitor.getPermGenStats(); - String message = format("Starting %s build in daemon [uptime: %s, performance: %s%%", - NumberUtil.ordinal(nextBuildNum), runningStats.getPrettyUpTime(), getCurrentPerformance()); - if (tenuredStats.getUsage() > 0) { - message += format(", GC rate: %.2f/s, tenured heap usage: %s%% of %s", tenuredStats.getRate(), tenuredStats.getUsage(), NumberUtil.formatBytes(tenuredStats.getMax())); - if (permgenStats.getUsage() > 0) { - message += format(", perm gen usage: %s%% of %s", - permgenStats.getUsage(), NumberUtil.formatBytes(permgenStats.getMax())); - } - } else { - message += ", no major garbage collections"; - } - message += "]"; - return message; - } else { - return format("Starting %s build in daemon [uptime: %s, performance: %s%%]", - NumberUtil.ordinal(nextBuildNum), runningStats.getPrettyUpTime(), getCurrentPerformance()); + + StringBuilder message = new StringBuilder(format("Starting %s build in daemon ", NumberUtil.ordinal(nextBuildNum))); + message.append(format("[uptime: %s, performance: %s%%", runningStats.getPrettyUpTime(), getCurrentPerformance())); + + GarbageCollectionStats heapStats = gcMonitor.getHeapStats(); + if (heapStats.isValid()) { + message.append(format(", GC rate: %.2f/s", heapStats.getGcRate())); + message.append(format(", heap usage: %s%% of %s", heapStats.getUsedPercent(), NumberUtil.formatBytes(heapStats.getMaxSizeInBytes()))); } + + GarbageCollectionStats nonHeapStats = gcMonitor.getNonHeapStats(); + if (nonHeapStats.isValid()) { + message.append(format(", non-heap usage: %s%% of %s", nonHeapStats.getUsedPercent(), NumberUtil.formatBytes(nonHeapStats.getMaxSizeInBytes()))); + } + message.append("]"); + + return message.toString(); } /** diff --git a/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/server/health/DaemonMemoryStatus.java b/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/server/health/DaemonMemoryStatus.java index 6b75cc7fa1e63..38df8f6d6d70f 100644 --- a/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/server/health/DaemonMemoryStatus.java +++ b/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/server/health/DaemonMemoryStatus.java @@ -16,96 +16,83 @@ package org.gradle.launcher.daemon.server.health; -import org.gradle.api.GradleException; import org.gradle.api.logging.Logger; import org.gradle.api.logging.Logging; import org.gradle.api.specs.Spec; import org.gradle.launcher.daemon.server.health.gc.GarbageCollectionStats; -import org.gradle.launcher.daemon.server.health.gc.GarbageCollectorMonitoringStrategy; - -import static java.lang.String.format; public class DaemonMemoryStatus { private static final Logger LOGGER = Logging.getLogger(DaemonMemoryStatus.class); public static final String ENABLE_PERFORMANCE_MONITORING = "org.gradle.daemon.performance.enable-monitoring"; - public static final String TENURED_USAGE_EXPIRE_AT = "org.gradle.daemon.performance.tenured-usage-expire-at"; - public static final String TENURED_RATE_EXPIRE_AT = "org.gradle.daemon.performance.tenured-rate-expire-at"; - public static final String PERMGEN_USAGE_EXPIRE_AT = "org.gradle.daemon.performance.permgen-usage-expire-at"; - public static final String THRASHING_EXPIRE_AT = "org.gradle.daemon.performance.thrashing-expire-at"; - private static final String TENURED = "tenured"; - private static final String PERMGEN = "perm gen"; + private static final String HEAP = "heap"; + private static final String NON_HEAP = "non-heap"; private final DaemonHealthStats stats; - private final GarbageCollectorMonitoringStrategy strategy; - private final int tenuredUsageThreshold; - private final double tenuredRateThreshold; - private final int permgenUsageThreshold; + private final int heapUsageThreshold; + private final double heapRateThreshold; + private final int nonHeapUsageThreshold; private final double thrashingThreshold; - public DaemonMemoryStatus(DaemonHealthStats stats) { + public DaemonMemoryStatus(DaemonHealthStats stats, int heapUsageThreshold, double heapRateThreshold, int nonHeapUsageThreshold, double thrashingThreshold) { this.stats = stats; - this.strategy = stats.getGcMonitor().getGcStrategy(); - this.tenuredUsageThreshold = parseValue(TENURED_USAGE_EXPIRE_AT, strategy.getTenuredUsageThreshold()); - this.tenuredRateThreshold = parseValue(TENURED_RATE_EXPIRE_AT, strategy.getGcRateThreshold()); - this.permgenUsageThreshold = parseValue(PERMGEN_USAGE_EXPIRE_AT, strategy.getPermGenUsageThreshold()); - this.thrashingThreshold = parseValue(THRASHING_EXPIRE_AT, strategy.getThrashingThreshold()); + this.heapUsageThreshold = heapUsageThreshold; + this.heapRateThreshold = heapRateThreshold; + this.nonHeapUsageThreshold = nonHeapUsageThreshold; + this.thrashingThreshold = thrashingThreshold; } - public boolean isTenuredSpaceExhausted() { - GarbageCollectionStats gcStats = stats.getGcMonitor().getTenuredStats(); + public boolean isHeapSpaceExhausted() { + GarbageCollectionStats gcStats = stats.getHeapStats(); - return exceedsThreshold(TENURED, gcStats, new Spec() { + return exceedsThreshold(HEAP, gcStats, new Spec() { @Override public boolean isSatisfiedBy(GarbageCollectionStats gcStats) { - return tenuredUsageThreshold != 0 - && tenuredRateThreshold != 0 - && gcStats.getEventCount() >= 5 - && gcStats.getUsage() >= tenuredUsageThreshold - && gcStats.getRate() >= tenuredRateThreshold; + return heapUsageThreshold != 0 + && heapRateThreshold != 0 + && gcStats.isValid() + && gcStats.getUsedPercent() >= heapUsageThreshold + && gcStats.getGcRate() >= heapRateThreshold; } }); } - public boolean isPermGenSpaceExhausted() { - GarbageCollectionStats gcStats = stats.getGcMonitor().getPermGenStats(); + public boolean isNonHeapSpaceExhausted() { + GarbageCollectionStats gcStats = stats.getNonHeapStats(); - return exceedsThreshold(PERMGEN, gcStats, new Spec() { + return exceedsThreshold(NON_HEAP, gcStats, new Spec() { @Override public boolean isSatisfiedBy(GarbageCollectionStats gcStats) { - return permgenUsageThreshold != 0 - && gcStats.getEventCount() >= 5 - && gcStats.getUsage() >= permgenUsageThreshold; + return nonHeapUsageThreshold != 0 + && gcStats.isValid() + && gcStats.getUsedPercent() >= nonHeapUsageThreshold; } }); } public boolean isThrashing() { - GarbageCollectionStats gcStats = stats.getGcMonitor().getTenuredStats(); + GarbageCollectionStats gcStats = stats.getHeapStats(); - return exceedsThreshold(TENURED, gcStats, new Spec() { + return exceedsThreshold(HEAP, gcStats, new Spec() { @Override public boolean isSatisfiedBy(GarbageCollectionStats gcStats) { - return tenuredUsageThreshold != 0 + return heapUsageThreshold != 0 && thrashingThreshold != 0 - && gcStats.getEventCount() >= 5 - && gcStats.getUsage() >= tenuredUsageThreshold - && gcStats.getRate() >= thrashingThreshold; + && gcStats.isValid() + && gcStats.getUsedPercent() >= heapUsageThreshold + && gcStats.getGcRate() >= thrashingThreshold; } }); } private boolean exceedsThreshold(String pool, GarbageCollectionStats gcStats, Spec spec) { - if (isEnabled() - && strategy != GarbageCollectorMonitoringStrategy.UNKNOWN - && spec.isSatisfiedBy(gcStats)) { - - if (gcStats.getUsage() > 0) { - LOGGER.debug(String.format("GC rate: %.2f/s %s usage: %s%%", gcStats.getRate(), pool, gcStats.getUsage())); + if (isEnabled() && spec.isSatisfiedBy(gcStats)) { + if (gcStats.isValid() && gcStats.getUsedPercent() > 0) { + LOGGER.debug(String.format("%s: GC rate: %.2f/s %s usage: %s%%", pool, gcStats.getGcRate(), pool, gcStats.getUsedPercent())); } else { - LOGGER.debug("GC rate: 0.0/s"); + LOGGER.debug("{}: GC rate: 0.0/s", pool); } return true; @@ -118,34 +105,4 @@ private boolean isEnabled() { String enabledValue = System.getProperty(ENABLE_PERFORMANCE_MONITORING, "true"); return Boolean.parseBoolean(enabledValue); } - - private static int parseValue(String property, int defaultValue) { - String expireAt = System.getProperty(property); - - if (expireAt == null) { - return defaultValue; - } - try { - return Integer.parseInt(expireAt); - } catch (Exception e) { - throw new GradleException(format( - "System property '%s' has incorrect value: '%s'. The value needs to be an integer.", - property, expireAt)); - } - } - - private static double parseValue(String property, double defaultValue) { - String expireAt = System.getProperty(property); - - if (expireAt == null) { - return defaultValue; - } - try { - return Double.parseDouble(expireAt); - } catch (Exception e) { - throw new GradleException(format( - "System property '%s' has incorrect value: '%s'. The value needs to be a double.", - property, expireAt)); - } - } } diff --git a/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/server/health/HealthExpirationStrategy.java b/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/server/health/HealthExpirationStrategy.java index d8480a40f6dfd..c4f258eb00da4 100644 --- a/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/server/health/HealthExpirationStrategy.java +++ b/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/server/health/HealthExpirationStrategy.java @@ -28,8 +28,8 @@ public class HealthExpirationStrategy implements DaemonExpirationStrategy { public HealthExpirationStrategy(DaemonMemoryStatus memoryStatus) { this.strategy = new AnyDaemonExpirationStrategy(ImmutableList.of( new GcThrashingDaemonExpirationStrategy(memoryStatus), - new LowTenuredSpaceDaemonExpirationStrategy(memoryStatus), - new LowPermGenDaemonExpirationStrategy(memoryStatus) + new LowHeapSpaceDaemonExpirationStrategy(memoryStatus), + new LowNonHeapDaemonExpirationStrategy(memoryStatus) )); } diff --git a/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/server/health/LowTenuredSpaceDaemonExpirationStrategy.java b/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/server/health/LowHeapSpaceDaemonExpirationStrategy.java similarity index 80% rename from subprojects/launcher/src/main/java/org/gradle/launcher/daemon/server/health/LowTenuredSpaceDaemonExpirationStrategy.java rename to subprojects/launcher/src/main/java/org/gradle/launcher/daemon/server/health/LowHeapSpaceDaemonExpirationStrategy.java index 2e44a16ea8f00..0337c53da3beb 100644 --- a/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/server/health/LowTenuredSpaceDaemonExpirationStrategy.java +++ b/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/server/health/LowHeapSpaceDaemonExpirationStrategy.java @@ -23,20 +23,20 @@ import static org.gradle.launcher.daemon.server.expiry.DaemonExpirationStatus.GRACEFUL_EXPIRE; -public class LowTenuredSpaceDaemonExpirationStrategy implements DaemonExpirationStrategy { +public class LowHeapSpaceDaemonExpirationStrategy implements DaemonExpirationStrategy { private final DaemonMemoryStatus status; - private static final Logger LOG = Logging.getLogger(LowTenuredSpaceDaemonExpirationStrategy.class); + private static final Logger LOG = Logging.getLogger(LowHeapSpaceDaemonExpirationStrategy.class); public static final String EXPIRATION_REASON = "after running out of JVM memory"; - public static final String EXPIRE_DAEMON_MESSAGE = "Expiring Daemon because JVM Tenured space is exhausted"; + public static final String EXPIRE_DAEMON_MESSAGE = "Expiring Daemon because JVM heap space is exhausted"; - public LowTenuredSpaceDaemonExpirationStrategy(DaemonMemoryStatus status) { + public LowHeapSpaceDaemonExpirationStrategy(DaemonMemoryStatus status) { this.status = status; } @Override public DaemonExpirationResult checkExpiration() { - if (status.isTenuredSpaceExhausted()) { + if (status.isHeapSpaceExhausted()) { LOG.warn(EXPIRE_DAEMON_MESSAGE); return new DaemonExpirationResult(GRACEFUL_EXPIRE, EXPIRATION_REASON); } else { diff --git a/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/server/health/LowPermGenDaemonExpirationStrategy.java b/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/server/health/LowNonHeapDaemonExpirationStrategy.java similarity index 79% rename from subprojects/launcher/src/main/java/org/gradle/launcher/daemon/server/health/LowPermGenDaemonExpirationStrategy.java rename to subprojects/launcher/src/main/java/org/gradle/launcher/daemon/server/health/LowNonHeapDaemonExpirationStrategy.java index c786a80831676..19e0f293d6a1b 100644 --- a/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/server/health/LowPermGenDaemonExpirationStrategy.java +++ b/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/server/health/LowNonHeapDaemonExpirationStrategy.java @@ -23,20 +23,20 @@ import static org.gradle.launcher.daemon.server.expiry.DaemonExpirationStatus.GRACEFUL_EXPIRE; -public class LowPermGenDaemonExpirationStrategy implements DaemonExpirationStrategy { +public class LowNonHeapDaemonExpirationStrategy implements DaemonExpirationStrategy { private final DaemonMemoryStatus status; - private static final Logger LOG = Logging.getLogger(LowPermGenDaemonExpirationStrategy.class); + private static final Logger LOG = Logging.getLogger(LowNonHeapDaemonExpirationStrategy.class); public static final String EXPIRATION_REASON = "after running out of JVM memory"; - public LowPermGenDaemonExpirationStrategy(DaemonMemoryStatus status) { + public LowNonHeapDaemonExpirationStrategy(DaemonMemoryStatus status) { this.status = status; } @Override public DaemonExpirationResult checkExpiration() { - if (status.isPermGenSpaceExhausted()) { - LOG.info("Expiring Daemon due to JVM PermGen space being exhausted"); + if (status.isNonHeapSpaceExhausted()) { + LOG.info("Expiring Daemon due to JVM Metaspace space being exhausted"); return new DaemonExpirationResult(GRACEFUL_EXPIRE, EXPIRATION_REASON); } else { return DaemonExpirationResult.NOT_TRIGGERED; diff --git a/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/server/health/gc/DefaultSlidingWindow.java b/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/server/health/gc/DefaultSlidingWindow.java index 68cc5a8893514..1138a88a96a55 100644 --- a/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/server/health/gc/DefaultSlidingWindow.java +++ b/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/server/health/gc/DefaultSlidingWindow.java @@ -18,7 +18,7 @@ import com.google.common.collect.Sets; -import java.util.Set; +import java.util.Collection; import java.util.concurrent.LinkedBlockingDeque; import java.util.concurrent.locks.ReentrantLock; @@ -43,7 +43,7 @@ public void slideAndInsert(T element) { } @Override - public Set snapshot() { + public Collection snapshot() { lock.lock(); try { return Sets.newLinkedHashSet(deque); @@ -51,4 +51,14 @@ public Set snapshot() { lock.unlock(); } } + + @Override + public T latest() { + lock.lock(); + try { + return deque.peekLast(); + } finally { + lock.unlock(); + } + } } diff --git a/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/server/health/gc/GarbageCollectionCheck.java b/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/server/health/gc/GarbageCollectionCheck.java index 9bee6e54d9eaf..c2c91a103fbc6 100644 --- a/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/server/health/gc/GarbageCollectionCheck.java +++ b/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/server/health/gc/GarbageCollectionCheck.java @@ -16,42 +16,49 @@ package org.gradle.launcher.daemon.server.health.gc; -import org.gradle.api.specs.Spec; -import org.gradle.util.CollectionUtils; +import org.gradle.internal.time.Clock; import java.lang.management.GarbageCollectorMXBean; import java.lang.management.ManagementFactory; import java.lang.management.MemoryPoolMXBean; +import java.lang.management.MemoryType; import java.util.List; -import java.util.Map; public class GarbageCollectionCheck implements Runnable { - final Map> events; - final List memoryPools; - final String garbageCollector; - - public GarbageCollectionCheck(Map> events, List memoryPools, String garbageCollector) { - this.events = events; - this.memoryPools = memoryPools; - this.garbageCollector = garbageCollector; + + private final Clock clock; + private final GarbageCollectorMXBean garbageCollectorMXBean; + + private final String heapMemoryPool; + private final SlidingWindow heapEvents; + + private final String nonHeapMemoryPool; + private final SlidingWindow nonHeapEvents; + + public GarbageCollectionCheck(Clock clock, GarbageCollectorMXBean garbageCollectorMXBean, String heapMemoryPool, SlidingWindow heapEvents, String nonHeapMemoryPool, SlidingWindow nonHeapEvents) { + this.clock = clock; + this.garbageCollectorMXBean = garbageCollectorMXBean; + this.heapMemoryPool = heapMemoryPool; + this.heapEvents = heapEvents; + this.nonHeapMemoryPool = nonHeapMemoryPool; + this.nonHeapEvents = nonHeapEvents; } @Override public void run() { - List garbageCollectorMXBeans = ManagementFactory.getGarbageCollectorMXBeans(); - GarbageCollectorMXBean garbageCollectorMXBean = CollectionUtils.findFirst(garbageCollectorMXBeans, new Spec() { - @Override - public boolean isSatisfiedBy(GarbageCollectorMXBean mbean) { - return mbean.getName().equals(garbageCollector); - } - }); - List memoryPoolMXBeans = ManagementFactory.getMemoryPoolMXBeans(); for (MemoryPoolMXBean memoryPoolMXBean : memoryPoolMXBeans) { - String pool = memoryPoolMXBean.getName(); - if (memoryPools.contains(pool)) { - GarbageCollectionEvent event = new GarbageCollectionEvent(System.currentTimeMillis(), memoryPoolMXBean.getCollectionUsage(), garbageCollectorMXBean.getCollectionCount()); - events.get(pool).slideAndInsert(event); + String poolName = memoryPoolMXBean.getName(); + if (memoryPoolMXBean.getType() == MemoryType.HEAP && poolName.equals(heapMemoryPool)) { + GarbageCollectionEvent latest = heapEvents.latest(); + long currentCount = garbageCollectorMXBean.getCollectionCount(); + // There has been a GC event + if (latest == null || latest.getCount() != currentCount) { + heapEvents.slideAndInsert(new GarbageCollectionEvent(clock.getCurrentTime(), memoryPoolMXBean.getCollectionUsage(), currentCount)); + } + } + if (memoryPoolMXBean.getType() == MemoryType.NON_HEAP && poolName.equals(nonHeapMemoryPool)) { + nonHeapEvents.slideAndInsert(new GarbageCollectionEvent(clock.getCurrentTime(), memoryPoolMXBean.getUsage(), -1)); } } } diff --git a/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/server/health/gc/GarbageCollectionEvent.java b/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/server/health/gc/GarbageCollectionEvent.java index f1887cc6a87fe..9c2be7a5387f6 100644 --- a/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/server/health/gc/GarbageCollectionEvent.java +++ b/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/server/health/gc/GarbageCollectionEvent.java @@ -19,9 +19,9 @@ import java.lang.management.MemoryUsage; public class GarbageCollectionEvent { - final long timestamp; - final MemoryUsage usage; - final long count; + private final long timestamp; + private final MemoryUsage usage; + private final long count; public GarbageCollectionEvent(long timestamp, MemoryUsage usage, long count) { this.timestamp = timestamp; diff --git a/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/server/health/gc/GarbageCollectionMonitor.java b/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/server/health/gc/GarbageCollectionMonitor.java index 1a67343e5dcc2..3bf5d5df24fdd 100644 --- a/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/server/health/gc/GarbageCollectionMonitor.java +++ b/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/server/health/gc/GarbageCollectionMonitor.java @@ -16,27 +16,28 @@ package org.gradle.launcher.daemon.server.health.gc; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; import org.gradle.api.Transformer; import org.gradle.api.logging.Logger; import org.gradle.api.logging.Logging; import org.gradle.api.specs.Spec; +import org.gradle.internal.jvm.Jvm; +import org.gradle.internal.time.Time; import org.gradle.util.CollectionUtils; import java.lang.management.GarbageCollectorMXBean; import java.lang.management.ManagementFactory; import java.util.List; -import java.util.Map; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; public class GarbageCollectionMonitor { - public static final int POLL_INTERVAL_SECONDS = 1; + private static final int POLL_INTERVAL_SECONDS = 1; private static final int POLL_DELAY_SECONDS = 1; private static final int EVENT_WINDOW = 20; private static final Logger LOGGER = Logging.getLogger(GarbageCollectionMonitor.class); - private final Map> events; + + private final SlidingWindow heapEvents; + private final SlidingWindow nonHeapEvents; private final GarbageCollectorMonitoringStrategy gcStrategy; private final ScheduledExecutorService pollingExecutor; @@ -47,20 +48,14 @@ public GarbageCollectionMonitor(ScheduledExecutorService pollingExecutor) { public GarbageCollectionMonitor(GarbageCollectorMonitoringStrategy gcStrategy, ScheduledExecutorService pollingExecutor) { this.pollingExecutor = pollingExecutor; this.gcStrategy = gcStrategy; - + this.heapEvents = new DefaultSlidingWindow(EVENT_WINDOW); + this.nonHeapEvents = new DefaultSlidingWindow(EVENT_WINDOW); if (gcStrategy != GarbageCollectorMonitoringStrategy.UNKNOWN) { - events = ImmutableMap.>of( - gcStrategy.getTenuredPoolName(), new DefaultSlidingWindow(EVENT_WINDOW), - gcStrategy.getPermGenPoolName(), new DefaultSlidingWindow(EVENT_WINDOW) - ); - pollForValues(gcStrategy.getGarbageCollectorName(), ImmutableList.copyOf(events.keySet())); - } else { - events = ImmutableMap.>builder().build(); + pollForValues(); } } private static GarbageCollectorMonitoringStrategy determineGcStrategy() { - JVMStrategy jvmStrategy = JVMStrategy.current(); final List garbageCollectors = CollectionUtils.collect(ManagementFactory.getGarbageCollectorMXBeans(), new Transformer() { @Override @@ -68,7 +63,7 @@ public String transform(GarbageCollectorMXBean garbageCollectorMXBean) { return garbageCollectorMXBean.getName(); } }); - GarbageCollectorMonitoringStrategy gcStrategy = CollectionUtils.findFirst(jvmStrategy.getGcStrategies(), new Spec() { + GarbageCollectorMonitoringStrategy gcStrategy = CollectionUtils.findFirst(GarbageCollectorMonitoringStrategy.values(), new Spec() { @Override public boolean isSatisfiedBy(GarbageCollectorMonitoringStrategy strategy) { return garbageCollectors.contains(strategy.getGarbageCollectorName()); @@ -76,74 +71,32 @@ public boolean isSatisfiedBy(GarbageCollectorMonitoringStrategy strategy) { }); if (gcStrategy == null) { - LOGGER.info("Unable to determine a garbage collection monitoring strategy for " + jvmStrategy.toString()); + LOGGER.info("Unable to determine a garbage collection monitoring strategy for " + Jvm.current().toString()); return GarbageCollectorMonitoringStrategy.UNKNOWN; } else { return gcStrategy; } } - private void pollForValues(String garbageCollectorName, List memoryPoolNames) { - pollingExecutor.scheduleAtFixedRate(new GarbageCollectionCheck(events, memoryPoolNames, garbageCollectorName), POLL_DELAY_SECONDS, POLL_INTERVAL_SECONDS, TimeUnit.SECONDS); - } - - public GarbageCollectionStats getTenuredStats() { - return getGarbageCollectionStatsWithEmptyDefault(gcStrategy.getTenuredPoolName()); + private void pollForValues() { + GarbageCollectorMXBean garbageCollectorMXBean = CollectionUtils.findFirst(ManagementFactory.getGarbageCollectorMXBeans(), new Spec() { + @Override + public boolean isSatisfiedBy(GarbageCollectorMXBean element) { + return element.getName().equals(gcStrategy.getGarbageCollectorName()); + } + }); + pollingExecutor.scheduleAtFixedRate(new GarbageCollectionCheck(Time.clock(), garbageCollectorMXBean, gcStrategy.getHeapPoolName(), heapEvents, gcStrategy.getNonHeapPoolName(), nonHeapEvents), POLL_DELAY_SECONDS, POLL_INTERVAL_SECONDS, TimeUnit.SECONDS); } - public GarbageCollectionStats getPermGenStats() { - return getGarbageCollectionStatsWithEmptyDefault(gcStrategy.getPermGenPoolName()); + public GarbageCollectionStats getHeapStats() { + return GarbageCollectionStats.forHeap(heapEvents.snapshot()); } - private GarbageCollectionStats getGarbageCollectionStatsWithEmptyDefault(final String memoryPoolName) { - SlidingWindow slidingWindow; - if ((memoryPoolName == null) || events.get(memoryPoolName) == null) { // events has no entries on UNKNOWN - slidingWindow = new DefaultSlidingWindow(EVENT_WINDOW); - } else { - slidingWindow = events.get(memoryPoolName); - } - return new GarbageCollectionStats(slidingWindow.snapshot()); + public GarbageCollectionStats getNonHeapStats() { + return GarbageCollectionStats.forNonHeap(nonHeapEvents.snapshot()); } public GarbageCollectorMonitoringStrategy getGcStrategy() { return gcStrategy; } - - public enum JVMStrategy { - IBM(GarbageCollectorMonitoringStrategy.IBM_ALL), - ORACLE_HOTSPOT(GarbageCollectorMonitoringStrategy.ORACLE_PARALLEL_CMS, - GarbageCollectorMonitoringStrategy.ORACLE_SERIAL, - GarbageCollectorMonitoringStrategy.ORACLE_6_CMS, - GarbageCollectorMonitoringStrategy.ORACLE_G1), - UNSUPPORTED(); - - final GarbageCollectorMonitoringStrategy[] gcStrategies; - - JVMStrategy(GarbageCollectorMonitoringStrategy... gcStrategies) { - this.gcStrategies = gcStrategies; - } - - static JVMStrategy current() { - String vmname = System.getProperty("java.vm.name"); - - if (vmname.equals("IBM J9 VM")) { - return IBM; - } - - if (vmname.startsWith("Java HotSpot(TM)")) { - return ORACLE_HOTSPOT; - } - - return UNSUPPORTED; - } - - public GarbageCollectorMonitoringStrategy[] getGcStrategies() { - return gcStrategies; - } - - @Override - public String toString() { - return "JVMStrategy{" + System.getProperty("java.vendor") + " version " + System.getProperty("java.version") + "}"; - } - } } diff --git a/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/server/health/gc/GarbageCollectionStats.java b/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/server/health/gc/GarbageCollectionStats.java index 7c0d318987501..04362d7bab879 100644 --- a/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/server/health/gc/GarbageCollectionStats.java +++ b/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/server/health/gc/GarbageCollectionStats.java @@ -16,118 +16,100 @@ package org.gradle.launcher.daemon.server.health.gc; +import com.google.common.collect.Iterables; import org.gradle.internal.util.NumberUtil; -import java.lang.management.MemoryUsage; -import java.util.Set; +import java.util.Collection; +import java.util.concurrent.TimeUnit; public class GarbageCollectionStats { - final private double rate; - final private long used; - final private long max; - final private long eventCount; - - public GarbageCollectionStats(Set events) { - this.rate = calculateRate(events); - this.used = calculateAverageUsage(events); - this.max = calculateMaxSize(events); - this.eventCount = events.size(); - } - - static double calculateRate(Set events) { - long firstGC = 0; - long lastGC = 0; - long firstCount = 0; - long lastCount = 0; - for (GarbageCollectionEvent event : events) { - // Skip if this was a polling event and the garbage collector did not fire in between events - if (event.getCount() == lastCount || event.getCount() == 0) { - continue; - } - - lastCount = event.getCount(); - - if (firstGC == 0) { - firstGC = event.getTimestamp(); - firstCount = event.getCount(); - } else { - lastGC = event.getTimestamp(); - } + private final double gcRate; + private final int usedPercent; + private final long maxSizeInBytes; + private final long eventCount; + + private GarbageCollectionStats(double gcRate, long usedSizeInBytes, long maxSizeInBytes, long eventCount) { + this.gcRate = gcRate; + if (maxSizeInBytes > 0) { + this.usedPercent = NumberUtil.percentOf(usedSizeInBytes, maxSizeInBytes); + } else { + this.usedPercent = 0; } + this.maxSizeInBytes = maxSizeInBytes; + this.eventCount = eventCount; + } - if (events.size() < 2 || lastCount == 0) { - return 0; + static GarbageCollectionStats forHeap(Collection events) { + if (events.isEmpty()) { + return noData(); } else { - long elapsed = lastGC - firstGC; - long totalCount = lastCount - firstCount; - return ((double) totalCount) / elapsed * 1000; + return new GarbageCollectionStats( + calculateRate(events), + calculateAverageUsage(events), + findMaxSize(events), + events.size() + ); } } - static long calculateAverageUsage(Set events) { - if (events.size() < 1) { - return -1; + static GarbageCollectionStats forNonHeap(Collection events) { + if (events.isEmpty()) { + return noData(); + } else { + return new GarbageCollectionStats( + 0, // non-heap spaces are not garbage collected + calculateAverageUsage(events), + findMaxSize(events), + events.size() + ); } + } - long total = 0; - long firstCount = 0; - long lastCount = 0; - for (GarbageCollectionEvent event : events) { - // Skip if the garbage collector did not fire in between events - if (event.getCount() == lastCount || event.getCount() == 0) { - continue; - } - - MemoryUsage usage = event.getUsage(); - if (firstCount == 0) { - firstCount = event.getCount(); - total += usage.getUsed(); - } else { - total += usage.getUsed() * (event.getCount() - lastCount); - } - - lastCount = event.getCount(); - } + private static GarbageCollectionStats noData() { + return new GarbageCollectionStats(0, 0, -1, 0); + } - if (lastCount == 0 || lastCount == firstCount) { - return -1; - } else { - long totalCount = lastCount - firstCount + 1; - return total / totalCount; + private static double calculateRate(Collection events) { + if (events.size() < 2) { + // not enough data points + return 0; } + GarbageCollectionEvent first = events.iterator().next(); + GarbageCollectionEvent last = Iterables.getLast(events); + // Total number of garbage collection events observed in the window + long gcCountDelta = last.getCount() - first.getCount(); + // Time interval between the first event in the window and the last + long timeDelta = TimeUnit.MILLISECONDS.toSeconds(last.getTimestamp() - first.getTimestamp()); + return (double)gcCountDelta / timeDelta; } - static long calculateMaxSize(Set events) { - if (events.size() < 1) { - return -1; + private static long calculateAverageUsage(Collection events) { + long sum = 0; + for (GarbageCollectionEvent event : events) { + sum += event.getUsage().getUsed(); } - - // Maximum pool size is fixed, so we should only need to get it from the first event - MemoryUsage usage = events.iterator().next().getUsage(); - return usage.getMax(); + return sum / events.size(); } - public double getRate() { - return rate; + private static long findMaxSize(Collection events) { + // Maximum pool size is fixed, so we should only need to get it from the first event + GarbageCollectionEvent first = events.iterator().next(); + return first.getUsage().getMax(); } - public int getUsage() { - if (used > 0 && max > 0) { - return NumberUtil.percentOf(used, max); - } else { - return -1; - } + public double getGcRate() { + return gcRate; } - public double getUsed() { - return used; + public int getUsedPercent() { + return usedPercent; } - public long getMax() { - return max; + public long getMaxSizeInBytes() { + return maxSizeInBytes; } - public long getEventCount() { - return eventCount; + public boolean isValid() { + return eventCount >= 5 && maxSizeInBytes > 0; } } diff --git a/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/server/health/gc/GarbageCollectorMonitoringStrategy.java b/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/server/health/gc/GarbageCollectorMonitoringStrategy.java index 9d8453a71a34a..943fff01f7993 100644 --- a/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/server/health/gc/GarbageCollectorMonitoringStrategy.java +++ b/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/server/health/gc/GarbageCollectorMonitoringStrategy.java @@ -17,33 +17,33 @@ package org.gradle.launcher.daemon.server.health.gc; public enum GarbageCollectorMonitoringStrategy { - ORACLE_PARALLEL_CMS("PS Old Gen", "PS Perm Gen", "PS MarkSweep", 1.2, 80, 80, 5.0), - ORACLE_6_CMS("CMS Old Gen", "CMS Perm Gen", "ConcurrentMarkSweep", 1.2, 80, 80, 5.0), - ORACLE_SERIAL("Tenured Gen", "Perm Gen", "MarkSweepCompact", 1.2, 80, 80, 5.0), - ORACLE_G1("G1 Old Gen", "G1 Perm Gen", "G1 Old Generation", 0.4, 75, 80, 2.0), - IBM_ALL("Java heap", "PermGen Not Used", "MarkSweepCompact", 0.8, 70, -1, 6.0), + ORACLE_PARALLEL_CMS("PS Old Gen", "Metaspace", "PS MarkSweep", 1.2, 80, 80, 5.0), + ORACLE_6_CMS("CMS Old Gen", "Metaspace", "ConcurrentMarkSweep", 1.2, 80, 80, 5.0), + ORACLE_SERIAL("Tenured Gen", "Metaspace", "MarkSweepCompact", 1.2, 80, 80, 5.0), + ORACLE_G1("G1 Old Gen", "Metaspace", "G1 Old Generation", 0.4, 75, 80, 2.0), + IBM_ALL("Java heap", "Not Used", "MarkSweepCompact", 0.8, 70, -1, 6.0), UNKNOWN(null, null, null, -1, -1, -1, -1); - private final String tenuredPoolName; - private final String permGenPoolName; + private final String heapPoolName; + private final String nonHeapPoolName; private final String garbageCollectorName; private final double gcRateThreshold; - private final int tenuredUsageThreshold; - private final int permGenUsageThreshold; + private final int heapUsageThreshold; + private final int nonHeapUsageThreshold; private final double thrashingThreshold; - GarbageCollectorMonitoringStrategy(String tenuredPoolName, String permGenPoolName, String garbageCollectorName, double gcRateThreshold, int tenuredUsageThreshold, int permGenUsageThreshold, double thrashingThreshold) { - this.tenuredPoolName = tenuredPoolName; - this.permGenPoolName = permGenPoolName; + GarbageCollectorMonitoringStrategy(String heapPoolName, String nonHeapPoolName, String garbageCollectorName, double gcRateThreshold, int heapUsageThreshold, int nonHeapUsageThreshold, double thrashingThreshold) { + this.heapPoolName = heapPoolName; + this.nonHeapPoolName = nonHeapPoolName; this.garbageCollectorName = garbageCollectorName; this.gcRateThreshold = gcRateThreshold; - this.tenuredUsageThreshold = tenuredUsageThreshold; - this.permGenUsageThreshold = permGenUsageThreshold; + this.heapUsageThreshold = heapUsageThreshold; + this.nonHeapUsageThreshold = nonHeapUsageThreshold; this.thrashingThreshold = thrashingThreshold; } - public String getTenuredPoolName() { - return tenuredPoolName; + public String getHeapPoolName() { + return heapPoolName; } public String getGarbageCollectorName() { @@ -54,16 +54,16 @@ public double getGcRateThreshold() { return gcRateThreshold; } - public int getTenuredUsageThreshold() { - return tenuredUsageThreshold; + public int getHeapUsageThreshold() { + return heapUsageThreshold; } - public String getPermGenPoolName() { - return permGenPoolName; + public String getNonHeapPoolName() { + return nonHeapPoolName; } - public int getPermGenUsageThreshold() { - return permGenUsageThreshold; + public int getNonHeapUsageThreshold() { + return nonHeapUsageThreshold; } public double getThrashingThreshold() { diff --git a/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/server/health/gc/SlidingWindow.java b/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/server/health/gc/SlidingWindow.java index 2b2f2c8f3040f..1f09fa5643236 100644 --- a/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/server/health/gc/SlidingWindow.java +++ b/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/server/health/gc/SlidingWindow.java @@ -16,7 +16,7 @@ package org.gradle.launcher.daemon.server.health.gc; -import java.util.Set; +import java.util.Collection; public interface SlidingWindow { /** @@ -24,12 +24,17 @@ public interface SlidingWindow { * * @param element The element to add */ - public void slideAndInsert(T element); + void slideAndInsert(T element); /** - * Returns a snapshot of the elements in the window as a Set view. + * Returns a snapshot of the elements in the window. * - * @return Set view of the elements + * @return collection view of the elements */ - public Set snapshot(); + Collection snapshot(); + + /** + * @return the latest event in the window. + */ + T latest(); } diff --git a/subprojects/launcher/src/test/groovy/org/gradle/launcher/daemon/server/health/DaemonHealthStatsTest.groovy b/subprojects/launcher/src/test/groovy/org/gradle/launcher/daemon/server/health/DaemonHealthStatsTest.groovy index 03626460557ae..08db6d2271d2e 100644 --- a/subprojects/launcher/src/test/groovy/org/gradle/launcher/daemon/server/health/DaemonHealthStatsTest.groovy +++ b/subprojects/launcher/src/test/groovy/org/gradle/launcher/daemon/server/health/DaemonHealthStatsTest.groovy @@ -42,19 +42,18 @@ class DaemonHealthStatsTest extends Specification { def "consumes subsequent builds"() { when: gcInfo.getCollectionTime() >> 25 - gcMonitor.getTenuredStats() >> { - Stub(GarbageCollectionStats) { - getUsage() >> 10 - getMax() >> 1024 - getRate() >> 1.0 - } + gcMonitor.getHeapStats() >> { + new GarbageCollectionStats(1.0, 103, 1024, 5) + } + gcMonitor.getNonHeapStats() >> { + new GarbageCollectionStats(0, 1024, 2048, 5) } runningStats.getBuildCount() >> 1 runningStats.getPrettyUpTime() >> "3 mins" runningStats.getAllBuildsTime() >> 1000 then: - healthStats.healthInfo == String.format("Starting 2nd build in daemon [uptime: 3 mins, performance: 98%%, GC rate: %.2f/s, tenured heap usage: 10%% of %.1f kB]", 1.0, 1.0) + healthStats.healthInfo == "Starting 2nd build in daemon [uptime: 3 mins, performance: 98%, GC rate: 1.00/s, heap usage: 10% of 1.0 kB, non-heap usage: 50% of 2.0 kB]" } def "handles no garbage collection data"() { @@ -64,16 +63,15 @@ class DaemonHealthStatsTest extends Specification { runningStats.getPrettyUpTime() >> "3 mins" runningStats.getAllBuildsTime() >> 1000 - gcMonitor.getTenuredStats() >> { - Stub(GarbageCollectionStats) { - getUsage() >> -1 - getMax() >> -1 - getRate() >> 0 - } + gcMonitor.getHeapStats() >> { + GarbageCollectionStats.noData() + } + gcMonitor.getNonHeapStats() >> { + GarbageCollectionStats.noData() } then: - healthStats.healthInfo == "Starting 2nd build in daemon [uptime: 3 mins, performance: 98%, no major garbage collections]" + healthStats.healthInfo == "Starting 2nd build in daemon [uptime: 3 mins, performance: 98%]" } } diff --git a/subprojects/launcher/src/test/groovy/org/gradle/launcher/daemon/server/health/DaemonMemoryStatusTest.groovy b/subprojects/launcher/src/test/groovy/org/gradle/launcher/daemon/server/health/DaemonMemoryStatusTest.groovy index 7d5978152cd7c..aea4fba63d870 100644 --- a/subprojects/launcher/src/test/groovy/org/gradle/launcher/daemon/server/health/DaemonMemoryStatusTest.groovy +++ b/subprojects/launcher/src/test/groovy/org/gradle/launcher/daemon/server/health/DaemonMemoryStatusTest.groovy @@ -16,155 +16,110 @@ package org.gradle.launcher.daemon.server.health -import org.gradle.api.GradleException -import org.gradle.launcher.daemon.server.health.gc.GarbageCollectionMonitor import org.gradle.launcher.daemon.server.health.gc.GarbageCollectionStats -import org.gradle.launcher.daemon.server.health.gc.GarbageCollectorMonitoringStrategy import org.gradle.util.SetSystemProperties import org.junit.Rule import spock.lang.Specification import spock.lang.Unroll -import static DaemonMemoryStatus.PERMGEN_USAGE_EXPIRE_AT -import static DaemonMemoryStatus.TENURED_RATE_EXPIRE_AT -import static DaemonMemoryStatus.TENURED_USAGE_EXPIRE_AT -import static DaemonMemoryStatus.THRASHING_EXPIRE_AT class DaemonMemoryStatusTest extends Specification { - @Rule SetSystemProperties props = new SetSystemProperties() + @Rule + SetSystemProperties props = new SetSystemProperties() - def gcMonitor = Mock(GarbageCollectionMonitor) def stats = Mock(DaemonHealthStats) - - def "validates supplied tenured usage threshold value"() { - System.setProperty(TENURED_USAGE_EXPIRE_AT, "foo") - - when: - status.isTenuredSpaceExhausted() - - then: - def ex = thrown(GradleException) - ex.message == "System property 'org.gradle.daemon.performance.tenured-usage-expire-at' has incorrect value: 'foo'. The value needs to be an integer." - } - - def "validates supplied tenured rate threshold value"() { - System.setProperty(TENURED_RATE_EXPIRE_AT, "foo") - - when: - status.isTenuredSpaceExhausted() - - then: - def ex = thrown(GradleException) - ex.message == "System property 'org.gradle.daemon.performance.tenured-rate-expire-at' has incorrect value: 'foo'. The value needs to be a double." + DaemonMemoryStatus create(int heapUsageThreshold, double heapRateThreshold, int nonHeapUsageThreshold, double thrashingThreshold) { + return new DaemonMemoryStatus(stats, heapUsageThreshold, heapRateThreshold, nonHeapUsageThreshold, thrashingThreshold) } @Unroll - def "knows when tenured space is exhausted (#rateThreshold <= #rate, #usageThreshold <= #used)"() { + def "knows when heap space is exhausted (#rateThreshold <= #rate, #usageThreshold <= #usage)"(double rateThreshold, int usageThreshold, double rate, int usage, boolean unhealthy) { when: - System.setProperty(TENURED_USAGE_EXPIRE_AT, usageThreshold.toString()) - System.setProperty(TENURED_RATE_EXPIRE_AT, rateThreshold.toString()) - gcMonitor.getTenuredStats() >> { - Stub(GarbageCollectionStats) { - getUsage() >> used - getRate() >> rate - getEventCount() >> 10 - } + def status = create(usageThreshold, rateThreshold, 100, 100) + stats.getHeapStats() >> { + new GarbageCollectionStats(rate, usage, 100, 10) } then: - status.isTenuredSpaceExhausted() == unhealthy + status.isHeapSpaceExhausted() == unhealthy where: - rateThreshold | usageThreshold | rate | used | unhealthy - 1.0 | 90 | 1.1 | 100 | true - 1.0 | 90 | 1.1 | 91 | true - 1.0 | 90 | 1.1 | 89 | false - 1.0 | 90 | 0.9 | 91 | false - 1.0 | 0 | 1.0 | 0 | false - 1.0 | 0 | 1.0 | -1 | false - 0 | 90 | 0 | 100 | false - 1.0 | 0 | 1.1 | 100 | false - 0 | 90 | 1.1 | 100 | false - 1.0 | 100 | 1.1 | 100 | true - 1.0 | 75 | 1.1 | 75 | true - 1.0 | 75 | 1.0 | 100 | true + rateThreshold | usageThreshold | rate | usage | unhealthy + 1.0 | 90 | 1.1 | 100 | true + 1.0 | 90 | 1.1 | 91 | true + 1.0 | 90 | 1.1 | 89 | false + 1.0 | 90 | 0.9 | 91 | false + 1.0 | 0 | 1.0 | 0 | false + 0 | 90 | 0 | 100 | false + 1.0 | 0 | 1.1 | 100 | false + 0 | 90 | 1.1 | 100 | false + 1.0 | 100 | 1.1 | 100 | true + 1.0 | 75 | 1.1 | 75 | true + 1.0 | 75 | 1.0 | 100 | true } @Unroll - def "knows when perm gen space is exhausted (#usageThreshold <= #used, #usageThreshold <= #used)"() { + def "knows when metaspace is exhausted (#usageThreshold <= #usage, #usageThreshold <= #usage)"() { when: - System.setProperty(PERMGEN_USAGE_EXPIRE_AT, usageThreshold.toString()) - gcMonitor.getPermGenStats() >> { - Stub(GarbageCollectionStats) { - getUsage() >> used - getEventCount() >> 10 - } + def status = create(100, 100, usageThreshold, 100) + stats.getNonHeapStats() >> { + new GarbageCollectionStats(0, usage, 100, 10) } then: - status.isPermGenSpaceExhausted() == unhealthy + status.isNonHeapSpaceExhausted() == unhealthy where: - usageThreshold | used | unhealthy - 90 | 100 | true - 90 | 91 | true - 90 | 90 | true - 90 | 89 | false - 0 | 0 | false - 0 | 100 | false - 100 | 100 | true + usageThreshold | usage | unhealthy + 90 | 100 | true + 90 | 91 | true + 90 | 90 | true + 90 | 89 | false + 0 | 0 | false + 0 | 100 | false + 100 | 100 | true } @Unroll - def "knows when gc is thrashing (#rateThreshold <= #rate)"() { + def "knows when gc is thrashing (#rateThreshold <= #rate)"(double rateThreshold, int usageThreshold, double rate, int usage, boolean thrashing) { when: - System.setProperty(TENURED_USAGE_EXPIRE_AT, usageThreshold.toString()) - System.setProperty(THRASHING_EXPIRE_AT, rateThreshold.toString()) - gcMonitor.getTenuredStats() >> { - Stub(GarbageCollectionStats) { - getRate() >> rate - getUsage() >> usage - getEventCount() >> 10 - } + def status = create(usageThreshold, 100, 100, rateThreshold) + stats.getHeapStats() >> { + new GarbageCollectionStats(rate, usage, 100, 10) } then: status.isThrashing() == thrashing where: - rateThreshold | usageThreshold | rate | usage | thrashing - 10 | 90 | 15 | 100 | true - 10 | 90 | 10.1 | 91 | true - 10 | 90 | 10.1 | 89 | false - 10 | 90 | 9.9 | 91 | false - 10 | 0 | 15 | 0 | false - 0 | 90 | 0 | 100 | false - 10 | 0 | 10.1 | 100 | false - 0 | 90 | 10.1 | 100 | false - 10 | 100 | 10.1 | 100 | true - 10 | 75 | 10.1 | 75 | true - 10 | 75 | 10 | 100 | true - 10 | 90 | 0 | 100 | false - 10 | 90 | 15 | 0 | false + rateThreshold | usageThreshold | rate | usage | thrashing + 10 | 90 | 15 | 100 | true + 10 | 90 | 10.1 | 91 | true + 10 | 90 | 10.1 | 89 | false + 10 | 90 | 9.9 | 91 | false + 10 | 0 | 15 | 0 | false + 0 | 90 | 0 | 100 | false + 10 | 0 | 10.1 | 100 | false + 0 | 90 | 10.1 | 100 | false + 10 | 100 | 10.1 | 100 | true + 10 | 75 | 10.1 | 75 | true + 10 | 75 | 10 | 100 | true + 10 | 90 | 0 | 100 | false + 10 | 90 | 15 | 0 | false } def "can disable daemon performance monitoring"() { when: + def status = create(100, 100, 100, 100) System.setProperty(DaemonMemoryStatus.ENABLE_PERFORMANCE_MONITORING, "false") then: - !status.isTenuredSpaceExhausted() + !status.isHeapSpaceExhausted() and: - !status.isPermGenSpaceExhausted() + !status.isNonHeapSpaceExhausted() and: !status.isThrashing() } - - DaemonMemoryStatus getStatus() { - 1 * gcMonitor.gcStrategy >> GarbageCollectorMonitoringStrategy.ORACLE_PARALLEL_CMS - _ * stats.getGcMonitor() >> gcMonitor - return new DaemonMemoryStatus(stats) - } } diff --git a/subprojects/launcher/src/test/groovy/org/gradle/launcher/daemon/server/health/LowTenuredSpaceDaemonExpirationStrategyTest.groovy b/subprojects/launcher/src/test/groovy/org/gradle/launcher/daemon/server/health/LowHeapSpaceDaemonExpirationStrategyTest.groovy similarity index 74% rename from subprojects/launcher/src/test/groovy/org/gradle/launcher/daemon/server/health/LowTenuredSpaceDaemonExpirationStrategyTest.groovy rename to subprojects/launcher/src/test/groovy/org/gradle/launcher/daemon/server/health/LowHeapSpaceDaemonExpirationStrategyTest.groovy index bacd4684a2e45..9f07beb337198 100644 --- a/subprojects/launcher/src/test/groovy/org/gradle/launcher/daemon/server/health/LowTenuredSpaceDaemonExpirationStrategyTest.groovy +++ b/subprojects/launcher/src/test/groovy/org/gradle/launcher/daemon/server/health/LowHeapSpaceDaemonExpirationStrategyTest.groovy @@ -21,31 +21,31 @@ import spock.lang.Specification import static org.gradle.launcher.daemon.server.expiry.DaemonExpirationStatus.GRACEFUL_EXPIRE -class LowTenuredSpaceDaemonExpirationStrategyTest extends Specification { +class LowHeapSpaceDaemonExpirationStrategyTest extends Specification { private final DaemonMemoryStatus status = Mock(DaemonMemoryStatus) def "daemon is expired when tenured space is low" () { - LowTenuredSpaceDaemonExpirationStrategy strategy = new LowTenuredSpaceDaemonExpirationStrategy(status) + LowHeapSpaceDaemonExpirationStrategy strategy = new LowHeapSpaceDaemonExpirationStrategy(status) when: DaemonExpirationResult result = strategy.checkExpiration() then: - 1 * status.isTenuredSpaceExhausted() >> true + 1 * status.isHeapSpaceExhausted() >> true and: result.status == GRACEFUL_EXPIRE - result.reason == LowTenuredSpaceDaemonExpirationStrategy.EXPIRATION_REASON + result.reason == LowHeapSpaceDaemonExpirationStrategy.EXPIRATION_REASON } def "daemon is not expired when tenured space is fine" () { - LowTenuredSpaceDaemonExpirationStrategy strategy = new LowTenuredSpaceDaemonExpirationStrategy(status) + LowHeapSpaceDaemonExpirationStrategy strategy = new LowHeapSpaceDaemonExpirationStrategy(status) when: DaemonExpirationResult result = strategy.checkExpiration() then: - 1 * status.isTenuredSpaceExhausted() >> false + 1 * status.isHeapSpaceExhausted() >> false and: result == DaemonExpirationResult.NOT_TRIGGERED diff --git a/subprojects/launcher/src/test/groovy/org/gradle/launcher/daemon/server/health/LowPermGenDaemonExpirationStrategyTest.groovy b/subprojects/launcher/src/test/groovy/org/gradle/launcher/daemon/server/health/LowNonHeapDaemonExpirationStrategyTest.groovy similarity index 76% rename from subprojects/launcher/src/test/groovy/org/gradle/launcher/daemon/server/health/LowPermGenDaemonExpirationStrategyTest.groovy rename to subprojects/launcher/src/test/groovy/org/gradle/launcher/daemon/server/health/LowNonHeapDaemonExpirationStrategyTest.groovy index 4c7cc5754cfa4..10f4156aa7aaf 100644 --- a/subprojects/launcher/src/test/groovy/org/gradle/launcher/daemon/server/health/LowPermGenDaemonExpirationStrategyTest.groovy +++ b/subprojects/launcher/src/test/groovy/org/gradle/launcher/daemon/server/health/LowNonHeapDaemonExpirationStrategyTest.groovy @@ -21,31 +21,31 @@ import spock.lang.Specification import static org.gradle.launcher.daemon.server.expiry.DaemonExpirationStatus.GRACEFUL_EXPIRE -class LowPermGenDaemonExpirationStrategyTest extends Specification { +class LowNonHeapDaemonExpirationStrategyTest extends Specification { private final DaemonMemoryStatus status = Mock(DaemonMemoryStatus) def "daemon is expired when perm gen space is low" () { - LowPermGenDaemonExpirationStrategy strategy = new LowPermGenDaemonExpirationStrategy(status) + LowNonHeapDaemonExpirationStrategy strategy = new LowNonHeapDaemonExpirationStrategy(status) when: DaemonExpirationResult result = strategy.checkExpiration() then: - 1 * status.isPermGenSpaceExhausted() >> true + 1 * status.isNonHeapSpaceExhausted() >> true and: result.status == GRACEFUL_EXPIRE - result.reason == LowPermGenDaemonExpirationStrategy.EXPIRATION_REASON + result.reason == LowNonHeapDaemonExpirationStrategy.EXPIRATION_REASON } def "daemon is not expired when tenured space is fine" () { - LowPermGenDaemonExpirationStrategy strategy = new LowPermGenDaemonExpirationStrategy(status) + LowNonHeapDaemonExpirationStrategy strategy = new LowNonHeapDaemonExpirationStrategy(status) when: DaemonExpirationResult result = strategy.checkExpiration() then: - 1 * status.isPermGenSpaceExhausted() >> false + 1 * status.isNonHeapSpaceExhausted() >> false and: result == DaemonExpirationResult.NOT_TRIGGERED diff --git a/subprojects/launcher/src/test/groovy/org/gradle/launcher/daemon/server/health/gc/GarbageCollectionMonitorTest.groovy b/subprojects/launcher/src/test/groovy/org/gradle/launcher/daemon/server/health/gc/GarbageCollectionMonitorTest.groovy index 6e14e5073ea9e..66a4a6dfbf408 100644 --- a/subprojects/launcher/src/test/groovy/org/gradle/launcher/daemon/server/health/gc/GarbageCollectionMonitorTest.groovy +++ b/subprojects/launcher/src/test/groovy/org/gradle/launcher/daemon/server/health/gc/GarbageCollectionMonitorTest.groovy @@ -17,31 +17,12 @@ package org.gradle.launcher.daemon.server.health.gc import spock.lang.Specification -import spock.lang.Unroll import java.util.concurrent.ScheduledExecutorService class GarbageCollectionMonitorTest extends Specification { ScheduledExecutorService scheduledExecutorService = Mock(ScheduledExecutorService) - @Unroll - def "schedules periodic garbage collection checks (#strategy)"() { - when: - new GarbageCollectionMonitor(strategy, scheduledExecutorService) - - then: - 1 * scheduledExecutorService.scheduleAtFixedRate(_, _, _, _) >> { args -> - GarbageCollectionCheck check = args[0] as GarbageCollectionCheck - assert check.garbageCollector == strategy.garbageCollectorName - assert check.memoryPools == [ strategy.tenuredPoolName, strategy.permGenPoolName ] - assert check.events.containsKey(strategy.tenuredPoolName) - assert check.events.containsKey(strategy.permGenPoolName) - } - - where: - strategy << GarbageCollectorMonitoringStrategy.values() - GarbageCollectorMonitoringStrategy.UNKNOWN - } - def "does not schedule garbage collection check when GC strategy is unknown" () { when: new GarbageCollectionMonitor(GarbageCollectorMonitoringStrategy.UNKNOWN, scheduledExecutorService) @@ -50,23 +31,23 @@ class GarbageCollectionMonitorTest extends Specification { 0 * scheduledExecutorService.scheduleAtFixedRate(_, _, _, _) } - def "tenured stats defaults to empty given unknown garbage collector"() { + def "heap stats defaults to empty given unknown garbage collector"() { given: def monitor = new GarbageCollectionMonitor(GarbageCollectorMonitoringStrategy.UNKNOWN, scheduledExecutorService) when: - monitor.getTenuredStats() + monitor.getHeapStats() then: noExceptionThrown() } - def "perm gen stats defaults to empty given unknown garbage collector"() { + def "non-heap stats defaults to empty given unknown garbage collector"() { given: def monitor = new GarbageCollectionMonitor(GarbageCollectorMonitoringStrategy.UNKNOWN, scheduledExecutorService) when: - monitor.getPermGenStats() + monitor.getNonHeapStats() then: noExceptionThrown() diff --git a/subprojects/launcher/src/test/groovy/org/gradle/launcher/daemon/server/health/gc/GarbageCollectionStatsTest.groovy b/subprojects/launcher/src/test/groovy/org/gradle/launcher/daemon/server/health/gc/GarbageCollectionStatsTest.groovy index 2e7deedf71e0f..a9c8d4f0a7dab 100644 --- a/subprojects/launcher/src/test/groovy/org/gradle/launcher/daemon/server/health/gc/GarbageCollectionStatsTest.groovy +++ b/subprojects/launcher/src/test/groovy/org/gradle/launcher/daemon/server/health/gc/GarbageCollectionStatsTest.groovy @@ -20,25 +20,66 @@ import spock.lang.Specification import java.lang.management.MemoryUsage; -public class GarbageCollectionStatsTest extends Specification { - def "correctly calculates garbage collection rate"() { +class GarbageCollectionStatsTest extends Specification { + def "correctly calculates stats for heaps"() { + def heapStats = GarbageCollectionStats.forHeap(heapEvents) expect: - new GarbageCollectionStats(checkStream).rate == (double)8/3 + heapStats.valid + heapStats.gcRate == 3.0d + heapStats.maxSizeInBytes == 1000 + heapStats.usedPercent == 50 } - def "correctly calculates average usage"() { + def "correctly calculates stats for non-heaps"() { + def nonHeapStats = GarbageCollectionStats.forNonHeap(nonHeapEvents) expect: - new GarbageCollectionStats(checkStream).usage == 73 + nonHeapStats.valid + nonHeapStats.gcRate == 0 + nonHeapStats.maxSizeInBytes == 1000 + nonHeapStats.usedPercent == 70 } - Set getCheckStream() { - Set checks = [ - new GarbageCollectionEvent(1000, new MemoryUsage(0, 250, 1000, 1000), 2), - new GarbageCollectionEvent(2000, new MemoryUsage(0, 500, 1000, 1000), 3), - new GarbageCollectionEvent(2500, new MemoryUsage(0, 500, 1000, 1000), 3), - new GarbageCollectionEvent(3000, new MemoryUsage(0, 750, 1000, 1000), 6), - new GarbageCollectionEvent(3500, new MemoryUsage(0, 750, 1000, 1000), 6), - new GarbageCollectionEvent(4000, new MemoryUsage(0, 900, 1000, 1000), 10) + def "reports invalid when fewer than 5 events are seen"() { + expect: + !stats.valid + stats.maxSizeInBytes == 1000 + where: + stats << [ + GarbageCollectionStats.forHeap(heapEvents.take(3)), + GarbageCollectionStats.forNonHeap(nonHeapEvents.take(3)) + ] + } + + def "reports invalid when no events are seen"() { + expect: + !stats.valid + stats.gcRate == 0 + stats.maxSizeInBytes == -1 + stats.usedPercent == 0 + where: + stats << [ + GarbageCollectionStats.forHeap([]), + GarbageCollectionStats.forNonHeap([]) + ] + } + + def getHeapEvents() { + return [ + new GarbageCollectionEvent(0000, new MemoryUsage(0, 100, 1000, 1000), 1), + new GarbageCollectionEvent(1000, new MemoryUsage(0, 250, 1000, 1000), 2), + new GarbageCollectionEvent(2000, new MemoryUsage(0, 500, 1000, 1000), 3), + new GarbageCollectionEvent(3000, new MemoryUsage(0, 750, 1000, 1000), 6), + new GarbageCollectionEvent(4000, new MemoryUsage(0, 900, 1000, 1000), 13) + ] + } + + def getNonHeapEvents() { + return [ + new GarbageCollectionEvent(0000, new MemoryUsage(0, 500, 1000, 1000), 0), + new GarbageCollectionEvent(1000, new MemoryUsage(0, 600, 1000, 1000), 0), + new GarbageCollectionEvent(2000, new MemoryUsage(0, 700, 1000, 1000), 0), + new GarbageCollectionEvent(3000, new MemoryUsage(0, 800, 1000, 1000), 0), + new GarbageCollectionEvent(4000, new MemoryUsage(0, 900, 1000, 1000), 0) ] } } diff --git a/subprojects/soak/src/integTest/groovy/org/gradle/launcher/daemon/DaemonPerformanceMonitoringSoakTest.groovy b/subprojects/soak/src/integTest/groovy/org/gradle/launcher/daemon/DaemonPerformanceMonitoringSoakTest.groovy index b9b8f7f2273a5..fa9596545fc1d 100644 --- a/subprojects/soak/src/integTest/groovy/org/gradle/launcher/daemon/DaemonPerformanceMonitoringSoakTest.groovy +++ b/subprojects/soak/src/integTest/groovy/org/gradle/launcher/daemon/DaemonPerformanceMonitoringSoakTest.groovy @@ -123,7 +123,7 @@ class DaemonPerformanceMonitoringSoakTest extends DaemonMultiJdkIntegrationTest } def "when build leaks permgen space daemon is expired"() { - assumeTrue(version.vendor != JdkVendor.IBM && version.version == "1.7") + assumeTrue(version.vendor != JdkVendor.IBM) when: setupBuildScript = permGenLeak From 24dce2adfca65596a8a5efb2e050c5d6c32ec251 Mon Sep 17 00:00:00 2001 From: "Rodrigo B. de Oliveira" Date: Sat, 23 Feb 2019 15:26:12 -0300 Subject: [PATCH 090/853] Move `assumeJava11` closer to the other `assume*` functions --- .../integration/ProjectSchemaAccessorsIntegrationTest.kt | 8 -------- .../kotlin/dsl/fixtures/AbstractKotlinIntegrationTest.kt | 5 +++++ 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/subprojects/kotlin-dsl-integ-tests/src/integTest/kotlin/org/gradle/kotlin/dsl/integration/ProjectSchemaAccessorsIntegrationTest.kt b/subprojects/kotlin-dsl-integ-tests/src/integTest/kotlin/org/gradle/kotlin/dsl/integration/ProjectSchemaAccessorsIntegrationTest.kt index 3b3921c8f20e9..f18e7e9638c2e 100644 --- a/subprojects/kotlin-dsl-integ-tests/src/integTest/kotlin/org/gradle/kotlin/dsl/integration/ProjectSchemaAccessorsIntegrationTest.kt +++ b/subprojects/kotlin-dsl-integ-tests/src/integTest/kotlin/org/gradle/kotlin/dsl/integration/ProjectSchemaAccessorsIntegrationTest.kt @@ -16,8 +16,6 @@ package org.gradle.kotlin.dsl.integration -import org.gradle.api.JavaVersion - import org.gradle.kotlin.dsl.fixtures.FoldersDsl import org.gradle.kotlin.dsl.fixtures.FoldersDslExpression import org.gradle.kotlin.dsl.fixtures.containsMultiLineString @@ -29,7 +27,6 @@ import org.hamcrest.CoreMatchers.containsString import org.hamcrest.CoreMatchers.not import org.hamcrest.MatcherAssert.assertThat -import org.junit.Assume.assumeTrue import org.junit.Ignore import org.junit.Test @@ -1204,11 +1201,6 @@ class ProjectSchemaAccessorsIntegrationTest : AbstractPluginIntegrationTest() { ) } - private - fun assumeJava11() { - assumeTrue("Test requires Java 11", JavaVersion.current().isJava11Compatible) - } - private fun withBuildSrc(contents: FoldersDslExpression) { withFolders { diff --git a/subprojects/kotlin-dsl-test-fixtures/src/main/kotlin/org/gradle/kotlin/dsl/fixtures/AbstractKotlinIntegrationTest.kt b/subprojects/kotlin-dsl-test-fixtures/src/main/kotlin/org/gradle/kotlin/dsl/fixtures/AbstractKotlinIntegrationTest.kt index 7309eb5cbfb68..94c17e21b782b 100644 --- a/subprojects/kotlin-dsl-test-fixtures/src/main/kotlin/org/gradle/kotlin/dsl/fixtures/AbstractKotlinIntegrationTest.kt +++ b/subprojects/kotlin-dsl-test-fixtures/src/main/kotlin/org/gradle/kotlin/dsl/fixtures/AbstractKotlinIntegrationTest.kt @@ -197,6 +197,11 @@ abstract class AbstractKotlinIntegrationTest : AbstractIntegrationTest() { assumeTrue("Test disabled under JDK 11 and higher", JavaVersion.current() < JavaVersion.VERSION_11) } + protected + fun assumeJava11() { + assumeTrue("Test requires Java 11 or higher", JavaVersion.current().isJava11Compatible) + } + protected fun assumeNonEmbeddedGradleExecuter() { assumeFalse(GradleContextualExecuter.isEmbedded()) From 3741a22a820868aba45dfc4def2d663e2e25d7ad Mon Sep 17 00:00:00 2001 From: "Rodrigo B. de Oliveira" Date: Sat, 23 Feb 2019 16:06:34 -0300 Subject: [PATCH 091/853] Compile `PrecompiledScriptPlugin` plugins blocks In preparation to compute the project schema implied by them so type-safe accessors can be generated. --- ...mpilePrecompiledScriptPluginPluginsTest.kt | 104 ++++++++++++++++++ .../precompiled/PrecompiledScriptPlugins.kt | 2 +- .../ClassPathSensitiveCodeGenerationTask.kt | 2 +- .../CompilePrecompiledScriptPluginPlugins.kt | 30 ++++- .../GenerateInternalPluginSpecBuilders.kt | 11 +- ...eneratePrecompiledScriptPluginAccessors.kt | 4 +- .../tasks/GenerateScriptPluginAdapters.kt | 2 +- .../dsl/execution/ResidualProgramCompiler.kt | 26 +++-- .../kotlin/dsl/support/KotlinCompiler.kt | 49 ++++++++- 9 files changed, 205 insertions(+), 25 deletions(-) create mode 100644 subprojects/kotlin-dsl-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/CompilePrecompiledScriptPluginPluginsTest.kt diff --git a/subprojects/kotlin-dsl-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/CompilePrecompiledScriptPluginPluginsTest.kt b/subprojects/kotlin-dsl-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/CompilePrecompiledScriptPluginPluginsTest.kt new file mode 100644 index 0000000000000..801f077176660 --- /dev/null +++ b/subprojects/kotlin-dsl-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/CompilePrecompiledScriptPluginPluginsTest.kt @@ -0,0 +1,104 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.kotlin.dsl.plugins.precompiled.tasks + +import com.nhaarman.mockito_kotlin.any +import com.nhaarman.mockito_kotlin.doReturn +import com.nhaarman.mockito_kotlin.inOrder +import com.nhaarman.mockito_kotlin.mock + +import org.gradle.kotlin.dsl.fixtures.classLoaderFor + +import org.gradle.kotlin.dsl.plugins.precompiled.AbstractPrecompiledScriptPluginTest + +import org.gradle.plugin.use.PluginDependenciesSpec +import org.gradle.plugin.use.PluginDependencySpec + +import org.junit.Test + +import java.net.URLClassLoader + + +class CompilePrecompiledScriptPluginPluginsTest : AbstractPrecompiledScriptPluginTest() { + + @Test + fun `can compile multiple source dirs`() { + + withFolders { + "build/plugins/src" { + "a" { + withFile("a.gradle.kts", """plugins { java }""") + } + "b" { + withFile("b.gradle.kts", """plugins { id("a") }""") + } + } + } + + withBuildScript(""" + + plugins { `kotlin-dsl` } + + fun Project.pluginsDir(path: String) = layout.buildDirectory.dir("plugins/" + path) + + tasks { + register<${CompilePrecompiledScriptPluginPlugins::class.qualifiedName}>("compilePlugins") { + sourceDir(pluginsDir("src/a")) + sourceDir(pluginsDir("src/b")) + outputDir.set(pluginsDir("output")) + classPathFiles = configurations.compileClasspath.get() + } + } + """) + + build("compilePlugins") + + classLoaderFor(existing("build/plugins/output")).use { classLoader -> + classLoader.expectPluginFromPluginsBlock( + "A_gradle", + "org.gradle.java" + ) + classLoader.expectPluginFromPluginsBlock( + "B_gradle", + "a" + ) + } + } + + private + fun URLClassLoader.expectPluginFromPluginsBlock(pluginsBlockClass: String, expectedPluginId: String) { + + val plugin = mock() + val plugins = mock { + on { id(any()) } doReturn plugin + } + + evalPluginsBlockOf(pluginsBlockClass, plugins) + + inOrder(plugins, plugin) { + verify(plugins).id(expectedPluginId) + verifyNoMoreInteractions() + } + } + + private + fun URLClassLoader.evalPluginsBlockOf(pluginsBlockClass: String, plugins: PluginDependenciesSpec) { + loadClass(pluginsBlockClass).getDeclaredConstructor(PluginDependenciesSpec::class.java).newInstance( + plugins + ) + } +} diff --git a/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPlugins.kt b/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPlugins.kt index 1ca5492024e40..66c1d805b14a5 100644 --- a/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPlugins.kt +++ b/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPlugins.kt @@ -251,7 +251,7 @@ fun resolverEnvironment(implicitImports: List) = + "=\"" + implicitImports.joinToString(separator = ":") + "\"") -private +internal fun Project.implicitImports(): List = serviceOf().list diff --git a/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/ClassPathSensitiveCodeGenerationTask.kt b/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/ClassPathSensitiveCodeGenerationTask.kt index d83df6bda7136..6e52681ffd851 100644 --- a/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/ClassPathSensitiveCodeGenerationTask.kt +++ b/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/ClassPathSensitiveCodeGenerationTask.kt @@ -22,7 +22,7 @@ import org.gradle.api.tasks.OutputDirectory abstract class ClassPathSensitiveCodeGenerationTask : ClassPathSensitiveTask() { @get:OutputDirectory - var sourceCodeOutputDir = project.objects.directoryProperty() + var sourceCodeOutputDir = directoryProperty() } diff --git a/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/CompilePrecompiledScriptPluginPlugins.kt b/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/CompilePrecompiledScriptPluginPlugins.kt index c05e11f53fd95..b319810b5f5af 100644 --- a/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/CompilePrecompiledScriptPluginPlugins.kt +++ b/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/CompilePrecompiledScriptPluginPlugins.kt @@ -19,21 +19,43 @@ package org.gradle.kotlin.dsl.plugins.precompiled.tasks import org.gradle.api.file.Directory import org.gradle.api.provider.Provider import org.gradle.api.tasks.CacheableTask +import org.gradle.api.tasks.InputFiles import org.gradle.api.tasks.OutputDirectory import org.gradle.api.tasks.TaskAction +import org.gradle.kotlin.dsl.execution.scriptDefinitionFromTemplate +import org.gradle.kotlin.dsl.plugins.precompiled.implicitImports + +import org.gradle.kotlin.dsl.support.KotlinPluginsBlock +import org.gradle.kotlin.dsl.support.compileKotlinScriptModuleTo + @CacheableTask open class CompilePrecompiledScriptPluginPlugins : ClassPathSensitiveTask() { @get:OutputDirectory - var outputDir = project.objects.directoryProperty() + var outputDir = directoryProperty() + + @get:InputFiles + val sourceFiles = sourceDirectorySet( + "precompiled-script-plugin-plugins", + "Precompiled script plugin plugins" + ) + + fun sourceDir(dir: Provider) = sourceFiles.srcDir(dir) @TaskAction fun compile() { - outputDir.withOutputDirectory { + outputDir.withOutputDirectory { outputDir -> + compileKotlinScriptModuleTo( + outputDir, + sourceFiles.name, + sourceFiles.map { it.path }, + scriptDefinitionFromTemplate(KotlinPluginsBlock::class, project.implicitImports()), + classPathFiles, + logger, + { it } + ) } } - - fun sourceDir(dir: Provider) = Unit } diff --git a/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/GenerateInternalPluginSpecBuilders.kt b/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/GenerateInternalPluginSpecBuilders.kt index 5b464200d20bb..d26db8a3f8ac5 100644 --- a/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/GenerateInternalPluginSpecBuilders.kt +++ b/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/GenerateInternalPluginSpecBuilders.kt @@ -17,6 +17,7 @@ package org.gradle.kotlin.dsl.plugins.precompiled.tasks import org.gradle.api.DefaultTask +import org.gradle.api.internal.AbstractTask import org.gradle.api.tasks.CacheableTask import org.gradle.api.tasks.InputFiles import org.gradle.api.tasks.Internal @@ -48,10 +49,18 @@ open class GenerateInternalPluginSpecBuilders : DefaultTask() { get() = scriptPluginFilesOf(plugins) @get:OutputDirectory - var sourceCodeOutputDir = project.objects.directoryProperty() + var sourceCodeOutputDir = directoryProperty() @TaskAction fun generate() { // TODO() } } + + +internal +fun AbstractTask.directoryProperty() = project.objects.directoryProperty() + + +internal +fun AbstractTask.sourceDirectorySet(name: String, displayName: String) = project.objects.sourceDirectorySet(name, displayName) diff --git a/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/GeneratePrecompiledScriptPluginAccessors.kt b/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/GeneratePrecompiledScriptPluginAccessors.kt index 526078baacf4c..90db5f0f3deb3 100644 --- a/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/GeneratePrecompiledScriptPluginAccessors.kt +++ b/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/GeneratePrecompiledScriptPluginAccessors.kt @@ -45,11 +45,11 @@ import java.io.File open class GeneratePrecompiledScriptPluginAccessors : ClassPathSensitiveCodeGenerationTask() { @get:OutputDirectory - var metadataOutputDir = project.objects.directoryProperty() + var metadataOutputDir = directoryProperty() @get:InputDirectory @get:PathSensitive(PathSensitivity.RELATIVE) - var compiledPluginsBlocksDir = project.objects.directoryProperty() + var compiledPluginsBlocksDir = directoryProperty() @get:Internal internal diff --git a/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/GenerateScriptPluginAdapters.kt b/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/GenerateScriptPluginAdapters.kt index 736a7b85e3f82..76506410c7946 100644 --- a/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/GenerateScriptPluginAdapters.kt +++ b/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/GenerateScriptPluginAdapters.kt @@ -36,7 +36,7 @@ import java.io.File open class GenerateScriptPluginAdapters : DefaultTask() { @get:OutputDirectory - var outputDirectory = project.objects.directoryProperty() + var outputDirectory = directoryProperty() @get:Internal internal diff --git a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/execution/ResidualProgramCompiler.kt b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/execution/ResidualProgramCompiler.kt index 07f670bd56f11..b3b0b00ed75a6 100644 --- a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/execution/ResidualProgramCompiler.kt +++ b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/execution/ResidualProgramCompiler.kt @@ -659,21 +659,27 @@ class ResidualProgramCompiler( val buildscriptWithPluginsScriptDefinition get() = scriptDefinitionFromTemplate(KotlinBuildscriptAndPluginsBlock::class) + private fun scriptDefinitionFromTemplate(template: KClass) = + scriptDefinitionFromTemplate(template, implicitImports) +} - object : KotlinScriptDefinition(template), DependenciesResolver { - override val dependencyResolver = this +fun scriptDefinitionFromTemplate( + template: KClass, + implicitImports: List +): KotlinScriptDefinition = object : KotlinScriptDefinition(template), DependenciesResolver { - override fun resolve( - scriptContents: ScriptContents, - environment: Environment - ): DependenciesResolver.ResolveResult = DependenciesResolver.ResolveResult.Success( - ScriptDependencies(imports = implicitImports), - emptyList() - ) - } + override val dependencyResolver = this + + override fun resolve( + scriptContents: ScriptContents, + environment: Environment + ): DependenciesResolver.ResolveResult = DependenciesResolver.ResolveResult.Success( + ScriptDependencies(imports = implicitImports), + emptyList() + ) } diff --git a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/KotlinCompiler.kt b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/KotlinCompiler.kt index 4631a1985d83a..c748777c5ab8c 100644 --- a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/KotlinCompiler.kt +++ b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/KotlinCompiler.kt @@ -72,6 +72,24 @@ import java.io.OutputStream import java.io.PrintStream +fun compileKotlinScriptModuleTo( + outputDirectory: File, + moduleName: String, + scriptFiles: Collection, + scriptDef: KotlinScriptDefinition, + classPath: Iterable, + logger: Logger, + pathTranslation: (String) -> String +) = compileKotlinScriptModuleTo( + outputDirectory, + moduleName, + scriptFiles, + scriptDef, + classPath, + LoggingMessageCollector(logger, pathTranslation) +) + + internal fun compileKotlinScriptToDirectory( outputDirectory: File, @@ -79,19 +97,41 @@ fun compileKotlinScriptToDirectory( scriptDef: KotlinScriptDefinition, classPath: List, messageCollector: LoggingMessageCollector -): String = +): String { + + compileKotlinScriptModuleTo( + outputDirectory, + "buildscript", + listOf(scriptFile.path), + scriptDef, + classPath, + messageCollector + ) + + return NameUtils.getScriptNameForFile(scriptFile.name).asString() +} + +private +fun compileKotlinScriptModuleTo( + outputDirectory: File, + moduleName: String, + scriptFiles: Collection, + scriptDef: KotlinScriptDefinition, + classPath: Iterable, + messageCollector: LoggingMessageCollector +) { withRootDisposable { withCompilationExceptionHandler(messageCollector) { val configuration = compilerConfigurationFor(messageCollector).apply { - addKotlinSourceRoot(scriptFile.canonicalPath) put(JVM_TARGET, JVM_1_8) put(RETAIN_OUTPUT_IN_MEMORY, false) put(OUTPUT_DIRECTORY, outputDirectory) - setModuleName("buildscript") + setModuleName(moduleName) addScriptDefinition(scriptDef) + scriptFiles.forEach { addKotlinSourceRoot(it) } classPath.forEach { addJvmClasspathRoot(it) } } val environment = kotlinCoreEnvironmentFor(configuration).apply { @@ -100,10 +140,9 @@ fun compileKotlinScriptToDirectory( compileBunchOfSources(environment) || throw ScriptCompilationException(messageCollector.errors) - - NameUtils.getScriptNameForFile(scriptFile.name).asString() } } +} private From 38e221c36955952a1272361a905805fe9def431c Mon Sep 17 00:00:00 2001 From: "Rodrigo B. de Oliveira" Date: Sat, 23 Feb 2019 18:07:19 -0300 Subject: [PATCH 092/853] Add missing `@PathSensitive(PathSensitivity.RELATIVE)` annotation --- .../tasks/CompilePrecompiledScriptPluginPlugins.kt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/CompilePrecompiledScriptPluginPlugins.kt b/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/CompilePrecompiledScriptPluginPlugins.kt index b319810b5f5af..2774f74fe2323 100644 --- a/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/CompilePrecompiledScriptPluginPlugins.kt +++ b/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/CompilePrecompiledScriptPluginPlugins.kt @@ -21,6 +21,8 @@ import org.gradle.api.provider.Provider import org.gradle.api.tasks.CacheableTask import org.gradle.api.tasks.InputFiles import org.gradle.api.tasks.OutputDirectory +import org.gradle.api.tasks.PathSensitive +import org.gradle.api.tasks.PathSensitivity import org.gradle.api.tasks.TaskAction import org.gradle.kotlin.dsl.execution.scriptDefinitionFromTemplate @@ -36,6 +38,7 @@ open class CompilePrecompiledScriptPluginPlugins : ClassPathSensitiveTask() { @get:OutputDirectory var outputDir = directoryProperty() + @get:PathSensitive(PathSensitivity.RELATIVE) @get:InputFiles val sourceFiles = sourceDirectorySet( "precompiled-script-plugin-plugins", @@ -54,7 +57,7 @@ open class CompilePrecompiledScriptPluginPlugins : ClassPathSensitiveTask() { scriptDefinitionFromTemplate(KotlinPluginsBlock::class, project.implicitImports()), classPathFiles, logger, - { it } + { it } // TODO: translate paths ) } } From 257a189ae6bd71617f3a1660414f83fb18d9a23b Mon Sep 17 00:00:00 2001 From: Sterling Greene Date: Sat, 23 Feb 2019 16:19:44 -0500 Subject: [PATCH 093/853] Add integration test that fails if Gradle does not understand the JVM's GC settings --- .../DaemonExpirationIntegrationTest.groovy | 33 +++++++++++++ .../daemon/server/DaemonServices.java | 11 +++-- .../server/health/DaemonHealthStats.java | 8 +--- .../health/gc/GarbageCollectionMonitor.java | 37 --------------- .../GarbageCollectorMonitoringStrategy.java | 47 +++++++++++++++++++ 5 files changed, 89 insertions(+), 47 deletions(-) create mode 100644 subprojects/launcher/src/integTest/groovy/org/gradle/launcher/daemon/DaemonExpirationIntegrationTest.groovy diff --git a/subprojects/launcher/src/integTest/groovy/org/gradle/launcher/daemon/DaemonExpirationIntegrationTest.groovy b/subprojects/launcher/src/integTest/groovy/org/gradle/launcher/daemon/DaemonExpirationIntegrationTest.groovy new file mode 100644 index 0000000000000..ee549c9f6460c --- /dev/null +++ b/subprojects/launcher/src/integTest/groovy/org/gradle/launcher/daemon/DaemonExpirationIntegrationTest.groovy @@ -0,0 +1,33 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.launcher.daemon + +import org.gradle.integtests.fixtures.daemon.DaemonIntegrationSpec +import org.gradle.launcher.daemon.server.health.gc.GarbageCollectorMonitoringStrategy + +class DaemonExpirationIntegrationTest extends DaemonIntegrationSpec { + def "daemon understands the GC used"() { + buildFile << """ + import ${GarbageCollectorMonitoringStrategy.canonicalName} + + def strategy = services.get(GarbageCollectorMonitoringStrategy) + assert strategy != GarbageCollectorMonitoringStrategy.UNKNOWN + """ + expect: + run "help" + } +} diff --git a/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/server/DaemonServices.java b/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/server/DaemonServices.java index ffdf85dffbf45..1829ed70e7243 100644 --- a/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/server/DaemonServices.java +++ b/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/server/DaemonServices.java @@ -105,8 +105,7 @@ public File getDaemonLogFile() { return new File(get(DaemonDir.class).getVersionedDir(), fileName); } - protected DaemonMemoryStatus createDaemonMemoryStatus(DaemonHealthStats healthStats) { - GarbageCollectorMonitoringStrategy strategy = healthStats.getGcStrategy(); + protected DaemonMemoryStatus createDaemonMemoryStatus(DaemonHealthStats healthStats, GarbageCollectorMonitoringStrategy strategy) { return new DaemonMemoryStatus(healthStats, strategy.getHeapUsageThreshold(), strategy.getGcRateThreshold(), strategy.getNonHeapUsageThreshold(), strategy.getThrashingThreshold()); } @@ -130,8 +129,12 @@ protected HealthExpirationStrategy createHealthExpirationStrategy(DaemonMemorySt return new HealthExpirationStrategy(memoryStatus); } - protected DaemonHealthStats createDaemonHealthStats(DaemonRunningStats runningStats, ExecutorFactory executorFactory) { - return new DaemonHealthStats(runningStats, executorFactory); + protected DaemonHealthStats createDaemonHealthStats(DaemonRunningStats runningStats, GarbageCollectorMonitoringStrategy strategy, ExecutorFactory executorFactory) { + return new DaemonHealthStats(runningStats, strategy, executorFactory); + } + + protected GarbageCollectorMonitoringStrategy createGarbageCollectorMonitoringStrategy() { + return GarbageCollectorMonitoringStrategy.determineGcStrategy(); } protected ImmutableList createDaemonCommandActions(DaemonContext daemonContext, ProcessEnvironment processEnvironment, DaemonHealthStats healthStats, DaemonHealthCheck healthCheck, BuildExecuter buildActionExecuter, DaemonRunningStats runningStats) { diff --git a/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/server/health/DaemonHealthStats.java b/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/server/health/DaemonHealthStats.java index b61b4385570fb..05c5faa31413e 100644 --- a/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/server/health/DaemonHealthStats.java +++ b/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/server/health/DaemonHealthStats.java @@ -36,11 +36,11 @@ public class DaemonHealthStats implements Stoppable { private final GarbageCollectionInfo gcInfo; private final GarbageCollectionMonitor gcMonitor; - public DaemonHealthStats(DaemonRunningStats runningStats, ExecutorFactory executorFactory) { + public DaemonHealthStats(DaemonRunningStats runningStats, GarbageCollectorMonitoringStrategy strategy, ExecutorFactory executorFactory) { this.runningStats = runningStats; this.scheduler = executorFactory.createScheduled("Daemon health stats", 1); this.gcInfo = new GarbageCollectionInfo(); - this.gcMonitor = new GarbageCollectionMonitor(scheduler); + this.gcMonitor = new GarbageCollectionMonitor(strategy, scheduler); } @VisibleForTesting @@ -58,10 +58,6 @@ public void stop() { } } - public GarbageCollectorMonitoringStrategy getGcStrategy() { - return gcMonitor.getGcStrategy(); - } - public GarbageCollectionStats getHeapStats() { return gcMonitor.getHeapStats(); } diff --git a/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/server/health/gc/GarbageCollectionMonitor.java b/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/server/health/gc/GarbageCollectionMonitor.java index 3bf5d5df24fdd..94c81df152dfa 100644 --- a/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/server/health/gc/GarbageCollectionMonitor.java +++ b/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/server/health/gc/GarbageCollectionMonitor.java @@ -16,17 +16,12 @@ package org.gradle.launcher.daemon.server.health.gc; -import org.gradle.api.Transformer; -import org.gradle.api.logging.Logger; -import org.gradle.api.logging.Logging; import org.gradle.api.specs.Spec; -import org.gradle.internal.jvm.Jvm; import org.gradle.internal.time.Time; import org.gradle.util.CollectionUtils; import java.lang.management.GarbageCollectorMXBean; import java.lang.management.ManagementFactory; -import java.util.List; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; @@ -34,17 +29,12 @@ public class GarbageCollectionMonitor { private static final int POLL_INTERVAL_SECONDS = 1; private static final int POLL_DELAY_SECONDS = 1; private static final int EVENT_WINDOW = 20; - private static final Logger LOGGER = Logging.getLogger(GarbageCollectionMonitor.class); private final SlidingWindow heapEvents; private final SlidingWindow nonHeapEvents; private final GarbageCollectorMonitoringStrategy gcStrategy; private final ScheduledExecutorService pollingExecutor; - public GarbageCollectionMonitor(ScheduledExecutorService pollingExecutor) { - this(determineGcStrategy(), pollingExecutor); - } - public GarbageCollectionMonitor(GarbageCollectorMonitoringStrategy gcStrategy, ScheduledExecutorService pollingExecutor) { this.pollingExecutor = pollingExecutor; this.gcStrategy = gcStrategy; @@ -55,29 +45,6 @@ public GarbageCollectionMonitor(GarbageCollectorMonitoringStrategy gcStrategy, S } } - private static GarbageCollectorMonitoringStrategy determineGcStrategy() { - - final List garbageCollectors = CollectionUtils.collect(ManagementFactory.getGarbageCollectorMXBeans(), new Transformer() { - @Override - public String transform(GarbageCollectorMXBean garbageCollectorMXBean) { - return garbageCollectorMXBean.getName(); - } - }); - GarbageCollectorMonitoringStrategy gcStrategy = CollectionUtils.findFirst(GarbageCollectorMonitoringStrategy.values(), new Spec() { - @Override - public boolean isSatisfiedBy(GarbageCollectorMonitoringStrategy strategy) { - return garbageCollectors.contains(strategy.getGarbageCollectorName()); - } - }); - - if (gcStrategy == null) { - LOGGER.info("Unable to determine a garbage collection monitoring strategy for " + Jvm.current().toString()); - return GarbageCollectorMonitoringStrategy.UNKNOWN; - } else { - return gcStrategy; - } - } - private void pollForValues() { GarbageCollectorMXBean garbageCollectorMXBean = CollectionUtils.findFirst(ManagementFactory.getGarbageCollectorMXBeans(), new Spec() { @Override @@ -95,8 +62,4 @@ public GarbageCollectionStats getHeapStats() { public GarbageCollectionStats getNonHeapStats() { return GarbageCollectionStats.forNonHeap(nonHeapEvents.snapshot()); } - - public GarbageCollectorMonitoringStrategy getGcStrategy() { - return gcStrategy; - } } diff --git a/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/server/health/gc/GarbageCollectorMonitoringStrategy.java b/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/server/health/gc/GarbageCollectorMonitoringStrategy.java index 943fff01f7993..ebce9c8318773 100644 --- a/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/server/health/gc/GarbageCollectorMonitoringStrategy.java +++ b/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/server/health/gc/GarbageCollectorMonitoringStrategy.java @@ -16,7 +16,20 @@ package org.gradle.launcher.daemon.server.health.gc; +import org.gradle.api.Transformer; +import org.gradle.api.logging.Logger; +import org.gradle.api.logging.Logging; +import org.gradle.api.specs.Spec; +import org.gradle.internal.jvm.Jvm; +import org.gradle.util.CollectionUtils; + +import java.lang.management.GarbageCollectorMXBean; +import java.lang.management.ManagementFactory; +import java.lang.management.MemoryPoolMXBean; +import java.util.List; + public enum GarbageCollectorMonitoringStrategy { + ORACLE_PARALLEL_CMS("PS Old Gen", "Metaspace", "PS MarkSweep", 1.2, 80, 80, 5.0), ORACLE_6_CMS("CMS Old Gen", "Metaspace", "ConcurrentMarkSweep", 1.2, 80, 80, 5.0), ORACLE_SERIAL("Tenured Gen", "Metaspace", "MarkSweepCompact", 1.2, 80, 80, 5.0), @@ -24,6 +37,8 @@ public enum GarbageCollectorMonitoringStrategy { IBM_ALL("Java heap", "Not Used", "MarkSweepCompact", 0.8, 70, -1, 6.0), UNKNOWN(null, null, null, -1, -1, -1, -1); + private static final Logger LOGGER = Logging.getLogger(GarbageCollectionMonitor.class); + private final String heapPoolName; private final String nonHeapPoolName; private final String garbageCollectorName; @@ -69,4 +84,36 @@ public int getNonHeapUsageThreshold() { public double getThrashingThreshold() { return thrashingThreshold; } + + public static GarbageCollectorMonitoringStrategy determineGcStrategy() { + final List garbageCollectors = CollectionUtils.collect(ManagementFactory.getGarbageCollectorMXBeans(), new Transformer() { + @Override + public String transform(GarbageCollectorMXBean garbageCollectorMXBean) { + return garbageCollectorMXBean.getName(); + } + }); + GarbageCollectorMonitoringStrategy gcStrategy = CollectionUtils.findFirst(GarbageCollectorMonitoringStrategy.values(), new Spec() { + @Override + public boolean isSatisfiedBy(GarbageCollectorMonitoringStrategy strategy) { + return garbageCollectors.contains(strategy.getGarbageCollectorName()); + } + }); + + if (gcStrategy == null) { + LOGGER.info("Unable to determine a garbage collection monitoring strategy for " + Jvm.current().toString()); + return GarbageCollectorMonitoringStrategy.UNKNOWN; + } else { + List memoryPools = CollectionUtils.collect(ManagementFactory.getMemoryPoolMXBeans(), new Transformer() { + @Override + public String transform(MemoryPoolMXBean memoryPoolMXBean) { + return memoryPoolMXBean.getName(); + } + }); + if (!memoryPools.contains(gcStrategy.heapPoolName) || !memoryPools.contains(gcStrategy.nonHeapPoolName)) { + LOGGER.info("Unable to determine which memory pools to monitor for " + Jvm.current().toString()); + return GarbageCollectorMonitoringStrategy.UNKNOWN; + } + return gcStrategy; + } + } } From a11ba879b1d7470bc03bc2ea73044210ff30b01e Mon Sep 17 00:00:00 2001 From: Gradleware Git Bot Date: Sun, 24 Feb 2019 02:30:43 +0100 Subject: [PATCH 094/853] Publish 5.3-20190224011633+0000 --- released-versions.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/released-versions.json b/released-versions.json index bd1401fef901e..3b3a57b2b599f 100644 --- a/released-versions.json +++ b/released-versions.json @@ -1,7 +1,7 @@ { "latestReleaseSnapshot": { - "version": "5.3-20190223013127+0000", - "buildTime": "20190223013127+0000" + "version": "5.3-20190224011633+0000", + "buildTime": "20190224011633+0000" }, "latestRc": { "version": "5.2-rc-1", From 1a717f44df5ff9d6d793cb9969fb15dd10661369 Mon Sep 17 00:00:00 2001 From: Sterling Greene Date: Sun, 24 Feb 2019 01:32:25 -0500 Subject: [PATCH 095/853] Update to latest nightly --- gradle/wrapper/gradle-wrapper.jar | Bin 55504 -> 55616 bytes gradle/wrapper/gradle-wrapper.properties | 2 +- gradlew | 18 +++++++++++++++++- gradlew.bat | 18 +++++++++++++++++- 4 files changed, 35 insertions(+), 3 deletions(-) diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 607a6cf23437cac28351f36a4a91f14a5d17cdbd..5c2d1cf016b3885f6930543d57b744ea8c220a1a 100644 GIT binary patch delta 3020 zcmYk8c{G%51Bdfui7XQ{2BB<~CHuY>S!0N@XU}BM2;-#&y&=Ph$6DD6!(^9G5)CF9 zV=!6DzGlsq#@ndR=e*~9-~HEhUB7egbMEJ_hgx^Mz5aOZ0||~iZ*>hk`>|tO{9vkt z3I+`&!G5#lzrueOFXmgnt?zy5{I$QOS+Txi?B;jQUIN7L#4fxtV~cF^3Q5b*)I&&h zm3(Qa4eW&^E=gRJ+5ihC7;4OYAi)Fd@XK_ouM#yi6rFVj&QH&YcWA=|& zI0}lrR0=8#yBg*<1GUDhrnO{bBwK*~8=Dwimj0h}EcaV&cquQ@r`*;^R~hJv_~`32 zi*9Gv$5;isEmW&vhwKgV-JTlTE&p*@&+i~HV1CmX_H!8~#UGbAj;fmAWcNl*fa18pd8Ful`5LJNGm^SDa1H-s`=|>}s=U7jC?KZ#~l8 zAvy%7T@&kEU*Y8~C)l8IGV|f-y_0n3zWWw0A9ZGQSKpn@_586ynoYPqn6k2U@CF9% z$PFNQx^020;$>=7RgdL^&=<=or951M_I8OXdefAMl{(4PZ7I5}qDo9T4dY|_CYTFS zL-BUH)F&P?axu<7N5WS<2;0R~ZO`L$4!)k7o&ja*Qnq?~(PT1NY{Ej2;h0;4R22>I zSL0*X8&gP~Sl@({EBl|b<}(X+bZISKa{Z*v`!?+P_AzJD>r+NbiE9FLOJalRLxoLg zYeTliwRh74+`r(uo^~$}A~5iPGg<4Ze6JeBgSk1)ZY}*~EH*2La<|GJyg!^&76dY| zt#lqJ%DkzmFjc5pi=&M){q5kOD;Ux&?JDs2LtaYNiUlgm&8BnGMws%Y(r{n7?BUf> zMyPKo?PAU;b7Jt9rY3AaJZcdRiKa*e9RyNDxBuSe4ayl48nLTT$IQ{yRr1$Dn&e2o zEA(EA>b2ONL806_G??ulp2zt=BDkDuTs9HA9!-7)Qybqca6+}&o5fik=SfoEu~ZIT zIS|@=Zc5}!ANG(aow@LBgn9*UNYvQ6_|JQ~jdJ3-uuVaZdPLY*HlDpX=CM=J%vU-t z{<}Y2w9UG}4p_hsVw8ydjt3ZF9WH}*9yP`Z1N%)ruC!S^`T3R+tpd*~c!kS=*bieE z5*4;&xs-H`i4cUJW*lCI-k2~o-2{Z`l2`#6l%(wxy_czRPrsM3Qtgf?Ld4#MUvl>au|~_ z&Cg4Fuu@e+fBH#oTtISe#Um##broA?n35@9m{e#1na7a1Ci+4td0+0)obtBoiv=CT za36YHw?QFFxraEaH++Ww;puZjnKER#Z`%FCQOA=o8?F^klMYad$tMec`Lf zCT1OMqXW+dDQUrTXwA0XJ_;8iwYPn$wgU5_zCN36H`MbO-Cy_Gb9{Rt=()vf(#gR5 zD>o=co-AWj8&!DjhLp*q&R_(#QXuY*67#*CPovLrLn95FAeGX7#i0MvLss~Y z+(8dCW@^YEdkc)9C$zh4W73L=1l&>V*b?Xtzr$g;ssl&y0UT6iMYVR6y&P2H}1tCXzISZS|Lwy&U3=*>xZ zC3Jrz@jUFN0{Newpi&3_?g~UzxD|dty;l{pYW#G$?HE5!y3ot4D)(M>MJ|%)xZEb6 zxGK8u7W&;dW+k%-SHl~!_hZ;`KMC4%Qz{H@)r2-xhw|^7IGG!yZTv3D&P@lor1LV8 zs@(rE`o)}xU|Yerq8Zn(sdj#P2)4eDOOe0E5)vNxOb=Lp;~ZZXoiv!QBgvvvboVSU zR^zxVpT(Z;HDPsvt-6P1_}=ha;d}XYqVp9> z6LkYveb04Dc!d-=H;;`^Mi!2{!5eY$BMzOa)@6z4ckE{ZN7J5){mEh86iYf0Vdw!z z+SznPMNYcT#Y9fFChX`%?f7l(Jk`L2(N z`RFc>^o1qi8rbOa>o7kDQyYFKZD0z)z3|rL+JFXU=@@+X*0cd+H_P4Rmb+6C0pAa& z{-vDzcLi=`?wq|VEHNS~dCJ(} z=KV}pR-B43YrcN$rO;N{-Z=J( z;Kj&p`6JISHG*rMC!iRB;iy(pw%nAQ=?rJ~PKa@lbgl9Om&7`PK(!7}ust`fWw#B+65e?N4I%J?wNE zo4~sF;^68bva}zf{NXbppv#C5AWZ}#M|_zMz{wF`fZ7elbc_A>(?O(;{qK~-iIYG| P_j&NmD1;SB`tR@`JT0^n delta 2908 zcmYk8c{J2(AHehLBFoqs+gQ4mEMv)%Ok>Y3OW86^7|d9+L_!$Z8B6+wLRl_XWE(_e zYzbk=Iul9^hBt|%QK?>c&OPUSpT9nz&-a|~InVRg)7yOfHSu^;k_>0BRM4_E$FXD5 zf?&3cCLRsF0{fk-Jf@MAK)9AItq$iB(jBewwC3YeQ&KSHv8NI1fwJ1^{$_1;=EG^qtxu#F()x7Poz5JbO*KAt z2%)yGRtlUm5_#|a)l(JgrA2Z!uV!p;yxp3%HHj#%ylbY9FMA*` zB9YTH*<>I-+2N{>gP~jdW6+mmhyTX7)MGvuWclOJ^r504J>$GkV*-D601<=Pk}6I! ztdf$6EHLzXk#h(k(N_v2_3rWKv%c0KWs5Yc<5ENog!9@;mh0kt8nftqQ>Hm_97^K; z_sh9-B+*7}wuOttFvMcpdcZkM_Po^SJQv4*Px! z*&%m%yjI-nQ^)-(8=ozHr@27?@@e*`>N@4vSlj-&-bE>;*R;0iYeje!eXGViHRDe3 z`9-cw-xj`Mk>`f3Fd8wv9P(siP)g7oQ;SGa7rcqdit}!`cV#y^_Vzfr5g|7mTU!(_ z7g+V8P0^^=<}Yqy=9!g?8r^j(N(b=haSH`~@Wh9LZ2Y+XU)Eu1a zegS<@bB9Mof8@{F1J!Q4JnaWOKH*d?A|o7LkzOOxN5dXkyv*G_$)SWE`wx_KP5`rp zgrv8K_NP z#V|4)VutNc=i(ie2l5}^%@S)~b*i$r#3Wi`n=5OlE*L2bFXJ5c3<9z_(mC52MGuuP z&ITEzOA2R*(0&r9)#scU5obKa9v4rr*n3qP-RzVMZ!wIpYp+6Ow&_6J&(*#xCg+(r z=Ay!D3iP2GhH*29-YAdpfuuHHx3dQIJ2j(}S_?U)QGVNjtsZ zG@Y0nx98W4QV2R>b0a#OgYb4BUFSl7fDoitcsQ+$cWx}seu{0KVfd?NZD#*#A}!e6 zJfxv7+T0AIw)n}B@EHq6GU|GRe};X(6Lyunnc8*?)m~q=X&mfNgZKOQH3SAr%oKzZ zK0K9K!n5wH-uYH-%dV*)-Ei5-n%wb8J0$~K-HK}#e|WzTw{G3J`DL6mIpVW9H4tZ^ zwNFf!%fV~f{qF{Ucv`QAf7x}NzxNAh)#eEGfvd0HeLHYa3>Y ze)O@f`|`AiFvV~|M>>{Ne)(;;*9Tt#*JK{oyW~&eb~ZQ6U-eGq25>J13xDG6*a{;o z3KWteRo-OyWD7}hv3|@A*mJqBFO6oY`6#LVy`)|%JiV^;l>8aGqwdd`8_$KF(sg|j zQ}JQQz8|&np{?5|f>RF+*m{o}Aj1-Jf9fFI5;Vq>P~rJ|NvJ)}@#oF!`8%JB8D2SQ zmj3S>2bNa8Lxs?7s2D^6bzpX5?J<&j!`J|SG3<}yt1GxoeYlg^{JtfWRol8h{El%L z1!~3Sa7Rop-cH~hOHcIy+=`tLizOvV;!Ed?2l{14e1`=S(Tc;z9b5(;b`N^tiBz{W z#*94i8PP}JA`IJO9q}Z%kz05BDTfX6&&V1cD;e9=g^7S!rv}eTrCU6 zlz1U*7p}{i9FU9Skt0%GD(~?jDiY^YdOb;vswv+sgUWcPDSYios$F~Q zf|<&VGS5pKRF9i)%oJDR@`awsJaoopEt%1ms=8K@ck;)&Om0ODe0epZ>W7=7sibbpxoP0b2xJ@cBU zdvPj~dw#j9DaHdOpdxHaq;e?8*ITx7yp$t)L{%#&B@QWUAe_}6;JO^IRTs!KotWax zTy9ZQ!Ci5+{sx`Ta5uWF7_qAJ(?s2e})Q!K}X6H#?&o8-lHiW zIQ<$11Yc(+uE}#iYt#|SfVfF@pfs9^wlOe}KFkNMPr_KtK$a;_;Cupeu#q6f91y2q zz`bN<+L^LrF$E2$1AxjLW|){Z1^&tdjfxaOgBe5M@jdYNj5qMCkXd+Vb%3W2j!=ua zCvO%85KE5q47fOp1j Date: Sat, 23 Feb 2019 17:20:04 +0100 Subject: [PATCH 096/853] Refine ScriptCachingIntegrationTest by spliting the MEMORY_HOG in 1024 arrays in order to allow allocation in fragmented heap Signed-off-by: Paul Merlin --- .../kotlin/dsl/caching/ScriptCachingIntegrationTest.kt | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/subprojects/kotlin-dsl/src/integTest/kotlin/org/gradle/kotlin/dsl/caching/ScriptCachingIntegrationTest.kt b/subprojects/kotlin-dsl/src/integTest/kotlin/org/gradle/kotlin/dsl/caching/ScriptCachingIntegrationTest.kt index 2a3d9e083892c..8e20c59bf7d05 100644 --- a/subprojects/kotlin-dsl/src/integTest/kotlin/org/gradle/kotlin/dsl/caching/ScriptCachingIntegrationTest.kt +++ b/subprojects/kotlin-dsl/src/integTest/kotlin/org/gradle/kotlin/dsl/caching/ScriptCachingIntegrationTest.kt @@ -25,10 +25,8 @@ import org.gradle.kotlin.dsl.execution.ProgramSource import org.gradle.kotlin.dsl.execution.ProgramTarget import org.gradle.kotlin.dsl.fixtures.DeepThought -import org.junit.Ignore import org.junit.Test -import spock.lang.Issue import java.io.File import java.util.UUID @@ -217,8 +215,6 @@ class ScriptCachingIntegrationTest : AbstractScriptCachingIntegrationTest() { } @Test - @Ignore - @Issue("https://github.com/gradle/gradle-private/issues/1801") fun `in-memory script class loading cache releases memory of unused entries`() { // given: buildSrc memory hog @@ -227,14 +223,14 @@ class ScriptCachingIntegrationTest : AbstractScriptCachingIntegrationTest() { import org.gradle.api.tasks.* class MyTask extends DefaultTask { - static final byte[] MEMORY_HOG = new byte[64 * 1024 * 1024] + static final byte[][] MEMORY_HOG = new byte[1024][1024 * 64] @TaskAction void runAction0() {} } """) val settingsFile = cachedSettingsFile(withSettings(""), false, false) val buildFile = cachedBuildFile(withBuildScript("""task("myTask")"""), true) - // expect: + // expect: memory hog released for (run in 1..4) { myTask.writeText(myTask.readText().replace("runAction${run - 1}", "runAction$run")) buildWithDaemonHeapSize(256, "myTask").apply { From 604cf381dbd2f18bbefa20299462ac41f3a7da13 Mon Sep 17 00:00:00 2001 From: Stefan Wolf Date: Thu, 21 Feb 2019 16:50:49 +0100 Subject: [PATCH 097/853] Enable incremental transform workspaces by default --- ...ildArtifactTransformIntegrationTest.groovy | 8 +--- .../gradle/api/internal/FeaturePreviews.java | 2 +- ...ctTransformBuildScanIntegrationTest.groovy | 6 --- ...factTransformCachingIntegrationTest.groovy | 23 ++--------- .../ArtifactTransformIntegrationTest.groovy | 5 --- ...actTransformParallelIntegrationTest.groovy | 7 ---- ...ldsArtifactTransformIntegrationTest.groovy | 7 ---- ...ldsArtifactTransformIntegrationTest.groovy | 6 --- ...ransformationLoggingIntegrationTest.groovy | 3 -- .../DefaultDependencyManagementServices.java | 7 ++-- .../transform/DefaultTransformerInvoker.java | 9 ++-- .../DefaultTransformerInvokerTest.groovy | 3 +- ...mentalArtifactTransformationsRunner.groovy | 41 ------------------- .../fixtures/FeaturePreviewsFixture.groovy | 8 +--- ...ractConsoleBuildPhaseFunctionalTest.groovy | 3 -- 15 files changed, 13 insertions(+), 125 deletions(-) delete mode 100644 subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/ExperimentalIncrementalArtifactTransformationsRunner.groovy diff --git a/subprojects/composite-builds/src/integTest/groovy/org/gradle/integtests/composite/CompositeBuildArtifactTransformIntegrationTest.groovy b/subprojects/composite-builds/src/integTest/groovy/org/gradle/integtests/composite/CompositeBuildArtifactTransformIntegrationTest.groovy index 037ef25214eeb..d092f49a8f389 100644 --- a/subprojects/composite-builds/src/integTest/groovy/org/gradle/integtests/composite/CompositeBuildArtifactTransformIntegrationTest.groovy +++ b/subprojects/composite-builds/src/integTest/groovy/org/gradle/integtests/composite/CompositeBuildArtifactTransformIntegrationTest.groovy @@ -16,13 +16,8 @@ package org.gradle.integtests.composite -import org.gradle.integtests.fixtures.ExperimentalIncrementalArtifactTransformationsRunner import org.gradle.test.fixtures.file.TestFile -import org.junit.runner.RunWith -import static org.gradle.integtests.fixtures.ExperimentalIncrementalArtifactTransformationsRunner.configureIncrementalArtifactTransformations - -@RunWith(ExperimentalIncrementalArtifactTransformationsRunner) class CompositeBuildArtifactTransformIntegrationTest extends AbstractCompositeBuildIntegrationTest { def "can apply a transform to the outputs of included builds"() { @@ -36,7 +31,6 @@ class CompositeBuildArtifactTransformIntegrationTest extends AbstractCompositeBu apply plugin: 'java' """ } - configureIncrementalArtifactTransformations(buildA.settingsFile) includedBuilds << buildB includedBuilds << buildC @@ -84,6 +78,6 @@ class CompositeBuildArtifactTransformIntegrationTest extends AbstractCompositeBu } private String expectedWorkspaceLocation(TestFile includedBuild) { - ExperimentalIncrementalArtifactTransformationsRunner.incrementalArtifactTransformations ? includedBuild.file("build/transforms") : executer.gradleUserHomeDir + includedBuild.file("build/transforms") } } diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/FeaturePreviews.java b/subprojects/core/src/main/java/org/gradle/api/internal/FeaturePreviews.java index ec33750d8b3ab..157a448bccd1d 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/FeaturePreviews.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/FeaturePreviews.java @@ -29,7 +29,7 @@ public enum Feature { IMPROVED_POM_SUPPORT(false), GRADLE_METADATA(true), STABLE_PUBLISHING(false), - INCREMENTAL_ARTIFACT_TRANSFORMATIONS(true); + INCREMENTAL_ARTIFACT_TRANSFORMATIONS(false); public static Feature withName(String name) { try { diff --git a/subprojects/dependency-management/src/integTest/groovy/org/gradle/api/artifacts/transform/ArtifactTransformBuildScanIntegrationTest.groovy b/subprojects/dependency-management/src/integTest/groovy/org/gradle/api/artifacts/transform/ArtifactTransformBuildScanIntegrationTest.groovy index 9ef45f587d4b0..c761e9501da5d 100644 --- a/subprojects/dependency-management/src/integTest/groovy/org/gradle/api/artifacts/transform/ArtifactTransformBuildScanIntegrationTest.groovy +++ b/subprojects/dependency-management/src/integTest/groovy/org/gradle/api/artifacts/transform/ArtifactTransformBuildScanIntegrationTest.groovy @@ -17,13 +17,8 @@ package org.gradle.api.artifacts.transform import org.gradle.integtests.fixtures.AbstractIntegrationSpec -import org.gradle.integtests.fixtures.ExperimentalIncrementalArtifactTransformationsRunner import org.gradle.internal.scan.config.fixtures.BuildScanPluginFixture -import org.junit.runner.RunWith -import static org.gradle.integtests.fixtures.ExperimentalIncrementalArtifactTransformationsRunner.configureIncrementalArtifactTransformations - -@RunWith(ExperimentalIncrementalArtifactTransformationsRunner) class ArtifactTransformBuildScanIntegrationTest extends AbstractIntegrationSpec { def fixture = new BuildScanPluginFixture(testDirectory, mavenRepo, createExecuter()) @@ -32,7 +27,6 @@ class ArtifactTransformBuildScanIntegrationTest extends AbstractIntegrationSpec include 'lib' include 'util' """ - configureIncrementalArtifactTransformations(settingsFile) fixture.logConfig = true fixture.publishDummyBuildScanPluginNow() } diff --git a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformCachingIntegrationTest.groovy b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformCachingIntegrationTest.groovy index 8c7ecaa3c742f..0e583a1310515 100644 --- a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformCachingIntegrationTest.groovy +++ b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformCachingIntegrationTest.groovy @@ -20,25 +20,18 @@ import org.gradle.api.internal.artifacts.ivyservice.CacheLayout import org.gradle.api.internal.artifacts.transform.DefaultTransformationWorkspace import org.gradle.cache.internal.LeastRecentlyUsedCacheCleanup import org.gradle.integtests.fixtures.AbstractHttpDependencyResolutionTest -import org.gradle.integtests.fixtures.ExperimentalIncrementalArtifactTransformationsRunner -import org.gradle.integtests.fixtures.RequiredFeature -import org.gradle.integtests.fixtures.RequiredFeatures import org.gradle.integtests.fixtures.cache.FileAccessTimeJournalFixture import org.gradle.test.fixtures.file.TestFile import org.gradle.test.fixtures.server.http.BlockingHttpServer import org.junit.Rule -import org.junit.runner.RunWith import spock.lang.Unroll import java.util.regex.Pattern import static java.util.concurrent.TimeUnit.MILLISECONDS import static java.util.concurrent.TimeUnit.SECONDS -import static org.gradle.integtests.fixtures.ExperimentalIncrementalArtifactTransformationsRunner.configureIncrementalArtifactTransformations -import static org.gradle.integtests.fixtures.ExperimentalIncrementalArtifactTransformationsRunner.incrementalArtifactTransformations import static org.gradle.test.fixtures.ConcurrentTestUtil.poll -@RunWith(ExperimentalIncrementalArtifactTransformationsRunner) class ArtifactTransformCachingIntegrationTest extends AbstractHttpDependencyResolutionTest implements FileAccessTimeJournalFixture { private final static long MAX_CACHE_AGE_IN_DAYS = LeastRecentlyUsedCacheCleanup.DEFAULT_MAX_AGE_IN_DAYS_FOR_RECREATABLE_CACHE_ENTRIES @@ -51,7 +44,6 @@ class ArtifactTransformCachingIntegrationTest extends AbstractHttpDependencyReso include 'util' include 'app' """ - configureIncrementalArtifactTransformations(settingsFile) buildFile << resolveTask } @@ -702,11 +694,7 @@ class ArtifactTransformCachingIntegrationTest extends AbstractHttpDependencyReso output.count("Transformed") == 2 isTransformed("dir1.classes", "dir1.classes.dir") isTransformed("lib1.jar", "lib1.jar.txt") - if (incrementalArtifactTransformations) { - outputDir("dir1.classes", "dir1.classes.dir") == outputDir1 - } else { - outputDir("dir1.classes", "dir1.classes.dir") != outputDir1 - } + outputDir("dir1.classes", "dir1.classes.dir") == outputDir1 gradleUserHomeOutputDir("lib1.jar", "lib1.jar.txt") != outputDir2 when: @@ -718,7 +706,6 @@ class ArtifactTransformCachingIntegrationTest extends AbstractHttpDependencyReso output.count("Transformed") == 0 } - @RequiredFeatures(@RequiredFeature(feature = ExperimentalIncrementalArtifactTransformationsRunner.INCREMENTAL_ARTIFACT_TRANSFORMATIONS, value = "true")) def "transform is executed in different workspace for different file produced in chain"() { given: buildFile << declareAttributes() << withJarTasks() << duplicatorTransform << """ @@ -1662,12 +1649,8 @@ ${getFileSizerBody(fileValue, 'outputs.dir(', 'outputs.file(')} } Set projectOutputDirs(String from, String to, Closure stream = { output }) { - if (incrementalArtifactTransformations) { - def parts = [Pattern.quote(temporaryFolder.getTestDirectory().absolutePath) + ".*", "build", "transforms", "\\w+"] - return outputDirs(from, to, parts.join(quotedFileSeparator), stream) - } else { - return gradleUserHomeOutputDirs(from, to, stream) - } + def parts = [Pattern.quote(temporaryFolder.getTestDirectory().absolutePath) + ".*", "build", "transforms", "\\w+"] + return outputDirs(from, to, parts.join(quotedFileSeparator), stream) } Set gradleUserHomeOutputDirs(String from, String to, Closure stream = { output }) { diff --git a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformIntegrationTest.groovy b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformIntegrationTest.groovy index e6ea0964af016..49556d1a83be8 100644 --- a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformIntegrationTest.groovy +++ b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformIntegrationTest.groovy @@ -19,17 +19,13 @@ package org.gradle.integtests.resolve.transform import org.gradle.api.internal.artifacts.transform.ExecuteScheduledTransformationStepBuildOperationType import org.gradle.integtests.fixtures.AbstractHttpDependencyResolutionTest import org.gradle.integtests.fixtures.BuildOperationsFixture -import org.gradle.integtests.fixtures.ExperimentalIncrementalArtifactTransformationsRunner import org.gradle.internal.file.FileType import org.hamcrest.Matcher -import org.junit.runner.RunWith import spock.lang.Issue import spock.lang.Unroll -import static org.gradle.integtests.fixtures.ExperimentalIncrementalArtifactTransformationsRunner.configureIncrementalArtifactTransformations import static org.gradle.util.Matchers.matchesRegexp -@RunWith(ExperimentalIncrementalArtifactTransformationsRunner) class ArtifactTransformIntegrationTest extends AbstractHttpDependencyResolutionTest { def setup() { settingsFile << """ @@ -37,7 +33,6 @@ class ArtifactTransformIntegrationTest extends AbstractHttpDependencyResolutionT include 'lib' include 'app' """ - configureIncrementalArtifactTransformations(settingsFile) buildFile << """ def usage = Attribute.of('usage', String) diff --git a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformParallelIntegrationTest.groovy b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformParallelIntegrationTest.groovy index 3ef961617d316..98c5a720ac991 100644 --- a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformParallelIntegrationTest.groovy +++ b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformParallelIntegrationTest.groovy @@ -17,15 +17,10 @@ package org.gradle.integtests.resolve.transform import org.gradle.integtests.fixtures.AbstractDependencyResolutionTest -import org.gradle.integtests.fixtures.ExperimentalIncrementalArtifactTransformationsRunner import org.gradle.integtests.fixtures.build.BuildTestFile import org.gradle.test.fixtures.server.http.BlockingHttpServer import org.junit.Rule -import org.junit.runner.RunWith -import static org.gradle.integtests.fixtures.ExperimentalIncrementalArtifactTransformationsRunner.configureIncrementalArtifactTransformations - -@RunWith(ExperimentalIncrementalArtifactTransformationsRunner) class ArtifactTransformParallelIntegrationTest extends AbstractDependencyResolutionTest { @Rule BlockingHttpServer server = new BlockingHttpServer() @@ -38,8 +33,6 @@ class ArtifactTransformParallelIntegrationTest extends AbstractDependencyResolut private void setupBuild(BuildTestFile buildTestFile) { buildTestFile.with { - configureIncrementalArtifactTransformations(buildTestFile.settingsFile) - settingsFile << """ rootProject.name = '${rootProjectName}' """ diff --git a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ConcurrentBuildsArtifactTransformIntegrationTest.groovy b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ConcurrentBuildsArtifactTransformIntegrationTest.groovy index fe6de50a6fbce..a60aa6b3fa528 100644 --- a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ConcurrentBuildsArtifactTransformIntegrationTest.groovy +++ b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ConcurrentBuildsArtifactTransformIntegrationTest.groovy @@ -17,21 +17,14 @@ package org.gradle.integtests.resolve.transform import org.gradle.integtests.fixtures.AbstractDependencyResolutionTest -import org.gradle.integtests.fixtures.ExperimentalIncrementalArtifactTransformationsRunner import org.gradle.test.fixtures.server.http.BlockingHttpServer import org.junit.Rule -import org.junit.runner.RunWith -import static org.gradle.integtests.fixtures.ExperimentalIncrementalArtifactTransformationsRunner.configureIncrementalArtifactTransformations - -@RunWith(ExperimentalIncrementalArtifactTransformationsRunner) class ConcurrentBuildsArtifactTransformIntegrationTest extends AbstractDependencyResolutionTest { @Rule BlockingHttpServer server = new BlockingHttpServer() def setup() { server.start() - configureIncrementalArtifactTransformations(settingsFile) - buildFile << """ enum Color { Red, Green, Blue } def type = Attribute.of("artifactType", String) diff --git a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/CrashingBuildsArtifactTransformIntegrationTest.groovy b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/CrashingBuildsArtifactTransformIntegrationTest.groovy index 2035482f5cd8e..b00a30e4bc7e7 100644 --- a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/CrashingBuildsArtifactTransformIntegrationTest.groovy +++ b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/CrashingBuildsArtifactTransformIntegrationTest.groovy @@ -17,16 +17,10 @@ package org.gradle.integtests.resolve.transform import org.gradle.integtests.fixtures.AbstractDependencyResolutionTest -import org.gradle.integtests.fixtures.ExperimentalIncrementalArtifactTransformationsRunner -import org.junit.runner.RunWith -import static org.gradle.integtests.fixtures.ExperimentalIncrementalArtifactTransformationsRunner.configureIncrementalArtifactTransformations - -@RunWith(ExperimentalIncrementalArtifactTransformationsRunner) class CrashingBuildsArtifactTransformIntegrationTest extends AbstractDependencyResolutionTest { def "cleans up cached output after build process crashes during transform"() { given: - configureIncrementalArtifactTransformations(settingsFile) buildFile << """ enum Color { Red, Green, Blue } diff --git a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/TransformationLoggingIntegrationTest.groovy b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/TransformationLoggingIntegrationTest.groovy index ee53c80837116..8eb5229b16afb 100644 --- a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/TransformationLoggingIntegrationTest.groovy +++ b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/TransformationLoggingIntegrationTest.groovy @@ -20,8 +20,6 @@ import org.gradle.api.logging.configuration.ConsoleOutput import org.gradle.integtests.fixtures.console.AbstractConsoleGroupedTaskFunctionalTest import spock.lang.Unroll -import static org.gradle.integtests.fixtures.FeaturePreviewsFixture.enableIncrementalArtifactTransformations - class TransformationLoggingIntegrationTest extends AbstractConsoleGroupedTaskFunctionalTest { ConsoleOutput consoleType @@ -34,7 +32,6 @@ class TransformationLoggingIntegrationTest extends AbstractConsoleGroupedTaskFun include 'util' include 'app' """ - enableIncrementalArtifactTransformations(settingsFile) buildFile << """ import java.nio.file.Files diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/DefaultDependencyManagementServices.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/DefaultDependencyManagementServices.java index 6d43eafc6760c..e5ce970e27f56 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/DefaultDependencyManagementServices.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/DefaultDependencyManagementServices.java @@ -261,8 +261,8 @@ TransformerInvoker createTransformerInvoker(WorkExecutor workExe FileCollectionFingerprinterRegistry fileCollectionFingerprinterRegistry, FileCollectionFactory fileCollectionFactory, ClassLoaderHierarchyHasher classLoaderHierarchyHasher, - ProjectFinder projectFinder, - FeaturePreviews featurePreviews) { + ProjectFinder projectFinder + ) { return new DefaultTransformerInvoker( workExecutor, fileSystemSnapshotter, @@ -271,8 +271,7 @@ TransformerInvoker createTransformerInvoker(WorkExecutor workExe fileCollectionFingerprinterRegistry, fileCollectionFactory, classLoaderHierarchyHasher, - projectFinder, - featurePreviews.isFeatureEnabled(FeaturePreviews.Feature.INCREMENTAL_ARTIFACT_TRANSFORMATIONS) + projectFinder ); } diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvoker.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvoker.java index 792dcaa61dbc6..79d5705b40b28 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvoker.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvoker.java @@ -86,7 +86,6 @@ public class DefaultTransformerInvoker implements TransformerInvoker { private final FileCollectionFingerprinter outputFingerprinter; private final ClassLoaderHierarchyHasher classLoaderHierarchyHasher; private final ProjectFinder projectFinder; - private final boolean useTransformationWorkspaces; public DefaultTransformerInvoker(WorkExecutor workExecutor, FileSystemSnapshotter fileSystemSnapshotter, @@ -95,8 +94,7 @@ public DefaultTransformerInvoker(WorkExecutor workExecutor, FileCollectionFingerprinterRegistry fileCollectionFingerprinterRegistry, FileCollectionFactory fileCollectionFactory, ClassLoaderHierarchyHasher classLoaderHierarchyHasher, - ProjectFinder projectFinder, - boolean useTransformationWorkspaces) { + ProjectFinder projectFinder) { this.workExecutor = workExecutor; this.fileSystemSnapshotter = fileSystemSnapshotter; this.artifactTransformListener = artifactTransformListener; @@ -105,8 +103,7 @@ public DefaultTransformerInvoker(WorkExecutor workExecutor, this.fileCollectionFactory = fileCollectionFactory; this.classLoaderHierarchyHasher = classLoaderHierarchyHasher; this.projectFinder = projectFinder; - this.useTransformationWorkspaces = useTransformationWorkspaces; - outputFingerprinter = fileCollectionFingerprinterRegistry.getFingerprinter(OutputNormalizer.class); + this.outputFingerprinter = fileCollectionFingerprinterRegistry.getFingerprinter(OutputNormalizer.class); } @Override @@ -174,7 +171,7 @@ private CachingTransformationWorkspaceProvider determineWorkspaceProvider(@Nulla @Nullable private ProjectInternal determineProducerProject(TransformationSubject subject) { - if (!useTransformationWorkspaces || !subject.getProducer().isPresent()) { + if (!subject.getProducer().isPresent()) { return null; } ProjectComponentIdentifier projectComponentIdentifier = subject.getProducer().get(); diff --git a/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvokerTest.groovy b/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvokerTest.groovy index 3aafa89d76bc4..55af5ec7f1928 100644 --- a/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvokerTest.groovy +++ b/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvokerTest.groovy @@ -94,8 +94,7 @@ class DefaultTransformerInvokerTest extends AbstractProjectBuilderSpec { registry, fileCollectionFactory, classloaderHasher, - projectFinder, - true + projectFinder ) private static class TestTransformer implements Transformer { diff --git a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/ExperimentalIncrementalArtifactTransformationsRunner.groovy b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/ExperimentalIncrementalArtifactTransformationsRunner.groovy deleted file mode 100644 index d3c350e8a0acd..0000000000000 --- a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/ExperimentalIncrementalArtifactTransformationsRunner.groovy +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright 2018 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.gradle.integtests.fixtures - -import groovy.transform.CompileStatic -import org.gradle.test.fixtures.file.TestFile - -@CompileStatic -class ExperimentalIncrementalArtifactTransformationsRunner extends BehindFlagFeatureRunner { - public final static String INCREMENTAL_ARTIFACT_TRANSFORMATIONS = "org.gradle.internal.artifacts.transforms.testWithTransformerWorkspaces" - - ExperimentalIncrementalArtifactTransformationsRunner(Class target) { - super(target, [ - (INCREMENTAL_ARTIFACT_TRANSFORMATIONS): booleanFeature("project workspaces for transformations") - ]) - } - - static boolean isIncrementalArtifactTransformations() { - Boolean.getBoolean(INCREMENTAL_ARTIFACT_TRANSFORMATIONS) - } - - static void configureIncrementalArtifactTransformations(TestFile settingsFile) { - if (incrementalArtifactTransformations) { - FeaturePreviewsFixture.enableIncrementalArtifactTransformations(settingsFile) - } - } -} diff --git a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/FeaturePreviewsFixture.groovy b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/FeaturePreviewsFixture.groovy index 3fff644e52cd7..2f466e824a01e 100644 --- a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/FeaturePreviewsFixture.groovy +++ b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/FeaturePreviewsFixture.groovy @@ -21,7 +21,7 @@ import org.gradle.api.internal.FeaturePreviews.Feature class FeaturePreviewsFixture { static def activeFeatures() { - EnumSet.of(Feature.GRADLE_METADATA, Feature.INCREMENTAL_ARTIFACT_TRANSFORMATIONS) + EnumSet.of(Feature.GRADLE_METADATA) } static def inactiveFeatures() { @@ -33,12 +33,6 @@ class FeaturePreviewsFixture { static void enableGradleMetadata(File settings) { settings << """ enableFeaturePreview("GRADLE_METADATA") -""" - } - - static void enableIncrementalArtifactTransformations(File settings) { - settings << """ -enableFeaturePreview("INCREMENTAL_ARTIFACT_TRANSFORMATIONS") """ } } diff --git a/subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/AbstractConsoleBuildPhaseFunctionalTest.groovy b/subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/AbstractConsoleBuildPhaseFunctionalTest.groovy index f2b2744569e53..a8b4ca49f59d9 100644 --- a/subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/AbstractConsoleBuildPhaseFunctionalTest.groovy +++ b/subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/AbstractConsoleBuildPhaseFunctionalTest.groovy @@ -26,8 +26,6 @@ import org.gradle.test.fixtures.server.http.BlockingHttpServer import org.junit.Rule import spock.lang.Unroll -import static org.gradle.integtests.fixtures.FeaturePreviewsFixture.enableIncrementalArtifactTransformations - abstract class AbstractConsoleBuildPhaseFunctionalTest extends AbstractIntegrationSpec implements RichConsoleStyling { @Rule BlockingHttpServer server = new BlockingHttpServer() @@ -324,7 +322,6 @@ abstract class AbstractConsoleBuildPhaseFunctionalTest extends AbstractIntegrati include 'lib' include 'util' """ - enableIncrementalArtifactTransformations(settingsFile) buildFile << """ def usage = Attribute.of('usage', String) def artifactType = Attribute.of('artifactType', String) From 0247ea56136bcc545b0507f2015087c60e4b3d55 Mon Sep 17 00:00:00 2001 From: Adam Murdoch Date: Fri, 22 Feb 2019 13:58:20 +1100 Subject: [PATCH 098/853] Update tests for changes to artifact transform workspace locations and add some coverage to demonstrate that the various path sensitivities work as expected when using the build cache, and to document the ways that they are broken for project artifacts when not caching. --- ...ansformInputArtifactIntegrationTest.groovy | 276 ++++++++++++++---- 1 file changed, 215 insertions(+), 61 deletions(-) diff --git a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformInputArtifactIntegrationTest.groovy b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformInputArtifactIntegrationTest.groovy index b708b0a831033..f4645e9dd3ba8 100644 --- a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformInputArtifactIntegrationTest.groovy +++ b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformInputArtifactIntegrationTest.groovy @@ -60,8 +60,10 @@ class ArtifactTransformInputArtifactIntegrationTest extends AbstractDependencyRe failure.assertHasCause("broken") } + // Documents existing behaviour. The absolute path of the input artifact is baked into the workspace identity + // and so when the path changes the outputs are invalidated @Unroll - def "can attach #description to input artifact property with project artifact file"() { + def "can attach #description to input artifact property with project artifact file but it has no effect when not caching"() { settingsFile << "include 'a', 'b', 'c'" setupBuildWithColorTransformAction() buildFile << """ @@ -157,19 +159,22 @@ class ArtifactTransformInputArtifactIntegrationTest extends AbstractDependencyRe when: succeeds(":a:resolve") - then: // have already seen these artifacts before + then: // have already seen these artifacts before, but the transform outputs have been been overwritten result.assertTasksNotSkipped(":b:producer", ":a:resolve") - transformed() + transformed("b.jar") outputContains("result = [b.jar.green, c.jar.green]") where: - description | annotation - "no sensitivity" | "" - "@PathSensitive(PathSensitivity.ABSOLUTE)" | "@PathSensitive(PathSensitivity.ABSOLUTE)" + description | annotation + "no sensitivity" | "" + "@PathSensitive(PathSensitivity.ABSOLUTE)" | "@PathSensitive(PathSensitivity.ABSOLUTE)" + "@PathSensitive(PathSensitivity.RELATIVE)" | "@PathSensitive(PathSensitivity.RELATIVE)" + "@PathSensitive(PathSensitivity.NAME_ONLY)" | "@PathSensitive(PathSensitivity.NAME_ONLY)" + "@PathSensitive(PathSensitivity.NONE)" | "@PathSensitive(PathSensitivity.NONE)" } @Unroll - def "can attach #description to input artifact property with project artifact directory"() { + def "can attach #description to input artifact property with project artifact directory but it has no effect when not caching"() { settingsFile << "include 'a', 'b', 'c'" setupBuildWithColorTransformAction { produceDirs() @@ -285,10 +290,20 @@ class ArtifactTransformInputArtifactIntegrationTest extends AbstractDependencyRe transformed() outputContains("result = [b-blue.green, c-dir.green]") + when: + succeeds(":a:resolve") + + then: // have already seen these artifacts before, but the transform outputs have been been overwritten + result.assertTasksNotSkipped(":b:producer", ":a:resolve") + transformed("b-dir") + outputContains("result = [b-dir.green, c-dir.green]") + where: - description | annotation - "no sensitivity" | "" - "@PathSensitive(PathSensitivity.ABSOLUTE)" | "@PathSensitive(PathSensitivity.ABSOLUTE)" + description | annotation + "no sensitivity" | "" + "@PathSensitive(PathSensitivity.ABSOLUTE)" | "@PathSensitive(PathSensitivity.ABSOLUTE)" + "@PathSensitive(PathSensitivity.RELATIVE)" | "@PathSensitive(PathSensitivity.RELATIVE)" + "@PathSensitive(PathSensitivity.NAME_ONLY)" | "@PathSensitive(PathSensitivity.NAME_ONLY)" } def "re-runs transform when input artifact file changes from file to missing"() { @@ -345,13 +360,13 @@ class ArtifactTransformInputArtifactIntegrationTest extends AbstractDependencyRe when: succeeds(":a:resolve") - then: // seen these before + then: // seen these before, but the transform outputs have been overwritten result.assertTasksNotSkipped(":b:producer", ":a:resolve") - transformed() + transformed("b.jar") outputContains("result = [b.jar.green, c.jar.green]") } - def "can attach @PathSensitive(NONE) to input artifact property for project artifact file"() { + def "honors @PathSensitive(NONE) on input artifact property for project artifact file when caching"() { settingsFile << "include 'a', 'b', 'c'" setupBuildWithColorTransformAction() buildFile << """ @@ -362,6 +377,7 @@ class ArtifactTransformInputArtifactIntegrationTest extends AbstractDependencyRe } } + @CacheableTransformAction abstract class MakeGreen implements TransformAction { @PathSensitive(PathSensitivity.NONE) @InputArtifact @@ -376,7 +392,7 @@ class ArtifactTransformInputArtifactIntegrationTest extends AbstractDependencyRe """ when: - succeeds(":a:resolve") + withBuildCache().succeeds(":a:resolve") then: result.assertTasksNotSkipped(":b:producer", ":c:producer", ":a:resolve") @@ -385,7 +401,7 @@ class ArtifactTransformInputArtifactIntegrationTest extends AbstractDependencyRe when: executer.withArguments("-PbOutputDir=out") - succeeds(":a:resolve") + withBuildCache().succeeds(":a:resolve") then: // path has changed, but should be up to date result.assertTasksNotSkipped(":b:producer", ":a:resolve") @@ -394,7 +410,7 @@ class ArtifactTransformInputArtifactIntegrationTest extends AbstractDependencyRe when: executer.withArguments("-PbOutputDir=out", "-PbFileName=b-blue.jar") - succeeds(":a:resolve") + withBuildCache().succeeds(":a:resolve") then: // name has changed, but should be up to date result.assertTasksNotSkipped(":b:producer", ":a:resolve") @@ -402,7 +418,7 @@ class ArtifactTransformInputArtifactIntegrationTest extends AbstractDependencyRe outputContains("result = [b.green, c.green]") when: - executer.withArguments("-PbOutputDir=out", "-PbFileName=b-blue.jar", "-PbContent=b-new") + withBuildCache().executer.withArguments("-PbOutputDir=out", "-PbFileName=b-blue.jar", "-PbContent=b-new") succeeds(":a:resolve") then: // new content, should run @@ -411,7 +427,7 @@ class ArtifactTransformInputArtifactIntegrationTest extends AbstractDependencyRe outputContains("result = [b-new.green, c.green]") when: - executer.withArguments("-PbOutputDir=out", "-PbFileName=b-blue.jar", "-PbContent=b-new") + withBuildCache().executer.withArguments("-PbOutputDir=out", "-PbFileName=b-blue.jar", "-PbContent=b-new") succeeds(":a:resolve") then: // no change, should be up to date @@ -420,7 +436,7 @@ class ArtifactTransformInputArtifactIntegrationTest extends AbstractDependencyRe outputContains("result = [b-new.green, c.green]") when: - succeeds(":a:resolve") + withBuildCache().succeeds(":a:resolve") then: // have already seen these artifacts before result.assertTasksNotSkipped(":b:producer", ":a:resolve") @@ -429,7 +445,7 @@ class ArtifactTransformInputArtifactIntegrationTest extends AbstractDependencyRe } @Unroll - def "can attach @PathSensitive(#sensitivity) to input artifact property for project artifact directory"() { + def "honors @PathSensitive(#sensitivity) to input artifact property for project artifact directory when caching"() { settingsFile << "include 'a', 'b', 'c'" setupBuildWithColorTransformAction { produceDirs() @@ -442,6 +458,7 @@ class ArtifactTransformInputArtifactIntegrationTest extends AbstractDependencyRe } } + @CacheableTransformAction abstract class MakeGreen implements TransformAction { @PathSensitive(PathSensitivity.${sensitivity}) @InputArtifact @@ -456,7 +473,7 @@ class ArtifactTransformInputArtifactIntegrationTest extends AbstractDependencyRe """ when: - succeeds(":a:resolve") + withBuildCache().succeeds(":a:resolve") then: result.assertTasksNotSkipped(":b:producer", ":c:producer", ":a:resolve") @@ -465,7 +482,7 @@ class ArtifactTransformInputArtifactIntegrationTest extends AbstractDependencyRe when: executer.withArguments("-PbOutputDir=out") - succeeds(":a:resolve") + withBuildCache().succeeds(":a:resolve") then: // path has changed, but should be up to date result.assertTasksNotSkipped(":b:producer", ":a:resolve") @@ -474,7 +491,7 @@ class ArtifactTransformInputArtifactIntegrationTest extends AbstractDependencyRe when: executer.withArguments("-PbOutputDir=out", "-PbDirName=b-blue") - succeeds(":a:resolve") + withBuildCache().succeeds(":a:resolve") then: // name has changed, but should be up to date result.assertTasksNotSkipped(":b:producer", ":a:resolve") @@ -483,7 +500,7 @@ class ArtifactTransformInputArtifactIntegrationTest extends AbstractDependencyRe when: executer.withArguments("-PbOutputDir=out", "-PbDirName=b-blue", "-PbContent=new") - succeeds(":a:resolve") + withBuildCache().succeeds(":a:resolve") then: // new content, should run result.assertTasksNotSkipped(":b:producer", ":a:resolve") @@ -492,7 +509,7 @@ class ArtifactTransformInputArtifactIntegrationTest extends AbstractDependencyRe when: executer.withArguments("-PbOutputDir=out", "-PbDirName=b-blue", "-PbContent=new") - succeeds(":a:resolve") + withBuildCache().succeeds(":a:resolve") then: // no change, should be up to date result.assertTasksNotSkipped(":a:resolve") @@ -501,7 +518,7 @@ class ArtifactTransformInputArtifactIntegrationTest extends AbstractDependencyRe when: executer.withArguments("-PbOutputDir=out", "-PbDirName=b-blue", "-PbContent=new", "-PbName=new") - succeeds(":a:resolve") + withBuildCache().succeeds(":a:resolve") then: // new content (renamed file), should run result.assertTasksNotSkipped(":b:producer", ":a:resolve") @@ -509,7 +526,7 @@ class ArtifactTransformInputArtifactIntegrationTest extends AbstractDependencyRe outputContains("result = [b-blue.green, c-dir.green]") when: - succeeds(":a:resolve") + withBuildCache().succeeds(":a:resolve") then: // have already seen these artifacts before result.assertTasksNotSkipped(":b:producer", ":a:resolve") @@ -517,11 +534,11 @@ class ArtifactTransformInputArtifactIntegrationTest extends AbstractDependencyRe outputContains("result = [b-dir.green, c-dir.green]") where: - sensitivity << [PathSensitivity.RELATIVE, PathSensitivity.NONE] + sensitivity << [PathSensitivity.NAME_ONLY, PathSensitivity.RELATIVE] } @Unroll - def "can attach @PathSensitive(#sensitivity) to input artifact property for project artifact file"() { + def "honors @PathSensitive(#sensitivity) on input artifact property for project artifact file when caching"() { settingsFile << "include 'a', 'b', 'c'" setupBuildWithColorTransformAction() buildFile << """ @@ -532,6 +549,7 @@ class ArtifactTransformInputArtifactIntegrationTest extends AbstractDependencyRe } } + @CacheableTransformAction abstract class MakeGreen implements TransformAction { @PathSensitive(PathSensitivity.${sensitivity}) @InputArtifact @@ -546,7 +564,7 @@ class ArtifactTransformInputArtifactIntegrationTest extends AbstractDependencyRe """ when: - succeeds(":a:resolve") + withBuildCache().succeeds(":a:resolve") then: result.assertTasksNotSkipped(":b:producer", ":c:producer", ":a:resolve") @@ -555,7 +573,7 @@ class ArtifactTransformInputArtifactIntegrationTest extends AbstractDependencyRe when: executer.withArguments("-PbOutputDir=out") - succeeds(":a:resolve") + withBuildCache().succeeds(":a:resolve") then: // path has changed, but should be up to date result.assertTasksNotSkipped(":b:producer", ":a:resolve") @@ -564,7 +582,7 @@ class ArtifactTransformInputArtifactIntegrationTest extends AbstractDependencyRe when: executer.withArguments("-PbOutputDir=out", "-PbFileName=b-blue.jar") - succeeds(":a:resolve") + withBuildCache().succeeds(":a:resolve") then: // name has changed, should run result.assertTasksNotSkipped(":b:producer", ":a:resolve") @@ -573,7 +591,7 @@ class ArtifactTransformInputArtifactIntegrationTest extends AbstractDependencyRe when: executer.withArguments("-PbOutputDir=out", "-PbFileName=b-blue.jar", "-PbContent=new") - succeeds(":a:resolve") + withBuildCache().succeeds(":a:resolve") then: // new content, should run result.assertTasksNotSkipped(":b:producer", ":a:resolve") @@ -582,7 +600,7 @@ class ArtifactTransformInputArtifactIntegrationTest extends AbstractDependencyRe when: executer.withArguments("-PbOutputDir=out", "-PbFileName=b-blue.jar", "-PbContent=new") - succeeds(":a:resolve") + withBuildCache().succeeds(":a:resolve") then: // no change, should be up to date result.assertTasksNotSkipped(":a:resolve") @@ -590,7 +608,7 @@ class ArtifactTransformInputArtifactIntegrationTest extends AbstractDependencyRe outputContains("result = [b-blue.jar.green, c.jar.green]") when: - succeeds(":a:resolve") + withBuildCache().succeeds(":a:resolve") then: // have already seen these artifacts before result.assertTasksNotSkipped(":b:producer", ":a:resolve") @@ -601,7 +619,7 @@ class ArtifactTransformInputArtifactIntegrationTest extends AbstractDependencyRe sensitivity << [PathSensitivity.RELATIVE, PathSensitivity.NAME_ONLY] } - def "can attach @PathSensitive(NAME_ONLY) to input artifact property for project artifact directory"() { + def "honors content changes for @PathSensitive(NONE) on input artifact property for project artifact directory when not caching"() { settingsFile << "include 'a', 'b', 'c'" setupBuildWithColorTransformAction { produceDirs() @@ -615,7 +633,7 @@ class ArtifactTransformInputArtifactIntegrationTest extends AbstractDependencyRe } abstract class MakeGreen implements TransformAction { - @PathSensitive(PathSensitivity.NAME_ONLY) + @PathSensitive(PathSensitivity.NONE) @InputArtifact abstract File getInput() @@ -639,16 +657,16 @@ class ArtifactTransformInputArtifactIntegrationTest extends AbstractDependencyRe executer.withArguments("-PbOutputDir=out") succeeds(":a:resolve") - then: // path has changed, but should be up to date + then: // path has changed, but path is baked into workspace identity result.assertTasksNotSkipped(":b:producer", ":a:resolve") - transformed() + transformed("b-dir") outputContains("result = [b-dir.green, c-dir.green]") when: executer.withArguments("-PbOutputDir=out", "-PbDirName=b-blue") succeeds(":a:resolve") - then: // name has changed, should run + then: // name has changed, but path is baked into workspace identity result.assertTasksNotSkipped(":b:producer", ":a:resolve") transformed("b-blue") outputContains("result = [b-blue.green, c-dir.green]") @@ -675,9 +693,9 @@ class ArtifactTransformInputArtifactIntegrationTest extends AbstractDependencyRe executer.withArguments("-PbOutputDir=out", "-PbDirName=b-blue", "-PbContent=new", "-PbName=new") succeeds(":a:resolve") - then: // new content (renamed file), should run + then: // new content (renamed file), should not run result.assertTasksNotSkipped(":b:producer", ":a:resolve") - transformed("b-blue") + transformed() outputContains("result = [b-blue.green, c-dir.green]") when: @@ -689,6 +707,95 @@ class ArtifactTransformInputArtifactIntegrationTest extends AbstractDependencyRe outputContains("result = [b-dir.green, c-dir.green]") } + def "honors @PathSensitive(NONE) on input artifact property for project artifact directory when caching"() { + settingsFile << "include 'a', 'b', 'c'" + setupBuildWithColorTransformAction { + produceDirs() + } + buildFile << """ + project(':a') { + dependencies { + implementation project(':b') + implementation project(':c') + } + } + + @CacheableTransformAction + abstract class MakeGreen implements TransformAction { + @PathSensitive(PathSensitivity.NONE) + @InputArtifact + abstract File getInput() + + void transform(TransformOutputs outputs) { + println "processing \${input.name}" + def output = outputs.file(input.name + ".green") + output.text = input.list().length + ".green" + } + } + """ + + when: + withBuildCache().succeeds(":a:resolve") + + then: + result.assertTasksNotSkipped(":b:producer", ":c:producer", ":a:resolve") + transformed("b-dir", "c-dir") + outputContains("result = [b-dir.green, c-dir.green]") + + when: + executer.withArguments("-PbOutputDir=out") + withBuildCache().succeeds(":a:resolve") + + then: // path has changed, should be up to date + result.assertTasksNotSkipped(":b:producer", ":a:resolve") + transformed() + outputContains("result = [b-dir.green, c-dir.green]") + + when: + executer.withArguments("-PbOutputDir=out", "-PbDirName=b-blue") + withBuildCache().succeeds(":a:resolve") + + then: // name has changed, should be up to date + result.assertTasksNotSkipped(":b:producer", ":a:resolve") + transformed() + outputContains("result = [b-dir.green, c-dir.green]") + + when: + executer.withArguments("-PbOutputDir=out", "-PbDirName=b-blue", "-PbContent=new") + withBuildCache().succeeds(":a:resolve") + + then: // new content, should run + result.assertTasksNotSkipped(":b:producer", ":a:resolve") + transformed("b-blue") + outputContains("result = [b-blue.green, c-dir.green]") + + when: + executer.withArguments("-PbOutputDir=out", "-PbDirName=b-blue", "-PbContent=new") + withBuildCache().succeeds(":a:resolve") + + then: // no change, should be up to date + result.assertTasksNotSkipped(":a:resolve") + transformed() + outputContains("result = [b-blue.green, c-dir.green]") + + when: + executer.withArguments("-PbOutputDir=out", "-PbDirName=b-blue", "-PbContent=new", "-PbName=new") + withBuildCache().succeeds(":a:resolve") + + then: // new content (renamed file), should not run + result.assertTasksNotSkipped(":b:producer", ":a:resolve") + transformed() + outputContains("result = [b-blue.green, c-dir.green]") + + when: + withBuildCache().succeeds(":a:resolve") + + then: // have already seen these artifacts before + result.assertTasksNotSkipped(":b:producer", ":a:resolve") + transformed() + outputContains("result = [b-dir.green, c-dir.green]") + } + def "can attach @PathSensitive(NONE) to input artifact property for external artifact"() { setupBuildWithColorTransformAction() def lib1 = mavenRepo.module("group1", "lib", "1.0").adhocVariants().variant('runtime', [color: 'blue']).withModuleMetadata().publish() @@ -856,7 +963,7 @@ class ArtifactTransformInputArtifactIntegrationTest extends AbstractDependencyRe } @Unroll - def "can attach @#annotation to input artifact property with project artifact file"() { + def "honors content changes with @#annotation on input artifact property with project artifact file when not caching"() { settingsFile << "include 'a', 'b', 'c'" setupBuildWithColorTransformAction { produceJars() @@ -916,36 +1023,46 @@ class ArtifactTransformInputArtifactIntegrationTest extends AbstractDependencyRe outputContains("result = [b.jar.green, c.jar.green]") when: - executer.withArguments("-PbContent=new", "-PbOutputDir=out") + executer.withArguments("-PbContent=new", "-PbTimestamp=567") succeeds(":a:resolve") - then: // path has changed, transforms up-to-date + then: // timestamp change only, should not run result.assertTasksNotSkipped(":b:producer", ":a:resolve") transformed() outputContains("result = [b.jar.green, c.jar.green]") when: - executer.withArguments("-PbContent=new", "-PbOutputDir=out", "-PbFileName=b-blue.jar") + executer.withArguments("-PbContent=new", "-PbTimestamp=567", "-PbOutputDir=out") succeeds(":a:resolve") - then: // new file name, transforms up-to-date + then: // path has changed, but path is baked into workspace identity result.assertTasksNotSkipped(":b:producer", ":a:resolve") - transformed() + transformed("b.jar") outputContains("result = [b.jar.green, c.jar.green]") when: + executer.withArguments("-PbContent=new", "-PbTimestamp=567", "-PbOutputDir=out", "-PbFileName=b-blue.jar") succeeds(":a:resolve") - then: // have already seen these artifacts before + then: // new file name, but path is baked into workspace identity result.assertTasksNotSkipped(":b:producer", ":a:resolve") - transformed() + transformed("b-blue.jar") + outputContains("result = [b-blue.jar.green, c.jar.green]") + + when: + succeeds(":a:resolve") + + then: // have already seen these artifacts before, but outputs have been overwritten + result.assertTasksNotSkipped(":b:producer", ":a:resolve") + transformed("b.jar") outputContains("result = [b.jar.green, c.jar.green]") where: annotation << ["Classpath", "CompileClasspath"] } - def "result is loaded from the build cache"() { + @Unroll + def "honors @#annotation on input artifact property with project artifact file when caching"() { settingsFile << "include 'a', 'b', 'c'" setupBuildWithColorTransformAction { produceJars() @@ -960,7 +1077,7 @@ class ArtifactTransformInputArtifactIntegrationTest extends AbstractDependencyRe @CacheableTransformAction abstract class MakeGreen implements TransformAction { - @InputArtifact @Classpath + @InputArtifact @${annotation} abstract File getInput() void transform(TransformOutputs outputs) { @@ -980,31 +1097,68 @@ class ArtifactTransformInputArtifactIntegrationTest extends AbstractDependencyRe outputContains("result = [b.jar.green, c.jar.green]") when: - executer.withArguments("-PbTimestamp=5678") - succeeds(":a:resolve") + withBuildCache().succeeds(":a:resolve") - then: // timestamp change without build cache + then: // no change, should be up to date + result.assertTasksNotSkipped(":a:resolve") + transformed() + outputContains("result = [b.jar.green, c.jar.green]") + + when: + executer.withArguments("-PbContent=new") + withBuildCache().succeeds(":a:resolve") + + then: // new content, should run result.assertTasksNotSkipped(":b:producer", ":a:resolve") transformed("b.jar") outputContains("result = [b.jar.green, c.jar.green]") when: - executer.withArguments("-PbTimestamp=7890") + executer.withArguments("-PbContent=new") + withBuildCache().succeeds(":a:resolve") + + then: // no change, should be up to date + result.assertTasksNotSkipped(":a:resolve") + transformed() + outputContains("result = [b.jar.green, c.jar.green]") + + when: + executer.withArguments("-PbContent=new", "-PbTimestamp=567") withBuildCache().succeeds(":a:resolve") - then: // timestamp change, pulled from cache + then: // timestamp change only, should not run result.assertTasksNotSkipped(":b:producer", ":a:resolve") transformed() outputContains("result = [b.jar.green, c.jar.green]") when: - executer.withArguments("-PbTimestamp=7890") - succeeds(":a:resolve") + executer.withArguments("-PbContent=new", "-PbTimestamp=567", "-PbOutputDir=out") + withBuildCache().succeeds(":a:resolve") - then: // no change, up-to-date - result.assertTasksNotSkipped(":a:resolve") + then: // path has changed, should not run + result.assertTasksNotSkipped(":b:producer", ":a:resolve") transformed() outputContains("result = [b.jar.green, c.jar.green]") + + when: + executer.withArguments("-PbContent=new", "-PbTimestamp=567", "-PbOutputDir=out", "-PbFileName=b-blue.jar") + withBuildCache().succeeds(":a:resolve") + + then: // new file name, should not run + result.assertTasksNotSkipped(":b:producer", ":a:resolve") + transformed() + outputContains("result = [b.jar.green, c.jar.green]") + + when: + withBuildCache().succeeds(":a:resolve") + + then: // have already seen these artifacts before, should not run + result.assertTasksNotSkipped(":b:producer", ":a:resolve") + transformed() + outputContains("result = [b.jar.green, c.jar.green]") + + where: + annotation << ["Classpath", "CompileClasspath"] } void transformed(String... expected) { From 9e84577bfce96a97933212e858e3c45e394389f2 Mon Sep 17 00:00:00 2001 From: Gary Hale Date: Sun, 24 Feb 2019 17:39:11 -0500 Subject: [PATCH 099/853] Set initial heap size for classloader leak test --- .../launcher/daemon/ClassLoaderLeakAvoidanceSoakTest.groovy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subprojects/soak/src/integTest/groovy/org/gradle/launcher/daemon/ClassLoaderLeakAvoidanceSoakTest.groovy b/subprojects/soak/src/integTest/groovy/org/gradle/launcher/daemon/ClassLoaderLeakAvoidanceSoakTest.groovy index cfb5b10a930b5..c5e8e70d9fbe1 100644 --- a/subprojects/soak/src/integTest/groovy/org/gradle/launcher/daemon/ClassLoaderLeakAvoidanceSoakTest.groovy +++ b/subprojects/soak/src/integTest/groovy/org/gradle/launcher/daemon/ClassLoaderLeakAvoidanceSoakTest.groovy @@ -94,7 +94,7 @@ class ClassLoaderLeakAvoidanceSoakTest extends AbstractIntegrationSpec { expect: for(int i = 0; i < 35; i++) { buildFile.text = buildFile.text.replace("Foo$i", "Foo${i + 1}") - executer.withBuildJvmOpts("-Xmx128m", "-XX:+HeapDumpOnOutOfMemoryError", "-XX:MaxMetaspaceSize=64m") + executer.withBuildJvmOpts("-Xms64m", "-Xmx128m", "-XX:+HeapDumpOnOutOfMemoryError", "-XX:MaxMetaspaceSize=64m") assert succeeds("myTask") } } From 3cee9c702b451eb3e1c7b9a5dc482c36076d0f17 Mon Sep 17 00:00:00 2001 From: Gradleware Git Bot Date: Mon, 25 Feb 2019 02:47:38 +0100 Subject: [PATCH 100/853] Publish 5.3-20190225013325+0000 --- released-versions.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/released-versions.json b/released-versions.json index 3b3a57b2b599f..ca33ca082760f 100644 --- a/released-versions.json +++ b/released-versions.json @@ -1,7 +1,7 @@ { "latestReleaseSnapshot": { - "version": "5.3-20190224011633+0000", - "buildTime": "20190224011633+0000" + "version": "5.3-20190225013325+0000", + "buildTime": "20190225013325+0000" }, "latestRc": { "version": "5.2-rc-1", From 68943c88eeef8a373a21e7513b6b0584e69c251a Mon Sep 17 00:00:00 2001 From: Stefan Wolf Date: Mon, 25 Feb 2019 09:16:45 +0100 Subject: [PATCH 101/853] Rename CacheableTransform{Action -> } The action doesn't add anything to the name. --- ...bleTransformAction.java => CacheableTransform.java} | 4 ++-- ...rtifactTransformInputArtifactIntegrationTest.groovy | 10 +++++----- ...ifactTransformValuesInjectionIntegrationTest.groovy | 4 ++-- .../DefaultTransformationRegistrationFactory.java | 4 ++-- 4 files changed, 11 insertions(+), 11 deletions(-) rename subprojects/core-api/src/main/java/org/gradle/api/artifacts/transform/{CacheableTransformAction.java => CacheableTransform.java} (95%) diff --git a/subprojects/core-api/src/main/java/org/gradle/api/artifacts/transform/CacheableTransformAction.java b/subprojects/core-api/src/main/java/org/gradle/api/artifacts/transform/CacheableTransform.java similarity index 95% rename from subprojects/core-api/src/main/java/org/gradle/api/artifacts/transform/CacheableTransformAction.java rename to subprojects/core-api/src/main/java/org/gradle/api/artifacts/transform/CacheableTransform.java index e1d510ddd6638..4b1dd5ef91ce9 100644 --- a/subprojects/core-api/src/main/java/org/gradle/api/artifacts/transform/CacheableTransformAction.java +++ b/subprojects/core-api/src/main/java/org/gradle/api/artifacts/transform/CacheableTransform.java @@ -26,12 +26,12 @@ /** *

    Attached to an {@link TransformAction} type to indicate that the build cache should be used for artifact transforms of this type.

    * - *

    Only an artifact transform that produces reproducible and relocatable outputs should be marked with {@code CacheableTransformAction}.

    + *

    Only an artifact transform that produces reproducible and relocatable outputs should be marked with {@code CacheableTransform}.

    * * @since 5.3 */ @Incubating @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE}) -public @interface CacheableTransformAction { +public @interface CacheableTransform { } diff --git a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformInputArtifactIntegrationTest.groovy b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformInputArtifactIntegrationTest.groovy index f4645e9dd3ba8..276e526f3dc53 100644 --- a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformInputArtifactIntegrationTest.groovy +++ b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformInputArtifactIntegrationTest.groovy @@ -377,7 +377,7 @@ class ArtifactTransformInputArtifactIntegrationTest extends AbstractDependencyRe } } - @CacheableTransformAction + @CacheableTransform abstract class MakeGreen implements TransformAction { @PathSensitive(PathSensitivity.NONE) @InputArtifact @@ -458,7 +458,7 @@ class ArtifactTransformInputArtifactIntegrationTest extends AbstractDependencyRe } } - @CacheableTransformAction + @CacheableTransform abstract class MakeGreen implements TransformAction { @PathSensitive(PathSensitivity.${sensitivity}) @InputArtifact @@ -549,7 +549,7 @@ class ArtifactTransformInputArtifactIntegrationTest extends AbstractDependencyRe } } - @CacheableTransformAction + @CacheableTransform abstract class MakeGreen implements TransformAction { @PathSensitive(PathSensitivity.${sensitivity}) @InputArtifact @@ -720,7 +720,7 @@ class ArtifactTransformInputArtifactIntegrationTest extends AbstractDependencyRe } } - @CacheableTransformAction + @CacheableTransform abstract class MakeGreen implements TransformAction { @PathSensitive(PathSensitivity.NONE) @InputArtifact @@ -1075,7 +1075,7 @@ class ArtifactTransformInputArtifactIntegrationTest extends AbstractDependencyRe } } - @CacheableTransformAction + @CacheableTransform abstract class MakeGreen implements TransformAction { @InputArtifact @${annotation} abstract File getInput() diff --git a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformValuesInjectionIntegrationTest.groovy b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformValuesInjectionIntegrationTest.groovy index 618bef70b00de..5e2766347f005 100644 --- a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformValuesInjectionIntegrationTest.groovy +++ b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformValuesInjectionIntegrationTest.groovy @@ -178,7 +178,7 @@ class ArtifactTransformValuesInjectionIntegrationTest extends AbstractDependency ConfigurableFileCollection getAbsolutePathSensitivity() } - @CacheableTransformAction + @CacheableTransform abstract class MakeGreenAction implements TransformAction { @TransformParameters abstract MakeGreen getParameters() @@ -326,7 +326,7 @@ class ArtifactTransformValuesInjectionIntegrationTest extends AbstractDependency void setExtension(String value) } - @CacheableTransformAction + @CacheableTransform abstract class MakeGreenAction implements TransformAction { @TransformParameters abstract MakeGreen getParameters() diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformationRegistrationFactory.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformationRegistrationFactory.java index 209d9a2891cba..0da58e27bf9f4 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformationRegistrationFactory.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformationRegistrationFactory.java @@ -18,7 +18,7 @@ import org.gradle.api.InvalidUserDataException; import org.gradle.api.artifacts.transform.ArtifactTransform; -import org.gradle.api.artifacts.transform.CacheableTransformAction; +import org.gradle.api.artifacts.transform.CacheableTransform; import org.gradle.api.artifacts.transform.InputArtifact; import org.gradle.api.artifacts.transform.InputArtifactDependencies; import org.gradle.api.artifacts.transform.TransformAction; @@ -93,7 +93,7 @@ public ArtifactTransformRegistration create(ImmutableAttributes from, ImmutableA TypeMetadata actionMetadata = actionMetadataStore.getTypeMetadata(implementation); DefaultParameterValidationContext parameterValidationContext = new DefaultParameterValidationContext(validationMessages); actionMetadata.collectValidationFailures(null, parameterValidationContext); - boolean cacheable = implementation.isAnnotationPresent(CacheableTransformAction.class); + boolean cacheable = implementation.isAnnotationPresent(CacheableTransform.class); // Should retain this on the metadata rather than calculate on each invocation Class inputArtifactNormalizer = null; From ed006823d7cc85af0cd7a8b8174e97192bedf9c1 Mon Sep 17 00:00:00 2001 From: Stefan Wolf Date: Mon, 25 Feb 2019 10:53:37 +0100 Subject: [PATCH 102/853] Rename {Isolatable -> Isolated}Parameters --- .../transform/DefaultTransformer.java | 32 +++++++++---------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformer.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformer.java index 30e9665d66702..a8ab939abc163 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformer.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformer.java @@ -84,7 +84,7 @@ public class DefaultTransformer extends AbstractTransformer { private final InstanceFactory instanceFactory; private final boolean cacheable; - private IsolatableParameters isolatable; + private IsolatedParameters isolatedParameters; public DefaultTransformer( Class implementationClass, @@ -137,7 +137,7 @@ public Class getInputArtifactDependenciesNormalizer() @Override public boolean isIsolated() { - return isolatable != null; + return isolatedParameters != null; } public boolean requiresDependencies() { @@ -151,7 +151,7 @@ public boolean isCacheable() { @Override public HashCode getSecondaryInputHash() { - return getIsolatable().getSecondaryInputsHash(); + return getIsolatedParameters().getSecondaryInputsHash(); } @Override @@ -177,13 +177,13 @@ public void visitInputFileProperty(String propertyName, boolean optional, boolea @Override public void isolateParameters(FileCollectionFingerprinterRegistry fingerprinterRegistry) { try { - isolatable = doIsolateParameters(fingerprinterRegistry); + isolatedParameters = doIsolateParameters(fingerprinterRegistry); } catch (Exception e) { throw new VariantTransformConfigurationException(String.format("Cannot isolate parameters %s of artifact transform %s", parameterObject, ModelType.of(getImplementationClass()).getDisplayName()), e); } } - protected IsolatableParameters doIsolateParameters(FileCollectionFingerprinterRegistry fingerprinterRegistry) { + protected IsolatedParameters doIsolateParameters(FileCollectionFingerprinterRegistry fingerprinterRegistry) { Isolatable isolatableParameterObject = isolatableFactory.isolate(parameterObject); Hasher hasher = Hashing.newHasher(); @@ -194,7 +194,7 @@ protected IsolatableParameters doIsolateParameters(FileCollectionFingerprinterRe fingerprintParameters(valueSnapshotter, fingerprinterRegistry, fileCollectionFactory, parameterPropertyWalker, hasher, isolatableParameterObject.isolate(), cacheable); } HashCode secondaryInputsHash = hasher.hash(); - return new IsolatableParameters(isolatableParameterObject, secondaryInputsHash); + return new IsolatedParameters(isolatableParameterObject, secondaryInputsHash); } private static void fingerprintParameters( @@ -267,15 +267,15 @@ private static String getParameterObjectDisplayName(Object parameterObject) { } private TransformAction newTransformAction(File inputFile, ArtifactTransformDependencies artifactTransformDependencies) { - ServiceLookup services = new TransformServiceLookup(inputFile, getIsolatable().getIsolatableParameters().isolate(), requiresDependencies ? artifactTransformDependencies : null); + ServiceLookup services = new TransformServiceLookup(inputFile, getIsolatedParameters().getIsolatedParameterObject().isolate(), requiresDependencies ? artifactTransformDependencies : null); return instanceFactory.newInstance(services); } - private IsolatableParameters getIsolatable() { - if (isolatable == null) { + private IsolatedParameters getIsolatedParameters() { + if (isolatedParameters == null) { throw new IllegalStateException("The parameters of " + getDisplayName() + "need to be isolated first!"); } - return isolatable; + return isolatedParameters; } private static class TransformServiceLookup implements ServiceLookup { @@ -365,21 +365,21 @@ public Object getValueToInject() { } } - private static class IsolatableParameters { + private static class IsolatedParameters { private HashCode secondaryInputsHash; - private Isolatable isolatableParameters; + private Isolatable isolatedParameterObject; - public IsolatableParameters(Isolatable isolatableParameters, HashCode secondaryInputsHash) { + public IsolatedParameters(Isolatable isolatedParameterObject, HashCode secondaryInputsHash) { this.secondaryInputsHash = secondaryInputsHash; - this.isolatableParameters = isolatableParameters; + this.isolatedParameterObject = isolatedParameterObject; } public HashCode getSecondaryInputsHash() { return secondaryInputsHash; } - public Isolatable getIsolatableParameters() { - return isolatableParameters; + public Isolatable getIsolatedParameterObject() { + return isolatedParameterObject; } } } From 03e0697c90176db4d2e6a288fb0fb641dd70b417 Mon Sep 17 00:00:00 2001 From: Cedric Champeau Date: Fri, 15 Feb 2019 15:53:21 +0100 Subject: [PATCH 103/853] Make Gradle metadata format 1.0 This commit bumps the Gradle metadata format to 1.0. The specification file of the format has been changed so that the name of the file indicates which version it covers. Starting from this commit, it is illegal to change the metadata file format _without_ backwards compatibility in mind. --- .../parser/ModuleMetadataParser.java | 2 +- .../parser/ModuleMetadataParserTest.groovy | 36 +++++++++---------- .../gradle/boolean-attributes.module | 2 +- .../dependencies-with-attributes.module | 2 +- .../gradle/java-library-with-excludes.module | 2 +- .../gradle/module-with-capabilities.module | 2 +- .../gradle/module-with-constraints.module | 2 +- .../gradle/module-with-dependencies.module | 2 +- .../gradle/module-with-variants.module | 2 +- .../gradle/with-custom-attributes.module | 2 +- .../gradle/with-nondefault-status.module | 2 +- ...adle-module-metadata-1.0-specification.md} | 23 ++++++++---- .../demo/producer/1.0/producer-1.0.module | 2 +- .../test/fixtures/GradleModuleMetadata.groovy | 2 +- 14 files changed, 46 insertions(+), 37 deletions(-) rename subprojects/docs/src/docs/design/{gradle-module-metadata-specification.md => gradle-module-metadata-1.0-specification.md} (89%) diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/parser/ModuleMetadataParser.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/parser/ModuleMetadataParser.java index 7fa9be54b5f3a..afab83b7eaad5 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/parser/ModuleMetadataParser.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/parser/ModuleMetadataParser.java @@ -55,7 +55,7 @@ import static org.apache.commons.lang.StringUtils.capitalize; public class ModuleMetadataParser { - public static final String FORMAT_VERSION = "0.4"; + public static final String FORMAT_VERSION = "1.0"; private final ImmutableAttributesFactory attributesFactory; private final NamedObjectInstantiator instantiator; private final ExcludeRuleConverter excludeRuleConverter; diff --git a/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/parser/ModuleMetadataParserTest.groovy b/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/parser/ModuleMetadataParserTest.groovy index a2616473a076c..d526ce267e405 100644 --- a/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/parser/ModuleMetadataParserTest.groovy +++ b/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/parser/ModuleMetadataParserTest.groovy @@ -80,7 +80,7 @@ class ModuleMetadataParserTest extends Specification { def metadata = Mock(MutableModuleComponentResolveMetadata) when: - parser.parse(resource('{ "formatVersion": "0.4" }'), metadata) + parser.parse(resource('{ "formatVersion": "1.0" }'), metadata) then: 1 * metadata.setContentHash(_) @@ -93,7 +93,7 @@ class ModuleMetadataParserTest extends Specification { when: parser.parse(resource(''' { - "formatVersion": "0.4", + "formatVersion": "1.0", "component": { "url": "elsewhere", "group": "g", "module": "m", "version": "v" }, "builtBy": { "gradle": { "version": "123", "buildId": "abc" } } } @@ -110,7 +110,7 @@ class ModuleMetadataParserTest extends Specification { when: parser.parse(resource(''' { - "formatVersion": "0.4", + "formatVersion": "1.0", "component": { "url": "elsewhere", "group": "g", "module": "m", "version": "v", "attributes": {"foo": "bar", "org.gradle.status": "release" } }, "builtBy": { "gradle": { "version": "123", "buildId": "abc" } } } @@ -129,7 +129,7 @@ class ModuleMetadataParserTest extends Specification { when: parser.parse(resource(''' { - "formatVersion": "0.4", + "formatVersion": "1.0", "variants": [ { "name": "api", @@ -157,7 +157,7 @@ class ModuleMetadataParserTest extends Specification { when: parser.parse(resource(''' { - "formatVersion": "0.4", + "formatVersion": "1.0", "variants": [ { "name": "api", @@ -186,7 +186,7 @@ class ModuleMetadataParserTest extends Specification { when: parser.parse(resource(''' { - "formatVersion": "0.4", + "formatVersion": "1.0", "variants": [ { "name": "api", @@ -227,7 +227,7 @@ class ModuleMetadataParserTest extends Specification { when: parser.parse(resource(''' { - "formatVersion": "0.4", + "formatVersion": "1.0", "variants": [ { "name": "api", @@ -284,7 +284,7 @@ class ModuleMetadataParserTest extends Specification { when: parser.parse(resource(''' { - "formatVersion": "0.4", + "formatVersion": "1.0", "variants": [ { "name": "api", @@ -335,7 +335,7 @@ class ModuleMetadataParserTest extends Specification { when: parser.parse(resource(''' { - "formatVersion": "0.4", + "formatVersion": "1.0", "variants": [ { "name": "api", @@ -376,7 +376,7 @@ class ModuleMetadataParserTest extends Specification { when: parser.parse(resource(''' { - "formatVersion": "0.4", + "formatVersion": "1.0", "variants": [ { "name": "api", @@ -416,7 +416,7 @@ class ModuleMetadataParserTest extends Specification { when: parser.parse(resource(''' { - "formatVersion": "0.4", + "formatVersion": "1.0", "builtBy": { "gradle": { "version": "123", "buildId": "abc" } }, "variants": [ { @@ -441,7 +441,7 @@ class ModuleMetadataParserTest extends Specification { when: parser.parse(resource(''' { - "formatVersion": "0.4", + "formatVersion": "1.0", "variants": [ { "name": "api" @@ -471,7 +471,7 @@ class ModuleMetadataParserTest extends Specification { when: parser.parse(resource(''' { - "formatVersion": "0.4", + "formatVersion": "1.0", "variants": [ { "name": "api", @@ -522,7 +522,7 @@ class ModuleMetadataParserTest extends Specification { when: parser.parse(resource('''{ - "formatVersion": "0.4", + "formatVersion": "1.0", "otherString": "string", "otherNumber": 123, "otherBoolean": true, @@ -542,7 +542,7 @@ class ModuleMetadataParserTest extends Specification { when: parser.parse(resource(''' { - "formatVersion": "0.4", + "formatVersion": "1.0", "variants": [ { "name": "api", @@ -570,7 +570,7 @@ class ModuleMetadataParserTest extends Specification { when: parser.parse(resource(''' { - "formatVersion": "0.4", + "formatVersion": "1.0", "variants": [ { "name": "api", @@ -602,7 +602,7 @@ class ModuleMetadataParserTest extends Specification { when: parser.parse(resource(''' { - "formatVersion": "0.4", + "formatVersion": "1.0", "variants": [ { "name": "api", @@ -685,7 +685,7 @@ class ModuleMetadataParserTest extends Specification { then: def e = thrown(MetaDataParseException) e.message == "Could not parse module metadata " - e.cause.message == "Unsupported format version '123.4' specified in module metadata. This version of Gradle supports format version 0.4 only." + e.cause.message == "Unsupported format version '123.4' specified in module metadata. This version of Gradle supports format version 1.0 only." } def resource(String content) { diff --git a/subprojects/dependency-management/src/test/resources/org/gradle/api/internal/artifacts/ivyservice/modulecache/ModuleMetadataSerializerTest/gradle/boolean-attributes.module b/subprojects/dependency-management/src/test/resources/org/gradle/api/internal/artifacts/ivyservice/modulecache/ModuleMetadataSerializerTest/gradle/boolean-attributes.module index 638f567b8a3ed..7b104104ac0e0 100644 --- a/subprojects/dependency-management/src/test/resources/org/gradle/api/internal/artifacts/ivyservice/modulecache/ModuleMetadataSerializerTest/gradle/boolean-attributes.module +++ b/subprojects/dependency-management/src/test/resources/org/gradle/api/internal/artifacts/ivyservice/modulecache/ModuleMetadataSerializerTest/gradle/boolean-attributes.module @@ -1,5 +1,5 @@ { - "formatVersion": "0.4", + "formatVersion": "1.0", "builtBy": { "gradle": { "version": "123", "buildId": "abc" } }, "variants": [ { diff --git a/subprojects/dependency-management/src/test/resources/org/gradle/api/internal/artifacts/ivyservice/modulecache/ModuleMetadataSerializerTest/gradle/dependencies-with-attributes.module b/subprojects/dependency-management/src/test/resources/org/gradle/api/internal/artifacts/ivyservice/modulecache/ModuleMetadataSerializerTest/gradle/dependencies-with-attributes.module index d5e877a34eea4..61a2e9ad33d00 100644 --- a/subprojects/dependency-management/src/test/resources/org/gradle/api/internal/artifacts/ivyservice/modulecache/ModuleMetadataSerializerTest/gradle/dependencies-with-attributes.module +++ b/subprojects/dependency-management/src/test/resources/org/gradle/api/internal/artifacts/ivyservice/modulecache/ModuleMetadataSerializerTest/gradle/dependencies-with-attributes.module @@ -1,5 +1,5 @@ { - "formatVersion": "0.4", + "formatVersion": "1.0", "variants": [ { "name": "api", diff --git a/subprojects/dependency-management/src/test/resources/org/gradle/api/internal/artifacts/ivyservice/modulecache/ModuleMetadataSerializerTest/gradle/java-library-with-excludes.module b/subprojects/dependency-management/src/test/resources/org/gradle/api/internal/artifacts/ivyservice/modulecache/ModuleMetadataSerializerTest/gradle/java-library-with-excludes.module index 04b99253f4059..fd86eab36a932 100644 --- a/subprojects/dependency-management/src/test/resources/org/gradle/api/internal/artifacts/ivyservice/modulecache/ModuleMetadataSerializerTest/gradle/java-library-with-excludes.module +++ b/subprojects/dependency-management/src/test/resources/org/gradle/api/internal/artifacts/ivyservice/modulecache/ModuleMetadataSerializerTest/gradle/java-library-with-excludes.module @@ -1,5 +1,5 @@ { - "formatVersion": "0.4", + "formatVersion": "1.0", "component": { "group": "org.gradle.test", "module": "publishTest", diff --git a/subprojects/dependency-management/src/test/resources/org/gradle/api/internal/artifacts/ivyservice/modulecache/ModuleMetadataSerializerTest/gradle/module-with-capabilities.module b/subprojects/dependency-management/src/test/resources/org/gradle/api/internal/artifacts/ivyservice/modulecache/ModuleMetadataSerializerTest/gradle/module-with-capabilities.module index 22c7d8f825d50..6291f65e0b7e3 100644 --- a/subprojects/dependency-management/src/test/resources/org/gradle/api/internal/artifacts/ivyservice/modulecache/ModuleMetadataSerializerTest/gradle/module-with-capabilities.module +++ b/subprojects/dependency-management/src/test/resources/org/gradle/api/internal/artifacts/ivyservice/modulecache/ModuleMetadataSerializerTest/gradle/module-with-capabilities.module @@ -1,5 +1,5 @@ { - "formatVersion": "0.4", + "formatVersion": "1.0", "variants": [ { "name": "api", diff --git a/subprojects/dependency-management/src/test/resources/org/gradle/api/internal/artifacts/ivyservice/modulecache/ModuleMetadataSerializerTest/gradle/module-with-constraints.module b/subprojects/dependency-management/src/test/resources/org/gradle/api/internal/artifacts/ivyservice/modulecache/ModuleMetadataSerializerTest/gradle/module-with-constraints.module index 50ba1cad77354..be74f29da84bc 100644 --- a/subprojects/dependency-management/src/test/resources/org/gradle/api/internal/artifacts/ivyservice/modulecache/ModuleMetadataSerializerTest/gradle/module-with-constraints.module +++ b/subprojects/dependency-management/src/test/resources/org/gradle/api/internal/artifacts/ivyservice/modulecache/ModuleMetadataSerializerTest/gradle/module-with-constraints.module @@ -1,5 +1,5 @@ { - "formatVersion": "0.4", + "formatVersion": "1.0", "variants": [ { "name": "api", diff --git a/subprojects/dependency-management/src/test/resources/org/gradle/api/internal/artifacts/ivyservice/modulecache/ModuleMetadataSerializerTest/gradle/module-with-dependencies.module b/subprojects/dependency-management/src/test/resources/org/gradle/api/internal/artifacts/ivyservice/modulecache/ModuleMetadataSerializerTest/gradle/module-with-dependencies.module index f288d9488a32d..88fdf10270891 100644 --- a/subprojects/dependency-management/src/test/resources/org/gradle/api/internal/artifacts/ivyservice/modulecache/ModuleMetadataSerializerTest/gradle/module-with-dependencies.module +++ b/subprojects/dependency-management/src/test/resources/org/gradle/api/internal/artifacts/ivyservice/modulecache/ModuleMetadataSerializerTest/gradle/module-with-dependencies.module @@ -1,5 +1,5 @@ { - "formatVersion": "0.4", + "formatVersion": "1.0", "variants": [ { "name": "api", diff --git a/subprojects/dependency-management/src/test/resources/org/gradle/api/internal/artifacts/ivyservice/modulecache/ModuleMetadataSerializerTest/gradle/module-with-variants.module b/subprojects/dependency-management/src/test/resources/org/gradle/api/internal/artifacts/ivyservice/modulecache/ModuleMetadataSerializerTest/gradle/module-with-variants.module index f8e39e1b2505b..4b885c14e1fd9 100644 --- a/subprojects/dependency-management/src/test/resources/org/gradle/api/internal/artifacts/ivyservice/modulecache/ModuleMetadataSerializerTest/gradle/module-with-variants.module +++ b/subprojects/dependency-management/src/test/resources/org/gradle/api/internal/artifacts/ivyservice/modulecache/ModuleMetadataSerializerTest/gradle/module-with-variants.module @@ -1,5 +1,5 @@ { - "formatVersion": "0.4", + "formatVersion": "1.0", "variants": [ { "name": "api", diff --git a/subprojects/dependency-management/src/test/resources/org/gradle/api/internal/artifacts/ivyservice/modulecache/ModuleMetadataSerializerTest/gradle/with-custom-attributes.module b/subprojects/dependency-management/src/test/resources/org/gradle/api/internal/artifacts/ivyservice/modulecache/ModuleMetadataSerializerTest/gradle/with-custom-attributes.module index e8f2756eaacc7..fb2883e8cebe2 100644 --- a/subprojects/dependency-management/src/test/resources/org/gradle/api/internal/artifacts/ivyservice/modulecache/ModuleMetadataSerializerTest/gradle/with-custom-attributes.module +++ b/subprojects/dependency-management/src/test/resources/org/gradle/api/internal/artifacts/ivyservice/modulecache/ModuleMetadataSerializerTest/gradle/with-custom-attributes.module @@ -1,5 +1,5 @@ { - "formatVersion": "0.4", + "formatVersion": "1.0", "component": { "group": "org.gradle.test", "module": "publishTest", diff --git a/subprojects/dependency-management/src/test/resources/org/gradle/api/internal/artifacts/ivyservice/modulecache/ModuleMetadataSerializerTest/gradle/with-nondefault-status.module b/subprojects/dependency-management/src/test/resources/org/gradle/api/internal/artifacts/ivyservice/modulecache/ModuleMetadataSerializerTest/gradle/with-nondefault-status.module index 684af2c794b54..ee4092c42f4f9 100644 --- a/subprojects/dependency-management/src/test/resources/org/gradle/api/internal/artifacts/ivyservice/modulecache/ModuleMetadataSerializerTest/gradle/with-nondefault-status.module +++ b/subprojects/dependency-management/src/test/resources/org/gradle/api/internal/artifacts/ivyservice/modulecache/ModuleMetadataSerializerTest/gradle/with-nondefault-status.module @@ -1,5 +1,5 @@ { - "formatVersion": "0.4", + "formatVersion": "1.0", "component": { "group": "org.gradle.test", "module": "publishTest", diff --git a/subprojects/docs/src/docs/design/gradle-module-metadata-specification.md b/subprojects/docs/src/docs/design/gradle-module-metadata-1.0-specification.md similarity index 89% rename from subprojects/docs/src/docs/design/gradle-module-metadata-specification.md rename to subprojects/docs/src/docs/design/gradle-module-metadata-1.0-specification.md index e6e0ecc19d904..1d51f2dce010d 100644 --- a/subprojects/docs/src/docs/design/gradle-module-metadata-specification.md +++ b/subprojects/docs/src/docs/design/gradle-module-metadata-1.0-specification.md @@ -1,8 +1,8 @@ -# Gradle module metadata specification +# Gradle module metadata 1.0 specification -_Note: this format is not yet stable and may change at any time. Gradle does not guarantee to offer any long term support for this version of the format. Any version before 1.0 is intentionally assumed not backwards compatible, and the parsers are not required to support pre 1.0 releases._ +Consumption of Gradle metadata is automatic. However publication needs to be enabled explicitly for any Gradle version prior to Gradle 6. -Support for Gradle metadata can be enabled in Gradle settings file (`settings.gradle`): +Publishing Gradle metadata can be enabled in Gradle settings file (`settings.gradle`): ``` enableFeaturePreview("GRADLE_METADATA") @@ -10,7 +10,7 @@ enableFeaturePreview("GRADLE_METADATA") ## Goal -This document describes version 0.4 of the Gradle module metadata file. A module metadata file describes the contents of a _module_, which is the unit of publication for a particular repository format, such as a module in a Maven repository. This is often called a "package" in many repository formats. +This document describes version 1.0 of the Gradle module metadata file. A module metadata file describes the contents of a _module_, which is the unit of publication for a particular repository format, such as a module in a Maven repository. This is often called a "package" in many repository formats. The module metadata file is a JSON file published alongside the existing repository specific metadata files, such as a Maven POM or Ivy descriptor. It adds additional metadata that can be used by Gradle versions and other tooling that understand the format. This allows the rich Gradle model to be mapped to and "tunnelled" through existing repository formats, while continuing to support existing Gradle versions and tooling that does not understand the format. @@ -18,7 +18,7 @@ The module metadata file is intended to be machine generated rather than written The module metadata file is also intended to fully describe the binaries in the module where it is present so that it can replace the existing metadata files. This would allow a Gradle repository format to be added, for example. -In version 0.4, the module metadata file can describe only those modules that contain a single _component_, which is some piece of software such as a library or application. Support for more sophisticated mappings will be added by later versions. +In version 1.0, the module metadata file can describe only those modules that contain a single _component_, which is some piece of software such as a library or application. Support for more sophisticated mappings may be added by later versions. ## Usage in a Maven repository @@ -32,7 +32,7 @@ The file must be encoded using UTF-8. The file must contain a JSON object with the following values: -- `formatVersion`: must be present and the first value of the JSON object. Its value must be `"0.4"` +- `formatVersion`: must be present and the first value of the JSON object. Its value must be `"1.0"` - `component`: optional. Describes the identity of the component contained in the module. - `builtBy`: optional. Describes the producer of this metadata file and the contents of the module. - `variants`: optional. Describes the variants of the component packaged in the module, if any. @@ -85,6 +85,15 @@ This value must contain an array of 0 or more capabilities. Each capability is a #### Standard attributes - `org.gradle.usage` indicates the purpose of the variant. See the `org.gradle.api.attributes.Usage` class for more details. Value must be a string. +- `org.gradle.status` indicates the kind of release: one of `release` or `integration`. + +#### Java Ecosystem specific attributes + +- `org.gradle.dependency.bundling` indicates how dependencies of the variant are bundled. Either externally, embedded or shadowed. See the `org.gradle.api.attributes.java.Bundling` for more details. Value must be a string. +- `org.gradle.component.category` indicates the type of component (library or platform). This attribute is mostly used to disambiguate Maven POM files derived either as a platform or a library. + +#### Native ecosystem specific attributes + - `org.gradle.native.debuggable` indicates native binaries that are debuggable. Value must be a boolean. ### `available-at` value @@ -151,7 +160,7 @@ This value must contain an array with zero or more elements. Each element must b ``` { - "formatVersion": "0.4", + "formatVersion": "1.0", "component": { "group": "my.group", "module": "mylib", diff --git a/subprojects/docs/src/samples/java-feature-variant/requiring-features-external/repo/org/gradle/demo/producer/1.0/producer-1.0.module b/subprojects/docs/src/samples/java-feature-variant/requiring-features-external/repo/org/gradle/demo/producer/1.0/producer-1.0.module index c895deabe5806..a6f21573f4e08 100644 --- a/subprojects/docs/src/samples/java-feature-variant/requiring-features-external/repo/org/gradle/demo/producer/1.0/producer-1.0.module +++ b/subprojects/docs/src/samples/java-feature-variant/requiring-features-external/repo/org/gradle/demo/producer/1.0/producer-1.0.module @@ -1,5 +1,5 @@ { - "formatVersion": "0.4", + "formatVersion": "1.0", "component": { "group": "org.gradle.demo", "module": "producer", diff --git a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/GradleModuleMetadata.groovy b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/GradleModuleMetadata.groovy index 273ec9ba0a380..45ebe7e9d6fdc 100644 --- a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/GradleModuleMetadata.groovy +++ b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/GradleModuleMetadata.groovy @@ -35,7 +35,7 @@ class GradleModuleMetadata { JsonReader reader = new JsonReader(r) values = readObject(reader) } - assert values.formatVersion == '0.4' + assert values.formatVersion == '1.0' assert values.createdBy.gradle.version == GradleVersion.current().version assert values.createdBy.gradle.buildId variants = (values.variants ?: []).collect { new Variant(it.name, it) } From 2c1ba38da5b4a229765ca3cf17ec5e8c9c895558 Mon Sep 17 00:00:00 2001 From: Cedric Champeau Date: Mon, 18 Feb 2019 10:10:41 +0100 Subject: [PATCH 104/853] Add missing value type --- .../src/docs/design/gradle-module-metadata-1.0-specification.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subprojects/docs/src/docs/design/gradle-module-metadata-1.0-specification.md b/subprojects/docs/src/docs/design/gradle-module-metadata-1.0-specification.md index 1d51f2dce010d..f94eb3de4e1ea 100644 --- a/subprojects/docs/src/docs/design/gradle-module-metadata-1.0-specification.md +++ b/subprojects/docs/src/docs/design/gradle-module-metadata-1.0-specification.md @@ -90,7 +90,7 @@ This value must contain an array of 0 or more capabilities. Each capability is a #### Java Ecosystem specific attributes - `org.gradle.dependency.bundling` indicates how dependencies of the variant are bundled. Either externally, embedded or shadowed. See the `org.gradle.api.attributes.java.Bundling` for more details. Value must be a string. -- `org.gradle.component.category` indicates the type of component (library or platform). This attribute is mostly used to disambiguate Maven POM files derived either as a platform or a library. +- `org.gradle.component.category` indicates the type of component (library or platform). This attribute is mostly used to disambiguate Maven POM files derived either as a platform or a library. Value must be a string. #### Native ecosystem specific attributes From 56d888eaf1a85330a394c11d92a40388aa3a7fdb Mon Sep 17 00:00:00 2001 From: Cedric Champeau Date: Wed, 20 Feb 2019 09:04:32 +0100 Subject: [PATCH 105/853] Rename writer/parser classes for consistency --- ...leMetadataResolutionIntegrationTest.groovy | 2 +- ...leMetadataResolutionIntegrationTest.groovy | 2 +- .../DefaultDependencyManagementServices.java | 4 ++-- ...r.java => GradleModuleMetadataParser.java} | 4 ++-- .../DefaultBaseRepositoryFactory.java | 6 ++--- .../DefaultIvyArtifactRepository.java | 6 ++--- .../DefaultMavenArtifactRepository.java | 10 ++++----- .../DefaultMavenLocalArtifactRepository.java | 4 ++-- .../DefaultGradleModuleMetadataSource.java | 6 ++--- ... => GradleModuleMetadataParserTest.groovy} | 4 ++-- .../ModuleMetadataSerializerTest.groovy | 8 +++---- .../DefaultBaseRepositoryFactoryTest.groovy | 4 ++-- .../DefaultIvyArtifactRepositoryTest.groovy | 4 ++-- .../DefaultMavenArtifactRepositoryTest.groovy | 4 ++-- .../DefaultMavenLocalRepositoryTest.groovy | 4 ++-- .../gradle/GradleFileModuleAdapter.groovy | 4 ++-- ...r.java => GradleModuleMetadataWriter.java} | 10 ++++----- .../publish/tasks/GenerateModuleMetadata.java | 4 ++-- .../ModuleMetadataFileGeneratorTest.groovy | 22 +++++++++---------- 19 files changed, 56 insertions(+), 56 deletions(-) rename subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/parser/{ModuleMetadataParser.java => GradleModuleMetadataParser.java} (98%) rename subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/parser/{ModuleMetadataParserTest.groovy => GradleModuleMetadataParserTest.groovy} (99%) rename subprojects/publish/src/main/java/org/gradle/api/publish/internal/{ModuleMetadataFileGenerator.java => GradleModuleMetadataWriter.java} (98%) diff --git a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/maven/MavenLocalDependencyWithGradleMetadataResolutionIntegrationTest.groovy b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/maven/MavenLocalDependencyWithGradleMetadataResolutionIntegrationTest.groovy index 066db41a4368d..3d165c4d22c9c 100644 --- a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/maven/MavenLocalDependencyWithGradleMetadataResolutionIntegrationTest.groovy +++ b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/maven/MavenLocalDependencyWithGradleMetadataResolutionIntegrationTest.groovy @@ -20,7 +20,7 @@ import org.gradle.integtests.fixtures.AbstractDependencyResolutionTest import org.gradle.integtests.fixtures.FeaturePreviewsFixture import org.gradle.integtests.fixtures.resolve.ResolveTestFixture -import static org.gradle.api.internal.artifacts.ivyservice.ivyresolve.parser.ModuleMetadataParser.FORMAT_VERSION +import static org.gradle.api.internal.artifacts.ivyservice.ivyresolve.parser.GradleModuleMetadataParser.FORMAT_VERSION class MavenLocalDependencyWithGradleMetadataResolutionIntegrationTest extends AbstractDependencyResolutionTest { def resolve = new ResolveTestFixture(buildFile) diff --git a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/maven/MavenRemoteDependencyWithGradleMetadataResolutionIntegrationTest.groovy b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/maven/MavenRemoteDependencyWithGradleMetadataResolutionIntegrationTest.groovy index 61486537a7d2d..c864c62ae7d75 100644 --- a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/maven/MavenRemoteDependencyWithGradleMetadataResolutionIntegrationTest.groovy +++ b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/maven/MavenRemoteDependencyWithGradleMetadataResolutionIntegrationTest.groovy @@ -21,7 +21,7 @@ import org.gradle.integtests.fixtures.FeaturePreviewsFixture import org.gradle.integtests.fixtures.resolve.ResolveTestFixture import spock.lang.Unroll -import static org.gradle.api.internal.artifacts.ivyservice.ivyresolve.parser.ModuleMetadataParser.FORMAT_VERSION +import static org.gradle.api.internal.artifacts.ivyservice.ivyresolve.parser.GradleModuleMetadataParser.FORMAT_VERSION class MavenRemoteDependencyWithGradleMetadataResolutionIntegrationTest extends AbstractHttpDependencyResolutionTest { def resolve = new ResolveTestFixture(buildFile).expectDefaultConfiguration("runtime") diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/DefaultDependencyManagementServices.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/DefaultDependencyManagementServices.java index e5ce970e27f56..a701efd7068c0 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/DefaultDependencyManagementServices.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/DefaultDependencyManagementServices.java @@ -54,7 +54,7 @@ import org.gradle.api.internal.artifacts.ivyservice.dependencysubstitution.DependencySubstitutionRules; import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.ResolveIvyFactory; import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.parser.GradlePomModuleDescriptorParser; -import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.parser.ModuleMetadataParser; +import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.parser.GradleModuleMetadataParser; import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.strategy.VersionSelectorScheme; import org.gradle.api.internal.artifacts.ivyservice.moduleconverter.LocalComponentMetadataBuilder; import org.gradle.api.internal.artifacts.ivyservice.moduleconverter.dependencies.LocalConfigurationMetadataBuilder; @@ -332,7 +332,7 @@ BaseRepositoryFactory createBaseRepositoryFactory(LocalMavenRepositoryLocator lo artifactIdentifierFileStore, externalResourceFileStore, new GradlePomModuleDescriptorParser(versionSelectorScheme, moduleIdentifierFactory, fileResourceRepository, metadataFactory), - new ModuleMetadataParser(attributesFactory, moduleIdentifierFactory, NamedObjectInstantiator.INSTANCE), + new GradleModuleMetadataParser(attributesFactory, moduleIdentifierFactory, NamedObjectInstantiator.INSTANCE), authenticationSchemeRegistry, ivyContextManager, moduleIdentifierFactory, diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/parser/ModuleMetadataParser.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/parser/GradleModuleMetadataParser.java similarity index 98% rename from subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/parser/ModuleMetadataParser.java rename to subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/parser/GradleModuleMetadataParser.java index afab83b7eaad5..bd3e20eef596b 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/parser/ModuleMetadataParser.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/parser/GradleModuleMetadataParser.java @@ -54,13 +54,13 @@ import static com.google.gson.stream.JsonToken.NUMBER; import static org.apache.commons.lang.StringUtils.capitalize; -public class ModuleMetadataParser { +public class GradleModuleMetadataParser { public static final String FORMAT_VERSION = "1.0"; private final ImmutableAttributesFactory attributesFactory; private final NamedObjectInstantiator instantiator; private final ExcludeRuleConverter excludeRuleConverter; - public ModuleMetadataParser(ImmutableAttributesFactory attributesFactory, ImmutableModuleIdentifierFactory moduleIdentifierFactory, NamedObjectInstantiator instantiator) { + public GradleModuleMetadataParser(ImmutableAttributesFactory attributesFactory, ImmutableModuleIdentifierFactory moduleIdentifierFactory, NamedObjectInstantiator instantiator) { this.attributesFactory = attributesFactory; this.instantiator = instantiator; this.excludeRuleConverter = new DefaultExcludeRuleConverter(moduleIdentifierFactory); diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/repositories/DefaultBaseRepositoryFactory.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/repositories/DefaultBaseRepositoryFactory.java index 0ee2506cd73e3..3a04ec35b316c 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/repositories/DefaultBaseRepositoryFactory.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/repositories/DefaultBaseRepositoryFactory.java @@ -32,7 +32,7 @@ import org.gradle.api.internal.artifacts.dsl.DefaultRepositoryHandler; import org.gradle.api.internal.artifacts.ivyservice.IvyContextManager; import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.parser.MetaDataParser; -import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.parser.ModuleMetadataParser; +import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.parser.GradleModuleMetadataParser; import org.gradle.api.internal.artifacts.mvnsettings.LocalMavenRepositoryLocator; import org.gradle.api.internal.artifacts.repositories.metadata.IvyMutableModuleMetadataFactory; import org.gradle.api.internal.artifacts.repositories.metadata.MavenMutableModuleMetadataFactory; @@ -64,7 +64,7 @@ public class DefaultBaseRepositoryFactory implements BaseRepositoryFactory { private final FileStore artifactFileStore; private final FileStore externalResourcesFileStore; private final MetaDataParser pomParser; - private final ModuleMetadataParser metadataParser; + private final GradleModuleMetadataParser metadataParser; private final AuthenticationSchemeRegistry authenticationSchemeRegistry; private final IvyContextManager ivyContextManager; private final ImmutableModuleIdentifierFactory moduleIdentifierFactory; @@ -84,7 +84,7 @@ public DefaultBaseRepositoryFactory(LocalMavenRepositoryLocator localMavenReposi FileStore artifactFileStore, FileStore externalResourcesFileStore, MetaDataParser pomParser, - ModuleMetadataParser metadataParser, + GradleModuleMetadataParser metadataParser, AuthenticationSchemeRegistry authenticationSchemeRegistry, IvyContextManager ivyContextManager, ImmutableModuleIdentifierFactory moduleIdentifierFactory, diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/repositories/DefaultIvyArtifactRepository.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/repositories/DefaultIvyArtifactRepository.java index edeafbc67476d..61ab0cc301e2e 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/repositories/DefaultIvyArtifactRepository.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/repositories/DefaultIvyArtifactRepository.java @@ -39,7 +39,7 @@ import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.parser.IvyModuleDescriptorConverter; import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.parser.IvyXmlModuleDescriptorParser; import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.parser.MetaDataParser; -import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.parser.ModuleMetadataParser; +import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.parser.GradleModuleMetadataParser; import org.gradle.api.internal.artifacts.repositories.descriptor.IvyRepositoryDescriptor; import org.gradle.api.internal.artifacts.repositories.descriptor.RepositoryDescriptor; import org.gradle.api.internal.artifacts.repositories.layout.AbstractRepositoryLayout; @@ -98,7 +98,7 @@ public class DefaultIvyArtifactRepository extends AbstractAuthenticationSupporte private final ImmutableModuleIdentifierFactory moduleIdentifierFactory; private final InstantiatorFactory instantiatorFactory; private final FileResourceRepository fileResourceRepository; - private final ModuleMetadataParser moduleMetadataParser; + private final GradleModuleMetadataParser moduleMetadataParser; private final IvyMutableModuleMetadataFactory metadataFactory; private final IsolatableFactory isolatableFactory; private final IvyMetadataSources metadataSources = new IvyMetadataSources(); @@ -112,7 +112,7 @@ public DefaultIvyArtifactRepository(FileResolver fileResolver, RepositoryTranspo ImmutableModuleIdentifierFactory moduleIdentifierFactory, InstantiatorFactory instantiatorFactory, FileResourceRepository fileResourceRepository, - ModuleMetadataParser moduleMetadataParser, + GradleModuleMetadataParser moduleMetadataParser, FeaturePreviews featurePreviews, IvyMutableModuleMetadataFactory metadataFactory, IsolatableFactory isolatableFactory, diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/repositories/DefaultMavenArtifactRepository.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/repositories/DefaultMavenArtifactRepository.java index 7d4bf27e01170..232f5e1feafb1 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/repositories/DefaultMavenArtifactRepository.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/repositories/DefaultMavenArtifactRepository.java @@ -33,7 +33,7 @@ import org.gradle.api.internal.artifacts.ModuleVersionPublisher; import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.ConfiguredModuleComponentRepository; import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.parser.MetaDataParser; -import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.parser.ModuleMetadataParser; +import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.parser.GradleModuleMetadataParser; import org.gradle.api.internal.artifacts.repositories.descriptor.MavenRepositoryDescriptor; import org.gradle.api.internal.artifacts.repositories.descriptor.RepositoryDescriptor; import org.gradle.api.internal.artifacts.repositories.maven.MavenMetadataLoader; @@ -86,7 +86,7 @@ public boolean isUsableModule(String repoName, MutableMavenModuleResolveMetadata private final LocallyAvailableResourceFinder locallyAvailableResourceFinder; private final FileStore artifactFileStore; private final MetaDataParser pomParser; - private final ModuleMetadataParser metadataParser; + private final GradleModuleMetadataParser metadataParser; private final ImmutableModuleIdentifierFactory moduleIdentifierFactory; private final FileStore resourcesFileStore; private final FileResourceRepository fileResourceRepository; @@ -100,7 +100,7 @@ public DefaultMavenArtifactRepository(FileResolver fileResolver, RepositoryTrans InstantiatorFactory instantiatorFactory, FileStore artifactFileStore, MetaDataParser pomParser, - ModuleMetadataParser metadataParser, + GradleModuleMetadataParser metadataParser, AuthenticationContainer authenticationContainer, ImmutableModuleIdentifierFactory moduleIdentifierFactory, FileStore resourcesFileStore, @@ -120,7 +120,7 @@ public DefaultMavenArtifactRepository(Transformer artifactFileStore, MetaDataParser pomParser, - ModuleMetadataParser metadataParser, + GradleModuleMetadataParser metadataParser, AuthenticationContainer authenticationContainer, ImmutableModuleIdentifierFactory moduleIdentifierFactory, FileStore resourcesFileStore, @@ -273,7 +273,7 @@ private MetaDataParser getPomParser() { return pomParser; } - private ModuleMetadataParser getMetadataParser() { + private GradleModuleMetadataParser getMetadataParser() { return metadataParser; } diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/repositories/DefaultMavenLocalArtifactRepository.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/repositories/DefaultMavenLocalArtifactRepository.java index b523cf1209d11..633cedaecd38c 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/repositories/DefaultMavenLocalArtifactRepository.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/repositories/DefaultMavenLocalArtifactRepository.java @@ -22,7 +22,7 @@ import org.gradle.internal.instantiation.InstantiatorFactory; import org.gradle.api.internal.artifacts.ImmutableModuleIdentifierFactory; import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.parser.MetaDataParser; -import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.parser.ModuleMetadataParser; +import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.parser.GradleModuleMetadataParser; import org.gradle.api.internal.artifacts.repositories.maven.MavenMetadataLoader; import org.gradle.api.internal.artifacts.repositories.metadata.DefaultMavenPomMetadataSource; import org.gradle.api.internal.artifacts.repositories.metadata.MavenMetadataArtifactProvider; @@ -56,7 +56,7 @@ public DefaultMavenLocalArtifactRepository(FileResolver fileResolver, Repository LocallyAvailableResourceFinder locallyAvailableResourceFinder, InstantiatorFactory instantiatorFactory, FileStore artifactFileStore, MetaDataParser pomParser, - ModuleMetadataParser metadataParser, + GradleModuleMetadataParser metadataParser, AuthenticationContainer authenticationContainer, ImmutableModuleIdentifierFactory moduleIdentifierFactory, FileResourceRepository fileResourceRepository, diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/repositories/metadata/DefaultGradleModuleMetadataSource.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/repositories/metadata/DefaultGradleModuleMetadataSource.java index 06bed095f3209..b20815bc9aac9 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/repositories/metadata/DefaultGradleModuleMetadataSource.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/repositories/metadata/DefaultGradleModuleMetadataSource.java @@ -18,7 +18,7 @@ import org.gradle.api.artifacts.ModuleIdentifier; import org.gradle.api.artifacts.component.ModuleComponentIdentifier; import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.ComponentResolvers; -import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.parser.ModuleMetadataParser; +import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.parser.GradleModuleMetadataParser; import org.gradle.api.internal.artifacts.repositories.resolver.ExternalResourceArtifactResolver; import org.gradle.api.internal.artifacts.repositories.resolver.ResourcePattern; import org.gradle.api.internal.artifacts.repositories.resolver.VersionLister; @@ -40,12 +40,12 @@ * Because of this, we will generate an empty instance (either a Ivy or Maven) based on the repository type. */ public class DefaultGradleModuleMetadataSource extends AbstractMetadataSource { - private final ModuleMetadataParser metadataParser; + private final GradleModuleMetadataParser metadataParser; private final MutableModuleMetadataFactory mutableModuleMetadataFactory; private final boolean listVersions; @Inject - public DefaultGradleModuleMetadataSource(ModuleMetadataParser metadataParser, MutableModuleMetadataFactory mutableModuleMetadataFactory, boolean listVersions) { + public DefaultGradleModuleMetadataSource(GradleModuleMetadataParser metadataParser, MutableModuleMetadataFactory mutableModuleMetadataFactory, boolean listVersions) { this.metadataParser = metadataParser; this.mutableModuleMetadataFactory = mutableModuleMetadataFactory; this.listVersions = listVersions; diff --git a/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/parser/ModuleMetadataParserTest.groovy b/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/parser/GradleModuleMetadataParserTest.groovy similarity index 99% rename from subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/parser/ModuleMetadataParserTest.groovy rename to subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/parser/GradleModuleMetadataParserTest.groovy index d526ce267e405..0e4b80bcca54d 100644 --- a/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/parser/ModuleMetadataParserTest.groovy +++ b/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/parser/GradleModuleMetadataParserTest.groovy @@ -34,12 +34,12 @@ import spock.lang.Specification import static org.gradle.util.AttributeTestUtil.attributes -class ModuleMetadataParserTest extends Specification { +class GradleModuleMetadataParserTest extends Specification { @Rule final TestNameTestDirectoryProvider temporaryFolder = new TestNameTestDirectoryProvider() def identifierFactory = new DefaultImmutableModuleIdentifierFactory() - def parser = new ModuleMetadataParser(AttributeTestUtil.attributesFactory(), identifierFactory, NamedObjectInstantiator.INSTANCE) + def parser = new GradleModuleMetadataParser(AttributeTestUtil.attributesFactory(), identifierFactory, NamedObjectInstantiator.INSTANCE) VersionConstraint emptyConstraint() { DefaultImmutableVersionConstraint.of() diff --git a/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/modulecache/ModuleMetadataSerializerTest.groovy b/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/modulecache/ModuleMetadataSerializerTest.groovy index dcda90a665728..6f5db2e676290 100644 --- a/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/modulecache/ModuleMetadataSerializerTest.groovy +++ b/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/modulecache/ModuleMetadataSerializerTest.groovy @@ -26,7 +26,7 @@ import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.parser.GradlePomM import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.parser.IvyModuleDescriptorConverter import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.parser.IvyXmlModuleDescriptorParser import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.parser.MetaDataParser -import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.parser.ModuleMetadataParser +import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.parser.GradleModuleMetadataParser import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.strategy.DefaultVersionComparator import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.strategy.DefaultVersionSelectorScheme import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.strategy.MavenVersionSelectorScheme @@ -59,7 +59,7 @@ class ModuleMetadataSerializerTest extends Specification { private final ModuleMetadataSerializer serializer = moduleMetadataSerializer() private GradlePomModuleDescriptorParser pomModuleDescriptorParser = pomParser() private MetaDataParser ivyDescriptorParser = ivyParser() - private ModuleMetadataParser gradleMetadataParser = gradleMetadataParser() + private GradleModuleMetadataParser gradleMetadataParser = gradleMetadataParser() def "all samples are different"() { given: @@ -175,8 +175,8 @@ class ModuleMetadataSerializerTest extends Specification { ) } - private ModuleMetadataParser gradleMetadataParser() { - new ModuleMetadataParser( + private GradleModuleMetadataParser gradleMetadataParser() { + new GradleModuleMetadataParser( AttributeTestUtil.attributesFactory(), moduleIdentifierFactory, NamedObjectInstantiator.INSTANCE diff --git a/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/repositories/DefaultBaseRepositoryFactoryTest.groovy b/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/repositories/DefaultBaseRepositoryFactoryTest.groovy index 4392a42bd1a66..4cffd37084523 100644 --- a/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/repositories/DefaultBaseRepositoryFactoryTest.groovy +++ b/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/repositories/DefaultBaseRepositoryFactoryTest.groovy @@ -22,7 +22,7 @@ import org.gradle.api.internal.artifacts.ImmutableModuleIdentifierFactory import org.gradle.api.internal.artifacts.dsl.DefaultRepositoryHandler import org.gradle.api.internal.artifacts.ivyservice.IvyContextManager import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.parser.MetaDataParser -import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.parser.ModuleMetadataParser +import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.parser.GradleModuleMetadataParser import org.gradle.api.internal.artifacts.mvnsettings.LocalMavenRepositoryLocator import org.gradle.api.internal.artifacts.repositories.metadata.IvyMutableModuleMetadataFactory import org.gradle.api.internal.artifacts.repositories.metadata.MavenMutableModuleMetadataFactory @@ -50,7 +50,7 @@ class DefaultBaseRepositoryFactoryTest extends Specification { final ArtifactIdentifierFileStore artifactIdentifierFileStore = Stub() final ExternalResourceFileStore externalResourceFileStore = Stub() final MetaDataParser pomParser = Mock() - final ModuleMetadataParser metadataParser = Mock() + final GradleModuleMetadataParser metadataParser = Mock() final ivyContextManager = Mock(IvyContextManager) final AuthenticationSchemeRegistry authenticationSchemeRegistry = new DefaultAuthenticationSchemeRegistry() final ImmutableModuleIdentifierFactory moduleIdentifierFactory = Mock() diff --git a/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/repositories/DefaultIvyArtifactRepositoryTest.groovy b/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/repositories/DefaultIvyArtifactRepositoryTest.groovy index 0780b344f27fd..2429bffa989e7 100644 --- a/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/repositories/DefaultIvyArtifactRepositoryTest.groovy +++ b/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/repositories/DefaultIvyArtifactRepositoryTest.groovy @@ -24,7 +24,7 @@ import org.gradle.api.artifacts.repositories.AuthenticationContainer import org.gradle.api.internal.artifacts.DefaultImmutableModuleIdentifierFactory import org.gradle.api.internal.artifacts.ImmutableModuleIdentifierFactory import org.gradle.api.internal.artifacts.ivyservice.IvyContextManager -import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.parser.ModuleMetadataParser +import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.parser.GradleModuleMetadataParser import org.gradle.api.internal.artifacts.repositories.metadata.IvyMutableModuleMetadataFactory import org.gradle.api.internal.artifacts.repositories.resolver.IvyResolver import org.gradle.api.internal.artifacts.repositories.transport.RepositoryTransport @@ -58,7 +58,7 @@ class DefaultIvyArtifactRepositoryTest extends Specification { final AuthenticationContainer authenticationContainer = Stub() final ivyContextManager = Mock(IvyContextManager) final ImmutableModuleIdentifierFactory moduleIdentifierFactory = Mock() - final ModuleMetadataParser moduleMetadataParser = new ModuleMetadataParser(Mock(ImmutableAttributesFactory), moduleIdentifierFactory, Mock(NamedObjectInstantiator)) + final GradleModuleMetadataParser moduleMetadataParser = new GradleModuleMetadataParser(Mock(ImmutableAttributesFactory), moduleIdentifierFactory, Mock(NamedObjectInstantiator)) final IvyMutableModuleMetadataFactory metadataFactory = new IvyMutableModuleMetadataFactory(new DefaultImmutableModuleIdentifierFactory(), AttributeTestUtil.attributesFactory()) final DefaultIvyArtifactRepository repository = instantiator.newInstance(DefaultIvyArtifactRepository.class, fileResolver, transportFactory, locallyAvailableResourceFinder, artifactIdentifierFileStore, externalResourceFileStore, authenticationContainer, ivyContextManager, moduleIdentifierFactory, TestUtil.instantiatorFactory(), Mock(FileResourceRepository), moduleMetadataParser, TestUtil.featurePreviews(), metadataFactory, SnapshotTestUtil.valueSnapshotter(), Mock(ObjectFactory)) diff --git a/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/repositories/DefaultMavenArtifactRepositoryTest.groovy b/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/repositories/DefaultMavenArtifactRepositoryTest.groovy index bfb2c9058b93a..da1d75037ea8a 100644 --- a/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/repositories/DefaultMavenArtifactRepositoryTest.groovy +++ b/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/repositories/DefaultMavenArtifactRepositoryTest.groovy @@ -23,7 +23,7 @@ import org.gradle.api.artifacts.ComponentMetadataVersionLister import org.gradle.api.artifacts.repositories.AuthenticationContainer import org.gradle.api.internal.artifacts.ImmutableModuleIdentifierFactory import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.parser.MetaDataParser -import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.parser.ModuleMetadataParser +import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.parser.GradleModuleMetadataParser import org.gradle.api.internal.artifacts.repositories.metadata.MavenMutableModuleMetadataFactory import org.gradle.api.internal.artifacts.repositories.resolver.MavenResolver import org.gradle.api.internal.artifacts.repositories.transport.RepositoryTransport @@ -50,7 +50,7 @@ class DefaultMavenArtifactRepositoryTest extends Specification { final ArtifactIdentifierFileStore artifactIdentifierFileStore = Stub() final ExternalResourceFileStore externalResourceFileStore = Stub() final MetaDataParser pomParser = Stub() - final ModuleMetadataParser metadataParser = Stub() + final GradleModuleMetadataParser metadataParser = Stub() final AuthenticationContainer authenticationContainer = Stub() final ImmutableModuleIdentifierFactory moduleIdentifierFactory = Stub() final MavenMutableModuleMetadataFactory mavenMetadataFactory = new MavenMutableModuleMetadataFactory(moduleIdentifierFactory, AttributeTestUtil.attributesFactory(), TestUtil.objectInstantiator(), TestUtil.featurePreviews()) diff --git a/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/repositories/DefaultMavenLocalRepositoryTest.groovy b/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/repositories/DefaultMavenLocalRepositoryTest.groovy index ec6e7efc4a668..b57920c3b0822 100644 --- a/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/repositories/DefaultMavenLocalRepositoryTest.groovy +++ b/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/repositories/DefaultMavenLocalRepositoryTest.groovy @@ -18,7 +18,7 @@ package org.gradle.api.internal.artifacts.repositories import org.gradle.api.artifacts.repositories.AuthenticationContainer import org.gradle.api.internal.artifacts.ImmutableModuleIdentifierFactory import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.parser.MetaDataParser -import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.parser.ModuleMetadataParser +import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.parser.GradleModuleMetadataParser import org.gradle.api.internal.artifacts.repositories.metadata.MavenMutableModuleMetadataFactory import org.gradle.api.internal.artifacts.repositories.transport.RepositoryTransport import org.gradle.api.internal.artifacts.repositories.transport.RepositoryTransportFactory @@ -41,7 +41,7 @@ class DefaultMavenLocalRepositoryTest extends Specification { final ExternalResourceRepository resourceRepository = Mock() final ArtifactIdentifierFileStore artifactIdentifierFileStore = Stub() final MetaDataParser pomParser = Stub() - final ModuleMetadataParser metadataParser = Stub() + final GradleModuleMetadataParser metadataParser = Stub() final AuthenticationContainer authenticationContainer = Stub() final ImmutableModuleIdentifierFactory moduleIdentifierFactory = Mock() final MavenMutableModuleMetadataFactory mavenMetadataFactory = new MavenMutableModuleMetadataFactory(moduleIdentifierFactory, AttributeTestUtil.attributesFactory(), TestUtil.objectInstantiator(), TestUtil.featurePreviews()) diff --git a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/gradle/GradleFileModuleAdapter.groovy b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/gradle/GradleFileModuleAdapter.groovy index 96c3fbb7f11cf..c0a2ec0ada627 100644 --- a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/gradle/GradleFileModuleAdapter.groovy +++ b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/gradle/GradleFileModuleAdapter.groovy @@ -17,7 +17,7 @@ package org.gradle.test.fixtures.gradle import groovy.json.JsonBuilder -import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.parser.ModuleMetadataParser +import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.parser.GradleModuleMetadataParser import org.gradle.test.fixtures.file.TestFile class GradleFileModuleAdapter { @@ -40,7 +40,7 @@ class GradleFileModuleAdapter { def file = moduleDir.file("$module-${version}.module") def jsonBuilder = new JsonBuilder() jsonBuilder { - formatVersion ModuleMetadataParser.FORMAT_VERSION + formatVersion GradleModuleMetadataParser.FORMAT_VERSION builtBy { gradle { } } diff --git a/subprojects/publish/src/main/java/org/gradle/api/publish/internal/ModuleMetadataFileGenerator.java b/subprojects/publish/src/main/java/org/gradle/api/publish/internal/GradleModuleMetadataWriter.java similarity index 98% rename from subprojects/publish/src/main/java/org/gradle/api/publish/internal/ModuleMetadataFileGenerator.java rename to subprojects/publish/src/main/java/org/gradle/api/publish/internal/GradleModuleMetadataWriter.java index 20ef852de15c9..14e3f5a33dea4 100644 --- a/subprojects/publish/src/main/java/org/gradle/api/publish/internal/ModuleMetadataFileGenerator.java +++ b/subprojects/publish/src/main/java/org/gradle/api/publish/internal/GradleModuleMetadataWriter.java @@ -38,7 +38,7 @@ import org.gradle.api.component.SoftwareComponent; import org.gradle.api.internal.artifacts.DefaultExcludeRule; import org.gradle.api.internal.artifacts.dependencies.DefaultImmutableVersionConstraint; -import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.parser.ModuleMetadataParser; +import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.parser.GradleModuleMetadataParser; import org.gradle.api.internal.artifacts.ivyservice.projectmodule.ProjectDependencyPublicationResolver; import org.gradle.api.internal.attributes.AttributeContainerInternal; import org.gradle.api.internal.attributes.ImmutableAttributes; @@ -69,17 +69,17 @@ *

    Whenever you change this class, make sure you also:

    * *
      - *
    • Update the corresponding {@link ModuleMetadataParser module metadata parser}
    • + *
    • Update the corresponding {@link GradleModuleMetadataParser module metadata parser}
    • *
    • Update the module metadata specification (subprojects/docs/src/docs/design/gradle-module-metadata-specification.md)
    • *
    • Update {@link org.gradle.api.internal.artifacts.ivyservice.modulecache.ModuleMetadataSerializer the module metadata serializer}
    • *
    • Add a sample for the module metadata serializer test, to make sure that serialized metadata is idempotent
    • *
    */ -public class ModuleMetadataFileGenerator { +public class GradleModuleMetadataWriter { private final BuildInvocationScopeId buildInvocationScopeId; private final ProjectDependencyPublicationResolver projectDependencyResolver; - public ModuleMetadataFileGenerator(BuildInvocationScopeId buildInvocationScopeId, ProjectDependencyPublicationResolver projectDependencyResolver) { + public GradleModuleMetadataWriter(BuildInvocationScopeId buildInvocationScopeId, ProjectDependencyPublicationResolver projectDependencyResolver) { this.buildInvocationScopeId = buildInvocationScopeId; this.projectDependencyResolver = projectDependencyResolver; } @@ -257,7 +257,7 @@ private void writeCreator(JsonWriter jsonWriter) throws IOException { private void writeFormat(JsonWriter jsonWriter) throws IOException { jsonWriter.name("formatVersion"); - jsonWriter.value(ModuleMetadataParser.FORMAT_VERSION); + jsonWriter.value(GradleModuleMetadataParser.FORMAT_VERSION); } private void writeVariantHostedInAnotherModule(ModuleVersionIdentifier coordinates, ModuleVersionIdentifier targetCoordinates, UsageContext variant, JsonWriter jsonWriter) throws IOException { diff --git a/subprojects/publish/src/main/java/org/gradle/api/publish/tasks/GenerateModuleMetadata.java b/subprojects/publish/src/main/java/org/gradle/api/publish/tasks/GenerateModuleMetadata.java index aba31839eb3d5..48b54f90fcbe0 100644 --- a/subprojects/publish/src/main/java/org/gradle/api/publish/tasks/GenerateModuleMetadata.java +++ b/subprojects/publish/src/main/java/org/gradle/api/publish/tasks/GenerateModuleMetadata.java @@ -35,7 +35,7 @@ import org.gradle.api.provider.ListProperty; import org.gradle.api.provider.Property; import org.gradle.api.publish.Publication; -import org.gradle.api.publish.internal.ModuleMetadataFileGenerator; +import org.gradle.api.publish.internal.GradleModuleMetadataWriter; import org.gradle.api.publish.internal.PublicationInternal; import org.gradle.api.specs.Spec; import org.gradle.api.specs.Specs; @@ -167,7 +167,7 @@ void run() { try { Writer writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file), "utf8")); try { - new ModuleMetadataFileGenerator(getBuildInvocationScopeId(), getProjectDependencyPublicationResolver()).generateTo(publication, publications, writer); + new GradleModuleMetadataWriter(getBuildInvocationScopeId(), getProjectDependencyPublicationResolver()).generateTo(publication, publications, writer); } finally { writer.close(); } diff --git a/subprojects/publish/src/test/groovy/org/gradle/api/publish/internal/ModuleMetadataFileGeneratorTest.groovy b/subprojects/publish/src/test/groovy/org/gradle/api/publish/internal/ModuleMetadataFileGeneratorTest.groovy index fc8560884fd5d..1e51f1452e903 100644 --- a/subprojects/publish/src/test/groovy/org/gradle/api/publish/internal/ModuleMetadataFileGeneratorTest.groovy +++ b/subprojects/publish/src/test/groovy/org/gradle/api/publish/internal/ModuleMetadataFileGeneratorTest.groovy @@ -28,7 +28,7 @@ import org.gradle.api.component.ComponentWithVariants import org.gradle.api.internal.artifacts.DefaultExcludeRule import org.gradle.api.internal.artifacts.DefaultModuleVersionIdentifier import org.gradle.api.internal.artifacts.dependencies.DefaultImmutableVersionConstraint -import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.parser.ModuleMetadataParser +import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.parser.GradleModuleMetadataParser import org.gradle.api.internal.artifacts.ivyservice.projectmodule.ProjectDependencyPublicationResolver import org.gradle.api.internal.attributes.ImmutableAttributes import org.gradle.api.internal.component.SoftwareComponentInternal @@ -64,7 +64,7 @@ class ModuleMetadataFileGeneratorTest extends Specification { def buildId = UniqueId.generate() def id = DefaultModuleVersionIdentifier.newId("group", "module", "1.2") def projectDependencyResolver = Mock(ProjectDependencyPublicationResolver) - def generator = new ModuleMetadataFileGenerator(new BuildInvocationScopeId(buildId), projectDependencyResolver) + def generator = new GradleModuleMetadataWriter(new BuildInvocationScopeId(buildId), projectDependencyResolver) def "writes file for component with no variants"() { def writer = new StringWriter() @@ -76,7 +76,7 @@ class ModuleMetadataFileGeneratorTest extends Specification { then: writer.toString() == """{ - "formatVersion": "${ModuleMetadataParser.FORMAT_VERSION}", + "formatVersion": "${GradleModuleMetadataParser.FORMAT_VERSION}", "component": { "group": "group", "module": "module", @@ -104,7 +104,7 @@ class ModuleMetadataFileGeneratorTest extends Specification { then: writer.toString() == """{ - "formatVersion": "${ModuleMetadataParser.FORMAT_VERSION}", + "formatVersion": "${GradleModuleMetadataParser.FORMAT_VERSION}", "component": { "group": "group", "module": "module", @@ -162,7 +162,7 @@ class ModuleMetadataFileGeneratorTest extends Specification { then: writer.toString() == """{ - "formatVersion": "${ModuleMetadataParser.FORMAT_VERSION}", + "formatVersion": "${GradleModuleMetadataParser.FORMAT_VERSION}", "component": { "group": "group", "module": "module", @@ -292,7 +292,7 @@ class ModuleMetadataFileGeneratorTest extends Specification { then: writer.toString() == """{ - "formatVersion": "${ModuleMetadataParser.FORMAT_VERSION}", + "formatVersion": "${GradleModuleMetadataParser.FORMAT_VERSION}", "component": { "group": "group", "module": "module", @@ -463,7 +463,7 @@ class ModuleMetadataFileGeneratorTest extends Specification { then: writer.toString() == """{ - "formatVersion": "${ModuleMetadataParser.FORMAT_VERSION}", + "formatVersion": "${GradleModuleMetadataParser.FORMAT_VERSION}", "component": { "group": "group", "module": "module", @@ -559,7 +559,7 @@ class ModuleMetadataFileGeneratorTest extends Specification { then: writer.toString() == """{ - "formatVersion": "${ModuleMetadataParser.FORMAT_VERSION}", + "formatVersion": "${GradleModuleMetadataParser.FORMAT_VERSION}", "component": { "group": "group", "module": "module", @@ -619,7 +619,7 @@ class ModuleMetadataFileGeneratorTest extends Specification { then: writer.toString() == """{ - "formatVersion": "${ModuleMetadataParser.FORMAT_VERSION}", + "formatVersion": "${GradleModuleMetadataParser.FORMAT_VERSION}", "component": { "group": "group", "module": "module", @@ -684,7 +684,7 @@ class ModuleMetadataFileGeneratorTest extends Specification { then: writer.toString() == """{ - "formatVersion": "${ModuleMetadataParser.FORMAT_VERSION}", + "formatVersion": "${GradleModuleMetadataParser.FORMAT_VERSION}", "component": { "url": "../../module/1.2/module-1.2.module", "group": "group", @@ -745,7 +745,7 @@ class ModuleMetadataFileGeneratorTest extends Specification { then: writer.toString() == """{ - "formatVersion": "${ModuleMetadataParser.FORMAT_VERSION}", + "formatVersion": "${GradleModuleMetadataParser.FORMAT_VERSION}", "component": { "group": "group", "module": "module", From 98ddaa7173cd4c29f2fc8b0c74b4a72ea7749d65 Mon Sep 17 00:00:00 2001 From: Cedric Champeau Date: Wed, 20 Feb 2019 09:55:42 +0100 Subject: [PATCH 106/853] Make Gradle metadata parsing lenient to errors This commit makes metadata parsing lenient: if a version is not the expected one, but we still manage to parse something, then we don't fail. However, if parsing fails, we warn that the version found in the metadata file is different from the one we expected. This should give older Gradle versions a chance to parse newer versions of Gradle metadata, especially in case new things are added, that current Gradle doesn't care about. --- .../parser/GradleModuleMetadataParser.java | 21 +- .../parser/MetaDataParseException.java | 4 + .../GradleModuleMetadataParserTest.groovy | 184 +++++++++++------- 3 files changed, 128 insertions(+), 81 deletions(-) diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/parser/GradleModuleMetadataParser.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/parser/GradleModuleMetadataParser.java index bd3e20eef596b..3a16c3f6cf280 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/parser/GradleModuleMetadataParser.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/parser/GradleModuleMetadataParser.java @@ -34,6 +34,8 @@ import org.gradle.api.internal.attributes.ImmutableAttributes; import org.gradle.api.internal.attributes.ImmutableAttributesFactory; import org.gradle.api.internal.model.NamedObjectInstantiator; +import org.gradle.api.logging.Logger; +import org.gradle.api.logging.Logging; import org.gradle.internal.component.external.model.MutableComponentVariant; import org.gradle.internal.component.external.model.MutableModuleComponentResolveMetadata; import org.gradle.internal.component.model.ExcludeMetadata; @@ -41,6 +43,7 @@ import org.gradle.internal.resource.local.LocallyAvailableExternalResource; import org.gradle.internal.snapshot.impl.CoercingStringValueSnapshot; +import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; @@ -55,6 +58,8 @@ import static org.apache.commons.lang.StringUtils.capitalize; public class GradleModuleMetadataParser { + private final static Logger LOGGER = Logging.getLogger(GradleModuleMetadataParser.class); + public static final String FORMAT_VERSION = "1.0"; private final ImmutableAttributesFactory attributesFactory; private final NamedObjectInstantiator instantiator; @@ -70,6 +75,7 @@ public void parse(final LocallyAvailableExternalResource resource, final Mutable resource.withContent(new Transformer() { @Override public Void transform(InputStream inputStream) { + String version = null; try { JsonReader reader = new JsonReader(new InputStreamReader(inputStream, "utf-8")); reader.beginObject(); @@ -83,14 +89,18 @@ public Void transform(InputStream inputStream) { if (reader.peek() != JsonToken.STRING) { throw new RuntimeException("The 'formatVersion' value should have a string value."); } - String version = reader.nextString(); - if (!version.equals(FORMAT_VERSION)) { - throw new RuntimeException(String.format("Unsupported format version '%s' specified in module metadata. This version of Gradle supports format version %s only.", version, FORMAT_VERSION)); - } + version = reader.nextString(); consumeTopLevelElements(reader, metadata); - metadata.setContentHash(HashUtil.createHash(resource.getFile(), "MD5")); + File file = resource.getFile(); + metadata.setContentHash(HashUtil.createHash(file, "MD5")); + if (!FORMAT_VERSION.equals(version)) { + LOGGER.debug("Unrecognized metadata format version '%s' found in '%s'. Parsing succeeded but it may lead to unexpected resolution results. Try upgrading to a newer version of Gradle", version, file); + } return null; } catch (Exception e) { + if (version != null && !FORMAT_VERSION.equals(version)) { + throw new MetaDataParseException("module metadata", resource, String.format("unsupported format version '%s' specified in module metadata. This version of Gradle supports format version %s.", version, FORMAT_VERSION), e); + } throw new MetaDataParseException("module metadata", resource, e); } } @@ -162,7 +172,6 @@ private void consumeVariant(JsonReader reader, MutableModuleComponentResolveMeta } } reader.endObject(); - MutableComponentVariant variant = metadata.addVariant(variantName, attributes); populateVariant(files, dependencies, dependencyConstraints, capabilities, variant); AttributeValue entry = attributes.findEntry(PlatformSupport.COMPONENT_CATEGORY); diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/parser/MetaDataParseException.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/parser/MetaDataParseException.java index f62276111cd47..791330e878f32 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/parser/MetaDataParseException.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/parser/MetaDataParseException.java @@ -29,4 +29,8 @@ public MetaDataParseException(String message) { public MetaDataParseException(String typeName, ExternalResource resource, Throwable cause) { super(String.format("Could not parse %s %s", typeName, resource.getDisplayName()), cause); } + + public MetaDataParseException(String typeName, ExternalResource resource, String details, Throwable cause) { + super(String.format("Could not parse %s %s: %s", typeName, resource.getDisplayName(), details), cause); + } } diff --git a/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/parser/GradleModuleMetadataParserTest.groovy b/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/parser/GradleModuleMetadataParserTest.groovy index 0e4b80bcca54d..16d22b1a15a2e 100644 --- a/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/parser/GradleModuleMetadataParserTest.groovy +++ b/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/parser/GradleModuleMetadataParserTest.groovy @@ -31,10 +31,88 @@ import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider import org.gradle.util.AttributeTestUtil import org.junit.Rule import spock.lang.Specification +import spock.lang.Unroll import static org.gradle.util.AttributeTestUtil.attributes class GradleModuleMetadataParserTest extends Specification { + private static final String UNKNOWN_FILE_VALUES = ''' + { + "formatVersion": "1.0", + "variants": [ + { + "name": "api", + "files": [{ + "name": "file", + "url": "file", + "otherString": "string", + "otherNumber": 123, + "otherBoolean": true, + "otherNull": null, + "otherObject": { "a": 1, "b": "ignore-me", "c": [], "d": { } }, + "otherArray": [ "a", 123, false, [], null, { } ] + }] + } + ] + } +''' + private static final String UNKNOWN_DEPENDENCY_VALUES = ''' + { + "formatVersion": "1.0", + "variants": [ + { + "name": "api", + "dependencies": [{ + "group": "g", + "module": "m", + "version": { "prefers": "v" }, + "excludes": [ + { "group": "g", "otherString": "string", "otherNumber": 123, "otherObject": { "a": 1 } } + ], + "otherString": "string", + "otherNumber": 123, + "otherBoolean": true, + "otherNull": null, + "otherObject": { "a": 1, "b": "ignore-me", "c": [], "d": { } }, + "otherArray": [ "a", 123, false, [], null, { } ] + }] + } + ] + } +''' + private static final String UNKNOWN_VARIANT_VALUES = ''' + { + "formatVersion": "1.0", + "variants": [ + { + "name": "api", + "otherString": "string", + "otherNumber": 123, + "otherBoolean": true, + "otherNull": null, + "otherObject": { "a": 1, "b": "ignore-me", "c": [], "d": { } }, + "otherArray": [ "a", 123, false, [], null, { } ] + } + ] + } +''' + private static final String UNKNOWN_TOP_LEVEL = '''{ + "formatVersion": "1.0", + "otherString": "string", + "otherNumber": 123, + "otherBoolean": true, + "otherNull": null, + "otherObject": { "a": 1, "b": "ignore-me", "c": [], "d": { } }, + "otherArray": [ "a", 123, false, [], null, { } ] + }''' + + private static final Map UNKOWN_DATASET = [ + UNKNOWN_TOP_LEVEL: UNKNOWN_TOP_LEVEL, + UNKNOWN_DEPENDENCY_VALUES: UNKNOWN_DEPENDENCY_VALUES, + UNKNOWN_VARIANT_VALUES: UNKNOWN_VARIANT_VALUES, + UNKNOWN_FILE_VALUES: UNKNOWN_FILE_VALUES + ] + @Rule final TestNameTestDirectoryProvider temporaryFolder = new TestNameTestDirectoryProvider() @@ -54,7 +132,7 @@ class GradleModuleMetadataParserTest extends Specification { } VersionConstraint prefers(String version) { - DefaultImmutableVersionConstraint.of(version,'', '', []) + DefaultImmutableVersionConstraint.of(version, '', '', []) } VersionConstraint strictly(String version) { @@ -268,7 +346,7 @@ class GradleModuleMetadataParserTest extends Specification { 1 * variant1.addDependency("g2", "m2", prefers("v2"), [], null, ImmutableAttributes.EMPTY, []) 1 * variant1.addDependency("g3", "m3", requires("v3"), excludes("gx:mx", "*:*"), null, ImmutableAttributes.EMPTY, []) 1 * metadata.addVariant("runtime", attributes(usage: "runtime", packaging: "zip")) >> variant2 - 1 * variant2.addDependency("g3", "m3", prefers("v3"), [], null, ImmutableAttributes.EMPTY, { it[0].group == 'org' && it[0].name=='foo' && it[0].version=='1.0'}) + 1 * variant2.addDependency("g3", "m3", prefers("v3"), [], null, ImmutableAttributes.EMPTY, { it[0].group == 'org' && it[0].name == 'foo' && it[0].version == '1.0' }) 1 * variant2.addDependency("g4", "m4", strictly("v5"), [], null, ImmutableAttributes.EMPTY, []) 1 * variant2.addDependency("g5", "m5", prefersAndRejects("v5", ["v6", "v7"]), [], null, ImmutableAttributes.EMPTY, []) 1 * variant2.addDependency("g6", "m6", strictly("v6"), [], "v5 is buggy", ImmutableAttributes.EMPTY, []) @@ -521,15 +599,7 @@ class GradleModuleMetadataParserTest extends Specification { def metadata = Mock(MutableModuleComponentResolveMetadata) when: - parser.parse(resource('''{ - "formatVersion": "1.0", - "otherString": "string", - "otherNumber": 123, - "otherBoolean": true, - "otherNull": null, - "otherObject": { "a": 1, "b": "ignore-me", "c": [], "d": { } }, - "otherArray": [ "a", 123, false, [], null, { } ] - }'''), metadata) + parser.parse(resource(UNKNOWN_TOP_LEVEL), metadata) then: 1 * metadata.setContentHash(_) @@ -540,22 +610,7 @@ class GradleModuleMetadataParserTest extends Specification { def metadata = Mock(MutableModuleComponentResolveMetadata) when: - parser.parse(resource(''' - { - "formatVersion": "1.0", - "variants": [ - { - "name": "api", - "otherString": "string", - "otherNumber": 123, - "otherBoolean": true, - "otherNull": null, - "otherObject": { "a": 1, "b": "ignore-me", "c": [], "d": { } }, - "otherArray": [ "a", 123, false, [], null, { } ] - } - ] - } -'''), metadata) + parser.parse(resource(UNKNOWN_VARIANT_VALUES), metadata) then: 1 * metadata.addVariant("api", attributes([:])) @@ -568,26 +623,7 @@ class GradleModuleMetadataParserTest extends Specification { def variant = Mock(MutableComponentVariant) when: - parser.parse(resource(''' - { - "formatVersion": "1.0", - "variants": [ - { - "name": "api", - "files": [{ - "name": "file", - "url": "file", - "otherString": "string", - "otherNumber": 123, - "otherBoolean": true, - "otherNull": null, - "otherObject": { "a": 1, "b": "ignore-me", "c": [], "d": { } }, - "otherArray": [ "a", 123, false, [], null, { } ] - }] - } - ] - } -'''), metadata) + parser.parse(resource(UNKNOWN_FILE_VALUES), metadata) then: 1 * metadata.addVariant("api", attributes([:])) >> variant @@ -600,30 +636,7 @@ class GradleModuleMetadataParserTest extends Specification { def variant = Mock(MutableComponentVariant) when: - parser.parse(resource(''' - { - "formatVersion": "1.0", - "variants": [ - { - "name": "api", - "dependencies": [{ - "group": "g", - "module": "m", - "version": { "prefers": "v" }, - "excludes": [ - { "group": "g", "otherString": "string", "otherNumber": 123, "otherObject": { "a": 1 } } - ], - "otherString": "string", - "otherNumber": 123, - "otherBoolean": true, - "otherNull": null, - "otherObject": { "a": 1, "b": "ignore-me", "c": [], "d": { } }, - "otherArray": [ "a", 123, false, [], null, { } ] - }] - } - ] - } -'''), metadata) + parser.parse(resource(UNKNOWN_DEPENDENCY_VALUES), metadata) then: 1 * metadata.addVariant("api", attributes([:])) >> variant @@ -676,16 +689,37 @@ class GradleModuleMetadataParserTest extends Specification { e.cause.message == "The 'formatVersion' value should have a string value." } - def "fails on unsupported format version"() { + def "fails on unsupported format version if json parsing fails and metadata format is not the expected one"() { def metadata = Mock(MutableModuleComponentResolveMetadata) when: - parser.parse(resource('{ "formatVersion": "123.4" }'), metadata) + parser.parse(resource('{ "formatVersion": "123.4", "variants": {} }'), metadata) then: def e = thrown(MetaDataParseException) - e.message == "Could not parse module metadata " - e.cause.message == "Unsupported format version '123.4' specified in module metadata. This version of Gradle supports format version 1.0 only." + e.message == "Could not parse module metadata : unsupported format version '123.4' specified in module metadata. This version of Gradle supports format version 1.0." + e.cause.message == "Expected BEGIN_ARRAY but was BEGIN_OBJECT at line 1 column 42 path \$.variants" + } + + @Unroll + def "is lenient with version checks if we manage to parse content (#label, version = #version)"() { + def metadata = Mock(MutableModuleComponentResolveMetadata) { + addVariant(_, _) >> Stub(MutableComponentVariant) + } + + when: + parser.parse(resource(replaceMetadataVersion(json, version)), metadata) + + then: + 1 * metadata.setContentHash(_) + + where: + [json, version] << [UNKOWN_DATASET.values(), ['0.4', '1.1', '1.5', '123.4']].combinations() + label = UNKOWN_DATASET.entrySet().find { it.value == json }.key + } + + String replaceMetadataVersion(String json, String metadataVersion) { + json.replace('"formatVersion": "1.0"', '"formatVersion": "' + metadataVersion + '"') } def resource(String content) { From 08cacc5424e4201a5a01861942736cf5325abcb4 Mon Sep 17 00:00:00 2001 From: Cedric Champeau Date: Wed, 20 Feb 2019 12:12:11 +0100 Subject: [PATCH 107/853] Add cross-version Gradle metadata parsing test This test makes sure that current Gradle can consume previous version Gradle metadata, and opposite. Currently the test shows that current can consume 0.4 format, but the opposite is not true. --- ...aLibraryCrossVersionIntegrationTest.groovy | 116 ++++++++++++++++++ .../internal/DefaultJavaFeatureSpec.java | 4 + 2 files changed, 120 insertions(+) create mode 100644 subprojects/dependency-management/src/crossVersionTest/groovy/org/gradle/integtests/resolve/GradleMetadataJavaLibraryCrossVersionIntegrationTest.groovy diff --git a/subprojects/dependency-management/src/crossVersionTest/groovy/org/gradle/integtests/resolve/GradleMetadataJavaLibraryCrossVersionIntegrationTest.groovy b/subprojects/dependency-management/src/crossVersionTest/groovy/org/gradle/integtests/resolve/GradleMetadataJavaLibraryCrossVersionIntegrationTest.groovy new file mode 100644 index 0000000000000..b15c0627218b7 --- /dev/null +++ b/subprojects/dependency-management/src/crossVersionTest/groovy/org/gradle/integtests/resolve/GradleMetadataJavaLibraryCrossVersionIntegrationTest.groovy @@ -0,0 +1,116 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.integtests.resolve + +import org.gradle.integtests.fixtures.CrossVersionIntegrationSpec +import org.gradle.integtests.fixtures.TargetVersions +import org.gradle.util.GradleVersion + +import static org.gradle.integtests.fixtures.AbstractIntegrationSpec.jcenterRepository + +@TargetVersions("5.2.1+") +class GradleMetadataJavaLibraryCrossVersionIntegrationTest extends CrossVersionIntegrationSpec { + + // The version in which Gradle metadata became "stable" + private static final GradleVersion STABLE_METADATA_VERSION = GradleVersion.version("5.3") + + def setup() { + settingsFile << """ + rootProject.name = 'test' + enableFeaturePreview('GRADLE_METADATA') + include 'consumer' + include 'producer' + """ + buildFile << """ + allprojects { + apply plugin: 'java-library' + + group = 'com.acme' + version = '1.0' + + repositories { + maven { url "\${rootProject.buildDir}/repo" } + ${jcenterRepository()} + } + } + """ + + file('producer/build.gradle') << """ + apply plugin: 'maven-publish' + + dependencies { + constraints { + api 'org.apache.commons:commons-lang3:3.8.1' + } + implementation('org.apache.commons:commons-lang3') { + version { + strictly '[3.8, 3.9[' + because "Doesn't work with other versions than 3.8" + } + } + } + + java { + if (JavaPluginExtension.metaClass.respondsTo(delegate, 'registerFeature')) { + registerFeature("hibernateSupport") { + usingSourceSet(sourceSets.main) + capability("com.acme", "producer-hibernate-support", "1.0") + } + } + } + + publishing { + repositories { + maven { url "\${rootProject.buildDir}/repo" } + } + + publications { + producerLib(MavenPublication) { + from components.java + } + } + } + """ + + file('consumer/build.gradle') << """ + dependencies { + api 'com.acme:producer:1.0' + } + + task resolve { + doLast { + println configurations.runtimeClasspath.files + } + } + """ + } + + def "can consume library published with previous version of Gradle"() { + expect: + version previous withTasks ':producer:publish' run() + version current withTasks ':consumer:resolve' run() + } + + def "previous Gradle can consume library published with current version of Gradle"() { + expect: + version current withTasks ':producer:publish' run() + if (previous.version.compareTo(STABLE_METADATA_VERSION) >= 0) { + version previous withTasks ':consumer:resolve' run() + } + } + +} diff --git a/subprojects/plugins/src/main/java/org/gradle/api/plugins/internal/DefaultJavaFeatureSpec.java b/subprojects/plugins/src/main/java/org/gradle/api/plugins/internal/DefaultJavaFeatureSpec.java index 540b9f72fe496..e88a5c26fd627 100644 --- a/subprojects/plugins/src/main/java/org/gradle/api/plugins/internal/DefaultJavaFeatureSpec.java +++ b/subprojects/plugins/src/main/java/org/gradle/api/plugins/internal/DefaultJavaFeatureSpec.java @@ -17,6 +17,7 @@ import com.google.common.collect.Lists; import org.gradle.api.Action; +import org.gradle.api.InvalidUserCodeException; import org.gradle.api.Task; import org.gradle.api.artifacts.Configuration; import org.gradle.api.artifacts.ConfigurationContainer; @@ -103,6 +104,9 @@ public void create() { } private void setupConfigurations(SourceSet sourceSet) { + if (sourceSet == null) { + throw new InvalidUserCodeException("You must specify which source set to use for feature '" + name + "'"); + } String apiConfigurationName; String implConfigurationName; String apiElementsConfigurationName; From e8d38628903e7d039cc0b7fc54d8bd71fb2f692e Mon Sep 17 00:00:00 2001 From: Cedric Champeau Date: Wed, 20 Feb 2019 12:14:12 +0100 Subject: [PATCH 108/853] Move "category" attribute to the standard attributes --- .../src/docs/design/gradle-module-metadata-1.0-specification.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subprojects/docs/src/docs/design/gradle-module-metadata-1.0-specification.md b/subprojects/docs/src/docs/design/gradle-module-metadata-1.0-specification.md index f94eb3de4e1ea..06a07997ce06f 100644 --- a/subprojects/docs/src/docs/design/gradle-module-metadata-1.0-specification.md +++ b/subprojects/docs/src/docs/design/gradle-module-metadata-1.0-specification.md @@ -86,11 +86,11 @@ This value must contain an array of 0 or more capabilities. Each capability is a - `org.gradle.usage` indicates the purpose of the variant. See the `org.gradle.api.attributes.Usage` class for more details. Value must be a string. - `org.gradle.status` indicates the kind of release: one of `release` or `integration`. +- `org.gradle.component.category` indicates the type of component (library or platform). This attribute is mostly used to disambiguate Maven POM files derived either as a platform or a library. Value must be a string. #### Java Ecosystem specific attributes - `org.gradle.dependency.bundling` indicates how dependencies of the variant are bundled. Either externally, embedded or shadowed. See the `org.gradle.api.attributes.java.Bundling` for more details. Value must be a string. -- `org.gradle.component.category` indicates the type of component (library or platform). This attribute is mostly used to disambiguate Maven POM files derived either as a platform or a library. Value must be a string. #### Native ecosystem specific attributes From f6a98158e75a636245f70d46604fcab3152361e8 Mon Sep 17 00:00:00 2001 From: Cedric Champeau Date: Thu, 21 Feb 2019 18:46:15 +0100 Subject: [PATCH 109/853] Document the target JVM version attribute --- .../docs/design/gradle-module-metadata-1.0-specification.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/subprojects/docs/src/docs/design/gradle-module-metadata-1.0-specification.md b/subprojects/docs/src/docs/design/gradle-module-metadata-1.0-specification.md index 06a07997ce06f..a881f2c2f941a 100644 --- a/subprojects/docs/src/docs/design/gradle-module-metadata-1.0-specification.md +++ b/subprojects/docs/src/docs/design/gradle-module-metadata-1.0-specification.md @@ -87,10 +87,11 @@ This value must contain an array of 0 or more capabilities. Each capability is a - `org.gradle.usage` indicates the purpose of the variant. See the `org.gradle.api.attributes.Usage` class for more details. Value must be a string. - `org.gradle.status` indicates the kind of release: one of `release` or `integration`. - `org.gradle.component.category` indicates the type of component (library or platform). This attribute is mostly used to disambiguate Maven POM files derived either as a platform or a library. Value must be a string. +- `org.gradle.dependency.bundling` indicates how dependencies of the variant are bundled. Either externally, embedded or shadowed. See the `org.gradle.api.attributes.Bundling` for more details. Value must be a string. #### Java Ecosystem specific attributes -- `org.gradle.dependency.bundling` indicates how dependencies of the variant are bundled. Either externally, embedded or shadowed. See the `org.gradle.api.attributes.java.Bundling` for more details. Value must be a string. +- `org.gradle.jvm.version` indicated the minimal target JVM version of a library. For example is built for java 8, its minimal target is `8`. If it's a multi-release jar for Java 9, 10 and 11, it's minimal target is `9`. Value must be an integer corresponding to the Java version. #### Native ecosystem specific attributes From 331d76f704a306676622db71148c12efef7677d2 Mon Sep 17 00:00:00 2001 From: Cedric Champeau Date: Fri, 22 Feb 2019 11:17:22 +0100 Subject: [PATCH 110/853] Fix tests for Gradle metadata 1.0 - Fix cross version test runtime classpath - Remove test which is no longer true now that parsing is lenient --- .../dependency-management.gradle.kts | 3 +- ...leMetadataResolutionIntegrationTest.groovy | 41 ------------------- 2 files changed, 2 insertions(+), 42 deletions(-) diff --git a/subprojects/dependency-management/dependency-management.gradle.kts b/subprojects/dependency-management/dependency-management.gradle.kts index 00f539a55dbb0..52512a4e1eabc 100644 --- a/subprojects/dependency-management/dependency-management.gradle.kts +++ b/subprojects/dependency-management/dependency-management.gradle.kts @@ -14,7 +14,6 @@ * limitations under the License. */ -import org.gradle.build.ClasspathManifest import org.gradle.gradlebuild.testing.integrationtests.cleanup.WhenNotEmpty import org.gradle.gradlebuild.unittestandcompile.ModuleType @@ -56,6 +55,8 @@ dependencies { testFixturesApi(project(":resourcesHttp", "testFixturesApiElements")) testFixturesImplementation(project(":internalIntegTesting")) + + crossVersionTestRuntimeOnly(project(":maven")) } gradlebuildJava { diff --git a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/maven/MavenRemoteDependencyWithGradleMetadataResolutionIntegrationTest.groovy b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/maven/MavenRemoteDependencyWithGradleMetadataResolutionIntegrationTest.groovy index c864c62ae7d75..f6b769290335b 100644 --- a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/maven/MavenRemoteDependencyWithGradleMetadataResolutionIntegrationTest.groovy +++ b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/maven/MavenRemoteDependencyWithGradleMetadataResolutionIntegrationTest.groovy @@ -774,47 +774,6 @@ dependencies { failure.assertHasCause("Could not parse module metadata ${m.moduleMetadata.uri}") } - def "reports failure to accept module metadata with unexpected format version"() { - def m = mavenHttpRepo.module("test", "a", "1.2").withModuleMetadata().publish() - m.moduleMetadata.file.text = m.moduleMetadata.file.text.replace(FORMAT_VERSION, "123.67") - - given: - buildFile << """ -repositories { - maven { - url = '${mavenHttpRepo.uri}' - } -} -configurations { compile } -dependencies { - compile 'test:a:1.2' -} -""" - - m.moduleMetadata.expectGet() - - when: - fails("checkDeps") - - then: - failure.assertHasCause("Could not resolve all dependencies for configuration ':compile'.") - failure.assertHasCause("Could not resolve test:a:1.2.") - failure.assertHasCause("Could not parse module metadata ${m.moduleMetadata.uri}") - failure.assertHasCause("Unsupported format version '123.67' specified in module metadata. This version of Gradle supports format version ${FORMAT_VERSION} only.") - - when: - server.resetExpectations() - m.moduleMetadata.expectHead() - - fails("checkDeps") - - then: - failure.assertHasCause("Could not resolve all dependencies for configuration ':compile'.") - failure.assertHasCause("Could not resolve test:a:1.2.") - failure.assertHasCause("Could not parse module metadata ${m.moduleMetadata.uri}") - failure.assertHasCause("Unsupported format version '123.67' specified in module metadata. This version of Gradle supports format version ${FORMAT_VERSION} only.") - } - def "reports failure to locate files"() { def m = mavenHttpRepo.module("test", "a", "1.2").withModuleMetadata() m.artifact(classifier: 'extra') From 2c5b187ec20c22ccb4e05ce61fd76ff084d245cc Mon Sep 17 00:00:00 2001 From: Stefan Wolf Date: Mon, 25 Feb 2019 14:09:45 +0100 Subject: [PATCH 111/853] Mark DefaultConfiguration package with non-null API and fix some warnings in `DefaultConfiguration`. --- .../java/org/gradle/internal/Actions.java | 1 + .../internal/CompositeDomainObjectSet.java | 1 + .../internal/artifacts/ResolverResults.java | 4 +++ .../configurations/DefaultConfiguration.java | 30 +++++++++---------- ...rationResolutionBuildOperationDetails.java | 4 +-- .../configurations/package-info.java | 20 +++++++++++++ 6 files changed, 42 insertions(+), 18 deletions(-) create mode 100644 subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/configurations/package-info.java diff --git a/subprojects/base-services/src/main/java/org/gradle/internal/Actions.java b/subprojects/base-services/src/main/java/org/gradle/internal/Actions.java index 7e962a9654d87..2aa4b7fc6d435 100644 --- a/subprojects/base-services/src/main/java/org/gradle/internal/Actions.java +++ b/subprojects/base-services/src/main/java/org/gradle/internal/Actions.java @@ -91,6 +91,7 @@ public static Action composite(List> actions) * @param The type of the object that action is for * @return The composite action. */ + @SafeVarargs public static Action composite(Action... actions) { List> filtered = Lists.newArrayListWithCapacity(actions.length); for (Action action : actions) { diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/CompositeDomainObjectSet.java b/subprojects/core/src/main/java/org/gradle/api/internal/CompositeDomainObjectSet.java index 8bf1c243067f5..d8a77c82c048a 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/CompositeDomainObjectSet.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/CompositeDomainObjectSet.java @@ -48,6 +48,7 @@ public static CompositeDomainObjectSet create(Class type, DomainObject return create(type, CollectionCallbackActionDecorator.NOOP, collections); } + @SafeVarargs public static CompositeDomainObjectSet create(Class type, CollectionCallbackActionDecorator callbackActionDecorator, DomainObjectCollection... collections) { DefaultDomainObjectSet backingSet = new DefaultDomainObjectSet(type, new DomainObjectCompositeCollection(), callbackActionDecorator); CompositeDomainObjectSet out = new CompositeDomainObjectSet(backingSet, callbackActionDecorator); diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ResolverResults.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ResolverResults.java index 99ad65411eefd..00950631f622a 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ResolverResults.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ResolverResults.java @@ -21,6 +21,8 @@ import org.gradle.api.internal.artifacts.ivyservice.resolveengine.artifact.VisitedArtifactSet; import org.gradle.api.internal.artifacts.ivyservice.resolveengine.projectresult.ResolvedLocalComponentsResult; +import javax.annotation.Nullable; + public interface ResolverResults { boolean hasError(); @@ -71,6 +73,7 @@ public interface ResolverResults { * removes the exception from the underlying resolver results, meaning that subsequent calls to consume * will return null. */ + @Nullable ResolveException consumeNonFatalFailure(); /** @@ -79,6 +82,7 @@ public interface ResolverResults { * this doesn't consume the error, so subsequent calls will return the same instance, unless the error was * consumed in between. */ + @Nullable Throwable getFailure(); boolean hasResolutionResult(); diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/configurations/DefaultConfiguration.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/configurations/DefaultConfiguration.java index ffb77e481a94a..fa058ac682b78 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/configurations/DefaultConfiguration.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/configurations/DefaultConfiguration.java @@ -263,7 +263,7 @@ public DefaultConfiguration(DomainObjectContext domainObjectContext, this.attributesFactory = attributesFactory; this.configurationAttributes = attributesFactory.mutable(); this.domainObjectContext = domainObjectContext; - this.intrinsicFiles = new ConfigurationFileCollection(Specs.satisfyAll()); + this.intrinsicFiles = new ConfigurationFileCollection(Specs.satisfyAll()); this.documentationRegistry = documentationRegistry; this.resolutionLock = domainObjectProjectStateHandler.newExclusiveOperationLock(); this.resolvableDependencies = instantiator.newInstance(ConfigurationResolvableDependencies.class, this); @@ -391,20 +391,21 @@ public Configuration setTransitive(boolean transitive) { return this; } + @Nullable public String getDescription() { return description; } - public Configuration setDescription(String description) { + public Configuration setDescription(@Nullable String description) { this.description = description; return this; } public Set getHierarchy() { if (extendsFrom.isEmpty()) { - return Collections.singleton(this); + return Collections.singleton(this); } - Set result = WrapUtil.toLinkedSet(this); + Set result = WrapUtil.toLinkedSet(this); collectSuperConfigs(this, result); return result; } @@ -454,7 +455,7 @@ public void runDependencyActions() { } public Set getAll() { - return ImmutableSet.copyOf(configurationsProvider.getAll()); + return ImmutableSet.copyOf(configurationsProvider.getAll()); } public Set resolve() { @@ -948,7 +949,7 @@ private DefaultConfiguration createCopy(Set dependencies, Set attribute : configurationAttributes.keySet()) { Object value = configurationAttributes.getAttribute(attribute); - copiedConfiguration.getAttributes().attribute(Cast.>uncheckedCast(attribute), value); + copiedConfiguration.getAttributes().attribute(Cast.uncheckedNonnullCast(attribute), value); } } @@ -971,11 +972,11 @@ private DefaultConfiguration createCopy(Set dependencies, SetconvertClosureToSpec(dependencySpec)); + return copy(Specs.convertClosureToSpec(dependencySpec)); } public Configuration copyRecursive(Closure dependencySpec) { - return copyRecursive(Specs.convertClosureToSpec(dependencySpec)); + return copyRecursive(Specs.convertClosureToSpec(dependencySpec)); } public ResolutionStrategyInternal getResolutionStrategy() { @@ -1316,7 +1317,7 @@ public String toString() { } public FileCollection getFiles() { - return new ConfigurationFileCollection(Specs.satisfyAll()); + return new ConfigurationFileCollection(Specs.satisfyAll()); } public DependencySet getDependencies() { @@ -1407,7 +1408,7 @@ public ArtifactCollection getArtifacts() { @Override public FileCollection getFiles() { - return new ConfigurationFileCollection(Specs.satisfyAll(), viewAttributes, componentFilter, lenient, allowNoMatchingVariants); + return new ConfigurationFileCollection(Specs.satisfyAll(), viewAttributes, componentFilter, lenient, allowNoMatchingVariants); } } @@ -1580,21 +1581,18 @@ private ImmutableAttributes lockViewAttributes() { private class ConfigurationArtifactCollection implements ArtifactCollection { private final ConfigurationFileCollection fileCollection; - private final AttributeContainerInternal viewAttributes; - private final Spec componentFilter; private final boolean lenient; private Set artifactResults; private Set failures; ConfigurationArtifactCollection() { - this(configurationAttributes, Specs.satisfyAll(), false, false); + this(configurationAttributes, Specs.satisfyAll(), false, false); } ConfigurationArtifactCollection(AttributeContainerInternal attributes, Spec componentFilter, boolean lenient, boolean allowNoMatchingVariants) { assertIsResolvable(); - this.viewAttributes = attributes.asImmutable(); - this.componentFilter = componentFilter; - this.fileCollection = new ConfigurationFileCollection(Specs.satisfyAll(), viewAttributes, this.componentFilter, lenient, allowNoMatchingVariants); + AttributeContainerInternal viewAttributes = attributes.asImmutable(); + this.fileCollection = new ConfigurationFileCollection(Specs.satisfyAll(), viewAttributes, componentFilter, lenient, allowNoMatchingVariants); this.lenient = lenient; } diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/configurations/ResolveConfigurationResolutionBuildOperationDetails.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/configurations/ResolveConfigurationResolutionBuildOperationDetails.java index 7947c0235cdb0..6c232b2fd2b38 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/configurations/ResolveConfigurationResolutionBuildOperationDetails.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/configurations/ResolveConfigurationResolutionBuildOperationDetails.java @@ -47,9 +47,9 @@ class ResolveConfigurationResolutionBuildOperationDetails implements ResolveConf ResolveConfigurationResolutionBuildOperationDetails( String configurationName, boolean isScriptConfiguration, - String configurationDescription, + @Nullable String configurationDescription, String buildPath, - String projectPath, + @Nullable String projectPath, boolean isConfigurationVisible, boolean isConfigurationTransitive, List repositories diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/configurations/package-info.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/configurations/package-info.java new file mode 100644 index 0000000000000..88176c2b9f9b0 --- /dev/null +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/configurations/package-info.java @@ -0,0 +1,20 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +@NonNullApi +package org.gradle.api.internal.artifacts.configurations; + +import org.gradle.api.NonNullApi; From f918d2f94cc822a7866e7f033bed94a8204d4cad Mon Sep 17 00:00:00 2001 From: Stefan Wolf Date: Mon, 25 Feb 2019 14:11:57 +0100 Subject: [PATCH 112/853] Pass around empty service registry instead of `null`. --- .../internal/service/ServiceRegistry.java | 43 +++++++++++++++++++ .../org/gradle/execution/plan/ActionNode.java | 2 +- .../configurations/DefaultConfiguration.java | 2 +- .../transform/TransformationStep.java | 5 ++- .../api/internal/tasks/WorkNodeAction.java | 2 +- 5 files changed, 49 insertions(+), 5 deletions(-) diff --git a/subprojects/base-services/src/main/java/org/gradle/internal/service/ServiceRegistry.java b/subprojects/base-services/src/main/java/org/gradle/internal/service/ServiceRegistry.java index 8991b9c44b4fc..5794a3d7a78b0 100644 --- a/subprojects/base-services/src/main/java/org/gradle/internal/service/ServiceRegistry.java +++ b/subprojects/base-services/src/main/java/org/gradle/internal/service/ServiceRegistry.java @@ -15,9 +15,11 @@ */ package org.gradle.internal.service; +import com.google.common.collect.ImmutableList; import org.gradle.internal.Factory; import org.gradle.internal.scan.UsedByScanPlugin; +import java.lang.annotation.Annotation; import java.lang.reflect.Type; import java.util.List; @@ -88,4 +90,45 @@ public interface ServiceRegistry extends ServiceLookup { * @throws ServiceLookupException On failure to lookup the specified service factory. */ T newInstance(Class type) throws UnknownServiceException, ServiceLookupException; + + ServiceRegistry EMPTY = new ServiceRegistry() { + @Override + public T get(Class serviceType) throws UnknownServiceException, ServiceLookupException { + throw emptyServiceRegistryException(serviceType); + } + + @Override + public List getAll(Class serviceType) throws ServiceLookupException { + return ImmutableList.of(); + } + + @Override + public Object get(Type serviceType) throws UnknownServiceException, ServiceLookupException { + throw emptyServiceRegistryException(serviceType); + } + + @Override + public Object find(Type serviceType) throws ServiceLookupException { + return null; + } + + @Override + public Factory getFactory(Class type) throws UnknownServiceException, ServiceLookupException { + throw emptyServiceRegistryException(type); + } + + private UnknownServiceException emptyServiceRegistryException(Type type) { + return new UnknownServiceException(type, "Nothing is available in the empty service registry."); + } + + @Override + public T newInstance(Class type) throws UnknownServiceException, ServiceLookupException { + throw emptyServiceRegistryException(type); + } + + @Override + public Object get(Type serviceType, Class annotatedWith) throws UnknownServiceException, ServiceLookupException { + throw emptyServiceRegistryException(serviceType); + } + }; } diff --git a/subprojects/core/src/main/java/org/gradle/execution/plan/ActionNode.java b/subprojects/core/src/main/java/org/gradle/execution/plan/ActionNode.java index ece7e47cd2dd3..08ddf609cd398 100644 --- a/subprojects/core/src/main/java/org/gradle/execution/plan/ActionNode.java +++ b/subprojects/core/src/main/java/org/gradle/execution/plan/ActionNode.java @@ -80,7 +80,7 @@ public Project getProject() { public void run(ProjectExecutionServiceRegistry services) { ProjectInternal project = (ProjectInternal) action.getProject(); - ServiceRegistry registry = project == null ? null : services.forProject(project); + ServiceRegistry registry = project == null ? ServiceRegistry.EMPTY : services.forProject(project); action.run(registry); } } diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/configurations/DefaultConfiguration.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/configurations/DefaultConfiguration.java index fa058ac682b78..7a9d833b63776 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/configurations/DefaultConfiguration.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/configurations/DefaultConfiguration.java @@ -673,7 +673,7 @@ public Project getProject() { } @Override - public void run(@Nullable ServiceRegistry registry) { + public void run(ServiceRegistry registry) { resolveExclusively(GRAPH_RESOLVED); } }, fileCollectionFactory); diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/TransformationStep.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/TransformationStep.java index 880d8993d48c7..b4cf6783c37f1 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/TransformationStep.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/TransformationStep.java @@ -27,6 +27,7 @@ import org.gradle.api.internal.tasks.TaskDependencyResolveContext; import org.gradle.api.internal.tasks.WorkNodeAction; import org.gradle.execution.ProjectExecutionServiceRegistry; +import org.gradle.internal.Cast; import org.gradle.internal.Try; import org.gradle.internal.fingerprint.FileCollectionFingerprinterRegistry; import org.gradle.internal.service.ServiceRegistry; @@ -70,8 +71,8 @@ public Project getProject() { } @Override - public void run(@Nullable ServiceRegistry registry) { - FileCollectionFingerprinterRegistry fingerprinterRegistry = getFingerprinterRegistry(registry == null ? null : registry.get(FileCollectionFingerprinterRegistry.class)); + public void run(ServiceRegistry registry) { + FileCollectionFingerprinterRegistry fingerprinterRegistry = getFingerprinterRegistry(Cast.uncheckedCast(registry.find(FileCollectionFingerprinterRegistry.class))); isolateExclusively(fingerprinterRegistry); } }; diff --git a/subprojects/model-core/src/main/java/org/gradle/api/internal/tasks/WorkNodeAction.java b/subprojects/model-core/src/main/java/org/gradle/api/internal/tasks/WorkNodeAction.java index d07b5ca2eb4b7..e4e29e60d8be2 100644 --- a/subprojects/model-core/src/main/java/org/gradle/api/internal/tasks/WorkNodeAction.java +++ b/subprojects/model-core/src/main/java/org/gradle/api/internal/tasks/WorkNodeAction.java @@ -34,5 +34,5 @@ public interface WorkNodeAction { /** * Run the action, throwing any failure. */ - void run(@Nullable ServiceRegistry registry); + void run(ServiceRegistry registry); } From dab10bb813054890fe6d6b276719940b2f4819b8 Mon Sep 17 00:00:00 2001 From: Stefan Wolf Date: Mon, 25 Feb 2019 14:49:57 +0100 Subject: [PATCH 113/853] Add test for input artifact classpath normalization --- ...ansformInputArtifactIntegrationTest.groovy | 50 +++++++++++++++++++ .../ArtifactTransformTestFixture.groovy | 7 ++- 2 files changed, 56 insertions(+), 1 deletion(-) diff --git a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformInputArtifactIntegrationTest.groovy b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformInputArtifactIntegrationTest.groovy index 276e526f3dc53..c68cf6f8556ba 100644 --- a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformInputArtifactIntegrationTest.groovy +++ b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformInputArtifactIntegrationTest.groovy @@ -1161,6 +1161,56 @@ class ArtifactTransformInputArtifactIntegrationTest extends AbstractDependencyRe annotation << ["Classpath", "CompileClasspath"] } + def "honors runtime classpath normalization for input artifact"() { + settingsFile << "include 'a', 'b', 'c'" + setupBuildWithColorTransformAction { + produceJars() + } + buildFile << """ + project(':a') { + dependencies { + implementation project(':b') + implementation project(':c') + } + + normalization { + runtimeClasspath { + ignore("ignored.txt") + } + } + } + + abstract class MakeGreen implements TransformAction { + @InputArtifact @Classpath + abstract File getInput() + + void transform(TransformOutputs outputs) { + println "processing \${input.name}" + def output = outputs.file(input.name + ".green") + output.text = input.text + ".green" + } + } + """ + + when: + executer.withArguments("-PbEntryName=ignored.txt") + succeeds(":a:resolve") + + then: + result.assertTasksNotSkipped(":b:producer", ":c:producer", ":a:resolve") + transformed("b.jar", "c.jar") + outputContains("result = [b.jar.green, c.jar.green]") + + when: + executer.withArguments("-PbEntryName=ignored.txt", "-PbContent=different") + succeeds(":a:resolve") + + then: // change is ignored due to normalization + result.assertTasksNotSkipped(":b:producer", ":a:resolve") + transformed() + outputContains("result = [b.jar.green, c.jar.green]") + } + void transformed(String... expected) { def actual = output.readLines().inject([]) { items, line -> def matcher = Pattern.compile("processing\\s+(.+)").matcher(line) diff --git a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformTestFixture.groovy b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformTestFixture.groovy index 24fe09042934f..10ab82c28c108 100644 --- a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformTestFixture.groovy +++ b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformTestFixture.groovy @@ -129,13 +129,15 @@ class JarProducer extends DefaultTask { String content = "content" @Input long timestamp = 123L + @Input + String entryName = "thing.class" @TaskAction def go() { def file = output.get().asFile file.withOutputStream { def jarFile = new JarOutputStream(it) - def entry = new ZipEntry("thing.class") + def entry = new ZipEntry(entryName) entry.time = timestamp jarFile.putNextEntry(entry) jarFile << content @@ -257,6 +259,9 @@ allprojects { p -> if (project.hasProperty("\${project.name}Timestamp")) { timestamp = Long.parseLong(project.property("\${project.name}Timestamp")) } + if (project.hasProperty("\${project.name}EntryName")) { + entryName = project.property("\${project.name}EntryName") + } } """.stripIndent() } From 565c07218fb36b768e84f12f5708ccf0f884b5c3 Mon Sep 17 00:00:00 2001 From: Stefan Wolf Date: Mon, 25 Feb 2019 14:59:12 +0100 Subject: [PATCH 114/853] Remove unused custom values for build cache We now get enough information out of the box about buildSrc task, we don't need to add the custom values. --- .../profiling/buildscan/BuildScanPlugin.kt | 22 +------- .../profiling/buildscan/Visitor.kt | 53 ------------------- 2 files changed, 2 insertions(+), 73 deletions(-) delete mode 100644 buildSrc/subprojects/profiling/src/main/kotlin/org/gradle/gradlebuild/profiling/buildscan/Visitor.kt diff --git a/buildSrc/subprojects/profiling/src/main/kotlin/org/gradle/gradlebuild/profiling/buildscan/BuildScanPlugin.kt b/buildSrc/subprojects/profiling/src/main/kotlin/org/gradle/gradlebuild/profiling/buildscan/BuildScanPlugin.kt index 2fc034e771cad..93d7aefb5a4bc 100644 --- a/buildSrc/subprojects/profiling/src/main/kotlin/org/gradle/gradlebuild/profiling/buildscan/BuildScanPlugin.kt +++ b/buildSrc/subprojects/profiling/src/main/kotlin/org/gradle/gradlebuild/profiling/buildscan/BuildScanPlugin.kt @@ -28,19 +28,15 @@ import org.gradle.build.docs.CacheableAsciidoctorTask import org.gradle.gradlebuild.BuildEnvironment.isCiServer import org.gradle.gradlebuild.BuildEnvironment.isJenkins import org.gradle.gradlebuild.BuildEnvironment.isTravis -import org.gradle.internal.classloader.ClassLoaderHierarchyHasher -import org.gradle.kotlin.dsl.apply -import org.gradle.kotlin.dsl.support.serviceOf -import org.gradle.kotlin.dsl.the +import org.gradle.kotlin.dsl.* import org.jsoup.Jsoup import org.jsoup.parser.Parser import java.net.URLEncoder +import java.util.concurrent.atomic.AtomicBoolean import kotlin.collections.component1 import kotlin.collections.component2 import kotlin.collections.filter import kotlin.collections.forEach -import org.gradle.kotlin.dsl.* -import java.util.concurrent.atomic.AtomicBoolean const val serverUrl = "https://e.grdev.net" @@ -261,20 +257,6 @@ open class BuildScanPlugin : Plugin { fun Project.extractBuildCacheData() { if (gradle.startParameter.isBuildCacheEnabled) { buildScan.tag("CACHED") - - val tasksToInvestigate = System.getProperty("cache.investigate.tasks", ":baseServices:classpathManifest") - .split(",") - - gradle.taskGraph.whenReady { - buildScan.buildFinished { - gradle.taskGraph.allTasks - .filter { it.state.executed && it.path in tasksToInvestigate } - .forEach { task -> - val hasher = gradle.serviceOf() - Visitor(buildScan, hasher, task).visit(task::class.java.classLoader) - } - } - } } } diff --git a/buildSrc/subprojects/profiling/src/main/kotlin/org/gradle/gradlebuild/profiling/buildscan/Visitor.kt b/buildSrc/subprojects/profiling/src/main/kotlin/org/gradle/gradlebuild/profiling/buildscan/Visitor.kt deleted file mode 100644 index 03e5f8f904107..0000000000000 --- a/buildSrc/subprojects/profiling/src/main/kotlin/org/gradle/gradlebuild/profiling/buildscan/Visitor.kt +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright 2018 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.gradle.gradlebuild.profiling.buildscan - -import com.gradle.scan.plugin.BuildScanExtension -import org.gradle.api.Task -import org.gradle.internal.classloader.ClassLoaderHierarchyHasher -import org.gradle.internal.classloader.ClassLoaderVisitor -import java.net.URLClassLoader - - -class Visitor( - private val buildScan: BuildScanExtension, - private val hasher: ClassLoaderHierarchyHasher, - private val prefix: String -) : ClassLoaderVisitor() { - - private - var counter = 0 - - constructor(buildScan: BuildScanExtension, hasher: ClassLoaderHierarchyHasher, task: Task) : - this(buildScan, hasher, "${task.path}-classloader") - - private - fun classloaderHash(loader: ClassLoader): String? { - return hasher.getClassLoaderHash(loader)?.toString() - } - - override fun visit(classLoader: ClassLoader) { - val hash = classloaderHash(classLoader) - if (!hash.isNullOrEmpty()) { - val classloaderName = classLoader::class.java.simpleName - buildScan.value("$prefix-${counter++}-$classloaderName-hash", hash) - if ((this.counter <= 2) && (classLoader is URLClassLoader && (!classloaderName.contains("ExtClassLoader")))) { - buildScan.value("$prefix-${counter - 1}-classpath", classLoader.urLs.joinToString(":")) - } - } - super.visit(classLoader) - } -} From fca28ff98de4eb944f2b3bad3ff4f8dab5db7cd3 Mon Sep 17 00:00:00 2001 From: "Rodrigo B. de Oliveira" Date: Mon, 25 Feb 2019 11:20:57 -0300 Subject: [PATCH 115/853] Compute `PluginRequests` implied by precompiled script plugin --- .../PrecompiledScriptPluginAccessorsTest.kt | 83 ++++++-- .../precompiled/PrecompiledScriptPlugins.kt | 10 +- ...eneratePrecompiledScriptPluginAccessors.kt | 197 +++++++++++++++--- .../dsl/fixtures/bytecode/AsmExtensions.kt | 5 - 4 files changed, 239 insertions(+), 56 deletions(-) diff --git a/subprojects/kotlin-dsl-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPluginAccessorsTest.kt b/subprojects/kotlin-dsl-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPluginAccessorsTest.kt index f6a112b2aab21..b18155db60d50 100644 --- a/subprojects/kotlin-dsl-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPluginAccessorsTest.kt +++ b/subprojects/kotlin-dsl-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPluginAccessorsTest.kt @@ -21,12 +21,17 @@ import com.nhaarman.mockito_kotlin.doReturn import com.nhaarman.mockito_kotlin.inOrder import com.nhaarman.mockito_kotlin.mock +import org.gradle.api.Plugin import org.gradle.api.Project import org.gradle.api.plugins.PluginManager import org.gradle.kotlin.dsl.fixtures.FoldersDsl import org.gradle.kotlin.dsl.fixtures.bytecode.InternalName +import org.gradle.kotlin.dsl.fixtures.bytecode.RETURN +import org.gradle.kotlin.dsl.fixtures.bytecode.internalName import org.gradle.kotlin.dsl.fixtures.bytecode.publicClass +import org.gradle.kotlin.dsl.fixtures.bytecode.publicDefaultConstructor +import org.gradle.kotlin.dsl.fixtures.bytecode.publicMethod import org.gradle.kotlin.dsl.fixtures.normalisedPath import org.gradle.kotlin.dsl.fixtures.pluginDescriptorEntryFor import org.gradle.kotlin.dsl.support.zipTo @@ -56,8 +61,8 @@ class PrecompiledScriptPluginAccessorsTest : AbstractPrecompiledScriptPluginTest "src/main/kotlin" { "extensions" { withFile("Extensions.kt", """ - class App { var name: String = "app" } - class Lib { var name: String = "lib" } + open class App { var name: String = "app" } + open class Lib { var name: String = "lib" } """) } withFile("external-app.gradle.kts", """ @@ -150,24 +155,10 @@ class PrecompiledScriptPluginAccessorsTest : AbstractPrecompiledScriptPluginTest fun `can use plugin spec builders for plugins in the implementation classpath`() { // given: - val pluginJar = jarForPlugin("my.plugin", "MyPlugin") - - withKotlinDslPlugin().appendText(""" - - dependencies { - implementation(files("${pluginJar.normalisedPath}")) - } - - """) - - withPrecompiledKotlinScript("plugin.gradle.kts", """ - - plugins { - my.plugin - } - - """) + val pluginId = "my.plugin" + val pluginJar = jarForPlugin(pluginId, "MyPlugin") + withPrecompiledScriptApplying(pluginId, pluginJar) compileKotlin() val (project, pluginManager) = projectAndPluginManagerMocks() @@ -178,11 +169,45 @@ class PrecompiledScriptPluginAccessorsTest : AbstractPrecompiledScriptPluginTest ) inOrder(pluginManager) { - verify(pluginManager).apply("my.plugin") + verify(pluginManager).apply(pluginId) verifyNoMoreInteractions() } } + @Test + fun `plugin application errors are propagated`() { + + // given: + val pluginId = "invalid.plugin" + val pluginJar = jarWithInvalidPlugin(pluginId, "InvalidPlugin") + + withPrecompiledScriptApplying(pluginId, pluginJar) + + buildAndFail("classes").assertHasDescription( + "An exception occurred applying plugin request [id: '$pluginId']" + ).assertHasCause( + "'InvalidPlugin' is neither a plugin or a rule source and cannot be applied." + ) + } + + private + fun withPrecompiledScriptApplying(pluginId: String, pluginJar: File) { + + withKotlinDslPlugin().appendText(""" + + dependencies { + implementation(files("${pluginJar.normalisedPath}")) + } + + """) + + withPrecompiledKotlinScript("plugin.gradle.kts", """ + + plugins { $pluginId } + + """) + } + @Test fun `can use plugin spec builders in multi-project builds with local and external plugins`() { @@ -269,12 +294,28 @@ class PrecompiledScriptPluginAccessorsTest : AbstractPrecompiledScriptPluginTest get() = root.relativeTo(projectRoot).path private - fun jarForPlugin(id: String, implClass: String): File = + fun jarWithInvalidPlugin(id: String, implClass: String): File = pluginJarWith( pluginDescriptorEntryFor(id, implClass), "$implClass.class" to publicClass(InternalName(implClass)) ) + private + fun jarForPlugin(id: String, implClass: String): File = + pluginJarWith( + pluginDescriptorEntryFor(id, implClass), + "$implClass.class" to emptyPluginClassNamed(implClass) + ) + + private + fun emptyPluginClassNamed(implClass: String): ByteArray = + publicClass(InternalName(implClass), interfaces = listOf(Plugin::class.internalName)) { + publicDefaultConstructor() + publicMethod("apply", "(Ljava/lang/Object;)V") { + RETURN() + } + } + private fun pluginJarWith(vararg entries: Pair): File = newFile("my.plugin.jar").also { file -> diff --git a/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPlugins.kt b/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPlugins.kt index 66c1d805b14a5..4dbcd78b7f1e4 100644 --- a/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPlugins.kt +++ b/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPlugins.kt @@ -184,14 +184,18 @@ fun Project.enableScriptCompilationOf(scriptPlugins: List) { + scriptPluginPluginsFor(projectPlugins) + .groupBy { + it.plugins }.let { projectSchemaImpliedByPluginGroups(it) }.forEach { (projectSchema, pluginGroups) -> @@ -90,13 +125,88 @@ open class GeneratePrecompiledScriptPluginAccessors : ClassPathSensitiveCodeGene writeContentAddressableImplicitImportFor(scriptPlugin, projectSchema.packageName) } } + } + + private + fun scriptPluginPluginsFor(projectPlugins: List) = sequence { + val loader = createPluginsClassLoader() + try { + for (plugin in projectPlugins) { + loader.scriptPluginPluginsFor(plugin)?.let { + yield(it) + } + } + } finally { + stoppable(loader).stop() + } + } + + private + fun ClassLoader.scriptPluginPluginsFor(plugin: PrecompiledScriptPlugin): ScriptPluginPlugins? { + + // The compiled script class won't be present for precompiled script plugins + // which don't include a `plugins` block + if (getResource(compiledScriptClassFile(plugin)) == null) { + return null } + + val pluginRequests = collectPluginRequestsOf(plugin) + + // TODO: move to projectSchemaImpliedByPluginGroups + project.createSyntheticProject( + temporaryDir, + classPathFiles.files, + pluginRequests + ) + + return null // TODO } + private + fun ClassLoader.collectPluginRequestsOf(plugin: PrecompiledScriptPlugin): PluginRequests = + PluginRequestCollector(scriptSourceFor(plugin)).run { + + loadClass(plugin.compiledScriptTypeName) + .getConstructor(PluginDependenciesSpec::class.java) + .newInstance(createSpec(1)) + + pluginRequests + } + + private + fun compiledScriptClassFile(plugin: PrecompiledScriptPlugin) = + plugin.compiledScriptTypeName.replace('.', '/') + ".class" + + private + fun scriptSourceFor(plugin: PrecompiledScriptPlugin) = + TextResourceScriptSource( + BasicTextResourceLoader().loadFile("Precompiled script plugin", plugin.scriptFile) + ) + + private + fun selectProjectPlugins() = plugins.filter { it.scriptType == KotlinScriptType.PROJECT } + + private + fun createPluginsClassLoader(): ClassLoader = + classLoaderScopeRegistry() + .coreAndPluginsScope + .createChild("$path/precompiled-script-plugins").run { + local(compiledPluginsClassPath()) + lock() + localClassLoader + } + + private + fun classLoaderScopeRegistry() = project.serviceOf() + + private + fun compiledPluginsClassPath() = + DefaultClassPath.of(compiledPluginsBlocksDir.get().asFile) + classPath + private fun projectSchemaImpliedByPluginGroups( - pluginGroupsPerPluginsBlock: Map, List> - ): Iterable>> = emptyList() // TODO + pluginGroupsPerPlugins: Map, List> + ): Iterable>> = emptyList() // TODO private fun IO.writeTypeSafeAccessorsFor(projectSchema: HashedProjectSchema) { @@ -104,19 +214,14 @@ open class GeneratePrecompiledScriptPluginAccessors : ClassPathSensitiveCodeGene } private - fun IO.writeContentAddressableImplicitImportFor(scriptPlugin: ScriptWithPluginsBlock, packageName: String) { + fun IO.writeContentAddressableImplicitImportFor(scriptPlugin: ScriptPluginPlugins, packageName: String) { io { writeFile(implicitImportFileFor(scriptPlugin), "$packageName.*".toByteArray()) } } private - fun implicitImportFileFor(scriptPlugin: ScriptWithPluginsBlock): File = - metadataOutputDir.get().asFile.resolve(scriptPlugin.script.hashString) + fun implicitImportFileFor(scriptPluginPlugins: ScriptPluginPlugins): File = + metadataOutputDir.get().asFile.resolve(scriptPluginPlugins.scriptPlugin.hashString) - private - fun scriptWithPluginsBlock(plugin: PrecompiledScriptPlugin): ScriptWithPluginsBlock? { - if (plugin.scriptType != KotlinScriptType.PROJECT) return null - return null - } private fun projectSchemaImpliedBy( @@ -125,6 +230,51 @@ open class GeneratePrecompiledScriptPluginAccessors : ClassPathSensitiveCodeGene } +private +fun Project.createSyntheticProject( + projectDir: File, + rootProjectClassPath: Collection, + pluginRequests: PluginRequests +) { + + val syntheticRootProject = ProjectBuilder.builder() + .withProjectDir(projectDir) + .build() + + val scriptHandler = syntheticRootProject.buildscript as ScriptHandlerInternal + scriptHandler.addScriptClassPathDependency( + DefaultSelfResolvingDependency( + syntheticRootProject.serviceOf().fixed("kotlin-dsl-accessors-classpath", rootProjectClassPath) as FileCollectionInternal + ) + ) + + val rootProjectScope = (syntheticRootProject as ProjectInternal).classLoaderScope + syntheticRootProject.serviceOf().apply { + applyPlugins( + DefaultPluginRequests.EMPTY, + scriptHandler, + syntheticRootProject.pluginManager, + rootProjectScope + ) + } + + val syntheticProject = ProjectBuilder.builder() + .withParent(syntheticRootProject) + .withProjectDir(projectDir.resolve("kotlin-dsl-accessors/library")) + .build() + + val targetProjectScope = (syntheticProject as ProjectInternal).classLoaderScope + syntheticProject.serviceOf().apply { + applyPlugins( + pluginRequests, + syntheticProject.buildscript as ScriptHandlerInternal, + syntheticProject.pluginManager, + targetProjectScope + ) + } +} + + internal data class HashedProjectSchema( val schema: TypedProjectSchema, @@ -141,15 +291,8 @@ data class HashedProjectSchema( internal -data class ScriptWithPluginsBlock( - val script: PrecompiledScriptPlugin, - val pluginsBlock: PluginsBlock -) - - -internal -data class PluginsBlock( - val lineNumber: Int, +data class ScriptPluginPlugins( + val scriptPlugin: PrecompiledScriptPlugin, val plugins: List ) diff --git a/subprojects/kotlin-dsl-test-fixtures/src/main/kotlin/org/gradle/kotlin/dsl/fixtures/bytecode/AsmExtensions.kt b/subprojects/kotlin-dsl-test-fixtures/src/main/kotlin/org/gradle/kotlin/dsl/fixtures/bytecode/AsmExtensions.kt index 4823f622727c5..161b7817c7977 100644 --- a/subprojects/kotlin-dsl-test-fixtures/src/main/kotlin/org/gradle/kotlin/dsl/fixtures/bytecode/AsmExtensions.kt +++ b/subprojects/kotlin-dsl-test-fixtures/src/main/kotlin/org/gradle/kotlin/dsl/fixtures/bytecode/AsmExtensions.kt @@ -68,7 +68,6 @@ fun ClassWriter.endClass(): ByteArray { } -internal fun ClassWriter.publicDefaultConstructor(superName: InternalName = InternalNameOf.javaLangObject) { publicMethod("", "()V") { ALOAD(0) @@ -90,7 +89,6 @@ fun ClassVisitor.publicStaticMethod( } -internal fun ClassVisitor.publicMethod( name: String, desc: String, @@ -211,7 +209,6 @@ fun MethodVisitor.ARETURN() { } -internal fun MethodVisitor.RETURN() { visitInsn(Opcodes.RETURN) } @@ -325,11 +322,9 @@ object InternalNameOf { } -internal val KClass<*>.internalName: InternalName get() = java.internalName -internal inline val Class<*>.internalName: InternalName get() = InternalName(Type.getInternalName(this)) From 3985a0600d0dc2418932a0c375f99a55c784de0b Mon Sep 17 00:00:00 2001 From: Stefan Wolf Date: Thu, 21 Feb 2019 15:40:07 +0100 Subject: [PATCH 116/853] Use a type parameter on the transform action to determine the type of the transform parameter --- .../api/artifacts/dsl/DependencyHandler.java | 3 +- .../artifacts/transform/TransformAction.java | 5 +- ...factTransformCachingIntegrationTest.groovy | 7 +- ...ansformInputArtifactIntegrationTest.groovy | 26 +++--- .../ArtifactTransformIntegrationTest.groovy | 15 ++-- ...ctTransformIsolationIntegrationTest.groovy | 9 +-- .../ArtifactTransformTestFixture.groovy | 2 +- ...sformValuesInjectionIntegrationTest.groovy | 32 +++----- ...formWithDependenciesIntegrationTest.groovy | 17 ++-- ...nsformWithFileInputsIntegrationTest.groovy | 11 +-- .../artifacts/VariantTransformRegistry.java | 3 +- .../DefaultDependencyHandler.java | 3 +- .../DefaultVariantTransformRegistry.java | 35 ++++---- .../artifacts/transform/UnzipTransform.java | 2 +- ...DefaultVariantTransformRegistryTest.groovy | 81 +++++++++++-------- ...ractConsoleBuildPhaseFunctionalTest.groovy | 5 +- 16 files changed, 130 insertions(+), 126 deletions(-) diff --git a/subprojects/core-api/src/main/java/org/gradle/api/artifacts/dsl/DependencyHandler.java b/subprojects/core-api/src/main/java/org/gradle/api/artifacts/dsl/DependencyHandler.java index 0ffd7908ae9e2..df96d52f9fdf6 100644 --- a/subprojects/core-api/src/main/java/org/gradle/api/artifacts/dsl/DependencyHandler.java +++ b/subprojects/core-api/src/main/java/org/gradle/api/artifacts/dsl/DependencyHandler.java @@ -22,7 +22,6 @@ import org.gradle.api.artifacts.query.ArtifactResolutionQuery; import org.gradle.api.artifacts.transform.ParameterizedTransformSpec; import org.gradle.api.artifacts.transform.TransformAction; -import org.gradle.api.artifacts.transform.TransformSpec; import org.gradle.api.artifacts.transform.VariantTransform; import org.gradle.api.artifacts.type.ArtifactTypeContainer; import org.gradle.api.attributes.AttributesSchema; @@ -461,7 +460,7 @@ public interface DependencyHandler { * @since 5.3 */ @Incubating - void registerTransformAction(Class actionType, Action registrationAction); + void registerTransformAction(Class> actionType, Action> registrationAction); /** * Declares a dependency on a platform. If the target coordinates represent multiple diff --git a/subprojects/core-api/src/main/java/org/gradle/api/artifacts/transform/TransformAction.java b/subprojects/core-api/src/main/java/org/gradle/api/artifacts/transform/TransformAction.java index 171237dbaf449..153ead116a65e 100644 --- a/subprojects/core-api/src/main/java/org/gradle/api/artifacts/transform/TransformAction.java +++ b/subprojects/core-api/src/main/java/org/gradle/api/artifacts/transform/TransformAction.java @@ -31,10 +31,13 @@ * *

    A property annotated with {@link InputArtifactDependencies} will receive the dependencies of its input artifact. * + * @param Parameter type for the transform action. Should be {@link Void} if the action does not have parameters. * @since 5.3 */ +@SuppressWarnings("unused") @Incubating -public interface TransformAction { +public interface TransformAction { + /** * Executes the transform. * diff --git a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformCachingIntegrationTest.groovy b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformCachingIntegrationTest.groovy index 0e583a1310515..9fa51d481015b 100644 --- a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformCachingIntegrationTest.groovy +++ b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformCachingIntegrationTest.groovy @@ -1480,13 +1480,12 @@ ${getFileSizerBody(fileValue, 'new File(outputDirectory, ', 'new File(outputDire String registerFileSizerWithParameterObject(String fileValue) { """ - @AssociatedTransformAction(FileSizerAction) interface FileSizer { @Input Number getValue() void setValue(Number value) } - abstract class FileSizerAction implements TransformAction { + abstract class FileSizerAction implements TransformAction { @TransformParameters abstract FileSizer getParameters() @@ -1500,7 +1499,7 @@ ${getFileSizerBody(fileValue, 'outputs.dir(', 'outputs.file(')} allprojects { dependencies { - registerTransform(FileSizer) { + registerTransformAction(FileSizerAction) { from.attribute(artifactType, "jar") to.attribute(artifactType, "size") parameters { @@ -1571,7 +1570,7 @@ ${getFileSizerBody(fileValue, 'outputs.dir(', 'outputs.file(')} """ allprojects { dependencies { - registerTransform${useParameterObject ? "(FileSizer)" : ""} { + registerTransform${useParameterObject ? "Action(FileSizerAction)" : ""} { from.attribute(artifactType, "classes") to.attribute(artifactType, "size") ${useParameterObject ? "parameters { value = paramValue }" : "artifactTransform(FileSizer) { params(paramValue) }"} diff --git a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformInputArtifactIntegrationTest.groovy b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformInputArtifactIntegrationTest.groovy index 276e526f3dc53..954a92d6999fd 100644 --- a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformInputArtifactIntegrationTest.groovy +++ b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformInputArtifactIntegrationTest.groovy @@ -38,7 +38,7 @@ class ArtifactTransformInputArtifactIntegrationTest extends AbstractDependencyRe tasks.producer.doLast { throw new RuntimeException('broken') } } - abstract class MakeGreen implements TransformAction { + abstract class MakeGreen implements TransformAction { @InputArtifact abstract File getInput() @@ -74,7 +74,7 @@ class ArtifactTransformInputArtifactIntegrationTest extends AbstractDependencyRe } } - abstract class MakeGreen implements TransformAction { + abstract class MakeGreen implements TransformAction { @InputArtifact ${annotation} abstract File getInput() @@ -187,7 +187,7 @@ class ArtifactTransformInputArtifactIntegrationTest extends AbstractDependencyRe } } - abstract class MakeGreen implements TransformAction { + abstract class MakeGreen implements TransformAction { @InputArtifact ${annotation} abstract File getInput() @@ -317,7 +317,7 @@ class ArtifactTransformInputArtifactIntegrationTest extends AbstractDependencyRe } } - abstract class MakeGreen implements TransformAction { + abstract class MakeGreen implements TransformAction { @InputArtifact abstract File getInput() @@ -378,7 +378,7 @@ class ArtifactTransformInputArtifactIntegrationTest extends AbstractDependencyRe } @CacheableTransform - abstract class MakeGreen implements TransformAction { + abstract class MakeGreen implements TransformAction { @PathSensitive(PathSensitivity.NONE) @InputArtifact abstract File getInput() @@ -459,7 +459,7 @@ class ArtifactTransformInputArtifactIntegrationTest extends AbstractDependencyRe } @CacheableTransform - abstract class MakeGreen implements TransformAction { + abstract class MakeGreen implements TransformAction { @PathSensitive(PathSensitivity.${sensitivity}) @InputArtifact abstract File getInput() @@ -550,7 +550,7 @@ class ArtifactTransformInputArtifactIntegrationTest extends AbstractDependencyRe } @CacheableTransform - abstract class MakeGreen implements TransformAction { + abstract class MakeGreen implements TransformAction { @PathSensitive(PathSensitivity.${sensitivity}) @InputArtifact abstract File getInput() @@ -632,7 +632,7 @@ class ArtifactTransformInputArtifactIntegrationTest extends AbstractDependencyRe } } - abstract class MakeGreen implements TransformAction { + abstract class MakeGreen implements TransformAction { @PathSensitive(PathSensitivity.NONE) @InputArtifact abstract File getInput() @@ -721,7 +721,7 @@ class ArtifactTransformInputArtifactIntegrationTest extends AbstractDependencyRe } @CacheableTransform - abstract class MakeGreen implements TransformAction { + abstract class MakeGreen implements TransformAction { @PathSensitive(PathSensitivity.NONE) @InputArtifact abstract File getInput() @@ -823,7 +823,7 @@ class ArtifactTransformInputArtifactIntegrationTest extends AbstractDependencyRe implementation 'group2:lib2:1.0' } - abstract class MakeGreen implements TransformAction { + abstract class MakeGreen implements TransformAction { @PathSensitive(PathSensitivity.NONE) @InputArtifact abstract File getInput() @@ -909,7 +909,7 @@ class ArtifactTransformInputArtifactIntegrationTest extends AbstractDependencyRe implementation 'group2:lib2:1.0' } - abstract class MakeGreen implements TransformAction { + abstract class MakeGreen implements TransformAction { @PathSensitive(PathSensitivity.${sensitivity}) @InputArtifact abstract File getInput() @@ -976,7 +976,7 @@ class ArtifactTransformInputArtifactIntegrationTest extends AbstractDependencyRe } } - abstract class MakeGreen implements TransformAction { + abstract class MakeGreen implements TransformAction { @InputArtifact @${annotation} abstract File getInput() @@ -1076,7 +1076,7 @@ class ArtifactTransformInputArtifactIntegrationTest extends AbstractDependencyRe } @CacheableTransform - abstract class MakeGreen implements TransformAction { + abstract class MakeGreen implements TransformAction { @InputArtifact @${annotation} abstract File getInput() diff --git a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformIntegrationTest.groovy b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformIntegrationTest.groovy index 49556d1a83be8..f923904f67a42 100644 --- a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformIntegrationTest.groovy +++ b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformIntegrationTest.groovy @@ -803,7 +803,7 @@ $fileSizer } } - abstract class IdentityTransform implements TransformAction { + abstract class IdentityTransform implements TransformAction { @InputArtifact abstract File getInput() @@ -1553,7 +1553,7 @@ Found the following transforms: compile files(a) } - class FailingTransformAction implements TransformAction { + class FailingTransformAction implements TransformAction { void transform(TransformOutputs outputs) { ${switch (type) { case FileType.Missing: @@ -1623,7 +1623,7 @@ Found the following transforms: compile files(a) } - class DirectoryTransformAction implements TransformAction { + class DirectoryTransformAction implements TransformAction { void transform(TransformOutputs outputs) { def outputFile = outputs.file("some/dir/output.txt") assert outputFile.parentFile.directory @@ -1661,7 +1661,7 @@ Found the following transforms: compile files(a) } - abstract class MyTransformAction implements TransformAction { + abstract class MyTransformAction implements TransformAction { @InputArtifact abstract File getInput() @@ -1739,7 +1739,7 @@ Found the following transforms: SomewhereElseTransform.output = file("other.jar") - class SomewhereElseTransform implements TransformAction { + class SomewhereElseTransform implements TransformAction { static def output void transform(TransformOutputs outputs) { def outputFile = outputs.file(output) @@ -1947,19 +1947,18 @@ Found the following transforms: String toString() { return "" } } - @AssociatedTransformAction(CustomAction) interface Custom { @Input CustomType getInput() void setInput(CustomType input) } - class CustomAction implements TransformAction { + class CustomAction implements TransformAction { void transform(TransformOutputs outputs) { } } dependencies { - registerTransform(Custom) { + registerTransformAction(CustomAction) { from.attribute(artifactType, 'jar') to.attribute(artifactType, 'size') parameters { diff --git a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformIsolationIntegrationTest.groovy b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformIsolationIntegrationTest.groovy index 5bde248d22e78..8128eea835924 100644 --- a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformIsolationIntegrationTest.groovy +++ b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformIsolationIntegrationTest.groovy @@ -85,14 +85,13 @@ class Resolve extends Copy { given: buildFile << """ - @AssociatedTransformAction(CountRecorderAction) interface CountRecorder { @Input Counter getCounter() void setCounter(Counter counter) } - abstract class CountRecorderAction implements TransformAction { + abstract class CountRecorderAction implements TransformAction { private final Counter counter; @TransformParameters @@ -135,7 +134,7 @@ class Resolve extends Copy { } dependencies { - registerTransform(CountRecorder) { + registerTransformAction(CountRecorderAction) { from.attribute(artifactType, 'jar') to.attribute(artifactType, 'firstCount') parameters { @@ -143,14 +142,14 @@ class Resolve extends Copy { } } buildScriptCounter.increment() - registerTransform(CountRecorder) { + registerTransformAction(CountRecorderAction) { from.attribute(artifactType, 'jar') to.attribute(artifactType, 'secondCount') parameters { counter = buildScriptCounter } } - registerTransform(CountRecorder) { + registerTransformAction(CountRecorderAction) { from.attribute(artifactType, 'jar') to.attribute(artifactType, 'thirdCount') parameters { diff --git a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformTestFixture.groovy b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformTestFixture.groovy index 24fe09042934f..3709e5e094cf4 100644 --- a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformTestFixture.groovy +++ b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformTestFixture.groovy @@ -180,7 +180,7 @@ allprojects { buildFile << """ allprojects { p -> dependencies { - registerTransform(MakeGreen) { + registerTransformAction(MakeGreenAction) { from.attribute(color, 'blue') to.attribute(color, 'green') parameters { diff --git a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformValuesInjectionIntegrationTest.groovy b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformValuesInjectionIntegrationTest.groovy index 5e2766347f005..5222859984d2d 100644 --- a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformValuesInjectionIntegrationTest.groovy +++ b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformValuesInjectionIntegrationTest.groovy @@ -47,7 +47,7 @@ class ArtifactTransformValuesInjectionIntegrationTest extends AbstractDependency buildFile << """ allprojects { dependencies { - registerTransform(MakeGreen) { + registerTransformAction(MakeGreenAction) { from.attribute(color, 'blue') to.attribute(color, 'green') parameters { @@ -64,14 +64,13 @@ class ArtifactTransformValuesInjectionIntegrationTest extends AbstractDependency } } - @AssociatedTransformAction(MakeGreenAction) interface MakeGreen { @Input String getExtension() void setExtension(String value) } - abstract class MakeGreenAction implements TransformAction { + abstract class MakeGreenAction implements TransformAction { @TransformParameters abstract MakeGreen getParameters() @InputArtifact @@ -112,7 +111,6 @@ class ArtifactTransformValuesInjectionIntegrationTest extends AbstractDependency } } - @AssociatedTransformAction(MakeGreenAction) interface MakeGreen { @Input ${type} getProp() @@ -120,7 +118,7 @@ class ArtifactTransformValuesInjectionIntegrationTest extends AbstractDependency ${type} getOtherProp() } - abstract class MakeGreenAction implements TransformAction { + abstract class MakeGreenAction implements TransformAction { @TransformParameters abstract MakeGreen getParameters() @@ -161,7 +159,6 @@ class ArtifactTransformValuesInjectionIntegrationTest extends AbstractDependency } } - @AssociatedTransformAction(MakeGreenAction) interface MakeGreen { String getExtension() void setExtension(String value) @@ -179,7 +176,7 @@ class ArtifactTransformValuesInjectionIntegrationTest extends AbstractDependency } @CacheableTransform - abstract class MakeGreenAction implements TransformAction { + abstract class MakeGreenAction implements TransformAction { @TransformParameters abstract MakeGreen getParameters() @@ -220,7 +217,6 @@ class ArtifactTransformValuesInjectionIntegrationTest extends AbstractDependency } } - @AssociatedTransformAction(MakeGreenAction) interface MakeGreen { @Input String getExtension() @@ -230,7 +226,7 @@ class ArtifactTransformValuesInjectionIntegrationTest extends AbstractDependency void setBad(String value) } - abstract class MakeGreenAction implements TransformAction { + abstract class MakeGreenAction implements TransformAction { @TransformParameters abstract MakeGreen getParameters() @@ -270,7 +266,6 @@ class ArtifactTransformValuesInjectionIntegrationTest extends AbstractDependency } } - @AssociatedTransformAction(MakeGreenAction) interface MakeGreen { String getExtension() void setExtension(String value) @@ -279,7 +274,7 @@ class ArtifactTransformValuesInjectionIntegrationTest extends AbstractDependency void setBad(String value) } - abstract class MakeGreenAction implements TransformAction { + abstract class MakeGreenAction implements TransformAction { @TransformParameters abstract MakeGreen getParameters() @@ -319,7 +314,6 @@ class ArtifactTransformValuesInjectionIntegrationTest extends AbstractDependency } } - @AssociatedTransformAction(MakeGreenAction) interface MakeGreen { @Input String getExtension() @@ -327,7 +321,7 @@ class ArtifactTransformValuesInjectionIntegrationTest extends AbstractDependency } @CacheableTransform - abstract class MakeGreenAction implements TransformAction { + abstract class MakeGreenAction implements TransformAction { @TransformParameters abstract MakeGreen getParameters() @@ -385,14 +379,13 @@ class ArtifactTransformValuesInjectionIntegrationTest extends AbstractDependency } } - @AssociatedTransformAction(MakeGreenAction) interface MakeGreen { @Input String getExtension() void setExtension(String value) } - abstract class MakeGreenAction implements TransformAction { + abstract class MakeGreenAction implements TransformAction { @${annotation.simpleName} String getBad() { } @@ -433,7 +426,7 @@ project(':b') { } } -abstract class MakeGreen implements TransformAction { +abstract class MakeGreen implements TransformAction { @InputArtifactDependencies abstract ${targetType} getDependencies() @InputArtifact @@ -525,14 +518,13 @@ abstract class MakeGreen extends ArtifactTransform { } } - @AssociatedTransformAction(MakeGreenAction) interface MakeGreen { @Input String getExtension() void setExtension(String value) } - class MakeGreenAction implements TransformAction { + class MakeGreenAction implements TransformAction { private MakeGreen conf @Inject @@ -569,7 +561,7 @@ project(':a') { } } -abstract class MakeGreen implements TransformAction { +abstract class MakeGreen implements TransformAction { @InputArtifact abstract FileCollection getDependencies() @@ -603,7 +595,7 @@ project(':a') { } } -abstract class MakeGreen implements TransformAction { +abstract class MakeGreen implements TransformAction { @Inject abstract File getWorkspace() diff --git a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformWithDependenciesIntegrationTest.groovy b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformWithDependenciesIntegrationTest.groovy index 817c007df7f56..8f2822164815d 100644 --- a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformWithDependenciesIntegrationTest.groovy +++ b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformWithDependenciesIntegrationTest.groovy @@ -53,7 +53,6 @@ class ArtifactTransformWithDependenciesIntegrationTest extends AbstractHttpDepen setupBuildWithColorAttributes(cl) buildFile << """ -@AssociatedTransformAction(TestTransformAction) interface TestTransform { @Input String getTransformName() @@ -108,7 +107,7 @@ project(':app') { import javax.inject.Inject -abstract class TestTransformAction implements TransformAction { +abstract class TestTransformAction implements TransformAction { @TransformParameters abstract TestTransform getParameters() @@ -131,7 +130,7 @@ abstract class TestTransformAction implements TransformAction { } } -abstract class SimpleTransform implements TransformAction { +abstract class SimpleTransform implements TransformAction { @InputArtifact abstract File getInput() @@ -155,7 +154,7 @@ abstract class SimpleTransform implements TransformAction { buildFile << """ allprojects { dependencies { - registerTransform(TestTransform) { + registerTransformAction(TestTransformAction) { from.attribute(color, 'blue') to.attribute(color, 'green') parameters { @@ -177,7 +176,7 @@ allprojects { from.attribute(color, 'blue') to.attribute(color, 'yellow') } - registerTransform(TestTransform) { + registerTransformAction(TestTransformAction) { from.attribute(color, 'yellow') to.attribute(color, 'green') parameters { @@ -195,14 +194,14 @@ allprojects { allprojects { dependencies { // Multi step transform - registerTransform(TestTransform) { + registerTransformAction(TestTransformAction) { from.attribute(color, 'blue') to.attribute(color, 'yellow') parameters { transformName = 'Transform step 1' } } - registerTransform(TestTransform) { + registerTransformAction(TestTransformAction) { from.attribute(color, 'yellow') to.attribute(color, 'green') parameters { @@ -420,7 +419,7 @@ allprojects { } } -abstract class NoneTransformAction implements TransformAction { +abstract class NoneTransformAction implements TransformAction { @InputArtifactDependencies @PathSensitive(PathSensitivity.NONE) abstract FileCollection getInputArtifactDependencies() @@ -516,7 +515,7 @@ allprojects { } } -abstract class ClasspathTransformAction implements TransformAction { +abstract class ClasspathTransformAction implements TransformAction { @InputArtifactDependencies @${classpathAnnotation.simpleName} abstract FileCollection getInputArtifactDependencies() diff --git a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformWithFileInputsIntegrationTest.groovy b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformWithFileInputsIntegrationTest.groovy index 83ed25ab7334e..4d73082600754 100644 --- a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformWithFileInputsIntegrationTest.groovy +++ b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformWithFileInputsIntegrationTest.groovy @@ -31,13 +31,12 @@ class ArtifactTransformWithFileInputsIntegrationTest extends AbstractDependencyR """) } buildFile << """ - @AssociatedTransformAction(MakeGreenAction) interface MakeGreen { $inputAnnotations ConfigurableFileCollection getSomeFiles() } - abstract class MakeGreenAction implements TransformAction { + abstract class MakeGreenAction implements TransformAction { @TransformParameters abstract MakeGreen getParameters() @InputArtifact @@ -154,7 +153,7 @@ class ArtifactTransformWithFileInputsIntegrationTest extends AbstractDependencyR """ setupBuildWithTransformFileInputs() buildFile << """ - abstract class MakeRedAction implements TransformAction { + abstract class MakeRedAction implements TransformAction { @InputArtifact abstract File getInput() @@ -284,13 +283,12 @@ class ArtifactTransformWithFileInputsIntegrationTest extends AbstractDependencyR } } - @AssociatedTransformAction(MakeGreenAction) interface MakeGreen { @InputFile RegularFileProperty getSomeFile() } - abstract class MakeGreenAction implements TransformAction { + abstract class MakeGreenAction implements TransformAction { @TransformParameters abstract MakeGreen getParameters() @InputArtifact @@ -338,13 +336,12 @@ class ArtifactTransformWithFileInputsIntegrationTest extends AbstractDependencyR } } - @AssociatedTransformAction(MakeGreenAction) interface MakeGreen { @InputDirectory DirectoryProperty getSomeDir() } - abstract class MakeGreenAction implements TransformAction { + abstract class MakeGreenAction implements TransformAction { @TransformParameters abstract MakeGreen getParameters() @InputArtifact diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/VariantTransformRegistry.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/VariantTransformRegistry.java index 4db06e169b3f5..dcdd6b90c6f51 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/VariantTransformRegistry.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/VariantTransformRegistry.java @@ -19,7 +19,6 @@ import org.gradle.api.Action; import org.gradle.api.artifacts.transform.ParameterizedTransformSpec; import org.gradle.api.artifacts.transform.TransformAction; -import org.gradle.api.artifacts.transform.TransformSpec; import org.gradle.api.artifacts.transform.VariantTransform; public interface VariantTransformRegistry { @@ -33,7 +32,7 @@ public interface VariantTransformRegistry { void registerTransform(Class parameterType, Action> registrationAction); - void registerTransformAction(Class actionType, Action registrationAction); + void registerTransformAction(Class> actionType, Action> registrationAction); Iterable getTransforms(); } diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/dsl/dependencies/DefaultDependencyHandler.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/dsl/dependencies/DefaultDependencyHandler.java index 46e09cd54c74c..e22f4cd237b7a 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/dsl/dependencies/DefaultDependencyHandler.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/dsl/dependencies/DefaultDependencyHandler.java @@ -29,7 +29,6 @@ import org.gradle.api.artifacts.query.ArtifactResolutionQuery; import org.gradle.api.artifacts.transform.ParameterizedTransformSpec; import org.gradle.api.artifacts.transform.TransformAction; -import org.gradle.api.artifacts.transform.TransformSpec; import org.gradle.api.artifacts.transform.VariantTransform; import org.gradle.api.artifacts.type.ArtifactTypeContainer; import org.gradle.api.attributes.AttributesSchema; @@ -220,7 +219,7 @@ public void registerTransform(Class parameterType, Action void registerTransformAction(Class actionType, Action registrationAction) { + public void registerTransformAction(Class> actionType, Action> registrationAction) { transforms.registerTransformAction(actionType, registrationAction); } diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultVariantTransformRegistry.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultVariantTransformRegistry.java index 6ccc6d3105ac8..625a7441aa815 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultVariantTransformRegistry.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultVariantTransformRegistry.java @@ -17,6 +17,7 @@ package org.gradle.api.internal.artifacts.transform; import com.google.common.collect.Lists; +import com.google.common.reflect.TypeToken; import org.gradle.api.Action; import org.gradle.api.ActionConfiguration; import org.gradle.api.NonExtensible; @@ -40,6 +41,7 @@ import org.gradle.model.internal.type.ModelType; import javax.annotation.Nullable; +import java.lang.reflect.ParameterizedType; import java.util.Arrays; import java.util.List; @@ -87,11 +89,14 @@ public void registerTransform(Class parameterType, Action void registerTransformAction(Class actionType, Action registrationAction) { - ActionRegistration registration = instantiatorFactory.decorateLenient().newInstance(ActionRegistration.class, immutableAttributesFactory); + public void registerTransformAction(Class> actionType, Action> registrationAction) { + ParameterizedType superType = (ParameterizedType) TypeToken.of(actionType).getSupertype(TransformAction.class).getType(); + Class parameterType = Cast.uncheckedNonnullCast(TypeToken.of(superType.getActualTypeArguments()[0]).getRawType()); + T parameterObject = (Object.class.equals(parameterType) || Void.class.isAssignableFrom(parameterType)) ? null : parametersInstantiationScheme.withServices(services).newInstance(parameterType); + TypedRegistration registration = Cast.uncheckedNonnullCast(instantiatorFactory.decorateLenient().newInstance(TypedRegistration.class, parameterObject, immutableAttributesFactory)); registrationAction.execute(registration); - register(registration, actionType, null); + register(registration, actionType, parameterObject); } private void register(RecordingRegistration registration, Class actionType, @Nullable T parameterObject) { @@ -185,31 +190,31 @@ public static class TypedRegistration extends RecordingRegistration implement private final T parameterObject; Class actionType; - public TypedRegistration(T parameterObject, ImmutableAttributesFactory immutableAttributesFactory) { + public TypedRegistration(@Nullable T parameterObject, ImmutableAttributesFactory immutableAttributesFactory) { super(immutableAttributesFactory); this.parameterObject = parameterObject; - AssociatedTransformAction associatedTransformAction = parameterObject.getClass().getAnnotation(AssociatedTransformAction.class); - if (associatedTransformAction != null) { - actionType = associatedTransformAction.value(); + if (parameterObject != null) { + AssociatedTransformAction associatedTransformAction = parameterObject.getClass().getAnnotation(AssociatedTransformAction.class); + if (associatedTransformAction != null) { + actionType = associatedTransformAction.value(); + } } } @Override public T getParameters() { + if (parameterObject == null) { + throw new VariantTransformConfigurationException("Cannot query parameters for parameterless artifact transform."); + } return parameterObject; } @Override public void parameters(Action action) { + if (parameterObject == null) { + throw new VariantTransformConfigurationException("Cannot configure parameters for parameterless artifact transform."); + } action.execute(parameterObject); } } - - @NonExtensible - public static class ActionRegistration extends RecordingRegistration { - - public ActionRegistration(ImmutableAttributesFactory immutableAttributesFactory) { - super(immutableAttributesFactory); - } - } } diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/UnzipTransform.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/UnzipTransform.java index eee90b1f051f1..823f9eecca085 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/UnzipTransform.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/UnzipTransform.java @@ -38,7 +38,7 @@ * is located in the output directory of the transform and is named after the zipped file name * minus the extension. */ -public interface UnzipTransform extends TransformAction { +public interface UnzipTransform extends TransformAction { @InputArtifact File getZippedFile(); diff --git a/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/DefaultVariantTransformRegistryTest.groovy b/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/DefaultVariantTransformRegistryTest.groovy index 341ed0048475f..801f8a0f25723 100644 --- a/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/DefaultVariantTransformRegistryTest.groovy +++ b/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/DefaultVariantTransformRegistryTest.groovy @@ -16,8 +16,8 @@ package org.gradle.api.internal.artifacts.transform + import org.gradle.api.artifacts.transform.ArtifactTransform -import org.gradle.api.artifacts.transform.AssociatedTransformAction import org.gradle.api.artifacts.transform.TransformAction import org.gradle.api.artifacts.transform.TransformOutputs import org.gradle.api.artifacts.transform.VariantTransformConfigurationException @@ -38,7 +38,6 @@ import org.gradle.util.AttributeTestUtil import org.gradle.util.TestUtil import org.junit.Rule import spock.lang.Specification -import spock.lang.Unroll import javax.inject.Inject @@ -127,7 +126,7 @@ class DefaultVariantTransformRegistryTest extends Specification { def "creates registration with annotated parameters object"() { when: - registry.registerTransform(TestTransform) { + registry.registerTransformAction(TestTransformAction) { it.from.attribute(TEST_ATTRIBUTE, "FROM") it.to.attribute(TEST_ATTRIBUTE, "TO") } @@ -141,9 +140,9 @@ class DefaultVariantTransformRegistryTest extends Specification { registration.transformationStep.transformer.parameterObject instanceof TestTransform } - def "creates registration with with action"() { + def "creates registration for parametereless action"() { when: - registry.registerTransformAction(TestTransformAction) { + registry.registerTransformAction(ParameterlessTestTransformAction) { it.from.attribute(TEST_ATTRIBUTE, "FROM") it.to.attribute(TEST_ATTRIBUTE, "TO") } @@ -153,15 +152,44 @@ class DefaultVariantTransformRegistryTest extends Specification { def registration = registry.transforms[0] registration.from.getAttribute(TEST_ATTRIBUTE) == "FROM" registration.to.getAttribute(TEST_ATTRIBUTE) == "TO" - registration.transformationStep.transformer.implementationClass == TestTransformAction + registration.transformationStep.transformer.implementationClass == ParameterlessTestTransformAction registration.transformationStep.transformer.parameterObject == null } + def "cannot configure parameters for parameterless action"() { + when: + registry.registerTransformAction(ParameterlessTestTransformAction) { + it.from.attribute(TEST_ATTRIBUTE, "FROM") + it.to.attribute(TEST_ATTRIBUTE, "TO") + it.parameters { + } + } + + then: + def e = thrown(VariantTransformConfigurationException) + e.message == 'Cannot configure parameters for parameterless artifact transform.' + e.cause == null + } + + def "cannot query parameters object for parameterless action"() { + when: + registry.registerTransformAction(ParameterlessTestTransformAction) { + it.from.attribute(TEST_ATTRIBUTE, "FROM") + it.to.attribute(TEST_ATTRIBUTE, "TO") + it.parameters + } + + then: + def e = thrown(VariantTransformConfigurationException) + e.message == 'Cannot query parameters for parameterless artifact transform.' + e.cause == null + } + def "delegates are DSL decorated but not extensible when registering with config object"() { def registration when: - registry.registerTransform(TestTransform) { + registry.registerTransformAction(TestTransformAction) { it.from.attribute(TEST_ATTRIBUTE, "FROM") it.to.attribute(TEST_ATTRIBUTE, "TO") registration = it @@ -237,10 +265,9 @@ class DefaultVariantTransformRegistryTest extends Specification { e.cause == null } - @Unroll - def "fails when no from attributes are provided for #method"() { + def "fails when no from attributes are provided for registerTransformAction"() { when: - registry."$method"(argument) { + registry.registerTransformAction(TestTransformAction) { it.to.attribute(TEST_ATTRIBUTE, "to") } @@ -248,11 +275,6 @@ class DefaultVariantTransformRegistryTest extends Specification { def e = thrown(VariantTransformConfigurationException) e.message == "Could not register transform: at least one 'from' attribute must be provided." e.cause == null - - where: - method | argument - "registerTransform" | TestTransform - "registerTransformAction" | TestTransformAction } def "fails when no to attributes are provided for legacy registration"() { @@ -268,10 +290,9 @@ class DefaultVariantTransformRegistryTest extends Specification { e.cause == null } - @Unroll - def "fails when no to attributes are provided for #method"() { + def "fails when no to attributes are provided for registerTransformAction"() { when: - registry."${method}"(argument) { + registry.registerTransformAction(TestTransformAction) { it.from.attribute(TEST_ATTRIBUTE, "from") } @@ -279,11 +300,6 @@ class DefaultVariantTransformRegistryTest extends Specification { def e = thrown(VariantTransformConfigurationException) e.message == "Could not register transform: at least one 'to' attribute must be provided." e.cause == null - - where: - method | argument - "registerTransform" | TestTransform - "registerTransformAction" | TestTransformAction } def "fails when to attributes are not a subset of from attributes for legacy registration"() { @@ -302,10 +318,9 @@ class DefaultVariantTransformRegistryTest extends Specification { e.cause == null } - @Unroll - def "fails when to attributes are not a subset of from attributes for #method"() { + def "fails when to attributes are not a subset of from attributes for registerTransformAction"() { when: - registry."$method"(argument) { + registry.registerTransformAction(TestTransformAction) { it.from.attribute(TEST_ATTRIBUTE, "from") it.from.attribute(Attribute.of("from2", String), "from") it.to.attribute(TEST_ATTRIBUTE, "to") @@ -316,14 +331,8 @@ class DefaultVariantTransformRegistryTest extends Specification { def e = thrown(VariantTransformConfigurationException) e.message == "Could not register transform: each 'to' attribute must be included as a 'from' attribute." e.cause == null - - where: - method | argument - "registerTransform" | TestTransform - "registerTransformAction" | TestTransformAction } - @AssociatedTransformAction(TestTransformAction) static class TestTransform { String value } @@ -339,7 +348,13 @@ class DefaultVariantTransformRegistryTest extends Specification { } } - static class TestTransformAction implements TransformAction { + static class TestTransformAction implements TransformAction { + @Override + void transform(TransformOutputs outputs) { + } + } + + static class ParameterlessTestTransformAction implements TransformAction { @Override void transform(TransformOutputs outputs) { } diff --git a/subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/AbstractConsoleBuildPhaseFunctionalTest.groovy b/subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/AbstractConsoleBuildPhaseFunctionalTest.groovy index a8b4ca49f59d9..9bd062c23b9b4 100644 --- a/subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/AbstractConsoleBuildPhaseFunctionalTest.groovy +++ b/subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/AbstractConsoleBuildPhaseFunctionalTest.groovy @@ -326,14 +326,13 @@ abstract class AbstractConsoleBuildPhaseFunctionalTest extends AbstractIntegrati def usage = Attribute.of('usage', String) def artifactType = Attribute.of('artifactType', String) - @AssociatedTransformAction(FileSizerAction) interface FileSizer { @Input String getSuffix() void setSuffix(String suffix) } - abstract class FileSizerAction implements TransformAction { + abstract class FileSizerAction implements TransformAction { @TransformParameters abstract FileSizer getParameters() @InputArtifactDependencies @@ -390,7 +389,7 @@ abstract class AbstractConsoleBuildPhaseFunctionalTest extends AbstractIntegrati to.attribute(artifactType, "double") artifactTransform(FileDoubler) } - registerTransform(FileSizer) { + registerTransformAction(FileSizerAction) { from.attribute(artifactType, "double") to.attribute(artifactType, "size") parameters { From 0d21934e74965e7644a3236a99f3d57db3835d93 Mon Sep 17 00:00:00 2001 From: Stefan Wolf Date: Mon, 25 Feb 2019 15:26:28 +0100 Subject: [PATCH 117/853] Rename { -> Inject}TransformParameters --- ...rs.java => InjectTransformParameters.java} | 2 +- .../artifacts/transform/TransformAction.java | 2 +- ...factTransformCachingIntegrationTest.groovy | 2 +- ...ctTransformIsolationIntegrationTest.groovy | 2 +- ...sformValuesInjectionIntegrationTest.groovy | 20 +++++++++---------- ...formWithDependenciesIntegrationTest.groovy | 2 +- ...nsformWithFileInputsIntegrationTest.groovy | 6 +++--- ...pendencyManagementGlobalScopeServices.java | 10 +++++----- .../transform/DefaultTransformer.java | 4 ++-- ...ractConsoleBuildPhaseFunctionalTest.groovy | 2 +- ...lidateTaskPropertiesIntegrationTest.groovy | 4 ++-- 11 files changed, 28 insertions(+), 28 deletions(-) rename subprojects/core-api/src/main/java/org/gradle/api/artifacts/transform/{TransformParameters.java => InjectTransformParameters.java} (96%) diff --git a/subprojects/core-api/src/main/java/org/gradle/api/artifacts/transform/TransformParameters.java b/subprojects/core-api/src/main/java/org/gradle/api/artifacts/transform/InjectTransformParameters.java similarity index 96% rename from subprojects/core-api/src/main/java/org/gradle/api/artifacts/transform/TransformParameters.java rename to subprojects/core-api/src/main/java/org/gradle/api/artifacts/transform/InjectTransformParameters.java index 1107d99ab276a..68ca41f97abe3 100644 --- a/subprojects/core-api/src/main/java/org/gradle/api/artifacts/transform/TransformParameters.java +++ b/subprojects/core-api/src/main/java/org/gradle/api/artifacts/transform/InjectTransformParameters.java @@ -35,5 +35,5 @@ @Target({ElementType.METHOD}) @Documented @InjectionPointQualifier -public @interface TransformParameters { +public @interface InjectTransformParameters { } diff --git a/subprojects/core-api/src/main/java/org/gradle/api/artifacts/transform/TransformAction.java b/subprojects/core-api/src/main/java/org/gradle/api/artifacts/transform/TransformAction.java index 153ead116a65e..c7ef9ed46e7e4 100644 --- a/subprojects/core-api/src/main/java/org/gradle/api/artifacts/transform/TransformAction.java +++ b/subprojects/core-api/src/main/java/org/gradle/api/artifacts/transform/TransformAction.java @@ -25,7 +25,7 @@ * *

    Implementations can receive parameters by using annotated abstract getter methods.

    * - *

    A property annotated with {@link TransformParameters} will receive the object provided by {@link ParameterizedTransformSpec#getParameters()}. + *

    A property annotated with {@link InjectTransformParameters} will receive the object provided by {@link ParameterizedTransformSpec#getParameters()}. * *

    A property annotated with {@link InputArtifact} will receive the input artifact location, which is the file or directory that the transform should be applied to. * diff --git a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformCachingIntegrationTest.groovy b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformCachingIntegrationTest.groovy index 9fa51d481015b..1cd8c704ecd99 100644 --- a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformCachingIntegrationTest.groovy +++ b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformCachingIntegrationTest.groovy @@ -1486,7 +1486,7 @@ ${getFileSizerBody(fileValue, 'new File(outputDirectory, ', 'new File(outputDire void setValue(Number value) } abstract class FileSizerAction implements TransformAction { - @TransformParameters + @InjectTransformParameters abstract FileSizer getParameters() @InputArtifact diff --git a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformIsolationIntegrationTest.groovy b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformIsolationIntegrationTest.groovy index 8128eea835924..d0e4971d8e36f 100644 --- a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformIsolationIntegrationTest.groovy +++ b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformIsolationIntegrationTest.groovy @@ -94,7 +94,7 @@ class Resolve extends Copy { abstract class CountRecorderAction implements TransformAction { private final Counter counter; - @TransformParameters + @InjectTransformParameters abstract CountRecorder getParameters() @InputArtifact diff --git a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformValuesInjectionIntegrationTest.groovy b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformValuesInjectionIntegrationTest.groovy index 5222859984d2d..0343f8a438067 100644 --- a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformValuesInjectionIntegrationTest.groovy +++ b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformValuesInjectionIntegrationTest.groovy @@ -16,9 +16,9 @@ package org.gradle.integtests.resolve.transform +import org.gradle.api.artifacts.transform.InjectTransformParameters import org.gradle.api.artifacts.transform.InputArtifact import org.gradle.api.artifacts.transform.InputArtifactDependencies -import org.gradle.api.artifacts.transform.TransformParameters import org.gradle.api.file.FileCollection import org.gradle.api.tasks.Console import org.gradle.api.tasks.Destroys @@ -71,7 +71,7 @@ class ArtifactTransformValuesInjectionIntegrationTest extends AbstractDependency } abstract class MakeGreenAction implements TransformAction { - @TransformParameters + @InjectTransformParameters abstract MakeGreen getParameters() @InputArtifact abstract File getInput() @@ -119,7 +119,7 @@ class ArtifactTransformValuesInjectionIntegrationTest extends AbstractDependency } abstract class MakeGreenAction implements TransformAction { - @TransformParameters + @InjectTransformParameters abstract MakeGreen getParameters() void transform(TransformOutputs outputs) { @@ -177,7 +177,7 @@ class ArtifactTransformValuesInjectionIntegrationTest extends AbstractDependency @CacheableTransform abstract class MakeGreenAction implements TransformAction { - @TransformParameters + @InjectTransformParameters abstract MakeGreen getParameters() void transform(TransformOutputs outputs) { @@ -227,7 +227,7 @@ class ArtifactTransformValuesInjectionIntegrationTest extends AbstractDependency } abstract class MakeGreenAction implements TransformAction { - @TransformParameters + @InjectTransformParameters abstract MakeGreen getParameters() void transform(TransformOutputs outputs) { @@ -275,7 +275,7 @@ class ArtifactTransformValuesInjectionIntegrationTest extends AbstractDependency } abstract class MakeGreenAction implements TransformAction { - @TransformParameters + @InjectTransformParameters abstract MakeGreen getParameters() void transform(TransformOutputs outputs) { @@ -294,7 +294,7 @@ class ArtifactTransformValuesInjectionIntegrationTest extends AbstractDependency failure.assertHasCause("Cannot use @${annotation.simpleName} annotation on method MakeGreen.getBad().") where: - annotation << [InputArtifact, InputArtifactDependencies, TransformParameters] + annotation << [InputArtifact, InputArtifactDependencies, InjectTransformParameters] } def "transform action is validated for input output annotations"() { @@ -322,7 +322,7 @@ class ArtifactTransformValuesInjectionIntegrationTest extends AbstractDependency @CacheableTransform abstract class MakeGreenAction implements TransformAction { - @TransformParameters + @InjectTransformParameters abstract MakeGreen getParameters() @InputFile @@ -498,7 +498,7 @@ abstract class MakeGreen extends ArtifactTransform { failure.assertHasCause("Cannot use @${annotation.simpleName} annotation on method MakeGreen.getInputFile().") where: - annotation << [InputArtifact, InputArtifactDependencies, TransformParameters] + annotation << [InputArtifact, InputArtifactDependencies, InjectTransformParameters] } def "transform cannot receive parameter object via constructor parameter"() { @@ -634,6 +634,6 @@ abstract class MakeGreen implements TransformAction { failure.assertHasCause("Cannot use @${annotation.simpleName} annotation on method MyTask.getThing().") where: - annotation << [InputArtifact, InputArtifactDependencies, TransformParameters] + annotation << [InputArtifact, InputArtifactDependencies, InjectTransformParameters] } } diff --git a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformWithDependenciesIntegrationTest.groovy b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformWithDependenciesIntegrationTest.groovy index 8f2822164815d..93c42d729ecfa 100644 --- a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformWithDependenciesIntegrationTest.groovy +++ b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformWithDependenciesIntegrationTest.groovy @@ -109,7 +109,7 @@ import javax.inject.Inject abstract class TestTransformAction implements TransformAction { - @TransformParameters + @InjectTransformParameters abstract TestTransform getParameters() @InputArtifactDependencies diff --git a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformWithFileInputsIntegrationTest.groovy b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformWithFileInputsIntegrationTest.groovy index 4d73082600754..55830953d47ab 100644 --- a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformWithFileInputsIntegrationTest.groovy +++ b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformWithFileInputsIntegrationTest.groovy @@ -37,7 +37,7 @@ class ArtifactTransformWithFileInputsIntegrationTest extends AbstractDependencyR } abstract class MakeGreenAction implements TransformAction { - @TransformParameters + @InjectTransformParameters abstract MakeGreen getParameters() @InputArtifact abstract File getInput() @@ -289,7 +289,7 @@ class ArtifactTransformWithFileInputsIntegrationTest extends AbstractDependencyR } abstract class MakeGreenAction implements TransformAction { - @TransformParameters + @InjectTransformParameters abstract MakeGreen getParameters() @InputArtifact abstract File getInput() @@ -342,7 +342,7 @@ class ArtifactTransformWithFileInputsIntegrationTest extends AbstractDependencyR } abstract class MakeGreenAction implements TransformAction { - @TransformParameters + @InjectTransformParameters abstract MakeGreen getParameters() @InputArtifact abstract File getInput() diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/DependencyManagementGlobalScopeServices.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/DependencyManagementGlobalScopeServices.java index 539373755ba7e..9a87348ffabb1 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/DependencyManagementGlobalScopeServices.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/DependencyManagementGlobalScopeServices.java @@ -17,9 +17,9 @@ package org.gradle.api.internal.artifacts; import com.google.common.collect.ImmutableSet; +import org.gradle.api.artifacts.transform.InjectTransformParameters; import org.gradle.api.artifacts.transform.InputArtifact; import org.gradle.api.artifacts.transform.InputArtifactDependencies; -import org.gradle.api.artifacts.transform.TransformParameters; import org.gradle.api.internal.artifacts.ivyservice.DefaultIvyContextManager; import org.gradle.api.internal.artifacts.ivyservice.IvyContextManager; import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.strategy.DefaultVersionComparator; @@ -122,11 +122,11 @@ InputArtifactDependenciesAnnotationHandler createInputArtifactDependenciesAnnota } InjectAnnotationHandler createTransformParametersAnnotationHandler() { - return new DefaultInjectAnnotationHandler(TransformParameters.class); + return new DefaultInjectAnnotationHandler(InjectTransformParameters.class); } PropertyAnnotationHandler createTransformParametersPropertyAnnotationHandler() { - return new NoOpPropertyAnnotationHandler(TransformParameters.class); + return new NoOpPropertyAnnotationHandler(InjectTransformParameters.class); } ArtifactTransformParameterScheme createArtifactTransformParameterScheme(InspectionSchemeFactory inspectionSchemeFactory, InstantiatorFactory instantiatorFactory) { @@ -137,9 +137,9 @@ ArtifactTransformParameterScheme createArtifactTransformParameterScheme(Inspecti } ArtifactTransformActionScheme createArtifactTransformActionScheme(InspectionSchemeFactory inspectionSchemeFactory, InstantiatorFactory instantiatorFactory) { - InstantiationScheme instantiationScheme = instantiatorFactory.injectScheme(ImmutableSet.of(InputArtifact.class, InputArtifactDependencies.class, TransformParameters.class)); + InstantiationScheme instantiationScheme = instantiatorFactory.injectScheme(ImmutableSet.of(InputArtifact.class, InputArtifactDependencies.class, InjectTransformParameters.class)); InstantiationScheme legacyInstantiationScheme = instantiatorFactory.injectScheme(); - InspectionScheme inspectionScheme = inspectionSchemeFactory.inspectionScheme(ImmutableSet.of(InputArtifact.class, InputArtifactDependencies.class, TransformParameters.class, Inject.class, Classpath.class, CompileClasspath.class)); + InspectionScheme inspectionScheme = inspectionSchemeFactory.inspectionScheme(ImmutableSet.of(InputArtifact.class, InputArtifactDependencies.class, InjectTransformParameters.class, Inject.class, Classpath.class, CompileClasspath.class)); return new ArtifactTransformActionScheme(instantiationScheme, inspectionScheme, legacyInstantiationScheme); } } diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformer.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformer.java index a50896ff0161a..dba22da017f6e 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformer.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformer.java @@ -21,10 +21,10 @@ import com.google.common.reflect.TypeToken; import org.gradle.api.InvalidUserDataException; import org.gradle.api.Project; +import org.gradle.api.artifacts.transform.InjectTransformParameters; import org.gradle.api.artifacts.transform.InputArtifact; import org.gradle.api.artifacts.transform.InputArtifactDependencies; import org.gradle.api.artifacts.transform.TransformAction; -import org.gradle.api.artifacts.transform.TransformParameters; import org.gradle.api.artifacts.transform.VariantTransformConfigurationException; import org.gradle.api.file.FileCollection; import org.gradle.api.internal.attributes.ImmutableAttributes; @@ -322,7 +322,7 @@ public TransformServiceLookup(File inputFile, @Nullable Object parameters, @Null ImmutableList.Builder builder = ImmutableList.builder(); builder.add(new InjectionPoint(InputArtifact.class, File.class, inputFile)); if (parameters != null) { - builder.add(new InjectionPoint(TransformParameters.class, parameters.getClass(), parameters)); + builder.add(new InjectionPoint(InjectTransformParameters.class, parameters.getClass(), parameters)); } if (artifactTransformDependencies != null) { builder.add(new InjectionPoint(InputArtifactDependencies.class, artifactTransformDependencies.getFiles())); diff --git a/subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/AbstractConsoleBuildPhaseFunctionalTest.groovy b/subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/AbstractConsoleBuildPhaseFunctionalTest.groovy index 9bd062c23b9b4..f498cb58d519a 100644 --- a/subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/AbstractConsoleBuildPhaseFunctionalTest.groovy +++ b/subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/AbstractConsoleBuildPhaseFunctionalTest.groovy @@ -333,7 +333,7 @@ abstract class AbstractConsoleBuildPhaseFunctionalTest extends AbstractIntegrati } abstract class FileSizerAction implements TransformAction { - @TransformParameters + @InjectTransformParameters abstract FileSizer getParameters() @InputArtifactDependencies abstract FileCollection getDependencies() diff --git a/subprojects/plugin-development/src/integTest/groovy/org/gradle/plugin/devel/tasks/ValidateTaskPropertiesIntegrationTest.groovy b/subprojects/plugin-development/src/integTest/groovy/org/gradle/plugin/devel/tasks/ValidateTaskPropertiesIntegrationTest.groovy index d9f80584aac04..c78c56878ebb5 100644 --- a/subprojects/plugin-development/src/integTest/groovy/org/gradle/plugin/devel/tasks/ValidateTaskPropertiesIntegrationTest.groovy +++ b/subprojects/plugin-development/src/integTest/groovy/org/gradle/plugin/devel/tasks/ValidateTaskPropertiesIntegrationTest.groovy @@ -16,9 +16,9 @@ package org.gradle.plugin.devel.tasks +import org.gradle.api.artifacts.transform.InjectTransformParameters import org.gradle.api.artifacts.transform.InputArtifact import org.gradle.api.artifacts.transform.InputArtifactDependencies -import org.gradle.api.artifacts.transform.TransformParameters import org.gradle.api.file.FileCollection import org.gradle.api.model.ObjectFactory import org.gradle.api.tasks.Console @@ -227,7 +227,7 @@ class ValidateTaskPropertiesIntegrationTest extends AbstractIntegrationSpec { annotation | _ InputArtifact | _ InputArtifactDependencies | _ - TransformParameters | _ + InjectTransformParameters | _ } def "detects missing annotation on Groovy properties"() { From e31882e0ab1b4105cbd9d7c771282a2a4be878dc Mon Sep 17 00:00:00 2001 From: Gradleware Git Bot Date: Mon, 25 Feb 2019 15:29:26 +0100 Subject: [PATCH 118/853] Publish 5.3-20190225141513+0000 --- released-versions.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/released-versions.json b/released-versions.json index ca33ca082760f..becf616c94a77 100644 --- a/released-versions.json +++ b/released-versions.json @@ -1,7 +1,7 @@ { "latestReleaseSnapshot": { - "version": "5.3-20190225013325+0000", - "buildTime": "20190225013325+0000" + "version": "5.3-20190225141513+0000", + "buildTime": "20190225141513+0000" }, "latestRc": { "version": "5.2-rc-1", From a71493483b47be581843017a615cdcff6f40f410 Mon Sep 17 00:00:00 2001 From: Louis Jacomet Date: Mon, 25 Feb 2019 10:47:27 +0100 Subject: [PATCH 119/853] Proper propagation of flag when modifying metadata The `ConfigurationBoundExternalDependencyMetadata` was not properly propagating the `alwaysUseAttributeMatching` state when the metadata was modified. This caused legacy Maven / Ivy interop to kick in, as happened before Maven was fully moved to variant aware dependency management. One test needed to be modified, which in reality should have been changed at the 5.0 release. Fixes #8586 --- ...MixedMavenAndIvyModulesIntegrationTest.groovy | 16 ++++++++-------- ...igurationBoundExternalDependencyMetadata.java | 15 ++++++++++----- 2 files changed, 18 insertions(+), 13 deletions(-) diff --git a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/maven/MixedMavenAndIvyModulesIntegrationTest.groovy b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/maven/MixedMavenAndIvyModulesIntegrationTest.groovy index 360c4ab1a41c2..8b0c584329c3a 100644 --- a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/maven/MixedMavenAndIvyModulesIntegrationTest.groovy +++ b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/maven/MixedMavenAndIvyModulesIntegrationTest.groovy @@ -206,14 +206,16 @@ dependencies { } } - def "selects correct configuration of ivy module when dependency from consuming maven module is substituted"() { - def notRequired = ivyRepo.module("org.test", "ignore-me", "1.0") + def "selects default configuration of ivy module when dependency from consuming maven module is substituted"() { def m1 = ivyRepo.module("org.test", "m1", "1.0") .configuration("compile") .publish() def m2 = ivyRepo.module("org.test", "m2", "1.0").publish() .configuration("master") .publish() + def m3 = ivyRepo.module("org.test", "m3", "1.0").publish() + .configuration("master") + .publish() ivyRepo.module("org.test", "ivy", "1.2") .configuration("compile") .configuration("runtime") @@ -222,10 +224,10 @@ dependencies { .configuration("default") .dependsOn(m1, conf: "compile") .dependsOn(m2, conf: "master") - .dependsOn(notRequired, conf: "*,!compile,!master->unknown") + .dependsOn(m3, conf: "*,!compile,!master") .artifact(name: "compile", conf: "compile") .artifact(name: "master", conf: "master") - .artifact(name: 'ignore-me', conf: "other,default,runtime") + .artifact(name: 'default', conf: "other,default,runtime") .publish() def ivyModule = ivyRepo.module("org.test", "ivy", "1.0") mavenRepo.module("org.test", "maven", "1.0") @@ -246,10 +248,8 @@ configurations.conf.resolutionStrategy.force('org.test:ivy:1.2') configuration = 'compile' edge('org.test:ivy:1.0', 'org.test:ivy:1.2') { forced() - artifact(name: 'compile') - artifact(name: 'master') - module('org.test:m1:1.0') - module('org.test:m2:1.0') + artifact(name: 'default') + module('org.test:m3:1.0') } } } diff --git a/subprojects/dependency-management/src/main/java/org/gradle/internal/component/external/model/ConfigurationBoundExternalDependencyMetadata.java b/subprojects/dependency-management/src/main/java/org/gradle/internal/component/external/model/ConfigurationBoundExternalDependencyMetadata.java index add9f658f15e0..903ea59462ebe 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/internal/component/external/model/ConfigurationBoundExternalDependencyMetadata.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/internal/component/external/model/ConfigurationBoundExternalDependencyMetadata.java @@ -51,17 +51,22 @@ public class ConfigurationBoundExternalDependencyMetadata implements ModuleDepen private boolean alwaysUseAttributeMatching; - private ConfigurationBoundExternalDependencyMetadata(ConfigurationMetadata configuration, ModuleComponentIdentifier componentId, ExternalDependencyDescriptor dependencyDescriptor, String reason) { + private ConfigurationBoundExternalDependencyMetadata(ConfigurationMetadata configuration, ModuleComponentIdentifier componentId, ExternalDependencyDescriptor dependencyDescriptor, boolean alwaysUseAttributeMatching, String reason) { this.configuration = configuration; this.componentId = componentId; this.dependencyDescriptor = dependencyDescriptor; + this.alwaysUseAttributeMatching = alwaysUseAttributeMatching; this.reason = reason; this.isTransitive = dependencyDescriptor.isTransitive(); this.isConstraint = dependencyDescriptor.isConstraint(); } + private ConfigurationBoundExternalDependencyMetadata(ConfigurationMetadata configuration, ModuleComponentIdentifier componentId, ExternalDependencyDescriptor dependencyDescriptor, boolean alwaysUseAttributeMatching) { + this(configuration, componentId, dependencyDescriptor, alwaysUseAttributeMatching, null); + } + public ConfigurationBoundExternalDependencyMetadata(ConfigurationMetadata configuration, ModuleComponentIdentifier componentId, ExternalDependencyDescriptor dependencyDescriptor) { - this(configuration, componentId, dependencyDescriptor, null); + this(configuration, componentId, dependencyDescriptor, false, null); } public ConfigurationBoundExternalDependencyMetadata alwaysUseAttributeMatching() { @@ -134,16 +139,16 @@ public ModuleDependencyMetadata withReason(String reason) { if (Objects.equal(reason, this.getReason())) { return this; } - return new ConfigurationBoundExternalDependencyMetadata(configuration, componentId, dependencyDescriptor, reason); + return new ConfigurationBoundExternalDependencyMetadata(configuration, componentId, dependencyDescriptor, alwaysUseAttributeMatching, reason); } public ConfigurationBoundExternalDependencyMetadata withDescriptor(ExternalDependencyDescriptor descriptor) { - return new ConfigurationBoundExternalDependencyMetadata(configuration, componentId, descriptor); + return new ConfigurationBoundExternalDependencyMetadata(configuration, componentId, descriptor, alwaysUseAttributeMatching); } private ModuleDependencyMetadata withRequested(ModuleComponentSelector newSelector) { ExternalDependencyDescriptor newDelegate = dependencyDescriptor.withRequested(newSelector); - return new ConfigurationBoundExternalDependencyMetadata(configuration, componentId, newDelegate); + return new ConfigurationBoundExternalDependencyMetadata(configuration, componentId, newDelegate, alwaysUseAttributeMatching); } @Override From e9f1c7a92e414a9a3ce08e1324fd082af710c2cd Mon Sep 17 00:00:00 2001 From: Louis Jacomet Date: Mon, 25 Feb 2019 10:55:23 +0100 Subject: [PATCH 120/853] Release note potential breaking change Issue #8586 --- .../docs/src/docs/userguide/upgrading_version_5.adoc | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/subprojects/docs/src/docs/userguide/upgrading_version_5.adoc b/subprojects/docs/src/docs/userguide/upgrading_version_5.adoc index 5e38c34966fbb..ab71fb7b2c825 100644 --- a/subprojects/docs/src/docs/userguide/upgrading_version_5.adoc +++ b/subprojects/docs/src/docs/userguide/upgrading_version_5.adoc @@ -38,7 +38,7 @@ Some plugins will break with this new version of Gradle, for example because the === Potential breaking changes -==== Bugfixes in platform resolution +==== Bug fixes in platform resolution There was a bug from Gradle 5.0 to 5.2.1 (included) where enforced platforms would potentially include dependencies instead of constraints. This would happen whenever a POM file defined both dependencies and "constraints" (via ``) and that you used `enforcedPlatform`. @@ -73,6 +73,13 @@ java { } ``` +==== Bug fix in Maven / Ivy interoperability with dependency substitution + +If you have a Maven dependency pointing to an Ivy dependency where the `default` configuration dependencies do not match the `compile` + `runtime` + `master` ones +_and_ that Ivy dependency was substituted (using a `resolutionStrategy.force`, `resolutionStrategy.eachDependency` or `resolutionStrategy.dependencySubstitution`) +then this fix will impact you. +The legacy behaviour of Gradle, prior to 5.0, was still in place instead of being replaced by the changes introduced by improved pom support. + [[changes_5.2]] == Upgrading from 5.1 and earlier From d97c742862d0a184789b245b885e15922e44df66 Mon Sep 17 00:00:00 2001 From: Stefan Wolf Date: Mon, 25 Feb 2019 17:52:58 +0100 Subject: [PATCH 121/853] Add failing test for problems with generic type parameters The return type of the property is not correct, since bound type parameters of the superclass are not taken into account. --- ...edClassGeneratorInjectDecoratedTest.groovy | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/subprojects/model-core/src/test/groovy/org/gradle/internal/instantiation/AsmBackedClassGeneratorInjectDecoratedTest.groovy b/subprojects/model-core/src/test/groovy/org/gradle/internal/instantiation/AsmBackedClassGeneratorInjectDecoratedTest.groovy index a13ee47cf722a..ce77d26b3c6f1 100644 --- a/subprojects/model-core/src/test/groovy/org/gradle/internal/instantiation/AsmBackedClassGeneratorInjectDecoratedTest.groovy +++ b/subprojects/model-core/src/test/groovy/org/gradle/internal/instantiation/AsmBackedClassGeneratorInjectDecoratedTest.groovy @@ -21,11 +21,13 @@ import org.gradle.api.plugins.ExtensionContainer import org.gradle.internal.service.DefaultServiceRegistry import org.gradle.internal.service.ServiceLookup import org.gradle.internal.service.ServiceRegistry +import org.gradle.util.ToBeImplemented import javax.inject.Inject import java.lang.annotation.Annotation import java.lang.annotation.Retention import java.lang.annotation.RetentionPolicy +import java.lang.reflect.InvocationTargetException import java.lang.reflect.ParameterizedType import java.lang.reflect.Type @@ -64,6 +66,23 @@ class AsmBackedClassGeneratorInjectDecoratedTest extends AbstractClassGeneratorS obj.getProperty("thing") == 12 } + @ToBeImplemented("Resolving type parameters to implement the correct methods in the subclass does not work, yet") + def "can inject service using @Inject on a super interface with type parameters"() { + given: + def services = Mock(ServiceLookup) + _ * services.get(Number) >> 12 + + when: + def obj = create(AbstractClassWithConcreteTypeParameter, services) + + then: + def e = thrown(InvocationTargetException) + e.cause.class == NullPointerException +// obj.thing == 12 +// obj.getThing() == 12 +// obj.getProperty("thing") == 12 + } + def "can inject service using @Inject on an interface getter method"() { given: def services = Mock(ServiceLookup) @@ -311,6 +330,13 @@ interface InterfaceWithServices { Number getThing() } +interface InterfaceWithTypeParameter { + @Inject + T getThing() +} + +abstract class AbstractClassWithConcreteTypeParameter implements InterfaceWithTypeParameter {} + class BeanWithServices { @Inject Number getThing() { From 27538064e43b4cbf2414b47eaba0a73faba15c40 Mon Sep 17 00:00:00 2001 From: "Rodrigo B. de Oliveira" Date: Mon, 25 Feb 2019 14:51:46 -0300 Subject: [PATCH 122/853] Compute project schema implied by plugin requests --- ...eneratePrecompiledScriptPluginAccessors.kt | 153 +++++++++++------- .../dsl/accessors/AccessorsClassPath.kt | 1 - 2 files changed, 95 insertions(+), 59 deletions(-) diff --git a/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/GeneratePrecompiledScriptPluginAccessors.kt b/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/GeneratePrecompiledScriptPluginAccessors.kt index c494c4a84fae6..432410fa2e670 100644 --- a/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/GeneratePrecompiledScriptPluginAccessors.kt +++ b/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/GeneratePrecompiledScriptPluginAccessors.kt @@ -39,6 +39,7 @@ import org.gradle.internal.resource.BasicTextResourceLoader import org.gradle.kotlin.dsl.accessors.TypedProjectSchema import org.gradle.kotlin.dsl.accessors.hashCodeFor +import org.gradle.kotlin.dsl.accessors.schemaFor import org.gradle.kotlin.dsl.concurrent.IO import org.gradle.kotlin.dsl.concurrent.withAsynchronousIO @@ -50,6 +51,7 @@ import org.gradle.kotlin.dsl.support.KotlinScriptType import org.gradle.kotlin.dsl.support.serviceOf import org.gradle.plugin.management.internal.DefaultPluginRequests +import org.gradle.plugin.management.internal.PluginRequestInternal import org.gradle.plugin.management.internal.PluginRequests import org.gradle.plugin.use.PluginDependenciesSpec import org.gradle.plugin.use.internal.PluginRequestApplicator @@ -116,19 +118,22 @@ open class GeneratePrecompiledScriptPluginAccessors : ClassPathSensitiveCodeGene fun IO.generateTypeSafeAccessorsFor(projectPlugins: List) { scriptPluginPluginsFor(projectPlugins) .groupBy { - it.plugins + UniquePluginRequests(it.plugins) }.let { projectSchemaImpliedByPluginGroups(it) - }.forEach { (projectSchema, pluginGroups) -> + }.forEach { (projectSchema, scriptPlugins) -> writeTypeSafeAccessorsFor(projectSchema) - for (scriptPlugin in pluginGroups) { - writeContentAddressableImplicitImportFor(scriptPlugin, projectSchema.packageName) + for (scriptPlugin in scriptPlugins) { + writeContentAddressableImplicitImportFor( + scriptPlugin, + projectSchema.packageName + ) } } } private - fun scriptPluginPluginsFor(projectPlugins: List) = sequence { + fun scriptPluginPluginsFor(projectPlugins: List) = sequence { val loader = createPluginsClassLoader() try { for (plugin in projectPlugins) { @@ -150,16 +155,10 @@ open class GeneratePrecompiledScriptPluginAccessors : ClassPathSensitiveCodeGene return null } - val pluginRequests = collectPluginRequestsOf(plugin) - - // TODO: move to projectSchemaImpliedByPluginGroups - project.createSyntheticProject( - temporaryDir, - classPathFiles.files, - pluginRequests + return ScriptPluginPlugins( + plugin, + collectPluginRequestsOf(plugin) ) - - return null // TODO } private @@ -205,12 +204,19 @@ open class GeneratePrecompiledScriptPluginAccessors : ClassPathSensitiveCodeGene private fun projectSchemaImpliedByPluginGroups( - pluginGroupsPerPlugins: Map, List> - ): Iterable>> = emptyList() // TODO + pluginGroupsPerRequests: Map> + ): Iterable>> { + + val schemaBuilder = SyntheticProjectSchemaBuilder(temporaryDir, classPathFiles.files) + return pluginGroupsPerRequests.map { (uniquePluginRequests, scriptPlugins) -> + val schema = schemaBuilder.schemaFor(uniquePluginRequests.plugins) + HashedProjectSchema(schema) to scriptPlugins + } + } private fun IO.writeTypeSafeAccessorsFor(projectSchema: HashedProjectSchema) { - TODO("not implemented") + println(projectSchema) } private @@ -221,57 +227,69 @@ open class GeneratePrecompiledScriptPluginAccessors : ClassPathSensitiveCodeGene private fun implicitImportFileFor(scriptPluginPlugins: ScriptPluginPlugins): File = metadataOutputDir.get().asFile.resolve(scriptPluginPlugins.scriptPlugin.hashString) +} +internal +class SyntheticProjectSchemaBuilder(rootProjectDir: File, rootProjectClassPath: Set) { + private - fun projectSchemaImpliedBy( - plugins: List - ): TypedProjectSchema = TODO() -} + val rootProject = buildRootProject(rootProjectDir, rootProjectClassPath) + fun schemaFor(plugins: PluginRequests): TypedProjectSchema = + schemaFor(childProjectWith(plugins)) -private -fun Project.createSyntheticProject( - projectDir: File, - rootProjectClassPath: Collection, - pluginRequests: PluginRequests -) { + private + fun childProjectWith(pluginRequests: PluginRequests): Project { - val syntheticRootProject = ProjectBuilder.builder() - .withProjectDir(projectDir) - .build() + val project = ProjectBuilder.builder() + .withParent(rootProject) + .withProjectDir(rootProject.projectDir.resolve("schema")) + .build() - val scriptHandler = syntheticRootProject.buildscript as ScriptHandlerInternal - scriptHandler.addScriptClassPathDependency( - DefaultSelfResolvingDependency( - syntheticRootProject.serviceOf().fixed("kotlin-dsl-accessors-classpath", rootProjectClassPath) as FileCollectionInternal - ) - ) - - val rootProjectScope = (syntheticRootProject as ProjectInternal).classLoaderScope - syntheticRootProject.serviceOf().apply { - applyPlugins( - DefaultPluginRequests.EMPTY, - scriptHandler, - syntheticRootProject.pluginManager, - rootProjectScope - ) + applyPluginsTo(project, pluginRequests) + + return project + } + + private + fun buildRootProject(projectDir: File, rootProjectClassPath: Collection): Project { + + val project = ProjectBuilder.builder() + .withProjectDir(projectDir) + .build() + + addScriptClassPathDependencyTo(project, rootProjectClassPath) + + applyPluginsTo(project, DefaultPluginRequests.EMPTY) + + return project } - val syntheticProject = ProjectBuilder.builder() - .withParent(syntheticRootProject) - .withProjectDir(projectDir.resolve("kotlin-dsl-accessors/library")) - .build() - - val targetProjectScope = (syntheticProject as ProjectInternal).classLoaderScope - syntheticProject.serviceOf().apply { - applyPlugins( - pluginRequests, - syntheticProject.buildscript as ScriptHandlerInternal, - syntheticProject.pluginManager, - targetProjectScope + private + fun addScriptClassPathDependencyTo(project: Project, rootProjectClassPath: Collection) { + val scriptHandler = project.buildscript as ScriptHandlerInternal + scriptHandler.addScriptClassPathDependency( + DefaultSelfResolvingDependency( + project + .serviceOf() + .fixed("kotlin-dsl-accessors-classpath", rootProjectClassPath) as FileCollectionInternal + ) ) } + + private + fun applyPluginsTo(project: Project, pluginRequests: PluginRequests) { + val targetProjectScope = (project as ProjectInternal).classLoaderScope + project.serviceOf().apply { + applyPlugins( + pluginRequests, + project.buildscript as ScriptHandlerInternal, + project.pluginManager, + targetProjectScope + ) + } + } } @@ -293,7 +311,26 @@ data class HashedProjectSchema( internal data class ScriptPluginPlugins( val scriptPlugin: PrecompiledScriptPlugin, - val plugins: List + val plugins: PluginRequests +) + + +internal +class UniquePluginRequests(val plugins: PluginRequests) { + + val applications = plugins.map { it.toPluginApplication() } + + override fun equals(other: Any?): Boolean = + other is UniquePluginRequests && applications == other.applications + + override fun hashCode(): Int = + applications.hashCode() +} + + +internal +fun PluginRequestInternal.toPluginApplication() = PluginApplication( + id.id, version, isApply ) diff --git a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/accessors/AccessorsClassPath.kt b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/accessors/AccessorsClassPath.kt index c222f779c7cd5..729e36392f34a 100644 --- a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/accessors/AccessorsClassPath.kt +++ b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/accessors/AccessorsClassPath.kt @@ -135,7 +135,6 @@ fun configuredProjectSchemaOf(project: Project): TypedProjectSchema? = } else null -internal fun schemaFor(project: Project): TypedProjectSchema = projectSchemaProviderOf(project).schemaFor(project) From 78a058338642901ad15bf1a76e2825e6be147f74 Mon Sep 17 00:00:00 2001 From: "Rodrigo B. de Oliveira" Date: Mon, 25 Feb 2019 14:57:28 -0300 Subject: [PATCH 123/853] Polish `ResidualProgramCompiler` - Organize imports --- .../org/gradle/kotlin/dsl/execution/ResidualProgramCompiler.kt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/execution/ResidualProgramCompiler.kt b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/execution/ResidualProgramCompiler.kt index b3b0b00ed75a6..bc0c015ecb65b 100644 --- a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/execution/ResidualProgramCompiler.kt +++ b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/execution/ResidualProgramCompiler.kt @@ -36,6 +36,7 @@ import org.gradle.kotlin.dsl.support.KotlinInitscriptBlock import org.gradle.kotlin.dsl.support.KotlinPluginsBlock import org.gradle.kotlin.dsl.support.KotlinScriptHost import org.gradle.kotlin.dsl.support.KotlinSettingsBuildscriptBlock + import org.gradle.kotlin.dsl.support.bytecode.ACONST_NULL import org.gradle.kotlin.dsl.support.bytecode.ALOAD import org.gradle.kotlin.dsl.support.bytecode.ARETURN @@ -57,10 +58,12 @@ import org.gradle.kotlin.dsl.support.bytecode.loadByteArray import org.gradle.kotlin.dsl.support.bytecode.publicClass import org.gradle.kotlin.dsl.support.bytecode.publicDefaultConstructor import org.gradle.kotlin.dsl.support.bytecode.publicMethod + import org.gradle.kotlin.dsl.support.compileKotlinScriptToDirectory import org.gradle.kotlin.dsl.support.messageCollectorFor import org.gradle.plugin.management.internal.DefaultPluginRequests + import org.gradle.plugin.use.internal.PluginRequestCollector import org.jetbrains.kotlin.script.KotlinScriptDefinition From d189268454cc4190b2503ad7c00b0339ec5b2fd0 Mon Sep 17 00:00:00 2001 From: "Rodrigo B. de Oliveira" Date: Mon, 25 Feb 2019 14:57:52 -0300 Subject: [PATCH 124/853] Polish `ExtractPrecompiledScriptPluginPlugins` - Reuse `directoryProperty()` extension --- .../precompiled/tasks/ExtractPrecompiledScriptPluginPlugins.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/ExtractPrecompiledScriptPluginPlugins.kt b/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/ExtractPrecompiledScriptPluginPlugins.kt index 5b87d08835e54..7db2311349098 100644 --- a/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/ExtractPrecompiledScriptPluginPlugins.kt +++ b/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/ExtractPrecompiledScriptPluginPlugins.kt @@ -47,7 +47,7 @@ import java.io.File open class ExtractPrecompiledScriptPluginPlugins : DefaultTask() { @get:OutputDirectory - var outputDir = project.objects.directoryProperty() + var outputDir = directoryProperty() @get:Internal internal From 3ed06d28f76fc7e6e3c68013af0e0e6e20262e00 Mon Sep 17 00:00:00 2001 From: Stefan Wolf Date: Mon, 25 Feb 2019 22:07:06 +0100 Subject: [PATCH 125/853] Use TransformParameters as marker interface So it is easy to find all the parameter objects for artifact transforms. --- .../api/artifacts/dsl/DependencyHandler.java | 3 +- .../artifacts/transform/TransformAction.java | 5 +- .../transform/TransformParameters.java | 28 +++++++ ...factTransformCachingIntegrationTest.groovy | 10 +-- ...ansformInputArtifactIntegrationTest.groovy | 26 +++---- .../ArtifactTransformIntegrationTest.groovy | 24 +++--- ...ctTransformIsolationIntegrationTest.groovy | 14 ++-- .../ArtifactTransformTestFixture.groovy | 2 +- ...sformValuesInjectionIntegrationTest.groovy | 78 +++++++++---------- ...formWithDependenciesIntegrationTest.groovy | 24 +++--- ...nsformWithFileInputsIntegrationTest.groovy | 22 +++--- .../artifacts/VariantTransformRegistry.java | 3 +- .../DefaultDependencyHandler.java | 3 +- .../DefaultVariantTransformRegistry.java | 5 +- .../artifacts/transform/UnzipTransform.java | 3 +- ...DefaultVariantTransformRegistryTest.groovy | 36 +++++---- ...ractConsoleBuildPhaseFunctionalTest.groovy | 8 +- 17 files changed, 165 insertions(+), 129 deletions(-) create mode 100644 subprojects/core-api/src/main/java/org/gradle/api/artifacts/transform/TransformParameters.java diff --git a/subprojects/core-api/src/main/java/org/gradle/api/artifacts/dsl/DependencyHandler.java b/subprojects/core-api/src/main/java/org/gradle/api/artifacts/dsl/DependencyHandler.java index df96d52f9fdf6..692b787584519 100644 --- a/subprojects/core-api/src/main/java/org/gradle/api/artifacts/dsl/DependencyHandler.java +++ b/subprojects/core-api/src/main/java/org/gradle/api/artifacts/dsl/DependencyHandler.java @@ -22,6 +22,7 @@ import org.gradle.api.artifacts.query.ArtifactResolutionQuery; import org.gradle.api.artifacts.transform.ParameterizedTransformSpec; import org.gradle.api.artifacts.transform.TransformAction; +import org.gradle.api.artifacts.transform.TransformParameters; import org.gradle.api.artifacts.transform.VariantTransform; import org.gradle.api.artifacts.type.ArtifactTypeContainer; import org.gradle.api.attributes.AttributesSchema; @@ -460,7 +461,7 @@ public interface DependencyHandler { * @since 5.3 */ @Incubating - void registerTransformAction(Class> actionType, Action> registrationAction); + void registerTransformAction(Class> actionType, Action> registrationAction); /** * Declares a dependency on a platform. If the target coordinates represent multiple diff --git a/subprojects/core-api/src/main/java/org/gradle/api/artifacts/transform/TransformAction.java b/subprojects/core-api/src/main/java/org/gradle/api/artifacts/transform/TransformAction.java index c7ef9ed46e7e4..8d4e4f2fc24cb 100644 --- a/subprojects/core-api/src/main/java/org/gradle/api/artifacts/transform/TransformAction.java +++ b/subprojects/core-api/src/main/java/org/gradle/api/artifacts/transform/TransformAction.java @@ -31,12 +31,11 @@ * *

    A property annotated with {@link InputArtifactDependencies} will receive the dependencies of its input artifact. * - * @param Parameter type for the transform action. Should be {@link Void} if the action does not have parameters. + * @param Parameter type for the transform action. Should be {@link TransformParameters} if the action does not have parameters. * @since 5.3 */ -@SuppressWarnings("unused") @Incubating -public interface TransformAction { +public interface TransformAction { /** * Executes the transform. diff --git a/subprojects/core-api/src/main/java/org/gradle/api/artifacts/transform/TransformParameters.java b/subprojects/core-api/src/main/java/org/gradle/api/artifacts/transform/TransformParameters.java new file mode 100644 index 0000000000000..9887f73ed5dbc --- /dev/null +++ b/subprojects/core-api/src/main/java/org/gradle/api/artifacts/transform/TransformParameters.java @@ -0,0 +1,28 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.api.artifacts.transform; + +import org.gradle.api.Incubating; + +/** + * Marker interface for parameters to {@link TransformAction}. + * + * @since 5.3 + */ +@Incubating +public interface TransformParameters { +} diff --git a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformCachingIntegrationTest.groovy b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformCachingIntegrationTest.groovy index 1cd8c704ecd99..207cfd7a34eca 100644 --- a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformCachingIntegrationTest.groovy +++ b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformCachingIntegrationTest.groovy @@ -1480,14 +1480,14 @@ ${getFileSizerBody(fileValue, 'new File(outputDirectory, ', 'new File(outputDire String registerFileSizerWithParameterObject(String fileValue) { """ - interface FileSizer { + interface FileSizerParameters extends TransformParameters { @Input Number getValue() void setValue(Number value) } - abstract class FileSizerAction implements TransformAction { + abstract class FileSizer implements TransformAction { @InjectTransformParameters - abstract FileSizer getParameters() + abstract FileSizerParameters getParameters() @InputArtifact abstract File getInput() @@ -1499,7 +1499,7 @@ ${getFileSizerBody(fileValue, 'outputs.dir(', 'outputs.file(')} allprojects { dependencies { - registerTransformAction(FileSizerAction) { + registerTransformAction(FileSizer) { from.attribute(artifactType, "jar") to.attribute(artifactType, "size") parameters { @@ -1570,7 +1570,7 @@ ${getFileSizerBody(fileValue, 'outputs.dir(', 'outputs.file(')} """ allprojects { dependencies { - registerTransform${useParameterObject ? "Action(FileSizerAction)" : ""} { + registerTransform${useParameterObject ? "Action(FileSizer)" : ""} { from.attribute(artifactType, "classes") to.attribute(artifactType, "size") ${useParameterObject ? "parameters { value = paramValue }" : "artifactTransform(FileSizer) { params(paramValue) }"} diff --git a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformInputArtifactIntegrationTest.groovy b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformInputArtifactIntegrationTest.groovy index 954a92d6999fd..0e5dd3317885a 100644 --- a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformInputArtifactIntegrationTest.groovy +++ b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformInputArtifactIntegrationTest.groovy @@ -38,7 +38,7 @@ class ArtifactTransformInputArtifactIntegrationTest extends AbstractDependencyRe tasks.producer.doLast { throw new RuntimeException('broken') } } - abstract class MakeGreen implements TransformAction { + abstract class MakeGreen implements TransformAction { @InputArtifact abstract File getInput() @@ -74,7 +74,7 @@ class ArtifactTransformInputArtifactIntegrationTest extends AbstractDependencyRe } } - abstract class MakeGreen implements TransformAction { + abstract class MakeGreen implements TransformAction { @InputArtifact ${annotation} abstract File getInput() @@ -187,7 +187,7 @@ class ArtifactTransformInputArtifactIntegrationTest extends AbstractDependencyRe } } - abstract class MakeGreen implements TransformAction { + abstract class MakeGreen implements TransformAction { @InputArtifact ${annotation} abstract File getInput() @@ -317,7 +317,7 @@ class ArtifactTransformInputArtifactIntegrationTest extends AbstractDependencyRe } } - abstract class MakeGreen implements TransformAction { + abstract class MakeGreen implements TransformAction { @InputArtifact abstract File getInput() @@ -378,7 +378,7 @@ class ArtifactTransformInputArtifactIntegrationTest extends AbstractDependencyRe } @CacheableTransform - abstract class MakeGreen implements TransformAction { + abstract class MakeGreen implements TransformAction { @PathSensitive(PathSensitivity.NONE) @InputArtifact abstract File getInput() @@ -459,7 +459,7 @@ class ArtifactTransformInputArtifactIntegrationTest extends AbstractDependencyRe } @CacheableTransform - abstract class MakeGreen implements TransformAction { + abstract class MakeGreen implements TransformAction { @PathSensitive(PathSensitivity.${sensitivity}) @InputArtifact abstract File getInput() @@ -550,7 +550,7 @@ class ArtifactTransformInputArtifactIntegrationTest extends AbstractDependencyRe } @CacheableTransform - abstract class MakeGreen implements TransformAction { + abstract class MakeGreen implements TransformAction { @PathSensitive(PathSensitivity.${sensitivity}) @InputArtifact abstract File getInput() @@ -632,7 +632,7 @@ class ArtifactTransformInputArtifactIntegrationTest extends AbstractDependencyRe } } - abstract class MakeGreen implements TransformAction { + abstract class MakeGreen implements TransformAction { @PathSensitive(PathSensitivity.NONE) @InputArtifact abstract File getInput() @@ -721,7 +721,7 @@ class ArtifactTransformInputArtifactIntegrationTest extends AbstractDependencyRe } @CacheableTransform - abstract class MakeGreen implements TransformAction { + abstract class MakeGreen implements TransformAction { @PathSensitive(PathSensitivity.NONE) @InputArtifact abstract File getInput() @@ -823,7 +823,7 @@ class ArtifactTransformInputArtifactIntegrationTest extends AbstractDependencyRe implementation 'group2:lib2:1.0' } - abstract class MakeGreen implements TransformAction { + abstract class MakeGreen implements TransformAction { @PathSensitive(PathSensitivity.NONE) @InputArtifact abstract File getInput() @@ -909,7 +909,7 @@ class ArtifactTransformInputArtifactIntegrationTest extends AbstractDependencyRe implementation 'group2:lib2:1.0' } - abstract class MakeGreen implements TransformAction { + abstract class MakeGreen implements TransformAction { @PathSensitive(PathSensitivity.${sensitivity}) @InputArtifact abstract File getInput() @@ -976,7 +976,7 @@ class ArtifactTransformInputArtifactIntegrationTest extends AbstractDependencyRe } } - abstract class MakeGreen implements TransformAction { + abstract class MakeGreen implements TransformAction { @InputArtifact @${annotation} abstract File getInput() @@ -1076,7 +1076,7 @@ class ArtifactTransformInputArtifactIntegrationTest extends AbstractDependencyRe } @CacheableTransform - abstract class MakeGreen implements TransformAction { + abstract class MakeGreen implements TransformAction { @InputArtifact @${annotation} abstract File getInput() diff --git a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformIntegrationTest.groovy b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformIntegrationTest.groovy index f923904f67a42..391385f253a34 100644 --- a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformIntegrationTest.groovy +++ b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformIntegrationTest.groovy @@ -803,7 +803,7 @@ $fileSizer } } - abstract class IdentityTransform implements TransformAction { + abstract class IdentityTransform implements TransformAction { @InputArtifact abstract File getInput() @@ -1553,7 +1553,7 @@ Found the following transforms: compile files(a) } - class FailingTransformAction implements TransformAction { + class FailingTransform implements TransformAction { void transform(TransformOutputs outputs) { ${switch (type) { case FileType.Missing: @@ -1575,7 +1575,7 @@ Found the following transforms: }} } } - ${declareTransformAction('FailingTransformAction')} + ${declareTransformAction('FailingTransform')} task resolve(type: Copy) { def artifacts = configurations.compile.incoming.artifactView { @@ -1623,7 +1623,7 @@ Found the following transforms: compile files(a) } - class DirectoryTransformAction implements TransformAction { + class DirectoryTransform implements TransformAction { void transform(TransformOutputs outputs) { def outputFile = outputs.file("some/dir/output.txt") assert outputFile.parentFile.directory @@ -1633,7 +1633,7 @@ Found the following transforms: new File(outputDir, "in-dir.txt").text = "another output" } } - ${declareTransformAction('DirectoryTransformAction')} + ${declareTransformAction('DirectoryTransform')} task resolve(type: Copy) { def artifacts = configurations.compile.incoming.artifactView { @@ -1661,7 +1661,7 @@ Found the following transforms: compile files(a) } - abstract class MyTransformAction implements TransformAction { + abstract class MyTransform implements TransformAction { @InputArtifact abstract File getInput() @@ -1672,7 +1672,7 @@ Found the following transforms: } } dependencies { - registerTransformAction(MyTransformAction) { + registerTransformAction(MyTransform) { from.attribute(artifactType, 'directory') to.attribute(artifactType, 'size') } @@ -1739,7 +1739,7 @@ Found the following transforms: SomewhereElseTransform.output = file("other.jar") - class SomewhereElseTransform implements TransformAction { + class SomewhereElseTransform implements TransformAction { static def output void transform(TransformOutputs outputs) { def outputFile = outputs.file(output) @@ -1947,18 +1947,18 @@ Found the following transforms: String toString() { return "" } } - interface Custom { + interface CustomParameters extends TransformParameters { @Input CustomType getInput() void setInput(CustomType input) } - class CustomAction implements TransformAction { + class Custom implements TransformAction { void transform(TransformOutputs outputs) { } } dependencies { - registerTransformAction(CustomAction) { + registerTransformAction(Custom) { from.attribute(artifactType, 'jar') to.attribute(artifactType, 'size') parameters { @@ -1979,7 +1979,7 @@ Found the following transforms: when: fails "resolve" then: - Matcher matchesCannotIsolate = matchesRegexp("Cannot isolate parameters Custom\\\$Inject@.* of artifact transform CustomAction") + Matcher matchesCannotIsolate = matchesRegexp("Cannot isolate parameters CustomParameters\\\$Inject@.* of artifact transform Custom") if (scheduled) { failure.assertThatDescription(matchesCannotIsolate) } else { diff --git a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformIsolationIntegrationTest.groovy b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformIsolationIntegrationTest.groovy index d0e4971d8e36f..7a68aaed19650 100644 --- a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformIsolationIntegrationTest.groovy +++ b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformIsolationIntegrationTest.groovy @@ -85,22 +85,22 @@ class Resolve extends Copy { given: buildFile << """ - interface CountRecorder { + interface CountRecorderParameters extends TransformParameters{ @Input Counter getCounter() void setCounter(Counter counter) } - abstract class CountRecorderAction implements TransformAction { + abstract class CountRecorder implements TransformAction { private final Counter counter; @InjectTransformParameters - abstract CountRecorder getParameters() + abstract CountRecorderParameters getParameters() @InputArtifact abstract File getInput() - CountRecorderAction() { + CountRecorder() { println "Creating CountRecorder" } @@ -134,7 +134,7 @@ class Resolve extends Copy { } dependencies { - registerTransformAction(CountRecorderAction) { + registerTransformAction(CountRecorder) { from.attribute(artifactType, 'jar') to.attribute(artifactType, 'firstCount') parameters { @@ -142,14 +142,14 @@ class Resolve extends Copy { } } buildScriptCounter.increment() - registerTransformAction(CountRecorderAction) { + registerTransformAction(CountRecorder) { from.attribute(artifactType, 'jar') to.attribute(artifactType, 'secondCount') parameters { counter = buildScriptCounter } } - registerTransformAction(CountRecorderAction) { + registerTransformAction(CountRecorder) { from.attribute(artifactType, 'jar') to.attribute(artifactType, 'thirdCount') parameters { diff --git a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformTestFixture.groovy b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformTestFixture.groovy index 3709e5e094cf4..b344cf57619e3 100644 --- a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformTestFixture.groovy +++ b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformTestFixture.groovy @@ -180,7 +180,7 @@ allprojects { buildFile << """ allprojects { p -> dependencies { - registerTransformAction(MakeGreenAction) { + registerTransformAction(MakeGreen) { from.attribute(color, 'blue') to.attribute(color, 'green') parameters { diff --git a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformValuesInjectionIntegrationTest.groovy b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformValuesInjectionIntegrationTest.groovy index 0343f8a438067..0a8909edbb13e 100644 --- a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformValuesInjectionIntegrationTest.groovy +++ b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformValuesInjectionIntegrationTest.groovy @@ -47,7 +47,7 @@ class ArtifactTransformValuesInjectionIntegrationTest extends AbstractDependency buildFile << """ allprojects { dependencies { - registerTransformAction(MakeGreenAction) { + registerTransformAction(MakeGreen) { from.attribute(color, 'blue') to.attribute(color, 'green') parameters { @@ -64,15 +64,15 @@ class ArtifactTransformValuesInjectionIntegrationTest extends AbstractDependency } } - interface MakeGreen { + interface MakeGreenParameters extends TransformParameters { @Input String getExtension() void setExtension(String value) } - abstract class MakeGreenAction implements TransformAction { + abstract class MakeGreen implements TransformAction { @InjectTransformParameters - abstract MakeGreen getParameters() + abstract MakeGreenParameters getParameters() @InputArtifact abstract File getInput() @@ -111,16 +111,16 @@ class ArtifactTransformValuesInjectionIntegrationTest extends AbstractDependency } } - interface MakeGreen { + interface MakeGreenParameters extends TransformParameters { @Input ${type} getProp() @Input @Optional ${type} getOtherProp() } - abstract class MakeGreenAction implements TransformAction { + abstract class MakeGreen implements TransformAction { @InjectTransformParameters - abstract MakeGreen getParameters() + abstract MakeGreenParameters getParameters() void transform(TransformOutputs outputs) { println "processing using " + parameters.prop.get() @@ -159,7 +159,7 @@ class ArtifactTransformValuesInjectionIntegrationTest extends AbstractDependency } } - interface MakeGreen { + interface MakeGreenParameters extends TransformParameters { String getExtension() void setExtension(String value) @OutputDirectory @@ -176,9 +176,9 @@ class ArtifactTransformValuesInjectionIntegrationTest extends AbstractDependency } @CacheableTransform - abstract class MakeGreenAction implements TransformAction { + abstract class MakeGreen implements TransformAction { @InjectTransformParameters - abstract MakeGreen getParameters() + abstract MakeGreenParameters getParameters() void transform(TransformOutputs outputs) { throw new RuntimeException() @@ -190,8 +190,8 @@ class ArtifactTransformValuesInjectionIntegrationTest extends AbstractDependency fails(":a:resolve") then: - failure.assertThatDescription(matchesRegexp('Cannot isolate parameters MakeGreen\\$Inject@.* of artifact transform MakeGreenAction')) - failure.assertHasCause('Some problems were found with the configuration of the artifact transform parameter MakeGreen.') + failure.assertThatDescription(matchesRegexp('Cannot isolate parameters MakeGreenParameters\\$Inject@.* of artifact transform MakeGreen')) + failure.assertHasCause('Some problems were found with the configuration of the artifact transform parameter MakeGreenParameters.') failure.assertHasCause("Property 'extension' is not annotated with an input annotation.") failure.assertHasCause("Property 'outputDir' is annotated with unsupported annotation @OutputDirectory.") failure.assertHasCause("Property 'missingInput' does not have a value specified.") @@ -217,7 +217,7 @@ class ArtifactTransformValuesInjectionIntegrationTest extends AbstractDependency } } - interface MakeGreen { + interface MakeGreenParameters extends TransformParameters { @Input String getExtension() void setExtension(String value) @@ -226,9 +226,9 @@ class ArtifactTransformValuesInjectionIntegrationTest extends AbstractDependency void setBad(String value) } - abstract class MakeGreenAction implements TransformAction { + abstract class MakeGreen implements TransformAction { @InjectTransformParameters - abstract MakeGreen getParameters() + abstract MakeGreenParameters getParameters() void transform(TransformOutputs outputs) { throw new RuntimeException() @@ -240,8 +240,8 @@ class ArtifactTransformValuesInjectionIntegrationTest extends AbstractDependency fails(":a:resolve") then: - failure.assertThatDescription(matchesRegexp('Cannot isolate parameters MakeGreen\\$Inject@.* of artifact transform MakeGreenAction')) - failure.assertHasCause('A problem was found with the configuration of the artifact transform parameter MakeGreen.') + failure.assertThatDescription(matchesRegexp('Cannot isolate parameters MakeGreenParameters\\$Inject@.* of artifact transform MakeGreen')) + failure.assertHasCause('A problem was found with the configuration of the artifact transform parameter MakeGreenParameters.') failure.assertHasCause("Property 'bad' is annotated with unsupported annotation @${annotation.simpleName}.") where: @@ -266,7 +266,7 @@ class ArtifactTransformValuesInjectionIntegrationTest extends AbstractDependency } } - interface MakeGreen { + interface MakeGreenParameters extends TransformParameters { String getExtension() void setExtension(String value) @${annotation.simpleName} @@ -274,9 +274,9 @@ class ArtifactTransformValuesInjectionIntegrationTest extends AbstractDependency void setBad(String value) } - abstract class MakeGreenAction implements TransformAction { + abstract class MakeGreen implements TransformAction { @InjectTransformParameters - abstract MakeGreen getParameters() + abstract MakeGreenParameters getParameters() void transform(TransformOutputs outputs) { throw new RuntimeException() @@ -289,9 +289,9 @@ class ArtifactTransformValuesInjectionIntegrationTest extends AbstractDependency then: failure.assertHasDescription('A problem occurred evaluating root project') - failure.assertHasCause('Could not create an instance of type MakeGreen.') - failure.assertHasCause('Could not generate a decorated class for interface MakeGreen.') - failure.assertHasCause("Cannot use @${annotation.simpleName} annotation on method MakeGreen.getBad().") + failure.assertHasCause('Could not create an instance of type MakeGreenParameters.') + failure.assertHasCause('Could not generate a decorated class for interface MakeGreenParameters.') + failure.assertHasCause("Cannot use @${annotation.simpleName} annotation on method MakeGreenParameters.getBad().") where: annotation << [InputArtifact, InputArtifactDependencies, InjectTransformParameters] @@ -314,16 +314,16 @@ class ArtifactTransformValuesInjectionIntegrationTest extends AbstractDependency } } - interface MakeGreen { + interface MakeGreenParameters extends TransformParameters { @Input String getExtension() void setExtension(String value) } @CacheableTransform - abstract class MakeGreenAction implements TransformAction { + abstract class MakeGreen implements TransformAction { @InjectTransformParameters - abstract MakeGreen getParameters() + abstract MakeGreenParameters getParameters() @InputFile File inputFile @@ -352,7 +352,7 @@ class ArtifactTransformValuesInjectionIntegrationTest extends AbstractDependency then: failure.assertHasDescription('A problem occurred evaluating root project') - failure.assertHasCause('Some problems were found with the configuration of MakeGreenAction.') + failure.assertHasCause('Some problems were found with the configuration of MakeGreen.') failure.assertHasCause("Property 'conflictingAnnotations' is annotated with unsupported annotation @InputFile.") failure.assertHasCause("Property 'conflictingAnnotations' has conflicting property types declared: @InputArtifact, @InputArtifactDependencies.") failure.assertHasCause("Property 'inputFile' is annotated with unsupported annotation @InputFile.") @@ -379,13 +379,13 @@ class ArtifactTransformValuesInjectionIntegrationTest extends AbstractDependency } } - interface MakeGreen { + interface MakeGreenParameters extends TransformParameters { @Input String getExtension() void setExtension(String value) } - abstract class MakeGreenAction implements TransformAction { + abstract class MakeGreen implements TransformAction { @${annotation.simpleName} String getBad() { } @@ -400,7 +400,7 @@ class ArtifactTransformValuesInjectionIntegrationTest extends AbstractDependency then: failure.assertHasDescription('A problem occurred evaluating root project') - failure.assertHasCause('A problem was found with the configuration of MakeGreenAction.') + failure.assertHasCause('A problem was found with the configuration of MakeGreen.') failure.assertHasCause("Property 'bad' is annotated with unsupported annotation @${annotation.simpleName}.") where: @@ -426,7 +426,7 @@ project(':b') { } } -abstract class MakeGreen implements TransformAction { +abstract class MakeGreen implements TransformAction { @InputArtifactDependencies abstract ${targetType} getDependencies() @InputArtifact @@ -518,17 +518,17 @@ abstract class MakeGreen extends ArtifactTransform { } } - interface MakeGreen { + interface MakeGreenParameters extends TransformParameters { @Input String getExtension() void setExtension(String value) } - class MakeGreenAction implements TransformAction { - private MakeGreen conf + class MakeGreen implements TransformAction { + private MakeGreenParameters conf @Inject - MakeGreenAction(MakeGreen conf) { + MakeGreen(MakeGreenParameters conf) { this.conf = conf } @@ -543,8 +543,8 @@ abstract class MakeGreen extends ArtifactTransform { then: // Documents existing behaviour. Should fail eagerly and with a better error message failure.assertHasDescription("Execution failed for task ':a:resolve'.") - failure.assertHasCause("Execution failed for MakeGreenAction: ${file('b/build/b.jar')}.") - failure.assertHasCause("Unable to determine constructor argument #1: missing parameter of interface MakeGreen, or no service of type interface MakeGreen") + failure.assertHasCause("Execution failed for MakeGreen: ${file('b/build/b.jar')}.") + failure.assertHasCause("Unable to determine constructor argument #1: missing parameter of interface MakeGreenParameters, or no service of type interface MakeGreenParameters") } @Unroll @@ -561,7 +561,7 @@ project(':a') { } } -abstract class MakeGreen implements TransformAction { +abstract class MakeGreen implements TransformAction { @InputArtifact abstract FileCollection getDependencies() @@ -595,7 +595,7 @@ project(':a') { } } -abstract class MakeGreen implements TransformAction { +abstract class MakeGreen implements TransformAction { @Inject abstract File getWorkspace() diff --git a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformWithDependenciesIntegrationTest.groovy b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformWithDependenciesIntegrationTest.groovy index 93c42d729ecfa..90f157ab62350 100644 --- a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformWithDependenciesIntegrationTest.groovy +++ b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformWithDependenciesIntegrationTest.groovy @@ -53,7 +53,7 @@ class ArtifactTransformWithDependenciesIntegrationTest extends AbstractHttpDepen setupBuildWithColorAttributes(cl) buildFile << """ -interface TestTransform { +interface TestTransformParameters extends TransformParameters { @Input String getTransformName() void setTransformName(String name) @@ -107,10 +107,10 @@ project(':app') { import javax.inject.Inject -abstract class TestTransformAction implements TransformAction { +abstract class TestTransform implements TransformAction { @InjectTransformParameters - abstract TestTransform getParameters() + abstract TestTransformParameters getParameters() @InputArtifactDependencies abstract FileCollection getInputArtifactDependencies() @@ -130,7 +130,7 @@ abstract class TestTransformAction implements TransformAction { } } -abstract class SimpleTransform implements TransformAction { +abstract class SimpleTransform implements TransformAction { @InputArtifact abstract File getInput() @@ -154,7 +154,7 @@ abstract class SimpleTransform implements TransformAction { buildFile << """ allprojects { dependencies { - registerTransformAction(TestTransformAction) { + registerTransformAction(TestTransform) { from.attribute(color, 'blue') to.attribute(color, 'green') parameters { @@ -176,7 +176,7 @@ allprojects { from.attribute(color, 'blue') to.attribute(color, 'yellow') } - registerTransformAction(TestTransformAction) { + registerTransformAction(TestTransform) { from.attribute(color, 'yellow') to.attribute(color, 'green') parameters { @@ -194,14 +194,14 @@ allprojects { allprojects { dependencies { // Multi step transform - registerTransformAction(TestTransformAction) { + registerTransformAction(TestTransform) { from.attribute(color, 'blue') to.attribute(color, 'yellow') parameters { transformName = 'Transform step 1' } } - registerTransformAction(TestTransformAction) { + registerTransformAction(TestTransform) { from.attribute(color, 'yellow') to.attribute(color, 'green') parameters { @@ -412,14 +412,14 @@ project(':common') { buildFile << """ allprojects { dependencies { - registerTransformAction(NoneTransformAction) { + registerTransformAction(NoneTransform) { from.attribute(color, 'blue') to.attribute(color, 'green') } } } -abstract class NoneTransformAction implements TransformAction { +abstract class NoneTransform implements TransformAction { @InputArtifactDependencies @PathSensitive(PathSensitivity.NONE) abstract FileCollection getInputArtifactDependencies() @@ -508,14 +508,14 @@ abstract class NoneTransformAction implements TransformAction { buildFile << """ allprojects { dependencies { - registerTransformAction(ClasspathTransformAction) { + registerTransformAction(ClasspathTransform) { from.attribute(color, 'blue') to.attribute(color, 'green') } } } -abstract class ClasspathTransformAction implements TransformAction { +abstract class ClasspathTransform implements TransformAction { @InputArtifactDependencies @${classpathAnnotation.simpleName} abstract FileCollection getInputArtifactDependencies() diff --git a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformWithFileInputsIntegrationTest.groovy b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformWithFileInputsIntegrationTest.groovy index 55830953d47ab..44cc1742a338d 100644 --- a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformWithFileInputsIntegrationTest.groovy +++ b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformWithFileInputsIntegrationTest.groovy @@ -31,14 +31,14 @@ class ArtifactTransformWithFileInputsIntegrationTest extends AbstractDependencyR """) } buildFile << """ - interface MakeGreen { + interface MakeGreenParameters extends TransformParameters{ $inputAnnotations ConfigurableFileCollection getSomeFiles() } - abstract class MakeGreenAction implements TransformAction { + abstract class MakeGreen implements TransformAction { @InjectTransformParameters - abstract MakeGreen getParameters() + abstract MakeGreenParameters getParameters() @InputArtifact abstract File getInput() @@ -153,7 +153,7 @@ class ArtifactTransformWithFileInputsIntegrationTest extends AbstractDependencyR """ setupBuildWithTransformFileInputs() buildFile << """ - abstract class MakeRedAction implements TransformAction { + abstract class MakeRed implements TransformAction { @InputArtifact abstract File getInput() @@ -174,7 +174,7 @@ class ArtifactTransformWithFileInputsIntegrationTest extends AbstractDependencyR attributes.attribute(attr, 'red') }.files dependencies { - registerTransformAction(MakeRedAction) { + registerTransformAction(MakeRed) { from.attribute(color, 'blue') to.attribute(color, 'red') } @@ -283,14 +283,14 @@ class ArtifactTransformWithFileInputsIntegrationTest extends AbstractDependencyR } } - interface MakeGreen { + interface MakeGreenParameters extends TransformParameters { @InputFile RegularFileProperty getSomeFile() } - abstract class MakeGreenAction implements TransformAction { + abstract class MakeGreen implements TransformAction { @InjectTransformParameters - abstract MakeGreen getParameters() + abstract MakeGreenParameters getParameters() @InputArtifact abstract File getInput() @@ -336,14 +336,14 @@ class ArtifactTransformWithFileInputsIntegrationTest extends AbstractDependencyR } } - interface MakeGreen { + interface MakeGreenParameters extends TransformParameters { @InputDirectory DirectoryProperty getSomeDir() } - abstract class MakeGreenAction implements TransformAction { + abstract class MakeGreen implements TransformAction { @InjectTransformParameters - abstract MakeGreen getParameters() + abstract MakeGreenParameters getParameters() @InputArtifact abstract File getInput() diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/VariantTransformRegistry.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/VariantTransformRegistry.java index dcdd6b90c6f51..8e6e42d3efb72 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/VariantTransformRegistry.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/VariantTransformRegistry.java @@ -19,6 +19,7 @@ import org.gradle.api.Action; import org.gradle.api.artifacts.transform.ParameterizedTransformSpec; import org.gradle.api.artifacts.transform.TransformAction; +import org.gradle.api.artifacts.transform.TransformParameters; import org.gradle.api.artifacts.transform.VariantTransform; public interface VariantTransformRegistry { @@ -32,7 +33,7 @@ public interface VariantTransformRegistry { void registerTransform(Class parameterType, Action> registrationAction); - void registerTransformAction(Class> actionType, Action> registrationAction); + void registerTransformAction(Class> actionType, Action> registrationAction); Iterable getTransforms(); } diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/dsl/dependencies/DefaultDependencyHandler.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/dsl/dependencies/DefaultDependencyHandler.java index e22f4cd237b7a..840bac0692af8 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/dsl/dependencies/DefaultDependencyHandler.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/dsl/dependencies/DefaultDependencyHandler.java @@ -29,6 +29,7 @@ import org.gradle.api.artifacts.query.ArtifactResolutionQuery; import org.gradle.api.artifacts.transform.ParameterizedTransformSpec; import org.gradle.api.artifacts.transform.TransformAction; +import org.gradle.api.artifacts.transform.TransformParameters; import org.gradle.api.artifacts.transform.VariantTransform; import org.gradle.api.artifacts.type.ArtifactTypeContainer; import org.gradle.api.attributes.AttributesSchema; @@ -219,7 +220,7 @@ public void registerTransform(Class parameterType, Action void registerTransformAction(Class> actionType, Action> registrationAction) { + public void registerTransformAction(Class> actionType, Action> registrationAction) { transforms.registerTransformAction(actionType, registrationAction); } diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultVariantTransformRegistry.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultVariantTransformRegistry.java index 625a7441aa815..cda198b01dafb 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultVariantTransformRegistry.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultVariantTransformRegistry.java @@ -25,6 +25,7 @@ import org.gradle.api.artifacts.transform.AssociatedTransformAction; import org.gradle.api.artifacts.transform.ParameterizedTransformSpec; import org.gradle.api.artifacts.transform.TransformAction; +import org.gradle.api.artifacts.transform.TransformParameters; import org.gradle.api.artifacts.transform.TransformSpec; import org.gradle.api.artifacts.transform.VariantTransform; import org.gradle.api.artifacts.transform.VariantTransformConfigurationException; @@ -89,10 +90,10 @@ public void registerTransform(Class parameterType, Action void registerTransformAction(Class> actionType, Action> registrationAction) { + public void registerTransformAction(Class> actionType, Action> registrationAction) { ParameterizedType superType = (ParameterizedType) TypeToken.of(actionType).getSupertype(TransformAction.class).getType(); Class parameterType = Cast.uncheckedNonnullCast(TypeToken.of(superType.getActualTypeArguments()[0]).getRawType()); - T parameterObject = (Object.class.equals(parameterType) || Void.class.isAssignableFrom(parameterType)) ? null : parametersInstantiationScheme.withServices(services).newInstance(parameterType); + T parameterObject = parameterType == TransformParameters.class ? null : parametersInstantiationScheme.withServices(services).newInstance(parameterType); TypedRegistration registration = Cast.uncheckedNonnullCast(instantiatorFactory.decorateLenient().newInstance(TypedRegistration.class, parameterObject, immutableAttributesFactory)); registrationAction.execute(registration); diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/UnzipTransform.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/UnzipTransform.java index 823f9eecca085..be795426a87f0 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/UnzipTransform.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/UnzipTransform.java @@ -21,6 +21,7 @@ import org.gradle.api.artifacts.transform.InputArtifact; import org.gradle.api.artifacts.transform.TransformAction; import org.gradle.api.artifacts.transform.TransformOutputs; +import org.gradle.api.artifacts.transform.TransformParameters; import org.gradle.internal.UncheckedException; import java.io.BufferedInputStream; @@ -38,7 +39,7 @@ * is located in the output directory of the transform and is named after the zipped file name * minus the extension. */ -public interface UnzipTransform extends TransformAction { +public interface UnzipTransform extends TransformAction { @InputArtifact File getZippedFile(); diff --git a/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/DefaultVariantTransformRegistryTest.groovy b/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/DefaultVariantTransformRegistryTest.groovy index 801f8a0f25723..cf35924c24443 100644 --- a/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/DefaultVariantTransformRegistryTest.groovy +++ b/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/DefaultVariantTransformRegistryTest.groovy @@ -16,10 +16,14 @@ package org.gradle.api.internal.artifacts.transform - +import com.google.common.collect.ImmutableSet import org.gradle.api.artifacts.transform.ArtifactTransform +import org.gradle.api.artifacts.transform.InjectTransformParameters +import org.gradle.api.artifacts.transform.InputArtifact +import org.gradle.api.artifacts.transform.InputArtifactDependencies import org.gradle.api.artifacts.transform.TransformAction import org.gradle.api.artifacts.transform.TransformOutputs +import org.gradle.api.artifacts.transform.TransformParameters import org.gradle.api.artifacts.transform.VariantTransformConfigurationException import org.gradle.api.attributes.Attribute import org.gradle.api.internal.DynamicObjectAware @@ -60,7 +64,7 @@ class DefaultVariantTransformRegistryTest extends Specification { def classLoaderHierarchyHasher = Mock(ClassLoaderHierarchyHasher) def attributesFactory = AttributeTestUtil.attributesFactory() def domainObjectContextProjectStateHandler = Mock(DomainObjectProjectStateHandler) - def registryFactory = new DefaultTransformationRegistrationFactory(isolatableFactory, classLoaderHierarchyHasher, transformerInvoker, valueSnapshotter, fileCollectionFactory, fileCollectionFingerprinterRegistry, domainObjectContextProjectStateHandler, new ArtifactTransformParameterScheme(instantiatorFactory.injectScheme(), inspectionScheme), new ArtifactTransformActionScheme(instantiatorFactory.injectScheme(), inspectionScheme, instantiatorFactory.injectScheme())) + def registryFactory = new DefaultTransformationRegistrationFactory(isolatableFactory, classLoaderHierarchyHasher, transformerInvoker, valueSnapshotter, fileCollectionFactory, fileCollectionFingerprinterRegistry, domainObjectContextProjectStateHandler, new ArtifactTransformParameterScheme(instantiatorFactory.injectScheme(), inspectionScheme), new ArtifactTransformActionScheme(instantiatorFactory.injectScheme(ImmutableSet.of(InputArtifact.class, InputArtifactDependencies.class, InjectTransformParameters.class)), inspectionScheme, instantiatorFactory.injectScheme())) def registry = new DefaultVariantTransformRegistry(instantiatorFactory, attributesFactory, Stub(ServiceRegistry), registryFactory, instantiatorFactory.injectScheme()) def "setup"() { @@ -126,7 +130,7 @@ class DefaultVariantTransformRegistryTest extends Specification { def "creates registration with annotated parameters object"() { when: - registry.registerTransformAction(TestTransformAction) { + registry.registerTransformAction(TestTransform) { it.from.attribute(TEST_ATTRIBUTE, "FROM") it.to.attribute(TEST_ATTRIBUTE, "TO") } @@ -136,13 +140,13 @@ class DefaultVariantTransformRegistryTest extends Specification { def registration = registry.transforms[0] registration.from.getAttribute(TEST_ATTRIBUTE) == "FROM" registration.to.getAttribute(TEST_ATTRIBUTE) == "TO" - registration.transformationStep.transformer.implementationClass == TestTransformAction - registration.transformationStep.transformer.parameterObject instanceof TestTransform + registration.transformationStep.transformer.implementationClass == TestTransform + registration.transformationStep.transformer.parameterObject instanceof TestParameters } def "creates registration for parametereless action"() { when: - registry.registerTransformAction(ParameterlessTestTransformAction) { + registry.registerTransformAction(ParameterlessTestTransform) { it.from.attribute(TEST_ATTRIBUTE, "FROM") it.to.attribute(TEST_ATTRIBUTE, "TO") } @@ -152,13 +156,13 @@ class DefaultVariantTransformRegistryTest extends Specification { def registration = registry.transforms[0] registration.from.getAttribute(TEST_ATTRIBUTE) == "FROM" registration.to.getAttribute(TEST_ATTRIBUTE) == "TO" - registration.transformationStep.transformer.implementationClass == ParameterlessTestTransformAction + registration.transformationStep.transformer.implementationClass == ParameterlessTestTransform registration.transformationStep.transformer.parameterObject == null } def "cannot configure parameters for parameterless action"() { when: - registry.registerTransformAction(ParameterlessTestTransformAction) { + registry.registerTransformAction(ParameterlessTestTransform) { it.from.attribute(TEST_ATTRIBUTE, "FROM") it.to.attribute(TEST_ATTRIBUTE, "TO") it.parameters { @@ -173,7 +177,7 @@ class DefaultVariantTransformRegistryTest extends Specification { def "cannot query parameters object for parameterless action"() { when: - registry.registerTransformAction(ParameterlessTestTransformAction) { + registry.registerTransformAction(ParameterlessTestTransform) { it.from.attribute(TEST_ATTRIBUTE, "FROM") it.to.attribute(TEST_ATTRIBUTE, "TO") it.parameters @@ -189,7 +193,7 @@ class DefaultVariantTransformRegistryTest extends Specification { def registration when: - registry.registerTransformAction(TestTransformAction) { + registry.registerTransformAction(TestTransform) { it.from.attribute(TEST_ATTRIBUTE, "FROM") it.to.attribute(TEST_ATTRIBUTE, "TO") registration = it @@ -267,7 +271,7 @@ class DefaultVariantTransformRegistryTest extends Specification { def "fails when no from attributes are provided for registerTransformAction"() { when: - registry.registerTransformAction(TestTransformAction) { + registry.registerTransformAction(TestTransform) { it.to.attribute(TEST_ATTRIBUTE, "to") } @@ -292,7 +296,7 @@ class DefaultVariantTransformRegistryTest extends Specification { def "fails when no to attributes are provided for registerTransformAction"() { when: - registry.registerTransformAction(TestTransformAction) { + registry.registerTransformAction(TestTransform) { it.from.attribute(TEST_ATTRIBUTE, "from") } @@ -320,7 +324,7 @@ class DefaultVariantTransformRegistryTest extends Specification { def "fails when to attributes are not a subset of from attributes for registerTransformAction"() { when: - registry.registerTransformAction(TestTransformAction) { + registry.registerTransformAction(TestTransform) { it.from.attribute(TEST_ATTRIBUTE, "from") it.from.attribute(Attribute.of("from2", String), "from") it.to.attribute(TEST_ATTRIBUTE, "to") @@ -333,7 +337,7 @@ class DefaultVariantTransformRegistryTest extends Specification { e.cause == null } - static class TestTransform { + static class TestParameters implements TransformParameters { String value } @@ -348,13 +352,13 @@ class DefaultVariantTransformRegistryTest extends Specification { } } - static class TestTransformAction implements TransformAction { + static class TestTransform implements TransformAction { @Override void transform(TransformOutputs outputs) { } } - static class ParameterlessTestTransformAction implements TransformAction { + static class ParameterlessTestTransform implements TransformAction { @Override void transform(TransformOutputs outputs) { } diff --git a/subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/AbstractConsoleBuildPhaseFunctionalTest.groovy b/subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/AbstractConsoleBuildPhaseFunctionalTest.groovy index f498cb58d519a..dfbfd6bf6b050 100644 --- a/subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/AbstractConsoleBuildPhaseFunctionalTest.groovy +++ b/subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/AbstractConsoleBuildPhaseFunctionalTest.groovy @@ -326,15 +326,15 @@ abstract class AbstractConsoleBuildPhaseFunctionalTest extends AbstractIntegrati def usage = Attribute.of('usage', String) def artifactType = Attribute.of('artifactType', String) - interface FileSizer { + interface FileSizerParameters extends TransformParameters { @Input String getSuffix() void setSuffix(String suffix) } - abstract class FileSizerAction implements TransformAction { + abstract class FileSizer implements TransformAction { @InjectTransformParameters - abstract FileSizer getParameters() + abstract FileSizerParameters getParameters() @InputArtifactDependencies abstract FileCollection getDependencies() @InputArtifact @@ -389,7 +389,7 @@ abstract class AbstractConsoleBuildPhaseFunctionalTest extends AbstractIntegrati to.attribute(artifactType, "double") artifactTransform(FileDoubler) } - registerTransformAction(FileSizerAction) { + registerTransformAction(FileSizer) { from.attribute(artifactType, "double") to.attribute(artifactType, "size") parameters { From a0d87fbde3d227bb8a1a9fbcc640a6be856a7312 Mon Sep 17 00:00:00 2001 From: "Rodrigo B. de Oliveira" Date: Mon, 25 Feb 2019 18:55:05 -0300 Subject: [PATCH 126/853] Emit type-safe accessors for precompiled script plugins --- .../PrecompiledScriptPluginAccessorsTest.kt | 2 - .../precompiled/PrecompiledScriptPlugin.kt | 6 +- .../precompiled/PrecompiledScriptPlugins.kt | 76 ++++++++++++------- ...eneratePrecompiledScriptPluginAccessors.kt | 33 +++++--- .../kotlin/dsl/accessors/AccessorFragment.kt | 4 +- .../kotlin/dsl/accessors/AccessorFragments.kt | 8 +- .../dsl/accessors/AccessorsClassPath.kt | 12 +-- .../gradle/kotlin/dsl/accessors/Emitter.kt | 30 ++++++-- .../PrecompiledScriptDependenciesResolver.kt | 24 ++++-- 9 files changed, 124 insertions(+), 71 deletions(-) diff --git a/subprojects/kotlin-dsl-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPluginAccessorsTest.kt b/subprojects/kotlin-dsl-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPluginAccessorsTest.kt index b18155db60d50..bd5d04ce541a5 100644 --- a/subprojects/kotlin-dsl-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPluginAccessorsTest.kt +++ b/subprojects/kotlin-dsl-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPluginAccessorsTest.kt @@ -42,7 +42,6 @@ import org.hamcrest.CoreMatchers.allOf import org.hamcrest.CoreMatchers.containsString import org.hamcrest.MatcherAssert.assertThat -import org.junit.Ignore import org.junit.Test import java.io.File @@ -50,7 +49,6 @@ import java.io.File class PrecompiledScriptPluginAccessorsTest : AbstractPrecompiledScriptPluginTest() { - @Ignore("wip") @Test fun `can use type-safe accessors with same name but different meaning in sibling plugins`() { diff --git a/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPlugin.kt b/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPlugin.kt index 1e49212d3bb7a..2b8155a70e873 100644 --- a/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPlugin.kt +++ b/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPlugin.kt @@ -100,11 +100,7 @@ data class PrecompiledScriptPlugin(internal val scriptFile: File) { } val hashString by lazy { - hash.toString() - } - - val hash by lazy { - Hashing.hashString(scriptText) + Hashing.hashString(scriptText).toString() } val scriptText: String diff --git a/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPlugins.kt b/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPlugins.kt index 4dbcd78b7f1e4..5cbfaa2496f85 100644 --- a/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPlugins.kt +++ b/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPlugins.kt @@ -26,7 +26,6 @@ import org.gradle.api.provider.Provider import org.gradle.api.tasks.SourceSet import org.gradle.api.tasks.SourceSetContainer -import org.gradle.api.tasks.TaskProvider import org.gradle.kotlin.dsl.* import org.gradle.kotlin.dsl.plugins.precompiled.tasks.CompilePrecompiledScriptPluginPlugins @@ -198,26 +197,58 @@ fun Project.enableScriptCompilationOf(scriptPlugins: List( + "accessors", + "generatePrecompiledScriptPluginAccessors" + ) { + dependsOn(compilePluginsBlocks) + classPathFiles = compileClasspath + sourceCodeOutputDir.set(it) + metadataOutputDir.set(generatedMetadata) + compiledPluginsBlocksDir.set(compiledPluginsBlocks) + plugins = scriptPlugins + } + + val configurePrecompiledScriptPluginImports by registering { + inputs.files( + project.files(generatedMetadata).builtBy(generatePrecompiledScriptPluginAccessors) + ) } - named("compileKotlin") { + val compileKotlin by existing(KotlinCompile::class) { dependsOn(generatePrecompiledScriptPluginAccessors) dependsOn(generateInternalPluginSpecBuilders) dependsOn(generateExternalPluginSpecBuilders) - kotlinOptions { - freeCompilerArgs += listOf( - "-script-templates", scriptTemplates, - // Propagate implicit imports and other settings - "-Xscript-resolver-environment=${resolverEnvironmentFor(generatePrecompiledScriptPluginAccessors)}" + dependsOn(configurePrecompiledScriptPluginImports) + } + + configurePrecompiledScriptPluginImports { + doLast { + + val metadataDir = generatedMetadata.get().asFile + require(metadataDir.isDirectory) + + val precompiledScriptPluginImports = + metadataDir.listFiles().map { + it.name to it.readLines() + } + + val resolverEnvironment = resolverEnvironmentStringFor( + listOf( + PrecompiledScriptDependenciesResolver.EnvironmentProperties.kotlinDslImplicitImports to implicitImports() + ) + precompiledScriptPluginImports ) + + compileKotlin.get().apply { + kotlinOptions { + freeCompilerArgs += listOf( + "-script-templates", scriptTemplates, + // Propagate implicit imports and other settings + "-Xscript-resolver-environment=$resolverEnvironment" + ) + } + } } } } @@ -228,14 +259,6 @@ private fun Project.compileClasspath() = sourceSets["main"].compileClasspath -private -fun Project.resolverEnvironmentFor( - accessors: TaskProvider -) = resolverEnvironment( - implicitImports() // + (accessors.get().kotlinPackageName + ".*") -) - - private val scriptTemplates by lazy { listOf( @@ -250,9 +273,10 @@ val scriptTemplates by lazy { private -fun resolverEnvironment(implicitImports: List) = - (PrecompiledScriptDependenciesResolver.EnvironmentProperties.kotlinDslImplicitImports - + "=\"" + implicitImports.joinToString(separator = ":") + "\"") +fun resolverEnvironmentStringFor(properties: Iterable>>): String = + properties.joinToString(separator = ",") { (key, values) -> + "$key=\"${values.joinToString(":")}\"" + } internal diff --git a/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/GeneratePrecompiledScriptPluginAccessors.kt b/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/GeneratePrecompiledScriptPluginAccessors.kt index 432410fa2e670..69e599a815d74 100644 --- a/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/GeneratePrecompiledScriptPluginAccessors.kt +++ b/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/GeneratePrecompiledScriptPluginAccessors.kt @@ -38,6 +38,7 @@ import org.gradle.internal.hash.HashCode import org.gradle.internal.resource.BasicTextResourceLoader import org.gradle.kotlin.dsl.accessors.TypedProjectSchema +import org.gradle.kotlin.dsl.accessors.buildAccessorsFor import org.gradle.kotlin.dsl.accessors.hashCodeFor import org.gradle.kotlin.dsl.accessors.schemaFor @@ -205,18 +206,28 @@ open class GeneratePrecompiledScriptPluginAccessors : ClassPathSensitiveCodeGene private fun projectSchemaImpliedByPluginGroups( pluginGroupsPerRequests: Map> - ): Iterable>> { + ): Map> { val schemaBuilder = SyntheticProjectSchemaBuilder(temporaryDir, classPathFiles.files) - return pluginGroupsPerRequests.map { (uniquePluginRequests, scriptPlugins) -> + return pluginGroupsPerRequests.flatMap { (uniquePluginRequests, scriptPlugins) -> val schema = schemaBuilder.schemaFor(uniquePluginRequests.plugins) - HashedProjectSchema(schema) to scriptPlugins - } + val hashedSchema = HashedProjectSchema(schema) + scriptPlugins.map { hashedSchema to it } + }.groupBy( + { (schema, _) -> schema }, + { (_, plugin) -> plugin } + ) } private - fun IO.writeTypeSafeAccessorsFor(projectSchema: HashedProjectSchema) { - println(projectSchema) + fun IO.writeTypeSafeAccessorsFor(hashedSchema: HashedProjectSchema) { + buildAccessorsFor( + hashedSchema.schema, + classPath, + sourceCodeOutputDir.get().asFile, + temporaryDir.resolve("accessors"), + hashedSchema.packageName + ) } private @@ -273,7 +284,7 @@ class SyntheticProjectSchemaBuilder(rootProjectDir: File, rootProjectClassPath: DefaultSelfResolvingDependency( project .serviceOf() - .fixed("kotlin-dsl-accessors-classpath", rootProjectClassPath) as FileCollectionInternal + .fixed("precompiled-script-plugins-accessors-classpath", rootProjectClassPath) as FileCollectionInternal ) ) } @@ -299,7 +310,7 @@ data class HashedProjectSchema( val hash: HashCode = hashCodeFor(schema) ) { val packageName by lazy { - kotlinPackageNameFor("gradle-kotlin-dsl.type-safe-accessors.$$hash") + "gradle.kotlin.dsl.accessors._$hash" } override fun hashCode(): Int = hash.hashCode() @@ -320,11 +331,9 @@ class UniquePluginRequests(val plugins: PluginRequests) { val applications = plugins.map { it.toPluginApplication() } - override fun equals(other: Any?): Boolean = - other is UniquePluginRequests && applications == other.applications + override fun equals(other: Any?): Boolean = other is UniquePluginRequests && applications == other.applications - override fun hashCode(): Int = - applications.hashCode() + override fun hashCode(): Int = applications.hashCode() } diff --git a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/accessors/AccessorFragment.kt b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/accessors/AccessorFragment.kt index c972dbc38a691..586d2c113dc9f 100644 --- a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/accessors/AccessorFragment.kt +++ b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/accessors/AccessorFragment.kt @@ -21,8 +21,6 @@ import kotlinx.metadata.jvm.KotlinClassMetadata import org.gradle.internal.classanalysis.AsmConstants.ASM_LEVEL -import org.gradle.kotlin.dsl.support.bytecode.InternalName - import org.jetbrains.org.objectweb.asm.ClassVisitor import org.jetbrains.org.objectweb.asm.ClassWriter @@ -59,4 +57,4 @@ data class MetadataFragmentScope( internal -typealias Fragments = Pair> +typealias Fragments = Pair> diff --git a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/accessors/AccessorFragments.kt b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/accessors/AccessorFragments.kt index 1ac353aae5432..1eb879094dfff 100644 --- a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/accessors/AccessorFragments.kt +++ b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/accessors/AccessorFragments.kt @@ -25,8 +25,6 @@ import org.gradle.api.reflect.TypeOf import org.gradle.internal.hash.HashUtil -import org.gradle.kotlin.dsl.codegen.kotlinDslPackagePath - import org.gradle.kotlin.dsl.support.bytecode.ALOAD import org.gradle.kotlin.dsl.support.bytecode.ARETURN import org.gradle.kotlin.dsl.support.bytecode.CHECKCAST @@ -68,7 +66,7 @@ private fun fragmentsForConfiguration(accessor: Accessor.ForConfiguration): Fragments = accessor.run { val propertyName = name.original - val className = InternalName("$kotlinDslPackagePath/${propertyName.capitalize()}ConfigurationAccessorsKt") + val className = "${propertyName.capitalize()}ConfigurationAccessorsKt" className to sequenceOf( AccessorFragment( @@ -802,8 +800,8 @@ val kotlinPrimitiveTypes = primitiveTypeStrings.asSequence().map { (jvmName, kot private -fun internalNameForAccessorClassOf(accessorSpec: TypedAccessorSpec): InternalName = - InternalName("$kotlinDslPackagePath/Accessors${hashOf(accessorSpec)}Kt") +fun internalNameForAccessorClassOf(accessorSpec: TypedAccessorSpec): String = + "Accessors${hashOf(accessorSpec)}Kt" private diff --git a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/accessors/AccessorsClassPath.kt b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/accessors/AccessorsClassPath.kt index 729e36392f34a..69235ebd58265 100644 --- a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/accessors/AccessorsClassPath.kt +++ b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/accessors/AccessorsClassPath.kt @@ -148,18 +148,19 @@ private fun scriptCacheOf(project: Project) = project.serviceOf() -internal fun IO.buildAccessorsFor( projectSchema: TypedProjectSchema, classPath: ClassPath, srcDir: File, - binDir: File + binDir: File, + packageName: String = kotlinDslPackageName ) { val availableSchema = availableProjectSchemaFor(projectSchema, classPath) emitAccessorsFor( availableSchema, srcDir, - binDir + binDir, + OutputPackage(packageName) ) } @@ -518,10 +519,11 @@ internal fun IO.writeAccessorsTo( outputFile: File, accessors: List, - imports: List = emptyList() + imports: List = emptyList(), + packageName: String = kotlinDslPackageName ) = io { outputFile.bufferedWriter().useToRun { - appendReproducibleNewLine(fileHeaderWithImportsFor(/* TODO: accept packageName here */)) + appendReproducibleNewLine(fileHeaderWithImportsFor(packageName)) if (imports.isNotEmpty()) { imports.forEach { appendReproducibleNewLine("import $it") diff --git a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/accessors/Emitter.kt b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/accessors/Emitter.kt index cbe5b4415497d..dc51c088eed34 100644 --- a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/accessors/Emitter.kt +++ b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/accessors/Emitter.kt @@ -19,8 +19,6 @@ package org.gradle.kotlin.dsl.accessors import org.gradle.api.NamedDomainObjectContainer import org.gradle.api.artifacts.Configuration -import org.gradle.kotlin.dsl.codegen.kotlinDslPackagePath - import org.gradle.kotlin.dsl.concurrent.IO import org.gradle.kotlin.dsl.concurrent.writeFile @@ -39,14 +37,15 @@ internal fun IO.emitAccessorsFor( projectSchema: ProjectSchema, srcDir: File, - binDir: File + binDir: File, + outputPackage: OutputPackage ): List { - makeAccessorOutputDirs(srcDir, binDir, kotlinDslPackagePath) + makeAccessorOutputDirs(srcDir, binDir, outputPackage.path) val emittedClassNames = accessorsFor(projectSchema).map { accessor -> - emitClassFor(accessor, srcDir, binDir) + emitClassFor(accessor, srcDir, binDir, outputPackage) }.toList() writeFile( @@ -66,10 +65,25 @@ fun IO.makeAccessorOutputDirs(srcDir: File, binDir: File, packagePath: String) = } +internal +data class OutputPackage(val name: String) { + + val path by lazy { + name.replace('.', '/') + } +} + + private -fun IO.emitClassFor(accessor: Accessor, srcDir: File, binDir: File): InternalName { +fun IO.emitClassFor( + accessor: Accessor, + srcDir: File, + binDir: File, + outputPackage: OutputPackage +): InternalName { - val (className, fragments) = fragmentsFor(accessor) + val (simpleClassName, fragments) = fragmentsFor(accessor) + val className = InternalName("${outputPackage.path}/$simpleClassName") val sourceCode = mutableListOf() val metadataWriter = beginFileFacadeClassHeader() val classWriter = beginPublicClass(className) @@ -81,7 +95,7 @@ fun IO.emitClassFor(accessor: Accessor, srcDir: File, binDir: File): InternalNam } val sourceFile = srcDir.resolve("${className.value.removeSuffix("Kt")}.kt") - writeAccessorsTo(sourceFile, sourceCode, importsRequiredBy(accessor)) + writeAccessorsTo(sourceFile, sourceCode, importsRequiredBy(accessor), outputPackage.name) val classHeader = metadataWriter.closeHeader() val classBytes = classWriter.endKotlinClass(classHeader) diff --git a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/precompile/PrecompiledScriptDependenciesResolver.kt b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/precompile/PrecompiledScriptDependenciesResolver.kt index b6dfb4e8c2079..6376957ae7a05 100644 --- a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/precompile/PrecompiledScriptDependenciesResolver.kt +++ b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/precompile/PrecompiledScriptDependenciesResolver.kt @@ -16,15 +16,17 @@ package org.gradle.kotlin.dsl.precompile +import org.gradle.internal.hash.Hashing + import org.gradle.kotlin.dsl.resolver.KotlinBuildScriptDependencies import java.util.concurrent.Future -import kotlin.script.dependencies.ScriptDependenciesResolver +import kotlin.script.dependencies.Environment +import kotlin.script.dependencies.KotlinScriptExternalDependencies import kotlin.script.dependencies.PseudoFuture import kotlin.script.dependencies.ScriptContents -import kotlin.script.dependencies.KotlinScriptExternalDependencies -import kotlin.script.dependencies.Environment +import kotlin.script.dependencies.ScriptDependenciesResolver class PrecompiledScriptDependenciesResolver : ScriptDependenciesResolver { @@ -42,7 +44,7 @@ class PrecompiledScriptDependenciesResolver : ScriptDependenciesResolver { PseudoFuture( KotlinBuildScriptDependencies( - imports = implicitImportsFrom(environment), + imports = implicitImportsFrom(environment) + precompiledScriptPluginImportsFrom(environment, script), classpath = emptyList(), sources = emptyList() ) @@ -50,6 +52,18 @@ class PrecompiledScriptDependenciesResolver : ScriptDependenciesResolver { private fun implicitImportsFrom(environment: Environment?) = - (environment?.get(EnvironmentProperties.kotlinDslImplicitImports) as? String)?.split(':') + environment.stringList(EnvironmentProperties.kotlinDslImplicitImports) + + private + fun precompiledScriptPluginImportsFrom(environment: Environment?, script: ScriptContents): List = + environment.stringList(Hashing.hashString(script.text).toString()) + + private + fun Environment?.stringList(key: String) = + string(key)?.split(':') ?: emptyList() + + private + fun Environment?.string(key: String) = + this?.get(key) as? String } From 2acec9193e55b0ab04a947ac9bb2b20a92168880 Mon Sep 17 00:00:00 2001 From: Stefan Wolf Date: Mon, 25 Feb 2019 23:10:42 +0100 Subject: [PATCH 127/853] Address more review feedback --- .../ArtifactTransformInputArtifactIntegrationTest.groovy | 4 ++-- .../api/internal/artifacts/transform/DefaultTransformer.java | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformInputArtifactIntegrationTest.groovy b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformInputArtifactIntegrationTest.groovy index c68cf6f8556ba..91f5c9ace7e58 100644 --- a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformInputArtifactIntegrationTest.groovy +++ b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformInputArtifactIntegrationTest.groovy @@ -1194,7 +1194,7 @@ class ArtifactTransformInputArtifactIntegrationTest extends AbstractDependencyRe when: executer.withArguments("-PbEntryName=ignored.txt") - succeeds(":a:resolve") + run(":a:resolve") then: result.assertTasksNotSkipped(":b:producer", ":c:producer", ":a:resolve") @@ -1203,7 +1203,7 @@ class ArtifactTransformInputArtifactIntegrationTest extends AbstractDependencyRe when: executer.withArguments("-PbEntryName=ignored.txt", "-PbContent=different") - succeeds(":a:resolve") + run(":a:resolve") then: // change is ignored due to normalization result.assertTasksNotSkipped(":b:producer", ":a:resolve") diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformer.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformer.java index a8ab939abc163..5e7cc013787ba 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformer.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformer.java @@ -366,8 +366,8 @@ public Object getValueToInject() { } private static class IsolatedParameters { - private HashCode secondaryInputsHash; - private Isolatable isolatedParameterObject; + private final HashCode secondaryInputsHash; + private final Isolatable isolatedParameterObject; public IsolatedParameters(Isolatable isolatedParameterObject, HashCode secondaryInputsHash) { this.secondaryInputsHash = secondaryInputsHash; From ac8917e3cede67b1511eda818459bbd2961a7e79 Mon Sep 17 00:00:00 2001 From: Sterling Greene Date: Mon, 25 Feb 2019 18:35:24 -0500 Subject: [PATCH 128/853] Move ReplacedBy to org.gradle.api Make sure we get an error if you combine two annotations with ReplacedBy --- .../source/model/AbstractLanguageElement.java | 2 +- .../gradle/api/{tasks => }/ReplacedBy.java | 8 ++-- .../properties/DefaultTypeMetadataStore.java | 13 +++---- .../tasks/bundling/AbstractArchiveTask.java | 9 +---- .../scopes/ExecutionGlobalServices.java | 4 +- .../DefaultTypeMetadataStoreTest.groovy | 4 +- .../src/docs/userguide/more_about_tasks.adoc | 2 +- ...lidateTaskPropertiesIntegrationTest.groovy | 37 +++++++++++++++++++ .../devel/tasks/ValidateTaskProperties.java | 2 +- 9 files changed, 57 insertions(+), 24 deletions(-) rename subprojects/core-api/src/main/java/org/gradle/api/{tasks => }/ReplacedBy.java (82%) diff --git a/buildSrc/subprojects/build/src/main/groovy/org/gradle/build/docs/dsl/source/model/AbstractLanguageElement.java b/buildSrc/subprojects/build/src/main/groovy/org/gradle/build/docs/dsl/source/model/AbstractLanguageElement.java index 7c63c8d629195..93afe04eda678 100644 --- a/buildSrc/subprojects/build/src/main/groovy/org/gradle/build/docs/dsl/source/model/AbstractLanguageElement.java +++ b/buildSrc/subprojects/build/src/main/groovy/org/gradle/build/docs/dsl/source/model/AbstractLanguageElement.java @@ -60,7 +60,7 @@ public boolean isIncubating() { } public boolean isReplaced() { - return annotationNames.contains("org.gradle.api.tasks.ReplacedBy"); + return annotationNames.contains("org.gradle.api.ReplacedBy"); } public String getReplacement() { diff --git a/subprojects/core-api/src/main/java/org/gradle/api/tasks/ReplacedBy.java b/subprojects/core-api/src/main/java/org/gradle/api/ReplacedBy.java similarity index 82% rename from subprojects/core-api/src/main/java/org/gradle/api/tasks/ReplacedBy.java rename to subprojects/core-api/src/main/java/org/gradle/api/ReplacedBy.java index eeb7c8704f474..2634a9ade74d5 100644 --- a/subprojects/core-api/src/main/java/org/gradle/api/tasks/ReplacedBy.java +++ b/subprojects/core-api/src/main/java/org/gradle/api/ReplacedBy.java @@ -14,7 +14,9 @@ * limitations under the License. */ -package org.gradle.api.tasks; +package org.gradle.api; + +import org.gradle.api.tasks.Internal; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; @@ -25,13 +27,13 @@ /** *

    Attached to a task property to indicate that the property has been replaced by another. Like {@link Internal}, the property is ignored during up-to-date checks.

    * - *

    This annotation should be attached to the getter and setter method in Java or the property field in Groovy. You should also consider adding {@link Deprecated} to any replaced property.

    + *

    This annotation should be attached to the getter method in Java or the property field in Groovy. You should also consider adding {@link Deprecated} to any replaced property.

    * *

    This will cause the task not to be considered out-of-date when the property has changed.

    */ @Documented @Retention(RetentionPolicy.RUNTIME) -@Target(ElementType.METHOD) +@Target({ElementType.METHOD, ElementType.FIELD}) public @interface ReplacedBy { /** * The Java Bean-style name of the replacement property. diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/DefaultTypeMetadataStore.java b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/DefaultTypeMetadataStore.java index 1820d44860879..bc38b29e515e4 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/DefaultTypeMetadataStore.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/DefaultTypeMetadataStore.java @@ -38,7 +38,6 @@ import org.gradle.api.plugins.ExtensionAware; import org.gradle.api.tasks.Optional; import org.gradle.api.tasks.PathSensitive; -import org.gradle.api.tasks.ReplacedBy; import org.gradle.api.tasks.SkipWhenEmpty; import org.gradle.cache.internal.CrossBuildInMemoryCache; import org.gradle.cache.internal.CrossBuildInMemoryCacheFactory; @@ -58,7 +57,7 @@ public class DefaultTypeMetadataStore implements TypeMetadataStore { // Avoid reflecting on classes we know we don't need to look at private static final ImmutableSet> IGNORED_SUPER_CLASSES = ImmutableSet.of( - ConventionTask.class, DefaultTask.class, AbstractTask.class, Task.class, Object.class, GroovyObject.class, IConventionAware.class, ExtensionAware.class, HasConvention.class, ScriptOrigin.class, DynamicObjectAware.class + ConventionTask.class, DefaultTask.class, AbstractTask.class, Task.class, Object.class, GroovyObject.class, IConventionAware.class, ExtensionAware.class, HasConvention.class, ScriptOrigin.class, DynamicObjectAware.class ); private static final ImmutableSet> IGNORED_METHODS = ImmutableSet.of(Object.class, GroovyObject.class, ScriptOrigin.class); @@ -115,11 +114,11 @@ private static Multimap, Class private static Set> collectRelevantAnnotationTypes(Set> propertyTypeAnnotations) { return ImmutableSet.>builder() - .addAll(propertyTypeAnnotations) - .add(Optional.class) - .add(SkipWhenEmpty.class) - .add(PathSensitive.class) - .build(); + .addAll(propertyTypeAnnotations) + .add(Optional.class) + .add(SkipWhenEmpty.class) + .add(PathSensitive.class) + .build(); } @Override diff --git a/subprojects/core/src/main/java/org/gradle/api/tasks/bundling/AbstractArchiveTask.java b/subprojects/core/src/main/java/org/gradle/api/tasks/bundling/AbstractArchiveTask.java index 9e9c8cc28cd21..e0f05da0e5180 100644 --- a/subprojects/core/src/main/java/org/gradle/api/tasks/bundling/AbstractArchiveTask.java +++ b/subprojects/core/src/main/java/org/gradle/api/tasks/bundling/AbstractArchiveTask.java @@ -29,7 +29,7 @@ import org.gradle.api.tasks.Input; import org.gradle.api.tasks.Internal; import org.gradle.api.tasks.OutputFile; -import org.gradle.api.tasks.ReplacedBy; +import org.gradle.api.ReplacedBy; import org.gradle.internal.nativeplatform.filesystem.FileSystem; import org.gradle.internal.reflect.Instantiator; import org.gradle.util.GUtil; @@ -120,7 +120,6 @@ public String getArchiveName() { * @deprecated Use {@link #getArchiveFileName()} */ @Deprecated - @ReplacedBy("archiveFileName") public void setArchiveName(String name) { archiveName.set(name); } @@ -189,7 +188,6 @@ public File getDestinationDir() { * @deprecated Use {@link #getDestinationDirectory()} */ @Deprecated - @ReplacedBy("destinationDirectory") public void setDestinationDir(File destinationDir) { archiveDestinationDirectory.set(destinationDir); } @@ -223,7 +221,6 @@ public String getBaseName() { * @deprecated Use {@link #getArchiveBaseName()} */ @Deprecated - @ReplacedBy("archiveBaseName") public void setBaseName(@Nullable String baseName) { this.archiveBaseName.set(baseName); } @@ -258,7 +255,6 @@ public String getAppendix() { * @deprecated Use {@link #getArchiveAppendix()} */ @Deprecated - @ReplacedBy("archiveAppendix") public void setAppendix(@Nullable String appendix) { this.archiveAppendix.set(appendix); } @@ -293,7 +289,6 @@ public String getVersion() { * @deprecated Use {@link #getArchiveVersion()} */ @Deprecated - @ReplacedBy("archiveVersion") public void setVersion(@Nullable String version) { this.archiveVersion.set(version); } @@ -326,7 +321,6 @@ public String getExtension() { * @deprecated Use {@link #getArchiveExtension()} */ @Deprecated - @ReplacedBy("archiveExtension") public void setExtension(@Nullable String extension) { this.archiveExtension.set(extension); } @@ -359,7 +353,6 @@ public String getClassifier() { * @deprecated Use {@link #getArchiveClassifier()} */ @Deprecated - @ReplacedBy("archiveClassifier") public void setClassifier(@Nullable String classifier) { this.archiveClassifier.set(classifier); } diff --git a/subprojects/core/src/main/java/org/gradle/internal/service/scopes/ExecutionGlobalServices.java b/subprojects/core/src/main/java/org/gradle/internal/service/scopes/ExecutionGlobalServices.java index 860d45b58a2e6..2c164029fc0e2 100644 --- a/subprojects/core/src/main/java/org/gradle/internal/service/scopes/ExecutionGlobalServices.java +++ b/subprojects/core/src/main/java/org/gradle/internal/service/scopes/ExecutionGlobalServices.java @@ -16,6 +16,7 @@ package org.gradle.internal.service.scopes; import com.google.common.collect.ImmutableSet; +import org.gradle.api.ReplacedBy; import org.gradle.api.internal.project.taskfactory.DefaultTaskClassInfoStore; import org.gradle.api.internal.project.taskfactory.TaskClassInfoStore; import org.gradle.api.internal.tasks.properties.InspectionScheme; @@ -50,7 +51,6 @@ import org.gradle.api.tasks.OutputDirectory; import org.gradle.api.tasks.OutputFile; import org.gradle.api.tasks.OutputFiles; -import org.gradle.api.tasks.ReplacedBy; import org.gradle.api.tasks.options.OptionValues; import org.gradle.cache.internal.CrossBuildInMemoryCacheFactory; import org.gradle.internal.instantiation.InstantiationScheme; @@ -66,7 +66,7 @@ InspectionSchemeFactory createInspectionSchemeFactory(List> UNPROCESSED_PROPERTY_TYPE_ANNOTATIONS = [ - Console, Internal, Inject + Console, Internal, Inject, ReplacedBy ] @Shared GroovyClassLoader groovyClassLoader @@ -241,6 +242,7 @@ class DefaultTypeMetadataStoreTest extends Specification { @OutputDirectories Set outputDirectories @Inject Object injectedService @Internal Object internal + @ReplacedBy("inputString") String oldProperty @Console boolean console } diff --git a/subprojects/docs/src/docs/userguide/more_about_tasks.adoc b/subprojects/docs/src/docs/userguide/more_about_tasks.adoc index 0bd96884e8edb..3bb95465df71d 100644 --- a/subprojects/docs/src/docs/userguide/more_about_tasks.adoc +++ b/subprojects/docs/src/docs/userguide/more_about_tasks.adoc @@ -643,7 +643,7 @@ Using a file tree turns <> of | Any type | Indicates that the property is used internally but is neither an input nor an output. -| `@link:{javadocPath}/org/gradle/api/tasks/ReplacedBy.html[ReplacedBy]` +| `@link:{javadocPath}/org/gradle/api/ReplacedBy.html[ReplacedBy]` | Any type | Indicates that the property has been replaced by another and should be ignored as an input or output. diff --git a/subprojects/plugin-development/src/integTest/groovy/org/gradle/plugin/devel/tasks/ValidateTaskPropertiesIntegrationTest.groovy b/subprojects/plugin-development/src/integTest/groovy/org/gradle/plugin/devel/tasks/ValidateTaskPropertiesIntegrationTest.groovy index d9f80584aac04..6067e6fd81170 100644 --- a/subprojects/plugin-development/src/integTest/groovy/org/gradle/plugin/devel/tasks/ValidateTaskPropertiesIntegrationTest.groovy +++ b/subprojects/plugin-development/src/integTest/groovy/org/gradle/plugin/devel/tasks/ValidateTaskPropertiesIntegrationTest.groovy @@ -16,6 +16,7 @@ package org.gradle.plugin.devel.tasks +import org.gradle.api.ReplacedBy import org.gradle.api.artifacts.transform.InputArtifact import org.gradle.api.artifacts.transform.InputArtifactDependencies import org.gradle.api.artifacts.transform.TransformParameters @@ -170,6 +171,7 @@ class ValidateTaskPropertiesIntegrationTest extends AbstractIntegrationSpec { Inject | Inject.name | ObjectFactory OptionValues | "${OptionValues.name}(\"a\")" | List Internal | 'Internal' | String + ReplacedBy | 'ReplacedBy' | String Console | 'Console' | Boolean Destroys | 'Destroys' | FileCollection LocalState | 'LocalState' | FileCollection @@ -590,4 +592,39 @@ class ValidateTaskPropertiesIntegrationTest extends AbstractIntegrationSpec { 'classes' | 'output.classesDirs' 'classpath' | ' compileClasspath ' } + + def "reports conflicting types when property is replaced but keeps old annotations"() { + file("src/main/java/MyTask.java") << """ + import org.gradle.api.*; + import org.gradle.api.tasks.*; + import org.gradle.api.provider.*; + + public class MyTask extends DefaultTask { + private final Property newProperty = getProject().getObjects().property(String.class); + + @Input + @ReplacedBy("newProperty") + public String getOldProperty() { + return newProperty.get(); + } + + public void setOldProperty(String oldProperty) { + newProperty.set(oldProperty); + } + + @Input + public Property getNewProperty() { + return newProperty; + } + } + """ + + when: + fails "validateTaskProperties" + + then: + file("build/reports/task-properties/report.txt").text == """ + Warning: Task type 'MyTask': property 'oldProperty' has conflicting property types declared: @Input, @ReplacedBy + """.stripIndent().trim() + } } diff --git a/subprojects/plugin-development/src/main/java/org/gradle/plugin/devel/tasks/ValidateTaskProperties.java b/subprojects/plugin-development/src/main/java/org/gradle/plugin/devel/tasks/ValidateTaskProperties.java index 9c299de7e4365..40c61798c8268 100644 --- a/subprojects/plugin-development/src/main/java/org/gradle/plugin/devel/tasks/ValidateTaskProperties.java +++ b/subprojects/plugin-development/src/main/java/org/gradle/plugin/devel/tasks/ValidateTaskProperties.java @@ -102,7 +102,7 @@ *
  • {@literal @}{@link javax.inject.Inject} marks a Gradle service used by the task.
  • *
  • {@literal @}{@link org.gradle.api.tasks.Console Console} marks a property that only influences the console output of the task.
  • *
  • {@literal @}{@link org.gradle.api.tasks.Internal Internal} mark an internal property of the task.
  • - *
  • {@literal @}{@link org.gradle.api.tasks.ReplacedBy ReplacedBy} mark a property as replaced by another (similar to {@code Internal}).
  • + *
  • {@literal @}{@link org.gradle.api.ReplacedBy ReplacedBy} mark a property as replaced by another (similar to {@code Internal}).
  • * * * From b8e871b1e766f7a4465604e3df17fc5f565b3348 Mon Sep 17 00:00:00 2001 From: Daniel Lacasse Date: Mon, 25 Feb 2019 18:35:23 -0500 Subject: [PATCH 129/853] Ensure builds containing deployements report accurate build time --- ...ymentContinuousBuildIntegrationTest.groovy | 145 ++++++++++++++++++ .../ContinuousBuildActionExecuter.java | 11 +- 2 files changed, 153 insertions(+), 3 deletions(-) create mode 100644 subprojects/launcher/src/integTest/groovy/org/gradle/launcher/continuous/DeploymentContinuousBuildIntegrationTest.groovy diff --git a/subprojects/launcher/src/integTest/groovy/org/gradle/launcher/continuous/DeploymentContinuousBuildIntegrationTest.groovy b/subprojects/launcher/src/integTest/groovy/org/gradle/launcher/continuous/DeploymentContinuousBuildIntegrationTest.groovy new file mode 100644 index 0000000000000..f67ce46e04e9a --- /dev/null +++ b/subprojects/launcher/src/integTest/groovy/org/gradle/launcher/continuous/DeploymentContinuousBuildIntegrationTest.groovy @@ -0,0 +1,145 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.launcher.continuous + +class DeploymentContinuousBuildIntegrationTest extends Java7RequiringContinuousIntegrationTest { + File triggerFile = file('triggerFile') + File keyFile = file('keyFile') + + def setup() { + buildFile << """ + import javax.inject.Inject + import org.gradle.deployment.internal.Deployment + import org.gradle.deployment.internal.DeploymentHandle + import org.gradle.deployment.internal.DeploymentRegistry + import org.gradle.deployment.internal.DeploymentRegistry.ChangeBehavior + + task runDeployment(type: RunTestDeployment) { + triggerFile = file('${triggerFile.name}') + keyFile = file('${keyFile.name}') + } + + class TestDeploymentHandle implements DeploymentHandle { + final File keyFile + boolean running + + @Inject + TestDeploymentHandle(key, File keyFile) { + this.keyFile = keyFile + keyFile.text = key + } + + public void start(Deployment deployment) { + running = true + } + + public boolean isRunning() { + return running + } + + public void stop() { + running = false + keyFile.delete() + } + } + + class RunTestDeployment extends DefaultTask { + @InputFile + File triggerFile + + @OutputFile + File keyFile + + @Inject + protected DeploymentRegistry getDeploymentRegistry() { + throw new UnsupportedOperationException() + } + + @TaskAction + void doDeployment() { + // we set a different key for every build so we can detect if we + // somehow get a different deployment handle between builds + def key = System.currentTimeMillis() + + TestDeploymentHandle handle = getDeploymentRegistry().get('test', TestDeploymentHandle.class) + if (handle == null) { + // This should only happen once (1st build), so if we get a different value in keyFile between + // builds then we know we can detect if we didn't get the same handle + handle = getDeploymentRegistry().start('test', DeploymentRegistry.ChangeBehavior.NONE, TestDeploymentHandle.class, key, keyFile) + } + + println "\\nCurrent Key: \$key, Deployed Key: \$handle.keyFile.text" + assert handle.isRunning() + } + } + """ + buildTimeout = 30 + } + + def "deployment promoted to continuous build reports accurate build time" () { + triggerFile.text = "0" + + when: + withoutContinuousBuild() + succeeds("runDeployment") + + then: + def key = file('keyFile').text + assertDeploymentIsRunning(key) + buildTimes.size() == 2 + buildTimes[0] >= buildTimes[1] + } + + def "deployment in continuous build reports accurate build time" () { + triggerFile.text = "0" + + when: + succeeds("runDeployment") + + then: + def key = file('keyFile').text + assertDeploymentIsRunning(key) + + when: + def lastBuildTime = one(buildTimes) + waitBeforeModification triggerFile + triggerFile << "\n#a change" + succeeds() + + then: + assertDeploymentIsRunning(key) + lastBuildTime >= one(buildTimes) + } + + List getBuildTimes() { + return (output =~ /BUILD SUCCESSFUL in (\d+)s/).collect { it[1].toString().toInteger() } + } + + private static T one(Iterable iterable) { + def iterator = iterable.iterator() + assert iterator.hasNext() + def item = iterator.next() + assert !iterator.hasNext() + return item + } + + void assertDeploymentIsRunning(String key) { + // assert that the keyFile still exists and has the same contents (ie handle is still running) + assert keyFile.exists() + assert keyFile.text == key + } +} diff --git a/subprojects/launcher/src/main/java/org/gradle/tooling/internal/provider/ContinuousBuildActionExecuter.java b/subprojects/launcher/src/main/java/org/gradle/tooling/internal/provider/ContinuousBuildActionExecuter.java index 56f60a4b2ff22..0d246d4aad43b 100644 --- a/subprojects/launcher/src/main/java/org/gradle/tooling/internal/provider/ContinuousBuildActionExecuter.java +++ b/subprojects/launcher/src/main/java/org/gradle/tooling/internal/provider/ContinuousBuildActionExecuter.java @@ -105,6 +105,7 @@ private void waitForDeployments(BuildAction action, BuildRequestContext requestC ((DeploymentInternal) deployment).outOfDate(); } logger.println().println("Reloadable deployment detected. Entering continuous build."); + resetBuildStartedTime(buildSessionScopeServices); ContinuousExecutionGate deploymentRequestExecutionGate = deploymentRegistry.getExecutionGate(); executeMultipleBuilds(action, requestContext, actionParameters, buildSessionScopeServices, cancellableOperationManager, deploymentRequestExecutionGate); } @@ -114,8 +115,6 @@ private void waitForDeployments(BuildAction action, BuildRequestContext requestC private BuildActionResult executeMultipleBuilds(BuildAction action, final BuildRequestContext requestContext, final BuildActionParameters actionParameters, final ServiceRegistry buildSessionScopeServices, CancellableOperationManager cancellableOperationManager, ContinuousExecutionGate continuousExecutionGate) { BuildCancellationToken cancellationToken = requestContext.getCancellationToken(); - BuildStartedTime buildStartedTime = buildSessionScopeServices.get(BuildStartedTime.class); - Clock clock = buildSessionScopeServices.get(Clock.class); BuildActionResult lastResult; while (true) { @@ -152,7 +151,7 @@ public void run() { break; } else { logger.println("Change detected, executing build...").println(); - buildStartedTime.reset(clock.getCurrentTime()); + resetBuildStartedTime(buildSessionScopeServices); } } @@ -160,6 +159,12 @@ public void run() { return lastResult; } + private void resetBuildStartedTime(ServiceRegistry buildSessionScopeServices) { + BuildStartedTime buildStartedTime = buildSessionScopeServices.get(BuildStartedTime.class); + Clock clock = buildSessionScopeServices.get(Clock.class); + buildStartedTime.reset(clock.getCurrentTime()); + } + private String determineExitHint(BuildRequestContext requestContext) { if (requestContext.isInteractive()) { if (operatingSystem.isWindows()) { From 3b7b0e0192dbc30b58b0433611b3aa707bac4dd0 Mon Sep 17 00:00:00 2001 From: Daniel Lacasse Date: Mon, 25 Feb 2019 19:25:48 -0500 Subject: [PATCH 130/853] Use `CollectionUtils.single` instead of custom implementation --- .../NativeComponentModelPluginTest.groovy | 25 +++++++------------ 1 file changed, 9 insertions(+), 16 deletions(-) diff --git a/subprojects/platform-native/src/test/groovy/org/gradle/nativeplatform/plugins/NativeComponentModelPluginTest.groovy b/subprojects/platform-native/src/test/groovy/org/gradle/nativeplatform/plugins/NativeComponentModelPluginTest.groovy index 59df141cd67e4..c7344d3be5520 100644 --- a/subprojects/platform-native/src/test/groovy/org/gradle/nativeplatform/plugins/NativeComponentModelPluginTest.groovy +++ b/subprojects/platform-native/src/test/groovy/org/gradle/nativeplatform/plugins/NativeComponentModelPluginTest.groovy @@ -47,6 +47,7 @@ import org.gradle.util.TestUtil import spock.lang.Issue import static org.gradle.model.internal.type.ModelTypes.modelMap +import static org.gradle.util.CollectionUtils.single class NativeComponentModelPluginTest extends AbstractProjectBuilderSpec { def registry @@ -120,8 +121,8 @@ class NativeComponentModelPluginTest extends AbstractProjectBuilderSpec { } then: - one(binaries.withType(NativeExecutableBinarySpec)).flavor.name == DefaultFlavor.DEFAULT - one(binaries.withType(SharedLibraryBinarySpec)).flavor.name == DefaultFlavor.DEFAULT + single(binaries.withType(NativeExecutableBinarySpec)).flavor.name == DefaultFlavor.DEFAULT + single(binaries.withType(SharedLibraryBinarySpec)).flavor.name == DefaultFlavor.DEFAULT } def "behaves correctly for defaults when domain is explicitly configured"() { @@ -133,10 +134,10 @@ class NativeComponentModelPluginTest extends AbstractProjectBuilderSpec { .mutate(FlavorContainer) { it.add named(Flavor, "flavor1") } then: - one(toolChains).name == 'tc' + single(toolChains).name == 'tc' platforms.size() == 1 - one(buildTypes).name == 'bt' - one(flavors).name == 'flavor1' + single(buildTypes).name == 'bt' + single(flavors).name == 'flavor1' } def "creates binaries for executable"() { @@ -157,8 +158,8 @@ class NativeComponentModelPluginTest extends AbstractProjectBuilderSpec { } then: - NativeExecutableSpec executable = one(components.values()) as NativeExecutableSpec - NativeExecutableBinarySpec executableBinary = one(binaries) as NativeExecutableBinarySpec + NativeExecutableSpec executable = single(components.values()) as NativeExecutableSpec + NativeExecutableBinarySpec executableBinary = single(binaries) as NativeExecutableBinarySpec with(executableBinary) { name == 'executable' component == executable @@ -190,7 +191,7 @@ class NativeComponentModelPluginTest extends AbstractProjectBuilderSpec { } then: - NativeLibrarySpec library = one(components.values()) as NativeLibrarySpec + NativeLibrarySpec library = single(components.values()) as NativeLibrarySpec SharedLibraryBinarySpec sharedLibraryBinary = binaries.testSharedLibrary as SharedLibraryBinarySpec with(sharedLibraryBinary) { name == 'sharedLibrary' @@ -247,14 +248,6 @@ class NativeComponentModelPluginTest extends AbstractProjectBuilderSpec { } } - static T one(Iterable iterable) { - def iterator = iterable.iterator() - assert iterator.hasNext() - def item = iterator.next() - assert !iterator.hasNext() - return item - } - public T named(Class type, def name) { Stub(type) { getName() >> name From 4579123c9d98351ecceeccdb8d9d51a8a8a678a8 Mon Sep 17 00:00:00 2001 From: Daniel Lacasse Date: Mon, 25 Feb 2019 19:54:23 -0500 Subject: [PATCH 131/853] Extract deployment fixture to share between tests --- .../fixtures/TestDeploymentFixture.groovy | 120 ++++++++++++++++++ ...ymentContinuousBuildIntegrationTest.groovy | 110 +++------------- ...ndleContinuousBuildCrossVersionSpec.groovy | 102 ++------------- 3 files changed, 147 insertions(+), 185 deletions(-) create mode 100644 subprojects/core/src/testFixtures/groovy/org/gradle/test/fixtures/TestDeploymentFixture.groovy diff --git a/subprojects/core/src/testFixtures/groovy/org/gradle/test/fixtures/TestDeploymentFixture.groovy b/subprojects/core/src/testFixtures/groovy/org/gradle/test/fixtures/TestDeploymentFixture.groovy new file mode 100644 index 0000000000000..d38a51509560c --- /dev/null +++ b/subprojects/core/src/testFixtures/groovy/org/gradle/test/fixtures/TestDeploymentFixture.groovy @@ -0,0 +1,120 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.test.fixtures + +import org.gradle.deployment.internal.Deployment +import org.gradle.deployment.internal.DeploymentHandle +import org.gradle.deployment.internal.DeploymentRegistry +import org.gradle.test.fixtures.file.TestFile + +class TestDeploymentFixture { + private File triggerFile + private File keyFile + + void writeToProject(TestFile projectDir) { + triggerFile = projectDir.file('triggerFile') + keyFile = projectDir.file('keyFile') + + triggerFile.text = "0" + + projectDir.file("build.gradle") << """ + import javax.inject.Inject + import ${Deployment.canonicalName} + import ${DeploymentHandle.canonicalName} + import ${DeploymentRegistry.canonicalName} + import ${DeploymentRegistry.ChangeBehavior.canonicalName} + + task runDeployment(type: RunTestDeployment) { + triggerFile = file('${triggerFile.name}') + keyFile = file('${keyFile.name}') + } + + class TestDeploymentHandle implements DeploymentHandle { + final File keyFile + boolean running + + @Inject + TestDeploymentHandle(key, File keyFile) { + this.keyFile = keyFile + keyFile.text = key + } + + public void start(Deployment deployment) { + running = true + } + + public boolean isRunning() { + return running + } + + public void stop() { + running = false + keyFile.delete() + } + } + + class RunTestDeployment extends DefaultTask { + @InputFile + File triggerFile + + @OutputFile + File keyFile + + @Inject + protected DeploymentRegistry getDeploymentRegistry() { + throw new UnsupportedOperationException() + } + + @TaskAction + void doDeployment() { + // we set a different key for every build so we can detect if we + // somehow get a different deployment handle between builds + def key = System.currentTimeMillis() + + TestDeploymentHandle handle = getDeploymentRegistry().get('test', TestDeploymentHandle.class) + if (handle == null) { + // This should only happen once (1st build), so if we get a different value in keyFile between + // builds then we know we can detect if we didn't get the same handle + handle = getDeploymentRegistry().start('test', DeploymentRegistry.ChangeBehavior.NONE, TestDeploymentHandle.class, key, keyFile) + } + + println "\\nCurrent Key: \$key, Deployed Key: \$handle.keyFile.text" + assert handle.isRunning() + } + } + """ + } + + File getTriggerFile() { + return triggerFile + } + + File getKeyFile() { + return keyFile + } + + void assertDeploymentIsRunning(String key) { + // assert that the keyFile still exists and has the same contents (ie handle is still running) + assert keyFile.exists() + assert keyFile.text == key + } + + void assertDeploymentIsStopped() { + // assert that the deployment handle was stopped and removed the key file + assert !keyFile.exists() + } +} diff --git a/subprojects/launcher/src/integTest/groovy/org/gradle/launcher/continuous/DeploymentContinuousBuildIntegrationTest.groovy b/subprojects/launcher/src/integTest/groovy/org/gradle/launcher/continuous/DeploymentContinuousBuildIntegrationTest.groovy index f67ce46e04e9a..d3c7d23fbdf3c 100644 --- a/subprojects/launcher/src/integTest/groovy/org/gradle/launcher/continuous/DeploymentContinuousBuildIntegrationTest.groovy +++ b/subprojects/launcher/src/integTest/groovy/org/gradle/launcher/continuous/DeploymentContinuousBuildIntegrationTest.groovy @@ -16,130 +16,50 @@ package org.gradle.launcher.continuous -class DeploymentContinuousBuildIntegrationTest extends Java7RequiringContinuousIntegrationTest { - File triggerFile = file('triggerFile') - File keyFile = file('keyFile') - - def setup() { - buildFile << """ - import javax.inject.Inject - import org.gradle.deployment.internal.Deployment - import org.gradle.deployment.internal.DeploymentHandle - import org.gradle.deployment.internal.DeploymentRegistry - import org.gradle.deployment.internal.DeploymentRegistry.ChangeBehavior - - task runDeployment(type: RunTestDeployment) { - triggerFile = file('${triggerFile.name}') - keyFile = file('${keyFile.name}') - } - - class TestDeploymentHandle implements DeploymentHandle { - final File keyFile - boolean running - - @Inject - TestDeploymentHandle(key, File keyFile) { - this.keyFile = keyFile - keyFile.text = key - } - - public void start(Deployment deployment) { - running = true - } - - public boolean isRunning() { - return running - } - - public void stop() { - running = false - keyFile.delete() - } - } - - class RunTestDeployment extends DefaultTask { - @InputFile - File triggerFile +import org.gradle.test.fixtures.TestDeploymentFixture - @OutputFile - File keyFile +import static org.gradle.util.CollectionUtils.single - @Inject - protected DeploymentRegistry getDeploymentRegistry() { - throw new UnsupportedOperationException() - } - - @TaskAction - void doDeployment() { - // we set a different key for every build so we can detect if we - // somehow get a different deployment handle between builds - def key = System.currentTimeMillis() - - TestDeploymentHandle handle = getDeploymentRegistry().get('test', TestDeploymentHandle.class) - if (handle == null) { - // This should only happen once (1st build), so if we get a different value in keyFile between - // builds then we know we can detect if we didn't get the same handle - handle = getDeploymentRegistry().start('test', DeploymentRegistry.ChangeBehavior.NONE, TestDeploymentHandle.class, key, keyFile) - } +class DeploymentContinuousBuildIntegrationTest extends Java7RequiringContinuousIntegrationTest { + def fixture = new TestDeploymentFixture() - println "\\nCurrent Key: \$key, Deployed Key: \$handle.keyFile.text" - assert handle.isRunning() - } - } - """ + def setup() { + fixture.writeToProject(testDirectory) buildTimeout = 30 } def "deployment promoted to continuous build reports accurate build time" () { - triggerFile.text = "0" - when: withoutContinuousBuild() succeeds("runDeployment") then: - def key = file('keyFile').text - assertDeploymentIsRunning(key) + def key = fixture.keyFile.text + fixture.assertDeploymentIsRunning(key) buildTimes.size() == 2 buildTimes[0] >= buildTimes[1] } def "deployment in continuous build reports accurate build time" () { - triggerFile.text = "0" - when: succeeds("runDeployment") then: - def key = file('keyFile').text - assertDeploymentIsRunning(key) + def key = fixture.keyFile.text + fixture.assertDeploymentIsRunning(key) when: - def lastBuildTime = one(buildTimes) - waitBeforeModification triggerFile - triggerFile << "\n#a change" + def lastBuildTime = single(buildTimes) + waitBeforeModification fixture.triggerFile + fixture.triggerFile << "\n#a change" succeeds() then: - assertDeploymentIsRunning(key) - lastBuildTime >= one(buildTimes) + fixture.assertDeploymentIsRunning(key) + lastBuildTime >= single(buildTimes) } List getBuildTimes() { return (output =~ /BUILD SUCCESSFUL in (\d+)s/).collect { it[1].toString().toInteger() } } - - private static T one(Iterable iterable) { - def iterator = iterable.iterator() - assert iterator.hasNext() - def item = iterator.next() - assert !iterator.hasNext() - return item - } - - void assertDeploymentIsRunning(String key) { - // assert that the keyFile still exists and has the same contents (ie handle is still running) - assert keyFile.exists() - assert keyFile.text == key - } } diff --git a/subprojects/tooling-api/src/crossVersionTest/groovy/org/gradle/integtests/tooling/r25/DeploymentHandleContinuousBuildCrossVersionSpec.groovy b/subprojects/tooling-api/src/crossVersionTest/groovy/org/gradle/integtests/tooling/r25/DeploymentHandleContinuousBuildCrossVersionSpec.groovy index 4746f9dfc6973..0134b2f442f79 100644 --- a/subprojects/tooling-api/src/crossVersionTest/groovy/org/gradle/integtests/tooling/r25/DeploymentHandleContinuousBuildCrossVersionSpec.groovy +++ b/subprojects/tooling-api/src/crossVersionTest/groovy/org/gradle/integtests/tooling/r25/DeploymentHandleContinuousBuildCrossVersionSpec.groovy @@ -19,118 +19,40 @@ package org.gradle.integtests.tooling.r25 import org.gradle.integtests.fixtures.executer.GradleVersions import org.gradle.integtests.tooling.fixture.ContinuousBuildToolingApiSpecification import org.gradle.integtests.tooling.fixture.TargetGradleVersion +import org.gradle.test.fixtures.TestDeploymentFixture import spock.lang.Timeout @Timeout(120) @TargetGradleVersion(GradleVersions.SUPPORTS_DEPLOYMENT_REGISTRY) class DeploymentHandleContinuousBuildCrossVersionSpec extends ContinuousBuildToolingApiSpecification { - File triggerFile = file('triggerFile') - File keyFile = file('keyFile') + def fixture = new TestDeploymentFixture() def setup() { - buildFile << """ - import javax.inject.Inject - import org.gradle.deployment.internal.Deployment - import org.gradle.deployment.internal.DeploymentHandle - import org.gradle.deployment.internal.DeploymentRegistry - import org.gradle.deployment.internal.DeploymentRegistry.ChangeBehavior - - task runDeployment(type: RunTestDeployment) { - triggerFile = file('${triggerFile.name}') - keyFile = file('${keyFile.name}') - } - - class TestDeploymentHandle implements DeploymentHandle { - final File keyFile - boolean running - - @Inject - TestDeploymentHandle(key, File keyFile) { - this.keyFile = keyFile - keyFile.text = key - } - - public void start(Deployment deployment) { - running = true - } - - public boolean isRunning() { - return running - } - - public void stop() { - running = false - keyFile.delete() - } - } - - class RunTestDeployment extends DefaultTask { - @InputFile - File triggerFile - - @OutputFile - File keyFile - - @Inject - protected DeploymentRegistry getDeploymentRegistry() { - throw new UnsupportedOperationException() - } - - @TaskAction - void doDeployment() { - // we set a different key for every build so we can detect if we - // somehow get a different deployment handle between builds - def key = System.currentTimeMillis() - - TestDeploymentHandle handle = getDeploymentRegistry().get('test', TestDeploymentHandle.class) - if (handle == null) { - // This should only happen once (1st build), so if we get a different value in keyFile between - // builds then we know we can detect if we didn't get the same handle - handle = getDeploymentRegistry().start('test', DeploymentRegistry.ChangeBehavior.NONE, TestDeploymentHandle.class, key, keyFile) - } - - println "\\nCurrent Key: \$key, Deployed Key: \$handle.keyFile.text" - assert handle.isRunning() - } - } - """ + fixture.writeToProject(projectDir) buildTimeout = 30 } def "deployment is stopped when continuous build is cancelled" () { - triggerFile.text = "0" - when: runBuild(["runDeployment"]) { succeeds() - def key = file('keyFile').text - deploymentIsRunning(key) + def key = fixture.keyFile.text + fixture.assertDeploymentIsRunning(key) - waitBeforeModification triggerFile - triggerFile << "\n#a change" + waitBeforeModification fixture.triggerFile + fixture.triggerFile << "\n#a change" succeeds() - deploymentIsRunning(key) + fixture.assertDeploymentIsRunning(key) - waitBeforeModification triggerFile - triggerFile << "\n#another change" + waitBeforeModification fixture.triggerFile + fixture.triggerFile << "\n#another change" succeeds() - deploymentIsRunning(key) + fixture.assertDeploymentIsRunning(key) cancel() } then: - deploymentIsStopped() - } - - void deploymentIsRunning(String key) { - // assert that the keyFile still exists and has the same contents (ie handle is still running) - assert keyFile.exists() - assert keyFile.text == key - } - - void deploymentIsStopped() { - // assert that the deployment handle was stopped and removed the key file - assert !keyFile.exists() + fixture.assertDeploymentIsStopped() } } From 2e541da4ca4a424547486cc4c612e0f5fc5e5956 Mon Sep 17 00:00:00 2001 From: Sterling Greene Date: Mon, 25 Feb 2019 20:41:14 -0500 Subject: [PATCH 132/853] Ignore permgen soak test --- .../launcher/daemon/DaemonPerformanceMonitoringSoakTest.groovy | 2 ++ 1 file changed, 2 insertions(+) diff --git a/subprojects/soak/src/integTest/groovy/org/gradle/launcher/daemon/DaemonPerformanceMonitoringSoakTest.groovy b/subprojects/soak/src/integTest/groovy/org/gradle/launcher/daemon/DaemonPerformanceMonitoringSoakTest.groovy index fa9596545fc1d..2adf86c18d2bb 100644 --- a/subprojects/soak/src/integTest/groovy/org/gradle/launcher/daemon/DaemonPerformanceMonitoringSoakTest.groovy +++ b/subprojects/soak/src/integTest/groovy/org/gradle/launcher/daemon/DaemonPerformanceMonitoringSoakTest.groovy @@ -28,6 +28,7 @@ import org.gradle.launcher.daemon.server.health.GcThrashingDaemonExpirationStrat import org.gradle.soak.categories.SoakTest import org.gradle.test.fixtures.ConcurrentTestUtil import org.junit.experimental.categories.Category +import spock.lang.Ignore import spock.lang.Unroll import static org.junit.Assume.assumeTrue @@ -122,6 +123,7 @@ class DaemonPerformanceMonitoringSoakTest extends DaemonMultiJdkIntegrationTest daemons.daemon.log.contains(DaemonStateCoordinator.DAEMON_WILL_STOP_MESSAGE) } + @Ignore def "when build leaks permgen space daemon is expired"() { assumeTrue(version.vendor != JdkVendor.IBM) From 534a500d7e7df3662e49df1a90b5a9c59b8d69c4 Mon Sep 17 00:00:00 2001 From: Gradleware Git Bot Date: Tue, 26 Feb 2019 02:49:11 +0100 Subject: [PATCH 133/853] Publish 5.3-20190226013556+0000 --- released-versions.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/released-versions.json b/released-versions.json index becf616c94a77..c3dee92ef6641 100644 --- a/released-versions.json +++ b/released-versions.json @@ -1,7 +1,7 @@ { "latestReleaseSnapshot": { - "version": "5.3-20190225141513+0000", - "buildTime": "20190225141513+0000" + "version": "5.3-20190226013556+0000", + "buildTime": "20190226013556+0000" }, "latestRc": { "version": "5.2-rc-1", From b02eccf0dfb443947e38f3426e762b66a07739ea Mon Sep 17 00:00:00 2001 From: Sterling Greene Date: Mon, 25 Feb 2019 20:42:53 -0500 Subject: [PATCH 134/853] Add @Incubating to ReplacedBy --- .../core-api/src/main/java/org/gradle/api/ReplacedBy.java | 3 +++ .../devel/tasks/ValidateTaskPropertiesIntegrationTest.groovy | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/subprojects/core-api/src/main/java/org/gradle/api/ReplacedBy.java b/subprojects/core-api/src/main/java/org/gradle/api/ReplacedBy.java index 2634a9ade74d5..8ae3fd7e36df5 100644 --- a/subprojects/core-api/src/main/java/org/gradle/api/ReplacedBy.java +++ b/subprojects/core-api/src/main/java/org/gradle/api/ReplacedBy.java @@ -30,10 +30,13 @@ *

    This annotation should be attached to the getter method in Java or the property field in Groovy. You should also consider adding {@link Deprecated} to any replaced property.

    * *

    This will cause the task not to be considered out-of-date when the property has changed.

    + * + * @since 5.3 */ @Documented @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.METHOD, ElementType.FIELD}) +@Incubating public @interface ReplacedBy { /** * The Java Bean-style name of the replacement property. diff --git a/subprojects/plugin-development/src/integTest/groovy/org/gradle/plugin/devel/tasks/ValidateTaskPropertiesIntegrationTest.groovy b/subprojects/plugin-development/src/integTest/groovy/org/gradle/plugin/devel/tasks/ValidateTaskPropertiesIntegrationTest.groovy index 6067e6fd81170..16478f9951b3c 100644 --- a/subprojects/plugin-development/src/integTest/groovy/org/gradle/plugin/devel/tasks/ValidateTaskPropertiesIntegrationTest.groovy +++ b/subprojects/plugin-development/src/integTest/groovy/org/gradle/plugin/devel/tasks/ValidateTaskPropertiesIntegrationTest.groovy @@ -171,7 +171,7 @@ class ValidateTaskPropertiesIntegrationTest extends AbstractIntegrationSpec { Inject | Inject.name | ObjectFactory OptionValues | "${OptionValues.name}(\"a\")" | List Internal | 'Internal' | String - ReplacedBy | 'ReplacedBy' | String + ReplacedBy | 'ReplacedBy("")' | String Console | 'Console' | Boolean Destroys | 'Destroys' | FileCollection LocalState | 'LocalState' | FileCollection @@ -624,7 +624,7 @@ class ValidateTaskPropertiesIntegrationTest extends AbstractIntegrationSpec { then: file("build/reports/task-properties/report.txt").text == """ - Warning: Task type 'MyTask': property 'oldProperty' has conflicting property types declared: @Input, @ReplacedBy + Warning: Task type 'MyTask': property 'oldProperty' has conflicting property types declared: @Input, @ReplacedBy. """.stripIndent().trim() } } From 576eb5b34765b51e87c8a8598eb1c8e78d5ed288 Mon Sep 17 00:00:00 2001 From: Stefan Wolf Date: Mon, 25 Feb 2019 17:52:58 +0100 Subject: [PATCH 135/853] Add failing test for problems with generic type parameters The return type of the property is not correct, since bound type parameters of the superclass are not taken into account. --- ...edClassGeneratorInjectDecoratedTest.groovy | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/subprojects/model-core/src/test/groovy/org/gradle/internal/instantiation/AsmBackedClassGeneratorInjectDecoratedTest.groovy b/subprojects/model-core/src/test/groovy/org/gradle/internal/instantiation/AsmBackedClassGeneratorInjectDecoratedTest.groovy index a13ee47cf722a..ce77d26b3c6f1 100644 --- a/subprojects/model-core/src/test/groovy/org/gradle/internal/instantiation/AsmBackedClassGeneratorInjectDecoratedTest.groovy +++ b/subprojects/model-core/src/test/groovy/org/gradle/internal/instantiation/AsmBackedClassGeneratorInjectDecoratedTest.groovy @@ -21,11 +21,13 @@ import org.gradle.api.plugins.ExtensionContainer import org.gradle.internal.service.DefaultServiceRegistry import org.gradle.internal.service.ServiceLookup import org.gradle.internal.service.ServiceRegistry +import org.gradle.util.ToBeImplemented import javax.inject.Inject import java.lang.annotation.Annotation import java.lang.annotation.Retention import java.lang.annotation.RetentionPolicy +import java.lang.reflect.InvocationTargetException import java.lang.reflect.ParameterizedType import java.lang.reflect.Type @@ -64,6 +66,23 @@ class AsmBackedClassGeneratorInjectDecoratedTest extends AbstractClassGeneratorS obj.getProperty("thing") == 12 } + @ToBeImplemented("Resolving type parameters to implement the correct methods in the subclass does not work, yet") + def "can inject service using @Inject on a super interface with type parameters"() { + given: + def services = Mock(ServiceLookup) + _ * services.get(Number) >> 12 + + when: + def obj = create(AbstractClassWithConcreteTypeParameter, services) + + then: + def e = thrown(InvocationTargetException) + e.cause.class == NullPointerException +// obj.thing == 12 +// obj.getThing() == 12 +// obj.getProperty("thing") == 12 + } + def "can inject service using @Inject on an interface getter method"() { given: def services = Mock(ServiceLookup) @@ -311,6 +330,13 @@ interface InterfaceWithServices { Number getThing() } +interface InterfaceWithTypeParameter { + @Inject + T getThing() +} + +abstract class AbstractClassWithConcreteTypeParameter implements InterfaceWithTypeParameter {} + class BeanWithServices { @Inject Number getThing() { From 42eba7b2a7e87ce7798befe3299b49ad664f5ef6 Mon Sep 17 00:00:00 2001 From: Adam Murdoch Date: Tue, 26 Feb 2019 12:31:00 +1100 Subject: [PATCH 136/853] A partial fix for class generation to handle service injection methods inherited from parameterized types and that use a type variable for their return type. --- .../instantiation/AbstractClassGenerator.java | 253 ++++++++++++------ .../AsmBackedClassGenerator.java | 100 ++++--- .../internal/asm/AsmClassGeneratorUtils.java | 14 +- ...edClassGeneratorInjectDecoratedTest.groovy | 53 ++-- .../AsmBackedClassGeneratorTest.java | 19 ++ 5 files changed, 291 insertions(+), 148 deletions(-) diff --git a/subprojects/model-core/src/main/java/org/gradle/internal/instantiation/AbstractClassGenerator.java b/subprojects/model-core/src/main/java/org/gradle/internal/instantiation/AbstractClassGenerator.java index 5bfb57bb7e4da..fb8c853f111e1 100644 --- a/subprojects/model-core/src/main/java/org/gradle/internal/instantiation/AbstractClassGenerator.java +++ b/subprojects/model-core/src/main/java/org/gradle/internal/instantiation/AbstractClassGenerator.java @@ -57,7 +57,9 @@ import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Modifier; +import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; +import java.lang.reflect.TypeVariable; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; @@ -211,7 +213,7 @@ private GeneratedClass generateUnderLock(Class type) { private void inspectType(Class type, List validators, List generationHandlers, UnclaimedPropertyHandler unclaimedHandler) { ClassDetails classDetails = ClassInspector.inspect(type); - ClassMetaData classMetaData = new ClassMetaData(); + ClassMetadata classMetaData = new ClassMetadata(type); assembleProperties(classDetails, classMetaData); for (ClassGenerationHandler handler : generationHandlers) { @@ -225,7 +227,7 @@ private void inspectType(Class type, List validators, List type, List generationH } } - private void assembleProperties(ClassDetails classDetails, ClassMetaData classMetaData) { + private void assembleProperties(ClassDetails classDetails, ClassMetadata classMetaData) { for (PropertyDetails property : classDetails.getProperties()) { - PropertyMetaData propertyMetaData = classMetaData.property(property.getName()); + PropertyMetadata propertyMetaData = classMetaData.property(property.getName()); for (Method method : property.getGetters()) { - propertyMetaData.addGetter(method); + propertyMetaData.addGetter(classMetaData.resolveTypeVariables(method)); } for (Method method : property.getSetters()) { propertyMetaData.addSetter(method); @@ -295,7 +297,7 @@ private void assembleProperties(ClassDetails classDetails, ClassMetaData classMe for (Method method : classDetails.getInstanceMethods()) { Class[] parameterTypes = method.getParameterTypes(); if (parameterTypes.length == 1) { - PropertyMetaData propertyMetaData = classMetaData.getProperty(method.getName()); + PropertyMetadata propertyMetaData = classMetaData.getProperty(method.getName()); if (propertyMetaData != null) { propertyMetaData.addSetMethod(method); } @@ -439,34 +441,103 @@ public GeneratedClassImpl asWrapper() { } } - private static class ClassMetaData { - private final Map properties = new LinkedHashMap(); + private static class ClassMetadata { + private final Class type; + private final Map properties = new LinkedHashMap(); + + public ClassMetadata(Class type) { + this.type = type; + } + + /** + * Determines the concrete return type of the given method, resolving any type parameters. + * + *

    Note: this is only partially implemented.

    + */ + public MethodMetadata resolveTypeVariables(Method method) { + Type returnType = method.getGenericReturnType(); + if (returnType instanceof TypeVariable) { + TypeVariable typeVar = (TypeVariable) method.getGenericReturnType(); + // TODO - need to traverse all supertypes (super class, and all inherited interface) + for (Type genericInterface : type.getGenericInterfaces()) { + if (genericInterface instanceof ParameterizedType) { + ParameterizedType parameterizedType = (ParameterizedType) genericInterface; + if (parameterizedType.getRawType().equals(method.getDeclaringClass())) { + TypeVariable>[] typeParameters = method.getDeclaringClass().getTypeParameters(); + for (int i = 0; i < typeParameters.length; i++) { + TypeVariable> typeParameter = typeParameters[i]; + if (typeParameter.getName().equals(typeVar.getName())) { + // TODO - should resolve type variables + return new MethodMetadata(method, parameterizedType.getActualTypeArguments()[i]); + } + } + } + } + } + } + // TODO - Should handle a parameterized type containing type variables + return new MethodMetadata(method, returnType); + } @Nullable - public PropertyMetaData getProperty(String name) { + public PropertyMetadata getProperty(String name) { return properties.get(name); } - public PropertyMetaData property(String name) { - PropertyMetaData property = properties.get(name); + public PropertyMetadata property(String name) { + PropertyMetadata property = properties.get(name); if (property == null) { - property = new PropertyMetaData(name); + property = new PropertyMetadata(name); properties.put(name, property); } return property; } } - protected static class PropertyMetaData { + protected static class MethodMetadata { + private final Method method; + private final Type returnType; + + public MethodMetadata(Method method, Type returnType) { + this.method = method; + this.returnType = returnType; + } + + public String getName() { + return method.getName(); + } + + public boolean isAbstract() { + return Modifier.isAbstract(method.getModifiers()); + } + + boolean shouldOverride() { + return !Modifier.isFinal(method.getModifiers()) && !method.isBridge(); + } + + boolean shouldImplement() { + return !method.isBridge(); + } + + public Class getReturnType() { + return method.getReturnType(); + } + + public Type getGenericReturnType() { + return returnType; + } + } + + protected static class PropertyMetadata { private final String name; - private final List getters = new ArrayList(); - private final List overridableGetters = new ArrayList(); + private final List getters = new ArrayList<>(); + private final List overridableGetters = new ArrayList<>(); private final List overridableSetters = new ArrayList(); private final List setters = new ArrayList(); private final List setMethods = new ArrayList(); - private Method mainGetter; + private MethodMetadata mainGetter; - private PropertyMetaData(String name) { + private PropertyMetadata(String name) { this.name = name; } @@ -483,7 +554,11 @@ public boolean isReadable() { return mainGetter != null; } - public List getOverridableGetters() { + public MethodMetadata getMainGetter() { + return mainGetter; + } + + public List getOverridableGetters() { return overridableGetters; } @@ -505,15 +580,15 @@ public Type getGenericType() { return setters.get(0).getGenericParameterTypes()[0]; } - public void addGetter(Method method) { - if (!Modifier.isFinal(method.getModifiers()) && !method.isBridge()) { - overridableGetters.add(method); + public void addGetter(MethodMetadata metadata) { + if (metadata.shouldOverride()) { + overridableGetters.add(metadata); } - getters.add(method); + getters.add(metadata); if (mainGetter == null) { - mainGetter = method; - } else if (mainGetter.isBridge() && !method.isBridge()) { - mainGetter = method; + mainGetter = metadata; + } else if (!mainGetter.shouldImplement() && metadata.shouldImplement()) { + mainGetter = metadata; } } @@ -551,7 +626,7 @@ void visitInstanceMethod(Method method) { /** * Collect information about a property. This is called for all properties of a type. */ - void visitProperty(PropertyMetaData property) { + void visitProperty(PropertyMetadata property) { } /** @@ -564,14 +639,14 @@ public void hasFields() { * Handler can claim the property, taking responsibility for generating whatever is required to make the property work. * Handler is also expected to take care of validation. */ - boolean claimPropertyImplementation(PropertyMetaData property) { + boolean claimPropertyImplementation(PropertyMetadata property) { return false; } /** * Called when another a handler with higher precedence has also claimed the given property. */ - void ambiguous(PropertyMetaData property) { + void ambiguous(PropertyMetadata property) { // No supposed to happen throw new UnsupportedOperationException("Multiple matches for " + property.getName()); } @@ -587,7 +662,7 @@ private interface UnclaimedPropertyHandler { /** * Called when no handler has claimed the property. */ - void unclaimed(PropertyMetaData property); + void unclaimed(PropertyMetadata property); } private static class DslMixInPropertyType extends ClassGenerationHandler { @@ -595,7 +670,7 @@ private static class DslMixInPropertyType extends ClassGenerationHandler { private boolean providesOwnDynamicObject; private boolean needDynamicAware; private boolean needGroovyObject; - private final List mutableProperties = new ArrayList(); + private final List mutableProperties = new ArrayList(); private final MethodSet actionMethods = new MethodSet(); private final SetMultimap closureMethods = LinkedHashMultimap.create(); @@ -610,7 +685,7 @@ void startType(Class type) { } @Override - void visitProperty(PropertyMetaData property) { + void visitProperty(PropertyMetadata property) { if (property.setters.isEmpty()) { return; } @@ -622,7 +697,7 @@ void visitProperty(PropertyMetaData property) { } @Override - boolean claimPropertyImplementation(PropertyMetaData property) { + boolean claimPropertyImplementation(PropertyMetadata property) { if (property.getName().equals("asDynamicObject")) { providesOwnDynamicObject = true; return true; @@ -661,7 +736,7 @@ void applyTo(ClassGenerationVisitor visitor) { } private void addSetMethods(AbstractClassGenerator.ClassGenerationVisitor visitor) { - for (PropertyMetaData property : mutableProperties) { + for (PropertyMetadata property : mutableProperties) { if (property.setMethods.isEmpty()) { for (Method setter : property.setters) { visitor.addSetMethod(property, setter); @@ -709,7 +784,7 @@ private static class ExtensibleTypePropertyHandler extends ClassGenerationHandle private boolean conventionAware; private boolean extensible; private boolean hasExtensionAwareImplementation; - private final List conventionProperties = new ArrayList(); + private final List conventionProperties = new ArrayList(); @Override void startType(Class type) { @@ -727,11 +802,11 @@ void startType(Class type) { } @Override - boolean claimPropertyImplementation(PropertyMetaData property) { + boolean claimPropertyImplementation(PropertyMetadata property) { if (extensible) { if (property.getName().equals("extensions")) { - for (Method getter : property.getOverridableGetters()) { - if (Modifier.isAbstract(getter.getModifiers())) { + for (MethodMetadata getter : property.getOverridableGetters()) { + if (getter.isAbstract()) { return true; } } @@ -747,9 +822,9 @@ boolean claimPropertyImplementation(PropertyMetaData property) { } @Override - public void unclaimed(PropertyMetaData property) { - for (Method getter : property.getOverridableGetters()) { - if (!getter.getDeclaringClass().isAssignableFrom(noMappingClass)) { + public void unclaimed(PropertyMetadata property) { + for (MethodMetadata getter : property.getOverridableGetters()) { + if (!getter.method.getDeclaringClass().isAssignableFrom(noMappingClass)) { conventionProperties.add(property); break; } @@ -774,10 +849,10 @@ void applyTo(ClassGenerationVisitor visitor) { if (conventionAware && !IConventionAware.class.isAssignableFrom(type)) { visitor.mixInConventionAware(); } - for (PropertyMetaData property : conventionProperties) { + for (PropertyMetadata property : conventionProperties) { visitor.applyConventionMappingToProperty(property); - for (Method getter : property.getOverridableGetters()) { - visitor.applyConventionMappingToGetter(property, getter); + for (MethodMetadata getter : property.getOverridableGetters()) { + visitor.applyConventionMappingToGetter(property, getter.method); } for (Method setter : property.getOverridableSetters()) { visitor.applyConventionMappingToSetter(property, setter); @@ -787,8 +862,8 @@ void applyTo(ClassGenerationVisitor visitor) { } private static class ManagedTypeHandler extends ClassGenerationHandler { - private final List mutableProperties = new ArrayList<>(); - private final List readOnlyProperties = new ArrayList<>(); + private final List mutableProperties = new ArrayList<>(); + private final List readOnlyProperties = new ArrayList<>(); private boolean hasFields; @Override @@ -797,10 +872,10 @@ public void hasFields() { } @Override - boolean claimPropertyImplementation(PropertyMetaData property) { + boolean claimPropertyImplementation(PropertyMetadata property) { // Skip properties with non-abstract getter or setter implementations - for (Method getter : property.getters) { - if (!Modifier.isAbstract(getter.getModifiers())) { + for (MethodMetadata getter : property.getters) { + if (!getter.isAbstract()) { return false; } } @@ -847,19 +922,19 @@ void applyTo(ClassInspectionVisitor visitor) { @Override void applyTo(ClassGenerationVisitor visitor) { - for (PropertyMetaData property : mutableProperties) { + for (PropertyMetadata property : mutableProperties) { visitor.applyManagedStateToProperty(property); - for (Method getter : property.getters) { - visitor.applyManagedStateToGetter(property, getter); + for (MethodMetadata getter : property.getters) { + visitor.applyManagedStateToGetter(property, getter.method); } for (Method setter : property.setters) { visitor.applyManagedStateToSetter(property, setter); } } - for (PropertyMetaData property : readOnlyProperties) { + for (PropertyMetadata property : readOnlyProperties) { visitor.applyManagedStateToProperty(property); - for (Method getter : property.getters) { - visitor.applyReadOnlyManagedStateToGetter(property, getter); + for (MethodMetadata getter : property.getters) { + visitor.applyReadOnlyManagedStateToGetter(property, getter.method); } } if (!hasFields) { @@ -869,10 +944,10 @@ void applyTo(ClassGenerationVisitor visitor) { } private static class PropertyTypePropertyHandler extends ClassGenerationHandler { - private final List propertyTyped = new ArrayList(); + private final List propertyTyped = new ArrayList(); @Override - void visitProperty(PropertyMetaData property) { + void visitProperty(PropertyMetadata property) { if (property.isReadable() && isModelProperty(property)) { propertyTyped.add(property); } @@ -880,12 +955,12 @@ void visitProperty(PropertyMetaData property) { @Override void applyTo(ClassGenerationVisitor visitor) { - for (PropertyMetaData property : propertyTyped) { - visitor.addPropertySetters(property, property.mainGetter); + for (PropertyMetadata property : propertyTyped) { + visitor.addPropertySetters(property, property.mainGetter.method); } } - private boolean isModelProperty(PropertyMetaData property) { + private boolean isModelProperty(PropertyMetadata property) { return Property.class.isAssignableFrom(property.getType()) || HasMultipleValues.class.isAssignableFrom(property.getType()) || MapProperty.class.isAssignableFrom(property.getType()); @@ -967,7 +1042,7 @@ private static class ServicesPropertyHandler extends ClassGenerationHandler { private boolean hasServicesProperty; @Override - public boolean claimPropertyImplementation(PropertyMetaData property) { + public boolean claimPropertyImplementation(PropertyMetadata property) { if (property.getName().equals("services") && property.isReadable() && ServiceRegistry.class.isAssignableFrom(property.getType())) { hasServicesProperty = true; return true; @@ -985,16 +1060,16 @@ void applyTo(ClassInspectionVisitor visitor) { private static abstract class AbstractInjectedPropertyHandler extends ClassGenerationHandler { final Class annotation; - final List serviceInjectionProperties = new ArrayList(); + final List serviceInjectionProperties = new ArrayList(); public AbstractInjectedPropertyHandler(Class annotation) { this.annotation = annotation; } @Override - public boolean claimPropertyImplementation(PropertyMetaData property) { - for (Method method : property.getters) { - if (method.getAnnotation(annotation) != null) { + public boolean claimPropertyImplementation(PropertyMetadata property) { + for (MethodMetadata getter : property.getters) { + if (getter.method.getAnnotation(annotation) != null) { serviceInjectionProperties.add(property); return true; } @@ -1003,14 +1078,14 @@ public boolean claimPropertyImplementation(PropertyMetaData property) { } @Override - void ambiguous(PropertyMetaData property) { - for (Method method : property.getters) { - if (method.getAnnotation(annotation) != null) { + void ambiguous(PropertyMetadata property) { + for (MethodMetadata getter : property.getters) { + if (getter.method.getAnnotation(annotation) != null) { TreeFormatter formatter = new TreeFormatter(); formatter.node("Cannot use "); formatter.appendAnnotation(annotation); formatter.append(" annotation on method "); - formatter.appendMethod(method); + formatter.appendMethod(getter.method); formatter.append("."); throw new IllegalArgumentException(formatter.toString()); } @@ -1027,7 +1102,7 @@ void applyTo(ClassInspectionVisitor visitor) { public List> getInjectedServices() { ImmutableList.Builder> services = ImmutableList.builderWithExpectedSize(serviceInjectionProperties.size()); - for (PropertyMetaData property : serviceInjectionProperties) { + for (PropertyMetadata property : serviceInjectionProperties) { services.add(property.getType()); } return services.build(); @@ -1049,9 +1124,9 @@ public InjectAnnotationPropertyHandler() { @Override public void applyTo(ClassGenerationVisitor visitor) { - for (PropertyMetaData property : serviceInjectionProperties) { + for (PropertyMetadata property : serviceInjectionProperties) { visitor.applyServiceInjectionToProperty(property); - for (Method getter : property.getOverridableGetters()) { + for (MethodMetadata getter : property.getOverridableGetters()) { visitor.applyServiceInjectionToGetter(property, getter); } for (Method setter : property.getOverridableSetters()) { @@ -1068,9 +1143,9 @@ public CustomInjectAnnotationPropertyHandler(Class injectA @Override public void applyTo(ClassGenerationVisitor visitor) { - for (PropertyMetaData property : serviceInjectionProperties) { + for (PropertyMetadata property : serviceInjectionProperties) { visitor.applyServiceInjectionToProperty(property); - for (Method getter : property.getOverridableGetters()) { + for (MethodMetadata getter : property.getOverridableGetters()) { visitor.applyServiceInjectionToGetter(property, annotation, getter); } for (Method setter : property.getOverridableSetters()) { @@ -1133,39 +1208,39 @@ protected interface ClassGenerationVisitor { void addExtensionsProperty(); - void applyServiceInjectionToProperty(PropertyMetaData property); + void applyServiceInjectionToProperty(PropertyMetadata property); - void applyServiceInjectionToGetter(PropertyMetaData property, Method getter); + void applyServiceInjectionToGetter(PropertyMetadata property, MethodMetadata getter); - void applyServiceInjectionToSetter(PropertyMetaData property, Method setter); + void applyServiceInjectionToSetter(PropertyMetadata property, Method setter); - void applyServiceInjectionToGetter(PropertyMetaData property, Class annotation, Method getter); + void applyServiceInjectionToGetter(PropertyMetadata property, Class annotation, MethodMetadata getter); - void applyServiceInjectionToSetter(PropertyMetaData property, Class annotation, Method setter); + void applyServiceInjectionToSetter(PropertyMetadata property, Class annotation, Method setter); - void applyManagedStateToProperty(PropertyMetaData property); + void applyManagedStateToProperty(PropertyMetadata property); - void applyManagedStateToGetter(PropertyMetaData property, Method getter); + void applyManagedStateToGetter(PropertyMetadata property, Method getter); - void applyManagedStateToSetter(PropertyMetaData property, Method setter); + void applyManagedStateToSetter(PropertyMetadata property, Method setter); - void applyReadOnlyManagedStateToGetter(PropertyMetaData property, Method getter); + void applyReadOnlyManagedStateToGetter(PropertyMetadata property, Method getter); - void addManagedMethods(List properties, List readOnlyProperties); + void addManagedMethods(List properties, List readOnlyProperties); - void applyConventionMappingToProperty(PropertyMetaData property); + void applyConventionMappingToProperty(PropertyMetadata property); - void applyConventionMappingToGetter(PropertyMetaData property, Method getter); + void applyConventionMappingToGetter(PropertyMetadata property, Method getter); - void applyConventionMappingToSetter(PropertyMetaData property, Method setter); + void applyConventionMappingToSetter(PropertyMetadata property, Method setter); - void applyConventionMappingToSetMethod(PropertyMetaData property, Method metaMethod); + void applyConventionMappingToSetMethod(PropertyMetadata property, Method metaMethod); - void addSetMethod(PropertyMetaData propertyMetaData, Method setter); + void addSetMethod(PropertyMetadata propertyMetaData, Method setter); void addActionMethod(Method method); - void addPropertySetters(PropertyMetaData property, Method getter); + void addPropertySetters(PropertyMetadata property, Method getter); Class generate() throws Exception; } diff --git a/subprojects/model-core/src/main/java/org/gradle/internal/instantiation/AsmBackedClassGenerator.java b/subprojects/model-core/src/main/java/org/gradle/internal/instantiation/AsmBackedClassGenerator.java index 537110bd3f28b..7eb64cebaa778 100644 --- a/subprojects/model-core/src/main/java/org/gradle/internal/instantiation/AsmBackedClassGenerator.java +++ b/subprojects/model-core/src/main/java/org/gradle/internal/instantiation/AsmBackedClassGenerator.java @@ -78,6 +78,7 @@ import java.util.Map; import java.util.Set; +import static org.gradle.model.internal.asm.AsmClassGeneratorUtils.getterSignature; import static org.gradle.model.internal.asm.AsmClassGeneratorUtils.signature; import static org.objectweb.asm.Opcodes.AALOAD; import static org.objectweb.asm.Opcodes.ACC_PRIVATE; @@ -436,6 +437,7 @@ public void addDefaultConstructor() { methodVisitor.visitEnd(); } + @Override public void addConstructor(Constructor constructor) { List paramTypes = new ArrayList(); for (Class paramType : constructor.getParameterTypes()) { @@ -500,6 +502,7 @@ public void add(MethodVisitor visitor) { }); } + @Override public void mixInDynamicAware() { if (!mixInDsl) { return; @@ -596,6 +599,7 @@ private void generateCreateDynamicObject(MethodVisitor visitor) { } } + @Override public void mixInConventionAware() { // GENERATE private ConventionMapping mapping @@ -637,6 +641,7 @@ public void add(MethodVisitor visitor) { // END } + @Override public void mixInGroovyObject() { if (!mixInDsl) { return; @@ -692,7 +697,7 @@ private void addSetter(String methodName, String methodDescriptor, MethodCodeBod } @Override - public void addPropertySetters(PropertyMetaData property, Method getter) { + public void addPropertySetters(PropertyMetadata property, Method getter) { if (!mixInDsl) { return; } @@ -753,6 +758,7 @@ private void addGetter(String methodName, Type returnType, String methodDescript methodVisitor.visitEnd(); } + @Override public void addDynamicMethods() { if (!mixInDsl) { return; @@ -854,7 +860,8 @@ public void add(MethodVisitor methodVisitor) { }); } - public void applyServiceInjectionToProperty(PropertyMetaData property) { + @Override + public void applyServiceInjectionToProperty(PropertyMetadata property) { // GENERATE private ; String fieldName = propFieldName(property); visitor.visitField(Opcodes.ACC_PRIVATE, fieldName, Type.getDescriptor(property.getType()), null, null); @@ -881,12 +888,13 @@ private void generateGetServices() { mv.visitEnd(); } - public void applyServiceInjectionToGetter(PropertyMetaData property, Method getter) { + @Override + public void applyServiceInjectionToGetter(PropertyMetadata property, MethodMetadata getter) { applyServiceInjectionToGetter(property, null, getter); } @Override - public void applyServiceInjectionToGetter(PropertyMetaData property, final Class annotation, Method getter) { + public void applyServiceInjectionToGetter(PropertyMetadata property, final Class annotation, MethodMetadata getter) { // GENERATE public () { if ( == null) { = >.get(>); } return } final String getterName = getter.getName(); Type returnType = Type.getType(getter.getReturnType()); @@ -894,7 +902,7 @@ public void applyServiceInjectionToGetter(PropertyMetaData property, final Class final Type serviceType = Type.getType(property.getType()); final java.lang.reflect.Type genericServiceType = property.getGenericType(); String propFieldName = propFieldName(property); - String signature = signature(getter); + String signature = getterSignature(getter.getGenericReturnType()); addLazyGetter(getterName, returnType, methodDescriptor, signature, propFieldName, serviceType, new MethodCodeBody() { @Override @@ -938,7 +946,7 @@ private void putServiceRegistryOnStack(MethodVisitor methodVisitor) { } @Override - public void applyServiceInjectionToSetter(PropertyMetaData property, Class annotation, Method setter) { + public void applyServiceInjectionToSetter(PropertyMetadata property, Class annotation, Method setter) { applyServiceInjectionToSetter(property, setter); } @@ -952,19 +960,20 @@ private String getConstantNameForGenericReturnType(java.lang.reflect.Type generi return entry.fieldName; } - public void applyServiceInjectionToSetter(PropertyMetaData property, Method setter) { + @Override + public void applyServiceInjectionToSetter(PropertyMetadata property, Method setter) { addSetterForProperty(property, setter); } @Override - public void applyManagedStateToProperty(PropertyMetaData property) { + public void applyManagedStateToProperty(PropertyMetadata property) { // GENERATE private ; String fieldName = propFieldName(property); visitor.visitField(Opcodes.ACC_PRIVATE, fieldName, Type.getDescriptor(property.getType()), null, null); } @Override - public void applyReadOnlyManagedStateToGetter(PropertyMetaData property, Method getter) { + public void applyReadOnlyManagedStateToGetter(PropertyMetadata property, Method getter) { // GENERATE public () { if ( == null) { = services.get(ObjectFactory.class).(xxx); } return } Type propType = Type.getType(property.getType()); Type returnType = Type.getType(getter.getReturnType()); @@ -1013,7 +1022,7 @@ public void applyReadOnlyManagedStateToGetter(PropertyMetaData property, Method } @Override - public void applyManagedStateToGetter(PropertyMetaData property, Method getter) { + public void applyManagedStateToGetter(PropertyMetadata property, Method getter) { // GENERATE public () { return } Type returnType = Type.getType(getter.getReturnType()); String methodDescriptor = Type.getMethodDescriptor(returnType); @@ -1025,11 +1034,11 @@ public void applyManagedStateToGetter(PropertyMetaData property, Method getter) } @Override - public void applyManagedStateToSetter(PropertyMetaData property, Method setter) { + public void applyManagedStateToSetter(PropertyMetadata property, Method setter) { addSetterForProperty(property, setter); } - private void addSetterForProperty(PropertyMetaData property, Method setter) { + private void addSetterForProperty(PropertyMetadata property, Method setter) { // GENERATE public void ( value) { == value } String methodDescriptor = Type.getMethodDescriptor(setter); Type fieldType = Type.getType(property.getType()); @@ -1059,7 +1068,7 @@ private void generatePublicTypeMethod() { } @Override - public void addManagedMethods(List mutableProperties, List readOnlyProperties) { + public void addManagedMethods(List mutableProperties, List readOnlyProperties) { visitor.visitField(PV_FINAL_STATIC, FACTORY_FIELD, Type.getType(Managed.Factory.class).getDescriptor(), null, null); // Generate: (Object[] state) { } @@ -1071,7 +1080,7 @@ public void addManagedMethods(List mutableProperties, List", RETURN_VOID, false); } for (int i = 0; i < mutableProperties.size(); i++) { - PropertyMetaData propertyMetaData = mutableProperties.get(i); + PropertyMetadata propertyMetaData = mutableProperties.get(i); methodVisitor.visitVarInsn(ALOAD, 0); methodVisitor.visitVarInsn(ALOAD, 1); methodVisitor.visitLdcInsn(i); @@ -1081,7 +1090,7 @@ public void addManagedMethods(List mutableProperties, List mutableProperties, List mutableProperties, List mutableProperties, List valueClass, Type val } } - public void applyConventionMappingToSetter(PropertyMetaData property, Method setter) { + @Override + public void applyConventionMappingToSetter(PropertyMetadata property, Method setter) { if (!conventionAware) { return; } @@ -1281,7 +1293,8 @@ public void applyConventionMappingToSetter(PropertyMetaData property, Method set methodVisitor.visitEnd(); } - public void addSetMethod(PropertyMetaData property, Method setter) { + @Override + public void addSetMethod(PropertyMetadata property, Method setter) { if (!mixInDsl) { return; } @@ -1309,7 +1322,8 @@ public void addSetMethod(PropertyMetaData property, Method setter) { methodVisitor.visitEnd(); } - public void applyConventionMappingToSetMethod(PropertyMetaData property, Method method) { + @Override + public void applyConventionMappingToSetMethod(PropertyMetadata property, Method method) { if (!mixInDsl || !conventionAware) { return; } @@ -1342,6 +1356,7 @@ public void applyConventionMappingToSetMethod(PropertyMetaData property, Method methodVisitor.visitEnd(); } + @Override public void addActionMethod(Method method) { if (!mixInDsl) { return; @@ -1385,7 +1400,7 @@ public Type transform(Class clazz) { methodVisitor.visitEnd(); } - void generateServiceRegistrySupportMethods() { + private void generateServiceRegistrySupportMethods() { generateServicesField(); generateGetServices(); } @@ -1462,6 +1477,7 @@ private Object getAnnotationParameterValue(Annotation annotation, Method method) } } + @Override public Class generate() { writeGenericReturnTypeFields(); visitor.visitEnd(); @@ -1561,63 +1577,63 @@ public void addExtensionsProperty() { } @Override - public void applyServiceInjectionToProperty(PropertyMetaData property) { + public void applyServiceInjectionToProperty(PropertyMetadata property) { } @Override - public void applyServiceInjectionToGetter(PropertyMetaData property, Method getter) { + public void applyServiceInjectionToGetter(PropertyMetadata property, MethodMetadata getter) { } @Override - public void applyServiceInjectionToSetter(PropertyMetaData property, Method setter) { + public void applyServiceInjectionToSetter(PropertyMetadata property, Method setter) { } @Override - public void applyServiceInjectionToGetter(PropertyMetaData property, Class annotation, Method getter) { + public void applyServiceInjectionToGetter(PropertyMetadata property, Class annotation, MethodMetadata getter) { } @Override - public void applyServiceInjectionToSetter(PropertyMetaData property, Class annotation, Method setter) { + public void applyServiceInjectionToSetter(PropertyMetadata property, Class annotation, Method setter) { } @Override - public void applyManagedStateToProperty(PropertyMetaData property) { + public void applyManagedStateToProperty(PropertyMetadata property) { } @Override - public void applyReadOnlyManagedStateToGetter(PropertyMetaData property, Method getter) { + public void applyReadOnlyManagedStateToGetter(PropertyMetadata property, Method getter) { } @Override - public void applyManagedStateToGetter(PropertyMetaData property, Method getter) { + public void applyManagedStateToGetter(PropertyMetadata property, Method getter) { } @Override - public void applyManagedStateToSetter(PropertyMetaData property, Method setter) { + public void applyManagedStateToSetter(PropertyMetadata property, Method setter) { } @Override - public void addManagedMethods(List properties, List readOnlyProperties) { + public void addManagedMethods(List properties, List readOnlyProperties) { } @Override - public void applyConventionMappingToProperty(PropertyMetaData property) { + public void applyConventionMappingToProperty(PropertyMetadata property) { } @Override - public void applyConventionMappingToGetter(PropertyMetaData property, Method getter) { + public void applyConventionMappingToGetter(PropertyMetadata property, Method getter) { } @Override - public void applyConventionMappingToSetter(PropertyMetaData property, Method setter) { + public void applyConventionMappingToSetter(PropertyMetadata property, Method setter) { } @Override - public void applyConventionMappingToSetMethod(PropertyMetaData property, Method metaMethod) { + public void applyConventionMappingToSetMethod(PropertyMetadata property, Method metaMethod) { } @Override - public void addSetMethod(PropertyMetaData propertyMetaData, Method setter) { + public void addSetMethod(PropertyMetadata propertyMetaData, Method setter) { } @Override @@ -1625,7 +1641,7 @@ public void addActionMethod(Method method) { } @Override - public void addPropertySetters(PropertyMetaData property, Method getter) { + public void addPropertySetters(PropertyMetadata property, Method getter) { } @Override diff --git a/subprojects/model-core/src/main/java/org/gradle/model/internal/asm/AsmClassGeneratorUtils.java b/subprojects/model-core/src/main/java/org/gradle/model/internal/asm/AsmClassGeneratorUtils.java index 74e4c25bab1e6..d5c2e0a63c6dc 100644 --- a/subprojects/model-core/src/main/java/org/gradle/model/internal/asm/AsmClassGeneratorUtils.java +++ b/subprojects/model-core/src/main/java/org/gradle/model/internal/asm/AsmClassGeneratorUtils.java @@ -18,7 +18,12 @@ import org.objectweb.asm.Type; -import java.lang.reflect.*; +import java.lang.reflect.Constructor; +import java.lang.reflect.GenericArrayType; +import java.lang.reflect.Method; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.TypeVariable; +import java.lang.reflect.WildcardType; public class AsmClassGeneratorUtils { @@ -34,6 +39,13 @@ public static String signature(Constructor constructor) { return builder.toString(); } + public static String getterSignature(java.lang.reflect.Type returnType) { + StringBuilder builder = new StringBuilder(); + builder.append("()"); + visitType(returnType, builder); + return builder.toString(); + } + /** * Generates the signature for the given method */ diff --git a/subprojects/model-core/src/test/groovy/org/gradle/internal/instantiation/AsmBackedClassGeneratorInjectDecoratedTest.groovy b/subprojects/model-core/src/test/groovy/org/gradle/internal/instantiation/AsmBackedClassGeneratorInjectDecoratedTest.groovy index ce77d26b3c6f1..16802bc286676 100644 --- a/subprojects/model-core/src/test/groovy/org/gradle/internal/instantiation/AsmBackedClassGeneratorInjectDecoratedTest.groovy +++ b/subprojects/model-core/src/test/groovy/org/gradle/internal/instantiation/AsmBackedClassGeneratorInjectDecoratedTest.groovy @@ -21,16 +21,16 @@ import org.gradle.api.plugins.ExtensionContainer import org.gradle.internal.service.DefaultServiceRegistry import org.gradle.internal.service.ServiceLookup import org.gradle.internal.service.ServiceRegistry -import org.gradle.util.ToBeImplemented import javax.inject.Inject import java.lang.annotation.Annotation import java.lang.annotation.Retention import java.lang.annotation.RetentionPolicy -import java.lang.reflect.InvocationTargetException import java.lang.reflect.ParameterizedType import java.lang.reflect.Type +import static org.gradle.internal.instantiation.AsmBackedClassGeneratorTest.AbstractClassWithConcreteTypeParameter +import static org.gradle.internal.instantiation.AsmBackedClassGeneratorTest.AbstractClassWithParameterizedTypeParameter import static org.gradle.internal.instantiation.AsmBackedClassGeneratorTest.FinalInjectBean import static org.gradle.internal.instantiation.AsmBackedClassGeneratorTest.NonGetterInjectBean import static org.gradle.internal.instantiation.AsmBackedClassGeneratorTest.PrivateInjectBean @@ -66,8 +66,7 @@ class AsmBackedClassGeneratorInjectDecoratedTest extends AbstractClassGeneratorS obj.getProperty("thing") == 12 } - @ToBeImplemented("Resolving type parameters to implement the correct methods in the subclass does not work, yet") - def "can inject service using @Inject on a super interface with type parameters"() { + def "can inject service using @Inject on a super interface with class type parameter"() { given: def services = Mock(ServiceLookup) _ * services.get(Number) >> 12 @@ -76,11 +75,40 @@ class AsmBackedClassGeneratorInjectDecoratedTest extends AbstractClassGeneratorS def obj = create(AbstractClassWithConcreteTypeParameter, services) then: - def e = thrown(InvocationTargetException) - e.cause.class == NullPointerException -// obj.thing == 12 -// obj.getThing() == 12 -// obj.getProperty("thing") == 12 + obj.thing == 12 + obj.getThing() == 12 + obj.getProperty("thing") == 12 + obj.doSomething() + + def returnType = obj.getClass().getDeclaredMethod("getThing").genericReturnType + returnType == Number + } + + def "can inject service using @Inject on a super interface with parameterized type parameter"() { + given: + def services = Mock(ServiceLookup) + _ * services.get(_) >> { Type type -> + assert type instanceof ParameterizedType + assert type.rawType == List.class + assert type.actualTypeArguments.length == 1 + assert type.actualTypeArguments[0] == Number + return [12] + } + + when: + def obj = create(AbstractClassWithParameterizedTypeParameter, services) + + then: + obj.thing == [12] + obj.getThing() == [12] + obj.getProperty("thing") == [12] + obj.doSomething() == "[12]" + + def returnType = obj.getClass().getDeclaredMethod("getThing").genericReturnType + returnType instanceof ParameterizedType + returnType.rawType == List + returnType.actualTypeArguments.length == 1 + returnType.actualTypeArguments[0] == Number } def "can inject service using @Inject on an interface getter method"() { @@ -330,13 +358,6 @@ interface InterfaceWithServices { Number getThing() } -interface InterfaceWithTypeParameter { - @Inject - T getThing() -} - -abstract class AbstractClassWithConcreteTypeParameter implements InterfaceWithTypeParameter {} - class BeanWithServices { @Inject Number getThing() { diff --git a/subprojects/model-core/src/test/groovy/org/gradle/internal/instantiation/AsmBackedClassGeneratorTest.java b/subprojects/model-core/src/test/groovy/org/gradle/internal/instantiation/AsmBackedClassGeneratorTest.java index 683de491370b8..b4a2748847747 100755 --- a/subprojects/model-core/src/test/groovy/org/gradle/internal/instantiation/AsmBackedClassGeneratorTest.java +++ b/subprojects/model-core/src/test/groovy/org/gradle/internal/instantiation/AsmBackedClassGeneratorTest.java @@ -1820,4 +1820,23 @@ void thing() { setName("thing"); } } + + interface InterfaceWithTypeParameter { + @Inject + T getThing(); + } + + public static abstract class AbstractClassWithConcreteTypeParameter implements InterfaceWithTypeParameter { + public String doSomething() { + Number thing = getThing(); + return String.valueOf(thing); + } + } + + public static abstract class AbstractClassWithParameterizedTypeParameter implements InterfaceWithTypeParameter> { + public String doSomething() { + List thing = getThing(); + return thing.toString(); + } + } } From e81eaf42a8af78dd79c6adf52bc2fdb3150578c7 Mon Sep 17 00:00:00 2001 From: Louis Jacomet Date: Tue, 26 Feb 2019 11:33:56 +0100 Subject: [PATCH 137/853] Rebase Android performance test Following changes for #8099 this performance test saw a significant performance boost of about 20%. --- .../android/RealLifeAndroidStudioMockupPerformanceTest.groovy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subprojects/performance/src/performanceTest/groovy/org/gradle/performance/regression/android/RealLifeAndroidStudioMockupPerformanceTest.groovy b/subprojects/performance/src/performanceTest/groovy/org/gradle/performance/regression/android/RealLifeAndroidStudioMockupPerformanceTest.groovy index 5eef3a926d40f..9902e8fad35ff 100644 --- a/subprojects/performance/src/performanceTest/groovy/org/gradle/performance/regression/android/RealLifeAndroidStudioMockupPerformanceTest.groovy +++ b/subprojects/performance/src/performanceTest/groovy/org/gradle/performance/regression/android/RealLifeAndroidStudioMockupPerformanceTest.groovy @@ -27,7 +27,7 @@ class RealLifeAndroidStudioMockupPerformanceTest extends AbstractAndroidStudioMo experiment(testProject) { minimumVersion = "4.3.1" - targetVersions = ["5.3-20190122101802+0000"] + targetVersions = ["5.3-20190226013556+0000"] action('org.gradle.performance.android.SyncAction') { jvmArguments = ["-Xms5g", "-Xmx5g"] } From bbc51c618ad532f98436d74b49b9d1f169e26953 Mon Sep 17 00:00:00 2001 From: Stefan Wolf Date: Tue, 26 Feb 2019 09:47:37 +0100 Subject: [PATCH 138/853] Rename registerTransform{Action -> } --- .../api/artifacts/dsl/DependencyHandler.java | 13 +------ .../transform/ParameterizedTransformSpec.java | 39 ------------------- .../artifacts/transform/TransformAction.java | 2 +- .../artifacts/transform/TransformSpec.java | 15 ++++++- ...factTransformCachingIntegrationTest.groovy | 4 +- .../ArtifactTransformIntegrationTest.groovy | 8 ++-- ...ctTransformIsolationIntegrationTest.groovy | 6 +-- .../ArtifactTransformTestFixture.groovy | 4 +- ...sformValuesInjectionIntegrationTest.groovy | 2 +- ...formWithDependenciesIntegrationTest.groovy | 14 +++---- ...nsformWithFileInputsIntegrationTest.groovy | 2 +- .../artifacts/VariantTransformRegistry.java | 6 +-- .../DefaultDependencyHandler.java | 11 ++---- ...aultTransformationRegistrationFactory.java | 3 +- .../transform/DefaultTransformer.java | 15 +++---- .../DefaultVariantTransformRegistry.java | 28 +++---------- .../TransformationRegistrationFactory.java | 3 +- ...DefaultVariantTransformRegistryTest.groovy | 33 ++++++---------- .../language/plugins/NativeBasePlugin.java | 2 +- ...ractConsoleBuildPhaseFunctionalTest.groovy | 2 +- 20 files changed, 71 insertions(+), 141 deletions(-) delete mode 100644 subprojects/core-api/src/main/java/org/gradle/api/artifacts/transform/ParameterizedTransformSpec.java diff --git a/subprojects/core-api/src/main/java/org/gradle/api/artifacts/dsl/DependencyHandler.java b/subprojects/core-api/src/main/java/org/gradle/api/artifacts/dsl/DependencyHandler.java index 692b787584519..eb2552d80a710 100644 --- a/subprojects/core-api/src/main/java/org/gradle/api/artifacts/dsl/DependencyHandler.java +++ b/subprojects/core-api/src/main/java/org/gradle/api/artifacts/dsl/DependencyHandler.java @@ -20,9 +20,9 @@ import org.gradle.api.Incubating; import org.gradle.api.artifacts.Dependency; import org.gradle.api.artifacts.query.ArtifactResolutionQuery; -import org.gradle.api.artifacts.transform.ParameterizedTransformSpec; import org.gradle.api.artifacts.transform.TransformAction; import org.gradle.api.artifacts.transform.TransformParameters; +import org.gradle.api.artifacts.transform.TransformSpec; import org.gradle.api.artifacts.transform.VariantTransform; import org.gradle.api.artifacts.type.ArtifactTypeContainer; import org.gradle.api.attributes.AttributesSchema; @@ -445,15 +445,6 @@ public interface DependencyHandler { */ void registerTransform(Action registrationAction); - /** - * Registers an artifact transform with a parameter object. - * - * @see TransformAction - * @since 5.2 - */ - @Incubating - void registerTransform(Class parameterType, Action> registrationAction); - /** * Registers an artifact transform without a parameter object. * @@ -461,7 +452,7 @@ public interface DependencyHandler { * @since 5.3 */ @Incubating - void registerTransformAction(Class> actionType, Action> registrationAction); + void registerTransform(Class> actionType, Action> registrationAction); /** * Declares a dependency on a platform. If the target coordinates represent multiple diff --git a/subprojects/core-api/src/main/java/org/gradle/api/artifacts/transform/ParameterizedTransformSpec.java b/subprojects/core-api/src/main/java/org/gradle/api/artifacts/transform/ParameterizedTransformSpec.java deleted file mode 100644 index 7635456c66431..0000000000000 --- a/subprojects/core-api/src/main/java/org/gradle/api/artifacts/transform/ParameterizedTransformSpec.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright 2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.gradle.api.artifacts.transform; - -import org.gradle.api.Action; -import org.gradle.api.Incubating; - -/** - * Defines an artifact transformation. - * - * @param The transform specific parameter type. - * @since 5.3 - */ -@Incubating -public interface ParameterizedTransformSpec extends TransformSpec { - /** - * The parameters for the transform action. - */ - T getParameters(); - - /** - * Configure the parameters for the transform action. - */ - void parameters(Action action); -} diff --git a/subprojects/core-api/src/main/java/org/gradle/api/artifacts/transform/TransformAction.java b/subprojects/core-api/src/main/java/org/gradle/api/artifacts/transform/TransformAction.java index 8d4e4f2fc24cb..ec21b3af2f318 100644 --- a/subprojects/core-api/src/main/java/org/gradle/api/artifacts/transform/TransformAction.java +++ b/subprojects/core-api/src/main/java/org/gradle/api/artifacts/transform/TransformAction.java @@ -25,7 +25,7 @@ * *

    Implementations can receive parameters by using annotated abstract getter methods.

    * - *

    A property annotated with {@link InjectTransformParameters} will receive the object provided by {@link ParameterizedTransformSpec#getParameters()}. + *

    A property annotated with {@link InjectTransformParameters} will receive the object provided by {@link TransformSpec#getParameters()}. * *

    A property annotated with {@link InputArtifact} will receive the input artifact location, which is the file or directory that the transform should be applied to. * diff --git a/subprojects/core-api/src/main/java/org/gradle/api/artifacts/transform/TransformSpec.java b/subprojects/core-api/src/main/java/org/gradle/api/artifacts/transform/TransformSpec.java index 68fc1db97a93d..3512d9d397973 100644 --- a/subprojects/core-api/src/main/java/org/gradle/api/artifacts/transform/TransformSpec.java +++ b/subprojects/core-api/src/main/java/org/gradle/api/artifacts/transform/TransformSpec.java @@ -16,16 +16,17 @@ package org.gradle.api.artifacts.transform; +import org.gradle.api.Action; import org.gradle.api.Incubating; import org.gradle.api.attributes.AttributeContainer; /** * Base configuration for artifact transform registrations. - * + * @param The transform specific parameter type. * @since 5.3 */ @Incubating -public interface TransformSpec { +public interface TransformSpec { /** * Attributes that match the variant that is consumed. */ @@ -35,4 +36,14 @@ public interface TransformSpec { * Attributes that match the variant that is produced. */ AttributeContainer getTo(); + + /** + * The parameters for the transform action. + */ + T getParameters(); + + /** + * Configure the parameters for the transform action. + */ + void parameters(Action action); } diff --git a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformCachingIntegrationTest.groovy b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformCachingIntegrationTest.groovy index 207cfd7a34eca..420ddf3468d87 100644 --- a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformCachingIntegrationTest.groovy +++ b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformCachingIntegrationTest.groovy @@ -1499,7 +1499,7 @@ ${getFileSizerBody(fileValue, 'outputs.dir(', 'outputs.file(')} allprojects { dependencies { - registerTransformAction(FileSizer) { + registerTransform(FileSizer) { from.attribute(artifactType, "jar") to.attribute(artifactType, "size") parameters { @@ -1570,7 +1570,7 @@ ${getFileSizerBody(fileValue, 'outputs.dir(', 'outputs.file(')} """ allprojects { dependencies { - registerTransform${useParameterObject ? "Action(FileSizer)" : ""} { + registerTransform${useParameterObject ? "(FileSizer)" : ""} { from.attribute(artifactType, "classes") to.attribute(artifactType, "size") ${useParameterObject ? "parameters { value = paramValue }" : "artifactTransform(FileSizer) { params(paramValue) }"} diff --git a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformIntegrationTest.groovy b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformIntegrationTest.groovy index 391385f253a34..3bbf3201ba79b 100644 --- a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformIntegrationTest.groovy +++ b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformIntegrationTest.groovy @@ -797,7 +797,7 @@ $fileSizer } dependencies { - registerTransformAction(IdentityTransform) { + registerTransform(IdentityTransform) { from.attribute(artifactType, 'jar') to.attribute(artifactType, 'identity') } @@ -1672,7 +1672,7 @@ Found the following transforms: } } dependencies { - registerTransformAction(MyTransform) { + registerTransform(MyTransform) { from.attribute(artifactType, 'directory') to.attribute(artifactType, 'size') } @@ -1958,7 +1958,7 @@ Found the following transforms: } dependencies { - registerTransformAction(Custom) { + registerTransform(Custom) { from.attribute(artifactType, 'jar') to.attribute(artifactType, 'size') parameters { @@ -2305,7 +2305,7 @@ Found the following transforms: def declareTransformAction(String transformActionImplementation) { """ dependencies { - registerTransformAction($transformActionImplementation) { + registerTransform($transformActionImplementation) { from.attribute(artifactType, 'jar') to.attribute(artifactType, 'size') } diff --git a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformIsolationIntegrationTest.groovy b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformIsolationIntegrationTest.groovy index 7a68aaed19650..df98ce43994aa 100644 --- a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformIsolationIntegrationTest.groovy +++ b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformIsolationIntegrationTest.groovy @@ -134,7 +134,7 @@ class Resolve extends Copy { } dependencies { - registerTransformAction(CountRecorder) { + registerTransform(CountRecorder) { from.attribute(artifactType, 'jar') to.attribute(artifactType, 'firstCount') parameters { @@ -142,14 +142,14 @@ class Resolve extends Copy { } } buildScriptCounter.increment() - registerTransformAction(CountRecorder) { + registerTransform(CountRecorder) { from.attribute(artifactType, 'jar') to.attribute(artifactType, 'secondCount') parameters { counter = buildScriptCounter } } - registerTransformAction(CountRecorder) { + registerTransform(CountRecorder) { from.attribute(artifactType, 'jar') to.attribute(artifactType, 'thirdCount') parameters { diff --git a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformTestFixture.groovy b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformTestFixture.groovy index b344cf57619e3..cee608de76900 100644 --- a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformTestFixture.groovy +++ b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformTestFixture.groovy @@ -156,7 +156,7 @@ class JarProducer extends DefaultTask { buildFile << """ allprojects { dependencies { - registerTransformAction(MakeGreen) { + registerTransform(MakeGreen) { from.attribute(color, 'blue') to.attribute(color, 'green') } @@ -180,7 +180,7 @@ allprojects { buildFile << """ allprojects { p -> dependencies { - registerTransformAction(MakeGreen) { + registerTransform(MakeGreen) { from.attribute(color, 'blue') to.attribute(color, 'green') parameters { diff --git a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformValuesInjectionIntegrationTest.groovy b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformValuesInjectionIntegrationTest.groovy index 0a8909edbb13e..193bee5e945c8 100644 --- a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformValuesInjectionIntegrationTest.groovy +++ b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformValuesInjectionIntegrationTest.groovy @@ -47,7 +47,7 @@ class ArtifactTransformValuesInjectionIntegrationTest extends AbstractDependency buildFile << """ allprojects { dependencies { - registerTransformAction(MakeGreen) { + registerTransform(MakeGreen) { from.attribute(color, 'blue') to.attribute(color, 'green') parameters { diff --git a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformWithDependenciesIntegrationTest.groovy b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformWithDependenciesIntegrationTest.groovy index 90f157ab62350..049d794d558d1 100644 --- a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformWithDependenciesIntegrationTest.groovy +++ b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformWithDependenciesIntegrationTest.groovy @@ -154,7 +154,7 @@ abstract class SimpleTransform implements TransformAction { buildFile << """ allprojects { dependencies { - registerTransformAction(TestTransform) { + registerTransform(TestTransform) { from.attribute(color, 'blue') to.attribute(color, 'green') parameters { @@ -172,11 +172,11 @@ allprojects { allprojects { dependencies { //Multi step transform, without dependencies at step 1 - registerTransformAction(SimpleTransform) { + registerTransform(SimpleTransform) { from.attribute(color, 'blue') to.attribute(color, 'yellow') } - registerTransformAction(TestTransform) { + registerTransform(TestTransform) { from.attribute(color, 'yellow') to.attribute(color, 'green') parameters { @@ -194,14 +194,14 @@ allprojects { allprojects { dependencies { // Multi step transform - registerTransformAction(TestTransform) { + registerTransform(TestTransform) { from.attribute(color, 'blue') to.attribute(color, 'yellow') parameters { transformName = 'Transform step 1' } } - registerTransformAction(TestTransform) { + registerTransform(TestTransform) { from.attribute(color, 'yellow') to.attribute(color, 'green') parameters { @@ -412,7 +412,7 @@ project(':common') { buildFile << """ allprojects { dependencies { - registerTransformAction(NoneTransform) { + registerTransform(NoneTransform) { from.attribute(color, 'blue') to.attribute(color, 'green') } @@ -508,7 +508,7 @@ abstract class NoneTransform implements TransformAction { buildFile << """ allprojects { dependencies { - registerTransformAction(ClasspathTransform) { + registerTransform(ClasspathTransform) { from.attribute(color, 'blue') to.attribute(color, 'green') } diff --git a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformWithFileInputsIntegrationTest.groovy b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformWithFileInputsIntegrationTest.groovy index 44cc1742a338d..0281300db597f 100644 --- a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformWithFileInputsIntegrationTest.groovy +++ b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformWithFileInputsIntegrationTest.groovy @@ -174,7 +174,7 @@ class ArtifactTransformWithFileInputsIntegrationTest extends AbstractDependencyR attributes.attribute(attr, 'red') }.files dependencies { - registerTransformAction(MakeRed) { + registerTransform(MakeRed) { from.attribute(color, 'blue') to.attribute(color, 'red') } diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/VariantTransformRegistry.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/VariantTransformRegistry.java index 8e6e42d3efb72..50fcb3e30b9a0 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/VariantTransformRegistry.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/VariantTransformRegistry.java @@ -17,9 +17,9 @@ package org.gradle.api.internal.artifacts; import org.gradle.api.Action; -import org.gradle.api.artifacts.transform.ParameterizedTransformSpec; import org.gradle.api.artifacts.transform.TransformAction; import org.gradle.api.artifacts.transform.TransformParameters; +import org.gradle.api.artifacts.transform.TransformSpec; import org.gradle.api.artifacts.transform.VariantTransform; public interface VariantTransformRegistry { @@ -31,9 +31,7 @@ public interface VariantTransformRegistry { */ void registerTransform(Action registrationAction); - void registerTransform(Class parameterType, Action> registrationAction); - - void registerTransformAction(Class> actionType, Action> registrationAction); + void registerTransform(Class> actionType, Action> registrationAction); Iterable getTransforms(); } diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/dsl/dependencies/DefaultDependencyHandler.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/dsl/dependencies/DefaultDependencyHandler.java index 840bac0692af8..9ab7c116d3f06 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/dsl/dependencies/DefaultDependencyHandler.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/dsl/dependencies/DefaultDependencyHandler.java @@ -27,9 +27,9 @@ import org.gradle.api.artifacts.dsl.DependencyConstraintHandler; import org.gradle.api.artifacts.dsl.DependencyHandler; import org.gradle.api.artifacts.query.ArtifactResolutionQuery; -import org.gradle.api.artifacts.transform.ParameterizedTransformSpec; import org.gradle.api.artifacts.transform.TransformAction; import org.gradle.api.artifacts.transform.TransformParameters; +import org.gradle.api.artifacts.transform.TransformSpec; import org.gradle.api.artifacts.transform.VariantTransform; import org.gradle.api.artifacts.type.ArtifactTypeContainer; import org.gradle.api.attributes.AttributesSchema; @@ -215,13 +215,8 @@ public void registerTransform(Action registrationActio } @Override - public void registerTransform(Class parameterType, Action> registrationAction) { - transforms.registerTransform(parameterType, registrationAction); - } - - @Override - public void registerTransformAction(Class> actionType, Action> registrationAction) { - transforms.registerTransformAction(actionType, registrationAction); + public void registerTransform(Class> actionType, Action> registrationAction) { + transforms.registerTransform(actionType, registrationAction); } @Override diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformationRegistrationFactory.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformationRegistrationFactory.java index 0da58e27bf9f4..1d19a6da89b73 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformationRegistrationFactory.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformationRegistrationFactory.java @@ -22,6 +22,7 @@ import org.gradle.api.artifacts.transform.InputArtifact; import org.gradle.api.artifacts.transform.InputArtifactDependencies; import org.gradle.api.artifacts.transform.TransformAction; +import org.gradle.api.artifacts.transform.TransformParameters; import org.gradle.api.internal.artifacts.ArtifactTransformRegistration; import org.gradle.api.internal.attributes.AttributeContainerInternal; import org.gradle.api.internal.attributes.ImmutableAttributes; @@ -88,7 +89,7 @@ public DefaultTransformationRegistrationFactory( } @Override - public ArtifactTransformRegistration create(ImmutableAttributes from, ImmutableAttributes to, Class implementation, @Nullable Object parameterObject) { + public ArtifactTransformRegistration create(ImmutableAttributes from, ImmutableAttributes to, Class implementation, @Nullable TransformParameters parameterObject) { List validationMessages = new ArrayList<>(); TypeMetadata actionMetadata = actionMetadataStore.getTypeMetadata(implementation); DefaultParameterValidationContext parameterValidationContext = new DefaultParameterValidationContext(validationMessages); diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformer.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformer.java index dba22da017f6e..e659f026c74ac 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformer.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformer.java @@ -25,6 +25,7 @@ import org.gradle.api.artifacts.transform.InputArtifact; import org.gradle.api.artifacts.transform.InputArtifactDependencies; import org.gradle.api.artifacts.transform.TransformAction; +import org.gradle.api.artifacts.transform.TransformParameters; import org.gradle.api.artifacts.transform.VariantTransformConfigurationException; import org.gradle.api.file.FileCollection; import org.gradle.api.internal.attributes.ImmutableAttributes; @@ -75,7 +76,7 @@ public class DefaultTransformer extends AbstractTransformer { - private final Object parameterObject; + private final TransformParameters parameterObject; private final Class fileNormalizer; private final Class dependenciesNormalizer; private final ClassLoaderHierarchyHasher classLoaderHierarchyHasher; @@ -95,7 +96,7 @@ public class DefaultTransformer extends AbstractTransformer { public DefaultTransformer( Class implementationClass, - @Nullable Object parameterObject, + @Nullable TransformParameters parameterObject, ImmutableAttributes fromAttributes, Class inputArtifactNormalizer, Class dependenciesNormalizer, @@ -221,7 +222,7 @@ private void isolateExclusively() { } protected IsolatableParameters doIsolateParameters() { - Isolatable isolatableParameterObject = isolatableFactory.isolate(parameterObject); + Isolatable isolatableParameterObject = isolatableFactory.isolate(parameterObject); Hasher hasher = Hashing.newHasher(); appendActionImplementation(getImplementationClass(), hasher, classLoaderHierarchyHasher); @@ -318,7 +319,7 @@ private IsolatableParameters getIsolatable() { private static class TransformServiceLookup implements ServiceLookup { private final ImmutableList injectionPoints; - public TransformServiceLookup(File inputFile, @Nullable Object parameters, @Nullable ArtifactTransformDependencies artifactTransformDependencies) { + public TransformServiceLookup(File inputFile, @Nullable TransformParameters parameters, @Nullable ArtifactTransformDependencies artifactTransformDependencies) { ImmutableList.Builder builder = ImmutableList.builder(); builder.add(new InjectionPoint(InputArtifact.class, File.class, inputFile)); if (parameters != null) { @@ -404,9 +405,9 @@ public Object getValueToInject() { private static class IsolatableParameters { private HashCode secondaryInputsHash; - private Isolatable isolatableParameters; + private Isolatable isolatableParameters; - public IsolatableParameters(Isolatable isolatableParameters, HashCode secondaryInputsHash) { + public IsolatableParameters(Isolatable isolatableParameters, HashCode secondaryInputsHash) { this.secondaryInputsHash = secondaryInputsHash; this.isolatableParameters = isolatableParameters; } @@ -415,7 +416,7 @@ public HashCode getSecondaryInputsHash() { return secondaryInputsHash; } - public Isolatable getIsolatableParameters() { + public Isolatable getIsolatableParameters() { return isolatableParameters; } } diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultVariantTransformRegistry.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultVariantTransformRegistry.java index cda198b01dafb..964a657ae29c1 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultVariantTransformRegistry.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultVariantTransformRegistry.java @@ -22,8 +22,6 @@ import org.gradle.api.ActionConfiguration; import org.gradle.api.NonExtensible; import org.gradle.api.artifacts.transform.ArtifactTransform; -import org.gradle.api.artifacts.transform.AssociatedTransformAction; -import org.gradle.api.artifacts.transform.ParameterizedTransformSpec; import org.gradle.api.artifacts.transform.TransformAction; import org.gradle.api.artifacts.transform.TransformParameters; import org.gradle.api.artifacts.transform.TransformSpec; @@ -81,16 +79,7 @@ public void registerTransform(Action registrationActio } @Override - public void registerTransform(Class parameterType, Action> registrationAction) { - T parameterObject = parametersInstantiationScheme.withServices(services).newInstance(parameterType); - TypedRegistration registration = Cast.uncheckedNonnullCast(instantiatorFactory.decorateLenient().newInstance(TypedRegistration.class, parameterObject, immutableAttributesFactory)); - registrationAction.execute(registration); - - register(registration, registration.actionType, parameterObject); - } - - @Override - public void registerTransformAction(Class> actionType, Action> registrationAction) { + public void registerTransform(Class> actionType, Action> registrationAction) { ParameterizedType superType = (ParameterizedType) TypeToken.of(actionType).getSupertype(TransformAction.class).getType(); Class parameterType = Cast.uncheckedNonnullCast(TypeToken.of(superType.getActualTypeArguments()[0]).getRawType()); T parameterObject = parameterType == TransformParameters.class ? null : parametersInstantiationScheme.withServices(services).newInstance(parameterType); @@ -100,7 +89,7 @@ public void registerTransformAction(Class void register(RecordingRegistration registration, Class actionType, @Nullable T parameterObject) { + private void register(RecordingRegistration registration, Class actionType, @Nullable T parameterObject) { validateActionType(actionType); validateAttributes(registration); try { @@ -117,7 +106,7 @@ private void validateActionType(@Nullable Class actionType) { } } - private void validateAttributes(RecordingRegistration registration) { + private void validateAttributes(RecordingRegistration registration) { if (registration.to.isEmpty()) { throw new VariantTransformConfigurationException("Could not register transform: at least one 'to' attribute must be provided."); } @@ -133,7 +122,7 @@ public Iterable getTransforms() { return transforms; } - public static abstract class RecordingRegistration implements TransformSpec { + public static abstract class RecordingRegistration { final AttributeContainerInternal from; final AttributeContainerInternal to; @@ -187,19 +176,12 @@ Object[] getTransformParameters() { } @NonExtensible - public static class TypedRegistration extends RecordingRegistration implements ParameterizedTransformSpec { + public static class TypedRegistration extends RecordingRegistration implements TransformSpec { private final T parameterObject; - Class actionType; public TypedRegistration(@Nullable T parameterObject, ImmutableAttributesFactory immutableAttributesFactory) { super(immutableAttributesFactory); this.parameterObject = parameterObject; - if (parameterObject != null) { - AssociatedTransformAction associatedTransformAction = parameterObject.getClass().getAnnotation(AssociatedTransformAction.class); - if (associatedTransformAction != null) { - actionType = associatedTransformAction.value(); - } - } } @Override diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/TransformationRegistrationFactory.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/TransformationRegistrationFactory.java index 082bde6fffdc3..a77b05efac028 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/TransformationRegistrationFactory.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/TransformationRegistrationFactory.java @@ -18,12 +18,13 @@ import org.gradle.api.artifacts.transform.ArtifactTransform; import org.gradle.api.artifacts.transform.TransformAction; +import org.gradle.api.artifacts.transform.TransformParameters; import org.gradle.api.internal.artifacts.ArtifactTransformRegistration; import org.gradle.api.internal.attributes.ImmutableAttributes; import javax.annotation.Nullable; public interface TransformationRegistrationFactory { - ArtifactTransformRegistration create(ImmutableAttributes from, ImmutableAttributes to, Class implementation, @Nullable Object parameterObject); + ArtifactTransformRegistration create(ImmutableAttributes from, ImmutableAttributes to, Class implementation, @Nullable TransformParameters parameterObject); ArtifactTransformRegistration create(ImmutableAttributes from, ImmutableAttributes to, Class implementation, Object[] params); } diff --git a/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/DefaultVariantTransformRegistryTest.groovy b/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/DefaultVariantTransformRegistryTest.groovy index cf35924c24443..0cd5bc39a8fe5 100644 --- a/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/DefaultVariantTransformRegistryTest.groovy +++ b/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/DefaultVariantTransformRegistryTest.groovy @@ -130,7 +130,7 @@ class DefaultVariantTransformRegistryTest extends Specification { def "creates registration with annotated parameters object"() { when: - registry.registerTransformAction(TestTransform) { + registry.registerTransform(TestTransform) { it.from.attribute(TEST_ATTRIBUTE, "FROM") it.to.attribute(TEST_ATTRIBUTE, "TO") } @@ -146,7 +146,7 @@ class DefaultVariantTransformRegistryTest extends Specification { def "creates registration for parametereless action"() { when: - registry.registerTransformAction(ParameterlessTestTransform) { + registry.registerTransform(ParameterlessTestTransform) { it.from.attribute(TEST_ATTRIBUTE, "FROM") it.to.attribute(TEST_ATTRIBUTE, "TO") } @@ -162,7 +162,7 @@ class DefaultVariantTransformRegistryTest extends Specification { def "cannot configure parameters for parameterless action"() { when: - registry.registerTransformAction(ParameterlessTestTransform) { + registry.registerTransform(ParameterlessTestTransform) { it.from.attribute(TEST_ATTRIBUTE, "FROM") it.to.attribute(TEST_ATTRIBUTE, "TO") it.parameters { @@ -177,7 +177,7 @@ class DefaultVariantTransformRegistryTest extends Specification { def "cannot query parameters object for parameterless action"() { when: - registry.registerTransformAction(ParameterlessTestTransform) { + registry.registerTransform(ParameterlessTestTransform) { it.from.attribute(TEST_ATTRIBUTE, "FROM") it.to.attribute(TEST_ATTRIBUTE, "TO") it.parameters @@ -193,7 +193,7 @@ class DefaultVariantTransformRegistryTest extends Specification { def registration when: - registry.registerTransformAction(TestTransform) { + registry.registerTransform(TestTransform) { it.from.attribute(TEST_ATTRIBUTE, "FROM") it.to.attribute(TEST_ATTRIBUTE, "TO") registration = it @@ -232,17 +232,6 @@ class DefaultVariantTransformRegistryTest extends Specification { e.cause == null } - def "fails when registering unannotated parameter type"() { - when: - registry.registerTransform(UnAnnotatedTestTransformConfig) { - } - - then: - def e = thrown(VariantTransformConfigurationException) - e.message == 'Could not register transform: an artifact transform action must be provided.' - e.cause == null - } - def "fails when multiple artifactTransforms are provided for registration"() { when: registry.registerTransform { @@ -269,9 +258,9 @@ class DefaultVariantTransformRegistryTest extends Specification { e.cause == null } - def "fails when no from attributes are provided for registerTransformAction"() { + def "fails when no from attributes are provided for registerTransform"() { when: - registry.registerTransformAction(TestTransform) { + registry.registerTransform(TestTransform) { it.to.attribute(TEST_ATTRIBUTE, "to") } @@ -294,9 +283,9 @@ class DefaultVariantTransformRegistryTest extends Specification { e.cause == null } - def "fails when no to attributes are provided for registerTransformAction"() { + def "fails when no to attributes are provided for registerTransform"() { when: - registry.registerTransformAction(TestTransform) { + registry.registerTransform(TestTransform) { it.from.attribute(TEST_ATTRIBUTE, "from") } @@ -322,9 +311,9 @@ class DefaultVariantTransformRegistryTest extends Specification { e.cause == null } - def "fails when to attributes are not a subset of from attributes for registerTransformAction"() { + def "fails when to attributes are not a subset of from attributes for registerTransform"() { when: - registry.registerTransformAction(TestTransform) { + registry.registerTransform(TestTransform) { it.from.attribute(TEST_ATTRIBUTE, "from") it.from.attribute(Attribute.of("from2", String), "from") it.to.attribute(TEST_ATTRIBUTE, "to") diff --git a/subprojects/language-native/src/main/java/org/gradle/language/plugins/NativeBasePlugin.java b/subprojects/language-native/src/main/java/org/gradle/language/plugins/NativeBasePlugin.java index 11fe1facecb5e..26090186a8b20 100644 --- a/subprojects/language-native/src/main/java/org/gradle/language/plugins/NativeBasePlugin.java +++ b/subprojects/language-native/src/main/java/org/gradle/language/plugins/NativeBasePlugin.java @@ -439,7 +439,7 @@ private TaskProvider extractSymbols(final TaskProvider { + dependencyHandler.registerTransform(UnzipTransform.class, variantTransform -> { variantTransform.getFrom().attribute(ArtifactAttributes.ARTIFACT_FORMAT, ZIP_TYPE); variantTransform.getFrom().attribute(Usage.USAGE_ATTRIBUTE, objects.named(Usage.class, Usage.C_PLUS_PLUS_API)); variantTransform.getTo().attribute(ArtifactAttributes.ARTIFACT_FORMAT, DIRECTORY_TYPE); diff --git a/subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/AbstractConsoleBuildPhaseFunctionalTest.groovy b/subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/AbstractConsoleBuildPhaseFunctionalTest.groovy index dfbfd6bf6b050..3c04a5c9d1530 100644 --- a/subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/AbstractConsoleBuildPhaseFunctionalTest.groovy +++ b/subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/AbstractConsoleBuildPhaseFunctionalTest.groovy @@ -389,7 +389,7 @@ abstract class AbstractConsoleBuildPhaseFunctionalTest extends AbstractIntegrati to.attribute(artifactType, "double") artifactTransform(FileDoubler) } - registerTransformAction(FileSizer) { + registerTransform(FileSizer) { from.attribute(artifactType, "double") to.attribute(artifactType, "size") parameters { From 7d738a8dd6483ea8ab7ac72e187f2f550db8581a Mon Sep 17 00:00:00 2001 From: Stefan Wolf Date: Tue, 26 Feb 2019 09:50:10 +0100 Subject: [PATCH 139/853] Remove AssociatedTransformAction This is not required anymore, since we infer the parameters object from the action instead of the other way round. --- .../transform/AssociatedTransformAction.java | 36 ------------------- 1 file changed, 36 deletions(-) delete mode 100644 subprojects/core-api/src/main/java/org/gradle/api/artifacts/transform/AssociatedTransformAction.java diff --git a/subprojects/core-api/src/main/java/org/gradle/api/artifacts/transform/AssociatedTransformAction.java b/subprojects/core-api/src/main/java/org/gradle/api/artifacts/transform/AssociatedTransformAction.java deleted file mode 100644 index 009d1e7f07e66..0000000000000 --- a/subprojects/core-api/src/main/java/org/gradle/api/artifacts/transform/AssociatedTransformAction.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright 2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.gradle.api.artifacts.transform; - -import org.gradle.api.Incubating; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * Attached to an artifact transform parameter type to declare the corresponding {@link TransformAction} implementation to use. - * - * @since 5.3 - */ -@Incubating -@Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.TYPE}) -public @interface AssociatedTransformAction { - Class value(); -} From 3d13b93eb2bebb3eb0b4511a56216167b52f6fc4 Mon Sep 17 00:00:00 2001 From: Paul Merlin Date: Tue, 26 Feb 2019 08:10:58 -0300 Subject: [PATCH 140/853] Fix typo Co-Authored-By: bamboo --- .../kotlin/dsl/plugins/precompiled/PrecompiledScriptPlugins.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPlugins.kt b/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPlugins.kt index 5cbfaa2496f85..926dc482ca33b 100644 --- a/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPlugins.kt +++ b/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPlugins.kt @@ -64,7 +64,7 @@ import org.jetbrains.kotlin.gradle.tasks.KotlinCompile * - the `.settings.gradle.kts` file name suffix defines a [Settings] script plugin * - and finally, the simpler `.gradle.kts` file name suffix defines a [Project] script plugin * - * ## Definining the plugin id + * ## Defining the plugin id * * The Gradle plugin id for a precompiled script plugin is defined via its file name * plus optional package declaration in the following manner: From b0caf782bc97dfe62f91c82e3d9bec5337b74cd0 Mon Sep 17 00:00:00 2001 From: Paul Merlin Date: Wed, 6 Feb 2019 18:19:54 +0100 Subject: [PATCH 141/853] Kill leaking kotlin compiler daemons Signed-off-by: Paul Merlin --- .../org/gradle/testing/LeakingProcessKillPattern.kt | 5 ++++- .../gradle/testing/LeakingProcessKillPatternTest.groovy | 9 +++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/buildSrc/subprojects/cleanup/src/main/kotlin/org/gradle/testing/LeakingProcessKillPattern.kt b/buildSrc/subprojects/cleanup/src/main/kotlin/org/gradle/testing/LeakingProcessKillPattern.kt index bdc30e3086bee..bed66afcebba0 100644 --- a/buildSrc/subprojects/cleanup/src/main/kotlin/org/gradle/testing/LeakingProcessKillPattern.kt +++ b/buildSrc/subprojects/cleanup/src/main/kotlin/org/gradle/testing/LeakingProcessKillPattern.kt @@ -21,7 +21,10 @@ import java.util.regex.Pattern object LeakingProcessKillPattern { + private + val kotlinCompilerPattern = "(?:${Pattern.quote("-Dkotlin.environment.keepalive org.jetbrains.kotlin.daemon.KotlinCompileDaemon")})" + @JvmStatic fun generate(rootProjectDir: String): String = - "(?i)[/\\\\](java(?:\\.exe)?.+?(?:(?:-cp.+${Pattern.quote(rootProjectDir)}.+?(org\\.gradle\\.|[a-zA-Z]+))|(?:-classpath.+${Pattern.quote(rootProjectDir)}.+?${Pattern.quote("\\build\\")}.+?(org\\.gradle\\.|[a-zA-Z]+))|(?:-classpath.+${Pattern.quote(rootProjectDir)}.+?(play\\.core\\.server\\.NettyServer))).+)" + "(?i)[/\\\\](java(?:\\.exe)?.+?(?:(?:-cp.+${Pattern.quote(rootProjectDir)}.+?(org\\.gradle\\.|[a-zA-Z]+))|(?:-classpath.+${Pattern.quote(rootProjectDir)}.+?${Pattern.quote("\\build\\")}.+?(org\\.gradle\\.|[a-zA-Z]+))|(?:-classpath.+${Pattern.quote(rootProjectDir)}.+?(play\\.core\\.server\\.NettyServer))|$kotlinCompilerPattern).+)" } diff --git a/buildSrc/subprojects/cleanup/src/test/groovy/org/gradle/testing/LeakingProcessKillPatternTest.groovy b/buildSrc/subprojects/cleanup/src/test/groovy/org/gradle/testing/LeakingProcessKillPatternTest.groovy index 507373cb755ac..83c05c0c3a1a8 100644 --- a/buildSrc/subprojects/cleanup/src/test/groovy/org/gradle/testing/LeakingProcessKillPatternTest.groovy +++ b/buildSrc/subprojects/cleanup/src/test/groovy/org/gradle/testing/LeakingProcessKillPatternTest.groovy @@ -46,4 +46,13 @@ class LeakingProcessKillPatternTest extends Specification { expect: !(line =~ LeakingProcessKillPattern.generate(projectDir)).find() } + + def "matches kotlin compiler on linux"() { + def line = '11522 ? Sl 1:10 /home/paul/.sdkman/candidates/java/10.0.2-oracle/bin/java -cp /home/paul/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-compiler-embeddable/1.3.11/a8db6c14f8b8ed74aa11b8379f961587b639c571/kotlin-compiler-embeddable-1.3.11.jar:/home/paul/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-reflect/1.3.11/aae7b33412715e9ed441934c4ffaad1bb80e9d36/kotlin-reflect-1.3.11.jar:/home/paul/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-stdlib/1.3.11/4cbc5922a54376018307a731162ccaf3ef851a39/kotlin-stdlib-1.3.11.jar:/home/paul/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-script-runtime/1.3.11/1ef3a816aeacb9cd051b3ed37e2abf88910f1503/kotlin-script-runtime-1.3.11.jar:/home/paul/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-stdlib-common/1.3.11/d8b8e746e279f1c4f5e08bc14a96b82e6bb1de02/kotlin-stdlib-common-1.3.11.jar:/home/paul/.gradle/caches/modules-2/files-2.1/org.jetbrains/annotations/13.0/919f0dfe192fb4e063e7dacadee7f8bb9a2672a9/annotations-13.0.jar -Djava.awt.headless=true -Djava.rmi.server.hostname=127.0.0.1 -Xmx320m -Dkotlin.environment.keepalive org.jetbrains.kotlin.daemon.KotlinCompileDaemon --daemon-runFilesPath /home/paul/.kotlin/daemon --daemon-autoshutdownIdleSeconds=7200 --daemon-compilerClasspath /home/paul/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-compiler-embeddable/1.3.11/a8db6c14f8b8ed74aa11b8379f961587b639c571/kotlin-compiler-embeddable-1.3.11.jar:/home/paul/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-reflect/1.3.11/aae7b33412715e9ed441934c4ffaad1bb80e9d36/kotlin-reflect-1.3.11.jar:/home/paul/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-stdlib/1.3.11/4cbc5922a54376018307a731162ccaf3ef851a39/kotlin-stdlib-1.3.11.jar:/home/paul/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-script-runtime/1.3.11/1ef3a816aeacb9cd051b3ed37e2abf88910f1503/kotlin-script-runtime-1.3.11.jar:/home/paul/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-stdlib-common/1.3.11/d8b8e746e279f1c4f5e08bc14a96b82e6bb1de02/kotlin-stdlib-common-1.3.11.jar:/home/paul/.gradle/caches/modules-2/files-2.1/org.jetbrains/annotations/13.0/919f0dfe192fb4e063e7dacadee7f8bb9a2672a9/annotations-13.0.jar' + + def projectDir = "/home/paul/src/kotlin-dsl" + + expect: + (line =~ LeakingProcessKillPattern.generate(projectDir)).find() + } } From 494697898098b5c03a038db3b3b5434d1470000a Mon Sep 17 00:00:00 2001 From: "Rodrigo B. de Oliveira" Date: Tue, 26 Feb 2019 09:20:00 -0300 Subject: [PATCH 142/853] Move `AbstractTask` extensions to separate file --- .../tasks/AbstractTaskExtensions.kt | 27 +++++++++++++++++++ .../GenerateInternalPluginSpecBuilders.kt | 11 +------- 2 files changed, 28 insertions(+), 10 deletions(-) create mode 100644 subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/AbstractTaskExtensions.kt diff --git a/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/AbstractTaskExtensions.kt b/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/AbstractTaskExtensions.kt new file mode 100644 index 0000000000000..e3868e4bc42a0 --- /dev/null +++ b/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/AbstractTaskExtensions.kt @@ -0,0 +1,27 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.kotlin.dsl.plugins.precompiled.tasks + +import org.gradle.api.internal.AbstractTask + + +internal +fun AbstractTask.directoryProperty() = project.objects.directoryProperty() + + +internal +fun AbstractTask.sourceDirectorySet(name: String, displayName: String) = project.objects.sourceDirectorySet(name, displayName) diff --git a/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/GenerateInternalPluginSpecBuilders.kt b/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/GenerateInternalPluginSpecBuilders.kt index d26db8a3f8ac5..e38c8ce86052a 100644 --- a/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/GenerateInternalPluginSpecBuilders.kt +++ b/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/GenerateInternalPluginSpecBuilders.kt @@ -17,7 +17,6 @@ package org.gradle.kotlin.dsl.plugins.precompiled.tasks import org.gradle.api.DefaultTask -import org.gradle.api.internal.AbstractTask import org.gradle.api.tasks.CacheableTask import org.gradle.api.tasks.InputFiles import org.gradle.api.tasks.Internal @@ -53,14 +52,6 @@ open class GenerateInternalPluginSpecBuilders : DefaultTask() { @TaskAction fun generate() { - // TODO() + // TODO } } - - -internal -fun AbstractTask.directoryProperty() = project.objects.directoryProperty() - - -internal -fun AbstractTask.sourceDirectorySet(name: String, displayName: String) = project.objects.sourceDirectorySet(name, displayName) From 0a99f297c91db56f81fe36a6dd7dcb2d863e8573 Mon Sep 17 00:00:00 2001 From: "Rodrigo B. de Oliveira" Date: Tue, 26 Feb 2019 09:21:28 -0300 Subject: [PATCH 143/853] Polish `GeneratePrecompiledScriptPluginAccessors` - Make documentation more precise (_list of plugins_ versus _set of plugins_) - Remove unnecessary `apply` - Reduce visibility of members --- ...eneratePrecompiledScriptPluginAccessors.kt | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/GeneratePrecompiledScriptPluginAccessors.kt b/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/GeneratePrecompiledScriptPluginAccessors.kt index 69e599a815d74..dae21c334df92 100644 --- a/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/GeneratePrecompiledScriptPluginAccessors.kt +++ b/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/GeneratePrecompiledScriptPluginAccessors.kt @@ -48,6 +48,8 @@ import org.gradle.kotlin.dsl.concurrent.writeFile import org.gradle.kotlin.dsl.plugins.precompiled.PrecompiledScriptPlugin +import org.gradle.kotlin.dsl.precompile.PrecompiledScriptDependenciesResolver + import org.gradle.kotlin.dsl.support.KotlinScriptType import org.gradle.kotlin.dsl.support.serviceOf @@ -86,14 +88,14 @@ open class GeneratePrecompiledScriptPluginAccessors : ClassPathSensitiveCodeGene /** * ## Computation and sharing of type-safe accessors - * 1. Group precompiled script plugins by the set of plugins applied in their `plugins` block. - * 2. For each group, compute the project schema implied by the set of plugins. + * 1. Group precompiled script plugins by the list of plugins applied in their `plugins` block. + * 2. For each group, compute the project schema implied by the list of plugins. * 3. Re-group precompiled script plugins by project schema. * 4. For each group, emit the type-safe accessors implied by the schema to a package named after the schema * hash code. * 5. For each group, for each script plugin in the group, write the generated package name to a file named * after the contents of the script plugin file. This is so the file can be easily found by - * `PrecompiledScriptDependenciesResolver`. + * [PrecompiledScriptDependenciesResolver]. */ @TaskAction fun generate() { @@ -292,14 +294,12 @@ class SyntheticProjectSchemaBuilder(rootProjectDir: File, rootProjectClassPath: private fun applyPluginsTo(project: Project, pluginRequests: PluginRequests) { val targetProjectScope = (project as ProjectInternal).classLoaderScope - project.serviceOf().apply { - applyPlugins( - pluginRequests, - project.buildscript as ScriptHandlerInternal, - project.pluginManager, - targetProjectScope - ) - } + project.serviceOf().applyPlugins( + pluginRequests, + project.buildscript as ScriptHandlerInternal, + project.pluginManager, + targetProjectScope + ) } } @@ -326,7 +326,7 @@ data class ScriptPluginPlugins( ) -internal +private class UniquePluginRequests(val plugins: PluginRequests) { val applications = plugins.map { it.toPluginApplication() } @@ -337,7 +337,7 @@ class UniquePluginRequests(val plugins: PluginRequests) { } -internal +private fun PluginRequestInternal.toPluginApplication() = PluginApplication( id.id, version, isApply ) From 06a4690aa97349574343dc3358d243ab42531f1e Mon Sep 17 00:00:00 2001 From: "Rodrigo B. de Oliveira" Date: Tue, 26 Feb 2019 09:23:26 -0300 Subject: [PATCH 144/853] Polish `ClassPathSensitiveCodeGenerationTask` - Move function closer to usage --- .../tasks/ClassPathSensitiveCodeGenerationTask.kt | 5 ----- .../precompiled/tasks/GenerateExternalPluginSpecBuilders.kt | 6 ++++++ 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/ClassPathSensitiveCodeGenerationTask.kt b/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/ClassPathSensitiveCodeGenerationTask.kt index 6e52681ffd851..af1741817a33c 100644 --- a/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/ClassPathSensitiveCodeGenerationTask.kt +++ b/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/ClassPathSensitiveCodeGenerationTask.kt @@ -24,8 +24,3 @@ abstract class ClassPathSensitiveCodeGenerationTask : ClassPathSensitiveTask() { @get:OutputDirectory var sourceCodeOutputDir = directoryProperty() } - - -internal -fun kotlinPackageNameFor(packageName: String) = - packageName.split('.').joinToString(".") { "`$it`" } diff --git a/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/GenerateExternalPluginSpecBuilders.kt b/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/GenerateExternalPluginSpecBuilders.kt index b484bd61df525..d0bc1ced40871 100644 --- a/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/GenerateExternalPluginSpecBuilders.kt +++ b/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/GenerateExternalPluginSpecBuilders.kt @@ -21,6 +21,7 @@ import org.gradle.api.tasks.Internal import org.gradle.api.tasks.TaskAction import org.gradle.kotlin.dsl.accessors.writeSourceCodeForPluginSpecBuildersFor + import java.io.File @@ -59,3 +60,8 @@ open class GenerateExternalPluginSpecBuilders : ClassPathSensitiveCodeGeneration val packageName get() = "org.gradle.kotlin.dsl" } + + +private +fun kotlinPackageNameFor(packageName: String) = + packageName.split('.').joinToString(".") { "`$it`" } From 09f12db949e26ac66d2cd35365db4545627437c0 Mon Sep 17 00:00:00 2001 From: "Rodrigo B. de Oliveira" Date: Tue, 26 Feb 2019 09:24:14 -0300 Subject: [PATCH 145/853] Organize imports --- .../plugins/precompiled/tasks/GenerateScriptPluginAdapters.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/GenerateScriptPluginAdapters.kt b/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/GenerateScriptPluginAdapters.kt index 76506410c7946..4240b025cebe4 100644 --- a/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/GenerateScriptPluginAdapters.kt +++ b/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/GenerateScriptPluginAdapters.kt @@ -25,6 +25,7 @@ import org.gradle.api.tasks.PathSensitive import org.gradle.api.tasks.PathSensitivity import org.gradle.api.tasks.OutputDirectory import org.gradle.api.tasks.TaskAction + import org.gradle.kotlin.dsl.plugins.precompiled.PrecompiledScriptPlugin import org.gradle.kotlin.dsl.support.normaliseLineSeparators From bf91d3a3db1bf8d75acd3301a59cec847fa9b3d2 Mon Sep 17 00:00:00 2001 From: "Rodrigo B. de Oliveira" Date: Tue, 26 Feb 2019 09:28:41 -0300 Subject: [PATCH 146/853] Move `DirectoryProperty` extension to separate file --- .../tasks/DirectoryPropertyExtensions.kt | 36 +++++++++++++++++++ .../tasks/GenerateScriptPluginAdapters.kt | 18 +--------- 2 files changed, 37 insertions(+), 17 deletions(-) create mode 100644 subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/DirectoryPropertyExtensions.kt diff --git a/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/DirectoryPropertyExtensions.kt b/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/DirectoryPropertyExtensions.kt new file mode 100644 index 0000000000000..f2c2ffdf281cb --- /dev/null +++ b/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/DirectoryPropertyExtensions.kt @@ -0,0 +1,36 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.kotlin.dsl.plugins.precompiled.tasks + +import org.gradle.api.file.DirectoryProperty + +import java.io.File + + +internal +inline fun DirectoryProperty.withOutputDirectory(action: (File) -> T): T = + asFile.get().let { outputDir -> + recreate(outputDir) + action(outputDir) + } + + +internal +fun recreate(outputDir: File) { + outputDir.deleteRecursively() + outputDir.mkdirs() +} diff --git a/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/GenerateScriptPluginAdapters.kt b/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/GenerateScriptPluginAdapters.kt index 4240b025cebe4..f9ae19c8fe871 100644 --- a/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/GenerateScriptPluginAdapters.kt +++ b/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/GenerateScriptPluginAdapters.kt @@ -17,13 +17,12 @@ package org.gradle.kotlin.dsl.plugins.precompiled.tasks import org.gradle.api.DefaultTask -import org.gradle.api.file.DirectoryProperty import org.gradle.api.tasks.CacheableTask import org.gradle.api.tasks.InputFiles import org.gradle.api.tasks.Internal +import org.gradle.api.tasks.OutputDirectory import org.gradle.api.tasks.PathSensitive import org.gradle.api.tasks.PathSensitivity -import org.gradle.api.tasks.OutputDirectory import org.gradle.api.tasks.TaskAction import org.gradle.kotlin.dsl.plugins.precompiled.PrecompiledScriptPlugin @@ -104,21 +103,6 @@ fun packageDir(outputDir: File, packageName: String) = outputDir.mkdir(packageName.replace('.', '/')) -internal -inline fun DirectoryProperty.withOutputDirectory(action: (File) -> T): T = - asFile.get().let { outputDir -> - recreate(outputDir) - action(outputDir) - } - - -internal -fun recreate(outputDir: File) { - outputDir.deleteRecursively() - outputDir.mkdirs() -} - - private fun File.mkdir(relative: String) = resolve(relative).apply { mkdirs() } From a29d82acbba06eec01ae06a6eebcb754e8dd43ed Mon Sep 17 00:00:00 2001 From: Bo Zhang Date: Tue, 26 Feb 2019 20:36:37 +0800 Subject: [PATCH 147/853] Don't run coordinator on ec2 (#8621) Our H2 performance database has an ancient configuration and is incompatible with JDK11.0.2. We're using a patched JDK11.0.2 version (https://github.com/gradle/gradle-private/issues/1861) on Hetzner agents. But EC2 agents are not patched, performance coordinator builds will fail on EC2 agents. Before fixing H2 db issue, let's not run performance coordinators on EC2 agents. --- .../configurations/PerformanceTest.kt | 5 +++++ ...e_Check_PerformanceExperimentCoordinator.kts | 17 ----------------- .../Gradle_Check_PerformanceTestCoordinator.kts | 17 ----------------- 3 files changed, 5 insertions(+), 34 deletions(-) delete mode 100644 .teamcity/Gradle_Check/patches/buildTypes/Gradle_Check_PerformanceExperimentCoordinator.kts delete mode 100644 .teamcity/Gradle_Check/patches/buildTypes/Gradle_Check_PerformanceTestCoordinator.kts diff --git a/.teamcity/Gradle_Check/configurations/PerformanceTest.kt b/.teamcity/Gradle_Check/configurations/PerformanceTest.kt index 7775e1f8490f2..6bd8940d62563 100644 --- a/.teamcity/Gradle_Check/configurations/PerformanceTest.kt +++ b/.teamcity/Gradle_Check/configurations/PerformanceTest.kt @@ -25,6 +25,11 @@ class PerformanceTest(model: CIBuildModel, type: PerformanceTestType, stage: Sta } } + requirements { + // TODO this can be removed once https://github.com/gradle/gradle-private/issues/1861 is closed + doesNotContain("teamcity.agent.name", "ec2") + } + params { param("performance.baselines", type.defaultBaselines) param("env.GRADLE_OPTS", "-Xmx1536m -XX:MaxPermSize=384m") diff --git a/.teamcity/Gradle_Check/patches/buildTypes/Gradle_Check_PerformanceExperimentCoordinator.kts b/.teamcity/Gradle_Check/patches/buildTypes/Gradle_Check_PerformanceExperimentCoordinator.kts deleted file mode 100644 index f9ac18b26c3fd..0000000000000 --- a/.teamcity/Gradle_Check/patches/buildTypes/Gradle_Check_PerformanceExperimentCoordinator.kts +++ /dev/null @@ -1,17 +0,0 @@ -package Gradle_Check.patches.buildTypes - -import jetbrains.buildServer.configs.kotlin.v2018_2.* -import jetbrains.buildServer.configs.kotlin.v2018_2.ui.* - -/* -This patch script was generated by TeamCity on settings change in UI. -To apply the patch, change the buildType with uuid = 'Gradle_Check_PerformanceExperimentCoordinator' (id = 'Gradle_Check_PerformanceExperimentCoordinator') -accordingly, and delete the patch script. -*/ -changeBuildType(uuid("Gradle_Check_PerformanceExperimentCoordinator")) { - requirements { - add { - doesNotContain("teamcity.agent.name", "ec2") - } - } -} diff --git a/.teamcity/Gradle_Check/patches/buildTypes/Gradle_Check_PerformanceTestCoordinator.kts b/.teamcity/Gradle_Check/patches/buildTypes/Gradle_Check_PerformanceTestCoordinator.kts deleted file mode 100644 index 4fa0aa8b3c17a..0000000000000 --- a/.teamcity/Gradle_Check/patches/buildTypes/Gradle_Check_PerformanceTestCoordinator.kts +++ /dev/null @@ -1,17 +0,0 @@ -package Gradle_Check.patches.buildTypes - -import jetbrains.buildServer.configs.kotlin.v2018_2.* -import jetbrains.buildServer.configs.kotlin.v2018_2.ui.* - -/* -This patch script was generated by TeamCity on settings change in UI. -To apply the patch, change the buildType with uuid = 'Gradle_Check_PerformanceTestCoordinator' (id = 'Gradle_Check_PerformanceTestCoordinator') -accordingly, and delete the patch script. -*/ -changeBuildType(uuid("Gradle_Check_PerformanceTestCoordinator")) { - requirements { - add { - doesNotContain("teamcity.agent.name", "ec2") - } - } -} From f8b34fdbb1de1d019541558d7920e5bae19e31cc Mon Sep 17 00:00:00 2001 From: Bo Zhang Date: Tue, 26 Feb 2019 20:36:37 +0800 Subject: [PATCH 148/853] Don't run coordinator on ec2 (#8621) Our H2 performance database has an ancient configuration and is incompatible with JDK11.0.2. We're using a patched JDK11.0.2 version (https://github.com/gradle/gradle-private/issues/1861) on Hetzner agents. But EC2 agents are not patched, performance coordinator builds will fail on EC2 agents. Before fixing H2 db issue, let's not run performance coordinators on EC2 agents. --- .teamcity/Gradle_Check/configurations/PerformanceTest.kt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.teamcity/Gradle_Check/configurations/PerformanceTest.kt b/.teamcity/Gradle_Check/configurations/PerformanceTest.kt index 7775e1f8490f2..6bd8940d62563 100644 --- a/.teamcity/Gradle_Check/configurations/PerformanceTest.kt +++ b/.teamcity/Gradle_Check/configurations/PerformanceTest.kt @@ -25,6 +25,11 @@ class PerformanceTest(model: CIBuildModel, type: PerformanceTestType, stage: Sta } } + requirements { + // TODO this can be removed once https://github.com/gradle/gradle-private/issues/1861 is closed + doesNotContain("teamcity.agent.name", "ec2") + } + params { param("performance.baselines", type.defaultBaselines) param("env.GRADLE_OPTS", "-Xmx1536m -XX:MaxPermSize=384m") From 3466fad4460fa37ca992d9a85d460232c8960492 Mon Sep 17 00:00:00 2001 From: "Rodrigo B. de Oliveira" Date: Tue, 26 Feb 2019 09:45:42 -0300 Subject: [PATCH 149/853] Remove unnecessary task dependencies - The wiring is already done via `builtBy` --- .../kotlin/dsl/plugins/precompiled/PrecompiledScriptPlugins.kt | 3 --- 1 file changed, 3 deletions(-) diff --git a/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPlugins.kt b/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPlugins.kt index 926dc482ca33b..80af0f4ffb7cd 100644 --- a/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPlugins.kt +++ b/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPlugins.kt @@ -217,9 +217,6 @@ fun Project.enableScriptCompilationOf(scriptPlugins: List Date: Tue, 26 Feb 2019 09:47:02 -0300 Subject: [PATCH 150/853] Remove unused function --- .../dsl/plugins/precompiled/PrecompiledScriptPlugins.kt | 7 ------- 1 file changed, 7 deletions(-) diff --git a/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPlugins.kt b/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPlugins.kt index 80af0f4ffb7cd..302f5939a25ee 100644 --- a/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPlugins.kt +++ b/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPlugins.kt @@ -345,13 +345,6 @@ inline fun Project.codeGenerationTask( } -private -fun Project.generatedSourceDirFor(purpose: String): Provider = - buildDir("generated-sources/kotlin-dsl-$purpose/kotlin").also { - sourceSets["main"].kotlin.srcDir(it) - } - - private fun Project.buildDir(path: String) = layout.buildDirectory.dir(path) From 8e58cba3f585f7d3ac8a00850fd3029b7fd036ed Mon Sep 17 00:00:00 2001 From: "Rodrigo B. de Oliveira" Date: Tue, 26 Feb 2019 09:47:24 -0300 Subject: [PATCH 151/853] Polish `PrecompiledScriptPlugins` - Add import required by kdoc link - Remove TODO section --- .../dsl/plugins/precompiled/PrecompiledScriptPlugins.kt | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPlugins.kt b/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPlugins.kt index 302f5939a25ee..f669b42fe0b28 100644 --- a/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPlugins.kt +++ b/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPlugins.kt @@ -34,6 +34,7 @@ import org.gradle.kotlin.dsl.plugins.precompiled.tasks.GenerateExternalPluginSpe import org.gradle.kotlin.dsl.plugins.precompiled.tasks.GenerateInternalPluginSpecBuilders import org.gradle.kotlin.dsl.plugins.precompiled.tasks.GeneratePrecompiledScriptPluginAccessors import org.gradle.kotlin.dsl.plugins.precompiled.tasks.GenerateScriptPluginAdapters +import org.gradle.kotlin.dsl.plugins.precompiled.tasks.HashedProjectSchema import org.gradle.kotlin.dsl.precompile.PrecompiledInitScript import org.gradle.kotlin.dsl.precompile.PrecompiledProjectScript @@ -118,13 +119,6 @@ import org.jetbrains.kotlin.gradle.tasks.KotlinCompile * and external plugin spec builders * - [GeneratePrecompiledScriptPluginAccessors] - uses the compiled `plugins` block of each precompiled script plugin * to compute its [HashedProjectSchema] and emit the corresponding type-safe accessors - * - * ## Todo - * - DONE type-safe plugin spec accessors for plugins in the precompiled script plugin classpath - * - [ ] limit the set of type-safe accessors visible to a precompiled script plugin to - * those provided by the plugins in its `plugins` block - * - [ ] emit help message when a precompiled script plugin includes a version in its `plugins` block - * - [ ] validate plugin ids against declared plugin dependencies (that comes for free) */ class PrecompiledScriptPlugins : Plugin { From 68e4c52927e09738f7be11cf4ddf3a06e08b6150 Mon Sep 17 00:00:00 2001 From: "Rodrigo B. de Oliveira" Date: Tue, 26 Feb 2019 10:04:17 -0300 Subject: [PATCH 152/853] Extract plugin related fixture function to separate file --- .../org/gradle/kotlin/dsl/fixtures/plugins.kt | 21 +++++++++++++++++++ .../gradle/kotlin/dsl/fixtures/zipUtils.kt | 16 -------------- .../accessors/PluginAccessorsClassPathTest.kt | 13 +++++++++++- 3 files changed, 33 insertions(+), 17 deletions(-) create mode 100644 subprojects/kotlin-dsl-test-fixtures/src/main/kotlin/org/gradle/kotlin/dsl/fixtures/plugins.kt diff --git a/subprojects/kotlin-dsl-test-fixtures/src/main/kotlin/org/gradle/kotlin/dsl/fixtures/plugins.kt b/subprojects/kotlin-dsl-test-fixtures/src/main/kotlin/org/gradle/kotlin/dsl/fixtures/plugins.kt new file mode 100644 index 0000000000000..b872922d9c23b --- /dev/null +++ b/subprojects/kotlin-dsl-test-fixtures/src/main/kotlin/org/gradle/kotlin/dsl/fixtures/plugins.kt @@ -0,0 +1,21 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.kotlin.dsl.fixtures + + +fun pluginDescriptorEntryFor(id: String, implClass: String) = + "META-INF/gradle-plugins/$id.properties" to "implementation-class=$implClass".toByteArray() diff --git a/subprojects/kotlin-dsl-test-fixtures/src/main/kotlin/org/gradle/kotlin/dsl/fixtures/zipUtils.kt b/subprojects/kotlin-dsl-test-fixtures/src/main/kotlin/org/gradle/kotlin/dsl/fixtures/zipUtils.kt index f6c2ff5efbdea..085c895e26206 100644 --- a/subprojects/kotlin-dsl-test-fixtures/src/main/kotlin/org/gradle/kotlin/dsl/fixtures/zipUtils.kt +++ b/subprojects/kotlin-dsl-test-fixtures/src/main/kotlin/org/gradle/kotlin/dsl/fixtures/zipUtils.kt @@ -1,9 +1,5 @@ package org.gradle.kotlin.dsl.fixtures -import org.gradle.kotlin.dsl.support.zipTo - -import java.io.File - import kotlin.reflect.KClass @@ -23,15 +19,3 @@ fun classEntryFor(clazz: Class<*>): Pair { val classFilePath = clazz.name.replace('.', '/') + ".class" return classFilePath to clazz.getResource("/$classFilePath").readBytes() } - - -fun jarWithPluginDescriptors(file: File, vararg pluginIdsToImplClasses: Pair) = - file.also { - zipTo(it, pluginIdsToImplClasses.asSequence().map { (id, implClass) -> - pluginDescriptorEntryFor(id, implClass) - }) - } - - -fun pluginDescriptorEntryFor(id: String, implClass: String) = - "META-INF/gradle-plugins/$id.properties" to "implementation-class=$implClass".toByteArray() diff --git a/subprojects/kotlin-dsl/src/test/kotlin/org/gradle/kotlin/dsl/accessors/PluginAccessorsClassPathTest.kt b/subprojects/kotlin-dsl/src/test/kotlin/org/gradle/kotlin/dsl/accessors/PluginAccessorsClassPathTest.kt index bb56de9e4b200..5ae08e05e8908 100644 --- a/subprojects/kotlin-dsl/src/test/kotlin/org/gradle/kotlin/dsl/accessors/PluginAccessorsClassPathTest.kt +++ b/subprojects/kotlin-dsl/src/test/kotlin/org/gradle/kotlin/dsl/accessors/PluginAccessorsClassPathTest.kt @@ -26,10 +26,11 @@ import org.gradle.kotlin.dsl.concurrent.withSynchronousIO import org.gradle.kotlin.dsl.fixtures.classLoaderFor import org.gradle.kotlin.dsl.fixtures.containsMultiLineString -import org.gradle.kotlin.dsl.fixtures.jarWithPluginDescriptors +import org.gradle.kotlin.dsl.fixtures.pluginDescriptorEntryFor import org.gradle.kotlin.dsl.support.normaliseLineSeparators import org.gradle.kotlin.dsl.support.useToRun +import org.gradle.kotlin.dsl.support.zipTo import org.gradle.plugin.use.PluginDependenciesSpec import org.gradle.plugin.use.PluginDependencySpec @@ -42,6 +43,8 @@ import org.hamcrest.MatcherAssert.assertThat import org.junit.Test +import java.io.File + class PluginAccessorsClassPathTest : TestWithClassPath() { @@ -147,4 +150,12 @@ class PluginAccessorsClassPathTest : TestWithClassPath() { verifyNoMoreInteractions(plugins) } } + + private + fun jarWithPluginDescriptors(file: File, vararg pluginIdsToImplClasses: Pair) = + file.also { + zipTo(it, pluginIdsToImplClasses.asSequence().map { (id, implClass) -> + pluginDescriptorEntryFor(id, implClass) + }) + } } From 3f523d2916015ba295e88edc216c4b04275a30cf Mon Sep 17 00:00:00 2001 From: Benedikt Ritter Date: Tue, 26 Feb 2019 14:10:34 +0100 Subject: [PATCH 153/853] Use latest httpcomponents release in docs (#8595) The Apache Commons HttpComponents library has evolved to its own top level project inside the Apache Software Foundation. The docs and examples of the java-library plugin still reference the now deprecated commons-httpclient release. Although the docs are about the java-library plugin, this can still confuse users. For this reason, this updates the docs and examples to use org.apache.httpcomponents:httpclient instead. --- .../docs/userguide/java_library_plugin.adoc | 4 +-- .../quickstart/groovy/build.gradle | 2 +- .../java/org/gradle/HttpClientWrapper.java | 32 +++++++++++-------- .../quickstart/kotlin/build.gradle.kts | 2 +- .../java/org/gradle/HttpClientWrapper.java | 32 +++++++++++-------- 5 files changed, 42 insertions(+), 30 deletions(-) diff --git a/subprojects/docs/src/docs/userguide/java_library_plugin.adoc b/subprojects/docs/src/docs/userguide/java_library_plugin.adoc index b97a17ac3fd1b..22a80ab43a88c 100644 --- a/subprojects/docs/src/docs/userguide/java_library_plugin.adoc +++ b/subprojects/docs/src/docs/userguide/java_library_plugin.adoc @@ -97,11 +97,11 @@ The following class makes use of a couple of third-party libraries, one of which include::{samplesPath}/java-library/quickstart/groovy/src/main/java/org/gradle/HttpClientWrapper.java[tag=sample] ---- -The _public_ constructor of `HttpClientWrapper` uses `HttpClient` as a parameter, so it is exposed to consumers and therefore belongs to the API. Note that `GetMethod` is used in the signature of a _private_ method, and so it doesn't count towards making HttpClient an API dependency. +The _public_ constructor of `HttpClientWrapper` uses `HttpClient` as a parameter, so it is exposed to consumers and therefore belongs to the API. Note that `HttpGet` and `HttpEntity` are used in the signature of a _private_ method, and so they don't count towards making HttpClient an API dependency. On the other hand, the `ExceptionUtils` type, coming from the `commons-lang` library, is only used in a method body (not in its signature), so it's an implementation dependency. -Therefore, we can deduce that `commons-httpclient` is an API dependency, whereas `commons-lang` is an implementation dependency. This conclusion translates into the following declaration in the build script: +Therefore, we can deduce that `httpclient` is an API dependency, whereas `commons-lang` is an implementation dependency. This conclusion translates into the following declaration in the build script: .Declaring API and implementation dependencies ==== diff --git a/subprojects/docs/src/samples/java-library/quickstart/groovy/build.gradle b/subprojects/docs/src/samples/java-library/quickstart/groovy/build.gradle index 83f474fe4e9a6..b076ffcd374b3 100644 --- a/subprojects/docs/src/samples/java-library/quickstart/groovy/build.gradle +++ b/subprojects/docs/src/samples/java-library/quickstart/groovy/build.gradle @@ -29,7 +29,7 @@ repositories { // tag::dependencies[] dependencies { - api 'commons-httpclient:commons-httpclient:3.1' + api 'org.apache.httpcomponents:httpclient:4.5.7' implementation 'org.apache.commons:commons-lang3:3.5' } // end::dependencies[] diff --git a/subprojects/docs/src/samples/java-library/quickstart/groovy/src/main/java/org/gradle/HttpClientWrapper.java b/subprojects/docs/src/samples/java-library/quickstart/groovy/src/main/java/org/gradle/HttpClientWrapper.java index bd442b0315f85..f137bb35b65ec 100644 --- a/subprojects/docs/src/samples/java-library/quickstart/groovy/src/main/java/org/gradle/HttpClientWrapper.java +++ b/subprojects/docs/src/samples/java-library/quickstart/groovy/src/main/java/org/gradle/HttpClientWrapper.java @@ -17,9 +17,14 @@ // tag::sample[] // The following types can appear anywhere in the code // but say nothing about API or implementation usage -import org.apache.commons.httpclient.*; -import org.apache.commons.httpclient.methods.*; import org.apache.commons.lang3.exception.ExceptionUtils; +import org.apache.http.HttpEntity; +import org.apache.http.HttpResponse; +import org.apache.http.HttpStatus; +import org.apache.http.client.HttpClient; +import org.apache.http.client.methods.HttpGet; + +import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.UnsupportedEncodingException; @@ -35,26 +40,27 @@ public HttpClientWrapper(HttpClient client) { // public methods belongs to your API public byte[] doRawGet(String url) { - GetMethod method = new GetMethod(url); + HttpGet request = new HttpGet(url); try { - int statusCode = doGet(method); - return method.getResponseBody(); - + HttpEntity entity = doGet(request); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + entity.writeTo(baos); + return baos.toByteArray(); } catch (Exception e) { ExceptionUtils.rethrow(e); // this dependency is internal only } finally { - method.releaseConnection(); + request.releaseConnection(); } return null; } - // GetMethod is used in a private method, so doesn't belong to the API - private int doGet(GetMethod method) throws Exception { - int statusCode = client.executeMethod(method); - if (statusCode != HttpStatus.SC_OK) { - System.err.println("Method failed: " + method.getStatusLine()); + // HttpGet and HttpEntity are used in a private method, so they don't belong to the API + private HttpEntity doGet(HttpGet get) throws Exception { + HttpResponse response = client.execute(get); + if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) { + System.err.println("Method failed: " + response.getStatusLine()); } - return statusCode; + return response.getEntity(); } } // end::sample[] diff --git a/subprojects/docs/src/samples/java-library/quickstart/kotlin/build.gradle.kts b/subprojects/docs/src/samples/java-library/quickstart/kotlin/build.gradle.kts index 1b0b329147e8b..63e113ae80ac3 100644 --- a/subprojects/docs/src/samples/java-library/quickstart/kotlin/build.gradle.kts +++ b/subprojects/docs/src/samples/java-library/quickstart/kotlin/build.gradle.kts @@ -13,7 +13,7 @@ repositories { // tag::dependencies[] dependencies { - api("commons-httpclient:commons-httpclient:3.1") + api("org.apache.httpcomponents:httpclient:4.5.7") implementation("org.apache.commons:commons-lang3:3.5") } // end::dependencies[] diff --git a/subprojects/docs/src/samples/java-library/quickstart/kotlin/src/main/java/org/gradle/HttpClientWrapper.java b/subprojects/docs/src/samples/java-library/quickstart/kotlin/src/main/java/org/gradle/HttpClientWrapper.java index bd442b0315f85..f137bb35b65ec 100644 --- a/subprojects/docs/src/samples/java-library/quickstart/kotlin/src/main/java/org/gradle/HttpClientWrapper.java +++ b/subprojects/docs/src/samples/java-library/quickstart/kotlin/src/main/java/org/gradle/HttpClientWrapper.java @@ -17,9 +17,14 @@ // tag::sample[] // The following types can appear anywhere in the code // but say nothing about API or implementation usage -import org.apache.commons.httpclient.*; -import org.apache.commons.httpclient.methods.*; import org.apache.commons.lang3.exception.ExceptionUtils; +import org.apache.http.HttpEntity; +import org.apache.http.HttpResponse; +import org.apache.http.HttpStatus; +import org.apache.http.client.HttpClient; +import org.apache.http.client.methods.HttpGet; + +import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.UnsupportedEncodingException; @@ -35,26 +40,27 @@ public HttpClientWrapper(HttpClient client) { // public methods belongs to your API public byte[] doRawGet(String url) { - GetMethod method = new GetMethod(url); + HttpGet request = new HttpGet(url); try { - int statusCode = doGet(method); - return method.getResponseBody(); - + HttpEntity entity = doGet(request); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + entity.writeTo(baos); + return baos.toByteArray(); } catch (Exception e) { ExceptionUtils.rethrow(e); // this dependency is internal only } finally { - method.releaseConnection(); + request.releaseConnection(); } return null; } - // GetMethod is used in a private method, so doesn't belong to the API - private int doGet(GetMethod method) throws Exception { - int statusCode = client.executeMethod(method); - if (statusCode != HttpStatus.SC_OK) { - System.err.println("Method failed: " + method.getStatusLine()); + // HttpGet and HttpEntity are used in a private method, so they don't belong to the API + private HttpEntity doGet(HttpGet get) throws Exception { + HttpResponse response = client.execute(get); + if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) { + System.err.println("Method failed: " + response.getStatusLine()); } - return statusCode; + return response.getEntity(); } } // end::sample[] From 7414f14e0da45e53c8f17b70e69dc27b3de86518 Mon Sep 17 00:00:00 2001 From: "Rodrigo B. de Oliveira" Date: Tue, 26 Feb 2019 10:12:21 -0300 Subject: [PATCH 154/853] Re-enable Kotlin DSL x-version test for Kotlin Gradle plugin 1.2.20 --- .../dsl/KotlinDslPluginGradlePluginCrossVersionSmokeTest.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/subprojects/kotlin-dsl-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/plugins/dsl/KotlinDslPluginGradlePluginCrossVersionSmokeTest.kt b/subprojects/kotlin-dsl-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/plugins/dsl/KotlinDslPluginGradlePluginCrossVersionSmokeTest.kt index 1e2c310e9d85a..e19b4cd6b4d6d 100644 --- a/subprojects/kotlin-dsl-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/plugins/dsl/KotlinDslPluginGradlePluginCrossVersionSmokeTest.kt +++ b/subprojects/kotlin-dsl-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/plugins/dsl/KotlinDslPluginGradlePluginCrossVersionSmokeTest.kt @@ -43,8 +43,8 @@ class KotlinDslPluginGradlePluginCrossVersionSmokeTest( @JvmStatic fun testedKotlinVersions() = listOf( embeddedKotlinVersion, - "1.2.71" -// "1.2.20" TODO:re-enable 1.2.20 + "1.2.71", + "1.2.20" ) } From 27fbbd7b88fd6d99141c8cefb02e69a5b28ab607 Mon Sep 17 00:00:00 2001 From: Louis Jacomet Date: Mon, 25 Feb 2019 17:48:50 +0100 Subject: [PATCH 155/853] Improve ComponentSelectionReason.isExpected The previous implementation relied on ordering. There have been reports of that order not holding. We now check for a unique `requested` or `root` reason. Fixes #8435 --- .../result/ComponentSelectionReasons.java | 2 +- ...DefaultComponentSelectionReasonTest.groovy | 64 +++++++++++++++++++ 2 files changed, 65 insertions(+), 1 deletion(-) create mode 100644 subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/result/DefaultComponentSelectionReasonTest.groovy diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/result/ComponentSelectionReasons.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/result/ComponentSelectionReasons.java index aef0dd92d4767..7193a3544b97d 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/result/ComponentSelectionReasons.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/result/ComponentSelectionReasons.java @@ -96,7 +96,7 @@ public boolean isSelectedByRule() { } public boolean isExpected() { - return isCauseExpected(Iterables.getLast(descriptions)); + return descriptions.size() == 1 && isCauseExpected(Iterables.getLast(descriptions)); } public boolean isCompositeSubstitution() { diff --git a/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/result/DefaultComponentSelectionReasonTest.groovy b/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/result/DefaultComponentSelectionReasonTest.groovy new file mode 100644 index 0000000000000..245ade5b07dc0 --- /dev/null +++ b/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/result/DefaultComponentSelectionReasonTest.groovy @@ -0,0 +1,64 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.api.internal.artifacts.ivyservice.resolveengine.result + +import org.gradle.api.artifacts.result.ComponentSelectionCause +import org.gradle.api.artifacts.result.ComponentSelectionReason +import org.gradle.internal.Describables +import spock.lang.Specification + +class DefaultComponentSelectionReasonTest extends Specification { + + def "requested only selection reason is expected"() { + when: + def reason = ComponentSelectionReasons.requested() + + then: + reason.isExpected() + } + + def "root only selection reason is expected"() { + when: + def reason = ComponentSelectionReasons.root() + + then: + reason.isExpected() + } + + def "requested with other selection reason is not expected"() { + given: + def reason = ComponentSelectionReasons.requested() + + when: + addCause(reason, ComponentSelectionCause.CONFLICT_RESOLUTION, "test") + + then: + !reason.isExpected() + } + + def "other selection reason and requested is not expected"() { + when: + def reason = ComponentSelectionReasons.of(new DefaultComponentSelectionDescriptor(ComponentSelectionCause.REQUESTED), new DefaultComponentSelectionDescriptor(ComponentSelectionCause.FORCED)) + + then: + !reason.isExpected() + } + + def addCause(ComponentSelectionReason reason, ComponentSelectionCause cause, String description) { + ((ComponentSelectionReasonInternal) reason).addCause(cause, Describables.of(description)) + } +} From 911e1f84d885d97bb66d05790c6f346880663c56 Mon Sep 17 00:00:00 2001 From: Louis Jacomet Date: Tue, 26 Feb 2019 11:10:41 +0100 Subject: [PATCH 156/853] Clarify plugin incompatibility Since applying the `java-platform` plugin after `java` or `java-library` already throws, we will just improve the error message in that case. In order to not break existing builds, applying `java` or `java-library` after `java-platform` will cause a deprecation warning in 5.3+ and will break in 6+. Fixes #8553 --- .../docs/userguide/java_platform_plugin.adoc | 5 ++ ...aIncompatiblePluginsIntegrationTest.groovy | 57 +++++++++++++++++++ .../api/plugins/JavaPlatformPlugin.java | 7 +++ .../org/gradle/api/plugins/JavaPlugin.java | 6 ++ 4 files changed, 75 insertions(+) create mode 100644 subprojects/plugins/src/integTest/groovy/org/gradle/java/JavaIncompatiblePluginsIntegrationTest.groovy diff --git a/subprojects/docs/src/docs/userguide/java_platform_plugin.adoc b/subprojects/docs/src/docs/userguide/java_platform_plugin.adoc index 360e06777028e..9e6609bb2ed09 100644 --- a/subprojects/docs/src/docs/userguide/java_platform_plugin.adoc +++ b/subprojects/docs/src/docs/userguide/java_platform_plugin.adoc @@ -30,6 +30,11 @@ it is only used to reference other libraries, so that they play well together du Platforms can be published as {maven-bom}[Maven BOMs] or with the experimental {metadata-file-spec}[Gradle metadata file] format. +[NOTE] +==== +The `java-platform` plugin cannot be used in combination with the `java` or `java-library` plugins in a given project. +Conceptually a project is either a platform, with no binaries, _or_ produces binaries. +==== [[sec:java_platform_usage]] == Usage diff --git a/subprojects/plugins/src/integTest/groovy/org/gradle/java/JavaIncompatiblePluginsIntegrationTest.groovy b/subprojects/plugins/src/integTest/groovy/org/gradle/java/JavaIncompatiblePluginsIntegrationTest.groovy new file mode 100644 index 0000000000000..4f8ee3519c2c5 --- /dev/null +++ b/subprojects/plugins/src/integTest/groovy/org/gradle/java/JavaIncompatiblePluginsIntegrationTest.groovy @@ -0,0 +1,57 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.java + +import org.gradle.integtests.fixtures.AbstractIntegrationSpec +import spock.lang.Unroll + +class JavaIncompatiblePluginsIntegrationTest extends AbstractIntegrationSpec { + + @Unroll + def "nag users when applying both java-platform and #plugin"() { + when: + buildFile << """ +plugins { + id 'java-platform' + id '${plugin}' +} +""" + then: + executer.expectDeprecationWarning() + succeeds 'help' + + where: + plugin << ['java', 'java-library'] + } + + @Unroll + def "cannot apply both #plugin and java-platform"() { + when: + buildFile << """ +plugins { + id '${plugin}' + id 'java-platform' +} +""" + then: + fails 'help' + failureHasCause("The \"java-platform\" plugin cannot be applied together with the \"java\" (or \"java-library\") plugin") + + where: + plugin << ['java', 'java-library'] + } +} diff --git a/subprojects/plugins/src/main/java/org/gradle/api/plugins/JavaPlatformPlugin.java b/subprojects/plugins/src/main/java/org/gradle/api/plugins/JavaPlatformPlugin.java index 67d8761042009..cec72c4688c5c 100644 --- a/subprojects/plugins/src/main/java/org/gradle/api/plugins/JavaPlatformPlugin.java +++ b/subprojects/plugins/src/main/java/org/gradle/api/plugins/JavaPlatformPlugin.java @@ -93,11 +93,18 @@ public JavaPlatformPlugin(SoftwareComponentFactory softwareComponentFactory) { @Override public void apply(Project project) { + if (project.getPluginManager().hasPlugin("java")) { + // This already throws when creating `apiElements` so be eager to have a clear error message + throw new IllegalStateException("The \"java-platform\" plugin cannot be applied together with the \"java\" (or \"java-library\") plugin. " + + "A project is either a platform or a library but cannot be both at the same time."); + } project.getPluginManager().apply(BasePlugin.class); createConfigurations(project); configureExtension(project); addPlatformDisambiguationRule(project); JavaEcosystemSupport.configureSchema(project.getDependencies().getAttributesSchema(), project.getObjects()); + + } private void addPlatformDisambiguationRule(Project project) { diff --git a/subprojects/plugins/src/main/java/org/gradle/api/plugins/JavaPlugin.java b/subprojects/plugins/src/main/java/org/gradle/api/plugins/JavaPlugin.java index 7ca7e867d46bf..27ba7088e8a1a 100644 --- a/subprojects/plugins/src/main/java/org/gradle/api/plugins/JavaPlugin.java +++ b/subprojects/plugins/src/main/java/org/gradle/api/plugins/JavaPlugin.java @@ -55,6 +55,7 @@ import org.gradle.api.tasks.testing.Test; import org.gradle.internal.cleanup.BuildOutputCleanupRegistry; import org.gradle.language.jvm.tasks.ProcessResources; +import org.gradle.util.DeprecationLogger; import javax.inject.Inject; import java.io.File; @@ -274,6 +275,11 @@ public void apply(ProjectInternal project) { configureTest(project, javaConvention); configureArchivesAndComponent(project, javaConvention); configureBuild(project); + + if (project.getPluginManager().hasPlugin("java-platform")) { + DeprecationLogger.nagUserOfDeprecatedBehaviour("The \"java\" (or \"java-library\") plugin cannot be used together with the \"java-platform\" plugin on a given project. " + + "A project is either a platform or a library but cannot be both at the same time."); + } } private void configureSourceSets(JavaPluginConvention pluginConvention, final BuildOutputCleanupRegistry buildOutputCleanupRegistry) { From af5a05ebc4ca89f724c3ba2e53ac40a8423d1462 Mon Sep 17 00:00:00 2001 From: "Rodrigo B. de Oliveira" Date: Tue, 26 Feb 2019 11:09:47 -0300 Subject: [PATCH 157/853] Disable `verifyTestFilesCleanup` in Kotlin DSL projects with leaking test files --- .../kotlin-dsl-integ-tests/kotlin-dsl-integ-tests.gradle.kts | 5 +++++ subprojects/kotlin-dsl-plugins/kotlin-dsl-plugins.gradle.kts | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/subprojects/kotlin-dsl-integ-tests/kotlin-dsl-integ-tests.gradle.kts b/subprojects/kotlin-dsl-integ-tests/kotlin-dsl-integ-tests.gradle.kts index 4a3c49a405807..6a1a83e741574 100644 --- a/subprojects/kotlin-dsl-integ-tests/kotlin-dsl-integ-tests.gradle.kts +++ b/subprojects/kotlin-dsl-integ-tests/kotlin-dsl-integ-tests.gradle.kts @@ -49,6 +49,11 @@ pluginBundles.forEach { tasks { + // TODO:kotlin-dsl + verifyTestFilesCleanup { + isEnabled = false + } + val testEnvironment by registering { pluginBundles.forEach { dependsOn("$it:publishPluginsToTestRepository") diff --git a/subprojects/kotlin-dsl-plugins/kotlin-dsl-plugins.gradle.kts b/subprojects/kotlin-dsl-plugins/kotlin-dsl-plugins.gradle.kts index da34d30592eb3..e9b4492304140 100644 --- a/subprojects/kotlin-dsl-plugins/kotlin-dsl-plugins.gradle.kts +++ b/subprojects/kotlin-dsl-plugins/kotlin-dsl-plugins.gradle.kts @@ -99,3 +99,8 @@ integTestTasks.configureEach { tasks.noDaemonIntegTest { enabled = false } + +// TODO:kotlin-dsl +tasks.verifyTestFilesCleanup { + enabled = false +} From 637f921d031bb573ba01e7a49f96435d55842154 Mon Sep 17 00:00:00 2001 From: "Rodrigo B. de Oliveira" Date: Tue, 26 Feb 2019 11:15:14 -0300 Subject: [PATCH 158/853] Use same spelling for `Task.enabled` property --- .../kotlin-dsl-integ-tests/kotlin-dsl-integ-tests.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subprojects/kotlin-dsl-integ-tests/kotlin-dsl-integ-tests.gradle.kts b/subprojects/kotlin-dsl-integ-tests/kotlin-dsl-integ-tests.gradle.kts index 6a1a83e741574..17735bba53663 100644 --- a/subprojects/kotlin-dsl-integ-tests/kotlin-dsl-integ-tests.gradle.kts +++ b/subprojects/kotlin-dsl-integ-tests/kotlin-dsl-integ-tests.gradle.kts @@ -51,7 +51,7 @@ tasks { // TODO:kotlin-dsl verifyTestFilesCleanup { - isEnabled = false + enabled = false } val testEnvironment by registering { From d7f06142bbf3bb21134d3ed3e9ee69af2d4f1f0a Mon Sep 17 00:00:00 2001 From: Stefan Wolf Date: Tue, 26 Feb 2019 14:06:41 +0100 Subject: [PATCH 159/853] Add TransformAction.getParameters So the implementors of `TransformAction` don't need to add the method. --- subprojects/core-api/core-api.gradle.kts | 3 +- .../artifacts/transform/TransformAction.java | 10 ++++-- ...factTransformCachingIntegrationTest.groovy | 3 -- .../ArtifactTransformIntegrationTest.groovy | 8 ++--- ...ctTransformIsolationIntegrationTest.groovy | 5 --- ...sformValuesInjectionIntegrationTest.groovy | 31 +++---------------- ...formWithDependenciesIntegrationTest.groovy | 3 -- ...nsformWithFileInputsIntegrationTest.groovy | 6 ---- .../transform/DefaultTransformer.java | 7 +++-- ...DefaultVariantTransformRegistryTest.groovy | 4 +-- ...ractConsoleBuildPhaseFunctionalTest.groovy | 2 -- 11 files changed, 24 insertions(+), 58 deletions(-) diff --git a/subprojects/core-api/core-api.gradle.kts b/subprojects/core-api/core-api.gradle.kts index 7e0fa843896b3..367fc59afbbb7 100644 --- a/subprojects/core-api/core-api.gradle.kts +++ b/subprojects/core-api/core-api.gradle.kts @@ -1,5 +1,5 @@ -import org.gradle.gradlebuild.unittestandcompile.ModuleType import org.gradle.gradlebuild.testing.integrationtests.cleanup.WhenNotEmpty +import org.gradle.gradlebuild.unittestandcompile.ModuleType /* * Copyright 2017 the original author or authors. @@ -33,6 +33,7 @@ dependencies { implementation(library("commons_io")) implementation(library("commons_lang")) implementation(library("jcip")) + implementation(library("inject")) testFixturesImplementation(project(":internalTesting")) } diff --git a/subprojects/core-api/src/main/java/org/gradle/api/artifacts/transform/TransformAction.java b/subprojects/core-api/src/main/java/org/gradle/api/artifacts/transform/TransformAction.java index ec21b3af2f318..96ae08786cead 100644 --- a/subprojects/core-api/src/main/java/org/gradle/api/artifacts/transform/TransformAction.java +++ b/subprojects/core-api/src/main/java/org/gradle/api/artifacts/transform/TransformAction.java @@ -18,6 +18,8 @@ import org.gradle.api.Incubating; +import javax.inject.Inject; + /** * Interface for artifact transform actions. * @@ -25,8 +27,6 @@ * *

    Implementations can receive parameters by using annotated abstract getter methods.

    * - *

    A property annotated with {@link InjectTransformParameters} will receive the object provided by {@link TransformSpec#getParameters()}. - * *

    A property annotated with {@link InputArtifact} will receive the input artifact location, which is the file or directory that the transform should be applied to. * *

    A property annotated with {@link InputArtifactDependencies} will receive the dependencies of its input artifact. @@ -37,6 +37,12 @@ @Incubating public interface TransformAction { + /** + * The object provided by {@link TransformSpec#getParameters()}. + */ + @Inject + T getParameters(); + /** * Executes the transform. * diff --git a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformCachingIntegrationTest.groovy b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformCachingIntegrationTest.groovy index 420ddf3468d87..d16df4695ad71 100644 --- a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformCachingIntegrationTest.groovy +++ b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformCachingIntegrationTest.groovy @@ -1486,9 +1486,6 @@ ${getFileSizerBody(fileValue, 'new File(outputDirectory, ', 'new File(outputDire void setValue(Number value) } abstract class FileSizer implements TransformAction { - @InjectTransformParameters - abstract FileSizerParameters getParameters() - @InputArtifact abstract File getInput() diff --git a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformIntegrationTest.groovy b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformIntegrationTest.groovy index 3bbf3201ba79b..488bf1add791c 100644 --- a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformIntegrationTest.groovy +++ b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformIntegrationTest.groovy @@ -1553,7 +1553,7 @@ Found the following transforms: compile files(a) } - class FailingTransform implements TransformAction { + abstract class FailingTransform implements TransformAction { void transform(TransformOutputs outputs) { ${switch (type) { case FileType.Missing: @@ -1623,7 +1623,7 @@ Found the following transforms: compile files(a) } - class DirectoryTransform implements TransformAction { + abstract class DirectoryTransform implements TransformAction { void transform(TransformOutputs outputs) { def outputFile = outputs.file("some/dir/output.txt") assert outputFile.parentFile.directory @@ -1739,7 +1739,7 @@ Found the following transforms: SomewhereElseTransform.output = file("other.jar") - class SomewhereElseTransform implements TransformAction { + abstract class SomewhereElseTransform implements TransformAction { static def output void transform(TransformOutputs outputs) { def outputFile = outputs.file(output) @@ -1953,7 +1953,7 @@ Found the following transforms: void setInput(CustomType input) } - class Custom implements TransformAction { + abstract class Custom implements TransformAction { void transform(TransformOutputs outputs) { } } diff --git a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformIsolationIntegrationTest.groovy b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformIsolationIntegrationTest.groovy index df98ce43994aa..60c5b9e497efe 100644 --- a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformIsolationIntegrationTest.groovy +++ b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformIsolationIntegrationTest.groovy @@ -92,11 +92,6 @@ class Resolve extends Copy { } abstract class CountRecorder implements TransformAction { - private final Counter counter; - - @InjectTransformParameters - abstract CountRecorderParameters getParameters() - @InputArtifact abstract File getInput() diff --git a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformValuesInjectionIntegrationTest.groovy b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformValuesInjectionIntegrationTest.groovy index 193bee5e945c8..774ae9c68ceaf 100644 --- a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformValuesInjectionIntegrationTest.groovy +++ b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformValuesInjectionIntegrationTest.groovy @@ -71,8 +71,6 @@ class ArtifactTransformValuesInjectionIntegrationTest extends AbstractDependency } abstract class MakeGreen implements TransformAction { - @InjectTransformParameters - abstract MakeGreenParameters getParameters() @InputArtifact abstract File getInput() @@ -119,9 +117,6 @@ class ArtifactTransformValuesInjectionIntegrationTest extends AbstractDependency } abstract class MakeGreen implements TransformAction { - @InjectTransformParameters - abstract MakeGreenParameters getParameters() - void transform(TransformOutputs outputs) { println "processing using " + parameters.prop.get() assert parameters.otherProp.getOrNull() == ${expectedNullValue} @@ -177,9 +172,6 @@ class ArtifactTransformValuesInjectionIntegrationTest extends AbstractDependency @CacheableTransform abstract class MakeGreen implements TransformAction { - @InjectTransformParameters - abstract MakeGreenParameters getParameters() - void transform(TransformOutputs outputs) { throw new RuntimeException() } @@ -227,9 +219,6 @@ class ArtifactTransformValuesInjectionIntegrationTest extends AbstractDependency } abstract class MakeGreen implements TransformAction { - @InjectTransformParameters - abstract MakeGreenParameters getParameters() - void transform(TransformOutputs outputs) { throw new RuntimeException() } @@ -275,9 +264,6 @@ class ArtifactTransformValuesInjectionIntegrationTest extends AbstractDependency } abstract class MakeGreen implements TransformAction { - @InjectTransformParameters - abstract MakeGreenParameters getParameters() - void transform(TransformOutputs outputs) { throw new RuntimeException() } @@ -322,9 +308,6 @@ class ArtifactTransformValuesInjectionIntegrationTest extends AbstractDependency @CacheableTransform abstract class MakeGreen implements TransformAction { - @InjectTransformParameters - abstract MakeGreenParameters getParameters() - @InputFile File inputFile @@ -501,7 +484,7 @@ abstract class MakeGreen extends ArtifactTransform { annotation << [InputArtifact, InputArtifactDependencies, InjectTransformParameters] } - def "transform cannot receive parameter object via constructor parameter"() { + def "transform can receive parameter object via constructor parameter"() { settingsFile << """ include 'a', 'b', 'c' """ @@ -524,7 +507,7 @@ abstract class MakeGreen extends ArtifactTransform { void setExtension(String value) } - class MakeGreen implements TransformAction { + abstract class MakeGreen implements TransformAction { private MakeGreenParameters conf @Inject @@ -537,14 +520,8 @@ abstract class MakeGreen extends ArtifactTransform { } """ - when: - fails(":a:resolve") - - then: - // Documents existing behaviour. Should fail eagerly and with a better error message - failure.assertHasDescription("Execution failed for task ':a:resolve'.") - failure.assertHasCause("Execution failed for MakeGreen: ${file('b/build/b.jar')}.") - failure.assertHasCause("Unable to determine constructor argument #1: missing parameter of interface MakeGreenParameters, or no service of type interface MakeGreenParameters") + expect: + succeeds(":a:resolve") } @Unroll diff --git a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformWithDependenciesIntegrationTest.groovy b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformWithDependenciesIntegrationTest.groovy index 049d794d558d1..d8b9d60721ac3 100644 --- a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformWithDependenciesIntegrationTest.groovy +++ b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformWithDependenciesIntegrationTest.groovy @@ -109,9 +109,6 @@ import javax.inject.Inject abstract class TestTransform implements TransformAction { - @InjectTransformParameters - abstract TestTransformParameters getParameters() - @InputArtifactDependencies abstract FileCollection getInputArtifactDependencies() diff --git a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformWithFileInputsIntegrationTest.groovy b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformWithFileInputsIntegrationTest.groovy index 8ca65c4fd219b..de80ad6e36617 100644 --- a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformWithFileInputsIntegrationTest.groovy +++ b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformWithFileInputsIntegrationTest.groovy @@ -37,8 +37,6 @@ class ArtifactTransformWithFileInputsIntegrationTest extends AbstractDependencyR } abstract class MakeGreen implements TransformAction { - @InjectTransformParameters - abstract MakeGreenParameters getParameters() @InputArtifact abstract File getInput() @@ -289,8 +287,6 @@ class ArtifactTransformWithFileInputsIntegrationTest extends AbstractDependencyR } abstract class MakeGreen implements TransformAction { - @InjectTransformParameters - abstract MakeGreenParameters getParameters() @InputArtifact abstract File getInput() @@ -342,8 +338,6 @@ class ArtifactTransformWithFileInputsIntegrationTest extends AbstractDependencyR } abstract class MakeGreen implements TransformAction { - @InjectTransformParameters - abstract MakeGreenParameters getParameters() @InputArtifact abstract File getInput() diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformer.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformer.java index 4858d5ef2be35..0e9b8b4732512 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformer.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformer.java @@ -20,7 +20,6 @@ import com.google.common.collect.ImmutableSortedMap; import com.google.common.reflect.TypeToken; import org.gradle.api.InvalidUserDataException; -import org.gradle.api.artifacts.transform.InjectTransformParameters; import org.gradle.api.artifacts.transform.InputArtifact; import org.gradle.api.artifacts.transform.InputArtifactDependencies; import org.gradle.api.artifacts.transform.TransformAction; @@ -286,7 +285,9 @@ public TransformServiceLookup(File inputFile, @Nullable TransformParameters para ImmutableList.Builder builder = ImmutableList.builder(); builder.add(new InjectionPoint(InputArtifact.class, File.class, inputFile)); if (parameters != null) { - builder.add(new InjectionPoint(InjectTransformParameters.class, parameters.getClass(), parameters)); + builder.add(new InjectionPoint(null, parameters.getClass(), parameters)); + } else { + builder.add(new InjectionPoint(null, TransformParameters.class, new TransformParameters() {})); } if (artifactTransformDependencies != null) { builder.add(new InjectionPoint(InputArtifactDependencies.class, artifactTransformDependencies.getFiles())); @@ -334,7 +335,7 @@ private static class InjectionPoint { private final Class injectedType; private final Object valueToInject; - public InjectionPoint(Class annotation, Class injectedType, Object valueToInject) { + public InjectionPoint(@Nullable Class annotation, Class injectedType, Object valueToInject) { this.annotation = annotation; this.injectedType = injectedType; this.valueToInject = valueToInject; diff --git a/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/DefaultVariantTransformRegistryTest.groovy b/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/DefaultVariantTransformRegistryTest.groovy index 0cd5bc39a8fe5..5ae9669dcb901 100644 --- a/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/DefaultVariantTransformRegistryTest.groovy +++ b/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/DefaultVariantTransformRegistryTest.groovy @@ -341,13 +341,13 @@ class DefaultVariantTransformRegistryTest extends Specification { } } - static class TestTransform implements TransformAction { + static abstract class TestTransform implements TransformAction { @Override void transform(TransformOutputs outputs) { } } - static class ParameterlessTestTransform implements TransformAction { + static abstract class ParameterlessTestTransform implements TransformAction { @Override void transform(TransformOutputs outputs) { } diff --git a/subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/AbstractConsoleBuildPhaseFunctionalTest.groovy b/subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/AbstractConsoleBuildPhaseFunctionalTest.groovy index 3c04a5c9d1530..eb8b4714e596f 100644 --- a/subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/AbstractConsoleBuildPhaseFunctionalTest.groovy +++ b/subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/AbstractConsoleBuildPhaseFunctionalTest.groovy @@ -333,8 +333,6 @@ abstract class AbstractConsoleBuildPhaseFunctionalTest extends AbstractIntegrati } abstract class FileSizer implements TransformAction { - @InjectTransformParameters - abstract FileSizerParameters getParameters() @InputArtifactDependencies abstract FileCollection getDependencies() @InputArtifact From 827e336f6833782980adfdc9baf8955c854cd362 Mon Sep 17 00:00:00 2001 From: "Rodrigo B. de Oliveira" Date: Tue, 26 Feb 2019 12:07:06 -0300 Subject: [PATCH 160/853] Simplify `AbstractKotlinIntegrationTest` hierarchy --- ...PluginGradlePluginCrossVersionSmokeTest.kt | 2 +- .../dsl/plugins/dsl/KotlinDslPluginTest.kt | 23 +++--------- .../embedded/EmbeddedKotlinPluginTest.kt | 12 +++---- .../AbstractPrecompiledScriptPluginTest.kt | 35 ------------------- .../fixtures/AbstractKotlinIntegrationTest.kt | 35 +++++++++++++++++++ .../AccessorsClassPathIntegrationTest.kt | 8 ----- .../KotlinBuildScriptModelIntegrationTest.kt | 28 ++++++++------- .../KotlinInitScriptModelIntegrationTest.kt | 4 --- ...otlinSettingsScriptModelIntegrationTest.kt | 4 +-- .../integration/ScriptModelIntegrationTest.kt | 24 +++++-------- 10 files changed, 72 insertions(+), 103 deletions(-) diff --git a/subprojects/kotlin-dsl-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/plugins/dsl/KotlinDslPluginGradlePluginCrossVersionSmokeTest.kt b/subprojects/kotlin-dsl-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/plugins/dsl/KotlinDslPluginGradlePluginCrossVersionSmokeTest.kt index e19b4cd6b4d6d..1af56c36ac008 100644 --- a/subprojects/kotlin-dsl-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/plugins/dsl/KotlinDslPluginGradlePluginCrossVersionSmokeTest.kt +++ b/subprojects/kotlin-dsl-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/plugins/dsl/KotlinDslPluginGradlePluginCrossVersionSmokeTest.kt @@ -99,7 +99,7 @@ class KotlinDslPluginGradlePluginCrossVersionSmokeTest( """) withFile("src/main/kotlin/SomeSource.kt", "fun main(args: Array) {}") - buildWithPlugin("classes").apply { + build("classes").apply { assertThat( output, allOf( diff --git a/subprojects/kotlin-dsl-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/plugins/dsl/KotlinDslPluginTest.kt b/subprojects/kotlin-dsl-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/plugins/dsl/KotlinDslPluginTest.kt index 08c8cf827a1af..92baa44fa5ebd 100644 --- a/subprojects/kotlin-dsl-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/plugins/dsl/KotlinDslPluginTest.kt +++ b/subprojects/kotlin-dsl-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/plugins/dsl/KotlinDslPluginTest.kt @@ -2,12 +2,12 @@ package org.gradle.kotlin.dsl.plugins.dsl import org.gradle.api.internal.DocumentationRegistry -import org.gradle.test.fixtures.file.LeaksFileHandles - import org.gradle.kotlin.dsl.fixtures.AbstractPluginTest import org.gradle.kotlin.dsl.fixtures.containsMultiLineString import org.gradle.kotlin.dsl.fixtures.normalisedPath +import org.gradle.test.fixtures.file.LeaksFileHandles + import org.hamcrest.CoreMatchers.containsString import org.hamcrest.CoreMatchers.not @@ -38,7 +38,7 @@ class KotlinDslPluginTest : AbstractPluginTest() { """) - val result = buildWithPlugin("classes") + val result = build("classes") result.assertTaskExecuted(":compileKotlin") } @@ -212,7 +212,7 @@ class KotlinDslPluginTest : AbstractPluginTest() { """) - val result = buildWithPlugin("classes") + val result = build("classes") result.assertTaskExecuted(":compileKotlin") } @@ -332,20 +332,7 @@ class KotlinDslPluginTest : AbstractPluginTest() { """) } - private - fun withKotlinDslPlugin() { - withBuildScript(""" - - plugins { - `kotlin-dsl` - } - - $repositoriesBlock - - """) - } - private fun outputOf(vararg arguments: String) = - buildWithPlugin(*arguments).output + build(*arguments).output } diff --git a/subprojects/kotlin-dsl-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/plugins/embedded/EmbeddedKotlinPluginTest.kt b/subprojects/kotlin-dsl-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/plugins/embedded/EmbeddedKotlinPluginTest.kt index d2f2d02d7def1..98fa7db6281b4 100644 --- a/subprojects/kotlin-dsl-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/plugins/embedded/EmbeddedKotlinPluginTest.kt +++ b/subprojects/kotlin-dsl-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/plugins/embedded/EmbeddedKotlinPluginTest.kt @@ -44,7 +44,7 @@ class EmbeddedKotlinPluginTest : AbstractPluginTest() { """) - val result = buildWithPlugin("assemble") + val result = build("assemble") result.assertOutputContains(":compileKotlin NO-SOURCE") } @@ -73,7 +73,7 @@ class EmbeddedKotlinPluginTest : AbstractPluginTest() { """) - buildWithPlugin("assertions") + build("assertions") } @Test @@ -94,7 +94,7 @@ class EmbeddedKotlinPluginTest : AbstractPluginTest() { """) - val result = buildWithPlugin("dependencies") + val result = build("dependencies") assertThat(result.output, containsString("Embedded Kotlin Repository")) listOf("stdlib", "reflect", "compiler-embeddable").forEach { @@ -150,7 +150,7 @@ class EmbeddedKotlinPluginTest : AbstractPluginTest() { printFileNamesOf() """) - val result = buildWithPlugin("help") + val result = build("help") listOf("stdlib", "reflect").forEach { assertThat(result.output, containsString("kotlin-$it-$embeddedKotlinVersion.jar")) @@ -174,7 +174,7 @@ class EmbeddedKotlinPluginTest : AbstractPluginTest() { configurations["customConfiguration"].files.map { println(it) } """) - val result = buildWithPlugin("dependencies", "--configuration", "customConfiguration") + val result = build("dependencies", "--configuration", "customConfiguration") listOf("stdlib", "reflect").forEach { assertThat(result.output, containsString("org.jetbrains.kotlin:kotlin-$it:$embeddedKotlinVersion")) @@ -202,7 +202,7 @@ class EmbeddedKotlinPluginTest : AbstractPluginTest() { withFile("src/main/kotlin/source.kt", """var foo = "bar"""") - val result = buildWithPlugin("assemble") + val result = build("assemble") result.assertTaskExecuted(":compileKotlin") } diff --git a/subprojects/kotlin-dsl-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/AbstractPrecompiledScriptPluginTest.kt b/subprojects/kotlin-dsl-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/AbstractPrecompiledScriptPluginTest.kt index ddf128cfb9275..bd546c5fe94af 100644 --- a/subprojects/kotlin-dsl-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/AbstractPrecompiledScriptPluginTest.kt +++ b/subprojects/kotlin-dsl-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/AbstractPrecompiledScriptPluginTest.kt @@ -29,18 +29,6 @@ open class AbstractPrecompiledScriptPluginTest : AbstractPluginTest() { requireGradleDistributionOnEmbeddedExecuter() } - protected - fun givenPrecompiledKotlinScript(fileName: String, code: String) { - withKotlinDslPlugin() - withPrecompiledKotlinScript(fileName, code) - compileKotlin() - } - - protected - fun withPrecompiledKotlinScript(fileName: String, code: String) { - withFile("src/main/kotlin/$fileName", code) - } - protected inline fun instantiatePrecompiledScriptOf(target: T, className: String): Any = loadCompiledKotlinClass(className) @@ -51,27 +39,4 @@ open class AbstractPrecompiledScriptPluginTest : AbstractPluginTest() { fun loadCompiledKotlinClass(className: String): Class<*> = classLoaderFor(existing("build/classes/kotlin/main")) .loadClass(className) - - protected - fun withKotlinDslPlugin() = - withKotlinDslPluginIn(".") - - protected - fun withKotlinDslPluginIn(baseDir: String) = - withBuildScriptIn(baseDir, scriptWithKotlinDslPlugin()) - - protected - fun scriptWithKotlinDslPlugin(): String = - """ - plugins { - `kotlin-dsl` - } - - $repositoriesBlock - """ - - protected - fun compileKotlin(taskName: String = "classes") { - buildWithPlugin(taskName).assertTaskExecuted(":compileKotlin") - } } diff --git a/subprojects/kotlin-dsl-test-fixtures/src/main/kotlin/org/gradle/kotlin/dsl/fixtures/AbstractKotlinIntegrationTest.kt b/subprojects/kotlin-dsl-test-fixtures/src/main/kotlin/org/gradle/kotlin/dsl/fixtures/AbstractKotlinIntegrationTest.kt index 94c17e21b782b..a26a0adb43fe2 100644 --- a/subprojects/kotlin-dsl-test-fixtures/src/main/kotlin/org/gradle/kotlin/dsl/fixtures/AbstractKotlinIntegrationTest.kt +++ b/subprojects/kotlin-dsl-test-fixtures/src/main/kotlin/org/gradle/kotlin/dsl/fixtures/AbstractKotlinIntegrationTest.kt @@ -129,6 +129,41 @@ abstract class AbstractKotlinIntegrationTest : AbstractIntegrationTest() { """) } + + protected + fun givenPrecompiledKotlinScript(fileName: String, code: String) { + withKotlinDslPlugin() + withPrecompiledKotlinScript(fileName, code) + compileKotlin() + } + + protected + fun withPrecompiledKotlinScript(fileName: String, code: String) = + withFile("src/main/kotlin/$fileName", code) + + protected + fun withKotlinDslPlugin() = + withKotlinDslPluginIn(".") + + protected + fun withKotlinDslPluginIn(baseDir: String) = + withBuildScriptIn(baseDir, scriptWithKotlinDslPlugin()) + + protected + fun scriptWithKotlinDslPlugin(): String = + """ + plugins { + `kotlin-dsl` + } + + $repositoriesBlock + """ + + protected + fun compileKotlin(taskName: String = "classes") { + build(taskName).assertTaskExecuted(":compileKotlin") + } + protected fun withClassJar(fileName: String, vararg classes: Class<*>) = withZip(fileName, classEntriesFor(*classes)) diff --git a/subprojects/kotlin-dsl/src/integTest/kotlin/org/gradle/kotlin/dsl/accessors/AccessorsClassPathIntegrationTest.kt b/subprojects/kotlin-dsl/src/integTest/kotlin/org/gradle/kotlin/dsl/accessors/AccessorsClassPathIntegrationTest.kt index 2f56e422a9184..409ab224bef0a 100644 --- a/subprojects/kotlin-dsl/src/integTest/kotlin/org/gradle/kotlin/dsl/accessors/AccessorsClassPathIntegrationTest.kt +++ b/subprojects/kotlin-dsl/src/integTest/kotlin/org/gradle/kotlin/dsl/accessors/AccessorsClassPathIntegrationTest.kt @@ -129,12 +129,4 @@ class AccessorsClassPathIntegrationTest : ScriptModelIntegrationTest() { private val accessorsClassFilePath = "org/gradle/kotlin/dsl/ArchivesConfigurationAccessorsKt.class" - - private - fun classPathFor(buildFile: File) = - kotlinBuildScriptModelFor(buildFile).classPath - - private - fun kotlinBuildScriptModelFor(buildFile: File) = - kotlinBuildScriptModelFor(projectRoot, buildFile) } diff --git a/subprojects/kotlin-dsl/src/integTest/kotlin/org/gradle/kotlin/dsl/integration/KotlinBuildScriptModelIntegrationTest.kt b/subprojects/kotlin-dsl/src/integTest/kotlin/org/gradle/kotlin/dsl/integration/KotlinBuildScriptModelIntegrationTest.kt index 9a550d0656ea7..6af52da3726e1 100644 --- a/subprojects/kotlin-dsl/src/integTest/kotlin/org/gradle/kotlin/dsl/integration/KotlinBuildScriptModelIntegrationTest.kt +++ b/subprojects/kotlin-dsl/src/integTest/kotlin/org/gradle/kotlin/dsl/integration/KotlinBuildScriptModelIntegrationTest.kt @@ -26,11 +26,11 @@ class KotlinBuildScriptModelIntegrationTest : ScriptModelIntegrationTest() { withBuildSrc() withDefaultSettings() - withBuildScript(""" + val buildScript = withBuildScript(""" val p = """) - assertContainsBuildSrc(canonicalClassPath()) + assertContainsBuildSrc(canonicalClassPathFor(buildScript)) } @Test @@ -39,11 +39,11 @@ class KotlinBuildScriptModelIntegrationTest : ScriptModelIntegrationTest() { withBuildSrc() withDefaultSettings() - withBuildScript(""" + val buildScript = withBuildScript(""" buildscript { TODO() } """) - assertContainsBuildSrc(canonicalClassPath()) + assertContainsBuildSrc(canonicalClassPathFor(buildScript)) } @Test @@ -52,7 +52,7 @@ class KotlinBuildScriptModelIntegrationTest : ScriptModelIntegrationTest() { withFile("classes.jar") withDefaultSettings() - withBuildScript(""" + val buildScript = withBuildScript(""" buildscript { dependencies { classpath(files("classes.jar")) @@ -63,7 +63,9 @@ class KotlinBuildScriptModelIntegrationTest : ScriptModelIntegrationTest() { """) assertClassPathContains( - existing("classes.jar")) + canonicalClassPathFor(buildScript), + existing("classes.jar") + ) } @Test @@ -85,7 +87,7 @@ class KotlinBuildScriptModelIntegrationTest : ScriptModelIntegrationTest() { """) withDefaultSettings() - assertContainsBuildSrc(canonicalClassPath()) + assertContainsBuildSrc(canonicalClassPathFor(file("build.gradle.kts"))) } @Test @@ -96,7 +98,7 @@ class KotlinBuildScriptModelIntegrationTest : ScriptModelIntegrationTest() { withFile("classes.jar", "") withDefaultSettings() - withFile("build.gradle", """ + val buildScript = withFile("build.gradle", """ buildscript { dependencies { classpath(files("classes.jar")) @@ -104,7 +106,7 @@ class KotlinBuildScriptModelIntegrationTest : ScriptModelIntegrationTest() { } """) - val classPath = canonicalClassPath() + val classPath = canonicalClassPathFor(buildScript) assertThat( classPath.map { it.name }, hasItem("classes.jar")) @@ -337,7 +339,7 @@ class KotlinBuildScriptModelIntegrationTest : ScriptModelIntegrationTest() { val scriptPlugin = withFile("plugin.gradle.kts", scriptPluginCode) - val scriptPluginClassPath = canonicalClassPathFor(projectRoot, scriptPlugin) + val scriptPluginClassPath = canonicalClassPathFor(scriptPlugin) assertThat( scriptPluginClassPath.map { it.name }, allOf( @@ -366,7 +368,7 @@ class KotlinBuildScriptModelIntegrationTest : ScriptModelIntegrationTest() { throw IllegalStateException() """) - val model = kotlinBuildScriptModelFor(projectRoot, scriptPlugin) + val model = kotlinBuildScriptModelFor(scriptPlugin) assertThat( "Script body shouldn't be evaluated", model.exceptions, @@ -383,14 +385,14 @@ class KotlinBuildScriptModelIntegrationTest : ScriptModelIntegrationTest() { @Test fun `can fetch classpath of plugin portal plugin in plugins block`() { withDefaultSettings() - withBuildScript(""" + val buildScript = withBuildScript(""" plugins { id("org.gradle.hello-world") version "0.2" } """) assertThat( - canonicalClassPath().map { it.name }, + canonicalClassPathFor(buildScript).map { it.name }, hasItems("gradle-hello-world-plugin-0.2.jar")) } diff --git a/subprojects/kotlin-dsl/src/integTest/kotlin/org/gradle/kotlin/dsl/integration/KotlinInitScriptModelIntegrationTest.kt b/subprojects/kotlin-dsl/src/integTest/kotlin/org/gradle/kotlin/dsl/integration/KotlinInitScriptModelIntegrationTest.kt index a6e35528493b3..1696defcb5328 100644 --- a/subprojects/kotlin-dsl/src/integTest/kotlin/org/gradle/kotlin/dsl/integration/KotlinInitScriptModelIntegrationTest.kt +++ b/subprojects/kotlin-dsl/src/integTest/kotlin/org/gradle/kotlin/dsl/integration/KotlinInitScriptModelIntegrationTest.kt @@ -49,8 +49,4 @@ class KotlinInitScriptModelIntegrationTest : ScriptModelIntegrationTest() { classPath, existing("classes.jar")) } - - private - fun canonicalClassPathFor(initScript: File) = - canonicalClassPathFor(projectRoot, initScript) } diff --git a/subprojects/kotlin-dsl/src/integTest/kotlin/org/gradle/kotlin/dsl/integration/KotlinSettingsScriptModelIntegrationTest.kt b/subprojects/kotlin-dsl/src/integTest/kotlin/org/gradle/kotlin/dsl/integration/KotlinSettingsScriptModelIntegrationTest.kt index fbf2f6409ce3f..184e9043bcdb2 100644 --- a/subprojects/kotlin-dsl/src/integTest/kotlin/org/gradle/kotlin/dsl/integration/KotlinSettingsScriptModelIntegrationTest.kt +++ b/subprojects/kotlin-dsl/src/integTest/kotlin/org/gradle/kotlin/dsl/integration/KotlinSettingsScriptModelIntegrationTest.kt @@ -32,7 +32,7 @@ class KotlinSettingsScriptModelIntegrationTest : ScriptModelIntegrationTest() { } """) - val classPath = canonicalClassPathFor(projectRoot, settings) + val classPath = canonicalClassPathFor(settings) assertContainsBuildSrc(classPath) assertContainsGradleKotlinDslJars(classPath) @@ -64,7 +64,7 @@ class KotlinSettingsScriptModelIntegrationTest : ScriptModelIntegrationTest() { } """) - val classPath = canonicalClassPathFor(projectRoot, settings) + val classPath = canonicalClassPathFor(settings) assertContainsBuildSrc(classPath) assertContainsGradleKotlinDslJars(classPath) diff --git a/subprojects/kotlin-dsl/src/integTest/kotlin/org/gradle/kotlin/dsl/integration/ScriptModelIntegrationTest.kt b/subprojects/kotlin-dsl/src/integTest/kotlin/org/gradle/kotlin/dsl/integration/ScriptModelIntegrationTest.kt index eb870b4cf8f3b..5d18a6ba158b2 100644 --- a/subprojects/kotlin-dsl/src/integTest/kotlin/org/gradle/kotlin/dsl/integration/ScriptModelIntegrationTest.kt +++ b/subprojects/kotlin-dsl/src/integTest/kotlin/org/gradle/kotlin/dsl/integration/ScriptModelIntegrationTest.kt @@ -27,7 +27,7 @@ abstract class ScriptModelIntegrationTest : AbstractKotlinIntegrationTest() { protected fun sourcePathFor(scriptFile: File) = - kotlinBuildScriptModelFor(projectRoot, scriptFile).sourcePath + kotlinBuildScriptModelFor(scriptFile).sourcePath protected class ProjectSourceRoots(val projectDir: File, val sourceSets: List, val languages: List) @@ -123,15 +123,11 @@ abstract class ScriptModelIntegrationTest : AbstractKotlinIntegrationTest() { val excludeItems = not(hasItems(*excludes.map { it.name }.toTypedArray())) val condition = if (excludes.isEmpty()) includeItems else allOf(includeItems, excludeItems) assertThat( - classPathFor(importedProjectDir, buildScript).map { it.name }, + classPathFor(buildScript, importedProjectDir).map { it.name }, condition ) } - protected - fun assertClassPathContains(vararg files: File) = - assertClassPathContains(canonicalClassPath(), *files) - protected fun assertClassPathContains(classPath: List, vararg files: File) = assertThat( @@ -166,28 +162,24 @@ abstract class ScriptModelIntegrationTest : AbstractKotlinIntegrationTest() { assert(it.size == files.size) } - protected - fun canonicalClassPath() = - canonicalClassPathFor(projectRoot) - protected fun withJar(named: String): File = withClassJar(named, DeepThought::class.java) internal - fun canonicalClassPathFor(projectDir: File, scriptFile: File? = null) = - kotlinBuildScriptModelFor(projectDir, scriptFile).canonicalClassPath + fun canonicalClassPathFor(scriptFile: File, projectDir: File = projectRoot) = + kotlinBuildScriptModelFor(scriptFile, projectDir).canonicalClassPath - private - fun classPathFor(importedProjectDir: File, scriptFile: File?) = - kotlinBuildScriptModelFor(importedProjectDir, scriptFile).classPath + protected + fun classPathFor(scriptFile: File, projectDir: File = projectRoot) = + kotlinBuildScriptModelFor(scriptFile, projectDir).classPath internal val KotlinBuildScriptModel.canonicalClassPath get() = classPath.map(File::getCanonicalFile) internal - fun kotlinBuildScriptModelFor(importedProjectDir: File, scriptFile: File? = null): KotlinBuildScriptModel = + fun kotlinBuildScriptModelFor(scriptFile: File, importedProjectDir: File = projectRoot): KotlinBuildScriptModel = future { fetchKotlinBuildScriptModelFor( KotlinBuildScriptModelRequest( From 4f27e70e1a99cb46c87006683b6e06671de23583 Mon Sep 17 00:00:00 2001 From: Stefan Wolf Date: Tue, 26 Feb 2019 14:10:35 +0100 Subject: [PATCH 161/853] Remove InjectTransformParameters The annotation is not required any more. --- .../transform/InjectTransformParameters.java | 39 ------------------- ...sformValuesInjectionIntegrationTest.groovy | 7 ++-- ...pendencyManagementGlobalScopeServices.java | 17 +------- ...DefaultVariantTransformRegistryTest.groovy | 3 +- ...lidateTaskPropertiesIntegrationTest.groovy | 2 - 5 files changed, 6 insertions(+), 62 deletions(-) delete mode 100644 subprojects/core-api/src/main/java/org/gradle/api/artifacts/transform/InjectTransformParameters.java diff --git a/subprojects/core-api/src/main/java/org/gradle/api/artifacts/transform/InjectTransformParameters.java b/subprojects/core-api/src/main/java/org/gradle/api/artifacts/transform/InjectTransformParameters.java deleted file mode 100644 index 68ca41f97abe3..0000000000000 --- a/subprojects/core-api/src/main/java/org/gradle/api/artifacts/transform/InjectTransformParameters.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright 2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.gradle.api.artifacts.transform; - -import org.gradle.api.Incubating; -import org.gradle.api.reflect.InjectionPointQualifier; - -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * Attached to a property that should receive the parameter object of the artifact transform. - * - * @since 5.3 - */ -@Incubating -@Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.METHOD}) -@Documented -@InjectionPointQualifier -public @interface InjectTransformParameters { -} diff --git a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformValuesInjectionIntegrationTest.groovy b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformValuesInjectionIntegrationTest.groovy index 774ae9c68ceaf..8afc8cc3339ef 100644 --- a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformValuesInjectionIntegrationTest.groovy +++ b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformValuesInjectionIntegrationTest.groovy @@ -16,7 +16,6 @@ package org.gradle.integtests.resolve.transform -import org.gradle.api.artifacts.transform.InjectTransformParameters import org.gradle.api.artifacts.transform.InputArtifact import org.gradle.api.artifacts.transform.InputArtifactDependencies import org.gradle.api.file.FileCollection @@ -280,7 +279,7 @@ class ArtifactTransformValuesInjectionIntegrationTest extends AbstractDependency failure.assertHasCause("Cannot use @${annotation.simpleName} annotation on method MakeGreenParameters.getBad().") where: - annotation << [InputArtifact, InputArtifactDependencies, InjectTransformParameters] + annotation << [InputArtifact, InputArtifactDependencies] } def "transform action is validated for input output annotations"() { @@ -481,7 +480,7 @@ abstract class MakeGreen extends ArtifactTransform { failure.assertHasCause("Cannot use @${annotation.simpleName} annotation on method MakeGreen.getInputFile().") where: - annotation << [InputArtifact, InputArtifactDependencies, InjectTransformParameters] + annotation << [InputArtifact, InputArtifactDependencies] } def "transform can receive parameter object via constructor parameter"() { @@ -611,6 +610,6 @@ abstract class MakeGreen implements TransformAction { failure.assertHasCause("Cannot use @${annotation.simpleName} annotation on method MyTask.getThing().") where: - annotation << [InputArtifact, InputArtifactDependencies, InjectTransformParameters] + annotation << [InputArtifact, InputArtifactDependencies] } } diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/DependencyManagementGlobalScopeServices.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/DependencyManagementGlobalScopeServices.java index 9a87348ffabb1..7af1b702b5814 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/DependencyManagementGlobalScopeServices.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/DependencyManagementGlobalScopeServices.java @@ -17,7 +17,6 @@ package org.gradle.api.internal.artifacts; import com.google.common.collect.ImmutableSet; -import org.gradle.api.artifacts.transform.InjectTransformParameters; import org.gradle.api.artifacts.transform.InputArtifact; import org.gradle.api.artifacts.transform.InputArtifactDependencies; import org.gradle.api.internal.artifacts.ivyservice.DefaultIvyContextManager; @@ -40,8 +39,6 @@ import org.gradle.api.internal.artifacts.transform.InputArtifactDependenciesAnnotationHandler; import org.gradle.api.internal.tasks.properties.InspectionScheme; import org.gradle.api.internal.tasks.properties.InspectionSchemeFactory; -import org.gradle.api.internal.tasks.properties.annotations.NoOpPropertyAnnotationHandler; -import org.gradle.api.internal.tasks.properties.annotations.PropertyAnnotationHandler; import org.gradle.api.tasks.Classpath; import org.gradle.api.tasks.CompileClasspath; import org.gradle.api.tasks.Console; @@ -52,8 +49,6 @@ import org.gradle.api.tasks.Internal; import org.gradle.api.tasks.Nested; import org.gradle.cache.internal.ProducerGuard; -import org.gradle.internal.instantiation.DefaultInjectAnnotationHandler; -import org.gradle.internal.instantiation.InjectAnnotationHandler; import org.gradle.internal.instantiation.InstantiationScheme; import org.gradle.internal.instantiation.InstantiatorFactory; import org.gradle.internal.nativeplatform.filesystem.FileSystem; @@ -121,14 +116,6 @@ InputArtifactDependenciesAnnotationHandler createInputArtifactDependenciesAnnota return new InputArtifactDependenciesAnnotationHandler(); } - InjectAnnotationHandler createTransformParametersAnnotationHandler() { - return new DefaultInjectAnnotationHandler(InjectTransformParameters.class); - } - - PropertyAnnotationHandler createTransformParametersPropertyAnnotationHandler() { - return new NoOpPropertyAnnotationHandler(InjectTransformParameters.class); - } - ArtifactTransformParameterScheme createArtifactTransformParameterScheme(InspectionSchemeFactory inspectionSchemeFactory, InstantiatorFactory instantiatorFactory) { // TODO - should decorate InstantiationScheme instantiationScheme = instantiatorFactory.injectScheme(); @@ -137,9 +124,9 @@ ArtifactTransformParameterScheme createArtifactTransformParameterScheme(Inspecti } ArtifactTransformActionScheme createArtifactTransformActionScheme(InspectionSchemeFactory inspectionSchemeFactory, InstantiatorFactory instantiatorFactory) { - InstantiationScheme instantiationScheme = instantiatorFactory.injectScheme(ImmutableSet.of(InputArtifact.class, InputArtifactDependencies.class, InjectTransformParameters.class)); + InstantiationScheme instantiationScheme = instantiatorFactory.injectScheme(ImmutableSet.of(InputArtifact.class, InputArtifactDependencies.class)); InstantiationScheme legacyInstantiationScheme = instantiatorFactory.injectScheme(); - InspectionScheme inspectionScheme = inspectionSchemeFactory.inspectionScheme(ImmutableSet.of(InputArtifact.class, InputArtifactDependencies.class, InjectTransformParameters.class, Inject.class, Classpath.class, CompileClasspath.class)); + InspectionScheme inspectionScheme = inspectionSchemeFactory.inspectionScheme(ImmutableSet.of(InputArtifact.class, InputArtifactDependencies.class, Inject.class, Classpath.class, CompileClasspath.class)); return new ArtifactTransformActionScheme(instantiationScheme, inspectionScheme, legacyInstantiationScheme); } } diff --git a/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/DefaultVariantTransformRegistryTest.groovy b/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/DefaultVariantTransformRegistryTest.groovy index 5ae9669dcb901..9fa64c8663b3b 100644 --- a/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/DefaultVariantTransformRegistryTest.groovy +++ b/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/DefaultVariantTransformRegistryTest.groovy @@ -18,7 +18,6 @@ package org.gradle.api.internal.artifacts.transform import com.google.common.collect.ImmutableSet import org.gradle.api.artifacts.transform.ArtifactTransform -import org.gradle.api.artifacts.transform.InjectTransformParameters import org.gradle.api.artifacts.transform.InputArtifact import org.gradle.api.artifacts.transform.InputArtifactDependencies import org.gradle.api.artifacts.transform.TransformAction @@ -64,7 +63,7 @@ class DefaultVariantTransformRegistryTest extends Specification { def classLoaderHierarchyHasher = Mock(ClassLoaderHierarchyHasher) def attributesFactory = AttributeTestUtil.attributesFactory() def domainObjectContextProjectStateHandler = Mock(DomainObjectProjectStateHandler) - def registryFactory = new DefaultTransformationRegistrationFactory(isolatableFactory, classLoaderHierarchyHasher, transformerInvoker, valueSnapshotter, fileCollectionFactory, fileCollectionFingerprinterRegistry, domainObjectContextProjectStateHandler, new ArtifactTransformParameterScheme(instantiatorFactory.injectScheme(), inspectionScheme), new ArtifactTransformActionScheme(instantiatorFactory.injectScheme(ImmutableSet.of(InputArtifact.class, InputArtifactDependencies.class, InjectTransformParameters.class)), inspectionScheme, instantiatorFactory.injectScheme())) + def registryFactory = new DefaultTransformationRegistrationFactory(isolatableFactory, classLoaderHierarchyHasher, transformerInvoker, valueSnapshotter, fileCollectionFactory, fileCollectionFingerprinterRegistry, domainObjectContextProjectStateHandler, new ArtifactTransformParameterScheme(instantiatorFactory.injectScheme(), inspectionScheme), new ArtifactTransformActionScheme(instantiatorFactory.injectScheme(ImmutableSet.of(InputArtifact.class, InputArtifactDependencies.class)), inspectionScheme, instantiatorFactory.injectScheme())) def registry = new DefaultVariantTransformRegistry(instantiatorFactory, attributesFactory, Stub(ServiceRegistry), registryFactory, instantiatorFactory.injectScheme()) def "setup"() { diff --git a/subprojects/plugin-development/src/integTest/groovy/org/gradle/plugin/devel/tasks/ValidateTaskPropertiesIntegrationTest.groovy b/subprojects/plugin-development/src/integTest/groovy/org/gradle/plugin/devel/tasks/ValidateTaskPropertiesIntegrationTest.groovy index c78c56878ebb5..5852c0c2575fc 100644 --- a/subprojects/plugin-development/src/integTest/groovy/org/gradle/plugin/devel/tasks/ValidateTaskPropertiesIntegrationTest.groovy +++ b/subprojects/plugin-development/src/integTest/groovy/org/gradle/plugin/devel/tasks/ValidateTaskPropertiesIntegrationTest.groovy @@ -16,7 +16,6 @@ package org.gradle.plugin.devel.tasks -import org.gradle.api.artifacts.transform.InjectTransformParameters import org.gradle.api.artifacts.transform.InputArtifact import org.gradle.api.artifacts.transform.InputArtifactDependencies import org.gradle.api.file.FileCollection @@ -227,7 +226,6 @@ class ValidateTaskPropertiesIntegrationTest extends AbstractIntegrationSpec { annotation | _ InputArtifact | _ InputArtifactDependencies | _ - InjectTransformParameters | _ } def "detects missing annotation on Groovy properties"() { From 07f65a478d6a5fc04e484fa60c18d276fdebe290 Mon Sep 17 00:00:00 2001 From: "Rodrigo B. de Oliveira" Date: Tue, 26 Feb 2019 12:30:15 -0300 Subject: [PATCH 162/853] Move `PrecompiledScriptPluginModelIntegrationTest` to `kotlinDslIntegTests` So it can be executed against the latest version of `kotlinDslPlugins`. --- ...ompiledScriptPluginModelIntegrationTest.kt | 65 +++++++++++++++---- .../fixtures/AbstractKotlinIntegrationTest.kt | 58 ++++++++++++++++- .../KotlinBuildScriptModelIntegrationTest.kt | 10 +-- .../integration/ScriptModelIntegrationTest.kt | 57 ++-------------- 4 files changed, 118 insertions(+), 72 deletions(-) rename subprojects/{kotlin-dsl => kotlin-dsl-integ-tests}/src/integTest/kotlin/org/gradle/kotlin/dsl/integration/PrecompiledScriptPluginModelIntegrationTest.kt (58%) diff --git a/subprojects/kotlin-dsl/src/integTest/kotlin/org/gradle/kotlin/dsl/integration/PrecompiledScriptPluginModelIntegrationTest.kt b/subprojects/kotlin-dsl-integ-tests/src/integTest/kotlin/org/gradle/kotlin/dsl/integration/PrecompiledScriptPluginModelIntegrationTest.kt similarity index 58% rename from subprojects/kotlin-dsl/src/integTest/kotlin/org/gradle/kotlin/dsl/integration/PrecompiledScriptPluginModelIntegrationTest.kt rename to subprojects/kotlin-dsl-integ-tests/src/integTest/kotlin/org/gradle/kotlin/dsl/integration/PrecompiledScriptPluginModelIntegrationTest.kt index 0f95dac599fe5..ac934e430ee51 100644 --- a/subprojects/kotlin-dsl/src/integTest/kotlin/org/gradle/kotlin/dsl/integration/PrecompiledScriptPluginModelIntegrationTest.kt +++ b/subprojects/kotlin-dsl-integ-tests/src/integTest/kotlin/org/gradle/kotlin/dsl/integration/PrecompiledScriptPluginModelIntegrationTest.kt @@ -1,24 +1,43 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package org.gradle.kotlin.dsl.integration import org.gradle.kotlin.dsl.fixtures.FoldersDsl +import org.hamcrest.MatcherAssert.assertThat +import org.hamcrest.Matchers.hasItem +import org.hamcrest.Matchers.startsWith + +import org.junit.Ignore import org.junit.Test import java.io.File -class PrecompiledScriptPluginModelIntegrationTest : ScriptModelIntegrationTest() { +class PrecompiledScriptPluginModelIntegrationTest : AbstractPluginIntegrationTest() { @Test fun `given a single project build, the classpath of a precompiled script plugin is the compile classpath of its enclosing source-set`() { val implementationDependency = - withJar("implementation.jar") + withDeepThoughtJar("implementation.jar") val classpathDependency = - withJar("classpath.jar") - - withDefaultSettings() + withDeepThoughtJar("classpath.jar") withBuildScript(""" plugins { @@ -42,7 +61,8 @@ class PrecompiledScriptPluginModelIntegrationTest : ScriptModelIntegrationTest() assertClassPathFor( precompiledScriptPlugin, includes = setOf(implementationDependency), - excludes = setOf(classpathDependency)) + excludes = setOf(classpathDependency) + ) } @Test @@ -54,12 +74,12 @@ class PrecompiledScriptPluginModelIntegrationTest : ScriptModelIntegrationTest() val dependencyB = withFile("b.jar") - withFolders { + withDefaultSettings().appendText(""" + include("project-a") + include("project-b") + """) - withFile("settings.gradle.kts", """ - include("project-a") - include("project-b") - """) + withFolders { "project-a" { "src/main/kotlin" { @@ -79,12 +99,31 @@ class PrecompiledScriptPluginModelIntegrationTest : ScriptModelIntegrationTest() assertClassPathFor( existing("project-a/src/main/kotlin/my-plugin-a.gradle.kts"), includes = setOf(dependencyA), - excludes = setOf(dependencyB)) + excludes = setOf(dependencyB) + ) assertClassPathFor( existing("project-b/src/main/kotlin/my-plugin-b.gradle.kts"), includes = setOf(dependencyB), - excludes = setOf(dependencyA)) + excludes = setOf(dependencyA) + ) + } + + @Ignore("wip") + @Test + fun `implicit imports include type-safe accessors packages`() { + + withDefaultSettings() + withKotlinDslPlugin() + + val pluginFile = withPrecompiledKotlinScript("plugin.gradle.kts", """ + plugins { java } + """) + + assertThat( + kotlinBuildScriptModelFor(pluginFile).implicitImports, + hasItem(startsWith("gradle.kotlin.dsl.accessors._")) + ) } private diff --git a/subprojects/kotlin-dsl-test-fixtures/src/main/kotlin/org/gradle/kotlin/dsl/fixtures/AbstractKotlinIntegrationTest.kt b/subprojects/kotlin-dsl-test-fixtures/src/main/kotlin/org/gradle/kotlin/dsl/fixtures/AbstractKotlinIntegrationTest.kt index a26a0adb43fe2..8660281dc8c24 100644 --- a/subprojects/kotlin-dsl-test-fixtures/src/main/kotlin/org/gradle/kotlin/dsl/fixtures/AbstractKotlinIntegrationTest.kt +++ b/subprojects/kotlin-dsl-test-fixtures/src/main/kotlin/org/gradle/kotlin/dsl/fixtures/AbstractKotlinIntegrationTest.kt @@ -23,12 +23,21 @@ import org.gradle.integtests.fixtures.executer.ExecutionFailure import org.gradle.integtests.fixtures.executer.ExecutionResult import org.gradle.integtests.fixtures.executer.GradleContextualExecuter +import org.gradle.kotlin.dsl.concurrent.future + +import org.gradle.kotlin.dsl.resolver.GradleInstallation +import org.gradle.kotlin.dsl.resolver.KotlinBuildScriptModelRequest +import org.gradle.kotlin.dsl.resolver.fetchKotlinBuildScriptModelFor + import org.gradle.kotlin.dsl.support.zipTo +import org.gradle.kotlin.dsl.tooling.models.KotlinBuildScriptModel import org.hamcrest.CoreMatchers.allOf import org.hamcrest.CoreMatchers.containsString import org.hamcrest.CoreMatchers.not import org.hamcrest.Matcher +import org.hamcrest.Matchers.hasItems + import org.junit.Assert.assertThat import org.junit.Assume.assumeFalse import org.junit.Assume.assumeTrue @@ -129,7 +138,6 @@ abstract class AbstractKotlinIntegrationTest : AbstractIntegrationTest() { """) } - protected fun givenPrecompiledKotlinScript(fileName: String, code: String) { withKotlinDslPlugin() @@ -159,11 +167,59 @@ abstract class AbstractKotlinIntegrationTest : AbstractIntegrationTest() { $repositoriesBlock """ + protected + fun assertClassPathFor( + buildScript: File, + includes: Set, + excludes: Set, + importedProjectDir: File = projectRoot + ) { + val includeItems = hasItems(*includes.map { it.name }.toTypedArray()) + val excludeItems = not(hasItems(*excludes.map { it.name }.toTypedArray())) + val condition = if (excludes.isEmpty()) includeItems else allOf(includeItems, excludeItems) + assertThat( + classPathFor(buildScript, importedProjectDir).map { it.name }, + condition + ) + } + + protected + fun classPathFor(scriptFile: File, projectDir: File = projectRoot) = + kotlinBuildScriptModelFor(scriptFile, projectDir).classPath + + protected + fun kotlinBuildScriptModelFor( + scriptFile: File, + importedProjectDir: File = projectRoot + ): KotlinBuildScriptModel = future { + + fetchKotlinBuildScriptModelFor( + KotlinBuildScriptModelRequest( + projectDir = importedProjectDir, + scriptFile = scriptFile, + gradleInstallation = testGradleInstallation(), + gradleUserHome = buildContext.gradleUserHomeDir + ) + ) { + + setStandardOutput(System.out) + setStandardError(System.err) + } + }.get() + + private + fun testGradleInstallation() = + GradleInstallation.Local(distribution.gradleHomeDir) + protected fun compileKotlin(taskName: String = "classes") { build(taskName).assertTaskExecuted(":compileKotlin") } + protected + fun withDeepThoughtJar(named: String): File = + withClassJar(named, DeepThought::class.java) + protected fun withClassJar(fileName: String, vararg classes: Class<*>) = withZip(fileName, classEntriesFor(*classes)) diff --git a/subprojects/kotlin-dsl/src/integTest/kotlin/org/gradle/kotlin/dsl/integration/KotlinBuildScriptModelIntegrationTest.kt b/subprojects/kotlin-dsl/src/integTest/kotlin/org/gradle/kotlin/dsl/integration/KotlinBuildScriptModelIntegrationTest.kt index 6af52da3726e1..8e995cf4c2e91 100644 --- a/subprojects/kotlin-dsl/src/integTest/kotlin/org/gradle/kotlin/dsl/integration/KotlinBuildScriptModelIntegrationTest.kt +++ b/subprojects/kotlin-dsl/src/integTest/kotlin/org/gradle/kotlin/dsl/integration/KotlinBuildScriptModelIntegrationTest.kt @@ -191,8 +191,8 @@ class KotlinBuildScriptModelIntegrationTest : ScriptModelIntegrationTest() { @Test fun `can fetch buildscript classpath for sub-project script outside root project dir`() { - val rootDependency = withJar("libs/root.jar") - val subDependency = withJar("libs/sub.jar") + val rootDependency = withDeepThoughtJar("libs/root.jar") + val subDependency = withDeepThoughtJar("libs/sub.jar") withFolders { @@ -247,9 +247,9 @@ class KotlinBuildScriptModelIntegrationTest : ScriptModelIntegrationTest() { fun assertCanFetchClassPathForSubProjectScriptOfNestedProjectOutsideProjectRoot(nestedProjectName: String) { withDefaultSettings() - val rootDependency = withJar("libs/root-dep.jar") - val nestedRootDependency = withJar("libs/$nestedProjectName-root-dep.jar") - val nestedSubDependency = withJar("libs/$nestedProjectName-sub-dep.jar") + val rootDependency = withDeepThoughtJar("libs/root-dep.jar") + val nestedRootDependency = withDeepThoughtJar("libs/$nestedProjectName-root-dep.jar") + val nestedSubDependency = withDeepThoughtJar("libs/$nestedProjectName-sub-dep.jar") withFolders { nestedProjectName { diff --git a/subprojects/kotlin-dsl/src/integTest/kotlin/org/gradle/kotlin/dsl/integration/ScriptModelIntegrationTest.kt b/subprojects/kotlin-dsl/src/integTest/kotlin/org/gradle/kotlin/dsl/integration/ScriptModelIntegrationTest.kt index 5d18a6ba158b2..3b19d72bbdd61 100644 --- a/subprojects/kotlin-dsl/src/integTest/kotlin/org/gradle/kotlin/dsl/integration/ScriptModelIntegrationTest.kt +++ b/subprojects/kotlin-dsl/src/integTest/kotlin/org/gradle/kotlin/dsl/integration/ScriptModelIntegrationTest.kt @@ -1,18 +1,14 @@ package org.gradle.kotlin.dsl.integration -import org.gradle.kotlin.dsl.concurrent.future - import org.gradle.kotlin.dsl.fixtures.AbstractKotlinIntegrationTest -import org.gradle.kotlin.dsl.fixtures.DeepThought import org.gradle.kotlin.dsl.fixtures.matching -import org.gradle.kotlin.dsl.resolver.GradleInstallation -import org.gradle.kotlin.dsl.resolver.KotlinBuildScriptModelRequest -import org.gradle.kotlin.dsl.resolver.fetchKotlinBuildScriptModelFor - import org.gradle.kotlin.dsl.tooling.models.KotlinBuildScriptModel -import org.hamcrest.CoreMatchers.* +import org.hamcrest.CoreMatchers.allOf +import org.hamcrest.CoreMatchers.hasItem +import org.hamcrest.CoreMatchers.hasItems +import org.hamcrest.CoreMatchers.not import org.hamcrest.Matcher import org.hamcrest.MatcherAssert.assertThat @@ -112,22 +108,6 @@ abstract class ScriptModelIntegrationTest : AbstractKotlinIntegrationTest() { matching("gradle-kotlin-dsl-extensions-$version\\.jar"))) } - protected - fun assertClassPathFor( - buildScript: File, - includes: Set, - excludes: Set, - importedProjectDir: File = projectRoot - ) { - val includeItems = hasItems(*includes.map { it.name }.toTypedArray()) - val excludeItems = not(hasItems(*excludes.map { it.name }.toTypedArray())) - val condition = if (excludes.isEmpty()) includeItems else allOf(includeItems, excludeItems) - assertThat( - classPathFor(buildScript, importedProjectDir).map { it.name }, - condition - ) - } - protected fun assertClassPathContains(classPath: List, vararg files: File) = assertThat( @@ -162,40 +142,11 @@ abstract class ScriptModelIntegrationTest : AbstractKotlinIntegrationTest() { assert(it.size == files.size) } - protected - fun withJar(named: String): File = - withClassJar(named, DeepThought::class.java) - internal fun canonicalClassPathFor(scriptFile: File, projectDir: File = projectRoot) = kotlinBuildScriptModelFor(scriptFile, projectDir).canonicalClassPath - protected - fun classPathFor(scriptFile: File, projectDir: File = projectRoot) = - kotlinBuildScriptModelFor(scriptFile, projectDir).classPath - internal val KotlinBuildScriptModel.canonicalClassPath get() = classPath.map(File::getCanonicalFile) - - internal - fun kotlinBuildScriptModelFor(scriptFile: File, importedProjectDir: File = projectRoot): KotlinBuildScriptModel = - future { - fetchKotlinBuildScriptModelFor( - KotlinBuildScriptModelRequest( - projectDir = importedProjectDir, - scriptFile = scriptFile, - gradleInstallation = testGradleInstallation(), - gradleUserHome = buildContext.gradleUserHomeDir - ) - ) { - - setStandardOutput(System.out) - setStandardError(System.err) - } - }.get() - - private - fun testGradleInstallation() = - GradleInstallation.Local(distribution.gradleHomeDir) } From 151dcf7eb0a22739de716043f9fd750a8395f0f7 Mon Sep 17 00:00:00 2001 From: Stefan Wolf Date: Tue, 26 Feb 2019 15:09:16 +0100 Subject: [PATCH 163/853] Use TransformParameters.None for parameterless transforms --- .../artifacts/transform/TransformAction.java | 2 +- .../transform/TransformParameters.java | 1 + ...ansformInputArtifactIntegrationTest.groovy | 28 +++++++++---------- .../ArtifactTransformIntegrationTest.groovy | 12 ++++---- .../ArtifactTransformTestFixture.groovy | 2 ++ ...sformValuesInjectionIntegrationTest.groovy | 6 ++-- ...formWithDependenciesIntegrationTest.groovy | 6 ++-- ...nsformWithFileInputsIntegrationTest.groovy | 2 +- .../transform/DefaultTransformer.java | 8 ++++-- .../DefaultVariantTransformRegistry.java | 5 +++- .../artifacts/transform/UnzipTransform.java | 2 +- ...DefaultVariantTransformRegistryTest.groovy | 21 +++++++++++++- 12 files changed, 63 insertions(+), 32 deletions(-) diff --git a/subprojects/core-api/src/main/java/org/gradle/api/artifacts/transform/TransformAction.java b/subprojects/core-api/src/main/java/org/gradle/api/artifacts/transform/TransformAction.java index 96ae08786cead..ac6d820260330 100644 --- a/subprojects/core-api/src/main/java/org/gradle/api/artifacts/transform/TransformAction.java +++ b/subprojects/core-api/src/main/java/org/gradle/api/artifacts/transform/TransformAction.java @@ -31,7 +31,7 @@ * *

    A property annotated with {@link InputArtifactDependencies} will receive the dependencies of its input artifact. * - * @param Parameter type for the transform action. Should be {@link TransformParameters} if the action does not have parameters. + * @param Parameter type for the transform action. Should be {@link TransformParameters.None} if the action does not have parameters. * @since 5.3 */ @Incubating diff --git a/subprojects/core-api/src/main/java/org/gradle/api/artifacts/transform/TransformParameters.java b/subprojects/core-api/src/main/java/org/gradle/api/artifacts/transform/TransformParameters.java index 9887f73ed5dbc..1ba8383da5c48 100644 --- a/subprojects/core-api/src/main/java/org/gradle/api/artifacts/transform/TransformParameters.java +++ b/subprojects/core-api/src/main/java/org/gradle/api/artifacts/transform/TransformParameters.java @@ -25,4 +25,5 @@ */ @Incubating public interface TransformParameters { + interface None extends TransformParameters {} } diff --git a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformInputArtifactIntegrationTest.groovy b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformInputArtifactIntegrationTest.groovy index fa0f050828803..bd117dd6093dd 100644 --- a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformInputArtifactIntegrationTest.groovy +++ b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformInputArtifactIntegrationTest.groovy @@ -38,7 +38,7 @@ class ArtifactTransformInputArtifactIntegrationTest extends AbstractDependencyRe tasks.producer.doLast { throw new RuntimeException('broken') } } - abstract class MakeGreen implements TransformAction { + abstract class MakeGreen implements TransformAction { @InputArtifact abstract File getInput() @@ -74,7 +74,7 @@ class ArtifactTransformInputArtifactIntegrationTest extends AbstractDependencyRe } } - abstract class MakeGreen implements TransformAction { + abstract class MakeGreen implements TransformAction { @InputArtifact ${annotation} abstract File getInput() @@ -187,7 +187,7 @@ class ArtifactTransformInputArtifactIntegrationTest extends AbstractDependencyRe } } - abstract class MakeGreen implements TransformAction { + abstract class MakeGreen implements TransformAction { @InputArtifact ${annotation} abstract File getInput() @@ -317,7 +317,7 @@ class ArtifactTransformInputArtifactIntegrationTest extends AbstractDependencyRe } } - abstract class MakeGreen implements TransformAction { + abstract class MakeGreen implements TransformAction { @InputArtifact abstract File getInput() @@ -378,7 +378,7 @@ class ArtifactTransformInputArtifactIntegrationTest extends AbstractDependencyRe } @CacheableTransform - abstract class MakeGreen implements TransformAction { + abstract class MakeGreen implements TransformAction { @PathSensitive(PathSensitivity.NONE) @InputArtifact abstract File getInput() @@ -459,7 +459,7 @@ class ArtifactTransformInputArtifactIntegrationTest extends AbstractDependencyRe } @CacheableTransform - abstract class MakeGreen implements TransformAction { + abstract class MakeGreen implements TransformAction { @PathSensitive(PathSensitivity.${sensitivity}) @InputArtifact abstract File getInput() @@ -550,7 +550,7 @@ class ArtifactTransformInputArtifactIntegrationTest extends AbstractDependencyRe } @CacheableTransform - abstract class MakeGreen implements TransformAction { + abstract class MakeGreen implements TransformAction { @PathSensitive(PathSensitivity.${sensitivity}) @InputArtifact abstract File getInput() @@ -632,7 +632,7 @@ class ArtifactTransformInputArtifactIntegrationTest extends AbstractDependencyRe } } - abstract class MakeGreen implements TransformAction { + abstract class MakeGreen implements TransformAction { @PathSensitive(PathSensitivity.NONE) @InputArtifact abstract File getInput() @@ -721,7 +721,7 @@ class ArtifactTransformInputArtifactIntegrationTest extends AbstractDependencyRe } @CacheableTransform - abstract class MakeGreen implements TransformAction { + abstract class MakeGreen implements TransformAction { @PathSensitive(PathSensitivity.NONE) @InputArtifact abstract File getInput() @@ -823,7 +823,7 @@ class ArtifactTransformInputArtifactIntegrationTest extends AbstractDependencyRe implementation 'group2:lib2:1.0' } - abstract class MakeGreen implements TransformAction { + abstract class MakeGreen implements TransformAction { @PathSensitive(PathSensitivity.NONE) @InputArtifact abstract File getInput() @@ -909,7 +909,7 @@ class ArtifactTransformInputArtifactIntegrationTest extends AbstractDependencyRe implementation 'group2:lib2:1.0' } - abstract class MakeGreen implements TransformAction { + abstract class MakeGreen implements TransformAction { @PathSensitive(PathSensitivity.${sensitivity}) @InputArtifact abstract File getInput() @@ -976,7 +976,7 @@ class ArtifactTransformInputArtifactIntegrationTest extends AbstractDependencyRe } } - abstract class MakeGreen implements TransformAction { + abstract class MakeGreen implements TransformAction { @InputArtifact @${annotation} abstract File getInput() @@ -1076,7 +1076,7 @@ class ArtifactTransformInputArtifactIntegrationTest extends AbstractDependencyRe } @CacheableTransform - abstract class MakeGreen implements TransformAction { + abstract class MakeGreen implements TransformAction { @InputArtifact @${annotation} abstract File getInput() @@ -1180,7 +1180,7 @@ class ArtifactTransformInputArtifactIntegrationTest extends AbstractDependencyRe } } - abstract class MakeGreen implements TransformAction { + abstract class MakeGreen implements TransformAction { @InputArtifact @Classpath abstract File getInput() diff --git a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformIntegrationTest.groovy b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformIntegrationTest.groovy index 488bf1add791c..9583eb48d055f 100644 --- a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformIntegrationTest.groovy +++ b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformIntegrationTest.groovy @@ -35,6 +35,8 @@ class ArtifactTransformIntegrationTest extends AbstractHttpDependencyResolutionT """ buildFile << """ +import org.gradle.api.artifacts.transform.TransformParameters + def usage = Attribute.of('usage', String) def artifactType = Attribute.of('artifactType', String) def extraAttribute = Attribute.of('extra', String) @@ -803,7 +805,7 @@ $fileSizer } } - abstract class IdentityTransform implements TransformAction { + abstract class IdentityTransform implements TransformAction { @InputArtifact abstract File getInput() @@ -1553,7 +1555,7 @@ Found the following transforms: compile files(a) } - abstract class FailingTransform implements TransformAction { + abstract class FailingTransform implements TransformAction { void transform(TransformOutputs outputs) { ${switch (type) { case FileType.Missing: @@ -1623,7 +1625,7 @@ Found the following transforms: compile files(a) } - abstract class DirectoryTransform implements TransformAction { + abstract class DirectoryTransform implements TransformAction { void transform(TransformOutputs outputs) { def outputFile = outputs.file("some/dir/output.txt") assert outputFile.parentFile.directory @@ -1661,7 +1663,7 @@ Found the following transforms: compile files(a) } - abstract class MyTransform implements TransformAction { + abstract class MyTransform implements TransformAction { @InputArtifact abstract File getInput() @@ -1739,7 +1741,7 @@ Found the following transforms: SomewhereElseTransform.output = file("other.jar") - abstract class SomewhereElseTransform implements TransformAction { + abstract class SomewhereElseTransform implements TransformAction { static def output void transform(TransformOutputs outputs) { def outputFile = outputs.file(output) diff --git a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformTestFixture.groovy b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformTestFixture.groovy index 5950ab8de3cd4..e3bad2eaa057b 100644 --- a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformTestFixture.groovy +++ b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformTestFixture.groovy @@ -51,6 +51,8 @@ trait ArtifactTransformTestFixture { buildFile << """ import ${javax.inject.Inject.name} +// TODO: Default imports should work for of inner classes +import ${org.gradle.api.artifacts.transform.TransformParameters.name} def color = Attribute.of('color', String) allprojects { diff --git a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformValuesInjectionIntegrationTest.groovy b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformValuesInjectionIntegrationTest.groovy index 8afc8cc3339ef..065c0d2038be1 100644 --- a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformValuesInjectionIntegrationTest.groovy +++ b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformValuesInjectionIntegrationTest.groovy @@ -408,7 +408,7 @@ project(':b') { } } -abstract class MakeGreen implements TransformAction { +abstract class MakeGreen implements TransformAction { @InputArtifactDependencies abstract ${targetType} getDependencies() @InputArtifact @@ -537,7 +537,7 @@ project(':a') { } } -abstract class MakeGreen implements TransformAction { +abstract class MakeGreen implements TransformAction { @InputArtifact abstract FileCollection getDependencies() @@ -571,7 +571,7 @@ project(':a') { } } -abstract class MakeGreen implements TransformAction { +abstract class MakeGreen implements TransformAction { @Inject abstract File getWorkspace() diff --git a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformWithDependenciesIntegrationTest.groovy b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformWithDependenciesIntegrationTest.groovy index d8b9d60721ac3..05bc8e3daa0d0 100644 --- a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformWithDependenciesIntegrationTest.groovy +++ b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformWithDependenciesIntegrationTest.groovy @@ -127,7 +127,7 @@ abstract class TestTransform implements TransformAction } } -abstract class SimpleTransform implements TransformAction { +abstract class SimpleTransform implements TransformAction { @InputArtifact abstract File getInput() @@ -416,7 +416,7 @@ allprojects { } } -abstract class NoneTransform implements TransformAction { +abstract class NoneTransform implements TransformAction { @InputArtifactDependencies @PathSensitive(PathSensitivity.NONE) abstract FileCollection getInputArtifactDependencies() @@ -512,7 +512,7 @@ allprojects { } } -abstract class ClasspathTransform implements TransformAction { +abstract class ClasspathTransform implements TransformAction { @InputArtifactDependencies @${classpathAnnotation.simpleName} abstract FileCollection getInputArtifactDependencies() diff --git a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformWithFileInputsIntegrationTest.groovy b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformWithFileInputsIntegrationTest.groovy index de80ad6e36617..686bda313ed75 100644 --- a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformWithFileInputsIntegrationTest.groovy +++ b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformWithFileInputsIntegrationTest.groovy @@ -151,7 +151,7 @@ class ArtifactTransformWithFileInputsIntegrationTest extends AbstractDependencyR """ setupBuildWithTransformFileInputs() buildFile << """ - abstract class MakeRed implements TransformAction { + abstract class MakeRed implements TransformAction { @InputArtifact abstract File getInput() diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformer.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformer.java index 0e9b8b4732512..a0993ef4ef62c 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformer.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformer.java @@ -279,6 +279,8 @@ private IsolatedParameters getIsolatedParameters() { } private static class TransformServiceLookup implements ServiceLookup { + private static final TransformParameters.None NO_PARAMETERS = new TransformParameters.None() {}; + private final ImmutableList injectionPoints; public TransformServiceLookup(File inputFile, @Nullable TransformParameters parameters, @Nullable ArtifactTransformDependencies artifactTransformDependencies) { @@ -287,7 +289,7 @@ public TransformServiceLookup(File inputFile, @Nullable TransformParameters para if (parameters != null) { builder.add(new InjectionPoint(null, parameters.getClass(), parameters)); } else { - builder.add(new InjectionPoint(null, TransformParameters.class, new TransformParameters() {})); + builder.add(new InjectionPoint(null, TransformParameters.None.class, NO_PARAMETERS)); } if (artifactTransformDependencies != null) { builder.add(new InjectionPoint(InputArtifactDependencies.class, artifactTransformDependencies.getFiles())); @@ -300,7 +302,9 @@ private Object find(Type serviceType, @Nullable Class anno TypeToken serviceTypeToken = TypeToken.of(serviceType); for (InjectionPoint injectionPoint : injectionPoints) { if (annotatedWith == injectionPoint.getAnnotation() && serviceTypeToken.isSupertypeOf(injectionPoint.getInjectedType())) { - return injectionPoint.getValueToInject(); + Object valueToInject = injectionPoint.getValueToInject(); + + return valueToInject; } } return null; diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultVariantTransformRegistry.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultVariantTransformRegistry.java index 964a657ae29c1..b4f595d98b971 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultVariantTransformRegistry.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultVariantTransformRegistry.java @@ -82,7 +82,10 @@ public void registerTransform(Action registrationActio public void registerTransform(Class> actionType, Action> registrationAction) { ParameterizedType superType = (ParameterizedType) TypeToken.of(actionType).getSupertype(TransformAction.class).getType(); Class parameterType = Cast.uncheckedNonnullCast(TypeToken.of(superType.getActualTypeArguments()[0]).getRawType()); - T parameterObject = parameterType == TransformParameters.class ? null : parametersInstantiationScheme.withServices(services).newInstance(parameterType); + if (parameterType == TransformParameters.class) { + throw new VariantTransformConfigurationException(String.format("Could not register transform: must use a sub-type of %s as parameter type. Use %s for transforms without parameters.", ModelType.of(TransformParameters.class).getDisplayName(), ModelType.of(TransformParameters.None.class).getDisplayName())); + } + T parameterObject = parameterType == TransformParameters.None.class ? null : parametersInstantiationScheme.withServices(services).newInstance(parameterType); TypedRegistration registration = Cast.uncheckedNonnullCast(instantiatorFactory.decorateLenient().newInstance(TypedRegistration.class, parameterObject, immutableAttributesFactory)); registrationAction.execute(registration); diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/UnzipTransform.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/UnzipTransform.java index be795426a87f0..4272b6a0c1e18 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/UnzipTransform.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/UnzipTransform.java @@ -39,7 +39,7 @@ * is located in the output directory of the transform and is named after the zipped file name * minus the extension. */ -public interface UnzipTransform extends TransformAction { +public interface UnzipTransform extends TransformAction { @InputArtifact File getZippedFile(); diff --git a/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/DefaultVariantTransformRegistryTest.groovy b/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/DefaultVariantTransformRegistryTest.groovy index 9fa64c8663b3b..0ded6694c2c5c 100644 --- a/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/DefaultVariantTransformRegistryTest.groovy +++ b/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/DefaultVariantTransformRegistryTest.groovy @@ -159,6 +159,19 @@ class DefaultVariantTransformRegistryTest extends Specification { registration.transformationStep.transformer.parameterObject == null } + def "cannot use TransformParameters as parameter type"() { + when: + registry.registerTransform(UnspecifiedTestTransform) { + it.from.attribute(TEST_ATTRIBUTE, "FROM") + it.to.attribute(TEST_ATTRIBUTE, "TO") + } + + then: + def e = thrown(VariantTransformConfigurationException) + e.message == 'Could not register transform: must use a sub-type of TransformParameters as parameter type. Use TransformParameters.None for transforms without parameters.' + e.cause == null + } + def "cannot configure parameters for parameterless action"() { when: registry.registerTransform(ParameterlessTestTransform) { @@ -346,7 +359,13 @@ class DefaultVariantTransformRegistryTest extends Specification { } } - static abstract class ParameterlessTestTransform implements TransformAction { + static abstract class ParameterlessTestTransform implements TransformAction { + @Override + void transform(TransformOutputs outputs) { + } + } + + static abstract class UnspecifiedTestTransform implements TransformAction { @Override void transform(TransformOutputs outputs) { } From 31662e688e70a6215f19a11322897c1a02a50884 Mon Sep 17 00:00:00 2001 From: Stefan Wolf Date: Tue, 26 Feb 2019 15:10:41 +0100 Subject: [PATCH 164/853] Address review feedback --- .../api/artifacts/transform/TransformParameters.java | 2 +- .../org/gradle/api/artifacts/transform/TransformSpec.java | 1 + .../transform/DefaultVariantTransformRegistry.java | 8 ++++---- .../transform/DefaultVariantTransformRegistryTest.groovy | 4 ++-- 4 files changed, 8 insertions(+), 7 deletions(-) diff --git a/subprojects/core-api/src/main/java/org/gradle/api/artifacts/transform/TransformParameters.java b/subprojects/core-api/src/main/java/org/gradle/api/artifacts/transform/TransformParameters.java index 1ba8383da5c48..8f79976c72050 100644 --- a/subprojects/core-api/src/main/java/org/gradle/api/artifacts/transform/TransformParameters.java +++ b/subprojects/core-api/src/main/java/org/gradle/api/artifacts/transform/TransformParameters.java @@ -19,7 +19,7 @@ import org.gradle.api.Incubating; /** - * Marker interface for parameters to {@link TransformAction}. + * Marker interface for parameter objects to {@link TransformAction}s. * * @since 5.3 */ diff --git a/subprojects/core-api/src/main/java/org/gradle/api/artifacts/transform/TransformSpec.java b/subprojects/core-api/src/main/java/org/gradle/api/artifacts/transform/TransformSpec.java index 3512d9d397973..1c5b61f3271e0 100644 --- a/subprojects/core-api/src/main/java/org/gradle/api/artifacts/transform/TransformSpec.java +++ b/subprojects/core-api/src/main/java/org/gradle/api/artifacts/transform/TransformSpec.java @@ -22,6 +22,7 @@ /** * Base configuration for artifact transform registrations. + * * @param The transform specific parameter type. * @since 5.3 */ diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultVariantTransformRegistry.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultVariantTransformRegistry.java index b4f595d98b971..cd631e2c4eaf7 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultVariantTransformRegistry.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultVariantTransformRegistry.java @@ -103,13 +103,13 @@ private void register(RecordingRegistration regi } } - private void validateActionType(@Nullable Class actionType) { + private static void validateActionType(@Nullable Class actionType) { if (actionType == null) { throw new VariantTransformConfigurationException("Could not register transform: an artifact transform action must be provided."); } } - private void validateAttributes(RecordingRegistration registration) { + private static void validateAttributes(RecordingRegistration registration) { if (registration.to.isEmpty()) { throw new VariantTransformConfigurationException("Could not register transform: at least one 'to' attribute must be provided."); } @@ -190,7 +190,7 @@ public TypedRegistration(@Nullable T parameterObject, ImmutableAttributesFactory @Override public T getParameters() { if (parameterObject == null) { - throw new VariantTransformConfigurationException("Cannot query parameters for parameterless artifact transform."); + throw new VariantTransformConfigurationException("Cannot query parameters for artifact transform without parameters."); } return parameterObject; } @@ -198,7 +198,7 @@ public T getParameters() { @Override public void parameters(Action action) { if (parameterObject == null) { - throw new VariantTransformConfigurationException("Cannot configure parameters for parameterless artifact transform."); + throw new VariantTransformConfigurationException("Cannot configure parameters for artifact transform without parameters."); } action.execute(parameterObject); } diff --git a/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/DefaultVariantTransformRegistryTest.groovy b/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/DefaultVariantTransformRegistryTest.groovy index 0ded6694c2c5c..2deb2c05e5dc3 100644 --- a/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/DefaultVariantTransformRegistryTest.groovy +++ b/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/DefaultVariantTransformRegistryTest.groovy @@ -183,7 +183,7 @@ class DefaultVariantTransformRegistryTest extends Specification { then: def e = thrown(VariantTransformConfigurationException) - e.message == 'Cannot configure parameters for parameterless artifact transform.' + e.message == 'Cannot configure parameters for artifact transform without parameters.' e.cause == null } @@ -197,7 +197,7 @@ class DefaultVariantTransformRegistryTest extends Specification { then: def e = thrown(VariantTransformConfigurationException) - e.message == 'Cannot query parameters for parameterless artifact transform.' + e.message == 'Cannot query parameters for artifact transform without parameters.' e.cause == null } From 66e42a9b8fd2c3d829ab4600f680f5dc3a5c7aaf Mon Sep 17 00:00:00 2001 From: Stefan Wolf Date: Tue, 26 Feb 2019 15:41:25 +0100 Subject: [PATCH 165/853] Use inner Parameters class for transform parameters. --- ...factTransformCachingIntegrationTest.groovy | 15 +- .../ArtifactTransformIntegrationTest.groovy | 16 +- ...ctTransformIsolationIntegrationTest.groovy | 12 +- ...sformValuesInjectionIntegrationTest.groovy | 152 +++++++++--------- ...formWithDependenciesIntegrationTest.groovy | 13 +- ...nsformWithFileInputsIntegrationTest.groovy | 30 ++-- ...DefaultVariantTransformRegistryTest.groovy | 12 +- ...ractConsoleBuildPhaseFunctionalTest.groovy | 12 +- 8 files changed, 131 insertions(+), 131 deletions(-) diff --git a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformCachingIntegrationTest.groovy b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformCachingIntegrationTest.groovy index d16df4695ad71..4b8c3cd57d135 100644 --- a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformCachingIntegrationTest.groovy +++ b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformCachingIntegrationTest.groovy @@ -818,7 +818,7 @@ class ArtifactTransformCachingIntegrationTest extends AbstractHttpDependencyReso } @Unroll - def "failure in transformation chain propagates (position in chain: #failingTransform"() { + def "failure in transformation chain propagates (position in chain: #failingTransform)"() { given: Closure possiblyFailingTransform = { index -> @@ -1480,12 +1480,13 @@ ${getFileSizerBody(fileValue, 'new File(outputDirectory, ', 'new File(outputDire String registerFileSizerWithParameterObject(String fileValue) { """ - interface FileSizerParameters extends TransformParameters { - @Input - Number getValue() - void setValue(Number value) - } - abstract class FileSizer implements TransformAction { + abstract class FileSizer implements TransformAction { + interface Parameters extends TransformParameters { + @Input + Number getValue() + void setValue(Number value) + } + @InputArtifact abstract File getInput() diff --git a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformIntegrationTest.groovy b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformIntegrationTest.groovy index 9583eb48d055f..6fc6f209d81ac 100644 --- a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformIntegrationTest.groovy +++ b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformIntegrationTest.groovy @@ -1949,13 +1949,13 @@ Found the following transforms: String toString() { return "" } } - interface CustomParameters extends TransformParameters { - @Input - CustomType getInput() - void setInput(CustomType input) - } - - abstract class Custom implements TransformAction { + abstract class Custom implements TransformAction { + interface Parameters extends TransformParameters { + @Input + CustomType getInput() + void setInput(CustomType input) + } + void transform(TransformOutputs outputs) { } } @@ -1981,7 +1981,7 @@ Found the following transforms: when: fails "resolve" then: - Matcher matchesCannotIsolate = matchesRegexp("Cannot isolate parameters CustomParameters\\\$Inject@.* of artifact transform Custom") + Matcher matchesCannotIsolate = matchesRegexp("Cannot isolate parameters Custom\\\$Parameters\\\$Inject@.* of artifact transform Custom") if (scheduled) { failure.assertThatDescription(matchesCannotIsolate) } else { diff --git a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformIsolationIntegrationTest.groovy b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformIsolationIntegrationTest.groovy index 60c5b9e497efe..6aa97f2042f63 100644 --- a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformIsolationIntegrationTest.groovy +++ b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformIsolationIntegrationTest.groovy @@ -85,13 +85,13 @@ class Resolve extends Copy { given: buildFile << """ - interface CountRecorderParameters extends TransformParameters{ - @Input - Counter getCounter() - void setCounter(Counter counter) - } + abstract class CountRecorder implements TransformAction { + interface Parameters extends TransformParameters{ + @Input + Counter getCounter() + void setCounter(Counter counter) + } - abstract class CountRecorder implements TransformAction { @InputArtifact abstract File getInput() diff --git a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformValuesInjectionIntegrationTest.groovy b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformValuesInjectionIntegrationTest.groovy index 065c0d2038be1..7ebce53f69cf4 100644 --- a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformValuesInjectionIntegrationTest.groovy +++ b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformValuesInjectionIntegrationTest.groovy @@ -63,13 +63,13 @@ class ArtifactTransformValuesInjectionIntegrationTest extends AbstractDependency } } - interface MakeGreenParameters extends TransformParameters { - @Input - String getExtension() - void setExtension(String value) - } - - abstract class MakeGreen implements TransformAction { + abstract class MakeGreen implements TransformAction { + interface Parameters extends TransformParameters { + @Input + String getExtension() + void setExtension(String value) + } + @InputArtifact abstract File getInput() @@ -108,14 +108,14 @@ class ArtifactTransformValuesInjectionIntegrationTest extends AbstractDependency } } - interface MakeGreenParameters extends TransformParameters { - @Input - ${type} getProp() - @Input @Optional - ${type} getOtherProp() - } + abstract class MakeGreen implements TransformAction { + interface Parameters extends TransformParameters { + @Input + ${type} getProp() + @Input @Optional + ${type} getOtherProp() + } - abstract class MakeGreen implements TransformAction { void transform(TransformOutputs outputs) { println "processing using " + parameters.prop.get() assert parameters.otherProp.getOrNull() == ${expectedNullValue} @@ -153,24 +153,24 @@ class ArtifactTransformValuesInjectionIntegrationTest extends AbstractDependency } } - interface MakeGreenParameters extends TransformParameters { - String getExtension() - void setExtension(String value) - @OutputDirectory - File getOutputDir() - void setOutputDir(File outputDir) - @Input - String getMissingInput() - void setMissingInput(String missing) - @InputFiles - ConfigurableFileCollection getNoPathSensitivity() - @PathSensitive(PathSensitivity.ABSOLUTE) - @InputFiles - ConfigurableFileCollection getAbsolutePathSensitivity() - } - @CacheableTransform - abstract class MakeGreen implements TransformAction { + abstract class MakeGreen implements TransformAction { + interface Parameters extends TransformParameters { + String getExtension() + void setExtension(String value) + @OutputDirectory + File getOutputDir() + void setOutputDir(File outputDir) + @Input + String getMissingInput() + void setMissingInput(String missing) + @InputFiles + ConfigurableFileCollection getNoPathSensitivity() + @PathSensitive(PathSensitivity.ABSOLUTE) + @InputFiles + ConfigurableFileCollection getAbsolutePathSensitivity() + } + void transform(TransformOutputs outputs) { throw new RuntimeException() } @@ -181,8 +181,8 @@ class ArtifactTransformValuesInjectionIntegrationTest extends AbstractDependency fails(":a:resolve") then: - failure.assertThatDescription(matchesRegexp('Cannot isolate parameters MakeGreenParameters\\$Inject@.* of artifact transform MakeGreen')) - failure.assertHasCause('Some problems were found with the configuration of the artifact transform parameter MakeGreenParameters.') + failure.assertThatDescription(matchesRegexp('Cannot isolate parameters MakeGreen\\$Parameters\\$Inject@.* of artifact transform MakeGreen')) + failure.assertHasCause('Some problems were found with the configuration of the artifact transform parameter MakeGreen.Parameters.') failure.assertHasCause("Property 'extension' is not annotated with an input annotation.") failure.assertHasCause("Property 'outputDir' is annotated with unsupported annotation @OutputDirectory.") failure.assertHasCause("Property 'missingInput' does not have a value specified.") @@ -208,16 +208,16 @@ class ArtifactTransformValuesInjectionIntegrationTest extends AbstractDependency } } - interface MakeGreenParameters extends TransformParameters { - @Input - String getExtension() - void setExtension(String value) - @${annotation.simpleName} - String getBad() - void setBad(String value) - } + abstract class MakeGreen implements TransformAction { + interface Parameters extends TransformParameters { + @Input + String getExtension() + void setExtension(String value) + @${annotation.simpleName} + String getBad() + void setBad(String value) + } - abstract class MakeGreen implements TransformAction { void transform(TransformOutputs outputs) { throw new RuntimeException() } @@ -228,8 +228,8 @@ class ArtifactTransformValuesInjectionIntegrationTest extends AbstractDependency fails(":a:resolve") then: - failure.assertThatDescription(matchesRegexp('Cannot isolate parameters MakeGreenParameters\\$Inject@.* of artifact transform MakeGreen')) - failure.assertHasCause('A problem was found with the configuration of the artifact transform parameter MakeGreenParameters.') + failure.assertThatDescription(matchesRegexp('Cannot isolate parameters MakeGreen\\$Parameters\\$Inject@.* of artifact transform MakeGreen')) + failure.assertHasCause('A problem was found with the configuration of the artifact transform parameter MakeGreen.Parameters.') failure.assertHasCause("Property 'bad' is annotated with unsupported annotation @${annotation.simpleName}.") where: @@ -254,15 +254,15 @@ class ArtifactTransformValuesInjectionIntegrationTest extends AbstractDependency } } - interface MakeGreenParameters extends TransformParameters { - String getExtension() - void setExtension(String value) - @${annotation.simpleName} - String getBad() - void setBad(String value) - } + abstract class MakeGreen implements TransformAction { + interface Parameters extends TransformParameters { + String getExtension() + void setExtension(String value) + @${annotation.simpleName} + String getBad() + void setBad(String value) + } - abstract class MakeGreen implements TransformAction { void transform(TransformOutputs outputs) { throw new RuntimeException() } @@ -274,9 +274,9 @@ class ArtifactTransformValuesInjectionIntegrationTest extends AbstractDependency then: failure.assertHasDescription('A problem occurred evaluating root project') - failure.assertHasCause('Could not create an instance of type MakeGreenParameters.') - failure.assertHasCause('Could not generate a decorated class for interface MakeGreenParameters.') - failure.assertHasCause("Cannot use @${annotation.simpleName} annotation on method MakeGreenParameters.getBad().") + failure.assertHasCause('Could not create an instance of type MakeGreen$Parameters.') + failure.assertHasCause('Could not generate a decorated class for interface MakeGreen$Parameters.') + failure.assertHasCause("Cannot use @${annotation.simpleName} annotation on method Parameters.getBad().") where: annotation << [InputArtifact, InputArtifactDependencies] @@ -299,14 +299,14 @@ class ArtifactTransformValuesInjectionIntegrationTest extends AbstractDependency } } - interface MakeGreenParameters extends TransformParameters { - @Input - String getExtension() - void setExtension(String value) - } - @CacheableTransform - abstract class MakeGreen implements TransformAction { + abstract class MakeGreen implements TransformAction { + interface Parameters extends TransformParameters { + @Input + String getExtension() + void setExtension(String value) + } + @InputFile File inputFile @@ -361,13 +361,13 @@ class ArtifactTransformValuesInjectionIntegrationTest extends AbstractDependency } } - interface MakeGreenParameters extends TransformParameters { - @Input - String getExtension() - void setExtension(String value) - } + abstract class MakeGreen implements TransformAction { + interface Parameters extends TransformParameters { + @Input + String getExtension() + void setExtension(String value) + } - abstract class MakeGreen implements TransformAction { @${annotation.simpleName} String getBad() { } @@ -500,17 +500,17 @@ abstract class MakeGreen extends ArtifactTransform { } } - interface MakeGreenParameters extends TransformParameters { - @Input - String getExtension() - void setExtension(String value) - } + abstract class MakeGreen implements TransformAction { + interface Parameters extends TransformParameters { + @Input + String getExtension() + void setExtension(String value) + } - abstract class MakeGreen implements TransformAction { - private MakeGreenParameters conf + private Parameters conf @Inject - MakeGreen(MakeGreenParameters conf) { + MakeGreen(Parameters conf) { this.conf = conf } diff --git a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformWithDependenciesIntegrationTest.groovy b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformWithDependenciesIntegrationTest.groovy index 05bc8e3daa0d0..5d48ab9e560ca 100644 --- a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformWithDependenciesIntegrationTest.groovy +++ b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformWithDependenciesIntegrationTest.groovy @@ -53,12 +53,6 @@ class ArtifactTransformWithDependenciesIntegrationTest extends AbstractHttpDepen setupBuildWithColorAttributes(cl) buildFile << """ -interface TestTransformParameters extends TransformParameters { - @Input - String getTransformName() - void setTransformName(String name) -} - allprojects { repositories { maven { @@ -107,7 +101,12 @@ project(':app') { import javax.inject.Inject -abstract class TestTransform implements TransformAction { +abstract class TestTransform implements TransformAction { + interface Parameters extends TransformParameters { + @Input + String getTransformName() + void setTransformName(String name) + } @InputArtifactDependencies abstract FileCollection getInputArtifactDependencies() diff --git a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformWithFileInputsIntegrationTest.groovy b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformWithFileInputsIntegrationTest.groovy index 686bda313ed75..a43d1deae3618 100644 --- a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformWithFileInputsIntegrationTest.groovy +++ b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformWithFileInputsIntegrationTest.groovy @@ -31,12 +31,12 @@ class ArtifactTransformWithFileInputsIntegrationTest extends AbstractDependencyR """) } buildFile << """ - interface MakeGreenParameters extends TransformParameters{ - $inputAnnotations - ConfigurableFileCollection getSomeFiles() - } + abstract class MakeGreen implements TransformAction { + interface Parameters extends TransformParameters{ + $inputAnnotations + ConfigurableFileCollection getSomeFiles() + } - abstract class MakeGreen implements TransformAction { @InputArtifact abstract File getInput() @@ -281,12 +281,12 @@ class ArtifactTransformWithFileInputsIntegrationTest extends AbstractDependencyR } } - interface MakeGreenParameters extends TransformParameters { - @InputFile - RegularFileProperty getSomeFile() - } + abstract class MakeGreen implements TransformAction { + interface Parameters extends TransformParameters { + @InputFile + RegularFileProperty getSomeFile() + } - abstract class MakeGreen implements TransformAction { @InputArtifact abstract File getInput() @@ -332,12 +332,12 @@ class ArtifactTransformWithFileInputsIntegrationTest extends AbstractDependencyR } } - interface MakeGreenParameters extends TransformParameters { - @InputDirectory - DirectoryProperty getSomeDir() - } + abstract class MakeGreen implements TransformAction { + interface Parameters extends TransformParameters { + @InputDirectory + DirectoryProperty getSomeDir() + } - abstract class MakeGreen implements TransformAction { @InputArtifact abstract File getInput() diff --git a/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/DefaultVariantTransformRegistryTest.groovy b/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/DefaultVariantTransformRegistryTest.groovy index 2deb2c05e5dc3..11a5cefd3721c 100644 --- a/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/DefaultVariantTransformRegistryTest.groovy +++ b/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/DefaultVariantTransformRegistryTest.groovy @@ -140,7 +140,7 @@ class DefaultVariantTransformRegistryTest extends Specification { registration.from.getAttribute(TEST_ATTRIBUTE) == "FROM" registration.to.getAttribute(TEST_ATTRIBUTE) == "TO" registration.transformationStep.transformer.implementationClass == TestTransform - registration.transformationStep.transformer.parameterObject instanceof TestParameters + registration.transformationStep.transformer.parameterObject instanceof TestTransform.Parameters } def "creates registration for parametereless action"() { @@ -338,10 +338,6 @@ class DefaultVariantTransformRegistryTest extends Specification { e.cause == null } - static class TestParameters implements TransformParameters { - String value - } - static class UnAnnotatedTestTransformConfig { String value } @@ -353,7 +349,11 @@ class DefaultVariantTransformRegistryTest extends Specification { } } - static abstract class TestTransform implements TransformAction { + static abstract class TestTransform implements TransformAction { + static class Parameters implements TransformParameters { + String value + } + @Override void transform(TransformOutputs outputs) { } diff --git a/subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/AbstractConsoleBuildPhaseFunctionalTest.groovy b/subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/AbstractConsoleBuildPhaseFunctionalTest.groovy index eb8b4714e596f..3b36307d5a9a7 100644 --- a/subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/AbstractConsoleBuildPhaseFunctionalTest.groovy +++ b/subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/AbstractConsoleBuildPhaseFunctionalTest.groovy @@ -326,13 +326,13 @@ abstract class AbstractConsoleBuildPhaseFunctionalTest extends AbstractIntegrati def usage = Attribute.of('usage', String) def artifactType = Attribute.of('artifactType', String) - interface FileSizerParameters extends TransformParameters { - @Input - String getSuffix() - void setSuffix(String suffix) - } + abstract class FileSizer implements TransformAction { + interface Parameters extends TransformParameters { + @Input + String getSuffix() + void setSuffix(String suffix) + } - abstract class FileSizer implements TransformAction { @InputArtifactDependencies abstract FileCollection getDependencies() @InputArtifact From 0bcacad6a7122da15dd401f1ec6ce6c0fd89fedd Mon Sep 17 00:00:00 2001 From: Stefan Wolf Date: Tue, 26 Feb 2019 18:25:04 +0100 Subject: [PATCH 166/853] Use final class for TransformParameters.None --- .../transform/TransformParameters.java | 10 +++++- .../ArtifactTransformTestFixture.groovy | 2 ++ ...sformValuesInjectionIntegrationTest.groovy | 28 +++++++++++++++ .../transform/DefaultTransformer.java | 36 ++++++++++--------- 4 files changed, 59 insertions(+), 17 deletions(-) diff --git a/subprojects/core-api/src/main/java/org/gradle/api/artifacts/transform/TransformParameters.java b/subprojects/core-api/src/main/java/org/gradle/api/artifacts/transform/TransformParameters.java index 8f79976c72050..6f22976375155 100644 --- a/subprojects/core-api/src/main/java/org/gradle/api/artifacts/transform/TransformParameters.java +++ b/subprojects/core-api/src/main/java/org/gradle/api/artifacts/transform/TransformParameters.java @@ -25,5 +25,13 @@ */ @Incubating public interface TransformParameters { - interface None extends TransformParameters {} + /** + * Used for {@link TransformAction}s that do not require a parameter object. + * + * @since 5.3 + */ + @Incubating + final class None implements TransformParameters { + private None() {} + } } diff --git a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformTestFixture.groovy b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformTestFixture.groovy index e3bad2eaa057b..2f646d735afc0 100644 --- a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformTestFixture.groovy +++ b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformTestFixture.groovy @@ -187,9 +187,11 @@ allprojects { p -> registerTransform(MakeGreen) { from.attribute(color, 'blue') to.attribute(color, 'green') + ${builder.transformParamsConfig.empty ? "" : """ parameters { ${builder.transformParamsConfig} } + """} } } } diff --git a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformValuesInjectionIntegrationTest.groovy b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformValuesInjectionIntegrationTest.groovy index 7ebce53f69cf4..7c3c04b6b70d6 100644 --- a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformValuesInjectionIntegrationTest.groovy +++ b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformValuesInjectionIntegrationTest.groovy @@ -190,6 +190,34 @@ class ArtifactTransformValuesInjectionIntegrationTest extends AbstractDependency failure.assertHasCause("Property 'noPathSensitivity' is declared without path sensitivity. Properties of cacheable transforms must declare their path sensitivity.") } + def "cannot query parameters for transform without parameters"() { + settingsFile << """ + include 'a', 'b', 'c' + """ + setupBuildWithColorTransform() + buildFile << """ + project(':a') { + dependencies { + implementation project(':b') + implementation project(':c') + } + } + + abstract class MakeGreen implements TransformAction { + void transform(TransformOutputs outputs) { + println getParameters() + } + } +""" + + when: + fails(":a:resolve") + + then: + failure.assertResolutionFailure(':a:implementation') + failure.assertHasCause("Cannot query parameters for artifact transform without parameters.") + } + @Unroll def "transform parameters type cannot use annotation @#annotation.simpleName"() { settingsFile << """ diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformer.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformer.java index a0993ef4ef62c..b8c399354fe27 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformer.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformer.java @@ -68,6 +68,7 @@ import java.util.ArrayList; import java.util.List; import java.util.Map; +import java.util.function.Supplier; import java.util.stream.Collectors; public class DefaultTransformer extends AbstractTransformer { @@ -279,20 +280,20 @@ private IsolatedParameters getIsolatedParameters() { } private static class TransformServiceLookup implements ServiceLookup { - private static final TransformParameters.None NO_PARAMETERS = new TransformParameters.None() {}; - private final ImmutableList injectionPoints; public TransformServiceLookup(File inputFile, @Nullable TransformParameters parameters, @Nullable ArtifactTransformDependencies artifactTransformDependencies) { ImmutableList.Builder builder = ImmutableList.builder(); - builder.add(new InjectionPoint(InputArtifact.class, File.class, inputFile)); + builder.add(InjectionPoint.injectedByAnnotation(InputArtifact.class, () -> inputFile)); if (parameters != null) { - builder.add(new InjectionPoint(null, parameters.getClass(), parameters)); + builder.add(InjectionPoint.injectedByType(parameters.getClass(), () -> parameters)); } else { - builder.add(new InjectionPoint(null, TransformParameters.None.class, NO_PARAMETERS)); + builder.add(InjectionPoint.injectedByType(TransformParameters.None.class, () -> { + throw new UnknownServiceException(TransformParameters.None.class, "Cannot query parameters for artifact transform without parameters."); + })); } if (artifactTransformDependencies != null) { - builder.add(new InjectionPoint(InputArtifactDependencies.class, artifactTransformDependencies.getFiles())); + builder.add(InjectionPoint.injectedByAnnotation(InputArtifactDependencies.class, () -> artifactTransformDependencies.getFiles())); } this.injectionPoints = builder.build(); } @@ -302,9 +303,7 @@ private Object find(Type serviceType, @Nullable Class anno TypeToken serviceTypeToken = TypeToken.of(serviceType); for (InjectionPoint injectionPoint : injectionPoints) { if (annotatedWith == injectionPoint.getAnnotation() && serviceTypeToken.isSupertypeOf(injectionPoint.getInjectedType())) { - Object valueToInject = injectionPoint.getValueToInject(); - - return valueToInject; + return injectionPoint.getValueToInject(); } } return null; @@ -337,18 +336,22 @@ public Object get(Type serviceType, Class annotatedWith) t private static class InjectionPoint { private final Class annotation; private final Class injectedType; - private final Object valueToInject; + private final Supplier valueToInject; + + public static InjectionPoint injectedByAnnotation(Class annotation, Supplier valueToInject) { + return new InjectionPoint(annotation, determineTypeFromAnnotation(annotation), valueToInject); + } - public InjectionPoint(@Nullable Class annotation, Class injectedType, Object valueToInject) { + public static InjectionPoint injectedByType(Class injectedType, Supplier valueToInject) { + return new InjectionPoint(null, injectedType, valueToInject); + } + + private InjectionPoint(@Nullable Class annotation, Class injectedType, Supplier valueToInject) { this.annotation = annotation; this.injectedType = injectedType; this.valueToInject = valueToInject; } - public InjectionPoint(Class annotation, Object valueToInject) { - this(annotation, determineTypeFromAnnotation(annotation), valueToInject); - } - private static Class determineTypeFromAnnotation(Class annotation) { Class[] supportedTypes = annotation.getAnnotation(InjectionPointQualifier.class).supportedTypes(); if (supportedTypes.length != 1) { @@ -357,6 +360,7 @@ private static Class determineTypeFromAnnotation(Class return supportedTypes[0]; } + @Nullable public Class getAnnotation() { return annotation; } @@ -366,7 +370,7 @@ public Class getInjectedType() { } public Object getValueToInject() { - return valueToInject; + return valueToInject.get(); } } } From d7b2cf1d29832640f3eb6324a014eea6149aa525 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=B3r=C3=A1nt=20Pint=C3=A9r?= Date: Tue, 26 Feb 2019 18:36:31 +0100 Subject: [PATCH 167/853] Improve Javadoc Co-Authored-By: wolfs --- .../org/gradle/api/artifacts/transform/TransformParameters.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subprojects/core-api/src/main/java/org/gradle/api/artifacts/transform/TransformParameters.java b/subprojects/core-api/src/main/java/org/gradle/api/artifacts/transform/TransformParameters.java index 6f22976375155..72bc2c266f7a4 100644 --- a/subprojects/core-api/src/main/java/org/gradle/api/artifacts/transform/TransformParameters.java +++ b/subprojects/core-api/src/main/java/org/gradle/api/artifacts/transform/TransformParameters.java @@ -26,7 +26,7 @@ @Incubating public interface TransformParameters { /** - * Used for {@link TransformAction}s that do not require a parameter object. + * Used for {@link TransformAction}s without parameters. * * @since 5.3 */ From c212a57110609c647a3eb93e5f0dd10f6f6670c8 Mon Sep 17 00:00:00 2001 From: "Rodrigo B. de Oliveira" Date: Tue, 26 Feb 2019 15:25:50 -0300 Subject: [PATCH 168/853] Annotate `PrecompiledScriptPluginAccessorsTest` with `@LeaksFileHandles` --- .../plugins/precompiled/PrecompiledScriptPluginAccessorsTest.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subprojects/kotlin-dsl-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPluginAccessorsTest.kt b/subprojects/kotlin-dsl-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPluginAccessorsTest.kt index bd5d04ce541a5..2479b0e331396 100644 --- a/subprojects/kotlin-dsl-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPluginAccessorsTest.kt +++ b/subprojects/kotlin-dsl-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPluginAccessorsTest.kt @@ -47,6 +47,7 @@ import org.junit.Test import java.io.File +@LeaksFileHandles("Kotlin Compiler Daemon working directory") class PrecompiledScriptPluginAccessorsTest : AbstractPrecompiledScriptPluginTest() { @Test @@ -148,7 +149,6 @@ class PrecompiledScriptPluginAccessorsTest : AbstractPrecompiledScriptPluginTest } } - @LeaksFileHandles("TDB") @Test fun `can use plugin spec builders for plugins in the implementation classpath`() { From 3fa9170725f63e3b96f9a0c2368b5b2e52a98e80 Mon Sep 17 00:00:00 2001 From: "Rodrigo B. de Oliveira" Date: Tue, 26 Feb 2019 18:32:31 -0300 Subject: [PATCH 169/853] Remove unused import --- .../dsl/integration/KotlinInitScriptModelIntegrationTest.kt | 2 -- 1 file changed, 2 deletions(-) diff --git a/subprojects/kotlin-dsl/src/integTest/kotlin/org/gradle/kotlin/dsl/integration/KotlinInitScriptModelIntegrationTest.kt b/subprojects/kotlin-dsl/src/integTest/kotlin/org/gradle/kotlin/dsl/integration/KotlinInitScriptModelIntegrationTest.kt index 1696defcb5328..af10ce428cb2e 100644 --- a/subprojects/kotlin-dsl/src/integTest/kotlin/org/gradle/kotlin/dsl/integration/KotlinInitScriptModelIntegrationTest.kt +++ b/subprojects/kotlin-dsl/src/integTest/kotlin/org/gradle/kotlin/dsl/integration/KotlinInitScriptModelIntegrationTest.kt @@ -5,8 +5,6 @@ import org.hamcrest.MatcherAssert.assertThat import org.junit.Test -import java.io.File - class KotlinInitScriptModelIntegrationTest : ScriptModelIntegrationTest() { From 9693ece8bb430faabdcdf4728cf880f69ef867dc Mon Sep 17 00:00:00 2001 From: Gradleware Git Bot Date: Tue, 26 Feb 2019 22:41:32 +0100 Subject: [PATCH 170/853] Publish 5.3-20190226212742+0000 --- released-versions.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/released-versions.json b/released-versions.json index c3dee92ef6641..9b56d60ab151d 100644 --- a/released-versions.json +++ b/released-versions.json @@ -1,7 +1,7 @@ { "latestReleaseSnapshot": { - "version": "5.3-20190226013556+0000", - "buildTime": "20190226013556+0000" + "version": "5.3-20190226212742+0000", + "buildTime": "20190226212742+0000" }, "latestRc": { "version": "5.2-rc-1", From 36574771ae88f61967f593679473f20c9e066acc Mon Sep 17 00:00:00 2001 From: Sterling Greene Date: Tue, 26 Feb 2019 17:19:18 -0500 Subject: [PATCH 171/853] Bump to latest nightly --- gradle/wrapper/gradle-wrapper.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index e75924361df45..5a6597cf54a11 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions-snapshots/gradle-5.3-20190224011633+0000-bin.zip +distributionUrl=https\://services.gradle.org/distributions-snapshots/gradle-5.3-20190226013556+0000-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists From 031de69d31e7091ce0d7ceeef0b5eba23390bced Mon Sep 17 00:00:00 2001 From: "Rodrigo B. de Oliveira" Date: Tue, 26 Feb 2019 20:47:58 -0300 Subject: [PATCH 172/853] Include implicit imports for precompiled script plugin accessors In model response. Unfortunately the test must continue to be `@Ignore`d because the tests don't execute against the latest version of the model builder. --- ...ompiledScriptPluginModelIntegrationTest.kt | 3 +- .../precompiled/PrecompiledScriptPlugins.kt | 59 ++++++-------- .../CompilePrecompiledScriptPluginPlugins.kt | 3 +- ...rePrecompiledScriptDependenciesResolver.kt | 77 +++++++++++++++++++ .../builders/KotlinBuildScriptModelBuilder.kt | 34 +++++++- .../PrecompiledScriptDependenciesResolver.kt | 7 +- .../dsl/provider/KotlinDslProviderMode.kt | 1 + .../resolver/KotlinBuildScriptModelRequest.kt | 1 + 8 files changed, 142 insertions(+), 43 deletions(-) create mode 100644 subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/ConfigurePrecompiledScriptDependenciesResolver.kt diff --git a/subprojects/kotlin-dsl-integ-tests/src/integTest/kotlin/org/gradle/kotlin/dsl/integration/PrecompiledScriptPluginModelIntegrationTest.kt b/subprojects/kotlin-dsl-integ-tests/src/integTest/kotlin/org/gradle/kotlin/dsl/integration/PrecompiledScriptPluginModelIntegrationTest.kt index ac934e430ee51..eba76678b241c 100644 --- a/subprojects/kotlin-dsl-integ-tests/src/integTest/kotlin/org/gradle/kotlin/dsl/integration/PrecompiledScriptPluginModelIntegrationTest.kt +++ b/subprojects/kotlin-dsl-integ-tests/src/integTest/kotlin/org/gradle/kotlin/dsl/integration/PrecompiledScriptPluginModelIntegrationTest.kt @@ -56,7 +56,7 @@ class PrecompiledScriptPluginModelIntegrationTest : AbstractPluginIntegrationTes """) val precompiledScriptPlugin = - withFile("src/main/kotlin/my-plugin.gradle.kts") + withPrecompiledKotlinScript("my-plugin.gradle.kts", "") assertClassPathFor( precompiledScriptPlugin, @@ -113,7 +113,6 @@ class PrecompiledScriptPluginModelIntegrationTest : AbstractPluginIntegrationTes @Test fun `implicit imports include type-safe accessors packages`() { - withDefaultSettings() withKotlinDslPlugin() val pluginFile = withPrecompiledKotlinScript("plugin.gradle.kts", """ diff --git a/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPlugins.kt b/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPlugins.kt index f669b42fe0b28..b74e267fdc80a 100644 --- a/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPlugins.kt +++ b/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPlugins.kt @@ -26,9 +26,11 @@ import org.gradle.api.provider.Provider import org.gradle.api.tasks.SourceSet import org.gradle.api.tasks.SourceSetContainer +import org.gradle.api.tasks.TaskProvider import org.gradle.kotlin.dsl.* import org.gradle.kotlin.dsl.plugins.precompiled.tasks.CompilePrecompiledScriptPluginPlugins +import org.gradle.kotlin.dsl.plugins.precompiled.tasks.ConfigurePrecompiledScriptDependenciesResolver import org.gradle.kotlin.dsl.plugins.precompiled.tasks.ExtractPrecompiledScriptPluginPlugins import org.gradle.kotlin.dsl.plugins.precompiled.tasks.GenerateExternalPluginSpecBuilders import org.gradle.kotlin.dsl.plugins.precompiled.tasks.GenerateInternalPluginSpecBuilders @@ -38,13 +40,10 @@ import org.gradle.kotlin.dsl.plugins.precompiled.tasks.HashedProjectSchema import org.gradle.kotlin.dsl.precompile.PrecompiledInitScript import org.gradle.kotlin.dsl.precompile.PrecompiledProjectScript -import org.gradle.kotlin.dsl.precompile.PrecompiledScriptDependenciesResolver import org.gradle.kotlin.dsl.precompile.PrecompiledSettingsScript import org.gradle.kotlin.dsl.provider.gradleKotlinDslJarsOf - -import org.gradle.kotlin.dsl.support.ImplicitImports -import org.gradle.kotlin.dsl.support.serviceOf +import org.gradle.kotlin.dsl.provider.inClassPathMode import org.gradle.plugin.devel.GradlePluginDevelopmentExtension import org.gradle.plugin.devel.plugins.JavaGradlePluginPlugin @@ -191,7 +190,7 @@ fun Project.enableScriptCompilationOf(scriptPlugins: List( "accessors", "generatePrecompiledScriptPluginAccessors" @@ -204,33 +203,19 @@ fun Project.enableScriptCompilationOf(scriptPlugins: List compileKotlin.get().apply { kotlinOptions { freeCompilerArgs += listOf( @@ -242,6 +227,20 @@ fun Project.enableScriptCompilationOf(scriptPlugins: List +) { + rootProject.tasks.named("projects" /*KotlinDslProviderMode.modelTaskName*/) { + it.dependsOn(modelTask) } } @@ -263,18 +262,6 @@ val scriptTemplates by lazy { } -private -fun resolverEnvironmentStringFor(properties: Iterable>>): String = - properties.joinToString(separator = ",") { (key, values) -> - "$key=\"${values.joinToString(":")}\"" - } - - -internal -fun Project.implicitImports(): List = - serviceOf().list - - private fun Project.exposeScriptsAsGradlePlugins(scriptPlugins: List) { diff --git a/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/CompilePrecompiledScriptPluginPlugins.kt b/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/CompilePrecompiledScriptPluginPlugins.kt index 2774f74fe2323..f243d9f7c0df4 100644 --- a/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/CompilePrecompiledScriptPluginPlugins.kt +++ b/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/CompilePrecompiledScriptPluginPlugins.kt @@ -26,10 +26,11 @@ import org.gradle.api.tasks.PathSensitivity import org.gradle.api.tasks.TaskAction import org.gradle.kotlin.dsl.execution.scriptDefinitionFromTemplate -import org.gradle.kotlin.dsl.plugins.precompiled.implicitImports +import org.gradle.kotlin.dsl.support.ImplicitImports import org.gradle.kotlin.dsl.support.KotlinPluginsBlock import org.gradle.kotlin.dsl.support.compileKotlinScriptModuleTo +import org.gradle.kotlin.dsl.support.serviceOf @CacheableTask diff --git a/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/ConfigurePrecompiledScriptDependenciesResolver.kt b/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/ConfigurePrecompiledScriptDependenciesResolver.kt new file mode 100644 index 0000000000000..73e0f12f694ad --- /dev/null +++ b/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/ConfigurePrecompiledScriptDependenciesResolver.kt @@ -0,0 +1,77 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.kotlin.dsl.plugins.precompiled.tasks + +import org.gradle.api.DefaultTask +import org.gradle.api.Project +import org.gradle.api.tasks.Internal +import org.gradle.api.tasks.TaskAction + +import org.gradle.kotlin.dsl.precompile.PrecompiledScriptDependenciesResolver.EnvironmentProperties.kotlinDslImplicitImports +import org.gradle.kotlin.dsl.support.ImplicitImports + +import org.gradle.kotlin.dsl.support.serviceOf + + +open class ConfigurePrecompiledScriptDependenciesResolver : DefaultTask() { + + @Internal + val metadataDir = project.objects.directoryProperty() + + private + lateinit var onConfigure: (String) -> Unit + + fun onConfigure(action: (String) -> Unit) { + onConfigure = action + } + + @TaskAction + fun configureImports() { + + val precompiledScriptPluginImports = precompiledScriptPluginImports() + + val resolverEnvironment = resolverEnvironmentStringFor( + listOf( + kotlinDslImplicitImports to project.implicitImports() + ) + precompiledScriptPluginImports + ) + + onConfigure(resolverEnvironment) + } + + private + fun precompiledScriptPluginImports(): List>> = + metadataDirFile().run { + require(isDirectory) + listFiles().map { + it.name to it.readLines() + } + } + + private + fun metadataDirFile() = metadataDir.get().asFile + + private + fun resolverEnvironmentStringFor(properties: Iterable>>): String = + properties.joinToString(separator = ",") { (key, values) -> + "$key=\"${values.joinToString(":")}\"" + } +} + + +internal +fun Project.implicitImports() = serviceOf().list diff --git a/subprojects/kotlin-dsl-tooling-builders/src/main/kotlin/org/gradle/kotlin/dsl/tooling/builders/KotlinBuildScriptModelBuilder.kt b/subprojects/kotlin-dsl-tooling-builders/src/main/kotlin/org/gradle/kotlin/dsl/tooling/builders/KotlinBuildScriptModelBuilder.kt index 90d3e2c528cba..267bf73ea45db 100644 --- a/subprojects/kotlin-dsl-tooling-builders/src/main/kotlin/org/gradle/kotlin/dsl/tooling/builders/KotlinBuildScriptModelBuilder.kt +++ b/subprojects/kotlin-dsl-tooling-builders/src/main/kotlin/org/gradle/kotlin/dsl/tooling/builders/KotlinBuildScriptModelBuilder.kt @@ -42,6 +42,8 @@ import org.gradle.kotlin.dsl.accessors.projectAccessorsClassPath import org.gradle.kotlin.dsl.execution.EvalOption +import org.gradle.kotlin.dsl.precompile.PrecompiledScriptDependenciesResolver + import org.gradle.kotlin.dsl.provider.ClassPathModeExceptionCollector import org.gradle.kotlin.dsl.provider.KotlinScriptClassPathProvider import org.gradle.kotlin.dsl.provider.KotlinScriptEvaluator @@ -203,10 +205,30 @@ fun precompiledScriptPluginModelBuilder( scriptFile = scriptFile, project = modelRequestProject, scriptClassPath = DefaultClassPath.of(enclosingSourceSet.sourceSet.compileClasspath), - enclosingScriptProjectDir = enclosingSourceSet.project.projectDir + enclosingScriptProjectDir = enclosingSourceSet.project.projectDir, + additionalImports = { + val metadataDir = enclosingSourceSet.project.buildDir.resolve("precompiled-script-plugins") + require(metadataDir.isDirectory) + implicitImportsFor( + hashOf(scriptFile), + metadataDir + ) ?: emptyList() + } ) +private +fun implicitImportsFor(precompiledScriptPluginHash: String, metadataDir: File): List? = + metadataDir + .resolve(precompiledScriptPluginHash) + .takeIf { it.isFile } + ?.readLines() + + +private +fun hashOf(scriptFile: File) = PrecompiledScriptDependenciesResolver.hashOf(scriptFile.readText()) + + private fun projectScriptModelBuilder( scriptFile: File?, @@ -359,7 +381,8 @@ data class KotlinScriptTargetModelBuilder( val scriptClassPath: ClassPath, val accessorsClassPath: (ClassPath) -> AccessorsClassPath = { AccessorsClassPath.empty }, val sourceLookupScriptHandlers: List = emptyList(), - val enclosingScriptProjectDir: File? = null + val enclosingScriptProjectDir: File? = null, + val additionalImports: () -> List = { emptyList() } ) { fun buildModel(): KotlinBuildScriptModel { @@ -370,10 +393,15 @@ data class KotlinScriptTargetModelBuilder( accessorsClassPath(scriptClassPath) } ?: AccessorsClassPath.empty + val additionalImports = + classPathModeExceptionCollector.ignoringErrors { + additionalImports() + } ?: emptyList() + return StandardKotlinBuildScriptModel( (scriptClassPath + accessorsClassPath.bin).asFiles, (gradleSource() + classpathSources + accessorsClassPath.src).asFiles, - implicitImports, + implicitImports + additionalImports, buildEditorReportsFor(classPathModeExceptionCollector.exceptions), classPathModeExceptionCollector.exceptions.map(::exceptionToString), enclosingScriptProjectDir diff --git a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/precompile/PrecompiledScriptDependenciesResolver.kt b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/precompile/PrecompiledScriptDependenciesResolver.kt index 6376957ae7a05..0403d5bcb4f3a 100644 --- a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/precompile/PrecompiledScriptDependenciesResolver.kt +++ b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/precompile/PrecompiledScriptDependenciesResolver.kt @@ -31,6 +31,11 @@ import kotlin.script.dependencies.ScriptDependenciesResolver class PrecompiledScriptDependenciesResolver : ScriptDependenciesResolver { + companion object { + + fun hashOf(charSequence: CharSequence?) = Hashing.hashString(charSequence).toString() + } + object EnvironmentProperties { const val kotlinDslImplicitImports = "kotlinDslImplicitImports" } @@ -56,7 +61,7 @@ class PrecompiledScriptDependenciesResolver : ScriptDependenciesResolver { private fun precompiledScriptPluginImportsFrom(environment: Environment?, script: ScriptContents): List = - environment.stringList(Hashing.hashString(script.text).toString()) + environment.stringList(hashOf(script.text)) private fun Environment?.stringList(key: String) = diff --git a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/provider/KotlinDslProviderMode.kt b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/provider/KotlinDslProviderMode.kt index e9b371a297b81..f4d551f635b1b 100644 --- a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/provider/KotlinDslProviderMode.kt +++ b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/provider/KotlinDslProviderMode.kt @@ -20,6 +20,7 @@ internal object KotlinDslProviderMode { const val systemPropertyName = "org.gradle.kotlin.dsl.provider.mode" const val classPathMode = "classpath" + const val modelTaskName = "projects" } diff --git a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/resolver/KotlinBuildScriptModelRequest.kt b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/resolver/KotlinBuildScriptModelRequest.kt index f1105d62d68a1..8060a54f18c19 100644 --- a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/resolver/KotlinBuildScriptModelRequest.kt +++ b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/resolver/KotlinBuildScriptModelRequest.kt @@ -124,6 +124,7 @@ fun ProjectConnection.modelBuilderFor(request: KotlinBuildScriptModelRequest) = model(KotlinBuildScriptModel::class.java).apply { setJavaHome(request.javaHome) setJvmArguments(request.jvmOptions + modelSpecificJvmOptions) + forTasks(KotlinDslProviderMode.modelTaskName) val arguments = request.options.toMutableList() arguments += "-P$kotlinBuildScriptModelCorrelationId=${request.correlationId}" From 4fe5ac154c3e3e16b0bf3234e09a650795ff0d6c Mon Sep 17 00:00:00 2001 From: Gary Hale Date: Tue, 26 Feb 2019 20:20:25 -0500 Subject: [PATCH 173/853] Ignore soak tests that are flaky due to changes in GC monitor --- .../launcher/daemon/DaemonPerformanceMonitoringSoakTest.groovy | 2 ++ 1 file changed, 2 insertions(+) diff --git a/subprojects/soak/src/integTest/groovy/org/gradle/launcher/daemon/DaemonPerformanceMonitoringSoakTest.groovy b/subprojects/soak/src/integTest/groovy/org/gradle/launcher/daemon/DaemonPerformanceMonitoringSoakTest.groovy index 3a45e4a2eed1b..5d4e7df2824f1 100644 --- a/subprojects/soak/src/integTest/groovy/org/gradle/launcher/daemon/DaemonPerformanceMonitoringSoakTest.groovy +++ b/subprojects/soak/src/integTest/groovy/org/gradle/launcher/daemon/DaemonPerformanceMonitoringSoakTest.groovy @@ -94,6 +94,7 @@ class DaemonPerformanceMonitoringSoakTest extends DaemonMultiJdkIntegrationTest !daemonIsExpiredEagerly() } + @Ignore def "when leak occurs while daemon is idle daemon is still expired"() { // This is so the idle timeout expiration strategy doesn't kick in // before the gc monitoring expires the daemon @@ -137,6 +138,7 @@ class DaemonPerformanceMonitoringSoakTest extends DaemonMultiJdkIntegrationTest daemonIsExpiredEagerly() } + @Ignore def "detects a thrashing condition" () { // This is so the idle timeout expiration strategy doesn't kick in // before the gc monitoring expires the daemon From ffef6853426ff45f74c1e77f5239a169ab6b54b4 Mon Sep 17 00:00:00 2001 From: "Rodrigo B. de Oliveira" Date: Tue, 26 Feb 2019 22:52:37 -0300 Subject: [PATCH 174/853] Bump `kotlin-dsl-plugins` version --- subprojects/kotlin-dsl-plugins/kotlin-dsl-plugins.gradle.kts | 2 +- subprojects/kotlin-dsl/kotlin-dsl.gradle.kts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/subprojects/kotlin-dsl-plugins/kotlin-dsl-plugins.gradle.kts b/subprojects/kotlin-dsl-plugins/kotlin-dsl-plugins.gradle.kts index e9b4492304140..5a1e88cfba7fd 100644 --- a/subprojects/kotlin-dsl-plugins/kotlin-dsl-plugins.gradle.kts +++ b/subprojects/kotlin-dsl-plugins/kotlin-dsl-plugins.gradle.kts @@ -27,7 +27,7 @@ plugins { description = "Kotlin DSL Gradle Plugins deployed to the Plugin Portal" group = "org.gradle.kotlin" -version = "1.2.3" +version = "1.2.4" base.archivesBaseName = "plugins" diff --git a/subprojects/kotlin-dsl/kotlin-dsl.gradle.kts b/subprojects/kotlin-dsl/kotlin-dsl.gradle.kts index ace709535053d..7fc34780ee451 100644 --- a/subprojects/kotlin-dsl/kotlin-dsl.gradle.kts +++ b/subprojects/kotlin-dsl/kotlin-dsl.gradle.kts @@ -72,7 +72,7 @@ dependencies { // --- Enable automatic generation of API extensions ------------------- val apiExtensionsOutputDir = file("src/generated/kotlin") -val publishedKotlinDslPluginVersion = "1.2.2" // TODO:kotlin-dsl +val publishedKotlinDslPluginVersion = "1.2.3" // TODO:kotlin-dsl tasks { From 2ba63890b9354e04a9d17508ee12319a3a66f584 Mon Sep 17 00:00:00 2001 From: "Rodrigo B. de Oliveira" Date: Tue, 26 Feb 2019 22:53:54 -0300 Subject: [PATCH 175/853] Un-ignore script model test After publishing new `kotlin-dsl-plugins` version. --- .../integration/PrecompiledScriptPluginModelIntegrationTest.kt | 2 -- 1 file changed, 2 deletions(-) diff --git a/subprojects/kotlin-dsl-integ-tests/src/integTest/kotlin/org/gradle/kotlin/dsl/integration/PrecompiledScriptPluginModelIntegrationTest.kt b/subprojects/kotlin-dsl-integ-tests/src/integTest/kotlin/org/gradle/kotlin/dsl/integration/PrecompiledScriptPluginModelIntegrationTest.kt index eba76678b241c..a763ebebe1ea3 100644 --- a/subprojects/kotlin-dsl-integ-tests/src/integTest/kotlin/org/gradle/kotlin/dsl/integration/PrecompiledScriptPluginModelIntegrationTest.kt +++ b/subprojects/kotlin-dsl-integ-tests/src/integTest/kotlin/org/gradle/kotlin/dsl/integration/PrecompiledScriptPluginModelIntegrationTest.kt @@ -22,7 +22,6 @@ import org.hamcrest.MatcherAssert.assertThat import org.hamcrest.Matchers.hasItem import org.hamcrest.Matchers.startsWith -import org.junit.Ignore import org.junit.Test import java.io.File @@ -109,7 +108,6 @@ class PrecompiledScriptPluginModelIntegrationTest : AbstractPluginIntegrationTes ) } - @Ignore("wip") @Test fun `implicit imports include type-safe accessors packages`() { From e0e2f5e66e7e81e91b85ee2abeb151c148a022e8 Mon Sep 17 00:00:00 2001 From: "Rodrigo B. de Oliveira" Date: Tue, 26 Feb 2019 22:55:09 -0300 Subject: [PATCH 176/853] Always recreate output directory --- .../precompiled/tasks/GenerateInternalPluginSpecBuilders.kt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/GenerateInternalPluginSpecBuilders.kt b/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/GenerateInternalPluginSpecBuilders.kt index e38c8ce86052a..d84187b0112ad 100644 --- a/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/GenerateInternalPluginSpecBuilders.kt +++ b/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/GenerateInternalPluginSpecBuilders.kt @@ -52,6 +52,8 @@ open class GenerateInternalPluginSpecBuilders : DefaultTask() { @TaskAction fun generate() { - // TODO + sourceCodeOutputDir.withOutputDirectory { + + } } } From df7e5cdeef33e7b24dc940b7103fd274da727f87 Mon Sep 17 00:00:00 2001 From: "Rodrigo B. de Oliveira" Date: Tue, 26 Feb 2019 22:55:43 -0300 Subject: [PATCH 177/853] Trigger generation of plugin spec builders during script model requests --- .../kotlin/dsl/plugins/precompiled/PrecompiledScriptPlugins.kt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPlugins.kt b/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPlugins.kt index b74e267fdc80a..5b623773f62d9 100644 --- a/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPlugins.kt +++ b/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPlugins.kt @@ -204,6 +204,8 @@ fun Project.enableScriptCompilationOf(scriptPlugins: List Date: Wed, 27 Feb 2019 04:05:49 +0100 Subject: [PATCH 178/853] Publish 5.3-20190227025139+0000 --- released-versions.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/released-versions.json b/released-versions.json index 9b56d60ab151d..e1239bef37aa5 100644 --- a/released-versions.json +++ b/released-versions.json @@ -1,7 +1,7 @@ { "latestReleaseSnapshot": { - "version": "5.3-20190226212742+0000", - "buildTime": "20190226212742+0000" + "version": "5.3-20190227025139+0000", + "buildTime": "20190227025139+0000" }, "latestRc": { "version": "5.2-rc-1", From 908e2827c846e1d404621111ed47f8277424a266 Mon Sep 17 00:00:00 2001 From: Stefan Wolf Date: Wed, 27 Feb 2019 08:21:54 +0100 Subject: [PATCH 179/853] Infer parameters from action --- .../transforms/ExplodeZipAndFindJars.groovy | 5 ++- .../transforms/FindGradleClasspath.groovy | 6 +-- .../transforms/FindGradleJar.groovy | 22 ++++------ .../build/AddGradleApiParameterNames.kt | 21 ++++------ .../gradle/gradlebuild/packaging/Minify.kt | 15 +++---- .../gradlebuild/packaging/ShadeClasses.kt | 40 ++++++++----------- .../gradlebuild/packaging/ShadedJarPlugin.kt | 8 ++-- gradle/wrapper/gradle-wrapper.properties | 2 +- .../distributions/binary-compatibility.gradle | 7 +--- .../kotlin/dsl/resolver/FindGradleSources.kt | 5 ++- .../resolver/SourceDistributionProvider.kt | 9 +++-- 11 files changed, 58 insertions(+), 82 deletions(-) diff --git a/buildSrc/subprojects/binary-compatibility/src/main/groovy/org/gradle/binarycompatibility/transforms/ExplodeZipAndFindJars.groovy b/buildSrc/subprojects/binary-compatibility/src/main/groovy/org/gradle/binarycompatibility/transforms/ExplodeZipAndFindJars.groovy index 79c29f4537cf6..40cbd998e1492 100644 --- a/buildSrc/subprojects/binary-compatibility/src/main/groovy/org/gradle/binarycompatibility/transforms/ExplodeZipAndFindJars.groovy +++ b/buildSrc/subprojects/binary-compatibility/src/main/groovy/org/gradle/binarycompatibility/transforms/ExplodeZipAndFindJars.groovy @@ -21,15 +21,16 @@ import groovy.transform.CompileStatic import org.gradle.api.artifacts.transform.InputArtifact import org.gradle.api.artifacts.transform.TransformAction import org.gradle.api.artifacts.transform.TransformOutputs +import org.gradle.api.artifacts.transform.TransformParameters import org.gradle.api.tasks.PathSensitive import org.gradle.api.tasks.PathSensitivity +import java.nio.file.Files import java.util.zip.ZipEntry import java.util.zip.ZipInputStream -import java.nio.file.Files @CompileStatic -abstract class ExplodeZipAndFindJars implements TransformAction { +abstract class ExplodeZipAndFindJars implements TransformAction { @PathSensitive(PathSensitivity.NAME_ONLY) @InputArtifact diff --git a/buildSrc/subprojects/binary-compatibility/src/main/groovy/org/gradle/binarycompatibility/transforms/FindGradleClasspath.groovy b/buildSrc/subprojects/binary-compatibility/src/main/groovy/org/gradle/binarycompatibility/transforms/FindGradleClasspath.groovy index 9563793a3d9d8..531fec291900c 100644 --- a/buildSrc/subprojects/binary-compatibility/src/main/groovy/org/gradle/binarycompatibility/transforms/FindGradleClasspath.groovy +++ b/buildSrc/subprojects/binary-compatibility/src/main/groovy/org/gradle/binarycompatibility/transforms/FindGradleClasspath.groovy @@ -16,16 +16,16 @@ package org.gradle.binarycompatibility.transforms +import groovy.transform.CompileStatic import org.gradle.api.artifacts.transform.InputArtifact import org.gradle.api.artifacts.transform.TransformAction import org.gradle.api.artifacts.transform.TransformOutputs +import org.gradle.api.artifacts.transform.TransformParameters import org.gradle.api.tasks.PathSensitive import org.gradle.api.tasks.PathSensitivity -import groovy.transform.CompileStatic - @CompileStatic -abstract class FindGradleClasspath implements TransformAction { +abstract class FindGradleClasspath implements TransformAction { @PathSensitive(PathSensitivity.NAME_ONLY) @InputArtifact diff --git a/buildSrc/subprojects/binary-compatibility/src/main/groovy/org/gradle/binarycompatibility/transforms/FindGradleJar.groovy b/buildSrc/subprojects/binary-compatibility/src/main/groovy/org/gradle/binarycompatibility/transforms/FindGradleJar.groovy index 3e4bc063d9152..bf9d61d50f483 100644 --- a/buildSrc/subprojects/binary-compatibility/src/main/groovy/org/gradle/binarycompatibility/transforms/FindGradleJar.groovy +++ b/buildSrc/subprojects/binary-compatibility/src/main/groovy/org/gradle/binarycompatibility/transforms/FindGradleJar.groovy @@ -17,7 +17,7 @@ package org.gradle.binarycompatibility.transforms -import org.gradle.api.artifacts.transform.AssociatedTransformAction +import groovy.transform.CompileStatic import org.gradle.api.artifacts.transform.InputArtifact import org.gradle.api.artifacts.transform.TransformAction import org.gradle.api.artifacts.transform.TransformOutputs @@ -26,21 +26,15 @@ import org.gradle.api.tasks.Input import org.gradle.api.tasks.PathSensitive import org.gradle.api.tasks.PathSensitivity -import groovy.transform.CompileStatic - -@AssociatedTransformAction(FindGradleJarAction) @CompileStatic -interface FindGradleJar { - @Input - String getTarget() - void setTarget(String target) -} +abstract class FindGradleJar implements TransformAction { -@CompileStatic -abstract class FindGradleJarAction implements TransformAction { - - @TransformParameters - abstract FindGradleJar getParameters() + @CompileStatic + interface Parameters extends TransformParameters { + @Input + String getTarget() + void setTarget(String target) + } @PathSensitive(PathSensitivity.NAME_ONLY) @InputArtifact diff --git a/buildSrc/subprojects/kotlin-dsl/src/main/kotlin/build/AddGradleApiParameterNames.kt b/buildSrc/subprojects/kotlin-dsl/src/main/kotlin/build/AddGradleApiParameterNames.kt index 60b52596aaa19..eb51a99b30163 100644 --- a/buildSrc/subprojects/kotlin-dsl/src/main/kotlin/build/AddGradleApiParameterNames.kt +++ b/buildSrc/subprojects/kotlin-dsl/src/main/kotlin/build/AddGradleApiParameterNames.kt @@ -18,7 +18,6 @@ package build import accessors.sourceSets import org.gradle.api.Project -import org.gradle.api.artifacts.transform.AssociatedTransformAction import org.gradle.api.artifacts.transform.InputArtifact import org.gradle.api.artifacts.transform.TransformAction import org.gradle.api.artifacts.transform.TransformOutputs @@ -89,21 +88,15 @@ fun Project.withCompileOnlyGradleApiModulesWithParameterNames(vararg gradleModul } -@AssociatedTransformAction(AddGradleApiParameterNamesAction::class) internal -interface AddGradleApiParameterNames { - @get:Input - var publicApiIncludes: List - @get:Input - var publicApiExcludes: List -} - +abstract class AddGradleApiParameterNames : TransformAction { -internal -abstract class AddGradleApiParameterNamesAction : TransformAction { - - @get:TransformParameters - abstract val parameters: AddGradleApiParameterNames + interface Parameters : TransformParameters { + @get:Input + var publicApiIncludes: List + @get:Input + var publicApiExcludes: List + } @get:PathSensitive(PathSensitivity.NAME_ONLY) @get:InputArtifact diff --git a/buildSrc/subprojects/packaging/src/main/kotlin/org/gradle/gradlebuild/packaging/Minify.kt b/buildSrc/subprojects/packaging/src/main/kotlin/org/gradle/gradlebuild/packaging/Minify.kt index d17c6955396ef..659f9ad01b347 100644 --- a/buildSrc/subprojects/packaging/src/main/kotlin/org/gradle/gradlebuild/packaging/Minify.kt +++ b/buildSrc/subprojects/packaging/src/main/kotlin/org/gradle/gradlebuild/packaging/Minify.kt @@ -17,7 +17,6 @@ package org.gradle.gradlebuild.packaging import com.google.common.io.Files -import org.gradle.api.artifacts.transform.AssociatedTransformAction import org.gradle.api.artifacts.transform.InputArtifact import org.gradle.api.artifacts.transform.TransformAction import org.gradle.api.artifacts.transform.TransformOutputs @@ -32,16 +31,12 @@ import java.util.jar.JarFile import java.util.jar.JarOutputStream -@AssociatedTransformAction(MinifyAction::class) -interface Minify { - @get:Input - var keepClassesByArtifact: Map> -} - +abstract class Minify : TransformAction { -abstract class MinifyAction : TransformAction { - @get:TransformParameters - abstract val parameters: Minify + interface Parameters : TransformParameters { + @get:Input + var keepClassesByArtifact: Map> + } @get:PathSensitive(PathSensitivity.NAME_ONLY) @get:InputArtifact diff --git a/buildSrc/subprojects/packaging/src/main/kotlin/org/gradle/gradlebuild/packaging/ShadeClasses.kt b/buildSrc/subprojects/packaging/src/main/kotlin/org/gradle/gradlebuild/packaging/ShadeClasses.kt index 5e99ca1a74e70..d9deb179d143e 100644 --- a/buildSrc/subprojects/packaging/src/main/kotlin/org/gradle/gradlebuild/packaging/ShadeClasses.kt +++ b/buildSrc/subprojects/packaging/src/main/kotlin/org/gradle/gradlebuild/packaging/ShadeClasses.kt @@ -17,8 +17,7 @@ package org.gradle.gradlebuild.packaging import com.google.gson.Gson -import org.gradle.api.artifacts.transform.AssociatedTransformAction -import org.gradle.api.artifacts.transform.CacheableTransformAction +import org.gradle.api.artifacts.transform.CacheableTransform import org.gradle.api.artifacts.transform.InputArtifact import org.gradle.api.artifacts.transform.TransformAction import org.gradle.api.artifacts.transform.TransformOutputs @@ -44,24 +43,19 @@ private const val manifestFileName = "MANIFEST.MF" -@AssociatedTransformAction(ShadeClassesAction::class) -interface ShadeClasses { - @get:Input - var shadowPackage: String - @get:Input - var keepPackages: Set - @get:Input - var unshadedPackages: Set - @get:Input - var ignoredPackages: Set -} - +@CacheableTransform +abstract class ShadeClasses : TransformAction { -@CacheableTransformAction -abstract class ShadeClassesAction : TransformAction { - - @get:TransformParameters - abstract val parameters: ShadeClasses + interface Parameters : TransformParameters { + @get:Input + var shadowPackage: String + @get:Input + var keepPackages: Set + @get:Input + var unshadedPackages: Set + @get:Input + var ignoredPackages: Set + } @get:Classpath @get:InputArtifact @@ -85,7 +79,7 @@ abstract class ShadeClassesAction : TransformAction { } -abstract class FindClassTrees : TransformAction { +abstract class FindClassTrees : TransformAction { @get:InputArtifact abstract val input: File @@ -95,7 +89,7 @@ abstract class FindClassTrees : TransformAction { } -abstract class FindEntryPoints : TransformAction { +abstract class FindEntryPoints : TransformAction { @get:InputArtifact abstract val input: File @@ -105,7 +99,7 @@ abstract class FindEntryPoints : TransformAction { } -abstract class FindRelocatedClasses : TransformAction { +abstract class FindRelocatedClasses : TransformAction { @get:InputArtifact abstract val input: File @@ -115,7 +109,7 @@ abstract class FindRelocatedClasses : TransformAction { } -abstract class FindManifests : TransformAction { +abstract class FindManifests : TransformAction { @get:InputArtifact abstract val input: File diff --git a/buildSrc/subprojects/packaging/src/main/kotlin/org/gradle/gradlebuild/packaging/ShadedJarPlugin.kt b/buildSrc/subprojects/packaging/src/main/kotlin/org/gradle/gradlebuild/packaging/ShadedJarPlugin.kt index 8fc85f071a9ca..4a4d36acb38fe 100644 --- a/buildSrc/subprojects/packaging/src/main/kotlin/org/gradle/gradlebuild/packaging/ShadedJarPlugin.kt +++ b/buildSrc/subprojects/packaging/src/main/kotlin/org/gradle/gradlebuild/packaging/ShadedJarPlugin.kt @@ -95,19 +95,19 @@ open class ShadedJarPlugin : Plugin { } } dependencies { - registerTransformAction(FindRelocatedClasses::class) { + registerTransform(FindRelocatedClasses::class) { from.attribute(artifactType, relocatedClassesAndAnalysisType) to.attribute(artifactType, relocatedClassesType) } - registerTransformAction(FindEntryPoints::class) { + registerTransform(FindEntryPoints::class) { from.attribute(artifactType, relocatedClassesAndAnalysisType) to.attribute(artifactType, entryPointsType) } - registerTransformAction(FindClassTrees::class) { + registerTransform(FindClassTrees::class) { from.attribute(artifactType, relocatedClassesAndAnalysisType) to.attribute(artifactType, classTreesType) } - registerTransformAction(FindManifests::class) { + registerTransform(FindManifests::class) { from.attribute(artifactType, relocatedClassesAndAnalysisType) to.attribute(artifactType, manifestsType) } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 5a6597cf54a11..bb28c04769b4d 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions-snapshots/gradle-5.3-20190226013556+0000-bin.zip +distributionUrl=https\://services.gradle.org/distributions-snapshots/gradle-5.3-20190226212742+0000-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/subprojects/distributions/binary-compatibility.gradle b/subprojects/distributions/binary-compatibility.gradle index 259eb72c0e267..5587bdab7d726 100644 --- a/subprojects/distributions/binary-compatibility.gradle +++ b/subprojects/distributions/binary-compatibility.gradle @@ -14,9 +14,6 @@ * limitations under the License. */ - - - import japicmp.model.JApiChangeStatus import me.champeau.gradle.japicmp.JapicmpTask import org.gradle.binarycompatibility.AcceptedApiChanges @@ -66,11 +63,11 @@ dependencies { // This transform takes the Gradle zip distribution, // and unzips the Gradle jar files that it contains in a directory - registerTransformAction(ExplodeZipAndFindJars) { + registerTransform(ExplodeZipAndFindJars) { from.attribute(ARTIFACT_TYPE, 'zip') to.attribute(ARTIFACT_TYPE, 'gradle-libs-dir') } - registerTransformAction(FindGradleClasspath) { + registerTransform(FindGradleClasspath) { from.attribute(ARTIFACT_TYPE, 'gradle-libs-dir') to.attribute(ARTIFACT_TYPE, 'gradle-classpath') } diff --git a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/resolver/FindGradleSources.kt b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/resolver/FindGradleSources.kt index 1f401e8493f0b..6990c6679e1d5 100644 --- a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/resolver/FindGradleSources.kt +++ b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/resolver/FindGradleSources.kt @@ -19,6 +19,7 @@ package org.gradle.kotlin.dsl.resolver import org.gradle.api.artifacts.transform.InputArtifact import org.gradle.api.artifacts.transform.TransformAction import org.gradle.api.artifacts.transform.TransformOutputs +import org.gradle.api.artifacts.transform.TransformParameters import org.gradle.api.tasks.PathSensitive import org.gradle.api.tasks.PathSensitivity import org.gradle.kotlin.dsl.support.unzipTo @@ -30,7 +31,7 @@ import java.io.File * a downloaded ZIP of the Gradle sources, and will return the list of main sources * subdirectories for all subprojects. */ -abstract class FindGradleSources : TransformAction { +abstract class FindGradleSources : TransformAction { @get:InputArtifact abstract val input: File @@ -59,7 +60,7 @@ abstract class FindGradleSources : TransformAction { } -abstract class UnzipDistribution : TransformAction { +abstract class UnzipDistribution : TransformAction { @get:PathSensitive(PathSensitivity.NONE) @get:InputArtifact abstract val input: File diff --git a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/resolver/SourceDistributionProvider.kt b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/resolver/SourceDistributionProvider.kt index 1bc431b8ca512..10050c3384c37 100644 --- a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/resolver/SourceDistributionProvider.kt +++ b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/resolver/SourceDistributionProvider.kt @@ -21,6 +21,7 @@ import org.gradle.api.artifacts.Dependency import org.gradle.api.artifacts.repositories.ArtifactRepository import org.gradle.api.artifacts.repositories.IvyArtifactRepository import org.gradle.api.artifacts.transform.TransformAction +import org.gradle.api.artifacts.transform.TransformParameters import org.gradle.api.artifacts.transform.TransformSpec import org.gradle.api.attributes.Attribute import org.gradle.kotlin.dsl.* @@ -69,11 +70,11 @@ class SourceDistributionResolver(val project: Project) : SourceDistributionProvi private fun registerTransforms() { - registerTransformAction { + registerTransform { from.attribute(artifactType, zipType) to.attribute(artifactType, unzippedDistributionType) } - registerTransformAction { + registerTransform { from.attribute(artifactType, unzippedDistributionType) to.attribute(artifactType, sourceDirectory) } @@ -150,8 +151,8 @@ class SourceDistributionResolver(val project: Project) : SourceDistributionProvi } private - inline fun registerTransformAction(crossinline configure: TransformSpec.() -> Unit) = - dependencies.registerTransformAction(T::class.java) { configure(it) } + inline fun > registerTransform(crossinline configure: TransformSpec.() -> Unit) = + dependencies.registerTransform(T::class.java) { configure(it) } private fun ivy(configure: IvyArtifactRepository.() -> Unit) = From b863e775563c403d0611791bd6eae3be3327826d Mon Sep 17 00:00:00 2001 From: Stefan Wolf Date: Tue, 26 Feb 2019 13:06:37 +0100 Subject: [PATCH 180/853] Simplify resolving type parameters Using Guava's TypeToken simplifies things and supports full resolution. --- .../instantiation/AbstractClassGenerator.java | 28 ++------------- ...edClassGeneratorInjectDecoratedTest.groovy | 36 ++++++++++++++++++- .../AsmBackedClassGeneratorTest.java | 14 ++++++++ 3 files changed, 52 insertions(+), 26 deletions(-) diff --git a/subprojects/model-core/src/main/java/org/gradle/internal/instantiation/AbstractClassGenerator.java b/subprojects/model-core/src/main/java/org/gradle/internal/instantiation/AbstractClassGenerator.java index fb8c853f111e1..705ded9e388a5 100644 --- a/subprojects/model-core/src/main/java/org/gradle/internal/instantiation/AbstractClassGenerator.java +++ b/subprojects/model-core/src/main/java/org/gradle/internal/instantiation/AbstractClassGenerator.java @@ -20,6 +20,7 @@ import com.google.common.collect.ImmutableSet; import com.google.common.collect.LinkedHashMultimap; import com.google.common.collect.SetMultimap; +import com.google.common.reflect.TypeToken; import groovy.lang.Closure; import groovy.lang.GroovyObject; import org.gradle.api.Action; @@ -57,9 +58,7 @@ import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Modifier; -import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; -import java.lang.reflect.TypeVariable; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; @@ -451,32 +450,11 @@ public ClassMetadata(Class type) { /** * Determines the concrete return type of the given method, resolving any type parameters. - * - *

    Note: this is only partially implemented.

    */ public MethodMetadata resolveTypeVariables(Method method) { Type returnType = method.getGenericReturnType(); - if (returnType instanceof TypeVariable) { - TypeVariable typeVar = (TypeVariable) method.getGenericReturnType(); - // TODO - need to traverse all supertypes (super class, and all inherited interface) - for (Type genericInterface : type.getGenericInterfaces()) { - if (genericInterface instanceof ParameterizedType) { - ParameterizedType parameterizedType = (ParameterizedType) genericInterface; - if (parameterizedType.getRawType().equals(method.getDeclaringClass())) { - TypeVariable>[] typeParameters = method.getDeclaringClass().getTypeParameters(); - for (int i = 0; i < typeParameters.length; i++) { - TypeVariable> typeParameter = typeParameters[i]; - if (typeParameter.getName().equals(typeVar.getName())) { - // TODO - should resolve type variables - return new MethodMetadata(method, parameterizedType.getActualTypeArguments()[i]); - } - } - } - } - } - } - // TODO - Should handle a parameterized type containing type variables - return new MethodMetadata(method, returnType); + Type resolvedReturnType = returnType instanceof Class ? returnType : TypeToken.of(type).method(method).getReturnType().getType(); + return new MethodMetadata(method, resolvedReturnType); } @Nullable diff --git a/subprojects/model-core/src/test/groovy/org/gradle/internal/instantiation/AsmBackedClassGeneratorInjectDecoratedTest.groovy b/subprojects/model-core/src/test/groovy/org/gradle/internal/instantiation/AsmBackedClassGeneratorInjectDecoratedTest.groovy index 3be02d3f4d6d9..d500da5fa4e48 100644 --- a/subprojects/model-core/src/test/groovy/org/gradle/internal/instantiation/AsmBackedClassGeneratorInjectDecoratedTest.groovy +++ b/subprojects/model-core/src/test/groovy/org/gradle/internal/instantiation/AsmBackedClassGeneratorInjectDecoratedTest.groovy @@ -29,6 +29,7 @@ import java.lang.annotation.RetentionPolicy import java.lang.reflect.ParameterizedType import java.lang.reflect.Type +import static org.gradle.internal.instantiation.AsmBackedClassGeneratorTest.AbstractClassRealizingTwoTypeParameters import static org.gradle.internal.instantiation.AsmBackedClassGeneratorTest.AbstractClassWithParameterizedTypeParameter import static org.gradle.internal.instantiation.AsmBackedClassGeneratorTest.AbstractClassWithConcreteTypeParameter import static org.gradle.internal.instantiation.AsmBackedClassGeneratorTest.FinalInjectBean @@ -84,7 +85,40 @@ class AsmBackedClassGeneratorInjectDecoratedTest extends AbstractClassGeneratorS returnType == Number } - def "can inject service using @Inject on a super interface with parameterized type parameter"() { + def "can inject services using @Inject on a super interface with type parameter remapping"() { + given: + def services = Mock(ServiceLookup) + _ * services.get(_) >> { Type type -> + if (type instanceof ParameterizedType) { + assert type.rawType == List.class + assert type.actualTypeArguments.length == 1 + assert type.actualTypeArguments[0] == String + return ["Hello", "Number"] + } + assert type == Number + return 12 + } + + when: + def obj = create(AbstractClassRealizingTwoTypeParameters, services) + + then: + obj.thing == 12 + obj.getThing() == 12 + obj.getProperty("thing") == 12 + obj.getOtherThing() == ["Hello", "Number"] + obj.doSomething() == "Hello Number 12" + + def returnType = obj.getClass().getDeclaredMethod("getThing").genericReturnType + returnType == Number.class + def otherReturnType = obj.getClass().getDeclaredMethod("getOtherThing").genericReturnType + otherReturnType instanceof ParameterizedType + otherReturnType.rawType == List + otherReturnType.actualTypeArguments.length == 1 + otherReturnType.actualTypeArguments[0] == String + } + + def "can inject service using @Inject on a super interface with parameterized type parameters"() { given: def services = Mock(ServiceLookup) _ * services.get(_) >> { Type type -> diff --git a/subprojects/model-core/src/test/groovy/org/gradle/internal/instantiation/AsmBackedClassGeneratorTest.java b/subprojects/model-core/src/test/groovy/org/gradle/internal/instantiation/AsmBackedClassGeneratorTest.java index b4a2748847747..daed2cb4676d8 100755 --- a/subprojects/model-core/src/test/groovy/org/gradle/internal/instantiation/AsmBackedClassGeneratorTest.java +++ b/subprojects/model-core/src/test/groovy/org/gradle/internal/instantiation/AsmBackedClassGeneratorTest.java @@ -15,6 +15,7 @@ */ package org.gradle.internal.instantiation; +import com.google.common.base.Joiner; import groovy.lang.Closure; import groovy.lang.GroovyObject; import groovy.lang.MissingMethodException; @@ -1839,4 +1840,17 @@ public String doSomething() { return thing.toString(); } } + + public static abstract class AbstractClassWithTwoTypeParameters implements InterfaceWithTypeParameter { + @Inject + public abstract List getOtherThing(); + } + + public static abstract class AbstractClassRealizingTwoTypeParameters extends AbstractClassWithTwoTypeParameters { + public String doSomething() { + Number thing = getThing(); + List otherThing = getOtherThing(); + return Joiner.on(" ").join(otherThing) + " " + thing; + } + } } From f3a1cfb508ce938421c47cbb6fe9115657853347 Mon Sep 17 00:00:00 2001 From: Stefan Wolf Date: Wed, 27 Feb 2019 09:00:08 +0100 Subject: [PATCH 181/853] Rebaseline GradleInceptionPerformanceTest Looks like the last rebaseline showed a small regression in `buildSrc api change in gradleBuildCurrent comparing gradle`. Rebaselining, so this test is not at the brink of failure. --- .../regression/inception/GradleInceptionPerformanceTest.groovy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subprojects/performance/src/performanceTest/groovy/org/gradle/performance/regression/inception/GradleInceptionPerformanceTest.groovy b/subprojects/performance/src/performanceTest/groovy/org/gradle/performance/regression/inception/GradleInceptionPerformanceTest.groovy index c2315550fed93..f9ca35757e9c2 100644 --- a/subprojects/performance/src/performanceTest/groovy/org/gradle/performance/regression/inception/GradleInceptionPerformanceTest.groovy +++ b/subprojects/performance/src/performanceTest/groovy/org/gradle/performance/regression/inception/GradleInceptionPerformanceTest.groovy @@ -52,7 +52,7 @@ class GradleInceptionPerformanceTest extends AbstractCrossVersionPerformanceTest } def setup() { - def targetVersion = "5.3-20190201000727+0000" + def targetVersion = "5.3-20190226212742+0000" runner.targetVersions = [targetVersion] runner.minimumVersion = targetVersion } From 526bbe76f7eb2a307ce7a96d3f06e7e67c16c78c Mon Sep 17 00:00:00 2001 From: Bo Zhang Date: Wed, 27 Feb 2019 19:27:39 +0800 Subject: [PATCH 182/853] Fix issue of TeamCity recognizing OOM in build log We had some tests outputting `GC overhead limit exceeded`, which will be recognized by TeamCity as build failure - even though these tests pass, TeamCity mark the whole build as failed. This commit fixes the issue by text replacement. --- ...DaemonPerformanceMonitoringSoakTest.groovy | 29 ++++++++++++------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/subprojects/soak/src/integTest/groovy/org/gradle/launcher/daemon/DaemonPerformanceMonitoringSoakTest.groovy b/subprojects/soak/src/integTest/groovy/org/gradle/launcher/daemon/DaemonPerformanceMonitoringSoakTest.groovy index 5d4e7df2824f1..75fb1a43649eb 100644 --- a/subprojects/soak/src/integTest/groovy/org/gradle/launcher/daemon/DaemonPerformanceMonitoringSoakTest.groovy +++ b/subprojects/soak/src/integTest/groovy/org/gradle/launcher/daemon/DaemonPerformanceMonitoringSoakTest.groovy @@ -209,19 +209,28 @@ class DaemonPerformanceMonitoringSoakTest extends DaemonMultiJdkIntegrationTest static int x static map = [:] } - State.x++ + try { + State.x++ - //simulate normal collectible objects - 5000.times { - State.map.put(it, "foo" * ${leakRate}) - } + //simulate normal collectible objects + 5000.times { + State.map.put(it, "foo" * ${leakRate}) + } - //simulate the leak - 1000.times { - State.map.put(UUID.randomUUID(), "foo" * ${leakRate}) - } + //simulate the leak + 1000.times { + State.map.put(UUID.randomUUID(), "foo" * ${leakRate}) + } - println "Build: " + State.x + println "Build: " + State.x + } catch(OutOfMemoryError e) { + if (e.message == "GC overhead limit exceeded") { + // TeamCity recognizes this message as build failures if it occurs in build log + throw new OutOfMemoryError("GC_overhead_limit_exceeded") + } else { + throw e + } + } """ } From a9540681b361e20011ec7f44755b9ad106cecb22 Mon Sep 17 00:00:00 2001 From: "Rodrigo B. de Oliveira" Date: Wed, 27 Feb 2019 09:31:20 -0300 Subject: [PATCH 183/853] Add missing $repositoriesBlock to failing tests It seems there's a regression resolving `org.jetbrains.kotlin:kotlin-scripting-compiler-embeddable:1.3.21` To be investigated further. --- .../integration/ScriptModelIntegrationTest.kt | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/subprojects/kotlin-dsl/src/integTest/kotlin/org/gradle/kotlin/dsl/integration/ScriptModelIntegrationTest.kt b/subprojects/kotlin-dsl/src/integTest/kotlin/org/gradle/kotlin/dsl/integration/ScriptModelIntegrationTest.kt index 3b19d72bbdd61..cd867a88b1638 100644 --- a/subprojects/kotlin-dsl/src/integTest/kotlin/org/gradle/kotlin/dsl/integration/ScriptModelIntegrationTest.kt +++ b/subprojects/kotlin-dsl/src/integTest/kotlin/org/gradle/kotlin/dsl/integration/ScriptModelIntegrationTest.kt @@ -66,7 +66,7 @@ abstract class ScriptModelIntegrationTest : AbstractKotlinIntegrationTest() { protected fun withMultiProjectKotlinBuildSrc(): Array { - withSettingsIn("buildSrc", """ + withDefaultSettingsIn("buildSrc").appendText(""" include(":a", ":b", ":c") """) withFile("buildSrc/build.gradle.kts", """ @@ -75,10 +75,14 @@ abstract class ScriptModelIntegrationTest : AbstractKotlinIntegrationTest() { `kotlin-dsl` apply false } - val kotlinDslProjects = listOf(project.project(":a"), project.project(":b")) + val kotlinDslProjects = listOf( + project(":a"), + project(":b") + ) - kotlinDslProjects.forEach { - it.apply(plugin = "org.gradle.kotlin.kotlin-dsl") + configure(kotlinDslProjects) { + apply(plugin = "org.gradle.kotlin.kotlin-dsl") + $repositoriesBlock } dependencies { @@ -86,6 +90,7 @@ abstract class ScriptModelIntegrationTest : AbstractKotlinIntegrationTest() { "runtime"(project(it.path)) } } + """) withFile("buildSrc/b/build.gradle.kts", """dependencies { implementation(project(":c")) }""") withFile("buildSrc/c/build.gradle.kts", "plugins { java }") @@ -94,7 +99,8 @@ abstract class ScriptModelIntegrationTest : AbstractKotlinIntegrationTest() { withMainSourceSetJavaIn("buildSrc"), withMainSourceSetJavaKotlinIn("buildSrc/a"), withMainSourceSetJavaKotlinIn("buildSrc/b"), - withMainSourceSetJavaIn("buildSrc/c")) + withMainSourceSetJavaIn("buildSrc/c") + ) } protected From 6b60eb3fd781a11aa52af2cb4d7c1c53e5ac53f6 Mon Sep 17 00:00:00 2001 From: "Rodrigo B. de Oliveira" Date: Wed, 27 Feb 2019 09:57:29 -0300 Subject: [PATCH 184/853] Introduce `prepareKotlinBuildScriptModel` task To replace `projects` as the trigger for precompiled script plugin type-safe accessor code generation tasks. --- .../dsl/plugins/precompiled/PrecompiledScriptPlugins.kt | 9 ++++++--- .../KotlinScriptingModelBuildersRegistrationAction.kt | 6 +++++- .../gradle/kotlin/dsl/provider/KotlinDslProviderMode.kt | 1 - .../kotlin/dsl/resolver/KotlinBuildScriptModelRequest.kt | 5 ++++- 4 files changed, 15 insertions(+), 6 deletions(-) diff --git a/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPlugins.kt b/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPlugins.kt index 5b623773f62d9..73213b88461ca 100644 --- a/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPlugins.kt +++ b/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPlugins.kt @@ -44,6 +44,7 @@ import org.gradle.kotlin.dsl.precompile.PrecompiledSettingsScript import org.gradle.kotlin.dsl.provider.gradleKotlinDslJarsOf import org.gradle.kotlin.dsl.provider.inClassPathMode +import org.gradle.kotlin.dsl.resolver.kotlinBuildScriptModelTask import org.gradle.plugin.devel.GradlePluginDevelopmentExtension import org.gradle.plugin.devel.plugins.JavaGradlePluginPlugin @@ -231,17 +232,19 @@ fun Project.enableScriptCompilationOf(scriptPlugins: List ) { - rootProject.tasks.named("projects" /*KotlinDslProviderMode.modelTaskName*/) { + rootProject.tasks.named(kotlinBuildScriptModelTask) { it.dependsOn(modelTask) } } diff --git a/subprojects/kotlin-dsl-tooling-builders/src/main/kotlin/org/gradle/kotlin/dsl/tooling/builders/KotlinScriptingModelBuildersRegistrationAction.kt b/subprojects/kotlin-dsl-tooling-builders/src/main/kotlin/org/gradle/kotlin/dsl/tooling/builders/KotlinScriptingModelBuildersRegistrationAction.kt index facfbb5beb659..f02bbb717630f 100644 --- a/subprojects/kotlin-dsl-tooling-builders/src/main/kotlin/org/gradle/kotlin/dsl/tooling/builders/KotlinScriptingModelBuildersRegistrationAction.kt +++ b/subprojects/kotlin-dsl-tooling-builders/src/main/kotlin/org/gradle/kotlin/dsl/tooling/builders/KotlinScriptingModelBuildersRegistrationAction.kt @@ -19,6 +19,7 @@ import org.gradle.api.internal.project.ProjectInternal import org.gradle.configuration.project.ProjectConfigureAction +import org.gradle.kotlin.dsl.resolver.kotlinBuildScriptModelTask import org.gradle.kotlin.dsl.support.serviceOf import org.gradle.tooling.provider.model.ToolingModelBuilderRegistry @@ -27,9 +28,12 @@ import org.gradle.tooling.provider.model.ToolingModelBuilderRegistry class KotlinScriptingModelBuildersRegistrationAction : ProjectConfigureAction { override fun execute(project: ProjectInternal) { - project.serviceOf().run { + project.serviceOf().apply { register(KotlinBuildScriptModelBuilder) register(KotlinBuildScriptTemplateModelBuilder) } + project.tasks.apply { + register(kotlinBuildScriptModelTask) + } } } diff --git a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/provider/KotlinDslProviderMode.kt b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/provider/KotlinDslProviderMode.kt index f4d551f635b1b..e9b371a297b81 100644 --- a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/provider/KotlinDslProviderMode.kt +++ b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/provider/KotlinDslProviderMode.kt @@ -20,7 +20,6 @@ internal object KotlinDslProviderMode { const val systemPropertyName = "org.gradle.kotlin.dsl.provider.mode" const val classPathMode = "classpath" - const val modelTaskName = "projects" } diff --git a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/resolver/KotlinBuildScriptModelRequest.kt b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/resolver/KotlinBuildScriptModelRequest.kt index 8060a54f18c19..514d62e1645cd 100644 --- a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/resolver/KotlinBuildScriptModelRequest.kt +++ b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/resolver/KotlinBuildScriptModelRequest.kt @@ -124,7 +124,7 @@ fun ProjectConnection.modelBuilderFor(request: KotlinBuildScriptModelRequest) = model(KotlinBuildScriptModel::class.java).apply { setJavaHome(request.javaHome) setJvmArguments(request.jvmOptions + modelSpecificJvmOptions) - forTasks(KotlinDslProviderMode.modelTaskName) + forTasks(kotlinBuildScriptModelTask) val arguments = request.options.toMutableList() arguments += "-P$kotlinBuildScriptModelCorrelationId=${request.correlationId}" @@ -148,6 +148,9 @@ const val kotlinBuildScriptModelTarget = "org.gradle.kotlin.dsl.provider.script" const val kotlinBuildScriptModelCorrelationId = "org.gradle.kotlin.dsl.provider.cid" +const val kotlinBuildScriptModelTask = "prepareKotlinBuildScriptModel" + + private fun connectorFor(request: KotlinBuildScriptModelRequest, projectDir: File): GradleConnector = connectorFor(projectDir, request.gradleInstallation) From da772c3265892ee58753d26ad4b12d9d00cf0aed Mon Sep 17 00:00:00 2001 From: Stefan Wolf Date: Wed, 27 Feb 2019 14:06:40 +0100 Subject: [PATCH 185/853] Fix missing callout in migrating_from_ant --- .../userguide/antMigration/multiProject/groovy/web/build.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subprojects/docs/src/samples/userguide/antMigration/multiProject/groovy/web/build.xml b/subprojects/docs/src/samples/userguide/antMigration/multiProject/groovy/web/build.xml index e03ca31506a48..faf25ec6a133d 100644 --- a/subprojects/docs/src/samples/userguide/antMigration/multiProject/groovy/web/build.xml +++ b/subprojects/docs/src/samples/userguide/antMigration/multiProject/groovy/web/build.xml @@ -7,7 +7,7 @@ - + From 4d859a3436580c2dead33104cac7c0e572c1ad36 Mon Sep 17 00:00:00 2001 From: rhart Date: Wed, 27 Feb 2019 13:15:38 +0000 Subject: [PATCH 186/853] Update supported build scan plugin to 2.2-rc-1 --- buildSrc/subprojects/profiling/profiling.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/buildSrc/subprojects/profiling/profiling.gradle.kts b/buildSrc/subprojects/profiling/profiling.gradle.kts index f2f31ff7deb9d..95bd36cd9fc7a 100644 --- a/buildSrc/subprojects/profiling/profiling.gradle.kts +++ b/buildSrc/subprojects/profiling/profiling.gradle.kts @@ -1,7 +1,7 @@ dependencies { implementation("me.champeau.gradle:jmh-gradle-plugin:0.4.8") implementation("org.jsoup:jsoup:1.11.3") - implementation("com.gradle:build-scan-plugin:2.1") + implementation("com.gradle:build-scan-plugin:2.2-rc-1-20190226165117-release") implementation(project(":configuration")) implementation(project(":kotlinDsl")) implementation(project(":plugins")) From a21b18a39f4ed0c1241f5ff392586808da11bc04 Mon Sep 17 00:00:00 2001 From: Bo Zhang Date: Wed, 27 Feb 2019 22:25:19 +0800 Subject: [PATCH 187/853] Upgrade tagging plugin to 0.52 See https://github.com/gradle/ci-health/pull/166 --- build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle.kts b/build.gradle.kts index 2f6638355830b..fd25210f41830 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -32,7 +32,7 @@ plugins { // We have to apply it here at the moment, so that when the build scan plugin is auto-applied via --scan can detect that // the plugin has been already applied. For that the plugin has to be applied with the new plugin DSL syntax. com.gradle.`build-scan` - id("org.gradle.ci.tag-single-build") version("0.50") + id("org.gradle.ci.tag-single-build") version("0.52") } defaultTasks("assemble") From 1a3f6a92d748ea6978b34a3c19cc506aef9c95bd Mon Sep 17 00:00:00 2001 From: Bo Zhang Date: Wed, 27 Feb 2019 22:25:19 +0800 Subject: [PATCH 188/853] Upgrade tagging plugin to 0.52 See https://github.com/gradle/ci-health/pull/166 --- build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle.kts b/build.gradle.kts index d6d8a558440e7..496d5413ab28b 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -32,7 +32,7 @@ plugins { // We have to apply it here at the moment, so that when the build scan plugin is auto-applied via --scan can detect that // the plugin has been already applied. For that the plugin has to be applied with the new plugin DSL syntax. com.gradle.`build-scan` - id("org.gradle.ci.tag-single-build") version("0.50") + id("org.gradle.ci.tag-single-build") version("0.52") } defaultTasks("assemble") From 2c032dac2faa9774b06c44710c24ff0c9d35c808 Mon Sep 17 00:00:00 2001 From: "Rodrigo B. de Oliveira" Date: Wed, 27 Feb 2019 12:19:50 -0300 Subject: [PATCH 189/853] Move implementation of `PrecompiledScriptPlugins` to `kotlinDslProviderPlugins` So updates to the core logic no longer require publishing a new plugin version. --- .../precompiled/PrecompiledScriptPlugins.kt | 303 +-------------- .../kotlin-dsl-provider-plugins.gradle.kts | 7 + ...mpilePrecompiledScriptPluginPluginsTest.kt | 10 +- ...KotlinDslProviderPluginsServiceRegistry.kt | 6 + .../DefaultPrecompiledScriptPluginsSupport.kt | 363 ++++++++++++++++++ .../precompiled/PrecompiledScriptPlugin.kt | 0 .../tasks/AbstractTaskExtensions.kt | 0 .../ClassPathSensitiveCodeGenerationTask.kt | 0 .../tasks/ClassPathSensitiveTask.kt | 0 .../CompilePrecompiledScriptPluginPlugins.kt | 2 - ...rePrecompiledScriptDependenciesResolver.kt | 0 .../tasks/DirectoryPropertyExtensions.kt | 0 .../ExtractPrecompiledScriptPluginPlugins.kt | 0 .../GenerateExternalPluginSpecBuilders.kt | 0 .../GenerateInternalPluginSpecBuilders.kt | 1 - ...eneratePrecompiledScriptPluginAccessors.kt | 0 .../tasks/GenerateScriptPluginAdapters.kt | 0 .../PrecompiledScriptPluginTest.kt | 0 ...tractPrecompiledScriptPluginPluginsTest.kt | 0 .../PrecompiledScriptPluginsSupport.kt | 35 ++ 20 files changed, 432 insertions(+), 295 deletions(-) rename subprojects/{kotlin-dsl-plugins => kotlin-dsl-provider-plugins}/src/integTest/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/CompilePrecompiledScriptPluginPluginsTest.kt (93%) create mode 100644 subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/DefaultPrecompiledScriptPluginsSupport.kt rename subprojects/{kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl => kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider}/plugins/precompiled/PrecompiledScriptPlugin.kt (100%) rename subprojects/{kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl => kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider}/plugins/precompiled/tasks/AbstractTaskExtensions.kt (100%) rename subprojects/{kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl => kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider}/plugins/precompiled/tasks/ClassPathSensitiveCodeGenerationTask.kt (100%) rename subprojects/{kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl => kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider}/plugins/precompiled/tasks/ClassPathSensitiveTask.kt (100%) rename subprojects/{kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl => kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider}/plugins/precompiled/tasks/CompilePrecompiledScriptPluginPlugins.kt (95%) rename subprojects/{kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl => kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider}/plugins/precompiled/tasks/ConfigurePrecompiledScriptDependenciesResolver.kt (100%) rename subprojects/{kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl => kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider}/plugins/precompiled/tasks/DirectoryPropertyExtensions.kt (100%) rename subprojects/{kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl => kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider}/plugins/precompiled/tasks/ExtractPrecompiledScriptPluginPlugins.kt (100%) rename subprojects/{kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl => kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider}/plugins/precompiled/tasks/GenerateExternalPluginSpecBuilders.kt (100%) rename subprojects/{kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl => kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider}/plugins/precompiled/tasks/GenerateInternalPluginSpecBuilders.kt (99%) rename subprojects/{kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl => kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider}/plugins/precompiled/tasks/GeneratePrecompiledScriptPluginAccessors.kt (100%) rename subprojects/{kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl => kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider}/plugins/precompiled/tasks/GenerateScriptPluginAdapters.kt (100%) rename subprojects/{kotlin-dsl-plugins => kotlin-dsl-provider-plugins}/src/test/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPluginTest.kt (100%) rename subprojects/{kotlin-dsl-plugins => kotlin-dsl-provider-plugins}/src/test/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/ExtractPrecompiledScriptPluginPluginsTest.kt (100%) create mode 100644 subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/provider/PrecompiledScriptPluginsSupport.kt diff --git a/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPlugins.kt b/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPlugins.kt index 73213b88461ca..243781b3d4361 100644 --- a/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPlugins.kt +++ b/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPlugins.kt @@ -17,324 +17,53 @@ package org.gradle.kotlin.dsl.plugins.precompiled import org.gradle.api.Plugin import org.gradle.api.Project -import org.gradle.api.Task -import org.gradle.api.file.Directory import org.gradle.api.file.SourceDirectorySet -import org.gradle.api.initialization.Settings -import org.gradle.api.invocation.Gradle -import org.gradle.api.provider.Provider - import org.gradle.api.tasks.SourceSet import org.gradle.api.tasks.SourceSetContainer -import org.gradle.api.tasks.TaskProvider import org.gradle.kotlin.dsl.* -import org.gradle.kotlin.dsl.plugins.precompiled.tasks.CompilePrecompiledScriptPluginPlugins -import org.gradle.kotlin.dsl.plugins.precompiled.tasks.ConfigurePrecompiledScriptDependenciesResolver -import org.gradle.kotlin.dsl.plugins.precompiled.tasks.ExtractPrecompiledScriptPluginPlugins -import org.gradle.kotlin.dsl.plugins.precompiled.tasks.GenerateExternalPluginSpecBuilders -import org.gradle.kotlin.dsl.plugins.precompiled.tasks.GenerateInternalPluginSpecBuilders -import org.gradle.kotlin.dsl.plugins.precompiled.tasks.GeneratePrecompiledScriptPluginAccessors -import org.gradle.kotlin.dsl.plugins.precompiled.tasks.GenerateScriptPluginAdapters -import org.gradle.kotlin.dsl.plugins.precompiled.tasks.HashedProjectSchema - -import org.gradle.kotlin.dsl.precompile.PrecompiledInitScript -import org.gradle.kotlin.dsl.precompile.PrecompiledProjectScript -import org.gradle.kotlin.dsl.precompile.PrecompiledSettingsScript - +import org.gradle.kotlin.dsl.provider.PrecompiledScriptPluginsSupport import org.gradle.kotlin.dsl.provider.gradleKotlinDslJarsOf -import org.gradle.kotlin.dsl.provider.inClassPathMode -import org.gradle.kotlin.dsl.resolver.kotlinBuildScriptModelTask - -import org.gradle.plugin.devel.GradlePluginDevelopmentExtension -import org.gradle.plugin.devel.plugins.JavaGradlePluginPlugin +import org.gradle.kotlin.dsl.support.serviceOf import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet import org.jetbrains.kotlin.gradle.tasks.KotlinCompile +import java.util.function.Consumer + /** * Exposes `*.gradle.kts` scripts from regular Kotlin source-sets as binary Gradle plugins. * - * ## Defining the plugin target - * - * Precompiled script plugins can target one of the following Gradle model types, [Gradle], [Settings] or [Project]. - * - * The target of a given script plugin is defined via its file name suffix in the following manner: - * - the `.init.gradle.kts` file name suffix defines a [Gradle] script plugin - * - the `.settings.gradle.kts` file name suffix defines a [Settings] script plugin - * - and finally, the simpler `.gradle.kts` file name suffix defines a [Project] script plugin - * - * ## Defining the plugin id - * - * The Gradle plugin id for a precompiled script plugin is defined via its file name - * plus optional package declaration in the following manner: - * - for a script without a package declaration, the plugin id is simply the file name without the - * related plugin target suffix (see above) - * - for a script containing a package declaration, the plugin id is the declared package name dot the file name without the - * related plugin target suffix (see above) - * - * For a concrete example, take the definition of a precompiled [Project] script plugin id of - * `my.project.plugin`. Given the two rules above, there are two conventional ways to do it: - * * by naming the script `my.project.plugin.gradle.kts` and including no package declaration - * * by naming the script `plugin.gradle.kts` and including a package declaration of `my.project`: - * ```kotlin - * // plugin.gradle.kts - * package my.project - * - * // ... plugin implementation ... - * ``` - * ## Applying plugins - * Precompiled script plugins can apply plugins much in the same way as regular scripts can, using one - * of the many `apply` method overloads or, in the case of [Project] scripts, via the `plugins` block. - * - * And just as regular [Project] scripts can take advantage of - * [type-safe model accessors](https://docs.gradle.org/current/userguide/kotlin_dsl.html#type-safe-accessors) - * to model elements contributed by plugins applied via the `plugins` block, so can precompiled [Project] script plugins: - * ```kotlin - * // java7-project.gradle.kts - * - * plugins { - * java - * } - * - * java { // type-safe model accessor to the `java` extension contributed by the `java` plugin - * sourceCompatibility = JavaVersion.VERSION_1_7 - * targetCompatibility = JavaVersion.VERSION_1_7 - * } - * ``` - * ## Implementation Notes - * External plugin dependencies are declared as regular artifact dependencies but a more - * semantic preserving model could be introduced in the future. - * - * ### Type-safe accessors - * The process of generating type-safe accessors for precompiled script plugins is carried out by the - * following tasks: - * - [ExtractPrecompiledScriptPluginPlugins] - extracts the `plugins` block of every precompiled script plugin and - * saves it to a file with the same name in the output directory - * - [GenerateInternalPluginSpecBuilders] - generates plugin spec builders for the _Project_ script plugins defined - * in the current module - * - [GenerateExternalPluginSpecBuilders] - generates plugin spec builders for the plugins in the compile classpath - * - [CompilePrecompiledScriptPluginPlugins] - compiles the extracted `plugins` blocks along with the internal - * and external plugin spec builders - * - [GeneratePrecompiledScriptPluginAccessors] - uses the compiled `plugins` block of each precompiled script plugin - * to compute its [HashedProjectSchema] and emit the corresponding type-safe accessors + * @see PrecompiledScriptPluginsSupport */ class PrecompiledScriptPlugins : Plugin { override fun apply(project: Project): Unit = project.run { - val scriptPlugins = collectScriptPlugins() - - enableScriptCompilationOf(scriptPlugins) - - plugins.withType { - exposeScriptsAsGradlePlugins(scriptPlugins) - } - } -} - - -private -fun Project.enableScriptCompilationOf(scriptPlugins: List) { - - dependencies { - "kotlinCompilerPluginClasspath"(gradleKotlinDslJarsOf(project)) - "kotlinCompilerPluginClasspath"(gradleApi()) - } + val compileKotlin by tasks.existing(KotlinCompile::class) - val extractedPluginsBlocks = buildDir("kotlin-dsl/plugins-blocks/extracted") - - val compiledPluginsBlocks = buildDir("kotlin-dsl/plugins-blocks/compiled") - - val generatedMetadata = buildDir("precompiled-script-plugins") - - val compileClasspath = compileClasspath() - - tasks { - - val extractPrecompiledScriptPluginPlugins by registering(ExtractPrecompiledScriptPluginPlugins::class) { - plugins = scriptPlugins - outputDir.set(extractedPluginsBlocks) - } - - val (generateInternalPluginSpecBuilders, internalPluginSpecBuilders) = - codeGenerationTask( - "internal-plugin-spec-builders", - "generateInternalPluginSpecBuilders" - ) { - plugins = scriptPlugins - sourceCodeOutputDir.set(it) - } - - val (generateExternalPluginSpecBuilders, externalPluginSpecBuilders) = - codeGenerationTask( - "external-plugin-spec-builders", - "generateExternalPluginSpecBuilders" - ) { - classPathFiles = compileClasspath - sourceCodeOutputDir.set(it) - } - - val compilePluginsBlocks by registering(CompilePrecompiledScriptPluginPlugins::class) { - - dependsOn(extractPrecompiledScriptPluginPlugins) - sourceDir(extractedPluginsBlocks) - - dependsOn(generateInternalPluginSpecBuilders) - sourceDir(internalPluginSpecBuilders) - - dependsOn(generateExternalPluginSpecBuilders) - sourceDir(externalPluginSpecBuilders) - - classPathFiles = compileClasspath - outputDir.set(compiledPluginsBlocks) - } - - val (generatePrecompiledScriptPluginAccessors, _) = - codeGenerationTask( - "accessors", - "generatePrecompiledScriptPluginAccessors" - ) { - dependsOn(compilePluginsBlocks) - classPathFiles = compileClasspath - sourceCodeOutputDir.set(it) - metadataOutputDir.set(generatedMetadata) - compiledPluginsBlocksDir.set(compiledPluginsBlocks) - plugins = scriptPlugins - } - - val configurePrecompiledScriptDependenciesResolver by registering(ConfigurePrecompiledScriptDependenciesResolver::class) { - dependsOn(generateInternalPluginSpecBuilders) - dependsOn(generateExternalPluginSpecBuilders) - inputs.files( - project.files(generatedMetadata).builtBy(generatePrecompiledScriptPluginAccessors) - ) - metadataDir.set(generatedMetadata) - } - - val compileKotlin by existing(KotlinCompile::class) { - dependsOn(configurePrecompiledScriptDependenciesResolver) - } - - configurePrecompiledScriptDependenciesResolver { - onConfigure { resolverEnvironment -> + serviceOf().enableOn( + project, + sourceSets["main"].kotlin, + compileKotlin, + Consumer { kotlinCompilerArgs -> compileKotlin.get().apply { kotlinOptions { - freeCompilerArgs += listOf( - "-script-templates", scriptTemplates, - // Propagate implicit imports and other settings - "-Xscript-resolver-environment=$resolverEnvironment" - ) + freeCompilerArgs += kotlinCompilerArgs } } } - } + ) - if (inClassPathMode()) { - registerBuildScriptModelTask( - configurePrecompiledScriptDependenciesResolver - ) + dependencies { + "kotlinCompilerPluginClasspath"(gradleKotlinDslJarsOf(project)) + "kotlinCompilerPluginClasspath"(gradleApi()) } } } -private -fun Project.registerBuildScriptModelTask( - modelTask: TaskProvider -) { - rootProject.tasks.named(kotlinBuildScriptModelTask) { - it.dependsOn(modelTask) - } -} - - -private -fun Project.compileClasspath() = sourceSets["main"].compileClasspath - - -private -val scriptTemplates by lazy { - listOf( - // treat *.settings.gradle.kts files as Settings scripts - PrecompiledSettingsScript::class.qualifiedName!!, - // treat *.init.gradle.kts files as Gradle scripts - PrecompiledInitScript::class.qualifiedName!!, - // treat *.gradle.kts files as Project scripts - PrecompiledProjectScript::class.qualifiedName!! - ).joinToString(separator = ",") -} - - -private -fun Project.exposeScriptsAsGradlePlugins(scriptPlugins: List) { - - declareScriptPlugins(scriptPlugins) - - generatePluginAdaptersFor(scriptPlugins) -} - - -private -fun Project.collectScriptPlugins(): List = - pluginSourceSet.allSource.matching { - it.include("**/*.gradle.kts") - }.map(::PrecompiledScriptPlugin) - - -private -val Project.pluginSourceSet - get() = gradlePlugin.pluginSourceSet - - -private -val Project.gradlePlugin - get() = the() - - -private -fun Project.declareScriptPlugins(scriptPlugins: List) { - - configure { - for (scriptPlugin in scriptPlugins) { - plugins.create(scriptPlugin.id) { - it.id = scriptPlugin.id - it.implementationClass = scriptPlugin.implementationClass - } - } - } -} - - -private -fun Project.generatePluginAdaptersFor(scriptPlugins: List) { - - codeGenerationTask("plugins", "generateScriptPluginAdapters") { - plugins = scriptPlugins - outputDirectory.set(it) - } -} - - -private -inline fun Project.codeGenerationTask( - purpose: String, - taskName: String, - noinline configure: T.(Provider) -> Unit -) = buildDir("generated-sources/kotlin-dsl-$purpose/kotlin").let { outputDir -> - val task = tasks.register(taskName, T::class.java) { - it.configure(outputDir) - } - sourceSets["main"].kotlin.srcDir(files(outputDir).builtBy(task)) - task to outputDir -} - - -private -fun Project.buildDir(path: String) = layout.buildDirectory.dir(path) - - private val Project.sourceSets get() = project.the() diff --git a/subprojects/kotlin-dsl-provider-plugins/kotlin-dsl-provider-plugins.gradle.kts b/subprojects/kotlin-dsl-provider-plugins/kotlin-dsl-provider-plugins.gradle.kts index 5a84699ec654c..d5a9967288054 100644 --- a/subprojects/kotlin-dsl-provider-plugins/kotlin-dsl-provider-plugins.gradle.kts +++ b/subprojects/kotlin-dsl-provider-plugins/kotlin-dsl-provider-plugins.gradle.kts @@ -34,4 +34,11 @@ dependencies { compile(project(":distributionsDependencies")) compile(project(":kotlinDsl")) + compile(project(":pluginDevelopment")) + + testImplementation(project(":kotlinDslTestFixtures")) + testImplementation(project(":plugins")) + + integTestRuntimeOnly(project(":runtimeApiInfo")) + integTestRuntimeOnly(project(":apiMetadata")) } diff --git a/subprojects/kotlin-dsl-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/CompilePrecompiledScriptPluginPluginsTest.kt b/subprojects/kotlin-dsl-provider-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/CompilePrecompiledScriptPluginPluginsTest.kt similarity index 93% rename from subprojects/kotlin-dsl-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/CompilePrecompiledScriptPluginPluginsTest.kt rename to subprojects/kotlin-dsl-provider-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/CompilePrecompiledScriptPluginPluginsTest.kt index 801f077176660..98ef9308c9403 100644 --- a/subprojects/kotlin-dsl-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/CompilePrecompiledScriptPluginPluginsTest.kt +++ b/subprojects/kotlin-dsl-provider-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/CompilePrecompiledScriptPluginPluginsTest.kt @@ -21,19 +21,21 @@ import com.nhaarman.mockito_kotlin.doReturn import com.nhaarman.mockito_kotlin.inOrder import com.nhaarman.mockito_kotlin.mock +import org.gradle.kotlin.dsl.fixtures.AbstractKotlinIntegrationTest import org.gradle.kotlin.dsl.fixtures.classLoaderFor -import org.gradle.kotlin.dsl.plugins.precompiled.AbstractPrecompiledScriptPluginTest - import org.gradle.plugin.use.PluginDependenciesSpec import org.gradle.plugin.use.PluginDependencySpec +import org.junit.Ignore + import org.junit.Test import java.net.URLClassLoader -class CompilePrecompiledScriptPluginPluginsTest : AbstractPrecompiledScriptPluginTest() { +@Ignore("wip") +class CompilePrecompiledScriptPluginPluginsTest : AbstractKotlinIntegrationTest() { @Test fun `can compile multiple source dirs`() { @@ -51,8 +53,6 @@ class CompilePrecompiledScriptPluginPluginsTest : AbstractPrecompiledScriptPlugi withBuildScript(""" - plugins { `kotlin-dsl` } - fun Project.pluginsDir(path: String) = layout.buildDirectory.dir("plugins/" + path) tasks { diff --git a/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/KotlinDslProviderPluginsServiceRegistry.kt b/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/KotlinDslProviderPluginsServiceRegistry.kt index 22bf956f468b6..398cb26b53b2c 100644 --- a/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/KotlinDslProviderPluginsServiceRegistry.kt +++ b/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/KotlinDslProviderPluginsServiceRegistry.kt @@ -19,6 +19,8 @@ package org.gradle.kotlin.dsl.provider.plugins import org.gradle.internal.service.ServiceRegistration import org.gradle.internal.service.scopes.AbstractPluginServiceRegistry +import org.gradle.kotlin.dsl.plugins.precompiled.DefaultPrecompiledScriptPluginsSupport + class KotlinDslProviderPluginsServiceRegistry : AbstractPluginServiceRegistry() { @@ -38,4 +40,8 @@ object GradleUserHomeServices { @Suppress("unused") fun createKotlinScriptBasePluginsApplicator() = DefaultKotlinScriptBasePluginsApplicator() + + @Suppress("unused") + fun createPrecompiledScriptPluginsSupport() = + DefaultPrecompiledScriptPluginsSupport() } diff --git a/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/DefaultPrecompiledScriptPluginsSupport.kt b/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/DefaultPrecompiledScriptPluginsSupport.kt new file mode 100644 index 0000000000000..821cf143a6b60 --- /dev/null +++ b/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/DefaultPrecompiledScriptPluginsSupport.kt @@ -0,0 +1,363 @@ +/* + * Copyright 2018 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.gradle.kotlin.dsl.plugins.precompiled + +import org.gradle.api.Project +import org.gradle.api.Task +import org.gradle.api.file.Directory +import org.gradle.api.file.SourceDirectorySet +import org.gradle.api.initialization.Settings +import org.gradle.api.invocation.Gradle +import org.gradle.api.provider.Provider +import org.gradle.api.tasks.SourceSetContainer +import org.gradle.api.tasks.TaskProvider + +import org.gradle.kotlin.dsl.* +import org.gradle.kotlin.dsl.plugins.precompiled.tasks.CompilePrecompiledScriptPluginPlugins +import org.gradle.kotlin.dsl.plugins.precompiled.tasks.ConfigurePrecompiledScriptDependenciesResolver +import org.gradle.kotlin.dsl.plugins.precompiled.tasks.ExtractPrecompiledScriptPluginPlugins +import org.gradle.kotlin.dsl.plugins.precompiled.tasks.GenerateExternalPluginSpecBuilders +import org.gradle.kotlin.dsl.plugins.precompiled.tasks.GenerateInternalPluginSpecBuilders +import org.gradle.kotlin.dsl.plugins.precompiled.tasks.GeneratePrecompiledScriptPluginAccessors +import org.gradle.kotlin.dsl.plugins.precompiled.tasks.GenerateScriptPluginAdapters +import org.gradle.kotlin.dsl.plugins.precompiled.tasks.HashedProjectSchema + +import org.gradle.kotlin.dsl.precompile.PrecompiledInitScript +import org.gradle.kotlin.dsl.precompile.PrecompiledProjectScript +import org.gradle.kotlin.dsl.precompile.PrecompiledSettingsScript + +import org.gradle.kotlin.dsl.provider.PrecompiledScriptPluginsSupport +import org.gradle.kotlin.dsl.provider.inClassPathMode + +import org.gradle.kotlin.dsl.resolver.kotlinBuildScriptModelTask + +import org.gradle.plugin.devel.GradlePluginDevelopmentExtension +import org.gradle.plugin.devel.plugins.JavaGradlePluginPlugin + +import java.util.function.Consumer + + +/** + * Exposes `*.gradle.kts` scripts from regular Kotlin source-sets as binary Gradle plugins. + * + * ## Defining the plugin target + * + * Precompiled script plugins can target one of the following Gradle model types, [Gradle], [Settings] or [Project]. + * + * The target of a given script plugin is defined via its file name suffix in the following manner: + * - the `.init.gradle.kts` file name suffix defines a [Gradle] script plugin + * - the `.settings.gradle.kts` file name suffix defines a [Settings] script plugin + * - and finally, the simpler `.gradle.kts` file name suffix defines a [Project] script plugin + * + * ## Defining the plugin id + * + * The Gradle plugin id for a precompiled script plugin is defined via its file name + * plus optional package declaration in the following manner: + * - for a script without a package declaration, the plugin id is simply the file name without the + * related plugin target suffix (see above) + * - for a script containing a package declaration, the plugin id is the declared package name dot the file name without the + * related plugin target suffix (see above) + * + * For a concrete example, take the definition of a precompiled [Project] script plugin id of + * `my.project.plugin`. Given the two rules above, there are two conventional ways to do it: + * * by naming the script `my.project.plugin.gradle.kts` and including no package declaration + * * by naming the script `plugin.gradle.kts` and including a package declaration of `my.project`: + * ```kotlin + * // plugin.gradle.kts + * package my.project + * + * // ... plugin implementation ... + * ``` + * ## Applying plugins + * Precompiled script plugins can apply plugins much in the same way as regular scripts can, using one + * of the many `apply` method overloads or, in the case of [Project] scripts, via the `plugins` block. + * + * And just as regular [Project] scripts can take advantage of + * [type-safe model accessors](https://docs.gradle.org/current/userguide/kotlin_dsl.html#type-safe-accessors) + * to model elements contributed by plugins applied via the `plugins` block, so can precompiled [Project] script plugins: + * ```kotlin + * // java7-project.gradle.kts + * + * plugins { + * java + * } + * + * java { // type-safe model accessor to the `java` extension contributed by the `java` plugin + * sourceCompatibility = JavaVersion.VERSION_1_7 + * targetCompatibility = JavaVersion.VERSION_1_7 + * } + * ``` + * ## Implementation Notes + * External plugin dependencies are declared as regular artifact dependencies but a more + * semantic preserving model could be introduced in the future. + * + * ### Type-safe accessors + * The process of generating type-safe accessors for precompiled script plugins is carried out by the + * following tasks: + * - [ExtractPrecompiledScriptPluginPlugins] - extracts the `plugins` block of every precompiled script plugin and + * saves it to a file with the same name in the output directory + * - [GenerateInternalPluginSpecBuilders] - generates plugin spec builders for the _Project_ script plugins defined + * in the current module + * - [GenerateExternalPluginSpecBuilders] - generates plugin spec builders for the plugins in the compile classpath + * - [CompilePrecompiledScriptPluginPlugins] - compiles the extracted `plugins` blocks along with the internal + * and external plugin spec builders + * - [GeneratePrecompiledScriptPluginAccessors] - uses the compiled `plugins` block of each precompiled script plugin + * to compute its [HashedProjectSchema] and emit the corresponding type-safe accessors + */ +class DefaultPrecompiledScriptPluginsSupport : PrecompiledScriptPluginsSupport { + + override fun enableOn( + project: Project, + kotlinSourceDirectorySet: SourceDirectorySet, + kotlinCompileTask: TaskProvider, + kotlinCompilerArgsConsumer: Consumer> + ): Unit = project.run { + + val scriptPlugins = collectScriptPlugins() + + enableScriptCompilationOf( + scriptPlugins, + kotlinCompileTask, + kotlinSourceDirectorySet, + kotlinCompilerArgsConsumer + ) + + plugins.withType { + exposeScriptsAsGradlePlugins( + scriptPlugins, + kotlinSourceDirectorySet + ) + } + } +} + + +private +fun Project.enableScriptCompilationOf( + scriptPlugins: List, + kotlinCompileTask: TaskProvider, + kotlinSourceDirectorySet: SourceDirectorySet, + kotlinCompilerArgsConsumer: Consumer> +) { + + val extractedPluginsBlocks = buildDir("kotlin-dsl/plugins-blocks/extracted") + + val compiledPluginsBlocks = buildDir("kotlin-dsl/plugins-blocks/compiled") + + val generatedMetadata = buildDir("precompiled-script-plugins") + + val compileClasspath = compileClasspath() + + tasks { + + val extractPrecompiledScriptPluginPlugins by registering(ExtractPrecompiledScriptPluginPlugins::class) { + plugins = scriptPlugins + outputDir.set(extractedPluginsBlocks) + } + + val (generateInternalPluginSpecBuilders, internalPluginSpecBuilders) = + codeGenerationTask( + "internal-plugin-spec-builders", + "generateInternalPluginSpecBuilders", + kotlinSourceDirectorySet + ) { + plugins = scriptPlugins + sourceCodeOutputDir.set(it) + } + + val (generateExternalPluginSpecBuilders, externalPluginSpecBuilders) = + codeGenerationTask( + "external-plugin-spec-builders", + "generateExternalPluginSpecBuilders", + kotlinSourceDirectorySet + ) { + classPathFiles = compileClasspath + sourceCodeOutputDir.set(it) + } + + val compilePluginsBlocks by registering(CompilePrecompiledScriptPluginPlugins::class) { + + dependsOn(extractPrecompiledScriptPluginPlugins) + sourceDir(extractedPluginsBlocks) + + dependsOn(generateInternalPluginSpecBuilders) + sourceDir(internalPluginSpecBuilders) + + dependsOn(generateExternalPluginSpecBuilders) + sourceDir(externalPluginSpecBuilders) + + classPathFiles = compileClasspath + outputDir.set(compiledPluginsBlocks) + } + + val (generatePrecompiledScriptPluginAccessors, _) = + codeGenerationTask( + "accessors", + "generatePrecompiledScriptPluginAccessors", + kotlinSourceDirectorySet + ) { + dependsOn(compilePluginsBlocks) + classPathFiles = compileClasspath + sourceCodeOutputDir.set(it) + metadataOutputDir.set(generatedMetadata) + compiledPluginsBlocksDir.set(compiledPluginsBlocks) + plugins = scriptPlugins + } + + val configurePrecompiledScriptDependenciesResolver by registering(ConfigurePrecompiledScriptDependenciesResolver::class) { + dependsOn(generateInternalPluginSpecBuilders) + dependsOn(generateExternalPluginSpecBuilders) + inputs.files( + project.files(generatedMetadata).builtBy(generatePrecompiledScriptPluginAccessors) + ) + metadataDir.set(generatedMetadata) + } + + kotlinCompileTask { + dependsOn(configurePrecompiledScriptDependenciesResolver) + } + + configurePrecompiledScriptDependenciesResolver { + onConfigure { resolverEnvironment -> + kotlinCompilerArgsConsumer.accept( + listOf( + "-script-templates", scriptTemplates, + // Propagate implicit imports and other settings + "-Xscript-resolver-environment=$resolverEnvironment" + ) + ) + } + } + + if (inClassPathMode()) { + registerBuildScriptModelTask( + configurePrecompiledScriptDependenciesResolver + ) + } + } +} + + +private +fun Project.registerBuildScriptModelTask( + modelTask: TaskProvider +) { + rootProject.tasks.named(kotlinBuildScriptModelTask) { + it.dependsOn(modelTask) + } +} + + +private +fun Project.compileClasspath() = sourceSets["main"].compileClasspath + + +private +val scriptTemplates by lazy { + listOf( + // treat *.settings.gradle.kts files as Settings scripts + PrecompiledSettingsScript::class.qualifiedName!!, + // treat *.init.gradle.kts files as Gradle scripts + PrecompiledInitScript::class.qualifiedName!!, + // treat *.gradle.kts files as Project scripts + PrecompiledProjectScript::class.qualifiedName!! + ).joinToString(separator = ",") +} + + +private +fun Project.exposeScriptsAsGradlePlugins(scriptPlugins: List, kotlinSourceDirectorySet: SourceDirectorySet) { + + declareScriptPlugins(scriptPlugins) + + generatePluginAdaptersFor(scriptPlugins, kotlinSourceDirectorySet) +} + + +private +fun Project.collectScriptPlugins(): List = + mutableListOf().apply { + pluginSourceSet.allSource.matching { + it.include("**/*.gradle.kts") + }.visit { + if (!it.isDirectory) { + // TODO: preserve it.relativePath in PrecompiledScriptPlugin + add(PrecompiledScriptPlugin(it.file)) + } + } + } + + +private +val Project.pluginSourceSet + get() = gradlePlugin.pluginSourceSet + + +private +val Project.gradlePlugin + get() = the() + + +private +fun Project.declareScriptPlugins(scriptPlugins: List) { + + configure { + for (scriptPlugin in scriptPlugins) { + plugins.create(scriptPlugin.id) { + it.id = scriptPlugin.id + it.implementationClass = scriptPlugin.implementationClass + } + } + } +} + + +private +fun Project.generatePluginAdaptersFor(scriptPlugins: List, kotlinSourceDirectorySet: SourceDirectorySet) { + + codeGenerationTask( + "plugins", + "generateScriptPluginAdapters", + kotlinSourceDirectorySet + ) { + plugins = scriptPlugins + outputDirectory.set(it) + } +} + + +private +inline fun Project.codeGenerationTask( + purpose: String, + taskName: String, + kotlinSourceDirectorySet: SourceDirectorySet, + noinline configure: T.(Provider) -> Unit +) = buildDir("generated-sources/kotlin-dsl-$purpose/kotlin").let { outputDir -> + val task = tasks.register(taskName, T::class.java) { + it.configure(outputDir) + } + kotlinSourceDirectorySet.srcDir(files(outputDir).builtBy(task)) + task to outputDir +} + + +private +fun Project.buildDir(path: String) = layout.buildDirectory.dir(path) + + +private +val Project.sourceSets + get() = project.the() diff --git a/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPlugin.kt b/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/PrecompiledScriptPlugin.kt similarity index 100% rename from subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPlugin.kt rename to subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/PrecompiledScriptPlugin.kt diff --git a/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/AbstractTaskExtensions.kt b/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/AbstractTaskExtensions.kt similarity index 100% rename from subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/AbstractTaskExtensions.kt rename to subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/AbstractTaskExtensions.kt diff --git a/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/ClassPathSensitiveCodeGenerationTask.kt b/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/ClassPathSensitiveCodeGenerationTask.kt similarity index 100% rename from subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/ClassPathSensitiveCodeGenerationTask.kt rename to subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/ClassPathSensitiveCodeGenerationTask.kt diff --git a/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/ClassPathSensitiveTask.kt b/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/ClassPathSensitiveTask.kt similarity index 100% rename from subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/ClassPathSensitiveTask.kt rename to subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/ClassPathSensitiveTask.kt diff --git a/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/CompilePrecompiledScriptPluginPlugins.kt b/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/CompilePrecompiledScriptPluginPlugins.kt similarity index 95% rename from subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/CompilePrecompiledScriptPluginPlugins.kt rename to subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/CompilePrecompiledScriptPluginPlugins.kt index f243d9f7c0df4..ac70478369f70 100644 --- a/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/CompilePrecompiledScriptPluginPlugins.kt +++ b/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/CompilePrecompiledScriptPluginPlugins.kt @@ -26,11 +26,9 @@ import org.gradle.api.tasks.PathSensitivity import org.gradle.api.tasks.TaskAction import org.gradle.kotlin.dsl.execution.scriptDefinitionFromTemplate -import org.gradle.kotlin.dsl.support.ImplicitImports import org.gradle.kotlin.dsl.support.KotlinPluginsBlock import org.gradle.kotlin.dsl.support.compileKotlinScriptModuleTo -import org.gradle.kotlin.dsl.support.serviceOf @CacheableTask diff --git a/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/ConfigurePrecompiledScriptDependenciesResolver.kt b/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/ConfigurePrecompiledScriptDependenciesResolver.kt similarity index 100% rename from subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/ConfigurePrecompiledScriptDependenciesResolver.kt rename to subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/ConfigurePrecompiledScriptDependenciesResolver.kt diff --git a/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/DirectoryPropertyExtensions.kt b/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/DirectoryPropertyExtensions.kt similarity index 100% rename from subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/DirectoryPropertyExtensions.kt rename to subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/DirectoryPropertyExtensions.kt diff --git a/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/ExtractPrecompiledScriptPluginPlugins.kt b/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/ExtractPrecompiledScriptPluginPlugins.kt similarity index 100% rename from subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/ExtractPrecompiledScriptPluginPlugins.kt rename to subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/ExtractPrecompiledScriptPluginPlugins.kt diff --git a/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/GenerateExternalPluginSpecBuilders.kt b/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/GenerateExternalPluginSpecBuilders.kt similarity index 100% rename from subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/GenerateExternalPluginSpecBuilders.kt rename to subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/GenerateExternalPluginSpecBuilders.kt diff --git a/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/GenerateInternalPluginSpecBuilders.kt b/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/GenerateInternalPluginSpecBuilders.kt similarity index 99% rename from subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/GenerateInternalPluginSpecBuilders.kt rename to subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/GenerateInternalPluginSpecBuilders.kt index d84187b0112ad..fb93fe2bfeb55 100644 --- a/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/GenerateInternalPluginSpecBuilders.kt +++ b/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/GenerateInternalPluginSpecBuilders.kt @@ -53,7 +53,6 @@ open class GenerateInternalPluginSpecBuilders : DefaultTask() { @TaskAction fun generate() { sourceCodeOutputDir.withOutputDirectory { - } } } diff --git a/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/GeneratePrecompiledScriptPluginAccessors.kt b/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/GeneratePrecompiledScriptPluginAccessors.kt similarity index 100% rename from subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/GeneratePrecompiledScriptPluginAccessors.kt rename to subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/GeneratePrecompiledScriptPluginAccessors.kt diff --git a/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/GenerateScriptPluginAdapters.kt b/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/GenerateScriptPluginAdapters.kt similarity index 100% rename from subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/GenerateScriptPluginAdapters.kt rename to subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/GenerateScriptPluginAdapters.kt diff --git a/subprojects/kotlin-dsl-plugins/src/test/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPluginTest.kt b/subprojects/kotlin-dsl-provider-plugins/src/test/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPluginTest.kt similarity index 100% rename from subprojects/kotlin-dsl-plugins/src/test/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPluginTest.kt rename to subprojects/kotlin-dsl-provider-plugins/src/test/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPluginTest.kt diff --git a/subprojects/kotlin-dsl-plugins/src/test/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/ExtractPrecompiledScriptPluginPluginsTest.kt b/subprojects/kotlin-dsl-provider-plugins/src/test/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/ExtractPrecompiledScriptPluginPluginsTest.kt similarity index 100% rename from subprojects/kotlin-dsl-plugins/src/test/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/ExtractPrecompiledScriptPluginPluginsTest.kt rename to subprojects/kotlin-dsl-provider-plugins/src/test/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/ExtractPrecompiledScriptPluginPluginsTest.kt diff --git a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/provider/PrecompiledScriptPluginsSupport.kt b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/provider/PrecompiledScriptPluginsSupport.kt new file mode 100644 index 0000000000000..c06b8ac913823 --- /dev/null +++ b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/provider/PrecompiledScriptPluginsSupport.kt @@ -0,0 +1,35 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.kotlin.dsl.provider + +import org.gradle.api.Project +import org.gradle.api.Task +import org.gradle.api.file.SourceDirectorySet +import org.gradle.api.tasks.TaskProvider + +import java.util.function.Consumer + + +interface PrecompiledScriptPluginsSupport { + + fun enableOn( + project: Project, + kotlinSourceDirectorySet: SourceDirectorySet, + kotlinCompileTask: TaskProvider, + kotlinCompilerArgsConsumer: Consumer> + ) +} From 5a6b47c0b1f946a0f8bb091c97ec68f2a51f4208 Mon Sep 17 00:00:00 2001 From: "Rodrigo B. de Oliveira" Date: Wed, 27 Feb 2019 12:26:19 -0300 Subject: [PATCH 190/853] Depend on `pluginDevelopment` with parameter names Signed-off-by: Rodrigo B. de Oliveira --- .../kotlin-dsl-provider-plugins.gradle.kts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/subprojects/kotlin-dsl-provider-plugins/kotlin-dsl-provider-plugins.gradle.kts b/subprojects/kotlin-dsl-provider-plugins/kotlin-dsl-provider-plugins.gradle.kts index d5a9967288054..8dfa80348ea97 100644 --- a/subprojects/kotlin-dsl-provider-plugins/kotlin-dsl-provider-plugins.gradle.kts +++ b/subprojects/kotlin-dsl-provider-plugins/kotlin-dsl-provider-plugins.gradle.kts @@ -27,14 +27,16 @@ gradlebuildJava { moduleType = ModuleType.CORE } -withCompileOnlyGradleApiModulesWithParameterNames(":plugins") +withCompileOnlyGradleApiModulesWithParameterNames( + ":plugins", + ":pluginDevelopment" +) dependencies { compile(project(":distributionsDependencies")) compile(project(":kotlinDsl")) - compile(project(":pluginDevelopment")) testImplementation(project(":kotlinDslTestFixtures")) testImplementation(project(":plugins")) From 874396ad1b3fd5e1344fbb0d8e0d8288060ceda7 Mon Sep 17 00:00:00 2001 From: Louis Jacomet Date: Wed, 27 Feb 2019 10:46:04 +0100 Subject: [PATCH 191/853] Add configuration capabilities to core repositories Some of the configuration capabilities were not available for core repositories like `google` or `mavenCentral`. This change adds the ability to configure such repositories, including the content filtering aspect. Fixes #8280 --- .../api/artifacts/dsl/RepositoryHandler.java | 36 +++++++++ .../dsl/DefaultRepositoryHandler.java | 10 +++ .../changes/accepted-public-api-changes.json | 16 ++++ ...ralDependencyResolveIntegrationTest.groovy | 79 +++++++++++++++++++ ...gleDependencyResolveIntegrationTest.groovy | 8 +- ...terDependencyResolveIntegrationTest.groovy | 3 + 6 files changed, 151 insertions(+), 1 deletion(-) create mode 100644 subprojects/soak/src/integTest/groovy/org/gradle/connectivity/MavenCentralDependencyResolveIntegrationTest.groovy diff --git a/subprojects/core-api/src/main/java/org/gradle/api/artifacts/dsl/RepositoryHandler.java b/subprojects/core-api/src/main/java/org/gradle/api/artifacts/dsl/RepositoryHandler.java index 0ac627037d7b0..ade8c8f5190db 100644 --- a/subprojects/core-api/src/main/java/org/gradle/api/artifacts/dsl/RepositoryHandler.java +++ b/subprojects/core-api/src/main/java/org/gradle/api/artifacts/dsl/RepositoryHandler.java @@ -182,6 +182,24 @@ public interface RepositoryHandler extends ArtifactRepositoryContainer { */ MavenArtifactRepository mavenCentral(); + /** + * Adds a repository which looks in the Maven central repository for dependencies. The URL used to access this repository is + * {@value org.gradle.api.artifacts.ArtifactRepositoryContainer#MAVEN_CENTRAL_URL}. The name of the repository is + * {@value org.gradle.api.artifacts.ArtifactRepositoryContainer#DEFAULT_MAVEN_CENTRAL_REPO_NAME}. + * + *

    Examples:

    + *
    +     * repositories {
    +     *     mavenCentral()
    +     * }
    +     * 
    + * + * @param action a configuration action + * @return the added resolver + * @since 5.3 + */ + MavenArtifactRepository mavenCentral(Action action); + /** * Adds a repository which looks in the local Maven cache for dependencies. The name of the repository is * {@value org.gradle.api.artifacts.ArtifactRepositoryContainer#DEFAULT_MAVEN_LOCAL_REPO_NAME}. @@ -223,6 +241,24 @@ public interface RepositoryHandler extends ArtifactRepositoryContainer { */ MavenArtifactRepository google(); + /** + * Adds a repository which looks in Google's Maven repository for dependencies. + *

    + * The URL used to access this repository is {@literal "https://dl.google.com/dl/android/maven2/"}. + *

    + * Examples: + *

    +     * repositories {
    +     *     google()
    +     * }
    +     * 
    + * + * @param action a configuration action + * @return the added resolver + * @since 5.3 + */ + MavenArtifactRepository google(Action action); + /** * Adds and configures a Maven repository. Newly created instance of {@code MavenArtifactRepository} is passed as an argument to the closure. * diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/dsl/DefaultRepositoryHandler.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/dsl/DefaultRepositoryHandler.java index 7a278823576fd..3d9722c354d42 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/dsl/DefaultRepositoryHandler.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/dsl/DefaultRepositoryHandler.java @@ -77,6 +77,11 @@ public MavenArtifactRepository mavenCentral() { return addRepository(repositoryFactory.createMavenCentralRepository(), DEFAULT_MAVEN_CENTRAL_REPO_NAME); } + @Override + public MavenArtifactRepository mavenCentral(Action action) { + return addRepository(repositoryFactory.createMavenCentralRepository(), DEFAULT_MAVEN_CENTRAL_REPO_NAME, action); + } + public MavenArtifactRepository jcenter() { return addRepository(repositoryFactory.createJCenterRepository(), DEFAULT_BINTRAY_JCENTER_REPO_NAME); } @@ -98,6 +103,11 @@ public MavenArtifactRepository google() { return addRepository(repositoryFactory.createGoogleRepository(), GOOGLE_REPO_NAME); } + @Override + public MavenArtifactRepository google(Action action) { + return addRepository(repositoryFactory.createGoogleRepository(), GOOGLE_REPO_NAME, action); + } + public MavenArtifactRepository maven(Action action) { return addRepository(repositoryFactory.createMavenRepository(), MAVEN_REPO_DEFAULT_NAME, action); } diff --git a/subprojects/distributions/src/changes/accepted-public-api-changes.json b/subprojects/distributions/src/changes/accepted-public-api-changes.json index b98dd4c2c7190..208689b6fb776 100644 --- a/subprojects/distributions/src/changes/accepted-public-api-changes.json +++ b/subprojects/distributions/src/changes/accepted-public-api-changes.json @@ -5,6 +5,22 @@ "member": "Method org.gradle.api.tasks.testing.Test.getForkOptionsFactory()", "acceptation": "Added injection method", "changes": [] + }, + { + "type": "org.gradle.api.artifacts.dsl.RepositoryHandler", + "member": "Method org.gradle.api.artifacts.dsl.RepositoryHandler.google(org.gradle.api.Action)", + "acceptation": "Ability to configure repository", + "changes": [ + "Method added to interface" + ] + }, + { + "type": "org.gradle.api.artifacts.dsl.RepositoryHandler", + "member": "Method org.gradle.api.artifacts.dsl.RepositoryHandler.mavenCentral(org.gradle.api.Action)", + "acceptation": "Ability to configure repository", + "changes": [ + "Method added to interface" + ] } ] } diff --git a/subprojects/soak/src/integTest/groovy/org/gradle/connectivity/MavenCentralDependencyResolveIntegrationTest.groovy b/subprojects/soak/src/integTest/groovy/org/gradle/connectivity/MavenCentralDependencyResolveIntegrationTest.groovy new file mode 100644 index 0000000000000..c6ee64a2bd8e5 --- /dev/null +++ b/subprojects/soak/src/integTest/groovy/org/gradle/connectivity/MavenCentralDependencyResolveIntegrationTest.groovy @@ -0,0 +1,79 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.gradle.connectivity + +import org.gradle.integtests.fixtures.AbstractIntegrationSpec +import org.gradle.util.Requires +import org.gradle.util.TestPrecondition + +@Requires(TestPrecondition.ONLINE) +class MavenCentralDependencyResolveIntegrationTest extends AbstractIntegrationSpec { + def "resolves a minimal dependency from Maven Central"() { + given: + buildFile << """ +repositories { + mavenCentral() + mavenCentral { // just test this syntax works. + name = "otherCentral" + content { + includeGroup 'org.test' + } + } +} + +configurations { + compile +} + +dependencies { + compile "ch.qos.logback:logback-classic:1.0.13" +} + +task check { + doLast { + def compile = configurations.compile + assert compile.resolvedConfiguration.firstLevelModuleDependencies.collect { it.name } == [ + 'ch.qos.logback:logback-classic:1.0.13', + ] + + assert compile.collect { it.name } == [ + 'logback-classic-1.0.13.jar', + 'logback-core-1.0.13.jar', + 'slf4j-api-1.7.5.jar' + ] + + assert compile.resolvedConfiguration.resolvedArtifacts.collect { it.file.name } == [ + 'logback-classic-1.0.13.jar', + 'logback-core-1.0.13.jar', + 'slf4j-api-1.7.5.jar' + ] + } +} + +task repoNames { + doLast { + println repositories*.name + } +} +""" + + expect: + succeeds "check", "repoNames" + + and: + output.contains(["MavenRepo", "otherCentral"].toString()) + } +} diff --git a/subprojects/soak/src/integTest/groovy/org/gradle/connectivity/MavenGoogleDependencyResolveIntegrationTest.groovy b/subprojects/soak/src/integTest/groovy/org/gradle/connectivity/MavenGoogleDependencyResolveIntegrationTest.groovy index 61ad6ec70940f..7618890231684 100644 --- a/subprojects/soak/src/integTest/groovy/org/gradle/connectivity/MavenGoogleDependencyResolveIntegrationTest.groovy +++ b/subprojects/soak/src/integTest/groovy/org/gradle/connectivity/MavenGoogleDependencyResolveIntegrationTest.groovy @@ -27,6 +27,12 @@ class MavenGoogleDependencyResolveIntegrationTest extends AbstractDependencyReso buildFile << """ repositories { google() + google { // just test this syntax works. + name = "otherGoogle" + content { + includeGroup 'org.sample' + } + } } """ } @@ -36,7 +42,7 @@ class MavenGoogleDependencyResolveIntegrationTest extends AbstractDependencyReso buildFile << """ task checkRepoName { doLast { - assert repositories*.name == ['Google'] + assert repositories*.name == ['Google', 'otherGoogle'] } } """ diff --git a/subprojects/soak/src/integTest/groovy/org/gradle/connectivity/MavenJcenterDependencyResolveIntegrationTest.groovy b/subprojects/soak/src/integTest/groovy/org/gradle/connectivity/MavenJcenterDependencyResolveIntegrationTest.groovy index 48be7b4592f0f..c24bb5b4ea58c 100644 --- a/subprojects/soak/src/integTest/groovy/org/gradle/connectivity/MavenJcenterDependencyResolveIntegrationTest.groovy +++ b/subprojects/soak/src/integTest/groovy/org/gradle/connectivity/MavenJcenterDependencyResolveIntegrationTest.groovy @@ -28,6 +28,9 @@ repositories { jcenter() jcenter { // just test this syntax works. name = "otherJcenter" + content { + includeGroup 'org.sample' + } } } From e05055100be53e99e69c515622c3c0de7cbae76a Mon Sep 17 00:00:00 2001 From: Louis Jacomet Date: Wed, 27 Feb 2019 10:55:53 +0100 Subject: [PATCH 192/853] Add configuration capabilities to Maven local repo Some of the configuration capabilities were not available for maven local repository. This change adds the ability to configure this repository, including the content filtering aspect. Fixes #8191 --- .../api/artifacts/dsl/RepositoryHandler.java | 26 +++++++++++++++++++ ...avenLocalRepoResolveIntegrationTest.groovy | 6 ++++- .../dsl/DefaultRepositoryHandler.java | 5 ++++ .../changes/accepted-public-api-changes.json | 8 ++++++ 4 files changed, 44 insertions(+), 1 deletion(-) diff --git a/subprojects/core-api/src/main/java/org/gradle/api/artifacts/dsl/RepositoryHandler.java b/subprojects/core-api/src/main/java/org/gradle/api/artifacts/dsl/RepositoryHandler.java index ade8c8f5190db..73da4d9b7933d 100644 --- a/subprojects/core-api/src/main/java/org/gradle/api/artifacts/dsl/RepositoryHandler.java +++ b/subprojects/core-api/src/main/java/org/gradle/api/artifacts/dsl/RepositoryHandler.java @@ -224,6 +224,32 @@ public interface RepositoryHandler extends ArtifactRepositoryContainer { */ MavenArtifactRepository mavenLocal(); + /** + * Adds a repository which looks in the local Maven cache for dependencies. The name of the repository is + * {@value org.gradle.api.artifacts.ArtifactRepositoryContainer#DEFAULT_MAVEN_LOCAL_REPO_NAME}. + * + *

    Examples:

    + *
    +     * repositories {
    +     *     mavenLocal()
    +     * }
    +     * 
    + *

    + * The location for the repository is determined as follows (in order of precedence): + *

    + *
      + *
    1. The value of system property 'maven.repo.local' if set;
    2. + *
    3. The value of element <localRepository> of ~/.m2/settings.xml if this file exists and element is set;
    4. + *
    5. The value of element <localRepository> of $M2_HOME/conf/settings.xml (where $M2_HOME is the value of the environment variable with that name) if this file exists and element is set;
    6. + *
    7. The path ~/.m2/repository.
    8. + *
    + * + * @param action a configuration action + * @return the added resolver + * @since 5.3 + */ + MavenArtifactRepository mavenLocal(Action action); + /** * Adds a repository which looks in Google's Maven repository for dependencies. *

    diff --git a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/maven/MavenLocalRepoResolveIntegrationTest.groovy b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/maven/MavenLocalRepoResolveIntegrationTest.groovy index d4e9075493ead..721261f79d618 100644 --- a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/maven/MavenLocalRepoResolveIntegrationTest.groovy +++ b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/maven/MavenLocalRepoResolveIntegrationTest.groovy @@ -27,7 +27,11 @@ class MavenLocalRepoResolveIntegrationTest extends AbstractDependencyResolutionT using m2 buildFile << """ repositories { - mavenLocal() + mavenLocal { + content { + excludeGroup 'unused' + } + } } configurations { compile } dependencies { diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/dsl/DefaultRepositoryHandler.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/dsl/DefaultRepositoryHandler.java index 3d9722c354d42..39251ebdb5e7f 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/dsl/DefaultRepositoryHandler.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/dsl/DefaultRepositoryHandler.java @@ -99,6 +99,11 @@ public MavenArtifactRepository mavenLocal() { return addRepository(repositoryFactory.createMavenLocalRepository(), DEFAULT_MAVEN_LOCAL_REPO_NAME); } + @Override + public MavenArtifactRepository mavenLocal(Action action) { + return addRepository(repositoryFactory.createMavenLocalRepository(), DEFAULT_MAVEN_LOCAL_REPO_NAME, action); + } + public MavenArtifactRepository google() { return addRepository(repositoryFactory.createGoogleRepository(), GOOGLE_REPO_NAME); } diff --git a/subprojects/distributions/src/changes/accepted-public-api-changes.json b/subprojects/distributions/src/changes/accepted-public-api-changes.json index 208689b6fb776..8bef0ae5bff4f 100644 --- a/subprojects/distributions/src/changes/accepted-public-api-changes.json +++ b/subprojects/distributions/src/changes/accepted-public-api-changes.json @@ -21,6 +21,14 @@ "changes": [ "Method added to interface" ] + }, + { + "type": "org.gradle.api.artifacts.dsl.RepositoryHandler", + "member": "Method org.gradle.api.artifacts.dsl.RepositoryHandler.mavenLocal(org.gradle.api.Action)", + "acceptation": "Ability to configure repository", + "changes": [ + "Method added to interface" + ] } ] } From 48a7c7922d04993d7997d2d24a9c7a7c7a51b39c Mon Sep 17 00:00:00 2001 From: "Rodrigo B. de Oliveira" Date: Wed, 27 Feb 2019 12:43:45 -0300 Subject: [PATCH 193/853] Bump `kotlinDslPlugins` version --- subprojects/kotlin-dsl-plugins/kotlin-dsl-plugins.gradle.kts | 2 +- subprojects/kotlin-dsl/kotlin-dsl.gradle.kts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/subprojects/kotlin-dsl-plugins/kotlin-dsl-plugins.gradle.kts b/subprojects/kotlin-dsl-plugins/kotlin-dsl-plugins.gradle.kts index 5a1e88cfba7fd..aad3b39851488 100644 --- a/subprojects/kotlin-dsl-plugins/kotlin-dsl-plugins.gradle.kts +++ b/subprojects/kotlin-dsl-plugins/kotlin-dsl-plugins.gradle.kts @@ -27,7 +27,7 @@ plugins { description = "Kotlin DSL Gradle Plugins deployed to the Plugin Portal" group = "org.gradle.kotlin" -version = "1.2.4" +version = "1.2.5" base.archivesBaseName = "plugins" diff --git a/subprojects/kotlin-dsl/kotlin-dsl.gradle.kts b/subprojects/kotlin-dsl/kotlin-dsl.gradle.kts index 7fc34780ee451..c9814829c6717 100644 --- a/subprojects/kotlin-dsl/kotlin-dsl.gradle.kts +++ b/subprojects/kotlin-dsl/kotlin-dsl.gradle.kts @@ -72,7 +72,7 @@ dependencies { // --- Enable automatic generation of API extensions ------------------- val apiExtensionsOutputDir = file("src/generated/kotlin") -val publishedKotlinDslPluginVersion = "1.2.3" // TODO:kotlin-dsl +val publishedKotlinDslPluginVersion = "1.2.4" // TODO:kotlin-dsl tasks { From a57b579ac03882d858a71f91c24a41394d08e522 Mon Sep 17 00:00:00 2001 From: Stefan Wolf Date: Wed, 27 Feb 2019 16:01:56 +0100 Subject: [PATCH 194/853] Test nested beans on transform parameters --- ...sformValuesInjectionIntegrationTest.groovy | 18 ++++++ ...nsformWithFileInputsIntegrationTest.groovy | 58 ++++++++++++++++++- .../transform/DefaultTransformer.java | 5 +- 3 files changed, 79 insertions(+), 2 deletions(-) diff --git a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformValuesInjectionIntegrationTest.groovy b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformValuesInjectionIntegrationTest.groovy index 7c3c04b6b70d6..f20f560ab17a1 100644 --- a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformValuesInjectionIntegrationTest.groovy +++ b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformValuesInjectionIntegrationTest.groovy @@ -140,9 +140,22 @@ class ArtifactTransformValuesInjectionIntegrationTest extends AbstractDependency settingsFile << """ include 'a', 'b', 'c' """ + buildFile << """ + interface NestedType { + @InputFile + RegularFileProperty getInputFile() + @OutputDirectory + DirectoryProperty getOutputDirectory() + } + + allprojects { + ext.nested = objects.newInstance(NestedType) + } + """ setupBuildWithColorTransform { params(""" extension = 'green' + nested.set(project.ext.nested) """) } buildFile << """ @@ -169,6 +182,8 @@ class ArtifactTransformValuesInjectionIntegrationTest extends AbstractDependency @PathSensitive(PathSensitivity.ABSOLUTE) @InputFiles ConfigurableFileCollection getAbsolutePathSensitivity() + @Nested + Property getNested() } void transform(TransformOutputs outputs) { @@ -188,6 +203,9 @@ class ArtifactTransformValuesInjectionIntegrationTest extends AbstractDependency failure.assertHasCause("Property 'missingInput' does not have a value specified.") failure.assertHasCause("Property 'absolutePathSensitivity' is declared to be sensitive to absolute paths. This is not allowed for cacheable transforms.") failure.assertHasCause("Property 'noPathSensitivity' is declared without path sensitivity. Properties of cacheable transforms must declare their path sensitivity.") + failure.assertHasCause("Property 'nested.outputDirectory' is annotated with unsupported annotation @OutputDirectory.") + failure.assertHasCause("Property 'nested.inputFile' is declared without path sensitivity. Properties of cacheable transforms must declare their path sensitivity.") + errorOutput.count("> Property") == 2 * 7 } def "cannot query parameters for transform without parameters"() { diff --git a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformWithFileInputsIntegrationTest.groovy b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformWithFileInputsIntegrationTest.groovy index a43d1deae3618..e3639d4342911 100644 --- a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformWithFileInputsIntegrationTest.groovy +++ b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformWithFileInputsIntegrationTest.groovy @@ -114,6 +114,62 @@ class ArtifactTransformWithFileInputsIntegrationTest extends AbstractDependencyR outputContains("result = [b.jar.green, c.jar.green]") } + def "transform can receive a file input from a nested bean on the parameter object"() { + settingsFile << """ + include 'a', 'b' + """ + setupBuildWithColorTransform { + params(""" + nestedBean.set(provider { project.ext.nestedInputFiles }) + """) + } + buildFile << """ + interface NestedInputFiles { + @InputFiles + ConfigurableFileCollection getInputFiles() + } + + allprojects { + task tool(type: FileProducer) { + output = file("build/tool-\${project.name}.jar") + } + ext.nestedInputFiles = objects.newInstance(NestedInputFiles) + nestedInputFiles.inputFiles.from(tool.output) + } + + project(':a') { + dependencies { + implementation project(':b') + } + } + + abstract class MakeGreen implements TransformAction { + interface Parameters extends TransformParameters{ + @Nested + Property getNestedBean() + } + + @InputArtifact + abstract File getInput() + + void transform(TransformOutputs outputs) { + def inputFiles = parameters.nestedBean.get().inputFiles + println "processing \${input.name} using \${inputFiles*.name}" + def output = outputs.file(input.name + ".green") + def paramContent = inputFiles.collect { it.file ? it.text : it.list().length }.join("") + output.text = input.text + paramContent + ".green" + } + } + """ + + when: + run(":a:resolve") + + then: + outputContains("processing b.jar using [tool-a.jar]") + outputContains("result = [b.jar.green]") + } + def "transform can receive a file collection containing task outputs as parameter"() { settingsFile << """ include 'a', 'b', 'c' @@ -133,7 +189,7 @@ class ArtifactTransformWithFileInputsIntegrationTest extends AbstractDependencyR implementation project(':c') } } -""" + """ when: run(":a:resolve") diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformer.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformer.java index b8c399354fe27..65631cd6f4f54 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformer.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformer.java @@ -169,7 +169,10 @@ public void visitDependencies(TaskDependencyResolveContext context) { parameterPropertyWalker.visitProperties(parameterObject, ParameterValidationContext.NOOP, new PropertyVisitor.Adapter() { @Override public void visitInputFileProperty(String propertyName, boolean optional, boolean skipWhenEmpty, @Nullable Class fileNormalizer, PropertyValue value, InputFilePropertyType filePropertyType) { - context.maybeAdd(value.call()); + Object actualValue = value.call(); + if (actualValue != null) { + context.maybeAdd(actualValue); + } } }); } From 8064c4c76372d21a511b8b281fd3499cf802e63c Mon Sep 17 00:00:00 2001 From: Paul Merlin Date: Wed, 27 Feb 2019 17:05:20 +0100 Subject: [PATCH 195/853] Update user manual & samples for type-safe accessors in precompiled script plugins Signed-off-by: Paul Merlin --- .../docs/src/docs/userguide/kotlin_dsl.adoc | 17 ++++------------- .../inBuildSrc/build.gradle.kts | 2 +- .../inBuildSrc/buildSrc/build.gradle.kts | 2 +- .../kotlin/java-library-convention.gradle.kts | 6 +++--- 4 files changed, 9 insertions(+), 18 deletions(-) diff --git a/subprojects/docs/src/docs/userguide/kotlin_dsl.adoc b/subprojects/docs/src/docs/userguide/kotlin_dsl.adoc index 39c9a02e1383f..c5166a4ff7f3e 100644 --- a/subprojects/docs/src/docs/userguide/kotlin_dsl.adoc +++ b/subprojects/docs/src/docs/userguide/kotlin_dsl.adoc @@ -210,8 +210,8 @@ The Kotlin DSL currently supports type-safe model accessors for any of the follo [IMPORTANT] ==== -Only the main project build scripts have type-safe model accessors. -Initialization scripts, settings scripts, script plugins (precompiled or otherwise) do not. +Only the main project build scripts and precompiled project script plugins have type-safe model accessors. +Initialization scripts, settings scripts, script plugins do not. These limitations will be removed in a future Gradle release. ==== @@ -281,10 +281,7 @@ Type-safe accessors are unavailable for model elements contributed by the follow * Script plugins, via `apply(from = "script-plugin.gradle.kts")` * Plugins applied via <> -You also can not use type-safe accessors in: - - * Binary Gradle plugins implemented in Kotlin - * Precompiled script plugins (see below). +You also can not use type-safe accessors in Binary Gradle plugins implemented in Kotlin. If you can't find a type-safe accessor, _fall back to using the normal API_ for the corresponding types. To do that, you need to know the names and/or types of the configured model elements. @@ -755,7 +752,7 @@ So, to apply a precompiled script plugin, you need to know its ID. That is derived from its filename (minus the `.gradle.kts` extension) and its (optional) package declaration. For example, the script `src/main/kotlin/java-library-convention.gradle.kts` would have a plugin ID of `java-library-convention` (assuming it has no package declaration). -Likewise, `src/main/kotlin/my/java-library-convention.gradle.kts` would result in a plugin ID of `my.java-library-convention` as long as it has a package declaration that matches the source directory structure. +Likewise, `src/main/kotlin/my/java-library-convention.gradle.kts` would result in a plugin ID of `my.java-library-convention` as long as it has a package declaration of `my`. To demonstrate how you can implement and use a precompiled script plugin, let's walk through an example based on a `buildSrc` project. @@ -778,12 +775,6 @@ include::sample[dir="kotlinDsl/precompiledScriptPlugins/inBuildSrc",files="build This script plugin simply applies the Java Library and Checkstyle Plugins and configures them. Note that this will actually apply the plugins to the main project, i.e. the one that applies the precompiled script plugin -[IMPORTANT] -==== -Precompiled script plugins do not get <>. -This limitation will be removed in a future Gradle release. -==== - Finally, apply the script plugin to the root project as follows: .Applying the precompiled script plugin to the main project diff --git a/subprojects/docs/src/samples/kotlinDsl/precompiledScriptPlugins/inBuildSrc/build.gradle.kts b/subprojects/docs/src/samples/kotlinDsl/precompiledScriptPlugins/inBuildSrc/build.gradle.kts index 2caff31eb61c9..1ebf38ef45435 100644 --- a/subprojects/docs/src/samples/kotlinDsl/precompiledScriptPlugins/inBuildSrc/build.gradle.kts +++ b/subprojects/docs/src/samples/kotlinDsl/precompiledScriptPlugins/inBuildSrc/build.gradle.kts @@ -1,3 +1,3 @@ plugins { - id("java-library-convention") + `java-library-convention` } diff --git a/subprojects/docs/src/samples/kotlinDsl/precompiledScriptPlugins/inBuildSrc/buildSrc/build.gradle.kts b/subprojects/docs/src/samples/kotlinDsl/precompiledScriptPlugins/inBuildSrc/buildSrc/build.gradle.kts index 244e36726277d..230ab933f25be 100644 --- a/subprojects/docs/src/samples/kotlinDsl/precompiledScriptPlugins/inBuildSrc/buildSrc/build.gradle.kts +++ b/subprojects/docs/src/samples/kotlinDsl/precompiledScriptPlugins/inBuildSrc/buildSrc/build.gradle.kts @@ -2,8 +2,8 @@ plugins { `kotlin-dsl` } -// end::apply[] repositories { jcenter() } +// end::apply[] diff --git a/subprojects/docs/src/samples/kotlinDsl/precompiledScriptPlugins/inBuildSrc/buildSrc/src/main/kotlin/java-library-convention.gradle.kts b/subprojects/docs/src/samples/kotlinDsl/precompiledScriptPlugins/inBuildSrc/buildSrc/src/main/kotlin/java-library-convention.gradle.kts index 04dfaca0a39ed..84e5adf9ea360 100644 --- a/subprojects/docs/src/samples/kotlinDsl/precompiledScriptPlugins/inBuildSrc/buildSrc/src/main/kotlin/java-library-convention.gradle.kts +++ b/subprojects/docs/src/samples/kotlinDsl/precompiledScriptPlugins/inBuildSrc/buildSrc/src/main/kotlin/java-library-convention.gradle.kts @@ -3,12 +3,12 @@ plugins { checkstyle } -configure { +java { sourceCompatibility = JavaVersion.VERSION_11 targetCompatibility = JavaVersion.VERSION_11 } -configure { +checkstyle { maxWarnings = 0 // ... } @@ -19,6 +19,6 @@ tasks.withType { } dependencies { - "testImplementation"("junit:junit:4.12") + testImplementation("junit:junit:4.12") // ... } From 3e1b4d64e5be02b2498172e45ef9be82ffc6ade3 Mon Sep 17 00:00:00 2001 From: Paul Merlin Date: Wed, 27 Feb 2019 17:14:39 +0100 Subject: [PATCH 196/853] Add :kotlinDslProviderPlugins tests to CIBuildModel Signed-off-by: Paul Merlin --- .teamcity/Gradle_Check/model/CIBuildModel.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.teamcity/Gradle_Check/model/CIBuildModel.kt b/.teamcity/Gradle_Check/model/CIBuildModel.kt index 66c72f058454f..f329f39edee36 100644 --- a/.teamcity/Gradle_Check/model/CIBuildModel.kt +++ b/.teamcity/Gradle_Check/model/CIBuildModel.kt @@ -164,7 +164,7 @@ data class CIBuildModel ( GradleSubproject("apiMetadata", unitTests = false, functionalTests = false), GradleSubproject("kotlinDsl", unitTests = true, functionalTests = true), - GradleSubproject("kotlinDslProviderPlugins", unitTests = false, functionalTests = false), + GradleSubproject("kotlinDslProviderPlugins", unitTests = true, functionalTests = true), GradleSubproject("kotlinDslToolingModels", unitTests = false, functionalTests = false), GradleSubproject("kotlinDslToolingBuilders", unitTests = true, functionalTests = true), GradleSubproject("kotlinDslPlugins", unitTests = true, functionalTests = true), From 0078fc57761902e31993fd889ccb10dc7489ee4c Mon Sep 17 00:00:00 2001 From: Paul Merlin Date: Wed, 27 Feb 2019 17:33:03 +0100 Subject: [PATCH 197/853] Refine delete help message section in release notes Signed-off-by: Paul Merlin --- subprojects/docs/src/docs/release/notes.md | 32 ++++++++++++++++++---- 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/subprojects/docs/src/docs/release/notes.md b/subprojects/docs/src/docs/release/notes.md index d2f77ca4463fe..ab022f7b274ef 100644 --- a/subprojects/docs/src/docs/release/notes.md +++ b/subprojects/docs/src/docs/release/notes.md @@ -43,6 +43,32 @@ dependencies { Long story short, this can be used to model [optional dependencies](https://github.com/gradle/gradle/issues/867)! +## Better help message on delete operation failure + +The `:clean` task, all `Delete` tasks, and `project.delete {}` operations now provide a better help message when failing to delete files. The most frequent and hard to troubleshoot causes for failing to delete files are other processes holding file descriptors open, and concurrent writes. + +The help message now displays each failed path, which may be helpful in identifying which process might be holding files open, and will also display any files that were created in the target directory after a delete failure, which may be helpful in identifying when a process is still writing to the directory. + +For example, a process holding `some.file` open in your `build` directory while running the `:clean` task would cause the following message to be displayed: + +``` +* What went wrong: +Execution failed for task ':clean'. +> Unable to delete directory '/path/to/your/gradle-project/build' + Failed to delete some children. This might happen because a process has files open or has its working directory set in the target directory. + - /path/to/your/gradle-build/subproject/build/some.file +``` + +A process still writing to your `build` directory while running the `:clean` task would display: + +``` +* What went wrong: +Execution failed for task ':clean'. +> Unable to delete directory '/path/to/your/gradle-project/build' + New files were found. This might happen because a process is still writing to the target directory. + - /path/to/your/gradle-build/subproject/build/new.file +``` + ## Improvements for plugin authors ### Use abstract types @@ -66,12 +92,6 @@ In this release, plugin authors can use the `ObjectFactory.fileCollection()` met [The Checkstyle plugin](userguide/checkstyle_plugin.html) has been upgraded to use [Checkstyle version 8.17](http://checkstyle.sourceforge.net/releasenotes.html#Release_8.17) by default. -## Better help message on delete operation failure - -The `:clean` task, all `Delete` tasks, and `project.delete {}` operations now provide a better help message when failing to delete files. The most frequent and hard to troubleshoot causes for failing to delete files are other processes holding file descriptors open, and concurrent writes. - -The help message now displays each failed path, which may be helpful in identifying which process might be holding files open, and will also display any files that were created in the target directory after a delete failure, which may be helpful in identifying when a process is still writing to the directory. - ## Promoted features Promoted features are features that were incubating in previous versions of Gradle but are now supported and subject to backwards compatibility. See the User Manual section on the “[Feature Lifecycle](userguide/feature_lifecycle.html)” for more information. From 23b92ccc3a57ea100853ff45ef23e284f883d9a3 Mon Sep 17 00:00:00 2001 From: Stefan Wolf Date: Wed, 27 Feb 2019 17:49:54 +0100 Subject: [PATCH 198/853] Improve tests for validation errors --- ...sformValuesInjectionIntegrationTest.groovy | 55 ++++++++++++------- 1 file changed, 35 insertions(+), 20 deletions(-) diff --git a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformValuesInjectionIntegrationTest.groovy b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformValuesInjectionIntegrationTest.groovy index f20f560ab17a1..9a966a17dcaef 100644 --- a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformValuesInjectionIntegrationTest.groovy +++ b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformValuesInjectionIntegrationTest.groovy @@ -138,7 +138,7 @@ class ArtifactTransformValuesInjectionIntegrationTest extends AbstractDependency def "transform parameters are validated for input output annotations"() { settingsFile << """ - include 'a', 'b', 'c' + include 'a', 'b' """ buildFile << """ interface NestedType { @@ -162,7 +162,6 @@ class ArtifactTransformValuesInjectionIntegrationTest extends AbstractDependency project(':a') { dependencies { implementation project(':b') - implementation project(':c') } } @@ -198,14 +197,15 @@ class ArtifactTransformValuesInjectionIntegrationTest extends AbstractDependency then: failure.assertThatDescription(matchesRegexp('Cannot isolate parameters MakeGreen\\$Parameters\\$Inject@.* of artifact transform MakeGreen')) failure.assertHasCause('Some problems were found with the configuration of the artifact transform parameter MakeGreen.Parameters.') - failure.assertHasCause("Property 'extension' is not annotated with an input annotation.") - failure.assertHasCause("Property 'outputDir' is annotated with unsupported annotation @OutputDirectory.") - failure.assertHasCause("Property 'missingInput' does not have a value specified.") - failure.assertHasCause("Property 'absolutePathSensitivity' is declared to be sensitive to absolute paths. This is not allowed for cacheable transforms.") - failure.assertHasCause("Property 'noPathSensitivity' is declared without path sensitivity. Properties of cacheable transforms must declare their path sensitivity.") - failure.assertHasCause("Property 'nested.outputDirectory' is annotated with unsupported annotation @OutputDirectory.") - failure.assertHasCause("Property 'nested.inputFile' is declared without path sensitivity. Properties of cacheable transforms must declare their path sensitivity.") - errorOutput.count("> Property") == 2 * 7 + assertPropertyValidationErrors( + extension: 'is not annotated with an input annotation', + outputDir: 'is annotated with unsupported annotation @OutputDirectory', + missingInput: 'does not have a value specified', + absolutePathSensitivity: 'is declared to be sensitive to absolute paths. This is not allowed for cacheable transforms', + noPathSensitivity: 'is declared without path sensitivity. Properties of cacheable transforms must declare their path sensitivity', + 'nested.outputDirectory': 'is annotated with unsupported annotation @OutputDirectory', + 'nested.inputFile': 'is declared without path sensitivity. Properties of cacheable transforms must declare their path sensitivity', + ) } def "cannot query parameters for transform without parameters"() { @@ -239,7 +239,7 @@ class ArtifactTransformValuesInjectionIntegrationTest extends AbstractDependency @Unroll def "transform parameters type cannot use annotation @#annotation.simpleName"() { settingsFile << """ - include 'a', 'b', 'c' + include 'a', 'b' """ setupBuildWithColorTransform { params(""" @@ -250,7 +250,6 @@ class ArtifactTransformValuesInjectionIntegrationTest extends AbstractDependency project(':a') { dependencies { implementation project(':b') - implementation project(':c') } } @@ -276,7 +275,7 @@ class ArtifactTransformValuesInjectionIntegrationTest extends AbstractDependency then: failure.assertThatDescription(matchesRegexp('Cannot isolate parameters MakeGreen\\$Parameters\\$Inject@.* of artifact transform MakeGreen')) failure.assertHasCause('A problem was found with the configuration of the artifact transform parameter MakeGreen.Parameters.') - failure.assertHasCause("Property 'bad' is annotated with unsupported annotation @${annotation.simpleName}.") + assertPropertyValidationErrors(bad: "is annotated with unsupported annotation @${annotation.simpleName}") where: annotation << [OutputFile, OutputFiles, OutputDirectory, OutputDirectories, Destroys, LocalState, OptionValues] @@ -381,12 +380,16 @@ class ArtifactTransformValuesInjectionIntegrationTest extends AbstractDependency then: failure.assertHasDescription('A problem occurred evaluating root project') failure.assertHasCause('Some problems were found with the configuration of MakeGreen.') - failure.assertHasCause("Property 'conflictingAnnotations' is annotated with unsupported annotation @InputFile.") - failure.assertHasCause("Property 'conflictingAnnotations' has conflicting property types declared: @InputArtifact, @InputArtifactDependencies.") - failure.assertHasCause("Property 'inputFile' is annotated with unsupported annotation @InputFile.") - failure.assertHasCause("Property 'notAnnotated' is not annotated with an input annotation.") - failure.assertHasCause("Property 'noPathSensitivity' is declared without path sensitivity. Properties of cacheable transforms must declare their path sensitivity.") - failure.assertHasCause("Property 'absolutePathSensitivityDependencies' is declared to be sensitive to absolute paths. This is not allowed for cacheable transforms.") + assertPropertyValidationErrors( + 'conflictingAnnotations': [ + 'is annotated with unsupported annotation @InputFile', + 'has conflicting property types declared: @InputArtifact, @InputArtifactDependencies' + ], + inputFile: 'is annotated with unsupported annotation @InputFile', + notAnnotated: 'is not annotated with an input annotation', + noPathSensitivity: 'is declared without path sensitivity. Properties of cacheable transforms must declare their path sensitivity', + absolutePathSensitivityDependencies: 'is declared to be sensitive to absolute paths. This is not allowed for cacheable transforms' + ) } @Unroll @@ -429,7 +432,7 @@ class ArtifactTransformValuesInjectionIntegrationTest extends AbstractDependency then: failure.assertHasDescription('A problem occurred evaluating root project') failure.assertHasCause('A problem was found with the configuration of MakeGreen.') - failure.assertHasCause("Property 'bad' is annotated with unsupported annotation @${annotation.simpleName}.") + assertPropertyValidationErrors(bad: "is annotated with unsupported annotation @${annotation.simpleName}") where: annotation << [Input, InputFile, InputDirectory, OutputFile, OutputFiles, OutputDirectory, OutputDirectories, Destroys, LocalState, OptionValues, Console, Internal] @@ -658,4 +661,16 @@ abstract class MakeGreen implements TransformAction { where: annotation << [InputArtifact, InputArtifactDependencies] } + + void assertPropertyValidationErrors(Map validationErrors) { + int count = 0 + validationErrors.each { propertyName, errorMessageOrMessages -> + def errorMessages = errorMessageOrMessages instanceof Iterable ? [*errorMessageOrMessages] : [errorMessageOrMessages] + errorMessages.each { errorMessage -> + count++ + failure.assertHasCause("Property '${propertyName}' ${errorMessage}.") + } + } + assert errorOutput.count("> Property") == count + } } From ee148a77880108fee7ffecbf4939042955117865 Mon Sep 17 00:00:00 2001 From: Paul Merlin Date: Wed, 27 Feb 2019 16:03:15 +0100 Subject: [PATCH 199/853] Kotlin DSL release notes Signed-off-by: Paul Merlin --- subprojects/docs/src/docs/release/notes.md | 54 ++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/subprojects/docs/src/docs/release/notes.md b/subprojects/docs/src/docs/release/notes.md index ab022f7b274ef..bcc989ac498b0 100644 --- a/subprojects/docs/src/docs/release/notes.md +++ b/subprojects/docs/src/docs/release/notes.md @@ -43,6 +43,60 @@ dependencies { Long story short, this can be used to model [optional dependencies](https://github.com/gradle/gradle/issues/867)! +## Kotlin DSL + +### Kotlin 1.3.21 + +The embedded Kotlin version has been upgraded to Kotlin 1.3.21. + +Please see the [Kotlin 1.3.21 announcement](https://github.com/JetBrains/kotlin/releases/tag/v1.3.21) for details. + +### Type-safe accessors in precompiled script plugins + +Starting with Gradle 5.3, Kotlin precompiled project script plugins now have type-safe accessors, just like regular project build scripts. + +For example, here is how an hypothetical plugin that sets up a Java project according to some convention would be written as a Kotlin precompiled project script plugin in `buildSrc`: + +```kotlin +// buildSrc/src/main/kotlin/my-java-convention.gradle.kts +plugins { + `java-library` + checkstyle +} + +java { + sourceCompatibility = JavaVersion.VERSION_11 + targetCompatibility = JavaVersion.VERSION_11 +} + +tasks { + withType { + options.isWarnings = true + } + checkstyleMain { + maxWarnings = 0 + } +} + +dependencies { + testImplementation("junit:junit:4.12") +} +``` + +It makes use of type-safe accessors for the `java {}` extension, the `checkstyleMain` task and the `testImplementation` configuration, all contributed by the plugins it applies (`java-library` and `checkstyle`). + +This plugin can then be applied to regular projects: + +```kotlin +// build.gradle.kts +plugins { + `my-java-convetion` +} +``` + +See the [Precompiled script plugins](userguide/kotlin_dsl.html#kotdsl:precompiled_plugins) section of the user manual for more information. + + ## Better help message on delete operation failure The `:clean` task, all `Delete` tasks, and `project.delete {}` operations now provide a better help message when failing to delete files. The most frequent and hard to troubleshoot causes for failing to delete files are other processes holding file descriptors open, and concurrent writes. From 1101f703ef6fc5cad40f354ec246262c0c9f48ba Mon Sep 17 00:00:00 2001 From: Paul Merlin Date: Wed, 27 Feb 2019 19:08:19 +0100 Subject: [PATCH 200/853] Fix integ tests after new buit-in task Signed-off-by: Paul Merlin --- .../api/tasks/DeferredTaskDefinitionIntegrationTest.groovy | 2 +- .../gradle/api/tasks/TaskDefinitionIntegrationTest.groovy | 4 +++- .../taskgraph/RuleTaskBridgingIntegrationTest.groovy | 2 +- .../api/reporting/model/ModelReportIntegrationTest.groovy | 7 +++++++ 4 files changed, 12 insertions(+), 3 deletions(-) diff --git a/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/DeferredTaskDefinitionIntegrationTest.groovy b/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/DeferredTaskDefinitionIntegrationTest.groovy index 0344c5df1d506..0751736ffe738 100644 --- a/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/DeferredTaskDefinitionIntegrationTest.groovy +++ b/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/DeferredTaskDefinitionIntegrationTest.groovy @@ -264,7 +264,7 @@ class DeferredTaskDefinitionIntegrationTest extends AbstractIntegrationSpec { gradle.buildFinished { assert configureCount == 1 - assert tasksAllCount == 13 // built in tasks + task1 + assert tasksAllCount == 14 // built in tasks + task1 } """ diff --git a/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/TaskDefinitionIntegrationTest.groovy b/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/TaskDefinitionIntegrationTest.groovy index 5742961a5d804..fcac5afbaccbf 100644 --- a/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/TaskDefinitionIntegrationTest.groovy +++ b/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/TaskDefinitionIntegrationTest.groovy @@ -522,7 +522,7 @@ class TaskDefinitionIntegrationTest extends AbstractIntegrationSpec { def schema = tasks.collectionSchema.elements.collectEntries { e -> [ e.name, e.publicType.simpleName ] } - assert schema.size() == 16 + assert schema.size() == 17 assert schema["help"] == "Help" @@ -540,6 +540,8 @@ class TaskDefinitionIntegrationTest extends AbstractIntegrationSpec { assert schema["init"] == "InitBuild" assert schema["wrapper"] == "Wrapper" + + assert schema["prepareKotlinBuildScriptModel"] == "DefaultTask" assert schema["foo"] == "Foo" assert schema["bar"] == "Foo" diff --git a/subprojects/core/src/integTest/groovy/org/gradle/execution/taskgraph/RuleTaskBridgingIntegrationTest.groovy b/subprojects/core/src/integTest/groovy/org/gradle/execution/taskgraph/RuleTaskBridgingIntegrationTest.groovy index 43f5de593640d..9e374bc21075c 100644 --- a/subprojects/core/src/integTest/groovy/org/gradle/execution/taskgraph/RuleTaskBridgingIntegrationTest.groovy +++ b/subprojects/core/src/integTest/groovy/org/gradle/execution/taskgraph/RuleTaskBridgingIntegrationTest.groovy @@ -51,7 +51,7 @@ class RuleTaskBridgingIntegrationTest extends AbstractIntegrationSpec implements then: output.contains "as map: ModelMap 'tasks'" - output.contains "as container: [task ':buildEnvironment', task ':components', task ':dependencies', task ':dependencyInsight', task ':dependentComponents', task ':help', task ':init', task ':model', task ':projects', task ':properties', task ':tasks', task ':wrapper']" + output.contains "as container: [task ':buildEnvironment', task ':components', task ':dependencies', task ':dependencyInsight', task ':dependentComponents', task ':help', task ':init', task ':model', task ':prepareKotlinBuildScriptModel', task ':projects', task ':properties', task ':tasks', task ':wrapper']" output.contains "as model element: ModelMap 'tasks'" output.contains "name: tasks" } diff --git a/subprojects/diagnostics/src/integTest/groovy/org/gradle/api/reporting/model/ModelReportIntegrationTest.groovy b/subprojects/diagnostics/src/integTest/groovy/org/gradle/api/reporting/model/ModelReportIntegrationTest.groovy index 361289808c52b..567663bfee8fd 100644 --- a/subprojects/diagnostics/src/integTest/groovy/org/gradle/api/reporting/model/ModelReportIntegrationTest.groovy +++ b/subprojects/diagnostics/src/integTest/groovy/org/gradle/api/reporting/model/ModelReportIntegrationTest.groovy @@ -40,6 +40,7 @@ class ModelReportIntegrationTest extends AbstractIntegrationSpec { help() init() model() + prepareKotlinBuildScriptModel() projects() properties() tasks() @@ -337,6 +338,12 @@ model { | Creator: \tProject..tasks.model() | Rules: ⤷ copyToTaskContainer + + prepareKotlinBuildScriptModel + | Type: \torg.gradle.api.DefaultTask + | Value: \ttask ':prepareKotlinBuildScriptModel\' + | Creator: \tProject..tasks.prepareKotlinBuildScriptModel() + | Rules: + ⤷ copyToTaskContainer + projects | Type: \torg.gradle.api.tasks.diagnostics.ProjectReportTask | Value: \ttask ':projects\' From e64fe9551d4a409a43aec21150312bb3154de13e Mon Sep 17 00:00:00 2001 From: Paul Merlin Date: Wed, 27 Feb 2019 19:08:31 +0100 Subject: [PATCH 201/853] Fix samples tests after new buit-in task Signed-off-by: Paul Merlin --- .../internalViews/softwareModelExtend-iv-model.out | 6 ++++++ .../basicRuleSourcePlugin-model-task.out | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/subprojects/docs/src/samples/customModel/internalViews/softwareModelExtend-iv-model.out b/subprojects/docs/src/samples/customModel/internalViews/softwareModelExtend-iv-model.out index 9ded9af2c68dd..5c8eb102f1619 100644 --- a/subprojects/docs/src/samples/customModel/internalViews/softwareModelExtend-iv-model.out +++ b/subprojects/docs/src/samples/customModel/internalViews/softwareModelExtend-iv-model.out @@ -93,6 +93,12 @@ Root project | Creator: Project..tasks.model() | Rules: ⤷ copyToTaskContainer + + prepareKotlinBuildScriptModel + | Type: org.gradle.api.DefaultTask + | Value: task ':prepareKotlinBuildScriptModel' + | Creator: Project..tasks.prepareKotlinBuildScriptModel() + | Rules: + ⤷ copyToTaskContainer + projects | Type: org.gradle.api.tasks.diagnostics.ProjectReportTask | Value: task ':projects' diff --git a/subprojects/docs/src/samples/modelRules/basicRuleSourcePlugin/basicRuleSourcePlugin-model-task.out b/subprojects/docs/src/samples/modelRules/basicRuleSourcePlugin/basicRuleSourcePlugin-model-task.out index 70b2e7bba6b81..1be43c8d69595 100644 --- a/subprojects/docs/src/samples/modelRules/basicRuleSourcePlugin/basicRuleSourcePlugin-model-task.out +++ b/subprojects/docs/src/samples/modelRules/basicRuleSourcePlugin/basicRuleSourcePlugin-model-task.out @@ -112,6 +112,12 @@ Root project | Creator: Project..tasks.model() | Rules: ⤷ copyToTaskContainer + + prepareKotlinBuildScriptModel + | Type: org.gradle.api.DefaultTask + | Value: task ':prepareKotlinBuildScriptModel' + | Creator: Project..tasks.prepareKotlinBuildScriptModel() + | Rules: + ⤷ copyToTaskContainer + projects | Type: org.gradle.api.tasks.diagnostics.ProjectReportTask | Value: task ':projects' From 95fca0c6e162fa0256731b40281b69fb297296f7 Mon Sep 17 00:00:00 2001 From: Paul Merlin Date: Wed, 27 Feb 2019 19:20:23 +0100 Subject: [PATCH 202/853] Fix tapi cross versions tests after new buit-in task Signed-off-by: Paul Merlin --- .../tooling/fixture/ToolingApiSpecification.groovy | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/subprojects/tooling-api/src/testFixtures/groovy/org/gradle/integtests/tooling/fixture/ToolingApiSpecification.groovy b/subprojects/tooling-api/src/testFixtures/groovy/org/gradle/integtests/tooling/fixture/ToolingApiSpecification.groovy index 0ba705f59cc17..d82c083c7cf18 100644 --- a/subprojects/tooling-api/src/testFixtures/groovy/org/gradle/integtests/tooling/fixture/ToolingApiSpecification.groovy +++ b/subprojects/tooling-api/src/testFixtures/groovy/org/gradle/integtests/tooling/fixture/ToolingApiSpecification.groovy @@ -179,9 +179,12 @@ abstract class ToolingApiSpecification extends Specification { * Returns the set of implicit task names expected for a non-root project for the target Gradle version. */ Set getImplicitTasks() { - if (targetVersion > GradleVersion.version("3.1")) { + def targetBaseVersion = GradleVersion.version(targetDist.version.baseVersion.version) + if (targetBaseVersion >= GradleVersion.version("5.3")) { + return ['buildEnvironment', 'components', 'dependencies', 'dependencyInsight', 'dependentComponents', 'help', 'projects', 'properties', 'tasks', 'model', 'prepareKotlinBuildScriptModel'] + } else if (targetVersion > GradleVersion.version("3.1")) { return ['buildEnvironment', 'components', 'dependencies', 'dependencyInsight', 'dependentComponents', 'help', 'projects', 'properties', 'tasks', 'model'] - } else if (GradleVersion.version(targetDist.version.baseVersion.version) >= GradleVersion.version("2.10")) { + } else if (targetBaseVersion >= GradleVersion.version("2.10")) { return ['buildEnvironment', 'components', 'dependencies', 'dependencyInsight', 'help', 'projects', 'properties', 'tasks', 'model'] } else { return ['components', 'dependencies', 'dependencyInsight', 'help', 'projects', 'properties', 'tasks', 'model'] From 9cc35203183247986a32f425ce70f68b07f2cb5a Mon Sep 17 00:00:00 2001 From: Paul Merlin Date: Wed, 27 Feb 2019 19:50:35 +0100 Subject: [PATCH 203/853] Revert "Add :kotlinDslProviderPlugins tests to CIBuildModel" This reverts commit 3e1b4d64e5be02b2498172e45ef9be82ffc6ade3. --- .teamcity/Gradle_Check/model/CIBuildModel.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.teamcity/Gradle_Check/model/CIBuildModel.kt b/.teamcity/Gradle_Check/model/CIBuildModel.kt index f329f39edee36..66c72f058454f 100644 --- a/.teamcity/Gradle_Check/model/CIBuildModel.kt +++ b/.teamcity/Gradle_Check/model/CIBuildModel.kt @@ -164,7 +164,7 @@ data class CIBuildModel ( GradleSubproject("apiMetadata", unitTests = false, functionalTests = false), GradleSubproject("kotlinDsl", unitTests = true, functionalTests = true), - GradleSubproject("kotlinDslProviderPlugins", unitTests = true, functionalTests = true), + GradleSubproject("kotlinDslProviderPlugins", unitTests = false, functionalTests = false), GradleSubproject("kotlinDslToolingModels", unitTests = false, functionalTests = false), GradleSubproject("kotlinDslToolingBuilders", unitTests = true, functionalTests = true), GradleSubproject("kotlinDslPlugins", unitTests = true, functionalTests = true), From 853397e86cb8f888e34d290c953cdbab12b00a1f Mon Sep 17 00:00:00 2001 From: "Rodrigo B. de Oliveira" Date: Wed, 27 Feb 2019 16:18:11 -0300 Subject: [PATCH 204/853] Set `prepareKotlinBuildScriptModel` task group explicitly --- .../KotlinScriptingModelBuildersRegistrationAction.kt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/subprojects/kotlin-dsl-tooling-builders/src/main/kotlin/org/gradle/kotlin/dsl/tooling/builders/KotlinScriptingModelBuildersRegistrationAction.kt b/subprojects/kotlin-dsl-tooling-builders/src/main/kotlin/org/gradle/kotlin/dsl/tooling/builders/KotlinScriptingModelBuildersRegistrationAction.kt index f02bbb717630f..231a8c012057e 100644 --- a/subprojects/kotlin-dsl-tooling-builders/src/main/kotlin/org/gradle/kotlin/dsl/tooling/builders/KotlinScriptingModelBuildersRegistrationAction.kt +++ b/subprojects/kotlin-dsl-tooling-builders/src/main/kotlin/org/gradle/kotlin/dsl/tooling/builders/KotlinScriptingModelBuildersRegistrationAction.kt @@ -33,7 +33,9 @@ class KotlinScriptingModelBuildersRegistrationAction : ProjectConfigureAction { register(KotlinBuildScriptTemplateModelBuilder) } project.tasks.apply { - register(kotlinBuildScriptModelTask) + register(kotlinBuildScriptModelTask) { + it.group = "other" + } } } } From 74480e84e05d5f94fb52b9561f6d7284e913b923 Mon Sep 17 00:00:00 2001 From: Gradleware Git Bot Date: Wed, 27 Feb 2019 20:32:31 +0100 Subject: [PATCH 205/853] Publish 5.3-20190227191816+0000 --- released-versions.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/released-versions.json b/released-versions.json index e1239bef37aa5..a77591a307acd 100644 --- a/released-versions.json +++ b/released-versions.json @@ -1,7 +1,7 @@ { "latestReleaseSnapshot": { - "version": "5.3-20190227025139+0000", - "buildTime": "20190227025139+0000" + "version": "5.3-20190227191816+0000", + "buildTime": "20190227191816+0000" }, "latestRc": { "version": "5.2-rc-1", From 9fe94e765516062aeec32aac34c26c05200703f7 Mon Sep 17 00:00:00 2001 From: "Rodrigo B. de Oliveira" Date: Wed, 27 Feb 2019 16:32:57 -0300 Subject: [PATCH 206/853] Update `ProjectConfigurationChildrenProgressCrossVersionSpec` To take the newly introduced `prepareKotlinBuildScriptModel` task into account. Signed-off-by: Rodrigo B. de Oliveira --- .../ProjectConfigurationChildrenProgressCrossVersionSpec.groovy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subprojects/tooling-api/src/crossVersionTest/groovy/org/gradle/integtests/tooling/r40/ProjectConfigurationChildrenProgressCrossVersionSpec.groovy b/subprojects/tooling-api/src/crossVersionTest/groovy/org/gradle/integtests/tooling/r40/ProjectConfigurationChildrenProgressCrossVersionSpec.groovy index 60aa881adf626..cf02414782581 100644 --- a/subprojects/tooling-api/src/crossVersionTest/groovy/org/gradle/integtests/tooling/r40/ProjectConfigurationChildrenProgressCrossVersionSpec.groovy +++ b/subprojects/tooling-api/src/crossVersionTest/groovy/org/gradle/integtests/tooling/r40/ProjectConfigurationChildrenProgressCrossVersionSpec.groovy @@ -116,7 +116,7 @@ class ProjectConfigurationChildrenProgressCrossVersionSpec extends ToolingApiSpe events.assertIsABuild() and: - events.operation('Configure project :').children.size() <= 5 //only 'Apply plugin org.gradle.help-tasks', maybe before/afterEvaluated and 2 delayed task registrations + events.operation('Configure project :').children.size() <= 6 //only 'Apply plugin org.gradle.help-tasks', maybe before/afterEvaluated and 3 delayed task registrations } def "generates events for applied build scripts"() { From 8eec5da7027ef1f37523b55ddc0fa8d49805392c Mon Sep 17 00:00:00 2001 From: Rene Groeschke Date: Wed, 27 Feb 2019 21:00:22 +0100 Subject: [PATCH 207/853] Update build scan plugin to 2.2 (#8644) - update version used in build scan plugin itself - update default --scan version --- buildSrc/subprojects/profiling/profiling.gradle.kts | 2 +- .../internal/autoapply/AutoAppliedBuildScanPlugin.java | 2 +- .../org/gradle/smoketests/BuildScanPluginSmokeTest.groovy | 1 + 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/buildSrc/subprojects/profiling/profiling.gradle.kts b/buildSrc/subprojects/profiling/profiling.gradle.kts index 95bd36cd9fc7a..88e766f7133b5 100644 --- a/buildSrc/subprojects/profiling/profiling.gradle.kts +++ b/buildSrc/subprojects/profiling/profiling.gradle.kts @@ -1,7 +1,7 @@ dependencies { implementation("me.champeau.gradle:jmh-gradle-plugin:0.4.8") implementation("org.jsoup:jsoup:1.11.3") - implementation("com.gradle:build-scan-plugin:2.2-rc-1-20190226165117-release") + implementation("com.gradle:build-scan-plugin:2.2") implementation(project(":configuration")) implementation(project(":kotlinDsl")) implementation(project(":plugins")) diff --git a/subprojects/core/src/main/java/org/gradle/plugin/management/internal/autoapply/AutoAppliedBuildScanPlugin.java b/subprojects/core/src/main/java/org/gradle/plugin/management/internal/autoapply/AutoAppliedBuildScanPlugin.java index b5868ce31847e..12e3f39b278a7 100644 --- a/subprojects/core/src/main/java/org/gradle/plugin/management/internal/autoapply/AutoAppliedBuildScanPlugin.java +++ b/subprojects/core/src/main/java/org/gradle/plugin/management/internal/autoapply/AutoAppliedBuildScanPlugin.java @@ -31,7 +31,7 @@ public final class AutoAppliedBuildScanPlugin { public static final PluginId ID = new DefaultPluginId("com.gradle.build-scan"); public static final String GROUP = "com.gradle"; public static final String NAME = "build-scan-plugin"; - public static final String VERSION = "2.1"; + public static final String VERSION = "2.2"; /** * Adds the {@code build-scan} plugin spec to the given {@link PluginDependenciesSpec} and returns the diff --git a/subprojects/smoke-test/src/smokeTest/groovy/org/gradle/smoketests/BuildScanPluginSmokeTest.groovy b/subprojects/smoke-test/src/smokeTest/groovy/org/gradle/smoketests/BuildScanPluginSmokeTest.groovy index 117c4579b10a7..239d7143e3855 100644 --- a/subprojects/smoke-test/src/smokeTest/groovy/org/gradle/smoketests/BuildScanPluginSmokeTest.groovy +++ b/subprojects/smoke-test/src/smokeTest/groovy/org/gradle/smoketests/BuildScanPluginSmokeTest.groovy @@ -33,6 +33,7 @@ class BuildScanPluginSmokeTest extends AbstractSmokeTest { ] private static final List SUPPORTED = [ + "2.2", "2.1", "2.0.2" ] From 05d53b8bc13fe7e811cd3d1e2d7744656f937318 Mon Sep 17 00:00:00 2001 From: Paul Merlin Date: Wed, 27 Feb 2019 21:59:48 +0100 Subject: [PATCH 208/853] Revert "Set `prepareKotlinBuildScriptModel` task group explicitly" This reverts commit 853397e86cb8f888e34d290c953cdbab12b00a1f. --- .../KotlinScriptingModelBuildersRegistrationAction.kt | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/subprojects/kotlin-dsl-tooling-builders/src/main/kotlin/org/gradle/kotlin/dsl/tooling/builders/KotlinScriptingModelBuildersRegistrationAction.kt b/subprojects/kotlin-dsl-tooling-builders/src/main/kotlin/org/gradle/kotlin/dsl/tooling/builders/KotlinScriptingModelBuildersRegistrationAction.kt index 231a8c012057e..f02bbb717630f 100644 --- a/subprojects/kotlin-dsl-tooling-builders/src/main/kotlin/org/gradle/kotlin/dsl/tooling/builders/KotlinScriptingModelBuildersRegistrationAction.kt +++ b/subprojects/kotlin-dsl-tooling-builders/src/main/kotlin/org/gradle/kotlin/dsl/tooling/builders/KotlinScriptingModelBuildersRegistrationAction.kt @@ -33,9 +33,7 @@ class KotlinScriptingModelBuildersRegistrationAction : ProjectConfigureAction { register(KotlinBuildScriptTemplateModelBuilder) } project.tasks.apply { - register(kotlinBuildScriptModelTask) { - it.group = "other" - } + register(kotlinBuildScriptModelTask) } } } From 58f54c746f3bbabcef24083771b216ad63930382 Mon Sep 17 00:00:00 2001 From: Paul Merlin Date: Wed, 27 Feb 2019 22:15:23 +0100 Subject: [PATCH 209/853] Fix TaskVisibilityCrossVersionSpec by explicitly making the Kotlin DSL model task trigger an "invisible implicit task" Signed-off-by: Paul Merlin --- .../r21/TaskVisibilityCrossVersionSpec.groovy | 4 +-- .../fixture/ToolingApiSpecification.groovy | 26 +++++++++++++++---- 2 files changed, 23 insertions(+), 7 deletions(-) diff --git a/subprojects/tooling-api/src/crossVersionTest/groovy/org/gradle/integtests/tooling/r21/TaskVisibilityCrossVersionSpec.groovy b/subprojects/tooling-api/src/crossVersionTest/groovy/org/gradle/integtests/tooling/r21/TaskVisibilityCrossVersionSpec.groovy index ac119e97bd452..5e6b395303a84 100644 --- a/subprojects/tooling-api/src/crossVersionTest/groovy/org/gradle/integtests/tooling/r21/TaskVisibilityCrossVersionSpec.groovy +++ b/subprojects/tooling-api/src/crossVersionTest/groovy/org/gradle/integtests/tooling/r21/TaskVisibilityCrossVersionSpec.groovy @@ -54,8 +54,8 @@ project(':b:c') { } def "task visibility is correct"() { - def publicTasks = rootProjectImplicitTasks + ['t2'] - def publicSelectors = rootProjectImplicitSelectors + ['t1', 't2'] + def publicTasks = rootProjectImplicitTasks - implicitInvisibleTasks + ['t2'] + def publicSelectors = rootProjectImplicitSelectors - implicitInvisibleSelectors+ ['t1', 't2'] when: BuildInvocations model = withConnection { connection -> diff --git a/subprojects/tooling-api/src/testFixtures/groovy/org/gradle/integtests/tooling/fixture/ToolingApiSpecification.groovy b/subprojects/tooling-api/src/testFixtures/groovy/org/gradle/integtests/tooling/fixture/ToolingApiSpecification.groovy index d82c083c7cf18..fe127bf680063 100644 --- a/subprojects/tooling-api/src/testFixtures/groovy/org/gradle/integtests/tooling/fixture/ToolingApiSpecification.groovy +++ b/subprojects/tooling-api/src/testFixtures/groovy/org/gradle/integtests/tooling/fixture/ToolingApiSpecification.groovy @@ -44,6 +44,7 @@ import spock.lang.Specification import static org.gradle.integtests.fixtures.RetryConditions.onIssueWithReleasedGradleVersion import static spock.lang.Retry.Mode.SETUP_FEATURE_CLEANUP + /** * A spec that executes tests against all compatible versions of tooling API consumer and testDirectoryProvider, including the current Gradle version under test. * @@ -176,15 +177,14 @@ abstract class ToolingApiSpecification extends Specification { } /** - * Returns the set of implicit task names expected for a non-root project for the target Gradle version. + * Returns the set of implicit task names expected for any project for the target Gradle version. */ Set getImplicitTasks() { - def targetBaseVersion = GradleVersion.version(targetDist.version.baseVersion.version) - if (targetBaseVersion >= GradleVersion.version("5.3")) { + if (targetVersion >= GradleVersion.version("5.3")) { return ['buildEnvironment', 'components', 'dependencies', 'dependencyInsight', 'dependentComponents', 'help', 'projects', 'properties', 'tasks', 'model', 'prepareKotlinBuildScriptModel'] } else if (targetVersion > GradleVersion.version("3.1")) { return ['buildEnvironment', 'components', 'dependencies', 'dependencyInsight', 'dependentComponents', 'help', 'projects', 'properties', 'tasks', 'model'] - } else if (targetBaseVersion >= GradleVersion.version("2.10")) { + } else if (targetVersion >= GradleVersion.version("2.10")) { return ['buildEnvironment', 'components', 'dependencies', 'dependencyInsight', 'help', 'projects', 'properties', 'tasks', 'model'] } else { return ['components', 'dependencies', 'dependencyInsight', 'help', 'projects', 'properties', 'tasks', 'model'] @@ -192,7 +192,7 @@ abstract class ToolingApiSpecification extends Specification { } /** - * Returns the set of implicit selector names expected for a non-root project for the target Gradle version. + * Returns the set of implicit selector names expected for any project for the target Gradle version. * *

    Note that in some versions the handling of implicit selectors was broken, so this method may return a different value * to {@link #getImplicitTasks()}. @@ -201,6 +201,22 @@ abstract class ToolingApiSpecification extends Specification { return getImplicitTasks() } + /** + * Returns the set of invisible implicit task names expected for any project for the target Gradle version. + */ + Set getImplicitInvisibleTasks() { + return targetVersion >= GradleVersion.version("5.3") ? ['prepareKotlinBuildScriptModel'] : [] + } + + /** + * Returns the set of invisible implicit selector names expected for any project for the target Gradle version. + * + * See {@link #getImplicitInvisibleTasks}. + */ + Set getImplicitInvisibleSelectors() { + return implicitInvisibleTasks + } + /** * Returns the set of implicit task names expected for a root project for the target Gradle version. */ From c339c0858ca7ffaedb873cba275caf63be979c91 Mon Sep 17 00:00:00 2001 From: Paul Merlin Date: Wed, 27 Feb 2019 22:18:12 +0100 Subject: [PATCH 210/853] Add missing space Signed-off-by: Paul Merlin --- .../tooling/r21/TaskVisibilityCrossVersionSpec.groovy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subprojects/tooling-api/src/crossVersionTest/groovy/org/gradle/integtests/tooling/r21/TaskVisibilityCrossVersionSpec.groovy b/subprojects/tooling-api/src/crossVersionTest/groovy/org/gradle/integtests/tooling/r21/TaskVisibilityCrossVersionSpec.groovy index 5e6b395303a84..a9db48696ca7b 100644 --- a/subprojects/tooling-api/src/crossVersionTest/groovy/org/gradle/integtests/tooling/r21/TaskVisibilityCrossVersionSpec.groovy +++ b/subprojects/tooling-api/src/crossVersionTest/groovy/org/gradle/integtests/tooling/r21/TaskVisibilityCrossVersionSpec.groovy @@ -55,7 +55,7 @@ project(':b:c') { def "task visibility is correct"() { def publicTasks = rootProjectImplicitTasks - implicitInvisibleTasks + ['t2'] - def publicSelectors = rootProjectImplicitSelectors - implicitInvisibleSelectors+ ['t1', 't2'] + def publicSelectors = rootProjectImplicitSelectors - implicitInvisibleSelectors + ['t1', 't2'] when: BuildInvocations model = withConnection { connection -> From f4e89477230ee04580634600c9f90bd461e2c42f Mon Sep 17 00:00:00 2001 From: Daniel Lacasse Date: Wed, 27 Feb 2019 16:20:43 -0500 Subject: [PATCH 211/853] Update smoke test plugin versions --- .../org/gradle/smoketests/AbstractSmokeTest.groovy | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/subprojects/smoke-test/src/smokeTest/groovy/org/gradle/smoketests/AbstractSmokeTest.groovy b/subprojects/smoke-test/src/smokeTest/groovy/org/gradle/smoketests/AbstractSmokeTest.groovy index 7303cc24f9c15..7c83a5ff9bb11 100644 --- a/subprojects/smoke-test/src/smokeTest/groovy/org/gradle/smoketests/AbstractSmokeTest.groovy +++ b/subprojects/smoke-test/src/smokeTest/groovy/org/gradle/smoketests/AbstractSmokeTest.groovy @@ -47,10 +47,10 @@ abstract class AbstractSmokeTest extends Specification { static nebulaLint = "10.4.2" // https://plugins.gradle.org/plugin/nebula.dependency-lock - static nebulaDependencyLock = Versions.of("4.9.5", "5.0.6", "6.0.0", "7.0.1", "7.1.2") + static nebulaDependencyLock = Versions.of("4.9.5", "5.0.6", "6.0.0", "7.0.1", "7.1.2", "7.3.0") // https://plugins.gradle.org/plugin/nebula.resolution-rules - static nebulaResolutionRules = "7.0.7" + static nebulaResolutionRules = "7.0.8" // https://plugins.gradle.org/plugin/com.github.johnrengelman.shadow static shadow = Versions.of("4.0.4") @@ -59,19 +59,19 @@ abstract class AbstractSmokeTest extends Specification { static asciidoctor = "1.5.9.2" // https://plugins.gradle.org/plugin/com.github.spotbugs - static spotbugs = "1.6.9" + static spotbugs = "1.6.10" // https://plugins.gradle.org/plugin/com.bmuschko.docker-java-application - static docker = "4.3.0" + static docker = "4.5.0" // https://plugins.gradle.org/plugin/com.bmuschko.tomcat static tomcat = "2.5" // https://plugins.gradle.org/plugin/io.spring.dependency-management - static springDependencyManagement = "1.0.6.RELEASE" + static springDependencyManagement = "1.0.7.RELEASE" // https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-gradle-plugin - static springBoot = "2.1.2.RELEASE" + static springBoot = "2.1.3.RELEASE" // https://developer.android.com/studio/releases/build-tools static androidTools = "28.0.3" @@ -98,7 +98,7 @@ abstract class AbstractSmokeTest extends Specification { static grgit = "3.0.0" // https://plugins.gradle.org/plugin/com.github.ben-manes.versions - static gradleVersions = "0.20.0" + static gradleVersions = "0.21.0" // https://plugins.gradle.org/plugin/org.gradle.playframework static playframework = "0.4" From 7fe339635b8240b76557e215c98cf7cee6ae901c Mon Sep 17 00:00:00 2001 From: Sterling Greene Date: Wed, 27 Feb 2019 16:29:06 -0500 Subject: [PATCH 212/853] Bump to latest nightly --- gradle/wrapper/gradle-wrapper.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 5a6597cf54a11..293542e9e1b83 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions-snapshots/gradle-5.3-20190226013556+0000-bin.zip +distributionUrl=https\://services.gradle.org/distributions-snapshots/gradle-5.3-20190227191816+0000-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists From 0402a83ca61881c19a4d522290d39cee9d874baa Mon Sep 17 00:00:00 2001 From: Adam Murdoch Date: Mon, 25 Feb 2019 10:03:15 +1100 Subject: [PATCH 213/853] Rework the validators used by the `ValidateTaskProperties` task so they use the same API to report problems as validators in other places do. --- .../AbstractValidatingProperty.java | 2 +- .../DefaultParameterValidationContext.java | 8 ++-- .../properties/PropertyValidationAccess.java | 46 ++++++++++--------- .../tasks/properties/ValidationActions.java | 18 ++++---- .../ValidatingTaskExecuterTest.groovy | 6 +-- .../NestedBeanAnnotationHandlerTest.groovy | 2 +- .../transform/DefaultTransformer.java | 8 ++-- .../reflect/ParameterValidationContext.java | 14 ++++-- .../internal/reflect/PropertyExtractor.java | 2 +- ...lidateTaskPropertiesIntegrationTest.groovy | 33 +++++++++++-- 10 files changed, 87 insertions(+), 52 deletions(-) diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/AbstractValidatingProperty.java b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/AbstractValidatingProperty.java index 0b6646eb3a204..91fb8545d535a 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/AbstractValidatingProperty.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/AbstractValidatingProperty.java @@ -37,7 +37,7 @@ public void validate(TaskValidationContext context) { Object unpacked = DeferredUtil.unpack(value.call()); if (unpacked == null) { if (!optional) { - context.recordValidationMessage(String.format("No value has been specified for property '%s'.", propertyName)); + context.visitError(String.format("No value has been specified for property '%s'.", propertyName)); } } else { validationAction.validate(propertyName, unpacked, context); diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/DefaultParameterValidationContext.java b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/DefaultParameterValidationContext.java index cde72375976c0..dd89c8179e30a 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/DefaultParameterValidationContext.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/DefaultParameterValidationContext.java @@ -29,16 +29,16 @@ public DefaultParameterValidationContext(Collection messages) { } @Override - public void recordValidationMessage(@Nullable String ownerPath, String propertyName, String message) { + public void visitError(@Nullable String ownerPath, String propertyName, String message) { if (ownerPath == null) { - recordValidationMessage("Property '" + propertyName + "' " + message + "."); + visitError("Property '" + propertyName + "' " + message + "."); } else { - recordValidationMessage("Property '" + ownerPath + '.' + propertyName + "' " + message + "."); + visitError("Property '" + ownerPath + '.' + propertyName + "' " + message + "."); } } @Override - public void recordValidationMessage(String message) { + public void visitError(String message) { messages.add(message); } } diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/PropertyValidationAccess.java b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/PropertyValidationAccess.java index 298b2d48168fe..8a21afc1e92cc 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/PropertyValidationAccess.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/PropertyValidationAccess.java @@ -60,9 +60,15 @@ public class PropertyValidationAccess { private final static Map, PropertyValidator> PROPERTY_VALIDATORS = ImmutableMap.of( Input.class, new InputOnFileTypeValidator(), - InputFiles.class, new MissingPathSensitivityValidator(), - InputFile.class, new MissingPathSensitivityValidator(), - InputDirectory.class, new MissingPathSensitivityValidator() + InputFiles.class, new MissingPathSensitivityValidator(false), + InputFile.class, new MissingPathSensitivityValidator(false), + InputDirectory.class, new MissingPathSensitivityValidator(false) + ); + private final static Map, PropertyValidator> STRICT_PROPERTY_VALIDATORS = ImmutableMap.of( + Input.class, new InputOnFileTypeValidator(), + InputFiles.class, new MissingPathSensitivityValidator(true), + InputFile.class, new MissingPathSensitivityValidator(true), + InputDirectory.class, new MissingPathSensitivityValidator(true) ); private static final PropertyValidationAccess INSTANCE = new PropertyValidationAccess(); @@ -177,12 +183,9 @@ public void visit(final Class topLevelBean, boolean stricterValidation, final for (PropertyMetadata propertyMetadata : typeMetadata.getPropertiesMetadata()) { String qualifiedPropertyName = getQualifiedPropertyName(propertyMetadata.getPropertyName()); Class propertyType = propertyMetadata.getPropertyType(); - PropertyValidator validator = PROPERTY_VALIDATORS.get(propertyType); + PropertyValidator validator = stricterValidation ? STRICT_PROPERTY_VALIDATORS.get(propertyType) : PROPERTY_VALIDATORS.get(propertyType); if (validator != null) { - String validationMessage = validator.validate(stricterValidation, propertyMetadata); - if (validationMessage != null) { - validationContext.recordValidationMessage(null, propertyMetadata.getPropertyName(), validationMessage); - } + validator.validate(null, propertyMetadata, validationContext); } if (propertyMetadata.isAnnotationPresent(Nested.class)) { TypeToken beanType = unpackProvider(propertyMetadata.getGetterMethod()); @@ -210,12 +213,13 @@ public CollectingParameterValidationContext(Class topLevelBean, Map topLevelBean, boolean stricterValidation, Map valueType = metadata.getDeclaredType(); if (File.class.isAssignableFrom(valueType) || java.nio.file.Path.class.isAssignableFrom(valueType) || FileCollection.class.isAssignableFrom(valueType)) { - return "has @Input annotation used on property of type " + valueType.getName(); + validationContext.visitError(ownerPath, metadata.getPropertyName(), "has @Input annotation used on property of type " + valueType.getName()); } - return null; } } private static class MissingPathSensitivityValidator implements PropertyValidator { + final boolean stricterValidation; + + public MissingPathSensitivityValidator(boolean stricterValidation) { + this.stricterValidation = stricterValidation; + } - @Nullable @Override - public String validate(boolean stricterValidation, PropertyMetadata metadata) { + public void validate(@Nullable String ownerPath, PropertyMetadata metadata, ParameterValidationContext validationContext) { PathSensitive pathSensitive = metadata.getAnnotation(PathSensitive.class); if (stricterValidation && pathSensitive == null) { - return "is missing a @PathSensitive annotation, defaulting to PathSensitivity.ABSOLUTE"; + validationContext.visitError(ownerPath, metadata.getPropertyName(), "is missing a @PathSensitive annotation, defaulting to PathSensitivity.ABSOLUTE"); } - return null; } } diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/ValidationActions.java b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/ValidationActions.java index 9b3fda9674fe7..fa0acd25ba033 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/ValidationActions.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/ValidationActions.java @@ -35,9 +35,9 @@ public void doValidate(String propertyName, Object value, TaskValidationContext public void doValidate(String propertyName, Object value, TaskValidationContext context) { File file = toFile(context, value); if (!file.exists()) { - context.recordValidationMessage(String.format("File '%s' specified for property '%s' does not exist.", file, propertyName)); + context.visitError(String.format("File '%s' specified for property '%s' does not exist.", file, propertyName)); } else if (!file.isFile()) { - context.recordValidationMessage(String.format("File '%s' specified for property '%s' is not a file.", file, propertyName)); + context.visitError(String.format("File '%s' specified for property '%s' is not a file.", file, propertyName)); } } }, @@ -46,9 +46,9 @@ public void doValidate(String propertyName, Object value, TaskValidationContext public void doValidate(String propertyName, Object value, TaskValidationContext context) { File directory = toDirectory(context, value); if (!directory.exists()) { - context.recordValidationMessage(String.format("Directory '%s' specified for property '%s' does not exist.", directory, propertyName)); + context.visitError(String.format("Directory '%s' specified for property '%s' does not exist.", directory, propertyName)); } else if (!directory.isDirectory()) { - context.recordValidationMessage(String.format("Directory '%s' specified for property '%s' is not a directory.", directory, propertyName)); + context.visitError(String.format("Directory '%s' specified for property '%s' is not a directory.", directory, propertyName)); } } }, @@ -58,12 +58,12 @@ public void doValidate(String propertyName, Object value, TaskValidationContext File directory = toFile(context, value); if (directory.exists()) { if (!directory.isDirectory()) { - context.recordValidationMessage(String.format("Directory '%s' specified for property '%s' is not a directory.", directory, propertyName)); + context.visitError(String.format("Directory '%s' specified for property '%s' is not a directory.", directory, propertyName)); } } else { for (File candidate = directory.getParentFile(); candidate != null && !candidate.isDirectory(); candidate = candidate.getParentFile()) { if (candidate.exists() && !candidate.isDirectory()) { - context.recordValidationMessage(String.format("Cannot write to directory '%s' specified for property '%s', as ancestor '%s' is not a directory.", directory, propertyName, candidate)); + context.visitError(String.format("Cannot write to directory '%s' specified for property '%s', as ancestor '%s' is not a directory.", directory, propertyName, candidate)); return; } } @@ -84,13 +84,13 @@ public void doValidate(String propertyName, Object value, TaskValidationContext File file = toFile(context, value); if (file.exists()) { if (file.isDirectory()) { - context.recordValidationMessage(String.format("Cannot write to file '%s' specified for property '%s' as it is a directory.", file, propertyName)); + context.visitError(String.format("Cannot write to file '%s' specified for property '%s' as it is a directory.", file, propertyName)); } // else, assume we can write to anything that exists and is not a directory } else { for (File candidate = file.getParentFile(); candidate != null && !candidate.isDirectory(); candidate = candidate.getParentFile()) { if (candidate.exists() && !candidate.isDirectory()) { - context.recordValidationMessage(String.format("Cannot write to file '%s' specified for property '%s', as ancestor '%s' is not a directory.", file, propertyName, candidate)); + context.visitError(String.format("Cannot write to file '%s' specified for property '%s', as ancestor '%s' is not a directory.", file, propertyName, candidate)); break; } } @@ -119,7 +119,7 @@ public void validate(String propertyName, Object value, TaskValidationContext co try { doValidate(propertyName, value, context); } catch (UnsupportedNotationException ignored) { - context.recordValidationMessage(String.format("Value '%s' specified for property '%s' cannot be converted to a %s.", value, propertyName, targetType)); + context.visitError(String.format("Value '%s' specified for property '%s' cannot be converted to a %s.", value, propertyName, targetType)); } } diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/execution/ValidatingTaskExecuterTest.groovy b/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/execution/ValidatingTaskExecuterTest.groovy index cefc3084d4310..fa42ccb955c54 100644 --- a/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/execution/ValidatingTaskExecuterTest.groovy +++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/execution/ValidatingTaskExecuterTest.groovy @@ -59,7 +59,7 @@ class ValidatingTaskExecuterTest extends Specification { then: 1 * task.getProject() >> project 1 * executionContext.getTaskProperties() >> taskProperties - 1 * taskProperties.validate(_) >> { TaskValidationContext context -> context.recordValidationMessage('failure') } + 1 * taskProperties.validate(_) >> { TaskValidationContext context -> context.visitError('failure') } 1 * state.setOutcome(!null as Throwable) >> { def failure = it[0] assert failure instanceof TaskValidationException @@ -78,8 +78,8 @@ class ValidatingTaskExecuterTest extends Specification { 1 * task.getProject() >> project 1 * executionContext.getTaskProperties() >> taskProperties 1 * taskProperties.validate(_) >> { TaskValidationContext context -> - context.recordValidationMessage('failure1') - context.recordValidationMessage('failure2') + context.visitError('failure1') + context.visitError('failure2') } 1 * state.setOutcome(!null as Throwable) >> { def failure = it[0] diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/properties/annotations/NestedBeanAnnotationHandlerTest.groovy b/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/properties/annotations/NestedBeanAnnotationHandlerTest.groovy index 6feef7a5462ad..9868c397638f9 100644 --- a/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/properties/annotations/NestedBeanAnnotationHandlerTest.groovy +++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/properties/annotations/NestedBeanAnnotationHandlerTest.groovy @@ -58,7 +58,7 @@ class NestedBeanAnnotationHandlerTest extends Specification { validatingSpec.validate(validationContext) then: - 1 * validationContext.recordValidationMessage("No value has been specified for property 'name'.") + 1 * validationContext.visitError("No value has been specified for property 'name'.") 0 * _ } diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformer.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformer.java index b8c399354fe27..039de0af64f65 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformer.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformer.java @@ -118,10 +118,10 @@ public DefaultTransformer( public static void validateInputFileNormalizer(String propertyName, @Nullable Class normalizer, boolean cacheable, ParameterValidationContext parameterValidationContext) { if (cacheable) { if (normalizer == AbsolutePathInputNormalizer.class) { - parameterValidationContext.recordValidationMessage(null, propertyName, "is declared to be sensitive to absolute paths. This is not allowed for cacheable transforms"); + parameterValidationContext.visitError(null, propertyName, "is declared to be sensitive to absolute paths. This is not allowed for cacheable transforms"); } if (normalizer == null) { - parameterValidationContext.recordValidationMessage(null, propertyName, "is declared without path sensitivity. Properties of cacheable transforms must declare their path sensitivity"); + parameterValidationContext.visitError(null, propertyName, "is declared without path sensitivity. Properties of cacheable transforms must declare their path sensitivity"); } } } @@ -218,7 +218,7 @@ public void visitInputProperty(String propertyName, PropertyValue value, boolean Object preparedValue = InputParameterUtils.prepareInputParameterValue(value); if (preparedValue == null && !optional) { - validationContext.recordValidationMessage(null, propertyName, "does not have a value specified"); + validationContext.visitError(null, propertyName, "does not have a value specified"); } inputParameterFingerprintsBuilder.put(propertyName, valueSnapshotter.snapshot(preparedValue)); @@ -233,7 +233,7 @@ public void visitInputProperty(String propertyName, PropertyValue value, boolean @Override public void visitOutputFileProperty(String propertyName, boolean optional, PropertyValue value, OutputFilePropertyType filePropertyType) { - validationContext.recordValidationMessage(null, propertyName, "is annotated with an output annotation"); + validationContext.visitError(null, propertyName, "is annotated with an output annotation"); } @Override diff --git a/subprojects/model-core/src/main/java/org/gradle/internal/reflect/ParameterValidationContext.java b/subprojects/model-core/src/main/java/org/gradle/internal/reflect/ParameterValidationContext.java index 89a779bafd00b..7d3c5f8d58b84 100644 --- a/subprojects/model-core/src/main/java/org/gradle/internal/reflect/ParameterValidationContext.java +++ b/subprojects/model-core/src/main/java/org/gradle/internal/reflect/ParameterValidationContext.java @@ -21,15 +21,21 @@ public interface ParameterValidationContext { ParameterValidationContext NOOP = new ParameterValidationContext() { @Override - public void recordValidationMessage(@Nullable String ownerPath, String propertyName, String message) { + public void visitError(@Nullable String ownerPath, String propertyName, String message) { } @Override - public void recordValidationMessage(String message) { + public void visitError(String message) { } }; - void recordValidationMessage(@Nullable String ownerPath, String propertyName, String message); + /** + * Visits a validation error associated with the given property. + */ + void visitError(@Nullable String ownerPath, String propertyName, String message); - void recordValidationMessage(String message); + /** + * Visits a validation error. + */ + void visitError(String message); } diff --git a/subprojects/model-core/src/main/java/org/gradle/internal/reflect/PropertyExtractor.java b/subprojects/model-core/src/main/java/org/gradle/internal/reflect/PropertyExtractor.java index bd86b726ccac7..5789638d8e606 100644 --- a/subprojects/model-core/src/main/java/org/gradle/internal/reflect/PropertyExtractor.java +++ b/subprojects/model-core/src/main/java/org/gradle/internal/reflect/PropertyExtractor.java @@ -299,7 +299,7 @@ public void validationMessage(String message) { validationProblems.add(new ValidationProblem() { @Override public void collect(@Nullable String ownerPropertyPath, ParameterValidationContext validationContext) { - validationContext.recordValidationMessage(ownerPropertyPath, fieldName, message); + validationContext.visitError(ownerPropertyPath, fieldName, message); } }); } diff --git a/subprojects/plugin-development/src/integTest/groovy/org/gradle/plugin/devel/tasks/ValidateTaskPropertiesIntegrationTest.groovy b/subprojects/plugin-development/src/integTest/groovy/org/gradle/plugin/devel/tasks/ValidateTaskPropertiesIntegrationTest.groovy index e5044767a444a..eb4c1b0870d7f 100644 --- a/subprojects/plugin-development/src/integTest/groovy/org/gradle/plugin/devel/tasks/ValidateTaskPropertiesIntegrationTest.groovy +++ b/subprojects/plugin-development/src/integTest/groovy/org/gradle/plugin/devel/tasks/ValidateTaskPropertiesIntegrationTest.groovy @@ -352,6 +352,8 @@ class ValidateTaskPropertiesIntegrationTest extends AbstractIntegrationSpec { file("src/main/java/MyTask.java") << """ import org.gradle.api.*; import org.gradle.api.tasks.*; + import java.util.Set; + import java.util.Collections; import java.io.File; @CacheableTask @@ -393,6 +395,16 @@ class ValidateTaskPropertiesIntegrationTest extends AbstractIntegrationSpec { public File getInputDirectory() { return new File("inputDir"); } + + @InputFile + public File getInputFile() { + return new File("inputFile"); + } + + @InputFiles + public Set getInputFiles() { + return Collections.emptySet(); + } @Input public File getFile() { @@ -412,6 +424,8 @@ class ValidateTaskPropertiesIntegrationTest extends AbstractIntegrationSpec { Warning: Task type 'MyTask': property 'badTime' is not annotated with an input or output annotation. Warning: Task type 'MyTask': property 'file' has @Input annotation used on property of type java.io.File. Warning: Task type 'MyTask': property 'inputDirectory' is missing a @PathSensitive annotation, defaulting to PathSensitivity.ABSOLUTE. + Warning: Task type 'MyTask': property 'inputFile' is missing a @PathSensitive annotation, defaulting to PathSensitivity.ABSOLUTE. + Warning: Task type 'MyTask': property 'inputFiles' is missing a @PathSensitive annotation, defaulting to PathSensitivity.ABSOLUTE. Warning: Task type 'MyTask': property 'options.badNested' is not annotated with an input or output annotation. """.stripIndent().trim() } @@ -549,7 +563,7 @@ class ValidateTaskPropertiesIntegrationTest extends AbstractIntegrationSpec { compile localGroovy() } - validateTaskProperties.enableStricterValidation = true + validateTaskProperties.enableStricterValidation = project.hasProperty('strict') """ file("src/main/groovy/MyTask.groovy") << """ import org.gradle.api.* @@ -557,19 +571,30 @@ class ValidateTaskPropertiesIntegrationTest extends AbstractIntegrationSpec { class MyTask extends DefaultTask { @InputFile - File missingNormalization + File fileProp + + @InputFiles + Set filesProp + + @InputDirectory + File dirProp @javax.inject.Inject org.gradle.api.internal.file.FileResolver fileResolver } """ + expect: + succeeds("validateTaskProperties") + when: - fails "validateTaskProperties" + fails "validateTaskProperties", "-Pstrict" then: file("build/reports/task-properties/report.txt").text == """ - Warning: Task type 'MyTask': property 'missingNormalization' is missing a @PathSensitive annotation, defaulting to PathSensitivity.ABSOLUTE. + Warning: Task type 'MyTask': property 'dirProp' is missing a @PathSensitive annotation, defaulting to PathSensitivity.ABSOLUTE. + Warning: Task type 'MyTask': property 'fileProp' is missing a @PathSensitive annotation, defaulting to PathSensitivity.ABSOLUTE. + Warning: Task type 'MyTask': property 'filesProp' is missing a @PathSensitive annotation, defaulting to PathSensitivity.ABSOLUTE. """.stripIndent().trim() } From 52c1147a31dbf4810a6f3da0e71e1b08e5effdfe Mon Sep 17 00:00:00 2001 From: Adam Murdoch Date: Mon, 25 Feb 2019 11:59:13 +1100 Subject: [PATCH 214/853] Move the check that `@Input` should not be attached to properties whose type is a file-ish thing out of the implementation of `ValidateTaskProperties` and into the `TypeMetadata` so that the check is applied both at runtime and by `ValidateTaskProperties`. The check only has an effect at runtime for artifact transform parameters, because the result of these inspections are currently discarded at runtime for tasks and other things. --- .../properties/DefaultTypeMetadataStore.java | 38 +++++++- .../properties/PropertyValidationAccess.java | 15 +--- .../properties/PropertyValueVisitor.java | 25 ------ ...actInputFilePropertyAnnotationHandler.java | 5 ++ ...stractOutputPropertyAnnotationHandler.java | 5 ++ .../ClasspathPropertyAnnotationHandler.java | 5 ++ ...ileClasspathPropertyAnnotationHandler.java | 5 ++ .../DestroysPropertyAnnotationHandler.java | 5 ++ .../InputPropertyAnnotationHandler.java | 13 +++ .../LocalStatePropertyAnnotationHandler.java | 5 ++ .../NestedBeanAnnotationHandler.java | 5 ++ .../NoOpPropertyAnnotationHandler.java | 5 ++ .../PropertyAnnotationHandler.java | 23 ++++- .../DefaultTypeMetadataStoreTest.groovy | 40 +++++---- ...sformValuesInjectionIntegrationTest.groovy | 19 ++++ .../transform/DefaultTransformer.java | 5 +- .../internal/reflect/PropertyExtractor.java | 46 ++++------ .../reflect/PropertyExtractorTest.groovy | 88 +++++++++---------- 18 files changed, 216 insertions(+), 136 deletions(-) delete mode 100644 subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/PropertyValueVisitor.java diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/DefaultTypeMetadataStore.java b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/DefaultTypeMetadataStore.java index bc38b29e515e4..3cec762b8ae47 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/DefaultTypeMetadataStore.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/DefaultTypeMetadataStore.java @@ -41,7 +41,6 @@ import org.gradle.api.tasks.SkipWhenEmpty; import org.gradle.cache.internal.CrossBuildInMemoryCache; import org.gradle.cache.internal.CrossBuildInMemoryCacheFactory; -import org.gradle.internal.Pair; import org.gradle.internal.reflect.ParameterValidationContext; import org.gradle.internal.reflect.PropertyExtractor; import org.gradle.internal.reflect.PropertyMetadata; @@ -127,8 +126,41 @@ public TypeMetadata getTypeMetadata(final Class type) { } private TypeMetadata createTypeMetadata(Class type) { - Pair, ImmutableList> properties = propertyExtractor.extractPropertyMetadata(type); - return new DefaultTypeMetadata(properties.left, properties.right, annotationHandlers); + RecordingValidationContext validationContext = new RecordingValidationContext(); + ImmutableSet properties = propertyExtractor.extractPropertyMetadata(type, validationContext); + for (PropertyMetadata property : properties) { + PropertyAnnotationHandler annotationHandler = annotationHandlers.get(property.getPropertyType()); + annotationHandler.validatePropertyMetadata(property, validationContext); + } + return new DefaultTypeMetadata(properties, validationContext.getProblems(), annotationHandlers); + } + + private static class RecordingValidationContext implements ParameterValidationContext { + private ImmutableList.Builder builder = ImmutableList.builder(); + + ImmutableList getProblems() { + return builder.build(); + } + + @Override + public void visitError(@Nullable String ownerPath, final String propertyName, final String message) { + builder.add(new ValidationProblem() { + @Override + public void collect(@Nullable String ownerPropertyPath, ParameterValidationContext validationContext) { + validationContext.visitError(ownerPropertyPath, propertyName, message); + } + }); + } + + @Override + public void visitError(final String message) { + builder.add(new ValidationProblem() { + @Override + public void collect(@Nullable String ownerPropertyPath, ParameterValidationContext validationContext) { + validationContext.visitError(message); + } + }); + } } private static class DefaultTypeMetadata implements TypeMetadata { diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/PropertyValidationAccess.java b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/PropertyValidationAccess.java index 8a21afc1e92cc..d697ec0c44e1f 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/PropertyValidationAccess.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/PropertyValidationAccess.java @@ -22,10 +22,8 @@ import org.gradle.api.Named; import org.gradle.api.NonNullApi; import org.gradle.api.Task; -import org.gradle.api.file.FileCollection; import org.gradle.api.internal.project.taskfactory.TaskClassInfoStore; import org.gradle.api.provider.Provider; -import org.gradle.api.tasks.Input; import org.gradle.api.tasks.InputDirectory; import org.gradle.api.tasks.InputFile; import org.gradle.api.tasks.InputFiles; @@ -44,7 +42,6 @@ import org.gradle.internal.service.scopes.PluginServiceRegistry; import javax.annotation.Nullable; -import java.io.File; import java.lang.annotation.Annotation; import java.lang.reflect.Method; import java.lang.reflect.ParameterizedType; @@ -58,14 +55,12 @@ */ @NonNullApi public class PropertyValidationAccess { - private final static Map, PropertyValidator> PROPERTY_VALIDATORS = ImmutableMap.of( - Input.class, new InputOnFileTypeValidator(), + private final static Map, ? extends PropertyValidator> PROPERTY_VALIDATORS = ImmutableMap.of( InputFiles.class, new MissingPathSensitivityValidator(false), InputFile.class, new MissingPathSensitivityValidator(false), InputDirectory.class, new MissingPathSensitivityValidator(false) ); - private final static Map, PropertyValidator> STRICT_PROPERTY_VALIDATORS = ImmutableMap.of( - Input.class, new InputOnFileTypeValidator(), + private final static Map, ? extends PropertyValidator> STRICT_PROPERTY_VALIDATORS = ImmutableMap.of( InputFiles.class, new MissingPathSensitivityValidator(true), InputFile.class, new MissingPathSensitivityValidator(true), InputDirectory.class, new MissingPathSensitivityValidator(true) @@ -264,12 +259,6 @@ private interface PropertyValidator { private static class InputOnFileTypeValidator implements PropertyValidator { @Override public void validate(@Nullable String ownerPath, PropertyMetadata metadata, ParameterValidationContext validationContext) { - Class valueType = metadata.getDeclaredType(); - if (File.class.isAssignableFrom(valueType) - || java.nio.file.Path.class.isAssignableFrom(valueType) - || FileCollection.class.isAssignableFrom(valueType)) { - validationContext.visitError(ownerPath, metadata.getPropertyName(), "has @Input annotation used on property of type " + valueType.getName()); - } } } diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/PropertyValueVisitor.java b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/PropertyValueVisitor.java deleted file mode 100644 index 6d13abb09dce9..0000000000000 --- a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/PropertyValueVisitor.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright 2017 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.gradle.api.internal.tasks.properties; - -import org.gradle.internal.reflect.PropertyMetadata; - -public interface PropertyValueVisitor { - boolean shouldVisit(PropertyVisitor visitor); - - void visitPropertyValue(String propertyName, PropertyValue value, PropertyMetadata propertyMetadata, PropertyVisitor visitor, BeanPropertyContext context); -} diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/annotations/AbstractInputFilePropertyAnnotationHandler.java b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/annotations/AbstractInputFilePropertyAnnotationHandler.java index bd47367aac5dc..cd40bdd5c2f72 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/annotations/AbstractInputFilePropertyAnnotationHandler.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/annotations/AbstractInputFilePropertyAnnotationHandler.java @@ -25,6 +25,7 @@ import org.gradle.api.tasks.Optional; import org.gradle.api.tasks.PathSensitive; import org.gradle.api.tasks.SkipWhenEmpty; +import org.gradle.internal.reflect.ParameterValidationContext; import org.gradle.internal.reflect.PropertyMetadata; public abstract class AbstractInputFilePropertyAnnotationHandler implements PropertyAnnotationHandler { @@ -47,5 +48,9 @@ public void visitPropertyValue(String propertyName, PropertyValue value, Propert ); } + @Override + public void validatePropertyMetadata(PropertyMetadata propertyMetadata, ParameterValidationContext visitor) { + } + protected abstract InputFilePropertyType getFilePropertyType(); } diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/annotations/AbstractOutputPropertyAnnotationHandler.java b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/annotations/AbstractOutputPropertyAnnotationHandler.java index 1bf04cf6e3690..b54465b07e0fc 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/annotations/AbstractOutputPropertyAnnotationHandler.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/annotations/AbstractOutputPropertyAnnotationHandler.java @@ -21,6 +21,7 @@ import org.gradle.api.internal.tasks.properties.PropertyValue; import org.gradle.api.internal.tasks.properties.PropertyVisitor; import org.gradle.api.tasks.Optional; +import org.gradle.internal.reflect.ParameterValidationContext; import org.gradle.internal.reflect.PropertyMetadata; public abstract class AbstractOutputPropertyAnnotationHandler implements PropertyAnnotationHandler { @@ -36,4 +37,8 @@ public boolean shouldVisit(PropertyVisitor visitor) { public void visitPropertyValue(String propertyName, PropertyValue value, PropertyMetadata propertyMetadata, PropertyVisitor visitor, BeanPropertyContext context) { visitor.visitOutputFileProperty(propertyName, propertyMetadata.isAnnotationPresent(Optional.class), value, getFilePropertyType()); } + + @Override + public void validatePropertyMetadata(PropertyMetadata propertyMetadata, ParameterValidationContext visitor) { + } } diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/annotations/ClasspathPropertyAnnotationHandler.java b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/annotations/ClasspathPropertyAnnotationHandler.java index 5a0f70df4d3d9..fcd6150ac0c03 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/annotations/ClasspathPropertyAnnotationHandler.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/annotations/ClasspathPropertyAnnotationHandler.java @@ -28,6 +28,7 @@ import org.gradle.api.tasks.InputFiles; import org.gradle.api.tasks.Optional; import org.gradle.api.tasks.SkipWhenEmpty; +import org.gradle.internal.reflect.ParameterValidationContext; import org.gradle.internal.reflect.PropertyMetadata; import java.lang.annotation.Annotation; @@ -59,4 +60,8 @@ public void visitPropertyValue(String propertyName, PropertyValue value, Propert InputFilePropertyType.FILES ); } + + @Override + public void validatePropertyMetadata(PropertyMetadata propertyMetadata, ParameterValidationContext visitor) { + } } diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/annotations/CompileClasspathPropertyAnnotationHandler.java b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/annotations/CompileClasspathPropertyAnnotationHandler.java index f2c12b2b8ed7b..24acfd613fb5b 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/annotations/CompileClasspathPropertyAnnotationHandler.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/annotations/CompileClasspathPropertyAnnotationHandler.java @@ -28,6 +28,7 @@ import org.gradle.api.tasks.InputFiles; import org.gradle.api.tasks.Optional; import org.gradle.api.tasks.SkipWhenEmpty; +import org.gradle.internal.reflect.ParameterValidationContext; import org.gradle.internal.reflect.PropertyMetadata; import java.lang.annotation.Annotation; @@ -59,4 +60,8 @@ public void visitPropertyValue(String propertyName, PropertyValue value, Propert InputFilePropertyType.FILES ); } + + @Override + public void validatePropertyMetadata(PropertyMetadata propertyMetadata, ParameterValidationContext visitor) { + } } diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/annotations/DestroysPropertyAnnotationHandler.java b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/annotations/DestroysPropertyAnnotationHandler.java index a37a3e5d59996..88e838fdafcfd 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/annotations/DestroysPropertyAnnotationHandler.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/annotations/DestroysPropertyAnnotationHandler.java @@ -20,6 +20,7 @@ import org.gradle.api.internal.tasks.properties.PropertyValue; import org.gradle.api.internal.tasks.properties.PropertyVisitor; import org.gradle.api.tasks.Destroys; +import org.gradle.internal.reflect.ParameterValidationContext; import org.gradle.internal.reflect.PropertyMetadata; import java.lang.annotation.Annotation; @@ -39,4 +40,8 @@ public boolean shouldVisit(PropertyVisitor visitor) { public void visitPropertyValue(String propertyName, PropertyValue value, PropertyMetadata propertyMetadata, PropertyVisitor visitor, BeanPropertyContext context) { visitor.visitDestroyableProperty(value); } + + @Override + public void validatePropertyMetadata(PropertyMetadata propertyMetadata, ParameterValidationContext visitor) { + } } diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/annotations/InputPropertyAnnotationHandler.java b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/annotations/InputPropertyAnnotationHandler.java index 2c25b91efbb2a..0ea754440f218 100755 --- a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/annotations/InputPropertyAnnotationHandler.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/annotations/InputPropertyAnnotationHandler.java @@ -15,13 +15,16 @@ */ package org.gradle.api.internal.tasks.properties.annotations; +import org.gradle.api.file.FileCollection; import org.gradle.api.internal.tasks.properties.BeanPropertyContext; import org.gradle.api.internal.tasks.properties.PropertyValue; import org.gradle.api.internal.tasks.properties.PropertyVisitor; import org.gradle.api.tasks.Input; import org.gradle.api.tasks.Optional; +import org.gradle.internal.reflect.ParameterValidationContext; import org.gradle.internal.reflect.PropertyMetadata; +import java.io.File; import java.lang.annotation.Annotation; public class InputPropertyAnnotationHandler implements PropertyAnnotationHandler { @@ -38,4 +41,14 @@ public boolean shouldVisit(PropertyVisitor visitor) { public void visitPropertyValue(String propertyName, PropertyValue value, PropertyMetadata propertyMetadata, PropertyVisitor visitor, BeanPropertyContext context) { visitor.visitInputProperty(propertyName, value, propertyMetadata.isAnnotationPresent(Optional.class)); } + + @Override + public void validatePropertyMetadata(PropertyMetadata propertyMetadata, ParameterValidationContext visitor) { + Class valueType = propertyMetadata.getDeclaredType(); + if (File.class.isAssignableFrom(valueType) + || java.nio.file.Path.class.isAssignableFrom(valueType) + || FileCollection.class.isAssignableFrom(valueType)) { + visitor.visitError(null, propertyMetadata.getPropertyName(), "has @Input annotation used on property of type " + valueType.getName()); + } + } } diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/annotations/LocalStatePropertyAnnotationHandler.java b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/annotations/LocalStatePropertyAnnotationHandler.java index 7f41cb7875037..817267c471cf7 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/annotations/LocalStatePropertyAnnotationHandler.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/annotations/LocalStatePropertyAnnotationHandler.java @@ -19,6 +19,7 @@ import org.gradle.api.internal.tasks.properties.PropertyValue; import org.gradle.api.internal.tasks.properties.PropertyVisitor; import org.gradle.api.tasks.LocalState; +import org.gradle.internal.reflect.ParameterValidationContext; import org.gradle.internal.reflect.PropertyMetadata; import java.lang.annotation.Annotation; @@ -37,4 +38,8 @@ public boolean shouldVisit(PropertyVisitor visitor) { public void visitPropertyValue(String propertyName, PropertyValue value, PropertyMetadata propertyMetadata, PropertyVisitor visitor, BeanPropertyContext context) { visitor.visitLocalStateProperty(value); } + + @Override + public void validatePropertyMetadata(PropertyMetadata propertyMetadata, ParameterValidationContext visitor) { + } } diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/annotations/NestedBeanAnnotationHandler.java b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/annotations/NestedBeanAnnotationHandler.java index 2636e7dc5c8c1..ef5a066a4d57e 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/annotations/NestedBeanAnnotationHandler.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/annotations/NestedBeanAnnotationHandler.java @@ -24,6 +24,7 @@ import org.gradle.api.tasks.Nested; import org.gradle.api.tasks.Optional; import org.gradle.internal.UncheckedException; +import org.gradle.internal.reflect.ParameterValidationContext; import org.gradle.internal.reflect.PropertyMetadata; import javax.annotation.Nullable; @@ -57,6 +58,10 @@ public void visitPropertyValue(String propertyName, PropertyValue value, Propert } } + @Override + public void validatePropertyMetadata(PropertyMetadata propertyMetadata, ParameterValidationContext visitor) { + } + @Nullable private static Object unpackProvider(@Nullable Object value) { // Only unpack one level of Providers, since Provider> is not supported - we don't need two levels of laziness. diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/annotations/NoOpPropertyAnnotationHandler.java b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/annotations/NoOpPropertyAnnotationHandler.java index 64c59ea531238..6eee5bd607067 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/annotations/NoOpPropertyAnnotationHandler.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/annotations/NoOpPropertyAnnotationHandler.java @@ -19,6 +19,7 @@ import org.gradle.api.internal.tasks.properties.BeanPropertyContext; import org.gradle.api.internal.tasks.properties.PropertyValue; import org.gradle.api.internal.tasks.properties.PropertyVisitor; +import org.gradle.internal.reflect.ParameterValidationContext; import org.gradle.internal.reflect.PropertyMetadata; import java.lang.annotation.Annotation; @@ -42,4 +43,8 @@ public boolean shouldVisit(PropertyVisitor visitor) { @Override public void visitPropertyValue(String propertyName, PropertyValue value, PropertyMetadata propertyMetadata, PropertyVisitor visitor, BeanPropertyContext context) { } + + @Override + public void validatePropertyMetadata(PropertyMetadata propertyMetadata, ParameterValidationContext visitor) { + } } diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/annotations/PropertyAnnotationHandler.java b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/annotations/PropertyAnnotationHandler.java index a00d533abc456..ae56c397fd1f9 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/annotations/PropertyAnnotationHandler.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/annotations/PropertyAnnotationHandler.java @@ -15,18 +15,37 @@ */ package org.gradle.api.internal.tasks.properties.annotations; -import org.gradle.api.internal.tasks.properties.PropertyValueVisitor; +import org.gradle.api.internal.tasks.properties.BeanPropertyContext; +import org.gradle.api.internal.tasks.properties.PropertyValue; +import org.gradle.api.internal.tasks.properties.PropertyVisitor; +import org.gradle.internal.reflect.ParameterValidationContext; +import org.gradle.internal.reflect.PropertyMetadata; import java.lang.annotation.Annotation; /** * Handles validation, dependency handling, and skipping for a property marked with a given annotation. */ -public interface PropertyAnnotationHandler extends PropertyValueVisitor { +public interface PropertyAnnotationHandler { /** * The annotation type which this handler is responsible for. * * @return The annotation. */ Class getAnnotationType(); + + /** + * Is the given visitor interested in this annotation? + */ + boolean shouldVisit(PropertyVisitor visitor); + + /** + * Visit the value of a property with this annotation attached. + */ + void visitPropertyValue(String propertyName, PropertyValue value, PropertyMetadata propertyMetadata, PropertyVisitor visitor, BeanPropertyContext context); + + /** + * Visits problems associated with the given property, if any. + */ + void validatePropertyMetadata(PropertyMetadata propertyMetadata, ParameterValidationContext visitor); } diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/properties/DefaultTypeMetadataStoreTest.groovy b/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/properties/DefaultTypeMetadataStoreTest.groovy index 48e07f7bbc53c..9daed29281dac 100644 --- a/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/properties/DefaultTypeMetadataStoreTest.groovy +++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/properties/DefaultTypeMetadataStoreTest.groovy @@ -40,6 +40,7 @@ import org.gradle.api.tasks.OutputDirectory import org.gradle.api.tasks.OutputFile import org.gradle.api.tasks.OutputFiles import org.gradle.cache.internal.TestCrossBuildInMemoryCacheFactory +import org.gradle.internal.reflect.ParameterValidationContext import org.gradle.internal.reflect.PropertyMetadata import org.gradle.internal.scripts.ScriptOrigin import org.gradle.internal.service.ServiceRegistryBuilder @@ -74,25 +75,32 @@ class DefaultTypeMetadataStoreTest extends Specification { @SearchPath FileCollection searchPath } - class SearchPathAnnotationHandler implements PropertyAnnotationHandler { + def "can use custom annotation processor"() { + def annotationHandler = Stub(PropertyAnnotationHandler) + _ * annotationHandler.annotationType >> SearchPath - @Override - Class getAnnotationType() { - SearchPath - } + def metadataStore = new DefaultTypeMetadataStore([annotationHandler], [] as Set, new TestCrossBuildInMemoryCacheFactory()) - @Override - boolean shouldVisit(PropertyVisitor visitor) { - return true - } + when: + def typeMetadata = metadataStore.getTypeMetadata(TaskWithCustomAnnotation) + def propertiesMetadata = typeMetadata.propertiesMetadata.findAll { !isIgnored(it) } - @Override - void visitPropertyValue(String propertyName, PropertyValue value, PropertyMetadata propertyMetadata, PropertyVisitor visitor, BeanPropertyContext context) { - } + then: + propertiesMetadata.size() == 1 + def propertyMetadata = propertiesMetadata.first() + propertyMetadata.propertyName == 'searchPath' + propertyMetadata.propertyType == SearchPath + typeMetadata.getAnnotationHandlerFor(propertyMetadata) == annotationHandler + collectProblems(typeMetadata).empty } - def "can use custom annotation processor"() { - def annotationHandler = new SearchPathAnnotationHandler() + def "custom annotation processor can inspect for static property problems"() { + def annotationHandler = Stub(PropertyAnnotationHandler) + _ * annotationHandler.annotationType >> SearchPath + _ * annotationHandler.validatePropertyMetadata(_, _) >> { PropertyMetadata metadata, ParameterValidationContext context -> + context.visitError(null, metadata.propertyName, "is broken") + } + def metadataStore = new DefaultTypeMetadataStore([annotationHandler], [] as Set, new TestCrossBuildInMemoryCacheFactory()) when: @@ -103,9 +111,7 @@ class DefaultTypeMetadataStoreTest extends Specification { propertiesMetadata.size() == 1 def propertyMetadata = propertiesMetadata.first() propertyMetadata.propertyName == 'searchPath' - propertyMetadata.propertyType == SearchPath - typeMetadata.getAnnotationHandlerFor(propertyMetadata) == annotationHandler - collectProblems(typeMetadata).empty + collectProblems(typeMetadata) == ["Property 'searchPath' is broken."] } @Unroll diff --git a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformValuesInjectionIntegrationTest.groovy b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformValuesInjectionIntegrationTest.groovy index 7c3c04b6b70d6..ff8608e4d5c48 100644 --- a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformValuesInjectionIntegrationTest.groovy +++ b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformValuesInjectionIntegrationTest.groovy @@ -158,14 +158,30 @@ class ArtifactTransformValuesInjectionIntegrationTest extends AbstractDependency interface Parameters extends TransformParameters { String getExtension() void setExtension(String value) + @OutputDirectory File getOutputDir() void setOutputDir(File outputDir) + @Input String getMissingInput() void setMissingInput(String missing) + + @Input + File getFileInput() + void setFileInput(File file) + @InputFiles ConfigurableFileCollection getNoPathSensitivity() + + @InputFile + File getNoPathSensitivityFile() + void setNoPathSensitivityFile(File file) + + @InputDirectory + File getNoPathSensitivityDir() + void setNoPathSensitivityDir(File file) + @PathSensitive(PathSensitivity.ABSOLUTE) @InputFiles ConfigurableFileCollection getAbsolutePathSensitivity() @@ -186,7 +202,10 @@ class ArtifactTransformValuesInjectionIntegrationTest extends AbstractDependency failure.assertHasCause("Property 'extension' is not annotated with an input annotation.") failure.assertHasCause("Property 'outputDir' is annotated with unsupported annotation @OutputDirectory.") failure.assertHasCause("Property 'missingInput' does not have a value specified.") + failure.assertHasCause("Property 'fileInput' has @Input annotation used on property of type java.io.File.") failure.assertHasCause("Property 'absolutePathSensitivity' is declared to be sensitive to absolute paths. This is not allowed for cacheable transforms.") + failure.assertHasCause("Property 'noPathSensitivityFile' is declared without path sensitivity. Properties of cacheable transforms must declare their path sensitivity.") + failure.assertHasCause("Property 'noPathSensitivityDir' is declared without path sensitivity. Properties of cacheable transforms must declare their path sensitivity.") failure.assertHasCause("Property 'noPathSensitivity' is declared without path sensitivity. Properties of cacheable transforms must declare their path sensitivity.") } diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformer.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformer.java index 039de0af64f65..13c3cfe0b2ec8 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformer.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformer.java @@ -169,7 +169,10 @@ public void visitDependencies(TaskDependencyResolveContext context) { parameterPropertyWalker.visitProperties(parameterObject, ParameterValidationContext.NOOP, new PropertyVisitor.Adapter() { @Override public void visitInputFileProperty(String propertyName, boolean optional, boolean skipWhenEmpty, @Nullable Class fileNormalizer, PropertyValue value, InputFilePropertyType filePropertyType) { - context.maybeAdd(value.call()); + Object unpacked = value.call(); + if (unpacked != null) { + context.maybeAdd(unpacked); + } } }); } diff --git a/subprojects/model-core/src/main/java/org/gradle/internal/reflect/PropertyExtractor.java b/subprojects/model-core/src/main/java/org/gradle/internal/reflect/PropertyExtractor.java index 5789638d8e606..0d12423efe727 100644 --- a/subprojects/model-core/src/main/java/org/gradle/internal/reflect/PropertyExtractor.java +++ b/subprojects/model-core/src/main/java/org/gradle/internal/reflect/PropertyExtractor.java @@ -20,7 +20,6 @@ import com.google.common.base.Function; import com.google.common.base.Joiner; import com.google.common.base.Predicate; -import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Iterables; @@ -28,7 +27,6 @@ import com.google.common.collect.Maps; import com.google.common.collect.Multimap; import com.google.common.collect.Sets; -import org.gradle.internal.Pair; import org.gradle.util.CollectionUtils; import javax.annotation.Nonnull; @@ -77,7 +75,7 @@ private static ImmutableSet> allMethodsOf(Iterable Pair, ImmutableList> extractPropertyMetadata(Class type) { + public ImmutableSet extractPropertyMetadata(Class type, ParameterValidationContext validationContext) { final Set> propertyTypeAnnotations = primaryAnnotationTypes; final Map properties = Maps.newLinkedHashMap(); Types.walkTypeHierarchy(type, ignoredSuperclasses, new Types.TypeVisitor() { @@ -105,46 +103,44 @@ public void visitType(Class type) { properties.put(fieldName, propertyMetadata); } - Iterable declaredAnnotations = mergeDeclaredAnnotations(method, field, propertyMetadata); + Iterable declaredAnnotations = mergeDeclaredAnnotations(method, field, propertyMetadata, validationContext); // Discard overridden property type annotations when an overriding annotation is also present Iterable overriddenAnnotations = filterOverridingAnnotations(declaredAnnotations, propertyTypeAnnotations); - recordAnnotations(propertyMetadata, overriddenAnnotations, declaredAnnotations, propertyTypeAnnotations); + recordAnnotations(propertyMetadata, overriddenAnnotations, declaredAnnotations, propertyTypeAnnotations, validationContext); } } }); ImmutableSet.Builder propertyBuilder = ImmutableSet.builderWithExpectedSize(properties.size()); - ImmutableList.Builder problemBuilder = ImmutableList.builder(); for (PropertyMetadataBuilder property : properties.values()) { - validateProperty(property); - problemBuilder.addAll(property.validationProblems); + validateProperty(property, validationContext); if (property.propertyType != null) { propertyBuilder.add(property.toMetadata()); } } - return Pair.of(propertyBuilder.build(), problemBuilder.build()); + return propertyBuilder.build(); } - private void validateProperty(PropertyMetadataBuilder property) { + private void validateProperty(PropertyMetadataBuilder property, ParameterValidationContext validationContext) { if (!property.brokenType && property.propertyType == null) { - property.validationMessage("is not annotated with " + displayName); + validationContext.visitError(null, property.fieldName, "is not annotated with " + displayName); } } - private Iterable mergeDeclaredAnnotations(Method method, @Nullable Field field, PropertyMetadataBuilder property) { - Collection methodAnnotations = collectRelevantAnnotations(method.getDeclaredAnnotations(), property); + private Iterable mergeDeclaredAnnotations(Method method, @Nullable Field field, PropertyMetadataBuilder property, ParameterValidationContext validationContext) { + Collection methodAnnotations = collectRelevantAnnotations(method.getDeclaredAnnotations(), property, validationContext); if (Modifier.isPrivate(method.getModifiers())) { if (!methodAnnotations.isEmpty()) { - property.validationMessage("is private and annotated with @" + methodAnnotations.iterator().next().annotationType().getSimpleName()); + validationContext.visitError(null, property.fieldName, "is private and annotated with @" + methodAnnotations.iterator().next().annotationType().getSimpleName()); } property.hasBrokenType(); } if (field == null) { return methodAnnotations; } - Collection fieldAnnotations = collectRelevantAnnotations(field.getDeclaredAnnotations(), property); + Collection fieldAnnotations = collectRelevantAnnotations(field.getDeclaredAnnotations(), property, validationContext); if (fieldAnnotations.isEmpty()) { return methodAnnotations; } @@ -157,7 +153,7 @@ private Iterable mergeDeclaredAnnotations(Method method, @Nullable F while (iFieldAnnotation.hasNext()) { Annotation fieldAnnotation = iFieldAnnotation.next(); if (methodAnnotation.annotationType().equals(fieldAnnotation.annotationType())) { - property.validationMessage("has both a getter and field declared with annotation @" + methodAnnotation.annotationType().getSimpleName()); + validationContext.visitError(null, property.fieldName, "has both a getter and field declared with annotation @" + methodAnnotation.annotationType().getSimpleName()); iFieldAnnotation.remove(); } } @@ -186,7 +182,7 @@ public boolean apply(Annotation input) { }); } - private void recordAnnotations(PropertyMetadataBuilder property, Iterable overriddenAnnotations, Iterable annotations, Set> propertyTypeAnnotations) { + private void recordAnnotations(PropertyMetadataBuilder property, Iterable overriddenAnnotations, Iterable annotations, Set> propertyTypeAnnotations, ParameterValidationContext validationContext) { Set> declaredPropertyTypes = Sets.newLinkedHashSet(); for (Annotation annotation : overriddenAnnotations) { if (propertyTypeAnnotations.contains(annotation.annotationType())) { @@ -207,18 +203,18 @@ public String apply(Class annotationType) { } }); Set sortedNames = CollectionUtils.addAll(new TreeSet(), names); - property.validationMessage("has conflicting property types declared: " + Joiner.on(", ").join(sortedNames)); + validationContext.visitError(null, property.fieldName, "has conflicting property types declared: " + Joiner.on(", ").join(sortedNames)); } } - private Collection collectRelevantAnnotations(Annotation[] annotations, PropertyMetadataBuilder property) { + private Collection collectRelevantAnnotations(Annotation[] annotations, PropertyMetadataBuilder property, ParameterValidationContext validationContext) { List relevantAnnotations = Lists.newArrayListWithCapacity(annotations.length); for (Annotation annotation : annotations) { if (relevantAnnotationTypes.contains(annotation.annotationType())) { relevantAnnotations.add(annotation); } if (otherKnownAnnotations.contains(annotation.annotationType())) { - property.validationMessage("is annotated with unsupported annotation @" + annotation.annotationType().getSimpleName()); + validationContext.visitError(null, property.fieldName, "is annotated with unsupported annotation @" + annotation.annotationType().getSimpleName()); property.hasBrokenType(); } } @@ -282,7 +278,6 @@ private static class PropertyMetadataBuilder { private final Method method; private Class propertyType; private final Map, Annotation> annotations = Maps.newHashMap(); - private final List validationProblems = Lists.newArrayList(); private boolean brokenType; PropertyMetadataBuilder(Set> propertyTypeAnnotations, String fieldName, Method method) { @@ -295,15 +290,6 @@ public void hasBrokenType() { this.brokenType = true; } - public void validationMessage(String message) { - validationProblems.add(new ValidationProblem() { - @Override - public void collect(@Nullable String ownerPropertyPath, ParameterValidationContext validationContext) { - validationContext.visitError(ownerPropertyPath, fieldName, message); - } - }); - } - public void addAnnotation(Annotation annotation) { Class annotationType = annotation.annotationType(); // Record the most specific property type annotation only diff --git a/subprojects/model-core/src/test/groovy/org/gradle/internal/reflect/PropertyExtractorTest.groovy b/subprojects/model-core/src/test/groovy/org/gradle/internal/reflect/PropertyExtractorTest.groovy index cba7fc875e4ec..4a5f1bf431b86 100644 --- a/subprojects/model-core/src/test/groovy/org/gradle/internal/reflect/PropertyExtractorTest.groovy +++ b/subprojects/model-core/src/test/groovy/org/gradle/internal/reflect/PropertyExtractorTest.groovy @@ -20,6 +20,7 @@ import com.google.common.collect.ImmutableMultimap import com.google.common.collect.ImmutableSet import org.gradle.api.file.FileCollection import org.gradle.api.internal.tasks.properties.DefaultParameterValidationContext +import org.gradle.internal.Pair import spock.lang.Issue import spock.lang.Specification @@ -53,9 +54,9 @@ class PropertyExtractorTest extends Specification { def "can override property type in subclasses"() { expect: - extractor.extractPropertyMetadata(WithPropertyType1).left*.propertyType == [PropertyType1] - extractor.extractPropertyMetadata(WithPropertyType2).left*.propertyType == [PropertyType2] - extractor.extractPropertyMetadata(WithPropertyOverride).left*.propertyType == [PropertyType1Override] + extract(WithPropertyType1)*.propertyType == [PropertyType1] + extract(WithPropertyType2)*.propertyType == [PropertyType2] + extract(WithPropertyOverride)*.propertyType == [PropertyType1Override] } class OverridingProperties { @@ -65,11 +66,10 @@ class PropertyExtractorTest extends Specification { def "overriding annotation on same property takes effect"() { when: - def result = extractor.extractPropertyMetadata(OverridingProperties) + def result = extract(OverridingProperties) then: - assertPropertyTypes(result.left, inputFiles1: PropertyType1Override, inputFiles2: PropertyType1Override) - result.right.empty + assertPropertyTypes(result, inputFiles1: PropertyType1Override, inputFiles2: PropertyType1Override) } class BasePropertyType1OverrideProperty { @@ -94,11 +94,10 @@ class PropertyExtractorTest extends Specification { @Issue("https://github.com/gradle/gradle/issues/913") def "overriding annotation does not take precedence in sub-type"() { when: - def result = extractor.extractPropertyMetadata(OverridingPropertyType1Property) + def result = extract(OverridingPropertyType1Property) then: - assertPropertyTypes(result.left, overriddenType1Override: PropertyType1, overriddenType1: PropertyType1Override) - result.right.empty + assertPropertyTypes(result, overriddenType1Override: PropertyType1, overriddenType1: PropertyType1Override) } class WithBothFieldAndGetterAnnotation { @@ -112,11 +111,11 @@ class PropertyExtractorTest extends Specification { def "warns about both method and field having the same annotation"() { when: - def result = extractor.extractPropertyMetadata(WithBothFieldAndGetterAnnotation) + def result = extractWithProblems(WithBothFieldAndGetterAnnotation) then: assertPropertyTypes(result.left, inputFiles: PropertyType1) - collectProblems(result.right) == ["Property 'inputFiles' has both a getter and field declared with annotation @${PropertyType1.simpleName}."] + result.right == ["Property 'inputFiles' has both a getter and field declared with annotation @${PropertyType1.simpleName}."] } class WithBothFieldAndGetterAnnotationButIrrelevant { @@ -130,11 +129,10 @@ class PropertyExtractorTest extends Specification { def "doesn't warn about both method and field having the same irrelevant annotation"() { when: - def result = extractor.extractPropertyMetadata(WithBothFieldAndGetterAnnotationButIrrelevant) + def result = extract(WithBothFieldAndGetterAnnotationButIrrelevant) then: - assertPropertyTypes(result.left, inputFiles: PropertyType1) - result.right.empty + assertPropertyTypes(result, inputFiles: PropertyType1) } class WithAnnotationsOnPrivateProperties { @@ -155,11 +153,11 @@ class PropertyExtractorTest extends Specification { def "warns about annotations on private properties"() { when: - def result = extractor.extractPropertyMetadata(WithAnnotationsOnPrivateProperties) + def result = extractWithProblems(WithAnnotationsOnPrivateProperties) then: assertPropertyTypes(result.left, input: PropertyType1, outputFile: PropertyType2) - collectProblems(result.right) == [ + result.right == [ "Property 'input' is private and annotated with @${PropertyType1.simpleName}.", "Property 'outputFile' is private and annotated with @${PropertyType2.simpleName}." ] @@ -181,11 +179,11 @@ class PropertyExtractorTest extends Specification { def "warns about non-private getters that are not annotated"() { when: - def result = extractor.extractPropertyMetadata(WithUnannotatedProperties) + def result = extractWithProblems(WithUnannotatedProperties) then: result.left.empty - collectProblems(result.right) == [ + result.right == [ "Property 'bad1' is not annotated with a thing annotation.", "Property 'bad2' is not annotated with a thing annotation." ] @@ -203,11 +201,11 @@ class PropertyExtractorTest extends Specification { def "warns about conflicting property types being specified"() { when: - def result = extractor.extractPropertyMetadata(WithConflictingPropertyTypes) + def result = extractWithProblems(WithConflictingPropertyTypes) then: assertPropertyTypes(result.left, inputThing: PropertyType1, confusedFile: PropertyType2) - collectProblems(result.right) == [ + result.right == [ "Property 'confusedFile' has conflicting property types declared: @${PropertyType1.simpleName}, @${PropertyType2.simpleName}.", "Property 'inputThing' has conflicting property types declared: @${PropertyType1.simpleName}, @${PropertyType2.simpleName}." ] @@ -224,11 +222,11 @@ class PropertyExtractorTest extends Specification { def "warns about properties annotated with known bu unsupported annotations"() { when: - def result = extractor.extractPropertyMetadata(WithUnsupportedPropertyTypes) + def result = extractWithProblems(WithUnsupportedPropertyTypes) then: assertPropertyTypes(result.left, hasBoth: PropertyType1) - collectProblems(result.right) == [ + result.right == [ "Property 'hasBoth' is annotated with unsupported annotation @${KnownAnnotation.simpleName}.", "Property 'inputThing' is annotated with unsupported annotation @${KnownAnnotation.simpleName}." ] @@ -242,11 +240,10 @@ class PropertyExtractorTest extends Specification { def "doesn't warn about non-conflicting property types being specified"() { when: - def result = extractor.extractPropertyMetadata(WithNonConflictingPropertyTypes) + def result = extract(WithNonConflictingPropertyTypes) then: - assertPropertyTypes(result.left, classpath: PropertyType1Override) - result.right.empty + assertPropertyTypes(result, classpath: PropertyType1Override) } static class SimpleType { @@ -259,7 +256,7 @@ class PropertyExtractorTest extends Specification { def "can get annotated properties of simple type"() { when: - def result = extractor.extractPropertyMetadata(SimpleType) + def result = extractWithProblems(SimpleType) then: assertPropertyTypes(result.left, @@ -267,7 +264,7 @@ class PropertyExtractorTest extends Specification { inputFile: PropertyType1Override, inputDirectory: PropertyType2 ) - collectProblems(result.right) == ["Property 'injectedService' is not annotated with a thing annotation."] + result.right == ["Property 'injectedService' is not annotated with a thing annotation."] } static abstract class BaseClassWithGetters { @@ -295,11 +292,10 @@ class PropertyExtractorTest extends Specification { def "annotations are gathered from different getters"() { when: - def result = extractor.extractPropertyMetadata(WithGetters) + def result = extract(WithGetters) then: - assertPropertyTypes(result.left, boolean: PropertyType1, strings: PropertyType2) - result.right.empty + assertPropertyTypes(result, boolean: PropertyType1, strings: PropertyType2) } private static class BaseType { @@ -328,16 +324,15 @@ class PropertyExtractorTest extends Specification { def "overridden properties inherit super-class annotations"() { when: - def result = extractor.extractPropertyMetadata(OverridingType) + def result = extract(OverridingType) then: - assertPropertyTypes(result.left, + assertPropertyTypes(result, baseValue: PropertyType1, nonAnnotatedBaseValue: PropertyType1, superclassValue: PropertyType1, superclassValueWithDuplicateAnnotation: PropertyType1, ) - result.right.empty } private interface TaskSpec { @@ -354,13 +349,12 @@ class PropertyExtractorTest extends Specification { def "implemented properties inherit interface annotations"() { when: - def result = extractor.extractPropertyMetadata(InterfaceImplementingType) + def result = extract(InterfaceImplementingType) then: - assertPropertyTypes(result.left, + assertPropertyTypes(result, interfaceValue: PropertyType1 ) - result.right.empty } @SuppressWarnings("GroovyUnusedDeclaration") @@ -386,22 +380,26 @@ class PropertyExtractorTest extends Specification { @Issue("https://issues.gradle.org/browse/GRADLE-2115") def "annotation on private field is recognized for is-getter"() { when: - def result = extractor.extractPropertyMetadata(IsGetterType) + def result = extractWithProblems(IsGetterType) then: assertPropertyTypes(result.left, feature1: PropertyType1 ) - collectProblems(result.right) == ["Property 'feature2' is not annotated with a thing annotation."] + result.right == ["Property 'feature2' is not annotated with a thing annotation."] } - private static List collectProblems(Collection problems) { - def result = [] - def context = new DefaultParameterValidationContext(result) - problems.forEach { - it.collect(null, context) - } - return result + private Set extract(Class type) { + def problems = [] + def props = extractor.extractPropertyMetadata(type, new DefaultParameterValidationContext(problems)) + assert problems.empty + return props + } + + private Pair, List> extractWithProblems(Class type) { + def problems = [] + def props = extractor.extractPropertyMetadata(type, new DefaultParameterValidationContext(problems)) + return Pair.of(props, problems) } private static void assertPropertyTypes(Map expectedPropertyTypes, Set typeMetadata) { From 1c9c86073bfe36b15f9d2440085b3ccb250317e3 Mon Sep 17 00:00:00 2001 From: Adam Murdoch Date: Mon, 25 Feb 2019 17:15:37 +1100 Subject: [PATCH 215/853] Do not allow `@CacheableTask` to be attached to types that are not `Task` subtypes or `@CacheableTransformAction` to be attached to types that are not `TransformAction` subtypes. The check is performed as part of constructing the `TypeMetadata` for a given type, so is currently only applied for those things that use this. This includes tasks, artifact transform parameters, artifact transform actions, and types that are statically reachable via `@Nested` properties. For tasks, the result of the check is visible as an error (not warning) in the output of `ValidateTaskProperties` for tasks and is also an error at runtime (yes, at runtime). For artifact transforms, the result is visible as an error at runtime. This is intended to be a step towards making the result of all checks visible both at runtime and plugin build time for tasks and all other types. --- .../api/internal/tasks/TaskPropertyUtils.java | 63 ++++++++- .../DefaultParameterValidationContext.java | 5 + .../properties/DefaultTypeMetadataStore.java | 20 ++- .../properties/InspectionSchemeFactory.java | 23 +-- .../properties/PropertyValidationAccess.java | 5 + .../CacheableTaskTypeAnnotationHandler.java | 37 +++++ .../annotations/TypeAnnotationHandler.java | 35 +++++ .../scopes/ExecutionGlobalServices.java | 10 +- ...AnnotationProcessingTaskFactoryTest.groovy | 2 +- .../tasks/DefaultTaskInputsTest.groovy | 2 +- .../tasks/DefaultTaskOutputsTest.groovy | 2 +- .../tasks/properties/CustomCacheable.java | 27 ++++ .../DefaultPropertyWalkerTest.groovy | 2 +- .../DefaultTypeMetadataStoreTest.groovy | 35 ++++- .../InspectionSchemeFactoryTest.groovy | 2 +- ...sformValuesInjectionIntegrationTest.groovy | 132 ++++++++++++++++++ ...pendencyManagementGlobalScopeServices.java | 6 + ...cheableTransformTypeAnnotationHandler.java | 38 +++++ .../reflect/ParameterValidationContext.java | 9 ++ ...lidateTaskPropertiesIntegrationTest.groovy | 39 ++++++ 20 files changed, 468 insertions(+), 26 deletions(-) create mode 100644 subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/annotations/CacheableTaskTypeAnnotationHandler.java create mode 100644 subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/annotations/TypeAnnotationHandler.java create mode 100644 subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/properties/CustomCacheable.java create mode 100644 subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/CacheableTransformTypeAnnotationHandler.java diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/TaskPropertyUtils.java b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/TaskPropertyUtils.java index 45a5219f6941a..b5f141403b416 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/TaskPropertyUtils.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/TaskPropertyUtils.java @@ -16,21 +16,31 @@ package org.gradle.api.internal.tasks; +import org.gradle.api.InvalidUserDataException; import org.gradle.api.NonNullApi; +import org.gradle.api.Transformer; import org.gradle.api.internal.TaskInternal; -import org.gradle.internal.reflect.ParameterValidationContext; import org.gradle.api.internal.tasks.properties.PropertyVisitor; import org.gradle.api.internal.tasks.properties.PropertyWalker; +import org.gradle.api.tasks.TaskValidationException; +import org.gradle.internal.reflect.ParameterValidationContext; +import org.gradle.util.CollectionUtils; + +import javax.annotation.Nullable; +import java.util.ArrayList; +import java.util.List; @NonNullApi public class TaskPropertyUtils { - /** * Visits both properties declared via annotations on the properties of the task type as well as * properties declared via the runtime API ({@link org.gradle.api.tasks.TaskInputs} etc.). */ - public static void visitProperties(PropertyWalker propertyWalker, final TaskInternal task, PropertyVisitor visitor) { - propertyWalker.visitProperties(task, ParameterValidationContext.NOOP, visitor); + public static void visitProperties(PropertyWalker propertyWalker, final TaskInternal task, final PropertyVisitor visitor) { + StrictErrorsOnlyContext validationContext = new StrictErrorsOnlyContext(task); + propertyWalker.visitProperties(task, validationContext, visitor); + // Should instead forward these to the task's validation context + validationContext.assertNoProblems(); if (!visitor.visitOutputFilePropertiesOnly()) { task.getInputs().visitRegisteredProperties(visitor); } @@ -57,4 +67,49 @@ public static String checkPropertyName(String propertyName) { } return propertyName; } + + private static class StrictErrorsOnlyContext implements ParameterValidationContext { + private final TaskInternal task; + List problems; + + public StrictErrorsOnlyContext(TaskInternal task) { + this.task = task; + } + + void assertNoProblems() { + if (problems == null) { + return; + } + String message; + if (problems.size() == 1) { + message = String.format("A problem was found with the configuration of %s.", task); + } else { + message = String.format("Some problems were found with the configuration of %s.", task); + } + throw new TaskValidationException(message, CollectionUtils.collect(problems, new Transformer() { + @Override + public InvalidUserDataException transform(String message) { + return new InvalidUserDataException(message); + } + })); + } + + @Override + public void visitError(@Nullable String ownerPath, String propertyName, String message) { + // Ignore for now + } + + @Override + public void visitError(String message) { + // Ignore for now + } + + @Override + public void visitErrorStrict(String message) { + if (problems == null) { + problems = new ArrayList(); + } + problems.add(message); + } + } } diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/DefaultParameterValidationContext.java b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/DefaultParameterValidationContext.java index dd89c8179e30a..7e4fba423bd16 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/DefaultParameterValidationContext.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/DefaultParameterValidationContext.java @@ -41,4 +41,9 @@ public void visitError(@Nullable String ownerPath, String propertyName, String m public void visitError(String message) { messages.add(message); } + + @Override + public void visitErrorStrict(String message) { + visitError(message); + } } diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/DefaultTypeMetadataStore.java b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/DefaultTypeMetadataStore.java index 3cec762b8ae47..36ba9dd33cc96 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/DefaultTypeMetadataStore.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/DefaultTypeMetadataStore.java @@ -35,6 +35,7 @@ import org.gradle.api.internal.tasks.properties.annotations.AbstractOutputPropertyAnnotationHandler; import org.gradle.api.internal.tasks.properties.annotations.OverridingPropertyAnnotationHandler; import org.gradle.api.internal.tasks.properties.annotations.PropertyAnnotationHandler; +import org.gradle.api.internal.tasks.properties.annotations.TypeAnnotationHandler; import org.gradle.api.plugins.ExtensionAware; import org.gradle.api.tasks.Optional; import org.gradle.api.tasks.PathSensitive; @@ -62,6 +63,7 @@ public class DefaultTypeMetadataStore implements TypeMetadataStore { private static final ImmutableSet> IGNORED_METHODS = ImmutableSet.of(Object.class, GroovyObject.class, ScriptOrigin.class); private final ImmutableMap, ? extends PropertyAnnotationHandler> annotationHandlers; + private final Collection typeAnnotationHandlers; private final CrossBuildInMemoryCache, TypeMetadata> cache; private final PropertyExtractor propertyExtractor; private Transformer> typeMetadataFactory = new Transformer>() { @@ -71,13 +73,14 @@ public TypeMetadata transform(Class type) { } }; - public DefaultTypeMetadataStore(Collection annotationHandlers, Set> otherKnownAnnotations, CrossBuildInMemoryCacheFactory cacheFactory) { + public DefaultTypeMetadataStore(Collection annotationHandlers, Set> otherKnownAnnotations, Collection typeAnnotationHandlers, CrossBuildInMemoryCacheFactory cacheFactory) { this.annotationHandlers = Maps.uniqueIndex(annotationHandlers, new Function>() { @Override public Class apply(PropertyAnnotationHandler handler) { return handler.getAnnotationType(); } }); + this.typeAnnotationHandlers = typeAnnotationHandlers; Multimap, Class> annotationOverrides = collectAnnotationOverrides(annotationHandlers); Set> relevantAnnotationTypes = collectRelevantAnnotationTypes(((Map, PropertyAnnotationHandler>) Maps.uniqueIndex(annotationHandlers, new Function>() { @Override @@ -127,6 +130,11 @@ public TypeMetadata getTypeMetadata(final Class type) { private TypeMetadata createTypeMetadata(Class type) { RecordingValidationContext validationContext = new RecordingValidationContext(); + for (TypeAnnotationHandler annotationHandler : typeAnnotationHandlers) { + if (type.isAnnotationPresent(annotationHandler.getAnnotationType())) { + annotationHandler.validateTypeMetadata(type, validationContext); + } + } ImmutableSet properties = propertyExtractor.extractPropertyMetadata(type, validationContext); for (PropertyMetadata property : properties) { PropertyAnnotationHandler annotationHandler = annotationHandlers.get(property.getPropertyType()); @@ -161,6 +169,16 @@ public void collect(@Nullable String ownerPropertyPath, ParameterValidationConte } }); } + + @Override + public void visitErrorStrict(final String message) { + builder.add(new ValidationProblem() { + @Override + public void collect(@Nullable String ownerPropertyPath, ParameterValidationContext validationContext) { + validationContext.visitErrorStrict(message); + } + }); + } } private static class DefaultTypeMetadata implements TypeMetadata { diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/InspectionSchemeFactory.java b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/InspectionSchemeFactory.java index f826f41430794..09bb149c942c6 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/InspectionSchemeFactory.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/InspectionSchemeFactory.java @@ -24,6 +24,7 @@ import com.google.common.collect.ImmutableSet; import com.google.common.util.concurrent.UncheckedExecutionException; import org.gradle.api.internal.tasks.properties.annotations.PropertyAnnotationHandler; +import org.gradle.api.internal.tasks.properties.annotations.TypeAnnotationHandler; import org.gradle.cache.internal.CrossBuildInMemoryCacheFactory; import org.gradle.internal.UncheckedException; @@ -34,7 +35,8 @@ import java.util.Set; public class InspectionSchemeFactory { - private final Map, PropertyAnnotationHandler> allKnownHandlers; + private final Map, PropertyAnnotationHandler> allKnownPropertyHandlers; + private final ImmutableList allKnownTypeHandlers; private final CrossBuildInMemoryCacheFactory cacheFactory; // Assume for now that the annotations are all part of Gradle core and are never unloaded, so use strong references to the annotation types private final LoadingCache>, InspectionScheme> schemes = CacheBuilder.newBuilder().build(new CacheLoader>, InspectionScheme>() { @@ -42,29 +44,30 @@ public class InspectionSchemeFactory { public InspectionScheme load(Set> annotations) { ImmutableList.Builder builder = ImmutableList.builderWithExpectedSize(annotations.size()); for (Class annotation : annotations) { - PropertyAnnotationHandler handler = allKnownHandlers.get(annotation); + PropertyAnnotationHandler handler = allKnownPropertyHandlers.get(annotation); if (handler == null) { throw new IllegalArgumentException(String.format("Annotation @%s is not a registered annotation.", annotation.getSimpleName())); } builder.add(handler); } ImmutableList annotationHandlers = builder.build(); - ImmutableSet.Builder> otherAnnotations = ImmutableSet.builderWithExpectedSize(allKnownHandlers.size() - annotations.size()); - for (Class annotation : allKnownHandlers.keySet()) { + ImmutableSet.Builder> otherAnnotations = ImmutableSet.builderWithExpectedSize(allKnownPropertyHandlers.size() - annotations.size()); + for (Class annotation : allKnownPropertyHandlers.keySet()) { if (!annotations.contains(annotation)) { otherAnnotations.add(annotation); } } - return new InspectionSchemeImpl(annotationHandlers, otherAnnotations.build(), cacheFactory); + return new InspectionSchemeImpl(annotationHandlers, otherAnnotations.build(), allKnownTypeHandlers, cacheFactory); } }); - public InspectionSchemeFactory(List allKnownHandlers, CrossBuildInMemoryCacheFactory cacheFactory) { + public InspectionSchemeFactory(List allKnownPropertyHandlers, List allKnownTypeHandlers, CrossBuildInMemoryCacheFactory cacheFactory) { ImmutableMap.Builder, PropertyAnnotationHandler> builder = ImmutableMap.builder(); - for (PropertyAnnotationHandler handler : allKnownHandlers) { + for (PropertyAnnotationHandler handler : allKnownPropertyHandlers) { builder.put(handler.getAnnotationType(), handler); } - this.allKnownHandlers = builder.build(); + this.allKnownPropertyHandlers = builder.build(); + this.allKnownTypeHandlers = ImmutableList.copyOf(allKnownTypeHandlers); this.cacheFactory = cacheFactory; } @@ -83,8 +86,8 @@ private static class InspectionSchemeImpl implements InspectionScheme { private final DefaultPropertyWalker propertyWalker; private final DefaultTypeMetadataStore metadataStore; - public InspectionSchemeImpl(List annotationHandlers, Set> otherKnownAnnotations, CrossBuildInMemoryCacheFactory cacheFactory) { - metadataStore = new DefaultTypeMetadataStore(annotationHandlers, otherKnownAnnotations, cacheFactory); + public InspectionSchemeImpl(List annotationHandlers, Set> otherKnownAnnotations, List typeHandlers, CrossBuildInMemoryCacheFactory cacheFactory) { + metadataStore = new DefaultTypeMetadataStore(annotationHandlers, otherKnownAnnotations, typeHandlers, cacheFactory); propertyWalker = new DefaultPropertyWalker(metadataStore); } diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/PropertyValidationAccess.java b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/PropertyValidationAccess.java index d697ec0c44e1f..24d97fd6d9b3a 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/PropertyValidationAccess.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/PropertyValidationAccess.java @@ -217,6 +217,11 @@ public void visitError(String message) { // Treat all errors as warnings, for backwards compatibility problems.put(message, Boolean.FALSE); } + + @Override + public void visitErrorStrict(String message) { + problems.put(message, Boolean.TRUE); + } } } diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/annotations/CacheableTaskTypeAnnotationHandler.java b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/annotations/CacheableTaskTypeAnnotationHandler.java new file mode 100644 index 0000000000000..c72f4644a6869 --- /dev/null +++ b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/annotations/CacheableTaskTypeAnnotationHandler.java @@ -0,0 +1,37 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.api.internal.tasks.properties.annotations; + +import org.gradle.api.Task; +import org.gradle.api.tasks.CacheableTask; +import org.gradle.internal.reflect.ParameterValidationContext; + +import java.lang.annotation.Annotation; + +public class CacheableTaskTypeAnnotationHandler implements TypeAnnotationHandler { + @Override + public Class getAnnotationType() { + return CacheableTask.class; + } + + @Override + public void validateTypeMetadata(Class classWithAnnotationAttached, ParameterValidationContext visitor) { + if (!Task.class.isAssignableFrom(classWithAnnotationAttached)) { + visitor.visitErrorStrict(String.format("Cannot use @%s with type %s. This annotation cannot only be used with %s types.", getAnnotationType().getSimpleName(), classWithAnnotationAttached.getSimpleName(), Task.class.getSimpleName())); + } + } +} diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/annotations/TypeAnnotationHandler.java b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/annotations/TypeAnnotationHandler.java new file mode 100644 index 0000000000000..973cb25e4c2a5 --- /dev/null +++ b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/annotations/TypeAnnotationHandler.java @@ -0,0 +1,35 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.api.internal.tasks.properties.annotations; + +import org.gradle.internal.reflect.ParameterValidationContext; + +import java.lang.annotation.Annotation; + +public interface TypeAnnotationHandler { + /** + * The annotation type which this handler is responsible for. + * + * @return The annotation. + */ + Class getAnnotationType(); + + /** + * Visits problems associated with the given property, if any. + */ + void validateTypeMetadata(Class classWithAnnotationAttached, ParameterValidationContext visitor); +} diff --git a/subprojects/core/src/main/java/org/gradle/internal/service/scopes/ExecutionGlobalServices.java b/subprojects/core/src/main/java/org/gradle/internal/service/scopes/ExecutionGlobalServices.java index 2c164029fc0e2..31e070acf6231 100644 --- a/subprojects/core/src/main/java/org/gradle/internal/service/scopes/ExecutionGlobalServices.java +++ b/subprojects/core/src/main/java/org/gradle/internal/service/scopes/ExecutionGlobalServices.java @@ -23,6 +23,7 @@ import org.gradle.api.internal.tasks.properties.InspectionSchemeFactory; import org.gradle.api.internal.tasks.properties.PropertyWalker; import org.gradle.api.internal.tasks.properties.TaskScheme; +import org.gradle.api.internal.tasks.properties.annotations.CacheableTaskTypeAnnotationHandler; import org.gradle.api.internal.tasks.properties.annotations.DestroysPropertyAnnotationHandler; import org.gradle.api.internal.tasks.properties.annotations.InputDirectoryPropertyAnnotationHandler; import org.gradle.api.internal.tasks.properties.annotations.InputFilePropertyAnnotationHandler; @@ -36,6 +37,7 @@ import org.gradle.api.internal.tasks.properties.annotations.OutputFilePropertyAnnotationHandler; import org.gradle.api.internal.tasks.properties.annotations.OutputFilesPropertyAnnotationHandler; import org.gradle.api.internal.tasks.properties.annotations.PropertyAnnotationHandler; +import org.gradle.api.internal.tasks.properties.annotations.TypeAnnotationHandler; import org.gradle.api.tasks.Classpath; import org.gradle.api.tasks.CompileClasspath; import org.gradle.api.tasks.Console; @@ -60,8 +62,8 @@ import java.util.List; public class ExecutionGlobalServices { - InspectionSchemeFactory createInspectionSchemeFactory(List handlers, CrossBuildInMemoryCacheFactory cacheFactory) { - return new InspectionSchemeFactory(handlers, cacheFactory); + InspectionSchemeFactory createInspectionSchemeFactory(List propertyHandlers, List typeHandlers, CrossBuildInMemoryCacheFactory cacheFactory) { + return new InspectionSchemeFactory(propertyHandlers, typeHandlers, cacheFactory); } TaskScheme createTaskScheme(InspectionSchemeFactory inspectionSchemeFactory, InstantiatorFactory instantiatorFactory) { @@ -78,6 +80,10 @@ TaskClassInfoStore createTaskClassInfoStore(CrossBuildInMemoryCacheFactory cache return new DefaultTaskClassInfoStore(cacheFactory); } + TypeAnnotationHandler createCacheableTaskAnnotationHandler() { + return new CacheableTaskTypeAnnotationHandler(); + } + PropertyAnnotationHandler createInjectAnnotationHandler() { return new NoOpPropertyAnnotationHandler(Inject.class); } diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/project/taskfactory/AnnotationProcessingTaskFactoryTest.groovy b/subprojects/core/src/test/groovy/org/gradle/api/internal/project/taskfactory/AnnotationProcessingTaskFactoryTest.groovy index c95c2e44ee81d..a403b4a701268 100644 --- a/subprojects/core/src/test/groovy/org/gradle/api/internal/project/taskfactory/AnnotationProcessingTaskFactoryTest.groovy +++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/project/taskfactory/AnnotationProcessingTaskFactoryTest.groovy @@ -91,7 +91,7 @@ class AnnotationProcessingTaskFactoryTest extends AbstractProjectBuilderSpec { private ITaskFactory delegate def services = ServiceRegistryBuilder.builder().provider(new ExecutionGlobalServices()).build() def taskClassInfoStore = new DefaultTaskClassInfoStore(new TestCrossBuildInMemoryCacheFactory()) - def propertyWalker = new DefaultPropertyWalker(new DefaultTypeMetadataStore(services.getAll(PropertyAnnotationHandler), [] as Set, new TestCrossBuildInMemoryCacheFactory())) + def propertyWalker = new DefaultPropertyWalker(new DefaultTypeMetadataStore(services.getAll(PropertyAnnotationHandler), [] as Set, [] as List, new TestCrossBuildInMemoryCacheFactory())) @SuppressWarnings("GroovyUnusedDeclaration") private String inputValue = "value" diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/DefaultTaskInputsTest.groovy b/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/DefaultTaskInputsTest.groovy index c9a0f9160fef7..fc822aa062400 100644 --- a/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/DefaultTaskInputsTest.groovy +++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/DefaultTaskInputsTest.groovy @@ -61,7 +61,7 @@ class DefaultTaskInputsTest extends Specification { getDestroyables() >> Stub(TaskDestroyablesInternal) getLocalState() >> Stub(TaskLocalStateInternal) } - def walker = new DefaultPropertyWalker(new DefaultTypeMetadataStore([], [] as Set, new TestCrossBuildInMemoryCacheFactory())) + def walker = new DefaultPropertyWalker(new DefaultTypeMetadataStore([], [] as Set, [] as List, new TestCrossBuildInMemoryCacheFactory())) private final DefaultTaskInputs inputs = new DefaultTaskInputs(task, taskStatusNagger, walker, fileCollectionFactory) def "default values"() { diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/DefaultTaskOutputsTest.groovy b/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/DefaultTaskOutputsTest.groovy index 8540edec2ec3e..aa05f26a26e3c 100644 --- a/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/DefaultTaskOutputsTest.groovy +++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/DefaultTaskOutputsTest.groovy @@ -63,7 +63,7 @@ class DefaultTaskOutputsTest extends Specification { getLocalState() >> Stub(TaskLocalStateInternal) } - private final DefaultTaskOutputs outputs = new DefaultTaskOutputs(task, taskStatusNagger, new DefaultPropertyWalker(new DefaultTypeMetadataStore([], [] as Set, new TestCrossBuildInMemoryCacheFactory())), fileCollectionFactory) + def outputs = new DefaultTaskOutputs(task, taskStatusNagger, new DefaultPropertyWalker(new DefaultTypeMetadataStore([], [] as Set, [] as List, new TestCrossBuildInMemoryCacheFactory())), fileCollectionFactory) void hasNoOutputsByDefault() { setup: diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/properties/CustomCacheable.java b/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/properties/CustomCacheable.java new file mode 100644 index 0000000000000..98fc777c259ad --- /dev/null +++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/properties/CustomCacheable.java @@ -0,0 +1,27 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.api.internal.tasks.properties; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +@interface CustomCacheable { +} diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/properties/DefaultPropertyWalkerTest.groovy b/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/properties/DefaultPropertyWalkerTest.groovy index 518356fe3dcb6..41cc353cdae67 100644 --- a/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/properties/DefaultPropertyWalkerTest.groovy +++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/properties/DefaultPropertyWalkerTest.groovy @@ -228,6 +228,6 @@ class DefaultPropertyWalkerTest extends AbstractProjectBuilderSpec { } private visitProperties(TaskInternal task) { - new DefaultPropertyWalker(new DefaultTypeMetadataStore(services.getAll(PropertyAnnotationHandler), [] as Set, new TestCrossBuildInMemoryCacheFactory())).visitProperties(task, validationContext, visitor) + new DefaultPropertyWalker(new DefaultTypeMetadataStore(services.getAll(PropertyAnnotationHandler), [] as Set, [] as List, new TestCrossBuildInMemoryCacheFactory())).visitProperties(task, validationContext, visitor) } } diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/properties/DefaultTypeMetadataStoreTest.groovy b/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/properties/DefaultTypeMetadataStoreTest.groovy index 9daed29281dac..9649f2ca5fcba 100644 --- a/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/properties/DefaultTypeMetadataStoreTest.groovy +++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/properties/DefaultTypeMetadataStoreTest.groovy @@ -27,6 +27,7 @@ import org.gradle.api.internal.HasConvention import org.gradle.api.internal.IConventionAware import org.gradle.api.internal.tasks.properties.annotations.ClasspathPropertyAnnotationHandler import org.gradle.api.internal.tasks.properties.annotations.PropertyAnnotationHandler +import org.gradle.api.internal.tasks.properties.annotations.TypeAnnotationHandler import org.gradle.api.plugins.ExtensionAware import org.gradle.api.tasks.Classpath import org.gradle.api.tasks.Console @@ -65,7 +66,7 @@ class DefaultTypeMetadataStoreTest extends Specification { @Shared GroovyClassLoader groovyClassLoader def services = ServiceRegistryBuilder.builder().provider(new ExecutionGlobalServices()).build() - def metadataStore = new DefaultTypeMetadataStore(services.getAll(PropertyAnnotationHandler), [] as Set, new TestCrossBuildInMemoryCacheFactory()) + def metadataStore = new DefaultTypeMetadataStore(services.getAll(PropertyAnnotationHandler), [] as Set, [] as List, new TestCrossBuildInMemoryCacheFactory()) def setupSpec() { groovyClassLoader = new GroovyClassLoader(getClass().classLoader) @@ -75,11 +76,15 @@ class DefaultTypeMetadataStoreTest extends Specification { @SearchPath FileCollection searchPath } + @CustomCacheable + static class TypeWithCustomAnnotation { + } + def "can use custom annotation processor"() { def annotationHandler = Stub(PropertyAnnotationHandler) _ * annotationHandler.annotationType >> SearchPath - def metadataStore = new DefaultTypeMetadataStore([annotationHandler], [] as Set, new TestCrossBuildInMemoryCacheFactory()) + def metadataStore = new DefaultTypeMetadataStore([annotationHandler], [] as Set, [] as Set, new TestCrossBuildInMemoryCacheFactory()) when: def typeMetadata = metadataStore.getTypeMetadata(TaskWithCustomAnnotation) @@ -101,7 +106,7 @@ class DefaultTypeMetadataStoreTest extends Specification { context.visitError(null, metadata.propertyName, "is broken") } - def metadataStore = new DefaultTypeMetadataStore([annotationHandler], [] as Set, new TestCrossBuildInMemoryCacheFactory()) + def metadataStore = new DefaultTypeMetadataStore([annotationHandler], [] as Set, [] as Set, new TestCrossBuildInMemoryCacheFactory()) when: def typeMetadata = metadataStore.getTypeMetadata(TaskWithCustomAnnotation) @@ -114,6 +119,28 @@ class DefaultTypeMetadataStoreTest extends Specification { collectProblems(typeMetadata) == ["Property 'searchPath' is broken."] } + def "custom annotation processor can inspect for static type problems"() { + def annotationHandler = Stub(TypeAnnotationHandler) + _ * annotationHandler.annotationType >> CustomCacheable + _ * annotationHandler.validateTypeMetadata(_, _) >> { Class type, ParameterValidationContext context -> + context.visitError("type is broken") + } + + def metadataStore = new DefaultTypeMetadataStore([], [] as Set, [annotationHandler] as Set, new TestCrossBuildInMemoryCacheFactory()) + + when: + def taskMetadata = metadataStore.getTypeMetadata(DefaultTask) + + then: + collectProblems(taskMetadata).empty + + when: + def typeMetadata = metadataStore.getTypeMetadata(TypeWithCustomAnnotation) + + then: + collectProblems(typeMetadata) == ["type is broken"] + } + @Unroll def "can override @#parentAnnotation.simpleName property type with @#childAnnotation.simpleName"() { def parentTask = groovyClassLoader.parseClass """ @@ -213,7 +240,7 @@ class DefaultTypeMetadataStoreTest extends Specification { // need to declare their @Classpath properties as @InputFiles as well @Issue("https://github.com/gradle/gradle/issues/913") def "@Classpath takes precedence over @InputFiles when both are declared on property"() { - def metadataStore = new DefaultTypeMetadataStore(services.getAll(PropertyAnnotationHandler) + [new ClasspathPropertyAnnotationHandler()], [] as Set, new TestCrossBuildInMemoryCacheFactory()) + def metadataStore = new DefaultTypeMetadataStore(services.getAll(PropertyAnnotationHandler) + [new ClasspathPropertyAnnotationHandler()], [] as Set, [] as Set, new TestCrossBuildInMemoryCacheFactory()) when: def typeMetadata = metadataStore.getTypeMetadata(ClasspathPropertyTask) diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/properties/InspectionSchemeFactoryTest.groovy b/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/properties/InspectionSchemeFactoryTest.groovy index f7f637fc3738f..491cedbbec62e 100644 --- a/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/properties/InspectionSchemeFactoryTest.groovy +++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/properties/InspectionSchemeFactoryTest.groovy @@ -27,7 +27,7 @@ import java.lang.annotation.RetentionPolicy class InspectionSchemeFactoryTest extends Specification { def handler1 = handler(Thing1) def handler2 = handler(Thing2) - def factory = new InspectionSchemeFactory([handler1, handler2], new TestCrossBuildInMemoryCacheFactory()) + def factory = new InspectionSchemeFactory([handler1, handler2], [], new TestCrossBuildInMemoryCacheFactory()) def "creates inspection scheme"() { def scheme = factory.inspectionScheme([Thing1, Thing2]) diff --git a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformValuesInjectionIntegrationTest.groovy b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformValuesInjectionIntegrationTest.groovy index ff8608e4d5c48..0bfd9a364ecc1 100644 --- a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformValuesInjectionIntegrationTest.groovy +++ b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformValuesInjectionIntegrationTest.groovy @@ -16,6 +16,7 @@ package org.gradle.integtests.resolve.transform + import org.gradle.api.artifacts.transform.InputArtifact import org.gradle.api.artifacts.transform.InputArtifactDependencies import org.gradle.api.file.FileCollection @@ -237,6 +238,51 @@ class ArtifactTransformValuesInjectionIntegrationTest extends AbstractDependency failure.assertHasCause("Cannot query parameters for artifact transform without parameters.") } + def "transform parameters type cannot use caching annotations"() { + settingsFile << """ + include 'a', 'b', 'c' + """ + setupBuildWithColorTransform { + params(""" + extension = 'green' + """) + } + buildFile << """ + project(':a') { + dependencies { + implementation project(':b') + implementation project(':c') + } + } + + @AssociatedTransformAction(MakeGreenAction) + @CacheableTask @CacheableTransformAction + interface MakeGreen { + @Input + String getExtension() + void setExtension(String value) + } + + abstract class MakeGreenAction implements TransformAction { + @TransformParameters + abstract MakeGreen getParameters() + + void transform(TransformOutputs outputs) { + throw new RuntimeException() + } + } +""" + + when: + fails(":a:resolve") + + then: + failure.assertThatDescription(matchesRegexp('Cannot isolate parameters MakeGreen\\$Inject@.* of artifact transform MakeGreenAction')) + failure.assertHasCause('Some problems were found with the configuration of the artifact transform parameter MakeGreen.') + failure.assertHasCause("Cannot use @CacheableTask with type MakeGreen\$Inject. This annotation cannot only be used with Task types.") + failure.assertHasCause("Cannot use @CacheableTransformAction with type MakeGreen\$Inject. This annotation cannot only be used with TransformAction types.") + } + @Unroll def "transform parameters type cannot use annotation @#annotation.simpleName"() { settingsFile << """ @@ -390,6 +436,47 @@ class ArtifactTransformValuesInjectionIntegrationTest extends AbstractDependency failure.assertHasCause("Property 'absolutePathSensitivityDependencies' is declared to be sensitive to absolute paths. This is not allowed for cacheable transforms.") } + def "transform action type cannot use cacheable task annotation"() { + settingsFile << """ + include 'a', 'b', 'c' + """ + setupBuildWithColorTransform { + params(""" + extension = 'green' + """) + } + buildFile << """ + project(':a') { + dependencies { + implementation project(':b') + implementation project(':c') + } + } + + @AssociatedTransformAction(MakeGreenAction) + interface MakeGreen { + @Input + String getExtension() + void setExtension(String value) + } + + @CacheableTask + abstract class MakeGreenAction implements TransformAction { + void transform(TransformOutputs outputs) { + throw new RuntimeException() + } + } +""" + + when: + fails(":a:resolve") + + then: + failure.assertHasDescription('A problem occurred evaluating root project') + failure.assertHasCause('A problem was found with the configuration of MakeGreenAction.') + failure.assertHasCause("Cannot use @CacheableTask with type MakeGreenAction. This annotation cannot only be used with Task types.") + } + @Unroll def "transform action type cannot use annotation @#annotation.simpleName"() { settingsFile << """ @@ -639,6 +726,50 @@ abstract class MakeGreen implements TransformAction { failure.assertHasCause("No service of type class ${File.name} available.") } + def "task implementation cannot use cacheable transform annotation"() { + buildFile << """ + @CacheableTransformAction + class MyTask extends DefaultTask { + File getThing() { null } + } + + tasks.create('broken', MyTask) + """ + + expect: + fails('broken') + failure.assertHasDescription("A problem occurred evaluating root project") + failure.assertHasCause("Could not create task ':broken'.") + failure.assertHasCause("A problem was found with the configuration of task ':broken'.") + failure.assertHasCause("Cannot use @CacheableTransformAction with type MyTask_Decorated. This annotation cannot only be used with TransformAction types.") + } + + def "task @Nested bean cannot use cacheable annotations"() { + buildFile << """ + class MyTask extends DefaultTask { + @Nested + Options getThing() { new Options() } + + @TaskAction + void go() { } + } + + @CacheableTransformAction @CacheableTask + class Options { + } + + tasks.create('broken', MyTask) + """ + + expect: + // Probably should be eager + fails('broken') + failure.assertHasDescription("Could not determine the dependencies of task ':broken'.") + failure.assertHasCause("Some problems were found with the configuration of task ':broken'.") + failure.assertHasCause("Cannot use @CacheableTask with type Options. This annotation cannot only be used with Task types.") + failure.assertHasCause("Cannot use @CacheableTransformAction with type Options. This annotation cannot only be used with TransformAction types.") + } + @Unroll def "task implementation cannot use injection annotation @#annotation.simpleName"() { buildFile << """ @@ -652,6 +783,7 @@ abstract class MakeGreen implements TransformAction { expect: fails('broken') + failure.assertHasDescription("A problem occurred evaluating root project") failure.assertHasCause("Could not create task of type 'MyTask'.") failure.assertHasCause("Could not generate a decorated class for class MyTask.") failure.assertHasCause("Cannot use @${annotation.simpleName} annotation on method MyTask.getThing().") diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/DependencyManagementGlobalScopeServices.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/DependencyManagementGlobalScopeServices.java index 7af1b702b5814..7b64f4c95404d 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/DependencyManagementGlobalScopeServices.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/DependencyManagementGlobalScopeServices.java @@ -35,10 +35,12 @@ import org.gradle.api.internal.artifacts.ivyservice.moduleconverter.dependencies.ProjectIvyDependencyDescriptorFactory; import org.gradle.api.internal.artifacts.transform.ArtifactTransformActionScheme; import org.gradle.api.internal.artifacts.transform.ArtifactTransformParameterScheme; +import org.gradle.api.internal.artifacts.transform.CacheableTransformTypeAnnotationHandler; import org.gradle.api.internal.artifacts.transform.InputArtifactAnnotationHandler; import org.gradle.api.internal.artifacts.transform.InputArtifactDependenciesAnnotationHandler; import org.gradle.api.internal.tasks.properties.InspectionScheme; import org.gradle.api.internal.tasks.properties.InspectionSchemeFactory; +import org.gradle.api.internal.tasks.properties.annotations.TypeAnnotationHandler; import org.gradle.api.tasks.Classpath; import org.gradle.api.tasks.CompileClasspath; import org.gradle.api.tasks.Console; @@ -108,6 +110,10 @@ ProducerGuard createProducerAccess() { return ProducerGuard.adaptive(); } + TypeAnnotationHandler createCacheableTransformAnnotationHandler() { + return new CacheableTransformTypeAnnotationHandler(); + } + InputArtifactAnnotationHandler createInputArtifactAnnotationHandler() { return new InputArtifactAnnotationHandler(); } diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/CacheableTransformTypeAnnotationHandler.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/CacheableTransformTypeAnnotationHandler.java new file mode 100644 index 0000000000000..b4262ad09106f --- /dev/null +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/CacheableTransformTypeAnnotationHandler.java @@ -0,0 +1,38 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.api.internal.artifacts.transform; + +import org.gradle.api.artifacts.transform.CacheableTransformAction; +import org.gradle.api.artifacts.transform.TransformAction; +import org.gradle.api.internal.tasks.properties.annotations.TypeAnnotationHandler; +import org.gradle.internal.reflect.ParameterValidationContext; + +import java.lang.annotation.Annotation; + +public class CacheableTransformTypeAnnotationHandler implements TypeAnnotationHandler { + @Override + public Class getAnnotationType() { + return CacheableTransformAction.class; + } + + @Override + public void validateTypeMetadata(Class classWithAnnotationAttached, ParameterValidationContext visitor) { + if (!TransformAction.class.isAssignableFrom(classWithAnnotationAttached)) { + visitor.visitErrorStrict(String.format("Cannot use @%s with type %s. This annotation cannot only be used with %s types.", getAnnotationType().getSimpleName(), classWithAnnotationAttached.getSimpleName(), TransformAction.class.getSimpleName())); + } + } +} diff --git a/subprojects/model-core/src/main/java/org/gradle/internal/reflect/ParameterValidationContext.java b/subprojects/model-core/src/main/java/org/gradle/internal/reflect/ParameterValidationContext.java index 7d3c5f8d58b84..5459d1b04a65b 100644 --- a/subprojects/model-core/src/main/java/org/gradle/internal/reflect/ParameterValidationContext.java +++ b/subprojects/model-core/src/main/java/org/gradle/internal/reflect/ParameterValidationContext.java @@ -27,6 +27,10 @@ public void visitError(@Nullable String ownerPath, String propertyName, String m @Override public void visitError(String message) { } + + @Override + public void visitErrorStrict(String message) { + } }; /** @@ -38,4 +42,9 @@ public void visitError(String message) { * Visits a validation error. */ void visitError(String message); + + /** + * Visits a strict validation error. Strict errors are not ignored for tasks, whereas for backwards compatibility other errors are ignored (at runtime) or treated as warnings (at plugin build time). + */ + void visitErrorStrict(String message); } diff --git a/subprojects/plugin-development/src/integTest/groovy/org/gradle/plugin/devel/tasks/ValidateTaskPropertiesIntegrationTest.groovy b/subprojects/plugin-development/src/integTest/groovy/org/gradle/plugin/devel/tasks/ValidateTaskPropertiesIntegrationTest.groovy index eb4c1b0870d7f..a445b08ad92f9 100644 --- a/subprojects/plugin-development/src/integTest/groovy/org/gradle/plugin/devel/tasks/ValidateTaskPropertiesIntegrationTest.groovy +++ b/subprojects/plugin-development/src/integTest/groovy/org/gradle/plugin/devel/tasks/ValidateTaskPropertiesIntegrationTest.groovy @@ -16,6 +16,7 @@ package org.gradle.plugin.devel.tasks + import org.gradle.api.ReplacedBy import org.gradle.api.artifacts.transform.InputArtifact import org.gradle.api.artifacts.transform.InputArtifactDependencies @@ -230,6 +231,44 @@ class ValidateTaskPropertiesIntegrationTest extends AbstractIntegrationSpec { InputArtifactDependencies | _ } + def "validates task caching annotations"() { + file("src/main/java/MyTask.java") << """ + import org.gradle.api.*; + import org.gradle.api.tasks.*; + import org.gradle.api.artifacts.transform.*; + + @CacheableTransformAction + public class MyTask extends DefaultTask { + @Nested + Options getOptions() { + return null; + } + + @CacheableTask @CacheableTransformAction + public static class Options { + @Input + String getNestedThing() { + return null; + } + } + } + """ + + expect: + fails("validateTaskProperties") + failure.assertHasDescription("Execution failed for task ':validateTaskProperties'.") + failure.assertHasCause("Task property validation failed. See") + failure.assertHasCause("Error: Cannot use @CacheableTask with type Options. This annotation cannot only be used with Task types.") + failure.assertHasCause("Error: Cannot use @CacheableTransformAction with type MyTask. This annotation cannot only be used with TransformAction types.") + failure.assertHasCause("Error: Cannot use @CacheableTransformAction with type Options. This annotation cannot only be used with TransformAction types.") + + file("build/reports/task-properties/report.txt").text == """ + Error: Cannot use @CacheableTask with type Options. This annotation cannot only be used with Task types. + Error: Cannot use @CacheableTransformAction with type MyTask. This annotation cannot only be used with TransformAction types. + Error: Cannot use @CacheableTransformAction with type Options. This annotation cannot only be used with TransformAction types. + """.stripIndent().trim() + } + def "detects missing annotation on Groovy properties"() { buildFile << """ apply plugin: "groovy" From 6d6f2920e06b3d9e432f0f6a47832d5b9c610a3f Mon Sep 17 00:00:00 2001 From: Adam Murdoch Date: Tue, 26 Feb 2019 09:43:01 +1100 Subject: [PATCH 216/853] Change `ValidateTaskProperties` task to also validate the properties of artifact transform actions and parameter types. The task treats all problems with these types as errors, which is the same as the behaviour runtime. This is another step towards reporting on problems with all plugin types consistently at runtime and plugin build time, and later in other places too. There are still some task type checks that are reported only by the validation task and some artifact transform checks that are reported only at runtime. These can be cleaned up later. --- .../properties/PropertyValidationAccess.java | 102 ++++++++++---- .../internal/tasks/properties/TaskScheme.java | 13 +- .../internal/tasks/properties/TypeScheme.java | 23 ++++ ...sformValuesInjectionIntegrationTest.groovy | 12 +- .../ArtifactTransformActionScheme.java | 15 ++- .../ArtifactTransformParameterScheme.java | 15 ++- ...cheableTransformTypeAnnotationHandler.java | 4 +- ...lidateTaskPropertiesIntegrationTest.groovy | 126 +++++++++++++++++- .../devel/tasks/ValidateTaskProperties.java | 19 +-- 9 files changed, 270 insertions(+), 59 deletions(-) create mode 100644 subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/TypeScheme.java diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/PropertyValidationAccess.java b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/PropertyValidationAccess.java index 24d97fd6d9b3a..de694e271bbcf 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/PropertyValidationAccess.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/PropertyValidationAccess.java @@ -1,5 +1,5 @@ /* - * Copyright 2017 the original author or authors. + * Copyright 2019 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -22,6 +22,9 @@ import org.gradle.api.Named; import org.gradle.api.NonNullApi; import org.gradle.api.Task; +import org.gradle.api.artifacts.transform.CacheableTransform; +import org.gradle.api.artifacts.transform.TransformAction; +import org.gradle.api.internal.TaskInternal; import org.gradle.api.internal.project.taskfactory.TaskClassInfoStore; import org.gradle.api.provider.Provider; import org.gradle.api.tasks.InputDirectory; @@ -51,7 +54,7 @@ import java.util.Queue; /** - * Class for easy access to task property validation from the validator task. + * Class for easy access to property validation from the validator task. */ @NonNullApi public class PropertyValidationAccess { @@ -68,7 +71,7 @@ InputDirectory.class, new MissingPathSensitivityValidator(true) private static final PropertyValidationAccess INSTANCE = new PropertyValidationAccess(); private final TaskClassInfoStore taskClassInfoStore; - private final TypeMetadataStore metadataStore; + private final List typeSchemes; private PropertyValidationAccess() { ServiceRegistryBuilder builder = ServiceRegistryBuilder.builder().displayName("Global services"); @@ -87,24 +90,73 @@ void configure(ServiceRegistration registration) { }); ServiceRegistry services = builder.build(); taskClassInfoStore = services.get(TaskClassInfoStore.class); - metadataStore = services.get(TaskScheme.class).getInspectionScheme().getMetadataStore(); + typeSchemes = services.getAll(TypeScheme.class); } @SuppressWarnings("unused") public static void collectTaskValidationProblems(Class topLevelBean, Map problems, boolean enableStricterValidation) { - INSTANCE.collectValidationProblems(topLevelBean, problems, enableStricterValidation); + INSTANCE.collectTypeValidationProblems(topLevelBean, problems, enableStricterValidation); } - private void collectValidationProblems(Class topLevelBean, Map problems, boolean enableStricterValidation) { + @SuppressWarnings("unused") + public static void collectValidationProblems(Class topLevelBean, Map problems, boolean enableStricterValidation) { + INSTANCE.collectTypeValidationProblems(topLevelBean, problems, enableStricterValidation); + } + + private void collectTypeValidationProblems(Class topLevelBean, Map problems, boolean enableStricterValidation) { + // Skip this for now + if (topLevelBean.equals(TaskInternal.class)) { + return; + } + + TypeMetadataStore metadataStore = null; + for (TypeScheme typeScheme : typeSchemes) { + if (typeScheme.appliesTo(topLevelBean)) { + metadataStore = typeScheme.getMetadataStore(); + break; + } + } + if (metadataStore == null) { + // Don't know about this type + return; + } + + boolean cacheable; + boolean mapErrorsToWarnings; + if (Task.class.isAssignableFrom(topLevelBean)) { + cacheable = taskClassInfoStore.getTaskClassInfo(Cast.>uncheckedCast(topLevelBean)).isCacheable(); + // Treat all errors as warnings, for backwards compatibility + mapErrorsToWarnings = true; + } else if (TransformAction.class.isAssignableFrom(topLevelBean)) { + cacheable = topLevelBean.isAnnotationPresent(CacheableTransform.class); + mapErrorsToWarnings = false; + } else { + cacheable = false; + mapErrorsToWarnings = false; + } + Queue> queue = new ArrayDeque>(); BeanTypeNodeFactory nodeFactory = new BeanTypeNodeFactory(metadataStore); queue.add(nodeFactory.createRootNode(TypeToken.of(topLevelBean))); - boolean cacheable = taskClassInfoStore.getTaskClassInfo(Cast.>uncheckedCast(topLevelBean)).isCacheable(); boolean stricterValidation = enableStricterValidation || cacheable; while (!queue.isEmpty()) { BeanTypeNode node = queue.remove(); - node.visit(topLevelBean, stricterValidation, problems, queue, nodeFactory); + node.visit(topLevelBean, stricterValidation, new ProblemCollector(problems, mapErrorsToWarnings), queue, nodeFactory); + } + } + + private static class ProblemCollector { + final Map problems; + private final boolean mapErrorsToWarnings; + + public ProblemCollector(Map problems, boolean mapErrorsToWarnings) { + this.problems = problems; + this.mapErrorsToWarnings = mapErrorsToWarnings; + } + + void error(String message, boolean strict) { + problems.put(message, strict || !mapErrorsToWarnings); } } @@ -147,11 +199,12 @@ protected BeanTypeNode(@Nullable BeanTypeNode parentNode, @Nullable String pr this.beanType = beanType; } - public abstract void visit(Class topLevelBean, boolean stricterValidation, Map problems, Queue> queue, BeanTypeNodeFactory nodeFactory); + public abstract void visit(Class topLevelBean, boolean stricterValidation, ProblemCollector problems, Queue> queue, BeanTypeNodeFactory nodeFactory); public boolean nodeCreatesCycle(TypeToken childType) { return findNodeCreatingCycle(childType, Equivalence.equals()) != null; } + private final TypeToken beanType; protected TypeToken extractNestedType(Class parameterizedSuperClass, int typeParameterIndex) { @@ -171,7 +224,7 @@ public NestedBeanTypeNode(@Nullable BeanTypeNode parentNode, @Nullable String } @Override - public void visit(final Class topLevelBean, boolean stricterValidation, final Map problems, Queue> queue, BeanTypeNodeFactory nodeFactory) { + public void visit(final Class topLevelBean, boolean stricterValidation, ProblemCollector problems, Queue> queue, BeanTypeNodeFactory nodeFactory) { TypeMetadata typeMetadata = getTypeMetadata(); ParameterValidationContext validationContext = new CollectingParameterValidationContext(topLevelBean, problems); typeMetadata.collectValidationFailures(getPropertyName(), validationContext); @@ -193,34 +246,39 @@ private static TypeToken unpackProvider(Method method) { Class rawType = method.getReturnType(); TypeToken genericReturnType = TypeToken.of(method.getGenericReturnType()); if (Provider.class.isAssignableFrom(rawType)) { - return PropertyValidationAccess.extractNestedType(Cast.>>uncheckedCast(genericReturnType), Provider.class, 0); + return PropertyValidationAccess.extractNestedType(Cast.>>uncheckedCast(genericReturnType), Provider.class, 0); } return genericReturnType; } private class CollectingParameterValidationContext implements ParameterValidationContext { private final Class topLevelBean; - private final Map problems; + private final ProblemCollector problems; - public CollectingParameterValidationContext(Class topLevelBean, Map problems) { + public CollectingParameterValidationContext(Class topLevelBean, ProblemCollector problems) { this.topLevelBean = topLevelBean; this.problems = problems; } @Override public void visitError(@Nullable String ownerPath, String propertyName, String message) { - visitError(String.format("Task type '%s': property '%s' %s.", topLevelBean.getName(), getQualifiedPropertyName(propertyName), message)); + String decoratedMessage; + if (Task.class.isAssignableFrom(topLevelBean)) { + decoratedMessage = String.format("Task type '%s': property '%s' %s.", topLevelBean.getName(), getQualifiedPropertyName(propertyName), message); + } else { + decoratedMessage = String.format("Type '%s': property '%s' %s.", topLevelBean.getName(), getQualifiedPropertyName(propertyName), message); + } + visitError(decoratedMessage); } @Override public void visitError(String message) { - // Treat all errors as warnings, for backwards compatibility - problems.put(message, Boolean.FALSE); + problems.error(message, false); } @Override public void visitErrorStrict(String message) { - problems.put(message, Boolean.TRUE); + problems.error(message, true); } } } @@ -238,7 +296,7 @@ private String determinePropertyName(TypeToken nestedType) { } @Override - public void visit(Class topLevelBean, boolean stricterValidation, Map problems, Queue> queue, BeanTypeNodeFactory nodeFactory) { + public void visit(Class topLevelBean, boolean stricterValidation, ProblemCollector problems, Queue> queue, BeanTypeNodeFactory nodeFactory) { TypeToken nestedType = extractNestedType(Iterable.class, 0); nodeFactory.createAndAddToQueue(this, determinePropertyName(nestedType), nestedType, queue); } @@ -251,7 +309,7 @@ public MapBeanTypeNode(@Nullable BeanTypeNode parentNode, @Nullable String pa } @Override - public void visit(Class topLevelBean, boolean stricterValidation, Map problems, Queue> queue, BeanTypeNodeFactory nodeFactory) { + public void visit(Class topLevelBean, boolean stricterValidation, ProblemCollector problems, Queue> queue, BeanTypeNodeFactory nodeFactory) { TypeToken nestedType = extractNestedType(Map.class, 1); nodeFactory.createAndAddToQueue(this, getQualifiedPropertyName(""), nestedType, queue); } @@ -261,12 +319,6 @@ private interface PropertyValidator { void validate(@Nullable String ownerPath, PropertyMetadata metadata, ParameterValidationContext validationContext); } - private static class InputOnFileTypeValidator implements PropertyValidator { - @Override - public void validate(@Nullable String ownerPath, PropertyMetadata metadata, ParameterValidationContext validationContext) { - } - } - private static class MissingPathSensitivityValidator implements PropertyValidator { final boolean stricterValidation; diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/TaskScheme.java b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/TaskScheme.java index 24a9cf8c028b6..fb5f6b20343d7 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/TaskScheme.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/TaskScheme.java @@ -16,9 +16,10 @@ package org.gradle.api.internal.tasks.properties; +import org.gradle.api.Task; import org.gradle.internal.instantiation.InstantiationScheme; -public class TaskScheme { +public class TaskScheme implements TypeScheme { private final InstantiationScheme instantiationScheme; private final InspectionScheme inspectionScheme; @@ -27,6 +28,16 @@ public TaskScheme(InstantiationScheme instantiationScheme, InspectionScheme insp this.inspectionScheme = inspectionScheme; } + @Override + public TypeMetadataStore getMetadataStore() { + return inspectionScheme.getMetadataStore(); + } + + @Override + public boolean appliesTo(Class type) { + return Task.class.isAssignableFrom(type); + } + public InstantiationScheme getInstantiationScheme() { return instantiationScheme; } diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/TypeScheme.java b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/TypeScheme.java new file mode 100644 index 0000000000000..0745c37eb1ce1 --- /dev/null +++ b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/TypeScheme.java @@ -0,0 +1,23 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.api.internal.tasks.properties; + +public interface TypeScheme { + TypeMetadataStore getMetadataStore(); + + boolean appliesTo(Class type); +} diff --git a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformValuesInjectionIntegrationTest.groovy b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformValuesInjectionIntegrationTest.groovy index 0bfd9a364ecc1..aac8b91583fa7 100644 --- a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformValuesInjectionIntegrationTest.groovy +++ b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformValuesInjectionIntegrationTest.groovy @@ -256,7 +256,7 @@ class ArtifactTransformValuesInjectionIntegrationTest extends AbstractDependency } @AssociatedTransformAction(MakeGreenAction) - @CacheableTask @CacheableTransformAction + @CacheableTask @CacheableTransform interface MakeGreen { @Input String getExtension() @@ -280,7 +280,7 @@ class ArtifactTransformValuesInjectionIntegrationTest extends AbstractDependency failure.assertThatDescription(matchesRegexp('Cannot isolate parameters MakeGreen\\$Inject@.* of artifact transform MakeGreenAction')) failure.assertHasCause('Some problems were found with the configuration of the artifact transform parameter MakeGreen.') failure.assertHasCause("Cannot use @CacheableTask with type MakeGreen\$Inject. This annotation cannot only be used with Task types.") - failure.assertHasCause("Cannot use @CacheableTransformAction with type MakeGreen\$Inject. This annotation cannot only be used with TransformAction types.") + failure.assertHasCause("Cannot use @CacheableTransform with type MakeGreen\$Inject. This annotation cannot only be used with TransformAction types.") } @Unroll @@ -728,7 +728,7 @@ abstract class MakeGreen implements TransformAction { def "task implementation cannot use cacheable transform annotation"() { buildFile << """ - @CacheableTransformAction + @CacheableTransform class MyTask extends DefaultTask { File getThing() { null } } @@ -741,7 +741,7 @@ abstract class MakeGreen implements TransformAction { failure.assertHasDescription("A problem occurred evaluating root project") failure.assertHasCause("Could not create task ':broken'.") failure.assertHasCause("A problem was found with the configuration of task ':broken'.") - failure.assertHasCause("Cannot use @CacheableTransformAction with type MyTask_Decorated. This annotation cannot only be used with TransformAction types.") + failure.assertHasCause("Cannot use @CacheableTransform with type MyTask_Decorated. This annotation cannot only be used with TransformAction types.") } def "task @Nested bean cannot use cacheable annotations"() { @@ -754,7 +754,7 @@ abstract class MakeGreen implements TransformAction { void go() { } } - @CacheableTransformAction @CacheableTask + @CacheableTransform @CacheableTask class Options { } @@ -767,7 +767,7 @@ abstract class MakeGreen implements TransformAction { failure.assertHasDescription("Could not determine the dependencies of task ':broken'.") failure.assertHasCause("Some problems were found with the configuration of task ':broken'.") failure.assertHasCause("Cannot use @CacheableTask with type Options. This annotation cannot only be used with Task types.") - failure.assertHasCause("Cannot use @CacheableTransformAction with type Options. This annotation cannot only be used with TransformAction types.") + failure.assertHasCause("Cannot use @CacheableTransform with type Options. This annotation cannot only be used with TransformAction types.") } @Unroll diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/ArtifactTransformActionScheme.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/ArtifactTransformActionScheme.java index a9fe29d23f801..539ad28e70d50 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/ArtifactTransformActionScheme.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/ArtifactTransformActionScheme.java @@ -16,10 +16,13 @@ package org.gradle.api.internal.artifacts.transform; +import org.gradle.api.artifacts.transform.TransformAction; import org.gradle.api.internal.tasks.properties.InspectionScheme; +import org.gradle.api.internal.tasks.properties.TypeMetadataStore; +import org.gradle.api.internal.tasks.properties.TypeScheme; import org.gradle.internal.instantiation.InstantiationScheme; -public class ArtifactTransformActionScheme { +public class ArtifactTransformActionScheme implements TypeScheme { private final InstantiationScheme instantiationScheme; private final InspectionScheme inspectionScheme; private final InstantiationScheme legacyInstantiationScheme; @@ -30,6 +33,16 @@ public ArtifactTransformActionScheme(InstantiationScheme instantiationScheme, In this.legacyInstantiationScheme = legacyInstantiationScheme; } + @Override + public TypeMetadataStore getMetadataStore() { + return inspectionScheme.getMetadataStore(); + } + + @Override + public boolean appliesTo(Class type) { + return TransformAction.class.isAssignableFrom(type); + } + public InspectionScheme getInspectionScheme() { return inspectionScheme; } diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/ArtifactTransformParameterScheme.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/ArtifactTransformParameterScheme.java index feed182b9daaa..8923eca6db193 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/ArtifactTransformParameterScheme.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/ArtifactTransformParameterScheme.java @@ -16,10 +16,13 @@ package org.gradle.api.internal.artifacts.transform; +import org.gradle.api.artifacts.transform.AssociatedTransformAction; import org.gradle.api.internal.tasks.properties.InspectionScheme; +import org.gradle.api.internal.tasks.properties.TypeMetadataStore; +import org.gradle.api.internal.tasks.properties.TypeScheme; import org.gradle.internal.instantiation.InstantiationScheme; -public class ArtifactTransformParameterScheme { +public class ArtifactTransformParameterScheme implements TypeScheme { private final InstantiationScheme instantiationScheme; private final InspectionScheme inspectionScheme; @@ -28,6 +31,16 @@ public ArtifactTransformParameterScheme(InstantiationScheme instantiationScheme, this.inspectionScheme = inspectionScheme; } + @Override + public TypeMetadataStore getMetadataStore() { + return inspectionScheme.getMetadataStore(); + } + + @Override + public boolean appliesTo(Class type) { + return type.isAnnotationPresent(AssociatedTransformAction.class); + } + public InstantiationScheme getInstantiationScheme() { return instantiationScheme; } diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/CacheableTransformTypeAnnotationHandler.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/CacheableTransformTypeAnnotationHandler.java index b4262ad09106f..09e5cf84c6729 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/CacheableTransformTypeAnnotationHandler.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/CacheableTransformTypeAnnotationHandler.java @@ -16,7 +16,7 @@ package org.gradle.api.internal.artifacts.transform; -import org.gradle.api.artifacts.transform.CacheableTransformAction; +import org.gradle.api.artifacts.transform.CacheableTransform; import org.gradle.api.artifacts.transform.TransformAction; import org.gradle.api.internal.tasks.properties.annotations.TypeAnnotationHandler; import org.gradle.internal.reflect.ParameterValidationContext; @@ -26,7 +26,7 @@ public class CacheableTransformTypeAnnotationHandler implements TypeAnnotationHandler { @Override public Class getAnnotationType() { - return CacheableTransformAction.class; + return CacheableTransform.class; } @Override diff --git a/subprojects/plugin-development/src/integTest/groovy/org/gradle/plugin/devel/tasks/ValidateTaskPropertiesIntegrationTest.groovy b/subprojects/plugin-development/src/integTest/groovy/org/gradle/plugin/devel/tasks/ValidateTaskPropertiesIntegrationTest.groovy index a445b08ad92f9..5fff0345f2948 100644 --- a/subprojects/plugin-development/src/integTest/groovy/org/gradle/plugin/devel/tasks/ValidateTaskPropertiesIntegrationTest.groovy +++ b/subprojects/plugin-development/src/integTest/groovy/org/gradle/plugin/devel/tasks/ValidateTaskPropertiesIntegrationTest.groovy @@ -237,14 +237,14 @@ class ValidateTaskPropertiesIntegrationTest extends AbstractIntegrationSpec { import org.gradle.api.tasks.*; import org.gradle.api.artifacts.transform.*; - @CacheableTransformAction + @CacheableTransform public class MyTask extends DefaultTask { @Nested Options getOptions() { return null; } - @CacheableTask @CacheableTransformAction + @CacheableTask @CacheableTransform public static class Options { @Input String getNestedThing() { @@ -259,13 +259,13 @@ class ValidateTaskPropertiesIntegrationTest extends AbstractIntegrationSpec { failure.assertHasDescription("Execution failed for task ':validateTaskProperties'.") failure.assertHasCause("Task property validation failed. See") failure.assertHasCause("Error: Cannot use @CacheableTask with type Options. This annotation cannot only be used with Task types.") - failure.assertHasCause("Error: Cannot use @CacheableTransformAction with type MyTask. This annotation cannot only be used with TransformAction types.") - failure.assertHasCause("Error: Cannot use @CacheableTransformAction with type Options. This annotation cannot only be used with TransformAction types.") + failure.assertHasCause("Error: Cannot use @CacheableTransform with type MyTask. This annotation cannot only be used with TransformAction types.") + failure.assertHasCause("Error: Cannot use @CacheableTransform with type Options. This annotation cannot only be used with TransformAction types.") file("build/reports/task-properties/report.txt").text == """ Error: Cannot use @CacheableTask with type Options. This annotation cannot only be used with Task types. - Error: Cannot use @CacheableTransformAction with type MyTask. This annotation cannot only be used with TransformAction types. - Error: Cannot use @CacheableTransformAction with type Options. This annotation cannot only be used with TransformAction types. + Error: Cannot use @CacheableTransform with type MyTask. This annotation cannot only be used with TransformAction types. + Error: Cannot use @CacheableTransform with type Options. This annotation cannot only be used with TransformAction types. """.stripIndent().trim() } @@ -637,6 +637,120 @@ class ValidateTaskPropertiesIntegrationTest extends AbstractIntegrationSpec { """.stripIndent().trim() } + def "can validate properties of an artifact transform action"() { + file("src/main/java/MyTransformAction.java") << """ + import org.gradle.api.*; + import org.gradle.api.tasks.*; + import org.gradle.api.artifacts.transform.*; + import java.io.*; + + public abstract class MyTransformAction implements TransformAction { + // Should be ignored because it's not a getter + public void getVoid() { + } + + // Should be ignored because it's not a getter + public int getWithParameter(int count) { + return count; + } + + // Ignored because static + public static int getStatic() { + return 0; + } + + // Ignored because injected + @javax.inject.Inject + public abstract org.gradle.api.internal.file.FileResolver getInjected(); + + // Valid because it is annotated + @InputArtifact + public abstract File getGoodInput(); + + // Invalid because it has no annotation + public long getBadTime() { + return System.currentTimeMillis(); + } + + // Invalid because it has some other annotation + @Deprecated + public String getOldThing() { + return null; + } + + // Unsupported annotation + @InputFile + public abstract File getInputFile(); + } + """ + + expect: + fails "validateTaskProperties" + failure.assertHasCause "Task property validation failed" + failure.assertHasCause "Error: Type 'MyTransformAction': property 'badTime' is not annotated with an input annotation." + failure.assertHasCause "Error: Type 'MyTransformAction': property 'inputFile' is annotated with unsupported annotation @InputFile." + failure.assertHasCause "Error: Type 'MyTransformAction': property 'oldThing' is not annotated with an input annotation." + + file("build/reports/task-properties/report.txt").text == """ + Error: Type 'MyTransformAction': property 'badTime' is not annotated with an input annotation. + Error: Type 'MyTransformAction': property 'inputFile' is annotated with unsupported annotation @InputFile. + Error: Type 'MyTransformAction': property 'oldThing' is not annotated with an input annotation. + """.stripIndent().trim() + } + + def "can validate properties of an artifact transform parameters object"() { + file("src/main/java/MyTransformParameters.java") << """ + import org.gradle.api.*; + import org.gradle.api.tasks.*; + import org.gradle.api.artifacts.transform.*; + import java.io.*; + + @AssociatedTransformAction(MyTransformParameters.Action.class) + public interface MyTransformParameters { + // Should be ignored because it's not a getter + void getVoid(); + + // Should be ignored because it's not a getter + int getWithParameter(int count); + + // Ignored because injected + @javax.inject.Inject + org.gradle.api.internal.file.FileResolver getInjected(); + + // Valid because it is annotated + @InputFile + File getGoodInput(); + + // Invalid because it has no annotation + long getBadTime(); + + // Invalid because it has some other annotation + @Deprecated + String getOldThing(); + + // Unsupported annotation + @InputArtifact + File getInputFile(); + + abstract class Action implements TransformAction { + } + } + """ + + expect: + fails "validateTaskProperties" + failure.assertHasCause "Task property validation failed" + failure.assertHasCause "Error: Type 'MyTransformParameters': property 'badTime' is not annotated with an input annotation." + failure.assertHasCause "Error: Type 'MyTransformParameters': property 'inputFile' is annotated with unsupported annotation @InputArtifact." + failure.assertHasCause "Error: Type 'MyTransformParameters': property 'oldThing' is not annotated with an input annotation." + + file("build/reports/task-properties/report.txt").text == """ + Error: Type 'MyTransformParameters': property 'badTime' is not annotated with an input annotation. + Error: Type 'MyTransformParameters': property 'inputFile' is annotated with unsupported annotation @InputArtifact. + Error: Type 'MyTransformParameters': property 'oldThing' is not annotated with an input annotation. + """.stripIndent().trim() + } + @Unroll def "reports deprecated #property setter"() { buildFile << """ diff --git a/subprojects/plugin-development/src/main/java/org/gradle/plugin/devel/tasks/ValidateTaskProperties.java b/subprojects/plugin-development/src/main/java/org/gradle/plugin/devel/tasks/ValidateTaskProperties.java index 40c61798c8268..76e9cf1c5a6c3 100644 --- a/subprojects/plugin-development/src/main/java/org/gradle/plugin/devel/tasks/ValidateTaskProperties.java +++ b/subprojects/plugin-development/src/main/java/org/gradle/plugin/devel/tasks/ValidateTaskProperties.java @@ -27,7 +27,6 @@ import org.gradle.api.GradleException; import org.gradle.api.Incubating; import org.gradle.api.InvalidUserDataException; -import org.gradle.api.Task; import org.gradle.api.UncheckedIOException; import org.gradle.api.file.ConfigurableFileCollection; import org.gradle.api.file.EmptyFileVisitor; @@ -49,7 +48,6 @@ import org.gradle.api.tasks.TaskAction; import org.gradle.api.tasks.TaskValidationException; import org.gradle.api.tasks.VerificationTask; -import org.gradle.internal.Cast; import org.gradle.internal.classanalysis.AsmConstants; import org.gradle.internal.classloader.ClassLoaderFactory; import org.gradle.internal.classloader.ClassLoaderUtils; @@ -65,7 +63,6 @@ import java.io.IOException; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; -import java.lang.reflect.Modifier; import java.util.Collection; import java.util.List; import java.util.Map; @@ -142,12 +139,10 @@ public void validateTaskClasses() throws IOException { private void validateTaskClasses(final ClassLoader classLoader) throws IOException { final Map taskValidationProblems = Maps.newTreeMap(); - final Class taskInterface; final Method validatorMethod; try { - taskInterface = classLoader.loadClass(Task.class.getName()); Class validatorClass = classLoader.loadClass("org.gradle.api.internal.tasks.properties.PropertyValidationAccess"); - validatorMethod = validatorClass.getMethod("collectTaskValidationProblems", Class.class, Map.class, Boolean.TYPE); + validatorMethod = validatorClass.getMethod("collectValidationProblems", Class.class, Map.class, Boolean.TYPE); } catch (ClassNotFoundException | NoSuchMethodException e) { throw new RuntimeException(e); } @@ -177,18 +172,8 @@ public void visitFile(FileVisitDetails fileDetails) { } catch (NoClassDefFoundError e) { throw new GradleException("Could not load class: " + className, e); } - if (!Modifier.isPublic(clazz.getModifiers())) { - continue; - } - if (Modifier.isAbstract(clazz.getModifiers())) { - continue; - } - if (!taskInterface.isAssignableFrom(clazz)) { - continue; - } - Class taskClass = Cast.uncheckedCast(clazz); try { - validatorMethod.invoke(null, taskClass, taskValidationProblems, enableStricterValidation); + validatorMethod.invoke(null, clazz, taskValidationProblems, enableStricterValidation); } catch (IllegalAccessException e) { throw new RuntimeException(e); } catch (InvocationTargetException e) { From afa22a128a24d2169019cec123208c238a395183 Mon Sep 17 00:00:00 2001 From: Adam Murdoch Date: Wed, 27 Feb 2019 15:32:41 +1100 Subject: [PATCH 217/853] Test fixes for changes to artifact transform APIs. --- ...sformValuesInjectionIntegrationTest.groovy | 45 +++++++------------ .../ArtifactTransformParameterScheme.java | 4 +- ...lidateTaskPropertiesIntegrationTest.groovy | 6 +-- 3 files changed, 18 insertions(+), 37 deletions(-) diff --git a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformValuesInjectionIntegrationTest.groovy b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformValuesInjectionIntegrationTest.groovy index aac8b91583fa7..d556dcef16efe 100644 --- a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformValuesInjectionIntegrationTest.groovy +++ b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformValuesInjectionIntegrationTest.groovy @@ -255,17 +255,13 @@ class ArtifactTransformValuesInjectionIntegrationTest extends AbstractDependency } } - @AssociatedTransformAction(MakeGreenAction) - @CacheableTask @CacheableTransform - interface MakeGreen { - @Input - String getExtension() - void setExtension(String value) - } - - abstract class MakeGreenAction implements TransformAction { - @TransformParameters - abstract MakeGreen getParameters() + abstract class MakeGreen implements TransformAction { + @CacheableTask @CacheableTransform + interface Parameters extends TransformParameters { + @Input + String getExtension() + void setExtension(String value) + } void transform(TransformOutputs outputs) { throw new RuntimeException() @@ -277,10 +273,10 @@ class ArtifactTransformValuesInjectionIntegrationTest extends AbstractDependency fails(":a:resolve") then: - failure.assertThatDescription(matchesRegexp('Cannot isolate parameters MakeGreen\\$Inject@.* of artifact transform MakeGreenAction')) - failure.assertHasCause('Some problems were found with the configuration of the artifact transform parameter MakeGreen.') - failure.assertHasCause("Cannot use @CacheableTask with type MakeGreen\$Inject. This annotation cannot only be used with Task types.") - failure.assertHasCause("Cannot use @CacheableTransform with type MakeGreen\$Inject. This annotation cannot only be used with TransformAction types.") + failure.assertThatDescription(matchesRegexp('Cannot isolate parameters MakeGreen\\$Parameters\\$Inject@.* of artifact transform MakeGreen')) + failure.assertHasCause('Some problems were found with the configuration of the artifact transform parameter MakeGreen.Parameters.') + failure.assertHasCause("Cannot use @CacheableTask with type MakeGreen\$Parameters\$Inject. This annotation cannot only be used with Task types.") + failure.assertHasCause("Cannot use @CacheableTransform with type MakeGreen\$Parameters\$Inject. This annotation cannot only be used with TransformAction types.") } @Unroll @@ -440,11 +436,7 @@ class ArtifactTransformValuesInjectionIntegrationTest extends AbstractDependency settingsFile << """ include 'a', 'b', 'c' """ - setupBuildWithColorTransform { - params(""" - extension = 'green' - """) - } + setupBuildWithColorTransform() buildFile << """ project(':a') { dependencies { @@ -453,15 +445,8 @@ class ArtifactTransformValuesInjectionIntegrationTest extends AbstractDependency } } - @AssociatedTransformAction(MakeGreenAction) - interface MakeGreen { - @Input - String getExtension() - void setExtension(String value) - } - @CacheableTask - abstract class MakeGreenAction implements TransformAction { + abstract class MakeGreen implements TransformAction { void transform(TransformOutputs outputs) { throw new RuntimeException() } @@ -473,8 +458,8 @@ class ArtifactTransformValuesInjectionIntegrationTest extends AbstractDependency then: failure.assertHasDescription('A problem occurred evaluating root project') - failure.assertHasCause('A problem was found with the configuration of MakeGreenAction.') - failure.assertHasCause("Cannot use @CacheableTask with type MakeGreenAction. This annotation cannot only be used with Task types.") + failure.assertHasCause('A problem was found with the configuration of MakeGreen.') + failure.assertHasCause("Cannot use @CacheableTask with type MakeGreen. This annotation cannot only be used with Task types.") } @Unroll diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/ArtifactTransformParameterScheme.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/ArtifactTransformParameterScheme.java index 8923eca6db193..4498dca717160 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/ArtifactTransformParameterScheme.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/ArtifactTransformParameterScheme.java @@ -16,7 +16,7 @@ package org.gradle.api.internal.artifacts.transform; -import org.gradle.api.artifacts.transform.AssociatedTransformAction; +import org.gradle.api.artifacts.transform.TransformParameters; import org.gradle.api.internal.tasks.properties.InspectionScheme; import org.gradle.api.internal.tasks.properties.TypeMetadataStore; import org.gradle.api.internal.tasks.properties.TypeScheme; @@ -38,7 +38,7 @@ public TypeMetadataStore getMetadataStore() { @Override public boolean appliesTo(Class type) { - return type.isAnnotationPresent(AssociatedTransformAction.class); + return TransformParameters.class.isAssignableFrom(type); } public InstantiationScheme getInstantiationScheme() { diff --git a/subprojects/plugin-development/src/integTest/groovy/org/gradle/plugin/devel/tasks/ValidateTaskPropertiesIntegrationTest.groovy b/subprojects/plugin-development/src/integTest/groovy/org/gradle/plugin/devel/tasks/ValidateTaskPropertiesIntegrationTest.groovy index 5fff0345f2948..b4682876123b6 100644 --- a/subprojects/plugin-development/src/integTest/groovy/org/gradle/plugin/devel/tasks/ValidateTaskPropertiesIntegrationTest.groovy +++ b/subprojects/plugin-development/src/integTest/groovy/org/gradle/plugin/devel/tasks/ValidateTaskPropertiesIntegrationTest.groovy @@ -705,8 +705,7 @@ class ValidateTaskPropertiesIntegrationTest extends AbstractIntegrationSpec { import org.gradle.api.artifacts.transform.*; import java.io.*; - @AssociatedTransformAction(MyTransformParameters.Action.class) - public interface MyTransformParameters { + public interface MyTransformParameters extends TransformParameters { // Should be ignored because it's not a getter void getVoid(); @@ -731,9 +730,6 @@ class ValidateTaskPropertiesIntegrationTest extends AbstractIntegrationSpec { // Unsupported annotation @InputArtifact File getInputFile(); - - abstract class Action implements TransformAction { - } } """ From d015fde1742ec6b1992628bdd75e4995eeddc745 Mon Sep 17 00:00:00 2001 From: "Rodrigo B. de Oliveira" Date: Wed, 27 Feb 2019 19:25:59 -0300 Subject: [PATCH 218/853] Assert generated accessors are internal Work-in-progress. --- .../dsl/plugins/precompiled/KotlinParser.kt | 79 +++++++++++++++++++ .../PrecompiledScriptPluginAccessorsTest.kt | 61 +++++++++++++- 2 files changed, 138 insertions(+), 2 deletions(-) create mode 100644 subprojects/kotlin-dsl-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/KotlinParser.kt diff --git a/subprojects/kotlin-dsl-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/KotlinParser.kt b/subprojects/kotlin-dsl-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/KotlinParser.kt new file mode 100644 index 0000000000000..8bf7df0422290 --- /dev/null +++ b/subprojects/kotlin-dsl-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/KotlinParser.kt @@ -0,0 +1,79 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.kotlin.dsl.plugins.precompiled + +import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys +import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation +import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity +import org.jetbrains.kotlin.cli.common.messages.MessageCollector + +import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles +import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment + +import org.jetbrains.kotlin.com.intellij.openapi.project.Project +import org.jetbrains.kotlin.com.intellij.openapi.util.Disposer +import org.jetbrains.kotlin.com.intellij.psi.PsiManager +import org.jetbrains.kotlin.com.intellij.testFramework.LightVirtualFile + +import org.jetbrains.kotlin.config.CompilerConfiguration + +import org.jetbrains.kotlin.idea.KotlinFileType + +import org.jetbrains.kotlin.psi.KtFile + + +object KotlinParser { + + fun map(code: String, f: KtFile.() -> T): T = + withProject { f(parse("code.kt", code)) } + + fun Project.parse(name: String, code: String): KtFile = + psiManager.findFile(virtualFile(name, code)) as KtFile + + fun virtualFile(name: String, code: String) = + LightVirtualFile(name, KotlinFileType.INSTANCE, code) + + val Project.psiManager + get() = PsiManager.getInstance(this) + + fun withProject(f: Project.() -> T): T { + val parentDisposable = Disposer.newDisposable() + try { + val project = + KotlinCoreEnvironment.createForProduction( + parentDisposable, + CompilerConfiguration().apply { + put(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY, TestMessageCollector) + }, + EnvironmentConfigFiles.JVM_CONFIG_FILES + ).project + + return f(project) + } finally { + parentDisposable.dispose() + } + } + + private + object TestMessageCollector : MessageCollector { + override fun clear() = Unit + override fun hasErrors(): Boolean = false + override fun report(severity: CompilerMessageSeverity, message: String, location: CompilerMessageLocation?) { + println("$severity: $message") + } + } +} diff --git a/subprojects/kotlin-dsl-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPluginAccessorsTest.kt b/subprojects/kotlin-dsl-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPluginAccessorsTest.kt index 2479b0e331396..16707de3ffdb4 100644 --- a/subprojects/kotlin-dsl-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPluginAccessorsTest.kt +++ b/subprojects/kotlin-dsl-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPluginAccessorsTest.kt @@ -38,10 +38,18 @@ import org.gradle.kotlin.dsl.support.zipTo import org.gradle.test.fixtures.file.LeaksFileHandles -import org.hamcrest.CoreMatchers.allOf -import org.hamcrest.CoreMatchers.containsString import org.hamcrest.MatcherAssert.assertThat +import org.hamcrest.Matchers.allOf +import org.hamcrest.Matchers.containsString +import org.hamcrest.Matchers.empty +import org.hamcrest.Matchers.not +import org.jetbrains.kotlin.descriptors.Visibilities +import org.jetbrains.kotlin.descriptors.Visibility +import org.jetbrains.kotlin.psi.psiUtil.toVisibility +import org.jetbrains.kotlin.psi.psiUtil.visibilityModifierType + +import org.junit.Ignore import org.junit.Test import java.io.File @@ -125,6 +133,55 @@ class PrecompiledScriptPluginAccessorsTest : AbstractPrecompiledScriptPluginTest ) } + @Ignore("wip") + @Test + fun `generated type-safe accessors are internal`() { + + givenPrecompiledKotlinScript("java-project.gradle.kts", """ + plugins { java } + """) + + val generatedSourceFiles = + existing("build/generated-sources") + .walkTopDown() + .filter { it.isFile } + .toList() + + assertThat( + generatedSourceFiles, + not(empty()) + ) + + data class Declaration( + val packageName: String, + val name: String, + val visibility: Visibility? + ) + + val generatedAccessors = + KotlinParser.run { + withProject { + generatedSourceFiles.flatMap { file -> + parse(file.name, file.readText()).run { + val packageName = packageFqName.asString() + declarations.map { declaration -> + Declaration( + packageName, + declaration.name!!, + declaration.visibilityModifierType()?.toVisibility() + ) + } + } + } + } + } + + assertThat( + generatedAccessors.filterNot { it.visibility == Visibilities.INTERNAL }, + empty() + ) + } + @Test fun `can use core plugin spec builders`() { From 4e6276a7581fadf7eeda520d36862d5bebf68cb3 Mon Sep 17 00:00:00 2001 From: Eric Wendelin Date: Wed, 27 Feb 2019 12:57:26 -0700 Subject: [PATCH 219/853] Draft release notes preamble for Gradle 5.3 --- subprojects/docs/src/docs/release/notes.md | 10 ++++++---- subprojects/docs/src/docs/release/release-features.txt | 3 +++ 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/subprojects/docs/src/docs/release/notes.md b/subprojects/docs/src/docs/release/notes.md index ab022f7b274ef..37a43b52ce7e7 100644 --- a/subprojects/docs/src/docs/release/notes.md +++ b/subprojects/docs/src/docs/release/notes.md @@ -1,6 +1,8 @@ The Gradle team is excited to announce Gradle 5.3. -This release features [1](), [2](), ... [n](), and more. +This release features incubating support for publishing and consuming Gradle Module Metadata, +[feature variants AKA "optional dependencies"](#feature-variants-aka-optional-dependencies), +type-safe accessors in Kotlin pre-compiled script plugins, and more. We would like to thank the following community contributors to this release of Gradle: @@ -18,11 +20,11 @@ and [Josh Soref](https://github.com/jsoref). ## Upgrade Instructions -Switch your build to use Gradle 5.3 by updating your wrapper properties: +Switch your build to use Gradle 5.3 RC1 by updating your wrapper properties: -`./gradlew wrapper --gradle-version=5.3` +`./gradlew wrapper --gradle-version=5.3-rc-1` -Standalone downloads are available at [gradle.org/releases](https://gradle.org/releases). +Standalone downloads are available at [gradle.org/release-candidate](https://gradle.org/release-candidate). ## Feature variants, aka optional dependencies diff --git a/subprojects/docs/src/docs/release/release-features.txt b/subprojects/docs/src/docs/release/release-features.txt index e69de29bb2d1d..8a0bf424f9431 100644 --- a/subprojects/docs/src/docs/release/release-features.txt +++ b/subprojects/docs/src/docs/release/release-features.txt @@ -0,0 +1,3 @@ + - Incubating support for Gradle Module Metadata + - Feature variants AKA "optional dependencies" + - Type-safe accessors in Kotlin pre-compiled script plugins From a13dbda6002366a7e2fe30a7a1e4417eb2877c00 Mon Sep 17 00:00:00 2001 From: "Rodrigo B. de Oliveira" Date: Wed, 27 Feb 2019 22:03:09 -0300 Subject: [PATCH 220/853] Mark offending tests with `@LeaksFileHandles` --- .../PrecompiledScriptPluginModelIntegrationTest.kt | 3 +++ .../dsl/integration/KotlinBuildScriptModelIntegrationTest.kt | 3 +++ .../integration/KotlinSettingsScriptModelIntegrationTest.kt | 4 +++- 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/subprojects/kotlin-dsl-integ-tests/src/integTest/kotlin/org/gradle/kotlin/dsl/integration/PrecompiledScriptPluginModelIntegrationTest.kt b/subprojects/kotlin-dsl-integ-tests/src/integTest/kotlin/org/gradle/kotlin/dsl/integration/PrecompiledScriptPluginModelIntegrationTest.kt index a763ebebe1ea3..eec6f6b785da6 100644 --- a/subprojects/kotlin-dsl-integ-tests/src/integTest/kotlin/org/gradle/kotlin/dsl/integration/PrecompiledScriptPluginModelIntegrationTest.kt +++ b/subprojects/kotlin-dsl-integ-tests/src/integTest/kotlin/org/gradle/kotlin/dsl/integration/PrecompiledScriptPluginModelIntegrationTest.kt @@ -18,6 +18,8 @@ package org.gradle.kotlin.dsl.integration import org.gradle.kotlin.dsl.fixtures.FoldersDsl +import org.gradle.test.fixtures.file.LeaksFileHandles + import org.hamcrest.MatcherAssert.assertThat import org.hamcrest.Matchers.hasItem import org.hamcrest.Matchers.startsWith @@ -29,6 +31,7 @@ import java.io.File class PrecompiledScriptPluginModelIntegrationTest : AbstractPluginIntegrationTest() { + @LeaksFileHandles("Kotlin Compiler Daemon working directory") @Test fun `given a single project build, the classpath of a precompiled script plugin is the compile classpath of its enclosing source-set`() { diff --git a/subprojects/kotlin-dsl/src/integTest/kotlin/org/gradle/kotlin/dsl/integration/KotlinBuildScriptModelIntegrationTest.kt b/subprojects/kotlin-dsl/src/integTest/kotlin/org/gradle/kotlin/dsl/integration/KotlinBuildScriptModelIntegrationTest.kt index 8e995cf4c2e91..e1e8bc41c5ae0 100644 --- a/subprojects/kotlin-dsl/src/integTest/kotlin/org/gradle/kotlin/dsl/integration/KotlinBuildScriptModelIntegrationTest.kt +++ b/subprojects/kotlin-dsl/src/integTest/kotlin/org/gradle/kotlin/dsl/integration/KotlinBuildScriptModelIntegrationTest.kt @@ -5,6 +5,8 @@ import org.gradle.kotlin.dsl.fixtures.DeepThought import org.gradle.kotlin.dsl.fixtures.matching import org.gradle.kotlin.dsl.fixtures.normalisedPath +import org.gradle.test.fixtures.file.LeaksFileHandles + import org.hamcrest.CoreMatchers.allOf import org.hamcrest.CoreMatchers.equalTo import org.hamcrest.CoreMatchers.hasItem @@ -465,6 +467,7 @@ class KotlinBuildScriptModelIntegrationTest : ScriptModelIntegrationTest() { matchesProjectsSourceRoots(withMainSourceSetJavaKotlinIn("buildSrc"))) } + @LeaksFileHandles("Kotlin Compiler Daemon working directory") @Test fun `sourcePath includes buildSrc project dependencies source roots`() { diff --git a/subprojects/kotlin-dsl/src/integTest/kotlin/org/gradle/kotlin/dsl/integration/KotlinSettingsScriptModelIntegrationTest.kt b/subprojects/kotlin-dsl/src/integTest/kotlin/org/gradle/kotlin/dsl/integration/KotlinSettingsScriptModelIntegrationTest.kt index 184e9043bcdb2..a7d23777366a9 100644 --- a/subprojects/kotlin-dsl/src/integTest/kotlin/org/gradle/kotlin/dsl/integration/KotlinSettingsScriptModelIntegrationTest.kt +++ b/subprojects/kotlin-dsl/src/integTest/kotlin/org/gradle/kotlin/dsl/integration/KotlinSettingsScriptModelIntegrationTest.kt @@ -2,8 +2,9 @@ package org.gradle.kotlin.dsl.integration import org.gradle.kotlin.dsl.fixtures.normalisedPath -import org.junit.Assert.assertThat +import org.gradle.test.fixtures.file.LeaksFileHandles +import org.junit.Assert.assertThat import org.junit.Test @@ -83,6 +84,7 @@ class KotlinSettingsScriptModelIntegrationTest : ScriptModelIntegrationTest() { matchesProjectsSourceRoots(withMainSourceSetJavaKotlinIn("buildSrc"))) } + @LeaksFileHandles("Kotlin Compiler Daemon working directory") @Test fun `sourcePath includes buildSrc project dependencies source roots`() { From 67c3ae8f305dc24befc12b26c837b70b1ea1f12c Mon Sep 17 00:00:00 2001 From: "Rodrigo B. de Oliveira" Date: Wed, 27 Feb 2019 22:37:43 -0300 Subject: [PATCH 221/853] Make generated type-safe accessors `internal` --- .../PrecompiledScriptPluginAccessorsTest.kt | 14 ++++++++--- ...eneratePrecompiledScriptPluginAccessors.kt | 15 +++++++++++- .../dsl/accessors/AccessorsClassPath.kt | 10 ++++---- .../gradle/kotlin/dsl/accessors/Emitter.kt | 23 +++++++++++++++---- 4 files changed, 49 insertions(+), 13 deletions(-) diff --git a/subprojects/kotlin-dsl-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPluginAccessorsTest.kt b/subprojects/kotlin-dsl-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPluginAccessorsTest.kt index 16707de3ffdb4..d54f06491d490 100644 --- a/subprojects/kotlin-dsl-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPluginAccessorsTest.kt +++ b/subprojects/kotlin-dsl-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPluginAccessorsTest.kt @@ -42,6 +42,7 @@ import org.hamcrest.MatcherAssert.assertThat import org.hamcrest.Matchers.allOf import org.hamcrest.Matchers.containsString import org.hamcrest.Matchers.empty +import org.hamcrest.Matchers.equalTo import org.hamcrest.Matchers.not import org.jetbrains.kotlin.descriptors.Visibilities @@ -49,7 +50,6 @@ import org.jetbrains.kotlin.descriptors.Visibility import org.jetbrains.kotlin.psi.psiUtil.toVisibility import org.jetbrains.kotlin.psi.psiUtil.visibilityModifierType -import org.junit.Ignore import org.junit.Test import java.io.File @@ -133,7 +133,6 @@ class PrecompiledScriptPluginAccessorsTest : AbstractPrecompiledScriptPluginTest ) } - @Ignore("wip") @Test fun `generated type-safe accessors are internal`() { @@ -177,8 +176,17 @@ class PrecompiledScriptPluginAccessorsTest : AbstractPrecompiledScriptPluginTest } assertThat( + "Only the generated Gradle Plugin wrapper is not internal", generatedAccessors.filterNot { it.visibility == Visibilities.INTERNAL }, - empty() + equalTo( + listOf( + Declaration( + "", + "JavaProjectPlugin", + null + ) + ) + ) ) } diff --git a/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/GeneratePrecompiledScriptPluginAccessors.kt b/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/GeneratePrecompiledScriptPluginAccessors.kt index dae21c334df92..76ffdb8963e5a 100644 --- a/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/GeneratePrecompiledScriptPluginAccessors.kt +++ b/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/GeneratePrecompiledScriptPluginAccessors.kt @@ -228,10 +228,23 @@ open class GeneratePrecompiledScriptPluginAccessors : ClassPathSensitiveCodeGene classPath, sourceCodeOutputDir.get().asFile, temporaryDir.resolve("accessors"), - hashedSchema.packageName + hashedSchema.packageName, + ::makeInternal ) } + private + fun makeInternal(accessor: String): String = + accessor + .replaceIndent() + .let { valOrFun.matcher(it) } + .replaceAll("internal\n$1 ") + + private + val valOrFun by lazy { + "^(val|fun) ".toRegex(RegexOption.MULTILINE).toPattern() + } + private fun IO.writeContentAddressableImplicitImportFor(scriptPlugin: ScriptPluginPlugins, packageName: String) { io { writeFile(implicitImportFileFor(scriptPlugin), "$packageName.*".toByteArray()) } diff --git a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/accessors/AccessorsClassPath.kt b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/accessors/AccessorsClassPath.kt index 69235ebd58265..c4a2c8fd7b7dc 100644 --- a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/accessors/AccessorsClassPath.kt +++ b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/accessors/AccessorsClassPath.kt @@ -153,14 +153,16 @@ fun IO.buildAccessorsFor( classPath: ClassPath, srcDir: File, binDir: File, - packageName: String = kotlinDslPackageName + packageName: String = kotlinDslPackageName, + accessorFormat: (String) -> String = { it.replaceIndent() } ) { val availableSchema = availableProjectSchemaFor(projectSchema, classPath) emitAccessorsFor( availableSchema, srcDir, binDir, - OutputPackage(packageName) + OutputPackage(packageName), + accessorFormat ) } @@ -518,7 +520,7 @@ fun enabledJitAccessors(project: Project) = internal fun IO.writeAccessorsTo( outputFile: File, - accessors: List, + accessors: Iterable, imports: List = emptyList(), packageName: String = kotlinDslPackageName ) = io { @@ -531,7 +533,7 @@ fun IO.writeAccessorsTo( appendReproducibleNewLine() } accessors.forEach { - appendReproducibleNewLine(it.replaceIndent()) + appendReproducibleNewLine(it) appendReproducibleNewLine() } } diff --git a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/accessors/Emitter.kt b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/accessors/Emitter.kt index dc51c088eed34..da9c8a7fa79b5 100644 --- a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/accessors/Emitter.kt +++ b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/accessors/Emitter.kt @@ -38,14 +38,21 @@ fun IO.emitAccessorsFor( projectSchema: ProjectSchema, srcDir: File, binDir: File, - outputPackage: OutputPackage + outputPackage: OutputPackage, + accessorFormat: (String) -> String ): List { makeAccessorOutputDirs(srcDir, binDir, outputPackage.path) val emittedClassNames = accessorsFor(projectSchema).map { accessor -> - emitClassFor(accessor, srcDir, binDir, outputPackage) + emitClassFor( + accessor, + srcDir, + binDir, + outputPackage, + accessorFormat + ) }.toList() writeFile( @@ -79,7 +86,8 @@ fun IO.emitClassFor( accessor: Accessor, srcDir: File, binDir: File, - outputPackage: OutputPackage + outputPackage: OutputPackage, + accessorFormat: (String) -> String ): InternalName { val (simpleClassName, fragments) = fragmentsFor(accessor) @@ -89,13 +97,18 @@ fun IO.emitClassFor( val classWriter = beginPublicClass(className) for ((source, bytecode, metadata, signature) in fragments) { - sourceCode.add(source) + sourceCode.add(accessorFormat(source)) MetadataFragmentScope(signature, metadataWriter).run(metadata) BytecodeFragmentScope(signature, classWriter).run(bytecode) } val sourceFile = srcDir.resolve("${className.value.removeSuffix("Kt")}.kt") - writeAccessorsTo(sourceFile, sourceCode, importsRequiredBy(accessor), outputPackage.name) + writeAccessorsTo( + sourceFile, + sourceCode, + importsRequiredBy(accessor), + outputPackage.name + ) val classHeader = metadataWriter.closeHeader() val classBytes = classWriter.endKotlinClass(classHeader) From cffbd983d0d5a7af7c62086f696b90e7f29f4ada Mon Sep 17 00:00:00 2001 From: Gradleware Git Bot Date: Thu, 28 Feb 2019 02:43:59 +0100 Subject: [PATCH 222/853] Publish 5.3-20190228012955+0000 --- released-versions.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/released-versions.json b/released-versions.json index a77591a307acd..4a8b235cfbade 100644 --- a/released-versions.json +++ b/released-versions.json @@ -1,7 +1,7 @@ { "latestReleaseSnapshot": { - "version": "5.3-20190227191816+0000", - "buildTime": "20190227191816+0000" + "version": "5.3-20190228012955+0000", + "buildTime": "20190228012955+0000" }, "latestRc": { "version": "5.2-rc-1", From 192a84fda609cd5fb6c6836bb3b58740474ff0ea Mon Sep 17 00:00:00 2001 From: "Rodrigo B. de Oliveira" Date: Thu, 28 Feb 2019 00:12:26 -0300 Subject: [PATCH 223/853] Don't fail the build because type-safe accessors cannot be generated --- .../PrecompiledScriptPluginAccessorsTest.kt | 11 ++++---- ...eneratePrecompiledScriptPluginAccessors.kt | 27 ++++++++++++++++--- 2 files changed, 29 insertions(+), 9 deletions(-) diff --git a/subprojects/kotlin-dsl-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPluginAccessorsTest.kt b/subprojects/kotlin-dsl-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPluginAccessorsTest.kt index d54f06491d490..2280a72fe67e7 100644 --- a/subprojects/kotlin-dsl-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPluginAccessorsTest.kt +++ b/subprojects/kotlin-dsl-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPluginAccessorsTest.kt @@ -238,7 +238,7 @@ class PrecompiledScriptPluginAccessorsTest : AbstractPrecompiledScriptPluginTest } @Test - fun `plugin application errors are propagated`() { + fun `plugin application errors are reported but don't cause the build to fail`() { // given: val pluginId = "invalid.plugin" @@ -246,11 +246,10 @@ class PrecompiledScriptPluginAccessorsTest : AbstractPrecompiledScriptPluginTest withPrecompiledScriptApplying(pluginId, pluginJar) - buildAndFail("classes").assertHasDescription( - "An exception occurred applying plugin request [id: '$pluginId']" - ).assertHasCause( - "'InvalidPlugin' is neither a plugin or a rule source and cannot be applied." - ) + gradleExecuterFor(arrayOf("classes")).withStackTraceChecksDisabled().run().apply { + assertRawOutputContains("An exception occurred applying plugin request [id: '$pluginId']") + assertRawOutputContains("'InvalidPlugin' is neither a plugin or a rule source and cannot be applied.") + } } private diff --git a/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/GeneratePrecompiledScriptPluginAccessors.kt b/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/GeneratePrecompiledScriptPluginAccessors.kt index 76ffdb8963e5a..00badf46a4900 100644 --- a/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/GeneratePrecompiledScriptPluginAccessors.kt +++ b/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/GeneratePrecompiledScriptPluginAccessors.kt @@ -212,15 +212,36 @@ open class GeneratePrecompiledScriptPluginAccessors : ClassPathSensitiveCodeGene val schemaBuilder = SyntheticProjectSchemaBuilder(temporaryDir, classPathFiles.files) return pluginGroupsPerRequests.flatMap { (uniquePluginRequests, scriptPlugins) -> - val schema = schemaBuilder.schemaFor(uniquePluginRequests.plugins) - val hashedSchema = HashedProjectSchema(schema) - scriptPlugins.map { hashedSchema to it } + try { + val schema = schemaBuilder.schemaFor(uniquePluginRequests.plugins) + val hashedSchema = HashedProjectSchema(schema) + scriptPlugins.map { hashedSchema to it } + } catch (error: Throwable) { + reportProjectSchemaError(scriptPlugins, error) + emptyList>() + } }.groupBy( { (schema, _) -> schema }, { (_, plugin) -> plugin } ) } + private + fun reportProjectSchemaError(plugins: List, error: Throwable) { + logger.warn( + plugins.joinToString( + prefix = "Failed to generate type-safe Gradle model accessors for the following precompiled script plugins:\n", + separator = "\n", + postfix = "\n" + ) { " - " + projectRelativePathOf(it.scriptPlugin) } + , error + ) + } + + private + fun projectRelativePathOf(scriptPlugin: PrecompiledScriptPlugin) = + project.relativePath(scriptPlugin.scriptFile) + private fun IO.writeTypeSafeAccessorsFor(hashedSchema: HashedProjectSchema) { buildAccessorsFor( From 8eeb75788e82d393cc01fd2f6b76b94388e18ef8 Mon Sep 17 00:00:00 2001 From: "Rodrigo B. de Oliveira" Date: Thu, 28 Feb 2019 00:13:25 -0300 Subject: [PATCH 224/853] Move generated plugin spec builders to different package In order to avoid conflicts with the ones generated for build scripts. --- .../tasks/CompilePrecompiledScriptPluginPlugins.kt | 11 ++++++++++- .../ConfigurePrecompiledScriptDependenciesResolver.kt | 2 +- .../tasks/GenerateExternalPluginSpecBuilders.kt | 6 +++--- 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/CompilePrecompiledScriptPluginPlugins.kt b/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/CompilePrecompiledScriptPluginPlugins.kt index ac70478369f70..906fdb5257cf6 100644 --- a/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/CompilePrecompiledScriptPluginPlugins.kt +++ b/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/CompilePrecompiledScriptPluginPlugins.kt @@ -17,6 +17,7 @@ package org.gradle.kotlin.dsl.plugins.precompiled.tasks import org.gradle.api.file.Directory +import org.gradle.api.internal.AbstractTask import org.gradle.api.provider.Provider import org.gradle.api.tasks.CacheableTask import org.gradle.api.tasks.InputFiles @@ -53,7 +54,10 @@ open class CompilePrecompiledScriptPluginPlugins : ClassPathSensitiveTask() { outputDir, sourceFiles.name, sourceFiles.map { it.path }, - scriptDefinitionFromTemplate(KotlinPluginsBlock::class, project.implicitImports()), + scriptDefinitionFromTemplate( + KotlinPluginsBlock::class, + implicitImportsForPrecompiledScriptPlugins() + ), classPathFiles, logger, { it } // TODO: translate paths @@ -61,3 +65,8 @@ open class CompilePrecompiledScriptPluginPlugins : ClassPathSensitiveTask() { } } } + + +internal +fun AbstractTask.implicitImportsForPrecompiledScriptPlugins() = + project.implicitImports() + "gradle.kotlin.dsl.plugins.*" // TODO:kotlin-dsl read this value from GenerateExternalPluginSpecBuilder diff --git a/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/ConfigurePrecompiledScriptDependenciesResolver.kt b/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/ConfigurePrecompiledScriptDependenciesResolver.kt index 73e0f12f694ad..a8a04cada4ff8 100644 --- a/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/ConfigurePrecompiledScriptDependenciesResolver.kt +++ b/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/ConfigurePrecompiledScriptDependenciesResolver.kt @@ -46,7 +46,7 @@ open class ConfigurePrecompiledScriptDependenciesResolver : DefaultTask() { val resolverEnvironment = resolverEnvironmentStringFor( listOf( - kotlinDslImplicitImports to project.implicitImports() + kotlinDslImplicitImports to implicitImportsForPrecompiledScriptPlugins() ) + precompiledScriptPluginImports ) diff --git a/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/GenerateExternalPluginSpecBuilders.kt b/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/GenerateExternalPluginSpecBuilders.kt index d0bc1ced40871..e41321c0176bc 100644 --- a/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/GenerateExternalPluginSpecBuilders.kt +++ b/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/GenerateExternalPluginSpecBuilders.kt @@ -54,11 +54,11 @@ open class GenerateExternalPluginSpecBuilders : ClassPathSensitiveCodeGeneration kotlinPackageNameFor(packageName) } - // TODO: move to a package name derived from the classpath hash - // "gradle-kotlin-dsl.plugin-spec-builders.$$classPathHash" + // TODO:kotlin-dsl move to a package name derived from the classpath hash + // "gradle.kotlin.dsl.plugins._$classPathHash" private val packageName - get() = "org.gradle.kotlin.dsl" + get() = "gradle.kotlin.dsl.plugins" } From b1b2855b3e55c1c513ee7f80b8c8d5d0890cfe67 Mon Sep 17 00:00:00 2001 From: Bo Zhang Date: Thu, 28 Feb 2019 14:43:58 +0800 Subject: [PATCH 225/853] Update tagging plugin to 0.53 --- build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle.kts b/build.gradle.kts index 496d5413ab28b..658a64f2412ac 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -32,7 +32,7 @@ plugins { // We have to apply it here at the moment, so that when the build scan plugin is auto-applied via --scan can detect that // the plugin has been already applied. For that the plugin has to be applied with the new plugin DSL syntax. com.gradle.`build-scan` - id("org.gradle.ci.tag-single-build") version("0.52") + id("org.gradle.ci.tag-single-build") version("0.53") } defaultTasks("assemble") From 9a896ca95ef0b813710e527521bfe1c14768ee4b Mon Sep 17 00:00:00 2001 From: Bo Zhang Date: Thu, 28 Feb 2019 14:43:58 +0800 Subject: [PATCH 226/853] Update tagging plugin to 0.53 --- build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle.kts b/build.gradle.kts index fd25210f41830..529b570608922 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -32,7 +32,7 @@ plugins { // We have to apply it here at the moment, so that when the build scan plugin is auto-applied via --scan can detect that // the plugin has been already applied. For that the plugin has to be applied with the new plugin DSL syntax. com.gradle.`build-scan` - id("org.gradle.ci.tag-single-build") version("0.52") + id("org.gradle.ci.tag-single-build") version("0.53") } defaultTasks("assemble") From c8cf35badac33278dec04d8f2952c2a288238ecb Mon Sep 17 00:00:00 2001 From: Cedric Champeau Date: Thu, 28 Feb 2019 08:43:39 +0100 Subject: [PATCH 227/853] Tweak release notes - add mention to Gradle Module Metadata 1.0 - add mention to public API for custom components --- subprojects/docs/src/docs/release/notes.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/subprojects/docs/src/docs/release/notes.md b/subprojects/docs/src/docs/release/notes.md index ab022f7b274ef..0b75959b5bb8e 100644 --- a/subprojects/docs/src/docs/release/notes.md +++ b/subprojects/docs/src/docs/release/notes.md @@ -71,6 +71,16 @@ Execution failed for task ':clean'. ## Improvements for plugin authors +### Public API for publishing custom components + +Gradle now offers a public API to publish custom software components. +Refer to the `SoftwareComponentFactory` javadocs for details or look at the `JavaPlugin` and `JavaPlaftormPlugin` which have been migrated to use this API. + +### Gradle Module Metadata 1.0 + +Gradle Module Metadata is now 1.0. +Gradle will automatically consume published Gradle Metadata, but publication still requires to enable the `GRADLE_METADATA` feature preview. + ### Use abstract types - TBD - Abstract service injection getter methods From 5a9c23101108aa209fdc72b265a36a3911d6649d Mon Sep 17 00:00:00 2001 From: Cedric Champeau Date: Thu, 28 Feb 2019 09:20:01 +0100 Subject: [PATCH 228/853] Fix link to the module metadata file --- subprojects/docs/src/docs/userguide/feature_variants.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subprojects/docs/src/docs/userguide/feature_variants.adoc b/subprojects/docs/src/docs/userguide/feature_variants.adoc index ccabe151d4c28..f129b806b0cc9 100644 --- a/subprojects/docs/src/docs/userguide/feature_variants.adoc +++ b/subprojects/docs/src/docs/userguide/feature_variants.adoc @@ -13,7 +13,7 @@ // limitations under the License. :maven-optional-deps: https://maven.apache.org/guides/introduction/introduction-to-optional-and-excludes-dependencies.html[Maven optional dependencies] -:metadata-file-spec: https://github.com/gradle/gradle/blob/master/subprojects/docs/src/docs/design/gradle-module-metadata-specification.md +:metadata-file-spec: https://github.com/gradle/gradle/blob/master/subprojects/docs/src/docs/design/gradle-module-metadata-1.0-specification.md [[feature_variants]] = Feature variants and optional dependencies From 724c39eba712ec6c488565fcc0b3db01ec757abf Mon Sep 17 00:00:00 2001 From: Paul Merlin Date: Thu, 28 Feb 2019 09:26:08 +0100 Subject: [PATCH 229/853] Make ktlint happy Signed-off-by: Paul Merlin --- .../tasks/GeneratePrecompiledScriptPluginAccessors.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/GeneratePrecompiledScriptPluginAccessors.kt b/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/GeneratePrecompiledScriptPluginAccessors.kt index 00badf46a4900..2639e925372ba 100644 --- a/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/GeneratePrecompiledScriptPluginAccessors.kt +++ b/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/GeneratePrecompiledScriptPluginAccessors.kt @@ -233,8 +233,8 @@ open class GeneratePrecompiledScriptPluginAccessors : ClassPathSensitiveCodeGene prefix = "Failed to generate type-safe Gradle model accessors for the following precompiled script plugins:\n", separator = "\n", postfix = "\n" - ) { " - " + projectRelativePathOf(it.scriptPlugin) } - , error + ) { " - " + projectRelativePathOf(it.scriptPlugin) }, + error ) } From 12764180d3b250c54787c9398936d00a40788a4a Mon Sep 17 00:00:00 2001 From: Peter Ledbrook Date: Thu, 28 Feb 2019 09:19:31 +0000 Subject: [PATCH 230/853] Fix Asciidoctor deprecation warnings (#8513) This meant upgrading to version 1.5.10 of the Asciidoctor Gradle Plugin and *also* specifying the version of AsciidoctorJ to use in the build because version 1.5.10 of the plugin uses a version of AsciidoctorJ that is binary incompatible with our Asciidoctor extension. --- buildSrc/subprojects/build/build.gradle.kts | 2 +- subprojects/docs/docs.gradle | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/buildSrc/subprojects/build/build.gradle.kts b/buildSrc/subprojects/build/build.gradle.kts index e60abe0eb4c81..a5b22dd1095f1 100644 --- a/buildSrc/subprojects/build/build.gradle.kts +++ b/buildSrc/subprojects/build/build.gradle.kts @@ -1,6 +1,6 @@ dependencies { api("com.google.guava:guava:26.0-jre") - api("org.asciidoctor:asciidoctor-gradle-plugin:1.5.9.2") + api("org.asciidoctor:asciidoctor-gradle-plugin:1.5.10") implementation(project(":buildPlatform")) implementation("org.asciidoctor:asciidoctorj:1.5.8.1") diff --git a/subprojects/docs/docs.gradle b/subprojects/docs/docs.gradle index 283154d414f0d..b6365b1b589f5 100755 --- a/subprojects/docs/docs.gradle +++ b/subprojects/docs/docs.gradle @@ -352,6 +352,7 @@ def distDocs = tasks.register("distDocs", CacheableAsciidoctorTask) { } asciidoctorj { + version = '1.5.8.1' noDefaultRepositories = true } From 210b99dc62e1ad645aef7006d77a6b8bf28254b6 Mon Sep 17 00:00:00 2001 From: Paul Merlin Date: Wed, 27 Feb 2019 17:14:39 +0100 Subject: [PATCH 231/853] Add :kotlinDslProviderPlugins tests to CIBuildModel Signed-off-by: Paul Merlin --- .teamcity/Gradle_Check/model/CIBuildModel.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.teamcity/Gradle_Check/model/CIBuildModel.kt b/.teamcity/Gradle_Check/model/CIBuildModel.kt index 66c72f058454f..f329f39edee36 100644 --- a/.teamcity/Gradle_Check/model/CIBuildModel.kt +++ b/.teamcity/Gradle_Check/model/CIBuildModel.kt @@ -164,7 +164,7 @@ data class CIBuildModel ( GradleSubproject("apiMetadata", unitTests = false, functionalTests = false), GradleSubproject("kotlinDsl", unitTests = true, functionalTests = true), - GradleSubproject("kotlinDslProviderPlugins", unitTests = false, functionalTests = false), + GradleSubproject("kotlinDslProviderPlugins", unitTests = true, functionalTests = true), GradleSubproject("kotlinDslToolingModels", unitTests = false, functionalTests = false), GradleSubproject("kotlinDslToolingBuilders", unitTests = true, functionalTests = true), GradleSubproject("kotlinDslPlugins", unitTests = true, functionalTests = true), From 084e381464a1ff9d6ae2256ee731bb952ec5f2be Mon Sep 17 00:00:00 2001 From: Paul Merlin Date: Thu, 28 Feb 2019 11:12:58 +0100 Subject: [PATCH 232/853] Let 'does not generate events for non-existing build scripts' test be more precise and resilient by actually testing there's no script event instead of asserting on a magic number of events that encompass the combinations of tapi versions and target gradle versions Signed-off-by: Paul Merlin --- ...rojectConfigurationChildrenProgressCrossVersionSpec.groovy | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/subprojects/tooling-api/src/crossVersionTest/groovy/org/gradle/integtests/tooling/r40/ProjectConfigurationChildrenProgressCrossVersionSpec.groovy b/subprojects/tooling-api/src/crossVersionTest/groovy/org/gradle/integtests/tooling/r40/ProjectConfigurationChildrenProgressCrossVersionSpec.groovy index cf02414782581..5749439d53543 100644 --- a/subprojects/tooling-api/src/crossVersionTest/groovy/org/gradle/integtests/tooling/r40/ProjectConfigurationChildrenProgressCrossVersionSpec.groovy +++ b/subprojects/tooling-api/src/crossVersionTest/groovy/org/gradle/integtests/tooling/r40/ProjectConfigurationChildrenProgressCrossVersionSpec.groovy @@ -116,7 +116,9 @@ class ProjectConfigurationChildrenProgressCrossVersionSpec extends ToolingApiSpe events.assertIsABuild() and: - events.operation('Configure project :').children.size() <= 6 //only 'Apply plugin org.gradle.help-tasks', maybe before/afterEvaluated and 3 delayed task registrations + events.operation('Configure project :').descendants { + it.descriptor.displayName.contains("Apply script") + }.isEmpty() } def "generates events for applied build scripts"() { From 1082c99e2090e14f96bb4984c2694697ffb0d06f Mon Sep 17 00:00:00 2001 From: "Rodrigo B. de Oliveira" Date: Thu, 28 Feb 2019 10:22:43 -0300 Subject: [PATCH 233/853] Suppress more warnings in the generated Kotlin code --- .../kotlin/org/gradle/kotlin/dsl/codegen/SourceFileHeader.kt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/codegen/SourceFileHeader.kt b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/codegen/SourceFileHeader.kt index dd4bca850ad34..5713f756b347c 100644 --- a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/codegen/SourceFileHeader.kt +++ b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/codegen/SourceFileHeader.kt @@ -28,7 +28,10 @@ fun fileHeaderFor(packageName: String) = @file:Suppress( "redundant_projection", - "nothing_to_inline" + "nothing_to_inline", + "RemoveRedundantBackticks", + "ObjectPropertyName", + "unused" ) package $packageName From fe160891f79a410dc8e5b8c0f2dcbf8acb78fa21 Mon Sep 17 00:00:00 2001 From: "Rodrigo B. de Oliveira" Date: Thu, 28 Feb 2019 10:39:16 -0300 Subject: [PATCH 234/853] Move `DefaultPrecompiledScriptPluginsSupport` and family to correct package --- ...ompilePrecompiledScriptPluginPluginsTest.kt | 2 +- .../KotlinDslProviderPluginsServiceRegistry.kt | 2 +- .../DefaultPrecompiledScriptPluginsSupport.kt | 18 +++++++++--------- .../precompiled/PrecompiledScriptPlugin.kt | 2 +- .../tasks/AbstractTaskExtensions.kt | 2 +- .../ClassPathSensitiveCodeGenerationTask.kt | 2 +- .../tasks/ClassPathSensitiveTask.kt | 2 +- .../CompilePrecompiledScriptPluginPlugins.kt | 2 +- ...urePrecompiledScriptDependenciesResolver.kt | 2 +- .../tasks/DirectoryPropertyExtensions.kt | 2 +- .../ExtractPrecompiledScriptPluginPlugins.kt | 4 ++-- .../GenerateExternalPluginSpecBuilders.kt | 2 +- .../GenerateInternalPluginSpecBuilders.kt | 4 ++-- ...GeneratePrecompiledScriptPluginAccessors.kt | 4 ++-- .../tasks/GenerateScriptPluginAdapters.kt | 4 ++-- .../precompiled/PrecompiledScriptPluginTest.kt | 4 ++-- ...xtractPrecompiledScriptPluginPluginsTest.kt | 4 ++-- 17 files changed, 31 insertions(+), 31 deletions(-) rename subprojects/kotlin-dsl-provider-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/{ => provider}/plugins/precompiled/tasks/CompilePrecompiledScriptPluginPluginsTest.kt (98%) rename subprojects/kotlin-dsl-provider-plugins/src/test/kotlin/org/gradle/kotlin/dsl/{ => provider}/plugins/precompiled/PrecompiledScriptPluginTest.kt (95%) rename subprojects/kotlin-dsl-provider-plugins/src/test/kotlin/org/gradle/kotlin/dsl/{ => provider}/plugins/precompiled/tasks/ExtractPrecompiledScriptPluginPluginsTest.kt (96%) diff --git a/subprojects/kotlin-dsl-provider-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/CompilePrecompiledScriptPluginPluginsTest.kt b/subprojects/kotlin-dsl-provider-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/CompilePrecompiledScriptPluginPluginsTest.kt similarity index 98% rename from subprojects/kotlin-dsl-provider-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/CompilePrecompiledScriptPluginPluginsTest.kt rename to subprojects/kotlin-dsl-provider-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/CompilePrecompiledScriptPluginPluginsTest.kt index 98ef9308c9403..3c277f6ca45a4 100644 --- a/subprojects/kotlin-dsl-provider-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/CompilePrecompiledScriptPluginPluginsTest.kt +++ b/subprojects/kotlin-dsl-provider-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/CompilePrecompiledScriptPluginPluginsTest.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.gradle.kotlin.dsl.plugins.precompiled.tasks +package org.gradle.kotlin.dsl.provider.plugins.precompiled.tasks import com.nhaarman.mockito_kotlin.any import com.nhaarman.mockito_kotlin.doReturn diff --git a/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/KotlinDslProviderPluginsServiceRegistry.kt b/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/KotlinDslProviderPluginsServiceRegistry.kt index 398cb26b53b2c..002b9fa59aa78 100644 --- a/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/KotlinDslProviderPluginsServiceRegistry.kt +++ b/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/KotlinDslProviderPluginsServiceRegistry.kt @@ -19,7 +19,7 @@ package org.gradle.kotlin.dsl.provider.plugins import org.gradle.internal.service.ServiceRegistration import org.gradle.internal.service.scopes.AbstractPluginServiceRegistry -import org.gradle.kotlin.dsl.plugins.precompiled.DefaultPrecompiledScriptPluginsSupport +import org.gradle.kotlin.dsl.provider.plugins.precompiled.DefaultPrecompiledScriptPluginsSupport class KotlinDslProviderPluginsServiceRegistry : AbstractPluginServiceRegistry() { diff --git a/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/DefaultPrecompiledScriptPluginsSupport.kt b/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/DefaultPrecompiledScriptPluginsSupport.kt index 821cf143a6b60..49278618f4515 100644 --- a/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/DefaultPrecompiledScriptPluginsSupport.kt +++ b/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/DefaultPrecompiledScriptPluginsSupport.kt @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.gradle.kotlin.dsl.plugins.precompiled +package org.gradle.kotlin.dsl.provider.plugins.precompiled import org.gradle.api.Project import org.gradle.api.Task @@ -26,14 +26,14 @@ import org.gradle.api.tasks.SourceSetContainer import org.gradle.api.tasks.TaskProvider import org.gradle.kotlin.dsl.* -import org.gradle.kotlin.dsl.plugins.precompiled.tasks.CompilePrecompiledScriptPluginPlugins -import org.gradle.kotlin.dsl.plugins.precompiled.tasks.ConfigurePrecompiledScriptDependenciesResolver -import org.gradle.kotlin.dsl.plugins.precompiled.tasks.ExtractPrecompiledScriptPluginPlugins -import org.gradle.kotlin.dsl.plugins.precompiled.tasks.GenerateExternalPluginSpecBuilders -import org.gradle.kotlin.dsl.plugins.precompiled.tasks.GenerateInternalPluginSpecBuilders -import org.gradle.kotlin.dsl.plugins.precompiled.tasks.GeneratePrecompiledScriptPluginAccessors -import org.gradle.kotlin.dsl.plugins.precompiled.tasks.GenerateScriptPluginAdapters -import org.gradle.kotlin.dsl.plugins.precompiled.tasks.HashedProjectSchema +import org.gradle.kotlin.dsl.provider.plugins.precompiled.tasks.CompilePrecompiledScriptPluginPlugins +import org.gradle.kotlin.dsl.provider.plugins.precompiled.tasks.ConfigurePrecompiledScriptDependenciesResolver +import org.gradle.kotlin.dsl.provider.plugins.precompiled.tasks.ExtractPrecompiledScriptPluginPlugins +import org.gradle.kotlin.dsl.provider.plugins.precompiled.tasks.GenerateExternalPluginSpecBuilders +import org.gradle.kotlin.dsl.provider.plugins.precompiled.tasks.GenerateInternalPluginSpecBuilders +import org.gradle.kotlin.dsl.provider.plugins.precompiled.tasks.GeneratePrecompiledScriptPluginAccessors +import org.gradle.kotlin.dsl.provider.plugins.precompiled.tasks.GenerateScriptPluginAdapters +import org.gradle.kotlin.dsl.provider.plugins.precompiled.tasks.HashedProjectSchema import org.gradle.kotlin.dsl.precompile.PrecompiledInitScript import org.gradle.kotlin.dsl.precompile.PrecompiledProjectScript diff --git a/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/PrecompiledScriptPlugin.kt b/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/PrecompiledScriptPlugin.kt index 2b8155a70e873..e0dbb37199263 100644 --- a/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/PrecompiledScriptPlugin.kt +++ b/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/PrecompiledScriptPlugin.kt @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.gradle.kotlin.dsl.plugins.precompiled +package org.gradle.kotlin.dsl.provider.plugins.precompiled import org.gradle.api.Plugin diff --git a/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/AbstractTaskExtensions.kt b/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/AbstractTaskExtensions.kt index e3868e4bc42a0..d863a34847731 100644 --- a/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/AbstractTaskExtensions.kt +++ b/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/AbstractTaskExtensions.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.gradle.kotlin.dsl.plugins.precompiled.tasks +package org.gradle.kotlin.dsl.provider.plugins.precompiled.tasks import org.gradle.api.internal.AbstractTask diff --git a/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/ClassPathSensitiveCodeGenerationTask.kt b/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/ClassPathSensitiveCodeGenerationTask.kt index af1741817a33c..f0df2ae708ceb 100644 --- a/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/ClassPathSensitiveCodeGenerationTask.kt +++ b/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/ClassPathSensitiveCodeGenerationTask.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.gradle.kotlin.dsl.plugins.precompiled.tasks +package org.gradle.kotlin.dsl.provider.plugins.precompiled.tasks import org.gradle.api.tasks.OutputDirectory diff --git a/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/ClassPathSensitiveTask.kt b/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/ClassPathSensitiveTask.kt index d95607784e877..d6380c1eb6a76 100644 --- a/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/ClassPathSensitiveTask.kt +++ b/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/ClassPathSensitiveTask.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.gradle.kotlin.dsl.plugins.precompiled.tasks +package org.gradle.kotlin.dsl.provider.plugins.precompiled.tasks import org.gradle.api.DefaultTask import org.gradle.api.file.FileCollection diff --git a/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/CompilePrecompiledScriptPluginPlugins.kt b/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/CompilePrecompiledScriptPluginPlugins.kt index 906fdb5257cf6..adaa2b61b9861 100644 --- a/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/CompilePrecompiledScriptPluginPlugins.kt +++ b/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/CompilePrecompiledScriptPluginPlugins.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.gradle.kotlin.dsl.plugins.precompiled.tasks +package org.gradle.kotlin.dsl.provider.plugins.precompiled.tasks import org.gradle.api.file.Directory import org.gradle.api.internal.AbstractTask diff --git a/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/ConfigurePrecompiledScriptDependenciesResolver.kt b/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/ConfigurePrecompiledScriptDependenciesResolver.kt index a8a04cada4ff8..030b0b9676a07 100644 --- a/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/ConfigurePrecompiledScriptDependenciesResolver.kt +++ b/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/ConfigurePrecompiledScriptDependenciesResolver.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.gradle.kotlin.dsl.plugins.precompiled.tasks +package org.gradle.kotlin.dsl.provider.plugins.precompiled.tasks import org.gradle.api.DefaultTask import org.gradle.api.Project diff --git a/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/DirectoryPropertyExtensions.kt b/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/DirectoryPropertyExtensions.kt index f2c2ffdf281cb..635095b0a6cfd 100644 --- a/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/DirectoryPropertyExtensions.kt +++ b/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/DirectoryPropertyExtensions.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.gradle.kotlin.dsl.plugins.precompiled.tasks +package org.gradle.kotlin.dsl.provider.plugins.precompiled.tasks import org.gradle.api.file.DirectoryProperty diff --git a/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/ExtractPrecompiledScriptPluginPlugins.kt b/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/ExtractPrecompiledScriptPluginPlugins.kt index 7db2311349098..3f2ec41f54fc1 100644 --- a/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/ExtractPrecompiledScriptPluginPlugins.kt +++ b/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/ExtractPrecompiledScriptPluginPlugins.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.gradle.kotlin.dsl.plugins.precompiled.tasks +package org.gradle.kotlin.dsl.provider.plugins.precompiled.tasks import org.gradle.api.DefaultTask import org.gradle.api.Project @@ -32,7 +32,7 @@ import org.gradle.kotlin.dsl.execution.ProgramParser import org.gradle.kotlin.dsl.execution.ProgramSource import org.gradle.kotlin.dsl.execution.ProgramTarget -import org.gradle.kotlin.dsl.plugins.precompiled.PrecompiledScriptPlugin +import org.gradle.kotlin.dsl.provider.plugins.precompiled.PrecompiledScriptPlugin import org.gradle.kotlin.dsl.support.KotlinScriptType diff --git a/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/GenerateExternalPluginSpecBuilders.kt b/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/GenerateExternalPluginSpecBuilders.kt index e41321c0176bc..b13d303465db1 100644 --- a/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/GenerateExternalPluginSpecBuilders.kt +++ b/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/GenerateExternalPluginSpecBuilders.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.gradle.kotlin.dsl.plugins.precompiled.tasks +package org.gradle.kotlin.dsl.provider.plugins.precompiled.tasks import org.gradle.api.tasks.CacheableTask import org.gradle.api.tasks.Internal diff --git a/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/GenerateInternalPluginSpecBuilders.kt b/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/GenerateInternalPluginSpecBuilders.kt index fb93fe2bfeb55..1e12364c5a0f2 100644 --- a/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/GenerateInternalPluginSpecBuilders.kt +++ b/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/GenerateInternalPluginSpecBuilders.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.gradle.kotlin.dsl.plugins.precompiled.tasks +package org.gradle.kotlin.dsl.provider.plugins.precompiled.tasks import org.gradle.api.DefaultTask import org.gradle.api.tasks.CacheableTask @@ -25,7 +25,7 @@ import org.gradle.api.tasks.PathSensitive import org.gradle.api.tasks.PathSensitivity import org.gradle.api.tasks.TaskAction -import org.gradle.kotlin.dsl.plugins.precompiled.PrecompiledScriptPlugin +import org.gradle.kotlin.dsl.provider.plugins.precompiled.PrecompiledScriptPlugin import java.io.File diff --git a/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/GeneratePrecompiledScriptPluginAccessors.kt b/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/GeneratePrecompiledScriptPluginAccessors.kt index 2639e925372ba..9caaf98aeeb07 100644 --- a/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/GeneratePrecompiledScriptPluginAccessors.kt +++ b/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/GeneratePrecompiledScriptPluginAccessors.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.gradle.kotlin.dsl.plugins.precompiled.tasks +package org.gradle.kotlin.dsl.provider.plugins.precompiled.tasks import org.gradle.api.Project import org.gradle.api.internal.artifacts.dependencies.DefaultSelfResolvingDependency @@ -46,7 +46,7 @@ import org.gradle.kotlin.dsl.concurrent.IO import org.gradle.kotlin.dsl.concurrent.withAsynchronousIO import org.gradle.kotlin.dsl.concurrent.writeFile -import org.gradle.kotlin.dsl.plugins.precompiled.PrecompiledScriptPlugin +import org.gradle.kotlin.dsl.provider.plugins.precompiled.PrecompiledScriptPlugin import org.gradle.kotlin.dsl.precompile.PrecompiledScriptDependenciesResolver diff --git a/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/GenerateScriptPluginAdapters.kt b/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/GenerateScriptPluginAdapters.kt index f9ae19c8fe871..213ed42506ba3 100644 --- a/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/GenerateScriptPluginAdapters.kt +++ b/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/GenerateScriptPluginAdapters.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.gradle.kotlin.dsl.plugins.precompiled.tasks +package org.gradle.kotlin.dsl.provider.plugins.precompiled.tasks import org.gradle.api.DefaultTask import org.gradle.api.tasks.CacheableTask @@ -25,7 +25,7 @@ import org.gradle.api.tasks.PathSensitive import org.gradle.api.tasks.PathSensitivity import org.gradle.api.tasks.TaskAction -import org.gradle.kotlin.dsl.plugins.precompiled.PrecompiledScriptPlugin +import org.gradle.kotlin.dsl.provider.plugins.precompiled.PrecompiledScriptPlugin import org.gradle.kotlin.dsl.support.normaliseLineSeparators diff --git a/subprojects/kotlin-dsl-provider-plugins/src/test/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPluginTest.kt b/subprojects/kotlin-dsl-provider-plugins/src/test/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/PrecompiledScriptPluginTest.kt similarity index 95% rename from subprojects/kotlin-dsl-provider-plugins/src/test/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPluginTest.kt rename to subprojects/kotlin-dsl-provider-plugins/src/test/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/PrecompiledScriptPluginTest.kt index c2f2492f132ec..a7861f2e3ad43 100644 --- a/subprojects/kotlin-dsl-provider-plugins/src/test/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPluginTest.kt +++ b/subprojects/kotlin-dsl-provider-plugins/src/test/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/PrecompiledScriptPluginTest.kt @@ -1,8 +1,8 @@ -package org.gradle.kotlin.dsl.plugins.precompiled +package org.gradle.kotlin.dsl.provider.plugins.precompiled import org.gradle.kotlin.dsl.fixtures.TestWithTempFiles -import org.gradle.kotlin.dsl.plugins.precompiled.tasks.writeScriptPluginAdapterTo +import org.gradle.kotlin.dsl.provider.plugins.precompiled.tasks.writeScriptPluginAdapterTo import org.hamcrest.CoreMatchers.equalTo import org.hamcrest.CoreMatchers.startsWith diff --git a/subprojects/kotlin-dsl-provider-plugins/src/test/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/ExtractPrecompiledScriptPluginPluginsTest.kt b/subprojects/kotlin-dsl-provider-plugins/src/test/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/ExtractPrecompiledScriptPluginPluginsTest.kt similarity index 96% rename from subprojects/kotlin-dsl-provider-plugins/src/test/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/ExtractPrecompiledScriptPluginPluginsTest.kt rename to subprojects/kotlin-dsl-provider-plugins/src/test/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/ExtractPrecompiledScriptPluginPluginsTest.kt index 30c4bbe72bee5..2e52446201fcf 100644 --- a/subprojects/kotlin-dsl-provider-plugins/src/test/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/tasks/ExtractPrecompiledScriptPluginPluginsTest.kt +++ b/subprojects/kotlin-dsl-provider-plugins/src/test/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/ExtractPrecompiledScriptPluginPluginsTest.kt @@ -14,12 +14,12 @@ * limitations under the License. */ -package org.gradle.kotlin.dsl.plugins.precompiled.tasks +package org.gradle.kotlin.dsl.provider.plugins.precompiled.tasks import org.gradle.kotlin.dsl.fixtures.TestWithTempFiles import org.gradle.kotlin.dsl.fixtures.equalToMultiLineString -import org.gradle.kotlin.dsl.plugins.precompiled.PrecompiledScriptPlugin +import org.gradle.kotlin.dsl.provider.plugins.precompiled.PrecompiledScriptPlugin import org.hamcrest.Description import org.hamcrest.Matcher From d6da1e691d5fa3441b6fa12db8bfde8d09192e19 Mon Sep 17 00:00:00 2001 From: "Rodrigo B. de Oliveira" Date: Thu, 28 Feb 2019 11:26:42 -0300 Subject: [PATCH 235/853] Suppress `Useless cast` warnings for generated code --- .../org/gradle/kotlin/dsl/codegen/SourceFileHeader.kt | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/codegen/SourceFileHeader.kt b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/codegen/SourceFileHeader.kt index 5713f756b347c..709c7bc61a0c7 100644 --- a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/codegen/SourceFileHeader.kt +++ b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/codegen/SourceFileHeader.kt @@ -27,11 +27,12 @@ fun fileHeaderFor(packageName: String) = """$licenseHeader @file:Suppress( - "redundant_projection", + "unused", "nothing_to_inline", + "useless_cast", + "redundant_projection", "RemoveRedundantBackticks", - "ObjectPropertyName", - "unused" + "ObjectPropertyName" ) package $packageName From 8506c57b0218bd809c34876792706a09af138047 Mon Sep 17 00:00:00 2001 From: Sterling Greene Date: Thu, 28 Feb 2019 09:27:02 -0500 Subject: [PATCH 236/853] Update docker plugin test to use different tasks --- .../org/gradle/smoketests/ThirdPartyPluginsSmokeTest.groovy | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/subprojects/smoke-test/src/smokeTest/groovy/org/gradle/smoketests/ThirdPartyPluginsSmokeTest.groovy b/subprojects/smoke-test/src/smokeTest/groovy/org/gradle/smoketests/ThirdPartyPluginsSmokeTest.groovy index 0305dfc2fde79..5e7255d5b2cc2 100644 --- a/subprojects/smoke-test/src/smokeTest/groovy/org/gradle/smoketests/ThirdPartyPluginsSmokeTest.groovy +++ b/subprojects/smoke-test/src/smokeTest/groovy/org/gradle/smoketests/ThirdPartyPluginsSmokeTest.groovy @@ -117,10 +117,10 @@ class ThirdPartyPluginsSmokeTest extends AbstractSmokeTest { """.stripIndent() when: - def result = runner('dockerSyncArchive').forwardOutput().build() + def result = runner('assemble').forwardOutput().build() then: - result.task(':dockerSyncArchive').outcome == SUCCESS + result.task(':assemble').outcome == SUCCESS } @Issue('https://plugins.gradle.org/plugin/io.spring.dependency-management') From 89790db7326a5fa24ed0430119e7410393b65b45 Mon Sep 17 00:00:00 2001 From: "Rodrigo B. de Oliveira" Date: Thu, 28 Feb 2019 11:42:50 -0300 Subject: [PATCH 237/853] Format generated plugin spec builders correctly --- ...eneratePrecompiledScriptPluginAccessors.kt | 15 ++--------- .../dsl/accessors/AccessorsClassPath.kt | 27 +++++++++++++++++-- .../gradle/kotlin/dsl/accessors/Emitter.kt | 8 +++--- .../dsl/accessors/PluginAccessorsClassPath.kt | 22 +++++++-------- .../dsl/codegen/GradleApiExtensionsTest.kt | 2 +- 5 files changed, 43 insertions(+), 31 deletions(-) diff --git a/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/GeneratePrecompiledScriptPluginAccessors.kt b/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/GeneratePrecompiledScriptPluginAccessors.kt index 9caaf98aeeb07..c10042b340b46 100644 --- a/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/GeneratePrecompiledScriptPluginAccessors.kt +++ b/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/GeneratePrecompiledScriptPluginAccessors.kt @@ -37,6 +37,7 @@ import org.gradle.internal.concurrent.CompositeStoppable.stoppable import org.gradle.internal.hash.HashCode import org.gradle.internal.resource.BasicTextResourceLoader +import org.gradle.kotlin.dsl.accessors.AccessorFormats import org.gradle.kotlin.dsl.accessors.TypedProjectSchema import org.gradle.kotlin.dsl.accessors.buildAccessorsFor import org.gradle.kotlin.dsl.accessors.hashCodeFor @@ -250,22 +251,10 @@ open class GeneratePrecompiledScriptPluginAccessors : ClassPathSensitiveCodeGene sourceCodeOutputDir.get().asFile, temporaryDir.resolve("accessors"), hashedSchema.packageName, - ::makeInternal + AccessorFormats.internal ) } - private - fun makeInternal(accessor: String): String = - accessor - .replaceIndent() - .let { valOrFun.matcher(it) } - .replaceAll("internal\n$1 ") - - private - val valOrFun by lazy { - "^(val|fun) ".toRegex(RegexOption.MULTILINE).toPattern() - } - private fun IO.writeContentAddressableImplicitImportFor(scriptPlugin: ScriptPluginPlugins, packageName: String) { io { writeFile(implicitImportFileFor(scriptPlugin), "$packageName.*".toByteArray()) } diff --git a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/accessors/AccessorsClassPath.kt b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/accessors/AccessorsClassPath.kt index c4a2c8fd7b7dc..94043185bdb50 100644 --- a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/accessors/AccessorsClassPath.kt +++ b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/accessors/AccessorsClassPath.kt @@ -154,7 +154,7 @@ fun IO.buildAccessorsFor( srcDir: File, binDir: File, packageName: String = kotlinDslPackageName, - accessorFormat: (String) -> String = { it.replaceIndent() } + format: AccessorFormat = AccessorFormats.default ) { val availableSchema = availableProjectSchemaFor(projectSchema, classPath) emitAccessorsFor( @@ -162,11 +162,34 @@ fun IO.buildAccessorsFor( srcDir, binDir, OutputPackage(packageName), - accessorFormat + format ) } +typealias AccessorFormat = (String) -> String + + +object AccessorFormats { + + val default: AccessorFormat = { accessor -> + accessor.replaceIndent() + } + + val `internal`: AccessorFormat = { accessor -> + accessor + .replaceIndent() + .let { valFunOrClass.matcher(it) } + .replaceAll("internal\n$1 ") + } + + private + val valFunOrClass by lazy { + "^(val|fun|class) ".toRegex(RegexOption.MULTILINE).toPattern() + } +} + + internal fun importsRequiredBy(candidateTypes: List): List = defaultPackageTypesIn( diff --git a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/accessors/Emitter.kt b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/accessors/Emitter.kt index da9c8a7fa79b5..b7cf4bcaee20f 100644 --- a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/accessors/Emitter.kt +++ b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/accessors/Emitter.kt @@ -39,7 +39,7 @@ fun IO.emitAccessorsFor( srcDir: File, binDir: File, outputPackage: OutputPackage, - accessorFormat: (String) -> String + format: AccessorFormat ): List { makeAccessorOutputDirs(srcDir, binDir, outputPackage.path) @@ -51,7 +51,7 @@ fun IO.emitAccessorsFor( srcDir, binDir, outputPackage, - accessorFormat + format ) }.toList() @@ -87,7 +87,7 @@ fun IO.emitClassFor( srcDir: File, binDir: File, outputPackage: OutputPackage, - accessorFormat: (String) -> String + format: AccessorFormat ): InternalName { val (simpleClassName, fragments) = fragmentsFor(accessor) @@ -97,7 +97,7 @@ fun IO.emitClassFor( val classWriter = beginPublicClass(className) for ((source, bytecode, metadata, signature) in fragments) { - sourceCode.add(accessorFormat(source)) + sourceCode.add(format(source)) MetadataFragmentScope(signature, metadataWriter).run(metadata) BytecodeFragmentScope(signature, classWriter).run(bytecode) } diff --git a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/accessors/PluginAccessorsClassPath.kt b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/accessors/PluginAccessorsClassPath.kt index d9f143124fdb4..08bc1237aa619 100644 --- a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/accessors/PluginAccessorsClassPath.kt +++ b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/accessors/PluginAccessorsClassPath.kt @@ -108,7 +108,7 @@ fun writeSourceCodeForPluginSpecBuildersFor( writePluginAccessorsSourceCodeTo( sourceFile, pluginAccessorsFor(pluginDescriptorsClassPath), - accessibility = "internal\n", + format = AccessorFormats.internal, header = fileHeaderFor(packageName) ) } @@ -213,12 +213,12 @@ private fun IO.writePluginAccessorsSourceCodeTo( sourceFile: File, accessors: List, - accessibility: String = "", + format: AccessorFormat = AccessorFormats.default, header: String = fileHeader ) = io { sourceFile.bufferedWriter().useToRun { appendReproducibleNewLine(header) - appendSourceCodeForPluginAccessors(accessors, accessibility) + appendSourceCodeForPluginAccessors(accessors, format) } } @@ -226,7 +226,7 @@ fun IO.writePluginAccessorsSourceCodeTo( private fun BufferedWriter.appendSourceCodeForPluginAccessors( accessors: List, - accessibility: String = "" + format: AccessorFormat ) { appendReproducibleNewLine(""" @@ -245,29 +245,29 @@ fun BufferedWriter.appendSourceCodeForPluginAccessors( val pluginsRef = pluginDependenciesSpecOf(extendedType) when (this) { is PluginAccessor.ForPlugin -> { - appendReproducibleNewLine(""" + appendReproducibleNewLine(format(""" /** * The `$id` plugin implemented by [$implementationClass]. */ - ${accessibility}val `$extendedType`.`${extension.name}`: PluginDependencySpec + val `$extendedType`.`${extension.name}`: PluginDependencySpec get() = $pluginsRef.id("$id") - """.replaceIndent()) + """)) } is PluginAccessor.ForGroup -> { val groupType = extension.returnType.sourceName - appendReproducibleNewLine(""" + appendReproducibleNewLine(format(""" /** * The `$id` plugin group. */ - ${accessibility}class `$groupType`(internal val plugins: PluginDependenciesSpec) + class `$groupType`(internal val plugins: PluginDependenciesSpec) /** * Plugin ids starting with `$id`. */ - ${accessibility}val `$extendedType`.`${extension.name}`: `$groupType` + val `$extendedType`.`${extension.name}`: `$groupType` get() = `$groupType`($pluginsRef) - """.replaceIndent()) + """)) } } } diff --git a/subprojects/kotlin-dsl/src/test/kotlin/org/gradle/kotlin/dsl/codegen/GradleApiExtensionsTest.kt b/subprojects/kotlin-dsl/src/test/kotlin/org/gradle/kotlin/dsl/codegen/GradleApiExtensionsTest.kt index c3a86d9d4a908..1b9c961064fd8 100644 --- a/subprojects/kotlin-dsl/src/test/kotlin/org/gradle/kotlin/dsl/codegen/GradleApiExtensionsTest.kt +++ b/subprojects/kotlin-dsl/src/test/kotlin/org/gradle/kotlin/dsl/codegen/GradleApiExtensionsTest.kt @@ -65,7 +65,7 @@ class GradleApiExtensionsTest : TestWithClassPath() { ClassAndGroovyNamedArguments::class ) { - assertGeneratedJarHash("54c81ce29b4ed6af36b8309be52f3f0f") + assertGeneratedJarHash("d873264108ff96eec77a33fc1084743b") } } From d81b9bfe07754c543c37d91357359f2305649502 Mon Sep 17 00:00:00 2001 From: Stefan Wolf Date: Thu, 28 Feb 2019 16:21:07 +0100 Subject: [PATCH 238/853] Disallow Nested on transform parameters The user experience is currently not very good, mostly because we don't generate the nested managed type automatically if there is only an abstract getter declared. Let's re-introduce Nested when we have better support for nested managed types. --- ...sformValuesInjectionIntegrationTest.groovy | 24 ++------ ...nsformWithFileInputsIntegrationTest.groovy | 56 ------------------- ...pendencyManagementGlobalScopeServices.java | 3 +- 3 files changed, 5 insertions(+), 78 deletions(-) diff --git a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformValuesInjectionIntegrationTest.groovy b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformValuesInjectionIntegrationTest.groovy index bc9f28d321f50..ef510900becd0 100644 --- a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformValuesInjectionIntegrationTest.groovy +++ b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformValuesInjectionIntegrationTest.groovy @@ -27,6 +27,7 @@ import org.gradle.api.tasks.InputDirectory import org.gradle.api.tasks.InputFile import org.gradle.api.tasks.Internal import org.gradle.api.tasks.LocalState +import org.gradle.api.tasks.Nested import org.gradle.api.tasks.OutputDirectories import org.gradle.api.tasks.OutputDirectory import org.gradle.api.tasks.OutputFile @@ -141,22 +142,9 @@ class ArtifactTransformValuesInjectionIntegrationTest extends AbstractDependency settingsFile << """ include 'a', 'b' """ - buildFile << """ - interface NestedType { - @InputFile - RegularFileProperty getInputFile() - @OutputDirectory - DirectoryProperty getOutputDirectory() - } - - allprojects { - ext.nested = objects.newInstance(NestedType) - } - """ setupBuildWithColorTransform { params(""" extension = 'green' - nested.set(project.ext.nested) """) } buildFile << """ @@ -198,8 +186,6 @@ class ArtifactTransformValuesInjectionIntegrationTest extends AbstractDependency @PathSensitive(PathSensitivity.ABSOLUTE) @InputFiles ConfigurableFileCollection getAbsolutePathSensitivity() - @Nested - Property getNested() } void transform(TransformOutputs outputs) { @@ -225,9 +211,7 @@ class ArtifactTransformValuesInjectionIntegrationTest extends AbstractDependency absolutePathSensitivity: 'is declared to be sensitive to absolute paths. This is not allowed for cacheable transforms', noPathSensitivity: 'is declared without path sensitivity. Properties of cacheable transforms must declare their path sensitivity', noPathSensitivityDir: 'is declared without path sensitivity. Properties of cacheable transforms must declare their path sensitivity', - noPathSensitivityFile: 'is declared without path sensitivity. Properties of cacheable transforms must declare their path sensitivity', - 'nested.outputDirectory': 'is annotated with unsupported annotation @OutputDirectory', - 'nested.inputFile': 'is declared without path sensitivity. Properties of cacheable transforms must declare their path sensitivity', + noPathSensitivityFile: 'is declared without path sensitivity. Properties of cacheable transforms must declare their path sensitivity' ) } @@ -342,7 +326,7 @@ class ArtifactTransformValuesInjectionIntegrationTest extends AbstractDependency assertPropertyValidationErrors(bad: "is annotated with unsupported annotation @${annotation.simpleName}") where: - annotation << [OutputFile, OutputFiles, OutputDirectory, OutputDirectories, Destroys, LocalState, OptionValues] + annotation << [OutputFile, OutputFiles, OutputDirectory, OutputDirectories, Destroys, LocalState, OptionValues, Nested] } @Unroll @@ -529,7 +513,7 @@ class ArtifactTransformValuesInjectionIntegrationTest extends AbstractDependency assertPropertyValidationErrors(bad: "is annotated with unsupported annotation @${annotation.simpleName}") where: - annotation << [Input, InputFile, InputDirectory, OutputFile, OutputFiles, OutputDirectory, OutputDirectories, Destroys, LocalState, OptionValues, Console, Internal] + annotation << [Input, InputFile, InputDirectory, OutputFile, OutputFiles, OutputDirectory, OutputDirectories, Destroys, LocalState, OptionValues, Console, Internal, Nested] } @Unroll diff --git a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformWithFileInputsIntegrationTest.groovy b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformWithFileInputsIntegrationTest.groovy index e3639d4342911..a042e9de43a65 100644 --- a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformWithFileInputsIntegrationTest.groovy +++ b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformWithFileInputsIntegrationTest.groovy @@ -114,62 +114,6 @@ class ArtifactTransformWithFileInputsIntegrationTest extends AbstractDependencyR outputContains("result = [b.jar.green, c.jar.green]") } - def "transform can receive a file input from a nested bean on the parameter object"() { - settingsFile << """ - include 'a', 'b' - """ - setupBuildWithColorTransform { - params(""" - nestedBean.set(provider { project.ext.nestedInputFiles }) - """) - } - buildFile << """ - interface NestedInputFiles { - @InputFiles - ConfigurableFileCollection getInputFiles() - } - - allprojects { - task tool(type: FileProducer) { - output = file("build/tool-\${project.name}.jar") - } - ext.nestedInputFiles = objects.newInstance(NestedInputFiles) - nestedInputFiles.inputFiles.from(tool.output) - } - - project(':a') { - dependencies { - implementation project(':b') - } - } - - abstract class MakeGreen implements TransformAction { - interface Parameters extends TransformParameters{ - @Nested - Property getNestedBean() - } - - @InputArtifact - abstract File getInput() - - void transform(TransformOutputs outputs) { - def inputFiles = parameters.nestedBean.get().inputFiles - println "processing \${input.name} using \${inputFiles*.name}" - def output = outputs.file(input.name + ".green") - def paramContent = inputFiles.collect { it.file ? it.text : it.list().length }.join("") - output.text = input.text + paramContent + ".green" - } - } - """ - - when: - run(":a:resolve") - - then: - outputContains("processing b.jar using [tool-a.jar]") - outputContains("result = [b.jar.green]") - } - def "transform can receive a file collection containing task outputs as parameter"() { settingsFile << """ include 'a', 'b', 'c' diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/DependencyManagementGlobalScopeServices.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/DependencyManagementGlobalScopeServices.java index 7b64f4c95404d..9647a65c2b347 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/DependencyManagementGlobalScopeServices.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/DependencyManagementGlobalScopeServices.java @@ -49,7 +49,6 @@ import org.gradle.api.tasks.InputFile; import org.gradle.api.tasks.InputFiles; import org.gradle.api.tasks.Internal; -import org.gradle.api.tasks.Nested; import org.gradle.cache.internal.ProducerGuard; import org.gradle.internal.instantiation.InstantiationScheme; import org.gradle.internal.instantiation.InstantiatorFactory; @@ -125,7 +124,7 @@ InputArtifactDependenciesAnnotationHandler createInputArtifactDependenciesAnnota ArtifactTransformParameterScheme createArtifactTransformParameterScheme(InspectionSchemeFactory inspectionSchemeFactory, InstantiatorFactory instantiatorFactory) { // TODO - should decorate InstantiationScheme instantiationScheme = instantiatorFactory.injectScheme(); - InspectionScheme inspectionScheme = inspectionSchemeFactory.inspectionScheme(ImmutableSet.of(Input.class, InputFile.class, InputFiles.class, InputDirectory.class, Classpath.class, CompileClasspath.class, Nested.class, Inject.class, Console.class, Internal.class)); + InspectionScheme inspectionScheme = inspectionSchemeFactory.inspectionScheme(ImmutableSet.of(Input.class, InputFile.class, InputFiles.class, InputDirectory.class, Classpath.class, CompileClasspath.class, Inject.class, Console.class, Internal.class)); return new ArtifactTransformParameterScheme(instantiationScheme, inspectionScheme); } From 97839812178d9f964b96cbac65d14e3c2fea5056 Mon Sep 17 00:00:00 2001 From: "Rodrigo B. de Oliveira" Date: Thu, 28 Feb 2019 12:35:44 -0300 Subject: [PATCH 239/853] Temporarily disable `:kotlinDsl:verifyTestFilesCleanup` Signed-off-by: Rodrigo B. de Oliveira --- subprojects/kotlin-dsl/kotlin-dsl.gradle.kts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/subprojects/kotlin-dsl/kotlin-dsl.gradle.kts b/subprojects/kotlin-dsl/kotlin-dsl.gradle.kts index c9814829c6717..65e1ec644ea6e 100644 --- a/subprojects/kotlin-dsl/kotlin-dsl.gradle.kts +++ b/subprojects/kotlin-dsl/kotlin-dsl.gradle.kts @@ -76,6 +76,11 @@ val publishedKotlinDslPluginVersion = "1.2.4" // TODO:kotlin-dsl tasks { + // TODO:kotlin-dsl + verifyTestFilesCleanup { + enabled = false + } + val generateKotlinDependencyExtensions by registering(GenerateKotlinDependencyExtensions::class) { outputFile = apiExtensionsOutputDir.resolve("org/gradle/kotlin/dsl/KotlinDependencyExtensions.kt") embeddedKotlinVersion = kotlinVersion From df8c9dc3985a402409c4e72cb031d913706a9298 Mon Sep 17 00:00:00 2001 From: Adam Murdoch Date: Fri, 1 Mar 2019 06:18:59 +1100 Subject: [PATCH 240/853] Remove some placeholders from release notes. These things can be announced in 5.4 instead, after some basic docs have been added and some fixes. --- subprojects/docs/src/docs/release/notes.md | 7 ------- 1 file changed, 7 deletions(-) diff --git a/subprojects/docs/src/docs/release/notes.md b/subprojects/docs/src/docs/release/notes.md index 0b75959b5bb8e..495aae1532251 100644 --- a/subprojects/docs/src/docs/release/notes.md +++ b/subprojects/docs/src/docs/release/notes.md @@ -81,13 +81,6 @@ Refer to the `SoftwareComponentFactory` javadocs for details or look at the `Jav Gradle Module Metadata is now 1.0. Gradle will automatically consume published Gradle Metadata, but publication still requires to enable the `GRADLE_METADATA` feature preview. -### Use abstract types - -- TBD - Abstract service injection getter methods -- TBD - Abstract mutable property -- TBD - Abstract `ConfigurableFileCollection` property -- TBD - Use an interface for Gradle instantiated types - ### Factory method for creating `ConfigurableFileCollection` instances using `ObjectFactory` Plugin and task implementations often need to create instances of various useful types, to provide a configurable model and DSL that is consistent with other Gradle plugins. One such type is `ConfigurableFileCollection`. In previous releases, plugins could use `Project.files()` or `ProjectLayout.configurableFiles()` to create instance of this type. However, these interfaces are not always available, for example in a `Settings` plugin (rather than a `Project` plugin) or in a nested model object. From 0e535831877ff431f99dc2fc2149658f1097c42b Mon Sep 17 00:00:00 2001 From: "Rodrigo B. de Oliveira" Date: Thu, 28 Feb 2019 17:15:34 -0300 Subject: [PATCH 241/853] Remove spurious blank line --- subprojects/announce/announce.gradle.kts | 1 - 1 file changed, 1 deletion(-) diff --git a/subprojects/announce/announce.gradle.kts b/subprojects/announce/announce.gradle.kts index 3e6da8bbb7768..a023de7050654 100644 --- a/subprojects/announce/announce.gradle.kts +++ b/subprojects/announce/announce.gradle.kts @@ -25,7 +25,6 @@ dependencies { gradlebuildJava { moduleType = ModuleType.CORE - } From e0274ff0a9b5f1b1dfecf0e9def2ae7243bbed03 Mon Sep 17 00:00:00 2001 From: "Rodrigo B. de Oliveira" Date: Thu, 28 Feb 2019 17:16:43 -0300 Subject: [PATCH 242/853] Organize imports --- .../DefaultPrecompiledScriptPluginsSupport.kt | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/DefaultPrecompiledScriptPluginsSupport.kt b/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/DefaultPrecompiledScriptPluginsSupport.kt index 49278618f4515..5cd90927c8c84 100644 --- a/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/DefaultPrecompiledScriptPluginsSupport.kt +++ b/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/DefaultPrecompiledScriptPluginsSupport.kt @@ -26,6 +26,12 @@ import org.gradle.api.tasks.SourceSetContainer import org.gradle.api.tasks.TaskProvider import org.gradle.kotlin.dsl.* +import org.gradle.kotlin.dsl.precompile.PrecompiledInitScript +import org.gradle.kotlin.dsl.precompile.PrecompiledProjectScript +import org.gradle.kotlin.dsl.precompile.PrecompiledSettingsScript + +import org.gradle.kotlin.dsl.provider.PrecompiledScriptPluginsSupport +import org.gradle.kotlin.dsl.provider.inClassPathMode import org.gradle.kotlin.dsl.provider.plugins.precompiled.tasks.CompilePrecompiledScriptPluginPlugins import org.gradle.kotlin.dsl.provider.plugins.precompiled.tasks.ConfigurePrecompiledScriptDependenciesResolver import org.gradle.kotlin.dsl.provider.plugins.precompiled.tasks.ExtractPrecompiledScriptPluginPlugins @@ -35,13 +41,6 @@ import org.gradle.kotlin.dsl.provider.plugins.precompiled.tasks.GeneratePrecompi import org.gradle.kotlin.dsl.provider.plugins.precompiled.tasks.GenerateScriptPluginAdapters import org.gradle.kotlin.dsl.provider.plugins.precompiled.tasks.HashedProjectSchema -import org.gradle.kotlin.dsl.precompile.PrecompiledInitScript -import org.gradle.kotlin.dsl.precompile.PrecompiledProjectScript -import org.gradle.kotlin.dsl.precompile.PrecompiledSettingsScript - -import org.gradle.kotlin.dsl.provider.PrecompiledScriptPluginsSupport -import org.gradle.kotlin.dsl.provider.inClassPathMode - import org.gradle.kotlin.dsl.resolver.kotlinBuildScriptModelTask import org.gradle.plugin.devel.GradlePluginDevelopmentExtension From 6850d17ade8c444dbf655eabcff25945ef0c7c8b Mon Sep 17 00:00:00 2001 From: "Rodrigo B. de Oliveira" Date: Thu, 28 Feb 2019 17:18:04 -0300 Subject: [PATCH 243/853] Add `runtimeClasspath` to the synthetic project script classpath So required `runtimeOnly` dependencies are also available at plugin application time. --- .../PrecompiledScriptPluginAccessorsTest.kt | 22 +++++++++++++++++++ .../DefaultPrecompiledScriptPluginsSupport.kt | 5 ++++- ...eneratePrecompiledScriptPluginAccessors.kt | 9 ++++++-- 3 files changed, 33 insertions(+), 3 deletions(-) diff --git a/subprojects/kotlin-dsl-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPluginAccessorsTest.kt b/subprojects/kotlin-dsl-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPluginAccessorsTest.kt index 2280a72fe67e7..23317ecf5b1b1 100644 --- a/subprojects/kotlin-dsl-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPluginAccessorsTest.kt +++ b/subprojects/kotlin-dsl-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPluginAccessorsTest.kt @@ -133,6 +133,28 @@ class PrecompiledScriptPluginAccessorsTest : AbstractPrecompiledScriptPluginTest ) } + @Test + fun `can use type-safe accessors for the Kotlin Gradle plugin extensions`() { + + withKotlinDslPlugin().appendText(""" + dependencies { + implementation(kotlin("gradle-plugin")) + } + """) + + withPrecompiledKotlinScript("kotlin-library.gradle.kts", """ + + plugins { kotlin("jvm") } + + kotlin { } + + tasks.compileKotlin { kotlinOptions { } } + + """) + + compileKotlin() + } + @Test fun `generated type-safe accessors are internal`() { diff --git a/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/DefaultPrecompiledScriptPluginsSupport.kt b/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/DefaultPrecompiledScriptPluginsSupport.kt index 5cd90927c8c84..34e324206f407 100644 --- a/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/DefaultPrecompiledScriptPluginsSupport.kt +++ b/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/DefaultPrecompiledScriptPluginsSupport.kt @@ -18,6 +18,7 @@ package org.gradle.kotlin.dsl.provider.plugins.precompiled import org.gradle.api.Project import org.gradle.api.Task import org.gradle.api.file.Directory +import org.gradle.api.file.FileCollection import org.gradle.api.file.SourceDirectorySet import org.gradle.api.initialization.Settings import org.gradle.api.invocation.Gradle @@ -210,6 +211,7 @@ fun Project.enableScriptCompilationOf( ) { dependsOn(compilePluginsBlocks) classPathFiles = compileClasspath + runtimeClassPathFiles = configurations["runtimeClasspath"] sourceCodeOutputDir.set(it) metadataOutputDir.set(generatedMetadata) compiledPluginsBlocksDir.set(compiledPluginsBlocks) @@ -261,7 +263,8 @@ fun Project.registerBuildScriptModelTask( private -fun Project.compileClasspath() = sourceSets["main"].compileClasspath +fun Project.compileClasspath(): FileCollection = + sourceSets["main"].compileClasspath private diff --git a/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/GeneratePrecompiledScriptPluginAccessors.kt b/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/GeneratePrecompiledScriptPluginAccessors.kt index c10042b340b46..be19b961234c7 100644 --- a/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/GeneratePrecompiledScriptPluginAccessors.kt +++ b/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/GeneratePrecompiledScriptPluginAccessors.kt @@ -17,12 +17,14 @@ package org.gradle.kotlin.dsl.provider.plugins.precompiled.tasks import org.gradle.api.Project +import org.gradle.api.file.FileCollection import org.gradle.api.internal.artifacts.dependencies.DefaultSelfResolvingDependency import org.gradle.api.internal.file.FileCollectionFactory import org.gradle.api.internal.file.FileCollectionInternal import org.gradle.api.internal.initialization.ScriptHandlerInternal import org.gradle.api.internal.project.ProjectInternal import org.gradle.api.tasks.CacheableTask +import org.gradle.api.tasks.Classpath import org.gradle.api.tasks.InputDirectory import org.gradle.api.tasks.InputFiles import org.gradle.api.tasks.Internal @@ -69,6 +71,9 @@ import java.io.File @CacheableTask open class GeneratePrecompiledScriptPluginAccessors : ClassPathSensitiveCodeGenerationTask() { + @get:Classpath + lateinit var runtimeClassPathFiles: FileCollection + @get:OutputDirectory var metadataOutputDir = directoryProperty() @@ -211,7 +216,7 @@ open class GeneratePrecompiledScriptPluginAccessors : ClassPathSensitiveCodeGene pluginGroupsPerRequests: Map> ): Map> { - val schemaBuilder = SyntheticProjectSchemaBuilder(temporaryDir, classPathFiles.files) + val schemaBuilder = SyntheticProjectSchemaBuilder(temporaryDir, (classPathFiles + runtimeClassPathFiles).files) return pluginGroupsPerRequests.flatMap { (uniquePluginRequests, scriptPlugins) -> try { val schema = schemaBuilder.schemaFor(uniquePluginRequests.plugins) @@ -267,7 +272,7 @@ open class GeneratePrecompiledScriptPluginAccessors : ClassPathSensitiveCodeGene internal -class SyntheticProjectSchemaBuilder(rootProjectDir: File, rootProjectClassPath: Set) { +class SyntheticProjectSchemaBuilder(rootProjectDir: File, rootProjectClassPath: Collection) { private val rootProject = buildRootProject(rootProjectDir, rootProjectClassPath) From 68612d5275efe8ccdd11334bddefa9073242f78f Mon Sep 17 00:00:00 2001 From: "Rodrigo B. de Oliveira" Date: Thu, 28 Feb 2019 18:26:34 -0300 Subject: [PATCH 244/853] Polish `buildSrc/build.gradle.kts` - Remove unused imports - Favour type-safe accessor over `configure { ... }` --- buildSrc/build.gradle.kts | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts index dcbf7834bcb39..f1eef3c11a818 100644 --- a/buildSrc/build.gradle.kts +++ b/buildSrc/build.gradle.kts @@ -14,12 +14,8 @@ * limitations under the License. */ -import org.gradle.plugins.ide.idea.model.IdeaModel - import org.gradle.kotlin.dsl.plugins.dsl.KotlinDslPlugin -import org.jetbrains.kotlin.gradle.tasks.KotlinCompile - import java.io.File import java.util.Properties @@ -41,7 +37,7 @@ subprojects { applyKotlinProjectConventions() } - configure { + java { sourceCompatibility = JavaVersion.VERSION_1_8 targetCompatibility = JavaVersion.VERSION_1_8 } From f9f23632e841a5c6f53aebc3e185512e6c8e3cf7 Mon Sep 17 00:00:00 2001 From: "Rodrigo B. de Oliveira" Date: Thu, 28 Feb 2019 18:27:42 -0300 Subject: [PATCH 245/853] Ignore KtLint failures until we can make it ignore generated sources Or until the generated sources comply with the conventions. --- buildSrc/build.gradle.kts | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts index f1eef3c11a818..bb6ce99c659c9 100644 --- a/buildSrc/build.gradle.kts +++ b/buildSrc/build.gradle.kts @@ -211,4 +211,15 @@ fun Project.applyKotlinProjectConventions() { experimentalWarning.set(false) } } + + configure { + // TODO:kotlin-dsl unignore KtLint failures + // we would like to only exclude the generated-sources from the + // verification but unfortunately the filter doesn't seem to + // have an effect so :/ + ignoreFailures.set(true) + filter { + exclude("**/generated-sources/**") + } + } } From 5d82b33b3dae20d48c3fb0b2860514aeda4b6ce2 Mon Sep 17 00:00:00 2001 From: Stefan Wolf Date: Thu, 28 Feb 2019 22:57:28 +0100 Subject: [PATCH 246/853] Fix performance regression introduced by using TypeToken to resolve type variables (#8650) Only use type token to resolve type variables if there are type variables to resolve. --- .../internal/reflect/JavaReflectionUtil.java | 103 ++++++++++++++++++ .../reflect/JavaReflectionUtilTest.groovy | 54 +++++++++ .../JavaReflectionUtilTestMethods.java | 35 ++++++ .../instantiation/AbstractClassGenerator.java | 3 +- 4 files changed, 194 insertions(+), 1 deletion(-) create mode 100644 subprojects/base-services/src/test/groovy/org/gradle/internal/reflect/JavaReflectionUtilTest.groovy create mode 100644 subprojects/base-services/src/test/groovy/org/gradle/internal/reflect/JavaReflectionUtilTestMethods.java diff --git a/subprojects/base-services/src/main/java/org/gradle/internal/reflect/JavaReflectionUtil.java b/subprojects/base-services/src/main/java/org/gradle/internal/reflect/JavaReflectionUtil.java index bef057e6af51d..113c08149085e 100644 --- a/subprojects/base-services/src/main/java/org/gradle/internal/reflect/JavaReflectionUtil.java +++ b/subprojects/base-services/src/main/java/org/gradle/internal/reflect/JavaReflectionUtil.java @@ -17,8 +17,16 @@ package org.gradle.internal.reflect; import org.gradle.internal.UncheckedException; +import org.gradle.util.CollectionUtils; import java.lang.reflect.Constructor; +import java.lang.reflect.GenericArrayType; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.lang.reflect.TypeVariable; +import java.lang.reflect.WildcardType; +import java.util.ArrayDeque; +import java.util.Queue; public class JavaReflectionUtil { @@ -55,4 +63,99 @@ public static T newInstance(Class c) { throw UncheckedException.throwAsUncheckedException(e); } } + + /** + * Checks if a type has a type variable which may require resolving. + */ + public static boolean hasTypeVariable(Type type) { + // do some checks up-front, so we avoid creating the queue in most cases + // Cases we want to handle: + // - List + // - Class + // - List> + // - Integer[] + // - ? extends BaseType + // - Class[] + if (doesNotHaveTypeVariable(type)) { + return false; + } + if (type instanceof TypeVariable) { + return true; + } + if (type instanceof ParameterizedType) { + ParameterizedType parameterizedType = (ParameterizedType) type; + boolean noTypeVariables = true; + for (Type actualTypeArgument : parameterizedType.getActualTypeArguments()) { + if (actualTypeArgument instanceof TypeVariable) { + return true; + } + noTypeVariables &= doesNotHaveTypeVariable(actualTypeArgument); + } + if (noTypeVariables) { + return false; + } + } + if (type instanceof GenericArrayType) { + GenericArrayType genericArrayType = (GenericArrayType) type; + if (genericArrayType.getGenericComponentType() instanceof TypeVariable) { + return true; + } + } + + // Type is more complicated, need to check everything. + Queue typesToInspect = new ArrayDeque(); + typesToInspect.add(type); + while (!typesToInspect.isEmpty()) { + Type typeToInspect = typesToInspect.remove(); + if (typeToInspect instanceof Class) { + continue; + } + if (typeToInspect instanceof TypeVariable) { + return true; + } + if (typeToInspect instanceof ParameterizedType) { + ParameterizedType parameterizedType = (ParameterizedType) typeToInspect; + CollectionUtils.addAll(typesToInspect, parameterizedType.getActualTypeArguments()); + } else if (typeToInspect instanceof GenericArrayType) { + GenericArrayType arrayType = (GenericArrayType) typeToInspect; + typesToInspect.add(arrayType.getGenericComponentType()); + } else if (typeToInspect instanceof WildcardType) { + WildcardType wildcardType = (WildcardType) typeToInspect; + CollectionUtils.addAll(typesToInspect, wildcardType.getLowerBounds()); + CollectionUtils.addAll(typesToInspect, wildcardType.getUpperBounds()); + } else { + // We don't know what the type is - let Guava take care of it. + return true; + } + } + return false; + } + + /** + * Quick check if a type does not have any type variables. + * + * Handled cases: + * - raw Class + * - Wildcard type with Class bounds, e.g. ? extends BaseType + */ + private static boolean doesNotHaveTypeVariable(Type type) { + if (type instanceof Class) { + return true; + } + if (type instanceof WildcardType) { + WildcardType wildcardType = (WildcardType) type; + for (Type lowerBound : wildcardType.getLowerBounds()) { + if (!(lowerBound instanceof Class)) { + return false; + } + } + for (Type upperBound : wildcardType.getUpperBounds()) { + if (!(upperBound instanceof Class)) { + return false; + } + } + return true; + } + return false; + } } diff --git a/subprojects/base-services/src/test/groovy/org/gradle/internal/reflect/JavaReflectionUtilTest.groovy b/subprojects/base-services/src/test/groovy/org/gradle/internal/reflect/JavaReflectionUtilTest.groovy new file mode 100644 index 0000000000000..de72c0e7032e8 --- /dev/null +++ b/subprojects/base-services/src/test/groovy/org/gradle/internal/reflect/JavaReflectionUtilTest.groovy @@ -0,0 +1,54 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.internal.reflect + +import com.google.common.reflect.TypeToken +import org.gradle.testing.internal.util.Specification +import spock.lang.Unroll + +import java.util.function.BiConsumer + +class JavaReflectionUtilTest extends Specification { + + @Unroll + def "#type has type variable: #hasTypeVariable"() { + expect: + JavaReflectionUtil.hasTypeVariable(type.getType()) == hasTypeVariable + + where: + type | hasTypeVariable + new TypeToken>() {} | false + new TypeToken>() {} | false + new TypeToken[]>() {} | false + TypeToken.of(String.class) | false + TypeToken.of(String[].class) | false + new TypeToken>>>() {} | false + new TypeToken>>() {} | false + new TypeToken>>() {} | false + new TypeToken, List>>() {} | false + genericReturnType("simpleGenericReturnType") | true + genericReturnType("encapsulatedTypeVariable") | true + genericReturnType("arrayTypeWithTypeVariable") | true + genericReturnType("complexTypeWithTypeVariable") | true + genericReturnType("anotherComplexTypeWithTypeVariable") | true + genericReturnType("complexTypeWithArrayTypeVariable") | true + } + + private static TypeToken genericReturnType(String methodName) { + return TypeToken.of(JavaReflectionUtilTestMethods.getDeclaredMethod(methodName).genericReturnType) + } +} diff --git a/subprojects/base-services/src/test/groovy/org/gradle/internal/reflect/JavaReflectionUtilTestMethods.java b/subprojects/base-services/src/test/groovy/org/gradle/internal/reflect/JavaReflectionUtilTestMethods.java new file mode 100644 index 0000000000000..197afaa1c0d07 --- /dev/null +++ b/subprojects/base-services/src/test/groovy/org/gradle/internal/reflect/JavaReflectionUtilTestMethods.java @@ -0,0 +1,35 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.internal.reflect; + +import java.util.Collection; +import java.util.List; +import java.util.function.BiConsumer; + +public interface JavaReflectionUtilTestMethods { + T simpleGenericReturnType(); + + List encapsulatedTypeVariable(); + + T[] arrayTypeWithTypeVariable(); + + List>[]> complexTypeWithTypeVariable(); + + List>, ? extends List>[]> anotherComplexTypeWithTypeVariable(); + + List>, ? extends List>> complexTypeWithArrayTypeVariable(); +} diff --git a/subprojects/model-core/src/main/java/org/gradle/internal/instantiation/AbstractClassGenerator.java b/subprojects/model-core/src/main/java/org/gradle/internal/instantiation/AbstractClassGenerator.java index 705ded9e388a5..4c74fb34f43e4 100644 --- a/subprojects/model-core/src/main/java/org/gradle/internal/instantiation/AbstractClassGenerator.java +++ b/subprojects/model-core/src/main/java/org/gradle/internal/instantiation/AbstractClassGenerator.java @@ -43,6 +43,7 @@ import org.gradle.internal.reflect.ClassInspector; import org.gradle.internal.reflect.Instantiator; import org.gradle.internal.reflect.JavaPropertyReflectionUtil; +import org.gradle.internal.reflect.JavaReflectionUtil; import org.gradle.internal.reflect.MethodSet; import org.gradle.internal.reflect.PropertyAccessorType; import org.gradle.internal.reflect.PropertyDetails; @@ -453,7 +454,7 @@ public ClassMetadata(Class type) { */ public MethodMetadata resolveTypeVariables(Method method) { Type returnType = method.getGenericReturnType(); - Type resolvedReturnType = returnType instanceof Class ? returnType : TypeToken.of(type).method(method).getReturnType().getType(); + Type resolvedReturnType = JavaReflectionUtil.hasTypeVariable(returnType) ? TypeToken.of(type).method(method).getReturnType().getType() : returnType; return new MethodMetadata(method, resolvedReturnType); } From 32d19ef8207efb19f6525f5b65c689c5ce205539 Mon Sep 17 00:00:00 2001 From: "Rodrigo B. de Oliveira" Date: Thu, 28 Feb 2019 19:08:46 -0300 Subject: [PATCH 247/853] Suppress more warnings in generated code --- .../kotlin/org/gradle/kotlin/dsl/codegen/SourceFileHeader.kt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/codegen/SourceFileHeader.kt b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/codegen/SourceFileHeader.kt index 709c7bc61a0c7..1af04699c3efb 100644 --- a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/codegen/SourceFileHeader.kt +++ b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/codegen/SourceFileHeader.kt @@ -30,6 +30,8 @@ fun fileHeaderFor(packageName: String) = "unused", "nothing_to_inline", "useless_cast", + "unchecked_cast", + "extension_shadowed_by_member", "redundant_projection", "RemoveRedundantBackticks", "ObjectPropertyName" From e01b867ff3dc2be50605a063c07c78b05edf6bc8 Mon Sep 17 00:00:00 2001 From: "Rodrigo B. de Oliveira" Date: Thu, 28 Feb 2019 19:09:13 -0300 Subject: [PATCH 248/853] Expose result from `compileKotlin` --- .../kotlin/dsl/fixtures/AbstractKotlinIntegrationTest.kt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/subprojects/kotlin-dsl-test-fixtures/src/main/kotlin/org/gradle/kotlin/dsl/fixtures/AbstractKotlinIntegrationTest.kt b/subprojects/kotlin-dsl-test-fixtures/src/main/kotlin/org/gradle/kotlin/dsl/fixtures/AbstractKotlinIntegrationTest.kt index 8660281dc8c24..ea12a90742d19 100644 --- a/subprojects/kotlin-dsl-test-fixtures/src/main/kotlin/org/gradle/kotlin/dsl/fixtures/AbstractKotlinIntegrationTest.kt +++ b/subprojects/kotlin-dsl-test-fixtures/src/main/kotlin/org/gradle/kotlin/dsl/fixtures/AbstractKotlinIntegrationTest.kt @@ -212,9 +212,8 @@ abstract class AbstractKotlinIntegrationTest : AbstractIntegrationTest() { GradleInstallation.Local(distribution.gradleHomeDir) protected - fun compileKotlin(taskName: String = "classes") { + fun compileKotlin(taskName: String = "classes"): ExecutionResult = build(taskName).assertTaskExecuted(":compileKotlin") - } protected fun withDeepThoughtJar(named: String): File = From 6f43d2dcce03b8169525bbb4456a3c043aa88199 Mon Sep 17 00:00:00 2001 From: "Rodrigo B. de Oliveira" Date: Thu, 28 Feb 2019 19:13:48 -0300 Subject: [PATCH 249/853] Polish `PrecompiledScriptPluginIntegrationTest` - Reuse $repositoriesBlock - Reuse withPrecompiledKotlinScript --- .../integration/PrecompiledScriptPluginIntegrationTest.kt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/subprojects/kotlin-dsl-integ-tests/src/integTest/kotlin/org/gradle/kotlin/dsl/integration/PrecompiledScriptPluginIntegrationTest.kt b/subprojects/kotlin-dsl-integ-tests/src/integTest/kotlin/org/gradle/kotlin/dsl/integration/PrecompiledScriptPluginIntegrationTest.kt index 541994d305b3e..82ecb13cd272f 100644 --- a/subprojects/kotlin-dsl-integ-tests/src/integTest/kotlin/org/gradle/kotlin/dsl/integration/PrecompiledScriptPluginIntegrationTest.kt +++ b/subprojects/kotlin-dsl-integ-tests/src/integTest/kotlin/org/gradle/kotlin/dsl/integration/PrecompiledScriptPluginIntegrationTest.kt @@ -20,11 +20,11 @@ class PrecompiledScriptPluginIntegrationTest : AbstractPluginIntegrationTest() { id("org.gradle.kotlin-dsl.ktlint-convention") version "0.2.3" } - repositories { jcenter() } + $repositoriesBlock """) - withFile("src/main/kotlin/plugin-without-package.gradle.kts", "\n") - withFile("src/main/kotlin/plugins/plugin-with-package.gradle.kts", """ + withPrecompiledKotlinScript("plugin-without-package.gradle.kts", "") + withPrecompiledKotlinScript("plugins/plugin-with-package.gradle.kts", """ package plugins """) From 484f13d87852b030a002909ea18cff1cf07e9c22 Mon Sep 17 00:00:00 2001 From: Adam Murdoch Date: Wed, 27 Feb 2019 18:53:41 +1100 Subject: [PATCH 250/853] Remove some assumptions about which annotations are used for injecting services from the property inspection infrastructure, and instead have an injection scheme describe the annotations it supports to the property inspection scheme. Also remove some caching from the factories of these schemes, as the schemes are all global services now. --- .../properties/InspectionSchemeFactory.java | 57 ++++++++----------- .../internal/tasks/properties/TypeScheme.java | 3 + .../PropertyAnnotationHandler.java | 2 + .../scopes/ExecutionGlobalServices.java | 7 +-- .../DefaultTypeMetadataStoreTest.groovy | 4 +- .../InspectionSchemeFactoryTest.groovy | 41 ++++++++++--- ...pendencyManagementGlobalScopeServices.java | 6 +- .../InputArtifactAnnotationHandler.java | 5 -- ...ArtifactDependenciesAnnotationHandler.java | 5 -- .../instantiation/AbstractClassGenerator.java | 4 +- .../DefaultInjectAnnotationHandler.java | 37 ------------ .../DefaultInstantiationScheme.java | 12 +++- .../DefaultInstantiatorFactory.java | 47 ++++++--------- .../InjectAnnotationHandler.java | 2 +- .../instantiation/InstantiationScheme.java | 8 +++ .../instantiation/InstantiatorFactory.java | 2 +- ...edClassGeneratorInjectDecoratedTest.groovy | 2 +- .../DefaultInstantiatorFactoryTest.groovy | 26 +++------ 18 files changed, 118 insertions(+), 152 deletions(-) delete mode 100644 subprojects/model-core/src/main/java/org/gradle/internal/instantiation/DefaultInjectAnnotationHandler.java diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/InspectionSchemeFactory.java b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/InspectionSchemeFactory.java index 09bb149c942c6..c1efc66bcd2b9 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/InspectionSchemeFactory.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/InspectionSchemeFactory.java @@ -16,17 +16,14 @@ package org.gradle.api.internal.tasks.properties; -import com.google.common.cache.CacheBuilder; -import com.google.common.cache.CacheLoader; -import com.google.common.cache.LoadingCache; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; -import com.google.common.util.concurrent.UncheckedExecutionException; +import org.gradle.api.internal.tasks.properties.annotations.NoOpPropertyAnnotationHandler; import org.gradle.api.internal.tasks.properties.annotations.PropertyAnnotationHandler; import org.gradle.api.internal.tasks.properties.annotations.TypeAnnotationHandler; import org.gradle.cache.internal.CrossBuildInMemoryCacheFactory; -import org.gradle.internal.UncheckedException; +import org.gradle.internal.instantiation.InstantiationScheme; import java.lang.annotation.Annotation; import java.util.Collection; @@ -38,28 +35,6 @@ public class InspectionSchemeFactory { private final Map, PropertyAnnotationHandler> allKnownPropertyHandlers; private final ImmutableList allKnownTypeHandlers; private final CrossBuildInMemoryCacheFactory cacheFactory; - // Assume for now that the annotations are all part of Gradle core and are never unloaded, so use strong references to the annotation types - private final LoadingCache>, InspectionScheme> schemes = CacheBuilder.newBuilder().build(new CacheLoader>, InspectionScheme>() { - @Override - public InspectionScheme load(Set> annotations) { - ImmutableList.Builder builder = ImmutableList.builderWithExpectedSize(annotations.size()); - for (Class annotation : annotations) { - PropertyAnnotationHandler handler = allKnownPropertyHandlers.get(annotation); - if (handler == null) { - throw new IllegalArgumentException(String.format("Annotation @%s is not a registered annotation.", annotation.getSimpleName())); - } - builder.add(handler); - } - ImmutableList annotationHandlers = builder.build(); - ImmutableSet.Builder> otherAnnotations = ImmutableSet.builderWithExpectedSize(allKnownPropertyHandlers.size() - annotations.size()); - for (Class annotation : allKnownPropertyHandlers.keySet()) { - if (!annotations.contains(annotation)) { - otherAnnotations.add(annotation); - } - } - return new InspectionSchemeImpl(annotationHandlers, otherAnnotations.build(), allKnownTypeHandlers, cacheFactory); - } - }); public InspectionSchemeFactory(List allKnownPropertyHandlers, List allKnownTypeHandlers, CrossBuildInMemoryCacheFactory cacheFactory) { ImmutableMap.Builder, PropertyAnnotationHandler> builder = ImmutableMap.builder(); @@ -72,14 +47,30 @@ public InspectionSchemeFactory(List allKnow } /** - * Creates an {@link InspectionScheme} with the given annotations enabled. + * Creates a new {@link InspectionScheme} with the given annotations enabled and using the given instantiation scheme. */ - public InspectionScheme inspectionScheme(Collection> annotations) { - try { - return schemes.getUnchecked(ImmutableSet.copyOf(annotations)); - } catch (UncheckedExecutionException e) { - throw UncheckedException.throwAsUncheckedException(e.getCause()); + public InspectionScheme inspectionScheme(Collection> annotations, InstantiationScheme instantiationScheme) { + ImmutableList.Builder builder = ImmutableList.builderWithExpectedSize(annotations.size()); + for (Class annotation : annotations) { + PropertyAnnotationHandler handler = allKnownPropertyHandlers.get(annotation); + if (handler == null) { + throw new IllegalArgumentException(String.format("Annotation @%s is not a registered annotation.", annotation.getSimpleName())); + } + builder.add(handler); + } + for (Class annotation : instantiationScheme.getInjectionAnnotations()) { + if (!annotations.contains(annotation)) { + builder.add(new NoOpPropertyAnnotationHandler(annotation)); + } + } + ImmutableList annotationHandlers = builder.build(); + ImmutableSet.Builder> otherAnnotations = ImmutableSet.builderWithExpectedSize(allKnownPropertyHandlers.size() - annotations.size()); + for (Class annotation : allKnownPropertyHandlers.keySet()) { + if (!annotations.contains(annotation)) { + otherAnnotations.add(annotation); + } } + return new InspectionSchemeImpl(annotationHandlers, otherAnnotations.build(), allKnownTypeHandlers, cacheFactory); } private static class InspectionSchemeImpl implements InspectionScheme { diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/TypeScheme.java b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/TypeScheme.java index 0745c37eb1ce1..ad65ffc636902 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/TypeScheme.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/TypeScheme.java @@ -16,6 +16,9 @@ package org.gradle.api.internal.tasks.properties; +/** + * Metadata about a particular set of types. + */ public interface TypeScheme { TypeMetadataStore getMetadataStore(); diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/annotations/PropertyAnnotationHandler.java b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/annotations/PropertyAnnotationHandler.java index ae56c397fd1f9..71dc0b2f6b520 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/annotations/PropertyAnnotationHandler.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/annotations/PropertyAnnotationHandler.java @@ -25,6 +25,8 @@ /** * Handles validation, dependency handling, and skipping for a property marked with a given annotation. + * + *

    Each handler must be registered as a global service.

    */ public interface PropertyAnnotationHandler { /** diff --git a/subprojects/core/src/main/java/org/gradle/internal/service/scopes/ExecutionGlobalServices.java b/subprojects/core/src/main/java/org/gradle/internal/service/scopes/ExecutionGlobalServices.java index 31e070acf6231..0ce4b84e5f566 100644 --- a/subprojects/core/src/main/java/org/gradle/internal/service/scopes/ExecutionGlobalServices.java +++ b/subprojects/core/src/main/java/org/gradle/internal/service/scopes/ExecutionGlobalServices.java @@ -58,7 +58,6 @@ import org.gradle.internal.instantiation.InstantiationScheme; import org.gradle.internal.instantiation.InstantiatorFactory; -import javax.inject.Inject; import java.util.List; public class ExecutionGlobalServices { @@ -68,7 +67,7 @@ InspectionSchemeFactory createInspectionSchemeFactory(List> UNPROCESSED_PROPERTY_TYPE_ANNOTATIONS = [ - Console, Internal, Inject, ReplacedBy + Console, Internal, ReplacedBy ] @Shared GroovyClassLoader groovyClassLoader @@ -290,7 +290,7 @@ class DefaultTypeMetadataStoreTest extends Specification { static class Unannotated extends DefaultTask { String bad1 File bad2 - @Inject String ignore1 + @Console String ignore1 @Input String ignore2 } diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/properties/InspectionSchemeFactoryTest.groovy b/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/properties/InspectionSchemeFactoryTest.groovy index 491cedbbec62e..e3fe18e17075d 100644 --- a/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/properties/InspectionSchemeFactoryTest.groovy +++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/properties/InspectionSchemeFactoryTest.groovy @@ -16,9 +16,10 @@ package org.gradle.api.internal.tasks.properties - +import org.gradle.api.internal.tasks.properties.annotations.NoOpPropertyAnnotationHandler import org.gradle.api.internal.tasks.properties.annotations.PropertyAnnotationHandler import org.gradle.cache.internal.TestCrossBuildInMemoryCacheFactory +import org.gradle.internal.instantiation.InstantiationScheme import spock.lang.Specification import java.lang.annotation.Retention @@ -29,23 +30,40 @@ class InspectionSchemeFactoryTest extends Specification { def handler2 = handler(Thing2) def factory = new InspectionSchemeFactory([handler1, handler2], [], new TestCrossBuildInMemoryCacheFactory()) - def "creates inspection scheme"() { - def scheme = factory.inspectionScheme([Thing1, Thing2]) + def "creates inspection scheme that understands given property annotations and injection annotations"() { + def instantiationScheme = Stub(InstantiationScheme) + instantiationScheme.injectionAnnotations >> [InjectThing] + def scheme = factory.inspectionScheme([Thing1, Thing2], instantiationScheme) expect: def metadata = scheme.metadataStore.getTypeMetadata(AnnotatedBean) def problems = [] metadata.collectValidationFailures(null, new DefaultParameterValidationContext(problems)) problems.empty - metadata.propertiesMetadata.size() == 2 + metadata.propertiesMetadata.size() == 3 + + def properties = metadata.propertiesMetadata.groupBy { it.propertyName } + metadata.getAnnotationHandlerFor(properties.prop1) == handler1 + metadata.getAnnotationHandlerFor(properties.prop2) == handler2 + metadata.getAnnotationHandlerFor(properties.prop3) instanceof NoOpPropertyAnnotationHandler } - def "reuses inspection schemes"() { - def scheme = factory.inspectionScheme([Thing1, Thing2]) + def "annotation can be used for property annotation and injection annotations"() { + def instantiationScheme = Stub(InstantiationScheme) + instantiationScheme.injectionAnnotations >> [Thing2, InjectThing] + def scheme = factory.inspectionScheme([Thing1, Thing2], instantiationScheme) expect: - factory.inspectionScheme([Thing2, Thing1]).is(scheme) - factory.inspectionScheme([Thing2]) != scheme + def metadata = scheme.metadataStore.getTypeMetadata(AnnotatedBean) + def problems = [] + metadata.collectValidationFailures(null, new DefaultParameterValidationContext(problems)) + problems.empty + metadata.propertiesMetadata.size() == 3 + + def properties = metadata.propertiesMetadata.groupBy { it.propertyName } + metadata.getAnnotationHandlerFor(properties.prop1) == handler1 + metadata.getAnnotationHandlerFor(properties.prop2) == handler2 + metadata.getAnnotationHandlerFor(properties.prop3) instanceof NoOpPropertyAnnotationHandler } def handler(Class annotation) { @@ -61,6 +79,9 @@ class AnnotatedBean { @Thing2 String prop2 + + @InjectThing + String prop3 } @Retention(RetentionPolicy.RUNTIME) @@ -70,3 +91,7 @@ class AnnotatedBean { @Retention(RetentionPolicy.RUNTIME) @interface Thing2 { } + +@Retention(RetentionPolicy.RUNTIME) +@interface InjectThing { +} diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/DependencyManagementGlobalScopeServices.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/DependencyManagementGlobalScopeServices.java index 9647a65c2b347..f5ade7a8e7b18 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/DependencyManagementGlobalScopeServices.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/DependencyManagementGlobalScopeServices.java @@ -59,8 +59,6 @@ import org.gradle.internal.resource.local.FileResourceRepository; import org.gradle.internal.resource.transport.file.FileConnectorFactory; -import javax.inject.Inject; - class DependencyManagementGlobalScopeServices { FileResourceRepository createFileResourceRepository(FileSystem fileSystem) { return new FileResourceConnector(fileSystem); @@ -124,14 +122,14 @@ InputArtifactDependenciesAnnotationHandler createInputArtifactDependenciesAnnota ArtifactTransformParameterScheme createArtifactTransformParameterScheme(InspectionSchemeFactory inspectionSchemeFactory, InstantiatorFactory instantiatorFactory) { // TODO - should decorate InstantiationScheme instantiationScheme = instantiatorFactory.injectScheme(); - InspectionScheme inspectionScheme = inspectionSchemeFactory.inspectionScheme(ImmutableSet.of(Input.class, InputFile.class, InputFiles.class, InputDirectory.class, Classpath.class, CompileClasspath.class, Inject.class, Console.class, Internal.class)); + InspectionScheme inspectionScheme = inspectionSchemeFactory.inspectionScheme(ImmutableSet.of(Input.class, InputFile.class, InputFiles.class, InputDirectory.class, Classpath.class, CompileClasspath.class, Console.class, Internal.class), instantiationScheme); return new ArtifactTransformParameterScheme(instantiationScheme, inspectionScheme); } ArtifactTransformActionScheme createArtifactTransformActionScheme(InspectionSchemeFactory inspectionSchemeFactory, InstantiatorFactory instantiatorFactory) { InstantiationScheme instantiationScheme = instantiatorFactory.injectScheme(ImmutableSet.of(InputArtifact.class, InputArtifactDependencies.class)); + InspectionScheme inspectionScheme = inspectionSchemeFactory.inspectionScheme(ImmutableSet.of(InputArtifact.class, InputArtifactDependencies.class, Classpath.class, CompileClasspath.class), instantiationScheme); InstantiationScheme legacyInstantiationScheme = instantiatorFactory.injectScheme(); - InspectionScheme inspectionScheme = inspectionSchemeFactory.inspectionScheme(ImmutableSet.of(InputArtifact.class, InputArtifactDependencies.class, Inject.class, Classpath.class, CompileClasspath.class)); return new ArtifactTransformActionScheme(instantiationScheme, inspectionScheme, legacyInstantiationScheme); } } diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/InputArtifactAnnotationHandler.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/InputArtifactAnnotationHandler.java index b1afbc7d0b652..4df6db7de48bc 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/InputArtifactAnnotationHandler.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/InputArtifactAnnotationHandler.java @@ -29,11 +29,6 @@ public Class getAnnotationType() { return InputArtifact.class; } - @Override - public Class getAnnotation() { - return InputArtifact.class; - } - @Override protected InputFilePropertyType getFilePropertyType() { return InputFilePropertyType.FILE; diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/InputArtifactDependenciesAnnotationHandler.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/InputArtifactDependenciesAnnotationHandler.java index 82715f2075f5b..7a9c2015aa779 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/InputArtifactDependenciesAnnotationHandler.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/InputArtifactDependenciesAnnotationHandler.java @@ -29,11 +29,6 @@ public Class getAnnotationType() { return InputArtifactDependencies.class; } - @Override - public Class getAnnotation() { - return InputArtifactDependencies.class; - } - @Override protected InputFilePropertyType getFilePropertyType() { return InputFilePropertyType.FILES; diff --git a/subprojects/model-core/src/main/java/org/gradle/internal/instantiation/AbstractClassGenerator.java b/subprojects/model-core/src/main/java/org/gradle/internal/instantiation/AbstractClassGenerator.java index 4c74fb34f43e4..c6e211bf9cb9e 100644 --- a/subprojects/model-core/src/main/java/org/gradle/internal/instantiation/AbstractClassGenerator.java +++ b/subprojects/model-core/src/main/java/org/gradle/internal/instantiation/AbstractClassGenerator.java @@ -95,8 +95,8 @@ public AbstractClassGenerator(Collection allK this.enabledAnnotations = ImmutableSet.copyOf(enabledAnnotations); ImmutableSet.Builder> builder = ImmutableSet.builder(); for (InjectAnnotationHandler handler : allKnownAnnotations) { - if (!enabledAnnotations.contains(handler.getAnnotation())) { - builder.add(handler.getAnnotation()); + if (!enabledAnnotations.contains(handler.getAnnotationType())) { + builder.add(handler.getAnnotationType()); } } this.disabledAnnotations = builder.build(); diff --git a/subprojects/model-core/src/main/java/org/gradle/internal/instantiation/DefaultInjectAnnotationHandler.java b/subprojects/model-core/src/main/java/org/gradle/internal/instantiation/DefaultInjectAnnotationHandler.java deleted file mode 100644 index 3768b7be1ba29..0000000000000 --- a/subprojects/model-core/src/main/java/org/gradle/internal/instantiation/DefaultInjectAnnotationHandler.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright 2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.gradle.internal.instantiation; - -import java.lang.annotation.Annotation; - -public class DefaultInjectAnnotationHandler implements InjectAnnotationHandler { - private final Class annotation; - - public DefaultInjectAnnotationHandler(Class annotation) { - this.annotation = annotation; - } - - @Override - public String toString() { - return "handler for @" + annotation.getSimpleName(); - } - - @Override - public Class getAnnotation() { - return annotation; - } -} diff --git a/subprojects/model-core/src/main/java/org/gradle/internal/instantiation/DefaultInstantiationScheme.java b/subprojects/model-core/src/main/java/org/gradle/internal/instantiation/DefaultInstantiationScheme.java index 68fba5ab02fc7..92bee7eda6986 100644 --- a/subprojects/model-core/src/main/java/org/gradle/internal/instantiation/DefaultInstantiationScheme.java +++ b/subprojects/model-core/src/main/java/org/gradle/internal/instantiation/DefaultInstantiationScheme.java @@ -20,15 +20,25 @@ import org.gradle.internal.service.ServiceLookup; import org.gradle.internal.service.ServiceRegistry; +import java.lang.annotation.Annotation; +import java.util.Set; + class DefaultInstantiationScheme implements InstantiationScheme { private final DependencyInjectingInstantiator instantiator; private final ConstructorSelector constructorSelector; + private final Set> injectionAnnotations; - public DefaultInstantiationScheme(ConstructorSelector constructorSelector, ServiceRegistry defaultServices) { + public DefaultInstantiationScheme(ConstructorSelector constructorSelector, ServiceRegistry defaultServices, Set> injectionAnnotations) { this.constructorSelector = constructorSelector; + this.injectionAnnotations = injectionAnnotations; this.instantiator = new DependencyInjectingInstantiator(constructorSelector, defaultServices); } + @Override + public Set> getInjectionAnnotations() { + return injectionAnnotations; + } + @Override public InstanceFactory forType(Class type) { return instantiator.factoryFor(type); diff --git a/subprojects/model-core/src/main/java/org/gradle/internal/instantiation/DefaultInstantiatorFactory.java b/subprojects/model-core/src/main/java/org/gradle/internal/instantiation/DefaultInstantiatorFactory.java index 5378b1f269cd5..f99b1647cc334 100644 --- a/subprojects/model-core/src/main/java/org/gradle/internal/instantiation/DefaultInstantiatorFactory.java +++ b/subprojects/model-core/src/main/java/org/gradle/internal/instantiation/DefaultInstantiatorFactory.java @@ -16,22 +16,17 @@ package org.gradle.internal.instantiation; -import com.google.common.cache.CacheBuilder; -import com.google.common.cache.CacheLoader; -import com.google.common.cache.LoadingCache; import com.google.common.collect.ImmutableSet; -import com.google.common.util.concurrent.UncheckedExecutionException; import org.gradle.cache.internal.CrossBuildInMemoryCacheFactory; -import org.gradle.internal.UncheckedException; import org.gradle.internal.reflect.Instantiator; import org.gradle.internal.service.DefaultServiceRegistry; import org.gradle.internal.service.ServiceLookup; import org.gradle.internal.service.ServiceRegistry; +import javax.inject.Inject; import java.lang.annotation.Annotation; import java.util.Collection; import java.util.List; -import java.util.Set; public class DefaultInstantiatorFactory implements InstantiatorFactory { private final ServiceRegistry noServices = new DefaultServiceRegistry(); @@ -42,19 +37,6 @@ public class DefaultInstantiatorFactory implements InstantiatorFactory { private final DefaultInstantiationScheme decoratingScheme; private final DefaultInstantiationScheme decoratingLenientScheme; - // Assume for now that the annotations are all part of Gradle core and are never unloaded, so use strong references to the annotation types - private final LoadingCache>, InstantiationScheme> schemes = CacheBuilder.newBuilder().build(new CacheLoader>, InstantiationScheme>() { - @Override - public InstantiationScheme load(Set> annotations) { - for (Class annotation : annotations) { - assertKnownAnnotation(annotation); - } - ClassGenerator classGenerator = AsmBackedClassGenerator.injectOnly(annotationHandlers, annotations); - Jsr330ConstructorSelector constructorSelector = new Jsr330ConstructorSelector(classGenerator, cacheFactory.newClassCache()); - return new DefaultInstantiationScheme(constructorSelector, noServices); - } - }); - public DefaultInstantiatorFactory(CrossBuildInMemoryCacheFactory cacheFactory, List annotationHandlers) { this.cacheFactory = cacheFactory; this.annotationHandlers = annotationHandlers; @@ -64,11 +46,10 @@ public DefaultInstantiatorFactory(CrossBuildInMemoryCacheFactory cacheFactory, L ConstructorSelector decoratedJsr330Selector = new Jsr330ConstructorSelector(decorated, cacheFactory.newClassCache()); ConstructorSelector injectOnlyLenientSelector = new ParamsMatchingConstructorSelector(injectOnly, cacheFactory.newClassCache()); ConstructorSelector decoratedLenientSelector = new ParamsMatchingConstructorSelector(decorated, cacheFactory.newClassCache()); - injectOnlyScheme = new DefaultInstantiationScheme(injectOnlyJsr330Selector, noServices); - injectOnlyLenientScheme = new DefaultInstantiationScheme(injectOnlyLenientSelector, noServices); - decoratingScheme = new DefaultInstantiationScheme(decoratedJsr330Selector, noServices); - decoratingLenientScheme = new DefaultInstantiationScheme(decoratedLenientSelector, noServices); - schemes.put(ImmutableSet.of(), injectOnlyScheme); + injectOnlyScheme = new DefaultInstantiationScheme(injectOnlyJsr330Selector, noServices, ImmutableSet.of(Inject.class)); + injectOnlyLenientScheme = new DefaultInstantiationScheme(injectOnlyLenientSelector, noServices, ImmutableSet.of(Inject.class)); + decoratingScheme = new DefaultInstantiationScheme(decoratedJsr330Selector, noServices, ImmutableSet.of(Inject.class)); + decoratingLenientScheme = new DefaultInstantiationScheme(decoratedLenientSelector, noServices, ImmutableSet.of(Inject.class)); } @Override @@ -88,11 +69,19 @@ public InstantiationScheme injectScheme() { @Override public InstantiationScheme injectScheme(Collection> injectAnnotations) { - try { - return schemes.getUnchecked(ImmutableSet.copyOf(injectAnnotations)); - } catch (UncheckedExecutionException e) { - throw UncheckedException.throwAsUncheckedException(e.getCause()); + if (injectAnnotations.isEmpty()) { + return injectOnlyScheme; + } + + for (Class annotation : injectAnnotations) { + assertKnownAnnotation(annotation); } + ClassGenerator classGenerator = AsmBackedClassGenerator.injectOnly(annotationHandlers, ImmutableSet.copyOf(injectAnnotations)); + Jsr330ConstructorSelector constructorSelector = new Jsr330ConstructorSelector(classGenerator, cacheFactory.newClassCache()); + ImmutableSet.Builder> builder = ImmutableSet.builderWithExpectedSize(injectAnnotations.size() + 1); + builder.addAll(injectAnnotations); + builder.add(Inject.class); + return new DefaultInstantiationScheme(constructorSelector, noServices, builder.build()); } @Override @@ -127,7 +116,7 @@ public Instantiator injectAndDecorate(ServiceLookup services) { private void assertKnownAnnotation(Class annotation) { for (InjectAnnotationHandler annotationHandler : annotationHandlers) { - if (annotationHandler.getAnnotation().equals(annotation)) { + if (annotationHandler.getAnnotationType().equals(annotation)) { return; } } diff --git a/subprojects/model-core/src/main/java/org/gradle/internal/instantiation/InjectAnnotationHandler.java b/subprojects/model-core/src/main/java/org/gradle/internal/instantiation/InjectAnnotationHandler.java index 98dd663af76c8..78b57916343b1 100644 --- a/subprojects/model-core/src/main/java/org/gradle/internal/instantiation/InjectAnnotationHandler.java +++ b/subprojects/model-core/src/main/java/org/gradle/internal/instantiation/InjectAnnotationHandler.java @@ -24,5 +24,5 @@ *

    Implementations must be registered as global scoped services.

    */ public interface InjectAnnotationHandler { - Class getAnnotation(); + Class getAnnotationType(); } diff --git a/subprojects/model-core/src/main/java/org/gradle/internal/instantiation/InstantiationScheme.java b/subprojects/model-core/src/main/java/org/gradle/internal/instantiation/InstantiationScheme.java index 50afe8be77769..66af72caba077 100644 --- a/subprojects/model-core/src/main/java/org/gradle/internal/instantiation/InstantiationScheme.java +++ b/subprojects/model-core/src/main/java/org/gradle/internal/instantiation/InstantiationScheme.java @@ -19,12 +19,20 @@ import org.gradle.internal.reflect.Instantiator; import org.gradle.internal.service.ServiceLookup; +import java.lang.annotation.Annotation; +import java.util.Set; + /** * A scheme, or strategy, for creating objects. * *

    Implementations are provided by a {@link InstantiatorFactory}.

    */ public interface InstantiationScheme { + /** + * Returns the set of annotations that are used by this instantiation scheme for dependency injection. + */ + Set> getInjectionAnnotations(); + /** * Creates a new {@link InstanceFactory} for the given type, which creates instances based on the configuration of this scheme. */ diff --git a/subprojects/model-core/src/main/java/org/gradle/internal/instantiation/InstantiatorFactory.java b/subprojects/model-core/src/main/java/org/gradle/internal/instantiation/InstantiatorFactory.java index 6ef5642fcbc49..6765775e78b13 100644 --- a/subprojects/model-core/src/main/java/org/gradle/internal/instantiation/InstantiatorFactory.java +++ b/subprojects/model-core/src/main/java/org/gradle/internal/instantiation/InstantiatorFactory.java @@ -52,7 +52,7 @@ public interface InstantiatorFactory { InstantiationScheme injectScheme(); /** - * Create an {@link InstantiationScheme} that can inject services and user provided values into the instances it creates, but does not decorate the instances. Supports using the {@link javax.inject.Inject} annotation plus the given custom inject annotations. Is not lenient. + * Create a new {@link InstantiationScheme} that can inject services and user provided values into the instances it creates, but does not decorate the instances. Supports using the {@link javax.inject.Inject} annotation plus the given custom inject annotations. Is not lenient. * * @param injectAnnotations Zero or more annotations that mark properties whose value will be injected on creation. Each annotation must be known to this factory via a {@link InjectAnnotationHandler}. */ diff --git a/subprojects/model-core/src/test/groovy/org/gradle/internal/instantiation/AsmBackedClassGeneratorInjectDecoratedTest.groovy b/subprojects/model-core/src/test/groovy/org/gradle/internal/instantiation/AsmBackedClassGeneratorInjectDecoratedTest.groovy index d500da5fa4e48..998309a7c193e 100644 --- a/subprojects/model-core/src/test/groovy/org/gradle/internal/instantiation/AsmBackedClassGeneratorInjectDecoratedTest.groovy +++ b/subprojects/model-core/src/test/groovy/org/gradle/internal/instantiation/AsmBackedClassGeneratorInjectDecoratedTest.groovy @@ -377,7 +377,7 @@ class AsmBackedClassGeneratorInjectDecoratedTest extends AbstractClassGeneratorS class CustomAnnotationHandler implements InjectAnnotationHandler { @Override - Class getAnnotation() { + Class getAnnotationType() { return CustomInject } } diff --git a/subprojects/model-core/src/test/groovy/org/gradle/internal/instantiation/DefaultInstantiatorFactoryTest.groovy b/subprojects/model-core/src/test/groovy/org/gradle/internal/instantiation/DefaultInstantiatorFactoryTest.groovy index f8493ee7b8366..15337456bb377 100644 --- a/subprojects/model-core/src/test/groovy/org/gradle/internal/instantiation/DefaultInstantiatorFactoryTest.groovy +++ b/subprojects/model-core/src/test/groovy/org/gradle/internal/instantiation/DefaultInstantiatorFactoryTest.groovy @@ -19,6 +19,7 @@ package org.gradle.internal.instantiation import org.gradle.cache.internal.TestCrossBuildInMemoryCacheFactory import spock.lang.Specification +import javax.inject.Inject import java.lang.annotation.Annotation import java.lang.annotation.Retention import java.lang.annotation.RetentionPolicy @@ -27,18 +28,9 @@ import java.lang.annotation.RetentionPolicy class DefaultInstantiatorFactoryTest extends Specification { def instantiatorFactory = new DefaultInstantiatorFactory(new TestCrossBuildInMemoryCacheFactory(), [handler(Annotation1), handler(Annotation2)]) - def "caches InstantiationScheme instances"() { - def classes = [Annotation1] - + def "creates scheme with requested annotations"() { expect: - instantiatorFactory.injectScheme(classes).is(instantiatorFactory.injectScheme(classes)) - instantiatorFactory.injectScheme(classes as Set).is(instantiatorFactory.injectScheme(classes)) - instantiatorFactory.injectScheme([Annotation1, Annotation1]).is(instantiatorFactory.injectScheme(classes)) - - !instantiatorFactory.injectScheme(classes).is(instantiatorFactory.injectScheme([])) - !instantiatorFactory.injectScheme(classes).is(instantiatorFactory.injectScheme([Annotation1, Annotation2])) - - instantiatorFactory.injectScheme([Annotation2, Annotation1]).is(instantiatorFactory.injectScheme([Annotation1, Annotation2])) + instantiatorFactory.injectScheme([Annotation1]).injectionAnnotations == [Annotation1, Inject] as Set } def "uses Instantiators from inject schemes"() { @@ -57,12 +49,6 @@ class DefaultInstantiatorFactoryTest extends Specification { e.message == 'Annotation @Annotation3 is not a registered injection annotation.' } - def handler(Class annotation) { - InjectAnnotationHandler handler = Stub(InjectAnnotationHandler) - handler.annotation >> annotation - return handler - } - def "detects properties injected by annotation"() { def scheme = instantiatorFactory.injectScheme([Annotation1, Annotation2]) when: @@ -77,6 +63,12 @@ class DefaultInstantiatorFactoryTest extends Specification { instanceFactory.serviceInjectionTriggeredByAnnotation(Annotation1) instanceFactory.serviceInjectionTriggeredByAnnotation(Annotation2) } + + def handler(Class annotation) { + InjectAnnotationHandler handler = Stub(InjectAnnotationHandler) + handler.annotationType >> annotation + return handler + } } @Retention(RetentionPolicy.RUNTIME) From d95b49f1f5f271c706c1e7403ce134ca122b8d80 Mon Sep 17 00:00:00 2001 From: Adam Murdoch Date: Thu, 28 Feb 2019 10:30:47 +1100 Subject: [PATCH 251/853] Don't retain metadata for properties that aren't relevant at execution time, such as `@Inject` properties. --- .../properties/DefaultTypeMetadataStore.java | 6 +- ...actInputFilePropertyAnnotationHandler.java | 5 ++ ...stractOutputPropertyAnnotationHandler.java | 5 ++ .../ClasspathPropertyAnnotationHandler.java | 5 ++ ...ileClasspathPropertyAnnotationHandler.java | 5 ++ .../DestroysPropertyAnnotationHandler.java | 5 ++ .../InputPropertyAnnotationHandler.java | 5 ++ .../LocalStatePropertyAnnotationHandler.java | 5 ++ .../NestedBeanAnnotationHandler.java | 5 ++ .../NoOpPropertyAnnotationHandler.java | 5 ++ .../PropertyAnnotationHandler.java | 7 ++ .../DefaultTypeMetadataStoreTest.groovy | 64 +++++++++++-------- .../InspectionSchemeFactoryTest.groovy | 9 ++- 13 files changed, 100 insertions(+), 31 deletions(-) diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/DefaultTypeMetadataStore.java b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/DefaultTypeMetadataStore.java index 36ba9dd33cc96..93f3afed0fc8c 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/DefaultTypeMetadataStore.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/DefaultTypeMetadataStore.java @@ -136,11 +136,15 @@ private TypeMetadata createTypeMetadata(Class type) { } } ImmutableSet properties = propertyExtractor.extractPropertyMetadata(type, validationContext); + ImmutableSet.Builder effectiveProperties = ImmutableSet.builderWithExpectedSize(properties.size()); for (PropertyMetadata property : properties) { PropertyAnnotationHandler annotationHandler = annotationHandlers.get(property.getPropertyType()); annotationHandler.validatePropertyMetadata(property, validationContext); + if (annotationHandler.isPropertyRelevant()) { + effectiveProperties.add(property); + } } - return new DefaultTypeMetadata(properties, validationContext.getProblems(), annotationHandlers); + return new DefaultTypeMetadata(effectiveProperties.build(), validationContext.getProblems(), annotationHandlers); } private static class RecordingValidationContext implements ParameterValidationContext { diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/annotations/AbstractInputFilePropertyAnnotationHandler.java b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/annotations/AbstractInputFilePropertyAnnotationHandler.java index cd40bdd5c2f72..63aae95786526 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/annotations/AbstractInputFilePropertyAnnotationHandler.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/annotations/AbstractInputFilePropertyAnnotationHandler.java @@ -29,6 +29,11 @@ import org.gradle.internal.reflect.PropertyMetadata; public abstract class AbstractInputFilePropertyAnnotationHandler implements PropertyAnnotationHandler { + @Override + public boolean isPropertyRelevant() { + return true; + } + @Override public boolean shouldVisit(PropertyVisitor visitor) { return !visitor.visitOutputFilePropertiesOnly(); diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/annotations/AbstractOutputPropertyAnnotationHandler.java b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/annotations/AbstractOutputPropertyAnnotationHandler.java index b54465b07e0fc..7e0be99dddbba 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/annotations/AbstractOutputPropertyAnnotationHandler.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/annotations/AbstractOutputPropertyAnnotationHandler.java @@ -28,6 +28,11 @@ public abstract class AbstractOutputPropertyAnnotationHandler implements Propert protected abstract OutputFilePropertyType getFilePropertyType(); + @Override + public boolean isPropertyRelevant() { + return true; + } + @Override public boolean shouldVisit(PropertyVisitor visitor) { return true; diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/annotations/ClasspathPropertyAnnotationHandler.java b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/annotations/ClasspathPropertyAnnotationHandler.java index fcd6150ac0c03..706f1a455b407 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/annotations/ClasspathPropertyAnnotationHandler.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/annotations/ClasspathPropertyAnnotationHandler.java @@ -39,6 +39,11 @@ public Class getAnnotationType() { return Classpath.class; } + @Override + public boolean isPropertyRelevant() { + return true; + } + @Override public ImmutableList> getOverriddenAnnotationTypes() { return ImmutableList.of(InputFiles.class, InputArtifact.class, InputArtifactDependencies.class); diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/annotations/CompileClasspathPropertyAnnotationHandler.java b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/annotations/CompileClasspathPropertyAnnotationHandler.java index 24acfd613fb5b..7c914bf8f9b42 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/annotations/CompileClasspathPropertyAnnotationHandler.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/annotations/CompileClasspathPropertyAnnotationHandler.java @@ -39,6 +39,11 @@ public Class getAnnotationType() { return CompileClasspath.class; } + @Override + public boolean isPropertyRelevant() { + return true; + } + @Override public ImmutableList> getOverriddenAnnotationTypes() { return ImmutableList.of(InputFiles.class, InputArtifact.class, InputArtifactDependencies.class); diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/annotations/DestroysPropertyAnnotationHandler.java b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/annotations/DestroysPropertyAnnotationHandler.java index 88e838fdafcfd..18e94ef794fc9 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/annotations/DestroysPropertyAnnotationHandler.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/annotations/DestroysPropertyAnnotationHandler.java @@ -31,6 +31,11 @@ public Class getAnnotationType() { return Destroys.class; } + @Override + public boolean isPropertyRelevant() { + return true; + } + @Override public boolean shouldVisit(PropertyVisitor visitor) { return !visitor.visitOutputFilePropertiesOnly(); diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/annotations/InputPropertyAnnotationHandler.java b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/annotations/InputPropertyAnnotationHandler.java index 0ea754440f218..dd90a6b38558f 100755 --- a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/annotations/InputPropertyAnnotationHandler.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/annotations/InputPropertyAnnotationHandler.java @@ -32,6 +32,11 @@ public Class getAnnotationType() { return Input.class; } + @Override + public boolean isPropertyRelevant() { + return true; + } + @Override public boolean shouldVisit(PropertyVisitor visitor) { return !visitor.visitOutputFilePropertiesOnly(); diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/annotations/LocalStatePropertyAnnotationHandler.java b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/annotations/LocalStatePropertyAnnotationHandler.java index 817267c471cf7..e129cba4c2ef8 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/annotations/LocalStatePropertyAnnotationHandler.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/annotations/LocalStatePropertyAnnotationHandler.java @@ -29,6 +29,11 @@ public Class getAnnotationType() { return LocalState.class; } + @Override + public boolean isPropertyRelevant() { + return true; + } + @Override public boolean shouldVisit(PropertyVisitor visitor) { return !visitor.visitOutputFilePropertiesOnly(); diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/annotations/NestedBeanAnnotationHandler.java b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/annotations/NestedBeanAnnotationHandler.java index ef5a066a4d57e..3be4f64f585d5 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/annotations/NestedBeanAnnotationHandler.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/annotations/NestedBeanAnnotationHandler.java @@ -37,6 +37,11 @@ public Class getAnnotationType() { return Nested.class; } + @Override + public boolean isPropertyRelevant() { + return true; + } + @Override public boolean shouldVisit(PropertyVisitor visitor) { return !visitor.visitOutputFilePropertiesOnly(); diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/annotations/NoOpPropertyAnnotationHandler.java b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/annotations/NoOpPropertyAnnotationHandler.java index 6eee5bd607067..7a9de8c15837d 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/annotations/NoOpPropertyAnnotationHandler.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/annotations/NoOpPropertyAnnotationHandler.java @@ -31,6 +31,11 @@ public NoOpPropertyAnnotationHandler(Class annotationType) this.annotationType = annotationType; } + @Override + public boolean isPropertyRelevant() { + return false; + } + public Class getAnnotationType() { return annotationType; } diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/annotations/PropertyAnnotationHandler.java b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/annotations/PropertyAnnotationHandler.java index 71dc0b2f6b520..ecf53ec5d736d 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/annotations/PropertyAnnotationHandler.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/annotations/PropertyAnnotationHandler.java @@ -36,6 +36,13 @@ public interface PropertyAnnotationHandler { */ Class getAnnotationType(); + /** + * Does this handler do something useful with the properties that match it? Or can these properties be ignored? + * + * Should consider splitting up this type, perhaps into something that inspects the properties and produces the actual handlers and validation problems. + */ + boolean isPropertyRelevant(); + /** * Is the given visitor interested in this annotation? */ diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/properties/DefaultTypeMetadataStoreTest.groovy b/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/properties/DefaultTypeMetadataStoreTest.groovy index 6e5bff0e6f470..f552d6e223e64 100644 --- a/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/properties/DefaultTypeMetadataStoreTest.groovy +++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/properties/DefaultTypeMetadataStoreTest.groovy @@ -31,11 +31,13 @@ import org.gradle.api.internal.tasks.properties.annotations.TypeAnnotationHandle import org.gradle.api.plugins.ExtensionAware import org.gradle.api.tasks.Classpath import org.gradle.api.tasks.Console +import org.gradle.api.tasks.Destroys import org.gradle.api.tasks.Input import org.gradle.api.tasks.InputDirectory import org.gradle.api.tasks.InputFile import org.gradle.api.tasks.InputFiles import org.gradle.api.tasks.Internal +import org.gradle.api.tasks.LocalState import org.gradle.api.tasks.OutputDirectories import org.gradle.api.tasks.OutputDirectory import org.gradle.api.tasks.OutputFile @@ -57,7 +59,7 @@ import java.lang.annotation.Annotation class DefaultTypeMetadataStoreTest extends Specification { private static final List> PROCESSED_PROPERTY_TYPE_ANNOTATIONS = [ - InputFile, InputFiles, InputDirectory, OutputFile, OutputDirectory, OutputFiles, OutputDirectories + InputFile, InputFiles, InputDirectory, OutputFile, OutputDirectory, OutputFiles, OutputDirectories, Destroys, LocalState ] private static final List> UNPROCESSED_PROPERTY_TYPE_ANNOTATIONS = [ @@ -80,15 +82,16 @@ class DefaultTypeMetadataStoreTest extends Specification { static class TypeWithCustomAnnotation { } - def "can use custom annotation processor"() { + def "can use custom annotation handler"() { def annotationHandler = Stub(PropertyAnnotationHandler) + _ * annotationHandler.propertyRelevant >> true _ * annotationHandler.annotationType >> SearchPath def metadataStore = new DefaultTypeMetadataStore([annotationHandler], [] as Set, [] as Set, new TestCrossBuildInMemoryCacheFactory()) when: def typeMetadata = metadataStore.getTypeMetadata(TaskWithCustomAnnotation) - def propertiesMetadata = typeMetadata.propertiesMetadata.findAll { !isIgnored(it) } + def propertiesMetadata = typeMetadata.propertiesMetadata then: propertiesMetadata.size() == 1 @@ -99,8 +102,9 @@ class DefaultTypeMetadataStoreTest extends Specification { collectProblems(typeMetadata).empty } - def "custom annotation processor can inspect for static property problems"() { + def "custom annotation handler can inspect for static property problems"() { def annotationHandler = Stub(PropertyAnnotationHandler) + _ * annotationHandler.propertyRelevant >> true _ * annotationHandler.annotationType >> SearchPath _ * annotationHandler.validatePropertyMetadata(_, _) >> { PropertyMetadata metadata, ParameterValidationContext context -> context.visitError(null, metadata.propertyName, "is broken") @@ -110,7 +114,7 @@ class DefaultTypeMetadataStoreTest extends Specification { when: def typeMetadata = metadataStore.getTypeMetadata(TaskWithCustomAnnotation) - def propertiesMetadata = typeMetadata.propertiesMetadata.findAll { !isIgnored(it) } + def propertiesMetadata = typeMetadata.propertiesMetadata then: propertiesMetadata.size() == 1 @@ -119,7 +123,26 @@ class DefaultTypeMetadataStoreTest extends Specification { collectProblems(typeMetadata) == ["Property 'searchPath' is broken."] } - def "custom annotation processor can inspect for static type problems"() { + def "custom annotation that is not relevant can have validation problems"() { + def annotationHandler = Stub(PropertyAnnotationHandler) + _ * annotationHandler.propertyRelevant >> false + _ * annotationHandler.annotationType >> SearchPath + _ * annotationHandler.validatePropertyMetadata(_, _) >> { PropertyMetadata metadata, ParameterValidationContext context -> + context.visitError(null, metadata.propertyName, "is broken") + } + + def metadataStore = new DefaultTypeMetadataStore([annotationHandler], [] as Set, [] as Set, new TestCrossBuildInMemoryCacheFactory()) + + when: + def typeMetadata = metadataStore.getTypeMetadata(TaskWithCustomAnnotation) + def propertiesMetadata = typeMetadata.propertiesMetadata + + then: + propertiesMetadata.empty + collectProblems(typeMetadata) == ["Property 'searchPath' is broken."] + } + + def "custom type annotation handler can inspect for static type problems"() { def annotationHandler = Stub(TypeAnnotationHandler) _ * annotationHandler.annotationType >> CustomCacheable _ * annotationHandler.validateTypeMetadata(_, _) >> { Class type, ParameterValidationContext context -> @@ -189,11 +212,10 @@ class DefaultTypeMetadataStoreTest extends Specification { def parentProperty = parentMetadata.propertiesMetadata.first() def childMetadata = metadataStore.getTypeMetadata(childTask) - def childProperty = childMetadata.propertiesMetadata.first() expect: isOfType(parentProperty, processedAnnotation) - isIgnored(childProperty) + childMetadata.propertiesMetadata.empty collectProblems(parentMetadata).empty collectProblems(childMetadata).empty @@ -216,13 +238,12 @@ class DefaultTypeMetadataStoreTest extends Specification { """ def parentMetadata = metadataStore.getTypeMetadata(parentTask) - def parentProperty = parentMetadata.propertiesMetadata.first() def childMetadata = metadataStore.getTypeMetadata(childTask) def childProperty = childMetadata.propertiesMetadata.first() expect: - isIgnored(parentProperty) + parentMetadata.propertiesMetadata.empty isOfType(childProperty, processedAnnotation) collectProblems(parentMetadata).empty collectProblems(childMetadata).empty @@ -246,7 +267,7 @@ class DefaultTypeMetadataStoreTest extends Specification { def typeMetadata = metadataStore.getTypeMetadata(ClasspathPropertyTask) then: - def properties = typeMetadata.propertiesMetadata.findAll { !isIgnored(it) } + def properties = typeMetadata.propertiesMetadata properties*.propertyName as List == ["inputFiles1", "inputFiles2"] properties*.propertyType as List == [Classpath, Classpath] collectProblems(typeMetadata).empty @@ -273,6 +294,8 @@ class DefaultTypeMetadataStoreTest extends Specification { @OutputFiles Set outputFiles @OutputDirectory File outputDirectory @OutputDirectories Set outputDirectories + @Destroys Set destroys + @LocalState File someCache @Inject Object injectedService @Internal Object internal @ReplacedBy("inputString") String oldProperty @@ -284,22 +307,22 @@ class DefaultTypeMetadataStoreTest extends Specification { def properties = metadataStore.getTypeMetadata(SimpleTask).propertiesMetadata then: - nonIgnoredProperties(properties) == ["inputDirectory", "inputFile", "inputFiles", "inputString", "outputDirectories", "outputDirectory", "outputFile", "outputFiles"] + properties.propertyName.sort() == ["destroys", "inputDirectory", "inputFile", "inputFiles", "inputString", "outputDirectories", "outputDirectory", "outputFile", "outputFiles", "someCache"] } static class Unannotated extends DefaultTask { String bad1 File bad2 - @Console String ignore1 - @Input String ignore2 + @Console String notUseful1 + @Input String useful1 } - def "ignores properties that are not annotated"() { + def "ignores properties that are not annotated or that don't do anything"() { when: def metadata = metadataStore.getTypeMetadata(Unannotated) then: - metadata.propertiesMetadata.propertyName == ["ignore1", "ignore2"] + metadata.propertiesMetadata.propertyName == ["useful1"] collectProblems(metadata) == [ "Property 'bad1' is not annotated with an input or output annotation.", "Property 'bad2' is not annotated with an input or output annotation." @@ -335,13 +358,4 @@ class DefaultTypeMetadataStoreTest extends Specification { private static boolean isOfType(PropertyMetadata metadata, Class type) { metadata.propertyType == type } - - private static boolean isIgnored(PropertyMetadata propertyMetadata) { - def propertyType = propertyMetadata.propertyType - UNPROCESSED_PROPERTY_TYPE_ANNOTATIONS.contains(propertyType) - } - - private static List nonIgnoredProperties(Collection typeMetadata) { - typeMetadata.findAll { !isIgnored(it) }*.propertyName.sort() - } } diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/properties/InspectionSchemeFactoryTest.groovy b/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/properties/InspectionSchemeFactoryTest.groovy index e3fe18e17075d..b1875a2bc6fb1 100644 --- a/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/properties/InspectionSchemeFactoryTest.groovy +++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/properties/InspectionSchemeFactoryTest.groovy @@ -16,7 +16,7 @@ package org.gradle.api.internal.tasks.properties -import org.gradle.api.internal.tasks.properties.annotations.NoOpPropertyAnnotationHandler + import org.gradle.api.internal.tasks.properties.annotations.PropertyAnnotationHandler import org.gradle.cache.internal.TestCrossBuildInMemoryCacheFactory import org.gradle.internal.instantiation.InstantiationScheme @@ -40,12 +40,11 @@ class InspectionSchemeFactoryTest extends Specification { def problems = [] metadata.collectValidationFailures(null, new DefaultParameterValidationContext(problems)) problems.empty - metadata.propertiesMetadata.size() == 3 + metadata.propertiesMetadata.size() == 2 def properties = metadata.propertiesMetadata.groupBy { it.propertyName } metadata.getAnnotationHandlerFor(properties.prop1) == handler1 metadata.getAnnotationHandlerFor(properties.prop2) == handler2 - metadata.getAnnotationHandlerFor(properties.prop3) instanceof NoOpPropertyAnnotationHandler } def "annotation can be used for property annotation and injection annotations"() { @@ -58,16 +57,16 @@ class InspectionSchemeFactoryTest extends Specification { def problems = [] metadata.collectValidationFailures(null, new DefaultParameterValidationContext(problems)) problems.empty - metadata.propertiesMetadata.size() == 3 + metadata.propertiesMetadata.size() == 2 def properties = metadata.propertiesMetadata.groupBy { it.propertyName } metadata.getAnnotationHandlerFor(properties.prop1) == handler1 metadata.getAnnotationHandlerFor(properties.prop2) == handler2 - metadata.getAnnotationHandlerFor(properties.prop3) instanceof NoOpPropertyAnnotationHandler } def handler(Class annotation) { def handler = Stub(PropertyAnnotationHandler) + _ * handler.propertyRelevant >> true _ * handler.annotationType >> annotation return handler } From 22294b6e95e41249d8f13028103fff1db0e93b68 Mon Sep 17 00:00:00 2001 From: Adam Murdoch Date: Thu, 28 Feb 2019 15:36:49 +1100 Subject: [PATCH 252/853] Don't inspect generated types for annotated properties, instead inspect the public type. This avoids some unnecessary work. Also fix a typo in a couple of validation messages. --- .../api/internal/GeneratedSubclasses.java | 19 +++++++++++++++---- .../BuildCacheControllerFactory.java | 2 +- .../properties/DefaultTypeMetadataStore.java | 8 +++++--- .../CacheableTaskTypeAnnotationHandler.java | 3 ++- ...sformValuesInjectionIntegrationTest.groovy | 12 ++++++------ ...cheableTransformTypeAnnotationHandler.java | 3 ++- .../api/internal/plugins/DslObject.java | 4 ++-- .../AsmBackedClassGenerator.java | 7 +++++++ .../AsmBackedClassGeneratorTest.java | 6 ++++-- ...lidateTaskPropertiesIntegrationTest.groovy | 12 ++++++------ 10 files changed, 50 insertions(+), 26 deletions(-) diff --git a/subprojects/base-services/src/main/java/org/gradle/api/internal/GeneratedSubclasses.java b/subprojects/base-services/src/main/java/org/gradle/api/internal/GeneratedSubclasses.java index 24da3b9868e6e..c24ec47227e1c 100644 --- a/subprojects/base-services/src/main/java/org/gradle/api/internal/GeneratedSubclasses.java +++ b/subprojects/base-services/src/main/java/org/gradle/api/internal/GeneratedSubclasses.java @@ -16,17 +16,28 @@ package org.gradle.api.internal; +import org.gradle.internal.UncheckedException; + public class GeneratedSubclasses { private GeneratedSubclasses() { } - public static Class unpack(Object object) { + public static Class unpack(Class type) { + if (GeneratedSubclass.class.isAssignableFrom(type)) { + try { + return (Class) type.getMethod("generatedFrom").invoke(null); + } catch (Exception e) { + throw UncheckedException.throwAsUncheckedException(e); + } + } + return type; + } + + public static Class unpackType(Object object) { if (object instanceof GeneratedSubclass) { - GeneratedSubclass generatedSubclass = (GeneratedSubclass) object; - return generatedSubclass.publicType(); + return ((GeneratedSubclass) object).publicType(); } return object.getClass(); } - } diff --git a/subprojects/build-cache/src/main/java/org/gradle/caching/internal/controller/BuildCacheControllerFactory.java b/subprojects/build-cache/src/main/java/org/gradle/caching/internal/controller/BuildCacheControllerFactory.java index f741bf808fd06..37a2bc47ba1bd 100644 --- a/subprojects/build-cache/src/main/java/org/gradle/caching/internal/controller/BuildCacheControllerFactory.java +++ b/subprojects/build-cache/src/main/java/org/gradle/caching/internal/controller/BuildCacheControllerFactory.java @@ -204,7 +204,7 @@ private static final class BuildCacheDescription implements FinalizeBuildCacheCo private final ImmutableSortedMap config; private BuildCacheDescription(BuildCache buildCache, String type, ImmutableSortedMap config) { - this.className = GeneratedSubclasses.unpack(buildCache).getName(); + this.className = GeneratedSubclasses.unpackType(buildCache).getName(); this.push = buildCache.isPush(); this.type = type; this.config = config; diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/DefaultTypeMetadataStore.java b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/DefaultTypeMetadataStore.java index 93f3afed0fc8c..d1ecdfa603244 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/DefaultTypeMetadataStore.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/DefaultTypeMetadataStore.java @@ -30,6 +30,7 @@ import org.gradle.api.internal.AbstractTask; import org.gradle.api.internal.ConventionTask; import org.gradle.api.internal.DynamicObjectAware; +import org.gradle.api.internal.GeneratedSubclasses; import org.gradle.api.internal.HasConvention; import org.gradle.api.internal.IConventionAware; import org.gradle.api.internal.tasks.properties.annotations.AbstractOutputPropertyAnnotationHandler; @@ -129,13 +130,14 @@ public TypeMetadata getTypeMetadata(final Class type) { } private TypeMetadata createTypeMetadata(Class type) { + Class publicType = GeneratedSubclasses.unpack(type); RecordingValidationContext validationContext = new RecordingValidationContext(); for (TypeAnnotationHandler annotationHandler : typeAnnotationHandlers) { - if (type.isAnnotationPresent(annotationHandler.getAnnotationType())) { - annotationHandler.validateTypeMetadata(type, validationContext); + if (publicType.isAnnotationPresent(annotationHandler.getAnnotationType())) { + annotationHandler.validateTypeMetadata(publicType, validationContext); } } - ImmutableSet properties = propertyExtractor.extractPropertyMetadata(type, validationContext); + ImmutableSet properties = propertyExtractor.extractPropertyMetadata(publicType, validationContext); ImmutableSet.Builder effectiveProperties = ImmutableSet.builderWithExpectedSize(properties.size()); for (PropertyMetadata property : properties) { PropertyAnnotationHandler annotationHandler = annotationHandlers.get(property.getPropertyType()); diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/annotations/CacheableTaskTypeAnnotationHandler.java b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/annotations/CacheableTaskTypeAnnotationHandler.java index c72f4644a6869..537369340c71c 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/annotations/CacheableTaskTypeAnnotationHandler.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/annotations/CacheableTaskTypeAnnotationHandler.java @@ -19,6 +19,7 @@ import org.gradle.api.Task; import org.gradle.api.tasks.CacheableTask; import org.gradle.internal.reflect.ParameterValidationContext; +import org.gradle.model.internal.type.ModelType; import java.lang.annotation.Annotation; @@ -31,7 +32,7 @@ public Class getAnnotationType() { @Override public void validateTypeMetadata(Class classWithAnnotationAttached, ParameterValidationContext visitor) { if (!Task.class.isAssignableFrom(classWithAnnotationAttached)) { - visitor.visitErrorStrict(String.format("Cannot use @%s with type %s. This annotation cannot only be used with %s types.", getAnnotationType().getSimpleName(), classWithAnnotationAttached.getSimpleName(), Task.class.getSimpleName())); + visitor.visitErrorStrict(String.format("Cannot use @%s with type %s. This annotation can only be used with %s types.", getAnnotationType().getSimpleName(), ModelType.of(classWithAnnotationAttached).getDisplayName(), Task.class.getSimpleName())); } } } diff --git a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformValuesInjectionIntegrationTest.groovy b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformValuesInjectionIntegrationTest.groovy index ef510900becd0..a8d7d42e1141b 100644 --- a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformValuesInjectionIntegrationTest.groovy +++ b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformValuesInjectionIntegrationTest.groovy @@ -280,8 +280,8 @@ class ArtifactTransformValuesInjectionIntegrationTest extends AbstractDependency then: failure.assertThatDescription(matchesRegexp('Cannot isolate parameters MakeGreen\\$Parameters\\$Inject@.* of artifact transform MakeGreen')) failure.assertHasCause('Some problems were found with the configuration of the artifact transform parameter MakeGreen.Parameters.') - failure.assertHasCause("Cannot use @CacheableTask with type MakeGreen\$Parameters\$Inject. This annotation cannot only be used with Task types.") - failure.assertHasCause("Cannot use @CacheableTransform with type MakeGreen\$Parameters\$Inject. This annotation cannot only be used with TransformAction types.") + failure.assertHasCause("Cannot use @CacheableTask with type MakeGreen.Parameters. This annotation can only be used with Task types.") + failure.assertHasCause("Cannot use @CacheableTransform with type MakeGreen.Parameters. This annotation can only be used with TransformAction types.") } @Unroll @@ -467,7 +467,7 @@ class ArtifactTransformValuesInjectionIntegrationTest extends AbstractDependency then: failure.assertHasDescription('A problem occurred evaluating root project') failure.assertHasCause('A problem was found with the configuration of MakeGreen.') - failure.assertHasCause("Cannot use @CacheableTask with type MakeGreen. This annotation cannot only be used with Task types.") + failure.assertHasCause("Cannot use @CacheableTask with type MakeGreen. This annotation can only be used with Task types.") } @Unroll @@ -734,7 +734,7 @@ abstract class MakeGreen implements TransformAction { failure.assertHasDescription("A problem occurred evaluating root project") failure.assertHasCause("Could not create task ':broken'.") failure.assertHasCause("A problem was found with the configuration of task ':broken'.") - failure.assertHasCause("Cannot use @CacheableTransform with type MyTask_Decorated. This annotation cannot only be used with TransformAction types.") + failure.assertHasCause("Cannot use @CacheableTransform with type MyTask. This annotation can only be used with TransformAction types.") } def "task @Nested bean cannot use cacheable annotations"() { @@ -759,8 +759,8 @@ abstract class MakeGreen implements TransformAction { fails('broken') failure.assertHasDescription("Could not determine the dependencies of task ':broken'.") failure.assertHasCause("Some problems were found with the configuration of task ':broken'.") - failure.assertHasCause("Cannot use @CacheableTask with type Options. This annotation cannot only be used with Task types.") - failure.assertHasCause("Cannot use @CacheableTransform with type Options. This annotation cannot only be used with TransformAction types.") + failure.assertHasCause("Cannot use @CacheableTask with type Options. This annotation can only be used with Task types.") + failure.assertHasCause("Cannot use @CacheableTransform with type Options. This annotation can only be used with TransformAction types.") } @Unroll diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/CacheableTransformTypeAnnotationHandler.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/CacheableTransformTypeAnnotationHandler.java index 09e5cf84c6729..97dcb51b6ef77 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/CacheableTransformTypeAnnotationHandler.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/CacheableTransformTypeAnnotationHandler.java @@ -20,6 +20,7 @@ import org.gradle.api.artifacts.transform.TransformAction; import org.gradle.api.internal.tasks.properties.annotations.TypeAnnotationHandler; import org.gradle.internal.reflect.ParameterValidationContext; +import org.gradle.model.internal.type.ModelType; import java.lang.annotation.Annotation; @@ -32,7 +33,7 @@ public Class getAnnotationType() { @Override public void validateTypeMetadata(Class classWithAnnotationAttached, ParameterValidationContext visitor) { if (!TransformAction.class.isAssignableFrom(classWithAnnotationAttached)) { - visitor.visitErrorStrict(String.format("Cannot use @%s with type %s. This annotation cannot only be used with %s types.", getAnnotationType().getSimpleName(), classWithAnnotationAttached.getSimpleName(), TransformAction.class.getSimpleName())); + visitor.visitErrorStrict(String.format("Cannot use @%s with type %s. This annotation can only be used with %s types.", getAnnotationType().getSimpleName(), ModelType.of(classWithAnnotationAttached).getDisplayName(), TransformAction.class.getSimpleName())); } } } diff --git a/subprojects/model-core/src/main/java/org/gradle/api/internal/plugins/DslObject.java b/subprojects/model-core/src/main/java/org/gradle/api/internal/plugins/DslObject.java index cfff36c6ad588..dfb193caea965 100644 --- a/subprojects/model-core/src/main/java/org/gradle/api/internal/plugins/DslObject.java +++ b/subprojects/model-core/src/main/java/org/gradle/api/internal/plugins/DslObject.java @@ -88,11 +88,11 @@ public TypeOf getPublicType() { if (object instanceof HasPublicType) { return uncheckedCast(((HasPublicType) object).getPublicType()); } - return TypeOf.typeOf(GeneratedSubclasses.unpack(object)); + return TypeOf.typeOf(GeneratedSubclasses.unpackType(object)); } public Class getImplementationType() { - return GeneratedSubclasses.unpack(object); + return GeneratedSubclasses.unpackType(object); } private static T toType(Object delegate, Class type) { diff --git a/subprojects/model-core/src/main/java/org/gradle/internal/instantiation/AsmBackedClassGenerator.java b/subprojects/model-core/src/main/java/org/gradle/internal/instantiation/AsmBackedClassGenerator.java index 7eb64cebaa778..3bfa94ffd1368 100644 --- a/subprojects/model-core/src/main/java/org/gradle/internal/instantiation/AsmBackedClassGenerator.java +++ b/subprojects/model-core/src/main/java/org/gradle/internal/instantiation/AsmBackedClassGenerator.java @@ -1065,6 +1065,13 @@ private void generatePublicTypeMethod() { methodVisitor.visitInsn(ARETURN); methodVisitor.visitMaxs(0, 0); methodVisitor.visitEnd(); + + // Generate: static Class generatedFrom() { ... } + methodVisitor = visitor.visitMethod(ACC_PUBLIC | ACC_STATIC, "generatedFrom", RETURN_CLASS, null, EMPTY_STRINGS); + methodVisitor.visitLdcInsn(superclassType); + methodVisitor.visitInsn(ARETURN); + methodVisitor.visitMaxs(0, 0); + methodVisitor.visitEnd(); } @Override diff --git a/subprojects/model-core/src/test/groovy/org/gradle/internal/instantiation/AsmBackedClassGeneratorTest.java b/subprojects/model-core/src/test/groovy/org/gradle/internal/instantiation/AsmBackedClassGeneratorTest.java index daed2cb4676d8..16b0749b3180f 100755 --- a/subprojects/model-core/src/test/groovy/org/gradle/internal/instantiation/AsmBackedClassGeneratorTest.java +++ b/subprojects/model-core/src/test/groovy/org/gradle/internal/instantiation/AsmBackedClassGeneratorTest.java @@ -135,7 +135,8 @@ public void mixesInGeneratedSubclassInterface() throws Exception { Bean bean = newInstance(Bean.class); assertTrue(bean instanceof GeneratedSubclass); assertEquals(Bean.class, ((GeneratedSubclass)bean).publicType()); - assertEquals(Bean.class, GeneratedSubclasses.unpack(bean)); + assertEquals(Bean.class, GeneratedSubclasses.unpackType(bean)); + assertEquals(Bean.class, GeneratedSubclasses.unpack(bean.getClass())); } @Test @@ -143,7 +144,8 @@ public void mixesInGeneratedSubclassInterfaceToInterface() throws Exception { InterfaceWithDefaultMethods bean = newInstance(InterfaceWithDefaultMethods.class); assertTrue(bean instanceof GeneratedSubclass); assertEquals(InterfaceWithDefaultMethods.class, ((GeneratedSubclass)bean).publicType()); - assertEquals(InterfaceWithDefaultMethods.class, GeneratedSubclasses.unpack(bean)); + assertEquals(InterfaceWithDefaultMethods.class, GeneratedSubclasses.unpackType(bean)); + assertEquals(InterfaceWithDefaultMethods.class, GeneratedSubclasses.unpack(bean.getClass())); } @Test diff --git a/subprojects/plugin-development/src/integTest/groovy/org/gradle/plugin/devel/tasks/ValidateTaskPropertiesIntegrationTest.groovy b/subprojects/plugin-development/src/integTest/groovy/org/gradle/plugin/devel/tasks/ValidateTaskPropertiesIntegrationTest.groovy index b4682876123b6..cc026d7fdd992 100644 --- a/subprojects/plugin-development/src/integTest/groovy/org/gradle/plugin/devel/tasks/ValidateTaskPropertiesIntegrationTest.groovy +++ b/subprojects/plugin-development/src/integTest/groovy/org/gradle/plugin/devel/tasks/ValidateTaskPropertiesIntegrationTest.groovy @@ -258,14 +258,14 @@ class ValidateTaskPropertiesIntegrationTest extends AbstractIntegrationSpec { fails("validateTaskProperties") failure.assertHasDescription("Execution failed for task ':validateTaskProperties'.") failure.assertHasCause("Task property validation failed. See") - failure.assertHasCause("Error: Cannot use @CacheableTask with type Options. This annotation cannot only be used with Task types.") - failure.assertHasCause("Error: Cannot use @CacheableTransform with type MyTask. This annotation cannot only be used with TransformAction types.") - failure.assertHasCause("Error: Cannot use @CacheableTransform with type Options. This annotation cannot only be used with TransformAction types.") + failure.assertHasCause("Error: Cannot use @CacheableTask with type MyTask.Options. This annotation can only be used with Task types.") + failure.assertHasCause("Error: Cannot use @CacheableTransform with type MyTask. This annotation can only be used with TransformAction types.") + failure.assertHasCause("Error: Cannot use @CacheableTransform with type MyTask.Options. This annotation can only be used with TransformAction types.") file("build/reports/task-properties/report.txt").text == """ - Error: Cannot use @CacheableTask with type Options. This annotation cannot only be used with Task types. - Error: Cannot use @CacheableTransform with type MyTask. This annotation cannot only be used with TransformAction types. - Error: Cannot use @CacheableTransform with type Options. This annotation cannot only be used with TransformAction types. + Error: Cannot use @CacheableTask with type MyTask.Options. This annotation can only be used with Task types. + Error: Cannot use @CacheableTransform with type MyTask. This annotation can only be used with TransformAction types. + Error: Cannot use @CacheableTransform with type MyTask.Options. This annotation can only be used with TransformAction types. """.stripIndent().trim() } From 5dbe8f9ea17d5e40864ad972c5fd29888e762ed8 Mon Sep 17 00:00:00 2001 From: Adam Murdoch Date: Thu, 28 Feb 2019 17:03:01 +1100 Subject: [PATCH 253/853] Do not use the `Instantiator` infrastructure to create script instances. While this means some validation of the methods of the script itself (if any) will no longer happen, this validation is also somewhat expensive and does not seem not worth the performance penalty at this point. The checks might be better implemented at script compile time and the results persisted instead. --- .../gradle/internal/service/scopes/BuildScopeServices.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/subprojects/core/src/main/java/org/gradle/internal/service/scopes/BuildScopeServices.java b/subprojects/core/src/main/java/org/gradle/internal/service/scopes/BuildScopeServices.java index 01cb4fa543dc8..e034710df03c1 100644 --- a/subprojects/core/src/main/java/org/gradle/internal/service/scopes/BuildScopeServices.java +++ b/subprojects/core/src/main/java/org/gradle/internal/service/scopes/BuildScopeServices.java @@ -152,6 +152,7 @@ import org.gradle.internal.operations.BuildOperationExecutor; import org.gradle.internal.operations.logging.BuildOperationLoggerFactory; import org.gradle.internal.operations.logging.DefaultBuildOperationLoggerFactory; +import org.gradle.internal.reflect.DirectInstantiator; import org.gradle.internal.reflect.Instantiator; import org.gradle.internal.resource.TextResourceLoader; import org.gradle.internal.service.CachingServiceLocator; @@ -258,14 +259,14 @@ protected ITaskFactory createITaskFactory(Instantiator instantiator, TaskClassIn protected ScriptCompilerFactory createScriptCompileFactory(ListenerManager listenerManager, FileCacheBackedScriptClassCompiler scriptCompiler, - CrossBuildInMemoryCachingScriptClassCache cache, - InstantiatorFactory instantiatorFactory) { + CrossBuildInMemoryCachingScriptClassCache cache) { ScriptExecutionListener scriptExecutionListener = listenerManager.getBroadcaster(ScriptExecutionListener.class); return new DefaultScriptCompilerFactory( new BuildScopeInMemoryCachingScriptClassCompiler(cache, scriptCompiler), new DefaultScriptRunnerFactory( scriptExecutionListener, - instantiatorFactory.inject() + // Should use `InstantiatorFactory` instead to pick up some validation, but this is currently somewhat expensive + DirectInstantiator.INSTANCE ) ); } From b01ddc1a5532ba99b8afec464f2f927bb7b77946 Mon Sep 17 00:00:00 2001 From: Adam Murdoch Date: Fri, 1 Mar 2019 08:08:50 +1100 Subject: [PATCH 254/853] Defer service lookups until they are required when creating a decorated object instance. --- .../initialization/DefaultSettingsTest.groovy | 2 + .../initialization/SettingsFactoryTest.groovy | 2 + .../groovy/org/gradle/util/TestUtil.groovy | 1 + .../AsmBackedClassGenerator.java | 48 ++++--------------- .../DefaultInstantiatorFactory.java | 15 +++--- .../MixInExtensibleDynamicObject.java | 10 +++- .../AbstractClassGeneratorSpec.groovy | 13 +++-- ...smBackedClassGeneratorDecoratedTest.groovy | 13 +++++ ...edClassGeneratorInjectDecoratedTest.groovy | 42 ++++++++-------- .../AsmBackedClassGeneratorTest.java | 4 +- ...lassGeneratorBackedInstantiatorTest.groovy | 24 +++++----- 11 files changed, 89 insertions(+), 85 deletions(-) diff --git a/subprojects/core/src/test/groovy/org/gradle/initialization/DefaultSettingsTest.groovy b/subprojects/core/src/test/groovy/org/gradle/initialization/DefaultSettingsTest.groovy index 2536a9950e94c..5c3123d534abf 100644 --- a/subprojects/core/src/test/groovy/org/gradle/initialization/DefaultSettingsTest.groovy +++ b/subprojects/core/src/test/groovy/org/gradle/initialization/DefaultSettingsTest.groovy @@ -29,6 +29,7 @@ import org.gradle.api.internal.plugins.DefaultPluginManager import org.gradle.configuration.ScriptPluginFactory import org.gradle.groovy.scripts.ScriptSource import org.gradle.integtests.fixtures.FeaturePreviewsFixture +import org.gradle.internal.instantiation.InstantiatorFactory import org.gradle.internal.service.ServiceRegistry import org.gradle.internal.service.scopes.ServiceRegistryFactory import org.gradle.util.TestUtil @@ -62,6 +63,7 @@ class DefaultSettingsTest extends Specification { settingsServices.get(ProjectDescriptorRegistry) >> projectDescriptorRegistry settingsServices.get(FeaturePreviews) >> previews settingsServices.get(DefaultPluginManager) >>> [pluginManager, null] + settingsServices.get(InstantiatorFactory) >> Stub(InstantiatorFactory) serviceRegistryFactory = Mock(ServiceRegistryFactory) { 1 * createFor(_) >> settingsServices diff --git a/subprojects/core/src/test/groovy/org/gradle/initialization/SettingsFactoryTest.groovy b/subprojects/core/src/test/groovy/org/gradle/initialization/SettingsFactoryTest.groovy index 8a404afa6efba..6544105e174c1 100644 --- a/subprojects/core/src/test/groovy/org/gradle/initialization/SettingsFactoryTest.groovy +++ b/subprojects/core/src/test/groovy/org/gradle/initialization/SettingsFactoryTest.groovy @@ -26,6 +26,7 @@ import org.gradle.api.internal.initialization.ScriptHandlerInternal import org.gradle.api.internal.initialization.loadercache.DummyClassLoaderCache import org.gradle.configuration.ScriptPluginFactory import org.gradle.groovy.scripts.ScriptSource +import org.gradle.internal.instantiation.InstantiatorFactory import org.gradle.internal.service.ServiceRegistry import org.gradle.internal.service.scopes.ServiceRegistryFactory import org.gradle.util.TestUtil @@ -52,6 +53,7 @@ class SettingsFactoryTest extends Specification { 1 * settingsServices.get(ScriptPluginFactory) >> scriptPluginFactory 1 * settingsServices.get(ScriptHandlerFactory) >> scriptHandlerFactory 1 * settingsServices.get(ProjectDescriptorRegistry) >> projectDescriptorRegistry + 1 * settingsServices.get(InstantiatorFactory) >> Stub(InstantiatorFactory) 1 * projectDescriptorRegistry.addProject(_ as DefaultProjectDescriptor) 1 * scriptHandlerFactory.create(scriptSource, _ as ClassLoaderScope) >> Mock(ScriptHandlerInternal) diff --git a/subprojects/core/src/testFixtures/groovy/org/gradle/util/TestUtil.groovy b/subprojects/core/src/testFixtures/groovy/org/gradle/util/TestUtil.groovy index c8b795ca349b0..1f109308bb842 100644 --- a/subprojects/core/src/testFixtures/groovy/org/gradle/util/TestUtil.groovy +++ b/subprojects/core/src/testFixtures/groovy/org/gradle/util/TestUtil.groovy @@ -72,6 +72,7 @@ class TestUtil { private static ObjectFactory objFactory(FileResolver fileResolver) { DefaultServiceRegistry services = new DefaultServiceRegistry() services.add(ProviderFactory, new DefaultProviderFactory()) + services.add(InstantiatorFactory, instantiatorFactory()) return new DefaultObjectFactory(instantiatorFactory().injectAndDecorate(services), NamedObjectInstantiator.INSTANCE, fileResolver, TestFiles.directoryFileTreeFactory(), new DefaultFilePropertyFactory(fileResolver), TestFiles.fileCollectionFactory()) } diff --git a/subprojects/model-core/src/main/java/org/gradle/internal/instantiation/AsmBackedClassGenerator.java b/subprojects/model-core/src/main/java/org/gradle/internal/instantiation/AsmBackedClassGenerator.java index 3bfa94ffd1368..d54bd8a4a98d7 100644 --- a/subprojects/model-core/src/main/java/org/gradle/internal/instantiation/AsmBackedClassGenerator.java +++ b/subprojects/model-core/src/main/java/org/gradle/internal/instantiation/AsmBackedClassGenerator.java @@ -114,22 +114,6 @@ public static ServiceLookup getServicesForNext() { return SERVICES_FOR_NEXT_OBJECT.get().services; } - // Used by generated code - @SuppressWarnings("unused") - public static Instantiator getInstantiatorForNext() { - return createExtensionInstantiator(getServicesForNext(), SERVICES_FOR_NEXT_OBJECT.get().instantiator); - } - - private static Instantiator createExtensionInstantiator(ServiceLookup services, Instantiator nested) { - // The instantiator provided to the generated class is used for implementing `Convention`. - // To maintain backward compatibility, create a 'lenient' instantiator for this purpose, where possible. - InstantiatorFactory instantiatorFactory = (InstantiatorFactory) services.find(InstantiatorFactory.class); - if (instantiatorFactory != null) { - return instantiatorFactory.injectAndDecorateLenient(services); - } - return nested; - } - private AsmBackedClassGenerator(boolean decorate, String suffix, Collection allKnownAnnotations, Collection> enabledAnnotations) { super(allKnownAnnotations, enabledAnnotations); this.decorate = decorate; @@ -254,7 +238,8 @@ public ClassGenerationVisitor builder() { formatter.append(" is final."); throw new ClassGenerationException(formatter.toString()); } - ClassBuilderImpl builder = new ClassBuilderImpl(type, decorate, suffix, extensible, conventionAware, managed, providesOwnDynamicObjectImplementation, serviceInjection && !providesOwnServicesImplementation); + boolean requiresServicesMethod = (extensible || serviceInjection) && !providesOwnServicesImplementation; + ClassBuilderImpl builder = new ClassBuilderImpl(type, decorate, suffix, extensible, conventionAware, managed, providesOwnDynamicObjectImplementation, requiresServicesMethod); builder.startClass(); return builder; } @@ -268,7 +253,6 @@ private static class ClassBuilderImpl implements ClassGenerationVisitor { private static final String META_CLASS_FIELD = "_gr_mc_"; private static final String SERVICES_FIELD = "_gr_svcs_"; private static final String SERVICES_METHOD = "$gradleServices"; - private static final String INSTANTIATOR_FIELD = "_gr_inst_"; private static final String FACTORY_FIELD = "_gr_factory_"; private static final String CONVENTION_MAPPING_FIELD_DESCRIPTOR = Type.getDescriptor(ConventionMapping.class); private static final String META_CLASS_TYPE_DESCRIPTOR = Type.getDescriptor(MetaClass.class); @@ -283,7 +267,7 @@ private static class ClassBuilderImpl implements ClassGenerationVisitor { private final static Type CONVENTION_MAPPING_TYPE = Type.getType(ConventionMapping.class); private final static Type GROOVY_OBJECT_TYPE = Type.getType(GroovyObject.class); private final static Type CONVENTION_TYPE = Type.getType(Convention.class); - private static final Type ASM_BACKED_CLASS_GENERATOR_TYPE = Type.getType(AsmBackedClassGenerator.class); + private final static Type ASM_BACKED_CLASS_GENERATOR_TYPE = Type.getType(AsmBackedClassGenerator.class); private final static Type ABSTRACT_DYNAMIC_OBJECT_TYPE = Type.getType(AbstractDynamicObject.class); private final static Type EXTENSIBLE_DYNAMIC_OBJECT_HELPER_TYPE = Type.getType(MixInExtensibleDynamicObject.class); private final static Type NON_EXTENSIBLE_DYNAMIC_OBJECT_HELPER_TYPE = Type.getType(BeanDynamicObject.class); @@ -305,6 +289,7 @@ private static class ClassBuilderImpl implements ClassGenerationVisitor { private static final Type ACTION_TYPE = Type.getType(Action.class); private static final Type PROPERTY_INTERNAL_TYPE = Type.getType(PropertyInternal.class); private static final Type INSTANTIATOR_TYPE = Type.getType(Instantiator.class); + private static final Type INSTANTIATOR_FACTORY_TYPE = Type.getType(InstantiatorFactory.class); private static final Type OBJECT_FACTORY_TYPE = Type.getType(ObjectFactory.class); private static final Type CONFIGURABLE_FILE_COLLECTION_TYPE = Type.getType(ConfigurableFileCollection.class); private static final Type MANAGED_TYPE = Type.getType(Managed.class); @@ -317,7 +302,7 @@ private static class ClassBuilderImpl implements ClassGenerationVisitor { private static final Type EXTENSION_CONTAINER_TYPE = Type.getType(ExtensionContainer.class); private static final String RETURN_VOID_FROM_OBJECT = Type.getMethodDescriptor(Type.VOID_TYPE, OBJECT_TYPE); - private static final String RETURN_VOID_FROM_OBJECT_CLASS_DYNAMIC_OBJECT_INSTANTIATOR = Type.getMethodDescriptor(Type.VOID_TYPE, OBJECT_TYPE, CLASS_TYPE, DYNAMIC_OBJECT_TYPE, INSTANTIATOR_TYPE); + private static final String RETURN_VOID_FROM_OBJECT_CLASS_DYNAMIC_OBJECT_SERVICE_LOOKUP = Type.getMethodDescriptor(Type.VOID_TYPE, OBJECT_TYPE, CLASS_TYPE, DYNAMIC_OBJECT_TYPE, SERVICE_LOOKUP_TYPE); private static final String RETURN_OBJECT_FROM_STRING_OBJECT_BOOLEAN = Type.getMethodDescriptor(OBJECT_TYPE, OBJECT_TYPE, STRING_TYPE, Type.BOOLEAN_TYPE); private static final String RETURN_CLASS = Type.getMethodDescriptor(CLASS_TYPE); private static final String RETURN_BOOLEAN = Type.getMethodDescriptor(Type.BOOLEAN_TYPE); @@ -336,7 +321,6 @@ private static class ClassBuilderImpl implements ClassGenerationVisitor { private static final String RETURN_META_CLASS_REGISTRY = Type.getMethodDescriptor(META_CLASS_REGISTRY_TYPE); private static final String RETURN_SERVICE_REGISTRY = Type.getMethodDescriptor(SERVICE_REGISTRY_TYPE); private static final String RETURN_SERVICE_LOOKUP = Type.getMethodDescriptor(SERVICE_LOOKUP_TYPE); - private static final String RETURN_INSTANTIATOR = Type.getMethodDescriptor(INSTANTIATOR_TYPE); private static final String RETURN_META_CLASS = Type.getMethodDescriptor(META_CLASS_TYPE); private static final String RETURN_VOID_FROM_META_CLASS = Type.getMethodDescriptor(Type.VOID_TYPE, META_CLASS_TYPE); private static final String GET_DECLARED_METHOD_DESCRIPTOR = Type.getMethodDescriptor(METHOD_TYPE, STRING_TYPE, CLASS_ARRAY_TYPE); @@ -359,7 +343,6 @@ private static class ClassBuilderImpl implements ClassGenerationVisitor { private final Type superclassType; private final Map genericReturnTypeConstantsIndex = Maps.newHashMap(); private final AsmClassGenerator classGenerator; - private final boolean requiresInstantiator; private boolean hasMappingField; private final boolean conventionAware; private final boolean mixInDsl; @@ -377,7 +360,6 @@ private ClassBuilderImpl(Class type, boolean decorated, String suffix, boolea mixInDsl = decorated; this.extensible = extensible; this.conventionAware = conventionAware; - requiresInstantiator = !DynamicObjectAware.class.isAssignableFrom(type) && extensible; this.providesOwnDynamicObject = providesOwnDynamicObject; this.requiresServicesMethod = requiresServicesMethod; } @@ -479,12 +461,6 @@ private void initializeFields(MethodVisitor methodVisitor) { methodVisitor.visitMethodInsn(INVOKESTATIC, ASM_BACKED_CLASS_GENERATOR_TYPE.getInternalName(), "getServicesForNext", RETURN_SERVICE_LOOKUP, false); methodVisitor.visitFieldInsn(PUTFIELD, generatedType.getInternalName(), SERVICES_FIELD, SERVICE_LOOKUP_TYPE.getDescriptor()); } - if (requiresInstantiator) { - // this.instantiator = AsmBackedClassGenerator.getInstantiatorForNext() - methodVisitor.visitVarInsn(ALOAD, 0); - methodVisitor.visitMethodInsn(INVOKESTATIC, ASM_BACKED_CLASS_GENERATOR_TYPE.getInternalName(), "getInstantiatorForNext", RETURN_INSTANTIATOR, false); - methodVisitor.visitFieldInsn(PUTFIELD, generatedType.getInternalName(), INSTANTIATOR_FIELD, INSTANTIATOR_TYPE.getDescriptor()); - } } @Override @@ -513,11 +489,6 @@ public void mixInDynamicAware() { // END - if (requiresInstantiator) { - // GENERATE private Instantiator instantiator - visitor.visitField(Opcodes.ACC_PRIVATE, INSTANTIATOR_FIELD, INSTANTIATOR_TYPE.getDescriptor(), null, null); - } - if (extensible) { // GENERATE public Convention getConvention() { return getAsDynamicObject().getConvention(); } @@ -559,7 +530,7 @@ public void add(MethodVisitor visitor) { private void generateCreateDynamicObject(MethodVisitor visitor) { if (extensible) { - // GENERATE new MixInExtensibleDynamicObject(this, getClass().getSuperClass(), super.getAsDynamicObject(), this.instantiator) + // GENERATE new MixInExtensibleDynamicObject(this, getClass().getSuperClass(), super.getAsDynamicObject(), this.services()) visitor.visitTypeInsn(Opcodes.NEW, EXTENSIBLE_DYNAMIC_OBJECT_HELPER_TYPE.getInternalName()); visitor.visitInsn(Opcodes.DUP); @@ -579,11 +550,10 @@ private void generateCreateDynamicObject(MethodVisitor visitor) { visitor.visitInsn(Opcodes.ACONST_NULL); } - // GENERATE this.instantiator - visitor.visitVarInsn(ALOAD, 0); - visitor.visitFieldInsn(GETFIELD, generatedType.getInternalName(), INSTANTIATOR_FIELD, INSTANTIATOR_TYPE.getDescriptor()); + // GENERATE this.services() + putServiceRegistryOnStack(visitor); - visitor.visitMethodInsn(Opcodes.INVOKESPECIAL, EXTENSIBLE_DYNAMIC_OBJECT_HELPER_TYPE.getInternalName(), "", RETURN_VOID_FROM_OBJECT_CLASS_DYNAMIC_OBJECT_INSTANTIATOR, false); + visitor.visitMethodInsn(Opcodes.INVOKESPECIAL, EXTENSIBLE_DYNAMIC_OBJECT_HELPER_TYPE.getInternalName(), "", RETURN_VOID_FROM_OBJECT_CLASS_DYNAMIC_OBJECT_SERVICE_LOOKUP, false); // END } else { diff --git a/subprojects/model-core/src/main/java/org/gradle/internal/instantiation/DefaultInstantiatorFactory.java b/subprojects/model-core/src/main/java/org/gradle/internal/instantiation/DefaultInstantiatorFactory.java index f99b1647cc334..4b9776ad40592 100644 --- a/subprojects/model-core/src/main/java/org/gradle/internal/instantiation/DefaultInstantiatorFactory.java +++ b/subprojects/model-core/src/main/java/org/gradle/internal/instantiation/DefaultInstantiatorFactory.java @@ -29,7 +29,7 @@ import java.util.List; public class DefaultInstantiatorFactory implements InstantiatorFactory { - private final ServiceRegistry noServices = new DefaultServiceRegistry(); + private final ServiceRegistry defaultServices; private final CrossBuildInMemoryCacheFactory cacheFactory; private final List annotationHandlers; private final DefaultInstantiationScheme injectOnlyScheme; @@ -40,16 +40,19 @@ public class DefaultInstantiatorFactory implements InstantiatorFactory { public DefaultInstantiatorFactory(CrossBuildInMemoryCacheFactory cacheFactory, List annotationHandlers) { this.cacheFactory = cacheFactory; this.annotationHandlers = annotationHandlers; + DefaultServiceRegistry services = new DefaultServiceRegistry(); + services.add(InstantiatorFactory.class, this); + this.defaultServices = services; ClassGenerator injectOnly = AsmBackedClassGenerator.injectOnly(annotationHandlers, ImmutableSet.of()); ClassGenerator decorated = AsmBackedClassGenerator.decorateAndInject(annotationHandlers, ImmutableSet.of()); ConstructorSelector injectOnlyJsr330Selector = new Jsr330ConstructorSelector(injectOnly, cacheFactory.newClassCache()); ConstructorSelector decoratedJsr330Selector = new Jsr330ConstructorSelector(decorated, cacheFactory.newClassCache()); ConstructorSelector injectOnlyLenientSelector = new ParamsMatchingConstructorSelector(injectOnly, cacheFactory.newClassCache()); ConstructorSelector decoratedLenientSelector = new ParamsMatchingConstructorSelector(decorated, cacheFactory.newClassCache()); - injectOnlyScheme = new DefaultInstantiationScheme(injectOnlyJsr330Selector, noServices, ImmutableSet.of(Inject.class)); - injectOnlyLenientScheme = new DefaultInstantiationScheme(injectOnlyLenientSelector, noServices, ImmutableSet.of(Inject.class)); - decoratingScheme = new DefaultInstantiationScheme(decoratedJsr330Selector, noServices, ImmutableSet.of(Inject.class)); - decoratingLenientScheme = new DefaultInstantiationScheme(decoratedLenientSelector, noServices, ImmutableSet.of(Inject.class)); + injectOnlyScheme = new DefaultInstantiationScheme(injectOnlyJsr330Selector, defaultServices, ImmutableSet.of(Inject.class)); + injectOnlyLenientScheme = new DefaultInstantiationScheme(injectOnlyLenientSelector, defaultServices, ImmutableSet.of(Inject.class)); + decoratingScheme = new DefaultInstantiationScheme(decoratedJsr330Selector, defaultServices, ImmutableSet.of(Inject.class)); + decoratingLenientScheme = new DefaultInstantiationScheme(decoratedLenientSelector, defaultServices, ImmutableSet.of(Inject.class)); } @Override @@ -81,7 +84,7 @@ public InstantiationScheme injectScheme(Collection> ImmutableSet.Builder> builder = ImmutableSet.builderWithExpectedSize(injectAnnotations.size() + 1); builder.addAll(injectAnnotations); builder.add(Inject.class); - return new DefaultInstantiationScheme(constructorSelector, noServices, builder.build()); + return new DefaultInstantiationScheme(constructorSelector, defaultServices, builder.build()); } @Override diff --git a/subprojects/model-core/src/main/java/org/gradle/internal/instantiation/MixInExtensibleDynamicObject.java b/subprojects/model-core/src/main/java/org/gradle/internal/instantiation/MixInExtensibleDynamicObject.java index 8d9fd79dbcccb..77985c7a6b107 100644 --- a/subprojects/model-core/src/main/java/org/gradle/internal/instantiation/MixInExtensibleDynamicObject.java +++ b/subprojects/model-core/src/main/java/org/gradle/internal/instantiation/MixInExtensibleDynamicObject.java @@ -21,6 +21,7 @@ import org.gradle.internal.metaobject.BeanDynamicObject; import org.gradle.internal.metaobject.DynamicObject; import org.gradle.internal.reflect.Instantiator; +import org.gradle.internal.service.ServiceLookup; import javax.annotation.Nullable; @@ -29,8 +30,13 @@ */ public class MixInExtensibleDynamicObject extends ExtensibleDynamicObject { // Used by generated code - public MixInExtensibleDynamicObject(Object decoratedObject, Class publicType, @Nullable DynamicObject selfProvidedDynamicObject, Instantiator instantiator) { - super(decoratedObject, wrap(decoratedObject, publicType, selfProvidedDynamicObject), instantiator); + public MixInExtensibleDynamicObject(Object decoratedObject, Class publicType, @Nullable DynamicObject selfProvidedDynamicObject, ServiceLookup services) { + super(decoratedObject, wrap(decoratedObject, publicType, selfProvidedDynamicObject), instantiator(services)); + } + + private static Instantiator instantiator(ServiceLookup services) { + InstantiatorFactory instantiatorFactory = (InstantiatorFactory) services.get(InstantiatorFactory.class); + return instantiatorFactory.injectAndDecorateLenient(services); } private static AbstractDynamicObject wrap(Object delegateObject, Class publicType, DynamicObject dynamicObject) { diff --git a/subprojects/model-core/src/test/groovy/org/gradle/internal/instantiation/AbstractClassGeneratorSpec.groovy b/subprojects/model-core/src/test/groovy/org/gradle/internal/instantiation/AbstractClassGeneratorSpec.groovy index c66bd893d5218..f35627c4169b6 100644 --- a/subprojects/model-core/src/test/groovy/org/gradle/internal/instantiation/AbstractClassGeneratorSpec.groovy +++ b/subprojects/model-core/src/test/groovy/org/gradle/internal/instantiation/AbstractClassGeneratorSpec.groovy @@ -16,16 +16,17 @@ package org.gradle.internal.instantiation + import org.gradle.internal.reflect.Instantiator -import org.gradle.internal.service.DefaultServiceRegistry import org.gradle.internal.service.ServiceLookup +import org.gradle.util.TestUtil import spock.lang.Specification abstract class AbstractClassGeneratorSpec extends Specification { abstract ClassGenerator getGenerator() protected T create(Class clazz, Object... args) { - return create(clazz, new DefaultServiceRegistry(), args) + return create(clazz, defaultServices(), args) } protected T create(Class clazz, ServiceLookup services, Object... args) { @@ -33,7 +34,13 @@ abstract class AbstractClassGeneratorSpec extends Specification { } protected T create(ClassGenerator generator, Class clazz, Object... args) { - return create(generator, clazz, new DefaultServiceRegistry(), args) + return create(generator, clazz, defaultServices(), args) + } + + ServiceLookup defaultServices() { + ServiceLookup services = Mock(ServiceLookup) + _ * services.get(InstantiatorFactory.class) >> { TestUtil.instantiatorFactory() } + return services } protected T create(ClassGenerator generator, Class clazz, ServiceLookup services, Object... args) { diff --git a/subprojects/model-core/src/test/groovy/org/gradle/internal/instantiation/AsmBackedClassGeneratorDecoratedTest.groovy b/subprojects/model-core/src/test/groovy/org/gradle/internal/instantiation/AsmBackedClassGeneratorDecoratedTest.groovy index 03a0a83e4253c..32e8e001462ad 100644 --- a/subprojects/model-core/src/test/groovy/org/gradle/internal/instantiation/AsmBackedClassGeneratorDecoratedTest.groovy +++ b/subprojects/model-core/src/test/groovy/org/gradle/internal/instantiation/AsmBackedClassGeneratorDecoratedTest.groovy @@ -27,9 +27,22 @@ import org.gradle.internal.util.BiFunction import org.gradle.util.ConfigureUtil import spock.lang.Issue +import static org.gradle.internal.instantiation.AsmBackedClassGeneratorTest.* + class AsmBackedClassGeneratorDecoratedTest extends AbstractClassGeneratorSpec { final ClassGenerator generator = AsmBackedClassGenerator.decorateAndInject([], []) + def "can attach nested extensions to object"() { + given: + def bean = create(Bean) + def e1 = bean.extensions.create('one', Bean) + def e2 = e1.extensions.create('two', Bean) + + expect: + bean.one.is(e1) + bean.one.two.is(e2) + } + @Issue("GRADLE-2417") def "can use dynamic object as closure delegate"() { given: diff --git a/subprojects/model-core/src/test/groovy/org/gradle/internal/instantiation/AsmBackedClassGeneratorInjectDecoratedTest.groovy b/subprojects/model-core/src/test/groovy/org/gradle/internal/instantiation/AsmBackedClassGeneratorInjectDecoratedTest.groovy index 998309a7c193e..70b5a49a7ed21 100644 --- a/subprojects/model-core/src/test/groovy/org/gradle/internal/instantiation/AsmBackedClassGeneratorInjectDecoratedTest.groovy +++ b/subprojects/model-core/src/test/groovy/org/gradle/internal/instantiation/AsmBackedClassGeneratorInjectDecoratedTest.groovy @@ -19,8 +19,8 @@ package org.gradle.internal.instantiation import org.gradle.api.plugins.ExtensionAware import org.gradle.api.plugins.ExtensionContainer import org.gradle.internal.service.DefaultServiceRegistry -import org.gradle.internal.service.ServiceLookup import org.gradle.internal.service.ServiceRegistry +import org.gradle.util.TestUtil import javax.inject.Inject import java.lang.annotation.Annotation @@ -30,8 +30,8 @@ import java.lang.reflect.ParameterizedType import java.lang.reflect.Type import static org.gradle.internal.instantiation.AsmBackedClassGeneratorTest.AbstractClassRealizingTwoTypeParameters -import static org.gradle.internal.instantiation.AsmBackedClassGeneratorTest.AbstractClassWithParameterizedTypeParameter import static org.gradle.internal.instantiation.AsmBackedClassGeneratorTest.AbstractClassWithConcreteTypeParameter +import static org.gradle.internal.instantiation.AsmBackedClassGeneratorTest.AbstractClassWithParameterizedTypeParameter import static org.gradle.internal.instantiation.AsmBackedClassGeneratorTest.FinalInjectBean import static org.gradle.internal.instantiation.AsmBackedClassGeneratorTest.NonGetterInjectBean import static org.gradle.internal.instantiation.AsmBackedClassGeneratorTest.PrivateInjectBean @@ -41,7 +41,7 @@ class AsmBackedClassGeneratorInjectDecoratedTest extends AbstractClassGeneratorS def "can inject service using @Inject on a getter method with dummy method body"() { given: - def services = Mock(ServiceLookup) + def services = defaultServices() _ * services.get(Number) >> 12 when: @@ -55,7 +55,7 @@ class AsmBackedClassGeneratorInjectDecoratedTest extends AbstractClassGeneratorS def "can inject service using @Inject on an abstract service getter method"() { given: - def services = Mock(ServiceLookup) + def services = defaultServices() _ * services.get(Number) >> 12 when: @@ -69,7 +69,7 @@ class AsmBackedClassGeneratorInjectDecoratedTest extends AbstractClassGeneratorS def "can inject service using @Inject on a super interface with class type parameter"() { given: - def services = Mock(ServiceLookup) + def services = defaultServices() _ * services.get(Number) >> 12 when: @@ -87,7 +87,7 @@ class AsmBackedClassGeneratorInjectDecoratedTest extends AbstractClassGeneratorS def "can inject services using @Inject on a super interface with type parameter remapping"() { given: - def services = Mock(ServiceLookup) + def services = defaultServices() _ * services.get(_) >> { Type type -> if (type instanceof ParameterizedType) { assert type.rawType == List.class @@ -120,7 +120,7 @@ class AsmBackedClassGeneratorInjectDecoratedTest extends AbstractClassGeneratorS def "can inject service using @Inject on a super interface with parameterized type parameters"() { given: - def services = Mock(ServiceLookup) + def services = defaultServices() _ * services.get(_) >> { Type type -> assert type instanceof ParameterizedType assert type.rawType == List.class @@ -147,7 +147,7 @@ class AsmBackedClassGeneratorInjectDecoratedTest extends AbstractClassGeneratorS def "can inject service using @Inject on an interface getter method"() { given: - def services = Mock(ServiceLookup) + def services = defaultServices() _ * services.get(Number) >> 12 when: @@ -161,7 +161,7 @@ class AsmBackedClassGeneratorInjectDecoratedTest extends AbstractClassGeneratorS def "can optionally set injected service using a service setter method"() { given: - def services = Mock(ServiceLookup) + def services = defaultServices() when: def obj = create(BeanWithMutableServices, services) @@ -171,15 +171,11 @@ class AsmBackedClassGeneratorInjectDecoratedTest extends AbstractClassGeneratorS obj.thing == 12 obj.getThing() == 12 obj.getProperty("thing") == 12 - - and: - 1 * services.find(InstantiatorFactory) >> null - 0 * services._ } def "retains declared generic type of service getter"() { given: - def services = Mock(ServiceLookup) + def services = defaultServices() _ * services.get(_) >> { Type type -> assert type instanceof ParameterizedType assert type.rawType == List.class @@ -205,13 +201,12 @@ class AsmBackedClassGeneratorInjectDecoratedTest extends AbstractClassGeneratorS def "service lookup is lazy and the result is cached"() { given: - def services = Mock(ServiceLookup) + def services = defaultServices() when: def obj = create(BeanWithServices, services) then: - 1 * services.find(InstantiatorFactory) >> null 0 * services._ when: @@ -219,7 +214,7 @@ class AsmBackedClassGeneratorInjectDecoratedTest extends AbstractClassGeneratorS then: 1 * services.get(Number) >> 12 - 0 * services._ + 0 * services.get(Number) when: obj.thing @@ -230,7 +225,7 @@ class AsmBackedClassGeneratorInjectDecoratedTest extends AbstractClassGeneratorS def "can inject service using a custom annotation on getter method with dummy method body"() { given: - def services = Mock(ServiceLookup) + def services = defaultServices() _ * services.get(Number, CustomInject) >> 12 def generator = AsmBackedClassGenerator.decorateAndInject([new CustomAnnotationHandler()], [CustomInject]) @@ -246,7 +241,7 @@ class AsmBackedClassGeneratorInjectDecoratedTest extends AbstractClassGeneratorS def "can inject service using a custom annotation on abstract getter method"() { given: - def services = Mock(ServiceLookup) + def services = defaultServices() _ * services.get(Number, CustomInject) >> 12 def generator = AsmBackedClassGenerator.decorateAndInject([new CustomAnnotationHandler()], [CustomInject]) @@ -273,7 +268,7 @@ class AsmBackedClassGeneratorInjectDecoratedTest extends AbstractClassGeneratorS def "object can provide its own service registry to provide services for injection"() { given: - def services = Mock(ServiceLookup) + def services = defaultServices() when: def obj = create(BeanWithServicesAndServiceRegistry, services) @@ -407,9 +402,10 @@ class BeanWithMutableServices extends BeanWithServices { class BeanWithServicesAndServiceRegistry extends BeanWithServices { ServiceRegistry getServices() { - def services = new DefaultServiceRegistry() - services.add(Number, 12) - return services + def registry = new DefaultServiceRegistry() + registry.add(InstantiatorFactory.class, TestUtil.instantiatorFactory()) + registry.add(Number, 12) + return registry } } diff --git a/subprojects/model-core/src/test/groovy/org/gradle/internal/instantiation/AsmBackedClassGeneratorTest.java b/subprojects/model-core/src/test/groovy/org/gradle/internal/instantiation/AsmBackedClassGeneratorTest.java index 16b0749b3180f..f4d7eada84d3f 100755 --- a/subprojects/model-core/src/test/groovy/org/gradle/internal/instantiation/AsmBackedClassGeneratorTest.java +++ b/subprojects/model-core/src/test/groovy/org/gradle/internal/instantiation/AsmBackedClassGeneratorTest.java @@ -104,7 +104,9 @@ public class AsmBackedClassGeneratorTest { private final ClassGenerator generator = AsmBackedClassGenerator.decorateAndInject(Collections.emptyList(), Collections.>emptyList()); private T newInstance(Class clazz, Object... args) throws Exception { - return newInstance(clazz, new DefaultServiceRegistry(), args); + DefaultServiceRegistry services = new DefaultServiceRegistry(); + services.add(InstantiatorFactory.class, TestUtil.instantiatorFactory()); + return newInstance(clazz, services, args); } private T newInstance(Class clazz, ServiceRegistry services, Object... args) throws Exception { diff --git a/subprojects/model-core/src/test/groovy/org/gradle/internal/instantiation/DependencyInjectionUsingClassGeneratorBackedInstantiatorTest.groovy b/subprojects/model-core/src/test/groovy/org/gradle/internal/instantiation/DependencyInjectionUsingClassGeneratorBackedInstantiatorTest.groovy index 75dab15a4ef27..d3f13bde98963 100644 --- a/subprojects/model-core/src/test/groovy/org/gradle/internal/instantiation/DependencyInjectionUsingClassGeneratorBackedInstantiatorTest.groovy +++ b/subprojects/model-core/src/test/groovy/org/gradle/internal/instantiation/DependencyInjectionUsingClassGeneratorBackedInstantiatorTest.groovy @@ -17,7 +17,9 @@ package org.gradle.internal.instantiation import org.gradle.cache.internal.CrossBuildInMemoryCache import org.gradle.cache.internal.TestCrossBuildInMemoryCacheFactory +import org.gradle.internal.service.DefaultServiceRegistry import org.gradle.internal.service.ServiceLookup +import org.gradle.util.TestUtil import spock.lang.Specification import javax.inject.Inject @@ -25,12 +27,16 @@ import javax.inject.Inject class DependencyInjectionUsingClassGeneratorBackedInstantiatorTest extends Specification { final ClassGenerator classGenerator = AsmBackedClassGenerator.decorateAndInject([], []) final CrossBuildInMemoryCache cache = new TestCrossBuildInMemoryCacheFactory().newCache() - final ServiceLookup services = Mock() + final ServiceLookup services = new DefaultServiceRegistry() final DependencyInjectingInstantiator instantiator = new DependencyInjectingInstantiator(new Jsr330ConstructorSelector(classGenerator, cache), services) + def setup() { + services.add(InstantiatorFactory, TestUtil.instantiatorFactory()) + } + def "injects service using getter injection"() { given: - _ * services.get(String) >> "string" + services.add(String, "string") when: def result = instantiator.newInstance(HasGetterInjection) @@ -41,7 +47,7 @@ class DependencyInjectionUsingClassGeneratorBackedInstantiatorTest extends Speci def "injects service using abstract getter injection"() { given: - _ * services.get(String) >> "string" + services.add(String, "string") when: def result = instantiator.newInstance(AbstractHasGetterInjection) @@ -52,7 +58,7 @@ class DependencyInjectionUsingClassGeneratorBackedInstantiatorTest extends Speci def "constructor can use getter injected service"() { given: - _ * services.get(String) >> "string" + services.add(String, "string") when: def result = instantiator.newInstance(UsesInjectedServiceFromConstructor) @@ -64,7 +70,7 @@ class DependencyInjectionUsingClassGeneratorBackedInstantiatorTest extends Speci def "constructor can receive injected service and parameter"() { given: - _ * services.find(String) >> "string" + services.add(String, "string") when: def result = instantiator.newInstance(HasInjectConstructor, 12) @@ -76,9 +82,7 @@ class DependencyInjectionUsingClassGeneratorBackedInstantiatorTest extends Speci def "can use factory to create instance with injected service and parameter"() { given: - def services = Stub(ServiceLookup) - _ * services.find(String) >> "string" - _ * services.find(_) >> null + services.add(String, "string") when: def factory = instantiator.factoryFor(HasInjectConstructor) @@ -91,9 +95,7 @@ class DependencyInjectionUsingClassGeneratorBackedInstantiatorTest extends Speci def "can use factory to create instance with injected service using getter"() { given: - def services = Stub(ServiceLookup) - _ * services.get(String) >> "string" - _ * services.find(_) >> null + services.add(String, "string") when: def factory = instantiator.factoryFor(HasGetterInjection) From 3e0514f615c6145cc8da2eecb116adf51bd281cc Mon Sep 17 00:00:00 2001 From: Gradleware Git Bot Date: Fri, 1 Mar 2019 02:46:36 +0100 Subject: [PATCH 255/853] Publish 5.3-20190301013223+0000 --- released-versions.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/released-versions.json b/released-versions.json index 4a8b235cfbade..1fc5459084d63 100644 --- a/released-versions.json +++ b/released-versions.json @@ -1,7 +1,7 @@ { "latestReleaseSnapshot": { - "version": "5.3-20190228012955+0000", - "buildTime": "20190228012955+0000" + "version": "5.3-20190301013223+0000", + "buildTime": "20190301013223+0000" }, "latestRc": { "version": "5.2-rc-1", From c113a6ed45f8aecb962e182da42f6e5677f67766 Mon Sep 17 00:00:00 2001 From: "Rodrigo B. de Oliveira" Date: Fri, 1 Mar 2019 04:05:40 -0300 Subject: [PATCH 256/853] Handle application of sibling precompiled script plugins By reducing the precompiled script plugins graph to only contain external plugin references. --- .../PrecompiledScriptPluginAccessorsTest.kt | 44 ++++++++++ ...eneratePrecompiledScriptPluginAccessors.kt | 84 +++++++++++-------- .../plugins/precompiled/tasks/reduceGraph.kt | 62 ++++++++++++++ .../precompiled/tasks/ReduceGraphTest.kt | 45 ++++++++++ 4 files changed, 198 insertions(+), 37 deletions(-) create mode 100644 subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/reduceGraph.kt create mode 100644 subprojects/kotlin-dsl-provider-plugins/src/test/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/ReduceGraphTest.kt diff --git a/subprojects/kotlin-dsl-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPluginAccessorsTest.kt b/subprojects/kotlin-dsl-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPluginAccessorsTest.kt index 23317ecf5b1b1..0f4e828d82b28 100644 --- a/subprojects/kotlin-dsl-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPluginAccessorsTest.kt +++ b/subprojects/kotlin-dsl-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPluginAccessorsTest.kt @@ -155,6 +155,50 @@ class PrecompiledScriptPluginAccessorsTest : AbstractPrecompiledScriptPluginTest compileKotlin() } + @Test + fun `can use type-safe accessors for plugins applied by sibling plugin`() { + + withKotlinDslPlugin() + + withPrecompiledKotlinScript("my-java-library.gradle.kts", """ + plugins { java } + """) + + withPrecompiledKotlinScript("my-java-module.gradle.kts", """ + plugins { id("my-java-library") } + + java { } + + tasks.compileJava { } + """) + + compileKotlin() + } + + @Test + fun `can apply sibling plugin whether it has a plugins block or not`() { + + withKotlinDslPlugin() + + withPrecompiledKotlinScript("no-plugins.gradle.kts", "") + withPrecompiledKotlinScript("java-plugin.gradle.kts", """ + plugins { java } + """) + + withPrecompiledKotlinScript("plugins.gradle.kts", """ + plugins { + id("no-plugins") + id("java-plugin") + } + + java { } + + tasks.compileJava { } + """) + + compileKotlin() + } + @Test fun `generated type-safe accessors are internal`() { diff --git a/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/GeneratePrecompiledScriptPluginAccessors.kt b/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/GeneratePrecompiledScriptPluginAccessors.kt index be19b961234c7..053d2e9bf9431 100644 --- a/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/GeneratePrecompiledScriptPluginAccessors.kt +++ b/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/GeneratePrecompiledScriptPluginAccessors.kt @@ -49,16 +49,16 @@ import org.gradle.kotlin.dsl.concurrent.IO import org.gradle.kotlin.dsl.concurrent.withAsynchronousIO import org.gradle.kotlin.dsl.concurrent.writeFile -import org.gradle.kotlin.dsl.provider.plugins.precompiled.PrecompiledScriptPlugin - import org.gradle.kotlin.dsl.precompile.PrecompiledScriptDependenciesResolver +import org.gradle.kotlin.dsl.provider.plugins.precompiled.PrecompiledScriptPlugin + import org.gradle.kotlin.dsl.support.KotlinScriptType import org.gradle.kotlin.dsl.support.serviceOf import org.gradle.plugin.management.internal.DefaultPluginRequests -import org.gradle.plugin.management.internal.PluginRequestInternal import org.gradle.plugin.management.internal.PluginRequests + import org.gradle.plugin.use.PluginDependenciesSpec import org.gradle.plugin.use.internal.PluginRequestApplicator import org.gradle.plugin.use.internal.PluginRequestCollector @@ -125,9 +125,9 @@ open class GeneratePrecompiledScriptPluginAccessors : ClassPathSensitiveCodeGene private fun IO.generateTypeSafeAccessorsFor(projectPlugins: List) { - scriptPluginPluginsFor(projectPlugins) + resolvePluginGraphOf(projectPlugins) .groupBy { - UniquePluginRequests(it.plugins) + it.plugins }.let { projectSchemaImpliedByPluginGroups(it) }.forEach { (projectSchema, scriptPlugins) -> @@ -141,6 +141,22 @@ open class GeneratePrecompiledScriptPluginAccessors : ClassPathSensitiveCodeGene } } + private + fun resolvePluginGraphOf(projectPlugins: List): Sequence { + + val scriptPluginsById = scriptPluginPluginsFor(projectPlugins).associateBy { + it.scriptPlugin.id + } + + val pluginGraph = plugins.associate { + it.id to (scriptPluginsById[it.id]?.plugins ?: emptyList()) + } + + return reduceGraph(pluginGraph).asSequence().mapNotNull { (id, plugins) -> + scriptPluginsById[id]?.copy(plugins = plugins.toList()) + } + } + private fun scriptPluginPluginsFor(projectPlugins: List) = sequence { val loader = createPluginsClassLoader() @@ -166,13 +182,16 @@ open class GeneratePrecompiledScriptPluginAccessors : ClassPathSensitiveCodeGene return ScriptPluginPlugins( plugin, - collectPluginRequestsOf(plugin) + collectPluginRequestsOf(plugin).map { + // TODO:kotlin-dsl validate plugin request version, apply false, etc + it.id.id + } ) } private fun ClassLoader.collectPluginRequestsOf(plugin: PrecompiledScriptPlugin): PluginRequests = - PluginRequestCollector(scriptSourceFor(plugin)).run { + pluginRequestCollectorFor(plugin).run { loadClass(plugin.compiledScriptTypeName) .getConstructor(PluginDependenciesSpec::class.java) @@ -181,9 +200,10 @@ open class GeneratePrecompiledScriptPluginAccessors : ClassPathSensitiveCodeGene pluginRequests } + private - fun compiledScriptClassFile(plugin: PrecompiledScriptPlugin) = - plugin.compiledScriptTypeName.replace('.', '/') + ".class" + fun pluginRequestCollectorFor(plugin: PrecompiledScriptPlugin) = + PluginRequestCollector(scriptSourceFor(plugin)) private fun scriptSourceFor(plugin: PrecompiledScriptPlugin) = @@ -191,6 +211,10 @@ open class GeneratePrecompiledScriptPluginAccessors : ClassPathSensitiveCodeGene BasicTextResourceLoader().loadFile("Precompiled script plugin", plugin.scriptFile) ) + private + fun compiledScriptClassFile(plugin: PrecompiledScriptPlugin) = + plugin.compiledScriptTypeName.replace('.', '/') + ".class" + private fun selectProjectPlugins() = plugins.filter { it.scriptType == KotlinScriptType.PROJECT } @@ -213,13 +237,13 @@ open class GeneratePrecompiledScriptPluginAccessors : ClassPathSensitiveCodeGene private fun projectSchemaImpliedByPluginGroups( - pluginGroupsPerRequests: Map> + pluginGroupsPerRequests: Map, List> ): Map> { val schemaBuilder = SyntheticProjectSchemaBuilder(temporaryDir, (classPathFiles + runtimeClassPathFiles).files) return pluginGroupsPerRequests.flatMap { (uniquePluginRequests, scriptPlugins) -> try { - val schema = schemaBuilder.schemaFor(uniquePluginRequests.plugins) + val schema = schemaBuilder.schemaFor(pluginRequestsFor(uniquePluginRequests, scriptPlugins.first().scriptPlugin)) val hashedSchema = HashedProjectSchema(schema) scriptPlugins.map { hashedSchema to it } } catch (error: Throwable) { @@ -232,6 +256,17 @@ open class GeneratePrecompiledScriptPluginAccessors : ClassPathSensitiveCodeGene ) } + private + fun pluginRequestsFor(pluginIds: List, plugin: PrecompiledScriptPlugin): PluginRequests = + pluginRequestCollectorFor(plugin).run { + createSpec(1).apply { + pluginIds.forEach { + id(it) + } + } + pluginRequests + } + private fun reportProjectSchemaError(plugins: List, error: Throwable) { logger.warn( @@ -350,32 +385,7 @@ data class HashedProjectSchema( internal data class ScriptPluginPlugins( val scriptPlugin: PrecompiledScriptPlugin, - val plugins: PluginRequests -) - - -private -class UniquePluginRequests(val plugins: PluginRequests) { - - val applications = plugins.map { it.toPluginApplication() } - - override fun equals(other: Any?): Boolean = other is UniquePluginRequests && applications == other.applications - - override fun hashCode(): Int = applications.hashCode() -} - - -private -fun PluginRequestInternal.toPluginApplication() = PluginApplication( - id.id, version, isApply -) - - -internal -data class PluginApplication( - val id: String, - val version: String?, - val apply: Boolean? + val plugins: List ) diff --git a/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/reduceGraph.kt b/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/reduceGraph.kt new file mode 100644 index 0000000000000..2b18931848269 --- /dev/null +++ b/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/reduceGraph.kt @@ -0,0 +1,62 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.kotlin.dsl.provider.plugins.precompiled.tasks + + +/** + * Reduces the given [graph] so that it only includes external node references, + * e.g.: + * ``` + * reduce({a: [b, c], b: [e1], c: [d], d: [e2]}) => {a: [e1, e2], b: [e1], c: [e2], d: [e2]} + * ``` + */ +internal +fun reduceGraph(graph: Map>): Map> { + + val result = mutableMapOf>() + + val reducing = hashSetOf() + + fun reduce(node: V, refs: Iterable): Set { + + result[node]?.let { + return it + } + + val externalNodes = mutableSetOf() + result[node] = externalNodes + + reducing.add(node) + for (ref in refs) { + if (ref in reducing) { + continue + } + graph[ref]?.let { + externalNodes.addAll(reduce(ref, it)) + } ?: externalNodes.add(ref) + } + reducing.remove(node) + + return externalNodes + } + + for ((node, refs) in graph) { + reduce(node, refs) + } + + return result +} diff --git a/subprojects/kotlin-dsl-provider-plugins/src/test/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/ReduceGraphTest.kt b/subprojects/kotlin-dsl-provider-plugins/src/test/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/ReduceGraphTest.kt new file mode 100644 index 0000000000000..8d00a1f5e39cd --- /dev/null +++ b/subprojects/kotlin-dsl-provider-plugins/src/test/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/ReduceGraphTest.kt @@ -0,0 +1,45 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.kotlin.dsl.provider.plugins.precompiled.tasks + +import org.hamcrest.MatcherAssert.assertThat +import org.hamcrest.Matchers.equalTo + +import org.junit.Test + + +class ReduceGraphTest { + + @Test + fun `only external node references are left in the graph`() { + + assertThat( + reduceGraph(mapOf( + "a" to listOf("b", "c"), + "b" to listOf("e1"), + "c" to listOf("d"), + "d" to listOf("b", "e2") + )), + equalTo(mapOf( + "a" to setOf("e1", "e2"), + "b" to setOf("e1"), + "c" to setOf("e1", "e2"), + "d" to setOf("e1", "e2") + )) + ) + } +} From ef78754a0b6a0cea8648c9a0c427d3e2fc1671f9 Mon Sep 17 00:00:00 2001 From: "Rodrigo B. de Oliveira" Date: Fri, 1 Mar 2019 04:21:45 -0300 Subject: [PATCH 257/853] Fix refactoring gone wrong --- .../dsl/integration/PrecompiledScriptPluginIntegrationTest.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subprojects/kotlin-dsl-integ-tests/src/integTest/kotlin/org/gradle/kotlin/dsl/integration/PrecompiledScriptPluginIntegrationTest.kt b/subprojects/kotlin-dsl-integ-tests/src/integTest/kotlin/org/gradle/kotlin/dsl/integration/PrecompiledScriptPluginIntegrationTest.kt index 82ecb13cd272f..a33e2e69cc226 100644 --- a/subprojects/kotlin-dsl-integ-tests/src/integTest/kotlin/org/gradle/kotlin/dsl/integration/PrecompiledScriptPluginIntegrationTest.kt +++ b/subprojects/kotlin-dsl-integ-tests/src/integTest/kotlin/org/gradle/kotlin/dsl/integration/PrecompiledScriptPluginIntegrationTest.kt @@ -23,7 +23,7 @@ class PrecompiledScriptPluginIntegrationTest : AbstractPluginIntegrationTest() { $repositoriesBlock """) - withPrecompiledKotlinScript("plugin-without-package.gradle.kts", "") + withPrecompiledKotlinScript("plugin-without-package.gradle.kts", "\n") withPrecompiledKotlinScript("plugins/plugin-with-package.gradle.kts", """ package plugins """) From 22d42cc5999e67184bd1bd6b9034182f5124e6da Mon Sep 17 00:00:00 2001 From: "Rodrigo B. de Oliveira" Date: Fri, 1 Mar 2019 04:42:29 -0300 Subject: [PATCH 258/853] Update expected generated API extensions hash after latest changes To the generated Kotlin source code header. --- .../org/gradle/kotlin/dsl/codegen/GradleApiExtensionsTest.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subprojects/kotlin-dsl/src/test/kotlin/org/gradle/kotlin/dsl/codegen/GradleApiExtensionsTest.kt b/subprojects/kotlin-dsl/src/test/kotlin/org/gradle/kotlin/dsl/codegen/GradleApiExtensionsTest.kt index 1b9c961064fd8..03e5986f98aec 100644 --- a/subprojects/kotlin-dsl/src/test/kotlin/org/gradle/kotlin/dsl/codegen/GradleApiExtensionsTest.kt +++ b/subprojects/kotlin-dsl/src/test/kotlin/org/gradle/kotlin/dsl/codegen/GradleApiExtensionsTest.kt @@ -65,7 +65,7 @@ class GradleApiExtensionsTest : TestWithClassPath() { ClassAndGroovyNamedArguments::class ) { - assertGeneratedJarHash("d873264108ff96eec77a33fc1084743b") + assertGeneratedJarHash("92614891520da2bd5eb0e4c28c672a39") } } From f6aed9b2db7f2140649fa1acfb31db49ab39b8b9 Mon Sep 17 00:00:00 2001 From: Paul Merlin Date: Fri, 1 Mar 2019 09:16:42 +0100 Subject: [PATCH 259/853] Do not apply `kotlin-dsl` plugin to :buildSrc The :buildSrc root project doesn't need it, only subprojects do. And it adds unnecessary overhead. Signed-off-by: Paul Merlin --- buildSrc/build.gradle.kts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts index bb6ce99c659c9..3fdcd5722c043 100644 --- a/buildSrc/build.gradle.kts +++ b/buildSrc/build.gradle.kts @@ -20,7 +20,8 @@ import java.io.File import java.util.Properties plugins { - `kotlin-dsl` + `java` + `kotlin-dsl` apply false id("org.gradle.kotlin-dsl.ktlint-convention") version "0.2.3" apply false } @@ -181,7 +182,7 @@ fun Project.applyGroovyProjectConventions() { } tasks.withType().configureEach { - if (JavaVersion.current().isJava9Compatible()) { + if (JavaVersion.current().isJava9Compatible) { //allow ProjectBuilder to inject legacy types into the system classloader jvmArgs("--add-opens", "java.base/java.lang=ALL-UNNAMED") jvmArgs("--illegal-access=deny") @@ -207,7 +208,7 @@ fun Project.applyKotlinProjectConventions() { apply(plugin = "org.gradle.kotlin-dsl.ktlint-convention") plugins.withType { - kotlinDslPluginOptions { + configure { experimentalWarning.set(false) } } From ce5990a1e2eaf400303f155b7e2f653e681b80cd Mon Sep 17 00:00:00 2001 From: Paul Merlin Date: Fri, 1 Mar 2019 10:33:31 +0100 Subject: [PATCH 260/853] Upgrade ktlint-convention plugin Signed-off-by: Paul Merlin --- buildSrc/build.gradle.kts | 4 +++- .../subprojects/kotlin-dsl/kotlin-dsl.gradle.kts | 2 +- .../PrecompiledScriptPluginIntegrationTest.kt | 2 +- .../accessors/ProjectAccessorsClassPathTest.kt | 15 +++++---------- 4 files changed, 10 insertions(+), 13 deletions(-) diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts index 3fdcd5722c043..aa9cc65938783 100644 --- a/buildSrc/build.gradle.kts +++ b/buildSrc/build.gradle.kts @@ -22,7 +22,7 @@ import java.util.Properties plugins { `java` `kotlin-dsl` apply false - id("org.gradle.kotlin-dsl.ktlint-convention") version "0.2.3" apply false + id("org.gradle.kotlin-dsl.ktlint-convention") version "0.3.0" apply false } subprojects { @@ -219,6 +219,8 @@ fun Project.applyKotlinProjectConventions() { // verification but unfortunately the filter doesn't seem to // have an effect so :/ ignoreFailures.set(true) + // because of the above, the output is cluttered, disable console output + outputToConsole.set(false) filter { exclude("**/generated-sources/**") } diff --git a/buildSrc/subprojects/kotlin-dsl/kotlin-dsl.gradle.kts b/buildSrc/subprojects/kotlin-dsl/kotlin-dsl.gradle.kts index ec4c394fd215b..2f1429517ca5c 100644 --- a/buildSrc/subprojects/kotlin-dsl/kotlin-dsl.gradle.kts +++ b/buildSrc/subprojects/kotlin-dsl/kotlin-dsl.gradle.kts @@ -7,7 +7,7 @@ dependencies { implementation(kotlin("stdlib-jdk8")) implementation(kotlin("reflect")) - implementation("org.gradle.kotlin:gradle-kotlin-dsl-conventions:0.2.3") + implementation("org.gradle.kotlin:gradle-kotlin-dsl-conventions:0.3.0") implementation("com.gradle.publish:plugin-publish-plugin:0.10.0") implementation("com.thoughtworks.qdox:qdox:2.0-M9") diff --git a/subprojects/kotlin-dsl-integ-tests/src/integTest/kotlin/org/gradle/kotlin/dsl/integration/PrecompiledScriptPluginIntegrationTest.kt b/subprojects/kotlin-dsl-integ-tests/src/integTest/kotlin/org/gradle/kotlin/dsl/integration/PrecompiledScriptPluginIntegrationTest.kt index a33e2e69cc226..ab37d09a7b9c4 100644 --- a/subprojects/kotlin-dsl-integ-tests/src/integTest/kotlin/org/gradle/kotlin/dsl/integration/PrecompiledScriptPluginIntegrationTest.kt +++ b/subprojects/kotlin-dsl-integ-tests/src/integTest/kotlin/org/gradle/kotlin/dsl/integration/PrecompiledScriptPluginIntegrationTest.kt @@ -17,7 +17,7 @@ class PrecompiledScriptPluginIntegrationTest : AbstractPluginIntegrationTest() { withBuildScript(""" plugins { `kotlin-dsl` - id("org.gradle.kotlin-dsl.ktlint-convention") version "0.2.3" + id("org.gradle.kotlin-dsl.ktlint-convention") version "0.3.0" } $repositoriesBlock diff --git a/subprojects/kotlin-dsl/src/test/kotlin/org/gradle/kotlin/dsl/accessors/ProjectAccessorsClassPathTest.kt b/subprojects/kotlin-dsl/src/test/kotlin/org/gradle/kotlin/dsl/accessors/ProjectAccessorsClassPathTest.kt index 0fdf409aa9df6..0d4087ec03e41 100644 --- a/subprojects/kotlin-dsl/src/test/kotlin/org/gradle/kotlin/dsl/accessors/ProjectAccessorsClassPathTest.kt +++ b/subprojects/kotlin-dsl/src/test/kotlin/org/gradle/kotlin/dsl/accessors/ProjectAccessorsClassPathTest.kt @@ -81,14 +81,10 @@ class ProjectAccessorsClassPathTest : AbstractDslTest() { entry Unit>("function1"), entry Boolean>("function2") ), - containerElements = listOf( - ), - conventions = listOf( - ), - tasks = listOf( - ), - configurations = listOf( - ) + containerElements = listOf(), + conventions = listOf(), + tasks = listOf(), + configurations = listOf() ) val function0 = mock<() -> Unit>() @@ -161,8 +157,7 @@ class ProjectAccessorsClassPathTest : AbstractDslTest() { tasks = listOf( ProjectSchemaEntry(SchemaType.of(), "task", schemaTypeFor("CustomTask")) ), - configurations = listOf( - ) + configurations = listOf() ) val srcDir = newFolder("src") From 655df825241acd9cd9feb67d92b31c77d6b87c28 Mon Sep 17 00:00:00 2001 From: Paul Merlin Date: Fri, 1 Mar 2019 10:49:27 +0100 Subject: [PATCH 261/853] Add diagnostic logs to test Signed-off-by: Paul Merlin --- .../PrecompiledScriptPluginAccessorsTest.kt | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/subprojects/kotlin-dsl-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPluginAccessorsTest.kt b/subprojects/kotlin-dsl-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPluginAccessorsTest.kt index 0f4e828d82b28..c9c455892b936 100644 --- a/subprojects/kotlin-dsl-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPluginAccessorsTest.kt +++ b/subprojects/kotlin-dsl-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPluginAccessorsTest.kt @@ -152,6 +152,17 @@ class PrecompiledScriptPluginAccessorsTest : AbstractPrecompiledScriptPluginTest """) + build("generatePrecompiledScriptPluginAccessors") + existing("build/generated-sources/kotlin-dsl-accessors/kotlin").walk().filter { it.isFile }.forEach { + println("// CONTENT OF $it") + it.useLines { lines -> + lines.forEachIndexed { index, line -> + println("${index + 1}: $line") + } + } + println("================") + } + compileKotlin() } From 5307eee404a395a273a6edd5cb9f2440ab283b83 Mon Sep 17 00:00:00 2001 From: Louis Jacomet Date: Thu, 28 Feb 2019 12:18:12 +0100 Subject: [PATCH 262/853] Use interface instead of implementation When mapping dependencies to Maven scope, rely on the Maven specific UsageContext sub interface instead of using the concrete implementation. --- .../MavenPublishFeaturesJavaIntegTest.groovy | 25 ++++++++++++------- .../publication/DefaultMavenPublication.java | 9 +++---- 2 files changed, 20 insertions(+), 14 deletions(-) diff --git a/subprojects/maven/src/integTest/groovy/org/gradle/api/publish/maven/MavenPublishFeaturesJavaIntegTest.groovy b/subprojects/maven/src/integTest/groovy/org/gradle/api/publish/maven/MavenPublishFeaturesJavaIntegTest.groovy index 1c20c9a39d6e9..47b640ed9b3bc 100644 --- a/subprojects/maven/src/integTest/groovy/org/gradle/api/publish/maven/MavenPublishFeaturesJavaIntegTest.groovy +++ b/subprojects/maven/src/integTest/groovy/org/gradle/api/publish/maven/MavenPublishFeaturesJavaIntegTest.groovy @@ -187,8 +187,12 @@ class MavenPublishFeaturesJavaIntegTest extends AbstractMavenPublishFeaturesJava components.java.addVariantsFromConfiguration(configurations.optionalFeatureRuntimeElements, { it.mapToMavenScope('compile', true) }) - artifacts { - optionalFeatureRuntimeElements file:file("\$buildDir/$optionalFeatureFileName"), builtBy:'touchFile' + artifacts { + if ('$classifier' == 'null') { + optionalFeatureRuntimeElements file:file("\$buildDir/$optionalFeatureFileName"), builtBy:'touchFile' + } else { + optionalFeatureRuntimeElements file:file("\$buildDir/$optionalFeatureFileName"), builtBy:'touchFile', classifier: '$classifier' + } } task touchFile { @@ -212,7 +216,7 @@ class MavenPublishFeaturesJavaIntegTest extends AbstractMavenPublishFeaturesJava javaLibrary.withClassifiedArtifact("optional-feature", "jar") javaLibrary.mavenModule.assertArtifactsPublished( "publishTest-1.9.jar" , - optionalFeatureFileName , + "publishTest-1.9-optional-feature.jar" , "publishTest-1.9.pom", "publishTest-1.9.module") javaLibrary.parsedModuleMetadata.variant("apiElements") { @@ -224,7 +228,7 @@ class MavenPublishFeaturesJavaIntegTest extends AbstractMavenPublishFeaturesJava noMoreDependencies() } javaLibrary.parsedModuleMetadata.variant("optionalFeatureRuntimeElements") { - assert files*.name == [optionalFeatureFileName] + assert files*.name == ["publishTest-1.9-optional-feature.jar"] dependency('org', 'optionaldep', '1.0') noMoreDependencies() } @@ -236,7 +240,7 @@ class MavenPublishFeaturesJavaIntegTest extends AbstractMavenPublishFeaturesJava resolveRuntimeArtifacts(javaLibrary) { optionalFeatureCapabilities << "org:optional-feature:1.0" withModuleMetadata { - expectFiles "publishTest-1.9.jar", "optionaldep-1.0.jar", optionalFeatureFileName + expectFiles "publishTest-1.9.jar", "optionaldep-1.0.jar", "publishTest-1.9-optional-feature.jar" } withoutModuleMetadata { shouldFail { @@ -248,10 +252,13 @@ class MavenPublishFeaturesJavaIntegTest extends AbstractMavenPublishFeaturesJava } where: - id | optionalFeatureFileName | failureText - "with a classifier" | "publishTest-1.9-optional-feature.jar" | null - "with an arbitrary name" | "optional-feature-1.9.jar" | "Invalid publication 'maven': multiple artifacts with the identical extension and classifier ('jar', 'null')" - "with the same name " | "publishTest-1.9.jar" | "Invalid publication 'maven': multiple artifacts with the identical extension and classifier ('jar', 'null')" + id | optionalFeatureFileName | classifier | failureText + "with the same name and an implicit classifier" | "publishTest-1.9-optional-feature.jar" | null | null + "with an arbitrary name and no classifier" | "optional-feature-1.9.jar" | null | "Invalid publication 'maven': multiple artifacts with the identical extension and classifier ('jar', 'null')" + "with an arbitrary name and a classifier" | "other-1.9.jar" | "optional-feature" | null + "with an arbitrary name with an implicit classifier" | "other-1.9-optional-feature.jar" | null | null + "with the same name and no classifier" | "publishTest-1.9.jar" | null | "Invalid publication 'maven': multiple artifacts with the identical extension and classifier ('jar', 'null')" + "with the same name and a classifier" | "publishTest-1.9.jar" | "optional-feature" | null } diff --git a/subprojects/maven/src/main/java/org/gradle/api/publish/maven/internal/publication/DefaultMavenPublication.java b/subprojects/maven/src/main/java/org/gradle/api/publish/maven/internal/publication/DefaultMavenPublication.java index 24960a5f8e542..638e6a12acf88 100644 --- a/subprojects/maven/src/main/java/org/gradle/api/publish/maven/internal/publication/DefaultMavenPublication.java +++ b/subprojects/maven/src/main/java/org/gradle/api/publish/maven/internal/publication/DefaultMavenPublication.java @@ -54,7 +54,6 @@ import org.gradle.api.internal.component.UsageContext; import org.gradle.api.internal.file.FileCollectionFactory; import org.gradle.api.internal.java.JavaLibraryPlatform; -import org.gradle.api.internal.java.usagecontext.FeatureConfigurationUsageContext; import org.gradle.api.internal.project.ProjectInternal; import org.gradle.api.logging.Logger; import org.gradle.api.logging.Logging; @@ -349,8 +348,8 @@ private List getSortedUsageContexts() { } private Set dependenciesFor(UsageContext usage) { - if (usage instanceof FeatureConfigurationUsageContext) { - MavenPublishingAwareContext.ScopeMapping mapping = ((FeatureConfigurationUsageContext) usage).getScopeMapping(); + if (usage instanceof MavenPublishingAwareContext) { + MavenPublishingAwareContext.ScopeMapping mapping = ((MavenPublishingAwareContext) usage).getScopeMapping(); switch (mapping) { case compile: return apiDependencies; @@ -371,8 +370,8 @@ private Set dependenciesFor(UsageContext usage) { } private Set dependencyConstraintsFor(UsageContext usage) { - if (usage instanceof FeatureConfigurationUsageContext) { - MavenPublishingAwareContext.ScopeMapping mapping = ((FeatureConfigurationUsageContext) usage).getScopeMapping(); + if (usage instanceof MavenPublishingAwareContext) { + MavenPublishingAwareContext.ScopeMapping mapping = ((MavenPublishingAwareContext) usage).getScopeMapping(); switch (mapping) { case compile: case compile_optional: From efe6c200f835e871292bf464ea166f52ebc28258 Mon Sep 17 00:00:00 2001 From: Louis Jacomet Date: Thu, 28 Feb 2019 12:21:08 +0100 Subject: [PATCH 263/853] Mapping of feature variants for the Ivy world When using feature variants in the Ivy world, there was no special handling. This mostly meant that any added configuration based on the feature variant ended up being extended by the default Ivy configuration. Since the goal is to model optional features, such extension makes little sense. This change set improves the situation yb decoupling the Maven scope mapping from the optional status. The optional status is now available to Ivy publication and is used to control whether the `default` configuration should extend the created configuration. --- .../ConfigurationVariantDetails.java | 15 +++- .../component/IvyPublishingAwareContext.java | 22 ++++++ .../ivy/IvyPublishJavaIntegTest.groovy | 73 +++++++++++++++++++ .../publication/DefaultIvyPublication.java | 12 ++- .../MavenPublishFeaturesJavaIntegTest.groovy | 28 +++++-- .../ConfigurationVariantMapping.java | 8 +- .../FeatureConfigurationUsageContext.java | 10 ++- .../JavaConfigurationVariantMapping.java | 5 +- 8 files changed, 157 insertions(+), 16 deletions(-) create mode 100644 subprojects/core/src/main/java/org/gradle/api/internal/component/IvyPublishingAwareContext.java diff --git a/subprojects/core-api/src/main/java/org/gradle/api/component/ConfigurationVariantDetails.java b/subprojects/core-api/src/main/java/org/gradle/api/component/ConfigurationVariantDetails.java index 78f7850b945e1..98e56a6356536 100644 --- a/subprojects/core-api/src/main/java/org/gradle/api/component/ConfigurationVariantDetails.java +++ b/subprojects/core-api/src/main/java/org/gradle/api/component/ConfigurationVariantDetails.java @@ -38,6 +38,16 @@ public interface ConfigurationVariantDetails { */ void skip(); + /** + * Provides information about the optional status of this added configuration variant. + * + *
      + *
    • For the Maven world, this means that dependencies will be declared as {@code optional}.
    • + *
    • For the Ivy world, this means that configuration marked optional will not be extended by the {@code default} configuration.
    • + *
    + */ + void markOptional(); + /** * Provides information about how to publish to a Maven POM file. If * nothing is said, Gradle will publish all dependencies from this @@ -57,9 +67,8 @@ public interface ConfigurationVariantDetails { * * The mapping only applies to dependencies: dependency constraints will * systematically be published as import scope. + * @param scope the Maven scope to use for dependencies found in this configuration variant * - * @param scope the Maven scope to use for dependencies found in this configuration variant - * @param optional true if the dependencies found in this configuration variant should be published as optional */ - void mapToMavenScope(String scope, boolean optional); + void mapToMavenScope(String scope); } diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/component/IvyPublishingAwareContext.java b/subprojects/core/src/main/java/org/gradle/api/internal/component/IvyPublishingAwareContext.java new file mode 100644 index 0000000000000..02d4bfa69e539 --- /dev/null +++ b/subprojects/core/src/main/java/org/gradle/api/internal/component/IvyPublishingAwareContext.java @@ -0,0 +1,22 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.api.internal.component; + +public interface IvyPublishingAwareContext extends UsageContext { + + boolean isOptional(); +} diff --git a/subprojects/ivy/src/integTest/groovy/org/gradle/api/publish/ivy/IvyPublishJavaIntegTest.groovy b/subprojects/ivy/src/integTest/groovy/org/gradle/api/publish/ivy/IvyPublishJavaIntegTest.groovy index 79247df04323e..bee5d4255159c 100644 --- a/subprojects/ivy/src/integTest/groovy/org/gradle/api/publish/ivy/IvyPublishJavaIntegTest.groovy +++ b/subprojects/ivy/src/integTest/groovy/org/gradle/api/publish/ivy/IvyPublishJavaIntegTest.groovy @@ -978,6 +978,79 @@ class IvyPublishJavaIntegTest extends AbstractIvyPublishIntegTest { true | true | true } + @Unroll + def "can publish feature variants (optional: #optional)"() { + requiresExternalDependencies = true + + given: + createBuildScripts(""" + configurations { + optionalFeatureImplementation + optionalFeatureRuntimeElements { + extendsFrom optionalFeatureImplementation + canBeResolved = false + canBeConsumed = true + attributes { + attribute(Usage.USAGE_ATTRIBUTE, project.objects.named(Usage, Usage.JAVA_RUNTIME_JARS)) + } + outgoing.capability("org:optional-feature:\${version}") + } + compileClasspath.extendsFrom(optionalFeatureImplementation) + } + + dependencies { + optionalFeatureImplementation 'org.slf4j:slf4j-api:1.7.26' + } + + artifacts { + optionalFeatureRuntimeElements file:file("\$buildDir/other-artifact.jar"), builtBy:'touchFile', classifier: 'optional-feature' + } + + task touchFile { + doLast { + file("\$buildDir/other-artifact.jar") << "test" + } + } + + components.java.addVariantsFromConfiguration(configurations.optionalFeatureRuntimeElements) { + if ($optional) it.markOptional() + } + + publishing { + repositories { + ivy { url "${mavenRepo.uri}" } + } + publications { + ivy(IvyPublication) { + from components.java + } + } + } +""") + + when: + succeeds "publish" + + then: + with(javaLibrary.parsedIvy) { + configurations.keySet() == ["default", "compile", "runtime", "optionalFeatureRuntimeElements"] as Set + if (optional) { + configurations["default"].extend == ["runtime", "compile"] as Set + } else { + configurations["default"].extend == ["runtime", "compile", "optionalFeatureRuntimeElements"] as Set + } + configurations["runtime"].extend == null + configurations["optionalFeatureRuntimeElements"].extend == null + + expectArtifact("publishTest", "jar").hasConf(["compile"]) + expectArtifact("publishTest", "jar", "optional-feature").hasConf(["optionalFeatureRuntimeElements"]) + assertConfigurationDependsOn("optionalFeatureRuntimeElements", "org.slf4j:slf4j-api:1.7.26") + } + + where: + optional << [true, false] + } + private void createBuildScripts(def append) { settingsFile << "rootProject.name = 'publishTest' " diff --git a/subprojects/ivy/src/main/java/org/gradle/api/publish/ivy/internal/publication/DefaultIvyPublication.java b/subprojects/ivy/src/main/java/org/gradle/api/publish/ivy/internal/publication/DefaultIvyPublication.java index d2a9e1d417039..a7da3c2c59158 100644 --- a/subprojects/ivy/src/main/java/org/gradle/api/publish/ivy/internal/publication/DefaultIvyPublication.java +++ b/subprojects/ivy/src/main/java/org/gradle/api/publish/ivy/internal/publication/DefaultIvyPublication.java @@ -44,6 +44,7 @@ import org.gradle.api.internal.artifacts.ivyservice.projectmodule.ProjectDependencyPublicationResolver; import org.gradle.api.internal.attributes.ImmutableAttributes; import org.gradle.api.internal.attributes.ImmutableAttributesFactory; +import org.gradle.api.internal.component.IvyPublishingAwareContext; import org.gradle.api.internal.component.SoftwareComponentInternal; import org.gradle.api.internal.component.UsageContext; import org.gradle.api.internal.file.FileCollectionFactory; @@ -248,11 +249,16 @@ private void populateFromComponent() { for (UsageContext usageContext : getSortedUsageContexts()) { String conf = mapUsage(usageContext.getName()); configurations.maybeCreate(conf); - configurations.getByName("default").extend(conf); + if (usageContext instanceof IvyPublishingAwareContext) { + if (!((IvyPublishingAwareContext) usageContext).isOptional()) { + configurations.getByName("default").extend(conf); + } + } else { + configurations.getByName("default").extend(conf); + } for (PublishArtifact publishArtifact : usageContext.getArtifacts()) { - if (!artifactsOverridden && !seenArtifacts.contains(publishArtifact)) { - seenArtifacts.add(publishArtifact); + if (!artifactsOverridden && seenArtifacts.add(publishArtifact)) { artifact(publishArtifact).setConf(conf); } } diff --git a/subprojects/maven/src/integTest/groovy/org/gradle/api/publish/maven/MavenPublishFeaturesJavaIntegTest.groovy b/subprojects/maven/src/integTest/groovy/org/gradle/api/publish/maven/MavenPublishFeaturesJavaIntegTest.groovy index 47b640ed9b3bc..7df723ae3b1e7 100644 --- a/subprojects/maven/src/integTest/groovy/org/gradle/api/publish/maven/MavenPublishFeaturesJavaIntegTest.groovy +++ b/subprojects/maven/src/integTest/groovy/org/gradle/api/publish/maven/MavenPublishFeaturesJavaIntegTest.groovy @@ -44,7 +44,10 @@ class MavenPublishFeaturesJavaIntegTest extends AbstractMavenPublishFeaturesJava optionalFeatureImplementation 'org:optionaldep:1.0' } - components.java.addVariantsFromConfiguration(configurations.optionalFeatureRuntimeElements, { it.mapToMavenScope('compile', true) }) + components.java.addVariantsFromConfiguration(configurations.optionalFeatureRuntimeElements) { + it.mapToMavenScope('compile') + it.markOptional() + } """ when: @@ -124,8 +127,14 @@ class MavenPublishFeaturesJavaIntegTest extends AbstractMavenPublishFeaturesJava optionalFeature2Implementation 'org:optionaldep2-g2:1.0' } - components.java.addVariantsFromConfiguration(configurations.optionalFeature1RuntimeElements, { it.mapToMavenScope('compile', true) }) - components.java.addVariantsFromConfiguration(configurations.optionalFeature2RuntimeElements, { it.mapToMavenScope('compile', true) }) + components.java.addVariantsFromConfiguration(configurations.optionalFeature1RuntimeElements) { + it.mapToMavenScope('compile') + it.markOptional() + } + components.java.addVariantsFromConfiguration(configurations.optionalFeature2RuntimeElements) { + it.mapToMavenScope('compile') + it.markOptional() + } """ when: @@ -185,7 +194,10 @@ class MavenPublishFeaturesJavaIntegTest extends AbstractMavenPublishFeaturesJava optionalFeatureImplementation 'org:optionaldep:1.0' } - components.java.addVariantsFromConfiguration(configurations.optionalFeatureRuntimeElements, { it.mapToMavenScope('compile', true) }) + components.java.addVariantsFromConfiguration(configurations.optionalFeatureRuntimeElements) { + it.mapToMavenScope('compile') + it.markOptional() + } artifacts { if ('$classifier' == 'null') { @@ -285,7 +297,10 @@ class MavenPublishFeaturesJavaIntegTest extends AbstractMavenPublishFeaturesJava optionalFeatureImplementation 'org:optionaldep:1.0' } - components.java.addVariantsFromConfiguration(configurations.optionalFeatureRuntimeElements, { it.mapToMavenScope('compile', true) }) + components.java.addVariantsFromConfiguration(configurations.optionalFeatureRuntimeElements) { + it.mapToMavenScope('compile') + it.markOptional() + } def alt = configurations.optionalFeatureRuntimeElements.outgoing.variants.create("alternate") alt.attributes { @@ -366,7 +381,8 @@ class MavenPublishFeaturesJavaIntegTest extends AbstractMavenPublishFeaturesJava if (it.configurationVariant.name != 'alternate') { it.skip() } else { - it.mapToMavenScope('compile', true) + it.mapToMavenScope('compile') + it.markOptional() } } diff --git a/subprojects/plugins/src/main/java/org/gradle/api/internal/java/usagecontext/ConfigurationVariantMapping.java b/subprojects/plugins/src/main/java/org/gradle/api/internal/java/usagecontext/ConfigurationVariantMapping.java index b5e7e6d3cf428..ae367df0d4d16 100644 --- a/subprojects/plugins/src/main/java/org/gradle/api/internal/java/usagecontext/ConfigurationVariantMapping.java +++ b/subprojects/plugins/src/main/java/org/gradle/api/internal/java/usagecontext/ConfigurationVariantMapping.java @@ -135,9 +135,13 @@ public void skip() { } @Override - public void mapToMavenScope(String scope, boolean optional) { + public void markOptional() { + this.optional = true; + } + + @Override + public void mapToMavenScope(String scope) { this.mavenScope = assertValidScope(scope); - this.optional = optional; } private static String assertValidScope(String scope) { diff --git a/subprojects/plugins/src/main/java/org/gradle/api/internal/java/usagecontext/FeatureConfigurationUsageContext.java b/subprojects/plugins/src/main/java/org/gradle/api/internal/java/usagecontext/FeatureConfigurationUsageContext.java index 1b188db7ccd5d..6b49840f66652 100644 --- a/subprojects/plugins/src/main/java/org/gradle/api/internal/java/usagecontext/FeatureConfigurationUsageContext.java +++ b/subprojects/plugins/src/main/java/org/gradle/api/internal/java/usagecontext/FeatureConfigurationUsageContext.java @@ -18,17 +18,20 @@ import org.gradle.api.artifacts.Configuration; import org.gradle.api.artifacts.ConfigurationVariant; import org.gradle.api.internal.attributes.AttributeContainerInternal; +import org.gradle.api.internal.component.IvyPublishingAwareContext; import org.gradle.api.internal.component.MavenPublishingAwareContext; import org.gradle.api.plugins.internal.AbstractConfigurationUsageContext; -public class FeatureConfigurationUsageContext extends AbstractConfigurationUsageContext implements MavenPublishingAwareContext { +public class FeatureConfigurationUsageContext extends AbstractConfigurationUsageContext implements MavenPublishingAwareContext, IvyPublishingAwareContext { private final Configuration configuration; private final ScopeMapping scopeMapping; + private final boolean optional; public FeatureConfigurationUsageContext(String name, Configuration configuration, ConfigurationVariant variant, String mavenScope, boolean optional) { super(name, ((AttributeContainerInternal)variant.getAttributes()).asImmutable(), variant.getArtifacts()); this.configuration = configuration; this.scopeMapping = ScopeMapping.of(mavenScope, optional); + this.optional = optional; } @Override @@ -40,4 +43,9 @@ protected Configuration getConfiguration() { public ScopeMapping getScopeMapping() { return scopeMapping; } + + @Override + public boolean isOptional() { + return optional; + } } diff --git a/subprojects/plugins/src/main/java/org/gradle/api/plugins/internal/JavaConfigurationVariantMapping.java b/subprojects/plugins/src/main/java/org/gradle/api/plugins/internal/JavaConfigurationVariantMapping.java index 669db74d8c9bc..e75b03c0949e5 100644 --- a/subprojects/plugins/src/main/java/org/gradle/api/plugins/internal/JavaConfigurationVariantMapping.java +++ b/subprojects/plugins/src/main/java/org/gradle/api/plugins/internal/JavaConfigurationVariantMapping.java @@ -37,7 +37,10 @@ public JavaConfigurationVariantMapping(String scope, boolean optional) { public void execute(ConfigurationVariantDetails details) { ConfigurationVariant variant = details.getConfigurationVariant(); if (ArtifactTypeSpec.INSTANCE.isSatisfiedBy(variant)) { - details.mapToMavenScope(scope, optional); + details.mapToMavenScope(scope); + if (optional) { + details.markOptional(); + } } else { details.skip(); } From c00b19212716f9aa8421bb90a6171fc1e1ab822c Mon Sep 17 00:00:00 2001 From: Louis Jacomet Date: Thu, 28 Feb 2019 14:22:55 +0100 Subject: [PATCH 264/853] Rename method for clarity markOptional -> mapToOptional to indicate this is really a mapping from Gradle to the other metadata formats. --- .../api/component/ConfigurationVariantDetails.java | 2 +- .../api/publish/ivy/IvyPublishJavaIntegTest.groovy | 2 +- .../maven/MavenPublishFeaturesJavaIntegTest.groovy | 12 ++++++------ .../usagecontext/ConfigurationVariantMapping.java | 2 +- .../internal/JavaConfigurationVariantMapping.java | 2 +- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/subprojects/core-api/src/main/java/org/gradle/api/component/ConfigurationVariantDetails.java b/subprojects/core-api/src/main/java/org/gradle/api/component/ConfigurationVariantDetails.java index 98e56a6356536..40c73aa2e9004 100644 --- a/subprojects/core-api/src/main/java/org/gradle/api/component/ConfigurationVariantDetails.java +++ b/subprojects/core-api/src/main/java/org/gradle/api/component/ConfigurationVariantDetails.java @@ -46,7 +46,7 @@ public interface ConfigurationVariantDetails { *
  • For the Ivy world, this means that configuration marked optional will not be extended by the {@code default} configuration.
  • * */ - void markOptional(); + void mapToOptional(); /** * Provides information about how to publish to a Maven POM file. If diff --git a/subprojects/ivy/src/integTest/groovy/org/gradle/api/publish/ivy/IvyPublishJavaIntegTest.groovy b/subprojects/ivy/src/integTest/groovy/org/gradle/api/publish/ivy/IvyPublishJavaIntegTest.groovy index bee5d4255159c..83974a8339a55 100644 --- a/subprojects/ivy/src/integTest/groovy/org/gradle/api/publish/ivy/IvyPublishJavaIntegTest.groovy +++ b/subprojects/ivy/src/integTest/groovy/org/gradle/api/publish/ivy/IvyPublishJavaIntegTest.groovy @@ -1013,7 +1013,7 @@ class IvyPublishJavaIntegTest extends AbstractIvyPublishIntegTest { } components.java.addVariantsFromConfiguration(configurations.optionalFeatureRuntimeElements) { - if ($optional) it.markOptional() + if ($optional) it.mapToOptional() } publishing { diff --git a/subprojects/maven/src/integTest/groovy/org/gradle/api/publish/maven/MavenPublishFeaturesJavaIntegTest.groovy b/subprojects/maven/src/integTest/groovy/org/gradle/api/publish/maven/MavenPublishFeaturesJavaIntegTest.groovy index 7df723ae3b1e7..32f4a1bb414ef 100644 --- a/subprojects/maven/src/integTest/groovy/org/gradle/api/publish/maven/MavenPublishFeaturesJavaIntegTest.groovy +++ b/subprojects/maven/src/integTest/groovy/org/gradle/api/publish/maven/MavenPublishFeaturesJavaIntegTest.groovy @@ -46,7 +46,7 @@ class MavenPublishFeaturesJavaIntegTest extends AbstractMavenPublishFeaturesJava components.java.addVariantsFromConfiguration(configurations.optionalFeatureRuntimeElements) { it.mapToMavenScope('compile') - it.markOptional() + it.mapToOptional() } """ @@ -129,11 +129,11 @@ class MavenPublishFeaturesJavaIntegTest extends AbstractMavenPublishFeaturesJava components.java.addVariantsFromConfiguration(configurations.optionalFeature1RuntimeElements) { it.mapToMavenScope('compile') - it.markOptional() + it.mapToOptional() } components.java.addVariantsFromConfiguration(configurations.optionalFeature2RuntimeElements) { it.mapToMavenScope('compile') - it.markOptional() + it.mapToOptional() } """ @@ -196,7 +196,7 @@ class MavenPublishFeaturesJavaIntegTest extends AbstractMavenPublishFeaturesJava components.java.addVariantsFromConfiguration(configurations.optionalFeatureRuntimeElements) { it.mapToMavenScope('compile') - it.markOptional() + it.mapToOptional() } artifacts { @@ -299,7 +299,7 @@ class MavenPublishFeaturesJavaIntegTest extends AbstractMavenPublishFeaturesJava components.java.addVariantsFromConfiguration(configurations.optionalFeatureRuntimeElements) { it.mapToMavenScope('compile') - it.markOptional() + it.mapToOptional() } def alt = configurations.optionalFeatureRuntimeElements.outgoing.variants.create("alternate") @@ -382,7 +382,7 @@ class MavenPublishFeaturesJavaIntegTest extends AbstractMavenPublishFeaturesJava it.skip() } else { it.mapToMavenScope('compile') - it.markOptional() + it.mapToOptional() } } diff --git a/subprojects/plugins/src/main/java/org/gradle/api/internal/java/usagecontext/ConfigurationVariantMapping.java b/subprojects/plugins/src/main/java/org/gradle/api/internal/java/usagecontext/ConfigurationVariantMapping.java index ae367df0d4d16..4fc3fc698fca4 100644 --- a/subprojects/plugins/src/main/java/org/gradle/api/internal/java/usagecontext/ConfigurationVariantMapping.java +++ b/subprojects/plugins/src/main/java/org/gradle/api/internal/java/usagecontext/ConfigurationVariantMapping.java @@ -135,7 +135,7 @@ public void skip() { } @Override - public void markOptional() { + public void mapToOptional() { this.optional = true; } diff --git a/subprojects/plugins/src/main/java/org/gradle/api/plugins/internal/JavaConfigurationVariantMapping.java b/subprojects/plugins/src/main/java/org/gradle/api/plugins/internal/JavaConfigurationVariantMapping.java index e75b03c0949e5..4dbda22097486 100644 --- a/subprojects/plugins/src/main/java/org/gradle/api/plugins/internal/JavaConfigurationVariantMapping.java +++ b/subprojects/plugins/src/main/java/org/gradle/api/plugins/internal/JavaConfigurationVariantMapping.java @@ -39,7 +39,7 @@ public void execute(ConfigurationVariantDetails details) { if (ArtifactTypeSpec.INSTANCE.isSatisfiedBy(variant)) { details.mapToMavenScope(scope); if (optional) { - details.markOptional(); + details.mapToOptional(); } } else { details.skip(); From 34f3546c0d136ca92681fd088b64d37b7c0870d1 Mon Sep 17 00:00:00 2001 From: Louis Jacomet Date: Thu, 28 Feb 2019 20:21:29 +0100 Subject: [PATCH 265/853] Amend documentation for feature variants with Ivy Indicate what happens when mapping feature variants to Ivy and how they can be consumed in that context. --- .../docs/src/docs/userguide/feature_variants.adoc | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/subprojects/docs/src/docs/userguide/feature_variants.adoc b/subprojects/docs/src/docs/userguide/feature_variants.adoc index f129b806b0cc9..7cefe20b15d62 100644 --- a/subprojects/docs/src/docs/userguide/feature_variants.adoc +++ b/subprojects/docs/src/docs/userguide/feature_variants.adoc @@ -134,11 +134,11 @@ include::sample[dir="java-feature-variant/producer-separate-sourceset/kotlin",fi Depending on the metadata file format, publishing feature variants may be lossy: - using POM metadata (Maven), feature variants are published as **optional dependencies** and artifacts of feature variants are published with different _classifiers_ -- using Ivy metadata, feature variants are lost +- using Ivy metadata, feature variants are published as extra configurations, which are _not_ extended by the `default` configuration - using {metadata-file-spec}[experimental Gradle metadata], everything is published and consumers will get the full benefit of feature variants ==== -Publishing feature variants is supported using the `maven-publish` plugin only. +Publishing feature variants is supported using the `maven-publish` and `ivy-publish` plugins only. The Java Plugin (or Java Library Plugin) will take care of registering the additional variants for you, so there's no additional configuration required, only the regular publications: .Publishing a component with feature variants @@ -153,10 +153,11 @@ include::sample[dir="java-feature-variant/producer/kotlin",files="build.gradle.k [WARNING] ==== As mentioned earlier, feature variants can be lossy when published. -As a consequence, a consumer can depend on a feature variant only in two cases: +As a consequence, a consumer can depend on a feature variant only in these cases: - with a project dependency (in a multi-project build) -- with Gradle metadata enabled (the publisher MUST have published using Gradle metadata) +- with Gradle metadata available, that is the publisher MUST have published it +- within the Ivy world, by declaring a dependency on the configuration matching the feature ==== A consumer can specify that it needs a specific feature of a producer by declaring required capabilities. From a49dfb38c475d6f7a7fa3927671ecaa201d8b9aa Mon Sep 17 00:00:00 2001 From: Paul Merlin Date: Fri, 1 Mar 2019 12:35:07 +0100 Subject: [PATCH 266/853] Coverage for applying precompiled script plugin from Groovy script Signed-off-by: Paul Merlin --- .../PrecompiledScriptPluginIntegrationTest.kt | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/subprojects/kotlin-dsl-integ-tests/src/integTest/kotlin/org/gradle/kotlin/dsl/integration/PrecompiledScriptPluginIntegrationTest.kt b/subprojects/kotlin-dsl-integ-tests/src/integTest/kotlin/org/gradle/kotlin/dsl/integration/PrecompiledScriptPluginIntegrationTest.kt index ab37d09a7b9c4..aca4f3bdc9e65 100644 --- a/subprojects/kotlin-dsl-integ-tests/src/integTest/kotlin/org/gradle/kotlin/dsl/integration/PrecompiledScriptPluginIntegrationTest.kt +++ b/subprojects/kotlin-dsl-integ-tests/src/integTest/kotlin/org/gradle/kotlin/dsl/integration/PrecompiledScriptPluginIntegrationTest.kt @@ -100,4 +100,24 @@ class PrecompiledScriptPluginIntegrationTest : AbstractPluginIntegrationTest() { assertFalse(existing("build/generated-sources/kotlin-dsl-plugins/kotlin/FooPlugin.kt").exists()) assertTrue(existing("build/generated-sources/kotlin-dsl-plugins/kotlin/BarPlugin.kt").isFile) } + + @Test + fun `can apply precompiled script plugin from groovy script`() { + + requireGradleDistributionOnEmbeddedExecuter() + + withKotlinBuildSrc() + withFile("buildSrc/src/main/kotlin/my-plugin.gradle.kts", """ + tasks.register("myTask") {} + """) + + withDefaultSettings() + withFile("build.gradle", """ + plugins { + id 'my-plugin' + } + """) + + build("myTask") + } } From 50d135febaa940b88c27adf4cab09cc0307f2896 Mon Sep 17 00:00:00 2001 From: Paul Merlin Date: Fri, 1 Mar 2019 12:55:13 +0100 Subject: [PATCH 267/853] Tighten precompiled script plugins cacheability and relocatability Signed-off-by: Paul Merlin --- .../PrecompiledScriptPluginIntegrationTest.kt | 25 +++++++++++++++---- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/subprojects/kotlin-dsl-integ-tests/src/integTest/kotlin/org/gradle/kotlin/dsl/integration/PrecompiledScriptPluginIntegrationTest.kt b/subprojects/kotlin-dsl-integ-tests/src/integTest/kotlin/org/gradle/kotlin/dsl/integration/PrecompiledScriptPluginIntegrationTest.kt index aca4f3bdc9e65..cfb819148d516 100644 --- a/subprojects/kotlin-dsl-integ-tests/src/integTest/kotlin/org/gradle/kotlin/dsl/integration/PrecompiledScriptPluginIntegrationTest.kt +++ b/subprojects/kotlin-dsl-integ-tests/src/integTest/kotlin/org/gradle/kotlin/dsl/integration/PrecompiledScriptPluginIntegrationTest.kt @@ -35,7 +35,7 @@ class PrecompiledScriptPluginIntegrationTest : AbstractPluginIntegrationTest() { } @Test - fun `precompiled script plugins adapters generation is cached and relocatable`() { + fun `precompiled script plugins tasks are cached and relocatable`() { requireGradleDistributionOnEmbeddedExecuter() @@ -66,18 +66,33 @@ class PrecompiledScriptPluginIntegrationTest : AbstractPluginIntegrationTest() { val secondDir = newDir(secondLocation) firstDir.copyRecursively(secondDir) - val generationTask = ":generateScriptPluginAdapters" + val cachedTasks = listOf( + ":extractPrecompiledScriptPluginPlugins", + ":generateInternalPluginSpecBuilders", + ":generateExternalPluginSpecBuilders", + ":compilePluginsBlocks", + ":generatePrecompiledScriptPluginAccessors", + ":generateScriptPluginAdapters" + ) + val configurationTask = ":configurePrecompiledScriptDependenciesResolver" + val downstreamKotlinCompileTask = ":compileKotlin" build(firstDir, "classes", "--build-cache").apply { - assertTaskExecuted(generationTask) + cachedTasks.forEach { assertTaskExecuted(it) } + assertTaskExecuted(configurationTask) + assertTaskExecuted(downstreamKotlinCompileTask) } build(firstDir, "classes", "--build-cache").apply { - assertOutputContains("$generationTask UP-TO-DATE") + cachedTasks.forEach { assertOutputContains("$it UP-TO-DATE") } + assertTaskExecuted(configurationTask) + assertOutputContains("$downstreamKotlinCompileTask UP-TO-DATE") } build(secondDir, "classes", "--build-cache").apply { - assertOutputContains("$generationTask FROM-CACHE") + cachedTasks.forEach { assertOutputContains("$it FROM-CACHE") } + assertTaskExecuted(configurationTask) + assertOutputContains("$downstreamKotlinCompileTask FROM-CACHE") } } From bdd3008e459fab4e6961a51d56228eb918e7aa8d Mon Sep 17 00:00:00 2001 From: Paul Merlin Date: Fri, 1 Mar 2019 13:13:49 +0100 Subject: [PATCH 268/853] Limit buildSrc ktlint exclusion to offending code only That is the generated code for precompiled script plugins accessors Signed-off-by: Paul Merlin --- buildSrc/build.gradle.kts | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts index aa9cc65938783..109fc924a69d4 100644 --- a/buildSrc/build.gradle.kts +++ b/buildSrc/build.gradle.kts @@ -214,15 +214,9 @@ fun Project.applyKotlinProjectConventions() { } configure { - // TODO:kotlin-dsl unignore KtLint failures - // we would like to only exclude the generated-sources from the - // verification but unfortunately the filter doesn't seem to - // have an effect so :/ - ignoreFailures.set(true) - // because of the above, the output is cluttered, disable console output - outputToConsole.set(false) + // TODO:kotlin-dsl remove precompiled script plugins accessors exclusion from ktlint checks filter { - exclude("**/generated-sources/**") + exclude("gradle/kotlin/dsl/accessors/_*/**") } } } From 86290308019f222b0657e62322d03a19e3a9e27f Mon Sep 17 00:00:00 2001 From: Rene Groeschke Date: Fri, 1 Mar 2019 13:26:17 +0100 Subject: [PATCH 269/853] Update build scan plugin to 2.2.1 --- buildSrc/subprojects/profiling/profiling.gradle.kts | 2 +- .../internal/autoapply/AutoAppliedBuildScanPlugin.java | 2 +- .../org/gradle/smoketests/BuildScanPluginSmokeTest.groovy | 1 + 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/buildSrc/subprojects/profiling/profiling.gradle.kts b/buildSrc/subprojects/profiling/profiling.gradle.kts index 88e766f7133b5..84b74a6b89003 100644 --- a/buildSrc/subprojects/profiling/profiling.gradle.kts +++ b/buildSrc/subprojects/profiling/profiling.gradle.kts @@ -1,7 +1,7 @@ dependencies { implementation("me.champeau.gradle:jmh-gradle-plugin:0.4.8") implementation("org.jsoup:jsoup:1.11.3") - implementation("com.gradle:build-scan-plugin:2.2") + implementation("com.gradle:build-scan-plugin:2.2.1") implementation(project(":configuration")) implementation(project(":kotlinDsl")) implementation(project(":plugins")) diff --git a/subprojects/core/src/main/java/org/gradle/plugin/management/internal/autoapply/AutoAppliedBuildScanPlugin.java b/subprojects/core/src/main/java/org/gradle/plugin/management/internal/autoapply/AutoAppliedBuildScanPlugin.java index 12e3f39b278a7..b8055cbbfe8fc 100644 --- a/subprojects/core/src/main/java/org/gradle/plugin/management/internal/autoapply/AutoAppliedBuildScanPlugin.java +++ b/subprojects/core/src/main/java/org/gradle/plugin/management/internal/autoapply/AutoAppliedBuildScanPlugin.java @@ -31,7 +31,7 @@ public final class AutoAppliedBuildScanPlugin { public static final PluginId ID = new DefaultPluginId("com.gradle.build-scan"); public static final String GROUP = "com.gradle"; public static final String NAME = "build-scan-plugin"; - public static final String VERSION = "2.2"; + public static final String VERSION = "2.2.1"; /** * Adds the {@code build-scan} plugin spec to the given {@link PluginDependenciesSpec} and returns the diff --git a/subprojects/smoke-test/src/smokeTest/groovy/org/gradle/smoketests/BuildScanPluginSmokeTest.groovy b/subprojects/smoke-test/src/smokeTest/groovy/org/gradle/smoketests/BuildScanPluginSmokeTest.groovy index 239d7143e3855..489274e433922 100644 --- a/subprojects/smoke-test/src/smokeTest/groovy/org/gradle/smoketests/BuildScanPluginSmokeTest.groovy +++ b/subprojects/smoke-test/src/smokeTest/groovy/org/gradle/smoketests/BuildScanPluginSmokeTest.groovy @@ -33,6 +33,7 @@ class BuildScanPluginSmokeTest extends AbstractSmokeTest { ] private static final List SUPPORTED = [ + "2.2.1", "2.2", "2.1", "2.0.2" From 72dec614d9c1bb108a6c124e62d5e6f4511229f5 Mon Sep 17 00:00:00 2001 From: Jenn Strater Date: Thu, 28 Feb 2019 16:07:38 +0100 Subject: [PATCH 270/853] add some info about maven build scans to the conversion steps --- .../docs/userguide/migrating_from_maven.adoc | 28 ++++++++++++------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/subprojects/docs/src/docs/userguide/migrating_from_maven.adoc b/subprojects/docs/src/docs/userguide/migrating_from_maven.adoc index e6abf3241d1b4..c0c42612ce0f1 100644 --- a/subprojects/docs/src/docs/userguide/migrating_from_maven.adoc +++ b/subprojects/docs/src/docs/userguide/migrating_from_maven.adoc @@ -41,11 +41,17 @@ This may make migrating between the two seem intimidating, but migrations can be Here we lay out a series of steps for you to follow that will help facilitate the migration of any Maven build to Gradle: - 1. Keep the old Maven build and new Gradle build side by side -+ +TIP: Keep the old Maven build and new Gradle build side by side. You know the Maven build works, so you should keep it until you are confident that the Gradle build produces all the same artifacts and otherwise does what you need. This also means that users can try the Gradle build without getting a new copy of the source tree. - 2. Develop a mechanism to verify that the two builds produce the same artifacts + + . link:https://scans.gradle.com[Create a build scan for the Maven build]. ++ +A build scan will make it easier to visualize what's happening in your existing Maven build. +For Maven builds, you'll be able to see the project structure, what plugins are being used, a timeline of the build steps, and more. +Keep this handy so you can compare it to the Gradle build scans you get while converting the project. ++ +. Develop a mechanism to verify that the two builds produce the same artifacts + This is a vitally important step to ensure that your deployments and tests don't break. Even small changes, such as the contents of a manifest file in a JAR, can cause problems. @@ -58,23 +64,25 @@ You will need to factor in some inherent differences in the build output that Gr Generated POMs will contain only the information needed for consumption and they will use `` and `` scopes correctly for that scenario. You might also see differences in the order of files in archives and of files on classpaths. Most differences will be benign, but it's worth identifying them and verifying that they are OK. - 3. <> + . <> + This will create all the Gradle build files you need, even for <>. For simpler Maven projects, the Gradle build will be ready to run! - 4. link:{guidesUrl}/creating-build-scans/[Create a build scan] + . link:{guidesUrl}/creating-build-scans[Create a build scan for the Gradle build]. + A build scan will make it easier to visualize what's happening in the build. -In particular, you'll be able to see the project structure, the dependencies (regular and inter-project ones), what plugins are being used and the console output of the build. +For Gradle builds, you'll be able to see the project structure, the dependencies (regular and inter-project ones), what plugins are being used and the console output of the build. ++ +Your build may fail at this point, but that's ok; the scan will still run. Compare the build scan for the Gradle build to the one for the Maven build and continue down this list to troubleshoot the failures. + We recommend that you regularly generate build scans during the migration to help you identify and troubleshoot problems. -If you want, you can then use them to identify opportunities to improve the performance of the build, and performance is a big reason for switching to Gradle in the first place. - 5. <> - 6. <> +If you want, you can also use a Gradle build scan to identify opportunities to link:{guidesUrl}/performance/[improve the performance of the build], after all performance is a big reason for switching to Gradle in the first place. + . <> + . <> + Many tests can simply be migrated by configuring an extra source set. If you are using a third-party library, such as http://docs.fitnesse.org/FrontPage[FitNesse], look to see whether there is a suitable community plugin available on the https://plugins.gradle.org/[Gradle Plugin Portal]. - 7. Replace Maven plugins with Gradle equivalents + . Replace Maven plugins with Gradle equivalents + In the case of <>, Gradle often has an equivalent plugin that you can use. You might also find that you can <>. From 398118aac9ce0bfedaa860e20dcd9fe232b2ef11 Mon Sep 17 00:00:00 2001 From: Gary Hale Date: Tue, 26 Feb 2019 09:37:38 -0500 Subject: [PATCH 271/853] Fix metaspace daemon soak test --- .../launcher/daemon/DaemonPerformanceMonitoringSoakTest.groovy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subprojects/soak/src/integTest/groovy/org/gradle/launcher/daemon/DaemonPerformanceMonitoringSoakTest.groovy b/subprojects/soak/src/integTest/groovy/org/gradle/launcher/daemon/DaemonPerformanceMonitoringSoakTest.groovy index 75fb1a43649eb..7347d6b961c63 100644 --- a/subprojects/soak/src/integTest/groovy/org/gradle/launcher/daemon/DaemonPerformanceMonitoringSoakTest.groovy +++ b/subprojects/soak/src/integTest/groovy/org/gradle/launcher/daemon/DaemonPerformanceMonitoringSoakTest.groovy @@ -183,7 +183,7 @@ class DaemonPerformanceMonitoringSoakTest extends DaemonMultiJdkIntegrationTest try { for (int i = 0; i < maxBuilds; i++) { executer.noExtraLogging() - executer.withBuildJvmOpts("-D${DaemonMemoryStatus.ENABLE_PERFORMANCE_MONITORING}=true", "-Xms128m", "-Xmx${heapSize}", "-Dorg.gradle.daemon.performance.logging=true") + executer.withBuildJvmOpts("-D${DaemonMemoryStatus.ENABLE_PERFORMANCE_MONITORING}=true", "-Xms128m", "-XX:MaxMetaspaceSize=${heapSize}", "-Xmx${heapSize}", "-Dorg.gradle.daemon.performance.logging=true") GradleHandle gradle = executer.start() gradle.waitForExit() if (gradle.standardOutput ==~ /(?s).*Starting build in new daemon \[memory: [0-9].*/) { From f6f7cb87f462da35671e0fd922b7de509021ee14 Mon Sep 17 00:00:00 2001 From: Gary Hale Date: Tue, 26 Feb 2019 09:49:57 -0500 Subject: [PATCH 272/853] Unignore daemon metaspace soak test --- .../launcher/daemon/DaemonPerformanceMonitoringSoakTest.groovy | 2 -- 1 file changed, 2 deletions(-) diff --git a/subprojects/soak/src/integTest/groovy/org/gradle/launcher/daemon/DaemonPerformanceMonitoringSoakTest.groovy b/subprojects/soak/src/integTest/groovy/org/gradle/launcher/daemon/DaemonPerformanceMonitoringSoakTest.groovy index 7347d6b961c63..16f807e1dfc8e 100644 --- a/subprojects/soak/src/integTest/groovy/org/gradle/launcher/daemon/DaemonPerformanceMonitoringSoakTest.groovy +++ b/subprojects/soak/src/integTest/groovy/org/gradle/launcher/daemon/DaemonPerformanceMonitoringSoakTest.groovy @@ -28,7 +28,6 @@ import org.gradle.launcher.daemon.server.health.GcThrashingDaemonExpirationStrat import org.gradle.soak.categories.SoakTest import org.gradle.test.fixtures.ConcurrentTestUtil import org.junit.experimental.categories.Category -import spock.lang.Ignore import spock.lang.Unroll import static org.junit.Assume.assumeTrue @@ -124,7 +123,6 @@ class DaemonPerformanceMonitoringSoakTest extends DaemonMultiJdkIntegrationTest daemons.daemon.log.contains(DaemonStateCoordinator.DAEMON_WILL_STOP_MESSAGE) } - @Ignore def "when build leaks permgen space daemon is expired"() { assumeTrue(version.vendor != JdkVendor.IBM) From bee0cd8d337adc8ee1f4de7d44ea3dc5a9f920ae Mon Sep 17 00:00:00 2001 From: Gary Hale Date: Tue, 26 Feb 2019 17:32:15 -0500 Subject: [PATCH 273/853] Adjust soak tests to account for change in GC monitoring --- .../daemon/DaemonPerformanceMonitoringSoakTest.groovy | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/subprojects/soak/src/integTest/groovy/org/gradle/launcher/daemon/DaemonPerformanceMonitoringSoakTest.groovy b/subprojects/soak/src/integTest/groovy/org/gradle/launcher/daemon/DaemonPerformanceMonitoringSoakTest.groovy index 16f807e1dfc8e..5d884d8959f33 100644 --- a/subprojects/soak/src/integTest/groovy/org/gradle/launcher/daemon/DaemonPerformanceMonitoringSoakTest.groovy +++ b/subprojects/soak/src/integTest/groovy/org/gradle/launcher/daemon/DaemonPerformanceMonitoringSoakTest.groovy @@ -120,7 +120,7 @@ class DaemonPerformanceMonitoringSoakTest extends DaemonMultiJdkIntegrationTest } and: - daemons.daemon.log.contains(DaemonStateCoordinator.DAEMON_WILL_STOP_MESSAGE) + daemons.daemon.log.contains(DaemonStateCoordinator.DAEMON_WILL_STOP_MESSAGE) || daemons.daemon.log.contains(DaemonStateCoordinator.DAEMON_STOPPING_IMMEDIATELY_MESSAGE) } def "when build leaks permgen space daemon is expired"() { @@ -128,9 +128,9 @@ class DaemonPerformanceMonitoringSoakTest extends DaemonMultiJdkIntegrationTest when: setupBuildScript = permGenLeak - maxBuilds = 20 + maxBuilds = 30 heapSize = "200m" - leakRate = 3300 + leakRate = 3700 then: daemonIsExpiredEagerly() @@ -142,7 +142,7 @@ class DaemonPerformanceMonitoringSoakTest extends DaemonMultiJdkIntegrationTest // before the gc monitoring expires the daemon executer.withDaemonIdleTimeoutSecs(300) heapSize = "200m" - leakRate = 1700 + leakRate = 1400 when: leaksWithinOneBuild() From f69e53db82c6d8791187b4d3cafb6f888174895a Mon Sep 17 00:00:00 2001 From: Gary Hale Date: Thu, 28 Feb 2019 14:19:46 -0500 Subject: [PATCH 274/853] Adjust soak test settings a little more --- .../daemon/DaemonPerformanceMonitoringSoakTest.groovy | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/subprojects/soak/src/integTest/groovy/org/gradle/launcher/daemon/DaemonPerformanceMonitoringSoakTest.groovy b/subprojects/soak/src/integTest/groovy/org/gradle/launcher/daemon/DaemonPerformanceMonitoringSoakTest.groovy index 5d884d8959f33..17429828bc589 100644 --- a/subprojects/soak/src/integTest/groovy/org/gradle/launcher/daemon/DaemonPerformanceMonitoringSoakTest.groovy +++ b/subprojects/soak/src/integTest/groovy/org/gradle/launcher/daemon/DaemonPerformanceMonitoringSoakTest.groovy @@ -93,13 +93,12 @@ class DaemonPerformanceMonitoringSoakTest extends DaemonMultiJdkIntegrationTest !daemonIsExpiredEagerly() } - @Ignore def "when leak occurs while daemon is idle daemon is still expired"() { // This is so the idle timeout expiration strategy doesn't kick in // before the gc monitoring expires the daemon executer.withDaemonIdleTimeoutSecs(300) heapSize = "200m" - leakRate = 1000 + leakRate = 900 when: leaksWhenIdle() @@ -136,13 +135,12 @@ class DaemonPerformanceMonitoringSoakTest extends DaemonMultiJdkIntegrationTest daemonIsExpiredEagerly() } - @Ignore def "detects a thrashing condition" () { // This is so the idle timeout expiration strategy doesn't kick in // before the gc monitoring expires the daemon executer.withDaemonIdleTimeoutSecs(300) heapSize = "200m" - leakRate = 1400 + leakRate = 1300 when: leaksWithinOneBuild() From d03fc131792dddb4d4ca138572eedf4579964cd3 Mon Sep 17 00:00:00 2001 From: "Rodrigo B. de Oliveira" Date: Fri, 1 Mar 2019 11:18:32 -0300 Subject: [PATCH 275/853] Don't link to inaccessible types from the generated accessor source code --- .../org/gradle/kotlin/dsl/accessors/CodeGenerator.kt | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/accessors/CodeGenerator.kt b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/accessors/CodeGenerator.kt index f1b1e18595639..c34fcb5a7db38 100644 --- a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/accessors/CodeGenerator.kt +++ b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/accessors/CodeGenerator.kt @@ -76,7 +76,7 @@ private fun inaccessibleExtensionAccessorFor(targetType: String, name: AccessorNameSpec, typeAccess: TypeAccessibility.Inaccessible): String = name.run { """ /** - * Retrieves the [$original][${typeAccess.type}] extension. + * Retrieves the `$original` extension. * * ${documentInaccessibilityReasons(name, typeAccess)} */ @@ -84,7 +84,7 @@ fun inaccessibleExtensionAccessorFor(targetType: String, name: AccessorNameSpec, $thisExtensions.getByName("$stringLiteral") /** - * Configures the [$original][${typeAccess.type}] extension. + * Configures the `$original` extension. * * ${documentInaccessibilityReasons(name, typeAccess)} */ @@ -127,7 +127,7 @@ private fun inaccessibleConventionAccessorFor(targetType: String, name: AccessorNameSpec, typeAccess: TypeAccessibility.Inaccessible): String = name.run { """ /** - * Retrieves the [$original][${typeAccess.type}] convention. + * Retrieves the `$original` convention. * * ${documentInaccessibilityReasons(name, typeAccess)} */ @@ -135,7 +135,7 @@ fun inaccessibleConventionAccessorFor(targetType: String, name: AccessorNameSpec $thisConvention.getPluginByName("$stringLiteral") /** - * Configures the [$original][${typeAccess.type}] convention. + * Configures the `$original` convention. * * ${documentInaccessibilityReasons(name, typeAccess)} */ @@ -172,7 +172,7 @@ private fun inaccessibleExistingTaskAccessorFor(name: AccessorNameSpec, typeAccess: TypeAccessibility.Inaccessible): String = name.run { """ /** - * Provides the existing [$original][${typeAccess.type}] task. + * Provides the existing `$original` task. * * ${documentInaccessibilityReasons(name, typeAccess)} */ @@ -209,7 +209,7 @@ private fun inaccessibleExistingContainerElementAccessorFor(containerType: String, name: AccessorNameSpec, elementType: TypeAccessibility.Inaccessible): String = name.run { """ /** - * Provides the existing [$original][${elementType.type}] element. + * Provides the existing `$original` element. * * ${documentInaccessibilityReasons(name, elementType)} */ From ad41fd738bef1aa3d84f745a2d625614f2a5a734 Mon Sep 17 00:00:00 2001 From: Paul Merlin Date: Fri, 1 Mar 2019 15:40:12 +0100 Subject: [PATCH 276/853] Recreate task temporary dir Signed-off-by: Paul Merlin --- .../GeneratePrecompiledScriptPluginAccessors.kt | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/GeneratePrecompiledScriptPluginAccessors.kt b/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/GeneratePrecompiledScriptPluginAccessors.kt index 053d2e9bf9431..8248747da50ea 100644 --- a/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/GeneratePrecompiledScriptPluginAccessors.kt +++ b/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/GeneratePrecompiledScriptPluginAccessors.kt @@ -107,7 +107,7 @@ open class GeneratePrecompiledScriptPluginAccessors : ClassPathSensitiveCodeGene fun generate() { withAsynchronousIO(project) { - recreateOutputDir() + recreateTaskDirectories() val projectPlugins = selectProjectPlugins() if (projectPlugins.isNotEmpty()) { @@ -117,10 +117,14 @@ open class GeneratePrecompiledScriptPluginAccessors : ClassPathSensitiveCodeGene } private - fun IO.recreateOutputDir() { - // access output dir from main thread, recreate in IO thread + fun IO.recreateTaskDirectories() { + // access dirs from main thread, recreate in IO thread + val taskTemporaryDir = temporaryDir val metadataOutputDir = metadataOutputDir.get().asFile - io { recreate(metadataOutputDir) } + io { + recreate(taskTemporaryDir) + recreate(metadataOutputDir) + } } private From 60a2556fb2b80cf2bdc0a0f69971b5f5e1ae1cb1 Mon Sep 17 00:00:00 2001 From: "Rodrigo B. de Oliveira" Date: Fri, 1 Mar 2019 11:52:48 -0300 Subject: [PATCH 277/853] Remove superseded integration test Superseded by recent additions to `PrecompiledScriptPluginAccessorsTest`. --- ...mpilePrecompiledScriptPluginPluginsTest.kt | 104 ------------------ 1 file changed, 104 deletions(-) delete mode 100644 subprojects/kotlin-dsl-provider-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/CompilePrecompiledScriptPluginPluginsTest.kt diff --git a/subprojects/kotlin-dsl-provider-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/CompilePrecompiledScriptPluginPluginsTest.kt b/subprojects/kotlin-dsl-provider-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/CompilePrecompiledScriptPluginPluginsTest.kt deleted file mode 100644 index 3c277f6ca45a4..0000000000000 --- a/subprojects/kotlin-dsl-provider-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/CompilePrecompiledScriptPluginPluginsTest.kt +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Copyright 2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.gradle.kotlin.dsl.provider.plugins.precompiled.tasks - -import com.nhaarman.mockito_kotlin.any -import com.nhaarman.mockito_kotlin.doReturn -import com.nhaarman.mockito_kotlin.inOrder -import com.nhaarman.mockito_kotlin.mock - -import org.gradle.kotlin.dsl.fixtures.AbstractKotlinIntegrationTest -import org.gradle.kotlin.dsl.fixtures.classLoaderFor - -import org.gradle.plugin.use.PluginDependenciesSpec -import org.gradle.plugin.use.PluginDependencySpec - -import org.junit.Ignore - -import org.junit.Test - -import java.net.URLClassLoader - - -@Ignore("wip") -class CompilePrecompiledScriptPluginPluginsTest : AbstractKotlinIntegrationTest() { - - @Test - fun `can compile multiple source dirs`() { - - withFolders { - "build/plugins/src" { - "a" { - withFile("a.gradle.kts", """plugins { java }""") - } - "b" { - withFile("b.gradle.kts", """plugins { id("a") }""") - } - } - } - - withBuildScript(""" - - fun Project.pluginsDir(path: String) = layout.buildDirectory.dir("plugins/" + path) - - tasks { - register<${CompilePrecompiledScriptPluginPlugins::class.qualifiedName}>("compilePlugins") { - sourceDir(pluginsDir("src/a")) - sourceDir(pluginsDir("src/b")) - outputDir.set(pluginsDir("output")) - classPathFiles = configurations.compileClasspath.get() - } - } - """) - - build("compilePlugins") - - classLoaderFor(existing("build/plugins/output")).use { classLoader -> - classLoader.expectPluginFromPluginsBlock( - "A_gradle", - "org.gradle.java" - ) - classLoader.expectPluginFromPluginsBlock( - "B_gradle", - "a" - ) - } - } - - private - fun URLClassLoader.expectPluginFromPluginsBlock(pluginsBlockClass: String, expectedPluginId: String) { - - val plugin = mock() - val plugins = mock { - on { id(any()) } doReturn plugin - } - - evalPluginsBlockOf(pluginsBlockClass, plugins) - - inOrder(plugins, plugin) { - verify(plugins).id(expectedPluginId) - verifyNoMoreInteractions() - } - } - - private - fun URLClassLoader.evalPluginsBlockOf(pluginsBlockClass: String, plugins: PluginDependenciesSpec) { - loadClass(pluginsBlockClass).getDeclaredConstructor(PluginDependenciesSpec::class.java).newInstance( - plugins - ) - } -} From b3d56e078f37d4ea467d8c74d0a12894ed052581 Mon Sep 17 00:00:00 2001 From: "Rodrigo B. de Oliveira" Date: Fri, 1 Mar 2019 12:11:59 -0300 Subject: [PATCH 278/853] Remove `integTestRuntimeOnly` references from `kotlinDslProviderPlugins` The project no longer has integration tests. --- .../kotlin-dsl-provider-plugins.gradle.kts | 3 --- 1 file changed, 3 deletions(-) diff --git a/subprojects/kotlin-dsl-provider-plugins/kotlin-dsl-provider-plugins.gradle.kts b/subprojects/kotlin-dsl-provider-plugins/kotlin-dsl-provider-plugins.gradle.kts index 8dfa80348ea97..6d670b4325a3a 100644 --- a/subprojects/kotlin-dsl-provider-plugins/kotlin-dsl-provider-plugins.gradle.kts +++ b/subprojects/kotlin-dsl-provider-plugins/kotlin-dsl-provider-plugins.gradle.kts @@ -40,7 +40,4 @@ dependencies { testImplementation(project(":kotlinDslTestFixtures")) testImplementation(project(":plugins")) - - integTestRuntimeOnly(project(":runtimeApiInfo")) - integTestRuntimeOnly(project(":apiMetadata")) } From 63cef02b6d783e0cd288424ce52ff0c15d42def7 Mon Sep 17 00:00:00 2001 From: Paul Merlin Date: Fri, 1 Mar 2019 16:09:13 +0100 Subject: [PATCH 279/853] Isolate synthetic projects temporary root dirs Signed-off-by: Paul Merlin --- .../tasks/GeneratePrecompiledScriptPluginAccessors.kt | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/GeneratePrecompiledScriptPluginAccessors.kt b/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/GeneratePrecompiledScriptPluginAccessors.kt index 8248747da50ea..a3faba174fd91 100644 --- a/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/GeneratePrecompiledScriptPluginAccessors.kt +++ b/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/GeneratePrecompiledScriptPluginAccessors.kt @@ -66,6 +66,7 @@ import org.gradle.plugin.use.internal.PluginRequestCollector import org.gradle.testfixtures.ProjectBuilder import java.io.File +import java.nio.file.Files @CacheableTask @@ -244,7 +245,10 @@ open class GeneratePrecompiledScriptPluginAccessors : ClassPathSensitiveCodeGene pluginGroupsPerRequests: Map, List> ): Map> { - val schemaBuilder = SyntheticProjectSchemaBuilder(temporaryDir, (classPathFiles + runtimeClassPathFiles).files) + val schemaBuilder = SyntheticProjectSchemaBuilder( + Files.createTempDirectory(temporaryDir.toPath(), "project-").toFile(), + (classPathFiles + runtimeClassPathFiles).files + ) return pluginGroupsPerRequests.flatMap { (uniquePluginRequests, scriptPlugins) -> try { val schema = schemaBuilder.schemaFor(pluginRequestsFor(uniquePluginRequests, scriptPlugins.first().scriptPlugin)) From dd03f33fe89697dce423bccde8bd2c84dd527874 Mon Sep 17 00:00:00 2001 From: Paul Merlin Date: Fri, 1 Mar 2019 16:09:27 +0100 Subject: [PATCH 280/853] Drop no-op GenerateInternalPluginSpecBuilders Signed-off-by: Paul Merlin --- .../PrecompiledScriptPluginIntegrationTest.kt | 1 - .../DefaultPrecompiledScriptPluginsSupport.kt | 17 ------ .../GenerateInternalPluginSpecBuilders.kt | 58 ------------------- 3 files changed, 76 deletions(-) delete mode 100644 subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/GenerateInternalPluginSpecBuilders.kt diff --git a/subprojects/kotlin-dsl-integ-tests/src/integTest/kotlin/org/gradle/kotlin/dsl/integration/PrecompiledScriptPluginIntegrationTest.kt b/subprojects/kotlin-dsl-integ-tests/src/integTest/kotlin/org/gradle/kotlin/dsl/integration/PrecompiledScriptPluginIntegrationTest.kt index cfb819148d516..f3662909446d6 100644 --- a/subprojects/kotlin-dsl-integ-tests/src/integTest/kotlin/org/gradle/kotlin/dsl/integration/PrecompiledScriptPluginIntegrationTest.kt +++ b/subprojects/kotlin-dsl-integ-tests/src/integTest/kotlin/org/gradle/kotlin/dsl/integration/PrecompiledScriptPluginIntegrationTest.kt @@ -68,7 +68,6 @@ class PrecompiledScriptPluginIntegrationTest : AbstractPluginIntegrationTest() { val cachedTasks = listOf( ":extractPrecompiledScriptPluginPlugins", - ":generateInternalPluginSpecBuilders", ":generateExternalPluginSpecBuilders", ":compilePluginsBlocks", ":generatePrecompiledScriptPluginAccessors", diff --git a/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/DefaultPrecompiledScriptPluginsSupport.kt b/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/DefaultPrecompiledScriptPluginsSupport.kt index 34e324206f407..f237ea5036357 100644 --- a/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/DefaultPrecompiledScriptPluginsSupport.kt +++ b/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/DefaultPrecompiledScriptPluginsSupport.kt @@ -37,7 +37,6 @@ import org.gradle.kotlin.dsl.provider.plugins.precompiled.tasks.CompilePrecompil import org.gradle.kotlin.dsl.provider.plugins.precompiled.tasks.ConfigurePrecompiledScriptDependenciesResolver import org.gradle.kotlin.dsl.provider.plugins.precompiled.tasks.ExtractPrecompiledScriptPluginPlugins import org.gradle.kotlin.dsl.provider.plugins.precompiled.tasks.GenerateExternalPluginSpecBuilders -import org.gradle.kotlin.dsl.provider.plugins.precompiled.tasks.GenerateInternalPluginSpecBuilders import org.gradle.kotlin.dsl.provider.plugins.precompiled.tasks.GeneratePrecompiledScriptPluginAccessors import org.gradle.kotlin.dsl.provider.plugins.precompiled.tasks.GenerateScriptPluginAdapters import org.gradle.kotlin.dsl.provider.plugins.precompiled.tasks.HashedProjectSchema @@ -109,8 +108,6 @@ import java.util.function.Consumer * following tasks: * - [ExtractPrecompiledScriptPluginPlugins] - extracts the `plugins` block of every precompiled script plugin and * saves it to a file with the same name in the output directory - * - [GenerateInternalPluginSpecBuilders] - generates plugin spec builders for the _Project_ script plugins defined - * in the current module * - [GenerateExternalPluginSpecBuilders] - generates plugin spec builders for the plugins in the compile classpath * - [CompilePrecompiledScriptPluginPlugins] - compiles the extracted `plugins` blocks along with the internal * and external plugin spec builders @@ -168,16 +165,6 @@ fun Project.enableScriptCompilationOf( outputDir.set(extractedPluginsBlocks) } - val (generateInternalPluginSpecBuilders, internalPluginSpecBuilders) = - codeGenerationTask( - "internal-plugin-spec-builders", - "generateInternalPluginSpecBuilders", - kotlinSourceDirectorySet - ) { - plugins = scriptPlugins - sourceCodeOutputDir.set(it) - } - val (generateExternalPluginSpecBuilders, externalPluginSpecBuilders) = codeGenerationTask( "external-plugin-spec-builders", @@ -193,9 +180,6 @@ fun Project.enableScriptCompilationOf( dependsOn(extractPrecompiledScriptPluginPlugins) sourceDir(extractedPluginsBlocks) - dependsOn(generateInternalPluginSpecBuilders) - sourceDir(internalPluginSpecBuilders) - dependsOn(generateExternalPluginSpecBuilders) sourceDir(externalPluginSpecBuilders) @@ -219,7 +203,6 @@ fun Project.enableScriptCompilationOf( } val configurePrecompiledScriptDependenciesResolver by registering(ConfigurePrecompiledScriptDependenciesResolver::class) { - dependsOn(generateInternalPluginSpecBuilders) dependsOn(generateExternalPluginSpecBuilders) inputs.files( project.files(generatedMetadata).builtBy(generatePrecompiledScriptPluginAccessors) diff --git a/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/GenerateInternalPluginSpecBuilders.kt b/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/GenerateInternalPluginSpecBuilders.kt deleted file mode 100644 index 1e12364c5a0f2..0000000000000 --- a/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/GenerateInternalPluginSpecBuilders.kt +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright 2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.gradle.kotlin.dsl.provider.plugins.precompiled.tasks - -import org.gradle.api.DefaultTask -import org.gradle.api.tasks.CacheableTask -import org.gradle.api.tasks.InputFiles -import org.gradle.api.tasks.Internal -import org.gradle.api.tasks.OutputDirectory -import org.gradle.api.tasks.PathSensitive -import org.gradle.api.tasks.PathSensitivity -import org.gradle.api.tasks.TaskAction - -import org.gradle.kotlin.dsl.provider.plugins.precompiled.PrecompiledScriptPlugin - -import java.io.File - - -/** - * Generates plugin spec builders for the _Project_ script plugins defined in the current module. - */ -@CacheableTask -open class GenerateInternalPluginSpecBuilders : DefaultTask() { - - @get:Internal - internal - lateinit var plugins: List - - @get:InputFiles - @get:PathSensitive(PathSensitivity.RELATIVE) - @Suppress("unused") - internal - val scriptFiles: Set - get() = scriptPluginFilesOf(plugins) - - @get:OutputDirectory - var sourceCodeOutputDir = directoryProperty() - - @TaskAction - fun generate() { - sourceCodeOutputDir.withOutputDirectory { - } - } -} From 67a0c0430d8610b43bb133a691e5bd5a521f1f7e Mon Sep 17 00:00:00 2001 From: Gary Hale Date: Fri, 1 Mar 2019 11:52:05 -0500 Subject: [PATCH 281/853] Disable flaky soak tests We'll just refactor these tests instead of trying to make them work in their current form. --- .../daemon/DaemonPerformanceMonitoringSoakTest.groovy | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/subprojects/soak/src/integTest/groovy/org/gradle/launcher/daemon/DaemonPerformanceMonitoringSoakTest.groovy b/subprojects/soak/src/integTest/groovy/org/gradle/launcher/daemon/DaemonPerformanceMonitoringSoakTest.groovy index 17429828bc589..3edc6149b11af 100644 --- a/subprojects/soak/src/integTest/groovy/org/gradle/launcher/daemon/DaemonPerformanceMonitoringSoakTest.groovy +++ b/subprojects/soak/src/integTest/groovy/org/gradle/launcher/daemon/DaemonPerformanceMonitoringSoakTest.groovy @@ -28,6 +28,7 @@ import org.gradle.launcher.daemon.server.health.GcThrashingDaemonExpirationStrat import org.gradle.soak.categories.SoakTest import org.gradle.test.fixtures.ConcurrentTestUtil import org.junit.experimental.categories.Category +import spock.lang.Ignore import spock.lang.Unroll import static org.junit.Assume.assumeTrue @@ -93,6 +94,7 @@ class DaemonPerformanceMonitoringSoakTest extends DaemonMultiJdkIntegrationTest !daemonIsExpiredEagerly() } + @Ignore def "when leak occurs while daemon is idle daemon is still expired"() { // This is so the idle timeout expiration strategy doesn't kick in // before the gc monitoring expires the daemon @@ -122,6 +124,7 @@ class DaemonPerformanceMonitoringSoakTest extends DaemonMultiJdkIntegrationTest daemons.daemon.log.contains(DaemonStateCoordinator.DAEMON_WILL_STOP_MESSAGE) || daemons.daemon.log.contains(DaemonStateCoordinator.DAEMON_STOPPING_IMMEDIATELY_MESSAGE) } + @Ignore def "when build leaks permgen space daemon is expired"() { assumeTrue(version.vendor != JdkVendor.IBM) @@ -135,6 +138,7 @@ class DaemonPerformanceMonitoringSoakTest extends DaemonMultiJdkIntegrationTest daemonIsExpiredEagerly() } + @Ignore def "detects a thrashing condition" () { // This is so the idle timeout expiration strategy doesn't kick in // before the gc monitoring expires the daemon From d78ad0d531d2deb16cc87de3fefb39f7db0411c0 Mon Sep 17 00:00:00 2001 From: Paul Merlin Date: Fri, 1 Mar 2019 18:29:56 +0100 Subject: [PATCH 282/853] Fix typo Signed-off-by: Paul Merlin --- subprojects/docs/src/docs/release/notes.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subprojects/docs/src/docs/release/notes.md b/subprojects/docs/src/docs/release/notes.md index bcc989ac498b0..4aa4e5d896a5a 100644 --- a/subprojects/docs/src/docs/release/notes.md +++ b/subprojects/docs/src/docs/release/notes.md @@ -90,7 +90,7 @@ This plugin can then be applied to regular projects: ```kotlin // build.gradle.kts plugins { - `my-java-convetion` + `my-java-convention` } ``` From 2d26c93ba969d4b48b8f874a658660d3dd063877 Mon Sep 17 00:00:00 2001 From: "Rodrigo B. de Oliveira" Date: Fri, 1 Mar 2019 17:45:04 -0300 Subject: [PATCH 283/853] Reduce fixed cost of applying the `kotlin-dsl` plugin --- .../precompiled/DefaultPrecompiledScriptPluginsSupport.kt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/DefaultPrecompiledScriptPluginsSupport.kt b/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/DefaultPrecompiledScriptPluginsSupport.kt index f237ea5036357..9632479e921a3 100644 --- a/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/DefaultPrecompiledScriptPluginsSupport.kt +++ b/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/DefaultPrecompiledScriptPluginsSupport.kt @@ -124,6 +124,9 @@ class DefaultPrecompiledScriptPluginsSupport : PrecompiledScriptPluginsSupport { ): Unit = project.run { val scriptPlugins = collectScriptPlugins() + if (scriptPlugins.isEmpty()) { + return + } enableScriptCompilationOf( scriptPlugins, @@ -156,7 +159,7 @@ fun Project.enableScriptCompilationOf( val generatedMetadata = buildDir("precompiled-script-plugins") - val compileClasspath = compileClasspath() + val compileClasspath by lazy { compileClasspath() } tasks { From c2db5b609b915196c180281c696bbc3c9f3d7e53 Mon Sep 17 00:00:00 2001 From: "Rodrigo B. de Oliveira" Date: Fri, 1 Mar 2019 18:07:30 -0300 Subject: [PATCH 284/853] Remove debug log from test --- .../precompiled/PrecompiledScriptPluginAccessorsTest.kt | 9 --------- 1 file changed, 9 deletions(-) diff --git a/subprojects/kotlin-dsl-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPluginAccessorsTest.kt b/subprojects/kotlin-dsl-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPluginAccessorsTest.kt index c9c455892b936..c9de27395cdd6 100644 --- a/subprojects/kotlin-dsl-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPluginAccessorsTest.kt +++ b/subprojects/kotlin-dsl-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPluginAccessorsTest.kt @@ -153,15 +153,6 @@ class PrecompiledScriptPluginAccessorsTest : AbstractPrecompiledScriptPluginTest """) build("generatePrecompiledScriptPluginAccessors") - existing("build/generated-sources/kotlin-dsl-accessors/kotlin").walk().filter { it.isFile }.forEach { - println("// CONTENT OF $it") - it.useLines { lines -> - lines.forEachIndexed { index, line -> - println("${index + 1}: $line") - } - } - println("================") - } compileKotlin() } From ddf7661de521dad2c12dfc678869b2627ee45e90 Mon Sep 17 00:00:00 2001 From: Gradleware Git Bot Date: Fri, 1 Mar 2019 22:08:02 +0100 Subject: [PATCH 285/853] Publish 5.3-20190301205408+0000 --- released-versions.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/released-versions.json b/released-versions.json index 1fc5459084d63..6574183ba08dd 100644 --- a/released-versions.json +++ b/released-versions.json @@ -1,7 +1,7 @@ { "latestReleaseSnapshot": { - "version": "5.3-20190301013223+0000", - "buildTime": "20190301013223+0000" + "version": "5.3-20190301205408+0000", + "buildTime": "20190301205408+0000" }, "latestRc": { "version": "5.2-rc-1", From 0c939d0112e7829c716c2b4e8bc3a0e9d4cb276b Mon Sep 17 00:00:00 2001 From: "Rodrigo B. de Oliveira" Date: Fri, 1 Mar 2019 18:08:29 -0300 Subject: [PATCH 286/853] Support type-safe accessors for plugins with a package declaration --- .../PrecompiledScriptPluginAccessorsTest.kt | 21 +++++++++++++++++++ .../ExtractPrecompiledScriptPluginPlugins.kt | 15 +++++++++++-- 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/subprojects/kotlin-dsl-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPluginAccessorsTest.kt b/subprojects/kotlin-dsl-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPluginAccessorsTest.kt index c9de27395cdd6..25e9e2f1616e1 100644 --- a/subprojects/kotlin-dsl-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPluginAccessorsTest.kt +++ b/subprojects/kotlin-dsl-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPluginAccessorsTest.kt @@ -201,6 +201,27 @@ class PrecompiledScriptPluginAccessorsTest : AbstractPrecompiledScriptPluginTest compileKotlin() } + @Test + fun `can apply sibling plugin from another package`() { + + withKotlinDslPlugin() + + withPrecompiledKotlinScript("my/java-plugin.gradle.kts", """ + package my + plugins { java } + """) + + withPrecompiledKotlinScript("plugins.gradle.kts", """ + plugins { id("my.java-plugin") } + + java { } + + tasks.compileJava { } + """) + + compileKotlin() + } + @Test fun `generated type-safe accessors are internal`() { diff --git a/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/ExtractPrecompiledScriptPluginPlugins.kt b/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/ExtractPrecompiledScriptPluginPlugins.kt index 3f2ec41f54fc1..9cf04cb435763 100644 --- a/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/ExtractPrecompiledScriptPluginPlugins.kt +++ b/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/ExtractPrecompiledScriptPluginPlugins.kt @@ -106,13 +106,24 @@ fun parse(scriptPlugin: PrecompiledScriptPlugin): Program = ProgramParser.parse( private -fun writePluginsBlockTo(outputDir: File, scriptPlugin: PrecompiledScriptPlugin, program: Program.Plugins) { +fun writePluginsBlockTo( + outputDir: File, + scriptPlugin: PrecompiledScriptPlugin, + program: Program.Plugins +) { outputDir.resolve(scriptPlugin.scriptFileName).writeText( - lineNumberPreservingTextOf(program) + packageDeclarationOf(scriptPlugin) + lineNumberPreservingTextOf(program) ) } +private +fun packageDeclarationOf(scriptPlugin: PrecompiledScriptPlugin): String = + scriptPlugin.packageName?.let { + "package $it; " + } ?: "" + + private fun lineNumberPreservingTextOf(program: Program.Plugins): String = program.fragment.run { source.map { it.subText(0..range.endInclusive).preserve(range) } From d60c20f38fef4c2eecbea966008eea7e4d510b48 Mon Sep 17 00:00:00 2001 From: Sterling Greene Date: Fri, 1 Mar 2019 16:39:54 -0500 Subject: [PATCH 287/853] Fix build-scan test --- .../plugin/autoapply/AutoAppliedPluginsFunctionalTest.groovy | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/subprojects/plugin-use/src/integTest/groovy/org/gradle/plugin/autoapply/AutoAppliedPluginsFunctionalTest.groovy b/subprojects/plugin-use/src/integTest/groovy/org/gradle/plugin/autoapply/AutoAppliedPluginsFunctionalTest.groovy index b70e432388420..36ef5ff9624bb 100644 --- a/subprojects/plugin-use/src/integTest/groovy/org/gradle/plugin/autoapply/AutoAppliedPluginsFunctionalTest.groovy +++ b/subprojects/plugin-use/src/integTest/groovy/org/gradle/plugin/autoapply/AutoAppliedPluginsFunctionalTest.groovy @@ -84,11 +84,9 @@ class AutoAppliedPluginsFunctionalTest extends AbstractPluginIntegrationTest { def result = gradleHandle.waitForFinish() result.assertHasPostBuildOutput(BUILD_SCAN_LICENSE_QUESTION) result.assertHasPostBuildOutput(BUILD_SCAN_LICENSE_DECLINATION) - result.assertHasPostBuildOutput(BUILD_SCAN_PLUGIN_CONFIG_PROBLEM) result.assertNotOutput(BUILD_SCAN_SUCCESSFUL_PUBLISHING) result.assertNotOutput(BUILD_SCAN_LICENSE_NOTE) - result.assertHasPostBuildOutput("The buildScan extension 'termsOfServiceAgree' value must be exactly the string 'yes' (without quotes).") - result.assertHasPostBuildOutput("The value given was 'no'.") + result.assertHasPostBuildOutput("You must answer 'yes' to publish a build scan when prompted on the command line or accept the Gradle Terms of Service in a buildScan configuration block.") } def "can auto-apply build scan plugin and cancel license acceptance with ctrl-d in interactive console"() { From a22d178e6b377c53603a5990ec3abc8630285930 Mon Sep 17 00:00:00 2001 From: "Rodrigo B. de Oliveira" Date: Fri, 1 Mar 2019 18:41:03 -0300 Subject: [PATCH 288/853] Support type-safe accessors for plugins with matching file names But different packages by reconstructing the package directory structure when extracting the plugins blocks. --- .../PrecompiledScriptPluginAccessorsTest.kt | 118 +++++++++++++----- .../ExtractPrecompiledScriptPluginPlugins.kt | 16 ++- 2 files changed, 105 insertions(+), 29 deletions(-) diff --git a/subprojects/kotlin-dsl-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPluginAccessorsTest.kt b/subprojects/kotlin-dsl-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPluginAccessorsTest.kt index 25e9e2f1616e1..d0d21645cd009 100644 --- a/subprojects/kotlin-dsl-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPluginAccessorsTest.kt +++ b/subprojects/kotlin-dsl-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPluginAccessorsTest.kt @@ -61,38 +61,14 @@ class PrecompiledScriptPluginAccessorsTest : AbstractPrecompiledScriptPluginTest @Test fun `can use type-safe accessors with same name but different meaning in sibling plugins`() { - withProjectRoot(newDir("external-plugins")) { - withDefaultSettings() - withKotlinDslPlugin() - withFolders { - "src/main/kotlin" { - "extensions" { - withFile("Extensions.kt", """ - open class App { var name: String = "app" } - open class Lib { var name: String = "lib" } - """) - } - withFile("external-app.gradle.kts", """ - extensions.create("external", App::class) - """) - withFile("external-lib.gradle.kts", """ - extensions.create("external", Lib::class) - """) - } - } - build("assemble") - } - - val externalPlugins = existing("external-plugins/build/libs/external-plugins.jar") + val externalPlugins = withExternalPlugins() withFolders { "buildSrc" { withDefaultSettingsIn(relativePath) - withKotlinDslPlugin().appendText(""" - dependencies { - implementation(files("${externalPlugins.normalisedPath}")) - } - """) + withKotlinDslPlugin().appendText( + implementationDependencyOn(externalPlugins) + ) withFile("src/main/kotlin/local-app.gradle.kts", """ plugins { `external-app` } @@ -133,6 +109,13 @@ class PrecompiledScriptPluginAccessorsTest : AbstractPrecompiledScriptPluginTest ) } + private + fun implementationDependencyOn(file: File): String = """ + dependencies { + implementation(files("${file.normalisedPath}")) + } + """ + @Test fun `can use type-safe accessors for the Kotlin Gradle plugin extensions`() { @@ -177,6 +160,60 @@ class PrecompiledScriptPluginAccessorsTest : AbstractPrecompiledScriptPluginTest compileKotlin() } + @Test + fun `can use type-safe accessors from scripts with same name but different ids`() { + + val externalPlugins = withExternalPlugins() + + withKotlinDslPlugin() + withKotlinBuildSrc() + withFolders { + "buildSrc" { + existing("build.gradle.kts").appendText( + implementationDependencyOn(externalPlugins) + ) + "src/main/kotlin" { + withFile("app/model.gradle.kts", """ + package app + plugins { `external-app` } + println("*using " + external.name + " from app/model in " + project.name + "*") + """) + withFile("lib/model.gradle.kts", """ + package lib + plugins { `external-lib` } + println("*using " + external.name + " from lib/model in " + project.name + "*") + """) + } + } + } + + withDefaultSettings().appendText(""" + include("lib") + include("app") + """) + + withFolders { + "lib" { + withFile("build.gradle.kts", """ + plugins { lib.model } + """) + } + "app" { + withFile("build.gradle.kts", """ + plugins { app.model } + """) + } + } + + assertThat( + build("tasks").output, + allOf( + containsString("*using app from app/model in app*"), + containsString("*using lib from lib/model in lib*") + ) + ) + } + @Test fun `can apply sibling plugin whether it has a plugins block or not`() { @@ -436,6 +473,31 @@ class PrecompiledScriptPluginAccessorsTest : AbstractPrecompiledScriptPluginTest ) } + private + fun withExternalPlugins(): File = + withProjectRoot(newDir("external-plugins")) { + withDefaultSettings() + withKotlinDslPlugin() + withFolders { + "src/main/kotlin" { + "extensions" { + withFile("Extensions.kt", """ + open class App { var name: String = "app" } + open class Lib { var name: String = "lib" } + """) + } + withFile("external-app.gradle.kts", """ + extensions.create("external", App::class) + """) + withFile("external-lib.gradle.kts", """ + extensions.create("external", Lib::class) + """) + } + } + build("assemble") + existing("build/libs/external-plugins.jar") + } + private fun FoldersDsl.withKotlinDslPlugin(): File = withKotlinDslPluginIn(relativePath) diff --git a/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/ExtractPrecompiledScriptPluginPlugins.kt b/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/ExtractPrecompiledScriptPluginPlugins.kt index 9cf04cb435763..66305b360adb7 100644 --- a/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/ExtractPrecompiledScriptPluginPlugins.kt +++ b/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/ExtractPrecompiledScriptPluginPlugins.kt @@ -111,12 +111,26 @@ fun writePluginsBlockTo( scriptPlugin: PrecompiledScriptPlugin, program: Program.Plugins ) { - outputDir.resolve(scriptPlugin.scriptFileName).writeText( + outputFileFor(scriptPlugin, outputDir).writeText( packageDeclarationOf(scriptPlugin) + lineNumberPreservingTextOf(program) ) } +private +fun outputFileFor(scriptPlugin: PrecompiledScriptPlugin, outputDir: File) = + packageDirFor(scriptPlugin, outputDir).resolve(scriptPlugin.scriptFileName) + + +private +fun packageDirFor(scriptPlugin: PrecompiledScriptPlugin, outputDir: File): File = + scriptPlugin.packageName?.run { + outputDir.resolve(replace('.', '/')).apply { + mkdirs() + } + } ?: outputDir + + private fun packageDeclarationOf(scriptPlugin: PrecompiledScriptPlugin): String = scriptPlugin.packageName?.let { From 0e2eaa0e9e6138505990b1d31bba3da0f0cde6d0 Mon Sep 17 00:00:00 2001 From: Gradleware Git Bot Date: Sat, 2 Mar 2019 00:34:56 +0100 Subject: [PATCH 289/853] Publish 5.3-20190301232024+0000 --- released-versions.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/released-versions.json b/released-versions.json index 6574183ba08dd..12af8605222bc 100644 --- a/released-versions.json +++ b/released-versions.json @@ -1,7 +1,7 @@ { "latestReleaseSnapshot": { - "version": "5.3-20190301205408+0000", - "buildTime": "20190301205408+0000" + "version": "5.3-20190301232024+0000", + "buildTime": "20190301232024+0000" }, "latestRc": { "version": "5.2-rc-1", From b7f99d4656675a791312f6c5856b87e447e213ba Mon Sep 17 00:00:00 2001 From: Sterling Greene Date: Fri, 1 Mar 2019 18:47:18 -0500 Subject: [PATCH 290/853] use latest nightly --- gradle/wrapper/gradle-wrapper.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 293542e9e1b83..f632acc7edeb1 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions-snapshots/gradle-5.3-20190227191816+0000-bin.zip +distributionUrl=https\://services.gradle.org/distributions-snapshots/gradle-5.3-20190301232024+0000-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists From 6a7c8e2f02ab1ac27c20659583d2cfb49ddd30b8 Mon Sep 17 00:00:00 2001 From: Sterling Greene Date: Fri, 1 Mar 2019 18:53:24 -0500 Subject: [PATCH 291/853] Add a little polish to release notes --- subprojects/docs/src/docs/release/notes.md | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/subprojects/docs/src/docs/release/notes.md b/subprojects/docs/src/docs/release/notes.md index bedc76b5e60c2..c79763c13a738 100644 --- a/subprojects/docs/src/docs/release/notes.md +++ b/subprojects/docs/src/docs/release/notes.md @@ -15,7 +15,6 @@ We would like to thank the following community contributors to this release of G [Ricardo Pereira](https://github.com/thc202), [Thad House](https://github.com/ThadHouse), [Joe Kutner](https://github.com/jkutner), -... TBD ... and [Josh Soref](https://github.com/jsoref). ## Upgrade Instructions @@ -28,7 +27,7 @@ Standalone downloads are available at [gradle.org/release-candidate](https://gra ## Feature variants, aka optional dependencies -Gradle now provides a powerful model for declaring features a library provides, known as [feature variants](userguide/feature_variants.html) : +Gradle now provides a powerful model for declaring features a library provides, known as [feature variants](userguide/feature_variants.html): ```groovy java { @@ -45,6 +44,12 @@ dependencies { Long story short, this can be used to model [optional dependencies](https://github.com/gradle/gradle/issues/867)! +### Gradle Module Metadata 1.0 + +Gradle Module Metadata is now 1.0. + +Gradle will automatically consume published Gradle Metadata, but to publish Gradle Metadata requires you to enable the `GRADLE_METADATA` feature preview. + ## Kotlin DSL ### Kotlin 1.3.21 @@ -98,10 +103,9 @@ plugins { See the [Precompiled script plugins](userguide/kotlin_dsl.html#kotdsl:precompiled_plugins) section of the user manual for more information. - ## Better help message on delete operation failure -The `:clean` task, all `Delete` tasks, and `project.delete {}` operations now provide a better help message when failing to delete files. The most frequent and hard to troubleshoot causes for failing to delete files are other processes holding file descriptors open, and concurrent writes. +The `clean` task, all `Delete` tasks, and `project.delete {}` operations now provide a better help message when failing to delete files. The most frequent and hard to troubleshoot causes for failing to delete files are other processes holding file descriptors open, and concurrent writes. The help message now displays each failed path, which may be helpful in identifying which process might be holding files open, and will also display any files that were created in the target directory after a delete failure, which may be helpful in identifying when a process is still writing to the directory. @@ -132,11 +136,6 @@ Execution failed for task ':clean'. Gradle now offers a public API to publish custom software components. Refer to the `SoftwareComponentFactory` javadocs for details or look at the `JavaPlugin` and `JavaPlaftormPlugin` which have been migrated to use this API. -### Gradle Module Metadata 1.0 - -Gradle Module Metadata is now 1.0. -Gradle will automatically consume published Gradle Metadata, but publication still requires to enable the `GRADLE_METADATA` feature preview. - ### Factory method for creating `ConfigurableFileCollection` instances using `ObjectFactory` Plugin and task implementations often need to create instances of various useful types, to provide a configurable model and DSL that is consistent with other Gradle plugins. One such type is `ConfigurableFileCollection`. In previous releases, plugins could use `Project.files()` or `ProjectLayout.configurableFiles()` to create instance of this type. However, these interfaces are not always available, for example in a `Settings` plugin (rather than a `Project` plugin) or in a nested model object. From 4a2ae181eadec0f1c4c60dd3b30d3b971e1b3735 Mon Sep 17 00:00:00 2001 From: Sterling Greene Date: Fri, 1 Mar 2019 19:42:19 -0500 Subject: [PATCH 292/853] Fix link --- subprojects/docs/src/docs/release/notes.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subprojects/docs/src/docs/release/notes.md b/subprojects/docs/src/docs/release/notes.md index c79763c13a738..764fb9b7cc182 100644 --- a/subprojects/docs/src/docs/release/notes.md +++ b/subprojects/docs/src/docs/release/notes.md @@ -25,7 +25,7 @@ Switch your build to use Gradle 5.3 RC1 by updating your wrapper properties: Standalone downloads are available at [gradle.org/release-candidate](https://gradle.org/release-candidate). -## Feature variants, aka optional dependencies +## Feature variants aka optional dependencies Gradle now provides a powerful model for declaring features a library provides, known as [feature variants](userguide/feature_variants.html): From 8eea1de58041f4b8670afba64404041c043cc76c Mon Sep 17 00:00:00 2001 From: Gradleware Git Bot Date: Sat, 2 Mar 2019 02:16:15 +0100 Subject: [PATCH 293/853] Publish 5.3-20190302010121+0000 --- released-versions.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/released-versions.json b/released-versions.json index 12af8605222bc..72ec3d23ee1de 100644 --- a/released-versions.json +++ b/released-versions.json @@ -1,7 +1,7 @@ { "latestReleaseSnapshot": { - "version": "5.3-20190301232024+0000", - "buildTime": "20190301232024+0000" + "version": "5.3-20190302010121+0000", + "buildTime": "20190302010121+0000" }, "latestRc": { "version": "5.2-rc-1", From 733d9707bab680db9ce05a939bffbe9db15b238e Mon Sep 17 00:00:00 2001 From: blindpirate Date: Sat, 2 Mar 2019 03:09:46 +0000 Subject: [PATCH 294/853] TeamCity change in 'Gradle / Check' project: commit current project settings --- .teamcity/Gradle_Check/pluginData/plugin-settings.xml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.teamcity/Gradle_Check/pluginData/plugin-settings.xml b/.teamcity/Gradle_Check/pluginData/plugin-settings.xml index 4d0460b3c6a2d..f8bace73a1954 100644 --- a/.teamcity/Gradle_Check/pluginData/plugin-settings.xml +++ b/.teamcity/Gradle_Check/pluginData/plugin-settings.xml @@ -3,14 +3,14 @@ + + + - - - - + From d376dfaa73cf647852323b42b5cf3b2d82ca3440 Mon Sep 17 00:00:00 2001 From: Bo Zhang Date: Sat, 2 Mar 2019 11:16:04 +0800 Subject: [PATCH 295/853] Update tagging plugin to 0.54 --- build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle.kts b/build.gradle.kts index 529b570608922..0d3d143fa0fbb 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -32,7 +32,7 @@ plugins { // We have to apply it here at the moment, so that when the build scan plugin is auto-applied via --scan can detect that // the plugin has been already applied. For that the plugin has to be applied with the new plugin DSL syntax. com.gradle.`build-scan` - id("org.gradle.ci.tag-single-build") version("0.53") + id("org.gradle.ci.tag-single-build") version("0.54") } defaultTasks("assemble") From 89b3045cd17202c6c4b801b2c6f9ec858bd828ef Mon Sep 17 00:00:00 2001 From: Bo Zhang Date: Sat, 2 Mar 2019 11:16:04 +0800 Subject: [PATCH 296/853] Update tagging plugin to 0.54 --- build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle.kts b/build.gradle.kts index 658a64f2412ac..4aa694b099705 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -32,7 +32,7 @@ plugins { // We have to apply it here at the moment, so that when the build scan plugin is auto-applied via --scan can detect that // the plugin has been already applied. For that the plugin has to be applied with the new plugin DSL syntax. com.gradle.`build-scan` - id("org.gradle.ci.tag-single-build") version("0.53") + id("org.gradle.ci.tag-single-build") version("0.54") } defaultTasks("assemble") From 6284db6a232c994af5d53cb0ad96c7636114fc64 Mon Sep 17 00:00:00 2001 From: "Rodrigo B. de Oliveira" Date: Sat, 2 Mar 2019 04:49:36 -0300 Subject: [PATCH 297/853] Polish `GeneratePrecompiledScriptPluginAccessors` - Extract explaining method - Reduce scope of utility data class usage and visibility - Move shared function --- .../precompiled/PrecompiledScriptPlugin.kt | 4 ++ .../ExtractPrecompiledScriptPluginPlugins.kt | 1 + ...eneratePrecompiledScriptPluginAccessors.kt | 42 ++++++++++--------- .../tasks/GenerateScriptPluginAdapters.kt | 1 + 4 files changed, 28 insertions(+), 20 deletions(-) diff --git a/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/PrecompiledScriptPlugin.kt b/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/PrecompiledScriptPlugin.kt index e0dbb37199263..edb711566d2af 100644 --- a/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/PrecompiledScriptPlugin.kt +++ b/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/PrecompiledScriptPlugin.kt @@ -112,6 +112,10 @@ data class PrecompiledScriptPlugin(internal val scriptFile: File) { } +internal +fun scriptPluginFilesOf(list: List) = list.map { it.scriptFile }.toSet() + + private fun packageNameOf(file: File): String? = packageNameOf(normaliseLineSeparators(file.readText())) diff --git a/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/ExtractPrecompiledScriptPluginPlugins.kt b/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/ExtractPrecompiledScriptPluginPlugins.kt index 66305b360adb7..6069da16815fe 100644 --- a/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/ExtractPrecompiledScriptPluginPlugins.kt +++ b/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/ExtractPrecompiledScriptPluginPlugins.kt @@ -33,6 +33,7 @@ import org.gradle.kotlin.dsl.execution.ProgramSource import org.gradle.kotlin.dsl.execution.ProgramTarget import org.gradle.kotlin.dsl.provider.plugins.precompiled.PrecompiledScriptPlugin +import org.gradle.kotlin.dsl.provider.plugins.precompiled.scriptPluginFilesOf import org.gradle.kotlin.dsl.support.KotlinScriptType diff --git a/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/GeneratePrecompiledScriptPluginAccessors.kt b/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/GeneratePrecompiledScriptPluginAccessors.kt index a3faba174fd91..ed5f1ab48c756 100644 --- a/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/GeneratePrecompiledScriptPluginAccessors.kt +++ b/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/GeneratePrecompiledScriptPluginAccessors.kt @@ -52,6 +52,7 @@ import org.gradle.kotlin.dsl.concurrent.writeFile import org.gradle.kotlin.dsl.precompile.PrecompiledScriptDependenciesResolver import org.gradle.kotlin.dsl.provider.plugins.precompiled.PrecompiledScriptPlugin +import org.gradle.kotlin.dsl.provider.plugins.precompiled.scriptPluginFilesOf import org.gradle.kotlin.dsl.support.KotlinScriptType import org.gradle.kotlin.dsl.support.serviceOf @@ -131,16 +132,17 @@ open class GeneratePrecompiledScriptPluginAccessors : ClassPathSensitiveCodeGene private fun IO.generateTypeSafeAccessorsFor(projectPlugins: List) { resolvePluginGraphOf(projectPlugins) - .groupBy { - it.plugins - }.let { + .groupBy( + { it.plugins }, + { it.scriptPlugin } + ).let { projectSchemaImpliedByPluginGroups(it) }.forEach { (projectSchema, scriptPlugins) -> writeTypeSafeAccessorsFor(projectSchema) for (scriptPlugin in scriptPlugins) { writeContentAddressableImplicitImportFor( - scriptPlugin, - projectSchema.packageName + projectSchema.packageName, + scriptPlugin ) } } @@ -154,7 +156,7 @@ open class GeneratePrecompiledScriptPluginAccessors : ClassPathSensitiveCodeGene } val pluginGraph = plugins.associate { - it.id to (scriptPluginsById[it.id]?.plugins ?: emptyList()) + it.id to pluginsAppliedBy(it, scriptPluginsById) } return reduceGraph(pluginGraph).asSequence().mapNotNull { (id, plugins) -> @@ -162,6 +164,10 @@ open class GeneratePrecompiledScriptPluginAccessors : ClassPathSensitiveCodeGene } } + private + fun pluginsAppliedBy(scriptPlugin: PrecompiledScriptPlugin, scriptPluginsById: Map) = + scriptPluginsById[scriptPlugin.id]?.plugins ?: emptyList() + private fun scriptPluginPluginsFor(projectPlugins: List) = sequence { val loader = createPluginsClassLoader() @@ -242,8 +248,8 @@ open class GeneratePrecompiledScriptPluginAccessors : ClassPathSensitiveCodeGene private fun projectSchemaImpliedByPluginGroups( - pluginGroupsPerRequests: Map, List> - ): Map> { + pluginGroupsPerRequests: Map, List> + ): Map> { val schemaBuilder = SyntheticProjectSchemaBuilder( Files.createTempDirectory(temporaryDir.toPath(), "project-").toFile(), @@ -251,12 +257,12 @@ open class GeneratePrecompiledScriptPluginAccessors : ClassPathSensitiveCodeGene ) return pluginGroupsPerRequests.flatMap { (uniquePluginRequests, scriptPlugins) -> try { - val schema = schemaBuilder.schemaFor(pluginRequestsFor(uniquePluginRequests, scriptPlugins.first().scriptPlugin)) + val schema = schemaBuilder.schemaFor(pluginRequestsFor(uniquePluginRequests, scriptPlugins.first())) val hashedSchema = HashedProjectSchema(schema) scriptPlugins.map { hashedSchema to it } } catch (error: Throwable) { reportProjectSchemaError(scriptPlugins, error) - emptyList>() + emptyList>() } }.groupBy( { (schema, _) -> schema }, @@ -276,13 +282,13 @@ open class GeneratePrecompiledScriptPluginAccessors : ClassPathSensitiveCodeGene } private - fun reportProjectSchemaError(plugins: List, error: Throwable) { + fun reportProjectSchemaError(plugins: List, error: Throwable) { logger.warn( plugins.joinToString( prefix = "Failed to generate type-safe Gradle model accessors for the following precompiled script plugins:\n", separator = "\n", postfix = "\n" - ) { " - " + projectRelativePathOf(it.scriptPlugin) }, + ) { " - " + projectRelativePathOf(it) }, error ) } @@ -304,13 +310,13 @@ open class GeneratePrecompiledScriptPluginAccessors : ClassPathSensitiveCodeGene } private - fun IO.writeContentAddressableImplicitImportFor(scriptPlugin: ScriptPluginPlugins, packageName: String) { + fun IO.writeContentAddressableImplicitImportFor(packageName: String, scriptPlugin: PrecompiledScriptPlugin) { io { writeFile(implicitImportFileFor(scriptPlugin), "$packageName.*".toByteArray()) } } private - fun implicitImportFileFor(scriptPluginPlugins: ScriptPluginPlugins): File = - metadataOutputDir.get().asFile.resolve(scriptPluginPlugins.scriptPlugin.hashString) + fun implicitImportFileFor(scriptPlugin: PrecompiledScriptPlugin): File = + metadataOutputDir.get().asFile.resolve(scriptPlugin.hashString) } @@ -390,12 +396,8 @@ data class HashedProjectSchema( } -internal +private data class ScriptPluginPlugins( val scriptPlugin: PrecompiledScriptPlugin, val plugins: List ) - - -internal -fun scriptPluginFilesOf(list: List) = list.map { it.scriptFile }.toSet() diff --git a/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/GenerateScriptPluginAdapters.kt b/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/GenerateScriptPluginAdapters.kt index 213ed42506ba3..4aaf4613fe27c 100644 --- a/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/GenerateScriptPluginAdapters.kt +++ b/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/GenerateScriptPluginAdapters.kt @@ -26,6 +26,7 @@ import org.gradle.api.tasks.PathSensitivity import org.gradle.api.tasks.TaskAction import org.gradle.kotlin.dsl.provider.plugins.precompiled.PrecompiledScriptPlugin +import org.gradle.kotlin.dsl.provider.plugins.precompiled.scriptPluginFilesOf import org.gradle.kotlin.dsl.support.normaliseLineSeparators From b10e4e52f679866f0e68eed19fceaf0886802a1d Mon Sep 17 00:00:00 2001 From: "Rodrigo B. de Oliveira" Date: Sat, 2 Mar 2019 04:58:40 -0300 Subject: [PATCH 298/853] Polish `GeneratePrecompiledScriptPluginAccessors` - Extract explaining method - Add argument names --- .../tasks/GeneratePrecompiledScriptPluginAccessors.kt | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/GeneratePrecompiledScriptPluginAccessors.kt b/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/GeneratePrecompiledScriptPluginAccessors.kt index ed5f1ab48c756..5ddd078cbe435 100644 --- a/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/GeneratePrecompiledScriptPluginAccessors.kt +++ b/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/GeneratePrecompiledScriptPluginAccessors.kt @@ -252,8 +252,8 @@ open class GeneratePrecompiledScriptPluginAccessors : ClassPathSensitiveCodeGene ): Map> { val schemaBuilder = SyntheticProjectSchemaBuilder( - Files.createTempDirectory(temporaryDir.toPath(), "project-").toFile(), - (classPathFiles + runtimeClassPathFiles).files + rootProjectDir = uniqueTempDirectory(), + rootProjectClassPath = (classPathFiles + runtimeClassPathFiles).files ) return pluginGroupsPerRequests.flatMap { (uniquePluginRequests, scriptPlugins) -> try { @@ -270,6 +270,9 @@ open class GeneratePrecompiledScriptPluginAccessors : ClassPathSensitiveCodeGene ) } + private + fun uniqueTempDirectory() = Files.createTempDirectory(temporaryDir.toPath(), "project-").toFile() + private fun pluginRequestsFor(pluginIds: List, plugin: PrecompiledScriptPlugin): PluginRequests = pluginRequestCollectorFor(plugin).run { From 6855338f907ebf50d0130f08d525c567f2a857bd Mon Sep 17 00:00:00 2001 From: Paul Merlin Date: Sat, 2 Mar 2019 20:17:46 +0100 Subject: [PATCH 299/853] Bump :kotlinDslPlugins version Signed-off-by: Paul Merlin --- subprojects/kotlin-dsl-plugins/kotlin-dsl-plugins.gradle.kts | 2 +- subprojects/kotlin-dsl/kotlin-dsl.gradle.kts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/subprojects/kotlin-dsl-plugins/kotlin-dsl-plugins.gradle.kts b/subprojects/kotlin-dsl-plugins/kotlin-dsl-plugins.gradle.kts index aad3b39851488..cf2aa2477f5ee 100644 --- a/subprojects/kotlin-dsl-plugins/kotlin-dsl-plugins.gradle.kts +++ b/subprojects/kotlin-dsl-plugins/kotlin-dsl-plugins.gradle.kts @@ -27,7 +27,7 @@ plugins { description = "Kotlin DSL Gradle Plugins deployed to the Plugin Portal" group = "org.gradle.kotlin" -version = "1.2.5" +version = "1.2.6" base.archivesBaseName = "plugins" diff --git a/subprojects/kotlin-dsl/kotlin-dsl.gradle.kts b/subprojects/kotlin-dsl/kotlin-dsl.gradle.kts index 65e1ec644ea6e..78bb1c93f3ea5 100644 --- a/subprojects/kotlin-dsl/kotlin-dsl.gradle.kts +++ b/subprojects/kotlin-dsl/kotlin-dsl.gradle.kts @@ -72,7 +72,7 @@ dependencies { // --- Enable automatic generation of API extensions ------------------- val apiExtensionsOutputDir = file("src/generated/kotlin") -val publishedKotlinDslPluginVersion = "1.2.4" // TODO:kotlin-dsl +val publishedKotlinDslPluginVersion = "1.2.5" // TODO:kotlin-dsl tasks { From e5e4390e05e6da9bd0a6eaf81477471078c3ab97 Mon Sep 17 00:00:00 2001 From: Gradleware Git Bot Date: Sun, 3 Mar 2019 02:14:48 +0100 Subject: [PATCH 300/853] Publish 5.3-20190303010057+0000 --- released-versions.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/released-versions.json b/released-versions.json index 72ec3d23ee1de..a724e6898eefa 100644 --- a/released-versions.json +++ b/released-versions.json @@ -1,7 +1,7 @@ { "latestReleaseSnapshot": { - "version": "5.3-20190302010121+0000", - "buildTime": "20190302010121+0000" + "version": "5.3-20190303010057+0000", + "buildTime": "20190303010057+0000" }, "latestRc": { "version": "5.2-rc-1", From c9913554c6032894bb4433789db2ee87a801123e Mon Sep 17 00:00:00 2001 From: Paul Merlin Date: Sun, 3 Mar 2019 11:03:06 +0100 Subject: [PATCH 301/853] Fix race condition in GeneratePrecompiledScriptPluginAccessors i/o Under load, e.g. --parallel, writing could have happened concurrently to the deletions. Observed in performance tests. Signed-off-by: Paul Merlin --- .../GeneratePrecompiledScriptPluginAccessors.kt | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/GeneratePrecompiledScriptPluginAccessors.kt b/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/GeneratePrecompiledScriptPluginAccessors.kt index 5ddd078cbe435..7c0b6c7451825 100644 --- a/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/GeneratePrecompiledScriptPluginAccessors.kt +++ b/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/GeneratePrecompiledScriptPluginAccessors.kt @@ -107,9 +107,10 @@ open class GeneratePrecompiledScriptPluginAccessors : ClassPathSensitiveCodeGene */ @TaskAction fun generate() { - withAsynchronousIO(project) { - recreateTaskDirectories() + recreateTaskDirectories() + + withAsynchronousIO(project) { val projectPlugins = selectProjectPlugins() if (projectPlugins.isNotEmpty()) { @@ -119,14 +120,9 @@ open class GeneratePrecompiledScriptPluginAccessors : ClassPathSensitiveCodeGene } private - fun IO.recreateTaskDirectories() { - // access dirs from main thread, recreate in IO thread - val taskTemporaryDir = temporaryDir - val metadataOutputDir = metadataOutputDir.get().asFile - io { - recreate(taskTemporaryDir) - recreate(metadataOutputDir) - } + fun recreateTaskDirectories() { + recreate(temporaryDir) + recreate(metadataOutputDir.get().asFile) } private From 3e2653a1345e8042020dce37664dd4537c99ed81 Mon Sep 17 00:00:00 2001 From: Stefan Wolf Date: Sun, 3 Mar 2019 14:29:30 +0100 Subject: [PATCH 302/853] Cleanup for #8650 (#8663) * Improve test for hasTypeVariable * Move resolving type variables to model core * Add more test coverage for resolving type variables --- .../internal/reflect/JavaReflectionUtil.java | 103 --------------- .../reflect/JavaReflectionUtilTest.groovy | 54 -------- .../JavaReflectionUtilTestMethods.java | 35 ----- .../instantiation/AbstractClassGenerator.java | 5 +- .../reflect/JavaPropertyReflectionUtil.java | 120 ++++++++++++++++++ .../JavaPropertyReflectionUtilTest.groovy | 42 ++++++ ...JavaPropertyReflectionUtilTestMethods.java | 58 +++++++++ 7 files changed, 221 insertions(+), 196 deletions(-) delete mode 100644 subprojects/base-services/src/test/groovy/org/gradle/internal/reflect/JavaReflectionUtilTest.groovy delete mode 100644 subprojects/base-services/src/test/groovy/org/gradle/internal/reflect/JavaReflectionUtilTestMethods.java create mode 100644 subprojects/model-core/src/test/groovy/org/gradle/internal/reflect/JavaPropertyReflectionUtilTestMethods.java diff --git a/subprojects/base-services/src/main/java/org/gradle/internal/reflect/JavaReflectionUtil.java b/subprojects/base-services/src/main/java/org/gradle/internal/reflect/JavaReflectionUtil.java index 113c08149085e..bef057e6af51d 100644 --- a/subprojects/base-services/src/main/java/org/gradle/internal/reflect/JavaReflectionUtil.java +++ b/subprojects/base-services/src/main/java/org/gradle/internal/reflect/JavaReflectionUtil.java @@ -17,16 +17,8 @@ package org.gradle.internal.reflect; import org.gradle.internal.UncheckedException; -import org.gradle.util.CollectionUtils; import java.lang.reflect.Constructor; -import java.lang.reflect.GenericArrayType; -import java.lang.reflect.ParameterizedType; -import java.lang.reflect.Type; -import java.lang.reflect.TypeVariable; -import java.lang.reflect.WildcardType; -import java.util.ArrayDeque; -import java.util.Queue; public class JavaReflectionUtil { @@ -63,99 +55,4 @@ public static T newInstance(Class c) { throw UncheckedException.throwAsUncheckedException(e); } } - - /** - * Checks if a type has a type variable which may require resolving. - */ - public static boolean hasTypeVariable(Type type) { - // do some checks up-front, so we avoid creating the queue in most cases - // Cases we want to handle: - // - List - // - Class - // - List> - // - Integer[] - // - ? extends BaseType - // - Class[] - if (doesNotHaveTypeVariable(type)) { - return false; - } - if (type instanceof TypeVariable) { - return true; - } - if (type instanceof ParameterizedType) { - ParameterizedType parameterizedType = (ParameterizedType) type; - boolean noTypeVariables = true; - for (Type actualTypeArgument : parameterizedType.getActualTypeArguments()) { - if (actualTypeArgument instanceof TypeVariable) { - return true; - } - noTypeVariables &= doesNotHaveTypeVariable(actualTypeArgument); - } - if (noTypeVariables) { - return false; - } - } - if (type instanceof GenericArrayType) { - GenericArrayType genericArrayType = (GenericArrayType) type; - if (genericArrayType.getGenericComponentType() instanceof TypeVariable) { - return true; - } - } - - // Type is more complicated, need to check everything. - Queue typesToInspect = new ArrayDeque(); - typesToInspect.add(type); - while (!typesToInspect.isEmpty()) { - Type typeToInspect = typesToInspect.remove(); - if (typeToInspect instanceof Class) { - continue; - } - if (typeToInspect instanceof TypeVariable) { - return true; - } - if (typeToInspect instanceof ParameterizedType) { - ParameterizedType parameterizedType = (ParameterizedType) typeToInspect; - CollectionUtils.addAll(typesToInspect, parameterizedType.getActualTypeArguments()); - } else if (typeToInspect instanceof GenericArrayType) { - GenericArrayType arrayType = (GenericArrayType) typeToInspect; - typesToInspect.add(arrayType.getGenericComponentType()); - } else if (typeToInspect instanceof WildcardType) { - WildcardType wildcardType = (WildcardType) typeToInspect; - CollectionUtils.addAll(typesToInspect, wildcardType.getLowerBounds()); - CollectionUtils.addAll(typesToInspect, wildcardType.getUpperBounds()); - } else { - // We don't know what the type is - let Guava take care of it. - return true; - } - } - return false; - } - - /** - * Quick check if a type does not have any type variables. - * - * Handled cases: - * - raw Class - * - Wildcard type with Class bounds, e.g. ? extends BaseType - */ - private static boolean doesNotHaveTypeVariable(Type type) { - if (type instanceof Class) { - return true; - } - if (type instanceof WildcardType) { - WildcardType wildcardType = (WildcardType) type; - for (Type lowerBound : wildcardType.getLowerBounds()) { - if (!(lowerBound instanceof Class)) { - return false; - } - } - for (Type upperBound : wildcardType.getUpperBounds()) { - if (!(upperBound instanceof Class)) { - return false; - } - } - return true; - } - return false; - } } diff --git a/subprojects/base-services/src/test/groovy/org/gradle/internal/reflect/JavaReflectionUtilTest.groovy b/subprojects/base-services/src/test/groovy/org/gradle/internal/reflect/JavaReflectionUtilTest.groovy deleted file mode 100644 index de72c0e7032e8..0000000000000 --- a/subprojects/base-services/src/test/groovy/org/gradle/internal/reflect/JavaReflectionUtilTest.groovy +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright 2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.gradle.internal.reflect - -import com.google.common.reflect.TypeToken -import org.gradle.testing.internal.util.Specification -import spock.lang.Unroll - -import java.util.function.BiConsumer - -class JavaReflectionUtilTest extends Specification { - - @Unroll - def "#type has type variable: #hasTypeVariable"() { - expect: - JavaReflectionUtil.hasTypeVariable(type.getType()) == hasTypeVariable - - where: - type | hasTypeVariable - new TypeToken>() {} | false - new TypeToken>() {} | false - new TypeToken[]>() {} | false - TypeToken.of(String.class) | false - TypeToken.of(String[].class) | false - new TypeToken>>>() {} | false - new TypeToken>>() {} | false - new TypeToken>>() {} | false - new TypeToken, List>>() {} | false - genericReturnType("simpleGenericReturnType") | true - genericReturnType("encapsulatedTypeVariable") | true - genericReturnType("arrayTypeWithTypeVariable") | true - genericReturnType("complexTypeWithTypeVariable") | true - genericReturnType("anotherComplexTypeWithTypeVariable") | true - genericReturnType("complexTypeWithArrayTypeVariable") | true - } - - private static TypeToken genericReturnType(String methodName) { - return TypeToken.of(JavaReflectionUtilTestMethods.getDeclaredMethod(methodName).genericReturnType) - } -} diff --git a/subprojects/base-services/src/test/groovy/org/gradle/internal/reflect/JavaReflectionUtilTestMethods.java b/subprojects/base-services/src/test/groovy/org/gradle/internal/reflect/JavaReflectionUtilTestMethods.java deleted file mode 100644 index 197afaa1c0d07..0000000000000 --- a/subprojects/base-services/src/test/groovy/org/gradle/internal/reflect/JavaReflectionUtilTestMethods.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright 2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.gradle.internal.reflect; - -import java.util.Collection; -import java.util.List; -import java.util.function.BiConsumer; - -public interface JavaReflectionUtilTestMethods { - T simpleGenericReturnType(); - - List encapsulatedTypeVariable(); - - T[] arrayTypeWithTypeVariable(); - - List>[]> complexTypeWithTypeVariable(); - - List>, ? extends List>[]> anotherComplexTypeWithTypeVariable(); - - List>, ? extends List>> complexTypeWithArrayTypeVariable(); -} diff --git a/subprojects/model-core/src/main/java/org/gradle/internal/instantiation/AbstractClassGenerator.java b/subprojects/model-core/src/main/java/org/gradle/internal/instantiation/AbstractClassGenerator.java index c6e211bf9cb9e..ab3281fdcf6fe 100644 --- a/subprojects/model-core/src/main/java/org/gradle/internal/instantiation/AbstractClassGenerator.java +++ b/subprojects/model-core/src/main/java/org/gradle/internal/instantiation/AbstractClassGenerator.java @@ -20,7 +20,6 @@ import com.google.common.collect.ImmutableSet; import com.google.common.collect.LinkedHashMultimap; import com.google.common.collect.SetMultimap; -import com.google.common.reflect.TypeToken; import groovy.lang.Closure; import groovy.lang.GroovyObject; import org.gradle.api.Action; @@ -43,7 +42,6 @@ import org.gradle.internal.reflect.ClassInspector; import org.gradle.internal.reflect.Instantiator; import org.gradle.internal.reflect.JavaPropertyReflectionUtil; -import org.gradle.internal.reflect.JavaReflectionUtil; import org.gradle.internal.reflect.MethodSet; import org.gradle.internal.reflect.PropertyAccessorType; import org.gradle.internal.reflect.PropertyDetails; @@ -453,8 +451,7 @@ public ClassMetadata(Class type) { * Determines the concrete return type of the given method, resolving any type parameters. */ public MethodMetadata resolveTypeVariables(Method method) { - Type returnType = method.getGenericReturnType(); - Type resolvedReturnType = JavaReflectionUtil.hasTypeVariable(returnType) ? TypeToken.of(type).method(method).getReturnType().getType() : returnType; + Type resolvedReturnType = JavaPropertyReflectionUtil.resolveMethodReturnType(type, method); return new MethodMetadata(method, resolvedReturnType); } diff --git a/subprojects/model-core/src/main/java/org/gradle/internal/reflect/JavaPropertyReflectionUtil.java b/subprojects/model-core/src/main/java/org/gradle/internal/reflect/JavaPropertyReflectionUtil.java index 68b9806bccbd9..d89edccc20948 100644 --- a/subprojects/model-core/src/main/java/org/gradle/internal/reflect/JavaPropertyReflectionUtil.java +++ b/subprojects/model-core/src/main/java/org/gradle/internal/reflect/JavaPropertyReflectionUtil.java @@ -16,14 +16,24 @@ package org.gradle.internal.reflect; +import com.google.common.reflect.TypeToken; import org.apache.commons.lang.reflect.MethodUtils; import org.gradle.internal.UncheckedException; +import org.gradle.util.CollectionUtils; import javax.annotation.Nullable; import java.lang.annotation.Annotation; import java.lang.annotation.Inherited; +import java.lang.reflect.GenericArrayType; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.lang.reflect.TypeVariable; +import java.lang.reflect.WildcardType; +import java.util.ArrayDeque; +import java.util.List; +import java.util.Queue; import java.util.Set; import java.util.WeakHashMap; @@ -152,6 +162,116 @@ public static boolean hasDefaultToString(Object object) { } } + /** + * Resolves the return type of a method in a given class. + * + * For example, for {@code MyList implements List}, resolving the return type of {@link List#get(int)} in {@code MyList} yields {@link String}. + */ + public static Type resolveMethodReturnType(Class type, Method method) { + Type returnType = method.getGenericReturnType(); + if (type.equals(method.getDeclaringClass())) { + // No need to resolve type parameters if the method is from the same class. + return returnType; + } + // Checking if there is a type variable to resolve, since resolving the type variable via `TypeToken` is quite expensive. + return hasTypeVariable(returnType) ? TypeToken.of(type).method(method).getReturnType().getType() : returnType; + } + + /** + * Checks if a type has a type variable which may require resolving. + */ + public static boolean hasTypeVariable(Type type) { + // do some checks up-front, so we avoid creating the queue in most cases + // Cases we want to handle: + // - List + // - Class + // - List> + // - Integer[] + // - ? extends BaseType + // - Class[] + if (doesNotHaveTypeVariable(type)) { + return false; + } + if (type instanceof TypeVariable) { + return true; + } + if (type instanceof ParameterizedType) { + ParameterizedType parameterizedType = (ParameterizedType) type; + boolean noTypeVariables = true; + for (Type actualTypeArgument : parameterizedType.getActualTypeArguments()) { + if (actualTypeArgument instanceof TypeVariable) { + return true; + } + noTypeVariables &= doesNotHaveTypeVariable(actualTypeArgument); + } + if (noTypeVariables) { + return false; + } + } + if (type instanceof GenericArrayType) { + GenericArrayType genericArrayType = (GenericArrayType) type; + if (genericArrayType.getGenericComponentType() instanceof TypeVariable) { + return true; + } + } + + // Type is more complicated, need to check everything. + Queue typesToInspect = new ArrayDeque(); + typesToInspect.add(type); + while (!typesToInspect.isEmpty()) { + Type typeToInspect = typesToInspect.remove(); + if (typeToInspect instanceof Class) { + continue; + } + if (typeToInspect instanceof TypeVariable) { + return true; + } + if (typeToInspect instanceof ParameterizedType) { + ParameterizedType parameterizedType = (ParameterizedType) typeToInspect; + CollectionUtils.addAll(typesToInspect, parameterizedType.getActualTypeArguments()); + } else if (typeToInspect instanceof GenericArrayType) { + GenericArrayType arrayType = (GenericArrayType) typeToInspect; + typesToInspect.add(arrayType.getGenericComponentType()); + } else if (typeToInspect instanceof WildcardType) { + WildcardType wildcardType = (WildcardType) typeToInspect; + CollectionUtils.addAll(typesToInspect, wildcardType.getLowerBounds()); + CollectionUtils.addAll(typesToInspect, wildcardType.getUpperBounds()); + } else { + // We don't know what the type is - let Guava take care of it. + return true; + } + } + return false; + } + + /** + * Quick check if a type does not have any type variables. + * + * Handled cases: + * - raw Class + * - Wildcard type with Class bounds, e.g. ? extends BaseType + */ + private static boolean doesNotHaveTypeVariable(Type type) { + if (type instanceof Class) { + return true; + } + if (type instanceof WildcardType) { + WildcardType wildcardType = (WildcardType) type; + for (Type lowerBound : wildcardType.getLowerBounds()) { + if (!(lowerBound instanceof Class)) { + return false; + } + } + for (Type upperBound : wildcardType.getUpperBounds()) { + if (!(upperBound instanceof Class)) { + return false; + } + } + return true; + } + return false; + } + private static class GetterMethodBackedPropertyAccessor implements PropertyAccessor { private final String property; private final Method method; diff --git a/subprojects/model-core/src/test/groovy/org/gradle/internal/reflect/JavaPropertyReflectionUtilTest.groovy b/subprojects/model-core/src/test/groovy/org/gradle/internal/reflect/JavaPropertyReflectionUtilTest.groovy index 16fa3f2173474..db26258cad21f 100644 --- a/subprojects/model-core/src/test/groovy/org/gradle/internal/reflect/JavaPropertyReflectionUtilTest.groovy +++ b/subprojects/model-core/src/test/groovy/org/gradle/internal/reflect/JavaPropertyReflectionUtilTest.groovy @@ -18,10 +18,12 @@ package org.gradle.internal.reflect import spock.lang.Specification +import spock.lang.Unroll import java.lang.annotation.Inherited import java.lang.annotation.Retention import java.lang.annotation.RetentionPolicy +import java.lang.reflect.Type import static JavaPropertyReflectionUtil.getAnnotation import static JavaPropertyReflectionUtil.hasDefaultToString @@ -262,6 +264,46 @@ class JavaPropertyReflectionUtilTest extends Specification { expect: !hasDefaultToString(new ClassWithToString()) } + + @Unroll + def "#type has type variable: #hasTypeVariable"() { + expect: + JavaPropertyReflectionUtil.hasTypeVariable(type) == hasTypeVariable + + where: + testType << testedTypes + type = testType.first + hasTypeVariable = testType.second + } + + @Unroll + def "#method.genericReturnType resolves to #expectedResolvedReturnType"() { + def resolvedReturnType = JavaPropertyReflectionUtil.resolveMethodReturnType(JavaPropertyReflectionUtilTestMethods.InterfaceRealizingTypeParameter, method) + expect: + resolvedReturnType.toString() == expectedResolvedReturnType + + where: + method << (JavaPropertyReflectionUtilTestMethods.getDeclaredMethods() as List) + expectedResolvedReturnType = method.genericReturnType.toString().replace("T", "java.util.List") + } + + @Unroll + def "#method.genericReturnType is not resolved if declared on same class"() { + def resolvedReturnType = JavaPropertyReflectionUtil.resolveMethodReturnType(JavaPropertyReflectionUtilTestMethods, method) + expect: + resolvedReturnType == method.genericReturnType + + where: + method << (JavaPropertyReflectionUtilTestMethods.getDeclaredMethods() as List) + } + + private static List> getTestedTypes() { + def testedTypes = JavaPropertyReflectionUtilTestMethods.getDeclaredMethods().collect { + new Tuple2(it.genericReturnType, it.name.contains('TypeVariable')) + } + assert testedTypes.size() == 16 + return testedTypes + } } @Retention(RetentionPolicy.RUNTIME) diff --git a/subprojects/model-core/src/test/groovy/org/gradle/internal/reflect/JavaPropertyReflectionUtilTestMethods.java b/subprojects/model-core/src/test/groovy/org/gradle/internal/reflect/JavaPropertyReflectionUtilTestMethods.java new file mode 100644 index 0000000000000..c525151818f30 --- /dev/null +++ b/subprojects/model-core/src/test/groovy/org/gradle/internal/reflect/JavaPropertyReflectionUtilTestMethods.java @@ -0,0 +1,58 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.internal.reflect; + +import java.util.Collection; +import java.util.List; +import java.util.function.BiConsumer; + +public interface JavaPropertyReflectionUtilTestMethods { + T simpleTypeVariable(); + + List encapsulatedTypeVariable(); + + T[] arrayTypeWithTypeVariable(); + + List>[]> complexTypeWithTypeVariable(); + + List>, ? extends List>[]> anotherComplexTypeWithTypeVariable(); + + List>, ? extends List>> complexTypeWithArrayTypeVariable(); + + Class wildcardParameterized(); + + Class parameterized(); + + Class[] genericArrayType(); + + String simpleType(); + + String[] simpleArrayType(); + + List>> complexParameterized(); + + List> wildCardWithlowerBound(); + + List> wildCardWithUpperBound(); + + BiConsumer, List> anotherComplexParameterized(); + + V nonResolvedTypeVariable(); + + interface InterfaceRealizingTypeParameter extends JavaPropertyReflectionUtilTestMethods> { + } +} From cae5d325b3e271d50557b394157641b02bbe2453 Mon Sep 17 00:00:00 2001 From: Paul Merlin Date: Sun, 3 Mar 2019 17:11:59 +0100 Subject: [PATCH 303/853] Rebaseline GradleBuildPerformanceTest comparing the build Broken by the introduction of precompiled script plugins Signed-off-by: Paul Merlin --- subprojects/performance/templates.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subprojects/performance/templates.gradle b/subprojects/performance/templates.gradle index 1aaec22ea7da5..3cd35d76cf02c 100644 --- a/subprojects/performance/templates.gradle +++ b/subprojects/performance/templates.gradle @@ -27,7 +27,7 @@ tasks.register("gradleBuildBaseline", RemoteProject) { remoteUri = rootDir.absolutePath // Remember to update accordingly when rebasing/squashing // Do not use the "Rebase and merge" nor "Squash and merge" Github buttons when merging a PR that change the baseline - ref = 'df9851e45acebbba9fa1e3fe2194b0e5346c20dd' + ref = 'c9913554c6032894bb4433789db2ee87a801123e' } // === Java === From 2f1ccceba5288d3e2185629817e87bfb485f151a Mon Sep 17 00:00:00 2001 From: Paul Merlin Date: Sun, 3 Mar 2019 17:12:28 +0100 Subject: [PATCH 304/853] Ignored failing tests for bug in precompiled script plugins tasks wiring To be fixed and un-ignored Signed-off-by: Paul Merlin --- .../PrecompiledScriptPluginIntegrationTest.kt | 75 +++++++++++++++++++ 1 file changed, 75 insertions(+) diff --git a/subprojects/kotlin-dsl-integ-tests/src/integTest/kotlin/org/gradle/kotlin/dsl/integration/PrecompiledScriptPluginIntegrationTest.kt b/subprojects/kotlin-dsl-integ-tests/src/integTest/kotlin/org/gradle/kotlin/dsl/integration/PrecompiledScriptPluginIntegrationTest.kt index f3662909446d6..c51465403d547 100644 --- a/subprojects/kotlin-dsl-integ-tests/src/integTest/kotlin/org/gradle/kotlin/dsl/integration/PrecompiledScriptPluginIntegrationTest.kt +++ b/subprojects/kotlin-dsl-integ-tests/src/integTest/kotlin/org/gradle/kotlin/dsl/integration/PrecompiledScriptPluginIntegrationTest.kt @@ -3,8 +3,11 @@ package org.gradle.kotlin.dsl.integration import org.gradle.kotlin.dsl.fixtures.normalisedPath import org.gradle.test.fixtures.file.LeaksFileHandles +import org.hamcrest.CoreMatchers.containsString import org.junit.Assert.assertFalse +import org.junit.Assert.assertThat import org.junit.Assert.assertTrue +import org.junit.Ignore import org.junit.Test @@ -134,4 +137,76 @@ class PrecompiledScriptPluginIntegrationTest : AbstractPluginIntegrationTest() { build("myTask") } + + @Test + @Ignore("BUG") // TODO:kotlin-dsl fix & un-ignore + fun `accessors are available after script body change`() { + + requireGradleDistributionOnEmbeddedExecuter() + + withKotlinBuildSrc() + val myPluginScript = withFile("buildSrc/src/main/kotlin/my-plugin.gradle.kts", """ + plugins { base } + + base.archivesBaseName = "my" + + println("base") + """) + + withDefaultSettings() + withBuildScript(""" + plugins { + `my-plugin` + } + """) + + build("help").apply { + assertThat(output, containsString("base")) + } + + // TODO if you uncomment that line, then the test pass ... + // build("help") + + myPluginScript.appendText(""" + + println("modified") + """.trimIndent()) + + build("help").apply { + // TODO :buildSrc:compileKotlin currently fails with `Unresolved reference 'base'` + // TODO no imports for accessors are provided to :buildSrc:compileKotlin + assertThat(output, containsString("base")) + assertThat(output, containsString("modified")) + } + } + + @Test + @Ignore("BUG") // TODO:kotlin-dsl fix & un-ignore + fun `accessors are available after re-running tasks`() { + + requireGradleDistributionOnEmbeddedExecuter() + + withKotlinBuildSrc() + withFile("buildSrc/src/main/kotlin/my-plugin.gradle.kts", """ + plugins { base } + + base.archivesBaseName = "my" + """) + + withDefaultSettings() + withBuildScript(""" + plugins { + `my-plugin` + } + """) + + build("clean") + + // TODO if you uncomment that line, then the test pass ... + // build("clean") + + // TODO :buildSrc:compileKotlin currently fails with `Unresolved reference 'base'` + // TODO no imports for psp accessors are provided to :buildSrc:compileKotlin + build("clean", "--rerun-tasks") + } } From 6942d01525acf160769a751cb622b115f8072004 Mon Sep 17 00:00:00 2001 From: Paul Merlin Date: Sun, 3 Mar 2019 18:25:51 +0100 Subject: [PATCH 305/853] Fix nested submission to i/o worker Signed-off-by: Paul Merlin --- .../tasks/GeneratePrecompiledScriptPluginAccessors.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/GeneratePrecompiledScriptPluginAccessors.kt b/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/GeneratePrecompiledScriptPluginAccessors.kt index 7c0b6c7451825..f1f56764da86a 100644 --- a/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/GeneratePrecompiledScriptPluginAccessors.kt +++ b/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/GeneratePrecompiledScriptPluginAccessors.kt @@ -310,7 +310,7 @@ open class GeneratePrecompiledScriptPluginAccessors : ClassPathSensitiveCodeGene private fun IO.writeContentAddressableImplicitImportFor(packageName: String, scriptPlugin: PrecompiledScriptPlugin) { - io { writeFile(implicitImportFileFor(scriptPlugin), "$packageName.*".toByteArray()) } + writeFile(implicitImportFileFor(scriptPlugin), "$packageName.*".toByteArray()) } private From e9cac1459186f1b5ee977127f2bfeca73cdcccea Mon Sep 17 00:00:00 2001 From: Paul Merlin Date: Sun, 3 Mar 2019 20:11:29 +0100 Subject: [PATCH 306/853] Fix GeneratePrecompiledScriptPluginAccessors task loading plugins {} and un-ignore affected tests now passing Signed-off-by: Paul Merlin --- .../PrecompiledScriptPluginIntegrationTest.kt | 13 ------------- .../GeneratePrecompiledScriptPluginAccessors.kt | 12 +++++------- 2 files changed, 5 insertions(+), 20 deletions(-) diff --git a/subprojects/kotlin-dsl-integ-tests/src/integTest/kotlin/org/gradle/kotlin/dsl/integration/PrecompiledScriptPluginIntegrationTest.kt b/subprojects/kotlin-dsl-integ-tests/src/integTest/kotlin/org/gradle/kotlin/dsl/integration/PrecompiledScriptPluginIntegrationTest.kt index c51465403d547..b256add8aed0a 100644 --- a/subprojects/kotlin-dsl-integ-tests/src/integTest/kotlin/org/gradle/kotlin/dsl/integration/PrecompiledScriptPluginIntegrationTest.kt +++ b/subprojects/kotlin-dsl-integ-tests/src/integTest/kotlin/org/gradle/kotlin/dsl/integration/PrecompiledScriptPluginIntegrationTest.kt @@ -7,7 +7,6 @@ import org.hamcrest.CoreMatchers.containsString import org.junit.Assert.assertFalse import org.junit.Assert.assertThat import org.junit.Assert.assertTrue -import org.junit.Ignore import org.junit.Test @@ -139,7 +138,6 @@ class PrecompiledScriptPluginIntegrationTest : AbstractPluginIntegrationTest() { } @Test - @Ignore("BUG") // TODO:kotlin-dsl fix & un-ignore fun `accessors are available after script body change`() { requireGradleDistributionOnEmbeddedExecuter() @@ -164,24 +162,18 @@ class PrecompiledScriptPluginIntegrationTest : AbstractPluginIntegrationTest() { assertThat(output, containsString("base")) } - // TODO if you uncomment that line, then the test pass ... - // build("help") - myPluginScript.appendText(""" println("modified") """.trimIndent()) build("help").apply { - // TODO :buildSrc:compileKotlin currently fails with `Unresolved reference 'base'` - // TODO no imports for accessors are provided to :buildSrc:compileKotlin assertThat(output, containsString("base")) assertThat(output, containsString("modified")) } } @Test - @Ignore("BUG") // TODO:kotlin-dsl fix & un-ignore fun `accessors are available after re-running tasks`() { requireGradleDistributionOnEmbeddedExecuter() @@ -202,11 +194,6 @@ class PrecompiledScriptPluginIntegrationTest : AbstractPluginIntegrationTest() { build("clean") - // TODO if you uncomment that line, then the test pass ... - // build("clean") - - // TODO :buildSrc:compileKotlin currently fails with `Unresolved reference 'base'` - // TODO no imports for psp accessors are provided to :buildSrc:compileKotlin build("clean", "--rerun-tasks") } } diff --git a/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/GeneratePrecompiledScriptPluginAccessors.kt b/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/GeneratePrecompiledScriptPluginAccessors.kt index f1f56764da86a..18b724156f8c7 100644 --- a/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/GeneratePrecompiledScriptPluginAccessors.kt +++ b/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/GeneratePrecompiledScriptPluginAccessors.kt @@ -67,6 +67,7 @@ import org.gradle.plugin.use.internal.PluginRequestCollector import org.gradle.testfixtures.ProjectBuilder import java.io.File +import java.net.URLClassLoader import java.nio.file.Files @@ -227,13 +228,10 @@ open class GeneratePrecompiledScriptPluginAccessors : ClassPathSensitiveCodeGene private fun createPluginsClassLoader(): ClassLoader = - classLoaderScopeRegistry() - .coreAndPluginsScope - .createChild("$path/precompiled-script-plugins").run { - local(compiledPluginsClassPath()) - lock() - localClassLoader - } + URLClassLoader( + compiledPluginsClassPath().asURLArray, + classLoaderScopeRegistry().coreAndPluginsScope.localClassLoader + ) private fun classLoaderScopeRegistry() = project.serviceOf() From b2e9f6b0bed26fb63d2558b1f742e1203c214a94 Mon Sep 17 00:00:00 2001 From: Paul Merlin Date: Sun, 3 Mar 2019 20:14:46 +0100 Subject: [PATCH 307/853] Simplify :configurePrecompiledScriptDependenciesResolver dependencies Signed-off-by: Paul Merlin --- .../precompiled/DefaultPrecompiledScriptPluginsSupport.kt | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/DefaultPrecompiledScriptPluginsSupport.kt b/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/DefaultPrecompiledScriptPluginsSupport.kt index 9632479e921a3..ee392a2e15052 100644 --- a/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/DefaultPrecompiledScriptPluginsSupport.kt +++ b/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/DefaultPrecompiledScriptPluginsSupport.kt @@ -206,10 +206,7 @@ fun Project.enableScriptCompilationOf( } val configurePrecompiledScriptDependenciesResolver by registering(ConfigurePrecompiledScriptDependenciesResolver::class) { - dependsOn(generateExternalPluginSpecBuilders) - inputs.files( - project.files(generatedMetadata).builtBy(generatePrecompiledScriptPluginAccessors) - ) + dependsOn(generatePrecompiledScriptPluginAccessors) metadataDir.set(generatedMetadata) } From bd41bf5fdb0972c460b7f25c9dbb2e4d6b149dc8 Mon Sep 17 00:00:00 2001 From: Paul Merlin Date: Sun, 3 Mar 2019 20:18:14 +0100 Subject: [PATCH 308/853] Let :generatePrecompiledScriptPluginAccessors clean its output dir Signed-off-by: Paul Merlin --- .../tasks/GeneratePrecompiledScriptPluginAccessors.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/GeneratePrecompiledScriptPluginAccessors.kt b/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/GeneratePrecompiledScriptPluginAccessors.kt index 18b724156f8c7..7c1f616a4022b 100644 --- a/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/GeneratePrecompiledScriptPluginAccessors.kt +++ b/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/GeneratePrecompiledScriptPluginAccessors.kt @@ -123,6 +123,7 @@ open class GeneratePrecompiledScriptPluginAccessors : ClassPathSensitiveCodeGene private fun recreateTaskDirectories() { recreate(temporaryDir) + recreate(sourceCodeOutputDir.get().asFile) recreate(metadataOutputDir.get().asFile) } From 97daec3209ffcad9d0f39cc0ba1e3faca19cee7e Mon Sep 17 00:00:00 2001 From: Paul Merlin Date: Sun, 3 Mar 2019 20:34:05 +0100 Subject: [PATCH 309/853] Limit dir count in build/ on projects with precompiled script plugins Signed-off-by: Paul Merlin --- .../DefaultPrecompiledScriptPluginsSupport.kt | 2 +- .../tooling/builders/KotlinBuildScriptModelBuilder.kt | 11 ++++++++--- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/DefaultPrecompiledScriptPluginsSupport.kt b/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/DefaultPrecompiledScriptPluginsSupport.kt index ee392a2e15052..2b9396f1bce18 100644 --- a/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/DefaultPrecompiledScriptPluginsSupport.kt +++ b/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/DefaultPrecompiledScriptPluginsSupport.kt @@ -157,7 +157,7 @@ fun Project.enableScriptCompilationOf( val compiledPluginsBlocks = buildDir("kotlin-dsl/plugins-blocks/compiled") - val generatedMetadata = buildDir("precompiled-script-plugins") + val generatedMetadata = buildDir("kotlin-dsl/precompiled-script-plugins-metadata") val compileClasspath by lazy { compileClasspath() } diff --git a/subprojects/kotlin-dsl-tooling-builders/src/main/kotlin/org/gradle/kotlin/dsl/tooling/builders/KotlinBuildScriptModelBuilder.kt b/subprojects/kotlin-dsl-tooling-builders/src/main/kotlin/org/gradle/kotlin/dsl/tooling/builders/KotlinBuildScriptModelBuilder.kt index 267bf73ea45db..0e90ae77916bc 100644 --- a/subprojects/kotlin-dsl-tooling-builders/src/main/kotlin/org/gradle/kotlin/dsl/tooling/builders/KotlinBuildScriptModelBuilder.kt +++ b/subprojects/kotlin-dsl-tooling-builders/src/main/kotlin/org/gradle/kotlin/dsl/tooling/builders/KotlinBuildScriptModelBuilder.kt @@ -207,16 +207,21 @@ fun precompiledScriptPluginModelBuilder( scriptClassPath = DefaultClassPath.of(enclosingSourceSet.sourceSet.compileClasspath), enclosingScriptProjectDir = enclosingSourceSet.project.projectDir, additionalImports = { - val metadataDir = enclosingSourceSet.project.buildDir.resolve("precompiled-script-plugins") - require(metadataDir.isDirectory) implicitImportsFor( hashOf(scriptFile), - metadataDir + enclosingSourceSet.project.precompiledScriptPluginsMetadataDir ) ?: emptyList() } ) +private +val Project.precompiledScriptPluginsMetadataDir: File + get() = buildDir.resolve("kotlin-dsl/precompiled-script-plugins-metadata").apply { + require(isDirectory) + } + + private fun implicitImportsFor(precompiledScriptPluginHash: String, metadataDir: File): List? = metadataDir From 5a82fd7460890dab88b424dae085b3d7446887db Mon Sep 17 00:00:00 2001 From: Gradleware Git Bot Date: Mon, 4 Mar 2019 02:34:04 +0100 Subject: [PATCH 310/853] Publish 5.3-20190304012021+0000 --- released-versions.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/released-versions.json b/released-versions.json index a724e6898eefa..aa10adc6aa961 100644 --- a/released-versions.json +++ b/released-versions.json @@ -1,7 +1,7 @@ { "latestReleaseSnapshot": { - "version": "5.3-20190303010057+0000", - "buildTime": "20190303010057+0000" + "version": "5.3-20190304012021+0000", + "buildTime": "20190304012021+0000" }, "latestRc": { "version": "5.2-rc-1", From 376ae25a811171dcc3706415dcc0bd05407b25c1 Mon Sep 17 00:00:00 2001 From: Sterling Greene Date: Sun, 3 Mar 2019 23:29:51 -0500 Subject: [PATCH 311/853] Use checkstyle.html, not codenarc.html in Checkstyle example --- .../groovy/org/gradle/api/plugins/quality/Checkstyle.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/subprojects/code-quality/src/main/groovy/org/gradle/api/plugins/quality/Checkstyle.java b/subprojects/code-quality/src/main/groovy/org/gradle/api/plugins/quality/Checkstyle.java index 9da57d81feb9d..8630cc0899aa1 100644 --- a/subprojects/code-quality/src/main/groovy/org/gradle/api/plugins/quality/Checkstyle.java +++ b/subprojects/code-quality/src/main/groovy/org/gradle/api/plugins/quality/Checkstyle.java @@ -106,7 +106,7 @@ public IsolatedAntBuilder getAntBuilder() { * checkstyleTask { * reports { * html { - * destination "build/codenarc.html" + * destination "build/checkstyle.html" * } * } * } @@ -128,7 +128,7 @@ public CheckstyleReports reports(@DelegatesTo(value=CheckstyleReports.class, str * checkstyleTask { * reports { * html { - * destination "build/codenarc.html" + * destination "build/checkstyle.html" * } * } * } From 5fd550ed3012614a3ef6888d8fd7d33190d869b0 Mon Sep 17 00:00:00 2001 From: Sterling Greene Date: Sun, 3 Mar 2019 23:53:29 -0500 Subject: [PATCH 312/853] Polish PMD javadocs --- .../org/gradle/api/plugins/quality/Pmd.java | 31 +++++++++++----- .../api/plugins/quality/PmdExtension.java | 35 +++++++++++++------ 2 files changed, 47 insertions(+), 19 deletions(-) diff --git a/subprojects/code-quality/src/main/groovy/org/gradle/api/plugins/quality/Pmd.java b/subprojects/code-quality/src/main/groovy/org/gradle/api/plugins/quality/Pmd.java index af108dbc09702..0b396deaaab4a 100644 --- a/subprojects/code-quality/src/main/groovy/org/gradle/api/plugins/quality/Pmd.java +++ b/subprojects/code-quality/src/main/groovy/org/gradle/api/plugins/quality/Pmd.java @@ -147,7 +147,9 @@ public void setPmdClasspath(FileCollection pmdClasspath) { /** * The built-in rule sets to be used. See the official list of built-in rule sets. * - * Example: ruleSets = ["basic", "braces"] + *
    +     *     ruleSets = ["basic", "braces"]
    +     * 
    */ @Input public List getRuleSets() { @@ -157,7 +159,9 @@ public List getRuleSets() { /** * The built-in rule sets to be used. See the official list of built-in rule sets. * - * Example: ruleSets = ["basic", "braces"] + *
    +     *     ruleSets = ["basic", "braces"]
    +     * 
    */ public void setRuleSets(List ruleSets) { this.ruleSets = ruleSets; @@ -183,7 +187,9 @@ public void setTargetJdk(TargetJdk targetJdk) { * * See the official documentation for how to author a rule set. * - * Example: ruleSetConfig = resources.text.fromFile(resources.file("config/pmd/myRuleSets.xml")) + *
    +     *     ruleSetConfig = resources.text.fromFile(resources.file("config/pmd/myRuleSets.xml"))
    +     * 
    * * @since 2.2 */ @@ -199,7 +205,9 @@ public TextResource getRuleSetConfig() { * * See the official documentation for how to author a rule set. * - * Example: ruleSetConfig = resources.text.fromFile(resources.file("config/pmd/myRuleSets.xml")) + *
    +     *     ruleSetConfig = resources.text.fromFile(resources.file("config/pmd/myRuleSets.xml"))
    +     * 
    * * @since 2.2 */ @@ -209,8 +217,11 @@ public void setRuleSetConfig(@Nullable TextResource ruleSetConfig) { /** * The custom rule set files to be used. See the official documentation for how to author a rule set file. + * If you want to only use custom rule sets, you must clear {@code ruleSets}. * - * Example: ruleSetFiles = files("config/pmd/myRuleSets.xml") + *
    +     *     ruleSetFiles = files("config/pmd/myRuleSet.xml")
    +     * 
    */ @InputFiles @PathSensitive(PathSensitivity.NONE) @@ -225,8 +236,6 @@ public FileCollection getRuleSetFiles() { *
          *     ruleSetFiles = files("config/pmd/myRuleSets.xml")
          * 
    - * - * If you want to only use custom rule sets, you must clear {@code ruleSets}. */ public void setRuleSetFiles(FileCollection ruleSetFiles) { this.ruleSetFiles = ruleSetFiles; @@ -243,7 +252,9 @@ public final PmdReports getReports() { /** * Whether or not to allow the build to continue if there are warnings. * - * Example: ignoreFailures = true + *
    +     *     ignoreFailures = true
    +     * 
    */ public boolean getIgnoreFailures() { return ignoreFailures; @@ -253,7 +264,9 @@ public boolean getIgnoreFailures() { /** * Whether or not to allow the build to continue if there are warnings. * - * Example: ignoreFailures = true + *
    +     *     ignoreFailures = true
    +     * 
    */ public void setIgnoreFailures(boolean ignoreFailures) { this.ignoreFailures = ignoreFailures; diff --git a/subprojects/code-quality/src/main/groovy/org/gradle/api/plugins/quality/PmdExtension.java b/subprojects/code-quality/src/main/groovy/org/gradle/api/plugins/quality/PmdExtension.java index c5af5fd56edb2..b035ba51917c6 100644 --- a/subprojects/code-quality/src/main/groovy/org/gradle/api/plugins/quality/PmdExtension.java +++ b/subprojects/code-quality/src/main/groovy/org/gradle/api/plugins/quality/PmdExtension.java @@ -47,7 +47,9 @@ public PmdExtension(Project project) { /** * The built-in rule sets to be used. See the official list of built-in rule sets. * - * Example: ruleSets = ["category/java/errorprone.xml", "category/java/bestpractices.xml"] + *
    +     *     ruleSets = ["category/java/errorprone.xml", "category/java/bestpractices.xml"]
    +     * 
    */ public List getRuleSets() { return ruleSets; @@ -56,7 +58,9 @@ public List getRuleSets() { /** * The built-in rule sets to be used. See the official list of built-in rule sets. * - * Example: ruleSets = ["category/java/errorprone.xml", "category/java/bestpractices.xml"] + *
    +     *     ruleSets = ["category/java/errorprone.xml", "category/java/bestpractices.xml"]
    +     * 
    */ public void setRuleSets(List ruleSets) { this.ruleSets = ruleSets; @@ -65,7 +69,9 @@ public void setRuleSets(List ruleSets) { /** * Convenience method for adding rule sets. * - * Example: ruleSets "category/java/errorprone.xml", "category/java/bestpractices.xml" + *
    +     *     ruleSets "category/java/errorprone.xml", "category/java/bestpractices.xml"
    +     * 
    * * @param ruleSets the rule sets to be added */ @@ -106,7 +112,9 @@ public void setTargetJdk(Object value) { * * See the official documentation for the list of priorities. * - * Example: rulePriority = 3 + *
    +     *     rulePriority = 3
    +     * 
    */ public int getRulePriority() { return rulePriority; @@ -125,7 +133,9 @@ public void setRulePriority(int intValue) { * * See the official documentation for how to author a rule set. * - * Example: ruleSetConfig = resources.text.fromFile("config/pmd/myRuleSet.xml") + *
    +     *     ruleSetConfig = resources.text.fromFile("config/pmd/myRuleSet.xml")
    +     * 
    * * @since 2.2 */ @@ -139,7 +149,9 @@ public TextResource getRuleSetConfig() { * * See the official documentation for how to author a rule set. * - * Example: ruleSetConfig = resources.text.fromFile("config/pmd/myRuleSet.xml") + *
    +     *     ruleSetConfig = resources.text.fromFile("config/pmd/myRuleSet.xml")
    +     * 
    * * @since 2.2 */ @@ -149,8 +161,11 @@ public void setRuleSetConfig(@Nullable TextResource ruleSetConfig) { /** * The custom rule set files to be used. See the official documentation for how to author a rule set file. + * If you want to only use custom rule sets, you must clear {@code ruleSets}. * - * Example: ruleSetFiles = files("config/pmd/myRuleSet.xml") + *
    +     *     ruleSetFiles = files("config/pmd/myRuleSet.xml")
    +     * 
    */ public FileCollection getRuleSetFiles() { return ruleSetFiles; @@ -163,8 +178,6 @@ public FileCollection getRuleSetFiles() { *
          *     ruleSetFiles = files("config/pmd/myRuleSets.xml")
          * 
    - * - * If you want to only use custom rule sets, you must clear {@code ruleSets}. */ public void setRuleSetFiles(FileCollection ruleSetFiles) { this.ruleSetFiles = project.getObjects().fileCollection().from(ruleSetFiles); @@ -173,7 +186,9 @@ public void setRuleSetFiles(FileCollection ruleSetFiles) { /** * Convenience method for adding rule set files. * - * Example: ruleSetFiles "config/pmd/myRuleSet.xml" + *
    +     *     ruleSetFiles "config/pmd/myRuleSet.xml"
    +     * 
    * * @param ruleSetFiles the rule set files to be added */ From ee0d4e8576072a78449b3ef2bc6844e2a7a21906 Mon Sep 17 00:00:00 2001 From: Paul Merlin Date: Mon, 4 Mar 2019 08:36:30 +0100 Subject: [PATCH 313/853] Let SyntheticProjectSchemaBuilder reuse outer build gradle user home dir Signed-off-by: Paul Merlin --- .../GeneratePrecompiledScriptPluginAccessors.kt | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/GeneratePrecompiledScriptPluginAccessors.kt b/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/GeneratePrecompiledScriptPluginAccessors.kt index 7c1f616a4022b..e9dc8f4cc41c0 100644 --- a/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/GeneratePrecompiledScriptPluginAccessors.kt +++ b/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/GeneratePrecompiledScriptPluginAccessors.kt @@ -247,6 +247,7 @@ open class GeneratePrecompiledScriptPluginAccessors : ClassPathSensitiveCodeGene ): Map> { val schemaBuilder = SyntheticProjectSchemaBuilder( + gradleUserHomeDir = project.gradle.gradleUserHomeDir, rootProjectDir = uniqueTempDirectory(), rootProjectClassPath = (classPathFiles + runtimeClassPathFiles).files ) @@ -319,10 +320,14 @@ open class GeneratePrecompiledScriptPluginAccessors : ClassPathSensitiveCodeGene internal -class SyntheticProjectSchemaBuilder(rootProjectDir: File, rootProjectClassPath: Collection) { +class SyntheticProjectSchemaBuilder( + gradleUserHomeDir: File, + rootProjectDir: File, + rootProjectClassPath: Collection +) { private - val rootProject = buildRootProject(rootProjectDir, rootProjectClassPath) + val rootProject = buildRootProject(gradleUserHomeDir, rootProjectDir, rootProjectClassPath) fun schemaFor(plugins: PluginRequests): TypedProjectSchema = schemaFor(childProjectWith(plugins)) @@ -341,9 +346,14 @@ class SyntheticProjectSchemaBuilder(rootProjectDir: File, rootProjectClassPath: } private - fun buildRootProject(projectDir: File, rootProjectClassPath: Collection): Project { + fun buildRootProject( + gradleUserHomeDir: File, + projectDir: File, + rootProjectClassPath: Collection + ): Project { val project = ProjectBuilder.builder() + .withGradleUserHomeDir(gradleUserHomeDir) .withProjectDir(projectDir) .build() From 72d3773747d2bbf7a17cbfcde93ea8dfd45859d4 Mon Sep 17 00:00:00 2001 From: Paul Merlin Date: Mon, 4 Mar 2019 10:29:38 +0100 Subject: [PATCH 314/853] Temporarily ignore 'buildSrc api change in gradleBuildCurrent comparing gradle' Signed-off-by: Paul Merlin --- .../regression/inception/GradleInceptionPerformanceTest.groovy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subprojects/performance/src/performanceTest/groovy/org/gradle/performance/regression/inception/GradleInceptionPerformanceTest.groovy b/subprojects/performance/src/performanceTest/groovy/org/gradle/performance/regression/inception/GradleInceptionPerformanceTest.groovy index f9ca35757e9c2..20443abaede98 100644 --- a/subprojects/performance/src/performanceTest/groovy/org/gradle/performance/regression/inception/GradleInceptionPerformanceTest.groovy +++ b/subprojects/performance/src/performanceTest/groovy/org/gradle/performance/regression/inception/GradleInceptionPerformanceTest.groovy @@ -111,6 +111,6 @@ class GradleInceptionPerformanceTest extends AbstractCrossVersionPerformanceTest MEDIUM_MONOLITHIC_JAVA_PROJECT | "" | 40 LARGE_JAVA_MULTI_PROJECT | "" | 20 LARGE_JAVA_MULTI_PROJECT_KOTLIN_DSL | "" | 10 - 'gradleBuildCurrent' | "subprojects/build/" | 10 + // TODO:kotlin-dsl 'gradleBuildCurrent' | "subprojects/build/" | 10 } } From 41014e860f6f8210ebfc8ea88efbe87dabf4fbe2 Mon Sep 17 00:00:00 2001 From: "Rodrigo B. de Oliveira" Date: Mon, 4 Mar 2019 10:50:20 -0300 Subject: [PATCH 315/853] Clarify Kotlin DSL TODO --- .../plugins/precompiled/tasks/ClassPathSensitiveTask.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/ClassPathSensitiveTask.kt b/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/ClassPathSensitiveTask.kt index d6380c1eb6a76..674a4c9264ba8 100644 --- a/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/ClassPathSensitiveTask.kt +++ b/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/ClassPathSensitiveTask.kt @@ -35,7 +35,7 @@ abstract class ClassPathSensitiveTask : DefaultTask() { @get:Classpath lateinit var classPathFiles: FileCollection - // Todo: Replaced all of this by HashedClasspath + // TODO:kotlin-dsl Replace (classPathFiles, classPath, classPathHash) by a single HashedClassPath instance shared by all tasks @get:Internal protected val classPath by lazy { From dd0fb4a23429635db0687587bc7c7bab1ca124d0 Mon Sep 17 00:00:00 2001 From: Daniel Lacasse Date: Mon, 4 Mar 2019 09:00:46 -0500 Subject: [PATCH 316/853] Move the Gradle metadata 1.0 annoucement under the right section --- subprojects/docs/src/docs/release/notes.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/subprojects/docs/src/docs/release/notes.md b/subprojects/docs/src/docs/release/notes.md index 764fb9b7cc182..c16000164feb5 100644 --- a/subprojects/docs/src/docs/release/notes.md +++ b/subprojects/docs/src/docs/release/notes.md @@ -44,12 +44,6 @@ dependencies { Long story short, this can be used to model [optional dependencies](https://github.com/gradle/gradle/issues/867)! -### Gradle Module Metadata 1.0 - -Gradle Module Metadata is now 1.0. - -Gradle will automatically consume published Gradle Metadata, but to publish Gradle Metadata requires you to enable the `GRADLE_METADATA` feature preview. - ## Kotlin DSL ### Kotlin 1.3.21 @@ -136,6 +130,12 @@ Execution failed for task ':clean'. Gradle now offers a public API to publish custom software components. Refer to the `SoftwareComponentFactory` javadocs for details or look at the `JavaPlugin` and `JavaPlaftormPlugin` which have been migrated to use this API. +### Gradle Module Metadata 1.0 + +Gradle Module Metadata is now 1.0. + +Gradle will automatically consume published Gradle Metadata, but to publish Gradle Metadata requires you to enable the `GRADLE_METADATA` feature preview. + ### Factory method for creating `ConfigurableFileCollection` instances using `ObjectFactory` Plugin and task implementations often need to create instances of various useful types, to provide a configurable model and DSL that is consistent with other Gradle plugins. One such type is `ConfigurableFileCollection`. In previous releases, plugins could use `Project.files()` or `ProjectLayout.configurableFiles()` to create instance of this type. However, these interfaces are not always available, for example in a `Settings` plugin (rather than a `Project` plugin) or in a nested model object. From c764b8a0e62ebcdfc7bafd7137ae7f8416220955 Mon Sep 17 00:00:00 2001 From: Daniel Lacasse Date: Mon, 4 Mar 2019 09:01:11 -0500 Subject: [PATCH 317/853] Fix strange separation in contributor list --- subprojects/docs/src/docs/release/notes.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/subprojects/docs/src/docs/release/notes.md b/subprojects/docs/src/docs/release/notes.md index c16000164feb5..7dfb5d4b65dc7 100644 --- a/subprojects/docs/src/docs/release/notes.md +++ b/subprojects/docs/src/docs/release/notes.md @@ -6,9 +6,9 @@ type-safe accessors in Kotlin pre-compiled script plugins, and more. We would like to thank the following community contributors to this release of Gradle: -[Stefan M.](https://github.com/StefMa), -[Evgeny Mandrikov](https://github.com/Godin), -[Simon Legner](https://github.com/simon04), +[Stefan M.](https://github.com/StefMa), +[Evgeny Mandrikov](https://github.com/Godin), +[Simon Legner](https://github.com/simon04), [Raman Gupta](https://github.com/rocketraman), [Florian Dreier](https://github.com/DreierF), [Kenzie Togami](https://github.com/kenzierocks), From 26a989e198eb07c3e759ea53dee25d7344648aa8 Mon Sep 17 00:00:00 2001 From: Louis Jacomet Date: Fri, 1 Mar 2019 18:08:54 +0100 Subject: [PATCH 318/853] Rename category attribute Attribute is now `org.gradle.category` and the constant is named VARIANT_CATEGORY. The removal of the "component" part of the name was to clarify to what the category applies. --- ...ectDependencyResolveIntegrationTest.groovy | 2 +- .../ForcingPlatformAlignmentTest.groovy | 2 +- .../MavenBomResolveIntegrationTest.groovy | 4 +- .../JavaPlatformResolveIntegrationTest.groovy | 20 +- ...ComponentReplacementIntegrationTest.groovy | 6 +- ...riantAttributesRulesIntegrationTest.groovy | 2 +- .../dsl/dependencies/PlatformSupport.java | 10 +- .../RepositoryChainArtifactResolver.java | 2 +- .../parser/GradleModuleMetadataParser.java | 4 +- ...efaultMavenImmutableAttributesFactory.java | 4 +- .../model/DefaultLocalComponentMetadata.java | 2 +- ...faultMavenModuleResolveMetadataTest.groovy | 2 +- ...ncyInsightReportTaskIntegrationTest.groovy | 202 +++++++++--------- ...ReportVariantDetailsIntegrationTest.groovy | 30 +-- ...radle-module-metadata-1.0-specification.md | 2 +- .../kotlin/runtimeClasspath.out | 2 +- .../runtimeClasspath.out | 6 +- .../requiring-features/runtimeClasspath.out | 2 +- .../dependencyReasonReport.out | 2 +- .../dependencyReport.out | 2 +- .../DefaultWorkInProgressFormatterTest.groovy | 6 +- .../console/ProgressOperationTest.groovy | 6 +- .../maven/MavenPublishJavaIntegTest.groovy | 8 +- .../DefaultMavenPublicationTest.groovy | 2 +- .../AbstractMavenPublishIntegTest.groovy | 2 +- .../api/plugins/JavaPlatformPlugin.java | 4 +- .../api/plugins/JavaPlatformPluginTest.groovy | 8 +- 27 files changed, 172 insertions(+), 172 deletions(-) diff --git a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/ProjectDependencyResolveIntegrationTest.groovy b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/ProjectDependencyResolveIntegrationTest.groovy index 8e2380c4e1538..a4fabfa72e559 100644 --- a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/ProjectDependencyResolveIntegrationTest.groovy +++ b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/ProjectDependencyResolveIntegrationTest.groovy @@ -187,7 +187,7 @@ project(":b") { variant('runtime') module('org.other:externalA:1.2') { byReason('also check dependency reasons') - variant('runtime', ['org.gradle.status': 'release', 'org.gradle.component.category':'library', 'org.gradle.usage':'java-runtime']) + variant('runtime', ['org.gradle.status': 'release', 'org.gradle.category':'library', 'org.gradle.usage':'java-runtime']) } } } diff --git a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/alignment/ForcingPlatformAlignmentTest.groovy b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/alignment/ForcingPlatformAlignmentTest.groovy index ecf2435e6ea89..2a475c9a4cef7 100644 --- a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/alignment/ForcingPlatformAlignmentTest.groovy +++ b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/alignment/ForcingPlatformAlignmentTest.groovy @@ -1063,7 +1063,7 @@ include 'other' module(platformName) { version(platformVersion) { variant("platform") { - attribute('org.gradle.component.category', 'platform') + attribute('org.gradle.category', 'platform') members.each { member -> constraint(member) } diff --git a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/maven/MavenBomResolveIntegrationTest.groovy b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/maven/MavenBomResolveIntegrationTest.groovy index e7d809cb6c877..127ed428f64a8 100644 --- a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/maven/MavenBomResolveIntegrationTest.groovy +++ b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/maven/MavenBomResolveIntegrationTest.groovy @@ -169,12 +169,12 @@ class MavenBomResolveIntegrationTest extends AbstractHttpDependencyResolutionTes resolve.expectGraph { root(':', ':testproject:') { module("group:bom:1.0") { - variant("platform-runtime", ['org.gradle.component.category':'platform', 'org.gradle.status':'release', 'org.gradle.usage':'java-runtime']) + variant("platform-runtime", ['org.gradle.category':'platform', 'org.gradle.status':'release', 'org.gradle.usage':'java-runtime']) constraint("group:moduleA:2.0") noArtifacts() } module("group:bom:1.0") { - variant("runtime", ['org.gradle.component.category':'library', 'org.gradle.status':'release', 'org.gradle.usage':'java-runtime']) + variant("runtime", ['org.gradle.category':'library', 'org.gradle.status':'release', 'org.gradle.usage':'java-runtime']) module("group:moduleC:1.0") noArtifacts() } diff --git a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/platforms/JavaPlatformResolveIntegrationTest.groovy b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/platforms/JavaPlatformResolveIntegrationTest.groovy index 0c8af79cedb9b..60880906fa0af 100755 --- a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/platforms/JavaPlatformResolveIntegrationTest.groovy +++ b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/platforms/JavaPlatformResolveIntegrationTest.groovy @@ -70,7 +70,7 @@ class JavaPlatformResolveIntegrationTest extends AbstractHttpDependencyResolutio resolve.expectGraph { root(":", "org.test:test:1.9") { project(":platform", "org.test:platform:1.9") { - variant("apiElements", ['org.gradle.usage': 'java-api', 'org.gradle.component.category': 'platform']) + variant("apiElements", ['org.gradle.usage': 'java-api', 'org.gradle.category': 'platform']) constraint("org:foo:1.1") noArtifacts() } @@ -114,7 +114,7 @@ class JavaPlatformResolveIntegrationTest extends AbstractHttpDependencyResolutio resolve.expectGraph { root(":", "org.test:test:1.9") { project(":platform", "org.test:platform:1.9") { - variant("runtimeElements", ['org.gradle.usage': 'java-runtime', 'org.gradle.component.category': 'platform']) + variant("runtimeElements", ['org.gradle.usage': 'java-runtime', 'org.gradle.category': 'platform']) constraint("org:foo:1.1") constraint("org:bar:1.2") noArtifacts() @@ -159,7 +159,7 @@ class JavaPlatformResolveIntegrationTest extends AbstractHttpDependencyResolutio resolve.expectGraph { root(":", "org.test:test:1.9") { project(":platform", "org.test:platform:1.9") { - variant("apiElements", ['org.gradle.usage': 'java-api', 'org.gradle.component.category': 'platform']) + variant("apiElements", ['org.gradle.usage': 'java-api', 'org.gradle.category': 'platform']) constraint("org:foo:1.1") noArtifacts() } @@ -200,7 +200,7 @@ class JavaPlatformResolveIntegrationTest extends AbstractHttpDependencyResolutio resolve.expectGraph { root(":", "org.test:test:1.9") { project(":platform", "org.test:platform:1.9") { - variant("enforcedApiElements", ['org.gradle.usage': 'java-api', 'org.gradle.component.category': 'enforced-platform']) + variant("enforcedApiElements", ['org.gradle.usage': 'java-api', 'org.gradle.category': 'enforced-platform']) constraint("org:foo:1.1") noArtifacts() } @@ -219,9 +219,9 @@ class JavaPlatformResolveIntegrationTest extends AbstractHttpDependencyResolutio def platform = mavenHttpRepo.module("org", "platform", "1.0") .withModuleMetadata() .adhocVariants() - .variant("apiElements", [(Usage.USAGE_ATTRIBUTE.name): Usage.JAVA_API, (PlatformSupport.COMPONENT_CATEGORY.name): PlatformSupport.REGULAR_PLATFORM]) { useDefaultArtifacts = false } + .variant("apiElements", [(Usage.USAGE_ATTRIBUTE.name): Usage.JAVA_API, (PlatformSupport.VARIANT_CATEGORY.name): PlatformSupport.REGULAR_PLATFORM]) { useDefaultArtifacts = false } .dependsOn("org", "foo", "1.0") - .variant("runtimeElements", [(Usage.USAGE_ATTRIBUTE.name): Usage.JAVA_RUNTIME, (PlatformSupport.COMPONENT_CATEGORY.name): PlatformSupport.REGULAR_PLATFORM]) { + .variant("runtimeElements", [(Usage.USAGE_ATTRIBUTE.name): Usage.JAVA_RUNTIME, (PlatformSupport.VARIANT_CATEGORY.name): PlatformSupport.REGULAR_PLATFORM]) { useDefaultArtifacts = false } .dependsOn("org", "foo", "1.0") @@ -254,7 +254,7 @@ class JavaPlatformResolveIntegrationTest extends AbstractHttpDependencyResolutio configuration = "enforcedApiElements" variant("enforcedApiElements", [ 'org.gradle.usage': 'java-api', - 'org.gradle.component.category': 'enforced-platform', + 'org.gradle.category': 'enforced-platform', 'org.gradle.status': 'release', ]) module("org:foo:1.0") @@ -294,7 +294,7 @@ class JavaPlatformResolveIntegrationTest extends AbstractHttpDependencyResolutio edge("org:platform", "org:platform:1.0") { variant("platform-compile", [ 'org.gradle.usage': 'java-api', - 'org.gradle.component.category': 'platform', + 'org.gradle.category': 'platform', 'org.gradle.status': 'release', ]) byConstraint() @@ -303,7 +303,7 @@ class JavaPlatformResolveIntegrationTest extends AbstractHttpDependencyResolutio constraint("org:platform:1.0", "org:platform:1.0") { variant("platform-compile", [ 'org.gradle.usage': 'java-api', - 'org.gradle.component.category': 'platform', + 'org.gradle.category': 'platform', 'org.gradle.status': 'release', ]) } @@ -335,7 +335,7 @@ class JavaPlatformResolveIntegrationTest extends AbstractHttpDependencyResolutio root(":", "org.test:test:1.9") { module("org:top:1.0") { variant("enforced-platform-compile", [ - 'org.gradle.component.category': 'enforced-platform', + 'org.gradle.category': 'enforced-platform', 'org.gradle.status': 'release', 'org.gradle.usage': 'java-api']) noArtifacts() diff --git a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/rules/ComponentReplacementIntegrationTest.groovy b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/rules/ComponentReplacementIntegrationTest.groovy index 70c93ed78bdb4..a2bc1f484e1ca 100644 --- a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/rules/ComponentReplacementIntegrationTest.groovy +++ b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/rules/ComponentReplacementIntegrationTest.groovy @@ -429,9 +429,9 @@ class ComponentReplacementIntegrationTest extends AbstractIntegrationSpec { then: result.groupedOutput.task(':dependencyInsight').output.contains("""org:b:1 variant "runtime" [ - org.gradle.status = release (not requested) - org.gradle.usage = java-runtime (not requested) - org.gradle.component.category = library (not requested) + org.gradle.status = release (not requested) + org.gradle.usage = java-runtime (not requested) + org.gradle.category = library (not requested) ] Selection reasons: - Selected by rule : $expected diff --git a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/rules/VariantAttributesRulesIntegrationTest.groovy b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/rules/VariantAttributesRulesIntegrationTest.groovy index fc7ec98591901..fcddf2457898a 100644 --- a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/rules/VariantAttributesRulesIntegrationTest.groovy +++ b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/rules/VariantAttributesRulesIntegrationTest.groovy @@ -205,7 +205,7 @@ class VariantAttributesRulesIntegrationTest extends AbstractModuleDependencyReso // the format attribute is added by the rule expectedAttributes = [format: 'custom', 'org.gradle.status': GradleMetadataResolveRunner.useIvy() ? 'integration' : 'release'] expectedAttributes['org.gradle.usage'] = 'java-api' - expectedAttributes['org.gradle.component.category'] = 'library' + expectedAttributes['org.gradle.category'] = 'library' } } variant(expectedTargetVariant, expectedAttributes) diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/dsl/dependencies/PlatformSupport.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/dsl/dependencies/PlatformSupport.java index ffec7c1050f2e..24dc23bf24bf9 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/dsl/dependencies/PlatformSupport.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/dsl/dependencies/PlatformSupport.java @@ -31,18 +31,18 @@ import java.util.Set; public abstract class PlatformSupport { - public static final Attribute COMPONENT_CATEGORY = Attribute.of("org.gradle.component.category", String.class); + public static final Attribute VARIANT_CATEGORY = Attribute.of("org.gradle.category", String.class); public static final String LIBRARY = "library"; public static final String REGULAR_PLATFORM = "platform"; public static final String ENFORCED_PLATFORM = "enforced-platform"; public static boolean isTargettingPlatform(HasConfigurableAttributes target) { - String category = target.getAttributes().getAttribute(COMPONENT_CATEGORY); + String category = target.getAttributes().getAttribute(VARIANT_CATEGORY); return REGULAR_PLATFORM.equals(category) || ENFORCED_PLATFORM.equals(category); } public static void configureSchema(AttributesSchema attributesSchema) { - AttributeMatchingStrategy componentTypeMatchingStrategy = attributesSchema.attribute(PlatformSupport.COMPONENT_CATEGORY); + AttributeMatchingStrategy componentTypeMatchingStrategy = attributesSchema.attribute(PlatformSupport.VARIANT_CATEGORY); componentTypeMatchingStrategy.getDisambiguationRules().add(PlatformSupport.ComponentCategoryDisambiguationRule.class); } @@ -50,13 +50,13 @@ static void addPlatformAttribute(HasConfigurableAttributes dependency, fi dependency.attributes(new Action() { @Override public void execute(AttributeContainer attributeContainer) { - attributeContainer.attribute(COMPONENT_CATEGORY, type); + attributeContainer.attribute(VARIANT_CATEGORY, type); } }); } public static boolean hasForcedDependencies(ComponentVariant variant) { - return Objects.equal(variant.getAttributes().getAttribute(COMPONENT_CATEGORY), ENFORCED_PLATFORM); + return Objects.equal(variant.getAttributes().getAttribute(VARIANT_CATEGORY), ENFORCED_PLATFORM); } public static class ComponentCategoryDisambiguationRule implements AttributeDisambiguationRule, ReusableAction { diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/RepositoryChainArtifactResolver.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/RepositoryChainArtifactResolver.java index 82fedb9d7b0bc..d85105e5c39c5 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/RepositoryChainArtifactResolver.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/RepositoryChainArtifactResolver.java @@ -66,7 +66,7 @@ public ArtifactSet resolveArtifacts(ComponentResolveMetadata component, Configur } if (configuration.getArtifacts().isEmpty()) { // checks if it's a derived platform - AttributeValue componentTypeEntry = configuration.getAttributes().findEntry(PlatformSupport.COMPONENT_CATEGORY); + AttributeValue componentTypeEntry = configuration.getAttributes().findEntry(PlatformSupport.VARIANT_CATEGORY); if (componentTypeEntry.isPresent()) { String value = componentTypeEntry.get(); if (PlatformSupport.REGULAR_PLATFORM.equals(value) || PlatformSupport.ENFORCED_PLATFORM.equals(value)) { diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/parser/GradleModuleMetadataParser.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/parser/GradleModuleMetadataParser.java index 3a16c3f6cf280..e1429ab7f2f34 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/parser/GradleModuleMetadataParser.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/parser/GradleModuleMetadataParser.java @@ -174,10 +174,10 @@ private void consumeVariant(JsonReader reader, MutableModuleComponentResolveMeta reader.endObject(); MutableComponentVariant variant = metadata.addVariant(variantName, attributes); populateVariant(files, dependencies, dependencyConstraints, capabilities, variant); - AttributeValue entry = attributes.findEntry(PlatformSupport.COMPONENT_CATEGORY); + AttributeValue entry = attributes.findEntry(PlatformSupport.VARIANT_CATEGORY); if (entry.isPresent() && PlatformSupport.REGULAR_PLATFORM.equals(entry.get())) { // This generates a synthetic enforced platform variant with the same dependencies, similar to what the Maven variant derivation strategy does - ImmutableAttributes enforcedAttributes = attributesFactory.concat(attributes, attributesFactory.of(PlatformSupport.COMPONENT_CATEGORY, PlatformSupport.ENFORCED_PLATFORM)); + ImmutableAttributes enforcedAttributes = attributesFactory.concat(attributes, attributesFactory.of(PlatformSupport.VARIANT_CATEGORY, PlatformSupport.ENFORCED_PLATFORM)); MutableComponentVariant syntheticEnforcedVariant = metadata.addVariant("enforced" + capitalize(variantName), enforcedAttributes); populateVariant(files, dependencies, dependencyConstraints, capabilities, syntheticEnforcedVariant); } diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/repositories/metadata/DefaultMavenImmutableAttributesFactory.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/repositories/metadata/DefaultMavenImmutableAttributesFactory.java index b40c486bbc879..5d4560b009ef9 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/repositories/metadata/DefaultMavenImmutableAttributesFactory.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/repositories/metadata/DefaultMavenImmutableAttributesFactory.java @@ -80,7 +80,7 @@ public ImmutableAttributes libraryWithUsage(ImmutableAttributes original, String ImmutableAttributes result = concatCache.get(entry); if (result == null) { result = concat(original, USAGE_ATTRIBUTE, new CoercingStringValueSnapshot(usage, objectInstantiator)); - result = concat(result, PlatformSupport.COMPONENT_CATEGORY, PlatformSupport.LIBRARY); + result = concat(result, PlatformSupport.VARIANT_CATEGORY, PlatformSupport.LIBRARY); concatCache.put(entry, result); } return result; @@ -93,7 +93,7 @@ public ImmutableAttributes platformWithUsage(ImmutableAttributes original, Strin ImmutableAttributes result = concatCache.get(entry); if (result == null) { result = concat(original, USAGE_ATTRIBUTE, new CoercingStringValueSnapshot(usage, objectInstantiator)); - result = concat(result, PlatformSupport.COMPONENT_CATEGORY, componentType); + result = concat(result, PlatformSupport.VARIANT_CATEGORY, componentType); concatCache.put(entry, result); } return result; diff --git a/subprojects/dependency-management/src/main/java/org/gradle/internal/component/local/model/DefaultLocalComponentMetadata.java b/subprojects/dependency-management/src/main/java/org/gradle/internal/component/local/model/DefaultLocalComponentMetadata.java index 78d75af9559fe..0d6d79b9d2d9a 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/internal/component/local/model/DefaultLocalComponentMetadata.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/internal/component/local/model/DefaultLocalComponentMetadata.java @@ -407,7 +407,7 @@ public List getDependencies() { } } maybeAddGeneratedDependencies(result); - AttributeValue attributeValue = this.getAttributes().findEntry(PlatformSupport.COMPONENT_CATEGORY); + AttributeValue attributeValue = this.getAttributes().findEntry(PlatformSupport.VARIANT_CATEGORY); if (attributeValue.isPresent() && attributeValue.get().equals(PlatformSupport.ENFORCED_PLATFORM)) { // need to wrap all dependencies to force them ImmutableList rawDependencies = result.build(); diff --git a/subprojects/dependency-management/src/test/groovy/org/gradle/internal/component/external/model/DefaultMavenModuleResolveMetadataTest.groovy b/subprojects/dependency-management/src/test/groovy/org/gradle/internal/component/external/model/DefaultMavenModuleResolveMetadataTest.groovy index d2cd459c9bc30..efb8e28f4d6a2 100644 --- a/subprojects/dependency-management/src/test/groovy/org/gradle/internal/component/external/model/DefaultMavenModuleResolveMetadataTest.groovy +++ b/subprojects/dependency-management/src/test/groovy/org/gradle/internal/component/external/model/DefaultMavenModuleResolveMetadataTest.groovy @@ -147,7 +147,7 @@ class DefaultMavenModuleResolveMetadataTest extends AbstractLazyModuleComponentR def "recognises java library for packaging=#packaging"() { given: def stringUsageAttribute = Attribute.of(Usage.USAGE_ATTRIBUTE.getName(), String.class) - def componentTypeAttribute = PlatformSupport.COMPONENT_CATEGORY + def componentTypeAttribute = PlatformSupport.VARIANT_CATEGORY def metadata = new DefaultMutableMavenModuleResolveMetadata(Mock(ModuleVersionIdentifier), id, [], new DefaultMavenImmutableAttributesFactory(AttributeTestUtil.attributesFactory(), NamedObjectInstantiator.INSTANCE), TestUtil.objectInstantiator()) metadata.packaging = packaging metadata.variantMetadataRules.variantDerivationStrategy = new JavaEcosystemVariantDerivationStrategy() diff --git a/subprojects/diagnostics/src/integTest/groovy/org/gradle/api/tasks/diagnostics/DependencyInsightReportTaskIntegrationTest.groovy b/subprojects/diagnostics/src/integTest/groovy/org/gradle/api/tasks/diagnostics/DependencyInsightReportTaskIntegrationTest.groovy index 055c55cd5cfd6..2340f632dd6a6 100644 --- a/subprojects/diagnostics/src/integTest/groovy/org/gradle/api/tasks/diagnostics/DependencyInsightReportTaskIntegrationTest.groovy +++ b/subprojects/diagnostics/src/integTest/groovy/org/gradle/api/tasks/diagnostics/DependencyInsightReportTaskIntegrationTest.groovy @@ -147,9 +147,9 @@ No dependencies matching given input were found in configuration ':conf' outputContains """ org:leaf2:1.0 variant "runtime" [ - org.gradle.status = release (not requested) - org.gradle.usage = java-runtime (not requested) - org.gradle.component.category = library (not requested) + org.gradle.status = release (not requested) + org.gradle.usage = java-runtime (not requested) + org.gradle.category = library (not requested) ] org:leaf2:1.0 @@ -201,9 +201,9 @@ org:leaf2:1.0 Task :dependencyInsight org:leaf2:2.5 variant "runtime" [ - org.gradle.status = release (not requested) - org.gradle.usage = java-runtime (not requested) - org.gradle.component.category = library (not requested) + org.gradle.status = release (not requested) + org.gradle.usage = java-runtime (not requested) + org.gradle.category = library (not requested) ] Selection reasons: - By conflict resolution : between versions 1.5, 2.5 and 1.0 @@ -257,9 +257,9 @@ org:leaf2:1.5 -> 2.5 outputContains """ org:leaf:1.0 variant "runtime" [ - org.gradle.status = release (not requested) - org.gradle.usage = java-runtime (not requested) - org.gradle.component.category = library (not requested) + org.gradle.status = release (not requested) + org.gradle.usage = java-runtime (not requested) + org.gradle.category = library (not requested) ] org:leaf:1.0 @@ -279,9 +279,9 @@ org:leaf:1.0 outputContains """ org:leaf:1.0 variant "runtime" [ - org.gradle.status = release (not requested) - org.gradle.usage = java-runtime (not requested) - org.gradle.component.category = library (not requested) + org.gradle.status = release (not requested) + org.gradle.usage = java-runtime (not requested) + org.gradle.category = library (not requested) ] org:leaf:1.0 @@ -335,9 +335,9 @@ org:leaf:1.0 org:leaf2:2.5 variant "runtime" [ - org.gradle.status = release (not requested) - org.gradle.usage = java-runtime (not requested) - org.gradle.component.category = library (not requested) + org.gradle.status = release (not requested) + org.gradle.usage = java-runtime (not requested) + org.gradle.category = library (not requested) ] Selection reasons: - By conflict resolution : between versions 1.5, 2.5 and 1.0 @@ -408,9 +408,9 @@ org:leaf2:1.5 -> 2.5 org:leaf2:2.5 variant "runtime" [ - org.gradle.status = release (not requested) - org.gradle.usage = java-runtime (not requested) - org.gradle.component.category = library (not requested) + org.gradle.status = release (not requested) + org.gradle.usage = java-runtime (not requested) + org.gradle.category = library (not requested) ] Selection reasons: - By conflict resolution : between versions 1.5, 2.5 and 1.0 @@ -580,9 +580,9 @@ org:foo:1.+ FAILED outputContains """ org:leaf:1.0 (forced) variant "runtime" [ - org.gradle.status = release (not requested) - org.gradle.usage = java-runtime (not requested) - org.gradle.component.category = library (not requested) + org.gradle.status = release (not requested) + org.gradle.usage = java-runtime (not requested) + org.gradle.category = library (not requested) ] org:leaf:1.0 @@ -601,9 +601,9 @@ org:leaf:2.0 -> 1.0 outputContains """ org:leaf:1.0 (selected by rule) variant "runtime" [ - org.gradle.status = release (not requested) - org.gradle.usage = java-runtime (not requested) - org.gradle.component.category = library (not requested) + org.gradle.status = release (not requested) + org.gradle.usage = java-runtime (not requested) + org.gradle.category = library (not requested) ] org:leaf:1.0 @@ -644,9 +644,9 @@ org:leaf:2.0 -> 1.0 outputContains """ org:leaf:2 variant "runtime" [ - org.gradle.status = release (not requested) - org.gradle.usage = java-runtime (not requested) - org.gradle.component.category = library (not requested) + org.gradle.status = release (not requested) + org.gradle.usage = java-runtime (not requested) + org.gradle.category = library (not requested) ] Selection reasons: - Was requested : didn't match version 3 because testing stuff @@ -756,9 +756,9 @@ org:leaf:latest.integration -> 1.0 outputContains """ org:bar:2.0 variant "runtime" [ - org.gradle.status = release (not requested) - org.gradle.usage = java-runtime (not requested) - org.gradle.component.category = library (not requested) + org.gradle.status = release (not requested) + org.gradle.usage = java-runtime (not requested) + org.gradle.category = library (not requested) ] Selection reasons: - Forced @@ -819,9 +819,9 @@ org:foo:1.0 -> org:bar:2.0 outputContains """ org.test:bar:2.0 variant "runtime" [ - org.gradle.status = release (not requested) - org.gradle.usage = java-runtime (not requested) - org.gradle.component.category = library (not requested) + org.gradle.status = release (not requested) + org.gradle.usage = java-runtime (not requested) + org.gradle.category = library (not requested) ] Selection reasons: - Selected by rule : why not? @@ -831,9 +831,9 @@ org:bar:1.0 -> org.test:bar:2.0 org:baz:1.0 (selected by rule) variant "runtime" [ - org.gradle.status = release (not requested) - org.gradle.usage = java-runtime (not requested) - org.gradle.component.category = library (not requested) + org.gradle.status = release (not requested) + org.gradle.usage = java-runtime (not requested) + org.gradle.category = library (not requested) ] org:baz:1.0 @@ -841,9 +841,9 @@ org:baz:1.0 org:foo:2.0 variant "runtime" [ - org.gradle.status = release (not requested) - org.gradle.usage = java-runtime (not requested) - org.gradle.component.category = library (not requested) + org.gradle.status = release (not requested) + org.gradle.usage = java-runtime (not requested) + org.gradle.category = library (not requested) ] Selection reasons: - Selected by rule : because I am in control @@ -889,9 +889,9 @@ org:foo:1.0 -> 2.0 outputContains """ org:baz:2.0 (selected by rule) variant "runtime" [ - org.gradle.status = release (not requested) - org.gradle.usage = java-runtime (not requested) - org.gradle.component.category = library (not requested) + org.gradle.status = release (not requested) + org.gradle.usage = java-runtime (not requested) + org.gradle.category = library (not requested) ] org:baz:1.1 -> 2.0 @@ -899,9 +899,9 @@ org:baz:1.1 -> 2.0 org:bar:1.0 variant "runtime" [ - org.gradle.status = release (not requested) - org.gradle.usage = java-runtime (not requested) - org.gradle.component.category = library (not requested) + org.gradle.status = release (not requested) + org.gradle.usage = java-runtime (not requested) + org.gradle.category = library (not requested) ] Selection reasons: - Selected by rule : foo superseded by bar @@ -946,9 +946,9 @@ org:foo:1.0 -> org:bar:1.0 outputContains """ org:new-leaf:77 (selected by rule) variant "runtime" [ - org.gradle.status = release (not requested) - org.gradle.usage = java-runtime (not requested) - org.gradle.component.category = library (not requested) + org.gradle.status = release (not requested) + org.gradle.usage = java-runtime (not requested) + org.gradle.category = library (not requested) ] org:leaf:1.0 -> org:new-leaf:77 @@ -995,9 +995,9 @@ org:leaf:2.0 -> org:new-leaf:77 then: outputContains """org:bar:2.0 variant "runtime" [ - org.gradle.status = release (not requested) - org.gradle.usage = java-runtime (not requested) - org.gradle.component.category = library (not requested) + org.gradle.status = release (not requested) + org.gradle.usage = java-runtime (not requested) + org.gradle.category = library (not requested) ] Selection reasons: - Selected by rule : I am not sure I want to explain @@ -1007,9 +1007,9 @@ org:bar:1.0 -> 2.0 org:foo:2.0 variant "runtime" [ - org.gradle.status = release (not requested) - org.gradle.usage = java-runtime (not requested) - org.gradle.component.category = library (not requested) + org.gradle.status = release (not requested) + org.gradle.usage = java-runtime (not requested) + org.gradle.category = library (not requested) ] Selection reasons: - Selected by rule : I want to @@ -1100,9 +1100,9 @@ org:leaf:latest.integration -> 1.6 outputContains """ org:leaf:2.0 (forced) variant "runtime" [ - org.gradle.status = release (not requested) - org.gradle.usage = java-runtime (not requested) - org.gradle.component.category = library (not requested) + org.gradle.status = release (not requested) + org.gradle.usage = java-runtime (not requested) + org.gradle.category = library (not requested) ] org:leaf:2.0 @@ -1148,9 +1148,9 @@ org:leaf:1.0 -> 2.0 outputContains """ org:leaf:1.5 (forced) variant "runtime" [ - org.gradle.status = release (not requested) - org.gradle.usage = java-runtime (not requested) - org.gradle.component.category = library (not requested) + org.gradle.status = release (not requested) + org.gradle.usage = java-runtime (not requested) + org.gradle.category = library (not requested) ] org:leaf:1.0 -> 1.5 @@ -1197,9 +1197,9 @@ org:leaf:2.0 -> 1.5 outputContains """ org:leaf:1.0 (forced) variant "runtime" [ - org.gradle.status = release (not requested) - org.gradle.usage = java-runtime (not requested) - org.gradle.component.category = library (not requested) + org.gradle.status = release (not requested) + org.gradle.usage = java-runtime (not requested) + org.gradle.category = library (not requested) ] org:leaf:1.0 @@ -1245,9 +1245,9 @@ org:leaf:2.0 -> 1.0 outputContains """ org:leaf:2.0 variant "runtime" [ - org.gradle.status = release (not requested) - org.gradle.usage = java-runtime (not requested) - org.gradle.component.category = library (not requested) + org.gradle.status = release (not requested) + org.gradle.usage = java-runtime (not requested) + org.gradle.category = library (not requested) ] Selection reasons: - Forced @@ -1658,9 +1658,9 @@ project :C FAILED outputContains """ org:leaf2:1.0 variant "runtime" [ - org.gradle.status = release (not requested) - org.gradle.usage = java-runtime (not requested) - org.gradle.component.category = library (not requested) + org.gradle.status = release (not requested) + org.gradle.usage = java-runtime (not requested) + org.gradle.category = library (not requested) ] org:leaf2:1.0 @@ -1752,9 +1752,9 @@ project : outputContains """ org:leaf2:1.0 variant "runtime" [ - org.gradle.status = release (not requested) - org.gradle.usage = java-runtime (not requested) - org.gradle.component.category = library (not requested) + org.gradle.status = release (not requested) + org.gradle.usage = java-runtime (not requested) + org.gradle.category = library (not requested) ] org:leaf2:1.0 @@ -1855,7 +1855,7 @@ org:leaf4:1.0 variant "compile" [ org.gradle.status = release (not requested) org.gradle.usage = java-api - org.gradle.component.category = library (not requested) + org.gradle.category = library (not requested) Requested attributes not found in the selected variant: org.gradle.dependency.bundling = external @@ -1893,7 +1893,7 @@ org:leaf1:1.0 variant "compile" [ org.gradle.status = release (not requested) org.gradle.usage = java-api - org.gradle.component.category = library (not requested) + org.gradle.category = library (not requested) Requested attributes not found in the selected variant: org.gradle.dependency.bundling = external @@ -1913,7 +1913,7 @@ org:leaf2:1.0 variant "compile" [ org.gradle.status = release (not requested) org.gradle.usage = java-api - org.gradle.component.category = library (not requested) + org.gradle.category = library (not requested) Requested attributes not found in the selected variant: org.gradle.dependency.bundling = external @@ -2057,7 +2057,7 @@ org:leaf3:1.0 variant "compile" [ org.gradle.status = release (not requested) org.gradle.usage = java-api - org.gradle.component.category = library (not requested) + org.gradle.category = library (not requested) Requested attributes not found in the selected variant: org.gradle.dependency.bundling = external @@ -2105,9 +2105,9 @@ org:leaf3:1.0 then: result.groupedOutput.task(":dependencyInsight").output.contains("""foo:bar:2.0 variant "runtime" [ - org.gradle.status = release (not requested) - org.gradle.usage = java-runtime (not requested) - org.gradle.component.category = library (not requested) + org.gradle.status = release (not requested) + org.gradle.usage = java-runtime (not requested) + org.gradle.category = library (not requested) ] foo:bar:2.0 @@ -2115,9 +2115,9 @@ foo:bar:2.0 foo:foo:1.0 variant "runtime" [ - org.gradle.status = release (not requested) - org.gradle.usage = java-runtime (not requested) - org.gradle.component.category = library (not requested) + org.gradle.status = release (not requested) + org.gradle.usage = java-runtime (not requested) + org.gradle.category = library (not requested) ] foo:foo:1.0 @@ -2161,7 +2161,7 @@ foo:foo:1.0 variant "compile" [ org.gradle.status = release (not requested) org.gradle.usage = java-api - org.gradle.component.category = library (not requested) + org.gradle.category = library (not requested) Requested attributes not found in the selected variant: org.gradle.dependency.bundling = external @@ -2217,7 +2217,7 @@ org:foo -> $selected variant "compile" [ org.gradle.status = release (not requested) org.gradle.usage = java-api - org.gradle.component.category = library (not requested) + org.gradle.category = library (not requested) Requested attributes not found in the selected variant: org.gradle.dependency.bundling = external @@ -2270,7 +2270,7 @@ org:foo -> $selected variant "compile" [ org.gradle.status = release (not requested) org.gradle.usage = java-api - org.gradle.component.category = library (not requested) + org.gradle.category = library (not requested) Requested attributes not found in the selected variant: org.gradle.dependency.bundling = external @@ -2320,7 +2320,7 @@ org:foo:${displayVersion} -> $selected variant "compile" [ org.gradle.status = release (not requested) org.gradle.usage = java-api - org.gradle.component.category = library (not requested) + org.gradle.category = library (not requested) Requested attributes not found in the selected variant: org.gradle.dependency.bundling = external @@ -2376,7 +2376,7 @@ org:foo:[1.1,1.3] -> 1.3 variant "compile" [ org.gradle.status = release (not requested) org.gradle.usage = java-api - org.gradle.component.category = library (not requested) + org.gradle.category = library (not requested) Requested attributes not found in the selected variant: org.gradle.dependency.bundling = external @@ -2392,7 +2392,7 @@ org:foo:1.1 variant "compile" [ org.gradle.status = release (not requested) org.gradle.usage = java-api - org.gradle.component.category = library (not requested) + org.gradle.category = library (not requested) Requested attributes not found in the selected variant: org.gradle.dependency.bundling = external @@ -2452,7 +2452,7 @@ org:bar:1.0 variant "compile" [ org.gradle.status = release (not requested) org.gradle.usage = java-api - org.gradle.component.category = library (not requested) + org.gradle.category = library (not requested) Requested attributes not found in the selected variant: org.gradle.dependency.bundling = external @@ -2469,7 +2469,7 @@ org:foo:1.1 variant "compile" [ org.gradle.status = release (not requested) org.gradle.usage = java-api - org.gradle.component.category = library (not requested) + org.gradle.category = library (not requested) Requested attributes not found in the selected variant: org.gradle.dependency.bundling = external @@ -2514,7 +2514,7 @@ org:leaf:1.0 (by constraint) variant "compile" [ org.gradle.status = release (not requested) org.gradle.usage = java-api - org.gradle.component.category = library (not requested) + org.gradle.category = library (not requested) Requested attributes not found in the selected variant: org.gradle.dependency.bundling = external @@ -2567,7 +2567,7 @@ org.test:leaf:1.0 variant "compile" [ org.gradle.status = release (not requested) org.gradle.usage = java-api - org.gradle.component.category = library (not requested) + org.gradle.category = library (not requested) Requested attributes not found in the selected variant: org.gradle.dependency.bundling = external @@ -2614,9 +2614,9 @@ org.test:leaf:1.0 outputContains """ org:leaf2:1.0 variant "runtime" [ - org.gradle.status = release (not requested) - org.gradle.usage = java-runtime (not requested) - org.gradle.component.category = library (not requested) + org.gradle.status = release (not requested) + org.gradle.usage = java-runtime (not requested) + org.gradle.category = library (not requested) ] org:leaf2:1.0 @@ -2749,7 +2749,7 @@ org:foo:1.0 variant "compile" [ org.gradle.status = release (not requested) org.gradle.usage = java-api - org.gradle.component.category = library (not requested) + org.gradle.category = library (not requested) Requested attributes not found in the selected variant: org.gradle.dependency.bundling = external @@ -2806,7 +2806,7 @@ org:foo:{require [1.0,); reject 1.1} -> 1.0 variant "compile" [ org.gradle.status = release (not requested) org.gradle.usage = java-api - org.gradle.component.category = library (not requested) + org.gradle.category = library (not requested) Requested attributes not found in the selected variant: org.gradle.dependency.bundling = external @@ -2872,7 +2872,7 @@ org:foo:1.0 color = blue org.gradle.status = release (not requested) org.gradle.usage = java-api - org.gradle.component.category = library (not requested) + org.gradle.category = library (not requested) Requested attributes not found in the selected variant: org.gradle.dependency.bundling = external @@ -2947,7 +2947,7 @@ planet:mercury:1.0.2 variant "compile" [ org.gradle.status = release (not requested) org.gradle.usage = java-api - org.gradle.component.category = library (not requested) + org.gradle.category = library (not requested) Requested attributes not found in the selected variant: org.gradle.dependency.bundling = external @@ -2978,7 +2978,7 @@ planet:venus:2.0.1 variant "compile" [ org.gradle.status = release (not requested) org.gradle.usage = java-api - org.gradle.component.category = library (not requested) + org.gradle.category = library (not requested) Requested attributes not found in the selected variant: org.gradle.dependency.bundling = external @@ -3009,7 +3009,7 @@ planet:pluto:1.0.0 variant "compile" [ org.gradle.status = release (not requested) org.gradle.usage = java-api - org.gradle.component.category = library (not requested) + org.gradle.category = library (not requested) Requested attributes not found in the selected variant: org.gradle.dependency.bundling = external diff --git a/subprojects/diagnostics/src/integTest/groovy/org/gradle/api/tasks/diagnostics/DependencyInsightReportVariantDetailsIntegrationTest.groovy b/subprojects/diagnostics/src/integTest/groovy/org/gradle/api/tasks/diagnostics/DependencyInsightReportVariantDetailsIntegrationTest.groovy index e3faacd973470..39860d524f5a7 100644 --- a/subprojects/diagnostics/src/integTest/groovy/org/gradle/api/tasks/diagnostics/DependencyInsightReportVariantDetailsIntegrationTest.groovy +++ b/subprojects/diagnostics/src/integTest/groovy/org/gradle/api/tasks/diagnostics/DependencyInsightReportVariantDetailsIntegrationTest.groovy @@ -178,9 +178,9 @@ org:middle:1.0 FAILED output.contains """ org:leaf:1.0 variant "runtime" [ - org.gradle.status = release (not requested) - org.gradle.usage = java-runtime (not requested) - org.gradle.component.category = library (not requested) + org.gradle.status = release (not requested) + org.gradle.usage = java-runtime (not requested) + org.gradle.category = library (not requested) ] org:leaf:1.0 @@ -218,11 +218,11 @@ org:leaf:1.0 then: output.contains """org:leaf:1.0 variant "runtime" [ - org.gradle.status = release (not requested) - org.gradle.usage = java-runtime (not requested) - org.gradle.component.category = library (not requested) + org.gradle.status = release (not requested) + org.gradle.usage = java-runtime (not requested) + org.gradle.category = library (not requested) Requested attributes not found in the selected variant: - usage = dummy + usage = dummy ] org:leaf:1.0 @@ -280,10 +280,10 @@ org:leaf:1.0 outputContains """ org:testA:1.0 variant "runtime" [ - custom = dep_value - org.gradle.status = release (not requested) - org.gradle.usage = java-runtime (not requested) - org.gradle.component.category = library (not requested) + custom = dep_value + org.gradle.status = release (not requested) + org.gradle.usage = java-runtime (not requested) + org.gradle.category = library (not requested) ] org:testA:1.0 @@ -291,10 +291,10 @@ org:testA:1.0 org:testB:1.0 variant "runtime" [ - custom = dep_value - org.gradle.status = release (not requested) - org.gradle.usage = java-runtime (not requested) - org.gradle.component.category = library (not requested) + custom = dep_value + org.gradle.status = release (not requested) + org.gradle.usage = java-runtime (not requested) + org.gradle.category = library (not requested) ] org:testB:+ -> 1.0 diff --git a/subprojects/docs/src/docs/design/gradle-module-metadata-1.0-specification.md b/subprojects/docs/src/docs/design/gradle-module-metadata-1.0-specification.md index a881f2c2f941a..2908c522c1e35 100644 --- a/subprojects/docs/src/docs/design/gradle-module-metadata-1.0-specification.md +++ b/subprojects/docs/src/docs/design/gradle-module-metadata-1.0-specification.md @@ -86,7 +86,7 @@ This value must contain an array of 0 or more capabilities. Each capability is a - `org.gradle.usage` indicates the purpose of the variant. See the `org.gradle.api.attributes.Usage` class for more details. Value must be a string. - `org.gradle.status` indicates the kind of release: one of `release` or `integration`. -- `org.gradle.component.category` indicates the type of component (library or platform). This attribute is mostly used to disambiguate Maven POM files derived either as a platform or a library. Value must be a string. +- `org.gradle.category` indicates the type of component (library or platform). This attribute is mostly used to disambiguate Maven POM files derived either as a platform or a library. Value must be a string. - `org.gradle.dependency.bundling` indicates how dependencies of the variant are bundled. Either externally, embedded or shadowed. See the `org.gradle.api.attributes.Bundling` for more details. Value must be a string. #### Java Ecosystem specific attributes diff --git a/subprojects/docs/src/samples/java-feature-variant/incompatible-variants/kotlin/runtimeClasspath.out b/subprojects/docs/src/samples/java-feature-variant/incompatible-variants/kotlin/runtimeClasspath.out index 6f6b0059438e4..5bb8a22385fec 100644 --- a/subprojects/docs/src/samples/java-feature-variant/incompatible-variants/kotlin/runtimeClasspath.out +++ b/subprojects/docs/src/samples/java-feature-variant/incompatible-variants/kotlin/runtimeClasspath.out @@ -4,7 +4,7 @@ mysql:mysql-connector-java:8.0.14 variant "runtime" [ org.gradle.status = release (not requested) org.gradle.usage = java-runtime - org.gradle.component.category = library (not requested) + org.gradle.category = library (not requested) ] mysql:mysql-connector-java:8.0.14 diff --git a/subprojects/docs/src/samples/java-feature-variant/requiring-features-external/runtimeClasspath.out b/subprojects/docs/src/samples/java-feature-variant/requiring-features-external/runtimeClasspath.out index 85643c2c6a108..c80e0159ba2c7 100644 --- a/subprojects/docs/src/samples/java-feature-variant/requiring-features-external/runtimeClasspath.out +++ b/subprojects/docs/src/samples/java-feature-variant/requiring-features-external/runtimeClasspath.out @@ -4,7 +4,7 @@ org.mongodb:bson:3.9.1 variant "runtime" [ org.gradle.status = release (not requested) org.gradle.usage = java-runtime - org.gradle.component.category = library (not requested) + org.gradle.category = library (not requested) Requested attributes not found in the selected variant: org.gradle.dependency.bundling = external @@ -22,7 +22,7 @@ org.mongodb:mongodb-driver-core:3.9.1 variant "runtime" [ org.gradle.status = release (not requested) org.gradle.usage = java-runtime - org.gradle.component.category = library (not requested) + org.gradle.category = library (not requested) Requested attributes not found in the selected variant: org.gradle.dependency.bundling = external @@ -38,7 +38,7 @@ org.mongodb:mongodb-driver-sync:3.9.1 variant "runtime" [ org.gradle.status = release (not requested) org.gradle.usage = java-runtime - org.gradle.component.category = library (not requested) + org.gradle.category = library (not requested) Requested attributes not found in the selected variant: org.gradle.dependency.bundling = external diff --git a/subprojects/docs/src/samples/java-feature-variant/requiring-features/runtimeClasspath.out b/subprojects/docs/src/samples/java-feature-variant/requiring-features/runtimeClasspath.out index d84a70464a743..bf6ef85c99963 100644 --- a/subprojects/docs/src/samples/java-feature-variant/requiring-features/runtimeClasspath.out +++ b/subprojects/docs/src/samples/java-feature-variant/requiring-features/runtimeClasspath.out @@ -4,7 +4,7 @@ mysql:mysql-connector-java:8.0.14 variant "runtime" [ org.gradle.status = release (not requested) org.gradle.usage = java-runtime - org.gradle.component.category = library (not requested) + org.gradle.category = library (not requested) Requested attributes not found in the selected variant: org.gradle.dependency.bundling = external diff --git a/subprojects/docs/src/samples/userguide/dependencyManagement/inspectingDependencies/dependencyReason/dependencyReasonReport.out b/subprojects/docs/src/samples/userguide/dependencyManagement/inspectingDependencies/dependencyReason/dependencyReasonReport.out index 0c925d0842563..c1e90fc3e4c30 100644 --- a/subprojects/docs/src/samples/userguide/dependencyManagement/inspectingDependencies/dependencyReason/dependencyReasonReport.out +++ b/subprojects/docs/src/samples/userguide/dependencyManagement/inspectingDependencies/dependencyReason/dependencyReasonReport.out @@ -2,7 +2,7 @@ org.ow2.asm:asm:6.0 variant "compile" [ org.gradle.status = release (not requested) org.gradle.usage = java-api - org.gradle.component.category = library (not requested) + org.gradle.category = library (not requested) Requested attributes not found in the selected variant: org.gradle.dependency.bundling = external diff --git a/subprojects/docs/src/samples/userguide/dependencyManagement/managingTransitiveDependencies/declaringCapabilities/dependencyReport.out b/subprojects/docs/src/samples/userguide/dependencyManagement/managingTransitiveDependencies/declaringCapabilities/dependencyReport.out index 8ac46d8918c93..baf981f1f7278 100644 --- a/subprojects/docs/src/samples/userguide/dependencyManagement/managingTransitiveDependencies/declaringCapabilities/dependencyReport.out +++ b/subprojects/docs/src/samples/userguide/dependencyManagement/managingTransitiveDependencies/declaringCapabilities/dependencyReport.out @@ -21,7 +21,7 @@ org.slf4j:slf4j-log4j12:1.6.1 variant "compile" [ org.gradle.status = release (not requested) org.gradle.usage = java-api - org.gradle.component.category = library (not requested) + org.gradle.category = library (not requested) Requested attributes not found in the selected variant: org.gradle.dependency.bundling = external diff --git a/subprojects/logging/src/test/groovy/org/gradle/internal/logging/console/DefaultWorkInProgressFormatterTest.groovy b/subprojects/logging/src/test/groovy/org/gradle/internal/logging/console/DefaultWorkInProgressFormatterTest.groovy index a1bb77e261131..8b6351105030a 100644 --- a/subprojects/logging/src/test/groovy/org/gradle/internal/logging/console/DefaultWorkInProgressFormatterTest.groovy +++ b/subprojects/logging/src/test/groovy/org/gradle/internal/logging/console/DefaultWorkInProgressFormatterTest.groovy @@ -28,9 +28,9 @@ class DefaultWorkInProgressFormatterTest extends Specification { def "formats operations"() { given: - def op1 = new ProgressOperation("STATUS_1", "CATEGORY", new OperationIdentifier(1), null) + def op1 = new ProgressOperation("STATUS_1", "VARIANT_CATEGORY", new OperationIdentifier(1), null) def op2 = new ProgressOperation(null, null, new OperationIdentifier(2), op1) - def op3 = new ProgressOperation("STATUS_2", "CATEGORY", new OperationIdentifier(3), op2) + def op3 = new ProgressOperation("STATUS_2", "VARIANT_CATEGORY", new OperationIdentifier(3), op2) expect: statusBarFormatter.format(op3).first().text == "> STATUS_1 > STATUS_2" @@ -40,7 +40,7 @@ class DefaultWorkInProgressFormatterTest extends Specification { def "trims output to one less than the max console width"() { given: - def operation = new ProgressOperation("these are more than 10 characters", "CATEGORY", new OperationIdentifier(1), null) + def operation = new ProgressOperation("these are more than 10 characters", "VARIANT_CATEGORY", new OperationIdentifier(1), null) when: _ * consoleMetaData.getCols() >> 10 diff --git a/subprojects/logging/src/test/groovy/org/gradle/internal/logging/console/ProgressOperationTest.groovy b/subprojects/logging/src/test/groovy/org/gradle/internal/logging/console/ProgressOperationTest.groovy index 9fef606f936bf..2b17f3dbfce35 100644 --- a/subprojects/logging/src/test/groovy/org/gradle/internal/logging/console/ProgressOperationTest.groovy +++ b/subprojects/logging/src/test/groovy/org/gradle/internal/logging/console/ProgressOperationTest.groovy @@ -22,7 +22,7 @@ class ProgressOperationTest extends Specification { def "message prefers status"() { given: - ProgressOperation progressOperation = new ProgressOperation("STATUS", "CATEGORY", new OperationIdentifier(1), null) + ProgressOperation progressOperation = new ProgressOperation("STATUS", "VARIANT_CATEGORY", new OperationIdentifier(1), null) expect: progressOperation.getMessage() == "STATUS" @@ -30,7 +30,7 @@ class ProgressOperationTest extends Specification { def "message is null if all inputs are null"() { given: - ProgressOperation progressOperation = new ProgressOperation(null, "CATEGORY", new OperationIdentifier(1), null) + ProgressOperation progressOperation = new ProgressOperation(null, "VARIANT_CATEGORY", new OperationIdentifier(1), null) expect: progressOperation.getMessage() == null @@ -38,7 +38,7 @@ class ProgressOperationTest extends Specification { def "allows children to be managed"() { given: - ProgressOperation progressOperation = new ProgressOperation("STATUS", "CATEGORY", new OperationIdentifier(1), null) + ProgressOperation progressOperation = new ProgressOperation("STATUS", "VARIANT_CATEGORY", new OperationIdentifier(1), null) def mockOperation = Mock(ProgressOperation) when: diff --git a/subprojects/maven/src/integTest/groovy/org/gradle/api/publish/maven/MavenPublishJavaIntegTest.groovy b/subprojects/maven/src/integTest/groovy/org/gradle/api/publish/maven/MavenPublishJavaIntegTest.groovy index a97c5a216c7cb..fdf1c65f82c50 100644 --- a/subprojects/maven/src/integTest/groovy/org/gradle/api/publish/maven/MavenPublishJavaIntegTest.groovy +++ b/subprojects/maven/src/integTest/groovy/org/gradle/api/publish/maven/MavenPublishJavaIntegTest.groovy @@ -970,7 +970,7 @@ $append javaLibrary.parsedModuleMetadata.variant("apiElements") { dependency('org.test:bar:').exists() dependency('org.test:bom:1.0') { - hasAttribute(PlatformSupport.COMPONENT_CATEGORY.name, PlatformSupport.REGULAR_PLATFORM) + hasAttribute(PlatformSupport.VARIANT_CATEGORY.name, PlatformSupport.REGULAR_PLATFORM) } noMoreDependencies() } @@ -979,7 +979,7 @@ $append javaLibrary.parsedModuleMetadata.variant("runtimeElements") { dependency('org.test:bar:').exists() dependency('org.test:bom:1.0') { - hasAttribute(PlatformSupport.COMPONENT_CATEGORY.name, PlatformSupport.REGULAR_PLATFORM) + hasAttribute(PlatformSupport.VARIANT_CATEGORY.name, PlatformSupport.REGULAR_PLATFORM) } noMoreDependencies() } @@ -1144,7 +1144,7 @@ include(':platform') javaLibrary.parsedModuleMetadata.variant("apiElements") { dependency('org.test:bar:').exists() dependency('org.gradle.test:platform:1.9') { - hasAttribute(PlatformSupport.COMPONENT_CATEGORY.name, PlatformSupport.REGULAR_PLATFORM) + hasAttribute(PlatformSupport.VARIANT_CATEGORY.name, PlatformSupport.REGULAR_PLATFORM) } noMoreDependencies() } @@ -1153,7 +1153,7 @@ include(':platform') javaLibrary.parsedModuleMetadata.variant("runtimeElements") { dependency('org.test:bar:').exists() dependency('org.gradle.test:platform:1.9') { - hasAttribute(PlatformSupport.COMPONENT_CATEGORY.name, PlatformSupport.REGULAR_PLATFORM) + hasAttribute(PlatformSupport.VARIANT_CATEGORY.name, PlatformSupport.REGULAR_PLATFORM) } noMoreDependencies() } diff --git a/subprojects/maven/src/test/groovy/org/gradle/api/publish/maven/internal/publication/DefaultMavenPublicationTest.groovy b/subprojects/maven/src/test/groovy/org/gradle/api/publish/maven/internal/publication/DefaultMavenPublicationTest.groovy index 0deab6d9f445f..066c4252b0e65 100644 --- a/subprojects/maven/src/test/groovy/org/gradle/api/publish/maven/internal/publication/DefaultMavenPublicationTest.groovy +++ b/subprojects/maven/src/test/groovy/org/gradle/api/publish/maven/internal/publication/DefaultMavenPublicationTest.groovy @@ -532,6 +532,6 @@ class DefaultMavenPublicationTest extends Specification { } def platformAttribute() { - return AttributeTestUtil.attributes([(PlatformSupport.COMPONENT_CATEGORY.name) : PlatformSupport.REGULAR_PLATFORM]) + return AttributeTestUtil.attributes([(PlatformSupport.VARIANT_CATEGORY.name) : PlatformSupport.REGULAR_PLATFORM]) } } diff --git a/subprojects/maven/src/testFixtures/groovy/org/gradle/integtests/fixtures/publish/maven/AbstractMavenPublishIntegTest.groovy b/subprojects/maven/src/testFixtures/groovy/org/gradle/integtests/fixtures/publish/maven/AbstractMavenPublishIntegTest.groovy index 8e43e945082ab..6c1342bd253ad 100644 --- a/subprojects/maven/src/testFixtures/groovy/org/gradle/integtests/fixtures/publish/maven/AbstractMavenPublishIntegTest.groovy +++ b/subprojects/maven/src/testFixtures/groovy/org/gradle/integtests/fixtures/publish/maven/AbstractMavenPublishIntegTest.groovy @@ -132,7 +132,7 @@ abstract class AbstractMavenPublishIntegTest extends AbstractIntegrationSpec imp dependencies { attributesSchema { - getMatchingStrategy(PlatformSupport.COMPONENT_CATEGORY) + getMatchingStrategy(PlatformSupport.VARIANT_CATEGORY) .disambiguationRules .add(PlatformSupport.PreferRegularPlatform) } diff --git a/subprojects/plugins/src/main/java/org/gradle/api/plugins/JavaPlatformPlugin.java b/subprojects/plugins/src/main/java/org/gradle/api/plugins/JavaPlatformPlugin.java index cec72c4688c5c..bc0e75ed3f8c8 100644 --- a/subprojects/plugins/src/main/java/org/gradle/api/plugins/JavaPlatformPlugin.java +++ b/subprojects/plugins/src/main/java/org/gradle/api/plugins/JavaPlatformPlugin.java @@ -110,7 +110,7 @@ public void apply(Project project) { private void addPlatformDisambiguationRule(Project project) { project.getDependencies() .getAttributesSchema() - .getMatchingStrategy(PlatformSupport.COMPONENT_CATEGORY) + .getMatchingStrategy(PlatformSupport.VARIANT_CATEGORY) .getDisambiguationRules() .add(PlatformSupport.PreferRegularPlatform.class); } @@ -158,7 +158,7 @@ private Configuration createConsumableApi(Project project, ConfigurationContaine } private void declareConfigurationCategory(Configuration configuration, String value) { - configuration.getAttributes().attribute(PlatformSupport.COMPONENT_CATEGORY, value); + configuration.getAttributes().attribute(PlatformSupport.VARIANT_CATEGORY, value); } private void declareConfigurationUsage(Project project, Configuration configuration, String usage) { diff --git a/subprojects/plugins/src/test/groovy/org/gradle/api/plugins/JavaPlatformPluginTest.groovy b/subprojects/plugins/src/test/groovy/org/gradle/api/plugins/JavaPlatformPluginTest.groovy index 6782599c045bc..18cec3d52e769 100644 --- a/subprojects/plugins/src/test/groovy/org/gradle/api/plugins/JavaPlatformPluginTest.groovy +++ b/subprojects/plugins/src/test/groovy/org/gradle/api/plugins/JavaPlatformPluginTest.groovy @@ -120,17 +120,17 @@ class JavaPlatformPluginTest extends AbstractProjectBuilderSpec { runtimeUsage.dependencies == project.configurations.getByName(JavaPlatformPlugin.RUNTIME_CONFIGURATION_NAME).allDependencies.withType(ModuleDependency) runtimeUsage.dependencyConstraints.size() == 2 runtimeUsage.dependencyConstraints == project.configurations.getByName(JavaPlatformPlugin.RUNTIME_CONFIGURATION_NAME).allDependencyConstraints - runtimeUsage.attributes.keySet() == [Usage.USAGE_ATTRIBUTE, PlatformSupport.COMPONENT_CATEGORY] as Set + runtimeUsage.attributes.keySet() == [Usage.USAGE_ATTRIBUTE, PlatformSupport.VARIANT_CATEGORY] as Set runtimeUsage.attributes.getAttribute(Usage.USAGE_ATTRIBUTE).name == Usage.JAVA_RUNTIME - runtimeUsage.attributes.getAttribute(PlatformSupport.COMPONENT_CATEGORY) == PlatformSupport.REGULAR_PLATFORM + runtimeUsage.attributes.getAttribute(PlatformSupport.VARIANT_CATEGORY) == PlatformSupport.REGULAR_PLATFORM apiUsage.dependencies.size() == 1 apiUsage.dependencies == project.configurations.getByName(JavaPlatformPlugin.API_CONFIGURATION_NAME).allDependencies.withType(ModuleDependency) apiUsage.dependencyConstraints.size() == 1 apiUsage.dependencyConstraints == project.configurations.getByName(JavaPlatformPlugin.API_CONFIGURATION_NAME).allDependencyConstraints - apiUsage.attributes.keySet() == [Usage.USAGE_ATTRIBUTE, PlatformSupport.COMPONENT_CATEGORY] as Set + apiUsage.attributes.keySet() == [Usage.USAGE_ATTRIBUTE, PlatformSupport.VARIANT_CATEGORY] as Set apiUsage.attributes.getAttribute(Usage.USAGE_ATTRIBUTE).name == Usage.JAVA_API - apiUsage.attributes.getAttribute(PlatformSupport.COMPONENT_CATEGORY) == PlatformSupport.REGULAR_PLATFORM + apiUsage.attributes.getAttribute(PlatformSupport.VARIANT_CATEGORY) == PlatformSupport.REGULAR_PLATFORM } @Unroll("cannot add a dependency to the #configuration configuration by default") From 2f6aa4d888afbe5477856d8aa4c382779b3a8e5c Mon Sep 17 00:00:00 2001 From: Louis Jacomet Date: Mon, 4 Mar 2019 10:41:34 +0100 Subject: [PATCH 319/853] Update Category attribute to be typed Adapt code to new typed attributes, dealing with coercible String values when parsed from metadata and typed values when created inside a Gradle build. --- .../org/gradle/api/attributes/Category.java | 54 +++++++++++++++++++ ...ipleVariantSelectionIntegrationTest.groovy | 5 +- .../JavaPlatformResolveIntegrationTest.groovy | 6 +-- .../DefaultDependencyManagementServices.java | 5 +- .../DefaultDependencyConstraintHandler.java | 21 +++++--- .../DefaultDependencyHandler.java | 17 ++++-- .../dsl/dependencies/PlatformSupport.java | 51 ++++++++++-------- .../RepositoryChainArtifactResolver.java | 7 +-- .../parser/GradleModuleMetadataParser.java | 9 ++-- ...efaultMavenImmutableAttributesFactory.java | 10 ++-- .../MavenImmutableAttributesFactory.java | 2 + .../model/DefaultLocalComponentMetadata.java | 6 +-- ...aultDependencyConstraintHandlerTest.groovy | 4 +- .../DefaultDependencyHandlerTest.groovy | 2 +- ...faultMavenModuleResolveMetadataTest.groovy | 4 +- ...ncyInsightReportTaskIntegrationTest.groovy | 5 ++ ...ReportVariantDetailsIntegrationTest.groovy | 1 + .../maven/MavenPublishJavaIntegTest.groovy | 10 ++-- .../DefaultMavenPublicationTest.groovy | 4 +- .../AbstractMavenPublishIntegTest.groovy | 2 +- ...tionOutgoingVariantsIntegrationTest.groovy | 44 +++++++-------- ...jectTargetJvmVersionIntegrationTest.groovy | 5 ++ ...raryOutgoingVariantsIntegrationTest.groovy | 44 +++++++-------- ...jectOutgoingVariantsIntegrationTest.groovy | 44 +++++++-------- .../api/plugins/JavaPlatformPlugin.java | 30 ++++++----- .../org/gradle/api/plugins/JavaPlugin.java | 4 ++ .../internal/DefaultJavaFeatureSpec.java | 9 ++++ .../api/plugins/JavaPlatformPluginTest.groovy | 10 ++-- 28 files changed, 263 insertions(+), 152 deletions(-) create mode 100644 subprojects/core-api/src/main/java/org/gradle/api/attributes/Category.java diff --git a/subprojects/core-api/src/main/java/org/gradle/api/attributes/Category.java b/subprojects/core-api/src/main/java/org/gradle/api/attributes/Category.java new file mode 100644 index 0000000000000..0ab28cc715059 --- /dev/null +++ b/subprojects/core-api/src/main/java/org/gradle/api/attributes/Category.java @@ -0,0 +1,54 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.api.attributes; + +import org.gradle.api.Incubating; +import org.gradle.api.Named; + +/** + * This attribute describes the categories of variants for a given module. + *

    + * Two values are found in published components: + *

      + *
    • {@code library}: Indicates that the variant is a library, that usually means a binary and a set of dependencies
    • + *
    • {@code platform}: indicates that the variant is a platform, that usually means a definition of dependency constraints
    • + *
    + * One value is used for derivation. A {@code platform} variant can be consumed as a {@code enforced-platform} which means all the dependency + * information it provides is applied as {@code forced}. + * + * @since 5.3 + */ +@Incubating +public interface Category extends Named { + + Attribute CATEGORY_ATTRIBUTE = Attribute.of("org.gradle.category", Category.class); + + /** + * The library category + */ + String LIBRARY = "library"; + + /** + * The platform category + */ + String REGULAR_PLATFORM = "platform"; + + /** + * The enforced platform, usually a synthetic variant derived from the {@code platform} + */ + String ENFORCED_PLATFORM = "enforced-platform"; +} diff --git a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/attributes/CrossProjectMultipleVariantSelectionIntegrationTest.groovy b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/attributes/CrossProjectMultipleVariantSelectionIntegrationTest.groovy index 3968a335e75f1..10486d5c6944c 100644 --- a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/attributes/CrossProjectMultipleVariantSelectionIntegrationTest.groovy +++ b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/attributes/CrossProjectMultipleVariantSelectionIntegrationTest.groovy @@ -81,7 +81,7 @@ class CrossProjectMultipleVariantSelectionIntegrationTest extends AbstractDepend resolve.expectGraph { root(":", ":test:") { project(":lib", "test:lib:") { - variant "apiElements", ['org.gradle.usage':'java-api-jars', 'org.gradle.dependency.bundling':'external', 'org.gradle.jvm.version': JavaVersion.current().majorVersion] + variant "apiElements", ['org.gradle.usage':'java-api-jars', 'org.gradle.category':'library', 'org.gradle.dependency.bundling':'external', 'org.gradle.jvm.version': JavaVersion.current().majorVersion] artifact group:'', module:'', version: '', type: '', name: 'main', noType: true } project(":lib", "test:lib:") { @@ -103,6 +103,7 @@ class CrossProjectMultipleVariantSelectionIntegrationTest extends AbstractDepend canBeConsumed = true attributes { attribute(Usage.USAGE_ATTRIBUTE, project.objects.named(Usage, 'java-api-jars')) + attribute(Category.CATEGORY_ATTRIBUTE, project.objects.named(Category, Category.LIBRARY)) attribute(Bundling.BUNDLING_ATTRIBUTE, project.objects.named(Bundling, Bundling.EXTERNAL)) attribute(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE, Integer.valueOf(JavaVersion.current().majorVersion)) } @@ -129,7 +130,7 @@ class CrossProjectMultipleVariantSelectionIntegrationTest extends AbstractDepend resolve.expectGraph { root(":", ":test:") { project(":lib", "test:lib:") { - variant "apiElements", ['org.gradle.usage':'java-api-jars', 'org.gradle.dependency.bundling':'external', 'org.gradle.jvm.version': JavaVersion.current().majorVersion] + variant "apiElements", ['org.gradle.usage':'java-api-jars', 'org.gradle.category':'library', 'org.gradle.dependency.bundling':'external', 'org.gradle.jvm.version': JavaVersion.current().majorVersion] artifact group:'', module:'', version: '', type: '', name: 'main', noType: true } } diff --git a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/platforms/JavaPlatformResolveIntegrationTest.groovy b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/platforms/JavaPlatformResolveIntegrationTest.groovy index 60880906fa0af..72a75a57d6deb 100755 --- a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/platforms/JavaPlatformResolveIntegrationTest.groovy +++ b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/platforms/JavaPlatformResolveIntegrationTest.groovy @@ -16,8 +16,8 @@ package org.gradle.integtests.resolve.platforms +import org.gradle.api.attributes.Category import org.gradle.api.attributes.Usage -import org.gradle.api.internal.artifacts.dsl.dependencies.PlatformSupport import org.gradle.integtests.fixtures.AbstractHttpDependencyResolutionTest import org.gradle.integtests.fixtures.FeaturePreviewsFixture import org.gradle.integtests.fixtures.resolve.ResolveTestFixture @@ -219,9 +219,9 @@ class JavaPlatformResolveIntegrationTest extends AbstractHttpDependencyResolutio def platform = mavenHttpRepo.module("org", "platform", "1.0") .withModuleMetadata() .adhocVariants() - .variant("apiElements", [(Usage.USAGE_ATTRIBUTE.name): Usage.JAVA_API, (PlatformSupport.VARIANT_CATEGORY.name): PlatformSupport.REGULAR_PLATFORM]) { useDefaultArtifacts = false } + .variant("apiElements", [(Usage.USAGE_ATTRIBUTE.name): Usage.JAVA_API, (Category.CATEGORY_ATTRIBUTE.name): Category.REGULAR_PLATFORM]) { useDefaultArtifacts = false } .dependsOn("org", "foo", "1.0") - .variant("runtimeElements", [(Usage.USAGE_ATTRIBUTE.name): Usage.JAVA_RUNTIME, (PlatformSupport.VARIANT_CATEGORY.name): PlatformSupport.REGULAR_PLATFORM]) { + .variant("runtimeElements", [(Usage.USAGE_ATTRIBUTE.name): Usage.JAVA_RUNTIME, (Category.CATEGORY_ATTRIBUTE.name): Category.REGULAR_PLATFORM]) { useDefaultArtifacts = false } .dependsOn("org", "foo", "1.0") diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/DefaultDependencyManagementServices.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/DefaultDependencyManagementServices.java index 7c31126ab1529..d7e9e9808232b 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/DefaultDependencyManagementServices.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/DefaultDependencyManagementServices.java @@ -409,7 +409,8 @@ DependencyHandler createDependencyHandler(Instantiator instantiator, Configurati resolutionQueryFactory, attributesSchema, artifactTransformRegistrations, - artifactTypeRegistry); + artifactTypeRegistry, + NamedObjectInstantiator.INSTANCE); } DependencyLockingHandler createDependencyLockingHandler(Instantiator instantiator, ConfigurationContainerInternal configurationContainer) { @@ -421,7 +422,7 @@ DependencyLockingProvider createDependencyLockingProvider(Instantiator instantia } DependencyConstraintHandler createDependencyConstraintHandler(Instantiator instantiator, ConfigurationContainerInternal configurationContainer, DependencyFactory dependencyFactory, ComponentMetadataHandler componentMetadataHandler) { - return instantiator.newInstance(DefaultDependencyConstraintHandler.class, configurationContainer, dependencyFactory, componentMetadataHandler); + return instantiator.newInstance(DefaultDependencyConstraintHandler.class, configurationContainer, dependencyFactory, NamedObjectInstantiator.INSTANCE); } DefaultComponentMetadataHandler createComponentMetadataHandler(Instantiator instantiator, ImmutableModuleIdentifierFactory moduleIdentifierFactory, SimpleMapInterner interner, ImmutableAttributesFactory attributesFactory, IsolatableFactory isolatableFactory, ComponentMetadataRuleExecutor componentMetadataRuleExecutor) { diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/dsl/dependencies/DefaultDependencyConstraintHandler.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/dsl/dependencies/DefaultDependencyConstraintHandler.java index acba7fdfff465..8d0d40a47363e 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/dsl/dependencies/DefaultDependencyConstraintHandler.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/dsl/dependencies/DefaultDependencyConstraintHandler.java @@ -21,9 +21,10 @@ import org.gradle.api.artifacts.Configuration; import org.gradle.api.artifacts.ConfigurationContainer; import org.gradle.api.artifacts.DependencyConstraint; -import org.gradle.api.artifacts.dsl.ComponentMetadataHandler; import org.gradle.api.artifacts.dsl.DependencyConstraintHandler; +import org.gradle.api.attributes.Category; import org.gradle.api.internal.artifacts.dependencies.DependencyConstraintInternal; +import org.gradle.api.internal.model.NamedObjectInstantiator; import org.gradle.internal.metaobject.MethodAccess; import org.gradle.internal.metaobject.MethodMixIn; import org.gradle.util.ConfigureUtil; @@ -34,15 +35,19 @@ public class DefaultDependencyConstraintHandler implements DependencyConstraintH private final ConfigurationContainer configurationContainer; private final DependencyFactory dependencyFactory; private final DynamicAddDependencyMethods dynamicMethods; - private final ComponentMetadataHandler componentMetadataHandler; + private final NamedObjectInstantiator namedObjectInstantiator; + private final Category platform; + private final Category enforcedPlatform; public DefaultDependencyConstraintHandler(ConfigurationContainer configurationContainer, DependencyFactory dependencyFactory, - ComponentMetadataHandler componentMetadataHandler) { + NamedObjectInstantiator namedObjectInstantiator) { this.configurationContainer = configurationContainer; this.dependencyFactory = dependencyFactory; this.dynamicMethods = new DynamicAddDependencyMethods(configurationContainer, new DependencyConstraintAdder()); - this.componentMetadataHandler = componentMetadataHandler; + this.namedObjectInstantiator = namedObjectInstantiator; + platform = toCategory(Category.REGULAR_PLATFORM); + enforcedPlatform = toCategory(Category.ENFORCED_PLATFORM); } @Override @@ -68,7 +73,7 @@ public DependencyConstraint create(Object dependencyNotation, Action { @Override public DependencyConstraint add(Configuration configuration, Object dependencyNotation, Closure configureClosure) { diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/dsl/dependencies/DefaultDependencyHandler.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/dsl/dependencies/DefaultDependencyHandler.java index 9ab7c116d3f06..bc9d21978d095 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/dsl/dependencies/DefaultDependencyHandler.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/dsl/dependencies/DefaultDependencyHandler.java @@ -33,9 +33,11 @@ import org.gradle.api.artifacts.transform.VariantTransform; import org.gradle.api.artifacts.type.ArtifactTypeContainer; import org.gradle.api.attributes.AttributesSchema; +import org.gradle.api.attributes.Category; import org.gradle.api.attributes.HasConfigurableAttributes; import org.gradle.api.internal.artifacts.VariantTransformRegistry; import org.gradle.api.internal.artifacts.query.ArtifactResolutionQueryFactory; +import org.gradle.api.internal.model.NamedObjectInstantiator; import org.gradle.internal.Factory; import org.gradle.internal.metaobject.MethodAccess; import org.gradle.internal.metaobject.MethodMixIn; @@ -57,6 +59,7 @@ public class DefaultDependencyHandler implements DependencyHandler, MethodMixIn private final AttributesSchema attributesSchema; private final VariantTransformRegistry transforms; private final Factory artifactTypeContainer; + private final NamedObjectInstantiator namedObjectInstantiator; private final DynamicAddDependencyMethods dynamicMethods; public DefaultDependencyHandler(ConfigurationContainer configurationContainer, @@ -68,7 +71,8 @@ public DefaultDependencyHandler(ConfigurationContainer configurationContainer, ArtifactResolutionQueryFactory resolutionQueryFactory, AttributesSchema attributesSchema, VariantTransformRegistry transforms, - Factory artifactTypeContainer) { + Factory artifactTypeContainer, + NamedObjectInstantiator namedObjectInstantiator) { this.configurationContainer = configurationContainer; this.dependencyFactory = dependencyFactory; this.projectFinder = projectFinder; @@ -79,6 +83,7 @@ public DefaultDependencyHandler(ConfigurationContainer configurationContainer, this.attributesSchema = attributesSchema; this.transforms = transforms; this.artifactTypeContainer = artifactTypeContainer; + this.namedObjectInstantiator = namedObjectInstantiator; configureSchema(); dynamicMethods = new DynamicAddDependencyMethods(configurationContainer, new DirectDependencyAdder()); } @@ -223,7 +228,7 @@ public void registerTransform(Class) dependency, PlatformSupport.REGULAR_PLATFORM); + PlatformSupport.addPlatformAttribute((HasConfigurableAttributes) dependency, toCategory(Category.REGULAR_PLATFORM)); } return dependency; } @@ -241,9 +246,9 @@ public Dependency enforcedPlatform(Object notation) { if (platformDependency instanceof ExternalModuleDependency) { ExternalModuleDependency externalModuleDependency = (ExternalModuleDependency) platformDependency; externalModuleDependency.setForce(true); - PlatformSupport.addPlatformAttribute(externalModuleDependency, PlatformSupport.ENFORCED_PLATFORM); + PlatformSupport.addPlatformAttribute(externalModuleDependency, toCategory(Category.ENFORCED_PLATFORM)); } else if (platformDependency instanceof HasConfigurableAttributes) { - PlatformSupport.addPlatformAttribute((HasConfigurableAttributes) platformDependency, PlatformSupport.ENFORCED_PLATFORM); + PlatformSupport.addPlatformAttribute((HasConfigurableAttributes) platformDependency, toCategory(Category.ENFORCED_PLATFORM)); } return platformDependency; } @@ -255,6 +260,10 @@ public Dependency enforcedPlatform(Object notation, Action c return dep; } + private Category toCategory(String category) { + return namedObjectInstantiator.named(Category.class, category); + } + private class DirectDependencyAdder implements DynamicAddDependencyMethods.DependencyAdder { @Override diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/dsl/dependencies/PlatformSupport.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/dsl/dependencies/PlatformSupport.java index 24dc23bf24bf9..71931dd5963cd 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/dsl/dependencies/PlatformSupport.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/dsl/dependencies/PlatformSupport.java @@ -18,68 +18,77 @@ import com.google.common.base.Objects; import com.google.common.collect.ImmutableSet; import org.gradle.api.Action; -import org.gradle.api.attributes.Attribute; import org.gradle.api.attributes.AttributeContainer; import org.gradle.api.attributes.AttributeDisambiguationRule; import org.gradle.api.attributes.AttributeMatchingStrategy; import org.gradle.api.attributes.AttributesSchema; +import org.gradle.api.attributes.Category; import org.gradle.api.attributes.HasConfigurableAttributes; import org.gradle.api.attributes.MultipleCandidatesDetails; import org.gradle.api.internal.ReusableAction; +import org.gradle.api.internal.artifacts.repositories.metadata.MavenImmutableAttributesFactory; +import org.gradle.api.internal.model.NamedObjectInstantiator; import org.gradle.internal.component.external.model.ComponentVariant; import java.util.Set; public abstract class PlatformSupport { - public static final Attribute VARIANT_CATEGORY = Attribute.of("org.gradle.category", String.class); - public static final String LIBRARY = "library"; - public static final String REGULAR_PLATFORM = "platform"; - public static final String ENFORCED_PLATFORM = "enforced-platform"; + + public static final Category REGULAR_PLATFORM = NamedObjectInstantiator.INSTANCE.named(Category.class, Category.REGULAR_PLATFORM); + public static final Category ENFORCED_PLATFORM = NamedObjectInstantiator.INSTANCE.named(Category.class, Category.ENFORCED_PLATFORM); public static boolean isTargettingPlatform(HasConfigurableAttributes target) { - String category = target.getAttributes().getAttribute(VARIANT_CATEGORY); + Category category = target.getAttributes().getAttribute(Category.CATEGORY_ATTRIBUTE); return REGULAR_PLATFORM.equals(category) || ENFORCED_PLATFORM.equals(category); } public static void configureSchema(AttributesSchema attributesSchema) { - AttributeMatchingStrategy componentTypeMatchingStrategy = attributesSchema.attribute(PlatformSupport.VARIANT_CATEGORY); + AttributeMatchingStrategy componentTypeMatchingStrategy = attributesSchema.attribute(Category.CATEGORY_ATTRIBUTE); componentTypeMatchingStrategy.getDisambiguationRules().add(PlatformSupport.ComponentCategoryDisambiguationRule.class); } - static void addPlatformAttribute(HasConfigurableAttributes dependency, final String type) { + static void addPlatformAttribute(HasConfigurableAttributes dependency, final Category category) { dependency.attributes(new Action() { @Override public void execute(AttributeContainer attributeContainer) { - attributeContainer.attribute(VARIANT_CATEGORY, type); + attributeContainer.attribute(Category.CATEGORY_ATTRIBUTE, category); } }); } + /** + * Checks if the variant is an {@code enforced-platform} one. + *

    + * This method is designed to be called on parsed metadata and thus interacts with the {@code String} version of the attribute. + * + * @param variant the variant to test + * @return {@code true} if this represents an {@code enforced-platform}, {@code false} otherwise + */ public static boolean hasForcedDependencies(ComponentVariant variant) { - return Objects.equal(variant.getAttributes().getAttribute(VARIANT_CATEGORY), ENFORCED_PLATFORM); + return Objects.equal(variant.getAttributes().getAttribute(MavenImmutableAttributesFactory.CATEGORY_ATTRIBUTE), Category.ENFORCED_PLATFORM); } - public static class ComponentCategoryDisambiguationRule implements AttributeDisambiguationRule, ReusableAction { + public static class ComponentCategoryDisambiguationRule implements AttributeDisambiguationRule, ReusableAction { @Override - public void execute(MultipleCandidatesDetails details) { - String consumerValue = details.getConsumerValue(); - Set candidateValues = details.getCandidateValues(); + public void execute(MultipleCandidatesDetails details) { + Category consumerValue = details.getConsumerValue(); + Set candidateValues = details.getCandidateValues(); if (consumerValue == null) { // consumer expressed no preference, defaults to library - if (candidateValues.contains(LIBRARY)) { - details.closestMatch(LIBRARY); - return; - } + candidateValues.stream() + .filter(it -> it.getName().equals(Category.LIBRARY)) + .findFirst() + .ifPresent(it -> details.closestMatch(it)); } } } - public static class PreferRegularPlatform implements AttributeDisambiguationRule { - private final static Set PLATFORM_TYPES = ImmutableSet.of(REGULAR_PLATFORM, ENFORCED_PLATFORM); + public static class PreferRegularPlatform implements AttributeDisambiguationRule { + private final static Set PLATFORM_TYPES = ImmutableSet.of(REGULAR_PLATFORM, ENFORCED_PLATFORM); @Override - public void execute(MultipleCandidatesDetails details) { + public void execute(MultipleCandidatesDetails details) { if (details.getCandidateValues().equals(PLATFORM_TYPES)) { details.closestMatch(REGULAR_PLATFORM); } diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/RepositoryChainArtifactResolver.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/RepositoryChainArtifactResolver.java index d85105e5c39c5..9e044fb8a93ad 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/RepositoryChainArtifactResolver.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/RepositoryChainArtifactResolver.java @@ -15,9 +15,10 @@ */ package org.gradle.api.internal.artifacts.ivyservice.ivyresolve; -import org.gradle.api.internal.artifacts.dsl.dependencies.PlatformSupport; +import org.gradle.api.attributes.Category; import org.gradle.api.internal.artifacts.ivyservice.resolveengine.artifact.ArtifactSet; import org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes.ModuleExclusion; +import org.gradle.api.internal.artifacts.repositories.metadata.MavenImmutableAttributesFactory; import org.gradle.api.internal.artifacts.type.ArtifactTypeRegistry; import org.gradle.api.internal.attributes.AttributeValue; import org.gradle.api.internal.attributes.ImmutableAttributes; @@ -66,10 +67,10 @@ public ArtifactSet resolveArtifacts(ComponentResolveMetadata component, Configur } if (configuration.getArtifacts().isEmpty()) { // checks if it's a derived platform - AttributeValue componentTypeEntry = configuration.getAttributes().findEntry(PlatformSupport.VARIANT_CATEGORY); + AttributeValue componentTypeEntry = configuration.getAttributes().findEntry(MavenImmutableAttributesFactory.CATEGORY_ATTRIBUTE); if (componentTypeEntry.isPresent()) { String value = componentTypeEntry.get(); - if (PlatformSupport.REGULAR_PLATFORM.equals(value) || PlatformSupport.ENFORCED_PLATFORM.equals(value)) { + if (Category.REGULAR_PLATFORM.equals(value) || Category.ENFORCED_PLATFORM.equals(value)) { return NO_ARTIFACTS; } } diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/parser/GradleModuleMetadataParser.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/parser/GradleModuleMetadataParser.java index e1429ab7f2f34..3a294491b57de 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/parser/GradleModuleMetadataParser.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/parser/GradleModuleMetadataParser.java @@ -23,13 +23,14 @@ import org.gradle.api.Transformer; import org.gradle.api.artifacts.VersionConstraint; import org.gradle.api.attributes.Attribute; +import org.gradle.api.attributes.Category; import org.gradle.api.capabilities.Capability; import org.gradle.api.internal.artifacts.ImmutableModuleIdentifierFactory; import org.gradle.api.internal.artifacts.ImmutableVersionConstraint; import org.gradle.api.internal.artifacts.dependencies.DefaultImmutableVersionConstraint; -import org.gradle.api.internal.artifacts.dsl.dependencies.PlatformSupport; import org.gradle.api.internal.artifacts.ivyservice.moduleconverter.dependencies.DefaultExcludeRuleConverter; import org.gradle.api.internal.artifacts.ivyservice.moduleconverter.dependencies.ExcludeRuleConverter; +import org.gradle.api.internal.artifacts.repositories.metadata.MavenImmutableAttributesFactory; import org.gradle.api.internal.attributes.AttributeValue; import org.gradle.api.internal.attributes.ImmutableAttributes; import org.gradle.api.internal.attributes.ImmutableAttributesFactory; @@ -174,10 +175,10 @@ private void consumeVariant(JsonReader reader, MutableModuleComponentResolveMeta reader.endObject(); MutableComponentVariant variant = metadata.addVariant(variantName, attributes); populateVariant(files, dependencies, dependencyConstraints, capabilities, variant); - AttributeValue entry = attributes.findEntry(PlatformSupport.VARIANT_CATEGORY); - if (entry.isPresent() && PlatformSupport.REGULAR_PLATFORM.equals(entry.get())) { + AttributeValue entry = attributes.findEntry(MavenImmutableAttributesFactory.CATEGORY_ATTRIBUTE); + if (entry.isPresent() && Category.REGULAR_PLATFORM.equals(entry.get())) { // This generates a synthetic enforced platform variant with the same dependencies, similar to what the Maven variant derivation strategy does - ImmutableAttributes enforcedAttributes = attributesFactory.concat(attributes, attributesFactory.of(PlatformSupport.VARIANT_CATEGORY, PlatformSupport.ENFORCED_PLATFORM)); + ImmutableAttributes enforcedAttributes = attributesFactory.concat(attributes, MavenImmutableAttributesFactory.CATEGORY_ATTRIBUTE, new CoercingStringValueSnapshot(Category.ENFORCED_PLATFORM, instantiator)); MutableComponentVariant syntheticEnforcedVariant = metadata.addVariant("enforced" + capitalize(variantName), enforcedAttributes); populateVariant(files, dependencies, dependencyConstraints, capabilities, syntheticEnforcedVariant); } diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/repositories/metadata/DefaultMavenImmutableAttributesFactory.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/repositories/metadata/DefaultMavenImmutableAttributesFactory.java index 5d4560b009ef9..0a62818989a2f 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/repositories/metadata/DefaultMavenImmutableAttributesFactory.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/repositories/metadata/DefaultMavenImmutableAttributesFactory.java @@ -18,7 +18,7 @@ import com.google.common.base.Objects; import com.google.common.collect.Maps; import org.gradle.api.attributes.Attribute; -import org.gradle.api.internal.artifacts.dsl.dependencies.PlatformSupport; +import org.gradle.api.attributes.Category; import org.gradle.api.internal.attributes.AttributeContainerInternal; import org.gradle.api.internal.attributes.AttributeMergingException; import org.gradle.api.internal.attributes.ImmutableAttributes; @@ -76,11 +76,11 @@ public ImmutableAttributes safeConcat(ImmutableAttributes attributes1, Immutable @Override public ImmutableAttributes libraryWithUsage(ImmutableAttributes original, String usage) { - ComponentTypeEntry entry = new ComponentTypeEntry(original, PlatformSupport.LIBRARY, usage); + ComponentTypeEntry entry = new ComponentTypeEntry(original, Category.LIBRARY, usage); ImmutableAttributes result = concatCache.get(entry); if (result == null) { result = concat(original, USAGE_ATTRIBUTE, new CoercingStringValueSnapshot(usage, objectInstantiator)); - result = concat(result, PlatformSupport.VARIANT_CATEGORY, PlatformSupport.LIBRARY); + result = concat(result, CATEGORY_ATTRIBUTE, new CoercingStringValueSnapshot(Category.LIBRARY, objectInstantiator)); concatCache.put(entry, result); } return result; @@ -88,12 +88,12 @@ public ImmutableAttributes libraryWithUsage(ImmutableAttributes original, String @Override public ImmutableAttributes platformWithUsage(ImmutableAttributes original, String usage, boolean enforced) { - String componentType = enforced ? PlatformSupport.ENFORCED_PLATFORM : PlatformSupport.REGULAR_PLATFORM; + String componentType = enforced ? Category.ENFORCED_PLATFORM : Category.REGULAR_PLATFORM; ComponentTypeEntry entry = new ComponentTypeEntry(original, componentType, usage); ImmutableAttributes result = concatCache.get(entry); if (result == null) { result = concat(original, USAGE_ATTRIBUTE, new CoercingStringValueSnapshot(usage, objectInstantiator)); - result = concat(result, PlatformSupport.VARIANT_CATEGORY, componentType); + result = concat(result, CATEGORY_ATTRIBUTE, new CoercingStringValueSnapshot(componentType, objectInstantiator)); concatCache.put(entry, result); } return result; diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/repositories/metadata/MavenImmutableAttributesFactory.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/repositories/metadata/MavenImmutableAttributesFactory.java index e4dc7408391f5..8eb3fc61d3016 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/repositories/metadata/MavenImmutableAttributesFactory.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/repositories/metadata/MavenImmutableAttributesFactory.java @@ -16,6 +16,7 @@ package org.gradle.api.internal.artifacts.repositories.metadata; import org.gradle.api.attributes.Attribute; +import org.gradle.api.attributes.Category; import org.gradle.api.attributes.Usage; import org.gradle.api.internal.attributes.ImmutableAttributes; import org.gradle.api.internal.attributes.ImmutableAttributesFactory; @@ -29,6 +30,7 @@ public interface MavenImmutableAttributesFactory extends ImmutableAttributesFactory { // We need to work with the 'String' version of the usage attribute, since this is expected for all providers by the `PreferJavaRuntimeVariant` schema Attribute USAGE_ATTRIBUTE = Attribute.of(Usage.USAGE_ATTRIBUTE.getName(), String.class); + Attribute CATEGORY_ATTRIBUTE = Attribute.of(Category.CATEGORY_ATTRIBUTE.getName(), String.class); ImmutableAttributes libraryWithUsage(ImmutableAttributes original, String usage); ImmutableAttributes platformWithUsage(ImmutableAttributes original, String usage, boolean enforced); diff --git a/subprojects/dependency-management/src/main/java/org/gradle/internal/component/local/model/DefaultLocalComponentMetadata.java b/subprojects/dependency-management/src/main/java/org/gradle/internal/component/local/model/DefaultLocalComponentMetadata.java index 0d6d79b9d2d9a..8dfb1433afa4f 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/internal/component/local/model/DefaultLocalComponentMetadata.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/internal/component/local/model/DefaultLocalComponentMetadata.java @@ -30,10 +30,10 @@ import org.gradle.api.artifacts.PublishArtifact; import org.gradle.api.artifacts.component.ComponentIdentifier; import org.gradle.api.attributes.AttributeContainer; +import org.gradle.api.attributes.Category; import org.gradle.api.capabilities.CapabilitiesMetadata; import org.gradle.api.internal.artifacts.configurations.ConfigurationInternal; import org.gradle.api.internal.artifacts.configurations.OutgoingVariant; -import org.gradle.api.internal.artifacts.dsl.dependencies.PlatformSupport; import org.gradle.api.internal.artifacts.ivyservice.moduleconverter.dependencies.LocalConfigurationMetadataBuilder; import org.gradle.api.internal.attributes.AttributeValue; import org.gradle.api.internal.attributes.AttributesSchemaInternal; @@ -407,8 +407,8 @@ public List getDependencies() { } } maybeAddGeneratedDependencies(result); - AttributeValue attributeValue = this.getAttributes().findEntry(PlatformSupport.VARIANT_CATEGORY); - if (attributeValue.isPresent() && attributeValue.get().equals(PlatformSupport.ENFORCED_PLATFORM)) { + AttributeValue attributeValue = this.getAttributes().findEntry(Category.CATEGORY_ATTRIBUTE); + if (attributeValue.isPresent() && attributeValue.get().getName().equals(Category.ENFORCED_PLATFORM)) { // need to wrap all dependencies to force them ImmutableList rawDependencies = result.build(); result = ImmutableList.builder(); diff --git a/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/dsl/dependencies/DefaultDependencyConstraintHandlerTest.groovy b/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/dsl/dependencies/DefaultDependencyConstraintHandlerTest.groovy index 41ceccaeac007..f74516f0dc723 100644 --- a/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/dsl/dependencies/DefaultDependencyConstraintHandlerTest.groovy +++ b/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/dsl/dependencies/DefaultDependencyConstraintHandlerTest.groovy @@ -22,7 +22,6 @@ import org.gradle.api.artifacts.ConfigurationContainer import org.gradle.api.artifacts.DependencyConstraint import org.gradle.api.artifacts.DependencyConstraintSet import org.gradle.api.artifacts.VersionConstraint -import org.gradle.api.artifacts.dsl.ComponentMetadataHandler import org.gradle.util.TestUtil import spock.lang.Specification @@ -35,9 +34,8 @@ class DefaultDependencyConstraintHandlerTest extends Specification { private def dependencyFactory = Mock(DependencyFactory) private def configuration = Mock(Configuration) private def dependencyConstraintSet = Mock(DependencyConstraintSet) - private def componentMetadataHandler = Mock(ComponentMetadataHandler) - private DefaultDependencyConstraintHandler dependencyConstraintHandler = TestUtil.instantiatorFactory().decorateLenient().newInstance(DefaultDependencyConstraintHandler, configurationContainer, dependencyFactory, componentMetadataHandler) + private DefaultDependencyConstraintHandler dependencyConstraintHandler = TestUtil.instantiatorFactory().decorateLenient().newInstance(DefaultDependencyConstraintHandler, configurationContainer, dependencyFactory, TestUtil.objectInstantiator()) void setup() { _ * configurationContainer.findByName(TEST_CONF_NAME) >> configuration diff --git a/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/dsl/dependencies/DefaultDependencyHandlerTest.groovy b/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/dsl/dependencies/DefaultDependencyHandlerTest.groovy index 6a3aa350d0660..bffc04d490ae2 100644 --- a/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/dsl/dependencies/DefaultDependencyHandlerTest.groovy +++ b/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/dsl/dependencies/DefaultDependencyHandlerTest.groovy @@ -48,7 +48,7 @@ class DefaultDependencyHandlerTest extends Specification { private DefaultDependencyHandler dependencyHandler = TestUtil.instantiatorFactory().decorateLenient().newInstance(DefaultDependencyHandler, configurationContainer, dependencyFactory, projectFinder, Stub(DependencyConstraintHandler), Stub(ComponentMetadataHandler), Stub(ComponentModuleMetadataHandler), Stub(ArtifactResolutionQueryFactory), - Stub(AttributesSchema), Stub(VariantTransformRegistry), Stub(Factory)) + Stub(AttributesSchema), Stub(VariantTransformRegistry), Stub(Factory), TestUtil.objectInstantiator()) void setup() { _ * configurationContainer.findByName(TEST_CONF_NAME) >> configuration diff --git a/subprojects/dependency-management/src/test/groovy/org/gradle/internal/component/external/model/DefaultMavenModuleResolveMetadataTest.groovy b/subprojects/dependency-management/src/test/groovy/org/gradle/internal/component/external/model/DefaultMavenModuleResolveMetadataTest.groovy index efb8e28f4d6a2..f08c8587ffbdb 100644 --- a/subprojects/dependency-management/src/test/groovy/org/gradle/internal/component/external/model/DefaultMavenModuleResolveMetadataTest.groovy +++ b/subprojects/dependency-management/src/test/groovy/org/gradle/internal/component/external/model/DefaultMavenModuleResolveMetadataTest.groovy @@ -21,11 +21,11 @@ import org.gradle.api.artifacts.ModuleVersionIdentifier import org.gradle.api.artifacts.component.ModuleComponentIdentifier import org.gradle.api.attributes.Attribute import org.gradle.api.attributes.AttributeContainer +import org.gradle.api.attributes.Category import org.gradle.api.attributes.Usage import org.gradle.api.internal.artifacts.DefaultImmutableModuleIdentifierFactory import org.gradle.api.internal.artifacts.DefaultModuleIdentifier import org.gradle.api.internal.artifacts.dependencies.DefaultMutableVersionConstraint -import org.gradle.api.internal.artifacts.dsl.dependencies.PlatformSupport import org.gradle.api.internal.artifacts.repositories.metadata.DefaultMavenImmutableAttributesFactory import org.gradle.api.internal.artifacts.repositories.metadata.MavenMutableModuleMetadataFactory import org.gradle.api.internal.model.NamedObjectInstantiator @@ -147,7 +147,7 @@ class DefaultMavenModuleResolveMetadataTest extends AbstractLazyModuleComponentR def "recognises java library for packaging=#packaging"() { given: def stringUsageAttribute = Attribute.of(Usage.USAGE_ATTRIBUTE.getName(), String.class) - def componentTypeAttribute = PlatformSupport.VARIANT_CATEGORY + def componentTypeAttribute = Attribute.of(Category.CATEGORY_ATTRIBUTE.getName(), String.class) def metadata = new DefaultMutableMavenModuleResolveMetadata(Mock(ModuleVersionIdentifier), id, [], new DefaultMavenImmutableAttributesFactory(AttributeTestUtil.attributesFactory(), NamedObjectInstantiator.INSTANCE), TestUtil.objectInstantiator()) metadata.packaging = packaging metadata.variantMetadataRules.variantDerivationStrategy = new JavaEcosystemVariantDerivationStrategy() diff --git a/subprojects/diagnostics/src/integTest/groovy/org/gradle/api/tasks/diagnostics/DependencyInsightReportTaskIntegrationTest.groovy b/subprojects/diagnostics/src/integTest/groovy/org/gradle/api/tasks/diagnostics/DependencyInsightReportTaskIntegrationTest.groovy index 2340f632dd6a6..d45985bc04113 100644 --- a/subprojects/diagnostics/src/integTest/groovy/org/gradle/api/tasks/diagnostics/DependencyInsightReportTaskIntegrationTest.groovy +++ b/subprojects/diagnostics/src/integTest/groovy/org/gradle/api/tasks/diagnostics/DependencyInsightReportTaskIntegrationTest.groovy @@ -1705,6 +1705,7 @@ project : variant "runtimeElements" [ org.gradle.usage = java-runtime-jars (not requested) org.gradle.dependency.bundling = external (not requested) + org.gradle.category = library (not requested) org.gradle.jvm.version = ${JavaVersion.current().majorVersion} (not requested) ] @@ -1804,6 +1805,7 @@ project :impl variant "runtimeElements" [ org.gradle.usage = java-runtime-jars (not requested) org.gradle.dependency.bundling = external (not requested) + org.gradle.category = library (not requested) org.gradle.jvm.version = ${JavaVersion.current().majorVersion} (not requested) ] @@ -1974,6 +1976,7 @@ project :api variant "apiElements" [ org.gradle.usage = java-api-jars (compatible with: java-api) org.gradle.dependency.bundling = external + org.gradle.category = library (not requested) org.gradle.jvm.version = ${JavaVersion.current().majorVersion} ] @@ -1991,6 +1994,7 @@ project :some:deeply:nested variant "apiElements" [ org.gradle.usage = java-api-jars (compatible with: java-api) org.gradle.dependency.bundling = external + org.gradle.category = library (not requested) org.gradle.jvm.version = ${JavaVersion.current().majorVersion} ] @@ -2007,6 +2011,7 @@ project :some:deeply:nested variant "apiElements" [ org.gradle.usage = java-api-jars (compatible with: java-api) org.gradle.dependency.bundling = external + org.gradle.category = library (not requested) org.gradle.jvm.version = ${JavaVersion.current().majorVersion} ] diff --git a/subprojects/diagnostics/src/integTest/groovy/org/gradle/api/tasks/diagnostics/DependencyInsightReportVariantDetailsIntegrationTest.groovy b/subprojects/diagnostics/src/integTest/groovy/org/gradle/api/tasks/diagnostics/DependencyInsightReportVariantDetailsIntegrationTest.groovy index 39860d524f5a7..694e165c59718 100644 --- a/subprojects/diagnostics/src/integTest/groovy/org/gradle/api/tasks/diagnostics/DependencyInsightReportVariantDetailsIntegrationTest.groovy +++ b/subprojects/diagnostics/src/integTest/groovy/org/gradle/api/tasks/diagnostics/DependencyInsightReportVariantDetailsIntegrationTest.groovy @@ -57,6 +57,7 @@ class DependencyInsightReportVariantDetailsIntegrationTest extends AbstractInteg variant "$expectedVariant" [ $expectedAttributes org.gradle.dependency.bundling = external + org.gradle.category = library (not requested) org.gradle.jvm.version = ${JavaVersion.current().majorVersion} ] diff --git a/subprojects/maven/src/integTest/groovy/org/gradle/api/publish/maven/MavenPublishJavaIntegTest.groovy b/subprojects/maven/src/integTest/groovy/org/gradle/api/publish/maven/MavenPublishJavaIntegTest.groovy index fdf1c65f82c50..dffa300f123c6 100644 --- a/subprojects/maven/src/integTest/groovy/org/gradle/api/publish/maven/MavenPublishJavaIntegTest.groovy +++ b/subprojects/maven/src/integTest/groovy/org/gradle/api/publish/maven/MavenPublishJavaIntegTest.groovy @@ -16,7 +16,7 @@ package org.gradle.api.publish.maven -import org.gradle.api.internal.artifacts.dsl.dependencies.PlatformSupport +import org.gradle.api.attributes.Category import org.gradle.api.publish.maven.internal.publication.DefaultMavenPublication import org.gradle.integtests.fixtures.FeaturePreviewsFixture import org.gradle.integtests.fixtures.publish.maven.AbstractMavenPublishIntegTest @@ -970,7 +970,7 @@ $append javaLibrary.parsedModuleMetadata.variant("apiElements") { dependency('org.test:bar:').exists() dependency('org.test:bom:1.0') { - hasAttribute(PlatformSupport.VARIANT_CATEGORY.name, PlatformSupport.REGULAR_PLATFORM) + hasAttribute(Category.CATEGORY_ATTRIBUTE.name, Category.REGULAR_PLATFORM) } noMoreDependencies() } @@ -979,7 +979,7 @@ $append javaLibrary.parsedModuleMetadata.variant("runtimeElements") { dependency('org.test:bar:').exists() dependency('org.test:bom:1.0') { - hasAttribute(PlatformSupport.VARIANT_CATEGORY.name, PlatformSupport.REGULAR_PLATFORM) + hasAttribute(Category.CATEGORY_ATTRIBUTE.name, Category.REGULAR_PLATFORM) } noMoreDependencies() } @@ -1144,7 +1144,7 @@ include(':platform') javaLibrary.parsedModuleMetadata.variant("apiElements") { dependency('org.test:bar:').exists() dependency('org.gradle.test:platform:1.9') { - hasAttribute(PlatformSupport.VARIANT_CATEGORY.name, PlatformSupport.REGULAR_PLATFORM) + hasAttribute(Category.CATEGORY_ATTRIBUTE.name, Category.REGULAR_PLATFORM) } noMoreDependencies() } @@ -1153,7 +1153,7 @@ include(':platform') javaLibrary.parsedModuleMetadata.variant("runtimeElements") { dependency('org.test:bar:').exists() dependency('org.gradle.test:platform:1.9') { - hasAttribute(PlatformSupport.VARIANT_CATEGORY.name, PlatformSupport.REGULAR_PLATFORM) + hasAttribute(Category.CATEGORY_ATTRIBUTE.name, Category.REGULAR_PLATFORM) } noMoreDependencies() } diff --git a/subprojects/maven/src/test/groovy/org/gradle/api/publish/maven/internal/publication/DefaultMavenPublicationTest.groovy b/subprojects/maven/src/test/groovy/org/gradle/api/publish/maven/internal/publication/DefaultMavenPublicationTest.groovy index 066c4252b0e65..44a9680f2b8a8 100644 --- a/subprojects/maven/src/test/groovy/org/gradle/api/publish/maven/internal/publication/DefaultMavenPublicationTest.groovy +++ b/subprojects/maven/src/test/groovy/org/gradle/api/publish/maven/internal/publication/DefaultMavenPublicationTest.groovy @@ -24,12 +24,12 @@ import org.gradle.api.artifacts.ModuleDependency import org.gradle.api.artifacts.ModuleVersionIdentifier import org.gradle.api.artifacts.ProjectDependency import org.gradle.api.artifacts.PublishArtifact +import org.gradle.api.attributes.Category import org.gradle.api.component.ComponentWithVariants import org.gradle.api.file.FileCollection import org.gradle.api.internal.CollectionCallbackActionDecorator import org.gradle.api.internal.FeaturePreviews import org.gradle.api.internal.artifacts.DefaultModuleVersionIdentifier -import org.gradle.api.internal.artifacts.dsl.dependencies.PlatformSupport import org.gradle.api.internal.artifacts.ivyservice.projectmodule.ProjectDependencyPublicationResolver import org.gradle.api.internal.attributes.ImmutableAttributes import org.gradle.api.internal.component.SoftwareComponentInternal @@ -532,6 +532,6 @@ class DefaultMavenPublicationTest extends Specification { } def platformAttribute() { - return AttributeTestUtil.attributes([(PlatformSupport.VARIANT_CATEGORY.name) : PlatformSupport.REGULAR_PLATFORM]) + return AttributeTestUtil.attributesFactory().of(Category.CATEGORY_ATTRIBUTE, TestUtil.objectFactory().named(Category, Category.REGULAR_PLATFORM)) } } diff --git a/subprojects/maven/src/testFixtures/groovy/org/gradle/integtests/fixtures/publish/maven/AbstractMavenPublishIntegTest.groovy b/subprojects/maven/src/testFixtures/groovy/org/gradle/integtests/fixtures/publish/maven/AbstractMavenPublishIntegTest.groovy index 6c1342bd253ad..f3b3389ced2b5 100644 --- a/subprojects/maven/src/testFixtures/groovy/org/gradle/integtests/fixtures/publish/maven/AbstractMavenPublishIntegTest.groovy +++ b/subprojects/maven/src/testFixtures/groovy/org/gradle/integtests/fixtures/publish/maven/AbstractMavenPublishIntegTest.groovy @@ -132,7 +132,7 @@ abstract class AbstractMavenPublishIntegTest extends AbstractIntegrationSpec imp dependencies { attributesSchema { - getMatchingStrategy(PlatformSupport.VARIANT_CATEGORY) + getMatchingStrategy(Category.CATEGORY_ATTRIBUTE) .disambiguationRules .add(PlatformSupport.PreferRegularPlatform) } diff --git a/subprojects/plugins/src/integTest/groovy/org/gradle/java/JavaApplicationOutgoingVariantsIntegrationTest.groovy b/subprojects/plugins/src/integTest/groovy/org/gradle/java/JavaApplicationOutgoingVariantsIntegrationTest.groovy index 0ed5fdd931ef3..3a7a7467ea407 100644 --- a/subprojects/plugins/src/integTest/groovy/org/gradle/java/JavaApplicationOutgoingVariantsIntegrationTest.groovy +++ b/subprojects/plugins/src/integTest/groovy/org/gradle/java/JavaApplicationOutgoingVariantsIntegrationTest.groovy @@ -79,8 +79,8 @@ project(':consumer') { outputContains("files: [java.jar, file-dep.jar, compile-1.0.jar, other-java.jar, implementation-1.0.jar, runtime-1.0.jar, runtime-only-1.0.jar]") outputContains("file-dep.jar {artifactType=jar}") outputContains("compile.jar (test:compile:1.0) {artifactType=jar}") - outputContains("other-java.jar (project :other-java) {artifactType=jar, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-jars}") - outputContains("java.jar (project :java) {artifactType=jar, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-jars}") + outputContains("other-java.jar (project :other-java) {artifactType=jar, org.gradle.category=library, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-jars}") + outputContains("java.jar (project :java) {artifactType=jar, org.gradle.category=library, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-jars}") when: buildFile << """ @@ -97,8 +97,8 @@ project(':consumer') { outputContains("files: [java.jar, file-dep.jar, compile-1.0.jar, other-java.jar, implementation-1.0.jar, runtime-1.0.jar, runtime-only-1.0.jar]") outputContains("file-dep.jar {artifactType=jar, org.gradle.usage=java-runtime-jars}") outputContains("compile.jar (test:compile:1.0) {artifactType=jar, org.gradle.usage=java-runtime-jars}") - outputContains("other-java.jar (project :other-java) {artifactType=jar, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-jars}") - outputContains("java.jar (project :java) {artifactType=jar, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-jars}") + outputContains("other-java.jar (project :other-java) {artifactType=jar, org.gradle.category=library, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-jars}") + outputContains("java.jar (project :java) {artifactType=jar, org.gradle.category=library, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-jars}") } @Unroll @@ -118,8 +118,8 @@ project(':consumer') { outputContains("files: [java.jar, file-dep.jar, compile-1.0.jar, main, runtime-1.0.jar]") outputContains("file-dep.jar {artifactType=jar}") outputContains("compile.jar (test:compile:1.0) {artifactType=jar}") - outputContains("main (project :other-java) {artifactType=java-classes-directory, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-api-classes}") - outputContains("java.jar (project :java) {artifactType=jar, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-api-jars}") + outputContains("main (project :other-java) {artifactType=java-classes-directory, org.gradle.category=library, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-api-classes}") + outputContains("java.jar (project :java) {artifactType=jar, org.gradle.category=library, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-api-jars}") when: buildFile << """ @@ -136,8 +136,8 @@ project(':consumer') { outputContains("files: [java.jar, file-dep.jar, compile-1.0.jar, main, runtime-1.0.jar]") outputContains("file-dep.jar {artifactType=jar, org.gradle.usage=java-runtime-jars}") outputContains("compile.jar (test:compile:1.0) {artifactType=jar, org.gradle.usage=java-runtime-jars}") - outputContains("main (project :other-java) {artifactType=java-classes-directory, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-api-classes}") - outputContains("java.jar (project :java) {artifactType=jar, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-api-jars}") + outputContains("main (project :other-java) {artifactType=java-classes-directory, org.gradle.category=library, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-api-classes}") + outputContains("java.jar (project :java) {artifactType=jar, org.gradle.category=library, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-api-jars}") where: usage | _ @@ -161,8 +161,8 @@ project(':consumer') { outputContains("files: [java.jar, file-dep.jar, compile-1.0.jar, other-java.jar, implementation-1.0.jar, runtime-1.0.jar, runtime-only-1.0.jar]") outputContains("file-dep.jar {artifactType=jar}") outputContains("compile.jar (test:compile:1.0) {artifactType=jar}") - outputContains("other-java.jar (project :other-java) {artifactType=jar, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-jars}") - outputContains("java.jar (project :java) {artifactType=jar, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-jars}") + outputContains("other-java.jar (project :other-java) {artifactType=jar, org.gradle.category=library, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-jars}") + outputContains("java.jar (project :java) {artifactType=jar, org.gradle.category=library, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-jars}") when: buildFile << """ @@ -179,8 +179,8 @@ project(':consumer') { outputContains("files: [java.jar, file-dep.jar, compile-1.0.jar, other-java.jar, implementation-1.0.jar, runtime-1.0.jar, runtime-only-1.0.jar]") outputContains("file-dep.jar {artifactType=jar, org.gradle.usage=java-runtime-jars}") outputContains("compile.jar (test:compile:1.0) {artifactType=jar, org.gradle.usage=java-runtime-jars}") - outputContains("other-java.jar (project :other-java) {artifactType=jar, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-jars}") - outputContains("java.jar (project :java) {artifactType=jar, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-jars}") + outputContains("other-java.jar (project :other-java) {artifactType=jar, org.gradle.category=library, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-jars}") + outputContains("java.jar (project :java) {artifactType=jar, org.gradle.category=library, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-jars}") where: usage | _ @@ -202,8 +202,8 @@ project(':consumer') { result.assertTasksExecuted(":other-java:compileJava", ":other-java:processResources", ":other-java:classes", ":other-java:jar", ":java:compileJava", ":java:processResources", ":java:classes", ":java:jar", ":consumer:resolve") outputContains("files: [java.jar, file-dep.jar, compile-1.0.jar, other-java.jar, implementation-1.0.jar, runtime-1.0.jar, runtime-only-1.0.jar]") outputContains("file-dep.jar {artifactType=jar}") - outputContains("other-java.jar (project :other-java) {artifactType=jar, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-jars}") - outputContains("java.jar (project :java) {artifactType=jar, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-jars}") + outputContains("other-java.jar (project :other-java) {artifactType=jar, org.gradle.category=library, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-jars}") + outputContains("java.jar (project :java) {artifactType=jar, org.gradle.category=library, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-jars}") } def "provides runtime classes variant"() { @@ -222,8 +222,8 @@ project(':consumer') { outputContains("files: [main, file-dep.jar, compile-1.0.jar, main, implementation-1.0.jar, runtime-1.0.jar, runtime-only-1.0.jar]") outputContains("file-dep.jar {artifactType=jar}") outputContains("compile.jar (test:compile:1.0) {artifactType=jar}") - outputContains("main (project :other-java) {artifactType=java-classes-directory, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-classes}") - outputContains("main (project :java) {artifactType=java-classes-directory, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-classes}") + outputContains("main (project :other-java) {artifactType=java-classes-directory, org.gradle.category=library, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-classes}") + outputContains("main (project :java) {artifactType=java-classes-directory, org.gradle.category=library, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-classes}") when: buildFile << """ @@ -240,8 +240,8 @@ project(':consumer') { outputContains("files: [main, file-dep.jar, compile-1.0.jar, main, implementation-1.0.jar, runtime-1.0.jar, runtime-only-1.0.jar]") outputContains("file-dep.jar {artifactType=jar, org.gradle.usage=java-runtime-jars}") outputContains("compile.jar (test:compile:1.0) {artifactType=jar, org.gradle.usage=java-runtime-jars}") - outputContains("main (project :other-java) {artifactType=java-classes-directory, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-classes}") - outputContains("main (project :java) {artifactType=java-classes-directory, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-classes}") + outputContains("main (project :other-java) {artifactType=java-classes-directory, org.gradle.category=library, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-classes}") + outputContains("main (project :java) {artifactType=java-classes-directory, org.gradle.category=library, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-classes}") } def "provides runtime resources variant"() { @@ -260,8 +260,8 @@ project(':consumer') { outputContains("files: [main, file-dep.jar, compile-1.0.jar, main, implementation-1.0.jar, runtime-1.0.jar, runtime-only-1.0.jar]") outputContains("file-dep.jar {artifactType=jar}") outputContains("compile.jar (test:compile:1.0) {artifactType=jar}") - outputContains("main (project :other-java) {artifactType=java-resources-directory, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-resources}") - outputContains("main (project :java) {artifactType=java-resources-directory, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-resources}") + outputContains("main (project :other-java) {artifactType=java-resources-directory, org.gradle.category=library, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-resources}") + outputContains("main (project :java) {artifactType=java-resources-directory, org.gradle.category=library, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-resources}") when: buildFile << """ @@ -278,8 +278,8 @@ project(':consumer') { outputContains("files: [main, file-dep.jar, compile-1.0.jar, main, implementation-1.0.jar, runtime-1.0.jar, runtime-only-1.0.jar]") outputContains("file-dep.jar {artifactType=jar, org.gradle.usage=java-runtime-jars}") outputContains("compile.jar (test:compile:1.0) {artifactType=jar, org.gradle.usage=java-runtime-jars}") - outputContains("main (project :other-java) {artifactType=java-resources-directory, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-resources}") - outputContains("main (project :java) {artifactType=java-resources-directory, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-resources}") + outputContains("main (project :other-java) {artifactType=java-resources-directory, org.gradle.category=library, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-resources}") + outputContains("main (project :java) {artifactType=java-resources-directory, org.gradle.category=library, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-resources}") } static String defaultTargetPlatform() { diff --git a/subprojects/plugins/src/integTest/groovy/org/gradle/java/JavaLibraryCrossProjectTargetJvmVersionIntegrationTest.groovy b/subprojects/plugins/src/integTest/groovy/org/gradle/java/JavaLibraryCrossProjectTargetJvmVersionIntegrationTest.groovy index d15ba6e8bb268..d7914f42f06a1 100644 --- a/subprojects/plugins/src/integTest/groovy/org/gradle/java/JavaLibraryCrossProjectTargetJvmVersionIntegrationTest.groovy +++ b/subprojects/plugins/src/integTest/groovy/org/gradle/java/JavaLibraryCrossProjectTargetJvmVersionIntegrationTest.groovy @@ -58,10 +58,12 @@ class JavaLibraryCrossProjectTargetJvmVersionIntegrationTest extends AbstractInt then: failure.assertHasCause('''Unable to find a matching variant of project :producer: - Variant 'apiElements' capability test:producer:unspecified: + - Found org.gradle.category 'library' but wasn't required. - Required org.gradle.dependency.bundling 'external' and found compatible value 'external'. - Required org.gradle.jvm.version '6' and found incompatible value '7'. - Required org.gradle.usage 'java-api' and found compatible value 'java-api-jars'. - Variant 'runtimeElements' capability test:producer:unspecified: + - Found org.gradle.category 'library' but wasn't required. - Required org.gradle.dependency.bundling 'external' and found compatible value 'external'. - Required org.gradle.jvm.version '6' and found incompatible value '7'. - Required org.gradle.usage 'java-api' and found compatible value 'java-runtime-jars'.''') @@ -141,10 +143,12 @@ class JavaLibraryCrossProjectTargetJvmVersionIntegrationTest extends AbstractInt then: failure.assertHasCause("""Unable to find a matching variant of project :producer: - Variant 'apiElements' capability test:producer:unspecified: + - Found org.gradle.category 'library' but wasn't required. - Required org.gradle.dependency.bundling 'external' and found compatible value 'external'. - Required org.gradle.jvm.version '6' and found incompatible value '7'. - Required org.gradle.usage 'java-api' and found compatible value 'java-api-jars'. - Variant 'runtimeElements' capability test:producer:unspecified: + - Found org.gradle.category 'library' but wasn't required. - Required org.gradle.dependency.bundling 'external' and found compatible value 'external'. - Required org.gradle.jvm.version '6' and found incompatible value '7'. - Required org.gradle.usage 'java-api' and found compatible value 'java-runtime-jars'.""") @@ -162,6 +166,7 @@ class JavaLibraryCrossProjectTargetJvmVersionIntegrationTest extends AbstractInt root(":", ":test:") { project(':producer', 'test:producer:') { variant("apiElements", [ + 'org.gradle.category': 'library', 'org.gradle.dependency.bundling': 'external', 'org.gradle.jvm.version': '7', 'org.gradle.usage':'java-api-jars' diff --git a/subprojects/plugins/src/integTest/groovy/org/gradle/java/JavaLibraryOutgoingVariantsIntegrationTest.groovy b/subprojects/plugins/src/integTest/groovy/org/gradle/java/JavaLibraryOutgoingVariantsIntegrationTest.groovy index 4d4ae775feb2b..d6e6504f7b838 100644 --- a/subprojects/plugins/src/integTest/groovy/org/gradle/java/JavaLibraryOutgoingVariantsIntegrationTest.groovy +++ b/subprojects/plugins/src/integTest/groovy/org/gradle/java/JavaLibraryOutgoingVariantsIntegrationTest.groovy @@ -81,8 +81,8 @@ project(':consumer') { outputContains("files: [java.jar, file-dep.jar, api-1.0.jar, compile-1.0.jar, other-java.jar, implementation-1.0.jar, runtime-1.0.jar, runtime-only-1.0.jar]") outputContains("file-dep.jar {artifactType=jar}") outputContains("compile.jar (test:compile:1.0) {artifactType=jar}") - outputContains("other-java.jar (project :other-java) {artifactType=jar, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-jars}") - outputContains("java.jar (project :java) {artifactType=jar, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-jars}") + outputContains("other-java.jar (project :other-java) {artifactType=jar, org.gradle.category=library, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-jars}") + outputContains("java.jar (project :java) {artifactType=jar, org.gradle.category=library, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-jars}") when: buildFile << """ @@ -99,8 +99,8 @@ project(':consumer') { outputContains("files: [java.jar, file-dep.jar, api-1.0.jar, compile-1.0.jar, other-java.jar, implementation-1.0.jar, runtime-1.0.jar, runtime-only-1.0.jar]") outputContains("file-dep.jar {artifactType=jar, org.gradle.usage=java-runtime-jars}") outputContains("compile.jar (test:compile:1.0) {artifactType=jar, org.gradle.usage=java-runtime-jars}") - outputContains("other-java.jar (project :other-java) {artifactType=jar, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-jars}") - outputContains("java.jar (project :java) {artifactType=jar, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-jars}") + outputContains("other-java.jar (project :other-java) {artifactType=jar, org.gradle.category=library, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-jars}") + outputContains("java.jar (project :java) {artifactType=jar, org.gradle.category=library, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-jars}") } @Unroll @@ -119,8 +119,8 @@ project(':consumer') { outputContains("files: [main, file-dep.jar, api-1.0.jar, compile-1.0.jar, main, runtime-1.0.jar]") outputContains("file-dep.jar {artifactType=jar}") outputContains("compile.jar (test:compile:1.0) {artifactType=jar}") - outputContains("main (project :other-java) {artifactType=java-classes-directory, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-api-classes}") - outputContains("main (project :java) {artifactType=java-classes-directory, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-api-classes}") + outputContains("main (project :other-java) {artifactType=java-classes-directory, org.gradle.category=library, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-api-classes}") + outputContains("main (project :java) {artifactType=java-classes-directory, org.gradle.category=library, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-api-classes}") when: buildFile << """ @@ -137,8 +137,8 @@ project(':consumer') { outputContains("files: [main, file-dep.jar, api-1.0.jar, compile-1.0.jar, main, runtime-1.0.jar]") outputContains("file-dep.jar {artifactType=jar, org.gradle.usage=java-runtime-jars}") outputContains("compile.jar (test:compile:1.0) {artifactType=jar, org.gradle.usage=java-runtime-jars}") - outputContains("main (project :other-java) {artifactType=java-classes-directory, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-api-classes}") - outputContains("main (project :java) {artifactType=java-classes-directory, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-api-classes}") + outputContains("main (project :other-java) {artifactType=java-classes-directory, org.gradle.category=library, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-api-classes}") + outputContains("main (project :java) {artifactType=java-classes-directory, org.gradle.category=library, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-api-classes}") where: usage | _ @@ -162,8 +162,8 @@ project(':consumer') { outputContains("files: [java.jar, file-dep.jar, api-1.0.jar, compile-1.0.jar, other-java.jar, implementation-1.0.jar, runtime-1.0.jar, runtime-only-1.0.jar]") outputContains("file-dep.jar {artifactType=jar}") outputContains("compile.jar (test:compile:1.0) {artifactType=jar}") - outputContains("java.jar (project :java) {artifactType=jar, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-jars}") - outputContains("other-java.jar (project :other-java) {artifactType=jar, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-jars}") + outputContains("java.jar (project :java) {artifactType=jar, org.gradle.category=library, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-jars}") + outputContains("other-java.jar (project :other-java) {artifactType=jar, org.gradle.category=library, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-jars}") when: buildFile << """ @@ -180,8 +180,8 @@ project(':consumer') { outputContains("files: [java.jar, file-dep.jar, api-1.0.jar, compile-1.0.jar, other-java.jar, implementation-1.0.jar, runtime-1.0.jar, runtime-only-1.0.jar]") outputContains("file-dep.jar {artifactType=jar, org.gradle.usage=java-runtime-jars}") outputContains("compile.jar (test:compile:1.0) {artifactType=jar, org.gradle.usage=java-runtime-jars}") - outputContains("java.jar (project :java) {artifactType=jar, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-jars}") - outputContains("other-java.jar (project :other-java) {artifactType=jar, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-jars}") + outputContains("java.jar (project :java) {artifactType=jar, org.gradle.category=library, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-jars}") + outputContains("other-java.jar (project :other-java) {artifactType=jar, org.gradle.category=library, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-jars}") where: usage | _ @@ -203,8 +203,8 @@ project(':consumer') { result.assertTasksExecuted(":other-java:compileJava", ":other-java:processResources", ":other-java:classes", ":other-java:jar", ":java:compileJava", ":java:processResources", ":java:classes", ":java:jar", ":consumer:resolve") outputContains("files: [java.jar, file-dep.jar, api-1.0.jar, compile-1.0.jar, other-java.jar, implementation-1.0.jar, runtime-1.0.jar, runtime-only-1.0.jar]") outputContains("file-dep.jar {artifactType=jar}") - outputContains("java.jar (project :java) {artifactType=jar, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-jars}") - outputContains("other-java.jar (project :other-java) {artifactType=jar, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-jars}") + outputContains("java.jar (project :java) {artifactType=jar, org.gradle.category=library, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-jars}") + outputContains("other-java.jar (project :other-java) {artifactType=jar, org.gradle.category=library, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-jars}") } def "provides runtime classes variant"() { @@ -223,8 +223,8 @@ project(':consumer') { outputContains("files: [main, file-dep.jar, api-1.0.jar, compile-1.0.jar, main, implementation-1.0.jar, runtime-1.0.jar, runtime-only-1.0.jar]") outputContains("file-dep.jar {artifactType=jar}") outputContains("compile.jar (test:compile:1.0) {artifactType=jar}") - outputContains("main (project :other-java) {artifactType=java-classes-directory, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-classes}") - outputContains("main (project :java) {artifactType=java-classes-directory, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-classes}") + outputContains("main (project :other-java) {artifactType=java-classes-directory, org.gradle.category=library, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-classes}") + outputContains("main (project :java) {artifactType=java-classes-directory, org.gradle.category=library, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-classes}") when: buildFile << """ @@ -241,8 +241,8 @@ project(':consumer') { outputContains("files: [main, file-dep.jar, api-1.0.jar, compile-1.0.jar, main, implementation-1.0.jar, runtime-1.0.jar, runtime-only-1.0.jar]") outputContains("file-dep.jar {artifactType=jar, org.gradle.usage=java-runtime-jars}") outputContains("compile.jar (test:compile:1.0) {artifactType=jar, org.gradle.usage=java-runtime-jars}") - outputContains("main (project :other-java) {artifactType=java-classes-directory, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-classes}") - outputContains("main (project :java) {artifactType=java-classes-directory, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-classes}") + outputContains("main (project :other-java) {artifactType=java-classes-directory, org.gradle.category=library, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-classes}") + outputContains("main (project :java) {artifactType=java-classes-directory, org.gradle.category=library, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-classes}") } def "provides runtime resources variant"() { @@ -261,8 +261,8 @@ project(':consumer') { outputContains("files: [main, file-dep.jar, api-1.0.jar, compile-1.0.jar, main, implementation-1.0.jar, runtime-1.0.jar, runtime-only-1.0.jar]") outputContains("file-dep.jar {artifactType=jar}") outputContains("compile.jar (test:compile:1.0) {artifactType=jar}") - outputContains("main (project :other-java) {artifactType=java-resources-directory, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-resources}") - outputContains("main (project :java) {artifactType=java-resources-directory, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-resources}") + outputContains("main (project :other-java) {artifactType=java-resources-directory, org.gradle.category=library, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-resources}") + outputContains("main (project :java) {artifactType=java-resources-directory, org.gradle.category=library, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-resources}") when: buildFile << """ @@ -279,8 +279,8 @@ project(':consumer') { outputContains("files: [main, file-dep.jar, api-1.0.jar, compile-1.0.jar, main, implementation-1.0.jar, runtime-1.0.jar, runtime-only-1.0.jar]") outputContains("file-dep.jar {artifactType=jar, org.gradle.usage=java-runtime-jars}") outputContains("compile.jar (test:compile:1.0) {artifactType=jar, org.gradle.usage=java-runtime-jars}") - outputContains("main (project :other-java) {artifactType=java-resources-directory, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-resources}") - outputContains("main (project :java) {artifactType=java-resources-directory, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-resources}") + outputContains("main (project :other-java) {artifactType=java-resources-directory, org.gradle.category=library, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-resources}") + outputContains("main (project :java) {artifactType=java-resources-directory, org.gradle.category=library, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-resources}") } static String defaultTargetPlatform() { diff --git a/subprojects/plugins/src/integTest/groovy/org/gradle/java/JavaProjectOutgoingVariantsIntegrationTest.groovy b/subprojects/plugins/src/integTest/groovy/org/gradle/java/JavaProjectOutgoingVariantsIntegrationTest.groovy index 931a6592bd547..a7edbd6d46485 100644 --- a/subprojects/plugins/src/integTest/groovy/org/gradle/java/JavaProjectOutgoingVariantsIntegrationTest.groovy +++ b/subprojects/plugins/src/integTest/groovy/org/gradle/java/JavaProjectOutgoingVariantsIntegrationTest.groovy @@ -79,8 +79,8 @@ project(':consumer') { outputContains("files: [java.jar, file-dep.jar, compile-1.0.jar, other-java.jar, implementation-1.0.jar, runtime-1.0.jar, runtime-only-1.0.jar]") outputContains("file-dep.jar {artifactType=jar}") outputContains("compile.jar (test:compile:1.0) {artifactType=jar}") - outputContains("other-java.jar (project :other-java) {artifactType=jar, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-jars}") - outputContains("java.jar (project :java) {artifactType=jar, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-jars}") + outputContains("other-java.jar (project :other-java) {artifactType=jar, org.gradle.category=library, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-jars}") + outputContains("java.jar (project :java) {artifactType=jar, org.gradle.category=library, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-jars}") when: buildFile << """ @@ -97,8 +97,8 @@ project(':consumer') { outputContains("files: [java.jar, file-dep.jar, compile-1.0.jar, other-java.jar, implementation-1.0.jar, runtime-1.0.jar, runtime-only-1.0.jar]") outputContains("file-dep.jar {artifactType=jar, org.gradle.usage=java-runtime-jars}") outputContains("compile.jar (test:compile:1.0) {artifactType=jar, org.gradle.usage=java-runtime-jars}") - outputContains("other-java.jar (project :other-java) {artifactType=jar, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-jars}") - outputContains("java.jar (project :java) {artifactType=jar, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-jars}") + outputContains("other-java.jar (project :other-java) {artifactType=jar, org.gradle.category=library, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-jars}") + outputContains("java.jar (project :java) {artifactType=jar, org.gradle.category=library, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-jars}") } @Unroll @@ -117,8 +117,8 @@ project(':consumer') { outputContains("files: [java.jar, file-dep.jar, compile-1.0.jar, other-java.jar, runtime-1.0.jar]") outputContains("file-dep.jar {artifactType=jar}") outputContains("compile.jar (test:compile:1.0) {artifactType=jar}") - outputContains("other-java.jar (project :other-java) {artifactType=jar, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-api-jars}") - outputContains("java.jar (project :java) {artifactType=jar, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-api-jars}") + outputContains("other-java.jar (project :other-java) {artifactType=jar, org.gradle.category=library, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-api-jars}") + outputContains("java.jar (project :java) {artifactType=jar, org.gradle.category=library, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-api-jars}") when: buildFile << """ @@ -135,8 +135,8 @@ project(':consumer') { outputContains("files: [java.jar, file-dep.jar, compile-1.0.jar, other-java.jar, runtime-1.0.jar]") outputContains("file-dep.jar {artifactType=jar, org.gradle.usage=java-runtime-jars}") outputContains("compile.jar (test:compile:1.0) {artifactType=jar, org.gradle.usage=java-runtime-jars}") - outputContains("other-java.jar (project :other-java) {artifactType=jar, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-api-jars}") - outputContains("java.jar (project :java) {artifactType=jar, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-api-jars}") + outputContains("other-java.jar (project :other-java) {artifactType=jar, org.gradle.category=library, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-api-jars}") + outputContains("java.jar (project :java) {artifactType=jar, org.gradle.category=library, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-api-jars}") where: usage | _ @@ -161,8 +161,8 @@ project(':consumer') { outputContains("files: [java.jar, file-dep.jar, compile-1.0.jar, other-java.jar, implementation-1.0.jar, runtime-1.0.jar, runtime-only-1.0.jar]") outputContains("file-dep.jar {artifactType=jar}") outputContains("compile.jar (test:compile:1.0) {artifactType=jar}") - outputContains("other-java.jar (project :other-java) {artifactType=jar, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-jars}") - outputContains("java.jar (project :java) {artifactType=jar, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-jars}") + outputContains("other-java.jar (project :other-java) {artifactType=jar, org.gradle.category=library, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-jars}") + outputContains("java.jar (project :java) {artifactType=jar, org.gradle.category=library, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-jars}") when: buildFile << """ @@ -179,8 +179,8 @@ project(':consumer') { outputContains("files: [java.jar, file-dep.jar, compile-1.0.jar, other-java.jar, implementation-1.0.jar, runtime-1.0.jar, runtime-only-1.0.jar]") outputContains("file-dep.jar {artifactType=jar, org.gradle.usage=java-runtime-jars}") outputContains("compile.jar (test:compile:1.0) {artifactType=jar, org.gradle.usage=java-runtime-jars}") - outputContains("other-java.jar (project :other-java) {artifactType=jar, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-jars}") - outputContains("java.jar (project :java) {artifactType=jar, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-jars}") + outputContains("other-java.jar (project :other-java) {artifactType=jar, org.gradle.category=library, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-jars}") + outputContains("java.jar (project :java) {artifactType=jar, org.gradle.category=library, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-jars}") where: usage | _ @@ -202,8 +202,8 @@ project(':consumer') { result.assertTasksExecuted(":other-java:compileJava", ":other-java:processResources", ":other-java:classes", ":other-java:jar", ":java:compileJava", ":java:processResources", ":java:classes", ":java:jar", ":consumer:resolve") outputContains("files: [java.jar, file-dep.jar, compile-1.0.jar, other-java.jar, implementation-1.0.jar, runtime-1.0.jar, runtime-only-1.0.jar]") outputContains("file-dep.jar {artifactType=jar}") - outputContains("other-java.jar (project :other-java) {artifactType=jar, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-jars}") - outputContains("java.jar (project :java) {artifactType=jar, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-jars}") + outputContains("other-java.jar (project :other-java) {artifactType=jar, org.gradle.category=library, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-jars}") + outputContains("java.jar (project :java) {artifactType=jar, org.gradle.category=library, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-jars}") } def "provides runtime classes variant"() { @@ -221,8 +221,8 @@ project(':consumer') { outputContains("files: [main, file-dep.jar, compile-1.0.jar, main, implementation-1.0.jar, runtime-1.0.jar, runtime-only-1.0.jar]") outputContains("file-dep.jar {artifactType=jar}") outputContains("compile.jar (test:compile:1.0) {artifactType=jar}") - outputContains("main (project :other-java) {artifactType=java-classes-directory, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-classes}") - outputContains("main (project :java) {artifactType=java-classes-directory, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-classes}") + outputContains("main (project :other-java) {artifactType=java-classes-directory, org.gradle.category=library, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-classes}") + outputContains("main (project :java) {artifactType=java-classes-directory, org.gradle.category=library, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-classes}") when: buildFile << """ @@ -239,8 +239,8 @@ project(':consumer') { outputContains("files: [main, file-dep.jar, compile-1.0.jar, main, implementation-1.0.jar, runtime-1.0.jar, runtime-only-1.0.jar]") outputContains("file-dep.jar {artifactType=jar, org.gradle.usage=java-runtime-jars}") outputContains("compile.jar (test:compile:1.0) {artifactType=jar, org.gradle.usage=java-runtime-jars}") - outputContains("main (project :other-java) {artifactType=java-classes-directory, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-classes}") - outputContains("main (project :java) {artifactType=java-classes-directory, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-classes}") + outputContains("main (project :other-java) {artifactType=java-classes-directory, org.gradle.category=library, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-classes}") + outputContains("main (project :java) {artifactType=java-classes-directory, org.gradle.category=library, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-classes}") } def "provides runtime resources variant"() { @@ -259,8 +259,8 @@ project(':consumer') { outputContains("files: [main, file-dep.jar, compile-1.0.jar, main, implementation-1.0.jar, runtime-1.0.jar, runtime-only-1.0.jar]") outputContains("file-dep.jar {artifactType=jar}") outputContains("compile.jar (test:compile:1.0) {artifactType=jar}") - outputContains("main (project :other-java) {artifactType=java-resources-directory, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-resources}") - outputContains("main (project :java) {artifactType=java-resources-directory, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-resources}") + outputContains("main (project :other-java) {artifactType=java-resources-directory, org.gradle.category=library, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-resources}") + outputContains("main (project :java) {artifactType=java-resources-directory, org.gradle.category=library, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-resources}") when: buildFile << """ @@ -277,8 +277,8 @@ project(':consumer') { outputContains("files: [main, file-dep.jar, compile-1.0.jar, main, implementation-1.0.jar, runtime-1.0.jar, runtime-only-1.0.jar]") outputContains("file-dep.jar {artifactType=jar, org.gradle.usage=java-runtime-jars}") outputContains("compile.jar (test:compile:1.0) {artifactType=jar, org.gradle.usage=java-runtime-jars}") - outputContains("main (project :other-java) {artifactType=java-resources-directory, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-resources}") - outputContains("main (project :java) {artifactType=java-resources-directory, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-resources}") + outputContains("main (project :other-java) {artifactType=java-resources-directory, org.gradle.category=library, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-resources}") + outputContains("main (project :java) {artifactType=java-resources-directory, org.gradle.category=library, org.gradle.dependency.bundling=external, ${defaultTargetPlatform()}, org.gradle.usage=java-runtime-resources}") } static String defaultTargetPlatform() { diff --git a/subprojects/plugins/src/main/java/org/gradle/api/plugins/JavaPlatformPlugin.java b/subprojects/plugins/src/main/java/org/gradle/api/plugins/JavaPlatformPlugin.java index bc0e75ed3f8c8..c435e14657e03 100644 --- a/subprojects/plugins/src/main/java/org/gradle/api/plugins/JavaPlatformPlugin.java +++ b/subprojects/plugins/src/main/java/org/gradle/api/plugins/JavaPlatformPlugin.java @@ -23,12 +23,14 @@ import org.gradle.api.Project; import org.gradle.api.artifacts.Configuration; import org.gradle.api.artifacts.ConfigurationContainer; +import org.gradle.api.attributes.Category; import org.gradle.api.attributes.Usage; import org.gradle.api.component.AdhocComponentWithVariants; import org.gradle.api.component.SoftwareComponentFactory; import org.gradle.api.internal.artifacts.JavaEcosystemSupport; import org.gradle.api.internal.artifacts.dsl.dependencies.PlatformSupport; import org.gradle.api.internal.java.DefaultJavaPlatformExtension; +import org.gradle.api.model.ObjectFactory; import org.gradle.api.plugins.internal.JavaConfigurationVariantMapping; import javax.inject.Inject; @@ -110,7 +112,7 @@ public void apply(Project project) { private void addPlatformDisambiguationRule(Project project) { project.getDependencies() .getAttributesSchema() - .getMatchingStrategy(PlatformSupport.VARIANT_CATEGORY) + .getMatchingStrategy(Category.CATEGORY_ATTRIBUTE) .getDisambiguationRules() .add(PlatformSupport.PreferRegularPlatform.class); } @@ -125,18 +127,18 @@ private void createSoftwareComponent(Project project, Configuration apiElements, private void createConfigurations(Project project) { ConfigurationContainer configurations = project.getConfigurations(); Configuration api = configurations.create(API_CONFIGURATION_NAME, AS_BUCKET); - Configuration apiElements = createConsumableApi(project, configurations, api, API_ELEMENTS_CONFIGURATION_NAME, PlatformSupport.REGULAR_PLATFORM); - Configuration enforcedApiElements = createConsumableApi(project, configurations, api, ENFORCED_API_ELEMENTS_CONFIGURATION_NAME, PlatformSupport.ENFORCED_PLATFORM); + Configuration apiElements = createConsumableApi(project, configurations, api, API_ELEMENTS_CONFIGURATION_NAME, Category.REGULAR_PLATFORM); + Configuration enforcedApiElements = createConsumableApi(project, configurations, api, ENFORCED_API_ELEMENTS_CONFIGURATION_NAME, Category.ENFORCED_PLATFORM); Configuration runtime = project.getConfigurations().create(RUNTIME_CONFIGURATION_NAME, AS_BUCKET); runtime.extendsFrom(api); - Configuration runtimeElements = createConsumableRuntime(project, runtime, RUNTIME_ELEMENTS_CONFIGURATION_NAME, PlatformSupport.REGULAR_PLATFORM); - Configuration enforcedRuntimeElements = createConsumableRuntime(project, runtime, ENFORCED_RUNTIME_ELEMENTS_CONFIGURATION_NAME, PlatformSupport.ENFORCED_PLATFORM); + Configuration runtimeElements = createConsumableRuntime(project, runtime, RUNTIME_ELEMENTS_CONFIGURATION_NAME, Category.REGULAR_PLATFORM); + Configuration enforcedRuntimeElements = createConsumableRuntime(project, runtime, ENFORCED_RUNTIME_ELEMENTS_CONFIGURATION_NAME, Category.ENFORCED_PLATFORM); Configuration classpath = configurations.create(CLASSPATH_CONFIGURATION_NAME, AS_RESOLVABLE_CONFIGURATION); classpath.extendsFrom(runtimeElements); - declareConfigurationUsage(project, classpath, Usage.JAVA_RUNTIME); + declareConfigurationUsage(project.getObjects(), classpath, Usage.JAVA_RUNTIME); createSoftwareComponent(project, apiElements, runtimeElements); } @@ -144,25 +146,25 @@ private void createConfigurations(Project project) { private Configuration createConsumableRuntime(Project project, Configuration apiElements, String name, String platformKind) { Configuration runtimeElements = project.getConfigurations().create(name, AS_CONSUMABLE_CONFIGURATION); runtimeElements.extendsFrom(apiElements); - declareConfigurationUsage(project, runtimeElements, Usage.JAVA_RUNTIME); - declareConfigurationCategory(runtimeElements, platformKind); + declareConfigurationUsage(project.getObjects(), runtimeElements, Usage.JAVA_RUNTIME); + declareConfigurationCategory(project.getObjects(), runtimeElements, platformKind); return runtimeElements; } private Configuration createConsumableApi(Project project, ConfigurationContainer configurations, Configuration api, String name, String platformKind) { Configuration apiElements = configurations.create(name, AS_CONSUMABLE_CONFIGURATION); apiElements.extendsFrom(api); - declareConfigurationUsage(project, apiElements, Usage.JAVA_API); - declareConfigurationCategory(apiElements, platformKind); + declareConfigurationUsage(project.getObjects(), apiElements, Usage.JAVA_API); + declareConfigurationCategory(project.getObjects(), apiElements, platformKind); return apiElements; } - private void declareConfigurationCategory(Configuration configuration, String value) { - configuration.getAttributes().attribute(PlatformSupport.VARIANT_CATEGORY, value); + private void declareConfigurationCategory(ObjectFactory objectFactory, Configuration configuration, String value) { + configuration.getAttributes().attribute(Category.CATEGORY_ATTRIBUTE, objectFactory.named(Category.class, value)); } - private void declareConfigurationUsage(Project project, Configuration configuration, String usage) { - configuration.getAttributes().attribute(Usage.USAGE_ATTRIBUTE, project.getObjects().named(Usage.class, usage)); + private void declareConfigurationUsage(ObjectFactory objectFactory, Configuration configuration, String usage) { + configuration.getAttributes().attribute(Usage.USAGE_ATTRIBUTE, objectFactory.named(Usage.class, usage)); } private void configureExtension(Project project) { diff --git a/subprojects/plugins/src/main/java/org/gradle/api/plugins/JavaPlugin.java b/subprojects/plugins/src/main/java/org/gradle/api/plugins/JavaPlugin.java index 27ba7088e8a1a..cb0c79ebc383d 100644 --- a/subprojects/plugins/src/main/java/org/gradle/api/plugins/JavaPlugin.java +++ b/subprojects/plugins/src/main/java/org/gradle/api/plugins/JavaPlugin.java @@ -29,6 +29,7 @@ import org.gradle.api.artifacts.Dependency; import org.gradle.api.artifacts.PublishArtifact; import org.gradle.api.artifacts.type.ArtifactTypeDefinition; +import org.gradle.api.attributes.Category; import org.gradle.api.attributes.Usage; import org.gradle.api.attributes.Bundling; import org.gradle.api.component.AdhocComponentWithVariants; @@ -66,6 +67,7 @@ import static org.gradle.api.attributes.Usage.USAGE_ATTRIBUTE; import static org.gradle.api.attributes.Bundling.EXTERNAL; import static org.gradle.api.attributes.Bundling.BUNDLING_ATTRIBUTE; +import static org.gradle.api.attributes.Category.CATEGORY_ATTRIBUTE; /** *

    A {@link Plugin} which compiles and tests Java source, and assembles it into a JAR file.

    @@ -459,6 +461,7 @@ private void configureConfigurations(Project project, final JavaPluginConvention apiElementsConfiguration.setCanBeConsumed(true); apiElementsConfiguration.getAttributes().attribute(USAGE_ATTRIBUTE, objectFactory.named(Usage.class, Usage.JAVA_API_JARS)); apiElementsConfiguration.getAttributes().attribute(BUNDLING_ATTRIBUTE, objectFactory.named(Bundling.class, EXTERNAL)); + apiElementsConfiguration.getAttributes().attribute(CATEGORY_ATTRIBUTE, objectFactory.named(Category.class, Category.LIBRARY)); apiElementsConfiguration.extendsFrom(runtimeConfiguration); final Configuration runtimeElementsConfiguration = configurations.maybeCreate(RUNTIME_ELEMENTS_CONFIGURATION_NAME); @@ -468,6 +471,7 @@ private void configureConfigurations(Project project, final JavaPluginConvention runtimeElementsConfiguration.setDescription("Elements of runtime for main."); runtimeElementsConfiguration.getAttributes().attribute(USAGE_ATTRIBUTE, objectFactory.named(Usage.class, Usage.JAVA_RUNTIME_JARS)); runtimeElementsConfiguration.getAttributes().attribute(BUNDLING_ATTRIBUTE, objectFactory.named(Bundling.class, EXTERNAL)); + runtimeElementsConfiguration.getAttributes().attribute(CATEGORY_ATTRIBUTE, objectFactory.named(Category.class, Category.LIBRARY)); runtimeElementsConfiguration.extendsFrom(implementationConfiguration, runtimeOnlyConfiguration, runtimeConfiguration); defaultConfiguration.extendsFrom(runtimeElementsConfiguration); diff --git a/subprojects/plugins/src/main/java/org/gradle/api/plugins/internal/DefaultJavaFeatureSpec.java b/subprojects/plugins/src/main/java/org/gradle/api/plugins/internal/DefaultJavaFeatureSpec.java index e88a5c26fd627..dd84355e1ccf9 100644 --- a/subprojects/plugins/src/main/java/org/gradle/api/plugins/internal/DefaultJavaFeatureSpec.java +++ b/subprojects/plugins/src/main/java/org/gradle/api/plugins/internal/DefaultJavaFeatureSpec.java @@ -22,6 +22,7 @@ import org.gradle.api.artifacts.Configuration; import org.gradle.api.artifacts.ConfigurationContainer; import org.gradle.api.attributes.AttributeContainer; +import org.gradle.api.attributes.Category; import org.gradle.api.attributes.Usage; import org.gradle.api.attributes.Bundling; import org.gradle.api.attributes.java.TargetJvmVersion; @@ -51,6 +52,8 @@ import static org.gradle.api.attributes.Bundling.EXTERNAL; import static org.gradle.api.attributes.Bundling.BUNDLING_ATTRIBUTE; +import static org.gradle.api.attributes.Category.LIBRARY; +import static org.gradle.api.attributes.Category.CATEGORY_ATTRIBUTE; import static org.gradle.api.plugins.internal.JavaPluginsHelper.registerClassesDirVariant; public class DefaultJavaFeatureSpec implements FeatureSpecInternal { @@ -136,6 +139,8 @@ private void setupConfigurations(SourceSet sourceSet) { configurePacking(runtimeElements); configureTargetPlatform(apiElements); configureTargetPlatform(runtimeElements); + configureCategory(apiElements); + configureCategory(runtimeElements); configureCapabilities(apiElements); configureCapabilities(runtimeElements); attachArtifactToConfiguration(apiElements); @@ -181,6 +186,10 @@ private void configurePacking(Configuration configuration) { configuration.getAttributes().attribute(BUNDLING_ATTRIBUTE, objectFactory.named(Bundling.class, EXTERNAL)); } + private void configureCategory(Configuration configuration) { + configuration.getAttributes().attribute(CATEGORY_ATTRIBUTE, objectFactory.named(Category.class, LIBRARY)); + } + private void attachArtifactToConfiguration(Configuration configuration) { String jarTaskName = sourceSet.getJarTaskName(); if (!tasks.getNames().contains(jarTaskName)) { diff --git a/subprojects/plugins/src/test/groovy/org/gradle/api/plugins/JavaPlatformPluginTest.groovy b/subprojects/plugins/src/test/groovy/org/gradle/api/plugins/JavaPlatformPluginTest.groovy index 18cec3d52e769..25d186c60039c 100644 --- a/subprojects/plugins/src/test/groovy/org/gradle/api/plugins/JavaPlatformPluginTest.groovy +++ b/subprojects/plugins/src/test/groovy/org/gradle/api/plugins/JavaPlatformPluginTest.groovy @@ -18,8 +18,8 @@ package org.gradle.api.plugins import org.gradle.api.ProjectConfigurationException import org.gradle.api.artifacts.ModuleDependency +import org.gradle.api.attributes.Category import org.gradle.api.attributes.Usage -import org.gradle.api.internal.artifacts.dsl.dependencies.PlatformSupport import org.gradle.api.internal.component.UsageContext import org.gradle.test.fixtures.AbstractProjectBuilderSpec import spock.lang.Unroll @@ -120,17 +120,17 @@ class JavaPlatformPluginTest extends AbstractProjectBuilderSpec { runtimeUsage.dependencies == project.configurations.getByName(JavaPlatformPlugin.RUNTIME_CONFIGURATION_NAME).allDependencies.withType(ModuleDependency) runtimeUsage.dependencyConstraints.size() == 2 runtimeUsage.dependencyConstraints == project.configurations.getByName(JavaPlatformPlugin.RUNTIME_CONFIGURATION_NAME).allDependencyConstraints - runtimeUsage.attributes.keySet() == [Usage.USAGE_ATTRIBUTE, PlatformSupport.VARIANT_CATEGORY] as Set + runtimeUsage.attributes.keySet() == [Usage.USAGE_ATTRIBUTE, Category.CATEGORY_ATTRIBUTE] as Set runtimeUsage.attributes.getAttribute(Usage.USAGE_ATTRIBUTE).name == Usage.JAVA_RUNTIME - runtimeUsage.attributes.getAttribute(PlatformSupport.VARIANT_CATEGORY) == PlatformSupport.REGULAR_PLATFORM + runtimeUsage.attributes.getAttribute(Category.CATEGORY_ATTRIBUTE).name == Category.REGULAR_PLATFORM apiUsage.dependencies.size() == 1 apiUsage.dependencies == project.configurations.getByName(JavaPlatformPlugin.API_CONFIGURATION_NAME).allDependencies.withType(ModuleDependency) apiUsage.dependencyConstraints.size() == 1 apiUsage.dependencyConstraints == project.configurations.getByName(JavaPlatformPlugin.API_CONFIGURATION_NAME).allDependencyConstraints - apiUsage.attributes.keySet() == [Usage.USAGE_ATTRIBUTE, PlatformSupport.VARIANT_CATEGORY] as Set + apiUsage.attributes.keySet() == [Usage.USAGE_ATTRIBUTE, Category.CATEGORY_ATTRIBUTE] as Set apiUsage.attributes.getAttribute(Usage.USAGE_ATTRIBUTE).name == Usage.JAVA_API - apiUsage.attributes.getAttribute(PlatformSupport.VARIANT_CATEGORY) == PlatformSupport.REGULAR_PLATFORM + apiUsage.attributes.getAttribute(Category.CATEGORY_ATTRIBUTE).name == Category.REGULAR_PLATFORM } @Unroll("cannot add a dependency to the #configuration configuration by default") From 172a9af4f744a5493a3ee5a667ef674a5673a975 Mon Sep 17 00:00:00 2001 From: Daniel Lacasse Date: Mon, 4 Mar 2019 11:03:27 -0500 Subject: [PATCH 320/853] Mention potential breaking change regarding Windows symbolic links Junction points and symbolic links are now correctly handled as symbolic links by Gradle. --- .../docs/src/docs/userguide/upgrading_version_5.adoc | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/subprojects/docs/src/docs/userguide/upgrading_version_5.adoc b/subprojects/docs/src/docs/userguide/upgrading_version_5.adoc index ab71fb7b2c825..9844ab6f659ca 100644 --- a/subprojects/docs/src/docs/userguide/upgrading_version_5.adoc +++ b/subprojects/docs/src/docs/userguide/upgrading_version_5.adoc @@ -80,6 +80,10 @@ _and_ that Ivy dependency was substituted (using a `resolutionStrategy.force`, ` then this fix will impact you. The legacy behaviour of Gradle, prior to 5.0, was still in place instead of being replaced by the changes introduced by improved pom support. +==== Delete operations correctly handle symbolic links on Windows + +Gradle no longer ignores the `followSymlink` option on Windows for the `clean` task, all `Delete` tasks, and `project.delete {}` operations in the presence of junction points and symbolic links. + [[changes_5.2]] == Upgrading from 5.1 and earlier @@ -136,7 +140,7 @@ This may break plugins that relied on the previous behaviour. The incubating `operatingSystems` property on native components has been replaced with the link:{javadocPath}/org/gradle/language/cpp/CppComponent.html#getTargetMachines()[targetMachines] property. -### Change in behavior for tasks extending `AbstractArchiveTask` or subtypes (`Zip`, `Jar`, `War`, `Ear`, `Tar`) +### Change in behavior for tasks extending `AbstractArchiveTask` or subtypes (`Zip`, `Jar`, `War`, `Ear`, `Tar`) The `AbstractArchiveTask` has several new properties using the <>. Plugins that extend these types and override methods from the base class may no longer behave the same way. Internally, `AbstractArchiveTask` prefers the new properties and methods like `getArchiveName()` are façades over the new properties. From 0be4632fe99a5b4df71bb9140beb8abf56c5ec28 Mon Sep 17 00:00:00 2001 From: Cedric Champeau Date: Mon, 4 Mar 2019 14:57:24 +0100 Subject: [PATCH 321/853] Implement classifier to variant mapping This commit implements a strategy to disambiguate variants whenever the consumer uses a classifier in the dependency descriptor. This can be the case if a Maven library depends on a Gradle library published with Gradle module metadata, or even if a Gradle library depends on another Gradle library but makes use of a classifier (when it should really be using an attribute). --- .../ForcingPlatformAlignmentTest.groovy | 1 + ...fierToVariantResolveIntegrationTest.groovy | 147 ++++++++++++++++++ ...actVariantBackedConfigurationMetadata.java | 2 +- ...rationBoundExternalDependencyMetadata.java | 2 +- .../model/GradleDependencyMetadata.java | 2 +- .../model/AttributeConfigurationSelector.java | 43 ++++- .../LocalComponentDependencyMetadata.java | 2 +- .../AttributeConfigurationSelectorTest.groovy | 50 +++++- .../fixtures/publish/ModuleVersionSpec.groovy | 4 + .../fixtures/publish/VariantSpec.groovy | 1 + 10 files changed, 245 insertions(+), 9 deletions(-) create mode 100644 subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/maven/ClassifierToVariantResolveIntegrationTest.groovy diff --git a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/alignment/ForcingPlatformAlignmentTest.groovy b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/alignment/ForcingPlatformAlignmentTest.groovy index 2a475c9a4cef7..c6ec2565d9ec0 100644 --- a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/alignment/ForcingPlatformAlignmentTest.groovy +++ b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/alignment/ForcingPlatformAlignmentTest.groovy @@ -1067,6 +1067,7 @@ include 'other' members.each { member -> constraint(member) } + noArtifacts = true } // this is used only in BOMs members.each { member -> diff --git a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/maven/ClassifierToVariantResolveIntegrationTest.groovy b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/maven/ClassifierToVariantResolveIntegrationTest.groovy new file mode 100644 index 0000000000000..263160233eab4 --- /dev/null +++ b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/maven/ClassifierToVariantResolveIntegrationTest.groovy @@ -0,0 +1,147 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.integtests.resolve.maven + +import org.gradle.api.attributes.Usage +import org.gradle.integtests.fixtures.AbstractHttpDependencyResolutionTest +import org.gradle.integtests.fixtures.resolve.ResolveTestFixture + +class ClassifierToVariantResolveIntegrationTest extends AbstractHttpDependencyResolutionTest { + ResolveTestFixture resolve = new ResolveTestFixture(buildFile, "compileClasspath") + + def setup() { + settingsFile << """ + rootProject.name = 'test' + """ + buildFile << """ + apply plugin: 'java-library' + + repositories { + maven { url "${mavenHttpRepo.uri}" } + } + + """ + resolve.expectDefaultConfiguration('compile') + resolve.prepare() + } + + /** + * This simulates the case where a library is published with Gradle metadata, and + * that this library published additional variants, that use an artifact with a classifier. + * If a Maven consumer wants to use that artifact, it has no choice but using , + * so if a Gradle consumer depends on that Maven published library, we want to make sure we + * can match this classified dependency to a proper variant. + */ + def "reasonable behavior when a Maven library uses a classifier to select a Gradle variant"() { + def gradleLibrary = mavenHttpRepo.module("org", "lib", "1.0") + .adhocVariants() + .variant("apiElements", ['org.gradle.usage': Usage.JAVA_API_JARS, 'groovy.runtime': 'classic']) + .variant("runtimeElements", ['org.gradle.usage': Usage.JAVA_RUNTIME_JARS, 'groovy.runtime': 'classic']) + .variant("apiElementsIndy", ['org.gradle.usage': Usage.JAVA_API_JARS, 'groovy.runtime': 'indy']) { + artifact("lib-1.0-indy.jar") + } + .variant("runtimeElementsIndy", ['org.gradle.usage': Usage.JAVA_RUNTIME_JARS, 'groovy.runtime': 'indy']) { + artifact("lib-1.0-indy.jar") + } + .withGradleMetadataRedirection() + .withModuleMetadata() + .publish() + def mavenConsumer = mavenHttpRepo.module("org", "maven-consumer", "1.0") + .dependsOn("org", "lib", "1.0", "jar", "compile", "indy") + .publish() + + buildFile << """ + dependencies { + api 'org:maven-consumer:1.0' + } + """ + + when: + mavenConsumer.pom.expectGet() + mavenConsumer.artifact.expectGet() + gradleLibrary.pom.expectGet() + gradleLibrary.moduleMetadata.expectGet() + gradleLibrary.getArtifact(classifier: 'indy').expectGet() + run ':checkDeps' + + then: + resolve.expectGraph { + root(":", ":test:") { + module('org:maven-consumer:1.0') { + module('org:lib:1.0') { + variant('apiElementsIndy', [ + 'org.gradle.usage': Usage.JAVA_API_JARS, + 'org.gradle.status': 'release', + 'groovy.runtime': 'indy']) + artifact(name: 'lib', version: '1.0', classifier: 'indy') + } + } + } + } + + } + + /** + * A Gradle consumer should _not_ do this, but use attributes instead. However, + * there's nothing which prevents this from being done, so we must make sure it is + * supported. The path is exactly the same as when a Maven consumer wants to depend + * on a library published with Gradle that uses variants published using different + * classified artifacts. + */ + def "reasonable behavior when a Gradle consumer uses a classifier to select a Gradle variant"() { + def gradleLibrary = mavenHttpRepo.module("org", "lib", "1.0") + .adhocVariants() + .variant("apiElements", ['org.gradle.usage': Usage.JAVA_API_JARS, 'groovy.runtime': 'classic']) + .variant("runtimeElements", ['org.gradle.usage': Usage.JAVA_RUNTIME_JARS, 'groovy.runtime': 'classic']) + .variant("apiElementsIndy", ['org.gradle.usage': Usage.JAVA_API_JARS, 'groovy.runtime': 'indy']) { + artifact("lib-1.0-indy.jar") + } + .variant("runtimeElementsIndy", ['org.gradle.usage': Usage.JAVA_RUNTIME_JARS, 'groovy.runtime': 'indy']) { + artifact("lib-1.0-indy.jar") + } + .withGradleMetadataRedirection() + .withModuleMetadata() + .publish() + + buildFile << """ + dependencies { + api 'org:lib:1.0:indy' + } + """ + + when: + gradleLibrary.pom.expectGet() + gradleLibrary.moduleMetadata.expectGet() + gradleLibrary.getArtifact(classifier: 'indy').expectGet() + run ':checkDeps' + + then: + resolve.expectGraph { + root(":", ":test:") { + module('org:lib:1.0') { + variant('apiElementsIndy', [ + 'org.gradle.usage': Usage.JAVA_API_JARS, + 'org.gradle.status': 'release', + 'groovy.runtime': 'indy']) + artifact(name: 'lib', version: '1.0', classifier: 'indy') + } + } + } + + } + +} diff --git a/subprojects/dependency-management/src/main/java/org/gradle/internal/component/external/model/AbstractVariantBackedConfigurationMetadata.java b/subprojects/dependency-management/src/main/java/org/gradle/internal/component/external/model/AbstractVariantBackedConfigurationMetadata.java index 29229fb29abd9..bc2fc37632a4f 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/internal/component/external/model/AbstractVariantBackedConfigurationMetadata.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/internal/component/external/model/AbstractVariantBackedConfigurationMetadata.java @@ -143,7 +143,7 @@ public CapabilitiesMetadata getCapabilities() { @Override public List getArtifacts() { - return ImmutableList.of(); + return variant.getArtifacts(); } @Override diff --git a/subprojects/dependency-management/src/main/java/org/gradle/internal/component/external/model/ConfigurationBoundExternalDependencyMetadata.java b/subprojects/dependency-management/src/main/java/org/gradle/internal/component/external/model/ConfigurationBoundExternalDependencyMetadata.java index 903ea59462ebe..ffccd6d0cae4c 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/internal/component/external/model/ConfigurationBoundExternalDependencyMetadata.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/internal/component/external/model/ConfigurationBoundExternalDependencyMetadata.java @@ -89,7 +89,7 @@ public List selectConfigurations(ImmutableAttributes cons // This is a slight different condition than that used for a dependency declared in a Gradle project, // which is (targetHasVariants || consumerHasAttributes), relying on the fallback to 'default' for consumer attributes without any variants. if (alwaysUseAttributeMatching || hasVariants(targetComponent)) { - return ImmutableList.of(AttributeConfigurationSelector.selectConfigurationUsingAttributeMatching(consumerAttributes, explicitRequestedCapabilities, targetComponent, consumerSchema)); + return ImmutableList.of(AttributeConfigurationSelector.selectConfigurationUsingAttributeMatching(consumerAttributes, explicitRequestedCapabilities, targetComponent, consumerSchema, getArtifacts())); } return dependencyDescriptor.selectLegacyConfigurations(componentId, configuration, targetComponent); } diff --git a/subprojects/dependency-management/src/main/java/org/gradle/internal/component/external/model/GradleDependencyMetadata.java b/subprojects/dependency-management/src/main/java/org/gradle/internal/component/external/model/GradleDependencyMetadata.java index 21a780022110a..7cb4eeb2edb28 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/internal/component/external/model/GradleDependencyMetadata.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/internal/component/external/model/GradleDependencyMetadata.java @@ -96,7 +96,7 @@ public List getExcludes() { */ @Override public List selectConfigurations(ImmutableAttributes consumerAttributes, ComponentResolveMetadata targetComponent, AttributesSchemaInternal consumerSchema, Collection explicitRequestedCapabilities) { - return ImmutableList.of(AttributeConfigurationSelector.selectConfigurationUsingAttributeMatching(consumerAttributes, explicitRequestedCapabilities, targetComponent, consumerSchema)); + return ImmutableList.of(AttributeConfigurationSelector.selectConfigurationUsingAttributeMatching(consumerAttributes, explicitRequestedCapabilities, targetComponent, consumerSchema, getArtifacts())); } @Override diff --git a/subprojects/dependency-management/src/main/java/org/gradle/internal/component/model/AttributeConfigurationSelector.java b/subprojects/dependency-management/src/main/java/org/gradle/internal/component/model/AttributeConfigurationSelector.java index 770f038bac881..8534707a6513e 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/internal/component/model/AttributeConfigurationSelector.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/internal/component/model/AttributeConfigurationSelector.java @@ -18,6 +18,8 @@ import com.google.common.base.Optional; import com.google.common.collect.ImmutableList; +import com.google.common.collect.Lists; +import org.gradle.api.artifacts.ArtifactIdentifier; import org.gradle.api.artifacts.Dependency; import org.gradle.api.artifacts.ModuleVersionIdentifier; import org.gradle.api.capabilities.Capability; @@ -26,14 +28,16 @@ import org.gradle.internal.component.AmbiguousConfigurationSelectionException; import org.gradle.internal.component.NoMatchingCapabilitiesException; import org.gradle.internal.component.NoMatchingConfigurationSelectionException; +import org.gradle.internal.component.external.model.ModuleComponentArtifactMetadata; import org.gradle.internal.component.external.model.ShadowedCapability; import java.util.Collection; +import java.util.Collections; import java.util.List; public abstract class AttributeConfigurationSelector { - public static ConfigurationMetadata selectConfigurationUsingAttributeMatching(ImmutableAttributes consumerAttributes, Collection explicitRequestedCapabilities, ComponentResolveMetadata targetComponent, AttributesSchemaInternal consumerSchema) { + public static ConfigurationMetadata selectConfigurationUsingAttributeMatching(ImmutableAttributes consumerAttributes, Collection explicitRequestedCapabilities, ComponentResolveMetadata targetComponent, AttributesSchemaInternal consumerSchema, List requestedArtifacts) { Optional> variantsForGraphTraversal = targetComponent.getVariantsForGraphTraversal(); ImmutableList consumableConfigurations = variantsForGraphTraversal.or(ImmutableList.of()); AttributesSchemaInternal producerAttributeSchema = targetComponent.getAttributesSchema(); @@ -57,7 +61,7 @@ public static ConfigurationMetadata selectConfigurationUsingAttributeMatching(Im List strictlyMatchingCapabilities = filterVariantsByRequestedCapabilities(targetComponent, explicitRequestedCapabilities, matches, versionId.getGroup(), versionId.getName(), false); if (strictlyMatchingCapabilities.size() == 1) { return singleVariant(variantsForGraphTraversal, matches); - } else if (strictlyMatchingCapabilities.size() > 1){ + } else if (strictlyMatchingCapabilities.size() > 1) { // there are still more than one candidate, but this time we know only a subset strictly matches the required attributes // so we perform another round of selection on the remaining candidates strictlyMatchingCapabilities = attributeMatcher.matches(strictlyMatchingCapabilities, consumerAttributes, fallbackConfiguration); @@ -65,6 +69,18 @@ public static ConfigurationMetadata selectConfigurationUsingAttributeMatching(Im return singleVariant(variantsForGraphTraversal, matches); } } + if (requestedArtifacts.size() == 1) { + // Here, we know that the user requested a specific classifier. There may be multiple + // candidate variants left, but maybe only one of them provides the classified artifact + // we're looking for. + String classifier = requestedArtifacts.get(0).getClassifier(); + if (classifier != null) { + List sameClassifier = findVariantsProvidingExactlySameClassifier(matches, classifier); + if (sameClassifier != null && sameClassifier.size() == 1) { + return singleVariant(variantsForGraphTraversal, sameClassifier); + } + } + } } if (matches.size() == 1) { return singleVariant(variantsForGraphTraversal, matches); @@ -75,6 +91,29 @@ public static ConfigurationMetadata selectConfigurationUsingAttributeMatching(Im } } + private static List findVariantsProvidingExactlySameClassifier(List matches, String classifier) { + List sameClassifier = null; + // let's see if we can find a single variant which has exactly the requested artifacts + for (ConfigurationMetadata match : matches) { + List artifacts = match.getArtifacts(); + if (artifacts.size() == 1) { + ComponentArtifactMetadata componentArtifactMetadata = artifacts.get(0); + if (componentArtifactMetadata instanceof ModuleComponentArtifactMetadata) { + ArtifactIdentifier artifactIdentifier = ((ModuleComponentArtifactMetadata) componentArtifactMetadata).toArtifactIdentifier(); + if (classifier.equals(artifactIdentifier.getClassifier())) { + if (sameClassifier == null) { + sameClassifier = Collections.singletonList(match); + } else { + sameClassifier = Lists.newArrayList(sameClassifier); + sameClassifier.add(match); + } + } + } + } + } + return sameClassifier; + } + private static ConfigurationMetadata singleVariant(Optional> variantsForGraphTraversal, List matches) { ConfigurationMetadata match = matches.get(0); if (variantsForGraphTraversal.isPresent()) { diff --git a/subprojects/dependency-management/src/main/java/org/gradle/internal/component/model/LocalComponentDependencyMetadata.java b/subprojects/dependency-management/src/main/java/org/gradle/internal/component/model/LocalComponentDependencyMetadata.java index 89e6ca271d1b2..4f60af19f9704 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/internal/component/model/LocalComponentDependencyMetadata.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/internal/component/model/LocalComponentDependencyMetadata.java @@ -132,7 +132,7 @@ public List selectConfigurations(ImmutableAttributes cons Optional> targetVariants = targetComponent.getVariantsForGraphTraversal(); boolean useConfigurationAttributes = dependencyConfiguration == null && (consumerHasAttributes || targetVariants.isPresent()); if (useConfigurationAttributes) { - return ImmutableList.of(AttributeConfigurationSelector.selectConfigurationUsingAttributeMatching(consumerAttributes, explicitRequestedCapabilities, targetComponent, consumerSchema)); + return ImmutableList.of(AttributeConfigurationSelector.selectConfigurationUsingAttributeMatching(consumerAttributes, explicitRequestedCapabilities, targetComponent, consumerSchema, getArtifacts())); } String targetConfiguration = GUtil.elvis(dependencyConfiguration, Dependency.DEFAULT_CONFIGURATION); diff --git a/subprojects/dependency-management/src/test/groovy/org/gradle/internal/component/model/AttributeConfigurationSelectorTest.groovy b/subprojects/dependency-management/src/test/groovy/org/gradle/internal/component/model/AttributeConfigurationSelectorTest.groovy index 38412c12e0b58..ad97b27c5f613 100644 --- a/subprojects/dependency-management/src/test/groovy/org/gradle/internal/component/model/AttributeConfigurationSelectorTest.groovy +++ b/subprojects/dependency-management/src/test/groovy/org/gradle/internal/component/model/AttributeConfigurationSelectorTest.groovy @@ -18,6 +18,7 @@ package org.gradle.internal.component.model import com.google.common.base.Optional import com.google.common.collect.ImmutableList +import org.gradle.api.artifacts.ArtifactIdentifier import org.gradle.api.artifacts.ModuleVersionIdentifier import org.gradle.api.artifacts.component.ComponentIdentifier import org.gradle.api.attributes.Attribute @@ -30,6 +31,8 @@ import org.gradle.api.internal.attributes.DefaultAttributesSchema import org.gradle.api.internal.attributes.ImmutableAttributes import org.gradle.internal.component.AmbiguousConfigurationSelectionException import org.gradle.internal.component.NoMatchingConfigurationSelectionException +import org.gradle.internal.component.external.model.ModuleComponentArtifactIdentifier +import org.gradle.internal.component.external.model.ModuleComponentArtifactMetadata import org.gradle.util.SnapshotTestUtil import org.gradle.util.TestUtil import org.gradle.util.TextUtil @@ -45,6 +48,7 @@ class AttributeConfigurationSelectorTest extends Specification { private ConfigurationMetadata selected private ImmutableAttributes consumerAttributes = ImmutableAttributes.EMPTY private List requestedCapabilities = [] + private List artifacts = [] @Unroll def "selects a variant when there's no ambiguity"() { @@ -187,7 +191,7 @@ All of them match the consumer attributes: then: AmbiguousConfigurationSelectionException e = thrown() - failsWith(e,'''Cannot choose between the following variants of org:lib:1.0: + failsWith(e, '''Cannot choose between the following variants of org:lib:1.0: - api1 - api2 - api3 @@ -283,15 +287,55 @@ All of them match the consumer attributes: selected.name == 'second' } + def "should select the variant which matches the requested classifier"() { + def variant1 = variant("first", ImmutableAttributes.EMPTY) + def variant2 = variant("second", ImmutableAttributes.EMPTY) + + given: + variant1.getArtifacts() >> [ + artifact('foo', null) + ] + variant2.getArtifacts() >> [ + artifact('foo', 'classy') + ] + component(variant1, variant2) + + and: + requireArtifact('foo', 'jar', 'jar', 'classy') + + when: + performSelection() + + then: + selected.name == 'second' + } + private void performSelection() { selected = AttributeConfigurationSelector.selectConfigurationUsingAttributeMatching( consumerAttributes, requestedCapabilities, targetComponent, - attributesSchema + attributesSchema, + artifacts ) } + private void requireArtifact(String name = "foo", String type = "jar", String ext = "jar", String classifier = null) { + artifacts << new DefaultIvyArtifactName(name, type, ext, classifier) + } + + private ModuleComponentArtifactMetadata artifact(String name, String classifier) { + Stub(ModuleComponentArtifactMetadata) { + getId() >> Stub(ModuleComponentArtifactIdentifier) + toArtifactIdentifier() >> Stub(ArtifactIdentifier) { + getName() >> name + getType() >> "jar" + getExtension() >> "jar" + getClassifier() >> classifier + } + } + } + private consumerAttributes(Map attrs) { this.consumerAttributes = attributes(attrs) } @@ -349,7 +393,7 @@ All of them match the consumer attributes: @Override void execute(CompatibilityCheckDetails details) { - if (details.consumerValue == 'java-api' && details.producerValue=='java-runtime') { + if (details.consumerValue == 'java-api' && details.producerValue == 'java-runtime') { details.compatible() } } diff --git a/subprojects/dependency-management/src/testFixtures/groovy/org/gradle/integtests/fixtures/publish/ModuleVersionSpec.groovy b/subprojects/dependency-management/src/testFixtures/groovy/org/gradle/integtests/fixtures/publish/ModuleVersionSpec.groovy index 55e263fc46ae5..fa8dc6aaa3309 100644 --- a/subprojects/dependency-management/src/testFixtures/groovy/org/gradle/integtests/fixtures/publish/ModuleVersionSpec.groovy +++ b/subprojects/dependency-management/src/testFixtures/groovy/org/gradle/integtests/fixtures/publish/ModuleVersionSpec.groovy @@ -297,6 +297,10 @@ class ModuleVersionSpec { capabilities = variant.capabilities.collect { new CapabilitySpec(group: it.group, name: it.name, version: it.version) } + if (variant.noArtifacts) { + artifacts = [] + useDefaultArtifacts = false + } } } } diff --git a/subprojects/dependency-management/src/testFixtures/groovy/org/gradle/integtests/fixtures/publish/VariantSpec.groovy b/subprojects/dependency-management/src/testFixtures/groovy/org/gradle/integtests/fixtures/publish/VariantSpec.groovy index a64e0e73733a2..98e022639a305 100644 --- a/subprojects/dependency-management/src/testFixtures/groovy/org/gradle/integtests/fixtures/publish/VariantSpec.groovy +++ b/subprojects/dependency-management/src/testFixtures/groovy/org/gradle/integtests/fixtures/publish/VariantSpec.groovy @@ -26,6 +26,7 @@ class VariantSpec { Map attributes = [:] List artifacts = [] List capabilities = [] + boolean noArtifacts = false void dependsOn(coord) { dependsOn << coord From 20abac98149b55928f0ec6223ec823c1a61fdf4e Mon Sep 17 00:00:00 2001 From: "Rodrigo B. de Oliveira" Date: Mon, 4 Mar 2019 12:53:34 -0300 Subject: [PATCH 322/853] Avoid calling the Kotlin compiler when there are no source files In order to reduce the fixed cost of precompiled script plugins. --- .../CompilePrecompiledScriptPluginPlugins.kt | 26 ++++++++++--------- 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/CompilePrecompiledScriptPluginPlugins.kt b/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/CompilePrecompiledScriptPluginPlugins.kt index adaa2b61b9861..7e8e3460fc148 100644 --- a/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/CompilePrecompiledScriptPluginPlugins.kt +++ b/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/CompilePrecompiledScriptPluginPlugins.kt @@ -50,18 +50,20 @@ open class CompilePrecompiledScriptPluginPlugins : ClassPathSensitiveTask() { @TaskAction fun compile() { outputDir.withOutputDirectory { outputDir -> - compileKotlinScriptModuleTo( - outputDir, - sourceFiles.name, - sourceFiles.map { it.path }, - scriptDefinitionFromTemplate( - KotlinPluginsBlock::class, - implicitImportsForPrecompiledScriptPlugins() - ), - classPathFiles, - logger, - { it } // TODO: translate paths - ) + val scriptFiles = sourceFiles.map { it.path } + if (scriptFiles.isNotEmpty()) + compileKotlinScriptModuleTo( + outputDir, + sourceFiles.name, + scriptFiles, + scriptDefinitionFromTemplate( + KotlinPluginsBlock::class, + implicitImportsForPrecompiledScriptPlugins() + ), + classPathFiles, + logger, + { it } // TODO: translate paths + ) } } } From 0915189b448b2a99c11a9e622b7b6c4b655391ad Mon Sep 17 00:00:00 2001 From: "Rodrigo B. de Oliveira" Date: Mon, 4 Mar 2019 12:54:58 -0300 Subject: [PATCH 323/853] Reduce the async io scope In order to reduce the fixed cost of precompiled script plugins. --- .../tasks/GeneratePrecompiledScriptPluginAccessors.kt | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/GeneratePrecompiledScriptPluginAccessors.kt b/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/GeneratePrecompiledScriptPluginAccessors.kt index e9dc8f4cc41c0..28d147f0f49e1 100644 --- a/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/GeneratePrecompiledScriptPluginAccessors.kt +++ b/subprojects/kotlin-dsl-provider-plugins/src/main/kotlin/org/gradle/kotlin/dsl/provider/plugins/precompiled/tasks/GeneratePrecompiledScriptPluginAccessors.kt @@ -111,10 +111,9 @@ open class GeneratePrecompiledScriptPluginAccessors : ClassPathSensitiveCodeGene recreateTaskDirectories() - withAsynchronousIO(project) { - - val projectPlugins = selectProjectPlugins() - if (projectPlugins.isNotEmpty()) { + val projectPlugins = selectProjectPlugins() + if (projectPlugins.isNotEmpty()) { + withAsynchronousIO(project) { generateTypeSafeAccessorsFor(projectPlugins) } } From 811070ff1101e1b5070551713a0cef1d5409121f Mon Sep 17 00:00:00 2001 From: Gradleware Git Bot Date: Tue, 5 Mar 2019 02:19:09 +0100 Subject: [PATCH 324/853] Publish 5.3-20190305010422+0000 --- released-versions.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/released-versions.json b/released-versions.json index aa10adc6aa961..82006924a0f05 100644 --- a/released-versions.json +++ b/released-versions.json @@ -1,7 +1,7 @@ { "latestReleaseSnapshot": { - "version": "5.3-20190304012021+0000", - "buildTime": "20190304012021+0000" + "version": "5.3-20190305010422+0000", + "buildTime": "20190305010422+0000" }, "latestRc": { "version": "5.2-rc-1", From 9b9008771fdd216864c21053fbb4c9e7dfb74be6 Mon Sep 17 00:00:00 2001 From: Stefan Wolf Date: Tue, 5 Mar 2019 16:40:50 +0100 Subject: [PATCH 325/853] Remove plugin portal override from command line arguments --- .../GradleBuildConfigurationDefaults.kt | 5 +- .teamcity/Gradle_Check_dsl.iml | 55 +++++++++++++++---- 2 files changed, 46 insertions(+), 14 deletions(-) diff --git a/.teamcity/Gradle_Check/configurations/GradleBuildConfigurationDefaults.kt b/.teamcity/Gradle_Check/configurations/GradleBuildConfigurationDefaults.kt index ee8aa1d1623c9..f0ce90afbbc6a 100644 --- a/.teamcity/Gradle_Check/configurations/GradleBuildConfigurationDefaults.kt +++ b/.teamcity/Gradle_Check/configurations/GradleBuildConfigurationDefaults.kt @@ -33,8 +33,9 @@ fun gradleParameters(daemon: Boolean = true, isContinue: Boolean = true): List - + @@ -32,15 +35,32 @@ - + + + + + + + + + + + + + + + + + + @@ -58,14 +78,25 @@ - - - - - - - - - + + + + + + + + + + + + + + + + + + + + \ No newline at end of file From 5b6772186fd32be640539fec234ba2547ee817c1 Mon Sep 17 00:00:00 2001 From: Stefan Wolf Date: Tue, 5 Mar 2019 16:52:50 +0100 Subject: [PATCH 326/853] Fix configurations test --- .../Gradle_Check_Tests/ApplyDefaultConfigurationTest.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.teamcityTest/Gradle_Check_Tests/ApplyDefaultConfigurationTest.kt b/.teamcityTest/Gradle_Check_Tests/ApplyDefaultConfigurationTest.kt index a1585bdc74190..81fccbddd76b2 100644 --- a/.teamcityTest/Gradle_Check_Tests/ApplyDefaultConfigurationTest.kt +++ b/.teamcityTest/Gradle_Check_Tests/ApplyDefaultConfigurationTest.kt @@ -127,5 +127,5 @@ class ApplyDefaultConfigurationTest { private fun expectedRunnerParam(daemon: String = "--daemon", extraParameters: String = "") = - "-PmaxParallelForks=%maxParallelForks% -s $daemon --continue -I \"%teamcity.build.checkoutDir%/gradle/init-scripts/build-scan.init.gradle.kts\" -Dorg.gradle.internal.tasks.createops -Dorg.gradle.internal.plugins.portal.url.override=http://dev12.gradle.org:8081/artifactory/gradle-plugins/ $extraParameters -PteamCityUsername=%teamcity.username.restbot% -PteamCityPassword=%teamcity.password.restbot% -PteamCityBuildId=%teamcity.build.id% \"-Dscan.tag.Check\" \"-Dscan.tag.\"" + "-PmaxParallelForks=%maxParallelForks% -s $daemon --continue -I \"%teamcity.build.checkoutDir%/gradle/init-scripts/build-scan.init.gradle.kts\" -Dorg.gradle.internal.tasks.createops $extraParameters -PteamCityUsername=%teamcity.username.restbot% -PteamCityPassword=%teamcity.password.restbot% -PteamCityBuildId=%teamcity.build.id% \"-Dscan.tag.Check\" \"-Dscan.tag.\"" } From 1143e585d50f883d5025e01692eddb7ee4c27e10 Mon Sep 17 00:00:00 2001 From: Sterling Greene Date: Tue, 5 Mar 2019 10:48:52 -0500 Subject: [PATCH 327/853] Clarify behavior difference between Kotlin and Groovy scripts --- subprojects/docs/src/docs/userguide/more_about_tasks.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subprojects/docs/src/docs/userguide/more_about_tasks.adoc b/subprojects/docs/src/docs/userguide/more_about_tasks.adoc index 3bb95465df71d..3af708de66c0c 100644 --- a/subprojects/docs/src/docs/userguide/more_about_tasks.adoc +++ b/subprojects/docs/src/docs/userguide/more_about_tasks.adoc @@ -157,7 +157,7 @@ include::sample[dir="userguide/tasks/configureUsingBlock/groovy",files="build.gr include::sample[dir="userguide/tasks/configureUsingBlock/kotlin",files="build.gradle.kts[tags=configure]"] ==== -This works for _any_ task. Task access is just a shortcut for the `tasks.named()` method. It is important to note that if you pass a block to the `named()` method, this block is applied to _configure_ the task, not when the task executes. +This works for _any_ task. Task access is just a shortcut for the `tasks.named()` (Kotlin) or `tasks.getByName()` (Groovy) method. It is important to note that blocks used here are for _configuring_ the task and are not evaluated when the task executes. Have a look at link:{javadocPath}/org/gradle/api/tasks/TaskContainer.html[TaskContainer] for more options for configuring tasks. From ec8a8bc2dd4c0761880ccec4f28c5db79c2244bb Mon Sep 17 00:00:00 2001 From: Sterling Greene Date: Tue, 5 Mar 2019 11:12:52 -0500 Subject: [PATCH 328/853] Polish release notes more --- subprojects/docs/src/docs/release/notes.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/subprojects/docs/src/docs/release/notes.md b/subprojects/docs/src/docs/release/notes.md index 7dfb5d4b65dc7..9951fa2231d7b 100644 --- a/subprojects/docs/src/docs/release/notes.md +++ b/subprojects/docs/src/docs/release/notes.md @@ -2,7 +2,7 @@ The Gradle team is excited to announce Gradle 5.3. This release features incubating support for publishing and consuming Gradle Module Metadata, [feature variants AKA "optional dependencies"](#feature-variants-aka-optional-dependencies), -type-safe accessors in Kotlin pre-compiled script plugins, and more. +[type-safe accessors in Kotlin pre-compiled script plugins](#type-safe-accessors-in-precompiled-script-plugins), and more. We would like to thank the following community contributors to this release of Gradle: @@ -128,7 +128,7 @@ Execution failed for task ':clean'. ### Public API for publishing custom components Gradle now offers a public API to publish custom software components. -Refer to the `SoftwareComponentFactory` javadocs for details or look at the `JavaPlugin` and `JavaPlaftormPlugin` which have been migrated to use this API. +Refer to the [`SoftwareComponentFactory` documentation](javadoc/org/gradle/api/component/SoftwareComponentFactory.html) for details or look at the `JavaPlugin` and `JavaPlaftormPlugin` which have been migrated to use this API. ### Gradle Module Metadata 1.0 From bf191f81f6bc7f62b3baeb72388e45f63ef7035a Mon Sep 17 00:00:00 2001 From: Daniel Lacasse Date: Tue, 5 Mar 2019 22:12:04 +0100 Subject: [PATCH 329/853] Publish 5.3-rc-1 --- released-versions.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/released-versions.json b/released-versions.json index 82006924a0f05..f8e6255303c3e 100644 --- a/released-versions.json +++ b/released-versions.json @@ -4,8 +4,8 @@ "buildTime": "20190305010422+0000" }, "latestRc": { - "version": "5.2-rc-1", - "buildTime": "20190128225604+0000" + "version": "5.3-rc-1", + "buildTime": "20190305205202+0000" }, "finalReleases": [ { From 2b817b671e89c115ae4254fb9626f8c94017b054 Mon Sep 17 00:00:00 2001 From: Daniel Lacasse Date: Tue, 5 Mar 2019 16:49:37 -0500 Subject: [PATCH 330/853] Update wrapper to version 5.3-rc-1 --- gradle/wrapper/gradle-wrapper.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index f632acc7edeb1..31833fa77e100 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions-snapshots/gradle-5.3-20190301232024+0000-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-5.3-rc-1-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists From 7d13841d093cb1e7ac568a1a249fa341cca3294c Mon Sep 17 00:00:00 2001 From: Daniel Lacasse Date: Tue, 5 Mar 2019 16:49:51 -0500 Subject: [PATCH 331/853] Reset the release note for 5.4 --- subprojects/docs/src/docs/release/notes.md | 164 +++------------------ 1 file changed, 21 insertions(+), 143 deletions(-) diff --git a/subprojects/docs/src/docs/release/notes.md b/subprojects/docs/src/docs/release/notes.md index 9951fa2231d7b..3ce4d2ff63e43 100644 --- a/subprojects/docs/src/docs/release/notes.md +++ b/subprojects/docs/src/docs/release/notes.md @@ -1,154 +1,32 @@ -The Gradle team is excited to announce Gradle 5.3. +The Gradle team is excited to announce Gradle {gradleVersion}. -This release features incubating support for publishing and consuming Gradle Module Metadata, -[feature variants AKA "optional dependencies"](#feature-variants-aka-optional-dependencies), -[type-safe accessors in Kotlin pre-compiled script plugins](#type-safe-accessors-in-precompiled-script-plugins), and more. +This release features [1](), [2](), ... [n](), and more. We would like to thank the following community contributors to this release of Gradle: + -[Stefan M.](https://github.com/StefMa), -[Evgeny Mandrikov](https://github.com/Godin), -[Simon Legner](https://github.com/simon04), -[Raman Gupta](https://github.com/rocketraman), -[Florian Dreier](https://github.com/DreierF), -[Kenzie Togami](https://github.com/kenzierocks), -[Ricardo Pereira](https://github.com/thc202), -[Thad House](https://github.com/ThadHouse), -[Joe Kutner](https://github.com/jkutner), -and [Josh Soref](https://github.com/jsoref). - -## Upgrade Instructions - -Switch your build to use Gradle 5.3 RC1 by updating your wrapper properties: - -`./gradlew wrapper --gradle-version=5.3-rc-1` - -Standalone downloads are available at [gradle.org/release-candidate](https://gradle.org/release-candidate). - -## Feature variants aka optional dependencies - -Gradle now provides a powerful model for declaring features a library provides, known as [feature variants](userguide/feature_variants.html): - -```groovy -java { - // declare an "optional feature" - registerFeature("mysqlSupport") { - usingSourceSet(sourceSets.main) - } -} -dependencies { - // declare dependencies specific to the "optional feature" - mysqlSupportImplementation "mysql:mysql-connector-java:8.0.14" -} -``` - -Long story short, this can be used to model [optional dependencies](https://github.com/gradle/gradle/issues/867)! - -## Kotlin DSL - -### Kotlin 1.3.21 - -The embedded Kotlin version has been upgraded to Kotlin 1.3.21. - -Please see the [Kotlin 1.3.21 announcement](https://github.com/JetBrains/kotlin/releases/tag/v1.3.21) for details. - -### Type-safe accessors in precompiled script plugins - -Starting with Gradle 5.3, Kotlin precompiled project script plugins now have type-safe accessors, just like regular project build scripts. - -For example, here is how an hypothetical plugin that sets up a Java project according to some convention would be written as a Kotlin precompiled project script plugin in `buildSrc`: - -```kotlin -// buildSrc/src/main/kotlin/my-java-convention.gradle.kts -plugins { - `java-library` - checkstyle -} - -java { - sourceCompatibility = JavaVersion.VERSION_11 - targetCompatibility = JavaVersion.VERSION_11 -} - -tasks { - withType { - options.isWarnings = true - } - checkstyleMain { - maxWarnings = 0 - } -} - -dependencies { - testImplementation("junit:junit:4.12") -} -``` - -It makes use of type-safe accessors for the `java {}` extension, the `checkstyleMain` task and the `testImplementation` configuration, all contributed by the plugins it applies (`java-library` and `checkstyle`). - -This plugin can then be applied to regular projects: - -```kotlin -// build.gradle.kts -plugins { - `my-java-convention` -} -``` - -See the [Precompiled script plugins](userguide/kotlin_dsl.html#kotdsl:precompiled_plugins) section of the user manual for more information. - -## Better help message on delete operation failure - -The `clean` task, all `Delete` tasks, and `project.delete {}` operations now provide a better help message when failing to delete files. The most frequent and hard to troubleshoot causes for failing to delete files are other processes holding file descriptors open, and concurrent writes. - -The help message now displays each failed path, which may be helpful in identifying which process might be holding files open, and will also display any files that were created in the target directory after a delete failure, which may be helpful in identifying when a process is still writing to the directory. - -For example, a process holding `some.file` open in your `build` directory while running the `:clean` task would cause the following message to be displayed: - -``` -* What went wrong: -Execution failed for task ':clean'. -> Unable to delete directory '/path/to/your/gradle-project/build' - Failed to delete some children. This might happen because a process has files open or has its working directory set in the target directory. - - /path/to/your/gradle-build/subproject/build/some.file -``` - -A process still writing to your `build` directory while running the `:clean` task would display: - -``` -* What went wrong: -Execution failed for task ':clean'. -> Unable to delete directory '/path/to/your/gradle-project/build' - New files were found. This might happen because a process is still writing to the target directory. - - /path/to/your/gradle-build/subproject/build/new.file -``` - -## Improvements for plugin authors - -### Public API for publishing custom components - -Gradle now offers a public API to publish custom software components. -Refer to the [`SoftwareComponentFactory` documentation](javadoc/org/gradle/api/component/SoftwareComponentFactory.html) for details or look at the `JavaPlugin` and `JavaPlaftormPlugin` which have been migrated to use this API. - -### Gradle Module Metadata 1.0 - -Gradle Module Metadata is now 1.0. + -## Default JaCoCo version upgraded to 0.8.3 +## Upgrade Instructions -[The JaCoCo plugin](userguide/jacoco_plugin.html) has been upgraded to use [JaCoCo version 0.8.3](http://www.jacoco.org/jacoco/trunk/doc/changes.html) instead of 0.8.2 by default. +Switch your build to use Gradle {gradleVersion} by updating your wrapper properties: -## Default Checkstyle version upgraded to 8.17 +`./gradlew wrapper --gradle-version={gradleVersion}` -[The Checkstyle plugin](userguide/checkstyle_plugin.html) has been upgraded to use [Checkstyle version 8.17](http://checkstyle.sourceforge.net/releasenotes.html#Release_8.17) by default. +Standalone downloads are available at [gradle.org/releases](https://gradle.org/releases). ## Promoted features Promoted features are features that were incubating in previous versions of Gradle but are now supported and subject to backwards compatibility. @@ -173,15 +51,15 @@ in the next major Gradle version (Gradle 6.0). See the User Manual section on th The following are the newly deprecated items in this Gradle release. If you have concerns about a deprecation, please raise it via the [Gradle Forums](https://discuss.gradle.org). -### Incubating method `ProjectLayout.configurableFiles()` replaced by `ObjectFactory.fileCollection()` - -The method `ProjectLayout.configurableFiles()` is now deprecated, and will be removed in Gradle 6.0. You should use `ObjectFactory.fileCollection()` instead. + ### Breaking changes -See the [Gradle 5.x upgrade guide](userguide/upgrading_version_5.html#changes_5.3) to learn about breaking changes and considerations when upgrading to Gradle 5.3. +See the [Gradle 5.x upgrade guide](userguide/upgrading_version_5.html#changes_{gradleVersion}) to learn about breaking changes and considerations when upgrading to Gradle {gradleVersion}. From db8b2c184aba4d288a0852a843386babb1f819b9 Mon Sep 17 00:00:00 2001 From: Bo Zhang Date: Wed, 6 Mar 2019 08:45:50 +0800 Subject: [PATCH 332/853] Upgrade tagging plugin to 0.55 --- build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle.kts b/build.gradle.kts index 0d3d143fa0fbb..a4dbf38d2d60a 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -32,7 +32,7 @@ plugins { // We have to apply it here at the moment, so that when the build scan plugin is auto-applied via --scan can detect that // the plugin has been already applied. For that the plugin has to be applied with the new plugin DSL syntax. com.gradle.`build-scan` - id("org.gradle.ci.tag-single-build") version("0.54") + id("org.gradle.ci.tag-single-build") version("0.55") } defaultTasks("assemble") From 0a91c3549ff6b6dbd0cf028c8a1537a458f85d6f Mon Sep 17 00:00:00 2001 From: Gradleware Git Bot Date: Wed, 6 Mar 2019 02:20:49 +0100 Subject: [PATCH 333/853] Publish 5.3-20190306010147+0000 --- released-versions.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/released-versions.json b/released-versions.json index f8e6255303c3e..69c6b2e856599 100644 --- a/released-versions.json +++ b/released-versions.json @@ -1,7 +1,7 @@ { "latestReleaseSnapshot": { - "version": "5.3-20190305010422+0000", - "buildTime": "20190305010422+0000" + "version": "5.3-20190306010147+0000", + "buildTime": "20190306010147+0000" }, "latestRc": { "version": "5.3-rc-1", From f19500e2b4d9c0b2c575038fe76c309a6c2ff484 Mon Sep 17 00:00:00 2001 From: Bo Zhang Date: Wed, 6 Mar 2019 10:42:16 +0800 Subject: [PATCH 334/853] Make org.gradle.internal.plugins.portal.url.override configurable --- .../configurations/GradleBuildConfigurationDefaults.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.teamcity/Gradle_Check/configurations/GradleBuildConfigurationDefaults.kt b/.teamcity/Gradle_Check/configurations/GradleBuildConfigurationDefaults.kt index f0ce90afbbc6a..1ebd4d45b9403 100644 --- a/.teamcity/Gradle_Check/configurations/GradleBuildConfigurationDefaults.kt +++ b/.teamcity/Gradle_Check/configurations/GradleBuildConfigurationDefaults.kt @@ -33,8 +33,8 @@ fun gradleParameters(daemon: Boolean = true, isContinue: Boolean = true): List Date: Wed, 6 Mar 2019 13:57:11 +0800 Subject: [PATCH 335/853] Fix failed TeamCity Kotlin DSL test --- .../Gradle_Check_Tests/ApplyDefaultConfigurationTest.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.teamcityTest/Gradle_Check_Tests/ApplyDefaultConfigurationTest.kt b/.teamcityTest/Gradle_Check_Tests/ApplyDefaultConfigurationTest.kt index 81fccbddd76b2..b03a70416cba0 100644 --- a/.teamcityTest/Gradle_Check_Tests/ApplyDefaultConfigurationTest.kt +++ b/.teamcityTest/Gradle_Check_Tests/ApplyDefaultConfigurationTest.kt @@ -127,5 +127,5 @@ class ApplyDefaultConfigurationTest { private fun expectedRunnerParam(daemon: String = "--daemon", extraParameters: String = "") = - "-PmaxParallelForks=%maxParallelForks% -s $daemon --continue -I \"%teamcity.build.checkoutDir%/gradle/init-scripts/build-scan.init.gradle.kts\" -Dorg.gradle.internal.tasks.createops $extraParameters -PteamCityUsername=%teamcity.username.restbot% -PteamCityPassword=%teamcity.password.restbot% -PteamCityBuildId=%teamcity.build.id% \"-Dscan.tag.Check\" \"-Dscan.tag.\"" + "-PmaxParallelForks=%maxParallelForks% -s $daemon --continue -I \"%teamcity.build.checkoutDir%/gradle/init-scripts/build-scan.init.gradle.kts\" -Dorg.gradle.internal.tasks.createops -Dorg.gradle.internal.plugins.portal.url.override=%gradle.plugins.portal.url% $extraParameters -PteamCityUsername=%teamcity.username.restbot% -PteamCityPassword=%teamcity.password.restbot% -PteamCityBuildId=%teamcity.build.id% \"-Dscan.tag.Check\" \"-Dscan.tag.\"" } From 55af8e1a0f5e17dd3c91cc39aaa261c4d7d37514 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=B3r=C3=A1nt=20Pint=C3=A9r?= Date: Wed, 6 Mar 2019 11:48:06 +0100 Subject: [PATCH 336/853] Don't show errors about Java 8 API usage in IntelliJ Most of Gradle now requires JDK 8, but :core unfortunately requires Java 6, yet in many places it uses Java 8 APIs. To keep things in a workable state we only let IntelliJ warn about things not available in Java 8, and rely on runtime tests to prevent Java 7/8 APIs leaking into code that must still run on Java 6. --- .idea/inspectionProfiles/Gradle.xml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.idea/inspectionProfiles/Gradle.xml b/.idea/inspectionProfiles/Gradle.xml index a554a4f25d399..3d0904d5fcbb4 100644 --- a/.idea/inspectionProfiles/Gradle.xml +++ b/.idea/inspectionProfiles/Gradle.xml @@ -20,6 +20,9 @@ + + + From 1dd1d7ebbc80b8a90c689d0c002b95f96fb7fe07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=B3r=C3=A1nt=20Pint=C3=A9r?= Date: Tue, 5 Mar 2019 15:15:08 +0100 Subject: [PATCH 337/853] Remove unused classes --- .../state/AbstractTaskExecution.java | 54 ------------------- .../changedetection/state/TaskExecution.java | 25 --------- 2 files changed, 79 deletions(-) delete mode 100644 subprojects/core/src/main/java/org/gradle/api/internal/changedetection/state/AbstractTaskExecution.java delete mode 100644 subprojects/core/src/main/java/org/gradle/api/internal/changedetection/state/TaskExecution.java diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/changedetection/state/AbstractTaskExecution.java b/subprojects/core/src/main/java/org/gradle/api/internal/changedetection/state/AbstractTaskExecution.java deleted file mode 100644 index 89fb23ab4a66f..0000000000000 --- a/subprojects/core/src/main/java/org/gradle/api/internal/changedetection/state/AbstractTaskExecution.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright 2011 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.gradle.api.internal.changedetection.state; - -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableSortedMap; -import org.gradle.internal.snapshot.ValueSnapshot; -import org.gradle.internal.snapshot.impl.ImplementationSnapshot; - -public abstract class AbstractTaskExecution implements TaskExecution { - - private final ImplementationSnapshot implementation; - private final ImmutableList additionalImplementations; - private final ImmutableSortedMap inputProperties; - - public AbstractTaskExecution( - ImplementationSnapshot implementation, - ImmutableList additionalImplementations, - ImmutableSortedMap inputProperties - ) { - this.implementation = implementation; - this.additionalImplementations = additionalImplementations; - this.inputProperties = inputProperties; - } - - @Override - public ImplementationSnapshot getImplementation() { - return implementation; - } - - @Override - public ImmutableList getAdditionalImplementations() { - return additionalImplementations; - } - - @Override - public ImmutableSortedMap getInputProperties() { - return inputProperties; - } - -} diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/changedetection/state/TaskExecution.java b/subprojects/core/src/main/java/org/gradle/api/internal/changedetection/state/TaskExecution.java deleted file mode 100644 index dd86768f676d6..0000000000000 --- a/subprojects/core/src/main/java/org/gradle/api/internal/changedetection/state/TaskExecution.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright 2011 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.gradle.api.internal.changedetection.state; - -import org.gradle.internal.execution.history.ExecutionState; - -/** - * The state for a single task execution. - */ -public interface TaskExecution extends ExecutionState { - -} From 63aced5edc1b53bf7b1495c3ed7bb3d9b56be9c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=B3r=C3=A1nt=20Pint=C3=A9r?= Date: Tue, 5 Mar 2019 15:19:21 +0100 Subject: [PATCH 338/853] Use standard ExecutionStateChanges types --- .../transform/DefaultTransformerInvoker.java | 67 ++++--------------- .../changes/ExecutionStateChanges.java | 1 + 2 files changed, 14 insertions(+), 54 deletions(-) diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvoker.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvoker.java index ae150866ba0cc..acd51fba196fb 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvoker.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvoker.java @@ -29,23 +29,20 @@ import org.gradle.caching.internal.origin.OriginMetadata; import org.gradle.internal.Try; import org.gradle.internal.UncheckedException; -import org.gradle.internal.change.Change; -import org.gradle.internal.change.ChangeVisitor; -import org.gradle.internal.change.SummarizingChangeContainer; import org.gradle.internal.classloader.ClassLoaderHierarchyHasher; import org.gradle.internal.execution.CacheHandler; import org.gradle.internal.execution.ExecutionOutcome; import org.gradle.internal.execution.UnitOfWork; import org.gradle.internal.execution.WorkExecutor; import org.gradle.internal.execution.history.AfterPreviousExecutionState; +import org.gradle.internal.execution.history.BeforeExecutionState; import org.gradle.internal.execution.history.ExecutionHistoryStore; -import org.gradle.internal.execution.history.changes.AbstractFingerprintChanges; +import org.gradle.internal.execution.history.changes.DefaultExecutionStateChanges; import org.gradle.internal.execution.history.changes.ExecutionStateChanges; -import org.gradle.internal.execution.history.changes.InputFileChanges; +import org.gradle.internal.execution.history.impl.DefaultBeforeExecutionState; import org.gradle.internal.execution.impl.steps.UpToDateResult; import org.gradle.internal.file.TreeType; import org.gradle.internal.fingerprint.CurrentFileCollectionFingerprint; -import org.gradle.internal.fingerprint.FileCollectionFingerprint; import org.gradle.internal.fingerprint.FileCollectionFingerprinter; import org.gradle.internal.fingerprint.FileCollectionFingerprinterRegistry; import org.gradle.internal.fingerprint.OutputNormalizer; @@ -374,11 +371,17 @@ public void persistResult(ImmutableSortedMap getChangesSincePreviousExecution() { - return executionHistoryStore.load(identityString).map(previous -> { + Optional afterPreviousExecutionState = executionHistoryStore.load(identityString); + return afterPreviousExecutionState.map(previous -> { ImmutableSortedMap outputsBeforeExecution = snapshotOutputs(); - InputFileChanges inputFileChanges = new InputFileChanges(previous.getInputFileProperties(), inputFileFingerprints); - AllOutputFileChanges outputFileChanges = new AllOutputFileChanges(previous.getOutputFileProperties(), outputsBeforeExecution); - return new TransformerExecutionStateChanges(inputFileChanges, outputFileChanges, previous); + BeforeExecutionState current = new DefaultBeforeExecutionState( + previous.getImplementation(), + previous.getAdditionalImplementations(), + previous.getInputProperties(), + inputFileFingerprints, + outputsBeforeExecution + ); + return new DefaultExecutionStateChanges(previous, current, this); }); } @@ -417,38 +420,6 @@ public String getDisplayName() { return transformer.getDisplayName() + ": " + inputArtifact; } - private class TransformerExecutionStateChanges implements ExecutionStateChanges { - private final InputFileChanges inputFileChanges; - private final AllOutputFileChanges outputFileChanges; - private final AfterPreviousExecutionState afterPreviousExecutionState; - - public TransformerExecutionStateChanges(InputFileChanges inputFileChanges, AllOutputFileChanges outputFileChanges, AfterPreviousExecutionState afterPreviousExecutionState) { - this.inputFileChanges = inputFileChanges; - this.outputFileChanges = outputFileChanges; - this.afterPreviousExecutionState = afterPreviousExecutionState; - } - - @Override - public Iterable getInputFilesChanges() { - return ImmutableList.of(); - } - - @Override - public void visitAllChanges(ChangeVisitor visitor) { - new SummarizingChangeContainer(inputFileChanges, outputFileChanges).accept(visitor); - } - - @Override - public boolean isRebuildRequired() { - return true; - } - - @Override - public AfterPreviousExecutionState getPreviousExecution() { - return afterPreviousExecutionState; - } - } - private class TransformerExecutionBuildCacheKey implements BuildCacheKey { private final HashCode hashCode; @@ -468,18 +439,6 @@ public String getDisplayName() { } } - private static class AllOutputFileChanges extends AbstractFingerprintChanges { - - public AllOutputFileChanges(ImmutableSortedMap previous, ImmutableSortedMap current) { - super(previous, current, "Output"); - } - - @Override - public boolean accept(ChangeVisitor visitor) { - return accept(visitor, true); - } - } - private static class ImmutableTransformationWorkspaceIdentity implements TransformationWorkspaceIdentity { private final String inputArtifactPath; private final HashCode inputArtifactHash; diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/ExecutionStateChanges.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/ExecutionStateChanges.java index ca6eb025164f0..81be7ee635260 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/ExecutionStateChanges.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/ExecutionStateChanges.java @@ -45,5 +45,6 @@ public interface ExecutionStateChanges { /** * The base execution the changes are calculated against. */ + // TODO Use AfterPreviousExecutionState from context instead AfterPreviousExecutionState getPreviousExecution(); } From 9fb56e7eb39e4e54525d7c198822154acbf03541 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=B3r=C3=A1nt=20Pint=C3=A9r?= Date: Tue, 5 Mar 2019 16:41:49 +0100 Subject: [PATCH 339/853] Use standard ExecutionStates --- .../transform/DefaultTransformerInvoker.java | 135 ++++++++++-------- .../DefaultTransformerInvokerTest.groovy | 2 +- .../transform/WorkExecutorTestFixture.java | 5 +- 3 files changed, 77 insertions(+), 65 deletions(-) diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvoker.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvoker.java index acd51fba196fb..d3dbe970739bc 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvoker.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvoker.java @@ -73,6 +73,13 @@ import java.util.stream.Stream; public class DefaultTransformerInvoker implements TransformerInvoker { + private static final String INPUT_ARTIFACT_PROPERTY_NAME = "inputArtifact"; + private static final String DEPENDENCIES_PROPERTY_NAME = "inputArtifactDependencies"; + private static final String SECONDARY_INPUTS_HASH_PROPERTY_NAME = "inputPropertiesHash"; + private static final String OUTPUT_DIRECTORY_PROPERTY_NAME = "outputDirectory"; + private static final String RESULTS_FILE_PROPERTY_NAME = "resultsFile"; + private static final String INPUT_FILE_PATH_PREFIX = "i/"; + private static final String OUTPUT_FILE_PATH_PREFIX = "o/"; private final FileSystemSnapshotter fileSystemSnapshotter; private final WorkExecutor workExecutor; @@ -108,22 +115,38 @@ public Try> invoke(Transformer transformer, File inputArtifa FileCollectionFingerprinter inputArtifactFingerprinter = fingerprinterRegistry.getFingerprinter(transformer.getInputArtifactNormalizer()); String normalizedInputPath = inputArtifactFingerprinter.normalizePath(inputArtifactSnapshot); TransformationWorkspaceIdentity identity = getTransformationIdentity(producerProject, inputArtifactSnapshot, normalizedInputPath, transformer, dependenciesFingerprint); - return workspaceProvider.withWorkspace(identity, (identityString, workspace) -> { + return workspaceProvider.withWorkspace(identity, (identityStr, workspace) -> { return fireTransformListeners(transformer, subject, () -> { + String identityString = "transform/" + identityStr; + ExecutionHistoryStore executionHistoryStore = workspaceProvider.getExecutionHistoryStore(); + FileCollectionFingerprinter outputFingerprinter = fingerprinterRegistry.getFingerprinter(OutputNormalizer.class); + + AfterPreviousExecutionState afterPreviousExecutionState = executionHistoryStore.load(identityString).orElse(null); + ImplementationSnapshot implementationSnapshot = ImplementationSnapshot.of(transformer.getImplementationClass(), classLoaderHierarchyHasher); CurrentFileCollectionFingerprint inputArtifactFingerprint = inputArtifactFingerprinter.fingerprint(ImmutableList.of(inputArtifactSnapshot)); + ImmutableSortedMap inputFingerprints = snapshotInputs(transformer); + ImmutableSortedMap outputsBeforeExecution = snapshotOutputs(outputFingerprinter, fileCollectionFactory, workspace); + ImmutableSortedMap inputFileFingerprints = createInputFileFingerprints(inputArtifactFingerprint, dependenciesFingerprint); + BeforeExecutionState beforeExecutionState = new DefaultBeforeExecutionState( + implementationSnapshot, + ImmutableList.of(), + inputFingerprints, + inputFileFingerprints, + outputsBeforeExecution + ); + TransformerExecution execution = new TransformerExecution( transformer, - implementationSnapshot, + afterPreviousExecutionState, + beforeExecutionState, workspace, identityString, - workspaceProvider.getExecutionHistoryStore(), + executionHistoryStore, fileCollectionFactory, inputArtifact, - inputArtifactFingerprint, dependencies, - dependenciesFingerprint, - fingerprinterRegistry.getFingerprinter(OutputNormalizer.class) + outputFingerprinter ); UpToDateResult outcome = workExecutor.execute(execution); return execution.getResult(outcome); @@ -180,67 +203,43 @@ private Try> fireTransformListeners(Transformer transformer, } private static class TransformerExecution implements UnitOfWork { - private static final String INPUT_ARTIFACT_PROPERTY_NAME = "inputArtifact"; - private static final String DEPENDENCIES_PROPERTY_NAME = "inputArtifactDependencies"; - private static final String SECONDARY_INPUTS_HASH_PROPERTY_NAME = "inputPropertiesHash"; - private static final String OUTPUT_DIRECTORY_PROPERTY_NAME = "outputDirectory"; - private static final String RESULTS_FILE_PROPERTY_NAME = "resultsFile"; - private static final String INPUT_FILE_PATH_PREFIX = "i/"; - private static final String OUTPUT_FILE_PATH_PREFIX = "o/"; - private final Transformer transformer; - private final ImplementationSnapshot implementationSnapshot; + private final AfterPreviousExecutionState afterPreviousExecutionState; + private final BeforeExecutionState beforeExecutionState; private final TransformationWorkspace workspace; private final File inputArtifact; private final String identityString; private final ExecutionHistoryStore executionHistoryStore; private final FileCollectionFactory fileCollectionFactory; private final ArtifactTransformDependencies dependencies; - private final ImmutableSortedMap inputSnapshots; - private final ImmutableSortedMap inputFileFingerprints; private final FileCollectionFingerprinter outputFingerprinter; private final Timer executionTimer; public TransformerExecution( Transformer transformer, - ImplementationSnapshot implementationSnapshot, + @Nullable AfterPreviousExecutionState afterPreviousExecutionState, + BeforeExecutionState beforeExecutionState, TransformationWorkspace workspace, String identityString, ExecutionHistoryStore executionHistoryStore, FileCollectionFactory fileCollectionFactory, File inputArtifact, - CurrentFileCollectionFingerprint inputArtifactFingerprint, ArtifactTransformDependencies dependencies, - CurrentFileCollectionFingerprint dependenciesFingerprint, FileCollectionFingerprinter outputFingerprinter ) { - this.implementationSnapshot = implementationSnapshot; + this.afterPreviousExecutionState = afterPreviousExecutionState; + this.beforeExecutionState = beforeExecutionState; this.fileCollectionFactory = fileCollectionFactory; this.inputArtifact = inputArtifact; this.transformer = transformer; this.workspace = workspace; - this.identityString = "transform/" + identityString; + this.identityString = identityString; this.executionHistoryStore = executionHistoryStore; this.dependencies = dependencies; - this.inputSnapshots = ImmutableSortedMap.of( - // Emulate secondary inputs as a single property for now - SECONDARY_INPUTS_HASH_PROPERTY_NAME, ImplementationSnapshot.of("secondary inputs", transformer.getSecondaryInputHash()) - ); - this.inputFileFingerprints = createInputFileFingerprints(inputArtifactFingerprint, dependenciesFingerprint); this.outputFingerprinter = outputFingerprinter; this.executionTimer = Time.startTimer(); } - private static ImmutableSortedMap createInputFileFingerprints( - CurrentFileCollectionFingerprint inputArtifactFingerprint, - CurrentFileCollectionFingerprint dependenciesFingerprint - ) { - ImmutableSortedMap.Builder builder = ImmutableSortedMap.naturalOrder(); - builder.put(INPUT_ARTIFACT_PROPERTY_NAME, inputArtifactFingerprint); - builder.put(DEPENDENCIES_PROPERTY_NAME, dependenciesFingerprint); - return builder.build(); - } - @Override public ExecutionOutcome execute() { File outputDir = workspace.getOutputDirectory(); @@ -326,11 +325,11 @@ public void outputsRemovedAfterFailureToLoadFromCache() { @Override public CacheHandler createCacheHandler() { Hasher hasher = Hashing.newHasher(); - for (Map.Entry entry : inputSnapshots.entrySet()) { + for (Map.Entry entry : beforeExecutionState.getInputProperties().entrySet()) { hasher.putString(entry.getKey()); entry.getValue().appendToHasher(hasher); } - for (Map.Entry entry : inputFileFingerprints.entrySet()) { + for (Map.Entry entry : beforeExecutionState.getInputFileProperties().entrySet()) { hasher.putString(entry.getKey()); hasher.putHash(entry.getValue().getHash()); } @@ -359,10 +358,10 @@ public void persistResult(ImmutableSortedMap getChangesSincePreviousExecution() { - Optional afterPreviousExecutionState = executionHistoryStore.load(identityString); - return afterPreviousExecutionState.map(previous -> { - ImmutableSortedMap outputsBeforeExecution = snapshotOutputs(); - BeforeExecutionState current = new DefaultBeforeExecutionState( - previous.getImplementation(), - previous.getAdditionalImplementations(), - previous.getInputProperties(), - inputFileFingerprints, - outputsBeforeExecution - ); - return new DefaultExecutionStateChanges(previous, current, this); - }); + if (afterPreviousExecutionState == null) { + return Optional.empty(); + } else { + return Optional.of(new DefaultExecutionStateChanges(afterPreviousExecutionState, beforeExecutionState, this)); + } } @Override @@ -393,15 +385,7 @@ public Optional> getChangingOutputs() { @Override public ImmutableSortedMap snapshotAfterOutputsGenerated() { - return snapshotOutputs(); - } - - private ImmutableSortedMap snapshotOutputs() { - CurrentFileCollectionFingerprint outputFingerprint = outputFingerprinter.fingerprint(fileCollectionFactory.fixed(workspace.getOutputDirectory())); - CurrentFileCollectionFingerprint resultsFileFingerprint = outputFingerprinter.fingerprint(fileCollectionFactory.fixed(workspace.getResultsFile())); - return ImmutableSortedMap.of( - OUTPUT_DIRECTORY_PROPERTY_NAME, outputFingerprint, - RESULTS_FILE_PROPERTY_NAME, resultsFileFingerprint); + return snapshotOutputs(outputFingerprinter, fileCollectionFactory, workspace); } @Override @@ -439,6 +423,31 @@ public String getDisplayName() { } } + private static ImmutableSortedMap createInputFileFingerprints( + CurrentFileCollectionFingerprint inputArtifactFingerprint, + CurrentFileCollectionFingerprint dependenciesFingerprint + ) { + ImmutableSortedMap.Builder builder = ImmutableSortedMap.naturalOrder(); + builder.put(INPUT_ARTIFACT_PROPERTY_NAME, inputArtifactFingerprint); + builder.put(DEPENDENCIES_PROPERTY_NAME, dependenciesFingerprint); + return builder.build(); + } + + private static ImmutableSortedMap snapshotInputs(Transformer transformer) { + return ImmutableSortedMap.of( + // Emulate secondary inputs as a single property for now + SECONDARY_INPUTS_HASH_PROPERTY_NAME, ImplementationSnapshot.of("secondary inputs", transformer.getSecondaryInputHash()) + ); + } + + private static ImmutableSortedMap snapshotOutputs(FileCollectionFingerprinter outputFingerprinter, FileCollectionFactory fileCollectionFactory, TransformationWorkspace workspace) { + CurrentFileCollectionFingerprint outputFingerprint = outputFingerprinter.fingerprint(fileCollectionFactory.fixed(workspace.getOutputDirectory())); + CurrentFileCollectionFingerprint resultsFileFingerprint = outputFingerprinter.fingerprint(fileCollectionFactory.fixed(workspace.getResultsFile())); + return ImmutableSortedMap.of( + OUTPUT_DIRECTORY_PROPERTY_NAME, outputFingerprint, + RESULTS_FILE_PROPERTY_NAME, resultsFileFingerprint); + } + private static class ImmutableTransformationWorkspaceIdentity implements TransformationWorkspaceIdentity { private final String inputArtifactPath; private final HashCode inputArtifactHash; diff --git a/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvokerTest.groovy b/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvokerTest.groovy index b3d463f4a3906..17c16b084cf0b 100644 --- a/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvokerTest.groovy +++ b/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvokerTest.groovy @@ -49,12 +49,12 @@ import java.util.function.BiFunction class DefaultTransformerInvokerTest extends AbstractProjectBuilderSpec { - def workExecutorTestFixture = new WorkExecutorTestFixture() def immutableTransformsStoreDirectory = temporaryFolder.file("output") def mutableTransformsStoreDirectory = temporaryFolder.file("child/build/transforms") def fileSystemMirror = new DefaultFileSystemMirror(new DefaultWellKnownFileLocations([])) + def workExecutorTestFixture = new WorkExecutorTestFixture(fileSystemMirror) def fileSystemSnapshotter = new DefaultFileSystemSnapshotter(TestFiles.fileHasher(), new StringInterner(), TestFiles.fileSystem(), fileSystemMirror) def executionHistoryStore = new TestExecutionHistoryStore() diff --git a/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/WorkExecutorTestFixture.java b/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/WorkExecutorTestFixture.java index a264b352ddcae..656eff0c8bd96 100644 --- a/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/WorkExecutorTestFixture.java +++ b/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/WorkExecutorTestFixture.java @@ -31,6 +31,7 @@ import org.gradle.internal.scopeids.id.BuildInvocationScopeId; import org.gradle.internal.service.scopes.ExecutionGradleServices; import org.gradle.internal.snapshot.FileSystemSnapshot; +import org.gradle.internal.snapshot.impl.DefaultFileSystemMirror; import javax.annotation.Nullable; import java.io.File; @@ -68,15 +69,17 @@ public void close() { private BuildCancellationToken cancellationToken = new DefaultBuildCancellationToken(); private final WorkExecutor workExecutor; - WorkExecutorTestFixture() { + WorkExecutorTestFixture(DefaultFileSystemMirror fileSystemMirror) { BuildCacheCommandFactory buildCacheCommandFactory = null; OutputChangeListener outputChangeListener = new OutputChangeListener() { @Override public void beforeOutputChange() { + fileSystemMirror.beforeOutputChange(); } @Override public void beforeOutputChange(Iterable affectedOutputPaths) { + fileSystemMirror.beforeOutputChange(affectedOutputPaths); } }; OutputFilesRepository outputFilesRepository = new OutputFilesRepository() { From 3a57b9cda309ce5f8778bb9e821716b2743b680c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=B3r=C3=A1nt=20Pint=C3=A9r?= Date: Tue, 5 Mar 2019 23:26:14 +0100 Subject: [PATCH 340/853] Fix ignored added outputs for transforms --- .../execution/ExecuteActionsTaskExecuter.java | 3 ++- ...ResolveIncrementalChangesTaskExecuter.java | 4 +++- .../transform/DefaultTransformerInvoker.java | 4 +++- .../changes/DefaultExecutionStateChanges.java | 5 +++-- .../history/changes/OutputFileChanges.java | 19 +++++++++++++++++-- .../steps/IncrementalExecutionTest.groovy | 3 ++- 6 files changed, 30 insertions(+), 8 deletions(-) diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuter.java b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuter.java index 3ae6d2acf32fe..463b15a120eab 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuter.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuter.java @@ -50,6 +50,7 @@ import org.gradle.internal.execution.history.OutputFilesRepository; import org.gradle.internal.execution.history.changes.ExecutionStateChanges; import org.gradle.internal.execution.history.changes.OutputFileChanges; +import org.gradle.internal.execution.history.changes.OutputFileChanges.OutputHandling; import org.gradle.internal.execution.impl.OutputFilterUtil; import org.gradle.internal.execution.impl.steps.UpToDateResult; import org.gradle.internal.fingerprint.CurrentFileCollectionFingerprint; @@ -289,7 +290,7 @@ public void accept(BeforeExecutionState execution) { private boolean hasAnyOutputFileChanges(ImmutableSortedMap previous, ImmutableSortedMap current) { return !previous.keySet().equals(current.keySet()) - || new OutputFileChanges(previous, current).hasAnyChanges(); + || new OutputFileChanges(previous, current, OutputHandling.IGNORE_ADDED).hasAnyChanges(); } @Override diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/ResolveIncrementalChangesTaskExecuter.java b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/ResolveIncrementalChangesTaskExecuter.java index e7da7329e03b8..f1d362be1a996 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/ResolveIncrementalChangesTaskExecuter.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/ResolveIncrementalChangesTaskExecuter.java @@ -34,6 +34,8 @@ import java.util.function.Function; import java.util.function.Supplier; +import static org.gradle.internal.execution.history.changes.OutputFileChanges.OutputHandling.IGNORE_ADDED; + /** * Resolves the incremental changes to pass to the task actions. * @@ -72,7 +74,7 @@ public String getDisplayName() { // The value is cached, so we should be okay to call this many times return task.toString(); } - }); + }, IGNORE_ADDED); } }).orElse(null); } diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvoker.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvoker.java index d3dbe970739bc..bb109dc86b989 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvoker.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvoker.java @@ -72,6 +72,8 @@ import java.util.function.Supplier; import java.util.stream.Stream; +import static org.gradle.internal.execution.history.changes.OutputFileChanges.OutputHandling.DETECT_ADDED; + public class DefaultTransformerInvoker implements TransformerInvoker { private static final String INPUT_ARTIFACT_PROPERTY_NAME = "inputArtifact"; private static final String DEPENDENCIES_PROPERTY_NAME = "inputArtifactDependencies"; @@ -373,7 +375,7 @@ public Optional getChangesSincePreviousExecution() { if (afterPreviousExecutionState == null) { return Optional.empty(); } else { - return Optional.of(new DefaultExecutionStateChanges(afterPreviousExecutionState, beforeExecutionState, this)); + return Optional.of(new DefaultExecutionStateChanges(afterPreviousExecutionState, beforeExecutionState, this, DETECT_ADDED)); } } diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/DefaultExecutionStateChanges.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/DefaultExecutionStateChanges.java index fce75c1c9383f..f6bb5609574a0 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/DefaultExecutionStateChanges.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/DefaultExecutionStateChanges.java @@ -35,7 +35,7 @@ public class DefaultExecutionStateChanges implements ExecutionStateChanges { private final ChangeContainer allChanges; private final ChangeContainer rebuildTriggeringChanges; - public DefaultExecutionStateChanges(AfterPreviousExecutionState lastExecution, BeforeExecutionState thisExecution, Describable executable) { + public DefaultExecutionStateChanges(AfterPreviousExecutionState lastExecution, BeforeExecutionState thisExecution, Describable executable, OutputFileChanges.OutputHandling outputHandling) { this.previousExecution = lastExecution; // Capture changes in execution outcome @@ -79,7 +79,8 @@ public DefaultExecutionStateChanges(AfterPreviousExecutionState lastExecution, B executable); OutputFileChanges uncachedOutputChanges = new OutputFileChanges( lastExecution.getOutputFileProperties(), - thisExecution.getOutputFileProperties()); + thisExecution.getOutputFileProperties(), + outputHandling); ChangeContainer outputFileChanges = caching(uncachedOutputChanges); this.allChanges = errorHandling(executable, new SummarizingChangeContainer(previousSuccessState, implementationChanges, inputPropertyChanges, inputPropertyValueChanges, outputFilePropertyChanges, outputFileChanges, inputFilePropertyChanges, inputFileChanges)); diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/OutputFileChanges.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/OutputFileChanges.java index cfba7cc5e5d7a..4afefad6ca3e8 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/OutputFileChanges.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/OutputFileChanges.java @@ -24,8 +24,11 @@ public class OutputFileChanges extends AbstractFingerprintChanges { - public OutputFileChanges(ImmutableSortedMap previous, ImmutableSortedMap current) { + private final OutputHandling outputHandling; + + public OutputFileChanges(ImmutableSortedMap previous, ImmutableSortedMap current, OutputHandling outputHandling) { super(previous, current, "Output"); + this.outputHandling = outputHandling; } public boolean hasAnyChanges() { @@ -36,6 +39,18 @@ public boolean hasAnyChanges() { @Override public boolean accept(ChangeVisitor visitor) { - return accept(visitor, false); + return accept(visitor, outputHandling == OutputHandling.DETECT_ADDED); + } + + public enum OutputHandling { + /** + * Handle added outputs as changes. + */ + DETECT_ADDED, + + /** + * Ignore added outputs. + */ + IGNORE_ADDED } } diff --git a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/impl/steps/IncrementalExecutionTest.groovy b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/impl/steps/IncrementalExecutionTest.groovy index f956ec3710fd9..af97ffeaf1b4c 100644 --- a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/impl/steps/IncrementalExecutionTest.groovy +++ b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/impl/steps/IncrementalExecutionTest.groovy @@ -63,6 +63,7 @@ import java.util.function.BooleanSupplier import static org.gradle.internal.execution.ExecutionOutcome.EXECUTED import static org.gradle.internal.execution.ExecutionOutcome.UP_TO_DATE +import static org.gradle.internal.execution.history.changes.OutputFileChanges.OutputHandling.IGNORE_ADDED class IncrementalExecutionTest extends Specification { @@ -814,7 +815,7 @@ class IncrementalExecutionTest extends Specification { changes = executionHistoryStore.load(getIdentity()).map { previous -> def outputsBefore = snapshotOutputs() def beforeExecutionState = new DefaultBeforeExecutionState(implementationSnapshot, additionalImplementationSnapshots, snapshotInputProperties(), snapshotInputFiles(), outputsBefore) - return new DefaultExecutionStateChanges(previous, beforeExecutionState, this) + return new DefaultExecutionStateChanges(previous, beforeExecutionState, this, IGNORE_ADDED) } } From b8cc4000ffc1fe20c255d78b63ce0c1879d8b772 Mon Sep 17 00:00:00 2001 From: "James X. Nelson" Date: Sat, 12 Jan 2019 23:21:22 -0800 Subject: [PATCH 341/853] Issue 7398: groovy + java-library plugin compatibility. Signed-off-by: James X. Nelson --- .../docs/userguide/java_library_plugin.adoc | 5 +- .../groovy/GroovyPluginIntegrationTest.groovy | 99 +++++++++++++++++++ .../gradle/api/plugins/GroovyBasePlugin.java | 29 +++++- 3 files changed, 129 insertions(+), 4 deletions(-) create mode 100644 subprojects/plugins/src/integTest/groovy/org/gradle/groovy/GroovyPluginIntegrationTest.groovy diff --git a/subprojects/docs/src/docs/userguide/java_library_plugin.adoc b/subprojects/docs/src/docs/userguide/java_library_plugin.adoc index b97a17ac3fd1b..28971172240bd 100644 --- a/subprojects/docs/src/docs/userguide/java_library_plugin.adoc +++ b/subprojects/docs/src/docs/userguide/java_library_plugin.adoc @@ -237,15 +237,14 @@ The role of each configuration is described in the following tables: [[sec:java_library_known_issues_compat]] === Compatibility with other plugins -At the moment the Java Library plugin is only wired to behave correctly with the `java` plugin. Other plugins, such as the Groovy plugin, may not behave correctly. In particular, if the Groovy plugin is used in addition to the `java-library` plugin, then consumers may not get the Groovy classes when they consume the library. To workaround this, you need to explicitly wire the Groovy compile dependency, like this: +At the moment, the Java Library plugin is wired to behave correctly with the `java`, `groovy` and `kotlin` plugins. In Gradle 5.3 or early, some plugins, such as the Groovy plugin, may not behave correctly. In particular, if the Groovy plugin is used in addition to the `java-library` plugin, then consumers may not get the Groovy classes when they consume the library. To workaround this, you need to explicitly wire the Groovy compile dependency, like this: -.Configuring the Groovy plugin to work with Java Library +.Configuring the Groovy plugin to work with Java Library in Gradle 5.3 or earlier ==== include::sample[dir="java-library/with-groovy/groovy",files="a/build.gradle[tags=configure-groovy]"] include::sample[dir="java-library/with-groovy/kotlin",files="a/build.gradle.kts[tags=configure-groovy]"] ==== - [[sec:java_library_known_issues_memory]] === Increased memory usage for consumers diff --git a/subprojects/plugins/src/integTest/groovy/org/gradle/groovy/GroovyPluginIntegrationTest.groovy b/subprojects/plugins/src/integTest/groovy/org/gradle/groovy/GroovyPluginIntegrationTest.groovy new file mode 100644 index 0000000000000..8be0400db04c5 --- /dev/null +++ b/subprojects/plugins/src/integTest/groovy/org/gradle/groovy/GroovyPluginIntegrationTest.groovy @@ -0,0 +1,99 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.gradle.groovy + + +import org.gradle.integtests.fixtures.AbstractIntegrationSpec +import spock.lang.Issue +import spock.lang.Unroll + +class GroovyPluginIntegrationTest extends AbstractIntegrationSpec { + + private static final boolean javaLibUsesClasses = false // current behavior as of gradle 5.3 + private static final String javaLibUsageMessage = javaLibUsesClasses ? "classes" : "jar" + + @Issue("https://github.com/gradle/gradle/issues/7398") + @Unroll + def "groovy #classesOrJar output is transitive when #consumerPlugin plugin adds a project dependency to #consumerConf"( + String consumerPlugin, String consumerConf, boolean groovyWithJavaLib, String classesOrJar) { + given: + multiProjectBuild('issue7398', ['groovyLib', 'javaLib']) { + file('groovyLib').with { + file('src/main/groovy/GroovyClass.groovy') << "public class GroovyClass {}" + file('build.gradle') << """ + ${groovyWithJavaLib ? "apply plugin: 'java-library'" : ''} + apply plugin: 'groovy' + dependencies { + compileOnly localGroovy() + } + """ + } + file('javaLib').with { + // Hm... if we extend GroovyClass, compilation will fail because we did not make localGroovy() transitive, + // and our GroovyClass actually extends groovy.lang.GroovyObject, which fails when referenced as a supertype. + // We ignore this implementation detail by referencing GroovyClass as a field; (composition +1, inheritance -1). + file('src/main/java/JavaClass.java') << "public class JavaClass { GroovyClass reference; }" + file('build.gradle') << """ + apply plugin: '$consumerPlugin' + dependencies { + $consumerConf project(':groovyLib') + } + + task assertDependsOnGroovyLib { + dependsOn compileJava + doLast { + ${ classesOrJar == 'classes' ? ''' + def classesDirs = ['compileJava', 'compileGroovy'] + .collect { project(':groovyLib').tasks[it].destinationDir } + + assert compileJava.classpath.files.size() == 2 + assert compileJava.classpath.files.containsAll(classesDirs) + ''' : ''' + def jarFile = project(':groovyLib').tasks.jar.archiveFile.get().asFile + + assert compileJava.classpath.files.size() == 1 + assert compileJava.classpath.files.contains(jarFile) + def openJar = new java.util.jar.JarFile(jarFile) + assert openJar.getJarEntry("GroovyClass.class") + openJar.close() + ''' + } + } + } + """ + } + } + expect: + succeeds 'assertDependsOnGroovyLib' + + where: + // whenever groovy+java-library plugins are used, classesOrJar will be "classes", + // and when it is not, it will be "jar". We use two variables for nice Unrolled feature names. + // As of 5.3, these all actually assert the same thing: that jars are used on compile classpath, as that is current default. + consumerPlugin | consumerConf | groovyWithJavaLib | classesOrJar + 'java-library' | 'api' | javaLibUsesClasses | javaLibUsageMessage + 'java-library' | 'api' | false | "jar" + 'java-library' | 'compile' | javaLibUsesClasses | javaLibUsageMessage + 'java-library' | 'compile' | false | "jar" + 'java-library' | 'implementation' | javaLibUsesClasses | javaLibUsageMessage + 'java-library' | 'implementation' | false | "jar" + + 'java' | 'compile' | javaLibUsesClasses | javaLibUsageMessage + 'java' | 'compile' | false | "jar" + 'java' | 'implementation' | javaLibUsesClasses | javaLibUsageMessage + 'java' | 'implementation' | false | "jar" + } +} diff --git a/subprojects/plugins/src/main/java/org/gradle/api/plugins/GroovyBasePlugin.java b/subprojects/plugins/src/main/java/org/gradle/api/plugins/GroovyBasePlugin.java index f126608368b09..f4af97d05c956 100644 --- a/subprojects/plugins/src/main/java/org/gradle/api/plugins/GroovyBasePlugin.java +++ b/subprojects/plugins/src/main/java/org/gradle/api/plugins/GroovyBasePlugin.java @@ -16,11 +16,16 @@ package org.gradle.api.plugins; +import com.google.common.collect.ImmutableMap; import org.gradle.api.Action; +import org.gradle.api.NamedDomainObjectContainer; import org.gradle.api.Plugin; import org.gradle.api.Project; import org.gradle.api.Task; import org.gradle.api.Transformer; +import org.gradle.api.artifacts.Configuration; +import org.gradle.api.artifacts.ConfigurationVariant; +import org.gradle.api.artifacts.type.ArtifactTypeDefinition; import org.gradle.api.file.ConfigurableFileCollection; import org.gradle.api.file.FileCollection; import org.gradle.api.file.FileTreeElement; @@ -106,7 +111,7 @@ public boolean isSatisfiedBy(FileTreeElement element) { final Provider compileTask = project.getTasks().register(sourceSet.getCompileTaskName("groovy"), GroovyCompile.class, new Action() { @Override - public void execute(GroovyCompile compile) { + public void execute(final GroovyCompile compile) { SourceSetUtil.configureForSourceSet(sourceSet, groovySourceSet.getGroovy(), compile, compile.getOptions(), project); compile.dependsOn(sourceSet.getCompileJavaTaskName()); compile.setDescription("Compiles the " + sourceSet.getName() + " Groovy source."); @@ -120,6 +125,28 @@ public CompileOptions transform(GroovyCompile groovyCompile) { } })); + if (SourceSet.MAIN_SOURCE_SET_NAME.equals(sourceSet.getName())) { + // The user has chosen to use the java-library plugin; + // add a classes variant for groovy's main sourceSet compilation, + // so default-configuration project dependencies will see groovy's output. + project.getPluginManager().withPlugin("java-library", new Action() { + @Override + public void execute(AppliedPlugin plugin) { + Configuration apiElements = project.getConfigurations().getByName(sourceSet.getApiElementsConfigurationName()); + apiElements.getOutgoing().variants(new Action>() { + @Override + public void execute(NamedDomainObjectContainer variants) { + GroovyCompile groovyCompile = compileTask.get(); + variants.maybeCreate("classes").artifact(ImmutableMap.of( + "file", groovyCompile.getDestinationDir(), + "type", ArtifactTypeDefinition.JVM_CLASS_DIRECTORY, + "builtBy", groovyCompile + )); + } + }); + } + }); + } // TODO: `classes` should be a little more tied to the classesDirs for a SourceSet so every plugin // doesn't need to do this. From d682b941ff8bebb8c31855c3ff38633a2082e1d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=B3r=C3=A1nt=20Pint=C3=A9r?= Date: Tue, 5 Mar 2019 19:03:47 +0100 Subject: [PATCH 342/853] Return some incremental execution results in an immutable way We now use TaskExecuterResult instead of TaskExecutionContext. --- ...skBuildOperationTypeIntegrationTest.groovy | 2 +- ...perationNotificationIntegrationTest.groovy | 2 +- .../internal/tasks/TaskExecuterResult.java | 24 ++++++++ .../internal/tasks/TaskExecutionContext.java | 6 -- .../internal/tasks/TaskExecutionOutcome.java | 3 +- .../DefaultTaskExecutionContext.java | 13 ----- .../execution/EventFiringTaskExecuter.java | 24 +++++++- .../execution/ExecuteActionsTaskExecuter.java | 16 ++++- .../ExecuteTaskBuildOperationResult.java | 14 ++--- .../transform/DefaultTransformerInvoker.java | 2 +- .../internal/execution/ExecutionOutcome.java | 20 ++++++- .../impl/steps/SkipUpToDateStep.java | 8 +-- .../execution/impl/steps/UpToDateResult.java | 2 +- .../execution/impl/steps/CacheStepTest.groovy | 6 +- .../execution/impl/steps/ExecutionTest.groovy | 27 ++++----- .../steps/IncrementalExecutionTest.groovy | 58 +++++++++---------- .../impl/steps/SkipUpToDateStepTest.groovy | 6 +- 17 files changed, 146 insertions(+), 87 deletions(-) diff --git a/subprojects/core/src/integTest/groovy/org/gradle/api/internal/tasks/execution/ExecuteTaskBuildOperationTypeIntegrationTest.groovy b/subprojects/core/src/integTest/groovy/org/gradle/api/internal/tasks/execution/ExecuteTaskBuildOperationTypeIntegrationTest.groovy index ab887f5f2e54b..a0b158730e84c 100644 --- a/subprojects/core/src/integTest/groovy/org/gradle/api/internal/tasks/execution/ExecuteTaskBuildOperationTypeIntegrationTest.groovy +++ b/subprojects/core/src/integTest/groovy/org/gradle/api/internal/tasks/execution/ExecuteTaskBuildOperationTypeIntegrationTest.groovy @@ -44,7 +44,7 @@ class ExecuteTaskBuildOperationTypeIntegrationTest extends AbstractIntegrationSp op.result.skipMessage == "UP-TO-DATE" op.result.actionable == false op.result.originBuildInvocationId == null - op.result.upToDateMessages == null + op.result.upToDateMessages == [] } def "emits operation result for failed task execution"() { diff --git a/subprojects/core/src/integTest/groovy/org/gradle/internal/operations/notify/BuildOperationNotificationIntegrationTest.groovy b/subprojects/core/src/integTest/groovy/org/gradle/internal/operations/notify/BuildOperationNotificationIntegrationTest.groovy index b05d4eb101243..18650da17e927 100644 --- a/subprojects/core/src/integTest/groovy/org/gradle/internal/operations/notify/BuildOperationNotificationIntegrationTest.groovy +++ b/subprojects/core/src/integTest/groovy/org/gradle/internal/operations/notify/BuildOperationNotificationIntegrationTest.groovy @@ -90,7 +90,7 @@ class BuildOperationNotificationIntegrationTest extends AbstractIntegrationSpec notifications.finished(CalculateTaskGraphBuildOperationType.Result, [excludedTaskPaths: [], requestedTaskPaths: [":t"]]) notifications.started(NotifyTaskGraphWhenReadyBuildOperationType.Details, [buildPath: ':']) notifications.started(ExecuteTaskBuildOperationType.Details, [taskPath: ":t", buildPath: ":", taskClass: "org.gradle.api.DefaultTask"]) - notifications.finished(ExecuteTaskBuildOperationType.Result, [actionable: false, originExecutionTime: null, cachingDisabledReasonMessage: "Cacheability was not determined", upToDateMessages: null, cachingDisabledReasonCategory: "UNKNOWN", skipMessage: "UP-TO-DATE", originBuildInvocationId: null]) + notifications.finished(ExecuteTaskBuildOperationType.Result, [actionable: false, originExecutionTime: null, cachingDisabledReasonMessage: "Cacheability was not determined", upToDateMessages: [], cachingDisabledReasonCategory: "UNKNOWN", skipMessage: "UP-TO-DATE", originBuildInvocationId: null]) } def "can emit notifications for nested builds"() { diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/TaskExecuterResult.java b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/TaskExecuterResult.java index c723ef40f5c25..02778f7ddb4fb 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/TaskExecuterResult.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/TaskExecuterResult.java @@ -16,17 +16,41 @@ package org.gradle.api.internal.tasks; +import com.google.common.collect.ImmutableList; import org.gradle.caching.internal.origin.OriginMetadata; +import org.gradle.internal.Try; +import org.gradle.internal.execution.ExecutionOutcome; +import java.util.List; import java.util.Optional; public interface TaskExecuterResult { + /** + * Returns the reasons for executing this task. An empty list means the task was not executed. + */ + List getExecutionReasons(); + + /** + * The outcome of executing the task. + */ + Try getOutcome(); + /** * If the execution resulted in some previous output being reused, this returns its origin metadata. */ Optional getReusedOutputOriginMetadata(); TaskExecuterResult NO_REUSED_OUTPUT = new TaskExecuterResult() { + @Override + public List getExecutionReasons() { + return ImmutableList.of(); + } + + @Override + public Try getOutcome() { + return Try.successful(ExecutionOutcome.EXECUTED_FULLY); + } + @Override public Optional getReusedOutputOriginMetadata() { return Optional.empty(); diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/TaskExecutionContext.java b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/TaskExecutionContext.java index df58620fa1158..6a1d54cacc73d 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/TaskExecutionContext.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/TaskExecutionContext.java @@ -30,7 +30,6 @@ import org.gradle.internal.operations.ExecutingBuildOperation; import javax.annotation.Nullable; -import java.util.List; import java.util.Optional; public interface TaskExecutionContext { @@ -71,11 +70,6 @@ public interface TaskExecutionContext { */ long markExecutionTime(); - @Nullable - List getUpToDateMessages(); - - void setUpToDateMessages(List upToDateMessages); - void setTaskProperties(TaskProperties properties); TaskProperties getTaskProperties(); diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/TaskExecutionOutcome.java b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/TaskExecutionOutcome.java index 673e6809a752b..2e6ecbfd4eddc 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/TaskExecutionOutcome.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/TaskExecutionOutcome.java @@ -56,7 +56,8 @@ public static TaskExecutionOutcome valueOf(ExecutionOutcome outcome) { return FROM_CACHE; case UP_TO_DATE: return UP_TO_DATE; - case EXECUTED: + case EXECUTED_INCREMENTALLY: + case EXECUTED_FULLY: return EXECUTED; default: throw new AssertionError(); diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/DefaultTaskExecutionContext.java b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/DefaultTaskExecutionContext.java index ea006868e7d08..a9e937a789577 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/DefaultTaskExecutionContext.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/DefaultTaskExecutionContext.java @@ -31,7 +31,6 @@ import org.gradle.internal.time.Timer; import javax.annotation.Nullable; -import java.util.List; import java.util.Optional; public class DefaultTaskExecutionContext implements TaskExecutionContext { @@ -45,7 +44,6 @@ public class DefaultTaskExecutionContext implements TaskExecutionContext { private TaskExecutionMode taskExecutionMode; private boolean outputRemovedBeforeExecution; private TaskOutputCachingBuildCacheKey buildCacheKey; - private List upToDateMessages; private TaskProperties properties; private boolean taskCachingEnabled; private Long executionTime; @@ -152,17 +150,6 @@ public long markExecutionTime() { return this.executionTime = executionTimer.getElapsedMillis(); } - @Override - @Nullable - public List getUpToDateMessages() { - return upToDateMessages; - } - - @Override - public void setUpToDateMessages(List upToDateMessages) { - this.upToDateMessages = upToDateMessages; - } - @Override public void setTaskProperties(TaskProperties properties) { this.properties = properties; diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/EventFiringTaskExecuter.java b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/EventFiringTaskExecuter.java index 0a3ef92644366..9e4bede1a0f6f 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/EventFiringTaskExecuter.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/EventFiringTaskExecuter.java @@ -23,12 +23,15 @@ import org.gradle.api.internal.tasks.TaskExecutionContext; import org.gradle.api.internal.tasks.TaskStateInternal; import org.gradle.api.tasks.TaskExecutionException; +import org.gradle.internal.execution.ExecutionOutcome; import org.gradle.internal.operations.BuildOperationCategory; import org.gradle.internal.operations.BuildOperationContext; import org.gradle.internal.operations.BuildOperationDescriptor; import org.gradle.internal.operations.BuildOperationExecutor; import org.gradle.internal.operations.CallableBuildOperation; +import java.util.function.Function; + public class EventFiringTaskExecuter implements TaskExecuter { private final BuildOperationExecutor buildOperationExecutor; @@ -61,7 +64,26 @@ private TaskExecuterResult executeTask(BuildOperationContext operationContext) { } TaskExecuterResult result = delegate.execute(task, state, context); - operationContext.setResult(new ExecuteTaskBuildOperationResult(state, context, result.getReusedOutputOriginMetadata().orElse(null))); + + boolean incremental = result.getOutcome() + .map(new Function() { + @Override + public Boolean apply(ExecutionOutcome executionOutcome) { + return executionOutcome == ExecutionOutcome.EXECUTED_INCREMENTALLY; + } + }).orElseMapFailure(new Function() { + @Override + public Boolean apply(Throwable throwable) { + return false; + } + }); + + operationContext.setResult(new ExecuteTaskBuildOperationResult( + state, + result.getReusedOutputOriginMetadata().orElse(null), + incremental, + result.getExecutionReasons() + )); try { taskExecutionListener.afterExecute(task, state); diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuter.java b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuter.java index 463b15a120eab..3fbe08af33d79 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuter.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuter.java @@ -35,6 +35,7 @@ import org.gradle.api.tasks.TaskExecutionException; import org.gradle.caching.BuildCacheKey; import org.gradle.caching.internal.origin.OriginMetadata; +import org.gradle.internal.Try; import org.gradle.internal.UncheckedException; import org.gradle.internal.exceptions.Contextual; import org.gradle.internal.exceptions.DefaultMultiCauseException; @@ -124,7 +125,6 @@ public void accept(Throwable failure) { } } ); - context.setUpToDateMessages(result.getOutOfDateReasons()); return new TaskExecuterResult() { @Override public Optional getReusedOutputOriginMetadata() { @@ -133,6 +133,16 @@ public Optional getReusedOutputOriginMetadata() { ? Optional.of(result.getOriginMetadata()) : Optional.empty(); } + + @Override + public Try getOutcome() { + return result.getOutcome(); + } + + @Override + public List getExecutionReasons() { + return result.getExecutionReasons(); + } }; } @@ -158,7 +168,9 @@ public ExecutionOutcome execute() { actionListener.beforeActions(task); executeActions(task, context); return task.getState().getDidWork() - ? ExecutionOutcome.EXECUTED + ? context.isTaskExecutedIncrementally() + ? ExecutionOutcome.EXECUTED_INCREMENTALLY + : ExecutionOutcome.EXECUTED_FULLY : ExecutionOutcome.UP_TO_DATE; } finally { task.getState().setExecuting(false); diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/ExecuteTaskBuildOperationResult.java b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/ExecuteTaskBuildOperationResult.java index d33ce6eea9c3f..39074f4ccaacc 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/ExecuteTaskBuildOperationResult.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/ExecuteTaskBuildOperationResult.java @@ -17,7 +17,6 @@ package org.gradle.api.internal.tasks.execution; import org.gradle.api.internal.TaskOutputCachingState; -import org.gradle.api.internal.tasks.TaskExecutionContext; import org.gradle.api.internal.tasks.TaskOutputCachingDisabledReasonCategory; import org.gradle.api.internal.tasks.TaskStateInternal; import org.gradle.caching.internal.origin.OriginMetadata; @@ -29,13 +28,15 @@ public class ExecuteTaskBuildOperationResult implements ExecuteTaskBuildOperationType.Result { private final TaskStateInternal taskState; - private final TaskExecutionContext ctx; private final OriginMetadata originMetadata; + private final boolean incremental; + private final List executionReasons; - public ExecuteTaskBuildOperationResult(TaskStateInternal taskState, TaskExecutionContext ctx, @Nullable OriginMetadata originMetadata) { + public ExecuteTaskBuildOperationResult(TaskStateInternal taskState, @Nullable OriginMetadata originMetadata, boolean incremental, List executionReasons) { this.taskState = taskState; - this.ctx = ctx; this.originMetadata = originMetadata; + this.incremental = incremental; + this.executionReasons = executionReasons; } @Nullable @@ -78,15 +79,14 @@ public String getCachingDisabledReasonCategory() { } - @Nullable @Override public List getUpToDateMessages() { - return ctx.getUpToDateMessages(); + return executionReasons; } @Override public boolean isIncremental() { - return ctx.isTaskExecutedIncrementally(); + return incremental; } } diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvoker.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvoker.java index bb109dc86b989..071667f39b6a2 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvoker.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvoker.java @@ -250,7 +250,7 @@ public ExecutionOutcome execute() { GFileUtils.deleteFileQuietly(resultsFile); ImmutableList result = transformer.transform(inputArtifact, outputDir, dependencies); writeResultsFile(outputDir, resultsFile, result); - return ExecutionOutcome.EXECUTED; + return ExecutionOutcome.EXECUTED_FULLY; } private void writeResultsFile(File outputDir, File resultsFile, ImmutableList result) { diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/ExecutionOutcome.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/ExecutionOutcome.java index 48ebd2e31e61d..ad0e550caac12 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/ExecutionOutcome.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/ExecutionOutcome.java @@ -17,7 +17,25 @@ package org.gradle.internal.execution; public enum ExecutionOutcome { + /** + * The outputs haven't been changed, because the work is already up-to-date + * (i.e. its inputs and outputs match that of the previous execution in the + * same workspace). + */ UP_TO_DATE, + + /** + * The outputs of the work have been loaded from the build cache. + */ FROM_CACHE, - EXECUTED + + /** + * The work has been executed with information about the changes that happened since the previous execution. + */ + EXECUTED_INCREMENTALLY, + + /** + * The work has been executed with no incremental change information. + */ + EXECUTED_FULLY } diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/impl/steps/SkipUpToDateStep.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/impl/steps/SkipUpToDateStep.java index 25db744fd6e99..6b0559f830a72 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/impl/steps/SkipUpToDateStep.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/impl/steps/SkipUpToDateStep.java @@ -60,7 +60,7 @@ public UpToDateResult execute(C context) { } return new UpToDateResult() { @Override - public ImmutableList getOutOfDateReasons() { + public ImmutableList getExecutionReasons() { return ImmutableList.of(); } @@ -91,11 +91,11 @@ public boolean isReused() { } private UpToDateResult executeBecause(ImmutableList reasons, C context) { - logOutOfDateReasons(reasons, context.getWork()); + logExecutionReasons(reasons, context.getWork()); SnapshotResult result = delegate.execute(context); return new UpToDateResult() { @Override - public ImmutableList getOutOfDateReasons() { + public ImmutableList getExecutionReasons() { return reasons; } @@ -121,7 +121,7 @@ public boolean isReused() { }; } - private void logOutOfDateReasons(List reasons, UnitOfWork work) { + private void logExecutionReasons(List reasons, UnitOfWork work) { if (LOGGER.isInfoEnabled()) { Formatter formatter = new Formatter(); formatter.format("%s is not up-to-date because:", StringUtils.capitalize(work.getDisplayName())); diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/impl/steps/UpToDateResult.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/impl/steps/UpToDateResult.java index 2333ed9e0f639..34ce5150bb1b3 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/impl/steps/UpToDateResult.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/impl/steps/UpToDateResult.java @@ -23,5 +23,5 @@ public interface UpToDateResult extends SnapshotResult { * A list of messages describing the first few reasons encountered that caused the work to be executed. * An empty list means the work was up-to-date and hasn't been executed. */ - ImmutableList getOutOfDateReasons(); + ImmutableList getExecutionReasons(); } diff --git a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/impl/steps/CacheStepTest.groovy b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/impl/steps/CacheStepTest.groovy index 937b20d06b7bb..dbc997e18cbe2 100644 --- a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/impl/steps/CacheStepTest.groovy +++ b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/impl/steps/CacheStepTest.groovy @@ -10,7 +10,7 @@ * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and + * See the License for the specific language governing permissions andExecutionOutcome.EXECUTED * limitations under the License. */ @@ -75,7 +75,7 @@ class CacheStepTest extends Specification { def executionResult = new CurrentSnapshotResult() { final ImmutableSortedMap finalOutputs = ImmutableSortedMap.of("test", new EmptyCurrentFileCollectionFingerprint()) final OriginMetadata originMetadata = new OriginMetadata(currentBuildId, 0) - final Try outcome = Try.successful(ExecutionOutcome.EXECUTED) + final Try outcome = Try.successful(ExecutionOutcome.EXECUTED_FULLY) final boolean reused = false } @@ -120,7 +120,7 @@ class CacheStepTest extends Specification { def executionResult = new CurrentSnapshotResult() { final ImmutableSortedMap finalOutputs = ImmutableSortedMap.of("test", new EmptyCurrentFileCollectionFingerprint()) final OriginMetadata originMetadata = new OriginMetadata(currentBuildId, 0) - final Try outcome = Try.successful(ExecutionOutcome.EXECUTED) + final Try outcome = Try.successful(ExecutionOutcome.EXECUTED_FULLY) final boolean reused = false } when: diff --git a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/impl/steps/ExecutionTest.groovy b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/impl/steps/ExecutionTest.groovy index 622e2cf305023..32e08575ed4d7 100644 --- a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/impl/steps/ExecutionTest.groovy +++ b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/impl/steps/ExecutionTest.groovy @@ -30,7 +30,7 @@ import org.gradle.internal.fingerprint.CurrentFileCollectionFingerprint import spock.lang.Specification import java.time.Duration -import java.util.function.BooleanSupplier +import java.util.function.Supplier class ExecutionTest extends Specification { @@ -42,26 +42,27 @@ class ExecutionTest extends Specification { ) ) - def "executes the unit of work"() { - def unitOfWork = new TestUnitOfWork({ -> - return true - }) + def "executes the unit of work with outcome: #outcome"() { + def unitOfWork = new TestUnitOfWork({ -> outcome }) when: def result = executionStep.execute { -> unitOfWork} then: unitOfWork.executed - result.outcome.get() == ExecutionOutcome.EXECUTED + result.outcome.get() == outcome 1 * outputChangeListener.beforeOutputChange() 0 * _ + + where: + outcome << [ExecutionOutcome.EXECUTED_FULLY, ExecutionOutcome.EXECUTED_INCREMENTALLY] } def "reports no work done"() { when: def result = executionStep.execute { -> new TestUnitOfWork({ -> - return false + return ExecutionOutcome.UP_TO_DATE }) } @@ -92,20 +93,20 @@ class ExecutionTest extends Specification { def "invalidates only changing outputs"() { def changingOutputs = ['some/location'] - def unitOfWork = new TestUnitOfWork({ -> true }, changingOutputs) + def unitOfWork = new TestUnitOfWork({ -> ExecutionOutcome.EXECUTED_FULLY }, changingOutputs) when: def result = executionStep.execute { -> unitOfWork } then: - result.outcome.get() == ExecutionOutcome.EXECUTED + result.outcome.get() == ExecutionOutcome.EXECUTED_FULLY 1 * outputChangeListener.beforeOutputChange(changingOutputs) 0 * _ } def "fails the execution when build has been cancelled"() { - def unitOfWork = new TestUnitOfWork({ -> true }) + def unitOfWork = new TestUnitOfWork({ -> ExecutionOutcome.EXECUTED_FULLY }) when: cancellationToken.cancel() @@ -121,10 +122,10 @@ class ExecutionTest extends Specification { static class TestUnitOfWork implements UnitOfWork { - private final BooleanSupplier work + private final Supplier work private final Iterable changingOutputs - TestUnitOfWork(BooleanSupplier work = { -> true}, Iterable changingOutputs = null) { + TestUnitOfWork(Supplier work, Iterable changingOutputs = null) { this.changingOutputs = changingOutputs this.work = work } @@ -134,7 +135,7 @@ class ExecutionTest extends Specification { @Override ExecutionOutcome execute() { executed = true - return work.asBoolean ? ExecutionOutcome.EXECUTED : ExecutionOutcome.UP_TO_DATE + return work.get() } @Override diff --git a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/impl/steps/IncrementalExecutionTest.groovy b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/impl/steps/IncrementalExecutionTest.groovy index af97ffeaf1b4c..3cbb9fa536fac 100644 --- a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/impl/steps/IncrementalExecutionTest.groovy +++ b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/impl/steps/IncrementalExecutionTest.groovy @@ -59,9 +59,9 @@ import org.gradle.testing.internal.util.Specification import org.junit.Rule import java.time.Duration -import java.util.function.BooleanSupplier +import java.util.function.Supplier -import static org.gradle.internal.execution.ExecutionOutcome.EXECUTED +import static org.gradle.internal.execution.ExecutionOutcome.EXECUTED_FULLY import static org.gradle.internal.execution.ExecutionOutcome.UP_TO_DATE import static org.gradle.internal.execution.history.changes.OutputFileChanges.OutputHandling.IGNORE_ADDED @@ -140,14 +140,14 @@ class IncrementalExecutionTest extends Specification { "file": [file("parent/outFile")], "files": [file("parent1/outFile"), file("parent2/outputFile1"), file("parent2/outputFile2")], ).withWork { -> - true + EXECUTED_FULLY }.build() when: def result = execute(unitOfWork) then: - result.outcome.get() == EXECUTED + result.outcome.get() == EXECUTED_FULLY !result.reused def allDirs = ["outDir", "outDir1", "outDir2"].collect { file(it) } @@ -166,7 +166,7 @@ class IncrementalExecutionTest extends Specification { def result = execute(unitOfWork) then: - result.outcome.get() == EXECUTED + result.outcome.get() == EXECUTED_FULLY !result.reused result.finalOutputs.keySet() == ["dir", "emptyDir", "file", "missingDir", "missingFile"] as Set @@ -182,7 +182,7 @@ class IncrementalExecutionTest extends Specification { def result = execute(unitOfWork) then: - result.outcome.get() == EXECUTED + result.outcome.get() == EXECUTED_FULLY !result.reused def origin = result.originMetadata.buildInvocationId @@ -207,7 +207,7 @@ class IncrementalExecutionTest extends Specification { def result = execute(unitOfWork) then: - result.outcome.get() == EXECUTED + result.outcome.get() == EXECUTED_FULLY !result.reused def origin = result.originMetadata.buildInvocationId @@ -218,7 +218,7 @@ class IncrementalExecutionTest extends Specification { result = outOfDate(builder.build(), outputFilesChanged(file: [outputFile])) then: - result.outcome.get() == EXECUTED + result.outcome.get() == EXECUTED_FULLY !result.reused result.originMetadata.buildInvocationId == buildInvocationScopeId.id result.originMetadata.buildInvocationId != origin @@ -242,7 +242,7 @@ class IncrementalExecutionTest extends Specification { result = outOfDate(builder.build(), "Task has failed previously.") then: - result.outcome.get() == EXECUTED + result.outcome.get() == EXECUTED_FULLY !result.reused result.originMetadata.buildInvocationId == buildInvocationScopeId.id result.originMetadata.buildInvocationId != origin @@ -253,9 +253,9 @@ class IncrementalExecutionTest extends Specification { def result = execute(unitOfWork) then: - result.outcome.get() == EXECUTED + result.outcome.get() == EXECUTED_FULLY !result.reused - result.outOfDateReasons == ["No history is available."] + result.executionReasons == ["No history is available."] } def "out of date when output file removed"() { @@ -267,9 +267,9 @@ class IncrementalExecutionTest extends Specification { def result = execute(unitOfWork) then: - result.outcome.get() == EXECUTED + result.outcome.get() == EXECUTED_FULLY !result.reused - result.outOfDateReasons == ["Output property 'file' file ${outputFile.absolutePath} has been removed."] + result.executionReasons == ["Output property 'file' file ${outputFile.absolutePath} has been removed."] } def "out of date when output file in output dir removed"() { @@ -281,9 +281,9 @@ class IncrementalExecutionTest extends Specification { def result = execute(unitOfWork) then: - result.outcome.get() == EXECUTED + result.outcome.get() == EXECUTED_FULLY !result.reused - result.outOfDateReasons == ["Output property 'dir' file ${outputDirFile.absolutePath} has been removed."] + result.executionReasons == ["Output property 'dir' file ${outputDirFile.absolutePath} has been removed."] } def "out of date when output file has changed type"() { @@ -298,7 +298,7 @@ class IncrementalExecutionTest extends Specification { then: result.outcome.failure.get().message == "Execution failed for Test unit of work." !result.reused - result.outOfDateReasons == ["Output property 'file' file ${outputFile.absolutePath} has changed."] + result.executionReasons == ["Output property 'file' file ${outputFile.absolutePath} has changed."] } def "out of date when any file in output dir has changed type"() { @@ -313,7 +313,7 @@ class IncrementalExecutionTest extends Specification { then: result.outcome.failure.get().message == "Execution failed for Test unit of work." !result.reused - result.outOfDateReasons == ["Output property 'dir' file ${outputDirFile.absolutePath} has changed."] + result.executionReasons == ["Output property 'dir' file ${outputDirFile.absolutePath} has changed."] } def "out of date when any output file has changed contents"() { @@ -324,9 +324,9 @@ class IncrementalExecutionTest extends Specification { outputFile << "new content" def result = execute(unitOfWork) then: - result.outcome.get() == EXECUTED + result.outcome.get() == EXECUTED_FULLY !result.reused - result.outOfDateReasons == ["Output property 'file' file ${outputFile.absolutePath} has changed."] + result.executionReasons == ["Output property 'file' file ${outputFile.absolutePath} has changed."] } def "out of date when any file in output dir has changed contents"() { @@ -337,9 +337,9 @@ class IncrementalExecutionTest extends Specification { outputDirFile << "new content" def result = execute(unitOfWork) then: - result.outcome.get() == EXECUTED + result.outcome.get() == EXECUTED_FULLY !result.reused - result.outOfDateReasons == ["Output property 'dir' file ${outputDirFile.absolutePath} has changed."] + result.executionReasons == ["Output property 'dir' file ${outputDirFile.absolutePath} has changed."] } def "out-of-date when any output files properties are added"() { @@ -361,9 +361,9 @@ class IncrementalExecutionTest extends Specification { def result = execute(outputFilesRemovedUnitOfWork) then: - result.outcome.get() == EXECUTED + result.outcome.get() == EXECUTED_FULLY !result.reused - result.outOfDateReasons == ["Output property 'file' has been removed for ${outputFilesRemovedUnitOfWork.displayName}"] + result.executionReasons == ["Output property 'file' has been removed for ${outputFilesRemovedUnitOfWork.displayName}"] } def "out-of-date when implementation changes"() { @@ -613,9 +613,9 @@ class IncrementalExecutionTest extends Specification { UpToDateResult outOfDate(UnitOfWork unitOfWork, List expectedReasons) { def result = execute(unitOfWork) - assert result.outcome.get() == EXECUTED + assert result.outcome.get() == EXECUTED_FULLY assert !result.reused - assert result.outOfDateReasons == expectedReasons + assert result.executionReasons == expectedReasons return result } @@ -657,11 +657,11 @@ class IncrementalExecutionTest extends Specification { } class UnitOfWorkBuilder { - private BooleanSupplier work = { -> + private Supplier work = { -> create.each { it -> it.createFile() } - return true + return ExecutionOutcome.EXECUTED_FULLY } private Map inputProperties = [prop: "value"] private Map> inputs = inputFiles @@ -671,7 +671,7 @@ class IncrementalExecutionTest extends Specification { private ImplementationSnapshot implementation = ImplementationSnapshot.of(UnitOfWork.name, HashCode.fromInt(1234)) private - UnitOfWorkBuilder withWork(BooleanSupplier closure) { + UnitOfWorkBuilder withWork(Supplier closure) { work = closure return this } @@ -738,7 +738,7 @@ class IncrementalExecutionTest extends Specification { @Override ExecutionOutcome execute() { executed = true - return work.asBoolean ? EXECUTED : UP_TO_DATE + return work.get() } @Override diff --git a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/impl/steps/SkipUpToDateStepTest.groovy b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/impl/steps/SkipUpToDateStepTest.groovy index 5895a344eb8c8..f733982a11e51 100644 --- a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/impl/steps/SkipUpToDateStepTest.groovy +++ b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/impl/steps/SkipUpToDateStepTest.groovy @@ -36,7 +36,7 @@ class SkipUpToDateStepTest extends Specification { then: result.outcome.get() == ExecutionOutcome.UP_TO_DATE - result.outOfDateReasons.empty + result.executionReasons.empty _ * context.work >> work 1 * work.changesSincePreviousExecution >> Optional.of(changes) @@ -49,7 +49,7 @@ class SkipUpToDateStepTest extends Specification { def result = step.execute(context) then: - result.outOfDateReasons == ["change"] + result.executionReasons == ["change"] _ * context.work >> work 1 * work.changesSincePreviousExecution >> Optional.of(changes) @@ -65,7 +65,7 @@ class SkipUpToDateStepTest extends Specification { def result = step.execute(context) then: - result.outOfDateReasons == ["No history is available."] + result.executionReasons == ["No history is available."] _ * context.work >> work 1 * work.changesSincePreviousExecution >> Optional.empty() From ef0eed4263d2ee3640ab2ba4746638143c6d60be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=B3r=C3=A1nt=20Pint=C3=A9r?= Date: Tue, 5 Mar 2019 23:43:40 +0100 Subject: [PATCH 343/853] Exexute the context This is a step towards eventually merging the Context and the UnitOfWork --- .../execution/ExecuteActionsTaskExecuter.java | 13 ++++++-- .../execution/ProjectExecutionServices.java | 3 +- .../scopes/ExecutionGradleServices.java | 6 ++-- .../ExecuteActionsTaskExecuterTest.groovy | 4 +-- .../DefaultDependencyManagementServices.java | 10 +++---- .../transform/DefaultTransformerInvoker.java | 30 +++++++++++-------- .../transform/WorkExecutorTestFixture.java | 5 ++-- .../execution/{impl/steps => }/Context.java | 4 +-- .../execution/{impl/steps => }/Step.java | 4 +-- .../internal/execution/WorkExecutor.java | 4 +-- .../execution/impl/DefaultWorkExecutor.java | 20 +++++-------- .../execution/impl/steps/CacheStep.java | 1 + .../execution/impl/steps/CachingContext.java | 1 + .../impl/steps/CancelExecutionStep.java | 2 ++ .../impl/steps/CatchExceptionStep.java | 2 ++ .../impl/steps/CreateOutputsStep.java | 2 ++ .../execution/impl/steps/ExecuteStep.java | 2 ++ .../impl/steps/PrepareCachingStep.java | 2 ++ .../impl/steps/SkipUpToDateStep.java | 2 ++ .../impl/steps/SnapshotOutputStep.java | 2 ++ .../impl/steps/StoreSnapshotsStep.java | 2 ++ .../execution/impl/steps/TimeoutStep.java | 2 ++ .../execution/impl/steps/CacheStepTest.groovy | 2 ++ .../execution/impl/steps/ExecutionTest.groovy | 1 + .../steps/IncrementalExecutionTest.groovy | 12 ++++++-- .../impl/steps/SkipUpToDateStepTest.groovy | 2 ++ 26 files changed, 87 insertions(+), 53 deletions(-) rename subprojects/execution/src/main/java/org/gradle/internal/execution/{impl/steps => }/Context.java (87%) rename subprojects/execution/src/main/java/org/gradle/internal/execution/{impl/steps => }/Step.java (88%) diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuter.java b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuter.java index 3fbe08af33d79..501e3176605a5 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuter.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuter.java @@ -41,6 +41,7 @@ import org.gradle.internal.exceptions.DefaultMultiCauseException; import org.gradle.internal.exceptions.MultiCauseException; import org.gradle.internal.execution.CacheHandler; +import org.gradle.internal.execution.Context; import org.gradle.internal.execution.ExecutionException; import org.gradle.internal.execution.ExecutionOutcome; import org.gradle.internal.execution.UnitOfWork; @@ -84,7 +85,7 @@ public class ExecuteActionsTaskExecuter implements TaskExecuter { private final BuildOperationExecutor buildOperationExecutor; private final AsyncWorkTracker asyncWorkTracker; private final TaskActionListener actionListener; - private final WorkExecutor workExecutor; + private final WorkExecutor workExecutor; public ExecuteActionsTaskExecuter( boolean buildCacheEnabled, @@ -94,7 +95,7 @@ public ExecuteActionsTaskExecuter( BuildOperationExecutor buildOperationExecutor, AsyncWorkTracker asyncWorkTracker, TaskActionListener actionListener, - WorkExecutor workExecutor + WorkExecutor workExecutor ) { this.buildCacheEnabled = buildCacheEnabled; this.taskFingerprinter = taskFingerprinter; @@ -108,7 +109,13 @@ public ExecuteActionsTaskExecuter( @Override public TaskExecuterResult execute(final TaskInternal task, final TaskStateInternal state, TaskExecutionContext context) { - final UpToDateResult result = workExecutor.execute(new TaskExecution(task, context)); + final TaskExecution work = new TaskExecution(task, context); + final UpToDateResult result = workExecutor.execute(new Context() { + @Override + public UnitOfWork getWork() { + return work; + } + }); result.getOutcome().ifSuccessfulOrElse( new Consumer() { @Override diff --git a/subprojects/core/src/main/java/org/gradle/execution/ProjectExecutionServices.java b/subprojects/core/src/main/java/org/gradle/execution/ProjectExecutionServices.java index 81ae79c5e0bda..0f2d4c509cb95 100644 --- a/subprojects/core/src/main/java/org/gradle/execution/ProjectExecutionServices.java +++ b/subprojects/core/src/main/java/org/gradle/execution/ProjectExecutionServices.java @@ -56,6 +56,7 @@ import org.gradle.internal.classloader.ClassLoaderHierarchyHasher; import org.gradle.internal.cleanup.BuildOutputCleanupRegistry; import org.gradle.internal.event.ListenerManager; +import org.gradle.internal.execution.Context; import org.gradle.internal.execution.OutputChangeListener; import org.gradle.internal.execution.WorkExecutor; import org.gradle.internal.execution.history.ExecutionHistoryStore; @@ -104,7 +105,7 @@ TaskExecuter createTaskExecuter(TaskExecutionModeResolver repository, PropertyWalker propertyWalker, TaskExecutionGraphInternal taskExecutionGraph, TaskExecutionListener taskExecutionListener, - WorkExecutor workExecutor + WorkExecutor workExecutor ) { boolean buildCacheEnabled = buildCacheController.isEnabled(); diff --git a/subprojects/core/src/main/java/org/gradle/internal/service/scopes/ExecutionGradleServices.java b/subprojects/core/src/main/java/org/gradle/internal/service/scopes/ExecutionGradleServices.java index f9cf1e9368006..26f2af7da25ed 100644 --- a/subprojects/core/src/main/java/org/gradle/internal/service/scopes/ExecutionGradleServices.java +++ b/subprojects/core/src/main/java/org/gradle/internal/service/scopes/ExecutionGradleServices.java @@ -31,6 +31,7 @@ import org.gradle.internal.concurrent.ExecutorFactory; import org.gradle.internal.concurrent.ParallelismConfigurationManager; import org.gradle.internal.event.ListenerManager; +import org.gradle.internal.execution.Context; import org.gradle.internal.execution.OutputChangeListener; import org.gradle.internal.execution.Result; import org.gradle.internal.execution.WorkExecutor; @@ -44,7 +45,6 @@ import org.gradle.internal.execution.impl.steps.CachingContext; import org.gradle.internal.execution.impl.steps.CancelExecutionStep; import org.gradle.internal.execution.impl.steps.CatchExceptionStep; -import org.gradle.internal.execution.impl.steps.Context; import org.gradle.internal.execution.impl.steps.CreateOutputsStep; import org.gradle.internal.execution.impl.steps.CurrentSnapshotResult; import org.gradle.internal.execution.impl.steps.ExecuteStep; @@ -109,7 +109,7 @@ OutputChangeListener createOutputChangeListener(ListenerManager listenerManager) return listenerManager.getBroadcaster(OutputChangeListener.class); } - public WorkExecutor createWorkExecutor( + public WorkExecutor createWorkExecutor( BuildCacheController buildCacheController, BuildCacheCommandFactory buildCacheCommandFactory, BuildInvocationScopeId buildInvocationScopeId, @@ -118,7 +118,7 @@ public WorkExecutor createWorkExecutor( OutputFilesRepository outputFilesRepository, TimeoutHandler timeoutHandler ) { - return new DefaultWorkExecutor( + return new DefaultWorkExecutor( new SkipUpToDateStep( new StoreSnapshotsStep(outputFilesRepository, new PrepareCachingStep( diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuterTest.groovy b/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuterTest.groovy index 76c674aa67d8d..966400839bd33 100644 --- a/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuterTest.groovy +++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuterTest.groovy @@ -33,13 +33,13 @@ import org.gradle.groovy.scripts.ScriptSource import org.gradle.initialization.DefaultBuildCancellationToken import org.gradle.internal.exceptions.DefaultMultiCauseException import org.gradle.internal.exceptions.MultiCauseException +import org.gradle.internal.execution.Context import org.gradle.internal.execution.OutputChangeListener import org.gradle.internal.execution.history.ExecutionHistoryStore import org.gradle.internal.execution.history.OutputFilesRepository import org.gradle.internal.execution.impl.DefaultWorkExecutor import org.gradle.internal.execution.impl.steps.CancelExecutionStep import org.gradle.internal.execution.impl.steps.CatchExceptionStep -import org.gradle.internal.execution.impl.steps.Context import org.gradle.internal.execution.impl.steps.ExecuteStep import org.gradle.internal.execution.impl.steps.SkipUpToDateStep import org.gradle.internal.execution.impl.steps.SnapshotOutputStep @@ -78,7 +78,7 @@ class ExecuteActionsTaskExecuterTest extends Specification { def actionListener = Mock(TaskActionListener) def outputChangeListener = Mock(OutputChangeListener) def cancellationToken = new DefaultBuildCancellationToken() - def workExecutor = new DefaultWorkExecutor( + def workExecutor = new DefaultWorkExecutor( new SkipUpToDateStep( new SnapshotOutputStep( buildId, diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/DefaultDependencyManagementServices.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/DefaultDependencyManagementServices.java index d7e9e9808232b..ebf284f41392a 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/DefaultDependencyManagementServices.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/DefaultDependencyManagementServices.java @@ -53,8 +53,8 @@ import org.gradle.api.internal.artifacts.ivyservice.ShortCircuitEmptyConfigurationResolver; import org.gradle.api.internal.artifacts.ivyservice.dependencysubstitution.DependencySubstitutionRules; import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.ResolveIvyFactory; -import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.parser.GradlePomModuleDescriptorParser; import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.parser.GradleModuleMetadataParser; +import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.parser.GradlePomModuleDescriptorParser; import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.strategy.VersionSelectorScheme; import org.gradle.api.internal.artifacts.ivyservice.moduleconverter.LocalComponentMetadataBuilder; import org.gradle.api.internal.artifacts.ivyservice.moduleconverter.dependencies.LocalConfigurationMetadataBuilder; @@ -106,6 +106,7 @@ import org.gradle.internal.component.external.model.ModuleComponentArtifactMetadata; import org.gradle.internal.component.model.ComponentAttributeMatcher; import org.gradle.internal.event.ListenerManager; +import org.gradle.internal.execution.Context; import org.gradle.internal.execution.OutputChangeListener; import org.gradle.internal.execution.Result; import org.gradle.internal.execution.WorkExecutor; @@ -113,7 +114,6 @@ import org.gradle.internal.execution.history.OutputFilesRepository; import org.gradle.internal.execution.impl.DefaultWorkExecutor; import org.gradle.internal.execution.impl.steps.CatchExceptionStep; -import org.gradle.internal.execution.impl.steps.Context; import org.gradle.internal.execution.impl.steps.CreateOutputsStep; import org.gradle.internal.execution.impl.steps.CurrentSnapshotResult; import org.gradle.internal.execution.impl.steps.ExecuteStep; @@ -198,7 +198,7 @@ OutputFileCollectionFingerprinter createOutputFingerprinter(FileSystemSnapshotte * * Currently used for running artifact transformations in buildscript blocks. */ - WorkExecutor createWorkExecutor( + WorkExecutor createWorkExecutor( TimeoutHandler timeoutHandler, ListenerManager listenerManager ) { OutputChangeListener outputChangeListener = listenerManager.getBroadcaster(OutputChangeListener.class); @@ -214,7 +214,7 @@ public void recordOutputs(Iterable outputFileFinge }; // TODO: Figure out how to get rid of origin scope id in snapshot outputs step UniqueId fixedUniqueId = UniqueId.from("dhwwyv4tqrd43cbxmdsf24wquu"); - return new DefaultWorkExecutor( + return new DefaultWorkExecutor( new SkipUpToDateStep( new StoreSnapshotsStep(noopOutputFilesRepository, new PrepareCachingStep( @@ -254,7 +254,7 @@ MutableCachingTransformationWorkspaceProvider createCachingTransformerWorkspaceP return new MutableCachingTransformationWorkspaceProvider(workspaceProvider); } - TransformerInvoker createTransformerInvoker(WorkExecutor workExecutor, + TransformerInvoker createTransformerInvoker(WorkExecutor workExecutor, FileSystemSnapshotter fileSystemSnapshotter, ImmutableCachingTransformationWorkspaceProvider transformationWorkspaceProvider, ArtifactTransformListener artifactTransformListener, diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvoker.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvoker.java index 071667f39b6a2..a49dcb956d18f 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvoker.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvoker.java @@ -31,6 +31,7 @@ import org.gradle.internal.UncheckedException; import org.gradle.internal.classloader.ClassLoaderHierarchyHasher; import org.gradle.internal.execution.CacheHandler; +import org.gradle.internal.execution.Context; import org.gradle.internal.execution.ExecutionOutcome; import org.gradle.internal.execution.UnitOfWork; import org.gradle.internal.execution.WorkExecutor; @@ -84,14 +85,14 @@ public class DefaultTransformerInvoker implements TransformerInvoker { private static final String OUTPUT_FILE_PATH_PREFIX = "o/"; private final FileSystemSnapshotter fileSystemSnapshotter; - private final WorkExecutor workExecutor; + private final WorkExecutor workExecutor; private final ArtifactTransformListener artifactTransformListener; private final CachingTransformationWorkspaceProvider immutableTransformationWorkspaceProvider; private final FileCollectionFactory fileCollectionFactory; private final ClassLoaderHierarchyHasher classLoaderHierarchyHasher; private final ProjectFinder projectFinder; - public DefaultTransformerInvoker(WorkExecutor workExecutor, + public DefaultTransformerInvoker(WorkExecutor workExecutor, FileSystemSnapshotter fileSystemSnapshotter, ArtifactTransformListener artifactTransformListener, CachingTransformationWorkspaceProvider immutableTransformationWorkspaceProvider, @@ -117,13 +118,13 @@ public Try> invoke(Transformer transformer, File inputArtifa FileCollectionFingerprinter inputArtifactFingerprinter = fingerprinterRegistry.getFingerprinter(transformer.getInputArtifactNormalizer()); String normalizedInputPath = inputArtifactFingerprinter.normalizePath(inputArtifactSnapshot); TransformationWorkspaceIdentity identity = getTransformationIdentity(producerProject, inputArtifactSnapshot, normalizedInputPath, transformer, dependenciesFingerprint); - return workspaceProvider.withWorkspace(identity, (identityStr, workspace) -> { + return workspaceProvider.withWorkspace(identity, (identityString, workspace) -> { return fireTransformListeners(transformer, subject, () -> { - String identityString = "transform/" + identityStr; + String transformIdentity = "transform/" + identityString; ExecutionHistoryStore executionHistoryStore = workspaceProvider.getExecutionHistoryStore(); FileCollectionFingerprinter outputFingerprinter = fingerprinterRegistry.getFingerprinter(OutputNormalizer.class); - AfterPreviousExecutionState afterPreviousExecutionState = executionHistoryStore.load(identityString).orElse(null); + AfterPreviousExecutionState afterPreviousExecutionState = executionHistoryStore.load(transformIdentity).orElse(null); ImplementationSnapshot implementationSnapshot = ImplementationSnapshot.of(transformer.getImplementationClass(), classLoaderHierarchyHasher); CurrentFileCollectionFingerprint inputArtifactFingerprint = inputArtifactFingerprinter.fingerprint(ImmutableList.of(inputArtifactSnapshot)); @@ -143,15 +144,23 @@ public Try> invoke(Transformer transformer, File inputArtifa afterPreviousExecutionState, beforeExecutionState, workspace, - identityString, + transformIdentity, executionHistoryStore, fileCollectionFactory, inputArtifact, dependencies, outputFingerprinter ); - UpToDateResult outcome = workExecutor.execute(execution); - return execution.getResult(outcome); + + UpToDateResult outcome = workExecutor.execute(new Context() { + @Override + public UnitOfWork getWork() { + return execution; + } + }); + + return outcome.getOutcome() + .map(outcome1 -> execution.loadResultsFile()); }); }); } @@ -275,11 +284,6 @@ private void writeResultsFile(File outputDir, File resultsFile, ImmutableList Files.write(resultsFile.toPath(), (Iterable) relativePaths::iterator)); } - private Try> getResult(UpToDateResult result) { - return result.getOutcome() - .map(outcome -> loadResultsFile()); - } - private ImmutableList loadResultsFile() { Path transformerResultsPath = workspace.getResultsFile().toPath(); try { diff --git a/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/WorkExecutorTestFixture.java b/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/WorkExecutorTestFixture.java index 656eff0c8bd96..c382a81a36290 100644 --- a/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/WorkExecutorTestFixture.java +++ b/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/WorkExecutorTestFixture.java @@ -22,6 +22,7 @@ import org.gradle.caching.internal.controller.BuildCacheStoreCommand; import org.gradle.initialization.BuildCancellationToken; import org.gradle.initialization.DefaultBuildCancellationToken; +import org.gradle.internal.execution.Context; import org.gradle.internal.execution.OutputChangeListener; import org.gradle.internal.execution.WorkExecutor; import org.gradle.internal.execution.history.OutputFilesRepository; @@ -67,7 +68,7 @@ public void close() { }; private BuildInvocationScopeId buildInvocationScopeId = new BuildInvocationScopeId(UniqueId.generate()); private BuildCancellationToken cancellationToken = new DefaultBuildCancellationToken(); - private final WorkExecutor workExecutor; + private final WorkExecutor workExecutor; WorkExecutorTestFixture(DefaultFileSystemMirror fileSystemMirror) { BuildCacheCommandFactory buildCacheCommandFactory = null; @@ -103,7 +104,7 @@ public void recordOutputs(Iterable outputFileFinge ); } - public WorkExecutor getWorkExecutor() { + public WorkExecutor getWorkExecutor() { return workExecutor; } } diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/impl/steps/Context.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/Context.java similarity index 87% rename from subprojects/execution/src/main/java/org/gradle/internal/execution/impl/steps/Context.java rename to subprojects/execution/src/main/java/org/gradle/internal/execution/Context.java index 55ddd076ab1fd..8bd33e541d48b 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/impl/steps/Context.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/Context.java @@ -14,9 +14,7 @@ * limitations under the License. */ -package org.gradle.internal.execution.impl.steps; - -import org.gradle.internal.execution.UnitOfWork; +package org.gradle.internal.execution; public interface Context { UnitOfWork getWork(); diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/impl/steps/Step.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/Step.java similarity index 88% rename from subprojects/execution/src/main/java/org/gradle/internal/execution/impl/steps/Step.java rename to subprojects/execution/src/main/java/org/gradle/internal/execution/Step.java index f8a237f634dc5..bf64ff38552cf 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/impl/steps/Step.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/Step.java @@ -14,9 +14,7 @@ * limitations under the License. */ -package org.gradle.internal.execution.impl.steps; - -import org.gradle.internal.execution.Result; +package org.gradle.internal.execution; public interface Step { R execute(C context); diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/WorkExecutor.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/WorkExecutor.java index d987e8367153e..e0dd5bcd042e0 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/WorkExecutor.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/WorkExecutor.java @@ -16,6 +16,6 @@ package org.gradle.internal.execution; -public interface WorkExecutor { - R execute(UnitOfWork work); +public interface WorkExecutor { + R execute(C context); } diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/impl/DefaultWorkExecutor.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/impl/DefaultWorkExecutor.java index 2ff83f3e6d4ae..445840581333e 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/impl/DefaultWorkExecutor.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/impl/DefaultWorkExecutor.java @@ -16,26 +16,20 @@ package org.gradle.internal.execution.impl; +import org.gradle.internal.execution.Context; import org.gradle.internal.execution.Result; -import org.gradle.internal.execution.UnitOfWork; +import org.gradle.internal.execution.Step; import org.gradle.internal.execution.WorkExecutor; -import org.gradle.internal.execution.impl.steps.Context; -import org.gradle.internal.execution.impl.steps.Step; -public class DefaultWorkExecutor implements WorkExecutor { - private final Step executeStep; +public class DefaultWorkExecutor implements WorkExecutor { + private final Step executeStep; - public DefaultWorkExecutor(Step executeStep) { + public DefaultWorkExecutor(Step executeStep) { this.executeStep = executeStep; } @Override - public R execute(UnitOfWork work) { - return executeStep.execute(new Context() { - @Override - public UnitOfWork getWork() { - return work; - } - }); + public R execute(C context) { + return executeStep.execute(context); } } diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/impl/steps/CacheStep.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/impl/steps/CacheStep.java index 210fb78e94354..1fd25651ffff7 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/impl/steps/CacheStep.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/impl/steps/CacheStep.java @@ -26,6 +26,7 @@ import org.gradle.internal.Try; import org.gradle.internal.execution.ExecutionOutcome; import org.gradle.internal.execution.OutputChangeListener; +import org.gradle.internal.execution.Step; import org.gradle.internal.execution.UnitOfWork; import org.gradle.internal.fingerprint.CurrentFileCollectionFingerprint; import org.slf4j.Logger; diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/impl/steps/CachingContext.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/impl/steps/CachingContext.java index 836a721e191e1..29f86d4469ea3 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/impl/steps/CachingContext.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/impl/steps/CachingContext.java @@ -17,6 +17,7 @@ package org.gradle.internal.execution.impl.steps; import org.gradle.internal.execution.CacheHandler; +import org.gradle.internal.execution.Context; public interface CachingContext extends Context { CacheHandler getCacheHandler(); diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/impl/steps/CancelExecutionStep.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/impl/steps/CancelExecutionStep.java index b29476481444c..8ce6ed569dcbf 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/impl/steps/CancelExecutionStep.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/impl/steps/CancelExecutionStep.java @@ -18,7 +18,9 @@ import org.gradle.api.BuildCancelledException; import org.gradle.initialization.BuildCancellationToken; +import org.gradle.internal.execution.Context; import org.gradle.internal.execution.Result; +import org.gradle.internal.execution.Step; public class CancelExecutionStep implements Step { private final BuildCancellationToken cancellationToken; diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/impl/steps/CatchExceptionStep.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/impl/steps/CatchExceptionStep.java index edb7bcb9dee9e..1c50536c9d8d0 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/impl/steps/CatchExceptionStep.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/impl/steps/CatchExceptionStep.java @@ -17,9 +17,11 @@ package org.gradle.internal.execution.impl.steps; import org.gradle.internal.Try; +import org.gradle.internal.execution.Context; import org.gradle.internal.execution.ExecutionException; import org.gradle.internal.execution.ExecutionOutcome; import org.gradle.internal.execution.Result; +import org.gradle.internal.execution.Step; public class CatchExceptionStep implements Step { private final Step delegate; diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/impl/steps/CreateOutputsStep.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/impl/steps/CreateOutputsStep.java index 3607f480bda5d..1372bec821fd5 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/impl/steps/CreateOutputsStep.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/impl/steps/CreateOutputsStep.java @@ -17,7 +17,9 @@ package org.gradle.internal.execution.impl.steps; import org.gradle.api.file.FileCollection; +import org.gradle.internal.execution.Context; import org.gradle.internal.execution.Result; +import org.gradle.internal.execution.Step; import org.gradle.internal.execution.UnitOfWork; import org.gradle.internal.file.TreeType; import org.slf4j.Logger; diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/impl/steps/ExecuteStep.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/impl/steps/ExecuteStep.java index 96808723a17fb..38f19eb116fd9 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/impl/steps/ExecuteStep.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/impl/steps/ExecuteStep.java @@ -17,9 +17,11 @@ package org.gradle.internal.execution.impl.steps; import org.gradle.internal.Try; +import org.gradle.internal.execution.Context; import org.gradle.internal.execution.ExecutionOutcome; import org.gradle.internal.execution.OutputChangeListener; import org.gradle.internal.execution.Result; +import org.gradle.internal.execution.Step; import org.gradle.internal.execution.UnitOfWork; import java.util.Optional; diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/impl/steps/PrepareCachingStep.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/impl/steps/PrepareCachingStep.java index 49a18f75201eb..371bdd39d427a 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/impl/steps/PrepareCachingStep.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/impl/steps/PrepareCachingStep.java @@ -17,7 +17,9 @@ package org.gradle.internal.execution.impl.steps; import org.gradle.internal.execution.CacheHandler; +import org.gradle.internal.execution.Context; import org.gradle.internal.execution.Result; +import org.gradle.internal.execution.Step; import org.gradle.internal.execution.UnitOfWork; public class PrepareCachingStep implements Step { diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/impl/steps/SkipUpToDateStep.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/impl/steps/SkipUpToDateStep.java index 6b0559f830a72..3836177f3a312 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/impl/steps/SkipUpToDateStep.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/impl/steps/SkipUpToDateStep.java @@ -24,7 +24,9 @@ import org.gradle.internal.Try; import org.gradle.internal.change.Change; import org.gradle.internal.change.ChangeVisitor; +import org.gradle.internal.execution.Context; import org.gradle.internal.execution.ExecutionOutcome; +import org.gradle.internal.execution.Step; import org.gradle.internal.execution.UnitOfWork; import org.gradle.internal.fingerprint.FileCollectionFingerprint; import org.slf4j.Logger; diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/impl/steps/SnapshotOutputStep.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/impl/steps/SnapshotOutputStep.java index 8e8214f45305c..e1d1c8d4c470e 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/impl/steps/SnapshotOutputStep.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/impl/steps/SnapshotOutputStep.java @@ -19,8 +19,10 @@ import com.google.common.collect.ImmutableSortedMap; import org.gradle.caching.internal.origin.OriginMetadata; import org.gradle.internal.Try; +import org.gradle.internal.execution.Context; import org.gradle.internal.execution.ExecutionOutcome; import org.gradle.internal.execution.Result; +import org.gradle.internal.execution.Step; import org.gradle.internal.execution.UnitOfWork; import org.gradle.internal.fingerprint.CurrentFileCollectionFingerprint; import org.gradle.internal.id.UniqueId; diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/impl/steps/StoreSnapshotsStep.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/impl/steps/StoreSnapshotsStep.java index 498dc78d4d838..d574f7fbc8b02 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/impl/steps/StoreSnapshotsStep.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/impl/steps/StoreSnapshotsStep.java @@ -17,6 +17,8 @@ package org.gradle.internal.execution.impl.steps; import com.google.common.collect.ImmutableSortedMap; +import org.gradle.internal.execution.Context; +import org.gradle.internal.execution.Step; import org.gradle.internal.execution.history.OutputFilesRepository; import org.gradle.internal.fingerprint.CurrentFileCollectionFingerprint; diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/impl/steps/TimeoutStep.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/impl/steps/TimeoutStep.java index dbb89e8541bca..a5a1ab0cbb703 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/impl/steps/TimeoutStep.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/impl/steps/TimeoutStep.java @@ -18,7 +18,9 @@ import org.gradle.api.GradleException; import org.gradle.api.InvalidUserDataException; +import org.gradle.internal.execution.Context; import org.gradle.internal.execution.Result; +import org.gradle.internal.execution.Step; import org.gradle.internal.execution.UnitOfWork; import org.gradle.internal.execution.timeout.Timeout; import org.gradle.internal.execution.timeout.TimeoutHandler; diff --git a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/impl/steps/CacheStepTest.groovy b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/impl/steps/CacheStepTest.groovy index dbc997e18cbe2..4c8ac26616561 100644 --- a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/impl/steps/CacheStepTest.groovy +++ b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/impl/steps/CacheStepTest.groovy @@ -22,8 +22,10 @@ import org.gradle.caching.internal.controller.BuildCacheController import org.gradle.caching.internal.origin.OriginMetadata import org.gradle.internal.Try import org.gradle.internal.execution.CacheHandler +import org.gradle.internal.execution.Context import org.gradle.internal.execution.ExecutionOutcome import org.gradle.internal.execution.OutputChangeListener +import org.gradle.internal.execution.Step import org.gradle.internal.execution.UnitOfWork import org.gradle.internal.fingerprint.CurrentFileCollectionFingerprint import org.gradle.internal.fingerprint.impl.EmptyCurrentFileCollectionFingerprint diff --git a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/impl/steps/ExecutionTest.groovy b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/impl/steps/ExecutionTest.groovy index 32e08575ed4d7..c7e9e60302022 100644 --- a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/impl/steps/ExecutionTest.groovy +++ b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/impl/steps/ExecutionTest.groovy @@ -21,6 +21,7 @@ import org.gradle.api.BuildCancelledException import org.gradle.caching.internal.origin.OriginMetadata import org.gradle.initialization.DefaultBuildCancellationToken import org.gradle.internal.execution.CacheHandler +import org.gradle.internal.execution.Context import org.gradle.internal.execution.ExecutionException import org.gradle.internal.execution.ExecutionOutcome import org.gradle.internal.execution.OutputChangeListener diff --git a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/impl/steps/IncrementalExecutionTest.groovy b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/impl/steps/IncrementalExecutionTest.groovy index 3cbb9fa536fac..cccdf7ae140a8 100644 --- a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/impl/steps/IncrementalExecutionTest.groovy +++ b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/impl/steps/IncrementalExecutionTest.groovy @@ -27,6 +27,7 @@ import org.gradle.caching.internal.CacheableEntity import org.gradle.caching.internal.origin.OriginMetadata import org.gradle.internal.classloader.ClassLoaderHierarchyHasher import org.gradle.internal.execution.CacheHandler +import org.gradle.internal.execution.Context import org.gradle.internal.execution.ExecutionException import org.gradle.internal.execution.ExecutionOutcome import org.gradle.internal.execution.OutputChangeListener @@ -116,8 +117,8 @@ class IncrementalExecutionTest extends Specification { def unitOfWork = builder.build() - WorkExecutor getExecutor() { - new DefaultWorkExecutor( + WorkExecutor getExecutor() { + new DefaultWorkExecutor( new SkipUpToDateStep( new StoreSnapshotsStep(outputFilesRepository, new SnapshotOutputStep(buildInvocationScopeId.getId(), @@ -627,7 +628,12 @@ class IncrementalExecutionTest extends Specification { UpToDateResult execute(UnitOfWork unitOfWork) { fileSystemMirror.beforeBuildFinished() - executor.execute(unitOfWork) + executor.execute(new Context() { + @Override + UnitOfWork getWork() { + return unitOfWork + } + }) } private TestFile file(Object... path) { diff --git a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/impl/steps/SkipUpToDateStepTest.groovy b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/impl/steps/SkipUpToDateStepTest.groovy index f733982a11e51..fb86630e663a0 100644 --- a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/impl/steps/SkipUpToDateStepTest.groovy +++ b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/impl/steps/SkipUpToDateStepTest.groovy @@ -18,7 +18,9 @@ package org.gradle.internal.execution.impl.steps import org.gradle.internal.change.ChangeVisitor import org.gradle.internal.change.DescriptiveChange +import org.gradle.internal.execution.Context import org.gradle.internal.execution.ExecutionOutcome +import org.gradle.internal.execution.Step import org.gradle.internal.execution.UnitOfWork import org.gradle.internal.execution.history.changes.ExecutionStateChanges import org.gradle.testing.internal.util.Specification From bcc96db00f357a598692ba99d24d83090d605d5c Mon Sep 17 00:00:00 2001 From: Cedric Champeau Date: Wed, 6 Mar 2019 13:50:08 +0100 Subject: [PATCH 344/853] Fix Groovy/Java library compatibility This commit fixes the Groovy + Java Library compatibility, by making sure that if, and only if, the Java Library is applied on a project that also applies the Java Library plugin, then the correct variants is selected. --- .../resolve/ResolveTestFixture.groovy | 5 +- ...vaLibraryInteractionIntegrationTest.groovy | 135 ++++++++++++++++++ .../groovy/GroovyPluginIntegrationTest.groovy | 99 ------------- .../gradle/api/plugins/GroovyBasePlugin.java | 17 +-- .../plugins/internal/JavaPluginsHelper.java | 10 +- 5 files changed, 146 insertions(+), 120 deletions(-) create mode 100644 subprojects/plugins/src/integTest/groovy/org/gradle/groovy/GroovyJavaLibraryInteractionIntegrationTest.groovy delete mode 100644 subprojects/plugins/src/integTest/groovy/org/gradle/groovy/GroovyPluginIntegrationTest.groovy diff --git a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/resolve/ResolveTestFixture.groovy b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/resolve/ResolveTestFixture.groovy index f92ec76db0387..a67d80b1f4b0a 100644 --- a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/resolve/ResolveTestFixture.groovy +++ b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/resolve/ResolveTestFixture.groovy @@ -532,7 +532,10 @@ allprojects { } String getFileName() { - return "${getName()}${version ? '-' + version : ''}${classifier ? '-' + classifier : ''}${noType ? '' : '.' + getType()}" + if (noType) { + return getName() + } + return "${getName()}${version ? '-' + version : ''}${classifier ? '-' + classifier : ''}.${getType()}" } } diff --git a/subprojects/plugins/src/integTest/groovy/org/gradle/groovy/GroovyJavaLibraryInteractionIntegrationTest.groovy b/subprojects/plugins/src/integTest/groovy/org/gradle/groovy/GroovyJavaLibraryInteractionIntegrationTest.groovy new file mode 100644 index 0000000000000..b66e05120bbb9 --- /dev/null +++ b/subprojects/plugins/src/integTest/groovy/org/gradle/groovy/GroovyJavaLibraryInteractionIntegrationTest.groovy @@ -0,0 +1,135 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.gradle.groovy + +import org.gradle.api.JavaVersion +import org.gradle.integtests.fixtures.AbstractDependencyResolutionTest +import org.gradle.integtests.fixtures.resolve.ResolveTestFixture +import org.gradle.test.fixtures.archive.JarTestFixture +import spock.lang.Issue +import spock.lang.Unroll + +class GroovyJavaLibraryInteractionIntegrationTest extends AbstractDependencyResolutionTest { + + ResolveTestFixture resolve = new ResolveTestFixture(buildFile, "compileClasspath") + + def setup() { + settingsFile << """ + rootProject.name = 'test' + """ + resolve.prepare() + } + + @Issue("https://github.com/gradle/gradle/issues/7398") + @Unroll + def "selects #expected output when #consumerPlugin plugin adds a project dependency to #consumerConf and producer has java-library=#groovyWithJavaLib"( + String consumerPlugin, String consumerConf, boolean groovyWithJavaLib, String expected) { + given: + multiProjectBuild('issue7398', ['groovyLib', 'javaLib']) { + file('groovyLib').with { + file('src/main/groovy/GroovyClass.groovy') << "public class GroovyClass {}" + file('build.gradle') << """ + ${groovyWithJavaLib ? "apply plugin: 'java-library'" : ''} + apply plugin: 'groovy' + dependencies { + implementation localGroovy() + } + """ + } + file('javaLib').with { + file('src/main/java/JavaClass.java') << "public class JavaClass { GroovyClass reference; }" + file('build.gradle') << """ + apply plugin: '$consumerPlugin' + dependencies { + $consumerConf project(':groovyLib') + } + + task assertDependsOnGroovyLib { + dependsOn compileJava + doLast { + ${ + expected == 'classes' ? ''' + def classesDirs = ['compileJava', 'compileGroovy'] + .collect { project(':groovyLib').tasks[it].destinationDir } + + assert compileJava.classpath.files.size() == 2 + assert compileJava.classpath.files.containsAll(classesDirs) + ''' : ''' + def jarFile = project(':groovyLib').tasks.jar.archiveFile.get().asFile + + assert compileJava.classpath.files.size() == 1 + assert compileJava.classpath.files.contains(jarFile) + def openJar = new java.util.jar.JarFile(jarFile) + assert openJar.getJarEntry("GroovyClass.class") + openJar.close() + ''' + } + } + } + """ + } + } + when: + succeeds 'javaLib:checkDeps' + + if (expected == 'jar') { + def jar = new JarTestFixture(testDirectory.file("groovyLib/build/libs/groovyLib-1.0.jar")) + executedAndNotSkipped(":groovyLib:compileJava", ":groovyLib:compileGroovy", ":groovyLib:classes", ":groovyLib:jar") + jar.hasDescendants("Dummy.class", "GroovyClass.class") + } else { + executedAndNotSkipped(":groovyLib:compileJava", ":groovyLib:compileGroovy") + notExecuted(":groovyLib:classes", ":groovyLib:jar") + } + + then: + resolve.expectGraph { + root(":javaLib", "org.test:javaLib:1.0") { + project(":groovyLib", "org.test:groovyLib:1.0") { + variant("apiElements", [ + 'org.gradle.category': 'library', + 'org.gradle.dependency.bundling': 'external', + 'org.gradle.jvm.version': JavaVersion.current().majorVersion, + 'org.gradle.usage': "java-api-jars"]) // this is a bit curious, it's an artifact of how selection is done + switch (expected) { + case "jar": + artifact(name: "groovyLib") + break + case "classes": + // first one is "main" from Java sources + artifact(name: 'main', noType: true) + // second one is "main" from Groovy sources + artifact(name: 'main', noType: true) + break + } + } + } + } + + where: + consumerPlugin | consumerConf | groovyWithJavaLib | expected + 'java-library' | 'api' | true | "classes" + 'java-library' | 'api' | false | "jar" + 'java-library' | 'compile' | true | "classes" + 'java-library' | 'compile' | false | "jar" + 'java-library' | 'implementation' | true | "classes" + 'java-library' | 'implementation' | false | "jar" + + 'java' | 'compile' | true | "classes" + 'java' | 'compile' | false | "jar" + 'java' | 'implementation' | true | "classes" + 'java' | 'implementation' | false | "jar" + } +} diff --git a/subprojects/plugins/src/integTest/groovy/org/gradle/groovy/GroovyPluginIntegrationTest.groovy b/subprojects/plugins/src/integTest/groovy/org/gradle/groovy/GroovyPluginIntegrationTest.groovy deleted file mode 100644 index 8be0400db04c5..0000000000000 --- a/subprojects/plugins/src/integTest/groovy/org/gradle/groovy/GroovyPluginIntegrationTest.groovy +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright 2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.gradle.groovy - - -import org.gradle.integtests.fixtures.AbstractIntegrationSpec -import spock.lang.Issue -import spock.lang.Unroll - -class GroovyPluginIntegrationTest extends AbstractIntegrationSpec { - - private static final boolean javaLibUsesClasses = false // current behavior as of gradle 5.3 - private static final String javaLibUsageMessage = javaLibUsesClasses ? "classes" : "jar" - - @Issue("https://github.com/gradle/gradle/issues/7398") - @Unroll - def "groovy #classesOrJar output is transitive when #consumerPlugin plugin adds a project dependency to #consumerConf"( - String consumerPlugin, String consumerConf, boolean groovyWithJavaLib, String classesOrJar) { - given: - multiProjectBuild('issue7398', ['groovyLib', 'javaLib']) { - file('groovyLib').with { - file('src/main/groovy/GroovyClass.groovy') << "public class GroovyClass {}" - file('build.gradle') << """ - ${groovyWithJavaLib ? "apply plugin: 'java-library'" : ''} - apply plugin: 'groovy' - dependencies { - compileOnly localGroovy() - } - """ - } - file('javaLib').with { - // Hm... if we extend GroovyClass, compilation will fail because we did not make localGroovy() transitive, - // and our GroovyClass actually extends groovy.lang.GroovyObject, which fails when referenced as a supertype. - // We ignore this implementation detail by referencing GroovyClass as a field; (composition +1, inheritance -1). - file('src/main/java/JavaClass.java') << "public class JavaClass { GroovyClass reference; }" - file('build.gradle') << """ - apply plugin: '$consumerPlugin' - dependencies { - $consumerConf project(':groovyLib') - } - - task assertDependsOnGroovyLib { - dependsOn compileJava - doLast { - ${ classesOrJar == 'classes' ? ''' - def classesDirs = ['compileJava', 'compileGroovy'] - .collect { project(':groovyLib').tasks[it].destinationDir } - - assert compileJava.classpath.files.size() == 2 - assert compileJava.classpath.files.containsAll(classesDirs) - ''' : ''' - def jarFile = project(':groovyLib').tasks.jar.archiveFile.get().asFile - - assert compileJava.classpath.files.size() == 1 - assert compileJava.classpath.files.contains(jarFile) - def openJar = new java.util.jar.JarFile(jarFile) - assert openJar.getJarEntry("GroovyClass.class") - openJar.close() - ''' - } - } - } - """ - } - } - expect: - succeeds 'assertDependsOnGroovyLib' - - where: - // whenever groovy+java-library plugins are used, classesOrJar will be "classes", - // and when it is not, it will be "jar". We use two variables for nice Unrolled feature names. - // As of 5.3, these all actually assert the same thing: that jars are used on compile classpath, as that is current default. - consumerPlugin | consumerConf | groovyWithJavaLib | classesOrJar - 'java-library' | 'api' | javaLibUsesClasses | javaLibUsageMessage - 'java-library' | 'api' | false | "jar" - 'java-library' | 'compile' | javaLibUsesClasses | javaLibUsageMessage - 'java-library' | 'compile' | false | "jar" - 'java-library' | 'implementation' | javaLibUsesClasses | javaLibUsageMessage - 'java-library' | 'implementation' | false | "jar" - - 'java' | 'compile' | javaLibUsesClasses | javaLibUsageMessage - 'java' | 'compile' | false | "jar" - 'java' | 'implementation' | javaLibUsesClasses | javaLibUsageMessage - 'java' | 'implementation' | false | "jar" - } -} diff --git a/subprojects/plugins/src/main/java/org/gradle/api/plugins/GroovyBasePlugin.java b/subprojects/plugins/src/main/java/org/gradle/api/plugins/GroovyBasePlugin.java index f4af97d05c956..0f171091180ad 100644 --- a/subprojects/plugins/src/main/java/org/gradle/api/plugins/GroovyBasePlugin.java +++ b/subprojects/plugins/src/main/java/org/gradle/api/plugins/GroovyBasePlugin.java @@ -16,16 +16,12 @@ package org.gradle.api.plugins; -import com.google.common.collect.ImmutableMap; import org.gradle.api.Action; -import org.gradle.api.NamedDomainObjectContainer; import org.gradle.api.Plugin; import org.gradle.api.Project; import org.gradle.api.Task; import org.gradle.api.Transformer; import org.gradle.api.artifacts.Configuration; -import org.gradle.api.artifacts.ConfigurationVariant; -import org.gradle.api.artifacts.type.ArtifactTypeDefinition; import org.gradle.api.file.ConfigurableFileCollection; import org.gradle.api.file.FileCollection; import org.gradle.api.file.FileTreeElement; @@ -34,6 +30,7 @@ import org.gradle.api.internal.tasks.DefaultGroovySourceSet; import org.gradle.api.internal.tasks.DefaultSourceSet; import org.gradle.api.model.ObjectFactory; +import org.gradle.api.plugins.internal.JavaPluginsHelper; import org.gradle.api.plugins.internal.SourceSetUtil; import org.gradle.api.provider.Provider; import org.gradle.api.reporting.ReportingExtension; @@ -133,17 +130,7 @@ public CompileOptions transform(GroovyCompile groovyCompile) { @Override public void execute(AppliedPlugin plugin) { Configuration apiElements = project.getConfigurations().getByName(sourceSet.getApiElementsConfigurationName()); - apiElements.getOutgoing().variants(new Action>() { - @Override - public void execute(NamedDomainObjectContainer variants) { - GroovyCompile groovyCompile = compileTask.get(); - variants.maybeCreate("classes").artifact(ImmutableMap.of( - "file", groovyCompile.getDestinationDir(), - "type", ArtifactTypeDefinition.JVM_CLASS_DIRECTORY, - "builtBy", groovyCompile - )); - } - }); + JavaPluginsHelper.registerClassesDirVariant(compileTask, project.getObjects(), apiElements); } }); } diff --git a/subprojects/plugins/src/main/java/org/gradle/api/plugins/internal/JavaPluginsHelper.java b/subprojects/plugins/src/main/java/org/gradle/api/plugins/internal/JavaPluginsHelper.java index e2fd9d2e04a70..66061fd46654f 100644 --- a/subprojects/plugins/src/main/java/org/gradle/api/plugins/internal/JavaPluginsHelper.java +++ b/subprojects/plugins/src/main/java/org/gradle/api/plugins/internal/JavaPluginsHelper.java @@ -23,7 +23,7 @@ import org.gradle.api.internal.artifacts.publish.AbstractPublishArtifact; import org.gradle.api.model.ObjectFactory; import org.gradle.api.provider.Provider; -import org.gradle.api.tasks.compile.JavaCompile; +import org.gradle.api.tasks.compile.AbstractCompile; import javax.annotation.Nullable; import java.io.File; @@ -34,15 +34,15 @@ * into the public API. */ public class JavaPluginsHelper { - public static void registerClassesDirVariant(final Provider javaCompile, ObjectFactory objectFactory, Configuration configuration) { + public static void registerClassesDirVariant(final Provider compileTask, ObjectFactory objectFactory, Configuration configuration) { // Define a classes variant to use for compilation ConfigurationPublications publications = configuration.getOutgoing(); - ConfigurationVariant variant = publications.getVariants().create("classes"); + ConfigurationVariant variant = publications.getVariants().maybeCreate("classes"); variant.getAttributes().attribute(Usage.USAGE_ATTRIBUTE, objectFactory.named(Usage.class, Usage.JAVA_API_CLASSES)); - variant.artifact(new IntermediateJavaArtifact(ArtifactTypeDefinition.JVM_CLASS_DIRECTORY, javaCompile) { + variant.artifact(new IntermediateJavaArtifact(ArtifactTypeDefinition.JVM_CLASS_DIRECTORY, compileTask) { @Override public File getFile() { - return javaCompile.get().getDestinationDir(); + return compileTask.get().getDestinationDir(); } }); } From 88e797d720e8daf3367b8afbd3317db7b558cd07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=B3r=C3=A1nt=20Pint=C3=A9r?= Date: Wed, 6 Mar 2019 15:16:23 +0100 Subject: [PATCH 345/853] Pass execution context to UnitOfWork.execute() --- .../tasks/execution/ExecuteActionsTaskExecuter.java | 7 +++---- .../artifacts/transform/DefaultTransformerInvoker.java | 2 +- .../java/org/gradle/internal/execution/UnitOfWork.java | 2 +- .../gradle/internal/execution/impl/steps/ExecuteStep.java | 2 +- .../internal/execution/impl/steps/ExecutionTest.groovy | 2 +- .../execution/impl/steps/IncrementalExecutionTest.groovy | 2 +- 6 files changed, 8 insertions(+), 9 deletions(-) diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuter.java b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuter.java index 501e3176605a5..28ff77cc9ad8e 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuter.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuter.java @@ -135,7 +135,6 @@ public void accept(Throwable failure) { return new TaskExecuterResult() { @Override public Optional getReusedOutputOriginMetadata() { - //noinspection RedundantTypeArguments return result.isReused() ? Optional.of(result.getOriginMetadata()) : Optional.empty(); @@ -168,14 +167,14 @@ public String getIdentity() { } @Override - public ExecutionOutcome execute() { + public ExecutionOutcome execute(Context context) { task.getState().setExecuting(true); try { LOGGER.debug("Executing actions for {}.", task); actionListener.beforeActions(task); - executeActions(task, context); + executeActions(task, this.context); return task.getState().getDidWork() - ? context.isTaskExecutedIncrementally() + ? this.context.isTaskExecutedIncrementally() ? ExecutionOutcome.EXECUTED_INCREMENTALLY : ExecutionOutcome.EXECUTED_FULLY : ExecutionOutcome.UP_TO_DATE; diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvoker.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvoker.java index a49dcb956d18f..54e301ab70ae4 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvoker.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvoker.java @@ -252,7 +252,7 @@ public TransformerExecution( } @Override - public ExecutionOutcome execute() { + public ExecutionOutcome execute(Context context) { File outputDir = workspace.getOutputDirectory(); File resultsFile = workspace.getResultsFile(); GFileUtils.cleanDirectory(outputDir); diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/UnitOfWork.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/UnitOfWork.java index 4a994f68595a3..0da1de49d103a 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/UnitOfWork.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/UnitOfWork.java @@ -32,7 +32,7 @@ public interface UnitOfWork extends CacheableEntity { /** * Executes the work synchronously. */ - ExecutionOutcome execute(); + ExecutionOutcome execute(Context context); Optional getTimeout(); diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/impl/steps/ExecuteStep.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/impl/steps/ExecuteStep.java index 38f19eb116fd9..fa9ded41048e9 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/impl/steps/ExecuteStep.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/impl/steps/ExecuteStep.java @@ -45,7 +45,7 @@ public Result execute(Context context) { if (!changingOutputs.isPresent()) { outputChangeListener.beforeOutputChange(); } - ExecutionOutcome outcome = work.execute(); + ExecutionOutcome outcome = work.execute(context); return new Result() { @Override public Try getOutcome() { diff --git a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/impl/steps/ExecutionTest.groovy b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/impl/steps/ExecutionTest.groovy index c7e9e60302022..67c40e9d90bc7 100644 --- a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/impl/steps/ExecutionTest.groovy +++ b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/impl/steps/ExecutionTest.groovy @@ -134,7 +134,7 @@ class ExecutionTest extends Specification { boolean executed @Override - ExecutionOutcome execute() { + ExecutionOutcome execute(Context context) { executed = true return work.get() } diff --git a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/impl/steps/IncrementalExecutionTest.groovy b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/impl/steps/IncrementalExecutionTest.groovy index cccdf7ae140a8..407f6e3c59af6 100644 --- a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/impl/steps/IncrementalExecutionTest.groovy +++ b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/impl/steps/IncrementalExecutionTest.groovy @@ -742,7 +742,7 @@ class IncrementalExecutionTest extends Specification { boolean executed @Override - ExecutionOutcome execute() { + ExecutionOutcome execute(Context context) { executed = true return work.get() } From f25c4f7ae705fc9034e25922ba7bc6bfad904357 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=B3r=C3=A1nt=20Pint=C3=A9r?= Date: Wed, 6 Mar 2019 15:42:42 +0100 Subject: [PATCH 346/853] Move resolving incremental changes to the execution engine --- .../execution/ExecuteActionsTaskExecuter.java | 42 +++++-- ...ResolveIncrementalChangesTaskExecuter.java | 116 ------------------ .../execution/ProjectExecutionServices.java | 6 +- .../scopes/ExecutionGradleServices.java | 30 +++-- .../ExecuteActionsTaskExecuterTest.groovy | 24 ++-- .../DefaultDependencyManagementServices.java | 29 ++--- .../transform/DefaultTransformerInvoker.java | 49 ++++---- .../transform/WorkExecutorTestFixture.java | 6 +- .../gradle/internal/execution/UnitOfWork.java | 9 +- .../execution/impl/steps/CachingContext.java | 3 +- .../execution/impl/steps/ExecuteStep.java | 5 +- .../impl/steps/IncrementalChangesContext.java | 30 +++++ .../impl/steps/IncrementalContext.java | 42 +++++++ .../impl/steps/PrepareCachingStep.java | 11 +- .../impl/steps/ResolveChangesStep.java | 97 +++++++++++++++ .../impl/steps/SkipUpToDateStep.java | 5 +- .../execution/impl/steps/CacheStepTest.groovy | 9 ++ .../execution/impl/steps/ExecutionTest.groovy | 43 ++++--- .../steps/IncrementalExecutionTest.groovy | 45 ++++--- .../impl/steps/SkipUpToDateStepTest.groovy | 16 ++- 20 files changed, 367 insertions(+), 250 deletions(-) delete mode 100644 subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/ResolveIncrementalChangesTaskExecuter.java create mode 100644 subprojects/execution/src/main/java/org/gradle/internal/execution/impl/steps/IncrementalChangesContext.java create mode 100644 subprojects/execution/src/main/java/org/gradle/internal/execution/impl/steps/IncrementalContext.java create mode 100644 subprojects/execution/src/main/java/org/gradle/internal/execution/impl/steps/ResolveChangesStep.java diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuter.java b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuter.java index 28ff77cc9ad8e..cf9a2aea2c8e5 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuter.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuter.java @@ -41,7 +41,6 @@ import org.gradle.internal.exceptions.DefaultMultiCauseException; import org.gradle.internal.exceptions.MultiCauseException; import org.gradle.internal.execution.CacheHandler; -import org.gradle.internal.execution.Context; import org.gradle.internal.execution.ExecutionException; import org.gradle.internal.execution.ExecutionOutcome; import org.gradle.internal.execution.UnitOfWork; @@ -54,6 +53,8 @@ import org.gradle.internal.execution.history.changes.OutputFileChanges; import org.gradle.internal.execution.history.changes.OutputFileChanges.OutputHandling; import org.gradle.internal.execution.impl.OutputFilterUtil; +import org.gradle.internal.execution.impl.steps.IncrementalChangesContext; +import org.gradle.internal.execution.impl.steps.IncrementalContext; import org.gradle.internal.execution.impl.steps.UpToDateResult; import org.gradle.internal.fingerprint.CurrentFileCollectionFingerprint; import org.gradle.internal.fingerprint.FileCollectionFingerprint; @@ -72,6 +73,8 @@ import java.util.function.Consumer; import java.util.function.Function; +import static org.gradle.internal.execution.history.changes.OutputFileChanges.OutputHandling.IGNORE_ADDED; + /** * A {@link TaskExecuter} which executes the actions of a task. */ @@ -85,7 +88,7 @@ public class ExecuteActionsTaskExecuter implements TaskExecuter { private final BuildOperationExecutor buildOperationExecutor; private final AsyncWorkTracker asyncWorkTracker; private final TaskActionListener actionListener; - private final WorkExecutor workExecutor; + private final WorkExecutor workExecutor; public ExecuteActionsTaskExecuter( boolean buildCacheEnabled, @@ -95,7 +98,7 @@ public ExecuteActionsTaskExecuter( BuildOperationExecutor buildOperationExecutor, AsyncWorkTracker asyncWorkTracker, TaskActionListener actionListener, - WorkExecutor workExecutor + WorkExecutor workExecutor ) { this.buildCacheEnabled = buildCacheEnabled; this.taskFingerprinter = taskFingerprinter; @@ -108,13 +111,28 @@ public ExecuteActionsTaskExecuter( } @Override - public TaskExecuterResult execute(final TaskInternal task, final TaskStateInternal state, TaskExecutionContext context) { + public TaskExecuterResult execute(final TaskInternal task, final TaskStateInternal state, final TaskExecutionContext context) { final TaskExecution work = new TaskExecution(task, context); - final UpToDateResult result = workExecutor.execute(new Context() { + final UpToDateResult result = workExecutor.execute(new IncrementalContext() { @Override public UnitOfWork getWork() { return work; } + + @Override + public Optional getRebuildReason() { + return context.getTaskExecutionMode().getRebuildReason(); + } + + @Override + public Optional getAfterPreviousExecutionState() { + return Optional.ofNullable(context.getAfterPreviousExecution()); + } + + @Override + public Optional getBeforeExecutionState() { + return context.getBeforeExecutionState(); + } }); result.getOutcome().ifSuccessfulOrElse( new Consumer() { @@ -167,11 +185,17 @@ public String getIdentity() { } @Override - public ExecutionOutcome execute(Context context) { + public ExecutionOutcome execute(IncrementalChangesContext context) { task.getState().setExecuting(true); try { LOGGER.debug("Executing actions for {}.", task); actionListener.beforeActions(task); + context.getChanges().ifPresent(new Consumer() { + @Override + public void accept(ExecutionStateChanges changes) { + TaskExecution.this.context.setExecutionStateChanges(changes); + } + }); executeActions(task, this.context); return task.getState().getDidWork() ? this.context.isTaskExecutedIncrementally() @@ -214,8 +238,8 @@ public void visitLocalState(LocalStateVisitor visitor) { } @Override - public Optional getChangesSincePreviousExecution() { - return context.getExecutionStateChanges(); + public OutputHandling getOutputHandling() { + return IGNORE_ADDED; } @Override @@ -308,7 +332,7 @@ public void accept(BeforeExecutionState execution) { private boolean hasAnyOutputFileChanges(ImmutableSortedMap previous, ImmutableSortedMap current) { return !previous.keySet().equals(current.keySet()) - || new OutputFileChanges(previous, current, OutputHandling.IGNORE_ADDED).hasAnyChanges(); + || new OutputFileChanges(previous, current, IGNORE_ADDED).hasAnyChanges(); } @Override diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/ResolveIncrementalChangesTaskExecuter.java b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/ResolveIncrementalChangesTaskExecuter.java deleted file mode 100644 index f1d362be1a996..0000000000000 --- a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/ResolveIncrementalChangesTaskExecuter.java +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Copyright 2018 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.gradle.api.internal.tasks.execution; - -import org.gradle.api.Describable; -import org.gradle.api.internal.TaskInternal; -import org.gradle.api.internal.tasks.TaskExecuter; -import org.gradle.api.internal.tasks.TaskExecuterResult; -import org.gradle.api.internal.tasks.TaskExecutionContext; -import org.gradle.api.internal.tasks.TaskStateInternal; -import org.gradle.internal.change.Change; -import org.gradle.internal.change.ChangeVisitor; -import org.gradle.internal.change.DescriptiveChange; -import org.gradle.internal.execution.history.AfterPreviousExecutionState; -import org.gradle.internal.execution.history.BeforeExecutionState; -import org.gradle.internal.execution.history.changes.DefaultExecutionStateChanges; -import org.gradle.internal.execution.history.changes.ExecutionStateChanges; - -import javax.annotation.Nullable; -import java.util.function.Function; -import java.util.function.Supplier; - -import static org.gradle.internal.execution.history.changes.OutputFileChanges.OutputHandling.IGNORE_ADDED; - -/** - * Resolves the incremental changes to pass to the task actions. - * - * @see org.gradle.api.tasks.incremental.IncrementalTaskInputs - */ -public class ResolveIncrementalChangesTaskExecuter implements TaskExecuter { - private final TaskExecuter delegate; - - public ResolveIncrementalChangesTaskExecuter(TaskExecuter delegate) { - this.delegate = delegate; - } - - @Override - public TaskExecuterResult execute(final TaskInternal task, TaskStateInternal state, final TaskExecutionContext context) { - ExecutionStateChanges changes = context.getTaskExecutionMode().getRebuildReason() - .map(new Function() { - @Override - public ExecutionStateChanges apply(String rebuildReason) { - return new RebuildExecutionStateChanges(rebuildReason); - } - }).orElseGet(new Supplier() { - @Nullable - @Override - public ExecutionStateChanges get() { - final AfterPreviousExecutionState afterPreviousExecution = context.getAfterPreviousExecution(); - if (afterPreviousExecution == null || context.isOutputRemovedBeforeExecution()) { - return null; - } else { - // TODO We need a nicer describable wrapper around task here - return context.getBeforeExecutionState().map(new Function() { - @Override - public ExecutionStateChanges apply(BeforeExecutionState beforeExecution) { - return new DefaultExecutionStateChanges(afterPreviousExecution, beforeExecution, new Describable() { - @Override - public String getDisplayName() { - // The value is cached, so we should be okay to call this many times - return task.toString(); - } - }, IGNORE_ADDED); - } - }).orElse(null); - } - } - }); - - context.setExecutionStateChanges(changes); - - return delegate.execute(task, state, context); - } - - private static class RebuildExecutionStateChanges implements ExecutionStateChanges { - private final Change rebuildChange; - - public RebuildExecutionStateChanges(String rebuildReason) { - this.rebuildChange = new DescriptiveChange(rebuildReason); - } - - @Override - public Iterable getInputFilesChanges() { - throw new UnsupportedOperationException(); - } - - @Override - public void visitAllChanges(ChangeVisitor visitor) { - visitor.visitChange(rebuildChange); - } - - @Override - public boolean isRebuildRequired() { - return true; - } - - @Override - public AfterPreviousExecutionState getPreviousExecution() { - throw new UnsupportedOperationException(); - } - } -} diff --git a/subprojects/core/src/main/java/org/gradle/execution/ProjectExecutionServices.java b/subprojects/core/src/main/java/org/gradle/execution/ProjectExecutionServices.java index 0f2d4c509cb95..f3ddc8c7d50be 100644 --- a/subprojects/core/src/main/java/org/gradle/execution/ProjectExecutionServices.java +++ b/subprojects/core/src/main/java/org/gradle/execution/ProjectExecutionServices.java @@ -39,7 +39,6 @@ import org.gradle.api.internal.tasks.execution.ResolveBeforeExecutionOutputsTaskExecuter; import org.gradle.api.internal.tasks.execution.ResolveBeforeExecutionStateTaskExecuter; import org.gradle.api.internal.tasks.execution.ResolveBuildCacheKeyExecuter; -import org.gradle.api.internal.tasks.execution.ResolveIncrementalChangesTaskExecuter; import org.gradle.api.internal.tasks.execution.ResolveTaskExecutionModeExecuter; import org.gradle.api.internal.tasks.execution.ResolveTaskOutputCachingStateExecuter; import org.gradle.api.internal.tasks.execution.SkipEmptySourceFilesTaskExecuter; @@ -56,11 +55,11 @@ import org.gradle.internal.classloader.ClassLoaderHierarchyHasher; import org.gradle.internal.cleanup.BuildOutputCleanupRegistry; import org.gradle.internal.event.ListenerManager; -import org.gradle.internal.execution.Context; import org.gradle.internal.execution.OutputChangeListener; import org.gradle.internal.execution.WorkExecutor; import org.gradle.internal.execution.history.ExecutionHistoryStore; import org.gradle.internal.execution.history.OutputFilesRepository; +import org.gradle.internal.execution.impl.steps.IncrementalContext; import org.gradle.internal.execution.impl.steps.UpToDateResult; import org.gradle.internal.fingerprint.FileCollectionFingerprinter; import org.gradle.internal.fingerprint.FileCollectionFingerprinterRegistry; @@ -105,7 +104,7 @@ TaskExecuter createTaskExecuter(TaskExecutionModeResolver repository, PropertyWalker propertyWalker, TaskExecutionGraphInternal taskExecutionGraph, TaskExecutionListener taskExecutionListener, - WorkExecutor workExecutor + WorkExecutor workExecutor ) { boolean buildCacheEnabled = buildCacheController.isEnabled(); @@ -122,7 +121,6 @@ TaskExecuter createTaskExecuter(TaskExecutionModeResolver repository, actionListener, workExecutor ); - executer = new ResolveIncrementalChangesTaskExecuter(executer); executer = new ResolveTaskOutputCachingStateExecuter(buildCacheEnabled, resolver, executer); // TODO:lptr this should be added only if the scan plugin is applied, but SnapshotTaskInputsOperationIntegrationTest // TODO:lptr expects it to be added also when the build cache is enabled (but not the scan plugin) diff --git a/subprojects/core/src/main/java/org/gradle/internal/service/scopes/ExecutionGradleServices.java b/subprojects/core/src/main/java/org/gradle/internal/service/scopes/ExecutionGradleServices.java index 26f2af7da25ed..85b03220e6066 100644 --- a/subprojects/core/src/main/java/org/gradle/internal/service/scopes/ExecutionGradleServices.java +++ b/subprojects/core/src/main/java/org/gradle/internal/service/scopes/ExecutionGradleServices.java @@ -31,7 +31,6 @@ import org.gradle.internal.concurrent.ExecutorFactory; import org.gradle.internal.concurrent.ParallelismConfigurationManager; import org.gradle.internal.event.ListenerManager; -import org.gradle.internal.execution.Context; import org.gradle.internal.execution.OutputChangeListener; import org.gradle.internal.execution.Result; import org.gradle.internal.execution.WorkExecutor; @@ -48,7 +47,10 @@ import org.gradle.internal.execution.impl.steps.CreateOutputsStep; import org.gradle.internal.execution.impl.steps.CurrentSnapshotResult; import org.gradle.internal.execution.impl.steps.ExecuteStep; +import org.gradle.internal.execution.impl.steps.IncrementalChangesContext; +import org.gradle.internal.execution.impl.steps.IncrementalContext; import org.gradle.internal.execution.impl.steps.PrepareCachingStep; +import org.gradle.internal.execution.impl.steps.ResolveChangesStep; import org.gradle.internal.execution.impl.steps.SkipUpToDateStep; import org.gradle.internal.execution.impl.steps.SnapshotOutputStep; import org.gradle.internal.execution.impl.steps.StoreSnapshotsStep; @@ -109,7 +111,7 @@ OutputChangeListener createOutputChangeListener(ListenerManager listenerManager) return listenerManager.getBroadcaster(OutputChangeListener.class); } - public WorkExecutor createWorkExecutor( + public WorkExecutor createWorkExecutor( BuildCacheController buildCacheController, BuildCacheCommandFactory buildCacheCommandFactory, BuildInvocationScopeId buildInvocationScopeId, @@ -118,17 +120,19 @@ public WorkExecutor createWorkExecutor( OutputFilesRepository outputFilesRepository, TimeoutHandler timeoutHandler ) { - return new DefaultWorkExecutor( - new SkipUpToDateStep( - new StoreSnapshotsStep(outputFilesRepository, - new PrepareCachingStep( - new CacheStep(buildCacheController, outputChangeListener, buildCacheCommandFactory, - new SnapshotOutputStep(buildInvocationScopeId.getId(), - new CreateOutputsStep( - new CatchExceptionStep( - new TimeoutStep(timeoutHandler, - new CancelExecutionStep(cancellationToken, - new ExecuteStep(outputChangeListener) + return new DefaultWorkExecutor( + new ResolveChangesStep( + new SkipUpToDateStep( + new StoreSnapshotsStep(outputFilesRepository, + new PrepareCachingStep( + new CacheStep(buildCacheController, outputChangeListener, buildCacheCommandFactory, + new SnapshotOutputStep(buildInvocationScopeId.getId(), + new CreateOutputsStep( + new CatchExceptionStep( + new TimeoutStep(timeoutHandler, + new CancelExecutionStep(cancellationToken, + new ExecuteStep(outputChangeListener) + ) ) ) ) diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuterTest.groovy b/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuterTest.groovy index 966400839bd33..27ec1516a4505 100644 --- a/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuterTest.groovy +++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuterTest.groovy @@ -19,7 +19,7 @@ import com.google.common.collect.ImmutableSortedMap import com.google.common.collect.ImmutableSortedSet import org.gradle.api.execution.TaskActionListener import org.gradle.api.internal.TaskInternal -import org.gradle.api.internal.cache.StringInterner +import org.gradle.api.internal.changedetection.TaskExecutionMode import org.gradle.api.internal.project.ProjectInternal import org.gradle.api.internal.tasks.ContextAwareTaskAction import org.gradle.api.internal.tasks.TaskExecutionContext @@ -33,7 +33,6 @@ import org.gradle.groovy.scripts.ScriptSource import org.gradle.initialization.DefaultBuildCancellationToken import org.gradle.internal.exceptions.DefaultMultiCauseException import org.gradle.internal.exceptions.MultiCauseException -import org.gradle.internal.execution.Context import org.gradle.internal.execution.OutputChangeListener import org.gradle.internal.execution.history.ExecutionHistoryStore import org.gradle.internal.execution.history.OutputFilesRepository @@ -41,6 +40,9 @@ import org.gradle.internal.execution.impl.DefaultWorkExecutor import org.gradle.internal.execution.impl.steps.CancelExecutionStep import org.gradle.internal.execution.impl.steps.CatchExceptionStep import org.gradle.internal.execution.impl.steps.ExecuteStep +import org.gradle.internal.execution.impl.steps.IncrementalChangesContext +import org.gradle.internal.execution.impl.steps.IncrementalContext +import org.gradle.internal.execution.impl.steps.ResolveChangesStep import org.gradle.internal.execution.impl.steps.SkipUpToDateStep import org.gradle.internal.execution.impl.steps.SnapshotOutputStep import org.gradle.internal.execution.impl.steps.UpToDateResult @@ -65,7 +67,6 @@ class ExecuteActionsTaskExecuterTest extends Specification { def standardOutputCapture = Mock(StandardOutputCapture) def buildOperationExecutor = Mock(BuildOperationExecutor) def asyncWorkTracker = Mock(AsyncWorkTracker) - def stringInterner = new StringInterner() def taskFingerprinter = Stub(TaskFingerprinter) { fingerprintTaskFiles(task, _) >> ImmutableSortedMap.of() } @@ -78,13 +79,15 @@ class ExecuteActionsTaskExecuterTest extends Specification { def actionListener = Mock(TaskActionListener) def outputChangeListener = Mock(OutputChangeListener) def cancellationToken = new DefaultBuildCancellationToken() - def workExecutor = new DefaultWorkExecutor( - new SkipUpToDateStep( - new SnapshotOutputStep( - buildId, - new CatchExceptionStep( - new CancelExecutionStep(cancellationToken, - new ExecuteStep(outputChangeListener) + def workExecutor = new DefaultWorkExecutor( + new ResolveChangesStep( + new SkipUpToDateStep( + new SnapshotOutputStep( + buildId, + new CatchExceptionStep( + new CancelExecutionStep(cancellationToken, + new ExecuteStep(outputChangeListener) + ) ) ) ) @@ -101,6 +104,7 @@ class ExecuteActionsTaskExecuterTest extends Specification { executionContext.getOutputFilesBeforeExecution() >> ImmutableSortedMap.of() executionContext.getOverlappingOutputs() >> Optional.empty() executionContext.getExecutionStateChanges() >> Optional.empty() + executionContext.getTaskExecutionMode() >> TaskExecutionMode.INCREMENTAL executionContext.getTaskProperties() >> taskProperties taskProperties.getOutputFileProperties() >> ImmutableSortedSet.of() diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/DefaultDependencyManagementServices.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/DefaultDependencyManagementServices.java index ebf284f41392a..38a81124a2b10 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/DefaultDependencyManagementServices.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/DefaultDependencyManagementServices.java @@ -106,18 +106,17 @@ import org.gradle.internal.component.external.model.ModuleComponentArtifactMetadata; import org.gradle.internal.component.model.ComponentAttributeMatcher; import org.gradle.internal.event.ListenerManager; -import org.gradle.internal.execution.Context; import org.gradle.internal.execution.OutputChangeListener; -import org.gradle.internal.execution.Result; import org.gradle.internal.execution.WorkExecutor; import org.gradle.internal.execution.history.ExecutionHistoryStore; import org.gradle.internal.execution.history.OutputFilesRepository; import org.gradle.internal.execution.impl.DefaultWorkExecutor; import org.gradle.internal.execution.impl.steps.CatchExceptionStep; import org.gradle.internal.execution.impl.steps.CreateOutputsStep; -import org.gradle.internal.execution.impl.steps.CurrentSnapshotResult; import org.gradle.internal.execution.impl.steps.ExecuteStep; +import org.gradle.internal.execution.impl.steps.IncrementalContext; import org.gradle.internal.execution.impl.steps.PrepareCachingStep; +import org.gradle.internal.execution.impl.steps.ResolveChangesStep; import org.gradle.internal.execution.impl.steps.SkipUpToDateStep; import org.gradle.internal.execution.impl.steps.SnapshotOutputStep; import org.gradle.internal.execution.impl.steps.StoreSnapshotsStep; @@ -198,7 +197,7 @@ OutputFileCollectionFingerprinter createOutputFingerprinter(FileSystemSnapshotte * * Currently used for running artifact transformations in buildscript blocks. */ - WorkExecutor createWorkExecutor( + WorkExecutor createWorkExecutor( TimeoutHandler timeoutHandler, ListenerManager listenerManager ) { OutputChangeListener outputChangeListener = listenerManager.getBroadcaster(OutputChangeListener.class); @@ -214,15 +213,17 @@ public void recordOutputs(Iterable outputFileFinge }; // TODO: Figure out how to get rid of origin scope id in snapshot outputs step UniqueId fixedUniqueId = UniqueId.from("dhwwyv4tqrd43cbxmdsf24wquu"); - return new DefaultWorkExecutor( - new SkipUpToDateStep( - new StoreSnapshotsStep(noopOutputFilesRepository, - new PrepareCachingStep( - new SnapshotOutputStep(fixedUniqueId, - new CreateOutputsStep( - new CatchExceptionStep( - new TimeoutStep(timeoutHandler, - new ExecuteStep(outputChangeListener) + return new DefaultWorkExecutor<>( + new ResolveChangesStep<>( + new SkipUpToDateStep<>( + new StoreSnapshotsStep<>(noopOutputFilesRepository, + new PrepareCachingStep<>( + new SnapshotOutputStep<>(fixedUniqueId, + new CreateOutputsStep<>( + new CatchExceptionStep<>( + new TimeoutStep<>(timeoutHandler, + new ExecuteStep(outputChangeListener) + ) ) ) ) @@ -254,7 +255,7 @@ MutableCachingTransformationWorkspaceProvider createCachingTransformerWorkspaceP return new MutableCachingTransformationWorkspaceProvider(workspaceProvider); } - TransformerInvoker createTransformerInvoker(WorkExecutor workExecutor, + TransformerInvoker createTransformerInvoker(WorkExecutor workExecutor, FileSystemSnapshotter fileSystemSnapshotter, ImmutableCachingTransformationWorkspaceProvider transformationWorkspaceProvider, ArtifactTransformListener artifactTransformListener, diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvoker.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvoker.java index 54e301ab70ae4..66291b74572ed 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvoker.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvoker.java @@ -31,16 +31,16 @@ import org.gradle.internal.UncheckedException; import org.gradle.internal.classloader.ClassLoaderHierarchyHasher; import org.gradle.internal.execution.CacheHandler; -import org.gradle.internal.execution.Context; import org.gradle.internal.execution.ExecutionOutcome; import org.gradle.internal.execution.UnitOfWork; import org.gradle.internal.execution.WorkExecutor; import org.gradle.internal.execution.history.AfterPreviousExecutionState; import org.gradle.internal.execution.history.BeforeExecutionState; import org.gradle.internal.execution.history.ExecutionHistoryStore; -import org.gradle.internal.execution.history.changes.DefaultExecutionStateChanges; -import org.gradle.internal.execution.history.changes.ExecutionStateChanges; +import org.gradle.internal.execution.history.changes.OutputFileChanges.OutputHandling; import org.gradle.internal.execution.history.impl.DefaultBeforeExecutionState; +import org.gradle.internal.execution.impl.steps.IncrementalChangesContext; +import org.gradle.internal.execution.impl.steps.IncrementalContext; import org.gradle.internal.execution.impl.steps.UpToDateResult; import org.gradle.internal.file.TreeType; import org.gradle.internal.fingerprint.CurrentFileCollectionFingerprint; @@ -85,14 +85,14 @@ public class DefaultTransformerInvoker implements TransformerInvoker { private static final String OUTPUT_FILE_PATH_PREFIX = "o/"; private final FileSystemSnapshotter fileSystemSnapshotter; - private final WorkExecutor workExecutor; + private final WorkExecutor workExecutor; private final ArtifactTransformListener artifactTransformListener; private final CachingTransformationWorkspaceProvider immutableTransformationWorkspaceProvider; private final FileCollectionFactory fileCollectionFactory; private final ClassLoaderHierarchyHasher classLoaderHierarchyHasher; private final ProjectFinder projectFinder; - public DefaultTransformerInvoker(WorkExecutor workExecutor, + public DefaultTransformerInvoker(WorkExecutor workExecutor, FileSystemSnapshotter fileSystemSnapshotter, ArtifactTransformListener artifactTransformListener, CachingTransformationWorkspaceProvider immutableTransformationWorkspaceProvider, @@ -124,7 +124,7 @@ public Try> invoke(Transformer transformer, File inputArtifa ExecutionHistoryStore executionHistoryStore = workspaceProvider.getExecutionHistoryStore(); FileCollectionFingerprinter outputFingerprinter = fingerprinterRegistry.getFingerprinter(OutputNormalizer.class); - AfterPreviousExecutionState afterPreviousExecutionState = executionHistoryStore.load(transformIdentity).orElse(null); + Optional afterPreviousExecutionState = executionHistoryStore.load(transformIdentity); ImplementationSnapshot implementationSnapshot = ImplementationSnapshot.of(transformer.getImplementationClass(), classLoaderHierarchyHasher); CurrentFileCollectionFingerprint inputArtifactFingerprint = inputArtifactFingerprinter.fingerprint(ImmutableList.of(inputArtifactSnapshot)); @@ -141,7 +141,6 @@ public Try> invoke(Transformer transformer, File inputArtifa TransformerExecution execution = new TransformerExecution( transformer, - afterPreviousExecutionState, beforeExecutionState, workspace, transformIdentity, @@ -152,11 +151,26 @@ public Try> invoke(Transformer transformer, File inputArtifa outputFingerprinter ); - UpToDateResult outcome = workExecutor.execute(new Context() { + UpToDateResult outcome = workExecutor.execute(new IncrementalContext() { @Override public UnitOfWork getWork() { return execution; } + + @Override + public Optional getRebuildReason() { + return Optional.empty(); + } + + @Override + public Optional getAfterPreviousExecutionState() { + return afterPreviousExecutionState; + } + + @Override + public Optional getBeforeExecutionState() { + return Optional.of(beforeExecutionState); + } }); return outcome.getOutcome() @@ -215,7 +229,6 @@ private Try> fireTransformListeners(Transformer transformer, private static class TransformerExecution implements UnitOfWork { private final Transformer transformer; - private final AfterPreviousExecutionState afterPreviousExecutionState; private final BeforeExecutionState beforeExecutionState; private final TransformationWorkspace workspace; private final File inputArtifact; @@ -228,7 +241,6 @@ private static class TransformerExecution implements UnitOfWork { public TransformerExecution( Transformer transformer, - @Nullable AfterPreviousExecutionState afterPreviousExecutionState, BeforeExecutionState beforeExecutionState, TransformationWorkspace workspace, String identityString, @@ -238,7 +250,6 @@ public TransformerExecution( ArtifactTransformDependencies dependencies, FileCollectionFingerprinter outputFingerprinter ) { - this.afterPreviousExecutionState = afterPreviousExecutionState; this.beforeExecutionState = beforeExecutionState; this.fileCollectionFactory = fileCollectionFactory; this.inputArtifact = inputArtifact; @@ -252,7 +263,7 @@ public TransformerExecution( } @Override - public ExecutionOutcome execute(Context context) { + public ExecutionOutcome execute(IncrementalChangesContext context) { File outputDir = workspace.getOutputDirectory(); File resultsFile = workspace.getResultsFile(); GFileUtils.cleanDirectory(outputDir); @@ -315,6 +326,11 @@ public void visitOutputProperties(OutputPropertyVisitor visitor) { visitor.visitOutputProperty(RESULTS_FILE_PROPERTY_NAME, TreeType.FILE, fileCollectionFactory.fixed(workspace.getResultsFile())); } + @Override + public OutputHandling getOutputHandling() { + return DETECT_ADDED; + } + @Override public long markExecutionTime() { return executionTimer.getElapsedMillis(); @@ -374,15 +390,6 @@ public void persistResult(ImmutableSortedMap getChangesSincePreviousExecution() { - if (afterPreviousExecutionState == null) { - return Optional.empty(); - } else { - return Optional.of(new DefaultExecutionStateChanges(afterPreviousExecutionState, beforeExecutionState, this, DETECT_ADDED)); - } - } - @Override public Optional> getChangingOutputs() { return Optional.of(ImmutableList.of(workspace.getOutputDirectory().getAbsolutePath(), workspace.getResultsFile().getAbsolutePath())); diff --git a/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/WorkExecutorTestFixture.java b/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/WorkExecutorTestFixture.java index c382a81a36290..79447c76e2f0f 100644 --- a/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/WorkExecutorTestFixture.java +++ b/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/WorkExecutorTestFixture.java @@ -22,10 +22,10 @@ import org.gradle.caching.internal.controller.BuildCacheStoreCommand; import org.gradle.initialization.BuildCancellationToken; import org.gradle.initialization.DefaultBuildCancellationToken; -import org.gradle.internal.execution.Context; import org.gradle.internal.execution.OutputChangeListener; import org.gradle.internal.execution.WorkExecutor; import org.gradle.internal.execution.history.OutputFilesRepository; +import org.gradle.internal.execution.impl.steps.IncrementalContext; import org.gradle.internal.execution.impl.steps.UpToDateResult; import org.gradle.internal.execution.timeout.impl.DefaultTimeoutHandler; import org.gradle.internal.id.UniqueId; @@ -68,7 +68,7 @@ public void close() { }; private BuildInvocationScopeId buildInvocationScopeId = new BuildInvocationScopeId(UniqueId.generate()); private BuildCancellationToken cancellationToken = new DefaultBuildCancellationToken(); - private final WorkExecutor workExecutor; + private final WorkExecutor workExecutor; WorkExecutorTestFixture(DefaultFileSystemMirror fileSystemMirror) { BuildCacheCommandFactory buildCacheCommandFactory = null; @@ -104,7 +104,7 @@ public void recordOutputs(Iterable outputFileFinge ); } - public WorkExecutor getWorkExecutor() { + public WorkExecutor getWorkExecutor() { return workExecutor; } } diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/UnitOfWork.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/UnitOfWork.java index 0da1de49d103a..594b81bcb18c1 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/UnitOfWork.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/UnitOfWork.java @@ -20,7 +20,8 @@ import org.gradle.api.file.FileCollection; import org.gradle.caching.internal.CacheableEntity; import org.gradle.caching.internal.origin.OriginMetadata; -import org.gradle.internal.execution.history.changes.ExecutionStateChanges; +import org.gradle.internal.execution.history.changes.OutputFileChanges.OutputHandling; +import org.gradle.internal.execution.impl.steps.IncrementalChangesContext; import org.gradle.internal.file.TreeType; import org.gradle.internal.fingerprint.CurrentFileCollectionFingerprint; @@ -32,7 +33,7 @@ public interface UnitOfWork extends CacheableEntity { /** * Executes the work synchronously. */ - ExecutionOutcome execute(Context context); + ExecutionOutcome execute(IncrementalChangesContext context); Optional getTimeout(); @@ -49,8 +50,6 @@ public interface UnitOfWork extends CacheableEntity { void persistResult(ImmutableSortedMap finalOutputs, boolean successful, OriginMetadata originMetadata); - Optional getChangesSincePreviousExecution(); - /** * Paths to locations changed by the unit of work. * @@ -63,6 +62,8 @@ public interface UnitOfWork extends CacheableEntity { */ Optional> getChangingOutputs(); + OutputHandling getOutputHandling(); + @FunctionalInterface interface OutputPropertyVisitor { void visitOutputProperty(String name, TreeType type, FileCollection roots); diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/impl/steps/CachingContext.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/impl/steps/CachingContext.java index 29f86d4469ea3..8774bc0cbcec7 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/impl/steps/CachingContext.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/impl/steps/CachingContext.java @@ -17,8 +17,7 @@ package org.gradle.internal.execution.impl.steps; import org.gradle.internal.execution.CacheHandler; -import org.gradle.internal.execution.Context; -public interface CachingContext extends Context { +public interface CachingContext extends IncrementalChangesContext { CacheHandler getCacheHandler(); } diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/impl/steps/ExecuteStep.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/impl/steps/ExecuteStep.java index fa9ded41048e9..d645b875e0309 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/impl/steps/ExecuteStep.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/impl/steps/ExecuteStep.java @@ -17,7 +17,6 @@ package org.gradle.internal.execution.impl.steps; import org.gradle.internal.Try; -import org.gradle.internal.execution.Context; import org.gradle.internal.execution.ExecutionOutcome; import org.gradle.internal.execution.OutputChangeListener; import org.gradle.internal.execution.Result; @@ -26,7 +25,7 @@ import java.util.Optional; -public class ExecuteStep implements Step { +public class ExecuteStep implements Step { private final OutputChangeListener outputChangeListener; @@ -37,7 +36,7 @@ public ExecuteStep( } @Override - public Result execute(Context context) { + public Result execute(IncrementalChangesContext context) { UnitOfWork work = context.getWork(); Optional> changingOutputs = work.getChangingOutputs(); diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/impl/steps/IncrementalChangesContext.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/impl/steps/IncrementalChangesContext.java new file mode 100644 index 0000000000000..45cb7e2f9416d --- /dev/null +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/impl/steps/IncrementalChangesContext.java @@ -0,0 +1,30 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.internal.execution.impl.steps; + +import org.gradle.internal.execution.Context; +import org.gradle.internal.execution.history.changes.ExecutionStateChanges; + +import java.util.Optional; + +public interface IncrementalChangesContext extends Context { + /** + * Returns changes detected between the execution state after the last execution and before the current execution. + * Empty if changes couldn't be detected (e.g. because history was unavailable). + */ + Optional getChanges(); +} diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/impl/steps/IncrementalContext.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/impl/steps/IncrementalContext.java new file mode 100644 index 0000000000000..1a3824548cb45 --- /dev/null +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/impl/steps/IncrementalContext.java @@ -0,0 +1,42 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.internal.execution.impl.steps; + +import org.gradle.internal.execution.Context; +import org.gradle.internal.execution.history.AfterPreviousExecutionState; +import org.gradle.internal.execution.history.BeforeExecutionState; + +import java.util.Optional; + +public interface IncrementalContext extends Context { + /** + * If incremental mode is disabled, this returns the reason, otherwise it's empty. + */ + Optional getRebuildReason(); + + /** + * Returns the execution state after the previous execution if available. + * Empty when execution history is not available. + */ + Optional getAfterPreviousExecutionState(); + + /** + * Returns the execution state before execution. + * Empty if execution state was not observed before execution. + */ + Optional getBeforeExecutionState(); +} diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/impl/steps/PrepareCachingStep.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/impl/steps/PrepareCachingStep.java index 371bdd39d427a..eec7443a45382 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/impl/steps/PrepareCachingStep.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/impl/steps/PrepareCachingStep.java @@ -17,12 +17,14 @@ package org.gradle.internal.execution.impl.steps; import org.gradle.internal.execution.CacheHandler; -import org.gradle.internal.execution.Context; import org.gradle.internal.execution.Result; import org.gradle.internal.execution.Step; import org.gradle.internal.execution.UnitOfWork; +import org.gradle.internal.execution.history.changes.ExecutionStateChanges; -public class PrepareCachingStep implements Step { +import java.util.Optional; + +public class PrepareCachingStep implements Step { private final Step delegate; public PrepareCachingStep(Step delegate) { @@ -38,6 +40,11 @@ public CacheHandler getCacheHandler() { return cacheHandler; } + @Override + public Optional getChanges() { + return context.getChanges(); + } + @Override public UnitOfWork getWork() { return context.getWork(); diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/impl/steps/ResolveChangesStep.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/impl/steps/ResolveChangesStep.java new file mode 100644 index 0000000000000..a26c26c76a6d6 --- /dev/null +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/impl/steps/ResolveChangesStep.java @@ -0,0 +1,97 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.internal.execution.impl.steps; + +import org.gradle.internal.change.Change; +import org.gradle.internal.change.ChangeVisitor; +import org.gradle.internal.change.DescriptiveChange; +import org.gradle.internal.execution.Result; +import org.gradle.internal.execution.Step; +import org.gradle.internal.execution.UnitOfWork; +import org.gradle.internal.execution.history.AfterPreviousExecutionState; +import org.gradle.internal.execution.history.changes.DefaultExecutionStateChanges; +import org.gradle.internal.execution.history.changes.ExecutionStateChanges; + +import java.util.Optional; + +public class ResolveChangesStep implements Step { + private final Step delegate; + + public ResolveChangesStep(Step delegate) { + this.delegate = delegate; + } + + @Override + public R execute(IncrementalContext context) { + ExecutionStateChanges changes = context.getRebuildReason() + .map(rebuildReason -> + new RebuildExecutionStateChanges(rebuildReason) + ) + .orElseGet(() -> + context.getAfterPreviousExecutionState() + .flatMap(afterPreviousExecution -> context.getBeforeExecutionState() + .map(beforeExecution -> new DefaultExecutionStateChanges( + afterPreviousExecution, + beforeExecution, + context.getWork(), + context.getWork().getOutputHandling()) + ) + ) + .orElse(null) + ); + + return delegate.execute(new IncrementalChangesContext() { + @Override + public Optional getChanges() { + return Optional.ofNullable(changes); + } + + @Override + public UnitOfWork getWork() { + return context.getWork(); + } + }); + } + + private static class RebuildExecutionStateChanges implements ExecutionStateChanges { + private final Change rebuildChange; + + public RebuildExecutionStateChanges(String rebuildReason) { + this.rebuildChange = new DescriptiveChange(rebuildReason); + } + + @Override + public Iterable getInputFilesChanges() { + throw new UnsupportedOperationException(); + } + + @Override + public void visitAllChanges(ChangeVisitor visitor) { + visitor.visitChange(rebuildChange); + } + + @Override + public boolean isRebuildRequired() { + return true; + } + + @Override + public AfterPreviousExecutionState getPreviousExecution() { + throw new UnsupportedOperationException(); + } + } +} diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/impl/steps/SkipUpToDateStep.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/impl/steps/SkipUpToDateStep.java index 3836177f3a312..f418f6d0d65fb 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/impl/steps/SkipUpToDateStep.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/impl/steps/SkipUpToDateStep.java @@ -24,7 +24,6 @@ import org.gradle.internal.Try; import org.gradle.internal.change.Change; import org.gradle.internal.change.ChangeVisitor; -import org.gradle.internal.execution.Context; import org.gradle.internal.execution.ExecutionOutcome; import org.gradle.internal.execution.Step; import org.gradle.internal.execution.UnitOfWork; @@ -35,7 +34,7 @@ import java.util.Formatter; import java.util.List; -public class SkipUpToDateStep implements Step { +public class SkipUpToDateStep implements Step { private static final Logger LOGGER = LoggerFactory.getLogger(SkipUpToDateStep.class); private static final ImmutableList NO_HISTORY = ImmutableList.of("No history is available."); @@ -51,7 +50,7 @@ public UpToDateResult execute(C context) { if (LOGGER.isDebugEnabled()) { LOGGER.debug("Determining if {} is up-to-date", context.getWork().getDisplayName()); } - return context.getWork().getChangesSincePreviousExecution().map(changes -> { + return context.getChanges().map(changes -> { ImmutableList.Builder builder = ImmutableList.builder(); MessageCollectingChangeVisitor visitor = new MessageCollectingChangeVisitor(builder, 3); changes.visitAllChanges(visitor); diff --git a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/impl/steps/CacheStepTest.groovy b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/impl/steps/CacheStepTest.groovy index 4c8ac26616561..2f13834a6c8b1 100644 --- a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/impl/steps/CacheStepTest.groovy +++ b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/impl/steps/CacheStepTest.groovy @@ -27,6 +27,7 @@ import org.gradle.internal.execution.ExecutionOutcome import org.gradle.internal.execution.OutputChangeListener import org.gradle.internal.execution.Step import org.gradle.internal.execution.UnitOfWork +import org.gradle.internal.execution.history.changes.ExecutionStateChanges import org.gradle.internal.fingerprint.CurrentFileCollectionFingerprint import org.gradle.internal.fingerprint.impl.EmptyCurrentFileCollectionFingerprint import org.gradle.internal.id.UniqueId @@ -45,9 +46,17 @@ class CacheStepTest extends Specification { def loadMetadata = Mock(BuildCacheCommandFactory.LoadMetadata) def cachedOriginMetadata = Mock(OriginMetadata) def context = new CachingContext() { + @Override CacheHandler getCacheHandler() { CacheStepTest.this.cacheHandler } + + @Override + Optional getChanges() { + return Optional.empty() + } + + @Override UnitOfWork getWork() { unitOfWork } diff --git a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/impl/steps/ExecutionTest.groovy b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/impl/steps/ExecutionTest.groovy index 67c40e9d90bc7..c276a279cac47 100644 --- a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/impl/steps/ExecutionTest.groovy +++ b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/impl/steps/ExecutionTest.groovy @@ -21,24 +21,26 @@ import org.gradle.api.BuildCancelledException import org.gradle.caching.internal.origin.OriginMetadata import org.gradle.initialization.DefaultBuildCancellationToken import org.gradle.internal.execution.CacheHandler -import org.gradle.internal.execution.Context import org.gradle.internal.execution.ExecutionException import org.gradle.internal.execution.ExecutionOutcome import org.gradle.internal.execution.OutputChangeListener import org.gradle.internal.execution.UnitOfWork import org.gradle.internal.execution.history.changes.ExecutionStateChanges +import org.gradle.internal.execution.history.changes.OutputFileChanges import org.gradle.internal.fingerprint.CurrentFileCollectionFingerprint import spock.lang.Specification import java.time.Duration import java.util.function.Supplier +import static org.gradle.internal.execution.history.changes.OutputFileChanges.OutputHandling.DETECT_ADDED + class ExecutionTest extends Specification { def outputChangeListener = Mock(OutputChangeListener) def cancellationToken = new DefaultBuildCancellationToken() - def executionStep = new CatchExceptionStep( - new CancelExecutionStep(cancellationToken, + def executionStep = new CatchExceptionStep( + new CancelExecutionStep(cancellationToken, new ExecuteStep(outputChangeListener) ) ) @@ -46,7 +48,7 @@ class ExecutionTest extends Specification { def "executes the unit of work with outcome: #outcome"() { def unitOfWork = new TestUnitOfWork({ -> outcome }) when: - def result = executionStep.execute { -> unitOfWork} + def result = execute { -> unitOfWork} then: unitOfWork.executed @@ -61,7 +63,7 @@ class ExecutionTest extends Specification { def "reports no work done"() { when: - def result = executionStep.execute { -> + def result = execute { -> new TestUnitOfWork({ -> return ExecutionOutcome.UP_TO_DATE }) @@ -81,7 +83,7 @@ class ExecutionTest extends Specification { }) when: - def result = executionStep.execute { -> unitOfWork } + def result = execute { -> unitOfWork } then: result.outcome.failure.get() instanceof ExecutionException @@ -97,7 +99,7 @@ class ExecutionTest extends Specification { def unitOfWork = new TestUnitOfWork({ -> ExecutionOutcome.EXECUTED_FULLY }, changingOutputs) when: - def result = executionStep.execute { -> unitOfWork } + def result = execute { -> unitOfWork } then: result.outcome.get() == ExecutionOutcome.EXECUTED_FULLY @@ -111,7 +113,7 @@ class ExecutionTest extends Specification { when: cancellationToken.cancel() - def result = executionStep.execute { -> unitOfWork } + def result = execute { -> unitOfWork } then: result.outcome.failure.get() instanceof ExecutionException @@ -134,7 +136,7 @@ class ExecutionTest extends Specification { boolean executed @Override - ExecutionOutcome execute(Context context) { + ExecutionOutcome execute(IncrementalChangesContext context) { executed = true return work.get() } @@ -149,6 +151,11 @@ class ExecutionTest extends Specification { throw new UnsupportedOperationException() } + @Override + OutputFileChanges.OutputHandling getOutputHandling() { + return DETECT_ADDED + } + @Override long markExecutionTime() { throw new UnsupportedOperationException() @@ -174,11 +181,6 @@ class ExecutionTest extends Specification { throw new UnsupportedOperationException() } - @Override - Optional getChangesSincePreviousExecution() { - throw new UnsupportedOperationException() - } - @Override Optional> getChangingOutputs() { Optional.ofNullable(changingOutputs) @@ -205,4 +207,17 @@ class ExecutionTest extends Specification { } } + def execute(Supplier work) { + executionStep.execute(new IncrementalChangesContext() { + @Override + Optional getChanges() { + return Optional.empty() + } + + @Override + UnitOfWork getWork() { + return work.get() + } + }) + } } diff --git a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/impl/steps/IncrementalExecutionTest.groovy b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/impl/steps/IncrementalExecutionTest.groovy index 407f6e3c59af6..1bd35c8bf684f 100644 --- a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/impl/steps/IncrementalExecutionTest.groovy +++ b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/impl/steps/IncrementalExecutionTest.groovy @@ -36,9 +36,8 @@ import org.gradle.internal.execution.TestExecutionHistoryStore import org.gradle.internal.execution.TestOutputFilesRepository import org.gradle.internal.execution.UnitOfWork import org.gradle.internal.execution.WorkExecutor -import org.gradle.internal.execution.history.changes.DefaultExecutionStateChanges import org.gradle.internal.execution.history.changes.ExecutionStateChanges -import org.gradle.internal.execution.history.impl.DefaultBeforeExecutionState +import org.gradle.internal.execution.history.changes.OutputFileChanges import org.gradle.internal.execution.impl.DefaultWorkExecutor import org.gradle.internal.file.TreeType import org.gradle.internal.fingerprint.CurrentFileCollectionFingerprint @@ -58,14 +57,17 @@ import org.gradle.test.fixtures.file.TestFile import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider import org.gradle.testing.internal.util.Specification import org.junit.Rule +import spock.lang.Ignore import java.time.Duration import java.util.function.Supplier import static org.gradle.internal.execution.ExecutionOutcome.EXECUTED_FULLY import static org.gradle.internal.execution.ExecutionOutcome.UP_TO_DATE -import static org.gradle.internal.execution.history.changes.OutputFileChanges.OutputHandling.IGNORE_ADDED +import static org.gradle.internal.execution.history.changes.OutputFileChanges.OutputHandling.DETECT_ADDED +// FIXME:lptr +@Ignore class IncrementalExecutionTest extends Specification { @Rule @@ -117,14 +119,16 @@ class IncrementalExecutionTest extends Specification { def unitOfWork = builder.build() - WorkExecutor getExecutor() { - new DefaultWorkExecutor( - new SkipUpToDateStep( - new StoreSnapshotsStep(outputFilesRepository, - new SnapshotOutputStep(buildInvocationScopeId.getId(), - new CreateOutputsStep( - new CatchExceptionStep( - new ExecuteStep(outputChangeListener) + WorkExecutor getExecutor() { + new DefaultWorkExecutor( + new ResolveChangesStep( + new SkipUpToDateStep( + new StoreSnapshotsStep(outputFilesRepository, + new SnapshotOutputStep(buildInvocationScopeId.getId(), + new CreateOutputsStep( + new CatchExceptionStep( + new ExecuteStep(outputChangeListener) + ) ) ) ) @@ -667,7 +671,7 @@ class IncrementalExecutionTest extends Specification { create.each { it -> it.createFile() } - return ExecutionOutcome.EXECUTED_FULLY + return EXECUTED_FULLY } private Map inputProperties = [prop: "value"] private Map> inputs = inputFiles @@ -742,7 +746,7 @@ class IncrementalExecutionTest extends Specification { boolean executed @Override - ExecutionOutcome execute(Context context) { + ExecutionOutcome execute(IncrementalChangesContext context) { executed = true return work.get() } @@ -759,6 +763,11 @@ class IncrementalExecutionTest extends Specification { } } + @Override + OutputFileChanges.OutputHandling getOutputHandling() { + return DETECT_ADDED + } + @Override long markExecutionTime() { 0 @@ -815,16 +824,6 @@ class IncrementalExecutionTest extends Specification { ImplementationSnapshot implementationSnapshot = implementation - - @Override - Optional getChangesSincePreviousExecution() { - changes = executionHistoryStore.load(getIdentity()).map { previous -> - def outputsBefore = snapshotOutputs() - def beforeExecutionState = new DefaultBeforeExecutionState(implementationSnapshot, additionalImplementationSnapshots, snapshotInputProperties(), snapshotInputFiles(), outputsBefore) - return new DefaultExecutionStateChanges(previous, beforeExecutionState, this, IGNORE_ADDED) - } - } - private ImmutableSortedMap snapshotInputProperties() { def builder = ImmutableSortedMap.naturalOrder() inputProperties.each { propertyName, value -> diff --git a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/impl/steps/SkipUpToDateStepTest.groovy b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/impl/steps/SkipUpToDateStepTest.groovy index fb86630e663a0..af2797ab7d4ca 100644 --- a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/impl/steps/SkipUpToDateStepTest.groovy +++ b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/impl/steps/SkipUpToDateStepTest.groovy @@ -18,7 +18,6 @@ package org.gradle.internal.execution.impl.steps import org.gradle.internal.change.ChangeVisitor import org.gradle.internal.change.DescriptiveChange -import org.gradle.internal.execution.Context import org.gradle.internal.execution.ExecutionOutcome import org.gradle.internal.execution.Step import org.gradle.internal.execution.UnitOfWork @@ -27,8 +26,8 @@ import org.gradle.testing.internal.util.Specification class SkipUpToDateStepTest extends Specification { def delegate = Mock(Step) - def step = new SkipUpToDateStep(delegate) - def context = Mock(Context) + def step = new SkipUpToDateStep(delegate) + def context = Mock(IncrementalChangesContext) def work = Mock(UnitOfWork) def changes = Mock(ExecutionStateChanges) @@ -40,8 +39,7 @@ class SkipUpToDateStepTest extends Specification { result.outcome.get() == ExecutionOutcome.UP_TO_DATE result.executionReasons.empty - _ * context.work >> work - 1 * work.changesSincePreviousExecution >> Optional.of(changes) + 1 * context.changes >> Optional.of(changes) 1 * changes.visitAllChanges(_) >> {} 0 * _ } @@ -53,8 +51,8 @@ class SkipUpToDateStepTest extends Specification { then: result.executionReasons == ["change"] - _ * context.work >> work - 1 * work.changesSincePreviousExecution >> Optional.of(changes) + 1 * context.getWork() >> work + 1 * context.changes >> Optional.of(changes) 1 * changes.visitAllChanges(_) >> { ChangeVisitor visitor -> visitor.visitChange(new DescriptiveChange("change")) } @@ -69,8 +67,8 @@ class SkipUpToDateStepTest extends Specification { then: result.executionReasons == ["No history is available."] - _ * context.work >> work - 1 * work.changesSincePreviousExecution >> Optional.empty() + 1 * context.getWork() >> work + 1 * context.changes >> Optional.empty() 1 * delegate.execute(context) 0 * _ } From 3c7c170db4d8580e40d84df9e93ec9118e013cd5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=B3r=C3=A1nt=20Pint=C3=A9r?= Date: Wed, 6 Mar 2019 16:14:30 +0100 Subject: [PATCH 347/853] Move contexts and results to top-level API --- .../execution/ExecuteActionsTaskExecuter.java | 6 ++-- .../execution/ProjectExecutionServices.java | 4 +-- .../scopes/ExecutionGradleServices.java | 32 +++++++++---------- .../ExecuteActionsTaskExecuterTest.groovy | 18 +++++------ .../DefaultDependencyManagementServices.java | 22 ++++++------- .../transform/DefaultTransformerInvoker.java | 6 ++-- .../transform/WorkExecutorTestFixture.java | 4 +-- .../{impl/steps => }/CachingContext.java | 4 +-- .../steps => }/CurrentSnapshotResult.java | 2 +- .../steps => }/IncrementalChangesContext.java | 3 +- .../{impl/steps => }/IncrementalContext.java | 3 +- .../{impl/steps => }/SnapshotResult.java | 3 +- .../gradle/internal/execution/UnitOfWork.java | 1 - .../{impl/steps => }/UpToDateResult.java | 2 +- .../execution/{impl => }/steps/CacheStep.java | 4 ++- .../{impl => }/steps/CancelExecutionStep.java | 2 +- .../{impl => }/steps/CatchExceptionStep.java | 2 +- .../{impl => }/steps/CreateOutputsStep.java | 2 +- .../{impl => }/steps/ExecuteStep.java | 3 +- .../{impl => }/steps/PrepareCachingStep.java | 4 ++- .../{impl => }/steps/ResolveChangesStep.java | 4 ++- .../{impl => }/steps/SkipUpToDateStep.java | 5 ++- .../{impl => }/steps/SnapshotOutputStep.java | 3 +- .../{impl => }/steps/StoreSnapshotsStep.java | 3 +- .../{impl => }/steps/TimeoutStep.java | 2 +- .../{impl => }/steps/package-info.java | 2 +- .../{impl => }/steps/CacheStepTest.groovy | 6 ++-- .../{impl => }/steps/ExecutionTest.groovy | 6 +++- .../steps/IncrementalExecutionTest.groovy | 5 ++- .../steps/SkipUpToDateStepTest.groovy | 4 ++- 30 files changed, 92 insertions(+), 75 deletions(-) rename subprojects/execution/src/main/java/org/gradle/internal/execution/{impl/steps => }/CachingContext.java (87%) rename subprojects/execution/src/main/java/org/gradle/internal/execution/{impl/steps => }/CurrentSnapshotResult.java (94%) rename subprojects/execution/src/main/java/org/gradle/internal/execution/{impl/steps => }/IncrementalChangesContext.java (91%) rename subprojects/execution/src/main/java/org/gradle/internal/execution/{impl/steps => }/IncrementalContext.java (93%) rename subprojects/execution/src/main/java/org/gradle/internal/execution/{impl/steps => }/SnapshotResult.java (91%) rename subprojects/execution/src/main/java/org/gradle/internal/execution/{impl/steps => }/UpToDateResult.java (95%) rename subprojects/execution/src/main/java/org/gradle/internal/execution/{impl => }/steps/CacheStep.java (97%) rename subprojects/execution/src/main/java/org/gradle/internal/execution/{impl => }/steps/CancelExecutionStep.java (96%) rename subprojects/execution/src/main/java/org/gradle/internal/execution/{impl => }/steps/CatchExceptionStep.java (96%) rename subprojects/execution/src/main/java/org/gradle/internal/execution/{impl => }/steps/CreateOutputsStep.java (97%) rename subprojects/execution/src/main/java/org/gradle/internal/execution/{impl => }/steps/ExecuteStep.java (94%) rename subprojects/execution/src/main/java/org/gradle/internal/execution/{impl => }/steps/PrepareCachingStep.java (91%) rename subprojects/execution/src/main/java/org/gradle/internal/execution/{impl => }/steps/ResolveChangesStep.java (95%) rename subprojects/execution/src/main/java/org/gradle/internal/execution/{impl => }/steps/SkipUpToDateStep.java (96%) rename subprojects/execution/src/main/java/org/gradle/internal/execution/{impl => }/steps/SnapshotOutputStep.java (96%) rename subprojects/execution/src/main/java/org/gradle/internal/execution/{impl => }/steps/StoreSnapshotsStep.java (94%) rename subprojects/execution/src/main/java/org/gradle/internal/execution/{impl => }/steps/TimeoutStep.java (98%) rename subprojects/execution/src/main/java/org/gradle/internal/execution/{impl => }/steps/package-info.java (92%) rename subprojects/execution/src/test/groovy/org/gradle/internal/execution/{impl => }/steps/CacheStepTest.groovy (97%) rename subprojects/execution/src/test/groovy/org/gradle/internal/execution/{impl => }/steps/ExecutionTest.groovy (96%) rename subprojects/execution/src/test/groovy/org/gradle/internal/execution/{impl => }/steps/IncrementalExecutionTest.groovy (99%) rename subprojects/execution/src/test/groovy/org/gradle/internal/execution/{impl => }/steps/SkipUpToDateStepTest.groovy (93%) diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuter.java b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuter.java index cf9a2aea2c8e5..c20ad7290d74b 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuter.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuter.java @@ -43,7 +43,10 @@ import org.gradle.internal.execution.CacheHandler; import org.gradle.internal.execution.ExecutionException; import org.gradle.internal.execution.ExecutionOutcome; +import org.gradle.internal.execution.IncrementalChangesContext; +import org.gradle.internal.execution.IncrementalContext; import org.gradle.internal.execution.UnitOfWork; +import org.gradle.internal.execution.UpToDateResult; import org.gradle.internal.execution.WorkExecutor; import org.gradle.internal.execution.history.AfterPreviousExecutionState; import org.gradle.internal.execution.history.BeforeExecutionState; @@ -53,9 +56,6 @@ import org.gradle.internal.execution.history.changes.OutputFileChanges; import org.gradle.internal.execution.history.changes.OutputFileChanges.OutputHandling; import org.gradle.internal.execution.impl.OutputFilterUtil; -import org.gradle.internal.execution.impl.steps.IncrementalChangesContext; -import org.gradle.internal.execution.impl.steps.IncrementalContext; -import org.gradle.internal.execution.impl.steps.UpToDateResult; import org.gradle.internal.fingerprint.CurrentFileCollectionFingerprint; import org.gradle.internal.fingerprint.FileCollectionFingerprint; import org.gradle.internal.operations.BuildOperationContext; diff --git a/subprojects/core/src/main/java/org/gradle/execution/ProjectExecutionServices.java b/subprojects/core/src/main/java/org/gradle/execution/ProjectExecutionServices.java index f3ddc8c7d50be..722bfc249ee20 100644 --- a/subprojects/core/src/main/java/org/gradle/execution/ProjectExecutionServices.java +++ b/subprojects/core/src/main/java/org/gradle/execution/ProjectExecutionServices.java @@ -55,12 +55,12 @@ import org.gradle.internal.classloader.ClassLoaderHierarchyHasher; import org.gradle.internal.cleanup.BuildOutputCleanupRegistry; import org.gradle.internal.event.ListenerManager; +import org.gradle.internal.execution.IncrementalContext; import org.gradle.internal.execution.OutputChangeListener; +import org.gradle.internal.execution.UpToDateResult; import org.gradle.internal.execution.WorkExecutor; import org.gradle.internal.execution.history.ExecutionHistoryStore; import org.gradle.internal.execution.history.OutputFilesRepository; -import org.gradle.internal.execution.impl.steps.IncrementalContext; -import org.gradle.internal.execution.impl.steps.UpToDateResult; import org.gradle.internal.fingerprint.FileCollectionFingerprinter; import org.gradle.internal.fingerprint.FileCollectionFingerprinterRegistry; import org.gradle.internal.fingerprint.classpath.ClasspathFingerprinter; diff --git a/subprojects/core/src/main/java/org/gradle/internal/service/scopes/ExecutionGradleServices.java b/subprojects/core/src/main/java/org/gradle/internal/service/scopes/ExecutionGradleServices.java index 85b03220e6066..9bc159cd58ef3 100644 --- a/subprojects/core/src/main/java/org/gradle/internal/service/scopes/ExecutionGradleServices.java +++ b/subprojects/core/src/main/java/org/gradle/internal/service/scopes/ExecutionGradleServices.java @@ -31,8 +31,13 @@ import org.gradle.internal.concurrent.ExecutorFactory; import org.gradle.internal.concurrent.ParallelismConfigurationManager; import org.gradle.internal.event.ListenerManager; +import org.gradle.internal.execution.CachingContext; +import org.gradle.internal.execution.CurrentSnapshotResult; +import org.gradle.internal.execution.IncrementalChangesContext; +import org.gradle.internal.execution.IncrementalContext; import org.gradle.internal.execution.OutputChangeListener; import org.gradle.internal.execution.Result; +import org.gradle.internal.execution.UpToDateResult; import org.gradle.internal.execution.WorkExecutor; import org.gradle.internal.execution.history.ExecutionHistoryCacheAccess; import org.gradle.internal.execution.history.ExecutionHistoryStore; @@ -40,22 +45,17 @@ import org.gradle.internal.execution.history.impl.DefaultExecutionHistoryStore; import org.gradle.internal.execution.history.impl.DefaultOutputFilesRepository; import org.gradle.internal.execution.impl.DefaultWorkExecutor; -import org.gradle.internal.execution.impl.steps.CacheStep; -import org.gradle.internal.execution.impl.steps.CachingContext; -import org.gradle.internal.execution.impl.steps.CancelExecutionStep; -import org.gradle.internal.execution.impl.steps.CatchExceptionStep; -import org.gradle.internal.execution.impl.steps.CreateOutputsStep; -import org.gradle.internal.execution.impl.steps.CurrentSnapshotResult; -import org.gradle.internal.execution.impl.steps.ExecuteStep; -import org.gradle.internal.execution.impl.steps.IncrementalChangesContext; -import org.gradle.internal.execution.impl.steps.IncrementalContext; -import org.gradle.internal.execution.impl.steps.PrepareCachingStep; -import org.gradle.internal.execution.impl.steps.ResolveChangesStep; -import org.gradle.internal.execution.impl.steps.SkipUpToDateStep; -import org.gradle.internal.execution.impl.steps.SnapshotOutputStep; -import org.gradle.internal.execution.impl.steps.StoreSnapshotsStep; -import org.gradle.internal.execution.impl.steps.TimeoutStep; -import org.gradle.internal.execution.impl.steps.UpToDateResult; +import org.gradle.internal.execution.steps.CacheStep; +import org.gradle.internal.execution.steps.CancelExecutionStep; +import org.gradle.internal.execution.steps.CatchExceptionStep; +import org.gradle.internal.execution.steps.CreateOutputsStep; +import org.gradle.internal.execution.steps.ExecuteStep; +import org.gradle.internal.execution.steps.PrepareCachingStep; +import org.gradle.internal.execution.steps.ResolveChangesStep; +import org.gradle.internal.execution.steps.SkipUpToDateStep; +import org.gradle.internal.execution.steps.SnapshotOutputStep; +import org.gradle.internal.execution.steps.StoreSnapshotsStep; +import org.gradle.internal.execution.steps.TimeoutStep; import org.gradle.internal.execution.timeout.TimeoutHandler; import org.gradle.internal.resources.ResourceLockCoordinationService; import org.gradle.internal.scopeids.id.BuildInvocationScopeId; diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuterTest.groovy b/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuterTest.groovy index 27ec1516a4505..162bae30987ec 100644 --- a/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuterTest.groovy +++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuterTest.groovy @@ -33,19 +33,19 @@ import org.gradle.groovy.scripts.ScriptSource import org.gradle.initialization.DefaultBuildCancellationToken import org.gradle.internal.exceptions.DefaultMultiCauseException import org.gradle.internal.exceptions.MultiCauseException +import org.gradle.internal.execution.IncrementalChangesContext +import org.gradle.internal.execution.IncrementalContext import org.gradle.internal.execution.OutputChangeListener +import org.gradle.internal.execution.UpToDateResult import org.gradle.internal.execution.history.ExecutionHistoryStore import org.gradle.internal.execution.history.OutputFilesRepository import org.gradle.internal.execution.impl.DefaultWorkExecutor -import org.gradle.internal.execution.impl.steps.CancelExecutionStep -import org.gradle.internal.execution.impl.steps.CatchExceptionStep -import org.gradle.internal.execution.impl.steps.ExecuteStep -import org.gradle.internal.execution.impl.steps.IncrementalChangesContext -import org.gradle.internal.execution.impl.steps.IncrementalContext -import org.gradle.internal.execution.impl.steps.ResolveChangesStep -import org.gradle.internal.execution.impl.steps.SkipUpToDateStep -import org.gradle.internal.execution.impl.steps.SnapshotOutputStep -import org.gradle.internal.execution.impl.steps.UpToDateResult +import org.gradle.internal.execution.steps.CancelExecutionStep +import org.gradle.internal.execution.steps.CatchExceptionStep +import org.gradle.internal.execution.steps.ExecuteStep +import org.gradle.internal.execution.steps.ResolveChangesStep +import org.gradle.internal.execution.steps.SkipUpToDateStep +import org.gradle.internal.execution.steps.SnapshotOutputStep import org.gradle.internal.id.UniqueId import org.gradle.internal.operations.BuildOperationContext import org.gradle.internal.operations.BuildOperationExecutor diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/DefaultDependencyManagementServices.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/DefaultDependencyManagementServices.java index 38a81124a2b10..ccd4bfae51292 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/DefaultDependencyManagementServices.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/DefaultDependencyManagementServices.java @@ -106,22 +106,22 @@ import org.gradle.internal.component.external.model.ModuleComponentArtifactMetadata; import org.gradle.internal.component.model.ComponentAttributeMatcher; import org.gradle.internal.event.ListenerManager; +import org.gradle.internal.execution.IncrementalContext; import org.gradle.internal.execution.OutputChangeListener; +import org.gradle.internal.execution.UpToDateResult; import org.gradle.internal.execution.WorkExecutor; import org.gradle.internal.execution.history.ExecutionHistoryStore; import org.gradle.internal.execution.history.OutputFilesRepository; import org.gradle.internal.execution.impl.DefaultWorkExecutor; -import org.gradle.internal.execution.impl.steps.CatchExceptionStep; -import org.gradle.internal.execution.impl.steps.CreateOutputsStep; -import org.gradle.internal.execution.impl.steps.ExecuteStep; -import org.gradle.internal.execution.impl.steps.IncrementalContext; -import org.gradle.internal.execution.impl.steps.PrepareCachingStep; -import org.gradle.internal.execution.impl.steps.ResolveChangesStep; -import org.gradle.internal.execution.impl.steps.SkipUpToDateStep; -import org.gradle.internal.execution.impl.steps.SnapshotOutputStep; -import org.gradle.internal.execution.impl.steps.StoreSnapshotsStep; -import org.gradle.internal.execution.impl.steps.TimeoutStep; -import org.gradle.internal.execution.impl.steps.UpToDateResult; +import org.gradle.internal.execution.steps.CatchExceptionStep; +import org.gradle.internal.execution.steps.CreateOutputsStep; +import org.gradle.internal.execution.steps.ExecuteStep; +import org.gradle.internal.execution.steps.PrepareCachingStep; +import org.gradle.internal.execution.steps.ResolveChangesStep; +import org.gradle.internal.execution.steps.SkipUpToDateStep; +import org.gradle.internal.execution.steps.SnapshotOutputStep; +import org.gradle.internal.execution.steps.StoreSnapshotsStep; +import org.gradle.internal.execution.steps.TimeoutStep; import org.gradle.internal.execution.timeout.TimeoutHandler; import org.gradle.internal.fingerprint.FileCollectionFingerprinterRegistry; import org.gradle.internal.fingerprint.impl.OutputFileCollectionFingerprinter; diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvoker.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvoker.java index 66291b74572ed..458da72a4d634 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvoker.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvoker.java @@ -32,16 +32,16 @@ import org.gradle.internal.classloader.ClassLoaderHierarchyHasher; import org.gradle.internal.execution.CacheHandler; import org.gradle.internal.execution.ExecutionOutcome; +import org.gradle.internal.execution.IncrementalChangesContext; +import org.gradle.internal.execution.IncrementalContext; import org.gradle.internal.execution.UnitOfWork; +import org.gradle.internal.execution.UpToDateResult; import org.gradle.internal.execution.WorkExecutor; import org.gradle.internal.execution.history.AfterPreviousExecutionState; import org.gradle.internal.execution.history.BeforeExecutionState; import org.gradle.internal.execution.history.ExecutionHistoryStore; import org.gradle.internal.execution.history.changes.OutputFileChanges.OutputHandling; import org.gradle.internal.execution.history.impl.DefaultBeforeExecutionState; -import org.gradle.internal.execution.impl.steps.IncrementalChangesContext; -import org.gradle.internal.execution.impl.steps.IncrementalContext; -import org.gradle.internal.execution.impl.steps.UpToDateResult; import org.gradle.internal.file.TreeType; import org.gradle.internal.fingerprint.CurrentFileCollectionFingerprint; import org.gradle.internal.fingerprint.FileCollectionFingerprinter; diff --git a/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/WorkExecutorTestFixture.java b/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/WorkExecutorTestFixture.java index 79447c76e2f0f..521a3911e43fd 100644 --- a/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/WorkExecutorTestFixture.java +++ b/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/WorkExecutorTestFixture.java @@ -22,11 +22,11 @@ import org.gradle.caching.internal.controller.BuildCacheStoreCommand; import org.gradle.initialization.BuildCancellationToken; import org.gradle.initialization.DefaultBuildCancellationToken; +import org.gradle.internal.execution.IncrementalContext; import org.gradle.internal.execution.OutputChangeListener; +import org.gradle.internal.execution.UpToDateResult; import org.gradle.internal.execution.WorkExecutor; import org.gradle.internal.execution.history.OutputFilesRepository; -import org.gradle.internal.execution.impl.steps.IncrementalContext; -import org.gradle.internal.execution.impl.steps.UpToDateResult; import org.gradle.internal.execution.timeout.impl.DefaultTimeoutHandler; import org.gradle.internal.id.UniqueId; import org.gradle.internal.scopeids.id.BuildInvocationScopeId; diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/impl/steps/CachingContext.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/CachingContext.java similarity index 87% rename from subprojects/execution/src/main/java/org/gradle/internal/execution/impl/steps/CachingContext.java rename to subprojects/execution/src/main/java/org/gradle/internal/execution/CachingContext.java index 8774bc0cbcec7..4eb922f9f7224 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/impl/steps/CachingContext.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/CachingContext.java @@ -14,9 +14,7 @@ * limitations under the License. */ -package org.gradle.internal.execution.impl.steps; - -import org.gradle.internal.execution.CacheHandler; +package org.gradle.internal.execution; public interface CachingContext extends IncrementalChangesContext { CacheHandler getCacheHandler(); diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/impl/steps/CurrentSnapshotResult.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/CurrentSnapshotResult.java similarity index 94% rename from subprojects/execution/src/main/java/org/gradle/internal/execution/impl/steps/CurrentSnapshotResult.java rename to subprojects/execution/src/main/java/org/gradle/internal/execution/CurrentSnapshotResult.java index 0e3572fc7ed9a..f9b99d406d7a9 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/impl/steps/CurrentSnapshotResult.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/CurrentSnapshotResult.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.gradle.internal.execution.impl.steps; +package org.gradle.internal.execution; import com.google.common.collect.ImmutableSortedMap; import org.gradle.internal.fingerprint.CurrentFileCollectionFingerprint; diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/impl/steps/IncrementalChangesContext.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/IncrementalChangesContext.java similarity index 91% rename from subprojects/execution/src/main/java/org/gradle/internal/execution/impl/steps/IncrementalChangesContext.java rename to subprojects/execution/src/main/java/org/gradle/internal/execution/IncrementalChangesContext.java index 45cb7e2f9416d..67537cf9a9efe 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/impl/steps/IncrementalChangesContext.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/IncrementalChangesContext.java @@ -14,9 +14,8 @@ * limitations under the License. */ -package org.gradle.internal.execution.impl.steps; +package org.gradle.internal.execution; -import org.gradle.internal.execution.Context; import org.gradle.internal.execution.history.changes.ExecutionStateChanges; import java.util.Optional; diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/impl/steps/IncrementalContext.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/IncrementalContext.java similarity index 93% rename from subprojects/execution/src/main/java/org/gradle/internal/execution/impl/steps/IncrementalContext.java rename to subprojects/execution/src/main/java/org/gradle/internal/execution/IncrementalContext.java index 1a3824548cb45..0e22eb6d9c4d2 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/impl/steps/IncrementalContext.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/IncrementalContext.java @@ -14,9 +14,8 @@ * limitations under the License. */ -package org.gradle.internal.execution.impl.steps; +package org.gradle.internal.execution; -import org.gradle.internal.execution.Context; import org.gradle.internal.execution.history.AfterPreviousExecutionState; import org.gradle.internal.execution.history.BeforeExecutionState; diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/impl/steps/SnapshotResult.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/SnapshotResult.java similarity index 91% rename from subprojects/execution/src/main/java/org/gradle/internal/execution/impl/steps/SnapshotResult.java rename to subprojects/execution/src/main/java/org/gradle/internal/execution/SnapshotResult.java index 1b369970485ef..dc3b7e5b0538b 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/impl/steps/SnapshotResult.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/SnapshotResult.java @@ -14,11 +14,10 @@ * limitations under the License. */ -package org.gradle.internal.execution.impl.steps; +package org.gradle.internal.execution; import com.google.common.collect.ImmutableSortedMap; import org.gradle.caching.internal.origin.OriginMetadata; -import org.gradle.internal.execution.Result; import org.gradle.internal.fingerprint.FileCollectionFingerprint; public interface SnapshotResult extends Result { diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/UnitOfWork.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/UnitOfWork.java index 594b81bcb18c1..2ad4b047ae2e1 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/UnitOfWork.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/UnitOfWork.java @@ -21,7 +21,6 @@ import org.gradle.caching.internal.CacheableEntity; import org.gradle.caching.internal.origin.OriginMetadata; import org.gradle.internal.execution.history.changes.OutputFileChanges.OutputHandling; -import org.gradle.internal.execution.impl.steps.IncrementalChangesContext; import org.gradle.internal.file.TreeType; import org.gradle.internal.fingerprint.CurrentFileCollectionFingerprint; diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/impl/steps/UpToDateResult.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/UpToDateResult.java similarity index 95% rename from subprojects/execution/src/main/java/org/gradle/internal/execution/impl/steps/UpToDateResult.java rename to subprojects/execution/src/main/java/org/gradle/internal/execution/UpToDateResult.java index 34ce5150bb1b3..2dfc8144a9d70 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/impl/steps/UpToDateResult.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/UpToDateResult.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.gradle.internal.execution.impl.steps; +package org.gradle.internal.execution; import com.google.common.collect.ImmutableList; diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/impl/steps/CacheStep.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/CacheStep.java similarity index 97% rename from subprojects/execution/src/main/java/org/gradle/internal/execution/impl/steps/CacheStep.java rename to subprojects/execution/src/main/java/org/gradle/internal/execution/steps/CacheStep.java index 1fd25651ffff7..78d9e946ea71a 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/impl/steps/CacheStep.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/CacheStep.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.gradle.internal.execution.impl.steps; +package org.gradle.internal.execution.steps; import com.google.common.collect.ImmutableSortedMap; import org.gradle.caching.BuildCacheKey; @@ -24,6 +24,8 @@ import org.gradle.caching.internal.origin.OriginMetadata; import org.gradle.caching.internal.packaging.UnrecoverableUnpackingException; import org.gradle.internal.Try; +import org.gradle.internal.execution.CachingContext; +import org.gradle.internal.execution.CurrentSnapshotResult; import org.gradle.internal.execution.ExecutionOutcome; import org.gradle.internal.execution.OutputChangeListener; import org.gradle.internal.execution.Step; diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/impl/steps/CancelExecutionStep.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/CancelExecutionStep.java similarity index 96% rename from subprojects/execution/src/main/java/org/gradle/internal/execution/impl/steps/CancelExecutionStep.java rename to subprojects/execution/src/main/java/org/gradle/internal/execution/steps/CancelExecutionStep.java index 8ce6ed569dcbf..a5b94be40ac34 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/impl/steps/CancelExecutionStep.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/CancelExecutionStep.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.gradle.internal.execution.impl.steps; +package org.gradle.internal.execution.steps; import org.gradle.api.BuildCancelledException; import org.gradle.initialization.BuildCancellationToken; diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/impl/steps/CatchExceptionStep.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/CatchExceptionStep.java similarity index 96% rename from subprojects/execution/src/main/java/org/gradle/internal/execution/impl/steps/CatchExceptionStep.java rename to subprojects/execution/src/main/java/org/gradle/internal/execution/steps/CatchExceptionStep.java index 1c50536c9d8d0..d218491c83299 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/impl/steps/CatchExceptionStep.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/CatchExceptionStep.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.gradle.internal.execution.impl.steps; +package org.gradle.internal.execution.steps; import org.gradle.internal.Try; import org.gradle.internal.execution.Context; diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/impl/steps/CreateOutputsStep.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/CreateOutputsStep.java similarity index 97% rename from subprojects/execution/src/main/java/org/gradle/internal/execution/impl/steps/CreateOutputsStep.java rename to subprojects/execution/src/main/java/org/gradle/internal/execution/steps/CreateOutputsStep.java index 1372bec821fd5..28b1f77578434 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/impl/steps/CreateOutputsStep.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/CreateOutputsStep.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.gradle.internal.execution.impl.steps; +package org.gradle.internal.execution.steps; import org.gradle.api.file.FileCollection; import org.gradle.internal.execution.Context; diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/impl/steps/ExecuteStep.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/ExecuteStep.java similarity index 94% rename from subprojects/execution/src/main/java/org/gradle/internal/execution/impl/steps/ExecuteStep.java rename to subprojects/execution/src/main/java/org/gradle/internal/execution/steps/ExecuteStep.java index d645b875e0309..a28c5573c9f42 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/impl/steps/ExecuteStep.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/ExecuteStep.java @@ -14,10 +14,11 @@ * limitations under the License. */ -package org.gradle.internal.execution.impl.steps; +package org.gradle.internal.execution.steps; import org.gradle.internal.Try; import org.gradle.internal.execution.ExecutionOutcome; +import org.gradle.internal.execution.IncrementalChangesContext; import org.gradle.internal.execution.OutputChangeListener; import org.gradle.internal.execution.Result; import org.gradle.internal.execution.Step; diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/impl/steps/PrepareCachingStep.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/PrepareCachingStep.java similarity index 91% rename from subprojects/execution/src/main/java/org/gradle/internal/execution/impl/steps/PrepareCachingStep.java rename to subprojects/execution/src/main/java/org/gradle/internal/execution/steps/PrepareCachingStep.java index eec7443a45382..babdf46d4dbc6 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/impl/steps/PrepareCachingStep.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/PrepareCachingStep.java @@ -14,9 +14,11 @@ * limitations under the License. */ -package org.gradle.internal.execution.impl.steps; +package org.gradle.internal.execution.steps; import org.gradle.internal.execution.CacheHandler; +import org.gradle.internal.execution.CachingContext; +import org.gradle.internal.execution.IncrementalChangesContext; import org.gradle.internal.execution.Result; import org.gradle.internal.execution.Step; import org.gradle.internal.execution.UnitOfWork; diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/impl/steps/ResolveChangesStep.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/ResolveChangesStep.java similarity index 95% rename from subprojects/execution/src/main/java/org/gradle/internal/execution/impl/steps/ResolveChangesStep.java rename to subprojects/execution/src/main/java/org/gradle/internal/execution/steps/ResolveChangesStep.java index a26c26c76a6d6..5a37e51d9a863 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/impl/steps/ResolveChangesStep.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/ResolveChangesStep.java @@ -14,11 +14,13 @@ * limitations under the License. */ -package org.gradle.internal.execution.impl.steps; +package org.gradle.internal.execution.steps; import org.gradle.internal.change.Change; import org.gradle.internal.change.ChangeVisitor; import org.gradle.internal.change.DescriptiveChange; +import org.gradle.internal.execution.IncrementalChangesContext; +import org.gradle.internal.execution.IncrementalContext; import org.gradle.internal.execution.Result; import org.gradle.internal.execution.Step; import org.gradle.internal.execution.UnitOfWork; diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/impl/steps/SkipUpToDateStep.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/SkipUpToDateStep.java similarity index 96% rename from subprojects/execution/src/main/java/org/gradle/internal/execution/impl/steps/SkipUpToDateStep.java rename to subprojects/execution/src/main/java/org/gradle/internal/execution/steps/SkipUpToDateStep.java index f418f6d0d65fb..25dd99fe70a89 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/impl/steps/SkipUpToDateStep.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/SkipUpToDateStep.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.gradle.internal.execution.impl.steps; +package org.gradle.internal.execution.steps; import com.google.common.collect.ImmutableCollection; import com.google.common.collect.ImmutableList; @@ -25,8 +25,11 @@ import org.gradle.internal.change.Change; import org.gradle.internal.change.ChangeVisitor; import org.gradle.internal.execution.ExecutionOutcome; +import org.gradle.internal.execution.IncrementalChangesContext; +import org.gradle.internal.execution.SnapshotResult; import org.gradle.internal.execution.Step; import org.gradle.internal.execution.UnitOfWork; +import org.gradle.internal.execution.UpToDateResult; import org.gradle.internal.fingerprint.FileCollectionFingerprint; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/impl/steps/SnapshotOutputStep.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/SnapshotOutputStep.java similarity index 96% rename from subprojects/execution/src/main/java/org/gradle/internal/execution/impl/steps/SnapshotOutputStep.java rename to subprojects/execution/src/main/java/org/gradle/internal/execution/steps/SnapshotOutputStep.java index e1d1c8d4c470e..ae4bcdadaf84c 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/impl/steps/SnapshotOutputStep.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/SnapshotOutputStep.java @@ -14,12 +14,13 @@ * limitations under the License. */ -package org.gradle.internal.execution.impl.steps; +package org.gradle.internal.execution.steps; import com.google.common.collect.ImmutableSortedMap; import org.gradle.caching.internal.origin.OriginMetadata; import org.gradle.internal.Try; import org.gradle.internal.execution.Context; +import org.gradle.internal.execution.CurrentSnapshotResult; import org.gradle.internal.execution.ExecutionOutcome; import org.gradle.internal.execution.Result; import org.gradle.internal.execution.Step; diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/impl/steps/StoreSnapshotsStep.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/StoreSnapshotsStep.java similarity index 94% rename from subprojects/execution/src/main/java/org/gradle/internal/execution/impl/steps/StoreSnapshotsStep.java rename to subprojects/execution/src/main/java/org/gradle/internal/execution/steps/StoreSnapshotsStep.java index d574f7fbc8b02..672ff607c445d 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/impl/steps/StoreSnapshotsStep.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/StoreSnapshotsStep.java @@ -14,10 +14,11 @@ * limitations under the License. */ -package org.gradle.internal.execution.impl.steps; +package org.gradle.internal.execution.steps; import com.google.common.collect.ImmutableSortedMap; import org.gradle.internal.execution.Context; +import org.gradle.internal.execution.CurrentSnapshotResult; import org.gradle.internal.execution.Step; import org.gradle.internal.execution.history.OutputFilesRepository; import org.gradle.internal.fingerprint.CurrentFileCollectionFingerprint; diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/impl/steps/TimeoutStep.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/TimeoutStep.java similarity index 98% rename from subprojects/execution/src/main/java/org/gradle/internal/execution/impl/steps/TimeoutStep.java rename to subprojects/execution/src/main/java/org/gradle/internal/execution/steps/TimeoutStep.java index a5a1ab0cbb703..30b5e75dbd938 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/impl/steps/TimeoutStep.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/TimeoutStep.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.gradle.internal.execution.impl.steps; +package org.gradle.internal.execution.steps; import org.gradle.api.GradleException; import org.gradle.api.InvalidUserDataException; diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/impl/steps/package-info.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/package-info.java similarity index 92% rename from subprojects/execution/src/main/java/org/gradle/internal/execution/impl/steps/package-info.java rename to subprojects/execution/src/main/java/org/gradle/internal/execution/steps/package-info.java index 7b966c361628d..7564fbd4646de 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/impl/steps/package-info.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/package-info.java @@ -14,6 +14,6 @@ * limitations under the License. */ @NonNullApi -package org.gradle.internal.execution.impl.steps; +package org.gradle.internal.execution.steps; import org.gradle.api.NonNullApi; diff --git a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/impl/steps/CacheStepTest.groovy b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/CacheStepTest.groovy similarity index 97% rename from subprojects/execution/src/test/groovy/org/gradle/internal/execution/impl/steps/CacheStepTest.groovy rename to subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/CacheStepTest.groovy index 2f13834a6c8b1..5b19dfe416128 100644 --- a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/impl/steps/CacheStepTest.groovy +++ b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/CacheStepTest.groovy @@ -10,11 +10,11 @@ * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions andExecutionOutcome.EXECUTED + * See the License for the specific language governing permissions and * limitations under the License. */ -package org.gradle.internal.execution.impl.steps +package org.gradle.internal.execution.steps import com.google.common.collect.ImmutableSortedMap import org.gradle.caching.internal.command.BuildCacheCommandFactory @@ -22,7 +22,9 @@ import org.gradle.caching.internal.controller.BuildCacheController import org.gradle.caching.internal.origin.OriginMetadata import org.gradle.internal.Try import org.gradle.internal.execution.CacheHandler +import org.gradle.internal.execution.CachingContext import org.gradle.internal.execution.Context +import org.gradle.internal.execution.CurrentSnapshotResult import org.gradle.internal.execution.ExecutionOutcome import org.gradle.internal.execution.OutputChangeListener import org.gradle.internal.execution.Step diff --git a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/impl/steps/ExecutionTest.groovy b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/ExecutionTest.groovy similarity index 96% rename from subprojects/execution/src/test/groovy/org/gradle/internal/execution/impl/steps/ExecutionTest.groovy rename to subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/ExecutionTest.groovy index c276a279cac47..e2490bdaf3b17 100644 --- a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/impl/steps/ExecutionTest.groovy +++ b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/ExecutionTest.groovy @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.gradle.internal.execution.impl.steps +package org.gradle.internal.execution.steps import com.google.common.collect.ImmutableSortedMap import org.gradle.api.BuildCancelledException @@ -23,10 +23,14 @@ import org.gradle.initialization.DefaultBuildCancellationToken import org.gradle.internal.execution.CacheHandler import org.gradle.internal.execution.ExecutionException import org.gradle.internal.execution.ExecutionOutcome +import org.gradle.internal.execution.IncrementalChangesContext import org.gradle.internal.execution.OutputChangeListener import org.gradle.internal.execution.UnitOfWork import org.gradle.internal.execution.history.changes.ExecutionStateChanges import org.gradle.internal.execution.history.changes.OutputFileChanges +import org.gradle.internal.execution.steps.CancelExecutionStep +import org.gradle.internal.execution.steps.CatchExceptionStep +import org.gradle.internal.execution.steps.ExecuteStep import org.gradle.internal.fingerprint.CurrentFileCollectionFingerprint import spock.lang.Specification diff --git a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/impl/steps/IncrementalExecutionTest.groovy b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/IncrementalExecutionTest.groovy similarity index 99% rename from subprojects/execution/src/test/groovy/org/gradle/internal/execution/impl/steps/IncrementalExecutionTest.groovy rename to subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/IncrementalExecutionTest.groovy index 1bd35c8bf684f..d99f5fe9733fe 100644 --- a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/impl/steps/IncrementalExecutionTest.groovy +++ b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/IncrementalExecutionTest.groovy @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.gradle.internal.execution.impl.steps +package org.gradle.internal.execution.steps import com.google.common.collect.ImmutableList import com.google.common.collect.ImmutableSortedMap @@ -30,11 +30,14 @@ import org.gradle.internal.execution.CacheHandler import org.gradle.internal.execution.Context import org.gradle.internal.execution.ExecutionException import org.gradle.internal.execution.ExecutionOutcome +import org.gradle.internal.execution.IncrementalChangesContext +import org.gradle.internal.execution.IncrementalContext import org.gradle.internal.execution.OutputChangeListener import org.gradle.internal.execution.Result import org.gradle.internal.execution.TestExecutionHistoryStore import org.gradle.internal.execution.TestOutputFilesRepository import org.gradle.internal.execution.UnitOfWork +import org.gradle.internal.execution.UpToDateResult import org.gradle.internal.execution.WorkExecutor import org.gradle.internal.execution.history.changes.ExecutionStateChanges import org.gradle.internal.execution.history.changes.OutputFileChanges diff --git a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/impl/steps/SkipUpToDateStepTest.groovy b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/SkipUpToDateStepTest.groovy similarity index 93% rename from subprojects/execution/src/test/groovy/org/gradle/internal/execution/impl/steps/SkipUpToDateStepTest.groovy rename to subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/SkipUpToDateStepTest.groovy index af2797ab7d4ca..0f339e072982b 100644 --- a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/impl/steps/SkipUpToDateStepTest.groovy +++ b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/SkipUpToDateStepTest.groovy @@ -14,14 +14,16 @@ * limitations under the License. */ -package org.gradle.internal.execution.impl.steps +package org.gradle.internal.execution.steps import org.gradle.internal.change.ChangeVisitor import org.gradle.internal.change.DescriptiveChange import org.gradle.internal.execution.ExecutionOutcome +import org.gradle.internal.execution.IncrementalChangesContext import org.gradle.internal.execution.Step import org.gradle.internal.execution.UnitOfWork import org.gradle.internal.execution.history.changes.ExecutionStateChanges +import org.gradle.internal.execution.steps.SkipUpToDateStep import org.gradle.testing.internal.util.Specification class SkipUpToDateStepTest extends Specification { From a8a6dbe8c2a210dfbf7fbfdb2102385be6d0a2f5 Mon Sep 17 00:00:00 2001 From: Stefan Wolf Date: Wed, 6 Mar 2019 15:10:20 +0100 Subject: [PATCH 348/853] Test that upToDateWhen { false } disables caching --- .../tasks/CachedTaskExecutionIntegrationTest.groovy | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/CachedTaskExecutionIntegrationTest.groovy b/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/CachedTaskExecutionIntegrationTest.groovy index 2f1c0378bf682..4ec7c795d4744 100644 --- a/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/CachedTaskExecutionIntegrationTest.groovy +++ b/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/CachedTaskExecutionIntegrationTest.groovy @@ -24,6 +24,7 @@ import org.gradle.internal.jvm.Jvm import org.gradle.test.fixtures.file.TestFile import org.gradle.util.TextUtil import spock.lang.IgnoreIf +import spock.lang.Unroll class CachedTaskExecutionIntegrationTest extends AbstractIntegrationSpec implements DirectoryBuildCacheFixture { public static final String ORIGINAL_HELLO_WORLD = """ @@ -86,9 +87,13 @@ class CachedTaskExecutionIntegrationTest extends AbstractIntegrationSpec impleme skippedTasks.containsAll ":compileJava" } - def "cached tasks are executed with --rerun-tasks"() { + @Unroll + def "cached tasks are executed with #rerunMethod"() { expect: cacheDir.listFiles() as List == [] + buildFile << """ + tasks.withType(JavaCompile).configureEach { it.outputs.upToDateWhen { project.findProperty("upToDateWhenFalse") == null } } + """ when: withBuildCache().run "jar" @@ -102,7 +107,7 @@ class CachedTaskExecutionIntegrationTest extends AbstractIntegrationSpec impleme withBuildCache().run "clean" when: - withBuildCache().run "jar", "--rerun-tasks" + withBuildCache().run "jar", rerunMethod def updatedCacheContents = listCacheFiles() def updatedModificationTimes = updatedCacheContents*.lastModified() then: @@ -111,6 +116,9 @@ class CachedTaskExecutionIntegrationTest extends AbstractIntegrationSpec impleme originalModificationTimes.size().times { i -> assert originalModificationTimes[i] < updatedModificationTimes[i] } + + where: + rerunMethod << ["--rerun-tasks", "-PupToDateWhenFalse=true"] } def "task results don't get stored when pushing is disabled"() { From dbd8236f7e9634385d4f9cb567090496164f7e10 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=B3r=C3=A1nt=20Pint=C3=A9r?= Date: Wed, 6 Mar 2019 16:39:44 +0100 Subject: [PATCH 349/853] Store state after execution in execution engine Previously each unit of work had to implement its own persistence. Now the execution engine can handle all of the snapshotting on its own. This also fixes a bug where we recorded final outputs for tasks twice. --- .../execution/ExecuteActionsTaskExecuter.java | 25 ----------- .../scopes/ExecutionGradleServices.java | 7 +-- .../DefaultDependencyManagementServices.java | 6 ++- .../transform/DefaultTransformerInvoker.java | 17 ------- .../execution/IncrementalChangesContext.java | 2 +- .../gradle/internal/execution/UnitOfWork.java | 3 -- .../execution/steps/PrepareCachingStep.java | 17 +++++++ .../execution/steps/ResolveChangesStep.java | 16 +++++++ .../execution/steps/StoreSnapshotsStep.java | 44 ++++++++++++++++--- .../execution/steps/CacheStepTest.groovy | 17 +++++++ .../execution/steps/ExecutionTest.groovy | 25 +++++++---- .../steps/IncrementalExecutionTest.groovy | 17 +------ .../steps/SkipUpToDateStepTest.groovy | 1 - 13 files changed, 114 insertions(+), 83 deletions(-) diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuter.java b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuter.java index c20ad7290d74b..49933d96608b5 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuter.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuter.java @@ -305,31 +305,6 @@ public ImmutableSortedMap apply(Overla }).orElse(outputsAfterExecution); } - @Override - public void persistResult(final ImmutableSortedMap finalOutputs, final boolean successful, final OriginMetadata originMetadata) { - AfterPreviousExecutionState afterPreviousExecutionState = context.getAfterPreviousExecution(); - // Only persist history if there was no failure, or some output files have been changed - if (successful || afterPreviousExecutionState == null || hasAnyOutputFileChanges(afterPreviousExecutionState.getOutputFileProperties(), finalOutputs)) { - context.getBeforeExecutionState().ifPresent(new Consumer() { - @Override - public void accept(BeforeExecutionState execution) { - executionHistoryStore.store( - task.getPath(), - originMetadata, - execution.getImplementation(), - execution.getAdditionalImplementations(), - execution.getInputProperties(), - execution.getInputFileProperties(), - finalOutputs, - successful - ); - - outputFilesRepository.recordOutputs(finalOutputs.values()); - } - }); - } - } - private boolean hasAnyOutputFileChanges(ImmutableSortedMap previous, ImmutableSortedMap current) { return !previous.keySet().equals(current.keySet()) || new OutputFileChanges(previous, current, IGNORE_ADDED).hasAnyChanges(); diff --git a/subprojects/core/src/main/java/org/gradle/internal/service/scopes/ExecutionGradleServices.java b/subprojects/core/src/main/java/org/gradle/internal/service/scopes/ExecutionGradleServices.java index 9bc159cd58ef3..452d65d4fd869 100644 --- a/subprojects/core/src/main/java/org/gradle/internal/service/scopes/ExecutionGradleServices.java +++ b/subprojects/core/src/main/java/org/gradle/internal/service/scopes/ExecutionGradleServices.java @@ -112,10 +112,11 @@ OutputChangeListener createOutputChangeListener(ListenerManager listenerManager) } public WorkExecutor createWorkExecutor( - BuildCacheController buildCacheController, BuildCacheCommandFactory buildCacheCommandFactory, - BuildInvocationScopeId buildInvocationScopeId, + BuildCacheController buildCacheController, BuildCancellationToken cancellationToken, + BuildInvocationScopeId buildInvocationScopeId, + ExecutionHistoryStore executionHistoryStore, OutputChangeListener outputChangeListener, OutputFilesRepository outputFilesRepository, TimeoutHandler timeoutHandler @@ -123,7 +124,7 @@ public WorkExecutor createWorkExecutor( return new DefaultWorkExecutor( new ResolveChangesStep( new SkipUpToDateStep( - new StoreSnapshotsStep(outputFilesRepository, + new StoreSnapshotsStep(outputFilesRepository, executionHistoryStore, new PrepareCachingStep( new CacheStep(buildCacheController, outputChangeListener, buildCacheCommandFactory, new SnapshotOutputStep(buildInvocationScopeId.getId(), diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/DefaultDependencyManagementServices.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/DefaultDependencyManagementServices.java index ccd4bfae51292..393f9540ee3c4 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/DefaultDependencyManagementServices.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/DefaultDependencyManagementServices.java @@ -198,7 +198,9 @@ OutputFileCollectionFingerprinter createOutputFingerprinter(FileSystemSnapshotte * Currently used for running artifact transformations in buildscript blocks. */ WorkExecutor createWorkExecutor( - TimeoutHandler timeoutHandler, ListenerManager listenerManager + ExecutionHistoryStore executionHistoryStore, + ListenerManager listenerManager, + TimeoutHandler timeoutHandler ) { OutputChangeListener outputChangeListener = listenerManager.getBroadcaster(OutputChangeListener.class); OutputFilesRepository noopOutputFilesRepository = new OutputFilesRepository() { @@ -216,7 +218,7 @@ public void recordOutputs(Iterable outputFileFinge return new DefaultWorkExecutor<>( new ResolveChangesStep<>( new SkipUpToDateStep<>( - new StoreSnapshotsStep<>(noopOutputFilesRepository, + new StoreSnapshotsStep<>(noopOutputFilesRepository, executionHistoryStore, new PrepareCachingStep<>( new SnapshotOutputStep<>(fixedUniqueId, new CreateOutputsStep<>( diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvoker.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvoker.java index 458da72a4d634..40fb2963b5ad8 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvoker.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvoker.java @@ -26,7 +26,6 @@ import org.gradle.api.internal.file.FileCollectionFactory; import org.gradle.api.internal.project.ProjectInternal; import org.gradle.caching.BuildCacheKey; -import org.gradle.caching.internal.origin.OriginMetadata; import org.gradle.internal.Try; import org.gradle.internal.UncheckedException; import org.gradle.internal.classloader.ClassLoaderHierarchyHasher; @@ -374,22 +373,6 @@ public void store(Consumer storer) { }; } - @Override - public void persistResult(ImmutableSortedMap finalOutputs, boolean successful, OriginMetadata originMetadata) { - if (successful) { - executionHistoryStore.store( - identityString, - originMetadata, - beforeExecutionState.getImplementation(), - ImmutableList.of(), - beforeExecutionState.getInputProperties(), - beforeExecutionState.getInputFileProperties(), - finalOutputs, - successful - ); - } - } - @Override public Optional> getChangingOutputs() { return Optional.of(ImmutableList.of(workspace.getOutputDirectory().getAbsolutePath(), workspace.getResultsFile().getAbsolutePath())); diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/IncrementalChangesContext.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/IncrementalChangesContext.java index 67537cf9a9efe..08eb6d4408a2d 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/IncrementalChangesContext.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/IncrementalChangesContext.java @@ -20,7 +20,7 @@ import java.util.Optional; -public interface IncrementalChangesContext extends Context { +public interface IncrementalChangesContext extends IncrementalContext { /** * Returns changes detected between the execution state after the last execution and before the current execution. * Empty if changes couldn't be detected (e.g. because history was unavailable). diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/UnitOfWork.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/UnitOfWork.java index 2ad4b047ae2e1..f69ceae8ff929 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/UnitOfWork.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/UnitOfWork.java @@ -19,7 +19,6 @@ import com.google.common.collect.ImmutableSortedMap; import org.gradle.api.file.FileCollection; import org.gradle.caching.internal.CacheableEntity; -import org.gradle.caching.internal.origin.OriginMetadata; import org.gradle.internal.execution.history.changes.OutputFileChanges.OutputHandling; import org.gradle.internal.file.TreeType; import org.gradle.internal.fingerprint.CurrentFileCollectionFingerprint; @@ -47,8 +46,6 @@ public interface UnitOfWork extends CacheableEntity { CacheHandler createCacheHandler(); - void persistResult(ImmutableSortedMap finalOutputs, boolean successful, OriginMetadata originMetadata); - /** * Paths to locations changed by the unit of work. * diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/PrepareCachingStep.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/PrepareCachingStep.java index babdf46d4dbc6..e59a7f3734e3e 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/PrepareCachingStep.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/PrepareCachingStep.java @@ -22,6 +22,8 @@ import org.gradle.internal.execution.Result; import org.gradle.internal.execution.Step; import org.gradle.internal.execution.UnitOfWork; +import org.gradle.internal.execution.history.AfterPreviousExecutionState; +import org.gradle.internal.execution.history.BeforeExecutionState; import org.gradle.internal.execution.history.changes.ExecutionStateChanges; import java.util.Optional; @@ -47,6 +49,21 @@ public Optional getChanges() { return context.getChanges(); } + @Override + public Optional getRebuildReason() { + return context.getRebuildReason(); + } + + @Override + public Optional getAfterPreviousExecutionState() { + return context.getAfterPreviousExecutionState(); + } + + @Override + public Optional getBeforeExecutionState() { + return context.getBeforeExecutionState(); + } + @Override public UnitOfWork getWork() { return context.getWork(); diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/ResolveChangesStep.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/ResolveChangesStep.java index 5a37e51d9a863..ac92678b905d4 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/ResolveChangesStep.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/ResolveChangesStep.java @@ -25,6 +25,7 @@ import org.gradle.internal.execution.Step; import org.gradle.internal.execution.UnitOfWork; import org.gradle.internal.execution.history.AfterPreviousExecutionState; +import org.gradle.internal.execution.history.BeforeExecutionState; import org.gradle.internal.execution.history.changes.DefaultExecutionStateChanges; import org.gradle.internal.execution.history.changes.ExecutionStateChanges; @@ -62,6 +63,21 @@ public Optional getChanges() { return Optional.ofNullable(changes); } + @Override + public Optional getRebuildReason() { + return context.getRebuildReason(); + } + + @Override + public Optional getAfterPreviousExecutionState() { + return context.getAfterPreviousExecutionState(); + } + + @Override + public Optional getBeforeExecutionState() { + return context.getBeforeExecutionState(); + } + @Override public UnitOfWork getWork() { return context.getWork(); diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/StoreSnapshotsStep.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/StoreSnapshotsStep.java index 672ff607c445d..083cba73711d1 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/StoreSnapshotsStep.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/StoreSnapshotsStep.java @@ -17,21 +17,31 @@ package org.gradle.internal.execution.steps; import com.google.common.collect.ImmutableSortedMap; -import org.gradle.internal.execution.Context; import org.gradle.internal.execution.CurrentSnapshotResult; +import org.gradle.internal.execution.IncrementalContext; import org.gradle.internal.execution.Step; +import org.gradle.internal.execution.UnitOfWork; +import org.gradle.internal.execution.history.AfterPreviousExecutionState; +import org.gradle.internal.execution.history.ExecutionHistoryStore; import org.gradle.internal.execution.history.OutputFilesRepository; +import org.gradle.internal.execution.history.changes.OutputFileChanges; import org.gradle.internal.fingerprint.CurrentFileCollectionFingerprint; +import org.gradle.internal.fingerprint.FileCollectionFingerprint; -public class StoreSnapshotsStep implements Step { +import java.util.Optional; + +public class StoreSnapshotsStep implements Step { private final OutputFilesRepository outputFilesRepository; + private final ExecutionHistoryStore executionHistoryStore; private final Step delegate; public StoreSnapshotsStep( OutputFilesRepository outputFilesRepository, + ExecutionHistoryStore executionHistoryStore, Step delegate ) { this.outputFilesRepository = outputFilesRepository; + this.executionHistoryStore = executionHistoryStore; this.delegate = delegate; } @@ -40,13 +50,33 @@ public StoreSnapshotsStep( public CurrentSnapshotResult execute(C context) { CurrentSnapshotResult result = delegate.execute(context); ImmutableSortedMap finalOutputs = result.getFinalOutputs(); - context.getWork().persistResult( - finalOutputs, - result.getOutcome().isSuccessful(), - result.getOriginMetadata() - ); + context.getBeforeExecutionState().ifPresent(beforeExecutionState -> { + boolean successful = result.getOutcome().isSuccessful(); + Optional afterPreviousExecutionState = context.getAfterPreviousExecutionState(); + // Only persist history if there was no failure, or some output files have been changed + UnitOfWork work = context.getWork(); + if (successful + || !afterPreviousExecutionState.isPresent() + || hasAnyOutputFileChanges(afterPreviousExecutionState.get().getOutputFileProperties(), finalOutputs, work.getOutputHandling())) { + executionHistoryStore.store( + work.getIdentity(), + result.getOriginMetadata(), + beforeExecutionState.getImplementation(), + beforeExecutionState.getAdditionalImplementations(), + beforeExecutionState.getInputProperties(), + beforeExecutionState.getInputFileProperties(), + finalOutputs, + successful + ); + } + }); outputFilesRepository.recordOutputs(finalOutputs.values()); return result; } + + private static boolean hasAnyOutputFileChanges(ImmutableSortedMap previous, ImmutableSortedMap current, OutputFileChanges.OutputHandling outputHandling) { + return !previous.keySet().equals(current.keySet()) + || new OutputFileChanges(previous, current, outputHandling).hasAnyChanges(); + } } diff --git a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/CacheStepTest.groovy b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/CacheStepTest.groovy index 5b19dfe416128..e68fa54a27092 100644 --- a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/CacheStepTest.groovy +++ b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/CacheStepTest.groovy @@ -29,6 +29,8 @@ import org.gradle.internal.execution.ExecutionOutcome import org.gradle.internal.execution.OutputChangeListener import org.gradle.internal.execution.Step import org.gradle.internal.execution.UnitOfWork +import org.gradle.internal.execution.history.AfterPreviousExecutionState +import org.gradle.internal.execution.history.BeforeExecutionState import org.gradle.internal.execution.history.changes.ExecutionStateChanges import org.gradle.internal.fingerprint.CurrentFileCollectionFingerprint import org.gradle.internal.fingerprint.impl.EmptyCurrentFileCollectionFingerprint @@ -58,6 +60,21 @@ class CacheStepTest extends Specification { return Optional.empty() } + @Override + Optional getRebuildReason() { + return context.getRebuildReason(); + } + + @Override + Optional getAfterPreviousExecutionState() { + return context.getAfterPreviousExecutionState(); + } + + @Override + Optional getBeforeExecutionState() { + return context.getBeforeExecutionState(); + } + @Override UnitOfWork getWork() { unitOfWork diff --git a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/ExecutionTest.groovy b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/ExecutionTest.groovy index e2490bdaf3b17..2ac457a6c52d3 100644 --- a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/ExecutionTest.groovy +++ b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/ExecutionTest.groovy @@ -18,7 +18,6 @@ package org.gradle.internal.execution.steps import com.google.common.collect.ImmutableSortedMap import org.gradle.api.BuildCancelledException -import org.gradle.caching.internal.origin.OriginMetadata import org.gradle.initialization.DefaultBuildCancellationToken import org.gradle.internal.execution.CacheHandler import org.gradle.internal.execution.ExecutionException @@ -26,11 +25,10 @@ import org.gradle.internal.execution.ExecutionOutcome import org.gradle.internal.execution.IncrementalChangesContext import org.gradle.internal.execution.OutputChangeListener import org.gradle.internal.execution.UnitOfWork +import org.gradle.internal.execution.history.AfterPreviousExecutionState +import org.gradle.internal.execution.history.BeforeExecutionState import org.gradle.internal.execution.history.changes.ExecutionStateChanges import org.gradle.internal.execution.history.changes.OutputFileChanges -import org.gradle.internal.execution.steps.CancelExecutionStep -import org.gradle.internal.execution.steps.CatchExceptionStep -import org.gradle.internal.execution.steps.ExecuteStep import org.gradle.internal.fingerprint.CurrentFileCollectionFingerprint import spock.lang.Specification @@ -180,10 +178,6 @@ class ExecutionTest extends Specification { throw new UnsupportedOperationException() } - @Override - void persistResult(ImmutableSortedMap finalOutputs, boolean successful, OriginMetadata originMetadata) { - throw new UnsupportedOperationException() - } @Override Optional> getChangingOutputs() { @@ -218,6 +212,21 @@ class ExecutionTest extends Specification { return Optional.empty() } + @Override + Optional getRebuildReason() { + return Optional.empty() + } + + @Override + Optional getAfterPreviousExecutionState() { + return Optional.empty() + } + + @Override + Optional getBeforeExecutionState() { + return Optional.empty() + } + @Override UnitOfWork getWork() { return work.get() diff --git a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/IncrementalExecutionTest.groovy b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/IncrementalExecutionTest.groovy index d99f5fe9733fe..bb0f2f0f8a6d0 100644 --- a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/IncrementalExecutionTest.groovy +++ b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/IncrementalExecutionTest.groovy @@ -24,7 +24,6 @@ import org.gradle.api.internal.cache.StringInterner import org.gradle.api.internal.file.TestFiles import org.gradle.api.internal.file.collections.ImmutableFileCollection import org.gradle.caching.internal.CacheableEntity -import org.gradle.caching.internal.origin.OriginMetadata import org.gradle.internal.classloader.ClassLoaderHierarchyHasher import org.gradle.internal.execution.CacheHandler import org.gradle.internal.execution.Context @@ -121,12 +120,11 @@ class IncrementalExecutionTest extends Specification { def unitOfWork = builder.build() - WorkExecutor getExecutor() { new DefaultWorkExecutor( new ResolveChangesStep( new SkipUpToDateStep( - new StoreSnapshotsStep(outputFilesRepository, + new StoreSnapshotsStep(outputFilesRepository, executionHistoryStore, new SnapshotOutputStep(buildInvocationScopeId.getId(), new CreateOutputsStep( new CatchExceptionStep( @@ -791,19 +789,6 @@ class IncrementalExecutionTest extends Specification { throw new UnsupportedOperationException() } - @Override - void persistResult(ImmutableSortedMap finalOutputs, boolean successful, OriginMetadata originMetadata) { - executionHistoryStore.store( - getIdentity(), - originMetadata, - implementationSnapshot, - additionalImplementationSnapshots, - snapshotInputProperties(), - snapshotInputFiles(), - finalOutputs, - successful - ) - } @Override Optional> getChangingOutputs() { diff --git a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/SkipUpToDateStepTest.groovy b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/SkipUpToDateStepTest.groovy index 0f339e072982b..9b3a6baa9f85a 100644 --- a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/SkipUpToDateStepTest.groovy +++ b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/SkipUpToDateStepTest.groovy @@ -23,7 +23,6 @@ import org.gradle.internal.execution.IncrementalChangesContext import org.gradle.internal.execution.Step import org.gradle.internal.execution.UnitOfWork import org.gradle.internal.execution.history.changes.ExecutionStateChanges -import org.gradle.internal.execution.steps.SkipUpToDateStep import org.gradle.testing.internal.util.Specification class SkipUpToDateStepTest extends Specification { From b093ac30d9d826b7ba30ad9ebe6746a3bc9fc3f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=B3r=C3=A1nt=20Pint=C3=A9r?= Date: Wed, 6 Mar 2019 17:41:59 +0100 Subject: [PATCH 350/853] Fix test fixture --- .../artifacts/transform/WorkExecutorTestFixture.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/WorkExecutorTestFixture.java b/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/WorkExecutorTestFixture.java index 521a3911e43fd..2bc28f30d8e23 100644 --- a/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/WorkExecutorTestFixture.java +++ b/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/WorkExecutorTestFixture.java @@ -26,6 +26,7 @@ import org.gradle.internal.execution.OutputChangeListener; import org.gradle.internal.execution.UpToDateResult; import org.gradle.internal.execution.WorkExecutor; +import org.gradle.internal.execution.history.ExecutionHistoryStore; import org.gradle.internal.execution.history.OutputFilesRepository; import org.gradle.internal.execution.timeout.impl.DefaultTimeoutHandler; import org.gradle.internal.id.UniqueId; @@ -70,7 +71,8 @@ public void close() { private BuildCancellationToken cancellationToken = new DefaultBuildCancellationToken(); private final WorkExecutor workExecutor; - WorkExecutorTestFixture(DefaultFileSystemMirror fileSystemMirror) { + WorkExecutorTestFixture(DefaultFileSystemMirror fileSystemMirror, + ExecutionHistoryStore executionHistoryStore) { BuildCacheCommandFactory buildCacheCommandFactory = null; OutputChangeListener outputChangeListener = new OutputChangeListener() { @Override @@ -94,10 +96,11 @@ public void recordOutputs(Iterable outputFileFinge } }; workExecutor = new ExecutionGradleServices().createWorkExecutor( - buildCacheController, buildCacheCommandFactory, - buildInvocationScopeId, + buildCacheController, cancellationToken, + buildInvocationScopeId, + executionHistoryStore, outputChangeListener, outputFilesRepository, new DefaultTimeoutHandler(null) From 4ca185eb06b4e79bef531a9e0a28fee552c770d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=B3r=C3=A1nt=20Pint=C3=A9r?= Date: Wed, 6 Mar 2019 19:50:11 +0100 Subject: [PATCH 351/853] Fix users of test fixture --- .../transform/ArtifactTransformCachingIntegrationTest.groovy | 3 +-- .../artifacts/transform/DefaultTransformerInvokerTest.groovy | 4 ++-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformCachingIntegrationTest.groovy b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformCachingIntegrationTest.groovy index 4b8c3cd57d135..62cfb466241b8 100644 --- a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformCachingIntegrationTest.groovy +++ b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformCachingIntegrationTest.groovy @@ -234,8 +234,7 @@ class ArtifactTransformCachingIntegrationTest extends AbstractHttpDependencyReso println "Transformed \$input.name to \$outSize.name into \$outputDirectory" outSize.text = String.valueOf(input.length()) return [outSize] - } - if (target.equals("hash")) { + } else if (target.equals("hash")) { def outHash = new File(outputDirectory, input.name + ".hash") println "Transformed \$input.name to \$outHash.name into \$outputDirectory" outHash.text = 'hash' diff --git a/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvokerTest.groovy b/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvokerTest.groovy index 17c16b084cf0b..e99a9fd57f066 100644 --- a/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvokerTest.groovy +++ b/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvokerTest.groovy @@ -53,11 +53,11 @@ class DefaultTransformerInvokerTest extends AbstractProjectBuilderSpec { def immutableTransformsStoreDirectory = temporaryFolder.file("output") def mutableTransformsStoreDirectory = temporaryFolder.file("child/build/transforms") + def executionHistoryStore = new TestExecutionHistoryStore() def fileSystemMirror = new DefaultFileSystemMirror(new DefaultWellKnownFileLocations([])) - def workExecutorTestFixture = new WorkExecutorTestFixture(fileSystemMirror) + def workExecutorTestFixture = new WorkExecutorTestFixture(fileSystemMirror, executionHistoryStore) def fileSystemSnapshotter = new DefaultFileSystemSnapshotter(TestFiles.fileHasher(), new StringInterner(), TestFiles.fileSystem(), fileSystemMirror) - def executionHistoryStore = new TestExecutionHistoryStore() def transformationWorkspaceProvider = new TestTransformationWorkspaceProvider(immutableTransformsStoreDirectory, executionHistoryStore) def fileCollectionFactory = TestFiles.fileCollectionFactory() From df436a913a43888c53fed7fd4ad2880a3c7708bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=B3r=C3=A1nt=20Pint=C3=A9r?= Date: Wed, 6 Mar 2019 21:25:51 +0100 Subject: [PATCH 352/853] Remove unused class --- .../changes/NoHistoryTaskUpToDateState.java | 49 ------------------- 1 file changed, 49 deletions(-) delete mode 100644 subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/NoHistoryTaskUpToDateState.java diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/NoHistoryTaskUpToDateState.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/NoHistoryTaskUpToDateState.java deleted file mode 100644 index 565869bb82e60..0000000000000 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/NoHistoryTaskUpToDateState.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright 2018 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.gradle.internal.execution.history.changes; - -import org.gradle.internal.change.Change; -import org.gradle.internal.change.ChangeVisitor; -import org.gradle.internal.change.DescriptiveChange; -import org.gradle.internal.execution.history.AfterPreviousExecutionState; - -public class NoHistoryTaskUpToDateState implements ExecutionStateChanges { - - public static final NoHistoryTaskUpToDateState INSTANCE = new NoHistoryTaskUpToDateState(); - - private final DescriptiveChange noHistoryChange = new DescriptiveChange("No history is available."); - - @Override - public Iterable getInputFilesChanges() { - throw new UnsupportedOperationException("Input file changes can only be queried when history is available."); - } - - @Override - public void visitAllChanges(ChangeVisitor visitor) { - visitor.visitChange(noHistoryChange); - } - - @Override - public boolean isRebuildRequired() { - return true; - } - - @Override - public AfterPreviousExecutionState getPreviousExecution() { - throw new UnsupportedOperationException(); - } -} From ff34b8d7312407b7aa6f9617b3080dc0fe7fee16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=B3r=C3=A1nt=20Pint=C3=A9r?= Date: Wed, 6 Mar 2019 21:28:00 +0100 Subject: [PATCH 353/853] Remove unused parameter --- .../tasks/execution/ExecuteActionsTaskExecuter.java | 4 ---- .../java/org/gradle/execution/ProjectExecutionServices.java | 1 - .../tasks/execution/ExecuteActionsTaskExecuterTest.groovy | 6 +----- 3 files changed, 1 insertion(+), 10 deletions(-) diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuter.java b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuter.java index 49933d96608b5..a333661e05af0 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuter.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuter.java @@ -51,7 +51,6 @@ import org.gradle.internal.execution.history.AfterPreviousExecutionState; import org.gradle.internal.execution.history.BeforeExecutionState; import org.gradle.internal.execution.history.ExecutionHistoryStore; -import org.gradle.internal.execution.history.OutputFilesRepository; import org.gradle.internal.execution.history.changes.ExecutionStateChanges; import org.gradle.internal.execution.history.changes.OutputFileChanges; import org.gradle.internal.execution.history.changes.OutputFileChanges.OutputHandling; @@ -84,7 +83,6 @@ public class ExecuteActionsTaskExecuter implements TaskExecuter { private final boolean buildCacheEnabled; private final TaskFingerprinter taskFingerprinter; private final ExecutionHistoryStore executionHistoryStore; - private final OutputFilesRepository outputFilesRepository; private final BuildOperationExecutor buildOperationExecutor; private final AsyncWorkTracker asyncWorkTracker; private final TaskActionListener actionListener; @@ -94,7 +92,6 @@ public ExecuteActionsTaskExecuter( boolean buildCacheEnabled, TaskFingerprinter taskFingerprinter, ExecutionHistoryStore executionHistoryStore, - OutputFilesRepository outputFilesRepository, BuildOperationExecutor buildOperationExecutor, AsyncWorkTracker asyncWorkTracker, TaskActionListener actionListener, @@ -103,7 +100,6 @@ public ExecuteActionsTaskExecuter( this.buildCacheEnabled = buildCacheEnabled; this.taskFingerprinter = taskFingerprinter; this.executionHistoryStore = executionHistoryStore; - this.outputFilesRepository = outputFilesRepository; this.buildOperationExecutor = buildOperationExecutor; this.asyncWorkTracker = asyncWorkTracker; this.actionListener = actionListener; diff --git a/subprojects/core/src/main/java/org/gradle/execution/ProjectExecutionServices.java b/subprojects/core/src/main/java/org/gradle/execution/ProjectExecutionServices.java index 722bfc249ee20..857a68e065598 100644 --- a/subprojects/core/src/main/java/org/gradle/execution/ProjectExecutionServices.java +++ b/subprojects/core/src/main/java/org/gradle/execution/ProjectExecutionServices.java @@ -115,7 +115,6 @@ TaskExecuter createTaskExecuter(TaskExecutionModeResolver repository, buildCacheEnabled, taskFingerprinter, executionHistoryStore, - outputFilesRepository, buildOperationExecutor, asyncWorkTracker, actionListener, diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuterTest.groovy b/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuterTest.groovy index 162bae30987ec..619d0d443278f 100644 --- a/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuterTest.groovy +++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuterTest.groovy @@ -38,7 +38,6 @@ import org.gradle.internal.execution.IncrementalContext import org.gradle.internal.execution.OutputChangeListener import org.gradle.internal.execution.UpToDateResult import org.gradle.internal.execution.history.ExecutionHistoryStore -import org.gradle.internal.execution.history.OutputFilesRepository import org.gradle.internal.execution.impl.DefaultWorkExecutor import org.gradle.internal.execution.steps.CancelExecutionStep import org.gradle.internal.execution.steps.CatchExceptionStep @@ -71,9 +70,6 @@ class ExecuteActionsTaskExecuterTest extends Specification { fingerprintTaskFiles(task, _) >> ImmutableSortedMap.of() } def executionHistoryStore = Mock(ExecutionHistoryStore) - def outputFilesRepository = Stub(OutputFilesRepository) { - isGeneratedByGradle(_) >> true - } def buildId = UniqueId.generate() def actionListener = Mock(TaskActionListener) @@ -93,7 +89,7 @@ class ExecuteActionsTaskExecuterTest extends Specification { ) ) ) - def executer = new ExecuteActionsTaskExecuter(false, taskFingerprinter, executionHistoryStore, outputFilesRepository, buildOperationExecutor, asyncWorkTracker, actionListener, workExecutor) + def executer = new ExecuteActionsTaskExecuter(false, taskFingerprinter, executionHistoryStore, buildOperationExecutor, asyncWorkTracker, actionListener, workExecutor) def setup() { ProjectInternal project = Mock(ProjectInternal) From d9b4a5063a2477aee756d5c40e91a724b89d24f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=B3r=C3=A1nt=20Pint=C3=A9r?= Date: Wed, 6 Mar 2019 21:28:43 +0100 Subject: [PATCH 354/853] Use the correct execution history store for each unit of work --- .../tasks/execution/ExecuteActionsTaskExecuter.java | 11 +++++++++-- .../service/scopes/ExecutionGradleServices.java | 3 +-- .../DefaultDependencyManagementServices.java | 3 +-- .../transform/DefaultTransformerInvoker.java | 5 +++++ .../artifacts/transform/WorkExecutorTestFixture.java | 1 - .../org/gradle/internal/execution/UnitOfWork.java | 3 +++ .../internal/execution/steps/StoreSnapshotsStep.java | 6 +----- .../internal/execution/steps/ExecutionTest.groovy | 6 ++++++ .../execution/steps/IncrementalExecutionTest.groovy | 8 +++++++- 9 files changed, 33 insertions(+), 13 deletions(-) diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuter.java b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuter.java index a333661e05af0..46e8a8b270a3d 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuter.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuter.java @@ -108,7 +108,7 @@ public ExecuteActionsTaskExecuter( @Override public TaskExecuterResult execute(final TaskInternal task, final TaskStateInternal state, final TaskExecutionContext context) { - final TaskExecution work = new TaskExecution(task, context); + final TaskExecution work = new TaskExecution(task, context, executionHistoryStore); final UpToDateResult result = workExecutor.execute(new IncrementalContext() { @Override public UnitOfWork getWork() { @@ -169,10 +169,12 @@ public List getExecutionReasons() { private class TaskExecution implements UnitOfWork { private final TaskInternal task; private final TaskExecutionContext context; + private final ExecutionHistoryStore executionHistoryStore; - public TaskExecution(TaskInternal task, TaskExecutionContext context) { + public TaskExecution(TaskInternal task, TaskExecutionContext context, ExecutionHistoryStore executionHistoryStore) { this.task = task; this.context = context; + this.executionHistoryStore = executionHistoryStore; } @Override @@ -204,6 +206,11 @@ public void accept(ExecutionStateChanges changes) { } } + @Override + public ExecutionHistoryStore getExecutionHistoryStore() { + return executionHistoryStore; + } + @Override public void visitOutputProperties(OutputPropertyVisitor visitor) { for (OutputFilePropertySpec property : context.getTaskProperties().getOutputFileProperties()) { diff --git a/subprojects/core/src/main/java/org/gradle/internal/service/scopes/ExecutionGradleServices.java b/subprojects/core/src/main/java/org/gradle/internal/service/scopes/ExecutionGradleServices.java index 452d65d4fd869..4815249352255 100644 --- a/subprojects/core/src/main/java/org/gradle/internal/service/scopes/ExecutionGradleServices.java +++ b/subprojects/core/src/main/java/org/gradle/internal/service/scopes/ExecutionGradleServices.java @@ -116,7 +116,6 @@ public WorkExecutor createWorkExecutor( BuildCacheController buildCacheController, BuildCancellationToken cancellationToken, BuildInvocationScopeId buildInvocationScopeId, - ExecutionHistoryStore executionHistoryStore, OutputChangeListener outputChangeListener, OutputFilesRepository outputFilesRepository, TimeoutHandler timeoutHandler @@ -124,7 +123,7 @@ public WorkExecutor createWorkExecutor( return new DefaultWorkExecutor( new ResolveChangesStep( new SkipUpToDateStep( - new StoreSnapshotsStep(outputFilesRepository, executionHistoryStore, + new StoreSnapshotsStep(outputFilesRepository, new PrepareCachingStep( new CacheStep(buildCacheController, outputChangeListener, buildCacheCommandFactory, new SnapshotOutputStep(buildInvocationScopeId.getId(), diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/DefaultDependencyManagementServices.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/DefaultDependencyManagementServices.java index 393f9540ee3c4..b2e85da694af7 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/DefaultDependencyManagementServices.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/DefaultDependencyManagementServices.java @@ -198,7 +198,6 @@ OutputFileCollectionFingerprinter createOutputFingerprinter(FileSystemSnapshotte * Currently used for running artifact transformations in buildscript blocks. */ WorkExecutor createWorkExecutor( - ExecutionHistoryStore executionHistoryStore, ListenerManager listenerManager, TimeoutHandler timeoutHandler ) { @@ -218,7 +217,7 @@ public void recordOutputs(Iterable outputFileFinge return new DefaultWorkExecutor<>( new ResolveChangesStep<>( new SkipUpToDateStep<>( - new StoreSnapshotsStep<>(noopOutputFilesRepository, executionHistoryStore, + new StoreSnapshotsStep<>(noopOutputFilesRepository, new PrepareCachingStep<>( new SnapshotOutputStep<>(fixedUniqueId, new CreateOutputsStep<>( diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvoker.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvoker.java index 40fb2963b5ad8..0e6694cf8f0e3 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvoker.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvoker.java @@ -314,6 +314,11 @@ private ImmutableList loadResultsFile() { } } + @Override + public ExecutionHistoryStore getExecutionHistoryStore() { + return executionHistoryStore; + } + @Override public Optional getTimeout() { return Optional.empty(); diff --git a/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/WorkExecutorTestFixture.java b/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/WorkExecutorTestFixture.java index 2bc28f30d8e23..6831fde71607b 100644 --- a/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/WorkExecutorTestFixture.java +++ b/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/WorkExecutorTestFixture.java @@ -100,7 +100,6 @@ public void recordOutputs(Iterable outputFileFinge buildCacheController, cancellationToken, buildInvocationScopeId, - executionHistoryStore, outputChangeListener, outputFilesRepository, new DefaultTimeoutHandler(null) diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/UnitOfWork.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/UnitOfWork.java index f69ceae8ff929..4d92a8cafd4bd 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/UnitOfWork.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/UnitOfWork.java @@ -19,6 +19,7 @@ import com.google.common.collect.ImmutableSortedMap; import org.gradle.api.file.FileCollection; import org.gradle.caching.internal.CacheableEntity; +import org.gradle.internal.execution.history.ExecutionHistoryStore; import org.gradle.internal.execution.history.changes.OutputFileChanges.OutputHandling; import org.gradle.internal.file.TreeType; import org.gradle.internal.fingerprint.CurrentFileCollectionFingerprint; @@ -65,5 +66,7 @@ interface OutputPropertyVisitor { void visitOutputProperty(String name, TreeType type, FileCollection roots); } + ExecutionHistoryStore getExecutionHistoryStore(); + ImmutableSortedMap snapshotAfterOutputsGenerated(); } diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/StoreSnapshotsStep.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/StoreSnapshotsStep.java index 083cba73711d1..927bcd69502b9 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/StoreSnapshotsStep.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/StoreSnapshotsStep.java @@ -22,7 +22,6 @@ import org.gradle.internal.execution.Step; import org.gradle.internal.execution.UnitOfWork; import org.gradle.internal.execution.history.AfterPreviousExecutionState; -import org.gradle.internal.execution.history.ExecutionHistoryStore; import org.gradle.internal.execution.history.OutputFilesRepository; import org.gradle.internal.execution.history.changes.OutputFileChanges; import org.gradle.internal.fingerprint.CurrentFileCollectionFingerprint; @@ -32,16 +31,13 @@ public class StoreSnapshotsStep implements Step { private final OutputFilesRepository outputFilesRepository; - private final ExecutionHistoryStore executionHistoryStore; private final Step delegate; public StoreSnapshotsStep( OutputFilesRepository outputFilesRepository, - ExecutionHistoryStore executionHistoryStore, Step delegate ) { this.outputFilesRepository = outputFilesRepository; - this.executionHistoryStore = executionHistoryStore; this.delegate = delegate; } @@ -58,7 +54,7 @@ public CurrentSnapshotResult execute(C context) { if (successful || !afterPreviousExecutionState.isPresent() || hasAnyOutputFileChanges(afterPreviousExecutionState.get().getOutputFileProperties(), finalOutputs, work.getOutputHandling())) { - executionHistoryStore.store( + work.getExecutionHistoryStore().store( work.getIdentity(), result.getOriginMetadata(), beforeExecutionState.getImplementation(), diff --git a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/ExecutionTest.groovy b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/ExecutionTest.groovy index 2ac457a6c52d3..0fca3ae317112 100644 --- a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/ExecutionTest.groovy +++ b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/ExecutionTest.groovy @@ -27,6 +27,7 @@ import org.gradle.internal.execution.OutputChangeListener import org.gradle.internal.execution.UnitOfWork import org.gradle.internal.execution.history.AfterPreviousExecutionState import org.gradle.internal.execution.history.BeforeExecutionState +import org.gradle.internal.execution.history.ExecutionHistoryStore import org.gradle.internal.execution.history.changes.ExecutionStateChanges import org.gradle.internal.execution.history.changes.OutputFileChanges import org.gradle.internal.fingerprint.CurrentFileCollectionFingerprint @@ -143,6 +144,11 @@ class ExecutionTest extends Specification { return work.get() } + @Override + ExecutionHistoryStore getExecutionHistoryStore() { + throw new UnsupportedOperationException() + } + @Override Optional getTimeout() { throw new UnsupportedOperationException() diff --git a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/IncrementalExecutionTest.groovy b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/IncrementalExecutionTest.groovy index bb0f2f0f8a6d0..beb16b379607f 100644 --- a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/IncrementalExecutionTest.groovy +++ b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/IncrementalExecutionTest.groovy @@ -38,6 +38,7 @@ import org.gradle.internal.execution.TestOutputFilesRepository import org.gradle.internal.execution.UnitOfWork import org.gradle.internal.execution.UpToDateResult import org.gradle.internal.execution.WorkExecutor +import org.gradle.internal.execution.history.ExecutionHistoryStore import org.gradle.internal.execution.history.changes.ExecutionStateChanges import org.gradle.internal.execution.history.changes.OutputFileChanges import org.gradle.internal.execution.impl.DefaultWorkExecutor @@ -124,7 +125,7 @@ class IncrementalExecutionTest extends Specification { new DefaultWorkExecutor( new ResolveChangesStep( new SkipUpToDateStep( - new StoreSnapshotsStep(outputFilesRepository, executionHistoryStore, + new StoreSnapshotsStep(outputFilesRepository, new SnapshotOutputStep(buildInvocationScopeId.getId(), new CreateOutputsStep( new CatchExceptionStep( @@ -752,6 +753,11 @@ class IncrementalExecutionTest extends Specification { return work.get() } + @Override + ExecutionHistoryStore getExecutionHistoryStore() { + return IncrementalExecutionTest.this.executionHistoryStore + } + @Override Optional getTimeout() { throw new UnsupportedOperationException() From e98a683127956ed0533b6ade5936112235394fa6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=B3r=C3=A1nt=20Pint=C3=A9r?= Date: Wed, 6 Mar 2019 22:22:20 +0100 Subject: [PATCH 355/853] Address review feedback --- .../internal/tasks/TaskExecuterResult.java | 10 ++--- .../internal/tasks/TaskExecutionOutcome.java | 2 +- .../execution/EventFiringTaskExecuter.java | 18 +-------- .../execution/ExecuteActionsTaskExecuter.java | 32 +++++++-------- .../transform/DefaultTransformerInvoker.java | 9 ++--- .../internal/execution/ExecutionOutcome.java | 2 +- .../gradle/internal/execution/UnitOfWork.java | 6 ++- .../changes/DefaultExecutionStateChanges.java | 4 +- .../history/changes/OutputFileChanges.java | 27 ++----------- .../execution/steps/ResolveChangesStep.java | 7 ++-- .../execution/steps/StoreSnapshotsStep.java | 14 +++++-- .../execution/steps/CacheStepTest.groovy | 4 +- .../execution/steps/ExecutionTest.groovy | 16 +++----- .../steps/IncrementalExecutionTest.groovy | 39 +++++++++---------- 14 files changed, 76 insertions(+), 114 deletions(-) diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/TaskExecuterResult.java b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/TaskExecuterResult.java index 02778f7ddb4fb..73c493e97211f 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/TaskExecuterResult.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/TaskExecuterResult.java @@ -18,8 +18,6 @@ import com.google.common.collect.ImmutableList; import org.gradle.caching.internal.origin.OriginMetadata; -import org.gradle.internal.Try; -import org.gradle.internal.execution.ExecutionOutcome; import java.util.List; import java.util.Optional; @@ -31,9 +29,9 @@ public interface TaskExecuterResult { List getExecutionReasons(); /** - * The outcome of executing the task. + * Whether the task was executed incrementally. */ - Try getOutcome(); + boolean executedIncrementally(); /** * If the execution resulted in some previous output being reused, this returns its origin metadata. @@ -47,8 +45,8 @@ public List getExecutionReasons() { } @Override - public Try getOutcome() { - return Try.successful(ExecutionOutcome.EXECUTED_FULLY); + public boolean executedIncrementally() { + return false; } @Override diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/TaskExecutionOutcome.java b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/TaskExecutionOutcome.java index 2e6ecbfd4eddc..8113efad388e7 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/TaskExecutionOutcome.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/TaskExecutionOutcome.java @@ -57,7 +57,7 @@ public static TaskExecutionOutcome valueOf(ExecutionOutcome outcome) { case UP_TO_DATE: return UP_TO_DATE; case EXECUTED_INCREMENTALLY: - case EXECUTED_FULLY: + case EXECUTED: return EXECUTED; default: throw new AssertionError(); diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/EventFiringTaskExecuter.java b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/EventFiringTaskExecuter.java index 9e4bede1a0f6f..fa0304cb24ee7 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/EventFiringTaskExecuter.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/EventFiringTaskExecuter.java @@ -23,15 +23,12 @@ import org.gradle.api.internal.tasks.TaskExecutionContext; import org.gradle.api.internal.tasks.TaskStateInternal; import org.gradle.api.tasks.TaskExecutionException; -import org.gradle.internal.execution.ExecutionOutcome; import org.gradle.internal.operations.BuildOperationCategory; import org.gradle.internal.operations.BuildOperationContext; import org.gradle.internal.operations.BuildOperationDescriptor; import org.gradle.internal.operations.BuildOperationExecutor; import org.gradle.internal.operations.CallableBuildOperation; -import java.util.function.Function; - public class EventFiringTaskExecuter implements TaskExecuter { private final BuildOperationExecutor buildOperationExecutor; @@ -65,23 +62,10 @@ private TaskExecuterResult executeTask(BuildOperationContext operationContext) { TaskExecuterResult result = delegate.execute(task, state, context); - boolean incremental = result.getOutcome() - .map(new Function() { - @Override - public Boolean apply(ExecutionOutcome executionOutcome) { - return executionOutcome == ExecutionOutcome.EXECUTED_INCREMENTALLY; - } - }).orElseMapFailure(new Function() { - @Override - public Boolean apply(Throwable throwable) { - return false; - } - }); - operationContext.setResult(new ExecuteTaskBuildOperationResult( state, result.getReusedOutputOriginMetadata().orElse(null), - incremental, + result.executedIncrementally(), result.getExecutionReasons() )); diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuter.java b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuter.java index 46e8a8b270a3d..476e4aee16101 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuter.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuter.java @@ -35,7 +35,6 @@ import org.gradle.api.tasks.TaskExecutionException; import org.gradle.caching.BuildCacheKey; import org.gradle.caching.internal.origin.OriginMetadata; -import org.gradle.internal.Try; import org.gradle.internal.UncheckedException; import org.gradle.internal.exceptions.Contextual; import org.gradle.internal.exceptions.DefaultMultiCauseException; @@ -52,11 +51,8 @@ import org.gradle.internal.execution.history.BeforeExecutionState; import org.gradle.internal.execution.history.ExecutionHistoryStore; import org.gradle.internal.execution.history.changes.ExecutionStateChanges; -import org.gradle.internal.execution.history.changes.OutputFileChanges; -import org.gradle.internal.execution.history.changes.OutputFileChanges.OutputHandling; import org.gradle.internal.execution.impl.OutputFilterUtil; import org.gradle.internal.fingerprint.CurrentFileCollectionFingerprint; -import org.gradle.internal.fingerprint.FileCollectionFingerprint; import org.gradle.internal.operations.BuildOperationContext; import org.gradle.internal.operations.BuildOperationDescriptor; import org.gradle.internal.operations.BuildOperationExecutor; @@ -72,8 +68,6 @@ import java.util.function.Consumer; import java.util.function.Function; -import static org.gradle.internal.execution.history.changes.OutputFileChanges.OutputHandling.IGNORE_ADDED; - /** * A {@link TaskExecuter} which executes the actions of a task. */ @@ -155,8 +149,19 @@ public Optional getReusedOutputOriginMetadata() { } @Override - public Try getOutcome() { - return result.getOutcome(); + public boolean executedIncrementally() { + return result.getOutcome() + .map(new Function() { + @Override + public Boolean apply(ExecutionOutcome executionOutcome) { + return executionOutcome == ExecutionOutcome.EXECUTED_INCREMENTALLY; + } + }).orElseMapFailure(new Function() { + @Override + public Boolean apply(Throwable throwable) { + return false; + } + }); } @Override @@ -198,7 +203,7 @@ public void accept(ExecutionStateChanges changes) { return task.getState().getDidWork() ? this.context.isTaskExecutedIncrementally() ? ExecutionOutcome.EXECUTED_INCREMENTALLY - : ExecutionOutcome.EXECUTED_FULLY + : ExecutionOutcome.EXECUTED : ExecutionOutcome.UP_TO_DATE; } finally { task.getState().setExecuting(false); @@ -241,8 +246,8 @@ public void visitLocalState(LocalStateVisitor visitor) { } @Override - public OutputHandling getOutputHandling() { - return IGNORE_ADDED; + public boolean includeAddedOutputs() { + return false; } @Override @@ -308,11 +313,6 @@ public ImmutableSortedMap apply(Overla }).orElse(outputsAfterExecution); } - private boolean hasAnyOutputFileChanges(ImmutableSortedMap previous, ImmutableSortedMap current) { - return !previous.keySet().equals(current.keySet()) - || new OutputFileChanges(previous, current, IGNORE_ADDED).hasAnyChanges(); - } - @Override public long markExecutionTime() { return context.markExecutionTime(); diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvoker.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvoker.java index 0e6694cf8f0e3..84ba6c3be164d 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvoker.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvoker.java @@ -39,7 +39,6 @@ import org.gradle.internal.execution.history.AfterPreviousExecutionState; import org.gradle.internal.execution.history.BeforeExecutionState; import org.gradle.internal.execution.history.ExecutionHistoryStore; -import org.gradle.internal.execution.history.changes.OutputFileChanges.OutputHandling; import org.gradle.internal.execution.history.impl.DefaultBeforeExecutionState; import org.gradle.internal.file.TreeType; import org.gradle.internal.fingerprint.CurrentFileCollectionFingerprint; @@ -72,8 +71,6 @@ import java.util.function.Supplier; import java.util.stream.Stream; -import static org.gradle.internal.execution.history.changes.OutputFileChanges.OutputHandling.DETECT_ADDED; - public class DefaultTransformerInvoker implements TransformerInvoker { private static final String INPUT_ARTIFACT_PROPERTY_NAME = "inputArtifact"; private static final String DEPENDENCIES_PROPERTY_NAME = "inputArtifactDependencies"; @@ -269,7 +266,7 @@ public ExecutionOutcome execute(IncrementalChangesContext context) { GFileUtils.deleteFileQuietly(resultsFile); ImmutableList result = transformer.transform(inputArtifact, outputDir, dependencies); writeResultsFile(outputDir, resultsFile, result); - return ExecutionOutcome.EXECUTED_FULLY; + return ExecutionOutcome.EXECUTED; } private void writeResultsFile(File outputDir, File resultsFile, ImmutableList result) { @@ -331,8 +328,8 @@ public void visitOutputProperties(OutputPropertyVisitor visitor) { } @Override - public OutputHandling getOutputHandling() { - return DETECT_ADDED; + public boolean includeAddedOutputs() { + return true; } @Override diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/ExecutionOutcome.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/ExecutionOutcome.java index ad0e550caac12..f877c1d4b36f5 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/ExecutionOutcome.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/ExecutionOutcome.java @@ -37,5 +37,5 @@ public enum ExecutionOutcome { /** * The work has been executed with no incremental change information. */ - EXECUTED_FULLY + EXECUTED } diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/UnitOfWork.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/UnitOfWork.java index 4d92a8cafd4bd..c33cdef9600fc 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/UnitOfWork.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/UnitOfWork.java @@ -20,7 +20,6 @@ import org.gradle.api.file.FileCollection; import org.gradle.caching.internal.CacheableEntity; import org.gradle.internal.execution.history.ExecutionHistoryStore; -import org.gradle.internal.execution.history.changes.OutputFileChanges.OutputHandling; import org.gradle.internal.file.TreeType; import org.gradle.internal.fingerprint.CurrentFileCollectionFingerprint; @@ -59,7 +58,10 @@ public interface UnitOfWork extends CacheableEntity { */ Optional> getChangingOutputs(); - OutputHandling getOutputHandling(); + /** + * Whether files added are to be considered part of the output of the work. + */ + boolean includeAddedOutputs(); @FunctionalInterface interface OutputPropertyVisitor { diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/DefaultExecutionStateChanges.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/DefaultExecutionStateChanges.java index f6bb5609574a0..5d7beef53f302 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/DefaultExecutionStateChanges.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/DefaultExecutionStateChanges.java @@ -35,7 +35,7 @@ public class DefaultExecutionStateChanges implements ExecutionStateChanges { private final ChangeContainer allChanges; private final ChangeContainer rebuildTriggeringChanges; - public DefaultExecutionStateChanges(AfterPreviousExecutionState lastExecution, BeforeExecutionState thisExecution, Describable executable, OutputFileChanges.OutputHandling outputHandling) { + public DefaultExecutionStateChanges(AfterPreviousExecutionState lastExecution, BeforeExecutionState thisExecution, Describable executable, boolean includeAddedOutputs) { this.previousExecution = lastExecution; // Capture changes in execution outcome @@ -80,7 +80,7 @@ public DefaultExecutionStateChanges(AfterPreviousExecutionState lastExecution, B OutputFileChanges uncachedOutputChanges = new OutputFileChanges( lastExecution.getOutputFileProperties(), thisExecution.getOutputFileProperties(), - outputHandling); + includeAddedOutputs); ChangeContainer outputFileChanges = caching(uncachedOutputChanges); this.allChanges = errorHandling(executable, new SummarizingChangeContainer(previousSuccessState, implementationChanges, inputPropertyChanges, inputPropertyValueChanges, outputFilePropertyChanges, outputFileChanges, inputFilePropertyChanges, inputFileChanges)); diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/OutputFileChanges.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/OutputFileChanges.java index 4afefad6ca3e8..0855de65e5ca1 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/OutputFileChanges.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/OutputFileChanges.java @@ -17,40 +17,21 @@ package org.gradle.internal.execution.history.changes; import com.google.common.collect.ImmutableSortedMap; -import org.gradle.internal.change.ChangeDetectorVisitor; import org.gradle.internal.change.ChangeVisitor; import org.gradle.internal.fingerprint.CurrentFileCollectionFingerprint; import org.gradle.internal.fingerprint.FileCollectionFingerprint; public class OutputFileChanges extends AbstractFingerprintChanges { - private final OutputHandling outputHandling; + private final boolean includeAdded; - public OutputFileChanges(ImmutableSortedMap previous, ImmutableSortedMap current, OutputHandling outputHandling) { + public OutputFileChanges(ImmutableSortedMap previous, ImmutableSortedMap current, boolean includeAdded) { super(previous, current, "Output"); - this.outputHandling = outputHandling; - } - - public boolean hasAnyChanges() { - ChangeDetectorVisitor changeDetectorVisitor = new ChangeDetectorVisitor(); - accept(changeDetectorVisitor, true); - return changeDetectorVisitor.hasAnyChanges(); + this.includeAdded = includeAdded; } @Override public boolean accept(ChangeVisitor visitor) { - return accept(visitor, outputHandling == OutputHandling.DETECT_ADDED); - } - - public enum OutputHandling { - /** - * Handle added outputs as changes. - */ - DETECT_ADDED, - - /** - * Ignore added outputs. - */ - IGNORE_ADDED + return accept(visitor, includeAdded); } } diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/ResolveChangesStep.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/ResolveChangesStep.java index ac92678b905d4..b9b8dbfd3758f 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/ResolveChangesStep.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/ResolveChangesStep.java @@ -40,6 +40,7 @@ public ResolveChangesStep(Step delegate) { @Override public R execute(IncrementalContext context) { + final UnitOfWork work = context.getWork(); ExecutionStateChanges changes = context.getRebuildReason() .map(rebuildReason -> new RebuildExecutionStateChanges(rebuildReason) @@ -50,8 +51,8 @@ public R execute(IncrementalContext context) { .map(beforeExecution -> new DefaultExecutionStateChanges( afterPreviousExecution, beforeExecution, - context.getWork(), - context.getWork().getOutputHandling()) + work, + work.includeAddedOutputs()) ) ) .orElse(null) @@ -80,7 +81,7 @@ public Optional getBeforeExecutionState() { @Override public UnitOfWork getWork() { - return context.getWork(); + return work; } }); } diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/StoreSnapshotsStep.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/StoreSnapshotsStep.java index 927bcd69502b9..8e9b23baf924c 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/StoreSnapshotsStep.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/StoreSnapshotsStep.java @@ -17,6 +17,7 @@ package org.gradle.internal.execution.steps; import com.google.common.collect.ImmutableSortedMap; +import org.gradle.internal.change.ChangeDetectorVisitor; import org.gradle.internal.execution.CurrentSnapshotResult; import org.gradle.internal.execution.IncrementalContext; import org.gradle.internal.execution.Step; @@ -53,7 +54,7 @@ public CurrentSnapshotResult execute(C context) { UnitOfWork work = context.getWork(); if (successful || !afterPreviousExecutionState.isPresent() - || hasAnyOutputFileChanges(afterPreviousExecutionState.get().getOutputFileProperties(), finalOutputs, work.getOutputHandling())) { + || hasAnyOutputFileChanges(afterPreviousExecutionState.get().getOutputFileProperties(), finalOutputs)) { work.getExecutionHistoryStore().store( work.getIdentity(), result.getOriginMetadata(), @@ -71,8 +72,13 @@ public CurrentSnapshotResult execute(C context) { return result; } - private static boolean hasAnyOutputFileChanges(ImmutableSortedMap previous, ImmutableSortedMap current, OutputFileChanges.OutputHandling outputHandling) { - return !previous.keySet().equals(current.keySet()) - || new OutputFileChanges(previous, current, outputHandling).hasAnyChanges(); + private static boolean hasAnyOutputFileChanges(ImmutableSortedMap previous, ImmutableSortedMap current) { + if (!previous.keySet().equals(current.keySet())) { + return true; + } + ChangeDetectorVisitor visitor = new ChangeDetectorVisitor(); + OutputFileChanges changes = new OutputFileChanges(previous, current, true); + changes.accept(visitor); + return visitor.hasAnyChanges(); } } diff --git a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/CacheStepTest.groovy b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/CacheStepTest.groovy index e68fa54a27092..d560d07d29356 100644 --- a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/CacheStepTest.groovy +++ b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/CacheStepTest.groovy @@ -105,7 +105,7 @@ class CacheStepTest extends Specification { def executionResult = new CurrentSnapshotResult() { final ImmutableSortedMap finalOutputs = ImmutableSortedMap.of("test", new EmptyCurrentFileCollectionFingerprint()) final OriginMetadata originMetadata = new OriginMetadata(currentBuildId, 0) - final Try outcome = Try.successful(ExecutionOutcome.EXECUTED_FULLY) + final Try outcome = Try.successful(ExecutionOutcome.EXECUTED) final boolean reused = false } @@ -150,7 +150,7 @@ class CacheStepTest extends Specification { def executionResult = new CurrentSnapshotResult() { final ImmutableSortedMap finalOutputs = ImmutableSortedMap.of("test", new EmptyCurrentFileCollectionFingerprint()) final OriginMetadata originMetadata = new OriginMetadata(currentBuildId, 0) - final Try outcome = Try.successful(ExecutionOutcome.EXECUTED_FULLY) + final Try outcome = Try.successful(ExecutionOutcome.EXECUTED) final boolean reused = false } when: diff --git a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/ExecutionTest.groovy b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/ExecutionTest.groovy index 0fca3ae317112..c313df01daa5b 100644 --- a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/ExecutionTest.groovy +++ b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/ExecutionTest.groovy @@ -29,15 +29,12 @@ import org.gradle.internal.execution.history.AfterPreviousExecutionState import org.gradle.internal.execution.history.BeforeExecutionState import org.gradle.internal.execution.history.ExecutionHistoryStore import org.gradle.internal.execution.history.changes.ExecutionStateChanges -import org.gradle.internal.execution.history.changes.OutputFileChanges import org.gradle.internal.fingerprint.CurrentFileCollectionFingerprint import spock.lang.Specification import java.time.Duration import java.util.function.Supplier -import static org.gradle.internal.execution.history.changes.OutputFileChanges.OutputHandling.DETECT_ADDED - class ExecutionTest extends Specification { def outputChangeListener = Mock(OutputChangeListener) @@ -61,7 +58,7 @@ class ExecutionTest extends Specification { 0 * _ where: - outcome << [ExecutionOutcome.EXECUTED_FULLY, ExecutionOutcome.EXECUTED_INCREMENTALLY] + outcome << [ExecutionOutcome.EXECUTED, ExecutionOutcome.EXECUTED_INCREMENTALLY] } def "reports no work done"() { @@ -99,20 +96,20 @@ class ExecutionTest extends Specification { def "invalidates only changing outputs"() { def changingOutputs = ['some/location'] - def unitOfWork = new TestUnitOfWork({ -> ExecutionOutcome.EXECUTED_FULLY }, changingOutputs) + def unitOfWork = new TestUnitOfWork({ -> ExecutionOutcome.EXECUTED }, changingOutputs) when: def result = execute { -> unitOfWork } then: - result.outcome.get() == ExecutionOutcome.EXECUTED_FULLY + result.outcome.get() == ExecutionOutcome.EXECUTED 1 * outputChangeListener.beforeOutputChange(changingOutputs) 0 * _ } def "fails the execution when build has been cancelled"() { - def unitOfWork = new TestUnitOfWork({ -> ExecutionOutcome.EXECUTED_FULLY }) + def unitOfWork = new TestUnitOfWork({ -> ExecutionOutcome.EXECUTED }) when: cancellationToken.cancel() @@ -160,8 +157,8 @@ class ExecutionTest extends Specification { } @Override - OutputFileChanges.OutputHandling getOutputHandling() { - return DETECT_ADDED + boolean includeAddedOutputs() { + return true } @Override @@ -184,7 +181,6 @@ class ExecutionTest extends Specification { throw new UnsupportedOperationException() } - @Override Optional> getChangingOutputs() { Optional.ofNullable(changingOutputs) diff --git a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/IncrementalExecutionTest.groovy b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/IncrementalExecutionTest.groovy index beb16b379607f..9347bc9547f1c 100644 --- a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/IncrementalExecutionTest.groovy +++ b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/IncrementalExecutionTest.groovy @@ -40,7 +40,6 @@ import org.gradle.internal.execution.UpToDateResult import org.gradle.internal.execution.WorkExecutor import org.gradle.internal.execution.history.ExecutionHistoryStore import org.gradle.internal.execution.history.changes.ExecutionStateChanges -import org.gradle.internal.execution.history.changes.OutputFileChanges import org.gradle.internal.execution.impl.DefaultWorkExecutor import org.gradle.internal.file.TreeType import org.gradle.internal.fingerprint.CurrentFileCollectionFingerprint @@ -65,10 +64,8 @@ import spock.lang.Ignore import java.time.Duration import java.util.function.Supplier -import static org.gradle.internal.execution.ExecutionOutcome.EXECUTED_FULLY +import static org.gradle.internal.execution.ExecutionOutcome.EXECUTED import static org.gradle.internal.execution.ExecutionOutcome.UP_TO_DATE -import static org.gradle.internal.execution.history.changes.OutputFileChanges.OutputHandling.DETECT_ADDED - // FIXME:lptr @Ignore class IncrementalExecutionTest extends Specification { @@ -147,14 +144,14 @@ class IncrementalExecutionTest extends Specification { "file": [file("parent/outFile")], "files": [file("parent1/outFile"), file("parent2/outputFile1"), file("parent2/outputFile2")], ).withWork { -> - EXECUTED_FULLY + EXECUTED }.build() when: def result = execute(unitOfWork) then: - result.outcome.get() == EXECUTED_FULLY + result.outcome.get() == EXECUTED !result.reused def allDirs = ["outDir", "outDir1", "outDir2"].collect { file(it) } @@ -173,7 +170,7 @@ class IncrementalExecutionTest extends Specification { def result = execute(unitOfWork) then: - result.outcome.get() == EXECUTED_FULLY + result.outcome.get() == EXECUTED !result.reused result.finalOutputs.keySet() == ["dir", "emptyDir", "file", "missingDir", "missingFile"] as Set @@ -189,7 +186,7 @@ class IncrementalExecutionTest extends Specification { def result = execute(unitOfWork) then: - result.outcome.get() == EXECUTED_FULLY + result.outcome.get() == EXECUTED !result.reused def origin = result.originMetadata.buildInvocationId @@ -214,7 +211,7 @@ class IncrementalExecutionTest extends Specification { def result = execute(unitOfWork) then: - result.outcome.get() == EXECUTED_FULLY + result.outcome.get() == EXECUTED !result.reused def origin = result.originMetadata.buildInvocationId @@ -225,7 +222,7 @@ class IncrementalExecutionTest extends Specification { result = outOfDate(builder.build(), outputFilesChanged(file: [outputFile])) then: - result.outcome.get() == EXECUTED_FULLY + result.outcome.get() == EXECUTED !result.reused result.originMetadata.buildInvocationId == buildInvocationScopeId.id result.originMetadata.buildInvocationId != origin @@ -249,7 +246,7 @@ class IncrementalExecutionTest extends Specification { result = outOfDate(builder.build(), "Task has failed previously.") then: - result.outcome.get() == EXECUTED_FULLY + result.outcome.get() == EXECUTED !result.reused result.originMetadata.buildInvocationId == buildInvocationScopeId.id result.originMetadata.buildInvocationId != origin @@ -260,7 +257,7 @@ class IncrementalExecutionTest extends Specification { def result = execute(unitOfWork) then: - result.outcome.get() == EXECUTED_FULLY + result.outcome.get() == EXECUTED !result.reused result.executionReasons == ["No history is available."] } @@ -274,7 +271,7 @@ class IncrementalExecutionTest extends Specification { def result = execute(unitOfWork) then: - result.outcome.get() == EXECUTED_FULLY + result.outcome.get() == EXECUTED !result.reused result.executionReasons == ["Output property 'file' file ${outputFile.absolutePath} has been removed."] } @@ -288,7 +285,7 @@ class IncrementalExecutionTest extends Specification { def result = execute(unitOfWork) then: - result.outcome.get() == EXECUTED_FULLY + result.outcome.get() == EXECUTED !result.reused result.executionReasons == ["Output property 'dir' file ${outputDirFile.absolutePath} has been removed."] } @@ -331,7 +328,7 @@ class IncrementalExecutionTest extends Specification { outputFile << "new content" def result = execute(unitOfWork) then: - result.outcome.get() == EXECUTED_FULLY + result.outcome.get() == EXECUTED !result.reused result.executionReasons == ["Output property 'file' file ${outputFile.absolutePath} has changed."] } @@ -344,7 +341,7 @@ class IncrementalExecutionTest extends Specification { outputDirFile << "new content" def result = execute(unitOfWork) then: - result.outcome.get() == EXECUTED_FULLY + result.outcome.get() == EXECUTED !result.reused result.executionReasons == ["Output property 'dir' file ${outputDirFile.absolutePath} has changed."] } @@ -368,7 +365,7 @@ class IncrementalExecutionTest extends Specification { def result = execute(outputFilesRemovedUnitOfWork) then: - result.outcome.get() == EXECUTED_FULLY + result.outcome.get() == EXECUTED !result.reused result.executionReasons == ["Output property 'file' has been removed for ${outputFilesRemovedUnitOfWork.displayName}"] } @@ -620,7 +617,7 @@ class IncrementalExecutionTest extends Specification { UpToDateResult outOfDate(UnitOfWork unitOfWork, List expectedReasons) { def result = execute(unitOfWork) - assert result.outcome.get() == EXECUTED_FULLY + assert result.outcome.get() == EXECUTED assert !result.reused assert result.executionReasons == expectedReasons return result @@ -673,7 +670,7 @@ class IncrementalExecutionTest extends Specification { create.each { it -> it.createFile() } - return EXECUTED_FULLY + return EXECUTED } private Map inputProperties = [prop: "value"] private Map> inputs = inputFiles @@ -771,8 +768,8 @@ class IncrementalExecutionTest extends Specification { } @Override - OutputFileChanges.OutputHandling getOutputHandling() { - return DETECT_ADDED + boolean includeAddedOutputs() { + return true } @Override From 7d85e0b230f1afe8e8ec14aaea0e3ea93cd7d7cc Mon Sep 17 00:00:00 2001 From: Stefan Wolf Date: Wed, 6 Mar 2019 22:42:15 +0100 Subject: [PATCH 356/853] Improve upToDateWhen Javadoc To clarify that upToDateWhen also has an effect on the build cache. --- .../org/gradle/api/tasks/TaskOutputs.java | 35 ++++++++++++------- 1 file changed, 23 insertions(+), 12 deletions(-) diff --git a/subprojects/core-api/src/main/java/org/gradle/api/tasks/TaskOutputs.java b/subprojects/core-api/src/main/java/org/gradle/api/tasks/TaskOutputs.java index 2829db8394ddc..6ac2dc1e89e39 100644 --- a/subprojects/core-api/src/main/java/org/gradle/api/tasks/TaskOutputs.java +++ b/subprojects/core-api/src/main/java/org/gradle/api/tasks/TaskOutputs.java @@ -30,24 +30,35 @@ @HasInternalProtocol public interface TaskOutputs { /** - *

    Adds a predicate to determine whether the outputs of this task are up-to-date. The given closure is executed - * at task execution time. The closure is passed the task as a parameter. If the closure returns false, the task - * outputs are considered out-of-date and the task will be executed.

    - * - *

    You can add multiple such predicates. The task outputs are considered out-of-date when any predicate returns - * false.

    + *

    + * Adds a predicate to determine whether previous outputs of this task can be reused. + * The given closure is executed at task execution time. + * The closure is passed the task as a parameter. + * If the closure returns false, previous outputs of this task cannot be reused and the task will be executed. + * That means the task is out-of-date and no outputs will be loaded from the build cache. + *

    + * + *

    + * You can add multiple such predicates. + * The task outputs cannot be reused when any predicate returns false. + *

    * * @param upToDateClosure The closure to use to determine whether the task outputs are up-to-date. */ void upToDateWhen(Closure upToDateClosure); /** - *

    Adds a predicate to determine whether the outputs of this task are up-to-date. The given spec is evaluated at - * task execution time. If the spec returns false, the task outputs are considered out-of-date and the task will be - * executed.

    - * - *

    You can add multiple such predicates. The task outputs are considered out-of-date when any predicate returns - * false.

    + *

    + * Adds a predicate to determine whether previous outputs of this task can be reused. + * The given spec is evaluated at task execution time. + * If the spec returns false, previous outputs of this task cannot be reused and the task will be executed. + * That means the task is out-of-date and no outputs will be loaded from the build cache. + *

    + * + *

    + * You can add multiple such predicates. + * The task outputs cannot be reused when any predicate returns false. + *

    * * @param upToDateSpec The spec to use to determine whether the task outputs are up-to-date. */ From 63c601a656c7cbe36002537cdfb33b0d502297a2 Mon Sep 17 00:00:00 2001 From: Adam Murdoch Date: Wed, 6 Mar 2019 18:04:22 +1100 Subject: [PATCH 357/853] Fix test failure when script is cached. --- .../r51/ProjectConfigurationProgressEventCrossVersionSpec.groovy | 1 + 1 file changed, 1 insertion(+) diff --git a/subprojects/tooling-api/src/crossVersionTest/groovy/org/gradle/integtests/tooling/r51/ProjectConfigurationProgressEventCrossVersionSpec.groovy b/subprojects/tooling-api/src/crossVersionTest/groovy/org/gradle/integtests/tooling/r51/ProjectConfigurationProgressEventCrossVersionSpec.groovy index cf6b8519f3571..bbe618f6da037 100644 --- a/subprojects/tooling-api/src/crossVersionTest/groovy/org/gradle/integtests/tooling/r51/ProjectConfigurationProgressEventCrossVersionSpec.groovy +++ b/subprojects/tooling-api/src/crossVersionTest/groovy/org/gradle/integtests/tooling/r51/ProjectConfigurationProgressEventCrossVersionSpec.groovy @@ -217,6 +217,7 @@ class ProjectConfigurationProgressEventCrossVersionSpec extends ToolingApiSpecif def "reports plugin configuration results for remote script plugins"() { given: + toolingApi.requireIsolatedUserHome() // So that the script is not cached server.start() def scriptUri = server.uri("script.gradle") server.expect(server.get("script.gradle").send(""" From 909d5b926f5c8ecf8b89f0fab911c76bc3dcf06f Mon Sep 17 00:00:00 2001 From: Adam Murdoch Date: Wed, 6 Mar 2019 18:09:27 +1100 Subject: [PATCH 358/853] Change `BlockingHttpServer` fixture to return a 400 response rather than 500 response when an unexpected HTTP request is received. Also improve diagnostic messages for certain kinds of failures. --- .../fixtures/server/http/AbstractFailure.java | 57 ++++++ .../server/http/ChainingHttpHandler.java | 53 +++--- .../CyclicBarrierAnyOfRequestHandler.java | 63 ++++--- .../http/CyclicBarrierRequestHandler.java | 40 ++-- .../server/http/ExpectationState.java | 112 +++++++++++ .../test/fixtures/server/http/Failure.java | 20 ++ .../server/http/RequestConditionFailure.java | 23 +++ .../server/http/ResponseProducer.java | 11 ++ .../server/http/TrackingHttpHandler.java | 6 +- .../http/UnexpectedRequestException.java | 2 +- .../server/http/UnexpectedRequestFailure.java | 27 +++ .../server/http/BlockingHttpServerTest.groovy | 175 +++++++++--------- 12 files changed, 439 insertions(+), 150 deletions(-) create mode 100644 subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/server/http/AbstractFailure.java create mode 100644 subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/server/http/ExpectationState.java create mode 100644 subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/server/http/Failure.java create mode 100644 subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/server/http/RequestConditionFailure.java create mode 100644 subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/server/http/UnexpectedRequestFailure.java diff --git a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/server/http/AbstractFailure.java b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/server/http/AbstractFailure.java new file mode 100644 index 0000000000000..9957266717277 --- /dev/null +++ b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/server/http/AbstractFailure.java @@ -0,0 +1,57 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.test.fixtures.server.http; + +import com.sun.net.httpserver.HttpExchange; + +abstract class AbstractFailure implements ResponseProducer, Failure { + private final RuntimeException failure; + + public AbstractFailure(RuntimeException failure) { + this.failure = failure; + } + + @Override + public boolean isFailure() { + return true; + } + + @Override + public RuntimeException getFailure() { + return failure; + } + + @Override + public void writeTo(int requestId, HttpExchange exchange) { + throw new IllegalStateException(); + } + + protected static String withLeadingSlash(String path) { + if (path.startsWith("/")) { + return path; + } else { + return "/" + path; + } + } + + protected static String contextSuffix(String context) { + if (context.isEmpty()) { + return context; + } + return ". " + context; + } +} diff --git a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/server/http/ChainingHttpHandler.java b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/server/http/ChainingHttpHandler.java index e59eff64a7cf9..5ac795e20d9df 100644 --- a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/server/http/ChainingHttpHandler.java +++ b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/server/http/ChainingHttpHandler.java @@ -24,7 +24,7 @@ import org.gradle.internal.time.Clock; import org.gradle.internal.time.Time; -import javax.annotation.Nullable; +import java.io.IOException; import java.util.ArrayList; import java.util.Collection; import java.util.List; @@ -111,23 +111,23 @@ public void handle(HttpExchange httpExchange) { System.out.println(String.format("[%d] handling %s", id, outcome.getDisplayName())); try { - ResponseProducer responseProducer = selectProducer(id, httpExchange, outcome); - if (responseProducer != null) { - System.out.println(String.format("[%d] sending response for %s", id, outcome.getDisplayName())); + ResponseProducer responseProducer = selectProducer(id, httpExchange); + System.out.println(String.format("[%d] sending error response for %s", id, outcome.getDisplayName())); + if (!responseProducer.isFailure()) { responseProducer.writeTo(id, httpExchange); } else { - System.out.println(String.format("[%d] sending error response for unexpected request", id)); - if (outcome.method.equals("HEAD")) { - httpExchange.sendResponseHeaders(500, -1); - } else { - byte[] message = String.format("Failed request %s", outcome.getDisplayName()).getBytes(Charsets.UTF_8); - httpExchange.sendResponseHeaders(500, message.length); - httpExchange.getResponseBody().write(message); - } + Throwable failure = responseProducer.getFailure(); + requestFailed(outcome, failure); + sendFailure(httpExchange, 400, outcome); } } catch (Throwable t) { System.out.println(String.format("[%d] handling %s failed with exception", id, outcome.getDisplayName())); - requestFailed(outcome, t); + try { + sendFailure(httpExchange, 500, outcome); + } catch (IOException e) { + // Ignore + } + requestFailed(outcome, new AssertionError(String.format("Failed to handle %s", outcome.getDisplayName()), t)); } finally { requestCompleted(outcome); } @@ -136,6 +136,16 @@ public void handle(HttpExchange httpExchange) { } } + private void sendFailure(HttpExchange httpExchange, int responseCode, RequestOutcome outcome) throws IOException { + if (outcome.method.equals("HEAD")) { + httpExchange.sendResponseHeaders(responseCode, -1); + } else { + byte[] message = String.format("Failed request %s", outcome.getDisplayName()).getBytes(Charsets.UTF_8); + httpExchange.sendResponseHeaders(responseCode, message.length); + httpExchange.getResponseBody().write(message); + } + } + private RequestOutcome requestStarted(HttpExchange httpExchange) { lock.lock(); RequestOutcome outcome; @@ -152,7 +162,7 @@ private void requestFailed(RequestOutcome outcome, Throwable t) { lock.lock(); try { if (outcome.failure == null) { - outcome.failure = new AssertionError(String.format("Failed to handle %s", outcome.getDisplayName()), t); + outcome.failure = t; } } finally { lock.unlock(); @@ -163,18 +173,14 @@ private void requestCompleted(RequestOutcome outcome) { outcome.completed(); } - /** - * Returns null on failure. - */ - @Nullable - private ResponseProducer selectProducer(int id, HttpExchange httpExchange, RequestOutcome outcome) { + private ResponseProducer selectProducer(int id, HttpExchange httpExchange) { lock.lock(); try { requestsStarted++; condition.signalAll(); if (completed) { System.out.println(String.format("[%d] received request %s %s after HTTP server has stopped.", id, httpExchange.getRequestMethod(), httpExchange.getRequestURI())); - return null; + return new UnexpectedRequestFailure(httpExchange.getRequestMethod(), httpExchange.getRequestURI().getPath()); } for (TrackingHttpHandler handler : handlers) { ResponseProducer responseProducer = handler.selectResponseProducer(id, httpExchange); @@ -182,15 +188,10 @@ private ResponseProducer selectProducer(int id, HttpExchange httpExchange, Reque return responseProducer; } } - System.out.println(String.format("[%d] unexpected request %s %s", id, httpExchange.getRequestMethod(), httpExchange.getRequestURI())); - outcome.failure = new AssertionError(String.format("Received unexpected request %s %s", httpExchange.getRequestMethod(), httpExchange.getRequestURI().getPath())); - } catch (Throwable t) { - System.out.println(String.format("[%d] error during handling of request %s %s", id, httpExchange.getRequestMethod(), httpExchange.getRequestURI())); - outcome.failure = new AssertionError(String.format("Failed to handle %s %s", httpExchange.getRequestMethod(), httpExchange.getRequestURI().getPath()), t); + return new UnexpectedRequestFailure(httpExchange.getRequestMethod(), httpExchange.getRequestURI().getPath()); } finally { lock.unlock(); } - return null; } void waitForRequests(int requestCount) { diff --git a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/server/http/CyclicBarrierAnyOfRequestHandler.java b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/server/http/CyclicBarrierAnyOfRequestHandler.java index 1a6d69a3ec1a0..2ba1c7cc5c7e8 100644 --- a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/server/http/CyclicBarrierAnyOfRequestHandler.java +++ b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/server/http/CyclicBarrierAnyOfRequestHandler.java @@ -17,6 +17,7 @@ package org.gradle.test.fixtures.server.http; import com.sun.net.httpserver.HttpExchange; +import org.gradle.internal.UncheckedException; import org.gradle.internal.time.Clock; import org.gradle.internal.time.Time; @@ -45,7 +46,7 @@ class CyclicBarrierAnyOfRequestHandler implements TrackingHttpHandler, WaitPreco private final WaitPrecondition previous; private long mostRecentEvent; private boolean cancelled; - private AssertionError failure; + private final ExpectationState state = new ExpectationState(); CyclicBarrierAnyOfRequestHandler(Lock lock, int testId, int timeoutMs, int maxConcurrent, WaitPrecondition previous, Collection expectedRequests) { if (expectedRequests.size() < maxConcurrent) { @@ -84,7 +85,7 @@ public void assertCanWait() throws IllegalStateException { } @Override - public ResponseProducer selectResponseProducer(int id, HttpExchange exchange) throws Exception { + public ResponseProducer selectResponseProducer(int id, HttpExchange exchange) { ResourceHandlerWrapper handler; lock.lock(); try { @@ -101,9 +102,9 @@ public ResponseProducer selectResponseProducer(int id, HttpExchange exchange) th String path = exchange.getRequestURI().getPath().substring(1); handler = selectPending(notReceived, path); if (handler == null || !handler.getMethod().equals(exchange.getRequestMethod()) || waitingFor == 0) { - failure = new UnexpectedRequestException(String.format("Unexpected request %s /%s received. Waiting for %s further requests, already received %s, released %s, still expecting %s.", exchange.getRequestMethod(), path, waitingFor, received, released, format(notReceived))); + ResponseProducer failure = state.unexpectedRequest(exchange.getRequestMethod(), path, describeCurrentState()); condition.signalAll(); - throw failure; + return failure; } notReceived.remove(handler); @@ -115,25 +116,41 @@ public ResponseProducer selectResponseProducer(int id, HttpExchange exchange) th condition.signalAll(); } - while (!handler.isReleased() && failure == null && !cancelled) { + if (state.isFailed()) { + // Broken in another thread + System.out.println(String.format("[%d] failure in another thread", id)); + return state.alreadyFailed(exchange.getRequestMethod(), path, describeCurrentState()); + } + + while (!handler.isReleased() && !state.isFailed() && !cancelled) { long waitMs = mostRecentEvent + timeoutMs - clock.getCurrentTime(); if (waitMs < 0) { + ResponseProducer failure; if (waitingFor > 0) { System.out.println(String.format("[%d] timeout waiting for other requests", id)); - throw timeoutWaitingForRequests(); + failure = state.timeout(exchange.getRequestMethod(), path, "waiting for other requests", describeCurrentState()); + } else { + System.out.println(String.format("[%d] timeout waiting to be released", id)); + failure = state.timeout(exchange.getRequestMethod(), path, "waiting to be released", describeCurrentState()); } - System.out.println(String.format("[%d] timeout waiting to be released", id)); - failure = new AssertionError(String.format("Timeout waiting to be released. Waiting for %s further requests, received %s, released %s, not yet received %s.", waitingFor, received, released, format(notReceived))); condition.signalAll(); - throw failure; + return failure; } System.out.println(String.format("[%d] waiting to be released. Still waiting for %s further requests, already received %s", id, waitingFor, received)); - condition.await(waitMs, TimeUnit.MILLISECONDS); + try { + condition.await(waitMs, TimeUnit.MILLISECONDS); + } catch (InterruptedException e) { + throw UncheckedException.throwAsUncheckedException(e); + } } - if (failure != null) { + if (state.isFailed()) { // Broken in another thread System.out.println(String.format("[%d] failure in another thread", id)); - throw failure; + if (waitingFor > 0) { + return state.failureWhileWaiting(exchange.getRequestMethod(), path, "waiting for other requests", describeCurrentState()); + } else { + return state.failureWhileWaiting(exchange.getRequestMethod(), path, "waiting to be released", describeCurrentState()); + } } if (cancelled) { return new ResponseProducer() { @@ -154,6 +171,10 @@ public void writeTo(int requestId, HttpExchange exchange) { return handler; } + private String describeCurrentState() { + return String.format("Waiting for %s further requests, received %s, released %s, not yet received %s", waitingFor, received, released, format(notReceived)); + } + @Override public void cancelBlockedRequests() { lock.lock(); @@ -169,12 +190,12 @@ public void cancelBlockedRequests() { public void assertComplete(Collection failures) throws AssertionError { lock.lock(); try { - if (failure != null) { + if (state.isFailed()) { // Already reported return; } if (!notReceived.isEmpty()) { - failures.add(new AssertionError(String.format("Did not handle all expected requests. Waiting for %d further requests, received %s, released %s, not yet received %s.", waitingFor, received, released, format(notReceived)))); + failures.add(new AssertionError(String.format("Did not handle all expected requests. %s", describeCurrentState()))); } } finally { lock.unlock(); @@ -269,11 +290,12 @@ public void waitForAllPendingCalls() { mostRecentEvent = now; } - while (waitingFor > 0 && failure == null) { + while (waitingFor > 0 && !state.isFailed()) { long waitMs = mostRecentEvent + timeoutMs - clock.getCurrentTime(); if (waitMs < 0) { System.out.println(String.format("[%d] timeout waiting for expected requests.", testId)); - throw timeoutWaitingForRequests(); + timeoutWaitingForRequests(); + break; } System.out.println(String.format("[%d] waiting for %d further requests, received %s, released %s, not yet received %s", testId, waitingFor, received, released, format(notReceived))); try { @@ -282,8 +304,8 @@ public void waitForAllPendingCalls() { throw new RuntimeException(e); } } - if (failure != null) { - throw failure; + if (state.isFailed()) { + throw state.getWaitFailure(describeCurrentState()); } System.out.println(String.format("[%d] expected requests received, received %s, released %s, not yet received %s", testId, received, released, format(notReceived))); } finally { @@ -291,9 +313,8 @@ public void waitForAllPendingCalls() { } } - private AssertionError timeoutWaitingForRequests() { - failure = new AssertionError(String.format("Timeout waiting for expected requests. Waiting for %d further requests, received %s, released %s, not yet received %s.", waitingFor, received, released, format(notReceived))); + private void timeoutWaitingForRequests() { + state.timeout("waiting for expected requests", describeCurrentState()); condition.signalAll(); - throw failure; } } diff --git a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/server/http/CyclicBarrierRequestHandler.java b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/server/http/CyclicBarrierRequestHandler.java index 0de988dd9563c..242ff1379a906 100644 --- a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/server/http/CyclicBarrierRequestHandler.java +++ b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/server/http/CyclicBarrierRequestHandler.java @@ -17,6 +17,7 @@ package org.gradle.test.fixtures.server.http; import com.sun.net.httpserver.HttpExchange; +import org.gradle.internal.UncheckedException; import org.gradle.internal.time.Time; import org.gradle.internal.time.Timer; @@ -39,7 +40,7 @@ class CyclicBarrierRequestHandler implements TrackingHttpHandler, WaitPreconditi private final WaitPrecondition previous; private long mostRecentEvent; private boolean cancelled; - private AssertionError failure; + private final ExpectationState state = new ExpectationState(); CyclicBarrierRequestHandler(Lock lock, int timeoutMs, WaitPrecondition previous, Collection expectations) { this.lock = lock; @@ -74,7 +75,7 @@ public void assertCanWait() throws AssertionError { } @Override - public ResponseProducer selectResponseProducer(int id, HttpExchange httpExchange) throws Exception { + public ResponseProducer selectResponseProducer(int id, HttpExchange httpExchange) { ResourceHandler handler; lock.lock(); try { @@ -91,9 +92,9 @@ public ResponseProducer selectResponseProducer(int id, HttpExchange httpExchange String path = httpExchange.getRequestURI().getPath().substring(1); handler = selectPending(pending, path); if (handler == null || !handler.getMethod().equals(httpExchange.getRequestMethod())) { - failure = new UnexpectedRequestException(String.format("Unexpected request %s /%s received. Waiting for %s, already received %s.", httpExchange.getRequestMethod(), path, format(pending), received)); + ResponseProducer failure = state.unexpectedRequest(httpExchange.getRequestMethod(), path, describeCurrentState()); condition.signalAll(); - throw failure; + return failure; } received.add(httpExchange.getRequestMethod() + " /" + path); @@ -102,23 +103,34 @@ public ResponseProducer selectResponseProducer(int id, HttpExchange httpExchange condition.signalAll(); } - while (!pending.isEmpty() && failure == null && !cancelled) { + if (state.isFailed()) { + // Failed in another thread + System.out.println(String.format("[%d] failure in another thread", id)); + return state.alreadyFailed(httpExchange.getRequestMethod(), path, describeCurrentState()); + } + + while (!pending.isEmpty() && !state.isFailed() && !cancelled) { long waitMs = mostRecentEvent + timeoutMs - timer.getElapsedMillis(); if (waitMs < 0) { System.out.println(String.format("[%d] timeout waiting for other requests", id)); - failure = new AssertionError(String.format("Timeout waiting for expected requests to be received. Still waiting for %s, received %s.", format(pending), received)); + ResponseProducer failure = state.timeout(httpExchange.getRequestMethod(), path, "waiting for other requests", describeCurrentState()); condition.signalAll(); - throw failure; + return failure; } System.out.println(String.format("[%d] waiting for other requests. Still waiting for %s", id, format(pending))); - condition.await(waitMs, TimeUnit.MILLISECONDS); + try { + condition.await(waitMs, TimeUnit.MILLISECONDS); + } catch (InterruptedException e) { + UncheckedException.throwAsUncheckedException(e); + } } - if (failure != null) { + if (state.isFailed()) { // Failed in another thread System.out.println(String.format("[%d] failure in another thread", id)); - throw failure; + return state.failureWhileWaiting(httpExchange.getRequestMethod(), path, "waiting for other requests", describeCurrentState()); } + if (cancelled) { return new ResponseProducer() { @Override @@ -139,6 +151,10 @@ public void writeTo(int requestId, HttpExchange exchange) { return handler; } + private String describeCurrentState() { + return String.format("Waiting for %s, already received %s", format(pending), received); + } + @Override public void cancelBlockedRequests() { lock.lock(); @@ -179,12 +195,12 @@ static T selectPending(List handlers, String path public void assertComplete(Collection failures) throws AssertionError { lock.lock(); try { - if (failure != null) { + if (state.isFailed()) { // Already reported return; } if (!pending.isEmpty()) { - failures.add(new AssertionError(String.format("Did not receive expected requests. Waiting for %s, received %s", format(pending), received))); + failures.add(new AssertionError(String.format("Did not receive expected requests. %s", describeCurrentState()))); } } finally { lock.unlock(); diff --git a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/server/http/ExpectationState.java b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/server/http/ExpectationState.java new file mode 100644 index 0000000000000..99e45d9837edc --- /dev/null +++ b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/server/http/ExpectationState.java @@ -0,0 +1,112 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.test.fixtures.server.http; + +import static org.gradle.test.fixtures.server.http.AbstractFailure.contextSuffix; +import static org.gradle.test.fixtures.server.http.AbstractFailure.withLeadingSlash; + +class ExpectationState { + + private enum FailureType { + None, UnexpectedRequest, Timeout + } + + private FailureType failure = FailureType.None; + private String unexpectedMethod; + private String unexpectedPath; + + public boolean isFailed() { + return failure != FailureType.None; + } + + /** + * Signals that an unexpected request was received. + * + * @return A response to return to the client + */ + public ResponseProducer unexpectedRequest(String requestMethod, String path, String context) { + if (failure == FailureType.None) { + failure = FailureType.UnexpectedRequest; + unexpectedMethod = requestMethod; + unexpectedPath = path; + } + return new UnexpectedRequestFailure(requestMethod, path, context); + } + + /** + * Signals that a timeout occurred waiting to handle the given request. + * + * @return A response to return to the client + */ + public ResponseProducer timeout(String requestMethod, String path, String waitingFor, String context) { + if (failure == FailureType.None) { + failure = FailureType.Timeout; + } + return new RequestConditionFailure(requestMethod, path, String.format("Failed to handle %s %s due to a timeout %s%s", requestMethod, withLeadingSlash(path), waitingFor, contextSuffix(context))); + } + + /** + * Signals that a timeout occurred waiting for test condition to become true. + */ + public void timeout(String waitingFor, String context) { + if (failure == FailureType.None) { + failure = FailureType.Timeout; + } + } + + /** + * Creates a response to return to the client for an expected request received after a failure. + */ + public ResponseProducer alreadyFailed(String requestMethod, String path, String context) { + switch (failure) { + case UnexpectedRequest: + return new RequestConditionFailure(requestMethod, path, String.format("Failed to handle %s %s due to unexpected request %s %s%s", requestMethod, withLeadingSlash(path), unexpectedMethod, withLeadingSlash(unexpectedPath), contextSuffix(context))); + case Timeout: + return new RequestConditionFailure(requestMethod, path, String.format("Failed to handle %s %s due to a previous timeout%s", requestMethod, withLeadingSlash(path), contextSuffix(context))); + default: + throw new IllegalStateException(); + } + } + + /** + * Creates a response to return to the client for a request that was waiting when a failure occurred. + */ + public ResponseProducer failureWhileWaiting(String requestMethod, String path, String waitingFor, String context) { + switch (failure) { + case UnexpectedRequest: + return new RequestConditionFailure(requestMethod, path, String.format("Failed to handle %s %s due to unexpected request %s %s%s", requestMethod, withLeadingSlash(path), unexpectedMethod, withLeadingSlash(unexpectedPath), contextSuffix(context))); + case Timeout: + return new RequestConditionFailure(requestMethod, path, String.format("Failed to handle %s %s due to a timeout %s%s", requestMethod, withLeadingSlash(path), waitingFor, contextSuffix(context))); + default: + throw new IllegalStateException(); + } + } + + /** + * Creates an exception to throw to the test thread that is waiting for some condition + */ + public RuntimeException getWaitFailure(String context) { + switch (failure) { + case UnexpectedRequest: + return new RuntimeException(String.format("Unexpected request %s %s received%s", unexpectedMethod, withLeadingSlash(unexpectedPath), contextSuffix(context))); + case Timeout: + return new RuntimeException(String.format("Timeout waiting for expected requests%s", contextSuffix(context))); + default: + throw new IllegalStateException(); + } + } +} diff --git a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/server/http/Failure.java b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/server/http/Failure.java new file mode 100644 index 0000000000000..be6e4a175b39d --- /dev/null +++ b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/server/http/Failure.java @@ -0,0 +1,20 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.test.fixtures.server.http; + +interface Failure extends ResponseProducer { +} diff --git a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/server/http/RequestConditionFailure.java b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/server/http/RequestConditionFailure.java new file mode 100644 index 0000000000000..6648e6df81d87 --- /dev/null +++ b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/server/http/RequestConditionFailure.java @@ -0,0 +1,23 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.test.fixtures.server.http; + +class RequestConditionFailure extends AbstractFailure { + public RequestConditionFailure(String method, String path, String message) { + super(new RuntimeException(message)); + } +} diff --git a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/server/http/ResponseProducer.java b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/server/http/ResponseProducer.java index 2585f0c54e68a..bc8c8c95e4bc2 100644 --- a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/server/http/ResponseProducer.java +++ b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/server/http/ResponseProducer.java @@ -21,8 +21,19 @@ import java.io.IOException; interface ResponseProducer { + default boolean isFailure() { + return false; + } + /** * Called to handle a request. Is *not* called under lock. */ void writeTo(int requestId, HttpExchange exchange) throws IOException; + + /** + * Returns the failure, if any. + */ + default RuntimeException getFailure() { + throw new IllegalStateException(); + } } diff --git a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/server/http/TrackingHttpHandler.java b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/server/http/TrackingHttpHandler.java index 7d267a74e1091..5643eb71ed7c2 100644 --- a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/server/http/TrackingHttpHandler.java +++ b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/server/http/TrackingHttpHandler.java @@ -18,6 +18,7 @@ import com.sun.net.httpserver.HttpExchange; +import javax.annotation.Nullable; import java.util.Collection; interface TrackingHttpHandler { @@ -28,9 +29,10 @@ interface TrackingHttpHandler { * * This method may block until the request is ready to be handled, but must do so using a condition created from the state lock. * - * @throws Exception on failure to handle request. The handler is considered broken. + * @return null when this handler is not expecting any further requests. */ - ResponseProducer selectResponseProducer(int id, HttpExchange exchange) throws Exception; + @Nullable + ResponseProducer selectResponseProducer(int id, HttpExchange exchange); /** * Returns a precondition that asserts that this handler is not expecting any further requests to be released by the test in order to complete. diff --git a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/server/http/UnexpectedRequestException.java b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/server/http/UnexpectedRequestException.java index b6c1bc911b916..ad2a0b6b83294 100644 --- a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/server/http/UnexpectedRequestException.java +++ b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/server/http/UnexpectedRequestException.java @@ -16,7 +16,7 @@ package org.gradle.test.fixtures.server.http; -public class UnexpectedRequestException extends AssertionError { +public class UnexpectedRequestException extends RuntimeException { public UnexpectedRequestException(String message) { super(message, null); } diff --git a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/server/http/UnexpectedRequestFailure.java b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/server/http/UnexpectedRequestFailure.java new file mode 100644 index 0000000000000..ad11c550d8bfd --- /dev/null +++ b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/server/http/UnexpectedRequestFailure.java @@ -0,0 +1,27 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.test.fixtures.server.http; + +class UnexpectedRequestFailure extends AbstractFailure { + public UnexpectedRequestFailure(String method, String path) { + this(method, path, ""); + } + + public UnexpectedRequestFailure(String method, String path, String context) { + super(new UnexpectedRequestException(String.format("Unexpected request %s %s received%s", method, withLeadingSlash(path), contextSuffix(context)))); + } +} diff --git a/subprojects/internal-integ-testing/src/test/groovy/org/gradle/test/fixtures/server/http/BlockingHttpServerTest.groovy b/subprojects/internal-integ-testing/src/test/groovy/org/gradle/test/fixtures/server/http/BlockingHttpServerTest.groovy index c079d7fb900b5..4cbef694ef4cb 100644 --- a/subprojects/internal-integ-testing/src/test/groovy/org/gradle/test/fixtures/server/http/BlockingHttpServerTest.groovy +++ b/subprojects/internal-integ-testing/src/test/groovy/org/gradle/test/fixtures/server/http/BlockingHttpServerTest.groovy @@ -555,7 +555,7 @@ class BlockingHttpServerTest extends ConcurrentSpec { then: def e = thrown(RuntimeException) e.message == 'Failed to handle all HTTP requests.' - e.causes.message.sort() == ['Did not receive expected requests. Waiting for [GET /b], received []'] + e.causes.message.sort() == ['Did not receive expected requests. Waiting for [GET /b], already received []'] } def "fails when request is received after serial expectations met"() { @@ -576,7 +576,7 @@ class BlockingHttpServerTest extends ConcurrentSpec { then: def e = thrown(RuntimeException) e.message == 'Failed to handle all HTTP requests.' - e.causes.message.sort() == ['Received unexpected request GET /a'] + e.causes.message.sort() == ['Unexpected request GET /a received'] } def "fails when request path does not match expected serial request"() { @@ -585,7 +585,14 @@ class BlockingHttpServerTest extends ConcurrentSpec { server.start() when: - server.uri("b").toURL().text + def connection = server.uri("b").toURL().openConnection() + + then: + connection.responseCode == 400 + connection.responseMessage == "Bad Request" + + when: + connection.inputStream then: thrown(IOException) @@ -597,9 +604,8 @@ class BlockingHttpServerTest extends ConcurrentSpec { def e = thrown(RuntimeException) e.message == 'Failed to handle all HTTP requests.' e.causes.message == [ - 'Failed to handle GET /b' + 'Unexpected request GET /b received. Waiting for [GET /a], already received []' ] - e.causes[0].cause.message == 'Unexpected request GET /b received. Waiting for [GET /a], already received [].' } def "fails when request method does not match expected serial GET request"() { @@ -610,7 +616,13 @@ class BlockingHttpServerTest extends ConcurrentSpec { when: def connection = server.uri("a").toURL().openConnection() connection.requestMethod = 'HEAD' - connection.inputStream.text + + then: + connection.responseCode == 400 + connection.responseMessage == "Bad Request" + + when: + connection.inputStream then: thrown(IOException) @@ -622,9 +634,8 @@ class BlockingHttpServerTest extends ConcurrentSpec { def e = thrown(RuntimeException) e.message == 'Failed to handle all HTTP requests.' e.causes.message == [ - 'Failed to handle HEAD /a' + 'Unexpected request HEAD /a received. Waiting for [GET /a], already received []' ] - e.causes[0].cause.message == 'Unexpected request HEAD /a received. Waiting for [GET /a], already received [].' } def "fails when request method does not match expected serial PUT request"() { @@ -645,9 +656,8 @@ class BlockingHttpServerTest extends ConcurrentSpec { def e = thrown(RuntimeException) e.message == 'Failed to handle all HTTP requests.' e.causes.message == [ - 'Failed to handle GET /a' + 'Unexpected request GET /a received. Waiting for [PUT /a], already received []' ] - e.causes[0].cause.message == 'Unexpected request GET /a received. Waiting for [PUT /a], already received [].' } def "fails when request method does not match expected serial POST request"() { @@ -668,9 +678,8 @@ class BlockingHttpServerTest extends ConcurrentSpec { def e = thrown(RuntimeException) e.message == 'Failed to handle all HTTP requests.' e.causes.message.sort() == [ - 'Failed to handle GET /a' + 'Unexpected request GET /a received. Waiting for [POST /a], already received []' ] - e.causes[0].cause.message == 'Unexpected request GET /a received. Waiting for [POST /a], already received [].' } def "fails when some but not all expected parallel requests received"() { @@ -691,9 +700,8 @@ class BlockingHttpServerTest extends ConcurrentSpec { def e = thrown(RuntimeException) e.message == 'Failed to handle all HTTP requests.' e.causes.message.sort() == [ - 'Failed to handle GET /a' + 'Failed to handle GET /a due to a timeout waiting for other requests. Waiting for [GET /b], already received [GET /a]' ] - e.causes[0].cause.message == 'Timeout waiting for expected requests to be received. Still waiting for [GET /b], received [GET /a].' } def "fails when expected parallel request received after other request has failed"() { @@ -720,12 +728,9 @@ class BlockingHttpServerTest extends ConcurrentSpec { def e = thrown(RuntimeException) e.message == 'Failed to handle all HTTP requests.' e.causes.message == [ - 'Failed to handle GET /a', - 'Failed to handle GET /b', + 'Failed to handle GET /a due to a timeout waiting for other requests. Waiting for [GET /b], already received [GET /a]', + 'Failed to handle GET /b due to a previous timeout. Waiting for [], already received [GET /a, GET /b]' ] - e.causes[0].cause.message == 'Timeout waiting for expected requests to be received. Still waiting for [GET /b], received [GET /a].' - // TODO - message should say that expected request was received too late - e.causes[1].cause.message == 'Timeout waiting for expected requests to be received. Still waiting for [GET /b], received [GET /a].' } def "fails when some but not all expected parallel requests received when stop called"() { @@ -747,7 +752,7 @@ class BlockingHttpServerTest extends ConcurrentSpec { def e = thrown(RuntimeException) e.message == 'Failed to handle all HTTP requests.' e.causes.message == [ - 'Did not receive expected requests. Waiting for [GET /b], received [GET /a]' + 'Did not receive expected requests. Waiting for [GET /b], already received [GET /a]' ] } @@ -769,21 +774,34 @@ class BlockingHttpServerTest extends ConcurrentSpec { def e = thrown(RuntimeException) e.message == 'Failed to handle all HTTP requests.' e.causes.message.sort() == [ - 'Failed to handle GET /c' + 'Unexpected request GET /c received. Waiting for [GET /a, GET /b], already received []' ] - e.causes[0].cause.message == 'Unexpected request GET /c received. Waiting for [GET /a, GET /b], already received [].' } def "fails when request path does not match expected blocking parallel request"() { + def requestFailure = null + given: - server.expectConcurrentAndBlock("a", "b") + def handle = server.expectConcurrentAndBlock("a", "b") server.start() when: - server.uri("c").toURL().text + async { + start { + try { + server.uri("c").toURL().text + } catch (IOException e) { + requestFailure = e + } + } + handle.waitForAllPendingCalls() + } then: - thrown(IOException) + def waitException = thrown(RuntimeException) + waitException.message == 'Unexpected request GET /c received. Waiting for 2 further requests, received [], released [], not yet received [GET /a, GET /b]' + + requestFailure instanceof IOException when: server.stop() @@ -792,9 +810,8 @@ class BlockingHttpServerTest extends ConcurrentSpec { def e = thrown(RuntimeException) e.message == 'Failed to handle all HTTP requests.' e.causes.message.sort() == [ - 'Failed to handle GET /c' + 'Unexpected request GET /c received. Waiting for 2 further requests, received [], released [], not yet received [GET /a, GET /b]' ] - e.causes[0].cause.message == 'Unexpected request GET /c received. Waiting for 2 further requests, already received [], released [], still expecting [GET /a, GET /b].' } def "fails when request method does not match expected parallel request"() { @@ -847,14 +864,10 @@ class BlockingHttpServerTest extends ConcurrentSpec { def e = thrown(RuntimeException) e.message == 'Failed to handle all HTTP requests.' e.causes.message == [ - 'Failed to handle HEAD /a', - 'Failed to handle GET /b', - 'Failed to handle GET /c' + 'Unexpected request HEAD /a received. Waiting for [GET /a, GET /b, PUT /c], already received []', + 'Failed to handle GET /b due to unexpected request HEAD /a. Waiting for [GET /a, PUT /c], already received [GET /b]', + 'Unexpected request GET /c received. Waiting for [GET /a, PUT /c], already received [GET /b]' ] - e.causes[0].cause.message == 'Unexpected request HEAD /a received. Waiting for [GET /a, GET /b, PUT /c], already received [].' - // TODO - message should indicate GET /b was received at the time the failure happened - e.causes[1].cause.message == 'Unexpected request HEAD /a received. Waiting for [GET /a, GET /b, PUT /c], already received [].' - e.causes[2].cause.message == 'Unexpected request GET /c received. Waiting for [GET /a, PUT /c], already received [GET /b].' } def "fails when request method does not match expected blocking parallel request"() { @@ -863,7 +876,7 @@ class BlockingHttpServerTest extends ConcurrentSpec { def failure3 = null given: - server.expectConcurrentAndBlock(server.get("a"), server.get("b"), server.put("c")) + def handle = server.expectConcurrentAndBlock(server.get("a"), server.get("b"), server.put("c")) server.start() when: @@ -893,9 +906,14 @@ class BlockingHttpServerTest extends ConcurrentSpec { failure3 = t } } + server.waitForRequests(3) + handle.waitForAllPendingCalls() } then: + def waitException = thrown(RuntimeException) + waitException.message == 'Unexpected request HEAD /a received. Waiting for 2 further requests, received [GET /b], released [], not yet received [GET /a, PUT /c]' + failure1 instanceof IOException failure2 instanceof IOException failure3 instanceof IOException @@ -907,15 +925,10 @@ class BlockingHttpServerTest extends ConcurrentSpec { def e = thrown(RuntimeException) e.message == 'Failed to handle all HTTP requests.' e.causes.message == [ - 'Failed to handle HEAD /a', - 'Failed to handle GET /b', - 'Failed to handle GET /c', + 'Unexpected request HEAD /a received. Waiting for 3 further requests, received [], released [], not yet received [GET /a, GET /b, PUT /c]', + 'Failed to handle GET /b due to unexpected request HEAD /a. Waiting for 2 further requests, received [GET /b], released [], not yet received [GET /a, PUT /c]', + 'Unexpected request GET /c received. Waiting for 2 further requests, received [GET /b], released [], not yet received [GET /a, PUT /c]', ] - e.causes[0].cause.message == 'Unexpected request HEAD /a received. Waiting for 3 further requests, already received [], released [], still expecting [GET /a, GET /b, PUT /c].' - // TODO - message should indicate GET /b was received at the time the failure happened - e.causes[1].cause.message == 'Unexpected request HEAD /a received. Waiting for 3 further requests, already received [], released [], still expecting [GET /a, GET /b, PUT /c].' - // TODO - message should indicate GET /b was received at the time the failure happened - e.causes[2].cause.message == 'Unexpected request GET /c received. Waiting for 2 further requests, already received [GET /b], released [], still expecting [GET /a, PUT /c].' } def "fails when additional requests are made after parallel expectations are met"() { @@ -939,8 +952,8 @@ class BlockingHttpServerTest extends ConcurrentSpec { then: def e = thrown(RuntimeException) e.message == 'Failed to handle all HTTP requests.' - e.cause.message == 'Received unexpected request GET /c' - e.causes.message.sort() == ['Received unexpected request GET /c'] + e.cause.message == 'Unexpected request GET /c received' + e.causes.message.sort() == ['Unexpected request GET /c received'] } def "fails when some but not all expected parallel requests received while waiting"() { @@ -963,8 +976,8 @@ class BlockingHttpServerTest extends ConcurrentSpec { } then: - def waitError = thrown(AssertionError) - waitError.message == 'Timeout waiting for expected requests. Waiting for 1 further requests, received [GET /a], released [], not yet received [GET /b, GET /c].' + def waitError = thrown(RuntimeException) + waitError.message == 'Timeout waiting for expected requests. Waiting for 1 further requests, received [GET /a], released [], not yet received [GET /b, GET /c]' requestFailure instanceof IOException @@ -975,9 +988,8 @@ class BlockingHttpServerTest extends ConcurrentSpec { def e = thrown(RuntimeException) e.message == 'Failed to handle all HTTP requests.' e.causes.message == [ - 'Failed to handle GET /a' + 'Failed to handle GET /a due to a timeout waiting for other requests. Waiting for 1 further requests, received [GET /a], released [], not yet received [GET /b, GET /c]' ] - e.causes[0].cause.message == 'Timeout waiting for expected requests. Waiting for 1 further requests, received [GET /a], released [], not yet received [GET /b, GET /c].' } def "fails when expected parallel request received after waiting has failed"() { @@ -1000,8 +1012,8 @@ class BlockingHttpServerTest extends ConcurrentSpec { } then: - def waitError = thrown(AssertionError) - waitError.message == 'Timeout waiting for expected requests. Waiting for 1 further requests, received [GET /a], released [], not yet received [GET /b, GET /c].' + def waitError = thrown(RuntimeException) + waitError.message == 'Timeout waiting for expected requests. Waiting for 1 further requests, received [GET /a], released [], not yet received [GET /b, GET /c]' requestFailure instanceof IOException @@ -1018,12 +1030,9 @@ class BlockingHttpServerTest extends ConcurrentSpec { def e = thrown(RuntimeException) e.message == 'Failed to handle all HTTP requests.' e.causes.message == [ - 'Failed to handle GET /a', - 'Failed to handle GET /b' + 'Failed to handle GET /a due to a timeout waiting for other requests. Waiting for 1 further requests, received [GET /a], released [], not yet received [GET /b, GET /c]', + 'Failed to handle GET /b due to a previous timeout. Waiting for 0 further requests, received [GET /a, GET /b], released [], not yet received [GET /c]' ] - e.causes[0].cause.message == 'Timeout waiting for expected requests. Waiting for 1 further requests, received [GET /a], released [], not yet received [GET /b, GET /c].' - // TODO - message should indicate that request received after timeout - e.causes[1].cause.message == 'Timeout waiting for expected requests. Waiting for 1 further requests, received [GET /a], released [], not yet received [GET /b, GET /c].' } def "fails when unexpected request received while other request is waiting "() { @@ -1058,11 +1067,9 @@ class BlockingHttpServerTest extends ConcurrentSpec { def e = thrown(RuntimeException) e.message == 'Failed to handle all HTTP requests.' e.causes.message == [ - 'Failed to handle GET /a', - 'Failed to handle GET /c' + 'Failed to handle GET /a due to unexpected request GET /c. Waiting for [GET /b], already received [GET /a]', + 'Unexpected request GET /c received. Waiting for [GET /b], already received [GET /a]' ] - e.causes[0].cause.message == 'Unexpected request GET /c received. Waiting for [GET /b], already received [GET /a].' - e.causes[1].cause.message == 'Unexpected request GET /c received. Waiting for [GET /b], already received [GET /a].' failure1 instanceof IOException failure2 instanceof IOException @@ -1097,8 +1104,8 @@ class BlockingHttpServerTest extends ConcurrentSpec { } then: - def waitError = thrown(AssertionError) - waitError.message == "Unexpected request GET /d received. Waiting for 1 further requests, already received [GET /a], released [], still expecting [GET /b, GET /c]." + def waitError = thrown(RuntimeException) + waitError.message == "Unexpected request GET /d received. Waiting for 1 further requests, received [GET /a], released [], not yet received [GET /b, GET /c]" failure1 instanceof IOException failure2 instanceof IOException @@ -1110,11 +1117,9 @@ class BlockingHttpServerTest extends ConcurrentSpec { def e = thrown(RuntimeException) e.message == 'Failed to handle all HTTP requests.' e.causes.message == [ - 'Failed to handle GET /a', - 'Failed to handle GET /d' + 'Failed to handle GET /a due to unexpected request GET /d. Waiting for 1 further requests, received [GET /a], released [], not yet received [GET /b, GET /c]', + 'Unexpected request GET /d received. Waiting for 1 further requests, received [GET /a], released [], not yet received [GET /b, GET /c]' ] - e.causes[0].cause.message == 'Unexpected request GET /d received. Waiting for 1 further requests, already received [GET /a], released [], still expecting [GET /b, GET /c].' - e.causes[1].cause.message == 'Unexpected request GET /d received. Waiting for 1 further requests, already received [GET /a], released [], still expecting [GET /b, GET /c].' } def "fails when too many concurrent requests received while waiting"() { @@ -1156,8 +1161,8 @@ class BlockingHttpServerTest extends ConcurrentSpec { } then: - def waitError = thrown(AssertionError) - waitError.message == "Unexpected request GET /c received. Waiting for 0 further requests, already received [GET /a, GET /b], released [], still expecting [GET /c]." + def waitError = thrown(RuntimeException) + waitError.message == "Unexpected request GET /c received. Waiting for 0 further requests, received [GET /a, GET /b], released [], not yet received [GET /c]" failure1 instanceof IOException failure2 instanceof IOException @@ -1169,15 +1174,11 @@ class BlockingHttpServerTest extends ConcurrentSpec { then: def e = thrown(RuntimeException) e.message == 'Failed to handle all HTTP requests.' + // TODO - message should indicate that /c was expected but there were too many concurrent requests e.causes.message.sort() == [ - 'Failed to handle GET /a', - 'Failed to handle GET /b', - 'Failed to handle GET /c', - ] - e.causes.cause.message.sort() == [ - "Unexpected request GET /c received. Waiting for 0 further requests, already received [GET /a, GET /b], released [], still expecting [GET /c].", - "Unexpected request GET /c received. Waiting for 0 further requests, already received [GET /a, GET /b], released [], still expecting [GET /c].", - "Unexpected request GET /c received. Waiting for 0 further requests, already received [GET /a, GET /b], released [], still expecting [GET /c]." + 'Failed to handle GET /a due to unexpected request GET /c. Waiting for 0 further requests, received [GET /a, GET /b], released [], not yet received [GET /c]', + 'Failed to handle GET /b due to unexpected request GET /c. Waiting for 0 further requests, received [GET /a, GET /b], released [], not yet received [GET /c]', + 'Unexpected request GET /c received. Waiting for 0 further requests, received [GET /a, GET /b], released [], not yet received [GET /c]', ] } @@ -1216,9 +1217,9 @@ class BlockingHttpServerTest extends ConcurrentSpec { def e4 = thrown(RuntimeException) e4.message == 'Failed to handle all HTTP requests.' e4.causes.message == [ - 'Did not handle all expected requests. Waiting for 2 further requests, received [], released [], not yet received [GET /a, GET /b].', - 'Did not handle all expected requests. Waiting for 2 further requests, received [], released [], not yet received [GET /c, GET /d].', - 'Did not receive expected requests. Waiting for [GET /e], received []' + 'Did not handle all expected requests. Waiting for 2 further requests, received [], released [], not yet received [GET /a, GET /b]', + 'Did not handle all expected requests. Waiting for 2 further requests, received [], released [], not yet received [GET /c, GET /d]', + 'Did not receive expected requests. Waiting for [GET /e], already received []' ] } @@ -1242,8 +1243,8 @@ class BlockingHttpServerTest extends ConcurrentSpec { def e2 = thrown(RuntimeException) e2.message == 'Failed to handle all HTTP requests.' e2.causes.message == [ - 'Did not handle all expected requests. Waiting for 2 further requests, received [], released [], not yet received [GET /a, GET /b].', - 'Did not handle all expected requests. Waiting for 2 further requests, received [], released [], not yet received [GET /c, GET /d].', + 'Did not handle all expected requests. Waiting for 2 further requests, received [], released [], not yet received [GET /a, GET /b]', + 'Did not handle all expected requests. Waiting for 2 further requests, received [], released [], not yet received [GET /c, GET /d]', ] } @@ -1287,11 +1288,9 @@ class BlockingHttpServerTest extends ConcurrentSpec { def e = thrown(RuntimeException) e.message == 'Failed to handle all HTTP requests.' e.causes.message == [ - 'Failed to handle GET /a', - 'Failed to handle GET /b' + 'Failed to handle GET /a due to a timeout waiting to be released. Waiting for 0 further requests, received [GET /a, GET /b], released [], not yet received [GET /c]', + 'Failed to handle GET /b due to a timeout waiting to be released. Waiting for 0 further requests, received [GET /a, GET /b], released [], not yet received [GET /c]' ] - e.causes[0].cause.message == 'Timeout waiting to be released. Waiting for 0 further requests, received [GET /a, GET /b], released [], not yet received [GET /c].' - e.causes[1].cause.message == 'Timeout waiting to be released. Waiting for 0 further requests, received [GET /a, GET /b], released [], not yet received [GET /c].' } def "fails when request is not released after sending partial response"() { @@ -1356,9 +1355,9 @@ class BlockingHttpServerTest extends ConcurrentSpec { def e3 = thrown(RuntimeException) e3.message == 'Failed to handle all HTTP requests.' e3.causes.message == [ - 'Did not receive expected requests. Waiting for [GET /a], received []', - 'Did not handle all expected requests. Waiting for 1 further requests, received [], released [], not yet received [GET /b].', - 'Did not receive expected requests. Waiting for [GET /c], received []' + 'Did not receive expected requests. Waiting for [GET /a], already received []', + 'Did not handle all expected requests. Waiting for 1 further requests, received [], released [], not yet received [GET /b]', + 'Did not receive expected requests. Waiting for [GET /c], already received []' ] } From d7addcc0e57d16d6038144ec8cad3fb0e5290d41 Mon Sep 17 00:00:00 2001 From: Gradleware Git Bot Date: Thu, 7 Mar 2019 02:38:50 +0100 Subject: [PATCH 359/853] Publish 5.3-20190307012429+0000 --- released-versions.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/released-versions.json b/released-versions.json index 69c6b2e856599..6b45a43480cb6 100644 --- a/released-versions.json +++ b/released-versions.json @@ -1,7 +1,7 @@ { "latestReleaseSnapshot": { - "version": "5.3-20190306010147+0000", - "buildTime": "20190306010147+0000" + "version": "5.3-20190307012429+0000", + "buildTime": "20190307012429+0000" }, "latestRc": { "version": "5.3-rc-1", From bbb1c3aa4dc0077897eaf92e8bb0ee7b6e322237 Mon Sep 17 00:00:00 2001 From: Bo Zhang Date: Thu, 7 Mar 2019 10:56:15 +0800 Subject: [PATCH 360/853] Improve AbstractConsoleBuildResultFunctionalTest patterns We saw a lot of flaky tests in this test class. This commit improves the patterns to reduce the flakiness. --- .../AbstractConsoleBuildResultFunctionalTest.groovy | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/taskgrouping/AbstractConsoleBuildResultFunctionalTest.groovy b/subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/taskgrouping/AbstractConsoleBuildResultFunctionalTest.groovy index f462af6a43beb..a3bdab91fc2ca 100644 --- a/subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/taskgrouping/AbstractConsoleBuildResultFunctionalTest.groovy +++ b/subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/taskgrouping/AbstractConsoleBuildResultFunctionalTest.groovy @@ -52,7 +52,7 @@ abstract class AbstractConsoleBuildResultFunctionalTest extends AbstractConsoleG then: result.assertRawOutputContains(successMessage) LogContent.of(result.output).removeAnsiChars().withNormalizedEol().matches """(?s).* -BUILD SUCCESSFUL in \\d+s\\n? +BUILD SUCCESSFUL in \\d+s\\n* 2 actionable tasks: 2 executed .*""" @@ -62,7 +62,7 @@ BUILD SUCCESSFUL in \\d+s\\n? then: result.assertRawOutputContains(successMessage) LogContent.of(result.output).removeAnsiChars().withNormalizedEol().matches """(?s).* -BUILD SUCCESSFUL in \\d+s\\n? +BUILD SUCCESSFUL in \\d+s\\n* 2 actionable tasks: 1 executed, 1 up-to-date .*""" } @@ -95,9 +95,8 @@ BUILD SUCCESSFUL in \\d+s\\n? succeeds('success') then: - LogContent.of(result.output).removeAnsiChars().withNormalizedEol().matches """(?s).*build finished - -BUILD SUCCESSFUL in \\d+s\\n? + LogContent.of(result.output).removeAnsiChars().withNormalizedEol().matches """(?s).*build finished\\n* +BUILD SUCCESSFUL in \\d+s\\n* 1 actionable task: 1 executed .*""" } @@ -124,7 +123,7 @@ BUILD SUCCESSFUL in \\d+s\\n? // Check that the failure text appears either stdout or stderr def outputWithFailure = errorsShouldAppearOnStdout() ? failure.output : failure.error def outputWithoutFailure = errorsShouldAppearOnStdout() ? failure.error : failure.output - def outputWithFailureAndNoDebugging = LogContent.of(outputWithFailure).removeBlankLines().removeAnsiChars().removeDebugPrefix().withNormalizedEol() + def outputWithFailureAndNoDebugging = LogContent.of(outputWithFailure).removeAnsiChars().removeDebugPrefix().removeBlankLines().withNormalizedEol() outputWithFailure.contains("Build failed with an exception.") outputWithFailureAndNoDebugging.contains(""" From 26412c69b5e6e71b76cd989de246ae56a6c7ab29 Mon Sep 17 00:00:00 2001 From: Adam Murdoch Date: Thu, 7 Mar 2019 10:06:13 +1100 Subject: [PATCH 361/853] Tweak diagnostic messages produced by `BlockingHttpServer`. --- .../gradle/test/fixtures/server/http/BlockingHttpServer.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/server/http/BlockingHttpServer.java b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/server/http/BlockingHttpServer.java index 11090c20e40db..f9c3de6935a37 100644 --- a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/server/http/BlockingHttpServer.java +++ b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/server/http/BlockingHttpServer.java @@ -96,7 +96,7 @@ public URI uri(String resource) { */ public String callFromBuild(String resource) { URI uri = uri(resource); - return "System.out.println(\"calling " + uri + "\"); try { new java.net.URL(\"" + uri + "\").openConnection().getContentLength(); } catch(Exception e) { throw new RuntimeException(e); }; System.out.println(\"[G] response received\");"; + return "System.out.println(\"[G] calling " + uri + "\"); try { new java.net.URL(\"" + uri + "\").openConnection().getContentLength(); } catch(Exception e) { throw new RuntimeException(e); }; System.out.println(\"[G] response received from " + uri + "\");"; } public String callFromTaskAction(String resource) { @@ -108,7 +108,7 @@ public String callFromTaskAction(String resource) { */ public String callFromBuildUsingExpression(String expression) { String uriExpression = "\"" + getUri() + "/\" + " + expression; - return "System.out.println(\"calling \" + " + uriExpression + "); try { new java.net.URL(" + uriExpression + ").openConnection().getContentLength(); } catch(Exception e) { throw new RuntimeException(e); }; System.out.println(\"[G] response received\");"; + return "System.out.println(\"[G] calling \" + " + uriExpression + "); try { new java.net.URL(" + uriExpression + ").openConnection().getContentLength(); } catch(Exception e) { throw new RuntimeException(e); }; System.out.println(\"[G] response received from \" + " + uriExpression + ");"; } /** From db42687381cf3507e1bfa044e3771808eb6024f7 Mon Sep 17 00:00:00 2001 From: Adam Murdoch Date: Thu, 7 Mar 2019 10:07:20 +1100 Subject: [PATCH 362/853] Rework test to use `BlockingHttpServer` for synchronization instead of some ad hoc mechanism. Add some trace to see what is happening during the two concurrent builds that the test starts. --- .../BuildSourceBuilderIntegrationTest.groovy | 121 +++++++++--------- 1 file changed, 61 insertions(+), 60 deletions(-) diff --git a/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/BuildSourceBuilderIntegrationTest.groovy b/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/BuildSourceBuilderIntegrationTest.groovy index 615613c94396e..ca923d26c0146 100644 --- a/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/BuildSourceBuilderIntegrationTest.groovy +++ b/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/BuildSourceBuilderIntegrationTest.groovy @@ -18,95 +18,96 @@ package org.gradle.integtests import org.gradle.integtests.fixtures.AbstractIntegrationSpec import org.gradle.integtests.fixtures.timeout.IntegrationTestTimeout +import org.gradle.internal.nativeintegration.ProcessEnvironment +import org.gradle.internal.operations.BuildOperationDescriptor +import org.gradle.internal.operations.BuildOperationListener +import org.gradle.internal.operations.BuildOperationListenerManager +import org.gradle.internal.operations.OperationFinishEvent +import org.gradle.internal.operations.OperationIdentifier +import org.gradle.internal.operations.OperationProgressEvent +import org.gradle.internal.operations.OperationStartEvent import org.gradle.test.fixtures.file.TestFile +import org.gradle.test.fixtures.server.http.BlockingHttpServer +import org.junit.Rule import spock.lang.Issue @IntegrationTestTimeout(600) class BuildSourceBuilderIntegrationTest extends AbstractIntegrationSpec { + @Rule + BlockingHttpServer server = new BlockingHttpServer() @Issue("https://issues.gradle.org/browse/GRADLE-2032") def "can simultaneously run gradle on projects with buildSrc"() { - given: - def buildSrcDir = file("buildSrc").createDir() - writeSharedClassFile(buildSrcDir) - file('buildSrc/build.gradle').text = ''' - tasks.all { - doFirst { - println "${name} started at ${new Date().time}" + def initScript = file("init.gradle") + initScript << """ + import ${BuildOperationListenerManager.name} + import ${BuildOperationListener.name} + import ${BuildOperationDescriptor.name} + import ${OperationStartEvent.name} + import ${OperationProgressEvent.name} + import ${OperationFinishEvent.name} + import ${OperationIdentifier.name} + import ${ProcessEnvironment.name} + + def pid = gradle.services.get(ProcessEnvironment).maybeGetPid() + + def listener = new TraceListener(pid: pid) + def manager = gradle.services.get(BuildOperationListenerManager) + manager.addListener(listener) + gradle.buildFinished { manager.removeListener(listener) } + + class TraceListener implements BuildOperationListener { + Long pid + + void started(BuildOperationDescriptor buildOperation, OperationStartEvent startEvent) { + println("[\$pid] start " + buildOperation.displayName) + } + + void progress(OperationIdentifier operationIdentifier, OperationProgressEvent progressEvent) { } - doLast { - println "${name} finished at ${new Date().time}" + + void finished(BuildOperationDescriptor buildOperation, OperationFinishEvent finishEvent) { } } - ''' + """ + server.start() + + given: + def buildSrcDir = file("buildSrc").createDir() + writeSharedClassFile(buildSrcDir) buildFile.text = """ import org.gradle.integtest.test.BuildSrcTask - int MAX_LOOP_COUNT = java.util.concurrent.TimeUnit.MINUTES.toMillis(5) / 10 - task blocking(type:BuildSrcTask) { + task build1(type:BuildSrcTask) { doLast { - file("run1washere.lock").createNewFile() - - int count = 0 - while(!file("run2washere.lock").exists() && count++ < MAX_LOOP_COUNT){ - sleep 10 - } + ${server.callFromBuild('build1')} } } - task releasing(type:BuildSrcTask) { + task build2(type:BuildSrcTask) { doLast { - int count = 0 - while(!file("run1washere.lock").exists() && count++ < MAX_LOOP_COUNT){ - sleep 10 - } - file("run2washere.lock").createNewFile() + ${server.callFromBuild('build2')} } } """ + + server.expectConcurrent("build1", "build2") + when: - def runBlockingHandle = executer.withTasks("blocking").start() - def runReleaseHandle = executer.withTasks("releasing").start() + def runBlockingHandle = executer.withTasks("build1").usingInitScript(initScript).start() + def runReleaseHandle = executer.withTasks("build2").usingInitScript(initScript).start() + and: def releaseResult = runReleaseHandle.waitForFinish() def blockingResult = runBlockingHandle.waitForFinish() - then: - blockingResult.assertTasksExecuted(":blocking") - releaseResult.assertTasksExecuted(":releasing") - - def blockingTaskTimes = finishedTaskTimes(blockingResult.output) - def releasingTaskTimes = finishedTaskTimes(releaseResult.output) - - def blockingBuildSrcBuiltFirst = blockingTaskTimes.values().min() < releasingTaskTimes.values().min() - def (firstBuildResult, secondBuildResult) = blockingBuildSrcBuiltFirst ? [blockingResult, releaseResult] : [releaseResult, blockingResult] - def lastTaskTimeFromFirstBuildSrcBuild = finishedTaskTimes(firstBuildResult.output).values().max() - def firstTaskTimeFromSecondBuildSrcBuild = startedTaskTimes(secondBuildResult.output).values().min() - - lastTaskTimeFromFirstBuildSrcBuild < firstTaskTimeFromSecondBuildSrcBuild + then: + blockingResult.assertTasksExecuted(":build1") + releaseResult.assertTasksExecuted(":build2") cleanup: - runReleaseHandle.abort() - runBlockingHandle.abort() - } - - Map startedTaskTimes(String output) { - taskTimes(output, 'started') - } - - Map finishedTaskTimes(String output) { - taskTimes(output, 'finished') - } - - Map taskTimes(String output, String state) { - output.readLines().collect { - it =~ /(.*) ${state} at (\d*)/ - }.findAll { - it.matches() - }.collectEntries { - def match = it[0] - [(match[1]): Long.parseLong(match[2])] - } + runReleaseHandle?.abort() + runBlockingHandle?.abort() } void writeSharedClassFile(TestFile targetDirectory) { From 945645a02d7777e634f44297c22cef2f12425864 Mon Sep 17 00:00:00 2001 From: Adam Murdoch Date: Thu, 7 Mar 2019 13:11:10 +1100 Subject: [PATCH 363/853] Attempt to avoid silent retries using `java.net.URL`. --- .../server/http/BlockingHttpServer.java | 31 +++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/server/http/BlockingHttpServer.java b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/server/http/BlockingHttpServer.java index f9c3de6935a37..776eeb4b4b920 100644 --- a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/server/http/BlockingHttpServer.java +++ b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/server/http/BlockingHttpServer.java @@ -27,6 +27,8 @@ import java.io.File; import java.io.IOException; +import java.io.PrintWriter; +import java.io.StringWriter; import java.net.InetSocketAddress; import java.net.URI; import java.net.URISyntaxException; @@ -54,6 +56,7 @@ public class BlockingHttpServer extends ExternalResource { private final int timeoutMs; private final int serverId; private boolean running; + private int clientVarCounter; public BlockingHttpServer() throws IOException { this(120000); @@ -96,7 +99,19 @@ public URI uri(String resource) { */ public String callFromBuild(String resource) { URI uri = uri(resource); - return "System.out.println(\"[G] calling " + uri + "\"); try { new java.net.URL(\"" + uri + "\").openConnection().getContentLength(); } catch(Exception e) { throw new RuntimeException(e); }; System.out.println(\"[G] response received from " + uri + "\");"; + String var = "connection" + (clientVarCounter++); + StringWriter result = new StringWriter(); + PrintWriter writer = new PrintWriter(result); + writer.println("System.out.println(\"[G] calling " + uri + "\");"); + writer.println("try {"); + writer.println(" java.net.URLConnection " + var + " = new java.net.URL(\"" + uri + "\").openConnection();"); + writer.println(" " + var + ".setReadTimeout(0);"); // to avoid silent retry + writer.println(" " + var + ".getContentLength();"); + writer.println("} catch(Exception e) {"); + writer.println(" throw new RuntimeException(e);"); + writer.println("}"); + writer.println("System.out.println(\"[G] response received for " + uri + "\");"); + return result.toString(); } public String callFromTaskAction(String resource) { @@ -108,7 +123,19 @@ public String callFromTaskAction(String resource) { */ public String callFromBuildUsingExpression(String expression) { String uriExpression = "\"" + getUri() + "/\" + " + expression; - return "System.out.println(\"[G] calling \" + " + uriExpression + "); try { new java.net.URL(" + uriExpression + ").openConnection().getContentLength(); } catch(Exception e) { throw new RuntimeException(e); }; System.out.println(\"[G] response received from \" + " + uriExpression + ");"; + String var = "connection" + (clientVarCounter++); + StringWriter result = new StringWriter(); + PrintWriter writer = new PrintWriter(result); + writer.println("System.out.println(\"[G] calling \" + " + uriExpression + ");"); + writer.println("try {"); + writer.println(" java.net.URLConnection " + var + " = new java.net.URL(" + uriExpression + ").openConnection();"); + writer.println(" " + var + ".setReadTimeout(0);"); // to avoid silent retry + writer.println(" " + var + ".getContentLength();"); + writer.println("} catch(Exception e) {"); + writer.println(" throw new RuntimeException(e);"); + writer.println("}"); + writer.println("System.out.println(\"[G] response received for \" + " + uriExpression + ");"); + return result.toString(); } /** From 4c7fa8cf5f478dad2e2eb2a67d866735a769b83f Mon Sep 17 00:00:00 2001 From: Bo Zhang Date: Thu, 7 Mar 2019 13:32:16 +0800 Subject: [PATCH 364/853] Fix issue of TeamCity recognizing OOM in build log We had some tests outputting OOM message, which will be recognized by TeamCity as build failure - even though these tests pass, TeamCity mark the whole build as failed. This commit fixes the issue by text replacement. --- .../daemon/DaemonPerformanceMonitoringSoakTest.groovy | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/subprojects/soak/src/integTest/groovy/org/gradle/launcher/daemon/DaemonPerformanceMonitoringSoakTest.groovy b/subprojects/soak/src/integTest/groovy/org/gradle/launcher/daemon/DaemonPerformanceMonitoringSoakTest.groovy index 3edc6149b11af..b97d73cfd5d5c 100644 --- a/subprojects/soak/src/integTest/groovy/org/gradle/launcher/daemon/DaemonPerformanceMonitoringSoakTest.groovy +++ b/subprojects/soak/src/integTest/groovy/org/gradle/launcher/daemon/DaemonPerformanceMonitoringSoakTest.groovy @@ -224,12 +224,8 @@ class DaemonPerformanceMonitoringSoakTest extends DaemonMultiJdkIntegrationTest println "Build: " + State.x } catch(OutOfMemoryError e) { - if (e.message == "GC overhead limit exceeded") { - // TeamCity recognizes this message as build failures if it occurs in build log - throw new OutOfMemoryError("GC_overhead_limit_exceeded") - } else { - throw e - } + // TeamCity recognizes this message as build failures if it occurs in build log + throw new OutOfMemoryError(e?.message?.replace(' ', '_')) } """ } From e85504fafdf409a05fadab937b911a933c58ef87 Mon Sep 17 00:00:00 2001 From: Jonathan Leitschuh Date: Thu, 7 Mar 2019 01:09:57 -0800 Subject: [PATCH 365/853] Update subprojects/docs/src/docs/userguide/java_library_plugin.adoc Signed-off-by: James X. Nelson --- subprojects/docs/src/docs/userguide/java_library_plugin.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subprojects/docs/src/docs/userguide/java_library_plugin.adoc b/subprojects/docs/src/docs/userguide/java_library_plugin.adoc index 28971172240bd..b30c21e152ad7 100644 --- a/subprojects/docs/src/docs/userguide/java_library_plugin.adoc +++ b/subprojects/docs/src/docs/userguide/java_library_plugin.adoc @@ -237,7 +237,7 @@ The role of each configuration is described in the following tables: [[sec:java_library_known_issues_compat]] === Compatibility with other plugins -At the moment, the Java Library plugin is wired to behave correctly with the `java`, `groovy` and `kotlin` plugins. In Gradle 5.3 or early, some plugins, such as the Groovy plugin, may not behave correctly. In particular, if the Groovy plugin is used in addition to the `java-library` plugin, then consumers may not get the Groovy classes when they consume the library. To workaround this, you need to explicitly wire the Groovy compile dependency, like this: +At the moment, the Java Library plugin is wired to behave correctly with the `java`, `groovy` and `kotlin` plugins. In Gradle 5.3 or earlier, some plugins, such as the Groovy plugin, may not behave correctly. In particular, if the Groovy plugin is used in addition to the `java-library` plugin, then consumers may not get the Groovy classes when they consume the library. To workaround this, you need to explicitly wire the Groovy compile dependency, like this: .Configuring the Groovy plugin to work with Java Library in Gradle 5.3 or earlier ==== From 397875a6978bdf5a0307a0b0b9db78365806fe2d Mon Sep 17 00:00:00 2001 From: Jenn Strater Date: Thu, 7 Mar 2019 11:00:55 +0100 Subject: [PATCH 366/853] Update subprojects/docs/src/docs/userguide/migrating_from_maven.adoc --- subprojects/docs/src/docs/userguide/migrating_from_maven.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subprojects/docs/src/docs/userguide/migrating_from_maven.adoc b/subprojects/docs/src/docs/userguide/migrating_from_maven.adoc index c0c42612ce0f1..ea1f3060ed274 100644 --- a/subprojects/docs/src/docs/userguide/migrating_from_maven.adoc +++ b/subprojects/docs/src/docs/userguide/migrating_from_maven.adoc @@ -45,7 +45,7 @@ TIP: Keep the old Maven build and new Gradle build side by side. You know the Maven build works, so you should keep it until you are confident that the Gradle build produces all the same artifacts and otherwise does what you need. This also means that users can try the Gradle build without getting a new copy of the source tree. - . link:https://scans.gradle.com[Create a build scan for the Maven build]. + . link:https://scans.gradle.com#maven[Create a build scan for the Maven build]. + A build scan will make it easier to visualize what's happening in your existing Maven build. For Maven builds, you'll be able to see the project structure, what plugins are being used, a timeline of the build steps, and more. From 1a09db3ea4f38b243d1ca28cbf02007f13116956 Mon Sep 17 00:00:00 2001 From: wolf Date: Thu, 7 Mar 2019 12:02:24 +0000 Subject: [PATCH 367/853] TeamCity change in 'Gradle / Promotion' project: parameters of 'Publish Branch Snapshot (from Quick Feedback)' build configuration were updated --- .../Gradle_Promotion_PublishBranchSnapshotFromQuickFeedback.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/.teamcity/Gradle_Promotion/buildTypes/Gradle_Promotion_PublishBranchSnapshotFromQuickFeedback.xml b/.teamcity/Gradle_Promotion/buildTypes/Gradle_Promotion_PublishBranchSnapshotFromQuickFeedback.xml index d5fca066fc333..24ab2922df1e8 100644 --- a/.teamcity/Gradle_Promotion/buildTypes/Gradle_Promotion_PublishBranchSnapshotFromQuickFeedback.xml +++ b/.teamcity/Gradle_Promotion/buildTypes/Gradle_Promotion_PublishBranchSnapshotFromQuickFeedback.xml @@ -9,6 +9,7 @@ + From b99d6ce672f327ae6eda01dea318d85434fb5d8c Mon Sep 17 00:00:00 2001 From: wolf Date: Thu, 7 Mar 2019 12:02:59 +0000 Subject: [PATCH 368/853] TeamCity change in 'Gradle / Promotion' project: artifact dependencies of 'Publish Branch Snapshot (from Quick Feedback)' build configuration were updated --- .../Gradle_Promotion_PublishBranchSnapshotFromQuickFeedback.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.teamcity/Gradle_Promotion/buildTypes/Gradle_Promotion_PublishBranchSnapshotFromQuickFeedback.xml b/.teamcity/Gradle_Promotion/buildTypes/Gradle_Promotion_PublishBranchSnapshotFromQuickFeedback.xml index 24ab2922df1e8..7811400240714 100644 --- a/.teamcity/Gradle_Promotion/buildTypes/Gradle_Promotion_PublishBranchSnapshotFromQuickFeedback.xml +++ b/.teamcity/Gradle_Promotion/buildTypes/Gradle_Promotion_PublishBranchSnapshotFromQuickFeedback.xml @@ -33,7 +33,7 @@ - + From c211f22395b4eba74485b10313ee4bf167ac28e0 Mon Sep 17 00:00:00 2001 From: wolf Date: Thu, 7 Mar 2019 12:06:41 +0000 Subject: [PATCH 369/853] TeamCity change in 'Gradle / Promotion' project: parameters of 'Publish Branch Snapshot (from Quick Feedback)' build configuration were updated --- .../Gradle_Promotion_PublishBranchSnapshotFromQuickFeedback.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/.teamcity/Gradle_Promotion/buildTypes/Gradle_Promotion_PublishBranchSnapshotFromQuickFeedback.xml b/.teamcity/Gradle_Promotion/buildTypes/Gradle_Promotion_PublishBranchSnapshotFromQuickFeedback.xml index 7811400240714..4f320036844df 100644 --- a/.teamcity/Gradle_Promotion/buildTypes/Gradle_Promotion_PublishBranchSnapshotFromQuickFeedback.xml +++ b/.teamcity/Gradle_Promotion/buildTypes/Gradle_Promotion_PublishBranchSnapshotFromQuickFeedback.xml @@ -10,6 +10,7 @@ + From 8e3cb35965e549ac15a1714dd4582d9a9ada1354 Mon Sep 17 00:00:00 2001 From: wolf Date: Thu, 7 Mar 2019 12:08:09 +0000 Subject: [PATCH 370/853] TeamCity change in 'Gradle / Promotion' project: parameters of 'Publish Branch Snapshot (from Quick Feedback)' build configuration were updated --- .../Gradle_Promotion_PublishBranchSnapshotFromQuickFeedback.xml | 1 - 1 file changed, 1 deletion(-) diff --git a/.teamcity/Gradle_Promotion/buildTypes/Gradle_Promotion_PublishBranchSnapshotFromQuickFeedback.xml b/.teamcity/Gradle_Promotion/buildTypes/Gradle_Promotion_PublishBranchSnapshotFromQuickFeedback.xml index 4f320036844df..7811400240714 100644 --- a/.teamcity/Gradle_Promotion/buildTypes/Gradle_Promotion_PublishBranchSnapshotFromQuickFeedback.xml +++ b/.teamcity/Gradle_Promotion/buildTypes/Gradle_Promotion_PublishBranchSnapshotFromQuickFeedback.xml @@ -10,7 +10,6 @@ - From 30d0d539540d94dc0d7f63c4d7ed3f1697841630 Mon Sep 17 00:00:00 2001 From: wolf Date: Thu, 7 Mar 2019 12:08:48 +0000 Subject: [PATCH 371/853] TeamCity change in 'Gradle / Promotion' project: parameters of 'Publish Branch Snapshot (from Quick Feedback)' build configuration were updated --- .../Gradle_Promotion_PublishBranchSnapshotFromQuickFeedback.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.teamcity/Gradle_Promotion/buildTypes/Gradle_Promotion_PublishBranchSnapshotFromQuickFeedback.xml b/.teamcity/Gradle_Promotion/buildTypes/Gradle_Promotion_PublishBranchSnapshotFromQuickFeedback.xml index 7811400240714..db75031a2935b 100644 --- a/.teamcity/Gradle_Promotion/buildTypes/Gradle_Promotion_PublishBranchSnapshotFromQuickFeedback.xml +++ b/.teamcity/Gradle_Promotion/buildTypes/Gradle_Promotion_PublishBranchSnapshotFromQuickFeedback.xml @@ -9,7 +9,7 @@ - + From 4ae91ec498340abd4c059dadd793d8a45adf2357 Mon Sep 17 00:00:00 2001 From: wolf Date: Thu, 7 Mar 2019 12:11:01 +0000 Subject: [PATCH 372/853] TeamCity change in 'Gradle / Promotion' project: parameters of 'Publish Branch Snapshot (from Quick Feedback)' build configuration were updated --- .../Gradle_Promotion_PublishBranchSnapshotFromQuickFeedback.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.teamcity/Gradle_Promotion/buildTypes/Gradle_Promotion_PublishBranchSnapshotFromQuickFeedback.xml b/.teamcity/Gradle_Promotion/buildTypes/Gradle_Promotion_PublishBranchSnapshotFromQuickFeedback.xml index db75031a2935b..ebc7ec242e339 100644 --- a/.teamcity/Gradle_Promotion/buildTypes/Gradle_Promotion_PublishBranchSnapshotFromQuickFeedback.xml +++ b/.teamcity/Gradle_Promotion/buildTypes/Gradle_Promotion_PublishBranchSnapshotFromQuickFeedback.xml @@ -9,7 +9,7 @@ - + From b70bca6684904d0d17724c0cc8412e332ce581fa Mon Sep 17 00:00:00 2001 From: Daniel Lacasse Date: Thu, 7 Mar 2019 08:34:51 -0500 Subject: [PATCH 373/853] Remove `CorruptedTaskHistoryIntegrationTest` The usefulness of this test has become irrelevant. The test is flaky, and hardly test anything given the task history writing is now atomic. --- ...CorruptedTaskHistoryIntegrationTest.groovy | 154 ------------------ 1 file changed, 154 deletions(-) delete mode 100644 subprojects/core/src/integTest/groovy/org/gradle/api/internal/changedetection/CorruptedTaskHistoryIntegrationTest.groovy diff --git a/subprojects/core/src/integTest/groovy/org/gradle/api/internal/changedetection/CorruptedTaskHistoryIntegrationTest.groovy b/subprojects/core/src/integTest/groovy/org/gradle/api/internal/changedetection/CorruptedTaskHistoryIntegrationTest.groovy deleted file mode 100644 index f0ebb6d8e89d2..0000000000000 --- a/subprojects/core/src/integTest/groovy/org/gradle/api/internal/changedetection/CorruptedTaskHistoryIntegrationTest.groovy +++ /dev/null @@ -1,154 +0,0 @@ -/* - * Copyright 2017 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.gradle.api.internal.changedetection - -import org.gradle.integtests.fixtures.AbstractIntegrationSpec -import spock.lang.Issue - -class CorruptedTaskHistoryIntegrationTest extends AbstractIntegrationSpec { - - // If this test starts to be flaky it points to a problem in the code! - // See the linked issue. - @Issue("https://github.com/gradle/gradle/issues/2827") - def "broken build doesn't corrupt the artifact history"() { - def numberOfFiles = 10 - def numberOfOutputFilesPerTask = numberOfFiles - def numberOfInputProperties = 10 - def numberOfTasks = 100 - def totalNumberOfOutputDirectories = numberOfTasks - def killPollInterval = 10 - def totalNumberOfOutputFiles = numberOfTasks * numberOfOutputFilesPerTask + totalNumberOfOutputDirectories - - setupTestProject(numberOfFiles, numberOfInputProperties, numberOfTasks, killPollInterval) - - executer.beforeExecute { - // We need a separate JVM in order not to kill the test JVM - requireGradleDistribution() - } - - when: - succeeds("createFiles") - succeeds("clean") - fails("createFiles", "-PkillMe=true", "--max-workers=${numberOfTasks}") - def createdFiles = file('build').allDescendants().size() as BigDecimal - println "\nNumber of created files when the process has been killed: ${createdFiles}" - - then: - createdFiles in ((0.1 * totalNumberOfOutputFiles)..(0.9 * totalNumberOfOutputFiles)) - - expect: - succeeds "createFiles" - } - - /** - * Setup the test project.
    - * - * The test project is setup in a way that the Gradle build can be killed while it is writing to the task history repository, possibly corrupting it.
    - * - * We create {@code numberOfTasks} tasks, called {@code createFiles${number}}. - * Each of those tasks has {@code numberOfInputProperties} directory inputs, each one of them pointing to the input directory {@code 'inputs'}. - * The {@code 'inputs'} directory contains {@code numberOfFiles}. - * The {@code createFiles${number}} tasks create {@code numberOfFiles} files into the output directory {@code 'build/output${number}'} by using the worker API. So the task actions execute in parallel. - * If the Gradle property {@code 'killMe'} is set to some truthy value, we start a {@link Thread} which checks every {@code killPollInterval} ms if there are more than 40 output directories in 'build` and kills the Gradle process if there are. - * Finally, there is one task depending on all the tasks which are creating files. This one is just called {@code createFiles}. - */ - private void setupTestProject(int numberOfFiles, int numberOfInputProperties, int numberOfTasks, int killPollInterval) { - buildFile << """ -import org.gradle.api.DefaultTask -import org.gradle.api.tasks.InputDirectory -import org.gradle.api.tasks.OutputDirectory -import org.gradle.workers.IsolationMode -import org.gradle.workers.WorkerExecutor - -import javax.inject.Inject - -class CreateFiles implements Runnable { - - private final File outputDir - - @Inject - CreateFiles(File outputDir) { - this.outputDir=outputDir - } - - @Override - void run() { - (1..$numberOfFiles).each { - new File(outputDir, "\${it}.txt").text = "output\${it}" - } - } -} - -class CreateFilesTask extends DefaultTask { - private final WorkerExecutor workerExecutor - - @Inject - CreateFilesTask(WorkerExecutor workerExecutor) { - this.workerExecutor=workerExecutor - } - - ${(1..numberOfInputProperties).collect { inputProperty(it) }.join("\n")} - - @OutputDirectory - File outputDir - - @TaskAction - void createFiles() { - workerExecutor.submit(CreateFiles) { - isolationMode = IsolationMode.NONE - params(outputDir) - } - } -} - -apply plugin: 'base' - -task createFiles - -(1..$numberOfTasks).each { num -> - createFiles.dependsOn(tasks.create("createFiles\${num}", CreateFilesTask) { - ${(1..numberOfInputProperties).collect { "inputDir$it = file('inputs')" }.join("\n")} - outputDir = file("build/output\${num}") - }) -} - -if (project.findProperty("killMe")) { - new Thread({ - while (true) { - Thread.sleep(${killPollInterval}) - if (buildDir.exists() && buildDir.listFiles().size() > 20) { - System.exit(1) - } - } - }).start() -} - """ - - file('inputs').create { - (1..numberOfFiles).each { - file("input${it}.txt").text = "input${it}" - } - } - } - - private static String inputProperty(Integer postfix) { - """ - @InputDirectory - File inputDir${postfix} - """ - } -} From 1ce437f4ee8a090000185627e635f7a62da61046 Mon Sep 17 00:00:00 2001 From: Cedric Champeau Date: Wed, 6 Mar 2019 10:55:21 +0100 Subject: [PATCH 374/853] Improve section around feature variants --- subprojects/docs/src/docs/release/notes.md | 27 +++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/subprojects/docs/src/docs/release/notes.md b/subprojects/docs/src/docs/release/notes.md index 9951fa2231d7b..daee730518885 100644 --- a/subprojects/docs/src/docs/release/notes.md +++ b/subprojects/docs/src/docs/release/notes.md @@ -25,9 +25,29 @@ Switch your build to use Gradle 5.3 RC1 by updating your wrapper properties: Standalone downloads are available at [gradle.org/release-candidate](https://gradle.org/release-candidate). -## Feature variants aka optional dependencies +## Feature variants (or optional dependencies) -Gradle now provides a powerful model for declaring features a library provides, known as [feature variants](userguide/feature_variants.html): +Often a library needs to tell that some dependencies are only required if you use a specific feature of the library. +For example, you should only get the `mysql` dependencies if you actually plan to use MySQL. +Gradle now provides a powerful model for declaring those features a library provides, known as [feature variants](userguide/feature_variants.html): + +A consumer which depends on this specific feature (MySQL) of your library would then just have to tell that it needs it: + +```groovy +dependencies { + // At compile time, we need the library + implementation('org.gradle.demo:my-lib:1.0') + + runtimeOnly('org.gradle.demo:my-lib:1.0') { + capabilities { + // at runtime, we need the "MySQL" capability of this library + requireCapability("org.gradle.demo:producer-mysql-support") + } + } +} +``` + +The library author can therefore model dependencies in "groups" that correspond to a feature: ```groovy java { @@ -42,7 +62,8 @@ dependencies { } ``` -Long story short, this can be used to model [optional dependencies](https://github.com/gradle/gradle/issues/867)! +Long story short, this can be used to model the long requested [optional dependencies](https://github.com/gradle/gradle/issues/867)! +In practice, there are no optional dependencies: only dependencies that are _required_ if you use some features of a library. ## Kotlin DSL From 92c658e2de6047427c4fa7d329192adf4b3605ea Mon Sep 17 00:00:00 2001 From: Cedric Champeau Date: Wed, 6 Mar 2019 10:57:26 +0100 Subject: [PATCH 375/853] Polish Gradle Module Metadata section --- subprojects/docs/src/docs/release/notes.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/subprojects/docs/src/docs/release/notes.md b/subprojects/docs/src/docs/release/notes.md index daee730518885..9f76429bef2ca 100644 --- a/subprojects/docs/src/docs/release/notes.md +++ b/subprojects/docs/src/docs/release/notes.md @@ -155,6 +155,9 @@ Refer to the [`SoftwareComponentFactory` documentation](javadoc/org/gradle/api/c Gradle Module Metadata is now 1.0. +Gradle Module Metadata was created to solve many of the problems that have plagued dependency management for years, in particular, but not exclusively, in the Java ecosystem. +You can read more about Gradle Module Metadata in this [blog post](https://blog.gradle.org/gradle-metadata-1.0). + Gradle will automatically consume published Gradle Metadata, but to publish Gradle Metadata requires you to enable the `GRADLE_METADATA` feature preview. ### Factory method for creating `ConfigurableFileCollection` instances using `ObjectFactory` From a329a1750484cede3cb1d0d4f6d8ed4daeadc2a4 Mon Sep 17 00:00:00 2001 From: Cedric Champeau Date: Wed, 6 Mar 2019 11:26:48 +0100 Subject: [PATCH 376/853] Further polish the feature variants section --- subprojects/docs/src/docs/release/notes.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/subprojects/docs/src/docs/release/notes.md b/subprojects/docs/src/docs/release/notes.md index 9f76429bef2ca..04d89221d420e 100644 --- a/subprojects/docs/src/docs/release/notes.md +++ b/subprojects/docs/src/docs/release/notes.md @@ -25,9 +25,10 @@ Switch your build to use Gradle 5.3 RC1 by updating your wrapper properties: Standalone downloads are available at [gradle.org/release-candidate](https://gradle.org/release-candidate). -## Feature variants (or optional dependencies) +## Feature variants (similar to optional dependencies in Maven) -Often a library needs to tell that some dependencies are only required if you use a specific feature of the library. +Often a library needs to express that some dependencies are only required if you use a specific feature of the library. +Those dependencies must not be there _unless_ you use that feature and therefore are often flagged as "optional" in Maven. For example, you should only get the `mysql` dependencies if you actually plan to use MySQL. Gradle now provides a powerful model for declaring those features a library provides, known as [feature variants](userguide/feature_variants.html): From e0f2335c017bc1fce9f834662b3b9aace3f8b234 Mon Sep 17 00:00:00 2001 From: Cedric Champeau Date: Wed, 6 Mar 2019 21:48:52 +0100 Subject: [PATCH 377/853] Fix inner link to feature variants --- subprojects/docs/src/docs/release/notes.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/subprojects/docs/src/docs/release/notes.md b/subprojects/docs/src/docs/release/notes.md index 04d89221d420e..1e1fcf38ee32d 100644 --- a/subprojects/docs/src/docs/release/notes.md +++ b/subprojects/docs/src/docs/release/notes.md @@ -1,7 +1,7 @@ The Gradle team is excited to announce Gradle 5.3. This release features incubating support for publishing and consuming Gradle Module Metadata, -[feature variants AKA "optional dependencies"](#feature-variants-aka-optional-dependencies), +[feature variants or "optional dependencies"](#feature-variants), [type-safe accessors in Kotlin pre-compiled script plugins](#type-safe-accessors-in-precompiled-script-plugins), and more. We would like to thank the following community contributors to this release of Gradle: @@ -25,6 +25,8 @@ Switch your build to use Gradle 5.3 RC1 by updating your wrapper properties: Standalone downloads are available at [gradle.org/release-candidate](https://gradle.org/release-candidate). + + ## Feature variants (similar to optional dependencies in Maven) Often a library needs to express that some dependencies are only required if you use a specific feature of the library. From 3c2ed5d1d91bfcd03d70f497ff7b26bb347b13b6 Mon Sep 17 00:00:00 2001 From: Cedric Champeau Date: Wed, 6 Mar 2019 21:49:29 +0100 Subject: [PATCH 378/853] Minor tweak to notes. --- subprojects/docs/src/docs/release/notes.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subprojects/docs/src/docs/release/notes.md b/subprojects/docs/src/docs/release/notes.md index 1e1fcf38ee32d..ed7a7c2d8f25e 100644 --- a/subprojects/docs/src/docs/release/notes.md +++ b/subprojects/docs/src/docs/release/notes.md @@ -32,7 +32,7 @@ Standalone downloads are available at [gradle.org/release-candidate](https://gra Often a library needs to express that some dependencies are only required if you use a specific feature of the library. Those dependencies must not be there _unless_ you use that feature and therefore are often flagged as "optional" in Maven. For example, you should only get the `mysql` dependencies if you actually plan to use MySQL. -Gradle now provides a powerful model for declaring those features a library provides, known as [feature variants](userguide/feature_variants.html): +Gradle now provides a powerful model for declaring those features a library provides, known as [feature variants](userguide/feature_variants.html). A consumer which depends on this specific feature (MySQL) of your library would then just have to tell that it needs it: From 189e991794fb40a11a96044d0d23a8cfadce8d16 Mon Sep 17 00:00:00 2001 From: Cedric Champeau Date: Thu, 7 Mar 2019 14:00:09 +0100 Subject: [PATCH 379/853] Rework preamble/highlights --- subprojects/docs/src/docs/release/notes.md | 2 +- subprojects/docs/src/docs/release/release-features.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/subprojects/docs/src/docs/release/notes.md b/subprojects/docs/src/docs/release/notes.md index ed7a7c2d8f25e..6a8d833cced64 100644 --- a/subprojects/docs/src/docs/release/notes.md +++ b/subprojects/docs/src/docs/release/notes.md @@ -1,6 +1,6 @@ The Gradle team is excited to announce Gradle 5.3. -This release features incubating support for publishing and consuming Gradle Module Metadata, +This release features support for publishing and consuming Gradle Module Metadata, [feature variants or "optional dependencies"](#feature-variants), [type-safe accessors in Kotlin pre-compiled script plugins](#type-safe-accessors-in-precompiled-script-plugins), and more. diff --git a/subprojects/docs/src/docs/release/release-features.txt b/subprojects/docs/src/docs/release/release-features.txt index 8a0bf424f9431..6f466d0b4d7cb 100644 --- a/subprojects/docs/src/docs/release/release-features.txt +++ b/subprojects/docs/src/docs/release/release-features.txt @@ -1,3 +1,3 @@ - - Incubating support for Gradle Module Metadata - Feature variants AKA "optional dependencies" - Type-safe accessors in Kotlin pre-compiled script plugins + - Gradle Module Metadata 1.0 From 6e4347834b37d9ba3062911e120354ce26438922 Mon Sep 17 00:00:00 2001 From: wolf Date: Thu, 7 Mar 2019 15:24:43 +0000 Subject: [PATCH 380/853] TeamCity change in 'Gradle / Promotion' project: Versioned settings configuration updated --- .teamcity/Gradle_Promotion/Project.kt | 56 +++++++++++++++++ ...motion_AllBranchesStartReleaseCycleTest.kt | 44 ++++++++++++++ ...otion_AllBranchesStartReleaseCycleTest.xml | 57 ------------------ .../Gradle_Promotion_FinalRelease.kt | 52 ++++++++++++++++ .../Gradle_Promotion_FinalRelease.xml | 44 -------------- ...e_Promotion_MasterNightlySnapshotManual.kt | 47 +++++++++++++++ ..._Promotion_MasterNightlySnapshotManual.xml | 42 ------------- .../Gradle_Promotion_MasterSanityCheck.kt | 39 ++++++++++++ .../Gradle_Promotion_MasterSanityCheck.xml | 45 -------------- .../Gradle_Promotion_MilestoneMaster.kt | 52 ++++++++++++++++ .../Gradle_Promotion_MilestoneMaster.xml | 45 -------------- ..._PublishBranchSnapshotFromQuickFeedback.kt | 51 ++++++++++++++++ ...PublishBranchSnapshotFromQuickFeedback.xml | 43 ------------- ...motion_ReleaseSnapshotFromQuickFeedback.kt | 46 ++++++++++++++ ...otion_ReleaseSnapshotFromQuickFeedback.xml | 40 ------------- .../Gradle_Promotion_StartReleaseCycle.kt | 49 +++++++++++++++ .../Gradle_Promotion_StartReleaseCycle.xml | 45 -------------- .teamcity/Gradle_Promotion/buildTypes/bt39.kt | 60 +++++++++++++++++++ .../Gradle_Promotion/buildTypes/bt39.xml | 59 ------------------ .teamcity/Gradle_Promotion/buildTypes/bt60.kt | 52 ++++++++++++++++ .../Gradle_Promotion/buildTypes/bt60.xml | 44 -------------- .teamcity/Gradle_Promotion/buildTypes/bt61.kt | 58 ++++++++++++++++++ .../Gradle_Promotion/buildTypes/bt61.xml | 59 ------------------ .../pluginData/plugin-settings.xml | 12 ++-- .teamcity/Gradle_Promotion/project-config.xml | 30 ---------- .teamcity/Gradle_Promotion/settings.kts | 35 +++++++++++ ...radle_Promotion_GradlePromotionBranches.kt | 17 ++++++ ...adle_Promotion_GradlePromotionBranches.xml | 17 ------ .../vcsRoots/Gradle_Promotion__master_.kt | 17 ++++++ .../vcsRoots/Gradle_Promotion__master_.xml | 16 ----- 30 files changed, 681 insertions(+), 592 deletions(-) create mode 100644 .teamcity/Gradle_Promotion/Project.kt create mode 100644 .teamcity/Gradle_Promotion/buildTypes/Gradle_Promotion_AllBranchesStartReleaseCycleTest.kt delete mode 100644 .teamcity/Gradle_Promotion/buildTypes/Gradle_Promotion_AllBranchesStartReleaseCycleTest.xml create mode 100644 .teamcity/Gradle_Promotion/buildTypes/Gradle_Promotion_FinalRelease.kt delete mode 100644 .teamcity/Gradle_Promotion/buildTypes/Gradle_Promotion_FinalRelease.xml create mode 100644 .teamcity/Gradle_Promotion/buildTypes/Gradle_Promotion_MasterNightlySnapshotManual.kt delete mode 100644 .teamcity/Gradle_Promotion/buildTypes/Gradle_Promotion_MasterNightlySnapshotManual.xml create mode 100644 .teamcity/Gradle_Promotion/buildTypes/Gradle_Promotion_MasterSanityCheck.kt delete mode 100644 .teamcity/Gradle_Promotion/buildTypes/Gradle_Promotion_MasterSanityCheck.xml create mode 100644 .teamcity/Gradle_Promotion/buildTypes/Gradle_Promotion_MilestoneMaster.kt delete mode 100644 .teamcity/Gradle_Promotion/buildTypes/Gradle_Promotion_MilestoneMaster.xml create mode 100644 .teamcity/Gradle_Promotion/buildTypes/Gradle_Promotion_PublishBranchSnapshotFromQuickFeedback.kt delete mode 100644 .teamcity/Gradle_Promotion/buildTypes/Gradle_Promotion_PublishBranchSnapshotFromQuickFeedback.xml create mode 100644 .teamcity/Gradle_Promotion/buildTypes/Gradle_Promotion_ReleaseSnapshotFromQuickFeedback.kt delete mode 100644 .teamcity/Gradle_Promotion/buildTypes/Gradle_Promotion_ReleaseSnapshotFromQuickFeedback.xml create mode 100644 .teamcity/Gradle_Promotion/buildTypes/Gradle_Promotion_StartReleaseCycle.kt delete mode 100644 .teamcity/Gradle_Promotion/buildTypes/Gradle_Promotion_StartReleaseCycle.xml create mode 100644 .teamcity/Gradle_Promotion/buildTypes/bt39.kt delete mode 100644 .teamcity/Gradle_Promotion/buildTypes/bt39.xml create mode 100644 .teamcity/Gradle_Promotion/buildTypes/bt60.kt delete mode 100644 .teamcity/Gradle_Promotion/buildTypes/bt60.xml create mode 100644 .teamcity/Gradle_Promotion/buildTypes/bt61.kt delete mode 100644 .teamcity/Gradle_Promotion/buildTypes/bt61.xml delete mode 100644 .teamcity/Gradle_Promotion/project-config.xml create mode 100644 .teamcity/Gradle_Promotion/settings.kts create mode 100644 .teamcity/Gradle_Promotion/vcsRoots/Gradle_Promotion_GradlePromotionBranches.kt delete mode 100644 .teamcity/Gradle_Promotion/vcsRoots/Gradle_Promotion_GradlePromotionBranches.xml create mode 100644 .teamcity/Gradle_Promotion/vcsRoots/Gradle_Promotion__master_.kt delete mode 100644 .teamcity/Gradle_Promotion/vcsRoots/Gradle_Promotion__master_.xml diff --git a/.teamcity/Gradle_Promotion/Project.kt b/.teamcity/Gradle_Promotion/Project.kt new file mode 100644 index 0000000000000..518ae023dc530 --- /dev/null +++ b/.teamcity/Gradle_Promotion/Project.kt @@ -0,0 +1,56 @@ +package Gradle_Promotion + +import Gradle_Promotion.buildTypes.* +import Gradle_Promotion.vcsRoots.* +import jetbrains.buildServer.configs.kotlin.v2018_2.* +import jetbrains.buildServer.configs.kotlin.v2018_2.Project +import jetbrains.buildServer.configs.kotlin.v2018_2.projectFeatures.VersionedSettings +import jetbrains.buildServer.configs.kotlin.v2018_2.projectFeatures.versionedSettings + +object Project : Project({ + uuid = "16c9f3e3-36a9-4596-a35c-70a3c7a2c5c8" + id("Gradle_Promotion") + parentId("Gradle") + name = "Promotion" + + vcsRoot(Gradle_Promotion_GradlePromotionBranches) + vcsRoot(Gradle_Promotion__master_) + + buildType(Gradle_Promotion_PublishBranchSnapshotFromQuickFeedback) + buildType(Gradle_Promotion_MilestoneMaster) + buildType(bt60) + buildType(bt61) + buildType(Gradle_Promotion_StartReleaseCycle) + buildType(Gradle_Promotion_FinalRelease) + buildType(bt39) + buildType(Gradle_Promotion_AllBranchesStartReleaseCycleTest) + buildType(Gradle_Promotion_MasterSanityCheck) + buildType(Gradle_Promotion_MasterNightlySnapshotManual) + buildType(Gradle_Promotion_ReleaseSnapshotFromQuickFeedback) + + params { + password("env.ORG_GRADLE_PROJECT_gradleS3SecretKey", "credentialsJSON:0f1f842f-df6c-4db7-8271-f1f73c823aed") + password("env.ORG_GRADLE_PROJECT_artifactoryUserPassword", "credentialsJSON:2b7529cd-77cd-49f4-9416-9461f6ac9018") + param("env.ORG_GRADLE_PROJECT_gradleS3AccessKey", "AKIAJUN6ZAPAEO3BC7AQ") + password("env.DOTCOM_DEV_DOCS_AWS_SECRET_KEY", "credentialsJSON:ed0db35e-2034-444c-a9b1-d966b9abe89b") + param("env.DOTCOM_DEV_DOCS_AWS_ACCESS_KEY", "AKIAJFJBF5BXLBNI3E5A") + password("env.ORG_GRADLE_PROJECT_sdkmanToken", "credentialsJSON:64e60515-68db-4bbd-aeae-ba2e058ac3cb") + param("env.JAVA_HOME", "%linux.java11.openjdk.64bit%") + param("env.ORG_GRADLE_PROJECT_artifactoryUserName", "bot-build-tool") + password("env.ORG_GRADLE_PROJECT_infrastructureEmailPwd", "credentialsJSON:ea637ef1-7607-40a4-be39-ef1aa8bc5af0") + param("env.ORG_GRADLE_PROJECT_sdkmanKey", "8ed1a771bc236c287ad93c699bfdd2d7") + } + + features { + versionedSettings { + id = "PROJECT_EXT_15" + mode = VersionedSettings.Mode.ENABLED + buildSettingsMode = VersionedSettings.BuildSettingsMode.PREFER_SETTINGS_FROM_VCS + rootExtId = "Gradle_Branches_VersionedSettings" + showChanges = false + settingsFormat = VersionedSettings.Format.KOTLIN + storeSecureParamsOutsideOfVcs = true + } + } + buildTypesOrder = arrayListOf(Gradle_Promotion_MasterSanityCheck, bt39, Gradle_Promotion_MasterNightlySnapshotManual, Gradle_Promotion_StartReleaseCycle, bt61, Gradle_Promotion_ReleaseSnapshotFromQuickFeedback, Gradle_Promotion_PublishBranchSnapshotFromQuickFeedback, Gradle_Promotion_MilestoneMaster, bt60, Gradle_Promotion_FinalRelease) +}) diff --git a/.teamcity/Gradle_Promotion/buildTypes/Gradle_Promotion_AllBranchesStartReleaseCycleTest.kt b/.teamcity/Gradle_Promotion/buildTypes/Gradle_Promotion_AllBranchesStartReleaseCycleTest.kt new file mode 100644 index 0000000000000..0829dab680eec --- /dev/null +++ b/.teamcity/Gradle_Promotion/buildTypes/Gradle_Promotion_AllBranchesStartReleaseCycleTest.kt @@ -0,0 +1,44 @@ +package Gradle_Promotion.buildTypes + +import jetbrains.buildServer.configs.kotlin.v2018_2.* +import jetbrains.buildServer.configs.kotlin.v2018_2.buildSteps.gradle +import jetbrains.buildServer.configs.kotlin.v2018_2.triggers.schedule +import jetbrains.buildServer.configs.kotlin.v2018_2.triggers.vcs + +object Gradle_Promotion_AllBranchesStartReleaseCycleTest : BuildType({ + uuid = "59823634-f79d-4c11-bbca-782957a7d65c" + name = "Master - Start Release Cycle Test" + description = "Test for Start Release Cycle pipeline" + + vcs { + root(Gradle_Promotion.vcsRoots.Gradle_Promotion_GradlePromotionBranches) + } + + steps { + gradle { + name = "PromoteTest" + tasks = "clean promoteStartReleaseCycle" + buildFile = "" + gradleParams = "-PconfirmationCode=startCycle -Igradle/buildScanInit.gradle -PtestRun=1" + param("teamcity.tool.jacoco", "%teamcity.tool.jacoco.DEFAULT%") + } + } + + triggers { + vcs { + branchFilter = "+:master" + } + schedule { + schedulingPolicy = daily { + hour = 3 + } + branchFilter = "+:master" + triggerBuild = always() + withPendingChangesOnly = false + } + } + + requirements { + contains("teamcity.agent.jvm.os.name", "Linux") + } +}) diff --git a/.teamcity/Gradle_Promotion/buildTypes/Gradle_Promotion_AllBranchesStartReleaseCycleTest.xml b/.teamcity/Gradle_Promotion/buildTypes/Gradle_Promotion_AllBranchesStartReleaseCycleTest.xml deleted file mode 100644 index 3ad320d09e391..0000000000000 --- a/.teamcity/Gradle_Promotion/buildTypes/Gradle_Promotion_AllBranchesStartReleaseCycleTest.xml +++ /dev/null @@ -1,57 +0,0 @@ - - - Master - Start Release Cycle Test - Test for Start Release Cycle pipeline - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.teamcity/Gradle_Promotion/buildTypes/Gradle_Promotion_FinalRelease.kt b/.teamcity/Gradle_Promotion/buildTypes/Gradle_Promotion_FinalRelease.kt new file mode 100644 index 0000000000000..348a2743ba9ba --- /dev/null +++ b/.teamcity/Gradle_Promotion/buildTypes/Gradle_Promotion_FinalRelease.kt @@ -0,0 +1,52 @@ +package Gradle_Promotion.buildTypes + +import jetbrains.buildServer.configs.kotlin.v2018_2.* +import jetbrains.buildServer.configs.kotlin.v2018_2.buildSteps.gradle + +object Gradle_Promotion_FinalRelease : BuildType({ + uuid = "44e9390f-e46c-457e-aa18-31b020aef4de" + name = "Release - Final" + description = "Promotes the latest successful change on 'release' as a new release" + + artifactRules = """ + incoming-build-receipt/build-receipt.properties => incoming-build-receipt + promote-projects/gradle/gradle/build/gradle-checkout/build/build-receipt.properties + promote-projects/gradle/gradle/build/distributions/*.zip => promote-build-distributions + promote-projects/gradle/gradle/build/website-checkout/data/releases.xml + promote-projects/gradle/build/git-checkout/build/reports/distributions/integTest/** => distribution-tests + promote-projects/gradle/smoke-tests/build/reports/tests/** => post-smoke-tests + """.trimIndent() + + params { + text("gitUserEmail", "", label = "Git user.email Configuration", description = "Enter the git 'user.email' configuration to commit change under", display = ParameterDisplay.PROMPT, allowEmpty = true) + text("confirmationCode", "", label = "Confirmation Code", description = "Enter the value 'final' (no quotes) to confirm the promotion", display = ParameterDisplay.PROMPT, allowEmpty = false) + text("gitUserName", "", label = "Git user.name Configuration", description = "Enter the git 'user.name' configuration to commit change under", display = ParameterDisplay.PROMPT, allowEmpty = true) + } + + vcs { + root(Gradle_Promotion.vcsRoots.Gradle_Promotion__master_) + + checkoutMode = CheckoutMode.ON_SERVER + } + + steps { + gradle { + name = "Promote" + tasks = "promoteFinalRelease" + buildFile = "" + gradleParams = """-PuseBuildReceipt -PconfirmationCode=%confirmationCode% "-PgitUserName=%gitUserName%" "-PgitUserEmail=%gitUserEmail%" -Igradle/buildScanInit.gradle --build-cache "-Dgradle.cache.remote.url=%gradle.cache.remote.url%" "-Dgradle.cache.remote.username=%gradle.cache.remote.username%" "-Dgradle.cache.remote.password=%gradle.cache.remote.password%"""" + } + } + + dependencies { + artifacts(AbsoluteId("Gradle_Check_Stage_ReadyforRelease_Trigger")) { + buildRule = lastSuccessful("release") + cleanDestination = true + artifactRules = "build-receipt.properties => incoming-build-receipt/" + } + } + + requirements { + contains("teamcity.agent.jvm.os.name", "Linux") + } +}) diff --git a/.teamcity/Gradle_Promotion/buildTypes/Gradle_Promotion_FinalRelease.xml b/.teamcity/Gradle_Promotion/buildTypes/Gradle_Promotion_FinalRelease.xml deleted file mode 100644 index b150db422f24f..0000000000000 --- a/.teamcity/Gradle_Promotion/buildTypes/Gradle_Promotion_FinalRelease.xml +++ /dev/null @@ -1,44 +0,0 @@ - - - Release - Final - Promotes the latest successful change on 'release' as a new release - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.teamcity/Gradle_Promotion/buildTypes/Gradle_Promotion_MasterNightlySnapshotManual.kt b/.teamcity/Gradle_Promotion/buildTypes/Gradle_Promotion_MasterNightlySnapshotManual.kt new file mode 100644 index 0000000000000..bc6f2508e3250 --- /dev/null +++ b/.teamcity/Gradle_Promotion/buildTypes/Gradle_Promotion_MasterNightlySnapshotManual.kt @@ -0,0 +1,47 @@ +package Gradle_Promotion.buildTypes + +import jetbrains.buildServer.configs.kotlin.v2018_2.* +import jetbrains.buildServer.configs.kotlin.v2018_2.buildSteps.gradle + +object Gradle_Promotion_MasterNightlySnapshotManual : BuildType({ + uuid = "9a55bec1-4e70-449b-8f45-400093505afb" + name = "Master - Nightly Snapshot (from Quick Feedback)" + description = "Promotes the latest change on 'master' that passed the 'Quick Feedback' stage as new nightly. This build configuration can be triggered manually if there are issues further down the pipeline we can ignore temporarily." + + artifactRules = """ + incoming-build-receipt/build-receipt.properties => incoming-build-receipt + **/build/git-checkout/build/build-receipt.properties + **/build/distributions/*.zip => promote-build-distributions + **/build/website-checkout/data/releases.xml + **/build/gradle-checkout/build/reports/integTest/** => distribution-tests + **/smoke-tests/build/reports/tests/** => post-smoke-tests + """.trimIndent() + + vcs { + root(Gradle_Promotion.vcsRoots.Gradle_Promotion__master_) + + checkoutMode = CheckoutMode.ON_SERVER + cleanCheckout = true + showDependenciesChanges = true + } + + steps { + gradle { + name = "Promote" + tasks = "promoteNightly -s" + buildFile = "" + gradleParams = """-PuseBuildReceipt -i "-PgitUserName=Gradleware Git Bot" "-PgitUserEmail=gradlewaregitbot@gradleware.com" -Igradle/buildScanInit.gradle --build-cache "-Dgradle.cache.remote.url=%gradle.cache.remote.url%" "-Dgradle.cache.remote.username=%gradle.cache.remote.username%" "-Dgradle.cache.remote.password=%gradle.cache.remote.password%"""" + } + } + + dependencies { + artifacts(AbsoluteId("Gradle_Check_Stage_QuickFeedback_Trigger")) { + buildRule = lastSuccessful("master") + artifactRules = "build-receipt.properties => incoming-build-receipt/" + } + } + + requirements { + contains("teamcity.agent.jvm.os.name", "Linux") + } +}) diff --git a/.teamcity/Gradle_Promotion/buildTypes/Gradle_Promotion_MasterNightlySnapshotManual.xml b/.teamcity/Gradle_Promotion/buildTypes/Gradle_Promotion_MasterNightlySnapshotManual.xml deleted file mode 100644 index c71c53423012e..0000000000000 --- a/.teamcity/Gradle_Promotion/buildTypes/Gradle_Promotion_MasterNightlySnapshotManual.xml +++ /dev/null @@ -1,42 +0,0 @@ - - - Master - Nightly Snapshot (from Quick Feedback) - Promotes the latest change on 'master' that passed the 'Quick Feedback' stage as new nightly. This build configuration can be triggered manually if there are issues further down the pipeline we can ignore temporarily. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.teamcity/Gradle_Promotion/buildTypes/Gradle_Promotion_MasterSanityCheck.kt b/.teamcity/Gradle_Promotion/buildTypes/Gradle_Promotion_MasterSanityCheck.kt new file mode 100644 index 0000000000000..21b2e5038d8b5 --- /dev/null +++ b/.teamcity/Gradle_Promotion/buildTypes/Gradle_Promotion_MasterSanityCheck.kt @@ -0,0 +1,39 @@ +package Gradle_Promotion.buildTypes + +import jetbrains.buildServer.configs.kotlin.v2018_2.* +import jetbrains.buildServer.configs.kotlin.v2018_2.buildSteps.gradle +import jetbrains.buildServer.configs.kotlin.v2018_2.triggers.vcs + +object Gradle_Promotion_MasterSanityCheck : BuildType({ + uuid = "bf9b573a-6e5e-4db1-88b2-399e709026b5" + name = "Master - Sanity Check" + description = "Compilation and test execution of buildSrc" + + vcs { + root(Gradle_Promotion.vcsRoots.Gradle_Promotion__master_) + + checkoutMode = CheckoutMode.ON_SERVER + cleanCheckout = true + showDependenciesChanges = true + } + + steps { + gradle { + tasks = "tasks -s" + buildFile = "" + gradleParams = "-Igradle/buildScanInit.gradle" + param("org.jfrog.artifactory.selectedDeployableServer.defaultModuleVersionConfiguration", "GLOBAL") + param("ui.gradleRunner.gradle.build.file", "") + } + } + + triggers { + vcs { + branchFilter = "" + } + } + + requirements { + contains("teamcity.agent.jvm.os.name", "Linux") + } +}) diff --git a/.teamcity/Gradle_Promotion/buildTypes/Gradle_Promotion_MasterSanityCheck.xml b/.teamcity/Gradle_Promotion/buildTypes/Gradle_Promotion_MasterSanityCheck.xml deleted file mode 100644 index e2acce98e8cf5..0000000000000 --- a/.teamcity/Gradle_Promotion/buildTypes/Gradle_Promotion_MasterSanityCheck.xml +++ /dev/null @@ -1,45 +0,0 @@ - - - Master - Sanity Check - Compilation and test execution of buildSrc - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.teamcity/Gradle_Promotion/buildTypes/Gradle_Promotion_MilestoneMaster.kt b/.teamcity/Gradle_Promotion/buildTypes/Gradle_Promotion_MilestoneMaster.kt new file mode 100644 index 0000000000000..55dd7e974f93a --- /dev/null +++ b/.teamcity/Gradle_Promotion/buildTypes/Gradle_Promotion_MilestoneMaster.kt @@ -0,0 +1,52 @@ +package Gradle_Promotion.buildTypes + +import jetbrains.buildServer.configs.kotlin.v2018_2.* +import jetbrains.buildServer.configs.kotlin.v2018_2.buildSteps.gradle + +object Gradle_Promotion_MilestoneMaster : BuildType({ + uuid = "2ffb238a-08af-4f95-b863-9830d2bc3872" + name = "Release - Milestone" + description = "Promotes the latest successful change on 'release' as the new snapshot" + + artifactRules = """ + incoming-build-receipt/build-receipt.properties => incoming-build-receipt + promote-projects/gradle/gradle/build/gradle-checkout/build/build-receipt.properties + promote-projects/gradle/gradle/build/distributions/*.zip => promote-build-distributions + promote-projects/gradle/gradle/build/website-checkout/data/releases.xml + promote-projects/gradle/build/git-checkout/build/reports/distributions/integTest/** => distribution-tests + promote-projects/gradle/smoke-tests/build/reports/tests/** => post-smoke-tests + """.trimIndent() + + params { + text("gitUserEmail", "", label = "Git user.email Configuration", description = "Enter the git 'user.email' configuration to commit change under", display = ParameterDisplay.PROMPT, allowEmpty = true) + param("confirmationCode", "") + text("gitUserName", "", label = "Git user.name Configuration", description = "Enter the git 'user.name' configuration to commit change under", display = ParameterDisplay.PROMPT, allowEmpty = true) + } + + vcs { + root(Gradle_Promotion.vcsRoots.Gradle_Promotion__master_) + + checkoutMode = CheckoutMode.ON_SERVER + showDependenciesChanges = true + } + + steps { + gradle { + name = "Promote" + tasks = "promoteMilestone -s -PconfirmationCode=milestone" + buildFile = "" + gradleParams = """-PuseBuildReceipt -i "-PgitUserName=%gitUserName%" "-PgitUserEmail=%gitUserEmail%" -Igradle/buildScanInit.gradle --build-cache "-Dgradle.cache.remote.url=%gradle.cache.remote.url%" "-Dgradle.cache.remote.username=%gradle.cache.remote.username%" "-Dgradle.cache.remote.password=%gradle.cache.remote.password%"""" + } + } + + dependencies { + artifacts(AbsoluteId("Gradle_Check_Stage_ReadyforRelease_Trigger")) { + buildRule = lastSuccessful("release") + artifactRules = "build-receipt.properties => incoming-build-receipt/" + } + } + + requirements { + contains("teamcity.agent.jvm.os.name", "Linux") + } +}) diff --git a/.teamcity/Gradle_Promotion/buildTypes/Gradle_Promotion_MilestoneMaster.xml b/.teamcity/Gradle_Promotion/buildTypes/Gradle_Promotion_MilestoneMaster.xml deleted file mode 100644 index 4317a12635aa2..0000000000000 --- a/.teamcity/Gradle_Promotion/buildTypes/Gradle_Promotion_MilestoneMaster.xml +++ /dev/null @@ -1,45 +0,0 @@ - - - Release - Milestone - Promotes the latest successful change on 'release' as the new snapshot - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.teamcity/Gradle_Promotion/buildTypes/Gradle_Promotion_PublishBranchSnapshotFromQuickFeedback.kt b/.teamcity/Gradle_Promotion/buildTypes/Gradle_Promotion_PublishBranchSnapshotFromQuickFeedback.kt new file mode 100644 index 0000000000000..e348503acb75c --- /dev/null +++ b/.teamcity/Gradle_Promotion/buildTypes/Gradle_Promotion_PublishBranchSnapshotFromQuickFeedback.kt @@ -0,0 +1,51 @@ +package Gradle_Promotion.buildTypes + +import jetbrains.buildServer.configs.kotlin.v2018_2.* +import jetbrains.buildServer.configs.kotlin.v2018_2.buildSteps.gradle + +object Gradle_Promotion_PublishBranchSnapshotFromQuickFeedback : BuildType({ + uuid = "b7ecebd3-3812-4532-aa77-5679f9e9d6b3" + name = "Publish Branch Snapshot (from Quick Feedback)" + description = "Deploys a new wrapper for the selected build/branch. Does not update master or the documentation." + + artifactRules = """ + incoming-build-receipt/build-receipt.properties => incoming-build-receipt + **/build/git-checkout/build/build-receipt.properties + **/build/distributions/*.zip => promote-build-distributions + **/build/website-checkout/data/releases.xml + **/build/git-checkout/build/reports/integTest/** => distribution-tests + **/smoke-tests/build/reports/tests/** => post-smoke-tests + """.trimIndent() + + params { + param("branch.qualifier", "%dep.Gradle_Check_Stage_QuickFeedback_Trigger.teamcity.build.branch%") + text("branch.to.promote", "%branch.qualifier%", label = "Branch to promote", description = "Type in the branch of gradle/gradle you want to promote. Leave the default value when promoting an existing build.", display = ParameterDisplay.PROMPT, allowEmpty = false) + } + + vcs { + root(Gradle_Promotion.vcsRoots.Gradle_Promotion_GradlePromotionBranches) + + checkoutMode = CheckoutMode.ON_SERVER + } + + steps { + gradle { + name = "Promote" + tasks = "promoteSnapshot" + buildFile = "" + gradleParams = """-PuseBuildReceipt "-PgitUserName=Gradleware Git Bot" "-PgitUserEmail=gradlewaregitbot@gradleware.com" -Igradle/buildScanInit.gradle -PpromotedBranch=%branch.qualifier% --build-cache "-Dgradle.cache.remote.url=%gradle.cache.remote.url%" "-Dgradle.cache.remote.username=%gradle.cache.remote.username%" "-Dgradle.cache.remote.password=%gradle.cache.remote.password%"""" + } + } + + dependencies { + artifacts(AbsoluteId("Gradle_Check_Stage_QuickFeedback_Trigger")) { + buildRule = lastSuccessful("%branch.to.promote%") + cleanDestination = true + artifactRules = "build-receipt.properties => incoming-build-receipt/" + } + } + + requirements { + contains("teamcity.agent.jvm.os.name", "Linux") + } +}) diff --git a/.teamcity/Gradle_Promotion/buildTypes/Gradle_Promotion_PublishBranchSnapshotFromQuickFeedback.xml b/.teamcity/Gradle_Promotion/buildTypes/Gradle_Promotion_PublishBranchSnapshotFromQuickFeedback.xml deleted file mode 100644 index ebc7ec242e339..0000000000000 --- a/.teamcity/Gradle_Promotion/buildTypes/Gradle_Promotion_PublishBranchSnapshotFromQuickFeedback.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - Publish Branch Snapshot (from Quick Feedback) - Deploys a new wrapper for the selected build/branch. Does not update master or the documentation. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.teamcity/Gradle_Promotion/buildTypes/Gradle_Promotion_ReleaseSnapshotFromQuickFeedback.kt b/.teamcity/Gradle_Promotion/buildTypes/Gradle_Promotion_ReleaseSnapshotFromQuickFeedback.kt new file mode 100644 index 0000000000000..6f39d9aa93266 --- /dev/null +++ b/.teamcity/Gradle_Promotion/buildTypes/Gradle_Promotion_ReleaseSnapshotFromQuickFeedback.kt @@ -0,0 +1,46 @@ +package Gradle_Promotion.buildTypes + +import jetbrains.buildServer.configs.kotlin.v2018_2.* +import jetbrains.buildServer.configs.kotlin.v2018_2.buildSteps.gradle + +object Gradle_Promotion_ReleaseSnapshotFromQuickFeedback : BuildType({ + uuid = "eeff4410-1e7d-4db6-b7b8-34c1f2754477" + name = "Release - Release Nightly Snapshot (from Quick Feedback)" + description = "Deploys the latest successful change on 'release' as a new release nightly snapshot" + + artifactRules = """ + incoming-build-receipt/build-receipt.properties => incoming-build-receipt + **/build/git-checkout/build/build-receipt.properties + **/build/distributions/*.zip => promote-build-distributions + **/build/website-checkout/data/releases.xml + **/build/git-checkout/build/reports/integTest/** => distribution-tests + **/smoke-tests/build/reports/tests/** => post-smoke-tests + """.trimIndent() + + vcs { + root(Gradle_Promotion.vcsRoots.Gradle_Promotion__master_) + + checkoutMode = CheckoutMode.ON_SERVER + } + + steps { + gradle { + name = "Promote" + tasks = "promoteReleaseNightly" + buildFile = "" + gradleParams = """-PuseBuildReceipt "-PgitUserName=Gradleware Git Bot" "-PgitUserEmail=gradlewaregitbot@gradleware.com" -Igradle/buildScanInit.gradle --build-cache "-Dgradle.cache.remote.url=%gradle.cache.remote.url%" "-Dgradle.cache.remote.username=%gradle.cache.remote.username%" "-Dgradle.cache.remote.password=%gradle.cache.remote.password%"""" + } + } + + dependencies { + artifacts(AbsoluteId("Gradle_Check_Stage_QuickFeedback_Trigger")) { + buildRule = lastSuccessful("release") + cleanDestination = true + artifactRules = "build-receipt.properties => incoming-build-receipt/" + } + } + + requirements { + contains("teamcity.agent.jvm.os.name", "Linux") + } +}) diff --git a/.teamcity/Gradle_Promotion/buildTypes/Gradle_Promotion_ReleaseSnapshotFromQuickFeedback.xml b/.teamcity/Gradle_Promotion/buildTypes/Gradle_Promotion_ReleaseSnapshotFromQuickFeedback.xml deleted file mode 100644 index ca9d323d8d2ee..0000000000000 --- a/.teamcity/Gradle_Promotion/buildTypes/Gradle_Promotion_ReleaseSnapshotFromQuickFeedback.xml +++ /dev/null @@ -1,40 +0,0 @@ - - - Release - Release Nightly Snapshot (from Quick Feedback) - Deploys the latest successful change on 'release' as a new release nightly snapshot - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.teamcity/Gradle_Promotion/buildTypes/Gradle_Promotion_StartReleaseCycle.kt b/.teamcity/Gradle_Promotion/buildTypes/Gradle_Promotion_StartReleaseCycle.kt new file mode 100644 index 0000000000000..4e14e4291670a --- /dev/null +++ b/.teamcity/Gradle_Promotion/buildTypes/Gradle_Promotion_StartReleaseCycle.kt @@ -0,0 +1,49 @@ +package Gradle_Promotion.buildTypes + +import jetbrains.buildServer.configs.kotlin.v2018_2.* +import jetbrains.buildServer.configs.kotlin.v2018_2.buildSteps.gradle + +object Gradle_Promotion_StartReleaseCycle : BuildType({ + uuid = "355487d7-45b9-4387-9fc5-713e7683e6d0" + name = "Master - Start Release Cycle" + description = "Promotes a successful build on master as the start of a new release cycle on the release branch" + + artifactRules = """ + incoming-build-receipt/build-receipt.properties => incoming-build-receipt + promote-projects/gradle/build/reports/jdiff => jdiff + """.trimIndent() + + params { + text("gitUserEmail", "", label = "Git user.email Configuration", description = "Enter the git 'user.email' configuration to commit change under", display = ParameterDisplay.PROMPT, allowEmpty = true) + text("confirmationCode", "", label = "Confirmation Code", description = "Enter the value 'startCycle' (no quotes) to confirm the promotion", display = ParameterDisplay.PROMPT, allowEmpty = false) + text("gitUserName", "", label = "Git user.name Configuration", description = "Enter the git 'user.name' configuration to commit change under", display = ParameterDisplay.PROMPT, allowEmpty = true) + } + + vcs { + root(Gradle_Promotion.vcsRoots.Gradle_Promotion__master_) + + checkoutMode = CheckoutMode.ON_SERVER + } + + steps { + gradle { + name = "Promote" + tasks = "clean promoteStartReleaseCycle" + buildFile = "" + gradleParams = """-PuseBuildReceipt -PconfirmationCode=%confirmationCode% "-PgitUserName=%gitUserName%" "-PgitUserEmail=%gitUserEmail%" -Igradle/buildScanInit.gradle""" + param("org.jfrog.artifactory.selectedDeployableServer.defaultModuleVersionConfiguration", "GLOBAL") + } + } + + dependencies { + artifacts(AbsoluteId("Gradle_Check_Stage_ReadyforNightly_Trigger")) { + buildRule = lastSuccessful("master") + cleanDestination = true + artifactRules = "build-receipt.properties => incoming-build-receipt/" + } + } + + requirements { + contains("teamcity.agent.jvm.os.name", "Linux") + } +}) diff --git a/.teamcity/Gradle_Promotion/buildTypes/Gradle_Promotion_StartReleaseCycle.xml b/.teamcity/Gradle_Promotion/buildTypes/Gradle_Promotion_StartReleaseCycle.xml deleted file mode 100644 index 3decd3a85780f..0000000000000 --- a/.teamcity/Gradle_Promotion/buildTypes/Gradle_Promotion_StartReleaseCycle.xml +++ /dev/null @@ -1,45 +0,0 @@ - - - Master - Start Release Cycle - Promotes a successful build on master as the start of a new release cycle on the release branch - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.teamcity/Gradle_Promotion/buildTypes/bt39.kt b/.teamcity/Gradle_Promotion/buildTypes/bt39.kt new file mode 100644 index 0000000000000..8ecbd83d6a4fd --- /dev/null +++ b/.teamcity/Gradle_Promotion/buildTypes/bt39.kt @@ -0,0 +1,60 @@ +package Gradle_Promotion.buildTypes + +import jetbrains.buildServer.configs.kotlin.v2018_2.* +import jetbrains.buildServer.configs.kotlin.v2018_2.buildSteps.gradle +import jetbrains.buildServer.configs.kotlin.v2018_2.triggers.schedule + +object bt39 : BuildType({ + uuid = "01432c63-861f-4d08-ae0a-7d127f63096e" + name = "Master - Nightly Snapshot" + description = "Promotes the latest successful change on 'master' as the new nightly" + + artifactRules = """ + incoming-build-receipt/build-receipt.properties => incoming-build-receipt + **/build/git-checkout/build/build-receipt.properties + **/build/distributions/*.zip => promote-build-distributions + **/build/website-checkout/data/releases.xml + **/build/gradle-checkout/build/reports/integTest/** => distribution-tests + **/smoke-tests/build/reports/tests/** => post-smoke-tests + """.trimIndent() + + vcs { + root(Gradle_Promotion.vcsRoots.Gradle_Promotion__master_) + + checkoutMode = CheckoutMode.ON_SERVER + cleanCheckout = true + showDependenciesChanges = true + } + + steps { + gradle { + name = "Promote" + tasks = "promoteNightly -s" + buildFile = "" + gradleParams = """-PuseBuildReceipt -i "-PgitUserName=Gradleware Git Bot" "-PgitUserEmail=gradlewaregitbot@gradleware.com" -Igradle/buildScanInit.gradle --build-cache "-Dgradle.cache.remote.url=%gradle.cache.remote.url%" "-Dgradle.cache.remote.username=%gradle.cache.remote.username%" "-Dgradle.cache.remote.password=%gradle.cache.remote.password%"""" + } + } + + triggers { + schedule { + schedulingPolicy = daily { + hour = 0 + timezone = "" + } + branchFilter = "" + triggerBuild = always() + withPendingChangesOnly = false + } + } + + dependencies { + artifacts(AbsoluteId("Gradle_Check_Stage_ReadyforNightly_Trigger")) { + buildRule = lastSuccessful("master") + artifactRules = "build-receipt.properties => incoming-build-receipt/" + } + } + + requirements { + contains("teamcity.agent.jvm.os.name", "Linux") + } +}) diff --git a/.teamcity/Gradle_Promotion/buildTypes/bt39.xml b/.teamcity/Gradle_Promotion/buildTypes/bt39.xml deleted file mode 100644 index 18b5cb6d4355a..0000000000000 --- a/.teamcity/Gradle_Promotion/buildTypes/bt39.xml +++ /dev/null @@ -1,59 +0,0 @@ - - - Master - Nightly Snapshot - Promotes the latest successful change on 'master' as the new nightly - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.teamcity/Gradle_Promotion/buildTypes/bt60.kt b/.teamcity/Gradle_Promotion/buildTypes/bt60.kt new file mode 100644 index 0000000000000..0d8765f8529b7 --- /dev/null +++ b/.teamcity/Gradle_Promotion/buildTypes/bt60.kt @@ -0,0 +1,52 @@ +package Gradle_Promotion.buildTypes + +import jetbrains.buildServer.configs.kotlin.v2018_2.* +import jetbrains.buildServer.configs.kotlin.v2018_2.buildSteps.gradle + +object bt60 : BuildType({ + uuid = "5ed504bb-5ec3-46dc-a28a-e42a63ebbb31" + name = "Release - Release Candidate" + description = "Promotes the latest successful change on 'release' as a new release candidate" + + artifactRules = """ + incoming-build-receipt/build-receipt.properties => incoming-build-receipt + promote-projects/gradle/gradle/build/gradle-checkout/build/build-receipt.properties + promote-projects/gradle/gradle/build/distributions/*.zip => promote-build-distributions + promote-projects/gradle/gradle/build/website-checkout/data/releases.xml + promote-projects/gradle/build/git-checkout/build/reports/distributions/integTest/** => distribution-tests + promote-projects/gradle/smoke-tests/build/reports/tests/** => post-smoke-tests + """.trimIndent() + + params { + text("gitUserEmail", "", label = "Git user.email Configuration", description = "Enter the git 'user.email' configuration to commit change under", display = ParameterDisplay.PROMPT, allowEmpty = true) + text("confirmationCode", "", label = "Confirmation Code", description = "Enter the value 'rc' (no quotes) to confirm the promotion", display = ParameterDisplay.PROMPT, allowEmpty = false) + text("gitUserName", "", label = "Git user.name Configuration", description = "Enter the git 'user.name' configuration to commit change under", display = ParameterDisplay.PROMPT, allowEmpty = true) + } + + vcs { + root(Gradle_Promotion.vcsRoots.Gradle_Promotion__master_) + + checkoutMode = CheckoutMode.ON_SERVER + } + + steps { + gradle { + name = "Promote" + tasks = "promoteRc" + buildFile = "" + gradleParams = """-PuseBuildReceipt -PconfirmationCode=%confirmationCode% "-PgitUserName=%gitUserName%" "-PgitUserEmail=%gitUserEmail%" -Igradle/buildScanInit.gradle --build-cache "-Dgradle.cache.remote.url=%gradle.cache.remote.url%" "-Dgradle.cache.remote.username=%gradle.cache.remote.username%" "-Dgradle.cache.remote.password=%gradle.cache.remote.password%"""" + } + } + + dependencies { + artifacts(AbsoluteId("Gradle_Check_Stage_ReadyforRelease_Trigger")) { + buildRule = lastSuccessful("release") + cleanDestination = true + artifactRules = "build-receipt.properties => incoming-build-receipt/" + } + } + + requirements { + contains("teamcity.agent.jvm.os.name", "Linux") + } +}) diff --git a/.teamcity/Gradle_Promotion/buildTypes/bt60.xml b/.teamcity/Gradle_Promotion/buildTypes/bt60.xml deleted file mode 100644 index 5c04be0a25954..0000000000000 --- a/.teamcity/Gradle_Promotion/buildTypes/bt60.xml +++ /dev/null @@ -1,44 +0,0 @@ - - - Release - Release Candidate - Promotes the latest successful change on 'release' as a new release candidate - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.teamcity/Gradle_Promotion/buildTypes/bt61.kt b/.teamcity/Gradle_Promotion/buildTypes/bt61.kt new file mode 100644 index 0000000000000..917d36f001394 --- /dev/null +++ b/.teamcity/Gradle_Promotion/buildTypes/bt61.kt @@ -0,0 +1,58 @@ +package Gradle_Promotion.buildTypes + +import jetbrains.buildServer.configs.kotlin.v2018_2.* +import jetbrains.buildServer.configs.kotlin.v2018_2.buildSteps.gradle +import jetbrains.buildServer.configs.kotlin.v2018_2.triggers.schedule + +object bt61 : BuildType({ + uuid = "1f5ca7f8-b0f5-41f9-9ba7-6d518b2822f0" + name = "Release - Release Nightly Snapshot" + description = "Deploys the latest successful change on 'release' as a new release nightly snapshot" + + artifactRules = """ + incoming-build-receipt/build-receipt.properties => incoming-build-receipt + **/build/git-checkout/build/build-receipt.properties + **/build/distributions/*.zip => promote-build-distributions + **/build/website-checkout/data/releases.xml + **/build/git-checkout/build/reports/integTest/** => distribution-tests + **/smoke-tests/build/reports/tests/** => post-smoke-tests + """.trimIndent() + + vcs { + root(Gradle_Promotion.vcsRoots.Gradle_Promotion__master_) + + checkoutMode = CheckoutMode.ON_SERVER + } + + steps { + gradle { + name = "Promote" + tasks = "promoteReleaseNightly" + buildFile = "" + gradleParams = """-PuseBuildReceipt "-PgitUserName=Gradleware Git Bot" "-PgitUserEmail=gradlewaregitbot@gradleware.com" -Igradle/buildScanInit.gradle --build-cache "-Dgradle.cache.remote.url=%gradle.cache.remote.url%" "-Dgradle.cache.remote.username=%gradle.cache.remote.username%" "-Dgradle.cache.remote.password=%gradle.cache.remote.password%"""" + } + } + + triggers { + schedule { + schedulingPolicy = daily { + hour = 1 + } + branchFilter = "" + triggerBuild = always() + withPendingChangesOnly = false + } + } + + dependencies { + artifacts(AbsoluteId("Gradle_Check_Stage_ReadyforNightly_Trigger")) { + buildRule = lastSuccessful("release") + cleanDestination = true + artifactRules = "build-receipt.properties => incoming-build-receipt/" + } + } + + requirements { + contains("teamcity.agent.jvm.os.name", "Linux") + } +}) diff --git a/.teamcity/Gradle_Promotion/buildTypes/bt61.xml b/.teamcity/Gradle_Promotion/buildTypes/bt61.xml deleted file mode 100644 index 986290cdca3a3..0000000000000 --- a/.teamcity/Gradle_Promotion/buildTypes/bt61.xml +++ /dev/null @@ -1,59 +0,0 @@ - - - Release - Release Nightly Snapshot - Deploys the latest successful change on 'release' as a new release nightly snapshot - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.teamcity/Gradle_Promotion/pluginData/plugin-settings.xml b/.teamcity/Gradle_Promotion/pluginData/plugin-settings.xml index ade07a22aed3b..9e41c7cba5cfd 100644 --- a/.teamcity/Gradle_Promotion/pluginData/plugin-settings.xml +++ b/.teamcity/Gradle_Promotion/pluginData/plugin-settings.xml @@ -4,14 +4,14 @@ - - - - - - + + + + + + diff --git a/.teamcity/Gradle_Promotion/project-config.xml b/.teamcity/Gradle_Promotion/project-config.xml deleted file mode 100644 index eff5d262d249e..0000000000000 --- a/.teamcity/Gradle_Promotion/project-config.xml +++ /dev/null @@ -1,30 +0,0 @@ - - - Promotion - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.teamcity/Gradle_Promotion/settings.kts b/.teamcity/Gradle_Promotion/settings.kts new file mode 100644 index 0000000000000..c7191ef3ac88f --- /dev/null +++ b/.teamcity/Gradle_Promotion/settings.kts @@ -0,0 +1,35 @@ +package Gradle_Promotion + +import jetbrains.buildServer.configs.kotlin.v2018_2.* + +/* +The settings script is an entry point for defining a single +TeamCity project. TeamCity looks for the 'settings.kts' file in a +project directory and runs it if it's found, so the script name +shouldn't be changed and its package should be the same as the +project's id. + +The script should contain a single call to the project() function +with a Project instance or an init function as an argument. + +VcsRoots, BuildTypes, and Templates of this project must be +registered inside project using the vcsRoot(), buildType(), and +template() methods respectively. + +Subprojects can be defined either in their own settings.kts or by +calling the subProjects() method in this project. + +To debug settings scripts in command-line, run the + + mvnDebug org.jetbrains.teamcity:teamcity-configs-maven-plugin:generate + +command and attach your debugger to the port 8000. + +To debug in IntelliJ Idea, open the 'Maven Projects' tool window (View -> +Tool Windows -> Maven Projects), find the generate task +node (Plugins -> teamcity-configs -> teamcity-configs:generate), +the 'Debug' option is available in the context menu for the task. +*/ + +version = "2018.2" +project(Gradle_Promotion.Project) \ No newline at end of file diff --git a/.teamcity/Gradle_Promotion/vcsRoots/Gradle_Promotion_GradlePromotionBranches.kt b/.teamcity/Gradle_Promotion/vcsRoots/Gradle_Promotion_GradlePromotionBranches.kt new file mode 100644 index 0000000000000..849e427c7d40a --- /dev/null +++ b/.teamcity/Gradle_Promotion/vcsRoots/Gradle_Promotion_GradlePromotionBranches.kt @@ -0,0 +1,17 @@ +package Gradle_Promotion.vcsRoots + +import jetbrains.buildServer.configs.kotlin.v2018_2.* +import jetbrains.buildServer.configs.kotlin.v2018_2.vcs.GitVcsRoot + +object Gradle_Promotion_GradlePromotionBranches : GitVcsRoot({ + uuid = "e4bc6ac6-ab3f-4459-b4c4-7d6ba6e2cbf6" + name = "Gradle Promotion Branches" + url = "https://github.com/gradleware/gradle-promote.git" + branchSpec = "+:refs/heads/*" + agentGitPath = "%env.TEAMCITY_GIT_PATH%" + useMirrors = false + authMethod = password { + userName = "gradlewaregitbot" + password = "credentialsJSON:5306bfc7-041e-46e8-8d61-1d49424e7b04" + } +}) diff --git a/.teamcity/Gradle_Promotion/vcsRoots/Gradle_Promotion_GradlePromotionBranches.xml b/.teamcity/Gradle_Promotion/vcsRoots/Gradle_Promotion_GradlePromotionBranches.xml deleted file mode 100644 index fb3f3ab812928..0000000000000 --- a/.teamcity/Gradle_Promotion/vcsRoots/Gradle_Promotion_GradlePromotionBranches.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - Gradle Promotion Branches - - - - - - - - - - - - - - diff --git a/.teamcity/Gradle_Promotion/vcsRoots/Gradle_Promotion__master_.kt b/.teamcity/Gradle_Promotion/vcsRoots/Gradle_Promotion__master_.kt new file mode 100644 index 0000000000000..66133d3f1a0eb --- /dev/null +++ b/.teamcity/Gradle_Promotion/vcsRoots/Gradle_Promotion__master_.kt @@ -0,0 +1,17 @@ +package Gradle_Promotion.vcsRoots + +import jetbrains.buildServer.configs.kotlin.v2018_2.* +import jetbrains.buildServer.configs.kotlin.v2018_2.vcs.GitVcsRoot + +object Gradle_Promotion__master_ : GitVcsRoot({ + uuid = "0974a0e7-3f2f-4c3f-a185-aded6ac045ff" + name = "Gradle Promotion" + url = "https://github.com/gradleware/gradle-promote.git" + branch = "master" + agentGitPath = "%env.TEAMCITY_GIT_PATH%" + useMirrors = false + authMethod = password { + userName = "gradlewaregitbot" + password = "credentialsJSON:69f980df-e4d1-4622-9f0f-5be59df88a04" + } +}) diff --git a/.teamcity/Gradle_Promotion/vcsRoots/Gradle_Promotion__master_.xml b/.teamcity/Gradle_Promotion/vcsRoots/Gradle_Promotion__master_.xml deleted file mode 100644 index 18f29ceaa6a6d..0000000000000 --- a/.teamcity/Gradle_Promotion/vcsRoots/Gradle_Promotion__master_.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - Gradle Promotion - - - - - - - - - - - - - From 156fb5f1790b428715d5d66f54f08b5ad0aaf656 Mon Sep 17 00:00:00 2001 From: Gary Hale Date: Thu, 7 Mar 2019 10:34:15 -0500 Subject: [PATCH 381/853] Introduce test that simulates GC activity --- ...CollectionMonitoringIntegrationTest.groovy | 200 ++++++++++++++++++ .../server/health/DaemonHealthStats.java | 10 +- .../gc/DefaultGarbageCollectionMonitor.java | 80 +++++++ .../health/gc/GarbageCollectionMonitor.java | 56 +---- .../health/DaemonHealthStatsTest.groovy | 4 +- .../gc/GarbageCollectionMonitorTest.groovy | 6 +- ...DaemonPerformanceMonitoringSoakTest.groovy | 82 ------- 7 files changed, 303 insertions(+), 135 deletions(-) create mode 100644 subprojects/launcher/src/integTest/groovy/org/gradle/launcher/daemon/server/health/gc/GarbageCollectionMonitoringIntegrationTest.groovy create mode 100644 subprojects/launcher/src/main/java/org/gradle/launcher/daemon/server/health/gc/DefaultGarbageCollectionMonitor.java diff --git a/subprojects/launcher/src/integTest/groovy/org/gradle/launcher/daemon/server/health/gc/GarbageCollectionMonitoringIntegrationTest.groovy b/subprojects/launcher/src/integTest/groovy/org/gradle/launcher/daemon/server/health/gc/GarbageCollectionMonitoringIntegrationTest.groovy new file mode 100644 index 0000000000000..9e0507e19c163 --- /dev/null +++ b/subprojects/launcher/src/integTest/groovy/org/gradle/launcher/daemon/server/health/gc/GarbageCollectionMonitoringIntegrationTest.groovy @@ -0,0 +1,200 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.launcher.daemon.server.health.gc + +import org.gradle.integtests.fixtures.daemon.DaemonIntegrationSpec +import org.gradle.launcher.daemon.server.health.DaemonMemoryStatus + +import static org.gradle.launcher.daemon.server.DaemonStateCoordinator.DAEMON_STOPPING_IMMEDIATELY_MESSAGE +import static org.gradle.launcher.daemon.server.DaemonStateCoordinator.DAEMON_WILL_STOP_MESSAGE + +class GarbageCollectionMonitoringIntegrationTest extends DaemonIntegrationSpec { + def setup() { + executer.withEnvironmentVars(JAVA_TOOL_OPTIONS: "-D${DefaultGarbageCollectionMonitor.DISABLE_POLLING_SYSTEM_PROPERTY}=true -D${DaemonMemoryStatus.ENABLE_PERFORMANCE_MONITORING}=true") + } + + def "expires daemon when heap leaks slowly"() { + given: + configureGarbageCollectionHeapEventsFor(256, 512, 35, 1.8) + + when: + run "injectEvents" + + then: + daemons.daemon.stops() + + and: + daemons.daemon.log.contains(DAEMON_WILL_STOP_MESSAGE) + } + + def "expires daemon immediately when garbage collector is thrashing"() { + given: + configureGarbageCollectionHeapEventsFor(256, 512, 100, 5) + waitForDaemonExpiration() + + when: + fails "injectEvents" + + then: + failure.assertHasDescription("Gradle build daemon has been stopped: JVM garbage collector thrashing and after running out of JVM memory") + + and: + daemons.daemon.stops() + + and: + daemons.daemon.log.contains(DAEMON_STOPPING_IMMEDIATELY_MESSAGE) + } + + def "expires daemon when heap leaks while daemon is idle"() { + def initial = 256 + def max = 512 + def events = eventsFor(initial, max, 35, 1.8) + def initScript = file("init.gradle") + initScript << """ + ${injectionImports} + + gradle.buildFinished { + ${eventInjectionConfiguration("heap", events, initial, max)} + } + + gradle.rootProject { + tasks.create("startLeakAfterBuild") + } + """ + executer.usingInitScript(initScript) + + when: + succeeds "startLeakAfterBuild" + + then: + daemons.daemon.stops() + + and: + daemons.daemon.log.contains(DAEMON_WILL_STOP_MESSAGE) + } + + def "expires daemon when metaspace leaks"() { + given: + configureGarbageCollectionNonHeapEventsFor(256, 512, 35, 0) + + when: + run "injectEvents" + + then: + daemons.daemon.stops() + + and: + daemons.daemon.log.contains(DAEMON_WILL_STOP_MESSAGE) + } + + void configureGarbageCollectionHeapEventsFor(long initial, long max, long leakRate, double gcRate) { + configureGarbageCollectionEvents("heap", initial, max, leakRate, gcRate) + } + + void configureGarbageCollectionNonHeapEventsFor(long initial, long max, long leakRate, double gcRate) { + configureGarbageCollectionEvents("nonHeap", initial, max, leakRate, gcRate) + } + + void configureGarbageCollectionEvents(String type, long initial, long max, leakRate, gcRate) { + def events = eventsFor(initial, max, leakRate, gcRate) + buildFile << """ + ${injectionImports} + + task injectEvents { + doLast { + ${eventInjectionConfiguration(type, events, initial, max)} + } + } + """ + } + + String getInjectionImports() { + return """ + import org.gradle.launcher.daemon.server.health.gc.GarbageCollectionMonitor + import org.gradle.launcher.daemon.server.health.gc.GarbageCollectionEvent + import org.gradle.launcher.daemon.server.health.DaemonHealthStats + import org.gradle.internal.time.Clock + import org.gradle.internal.time.Time + import java.lang.management.MemoryUsage + """ + } + + String eventInjectionConfiguration(String type, Collection events, long initial, long max) { + return """ + DaemonHealthStats stats = services.get(DaemonHealthStats.class) + GarbageCollectionMonitor monitor = stats.getGcMonitor() + long startTime = Time.clock().getCurrentTime() + ${injectEvents("monitor.get${type.capitalize()}Events()", events, initial, max)} + println "GC rate: " + stats.get${type.capitalize()}Stats().getGcRate() + println " % used: " + stats.get${type.capitalize()}Stats().getUsedPercent() + "%" + """ + } + + void waitForDaemonExpiration() { + buildFile << """ + import org.gradle.internal.event.ListenerManager + import org.gradle.launcher.daemon.server.expiry.DaemonExpirationListener + import org.gradle.launcher.daemon.server.expiry.DaemonExpirationResult + import java.util.concurrent.CountDownLatch + import java.util.concurrent.TimeUnit + + def latch = new CountDownLatch(1) + services.get(ListenerManager.class).addListener(new DaemonExpirationListener() { + void onExpirationEvent(DaemonExpirationResult result) { + latch.countDown() + } + }) + + injectEvents.doLast { latch.await(6, TimeUnit.SECONDS) } + """ + } + + String injectEvents(String getter, Collection events, long initial, long max) { + StringBuilder builder = new StringBuilder() + events.each { Map event -> + builder.append("${getter}.slideAndInsert(new GarbageCollectionEvent(startTime + ${fromSeconds(event.timeOffset)}, ${usageFrom(initial, max, event.poolUsage)}, ${event.gcCount}))\n") + } + return builder.toString() + } + + Collection eventsFor(long initial, long max, long leakRate, double gcRate) { + def events = [] + long usage = initial + long gcCount = 0 + 20.times { count -> + usage += leakRate + if (usage > max) { + usage = max + } + gcCount = (gcRate * count) as long + events << ["timeOffset": count, "poolUsage": usage, "gcCount": gcCount] + } + return events + } + + long fromMB(long sizeInMB) { + return sizeInMB * 1024 * 1024 + } + + long fromSeconds(long seconds) { + return seconds * 1000 + } + + String usageFrom(long initial, long max, long used) { + return "new MemoryUsage(${fromMB(initial)}, ${fromMB(used)}, ${fromMB(used)}, ${fromMB(max)})" + } +} diff --git a/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/server/health/DaemonHealthStats.java b/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/server/health/DaemonHealthStats.java index 05c5faa31413e..1585b031a380c 100644 --- a/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/server/health/DaemonHealthStats.java +++ b/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/server/health/DaemonHealthStats.java @@ -21,6 +21,7 @@ import org.gradle.internal.concurrent.ManagedScheduledExecutor; import org.gradle.internal.concurrent.Stoppable; import org.gradle.internal.util.NumberUtil; +import org.gradle.launcher.daemon.server.health.gc.DefaultGarbageCollectionMonitor; import org.gradle.launcher.daemon.server.health.gc.GarbageCollectionInfo; import org.gradle.launcher.daemon.server.health.gc.GarbageCollectionMonitor; import org.gradle.launcher.daemon.server.health.gc.GarbageCollectionStats; @@ -34,13 +35,13 @@ public class DaemonHealthStats implements Stoppable { private final DaemonRunningStats runningStats; private final ManagedScheduledExecutor scheduler; private final GarbageCollectionInfo gcInfo; - private final GarbageCollectionMonitor gcMonitor; + private GarbageCollectionMonitor gcMonitor; public DaemonHealthStats(DaemonRunningStats runningStats, GarbageCollectorMonitoringStrategy strategy, ExecutorFactory executorFactory) { this.runningStats = runningStats; this.scheduler = executorFactory.createScheduled("Daemon health stats", 1); this.gcInfo = new GarbageCollectionInfo(); - this.gcMonitor = new GarbageCollectionMonitor(strategy, scheduler); + this.gcMonitor = new DefaultGarbageCollectionMonitor(strategy, scheduler); } @VisibleForTesting @@ -51,6 +52,11 @@ public DaemonHealthStats(DaemonRunningStats runningStats, GarbageCollectorMonito this.gcMonitor = gcMonitor; } + @VisibleForTesting + public GarbageCollectionMonitor getGcMonitor() { + return gcMonitor; + } + @Override public void stop() { if (scheduler != null) { diff --git a/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/server/health/gc/DefaultGarbageCollectionMonitor.java b/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/server/health/gc/DefaultGarbageCollectionMonitor.java new file mode 100644 index 0000000000000..6ab8d4bff66c9 --- /dev/null +++ b/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/server/health/gc/DefaultGarbageCollectionMonitor.java @@ -0,0 +1,80 @@ +/* + * Copyright 2016 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.launcher.daemon.server.health.gc; + +import com.google.common.annotations.VisibleForTesting; +import org.gradle.api.specs.Spec; +import org.gradle.internal.time.Time; +import org.gradle.util.CollectionUtils; + +import java.lang.management.GarbageCollectorMXBean; +import java.lang.management.ManagementFactory; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; + +public class DefaultGarbageCollectionMonitor implements GarbageCollectionMonitor { + public static final String DISABLE_POLLING_SYSTEM_PROPERTY = "org.gradle.daemon.gc.polling.disabled"; + + private static final int POLL_INTERVAL_SECONDS = 1; + private static final int POLL_DELAY_SECONDS = 1; + private static final int EVENT_WINDOW = 20; + + private final SlidingWindow heapEvents; + private final SlidingWindow nonHeapEvents; + private final GarbageCollectorMonitoringStrategy gcStrategy; + private final ScheduledExecutorService pollingExecutor; + + public DefaultGarbageCollectionMonitor(GarbageCollectorMonitoringStrategy gcStrategy, ScheduledExecutorService pollingExecutor) { + this.pollingExecutor = pollingExecutor; + this.gcStrategy = gcStrategy; + this.heapEvents = new DefaultSlidingWindow(EVENT_WINDOW); + this.nonHeapEvents = new DefaultSlidingWindow(EVENT_WINDOW); + if (gcStrategy != GarbageCollectorMonitoringStrategy.UNKNOWN && !Boolean.getBoolean(DISABLE_POLLING_SYSTEM_PROPERTY)) { + pollForValues(); + } + } + + private void pollForValues() { + GarbageCollectorMXBean garbageCollectorMXBean = CollectionUtils.findFirst(ManagementFactory.getGarbageCollectorMXBeans(), new Spec() { + @Override + public boolean isSatisfiedBy(GarbageCollectorMXBean element) { + return element.getName().equals(gcStrategy.getGarbageCollectorName()); + } + }); + pollingExecutor.scheduleAtFixedRate(new GarbageCollectionCheck(Time.clock(), garbageCollectorMXBean, gcStrategy.getHeapPoolName(), heapEvents, gcStrategy.getNonHeapPoolName(), nonHeapEvents), POLL_DELAY_SECONDS, POLL_INTERVAL_SECONDS, TimeUnit.SECONDS); + } + + @Override + public GarbageCollectionStats getHeapStats() { + return GarbageCollectionStats.forHeap(heapEvents.snapshot()); + } + + @Override + public GarbageCollectionStats getNonHeapStats() { + return GarbageCollectionStats.forNonHeap(nonHeapEvents.snapshot()); + } + + @VisibleForTesting + public SlidingWindow getHeapEvents() { + return heapEvents; + } + + @VisibleForTesting + public SlidingWindow getNonHeapEvents() { + return nonHeapEvents; + } +} diff --git a/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/server/health/gc/GarbageCollectionMonitor.java b/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/server/health/gc/GarbageCollectionMonitor.java index 94c81df152dfa..f7339b9da07be 100644 --- a/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/server/health/gc/GarbageCollectionMonitor.java +++ b/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/server/health/gc/GarbageCollectionMonitor.java @@ -1,5 +1,5 @@ /* - * Copyright 2016 the original author or authors. + * Copyright 2019 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,50 +16,14 @@ package org.gradle.launcher.daemon.server.health.gc; -import org.gradle.api.specs.Spec; -import org.gradle.internal.time.Time; -import org.gradle.util.CollectionUtils; +public interface GarbageCollectionMonitor { + /** + * Returns a {@link GarbageCollectionStats} object for the tenured heap of the daemon process. + */ + GarbageCollectionStats getHeapStats(); -import java.lang.management.GarbageCollectorMXBean; -import java.lang.management.ManagementFactory; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; - -public class GarbageCollectionMonitor { - private static final int POLL_INTERVAL_SECONDS = 1; - private static final int POLL_DELAY_SECONDS = 1; - private static final int EVENT_WINDOW = 20; - - private final SlidingWindow heapEvents; - private final SlidingWindow nonHeapEvents; - private final GarbageCollectorMonitoringStrategy gcStrategy; - private final ScheduledExecutorService pollingExecutor; - - public GarbageCollectionMonitor(GarbageCollectorMonitoringStrategy gcStrategy, ScheduledExecutorService pollingExecutor) { - this.pollingExecutor = pollingExecutor; - this.gcStrategy = gcStrategy; - this.heapEvents = new DefaultSlidingWindow(EVENT_WINDOW); - this.nonHeapEvents = new DefaultSlidingWindow(EVENT_WINDOW); - if (gcStrategy != GarbageCollectorMonitoringStrategy.UNKNOWN) { - pollForValues(); - } - } - - private void pollForValues() { - GarbageCollectorMXBean garbageCollectorMXBean = CollectionUtils.findFirst(ManagementFactory.getGarbageCollectorMXBeans(), new Spec() { - @Override - public boolean isSatisfiedBy(GarbageCollectorMXBean element) { - return element.getName().equals(gcStrategy.getGarbageCollectorName()); - } - }); - pollingExecutor.scheduleAtFixedRate(new GarbageCollectionCheck(Time.clock(), garbageCollectorMXBean, gcStrategy.getHeapPoolName(), heapEvents, gcStrategy.getNonHeapPoolName(), nonHeapEvents), POLL_DELAY_SECONDS, POLL_INTERVAL_SECONDS, TimeUnit.SECONDS); - } - - public GarbageCollectionStats getHeapStats() { - return GarbageCollectionStats.forHeap(heapEvents.snapshot()); - } - - public GarbageCollectionStats getNonHeapStats() { - return GarbageCollectionStats.forNonHeap(nonHeapEvents.snapshot()); - } + /** + * Returns a {@link GarbageCollectionStats} object for the metaspace region of the daemon process. + */ + GarbageCollectionStats getNonHeapStats(); } diff --git a/subprojects/launcher/src/test/groovy/org/gradle/launcher/daemon/server/health/DaemonHealthStatsTest.groovy b/subprojects/launcher/src/test/groovy/org/gradle/launcher/daemon/server/health/DaemonHealthStatsTest.groovy index 08db6d2271d2e..402fbd0994319 100644 --- a/subprojects/launcher/src/test/groovy/org/gradle/launcher/daemon/server/health/DaemonHealthStatsTest.groovy +++ b/subprojects/launcher/src/test/groovy/org/gradle/launcher/daemon/server/health/DaemonHealthStatsTest.groovy @@ -18,7 +18,7 @@ package org.gradle.launcher.daemon.server.health import org.gradle.internal.event.DefaultListenerManager import org.gradle.launcher.daemon.server.health.gc.GarbageCollectionInfo -import org.gradle.launcher.daemon.server.health.gc.GarbageCollectionMonitor +import org.gradle.launcher.daemon.server.health.gc.DefaultGarbageCollectionMonitor import org.gradle.launcher.daemon.server.health.gc.GarbageCollectionStats import org.gradle.launcher.daemon.server.stats.DaemonRunningStats import spock.lang.Specification @@ -27,7 +27,7 @@ class DaemonHealthStatsTest extends Specification { def listenerManager = new DefaultListenerManager() def gcInfo = Stub(GarbageCollectionInfo) - def gcMonitor = Stub(GarbageCollectionMonitor) + def gcMonitor = Stub(DefaultGarbageCollectionMonitor) def runningStats = Stub(DaemonRunningStats) def healthStats = new DaemonHealthStats(runningStats, gcInfo, gcMonitor) diff --git a/subprojects/launcher/src/test/groovy/org/gradle/launcher/daemon/server/health/gc/GarbageCollectionMonitorTest.groovy b/subprojects/launcher/src/test/groovy/org/gradle/launcher/daemon/server/health/gc/GarbageCollectionMonitorTest.groovy index 66a4a6dfbf408..6c4c8b9b1966c 100644 --- a/subprojects/launcher/src/test/groovy/org/gradle/launcher/daemon/server/health/gc/GarbageCollectionMonitorTest.groovy +++ b/subprojects/launcher/src/test/groovy/org/gradle/launcher/daemon/server/health/gc/GarbageCollectionMonitorTest.groovy @@ -25,7 +25,7 @@ class GarbageCollectionMonitorTest extends Specification { def "does not schedule garbage collection check when GC strategy is unknown" () { when: - new GarbageCollectionMonitor(GarbageCollectorMonitoringStrategy.UNKNOWN, scheduledExecutorService) + new DefaultGarbageCollectionMonitor(GarbageCollectorMonitoringStrategy.UNKNOWN, scheduledExecutorService) then: 0 * scheduledExecutorService.scheduleAtFixedRate(_, _, _, _) @@ -33,7 +33,7 @@ class GarbageCollectionMonitorTest extends Specification { def "heap stats defaults to empty given unknown garbage collector"() { given: - def monitor = new GarbageCollectionMonitor(GarbageCollectorMonitoringStrategy.UNKNOWN, scheduledExecutorService) + def monitor = new DefaultGarbageCollectionMonitor(GarbageCollectorMonitoringStrategy.UNKNOWN, scheduledExecutorService) when: monitor.getHeapStats() @@ -44,7 +44,7 @@ class GarbageCollectionMonitorTest extends Specification { def "non-heap stats defaults to empty given unknown garbage collector"() { given: - def monitor = new GarbageCollectionMonitor(GarbageCollectorMonitoringStrategy.UNKNOWN, scheduledExecutorService) + def monitor = new DefaultGarbageCollectionMonitor(GarbageCollectorMonitoringStrategy.UNKNOWN, scheduledExecutorService) when: monitor.getNonHeapStats() diff --git a/subprojects/soak/src/integTest/groovy/org/gradle/launcher/daemon/DaemonPerformanceMonitoringSoakTest.groovy b/subprojects/soak/src/integTest/groovy/org/gradle/launcher/daemon/DaemonPerformanceMonitoringSoakTest.groovy index b97d73cfd5d5c..02608d0495784 100644 --- a/subprojects/soak/src/integTest/groovy/org/gradle/launcher/daemon/DaemonPerformanceMonitoringSoakTest.groovy +++ b/subprojects/soak/src/integTest/groovy/org/gradle/launcher/daemon/DaemonPerformanceMonitoringSoakTest.groovy @@ -94,88 +94,6 @@ class DaemonPerformanceMonitoringSoakTest extends DaemonMultiJdkIntegrationTest !daemonIsExpiredEagerly() } - @Ignore - def "when leak occurs while daemon is idle daemon is still expired"() { - // This is so the idle timeout expiration strategy doesn't kick in - // before the gc monitoring expires the daemon - executer.withDaemonIdleTimeoutSecs(300) - heapSize = "200m" - leakRate = 900 - - when: - leaksWhenIdle() - executer.withArguments("-Dorg.gradle.daemon.healthcheckinterval=1000") - executer.withBuildJvmOpts("-D${DaemonMemoryStatus.ENABLE_PERFORMANCE_MONITORING}=true", "-Xms128m", "-Xmx${heapSize}", "-Dorg.gradle.daemon.performance.logging=true") - executer.noExtraLogging() - run() - - then: - daemons.daemon.assertIdle() - - and: - String logText = daemons.daemon.log - ConcurrentTestUtil.poll(30) { - println daemons.daemon.log - logText - logText = daemons.daemon.log - daemons.daemon.assertStopped() - } - - and: - daemons.daemon.log.contains(DaemonStateCoordinator.DAEMON_WILL_STOP_MESSAGE) || daemons.daemon.log.contains(DaemonStateCoordinator.DAEMON_STOPPING_IMMEDIATELY_MESSAGE) - } - - @Ignore - def "when build leaks permgen space daemon is expired"() { - assumeTrue(version.vendor != JdkVendor.IBM) - - when: - setupBuildScript = permGenLeak - maxBuilds = 30 - heapSize = "200m" - leakRate = 3700 - - then: - daemonIsExpiredEagerly() - } - - @Ignore - def "detects a thrashing condition" () { - // This is so the idle timeout expiration strategy doesn't kick in - // before the gc monitoring expires the daemon - executer.withDaemonIdleTimeoutSecs(300) - heapSize = "200m" - leakRate = 1300 - - when: - leaksWithinOneBuild() - executer.withArguments("-Dorg.gradle.daemon.healthcheckinterval=1000", "--debug") - executer.withBuildJvmOpts("-D${DaemonMemoryStatus.ENABLE_PERFORMANCE_MONITORING}=true", "-Xms128m", "-Xmx${heapSize}", "-Dorg.gradle.daemon.performance.logging=true") - executer.noExtraLogging() - GradleHandle gradle = executer.start() - - then: - ConcurrentTestUtil.poll(10) { - daemons.daemon.assertBusy() - } - - when: - file("leak").createFile() - - then: - ConcurrentTestUtil.poll(60) { - daemons.daemon.assertStopped() - } - - and: - daemons.daemon.log.contains(DaemonStateCoordinator.DAEMON_STOPPING_IMMEDIATELY_MESSAGE) - - when: - ExecutionFailure failure = gradle.waitForFailure() - - then: - failure.assertHasDescription(DaemonStoppedException.MESSAGE + ": " + GcThrashingDaemonExpirationStrategy.EXPIRATION_REASON) - } - private boolean daemonIsExpiredEagerly() { def dataFile = file("stats") setupBuildScript() From d47b077df1849f5b8bc82b2191158ee689628006 Mon Sep 17 00:00:00 2001 From: Sterling Greene Date: Thu, 7 Mar 2019 11:55:23 -0500 Subject: [PATCH 382/853] Remove synchronization around all system property getters --- .../SystemPropertiesIntegrationTest.groovy | 6 +-- .../org/gradle/internal/SystemProperties.java | 16 +++--- .../internal/SystemPropertiesTest.groovy | 50 ------------------- ...avaHomeBasedJavaCompilerFactoryTest.groovy | 8 ++- .../http/DefaultSslContextFactory.java | 4 +- .../http/DefaultSslContextFactoryTest.groovy | 6 +-- 6 files changed, 15 insertions(+), 75 deletions(-) diff --git a/subprojects/base-services/src/integTest/groovy/org/gradle/internal/SystemPropertiesIntegrationTest.groovy b/subprojects/base-services/src/integTest/groovy/org/gradle/internal/SystemPropertiesIntegrationTest.groovy index 51e00381976d5..6f662b5142ca3 100644 --- a/subprojects/base-services/src/integTest/groovy/org/gradle/internal/SystemPropertiesIntegrationTest.groovy +++ b/subprojects/base-services/src/integTest/groovy/org/gradle/internal/SystemPropertiesIntegrationTest.groovy @@ -28,7 +28,7 @@ class SystemPropertiesIntegrationTest extends ConcurrentSpec { final int threadCount = 100 Factory factory = Mock() String factoryCreationResult = 'test' - File originalJavaHomeDir = SystemProperties.instance.javaHomeDir + File originalJavaHomeDir = new File(System.properties['java.home'] as String) File providedJavaHomeDir = temporaryFolder.file('my/test/java/home/toolprovider') when: @@ -43,10 +43,10 @@ class SystemPropertiesIntegrationTest extends ConcurrentSpec { then: threadCount * factory.create() >> { - assert SystemProperties.instance.javaHomeDir == providedJavaHomeDir + assert new File(System.properties['java.home'] as String) == providedJavaHomeDir factoryCreationResult } - assert SystemProperties.instance.javaHomeDir == originalJavaHomeDir + assert new File(System.properties['java.home'] as String) == originalJavaHomeDir } def "sets a system property for the duration of a Factory operation"() { diff --git a/subprojects/base-services/src/main/java/org/gradle/internal/SystemProperties.java b/subprojects/base-services/src/main/java/org/gradle/internal/SystemProperties.java index a4451f42c3286..7910c23d89da7 100644 --- a/subprojects/base-services/src/main/java/org/gradle/internal/SystemProperties.java +++ b/subprojects/base-services/src/main/java/org/gradle/internal/SystemProperties.java @@ -71,34 +71,30 @@ public static SystemProperties getInstance() { private SystemProperties() { } - public synchronized String getLineSeparator() { + public String getLineSeparator() { return System.getProperty("line.separator"); } - public synchronized String getJavaIoTmpDir() { + public String getJavaIoTmpDir() { return System.getProperty("java.io.tmpdir"); } - public synchronized String getUserHome() { + public String getUserHome() { return System.getProperty("user.home"); } - public synchronized String getUserName() { + public String getUserName() { return System.getProperty("user.name"); } - public synchronized String getJavaVersion() { + public String getJavaVersion() { return System.getProperty("java.version"); } - public synchronized File getCurrentDir() { + public File getCurrentDir() { return new File(System.getProperty("user.dir")); } - public synchronized File getJavaHomeDir() { - return new File(System.getProperty("java.home")); - } - /** * Creates instance for Factory implementation with the provided Java home directory. Setting the "java.home" system property is thread-safe * and is set back to the original value of "java.home" after the operation. diff --git a/subprojects/base-services/src/test/groovy/org/gradle/internal/SystemPropertiesTest.groovy b/subprojects/base-services/src/test/groovy/org/gradle/internal/SystemPropertiesTest.groovy index 3b9d52fdd8d99..5aeafffa95b3c 100644 --- a/subprojects/base-services/src/test/groovy/org/gradle/internal/SystemPropertiesTest.groovy +++ b/subprojects/base-services/src/test/groovy/org/gradle/internal/SystemPropertiesTest.groovy @@ -18,60 +18,10 @@ package org.gradle.internal import spock.lang.Specification -import java.util.concurrent.ConcurrentHashMap -import java.util.concurrent.CountDownLatch - class SystemPropertiesTest extends Specification { def "can be queried for standard system properties"() { expect: SystemProperties.instance.isStandardProperty("os.name") !SystemProperties.instance.isStandardProperty("foo.bar") } - - def "prohibits concurrent reads of Java Home while factory is busy"() { - def repeat = 100 - def initialJavaHomePath = SystemProperties.instance.javaHomeDir.path - def temporaryJavaHomePath = initialJavaHomePath + "-2" - - def valuesSeenByFactory = Collections.newSetFromMap(new ConcurrentHashMap()) - - def factory = new Factory() { - @Override - Object create() { - valuesSeenByFactory.add(SystemProperties.instance.javaHomeDir.path) - return new Object() - } - } - - def latch = new CountDownLatch(2) - - new Thread(new Runnable() { - @Override - void run() { - for (int i = 0; i < repeat; i++) { - SystemProperties.instance.withJavaHome(new File(temporaryJavaHomePath), factory) - } - latch.countDown() - } - }).start() - - def valuesSeenByAnotherThread = Collections.newSetFromMap(new ConcurrentHashMap()) - - new Thread(new Runnable() { - @Override - void run() { - for (int i = 0; i < repeat; i++) { - valuesSeenByAnotherThread.add(SystemProperties.instance.javaHomeDir.path) - } - - latch.countDown() - } - }).start() - - latch.await() - - expect: - valuesSeenByFactory == Collections.singleton(temporaryJavaHomePath) - valuesSeenByAnotherThread == Collections.singleton(initialJavaHomePath) - } } diff --git a/subprojects/language-java/src/test/groovy/org/gradle/api/internal/tasks/compile/JavaHomeBasedJavaCompilerFactoryTest.groovy b/subprojects/language-java/src/test/groovy/org/gradle/api/internal/tasks/compile/JavaHomeBasedJavaCompilerFactoryTest.groovy index 520d5f57bc8bd..b8ae8816b33d8 100644 --- a/subprojects/language-java/src/test/groovy/org/gradle/api/internal/tasks/compile/JavaHomeBasedJavaCompilerFactoryTest.groovy +++ b/subprojects/language-java/src/test/groovy/org/gradle/api/internal/tasks/compile/JavaHomeBasedJavaCompilerFactoryTest.groovy @@ -17,7 +17,6 @@ package org.gradle.api.internal.tasks.compile import org.gradle.internal.Factory -import org.gradle.internal.SystemProperties import org.gradle.test.fixtures.file.TestFile import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider import org.junit.Rule @@ -58,9 +57,8 @@ class JavaHomeBasedJavaCompilerFactoryTest extends Specification { } def "creates Java compiler for mismatching Java home directory"() { - File originalJavaHomeDir = SystemProperties.instance.javaHomeDir + File originalJavaHomeDir = new File(System.properties['java.home'] as String) TestFile realJavaHome = temporaryFolder.file('my/test/java/home/real') - TestFile javaHomeFromToolProvidersPointOfView = temporaryFolder.file('my/test/java/home/toolprovider') when: JavaCompiler expectedJavaCompiler = factory.create() @@ -68,10 +66,10 @@ class JavaHomeBasedJavaCompilerFactoryTest extends Specification { then: 1 * currentJvmJavaHomeFactory.create() >> realJavaHome 1 * systemJavaCompilerFactory.create() >> { - assert SystemProperties.instance.javaHomeDir == realJavaHome + assert new File(System.properties['java.home'] as String) == realJavaHome javaCompiler } javaCompiler == expectedJavaCompiler - originalJavaHomeDir == SystemProperties.instance.javaHomeDir + originalJavaHomeDir == new File(System.properties['java.home'] as String) } } diff --git a/subprojects/resources-http/src/main/java/org/gradle/internal/resource/transport/http/DefaultSslContextFactory.java b/subprojects/resources-http/src/main/java/org/gradle/internal/resource/transport/http/DefaultSslContextFactory.java index e62e34c691a5b..477b088876163 100644 --- a/subprojects/resources-http/src/main/java/org/gradle/internal/resource/transport/http/DefaultSslContextFactory.java +++ b/subprojects/resources-http/src/main/java/org/gradle/internal/resource/transport/http/DefaultSslContextFactory.java @@ -48,7 +48,8 @@ public class DefaultSslContextFactory implements SslContextFactory { "javax.net.ssl.keyStoreType", "javax.net.ssl.keyStore", "javax.net.ssl.keyStoreProvider", - "javax.net.ssl.keyStorePassword" + "javax.net.ssl.keyStorePassword", + "java.home" ); private LoadingCache, SSLContext> cache = CacheBuilder.newBuilder().softValues().build(new SslContextCacheLoader()); @@ -66,7 +67,6 @@ public Map create() { for (String prop : SSL_SYSTEM_PROPERTIES) { currentProperties.put(prop, System.getProperty(prop)); } - currentProperties.put("java.home", SystemProperties.getInstance().getJavaHomeDir().getPath()); return currentProperties; } }); diff --git a/subprojects/resources-http/src/test/groovy/org/gradle/internal/resource/transport/http/DefaultSslContextFactoryTest.groovy b/subprojects/resources-http/src/test/groovy/org/gradle/internal/resource/transport/http/DefaultSslContextFactoryTest.groovy index f15acfa4ef4b6..8fb49376e7f40 100644 --- a/subprojects/resources-http/src/test/groovy/org/gradle/internal/resource/transport/http/DefaultSslContextFactoryTest.groovy +++ b/subprojects/resources-http/src/test/groovy/org/gradle/internal/resource/transport/http/DefaultSslContextFactoryTest.groovy @@ -17,11 +17,7 @@ package org.gradle.internal.resource.transport.http import org.apache.http.ssl.SSLInitializationException - -import org.gradle.internal.SystemProperties - import spock.lang.Specification - /** * Tests loading of keystores and truststores corresponding to system * properties specified. @@ -31,7 +27,7 @@ class DefaultSslContextFactoryTest extends Specification { def loader void setup() { - props = ['java.home': SystemProperties.getInstance().javaHomeDir.path] + props = ['java.home': System.properties['java.home']] loader = new DefaultSslContextFactory.SslContextCacheLoader() } From 9805138408cb341c49c753f736e0a5ea99c929f0 Mon Sep 17 00:00:00 2001 From: Sterling Greene Date: Thu, 7 Mar 2019 09:14:54 -0500 Subject: [PATCH 383/853] Disable ktlint for generated code for now fixes #8687 --- .../PrecompiledScriptPluginIntegrationTest.kt | 15 +++++++++++---- .../gradle/kotlin/dsl/codegen/SourceFileHeader.kt | 2 ++ .../kotlin/dsl/codegen/GradleApiExtensionsTest.kt | 2 +- 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/subprojects/kotlin-dsl-integ-tests/src/integTest/kotlin/org/gradle/kotlin/dsl/integration/PrecompiledScriptPluginIntegrationTest.kt b/subprojects/kotlin-dsl-integ-tests/src/integTest/kotlin/org/gradle/kotlin/dsl/integration/PrecompiledScriptPluginIntegrationTest.kt index b256add8aed0a..c06f3f7b3e526 100644 --- a/subprojects/kotlin-dsl-integ-tests/src/integTest/kotlin/org/gradle/kotlin/dsl/integration/PrecompiledScriptPluginIntegrationTest.kt +++ b/subprojects/kotlin-dsl-integ-tests/src/integTest/kotlin/org/gradle/kotlin/dsl/integration/PrecompiledScriptPluginIntegrationTest.kt @@ -2,7 +2,6 @@ package org.gradle.kotlin.dsl.integration import org.gradle.kotlin.dsl.fixtures.normalisedPath import org.gradle.test.fixtures.file.LeaksFileHandles - import org.hamcrest.CoreMatchers.containsString import org.junit.Assert.assertFalse import org.junit.Assert.assertThat @@ -25,9 +24,17 @@ class PrecompiledScriptPluginIntegrationTest : AbstractPluginIntegrationTest() { $repositoriesBlock """) - withPrecompiledKotlinScript("plugin-without-package.gradle.kts", "\n") - withPrecompiledKotlinScript("plugins/plugin-with-package.gradle.kts", """ - package plugins + withPrecompiledKotlinScript("plugin-without-package.gradle.kts", """ + plugins { + org.gradle.base + } + """) + withPrecompiledKotlinScript("org/gradle/plugins/plugin-with-package.gradle.kts", """ + package org.gradle.plugins + + plugins { + org.gradle.base + } """) build("generateScriptPluginAdapters") diff --git a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/codegen/SourceFileHeader.kt b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/codegen/SourceFileHeader.kt index 1af04699c3efb..9cb30f1c51192 100644 --- a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/codegen/SourceFileHeader.kt +++ b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/codegen/SourceFileHeader.kt @@ -37,6 +37,8 @@ fun fileHeaderFor(packageName: String) = "ObjectPropertyName" ) +/* ktlint-disable */ + package $packageName """ diff --git a/subprojects/kotlin-dsl/src/test/kotlin/org/gradle/kotlin/dsl/codegen/GradleApiExtensionsTest.kt b/subprojects/kotlin-dsl/src/test/kotlin/org/gradle/kotlin/dsl/codegen/GradleApiExtensionsTest.kt index 03e5986f98aec..be2de1aeb3b28 100644 --- a/subprojects/kotlin-dsl/src/test/kotlin/org/gradle/kotlin/dsl/codegen/GradleApiExtensionsTest.kt +++ b/subprojects/kotlin-dsl/src/test/kotlin/org/gradle/kotlin/dsl/codegen/GradleApiExtensionsTest.kt @@ -65,7 +65,7 @@ class GradleApiExtensionsTest : TestWithClassPath() { ClassAndGroovyNamedArguments::class ) { - assertGeneratedJarHash("92614891520da2bd5eb0e4c28c672a39") + assertGeneratedJarHash("d15166f9f64f94a9bc0ef6cf4d3836af") } } From e475ca67a356c49745754f5ad8741e024e832e22 Mon Sep 17 00:00:00 2001 From: Stefan Wolf Date: Thu, 7 Mar 2019 18:06:31 +0100 Subject: [PATCH 384/853] Retry test on old Gradle version when Dispatcher is not ready (#8704) Fixes gradle/gradle-private#744 --- .../integtests/fixtures/RetryConditions.groovy | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/RetryConditions.groovy b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/RetryConditions.groovy index d54818091699d..d836db30f13d0 100644 --- a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/RetryConditions.groovy +++ b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/RetryConditions.groovy @@ -17,9 +17,12 @@ package org.gradle.integtests.fixtures import org.gradle.api.JavaVersion +import org.gradle.integtests.fixtures.daemon.DaemonLogsAnalyzer import org.gradle.util.GradleVersion import org.gradle.util.TestPrecondition +import javax.annotation.Nullable + class RetryConditions { static private final String[] FILES_TO_PRESERVE = ['reproducible-archives-init.gradle'] @@ -66,7 +69,7 @@ class RetryConditions { return shouldRetry(specification, failure, daemonsFixture) } - private static boolean shouldRetry(Object specification, Throwable failure, daemonsFixture) { + private static boolean shouldRetry(Object specification, Throwable failure, @Nullable DaemonLogsAnalyzer daemonsFixture) { String releasedGradleVersion = specification.hasProperty("releasedGradleVersion") ? specification.releasedGradleVersion : null def caughtGradleConnectionException = specification.hasProperty("caughtGradleConnectionException") ? specification.caughtGradleConnectionException : null @@ -129,6 +132,19 @@ class RetryConditions { return cleanProjectDir(specification) } + // known problem with Gradle versions < 3.5 + // See https://github.com/gradle/gradle-private/issues/744 + if (targetDistVersion < GradleVersion.version('3.5') && daemonsFixture != null && getRootCauseMessage(failure) == 'Build cancelled.') { + for (daemon in daemonsFixture.daemons) { + if (daemon.log.contains('Could not receive message from client.') + && daemon.log.contains('java.lang.NullPointerException') + && daemon.log.contains('org.gradle.launcher.daemon.server.exec.LogToClient')) { + println "Retrying test because the dispatcher was not ready for receiving a log event. Check log of daemon with PID ${daemon.context.pid}." + return cleanProjectDir(specification) + } + } + } + // sometime sockets are unexpectedly disappearing on daemon side (running on windows): https://github.com/gradle/gradle/issues/1111 didSocketDisappearOnWindows(failure, specification, daemonsFixture, targetDistVersion >= GradleVersion.version('3.0')) } From ed923aae5ce6066277fc5ad03806f244322bfb4e Mon Sep 17 00:00:00 2001 From: Jendrik Johannes Date: Wed, 6 Mar 2019 12:31:31 +0100 Subject: [PATCH 385/853] Add test to pin down failure behavior during worker startup --- .../child/BootstrapSecurityManagerTest.groovy | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/subprojects/workers/src/test/groovy/org/gradle/process/internal/worker/child/BootstrapSecurityManagerTest.groovy b/subprojects/workers/src/test/groovy/org/gradle/process/internal/worker/child/BootstrapSecurityManagerTest.groovy index 734e0bc9c2a21..76af46bd8c02e 100644 --- a/subprojects/workers/src/test/groovy/org/gradle/process/internal/worker/child/BootstrapSecurityManagerTest.groovy +++ b/subprojects/workers/src/test/groovy/org/gradle/process/internal/worker/child/BootstrapSecurityManagerTest.groovy @@ -67,6 +67,24 @@ class BootstrapSecurityManagerTest extends Specification { System.getProperty("java.class.path") == [entry1.absolutePath, entry2.absolutePath].join(File.pathSeparator) } + def "fails with proper error message if System.in is not delivering all expected data"() { + given: + def incompleteStream = new ByteArrayOutputStream() + def dataOut = new DataOutputStream(new EncodedStream.EncodedOutput(incompleteStream)) + dataOut.writeInt(1) // expect one classpath entry + dataOut.write(1234) // but the entry is not a complete UTF-8 encoded String + + System.in = new ByteArrayInputStream(incompleteStream.toByteArray()) + + when: + new BootstrapSecurityManager(new TestClassLoader()).checkPermission(new AllPermission()) + + then: + RuntimeException e = thrown() + e.message == "Could not initialise system classpath." + e.cause instanceof EOFException + } + def "installs custom SecurityManager"() { URLClassLoader cl = new URLClassLoader([] as URL[], getClass().classLoader) From 5fd8ae77fb0b6eda6cf484154560e779fe3ffd7d Mon Sep 17 00:00:00 2001 From: Jendrik Johannes Date: Wed, 6 Mar 2019 12:32:49 +0100 Subject: [PATCH 386/853] Allow PROCESS workers to print startup exceptions if interrupted early --- .../org/gradle/api/tasks/TaskTimeoutIntegrationTest.groovy | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/TaskTimeoutIntegrationTest.groovy b/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/TaskTimeoutIntegrationTest.groovy index e7b88f6cb3046..2e1343eb7463f 100644 --- a/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/TaskTimeoutIntegrationTest.groovy +++ b/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/TaskTimeoutIntegrationTest.groovy @@ -152,6 +152,10 @@ class TaskTimeoutIntegrationTest extends AbstractIntegrationSpec { @Unroll def "timeout stops long running work items with #isolationMode isolation"() { given: + if (isolationMode == IsolationMode.PROCESS) { + // worker starting threads can be interrupted during worker startup and cause a 'Could not initialise system classpath' exception. + executer.withStackTraceChecksDisabled() + } buildFile << """ import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; @@ -193,6 +197,9 @@ class TaskTimeoutIntegrationTest extends AbstractIntegrationSpec { fails "block" failure.assertHasDescription("Execution failed for task ':block'.") failure.assertHasCause("Timeout has been exceeded") + if (isolationMode == IsolationMode.PROCESS && failure.output.contains("Caused by:")) { + assert failure.output.contains("Error occurred during initialization of VM") + } where: isolationMode << IsolationMode.values() From 091d9f3405e8f4efd0ac93372567a8191a9d0423 Mon Sep 17 00:00:00 2001 From: Jendrik Johannes Date: Thu, 7 Mar 2019 18:07:19 +0100 Subject: [PATCH 387/853] Link to issue for improving the current behavior tolerated by the test --- .../org/gradle/api/tasks/TaskTimeoutIntegrationTest.groovy | 1 + 1 file changed, 1 insertion(+) diff --git a/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/TaskTimeoutIntegrationTest.groovy b/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/TaskTimeoutIntegrationTest.groovy index 2e1343eb7463f..8bca409b81f3a 100644 --- a/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/TaskTimeoutIntegrationTest.groovy +++ b/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/TaskTimeoutIntegrationTest.groovy @@ -154,6 +154,7 @@ class TaskTimeoutIntegrationTest extends AbstractIntegrationSpec { given: if (isolationMode == IsolationMode.PROCESS) { // worker starting threads can be interrupted during worker startup and cause a 'Could not initialise system classpath' exception. + // See: https://github.com/gradle/gradle/issues/8699 executer.withStackTraceChecksDisabled() } buildFile << """ From 52f274b99e25a92f26949eb393160e5a27344955 Mon Sep 17 00:00:00 2001 From: Cedric Champeau Date: Thu, 7 Mar 2019 15:16:25 +0100 Subject: [PATCH 388/853] Fix Java usage disambiguation rules This commit makes sure that if for an API, we have 2 runtime candidates, we select the most appropriate runtime. This happened in a Kotlin test project. --- .../artifacts/JavaEcosystemSupport.java | 4 ++ .../api/plugins/JavaBasePluginTest.groovy | 42 +++++++++++++++++++ 2 files changed, 46 insertions(+) diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/artifacts/JavaEcosystemSupport.java b/subprojects/core/src/main/java/org/gradle/api/internal/artifacts/JavaEcosystemSupport.java index 0c044c5b66d20..84c37aecfe2fd 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/artifacts/JavaEcosystemSupport.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/artifacts/JavaEcosystemSupport.java @@ -140,6 +140,10 @@ public void execute(MultipleCandidatesDetails details) { } else if (candidateValues.contains(javaApi)) { // Prefer the API over the runtime when the API has been requested details.closestMatch(javaApi); + } else if (candidateValues.contains(javaRuntimeClasses)) { + details.closestMatch(javaRuntimeClasses); + } else if (candidateValues.contains(javaRuntimeJars)) { + details.closestMatch(javaRuntimeJars); } } else if (runtimeVariants.contains(consumerValue)) { // we're asking for a runtime variant, but no exact match was found diff --git a/subprojects/plugins/src/test/groovy/org/gradle/api/plugins/JavaBasePluginTest.groovy b/subprojects/plugins/src/test/groovy/org/gradle/api/plugins/JavaBasePluginTest.groovy index e3314e95f0c09..96a5d2d0eba29 100644 --- a/subprojects/plugins/src/test/groovy/org/gradle/api/plugins/JavaBasePluginTest.groovy +++ b/subprojects/plugins/src/test/groovy/org/gradle/api/plugins/JavaBasePluginTest.groovy @@ -18,6 +18,7 @@ package org.gradle.api.plugins import org.gradle.api.DefaultTask import org.gradle.api.JavaVersion import org.gradle.api.attributes.CompatibilityCheckDetails +import org.gradle.api.attributes.MultipleCandidatesDetails import org.gradle.api.attributes.Usage import org.gradle.api.internal.artifacts.JavaEcosystemSupport import org.gradle.api.reporting.ReportingExtension @@ -37,7 +38,9 @@ import org.gradle.platform.base.BinarySpec import org.gradle.test.fixtures.AbstractProjectBuilderSpec import org.gradle.test.fixtures.file.TestFile import org.gradle.util.SetSystemProperties +import org.gradle.util.TestUtil import org.junit.Rule +import spock.lang.Issue import spock.lang.Unroll import static org.gradle.api.file.FileCollectionMatchers.sameCollection @@ -500,4 +503,43 @@ class JavaBasePluginTest extends AbstractProjectBuilderSpec { Usage.JAVA_RUNTIME_JARS | Usage.JAVA_RUNTIME_RESOURCES | false Usage.JAVA_RUNTIME_JARS | Usage.JAVA_RUNTIME_JARS | true } + + @Issue("gradle/gradle#8700") + @Unroll + def "check default disambiguation rules (consumer=#consumer, candidates=#candidates, selected=#preferred)"() { + given: + JavaEcosystemSupport.UsageDisambiguationRules rules = new JavaEcosystemSupport.UsageDisambiguationRules( + usage(Usage.JAVA_API), + usage(Usage.JAVA_API_JARS), + usage(Usage.JAVA_API_CLASSES), + usage(Usage.JAVA_RUNTIME), + usage(Usage.JAVA_RUNTIME_JARS), + usage(Usage.JAVA_RUNTIME_CLASSES), + usage(Usage.JAVA_RUNTIME_RESOURCES) + ) + MultipleCandidatesDetails details = Mock() + + when: + rules.execute(details) + + then: + 1 * details.getConsumerValue() >> usage(consumer) + 1 * details.getCandidateValues() >> candidates.collect { usage(it) } + 1 * details.closestMatch(usage(preferred)) + + where: // not exhaustive, tests pathological cases + consumer | candidates | preferred + Usage.JAVA_API | [Usage.JAVA_API_JARS, Usage.JAVA_API_CLASSES] | Usage.JAVA_API_CLASSES + Usage.JAVA_API | [Usage.JAVA_RUNTIME_CLASSES, Usage.JAVA_API_CLASSES] | Usage.JAVA_API_CLASSES + Usage.JAVA_API | [Usage.JAVA_RUNTIME_CLASSES, Usage.JAVA_RUNTIME_JARS] | Usage.JAVA_RUNTIME_CLASSES + Usage.JAVA_API | [Usage.JAVA_API_JARS, Usage.JAVA_RUNTIME_JARS] | Usage.JAVA_API_JARS + + Usage.JAVA_RUNTIME | [Usage.JAVA_RUNTIME, Usage.JAVA_RUNTIME_JARS] | Usage.JAVA_RUNTIME + Usage.JAVA_RUNTIME_JARS | [Usage.JAVA_RUNTIME, Usage.JAVA_RUNTIME_JARS] | Usage.JAVA_RUNTIME_JARS + + } + + private Usage usage(String value) { + TestUtil.objectFactory().named(Usage, value) + } } From 2c34adddc6b059f2ba35c078e7e71bf275efbb35 Mon Sep 17 00:00:00 2001 From: Gradleware Git Bot Date: Thu, 7 Mar 2019 21:38:24 +0100 Subject: [PATCH 389/853] Publish 5.3-20190307202351+0000 --- released-versions.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/released-versions.json b/released-versions.json index 6b45a43480cb6..9b1f06278da81 100644 --- a/released-versions.json +++ b/released-versions.json @@ -1,7 +1,7 @@ { "latestReleaseSnapshot": { - "version": "5.3-20190307012429+0000", - "buildTime": "20190307012429+0000" + "version": "5.3-20190307202351+0000", + "buildTime": "20190307202351+0000" }, "latestRc": { "version": "5.3-rc-1", From 8400bc7b8403f22d581ca6c5d00263e2db5cba89 Mon Sep 17 00:00:00 2001 From: Sterling Greene Date: Thu, 7 Mar 2019 16:16:09 -0500 Subject: [PATCH 390/853] Bump to latest nightly --- gradle/wrapper/gradle-wrapper.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index f632acc7edeb1..3447790fc96de 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions-snapshots/gradle-5.3-20190301232024+0000-bin.zip +distributionUrl=https\://services.gradle.org/distributions-snapshots/gradle-5.3-20190307202351+0000-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists From 62f54639872548b18531f49832b1dfa8f9cca20a Mon Sep 17 00:00:00 2001 From: Gary Hale Date: Thu, 7 Mar 2019 16:25:54 -0500 Subject: [PATCH 391/853] Run simulated tests against all garbage collectors --- .../daemon}/JavaGarbageCollector.groovy | 22 +---- ...CollectionMonitoringIntegrationTest.groovy | 83 +++++++++++++++- ...DaemonPerformanceMonitoringCoverage.groovy | 2 +- ...DaemonPerformanceMonitoringSoakTest.groovy | 95 ------------------- .../FullyQualifiedGarbageCollector.groovy | 1 + 5 files changed, 86 insertions(+), 117 deletions(-) rename subprojects/{soak/src/testFixtures/groovy/org/gradle/launcher/daemon/fixtures => internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/daemon}/JavaGarbageCollector.groovy (59%) diff --git a/subprojects/soak/src/testFixtures/groovy/org/gradle/launcher/daemon/fixtures/JavaGarbageCollector.groovy b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/daemon/JavaGarbageCollector.groovy similarity index 59% rename from subprojects/soak/src/testFixtures/groovy/org/gradle/launcher/daemon/fixtures/JavaGarbageCollector.groovy rename to subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/daemon/JavaGarbageCollector.groovy index 1862aefbb0dc7..f522733f60883 100644 --- a/subprojects/soak/src/testFixtures/groovy/org/gradle/launcher/daemon/fixtures/JavaGarbageCollector.groovy +++ b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/daemon/JavaGarbageCollector.groovy @@ -1,5 +1,5 @@ /* - * Copyright 2016 the original author or authors. + * Copyright 2019 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,9 +14,9 @@ * limitations under the License. */ -package org.gradle.launcher.daemon.fixtures; +package org.gradle.integtests.fixtures.daemon -public enum JavaGarbageCollector { +enum JavaGarbageCollector { ORACLE_PARALLEL_CMS("-XX:+UseConcMarkSweepGC"), ORACLE_SERIAL9("-XX:+UseSerialGC"), ORACLE_G1("-XX:+UnlockExperimentalVMOptions -XX:+UseG1GC"), @@ -29,21 +29,7 @@ public enum JavaGarbageCollector { this.jvmArgs = jvmArgs } - static JavaGarbageCollector from(JdkVendor vendor, String gcName) { - if (vendor.equals(JdkVendor.IBM)) { - IBM_ALL - } else if (gcName.equals("PS MarkSweep")) { - ORACLE_PARALLEL_CMS - } else if (gcName.equals("MarkSweepCompact")) { - ORACLE_SERIAL9 - } else if (gcName.equals("G1 Old Generation")) { - ORACLE_G1 - } else { - UNKNOWN - } - } - - public String getJvmArgs() { + String getJvmArgs() { jvmArgs } } diff --git a/subprojects/launcher/src/integTest/groovy/org/gradle/launcher/daemon/server/health/gc/GarbageCollectionMonitoringIntegrationTest.groovy b/subprojects/launcher/src/integTest/groovy/org/gradle/launcher/daemon/server/health/gc/GarbageCollectionMonitoringIntegrationTest.groovy index 9e0507e19c163..c06f1790cd9c7 100644 --- a/subprojects/launcher/src/integTest/groovy/org/gradle/launcher/daemon/server/health/gc/GarbageCollectionMonitoringIntegrationTest.groovy +++ b/subprojects/launcher/src/integTest/groovy/org/gradle/launcher/daemon/server/health/gc/GarbageCollectionMonitoringIntegrationTest.groovy @@ -16,20 +16,31 @@ package org.gradle.launcher.daemon.server.health.gc +import org.gradle.integtests.fixtures.MultiVersionSpecRunner +import org.gradle.integtests.fixtures.TargetCoverage import org.gradle.integtests.fixtures.daemon.DaemonIntegrationSpec +import org.gradle.integtests.fixtures.daemon.JavaGarbageCollector import org.gradle.launcher.daemon.server.health.DaemonMemoryStatus +import org.gradle.util.TestPrecondition +import org.junit.runner.RunWith import static org.gradle.launcher.daemon.server.DaemonStateCoordinator.DAEMON_STOPPING_IMMEDIATELY_MESSAGE import static org.gradle.launcher.daemon.server.DaemonStateCoordinator.DAEMON_WILL_STOP_MESSAGE +@RunWith(MultiVersionSpecRunner) +@TargetCoverage({garbageCollectors}) class GarbageCollectionMonitoringIntegrationTest extends DaemonIntegrationSpec { + static def version + GarbageCollectorUnderTest garbageCollector = version + def setup() { + executer.withBuildJvmOpts(garbageCollector.configuration.jvmArgs.split(" ")) executer.withEnvironmentVars(JAVA_TOOL_OPTIONS: "-D${DefaultGarbageCollectionMonitor.DISABLE_POLLING_SYSTEM_PROPERTY}=true -D${DaemonMemoryStatus.ENABLE_PERFORMANCE_MONITORING}=true") } def "expires daemon when heap leaks slowly"() { given: - configureGarbageCollectionHeapEventsFor(256, 512, 35, 1.8) + configureGarbageCollectionHeapEventsFor(256, 512, 35, garbageCollector.monitoringStrategy.gcRateThreshold + 0.2) when: run "injectEvents" @@ -43,7 +54,7 @@ class GarbageCollectionMonitoringIntegrationTest extends DaemonIntegrationSpec { def "expires daemon immediately when garbage collector is thrashing"() { given: - configureGarbageCollectionHeapEventsFor(256, 512, 100, 5) + configureGarbageCollectionHeapEventsFor(256, 512, 100, garbageCollector.monitoringStrategy.thrashingThreshold + 0.2) waitForDaemonExpiration() when: @@ -62,7 +73,7 @@ class GarbageCollectionMonitoringIntegrationTest extends DaemonIntegrationSpec { def "expires daemon when heap leaks while daemon is idle"() { def initial = 256 def max = 512 - def events = eventsFor(initial, max, 35, 1.8) + def events = eventsFor(initial, max, 35, garbageCollector.monitoringStrategy.gcRateThreshold + 0.2) def initScript = file("init.gradle") initScript << """ ${injectionImports} @@ -101,6 +112,39 @@ class GarbageCollectionMonitoringIntegrationTest extends DaemonIntegrationSpec { daemons.daemon.log.contains(DAEMON_WILL_STOP_MESSAGE) } + def "does not expire daemon when leak does not consume heap threshold"() { + given: + configureGarbageCollectionHeapEventsFor(256, 512, 5, garbageCollector.monitoringStrategy.gcRateThreshold + 0.2) + + when: + run "injectEvents" + + then: + daemons.daemon.becomesIdle() + } + + def "does not expire daemon when leak does not cause excessive garbage collection"() { + given: + configureGarbageCollectionHeapEventsFor(256, 512, 35, garbageCollector.monitoringStrategy.gcRateThreshold - 0.2) + + when: + run "injectEvents" + + then: + daemons.daemon.becomesIdle() + } + + def "does not expire daemon when leak does not consume metaspace threshold"() { + given: + configureGarbageCollectionNonHeapEventsFor(256, 512, 5, 0) + + when: + run "injectEvents" + + then: + daemons.daemon.becomesIdle() + } + void configureGarbageCollectionHeapEventsFor(long initial, long max, long leakRate, double gcRate) { configureGarbageCollectionEvents("heap", initial, max, leakRate, gcRate) } @@ -171,6 +215,11 @@ class GarbageCollectionMonitoringIntegrationTest extends DaemonIntegrationSpec { return builder.toString() } + /** + * Generates garbage collection events starting at initial heap size (MB) and increasing by + * leakRate (MB) for every event, registering a variable number of garbage collections + * according to gcRate. Heap usage will cap at max. + */ Collection eventsFor(long initial, long max, long leakRate, double gcRate) { def events = [] long usage = initial @@ -197,4 +246,32 @@ class GarbageCollectionMonitoringIntegrationTest extends DaemonIntegrationSpec { String usageFrom(long initial, long max, long used) { return "new MemoryUsage(${fromMB(initial)}, ${fromMB(used)}, ${fromMB(used)}, ${fromMB(max)})" } + + static List getGarbageCollectors() { + if (TestPrecondition.JDK_IBM.fulfilled) { + return [ new GarbageCollectorUnderTest(JavaGarbageCollector.IBM_ALL, GarbageCollectorMonitoringStrategy.IBM_ALL) ] + } else { + return [ + new GarbageCollectorUnderTest(JavaGarbageCollector.ORACLE_PARALLEL_CMS, GarbageCollectorMonitoringStrategy.ORACLE_PARALLEL_CMS), + new GarbageCollectorUnderTest(JavaGarbageCollector.ORACLE_SERIAL9, GarbageCollectorMonitoringStrategy.ORACLE_SERIAL), + new GarbageCollectorUnderTest(JavaGarbageCollector.ORACLE_G1, GarbageCollectorMonitoringStrategy.ORACLE_G1) + ] + } + } + + static class GarbageCollectorUnderTest { + final JavaGarbageCollector configuration + final GarbageCollectorMonitoringStrategy monitoringStrategy + + GarbageCollectorUnderTest(JavaGarbageCollector configuration, GarbageCollectorMonitoringStrategy monitoringStrategy) { + this.configuration = configuration + this.monitoringStrategy = monitoringStrategy + } + + + @Override + public String toString() { + return configuration.name() + } + } } diff --git a/subprojects/soak/src/integTest/groovy/org/gradle/launcher/daemon/DaemonPerformanceMonitoringCoverage.groovy b/subprojects/soak/src/integTest/groovy/org/gradle/launcher/daemon/DaemonPerformanceMonitoringCoverage.groovy index 619396cfadeec..8fbe5954b5ade 100644 --- a/subprojects/soak/src/integTest/groovy/org/gradle/launcher/daemon/DaemonPerformanceMonitoringCoverage.groovy +++ b/subprojects/soak/src/integTest/groovy/org/gradle/launcher/daemon/DaemonPerformanceMonitoringCoverage.groovy @@ -18,7 +18,7 @@ package org.gradle.launcher.daemon import org.gradle.launcher.daemon.fixtures.FullyQualifiedGarbageCollector -import static org.gradle.launcher.daemon.fixtures.JavaGarbageCollector.* +import static org.gradle.integtests.fixtures.daemon.JavaGarbageCollector.* import static org.gradle.launcher.daemon.fixtures.JdkVendor.* class DaemonPerformanceMonitoringCoverage { diff --git a/subprojects/soak/src/integTest/groovy/org/gradle/launcher/daemon/DaemonPerformanceMonitoringSoakTest.groovy b/subprojects/soak/src/integTest/groovy/org/gradle/launcher/daemon/DaemonPerformanceMonitoringSoakTest.groovy index 02608d0495784..0f5e6100f67d4 100644 --- a/subprojects/soak/src/integTest/groovy/org/gradle/launcher/daemon/DaemonPerformanceMonitoringSoakTest.groovy +++ b/subprojects/soak/src/integTest/groovy/org/gradle/launcher/daemon/DaemonPerformanceMonitoringSoakTest.groovy @@ -17,22 +17,13 @@ package org.gradle.launcher.daemon import org.gradle.integtests.fixtures.TargetCoverage -import org.gradle.integtests.fixtures.executer.ExecutionFailure import org.gradle.integtests.fixtures.executer.GradleHandle import org.gradle.launcher.daemon.fixtures.DaemonMultiJdkIntegrationTest -import org.gradle.launcher.daemon.fixtures.JdkVendor -import org.gradle.launcher.daemon.server.DaemonStateCoordinator -import org.gradle.launcher.daemon.server.api.DaemonStoppedException import org.gradle.launcher.daemon.server.health.DaemonMemoryStatus -import org.gradle.launcher.daemon.server.health.GcThrashingDaemonExpirationStrategy import org.gradle.soak.categories.SoakTest -import org.gradle.test.fixtures.ConcurrentTestUtil import org.junit.experimental.categories.Category -import spock.lang.Ignore import spock.lang.Unroll -import static org.junit.Assume.assumeTrue - @Category(SoakTest) @TargetCoverage({DaemonPerformanceMonitoringCoverage.ALL_VERSIONS}) class DaemonPerformanceMonitoringSoakTest extends DaemonMultiJdkIntegrationTest { @@ -159,92 +150,6 @@ class DaemonPerformanceMonitoringSoakTest extends DaemonMultiJdkIntegrationTest """ } - private final Closure leaksWhenIdle = { - buildFile << """ - class State { - static int x - static map = [:] - } - State.x++ - - new Thread().start { - while (true) { - logger.warn "leaking some heap" - - //simulate normal collectible objects - 5000.times { - State.map.put(it, "foo" * ${leakRate}) - } - - //simulate the leak - 1000.times { - State.map.put(UUID.randomUUID(), "foo" * ${leakRate}) - } - sleep(750) - } - } - """ - } - - private final Closure permGenLeak = { - leakRate.times { - file("buildSrc/src/main/java/Generated${it}.java") << """ - public class Generated${it} { } - """ - } - buildFile << """ - import java.net.URLClassLoader - - class State { - static int x - static map = [:] - } - State.x++ - - //simulate normal perm gen usage - 5.times { - ClassLoader classLoader1 = new URLClassLoader(buildscript.classLoader.URLs) - ${leakRate}.times { - classLoader1.loadClass("Generated\${it}") - } - State.map.put("CL${it}", classLoader1) - } - - //simulate the leak - ClassLoader classLoader2 = new URLClassLoader(buildscript.classLoader.URLs) - ${leakRate}.times { - classLoader2.loadClass("Generated\${it}") - } - State.map.put(UUID.randomUUID(), classLoader2) - - println "Build: " + State.x - """ - } - - private final Closure leaksWithinOneBuild = { - buildFile << """ - def map = [:] - - while (true) { - if (file("leak").exists()) { - logger.debug "leaking some heap" - //simulate normal collectible objects - 10000.times { - map.put(it, "foo" * ${leakRate}) - } - - //simulate the leak - 1000.times { - map.put(UUID.randomUUID(), "foo" * ${leakRate}) - } - } else { - logger.warn "waiting for leak to start" - } - sleep 1000 - } - """ - } - String logJdk() { return """logger.warn("Build is running with JDK: \${System.getProperty('java.home')}")""" } diff --git a/subprojects/soak/src/testFixtures/groovy/org/gradle/launcher/daemon/fixtures/FullyQualifiedGarbageCollector.groovy b/subprojects/soak/src/testFixtures/groovy/org/gradle/launcher/daemon/fixtures/FullyQualifiedGarbageCollector.groovy index 831bb484990ee..66192ee07c922 100644 --- a/subprojects/soak/src/testFixtures/groovy/org/gradle/launcher/daemon/fixtures/FullyQualifiedGarbageCollector.groovy +++ b/subprojects/soak/src/testFixtures/groovy/org/gradle/launcher/daemon/fixtures/FullyQualifiedGarbageCollector.groovy @@ -17,6 +17,7 @@ package org.gradle.launcher.daemon.fixtures import org.gradle.api.JavaVersion +import org.gradle.integtests.fixtures.daemon.JavaGarbageCollector class FullyQualifiedGarbageCollector implements Comparable { JdkVendor vendor From dc28e056f20126b92ee6b9c4cec3e5ed40ece69d Mon Sep 17 00:00:00 2001 From: Stefan Wolf Date: Thu, 7 Mar 2019 17:06:00 +0100 Subject: [PATCH 392/853] Refactor promotion project --- .teamcity/Gradle_Promotion/Project.kt | 54 ++++++++++----- .../buildTypes/BasePromoteSnapshot.kt | 65 +++++++++++++++++++ .../buildTypes/BasePromotionBuildType.kt | 38 +++++++++++ .../Gradle_Promotion_FinalRelease.kt | 52 --------------- ...e_Promotion_MasterNightlySnapshotManual.kt | 47 -------------- .../Gradle_Promotion_MilestoneMaster.kt | 52 --------------- ..._PublishBranchSnapshotFromQuickFeedback.kt | 51 --------------- ...motion_ReleaseSnapshotFromQuickFeedback.kt | 46 ------------- ...terSanityCheck.kt => MasterSanityCheck.kt} | 8 ++- .../PromoteBranchSnapshotFromQuickFeedback.kt | 40 ++++++++++++ .../buildTypes/PromoteNightlySnapshot.kt | 37 +++++++++++ .../buildTypes/PromoteRelease.kt | 58 +++++++++++++++++ .../buildTypes/PromoteSnapshot.kt | 25 +++++++ .../PromoteSnapshotFromQuickFeedback.kt | 24 +++++++ ...rtReleaseCycle.kt => StartReleaseCycle.kt} | 34 ++++++---- ...eCycleTest.kt => StartReleaseCycleTest.kt} | 30 +++++---- .teamcity/Gradle_Promotion/buildTypes/bt39.kt | 60 ----------------- .teamcity/Gradle_Promotion/buildTypes/bt60.kt | 52 --------------- .teamcity/Gradle_Promotion/buildTypes/bt61.kt | 58 ----------------- 19 files changed, 371 insertions(+), 460 deletions(-) create mode 100644 .teamcity/Gradle_Promotion/buildTypes/BasePromoteSnapshot.kt create mode 100644 .teamcity/Gradle_Promotion/buildTypes/BasePromotionBuildType.kt delete mode 100644 .teamcity/Gradle_Promotion/buildTypes/Gradle_Promotion_FinalRelease.kt delete mode 100644 .teamcity/Gradle_Promotion/buildTypes/Gradle_Promotion_MasterNightlySnapshotManual.kt delete mode 100644 .teamcity/Gradle_Promotion/buildTypes/Gradle_Promotion_MilestoneMaster.kt delete mode 100644 .teamcity/Gradle_Promotion/buildTypes/Gradle_Promotion_PublishBranchSnapshotFromQuickFeedback.kt delete mode 100644 .teamcity/Gradle_Promotion/buildTypes/Gradle_Promotion_ReleaseSnapshotFromQuickFeedback.kt rename .teamcity/Gradle_Promotion/buildTypes/{Gradle_Promotion_MasterSanityCheck.kt => MasterSanityCheck.kt} (79%) create mode 100644 .teamcity/Gradle_Promotion/buildTypes/PromoteBranchSnapshotFromQuickFeedback.kt create mode 100644 .teamcity/Gradle_Promotion/buildTypes/PromoteNightlySnapshot.kt create mode 100644 .teamcity/Gradle_Promotion/buildTypes/PromoteRelease.kt create mode 100644 .teamcity/Gradle_Promotion/buildTypes/PromoteSnapshot.kt create mode 100644 .teamcity/Gradle_Promotion/buildTypes/PromoteSnapshotFromQuickFeedback.kt rename .teamcity/Gradle_Promotion/buildTypes/{Gradle_Promotion_StartReleaseCycle.kt => StartReleaseCycle.kt} (66%) rename .teamcity/Gradle_Promotion/buildTypes/{Gradle_Promotion_AllBranchesStartReleaseCycleTest.kt => StartReleaseCycleTest.kt} (53%) delete mode 100644 .teamcity/Gradle_Promotion/buildTypes/bt39.kt delete mode 100644 .teamcity/Gradle_Promotion/buildTypes/bt60.kt delete mode 100644 .teamcity/Gradle_Promotion/buildTypes/bt61.kt diff --git a/.teamcity/Gradle_Promotion/Project.kt b/.teamcity/Gradle_Promotion/Project.kt index 518ae023dc530..3a480a524f007 100644 --- a/.teamcity/Gradle_Promotion/Project.kt +++ b/.teamcity/Gradle_Promotion/Project.kt @@ -1,8 +1,16 @@ package Gradle_Promotion -import Gradle_Promotion.buildTypes.* -import Gradle_Promotion.vcsRoots.* -import jetbrains.buildServer.configs.kotlin.v2018_2.* +import Gradle_Promotion.buildTypes.MasterSanityCheck +import Gradle_Promotion.buildTypes.PromoteBranchSnapshotFromQuickFeedback +import Gradle_Promotion.buildTypes.PromoteFinalRelease +import Gradle_Promotion.buildTypes.PromoteMilestone +import Gradle_Promotion.buildTypes.PromoteNightlySnapshot +import Gradle_Promotion.buildTypes.PromoteReleaseCandidate +import Gradle_Promotion.buildTypes.PromoteSnapshotFromQuickFeedback +import Gradle_Promotion.buildTypes.StartReleaseCycle +import Gradle_Promotion.buildTypes.StartReleaseCycleTest +import Gradle_Promotion.vcsRoots.Gradle_Promotion_GradlePromotionBranches +import Gradle_Promotion.vcsRoots.Gradle_Promotion__master_ import jetbrains.buildServer.configs.kotlin.v2018_2.Project import jetbrains.buildServer.configs.kotlin.v2018_2.projectFeatures.VersionedSettings import jetbrains.buildServer.configs.kotlin.v2018_2.projectFeatures.versionedSettings @@ -16,17 +24,22 @@ object Project : Project({ vcsRoot(Gradle_Promotion_GradlePromotionBranches) vcsRoot(Gradle_Promotion__master_) - buildType(Gradle_Promotion_PublishBranchSnapshotFromQuickFeedback) - buildType(Gradle_Promotion_MilestoneMaster) - buildType(bt60) - buildType(bt61) - buildType(Gradle_Promotion_StartReleaseCycle) - buildType(Gradle_Promotion_FinalRelease) - buildType(bt39) - buildType(Gradle_Promotion_AllBranchesStartReleaseCycleTest) - buildType(Gradle_Promotion_MasterSanityCheck) - buildType(Gradle_Promotion_MasterNightlySnapshotManual) - buildType(Gradle_Promotion_ReleaseSnapshotFromQuickFeedback) + val nightlyMasterSnapshot = PromoteNightlySnapshot(uuid = "01432c63-861f-4d08-ae0a-7d127f63096e", branch = "master", hour = 0) + val masterSnapshotFromQuickFeedback = PromoteSnapshotFromQuickFeedback(uuid = "9a55bec1-4e70-449b-8f45-400093505afb", branch = "master") + val nightlyReleaseSnapshot = PromoteNightlySnapshot(uuid = "1f5ca7f8-b0f5-41f9-9ba7-6d518b2822f0", branch = "release", hour = 1) + val releaseSnapshotFromQuickFeedback = PromoteSnapshotFromQuickFeedback(uuid = "eeff4410-1e7d-4db6-b7b8-34c1f2754477", branch = "release") + + buildType(PromoteBranchSnapshotFromQuickFeedback) + buildType(PromoteMilestone) + buildType(PromoteReleaseCandidate) + buildType(nightlyReleaseSnapshot) + buildType(StartReleaseCycle) + buildType(PromoteFinalRelease) + buildType(nightlyMasterSnapshot) + buildType(StartReleaseCycleTest) + buildType(MasterSanityCheck) + buildType(masterSnapshotFromQuickFeedback) + buildType(releaseSnapshotFromQuickFeedback) params { password("env.ORG_GRADLE_PROJECT_gradleS3SecretKey", "credentialsJSON:0f1f842f-df6c-4db7-8271-f1f73c823aed") @@ -52,5 +65,16 @@ object Project : Project({ storeSecureParamsOutsideOfVcs = true } } - buildTypesOrder = arrayListOf(Gradle_Promotion_MasterSanityCheck, bt39, Gradle_Promotion_MasterNightlySnapshotManual, Gradle_Promotion_StartReleaseCycle, bt61, Gradle_Promotion_ReleaseSnapshotFromQuickFeedback, Gradle_Promotion_PublishBranchSnapshotFromQuickFeedback, Gradle_Promotion_MilestoneMaster, bt60, Gradle_Promotion_FinalRelease) + buildTypesOrder = arrayListOf( + MasterSanityCheck, + nightlyMasterSnapshot, + masterSnapshotFromQuickFeedback, + StartReleaseCycle, + nightlyReleaseSnapshot, + releaseSnapshotFromQuickFeedback, + PromoteBranchSnapshotFromQuickFeedback, + PromoteMilestone, + PromoteReleaseCandidate, + PromoteFinalRelease + ) }) diff --git a/.teamcity/Gradle_Promotion/buildTypes/BasePromoteSnapshot.kt b/.teamcity/Gradle_Promotion/buildTypes/BasePromoteSnapshot.kt new file mode 100644 index 0000000000000..7c367f3319616 --- /dev/null +++ b/.teamcity/Gradle_Promotion/buildTypes/BasePromoteSnapshot.kt @@ -0,0 +1,65 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package Gradle_Promotion.buildTypes + +import jetbrains.buildServer.configs.kotlin.v2018_2.AbsoluteId +import jetbrains.buildServer.configs.kotlin.v2018_2.buildSteps.gradle +import jetbrains.buildServer.configs.kotlin.v2018_2.vcs.GitVcsRoot + +open class BasePromoteSnapshot( + branch: String, + task: String, + val triggerName: String, + gitUserName: String = "Gradleware Git Bot", + gitUserEmail: String = "gradlewaregitbot@gradleware.com", + extraParameters: String = "", + vcsRoot: GitVcsRoot = Gradle_Promotion.vcsRoots.Gradle_Promotion__master_, + init: BasePromoteSnapshot.() -> Unit = {} +) : BasePromotionBuildType(vcsRoot = vcsRoot) { + + init { + artifactRules = """ + incoming-build-receipt/build-receipt.properties => incoming-build-receipt + **/build/git-checkout/build/build-receipt.properties + **/build/distributions/*.zip => promote-build-distributions + **/build/website-checkout/data/releases.xml + **/build/git-checkout/build/reports/integTest/** => distribution-tests + **/smoke-tests/build/reports/tests/** => post-smoke-tests + """.trimIndent() + + steps { + gradle { + name = "Promote" + tasks = task + useGradleWrapper = true + gradleParams = """-PuseBuildReceipt $extraParameters "-PgitUserName=$gitUserName" "-PgitUserEmail=$gitUserEmail" -Igradle/buildScanInit.gradle --build-cache "-Dgradle.cache.remote.url=%gradle.cache.remote.url%" "-Dgradle.cache.remote.username=%gradle.cache.remote.username%" "-Dgradle.cache.remote.password=%gradle.cache.remote.password%"""" + } + } + dependencies { + artifacts(AbsoluteId("Gradle_Check_Stage_${this@BasePromoteSnapshot.triggerName}_Trigger")) { + buildRule = lastSuccessful(branch) + cleanDestination = true + artifactRules = "build-receipt.properties => incoming-build-receipt/" + } + } + + requirements { + contains("teamcity.agent.jvm.os.name", "Linux") + } + this.init() + } +} diff --git a/.teamcity/Gradle_Promotion/buildTypes/BasePromotionBuildType.kt b/.teamcity/Gradle_Promotion/buildTypes/BasePromotionBuildType.kt new file mode 100644 index 0000000000000..d00c6979ede91 --- /dev/null +++ b/.teamcity/Gradle_Promotion/buildTypes/BasePromotionBuildType.kt @@ -0,0 +1,38 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package Gradle_Promotion.buildTypes + +import jetbrains.buildServer.configs.kotlin.v2018_2.BuildType +import jetbrains.buildServer.configs.kotlin.v2018_2.CheckoutMode +import jetbrains.buildServer.configs.kotlin.v2018_2.vcs.GitVcsRoot + +open class BasePromotionBuildType(vcsRoot: GitVcsRoot, cleanCheckout: Boolean = true, init: BasePromotionBuildType.() -> Unit = {}) : BuildType() { + init { + vcs { + root(vcsRoot) + + checkoutMode = CheckoutMode.ON_SERVER + this.cleanCheckout = cleanCheckout + showDependenciesChanges = true + } + + requirements { + contains("teamcity.agent.jvm.os.name", "Linux") + } + this.init() + } +} diff --git a/.teamcity/Gradle_Promotion/buildTypes/Gradle_Promotion_FinalRelease.kt b/.teamcity/Gradle_Promotion/buildTypes/Gradle_Promotion_FinalRelease.kt deleted file mode 100644 index 348a2743ba9ba..0000000000000 --- a/.teamcity/Gradle_Promotion/buildTypes/Gradle_Promotion_FinalRelease.kt +++ /dev/null @@ -1,52 +0,0 @@ -package Gradle_Promotion.buildTypes - -import jetbrains.buildServer.configs.kotlin.v2018_2.* -import jetbrains.buildServer.configs.kotlin.v2018_2.buildSteps.gradle - -object Gradle_Promotion_FinalRelease : BuildType({ - uuid = "44e9390f-e46c-457e-aa18-31b020aef4de" - name = "Release - Final" - description = "Promotes the latest successful change on 'release' as a new release" - - artifactRules = """ - incoming-build-receipt/build-receipt.properties => incoming-build-receipt - promote-projects/gradle/gradle/build/gradle-checkout/build/build-receipt.properties - promote-projects/gradle/gradle/build/distributions/*.zip => promote-build-distributions - promote-projects/gradle/gradle/build/website-checkout/data/releases.xml - promote-projects/gradle/build/git-checkout/build/reports/distributions/integTest/** => distribution-tests - promote-projects/gradle/smoke-tests/build/reports/tests/** => post-smoke-tests - """.trimIndent() - - params { - text("gitUserEmail", "", label = "Git user.email Configuration", description = "Enter the git 'user.email' configuration to commit change under", display = ParameterDisplay.PROMPT, allowEmpty = true) - text("confirmationCode", "", label = "Confirmation Code", description = "Enter the value 'final' (no quotes) to confirm the promotion", display = ParameterDisplay.PROMPT, allowEmpty = false) - text("gitUserName", "", label = "Git user.name Configuration", description = "Enter the git 'user.name' configuration to commit change under", display = ParameterDisplay.PROMPT, allowEmpty = true) - } - - vcs { - root(Gradle_Promotion.vcsRoots.Gradle_Promotion__master_) - - checkoutMode = CheckoutMode.ON_SERVER - } - - steps { - gradle { - name = "Promote" - tasks = "promoteFinalRelease" - buildFile = "" - gradleParams = """-PuseBuildReceipt -PconfirmationCode=%confirmationCode% "-PgitUserName=%gitUserName%" "-PgitUserEmail=%gitUserEmail%" -Igradle/buildScanInit.gradle --build-cache "-Dgradle.cache.remote.url=%gradle.cache.remote.url%" "-Dgradle.cache.remote.username=%gradle.cache.remote.username%" "-Dgradle.cache.remote.password=%gradle.cache.remote.password%"""" - } - } - - dependencies { - artifacts(AbsoluteId("Gradle_Check_Stage_ReadyforRelease_Trigger")) { - buildRule = lastSuccessful("release") - cleanDestination = true - artifactRules = "build-receipt.properties => incoming-build-receipt/" - } - } - - requirements { - contains("teamcity.agent.jvm.os.name", "Linux") - } -}) diff --git a/.teamcity/Gradle_Promotion/buildTypes/Gradle_Promotion_MasterNightlySnapshotManual.kt b/.teamcity/Gradle_Promotion/buildTypes/Gradle_Promotion_MasterNightlySnapshotManual.kt deleted file mode 100644 index bc6f2508e3250..0000000000000 --- a/.teamcity/Gradle_Promotion/buildTypes/Gradle_Promotion_MasterNightlySnapshotManual.kt +++ /dev/null @@ -1,47 +0,0 @@ -package Gradle_Promotion.buildTypes - -import jetbrains.buildServer.configs.kotlin.v2018_2.* -import jetbrains.buildServer.configs.kotlin.v2018_2.buildSteps.gradle - -object Gradle_Promotion_MasterNightlySnapshotManual : BuildType({ - uuid = "9a55bec1-4e70-449b-8f45-400093505afb" - name = "Master - Nightly Snapshot (from Quick Feedback)" - description = "Promotes the latest change on 'master' that passed the 'Quick Feedback' stage as new nightly. This build configuration can be triggered manually if there are issues further down the pipeline we can ignore temporarily." - - artifactRules = """ - incoming-build-receipt/build-receipt.properties => incoming-build-receipt - **/build/git-checkout/build/build-receipt.properties - **/build/distributions/*.zip => promote-build-distributions - **/build/website-checkout/data/releases.xml - **/build/gradle-checkout/build/reports/integTest/** => distribution-tests - **/smoke-tests/build/reports/tests/** => post-smoke-tests - """.trimIndent() - - vcs { - root(Gradle_Promotion.vcsRoots.Gradle_Promotion__master_) - - checkoutMode = CheckoutMode.ON_SERVER - cleanCheckout = true - showDependenciesChanges = true - } - - steps { - gradle { - name = "Promote" - tasks = "promoteNightly -s" - buildFile = "" - gradleParams = """-PuseBuildReceipt -i "-PgitUserName=Gradleware Git Bot" "-PgitUserEmail=gradlewaregitbot@gradleware.com" -Igradle/buildScanInit.gradle --build-cache "-Dgradle.cache.remote.url=%gradle.cache.remote.url%" "-Dgradle.cache.remote.username=%gradle.cache.remote.username%" "-Dgradle.cache.remote.password=%gradle.cache.remote.password%"""" - } - } - - dependencies { - artifacts(AbsoluteId("Gradle_Check_Stage_QuickFeedback_Trigger")) { - buildRule = lastSuccessful("master") - artifactRules = "build-receipt.properties => incoming-build-receipt/" - } - } - - requirements { - contains("teamcity.agent.jvm.os.name", "Linux") - } -}) diff --git a/.teamcity/Gradle_Promotion/buildTypes/Gradle_Promotion_MilestoneMaster.kt b/.teamcity/Gradle_Promotion/buildTypes/Gradle_Promotion_MilestoneMaster.kt deleted file mode 100644 index 55dd7e974f93a..0000000000000 --- a/.teamcity/Gradle_Promotion/buildTypes/Gradle_Promotion_MilestoneMaster.kt +++ /dev/null @@ -1,52 +0,0 @@ -package Gradle_Promotion.buildTypes - -import jetbrains.buildServer.configs.kotlin.v2018_2.* -import jetbrains.buildServer.configs.kotlin.v2018_2.buildSteps.gradle - -object Gradle_Promotion_MilestoneMaster : BuildType({ - uuid = "2ffb238a-08af-4f95-b863-9830d2bc3872" - name = "Release - Milestone" - description = "Promotes the latest successful change on 'release' as the new snapshot" - - artifactRules = """ - incoming-build-receipt/build-receipt.properties => incoming-build-receipt - promote-projects/gradle/gradle/build/gradle-checkout/build/build-receipt.properties - promote-projects/gradle/gradle/build/distributions/*.zip => promote-build-distributions - promote-projects/gradle/gradle/build/website-checkout/data/releases.xml - promote-projects/gradle/build/git-checkout/build/reports/distributions/integTest/** => distribution-tests - promote-projects/gradle/smoke-tests/build/reports/tests/** => post-smoke-tests - """.trimIndent() - - params { - text("gitUserEmail", "", label = "Git user.email Configuration", description = "Enter the git 'user.email' configuration to commit change under", display = ParameterDisplay.PROMPT, allowEmpty = true) - param("confirmationCode", "") - text("gitUserName", "", label = "Git user.name Configuration", description = "Enter the git 'user.name' configuration to commit change under", display = ParameterDisplay.PROMPT, allowEmpty = true) - } - - vcs { - root(Gradle_Promotion.vcsRoots.Gradle_Promotion__master_) - - checkoutMode = CheckoutMode.ON_SERVER - showDependenciesChanges = true - } - - steps { - gradle { - name = "Promote" - tasks = "promoteMilestone -s -PconfirmationCode=milestone" - buildFile = "" - gradleParams = """-PuseBuildReceipt -i "-PgitUserName=%gitUserName%" "-PgitUserEmail=%gitUserEmail%" -Igradle/buildScanInit.gradle --build-cache "-Dgradle.cache.remote.url=%gradle.cache.remote.url%" "-Dgradle.cache.remote.username=%gradle.cache.remote.username%" "-Dgradle.cache.remote.password=%gradle.cache.remote.password%"""" - } - } - - dependencies { - artifacts(AbsoluteId("Gradle_Check_Stage_ReadyforRelease_Trigger")) { - buildRule = lastSuccessful("release") - artifactRules = "build-receipt.properties => incoming-build-receipt/" - } - } - - requirements { - contains("teamcity.agent.jvm.os.name", "Linux") - } -}) diff --git a/.teamcity/Gradle_Promotion/buildTypes/Gradle_Promotion_PublishBranchSnapshotFromQuickFeedback.kt b/.teamcity/Gradle_Promotion/buildTypes/Gradle_Promotion_PublishBranchSnapshotFromQuickFeedback.kt deleted file mode 100644 index e348503acb75c..0000000000000 --- a/.teamcity/Gradle_Promotion/buildTypes/Gradle_Promotion_PublishBranchSnapshotFromQuickFeedback.kt +++ /dev/null @@ -1,51 +0,0 @@ -package Gradle_Promotion.buildTypes - -import jetbrains.buildServer.configs.kotlin.v2018_2.* -import jetbrains.buildServer.configs.kotlin.v2018_2.buildSteps.gradle - -object Gradle_Promotion_PublishBranchSnapshotFromQuickFeedback : BuildType({ - uuid = "b7ecebd3-3812-4532-aa77-5679f9e9d6b3" - name = "Publish Branch Snapshot (from Quick Feedback)" - description = "Deploys a new wrapper for the selected build/branch. Does not update master or the documentation." - - artifactRules = """ - incoming-build-receipt/build-receipt.properties => incoming-build-receipt - **/build/git-checkout/build/build-receipt.properties - **/build/distributions/*.zip => promote-build-distributions - **/build/website-checkout/data/releases.xml - **/build/git-checkout/build/reports/integTest/** => distribution-tests - **/smoke-tests/build/reports/tests/** => post-smoke-tests - """.trimIndent() - - params { - param("branch.qualifier", "%dep.Gradle_Check_Stage_QuickFeedback_Trigger.teamcity.build.branch%") - text("branch.to.promote", "%branch.qualifier%", label = "Branch to promote", description = "Type in the branch of gradle/gradle you want to promote. Leave the default value when promoting an existing build.", display = ParameterDisplay.PROMPT, allowEmpty = false) - } - - vcs { - root(Gradle_Promotion.vcsRoots.Gradle_Promotion_GradlePromotionBranches) - - checkoutMode = CheckoutMode.ON_SERVER - } - - steps { - gradle { - name = "Promote" - tasks = "promoteSnapshot" - buildFile = "" - gradleParams = """-PuseBuildReceipt "-PgitUserName=Gradleware Git Bot" "-PgitUserEmail=gradlewaregitbot@gradleware.com" -Igradle/buildScanInit.gradle -PpromotedBranch=%branch.qualifier% --build-cache "-Dgradle.cache.remote.url=%gradle.cache.remote.url%" "-Dgradle.cache.remote.username=%gradle.cache.remote.username%" "-Dgradle.cache.remote.password=%gradle.cache.remote.password%"""" - } - } - - dependencies { - artifacts(AbsoluteId("Gradle_Check_Stage_QuickFeedback_Trigger")) { - buildRule = lastSuccessful("%branch.to.promote%") - cleanDestination = true - artifactRules = "build-receipt.properties => incoming-build-receipt/" - } - } - - requirements { - contains("teamcity.agent.jvm.os.name", "Linux") - } -}) diff --git a/.teamcity/Gradle_Promotion/buildTypes/Gradle_Promotion_ReleaseSnapshotFromQuickFeedback.kt b/.teamcity/Gradle_Promotion/buildTypes/Gradle_Promotion_ReleaseSnapshotFromQuickFeedback.kt deleted file mode 100644 index 6f39d9aa93266..0000000000000 --- a/.teamcity/Gradle_Promotion/buildTypes/Gradle_Promotion_ReleaseSnapshotFromQuickFeedback.kt +++ /dev/null @@ -1,46 +0,0 @@ -package Gradle_Promotion.buildTypes - -import jetbrains.buildServer.configs.kotlin.v2018_2.* -import jetbrains.buildServer.configs.kotlin.v2018_2.buildSteps.gradle - -object Gradle_Promotion_ReleaseSnapshotFromQuickFeedback : BuildType({ - uuid = "eeff4410-1e7d-4db6-b7b8-34c1f2754477" - name = "Release - Release Nightly Snapshot (from Quick Feedback)" - description = "Deploys the latest successful change on 'release' as a new release nightly snapshot" - - artifactRules = """ - incoming-build-receipt/build-receipt.properties => incoming-build-receipt - **/build/git-checkout/build/build-receipt.properties - **/build/distributions/*.zip => promote-build-distributions - **/build/website-checkout/data/releases.xml - **/build/git-checkout/build/reports/integTest/** => distribution-tests - **/smoke-tests/build/reports/tests/** => post-smoke-tests - """.trimIndent() - - vcs { - root(Gradle_Promotion.vcsRoots.Gradle_Promotion__master_) - - checkoutMode = CheckoutMode.ON_SERVER - } - - steps { - gradle { - name = "Promote" - tasks = "promoteReleaseNightly" - buildFile = "" - gradleParams = """-PuseBuildReceipt "-PgitUserName=Gradleware Git Bot" "-PgitUserEmail=gradlewaregitbot@gradleware.com" -Igradle/buildScanInit.gradle --build-cache "-Dgradle.cache.remote.url=%gradle.cache.remote.url%" "-Dgradle.cache.remote.username=%gradle.cache.remote.username%" "-Dgradle.cache.remote.password=%gradle.cache.remote.password%"""" - } - } - - dependencies { - artifacts(AbsoluteId("Gradle_Check_Stage_QuickFeedback_Trigger")) { - buildRule = lastSuccessful("release") - cleanDestination = true - artifactRules = "build-receipt.properties => incoming-build-receipt/" - } - } - - requirements { - contains("teamcity.agent.jvm.os.name", "Linux") - } -}) diff --git a/.teamcity/Gradle_Promotion/buildTypes/Gradle_Promotion_MasterSanityCheck.kt b/.teamcity/Gradle_Promotion/buildTypes/MasterSanityCheck.kt similarity index 79% rename from .teamcity/Gradle_Promotion/buildTypes/Gradle_Promotion_MasterSanityCheck.kt rename to .teamcity/Gradle_Promotion/buildTypes/MasterSanityCheck.kt index 21b2e5038d8b5..45ed50213bcb5 100644 --- a/.teamcity/Gradle_Promotion/buildTypes/Gradle_Promotion_MasterSanityCheck.kt +++ b/.teamcity/Gradle_Promotion/buildTypes/MasterSanityCheck.kt @@ -1,11 +1,13 @@ package Gradle_Promotion.buildTypes -import jetbrains.buildServer.configs.kotlin.v2018_2.* +import jetbrains.buildServer.configs.kotlin.v2018_2.BuildType +import jetbrains.buildServer.configs.kotlin.v2018_2.CheckoutMode import jetbrains.buildServer.configs.kotlin.v2018_2.buildSteps.gradle import jetbrains.buildServer.configs.kotlin.v2018_2.triggers.vcs -object Gradle_Promotion_MasterSanityCheck : BuildType({ +object MasterSanityCheck : BuildType({ uuid = "bf9b573a-6e5e-4db1-88b2-399e709026b5" + id("Gradle_Promotion_MasterSanityCheck") name = "Master - Sanity Check" description = "Compilation and test execution of buildSrc" @@ -20,7 +22,7 @@ object Gradle_Promotion_MasterSanityCheck : BuildType({ steps { gradle { tasks = "tasks -s" - buildFile = "" + useGradleWrapper = true gradleParams = "-Igradle/buildScanInit.gradle" param("org.jfrog.artifactory.selectedDeployableServer.defaultModuleVersionConfiguration", "GLOBAL") param("ui.gradleRunner.gradle.build.file", "") diff --git a/.teamcity/Gradle_Promotion/buildTypes/PromoteBranchSnapshotFromQuickFeedback.kt b/.teamcity/Gradle_Promotion/buildTypes/PromoteBranchSnapshotFromQuickFeedback.kt new file mode 100644 index 0000000000000..a0394a4e2ca22 --- /dev/null +++ b/.teamcity/Gradle_Promotion/buildTypes/PromoteBranchSnapshotFromQuickFeedback.kt @@ -0,0 +1,40 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package Gradle_Promotion.buildTypes + +import jetbrains.buildServer.configs.kotlin.v2018_2.ParameterDisplay + +object PromoteBranchSnapshotFromQuickFeedback : BasePromoteSnapshot( + branch = "%branch.to.promote%", + triggerName = "QuickFeedback", + task = "promoteSnapshot", + extraParameters = "-PpromotedBranch=%branch.qualifier% ", + vcsRoot = Gradle_Promotion.vcsRoots.Gradle_Promotion_GradlePromotionBranches, + init = { + uuid = "b7ecebd3-3812-4532-aa77-5679f9e9d6b3" + id("Gradle_Promotion_PublishBranchSnapshotFromQuickFeedback") + name = "Publish Branch Snapshot (from Quick Feedback)" + description = "Deploys a new distribution snapshot for the selected build/branch. Does not update master or the documentation." + + val triggerName = this.triggerName + + params { + param("branch.qualifier", "%dep.Gradle_Check_Stage_${triggerName}_Trigger.teamcity.build.branch%") + text("branch.to.promote", "%branch.qualifier%", label = "Branch to promote", description = "Type in the branch of gradle/gradle you want to promote. Leave the default value when promoting an existing build.", display = ParameterDisplay.PROMPT, allowEmpty = false) + } + } +) diff --git a/.teamcity/Gradle_Promotion/buildTypes/PromoteNightlySnapshot.kt b/.teamcity/Gradle_Promotion/buildTypes/PromoteNightlySnapshot.kt new file mode 100644 index 0000000000000..f1b8b17f7bd77 --- /dev/null +++ b/.teamcity/Gradle_Promotion/buildTypes/PromoteNightlySnapshot.kt @@ -0,0 +1,37 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package Gradle_Promotion.buildTypes + +import jetbrains.buildServer.configs.kotlin.v2018_2.triggers.schedule + +class PromoteNightlySnapshot(uuid: String, branch: String, hour: Int) : PromoteSnapshot(branch = branch, triggerName = "ReadyforNightly", init = { + val capitalizedBranch = this.capitalizedBranch + this.uuid = uuid + id("Gradle_Promotion_${capitalizedBranch}Nightly") + name = "$capitalizedBranch - Nightly Snapshot" + description = "Promotes the latest successful changes on '$branch' from Ready for Nightly as a new nightly snapshot" + + triggers { + schedule { + schedulingPolicy = daily { + this.hour = hour + } + triggerBuild = always() + withPendingChangesOnly = false + } + } +}) diff --git a/.teamcity/Gradle_Promotion/buildTypes/PromoteRelease.kt b/.teamcity/Gradle_Promotion/buildTypes/PromoteRelease.kt new file mode 100644 index 0000000000000..1b87bc8af9235 --- /dev/null +++ b/.teamcity/Gradle_Promotion/buildTypes/PromoteRelease.kt @@ -0,0 +1,58 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package Gradle_Promotion.buildTypes + +import jetbrains.buildServer.configs.kotlin.v2018_2.ParameterDisplay + +open class PromoteRelease(task: String, requiredConfirmationCode: String, branch: String = "release", init: PromoteRelease.() -> Unit = {}) : BasePromoteSnapshot( + branch = branch, + task = task, + triggerName = "ReadyforRelease", + gitUserEmail = "%gitUserEmail%", + gitUserName = "%gitUserName%", + extraParameters = "-PconfirmationCode=%confirmationCode%" +) { + init { + params { + text("gitUserEmail", "", label = "Git user.email Configuration", description = "Enter the git 'user.email' configuration to commit change under", display = ParameterDisplay.PROMPT, allowEmpty = true) + text("confirmationCode", "", label = "Confirmation Code", description = "Enter the value '$requiredConfirmationCode' (no quotes) to confirm the promotion", display = ParameterDisplay.PROMPT, allowEmpty = false) + text("gitUserName", "", label = "Git user.name Configuration", description = "Enter the git 'user.name' configuration to commit change under", display = ParameterDisplay.PROMPT, allowEmpty = true) + } + this.init() + } +} + +object PromoteFinalRelease : PromoteRelease(task = "promoteFinalRelease", requiredConfirmationCode = "final", init = { + uuid = "44e9390f-e46c-457e-aa18-31b020aef4de" + id("Gradle_Promotion_FinalRelease") + name = "Release - Final" + description = "Promotes the latest successful change on 'release' as a new release" +}) + +object PromoteReleaseCandidate : PromoteRelease(task = "promoteRc", requiredConfirmationCode = "rc", init = { + uuid = "5ed504bb-5ec3-46dc-a28a-e42a63ebbb31" + id("Gradle_Promotion_ReleaseCandidate") + name = "Release - Release Candidate" + description = "Promotes the latest successful change on 'release' as a new release candidate" +}) + +object PromoteMilestone : PromoteRelease(task = "promoteMilestone", requiredConfirmationCode = "milestone", init = { + uuid = "2ffb238a-08af-4f95-b863-9830d2bc3872" + id("Gradle_Promotion_Milestone") + name = "Release - Milestone" + description = "Promotes the latest successful change on 'release' as a new milestone" +}) diff --git a/.teamcity/Gradle_Promotion/buildTypes/PromoteSnapshot.kt b/.teamcity/Gradle_Promotion/buildTypes/PromoteSnapshot.kt new file mode 100644 index 0000000000000..a2a216ffe5955 --- /dev/null +++ b/.teamcity/Gradle_Promotion/buildTypes/PromoteSnapshot.kt @@ -0,0 +1,25 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package Gradle_Promotion.buildTypes + +open class PromoteSnapshot(branch: String, triggerName: String, init: PromoteSnapshot.() -> Unit = {}) : BasePromoteSnapshot(branch = branch, triggerName = triggerName, task = "promote${if (branch == "master") "" else branch.capitalize()}Nightly") { + val capitalizedBranch = branch.capitalize() + + init { + this.init() + } +} diff --git a/.teamcity/Gradle_Promotion/buildTypes/PromoteSnapshotFromQuickFeedback.kt b/.teamcity/Gradle_Promotion/buildTypes/PromoteSnapshotFromQuickFeedback.kt new file mode 100644 index 0000000000000..a127f0906b661 --- /dev/null +++ b/.teamcity/Gradle_Promotion/buildTypes/PromoteSnapshotFromQuickFeedback.kt @@ -0,0 +1,24 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package Gradle_Promotion.buildTypes + +class PromoteSnapshotFromQuickFeedback(uuid: String, branch: String) : PromoteSnapshot(branch = branch, triggerName = "QuickFeedback", init = { + this.uuid = uuid + id("Gradle_Promotion_${capitalizedBranch}SnapshotFromQuickFeedback") + name = capitalizedBranch + description = "Promotes the latest successful changes on '$branch' from Quick Feedback as a new nightly snapshot" +}) diff --git a/.teamcity/Gradle_Promotion/buildTypes/Gradle_Promotion_StartReleaseCycle.kt b/.teamcity/Gradle_Promotion/buildTypes/StartReleaseCycle.kt similarity index 66% rename from .teamcity/Gradle_Promotion/buildTypes/Gradle_Promotion_StartReleaseCycle.kt rename to .teamcity/Gradle_Promotion/buildTypes/StartReleaseCycle.kt index 4e14e4291670a..382a75aa13d22 100644 --- a/.teamcity/Gradle_Promotion/buildTypes/Gradle_Promotion_StartReleaseCycle.kt +++ b/.teamcity/Gradle_Promotion/buildTypes/StartReleaseCycle.kt @@ -1,10 +1,28 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package Gradle_Promotion.buildTypes -import jetbrains.buildServer.configs.kotlin.v2018_2.* +import jetbrains.buildServer.configs.kotlin.v2018_2.AbsoluteId +import jetbrains.buildServer.configs.kotlin.v2018_2.ParameterDisplay import jetbrains.buildServer.configs.kotlin.v2018_2.buildSteps.gradle -object Gradle_Promotion_StartReleaseCycle : BuildType({ +object StartReleaseCycle : BasePromotionBuildType(vcsRoot = Gradle_Promotion.vcsRoots.Gradle_Promotion__master_, init = { uuid = "355487d7-45b9-4387-9fc5-713e7683e6d0" + id("Gradle_Promotion_StartReleaseCycle") name = "Master - Start Release Cycle" description = "Promotes a successful build on master as the start of a new release cycle on the release branch" @@ -19,17 +37,11 @@ object Gradle_Promotion_StartReleaseCycle : BuildType({ text("gitUserName", "", label = "Git user.name Configuration", description = "Enter the git 'user.name' configuration to commit change under", display = ParameterDisplay.PROMPT, allowEmpty = true) } - vcs { - root(Gradle_Promotion.vcsRoots.Gradle_Promotion__master_) - - checkoutMode = CheckoutMode.ON_SERVER - } - steps { gradle { name = "Promote" tasks = "clean promoteStartReleaseCycle" - buildFile = "" + useGradleWrapper = true gradleParams = """-PuseBuildReceipt -PconfirmationCode=%confirmationCode% "-PgitUserName=%gitUserName%" "-PgitUserEmail=%gitUserEmail%" -Igradle/buildScanInit.gradle""" param("org.jfrog.artifactory.selectedDeployableServer.defaultModuleVersionConfiguration", "GLOBAL") } @@ -42,8 +54,4 @@ object Gradle_Promotion_StartReleaseCycle : BuildType({ artifactRules = "build-receipt.properties => incoming-build-receipt/" } } - - requirements { - contains("teamcity.agent.jvm.os.name", "Linux") - } }) diff --git a/.teamcity/Gradle_Promotion/buildTypes/Gradle_Promotion_AllBranchesStartReleaseCycleTest.kt b/.teamcity/Gradle_Promotion/buildTypes/StartReleaseCycleTest.kt similarity index 53% rename from .teamcity/Gradle_Promotion/buildTypes/Gradle_Promotion_AllBranchesStartReleaseCycleTest.kt rename to .teamcity/Gradle_Promotion/buildTypes/StartReleaseCycleTest.kt index 0829dab680eec..d5827b329af15 100644 --- a/.teamcity/Gradle_Promotion/buildTypes/Gradle_Promotion_AllBranchesStartReleaseCycleTest.kt +++ b/.teamcity/Gradle_Promotion/buildTypes/StartReleaseCycleTest.kt @@ -1,24 +1,36 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package Gradle_Promotion.buildTypes -import jetbrains.buildServer.configs.kotlin.v2018_2.* import jetbrains.buildServer.configs.kotlin.v2018_2.buildSteps.gradle import jetbrains.buildServer.configs.kotlin.v2018_2.triggers.schedule import jetbrains.buildServer.configs.kotlin.v2018_2.triggers.vcs -object Gradle_Promotion_AllBranchesStartReleaseCycleTest : BuildType({ +object StartReleaseCycleTest : BasePromotionBuildType(vcsRoot = Gradle_Promotion.vcsRoots.Gradle_Promotion_GradlePromotionBranches, cleanCheckout = false, init = { uuid = "59823634-f79d-4c11-bbca-782957a7d65c" + id("Gradle_Promotion_AllBranchesStartReleaseCycleTest") name = "Master - Start Release Cycle Test" description = "Test for Start Release Cycle pipeline" - vcs { - root(Gradle_Promotion.vcsRoots.Gradle_Promotion_GradlePromotionBranches) - } - steps { gradle { name = "PromoteTest" tasks = "clean promoteStartReleaseCycle" - buildFile = "" + useGradleWrapper = true gradleParams = "-PconfirmationCode=startCycle -Igradle/buildScanInit.gradle -PtestRun=1" param("teamcity.tool.jacoco", "%teamcity.tool.jacoco.DEFAULT%") } @@ -37,8 +49,4 @@ object Gradle_Promotion_AllBranchesStartReleaseCycleTest : BuildType({ withPendingChangesOnly = false } } - - requirements { - contains("teamcity.agent.jvm.os.name", "Linux") - } }) diff --git a/.teamcity/Gradle_Promotion/buildTypes/bt39.kt b/.teamcity/Gradle_Promotion/buildTypes/bt39.kt deleted file mode 100644 index 8ecbd83d6a4fd..0000000000000 --- a/.teamcity/Gradle_Promotion/buildTypes/bt39.kt +++ /dev/null @@ -1,60 +0,0 @@ -package Gradle_Promotion.buildTypes - -import jetbrains.buildServer.configs.kotlin.v2018_2.* -import jetbrains.buildServer.configs.kotlin.v2018_2.buildSteps.gradle -import jetbrains.buildServer.configs.kotlin.v2018_2.triggers.schedule - -object bt39 : BuildType({ - uuid = "01432c63-861f-4d08-ae0a-7d127f63096e" - name = "Master - Nightly Snapshot" - description = "Promotes the latest successful change on 'master' as the new nightly" - - artifactRules = """ - incoming-build-receipt/build-receipt.properties => incoming-build-receipt - **/build/git-checkout/build/build-receipt.properties - **/build/distributions/*.zip => promote-build-distributions - **/build/website-checkout/data/releases.xml - **/build/gradle-checkout/build/reports/integTest/** => distribution-tests - **/smoke-tests/build/reports/tests/** => post-smoke-tests - """.trimIndent() - - vcs { - root(Gradle_Promotion.vcsRoots.Gradle_Promotion__master_) - - checkoutMode = CheckoutMode.ON_SERVER - cleanCheckout = true - showDependenciesChanges = true - } - - steps { - gradle { - name = "Promote" - tasks = "promoteNightly -s" - buildFile = "" - gradleParams = """-PuseBuildReceipt -i "-PgitUserName=Gradleware Git Bot" "-PgitUserEmail=gradlewaregitbot@gradleware.com" -Igradle/buildScanInit.gradle --build-cache "-Dgradle.cache.remote.url=%gradle.cache.remote.url%" "-Dgradle.cache.remote.username=%gradle.cache.remote.username%" "-Dgradle.cache.remote.password=%gradle.cache.remote.password%"""" - } - } - - triggers { - schedule { - schedulingPolicy = daily { - hour = 0 - timezone = "" - } - branchFilter = "" - triggerBuild = always() - withPendingChangesOnly = false - } - } - - dependencies { - artifacts(AbsoluteId("Gradle_Check_Stage_ReadyforNightly_Trigger")) { - buildRule = lastSuccessful("master") - artifactRules = "build-receipt.properties => incoming-build-receipt/" - } - } - - requirements { - contains("teamcity.agent.jvm.os.name", "Linux") - } -}) diff --git a/.teamcity/Gradle_Promotion/buildTypes/bt60.kt b/.teamcity/Gradle_Promotion/buildTypes/bt60.kt deleted file mode 100644 index 0d8765f8529b7..0000000000000 --- a/.teamcity/Gradle_Promotion/buildTypes/bt60.kt +++ /dev/null @@ -1,52 +0,0 @@ -package Gradle_Promotion.buildTypes - -import jetbrains.buildServer.configs.kotlin.v2018_2.* -import jetbrains.buildServer.configs.kotlin.v2018_2.buildSteps.gradle - -object bt60 : BuildType({ - uuid = "5ed504bb-5ec3-46dc-a28a-e42a63ebbb31" - name = "Release - Release Candidate" - description = "Promotes the latest successful change on 'release' as a new release candidate" - - artifactRules = """ - incoming-build-receipt/build-receipt.properties => incoming-build-receipt - promote-projects/gradle/gradle/build/gradle-checkout/build/build-receipt.properties - promote-projects/gradle/gradle/build/distributions/*.zip => promote-build-distributions - promote-projects/gradle/gradle/build/website-checkout/data/releases.xml - promote-projects/gradle/build/git-checkout/build/reports/distributions/integTest/** => distribution-tests - promote-projects/gradle/smoke-tests/build/reports/tests/** => post-smoke-tests - """.trimIndent() - - params { - text("gitUserEmail", "", label = "Git user.email Configuration", description = "Enter the git 'user.email' configuration to commit change under", display = ParameterDisplay.PROMPT, allowEmpty = true) - text("confirmationCode", "", label = "Confirmation Code", description = "Enter the value 'rc' (no quotes) to confirm the promotion", display = ParameterDisplay.PROMPT, allowEmpty = false) - text("gitUserName", "", label = "Git user.name Configuration", description = "Enter the git 'user.name' configuration to commit change under", display = ParameterDisplay.PROMPT, allowEmpty = true) - } - - vcs { - root(Gradle_Promotion.vcsRoots.Gradle_Promotion__master_) - - checkoutMode = CheckoutMode.ON_SERVER - } - - steps { - gradle { - name = "Promote" - tasks = "promoteRc" - buildFile = "" - gradleParams = """-PuseBuildReceipt -PconfirmationCode=%confirmationCode% "-PgitUserName=%gitUserName%" "-PgitUserEmail=%gitUserEmail%" -Igradle/buildScanInit.gradle --build-cache "-Dgradle.cache.remote.url=%gradle.cache.remote.url%" "-Dgradle.cache.remote.username=%gradle.cache.remote.username%" "-Dgradle.cache.remote.password=%gradle.cache.remote.password%"""" - } - } - - dependencies { - artifacts(AbsoluteId("Gradle_Check_Stage_ReadyforRelease_Trigger")) { - buildRule = lastSuccessful("release") - cleanDestination = true - artifactRules = "build-receipt.properties => incoming-build-receipt/" - } - } - - requirements { - contains("teamcity.agent.jvm.os.name", "Linux") - } -}) diff --git a/.teamcity/Gradle_Promotion/buildTypes/bt61.kt b/.teamcity/Gradle_Promotion/buildTypes/bt61.kt deleted file mode 100644 index 917d36f001394..0000000000000 --- a/.teamcity/Gradle_Promotion/buildTypes/bt61.kt +++ /dev/null @@ -1,58 +0,0 @@ -package Gradle_Promotion.buildTypes - -import jetbrains.buildServer.configs.kotlin.v2018_2.* -import jetbrains.buildServer.configs.kotlin.v2018_2.buildSteps.gradle -import jetbrains.buildServer.configs.kotlin.v2018_2.triggers.schedule - -object bt61 : BuildType({ - uuid = "1f5ca7f8-b0f5-41f9-9ba7-6d518b2822f0" - name = "Release - Release Nightly Snapshot" - description = "Deploys the latest successful change on 'release' as a new release nightly snapshot" - - artifactRules = """ - incoming-build-receipt/build-receipt.properties => incoming-build-receipt - **/build/git-checkout/build/build-receipt.properties - **/build/distributions/*.zip => promote-build-distributions - **/build/website-checkout/data/releases.xml - **/build/git-checkout/build/reports/integTest/** => distribution-tests - **/smoke-tests/build/reports/tests/** => post-smoke-tests - """.trimIndent() - - vcs { - root(Gradle_Promotion.vcsRoots.Gradle_Promotion__master_) - - checkoutMode = CheckoutMode.ON_SERVER - } - - steps { - gradle { - name = "Promote" - tasks = "promoteReleaseNightly" - buildFile = "" - gradleParams = """-PuseBuildReceipt "-PgitUserName=Gradleware Git Bot" "-PgitUserEmail=gradlewaregitbot@gradleware.com" -Igradle/buildScanInit.gradle --build-cache "-Dgradle.cache.remote.url=%gradle.cache.remote.url%" "-Dgradle.cache.remote.username=%gradle.cache.remote.username%" "-Dgradle.cache.remote.password=%gradle.cache.remote.password%"""" - } - } - - triggers { - schedule { - schedulingPolicy = daily { - hour = 1 - } - branchFilter = "" - triggerBuild = always() - withPendingChangesOnly = false - } - } - - dependencies { - artifacts(AbsoluteId("Gradle_Check_Stage_ReadyforNightly_Trigger")) { - buildRule = lastSuccessful("release") - cleanDestination = true - artifactRules = "build-receipt.properties => incoming-build-receipt/" - } - } - - requirements { - contains("teamcity.agent.jvm.os.name", "Linux") - } -}) From fc32ae4d59e5622b87e0a11525c538e235462fe1 Mon Sep 17 00:00:00 2001 From: Stefan Wolf Date: Thu, 7 Mar 2019 23:22:45 +0100 Subject: [PATCH 393/853] Always use daemon for build tagging Some tagging command lines have not been adjusted, so the daemon was not used as TC disables it by default. --- .teamcity/Gradle_Check/configurations/PerformanceTest.kt | 2 +- .teamcity/Gradle_Check/configurations/StagePasses.kt | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.teamcity/Gradle_Check/configurations/PerformanceTest.kt b/.teamcity/Gradle_Check/configurations/PerformanceTest.kt index 6bd8940d62563..4becc7e3c47c1 100644 --- a/.teamcity/Gradle_Check/configurations/PerformanceTest.kt +++ b/.teamcity/Gradle_Check/configurations/PerformanceTest.kt @@ -61,7 +61,7 @@ class PerformanceTest(model: CIBuildModel, type: PerformanceTestType, stage: Sta name = "TAG_BUILD" executionMode = BuildStep.ExecutionMode.ALWAYS tasks = "tagBuild" - gradleParams = "-PteamCityUsername=%teamcity.username.restbot% -PteamCityPassword=%teamcity.password.restbot% -PteamCityBuildId=%teamcity.build.id% -PgithubToken=%github.ci.oauth.token%" + gradleParams = "-PteamCityUsername=%teamcity.username.restbot% -PteamCityPassword=%teamcity.password.restbot% -PteamCityBuildId=%teamcity.build.id% -PgithubToken=%github.ci.oauth.token% --daemon" } } } diff --git a/.teamcity/Gradle_Check/configurations/StagePasses.kt b/.teamcity/Gradle_Check/configurations/StagePasses.kt index f5f5642b0e0ec..3bf135b08c1c2 100644 --- a/.teamcity/Gradle_Check/configurations/StagePasses.kt +++ b/.teamcity/Gradle_Check/configurations/StagePasses.kt @@ -29,7 +29,7 @@ class StagePasses(model: CIBuildModel, stage: Stage, prevStage: Stage?, contains -:.teamcityTest -:subprojects/docs/src/docs/release """.trimIndent() - val masterReleaseFiler = model.masterAndReleaseBranches.joinToString(prefix = "+:", separator = "\n+:") + val masterReleaseFilter = model.masterAndReleaseBranches.joinToString(prefix = "+:", separator = "\n+:") if (model.publishStatusToGitHub) { features { @@ -42,7 +42,7 @@ class StagePasses(model: CIBuildModel, stage: Stage, prevStage: Stage?, contains quietPeriodMode = VcsTrigger.QuietPeriodMode.USE_CUSTOM quietPeriod = 90 triggerRules = triggerExcludes - branchFilter = masterReleaseFiler + branchFilter = masterReleaseFilter } } else if (stage.trigger != Trigger.never) { triggers.schedule { @@ -60,7 +60,7 @@ class StagePasses(model: CIBuildModel, stage: Stage, prevStage: Stage?, contains triggerBuild = always() withPendingChangesOnly = true param("revisionRule", "lastFinished") - param("branchFilter", masterReleaseFiler) + param("branchFilter", masterReleaseFilter) } } @@ -85,7 +85,7 @@ class StagePasses(model: CIBuildModel, stage: Stage, prevStage: Stage?, contains name = "TAG_BUILD" executionMode = BuildStep.ExecutionMode.ALWAYS tasks = "tagBuild" - gradleParams = "-PteamCityUsername=%teamcity.username.restbot% -PteamCityPassword=%teamcity.password.restbot% -PteamCityBuildId=%teamcity.build.id% -PgithubToken=%github.ci.oauth.token% ${buildScanTag("StagePasses")}" + gradleParams = "-PteamCityUsername=%teamcity.username.restbot% -PteamCityPassword=%teamcity.password.restbot% -PteamCityBuildId=%teamcity.build.id% -PgithubToken=%github.ci.oauth.token% ${buildScanTag("StagePasses")} --daemon" } } } From 6880f91f6fde11a75409cd64f6649ab1ef122b5e Mon Sep 17 00:00:00 2001 From: Gary Hale Date: Thu, 7 Mar 2019 18:48:45 -0500 Subject: [PATCH 394/853] Remove tests now covered through simulated integration test --- ...DaemonPerformanceMonitoringSoakTest.groovy | 22 ------------------- 1 file changed, 22 deletions(-) diff --git a/subprojects/soak/src/integTest/groovy/org/gradle/launcher/daemon/DaemonPerformanceMonitoringSoakTest.groovy b/subprojects/soak/src/integTest/groovy/org/gradle/launcher/daemon/DaemonPerformanceMonitoringSoakTest.groovy index 0f5e6100f67d4..a9fbf247bd96d 100644 --- a/subprojects/soak/src/integTest/groovy/org/gradle/launcher/daemon/DaemonPerformanceMonitoringSoakTest.groovy +++ b/subprojects/soak/src/integTest/groovy/org/gradle/launcher/daemon/DaemonPerformanceMonitoringSoakTest.groovy @@ -63,28 +63,6 @@ class DaemonPerformanceMonitoringSoakTest extends DaemonMultiJdkIntegrationTest 40 | "1024m" | 4000 } - def "when build leaks within available memory the daemon is not expired"() { - when: - setupBuildScript = tenuredHeapLeak - maxBuilds = 20 - heapSize = "500m" - leakRate = 300 - - then: - !daemonIsExpiredEagerly() - } - - def "greedy build with no leak does not expire daemon"() { - when: - setupBuildScript = greedyBuildNoLeak - maxBuilds = 20 - heapSize = "200m" - leakRate = 3800 - - then: - !daemonIsExpiredEagerly() - } - private boolean daemonIsExpiredEagerly() { def dataFile = file("stats") setupBuildScript() From f6a0bf0ff87b5819e220b837da3f0790ae855674 Mon Sep 17 00:00:00 2001 From: Gary Hale Date: Thu, 7 Mar 2019 18:59:25 -0500 Subject: [PATCH 395/853] Add annotation to multiversion test --- .../gc/GarbageCollectionMonitoringIntegrationTest.groovy | 3 +++ 1 file changed, 3 insertions(+) diff --git a/subprojects/launcher/src/integTest/groovy/org/gradle/launcher/daemon/server/health/gc/GarbageCollectionMonitoringIntegrationTest.groovy b/subprojects/launcher/src/integTest/groovy/org/gradle/launcher/daemon/server/health/gc/GarbageCollectionMonitoringIntegrationTest.groovy index c06f1790cd9c7..5e0a6765d7833 100644 --- a/subprojects/launcher/src/integTest/groovy/org/gradle/launcher/daemon/server/health/gc/GarbageCollectionMonitoringIntegrationTest.groovy +++ b/subprojects/launcher/src/integTest/groovy/org/gradle/launcher/daemon/server/health/gc/GarbageCollectionMonitoringIntegrationTest.groovy @@ -16,17 +16,20 @@ package org.gradle.launcher.daemon.server.health.gc +import org.gradle.integtests.fixtures.ContextualMultiVersionTest import org.gradle.integtests.fixtures.MultiVersionSpecRunner import org.gradle.integtests.fixtures.TargetCoverage import org.gradle.integtests.fixtures.daemon.DaemonIntegrationSpec import org.gradle.integtests.fixtures.daemon.JavaGarbageCollector import org.gradle.launcher.daemon.server.health.DaemonMemoryStatus import org.gradle.util.TestPrecondition +import org.junit.experimental.categories.Category import org.junit.runner.RunWith import static org.gradle.launcher.daemon.server.DaemonStateCoordinator.DAEMON_STOPPING_IMMEDIATELY_MESSAGE import static org.gradle.launcher.daemon.server.DaemonStateCoordinator.DAEMON_WILL_STOP_MESSAGE +@Category(ContextualMultiVersionTest.class) @RunWith(MultiVersionSpecRunner) @TargetCoverage({garbageCollectors}) class GarbageCollectionMonitoringIntegrationTest extends DaemonIntegrationSpec { From dfbdf283152c617ebcd91262f1aeb0993ebac137 Mon Sep 17 00:00:00 2001 From: Gradleware Git Bot Date: Fri, 8 Mar 2019 02:45:39 +0100 Subject: [PATCH 396/853] Publish 5.3-20190308013119+0000 --- released-versions.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/released-versions.json b/released-versions.json index 9b1f06278da81..8d0d180809a7f 100644 --- a/released-versions.json +++ b/released-versions.json @@ -1,7 +1,7 @@ { "latestReleaseSnapshot": { - "version": "5.3-20190307202351+0000", - "buildTime": "20190307202351+0000" + "version": "5.3-20190308013119+0000", + "buildTime": "20190308013119+0000" }, "latestRc": { "version": "5.3-rc-1", From 7f855434967e07b4e9730cff633c14fc7362c186 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=B3r=C3=A1nt=20Pint=C3=A9r?= Date: Fri, 8 Mar 2019 08:59:06 +0100 Subject: [PATCH 397/853] Add test for CreateOutputsStep --- .../steps/CreateOutputsStepTest.groovy | 69 +++++++++++++++++++ .../steps/IncrementalExecutionTest.groovy | 29 -------- .../internal/execution/steps/StepSpec.groovy | 38 ++++++++++ 3 files changed, 107 insertions(+), 29 deletions(-) create mode 100644 subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/CreateOutputsStepTest.groovy create mode 100644 subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/StepSpec.groovy diff --git a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/CreateOutputsStepTest.groovy b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/CreateOutputsStepTest.groovy new file mode 100644 index 0000000000000..3d1c570c1d4a3 --- /dev/null +++ b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/CreateOutputsStepTest.groovy @@ -0,0 +1,69 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.internal.execution.steps + +import org.gradle.api.internal.file.collections.ImmutableFileCollection +import org.gradle.internal.execution.Context +import org.gradle.internal.execution.Result +import org.gradle.internal.execution.UnitOfWork +import org.gradle.internal.file.TreeType + +class CreateOutputsStepTest extends StepSpec { + def context = Stub(Context) { + getWork() >> work + } + def step = new CreateOutputsStep(delegate) + + def "outputs are created"() { + when: + step.execute(context) + + then: + 1 * work.visitOutputProperties(_ as UnitOfWork.OutputPropertyVisitor) >> { UnitOfWork.OutputPropertyVisitor visitor -> + visitor.visitOutputProperty("dir", TreeType.DIRECTORY, ImmutableFileCollection.of(file("outDir"))) + visitor.visitOutputProperty("dirs", TreeType.DIRECTORY, ImmutableFileCollection.of(file("outDir1"), file("outDir2"))) + visitor.visitOutputProperty("file", TreeType.FILE, ImmutableFileCollection.of(file("parent/outFile"))) + visitor.visitOutputProperty("files", TreeType.FILE, ImmutableFileCollection.of(file("parent1/outFile"), file("parent2/outputFile1"), file("parent2/outputFile2"))) + } + + then: + def allDirs = ["outDir", "outDir1", "outDir2"].collect { file(it) } + def allFiles = ["parent/outFile", "parent1/outFile1", "parent2/outFile1", "parent2/outFile2"].collect { file(it) } + allDirs.each { + assert it.isDirectory() + } + allFiles.each { + assert it.parentFile.isDirectory() + assert !it.exists() + } + + then: + 1 * delegate.execute(context) + 0 * _ + } + + def "result is preserved"() { + def expected = Mock(Result) + when: + def result = step.execute(context) + + then: + result == expected + 1 * work.visitOutputProperties(_ as UnitOfWork.OutputPropertyVisitor) + 1 * delegate.execute(context) >> expected + } +} diff --git a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/IncrementalExecutionTest.groovy b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/IncrementalExecutionTest.groovy index 9347bc9547f1c..731a2683adcfe 100644 --- a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/IncrementalExecutionTest.groovy +++ b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/IncrementalExecutionTest.groovy @@ -136,35 +136,6 @@ class IncrementalExecutionTest extends Specification { ) } - def "outputs are created"() { - def unitOfWork = builder.withOutputDirs( - dir: [file("outDir")], - dirs: [file("outDir1"), file("outDir2")], - ).withOutputFiles( - "file": [file("parent/outFile")], - "files": [file("parent1/outFile"), file("parent2/outputFile1"), file("parent2/outputFile2")], - ).withWork { -> - EXECUTED - }.build() - - when: - def result = execute(unitOfWork) - - then: - result.outcome.get() == EXECUTED - !result.reused - - def allDirs = ["outDir", "outDir1", "outDir2"].collect { file(it) } - def allFiles = ["parent/outFile", "parent1/outFile1", "parent2/outFile1", "parent2/outFile2"].collect { file(it) } - allDirs.each { - assert it.isDirectory() - } - allFiles.each { - assert it.parentFile.isDirectory() - assert !it.exists() - } - } - def "output snapshots are stored"() { when: def result = execute(unitOfWork) diff --git a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/StepSpec.groovy b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/StepSpec.groovy new file mode 100644 index 0000000000000..f9a0b7d7bac7e --- /dev/null +++ b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/StepSpec.groovy @@ -0,0 +1,38 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.internal.execution.steps + + +import org.gradle.internal.execution.Step +import org.gradle.internal.execution.UnitOfWork +import org.gradle.test.fixtures.file.TestFile +import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider +import org.gradle.testing.internal.util.Specification +import org.junit.Rule + +class StepSpec extends Specification { + @Rule + final TestNameTestDirectoryProvider temporaryFolder = TestNameTestDirectoryProvider.newInstance() + + final delegate = Mock(Step) + + final work = Mock(UnitOfWork) + + protected TestFile file(Object... path) { + return temporaryFolder.file(path) + } +} From 05019368445d45c53fc48633eaff6129da5c3cb8 Mon Sep 17 00:00:00 2001 From: Jendrik Johannes Date: Thu, 7 Mar 2019 10:52:08 +0100 Subject: [PATCH 398/853] Catch and remember connect exceptions directly in 'withConnection()' This allows us to analysis this exception in the retry conditions for problems caused by bugs that exist in older Gradle versions. --- .../tooling/fixture/ToolingApiSpecification.groovy | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/subprojects/tooling-api/src/testFixtures/groovy/org/gradle/integtests/tooling/fixture/ToolingApiSpecification.groovy b/subprojects/tooling-api/src/testFixtures/groovy/org/gradle/integtests/tooling/fixture/ToolingApiSpecification.groovy index fe127bf680063..19af086d9de2e 100644 --- a/subprojects/tooling-api/src/testFixtures/groovy/org/gradle/integtests/tooling/fixture/ToolingApiSpecification.groovy +++ b/subprojects/tooling-api/src/testFixtures/groovy/org/gradle/integtests/tooling/fixture/ToolingApiSpecification.groovy @@ -138,11 +138,21 @@ abstract class ToolingApiSpecification extends Specification { } public void withConnector(@DelegatesTo(GradleConnector) @ClosureParams(value = SimpleType, options = ["org.gradle.tooling.GradleConnector"]) Closure cl) { - toolingApi.withConnector(cl) + try { + toolingApi.withConnector(cl) + } catch (GradleConnectionException e) { + caughtGradleConnectionException = e + throw e + } } public T withConnection(GradleConnector connector, @DelegatesTo(ProjectConnection) @ClosureParams(value = SimpleType, options = ["org.gradle.tooling.ProjectConnection"]) Closure cl) { - toolingApi.withConnection(connector, cl) + try { + return toolingApi.withConnection(connector, cl) + } catch (GradleConnectionException e) { + caughtGradleConnectionException = e + throw e + } } def connector() { From c01e129bb87a69c6b9fef712eb35effbff18c96d Mon Sep 17 00:00:00 2001 From: Jendrik Johannes Date: Thu, 7 Mar 2019 10:53:33 +0100 Subject: [PATCH 399/853] Revert changes to tests only added to remember an exception for retry This is now automatically done in the ToolingApiSpecification test fixture. --- ...UnsupportedBuildJvmCrossVersionSpec.groovy | 25 ++++++++++--------- ...DaemonErrorFeedbackCrossVersionSpec.groovy | 7 +++--- ...rogressDaemonErrorsCrossVersionSpec.groovy | 5 ++-- ...rializableExceptionCrossVersionSpec.groovy | 3 +-- ...UnsupportedConsumerCrossVersionSpec.groovy | 25 ++++++++++--------- ...UnsupportedProviderCrossVersionSpec.groovy | 17 +++++++------ 6 files changed, 43 insertions(+), 39 deletions(-) diff --git a/subprojects/tooling-api/src/crossVersionTest/groovy/org/gradle/integtests/tooling/ToolingApiUnsupportedBuildJvmCrossVersionSpec.groovy b/subprojects/tooling-api/src/crossVersionTest/groovy/org/gradle/integtests/tooling/ToolingApiUnsupportedBuildJvmCrossVersionSpec.groovy index b35700581fd9d..ae83504c8f2ab 100644 --- a/subprojects/tooling-api/src/crossVersionTest/groovy/org/gradle/integtests/tooling/ToolingApiUnsupportedBuildJvmCrossVersionSpec.groovy +++ b/subprojects/tooling-api/src/crossVersionTest/groovy/org/gradle/integtests/tooling/ToolingApiUnsupportedBuildJvmCrossVersionSpec.groovy @@ -21,6 +21,7 @@ import org.gradle.integtests.fixtures.AvailableJavaHomes import org.gradle.integtests.tooling.fixture.TargetGradleVersion import org.gradle.integtests.tooling.fixture.ToolingApiSpecification import org.gradle.integtests.tooling.r18.BrokenAction +import org.gradle.tooling.GradleConnectionException import org.gradle.tooling.ProjectConnection import org.gradle.tooling.model.GradleProject import org.gradle.util.Requires @@ -42,9 +43,9 @@ class ToolingApiUnsupportedBuildJvmCrossVersionSpec extends ToolingApiSpecificat } then: - caughtGradleConnectionException = thrown() - caughtGradleConnectionException.message.startsWith("Could not execute build using Gradle ") - caughtGradleConnectionException.cause.message == "Gradle ${targetDist.version.version} requires Java 8 or later to run. Your build is currently configured to use Java ${jdk.javaVersion.majorVersion}." + GradleConnectionException e = thrown() + e.message.startsWith("Could not execute build using Gradle ") + e.cause.message == "Gradle ${targetDist.version.version} requires Java 8 or later to run. Your build is currently configured to use Java ${jdk.javaVersion.majorVersion}." where: jdk << AvailableJavaHomes.getJdks("1.5", "1.6", "1.7") @@ -60,9 +61,9 @@ class ToolingApiUnsupportedBuildJvmCrossVersionSpec extends ToolingApiSpecificat } then: - caughtGradleConnectionException = thrown() - caughtGradleConnectionException.message.startsWith("Could not fetch model of type 'GradleProject' using Gradle ") - caughtGradleConnectionException.cause.message == "Gradle ${targetDist.version.version} requires Java 8 or later to run. Your build is currently configured to use Java ${jdk.javaVersion.majorVersion}." + GradleConnectionException e = thrown() + e.message.startsWith("Could not fetch model of type 'GradleProject' using Gradle ") + e.cause.message == "Gradle ${targetDist.version.version} requires Java 8 or later to run. Your build is currently configured to use Java ${jdk.javaVersion.majorVersion}." where: jdk << AvailableJavaHomes.getJdks("1.5", "1.6", "1.7") @@ -78,9 +79,9 @@ class ToolingApiUnsupportedBuildJvmCrossVersionSpec extends ToolingApiSpecificat } then: - caughtGradleConnectionException = thrown() - caughtGradleConnectionException.message.startsWith("Could not run build action using Gradle ") - caughtGradleConnectionException.cause.message == "Gradle ${targetDist.version.version} requires Java 8 or later to run. Your build is currently configured to use Java ${jdk.javaVersion.majorVersion}." + GradleConnectionException e = thrown() + e.message.startsWith("Could not run build action using Gradle ") + e.cause.message == "Gradle ${targetDist.version.version} requires Java 8 or later to run. Your build is currently configured to use Java ${jdk.javaVersion.majorVersion}." where: jdk << AvailableJavaHomes.getJdks("1.5", "1.6", "1.7") @@ -96,9 +97,9 @@ class ToolingApiUnsupportedBuildJvmCrossVersionSpec extends ToolingApiSpecificat } then: - caughtGradleConnectionException = thrown() - caughtGradleConnectionException.message.startsWith("Could not execute tests using Gradle ") - caughtGradleConnectionException.cause.message == "Gradle ${targetDist.version.version} requires Java 8 or later to run. Your build is currently configured to use Java ${jdk.javaVersion.majorVersion}." + GradleConnectionException e = thrown() + e.message.startsWith("Could not execute tests using Gradle ") + e.cause.message == "Gradle ${targetDist.version.version} requires Java 8 or later to run. Your build is currently configured to use Java ${jdk.javaVersion.majorVersion}." where: jdk << AvailableJavaHomes.getJdks("1.5", "1.6", "1.7") diff --git a/subprojects/tooling-api/src/crossVersionTest/groovy/org/gradle/integtests/tooling/m9/DaemonErrorFeedbackCrossVersionSpec.groovy b/subprojects/tooling-api/src/crossVersionTest/groovy/org/gradle/integtests/tooling/m9/DaemonErrorFeedbackCrossVersionSpec.groovy index 7eddc8528f066..2d94fa34fa8d8 100644 --- a/subprojects/tooling-api/src/crossVersionTest/groovy/org/gradle/integtests/tooling/m9/DaemonErrorFeedbackCrossVersionSpec.groovy +++ b/subprojects/tooling-api/src/crossVersionTest/groovy/org/gradle/integtests/tooling/m9/DaemonErrorFeedbackCrossVersionSpec.groovy @@ -17,6 +17,7 @@ package org.gradle.integtests.tooling.m9 import org.gradle.integtests.tooling.fixture.ToolingApiSpecification +import org.gradle.tooling.GradleConnectionException import spock.lang.Issue import spock.lang.Timeout @@ -37,8 +38,8 @@ class DaemonErrorFeedbackCrossVersionSpec extends ToolingApiSpecification { } then: - caughtGradleConnectionException = thrown() - caughtGradleConnectionException.cause.message.contains "-Xasdf" - caughtGradleConnectionException.cause.message.contains "Unable to start the daemon" + GradleConnectionException ex = thrown() + ex.cause.message.contains "-Xasdf" + ex.cause.message.contains "Unable to start the daemon" } } diff --git a/subprojects/tooling-api/src/crossVersionTest/groovy/org/gradle/integtests/tooling/r25/TestProgressDaemonErrorsCrossVersionSpec.groovy b/subprojects/tooling-api/src/crossVersionTest/groovy/org/gradle/integtests/tooling/r25/TestProgressDaemonErrorsCrossVersionSpec.groovy index 7c88d893ec0a6..72e99f6bccc7c 100644 --- a/subprojects/tooling-api/src/crossVersionTest/groovy/org/gradle/integtests/tooling/r25/TestProgressDaemonErrorsCrossVersionSpec.groovy +++ b/subprojects/tooling-api/src/crossVersionTest/groovy/org/gradle/integtests/tooling/r25/TestProgressDaemonErrorsCrossVersionSpec.groovy @@ -18,6 +18,7 @@ package org.gradle.integtests.tooling.r25 import org.gradle.integtests.tooling.fixture.ToolingApiSpecification import org.gradle.test.fixtures.server.http.BlockingHttpServer +import org.gradle.tooling.GradleConnectionException import org.gradle.tooling.ProjectConnection import org.gradle.tooling.events.OperationType import org.gradle.tooling.events.ProgressEvent @@ -51,8 +52,8 @@ class TestProgressDaemonErrorsCrossVersionSpec extends ToolingApiSpecification { } then: "build fails with a DaemonDisappearedException" - caughtGradleConnectionException = thrown() - caughtGradleConnectionException.cause.message.contains('Gradle build daemon disappeared unexpectedly') + GradleConnectionException ex = thrown() + ex.cause.message.contains('Gradle build daemon disappeared unexpectedly') and: !result.empty diff --git a/subprojects/tooling-api/src/crossVersionTest/groovy/org/gradle/integtests/tooling/r32/NonSerializableExceptionCrossVersionSpec.groovy b/subprojects/tooling-api/src/crossVersionTest/groovy/org/gradle/integtests/tooling/r32/NonSerializableExceptionCrossVersionSpec.groovy index 8505095b50a63..10d60ed6b7b8f 100644 --- a/subprojects/tooling-api/src/crossVersionTest/groovy/org/gradle/integtests/tooling/r32/NonSerializableExceptionCrossVersionSpec.groovy +++ b/subprojects/tooling-api/src/crossVersionTest/groovy/org/gradle/integtests/tooling/r32/NonSerializableExceptionCrossVersionSpec.groovy @@ -159,8 +159,7 @@ task run { } - private String getStackTraceAsString(GradleConnectionException throwable) { - caughtGradleConnectionException = throwable + private static String getStackTraceAsString(GradleConnectionException throwable) { StringWriter stringWriter = new StringWriter() throwable.printStackTrace(new PrintWriter(stringWriter)) return stringWriter.toString() diff --git a/subprojects/tooling-api/src/crossVersionTest/groovy/org/gradle/integtests/tooling/r43/ToolingApiUnsupportedConsumerCrossVersionSpec.groovy b/subprojects/tooling-api/src/crossVersionTest/groovy/org/gradle/integtests/tooling/r43/ToolingApiUnsupportedConsumerCrossVersionSpec.groovy index 6808222ce4c33..1a14f94aec9f9 100644 --- a/subprojects/tooling-api/src/crossVersionTest/groovy/org/gradle/integtests/tooling/r43/ToolingApiUnsupportedConsumerCrossVersionSpec.groovy +++ b/subprojects/tooling-api/src/crossVersionTest/groovy/org/gradle/integtests/tooling/r43/ToolingApiUnsupportedConsumerCrossVersionSpec.groovy @@ -17,6 +17,7 @@ package org.gradle.integtests.tooling.r43 import org.gradle.integtests.tooling.fixture.ToolingApiVersion +import org.gradle.tooling.GradleConnectionException import org.gradle.util.GradleVersion @ToolingApiVersion("current") @@ -27,8 +28,8 @@ class ToolingApiUnsupportedConsumerCrossVersionSpec extends ToolingApiVersionSpe build() then: - caughtGradleConnectionException = thrown() - caughtGradleConnectionException.cause.message.contains('Support for clients using a tooling API version older than 3.0 was removed in Gradle 5.0. You should upgrade your tooling API client to version 3.0 or later.') + GradleConnectionException connectionException = thrown() + connectionException.cause.message.contains('Support for clients using a tooling API version older than 3.0 was removed in Gradle 5.0. You should upgrade your tooling API client to version 3.0 or later.') } @ToolingApiVersion(">=1.2 <3.0") @@ -37,8 +38,8 @@ class ToolingApiUnsupportedConsumerCrossVersionSpec extends ToolingApiVersionSpe build() then: - caughtGradleConnectionException = thrown() - caughtGradleConnectionException.cause.message.contains("Support for clients using a tooling API version older than 3.0 was removed in Gradle 5.0. You are currently using tooling API version ${GradleVersion.current().version}. You should upgrade your tooling API client to version 3.0 or later.") + GradleConnectionException connectionException = thrown() + connectionException.cause.message.contains("Support for clients using a tooling API version older than 3.0 was removed in Gradle 5.0. You are currently using tooling API version ${GradleVersion.current().version}. You should upgrade your tooling API client to version 3.0 or later.") } @ToolingApiVersion("<1.2") @@ -47,8 +48,8 @@ class ToolingApiUnsupportedConsumerCrossVersionSpec extends ToolingApiVersionSpe getModel() then: - caughtGradleConnectionException = thrown() - caughtGradleConnectionException.cause.message.contains('Support for clients using a tooling API version older than 3.0 was removed in Gradle 5.0. You should upgrade your tooling API client to version 3.0 or later.') + GradleConnectionException connectionException = thrown() + connectionException.cause.message.contains('Support for clients using a tooling API version older than 3.0 was removed in Gradle 5.0. You should upgrade your tooling API client to version 3.0 or later.') } @ToolingApiVersion(">=1.2 <3.0") @@ -57,8 +58,8 @@ class ToolingApiUnsupportedConsumerCrossVersionSpec extends ToolingApiVersionSpe getModel() then: - caughtGradleConnectionException = thrown() - caughtGradleConnectionException.cause.message.contains("Support for clients using a tooling API version older than 3.0 was removed in Gradle 5.0. You are currently using tooling API version ${GradleVersion.current().version}. You should upgrade your tooling API client to version 3.0 or later.") + GradleConnectionException connectionException = thrown() + connectionException.cause.message.contains("Support for clients using a tooling API version older than 3.0 was removed in Gradle 5.0. You are currently using tooling API version ${GradleVersion.current().version}. You should upgrade your tooling API client to version 3.0 or later.") } @ToolingApiVersion(">=1.8 <3.0") @@ -67,8 +68,8 @@ class ToolingApiUnsupportedConsumerCrossVersionSpec extends ToolingApiVersionSpe buildAction() then: - caughtGradleConnectionException = thrown() - caughtGradleConnectionException.cause.message.contains("Support for clients using a tooling API version older than 3.0 was removed in Gradle 5.0. You are currently using tooling API version ${GradleVersion.current().version}. You should upgrade your tooling API client to version 3.0 or later.") + GradleConnectionException connectionException = thrown() + connectionException.cause.message.contains("Support for clients using a tooling API version older than 3.0 was removed in Gradle 5.0. You are currently using tooling API version ${GradleVersion.current().version}. You should upgrade your tooling API client to version 3.0 or later.") } @ToolingApiVersion(">=2.6 <3.0") @@ -77,7 +78,7 @@ class ToolingApiUnsupportedConsumerCrossVersionSpec extends ToolingApiVersionSpe testExecution() then: - caughtGradleConnectionException = thrown() - caughtGradleConnectionException.cause.message.contains("Support for clients using a tooling API version older than 3.0 was removed in Gradle 5.0. You are currently using tooling API version ${GradleVersion.current().version}. You should upgrade your tooling API client to version 3.0 or later.") + GradleConnectionException connectionException = thrown() + connectionException.cause.message.contains("Support for clients using a tooling API version older than 3.0 was removed in Gradle 5.0. You are currently using tooling API version ${GradleVersion.current().version}. You should upgrade your tooling API client to version 3.0 or later.") } } diff --git a/subprojects/tooling-api/src/crossVersionTest/groovy/org/gradle/integtests/tooling/r43/ToolingApiUnsupportedProviderCrossVersionSpec.groovy b/subprojects/tooling-api/src/crossVersionTest/groovy/org/gradle/integtests/tooling/r43/ToolingApiUnsupportedProviderCrossVersionSpec.groovy index 4153a2a132540..b9a67e5a12868 100644 --- a/subprojects/tooling-api/src/crossVersionTest/groovy/org/gradle/integtests/tooling/r43/ToolingApiUnsupportedProviderCrossVersionSpec.groovy +++ b/subprojects/tooling-api/src/crossVersionTest/groovy/org/gradle/integtests/tooling/r43/ToolingApiUnsupportedProviderCrossVersionSpec.groovy @@ -18,6 +18,7 @@ package org.gradle.integtests.tooling.r43 import org.gradle.integtests.tooling.fixture.TargetGradleVersion import org.gradle.integtests.tooling.fixture.ToolingApiVersion +import org.gradle.tooling.GradleConnectionException @ToolingApiVersion("current") class ToolingApiUnsupportedProviderCrossVersionSpec extends ToolingApiVersionSpecification { @@ -27,8 +28,8 @@ class ToolingApiUnsupportedProviderCrossVersionSpec extends ToolingApiVersionSpe build() then: - caughtGradleConnectionException = thrown() - caughtGradleConnectionException.message.contains("Support for builds using Gradle versions older than 2.6 was removed in tooling API version 5.0. You are currently using Gradle version ${targetDist.version.version}. You should upgrade your Gradle build to use Gradle 2.6 or later.") + GradleConnectionException connectionException = thrown() + connectionException.message.contains("Support for builds using Gradle versions older than 2.6 was removed in tooling API version 5.0. You are currently using Gradle version ${targetDist.version.version}. You should upgrade your Gradle build to use Gradle 2.6 or later.") } @TargetGradleVersion("<2.6") @@ -37,8 +38,8 @@ class ToolingApiUnsupportedProviderCrossVersionSpec extends ToolingApiVersionSpe getModel() then: - caughtGradleConnectionException = thrown() - caughtGradleConnectionException.message.contains("Support for builds using Gradle versions older than 2.6 was removed in tooling API version 5.0. You are currently using Gradle version ${targetDist.version.version}. You should upgrade your Gradle build to use Gradle 2.6 or later.") + GradleConnectionException connectionException = thrown() + connectionException.message.contains("Support for builds using Gradle versions older than 2.6 was removed in tooling API version 5.0. You are currently using Gradle version ${targetDist.version.version}. You should upgrade your Gradle build to use Gradle 2.6 or later.") } @TargetGradleVersion("<2.6") @@ -47,8 +48,8 @@ class ToolingApiUnsupportedProviderCrossVersionSpec extends ToolingApiVersionSpe buildAction() then: - caughtGradleConnectionException = thrown() - caughtGradleConnectionException.message.contains("Support for builds using Gradle versions older than 2.6 was removed in tooling API version 5.0. You are currently using Gradle version ${targetDist.version.version}. You should upgrade your Gradle build to use Gradle 2.6 or later.") + GradleConnectionException connectionException = thrown() + connectionException.message.contains("Support for builds using Gradle versions older than 2.6 was removed in tooling API version 5.0. You are currently using Gradle version ${targetDist.version.version}. You should upgrade your Gradle build to use Gradle 2.6 or later.") } @TargetGradleVersion("<2.6") @@ -57,7 +58,7 @@ class ToolingApiUnsupportedProviderCrossVersionSpec extends ToolingApiVersionSpe testExecution() then: - caughtGradleConnectionException = thrown() - caughtGradleConnectionException.message.contains("Support for builds using Gradle versions older than 2.6 was removed in tooling API version 5.0. You are currently using Gradle version ${targetDist.version.version}. You should upgrade your Gradle build to use Gradle 2.6 or later.") + GradleConnectionException connectionException = thrown() + connectionException.message.contains("Support for builds using Gradle versions older than 2.6 was removed in tooling API version 5.0. You are currently using Gradle version ${targetDist.version.version}. You should upgrade your Gradle build to use Gradle 2.6 or later.") } } From 74f73845c528515f8fc285f5a0f7641de26306f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=B3r=C3=A1nt=20Pint=C3=A9r?= Date: Fri, 8 Mar 2019 09:25:59 +0100 Subject: [PATCH 400/853] Add test for StoreSnapshotsStep --- .../execution/steps/StoreSnapshotsStep.java | 18 +- .../steps/FingerprinterFixture.groovy | 64 +++++++ .../steps/StoreSnapshotsStepTest.groovy | 166 ++++++++++++++++++ 3 files changed, 243 insertions(+), 5 deletions(-) create mode 100644 subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/FingerprinterFixture.groovy create mode 100644 subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/StoreSnapshotsStepTest.groovy diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/StoreSnapshotsStep.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/StoreSnapshotsStep.java index 8e9b23baf924c..f354a5e08b9a2 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/StoreSnapshotsStep.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/StoreSnapshotsStep.java @@ -49,12 +49,10 @@ public CurrentSnapshotResult execute(C context) { ImmutableSortedMap finalOutputs = result.getFinalOutputs(); context.getBeforeExecutionState().ifPresent(beforeExecutionState -> { boolean successful = result.getOutcome().isSuccessful(); - Optional afterPreviousExecutionState = context.getAfterPreviousExecutionState(); // Only persist history if there was no failure, or some output files have been changed - UnitOfWork work = context.getWork(); if (successful - || !afterPreviousExecutionState.isPresent() - || hasAnyOutputFileChanges(afterPreviousExecutionState.get().getOutputFileProperties(), finalOutputs)) { + || didChangeOutput(context.getAfterPreviousExecutionState(), finalOutputs)) { + UnitOfWork work = context.getWork(); work.getExecutionHistoryStore().store( work.getIdentity(), result.getOriginMetadata(), @@ -72,10 +70,20 @@ public CurrentSnapshotResult execute(C context) { return result; } - private static boolean hasAnyOutputFileChanges(ImmutableSortedMap previous, ImmutableSortedMap current) { + @SuppressWarnings("OptionalUsedAsFieldOrParameterType") + private static boolean didChangeOutput(Optional afterPreviousExecutionState, ImmutableSortedMap current) { + // If there is no previous state, then we do have output changes + if (!afterPreviousExecutionState.isPresent()) { + return true; + } + + // If there are different output properties compared to the previous execution, then we do have output changes + ImmutableSortedMap previous = afterPreviousExecutionState.get().getOutputFileProperties(); if (!previous.keySet().equals(current.keySet())) { return true; } + + // Otherwise do deep compare of outputs ChangeDetectorVisitor visitor = new ChangeDetectorVisitor(); OutputFileChanges changes = new OutputFileChanges(previous, current, true); changes.accept(visitor); diff --git a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/FingerprinterFixture.groovy b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/FingerprinterFixture.groovy new file mode 100644 index 0000000000000..82fedaa454e18 --- /dev/null +++ b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/FingerprinterFixture.groovy @@ -0,0 +1,64 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.internal.execution.steps + +import com.google.common.collect.ImmutableSortedMap +import org.gradle.api.internal.cache.StringInterner +import org.gradle.api.internal.file.TestFiles +import org.gradle.api.internal.file.collections.ImmutableFileCollection +import org.gradle.internal.fingerprint.CurrentFileCollectionFingerprint +import org.gradle.internal.fingerprint.impl.AbsolutePathFileCollectionFingerprinter +import org.gradle.internal.hash.TestFileHasher +import org.gradle.internal.snapshot.WellKnownFileLocations +import org.gradle.internal.snapshot.impl.DefaultFileSystemMirror +import org.gradle.internal.snapshot.impl.DefaultFileSystemSnapshotter +import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider + +abstract trait FingerprinterFixture { + abstract TestNameTestDirectoryProvider getTemporaryFolder() + + final fingerprinter = new AbsolutePathFileCollectionFingerprinter( + new DefaultFileSystemSnapshotter( + new TestFileHasher(), + new StringInterner(), + TestFiles.fileSystem(), + new DefaultFileSystemMirror(new NoWellKnownFileLocations()) + ) + ) + + ImmutableSortedMap fingerprintsOf(Map properties) { + def builder = ImmutableSortedMap.naturalOrder() + properties.each { propertyName, value -> + def files = (value instanceof Iterable + ? (Collection) value + : [value]).collect { + it instanceof File + ? it + : temporaryFolder.file(it) + } + builder.put(propertyName, fingerprinter.fingerprint(ImmutableFileCollection.of(files))) + } + return builder.build() + } + + private static class NoWellKnownFileLocations implements WellKnownFileLocations { + @Override + boolean isImmutable(String path) { + return false + } + } +} diff --git a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/StoreSnapshotsStepTest.groovy b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/StoreSnapshotsStepTest.groovy new file mode 100644 index 0000000000000..cfb57055c0f91 --- /dev/null +++ b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/StoreSnapshotsStepTest.groovy @@ -0,0 +1,166 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.internal.execution.steps + +import com.google.common.collect.ImmutableList +import com.google.common.collect.ImmutableSortedMap +import org.gradle.caching.internal.origin.OriginMetadata +import org.gradle.internal.Try +import org.gradle.internal.execution.CurrentSnapshotResult +import org.gradle.internal.execution.ExecutionOutcome +import org.gradle.internal.execution.IncrementalContext +import org.gradle.internal.execution.history.AfterPreviousExecutionState +import org.gradle.internal.execution.history.BeforeExecutionState +import org.gradle.internal.execution.history.ExecutionHistoryStore +import org.gradle.internal.execution.history.OutputFilesRepository +import org.gradle.internal.fingerprint.CurrentFileCollectionFingerprint +import org.gradle.internal.hash.HashCode +import org.gradle.internal.snapshot.impl.ImplementationSnapshot + +class StoreSnapshotsStepTest extends StepSpec implements FingerprinterFixture { + def outputFilesRepository = Mock(OutputFilesRepository) + def executionHistoryStore = Mock(ExecutionHistoryStore) + + def originMetadata = Mock(OriginMetadata) + def implementationSnapshot = ImplementationSnapshot.of("Test", HashCode.fromInt(123)) + def additionalImplementations = ImmutableList.of() + def inputProperties = ImmutableSortedMap.of() + def inputFileProperties = ImmutableSortedMap.of() + def beforeExecutionState = Stub(BeforeExecutionState) { + getImplementation() >> implementationSnapshot + getAdditionalImplementations() >> additionalImplementations + getInputProperties() >> inputProperties + getInputFileProperties() >> inputFileProperties + } + def identity = "identity" + + def outputFile = file("output.txt").text = "output" + def finalOutputs = fingerprintsOf(output: outputFile) + + def context = Mock(IncrementalContext) + def step = new StoreSnapshotsStep(outputFilesRepository, delegate) + def delegateResult = Mock(CurrentSnapshotResult) + + def "output snapshots are stored after successful execution"() { + when: + def result = step.execute(context) + + then: + result == delegateResult + 1 * delegate.execute(context) >> delegateResult + + then: + 1 * delegateResult.finalOutputs >> finalOutputs + 1 * context.beforeExecutionState >> Optional.of(beforeExecutionState) + 1 * delegateResult.outcome >> Try.successful(ExecutionOutcome.EXECUTED) + + then: + interaction { expectStore(true, finalOutputs) } + + then: + 1 * outputFilesRepository.recordOutputs(finalOutputs.values()) + } + + def "output snapshots are stored after failed execution when there's no previous state available"() { + when: + def result = step.execute(context) + + then: + result == delegateResult + 1 * delegate.execute(context) >> delegateResult + + then: + 1 * delegateResult.finalOutputs >> finalOutputs + 1 * context.beforeExecutionState >> Optional.of(beforeExecutionState) + 1 * delegateResult.outcome >> Try.failure(new RuntimeException("execution error")) + + then: + 1 * context.afterPreviousExecutionState >> Optional.empty() + + then: + interaction { expectStore(false, finalOutputs) } + + then: + 1 * outputFilesRepository.recordOutputs(finalOutputs.values()) + } + + def "output snapshots are stored after failed execution with changed outputs"() { + def afterPreviousExecutionState = Mock(AfterPreviousExecutionState) + + when: + def result = step.execute(context) + + then: + result == delegateResult + 1 * delegate.execute(context) >> delegateResult + + then: + 1 * delegateResult.finalOutputs >> finalOutputs + 1 * context.beforeExecutionState >> Optional.of(beforeExecutionState) + 1 * delegateResult.outcome >> Try.failure(new RuntimeException("execution error")) + + then: + 1 * context.afterPreviousExecutionState >> Optional.of(afterPreviousExecutionState) + 1 * afterPreviousExecutionState.outputFileProperties >> fingerprintsOf([:]) + + then: + interaction { expectStore(false, finalOutputs) } + + then: + 1 * outputFilesRepository.recordOutputs(finalOutputs.values()) + } + + def "output snapshots are not stored after failed execution with unchanged outputs"() { + def afterPreviousExecutionState = Mock(AfterPreviousExecutionState) + + when: + def result = step.execute(context) + + then: + result == delegateResult + 1 * delegate.execute(context) >> delegateResult + + then: + 1 * delegateResult.finalOutputs >> finalOutputs + 1 * context.beforeExecutionState >> Optional.of(beforeExecutionState) + 1 * delegateResult.outcome >> Try.failure(new RuntimeException("execution error")) + + then: + 1 * context.afterPreviousExecutionState >> Optional.of(afterPreviousExecutionState) + 1 * afterPreviousExecutionState.outputFileProperties >> finalOutputs + + then: + 1 * outputFilesRepository.recordOutputs(finalOutputs.values()) + } + + void expectStore(boolean successful, ImmutableSortedMap finalOutputs) { + 1 * context.work >> work + 1 * work.executionHistoryStore >> executionHistoryStore + 1 * work.identity >> identity + 1 * delegateResult.originMetadata >> originMetadata + 1 * executionHistoryStore.store( + identity, + originMetadata, + implementationSnapshot, + additionalImplementations, + inputProperties, + inputFileProperties, + finalOutputs, + successful + ) + } +} From a2309a47d6a5e5c679dfe5f5ff84976b38e5b43a Mon Sep 17 00:00:00 2001 From: Stefan Wolf Date: Fri, 8 Mar 2019 09:31:58 +0100 Subject: [PATCH 401/853] Extract common build logic --- .teamcity/Gradle_AgentTest/settings.kts | 8 +- .../configurations/BaseGradleBuildType.kt | 2 +- .../configurations/FunctionalTest.kt | 4 +- .../GradleBuildConfigurationDefaults.kt | 46 +++------ .../configurations/Gradleception.kt | 1 + .../IndividualPerformanceScenarioWorkers.kt | 5 +- .../configurations/PerformanceTest.kt | 5 +- .../configurations/StagePasses.kt | 1 + .teamcity/Gradle_Check/model/CIBuildModel.kt | 96 +++++++------------ .../buildTypes/BasePromoteSnapshot.kt | 12 ++- .../buildTypes/BasePromotionBuildType.kt | 6 +- .../buildTypes/MasterSanityCheck.kt | 14 +-- .../buildTypes/StartReleaseCycle.kt | 4 +- .../buildTypes/StartReleaseCycleTest.kt | 5 +- .teamcity/common/BuildCache.kt | 42 ++++++++ .teamcity/common/JvmVendor.kt | 21 ++++ .teamcity/common/JvmVersion.kt | 21 ++++ .teamcity/common/Os.kt | 21 ++++ .teamcity/common/extensions.kt | 44 +++++++++ .../ApplyDefaultConfigurationTest.kt | 5 +- .../CIConfigIntegrationTests.kt | 34 +++---- 21 files changed, 252 insertions(+), 145 deletions(-) create mode 100644 .teamcity/common/BuildCache.kt create mode 100644 .teamcity/common/JvmVendor.kt create mode 100644 .teamcity/common/JvmVersion.kt create mode 100644 .teamcity/common/Os.kt create mode 100644 .teamcity/common/extensions.kt diff --git a/.teamcity/Gradle_AgentTest/settings.kts b/.teamcity/Gradle_AgentTest/settings.kts index 51ff91438f3b8..2fe64eef92a85 100644 --- a/.teamcity/Gradle_AgentTest/settings.kts +++ b/.teamcity/Gradle_AgentTest/settings.kts @@ -1,11 +1,11 @@ package Gradle_AgentTest +import common.JvmVersion +import common.NoBuildCache +import common.Os import jetbrains.buildServer.configs.kotlin.v2018_2.project import jetbrains.buildServer.configs.kotlin.v2018_2.version import model.CIBuildModel -import model.JvmVersion -import model.NoBuildCache -import model.OS import model.SpecificBuild import model.Stage import model.StageNames @@ -56,7 +56,7 @@ val buildModel = CIBuildModel( Stage(StageNames.QUICK_FEEDBACK_LINUX_ONLY, runsIndependent = true, specificBuilds = listOf(SpecificBuild.CompileAll, SpecificBuild.SanityCheck), - functionalTests = listOf(TestCoverage(TestType.quick, OS.linux, JvmVersion.java8))) + functionalTests = listOf(TestCoverage(TestType.quick, Os.linux, JvmVersion.java8))) ) ) project(RootProject(buildModel)) diff --git a/.teamcity/Gradle_Check/configurations/BaseGradleBuildType.kt b/.teamcity/Gradle_Check/configurations/BaseGradleBuildType.kt index e7e81dca491a9..c44d1a045a597 100644 --- a/.teamcity/Gradle_Check/configurations/BaseGradleBuildType.kt +++ b/.teamcity/Gradle_Check/configurations/BaseGradleBuildType.kt @@ -1,7 +1,7 @@ package configurations +import common.BuildCache import jetbrains.buildServer.configs.kotlin.v2018_2.BuildType -import model.BuildCache import model.CIBuildModel import model.Stage diff --git a/.teamcity/Gradle_Check/configurations/FunctionalTest.kt b/.teamcity/Gradle_Check/configurations/FunctionalTest.kt index df6dc67f3b58e..cefbc48226787 100644 --- a/.teamcity/Gradle_Check/configurations/FunctionalTest.kt +++ b/.teamcity/Gradle_Check/configurations/FunctionalTest.kt @@ -1,8 +1,8 @@ package configurations +import common.Os import jetbrains.buildServer.configs.kotlin.v2018_2.AbsoluteId import model.CIBuildModel -import model.OS import model.Stage import model.TestCoverage import model.TestType @@ -33,7 +33,7 @@ class FunctionalTest(model: CIBuildModel, testCoverage: TestCoverage, subProject params { param("env.JAVA_HOME", "%${testCoverage.os}.${testCoverage.buildJvmVersion}.openjdk.64bit%") - if (testCoverage.os == OS.linux) { + if (testCoverage.os == Os.linux) { param("env.ANDROID_HOME", "/opt/android/sdk") } } diff --git a/.teamcity/Gradle_Check/configurations/GradleBuildConfigurationDefaults.kt b/.teamcity/Gradle_Check/configurations/GradleBuildConfigurationDefaults.kt index 1ebd4d45b9403..1e2cb4c1ac87e 100644 --- a/.teamcity/Gradle_Check/configurations/GradleBuildConfigurationDefaults.kt +++ b/.teamcity/Gradle_Check/configurations/GradleBuildConfigurationDefaults.kt @@ -1,5 +1,8 @@ package configurations +import common.Os +import common.gradleWrapper +import common.requiresOs import jetbrains.buildServer.configs.kotlin.v2018_2.AbsoluteId import jetbrains.buildServer.configs.kotlin.v2018_2.BuildFeatures import jetbrains.buildServer.configs.kotlin.v2018_2.BuildStep @@ -9,11 +12,9 @@ import jetbrains.buildServer.configs.kotlin.v2018_2.CheckoutMode import jetbrains.buildServer.configs.kotlin.v2018_2.FailureAction import jetbrains.buildServer.configs.kotlin.v2018_2.ProjectFeatures import jetbrains.buildServer.configs.kotlin.v2018_2.buildFeatures.commitStatusPublisher -import jetbrains.buildServer.configs.kotlin.v2018_2.buildSteps.GradleBuildStep import jetbrains.buildServer.configs.kotlin.v2018_2.buildSteps.script import model.CIBuildModel import model.GradleSubproject -import model.OS import model.TestCoverage @@ -58,7 +59,7 @@ val m2CleanScriptWindows = """ ) """.trimIndent() -fun applyDefaultSettings(buildType: BuildType, os: OS = OS.linux, timeout: Int = 30, vcsRoot: String = "Gradle_Branches_GradlePersonalBranches") { +fun applyDefaultSettings(buildType: BuildType, os: Os = Os.linux, timeout: Int = 30, vcsRoot: String = "Gradle_Branches_GradlePersonalBranches") { buildType.artifactRules = """ build/report-* => . buildSrc/build/report-* => . @@ -74,14 +75,14 @@ fun applyDefaultSettings(buildType: BuildType, os: OS = OS.linux, timeout: Int = } buildType.requirements { - contains("teamcity.agent.jvm.os.name", os.agentRequirement) + requiresOs(os) } buildType.failureConditions { executionTimeoutMin = timeout } - if (os == OS.linux || os == OS.macos) { + if (os == Os.linux || os == Os.macos) { buildType.params { param("env.LC_ALL", "en_US.UTF-8") } @@ -110,12 +111,12 @@ fun ProjectFeatures.buildReportTab(title: String, startPage: String) { } private -fun BaseGradleBuildType.checkCleanM2Step(os: OS = OS.linux) { +fun BaseGradleBuildType.checkCleanM2Step(os: Os = Os.linux) { steps { script { name = "CHECK_CLEAN_M2" executionMode = BuildStep.ExecutionMode.ALWAYS - scriptContent = if (os == OS.windows) m2CleanScriptWindows else m2CleanScriptUnixLike + scriptContent = if (os == Os.windows) m2CleanScriptWindows else m2CleanScriptUnixLike } } } @@ -146,7 +147,7 @@ fun BaseGradleBuildType.tagBuildStep(model: CIBuildModel, daemon: Boolean = true } private -fun BaseGradleBuildType.gradleRunnerStep(model: CIBuildModel, gradleTasks: String, os: OS = OS.linux, extraParameters: String = "", daemon: Boolean = true) { +fun BaseGradleBuildType.gradleRunnerStep(model: CIBuildModel, gradleTasks: String, os: Os = Os.linux, extraParameters: String = "", daemon: Boolean = true) { val buildScanTags = model.buildScanTags + listOfNotNull(stage?.id) steps { @@ -167,7 +168,7 @@ fun BaseGradleBuildType.gradleRunnerStep(model: CIBuildModel, gradleTasks: Strin } private -fun BaseGradleBuildType.gradleRerunnerStep(model: CIBuildModel, gradleTasks: String, os: OS = OS.linux, extraParameters: String = "", daemon: Boolean = true) { +fun BaseGradleBuildType.gradleRerunnerStep(model: CIBuildModel, gradleTasks: String, os: Os = Os.linux, extraParameters: String = "", daemon: Boolean = true) { val buildScanTags = model.buildScanTags + listOfNotNull(stage?.id) steps { @@ -190,8 +191,8 @@ fun BaseGradleBuildType.gradleRerunnerStep(model: CIBuildModel, gradleTasks: Str } private -fun BaseGradleBuildType.killProcessStepIfNecessary(stepName: String, os: OS = OS.linux, daemon: Boolean = true) { - if (os == OS.windows) { +fun BaseGradleBuildType.killProcessStepIfNecessary(stepName: String, os: Os = Os.linux, daemon: Boolean = true) { + if (os == Os.windows) { steps { gradleWrapper { name = stepName @@ -203,7 +204,7 @@ fun BaseGradleBuildType.killProcessStepIfNecessary(stepName: String, os: OS = OS } } -fun applyDefaults(model: CIBuildModel, buildType: BaseGradleBuildType, gradleTasks: String, notQuick: Boolean = false, os: OS = OS.linux, extraParameters: String = "", timeout: Int = 90, extraSteps: BuildSteps.() -> Unit = {}, daemon: Boolean = true) { +fun applyDefaults(model: CIBuildModel, buildType: BaseGradleBuildType, gradleTasks: String, notQuick: Boolean = false, os: Os = Os.linux, extraParameters: String = "", timeout: Int = 90, extraSteps: BuildSteps.() -> Unit = {}, daemon: Boolean = true) { applyDefaultSettings(buildType, os, timeout) buildType.gradleRunnerStep(model, gradleTasks, os, extraParameters, daemon) @@ -217,7 +218,7 @@ fun applyDefaults(model: CIBuildModel, buildType: BaseGradleBuildType, gradleTas applyDefaultDependencies(model, buildType, notQuick) } -fun applyTestDefaults(model: CIBuildModel, buildType: BaseGradleBuildType, gradleTasks: String, notQuick: Boolean = false, os: OS = OS.linux, extraParameters: String = "", timeout: Int = 90, extraSteps: BuildSteps.() -> Unit = {}, daemon: Boolean = true) { +fun applyTestDefaults(model: CIBuildModel, buildType: BaseGradleBuildType, gradleTasks: String, notQuick: Boolean = false, os: Os = Os.linux, extraParameters: String = "", timeout: Int = 90, extraSteps: BuildSteps.() -> Unit = {}, daemon: Boolean = true) { applyDefaultSettings(buildType, os, timeout) buildType.gradleRunnerStep(model, gradleTasks, os, extraParameters, daemon) @@ -270,22 +271,3 @@ fun applyDefaultDependencies(model: CIBuildModel, buildType: BuildType, notQuick } } } - -/** - * Adds a [Gradle build step](https://confluence.jetbrains.com/display/TCDL/Gradle) - * that runs with the Gradle wrapper. - * - * @see GradleBuildStep - */ -fun BuildSteps.gradleWrapper(init: GradleBuildStep.() -> Unit): GradleBuildStep = - customGradle(init) { - useGradleWrapper = true - if (buildFile == null) { - buildFile = "" // Let Gradle detect the build script - } - } - -fun BuildSteps.customGradle(init: GradleBuildStep.() -> Unit, custom: GradleBuildStep.() -> Unit): GradleBuildStep = - GradleBuildStep(init) - .apply(custom) - .also { step(it) } diff --git a/.teamcity/Gradle_Check/configurations/Gradleception.kt b/.teamcity/Gradle_Check/configurations/Gradleception.kt index 0e702ad776cbd..d9ed5b4a485e3 100644 --- a/.teamcity/Gradle_Check/configurations/Gradleception.kt +++ b/.teamcity/Gradle_Check/configurations/Gradleception.kt @@ -1,5 +1,6 @@ package configurations +import common.customGradle import jetbrains.buildServer.configs.kotlin.v2018_2.AbsoluteId import jetbrains.buildServer.configs.kotlin.v2018_2.BuildSteps import jetbrains.buildServer.configs.kotlin.v2018_2.buildSteps.GradleBuildStep diff --git a/.teamcity/Gradle_Check/configurations/IndividualPerformanceScenarioWorkers.kt b/.teamcity/Gradle_Check/configurations/IndividualPerformanceScenarioWorkers.kt index 3f1d7dcfda66e..42bc613cd8b79 100644 --- a/.teamcity/Gradle_Check/configurations/IndividualPerformanceScenarioWorkers.kt +++ b/.teamcity/Gradle_Check/configurations/IndividualPerformanceScenarioWorkers.kt @@ -1,10 +1,11 @@ package configurations +import common.Os +import common.gradleWrapper import jetbrains.buildServer.configs.kotlin.v2018_2.AbsoluteId import jetbrains.buildServer.configs.kotlin.v2018_2.BuildStep import jetbrains.buildServer.configs.kotlin.v2018_2.buildSteps.script import model.CIBuildModel -import model.OS class IndividualPerformanceScenarioWorkers(model: CIBuildModel) : BaseGradleBuildType(model, init = { uuid = model.projectPrefix + "IndividualPerformanceScenarioWorkersLinux" @@ -44,7 +45,7 @@ class IndividualPerformanceScenarioWorkers(model: CIBuildModel) : BaseGradleBuil gradleParameters(isContinue = false) + listOf("""clean %templates% fullPerformanceTests --scenarios "%scenario%" --baselines %baselines% --warmups %warmups% --runs %runs% --checks %checks% --channel %channel% -x prepareSamples -Porg.gradle.performance.branchName=%teamcity.build.branch% -Porg.gradle.performance.db.url=%performance.db.url% -Porg.gradle.performance.db.username=%performance.db.username% -Porg.gradle.performance.db.password=%performance.db.password.tcagent% -PtimestampedVersion""", buildScanTag("IndividualPerformanceScenarioWorkers"), "-PtestJavaHome=${individualPerformanceTestJavaHome}") - + model.parentBuildCache.gradleParameters(OS.linux) + + model.parentBuildCache.gradleParameters(Os.linux) ).joinToString(separator = " ") } script { diff --git a/.teamcity/Gradle_Check/configurations/PerformanceTest.kt b/.teamcity/Gradle_Check/configurations/PerformanceTest.kt index 6bd8940d62563..7bbf13d251040 100644 --- a/.teamcity/Gradle_Check/configurations/PerformanceTest.kt +++ b/.teamcity/Gradle_Check/configurations/PerformanceTest.kt @@ -1,10 +1,11 @@ package configurations +import common.Os +import common.gradleWrapper import jetbrains.buildServer.configs.kotlin.v2018_2.AbsoluteId import jetbrains.buildServer.configs.kotlin.v2018_2.BuildStep import jetbrains.buildServer.configs.kotlin.v2018_2.buildSteps.script import model.CIBuildModel -import model.OS import model.PerformanceTestType import model.Stage @@ -48,7 +49,7 @@ class PerformanceTest(model: CIBuildModel, type: PerformanceTestType, stage: Sta gradleParameters() + listOf("clean distributed${type.taskId}s -x prepareSamples --baselines %performance.baselines% ${type.extraParameters} -PtimestampedVersion -Porg.gradle.performance.branchName=%teamcity.build.branch% -Porg.gradle.performance.db.url=%performance.db.url% -Porg.gradle.performance.db.username=%performance.db.username% -PteamCityUsername=%TC_USERNAME% -PteamCityPassword=%teamcity.password.restbot% -Porg.gradle.performance.buildTypeId=${IndividualPerformanceScenarioWorkers(model).id} -Porg.gradle.performance.workerTestTaskName=fullPerformanceTest -Porg.gradle.performance.coordinatorBuildId=%teamcity.build.id% -Porg.gradle.performance.db.password=%performance.db.password.tcagent%", buildScanTag("PerformanceTest"), "-PtestJavaHome=${coordinatorPerformanceTestJavaHome}") - + model.parentBuildCache.gradleParameters(OS.linux) + + model.parentBuildCache.gradleParameters(Os.linux) ).joinToString(separator = " ") } script { diff --git a/.teamcity/Gradle_Check/configurations/StagePasses.kt b/.teamcity/Gradle_Check/configurations/StagePasses.kt index f5f5642b0e0ec..3e465c7521cdd 100644 --- a/.teamcity/Gradle_Check/configurations/StagePasses.kt +++ b/.teamcity/Gradle_Check/configurations/StagePasses.kt @@ -1,5 +1,6 @@ package configurations +import common.gradleWrapper import jetbrains.buildServer.configs.kotlin.v2018_2.AbsoluteId import jetbrains.buildServer.configs.kotlin.v2018_2.BuildStep import jetbrains.buildServer.configs.kotlin.v2018_2.FailureAction diff --git a/.teamcity/Gradle_Check/model/CIBuildModel.kt b/.teamcity/Gradle_Check/model/CIBuildModel.kt index f329f39edee36..dad653f42ad9e 100644 --- a/.teamcity/Gradle_Check/model/CIBuildModel.kt +++ b/.teamcity/Gradle_Check/model/CIBuildModel.kt @@ -1,5 +1,10 @@ package model +import common.BuildCache +import common.JvmVendor +import common.JvmVersion +import common.Os +import common.builtInRemoteBuildCacheNode import configurations.BuildDistributions import configurations.CompileAll import configurations.DependenciesCheck @@ -21,23 +26,23 @@ enum class StageNames(override val stageName: String, override val description: data class CIBuildModel ( - val projectPrefix: String = "Gradle_Check_", - val rootProjectName: String = "Check", - val tagBuilds: Boolean = true, - val publishStatusToGitHub: Boolean = true, - val masterAndReleaseBranches: List = listOf("master", "release"), - val parentBuildCache: BuildCache = RemoteBuildCache("%gradle.cache.remote.url%"), - val childBuildCache: BuildCache = RemoteBuildCache("%gradle.cache.remote.url%"), - val buildScanTags: List = emptyList(), - val stages: List = listOf( + val projectPrefix: String = "Gradle_Check_", + val rootProjectName: String = "Check", + val tagBuilds: Boolean = true, + val publishStatusToGitHub: Boolean = true, + val masterAndReleaseBranches: List = listOf("master", "release"), + val parentBuildCache: BuildCache = builtInRemoteBuildCacheNode, + val childBuildCache: BuildCache = builtInRemoteBuildCacheNode, + val buildScanTags: List = emptyList(), + val stages: List = listOf( Stage(StageNames.QUICK_FEEDBACK_LINUX_ONLY, specificBuilds = listOf( SpecificBuild.CompileAll, SpecificBuild.SanityCheck), functionalTests = listOf( - TestCoverage(TestType.quick, OS.linux, JvmVersion.java11, vendor = JvmVendor.openjdk)), omitsSlowProjects = true), + TestCoverage(TestType.quick, Os.linux, JvmVersion.java11, vendor = JvmVendor.openjdk)), omitsSlowProjects = true), Stage(StageNames.QUICK_FEEDBACK, functionalTests = listOf( - TestCoverage(TestType.quick, OS.windows, JvmVersion.java8)), + TestCoverage(TestType.quick, Os.windows, JvmVersion.java8)), functionalTestsDependOnSpecificBuilds = true, omitsSlowProjects = true, dependsOnSanityCheck = true), @@ -47,28 +52,28 @@ data class CIBuildModel ( SpecificBuild.Gradleception, SpecificBuild.SmokeTests), functionalTests = listOf( - TestCoverage(TestType.platform, OS.linux, JvmVersion.java8), - TestCoverage(TestType.platform, OS.windows, JvmVersion.java11, vendor = JvmVendor.openjdk)), + TestCoverage(TestType.platform, Os.linux, JvmVersion.java8), + TestCoverage(TestType.platform, Os.windows, JvmVersion.java11, vendor = JvmVendor.openjdk)), performanceTests = listOf(PerformanceTestType.test), omitsSlowProjects = true), Stage(StageNames.READY_FOR_NIGHTLY, trigger = Trigger.eachCommit, functionalTests = listOf( - TestCoverage(TestType.quickFeedbackCrossVersion, OS.linux, JvmVersion.java8), - TestCoverage(TestType.quickFeedbackCrossVersion, OS.windows, JvmVersion.java8), - TestCoverage(TestType.parallel, OS.linux, JvmVersion.java11, vendor = JvmVendor.openjdk)) + TestCoverage(TestType.quickFeedbackCrossVersion, Os.linux, JvmVersion.java8), + TestCoverage(TestType.quickFeedbackCrossVersion, Os.windows, JvmVersion.java8), + TestCoverage(TestType.parallel, Os.linux, JvmVersion.java11, vendor = JvmVendor.openjdk)) ), Stage(StageNames.READY_FOR_RELEASE, trigger = Trigger.daily, functionalTests = listOf( - TestCoverage(TestType.soak, OS.linux, JvmVersion.java11, vendor = JvmVendor.openjdk), - TestCoverage(TestType.soak, OS.windows, JvmVersion.java8), - TestCoverage(TestType.allVersionsCrossVersion, OS.linux, JvmVersion.java8), - TestCoverage(TestType.allVersionsCrossVersion, OS.windows, JvmVersion.java8), - TestCoverage(TestType.noDaemon, OS.linux, JvmVersion.java8), - TestCoverage(TestType.noDaemon, OS.windows, JvmVersion.java11, vendor = JvmVendor.openjdk), - TestCoverage(TestType.platform, OS.macos, JvmVersion.java8), - TestCoverage(TestType.forceRealizeDependencyManagement, OS.linux, JvmVersion.java8)), + TestCoverage(TestType.soak, Os.linux, JvmVersion.java11, vendor = JvmVendor.openjdk), + TestCoverage(TestType.soak, Os.windows, JvmVersion.java8), + TestCoverage(TestType.allVersionsCrossVersion, Os.linux, JvmVersion.java8), + TestCoverage(TestType.allVersionsCrossVersion, Os.windows, JvmVersion.java8), + TestCoverage(TestType.noDaemon, Os.linux, JvmVersion.java8), + TestCoverage(TestType.noDaemon, Os.windows, JvmVersion.java11, vendor = JvmVendor.openjdk), + TestCoverage(TestType.platform, Os.macos, JvmVersion.java8), + TestCoverage(TestType.forceRealizeDependencyManagement, Os.linux, JvmVersion.java8)), performanceTests = listOf( PerformanceTestType.experiment)), Stage(StageNames.HISTORICAL_PERFORMANCE, @@ -79,11 +84,11 @@ data class CIBuildModel ( trigger = Trigger.never, runsIndependent = true, functionalTests = listOf( - TestCoverage(TestType.platform, OS.linux, JvmVersion.java12, vendor = JvmVendor.openjdk), - TestCoverage(TestType.platform, OS.windows, JvmVersion.java12, vendor = JvmVendor.openjdk)) + TestCoverage(TestType.platform, Os.linux, JvmVersion.java12, vendor = JvmVendor.openjdk), + TestCoverage(TestType.platform, Os.windows, JvmVersion.java12, vendor = JvmVendor.openjdk)) ) ), - val subProjects : List = listOf( + val subProjects : List = listOf( GradleSubproject("announce"), GradleSubproject("antlr"), GradleSubproject("baseServices"), @@ -192,29 +197,6 @@ data class GradleSubproject(val name: String, val unitTests: Boolean = true, val fun hasTestsOf(type: TestType) = (unitTests && type.unitTests) || (functionalTests && type.functionalTests) || (crossVersionTests && type.crossVersionTests) } -interface BuildCache { - fun gradleParameters(os: OS): List -} - -data class RemoteBuildCache(val url: String, val username: String = "%gradle.cache.remote.username%", val password: String = "%gradle.cache.remote.password%") : BuildCache { - override fun gradleParameters(os: OS): List { - return listOf("--build-cache", - os.escapeKeyValuePair("-Dgradle.cache.remote.url", url), - os.escapeKeyValuePair("-Dgradle.cache.remote.username", username), - os.escapeKeyValuePair("-Dgradle.cache.remote.password", password) - ) - } -} - -private -fun OS.escapeKeyValuePair(key: String, value: String) = if (this == OS.windows) """$key="$value"""" else """"$key=$value"""" - -object NoBuildCache : BuildCache { - override fun gradleParameters(os: OS): List { - return emptyList() - } -} - interface StageName { val stageName: String val description: String @@ -228,7 +210,7 @@ data class Stage(val stageName: StageName, val specificBuilds: List = emptyList()) { - linux("Linux"), windows("Windows"), macos("Mac", listOf("integTest", "native", "plugins", "resources", "scala", "workers", "wrapper", "platformPlay")) -} - -enum class JvmVersion { - java8, java9, java10, java11, java12 -} - enum class TestType(val unitTests: Boolean = true, val functionalTests: Boolean = true, val crossVersionTests: Boolean = false, val timeout: Int = 180) { // Include cross version tests, these take care of selecting a very small set of versions to cover when run as part of this stage, including the current version quick(true, true, true, 60), @@ -280,10 +254,6 @@ enum class TestType(val unitTests: Boolean = true, val functionalTests: Boolean forceRealizeDependencyManagement(false, true, false) } -enum class JvmVendor { - oracle, ibm, openjdk -} - enum class PerformanceTestType(val taskId: String, val timeout : Int, val defaultBaselines: String = "", val extraParameters : String = "") { test("PerformanceTest", 420, "defaults"), experiment("PerformanceExperiment", 420, "defaults"), diff --git a/.teamcity/Gradle_Promotion/buildTypes/BasePromoteSnapshot.kt b/.teamcity/Gradle_Promotion/buildTypes/BasePromoteSnapshot.kt index 7c367f3319616..b42de355c37d8 100644 --- a/.teamcity/Gradle_Promotion/buildTypes/BasePromoteSnapshot.kt +++ b/.teamcity/Gradle_Promotion/buildTypes/BasePromoteSnapshot.kt @@ -16,8 +16,11 @@ package Gradle_Promotion.buildTypes +import common.Os +import common.builtInRemoteBuildCacheNode +import common.gradleWrapper +import common.requiresOs import jetbrains.buildServer.configs.kotlin.v2018_2.AbsoluteId -import jetbrains.buildServer.configs.kotlin.v2018_2.buildSteps.gradle import jetbrains.buildServer.configs.kotlin.v2018_2.vcs.GitVcsRoot open class BasePromoteSnapshot( @@ -42,11 +45,10 @@ open class BasePromoteSnapshot( """.trimIndent() steps { - gradle { + gradleWrapper { name = "Promote" tasks = task - useGradleWrapper = true - gradleParams = """-PuseBuildReceipt $extraParameters "-PgitUserName=$gitUserName" "-PgitUserEmail=$gitUserEmail" -Igradle/buildScanInit.gradle --build-cache "-Dgradle.cache.remote.url=%gradle.cache.remote.url%" "-Dgradle.cache.remote.username=%gradle.cache.remote.username%" "-Dgradle.cache.remote.password=%gradle.cache.remote.password%"""" + gradleParams = """-PuseBuildReceipt $extraParameters "-PgitUserName=$gitUserName" "-PgitUserEmail=$gitUserEmail" -Igradle/buildScanInit.gradle ${builtInRemoteBuildCacheNode.gradleParameters(Os.linux).joinToString(" ")}""" } } dependencies { @@ -58,7 +60,7 @@ open class BasePromoteSnapshot( } requirements { - contains("teamcity.agent.jvm.os.name", "Linux") + requiresOs(Os.linux) } this.init() } diff --git a/.teamcity/Gradle_Promotion/buildTypes/BasePromotionBuildType.kt b/.teamcity/Gradle_Promotion/buildTypes/BasePromotionBuildType.kt index d00c6979ede91..31c31b7450ac0 100644 --- a/.teamcity/Gradle_Promotion/buildTypes/BasePromotionBuildType.kt +++ b/.teamcity/Gradle_Promotion/buildTypes/BasePromotionBuildType.kt @@ -16,6 +16,8 @@ package Gradle_Promotion.buildTypes +import common.Os +import common.requiresOs import jetbrains.buildServer.configs.kotlin.v2018_2.BuildType import jetbrains.buildServer.configs.kotlin.v2018_2.CheckoutMode import jetbrains.buildServer.configs.kotlin.v2018_2.vcs.GitVcsRoot @@ -25,13 +27,13 @@ open class BasePromotionBuildType(vcsRoot: GitVcsRoot, cleanCheckout: Boolean = vcs { root(vcsRoot) - checkoutMode = CheckoutMode.ON_SERVER + checkoutMode = CheckoutMode.ON_AGENT this.cleanCheckout = cleanCheckout showDependenciesChanges = true } requirements { - contains("teamcity.agent.jvm.os.name", "Linux") + requiresOs(Os.linux) } this.init() } diff --git a/.teamcity/Gradle_Promotion/buildTypes/MasterSanityCheck.kt b/.teamcity/Gradle_Promotion/buildTypes/MasterSanityCheck.kt index 45ed50213bcb5..0e2afbf7220eb 100644 --- a/.teamcity/Gradle_Promotion/buildTypes/MasterSanityCheck.kt +++ b/.teamcity/Gradle_Promotion/buildTypes/MasterSanityCheck.kt @@ -1,8 +1,10 @@ package Gradle_Promotion.buildTypes +import common.Os +import common.gradleWrapper +import common.requiresOs import jetbrains.buildServer.configs.kotlin.v2018_2.BuildType import jetbrains.buildServer.configs.kotlin.v2018_2.CheckoutMode -import jetbrains.buildServer.configs.kotlin.v2018_2.buildSteps.gradle import jetbrains.buildServer.configs.kotlin.v2018_2.triggers.vcs object MasterSanityCheck : BuildType({ @@ -14,18 +16,16 @@ object MasterSanityCheck : BuildType({ vcs { root(Gradle_Promotion.vcsRoots.Gradle_Promotion__master_) - checkoutMode = CheckoutMode.ON_SERVER + checkoutMode = CheckoutMode.ON_AGENT cleanCheckout = true showDependenciesChanges = true } steps { - gradle { - tasks = "tasks -s" - useGradleWrapper = true + gradleWrapper { + tasks = "tasks" gradleParams = "-Igradle/buildScanInit.gradle" param("org.jfrog.artifactory.selectedDeployableServer.defaultModuleVersionConfiguration", "GLOBAL") - param("ui.gradleRunner.gradle.build.file", "") } } @@ -36,6 +36,6 @@ object MasterSanityCheck : BuildType({ } requirements { - contains("teamcity.agent.jvm.os.name", "Linux") + requiresOs(Os.linux) } }) diff --git a/.teamcity/Gradle_Promotion/buildTypes/StartReleaseCycle.kt b/.teamcity/Gradle_Promotion/buildTypes/StartReleaseCycle.kt index 382a75aa13d22..a194f92020dcc 100644 --- a/.teamcity/Gradle_Promotion/buildTypes/StartReleaseCycle.kt +++ b/.teamcity/Gradle_Promotion/buildTypes/StartReleaseCycle.kt @@ -16,9 +16,9 @@ package Gradle_Promotion.buildTypes +import common.gradleWrapper import jetbrains.buildServer.configs.kotlin.v2018_2.AbsoluteId import jetbrains.buildServer.configs.kotlin.v2018_2.ParameterDisplay -import jetbrains.buildServer.configs.kotlin.v2018_2.buildSteps.gradle object StartReleaseCycle : BasePromotionBuildType(vcsRoot = Gradle_Promotion.vcsRoots.Gradle_Promotion__master_, init = { uuid = "355487d7-45b9-4387-9fc5-713e7683e6d0" @@ -38,7 +38,7 @@ object StartReleaseCycle : BasePromotionBuildType(vcsRoot = Gradle_Promotion.vcs } steps { - gradle { + gradleWrapper { name = "Promote" tasks = "clean promoteStartReleaseCycle" useGradleWrapper = true diff --git a/.teamcity/Gradle_Promotion/buildTypes/StartReleaseCycleTest.kt b/.teamcity/Gradle_Promotion/buildTypes/StartReleaseCycleTest.kt index d5827b329af15..205a89ec379c8 100644 --- a/.teamcity/Gradle_Promotion/buildTypes/StartReleaseCycleTest.kt +++ b/.teamcity/Gradle_Promotion/buildTypes/StartReleaseCycleTest.kt @@ -16,7 +16,7 @@ package Gradle_Promotion.buildTypes -import jetbrains.buildServer.configs.kotlin.v2018_2.buildSteps.gradle +import common.gradleWrapper import jetbrains.buildServer.configs.kotlin.v2018_2.triggers.schedule import jetbrains.buildServer.configs.kotlin.v2018_2.triggers.vcs @@ -27,12 +27,11 @@ object StartReleaseCycleTest : BasePromotionBuildType(vcsRoot = Gradle_Promotion description = "Test for Start Release Cycle pipeline" steps { - gradle { + gradleWrapper { name = "PromoteTest" tasks = "clean promoteStartReleaseCycle" useGradleWrapper = true gradleParams = "-PconfirmationCode=startCycle -Igradle/buildScanInit.gradle -PtestRun=1" - param("teamcity.tool.jacoco", "%teamcity.tool.jacoco.DEFAULT%") } } diff --git a/.teamcity/common/BuildCache.kt b/.teamcity/common/BuildCache.kt new file mode 100644 index 0000000000000..f03b7f039a25d --- /dev/null +++ b/.teamcity/common/BuildCache.kt @@ -0,0 +1,42 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package common + +interface BuildCache { + fun gradleParameters(os: Os): List +} + +data class RemoteBuildCache(val url: String, val username: String = "%gradle.cache.remote.username%", val password: String = "%gradle.cache.remote.password%") : BuildCache { + override fun gradleParameters(os: Os): List { + return listOf("--build-cache", + os.escapeKeyValuePair("-Dgradle.cache.remote.url", url), + os.escapeKeyValuePair("-Dgradle.cache.remote.username", username), + os.escapeKeyValuePair("-Dgradle.cache.remote.password", password) + ) + } +} + +val builtInRemoteBuildCacheNode = RemoteBuildCache("%gradle.cache.remote.url%") + +object NoBuildCache : BuildCache { + override fun gradleParameters(os: Os): List { + return emptyList() + } +} + +private +fun Os.escapeKeyValuePair(key: String, value: String) = if (this == Os.windows) """$key="$value"""" else """"$key=$value"""" diff --git a/.teamcity/common/JvmVendor.kt b/.teamcity/common/JvmVendor.kt new file mode 100644 index 0000000000000..528237a4e0088 --- /dev/null +++ b/.teamcity/common/JvmVendor.kt @@ -0,0 +1,21 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package common + +enum class JvmVendor { + oracle, ibm, openjdk +} diff --git a/.teamcity/common/JvmVersion.kt b/.teamcity/common/JvmVersion.kt new file mode 100644 index 0000000000000..26ddb0e688a10 --- /dev/null +++ b/.teamcity/common/JvmVersion.kt @@ -0,0 +1,21 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package common + +enum class JvmVersion { + java8, java9, java10, java11, java12 +} diff --git a/.teamcity/common/Os.kt b/.teamcity/common/Os.kt new file mode 100644 index 0000000000000..a406b7a2fad04 --- /dev/null +++ b/.teamcity/common/Os.kt @@ -0,0 +1,21 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package common + +enum class Os(val agentRequirement: String, val ignoredSubprojects: List = emptyList()) { + linux("Linux"), windows("Windows"), macos("Mac", listOf("integTest", "native", "plugins", "resources", "scala", "workers", "wrapper", "platformPlay")) +} diff --git a/.teamcity/common/extensions.kt b/.teamcity/common/extensions.kt new file mode 100644 index 0000000000000..1086e30403ec2 --- /dev/null +++ b/.teamcity/common/extensions.kt @@ -0,0 +1,44 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package common + +import jetbrains.buildServer.configs.kotlin.v2018_2.BuildSteps +import jetbrains.buildServer.configs.kotlin.v2018_2.Requirements +import jetbrains.buildServer.configs.kotlin.v2018_2.buildSteps.GradleBuildStep + +fun BuildSteps.customGradle(init: GradleBuildStep.() -> Unit, custom: GradleBuildStep.() -> Unit): GradleBuildStep = + GradleBuildStep(init) + .apply(custom) + .also { step(it) } + +/** + * Adds a [Gradle build step](https://confluence.jetbrains.com/display/TCDL/Gradle) + * that runs with the Gradle wrapper. + * + * @see GradleBuildStep + */ +fun BuildSteps.gradleWrapper(init: GradleBuildStep.() -> Unit): GradleBuildStep = + customGradle(init) { + useGradleWrapper = true + if (buildFile == null) { + buildFile = "" // Let Gradle detect the build script + } + } + +fun Requirements.requiresOs(os: Os) { + contains("teamcity.agent.jvm.os.name", os.agentRequirement) +} diff --git a/.teamcityTest/Gradle_Check_Tests/ApplyDefaultConfigurationTest.kt b/.teamcityTest/Gradle_Check_Tests/ApplyDefaultConfigurationTest.kt index b03a70416cba0..259d1b65221a9 100644 --- a/.teamcityTest/Gradle_Check_Tests/ApplyDefaultConfigurationTest.kt +++ b/.teamcityTest/Gradle_Check_Tests/ApplyDefaultConfigurationTest.kt @@ -1,3 +1,4 @@ +import common.Os import configurations.BaseGradleBuildType import configurations.applyDefaults import configurations.applyTestDefaults @@ -8,9 +9,7 @@ import io.mockk.mockk import io.mockk.slot import jetbrains.buildServer.configs.kotlin.v2018_2.BuildStep import jetbrains.buildServer.configs.kotlin.v2018_2.BuildSteps -import jetbrains.buildServer.configs.kotlin.v2018_2.FailureConditions import jetbrains.buildServer.configs.kotlin.v2018_2.buildSteps.GradleBuildStep -import model.OS import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Test @@ -97,7 +96,7 @@ class ApplyDefaultConfigurationTest { "'' , false, '--no-daemon'" ]) fun `can apply defaults to windows test configurations`(extraParameters: String, daemon: Boolean, expectedDaemonParam: String) { - applyTestDefaults(buildModel, buildType, "myTask", os = OS.windows, extraParameters = extraParameters, daemon = daemon) + applyTestDefaults(buildModel, buildType, "myTask", os = Os.windows, extraParameters = extraParameters, daemon = daemon) assertEquals(listOf( "GRADLE_RUNNER", diff --git a/.teamcityTest/Gradle_Check_Tests/CIConfigIntegrationTests.kt b/.teamcityTest/Gradle_Check_Tests/CIConfigIntegrationTests.kt index f16db92fddecc..7758c0c6f62a9 100644 --- a/.teamcityTest/Gradle_Check_Tests/CIConfigIntegrationTests.kt +++ b/.teamcityTest/Gradle_Check_Tests/CIConfigIntegrationTests.kt @@ -1,12 +1,12 @@ +import common.JvmVendor +import common.JvmVersion +import common.NoBuildCache +import common.Os import configurations.shouldBeSkipped import jetbrains.buildServer.configs.kotlin.v2018_2.Project import model.CIBuildModel import model.GradleSubproject -import model.JvmVendor -import model.JvmVersion -import model.NoBuildCache -import model.OS import model.SpecificBuild import model.Stage import model.StageName @@ -14,8 +14,8 @@ import model.StageNames import model.TestCoverage import model.TestType import org.junit.jupiter.api.Assertions.assertEquals -import org.junit.jupiter.api.Assertions.assertTrue import org.junit.jupiter.api.Assertions.assertFalse +import org.junit.jupiter.api.Assertions.assertTrue import org.junit.jupiter.api.Test import projects.RootProject import java.io.File @@ -37,7 +37,7 @@ class CIConfigIntegrationTests { val macOS = readyForRelease.subProjects.find { it.name.contains("Macos") }!! macOS.buildTypes.forEach { buildType -> - assertFalse(OS.macos.ignoredSubprojects.any { subproject -> + assertFalse(Os.macos.ignoredSubprojects.any { subproject -> buildType.name.endsWith("($subproject)") }) } @@ -108,8 +108,8 @@ class CIConfigIntegrationTests { SpecificBuild.SanityCheck, SpecificBuild.BuildDistributions), functionalTests = listOf( - TestCoverage(TestType.quick, OS.linux, JvmVersion.java8), - TestCoverage(TestType.quick, OS.windows, JvmVersion.java11, vendor = JvmVendor.openjdk)), + TestCoverage(TestType.quick, Os.linux, JvmVersion.java8), + TestCoverage(TestType.quick, Os.windows, JvmVersion.java11, vendor = JvmVendor.openjdk)), omitsSlowProjects = true) ) ) @@ -131,23 +131,23 @@ class CIConfigIntegrationTests { stages = listOf( Stage(DefaultStageName("Stage1", "Stage1 description"), functionalTests = listOf( - TestCoverage(TestType.quick, OS.linux, JvmVersion.java8), - TestCoverage(TestType.quick, OS.windows, JvmVersion.java8)), + TestCoverage(TestType.quick, Os.linux, JvmVersion.java8), + TestCoverage(TestType.quick, Os.windows, JvmVersion.java8)), omitsSlowProjects = true), Stage(DefaultStageName("Stage2", "Stage2 description"), functionalTests = listOf( - TestCoverage(TestType.noDaemon, OS.linux, JvmVersion.java8), - TestCoverage(TestType.noDaemon, OS.windows, JvmVersion.java8)), + TestCoverage(TestType.noDaemon, Os.linux, JvmVersion.java8), + TestCoverage(TestType.noDaemon, Os.windows, JvmVersion.java8)), omitsSlowProjects = true), Stage(DefaultStageName("Stage3", "Stage3 description"), functionalTests = listOf( - TestCoverage(TestType.platform, OS.linux, JvmVersion.java8), - TestCoverage(TestType.platform, OS.windows, JvmVersion.java8)), + TestCoverage(TestType.platform, Os.linux, JvmVersion.java8), + TestCoverage(TestType.platform, Os.windows, JvmVersion.java8)), omitsSlowProjects = false), Stage(DefaultStageName("Stage4", "Stage4 description"), functionalTests = listOf( - TestCoverage(TestType.parallel, OS.linux, JvmVersion.java8), - TestCoverage(TestType.parallel, OS.windows, JvmVersion.java8)), + TestCoverage(TestType.parallel, Os.linux, JvmVersion.java8), + TestCoverage(TestType.parallel, Os.windows, JvmVersion.java8)), omitsSlowProjects = false) ), subProjects = listOf( @@ -240,7 +240,7 @@ class CIConfigIntegrationTests { @Test fun long_ids_are_shortened() { - val testCoverage = TestCoverage(TestType.quickFeedbackCrossVersion, OS.windows, JvmVersion.java11, JvmVendor.oracle) + val testCoverage = TestCoverage(TestType.quickFeedbackCrossVersion, Os.windows, JvmVersion.java11, JvmVendor.oracle) val shortenedId = testCoverage.asConfigurationId(CIBuildModel(), "veryLongSubprojectNameLongerThanEverythingWeHave") assertTrue(shortenedId.length < 80) assertEquals(shortenedId, "Gradle_Check_QckFdbckCrssVrsn_Jv11_Orcl_Wndws_vryLngSbprjctNmLngrThnEvrythngWHv") From 09c1fb79362330cf99277f6b9419c4a124e38046 Mon Sep 17 00:00:00 2001 From: Stefan Wolf Date: Fri, 8 Mar 2019 09:44:20 +0100 Subject: [PATCH 402/853] Use gradle github organization for promotion instead of `gradleware`. --- .../vcsRoots/Gradle_Promotion_GradlePromotionBranches.kt | 3 +-- .../Gradle_Promotion/vcsRoots/Gradle_Promotion__master_.kt | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/.teamcity/Gradle_Promotion/vcsRoots/Gradle_Promotion_GradlePromotionBranches.kt b/.teamcity/Gradle_Promotion/vcsRoots/Gradle_Promotion_GradlePromotionBranches.kt index 849e427c7d40a..22443be0a5387 100644 --- a/.teamcity/Gradle_Promotion/vcsRoots/Gradle_Promotion_GradlePromotionBranches.kt +++ b/.teamcity/Gradle_Promotion/vcsRoots/Gradle_Promotion_GradlePromotionBranches.kt @@ -1,12 +1,11 @@ package Gradle_Promotion.vcsRoots -import jetbrains.buildServer.configs.kotlin.v2018_2.* import jetbrains.buildServer.configs.kotlin.v2018_2.vcs.GitVcsRoot object Gradle_Promotion_GradlePromotionBranches : GitVcsRoot({ uuid = "e4bc6ac6-ab3f-4459-b4c4-7d6ba6e2cbf6" name = "Gradle Promotion Branches" - url = "https://github.com/gradleware/gradle-promote.git" + url = "https://github.com/gradle/gradle-promote.git" branchSpec = "+:refs/heads/*" agentGitPath = "%env.TEAMCITY_GIT_PATH%" useMirrors = false diff --git a/.teamcity/Gradle_Promotion/vcsRoots/Gradle_Promotion__master_.kt b/.teamcity/Gradle_Promotion/vcsRoots/Gradle_Promotion__master_.kt index 66133d3f1a0eb..e8755b4c15c14 100644 --- a/.teamcity/Gradle_Promotion/vcsRoots/Gradle_Promotion__master_.kt +++ b/.teamcity/Gradle_Promotion/vcsRoots/Gradle_Promotion__master_.kt @@ -1,12 +1,11 @@ package Gradle_Promotion.vcsRoots -import jetbrains.buildServer.configs.kotlin.v2018_2.* import jetbrains.buildServer.configs.kotlin.v2018_2.vcs.GitVcsRoot object Gradle_Promotion__master_ : GitVcsRoot({ uuid = "0974a0e7-3f2f-4c3f-a185-aded6ac045ff" name = "Gradle Promotion" - url = "https://github.com/gradleware/gradle-promote.git" + url = "https://github.com/gradle/gradle-promote.git" branch = "master" agentGitPath = "%env.TEAMCITY_GIT_PATH%" useMirrors = false From b5c929d453d969d46ec6e34d2926b750ec6ce188 Mon Sep 17 00:00:00 2001 From: Peter Ledbrook Date: Fri, 8 Mar 2019 09:12:54 +0000 Subject: [PATCH 403/853] Add link from `SourceSet` API doc to user manual A lot of users land on this API doc when they do a web search for "gradle sourcesets". But it doesn't explain what source sets are. This change adds a link to the user manual which _does_ explain what they are and how to use them. Implements #dotorg-docs/348. --- .../src/main/java/org/gradle/api/tasks/SourceSet.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/subprojects/plugins/src/main/java/org/gradle/api/tasks/SourceSet.java b/subprojects/plugins/src/main/java/org/gradle/api/tasks/SourceSet.java index a815a6595a44a..c9626834c4292 100644 --- a/subprojects/plugins/src/main/java/org/gradle/api/tasks/SourceSet.java +++ b/subprojects/plugins/src/main/java/org/gradle/api/tasks/SourceSet.java @@ -25,10 +25,13 @@ import javax.annotation.Nullable; /** - * A {@code SourceSet} represents a logical group of Java source and resources. + * A {@code SourceSet} represents a logical group of Java source and resource files. They + * are covered in more detail in the + * user manual. *

    - * See the example below how {@link SourceSet} 'main' is accessed and how the {@link SourceDirectorySet} 'java' - * is configured to exclude some package from compilation. + * The following example shows how you can configure the 'main' source set, which in this + * case involves excluding classes whose package begins 'some.unwatned.package' from + * compilation of the source files in the 'java' {@link SourceDirectorySet}: * *

      * apply plugin: 'java'
    
    From a46cc5b09d835ccaf72cbf7a986f86fcf1e06565 Mon Sep 17 00:00:00 2001
    From: Stefan Wolf 
    Date: Mon, 4 Mar 2019 17:35:10 +0100
    Subject: [PATCH 404/853] Add santa tracker android performance test
    
    ---
     ...RealLifeAndroidBuildPerformanceTest.groovy | 11 +--
     subprojects/performance/templates.gradle      | 82 +++++++++++++++++++
     2 files changed, 88 insertions(+), 5 deletions(-)
    
    diff --git a/subprojects/performance/src/performanceTest/groovy/org/gradle/performance/regression/android/RealLifeAndroidBuildPerformanceTest.groovy b/subprojects/performance/src/performanceTest/groovy/org/gradle/performance/regression/android/RealLifeAndroidBuildPerformanceTest.groovy
    index 38c3caea79196..4d4c6591b15e1 100644
    --- a/subprojects/performance/src/performanceTest/groovy/org/gradle/performance/regression/android/RealLifeAndroidBuildPerformanceTest.groovy
    +++ b/subprojects/performance/src/performanceTest/groovy/org/gradle/performance/regression/android/RealLifeAndroidBuildPerformanceTest.groovy
    @@ -40,11 +40,12 @@ class RealLifeAndroidBuildPerformanceTest extends AbstractAndroidPerformanceTest
     
             where:
             testProject         | memory | parallel | warmUpRuns | runs | tasks
    -        'k9AndroidBuild'    | '1g'   | false    | null       | null | 'help'
    -        'k9AndroidBuild'    | '1g'   | false    | null       | null | 'assembleDebug'
    +        'k9AndroidBuild'           | '1g' | false | null | null | 'help'
    +        'k9AndroidBuild'           | '1g' | false | null | null | 'assembleDebug'
     //        'k9AndroidBuild'    | '1g'   | false    | null       | null | 'clean k9mail:assembleDebug'
    -        'largeAndroidBuild' | '5g'   | true     | null       | null | 'help'
    -        'largeAndroidBuild' | '5g'   | true     | null       | null | 'assembleDebug'
    -        'largeAndroidBuild' | '5g'   | true     | 2          | 8    | 'clean phthalic:assembleDebug'
    +        'largeAndroidBuild'        | '5g' | true  | null | null | 'help'
    +        'largeAndroidBuild'        | '5g' | true  | null | null | 'assembleDebug'
    +        'largeAndroidBuild'        | '5g' | true  | 2    | 8    | 'clean phthalic:assembleDebug'
    +        'santaTrackerAndroidBuild' | '1g' | true  | null | null | 'assembleDebug'
         }
     }
    diff --git a/subprojects/performance/templates.gradle b/subprojects/performance/templates.gradle
    index 3cd35d76cf02c..ef49ecb8841aa 100644
    --- a/subprojects/performance/templates.gradle
    +++ b/subprojects/performance/templates.gradle
    @@ -354,6 +354,88 @@ tasks.register("largeAndroidBuild", RemoteProject) {
         branch = 'android-34'
     }
     
    +tasks.register("santaTrackerAndroidBuild", RemoteProject) {
    +    remoteUri = 'https://github.com/gradle/santa-tracker-android.git'
    +    branch = 'agp-3.5.0'
    +    doLast {
    +        new File(outputDirectory, 'santa-tracker/google-services.json') << """
    +{
    +  "project_info": {
    +    "project_number": "012345678912",
    +    "firebase_url": "https://example.com",
    +    "project_id": "example",
    +    "storage_bucket": "example.example.com"
    +  },
    +  "client": [
    +    {
    +      "client_info": {
    +        "mobilesdk_app_id": "1:012345678912:android:0123456789abcdef",
    +        "android_client_info": {
    +          "package_name": "com.google.android.apps.santatracker.debug"
    +        }
    +      },
    +      "oauth_client": [
    +        {
    +          "client_id": "foo.example.com",
    +          "client_type": 3
    +        }
    +      ],
    +      "api_key": [
    +        {
    +          "current_key": "012345678901234567890123456789012345678"
    +        }
    +      ],
    +      "services": {
    +        "analytics_service": {
    +          "status": 1
    +        },
    +        "appinvite_service": {
    +          "status": 1,
    +          "other_platform_oauth_client": []
    +        },
    +        "ads_service": {
    +          "status": 2
    +        }
    +      }
    +    },
    +    {
    +      "client_info": {
    +        "mobilesdk_app_id": "1:012345678912:android:0123456789abcdef",
    +        "android_client_info": {
    +          "package_name": "com.google.android.apps.santatracker.debug"
    +        }
    +      },
    +      "oauth_client": [
    +        {
    +          "client_id": "foo.example.com",
    +          "client_type": 3
    +        }
    +      ],
    +      "api_key": [
    +        {
    +          "current_key": "012345678901234567890123456789012345678"
    +        }
    +      ],
    +      "services": {
    +        "analytics_service": {
    +          "status": 1
    +        },
    +        "appinvite_service": {
    +          "status": 1,
    +          "other_platform_oauth_client": []
    +        },
    +        "ads_service": {
    +          "status": 2
    +        }
    +      }
    +    }
    +  ],
    +  "configuration_version": "1"
    +}
    +"""
    +    }
    +}
    +
     tasks.register("excludeRuleMergingBuild", RemoteProject) {
         remoteUri = 'https://github.com/gradle/performance-comparisons.git'
         branch = 'master'
    
    From e5577e4fd00d6c0049169599fc45055cd0376956 Mon Sep 17 00:00:00 2001
    From: Stefan Wolf 
    Date: Tue, 5 Mar 2019 15:39:13 +0100
    Subject: [PATCH 405/853] Re-use scheduled transform result for immediate
     transforms
    
    ---
     .../DefaultDependencyManagementServices.java  | 30 +++++++++++++-
     .../AttributeMatchingVariantSelector.java     |  5 ++-
     .../ConsumerProvidedResolvedVariant.java      | 17 ++++++--
     .../transform/DefaultArtifactTransforms.java  |  7 +++-
     .../DefaultTransformationNodeFactory.java     | 14 +++++++
     .../PrecomputedTransformationResult.java      | 32 +++++++++++++++
     .../transform/TransformCompletion.java        |  6 +--
     .../transform/TransformationNode.java         |  2 +-
     .../transform/TransformationNodeFactory.java  |  6 +++
     .../transform/TransformationOperation.java    |  3 +-
     .../transform/TransformationResult.java       | 23 +++++++++++
     .../TransformingArtifactVisitor.java          | 10 ++---
     .../TransformingAsyncArtifactListener.java    | 39 ++++++++++++-------
     ...ttributeMatchingVariantSelectorSpec.groovy | 17 ++++----
     .../DefaultArtifactTransformsTest.groovy      | 13 ++++++-
     ...ansformingAsyncArtifactListenerTest.groovy | 19 +++++++--
     16 files changed, 197 insertions(+), 46 deletions(-)
     create mode 100644 subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/PrecomputedTransformationResult.java
     create mode 100644 subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/TransformationResult.java
    
    diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/DefaultDependencyManagementServices.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/DefaultDependencyManagementServices.java
    index b2e85da694af7..3d2dfb0cd67dc 100644
    --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/DefaultDependencyManagementServices.java
    +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/DefaultDependencyManagementServices.java
    @@ -18,6 +18,7 @@
     import org.gradle.StartParameter;
     import org.gradle.api.Describable;
     import org.gradle.api.artifacts.ConfigurablePublishArtifact;
    +import org.gradle.api.artifacts.component.ComponentArtifactIdentifier;
     import org.gradle.api.artifacts.dsl.ArtifactHandler;
     import org.gradle.api.artifacts.dsl.ComponentMetadataHandler;
     import org.gradle.api.artifacts.dsl.ComponentModuleMetadataHandler;
    @@ -58,6 +59,7 @@
     import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.strategy.VersionSelectorScheme;
     import org.gradle.api.internal.artifacts.ivyservice.moduleconverter.LocalComponentMetadataBuilder;
     import org.gradle.api.internal.artifacts.ivyservice.moduleconverter.dependencies.LocalConfigurationMetadataBuilder;
    +import org.gradle.api.internal.artifacts.ivyservice.resolveengine.artifact.ResolvedArtifactSet;
     import org.gradle.api.internal.artifacts.ivyservice.resolveengine.result.AttributeContainerSerializer;
     import org.gradle.api.internal.artifacts.ivyservice.resolveengine.store.ResolutionResultsStoreFactory;
     import org.gradle.api.internal.artifacts.mvnsettings.LocalMavenRepositoryLocator;
    @@ -76,10 +78,15 @@
     import org.gradle.api.internal.artifacts.transform.DefaultTransformerInvoker;
     import org.gradle.api.internal.artifacts.transform.DefaultVariantTransformRegistry;
     import org.gradle.api.internal.artifacts.transform.DomainObjectProjectStateHandler;
    +import org.gradle.api.internal.artifacts.transform.ExecutionGraphDependenciesResolver;
     import org.gradle.api.internal.artifacts.transform.ImmutableCachingTransformationWorkspaceProvider;
     import org.gradle.api.internal.artifacts.transform.MutableCachingTransformationWorkspaceProvider;
     import org.gradle.api.internal.artifacts.transform.MutableTransformationWorkspaceProvider;
    +import org.gradle.api.internal.artifacts.transform.Transformation;
    +import org.gradle.api.internal.artifacts.transform.TransformationNode;
    +import org.gradle.api.internal.artifacts.transform.TransformationNodeFactory;
     import org.gradle.api.internal.artifacts.transform.TransformationRegistrationFactory;
    +import org.gradle.api.internal.artifacts.transform.TransformationSubject;
     import org.gradle.api.internal.artifacts.transform.TransformerInvoker;
     import org.gradle.api.internal.artifacts.type.ArtifactTypeRegistry;
     import org.gradle.api.internal.artifacts.type.DefaultArtifactTypeRegistry;
    @@ -97,6 +104,7 @@
     import org.gradle.api.model.ObjectFactory;
     import org.gradle.configuration.internal.UserCodeApplicationContext;
     import org.gradle.initialization.ProjectAccessListener;
    +import org.gradle.internal.Try;
     import org.gradle.internal.authentication.AuthenticationSchemeRegistry;
     import org.gradle.internal.build.BuildState;
     import org.gradle.internal.classloader.ClassLoaderHierarchyHasher;
    @@ -149,6 +157,7 @@
     
     import javax.annotation.Nullable;
     import java.io.File;
    +import java.util.Collection;
     import java.util.List;
     
     public class DefaultDependencyManagementServices implements DependencyManagementServices {
    @@ -192,6 +201,21 @@ OutputFileCollectionFingerprinter createOutputFingerprinter(FileSystemSnapshotte
                 return new OutputFileCollectionFingerprinter(fileSystemSnapshotter);
             }
     
    +        TransformationNodeFactory createTransformationNodeFactory() {
    +            return new TransformationNodeFactory() {
    +                @Override
    +                public Collection getOrCreate(ResolvedArtifactSet artifactSet, Transformation transformation, ExecutionGraphDependenciesResolver dependenciesResolver) {
    +                    throw new UnsupportedOperationException("Cannot schedule transforms for build script dependencies");
    +                }
    +
    +                @Nullable
    +                @Override
    +                public Try getResultIfCompleted(ComponentArtifactIdentifier artifactId, Transformation transformation) {
    +                    return null;
    +                }
    +            };
    +        }
    +
             /**
              * Work executer for usage above Gradle scope
              *
    @@ -458,7 +482,8 @@ ConfigurationResolver createDependencyResolver(ArtifactDependencyResolver artifa
                                                            ArtifactTypeRegistry artifactTypeRegistry,
                                                            ComponentSelectorConverter componentSelectorConverter,
                                                            AttributeContainerSerializer attributeContainerSerializer,
    -                                                       BuildState currentBuild) {
    +                                                       BuildState currentBuild,
    +                                                       TransformationNodeFactory transformationNodeFactory) {
                 return new ErrorHandlingConfigurationResolver(
                         new ShortCircuitEmptyConfigurationResolver(
                             new DefaultConfigurationResolver(
    @@ -474,7 +499,8 @@ ConfigurationResolver createDependencyResolver(ArtifactDependencyResolver artifa
                                         attributesSchema,
                                         attributesFactory),
                                     attributesSchema,
    -                                attributesFactory
    +                                attributesFactory,
    +                                transformationNodeFactory
                                 ),
                                 moduleIdentifierFactory,
                                 buildOperationExecutor,
    diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/AttributeMatchingVariantSelector.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/AttributeMatchingVariantSelector.java
    index 0868bbd736920..4724dc976ac4e 100644
    --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/AttributeMatchingVariantSelector.java
    +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/AttributeMatchingVariantSelector.java
    @@ -41,6 +41,7 @@ class AttributeMatchingVariantSelector implements VariantSelector {
         private final ConsumerProvidedVariantFinder consumerProvidedVariantFinder;
         private final AttributesSchemaInternal schema;
         private final ImmutableAttributesFactory attributesFactory;
    +    private final TransformationNodeFactory transformationNodeFactory;
         private final ImmutableAttributes requested;
         private final boolean ignoreWhenNoMatches;
         private final ExtraExecutionGraphDependenciesResolverFactory dependenciesResolver;
    @@ -49,6 +50,7 @@ class AttributeMatchingVariantSelector implements VariantSelector {
             ConsumerProvidedVariantFinder consumerProvidedVariantFinder,
             AttributesSchemaInternal schema,
             ImmutableAttributesFactory attributesFactory,
    +        TransformationNodeFactory transformationNodeFactory,
             AttributeContainerInternal requested,
             boolean ignoreWhenNoMatches,
             ExtraExecutionGraphDependenciesResolverFactory dependenciesResolver
    @@ -56,6 +58,7 @@ class AttributeMatchingVariantSelector implements VariantSelector {
             this.consumerProvidedVariantFinder = consumerProvidedVariantFinder;
             this.schema = schema;
             this.attributesFactory = attributesFactory;
    +        this.transformationNodeFactory = transformationNodeFactory;
             this.requested = requested.asImmutable();
             this.ignoreWhenNoMatches = ignoreWhenNoMatches;
             this.dependenciesResolver = dependenciesResolver;
    @@ -105,7 +108,7 @@ private ResolvedArtifactSet doSelect(ResolvedVariantSet producer) {
                 ResolvedArtifactSet artifacts = result.getLeft().getArtifacts();
                 AttributeContainerInternal attributes = result.getRight().attributes;
                 Transformation transformation = result.getRight().transformation;
    -            return new ConsumerProvidedResolvedVariant(producer.getComponentId(), artifacts, attributes, transformation, dependenciesResolver);
    +            return new ConsumerProvidedResolvedVariant(producer.getComponentId(), artifacts, attributes, transformation, dependenciesResolver, transformationNodeFactory);
             }
     
             if (!candidates.isEmpty()) {
    diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/ConsumerProvidedResolvedVariant.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/ConsumerProvidedResolvedVariant.java
    index ba49dde0033ae..a05ab11e744d9 100644
    --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/ConsumerProvidedResolvedVariant.java
    +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/ConsumerProvidedResolvedVariant.java
    @@ -37,20 +37,29 @@ public class ConsumerProvidedResolvedVariant implements ResolvedArtifactSet {
         private final AttributeContainerInternal attributes;
         private final Transformation transformation;
         private final ExtraExecutionGraphDependenciesResolverFactory resolverFactory;
    +    private final TransformationNodeFactory transformationNodeFactory;
     
    -    public ConsumerProvidedResolvedVariant(ComponentIdentifier componentIdentifier, ResolvedArtifactSet delegate, AttributeContainerInternal target, Transformation transformation, ExtraExecutionGraphDependenciesResolverFactory dependenciesResolverFactory) {
    +    public ConsumerProvidedResolvedVariant(
    +        ComponentIdentifier componentIdentifier,
    +        ResolvedArtifactSet delegate,
    +        AttributeContainerInternal target,
    +        Transformation transformation,
    +        ExtraExecutionGraphDependenciesResolverFactory dependenciesResolverFactory,
    +        TransformationNodeFactory transformationNodeFactory
    +    ) {
             this.componentIdentifier = componentIdentifier;
             this.delegate = delegate;
             this.attributes = target;
             this.transformation = transformation;
             this.resolverFactory = dependenciesResolverFactory;
    +        this.transformationNodeFactory = transformationNodeFactory;
         }
     
         @Override
         public Completion startVisit(BuildOperationQueue actions, AsyncArtifactListener listener) {
    -        Map artifactResults = Maps.newConcurrentMap();
    -        Map fileResults = Maps.newConcurrentMap();
    -        Completion result = delegate.startVisit(actions, new TransformingAsyncArtifactListener(transformation, listener, actions, artifactResults, fileResults, getDependenciesResolver()));
    +        Map artifactResults = Maps.newConcurrentMap();
    +        Map fileResults = Maps.newConcurrentMap();
    +        Completion result = delegate.startVisit(actions, new TransformingAsyncArtifactListener(transformation, listener, actions, artifactResults, fileResults, getDependenciesResolver(), transformationNodeFactory));
             return new TransformCompletion(result, attributes, artifactResults, fileResults);
         }
     
    diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultArtifactTransforms.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultArtifactTransforms.java
    index 3173a6d173d02..f51ac0d18d592 100644
    --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultArtifactTransforms.java
    +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultArtifactTransforms.java
    @@ -24,20 +24,23 @@ public class DefaultArtifactTransforms implements ArtifactTransforms {
         private final ConsumerProvidedVariantFinder consumerProvidedVariantFinder;
         private final AttributesSchemaInternal schema;
         private final ImmutableAttributesFactory attributesFactory;
    +    private final TransformationNodeFactory transformationNodeFactory;
     
         public DefaultArtifactTransforms(
             ConsumerProvidedVariantFinder consumerProvidedVariantFinder,
             AttributesSchemaInternal schema,
    -        ImmutableAttributesFactory attributesFactory
    +        ImmutableAttributesFactory attributesFactory,
    +        TransformationNodeFactory transformationNodeFactory
         ) {
             this.consumerProvidedVariantFinder = consumerProvidedVariantFinder;
             this.schema = schema;
             this.attributesFactory = attributesFactory;
    +        this.transformationNodeFactory = transformationNodeFactory;
         }
     
         @Override
         public VariantSelector variantSelector(AttributeContainerInternal consumerAttributes, boolean allowNoMatchingVariants, ExtraExecutionGraphDependenciesResolverFactory dependenciesResolver) {
    -        return new AttributeMatchingVariantSelector(consumerProvidedVariantFinder, schema, attributesFactory, consumerAttributes.asImmutable(), allowNoMatchingVariants, dependenciesResolver);
    +        return new AttributeMatchingVariantSelector(consumerProvidedVariantFinder, schema, attributesFactory, transformationNodeFactory, consumerAttributes.asImmutable(), allowNoMatchingVariants, dependenciesResolver);
         }
     
     }
    diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformationNodeFactory.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformationNodeFactory.java
    index 02399d5cad558..71a7d8dd0b0a5 100644
    --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformationNodeFactory.java
    +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformationNodeFactory.java
    @@ -23,7 +23,9 @@
     import org.gradle.api.artifacts.component.ComponentArtifactIdentifier;
     import org.gradle.api.internal.artifacts.ivyservice.resolveengine.artifact.ResolvableArtifact;
     import org.gradle.api.internal.artifacts.ivyservice.resolveengine.artifact.ResolvedArtifactSet;
    +import org.gradle.internal.Try;
     
    +import javax.annotation.Nullable;
     import java.util.Collection;
     import java.util.List;
     import java.util.Map;
    @@ -43,6 +45,18 @@ public Collection getOrCreate(ResolvedArtifactSet artifactSe
             return builder.build();
         }
     
    +    @Override
    +    @Nullable
    +    public Try getResultIfCompleted(ComponentArtifactIdentifier artifactId, Transformation transformation) {
    +        List> transformationChain = unpackTransformation(transformation);
    +        ArtifactTransformKey transformKey = new ArtifactTransformKey(artifactId, transformationChain);
    +        TransformationNode node = transformations.get(transformKey);
    +        if (node != null && node.isComplete()) {
    +            return node.getTransformedSubject();
    +        }
    +        return null;
    +    }
    +
         private void collectTransformNodes(ResolvedArtifactSet artifactSet, ImmutableList.Builder builder, Function nodeCreator) {
             artifactSet.visitLocalArtifacts(new ResolvedArtifactSet.LocalArtifactVisitor() {
                 @Override
    diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/PrecomputedTransformationResult.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/PrecomputedTransformationResult.java
    new file mode 100644
    index 0000000000000..094ab9d794088
    --- /dev/null
    +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/PrecomputedTransformationResult.java
    @@ -0,0 +1,32 @@
    +/*
    + * Copyright 2019 the original author or authors.
    + *
    + * Licensed under the Apache License, Version 2.0 (the "License");
    + * you may not use this file except in compliance with the License.
    + * You may obtain a copy of the License at
    + *
    + *      http://www.apache.org/licenses/LICENSE-2.0
    + *
    + * Unless required by applicable law or agreed to in writing, software
    + * distributed under the License is distributed on an "AS IS" BASIS,
    + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    + * See the License for the specific language governing permissions and
    + * limitations under the License.
    + */
    +
    +package org.gradle.api.internal.artifacts.transform;
    +
    +import org.gradle.internal.Try;
    +
    +public class PrecomputedTransformationResult implements TransformationResult {
    +    private final Try result;
    +
    +    public PrecomputedTransformationResult(Try result) {
    +        this.result = result;
    +    }
    +
    +    @Override
    +    public Try getResult() {
    +        return result;
    +    }
    +}
    diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/TransformCompletion.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/TransformCompletion.java
    index b3fad67256d50..87591ed69a9b5 100644
    --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/TransformCompletion.java
    +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/TransformCompletion.java
    @@ -27,10 +27,10 @@
     public class TransformCompletion implements ResolvedArtifactSet.Completion {
         private final AttributeContainerInternal attributes;
         private final ResolvedArtifactSet.Completion delegate;
    -    private final Map artifactResults;
    -    private final Map fileResults;
    +    private final Map artifactResults;
    +    private final Map fileResults;
     
    -    public TransformCompletion(ResolvedArtifactSet.Completion delegate, AttributeContainerInternal attributes, Map artifactResults, Map fileResults) {
    +    public TransformCompletion(ResolvedArtifactSet.Completion delegate, AttributeContainerInternal attributes, Map artifactResults, Map fileResults) {
             this.delegate = delegate;
             this.attributes = attributes;
             this.artifactResults = artifactResults;
    diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/TransformationNode.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/TransformationNode.java
    index 618889c44ba3b..21acefb35a698 100644
    --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/TransformationNode.java
    +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/TransformationNode.java
    @@ -70,7 +70,7 @@ public String toString() {
             return transformationStep.getDisplayName();
         }
     
    -    private Try getTransformedSubject() {
    +    public Try getTransformedSubject() {
             if (transformedSubject == null) {
                 throw new IllegalStateException(String.format("Transformation %s has been scheduled and is now required, but did not execute, yet.", transformationStep.getDisplayName()));
             }
    diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/TransformationNodeFactory.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/TransformationNodeFactory.java
    index 6e32a6269caf3..e8f7a2bf73bc0 100644
    --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/TransformationNodeFactory.java
    +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/TransformationNodeFactory.java
    @@ -16,10 +16,16 @@
     
     package org.gradle.api.internal.artifacts.transform;
     
    +import org.gradle.api.artifacts.component.ComponentArtifactIdentifier;
     import org.gradle.api.internal.artifacts.ivyservice.resolveengine.artifact.ResolvedArtifactSet;
    +import org.gradle.internal.Try;
     
    +import javax.annotation.Nullable;
     import java.util.Collection;
     
     public interface TransformationNodeFactory {
         Collection getOrCreate(ResolvedArtifactSet artifactSet, Transformation transformation, ExecutionGraphDependenciesResolver dependenciesResolver);
    +
    +    @Nullable
    +    Try getResultIfCompleted(ComponentArtifactIdentifier artifactId, Transformation transformation);
     }
    diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/TransformationOperation.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/TransformationOperation.java
    index bc2944e5b2b66..8ef5c2ff91226 100644
    --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/TransformationOperation.java
    +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/TransformationOperation.java
    @@ -24,7 +24,7 @@
     
     import javax.annotation.Nullable;
     
    -class TransformationOperation implements RunnableBuildOperation {
    +class TransformationOperation implements TransformationResult, RunnableBuildOperation {
         private final Transformation transformation;
         private final TransformationSubject subject;
         private final ExecutionGraphDependenciesResolver dependenciesResolver;
    @@ -49,6 +49,7 @@ public BuildOperationDescriptor.Builder description() {
                 .operationType(BuildOperationCategory.UNCATEGORIZED);
         }
     
    +    @Override
         public Try getResult() {
             return result;
         }
    diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/TransformationResult.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/TransformationResult.java
    new file mode 100644
    index 0000000000000..e70c5ae94de67
    --- /dev/null
    +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/TransformationResult.java
    @@ -0,0 +1,23 @@
    +/*
    + * Copyright 2019 the original author or authors.
    + *
    + * Licensed under the Apache License, Version 2.0 (the "License");
    + * you may not use this file except in compliance with the License.
    + * You may obtain a copy of the License at
    + *
    + *      http://www.apache.org/licenses/LICENSE-2.0
    + *
    + * Unless required by applicable law or agreed to in writing, software
    + * distributed under the License is distributed on an "AS IS" BASIS,
    + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    + * See the License for the specific language governing permissions and
    + * limitations under the License.
    + */
    +
    +package org.gradle.api.internal.artifacts.transform;
    +
    +import org.gradle.internal.Try;
    +
    +public interface TransformationResult {
    +    Try getResult();
    +}
    diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/TransformingArtifactVisitor.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/TransformingArtifactVisitor.java
    index 765e8fd1ff535..95528b2707938 100644
    --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/TransformingArtifactVisitor.java
    +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/TransformingArtifactVisitor.java
    @@ -35,10 +35,10 @@
     class TransformingArtifactVisitor implements ArtifactVisitor {
         private final ArtifactVisitor visitor;
         private final AttributeContainerInternal target;
    -    private final Map artifactResults;
    -    private final Map fileResults;
    +    private final Map artifactResults;
    +    private final Map fileResults;
     
    -    TransformingArtifactVisitor(ArtifactVisitor visitor, AttributeContainerInternal target, Map artifactResults, Map fileResults) {
    +    TransformingArtifactVisitor(ArtifactVisitor visitor, AttributeContainerInternal target, Map artifactResults, Map fileResults) {
             this.visitor = visitor;
             this.target = target;
             this.artifactResults = artifactResults;
    @@ -47,7 +47,7 @@ class TransformingArtifactVisitor implements ArtifactVisitor {
     
         @Override
         public void visitArtifact(DisplayName variantName, AttributeContainer variantAttributes, ResolvableArtifact artifact) {
    -        TransformationOperation operation = artifactResults.get(artifact.getId());
    +        TransformationResult operation = artifactResults.get(artifact.getId());
             operation.getResult().ifSuccessfulOrElse(
                 transformedSubject -> {
                     ResolvedArtifact sourceArtifact = artifact.toPublicView();
    @@ -79,7 +79,7 @@ public boolean requireArtifactFiles() {
     
         @Override
         public void visitFile(ComponentArtifactIdentifier artifactIdentifier, DisplayName variantName, AttributeContainer variantAttributes, File file) {
    -        TransformationOperation operation = fileResults.get(file);
    +        TransformationResult operation = fileResults.get(file);
             operation.getResult().ifSuccessfulOrElse(
                 transformedSubject -> {
                     for (File outputFile : transformedSubject.getFiles()) {
    diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/TransformingAsyncArtifactListener.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/TransformingAsyncArtifactListener.java
    index ddf0c4255b75e..88897f89bc361 100644
    --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/TransformingAsyncArtifactListener.java
    +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/TransformingAsyncArtifactListener.java
    @@ -19,6 +19,7 @@
     import org.gradle.api.artifacts.component.ComponentArtifactIdentifier;
     import org.gradle.api.internal.artifacts.ivyservice.resolveengine.artifact.ResolvableArtifact;
     import org.gradle.api.internal.artifacts.ivyservice.resolveengine.artifact.ResolvedArtifactSet;
    +import org.gradle.internal.Try;
     import org.gradle.internal.operations.BuildOperationQueue;
     import org.gradle.internal.operations.RunnableBuildOperation;
     
    @@ -26,9 +27,10 @@
     import java.util.Map;
     
     class TransformingAsyncArtifactListener implements ResolvedArtifactSet.AsyncArtifactListener {
    -    private final Map artifactResults;
    -    private final Map fileResults;
    +    private final Map artifactResults;
    +    private final Map fileResults;
         private final ExecutionGraphDependenciesResolver dependenciesResolver;
    +    private final TransformationNodeFactory transformationNodeFactory;
         private final BuildOperationQueue actions;
         private final ResolvedArtifactSet.AsyncArtifactListener delegate;
         private final Transformation transformation;
    @@ -37,9 +39,10 @@ class TransformingAsyncArtifactListener implements ResolvedArtifactSet.AsyncArti
             Transformation transformation,
             ResolvedArtifactSet.AsyncArtifactListener delegate,
             BuildOperationQueue actions,
    -        Map artifactResults,
    -        Map fileResults,
    -        ExecutionGraphDependenciesResolver dependenciesResolver
    +        Map artifactResults,
    +        Map fileResults,
    +        ExecutionGraphDependenciesResolver dependenciesResolver,
    +        TransformationNodeFactory transformationNodeFactory
         ) {
             this.artifactResults = artifactResults;
             this.actions = actions;
    @@ -47,21 +50,27 @@ class TransformingAsyncArtifactListener implements ResolvedArtifactSet.AsyncArti
             this.delegate = delegate;
             this.fileResults = fileResults;
             this.dependenciesResolver = dependenciesResolver;
    +        this.transformationNodeFactory = transformationNodeFactory;
         }
     
         @Override
         public void artifactAvailable(ResolvableArtifact artifact) {
             ComponentArtifactIdentifier artifactId = artifact.getId();
    -        File file = artifact.getFile();
    -        TransformationSubject initialSubject = TransformationSubject.initial(artifactId, file);
    -        TransformationOperation operation = new TransformationOperation(transformation, initialSubject, dependenciesResolver);
    -        artifactResults.put(artifactId, operation);
    -        // We expect artifact transformations to be executed in a scheduled way,
    -        // so at this point we take the result from the in-memory cache.
    -        // Artifact transformations are always executed scheduled via the execution graph when the transformed component is declared as an input.
    -        // Using the BuildOperationQueue here to only realize that the result of the transformation is from the in-memory has a performance impact,
    -        // so we executing the (no-op) operation in place.
    -        operation.run(null);
    +        Try resultIfCompleted = transformationNodeFactory.getResultIfCompleted(artifactId, transformation);
    +        if (resultIfCompleted != null) {
    +            artifactResults.put(artifactId, new PrecomputedTransformationResult(resultIfCompleted));
    +        } else {
    +            File file = artifact.getFile();
    +            TransformationSubject initialSubject = TransformationSubject.initial(artifactId, file);
    +            TransformationOperation operation = new TransformationOperation(transformation, initialSubject, dependenciesResolver);
    +            artifactResults.put(artifactId, operation);
    +            // We expect artifact transformations to be executed in a scheduled way,
    +            // so at this point we take the result from the in-memory cache.
    +            // Artifact transformations are always executed scheduled via the execution graph when the transformed component is declared as an input.
    +            // Using the BuildOperationQueue here to only realize that the result of the transformation is from the in-memory has a performance impact,
    +            // so we executing the (no-op) operation in place.
    +            operation.run(null);
    +        }
         }
     
         @Override
    diff --git a/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/AttributeMatchingVariantSelectorSpec.groovy b/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/AttributeMatchingVariantSelectorSpec.groovy
    index 02d9b6a5a5485..876484ee52153 100644
    --- a/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/AttributeMatchingVariantSelectorSpec.groovy
    +++ b/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/AttributeMatchingVariantSelectorSpec.groovy
    @@ -32,6 +32,7 @@ import spock.lang.Specification
     class AttributeMatchingVariantSelectorSpec extends Specification {
     
         def consumerProvidedVariantFinder = Mock(ConsumerProvidedVariantFinder)
    +    def transformationNodeFactory = Mock(TransformationNodeFactory)
         def attributeMatcher = Mock(AttributeMatcher)
         def attributesSchema = Mock(AttributesSchemaInternal) {
             withProducer(_) >> attributeMatcher
    @@ -55,7 +56,7 @@ class AttributeMatchingVariantSelectorSpec extends Specification {
         def 'direct match on variant means no finder interaction'() {
             given:
             def resolvedArtifactSet = Mock(ResolvedArtifactSet)
    -        def selector = new AttributeMatchingVariantSelector(consumerProvidedVariantFinder, attributesSchema, attributesFactory, requestedAttributes, false, dependenciesResolverFactory)
    +        def selector = new AttributeMatchingVariantSelector(consumerProvidedVariantFinder, attributesSchema, attributesFactory, transformationNodeFactory, requestedAttributes, false, dependenciesResolverFactory)
     
             when:
             def result = selector.select(variantSet)
    @@ -73,7 +74,7 @@ class AttributeMatchingVariantSelectorSpec extends Specification {
                 asDescribable() >> Describables.of('other mocked variant')
                 getAttributes() >> otherVariantAttributes
             }
    -        def selector = new AttributeMatchingVariantSelector(consumerProvidedVariantFinder, attributesSchema, attributesFactory, requestedAttributes, false, dependenciesResolverFactory)
    +        def selector = new AttributeMatchingVariantSelector(consumerProvidedVariantFinder, attributesSchema, attributesFactory, transformationNodeFactory, requestedAttributes, false, dependenciesResolverFactory)
     
             when:
             def result = selector.select(variantSet)
    @@ -106,7 +107,7 @@ class AttributeMatchingVariantSelectorSpec extends Specification {
     
         def 'selecting a transform results in added DefaultTransformationDependency'() {
             given:
    -        def selector = new AttributeMatchingVariantSelector(consumerProvidedVariantFinder, attributesSchema, attributesFactory, requestedAttributes, false, dependenciesResolverFactory)
    +        def selector = new AttributeMatchingVariantSelector(consumerProvidedVariantFinder, attributesSchema, attributesFactory, transformationNodeFactory, requestedAttributes, false, dependenciesResolverFactory)
     
             when:
             def result = selector.select(variantSet)
    @@ -152,7 +153,7 @@ class AttributeMatchingVariantSelectorSpec extends Specification {
             }
             def transform1 = Mock(Transformation)
             def transform2 = Mock(Transformation)
    -        def selector = new AttributeMatchingVariantSelector(consumerProvidedVariantFinder, attributesSchema, attributesFactory, requestedAttributes, false, dependenciesResolverFactory)
    +        def selector = new AttributeMatchingVariantSelector(consumerProvidedVariantFinder, attributesSchema, attributesFactory, transformationNodeFactory, requestedAttributes, false, dependenciesResolverFactory)
     
             when:
             def result = selector.select(multiVariantSet)
    @@ -203,7 +204,7 @@ class AttributeMatchingVariantSelectorSpec extends Specification {
             }
             def transform1 = Mock(Transformation)
             def transform2 = Mock(Transformation)
    -        def selector = new AttributeMatchingVariantSelector(consumerProvidedVariantFinder, attributesSchema, attributesFactory, requestedAttributes, false, dependenciesResolverFactory)
    +        def selector = new AttributeMatchingVariantSelector(consumerProvidedVariantFinder, attributesSchema, attributesFactory, transformationNodeFactory, requestedAttributes, false, dependenciesResolverFactory)
     
             when:
             def result = selector.select(multiVariantSet)
    @@ -260,7 +261,7 @@ class AttributeMatchingVariantSelectorSpec extends Specification {
             def transform1 = Mock(Transformation)
             def transform2 = Mock(Transformation)
             def transform3 = Mock(Transformation)
    -        def selector = new AttributeMatchingVariantSelector(consumerProvidedVariantFinder, attributesSchema, attributesFactory, requestedAttributes, false, dependenciesResolverFactory)
    +        def selector = new AttributeMatchingVariantSelector(consumerProvidedVariantFinder, attributesSchema, attributesFactory, transformationNodeFactory, requestedAttributes, false, dependenciesResolverFactory)
     
             when:
             def result = selector.select(multiVariantSet)
    @@ -320,7 +321,7 @@ class AttributeMatchingVariantSelectorSpec extends Specification {
             def transform1 = Mock(Transformation)
             def transform2 = Mock(Transformation)
             def transform3 = Mock(Transformation)
    -        def selector = new AttributeMatchingVariantSelector(consumerProvidedVariantFinder, attributesSchema, attributesFactory, requestedAttributes, false, dependenciesResolverFactory)
    +        def selector = new AttributeMatchingVariantSelector(consumerProvidedVariantFinder, attributesSchema, attributesFactory, transformationNodeFactory, requestedAttributes, false, dependenciesResolverFactory)
     
             when:
             def result = selector.select(multiVariantSet)
    @@ -380,7 +381,7 @@ class AttributeMatchingVariantSelectorSpec extends Specification {
             def transform1 = Mock(Transformation)
             def transform2 = Mock(Transformation)
             def transform3 = Mock(Transformation)
    -        def selector = new AttributeMatchingVariantSelector(consumerProvidedVariantFinder, attributesSchema, attributesFactory, requestedAttributes, false, dependenciesResolverFactory)
    +        def selector = new AttributeMatchingVariantSelector(consumerProvidedVariantFinder, attributesSchema, attributesFactory, transformationNodeFactory, requestedAttributes, false, dependenciesResolverFactory)
     
             when:
             def result = selector.select(multiVariantSet)
    diff --git a/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/DefaultArtifactTransformsTest.groovy b/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/DefaultArtifactTransformsTest.groovy
    index 2623c2e4fe0b3..bf64b446dd434 100644
    --- a/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/DefaultArtifactTransformsTest.groovy
    +++ b/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/DefaultArtifactTransformsTest.groovy
    @@ -50,7 +50,18 @@ class DefaultArtifactTransformsTest extends Specification {
         def consumerSchema = Mock(AttributesSchemaInternal)
         def attributeMatcher = Mock(AttributeMatcher)
         def dependenciesResolver = Stub(ExtraExecutionGraphDependenciesResolverFactory)
    -    def transforms = new DefaultArtifactTransforms(matchingCache, consumerSchema, AttributeTestUtil.attributesFactory())
    +    def transformationNodeFactory = new TransformationNodeFactory() {
    +        @Override
    +        Collection getOrCreate(ResolvedArtifactSet artifactSet, Transformation transformation, ExecutionGraphDependenciesResolver dependenciesResolver) {
    +            throw new UnsupportedOperationException()
    +        }
    +
    +        @Override
    +        Try getResultIfCompleted(ComponentArtifactIdentifier artifactId, Transformation transformation) {
    +            return null
    +        }
    +    }
    +    def transforms = new DefaultArtifactTransforms(matchingCache, consumerSchema, AttributeTestUtil.attributesFactory(), transformationNodeFactory)
     
         def "selects producer variant with requested attributes"() {
             def variant1 = resolvedVariant()
    diff --git a/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/TransformingAsyncArtifactListenerTest.groovy b/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/TransformingAsyncArtifactListenerTest.groovy
    index 86abc1c3f0dcf..b443f424d169f 100644
    --- a/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/TransformingAsyncArtifactListenerTest.groovy
    +++ b/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/TransformingAsyncArtifactListenerTest.groovy
    @@ -16,9 +16,11 @@
     
     package org.gradle.api.internal.artifacts.transform
     
    +import com.google.common.collect.ImmutableList
     import com.google.common.collect.Maps
     import org.gradle.api.artifacts.component.ComponentArtifactIdentifier
     import org.gradle.api.internal.artifacts.ivyservice.resolveengine.artifact.ResolvableArtifact
    +import org.gradle.internal.Try
     import org.gradle.internal.operations.BuildOperation
     import org.gradle.internal.operations.BuildOperationQueue
     import org.gradle.testing.internal.util.Specification
    @@ -26,13 +28,14 @@ import org.gradle.testing.internal.util.Specification
     class TransformingAsyncArtifactListenerTest extends Specification {
         def transformation = Mock(Transformation)
         def operationQueue = Mock(BuildOperationQueue)
    -    def listener  = new TransformingAsyncArtifactListener(transformation, null, operationQueue, Maps.newHashMap(), Maps.newHashMap(), Mock(ExecutionGraphDependenciesResolver))
    +    def transformationNodeFactory = Mock(TransformationNodeFactory)
    +    def listener  = new TransformingAsyncArtifactListener(transformation, null, operationQueue, Maps.newHashMap(), Maps.newHashMap(), Mock(ExecutionGraphDependenciesResolver), transformationNodeFactory)
         def file = new File("foo")
         def artifactFile = new File("foo-artifact")
         def artifactId = Stub(ComponentArtifactIdentifier)
         def artifact = Stub(ResolvableArtifact) {
             getId() >> artifactId
    -        getArtifactFile() >> artifactFile
    +        getFile() >> artifactFile
         }
     
         def "adds file transformations to the build operation queue"() {
    @@ -43,11 +46,21 @@ class TransformingAsyncArtifactListenerTest extends Specification {
             1 * operationQueue.add(_ as BuildOperation)
         }
     
    -    def "runs artifact transformations immediately"() {
    +    def "runs artifact transformations immediately when not scheduled"() {
             when:
             listener.artifactAvailable(artifact)
     
             then:
    +        1 * transformationNodeFactory.getResultIfCompleted(artifactId, transformation) >> null
             1 * transformation.transform({ it.files == [artifactFile] }, _ as ExecutionGraphDependenciesResolver, _)
         }
    +
    +    def "re-uses scheduled artifact transformation result"() {
    +        when:
    +        listener.artifactAvailable(artifact)
    +
    +        then:
    +        1 * transformationNodeFactory.getResultIfCompleted(artifactId, transformation) >> Try.successful(TransformationSubject.initial(artifact.id, artifact.file).createSubjectFromResult(ImmutableList.of()))
    +        0 * transformation.transform(_, _ as ExecutionGraphDependenciesResolver, _)
    +    }
     }
    
    From ba2f24c4ed2aae9e0afa746a91d6e45e7621ee51 Mon Sep 17 00:00:00 2001
    From: =?UTF-8?q?L=C3=B3r=C3=A1nt=20Pint=C3=A9r?= 
    Date: Fri, 8 Mar 2019 10:43:21 +0100
    Subject: [PATCH 406/853] Move recording outputs to a separate step
    
    This also means that we don't need a dummy output recorder for non-incremental artifact transforms anymore.
    ---
     .../scopes/ExecutionGradleServices.java       | 21 ++++----
     .../DefaultDependencyManagementServices.java  | 15 +-----
     .../execution/steps/RecordOutputsStep.java    | 42 ++++++++++++++++
     .../execution/steps/StoreSnapshotsStep.java   |  7 ---
     .../steps/CreateOutputsStepTest.groovy        |  1 +
     .../steps/IncrementalExecutionTest.groovy     |  2 +-
     .../steps/RecordOutputsStepTest.groovy        | 48 +++++++++++++++++++
     .../steps/StoreSnapshotsStepTest.groovy       | 20 ++------
     8 files changed, 110 insertions(+), 46 deletions(-)
     create mode 100644 subprojects/execution/src/main/java/org/gradle/internal/execution/steps/RecordOutputsStep.java
     create mode 100644 subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/RecordOutputsStepTest.groovy
    
    diff --git a/subprojects/core/src/main/java/org/gradle/internal/service/scopes/ExecutionGradleServices.java b/subprojects/core/src/main/java/org/gradle/internal/service/scopes/ExecutionGradleServices.java
    index 4815249352255..141533542f718 100644
    --- a/subprojects/core/src/main/java/org/gradle/internal/service/scopes/ExecutionGradleServices.java
    +++ b/subprojects/core/src/main/java/org/gradle/internal/service/scopes/ExecutionGradleServices.java
    @@ -51,6 +51,7 @@
     import org.gradle.internal.execution.steps.CreateOutputsStep;
     import org.gradle.internal.execution.steps.ExecuteStep;
     import org.gradle.internal.execution.steps.PrepareCachingStep;
    +import org.gradle.internal.execution.steps.RecordOutputsStep;
     import org.gradle.internal.execution.steps.ResolveChangesStep;
     import org.gradle.internal.execution.steps.SkipUpToDateStep;
     import org.gradle.internal.execution.steps.SnapshotOutputStep;
    @@ -123,15 +124,17 @@ public WorkExecutor createWorkExecutor(
             return new DefaultWorkExecutor(
                 new ResolveChangesStep(
                     new SkipUpToDateStep(
    -                    new StoreSnapshotsStep(outputFilesRepository,
    -                        new PrepareCachingStep(
    -                            new CacheStep(buildCacheController, outputChangeListener, buildCacheCommandFactory,
    -                                new SnapshotOutputStep(buildInvocationScopeId.getId(),
    -                                    new CreateOutputsStep(
    -                                        new CatchExceptionStep(
    -                                            new TimeoutStep(timeoutHandler,
    -                                                new CancelExecutionStep(cancellationToken,
    -                                                    new ExecuteStep(outputChangeListener)
    +                    new RecordOutputsStep(outputFilesRepository,
    +                        new StoreSnapshotsStep(
    +                            new PrepareCachingStep(
    +                                new CacheStep(buildCacheController, outputChangeListener, buildCacheCommandFactory,
    +                                    new SnapshotOutputStep(buildInvocationScopeId.getId(),
    +                                        new CreateOutputsStep(
    +                                            new CatchExceptionStep(
    +                                                new TimeoutStep(timeoutHandler,
    +                                                    new CancelExecutionStep(cancellationToken,
    +                                                        new ExecuteStep(outputChangeListener)
    +                                                    )
                                                     )
                                                 )
                                             )
    diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/DefaultDependencyManagementServices.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/DefaultDependencyManagementServices.java
    index b2e85da694af7..ee4c3955152ab 100644
    --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/DefaultDependencyManagementServices.java
    +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/DefaultDependencyManagementServices.java
    @@ -111,7 +111,6 @@
     import org.gradle.internal.execution.UpToDateResult;
     import org.gradle.internal.execution.WorkExecutor;
     import org.gradle.internal.execution.history.ExecutionHistoryStore;
    -import org.gradle.internal.execution.history.OutputFilesRepository;
     import org.gradle.internal.execution.impl.DefaultWorkExecutor;
     import org.gradle.internal.execution.steps.CatchExceptionStep;
     import org.gradle.internal.execution.steps.CreateOutputsStep;
    @@ -140,7 +139,6 @@
     import org.gradle.internal.service.DefaultServiceRegistry;
     import org.gradle.internal.service.ServiceRegistration;
     import org.gradle.internal.service.ServiceRegistry;
    -import org.gradle.internal.snapshot.FileSystemSnapshot;
     import org.gradle.internal.snapshot.FileSystemSnapshotter;
     import org.gradle.internal.snapshot.ValueSnapshotter;
     import org.gradle.internal.typeconversion.NotationParser;
    @@ -148,7 +146,6 @@
     import org.gradle.vcs.internal.VcsMappingsStore;
     
     import javax.annotation.Nullable;
    -import java.io.File;
     import java.util.List;
     
     public class DefaultDependencyManagementServices implements DependencyManagementServices {
    @@ -202,22 +199,12 @@ WorkExecutor createWorkExecutor(
                 TimeoutHandler timeoutHandler
             ) {
                 OutputChangeListener outputChangeListener = listenerManager.getBroadcaster(OutputChangeListener.class);
    -            OutputFilesRepository noopOutputFilesRepository = new OutputFilesRepository() {
    -                @Override
    -                public boolean isGeneratedByGradle(File file) {
    -                    return true;
    -                }
    -
    -                @Override
    -                public void recordOutputs(Iterable outputFileFingerprints) {
    -                }
    -            };
                 // TODO: Figure out how to get rid of origin scope id in snapshot outputs step
                 UniqueId fixedUniqueId = UniqueId.from("dhwwyv4tqrd43cbxmdsf24wquu");
                 return new DefaultWorkExecutor<>(
                     new ResolveChangesStep<>(
                         new SkipUpToDateStep<>(
    -                        new StoreSnapshotsStep<>(noopOutputFilesRepository,
    +                        new StoreSnapshotsStep<>(
                                 new PrepareCachingStep<>(
                                     new SnapshotOutputStep<>(fixedUniqueId,
                                         new CreateOutputsStep<>(
    diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/RecordOutputsStep.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/RecordOutputsStep.java
    new file mode 100644
    index 0000000000000..ecb4b6ff8f313
    --- /dev/null
    +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/RecordOutputsStep.java
    @@ -0,0 +1,42 @@
    +/*
    + * Copyright 2019 the original author or authors.
    + *
    + * Licensed under the Apache License, Version 2.0 (the "License");
    + * you may not use this file except in compliance with the License.
    + * You may obtain a copy of the License at
    + *
    + *      http://www.apache.org/licenses/LICENSE-2.0
    + *
    + * Unless required by applicable law or agreed to in writing, software
    + * distributed under the License is distributed on an "AS IS" BASIS,
    + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    + * See the License for the specific language governing permissions and
    + * limitations under the License.
    + */
    +
    +package org.gradle.internal.execution.steps;
    +
    +import org.gradle.internal.execution.Context;
    +import org.gradle.internal.execution.CurrentSnapshotResult;
    +import org.gradle.internal.execution.Step;
    +import org.gradle.internal.execution.history.OutputFilesRepository;
    +
    +public class RecordOutputsStep implements Step {
    +    private final OutputFilesRepository outputFilesRepository;
    +    private final Step delegate;
    +
    +    public RecordOutputsStep(
    +        OutputFilesRepository outputFilesRepository,
    +        Step delegate
    +    ) {
    +        this.outputFilesRepository = outputFilesRepository;
    +        this.delegate = delegate;
    +    }
    +
    +    @Override
    +    public CurrentSnapshotResult execute(C context) {
    +        CurrentSnapshotResult result = delegate.execute(context);
    +        outputFilesRepository.recordOutputs(result.getFinalOutputs().values());
    +        return result;
    +    }
    +}
    diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/StoreSnapshotsStep.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/StoreSnapshotsStep.java
    index f354a5e08b9a2..211be538832e8 100644
    --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/StoreSnapshotsStep.java
    +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/StoreSnapshotsStep.java
    @@ -23,7 +23,6 @@
     import org.gradle.internal.execution.Step;
     import org.gradle.internal.execution.UnitOfWork;
     import org.gradle.internal.execution.history.AfterPreviousExecutionState;
    -import org.gradle.internal.execution.history.OutputFilesRepository;
     import org.gradle.internal.execution.history.changes.OutputFileChanges;
     import org.gradle.internal.fingerprint.CurrentFileCollectionFingerprint;
     import org.gradle.internal.fingerprint.FileCollectionFingerprint;
    @@ -31,19 +30,15 @@
     import java.util.Optional;
     
     public class StoreSnapshotsStep implements Step {
    -    private final OutputFilesRepository outputFilesRepository;
         private final Step delegate;
     
         public StoreSnapshotsStep(
    -        OutputFilesRepository outputFilesRepository,
             Step delegate
         ) {
    -        this.outputFilesRepository = outputFilesRepository;
             this.delegate = delegate;
         }
     
         @Override
    -    // TODO Return a simple Result (that includes the origin metadata) here
         public CurrentSnapshotResult execute(C context) {
             CurrentSnapshotResult result = delegate.execute(context);
             ImmutableSortedMap finalOutputs = result.getFinalOutputs();
    @@ -65,8 +60,6 @@ public CurrentSnapshotResult execute(C context) {
                     );
                 }
             });
    -        outputFilesRepository.recordOutputs(finalOutputs.values());
    -
             return result;
         }
     
    diff --git a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/CreateOutputsStepTest.groovy b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/CreateOutputsStepTest.groovy
    index 3d1c570c1d4a3..156257f2a10b8 100644
    --- a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/CreateOutputsStepTest.groovy
    +++ b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/CreateOutputsStepTest.groovy
    @@ -65,5 +65,6 @@ class CreateOutputsStepTest extends StepSpec {
             result == expected
             1 * work.visitOutputProperties(_ as UnitOfWork.OutputPropertyVisitor)
             1 * delegate.execute(context) >> expected
    +        0 * _
         }
     }
    diff --git a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/IncrementalExecutionTest.groovy b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/IncrementalExecutionTest.groovy
    index 731a2683adcfe..02e216d315c3b 100644
    --- a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/IncrementalExecutionTest.groovy
    +++ b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/IncrementalExecutionTest.groovy
    @@ -122,7 +122,7 @@ class IncrementalExecutionTest extends Specification {
             new DefaultWorkExecutor(
                 new ResolveChangesStep(
                     new SkipUpToDateStep(
    -                    new StoreSnapshotsStep(outputFilesRepository,
    +                    new StoreSnapshotsStep(
                             new SnapshotOutputStep(buildInvocationScopeId.getId(),
                                 new CreateOutputsStep(
                                     new CatchExceptionStep(
    diff --git a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/RecordOutputsStepTest.groovy b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/RecordOutputsStepTest.groovy
    new file mode 100644
    index 0000000000000..55d04680a5df3
    --- /dev/null
    +++ b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/RecordOutputsStepTest.groovy
    @@ -0,0 +1,48 @@
    +/*
    + * Copyright 2019 the original author or authors.
    + *
    + * Licensed under the Apache License, Version 2.0 (the "License");
    + * you may not use this file except in compliance with the License.
    + * You may obtain a copy of the License at
    + *
    + *      http://www.apache.org/licenses/LICENSE-2.0
    + *
    + * Unless required by applicable law or agreed to in writing, software
    + * distributed under the License is distributed on an "AS IS" BASIS,
    + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    + * See the License for the specific language governing permissions and
    + * limitations under the License.
    + */
    +
    +package org.gradle.internal.execution.steps
    +
    +import org.gradle.internal.execution.Context
    +import org.gradle.internal.execution.CurrentSnapshotResult
    +import org.gradle.internal.execution.history.OutputFilesRepository
    +
    +class RecordOutputsStepTest extends StepSpec implements FingerprinterFixture {
    +    def outputFilesRepository = Mock(OutputFilesRepository)
    +    def step = new RecordOutputsStep(outputFilesRepository, delegate)
    +
    +    def outputFile = file("output.txt").text = "output"
    +    def finalOutputs = fingerprintsOf(output: outputFile)
    +
    +    def context = Mock(Context)
    +    def delegateResult = Mock(CurrentSnapshotResult)
    +
    +    def "outputs are recorded after execution"() {
    +        when:
    +        def result = step.execute(context)
    +
    +        then:
    +        result == delegateResult
    +        1 * delegate.execute(context) >> delegateResult
    +
    +        then:
    +        1 * delegateResult.finalOutputs >> finalOutputs
    +
    +        then:
    +        1 * outputFilesRepository.recordOutputs(finalOutputs.values())
    +        0 * _
    +    }
    +}
    diff --git a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/StoreSnapshotsStepTest.groovy b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/StoreSnapshotsStepTest.groovy
    index cfb57055c0f91..8594f445310a0 100644
    --- a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/StoreSnapshotsStepTest.groovy
    +++ b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/StoreSnapshotsStepTest.groovy
    @@ -26,13 +26,11 @@ import org.gradle.internal.execution.IncrementalContext
     import org.gradle.internal.execution.history.AfterPreviousExecutionState
     import org.gradle.internal.execution.history.BeforeExecutionState
     import org.gradle.internal.execution.history.ExecutionHistoryStore
    -import org.gradle.internal.execution.history.OutputFilesRepository
     import org.gradle.internal.fingerprint.CurrentFileCollectionFingerprint
     import org.gradle.internal.hash.HashCode
     import org.gradle.internal.snapshot.impl.ImplementationSnapshot
     
     class StoreSnapshotsStepTest extends StepSpec implements FingerprinterFixture {
    -    def outputFilesRepository = Mock(OutputFilesRepository)
         def executionHistoryStore = Mock(ExecutionHistoryStore)
     
         def originMetadata = Mock(OriginMetadata)
    @@ -52,7 +50,7 @@ class StoreSnapshotsStepTest extends StepSpec implements FingerprinterFixture {
         def finalOutputs = fingerprintsOf(output: outputFile)
     
         def context = Mock(IncrementalContext)
    -    def step = new StoreSnapshotsStep(outputFilesRepository, delegate)
    +    def step = new StoreSnapshotsStep(delegate)
         def delegateResult = Mock(CurrentSnapshotResult)
     
         def "output snapshots are stored after successful execution"() {
    @@ -70,9 +68,7 @@ class StoreSnapshotsStepTest extends StepSpec implements FingerprinterFixture {
     
             then:
             interaction { expectStore(true, finalOutputs) }
    -
    -        then:
    -        1 * outputFilesRepository.recordOutputs(finalOutputs.values())
    +        0 * _
         }
     
         def "output snapshots are stored after failed execution when there's no previous state available"() {
    @@ -93,9 +89,7 @@ class StoreSnapshotsStepTest extends StepSpec implements FingerprinterFixture {
     
             then:
             interaction { expectStore(false, finalOutputs) }
    -
    -        then:
    -        1 * outputFilesRepository.recordOutputs(finalOutputs.values())
    +        0 * _
         }
     
         def "output snapshots are stored after failed execution with changed outputs"() {
    @@ -119,9 +113,7 @@ class StoreSnapshotsStepTest extends StepSpec implements FingerprinterFixture {
     
             then:
             interaction { expectStore(false, finalOutputs) }
    -
    -        then:
    -        1 * outputFilesRepository.recordOutputs(finalOutputs.values())
    +        0 * _
         }
     
         def "output snapshots are not stored after failed execution with unchanged outputs"() {
    @@ -142,9 +134,7 @@ class StoreSnapshotsStepTest extends StepSpec implements FingerprinterFixture {
             then:
             1 * context.afterPreviousExecutionState >> Optional.of(afterPreviousExecutionState)
             1 * afterPreviousExecutionState.outputFileProperties >> finalOutputs
    -
    -        then:
    -        1 * outputFilesRepository.recordOutputs(finalOutputs.values())
    +        0 * _
         }
     
         void expectStore(boolean successful, ImmutableSortedMap finalOutputs) {
    
    From 8833b498dd6abdfbb8b31fb13bed162758e235c1 Mon Sep 17 00:00:00 2001
    From: =?UTF-8?q?L=C3=B3r=C3=A1nt=20Pint=C3=A9r?= 
    Date: Fri, 8 Mar 2019 11:05:55 +0100
    Subject: [PATCH 407/853] Simplify CacheStepTest
    
    ---
     .../internal/execution/steps/CacheStep.java   |  44 ++++---
     .../execution/steps/CacheStepTest.groovy      | 115 +++++-------------
     .../steps/SkipUpToDateStepTest.groovy         |   8 +-
     3 files changed, 56 insertions(+), 111 deletions(-)
    
    diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/CacheStep.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/CacheStep.java
    index 78d9e946ea71a..bc098fa84a421 100644
    --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/CacheStep.java
    +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/CacheStep.java
    @@ -24,6 +24,7 @@
     import org.gradle.caching.internal.origin.OriginMetadata;
     import org.gradle.caching.internal.packaging.UnrecoverableUnpackingException;
     import org.gradle.internal.Try;
    +import org.gradle.internal.execution.CacheHandler;
     import org.gradle.internal.execution.CachingContext;
     import org.gradle.internal.execution.CurrentSnapshotResult;
     import org.gradle.internal.execution.ExecutionOutcome;
    @@ -62,33 +63,38 @@ public CurrentSnapshotResult execute(C context) {
             if (!buildCache.isEnabled()) {
                 return executeWithoutCache(context);
             }
    -        return context.getCacheHandler()
    +        CacheHandler cacheHandler = context.getCacheHandler();
    +        return cacheHandler
                 .load(cacheKey -> load(context.getWork(), cacheKey))
    -            .map(loadResult -> (CurrentSnapshotResult) new CurrentSnapshotResult() {
    -                @Override
    -                public Try getOutcome() {
    -                    return Try.successful(ExecutionOutcome.FROM_CACHE);
    -                }
    +            .map(loadResult -> {
    +                OriginMetadata originMetadata = loadResult.getOriginMetadata();
    +                ImmutableSortedMap finalOutputs = loadResult.getResultingSnapshots();
    +                return (CurrentSnapshotResult) new CurrentSnapshotResult() {
    +                    @Override
    +                    public Try getOutcome() {
    +                        return Try.successful(ExecutionOutcome.FROM_CACHE);
    +                    }
     
    -                @Override
    -                public OriginMetadata getOriginMetadata() {
    -                    return loadResult.getOriginMetadata();
    -                }
    +                    @Override
    +                    public OriginMetadata getOriginMetadata() {
    +                        return originMetadata;
    +                    }
     
    -                @Override
    -                public boolean isReused() {
    -                    return true;
    -                }
    +                    @Override
    +                    public boolean isReused() {
    +                        return true;
    +                    }
     
    -                @Override
    -                public ImmutableSortedMap getFinalOutputs() {
    -                    return loadResult.getResultingSnapshots();
    -                }
    +                    @Override
    +                    public ImmutableSortedMap getFinalOutputs() {
    +                        return finalOutputs;
    +                    }
    +                };
                 })
                 .orElseGet(() -> {
                     CurrentSnapshotResult executionResult = executeWithoutCache(context);
                     executionResult.getOutcome().ifSuccessfulOrElse(
    -                    outcome -> context.getCacheHandler().store(cacheKey -> store(context.getWork(), cacheKey, executionResult)),
    +                    outcome -> cacheHandler.store(cacheKey -> store(context.getWork(), cacheKey, executionResult)),
                         failure -> LOGGER.debug("Not storing result of {} in cache because the execution failed", context.getWork().getDisplayName())
                     );
                     return executionResult;
    diff --git a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/CacheStepTest.groovy b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/CacheStepTest.groovy
    index d560d07d29356..ac878b472a026 100644
    --- a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/CacheStepTest.groovy
    +++ b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/CacheStepTest.groovy
    @@ -16,85 +16,42 @@
     
     package org.gradle.internal.execution.steps
     
    -import com.google.common.collect.ImmutableSortedMap
     import org.gradle.caching.internal.command.BuildCacheCommandFactory
     import org.gradle.caching.internal.controller.BuildCacheController
     import org.gradle.caching.internal.origin.OriginMetadata
     import org.gradle.internal.Try
     import org.gradle.internal.execution.CacheHandler
     import org.gradle.internal.execution.CachingContext
    -import org.gradle.internal.execution.Context
     import org.gradle.internal.execution.CurrentSnapshotResult
     import org.gradle.internal.execution.ExecutionOutcome
     import org.gradle.internal.execution.OutputChangeListener
    -import org.gradle.internal.execution.Step
    -import org.gradle.internal.execution.UnitOfWork
    -import org.gradle.internal.execution.history.AfterPreviousExecutionState
    -import org.gradle.internal.execution.history.BeforeExecutionState
    -import org.gradle.internal.execution.history.changes.ExecutionStateChanges
    -import org.gradle.internal.fingerprint.CurrentFileCollectionFingerprint
    -import org.gradle.internal.fingerprint.impl.EmptyCurrentFileCollectionFingerprint
    -import org.gradle.internal.id.UniqueId
    -import spock.lang.Specification
    -
    -class CacheStepTest extends Specification {
     
    +class CacheStepTest extends StepSpec implements FingerprinterFixture {
         def buildCacheController = Mock(BuildCacheController)
         def buildCacheCommandFactory = Mock(BuildCacheCommandFactory)
         def outputChangeListener = Mock(OutputChangeListener)
    -    def currentBuildId = UniqueId.generate()
    -    Step delegateStep = Mock(Step)
    -    def cacheStep = new CacheStep(buildCacheController, outputChangeListener, buildCacheCommandFactory, delegateStep)
    +    def step = new CacheStep(buildCacheController, outputChangeListener, buildCacheCommandFactory, delegate)
         def cacheHandler = Mock(CacheHandler)
    -    def unitOfWork = Mock(UnitOfWork)
         def loadMetadata = Mock(BuildCacheCommandFactory.LoadMetadata)
    -    def cachedOriginMetadata = Mock(OriginMetadata)
    -    def context = new CachingContext() {
    -        @Override
    -        CacheHandler getCacheHandler() {
    -            CacheStepTest.this.cacheHandler
    -        }
    -
    -        @Override
    -        Optional getChanges() {
    -            return Optional.empty()
    -        }
    -
    -        @Override
    -        Optional getRebuildReason() {
    -            return context.getRebuildReason();
    -        }
    -
    -        @Override
    -        Optional getAfterPreviousExecutionState() {
    -            return context.getAfterPreviousExecutionState();
    -        }
    -
    -        @Override
    -        Optional getBeforeExecutionState() {
    -            return context.getBeforeExecutionState();
    -        }
    -
    -        @Override
    -        UnitOfWork getWork() {
    -            unitOfWork
    -        }
    -    }
    +
    +    def delegateResult = Mock(CurrentSnapshotResult)
    +    def context = Mock(CachingContext)
     
         def "loads from cache"() {
    -        def outputsFromCache = ImmutableSortedMap.of("test", new EmptyCurrentFileCollectionFingerprint())
    +        def cachedOriginMetadata = Mock(OriginMetadata)
    +        def outputsFromCache = fingerprintsOf("test": [])
     
             when:
    -        def result = cacheStep.execute(context)
    -        def originMetadata = result.originMetadata
    -        def finalOutputs = result.finalOutputs
    +        def result = step.execute(context)
    +
             then:
             result.outcome.get() == ExecutionOutcome.FROM_CACHE
             result.reused
    -        originMetadata == cachedOriginMetadata
    -        finalOutputs == outputsFromCache
    +        result.originMetadata == cachedOriginMetadata
    +        result.finalOutputs == outputsFromCache
     
             1 * buildCacheController.isEnabled() >> true
    +        1 * context.cacheHandler >> cacheHandler
             1 * cacheHandler.load(_) >> Optional.of(loadMetadata)
             1 * loadMetadata.originMetadata >> cachedOriginMetadata
             1 * loadMetadata.resultingSnapshots >> outputsFromCache
    @@ -102,64 +59,50 @@ class CacheStepTest extends Specification {
         }
     
         def "executes work and stores in cache on cache miss"() {
    -        def executionResult = new CurrentSnapshotResult() {
    -            final ImmutableSortedMap finalOutputs = ImmutableSortedMap.of("test", new EmptyCurrentFileCollectionFingerprint())
    -            final OriginMetadata originMetadata = new OriginMetadata(currentBuildId, 0)
    -            final Try outcome = Try.successful(ExecutionOutcome.EXECUTED)
    -            final boolean reused = false
    -        }
    -
             when:
    -        def result = cacheStep.execute(context)
    +        def result = step.execute(context)
     
             then:
    -        result == executionResult
    -        !result.reused
    +        result == delegateResult
     
             1 * buildCacheController.isEnabled() >> true
    +        1 * context.cacheHandler >> cacheHandler
             1 * cacheHandler.load(_) >> Optional.empty()
    -        1 * delegateStep.execute(_) >> executionResult
    +        1 * delegate.execute(context) >> delegateResult
    +        1 * delegateResult.outcome >> Try.successful(ExecutionOutcome.EXECUTED)
             1 * cacheHandler.store(_)
             0 * _
         }
     
         def "failures are not stored in the cache"() {
    -        def failedResult = new CurrentSnapshotResult() {
    -            final ImmutableSortedMap finalOutputs = ImmutableSortedMap.of("test", new EmptyCurrentFileCollectionFingerprint())
    -            final OriginMetadata originMetadata = new OriginMetadata(currentBuildId, 0)
    -            final Try outcome = Try.failure(new RuntimeException("failed"))
    -            final boolean reused = false
    -        }
    -
             when:
    -        def result = cacheStep.execute(context)
    +        def result = step.execute(context)
     
             then:
    -        result == failedResult
    +        result == delegateResult
             !result.reused
     
             1 * buildCacheController.isEnabled() >> true
    +        1 * context.cacheHandler >> cacheHandler
             1 * cacheHandler.load(_) >> Optional.empty()
    -        1 * delegateStep.execute(_) >> failedResult
    -        _ * unitOfWork.displayName >> "Display name"
    +        1 * delegate.execute(context) >> delegateResult
    +        1 * delegateResult.outcome >> Try.failure(new RuntimeException("failure"))
    +        1 * context.work >> work
    +        1 * work.displayName >> "Display name"
             0 * cacheHandler.store(_)
             0 * _
         }
     
         def "executes when caching is disabled"() {
    -        def executionResult = new CurrentSnapshotResult() {
    -            final ImmutableSortedMap finalOutputs = ImmutableSortedMap.of("test", new EmptyCurrentFileCollectionFingerprint())
    -            final OriginMetadata originMetadata = new OriginMetadata(currentBuildId, 0)
    -            final Try outcome = Try.successful(ExecutionOutcome.EXECUTED)
    -            final boolean reused = false
    -        }
             when:
    -        def result = cacheStep.execute(context)
    +        def result = step.execute(context)
    +
             then:
    -        result == executionResult
    +        result == delegateResult
    +        !result.reused
     
             1 * buildCacheController.isEnabled() >> false
    -        1 * delegateStep.execute(_) >> executionResult
    +        1 * delegate.execute(_) >> delegateResult
             0 * _
         }
     }
    diff --git a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/SkipUpToDateStepTest.groovy b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/SkipUpToDateStepTest.groovy
    index 9b3a6baa9f85a..aaedaffa124cd 100644
    --- a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/SkipUpToDateStepTest.groovy
    +++ b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/SkipUpToDateStepTest.groovy
    @@ -20,16 +20,12 @@ import org.gradle.internal.change.ChangeVisitor
     import org.gradle.internal.change.DescriptiveChange
     import org.gradle.internal.execution.ExecutionOutcome
     import org.gradle.internal.execution.IncrementalChangesContext
    -import org.gradle.internal.execution.Step
    -import org.gradle.internal.execution.UnitOfWork
     import org.gradle.internal.execution.history.changes.ExecutionStateChanges
    -import org.gradle.testing.internal.util.Specification
     
    -class SkipUpToDateStepTest extends Specification {
    -    def delegate = Mock(Step)
    +class SkipUpToDateStepTest extends StepSpec {
         def step = new SkipUpToDateStep(delegate)
         def context = Mock(IncrementalChangesContext)
    -    def work = Mock(UnitOfWork)
    +
         def changes = Mock(ExecutionStateChanges)
     
         def "skips when outputs are up to date"() {
    
    From 7d85e9a38302bd23b6d7f52a9fef22b9580c4734 Mon Sep 17 00:00:00 2001
    From: Jendrik Johannes 
    Date: Fri, 8 Mar 2019 11:28:44 +0100
    Subject: [PATCH 408/853] Remove old 'HipChat' webhook
    
    ---
     .../pluginData/plugin-settings.xml            | 19 +------------------
     1 file changed, 1 insertion(+), 18 deletions(-)
    
    diff --git a/.teamcity/Gradle_Promotion/pluginData/plugin-settings.xml b/.teamcity/Gradle_Promotion/pluginData/plugin-settings.xml
    index 9e41c7cba5cfd..566dff5528bd7 100644
    --- a/.teamcity/Gradle_Promotion/pluginData/plugin-settings.xml
    +++ b/.teamcity/Gradle_Promotion/pluginData/plugin-settings.xml
    @@ -1,20 +1,3 @@
     
    -
    -  
    -    
    -      
    -        
    -        
    -        
    -        
    -        
    -        
    -        
    -        
    -        
    -      
    -      
    -    
    -  
    -
    +
     
    
    From 55ec03eb34379b6aa73093fb13372057c0c16746 Mon Sep 17 00:00:00 2001
    From: Jendrik Johannes 
    Date: Fri, 8 Mar 2019 11:30:05 +0100
    Subject: [PATCH 409/853] Remove old reference to 'jdiff' report artificats
    
    We do not create these reports anymore. They were replaced with the
    binary compatibility reports in the Gradle build.
    ---
     .teamcity/Gradle_Promotion/buildTypes/StartReleaseCycle.kt | 1 -
     1 file changed, 1 deletion(-)
    
    diff --git a/.teamcity/Gradle_Promotion/buildTypes/StartReleaseCycle.kt b/.teamcity/Gradle_Promotion/buildTypes/StartReleaseCycle.kt
    index a194f92020dcc..3c2da9fd40152 100644
    --- a/.teamcity/Gradle_Promotion/buildTypes/StartReleaseCycle.kt
    +++ b/.teamcity/Gradle_Promotion/buildTypes/StartReleaseCycle.kt
    @@ -28,7 +28,6 @@ object StartReleaseCycle : BasePromotionBuildType(vcsRoot = Gradle_Promotion.vcs
     
         artifactRules = """
             incoming-build-receipt/build-receipt.properties => incoming-build-receipt
    -        promote-projects/gradle/build/reports/jdiff => jdiff
         """.trimIndent()
     
         params {
    
    From 9932d9ffbdd73de5b3800ac1a5b65c4fa5334ca4 Mon Sep 17 00:00:00 2001
    From: =?UTF-8?q?L=C3=B3r=C3=A1nt=20Pint=C3=A9r?= 
    Date: Fri, 8 Mar 2019 12:41:22 +0100
    Subject: [PATCH 410/853] Test forced rebuild to trigger a rebuild
    
    ---
     .../taskfactory/IncrementalTaskAction.java    | 14 ++++--
     .../changes/DefaultExecutionStateChanges.java | 12 +++--
     .../changes/ExecutionStateChanges.java        | 11 ++---
     .../execution/steps/ResolveChangesStep.java   | 10 ++--
     .../steps/IncrementalExecutionTest.groovy     | 46 +++++++++++--------
     .../steps/ResolveChangesStepTest.groovy       | 43 +++++++++++++++++
     6 files changed, 97 insertions(+), 39 deletions(-)
     create mode 100644 subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/ResolveChangesStepTest.groovy
    
    diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/project/taskfactory/IncrementalTaskAction.java b/subprojects/core/src/main/java/org/gradle/api/internal/project/taskfactory/IncrementalTaskAction.java
    index baaa26d47b831..50f5644d1fafd 100644
    --- a/subprojects/core/src/main/java/org/gradle/api/internal/project/taskfactory/IncrementalTaskAction.java
    +++ b/subprojects/core/src/main/java/org/gradle/api/internal/project/taskfactory/IncrementalTaskAction.java
    @@ -58,9 +58,17 @@ protected void doExecute(final Task task, String methodName) {
                 .map(new Function() {
                     @Override
                     public StatefulIncrementalTaskInputs apply(ExecutionStateChanges changes) {
    -                    return changes.isRebuildRequired()
    -                        ? createRebuildInputs(task)
    -                        : createIncrementalInputs(changes.getInputFilesChanges());
    +                    return changes.getInputFilesChanges().map(new Function, StatefulIncrementalTaskInputs>() {
    +                        @Override
    +                        public StatefulIncrementalTaskInputs apply(Iterable changes) {
    +                            return createIncrementalInputs(changes);
    +                        }
    +                    }).orElseGet(new Supplier() {
    +                        @Override
    +                        public StatefulIncrementalTaskInputs get() {
    +                            return createRebuildInputs(task);
    +                        }
    +                    });
                     }
                 }).orElseGet(new Supplier() {
                     @Override
    diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/DefaultExecutionStateChanges.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/DefaultExecutionStateChanges.java
    index 5d7beef53f302..afd599ed2f0dd 100644
    --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/DefaultExecutionStateChanges.java
    +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/DefaultExecutionStateChanges.java
    @@ -28,6 +28,8 @@
     import org.gradle.internal.execution.history.AfterPreviousExecutionState;
     import org.gradle.internal.execution.history.BeforeExecutionState;
     
    +import java.util.Optional;
    +
     public class DefaultExecutionStateChanges implements ExecutionStateChanges {
     
         private final AfterPreviousExecutionState previousExecution;
    @@ -96,10 +98,13 @@ private static ChangeContainer errorHandling(Describable executable, ChangeConta
         }
     
         @Override
    -    public Iterable getInputFilesChanges() {
    +    public Optional> getInputFilesChanges() {
    +        if (isRebuildRequired()) {
    +            return Optional.empty();
    +        }
             CollectingChangeVisitor visitor = new CollectingChangeVisitor();
             inputFileChanges.accept(visitor);
    -        return visitor.getChanges();
    +        return Optional.of(visitor.getChanges());
         }
     
         @Override
    @@ -107,8 +112,7 @@ public void visitAllChanges(ChangeVisitor visitor) {
             allChanges.accept(visitor);
         }
     
    -    @Override
    -    public boolean isRebuildRequired() {
    +    private boolean isRebuildRequired() {
             ChangeDetectorVisitor changeDetectorVisitor = new ChangeDetectorVisitor();
             rebuildTriggeringChanges.accept(changeDetectorVisitor);
             return changeDetectorVisitor.hasAnyChanges();
    diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/ExecutionStateChanges.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/ExecutionStateChanges.java
    index 81be7ee635260..467543da6e870 100644
    --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/ExecutionStateChanges.java
    +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/ExecutionStateChanges.java
    @@ -20,6 +20,8 @@
     import org.gradle.internal.change.ChangeVisitor;
     import org.gradle.internal.execution.history.AfterPreviousExecutionState;
     
    +import java.util.Optional;
    +
     /**
      * Represents the complete changes in execution state
      */
    @@ -28,20 +30,15 @@ public interface ExecutionStateChanges {
         int MAX_OUT_OF_DATE_MESSAGES = 3;
     
         /**
    -     * Returns changes to input files only.
    +     * Returns changes to input files only, or {@link Optional#empty()} if a full rebuild is required.
          */
    -    Iterable getInputFilesChanges();
    +    Optional> getInputFilesChanges();
     
         /**
          * Visits any change to inputs or outputs.
          */
         void visitAllChanges(ChangeVisitor visitor);
     
    -    /**
    -     * Whether there are changes that force an incremental task to fully rebuild.
    -     */
    -    boolean isRebuildRequired();
    -
         /**
          * The base execution the changes are calculated against.
          */
    diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/ResolveChangesStep.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/ResolveChangesStep.java
    index b9b8dbfd3758f..5a0201e12357b 100644
    --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/ResolveChangesStep.java
    +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/ResolveChangesStep.java
    @@ -86,6 +86,7 @@ public UnitOfWork getWork() {
             });
         }
     
    +    // TODO Use an Either type to capture rebuild reason instead of doing things like this
         private static class RebuildExecutionStateChanges implements ExecutionStateChanges {
             private final Change rebuildChange;
     
    @@ -94,8 +95,8 @@ public RebuildExecutionStateChanges(String rebuildReason) {
             }
     
             @Override
    -        public Iterable getInputFilesChanges() {
    -            throw new UnsupportedOperationException();
    +        public Optional> getInputFilesChanges() {
    +            return Optional.empty();
             }
     
             @Override
    @@ -103,11 +104,6 @@ public void visitAllChanges(ChangeVisitor visitor) {
                 visitor.visitChange(rebuildChange);
             }
     
    -        @Override
    -        public boolean isRebuildRequired() {
    -            return true;
    -        }
    -
             @Override
             public AfterPreviousExecutionState getPreviousExecution() {
                 throw new UnsupportedOperationException();
    diff --git a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/IncrementalExecutionTest.groovy b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/IncrementalExecutionTest.groovy
    index 02e216d315c3b..3e32fcc61447d 100644
    --- a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/IncrementalExecutionTest.groovy
    +++ b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/IncrementalExecutionTest.groovy
    @@ -26,18 +26,17 @@ import org.gradle.api.internal.file.collections.ImmutableFileCollection
     import org.gradle.caching.internal.CacheableEntity
     import org.gradle.internal.classloader.ClassLoaderHierarchyHasher
     import org.gradle.internal.execution.CacheHandler
    -import org.gradle.internal.execution.Context
     import org.gradle.internal.execution.ExecutionException
     import org.gradle.internal.execution.ExecutionOutcome
     import org.gradle.internal.execution.IncrementalChangesContext
     import org.gradle.internal.execution.IncrementalContext
     import org.gradle.internal.execution.OutputChangeListener
    -import org.gradle.internal.execution.Result
     import org.gradle.internal.execution.TestExecutionHistoryStore
    -import org.gradle.internal.execution.TestOutputFilesRepository
     import org.gradle.internal.execution.UnitOfWork
     import org.gradle.internal.execution.UpToDateResult
     import org.gradle.internal.execution.WorkExecutor
    +import org.gradle.internal.execution.history.AfterPreviousExecutionState
    +import org.gradle.internal.execution.history.BeforeExecutionState
     import org.gradle.internal.execution.history.ExecutionHistoryStore
     import org.gradle.internal.execution.history.changes.ExecutionStateChanges
     import org.gradle.internal.execution.impl.DefaultWorkExecutor
    @@ -59,15 +58,13 @@ import org.gradle.test.fixtures.file.TestFile
     import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider
     import org.gradle.testing.internal.util.Specification
     import org.junit.Rule
    -import spock.lang.Ignore
     
     import java.time.Duration
     import java.util.function.Supplier
     
     import static org.gradle.internal.execution.ExecutionOutcome.EXECUTED
     import static org.gradle.internal.execution.ExecutionOutcome.UP_TO_DATE
    -// FIXME:lptr
    -@Ignore
    +
     class IncrementalExecutionTest extends Specification {
     
         @Rule
    @@ -90,7 +87,6 @@ class IncrementalExecutionTest extends Specification {
                 fileSystemMirror.beforeOutputChange(affectedOutputPaths)
             }
         }
    -    def outputFilesRepository = new TestOutputFilesRepository()
         def buildInvocationScopeId = new BuildInvocationScopeId(UniqueId.generate())
         def classloaderHierarchyHasher = new ClassLoaderHierarchyHasher() {
             @Override
    @@ -120,16 +116,10 @@ class IncrementalExecutionTest extends Specification {
     
         WorkExecutor getExecutor() {
             new DefaultWorkExecutor(
    -            new ResolveChangesStep(
    -                new SkipUpToDateStep(
    -                    new StoreSnapshotsStep(
    -                        new SnapshotOutputStep(buildInvocationScopeId.getId(),
    -                            new CreateOutputsStep(
    -                                new CatchExceptionStep(
    -                                    new ExecuteStep(outputChangeListener)
    -                                )
    -                            )
    -                        )
    +            new SkipUpToDateStep(
    +                new StoreSnapshotsStep(
    +                    new SnapshotOutputStep(buildInvocationScopeId.getId(),
    +                        new ExecuteStep(outputChangeListener)
                         )
                     )
                 )
    @@ -602,11 +592,31 @@ class IncrementalExecutionTest extends Specification {
     
         UpToDateResult execute(UnitOfWork unitOfWork) {
             fileSystemMirror.beforeBuildFinished()
    -        executor.execute(new Context() {
    +        executor.execute(new IncrementalChangesContext() {
                 @Override
                 UnitOfWork getWork() {
                     return unitOfWork
                 }
    +
    +            @Override
    +            Optional getChanges() {
    +                return null
    +            }
    +
    +            @Override
    +            Optional getRebuildReason() {
    +                return null
    +            }
    +
    +            @Override
    +            Optional getAfterPreviousExecutionState() {
    +                return null
    +            }
    +
    +            @Override
    +            Optional getBeforeExecutionState() {
    +                return null
    +            }
             })
         }
     
    diff --git a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/ResolveChangesStepTest.groovy b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/ResolveChangesStepTest.groovy
    new file mode 100644
    index 0000000000000..f26c2af507b8c
    --- /dev/null
    +++ b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/ResolveChangesStepTest.groovy
    @@ -0,0 +1,43 @@
    +/*
    + * Copyright 2019 the original author or authors.
    + *
    + * Licensed under the Apache License, Version 2.0 (the "License");
    + * you may not use this file except in compliance with the License.
    + * You may obtain a copy of the License at
    + *
    + *      http://www.apache.org/licenses/LICENSE-2.0
    + *
    + * Unless required by applicable law or agreed to in writing, software
    + * distributed under the License is distributed on an "AS IS" BASIS,
    + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    + * See the License for the specific language governing permissions and
    + * limitations under the License.
    + */
    +
    +package org.gradle.internal.execution.steps
    +
    +import org.gradle.internal.execution.IncrementalChangesContext
    +import org.gradle.internal.execution.IncrementalContext
    +import org.gradle.internal.execution.Result
    +
    +class ResolveChangesStepTest extends StepSpec {
    +    def step = new ResolveChangesStep(delegate)
    +    def context = Mock(IncrementalContext)
    +    def delegateResult = Mock(Result)
    +
    +    def "doesn't detect input file changes when rebuild is forced"() {
    +        when:
    +        def result = step.execute(context)
    +
    +        then:
    +        result == delegateResult
    +
    +        1 * context.work >> work
    +        1 * delegate.execute(_ as IncrementalChangesContext) >> { IncrementalChangesContext delegateContext ->
    +            assert !delegateContext.changes.get().inputFilesChanges.present
    +            delegateResult
    +        }
    +        1 * context.rebuildReason >> Optional.of("force rebuild")
    +        0 * _
    +    }
    +}
    
    From 24e614450305faa839b09645a4a90ad01a80a836 Mon Sep 17 00:00:00 2001
    From: Stefan Wolf 
    Date: Fri, 8 Mar 2019 13:13:19 +0100
    Subject: [PATCH 411/853] Remove most of the `init` constructor parameters
    
    ---
     .teamcity/Gradle_Promotion/Project.kt         | 36 ++++++-------
     .../buildTypes/BasePromotionBuildType.kt      |  3 +-
     .../PromoteSnapshotFromQuickFeedback.kt       | 24 ---------
     ...PublishBranchSnapshotFromQuickFeedback.kt} |  9 ++--
     ...apshot.kt => PublishGradleDistribution.kt} | 10 ++--
     ...ySnapshot.kt => PublishNightlySnapshot.kt} | 31 ++++++-----
     ...ublishNightlySnapshotFromQuickFeedback.kt} | 13 +++--
     .../{PromoteRelease.kt => PublishRelease.kt}  |  8 +--
     .../buildTypes/StartReleaseCycle.kt           | 52 ++++++++++---------
     .../buildTypes/StartReleaseCycleTest.kt       | 48 +++++++++--------
     10 files changed, 112 insertions(+), 122 deletions(-)
     delete mode 100644 .teamcity/Gradle_Promotion/buildTypes/PromoteSnapshotFromQuickFeedback.kt
     rename .teamcity/Gradle_Promotion/buildTypes/{PromoteBranchSnapshotFromQuickFeedback.kt => PublishBranchSnapshotFromQuickFeedback.kt} (94%)
     rename .teamcity/Gradle_Promotion/buildTypes/{BasePromoteSnapshot.kt => PublishGradleDistribution.kt} (89%)
     rename .teamcity/Gradle_Promotion/buildTypes/{PromoteNightlySnapshot.kt => PublishNightlySnapshot.kt} (51%)
     rename .teamcity/Gradle_Promotion/buildTypes/{PromoteSnapshot.kt => PublishNightlySnapshotFromQuickFeedback.kt} (56%)
     rename .teamcity/Gradle_Promotion/buildTypes/{PromoteRelease.kt => PublishRelease.kt} (87%)
    
    diff --git a/.teamcity/Gradle_Promotion/Project.kt b/.teamcity/Gradle_Promotion/Project.kt
    index 3a480a524f007..c0e3ff4081a5d 100644
    --- a/.teamcity/Gradle_Promotion/Project.kt
    +++ b/.teamcity/Gradle_Promotion/Project.kt
    @@ -1,12 +1,12 @@
     package Gradle_Promotion
     
     import Gradle_Promotion.buildTypes.MasterSanityCheck
    -import Gradle_Promotion.buildTypes.PromoteBranchSnapshotFromQuickFeedback
    -import Gradle_Promotion.buildTypes.PromoteFinalRelease
    -import Gradle_Promotion.buildTypes.PromoteMilestone
    -import Gradle_Promotion.buildTypes.PromoteNightlySnapshot
    -import Gradle_Promotion.buildTypes.PromoteReleaseCandidate
    -import Gradle_Promotion.buildTypes.PromoteSnapshotFromQuickFeedback
    +import Gradle_Promotion.buildTypes.PublishBranchSnapshotFromQuickFeedback
    +import Gradle_Promotion.buildTypes.PublishFinalRelease
    +import Gradle_Promotion.buildTypes.PublishMilestone
    +import Gradle_Promotion.buildTypes.PublishNightlySnapshot
    +import Gradle_Promotion.buildTypes.PublishNightlySnapshotFromQuickFeedback
    +import Gradle_Promotion.buildTypes.PublishReleaseCandidate
     import Gradle_Promotion.buildTypes.StartReleaseCycle
     import Gradle_Promotion.buildTypes.StartReleaseCycleTest
     import Gradle_Promotion.vcsRoots.Gradle_Promotion_GradlePromotionBranches
    @@ -24,17 +24,17 @@ object Project : Project({
         vcsRoot(Gradle_Promotion_GradlePromotionBranches)
         vcsRoot(Gradle_Promotion__master_)
     
    -    val nightlyMasterSnapshot = PromoteNightlySnapshot(uuid = "01432c63-861f-4d08-ae0a-7d127f63096e", branch = "master", hour = 0)
    -    val masterSnapshotFromQuickFeedback = PromoteSnapshotFromQuickFeedback(uuid = "9a55bec1-4e70-449b-8f45-400093505afb", branch = "master")
    -    val nightlyReleaseSnapshot = PromoteNightlySnapshot(uuid = "1f5ca7f8-b0f5-41f9-9ba7-6d518b2822f0", branch = "release", hour = 1)
    -    val releaseSnapshotFromQuickFeedback = PromoteSnapshotFromQuickFeedback(uuid = "eeff4410-1e7d-4db6-b7b8-34c1f2754477", branch = "release")
    +    val nightlyMasterSnapshot = PublishNightlySnapshot(uuid = "01432c63-861f-4d08-ae0a-7d127f63096e", branch = "master", hour = 0)
    +    val masterSnapshotFromQuickFeedback = PublishNightlySnapshotFromQuickFeedback(uuid = "9a55bec1-4e70-449b-8f45-400093505afb", branch = "master")
    +    val nightlyReleaseSnapshot = PublishNightlySnapshot(uuid = "1f5ca7f8-b0f5-41f9-9ba7-6d518b2822f0", branch = "release", hour = 1)
    +    val releaseSnapshotFromQuickFeedback = PublishNightlySnapshotFromQuickFeedback(uuid = "eeff4410-1e7d-4db6-b7b8-34c1f2754477", branch = "release")
     
    -    buildType(PromoteBranchSnapshotFromQuickFeedback)
    -    buildType(PromoteMilestone)
    -    buildType(PromoteReleaseCandidate)
    +    buildType(PublishBranchSnapshotFromQuickFeedback)
    +    buildType(PublishMilestone)
    +    buildType(PublishReleaseCandidate)
         buildType(nightlyReleaseSnapshot)
         buildType(StartReleaseCycle)
    -    buildType(PromoteFinalRelease)
    +    buildType(PublishFinalRelease)
         buildType(nightlyMasterSnapshot)
         buildType(StartReleaseCycleTest)
         buildType(MasterSanityCheck)
    @@ -72,9 +72,9 @@ object Project : Project({
             StartReleaseCycle,
             nightlyReleaseSnapshot,
             releaseSnapshotFromQuickFeedback,
    -        PromoteBranchSnapshotFromQuickFeedback,
    -        PromoteMilestone,
    -        PromoteReleaseCandidate,
    -        PromoteFinalRelease
    +        PublishBranchSnapshotFromQuickFeedback,
    +        PublishMilestone,
    +        PublishReleaseCandidate,
    +        PublishFinalRelease
         )
     })
    diff --git a/.teamcity/Gradle_Promotion/buildTypes/BasePromotionBuildType.kt b/.teamcity/Gradle_Promotion/buildTypes/BasePromotionBuildType.kt
    index 31c31b7450ac0..802ce2546ed1f 100644
    --- a/.teamcity/Gradle_Promotion/buildTypes/BasePromotionBuildType.kt
    +++ b/.teamcity/Gradle_Promotion/buildTypes/BasePromotionBuildType.kt
    @@ -22,7 +22,7 @@ import jetbrains.buildServer.configs.kotlin.v2018_2.BuildType
     import jetbrains.buildServer.configs.kotlin.v2018_2.CheckoutMode
     import jetbrains.buildServer.configs.kotlin.v2018_2.vcs.GitVcsRoot
     
    -open class BasePromotionBuildType(vcsRoot: GitVcsRoot, cleanCheckout: Boolean = true, init: BasePromotionBuildType.() -> Unit = {}) : BuildType() {
    +abstract class BasePromotionBuildType(vcsRoot: GitVcsRoot, cleanCheckout: Boolean = true) : BuildType() {
         init {
             vcs {
                 root(vcsRoot)
    @@ -35,6 +35,5 @@ open class BasePromotionBuildType(vcsRoot: GitVcsRoot, cleanCheckout: Boolean =
             requirements {
                 requiresOs(Os.linux)
             }
    -        this.init()
         }
     }
    diff --git a/.teamcity/Gradle_Promotion/buildTypes/PromoteSnapshotFromQuickFeedback.kt b/.teamcity/Gradle_Promotion/buildTypes/PromoteSnapshotFromQuickFeedback.kt
    deleted file mode 100644
    index a127f0906b661..0000000000000
    --- a/.teamcity/Gradle_Promotion/buildTypes/PromoteSnapshotFromQuickFeedback.kt
    +++ /dev/null
    @@ -1,24 +0,0 @@
    -/*
    - * Copyright 2019 the original author or authors.
    - *
    - * Licensed under the Apache License, Version 2.0 (the "License");
    - * you may not use this file except in compliance with the License.
    - * You may obtain a copy of the License at
    - *
    - *      http://www.apache.org/licenses/LICENSE-2.0
    - *
    - * Unless required by applicable law or agreed to in writing, software
    - * distributed under the License is distributed on an "AS IS" BASIS,
    - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    - * See the License for the specific language governing permissions and
    - * limitations under the License.
    - */
    -
    -package Gradle_Promotion.buildTypes
    -
    -class PromoteSnapshotFromQuickFeedback(uuid: String, branch: String) : PromoteSnapshot(branch = branch, triggerName = "QuickFeedback", init = {
    -    this.uuid = uuid
    -    id("Gradle_Promotion_${capitalizedBranch}SnapshotFromQuickFeedback")
    -    name = capitalizedBranch
    -    description = "Promotes the latest successful changes on '$branch' from Quick Feedback as a new nightly snapshot"
    -})
    diff --git a/.teamcity/Gradle_Promotion/buildTypes/PromoteBranchSnapshotFromQuickFeedback.kt b/.teamcity/Gradle_Promotion/buildTypes/PublishBranchSnapshotFromQuickFeedback.kt
    similarity index 94%
    rename from .teamcity/Gradle_Promotion/buildTypes/PromoteBranchSnapshotFromQuickFeedback.kt
    rename to .teamcity/Gradle_Promotion/buildTypes/PublishBranchSnapshotFromQuickFeedback.kt
    index a0394a4e2ca22..9deab9fb5f1dd 100644
    --- a/.teamcity/Gradle_Promotion/buildTypes/PromoteBranchSnapshotFromQuickFeedback.kt
    +++ b/.teamcity/Gradle_Promotion/buildTypes/PublishBranchSnapshotFromQuickFeedback.kt
    @@ -18,13 +18,14 @@ package Gradle_Promotion.buildTypes
     
     import jetbrains.buildServer.configs.kotlin.v2018_2.ParameterDisplay
     
    -object PromoteBranchSnapshotFromQuickFeedback : BasePromoteSnapshot(
    +object PublishBranchSnapshotFromQuickFeedback : PublishGradleDistribution(
         branch = "%branch.to.promote%",
         triggerName = "QuickFeedback",
         task = "promoteSnapshot",
         extraParameters = "-PpromotedBranch=%branch.qualifier% ",
    -    vcsRoot = Gradle_Promotion.vcsRoots.Gradle_Promotion_GradlePromotionBranches,
    -    init = {
    +    vcsRoot = Gradle_Promotion.vcsRoots.Gradle_Promotion_GradlePromotionBranches
    +) {
    +    init {
             uuid = "b7ecebd3-3812-4532-aa77-5679f9e9d6b3"
             id("Gradle_Promotion_PublishBranchSnapshotFromQuickFeedback")
             name = "Publish Branch Snapshot (from Quick Feedback)"
    @@ -37,4 +38,4 @@ object PromoteBranchSnapshotFromQuickFeedback : BasePromoteSnapshot(
                 text("branch.to.promote", "%branch.qualifier%", label = "Branch to promote", description = "Type in the branch of gradle/gradle you want to promote. Leave the default value when promoting an existing build.", display = ParameterDisplay.PROMPT, allowEmpty = false)
             }
         }
    -)
    +}
    diff --git a/.teamcity/Gradle_Promotion/buildTypes/BasePromoteSnapshot.kt b/.teamcity/Gradle_Promotion/buildTypes/PublishGradleDistribution.kt
    similarity index 89%
    rename from .teamcity/Gradle_Promotion/buildTypes/BasePromoteSnapshot.kt
    rename to .teamcity/Gradle_Promotion/buildTypes/PublishGradleDistribution.kt
    index b42de355c37d8..f36a39723c9b2 100644
    --- a/.teamcity/Gradle_Promotion/buildTypes/BasePromoteSnapshot.kt
    +++ b/.teamcity/Gradle_Promotion/buildTypes/PublishGradleDistribution.kt
    @@ -23,15 +23,14 @@ import common.requiresOs
     import jetbrains.buildServer.configs.kotlin.v2018_2.AbsoluteId
     import jetbrains.buildServer.configs.kotlin.v2018_2.vcs.GitVcsRoot
     
    -open class BasePromoteSnapshot(
    +abstract class PublishGradleDistribution(
         branch: String,
         task: String,
         val triggerName: String,
         gitUserName: String = "Gradleware Git Bot",
         gitUserEmail: String = "gradlewaregitbot@gradleware.com",
         extraParameters: String = "",
    -    vcsRoot: GitVcsRoot = Gradle_Promotion.vcsRoots.Gradle_Promotion__master_,
    -    init: BasePromoteSnapshot.() -> Unit = {}
    +    vcsRoot: GitVcsRoot = Gradle_Promotion.vcsRoots.Gradle_Promotion__master_
     ) : BasePromotionBuildType(vcsRoot = vcsRoot) {
     
         init {
    @@ -52,7 +51,7 @@ open class BasePromoteSnapshot(
                 }
             }
             dependencies {
    -            artifacts(AbsoluteId("Gradle_Check_Stage_${this@BasePromoteSnapshot.triggerName}_Trigger")) {
    +            artifacts(AbsoluteId("Gradle_Check_Stage_${this@PublishGradleDistribution.triggerName}_Trigger")) {
                     buildRule = lastSuccessful(branch)
                     cleanDestination = true
                     artifactRules = "build-receipt.properties => incoming-build-receipt/"
    @@ -62,6 +61,7 @@ open class BasePromoteSnapshot(
             requirements {
                 requiresOs(Os.linux)
             }
    -        this.init()
         }
     }
    +
    +fun String.promoteNightlyTaskName(): String = "promote${if (this == "master") "" else capitalize()}Nightly"
    diff --git a/.teamcity/Gradle_Promotion/buildTypes/PromoteNightlySnapshot.kt b/.teamcity/Gradle_Promotion/buildTypes/PublishNightlySnapshot.kt
    similarity index 51%
    rename from .teamcity/Gradle_Promotion/buildTypes/PromoteNightlySnapshot.kt
    rename to .teamcity/Gradle_Promotion/buildTypes/PublishNightlySnapshot.kt
    index f1b8b17f7bd77..c88ebc8185e5d 100644
    --- a/.teamcity/Gradle_Promotion/buildTypes/PromoteNightlySnapshot.kt
    +++ b/.teamcity/Gradle_Promotion/buildTypes/PublishNightlySnapshot.kt
    @@ -18,20 +18,25 @@ package Gradle_Promotion.buildTypes
     
     import jetbrains.buildServer.configs.kotlin.v2018_2.triggers.schedule
     
    -class PromoteNightlySnapshot(uuid: String, branch: String, hour: Int) : PromoteSnapshot(branch = branch, triggerName = "ReadyforNightly", init = {
    -    val capitalizedBranch = this.capitalizedBranch
    -    this.uuid = uuid
    -    id("Gradle_Promotion_${capitalizedBranch}Nightly")
    -    name = "$capitalizedBranch - Nightly Snapshot"
    -    description = "Promotes the latest successful changes on '$branch' from Ready for Nightly as a new nightly snapshot"
    +class PublishNightlySnapshot(uuid: String, branch: String, hour: Int) : PublishGradleDistribution(
    +    branch = branch,
    +    task = branch.promoteNightlyTaskName(),
    +    triggerName = "ReadyforNightly"
    +) {
    +    init {
    +        this.uuid = uuid
    +        id("Gradle_Promotion_${branch.capitalize()}Nightly")
    +        name = "${branch.capitalize()} - Nightly Snapshot"
    +        description = "Promotes the latest successful changes on '$branch' from Ready for Nightly as a new nightly snapshot"
     
    -    triggers {
    -        schedule {
    -            schedulingPolicy = daily {
    -                this.hour = hour
    +        triggers {
    +            schedule {
    +                schedulingPolicy = daily {
    +                    this.hour = hour
    +                }
    +                triggerBuild = always()
    +                withPendingChangesOnly = false
                 }
    -            triggerBuild = always()
    -            withPendingChangesOnly = false
             }
         }
    -})
    +}
    diff --git a/.teamcity/Gradle_Promotion/buildTypes/PromoteSnapshot.kt b/.teamcity/Gradle_Promotion/buildTypes/PublishNightlySnapshotFromQuickFeedback.kt
    similarity index 56%
    rename from .teamcity/Gradle_Promotion/buildTypes/PromoteSnapshot.kt
    rename to .teamcity/Gradle_Promotion/buildTypes/PublishNightlySnapshotFromQuickFeedback.kt
    index a2a216ffe5955..229a40ebc4b51 100644
    --- a/.teamcity/Gradle_Promotion/buildTypes/PromoteSnapshot.kt
    +++ b/.teamcity/Gradle_Promotion/buildTypes/PublishNightlySnapshotFromQuickFeedback.kt
    @@ -16,10 +16,15 @@
     
     package Gradle_Promotion.buildTypes
     
    -open class PromoteSnapshot(branch: String, triggerName: String, init: PromoteSnapshot.() -> Unit = {}) : BasePromoteSnapshot(branch = branch, triggerName = triggerName, task = "promote${if (branch == "master") "" else branch.capitalize()}Nightly") {
    -    val capitalizedBranch = branch.capitalize()
    -
    +class PublishNightlySnapshotFromQuickFeedback(uuid: String, branch: String) : PublishGradleDistribution(
    +    branch = branch,
    +    task = branch.promoteNightlyTaskName(),
    +    triggerName = "QuickFeedback"
    +) {
         init {
    -        this.init()
    +        this.uuid = uuid
    +        id("Gradle_Promotion_${branch.capitalize()}SnapshotFromQuickFeedback")
    +        name = "${branch.capitalize()} - Nightly Snapshot (from QuickFeedback)"
    +        description = "Promotes the latest successful changes on '$branch' from Quick Feedback as a new nightly snapshot"
         }
     }
    diff --git a/.teamcity/Gradle_Promotion/buildTypes/PromoteRelease.kt b/.teamcity/Gradle_Promotion/buildTypes/PublishRelease.kt
    similarity index 87%
    rename from .teamcity/Gradle_Promotion/buildTypes/PromoteRelease.kt
    rename to .teamcity/Gradle_Promotion/buildTypes/PublishRelease.kt
    index 1b87bc8af9235..4f72bc0de91b3 100644
    --- a/.teamcity/Gradle_Promotion/buildTypes/PromoteRelease.kt
    +++ b/.teamcity/Gradle_Promotion/buildTypes/PublishRelease.kt
    @@ -18,7 +18,7 @@ package Gradle_Promotion.buildTypes
     
     import jetbrains.buildServer.configs.kotlin.v2018_2.ParameterDisplay
     
    -open class PromoteRelease(task: String, requiredConfirmationCode: String, branch: String = "release", init: PromoteRelease.() -> Unit = {}) : BasePromoteSnapshot(
    +abstract class PublishRelease(task: String, requiredConfirmationCode: String, branch: String = "release", init: PublishRelease.() -> Unit = {}) : PublishGradleDistribution(
         branch = branch,
         task = task,
         triggerName = "ReadyforRelease",
    @@ -36,21 +36,21 @@ open class PromoteRelease(task: String, requiredConfirmationCode: String, branch
         }
     }
     
    -object PromoteFinalRelease : PromoteRelease(task = "promoteFinalRelease", requiredConfirmationCode = "final", init = {
    +object PublishFinalRelease : PublishRelease(task = "promoteFinalRelease", requiredConfirmationCode = "final", init = {
         uuid = "44e9390f-e46c-457e-aa18-31b020aef4de"
         id("Gradle_Promotion_FinalRelease")
         name = "Release - Final"
         description = "Promotes the latest successful change on 'release' as a new release"
     })
     
    -object PromoteReleaseCandidate : PromoteRelease(task = "promoteRc", requiredConfirmationCode = "rc", init = {
    +object PublishReleaseCandidate : PublishRelease(task = "promoteRc", requiredConfirmationCode = "rc", init = {
         uuid = "5ed504bb-5ec3-46dc-a28a-e42a63ebbb31"
         id("Gradle_Promotion_ReleaseCandidate")
         name = "Release - Release Candidate"
         description = "Promotes the latest successful change on 'release' as a new release candidate"
     })
     
    -object PromoteMilestone : PromoteRelease(task = "promoteMilestone", requiredConfirmationCode = "milestone", init = {
    +object PublishMilestone : PublishRelease(task = "promoteMilestone", requiredConfirmationCode = "milestone", init = {
         uuid = "2ffb238a-08af-4f95-b863-9830d2bc3872"
         id("Gradle_Promotion_Milestone")
         name = "Release - Milestone"
    diff --git a/.teamcity/Gradle_Promotion/buildTypes/StartReleaseCycle.kt b/.teamcity/Gradle_Promotion/buildTypes/StartReleaseCycle.kt
    index 3c2da9fd40152..15d18146df442 100644
    --- a/.teamcity/Gradle_Promotion/buildTypes/StartReleaseCycle.kt
    +++ b/.teamcity/Gradle_Promotion/buildTypes/StartReleaseCycle.kt
    @@ -20,37 +20,39 @@ import common.gradleWrapper
     import jetbrains.buildServer.configs.kotlin.v2018_2.AbsoluteId
     import jetbrains.buildServer.configs.kotlin.v2018_2.ParameterDisplay
     
    -object StartReleaseCycle : BasePromotionBuildType(vcsRoot = Gradle_Promotion.vcsRoots.Gradle_Promotion__master_, init = {
    -    uuid = "355487d7-45b9-4387-9fc5-713e7683e6d0"
    -    id("Gradle_Promotion_StartReleaseCycle")
    -    name = "Master - Start Release Cycle"
    -    description = "Promotes a successful build on master as the start of a new release cycle on the release branch"
    +object StartReleaseCycle : BasePromotionBuildType(vcsRoot = Gradle_Promotion.vcsRoots.Gradle_Promotion__master_) {
    +    init {
    +        uuid = "355487d7-45b9-4387-9fc5-713e7683e6d0"
    +        id("Gradle_Promotion_StartReleaseCycle")
    +        name = "Master - Start Release Cycle"
    +        description = "Promotes a successful build on master as the start of a new release cycle on the release branch"
     
    -    artifactRules = """
    +        artifactRules = """
             incoming-build-receipt/build-receipt.properties => incoming-build-receipt
         """.trimIndent()
     
    -    params {
    -        text("gitUserEmail", "", label = "Git user.email Configuration", description = "Enter the git 'user.email' configuration to commit change under", display = ParameterDisplay.PROMPT, allowEmpty = true)
    -        text("confirmationCode", "", label = "Confirmation Code", description = "Enter the value 'startCycle' (no quotes) to confirm the promotion", display = ParameterDisplay.PROMPT, allowEmpty = false)
    -        text("gitUserName", "", label = "Git user.name Configuration", description = "Enter the git 'user.name' configuration to commit change under", display = ParameterDisplay.PROMPT, allowEmpty = true)
    -    }
    +        params {
    +            text("gitUserEmail", "", label = "Git user.email Configuration", description = "Enter the git 'user.email' configuration to commit change under", display = ParameterDisplay.PROMPT, allowEmpty = true)
    +            text("confirmationCode", "", label = "Confirmation Code", description = "Enter the value 'startCycle' (no quotes) to confirm the promotion", display = ParameterDisplay.PROMPT, allowEmpty = false)
    +            text("gitUserName", "", label = "Git user.name Configuration", description = "Enter the git 'user.name' configuration to commit change under", display = ParameterDisplay.PROMPT, allowEmpty = true)
    +        }
     
    -    steps {
    -        gradleWrapper {
    -            name = "Promote"
    -            tasks = "clean promoteStartReleaseCycle"
    -            useGradleWrapper = true
    -            gradleParams = """-PuseBuildReceipt -PconfirmationCode=%confirmationCode% "-PgitUserName=%gitUserName%" "-PgitUserEmail=%gitUserEmail%" -Igradle/buildScanInit.gradle"""
    -            param("org.jfrog.artifactory.selectedDeployableServer.defaultModuleVersionConfiguration", "GLOBAL")
    +        steps {
    +            gradleWrapper {
    +                name = "Promote"
    +                tasks = "clean promoteStartReleaseCycle"
    +                useGradleWrapper = true
    +                gradleParams = """-PuseBuildReceipt -PconfirmationCode=%confirmationCode% "-PgitUserName=%gitUserName%" "-PgitUserEmail=%gitUserEmail%" -Igradle/buildScanInit.gradle"""
    +                param("org.jfrog.artifactory.selectedDeployableServer.defaultModuleVersionConfiguration", "GLOBAL")
    +            }
             }
    -    }
     
    -    dependencies {
    -        artifacts(AbsoluteId("Gradle_Check_Stage_ReadyforNightly_Trigger")) {
    -            buildRule = lastSuccessful("master")
    -            cleanDestination = true
    -            artifactRules = "build-receipt.properties => incoming-build-receipt/"
    +        dependencies {
    +            artifacts(AbsoluteId("Gradle_Check_Stage_ReadyforNightly_Trigger")) {
    +                buildRule = lastSuccessful("master")
    +                cleanDestination = true
    +                artifactRules = "build-receipt.properties => incoming-build-receipt/"
    +            }
             }
         }
    -})
    +}
    diff --git a/.teamcity/Gradle_Promotion/buildTypes/StartReleaseCycleTest.kt b/.teamcity/Gradle_Promotion/buildTypes/StartReleaseCycleTest.kt
    index 205a89ec379c8..5b31d8527fd3b 100644
    --- a/.teamcity/Gradle_Promotion/buildTypes/StartReleaseCycleTest.kt
    +++ b/.teamcity/Gradle_Promotion/buildTypes/StartReleaseCycleTest.kt
    @@ -20,32 +20,34 @@ import common.gradleWrapper
     import jetbrains.buildServer.configs.kotlin.v2018_2.triggers.schedule
     import jetbrains.buildServer.configs.kotlin.v2018_2.triggers.vcs
     
    -object StartReleaseCycleTest : BasePromotionBuildType(vcsRoot = Gradle_Promotion.vcsRoots.Gradle_Promotion_GradlePromotionBranches, cleanCheckout = false, init = {
    -    uuid = "59823634-f79d-4c11-bbca-782957a7d65c"
    -    id("Gradle_Promotion_AllBranchesStartReleaseCycleTest")
    -    name = "Master - Start Release Cycle Test"
    -    description = "Test for Start Release Cycle pipeline"
    +object StartReleaseCycleTest : BasePromotionBuildType(vcsRoot = Gradle_Promotion.vcsRoots.Gradle_Promotion_GradlePromotionBranches, cleanCheckout = false) {
    +    init {
    +        uuid = "59823634-f79d-4c11-bbca-782957a7d65c"
    +        id("Gradle_Promotion_AllBranchesStartReleaseCycleTest")
    +        name = "Master - Start Release Cycle Test"
    +        description = "Test for Start Release Cycle pipeline"
     
    -    steps {
    -        gradleWrapper {
    -            name = "PromoteTest"
    -            tasks = "clean promoteStartReleaseCycle"
    -            useGradleWrapper = true
    -            gradleParams = "-PconfirmationCode=startCycle -Igradle/buildScanInit.gradle -PtestRun=1"
    +        steps {
    +            gradleWrapper {
    +                name = "PromoteTest"
    +                tasks = "clean promoteStartReleaseCycle"
    +                useGradleWrapper = true
    +                gradleParams = "-PconfirmationCode=startCycle -Igradle/buildScanInit.gradle -PtestRun=1"
    +            }
             }
    -    }
     
    -    triggers {
    -        vcs {
    -            branchFilter = "+:master"
    -        }
    -        schedule {
    -            schedulingPolicy = daily {
    -                hour = 3
    +        triggers {
    +            vcs {
    +                branchFilter = "+:master"
    +            }
    +            schedule {
    +                schedulingPolicy = daily {
    +                    hour = 3
    +                }
    +                branchFilter = "+:master"
    +                triggerBuild = always()
    +                withPendingChangesOnly = false
                 }
    -            branchFilter = "+:master"
    -            triggerBuild = always()
    -            withPendingChangesOnly = false
             }
         }
    -})
    +}
    
    From 422fb5682619f0161d0fbd3d5df43e7757da6bbd Mon Sep 17 00:00:00 2001
    From: =?UTF-8?q?L=C3=B3r=C3=A1nt=20Pint=C3=A9r?= 
    Date: Fri, 8 Mar 2019 13:18:18 +0100
    Subject: [PATCH 412/853] Move execution state change detection to mockable
     class
    
    ---
     .../execution/ExecuteActionsTaskExecuter.java |   2 +-
     .../scopes/ExecutionGradleServices.java       |   4 +-
     .../service/scopes/GlobalScopeServices.java   |   6 +
     .../ExecuteActionsTaskExecuterTest.groovy     |   3 +-
     .../DefaultDependencyManagementServices.java  |   4 +-
     .../transform/DefaultTransformerInvoker.java  |   2 +-
     .../gradle/internal/execution/UnitOfWork.java |   4 +-
     .../DefaultExecutionStateChangeDetector.java  | 140 ++++++++++++++++++
     .../changes/ExecutionStateChangeDetector.java |  32 ++++
     .../execution/steps/ResolveChangesStep.java   |  13 +-
     .../execution/steps/ExecutionTest.groovy      |   2 +-
     .../steps/IncrementalExecutionTest.groovy     |   2 +-
     .../steps/ResolveChangesStepTest.groovy       |   4 +-
     13 files changed, 204 insertions(+), 14 deletions(-)
     create mode 100644 subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/DefaultExecutionStateChangeDetector.java
     create mode 100644 subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/ExecutionStateChangeDetector.java
    
    diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuter.java b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuter.java
    index 476e4aee16101..4037b96f95198 100644
    --- a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuter.java
    +++ b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuter.java
    @@ -246,7 +246,7 @@ public void visitLocalState(LocalStateVisitor visitor) {
             }
     
             @Override
    -        public boolean includeAddedOutputs() {
    +        public boolean isAllowOverlappingOutputs() {
                 return false;
             }
     
    diff --git a/subprojects/core/src/main/java/org/gradle/internal/service/scopes/ExecutionGradleServices.java b/subprojects/core/src/main/java/org/gradle/internal/service/scopes/ExecutionGradleServices.java
    index 141533542f718..b6673d2304d83 100644
    --- a/subprojects/core/src/main/java/org/gradle/internal/service/scopes/ExecutionGradleServices.java
    +++ b/subprojects/core/src/main/java/org/gradle/internal/service/scopes/ExecutionGradleServices.java
    @@ -42,6 +42,7 @@
     import org.gradle.internal.execution.history.ExecutionHistoryCacheAccess;
     import org.gradle.internal.execution.history.ExecutionHistoryStore;
     import org.gradle.internal.execution.history.OutputFilesRepository;
    +import org.gradle.internal.execution.history.changes.ExecutionStateChangeDetector;
     import org.gradle.internal.execution.history.impl.DefaultExecutionHistoryStore;
     import org.gradle.internal.execution.history.impl.DefaultOutputFilesRepository;
     import org.gradle.internal.execution.impl.DefaultWorkExecutor;
    @@ -117,12 +118,13 @@ public WorkExecutor createWorkExecutor(
             BuildCacheController buildCacheController,
             BuildCancellationToken cancellationToken,
             BuildInvocationScopeId buildInvocationScopeId,
    +        ExecutionStateChangeDetector changeDetector,
             OutputChangeListener outputChangeListener,
             OutputFilesRepository outputFilesRepository,
             TimeoutHandler timeoutHandler
         ) {
             return new DefaultWorkExecutor(
    -            new ResolveChangesStep(
    +            new ResolveChangesStep(changeDetector,
                     new SkipUpToDateStep(
                         new RecordOutputsStep(outputFilesRepository,
                             new StoreSnapshotsStep(
    diff --git a/subprojects/core/src/main/java/org/gradle/internal/service/scopes/GlobalScopeServices.java b/subprojects/core/src/main/java/org/gradle/internal/service/scopes/GlobalScopeServices.java
    index 8da9413547d2f..d8947483c9a7b 100755
    --- a/subprojects/core/src/main/java/org/gradle/internal/service/scopes/GlobalScopeServices.java
    +++ b/subprojects/core/src/main/java/org/gradle/internal/service/scopes/GlobalScopeServices.java
    @@ -70,6 +70,8 @@
     import org.gradle.internal.concurrent.ParallelismConfigurationManager;
     import org.gradle.internal.environment.GradleBuildEnvironment;
     import org.gradle.internal.event.ListenerManager;
    +import org.gradle.internal.execution.history.changes.DefaultExecutionStateChangeDetector;
    +import org.gradle.internal.execution.history.changes.ExecutionStateChangeDetector;
     import org.gradle.internal.filewatch.DefaultFileWatcherFactory;
     import org.gradle.internal.filewatch.FileWatcherFactory;
     import org.gradle.internal.hash.DefaultStreamHasher;
    @@ -355,4 +357,8 @@ StreamHasher createStreamHasher() {
         Clock createClock() {
             return Time.clock();
         }
    +
    +    ExecutionStateChangeDetector createExecutionStateChangeDetector() {
    +        return new DefaultExecutionStateChangeDetector();
    +    }
     }
    diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuterTest.groovy b/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuterTest.groovy
    index 619d0d443278f..6b5a98a10bee5 100644
    --- a/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuterTest.groovy
    +++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuterTest.groovy
    @@ -38,6 +38,7 @@ import org.gradle.internal.execution.IncrementalContext
     import org.gradle.internal.execution.OutputChangeListener
     import org.gradle.internal.execution.UpToDateResult
     import org.gradle.internal.execution.history.ExecutionHistoryStore
    +import org.gradle.internal.execution.history.changes.DefaultExecutionStateChangeDetector
     import org.gradle.internal.execution.impl.DefaultWorkExecutor
     import org.gradle.internal.execution.steps.CancelExecutionStep
     import org.gradle.internal.execution.steps.CatchExceptionStep
    @@ -76,7 +77,7 @@ class ExecuteActionsTaskExecuterTest extends Specification {
         def outputChangeListener = Mock(OutputChangeListener)
         def cancellationToken = new DefaultBuildCancellationToken()
         def workExecutor = new DefaultWorkExecutor(
    -        new ResolveChangesStep(
    +        new ResolveChangesStep(new DefaultExecutionStateChangeDetector(),
                 new SkipUpToDateStep(
                     new SnapshotOutputStep(
                         buildId,
    diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/DefaultDependencyManagementServices.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/DefaultDependencyManagementServices.java
    index ee4c3955152ab..d300a3029dded 100644
    --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/DefaultDependencyManagementServices.java
    +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/DefaultDependencyManagementServices.java
    @@ -111,6 +111,7 @@
     import org.gradle.internal.execution.UpToDateResult;
     import org.gradle.internal.execution.WorkExecutor;
     import org.gradle.internal.execution.history.ExecutionHistoryStore;
    +import org.gradle.internal.execution.history.changes.ExecutionStateChangeDetector;
     import org.gradle.internal.execution.impl.DefaultWorkExecutor;
     import org.gradle.internal.execution.steps.CatchExceptionStep;
     import org.gradle.internal.execution.steps.CreateOutputsStep;
    @@ -195,6 +196,7 @@ OutputFileCollectionFingerprinter createOutputFingerprinter(FileSystemSnapshotte
              * Currently used for running artifact transformations in buildscript blocks.
              */
             WorkExecutor createWorkExecutor(
    +            ExecutionStateChangeDetector changeDetector,
                 ListenerManager listenerManager,
                 TimeoutHandler timeoutHandler
             ) {
    @@ -202,7 +204,7 @@ WorkExecutor createWorkExecutor(
                 // TODO: Figure out how to get rid of origin scope id in snapshot outputs step
                 UniqueId fixedUniqueId = UniqueId.from("dhwwyv4tqrd43cbxmdsf24wquu");
                 return new DefaultWorkExecutor<>(
    -                new ResolveChangesStep<>(
    +                new ResolveChangesStep<>(changeDetector,
                         new SkipUpToDateStep<>(
                             new StoreSnapshotsStep<>(
                                 new PrepareCachingStep<>(
    diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvoker.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvoker.java
    index 84ba6c3be164d..dbab073aafcc8 100644
    --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvoker.java
    +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvoker.java
    @@ -328,7 +328,7 @@ public void visitOutputProperties(OutputPropertyVisitor visitor) {
             }
     
             @Override
    -        public boolean includeAddedOutputs() {
    +        public boolean isAllowOverlappingOutputs() {
                 return true;
             }
     
    diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/UnitOfWork.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/UnitOfWork.java
    index c33cdef9600fc..96622f82b862a 100644
    --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/UnitOfWork.java
    +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/UnitOfWork.java
    @@ -59,9 +59,9 @@ public interface UnitOfWork extends CacheableEntity {
         Optional> getChangingOutputs();
     
         /**
    -     * Whether files added are to be considered part of the output of the work.
    +     * When overlapping outputs are allowed, output files added between executions are ignored during change detection.
          */
    -    boolean includeAddedOutputs();
    +    boolean isAllowOverlappingOutputs();
     
         @FunctionalInterface
         interface OutputPropertyVisitor {
    diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/DefaultExecutionStateChangeDetector.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/DefaultExecutionStateChangeDetector.java
    new file mode 100644
    index 0000000000000..7efe7dda80a92
    --- /dev/null
    +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/DefaultExecutionStateChangeDetector.java
    @@ -0,0 +1,140 @@
    +/*
    + * Copyright 2019 the original author or authors.
    + *
    + * Licensed under the Apache License, Version 2.0 (the "License");
    + * you may not use this file except in compliance with the License.
    + * You may obtain a copy of the License at
    + *
    + *      http://www.apache.org/licenses/LICENSE-2.0
    + *
    + * Unless required by applicable law or agreed to in writing, software
    + * distributed under the License is distributed on an "AS IS" BASIS,
    + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    + * See the License for the specific language governing permissions and
    + * limitations under the License.
    + */
    +
    +package org.gradle.internal.execution.history.changes;
    +
    +import org.gradle.api.Describable;
    +import org.gradle.internal.change.CachingChangeContainer;
    +import org.gradle.internal.change.Change;
    +import org.gradle.internal.change.ChangeContainer;
    +import org.gradle.internal.change.ChangeDetectorVisitor;
    +import org.gradle.internal.change.ChangeVisitor;
    +import org.gradle.internal.change.CollectingChangeVisitor;
    +import org.gradle.internal.change.ErrorHandlingChangeContainer;
    +import org.gradle.internal.change.SummarizingChangeContainer;
    +import org.gradle.internal.execution.history.AfterPreviousExecutionState;
    +import org.gradle.internal.execution.history.BeforeExecutionState;
    +
    +import java.util.Optional;
    +
    +public class DefaultExecutionStateChangeDetector implements ExecutionStateChangeDetector {
    +    @Override
    +    public ExecutionStateChanges detectChanges(AfterPreviousExecutionState lastExecution, BeforeExecutionState thisExecution, Describable executable, boolean allowOverlappingOutputs) {
    +        // Capture changes in execution outcome
    +        ChangeContainer previousSuccessState = new PreviousSuccessChanges(
    +            lastExecution.isSuccessful());
    +
    +        // Capture changes to implementation
    +        ChangeContainer implementationChanges = new ImplementationChanges(
    +            lastExecution.getImplementation(), lastExecution.getAdditionalImplementations(),
    +            thisExecution.getImplementation(), thisExecution.getAdditionalImplementations(),
    +            executable);
    +
    +        // Capture non-file input changes
    +        ChangeContainer inputPropertyChanges = new PropertyChanges(
    +            lastExecution.getInputProperties(),
    +            thisExecution.getInputProperties(),
    +            "Input",
    +            executable);
    +        ChangeContainer inputPropertyValueChanges = new InputValueChanges(
    +            lastExecution.getInputProperties(),
    +            thisExecution.getInputProperties(),
    +            executable);
    +
    +        // Capture input files state
    +        ChangeContainer inputFilePropertyChanges = new PropertyChanges(
    +            lastExecution.getInputFileProperties(),
    +            thisExecution.getInputFileProperties(),
    +            "Input file",
    +            executable);
    +        InputFileChanges directInputFileChanges = new InputFileChanges(
    +            lastExecution.getInputFileProperties(),
    +            thisExecution.getInputFileProperties());
    +        ChangeContainer inputFileChanges = caching(directInputFileChanges);
    +
    +        // Capture output files state
    +        ChangeContainer outputFilePropertyChanges = new PropertyChanges(
    +            lastExecution.getOutputFileProperties(),
    +            thisExecution.getOutputFileProperties(),
    +            "Output",
    +            executable);
    +        OutputFileChanges uncachedOutputChanges = new OutputFileChanges(
    +            lastExecution.getOutputFileProperties(),
    +            thisExecution.getOutputFileProperties(),
    +            allowOverlappingOutputs);
    +        ChangeContainer outputFileChanges = caching(uncachedOutputChanges);
    +
    +        return new DetectedExecutionStateChanges(
    +            lastExecution,
    +            errorHandling(executable, inputFileChanges),
    +            errorHandling(executable, new SummarizingChangeContainer(previousSuccessState, implementationChanges, inputPropertyChanges, inputPropertyValueChanges, outputFilePropertyChanges, outputFileChanges, inputFilePropertyChanges, inputFileChanges)),
    +            errorHandling(executable, new SummarizingChangeContainer(previousSuccessState, implementationChanges, inputPropertyChanges, inputPropertyValueChanges, inputFilePropertyChanges, outputFilePropertyChanges, outputFileChanges))
    +        );
    +    }
    +
    +    private static ChangeContainer caching(ChangeContainer wrapped) {
    +        return new CachingChangeContainer(MAX_OUT_OF_DATE_MESSAGES, wrapped);
    +    }
    +
    +    private static ChangeContainer errorHandling(Describable executable, ChangeContainer wrapped) {
    +        return new ErrorHandlingChangeContainer(executable, wrapped);
    +    }
    +
    +    private static class DetectedExecutionStateChanges implements ExecutionStateChanges {
    +        private final AfterPreviousExecutionState previousExecution;
    +        private final ChangeContainer inputFileChanges;
    +        private final ChangeContainer allChanges;
    +        private final ChangeContainer rebuildTriggeringChanges;
    +
    +        public DetectedExecutionStateChanges(
    +            AfterPreviousExecutionState previousExecution,
    +            ChangeContainer inputFileChanges,
    +            ChangeContainer allChanges,
    +            ChangeContainer rebuildTriggeringChanges
    +        ) {
    +            this.previousExecution = previousExecution;
    +            this.inputFileChanges = inputFileChanges;
    +            this.allChanges = allChanges;
    +            this.rebuildTriggeringChanges = rebuildTriggeringChanges;
    +        }
    +
    +        @Override
    +        public Optional> getInputFilesChanges() {
    +            if (isRebuildRequired()) {
    +                return Optional.empty();
    +            }
    +            CollectingChangeVisitor visitor = new CollectingChangeVisitor();
    +            inputFileChanges.accept(visitor);
    +            return Optional.of(visitor.getChanges());
    +        }
    +
    +        @Override
    +        public void visitAllChanges(ChangeVisitor visitor) {
    +            allChanges.accept(visitor);
    +        }
    +
    +        private boolean isRebuildRequired() {
    +            ChangeDetectorVisitor changeDetectorVisitor = new ChangeDetectorVisitor();
    +            rebuildTriggeringChanges.accept(changeDetectorVisitor);
    +            return changeDetectorVisitor.hasAnyChanges();
    +        }
    +
    +        @Override
    +        public AfterPreviousExecutionState getPreviousExecution() {
    +            return previousExecution;
    +        }
    +    }
    +}
    diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/ExecutionStateChangeDetector.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/ExecutionStateChangeDetector.java
    new file mode 100644
    index 0000000000000..3afdc307c2313
    --- /dev/null
    +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/ExecutionStateChangeDetector.java
    @@ -0,0 +1,32 @@
    +/*
    + * Copyright 2019 the original author or authors.
    + *
    + * Licensed under the Apache License, Version 2.0 (the "License");
    + * you may not use this file except in compliance with the License.
    + * You may obtain a copy of the License at
    + *
    + *      http://www.apache.org/licenses/LICENSE-2.0
    + *
    + * Unless required by applicable law or agreed to in writing, software
    + * distributed under the License is distributed on an "AS IS" BASIS,
    + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    + * See the License for the specific language governing permissions and
    + * limitations under the License.
    + */
    +
    +package org.gradle.internal.execution.history.changes;
    +
    +import org.gradle.api.Describable;
    +import org.gradle.internal.execution.history.AfterPreviousExecutionState;
    +import org.gradle.internal.execution.history.BeforeExecutionState;
    +
    +public interface ExecutionStateChangeDetector {
    +    int MAX_OUT_OF_DATE_MESSAGES = 3;
    +
    +    ExecutionStateChanges detectChanges(
    +        AfterPreviousExecutionState lastExecution,
    +        BeforeExecutionState thisExecution,
    +        Describable executable,
    +        boolean allowOverlappingOutputs
    +    );
    +}
    diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/ResolveChangesStep.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/ResolveChangesStep.java
    index 5a0201e12357b..22da841692723 100644
    --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/ResolveChangesStep.java
    +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/ResolveChangesStep.java
    @@ -26,15 +26,20 @@
     import org.gradle.internal.execution.UnitOfWork;
     import org.gradle.internal.execution.history.AfterPreviousExecutionState;
     import org.gradle.internal.execution.history.BeforeExecutionState;
    -import org.gradle.internal.execution.history.changes.DefaultExecutionStateChanges;
    +import org.gradle.internal.execution.history.changes.ExecutionStateChangeDetector;
     import org.gradle.internal.execution.history.changes.ExecutionStateChanges;
     
     import java.util.Optional;
     
     public class ResolveChangesStep implements Step {
    +    private final ExecutionStateChangeDetector changeDetector;
         private final Step delegate;
     
    -    public ResolveChangesStep(Step delegate) {
    +    public ResolveChangesStep(
    +        ExecutionStateChangeDetector changeDetector,
    +        Step delegate
    +    ) {
    +        this.changeDetector = changeDetector;
             this.delegate = delegate;
         }
     
    @@ -48,11 +53,11 @@ public R execute(IncrementalContext context) {
                 .orElseGet(() ->
                     context.getAfterPreviousExecutionState()
                         .flatMap(afterPreviousExecution -> context.getBeforeExecutionState()
    -                        .map(beforeExecution -> new DefaultExecutionStateChanges(
    +                        .map(beforeExecution -> changeDetector.detectChanges(
                                 afterPreviousExecution,
                                 beforeExecution,
                                 work,
    -                            work.includeAddedOutputs())
    +                            work.isAllowOverlappingOutputs())
                             )
                         )
                         .orElse(null)
    diff --git a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/ExecutionTest.groovy b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/ExecutionTest.groovy
    index c313df01daa5b..100c7c8f10bc6 100644
    --- a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/ExecutionTest.groovy
    +++ b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/ExecutionTest.groovy
    @@ -157,7 +157,7 @@ class ExecutionTest extends Specification {
             }
     
             @Override
    -        boolean includeAddedOutputs() {
    +        boolean isAllowOverlappingOutputs() {
                 return true
             }
     
    diff --git a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/IncrementalExecutionTest.groovy b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/IncrementalExecutionTest.groovy
    index 3e32fcc61447d..2b77209092ad3 100644
    --- a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/IncrementalExecutionTest.groovy
    +++ b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/IncrementalExecutionTest.groovy
    @@ -749,7 +749,7 @@ class IncrementalExecutionTest extends Specification {
                     }
     
                     @Override
    -                boolean includeAddedOutputs() {
    +                boolean isAllowOverlappingOutputs() {
                         return true
                     }
     
    diff --git a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/ResolveChangesStepTest.groovy b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/ResolveChangesStepTest.groovy
    index f26c2af507b8c..2f694866ccd7d 100644
    --- a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/ResolveChangesStepTest.groovy
    +++ b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/ResolveChangesStepTest.groovy
    @@ -19,9 +19,11 @@ package org.gradle.internal.execution.steps
     import org.gradle.internal.execution.IncrementalChangesContext
     import org.gradle.internal.execution.IncrementalContext
     import org.gradle.internal.execution.Result
    +import org.gradle.internal.execution.history.changes.ExecutionStateChangeDetector
     
     class ResolveChangesStepTest extends StepSpec {
    -    def step = new ResolveChangesStep(delegate)
    +    def changeDetector = Mock(ExecutionStateChangeDetector)
    +    def step = new ResolveChangesStep(changeDetector, delegate)
         def context = Mock(IncrementalContext)
         def delegateResult = Mock(Result)
     
    
    From 679de7efe762e660e1d6b172d26616b80d645239 Mon Sep 17 00:00:00 2001
    From: =?UTF-8?q?L=C3=B3r=C3=A1nt=20Pint=C3=A9r?= 
    Date: Fri, 8 Mar 2019 13:25:20 +0100
    Subject: [PATCH 413/853] Test ResolveChangesStepTest
    
    Also added the ability to disable change tracking completely for a work item. This is now handled separately from the case where change tracking is enabled, but history is unavailable.
    
    This feature is not used with tasks and artifact transforms yet.
    ---
     .../execution/steps/ResolveChangesStep.java   | 16 ++--
     .../execution/steps/SkipUpToDateStep.java     |  4 +-
     .../steps/ResolveChangesStepTest.groovy       | 80 +++++++++++++++++--
     .../steps/SkipUpToDateStepTest.groovy         |  4 +-
     4 files changed, 88 insertions(+), 16 deletions(-)
    
    diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/ResolveChangesStep.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/ResolveChangesStep.java
    index 22da841692723..d9acdee3ee7ef 100644
    --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/ResolveChangesStep.java
    +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/ResolveChangesStep.java
    @@ -33,6 +33,8 @@
     
     public class ResolveChangesStep implements Step {
         private final ExecutionStateChangeDetector changeDetector;
    +    private static final Change NO_HISTORY = new DescriptiveChange("No history is available.");
    +
         private final Step delegate;
     
         public ResolveChangesStep(
    @@ -48,17 +50,18 @@ public R execute(IncrementalContext context) {
             final UnitOfWork work = context.getWork();
             ExecutionStateChanges changes = context.getRebuildReason()
                 .map(rebuildReason ->
    -                new RebuildExecutionStateChanges(rebuildReason)
    +                new RebuildExecutionStateChanges(new DescriptiveChange(rebuildReason))
                 )
                 .orElseGet(() ->
    -                context.getAfterPreviousExecutionState()
    -                    .flatMap(afterPreviousExecution -> context.getBeforeExecutionState()
    -                        .map(beforeExecution -> changeDetector.detectChanges(
    +                context.getBeforeExecutionState()
    +                    .map(beforeExecution -> context.getAfterPreviousExecutionState()
    +                        .map(afterPreviousExecution -> changeDetector.detectChanges(
                                 afterPreviousExecution,
                                 beforeExecution,
                                 work,
                                 work.isAllowOverlappingOutputs())
                             )
    +                        .orElseGet(() -> new RebuildExecutionStateChanges(NO_HISTORY))
                         )
                         .orElse(null)
                 );
    @@ -91,12 +94,11 @@ public UnitOfWork getWork() {
             });
         }
     
    -    // TODO Use an Either type to capture rebuild reason instead of doing things like this
         private static class RebuildExecutionStateChanges implements ExecutionStateChanges {
             private final Change rebuildChange;
     
    -        public RebuildExecutionStateChanges(String rebuildReason) {
    -            this.rebuildChange = new DescriptiveChange(rebuildReason);
    +        public RebuildExecutionStateChanges(Change rebuildChange) {
    +            this.rebuildChange = rebuildChange;
             }
     
             @Override
    diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/SkipUpToDateStep.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/SkipUpToDateStep.java
    index 25dd99fe70a89..0f9187ad86ae7 100644
    --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/SkipUpToDateStep.java
    +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/SkipUpToDateStep.java
    @@ -40,7 +40,7 @@
     public class SkipUpToDateStep implements Step {
         private static final Logger LOGGER = LoggerFactory.getLogger(SkipUpToDateStep.class);
     
    -    private static final ImmutableList NO_HISTORY = ImmutableList.of("No history is available.");
    +    private static final ImmutableList CHANGE_TRACKING_DISABLED = ImmutableList.of("Change tracking is disabled.");
     
         private final Step delegate;
     
    @@ -91,7 +91,7 @@ public boolean isReused() {
                 } else {
                     return executeBecause(reasons, context);
                 }
    -        }).orElseGet(() -> executeBecause(NO_HISTORY, context));
    +        }).orElseGet(() -> executeBecause(CHANGE_TRACKING_DISABLED, context));
         }
     
         private UpToDateResult executeBecause(ImmutableList reasons, C context) {
    diff --git a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/ResolveChangesStepTest.groovy b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/ResolveChangesStepTest.groovy
    index 2f694866ccd7d..fe8cc8b551679 100644
    --- a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/ResolveChangesStepTest.groovy
    +++ b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/ResolveChangesStepTest.groovy
    @@ -19,7 +19,10 @@ package org.gradle.internal.execution.steps
     import org.gradle.internal.execution.IncrementalChangesContext
     import org.gradle.internal.execution.IncrementalContext
     import org.gradle.internal.execution.Result
    +import org.gradle.internal.execution.history.AfterPreviousExecutionState
    +import org.gradle.internal.execution.history.BeforeExecutionState
     import org.gradle.internal.execution.history.changes.ExecutionStateChangeDetector
    +import org.gradle.internal.execution.history.changes.ExecutionStateChanges
     
     class ResolveChangesStepTest extends StepSpec {
         def changeDetector = Mock(ExecutionStateChangeDetector)
    @@ -27,7 +30,7 @@ class ResolveChangesStepTest extends StepSpec {
         def context = Mock(IncrementalContext)
         def delegateResult = Mock(Result)
     
    -    def "doesn't detect input file changes when rebuild is forced"() {
    +    def "doesn't provide input file changes when rebuild is forced"() {
             when:
             def result = step.execute(context)
     
    @@ -35,11 +38,78 @@ class ResolveChangesStepTest extends StepSpec {
             result == delegateResult
     
             1 * context.work >> work
    -        1 * delegate.execute(_ as IncrementalChangesContext) >> { IncrementalChangesContext delegateContext ->
    -            assert !delegateContext.changes.get().inputFilesChanges.present
    -            delegateResult
    +        1 * delegate.execute(_) >> { IncrementalChangesContext delegateContext ->
    +            def changes = delegateContext.changes.get()
    +            assert !changes.inputFilesChanges.present
    +            String change = null
    +            changes.visitAllChanges({ change = it.message; false })
    +            assert change == "Forced rebuild."
    +            return delegateResult
             }
    -        1 * context.rebuildReason >> Optional.of("force rebuild")
    +        1 * context.rebuildReason >> Optional.of("Forced rebuild.")
    +        0 * _
    +    }
    +
    +    def "doesn't provide changes when change tracking is disabled"() {
    +        when:
    +        def result = step.execute(context)
    +
    +        then:
    +        result == delegateResult
    +
    +        1 * context.work >> work
    +        1 * delegate.execute(_) >> { IncrementalChangesContext delegateContext ->
    +            assert !delegateContext.changes.present
    +            return delegateResult
    +        }
    +        1 * context.rebuildReason >> Optional.empty()
    +        1 * context.beforeExecutionState >> Optional.empty()
    +        0 * _
    +    }
    +
    +    def "doesn't provide input file changes when no history is available"() {
    +        when:
    +        def result = step.execute(context)
    +
    +        then:
    +        result == delegateResult
    +
    +        1 * context.work >> work
    +        1 * delegate.execute(_) >> { IncrementalChangesContext delegateContext ->
    +            def changes = delegateContext.changes.get()
    +            assert !changes.inputFilesChanges.present
    +            String change = null
    +            changes.visitAllChanges({ change = it.message; false })
    +            assert change == "No history is available."
    +            return delegateResult
    +        }
    +        1 * context.rebuildReason >> Optional.empty()
    +        1 * context.beforeExecutionState >> Optional.of(Mock(BeforeExecutionState))
    +        1 * context.afterPreviousExecutionState >> Optional.empty()
    +        0 * _
    +    }
    +
    +    def "provides input file changes when history is available"() {
    +        def beforeExecutionState = Mock(BeforeExecutionState)
    +        def afterPreviousExecutionState = Mock(AfterPreviousExecutionState)
    +        def changes = Mock(ExecutionStateChanges)
    +
    +        when:
    +        def result = step.execute(context)
    +
    +        then:
    +        result == delegateResult
    +
    +        1 * context.work >> work
    +        1 * delegate.execute(_) >> { IncrementalChangesContext delegateContext ->
    +            assert delegateContext.changes.get() == changes
    +            return delegateResult
    +        }
    +        1 * context.rebuildReason >> Optional.empty()
    +        1 * context.beforeExecutionState >> Optional.of(beforeExecutionState)
    +        1 * context.afterPreviousExecutionState >> Optional.of(afterPreviousExecutionState)
    +        1 * work.allowOverlappingOutputs >> true
    +        1 * changeDetector.detectChanges(afterPreviousExecutionState, beforeExecutionState, work, true) >> changes
             0 * _
         }
     }
    diff --git a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/SkipUpToDateStepTest.groovy b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/SkipUpToDateStepTest.groovy
    index aaedaffa124cd..6623682563a72 100644
    --- a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/SkipUpToDateStepTest.groovy
    +++ b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/SkipUpToDateStepTest.groovy
    @@ -57,12 +57,12 @@ class SkipUpToDateStepTest extends StepSpec {
             0 * _
         }
     
    -    def "executes when there's no history available"() {
    +    def "executes when change tracking is disabled"() {
             when:
             def result = step.execute(context)
     
             then:
    -        result.executionReasons == ["No history is available."]
    +        result.executionReasons == ["Change tracking is disabled."]
     
             1 * context.getWork() >> work
             1 * context.changes >> Optional.empty()
    
    From df30597c125af113ad8265a11bc2f40e156a586f Mon Sep 17 00:00:00 2001
    From: =?UTF-8?q?L=C3=B3r=C3=A1nt=20Pint=C3=A9r?= 
    Date: Fri, 8 Mar 2019 14:11:20 +0100
    Subject: [PATCH 414/853] Separate broadcasting output changes and add more
     tests
    
    ---
     .../scopes/ExecutionGradleServices.java       |  5 +-
     .../ExecuteActionsTaskExecuterTest.groovy     |  8 ++-
     .../DefaultDependencyManagementServices.java  |  5 +-
     .../steps/BroadcastChangingOutputsStep.java   | 51 ++++++++++++++
     .../execution/steps/CatchExceptionStep.java   |  2 +-
     .../internal/execution/steps/ExecuteStep.java | 26 +-------
     .../BroadcastChangingOutputsStepTest.groovy   | 66 +++++++++++++++++++
     .../steps/CatchExceptionStepTest.groovy       | 59 +++++++++++++++++
     .../execution/steps/ExecuteStepTest.groovy    | 60 +++++++++++++++++
     .../execution/steps/ExecutionTest.groovy      |  4 +-
     .../steps/IncrementalExecutionTest.groovy     |  2 +-
     11 files changed, 257 insertions(+), 31 deletions(-)
     create mode 100644 subprojects/execution/src/main/java/org/gradle/internal/execution/steps/BroadcastChangingOutputsStep.java
     create mode 100644 subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/BroadcastChangingOutputsStepTest.groovy
     create mode 100644 subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/CatchExceptionStepTest.groovy
     create mode 100644 subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/ExecuteStepTest.groovy
    
    diff --git a/subprojects/core/src/main/java/org/gradle/internal/service/scopes/ExecutionGradleServices.java b/subprojects/core/src/main/java/org/gradle/internal/service/scopes/ExecutionGradleServices.java
    index b6673d2304d83..e50f30c7750ac 100644
    --- a/subprojects/core/src/main/java/org/gradle/internal/service/scopes/ExecutionGradleServices.java
    +++ b/subprojects/core/src/main/java/org/gradle/internal/service/scopes/ExecutionGradleServices.java
    @@ -46,6 +46,7 @@
     import org.gradle.internal.execution.history.impl.DefaultExecutionHistoryStore;
     import org.gradle.internal.execution.history.impl.DefaultOutputFilesRepository;
     import org.gradle.internal.execution.impl.DefaultWorkExecutor;
    +import org.gradle.internal.execution.steps.BroadcastChangingOutputsStep;
     import org.gradle.internal.execution.steps.CacheStep;
     import org.gradle.internal.execution.steps.CancelExecutionStep;
     import org.gradle.internal.execution.steps.CatchExceptionStep;
    @@ -135,7 +136,9 @@ public WorkExecutor createWorkExecutor(
                                                 new CatchExceptionStep(
                                                     new TimeoutStep(timeoutHandler,
                                                         new CancelExecutionStep(cancellationToken,
    -                                                        new ExecuteStep(outputChangeListener)
    +                                                        new BroadcastChangingOutputsStep(outputChangeListener,
    +                                                            new ExecuteStep()
    +                                                        )
                                                         )
                                                     )
                                                 )
    diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuterTest.groovy b/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuterTest.groovy
    index 6b5a98a10bee5..40886fe200ca1 100644
    --- a/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuterTest.groovy
    +++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuterTest.groovy
    @@ -40,6 +40,7 @@ import org.gradle.internal.execution.UpToDateResult
     import org.gradle.internal.execution.history.ExecutionHistoryStore
     import org.gradle.internal.execution.history.changes.DefaultExecutionStateChangeDetector
     import org.gradle.internal.execution.impl.DefaultWorkExecutor
    +import org.gradle.internal.execution.steps.BroadcastChangingOutputsStep
     import org.gradle.internal.execution.steps.CancelExecutionStep
     import org.gradle.internal.execution.steps.CatchExceptionStep
     import org.gradle.internal.execution.steps.ExecuteStep
    @@ -79,11 +80,12 @@ class ExecuteActionsTaskExecuterTest extends Specification {
         def workExecutor = new DefaultWorkExecutor(
             new ResolveChangesStep(new DefaultExecutionStateChangeDetector(),
                 new SkipUpToDateStep(
    -                new SnapshotOutputStep(
    -                    buildId,
    +                new SnapshotOutputStep(buildId,
                         new CatchExceptionStep(
                             new CancelExecutionStep(cancellationToken,
    -                            new ExecuteStep(outputChangeListener)
    +                            new BroadcastChangingOutputsStep(outputChangeListener,
    +                                new ExecuteStep()
    +                            )
                             )
                         )
                     )
    diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/DefaultDependencyManagementServices.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/DefaultDependencyManagementServices.java
    index d300a3029dded..517de9331d4b1 100644
    --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/DefaultDependencyManagementServices.java
    +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/DefaultDependencyManagementServices.java
    @@ -113,6 +113,7 @@
     import org.gradle.internal.execution.history.ExecutionHistoryStore;
     import org.gradle.internal.execution.history.changes.ExecutionStateChangeDetector;
     import org.gradle.internal.execution.impl.DefaultWorkExecutor;
    +import org.gradle.internal.execution.steps.BroadcastChangingOutputsStep;
     import org.gradle.internal.execution.steps.CatchExceptionStep;
     import org.gradle.internal.execution.steps.CreateOutputsStep;
     import org.gradle.internal.execution.steps.ExecuteStep;
    @@ -212,7 +213,9 @@ WorkExecutor createWorkExecutor(
                                         new CreateOutputsStep<>(
                                             new CatchExceptionStep<>(
                                                 new TimeoutStep<>(timeoutHandler,
    -                                                new ExecuteStep(outputChangeListener)
    +                                                new BroadcastChangingOutputsStep<>(outputChangeListener,
    +                                                    new ExecuteStep<>()
    +                                                )
                                                 )
                                             )
                                         )
    diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/BroadcastChangingOutputsStep.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/BroadcastChangingOutputsStep.java
    new file mode 100644
    index 0000000000000..348ae64bb0bde
    --- /dev/null
    +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/BroadcastChangingOutputsStep.java
    @@ -0,0 +1,51 @@
    +/*
    + * Copyright 2018 the original author or authors.
    + *
    + * Licensed under the Apache License, Version 2.0 (the "License");
    + * you may not use this file except in compliance with the License.
    + * You may obtain a copy of the License at
    + *
    + *      http://www.apache.org/licenses/LICENSE-2.0
    + *
    + * Unless required by applicable law or agreed to in writing, software
    + * distributed under the License is distributed on an "AS IS" BASIS,
    + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    + * See the License for the specific language governing permissions and
    + * limitations under the License.
    + */
    +
    +package org.gradle.internal.execution.steps;
    +
    +import org.gradle.internal.execution.Context;
    +import org.gradle.internal.execution.OutputChangeListener;
    +import org.gradle.internal.execution.Result;
    +import org.gradle.internal.execution.Step;
    +import org.gradle.internal.execution.UnitOfWork;
    +
    +import java.util.Optional;
    +
    +public class BroadcastChangingOutputsStep implements Step {
    +
    +    private final OutputChangeListener outputChangeListener;
    +    private final Step delegate;
    +
    +    public BroadcastChangingOutputsStep(
    +        OutputChangeListener outputChangeListener,
    +        Step delegate
    +    ) {
    +        this.outputChangeListener = outputChangeListener;
    +        this.delegate = delegate;
    +    }
    +
    +    @Override
    +    public Result execute(C context) {
    +        UnitOfWork work = context.getWork();
    +
    +        Optional> changingOutputs = work.getChangingOutputs();
    +        changingOutputs.ifPresent(outputs -> outputChangeListener.beforeOutputChange(outputs));
    +        if (!changingOutputs.isPresent()) {
    +            outputChangeListener.beforeOutputChange();
    +        }
    +        return delegate.execute(context);
    +    }
    +}
    diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/CatchExceptionStep.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/CatchExceptionStep.java
    index d218491c83299..5f71c8c3eae47 100644
    --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/CatchExceptionStep.java
    +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/CatchExceptionStep.java
    @@ -24,7 +24,7 @@
     import org.gradle.internal.execution.Step;
     
     public class CatchExceptionStep implements Step {
    -    private final Step delegate;
    +    private final Step delegate;
     
         public CatchExceptionStep(Step delegate) {
             this.delegate = delegate;
    diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/ExecuteStep.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/ExecuteStep.java
    index a28c5573c9f42..f9bfe368716b9 100644
    --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/ExecuteStep.java
    +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/ExecuteStep.java
    @@ -19,33 +19,13 @@
     import org.gradle.internal.Try;
     import org.gradle.internal.execution.ExecutionOutcome;
     import org.gradle.internal.execution.IncrementalChangesContext;
    -import org.gradle.internal.execution.OutputChangeListener;
     import org.gradle.internal.execution.Result;
     import org.gradle.internal.execution.Step;
    -import org.gradle.internal.execution.UnitOfWork;
    -
    -import java.util.Optional;
    -
    -public class ExecuteStep implements Step {
    -
    -    private final OutputChangeListener outputChangeListener;
    -
    -    public ExecuteStep(
    -        OutputChangeListener outputChangeListener
    -    ) {
    -        this.outputChangeListener = outputChangeListener;
    -    }
     
    +public class ExecuteStep implements Step {
         @Override
    -    public Result execute(IncrementalChangesContext context) {
    -        UnitOfWork work = context.getWork();
    -
    -        Optional> changingOutputs = work.getChangingOutputs();
    -        changingOutputs.ifPresent(outputs -> outputChangeListener.beforeOutputChange(outputs));
    -        if (!changingOutputs.isPresent()) {
    -            outputChangeListener.beforeOutputChange();
    -        }
    -        ExecutionOutcome outcome = work.execute(context);
    +    public Result execute(C context) {
    +        ExecutionOutcome outcome = context.getWork().execute(context);
             return new Result() {
                 @Override
                 public Try getOutcome() {
    diff --git a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/BroadcastChangingOutputsStepTest.groovy b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/BroadcastChangingOutputsStepTest.groovy
    new file mode 100644
    index 0000000000000..470151b317fb8
    --- /dev/null
    +++ b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/BroadcastChangingOutputsStepTest.groovy
    @@ -0,0 +1,66 @@
    +/*
    + * Copyright 2019 the original author or authors.
    + *
    + * Licensed under the Apache License, Version 2.0 (the "License");
    + * you may not use this file except in compliance with the License.
    + * You may obtain a copy of the License at
    + *
    + *      http://www.apache.org/licenses/LICENSE-2.0
    + *
    + * Unless required by applicable law or agreed to in writing, software
    + * distributed under the License is distributed on an "AS IS" BASIS,
    + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    + * See the License for the specific language governing permissions and
    + * limitations under the License.
    + */
    +
    +package org.gradle.internal.execution.steps
    +
    +import org.gradle.internal.execution.Context
    +import org.gradle.internal.execution.OutputChangeListener
    +import org.gradle.internal.execution.Result
    +
    +class BroadcastChangingOutputsStepTest extends StepSpec {
    +    def outputChangeListener = Mock(OutputChangeListener)
    +    def step = new BroadcastChangingOutputsStep(outputChangeListener, delegate)
    +    def context = Mock(Context)
    +    def delegateResult = Mock(Result)
    +
    +    def "notifies listener about all outputs changing"() {
    +        when:
    +        def result = step.execute(context)
    +
    +        then:
    +        result == delegateResult
    +
    +        1 * context.work >> work
    +        1 * work.changingOutputs >> Optional.empty()
    +
    +        then:
    +        1 * outputChangeListener.beforeOutputChange()
    +
    +        then:
    +        1 * delegate.execute(context) >> delegateResult
    +        0 * _
    +    }
    +
    +    def "notifies listener about specific outputs changing"() {
    +        def changingOutputs = ["output.txt"]
    +
    +        when:
    +        def result = step.execute(context)
    +
    +        then:
    +        result == delegateResult
    +
    +        1 * context.work >> work
    +        1 * work.changingOutputs >> Optional.of(changingOutputs)
    +
    +        then:
    +        1 * outputChangeListener.beforeOutputChange(changingOutputs)
    +
    +        then:
    +        1 * delegate.execute(context) >> delegateResult
    +        0 * _
    +    }
    +}
    diff --git a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/CatchExceptionStepTest.groovy b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/CatchExceptionStepTest.groovy
    new file mode 100644
    index 0000000000000..632f67976d0cd
    --- /dev/null
    +++ b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/CatchExceptionStepTest.groovy
    @@ -0,0 +1,59 @@
    +/*
    + * Copyright 2019 the original author or authors.
    + *
    + * Licensed under the Apache License, Version 2.0 (the "License");
    + * you may not use this file except in compliance with the License.
    + * You may obtain a copy of the License at
    + *
    + *      http://www.apache.org/licenses/LICENSE-2.0
    + *
    + * Unless required by applicable law or agreed to in writing, software
    + * distributed under the License is distributed on an "AS IS" BASIS,
    + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    + * See the License for the specific language governing permissions and
    + * limitations under the License.
    + */
    +
    +package org.gradle.internal.execution.steps
    +
    +import org.gradle.internal.execution.Context
    +import org.gradle.internal.execution.ExecutionException
    +import org.gradle.internal.execution.IncrementalChangesContext
    +import org.gradle.internal.execution.Result
    +import spock.lang.Unroll
    +
    +class CatchExceptionStepTest extends StepSpec {
    +    def step = new CatchExceptionStep(delegate)
    +    def context = Mock(IncrementalChangesContext)
    +
    +    def "successful result is preserved"() {
    +        def delegateResult = Mock(Result)
    +
    +        when:
    +        def result = step.execute(context)
    +
    +        then:
    +        result == delegateResult
    +
    +        1 * delegate.execute(context) >> delegateResult
    +        0 * _
    +    }
    +
    +    @Unroll
    +    def "failure #failure.class.simpleName is caught"() {
    +        when:
    +        def result = step.execute(context)
    +
    +        then:
    +        result.outcome.failure.get() instanceof ExecutionException
    +        result.outcome.failure.get().cause == failure
    +
    +        1 * delegate.execute(context) >> { throw failure }
    +        1 * context.work >> work
    +        1 * work.displayName >> "Failing work"
    +        0 * _
    +
    +        where:
    +        failure << [new RuntimeException(), new Error()]
    +    }
    +}
    diff --git a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/ExecuteStepTest.groovy b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/ExecuteStepTest.groovy
    new file mode 100644
    index 0000000000000..d20f3ea0debb1
    --- /dev/null
    +++ b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/ExecuteStepTest.groovy
    @@ -0,0 +1,60 @@
    +/*
    + * Copyright 2019 the original author or authors.
    + *
    + * Licensed under the Apache License, Version 2.0 (the "License");
    + * you may not use this file except in compliance with the License.
    + * You may obtain a copy of the License at
    + *
    + *      http://www.apache.org/licenses/LICENSE-2.0
    + *
    + * Unless required by applicable law or agreed to in writing, software
    + * distributed under the License is distributed on an "AS IS" BASIS,
    + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    + * See the License for the specific language governing permissions and
    + * limitations under the License.
    + */
    +
    +package org.gradle.internal.execution.steps
    +
    +import org.gradle.internal.execution.ExecutionOutcome
    +import org.gradle.internal.execution.IncrementalChangesContext
    +import org.gradle.internal.execution.UnitOfWork
    +import spock.lang.Specification
    +import spock.lang.Unroll
    +
    +class ExecuteStepTest extends Specification {
    +    def step = new ExecuteStep()
    +    def context = Mock(IncrementalChangesContext)
    +    def work = Mock(UnitOfWork)
    +
    +    @Unroll
    +    def "#outcome outcome is preserved"() {
    +        when:
    +        def result = step.execute(context)
    +
    +        then:
    +        result.outcome.get() == outcome
    +
    +        1 * context.work >> work
    +        1 * work.execute(context) >> { outcome }
    +
    +        where:
    +        outcome << ExecutionOutcome.values()
    +    }
    +
    +    @Unroll
    +    def "failure #failure.class.simpleName is not caught"() {
    +        when:
    +        def result = step.execute(context)
    +
    +        then:
    +        def ex = thrown Throwable
    +        ex == failure
    +
    +        1 * context.work >> work
    +        1 * work.execute(context) >> { throw failure }
    +
    +        where:
    +        failure << [new RuntimeException(), new Error()]
    +    }
    +}
    diff --git a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/ExecutionTest.groovy b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/ExecutionTest.groovy
    index 100c7c8f10bc6..959ff66eeb1f2 100644
    --- a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/ExecutionTest.groovy
    +++ b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/ExecutionTest.groovy
    @@ -41,7 +41,9 @@ class ExecutionTest extends Specification {
         def cancellationToken = new DefaultBuildCancellationToken()
         def executionStep = new CatchExceptionStep(
             new CancelExecutionStep(cancellationToken,
    -            new ExecuteStep(outputChangeListener)
    +            new BroadcastChangingOutputsStep(outputChangeListener,
    +                new ExecuteStep()
    +            )
             )
         )
     
    diff --git a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/IncrementalExecutionTest.groovy b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/IncrementalExecutionTest.groovy
    index 2b77209092ad3..e0d0a266581b0 100644
    --- a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/IncrementalExecutionTest.groovy
    +++ b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/IncrementalExecutionTest.groovy
    @@ -119,7 +119,7 @@ class IncrementalExecutionTest extends Specification {
                 new SkipUpToDateStep(
                     new StoreSnapshotsStep(
                         new SnapshotOutputStep(buildInvocationScopeId.getId(),
    -                        new ExecuteStep(outputChangeListener)
    +                        new BroadcastChangingOutputsStep(outputChangeListener, delegate)
                         )
                     )
                 )
    
    From 307fd7418fcc5946af6398b3c9e625c6b9fa9633 Mon Sep 17 00:00:00 2001
    From: =?UTF-8?q?L=C3=B3r=C3=A1nt=20Pint=C3=A9r?= 
    Date: Fri, 8 Mar 2019 14:16:14 +0100
    Subject: [PATCH 415/853] Add test for build cancellation
    
    ---
     .../execution/steps/CancelExecutionStep.java  |  5 +-
     .../steps/CancelExecutionStepTest.groovy      | 59 +++++++++++++++++++
     2 files changed, 63 insertions(+), 1 deletion(-)
     create mode 100644 subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/CancelExecutionStepTest.groovy
    
    diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/CancelExecutionStep.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/CancelExecutionStep.java
    index a5b94be40ac34..46599b3df9d41 100644
    --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/CancelExecutionStep.java
    +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/CancelExecutionStep.java
    @@ -26,7 +26,10 @@ public class CancelExecutionStep implements Step {
         private final BuildCancellationToken cancellationToken;
         private final Step delegate;
     
    -    public CancelExecutionStep(BuildCancellationToken cancellationToken, Step delegate) {
    +    public CancelExecutionStep(
    +        BuildCancellationToken cancellationToken,
    +        Step delegate
    +    ) {
             this.cancellationToken = cancellationToken;
             this.delegate = delegate;
         }
    diff --git a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/CancelExecutionStepTest.groovy b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/CancelExecutionStepTest.groovy
    new file mode 100644
    index 0000000000000..ee9f190984736
    --- /dev/null
    +++ b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/CancelExecutionStepTest.groovy
    @@ -0,0 +1,59 @@
    +/*
    + * Copyright 2019 the original author or authors.
    + *
    + * Licensed under the Apache License, Version 2.0 (the "License");
    + * you may not use this file except in compliance with the License.
    + * You may obtain a copy of the License at
    + *
    + *      http://www.apache.org/licenses/LICENSE-2.0
    + *
    + * Unless required by applicable law or agreed to in writing, software
    + * distributed under the License is distributed on an "AS IS" BASIS,
    + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    + * See the License for the specific language governing permissions and
    + * limitations under the License.
    + */
    +
    +package org.gradle.internal.execution.steps
    +
    +import org.gradle.api.BuildCancelledException
    +import org.gradle.initialization.BuildCancellationToken
    +import org.gradle.internal.execution.Context
    +import org.gradle.internal.execution.Result
    +
    +class CancelExecutionStepTest extends StepSpec {
    +    def cancellationToken = Mock(BuildCancellationToken)
    +    def step = new CancelExecutionStep(cancellationToken, delegate)
    +    def context = Mock(Context)
    +    def delegateResult = Mock(Result)
    +
    +    def "executes normally when cancellation is not requested"() {
    +        when:
    +        def result = step.execute(context)
    +
    +        then:
    +        result == delegateResult
    +
    +        1 * delegate.execute(context) >> delegateResult
    +
    +        then:
    +        1 * cancellationToken.cancellationRequested >> false
    +        0 *_
    +    }
    +
    +    def "cancels execution when cancellation is requested"() {
    +        when:
    +        step.execute(context)
    +
    +        then:
    +        thrown BuildCancelledException
    +
    +        1 * delegate.execute(context) >> delegateResult
    +
    +        then:
    +        1 * cancellationToken.cancellationRequested >> true
    +        1 * context.work >> work
    +        1 * work.displayName >> "cancelled work"
    +        0 *_
    +    }
    +}
    
    From a60e7a0dfbb90d2c7700b930969fd764206e35f2 Mon Sep 17 00:00:00 2001
    From: =?UTF-8?q?L=C3=B3r=C3=A1nt=20Pint=C3=A9r?= 
    Date: Fri, 8 Mar 2019 14:32:29 +0100
    Subject: [PATCH 416/853] Check that execution results are retained
    
    ---
     .../steps/SkipUpToDateStepTest.groovy         | 39 ++++++++++++++++++-
     1 file changed, 38 insertions(+), 1 deletion(-)
    
    diff --git a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/SkipUpToDateStepTest.groovy b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/SkipUpToDateStepTest.groovy
    index 6623682563a72..a10a9abdab77e 100644
    --- a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/SkipUpToDateStepTest.groovy
    +++ b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/SkipUpToDateStepTest.groovy
    @@ -16,11 +16,16 @@
     
     package org.gradle.internal.execution.steps
     
    +import com.google.common.collect.ImmutableSortedMap
    +import org.gradle.caching.internal.origin.OriginMetadata
    +import org.gradle.internal.Try
     import org.gradle.internal.change.ChangeVisitor
     import org.gradle.internal.change.DescriptiveChange
     import org.gradle.internal.execution.ExecutionOutcome
     import org.gradle.internal.execution.IncrementalChangesContext
    +import org.gradle.internal.execution.SnapshotResult
     import org.gradle.internal.execution.history.changes.ExecutionStateChanges
    +import org.gradle.internal.fingerprint.impl.EmptyCurrentFileCollectionFingerprint
     
     class SkipUpToDateStepTest extends StepSpec {
         def step = new SkipUpToDateStep(delegate)
    @@ -42,6 +47,11 @@ class SkipUpToDateStepTest extends StepSpec {
         }
     
         def "executes when outputs are not up to date"() {
    +        def delegateResult = Mock(SnapshotResult)
    +        def delegateOutcome = Try.successful(ExecutionOutcome.EXECUTED)
    +        def delegateOriginMetadata = Mock(OriginMetadata)
    +        def delegateFinalOutputs = ImmutableSortedMap.copyOf([test: EmptyCurrentFileCollectionFingerprint.EMPTY])
    +
             when:
             def result = step.execute(context)
     
    @@ -53,7 +63,34 @@ class SkipUpToDateStepTest extends StepSpec {
             1 * changes.visitAllChanges(_) >> { ChangeVisitor visitor ->
                 visitor.visitChange(new DescriptiveChange("change"))
             }
    -        1 * delegate.execute(context)
    +        1 * delegate.execute(context) >> delegateResult
    +        0 * _
    +
    +        when:
    +        def outcome = result.outcome
    +
    +        then:
    +        outcome == delegateOutcome
    +
    +        1 * delegateResult.outcome >> delegateOutcome
    +        0 * _
    +
    +        when:
    +        def originMetadata = result.originMetadata
    +
    +        then:
    +        originMetadata == delegateOriginMetadata
    +
    +        1 * delegateResult.originMetadata >> delegateOriginMetadata
    +        0 * _
    +
    +        when:
    +        def finalOutputs = result.finalOutputs
    +
    +        then:
    +        finalOutputs == delegateFinalOutputs
    +
    +        1 * delegateResult.finalOutputs >> delegateFinalOutputs
             0 * _
         }
     
    
    From f1cfb37e026a07e06c025204502c2e5b43889e8a Mon Sep 17 00:00:00 2001
    From: =?UTF-8?q?L=C3=B3r=C3=A1nt=20Pint=C3=A9r?= 
    Date: Fri, 8 Mar 2019 14:34:36 +0100
    Subject: [PATCH 417/853] Code cleanup NO_REUSED_OUTPUTS -> WITHOUT_OUTPUTS
    
    ---
     .../org/gradle/api/internal/tasks/TaskExecuterResult.java | 2 +-
     .../tasks/execution/CatchExceptionTaskExecuter.java       | 2 +-
     .../internal/tasks/execution/EventFiringTaskExecuter.java | 2 +-
     .../tasks/execution/SkipEmptySourceFilesTaskExecuter.java | 2 +-
     .../internal/tasks/execution/SkipOnlyIfTaskExecuter.java  | 4 ++--
     .../tasks/execution/SkipTaskWithNoActionsExecuter.java    | 2 +-
     .../internal/tasks/execution/ValidatingTaskExecuter.java  | 2 +-
     .../tasks/execution/CatchExceptionTaskExecuterTest.groovy | 2 +-
     .../tasks/execution/EventFiringTaskExecuterTest.groovy    | 8 ++++----
     .../ResolveBeforeExecutionOutputsTaskExecuterTest.groovy  | 4 ++--
     .../execution/ResolveBuildCacheKeyExecuterTest.groovy     | 4 ++--
     .../execution/ResolveTaskExecutionModeExecuterTest.groovy | 2 +-
     .../ResolveTaskOutputCachingStateExecuterTest.groovy      | 2 +-
     .../tasks/execution/SkipCachedTaskExecuterTest.groovy     | 8 ++++----
     .../execution/SkipEmptySourceFilesTaskExecuterTest.groovy | 4 ++--
     .../tasks/execution/SkipOnlyIfTaskExecuterTest.groovy     | 2 +-
     .../tasks/execution/ValidatingTaskExecuterTest.groovy     | 2 +-
     17 files changed, 27 insertions(+), 27 deletions(-)
    
    diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/TaskExecuterResult.java b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/TaskExecuterResult.java
    index 73c493e97211f..346fc7413c2ed 100644
    --- a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/TaskExecuterResult.java
    +++ b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/TaskExecuterResult.java
    @@ -38,7 +38,7 @@ public interface TaskExecuterResult {
          */
         Optional getReusedOutputOriginMetadata();
     
    -    TaskExecuterResult NO_REUSED_OUTPUT = new TaskExecuterResult() {
    +    TaskExecuterResult WITHOUT_OUTPUTS = new TaskExecuterResult() {
             @Override
             public List getExecutionReasons() {
                 return ImmutableList.of();
    diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/CatchExceptionTaskExecuter.java b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/CatchExceptionTaskExecuter.java
    index 03adf2cf04fce..a85bf2f6b7ee4 100644
    --- a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/CatchExceptionTaskExecuter.java
    +++ b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/CatchExceptionTaskExecuter.java
    @@ -36,7 +36,7 @@ public TaskExecuterResult execute(TaskInternal task, TaskStateInternal state, Ta
                 return delegate.execute(task, state, context);
             } catch (RuntimeException e) {
                 state.setOutcome(new TaskExecutionException(task, e));
    -            return TaskExecuterResult.NO_REUSED_OUTPUT;
    +            return TaskExecuterResult.WITHOUT_OUTPUTS;
             }
         }
     }
    diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/EventFiringTaskExecuter.java b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/EventFiringTaskExecuter.java
    index fa0304cb24ee7..e3928998c8d0c 100644
    --- a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/EventFiringTaskExecuter.java
    +++ b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/EventFiringTaskExecuter.java
    @@ -57,7 +57,7 @@ private TaskExecuterResult executeTask(BuildOperationContext operationContext) {
                         taskExecutionListener.beforeExecute(task);
                     } catch (Throwable t) {
                         state.setOutcome(new TaskExecutionException(task, t));
    -                    return TaskExecuterResult.NO_REUSED_OUTPUT;
    +                    return TaskExecuterResult.WITHOUT_OUTPUTS;
                     }
     
                     TaskExecuterResult result = delegate.execute(task, state, context);
    diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/SkipEmptySourceFilesTaskExecuter.java b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/SkipEmptySourceFilesTaskExecuter.java
    index 33112d126c6c8..a159525d06fd5 100644
    --- a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/SkipEmptySourceFilesTaskExecuter.java
    +++ b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/SkipEmptySourceFilesTaskExecuter.java
    @@ -103,7 +103,7 @@ public TaskExecuterResult execute(TaskInternal task, TaskStateInternal state, fi
                 }
                 taskInputsListener.onExecute(task, Cast.cast(FileCollectionInternal.class, sourceFiles));
                 executionHistoryStore.remove(task.getPath());
    -            return TaskExecuterResult.NO_REUSED_OUTPUT;
    +            return TaskExecuterResult.WITHOUT_OUTPUTS;
             } else {
                 taskInputsListener.onExecute(task, Cast.cast(FileCollectionInternal.class, properties.getInputFiles()));
             }
    diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/SkipOnlyIfTaskExecuter.java b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/SkipOnlyIfTaskExecuter.java
    index 9023aa74fb760..63c7a4e352890 100644
    --- a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/SkipOnlyIfTaskExecuter.java
    +++ b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/SkipOnlyIfTaskExecuter.java
    @@ -44,13 +44,13 @@ public TaskExecuterResult execute(TaskInternal task, TaskStateInternal state, Ta
                 skip = !task.getOnlyIf().isSatisfiedBy(task);
             } catch (Throwable t) {
                 state.setOutcome(new GradleException(String.format("Could not evaluate onlyIf predicate for %s.", task), t));
    -            return TaskExecuterResult.NO_REUSED_OUTPUT;
    +            return TaskExecuterResult.WITHOUT_OUTPUTS;
             }
     
             if (skip) {
                 LOGGER.info("Skipping {} as task onlyIf is false.", task);
                 state.setOutcome(TaskExecutionOutcome.SKIPPED);
    -            return TaskExecuterResult.NO_REUSED_OUTPUT;
    +            return TaskExecuterResult.WITHOUT_OUTPUTS;
             }
     
             return executer.execute(task, state, context);
    diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/SkipTaskWithNoActionsExecuter.java b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/SkipTaskWithNoActionsExecuter.java
    index 147e9f02e83d5..9042547349061 100644
    --- a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/SkipTaskWithNoActionsExecuter.java
    +++ b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/SkipTaskWithNoActionsExecuter.java
    @@ -52,7 +52,7 @@ public TaskExecuterResult execute(TaskInternal task, TaskStateInternal state, Ta
                 }
                 state.setActionable(false);
                 state.setOutcome(upToDate ? TaskExecutionOutcome.UP_TO_DATE : TaskExecutionOutcome.EXECUTED);
    -            return TaskExecuterResult.NO_REUSED_OUTPUT;
    +            return TaskExecuterResult.WITHOUT_OUTPUTS;
             }
             return executer.execute(task, state, context);
         }
    diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/ValidatingTaskExecuter.java b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/ValidatingTaskExecuter.java
    index 30784fa2efe67..48d4017bdfd49 100644
    --- a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/ValidatingTaskExecuter.java
    +++ b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/ValidatingTaskExecuter.java
    @@ -52,7 +52,7 @@ public TaskExecuterResult execute(TaskInternal task, TaskStateInternal state, Ta
             if (!messages.isEmpty()) {
                 List firstMessages = messages.subList(0, Math.min(5, messages.size()));
                 report(task, firstMessages, state);
    -            return TaskExecuterResult.NO_REUSED_OUTPUT;
    +            return TaskExecuterResult.WITHOUT_OUTPUTS;
             }
     
             return executer.execute(task, state, context);
    diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/execution/CatchExceptionTaskExecuterTest.groovy b/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/execution/CatchExceptionTaskExecuterTest.groovy
    index fbd144208a5b3..e27c5f24d48a9 100644
    --- a/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/execution/CatchExceptionTaskExecuterTest.groovy
    +++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/execution/CatchExceptionTaskExecuterTest.groovy
    @@ -39,7 +39,7 @@ class CatchExceptionTaskExecuterTest extends Specification {
             then:
             1 * delegate.execute(task, state, context) >> {
                 state.setOutcome(TaskExecutionOutcome.EXECUTED)
    -            return TaskExecuterResult.NO_REUSED_OUTPUT
    +            return TaskExecuterResult.WITHOUT_OUTPUTS
             }
             0 * _
             state.outcome == TaskExecutionOutcome.EXECUTED
    diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/execution/EventFiringTaskExecuterTest.groovy b/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/execution/EventFiringTaskExecuterTest.groovy
    index cdc38955d57a3..976408a7538d4 100644
    --- a/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/execution/EventFiringTaskExecuterTest.groovy
    +++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/execution/EventFiringTaskExecuterTest.groovy
    @@ -48,7 +48,7 @@ class EventFiringTaskExecuterTest extends Specification {
             1 * taskExecutionListener.beforeExecute(task)
     
             then:
    -        1 * delegate.execute(task, state, executionContext) >> TaskExecuterResult.NO_REUSED_OUTPUT
    +        1 * delegate.execute(task, state, executionContext) >> TaskExecuterResult.WITHOUT_OUTPUTS
     
             then:
             1 * taskExecutionListener.afterExecute(task, state)
    @@ -95,7 +95,7 @@ class EventFiringTaskExecuterTest extends Specification {
             then:
             1 * delegate.execute(task, state, executionContext) >> {
                 state.setOutcome(failure)
    -            return TaskExecuterResult.NO_REUSED_OUTPUT
    +            return TaskExecuterResult.WITHOUT_OUTPUTS
             }
     
             then:
    @@ -121,7 +121,7 @@ class EventFiringTaskExecuterTest extends Specification {
             1 * taskExecutionListener.beforeExecute(task)
     
             then:
    -        1 * delegate.execute(task, state, executionContext) >> TaskExecuterResult.NO_REUSED_OUTPUT
    +        1 * delegate.execute(task, state, executionContext) >> TaskExecuterResult.WITHOUT_OUTPUTS
     
             then:
             1 * taskExecutionListener.afterExecute(task, state) >> {
    @@ -152,7 +152,7 @@ class EventFiringTaskExecuterTest extends Specification {
             then:
             1 * delegate.execute(task, state, executionContext) >> {
                 state.setOutcome(failure)
    -            return TaskExecuterResult.NO_REUSED_OUTPUT
    +            return TaskExecuterResult.WITHOUT_OUTPUTS
             }
     
             then:
    diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/execution/ResolveBeforeExecutionOutputsTaskExecuterTest.groovy b/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/execution/ResolveBeforeExecutionOutputsTaskExecuterTest.groovy
    index 9482034012442..8cce5cfde7d00 100644
    --- a/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/execution/ResolveBeforeExecutionOutputsTaskExecuterTest.groovy
    +++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/execution/ResolveBeforeExecutionOutputsTaskExecuterTest.groovy
    @@ -66,7 +66,7 @@ class ResolveBeforeExecutionOutputsTaskExecuterTest extends Specification {
     
             then:
             1 * context.setOutputFilesBeforeExecution(outputFilesBeforeExecution)
    -        1 * delegate.execute(task, state, context) >> TaskExecuterResult.NO_REUSED_OUTPUT
    +        1 * delegate.execute(task, state, context) >> TaskExecuterResult.WITHOUT_OUTPUTS
             0 * context.setOverlappingOutputs(_ as OverlappingOutputs)
         }
     
    @@ -90,6 +90,6 @@ class ResolveBeforeExecutionOutputsTaskExecuterTest extends Specification {
     
             then:
             1 * context.setOutputFilesBeforeExecution(outputFilesBeforeExecution)
    -        1 * delegate.execute(task, state, context) >> TaskExecuterResult.NO_REUSED_OUTPUT
    +        1 * delegate.execute(task, state, context) >> TaskExecuterResult.WITHOUT_OUTPUTS
         }
     }
    diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/execution/ResolveBuildCacheKeyExecuterTest.groovy b/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/execution/ResolveBuildCacheKeyExecuterTest.groovy
    index 3f86bcf7ccad9..fc588a3a0247d 100644
    --- a/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/execution/ResolveBuildCacheKeyExecuterTest.groovy
    +++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/execution/ResolveBuildCacheKeyExecuterTest.groovy
    @@ -64,7 +64,7 @@ class ResolveBuildCacheKeyExecuterTest extends Specification {
             1 * taskContext.setBuildCacheKey(cacheKey)
     
             then:
    -        1 * delegate.execute(task, taskState, taskContext) >> TaskExecuterResult.NO_REUSED_OUTPUT
    +        1 * delegate.execute(task, taskState, taskContext) >> TaskExecuterResult.WITHOUT_OUTPUTS
             0 * _
         }
     
    @@ -99,7 +99,7 @@ class ResolveBuildCacheKeyExecuterTest extends Specification {
             1 * taskContext.setBuildCacheKey({ TaskOutputCachingBuildCacheKey key -> !key.valid } as TaskOutputCachingBuildCacheKey)
     
             then:
    -        1 * delegate.execute(task, taskState, taskContext) >> TaskExecuterResult.NO_REUSED_OUTPUT
    +        1 * delegate.execute(task, taskState, taskContext) >> TaskExecuterResult.WITHOUT_OUTPUTS
             0 * _
         }
     
    diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/execution/ResolveTaskExecutionModeExecuterTest.groovy b/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/execution/ResolveTaskExecutionModeExecuterTest.groovy
    index 27eae191a07ba..7b2fd82601ca9 100644
    --- a/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/execution/ResolveTaskExecutionModeExecuterTest.groovy
    +++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/execution/ResolveTaskExecutionModeExecuterTest.groovy
    @@ -74,7 +74,7 @@ class ResolveTaskExecutionModeExecuterTest extends Specification {
             1 * outputs.visitRegisteredProperties(_)
     
             then: 'delegate is executed'
    -        1 * delegate.execute(task, taskState, taskContext) >> TaskExecuterResult.NO_REUSED_OUTPUT
    +        1 * delegate.execute(task, taskState, taskContext) >> TaskExecuterResult.WITHOUT_OUTPUTS
     
             then: 'task artifact state is removed from taskContext'
             1 * outputs.setPreviousOutputFiles(null)
    diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/execution/ResolveTaskOutputCachingStateExecuterTest.groovy b/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/execution/ResolveTaskOutputCachingStateExecuterTest.groovy
    index 9e31812ed5285..48b877141d389 100644
    --- a/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/execution/ResolveTaskOutputCachingStateExecuterTest.groovy
    +++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/execution/ResolveTaskOutputCachingStateExecuterTest.groovy
    @@ -279,7 +279,7 @@ class ResolveTaskOutputCachingStateExecuterTest extends Specification {
             1 * taskState.setTaskOutputCaching({ !it.enabled } as TaskOutputCachingState)
     
             then:
    -        1 * delegate.execute(task, taskState, taskContext) >> TaskExecuterResult.NO_REUSED_OUTPUT
    +        1 * delegate.execute(task, taskState, taskContext) >> TaskExecuterResult.WITHOUT_OUTPUTS
             0 * _
         }
     
    diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/execution/SkipCachedTaskExecuterTest.groovy b/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/execution/SkipCachedTaskExecuterTest.groovy
    index 4920f96cccbca..7540f97fcbc8a 100644
    --- a/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/execution/SkipCachedTaskExecuterTest.groovy
    +++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/execution/SkipCachedTaskExecuterTest.groovy
    @@ -71,7 +71,7 @@ class SkipCachedTaskExecuterTest extends Specification {
             1 * taskExecutionMode.isAllowedToUseCachedResults() >> false
     
             then:
    -        1 * delegate.execute(task, taskState, taskContext) >> TaskExecuterResult.NO_REUSED_OUTPUT
    +        1 * delegate.execute(task, taskState, taskContext) >> TaskExecuterResult.WITHOUT_OUTPUTS
     
             then:
             1 * taskState.getFailure() >> null
    @@ -95,7 +95,7 @@ class SkipCachedTaskExecuterTest extends Specification {
             interaction { cachingDisabled() }
     
             then:
    -        1 * delegate.execute(task, taskState, taskContext) >> TaskExecuterResult.NO_REUSED_OUTPUT
    +        1 * delegate.execute(task, taskState, taskContext) >> TaskExecuterResult.WITHOUT_OUTPUTS
             0 * _
         }
     
    @@ -119,7 +119,7 @@ class SkipCachedTaskExecuterTest extends Specification {
             1 * buildCacheController.load(_) >> { throw new RuntimeException("unknown error") }
     
             then:
    -        1 * delegate.execute(task, taskState, taskContext) >> TaskExecuterResult.NO_REUSED_OUTPUT
    +        1 * delegate.execute(task, taskState, taskContext) >> TaskExecuterResult.WITHOUT_OUTPUTS
     
             then:
             1 * taskState.getFailure() >> null
    @@ -179,7 +179,7 @@ class SkipCachedTaskExecuterTest extends Specification {
             1 * buildCacheController.load(_)
     
             then:
    -        1 * delegate.execute(task, taskState, taskContext) >> TaskExecuterResult.NO_REUSED_OUTPUT
    +        1 * delegate.execute(task, taskState, taskContext) >> TaskExecuterResult.WITHOUT_OUTPUTS
     
             then:
             1 * taskState.getFailure() >> null
    diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/execution/SkipEmptySourceFilesTaskExecuterTest.groovy b/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/execution/SkipEmptySourceFilesTaskExecuterTest.groovy
    index 720cf7cf00327..5f08e9842e603 100644
    --- a/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/execution/SkipEmptySourceFilesTaskExecuterTest.groovy
    +++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/execution/SkipEmptySourceFilesTaskExecuterTest.groovy
    @@ -290,7 +290,7 @@ class SkipEmptySourceFilesTaskExecuterTest extends Specification {
     
             then:
             1 * taskProperties.getInputFiles() >> taskFiles
    -        1 * target.execute(task, state, taskContext) >> TaskExecuterResult.NO_REUSED_OUTPUT
    +        1 * target.execute(task, state, taskContext) >> TaskExecuterResult.WITHOUT_OUTPUTS
             1 * taskInputsListener.onExecute(task, taskFiles)
     
             then:
    @@ -308,7 +308,7 @@ class SkipEmptySourceFilesTaskExecuterTest extends Specification {
     
             then:
             1 * taskProperties.getInputFiles() >> taskFiles
    -        1 * target.execute(task, state, taskContext) >> TaskExecuterResult.NO_REUSED_OUTPUT
    +        1 * target.execute(task, state, taskContext) >> TaskExecuterResult.WITHOUT_OUTPUTS
             1 * taskInputsListener.onExecute(task, taskFiles)
     
             then:
    diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/execution/SkipOnlyIfTaskExecuterTest.groovy b/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/execution/SkipOnlyIfTaskExecuterTest.groovy
    index 6cf8aa493e0f7..f7e9e0540e0dd 100644
    --- a/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/execution/SkipOnlyIfTaskExecuterTest.groovy
    +++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/execution/SkipOnlyIfTaskExecuterTest.groovy
    @@ -64,7 +64,7 @@ class SkipOnlyIfTaskExecuterTest extends Specification {
     
             then:
             1 * spec.isSatisfiedBy(task) >> true
    -        1 * delegate.execute(task, state, executionContext) >> TaskExecuterResult.NO_REUSED_OUTPUT
    +        1 * delegate.execute(task, state, executionContext) >> TaskExecuterResult.WITHOUT_OUTPUTS
             noMoreInteractions()
         }
     
    diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/execution/ValidatingTaskExecuterTest.groovy b/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/execution/ValidatingTaskExecuterTest.groovy
    index fa42ccb955c54..cbc3a5c6b2ea0 100644
    --- a/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/execution/ValidatingTaskExecuterTest.groovy
    +++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/execution/ValidatingTaskExecuterTest.groovy
    @@ -48,7 +48,7 @@ class ValidatingTaskExecuterTest extends Specification {
             1 * task.getProject() >> project
             1 * executionContext.getTaskProperties() >> taskProperties
             1 * taskProperties.validate(_)
    -        1 * target.execute(task, state, executionContext) >> TaskExecuterResult.NO_REUSED_OUTPUT
    +        1 * target.execute(task, state, executionContext) >> TaskExecuterResult.WITHOUT_OUTPUTS
             0 * _
         }
     
    
    From b44cf898fb7f8d3f1a6261006eaa06d7ae94ccf4 Mon Sep 17 00:00:00 2001
    From: =?UTF-8?q?L=C3=B3r=C3=A1nt=20Pint=C3=A9r?= 
    Date: Fri, 8 Mar 2019 14:35:31 +0100
    Subject: [PATCH 418/853] Rename EXECUTED -> EXECUTED_NON_INCREMENTALLY
    
    ---
     .../internal/tasks/TaskExecutionOutcome.java  |  2 +-
     .../execution/ExecuteActionsTaskExecuter.java |  2 +-
     .../transform/DefaultTransformerInvoker.java  |  2 +-
     .../internal/execution/ExecutionOutcome.java  |  2 +-
     .../execution/steps/CacheStepTest.groovy      |  2 +-
     .../execution/steps/ExecutionTest.groovy      |  8 +++---
     .../steps/IncrementalExecutionTest.groovy     | 28 +++++++++----------
     .../steps/SkipUpToDateStepTest.groovy         |  2 +-
     .../steps/StoreSnapshotsStepTest.groovy       |  2 +-
     9 files changed, 25 insertions(+), 25 deletions(-)
    
    diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/TaskExecutionOutcome.java b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/TaskExecutionOutcome.java
    index 8113efad388e7..fb0a3de339bf8 100644
    --- a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/TaskExecutionOutcome.java
    +++ b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/TaskExecutionOutcome.java
    @@ -57,7 +57,7 @@ public static TaskExecutionOutcome valueOf(ExecutionOutcome outcome) {
                 case UP_TO_DATE:
                     return UP_TO_DATE;
                 case EXECUTED_INCREMENTALLY:
    -            case EXECUTED:
    +            case EXECUTED_NON_INCREMENTALLY:
                     return EXECUTED;
                 default:
                     throw new AssertionError();
    diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuter.java b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuter.java
    index 4037b96f95198..1b21776c1c37e 100644
    --- a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuter.java
    +++ b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuter.java
    @@ -203,7 +203,7 @@ public void accept(ExecutionStateChanges changes) {
                     return task.getState().getDidWork()
                         ? this.context.isTaskExecutedIncrementally()
                             ? ExecutionOutcome.EXECUTED_INCREMENTALLY
    -                        : ExecutionOutcome.EXECUTED
    +                        : ExecutionOutcome.EXECUTED_NON_INCREMENTALLY
                         : ExecutionOutcome.UP_TO_DATE;
                 } finally {
                     task.getState().setExecuting(false);
    diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvoker.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvoker.java
    index dbab073aafcc8..a525cf0e84712 100644
    --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvoker.java
    +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvoker.java
    @@ -266,7 +266,7 @@ public ExecutionOutcome execute(IncrementalChangesContext context) {
                 GFileUtils.deleteFileQuietly(resultsFile);
                 ImmutableList result = transformer.transform(inputArtifact, outputDir, dependencies);
                 writeResultsFile(outputDir, resultsFile, result);
    -            return ExecutionOutcome.EXECUTED;
    +            return ExecutionOutcome.EXECUTED_NON_INCREMENTALLY;
             }
     
             private void writeResultsFile(File outputDir, File resultsFile, ImmutableList result) {
    diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/ExecutionOutcome.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/ExecutionOutcome.java
    index f877c1d4b36f5..c8684c93bff83 100644
    --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/ExecutionOutcome.java
    +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/ExecutionOutcome.java
    @@ -37,5 +37,5 @@ public enum ExecutionOutcome {
         /**
          * The work has been executed with no incremental change information.
          */
    -    EXECUTED
    +    EXECUTED_NON_INCREMENTALLY
     }
    diff --git a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/CacheStepTest.groovy b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/CacheStepTest.groovy
    index ac878b472a026..6b88679e691a4 100644
    --- a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/CacheStepTest.groovy
    +++ b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/CacheStepTest.groovy
    @@ -69,7 +69,7 @@ class CacheStepTest extends StepSpec implements FingerprinterFixture {
             1 * context.cacheHandler >> cacheHandler
             1 * cacheHandler.load(_) >> Optional.empty()
             1 * delegate.execute(context) >> delegateResult
    -        1 * delegateResult.outcome >> Try.successful(ExecutionOutcome.EXECUTED)
    +        1 * delegateResult.outcome >> Try.successful(ExecutionOutcome.EXECUTED_NON_INCREMENTALLY)
             1 * cacheHandler.store(_)
             0 * _
         }
    diff --git a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/ExecutionTest.groovy b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/ExecutionTest.groovy
    index 959ff66eeb1f2..980756f175924 100644
    --- a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/ExecutionTest.groovy
    +++ b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/ExecutionTest.groovy
    @@ -60,7 +60,7 @@ class ExecutionTest extends Specification {
             0 * _
     
             where:
    -        outcome << [ExecutionOutcome.EXECUTED, ExecutionOutcome.EXECUTED_INCREMENTALLY]
    +        outcome << [ExecutionOutcome.EXECUTED_NON_INCREMENTALLY, ExecutionOutcome.EXECUTED_INCREMENTALLY]
         }
     
         def "reports no work done"() {
    @@ -98,20 +98,20 @@ class ExecutionTest extends Specification {
     
         def "invalidates only changing outputs"() {
             def changingOutputs = ['some/location']
    -        def unitOfWork = new TestUnitOfWork({ -> ExecutionOutcome.EXECUTED }, changingOutputs)
    +        def unitOfWork = new TestUnitOfWork({ -> ExecutionOutcome.EXECUTED_NON_INCREMENTALLY }, changingOutputs)
     
             when:
             def result = execute { -> unitOfWork }
     
             then:
    -        result.outcome.get() == ExecutionOutcome.EXECUTED
    +        result.outcome.get() == ExecutionOutcome.EXECUTED_NON_INCREMENTALLY
     
             1 * outputChangeListener.beforeOutputChange(changingOutputs)
             0 * _
         }
     
         def "fails the execution when build has been cancelled"() {
    -        def unitOfWork = new TestUnitOfWork({ -> ExecutionOutcome.EXECUTED })
    +        def unitOfWork = new TestUnitOfWork({ -> ExecutionOutcome.EXECUTED_NON_INCREMENTALLY })
     
             when:
             cancellationToken.cancel()
    diff --git a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/IncrementalExecutionTest.groovy b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/IncrementalExecutionTest.groovy
    index e0d0a266581b0..7036ca87132ca 100644
    --- a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/IncrementalExecutionTest.groovy
    +++ b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/IncrementalExecutionTest.groovy
    @@ -62,7 +62,7 @@ import org.junit.Rule
     import java.time.Duration
     import java.util.function.Supplier
     
    -import static org.gradle.internal.execution.ExecutionOutcome.EXECUTED
    +import static org.gradle.internal.execution.ExecutionOutcome.EXECUTED_NON_INCREMENTALLY
     import static org.gradle.internal.execution.ExecutionOutcome.UP_TO_DATE
     
     class IncrementalExecutionTest extends Specification {
    @@ -131,7 +131,7 @@ class IncrementalExecutionTest extends Specification {
             def result = execute(unitOfWork)
     
             then:
    -        result.outcome.get() == EXECUTED
    +        result.outcome.get() == EXECUTED_NON_INCREMENTALLY
             !result.reused
     
             result.finalOutputs.keySet() == ["dir", "emptyDir", "file", "missingDir", "missingFile"] as Set
    @@ -147,7 +147,7 @@ class IncrementalExecutionTest extends Specification {
             def result = execute(unitOfWork)
     
             then:
    -        result.outcome.get() == EXECUTED
    +        result.outcome.get() == EXECUTED_NON_INCREMENTALLY
             !result.reused
     
             def origin = result.originMetadata.buildInvocationId
    @@ -172,7 +172,7 @@ class IncrementalExecutionTest extends Specification {
             def result = execute(unitOfWork)
     
             then:
    -        result.outcome.get() == EXECUTED
    +        result.outcome.get() == EXECUTED_NON_INCREMENTALLY
             !result.reused
     
             def origin = result.originMetadata.buildInvocationId
    @@ -183,7 +183,7 @@ class IncrementalExecutionTest extends Specification {
             result = outOfDate(builder.build(), outputFilesChanged(file: [outputFile]))
     
             then:
    -        result.outcome.get() == EXECUTED
    +        result.outcome.get() == EXECUTED_NON_INCREMENTALLY
             !result.reused
             result.originMetadata.buildInvocationId == buildInvocationScopeId.id
             result.originMetadata.buildInvocationId != origin
    @@ -207,7 +207,7 @@ class IncrementalExecutionTest extends Specification {
             result = outOfDate(builder.build(), "Task has failed previously.")
     
             then:
    -        result.outcome.get() == EXECUTED
    +        result.outcome.get() == EXECUTED_NON_INCREMENTALLY
             !result.reused
             result.originMetadata.buildInvocationId == buildInvocationScopeId.id
             result.originMetadata.buildInvocationId != origin
    @@ -218,7 +218,7 @@ class IncrementalExecutionTest extends Specification {
             def result = execute(unitOfWork)
     
             then:
    -        result.outcome.get() == EXECUTED
    +        result.outcome.get() == EXECUTED_NON_INCREMENTALLY
             !result.reused
             result.executionReasons == ["No history is available."]
         }
    @@ -232,7 +232,7 @@ class IncrementalExecutionTest extends Specification {
             def result = execute(unitOfWork)
     
             then:
    -        result.outcome.get() == EXECUTED
    +        result.outcome.get() == EXECUTED_NON_INCREMENTALLY
             !result.reused
             result.executionReasons == ["Output property 'file' file ${outputFile.absolutePath} has been removed."]
         }
    @@ -246,7 +246,7 @@ class IncrementalExecutionTest extends Specification {
             def result = execute(unitOfWork)
     
             then:
    -        result.outcome.get() == EXECUTED
    +        result.outcome.get() == EXECUTED_NON_INCREMENTALLY
             !result.reused
             result.executionReasons == ["Output property 'dir' file ${outputDirFile.absolutePath} has been removed."]
         }
    @@ -289,7 +289,7 @@ class IncrementalExecutionTest extends Specification {
             outputFile << "new content"
             def result = execute(unitOfWork)
             then:
    -        result.outcome.get() == EXECUTED
    +        result.outcome.get() == EXECUTED_NON_INCREMENTALLY
             !result.reused
             result.executionReasons == ["Output property 'file' file ${outputFile.absolutePath} has changed."]
         }
    @@ -302,7 +302,7 @@ class IncrementalExecutionTest extends Specification {
             outputDirFile << "new content"
             def result = execute(unitOfWork)
             then:
    -        result.outcome.get() == EXECUTED
    +        result.outcome.get() == EXECUTED_NON_INCREMENTALLY
             !result.reused
             result.executionReasons == ["Output property 'dir' file ${outputDirFile.absolutePath} has changed."]
         }
    @@ -326,7 +326,7 @@ class IncrementalExecutionTest extends Specification {
             def result = execute(outputFilesRemovedUnitOfWork)
     
             then:
    -        result.outcome.get() == EXECUTED
    +        result.outcome.get() == EXECUTED_NON_INCREMENTALLY
             !result.reused
             result.executionReasons == ["Output property 'file' has been removed for ${outputFilesRemovedUnitOfWork.displayName}"]
         }
    @@ -578,7 +578,7 @@ class IncrementalExecutionTest extends Specification {
     
         UpToDateResult outOfDate(UnitOfWork unitOfWork, List expectedReasons) {
             def result = execute(unitOfWork)
    -        assert result.outcome.get() == EXECUTED
    +        assert result.outcome.get() == EXECUTED_NON_INCREMENTALLY
             assert !result.reused
             assert result.executionReasons == expectedReasons
             return result
    @@ -651,7 +651,7 @@ class IncrementalExecutionTest extends Specification {
                 create.each { it ->
                     it.createFile()
                 }
    -            return EXECUTED
    +            return EXECUTED_NON_INCREMENTALLY
             }
             private Map inputProperties = [prop: "value"]
             private Map> inputs = inputFiles
    diff --git a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/SkipUpToDateStepTest.groovy b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/SkipUpToDateStepTest.groovy
    index a10a9abdab77e..141578d8e264f 100644
    --- a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/SkipUpToDateStepTest.groovy
    +++ b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/SkipUpToDateStepTest.groovy
    @@ -48,7 +48,7 @@ class SkipUpToDateStepTest extends StepSpec {
     
         def "executes when outputs are not up to date"() {
             def delegateResult = Mock(SnapshotResult)
    -        def delegateOutcome = Try.successful(ExecutionOutcome.EXECUTED)
    +        def delegateOutcome = Try.successful(ExecutionOutcome.EXECUTED_NON_INCREMENTALLY)
             def delegateOriginMetadata = Mock(OriginMetadata)
             def delegateFinalOutputs = ImmutableSortedMap.copyOf([test: EmptyCurrentFileCollectionFingerprint.EMPTY])
     
    diff --git a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/StoreSnapshotsStepTest.groovy b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/StoreSnapshotsStepTest.groovy
    index 8594f445310a0..40453a67bdfd0 100644
    --- a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/StoreSnapshotsStepTest.groovy
    +++ b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/StoreSnapshotsStepTest.groovy
    @@ -64,7 +64,7 @@ class StoreSnapshotsStepTest extends StepSpec implements FingerprinterFixture {
             then:
             1 * delegateResult.finalOutputs >> finalOutputs
             1 * context.beforeExecutionState >> Optional.of(beforeExecutionState)
    -        1 * delegateResult.outcome >> Try.successful(ExecutionOutcome.EXECUTED)
    +        1 * delegateResult.outcome >> Try.successful(ExecutionOutcome.EXECUTED_NON_INCREMENTALLY)
     
             then:
             interaction { expectStore(true, finalOutputs) }
    
    From 8e82531a2b117fece0acdb4d5fd5fe1d75e6cca8 Mon Sep 17 00:00:00 2001
    From: =?UTF-8?q?L=C3=B3r=C3=A1nt=20Pint=C3=A9r?= 
    Date: Fri, 8 Mar 2019 14:36:46 +0100
    Subject: [PATCH 419/853] Address review feedback
    
    ---
     .../org/gradle/internal/execution/steps/ResolveChangesStep.java | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/ResolveChangesStep.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/ResolveChangesStep.java
    index d9acdee3ee7ef..de466a7f90f63 100644
    --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/ResolveChangesStep.java
    +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/ResolveChangesStep.java
    @@ -47,7 +47,7 @@ public ResolveChangesStep(
     
         @Override
         public R execute(IncrementalContext context) {
    -        final UnitOfWork work = context.getWork();
    +        UnitOfWork work = context.getWork();
             ExecutionStateChanges changes = context.getRebuildReason()
                 .map(rebuildReason ->
                     new RebuildExecutionStateChanges(new DescriptiveChange(rebuildReason))
    
    From d630e1c35ca3862f60c9153ed5f1fe8388d6e291 Mon Sep 17 00:00:00 2001
    From: Gary Hale 
    Date: Fri, 8 Mar 2019 08:45:31 -0500
    Subject: [PATCH 420/853] Remove unroll from daemon soak test
    
    ---
     .../daemon/DaemonPerformanceMonitoringSoakTest.groovy         | 4 +---
     1 file changed, 1 insertion(+), 3 deletions(-)
    
    diff --git a/subprojects/soak/src/integTest/groovy/org/gradle/launcher/daemon/DaemonPerformanceMonitoringSoakTest.groovy b/subprojects/soak/src/integTest/groovy/org/gradle/launcher/daemon/DaemonPerformanceMonitoringSoakTest.groovy
    index a9fbf247bd96d..600ca6de2c1fa 100644
    --- a/subprojects/soak/src/integTest/groovy/org/gradle/launcher/daemon/DaemonPerformanceMonitoringSoakTest.groovy
    +++ b/subprojects/soak/src/integTest/groovy/org/gradle/launcher/daemon/DaemonPerformanceMonitoringSoakTest.groovy
    @@ -22,7 +22,6 @@ import org.gradle.launcher.daemon.fixtures.DaemonMultiJdkIntegrationTest
     import org.gradle.launcher.daemon.server.health.DaemonMemoryStatus
     import org.gradle.soak.categories.SoakTest
     import org.junit.experimental.categories.Category
    -import spock.lang.Unroll
     
     @Category(SoakTest)
     @TargetCoverage({DaemonPerformanceMonitoringCoverage.ALL_VERSIONS})
    @@ -46,8 +45,7 @@ class DaemonPerformanceMonitoringSoakTest extends DaemonMultiJdkIntegrationTest
             )
         }
     
    -    @Unroll
    -    def "when build leaks slowly daemon is eventually expired (heap: #heap)"() {
    +    def "when build leaks slowly daemon is eventually expired"() {
             when:
             setupBuildScript = tenuredHeapLeak
             maxBuilds = builds
    
    From c092a8fb5327270986e3fbc729f3917e831b8040 Mon Sep 17 00:00:00 2001
    From: Jendrik Johannes 
    Date: Fri, 8 Mar 2019 14:55:03 +0100
    Subject: [PATCH 421/853] Add missing space
    
    ---
     .teamcity/Gradle_Promotion/pluginData/plugin-settings.xml | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    diff --git a/.teamcity/Gradle_Promotion/pluginData/plugin-settings.xml b/.teamcity/Gradle_Promotion/pluginData/plugin-settings.xml
    index 566dff5528bd7..677e924ad523a 100644
    --- a/.teamcity/Gradle_Promotion/pluginData/plugin-settings.xml
    +++ b/.teamcity/Gradle_Promotion/pluginData/plugin-settings.xml
    @@ -1,3 +1,3 @@
     
    -
    +
     
    
    From ef8c40e15921c26f7a5cceabdf37cd33e4f6ba0d Mon Sep 17 00:00:00 2001
    From: =?UTF-8?q?L=C3=B3r=C3=A1nt=20Pint=C3=A9r?= 
    Date: Fri, 8 Mar 2019 14:57:04 +0100
    Subject: [PATCH 422/853] Fix compile error
    
    ---
     .../internal/artifacts/transform/WorkExecutorTestFixture.java   | 2 ++
     1 file changed, 2 insertions(+)
    
    diff --git a/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/WorkExecutorTestFixture.java b/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/WorkExecutorTestFixture.java
    index 6831fde71607b..e8dcc74b55372 100644
    --- a/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/WorkExecutorTestFixture.java
    +++ b/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/WorkExecutorTestFixture.java
    @@ -28,6 +28,7 @@
     import org.gradle.internal.execution.WorkExecutor;
     import org.gradle.internal.execution.history.ExecutionHistoryStore;
     import org.gradle.internal.execution.history.OutputFilesRepository;
    +import org.gradle.internal.execution.history.changes.DefaultExecutionStateChangeDetector;
     import org.gradle.internal.execution.timeout.impl.DefaultTimeoutHandler;
     import org.gradle.internal.id.UniqueId;
     import org.gradle.internal.scopeids.id.BuildInvocationScopeId;
    @@ -100,6 +101,7 @@ public void recordOutputs(Iterable outputFileFinge
                 buildCacheController,
                 cancellationToken,
                 buildInvocationScopeId,
    +            new DefaultExecutionStateChangeDetector(),
                 outputChangeListener,
                 outputFilesRepository,
                 new DefaultTimeoutHandler(null)
    
    From 37e70e6d925159d258d38ccacf91127e1bfa48b8 Mon Sep 17 00:00:00 2001
    From: =?UTF-8?q?L=C3=B3r=C3=A1nt=20Pint=C3=A9r?= 
    Date: Fri, 8 Mar 2019 15:00:12 +0100
    Subject: [PATCH 423/853] Test timeout handling
    
    ---
     .../internal/execution/steps/TimeoutStep.java |   8 +-
     .../internal/execution/timeout/Timeout.java   |   9 +-
     .../timeout/impl/DefaultTimeoutHandler.java   |   6 +-
     .../execution/steps/TimeoutStepTest.groovy    | 112 ++++++++++++++++++
     4 files changed, 120 insertions(+), 15 deletions(-)
     create mode 100644 subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/TimeoutStepTest.groovy
    
    diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/TimeoutStep.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/TimeoutStep.java
    index 30b5e75dbd938..b61e32c454d20 100644
    --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/TimeoutStep.java
    +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/TimeoutStep.java
    @@ -32,7 +32,10 @@ public class TimeoutStep implements Step {
         private final TimeoutHandler timeoutHandler;
         private final Step delegate;
     
    -    public TimeoutStep(TimeoutHandler timeoutHandler, Step delegate) {
    +    public TimeoutStep(
    +        TimeoutHandler timeoutHandler,
    +        Step delegate
    +    ) {
             this.timeoutHandler = timeoutHandler;
             this.delegate = delegate;
         }
    @@ -57,8 +60,7 @@ private Result executeWithTimeout(C context, Duration timeout) {
             try {
                 return executeWithoutTimeout(context);
             } finally {
    -            taskTimeout.stop();
    -            if (taskTimeout.timedOut()) {
    +            if (taskTimeout.stop()) {
                     //noinspection ResultOfMethodCallIgnored
                     Thread.interrupted();
                     //noinspection ThrowFromFinallyBlock
    diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/timeout/Timeout.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/timeout/Timeout.java
    index fad0d0d3df5c1..fb92feff2210a 100644
    --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/timeout/Timeout.java
    +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/timeout/Timeout.java
    @@ -21,12 +21,7 @@
      */
     public interface Timeout {
         /**
    -     * Returns whether the work did time out.
    +     * Stops the timeout and returns whether the work did time out.
          */
    -    boolean timedOut();
    -
    -    /**
    -     * Stops the timeout.
    -     */
    -    void stop();
    +    boolean stop();
     }
    diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/timeout/impl/DefaultTimeoutHandler.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/timeout/impl/DefaultTimeoutHandler.java
    index be58bf8cbf179..9a096e78b2f46 100644
    --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/timeout/impl/DefaultTimeoutHandler.java
    +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/timeout/impl/DefaultTimeoutHandler.java
    @@ -54,12 +54,8 @@ private DefaultTimeout(ScheduledFuture timeoutTask, InterruptOnTimeout interr
             }
     
             @Override
    -        public void stop() {
    +        public boolean stop() {
                 timeoutTask.cancel(true);
    -        }
    -
    -        @Override
    -        public boolean timedOut() {
                 return interrupter.interrupted;
             }
         }
    diff --git a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/TimeoutStepTest.groovy b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/TimeoutStepTest.groovy
    new file mode 100644
    index 0000000000000..d4327ac66478f
    --- /dev/null
    +++ b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/TimeoutStepTest.groovy
    @@ -0,0 +1,112 @@
    +/*
    + * Copyright 2019 the original author or authors.
    + *
    + * Licensed under the Apache License, Version 2.0 (the "License");
    + * you may not use this file except in compliance with the License.
    + * You may obtain a copy of the License at
    + *
    + *      http://www.apache.org/licenses/LICENSE-2.0
    + *
    + * Unless required by applicable law or agreed to in writing, software
    + * distributed under the License is distributed on an "AS IS" BASIS,
    + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    + * See the License for the specific language governing permissions and
    + * limitations under the License.
    + */
    +
    +package org.gradle.internal.execution.steps
    +
    +
    +import org.gradle.api.InvalidUserDataException
    +import org.gradle.internal.execution.Context
    +import org.gradle.internal.execution.Result
    +import org.gradle.internal.execution.timeout.Timeout
    +import org.gradle.internal.execution.timeout.TimeoutHandler
    +
    +import java.time.Duration
    +import java.time.temporal.ChronoUnit
    +
    +class TimeoutStepTest extends StepSpec {
    +    def timeoutHandler = Mock(TimeoutHandler)
    +    def step = new TimeoutStep(timeoutHandler, delegate)
    +    def context = Mock(Context)
    +    def delegateResult = Mock(Result)
    +
    +    def "negative timeout is reported"() {
    +        when:
    +        step.execute(context)
    +
    +        then:
    +        thrown InvalidUserDataException
    +
    +        1 * context.work >> work
    +        1 * work.timeout >> Optional.of(Duration.of(-1, ChronoUnit.SECONDS))
    +        1 * work.displayName >> "bad work"
    +        0 * _
    +    }
    +
    +    def "executing without timeout succeeds"() {
    +        when:
    +        def result = step.execute(context)
    +
    +        then:
    +        result == delegateResult
    +
    +        1 * context.work >> work
    +        1 * work.timeout >> Optional.empty()
    +
    +        then:
    +        1 * delegate.execute(context) >> delegateResult
    +        0 * _
    +    }
    +
    +    def "executing under timeout succeeds"() {
    +        def duration = Duration.of(1, ChronoUnit.SECONDS)
    +        def timeout = Mock(Timeout)
    +
    +        when:
    +        def result = step.execute(context)
    +
    +        then:
    +        result == delegateResult
    +
    +        1 * context.work >> work
    +        1 * work.timeout >> Optional.of(duration)
    +
    +        then:
    +        timeoutHandler.start(_ as Thread, duration) >> timeout
    +
    +        then:
    +        1 * delegate.execute(context) >> delegateResult
    +
    +        then:
    +        1 * timeout.stop() >> false
    +        0 * _
    +    }
    +
    +    def "executing over timeout fails"() {
    +        def duration = Duration.of(1, ChronoUnit.SECONDS)
    +        def timeout = Mock(Timeout)
    +
    +        when:
    +        step.execute(context)
    +
    +        then:
    +        1 * context.work >> work
    +        1 * work.timeout >> Optional.of(duration)
    +
    +        then:
    +        1 * timeoutHandler.start(_ as Thread, duration) >> timeout
    +
    +        then:
    +        1 * delegate.execute(context) >> delegateResult
    +
    +        then:
    +        1 * timeout.stop() >> true
    +
    +        then:
    +        def ex = thrown Exception
    +        ex.message == "Timeout has been exceeded"
    +        0 * _
    +    }
    +}
    
    From 414467a94d661b2ddb9ed451819afa6b7fc4f04f Mon Sep 17 00:00:00 2001
    From: =?UTF-8?q?L=C3=B3r=C3=A1nt=20Pint=C3=A9r?= 
    Date: Fri, 8 Mar 2019 15:01:38 +0100
    Subject: [PATCH 424/853] Code cleanup: rename class
    
    ---
     .../internal/service/scopes/ExecutionGradleServices.java      | 4 ++--
     .../tasks/execution/ExecuteActionsTaskExecuterTest.groovy     | 4 ++--
     .../artifacts/DefaultDependencyManagementServices.java        | 4 ++--
     .../{SnapshotOutputStep.java => SnapshotOutputsStep.java}     | 4 ++--
     .../internal/execution/steps/IncrementalExecutionTest.groovy  | 2 +-
     5 files changed, 9 insertions(+), 9 deletions(-)
     rename subprojects/execution/src/main/java/org/gradle/internal/execution/steps/{SnapshotOutputStep.java => SnapshotOutputsStep.java} (95%)
    
    diff --git a/subprojects/core/src/main/java/org/gradle/internal/service/scopes/ExecutionGradleServices.java b/subprojects/core/src/main/java/org/gradle/internal/service/scopes/ExecutionGradleServices.java
    index e50f30c7750ac..2d22c2b65b8f1 100644
    --- a/subprojects/core/src/main/java/org/gradle/internal/service/scopes/ExecutionGradleServices.java
    +++ b/subprojects/core/src/main/java/org/gradle/internal/service/scopes/ExecutionGradleServices.java
    @@ -56,7 +56,7 @@
     import org.gradle.internal.execution.steps.RecordOutputsStep;
     import org.gradle.internal.execution.steps.ResolveChangesStep;
     import org.gradle.internal.execution.steps.SkipUpToDateStep;
    -import org.gradle.internal.execution.steps.SnapshotOutputStep;
    +import org.gradle.internal.execution.steps.SnapshotOutputsStep;
     import org.gradle.internal.execution.steps.StoreSnapshotsStep;
     import org.gradle.internal.execution.steps.TimeoutStep;
     import org.gradle.internal.execution.timeout.TimeoutHandler;
    @@ -131,7 +131,7 @@ public WorkExecutor createWorkExecutor(
                             new StoreSnapshotsStep(
                                 new PrepareCachingStep(
                                     new CacheStep(buildCacheController, outputChangeListener, buildCacheCommandFactory,
    -                                    new SnapshotOutputStep(buildInvocationScopeId.getId(),
    +                                    new SnapshotOutputsStep(buildInvocationScopeId.getId(),
                                             new CreateOutputsStep(
                                                 new CatchExceptionStep(
                                                     new TimeoutStep(timeoutHandler,
    diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuterTest.groovy b/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuterTest.groovy
    index 40886fe200ca1..6c5a6cf5f5687 100644
    --- a/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuterTest.groovy
    +++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuterTest.groovy
    @@ -46,7 +46,7 @@ import org.gradle.internal.execution.steps.CatchExceptionStep
     import org.gradle.internal.execution.steps.ExecuteStep
     import org.gradle.internal.execution.steps.ResolveChangesStep
     import org.gradle.internal.execution.steps.SkipUpToDateStep
    -import org.gradle.internal.execution.steps.SnapshotOutputStep
    +import org.gradle.internal.execution.steps.SnapshotOutputsStep
     import org.gradle.internal.id.UniqueId
     import org.gradle.internal.operations.BuildOperationContext
     import org.gradle.internal.operations.BuildOperationExecutor
    @@ -80,7 +80,7 @@ class ExecuteActionsTaskExecuterTest extends Specification {
         def workExecutor = new DefaultWorkExecutor(
             new ResolveChangesStep(new DefaultExecutionStateChangeDetector(),
                 new SkipUpToDateStep(
    -                new SnapshotOutputStep(buildId,
    +                new SnapshotOutputsStep(buildId,
                         new CatchExceptionStep(
                             new CancelExecutionStep(cancellationToken,
                                 new BroadcastChangingOutputsStep(outputChangeListener,
    diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/DefaultDependencyManagementServices.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/DefaultDependencyManagementServices.java
    index 517de9331d4b1..527823f6b4991 100644
    --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/DefaultDependencyManagementServices.java
    +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/DefaultDependencyManagementServices.java
    @@ -120,7 +120,7 @@
     import org.gradle.internal.execution.steps.PrepareCachingStep;
     import org.gradle.internal.execution.steps.ResolveChangesStep;
     import org.gradle.internal.execution.steps.SkipUpToDateStep;
    -import org.gradle.internal.execution.steps.SnapshotOutputStep;
    +import org.gradle.internal.execution.steps.SnapshotOutputsStep;
     import org.gradle.internal.execution.steps.StoreSnapshotsStep;
     import org.gradle.internal.execution.steps.TimeoutStep;
     import org.gradle.internal.execution.timeout.TimeoutHandler;
    @@ -209,7 +209,7 @@ WorkExecutor createWorkExecutor(
                         new SkipUpToDateStep<>(
                             new StoreSnapshotsStep<>(
                                 new PrepareCachingStep<>(
    -                                new SnapshotOutputStep<>(fixedUniqueId,
    +                                new SnapshotOutputsStep<>(fixedUniqueId,
                                         new CreateOutputsStep<>(
                                             new CatchExceptionStep<>(
                                                 new TimeoutStep<>(timeoutHandler,
    diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/SnapshotOutputStep.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/SnapshotOutputsStep.java
    similarity index 95%
    rename from subprojects/execution/src/main/java/org/gradle/internal/execution/steps/SnapshotOutputStep.java
    rename to subprojects/execution/src/main/java/org/gradle/internal/execution/steps/SnapshotOutputsStep.java
    index ae4bcdadaf84c..15ce0f293336d 100644
    --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/SnapshotOutputStep.java
    +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/SnapshotOutputsStep.java
    @@ -28,11 +28,11 @@
     import org.gradle.internal.fingerprint.CurrentFileCollectionFingerprint;
     import org.gradle.internal.id.UniqueId;
     
    -public class SnapshotOutputStep implements Step {
    +public class SnapshotOutputsStep implements Step {
         private final UniqueId buildInvocationScopeId;
         private final Step delegate;
     
    -    public SnapshotOutputStep(
    +    public SnapshotOutputsStep(
                 UniqueId buildInvocationScopeId,
                 Step delegate
         ) {
    diff --git a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/IncrementalExecutionTest.groovy b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/IncrementalExecutionTest.groovy
    index 7036ca87132ca..d5a310a8e048d 100644
    --- a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/IncrementalExecutionTest.groovy
    +++ b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/IncrementalExecutionTest.groovy
    @@ -118,7 +118,7 @@ class IncrementalExecutionTest extends Specification {
             new DefaultWorkExecutor(
                 new SkipUpToDateStep(
                     new StoreSnapshotsStep(
    -                    new SnapshotOutputStep(buildInvocationScopeId.getId(),
    +                    new SnapshotOutputsStep(buildInvocationScopeId.getId(),
                             new BroadcastChangingOutputsStep(outputChangeListener, delegate)
                         )
                     )
    
    From 058b495e6bc2130a7bb161a6198d64b7ef6fc4c9 Mon Sep 17 00:00:00 2001
    From: Louis Jacomet 
    Date: Fri, 8 Mar 2019 15:19:24 +0100
    Subject: [PATCH 425/853] Transform disambiguation with schema disambiguation
    
    With this change, transform disambiguation now first leverages the
    schema disambiguation rule.
    Size based disambiguation only happens in a second phase if still
    required.
    
    Fixes #8721
    ---
     .../ArtifactTransformIntegrationTest.groovy   |   3 +
     ...ateArtifactTransformIntegrationTest.groovy | 125 ++++++++++++++++++
     .../AttributeMatchingVariantSelector.java     |  24 +++-
     ...ttributeMatchingVariantSelectorSpec.groovy |  60 ++++++++-
     4 files changed, 208 insertions(+), 4 deletions(-)
    
    diff --git a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformIntegrationTest.groovy b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformIntegrationTest.groovy
    index 6fc6f209d81ac..690d459d424e5 100644
    --- a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformIntegrationTest.groovy
    +++ b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformIntegrationTest.groovy
    @@ -1029,6 +1029,7 @@ Found the following transforms:
                             }
                             variant3 {
                                 attributes.attribute(buildType, 'debug')
    +                            attributes.attribute(flavor, 'free')
                                 artifact jar1
                             }
                         }
    @@ -1109,11 +1110,13 @@ Found the following transforms:
           - With source attributes:
               - artifactType 'jar'
               - buildType 'debug'
    +          - flavor 'free'
               - usage 'api'
           - Candidate transform(s):
               - Transform 'BrokenTransform' producing attributes:
                   - artifactType 'transformed'
                   - buildType 'debug'
    +              - flavor 'free'
                   - usage 'api'"""
         }
     
    diff --git a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/DisambiguateArtifactTransformIntegrationTest.groovy b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/DisambiguateArtifactTransformIntegrationTest.groovy
    index 2f0fb0d007c5a..b3ba500823f0f 100644
    --- a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/DisambiguateArtifactTransformIntegrationTest.groovy
    +++ b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/DisambiguateArtifactTransformIntegrationTest.groovy
    @@ -18,6 +18,7 @@ package org.gradle.integtests.resolve.transform
     
     import org.gradle.integtests.fixtures.AbstractHttpDependencyResolutionTest
     import spock.lang.Issue
    +import spock.lang.Unroll
     
     class DisambiguateArtifactTransformIntegrationTest extends AbstractHttpDependencyResolutionTest {
     
    @@ -168,7 +169,9 @@ project(':app') {
     
         dependencies {
             registerTransform {
    +            from.attribute(Usage.USAGE_ATTRIBUTE, objects.named(Usage, Usage.JAVA_API_CLASSES))
                 from.attribute(artifactType, 'java-classes-directory')
    +            to.attribute(Usage.USAGE_ATTRIBUTE, objects.named(Usage, Usage.JAVA_API))
                 to.attribute(artifactType, 'final')
                 
                 if (project.hasProperty('extraAttribute')) {
    @@ -179,7 +182,9 @@ project(':app') {
                 artifactTransform(TestTransform)
             }
             registerTransform {
    +            from.attribute(Usage.USAGE_ATTRIBUTE, objects.named(Usage, Usage.JAVA_API_JARS))
                 from.attribute(artifactType, 'jar')
    +            to.attribute(Usage.USAGE_ATTRIBUTE, objects.named(Usage, Usage.JAVA_API))
                 to.attribute(artifactType, 'magic-jar')
     
                 if (project.hasProperty('extraAttribute')) {
    @@ -479,4 +484,124 @@ task resolve(type: Copy) {
             output.count('minified=true')
             output.count('Sizing') == 0
         }
    +
    +    @Unroll
    +    def "disambiguation leverages schema rules before doing it size based"() {
    +        given:
    +        settingsFile << """
    +include('child')
    +"""
    +        buildFile << """
    +def artifactType = Attribute.of('artifactType', String)
    +
    +apply plugin: 'java-library'
    +
    +allprojects {
    +    repositories {
    +        maven { url "${mavenRepo.uri}" }
    +    }
    +}
    +
    +project(':child') {
    +    configurations {
    +        runtimeElements {
    +            canBeResolved = false
    +            attributes {
    +                attribute(Bundling.BUNDLING_ATTRIBUTE, objects.named(Bundling, Bundling.EXTERNAL))
    +            }
    +        }
    +    }
    +    
    +    
    +    artifacts {
    +        buildDir.mkdirs()
    +        file("\$buildDir/test.jar").text = "toto"
    +        runtimeElements file("\$buildDir/test.jar")
    +    }
    +}
    +
    +dependencies {
    +    api project(':child')
    +    
    +    artifactTypes.getByName("jar") {
    +        attributes.attribute(Usage.USAGE_ATTRIBUTE, objects.named(Usage, "weird"))
    +    }
    +    
    +    if ($apiFirst) {
    +        registerTransform {
    +            from.attribute(artifactType, 'jar')
    +            from.attribute(Usage.USAGE_ATTRIBUTE, objects.named(Usage, "weird"))
    +            to.attribute(artifactType, 'jar')
    +            to.attribute(Usage.USAGE_ATTRIBUTE, objects.named(Usage, Usage.JAVA_API))
    +            artifactTransform(Identity)
    +        }
    +    }
    +    registerTransform {
    +        from.attribute(artifactType, 'jar')
    +        from.attribute(Usage.USAGE_ATTRIBUTE, objects.named(Usage, "weird"))
    +        to.attribute(artifactType, 'jar')
    +        to.attribute(Usage.USAGE_ATTRIBUTE, objects.named(Usage, Usage.JAVA_RUNTIME))
    +        artifactTransform(IllegalTransform)
    +    }
    +    if (!$apiFirst) {
    +        registerTransform {
    +            from.attribute(artifactType, 'jar')
    +            from.attribute(Usage.USAGE_ATTRIBUTE, objects.named(Usage, "weird"))
    +            to.attribute(artifactType, 'jar')
    +            to.attribute(Usage.USAGE_ATTRIBUTE, objects.named(Usage, Usage.JAVA_API))
    +            artifactTransform(Identity)
    +        }
    +    }
    +    registerTransform {
    +        from.attribute(artifactType, 'jar')
    +        to.attribute(artifactType, 'size')
    +        artifactTransform(FileSizer)
    +    }
    +}
    +
    +class Identity extends ArtifactTransform {
    +    List transform(File input) {
    +        return [input]
    +    }
    +}
    +
    +class IllegalTransform extends ArtifactTransform {
    +    List transform(File input) {
    +        throw new IllegalStateException("IllegalTransform should not be invoked")
    +    }
    +}
    +
    +class FileSizer extends ArtifactTransform {
    +    List transform(File input) {
    +        assert outputDirectory.directory && outputDirectory.list().length == 0
    +        def output = new File(outputDirectory, input.name + ".txt")
    +        println "Sizing \${input.name} to \${output.name}"
    +        output.text = String.valueOf(input.length())
    +        return [output]
    +    }
    +}
    +
    +task resolve(type: Copy) {
    +    def artifacts = configurations.compileClasspath.incoming.artifactView {
    +        attributes { it.attribute(artifactType, 'size') }
    +    }.artifacts
    +    from artifacts.artifactFiles
    +    into "\${buildDir}/libs"
    +    doLast {
    +        println "files: " + artifacts.collect { it.file.name }
    +        println "ids: " + artifacts.collect { it.id }
    +        println "components: " + artifacts.collect { it.id.componentIdentifier }
    +        println "variants: " + artifacts.collect { it.variant.attributes }
    +    }
    +}
    +"""
    +        when:
    +        succeeds "resolve"
    +
    +        then:
    +        output.contains('variants: [{artifactType=size, org.gradle.dependency.bundling=external, org.gradle.usage=java-api}]')
    +
    +        where:
    +        apiFirst << [true, false]
    +    }
     }
    diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/AttributeMatchingVariantSelector.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/AttributeMatchingVariantSelector.java
    index 0868bbd736920..8fa889f15b15c 100644
    --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/AttributeMatchingVariantSelector.java
    +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/AttributeMatchingVariantSelector.java
    @@ -36,6 +36,7 @@
     import java.util.Comparator;
     import java.util.List;
     import java.util.Optional;
    +import java.util.stream.Collectors;
     
     class AttributeMatchingVariantSelector implements VariantSelector {
         private final ConsumerProvidedVariantFinder consumerProvidedVariantFinder;
    @@ -98,7 +99,7 @@ private ResolvedArtifactSet doSelect(ResolvedVariantSet producer) {
                 }
             }
             if (candidates.size() > 1) {
    -            candidates = tryDisambiguate(matcher, candidates);
    +            candidates = tryDisambiguate(matcher, candidates, componentRequested);
             }
             if (candidates.size() == 1) {
                 Pair result = candidates.get(0);
    @@ -118,7 +119,13 @@ private ResolvedArtifactSet doSelect(ResolvedVariantSet producer) {
             throw new NoMatchingVariantSelectionException(producer.asDescribable().getDisplayName(), componentRequested, producer.getVariants(), matcher);
         }
     
    -    private List> tryDisambiguate(AttributeMatcher matcher, List> candidates) {
    +    private List> tryDisambiguate(AttributeMatcher matcher, List> candidates, ImmutableAttributes componentRequested) {
    +        candidates = disambiguateWithSchema(matcher, candidates, componentRequested);
    +
    +        if (candidates.size() == 1) {
    +            return candidates;
    +        }
    +
             if (candidates.size() == 2) {
                 // Short circuit logic when only 2 candidates
                 return compareCandidates(matcher, candidates.get(0), candidates.get(1))
    @@ -161,6 +168,19 @@ private List>
             return shortestTransforms;
         }
     
    +    private List> disambiguateWithSchema(AttributeMatcher matcher, List> candidates, ImmutableAttributes componentRequested) {
    +        List candidateAttributes = candidates.stream().map(pair -> pair.getRight().attributes).collect(Collectors.toList());
    +        List matches = matcher.matches(candidateAttributes, componentRequested);
    +        if (matches.size() == 1) {
    +            AttributeContainerInternal singleMatch = matches.get(0);
    +            return candidates.stream().filter(pair -> pair.getRight().attributes == singleMatch).collect(Collectors.toList());
    +        } else if (matches.size() > 0 && matches.size() < candidates.size()) {
    +            // We know all are compatibles, so this is only possible if some disambiguation happens but not getting us to 1 candidate
    +            return candidates.stream().filter(pair -> matches.contains(pair.getRight().attributes)).collect(Collectors.toList());
    +        }
    +        return candidates;
    +    }
    +
         private Optional> compareCandidates(AttributeMatcher matcher,
                                                                                                               Pair firstCandidate,
                                                                                                               Pair secondCandidate) {
    diff --git a/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/AttributeMatchingVariantSelectorSpec.groovy b/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/AttributeMatchingVariantSelectorSpec.groovy
    index 02d9b6a5a5485..11e30f674a010 100644
    --- a/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/AttributeMatchingVariantSelectorSpec.groovy
    +++ b/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/AttributeMatchingVariantSelectorSpec.groovy
    @@ -189,6 +189,7 @@ class AttributeMatchingVariantSelectorSpec extends Specification {
             1 * consumerProvidedVariantFinder.collectConsumerVariants(otherVariantAttributes, requestedAttributes, _) >> { args ->
                 args[2].matched(requestedAttributes, transform2, 3)
             }
    +        1 * attributeMatcher.matches(_, _) >> { args -> args[0] }
         }
     
         def 'can disambiguate 2 equivalent chains by picking shortest'() {
    @@ -240,6 +241,58 @@ class AttributeMatchingVariantSelectorSpec extends Specification {
             1 * consumerProvidedVariantFinder.collectConsumerVariants(otherVariantAttributes, requestedAttributes, _) >> { args ->
                 args[2].matched(requestedAttributes, transform2, 3)
             }
    +        1 * attributeMatcher.matches(_, _) >> { args -> args[0] }
    +    }
    +
    +    def 'can leverage schema disambiguation'() {
    +        given:
    +        def otherVariant = Mock(ResolvedVariant) {
    +            getAttributes() >> otherVariantAttributes
    +            asDescribable() >> Describables.of("mock other resolved variant")
    +        }
    +        def multiVariantSet = Mock(ResolvedVariantSet) {
    +            asDescribable() >> Describables.of("mock multi producer")
    +            getVariants() >> [variant, otherVariant]
    +        }
    +        def transform1 = Mock(Transformation)
    +        def transform2 = Mock(Transformation)
    +        def selector = new AttributeMatchingVariantSelector(consumerProvidedVariantFinder, attributesSchema, attributesFactory, requestedAttributes, false, dependenciesResolverFactory)
    +
    +        when:
    +        def result = selector.select(multiVariantSet)
    +
    +
    +        then:
    +        result.visitDependencies(new TaskDependencyResolveContext() {
    +            @Override
    +            void add(Object dependency) {
    +                assert dependency instanceof DefaultTransformationDependency
    +                assert dependency.transformation == transform1
    +            }
    +
    +            @Override
    +            void maybeAdd(Object dependency) {
    +
    +            }
    +
    +            @Override
    +            void visitFailure(Throwable failure) {
    +                throw failure
    +            }
    +
    +            @Override
    +            Task getTask() {
    +                return null
    +            }
    +        })
    +        1 * attributeMatcher.matches(_, _) >> Collections.emptyList()
    +        1 * consumerProvidedVariantFinder.collectConsumerVariants(variantAttributes, requestedAttributes, _) >> { args ->
    +            args[2].matched(requestedAttributes, transform1, 2)
    +        }
    +        1 * consumerProvidedVariantFinder.collectConsumerVariants(otherVariantAttributes, requestedAttributes, _) >> { args ->
    +            args[2].matched(variantAttributes, transform2, 3)
    +        }
    +        1 * attributeMatcher.matches(_, _) >> { args -> [args[0].get(0)] }
         }
     
         def 'can disambiguate between three chains when one subset of both others'() {
    @@ -300,6 +353,7 @@ class AttributeMatchingVariantSelectorSpec extends Specification {
             1 * consumerProvidedVariantFinder.collectConsumerVariants(yetAnotherVariantAttributes, requestedAttributes, _) >> { args ->
                 args[2].matched(requestedAttributes, transform3, 2)
             }
    +        1 * attributeMatcher.matches(_, _) >> { args -> args[0] }
         }
     
         def 'can disambiguate 3 equivalent chains by picking shortest'() {
    @@ -350,7 +404,6 @@ class AttributeMatchingVariantSelectorSpec extends Specification {
                 }
             })
             1 * attributeMatcher.matches(_, _) >> Collections.emptyList()
    -        2 * attributeMatcher.isMatching(requestedAttributes, requestedAttributes) >> true
             1 * consumerProvidedVariantFinder.collectConsumerVariants(variantAttributes, requestedAttributes, _) >> { args ->
                 args[2].matched(requestedAttributes, transform1, 3)
             }
    @@ -360,6 +413,8 @@ class AttributeMatchingVariantSelectorSpec extends Specification {
             1 * consumerProvidedVariantFinder.collectConsumerVariants(yetAnotherVariantAttributes, requestedAttributes, _) >> { args ->
                 args[2].matched(requestedAttributes, transform3, 3)
             }
    +        2 * attributeMatcher.isMatching(requestedAttributes, requestedAttributes) >> true
    +        1 * attributeMatcher.matches(_, _) >> { args -> args[0] }
         }
     
         def 'cannot disambiguate 3 chains when 2 different'() {
    @@ -409,7 +464,6 @@ class AttributeMatchingVariantSelectorSpec extends Specification {
                 }
             })
             1 * attributeMatcher.matches(_, _) >> Collections.emptyList()
    -        3 * attributeMatcher.isMatching(requestedAttributes, requestedAttributes) >>> [false, false, true]
             1 * consumerProvidedVariantFinder.collectConsumerVariants(variantAttributes, requestedAttributes, _) >> { args ->
                 args[2].matched(requestedAttributes, transform1, 3)
             }
    @@ -419,5 +473,7 @@ class AttributeMatchingVariantSelectorSpec extends Specification {
             1 * consumerProvidedVariantFinder.collectConsumerVariants(yetAnotherVariantAttributes, requestedAttributes, _) >> { args ->
                 args[2].matched(requestedAttributes, transform3, 3)
             }
    +        1 * attributeMatcher.matches(_, _) >> { args -> args[0] }
    +        3 * attributeMatcher.isMatching(requestedAttributes, requestedAttributes) >>> [false, false, true]
         }
     }
    
    From f3cef55ba3ed93a3c9350f99c3ec0c141a64faec Mon Sep 17 00:00:00 2001
    From: Gradleware Git Bot 
    Date: Fri, 8 Mar 2019 15:26:36 +0100
    Subject: [PATCH 426/853] Publish 5.3-20190308141055+0000
    
    ---
     released-versions.json | 4 ++--
     1 file changed, 2 insertions(+), 2 deletions(-)
    
    diff --git a/released-versions.json b/released-versions.json
    index 8d0d180809a7f..207530851ef18 100644
    --- a/released-versions.json
    +++ b/released-versions.json
    @@ -1,7 +1,7 @@
     {
         "latestReleaseSnapshot": {
    -        "version": "5.3-20190308013119+0000",
    -        "buildTime": "20190308013119+0000"
    +        "version": "5.3-20190308141055+0000",
    +        "buildTime": "20190308141055+0000"
         },
         "latestRc": {
             "version": "5.3-rc-1",
    
    From 3614a1048513a9385d5471fdf6943d4060d20ac3 Mon Sep 17 00:00:00 2001
    From: =?UTF-8?q?L=C3=B3r=C3=A1nt=20Pint=C3=A9r?= 
    Date: Fri, 8 Mar 2019 16:09:22 +0100
    Subject: [PATCH 427/853] Fix test
    
    ---
     .../tasks/execution/ExecuteActionsTaskExecuterTest.groovy        | 1 +
     1 file changed, 1 insertion(+)
    
    diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuterTest.groovy b/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuterTest.groovy
    index 6c5a6cf5f5687..3e0b645a7a8b6 100644
    --- a/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuterTest.groovy
    +++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuterTest.groovy
    @@ -104,6 +104,7 @@ class ExecuteActionsTaskExecuterTest extends Specification {
             executionContext.getOverlappingOutputs() >> Optional.empty()
             executionContext.getExecutionStateChanges() >> Optional.empty()
             executionContext.getTaskExecutionMode() >> TaskExecutionMode.INCREMENTAL
    +        executionContext.getBeforeExecutionState() >> Optional.empty()
     
             executionContext.getTaskProperties() >> taskProperties
             taskProperties.getOutputFileProperties() >> ImmutableSortedSet.of()
    
    From 8b0c574c8e9a16ccc355ad7b94a9dbaa736fb0bc Mon Sep 17 00:00:00 2001
    From: =?UTF-8?q?L=C3=B3r=C3=A1nt=20Pint=C3=A9r?= 
    Date: Fri, 8 Mar 2019 16:09:37 +0100
    Subject: [PATCH 428/853] Ignore IncrementalExecutionTest again for now
    
    ---
     .../internal/execution/steps/IncrementalExecutionTest.groovy   | 3 +++
     1 file changed, 3 insertions(+)
    
    diff --git a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/IncrementalExecutionTest.groovy b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/IncrementalExecutionTest.groovy
    index d5a310a8e048d..973c9ad0670ce 100644
    --- a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/IncrementalExecutionTest.groovy
    +++ b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/IncrementalExecutionTest.groovy
    @@ -58,6 +58,7 @@ import org.gradle.test.fixtures.file.TestFile
     import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider
     import org.gradle.testing.internal.util.Specification
     import org.junit.Rule
    +import spock.lang.Ignore
     
     import java.time.Duration
     import java.util.function.Supplier
    @@ -65,6 +66,8 @@ import java.util.function.Supplier
     import static org.gradle.internal.execution.ExecutionOutcome.EXECUTED_NON_INCREMENTALLY
     import static org.gradle.internal.execution.ExecutionOutcome.UP_TO_DATE
     
    +// FIXME:lptr
    +@Ignore
     class IncrementalExecutionTest extends Specification {
     
         @Rule
    
    From cf1e485a35185a34b282206f92f160da344d24aa Mon Sep 17 00:00:00 2001
    From: Stefan Wolf 
    Date: Fri, 8 Mar 2019 18:12:16 +0100
    Subject: [PATCH 429/853] Replace text after checkout
    
    ---
     subprojects/performance/templates.gradle | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    diff --git a/subprojects/performance/templates.gradle b/subprojects/performance/templates.gradle
    index ef49ecb8841aa..a84a4211b3793 100644
    --- a/subprojects/performance/templates.gradle
    +++ b/subprojects/performance/templates.gradle
    @@ -358,7 +358,7 @@ tasks.register("santaTrackerAndroidBuild", RemoteProject) {
         remoteUri = 'https://github.com/gradle/santa-tracker-android.git'
         branch = 'agp-3.5.0'
         doLast {
    -        new File(outputDirectory, 'santa-tracker/google-services.json') << """
    +        new File(outputDirectory, 'santa-tracker/google-services.json').text = """
     {
       "project_info": {
         "project_number": "012345678912",
    
    From e37c463b1cdf7e5560523fdf5c3ce3251d0d082c Mon Sep 17 00:00:00 2001
    From: Stefan Wolf 
    Date: Fri, 8 Mar 2019 18:28:13 +0100
    Subject: [PATCH 430/853] Use getCompleted instead of getResultIfCompleted
    
    ---
     .../DefaultDependencyManagementServices.java        |  8 +++-----
     .../transform/DefaultTransformationNodeFactory.java | 10 ++++------
     .../transform/PrecomputedTransformationResult.java  | 10 +++++-----
     .../transform/TransformationNodeFactory.java        |  6 ++----
     .../transform/TransformationOperation.java          |  8 ++++----
     .../artifacts/transform/TransformationResult.java   |  2 +-
     .../transform/TransformingArtifactVisitor.java      |  6 +++---
     .../TransformingAsyncArtifactListener.java          |  8 ++++----
     .../transform/DefaultArtifactTransformsTest.groovy  | 13 ++-----------
     .../TransformingAsyncArtifactListenerTest.groovy    |  4 ++--
     10 files changed, 30 insertions(+), 45 deletions(-)
    
    diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/DefaultDependencyManagementServices.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/DefaultDependencyManagementServices.java
    index 3d2dfb0cd67dc..1fe461f5d5b0b 100644
    --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/DefaultDependencyManagementServices.java
    +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/DefaultDependencyManagementServices.java
    @@ -86,7 +86,6 @@
     import org.gradle.api.internal.artifacts.transform.TransformationNode;
     import org.gradle.api.internal.artifacts.transform.TransformationNodeFactory;
     import org.gradle.api.internal.artifacts.transform.TransformationRegistrationFactory;
    -import org.gradle.api.internal.artifacts.transform.TransformationSubject;
     import org.gradle.api.internal.artifacts.transform.TransformerInvoker;
     import org.gradle.api.internal.artifacts.type.ArtifactTypeRegistry;
     import org.gradle.api.internal.artifacts.type.DefaultArtifactTypeRegistry;
    @@ -104,7 +103,6 @@
     import org.gradle.api.model.ObjectFactory;
     import org.gradle.configuration.internal.UserCodeApplicationContext;
     import org.gradle.initialization.ProjectAccessListener;
    -import org.gradle.internal.Try;
     import org.gradle.internal.authentication.AuthenticationSchemeRegistry;
     import org.gradle.internal.build.BuildState;
     import org.gradle.internal.classloader.ClassLoaderHierarchyHasher;
    @@ -159,6 +157,7 @@
     import java.io.File;
     import java.util.Collection;
     import java.util.List;
    +import java.util.Optional;
     
     public class DefaultDependencyManagementServices implements DependencyManagementServices {
     
    @@ -208,10 +207,9 @@ public Collection getOrCreate(ResolvedArtifactSet artifactSe
                         throw new UnsupportedOperationException("Cannot schedule transforms for build script dependencies");
                     }
     
    -                @Nullable
                     @Override
    -                public Try getResultIfCompleted(ComponentArtifactIdentifier artifactId, Transformation transformation) {
    -                    return null;
    +                public Optional getCompleted(ComponentArtifactIdentifier artifactId, Transformation transformation) {
    +                    return Optional.empty();
                     }
                 };
             }
    diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformationNodeFactory.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformationNodeFactory.java
    index 71a7d8dd0b0a5..b3bb52112494e 100644
    --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformationNodeFactory.java
    +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformationNodeFactory.java
    @@ -23,12 +23,11 @@
     import org.gradle.api.artifacts.component.ComponentArtifactIdentifier;
     import org.gradle.api.internal.artifacts.ivyservice.resolveengine.artifact.ResolvableArtifact;
     import org.gradle.api.internal.artifacts.ivyservice.resolveengine.artifact.ResolvedArtifactSet;
    -import org.gradle.internal.Try;
     
    -import javax.annotation.Nullable;
     import java.util.Collection;
     import java.util.List;
     import java.util.Map;
    +import java.util.Optional;
     import java.util.function.Function;
     
     public class DefaultTransformationNodeFactory implements TransformationNodeFactory {
    @@ -46,15 +45,14 @@ public Collection getOrCreate(ResolvedArtifactSet artifactSe
         }
     
         @Override
    -    @Nullable
    -    public Try getResultIfCompleted(ComponentArtifactIdentifier artifactId, Transformation transformation) {
    +    public Optional getCompleted(ComponentArtifactIdentifier artifactId, Transformation transformation) {
             List> transformationChain = unpackTransformation(transformation);
             ArtifactTransformKey transformKey = new ArtifactTransformKey(artifactId, transformationChain);
             TransformationNode node = transformations.get(transformKey);
             if (node != null && node.isComplete()) {
    -            return node.getTransformedSubject();
    +            return Optional.of(node);
             }
    -        return null;
    +        return Optional.empty();
         }
     
         private void collectTransformNodes(ResolvedArtifactSet artifactSet, ImmutableList.Builder builder, Function nodeCreator) {
    diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/PrecomputedTransformationResult.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/PrecomputedTransformationResult.java
    index 094ab9d794088..b919bae4b0e5d 100644
    --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/PrecomputedTransformationResult.java
    +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/PrecomputedTransformationResult.java
    @@ -19,14 +19,14 @@
     import org.gradle.internal.Try;
     
     public class PrecomputedTransformationResult implements TransformationResult {
    -    private final Try result;
    +    private final Try transformedSubject;
     
    -    public PrecomputedTransformationResult(Try result) {
    -        this.result = result;
    +    public PrecomputedTransformationResult(Try transformedSubject) {
    +        this.transformedSubject = transformedSubject;
         }
     
         @Override
    -    public Try getResult() {
    -        return result;
    +    public Try getTransformedSubject() {
    +        return transformedSubject;
         }
     }
    diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/TransformationNodeFactory.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/TransformationNodeFactory.java
    index e8f7a2bf73bc0..50c77ca68bd9c 100644
    --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/TransformationNodeFactory.java
    +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/TransformationNodeFactory.java
    @@ -18,14 +18,12 @@
     
     import org.gradle.api.artifacts.component.ComponentArtifactIdentifier;
     import org.gradle.api.internal.artifacts.ivyservice.resolveengine.artifact.ResolvedArtifactSet;
    -import org.gradle.internal.Try;
     
    -import javax.annotation.Nullable;
     import java.util.Collection;
    +import java.util.Optional;
     
     public interface TransformationNodeFactory {
         Collection getOrCreate(ResolvedArtifactSet artifactSet, Transformation transformation, ExecutionGraphDependenciesResolver dependenciesResolver);
     
    -    @Nullable
    -    Try getResultIfCompleted(ComponentArtifactIdentifier artifactId, Transformation transformation);
    +    Optional getCompleted(ComponentArtifactIdentifier artifactId, Transformation transformation);
     }
    diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/TransformationOperation.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/TransformationOperation.java
    index 8ef5c2ff91226..b1faf0df7e945 100644
    --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/TransformationOperation.java
    +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/TransformationOperation.java
    @@ -28,7 +28,7 @@ class TransformationOperation implements TransformationResult, RunnableBuildOper
         private final Transformation transformation;
         private final TransformationSubject subject;
         private final ExecutionGraphDependenciesResolver dependenciesResolver;
    -    private Try result;
    +    private Try transformedSubject;
     
         TransformationOperation(Transformation transformation, TransformationSubject subject, ExecutionGraphDependenciesResolver dependenciesResolver) {
             this.transformation = transformation;
    @@ -38,7 +38,7 @@ class TransformationOperation implements TransformationResult, RunnableBuildOper
     
         @Override
         public void run(@Nullable BuildOperationContext context) {
    -        result = transformation.transform(subject, dependenciesResolver, null);
    +        transformedSubject = transformation.transform(subject, dependenciesResolver, null);
         }
     
         @Override
    @@ -50,7 +50,7 @@ public BuildOperationDescriptor.Builder description() {
         }
     
         @Override
    -    public Try getResult() {
    -        return result;
    +    public Try getTransformedSubject() {
    +        return transformedSubject;
         }
     }
    diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/TransformationResult.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/TransformationResult.java
    index e70c5ae94de67..00b62f86b9148 100644
    --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/TransformationResult.java
    +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/TransformationResult.java
    @@ -19,5 +19,5 @@
     import org.gradle.internal.Try;
     
     public interface TransformationResult {
    -    Try getResult();
    +    Try getTransformedSubject();
     }
    diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/TransformingArtifactVisitor.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/TransformingArtifactVisitor.java
    index 95528b2707938..8cc80cdccb5a3 100644
    --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/TransformingArtifactVisitor.java
    +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/TransformingArtifactVisitor.java
    @@ -47,8 +47,8 @@ class TransformingArtifactVisitor implements ArtifactVisitor {
     
         @Override
         public void visitArtifact(DisplayName variantName, AttributeContainer variantAttributes, ResolvableArtifact artifact) {
    -        TransformationResult operation = artifactResults.get(artifact.getId());
    -        operation.getResult().ifSuccessfulOrElse(
    +        TransformationResult result = artifactResults.get(artifact.getId());
    +        result.getTransformedSubject().ifSuccessfulOrElse(
                 transformedSubject -> {
                     ResolvedArtifact sourceArtifact = artifact.toPublicView();
                     for (File output : transformedSubject.getFiles()) {
    @@ -80,7 +80,7 @@ public boolean requireArtifactFiles() {
         @Override
         public void visitFile(ComponentArtifactIdentifier artifactIdentifier, DisplayName variantName, AttributeContainer variantAttributes, File file) {
             TransformationResult operation = fileResults.get(file);
    -        operation.getResult().ifSuccessfulOrElse(
    +        operation.getTransformedSubject().ifSuccessfulOrElse(
                 transformedSubject -> {
                     for (File outputFile : transformedSubject.getFiles()) {
                         visitor.visitFile(new ComponentFileArtifactIdentifier(artifactIdentifier.getComponentIdentifier(), outputFile.getName()), variantName, target, outputFile);
    diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/TransformingAsyncArtifactListener.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/TransformingAsyncArtifactListener.java
    index 88897f89bc361..4f2ae2b1880e4 100644
    --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/TransformingAsyncArtifactListener.java
    +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/TransformingAsyncArtifactListener.java
    @@ -19,12 +19,12 @@
     import org.gradle.api.artifacts.component.ComponentArtifactIdentifier;
     import org.gradle.api.internal.artifacts.ivyservice.resolveengine.artifact.ResolvableArtifact;
     import org.gradle.api.internal.artifacts.ivyservice.resolveengine.artifact.ResolvedArtifactSet;
    -import org.gradle.internal.Try;
     import org.gradle.internal.operations.BuildOperationQueue;
     import org.gradle.internal.operations.RunnableBuildOperation;
     
     import java.io.File;
     import java.util.Map;
    +import java.util.Optional;
     
     class TransformingAsyncArtifactListener implements ResolvedArtifactSet.AsyncArtifactListener {
         private final Map artifactResults;
    @@ -56,9 +56,9 @@ class TransformingAsyncArtifactListener implements ResolvedArtifactSet.AsyncArti
         @Override
         public void artifactAvailable(ResolvableArtifact artifact) {
             ComponentArtifactIdentifier artifactId = artifact.getId();
    -        Try resultIfCompleted = transformationNodeFactory.getResultIfCompleted(artifactId, transformation);
    -        if (resultIfCompleted != null) {
    -            artifactResults.put(artifactId, new PrecomputedTransformationResult(resultIfCompleted));
    +        Optional node = transformationNodeFactory.getCompleted(artifactId, transformation);
    +        if (node.isPresent()) {
    +            artifactResults.put(artifactId, new PrecomputedTransformationResult(node.get().getTransformedSubject()));
             } else {
                 File file = artifact.getFile();
                 TransformationSubject initialSubject = TransformationSubject.initial(artifactId, file);
    diff --git a/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/DefaultArtifactTransformsTest.groovy b/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/DefaultArtifactTransformsTest.groovy
    index bf64b446dd434..c5a9b3b90856a 100644
    --- a/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/DefaultArtifactTransformsTest.groovy
    +++ b/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/DefaultArtifactTransformsTest.groovy
    @@ -50,17 +50,7 @@ class DefaultArtifactTransformsTest extends Specification {
         def consumerSchema = Mock(AttributesSchemaInternal)
         def attributeMatcher = Mock(AttributeMatcher)
         def dependenciesResolver = Stub(ExtraExecutionGraphDependenciesResolverFactory)
    -    def transformationNodeFactory = new TransformationNodeFactory() {
    -        @Override
    -        Collection getOrCreate(ResolvedArtifactSet artifactSet, Transformation transformation, ExecutionGraphDependenciesResolver dependenciesResolver) {
    -            throw new UnsupportedOperationException()
    -        }
    -
    -        @Override
    -        Try getResultIfCompleted(ComponentArtifactIdentifier artifactId, Transformation transformation) {
    -            return null
    -        }
    -    }
    +    def transformationNodeFactory = Mock(TransformationNodeFactory)
         def transforms = new DefaultArtifactTransforms(matchingCache, consumerSchema, AttributeTestUtil.attributesFactory(), transformationNodeFactory)
     
         def "selects producer variant with requested attributes"() {
    @@ -182,6 +172,7 @@ class DefaultArtifactTransformsTest extends Specification {
             }
             _ * transformation.getDisplayName() >> "transform"
             _ * transformation.requiresDependencies() >> false
    +        _ * transformationNodeFactory.getCompleted(_, _) >> Optional.empty()
     
             1 * transformation.transform({ it.files == [sourceArtifactFile]}, _ as ExecutionGraphDependenciesResolver, _) >> Try.successful(TransformationSubject.initial(sourceArtifactId, sourceArtifactFile).createSubjectFromResult(ImmutableList.of(outFile1, outFile2)))
     
    diff --git a/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/TransformingAsyncArtifactListenerTest.groovy b/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/TransformingAsyncArtifactListenerTest.groovy
    index b443f424d169f..fa0006fbd9e16 100644
    --- a/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/TransformingAsyncArtifactListenerTest.groovy
    +++ b/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/TransformingAsyncArtifactListenerTest.groovy
    @@ -51,7 +51,7 @@ class TransformingAsyncArtifactListenerTest extends Specification {
             listener.artifactAvailable(artifact)
     
             then:
    -        1 * transformationNodeFactory.getResultIfCompleted(artifactId, transformation) >> null
    +        1 * transformationNodeFactory.getCompleted(artifactId, transformation) >> null
             1 * transformation.transform({ it.files == [artifactFile] }, _ as ExecutionGraphDependenciesResolver, _)
         }
     
    @@ -60,7 +60,7 @@ class TransformingAsyncArtifactListenerTest extends Specification {
             listener.artifactAvailable(artifact)
     
             then:
    -        1 * transformationNodeFactory.getResultIfCompleted(artifactId, transformation) >> Try.successful(TransformationSubject.initial(artifact.id, artifact.file).createSubjectFromResult(ImmutableList.of()))
    +        1 * transformationNodeFactory.getCompleted(artifactId, transformation) >> Try.successful(TransformationSubject.initial(artifact.id, artifact.file).createSubjectFromResult(ImmutableList.of()))
             0 * transformation.transform(_, _ as ExecutionGraphDependenciesResolver, _)
         }
     }
    
    From 95750f7fd2fdf1f1e97a17b4beaf84a98cf2de15 Mon Sep 17 00:00:00 2001
    From: =?UTF-8?q?L=C3=B3r=C3=A1nt=20Pint=C3=A9r?= 
    Date: Fri, 8 Mar 2019 17:18:58 +0100
    Subject: [PATCH 431/853] Address review comments
    
    - improve comment about snapshot storage optimization
    - fix meaning of isAllowOverlappingOutputs()
    ---
     .../internal/tasks/execution/ExecuteActionsTaskExecuter.java    | 2 +-
     .../internal/artifacts/transform/DefaultTransformerInvoker.java | 2 +-
     .../org/gradle/internal/execution/steps/ResolveChangesStep.java | 2 +-
     .../org/gradle/internal/execution/steps/StoreSnapshotsStep.java | 2 +-
     .../org/gradle/internal/execution/steps/ExecutionTest.groovy    | 2 +-
     .../internal/execution/steps/IncrementalExecutionTest.groovy    | 2 +-
     .../internal/execution/steps/ResolveChangesStepTest.groovy      | 2 +-
     7 files changed, 7 insertions(+), 7 deletions(-)
    
    diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuter.java b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuter.java
    index 1b21776c1c37e..fe48c7ae3b2cf 100644
    --- a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuter.java
    +++ b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuter.java
    @@ -247,7 +247,7 @@ public void visitLocalState(LocalStateVisitor visitor) {
     
             @Override
             public boolean isAllowOverlappingOutputs() {
    -            return false;
    +            return true;
             }
     
             @Override
    diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvoker.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvoker.java
    index a525cf0e84712..e87ba02e1454a 100644
    --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvoker.java
    +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvoker.java
    @@ -329,7 +329,7 @@ public void visitOutputProperties(OutputPropertyVisitor visitor) {
     
             @Override
             public boolean isAllowOverlappingOutputs() {
    -            return true;
    +            return false;
             }
     
             @Override
    diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/ResolveChangesStep.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/ResolveChangesStep.java
    index de466a7f90f63..30442a9955644 100644
    --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/ResolveChangesStep.java
    +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/ResolveChangesStep.java
    @@ -59,7 +59,7 @@ public R execute(IncrementalContext context) {
                                 afterPreviousExecution,
                                 beforeExecution,
                                 work,
    -                            work.isAllowOverlappingOutputs())
    +                            !work.isAllowOverlappingOutputs())
                             )
                             .orElseGet(() -> new RebuildExecutionStateChanges(NO_HISTORY))
                         )
    diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/StoreSnapshotsStep.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/StoreSnapshotsStep.java
    index 211be538832e8..640e7708962b5 100644
    --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/StoreSnapshotsStep.java
    +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/StoreSnapshotsStep.java
    @@ -44,7 +44,7 @@ public CurrentSnapshotResult execute(C context) {
             ImmutableSortedMap finalOutputs = result.getFinalOutputs();
             context.getBeforeExecutionState().ifPresent(beforeExecutionState -> {
                 boolean successful = result.getOutcome().isSuccessful();
    -            // Only persist history if there was no failure, or some output files have been changed
    +            // Do not store snapshots if there was a failure, but the outputs didn't change
                 if (successful
                     || didChangeOutput(context.getAfterPreviousExecutionState(), finalOutputs)) {
                     UnitOfWork work = context.getWork();
    diff --git a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/ExecutionTest.groovy b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/ExecutionTest.groovy
    index 980756f175924..823a675ecbf4e 100644
    --- a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/ExecutionTest.groovy
    +++ b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/ExecutionTest.groovy
    @@ -160,7 +160,7 @@ class ExecutionTest extends Specification {
     
             @Override
             boolean isAllowOverlappingOutputs() {
    -            return true
    +            return false
             }
     
             @Override
    diff --git a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/IncrementalExecutionTest.groovy b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/IncrementalExecutionTest.groovy
    index 973c9ad0670ce..470c85732dcbb 100644
    --- a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/IncrementalExecutionTest.groovy
    +++ b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/IncrementalExecutionTest.groovy
    @@ -753,7 +753,7 @@ class IncrementalExecutionTest extends Specification {
     
                     @Override
                     boolean isAllowOverlappingOutputs() {
    -                    return true
    +                    return false
                     }
     
                     @Override
    diff --git a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/ResolveChangesStepTest.groovy b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/ResolveChangesStepTest.groovy
    index fe8cc8b551679..fbd40b82eba12 100644
    --- a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/ResolveChangesStepTest.groovy
    +++ b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/ResolveChangesStepTest.groovy
    @@ -109,7 +109,7 @@ class ResolveChangesStepTest extends StepSpec {
             1 * context.beforeExecutionState >> Optional.of(beforeExecutionState)
             1 * context.afterPreviousExecutionState >> Optional.of(afterPreviousExecutionState)
             1 * work.allowOverlappingOutputs >> true
    -        1 * changeDetector.detectChanges(afterPreviousExecutionState, beforeExecutionState, work, true) >> changes
    +        1 * changeDetector.detectChanges(afterPreviousExecutionState, beforeExecutionState, work, false) >> changes
             0 * _
         }
     }
    
    From e8619ac91e1b3fa664ac76020787842c2e1b356a Mon Sep 17 00:00:00 2001
    From: Stefan Wolf 
    Date: Fri, 8 Mar 2019 18:36:59 +0100
    Subject: [PATCH 432/853] Rename TransformationNode{Factory -> Registry}
    
    ---
     .../DefaultDependencyManagementServices.java   | 10 +++++-----
     .../internal/artifacts/DependencyServices.java | 12 ++++++------
     .../AttributeMatchingVariantSelector.java      |  8 ++++----
     .../ConsumerProvidedResolvedVariant.java       |  8 ++++----
     .../transform/DefaultArtifactTransforms.java   |  8 ++++----
     ... => DefaultTransformationNodeRegistry.java} |  2 +-
     .../TransformationNodeDependencyResolver.java  |  8 ++++----
     ...ry.java => TransformationNodeRegistry.java} |  2 +-
     .../TransformingAsyncArtifactListener.java     |  8 ++++----
     ...AttributeMatchingVariantSelectorSpec.groovy | 18 +++++++++---------
     .../DefaultArtifactTransformsTest.groovy       |  6 +++---
     ...ransformingAsyncArtifactListenerTest.groovy |  8 ++++----
     12 files changed, 49 insertions(+), 49 deletions(-)
     rename subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/{DefaultTransformationNodeFactory.java => DefaultTransformationNodeRegistry.java} (98%)
     rename subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/{TransformationNodeFactory.java => TransformationNodeRegistry.java} (96%)
    
    diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/DefaultDependencyManagementServices.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/DefaultDependencyManagementServices.java
    index 1fe461f5d5b0b..497d99ccdbd2d 100644
    --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/DefaultDependencyManagementServices.java
    +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/DefaultDependencyManagementServices.java
    @@ -84,7 +84,7 @@
     import org.gradle.api.internal.artifacts.transform.MutableTransformationWorkspaceProvider;
     import org.gradle.api.internal.artifacts.transform.Transformation;
     import org.gradle.api.internal.artifacts.transform.TransformationNode;
    -import org.gradle.api.internal.artifacts.transform.TransformationNodeFactory;
    +import org.gradle.api.internal.artifacts.transform.TransformationNodeRegistry;
     import org.gradle.api.internal.artifacts.transform.TransformationRegistrationFactory;
     import org.gradle.api.internal.artifacts.transform.TransformerInvoker;
     import org.gradle.api.internal.artifacts.type.ArtifactTypeRegistry;
    @@ -200,8 +200,8 @@ OutputFileCollectionFingerprinter createOutputFingerprinter(FileSystemSnapshotte
                 return new OutputFileCollectionFingerprinter(fileSystemSnapshotter);
             }
     
    -        TransformationNodeFactory createTransformationNodeFactory() {
    -            return new TransformationNodeFactory() {
    +        TransformationNodeRegistry createTransformationNodeRegistry() {
    +            return new TransformationNodeRegistry() {
                     @Override
                     public Collection getOrCreate(ResolvedArtifactSet artifactSet, Transformation transformation, ExecutionGraphDependenciesResolver dependenciesResolver) {
                         throw new UnsupportedOperationException("Cannot schedule transforms for build script dependencies");
    @@ -481,7 +481,7 @@ ConfigurationResolver createDependencyResolver(ArtifactDependencyResolver artifa
                                                            ComponentSelectorConverter componentSelectorConverter,
                                                            AttributeContainerSerializer attributeContainerSerializer,
                                                            BuildState currentBuild,
    -                                                       TransformationNodeFactory transformationNodeFactory) {
    +                                                       TransformationNodeRegistry transformationNodeRegistry) {
                 return new ErrorHandlingConfigurationResolver(
                         new ShortCircuitEmptyConfigurationResolver(
                             new DefaultConfigurationResolver(
    @@ -498,7 +498,7 @@ ConfigurationResolver createDependencyResolver(ArtifactDependencyResolver artifa
                                         attributesFactory),
                                     attributesSchema,
                                     attributesFactory,
    -                                transformationNodeFactory
    +                                transformationNodeRegistry
                                 ),
                                 moduleIdentifierFactory,
                                 buildOperationExecutor,
    diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/DependencyServices.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/DependencyServices.java
    index 9043e0c203fc9..b50eb54d8e474 100644
    --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/DependencyServices.java
    +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/DependencyServices.java
    @@ -17,10 +17,10 @@
     package org.gradle.api.internal.artifacts;
     
     import org.gradle.api.internal.artifacts.transform.ArtifactTransformListener;
    -import org.gradle.api.internal.artifacts.transform.DefaultTransformationNodeFactory;
    +import org.gradle.api.internal.artifacts.transform.DefaultTransformationNodeRegistry;
     import org.gradle.api.internal.artifacts.transform.TransformationNodeDependencyResolver;
     import org.gradle.api.internal.artifacts.transform.TransformationNodeExecutor;
    -import org.gradle.api.internal.artifacts.transform.TransformationNodeFactory;
    +import org.gradle.api.internal.artifacts.transform.TransformationNodeRegistry;
     import org.gradle.internal.event.ListenerManager;
     import org.gradle.internal.operations.BuildOperationExecutor;
     import org.gradle.internal.service.ServiceRegistration;
    @@ -56,12 +56,12 @@ ArtifactTransformListener createArtifactTransformListener(ListenerManager listen
                 return listenerManager.getBroadcaster(ArtifactTransformListener.class);
             }
     
    -        TransformationNodeFactory createTransformationNodeFactory() {
    -            return new DefaultTransformationNodeFactory();
    +        TransformationNodeRegistry createTransformationNodeRegistry() {
    +            return new DefaultTransformationNodeRegistry();
             }
     
    -        TransformationNodeDependencyResolver createTransformationNodeDependencyResolver(TransformationNodeFactory transformationNodeFactory) {
    -            return new TransformationNodeDependencyResolver(transformationNodeFactory);
    +        TransformationNodeDependencyResolver createTransformationNodeDependencyResolver(TransformationNodeRegistry transformationNodeRegistry) {
    +            return new TransformationNodeDependencyResolver(transformationNodeRegistry);
             }
     
             TransformationNodeExecutor createTransformationNodeExecutor(BuildOperationExecutor buildOperationExecutor, ArtifactTransformListener transformListener) {
    diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/AttributeMatchingVariantSelector.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/AttributeMatchingVariantSelector.java
    index 4724dc976ac4e..734083c359abc 100644
    --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/AttributeMatchingVariantSelector.java
    +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/AttributeMatchingVariantSelector.java
    @@ -41,7 +41,7 @@ class AttributeMatchingVariantSelector implements VariantSelector {
         private final ConsumerProvidedVariantFinder consumerProvidedVariantFinder;
         private final AttributesSchemaInternal schema;
         private final ImmutableAttributesFactory attributesFactory;
    -    private final TransformationNodeFactory transformationNodeFactory;
    +    private final TransformationNodeRegistry transformationNodeRegistry;
         private final ImmutableAttributes requested;
         private final boolean ignoreWhenNoMatches;
         private final ExtraExecutionGraphDependenciesResolverFactory dependenciesResolver;
    @@ -50,7 +50,7 @@ class AttributeMatchingVariantSelector implements VariantSelector {
             ConsumerProvidedVariantFinder consumerProvidedVariantFinder,
             AttributesSchemaInternal schema,
             ImmutableAttributesFactory attributesFactory,
    -        TransformationNodeFactory transformationNodeFactory,
    +        TransformationNodeRegistry transformationNodeRegistry,
             AttributeContainerInternal requested,
             boolean ignoreWhenNoMatches,
             ExtraExecutionGraphDependenciesResolverFactory dependenciesResolver
    @@ -58,7 +58,7 @@ class AttributeMatchingVariantSelector implements VariantSelector {
             this.consumerProvidedVariantFinder = consumerProvidedVariantFinder;
             this.schema = schema;
             this.attributesFactory = attributesFactory;
    -        this.transformationNodeFactory = transformationNodeFactory;
    +        this.transformationNodeRegistry = transformationNodeRegistry;
             this.requested = requested.asImmutable();
             this.ignoreWhenNoMatches = ignoreWhenNoMatches;
             this.dependenciesResolver = dependenciesResolver;
    @@ -108,7 +108,7 @@ private ResolvedArtifactSet doSelect(ResolvedVariantSet producer) {
                 ResolvedArtifactSet artifacts = result.getLeft().getArtifacts();
                 AttributeContainerInternal attributes = result.getRight().attributes;
                 Transformation transformation = result.getRight().transformation;
    -            return new ConsumerProvidedResolvedVariant(producer.getComponentId(), artifacts, attributes, transformation, dependenciesResolver, transformationNodeFactory);
    +            return new ConsumerProvidedResolvedVariant(producer.getComponentId(), artifacts, attributes, transformation, dependenciesResolver, transformationNodeRegistry);
             }
     
             if (!candidates.isEmpty()) {
    diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/ConsumerProvidedResolvedVariant.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/ConsumerProvidedResolvedVariant.java
    index a05ab11e744d9..2ef5f6c22a750 100644
    --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/ConsumerProvidedResolvedVariant.java
    +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/ConsumerProvidedResolvedVariant.java
    @@ -37,7 +37,7 @@ public class ConsumerProvidedResolvedVariant implements ResolvedArtifactSet {
         private final AttributeContainerInternal attributes;
         private final Transformation transformation;
         private final ExtraExecutionGraphDependenciesResolverFactory resolverFactory;
    -    private final TransformationNodeFactory transformationNodeFactory;
    +    private final TransformationNodeRegistry transformationNodeRegistry;
     
         public ConsumerProvidedResolvedVariant(
             ComponentIdentifier componentIdentifier,
    @@ -45,21 +45,21 @@ public ConsumerProvidedResolvedVariant(
             AttributeContainerInternal target,
             Transformation transformation,
             ExtraExecutionGraphDependenciesResolverFactory dependenciesResolverFactory,
    -        TransformationNodeFactory transformationNodeFactory
    +        TransformationNodeRegistry transformationNodeRegistry
         ) {
             this.componentIdentifier = componentIdentifier;
             this.delegate = delegate;
             this.attributes = target;
             this.transformation = transformation;
             this.resolverFactory = dependenciesResolverFactory;
    -        this.transformationNodeFactory = transformationNodeFactory;
    +        this.transformationNodeRegistry = transformationNodeRegistry;
         }
     
         @Override
         public Completion startVisit(BuildOperationQueue actions, AsyncArtifactListener listener) {
             Map artifactResults = Maps.newConcurrentMap();
             Map fileResults = Maps.newConcurrentMap();
    -        Completion result = delegate.startVisit(actions, new TransformingAsyncArtifactListener(transformation, listener, actions, artifactResults, fileResults, getDependenciesResolver(), transformationNodeFactory));
    +        Completion result = delegate.startVisit(actions, new TransformingAsyncArtifactListener(transformation, listener, actions, artifactResults, fileResults, getDependenciesResolver(), transformationNodeRegistry));
             return new TransformCompletion(result, attributes, artifactResults, fileResults);
         }
     
    diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultArtifactTransforms.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultArtifactTransforms.java
    index f51ac0d18d592..00a1ba658778e 100644
    --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultArtifactTransforms.java
    +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultArtifactTransforms.java
    @@ -24,23 +24,23 @@ public class DefaultArtifactTransforms implements ArtifactTransforms {
         private final ConsumerProvidedVariantFinder consumerProvidedVariantFinder;
         private final AttributesSchemaInternal schema;
         private final ImmutableAttributesFactory attributesFactory;
    -    private final TransformationNodeFactory transformationNodeFactory;
    +    private final TransformationNodeRegistry transformationNodeRegistry;
     
         public DefaultArtifactTransforms(
             ConsumerProvidedVariantFinder consumerProvidedVariantFinder,
             AttributesSchemaInternal schema,
             ImmutableAttributesFactory attributesFactory,
    -        TransformationNodeFactory transformationNodeFactory
    +        TransformationNodeRegistry transformationNodeRegistry
         ) {
             this.consumerProvidedVariantFinder = consumerProvidedVariantFinder;
             this.schema = schema;
             this.attributesFactory = attributesFactory;
    -        this.transformationNodeFactory = transformationNodeFactory;
    +        this.transformationNodeRegistry = transformationNodeRegistry;
         }
     
         @Override
         public VariantSelector variantSelector(AttributeContainerInternal consumerAttributes, boolean allowNoMatchingVariants, ExtraExecutionGraphDependenciesResolverFactory dependenciesResolver) {
    -        return new AttributeMatchingVariantSelector(consumerProvidedVariantFinder, schema, attributesFactory, transformationNodeFactory, consumerAttributes.asImmutable(), allowNoMatchingVariants, dependenciesResolver);
    +        return new AttributeMatchingVariantSelector(consumerProvidedVariantFinder, schema, attributesFactory, transformationNodeRegistry, consumerAttributes.asImmutable(), allowNoMatchingVariants, dependenciesResolver);
         }
     
     }
    diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformationNodeFactory.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformationNodeRegistry.java
    similarity index 98%
    rename from subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformationNodeFactory.java
    rename to subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformationNodeRegistry.java
    index b3bb52112494e..e8aac06dfb290 100644
    --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformationNodeFactory.java
    +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformationNodeRegistry.java
    @@ -30,7 +30,7 @@
     import java.util.Optional;
     import java.util.function.Function;
     
    -public class DefaultTransformationNodeFactory implements TransformationNodeFactory {
    +public class DefaultTransformationNodeRegistry implements TransformationNodeRegistry {
         private final Map transformations = Maps.newConcurrentMap();
     
         @Override
    diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/TransformationNodeDependencyResolver.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/TransformationNodeDependencyResolver.java
    index 7ff7c41ed1636..0f8f0bdd4b194 100644
    --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/TransformationNodeDependencyResolver.java
    +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/TransformationNodeDependencyResolver.java
    @@ -27,17 +27,17 @@
      * Resolves dependencies to {@link TransformationNode} objects.
      */
     public class TransformationNodeDependencyResolver implements DependencyResolver {
    -    private final TransformationNodeFactory transformationNodeFactory;
    +    private final TransformationNodeRegistry transformationNodeRegistry;
     
    -    public TransformationNodeDependencyResolver(TransformationNodeFactory transformationNodeFactory) {
    -        this.transformationNodeFactory = transformationNodeFactory;
    +    public TransformationNodeDependencyResolver(TransformationNodeRegistry transformationNodeRegistry) {
    +        this.transformationNodeRegistry = transformationNodeRegistry;
         }
     
         @Override
         public boolean resolve(Task task, Object node, Action resolveAction) {
             if (node instanceof DefaultTransformationDependency) {
                 DefaultTransformationDependency transformation = (DefaultTransformationDependency) node;
    -            Collection transformations = transformationNodeFactory.getOrCreate(transformation.getArtifacts(), transformation.getTransformation(), transformation.getDependenciesResolver());
    +            Collection transformations = transformationNodeRegistry.getOrCreate(transformation.getArtifacts(), transformation.getTransformation(), transformation.getDependenciesResolver());
                 for (TransformationNode transformationNode : transformations) {
                     resolveAction.execute(transformationNode);
                 }
    diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/TransformationNodeFactory.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/TransformationNodeRegistry.java
    similarity index 96%
    rename from subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/TransformationNodeFactory.java
    rename to subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/TransformationNodeRegistry.java
    index 50c77ca68bd9c..11f7a71821467 100644
    --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/TransformationNodeFactory.java
    +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/TransformationNodeRegistry.java
    @@ -22,7 +22,7 @@
     import java.util.Collection;
     import java.util.Optional;
     
    -public interface TransformationNodeFactory {
    +public interface TransformationNodeRegistry {
         Collection getOrCreate(ResolvedArtifactSet artifactSet, Transformation transformation, ExecutionGraphDependenciesResolver dependenciesResolver);
     
         Optional getCompleted(ComponentArtifactIdentifier artifactId, Transformation transformation);
    diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/TransformingAsyncArtifactListener.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/TransformingAsyncArtifactListener.java
    index 4f2ae2b1880e4..e6f3f8aa3cc40 100644
    --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/TransformingAsyncArtifactListener.java
    +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/TransformingAsyncArtifactListener.java
    @@ -30,7 +30,7 @@ class TransformingAsyncArtifactListener implements ResolvedArtifactSet.AsyncArti
         private final Map artifactResults;
         private final Map fileResults;
         private final ExecutionGraphDependenciesResolver dependenciesResolver;
    -    private final TransformationNodeFactory transformationNodeFactory;
    +    private final TransformationNodeRegistry transformationNodeRegistry;
         private final BuildOperationQueue actions;
         private final ResolvedArtifactSet.AsyncArtifactListener delegate;
         private final Transformation transformation;
    @@ -42,7 +42,7 @@ class TransformingAsyncArtifactListener implements ResolvedArtifactSet.AsyncArti
             Map artifactResults,
             Map fileResults,
             ExecutionGraphDependenciesResolver dependenciesResolver,
    -        TransformationNodeFactory transformationNodeFactory
    +        TransformationNodeRegistry transformationNodeRegistry
         ) {
             this.artifactResults = artifactResults;
             this.actions = actions;
    @@ -50,13 +50,13 @@ class TransformingAsyncArtifactListener implements ResolvedArtifactSet.AsyncArti
             this.delegate = delegate;
             this.fileResults = fileResults;
             this.dependenciesResolver = dependenciesResolver;
    -        this.transformationNodeFactory = transformationNodeFactory;
    +        this.transformationNodeRegistry = transformationNodeRegistry;
         }
     
         @Override
         public void artifactAvailable(ResolvableArtifact artifact) {
             ComponentArtifactIdentifier artifactId = artifact.getId();
    -        Optional node = transformationNodeFactory.getCompleted(artifactId, transformation);
    +        Optional node = transformationNodeRegistry.getCompleted(artifactId, transformation);
             if (node.isPresent()) {
                 artifactResults.put(artifactId, new PrecomputedTransformationResult(node.get().getTransformedSubject()));
             } else {
    diff --git a/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/AttributeMatchingVariantSelectorSpec.groovy b/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/AttributeMatchingVariantSelectorSpec.groovy
    index 876484ee52153..ad1364de943b3 100644
    --- a/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/AttributeMatchingVariantSelectorSpec.groovy
    +++ b/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/AttributeMatchingVariantSelectorSpec.groovy
    @@ -32,7 +32,7 @@ import spock.lang.Specification
     class AttributeMatchingVariantSelectorSpec extends Specification {
     
         def consumerProvidedVariantFinder = Mock(ConsumerProvidedVariantFinder)
    -    def transformationNodeFactory = Mock(TransformationNodeFactory)
    +    def transformationNodeRegistry = Mock(TransformationNodeRegistry)
         def attributeMatcher = Mock(AttributeMatcher)
         def attributesSchema = Mock(AttributesSchemaInternal) {
             withProducer(_) >> attributeMatcher
    @@ -56,7 +56,7 @@ class AttributeMatchingVariantSelectorSpec extends Specification {
         def 'direct match on variant means no finder interaction'() {
             given:
             def resolvedArtifactSet = Mock(ResolvedArtifactSet)
    -        def selector = new AttributeMatchingVariantSelector(consumerProvidedVariantFinder, attributesSchema, attributesFactory, transformationNodeFactory, requestedAttributes, false, dependenciesResolverFactory)
    +        def selector = new AttributeMatchingVariantSelector(consumerProvidedVariantFinder, attributesSchema, attributesFactory, transformationNodeRegistry, requestedAttributes, false, dependenciesResolverFactory)
     
             when:
             def result = selector.select(variantSet)
    @@ -74,7 +74,7 @@ class AttributeMatchingVariantSelectorSpec extends Specification {
                 asDescribable() >> Describables.of('other mocked variant')
                 getAttributes() >> otherVariantAttributes
             }
    -        def selector = new AttributeMatchingVariantSelector(consumerProvidedVariantFinder, attributesSchema, attributesFactory, transformationNodeFactory, requestedAttributes, false, dependenciesResolverFactory)
    +        def selector = new AttributeMatchingVariantSelector(consumerProvidedVariantFinder, attributesSchema, attributesFactory, transformationNodeRegistry, requestedAttributes, false, dependenciesResolverFactory)
     
             when:
             def result = selector.select(variantSet)
    @@ -107,7 +107,7 @@ class AttributeMatchingVariantSelectorSpec extends Specification {
     
         def 'selecting a transform results in added DefaultTransformationDependency'() {
             given:
    -        def selector = new AttributeMatchingVariantSelector(consumerProvidedVariantFinder, attributesSchema, attributesFactory, transformationNodeFactory, requestedAttributes, false, dependenciesResolverFactory)
    +        def selector = new AttributeMatchingVariantSelector(consumerProvidedVariantFinder, attributesSchema, attributesFactory, transformationNodeRegistry, requestedAttributes, false, dependenciesResolverFactory)
     
             when:
             def result = selector.select(variantSet)
    @@ -153,7 +153,7 @@ class AttributeMatchingVariantSelectorSpec extends Specification {
             }
             def transform1 = Mock(Transformation)
             def transform2 = Mock(Transformation)
    -        def selector = new AttributeMatchingVariantSelector(consumerProvidedVariantFinder, attributesSchema, attributesFactory, transformationNodeFactory, requestedAttributes, false, dependenciesResolverFactory)
    +        def selector = new AttributeMatchingVariantSelector(consumerProvidedVariantFinder, attributesSchema, attributesFactory, transformationNodeRegistry, requestedAttributes, false, dependenciesResolverFactory)
     
             when:
             def result = selector.select(multiVariantSet)
    @@ -204,7 +204,7 @@ class AttributeMatchingVariantSelectorSpec extends Specification {
             }
             def transform1 = Mock(Transformation)
             def transform2 = Mock(Transformation)
    -        def selector = new AttributeMatchingVariantSelector(consumerProvidedVariantFinder, attributesSchema, attributesFactory, transformationNodeFactory, requestedAttributes, false, dependenciesResolverFactory)
    +        def selector = new AttributeMatchingVariantSelector(consumerProvidedVariantFinder, attributesSchema, attributesFactory, transformationNodeRegistry, requestedAttributes, false, dependenciesResolverFactory)
     
             when:
             def result = selector.select(multiVariantSet)
    @@ -261,7 +261,7 @@ class AttributeMatchingVariantSelectorSpec extends Specification {
             def transform1 = Mock(Transformation)
             def transform2 = Mock(Transformation)
             def transform3 = Mock(Transformation)
    -        def selector = new AttributeMatchingVariantSelector(consumerProvidedVariantFinder, attributesSchema, attributesFactory, transformationNodeFactory, requestedAttributes, false, dependenciesResolverFactory)
    +        def selector = new AttributeMatchingVariantSelector(consumerProvidedVariantFinder, attributesSchema, attributesFactory, transformationNodeRegistry, requestedAttributes, false, dependenciesResolverFactory)
     
             when:
             def result = selector.select(multiVariantSet)
    @@ -321,7 +321,7 @@ class AttributeMatchingVariantSelectorSpec extends Specification {
             def transform1 = Mock(Transformation)
             def transform2 = Mock(Transformation)
             def transform3 = Mock(Transformation)
    -        def selector = new AttributeMatchingVariantSelector(consumerProvidedVariantFinder, attributesSchema, attributesFactory, transformationNodeFactory, requestedAttributes, false, dependenciesResolverFactory)
    +        def selector = new AttributeMatchingVariantSelector(consumerProvidedVariantFinder, attributesSchema, attributesFactory, transformationNodeRegistry, requestedAttributes, false, dependenciesResolverFactory)
     
             when:
             def result = selector.select(multiVariantSet)
    @@ -381,7 +381,7 @@ class AttributeMatchingVariantSelectorSpec extends Specification {
             def transform1 = Mock(Transformation)
             def transform2 = Mock(Transformation)
             def transform3 = Mock(Transformation)
    -        def selector = new AttributeMatchingVariantSelector(consumerProvidedVariantFinder, attributesSchema, attributesFactory, transformationNodeFactory, requestedAttributes, false, dependenciesResolverFactory)
    +        def selector = new AttributeMatchingVariantSelector(consumerProvidedVariantFinder, attributesSchema, attributesFactory, transformationNodeRegistry, requestedAttributes, false, dependenciesResolverFactory)
     
             when:
             def result = selector.select(multiVariantSet)
    diff --git a/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/DefaultArtifactTransformsTest.groovy b/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/DefaultArtifactTransformsTest.groovy
    index c5a9b3b90856a..93efcd140c144 100644
    --- a/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/DefaultArtifactTransformsTest.groovy
    +++ b/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/DefaultArtifactTransformsTest.groovy
    @@ -50,8 +50,8 @@ class DefaultArtifactTransformsTest extends Specification {
         def consumerSchema = Mock(AttributesSchemaInternal)
         def attributeMatcher = Mock(AttributeMatcher)
         def dependenciesResolver = Stub(ExtraExecutionGraphDependenciesResolverFactory)
    -    def transformationNodeFactory = Mock(TransformationNodeFactory)
    -    def transforms = new DefaultArtifactTransforms(matchingCache, consumerSchema, AttributeTestUtil.attributesFactory(), transformationNodeFactory)
    +    def transformationNodeRegistry = Mock(TransformationNodeRegistry)
    +    def transforms = new DefaultArtifactTransforms(matchingCache, consumerSchema, AttributeTestUtil.attributesFactory(), transformationNodeRegistry)
     
         def "selects producer variant with requested attributes"() {
             def variant1 = resolvedVariant()
    @@ -172,7 +172,7 @@ class DefaultArtifactTransformsTest extends Specification {
             }
             _ * transformation.getDisplayName() >> "transform"
             _ * transformation.requiresDependencies() >> false
    -        _ * transformationNodeFactory.getCompleted(_, _) >> Optional.empty()
    +        _ * transformationNodeRegistry.getCompleted(_, _) >> Optional.empty()
     
             1 * transformation.transform({ it.files == [sourceArtifactFile]}, _ as ExecutionGraphDependenciesResolver, _) >> Try.successful(TransformationSubject.initial(sourceArtifactId, sourceArtifactFile).createSubjectFromResult(ImmutableList.of(outFile1, outFile2)))
     
    diff --git a/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/TransformingAsyncArtifactListenerTest.groovy b/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/TransformingAsyncArtifactListenerTest.groovy
    index fa0006fbd9e16..762a837002b7d 100644
    --- a/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/TransformingAsyncArtifactListenerTest.groovy
    +++ b/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/TransformingAsyncArtifactListenerTest.groovy
    @@ -28,8 +28,8 @@ import org.gradle.testing.internal.util.Specification
     class TransformingAsyncArtifactListenerTest extends Specification {
         def transformation = Mock(Transformation)
         def operationQueue = Mock(BuildOperationQueue)
    -    def transformationNodeFactory = Mock(TransformationNodeFactory)
    -    def listener  = new TransformingAsyncArtifactListener(transformation, null, operationQueue, Maps.newHashMap(), Maps.newHashMap(), Mock(ExecutionGraphDependenciesResolver), transformationNodeFactory)
    +    def transformationNodeRegistry = Mock(TransformationNodeRegistry)
    +    def listener  = new TransformingAsyncArtifactListener(transformation, null, operationQueue, Maps.newHashMap(), Maps.newHashMap(), Mock(ExecutionGraphDependenciesResolver), transformationNodeRegistry)
         def file = new File("foo")
         def artifactFile = new File("foo-artifact")
         def artifactId = Stub(ComponentArtifactIdentifier)
    @@ -51,7 +51,7 @@ class TransformingAsyncArtifactListenerTest extends Specification {
             listener.artifactAvailable(artifact)
     
             then:
    -        1 * transformationNodeFactory.getCompleted(artifactId, transformation) >> null
    +        1 * transformationNodeRegistry.getCompleted(artifactId, transformation) >> null
             1 * transformation.transform({ it.files == [artifactFile] }, _ as ExecutionGraphDependenciesResolver, _)
         }
     
    @@ -60,7 +60,7 @@ class TransformingAsyncArtifactListenerTest extends Specification {
             listener.artifactAvailable(artifact)
     
             then:
    -        1 * transformationNodeFactory.getCompleted(artifactId, transformation) >> Try.successful(TransformationSubject.initial(artifact.id, artifact.file).createSubjectFromResult(ImmutableList.of()))
    +        1 * transformationNodeRegistry.getCompleted(artifactId, transformation) >> Try.successful(TransformationSubject.initial(artifact.id, artifact.file).createSubjectFromResult(ImmutableList.of()))
             0 * transformation.transform(_, _ as ExecutionGraphDependenciesResolver, _)
         }
     }
    
    From a44148aa0c48ce0ac5dfbf2fcca9f70f0dcc3bde Mon Sep 17 00:00:00 2001
    From: Louis Jacomet 
    Date: Fri, 8 Mar 2019 18:37:43 +0100
    Subject: [PATCH 433/853] Prefer equals over ==
    
    Usage of == is too dependent on the underlying implementation.
    
    Issue #8721
    ---
     .../artifacts/transform/AttributeMatchingVariantSelector.java   | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/AttributeMatchingVariantSelector.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/AttributeMatchingVariantSelector.java
    index 8fa889f15b15c..c51a529f1fa85 100644
    --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/AttributeMatchingVariantSelector.java
    +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/AttributeMatchingVariantSelector.java
    @@ -173,7 +173,7 @@ private List>
             List matches = matcher.matches(candidateAttributes, componentRequested);
             if (matches.size() == 1) {
                 AttributeContainerInternal singleMatch = matches.get(0);
    -            return candidates.stream().filter(pair -> pair.getRight().attributes == singleMatch).collect(Collectors.toList());
    +            return candidates.stream().filter(pair -> pair.getRight().attributes.equals(singleMatch)).collect(Collectors.toList());
             } else if (matches.size() > 0 && matches.size() < candidates.size()) {
                 // We know all are compatibles, so this is only possible if some disambiguation happens but not getting us to 1 candidate
                 return candidates.stream().filter(pair -> matches.contains(pair.getRight().attributes)).collect(Collectors.toList());
    
    From 71855a58e1fdc3b0f509a29ed1ccbba05fd065cd Mon Sep 17 00:00:00 2001
    From: Stefan Wolf 
    Date: Fri, 8 Mar 2019 18:46:08 +0100
    Subject: [PATCH 434/853] Describe why we run an artifact transform on the same
     thread
    
    without using the build operation queue.
    ---
     .../TransformingAsyncArtifactListener.java        | 15 ++++++++++-----
     1 file changed, 10 insertions(+), 5 deletions(-)
    
    diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/TransformingAsyncArtifactListener.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/TransformingAsyncArtifactListener.java
    index e6f3f8aa3cc40..0e1e47fa66307 100644
    --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/TransformingAsyncArtifactListener.java
    +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/TransformingAsyncArtifactListener.java
    @@ -64,11 +64,16 @@ public void artifactAvailable(ResolvableArtifact artifact) {
                 TransformationSubject initialSubject = TransformationSubject.initial(artifactId, file);
                 TransformationOperation operation = new TransformationOperation(transformation, initialSubject, dependenciesResolver);
                 artifactResults.put(artifactId, operation);
    -            // We expect artifact transformations to be executed in a scheduled way,
    -            // so at this point we take the result from the in-memory cache.
    -            // Artifact transformations are always executed scheduled via the execution graph when the transformed component is declared as an input.
    -            // Using the BuildOperationQueue here to only realize that the result of the transformation is from the in-memory has a performance impact,
    -            // so we executing the (no-op) operation in place.
    +            // If we are here, then the transform has not been scheduled.
    +            // So either
    +            //   1) the transformed variant is not declared as an input for a work item or resolved at configuration time, or
    +            //   2) the artifact to transform is an external artifact.
    +            // For 1), we don't do any performance optimizations since transformed variants should be declared as input to some work.
    +            // For 2), either the artifact has just been downloaded or it was already downloaded earlier.
    +            // If it has just been downloaded, then, since downloads happen in parallel, we are already on a worker thread and we use it to execute the transform.
    +            // If it has been downloaded earlier, then there is a high chance that the transformed artifact is already in a Gradle user home workspace and up-to-date.
    +            // Using the BuildOperationQueue here to only realize that the result of the transformation is up-to-date in the Gradle user home workspace has a performance impact,
    +            // so we are executing the up-to-date transform operation in place.
                 operation.run(null);
             }
         }
    
    From bb9eafee591181c97bd26e80502eb8fc1386fbab Mon Sep 17 00:00:00 2001
    From: =?UTF-8?q?L=C3=B3r=C3=A1nt=20Pint=C3=A9r?= 
    Date: Fri, 8 Mar 2019 18:53:46 +0100
    Subject: [PATCH 435/853] Fix IncrementalExecutionTest
    
    ---
     .../execution/steps/ExecutionTest.groovy      | 240 ------------------
     .../steps/IncrementalExecutionTest.groovy     | 109 ++++++--
     2 files changed, 81 insertions(+), 268 deletions(-)
     delete mode 100644 subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/ExecutionTest.groovy
    
    diff --git a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/ExecutionTest.groovy b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/ExecutionTest.groovy
    deleted file mode 100644
    index 823a675ecbf4e..0000000000000
    --- a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/ExecutionTest.groovy
    +++ /dev/null
    @@ -1,240 +0,0 @@
    -/*
    - * Copyright 2018 the original author or authors.
    - *
    - * Licensed under the Apache License, Version 2.0 (the "License");
    - * you may not use this file except in compliance with the License.
    - * You may obtain a copy of the License at
    - *
    - *      http://www.apache.org/licenses/LICENSE-2.0
    - *
    - * Unless required by applicable law or agreed to in writing, software
    - * distributed under the License is distributed on an "AS IS" BASIS,
    - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    - * See the License for the specific language governing permissions and
    - * limitations under the License.
    - */
    -
    -package org.gradle.internal.execution.steps
    -
    -import com.google.common.collect.ImmutableSortedMap
    -import org.gradle.api.BuildCancelledException
    -import org.gradle.initialization.DefaultBuildCancellationToken
    -import org.gradle.internal.execution.CacheHandler
    -import org.gradle.internal.execution.ExecutionException
    -import org.gradle.internal.execution.ExecutionOutcome
    -import org.gradle.internal.execution.IncrementalChangesContext
    -import org.gradle.internal.execution.OutputChangeListener
    -import org.gradle.internal.execution.UnitOfWork
    -import org.gradle.internal.execution.history.AfterPreviousExecutionState
    -import org.gradle.internal.execution.history.BeforeExecutionState
    -import org.gradle.internal.execution.history.ExecutionHistoryStore
    -import org.gradle.internal.execution.history.changes.ExecutionStateChanges
    -import org.gradle.internal.fingerprint.CurrentFileCollectionFingerprint
    -import spock.lang.Specification
    -
    -import java.time.Duration
    -import java.util.function.Supplier
    -
    -class ExecutionTest extends Specification {
    -
    -    def outputChangeListener = Mock(OutputChangeListener)
    -    def cancellationToken = new DefaultBuildCancellationToken()
    -    def executionStep = new CatchExceptionStep(
    -        new CancelExecutionStep(cancellationToken,
    -            new BroadcastChangingOutputsStep(outputChangeListener,
    -                new ExecuteStep()
    -            )
    -        )
    -    )
    -
    -    def "executes the unit of work with outcome: #outcome"() {
    -        def unitOfWork = new TestUnitOfWork({ -> outcome })
    -        when:
    -        def result = execute { -> unitOfWork}
    -
    -        then:
    -        unitOfWork.executed
    -        result.outcome.get() == outcome
    -
    -        1 * outputChangeListener.beforeOutputChange()
    -        0 * _
    -
    -        where:
    -        outcome << [ExecutionOutcome.EXECUTED_NON_INCREMENTALLY, ExecutionOutcome.EXECUTED_INCREMENTALLY]
    -    }
    -
    -    def "reports no work done"() {
    -        when:
    -        def result = execute { ->
    -            new TestUnitOfWork({ ->
    -                return ExecutionOutcome.UP_TO_DATE
    -            })
    -        }
    -
    -        then:
    -        result.outcome.get() == ExecutionOutcome.UP_TO_DATE
    -
    -        1 * outputChangeListener.beforeOutputChange()
    -        0 * _
    -    }
    -
    -    def "catches failures"() {
    -        def failure = new RuntimeException("broken")
    -        def unitOfWork = new TestUnitOfWork({ ->
    -            throw failure
    -        })
    -
    -        when:
    -        def result = execute { -> unitOfWork }
    -
    -        then:
    -        result.outcome.failure.get() instanceof ExecutionException
    -        result.outcome.failure.get().cause == failure
    -        result.outcome.failure.get().message.contains(unitOfWork.displayName)
    -
    -        1 * outputChangeListener.beforeOutputChange()
    -        0 * _
    -    }
    -
    -    def "invalidates only changing outputs"() {
    -        def changingOutputs = ['some/location']
    -        def unitOfWork = new TestUnitOfWork({ -> ExecutionOutcome.EXECUTED_NON_INCREMENTALLY }, changingOutputs)
    -
    -        when:
    -        def result = execute { -> unitOfWork }
    -
    -        then:
    -        result.outcome.get() == ExecutionOutcome.EXECUTED_NON_INCREMENTALLY
    -
    -        1 * outputChangeListener.beforeOutputChange(changingOutputs)
    -        0 * _
    -    }
    -
    -    def "fails the execution when build has been cancelled"() {
    -        def unitOfWork = new TestUnitOfWork({ -> ExecutionOutcome.EXECUTED_NON_INCREMENTALLY })
    -
    -        when:
    -        cancellationToken.cancel()
    -        def result = execute { -> unitOfWork }
    -
    -        then:
    -        result.outcome.failure.get() instanceof ExecutionException
    -        result.outcome.failure.get().cause instanceof BuildCancelledException
    -
    -        1 * outputChangeListener.beforeOutputChange()
    -        0 * _
    -    }
    -
    -    static class TestUnitOfWork implements UnitOfWork {
    -
    -        private final Supplier work
    -        private final Iterable changingOutputs
    -
    -        TestUnitOfWork(Supplier work, Iterable changingOutputs = null) {
    -            this.changingOutputs = changingOutputs
    -            this.work = work
    -        }
    -
    -        boolean executed
    -
    -        @Override
    -        ExecutionOutcome execute(IncrementalChangesContext context) {
    -            executed = true
    -            return work.get()
    -        }
    -
    -        @Override
    -        ExecutionHistoryStore getExecutionHistoryStore() {
    -            throw new UnsupportedOperationException()
    -        }
    -
    -        @Override
    -        Optional getTimeout() {
    -            throw new UnsupportedOperationException()
    -        }
    -
    -        @Override
    -        void visitOutputProperties(OutputPropertyVisitor visitor) {
    -            throw new UnsupportedOperationException()
    -        }
    -
    -        @Override
    -        boolean isAllowOverlappingOutputs() {
    -            return false
    -        }
    -
    -        @Override
    -        long markExecutionTime() {
    -            throw new UnsupportedOperationException()
    -        }
    -
    -        @Override
    -        void visitLocalState(LocalStateVisitor visitor) {
    -            throw new UnsupportedOperationException()
    -        }
    -
    -        @Override
    -        void outputsRemovedAfterFailureToLoadFromCache() {
    -            throw new UnsupportedOperationException()
    -        }
    -
    -        @Override
    -        CacheHandler createCacheHandler() {
    -            throw new UnsupportedOperationException()
    -        }
    -
    -        @Override
    -        Optional> getChangingOutputs() {
    -            Optional.ofNullable(changingOutputs)
    -        }
    -
    -        @Override
    -        ImmutableSortedMap snapshotAfterOutputsGenerated() {
    -            throw new UnsupportedOperationException()
    -        }
    -
    -        @Override
    -        String getIdentity() {
    -            throw new UnsupportedOperationException()
    -        }
    -
    -        @Override
    -        void visitOutputTrees(CacheableTreeVisitor visitor) {
    -            throw new UnsupportedOperationException()
    -        }
    -
    -        @Override
    -        String getDisplayName() {
    -            "Test unit of work"
    -        }
    -    }
    -
    -    def execute(Supplier work) {
    -        executionStep.execute(new IncrementalChangesContext() {
    -            @Override
    -            Optional getChanges() {
    -                return Optional.empty()
    -            }
    -
    -            @Override
    -            Optional getRebuildReason() {
    -                return Optional.empty()
    -            }
    -
    -            @Override
    -            Optional getAfterPreviousExecutionState() {
    -                return Optional.empty()
    -            }
    -
    -            @Override
    -            Optional getBeforeExecutionState() {
    -                return Optional.empty()
    -            }
    -
    -            @Override
    -            UnitOfWork getWork() {
    -                return work.get()
    -            }
    -        })
    -    }
    -}
    diff --git a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/IncrementalExecutionTest.groovy b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/IncrementalExecutionTest.groovy
    index 470c85732dcbb..eb1a26f367405 100644
    --- a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/IncrementalExecutionTest.groovy
    +++ b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/IncrementalExecutionTest.groovy
    @@ -31,14 +31,17 @@ import org.gradle.internal.execution.ExecutionOutcome
     import org.gradle.internal.execution.IncrementalChangesContext
     import org.gradle.internal.execution.IncrementalContext
     import org.gradle.internal.execution.OutputChangeListener
    +import org.gradle.internal.execution.Result
     import org.gradle.internal.execution.TestExecutionHistoryStore
    +import org.gradle.internal.execution.TestOutputFilesRepository
     import org.gradle.internal.execution.UnitOfWork
     import org.gradle.internal.execution.UpToDateResult
     import org.gradle.internal.execution.WorkExecutor
     import org.gradle.internal.execution.history.AfterPreviousExecutionState
     import org.gradle.internal.execution.history.BeforeExecutionState
     import org.gradle.internal.execution.history.ExecutionHistoryStore
    -import org.gradle.internal.execution.history.changes.ExecutionStateChanges
    +import org.gradle.internal.execution.history.changes.DefaultExecutionStateChangeDetector
    +import org.gradle.internal.execution.history.impl.DefaultBeforeExecutionState
     import org.gradle.internal.execution.impl.DefaultWorkExecutor
     import org.gradle.internal.file.TreeType
     import org.gradle.internal.fingerprint.CurrentFileCollectionFingerprint
    @@ -58,7 +61,6 @@ import org.gradle.test.fixtures.file.TestFile
     import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider
     import org.gradle.testing.internal.util.Specification
     import org.junit.Rule
    -import spock.lang.Ignore
     
     import java.time.Duration
     import java.util.function.Supplier
    @@ -66,8 +68,6 @@ import java.util.function.Supplier
     import static org.gradle.internal.execution.ExecutionOutcome.EXECUTED_NON_INCREMENTALLY
     import static org.gradle.internal.execution.ExecutionOutcome.UP_TO_DATE
     
    -// FIXME:lptr
    -@Ignore
     class IncrementalExecutionTest extends Specification {
     
         @Rule
    @@ -97,6 +97,7 @@ class IncrementalExecutionTest extends Specification {
                 return HashCode.fromInt(1234)
             }
         }
    +    def outputFilesRepository = new TestOutputFilesRepository()
         def valueSnapshotter = new DefaultValueSnapshotter(classloaderHierarchyHasher)
     
         final outputFile = temporaryFolder.file("output-file")
    @@ -117,18 +118,59 @@ class IncrementalExecutionTest extends Specification {
     
         def unitOfWork = builder.build()
     
    +    def changeDetector = new DefaultExecutionStateChangeDetector()
    +
         WorkExecutor getExecutor() {
    -        new DefaultWorkExecutor(
    -            new SkipUpToDateStep(
    -                new StoreSnapshotsStep(
    -                    new SnapshotOutputsStep(buildInvocationScopeId.getId(),
    -                        new BroadcastChangingOutputsStep(outputChangeListener, delegate)
    +        new DefaultWorkExecutor<>(
    +            new ResolveChangesStep(changeDetector,
    +                new SkipUpToDateStep(
    +                    new RecordOutputsStep(outputFilesRepository,
    +                        new StoreSnapshotsStep(
    +                            new SnapshotOutputsStep(buildInvocationScopeId.getId(),
    +                                new CreateOutputsStep(
    +                                    new CatchExceptionStep(
    +                                        new BroadcastChangingOutputsStep(outputChangeListener,
    +                                            new ExecuteStep()
    +                                        )
    +                                    )
    +                                )
    +                            )
    +                        )
                         )
                     )
                 )
             )
         }
     
    +    def "outputs are created"() {
    +        def unitOfWork = builder.withOutputDirs(
    +            dir: [file("outDir")],
    +            dirs: [file("outDir1"), file("outDir2")],
    +        ).withOutputFiles(
    +            "file": [file("parent/outFile")],
    +            "files": [file("parent1/outFile"), file("parent2/outputFile1"), file("parent2/outputFile2")],
    +        ).withWork { ->
    +            EXECUTED_NON_INCREMENTALLY
    +        }.build()
    +
    +        when:
    +        def result = execute(unitOfWork)
    +
    +        then:
    +        result.outcome.get() == EXECUTED_NON_INCREMENTALLY
    +        !result.reused
    +
    +        def allDirs = ["outDir", "outDir1", "outDir2"].collect { file(it) }
    +        def allFiles = ["parent/outFile", "parent1/outFile1", "parent2/outFile1", "parent2/outFile2"].collect { file(it) }
    +        allDirs.each {
    +            assert it.isDirectory()
    +        }
    +        allFiles.each {
    +            assert it.parentFile.isDirectory()
    +            assert !it.exists()
    +        }
    +    }
    +
         def "output snapshots are stored"() {
             when:
             def result = execute(unitOfWork)
    @@ -575,11 +617,11 @@ class IncrementalExecutionTest extends Specification {
             }
         }
     
    -    UpToDateResult outOfDate(UnitOfWork unitOfWork, String... expectedReasons) {
    +    UpToDateResult outOfDate(TestUnitOfWork unitOfWork, String... expectedReasons) {
             return outOfDate(unitOfWork, ImmutableList.copyOf(expectedReasons))
         }
     
    -    UpToDateResult outOfDate(UnitOfWork unitOfWork, List expectedReasons) {
    +    UpToDateResult outOfDate(TestUnitOfWork unitOfWork, List expectedReasons) {
             def result = execute(unitOfWork)
             assert result.outcome.get() == EXECUTED_NON_INCREMENTALLY
             assert !result.reused
    @@ -587,38 +629,37 @@ class IncrementalExecutionTest extends Specification {
             return result
         }
     
    -    UpToDateResult upToDate(UnitOfWork unitOfWork) {
    +    UpToDateResult upToDate(TestUnitOfWork unitOfWork) {
             def result = execute(unitOfWork)
             assert result.outcome.get() == UP_TO_DATE
             return result
         }
     
    -    UpToDateResult execute(UnitOfWork unitOfWork) {
    +    UpToDateResult execute(TestUnitOfWork unitOfWork) {
             fileSystemMirror.beforeBuildFinished()
    -        executor.execute(new IncrementalChangesContext() {
    +
    +        def afterPreviousExecutionState = executionHistoryStore.load(unitOfWork.identity)
    +        def beforeExecutionState = unitOfWork.beforeExecutionState
    +
    +        executor.execute(new IncrementalContext() {
                 @Override
                 UnitOfWork getWork() {
                     return unitOfWork
                 }
     
    -            @Override
    -            Optional getChanges() {
    -                return null
    -            }
    -
                 @Override
                 Optional getRebuildReason() {
    -                return null
    +                Optional.empty()
                 }
     
                 @Override
                 Optional getAfterPreviousExecutionState() {
    -                return null
    +                afterPreviousExecutionState
                 }
     
                 @Override
                 Optional getBeforeExecutionState() {
    -                return null
    +                Optional.of(beforeExecutionState)
                 }
             })
         }
    @@ -649,6 +690,10 @@ class IncrementalExecutionTest extends Specification {
             new UnitOfWorkBuilder()
         }
     
    +    interface TestUnitOfWork extends UnitOfWork {
    +        BeforeExecutionState getBeforeExecutionState()
    +    }
    +
         class UnitOfWorkBuilder {
             private Supplier work = { ->
                 create.each { it ->
    @@ -717,14 +762,11 @@ class IncrementalExecutionTest extends Specification {
                 return this
             }
     
    -        UnitOfWork build() {
    +        TestUnitOfWork build() {
                 def outputFileSpecs = outputFiles.collectEntries { key, value -> [(key): outputFileSpec(*value)] }
                 def outputDirSpecs = outputDirs.collectEntries { key, value -> [(key): outputDirectorySpec(*value)]}
    -            return new UnitOfWork() {
    +            return new TestUnitOfWork() {
                     private final Map outputs = outputFileSpecs + outputDirSpecs
    -                private final ImplementationSnapshot implementationSnapshot = implementation
    -                private final ImmutableList additionalImplementationSnapshots = ImmutableList.of()
    -                Optional changes
     
                     boolean executed
     
    @@ -734,6 +776,17 @@ class IncrementalExecutionTest extends Specification {
                         return work.get()
                     }
     
    +                @Override
    +                BeforeExecutionState getBeforeExecutionState() {
    +                    new DefaultBeforeExecutionState(
    +                        implementation,
    +                        ImmutableList.of(),
    +                        snapshotInputProperties(),
    +                        snapshotInputFiles(),
    +                        snapshotOutputs()
    +                    )
    +                }
    +
                     @Override
                     ExecutionHistoryStore getExecutionHistoryStore() {
                         return IncrementalExecutionTest.this.executionHistoryStore
    @@ -753,7 +806,7 @@ class IncrementalExecutionTest extends Specification {
     
                     @Override
                     boolean isAllowOverlappingOutputs() {
    -                    return false
    +                    return true
                     }
     
                     @Override
    
    From 1ed3cb3c350fac52986edc44f5ac68d61b5e3bb8 Mon Sep 17 00:00:00 2001
    From: Marc Philipp 
    Date: Fri, 8 Mar 2019 14:28:59 +0100
    Subject: [PATCH 436/853] Fix handling of aborted containers with completed
     children
    
    When a container `TestIdentifier` was reported as finished, we reported
    all of its children as skipped, regardless whether they already had been
    completed previously. Now, we only report unstarted children as skipped.
    
    Resolves #8685.
    ---
     .../JUnitPlatformTestExecutionListener.java   |  4 +-
     .../testing/fixture/JUnitCoverage.groovy      |  4 +-
     ...UnitAbortedTestClassIntegrationTest.groovy | 53 +++++++++++++++++++
     .../JUnitPlatformIntegrationTest.groovy       |  5 ++
     .../supportsAssumptionsInRules/build.gradle   | 18 +++++++
     .../java/org/gradle/SkippingRuleTests.java    | 48 +++++++++++++++++
     6 files changed, 129 insertions(+), 3 deletions(-)
     create mode 100644 subprojects/testing-jvm/src/integTest/groovy/org/gradle/testing/junit/JUnitAbortedTestClassIntegrationTest.groovy
     create mode 100644 subprojects/testing-jvm/src/integTest/resources/org/gradle/testing/junit/JUnitAbortedTestClassIntegrationTest/supportsAssumptionsInRules/build.gradle
     create mode 100644 subprojects/testing-jvm/src/integTest/resources/org/gradle/testing/junit/JUnitAbortedTestClassIntegrationTest/supportsAssumptionsInRules/src/test/java/org/gradle/SkippingRuleTests.java
    
    diff --git a/subprojects/testing-junit-platform/src/main/java/org/gradle/api/internal/tasks/testing/junitplatform/JUnitPlatformTestExecutionListener.java b/subprojects/testing-junit-platform/src/main/java/org/gradle/api/internal/tasks/testing/junitplatform/JUnitPlatformTestExecutionListener.java
    index 5c8f0faa6277a..66f68af23fd8d 100644
    --- a/subprojects/testing-junit-platform/src/main/java/org/gradle/api/internal/tasks/testing/junitplatform/JUnitPlatformTestExecutionListener.java
    +++ b/subprojects/testing-junit-platform/src/main/java/org/gradle/api/internal/tasks/testing/junitplatform/JUnitPlatformTestExecutionListener.java
    @@ -121,7 +121,9 @@ private void reportStartedUnlessAlreadyStarted(TestIdentifier testIdentifier) {
         }
     
         private void reportSkipped(TestIdentifier testIdentifier) {
    -        currentTestPlan.getChildren(testIdentifier).forEach(child -> executionSkipped(child));
    +        currentTestPlan.getChildren(testIdentifier).stream()
    +            .filter(child -> !wasStarted(child))
    +            .forEach(child -> executionSkipped(child));
             if (testIdentifier.isTest()) {
                 resultProcessor.completed(getId(testIdentifier), completeEvent(SKIPPED));
             } else if (isClass(testIdentifier)) {
    diff --git a/subprojects/testing-jvm/src/integTest/groovy/org/gradle/testing/fixture/JUnitCoverage.groovy b/subprojects/testing-jvm/src/integTest/groovy/org/gradle/testing/fixture/JUnitCoverage.groovy
    index a4ac8a4a29f1c..80f54e3c51eb2 100644
    --- a/subprojects/testing-jvm/src/integTest/groovy/org/gradle/testing/fixture/JUnitCoverage.groovy
    +++ b/subprojects/testing-jvm/src/integTest/groovy/org/gradle/testing/fixture/JUnitCoverage.groovy
    @@ -25,8 +25,8 @@ import org.gradle.api.JavaVersion
      */
     class JUnitCoverage {
         final static String NEWEST = '4.12'
    -    final static String LATEST_JUPITER_VERSION = '5.3.1'
    -    final static String LATEST_VINTAGE_VERSION = '5.3.1'
    +    final static String LATEST_JUPITER_VERSION = '5.4.0'
    +    final static String LATEST_VINTAGE_VERSION = '5.4.0'
         final static String JUPITER = 'Jupiter:' + LATEST_JUPITER_VERSION
         final static String VINTAGE = 'Vintage:' + LATEST_VINTAGE_VERSION
         final static String[] LARGE_COVERAGE = ['4.0', '4.4', '4.8.2', NEWEST]
    diff --git a/subprojects/testing-jvm/src/integTest/groovy/org/gradle/testing/junit/JUnitAbortedTestClassIntegrationTest.groovy b/subprojects/testing-jvm/src/integTest/groovy/org/gradle/testing/junit/JUnitAbortedTestClassIntegrationTest.groovy
    new file mode 100644
    index 0000000000000..b4cb252327d73
    --- /dev/null
    +++ b/subprojects/testing-jvm/src/integTest/groovy/org/gradle/testing/junit/JUnitAbortedTestClassIntegrationTest.groovy
    @@ -0,0 +1,53 @@
    +/*
    + * Copyright 2019 the original author or authors.
    + *
    + * Licensed under the Apache License, Version 2.0 (the "License");
    + * you may not use this file except in compliance with the License.
    + * You may obtain a copy of the License at
    + *
    + *      http://www.apache.org/licenses/LICENSE-2.0
    + *
    + * Unless required by applicable law or agreed to in writing, software
    + * distributed under the License is distributed on an "AS IS" BASIS,
    + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    + * See the License for the specific language governing permissions and
    + * limitations under the License.
    + */
    +
    +package org.gradle.testing.junit
    +
    +import org.gradle.integtests.fixtures.DefaultTestExecutionResult
    +import org.gradle.integtests.fixtures.TargetCoverage
    +import org.gradle.integtests.fixtures.TestResources
    +import org.gradle.testing.fixture.JUnitMultiVersionIntegrationSpec
    +import org.junit.Rule
    +
    +import static org.gradle.testing.fixture.JUnitCoverage.JUNIT_VINTAGE
    +
    +@TargetCoverage({ JUNIT_VINTAGE })
    +class JUnitAbortedTestClassIntegrationTest extends JUnitMultiVersionIntegrationSpec {
    +
    +    @Rule TestResources resources = new TestResources(temporaryFolder)
    +
    +    def supportsAssumptionsInRules() {
    +        given:
    +        executer.noExtraLogging()
    +        buildFile << """
    +dependencies {
    +    testCompile '$dependencyNotation'
    +}
    +"""
    +
    +        when:
    +        run('test')
    +
    +        then:
    +        def result = new DefaultTestExecutionResult(testDirectory)
    +        result.assertTestClassesExecuted('org.gradle.SkippingRuleTests')
    +        result.testClass('org.gradle.SkippingRuleTests')
    +            .assertTestCount(3, 0, 0)
    +            .assertTestsExecuted('a')
    +            .assertTestsSkipped('b', 'c')
    +    }
    +
    +}
    diff --git a/subprojects/testing-jvm/src/integTest/groovy/org/gradle/testing/junitplatform/JUnitPlatformIntegrationTest.groovy b/subprojects/testing-jvm/src/integTest/groovy/org/gradle/testing/junitplatform/JUnitPlatformIntegrationTest.groovy
    index 79436cf679c15..3ef02086d486a 100644
    --- a/subprojects/testing-jvm/src/integTest/groovy/org/gradle/testing/junitplatform/JUnitPlatformIntegrationTest.groovy
    +++ b/subprojects/testing-jvm/src/integTest/groovy/org/gradle/testing/junitplatform/JUnitPlatformIntegrationTest.groovy
    @@ -20,6 +20,7 @@ import org.gradle.integtests.fixtures.DefaultTestExecutionResult
     import org.gradle.util.Requires
     import org.gradle.util.TestPrecondition
     import spock.lang.Issue
    +import spock.lang.Timeout
     import spock.lang.Unroll
     
     import static org.gradle.testing.fixture.JUnitCoverage.LATEST_JUPITER_VERSION
    @@ -366,6 +367,7 @@ public class StaticInnerTest {
             'excludeEngines' | '"junit-jupiter"'
         }
     
    +    @Timeout(60)
         @Issue('https://github.com/gradle/gradle/issues/6453')
         def "can handle parallel test execution"() {
             given:
    @@ -383,8 +385,11 @@ public class StaticInnerTest {
     
                 import java.util.concurrent.*;
                 import org.junit.jupiter.api.*;
    +            import org.junit.jupiter.api.parallel.*;
                 import static org.junit.jupiter.api.Assertions.*;
    +            import static org.junit.jupiter.api.parallel.ExecutionMode.CONCURRENT;
     
    +            @Execution(CONCURRENT)
                 class Sync {
                     static CountDownLatch LATCH = new CountDownLatch($numTestClasses);
                 }
    diff --git a/subprojects/testing-jvm/src/integTest/resources/org/gradle/testing/junit/JUnitAbortedTestClassIntegrationTest/supportsAssumptionsInRules/build.gradle b/subprojects/testing-jvm/src/integTest/resources/org/gradle/testing/junit/JUnitAbortedTestClassIntegrationTest/supportsAssumptionsInRules/build.gradle
    new file mode 100644
    index 0000000000000..1c9cc4d8975c9
    --- /dev/null
    +++ b/subprojects/testing-jvm/src/integTest/resources/org/gradle/testing/junit/JUnitAbortedTestClassIntegrationTest/supportsAssumptionsInRules/build.gradle
    @@ -0,0 +1,18 @@
    +/*
    + * Copyright 2013 the original author or authors.
    + *
    + * Licensed under the Apache License, Version 2.0 (the "License");
    + * you may not use this file except in compliance with the License.
    + * You may obtain a copy of the License at
    + *
    + *      http://www.apache.org/licenses/LICENSE-2.0
    + *
    + * Unless required by applicable law or agreed to in writing, software
    + * distributed under the License is distributed on an "AS IS" BASIS,
    + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    + * See the License for the specific language governing permissions and
    + * limitations under the License.
    + */
    +
    +apply plugin: 'java'
    +repositories { mavenCentral() }
    diff --git a/subprojects/testing-jvm/src/integTest/resources/org/gradle/testing/junit/JUnitAbortedTestClassIntegrationTest/supportsAssumptionsInRules/src/test/java/org/gradle/SkippingRuleTests.java b/subprojects/testing-jvm/src/integTest/resources/org/gradle/testing/junit/JUnitAbortedTestClassIntegrationTest/supportsAssumptionsInRules/src/test/java/org/gradle/SkippingRuleTests.java
    new file mode 100644
    index 0000000000000..cb76679cfdc60
    --- /dev/null
    +++ b/subprojects/testing-jvm/src/integTest/resources/org/gradle/testing/junit/JUnitAbortedTestClassIntegrationTest/supportsAssumptionsInRules/src/test/java/org/gradle/SkippingRuleTests.java
    @@ -0,0 +1,48 @@
    +/*
    + * Copyright 2019 the original author or authors.
    + *
    + * Licensed under the Apache License, Version 2.0 (the "License");
    + * you may not use this file except in compliance with the License.
    + * You may obtain a copy of the License at
    + *
    + *      http://www.apache.org/licenses/LICENSE-2.0
    + *
    + * Unless required by applicable law or agreed to in writing, software
    + * distributed under the License is distributed on an "AS IS" BASIS,
    + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    + * See the License for the specific language governing permissions and
    + * limitations under the License.
    + */
    +
    +package org.gradle;
    +
    +import org.junit.FixMethodOrder;
    +import org.junit.Rule;
    +import org.junit.Test;
    +import org.junit.rules.MethodRule;
    +
    +import static org.junit.Assume.assumeFalse;
    +import static org.junit.runners.MethodSorters.NAME_ASCENDING;
    +
    +@FixMethodOrder(NAME_ASCENDING)
    +public class SkippingRuleTests {
    +
    +    @Rule
    +    public MethodRule misbehavingSkippingRule = (statement, method, target) -> {
    +        assumeFalse(method.getName().equals("b"));
    +        return statement;
    +    };
    +
    +    @Test
    +    public void a() {
    +    }
    +
    +    @Test
    +    public void b() {
    +    }
    +
    +    @Test
    +    public void c() {
    +    }
    +
    +}
    
    From 52584d70d13c0d850c142f9398b4a298d61aa22d Mon Sep 17 00:00:00 2001
    From: Louis Jacomet 
    Date: Fri, 8 Mar 2019 21:44:23 +0100
    Subject: [PATCH 437/853] Fix test broken by == to equals change
    
    Unfortunately the test used equals containers that were different
    instances.
    This commit fixes the test by using different containers.
    
    Issue #8721
    ---
     .../transform/AttributeMatchingVariantSelectorSpec.groovy       | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    diff --git a/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/AttributeMatchingVariantSelectorSpec.groovy b/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/AttributeMatchingVariantSelectorSpec.groovy
    index 11e30f674a010..df0b6df8895ca 100644
    --- a/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/AttributeMatchingVariantSelectorSpec.groovy
    +++ b/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/AttributeMatchingVariantSelectorSpec.groovy
    @@ -287,7 +287,7 @@ class AttributeMatchingVariantSelectorSpec extends Specification {
             })
             1 * attributeMatcher.matches(_, _) >> Collections.emptyList()
             1 * consumerProvidedVariantFinder.collectConsumerVariants(variantAttributes, requestedAttributes, _) >> { args ->
    -            args[2].matched(requestedAttributes, transform1, 2)
    +            args[2].matched(otherVariantAttributes, transform1, 2)
             }
             1 * consumerProvidedVariantFinder.collectConsumerVariants(otherVariantAttributes, requestedAttributes, _) >> { args ->
                 args[2].matched(variantAttributes, transform2, 3)
    
    From 323c91652a3f2aa56226044c5270dc6e39f78121 Mon Sep 17 00:00:00 2001
    From: Stefan Wolf 
    Date: Fri, 8 Mar 2019 23:20:28 +0100
    Subject: [PATCH 438/853] Fix unit test
    
    ---
     .../transform/TransformingAsyncArtifactListenerTest.groovy  | 6 ++++--
     1 file changed, 4 insertions(+), 2 deletions(-)
    
    diff --git a/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/TransformingAsyncArtifactListenerTest.groovy b/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/TransformingAsyncArtifactListenerTest.groovy
    index 762a837002b7d..4be8ef342405b 100644
    --- a/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/TransformingAsyncArtifactListenerTest.groovy
    +++ b/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/TransformingAsyncArtifactListenerTest.groovy
    @@ -37,6 +37,7 @@ class TransformingAsyncArtifactListenerTest extends Specification {
             getId() >> artifactId
             getFile() >> artifactFile
         }
    +    def node = Mock(TransformationNode)
     
         def "adds file transformations to the build operation queue"() {
             when:
    @@ -51,7 +52,7 @@ class TransformingAsyncArtifactListenerTest extends Specification {
             listener.artifactAvailable(artifact)
     
             then:
    -        1 * transformationNodeRegistry.getCompleted(artifactId, transformation) >> null
    +        1 * transformationNodeRegistry.getCompleted(artifactId, transformation) >> Optional.empty()
             1 * transformation.transform({ it.files == [artifactFile] }, _ as ExecutionGraphDependenciesResolver, _)
         }
     
    @@ -60,7 +61,8 @@ class TransformingAsyncArtifactListenerTest extends Specification {
             listener.artifactAvailable(artifact)
     
             then:
    -        1 * transformationNodeRegistry.getCompleted(artifactId, transformation) >> Try.successful(TransformationSubject.initial(artifact.id, artifact.file).createSubjectFromResult(ImmutableList.of()))
    +        1 * transformationNodeRegistry.getCompleted(artifactId, transformation) >> Optional.of(node)
    +        1 * node.getTransformedSubject() >> Try.successful(TransformationSubject.initial(artifact.id, artifact.file).createSubjectFromResult(ImmutableList.of()))
             0 * transformation.transform(_, _ as ExecutionGraphDependenciesResolver, _)
         }
     }
    
    From dfe45eae5bd72f0fd073897bf9f1e219e99b7fe8 Mon Sep 17 00:00:00 2001
    From: Stefan Wolf 
    Date: Sat, 9 Mar 2019 01:32:09 +0100
    Subject: [PATCH 439/853] Update
     subprojects/execution/src/main/java/org/gradle/internal/execution/steps/StoreSnapshotsStep.java
    
    Co-Authored-By: lptr 
    ---
     .../gradle/internal/execution/steps/StoreSnapshotsStep.java    | 3 ++-
     1 file changed, 2 insertions(+), 1 deletion(-)
    
    diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/StoreSnapshotsStep.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/StoreSnapshotsStep.java
    index 640e7708962b5..171d345a1aa13 100644
    --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/StoreSnapshotsStep.java
    +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/StoreSnapshotsStep.java
    @@ -44,7 +44,8 @@ public CurrentSnapshotResult execute(C context) {
             ImmutableSortedMap finalOutputs = result.getFinalOutputs();
             context.getBeforeExecutionState().ifPresent(beforeExecutionState -> {
                 boolean successful = result.getOutcome().isSuccessful();
    -            // Do not store snapshots if there was a failure, but the outputs didn't change
    +            // We do not store the history if there was a failure and the outputs did not change, since then the next execution can be incremental.
    +            // For example the current execution fails because of a compile failure and for the next execution the source file is fixed, so only the one changed source file needs to be compiled.
                 if (successful
                     || didChangeOutput(context.getAfterPreviousExecutionState(), finalOutputs)) {
                     UnitOfWork work = context.getWork();
    
    From d19f6c1f50307f5fde46a7e8142741ac2ff98db7 Mon Sep 17 00:00:00 2001
    From: Gradleware Git Bot 
    Date: Sat, 9 Mar 2019 02:44:28 +0100
    Subject: [PATCH 440/853] Publish 5.3-20190309012834+0000
    
    ---
     released-versions.json | 4 ++--
     1 file changed, 2 insertions(+), 2 deletions(-)
    
    diff --git a/released-versions.json b/released-versions.json
    index 207530851ef18..e62b380ba9c55 100644
    --- a/released-versions.json
    +++ b/released-versions.json
    @@ -1,7 +1,7 @@
     {
         "latestReleaseSnapshot": {
    -        "version": "5.3-20190308141055+0000",
    -        "buildTime": "20190308141055+0000"
    +        "version": "5.3-20190309012834+0000",
    +        "buildTime": "20190309012834+0000"
         },
         "latestRc": {
             "version": "5.3-rc-1",
    
    From 791183b1cf95981efd9d6fcdc191a4350359f235 Mon Sep 17 00:00:00 2001
    From: Bo Zhang 
    Date: Sat, 9 Mar 2019 15:27:29 +0800
    Subject: [PATCH 441/853] Update tagging plugin to 0.56
    
    ---
     build.gradle.kts                              |  3 +-
     .../UnitTestAndCompilePlugin.kt               | 35 -------------------
     2 files changed, 2 insertions(+), 36 deletions(-)
    
    diff --git a/build.gradle.kts b/build.gradle.kts
    index a4dbf38d2d60a..604ecdddb5357 100644
    --- a/build.gradle.kts
    +++ b/build.gradle.kts
    @@ -32,7 +32,8 @@ plugins {
         // We have to apply it here at the moment, so that when the build scan plugin is auto-applied via --scan can detect that
         // the plugin has been already applied. For that the plugin has to be applied with the new plugin DSL syntax.
         com.gradle.`build-scan`
    -    id("org.gradle.ci.tag-single-build") version("0.55")
    +    id("org.gradle.ci.tag-single-build") version("0.57" +
    +        "")
     }
     
     defaultTasks("assemble")
    diff --git a/buildSrc/subprojects/plugins/src/main/kotlin/org/gradle/gradlebuild/unittestandcompile/UnitTestAndCompilePlugin.kt b/buildSrc/subprojects/plugins/src/main/kotlin/org/gradle/gradlebuild/unittestandcompile/UnitTestAndCompilePlugin.kt
    index b0fb1b5d37493..d74946bcd21f8 100644
    --- a/buildSrc/subprojects/plugins/src/main/kotlin/org/gradle/gradlebuild/unittestandcompile/UnitTestAndCompilePlugin.kt
    +++ b/buildSrc/subprojects/plugins/src/main/kotlin/org/gradle/gradlebuild/unittestandcompile/UnitTestAndCompilePlugin.kt
    @@ -25,7 +25,6 @@ import org.gradle.api.JavaVersion
     import org.gradle.api.Named
     import org.gradle.api.Plugin
     import org.gradle.api.Project
    -import org.gradle.api.internal.tasks.testing.junit.result.TestResultSerializer
     import org.gradle.api.plugins.JavaPluginConvention
     import org.gradle.api.tasks.bundling.Jar
     import org.gradle.api.tasks.compile.AbstractCompile
    @@ -42,9 +41,7 @@ import org.gradle.plugins.ide.idea.IdeaPlugin
     import org.gradle.plugins.ide.idea.model.IdeaModel
     import org.gradle.process.CommandLineArgumentProvider
     import testLibrary
    -import java.lang.IllegalStateException
     import java.util.concurrent.Callable
    -import java.util.concurrent.atomic.AtomicInteger
     import java.util.jar.Attributes
     import kotlin.reflect.full.declaredFunctions
     
    @@ -101,9 +98,6 @@ const val tooManyTestFailuresThreshold = 10
     
     
     class UnitTestAndCompilePlugin : Plugin {
    -    private
    -    val allTestFailuresCount = AtomicInteger(0)
    -
         override fun apply(project: Project): Unit = project.run {
             apply(plugin = "groovy")
     
    @@ -201,19 +195,6 @@ class UnitTestAndCompilePlugin : Plugin {
             }
         }
     
    -    private
    -    fun Test.getPreviousFailedTestClasses(): Set = TestResultSerializer(binResultsDir).let { serializer ->
    -        val previousFailedTestClasses = mutableSetOf()
    -        serializer.read {
    -            if (failuresCount > 0) {
    -                allTestFailuresCount.addAndGet(failuresCount)
    -                previousFailedTestClasses.add(className)
    -            }
    -        }
    -
    -        previousFailedTestClasses
    -    }
    -
         private
         fun Test.configureJvmForTest() {
             val javaInstallationForTest = project.rootProject.availableJavaInstallations.javaInstallationForTest
    @@ -234,20 +215,6 @@ class UnitTestAndCompilePlugin : Plugin {
             inputs.property("javaInstallation", Callable { javaInstallationForTest.vendorAndMajorVersion })
         }
     
    -    private
    -    fun Test.onlyRunPreviousFailedClassesIfNecessary() {
    -        if (project.stringPropertyOrEmpty("onlyPreviousFailedTestClasses").toBoolean()) {
    -            val previousFailedClasses = getPreviousFailedTestClasses()
    -            if (allTestFailuresCount.get() > tooManyTestFailuresThreshold) {
    -                throw IllegalStateException("Too many failures (${allTestFailuresCount.get()}) in first run!")
    -            } else if (previousFailedClasses.isEmpty()) {
    -                enabled = false
    -            } else {
    -                previousFailedClasses.forEach { filter.includeTestsMatching(it) }
    -            }
    -        }
    -    }
    -
         private
         fun Project.configureTests() {
             tasks.withType().configureEach {
    @@ -255,8 +222,6 @@ class UnitTestAndCompilePlugin : Plugin {
     
                 configureJvmForTest()
     
    -            onlyRunPreviousFailedClassesIfNecessary()
    -
                 doFirst {
                     if (BuildEnvironment.isCiServer) {
                         logger.lifecycle("maxParallelForks for '$path' is $maxParallelForks")
    
    From af297f5abf357c77638170b55dfeac53e695d333 Mon Sep 17 00:00:00 2001
    From: Bo Zhang 
    Date: Sat, 9 Mar 2019 20:39:42 +0800
    Subject: [PATCH 442/853] Update tagging plugin to 0.57
    
    ---
     build.gradle.kts | 3 +--
     1 file changed, 1 insertion(+), 2 deletions(-)
    
    diff --git a/build.gradle.kts b/build.gradle.kts
    index 604ecdddb5357..772c0e3d8234d 100644
    --- a/build.gradle.kts
    +++ b/build.gradle.kts
    @@ -32,8 +32,7 @@ plugins {
         // We have to apply it here at the moment, so that when the build scan plugin is auto-applied via --scan can detect that
         // the plugin has been already applied. For that the plugin has to be applied with the new plugin DSL syntax.
         com.gradle.`build-scan`
    -    id("org.gradle.ci.tag-single-build") version("0.57" +
    -        "")
    +    id("org.gradle.ci.tag-single-build") version("0.57")
     }
     
     defaultTasks("assemble")
    
    From 4a3feb6a17411e65f8607fca12bedbc7a14ace26 Mon Sep 17 00:00:00 2001
    From: Bo Zhang 
    Date: Sat, 9 Mar 2019 15:27:29 +0800
    Subject: [PATCH 443/853] Update tagging plugin to 0.57
    
    ---
     build.gradle.kts                              |  2 +-
     .../UnitTestAndCompilePlugin.kt               | 35 -------------------
     2 files changed, 1 insertion(+), 36 deletions(-)
    
    diff --git a/build.gradle.kts b/build.gradle.kts
    index 4aa694b099705..91d57bd840016 100644
    --- a/build.gradle.kts
    +++ b/build.gradle.kts
    @@ -32,7 +32,7 @@ plugins {
         // We have to apply it here at the moment, so that when the build scan plugin is auto-applied via --scan can detect that
         // the plugin has been already applied. For that the plugin has to be applied with the new plugin DSL syntax.
         com.gradle.`build-scan`
    -    id("org.gradle.ci.tag-single-build") version("0.54")
    +    id("org.gradle.ci.tag-single-build") version("0.57")
     }
     
     defaultTasks("assemble")
    diff --git a/buildSrc/subprojects/plugins/src/main/kotlin/org/gradle/gradlebuild/unittestandcompile/UnitTestAndCompilePlugin.kt b/buildSrc/subprojects/plugins/src/main/kotlin/org/gradle/gradlebuild/unittestandcompile/UnitTestAndCompilePlugin.kt
    index b0fb1b5d37493..d74946bcd21f8 100644
    --- a/buildSrc/subprojects/plugins/src/main/kotlin/org/gradle/gradlebuild/unittestandcompile/UnitTestAndCompilePlugin.kt
    +++ b/buildSrc/subprojects/plugins/src/main/kotlin/org/gradle/gradlebuild/unittestandcompile/UnitTestAndCompilePlugin.kt
    @@ -25,7 +25,6 @@ import org.gradle.api.JavaVersion
     import org.gradle.api.Named
     import org.gradle.api.Plugin
     import org.gradle.api.Project
    -import org.gradle.api.internal.tasks.testing.junit.result.TestResultSerializer
     import org.gradle.api.plugins.JavaPluginConvention
     import org.gradle.api.tasks.bundling.Jar
     import org.gradle.api.tasks.compile.AbstractCompile
    @@ -42,9 +41,7 @@ import org.gradle.plugins.ide.idea.IdeaPlugin
     import org.gradle.plugins.ide.idea.model.IdeaModel
     import org.gradle.process.CommandLineArgumentProvider
     import testLibrary
    -import java.lang.IllegalStateException
     import java.util.concurrent.Callable
    -import java.util.concurrent.atomic.AtomicInteger
     import java.util.jar.Attributes
     import kotlin.reflect.full.declaredFunctions
     
    @@ -101,9 +98,6 @@ const val tooManyTestFailuresThreshold = 10
     
     
     class UnitTestAndCompilePlugin : Plugin {
    -    private
    -    val allTestFailuresCount = AtomicInteger(0)
    -
         override fun apply(project: Project): Unit = project.run {
             apply(plugin = "groovy")
     
    @@ -201,19 +195,6 @@ class UnitTestAndCompilePlugin : Plugin {
             }
         }
     
    -    private
    -    fun Test.getPreviousFailedTestClasses(): Set = TestResultSerializer(binResultsDir).let { serializer ->
    -        val previousFailedTestClasses = mutableSetOf()
    -        serializer.read {
    -            if (failuresCount > 0) {
    -                allTestFailuresCount.addAndGet(failuresCount)
    -                previousFailedTestClasses.add(className)
    -            }
    -        }
    -
    -        previousFailedTestClasses
    -    }
    -
         private
         fun Test.configureJvmForTest() {
             val javaInstallationForTest = project.rootProject.availableJavaInstallations.javaInstallationForTest
    @@ -234,20 +215,6 @@ class UnitTestAndCompilePlugin : Plugin {
             inputs.property("javaInstallation", Callable { javaInstallationForTest.vendorAndMajorVersion })
         }
     
    -    private
    -    fun Test.onlyRunPreviousFailedClassesIfNecessary() {
    -        if (project.stringPropertyOrEmpty("onlyPreviousFailedTestClasses").toBoolean()) {
    -            val previousFailedClasses = getPreviousFailedTestClasses()
    -            if (allTestFailuresCount.get() > tooManyTestFailuresThreshold) {
    -                throw IllegalStateException("Too many failures (${allTestFailuresCount.get()}) in first run!")
    -            } else if (previousFailedClasses.isEmpty()) {
    -                enabled = false
    -            } else {
    -                previousFailedClasses.forEach { filter.includeTestsMatching(it) }
    -            }
    -        }
    -    }
    -
         private
         fun Project.configureTests() {
             tasks.withType().configureEach {
    @@ -255,8 +222,6 @@ class UnitTestAndCompilePlugin : Plugin {
     
                 configureJvmForTest()
     
    -            onlyRunPreviousFailedClassesIfNecessary()
    -
                 doFirst {
                     if (BuildEnvironment.isCiServer) {
                         logger.lifecycle("maxParallelForks for '$path' is $maxParallelForks")
    
    From 91e99987e9f0faab25accc19ed12e84a6854b226 Mon Sep 17 00:00:00 2001
    From: Gradleware Git Bot 
    Date: Sun, 10 Mar 2019 02:51:16 +0100
    Subject: [PATCH 444/853] Publish 5.3-20190310013230+0000
    
    ---
     released-versions.json | 4 ++--
     1 file changed, 2 insertions(+), 2 deletions(-)
    
    diff --git a/released-versions.json b/released-versions.json
    index e62b380ba9c55..5cdf9af18ae58 100644
    --- a/released-versions.json
    +++ b/released-versions.json
    @@ -1,7 +1,7 @@
     {
         "latestReleaseSnapshot": {
    -        "version": "5.3-20190309012834+0000",
    -        "buildTime": "20190309012834+0000"
    +        "version": "5.3-20190310013230+0000",
    +        "buildTime": "20190310013230+0000"
         },
         "latestRc": {
             "version": "5.3-rc-1",
    
    From 2ebde5fcd7568daccf37bf99e03e80eebef469c4 Mon Sep 17 00:00:00 2001
    From: Bo Zhang 
    Date: Sun, 10 Mar 2019 14:39:59 +0800
    Subject: [PATCH 445/853] Update tagging plugin to 0.58
    
    ---
     build.gradle.kts | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    diff --git a/build.gradle.kts b/build.gradle.kts
    index 772c0e3d8234d..a86661ab7a462 100644
    --- a/build.gradle.kts
    +++ b/build.gradle.kts
    @@ -32,7 +32,7 @@ plugins {
         // We have to apply it here at the moment, so that when the build scan plugin is auto-applied via --scan can detect that
         // the plugin has been already applied. For that the plugin has to be applied with the new plugin DSL syntax.
         com.gradle.`build-scan`
    -    id("org.gradle.ci.tag-single-build") version("0.57")
    +    id("org.gradle.ci.tag-single-build") version("0.58")
     }
     
     defaultTasks("assemble")
    
    From afc3cd0f870aaa7998a0ea8c78d0f51a7eec4043 Mon Sep 17 00:00:00 2001
    From: Bo Zhang 
    Date: Sun, 10 Mar 2019 14:39:59 +0800
    Subject: [PATCH 446/853] Update tagging plugin to 0.58
    
    ---
     build.gradle.kts | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    diff --git a/build.gradle.kts b/build.gradle.kts
    index 91d57bd840016..553597af213dc 100644
    --- a/build.gradle.kts
    +++ b/build.gradle.kts
    @@ -32,7 +32,7 @@ plugins {
         // We have to apply it here at the moment, so that when the build scan plugin is auto-applied via --scan can detect that
         // the plugin has been already applied. For that the plugin has to be applied with the new plugin DSL syntax.
         com.gradle.`build-scan`
    -    id("org.gradle.ci.tag-single-build") version("0.57")
    +    id("org.gradle.ci.tag-single-build") version("0.58")
     }
     
     defaultTasks("assemble")
    
    From 3ca618fe97f5e3450a4d1c69da914ff9f2f19731 Mon Sep 17 00:00:00 2001
    From: Louis Jacomet 
    Date: Fri, 8 Mar 2019 17:28:07 +0100
    Subject: [PATCH 447/853] Update javadoc to remove deprecated configurations
    
    The javadoc of a number of core types were still using `compile` or
    `runtime` configurations in their examples.
    These have been moved to use `implementation`, `compileClasspath` or
    similar based on the example.
    
    Fixes #8714
    ---
     .../src/main/java/org/gradle/api/Project.java |  2 +-
     .../src/main/java/org/gradle/api/Script.java  |  2 +-
     .../api/artifacts/ConfigurationContainer.java | 22 +++++----
     .../api/artifacts/ModuleDependency.java       |  4 +-
     .../api/artifacts/ResolutionStrategy.java     |  2 +-
     .../api/artifacts/dsl/DependencyHandler.java  | 46 +++++++++----------
     .../query/ArtifactResolutionQuery.java        |  2 +-
     7 files changed, 42 insertions(+), 38 deletions(-)
    
    diff --git a/subprojects/core-api/src/main/java/org/gradle/api/Project.java b/subprojects/core-api/src/main/java/org/gradle/api/Project.java
    index 46f0ea07df8fb..12543caf28342 100644
    --- a/subprojects/core-api/src/main/java/org/gradle/api/Project.java
    +++ b/subprojects/core-api/src/main/java/org/gradle/api/Project.java
    @@ -1551,7 +1551,7 @@ public interface Project extends Comparable, ExtensionAware, PluginAwar
          * copy the files. Example:
          * 
          * copy {
    -     *    from configurations.runtime
    +     *    from configurations.runtimeClasspath
          *    into 'build/deploy/lib'
          * }
          * 
    diff --git a/subprojects/core-api/src/main/java/org/gradle/api/Script.java b/subprojects/core-api/src/main/java/org/gradle/api/Script.java index 0dfa568dcd092..a6e44a2a39e85 100755 --- a/subprojects/core-api/src/main/java/org/gradle/api/Script.java +++ b/subprojects/core-api/src/main/java/org/gradle/api/Script.java @@ -256,7 +256,7 @@ public interface Script { * is then used to copy the files. Example: *
          * copy {
    -     *    from configurations.runtime
    +     *    from configurations.runtimeClasspath
          *    into 'build/deploy/lib'
          * }
          * 
    diff --git a/subprojects/core-api/src/main/java/org/gradle/api/artifacts/ConfigurationContainer.java b/subprojects/core-api/src/main/java/org/gradle/api/artifacts/ConfigurationContainer.java index 9ff18b2586575..d3a90eef3381c 100644 --- a/subprojects/core-api/src/main/java/org/gradle/api/artifacts/ConfigurationContainer.java +++ b/subprojects/core-api/src/main/java/org/gradle/api/artifacts/ConfigurationContainer.java @@ -49,32 +49,36 @@ * An example showing how to refer to a given configuration by name * in order to get hold of all dependencies (e.g. jars, but only) *
    - *   apply plugin: 'java' //so that I can use 'compile' configuration
    + *   apply plugin: 'java' //so that I can use 'implementation', 'compileClasspath' configuration
      *
    - *   //copying all dependencies attached to 'compile' into a specific folder
    + *   dependencies {
    + *       implementation 'org.slf4j:slf4j-api:1.7.26'
    + *   }
    + *
    + *   //copying all dependencies attached to 'compileClasspath' into a specific folder
      *   task copyAllDependencies(type: Copy) {
    - *     //referring to the 'compile' configuration
    - *     from configurations.compile
    + *     //referring to the 'compileClasspath' configuration
    + *     from configurations.compileClasspath
      *     into 'allLibs'
      *   }
      * 
    * * An example showing how to declare and configure configurations *
    - * apply plugin: 'java' //so that I can use 'compile', 'testCompile' configurations
    + * apply plugin: 'java' //so that I can use 'implementation', 'testImplementation' configurations
      *
      * configurations {
      *   //adding a configuration:
      *   myConfiguration
      *
      *   //adding a configuration that extends existing configuration:
    - *   //(testCompile was added by the java plugin)
    - *   myIntegrationTestsCompile.extendsFrom(testCompile)
    + *   //(testImplementation was added by the java plugin)
    + *   myIntegrationTestsCompile.extendsFrom(testImplementation)
      *
      *   //configuring existing configurations not to put transitive dependencies on the compile classpath
      *   //this way you can avoid issues with implicit dependencies to transitive libraries
    - *   compile.transitive = false
    - *   testCompile.transitive = false
    + *   compileClasspath.transitive = false
    + *   testCompileClasspath.transitive = false
      * }
      * 
    * diff --git a/subprojects/core-api/src/main/java/org/gradle/api/artifacts/ModuleDependency.java b/subprojects/core-api/src/main/java/org/gradle/api/artifacts/ModuleDependency.java index 4ef7b84d32e22..995155db68e68 100644 --- a/subprojects/core-api/src/main/java/org/gradle/api/artifacts/ModuleDependency.java +++ b/subprojects/core-api/src/main/java/org/gradle/api/artifacts/ModuleDependency.java @@ -54,10 +54,10 @@ public interface ModuleDependency extends Dependency, HasConfigurableAttributes< * then consider using forced versions' feature: {@link ResolutionStrategy#force(Object...)}. * *
    -     * apply plugin: 'java' //so that I can declare 'compile' dependencies
    +     * apply plugin: 'java' //so that I can declare 'implementation' dependencies
          *
          * dependencies {
    -     *   compile('org.hibernate:hibernate:3.1') {
    +     *   implementation('org.hibernate:hibernate:3.1') {
          *     //excluding a particular transitive dependency:
          *     exclude module: 'cglib' //by artifact name
          *     exclude group: 'org.jmock' //by group
    diff --git a/subprojects/core-api/src/main/java/org/gradle/api/artifacts/ResolutionStrategy.java b/subprojects/core-api/src/main/java/org/gradle/api/artifacts/ResolutionStrategy.java
    index 26ac327a3880d..cf961d411e75d 100644
    --- a/subprojects/core-api/src/main/java/org/gradle/api/artifacts/ResolutionStrategy.java
    +++ b/subprojects/core-api/src/main/java/org/gradle/api/artifacts/ResolutionStrategy.java
    @@ -171,7 +171,7 @@ public interface ResolutionStrategy {
          * Example:
          * 
          * configurations {
    -     *   compile.resolutionStrategy {
    +     *   compileClasspath.resolutionStrategy {
          *     eachDependency { DependencyResolveDetails details ->
          *       //specifying a fixed version for all libraries with 'org.gradle' group
          *       if (details.requested.group == 'org.gradle') {
    diff --git a/subprojects/core-api/src/main/java/org/gradle/api/artifacts/dsl/DependencyHandler.java b/subprojects/core-api/src/main/java/org/gradle/api/artifacts/dsl/DependencyHandler.java
    index eb2552d80a710..7dd434a431d34 100644
    --- a/subprojects/core-api/src/main/java/org/gradle/api/artifacts/dsl/DependencyHandler.java
    +++ b/subprojects/core-api/src/main/java/org/gradle/api/artifacts/dsl/DependencyHandler.java
    @@ -38,29 +38,29 @@
      *
      * 
      * dependencies {
    - *     configurationName dependencyNotation1, dependencyNotation2, ...
    + *     configurationName dependencyNotation
      * }
      * 
    * *

    Example shows a basic way of declaring dependencies. *

      * apply plugin: 'java'
    - * //so that we can use 'compile', 'testCompile' for dependencies
    + * //so that we can use 'implementation', 'testImplementation' for dependencies
      *
      * dependencies {
      *   //for dependencies found in artifact repositories you can use
      *   //the group:name:version notation
    - *   compile 'commons-lang:commons-lang:2.6'
    - *   testCompile 'org.mockito:mockito:1.9.0-rc1'
    + *   implementation 'commons-lang:commons-lang:2.6'
    + *   testImplementation 'org.mockito:mockito:1.9.0-rc1'
      *
      *   //map-style notation:
    - *   compile group: 'com.google.code.guice', name: 'guice', version: '1.0'
    + *   implementation group: 'com.google.code.guice', name: 'guice', version: '1.0'
      *
      *   //declaring arbitrary files as dependencies
    - *   compile files('hibernate.jar', 'libs/spring.jar')
    + *   implementation files('hibernate.jar', 'libs/spring.jar')
      *
      *   //putting all jars from 'libs' onto compile classpath
    - *   compile fileTree('libs')
    + *   implementation fileTree('libs')
      * }
      * 
    * @@ -86,10 +86,10 @@ * * *
    - * apply plugin: 'java' //so that I can declare 'compile' dependencies
    + * apply plugin: 'java' //so that I can declare 'implementation' dependencies
      *
      * dependencies {
    - *   compile('org.hibernate:hibernate:3.1') {
    + *   implementation('org.hibernate:hibernate:3.1') {
      *     //in case of versions conflict '3.1' version of hibernate wins:
      *     force = true
      *
    @@ -111,14 +111,14 @@
      * 
      *
      * 
    - * apply plugin: 'java' //so that I can declare 'compile' dependencies
    + * apply plugin: 'java' //so that I can declare 'implementation' dependencies
      *
      * dependencies {
      *   //configuring dependency to specific configuration of the module
    - *   compile configuration: 'someConf', group: 'org.someOrg', name: 'someModule', version: '1.0'
    + *   implementation configuration: 'someConf', group: 'org.someOrg', name: 'someModule', version: '1.0'
      *
      *   //configuring dependency on 'someLib' module
    - *   compile(group: 'org.myorg', name: 'someLib', version:'1.0') {
    + *   implementation(group: 'org.myorg', name: 'someLib', version:'1.0') {
      *     //explicitly adding the dependency artifact:
      *     artifact {
      *       //useful when some artifact properties unconventional
    @@ -161,16 +161,16 @@
      *
      * 
      * apply plugin: 'java'
    - * //so that we can use 'compile', 'testCompile' for dependencies
    + * //so that we can use 'implementation', 'testImplementation' for dependencies
      *
      * dependencies {
      *   //for dependencies found in artifact repositories you can use
      *   //the string notation, e.g. group:name:version
    - *   compile 'commons-lang:commons-lang:2.6'
    - *   testCompile 'org.mockito:mockito:1.9.0-rc1'
    + *   implementation 'commons-lang:commons-lang:2.6'
    + *   testImplementation 'org.mockito:mockito:1.9.0-rc1'
      *
      *   //map notation:
    - *   compile group: 'com.google.code.guice', name: 'guice', version: '1.0'
    + *   implementation group: 'com.google.code.guice', name: 'guice', version: '1.0'
      * }
      * 
    * @@ -195,14 +195,14 @@ * *
      * apply plugin: 'java'
    - * //so that we can use 'compile', 'testCompile' for dependencies
    + * //so that we can use 'implementation', 'testImplementation' for dependencies
      *
      * dependencies {
      *   //declaring arbitrary files as dependencies
    - *   compile files('hibernate.jar', 'libs/spring.jar')
    + *   implementation files('hibernate.jar', 'libs/spring.jar')
      *
      *   //putting all jars from 'libs' onto compile classpath
    - *   compile fileTree('libs')
    + *   implementation fileTree('libs')
      * }
      * 
    * @@ -225,17 +225,17 @@ *
      * //Our Gradle plugin is written in groovy
      * apply plugin: 'groovy'
    - * //now we can use the 'compile' configuration for declaring dependencies
    + * //now we can use the 'implementation' configuration for declaring dependencies
      *
      * dependencies {
      *   //we will use the Groovy version that ships with Gradle:
    - *   compile localGroovy()
    + *   implementation localGroovy()
      *
      *   //our plugin requires Gradle API interfaces and classes to compile:
    - *   compile gradleApi()
    + *   implementation gradleApi()
      *
      *   //we will use the Gradle test-kit to test build logic:
    - *   testCompile gradleTestKit()
    + *   testImplementation gradleTestKit()
      * }
      * 
    * diff --git a/subprojects/core-api/src/main/java/org/gradle/api/artifacts/query/ArtifactResolutionQuery.java b/subprojects/core-api/src/main/java/org/gradle/api/artifacts/query/ArtifactResolutionQuery.java index 5b86d0992c14a..6f20250d79225 100644 --- a/subprojects/core-api/src/main/java/org/gradle/api/artifacts/query/ArtifactResolutionQuery.java +++ b/subprojects/core-api/src/main/java/org/gradle/api/artifacts/query/ArtifactResolutionQuery.java @@ -31,7 +31,7 @@ * * task resolveCompileSources { * doLast { - * def componentIds = configurations.compile.incoming.resolutionResult.allDependencies.collect { it.selected.id } + * def componentIds = configurations.compileClasspath.incoming.resolutionResult.allDependencies.collect { it.selected.id } * * def result = dependencies.createArtifactResolutionQuery() * .forComponents(componentIds) From 05d0a7b3b44f29d01fac4a160e23999858c04851 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Sun, 10 Mar 2019 16:38:06 +0100 Subject: [PATCH 448/853] Run tests against JUnit 4.13-beta-2 --- .../org/gradle/testing/fixture/JUnitCoverage.groovy | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/subprojects/testing-jvm/src/integTest/groovy/org/gradle/testing/fixture/JUnitCoverage.groovy b/subprojects/testing-jvm/src/integTest/groovy/org/gradle/testing/fixture/JUnitCoverage.groovy index 80f54e3c51eb2..66c1c8441a88c 100644 --- a/subprojects/testing-jvm/src/integTest/groovy/org/gradle/testing/fixture/JUnitCoverage.groovy +++ b/subprojects/testing-jvm/src/integTest/groovy/org/gradle/testing/fixture/JUnitCoverage.groovy @@ -25,16 +25,17 @@ import org.gradle.api.JavaVersion */ class JUnitCoverage { final static String NEWEST = '4.12' + final static String PREVIEW = '4.13-beta-2' final static String LATEST_JUPITER_VERSION = '5.4.0' final static String LATEST_VINTAGE_VERSION = '5.4.0' final static String JUPITER = 'Jupiter:' + LATEST_JUPITER_VERSION final static String VINTAGE = 'Vintage:' + LATEST_VINTAGE_VERSION - final static String[] LARGE_COVERAGE = ['4.0', '4.4', '4.8.2', NEWEST] - final static String[] IGNORE_ON_CLASS = ['4.4', '4.8.2', NEWEST] - final static String[] ASSUMPTIONS = ['4.5', NEWEST] - final static String[] CATEGORIES = ['4.8', NEWEST] - final static String[] FILTER_JUNIT3_TESTS = ['3.8.1', '4.6', NEWEST] - final static String[] JUNIT_4_LATEST = [NEWEST] + final static String[] LARGE_COVERAGE = ['4.0', '4.4', '4.8.2', NEWEST, PREVIEW] + final static String[] IGNORE_ON_CLASS = ['4.4', '4.8.2', NEWEST, PREVIEW] + final static String[] ASSUMPTIONS = ['4.5', NEWEST, PREVIEW] + final static String[] CATEGORIES = ['4.8', NEWEST, PREVIEW] + final static String[] FILTER_JUNIT3_TESTS = ['3.8.1', '4.6', NEWEST, PREVIEW] + final static String[] JUNIT_4_LATEST = [NEWEST, PREVIEW] final static String[] JUNIT_VINTAGE = emptyIfJava7(VINTAGE) final static String[] JUNIT_VINTAGE_JUPITER = emptyIfJava7(VINTAGE, JUPITER) From 826c1cb4316e3c5819446a74c039701b9ac00c09 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Sun, 10 Mar 2019 18:45:43 +0100 Subject: [PATCH 449/853] Fix filtering parameterized tests by category Prior to this commit methods in parameterized test classes were not checked for `@Category` annotations. Resolves #8424. --- ...itCategoriesCoverageIntegrationSpec.groovy | 25 +++-- .../build.gradle | 11 +++ .../org/gradle/NestedTestsWithCategories.java | 96 +++++++++++++++++++ .../test/java/org/gradle/SomeCategory.java | 4 + .../tasks/testing/junit/CategoryFilter.java | 16 +++- 5 files changed, 141 insertions(+), 11 deletions(-) create mode 100644 subprojects/testing-jvm/src/integTest/resources/org/gradle/testing/junit/JUnitCategoriesCoverageIntegrationSpec/canRunParameterizedTestsWithCategories/build.gradle create mode 100644 subprojects/testing-jvm/src/integTest/resources/org/gradle/testing/junit/JUnitCategoriesCoverageIntegrationSpec/canRunParameterizedTestsWithCategories/src/test/java/org/gradle/NestedTestsWithCategories.java create mode 100644 subprojects/testing-jvm/src/integTest/resources/org/gradle/testing/junit/JUnitCategoriesCoverageIntegrationSpec/canRunParameterizedTestsWithCategories/src/test/java/org/gradle/SomeCategory.java diff --git a/subprojects/testing-jvm/src/integTest/groovy/org/gradle/testing/junit/JUnitCategoriesCoverageIntegrationSpec.groovy b/subprojects/testing-jvm/src/integTest/groovy/org/gradle/testing/junit/JUnitCategoriesCoverageIntegrationSpec.groovy index 7b8171aa1c859..a289123cd6e9b 100644 --- a/subprojects/testing-jvm/src/integTest/groovy/org/gradle/testing/junit/JUnitCategoriesCoverageIntegrationSpec.groovy +++ b/subprojects/testing-jvm/src/integTest/groovy/org/gradle/testing/junit/JUnitCategoriesCoverageIntegrationSpec.groovy @@ -32,15 +32,10 @@ class JUnitCategoriesCoverageIntegrationSpec extends JUnitMultiVersionIntegratio def setup() { executer.noExtraLogging() - } - - def configureJUnit() { buildFile << "dependencies { testCompile '$dependencyNotation' }" } def canSpecifyIncludeAndExcludeCategories() { - configureJUnit() - when: run('test') @@ -59,8 +54,6 @@ class JUnitCategoriesCoverageIntegrationSpec extends JUnitMultiVersionIntegratio } def canSpecifyExcludesOnly() { - configureJUnit() - when: run('test') @@ -76,8 +69,6 @@ class JUnitCategoriesCoverageIntegrationSpec extends JUnitMultiVersionIntegratio } def canCombineCategoriesWithCustomRunner() { - configureJUnit() - when: run('test') @@ -87,4 +78,20 @@ class JUnitCategoriesCoverageIntegrationSpec extends JUnitMultiVersionIntegratio result.testClass("org.gradle.SomeLocaleTests").assertTestCount(3, 0, 0) result.testClass("org.gradle.SomeLocaleTests").assertTestsExecuted('ok1 [de]', 'ok1 [en]', 'ok1 [fr]') } + + def canRunParameterizedTestsWithCategories() { + when: + run('test') + + then: + def expectedTestClasses = ['org.gradle.NestedTestsWithCategories$TagOnMethodNoParam', 'org.gradle.NestedTestsWithCategories$TagOnMethod'] + if (isVintage() || !(version in ['4.10', '4.11', '4.12'])) { + expectedTestClasses << 'org.gradle.NestedTestsWithCategories$TagOnClass' + } + DefaultTestExecutionResult result = new DefaultTestExecutionResult(testDirectory) + result.assertTestClassesExecuted(expectedTestClasses as String[]) + expectedTestClasses.each { + result.testClass(it).assertTestCount(1, 0, 0) + } + } } diff --git a/subprojects/testing-jvm/src/integTest/resources/org/gradle/testing/junit/JUnitCategoriesCoverageIntegrationSpec/canRunParameterizedTestsWithCategories/build.gradle b/subprojects/testing-jvm/src/integTest/resources/org/gradle/testing/junit/JUnitCategoriesCoverageIntegrationSpec/canRunParameterizedTestsWithCategories/build.gradle new file mode 100644 index 0000000000000..987aa0bd0c1a0 --- /dev/null +++ b/subprojects/testing-jvm/src/integTest/resources/org/gradle/testing/junit/JUnitCategoriesCoverageIntegrationSpec/canRunParameterizedTestsWithCategories/build.gradle @@ -0,0 +1,11 @@ +apply plugin: "java" + +repositories { + mavenCentral() +} + +test { + useJUnit { + includeCategories 'org.gradle.SomeCategory' + } +} diff --git a/subprojects/testing-jvm/src/integTest/resources/org/gradle/testing/junit/JUnitCategoriesCoverageIntegrationSpec/canRunParameterizedTestsWithCategories/src/test/java/org/gradle/NestedTestsWithCategories.java b/subprojects/testing-jvm/src/integTest/resources/org/gradle/testing/junit/JUnitCategoriesCoverageIntegrationSpec/canRunParameterizedTestsWithCategories/src/test/java/org/gradle/NestedTestsWithCategories.java new file mode 100644 index 0000000000000..c633a47aa4814 --- /dev/null +++ b/subprojects/testing-jvm/src/integTest/resources/org/gradle/testing/junit/JUnitCategoriesCoverageIntegrationSpec/canRunParameterizedTestsWithCategories/src/test/java/org/gradle/NestedTestsWithCategories.java @@ -0,0 +1,96 @@ +package org.gradle; + +import org.junit.Test; +import org.junit.experimental.categories.Category; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +import java.util.ArrayList; + +import static org.junit.Assert.fail; + +public class NestedTestsWithCategories { + + @Category(SomeCategory.class) + @RunWith(Parameterized.class) + public static class TagOnClass { + @Parameterized.Parameters + public static Iterable getParameters() { + ArrayList parameters = new ArrayList<>(); + parameters.add(new Object[] { "tag on class" }); + return parameters; + } + + private final String param; + + public TagOnClass(String param) { + this.param = param; + } + + @Test + public void run() { + System.err.println("executed " + param); + } + } + + @RunWith(Parameterized.class) + public static class TagOnMethod { + @Parameterized.Parameters + public static Iterable getParameters() { + ArrayList parameters = new ArrayList<>(); + parameters.add(new Object[] { "tag on method" }); + return parameters; + } + + private final String param; + + public TagOnMethod(String param) { + this.param = param; + } + + @Test + @Category(SomeCategory.class) + public void run() { + System.err.println("executed " + param); + } + + @Test + public void filteredOut() { + throw new AssertionError("should be filtered out"); + } + } + + public static class TagOnMethodNoParam { + @Test + @Category(SomeCategory.class) + public void run() { + System.err.println("executed tag on method (no param)"); + } + + @Test + public void filteredOut() { + throw new AssertionError("should be filtered out"); + } + } + + @RunWith(Parameterized.class) + public static class Untagged { + @Parameterized.Parameters + public static Iterable getParameters() { + ArrayList parameters = new ArrayList<>(); + parameters.add(new Object[] { "untagged" }); + return parameters; + } + + private final String param; + + public Untagged(String param) { + this.param = param; + } + + @Test + public void run() { + System.err.println("executed " + param); + } + } +} diff --git a/subprojects/testing-jvm/src/integTest/resources/org/gradle/testing/junit/JUnitCategoriesCoverageIntegrationSpec/canRunParameterizedTestsWithCategories/src/test/java/org/gradle/SomeCategory.java b/subprojects/testing-jvm/src/integTest/resources/org/gradle/testing/junit/JUnitCategoriesCoverageIntegrationSpec/canRunParameterizedTestsWithCategories/src/test/java/org/gradle/SomeCategory.java new file mode 100644 index 0000000000000..036456a607fb4 --- /dev/null +++ b/subprojects/testing-jvm/src/integTest/resources/org/gradle/testing/junit/JUnitCategoriesCoverageIntegrationSpec/canRunParameterizedTestsWithCategories/src/test/java/org/gradle/SomeCategory.java @@ -0,0 +1,4 @@ +package org.gradle; + +public interface SomeCategory { +} diff --git a/subprojects/testing-jvm/src/main/java/org/gradle/api/internal/tasks/testing/junit/CategoryFilter.java b/subprojects/testing-jvm/src/main/java/org/gradle/api/internal/tasks/testing/junit/CategoryFilter.java index ebf57b91946b7..0d21368767135 100644 --- a/subprojects/testing-jvm/src/main/java/org/gradle/api/internal/tasks/testing/junit/CategoryFilter.java +++ b/subprojects/testing-jvm/src/main/java/org/gradle/api/internal/tasks/testing/junit/CategoryFilter.java @@ -43,8 +43,8 @@ class CategoryFilter extends Filter { public boolean shouldRun(final Description description) { Class testClass = description.getTestClass(); verifyCategories(testClass); - Description desc = description.isSuite() || testClass == null ? null : Description.createSuiteDescription(testClass); - return shouldRun(description, desc); + Description parent = description.isSuite() || testClass == null ? null : Description.createSuiteDescription(testClass); + return shouldRun(description, parent); } private void verifyCategories(Class testClass) { @@ -60,6 +60,18 @@ private void verifyCategories(Class testClass) { } private boolean shouldRun(final Description description, final Description parent) { + if (hasCorrectCategoryAnnotation(description, parent)) { + return true; + } + for (Description each : description.getChildren()) { + if (shouldRun(each, description)) { + return true; + } + } + return false; + } + + private boolean hasCorrectCategoryAnnotation(Description description, Description parent) { final Set> categories = new HashSet>(); Category annotation = description.getAnnotation(Category.class); if (annotation != null) { From 8fbb2904080a823a48c666c7e0469427101abb82 Mon Sep 17 00:00:00 2001 From: Gradleware Git Bot Date: Mon, 11 Mar 2019 02:21:41 +0100 Subject: [PATCH 450/853] Publish 5.3-20190311010311+0000 --- released-versions.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/released-versions.json b/released-versions.json index 5cdf9af18ae58..2c490c93a39a1 100644 --- a/released-versions.json +++ b/released-versions.json @@ -1,7 +1,7 @@ { "latestReleaseSnapshot": { - "version": "5.3-20190310013230+0000", - "buildTime": "20190310013230+0000" + "version": "5.3-20190311010311+0000", + "buildTime": "20190311010311+0000" }, "latestRc": { "version": "5.3-rc-1", From d7f0f4ecf17db848c51efe6dc9b20446109a89cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=B3r=C3=A1nt=20Pint=C3=A9r?= Date: Mon, 11 Mar 2019 04:47:00 +0100 Subject: [PATCH 451/853] Move only execution integration test to integTest source set --- ...ncrementalExecutionIntegrationTest.groovy} | 38 ++++++++-------- .../execution/TestOutputFilesRepository.java | 44 ------------------- 2 files changed, 19 insertions(+), 63 deletions(-) rename subprojects/execution/src/{test/groovy/org/gradle/internal/execution/steps/IncrementalExecutionTest.groovy => integTest/groovy/org/gradle/internal/execution/IncrementalExecutionIntegrationTest.groovy} (96%) delete mode 100644 subprojects/execution/src/test/groovy/org/gradle/internal/execution/TestOutputFilesRepository.java diff --git a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/IncrementalExecutionTest.groovy b/subprojects/execution/src/integTest/groovy/org/gradle/internal/execution/IncrementalExecutionIntegrationTest.groovy similarity index 96% rename from subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/IncrementalExecutionTest.groovy rename to subprojects/execution/src/integTest/groovy/org/gradle/internal/execution/IncrementalExecutionIntegrationTest.groovy index eb1a26f367405..7901515517728 100644 --- a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/IncrementalExecutionTest.groovy +++ b/subprojects/execution/src/integTest/groovy/org/gradle/internal/execution/IncrementalExecutionIntegrationTest.groovy @@ -1,5 +1,5 @@ /* - * Copyright 2018 the original author or authors. + * Copyright 2019 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.gradle.internal.execution.steps +package org.gradle.internal.execution import com.google.common.collect.ImmutableList import com.google.common.collect.ImmutableSortedMap @@ -25,24 +25,22 @@ import org.gradle.api.internal.file.TestFiles import org.gradle.api.internal.file.collections.ImmutableFileCollection import org.gradle.caching.internal.CacheableEntity import org.gradle.internal.classloader.ClassLoaderHierarchyHasher -import org.gradle.internal.execution.CacheHandler -import org.gradle.internal.execution.ExecutionException -import org.gradle.internal.execution.ExecutionOutcome -import org.gradle.internal.execution.IncrementalChangesContext -import org.gradle.internal.execution.IncrementalContext -import org.gradle.internal.execution.OutputChangeListener -import org.gradle.internal.execution.Result -import org.gradle.internal.execution.TestExecutionHistoryStore -import org.gradle.internal.execution.TestOutputFilesRepository -import org.gradle.internal.execution.UnitOfWork -import org.gradle.internal.execution.UpToDateResult -import org.gradle.internal.execution.WorkExecutor import org.gradle.internal.execution.history.AfterPreviousExecutionState import org.gradle.internal.execution.history.BeforeExecutionState import org.gradle.internal.execution.history.ExecutionHistoryStore +import org.gradle.internal.execution.history.OutputFilesRepository import org.gradle.internal.execution.history.changes.DefaultExecutionStateChangeDetector import org.gradle.internal.execution.history.impl.DefaultBeforeExecutionState import org.gradle.internal.execution.impl.DefaultWorkExecutor +import org.gradle.internal.execution.steps.BroadcastChangingOutputsStep +import org.gradle.internal.execution.steps.CatchExceptionStep +import org.gradle.internal.execution.steps.CreateOutputsStep +import org.gradle.internal.execution.steps.ExecuteStep +import org.gradle.internal.execution.steps.RecordOutputsStep +import org.gradle.internal.execution.steps.ResolveChangesStep +import org.gradle.internal.execution.steps.SkipUpToDateStep +import org.gradle.internal.execution.steps.SnapshotOutputsStep +import org.gradle.internal.execution.steps.StoreSnapshotsStep import org.gradle.internal.file.TreeType import org.gradle.internal.fingerprint.CurrentFileCollectionFingerprint import org.gradle.internal.fingerprint.impl.AbsolutePathFileCollectionFingerprinter @@ -68,7 +66,7 @@ import java.util.function.Supplier import static org.gradle.internal.execution.ExecutionOutcome.EXECUTED_NON_INCREMENTALLY import static org.gradle.internal.execution.ExecutionOutcome.UP_TO_DATE -class IncrementalExecutionTest extends Specification { +class IncrementalExecutionIntegrationTest extends Specification { @Rule final TestNameTestDirectoryProvider temporaryFolder = TestNameTestDirectoryProvider.newInstance() @@ -97,7 +95,9 @@ class IncrementalExecutionTest extends Specification { return HashCode.fromInt(1234) } } - def outputFilesRepository = new TestOutputFilesRepository() + def outputFilesRepository = Stub(OutputFilesRepository) { + isGeneratedByGradle() >> true + } def valueSnapshotter = new DefaultValueSnapshotter(classloaderHierarchyHasher) final outputFile = temporaryFolder.file("output-file") @@ -703,8 +703,8 @@ class IncrementalExecutionTest extends Specification { } private Map inputProperties = [prop: "value"] private Map> inputs = inputFiles - private Map> outputFiles = IncrementalExecutionTest.this.outputFiles - private Map> outputDirs = IncrementalExecutionTest.this.outputDirs + private Map> outputFiles = IncrementalExecutionIntegrationTest.this.outputFiles + private Map> outputDirs = IncrementalExecutionIntegrationTest.this.outputDirs private Collection create = createFiles private ImplementationSnapshot implementation = ImplementationSnapshot.of(UnitOfWork.name, HashCode.fromInt(1234)) private @@ -789,7 +789,7 @@ class IncrementalExecutionTest extends Specification { @Override ExecutionHistoryStore getExecutionHistoryStore() { - return IncrementalExecutionTest.this.executionHistoryStore + return IncrementalExecutionIntegrationTest.this.executionHistoryStore } @Override diff --git a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/TestOutputFilesRepository.java b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/TestOutputFilesRepository.java deleted file mode 100644 index 3db553c61bb5a..0000000000000 --- a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/TestOutputFilesRepository.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright 2018 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.gradle.internal.execution; - -import com.google.common.collect.Iterables; -import org.gradle.internal.execution.history.OutputFilesRepository; -import org.gradle.internal.snapshot.FileSystemSnapshot; - -import java.io.File; -import java.util.ArrayList; -import java.util.List; - -public class TestOutputFilesRepository implements OutputFilesRepository { - - private List outputFileFingerprints = new ArrayList<>(); - - @Override - public boolean isGeneratedByGradle(File file) { - return true; - } - - @Override - public void recordOutputs(Iterable outputFileFingerprints) { - Iterables.addAll(this.outputFileFingerprints, outputFileFingerprints); - } - - public List getOutputFileFingerprints() { - return outputFileFingerprints; - } -} From f660012226be575dec0c7365cbaef5cc66d60edd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=B3r=C3=A1nt=20Pint=C3=A9r?= Date: Mon, 11 Mar 2019 05:21:30 +0100 Subject: [PATCH 452/853] Simplify preparing caching --- .../scopes/ExecutionGradleServices.java | 21 ++---- .../DefaultDependencyManagementServices.java | 15 ++-- .../internal/execution/CachingContext.java | 21 ------ .../internal/execution/steps/CacheStep.java | 6 +- .../execution/steps/PrepareCachingStep.java | 73 ------------------- .../execution/steps/CacheStepTest.groovy | 23 ++++-- 6 files changed, 34 insertions(+), 125 deletions(-) delete mode 100644 subprojects/execution/src/main/java/org/gradle/internal/execution/CachingContext.java delete mode 100644 subprojects/execution/src/main/java/org/gradle/internal/execution/steps/PrepareCachingStep.java diff --git a/subprojects/core/src/main/java/org/gradle/internal/service/scopes/ExecutionGradleServices.java b/subprojects/core/src/main/java/org/gradle/internal/service/scopes/ExecutionGradleServices.java index 2d22c2b65b8f1..c0578910dc1f3 100644 --- a/subprojects/core/src/main/java/org/gradle/internal/service/scopes/ExecutionGradleServices.java +++ b/subprojects/core/src/main/java/org/gradle/internal/service/scopes/ExecutionGradleServices.java @@ -31,8 +31,6 @@ import org.gradle.internal.concurrent.ExecutorFactory; import org.gradle.internal.concurrent.ParallelismConfigurationManager; import org.gradle.internal.event.ListenerManager; -import org.gradle.internal.execution.CachingContext; -import org.gradle.internal.execution.CurrentSnapshotResult; import org.gradle.internal.execution.IncrementalChangesContext; import org.gradle.internal.execution.IncrementalContext; import org.gradle.internal.execution.OutputChangeListener; @@ -52,7 +50,6 @@ import org.gradle.internal.execution.steps.CatchExceptionStep; import org.gradle.internal.execution.steps.CreateOutputsStep; import org.gradle.internal.execution.steps.ExecuteStep; -import org.gradle.internal.execution.steps.PrepareCachingStep; import org.gradle.internal.execution.steps.RecordOutputsStep; import org.gradle.internal.execution.steps.ResolveChangesStep; import org.gradle.internal.execution.steps.SkipUpToDateStep; @@ -129,16 +126,14 @@ public WorkExecutor createWorkExecutor( new SkipUpToDateStep( new RecordOutputsStep(outputFilesRepository, new StoreSnapshotsStep( - new PrepareCachingStep( - new CacheStep(buildCacheController, outputChangeListener, buildCacheCommandFactory, - new SnapshotOutputsStep(buildInvocationScopeId.getId(), - new CreateOutputsStep( - new CatchExceptionStep( - new TimeoutStep(timeoutHandler, - new CancelExecutionStep(cancellationToken, - new BroadcastChangingOutputsStep(outputChangeListener, - new ExecuteStep() - ) + new CacheStep(buildCacheController, outputChangeListener, buildCacheCommandFactory, + new SnapshotOutputsStep(buildInvocationScopeId.getId(), + new CreateOutputsStep( + new CatchExceptionStep( + new TimeoutStep(timeoutHandler, + new CancelExecutionStep(cancellationToken, + new BroadcastChangingOutputsStep(outputChangeListener, + new ExecuteStep() ) ) ) diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/DefaultDependencyManagementServices.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/DefaultDependencyManagementServices.java index 527823f6b4991..6975bdb910b5c 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/DefaultDependencyManagementServices.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/DefaultDependencyManagementServices.java @@ -117,7 +117,6 @@ import org.gradle.internal.execution.steps.CatchExceptionStep; import org.gradle.internal.execution.steps.CreateOutputsStep; import org.gradle.internal.execution.steps.ExecuteStep; -import org.gradle.internal.execution.steps.PrepareCachingStep; import org.gradle.internal.execution.steps.ResolveChangesStep; import org.gradle.internal.execution.steps.SkipUpToDateStep; import org.gradle.internal.execution.steps.SnapshotOutputsStep; @@ -208,14 +207,12 @@ WorkExecutor createWorkExecutor( new ResolveChangesStep<>(changeDetector, new SkipUpToDateStep<>( new StoreSnapshotsStep<>( - new PrepareCachingStep<>( - new SnapshotOutputsStep<>(fixedUniqueId, - new CreateOutputsStep<>( - new CatchExceptionStep<>( - new TimeoutStep<>(timeoutHandler, - new BroadcastChangingOutputsStep<>(outputChangeListener, - new ExecuteStep<>() - ) + new SnapshotOutputsStep<>(fixedUniqueId, + new CreateOutputsStep<>( + new CatchExceptionStep<>( + new TimeoutStep<>(timeoutHandler, + new BroadcastChangingOutputsStep<>(outputChangeListener, + new ExecuteStep<>() ) ) ) diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/CachingContext.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/CachingContext.java deleted file mode 100644 index 4eb922f9f7224..0000000000000 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/CachingContext.java +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright 2018 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.gradle.internal.execution; - -public interface CachingContext extends IncrementalChangesContext { - CacheHandler getCacheHandler(); -} diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/CacheStep.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/CacheStep.java index bc098fa84a421..e9ef608fa1f75 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/CacheStep.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/CacheStep.java @@ -25,9 +25,9 @@ import org.gradle.caching.internal.packaging.UnrecoverableUnpackingException; import org.gradle.internal.Try; import org.gradle.internal.execution.CacheHandler; -import org.gradle.internal.execution.CachingContext; import org.gradle.internal.execution.CurrentSnapshotResult; import org.gradle.internal.execution.ExecutionOutcome; +import org.gradle.internal.execution.IncrementalChangesContext; import org.gradle.internal.execution.OutputChangeListener; import org.gradle.internal.execution.Step; import org.gradle.internal.execution.UnitOfWork; @@ -38,7 +38,7 @@ import javax.annotation.Nullable; import java.util.Optional; -public class CacheStep implements Step { +public class CacheStep implements Step { private static final Logger LOGGER = LoggerFactory.getLogger(CacheStep.class); private final BuildCacheController buildCache; @@ -63,7 +63,7 @@ public CurrentSnapshotResult execute(C context) { if (!buildCache.isEnabled()) { return executeWithoutCache(context); } - CacheHandler cacheHandler = context.getCacheHandler(); + CacheHandler cacheHandler = context.getWork().createCacheHandler(); return cacheHandler .load(cacheKey -> load(context.getWork(), cacheKey)) .map(loadResult -> { diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/PrepareCachingStep.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/PrepareCachingStep.java deleted file mode 100644 index e59a7f3734e3e..0000000000000 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/PrepareCachingStep.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright 2018 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.gradle.internal.execution.steps; - -import org.gradle.internal.execution.CacheHandler; -import org.gradle.internal.execution.CachingContext; -import org.gradle.internal.execution.IncrementalChangesContext; -import org.gradle.internal.execution.Result; -import org.gradle.internal.execution.Step; -import org.gradle.internal.execution.UnitOfWork; -import org.gradle.internal.execution.history.AfterPreviousExecutionState; -import org.gradle.internal.execution.history.BeforeExecutionState; -import org.gradle.internal.execution.history.changes.ExecutionStateChanges; - -import java.util.Optional; - -public class PrepareCachingStep implements Step { - private final Step delegate; - - public PrepareCachingStep(Step delegate) { - this.delegate = delegate; - } - - @Override - public R execute(C context) { - CacheHandler cacheHandler = context.getWork().createCacheHandler(); - return delegate.execute(new CachingContext() { - @Override - public CacheHandler getCacheHandler() { - return cacheHandler; - } - - @Override - public Optional getChanges() { - return context.getChanges(); - } - - @Override - public Optional getRebuildReason() { - return context.getRebuildReason(); - } - - @Override - public Optional getAfterPreviousExecutionState() { - return context.getAfterPreviousExecutionState(); - } - - @Override - public Optional getBeforeExecutionState() { - return context.getBeforeExecutionState(); - } - - @Override - public UnitOfWork getWork() { - return context.getWork(); - } - }); - } -} diff --git a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/CacheStepTest.groovy b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/CacheStepTest.groovy index 6b88679e691a4..9c04666139643 100644 --- a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/CacheStepTest.groovy +++ b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/CacheStepTest.groovy @@ -21,21 +21,21 @@ import org.gradle.caching.internal.controller.BuildCacheController import org.gradle.caching.internal.origin.OriginMetadata import org.gradle.internal.Try import org.gradle.internal.execution.CacheHandler -import org.gradle.internal.execution.CachingContext import org.gradle.internal.execution.CurrentSnapshotResult import org.gradle.internal.execution.ExecutionOutcome +import org.gradle.internal.execution.IncrementalChangesContext import org.gradle.internal.execution.OutputChangeListener class CacheStepTest extends StepSpec implements FingerprinterFixture { def buildCacheController = Mock(BuildCacheController) def buildCacheCommandFactory = Mock(BuildCacheCommandFactory) def outputChangeListener = Mock(OutputChangeListener) - def step = new CacheStep(buildCacheController, outputChangeListener, buildCacheCommandFactory, delegate) + def step = new CacheStep(buildCacheController, outputChangeListener, buildCacheCommandFactory, delegate) def cacheHandler = Mock(CacheHandler) def loadMetadata = Mock(BuildCacheCommandFactory.LoadMetadata) def delegateResult = Mock(CurrentSnapshotResult) - def context = Mock(CachingContext) + def context = Mock(IncrementalChangesContext) def "loads from cache"() { def cachedOriginMetadata = Mock(OriginMetadata) @@ -51,7 +51,8 @@ class CacheStepTest extends StepSpec implements FingerprinterFixture { result.finalOutputs == outputsFromCache 1 * buildCacheController.isEnabled() >> true - 1 * context.cacheHandler >> cacheHandler + 1 * context.work >> work + 1 * work.createCacheHandler() >> cacheHandler 1 * cacheHandler.load(_) >> Optional.of(loadMetadata) 1 * loadMetadata.originMetadata >> cachedOriginMetadata 1 * loadMetadata.resultingSnapshots >> outputsFromCache @@ -66,10 +67,15 @@ class CacheStepTest extends StepSpec implements FingerprinterFixture { result == delegateResult 1 * buildCacheController.isEnabled() >> true - 1 * context.cacheHandler >> cacheHandler + 1 * context.work >> work + 1 * work.createCacheHandler() >> cacheHandler 1 * cacheHandler.load(_) >> Optional.empty() + + then: 1 * delegate.execute(context) >> delegateResult 1 * delegateResult.outcome >> Try.successful(ExecutionOutcome.EXECUTED_NON_INCREMENTALLY) + + then: 1 * cacheHandler.store(_) 0 * _ } @@ -83,10 +89,15 @@ class CacheStepTest extends StepSpec implements FingerprinterFixture { !result.reused 1 * buildCacheController.isEnabled() >> true - 1 * context.cacheHandler >> cacheHandler + 1 * context.work >> work + 1 * work.createCacheHandler() >> cacheHandler 1 * cacheHandler.load(_) >> Optional.empty() + + then: 1 * delegate.execute(context) >> delegateResult 1 * delegateResult.outcome >> Try.failure(new RuntimeException("failure")) + + then: 1 * context.work >> work 1 * work.displayName >> "Display name" 0 * cacheHandler.store(_) From 72501f42df477dffdb1081461d45dd443698e97e Mon Sep 17 00:00:00 2001 From: Louis Jacomet Date: Mon, 11 Mar 2019 10:04:12 +0100 Subject: [PATCH 453/853] Clean up test code Issue #7398 --- ...vaLibraryInteractionIntegrationTest.groovy | 23 ------------------- 1 file changed, 23 deletions(-) diff --git a/subprojects/plugins/src/integTest/groovy/org/gradle/groovy/GroovyJavaLibraryInteractionIntegrationTest.groovy b/subprojects/plugins/src/integTest/groovy/org/gradle/groovy/GroovyJavaLibraryInteractionIntegrationTest.groovy index b66e05120bbb9..0e601c5bdeae6 100644 --- a/subprojects/plugins/src/integTest/groovy/org/gradle/groovy/GroovyJavaLibraryInteractionIntegrationTest.groovy +++ b/subprojects/plugins/src/integTest/groovy/org/gradle/groovy/GroovyJavaLibraryInteractionIntegrationTest.groovy @@ -56,29 +56,6 @@ class GroovyJavaLibraryInteractionIntegrationTest extends AbstractDependencyReso dependencies { $consumerConf project(':groovyLib') } - - task assertDependsOnGroovyLib { - dependsOn compileJava - doLast { - ${ - expected == 'classes' ? ''' - def classesDirs = ['compileJava', 'compileGroovy'] - .collect { project(':groovyLib').tasks[it].destinationDir } - - assert compileJava.classpath.files.size() == 2 - assert compileJava.classpath.files.containsAll(classesDirs) - ''' : ''' - def jarFile = project(':groovyLib').tasks.jar.archiveFile.get().asFile - - assert compileJava.classpath.files.size() == 1 - assert compileJava.classpath.files.contains(jarFile) - def openJar = new java.util.jar.JarFile(jarFile) - assert openJar.getJarEntry("GroovyClass.class") - openJar.close() - ''' - } - } - } """ } } From a3e6370fd957fea55413a4838ac688865b168a33 Mon Sep 17 00:00:00 2001 From: Stefan Wolf Date: Mon, 11 Mar 2019 11:07:15 +0100 Subject: [PATCH 454/853] Improve variable name --- .../artifacts/transform/TransformingArtifactVisitor.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/TransformingArtifactVisitor.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/TransformingArtifactVisitor.java index 8cc80cdccb5a3..540de65df2cdf 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/TransformingArtifactVisitor.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/TransformingArtifactVisitor.java @@ -79,8 +79,8 @@ public boolean requireArtifactFiles() { @Override public void visitFile(ComponentArtifactIdentifier artifactIdentifier, DisplayName variantName, AttributeContainer variantAttributes, File file) { - TransformationResult operation = fileResults.get(file); - operation.getTransformedSubject().ifSuccessfulOrElse( + TransformationResult result = fileResults.get(file); + result.getTransformedSubject().ifSuccessfulOrElse( transformedSubject -> { for (File outputFile : transformedSubject.getFiles()) { visitor.visitFile(new ComponentFileArtifactIdentifier(artifactIdentifier.getComponentIdentifier(), outputFile.getName()), variantName, target, outputFile); From 287b7e0cb969d1042d5e3f55776495eb4082a903 Mon Sep 17 00:00:00 2001 From: Louis Jacomet Date: Mon, 11 Mar 2019 11:42:00 +0100 Subject: [PATCH 455/853] Mention James Nelson in release notes --- subprojects/docs/src/docs/release/notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/subprojects/docs/src/docs/release/notes.md b/subprojects/docs/src/docs/release/notes.md index 6a8d833cced64..2dba45d459e5f 100644 --- a/subprojects/docs/src/docs/release/notes.md +++ b/subprojects/docs/src/docs/release/notes.md @@ -15,6 +15,7 @@ We would like to thank the following community contributors to this release of G [Ricardo Pereira](https://github.com/thc202), [Thad House](https://github.com/ThadHouse), [Joe Kutner](https://github.com/jkutner), +[James Nelson](https://github.com/JamesXNelson), and [Josh Soref](https://github.com/jsoref). ## Upgrade Instructions From 579d3af71433cdd314ec2e38734c72cb528d3c87 Mon Sep 17 00:00:00 2001 From: Cedric Champeau Date: Mon, 11 Mar 2019 10:22:20 +0100 Subject: [PATCH 456/853] Fix class cast exception when serializing integer attributes Hotfix for #8725 --- .../result/DesugaredAttributeContainerSerializer.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/result/DesugaredAttributeContainerSerializer.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/result/DesugaredAttributeContainerSerializer.java index 9382132dfa9f4..8f738cbe033c6 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/result/DesugaredAttributeContainerSerializer.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/result/DesugaredAttributeContainerSerializer.java @@ -37,6 +37,7 @@ public class DesugaredAttributeContainerSerializer extends AbstractSerializer Date: Mon, 11 Mar 2019 10:50:36 +0100 Subject: [PATCH 457/853] Update test case to illustrate error The test case used a String for the Java version, which works, but in practice the attribute is an `Integer`. Coercion did the magic, but if we use the _real_ type, it would have failed. --- ...rossProjectTargetJvmVersionIntegrationTest.groovy | 2 +- ...ryPublishedTargetJvmVersionIntegrationTest.groovy | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/subprojects/plugins/src/integTest/groovy/org/gradle/java/JavaLibraryCrossProjectTargetJvmVersionIntegrationTest.groovy b/subprojects/plugins/src/integTest/groovy/org/gradle/java/JavaLibraryCrossProjectTargetJvmVersionIntegrationTest.groovy index d7914f42f06a1..ab5cb231fd9bb 100644 --- a/subprojects/plugins/src/integTest/groovy/org/gradle/java/JavaLibraryCrossProjectTargetJvmVersionIntegrationTest.groovy +++ b/subprojects/plugins/src/integTest/groovy/org/gradle/java/JavaLibraryCrossProjectTargetJvmVersionIntegrationTest.groovy @@ -168,7 +168,7 @@ class JavaLibraryCrossProjectTargetJvmVersionIntegrationTest extends AbstractInt variant("apiElements", [ 'org.gradle.category': 'library', 'org.gradle.dependency.bundling': 'external', - 'org.gradle.jvm.version': '7', + 'org.gradle.jvm.version': 7, 'org.gradle.usage':'java-api-jars' ]) artifact group:'', module:'', version: '', type: '', name: 'main', noType: true diff --git a/subprojects/plugins/src/integTest/groovy/org/gradle/java/JavaLibraryPublishedTargetJvmVersionIntegrationTest.groovy b/subprojects/plugins/src/integTest/groovy/org/gradle/java/JavaLibraryPublishedTargetJvmVersionIntegrationTest.groovy index 1b79679521a32..4d314debbf94f 100644 --- a/subprojects/plugins/src/integTest/groovy/org/gradle/java/JavaLibraryPublishedTargetJvmVersionIntegrationTest.groovy +++ b/subprojects/plugins/src/integTest/groovy/org/gradle/java/JavaLibraryPublishedTargetJvmVersionIntegrationTest.groovy @@ -50,27 +50,27 @@ class JavaLibraryPublishedTargetJvmVersionIntegrationTest extends AbstractHttpDe .adhocVariants() .variant("apiElementsJdk6", [ 'org.gradle.dependency.bundling': 'external', - 'org.gradle.jvm.version': '6', + 'org.gradle.jvm.version': 6, 'org.gradle.usage': 'java-api-jars'], { artifact('producer-1.0-jdk6.jar') }) .variant("apiElementsJdk7", [ 'org.gradle.dependency.bundling': 'external', - 'org.gradle.jvm.version': '7', + 'org.gradle.jvm.version': 7, 'org.gradle.usage': 'java-api-jars'], { artifact('producer-1.0-jdk7.jar') }) .variant("apiElementsJdk9", [ 'org.gradle.dependency.bundling': 'external', - 'org.gradle.jvm.version': '9', + 'org.gradle.jvm.version': 9, 'org.gradle.usage': 'java-api-jars'], { artifact('producer-1.0-jdk9.jar') }) .variant("runtimeElementsJdk6", [ 'org.gradle.dependency.bundling': 'external', - 'org.gradle.jvm.version': '6', + 'org.gradle.jvm.version': 6, 'org.gradle.usage': 'java-runtime-jars'], { artifact('producer-1.0-jdk6.jar') }) .variant("runtimeElementsJdk7", [ 'org.gradle.dependency.bundling': 'external', - 'org.gradle.jvm.version': '7', + 'org.gradle.jvm.version': 7, 'org.gradle.usage': 'java-runtime-jars'], { artifact('producer-1.0-jdk7.jar') }) .variant("runtimeElementsJdk9", [ 'org.gradle.dependency.bundling': 'external', - 'org.gradle.jvm.version': '9', + 'org.gradle.jvm.version': 9, 'org.gradle.usage': 'java-runtime-jars'], { artifact('producer-1.0-jdk9.jar') }) .publish() From c49b44cee493077194fd787c2fef2eff5b424702 Mon Sep 17 00:00:00 2001 From: Stefan Wolf Date: Mon, 11 Mar 2019 14:26:40 +0100 Subject: [PATCH 458/853] Rebaseline RealLifeAndroidBuildPerformanceTest The newly added santa tracker android test has a regression against 5.1 which we are currently solving. Rebaselining until then. --- .../android/RealLifeAndroidBuildPerformanceTest.groovy | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/subprojects/performance/src/performanceTest/groovy/org/gradle/performance/regression/android/RealLifeAndroidBuildPerformanceTest.groovy b/subprojects/performance/src/performanceTest/groovy/org/gradle/performance/regression/android/RealLifeAndroidBuildPerformanceTest.groovy index 4d4c6591b15e1..2551ef930e0f9 100644 --- a/subprojects/performance/src/performanceTest/groovy/org/gradle/performance/regression/android/RealLifeAndroidBuildPerformanceTest.groovy +++ b/subprojects/performance/src/performanceTest/groovy/org/gradle/performance/regression/android/RealLifeAndroidBuildPerformanceTest.groovy @@ -29,8 +29,8 @@ class RealLifeAndroidBuildPerformanceTest extends AbstractAndroidPerformanceTest runner.args = parallel ? ['-Dorg.gradle.parallel=true'] : [] runner.warmUpRuns = warmUpRuns runner.runs = runs - runner.minimumVersion = "4.3.1" - runner.targetVersions = ["5.2-20181218000039+0000"] + runner.minimumVersion = "5.1.1" + runner.targetVersions = ["5.4-20190311000052+0000"] when: def result = runner.run() From d822b5018297fa80f106506b23d9e4590c9c904c Mon Sep 17 00:00:00 2001 From: Bo Zhang Date: Mon, 11 Mar 2019 21:55:59 +0800 Subject: [PATCH 459/853] Make patchKotlinCompilerEmbeddable depend on classpathManifest (#8734) This fixes https://github.com/gradle/gradle-private/issues/1930 Previously, `:kotlinCompilerEmbeddable:patchKotlinCompilerEmbeddable` doesn't depends on `:kotlinCompilerEmbeddable:classpathManifest`, which may result in the patched kotlin jar not including classpath property files. This commit fixes this issue by making implicit dependencies. --- .../kotlin-compiler-embeddable.gradle.kts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/subprojects/kotlin-compiler-embeddable/kotlin-compiler-embeddable.gradle.kts b/subprojects/kotlin-compiler-embeddable/kotlin-compiler-embeddable.gradle.kts index 5b6771b634145..f924ef2428ad1 100644 --- a/subprojects/kotlin-compiler-embeddable/kotlin-compiler-embeddable.gradle.kts +++ b/subprojects/kotlin-compiler-embeddable/kotlin-compiler-embeddable.gradle.kts @@ -55,9 +55,8 @@ tasks { dependenciesIncludes.set(mapOf( "jansi-" to listOf("META-INF/native/**", "org/fusesource/jansi/internal/CLibrary*.class") )) - additionalFiles = fileTree(classpathManifest.get().manifestFile.parentFile) { - include(classpathManifest.get().manifestFile.name) - } + additionalFiles = files(classpathManifest).asFileTree + outputFile.set(jar.get().archiveFile) } From ce2f22950ef5ceb0c2677061f0ee143abd55c264 Mon Sep 17 00:00:00 2001 From: Bo Zhang Date: Mon, 11 Mar 2019 21:55:59 +0800 Subject: [PATCH 460/853] Make patchKotlinCompilerEmbeddable depend on classpathManifest (#8734) This fixes https://github.com/gradle/gradle-private/issues/1930 Previously, `:kotlinCompilerEmbeddable:patchKotlinCompilerEmbeddable` doesn't depends on `:kotlinCompilerEmbeddable:classpathManifest`, which may result in the patched kotlin jar not including classpath property files. This commit fixes this issue by making implicit dependencies. --- .../kotlin-compiler-embeddable.gradle.kts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/subprojects/kotlin-compiler-embeddable/kotlin-compiler-embeddable.gradle.kts b/subprojects/kotlin-compiler-embeddable/kotlin-compiler-embeddable.gradle.kts index 5b6771b634145..f924ef2428ad1 100644 --- a/subprojects/kotlin-compiler-embeddable/kotlin-compiler-embeddable.gradle.kts +++ b/subprojects/kotlin-compiler-embeddable/kotlin-compiler-embeddable.gradle.kts @@ -55,9 +55,8 @@ tasks { dependenciesIncludes.set(mapOf( "jansi-" to listOf("META-INF/native/**", "org/fusesource/jansi/internal/CLibrary*.class") )) - additionalFiles = fileTree(classpathManifest.get().manifestFile.parentFile) { - include(classpathManifest.get().manifestFile.name) - } + additionalFiles = files(classpathManifest).asFileTree + outputFile.set(jar.get().archiveFile) } From 375e8a46b0cde8a91f1b714a23ef42472e7bb9c7 Mon Sep 17 00:00:00 2001 From: Cedric Champeau Date: Mon, 11 Mar 2019 16:05:23 +0100 Subject: [PATCH 461/853] Fix merge conflict --- .../transform/AttributeMatchingVariantSelectorSpec.groovy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/AttributeMatchingVariantSelectorSpec.groovy b/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/AttributeMatchingVariantSelectorSpec.groovy index bbef56d1fb673..ae2a0c6293a23 100644 --- a/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/AttributeMatchingVariantSelectorSpec.groovy +++ b/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/AttributeMatchingVariantSelectorSpec.groovy @@ -257,7 +257,7 @@ class AttributeMatchingVariantSelectorSpec extends Specification { } def transform1 = Mock(Transformation) def transform2 = Mock(Transformation) - def selector = new AttributeMatchingVariantSelector(consumerProvidedVariantFinder, attributesSchema, attributesFactory, requestedAttributes, false, dependenciesResolverFactory) + def selector = new AttributeMatchingVariantSelector(consumerProvidedVariantFinder, attributesSchema, attributesFactory, transformationNodeRegistry, requestedAttributes, false, dependenciesResolverFactory) when: def result = selector.select(multiVariantSet) From cb19a113017a9351f8d9fa767d50a9a0f590617a Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Mon, 11 Mar 2019 17:20:47 +0100 Subject: [PATCH 462/853] Revert "Run tests against JUnit 4.13-beta-2" This reverts commit 05d0a7b3b44f29d01fac4a160e23999858c04851. --- .../org/gradle/testing/fixture/JUnitCoverage.groovy | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/subprojects/testing-jvm/src/integTest/groovy/org/gradle/testing/fixture/JUnitCoverage.groovy b/subprojects/testing-jvm/src/integTest/groovy/org/gradle/testing/fixture/JUnitCoverage.groovy index 66c1c8441a88c..80f54e3c51eb2 100644 --- a/subprojects/testing-jvm/src/integTest/groovy/org/gradle/testing/fixture/JUnitCoverage.groovy +++ b/subprojects/testing-jvm/src/integTest/groovy/org/gradle/testing/fixture/JUnitCoverage.groovy @@ -25,17 +25,16 @@ import org.gradle.api.JavaVersion */ class JUnitCoverage { final static String NEWEST = '4.12' - final static String PREVIEW = '4.13-beta-2' final static String LATEST_JUPITER_VERSION = '5.4.0' final static String LATEST_VINTAGE_VERSION = '5.4.0' final static String JUPITER = 'Jupiter:' + LATEST_JUPITER_VERSION final static String VINTAGE = 'Vintage:' + LATEST_VINTAGE_VERSION - final static String[] LARGE_COVERAGE = ['4.0', '4.4', '4.8.2', NEWEST, PREVIEW] - final static String[] IGNORE_ON_CLASS = ['4.4', '4.8.2', NEWEST, PREVIEW] - final static String[] ASSUMPTIONS = ['4.5', NEWEST, PREVIEW] - final static String[] CATEGORIES = ['4.8', NEWEST, PREVIEW] - final static String[] FILTER_JUNIT3_TESTS = ['3.8.1', '4.6', NEWEST, PREVIEW] - final static String[] JUNIT_4_LATEST = [NEWEST, PREVIEW] + final static String[] LARGE_COVERAGE = ['4.0', '4.4', '4.8.2', NEWEST] + final static String[] IGNORE_ON_CLASS = ['4.4', '4.8.2', NEWEST] + final static String[] ASSUMPTIONS = ['4.5', NEWEST] + final static String[] CATEGORIES = ['4.8', NEWEST] + final static String[] FILTER_JUNIT3_TESTS = ['3.8.1', '4.6', NEWEST] + final static String[] JUNIT_4_LATEST = [NEWEST] final static String[] JUNIT_VINTAGE = emptyIfJava7(VINTAGE) final static String[] JUNIT_VINTAGE_JUPITER = emptyIfJava7(VINTAGE, JUPITER) From 116bee4d5045cecebe0205de6b0b5be4740ae32c Mon Sep 17 00:00:00 2001 From: "Rodrigo B. de Oliveira" Date: Mon, 11 Mar 2019 15:44:31 -0300 Subject: [PATCH 463/853] Move `kotlinDsl` generated sources to `$buildDir/generated-sources` And remove no longer necessary `clean` task configuration. --- .../kotlin/codegen/GenerateKotlinDependencyExtensions.kt | 7 +++---- subprojects/kotlin-dsl/kotlin-dsl.gradle.kts | 8 ++------ 2 files changed, 5 insertions(+), 10 deletions(-) diff --git a/buildSrc/subprojects/kotlin-dsl/src/main/kotlin/codegen/GenerateKotlinDependencyExtensions.kt b/buildSrc/subprojects/kotlin-dsl/src/main/kotlin/codegen/GenerateKotlinDependencyExtensions.kt index 3f609a42c4da9..f9e79e5d1c2cc 100644 --- a/buildSrc/subprojects/kotlin-dsl/src/main/kotlin/codegen/GenerateKotlinDependencyExtensions.kt +++ b/buildSrc/subprojects/kotlin-dsl/src/main/kotlin/codegen/GenerateKotlinDependencyExtensions.kt @@ -22,13 +22,12 @@ import org.gradle.api.tasks.Input import org.gradle.api.tasks.OutputFile import org.gradle.api.tasks.TaskAction -import java.io.File - +@Suppress("unused") open class GenerateKotlinDependencyExtensions : DefaultTask() { @get:OutputFile - var outputFile: File? = null + val outputFile = project.objects.fileProperty() @get:Input var embeddedKotlinVersion: String? = null @@ -39,7 +38,7 @@ open class GenerateKotlinDependencyExtensions : DefaultTask() { @Suppress("unused") @TaskAction fun generate() { - outputFile!!.writeText( + outputFile.get().asFile.writeText( """$licenseHeader package org.gradle.kotlin.dsl diff --git a/subprojects/kotlin-dsl/kotlin-dsl.gradle.kts b/subprojects/kotlin-dsl/kotlin-dsl.gradle.kts index 78bb1c93f3ea5..9d281cf33c9a1 100644 --- a/subprojects/kotlin-dsl/kotlin-dsl.gradle.kts +++ b/subprojects/kotlin-dsl/kotlin-dsl.gradle.kts @@ -70,7 +70,7 @@ dependencies { } // --- Enable automatic generation of API extensions ------------------- -val apiExtensionsOutputDir = file("src/generated/kotlin") +val apiExtensionsOutputDir = layout.buildDirectory.dir("generated-sources/kotlin") val publishedKotlinDslPluginVersion = "1.2.5" // TODO:kotlin-dsl @@ -82,7 +82,7 @@ tasks { } val generateKotlinDependencyExtensions by registering(GenerateKotlinDependencyExtensions::class) { - outputFile = apiExtensionsOutputDir.resolve("org/gradle/kotlin/dsl/KotlinDependencyExtensions.kt") + outputFile.set(apiExtensionsOutputDir.get().file("org/gradle/kotlin/dsl/KotlinDependencyExtensions.kt")) embeddedKotlinVersion = kotlinVersion kotlinDslPluginsVersion = publishedKotlinDslPluginVersion } @@ -95,10 +95,6 @@ tasks { kotlin.srcDir(files(apiExtensionsOutputDir).builtBy(generateExtensions)) } - clean { - delete(apiExtensionsOutputDir) - } - // -- Version manifest properties -------------------------------------- val writeVersionsManifest by registering(WriteProperties::class) { outputFile = buildDir.resolve("versionsManifest/gradle-kotlin-dsl-versions.properties") From 84c01bc2c3377157ef1672445438e9c6b9f9e7ea Mon Sep 17 00:00:00 2001 From: Gary Hale Date: Mon, 11 Mar 2019 16:22:19 -0400 Subject: [PATCH 464/853] Add JDK12 in-process testing jobs to experimental pipeline --- .teamcity/Gradle_Check/model/CIBuildModel.kt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.teamcity/Gradle_Check/model/CIBuildModel.kt b/.teamcity/Gradle_Check/model/CIBuildModel.kt index dad653f42ad9e..828260e28b8f9 100644 --- a/.teamcity/Gradle_Check/model/CIBuildModel.kt +++ b/.teamcity/Gradle_Check/model/CIBuildModel.kt @@ -84,6 +84,8 @@ data class CIBuildModel ( trigger = Trigger.never, runsIndependent = true, functionalTests = listOf( + TestCoverage(TestType.quick, Os.linux, JvmVersion.java12, vendor = JvmVendor.openjdk) + TestCoverage(TestType.quick, Os.windows, JvmVersion.java12, vendor = JvmVendor.openjdk), TestCoverage(TestType.platform, Os.linux, JvmVersion.java12, vendor = JvmVendor.openjdk), TestCoverage(TestType.platform, Os.windows, JvmVersion.java12, vendor = JvmVendor.openjdk)) ) From ddd8e29530fe8f7f020cd91e638fa732ce391b1b Mon Sep 17 00:00:00 2001 From: Daniel Lacasse Date: Mon, 11 Mar 2019 22:22:22 +0100 Subject: [PATCH 465/853] Publish 5.3-rc-2 --- released-versions.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/released-versions.json b/released-versions.json index 2c490c93a39a1..6c7ecb79d1ce4 100644 --- a/released-versions.json +++ b/released-versions.json @@ -4,8 +4,8 @@ "buildTime": "20190311010311+0000" }, "latestRc": { - "version": "5.3-rc-1", - "buildTime": "20190305205202+0000" + "version": "5.3-rc-2", + "buildTime": "20190311210726+0000" }, "finalReleases": [ { From 0adc13d04cc1c493eb730eac5a49f4111b977385 Mon Sep 17 00:00:00 2001 From: Gary Hale Date: Mon, 11 Mar 2019 17:24:20 -0400 Subject: [PATCH 466/853] fix typo in JDK12 experimental pipeline config --- .teamcity/Gradle_Check/model/CIBuildModel.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.teamcity/Gradle_Check/model/CIBuildModel.kt b/.teamcity/Gradle_Check/model/CIBuildModel.kt index 828260e28b8f9..4659a816131b0 100644 --- a/.teamcity/Gradle_Check/model/CIBuildModel.kt +++ b/.teamcity/Gradle_Check/model/CIBuildModel.kt @@ -84,7 +84,7 @@ data class CIBuildModel ( trigger = Trigger.never, runsIndependent = true, functionalTests = listOf( - TestCoverage(TestType.quick, Os.linux, JvmVersion.java12, vendor = JvmVendor.openjdk) + TestCoverage(TestType.quick, Os.linux, JvmVersion.java12, vendor = JvmVendor.openjdk), TestCoverage(TestType.quick, Os.windows, JvmVersion.java12, vendor = JvmVendor.openjdk), TestCoverage(TestType.platform, Os.linux, JvmVersion.java12, vendor = JvmVendor.openjdk), TestCoverage(TestType.platform, Os.windows, JvmVersion.java12, vendor = JvmVendor.openjdk)) From 98c9a12701928c566c31795fef45877e0e1ad9eb Mon Sep 17 00:00:00 2001 From: Stefan Wolf Date: Fri, 8 Mar 2019 11:45:55 +0100 Subject: [PATCH 467/853] Add missing Override annotations --- .../src/main/java/org/gradle/internal/change/FileChange.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/subprojects/snapshots/src/main/java/org/gradle/internal/change/FileChange.java b/subprojects/snapshots/src/main/java/org/gradle/internal/change/FileChange.java index 9c0584b0c9ae6..063d84319732a 100644 --- a/subprojects/snapshots/src/main/java/org/gradle/internal/change/FileChange.java +++ b/subprojects/snapshots/src/main/java/org/gradle/internal/change/FileChange.java @@ -49,6 +49,7 @@ private FileChange(String path, ChangeType change, String title, FileType previo this.currentFileType = currentFileType; } + @Override public String getMessage() { return title + " file " + path + " " + getDisplayedChangeType().describe() + "."; } @@ -75,6 +76,7 @@ public String getPath() { return path; } + @Override public File getFile() { return new File(path); } @@ -83,14 +85,17 @@ public ChangeType getType() { return change; } + @Override public boolean isAdded() { return change == ChangeType.ADDED; } + @Override public boolean isModified() { return change == ChangeType.MODIFIED; } + @Override public boolean isRemoved() { return change == ChangeType.REMOVED; } From adb3fda2d72e5d730aa04d690a371b499e0a108c Mon Sep 17 00:00:00 2001 From: Stefan Wolf Date: Mon, 11 Mar 2019 14:04:51 +0100 Subject: [PATCH 468/853] Remove unused DefaultExecutionStateChanges --- .../changes/DefaultExecutionStateChanges.java | 125 ------------------ 1 file changed, 125 deletions(-) delete mode 100644 subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/DefaultExecutionStateChanges.java diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/DefaultExecutionStateChanges.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/DefaultExecutionStateChanges.java deleted file mode 100644 index afd599ed2f0dd..0000000000000 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/DefaultExecutionStateChanges.java +++ /dev/null @@ -1,125 +0,0 @@ -/* - * Copyright 2018 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.gradle.internal.execution.history.changes; - -import org.gradle.api.Describable; -import org.gradle.internal.change.CachingChangeContainer; -import org.gradle.internal.change.Change; -import org.gradle.internal.change.ChangeContainer; -import org.gradle.internal.change.ChangeDetectorVisitor; -import org.gradle.internal.change.ChangeVisitor; -import org.gradle.internal.change.CollectingChangeVisitor; -import org.gradle.internal.change.ErrorHandlingChangeContainer; -import org.gradle.internal.change.SummarizingChangeContainer; -import org.gradle.internal.execution.history.AfterPreviousExecutionState; -import org.gradle.internal.execution.history.BeforeExecutionState; - -import java.util.Optional; - -public class DefaultExecutionStateChanges implements ExecutionStateChanges { - - private final AfterPreviousExecutionState previousExecution; - private final ChangeContainer inputFileChanges; - private final ChangeContainer allChanges; - private final ChangeContainer rebuildTriggeringChanges; - - public DefaultExecutionStateChanges(AfterPreviousExecutionState lastExecution, BeforeExecutionState thisExecution, Describable executable, boolean includeAddedOutputs) { - this.previousExecution = lastExecution; - - // Capture changes in execution outcome - ChangeContainer previousSuccessState = new PreviousSuccessChanges( - lastExecution.isSuccessful()); - - // Capture changes to implementation - ChangeContainer implementationChanges = new ImplementationChanges( - lastExecution.getImplementation(), lastExecution.getAdditionalImplementations(), - thisExecution.getImplementation(), thisExecution.getAdditionalImplementations(), - executable); - - // Capture non-file input changes - ChangeContainer inputPropertyChanges = new PropertyChanges( - lastExecution.getInputProperties(), - thisExecution.getInputProperties(), - "Input", - executable); - ChangeContainer inputPropertyValueChanges = new InputValueChanges( - lastExecution.getInputProperties(), - thisExecution.getInputProperties(), - executable); - - // Capture input files state - ChangeContainer inputFilePropertyChanges = new PropertyChanges( - lastExecution.getInputFileProperties(), - thisExecution.getInputFileProperties(), - "Input file", - executable); - InputFileChanges directInputFileChanges = new InputFileChanges( - lastExecution.getInputFileProperties(), - thisExecution.getInputFileProperties()); - ChangeContainer inputFileChanges = caching(directInputFileChanges); - this.inputFileChanges = errorHandling(executable, inputFileChanges); - - // Capture output files state - ChangeContainer outputFilePropertyChanges = new PropertyChanges( - lastExecution.getOutputFileProperties(), - thisExecution.getOutputFileProperties(), - "Output", - executable); - OutputFileChanges uncachedOutputChanges = new OutputFileChanges( - lastExecution.getOutputFileProperties(), - thisExecution.getOutputFileProperties(), - includeAddedOutputs); - ChangeContainer outputFileChanges = caching(uncachedOutputChanges); - - this.allChanges = errorHandling(executable, new SummarizingChangeContainer(previousSuccessState, implementationChanges, inputPropertyChanges, inputPropertyValueChanges, outputFilePropertyChanges, outputFileChanges, inputFilePropertyChanges, inputFileChanges)); - this.rebuildTriggeringChanges = errorHandling(executable, new SummarizingChangeContainer(previousSuccessState, implementationChanges, inputPropertyChanges, inputPropertyValueChanges, inputFilePropertyChanges, outputFilePropertyChanges, outputFileChanges)); - } - - private static ChangeContainer caching(ChangeContainer wrapped) { - return new CachingChangeContainer(MAX_OUT_OF_DATE_MESSAGES, wrapped); - } - - private static ChangeContainer errorHandling(Describable executable, ChangeContainer wrapped) { - return new ErrorHandlingChangeContainer(executable, wrapped); - } - - @Override - public Optional> getInputFilesChanges() { - if (isRebuildRequired()) { - return Optional.empty(); - } - CollectingChangeVisitor visitor = new CollectingChangeVisitor(); - inputFileChanges.accept(visitor); - return Optional.of(visitor.getChanges()); - } - - @Override - public void visitAllChanges(ChangeVisitor visitor) { - allChanges.accept(visitor); - } - - private boolean isRebuildRequired() { - ChangeDetectorVisitor changeDetectorVisitor = new ChangeDetectorVisitor(); - rebuildTriggeringChanges.accept(changeDetectorVisitor); - return changeDetectorVisitor.hasAnyChanges(); - } - - @Override - public AfterPreviousExecutionState getPreviousExecution() { - return previousExecution; - } -} From 86a3b70353c1bed76c3aa331ec9194d989b08645 Mon Sep 17 00:00:00 2001 From: Stefan Wolf Date: Mon, 11 Mar 2019 14:16:20 +0100 Subject: [PATCH 469/853] Remove ExecutionStateChanges.previousExecution --- .../changes/DefaultExecutionStateChangeDetector.java | 9 --------- .../execution/history/changes/ExecutionStateChanges.java | 7 ------- .../internal/execution/steps/ResolveChangesStep.java | 5 ----- .../internal/execution/steps/SkipUpToDateStep.java | 7 +++++-- .../internal/execution/steps/SkipUpToDateStepTest.groovy | 2 ++ 5 files changed, 7 insertions(+), 23 deletions(-) diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/DefaultExecutionStateChangeDetector.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/DefaultExecutionStateChangeDetector.java index 7efe7dda80a92..d35729ab25f4d 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/DefaultExecutionStateChangeDetector.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/DefaultExecutionStateChangeDetector.java @@ -78,7 +78,6 @@ public ExecutionStateChanges detectChanges(AfterPreviousExecutionState lastExecu ChangeContainer outputFileChanges = caching(uncachedOutputChanges); return new DetectedExecutionStateChanges( - lastExecution, errorHandling(executable, inputFileChanges), errorHandling(executable, new SummarizingChangeContainer(previousSuccessState, implementationChanges, inputPropertyChanges, inputPropertyValueChanges, outputFilePropertyChanges, outputFileChanges, inputFilePropertyChanges, inputFileChanges)), errorHandling(executable, new SummarizingChangeContainer(previousSuccessState, implementationChanges, inputPropertyChanges, inputPropertyValueChanges, inputFilePropertyChanges, outputFilePropertyChanges, outputFileChanges)) @@ -94,18 +93,15 @@ private static ChangeContainer errorHandling(Describable executable, ChangeConta } private static class DetectedExecutionStateChanges implements ExecutionStateChanges { - private final AfterPreviousExecutionState previousExecution; private final ChangeContainer inputFileChanges; private final ChangeContainer allChanges; private final ChangeContainer rebuildTriggeringChanges; public DetectedExecutionStateChanges( - AfterPreviousExecutionState previousExecution, ChangeContainer inputFileChanges, ChangeContainer allChanges, ChangeContainer rebuildTriggeringChanges ) { - this.previousExecution = previousExecution; this.inputFileChanges = inputFileChanges; this.allChanges = allChanges; this.rebuildTriggeringChanges = rebuildTriggeringChanges; @@ -131,10 +127,5 @@ private boolean isRebuildRequired() { rebuildTriggeringChanges.accept(changeDetectorVisitor); return changeDetectorVisitor.hasAnyChanges(); } - - @Override - public AfterPreviousExecutionState getPreviousExecution() { - return previousExecution; - } } } diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/ExecutionStateChanges.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/ExecutionStateChanges.java index 467543da6e870..1074f6a92dba8 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/ExecutionStateChanges.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/ExecutionStateChanges.java @@ -18,7 +18,6 @@ import org.gradle.internal.change.Change; import org.gradle.internal.change.ChangeVisitor; -import org.gradle.internal.execution.history.AfterPreviousExecutionState; import java.util.Optional; @@ -38,10 +37,4 @@ public interface ExecutionStateChanges { * Visits any change to inputs or outputs. */ void visitAllChanges(ChangeVisitor visitor); - - /** - * The base execution the changes are calculated against. - */ - // TODO Use AfterPreviousExecutionState from context instead - AfterPreviousExecutionState getPreviousExecution(); } diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/ResolveChangesStep.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/ResolveChangesStep.java index 30442a9955644..4a9240f5e6904 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/ResolveChangesStep.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/ResolveChangesStep.java @@ -110,10 +110,5 @@ public Optional> getInputFilesChanges() { public void visitAllChanges(ChangeVisitor visitor) { visitor.visitChange(rebuildChange); } - - @Override - public AfterPreviousExecutionState getPreviousExecution() { - throw new UnsupportedOperationException(); - } } } diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/SkipUpToDateStep.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/SkipUpToDateStep.java index 0f9187ad86ae7..fba313ab5fc30 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/SkipUpToDateStep.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/SkipUpToDateStep.java @@ -30,6 +30,7 @@ import org.gradle.internal.execution.Step; import org.gradle.internal.execution.UnitOfWork; import org.gradle.internal.execution.UpToDateResult; +import org.gradle.internal.execution.history.AfterPreviousExecutionState; import org.gradle.internal.fingerprint.FileCollectionFingerprint; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -62,6 +63,8 @@ public UpToDateResult execute(C context) { if (LOGGER.isInfoEnabled()) { LOGGER.info("Skipping {} as it is up-to-date.", context.getWork().getDisplayName()); } + @SuppressWarnings("OptionalGetWithoutIsPresent") + AfterPreviousExecutionState afterPreviousExecutionState = context.getAfterPreviousExecutionState().get(); return new UpToDateResult() { @Override public ImmutableList getExecutionReasons() { @@ -70,12 +73,12 @@ public ImmutableList getExecutionReasons() { @Override public ImmutableSortedMap getFinalOutputs() { - return changes.getPreviousExecution().getOutputFileProperties(); + return afterPreviousExecutionState.getOutputFileProperties(); } @Override public OriginMetadata getOriginMetadata() { - return changes.getPreviousExecution().getOriginMetadata(); + return afterPreviousExecutionState.getOriginMetadata(); } @Override diff --git a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/SkipUpToDateStepTest.groovy b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/SkipUpToDateStepTest.groovy index 141578d8e264f..2b8c3d71a284d 100644 --- a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/SkipUpToDateStepTest.groovy +++ b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/SkipUpToDateStepTest.groovy @@ -24,6 +24,7 @@ import org.gradle.internal.change.DescriptiveChange import org.gradle.internal.execution.ExecutionOutcome import org.gradle.internal.execution.IncrementalChangesContext import org.gradle.internal.execution.SnapshotResult +import org.gradle.internal.execution.history.AfterPreviousExecutionState import org.gradle.internal.execution.history.changes.ExecutionStateChanges import org.gradle.internal.fingerprint.impl.EmptyCurrentFileCollectionFingerprint @@ -43,6 +44,7 @@ class SkipUpToDateStepTest extends StepSpec { 1 * context.changes >> Optional.of(changes) 1 * changes.visitAllChanges(_) >> {} + 1 * context.afterPreviousExecutionState >> Optional.of(Mock(AfterPreviousExecutionState)) 0 * _ } From 079a19c54d9c7d444dd0e6125b66796289244eeb Mon Sep 17 00:00:00 2001 From: Stefan Wolf Date: Mon, 11 Mar 2019 18:33:16 +0100 Subject: [PATCH 470/853] Determine incremental behaviour in execution engine --- .../taskfactory/IncrementalTaskAction.java | 49 +++++++------------ .../DefaultExecutionStateChangeDetector.java | 30 +++++++----- .../changes/ExecutionStateChanges.java | 19 +++---- .../execution/steps/ResolveChangesStep.java | 28 +++++++---- .../steps/ResolveChangesStepTest.groovy | 45 +++++++++++++---- 5 files changed, 100 insertions(+), 71 deletions(-) diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/project/taskfactory/IncrementalTaskAction.java b/subprojects/core/src/main/java/org/gradle/api/internal/project/taskfactory/IncrementalTaskAction.java index 50f5644d1fafd..79dcb3cb6c5fe 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/project/taskfactory/IncrementalTaskAction.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/project/taskfactory/IncrementalTaskAction.java @@ -16,11 +16,10 @@ package org.gradle.api.internal.project.taskfactory; -import com.google.common.collect.ImmutableCollection; +import com.google.common.collect.ImmutableSortedMap; import org.gradle.api.Task; import org.gradle.api.internal.changedetection.changes.ChangesOnlyIncrementalTaskInputs; import org.gradle.api.internal.changedetection.changes.RebuildIncrementalTaskInputs; -import org.gradle.api.internal.changedetection.changes.StatefulIncrementalTaskInputs; import org.gradle.api.internal.tasks.ContextAwareTaskAction; import org.gradle.api.internal.tasks.TaskExecutionContext; import org.gradle.api.tasks.incremental.IncrementalTaskInputs; @@ -31,8 +30,6 @@ import org.gradle.internal.reflect.JavaMethod; import java.lang.reflect.Method; -import java.util.function.Function; -import java.util.function.Supplier; class IncrementalTaskAction extends StandardTaskAction implements ContextAwareTaskAction { @@ -54,39 +51,29 @@ public void releaseContext() { } protected void doExecute(final Task task, String methodName) { - IncrementalTaskInputs incrementalInputs = context.getExecutionStateChanges() - .map(new Function() { - @Override - public StatefulIncrementalTaskInputs apply(ExecutionStateChanges changes) { - return changes.getInputFilesChanges().map(new Function, StatefulIncrementalTaskInputs>() { - @Override - public StatefulIncrementalTaskInputs apply(Iterable changes) { - return createIncrementalInputs(changes); - } - }).orElseGet(new Supplier() { - @Override - public StatefulIncrementalTaskInputs get() { - return createRebuildInputs(task); - } - }); - } - }).orElseGet(new Supplier() { - @Override - public StatefulIncrementalTaskInputs get() { - return createRebuildInputs(task); - } - }); + @SuppressWarnings("OptionalGetWithoutIsPresent") + ExecutionStateChanges changes = context.getExecutionStateChanges().get(); + IncrementalTaskInputs incrementalTaskInputs = changes.visitInputFileChanges(new ExecutionStateChanges.IncrementalInputsVisitor() { + @Override + public IncrementalTaskInputs visitRebuild(ImmutableSortedMap allFileInputs) { + return createRebuildInputs(task, allFileInputs); + } - context.setTaskExecutedIncrementally(incrementalInputs.isIncremental()); - JavaMethod.of(task, Object.class, methodName, IncrementalTaskInputs.class).invoke(task, incrementalInputs); + @Override + public IncrementalTaskInputs visitIncrementalChange(Iterable inputFileChanges) { + return createIncrementalInputs(inputFileChanges); + } + }); + + context.setTaskExecutedIncrementally(incrementalTaskInputs.isIncremental()); + JavaMethod.of(task, Object.class, methodName, IncrementalTaskInputs.class).invoke(task, incrementalTaskInputs); } private ChangesOnlyIncrementalTaskInputs createIncrementalInputs(Iterable inputFilesChanges) { return instantiator.newInstance(ChangesOnlyIncrementalTaskInputs.class, inputFilesChanges); } - private RebuildIncrementalTaskInputs createRebuildInputs(Task task) { - ImmutableCollection currentInputs = context.getBeforeExecutionState().get().getInputFileProperties().values(); - return instantiator.newInstance(RebuildIncrementalTaskInputs.class, task, currentInputs); + private RebuildIncrementalTaskInputs createRebuildInputs(Task task, ImmutableSortedMap currentInputs) { + return instantiator.newInstance(RebuildIncrementalTaskInputs.class, task, currentInputs.values()); } } diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/DefaultExecutionStateChangeDetector.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/DefaultExecutionStateChangeDetector.java index d35729ab25f4d..7705a0b489b52 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/DefaultExecutionStateChangeDetector.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/DefaultExecutionStateChangeDetector.java @@ -28,8 +28,6 @@ import org.gradle.internal.execution.history.AfterPreviousExecutionState; import org.gradle.internal.execution.history.BeforeExecutionState; -import java.util.Optional; - public class DefaultExecutionStateChangeDetector implements ExecutionStateChangeDetector { @Override public ExecutionStateChanges detectChanges(AfterPreviousExecutionState lastExecution, BeforeExecutionState thisExecution, Describable executable, boolean allowOverlappingOutputs) { @@ -80,7 +78,8 @@ public ExecutionStateChanges detectChanges(AfterPreviousExecutionState lastExecu return new DetectedExecutionStateChanges( errorHandling(executable, inputFileChanges), errorHandling(executable, new SummarizingChangeContainer(previousSuccessState, implementationChanges, inputPropertyChanges, inputPropertyValueChanges, outputFilePropertyChanges, outputFileChanges, inputFilePropertyChanges, inputFileChanges)), - errorHandling(executable, new SummarizingChangeContainer(previousSuccessState, implementationChanges, inputPropertyChanges, inputPropertyValueChanges, inputFilePropertyChanges, outputFilePropertyChanges, outputFileChanges)) + errorHandling(executable, new SummarizingChangeContainer(previousSuccessState, implementationChanges, inputPropertyChanges, inputPropertyValueChanges, inputFilePropertyChanges, outputFilePropertyChanges, outputFileChanges)), + thisExecution ); } @@ -96,30 +95,29 @@ private static class DetectedExecutionStateChanges implements ExecutionStateChan private final ChangeContainer inputFileChanges; private final ChangeContainer allChanges; private final ChangeContainer rebuildTriggeringChanges; + private final BeforeExecutionState thisExecution; public DetectedExecutionStateChanges( ChangeContainer inputFileChanges, ChangeContainer allChanges, - ChangeContainer rebuildTriggeringChanges + ChangeContainer rebuildTriggeringChanges, + BeforeExecutionState thisExecution ) { this.inputFileChanges = inputFileChanges; this.allChanges = allChanges; this.rebuildTriggeringChanges = rebuildTriggeringChanges; + this.thisExecution = thisExecution; } @Override - public Optional> getInputFilesChanges() { - if (isRebuildRequired()) { - return Optional.empty(); - } - CollectingChangeVisitor visitor = new CollectingChangeVisitor(); - inputFileChanges.accept(visitor); - return Optional.of(visitor.getChanges()); + public void visitAllChanges(ChangeVisitor visitor) { + allChanges.accept(visitor); } @Override - public void visitAllChanges(ChangeVisitor visitor) { - allChanges.accept(visitor); + public T visitInputFileChanges(IncrementalInputsVisitor visitor) { + return isRebuildRequired() ? + visitor.visitRebuild(thisExecution.getInputFileProperties()) : visitor.visitIncrementalChange(collectInputFileChanges()); } private boolean isRebuildRequired() { @@ -127,5 +125,11 @@ private boolean isRebuildRequired() { rebuildTriggeringChanges.accept(changeDetectorVisitor); return changeDetectorVisitor.hasAnyChanges(); } + + private Iterable collectInputFileChanges() { + CollectingChangeVisitor visitor = new CollectingChangeVisitor(); + inputFileChanges.accept(visitor); + return visitor.getChanges(); + } } } diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/ExecutionStateChanges.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/ExecutionStateChanges.java index 1074f6a92dba8..193c6bb4fa18f 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/ExecutionStateChanges.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/ExecutionStateChanges.java @@ -16,25 +16,26 @@ package org.gradle.internal.execution.history.changes; +import com.google.common.collect.ImmutableSortedMap; import org.gradle.internal.change.Change; import org.gradle.internal.change.ChangeVisitor; - -import java.util.Optional; +import org.gradle.internal.fingerprint.CurrentFileCollectionFingerprint; /** * Represents the complete changes in execution state */ public interface ExecutionStateChanges { - int MAX_OUT_OF_DATE_MESSAGES = 3; - - /** - * Returns changes to input files only, or {@link Optional#empty()} if a full rebuild is required. - */ - Optional> getInputFilesChanges(); - /** * Visits any change to inputs or outputs. */ void visitAllChanges(ChangeVisitor visitor); + + T visitInputFileChanges(IncrementalInputsVisitor visitor); + + interface IncrementalInputsVisitor { + T visitRebuild(ImmutableSortedMap allFileInputs); + + T visitIncrementalChange(Iterable inputFileChanges); + } } diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/ResolveChangesStep.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/ResolveChangesStep.java index 4a9240f5e6904..7108f987f7dd3 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/ResolveChangesStep.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/ResolveChangesStep.java @@ -16,6 +16,7 @@ package org.gradle.internal.execution.steps; +import com.google.common.collect.ImmutableSortedMap; import org.gradle.internal.change.Change; import org.gradle.internal.change.ChangeVisitor; import org.gradle.internal.change.DescriptiveChange; @@ -28,7 +29,9 @@ import org.gradle.internal.execution.history.BeforeExecutionState; import org.gradle.internal.execution.history.changes.ExecutionStateChangeDetector; import org.gradle.internal.execution.history.changes.ExecutionStateChanges; +import org.gradle.internal.fingerprint.CurrentFileCollectionFingerprint; +import javax.annotation.Nullable; import java.util.Optional; public class ResolveChangesStep implements Step { @@ -48,12 +51,13 @@ public ResolveChangesStep( @Override public R execute(IncrementalContext context) { UnitOfWork work = context.getWork(); + Optional beforeExecutionState = context.getBeforeExecutionState(); ExecutionStateChanges changes = context.getRebuildReason() .map(rebuildReason -> - new RebuildExecutionStateChanges(new DescriptiveChange(rebuildReason)) + new RebuildExecutionStateChanges(new DescriptiveChange(rebuildReason), beforeExecutionState.orElse(null)) ) .orElseGet(() -> - context.getBeforeExecutionState() + beforeExecutionState .map(beforeExecution -> context.getAfterPreviousExecutionState() .map(afterPreviousExecution -> changeDetector.detectChanges( afterPreviousExecution, @@ -61,7 +65,7 @@ public R execute(IncrementalContext context) { work, !work.isAllowOverlappingOutputs()) ) - .orElseGet(() -> new RebuildExecutionStateChanges(NO_HISTORY)) + .orElseGet(() -> new RebuildExecutionStateChanges(NO_HISTORY, beforeExecution)) ) .orElse(null) ); @@ -84,7 +88,7 @@ public Optional getAfterPreviousExecutionState() { @Override public Optional getBeforeExecutionState() { - return context.getBeforeExecutionState(); + return beforeExecutionState; } @Override @@ -96,19 +100,25 @@ public UnitOfWork getWork() { private static class RebuildExecutionStateChanges implements ExecutionStateChanges { private final Change rebuildChange; + private final BeforeExecutionState beforeExecutionState; - public RebuildExecutionStateChanges(Change rebuildChange) { + public RebuildExecutionStateChanges(Change rebuildChange, @Nullable BeforeExecutionState beforeExecutionState) { this.rebuildChange = rebuildChange; + this.beforeExecutionState = beforeExecutionState; } @Override - public Optional> getInputFilesChanges() { - return Optional.empty(); + public void visitAllChanges(ChangeVisitor visitor) { + visitor.visitChange(rebuildChange); } @Override - public void visitAllChanges(ChangeVisitor visitor) { - visitor.visitChange(rebuildChange); + public T visitInputFileChanges(IncrementalInputsVisitor visitor) { + if (beforeExecutionState == null) { + throw new UnsupportedOperationException("Cannot query incremental inputs when input tracking is disabled."); + } + ImmutableSortedMap inputFileProperties = beforeExecutionState.getInputFileProperties(); + return visitor.visitRebuild(inputFileProperties); } } } diff --git a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/ResolveChangesStepTest.groovy b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/ResolveChangesStepTest.groovy index fbd40b82eba12..d1f065fcc919e 100644 --- a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/ResolveChangesStepTest.groovy +++ b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/ResolveChangesStepTest.groovy @@ -16,6 +16,8 @@ package org.gradle.internal.execution.steps +import com.google.common.collect.ImmutableSortedMap +import org.gradle.internal.change.Change import org.gradle.internal.execution.IncrementalChangesContext import org.gradle.internal.execution.IncrementalContext import org.gradle.internal.execution.Result @@ -23,11 +25,13 @@ import org.gradle.internal.execution.history.AfterPreviousExecutionState import org.gradle.internal.execution.history.BeforeExecutionState import org.gradle.internal.execution.history.changes.ExecutionStateChangeDetector import org.gradle.internal.execution.history.changes.ExecutionStateChanges +import org.gradle.internal.fingerprint.CurrentFileCollectionFingerprint class ResolveChangesStepTest extends StepSpec { def changeDetector = Mock(ExecutionStateChangeDetector) def step = new ResolveChangesStep(changeDetector, delegate) def context = Mock(IncrementalContext) + def beforeExecutionState = Mock(BeforeExecutionState) def delegateResult = Mock(Result) def "doesn't provide input file changes when rebuild is forced"() { @@ -40,13 +44,17 @@ class ResolveChangesStepTest extends StepSpec { 1 * context.work >> work 1 * delegate.execute(_) >> { IncrementalChangesContext delegateContext -> def changes = delegateContext.changes.get() - assert !changes.inputFilesChanges.present - String change = null - changes.visitAllChanges({ change = it.message; false }) - assert change == "Forced rebuild." + assert getRebuildReason(changes) == "Forced rebuild." + try { + changes.visitInputFileChanges(Mock(ExecutionStateChanges.IncrementalInputsVisitor)) + assert false + } catch (UnsupportedOperationException e) { + assert e.message == 'Cannot query incremental inputs when input tracking is disabled.' + } return delegateResult } 1 * context.rebuildReason >> Optional.of("Forced rebuild.") + 1 * context.beforeExecutionState >> Optional.empty() 0 * _ } @@ -77,14 +85,13 @@ class ResolveChangesStepTest extends StepSpec { 1 * context.work >> work 1 * delegate.execute(_) >> { IncrementalChangesContext delegateContext -> def changes = delegateContext.changes.get() - assert !changes.inputFilesChanges.present - String change = null - changes.visitAllChanges({ change = it.message; false }) - assert change == "No history is available." + assert !isIncremental(changes) + assert getRebuildReason(changes) == "No history is available." return delegateResult } 1 * context.rebuildReason >> Optional.empty() - 1 * context.beforeExecutionState >> Optional.of(Mock(BeforeExecutionState)) + 1 * context.beforeExecutionState >> Optional.of(beforeExecutionState) + 1 * beforeExecutionState.getInputFileProperties() >> ImmutableSortedMap.of() 1 * context.afterPreviousExecutionState >> Optional.empty() 0 * _ } @@ -112,4 +119,24 @@ class ResolveChangesStepTest extends StepSpec { 1 * changeDetector.detectChanges(afterPreviousExecutionState, beforeExecutionState, work, false) >> changes 0 * _ } + + private static boolean isIncremental(ExecutionStateChanges changes) { + return changes.visitInputFileChanges(new ExecutionStateChanges.IncrementalInputsVisitor() { + @Override + Boolean visitRebuild(ImmutableSortedMap allFileInputs) { + return false + } + + @Override + Boolean visitIncrementalChange(Iterable inputFileChanges) { + return true + } + }) + } + + private static String getRebuildReason(ExecutionStateChanges changes) { + String change = null + changes.visitAllChanges({ change = it.message; false }) + return change + } } From ef6e17c008f2297ce8fd3579f716445a432efd13 Mon Sep 17 00:00:00 2001 From: Gary Hale Date: Wed, 6 Mar 2019 08:58:25 -0500 Subject: [PATCH 471/853] Update references to 1.6 compatibility to 1.7 --- .../enforcerplugin/pom.xml | 4 +- .../flatmultimodule/webinar-parent/pom.xml | 4 +- .../multiModule/pom.xml | 4 +- .../multiModuleWithNestedParent/pom.xml | 4 +- .../multiModuleWithRemoteParent/pom.xml | 4 +- .../remoteparent/pom.xml | 4 +- .../singleModule/pom.xml | 4 +- .../testsJar/pom.xml | 4 +- ...mdPluginAuxclasspathIntegrationTest.groovy | 2 +- .../PmdPluginVersionIntegrationTest.groovy | 2 +- .../gradle/JansiEndUserIntegrationTest.groovy | 6 +- ...DependencyResolutionIntegrationTest.groovy | 60 +++++++++---------- ...DependencyResolutionIntegrationTest.groovy | 22 +++---- .../java/JavaLanguageIntegrationTest.groovy | 8 +-- .../java/JavaSourceSetIntegrationTest.groovy | 24 ++++---- .../SingleBinaryTypeWithVariantsTest.groovy | 52 ++++++++-------- .../BasicJavaCompilerIntegrationSpec.groovy | 17 +++--- ...crementalJavaCompileIntegrationTest.groovy | 2 +- ...calaCrossCompilationIntegrationTest.groovy | 2 +- ...itComponentUnderTestIntegrationTest.groovy | 14 ++--- .../r25/TestProgressCrossVersionSpec.groovy | 2 +- 21 files changed, 123 insertions(+), 122 deletions(-) diff --git a/subprojects/build-init/src/integTest/resources/org/gradle/buildinit/plugins/MavenConversionIntegrationTest/enforcerplugin/pom.xml b/subprojects/build-init/src/integTest/resources/org/gradle/buildinit/plugins/MavenConversionIntegrationTest/enforcerplugin/pom.xml index 30cc24b12a017..82ce123ea4d90 100644 --- a/subprojects/build-init/src/integTest/resources/org/gradle/buildinit/plugins/MavenConversionIntegrationTest/enforcerplugin/pom.xml +++ b/subprojects/build-init/src/integTest/resources/org/gradle/buildinit/plugins/MavenConversionIntegrationTest/enforcerplugin/pom.xml @@ -42,8 +42,8 @@ org.apache.maven.plugins maven-compiler-plugin - 1.6 - 1.6 + 1.7 + 1.7 diff --git a/subprojects/build-init/src/integTest/resources/org/gradle/buildinit/plugins/MavenConversionIntegrationTest/flatmultimodule/webinar-parent/pom.xml b/subprojects/build-init/src/integTest/resources/org/gradle/buildinit/plugins/MavenConversionIntegrationTest/flatmultimodule/webinar-parent/pom.xml index a1c5e72658e8a..b7a6212acd6e7 100644 --- a/subprojects/build-init/src/integTest/resources/org/gradle/buildinit/plugins/MavenConversionIntegrationTest/flatmultimodule/webinar-parent/pom.xml +++ b/subprojects/build-init/src/integTest/resources/org/gradle/buildinit/plugins/MavenConversionIntegrationTest/flatmultimodule/webinar-parent/pom.xml @@ -34,8 +34,8 @@ org.apache.maven.plugins maven-compiler-plugin - 1.6 - 1.6 + 1.7 + 1.7 diff --git a/subprojects/build-init/src/integTest/resources/org/gradle/buildinit/plugins/MavenConversionIntegrationTest/multiModule/pom.xml b/subprojects/build-init/src/integTest/resources/org/gradle/buildinit/plugins/MavenConversionIntegrationTest/multiModule/pom.xml index c7d9e282bcedd..7c438834abc87 100644 --- a/subprojects/build-init/src/integTest/resources/org/gradle/buildinit/plugins/MavenConversionIntegrationTest/multiModule/pom.xml +++ b/subprojects/build-init/src/integTest/resources/org/gradle/buildinit/plugins/MavenConversionIntegrationTest/multiModule/pom.xml @@ -34,8 +34,8 @@ org.apache.maven.plugins maven-compiler-plugin - 1.6 - 1.6 + 1.7 + 1.7 diff --git a/subprojects/build-init/src/integTest/resources/org/gradle/buildinit/plugins/MavenConversionIntegrationTest/multiModuleWithNestedParent/pom.xml b/subprojects/build-init/src/integTest/resources/org/gradle/buildinit/plugins/MavenConversionIntegrationTest/multiModuleWithNestedParent/pom.xml index 4b33064fd9894..43afc72e389dc 100644 --- a/subprojects/build-init/src/integTest/resources/org/gradle/buildinit/plugins/MavenConversionIntegrationTest/multiModuleWithNestedParent/pom.xml +++ b/subprojects/build-init/src/integTest/resources/org/gradle/buildinit/plugins/MavenConversionIntegrationTest/multiModuleWithNestedParent/pom.xml @@ -26,8 +26,8 @@ org.apache.maven.plugins maven-compiler-plugin - 1.6 - 1.6 + 1.7 + 1.7 diff --git a/subprojects/build-init/src/integTest/resources/org/gradle/buildinit/plugins/MavenConversionIntegrationTest/multiModuleWithRemoteParent/pom.xml b/subprojects/build-init/src/integTest/resources/org/gradle/buildinit/plugins/MavenConversionIntegrationTest/multiModuleWithRemoteParent/pom.xml index 5866f29dc0eb7..ec71537a8a5f4 100644 --- a/subprojects/build-init/src/integTest/resources/org/gradle/buildinit/plugins/MavenConversionIntegrationTest/multiModuleWithRemoteParent/pom.xml +++ b/subprojects/build-init/src/integTest/resources/org/gradle/buildinit/plugins/MavenConversionIntegrationTest/multiModuleWithRemoteParent/pom.xml @@ -48,8 +48,8 @@ org.apache.maven.plugins maven-compiler-plugin - 1.6 - 1.6 + 1.7 + 1.7 diff --git a/subprojects/build-init/src/integTest/resources/org/gradle/buildinit/plugins/MavenConversionIntegrationTest/remoteparent/pom.xml b/subprojects/build-init/src/integTest/resources/org/gradle/buildinit/plugins/MavenConversionIntegrationTest/remoteparent/pom.xml index d3de13ada3426..ea72edb34d1cd 100644 --- a/subprojects/build-init/src/integTest/resources/org/gradle/buildinit/plugins/MavenConversionIntegrationTest/remoteparent/pom.xml +++ b/subprojects/build-init/src/integTest/resources/org/gradle/buildinit/plugins/MavenConversionIntegrationTest/remoteparent/pom.xml @@ -24,8 +24,8 @@ org.apache.maven.plugins maven-compiler-plugin - 1.6 - 1.6 + 1.7 + 1.7 diff --git a/subprojects/build-init/src/integTest/resources/org/gradle/buildinit/plugins/MavenConversionIntegrationTest/singleModule/pom.xml b/subprojects/build-init/src/integTest/resources/org/gradle/buildinit/plugins/MavenConversionIntegrationTest/singleModule/pom.xml index a9b66b3c97a20..a436695b48acf 100644 --- a/subprojects/build-init/src/integTest/resources/org/gradle/buildinit/plugins/MavenConversionIntegrationTest/singleModule/pom.xml +++ b/subprojects/build-init/src/integTest/resources/org/gradle/buildinit/plugins/MavenConversionIntegrationTest/singleModule/pom.xml @@ -26,8 +26,8 @@ org.apache.maven.plugins maven-compiler-plugin - 1.6 - 1.6 + 1.7 + 1.7 diff --git a/subprojects/build-init/src/integTest/resources/org/gradle/buildinit/plugins/MavenConversionIntegrationTest/testsJar/pom.xml b/subprojects/build-init/src/integTest/resources/org/gradle/buildinit/plugins/MavenConversionIntegrationTest/testsJar/pom.xml index 59bb99fbe5905..b51566a30e671 100644 --- a/subprojects/build-init/src/integTest/resources/org/gradle/buildinit/plugins/MavenConversionIntegrationTest/testsJar/pom.xml +++ b/subprojects/build-init/src/integTest/resources/org/gradle/buildinit/plugins/MavenConversionIntegrationTest/testsJar/pom.xml @@ -37,8 +37,8 @@ org.apache.maven.plugins maven-compiler-plugin - 1.6 - 1.6 + 1.7 + 1.7 diff --git a/subprojects/code-quality/src/integTest/groovy/org/gradle/api/plugins/quality/pmd/PmdPluginAuxclasspathIntegrationTest.groovy b/subprojects/code-quality/src/integTest/groovy/org/gradle/api/plugins/quality/pmd/PmdPluginAuxclasspathIntegrationTest.groovy index 48a8a721cdfa3..f224a5d3750a9 100644 --- a/subprojects/code-quality/src/integTest/groovy/org/gradle/api/plugins/quality/pmd/PmdPluginAuxclasspathIntegrationTest.groovy +++ b/subprojects/code-quality/src/integTest/groovy/org/gradle/api/plugins/quality/pmd/PmdPluginAuxclasspathIntegrationTest.groovy @@ -39,7 +39,7 @@ class PmdPluginAuxclasspathIntegrationTest extends AbstractPmdPluginVersionInteg apply plugin: 'java' - ${!TestPrecondition.FIX_TO_WORK_ON_JAVA9.fulfilled ? "sourceCompatibility = 1.6" : ""} + ${!TestPrecondition.FIX_TO_WORK_ON_JAVA9.fulfilled ? "sourceCompatibility = 1.7" : ""} } project("pmd-rule") { diff --git a/subprojects/code-quality/src/integTest/groovy/org/gradle/api/plugins/quality/pmd/PmdPluginVersionIntegrationTest.groovy b/subprojects/code-quality/src/integTest/groovy/org/gradle/api/plugins/quality/pmd/PmdPluginVersionIntegrationTest.groovy index 75ab91d7fa312..7b5e0fafb63f9 100644 --- a/subprojects/code-quality/src/integTest/groovy/org/gradle/api/plugins/quality/pmd/PmdPluginVersionIntegrationTest.groovy +++ b/subprojects/code-quality/src/integTest/groovy/org/gradle/api/plugins/quality/pmd/PmdPluginVersionIntegrationTest.groovy @@ -44,7 +44,7 @@ class PmdPluginVersionIntegrationTest extends AbstractPmdPluginVersionIntegratio classpath = files() }"""} - ${!TestPrecondition.FIX_TO_WORK_ON_JAVA9.fulfilled ? "sourceCompatibility = 1.6" : ""} + ${!TestPrecondition.FIX_TO_WORK_ON_JAVA9.fulfilled ? "sourceCompatibility = 1.7" : ""} """.stripIndent() } diff --git a/subprojects/core/src/integTest/groovy/org/gradle/JansiEndUserIntegrationTest.groovy b/subprojects/core/src/integTest/groovy/org/gradle/JansiEndUserIntegrationTest.groovy index 024de193f0297..4f72007c52f4f 100644 --- a/subprojects/core/src/integTest/groovy/org/gradle/JansiEndUserIntegrationTest.groovy +++ b/subprojects/core/src/integTest/groovy/org/gradle/JansiEndUserIntegrationTest.groovy @@ -188,7 +188,7 @@ class JansiEndUserIntegrationTest extends AbstractIntegrationSpec { static String annotationProcessorDependency(File repoDir, String processorDependency) { """ - sourceCompatibility = '1.6' + sourceCompatibility = '1.7' repositories { maven { @@ -249,7 +249,7 @@ class JansiEndUserIntegrationTest extends AbstractIntegrationSpec { group = '$group' version = '$version' - sourceCompatibility = '1.6' + sourceCompatibility = '1.7' dependencies { compile 'org.fusesource.jansi:jansi:$JANSI_VERSION' @@ -284,7 +284,7 @@ class JansiEndUserIntegrationTest extends AbstractIntegrationSpec { import org.fusesource.jansi.AnsiConsole; @SupportedAnnotationTypes({"org.gradle.Custom"}) - @SupportedSourceVersion(SourceVersion.RELEASE_6) + @SupportedSourceVersion(SourceVersion.RELEASE_7) public class MyProcessor extends AbstractProcessor { @Override public synchronized void init(ProcessingEnvironment processingEnv) { diff --git a/subprojects/language-java/src/integTest/groovy/org/gradle/language/java/JavaLanguageCustomLibraryDependencyResolutionIntegrationTest.groovy b/subprojects/language-java/src/integTest/groovy/org/gradle/language/java/JavaLanguageCustomLibraryDependencyResolutionIntegrationTest.groovy index e48b5f37f249a..ddd94965e7067 100644 --- a/subprojects/language-java/src/integTest/groovy/org/gradle/language/java/JavaLanguageCustomLibraryDependencyResolutionIntegrationTest.groovy +++ b/subprojects/language-java/src/integTest/groovy/org/gradle/language/java/JavaLanguageCustomLibraryDependencyResolutionIntegrationTest.groovy @@ -142,15 +142,15 @@ model { model { components { zdep(CustomLibrary) { - javaVersions 6,7 + javaVersions 7,8 sources { java(JavaSourceSet) { } } } main(JvmLibrarySpec) { - targetPlatform 'java6' targetPlatform 'java7' + targetPlatform 'java8' sources { java { dependencies { @@ -162,18 +162,18 @@ model { } tasks { - mainJava6Jar { - doLast { - assert compileMainJava6JarMainJava.taskDependencies.getDependencies(compileMainJava6JarMainJava).contains(zdep6ApiJar) - assert compileMainJava6JarMainJava.classpath.files == [file("${buildDir}/jars/zdep/6Jar/api/zdep.jar")] as Set - } - } mainJava7Jar { doLast { assert compileMainJava7JarMainJava.taskDependencies.getDependencies(compileMainJava7JarMainJava).contains(zdep7ApiJar) assert compileMainJava7JarMainJava.classpath.files == [file("${buildDir}/jars/zdep/7Jar/api/zdep.jar")] as Set } } + mainJava8Jar { + doLast { + assert compileMainJava8JarMainJava.taskDependencies.getDependencies(compileMainJava8JarMainJava).contains(zdep8ApiJar) + assert compileMainJava8JarMainJava.classpath.files == [file("${buildDir}/jars/zdep/8Jar/api/zdep.jar")] as Set + } + } } } ''' @@ -181,16 +181,16 @@ model { file('src/main/java/TestApp.java') << 'public class TestApp {}' when: - succeeds ':mainJava6Jar' + succeeds ':mainJava7Jar' then: - executedAndNotSkipped ':zdep6ApiJar', ':mainJava6Jar' + executedAndNotSkipped ':zdep7ApiJar', ':mainJava7Jar' when: - succeeds ':mainJava7Jar' + succeeds ':mainJava8Jar' then: - executedAndNotSkipped ':zdep7ApiJar', ':mainJava7Jar' + executedAndNotSkipped ':zdep8ApiJar', ':mainJava8Jar' } def "should fail resolving dependencies only for the missing dependency variant"() { @@ -610,14 +610,14 @@ model { succeeds ':thirdJar' } - def "All components should depend on the corresponding variants"() { + def "all components should depend on the corresponding variants"() { given: theModel ''' model { components { main(JvmLibrarySpec) { - targetPlatform 'java6' targetPlatform 'java7' + targetPlatform 'java8' sources { java { dependencies { @@ -627,7 +627,7 @@ model { } } second(CustomLibrary) { - javaVersions 6,7 + javaVersions 7,8 sources { java(JavaSourceSet) { dependencies { @@ -637,28 +637,22 @@ model { } } third(JvmLibrarySpec) { - targetPlatform 'java6' targetPlatform 'java7' + targetPlatform 'java8' } } tasks { - mainJava6Jar { - doLast { - assert compileMainJava6JarMainJava.taskDependencies.getDependencies(compileMainJava6JarMainJava).contains(second6ApiJar) - assert compileMainJava6JarMainJava.classpath.files == [file("${buildDir}/jars/second/6Jar/api/second.jar")] as Set - } - } mainJava7Jar { doLast { assert compileMainJava7JarMainJava.taskDependencies.getDependencies(compileMainJava7JarMainJava).contains(second7ApiJar) assert compileMainJava7JarMainJava.classpath.files == [file("${buildDir}/jars/second/7Jar/api/second.jar")] as Set } } - second6Jar { + mainJava8Jar { doLast { - assert compileSecond6JarSecondJava.taskDependencies.getDependencies(compileSecond6JarSecondJava).contains(thirdJava6ApiJar) - assert compileSecond6JarSecondJava.classpath.files == [file("${buildDir}/jars/third/java6Jar/api/third.jar")] as Set + assert compileMainJava8JarMainJava.taskDependencies.getDependencies(compileMainJava8JarMainJava).contains(second8ApiJar) + assert compileMainJava8JarMainJava.classpath.files == [file("${buildDir}/jars/second/8Jar/api/second.jar")] as Set } } second7Jar { @@ -667,6 +661,12 @@ model { assert compileSecond7JarSecondJava.classpath.files == [file("${buildDir}/jars/third/java7Jar/api/third.jar")] as Set } } + second8Jar { + doLast { + assert compileSecond8JarSecondJava.taskDependencies.getDependencies(compileSecond8JarSecondJava).contains(thirdJava8ApiJar) + assert compileSecond8JarSecondJava.classpath.files == [file("${buildDir}/jars/third/java8Jar/api/third.jar")] as Set + } + } } } ''' @@ -680,15 +680,15 @@ model { then: executedAndNotSkipped ':tasks' + and: "Can build the Java 8 variant of all components" + succeeds ':mainJava8Jar' + succeeds ':second8Jar' + succeeds ':thirdJava8Jar' + and: "Can build the Java 7 variant of all components" succeeds ':mainJava7Jar' succeeds ':second7Jar' succeeds ':thirdJava7Jar' - - and: "Can build the Java 6 variant of all components" - succeeds ':mainJava6Jar' - succeeds ':second6Jar' - succeeds ':thirdJava6Jar' } def "can define a cyclic dependency"() { diff --git a/subprojects/language-java/src/integTest/groovy/org/gradle/language/java/JavaLanguageDependencyResolutionIntegrationTest.groovy b/subprojects/language-java/src/integTest/groovy/org/gradle/language/java/JavaLanguageDependencyResolutionIntegrationTest.groovy index acdb830a917bd..aac0e3df2ee38 100644 --- a/subprojects/language-java/src/integTest/groovy/org/gradle/language/java/JavaLanguageDependencyResolutionIntegrationTest.groovy +++ b/subprojects/language-java/src/integTest/groovy/org/gradle/language/java/JavaLanguageDependencyResolutionIntegrationTest.groovy @@ -899,12 +899,12 @@ model { model { components { dep(JvmLibrarySpec) { - targetPlatform 'java6' + targetPlatform 'java7' } main(JvmLibrarySpec) { + targetPlatform 'java8' targetPlatform 'java7' - targetPlatform 'java6' $scope.begin library 'dep' $scope.end @@ -912,11 +912,11 @@ model { } tasks { - mainJava6Jar.finalizedBy('checkDependencies') mainJava7Jar.finalizedBy('checkDependencies') + mainJava8Jar.finalizedBy('checkDependencies') create('checkDependencies') { - assert compileMainJava6JarMainJava.taskDependencies.getDependencies(compileMainJava6JarMainJava).contains(depApiJar) assert compileMainJava7JarMainJava.taskDependencies.getDependencies(compileMainJava7JarMainJava).contains(depApiJar) + assert compileMainJava8JarMainJava.taskDependencies.getDependencies(compileMainJava8JarMainJava).contains(depApiJar) } } } @@ -931,10 +931,10 @@ model { executedAndNotSkipped ':tasks' and: - succeeds 'mainJava6Jar' + succeeds 'mainJava7Jar' and: - succeeds 'mainJava7Jar' + succeeds 'mainJava8Jar' where: scope << DependencyScope.values() @@ -1088,13 +1088,13 @@ model { model { components { dep(JvmLibrarySpec) { - targetPlatform 'java6' targetPlatform 'java7' + targetPlatform 'java8' } main(JvmLibrarySpec) { targetPlatform 'java7' - targetPlatform 'java6' + targetPlatform 'java8' $scope.begin library 'dep' $scope.end @@ -1102,11 +1102,11 @@ model { } tasks { - mainJava6Jar.finalizedBy('checkDependencies') mainJava7Jar.finalizedBy('checkDependencies') + mainJava8Jar.finalizedBy('checkDependencies') create('checkDependencies') { - assert compileMainJava6JarMainJava.taskDependencies.getDependencies(compileMainJava6JarMainJava).contains(depJava6ApiJar) assert compileMainJava7JarMainJava.taskDependencies.getDependencies(compileMainJava7JarMainJava).contains(depJava7ApiJar) + assert compileMainJava8JarMainJava.taskDependencies.getDependencies(compileMainJava8JarMainJava).contains(depJava8ApiJar) } } } @@ -1121,7 +1121,7 @@ model { executedAndNotSkipped ':tasks' and: - succeeds 'mainJava6Jar', 'mainJava7Jar' + succeeds 'mainJava7Jar', 'mainJava8Jar' where: scope << DependencyScope.values() diff --git a/subprojects/language-java/src/integTest/groovy/org/gradle/language/java/JavaLanguageIntegrationTest.groovy b/subprojects/language-java/src/integTest/groovy/org/gradle/language/java/JavaLanguageIntegrationTest.groovy index 81ca28cb15d7e..9f19d41b2beea 100644 --- a/subprojects/language-java/src/integTest/groovy/org/gradle/language/java/JavaLanguageIntegrationTest.groovy +++ b/subprojects/language-java/src/integTest/groovy/org/gradle/language/java/JavaLanguageIntegrationTest.groovy @@ -59,7 +59,7 @@ class JavaLanguageIntegrationTest extends AbstractJvmLanguageIntegrationTest { model { components { myLib(JvmLibrarySpec) { - targetPlatform "java6" + targetPlatform "java7" } } } @@ -68,7 +68,7 @@ class JavaLanguageIntegrationTest extends AbstractJvmLanguageIntegrationTest { succeeds "assemble" and: - jarFile("build/jars/myLib/jar/myLib.jar").javaVersion == JavaVersion.VERSION_1_6 + jarFile("build/jars/myLib/jar/myLib.jar").javaVersion == JavaVersion.VERSION_1_7 jarFile("build/jars/myLib/jar/myLib.jar").hasDescendants(app.sources*.classFile.fullPath as String[]) } @@ -82,9 +82,9 @@ class JavaLanguageIntegrationTest extends AbstractJvmLanguageIntegrationTest { model { components { myLib(JvmLibrarySpec) { - targetPlatform "java6" targetPlatform "java7" targetPlatform "java8" + targetPlatform "java9" } } } @@ -93,9 +93,9 @@ class JavaLanguageIntegrationTest extends AbstractJvmLanguageIntegrationTest { succeeds "assemble" and: - jarFile("build/jars/myLib/java6Jar/myLib.jar").javaVersion == JavaVersion.VERSION_1_6 jarFile("build/jars/myLib/java7Jar/myLib.jar").javaVersion == JavaVersion.VERSION_1_7 jarFile("build/jars/myLib/java8Jar/myLib.jar").javaVersion == JavaVersion.VERSION_1_8 + jarFile("build/jars/myLib/java9Jar/myLib.jar").javaVersion == JavaVersion.VERSION_1_9 } def "erroneous target should produce reasonable error message"() { diff --git a/subprojects/language-java/src/integTest/groovy/org/gradle/language/java/JavaSourceSetIntegrationTest.groovy b/subprojects/language-java/src/integTest/groovy/org/gradle/language/java/JavaSourceSetIntegrationTest.groovy index ed8ac4408ea13..a102eb83c1aa6 100644 --- a/subprojects/language-java/src/integTest/groovy/org/gradle/language/java/JavaSourceSetIntegrationTest.groovy +++ b/subprojects/language-java/src/integTest/groovy/org/gradle/language/java/JavaSourceSetIntegrationTest.groovy @@ -148,26 +148,26 @@ model { def "can build JAR from multiple source sets"() { given: file("src/main/java/Main.java") << "public class Main {}" - file("src/main/resources/main.properties") << "java=6" - file("src/main/java7/Java7.java") << "public class Java7 {}" - file("src/main/java7-resources/java7.properties") << "java=7" + file("src/main/resources/main.properties") << "java=7" + file("src/main/java8/Java8.java") << "public class Java8 {}" + file("src/main/java8-resources/java8.properties") << "java=8" applyJavaPlugin(buildFile) buildFile << ''' model { components { main(JvmLibrarySpec) { - targetPlatform 'java6' targetPlatform 'java7' + targetPlatform 'java8' binaries { withType(JarBinarySpec) { binary -> - if (binary.targetPlatform.name == "java7") { + if (binary.targetPlatform.name == "java8") { sources { - java7(JavaSourceSet) { - source.srcDir "src/main/java7" + java8(JavaSourceSet) { + source.srcDir "src/main/java8" } - java7Resources(JvmResourceSet) { - source.srcDir "src/main/java7-resources" + java8Resources(JvmResourceSet) { + source.srcDir "src/main/java8-resources" } } } @@ -182,10 +182,10 @@ model { succeeds "assemble" then: - new JarTestFixture(file("build/jars/main/java6Jar/main.jar")).hasDescendants( - "Main.class", "main.properties"); new JarTestFixture(file("build/jars/main/java7Jar/main.jar")).hasDescendants( - "Main.class", "main.properties", "Java7.class", "java7.properties"); + "Main.class", "main.properties"); + new JarTestFixture(file("build/jars/main/java8Jar/main.jar")).hasDescendants( + "Main.class", "main.properties", "Java8.class", "java8.properties"); } } diff --git a/subprojects/language-java/src/integTest/groovy/org/gradle/language/java/SingleBinaryTypeWithVariantsTest.groovy b/subprojects/language-java/src/integTest/groovy/org/gradle/language/java/SingleBinaryTypeWithVariantsTest.groovy index f7a5900032f99..2b2a5d9663bcc 100644 --- a/subprojects/language-java/src/integTest/groovy/org/gradle/language/java/SingleBinaryTypeWithVariantsTest.groovy +++ b/subprojects/language-java/src/integTest/groovy/org/gradle/language/java/SingleBinaryTypeWithVariantsTest.groovy @@ -98,39 +98,39 @@ model { where: jdk1 | buildTypes1 | flavors1 | jdk2 | buildTypes2 | flavors2 | selected | errors - [6] | [] | [] | [6] | [] | [] | [:] | [:] - [6] | [] | [] | [6] | [] | [] | [firstDefaultDefaultJar: 'second/defaultDefaultJar'] | [:] - [6] | [] | [] | [6] | [] | ['paid'] | [firstDefaultDefaultJar: 'second/paidDefaultJar'] | [:] - [6] | [] | [] | [6] | [] | ['paid', 'free'] | [:] | [firstDefaultDefaultJar: ["Multiple compatible variants found for library 'second':", - "Jar 'second:freeDefaultJar' [flavor:'free', platform:'java6']", - "Jar 'second:paidDefaultJar' [flavor:'paid', platform:'java6']"]] - [6] | ['release'] | [] | [6] | ['debug'] | [] | [:] | [firstDefaultReleaseJar: ["Cannot find a compatible variant for library 'second'.", - "Required platform 'java6', available: 'java6'", + [7] | [] | [] | [7] | [] | [] | [:] | [:] + [7] | [] | [] | [7] | [] | [] | [firstDefaultDefaultJar: 'second/defaultDefaultJar'] | [:] + [7] | [] | [] | [7] | [] | ['paid'] | [firstDefaultDefaultJar: 'second/paidDefaultJar'] | [:] + [7] | [] | [] | [7] | [] | ['paid', 'free'] | [:] | [firstDefaultDefaultJar: ["Multiple compatible variants found for library 'second':", + "Jar 'second:freeDefaultJar' [flavor:'free', platform:'java7']", + "Jar 'second:paidDefaultJar' [flavor:'paid', platform:'java7']"]] + [7] | ['release'] | [] | [7] | ['debug'] | [] | [:] | [firstDefaultReleaseJar: ["Cannot find a compatible variant for library 'second'.", + "Required platform 'java7', available: 'java7'", "Required buildType 'release', available: 'debug'"]] - [6] | [] | [] | [6] | ['release', 'debug'] | ['paid', 'free'] | [:] | [firstDefaultDefaultJar: ["Multiple compatible variants found for library 'second':", - "Jar 'second:freeDebugJar' [buildType:'debug', flavor:'free', platform:'java6']", - "Jar 'second:freeReleaseJar' [buildType:'release', flavor:'free', platform:'java6']", - "Jar 'second:paidDebugJar' [buildType:'debug', flavor:'paid', platform:'java6']", - "Jar 'second:paidReleaseJar' [buildType:'release', flavor:'paid', platform:'java6']"]] - [6] | [] | ['paid'] | [6] | [] | ['paid'] | [firstPaidDefaultJar: 'second/paidDefaultJar'] | [:] - [6] | [] | ['paid', 'free'] | [6] | [] | ['paid', 'free'] | [firstFreeDefaultJar: 'second/freeDefaultJar', + [7] | [] | [] | [7] | ['release', 'debug'] | ['paid', 'free'] | [:] | [firstDefaultDefaultJar: ["Multiple compatible variants found for library 'second':", + "Jar 'second:freeDebugJar' [buildType:'debug', flavor:'free', platform:'java7']", + "Jar 'second:freeReleaseJar' [buildType:'release', flavor:'free', platform:'java7']", + "Jar 'second:paidDebugJar' [buildType:'debug', flavor:'paid', platform:'java7']", + "Jar 'second:paidReleaseJar' [buildType:'release', flavor:'paid', platform:'java7']"]] + [7] | [] | ['paid'] | [7] | [] | ['paid'] | [firstPaidDefaultJar: 'second/paidDefaultJar'] | [:] + [7] | [] | ['paid', 'free'] | [7] | [] | ['paid', 'free'] | [firstFreeDefaultJar: 'second/freeDefaultJar', firstPaidDefaultJar: 'second/paidDefaultJar'] | [:] - [6] | ['debug'] | ['free'] | [6] | ['debug', 'release'] | ['free'] | [firstFreeDebugJar: 'second/freeDebugJar'] | [:] - [6] | ['debug'] | ['free'] | [6] | ['debug'] | ['free', 'paid'] | [firstFreeDebugJar: 'second/freeDebugJar'] | [:] - [6] | ['debug'] | ['free'] | [5, 6, 7] | ['debug'] | ['free'] | [firstFreeDebugJar: 'second/freeDebug6Jar'] | [:] - [6] | ['debug'] | ['free'] | [7, 6, 5] | ['debug'] | ['free'] | [firstFreeDebugJar: 'second/freeDebug6Jar'] | [:] - [7] | ['debug'] | ['free'] | [5, 6] | ['debug'] | ['free'] | [firstFreeDebugJar: 'second/freeDebug6Jar'] | [:] - [6] | ['debug'] | ['free'] | [7] | ['debug'] | ['free'] | [:] | [firstFreeDebugJar: ["Cannot find a compatible variant for library 'second'", - "Required platform 'java6', available: 'java7'", + [7] | ['debug'] | ['free'] | [7] | ['debug', 'release'] | ['free'] | [firstFreeDebugJar: 'second/freeDebugJar'] | [:] + [7] | ['debug'] | ['free'] | [7] | ['debug'] | ['free', 'paid'] | [firstFreeDebugJar: 'second/freeDebugJar'] | [:] + [8] | ['debug'] | ['free'] | [7, 8, 9] | ['debug'] | ['free'] | [firstFreeDebugJar: 'second/freeDebug8Jar'] | [:] + [8] | ['debug'] | ['free'] | [9, 8, 7] | ['debug'] | ['free'] | [firstFreeDebugJar: 'second/freeDebug8Jar'] | [:] + [9] | ['debug'] | ['free'] | [7, 8] | ['debug'] | ['free'] | [firstFreeDebugJar: 'second/freeDebug8Jar'] | [:] + [7] | ['debug'] | ['free'] | [8] | ['debug'] | ['free'] | [:] | [firstFreeDebugJar: ["Cannot find a compatible variant for library 'second'", + "Required platform 'java7', available: 'java8'", "Required flavor 'free', available: 'free'", "Required buildType 'debug', available: 'debug'"]] - [6] | [] | ['paid'] | [6] | [] | ['free'] | [:] | [firstPaidDefaultJar: ["Cannot find a compatible variant for library 'second'", + [7] | [] | ['paid'] | [7] | [] | ['free'] | [:] | [firstPaidDefaultJar: ["Cannot find a compatible variant for library 'second'", "Required flavor 'paid', available: 'free'"]] - [6] | [] | ['paid'] | [6] | [] | ['free', 'other'] | [:] | [firstPaidDefaultJar: ["Cannot find a compatible variant for library 'second'", + [7] | [] | ['paid'] | [7] | [] | ['free', 'other'] | [:] | [firstPaidDefaultJar: ["Cannot find a compatible variant for library 'second'", "Required flavor 'paid', available: 'free', 'other'"]] - [6] | [] | ['paid', 'free'] | [6] | [] | ['free', 'other'] | [:] | [firstPaidDefaultJar: ["Cannot find a compatible variant for library 'second'", + [7] | [] | ['paid', 'free'] | [7] | [] | ['free', 'other'] | [:] | [firstPaidDefaultJar: ["Cannot find a compatible variant for library 'second'", "Required flavor 'paid', available: 'free', 'other'"]] - [6] | [] | ['paid', 'test'] | [6] | [] | ['free', 'other'] | [:] | [firstPaidDefaultJar: ["Cannot find a compatible variant for library 'second'", + [7] | [] | ['paid', 'test'] | [7] | [] | ['free', 'other'] | [:] | [firstPaidDefaultJar: ["Cannot find a compatible variant for library 'second'", "Required flavor 'paid', available: 'free', 'other'"], firstTestDefaultJar: ["Cannot find a compatible variant for library 'second'", "Required flavor 'test', available: 'free', 'other'"]] diff --git a/subprojects/plugins/src/integTest/groovy/org/gradle/java/compile/BasicJavaCompilerIntegrationSpec.groovy b/subprojects/plugins/src/integTest/groovy/org/gradle/java/compile/BasicJavaCompilerIntegrationSpec.groovy index 88ec847de1779..2f4f491986ff3 100644 --- a/subprojects/plugins/src/integTest/groovy/org/gradle/java/compile/BasicJavaCompilerIntegrationSpec.groovy +++ b/subprojects/plugins/src/integTest/groovy/org/gradle/java/compile/BasicJavaCompilerIntegrationSpec.groovy @@ -146,7 +146,7 @@ public class FxApp extends Application { given: goodCode() buildFile << """ -compileJava.options.compilerArgs.addAll(['--release', '7']) +compileJava.options.compilerArgs.addAll(['--release', '8']) """ expect: @@ -156,27 +156,28 @@ compileJava.options.compilerArgs.addAll(['--release', '7']) @Requires(TestPrecondition.JDK9_OR_LATER) def "compile fails when using newer API with release option"() { given: - file("src/main/java/compile/test/FailsOnJava7.java") << ''' + file("src/main/java/compile/test/FailsOnJava8.java") << ''' package compile.test; -import java.util.Optional; +import java.util.stream.Stream; +import java.util.function.Predicate; -public class FailsOnJava7 { - public Optional someOptional() { - return Optional.of("Hello"); +public class FailsOnJava8 { + public Stream takeFromStream(Stream stream) { + return stream.takeWhile(Predicate.isEqual("foo")); } } ''' buildFile << """ -compileJava.options.compilerArgs.addAll(['--release', '7']) +compileJava.options.compilerArgs.addAll(['--release', '8']) """ expect: fails 'compileJava' output.contains(logStatement()) failure.assertHasErrorOutput("cannot find symbol") - failure.assertHasErrorOutput("class Optional") + failure.assertHasErrorOutput("method takeWhile") } def buildScript() { diff --git a/subprojects/plugins/src/integTest/groovy/org/gradle/java/compile/IncrementalJavaCompileIntegrationTest.groovy b/subprojects/plugins/src/integTest/groovy/org/gradle/java/compile/IncrementalJavaCompileIntegrationTest.groovy index c65ab74a4b5d7..a614a2efc68f6 100644 --- a/subprojects/plugins/src/integTest/groovy/org/gradle/java/compile/IncrementalJavaCompileIntegrationTest.groovy +++ b/subprojects/plugins/src/integTest/groovy/org/gradle/java/compile/IncrementalJavaCompileIntegrationTest.groovy @@ -37,7 +37,7 @@ class IncrementalJavaCompileIntegrationTest extends AbstractIntegrationSpec impl executedAndNotSkipped ':compileJava' when: - buildFile << 'sourceCompatibility = 1.6\n' + buildFile << 'sourceCompatibility = 1.8\n' succeeds ':compileJava' then: diff --git a/subprojects/scala/src/integTest/groovy/org/gradle/scala/ScalaCrossCompilationIntegrationTest.groovy b/subprojects/scala/src/integTest/groovy/org/gradle/scala/ScalaCrossCompilationIntegrationTest.groovy index 2eabe6bd475c9..584b5b4161d29 100644 --- a/subprojects/scala/src/integTest/groovy/org/gradle/scala/ScalaCrossCompilationIntegrationTest.groovy +++ b/subprojects/scala/src/integTest/groovy/org/gradle/scala/ScalaCrossCompilationIntegrationTest.groovy @@ -25,7 +25,7 @@ import org.gradle.test.fixtures.file.ClassFile import org.gradle.util.TextUtil import org.junit.Assume -@TargetVersions(["1.6", "1.7", "1.8"]) +@TargetVersions(["1.7", "1.8"]) class ScalaCrossCompilationIntegrationTest extends MultiVersionIntegrationSpec { JavaVersion getJavaVersion() { JavaVersion.toVersion(MultiVersionIntegrationSpec.version) diff --git a/subprojects/testing-jvm/src/integTest/groovy/org/gradle/jvm/test/JUnitComponentUnderTestIntegrationTest.groovy b/subprojects/testing-jvm/src/integTest/groovy/org/gradle/jvm/test/JUnitComponentUnderTestIntegrationTest.groovy index 18c9e31c3ac39..427dd84b8f4c9 100644 --- a/subprojects/testing-jvm/src/integTest/groovy/org/gradle/jvm/test/JUnitComponentUnderTestIntegrationTest.groovy +++ b/subprojects/testing-jvm/src/integTest/groovy/org/gradle/jvm/test/JUnitComponentUnderTestIntegrationTest.groovy @@ -159,22 +159,22 @@ class JUnitComponentUnderTestIntegrationTest extends AbstractJUnitTestExecutionI greeterTestCase() when: - succeeds ':myTestGreeterJava6JarBinaryTest' - def result = new DefaultTestExecutionResult(testDirectory, 'build', 'myTest', 'greeterJava6Jar') + succeeds ':myTestGreeterJava7JarBinaryTest' + def result = new DefaultTestExecutionResult(testDirectory, 'build', 'myTest', 'greeterJava7Jar') then: - executedAndNotSkipped ':myTestGreeterJava6JarBinaryTest', ':compileGreeterJava6JarGreeterJava' + executedAndNotSkipped ':myTestGreeterJava7JarBinaryTest', ':compileGreeterJava7JarGreeterJava' result.assertTestClassesExecuted('com.acme.GreeterTest') result.testClass('com.acme.GreeterTest') .assertTestCount(1, 0, 0) .assertTestsExecuted('testGreeting') when: - succeeds ':myTestGreeterJava7JarBinaryTest' - result = new DefaultTestExecutionResult(testDirectory, 'build', 'myTest', 'greeterJava7Jar') + succeeds ':myTestGreeterJava8JarBinaryTest' + result = new DefaultTestExecutionResult(testDirectory, 'build', 'myTest', 'greeterJava8Jar') then: - executedAndNotSkipped ':myTestGreeterJava7JarBinaryTest', ':compileGreeterJava7JarGreeterJava' + executedAndNotSkipped ':myTestGreeterJava8JarBinaryTest', ':compileGreeterJava8JarGreeterJava' result.assertTestClassesExecuted('com.acme.GreeterTest') result.testClass('com.acme.GreeterTest') .assertTestCount(1, 0, 0) @@ -283,8 +283,8 @@ class JUnitComponentUnderTestIntegrationTest extends AbstractJUnitTestExecutionI model { components { greeter { - targetPlatform 'java6' targetPlatform 'java7' + targetPlatform 'java8' } } } diff --git a/subprojects/tooling-api/src/crossVersionTest/groovy/org/gradle/integtests/tooling/r25/TestProgressCrossVersionSpec.groovy b/subprojects/tooling-api/src/crossVersionTest/groovy/org/gradle/integtests/tooling/r25/TestProgressCrossVersionSpec.groovy index 42a5f735e5d93..6e9204b631038 100644 --- a/subprojects/tooling-api/src/crossVersionTest/groovy/org/gradle/integtests/tooling/r25/TestProgressCrossVersionSpec.groovy +++ b/subprojects/tooling-api/src/crossVersionTest/groovy/org/gradle/integtests/tooling/r25/TestProgressCrossVersionSpec.groovy @@ -470,7 +470,7 @@ class TestProgressCrossVersionSpec extends ToolingApiSpecification { def goodCode() { buildFile << """ apply plugin: 'java' - sourceCompatibility = 1.6 + sourceCompatibility = 1.7 ${mavenCentralRepository()} dependencies { testCompile 'junit:junit:4.12' } compileTestJava.options.fork = true // forked as 'Gradle Test Executor 1' From 8d7b01fc9c60052eae5dce85755be04e7bdb72c8 Mon Sep 17 00:00:00 2001 From: Gary Hale Date: Fri, 8 Mar 2019 10:47:58 -0500 Subject: [PATCH 472/853] Handle new constant types in Java 12 --- .../model/internal/type/ModelTypesTest.groovy | 20 +++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/subprojects/model-core/src/test/groovy/org/gradle/model/internal/type/ModelTypesTest.groovy b/subprojects/model-core/src/test/groovy/org/gradle/model/internal/type/ModelTypesTest.groovy index a2646efae252a..c61aac05db648 100644 --- a/subprojects/model-core/src/test/groovy/org/gradle/model/internal/type/ModelTypesTest.groovy +++ b/subprojects/model-core/src/test/groovy/org/gradle/model/internal/type/ModelTypesTest.groovy @@ -16,6 +16,7 @@ package org.gradle.model.internal.type +import org.gradle.api.JavaVersion import spock.lang.Specification import spock.lang.Unroll @@ -27,9 +28,24 @@ class ModelTypesTest extends Specification { where: types | closed - [Integer] | [Integer, Number, Comparable, Serializable] - [Integer, Double] | [Integer, Double, Number, Comparable, Serializable] + [Integer] | typeHierarchyForInteger + [Integer, Double] | typeHierarchyForInteger + typeHierarchyForDouble [Object] | [] [GroovyObject] | [] } + + static def getTypeHierarchyForDouble() { + return maybeWithJava12ConstantTypes([Double, Number, Comparable, Serializable]) + } + + static def getTypeHierarchyForInteger() { + return maybeWithJava12ConstantTypes([Integer, Number, Comparable, Serializable]) + } + + static def maybeWithJava12ConstantTypes(types) { + if (JavaVersion.current().java12Compatible) { + types += [Class.forName("java.lang.constant.Constable"), Class.forName("java.lang.constant.ConstantDesc")] + } + return types + } } From e381200cb64d99809e6f8c02c224a1b9e9b46773 Mon Sep 17 00:00:00 2001 From: Gary Hale Date: Fri, 8 Mar 2019 15:04:31 -0500 Subject: [PATCH 473/853] Ignore tests that need Java9 when running on Java8 --- .../gradle/language/java/JavaLanguageIntegrationTest.groovy | 2 +- .../language/java/SingleBinaryTypeWithVariantsTest.groovy | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/subprojects/language-java/src/integTest/groovy/org/gradle/language/java/JavaLanguageIntegrationTest.groovy b/subprojects/language-java/src/integTest/groovy/org/gradle/language/java/JavaLanguageIntegrationTest.groovy index 9f19d41b2beea..73509363fdc13 100644 --- a/subprojects/language-java/src/integTest/groovy/org/gradle/language/java/JavaLanguageIntegrationTest.groovy +++ b/subprojects/language-java/src/integTest/groovy/org/gradle/language/java/JavaLanguageIntegrationTest.groovy @@ -72,7 +72,7 @@ class JavaLanguageIntegrationTest extends AbstractJvmLanguageIntegrationTest { jarFile("build/jars/myLib/jar/myLib.jar").hasDescendants(app.sources*.classFile.fullPath as String[]) } - @Requires(TestPrecondition.JDK8_OR_LATER) + @Requires(TestPrecondition.JDK9_OR_LATER) def "multiple targets should produce in the correct bytecode"() { when: app.writeSources(file("src/myLib")) diff --git a/subprojects/language-java/src/integTest/groovy/org/gradle/language/java/SingleBinaryTypeWithVariantsTest.groovy b/subprojects/language-java/src/integTest/groovy/org/gradle/language/java/SingleBinaryTypeWithVariantsTest.groovy index 2b2a5d9663bcc..7df047bcd562f 100644 --- a/subprojects/language-java/src/integTest/groovy/org/gradle/language/java/SingleBinaryTypeWithVariantsTest.groovy +++ b/subprojects/language-java/src/integTest/groovy/org/gradle/language/java/SingleBinaryTypeWithVariantsTest.groovy @@ -16,6 +16,8 @@ package org.gradle.language.java +import org.gradle.api.JavaVersion +import org.junit.Assume import spock.lang.Unroll import static org.gradle.language.java.JavaIntegrationTesting.applyJavaPlugin @@ -25,6 +27,7 @@ class SingleBinaryTypeWithVariantsTest extends VariantAwareDependencyResolutionS @Unroll("matching {jdk #jdk1, flavors #flavors1, builtTypes #buildTypes1} with {jdk #jdk2, flavors #flavors2, buildTypes #buildTypes2} #outcome") def "check resolution of a custom component onto a component of the same type (same class, same variant dimensions)"() { given: + Assume.assumeTrue(jdk1.max() <= Integer.valueOf(JavaVersion.current().majorVersion)) applyJavaPlugin(buildFile) addCustomLibraryType(buildFile) From b67a04d9183fb58d1ca6c0e65f4f8b8b779f9a3b Mon Sep 17 00:00:00 2001 From: Gary Hale Date: Fri, 8 Mar 2019 15:50:32 -0500 Subject: [PATCH 474/853] Fix some more Java6 target compatibility instances --- .../SingleBinaryTypeWithVariantsTest.groovy | 79 ++++++++++--------- 1 file changed, 41 insertions(+), 38 deletions(-) diff --git a/subprojects/language-java/src/integTest/groovy/org/gradle/language/java/SingleBinaryTypeWithVariantsTest.groovy b/subprojects/language-java/src/integTest/groovy/org/gradle/language/java/SingleBinaryTypeWithVariantsTest.groovy index 7df047bcd562f..789395141015b 100644 --- a/subprojects/language-java/src/integTest/groovy/org/gradle/language/java/SingleBinaryTypeWithVariantsTest.groovy +++ b/subprojects/language-java/src/integTest/groovy/org/gradle/language/java/SingleBinaryTypeWithVariantsTest.groovy @@ -144,6 +144,7 @@ model { @Unroll("matching custom {jdk #jdk1, flavors #flavors1, builtTypes #buildTypes1} with Java {jdk #jdk2} #outcome") def "building a custom binary type and resolving against a library with standard JarBinarySpec instances"() { given: + Assume.assumeTrue(jdk1.max() <= Integer.valueOf(JavaVersion.current().majorVersion)) applyJavaPlugin(buildFile) addCustomLibraryType(buildFile) @@ -202,18 +203,18 @@ model { where: jdk1 | buildTypes1 | flavors1 | jdk2 | selected | errors - [6] | [] | [] | [6] | [:] | [:] - [6] | ['debug'] | ['free'] | [6, 7] | [firstFreeDebugJar: 'second/java6Jar'] | [:] - [6, 7] | ['debug'] | ['free'] | [6, 7] | [firstFreeDebug6Jar: 'second/java6Jar', - firstFreeDebug7Jar: 'second/java7Jar'] | [:] - [5, 6] | ['debug'] | ['free'] | [6, 7] | [firstFreeDebug6Jar: 'second/java6Jar'] | [firstFreeDebug5Jar: ["Cannot find a compatible variant for library 'second'", - "Required platform 'java5', available: 'java6', 'java7'", + [7] | [] | [] | [7] | [:] | [:] + [7] | ['debug'] | ['free'] | [7, 8] | [firstFreeDebugJar: 'second/java7Jar'] | [:] + [8, 9] | ['debug'] | ['free'] | [8, 9] | [firstFreeDebug8Jar: 'second/java8Jar', + firstFreeDebug9Jar: 'second/java9Jar'] | [:] + [7, 8] | ['debug'] | ['free'] | [8, 9] | [firstFreeDebug8Jar: 'second/java8Jar'] | [firstFreeDebug7Jar: ["Cannot find a compatible variant for library 'second'", + "Required platform 'java7', available: 'java8', 'java9'", "Required flavor 'free' but no compatible variant was found", "Required buildType 'debug' but no compatible variant was found"]] - [6] | ['debug', 'release'] | ['free', 'paid'] | [6, 7] | [firstFreeDebugJar : 'second/java6Jar', - firstFreeReleaseJar: 'second/java6Jar', - firstPaidDebugJar : 'second/java6Jar', - firstPaidReleaseJar: 'second/java6Jar'] | [:] + [7] | ['debug', 'release'] | ['free', 'paid'] | [7, 8] | [firstFreeDebugJar : 'second/java7Jar', + firstFreeReleaseJar: 'second/java7Jar', + firstPaidDebugJar : 'second/java7Jar', + firstPaidReleaseJar: 'second/java7Jar'] | [:] and: outcome = errors ? 'fails' : 'succeeds' @@ -222,6 +223,7 @@ model { @Unroll("matching Java #jdk1 with custom {jdk #jdk2, flavors #flavors2, builtTypes #buildTypes2} #outcome") def "building a standard JarBinarySpec instance and resolving against a library with custom binary types. "() { given: + Assume.assumeTrue(jdk1.max() <= Integer.valueOf(JavaVersion.current().majorVersion)) applyJavaPlugin(buildFile) addCustomLibraryType(buildFile) @@ -280,20 +282,20 @@ model { where: jdk1 | buildTypes2 | flavors2 | jdk2 | selected | errors - [6] | [] | [] | [6] | [:] | [:] - [6] | ['debug'] | ['free'] | [6, 7] | [firstJar: 'second/freeDebug6Jar'] | [:] - [6, 7] | ['debug'] | ['free'] | [6, 7] | [firstJava6Jar: 'second/freeDebug6Jar', - firstJava7Jar: 'second/freeDebug7Jar'] | [:] - [5, 6] | ['debug'] | ['free'] | [6, 7] | [firstJava6Jar: 'second/freeDebug6Jar'] | [firstJava5Jar: ["Cannot find a compatible variant for library 'second'.", - "Required platform 'java5', available: 'java6', 'java7'"]] - [6] | ['debug', 'release'] | [] | [6, 7] | [:] | [firstJar: ["Multiple compatible variants found for library 'second':", - "Jar 'second:defaultDebug6Jar' [buildType:'debug', platform:'java6']", - "Jar 'second:defaultRelease6Jar' [buildType:'release', platform:'java6']"]] - [6] | ['debug', 'release'] | ['free', 'paid'] | [6, 7] | [:] | [firstJar: ["Multiple compatible variants found for library 'second':", - "Jar 'second:freeDebug6Jar' [buildType:'debug', flavor:'free', platform:'java6']", - "Jar 'second:freeRelease6Jar' [buildType:'release', flavor:'free', platform:'java6']", - "Jar 'second:paidDebug6Jar' [buildType:'debug', flavor:'paid', platform:'java6']", - "Jar 'second:paidRelease6Jar' [buildType:'release', flavor:'paid', platform:'java6']"]] + [7] | [] | [] | [7] | [:] | [:] + [7] | ['debug'] | ['free'] | [7, 8] | [firstJar: 'second/freeDebug7Jar'] | [:] + [8, 9] | ['debug'] | ['free'] | [8, 9] | [firstJava8Jar: 'second/freeDebug8Jar', + firstJava9Jar: 'second/freeDebug9Jar'] | [:] + [7, 8] | ['debug'] | ['free'] | [8, 9] | [firstJava8Jar: 'second/freeDebug8Jar'] | [firstJava7Jar: ["Cannot find a compatible variant for library 'second'.", + "Required platform 'java7', available: 'java8', 'java9'"]] + [7] | ['debug', 'release'] | [] | [7, 8] | [:] | [firstJar: ["Multiple compatible variants found for library 'second':", + "Jar 'second:defaultDebug7Jar' [buildType:'debug', platform:'java7']", + "Jar 'second:defaultRelease7Jar' [buildType:'release', platform:'java7']"]] + [7] | ['debug', 'release'] | ['free', 'paid'] | [7, 8] | [:] | [firstJar: ["Multiple compatible variants found for library 'second':", + "Jar 'second:freeDebug7Jar' [buildType:'debug', flavor:'free', platform:'java7']", + "Jar 'second:freeRelease7Jar' [buildType:'release', flavor:'free', platform:'java7']", + "Jar 'second:paidDebug7Jar' [buildType:'debug', flavor:'paid', platform:'java7']", + "Jar 'second:paidRelease7Jar' [buildType:'release', flavor:'paid', platform:'java7']"]] and: outcome = errors ? 'fails' : 'succeeds' @@ -302,6 +304,7 @@ model { @Unroll("matching custom1 {jdk #jdk1, flavors #flavors) with custom2 {jdk #jdk2, builtTypes #buildTypes} #outcome") def "building a custom JarBinarySpec type and resolving against a library with a different custom JarBinarySpec type"() { given: + Assume.assumeTrue(jdk1.max() <= Integer.valueOf(JavaVersion.current().majorVersion)) applyJavaPlugin(buildFile) addCustomLibraryType(buildFile) @@ -364,22 +367,22 @@ model { where: jdk1 | flavors | buildTypes | jdk2 | selected | errors - [6] | [] | [] | [6] | [:] | [:] - [6] | ['free'] | ['debug'] | [6, 7] | [firstFreeJar: 'second/debug6Jar'] | [:] - [6, 7] | ['free'] | ['debug'] | [6, 7] | [firstFree6Jar: 'second/debug6Jar', - firstFree7Jar: 'second/debug7Jar'] | [:] - [5, 6] | ['free'] | ['debug'] | [6, 7] | [firstFree6Jar: 'second/debug6Jar'] | [firstFree5Jar: ["Cannot find a compatible variant for library 'second'", - "Required platform 'java5', available: 'java6', 'java7'", + [7] | [] | [] | [7] | [:] | [:] + [7] | ['free'] | ['debug'] | [7, 8] | [firstFreeJar: 'second/debug7Jar'] | [:] + [8, 9] | ['free'] | ['debug'] | [8, 9] | [firstFree8Jar: 'second/debug8Jar', + firstFree9Jar: 'second/debug9Jar'] | [:] + [7, 8] | ['free'] | ['debug'] | [8, 9] | [firstFree8Jar: 'second/debug8Jar'] | [firstFree7Jar: ["Cannot find a compatible variant for library 'second'", + "Required platform 'java7', available: 'java8', 'java9'", "Required flavor 'free' but no compatible variant was found"]] - [6] | [] | ['debug', 'release'] | [6, 7] | [:] | [firstDefaultJar: ["Multiple compatible variants found for library 'second':", - "Jar 'second:debug6Jar' [buildType:'debug', platform:'java6']", - "Jar 'second:release6Jar' [buildType:'release', platform:'java6']"]] - [6] | ['free', 'paid'] | ['debug', 'release'] | [6, 7] | [:] | [firstFreeJar: ["Multiple compatible variants found for library 'second':", - "Jar 'second:debug6Jar' [buildType:'debug', platform:'java6']", - "Jar 'second:release6Jar' [buildType:'release', platform:'java6']"], + [7] | [] | ['debug', 'release'] | [7, 8] | [:] | [firstDefaultJar: ["Multiple compatible variants found for library 'second':", + "Jar 'second:debug7Jar' [buildType:'debug', platform:'java7']", + "Jar 'second:release7Jar' [buildType:'release', platform:'java7']"]] + [7] | ['free', 'paid'] | ['debug', 'release'] | [7, 8] | [:] | [firstFreeJar: ["Multiple compatible variants found for library 'second':", + "Jar 'second:debug7Jar' [buildType:'debug', platform:'java7']", + "Jar 'second:release7Jar' [buildType:'release', platform:'java7']"], firstPaidJar: ["Multiple compatible variants found for library 'second':", - "Jar 'second:debug6Jar' [buildType:'debug', platform:'java6']", - "Jar 'second:release6Jar' [buildType:'release', platform:'java6']"]] + "Jar 'second:debug7Jar' [buildType:'debug', platform:'java7']", + "Jar 'second:release7Jar' [buildType:'release', platform:'java7']"]] and: outcome = errors ? 'fails' : 'succeeds' From 18ef40fb6f2b2613d256fb5a34ab75c6003de331 Mon Sep 17 00:00:00 2001 From: Gary Hale Date: Fri, 8 Mar 2019 16:13:50 -0500 Subject: [PATCH 475/853] Fix some more Java6 target compatibility instances --- .../jvm/tasks/api/internal/ApiClassExtractorTest.groovy | 4 ++++ .../tasks/api/internal/ApiClassExtractorTestSupport.groovy | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/subprojects/platform-jvm/src/test/groovy/org/gradle/jvm/tasks/api/internal/ApiClassExtractorTest.groovy b/subprojects/platform-jvm/src/test/groovy/org/gradle/jvm/tasks/api/internal/ApiClassExtractorTest.groovy index 9dda79d793458..22f7b1ed70804 100644 --- a/subprojects/platform-jvm/src/test/groovy/org/gradle/jvm/tasks/api/internal/ApiClassExtractorTest.groovy +++ b/subprojects/platform-jvm/src/test/groovy/org/gradle/jvm/tasks/api/internal/ApiClassExtractorTest.groovy @@ -16,8 +16,10 @@ package org.gradle.jvm.tasks.api.internal +import org.gradle.api.JavaVersion import org.gradle.internal.classanalysis.AsmConstants import org.gradle.internal.reflect.JavaReflectionUtil +import org.junit.Assume import org.objectweb.asm.ClassReader import org.objectweb.asm.ClassVisitor import org.objectweb.asm.Label @@ -284,6 +286,8 @@ class ApiClassExtractorTest extends ApiClassExtractorTestSupport { } void "target binary compatibility is maintained"() { + Assume.assumeFalse(target == '1.6' && JavaVersion.current().java12Compatible) + given: def api = toApi(target, [A: 'public class A {}']) diff --git a/subprojects/platform-jvm/src/test/groovy/org/gradle/jvm/tasks/api/internal/ApiClassExtractorTestSupport.groovy b/subprojects/platform-jvm/src/test/groovy/org/gradle/jvm/tasks/api/internal/ApiClassExtractorTestSupport.groovy index bed9de00908de..9b5f95865cf61 100644 --- a/subprojects/platform-jvm/src/test/groovy/org/gradle/jvm/tasks/api/internal/ApiClassExtractorTestSupport.groovy +++ b/subprojects/platform-jvm/src/test/groovy/org/gradle/jvm/tasks/api/internal/ApiClassExtractorTestSupport.groovy @@ -106,7 +106,7 @@ class ApiClassExtractorTestSupport extends Specification { public final TestNameTestDirectoryProvider temporaryFolder = new TestNameTestDirectoryProvider() protected ApiContainer toApi(Map sources) { - toApi('1.6', [], sources) + toApi('1.7', [], sources) } protected ApiContainer toApi(String targetVersion, Map sources) { @@ -114,7 +114,7 @@ class ApiClassExtractorTestSupport extends Specification { } protected ApiContainer toApi(List packages, Map sources) { - toApi('1.6', packages, sources) + toApi('1.7', packages, sources) } protected ApiContainer toApi(String targetVersion, List packages, Map sources) { From f04c8a65f51f8b0b1a89b3d5efa642197fd33abb Mon Sep 17 00:00:00 2001 From: Gary Hale Date: Fri, 8 Mar 2019 17:15:55 -0500 Subject: [PATCH 476/853] Fix some more Java6 target compatibility instances --- ...guageDependencyResolutionIntegrationTest.groovy | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/subprojects/language-java/src/integTest/groovy/org/gradle/language/java/JavaLanguageDependencyResolutionIntegrationTest.groovy b/subprojects/language-java/src/integTest/groovy/org/gradle/language/java/JavaLanguageDependencyResolutionIntegrationTest.groovy index aac0e3df2ee38..d93ab010c4ea8 100644 --- a/subprojects/language-java/src/integTest/groovy/org/gradle/language/java/JavaLanguageDependencyResolutionIntegrationTest.groovy +++ b/subprojects/language-java/src/integTest/groovy/org/gradle/language/java/JavaLanguageDependencyResolutionIntegrationTest.groovy @@ -1127,7 +1127,7 @@ model { scope << DependencyScope.values() } - @Requires(TestPrecondition.JDK8_OR_LATER) + @Requires(TestPrecondition.JDK9_OR_LATER) def "should not choose higher version than available"() { given: applyJavaPlugin(buildFile) @@ -1135,14 +1135,14 @@ model { model { components { dep(JvmLibrarySpec) { - targetPlatform 'java6' targetPlatform 'java7' targetPlatform 'java8' + targetPlatform 'java9' } main(JvmLibrarySpec) { targetPlatform 'java7' - targetPlatform 'java6' + targetPlatform 'java8' sources { java { dependencies { @@ -1154,11 +1154,11 @@ model { } tasks { - mainJava6Jar.finalizedBy('checkDependencies') mainJava7Jar.finalizedBy('checkDependencies') + mainJava8Jar.finalizedBy('checkDependencies') create('checkDependencies') { - assert compileMainJava6JarMainJava.taskDependencies.getDependencies(compileMainJava6JarMainJava).contains(depJava6ApiJar) assert compileMainJava7JarMainJava.taskDependencies.getDependencies(compileMainJava7JarMainJava).contains(depJava7ApiJar) + assert compileMainJava8JarMainJava.taskDependencies.getDependencies(compileMainJava8JarMainJava).contains(depJava8ApiJar) } } } @@ -1173,10 +1173,10 @@ model { executedAndNotSkipped ':tasks' then: - succeeds 'mainJava6Jar' + succeeds 'mainJava7Jar' and: - succeeds 'mainJava7Jar' + succeeds 'mainJava8Jar' } def "should display candidate platforms if no one matches"() { From 605c797f9373a3f1afa6eb1df0e9cadc7a84973d Mon Sep 17 00:00:00 2001 From: Gary Hale Date: Mon, 11 Mar 2019 11:25:17 -0400 Subject: [PATCH 477/853] Clean up some test constraints --- .../org/gradle/util/TestPrecondition.groovy | 6 +++++- .../SingleBinaryTypeWithVariantsTest.groovy | 19 +++++++++++++++---- .../api/internal/ApiClassExtractorTest.groovy | 6 ++++-- 3 files changed, 24 insertions(+), 7 deletions(-) diff --git a/subprojects/internal-testing/src/main/groovy/org/gradle/util/TestPrecondition.groovy b/subprojects/internal-testing/src/main/groovy/org/gradle/util/TestPrecondition.groovy index 923219b3f488a..d7095acca0d69 100644 --- a/subprojects/internal-testing/src/main/groovy/org/gradle/util/TestPrecondition.groovy +++ b/subprojects/internal-testing/src/main/groovy/org/gradle/util/TestPrecondition.groovy @@ -112,6 +112,9 @@ enum TestPrecondition implements org.gradle.internal.Factory { JDK10_OR_EARLIER({ JavaVersion.current() <= JavaVersion.VERSION_1_10 }), + JDK12_OR_LATER({ + JavaVersion.current() >= JavaVersion.VERSION_12 + }), JDK7_POSIX({ NOT_WINDOWS.fulfilled }), @@ -166,7 +169,8 @@ enum TestPrecondition implements org.gradle.internal.Factory { MSBUILD({ // Simplistic approach at detecting MSBuild by assuming Windows imply MSBuild is present WINDOWS.fulfilled - }) + }), + SUPPORTS_TARGETING_JAVA6({!JDK12_OR_LATER.fulfilled}) /** * A predicate for testing whether the precondition is fulfilled. diff --git a/subprojects/language-java/src/integTest/groovy/org/gradle/language/java/SingleBinaryTypeWithVariantsTest.groovy b/subprojects/language-java/src/integTest/groovy/org/gradle/language/java/SingleBinaryTypeWithVariantsTest.groovy index 789395141015b..387583feae36e 100644 --- a/subprojects/language-java/src/integTest/groovy/org/gradle/language/java/SingleBinaryTypeWithVariantsTest.groovy +++ b/subprojects/language-java/src/integTest/groovy/org/gradle/language/java/SingleBinaryTypeWithVariantsTest.groovy @@ -26,8 +26,9 @@ class SingleBinaryTypeWithVariantsTest extends VariantAwareDependencyResolutionS @Unroll("matching {jdk #jdk1, flavors #flavors1, builtTypes #buildTypes1} with {jdk #jdk2, flavors #flavors2, buildTypes #buildTypes2} #outcome") def "check resolution of a custom component onto a component of the same type (same class, same variant dimensions)"() { + assertAllTargetVersionsAreSupported(jdk1) + given: - Assume.assumeTrue(jdk1.max() <= Integer.valueOf(JavaVersion.current().majorVersion)) applyJavaPlugin(buildFile) addCustomLibraryType(buildFile) @@ -143,8 +144,9 @@ model { @Unroll("matching custom {jdk #jdk1, flavors #flavors1, builtTypes #buildTypes1} with Java {jdk #jdk2} #outcome") def "building a custom binary type and resolving against a library with standard JarBinarySpec instances"() { + assertAllTargetVersionsAreSupported(jdk1) + given: - Assume.assumeTrue(jdk1.max() <= Integer.valueOf(JavaVersion.current().majorVersion)) applyJavaPlugin(buildFile) addCustomLibraryType(buildFile) @@ -222,8 +224,9 @@ model { @Unroll("matching Java #jdk1 with custom {jdk #jdk2, flavors #flavors2, builtTypes #buildTypes2} #outcome") def "building a standard JarBinarySpec instance and resolving against a library with custom binary types. "() { + assertAllTargetVersionsAreSupported(jdk1) + given: - Assume.assumeTrue(jdk1.max() <= Integer.valueOf(JavaVersion.current().majorVersion)) applyJavaPlugin(buildFile) addCustomLibraryType(buildFile) @@ -303,8 +306,9 @@ model { @Unroll("matching custom1 {jdk #jdk1, flavors #flavors) with custom2 {jdk #jdk2, builtTypes #buildTypes} #outcome") def "building a custom JarBinarySpec type and resolving against a library with a different custom JarBinarySpec type"() { + assertAllTargetVersionsAreSupported(jdk1) + given: - Assume.assumeTrue(jdk1.max() <= Integer.valueOf(JavaVersion.current().majorVersion)) applyJavaPlugin(buildFile) addCustomLibraryType(buildFile) @@ -388,4 +392,11 @@ model { outcome = errors ? 'fails' : 'succeeds' } + /** + * Asserts that the current JDK can compile for all target versions (e.g. if we are running with JDK8, we + * will not be able to compile for Java9). + */ + private static assertAllTargetVersionsAreSupported(List targetVersions) { + Assume.assumeTrue(targetVersions.max() <= Integer.valueOf(JavaVersion.current().majorVersion)) + } } diff --git a/subprojects/platform-jvm/src/test/groovy/org/gradle/jvm/tasks/api/internal/ApiClassExtractorTest.groovy b/subprojects/platform-jvm/src/test/groovy/org/gradle/jvm/tasks/api/internal/ApiClassExtractorTest.groovy index 22f7b1ed70804..aa04d25448040 100644 --- a/subprojects/platform-jvm/src/test/groovy/org/gradle/jvm/tasks/api/internal/ApiClassExtractorTest.groovy +++ b/subprojects/platform-jvm/src/test/groovy/org/gradle/jvm/tasks/api/internal/ApiClassExtractorTest.groovy @@ -16,7 +16,6 @@ package org.gradle.jvm.tasks.api.internal -import org.gradle.api.JavaVersion import org.gradle.internal.classanalysis.AsmConstants import org.gradle.internal.reflect.JavaReflectionUtil import org.junit.Assume @@ -29,6 +28,8 @@ import spock.lang.Unroll import java.lang.reflect.Modifier +import static org.gradle.util.TestPrecondition.SUPPORTS_TARGETING_JAVA6 + class ApiClassExtractorTest extends ApiClassExtractorTestSupport { def "should not remove public method"() { @@ -286,7 +287,7 @@ class ApiClassExtractorTest extends ApiClassExtractorTestSupport { } void "target binary compatibility is maintained"() { - Assume.assumeFalse(target == '1.6' && JavaVersion.current().java12Compatible) + Assume.assumeFalse(target == "1.6" && !SUPPORTS_TARGETING_JAVA6.fulfilled) given: def api = toApi(target, [A: 'public class A {}']) @@ -308,6 +309,7 @@ class ApiClassExtractorTest extends ApiClassExtractorTestSupport { target | expectedVersion '1.6' | 50 '1.7' | 51 + '1.8' | 52 } def "should not remove public field"() { From dfd88b452919cffca7add39ecadcf4721022d439 Mon Sep 17 00:00:00 2001 From: Gary Hale Date: Mon, 11 Mar 2019 11:37:40 -0400 Subject: [PATCH 478/853] Handle scala jdk version better --- .../gradle/scala/ScalaCrossCompilationIntegrationTest.groovy | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/subprojects/scala/src/integTest/groovy/org/gradle/scala/ScalaCrossCompilationIntegrationTest.groovy b/subprojects/scala/src/integTest/groovy/org/gradle/scala/ScalaCrossCompilationIntegrationTest.groovy index 584b5b4161d29..a009336a3473d 100644 --- a/subprojects/scala/src/integTest/groovy/org/gradle/scala/ScalaCrossCompilationIntegrationTest.groovy +++ b/subprojects/scala/src/integTest/groovy/org/gradle/scala/ScalaCrossCompilationIntegrationTest.groovy @@ -25,7 +25,9 @@ import org.gradle.test.fixtures.file.ClassFile import org.gradle.util.TextUtil import org.junit.Assume -@TargetVersions(["1.7", "1.8"]) +import static org.gradle.util.TestPrecondition.SUPPORTS_TARGETING_JAVA6 + +@TargetVersions(["1.6", "1.7", "1.8"]) class ScalaCrossCompilationIntegrationTest extends MultiVersionIntegrationSpec { JavaVersion getJavaVersion() { JavaVersion.toVersion(MultiVersionIntegrationSpec.version) @@ -39,6 +41,7 @@ class ScalaCrossCompilationIntegrationTest extends MultiVersionIntegrationSpec { Assume.assumeTrue(target != null) // Java Compiler does not fork for joint compilation - therefore we cannot compile for a Java Version bigger than the current JVM Assume.assumeTrue(javaVersion.compareTo(JavaVersion.current()) <= 0) + Assume.assumeFalse(javaVersion.java6 && !SUPPORTS_TARGETING_JAVA6.fulfilled) def java = TextUtil.escapeString(target.getJavaExecutable()) def javaHome = TextUtil.escapeString(target.javaHome.absolutePath) From c512696601c88816b5c68e3a7b3589549c5a59fe Mon Sep 17 00:00:00 2001 From: Sterling Greene Date: Mon, 11 Mar 2019 17:03:42 -0400 Subject: [PATCH 479/853] Polish soak test --- ...DaemonPerformanceMonitoringSoakTest.groovy | 43 ++++--------------- 1 file changed, 9 insertions(+), 34 deletions(-) diff --git a/subprojects/soak/src/integTest/groovy/org/gradle/launcher/daemon/DaemonPerformanceMonitoringSoakTest.groovy b/subprojects/soak/src/integTest/groovy/org/gradle/launcher/daemon/DaemonPerformanceMonitoringSoakTest.groovy index 600ca6de2c1fa..85249155c4c59 100644 --- a/subprojects/soak/src/integTest/groovy/org/gradle/launcher/daemon/DaemonPerformanceMonitoringSoakTest.groovy +++ b/subprojects/soak/src/integTest/groovy/org/gradle/launcher/daemon/DaemonPerformanceMonitoringSoakTest.groovy @@ -26,14 +26,7 @@ import org.junit.experimental.categories.Category @Category(SoakTest) @TargetCoverage({DaemonPerformanceMonitoringCoverage.ALL_VERSIONS}) class DaemonPerformanceMonitoringSoakTest extends DaemonMultiJdkIntegrationTest { - int maxBuilds - String heapSize - int leakRate - Closure setupBuildScript - def setup() { - buildFile << "${logJdk()}" - // Set JVM args for GC String jvmArgs = "" if (file('gradle.properties').exists()) { @@ -47,23 +40,18 @@ class DaemonPerformanceMonitoringSoakTest extends DaemonMultiJdkIntegrationTest def "when build leaks slowly daemon is eventually expired"() { when: - setupBuildScript = tenuredHeapLeak - maxBuilds = builds - heapSize = heap - leakRate = rate - + setupTenuredHeapLeak(leakRate) then: - daemonIsExpiredEagerly() + daemonIsExpiredEagerly(maxBuilds, heapSize) where: - builds | heap | rate - 45 | "200m" | 600 - 40 | "1024m" | 4000 + maxBuilds | heapSize | leakRate + 45 | "200m" | 600 + 40 | "1024m" | 4000 } - private boolean daemonIsExpiredEagerly() { + private boolean daemonIsExpiredEagerly(int maxBuilds, String heapSize) { def dataFile = file("stats") - setupBuildScript() int newDaemons = 0 try { for (int i = 0; i < maxBuilds; i++) { @@ -88,8 +76,10 @@ class DaemonPerformanceMonitoringSoakTest extends DaemonMultiJdkIntegrationTest return false } - private final Closure tenuredHeapLeak = { + private final void setupTenuredHeapLeak(int leakRate) { buildFile << """ + logger.warn("Build is running with JDK: " + System.getProperty('java.home')) + class State { static int x static map = [:] @@ -114,19 +104,4 @@ class DaemonPerformanceMonitoringSoakTest extends DaemonMultiJdkIntegrationTest } """ } - - private final Closure greedyBuildNoLeak = { - buildFile << """ - Map map = [:] - - //simulate normal collectible objects - 5000.times { - map.put(it, "foo" * ${leakRate}) - } - """ - } - - String logJdk() { - return """logger.warn("Build is running with JDK: \${System.getProperty('java.home')}")""" - } } From 19af2e9f68e7e1dc5022f6e380fbc2b39dc395f3 Mon Sep 17 00:00:00 2001 From: Daniel Lacasse Date: Mon, 11 Mar 2019 19:38:06 -0400 Subject: [PATCH 480/853] Update Gradle wrapper to 5.3 RC2 --- gradle/wrapper/gradle-wrapper.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 3447790fc96de..a257a1753dd88 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions-snapshots/gradle-5.3-20190307202351+0000-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-5.3-rc-2-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists From 2c150567d8a117b17f6f2351e46e27573dc85e99 Mon Sep 17 00:00:00 2001 From: Daniel Lacasse Date: Mon, 11 Mar 2019 19:44:51 -0400 Subject: [PATCH 481/853] Update wrapper to latest nightly --- gradle/wrapper/gradle-wrapper.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index a257a1753dd88..0b686b49804c4 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-5.3-rc-2-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-5.4-20190311000052+0000-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists From 5bcc9ede615c88e2ba86982fd2e246a6f0f9f676 Mon Sep 17 00:00:00 2001 From: Bo Zhang Date: Tue, 12 Mar 2019 09:00:04 +0800 Subject: [PATCH 482/853] Correct distribution url --- gradle/wrapper/gradle-wrapper.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 0b686b49804c4..26ec2316bf4a1 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-5.4-20190311000052+0000-bin.zip +distributionUrl=https\://services.gradle.org/distributions-snapshots/gradle-5.4-20190311000052+0000-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists From cca66539e1f9dbf4dfaa8d87ad3666015b25f030 Mon Sep 17 00:00:00 2001 From: Gradleware Git Bot Date: Tue, 12 Mar 2019 02:34:42 +0100 Subject: [PATCH 483/853] Publish 5.3-20190312011340+0000 --- released-versions.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/released-versions.json b/released-versions.json index 6c7ecb79d1ce4..4cd37e6fe6308 100644 --- a/released-versions.json +++ b/released-versions.json @@ -1,7 +1,7 @@ { "latestReleaseSnapshot": { - "version": "5.3-20190311010311+0000", - "buildTime": "20190311010311+0000" + "version": "5.3-20190312011340+0000", + "buildTime": "20190312011340+0000" }, "latestRc": { "version": "5.3-rc-2", From b569811f882666a04363c984457c799cf38b08c8 Mon Sep 17 00:00:00 2001 From: Paul Merlin Date: Tue, 12 Mar 2019 10:51:07 +0100 Subject: [PATCH 484/853] Refine :kCE:patchKotlinCompilerEmbeddable task by turning additionnalFiles into a FileCollection renamed to additionnalRootFiles for clarity using @PathSensitive(PathSensitivity.NAME_ONLY) Signed-off-by: Paul Merlin --- .../build/PatchKotlinCompilerEmbeddable.kt | 39 +++++++++---------- .../kotlin-compiler-embeddable.gradle.kts | 2 +- 2 files changed, 20 insertions(+), 21 deletions(-) diff --git a/buildSrc/subprojects/kotlin-dsl/src/main/kotlin/build/PatchKotlinCompilerEmbeddable.kt b/buildSrc/subprojects/kotlin-dsl/src/main/kotlin/build/PatchKotlinCompilerEmbeddable.kt index adc70f5a45398..3e140c10e131d 100644 --- a/buildSrc/subprojects/kotlin-dsl/src/main/kotlin/build/PatchKotlinCompilerEmbeddable.kt +++ b/buildSrc/subprojects/kotlin-dsl/src/main/kotlin/build/PatchKotlinCompilerEmbeddable.kt @@ -17,16 +17,16 @@ package build import org.gradle.api.DefaultTask -import org.gradle.api.file.EmptyFileVisitor -import org.gradle.api.file.FileTree -import org.gradle.api.file.FileVisitDetails import org.gradle.api.file.RelativePath import org.gradle.api.specs.Spec import org.gradle.api.specs.Specs import org.gradle.api.tasks.CacheableTask import org.gradle.api.tasks.Classpath import org.gradle.api.tasks.Input +import org.gradle.api.tasks.InputFiles import org.gradle.api.tasks.OutputFile +import org.gradle.api.tasks.PathSensitive +import org.gradle.api.tasks.PathSensitivity import org.gradle.api.tasks.TaskAction import org.gradle.api.internal.file.archive.ZipCopyAction.CONSTANT_TIME_FOR_ZIP_ENTRIES @@ -47,16 +47,17 @@ open class PatchKotlinCompilerEmbeddable : DefaultTask() { val excludes = project.objects.listProperty() @Classpath - val originalFiles = project.files() + val originalFiles = project.objects.fileCollection() @Classpath - val dependencies = project.files() + val dependencies = project.objects.fileCollection() @Input val dependenciesIncludes = project.objects.mapProperty>() - @Classpath - lateinit var additionalFiles: FileTree + @InputFiles + @PathSensitive(PathSensitivity.NAME_ONLY) + val additionalRootFiles = project.objects.fileCollection() @OutputFile val outputFile = project.objects.fileProperty() @@ -87,7 +88,7 @@ open class PatchKotlinCompilerEmbeddable : DefaultTask() { patchedJar.setComment(originalJar.comment) copyFromOriginalApplyingExcludes(originalJar, patchedJar) copyFromDependenciesApplyingIncludes(patchedJar) - copyAdditionalFiles(patchedJar) + copyAdditionalRootFiles(patchedJar) } private @@ -114,19 +115,17 @@ open class PatchKotlinCompilerEmbeddable : DefaultTask() { } private - fun copyAdditionalFiles(patchedJar: ZipOutputStream) = - additionalFiles.visit(object : EmptyFileVisitor() { - override fun visitFile(fileDetails: FileVisitDetails) { - patchedJar.putNextEntry(ZipEntry(fileDetails.relativePath.pathString).apply { - time = CONSTANT_TIME_FOR_ZIP_ENTRIES - size = fileDetails.file.length() - }) - fileDetails.file.inputStream().buffered().use { input -> - input.copyTo(patchedJar) - } - patchedJar.closeEntry() + fun copyAdditionalRootFiles(patchedJar: ZipOutputStream) = + additionalRootFiles.forEach { additionalRootFile -> + patchedJar.putNextEntry(ZipEntry(additionalRootFile.name).apply { + time = CONSTANT_TIME_FOR_ZIP_ENTRIES + size = additionalRootFile.length() + }) + additionalRootFile.inputStream().buffered().use { input -> + input.copyTo(patchedJar) } - }) + patchedJar.closeEntry() + } private fun copyEntry(sourceJar: ZipFile, sourceEntry: ZipEntry, destinationJar: ZipOutputStream) { diff --git a/subprojects/kotlin-compiler-embeddable/kotlin-compiler-embeddable.gradle.kts b/subprojects/kotlin-compiler-embeddable/kotlin-compiler-embeddable.gradle.kts index f924ef2428ad1..cfa6d2b29aab8 100644 --- a/subprojects/kotlin-compiler-embeddable/kotlin-compiler-embeddable.gradle.kts +++ b/subprojects/kotlin-compiler-embeddable/kotlin-compiler-embeddable.gradle.kts @@ -55,7 +55,7 @@ tasks { dependenciesIncludes.set(mapOf( "jansi-" to listOf("META-INF/native/**", "org/fusesource/jansi/internal/CLibrary*.class") )) - additionalFiles = files(classpathManifest).asFileTree + additionalRootFiles.from(classpathManifest) outputFile.set(jar.get().archiveFile) } From cc9169c20ea914cc754833046abb63a607d6dfaa Mon Sep 17 00:00:00 2001 From: Paul Merlin Date: Tue, 12 Mar 2019 11:12:29 +0100 Subject: [PATCH 485/853] Prefer abstract task properties where applicable Signed-off-by: Paul Merlin --- .../build/PatchKotlinCompilerEmbeddable.kt | 23 +++++++++++-------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/buildSrc/subprojects/kotlin-dsl/src/main/kotlin/build/PatchKotlinCompilerEmbeddable.kt b/buildSrc/subprojects/kotlin-dsl/src/main/kotlin/build/PatchKotlinCompilerEmbeddable.kt index 3e140c10e131d..5bf07a33709f7 100644 --- a/buildSrc/subprojects/kotlin-dsl/src/main/kotlin/build/PatchKotlinCompilerEmbeddable.kt +++ b/buildSrc/subprojects/kotlin-dsl/src/main/kotlin/build/PatchKotlinCompilerEmbeddable.kt @@ -17,6 +17,8 @@ package build import org.gradle.api.DefaultTask +import org.gradle.api.file.ConfigurableFileCollection +import org.gradle.api.file.RegularFileProperty import org.gradle.api.file.RelativePath import org.gradle.api.specs.Spec import org.gradle.api.specs.Specs @@ -41,26 +43,27 @@ import org.gradle.kotlin.dsl.* @CacheableTask -open class PatchKotlinCompilerEmbeddable : DefaultTask() { +@Suppress("unused") +abstract class PatchKotlinCompilerEmbeddable : DefaultTask() { @Input val excludes = project.objects.listProperty() - @Classpath - val originalFiles = project.objects.fileCollection() + @get:Classpath + abstract val originalFiles: ConfigurableFileCollection - @Classpath - val dependencies = project.objects.fileCollection() + @get:Classpath + abstract val dependencies: ConfigurableFileCollection @Input val dependenciesIncludes = project.objects.mapProperty>() - @InputFiles - @PathSensitive(PathSensitivity.NAME_ONLY) - val additionalRootFiles = project.objects.fileCollection() + @get:InputFiles + @get:PathSensitive(PathSensitivity.NAME_ONLY) + abstract val additionalRootFiles: ConfigurableFileCollection - @OutputFile - val outputFile = project.objects.fileProperty() + @get:OutputFile + abstract val outputFile: RegularFileProperty @TaskAction @Suppress("unused") From 46f4d75ec41108e05c786dc755166f2ee7a8d241 Mon Sep 17 00:00:00 2001 From: Stefan Wolf Date: Fri, 8 Mar 2019 11:44:48 +0100 Subject: [PATCH 486/853] Add new IncrementalInputs type --- .../incremental/IncrementalInputs.java | 98 +++++++++++++++++++ .../execution/incremental/package-info.java | 23 +++++ .../incremental/IncrementalTaskInputs.java | 2 +- 3 files changed, 122 insertions(+), 1 deletion(-) create mode 100644 subprojects/core-api/src/main/java/org/gradle/api/execution/incremental/IncrementalInputs.java create mode 100644 subprojects/core-api/src/main/java/org/gradle/api/execution/incremental/package-info.java diff --git a/subprojects/core-api/src/main/java/org/gradle/api/execution/incremental/IncrementalInputs.java b/subprojects/core-api/src/main/java/org/gradle/api/execution/incremental/IncrementalInputs.java new file mode 100644 index 0000000000000..03fb40bbdc6e1 --- /dev/null +++ b/subprojects/core-api/src/main/java/org/gradle/api/execution/incremental/IncrementalInputs.java @@ -0,0 +1,98 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.api.execution.incremental; + +import org.gradle.api.Incubating; +import org.gradle.api.NonExtensible; +import org.gradle.api.tasks.incremental.InputFileDetails; + +/** + * Provides access to any input files that need to be processed by an incremental work action. + * + *

    + * An incremental work action is one that accepts a single {@link IncrementalInputs} parameter. + * The work action can then query what changed for an input property since the last execution to only process the changes. + * + *

    + * class IncrementalReverseTask extends DefaultTask {
    + *     {@literal @}InputDirectory
    + *     def File inputDir
    + *
    + *     {@literal @}OutputDirectory
    + *     def File outputDir
    + *
    + *     {@literal @}TaskAction
    + *     void execute(IncrementalInputs inputs) {
    + *         if (!inputs.incremental)
    + *             project.delete(outputDir.listFiles())
    + *
    + *         inputs.getChanges(inputDir).each { change ->
    + *             if (change.removed) {
    + *                 def targetFile = project.file("$outputDir/${change.file.name}")
    + *                 if (targetFile.exists()) {
    + *                     targetFile.delete()
    + *                 }
    + *             } else {
    + *                 def targetFile = project.file("$outputDir/${change.file.name}")
    + *                 targetFile.text = change.file.text.reverse()
    + *             }
    + *         }
    + *     }
    + * }
    + * 
    + * + *

    + * In the case where Gradle is unable to determine which input files need to be reprocessed, then all of the input files will be reported as added. + * Cases where this occurs include: + *

      + *
    • There is no history available from a previous execution.
    • + *
    • An non-file input property has changed since the previous execution.
    • + *
    • One or more output files have changed since the previous execution.
    • + *
    + * + * @since 5.4 + */ +@NonExtensible +@Incubating +public interface IncrementalInputs { + /** + * Indicates if it was possible for Gradle to determine which input files were out of date compared to a previous execution. + * Incremental inputs are unavailable when history is unavailable (i.e. this piece of work has never been executed before), or if there are changes to non-file input properties, or output files. + *

    + * When true: + *

    + *
      + *
    • {@link #getChanges(Object)} reports changes to the input files compared to the previous execution.
    • + *
    + *

    + * When false: + *

    + *
      + *
    • Every input file is reported via {@link #getChanges(Object)} as if it was 'added'.
    • + *
    + */ + boolean isIncremental(); + + /** + * Changes for the property. + * + *

    When {@link #isIncremental()} is {@code false}, then all elements of the property are returned as added.

    + * + * @param property The instance of the property to query. + */ + Iterable getChanges(Object property); +} diff --git a/subprojects/core-api/src/main/java/org/gradle/api/execution/incremental/package-info.java b/subprojects/core-api/src/main/java/org/gradle/api/execution/incremental/package-info.java new file mode 100644 index 0000000000000..3c492261fba50 --- /dev/null +++ b/subprojects/core-api/src/main/java/org/gradle/api/execution/incremental/package-info.java @@ -0,0 +1,23 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Classes for dealing with incremental execution. + */ +@NonNullApi +package org.gradle.api.execution.incremental; + +import org.gradle.api.NonNullApi; diff --git a/subprojects/core-api/src/main/java/org/gradle/api/tasks/incremental/IncrementalTaskInputs.java b/subprojects/core-api/src/main/java/org/gradle/api/tasks/incremental/IncrementalTaskInputs.java index e3243ac0a5a97..0a41e5aae0942 100644 --- a/subprojects/core-api/src/main/java/org/gradle/api/tasks/incremental/IncrementalTaskInputs.java +++ b/subprojects/core-api/src/main/java/org/gradle/api/tasks/incremental/IncrementalTaskInputs.java @@ -73,7 +73,7 @@ @NonExtensible public interface IncrementalTaskInputs { /** - * Indicates if it was possible for Gradle to determine which exactly input files were out of date compared to a previous execution. + * Indicates if it was possible for Gradle to determine which input files were out of date compared to a previous execution. * This is not possible in the case of no previous execution, changed input properties, output files, etc. *

    * When true: From 98dc90438fbf71cc31986983c884a31cde6f5820 Mon Sep 17 00:00:00 2001 From: Stefan Wolf Date: Fri, 8 Mar 2019 11:49:36 +0100 Subject: [PATCH 487/853] Add tests for incremental inputs --- .../IncrementalInputsIntegrationTest.groovy | 76 +++++++++++++++++++ ...ncrementalTaskInputsIntegrationTest.groovy | 71 +++++++++++++++++ .../IncrementalTasksIntegrationTest.groovy | 63 ++++----------- ...TransformIncrementalIntegrationTest.groovy | 65 ++++++++++++++++ 4 files changed, 228 insertions(+), 47 deletions(-) create mode 100644 subprojects/core/src/integTest/groovy/org/gradle/api/tasks/IncrementalInputsIntegrationTest.groovy create mode 100644 subprojects/core/src/integTest/groovy/org/gradle/api/tasks/IncrementalTaskInputsIntegrationTest.groovy create mode 100644 subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformIncrementalIntegrationTest.groovy diff --git a/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/IncrementalInputsIntegrationTest.groovy b/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/IncrementalInputsIntegrationTest.groovy new file mode 100644 index 0000000000000..12f4286075f3a --- /dev/null +++ b/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/IncrementalInputsIntegrationTest.groovy @@ -0,0 +1,76 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.api.tasks + +import org.gradle.internal.change.ChangeType + +class IncrementalInputsIntegrationTest extends IncrementalTasksIntegrationTest { + + String getTaskAction() { + """ + void execute(IncrementalInputs inputs) { + assert !(inputs instanceof ExtensionAware) + + if (project.hasProperty('forceFail')) { + throw new RuntimeException('failed') + } + + incrementalExecution = inputs.incremental + + inputs.getChanges(inputDir).each { change -> + switch (change) { + case { it.added }: + addedFiles << change.file + break + case { it.modified }: + modifiedFiles << change.file + break + case { it.removed }: + removedFiles << change.file + break + default: + throw new IllegalStateException() + } + } + + if (!inputs.incremental) { + createOutputsNonIncremental() + } + + touchOutputs() + } + """ + } + + @Override + ChangeType getRebuildChangeType() { + return ChangeType.ADDED + } + + def "incremental task is executed non-incrementally when input file property has been added"() { + given: + file('new-input.txt').text = "new input file" + previousExecution() + + when: + buildFile << "incremental.inputs.file('new-input.txt')" + + then: + executesWithRebuildContext() + } + +} diff --git a/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/IncrementalTaskInputsIntegrationTest.groovy b/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/IncrementalTaskInputsIntegrationTest.groovy new file mode 100644 index 0000000000000..6d27937103d65 --- /dev/null +++ b/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/IncrementalTaskInputsIntegrationTest.groovy @@ -0,0 +1,71 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.api.tasks + +import org.gradle.internal.change.ChangeType + +class IncrementalTaskInputsIntegrationTest extends IncrementalTasksIntegrationTest { + + String getTaskAction() { + """ + void execute(IncrementalTaskInputs inputs) { + assert !(inputs instanceof ExtensionAware) + + if (project.hasProperty('forceFail')) { + throw new RuntimeException('failed') + } + + incrementalExecution = inputs.incremental + + inputs.outOfDate { change -> + if (change.added) { + addedFiles << change.file + } else { + modifiedFiles << change.file + } + } + + inputs.removed { change -> + removedFiles << change.file + } + + if (!inputs.incremental) { + createOutputsNonIncremental() + } + + touchOutputs() + } + """ + } + + @Override + ChangeType getRebuildChangeType() { + ChangeType.MODIFIED + } + + def "incremental task is executed non-incrementally when input file property has been added"() { + given: + file('new-input.txt').text = "new input file" + previousExecution() + + when: + buildFile << "incremental.inputs.file('new-input.txt')" + + then: + executesWithRebuildContext("ext.modified += ['new-input.txt']") + } +} diff --git a/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/IncrementalTasksIntegrationTest.groovy b/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/IncrementalTasksIntegrationTest.groovy index cf635fb5a57ff..d6d24081a69bd 100644 --- a/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/IncrementalTasksIntegrationTest.groovy +++ b/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/IncrementalTasksIntegrationTest.groovy @@ -17,10 +17,16 @@ package org.gradle.api.tasks import org.gradle.integtests.fixtures.AbstractIntegrationSpec +import org.gradle.internal.change.ChangeType import spock.lang.Issue import spock.lang.Unroll -class IncrementalTasksIntegrationTest extends AbstractIntegrationSpec { +abstract class IncrementalTasksIntegrationTest extends AbstractIntegrationSpec { + + abstract String getTaskAction() + + abstract ChangeType getRebuildChangeType(); + def "setup"() { setupTaskSources() buildFile << buildFileBase @@ -45,39 +51,14 @@ class IncrementalTasksIntegrationTest extends AbstractIntegrationSpec { import org.gradle.api.plugins.* import org.gradle.api.tasks.* import org.gradle.api.tasks.incremental.* + import org.gradle.api.execution.incremental.* class BaseIncrementalTask extends DefaultTask { @InputDirectory def File inputDir @TaskAction - void execute(IncrementalTaskInputs inputs) { - assert !(inputs instanceof ExtensionAware) - - if (project.hasProperty('forceFail')) { - throw new RuntimeException('failed') - } - - incrementalExecution = inputs.incremental - - inputs.outOfDate { change -> - if (change.added) { - addedFiles << change.file - } else { - changedFiles << change.file - } - } - - inputs.removed { change -> - removedFiles << change.file - } - - if (!inputs.incremental) { - createOutputsNonIncremental() - } - - touchOutputs() - } + $taskAction def touchOutputs() { } @@ -86,7 +67,7 @@ class IncrementalTasksIntegrationTest extends AbstractIntegrationSpec { } def addedFiles = [] - def changedFiles = [] + def modifiedFiles = [] def removedFiles = [] def incrementalExecution } @@ -125,7 +106,7 @@ class IncrementalTasksIntegrationTest extends AbstractIntegrationSpec { ext { incrementalExecution = true added = [] - changed = [] + modified = [] removed = [] } @@ -133,7 +114,7 @@ class IncrementalTasksIntegrationTest extends AbstractIntegrationSpec { doLast { assert incremental.incrementalExecution == project.ext.incrementalExecution assert incremental.addedFiles.collect({ it.name }).sort() == project.ext.added - assert incremental.changedFiles.collect({ it.name }).sort() == project.ext.changed + assert incremental.modifiedFiles.collect({ it.name }).sort() == project.ext.modified assert incremental.removedFiles.collect({ it.name }).sort() == project.ext.removed } } @@ -164,7 +145,7 @@ class IncrementalTasksIntegrationTest extends AbstractIntegrationSpec { file('inputs/file1.txt') << "changed content" then: - executesWithIncrementalContext("ext.changed = ['file1.txt']") + executesWithIncrementalContext("ext.modified = ['file1.txt']") } def "incremental task is informed of 'out-of-date' files when input file added"() { @@ -214,7 +195,7 @@ class IncrementalTasksIntegrationTest extends AbstractIntegrationSpec { then: executesWithIncrementalContext(""" -ext.changed = ['file1.txt'] +ext.modified = ['file1.txt'] ext.removed = ['file2.txt'] ext.added = ['file3.txt', 'file4.txt'] """) @@ -249,18 +230,6 @@ ext.added = ['file3.txt', 'file4.txt'] executesWithRebuildContext() } - def "incremental task is informed that all input files are 'out-of-date' when input file property has been added"() { - given: - file('new-input.txt').text = "new input file" - previousExecution() - - when: - buildFile << "incremental.inputs.file('new-input.txt')" - - then: - executesWithRebuildContext("ext.changed += ['new-input.txt']") - } - def "incremental task is informed that all input files are 'out-of-date' when input file property has been removed"() { given: buildFile << """ @@ -373,7 +342,7 @@ ext.added = ['file3.txt', 'file4.txt'] failedExecution() then: - executesWithIncrementalContext("ext.changed = ['file1.txt']") + executesWithIncrementalContext("ext.modified = ['file1.txt']") } @Unroll @@ -445,7 +414,7 @@ ext.added = ['file3.txt', 'file4.txt'] def executesWithRebuildContext(String fileChanges = "") { buildFile << """ - ext.changed = ['file0.txt', 'file1.txt', 'file2.txt', 'inputs'] + ext.${rebuildChangeType.name().toLowerCase(Locale.US)} = ['file0.txt', 'file1.txt', 'file2.txt', 'inputs'] ext.incrementalExecution = false """ buildFile << fileChanges diff --git a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformIncrementalIntegrationTest.groovy b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformIncrementalIntegrationTest.groovy new file mode 100644 index 0000000000000..a953985a85ff6 --- /dev/null +++ b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformIncrementalIntegrationTest.groovy @@ -0,0 +1,65 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.integtests.resolve.transform + +import org.gradle.integtests.fixtures.AbstractDependencyResolutionTest + +class ArtifactTransformIncrementalIntegrationTest extends AbstractDependencyResolutionTest implements ArtifactTransformTestFixture { + + def "can query incremental changes"() { + settingsFile << """ + include 'a', 'b', 'c' + """ + setupBuildWithColorTransform { + produceDirs() + } + buildFile << """ + project(':a') { + dependencies { + implementation project(':b') + implementation project(':c') + } + } + + abstract class MakeGreen implements TransformAction { + + @Inject + abstract IncrementalInputs getIncrementalInputs() + + @InputArtifact + abstract File getInput() + + void transform(TransformOutputs outputs) { + println "incremental: " + incrementalInputs.incremental + println "changes: \\n" + incrementalInputs.getChanges(input).join("\\n") + } + } + """ + + when: + run(":a:resolve") + then: + outputContains("incremental: false") + + when: + executer.withArguments("-PbContent=changed") + run(":a:resolve") + then: + outputContains("incremental: true") + } + +} From 2e1dc7eab3b97388644327f41465095de494a1fb Mon Sep 17 00:00:00 2001 From: Stefan Wolf Date: Tue, 12 Mar 2019 10:33:25 +0100 Subject: [PATCH 488/853] Add fine grained incremental tasks --- .../AbstractIncrementalTaskAction.java | 45 +++++++ .../DefaultTaskClassInfoStore.java | 43 +++++-- .../IncrementalInputsTaskAction.java | 113 ++++++++++++++++++ ...a => IncrementalTaskInputsTaskAction.java} | 34 +++--- .../DefaultInputFilePropertySpec.java | 9 +- .../properties/GetInputFilesVisitor.java | 4 +- .../properties/InputFilePropertySpec.java | 1 + .../DefaultExecutionStateChangeDetector.java | 48 ++++++-- .../changes/DefaultInputFileChanges.java | 42 +++++++ .../changes/ExecutionStateChanges.java | 3 +- .../history/changes/InputFileChanges.java | 18 +-- .../steps/ResolveChangesStepTest.groovy | 4 +- 12 files changed, 305 insertions(+), 59 deletions(-) create mode 100644 subprojects/core/src/main/java/org/gradle/api/internal/project/taskfactory/AbstractIncrementalTaskAction.java create mode 100644 subprojects/core/src/main/java/org/gradle/api/internal/project/taskfactory/IncrementalInputsTaskAction.java rename subprojects/core/src/main/java/org/gradle/api/internal/project/taskfactory/{IncrementalTaskAction.java => IncrementalTaskInputsTaskAction.java} (75%) create mode 100644 subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/DefaultInputFileChanges.java diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/project/taskfactory/AbstractIncrementalTaskAction.java b/subprojects/core/src/main/java/org/gradle/api/internal/project/taskfactory/AbstractIncrementalTaskAction.java new file mode 100644 index 0000000000000..c7d55f9fb3ca7 --- /dev/null +++ b/subprojects/core/src/main/java/org/gradle/api/internal/project/taskfactory/AbstractIncrementalTaskAction.java @@ -0,0 +1,45 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.api.internal.project.taskfactory; + +import org.gradle.api.Task; +import org.gradle.api.internal.tasks.ContextAwareTaskAction; +import org.gradle.api.internal.tasks.TaskExecutionContext; + +import java.lang.reflect.Method; + +public abstract class AbstractIncrementalTaskAction extends StandardTaskAction implements ContextAwareTaskAction { + private TaskExecutionContext context; + + public AbstractIncrementalTaskAction(Class type, Method method) { + super(type, method); + } + + @Override + public void contextualise(TaskExecutionContext context) { + this.context = context; + } + + @Override + public void releaseContext() { + this.context = null; + } + + protected TaskExecutionContext getContext() { + return context; + } +} diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/project/taskfactory/DefaultTaskClassInfoStore.java b/subprojects/core/src/main/java/org/gradle/api/internal/project/taskfactory/DefaultTaskClassInfoStore.java index ed39c80fcf6a9..ea6b806ea9895 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/project/taskfactory/DefaultTaskClassInfoStore.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/project/taskfactory/DefaultTaskClassInfoStore.java @@ -23,6 +23,7 @@ import org.gradle.api.NonNullApi; import org.gradle.api.Task; import org.gradle.api.Transformer; +import org.gradle.api.execution.incremental.IncrementalInputs; import org.gradle.api.tasks.CacheableTask; import org.gradle.api.tasks.TaskAction; import org.gradle.api.tasks.incremental.IncrementalTaskInputs; @@ -65,7 +66,7 @@ private TaskClassInfo createTaskClassInfo(Class type) { if (taskActionFactory == null) { continue; } - if (taskActionFactory instanceof IncrementalTaskActionFactory) { + if (taskActionFactory instanceof AbstractIncrementalTaskActionFactory) { if (incremental) { throw new GradleException(String.format("Cannot have multiple @TaskAction methods accepting an %s parameter.", IncrementalTaskInputs.class.getSimpleName())); } @@ -97,12 +98,16 @@ private static TaskActionFactory createTaskAction(Class taskType TaskActionFactory taskActionFactory; if (parameterTypes.length == 1) { - if (!parameterTypes[0].equals(IncrementalTaskInputs.class)) { + Class parameterType = parameterTypes[0]; + if (parameterType.equals(IncrementalTaskInputs.class)) { + taskActionFactory = new IncrementalTaskInputsTaskActionFactory(taskType, method); + } else if (parameterType.equals(IncrementalInputs.class)) { + taskActionFactory = new IncrementalInputsTaskActionFactory(taskType, method); + } else { throw new GradleException(String.format( "Cannot use @TaskAction annotation on method %s.%s() because %s is not a valid parameter to an action method.", - declaringClass.getSimpleName(), method.getName(), parameterTypes[0])); + declaringClass.getSimpleName(), method.getName(), parameterType)); } - taskActionFactory = new IncrementalTaskActionFactory(taskType, method); } else { taskActionFactory = new StandardTaskActionFactory(taskType, method); } @@ -134,18 +139,42 @@ public Action create(Instantiator instantiator) { } } - private static class IncrementalTaskActionFactory implements TaskActionFactory { + private static class IncrementalInputsTaskActionFactory extends AbstractIncrementalTaskActionFactory { + public IncrementalInputsTaskActionFactory(Class taskType, Method method) { + super(taskType, method); + } + + @Override + protected Action doCreate(Instantiator instantiator, Class taskType, Method method) { + return new IncrementalInputsTaskAction(taskType, method); + } + } + + private static class IncrementalTaskInputsTaskActionFactory extends AbstractIncrementalTaskActionFactory { + public IncrementalTaskInputsTaskActionFactory(Class taskType, Method method) { + super(taskType, method); + } + + @Override + protected Action doCreate(Instantiator instantiator, Class taskType, Method method) { + return new IncrementalTaskInputsTaskAction(instantiator, taskType, method); + } + } + + private static abstract class AbstractIncrementalTaskActionFactory implements TaskActionFactory { private final Class taskType; private final Method method; - public IncrementalTaskActionFactory(Class taskType, Method method) { + public AbstractIncrementalTaskActionFactory(Class taskType, Method method) { this.taskType = taskType; this.method = method; } + protected abstract Action doCreate(Instantiator instantiator, Class taskType, Method method); + @Override public Action create(Instantiator instantiator) { - return new IncrementalTaskAction(instantiator, taskType, method); + return doCreate(instantiator, taskType, method); } } } diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/project/taskfactory/IncrementalInputsTaskAction.java b/subprojects/core/src/main/java/org/gradle/api/internal/project/taskfactory/IncrementalInputsTaskAction.java new file mode 100644 index 0000000000000..8d3f25ccad00f --- /dev/null +++ b/subprojects/core/src/main/java/org/gradle/api/internal/project/taskfactory/IncrementalInputsTaskAction.java @@ -0,0 +1,113 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.api.internal.project.taskfactory; + +import com.google.common.collect.ImmutableSortedMap; +import org.gradle.api.Task; +import org.gradle.api.execution.incremental.IncrementalInputs; +import org.gradle.api.internal.tasks.properties.InputFilePropertySpec; +import org.gradle.api.tasks.incremental.InputFileDetails; +import org.gradle.internal.Cast; +import org.gradle.internal.change.CollectingChangeVisitor; +import org.gradle.internal.execution.history.changes.ExecutionStateChanges; +import org.gradle.internal.execution.history.changes.InputFileChanges; +import org.gradle.internal.fingerprint.CurrentFileCollectionFingerprint; +import org.gradle.internal.fingerprint.FileCollectionFingerprint; +import org.gradle.internal.reflect.JavaMethod; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.lang.reflect.Method; +import java.util.HashMap; +import java.util.Map; + +public class IncrementalInputsTaskAction extends AbstractIncrementalTaskAction { + private static final Logger LOGGER = LoggerFactory.getLogger(IncrementalInputsTaskAction.class); + + public IncrementalInputsTaskAction(Class type, Method method) { + super(type, method); + } + + protected void doExecute(final Task task, String methodName) { + final Map propertyNameByValue = new HashMap(); + for (InputFilePropertySpec inputFileProperty : getContext().getTaskProperties().getInputFileProperties()) { + Object value = inputFileProperty.getValue().call(); + if (value != null) { + propertyNameByValue.put(value, inputFileProperty.getPropertyName()); + } + } + + @SuppressWarnings("OptionalGetWithoutIsPresent") final ExecutionStateChanges changes = getContext().getExecutionStateChanges().get(); + IncrementalInputs incrementalTaskInputs = changes.visitInputFileChanges(new ExecutionStateChanges.IncrementalInputsVisitor() { + @Override + public IncrementalInputs visitRebuild(ImmutableSortedMap allFileInputs) { + return createRebuildInputs(task, allFileInputs, propertyNameByValue); + } + + @Override + public IncrementalInputs visitIncrementalChange(InputFileChanges inputFileChanges) { + return createIncrementalInputs(inputFileChanges, propertyNameByValue); + } + }); + + getContext().setTaskExecutedIncrementally(incrementalTaskInputs.isIncremental()); + JavaMethod.of(task, Object.class, methodName, IncrementalInputs.class).invoke(task, incrementalTaskInputs); + } + + private IncrementalInputs createIncrementalInputs(final InputFileChanges changes, final Map propertyNameByValue) { + return new IncrementalInputs() { + @Override + public boolean isIncremental() { + return true; + } + + @Override + public Iterable getChanges(Object property) { + String propertyName = determinePropertyName(property, propertyNameByValue); + CollectingChangeVisitor visitor = new CollectingChangeVisitor(); + changes.accept(propertyName, visitor); + return Cast.uncheckedNonnullCast(visitor.getChanges()); + } + }; + } + + private IncrementalInputs createRebuildInputs(Task task, final ImmutableSortedMap currentInputs, final Map propertyNameByValue) { + LOGGER.info("All input files are considered out-of-date for incremental {}.", task); + return new IncrementalInputs() { + @Override + public boolean isIncremental() { + return false; + } + + @Override + public Iterable getChanges(Object property) { + CollectingChangeVisitor visitor = new CollectingChangeVisitor(); + CurrentFileCollectionFingerprint currentFileCollectionFingerprint = currentInputs.get(determinePropertyName(property, propertyNameByValue)); + currentFileCollectionFingerprint.visitChangesSince(FileCollectionFingerprint.EMPTY, "Input", true, visitor); + return Cast.uncheckedNonnullCast(visitor.getChanges()); + } + }; + } + + private static String determinePropertyName(Object property, Map propertyNameByValue) { + String propertyName = propertyNameByValue.get(property); + if (propertyName == null) { + throw new UnsupportedOperationException("Cannot query incremental changes: No property found for " + property + "."); + } + return propertyName; + } +} diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/project/taskfactory/IncrementalTaskAction.java b/subprojects/core/src/main/java/org/gradle/api/internal/project/taskfactory/IncrementalTaskInputsTaskAction.java similarity index 75% rename from subprojects/core/src/main/java/org/gradle/api/internal/project/taskfactory/IncrementalTaskAction.java rename to subprojects/core/src/main/java/org/gradle/api/internal/project/taskfactory/IncrementalTaskInputsTaskAction.java index 79dcb3cb6c5fe..968ecbc4cc8d5 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/project/taskfactory/IncrementalTaskAction.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/project/taskfactory/IncrementalTaskInputsTaskAction.java @@ -20,39 +20,29 @@ import org.gradle.api.Task; import org.gradle.api.internal.changedetection.changes.ChangesOnlyIncrementalTaskInputs; import org.gradle.api.internal.changedetection.changes.RebuildIncrementalTaskInputs; -import org.gradle.api.internal.tasks.ContextAwareTaskAction; -import org.gradle.api.internal.tasks.TaskExecutionContext; import org.gradle.api.tasks.incremental.IncrementalTaskInputs; import org.gradle.internal.change.Change; +import org.gradle.internal.change.CollectingChangeVisitor; import org.gradle.internal.execution.history.changes.ExecutionStateChanges; +import org.gradle.internal.execution.history.changes.InputFileChanges; import org.gradle.internal.fingerprint.CurrentFileCollectionFingerprint; import org.gradle.internal.reflect.Instantiator; import org.gradle.internal.reflect.JavaMethod; import java.lang.reflect.Method; -class IncrementalTaskAction extends StandardTaskAction implements ContextAwareTaskAction { +class IncrementalTaskInputsTaskAction extends AbstractIncrementalTaskAction { private final Instantiator instantiator; - private TaskExecutionContext context; - public IncrementalTaskAction(Instantiator instantiator, Class type, Method method) { + public IncrementalTaskInputsTaskAction(Instantiator instantiator, Class type, Method method) { super(type, method); this.instantiator = instantiator; } - public void contextualise(TaskExecutionContext context) { - this.context = context; - } - - @Override - public void releaseContext() { - this.context = null; - } - protected void doExecute(final Task task, String methodName) { @SuppressWarnings("OptionalGetWithoutIsPresent") - ExecutionStateChanges changes = context.getExecutionStateChanges().get(); + ExecutionStateChanges changes = getContext().getExecutionStateChanges().get(); IncrementalTaskInputs incrementalTaskInputs = changes.visitInputFileChanges(new ExecutionStateChanges.IncrementalInputsVisitor() { @Override public IncrementalTaskInputs visitRebuild(ImmutableSortedMap allFileInputs) { @@ -60,17 +50,23 @@ public IncrementalTaskInputs visitRebuild(ImmutableSortedMap inputFileChanges) { + public IncrementalTaskInputs visitIncrementalChange(InputFileChanges inputFileChanges) { return createIncrementalInputs(inputFileChanges); } }); - context.setTaskExecutedIncrementally(incrementalTaskInputs.isIncremental()); + getContext().setTaskExecutedIncrementally(incrementalTaskInputs.isIncremental()); JavaMethod.of(task, Object.class, methodName, IncrementalTaskInputs.class).invoke(task, incrementalTaskInputs); } - private ChangesOnlyIncrementalTaskInputs createIncrementalInputs(Iterable inputFilesChanges) { - return instantiator.newInstance(ChangesOnlyIncrementalTaskInputs.class, inputFilesChanges); + private ChangesOnlyIncrementalTaskInputs createIncrementalInputs(InputFileChanges inputFilesChanges) { + return instantiator.newInstance(ChangesOnlyIncrementalTaskInputs.class, collectInputFileChanges(inputFilesChanges)); + } + + private Iterable collectInputFileChanges(InputFileChanges inputFileChanges) { + CollectingChangeVisitor visitor = new CollectingChangeVisitor(); + inputFileChanges.accept(visitor); + return visitor.getChanges(); } private RebuildIncrementalTaskInputs createRebuildInputs(Task task, ImmutableSortedMap currentInputs) { diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/DefaultInputFilePropertySpec.java b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/DefaultInputFilePropertySpec.java index 897b58ad3b1a2..27fd792ff16ae 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/DefaultInputFilePropertySpec.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/DefaultInputFilePropertySpec.java @@ -21,9 +21,11 @@ public class DefaultInputFilePropertySpec extends AbstractFilePropertySpec implements InputFilePropertySpec { private final boolean skipWhenEmpty; + private final PropertyValue value; - public DefaultInputFilePropertySpec(String propertyName, Class normalizer, FileCollection files, boolean skipWhenEmpty) { + public DefaultInputFilePropertySpec(String propertyName, Class normalizer, FileCollection files, PropertyValue value, boolean skipWhenEmpty) { super(propertyName, normalizer, files); + this.value = value; this.skipWhenEmpty = skipWhenEmpty; } @@ -31,4 +33,9 @@ public DefaultInputFilePropertySpec(String propertyName, Class T visitInputFileChanges(IncrementalInputsVisitor visitor) { return isRebuildRequired() ? - visitor.visitRebuild(thisExecution.getInputFileProperties()) : visitor.visitIncrementalChange(collectInputFileChanges()); + visitor.visitRebuild(thisExecution.getInputFileProperties()) : visitor.visitIncrementalChange(inputFileChanges); } private boolean isRebuildRequired() { @@ -125,11 +153,5 @@ private boolean isRebuildRequired() { rebuildTriggeringChanges.accept(changeDetectorVisitor); return changeDetectorVisitor.hasAnyChanges(); } - - private Iterable collectInputFileChanges() { - CollectingChangeVisitor visitor = new CollectingChangeVisitor(); - inputFileChanges.accept(visitor); - return visitor.getChanges(); - } } } diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/DefaultInputFileChanges.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/DefaultInputFileChanges.java new file mode 100644 index 0000000000000..77640b28a1d1a --- /dev/null +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/DefaultInputFileChanges.java @@ -0,0 +1,42 @@ +/* + * Copyright 2016 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.internal.execution.history.changes; + +import com.google.common.collect.ImmutableSortedMap; +import org.gradle.internal.change.ChangeVisitor; +import org.gradle.internal.fingerprint.CurrentFileCollectionFingerprint; +import org.gradle.internal.fingerprint.FileCollectionFingerprint; + +public class DefaultInputFileChanges extends AbstractFingerprintChanges implements InputFileChanges { + private static final String TITLE = "Input"; + + public DefaultInputFileChanges(ImmutableSortedMap previous, ImmutableSortedMap current) { + super(previous, current, TITLE); + } + + @Override + public boolean accept(ChangeVisitor visitor) { + return accept(visitor, true); + } + + @Override + public boolean accept(String propertyName, ChangeVisitor visitor) { + CurrentFileCollectionFingerprint currentFileCollectionFingerprint = current.get(propertyName); + FileCollectionFingerprint previousFileCollectionFingerprint = previous.get(propertyName); + return currentFileCollectionFingerprint.visitChangesSince(previousFileCollectionFingerprint, TITLE, true, visitor); + } +} diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/ExecutionStateChanges.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/ExecutionStateChanges.java index 193c6bb4fa18f..9c11fb53824f8 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/ExecutionStateChanges.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/ExecutionStateChanges.java @@ -17,7 +17,6 @@ package org.gradle.internal.execution.history.changes; import com.google.common.collect.ImmutableSortedMap; -import org.gradle.internal.change.Change; import org.gradle.internal.change.ChangeVisitor; import org.gradle.internal.fingerprint.CurrentFileCollectionFingerprint; @@ -36,6 +35,6 @@ public interface ExecutionStateChanges { interface IncrementalInputsVisitor { T visitRebuild(ImmutableSortedMap allFileInputs); - T visitIncrementalChange(Iterable inputFileChanges); + T visitIncrementalChange(InputFileChanges inputFileChanges); } } diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/InputFileChanges.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/InputFileChanges.java index 5fbe400376724..c8d3c291e8e96 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/InputFileChanges.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/InputFileChanges.java @@ -1,5 +1,5 @@ /* - * Copyright 2016 the original author or authors. + * Copyright 2019 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,19 +16,9 @@ package org.gradle.internal.execution.history.changes; -import com.google.common.collect.ImmutableSortedMap; +import org.gradle.internal.change.ChangeContainer; import org.gradle.internal.change.ChangeVisitor; -import org.gradle.internal.fingerprint.CurrentFileCollectionFingerprint; -import org.gradle.internal.fingerprint.FileCollectionFingerprint; -public class InputFileChanges extends AbstractFingerprintChanges { - - public InputFileChanges(ImmutableSortedMap previous, ImmutableSortedMap current) { - super(previous, current, "Input"); - } - - @Override - public boolean accept(ChangeVisitor visitor) { - return accept(visitor, true); - } +public interface InputFileChanges extends ChangeContainer { + boolean accept(String propertyName, ChangeVisitor visitor); } diff --git a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/ResolveChangesStepTest.groovy b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/ResolveChangesStepTest.groovy index d1f065fcc919e..17486b82bce22 100644 --- a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/ResolveChangesStepTest.groovy +++ b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/ResolveChangesStepTest.groovy @@ -17,7 +17,6 @@ package org.gradle.internal.execution.steps import com.google.common.collect.ImmutableSortedMap -import org.gradle.internal.change.Change import org.gradle.internal.execution.IncrementalChangesContext import org.gradle.internal.execution.IncrementalContext import org.gradle.internal.execution.Result @@ -25,6 +24,7 @@ import org.gradle.internal.execution.history.AfterPreviousExecutionState import org.gradle.internal.execution.history.BeforeExecutionState import org.gradle.internal.execution.history.changes.ExecutionStateChangeDetector import org.gradle.internal.execution.history.changes.ExecutionStateChanges +import org.gradle.internal.execution.history.changes.InputFileChanges import org.gradle.internal.fingerprint.CurrentFileCollectionFingerprint class ResolveChangesStepTest extends StepSpec { @@ -128,7 +128,7 @@ class ResolveChangesStepTest extends StepSpec { } @Override - Boolean visitIncrementalChange(Iterable inputFileChanges) { + Boolean visitIncrementalChange(InputFileChanges inputFileChanges) { return true } }) From 8fbca4a435b0781ed79dcb6416074268760e9993 Mon Sep 17 00:00:00 2001 From: Paul Merlin Date: Tue, 12 Mar 2019 12:06:27 +0100 Subject: [PATCH 489/853] Prefer abstract task properties where applicable Signed-off-by: Paul Merlin --- .../src/main/kotlin/build/PatchKotlinCompilerEmbeddable.kt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/buildSrc/subprojects/kotlin-dsl/src/main/kotlin/build/PatchKotlinCompilerEmbeddable.kt b/buildSrc/subprojects/kotlin-dsl/src/main/kotlin/build/PatchKotlinCompilerEmbeddable.kt index 5bf07a33709f7..b73f9cf2ffa20 100644 --- a/buildSrc/subprojects/kotlin-dsl/src/main/kotlin/build/PatchKotlinCompilerEmbeddable.kt +++ b/buildSrc/subprojects/kotlin-dsl/src/main/kotlin/build/PatchKotlinCompilerEmbeddable.kt @@ -20,6 +20,7 @@ import org.gradle.api.DefaultTask import org.gradle.api.file.ConfigurableFileCollection import org.gradle.api.file.RegularFileProperty import org.gradle.api.file.RelativePath +import org.gradle.api.provider.ListProperty import org.gradle.api.specs.Spec import org.gradle.api.specs.Specs import org.gradle.api.tasks.CacheableTask @@ -46,8 +47,8 @@ import org.gradle.kotlin.dsl.* @Suppress("unused") abstract class PatchKotlinCompilerEmbeddable : DefaultTask() { - @Input - val excludes = project.objects.listProperty() + @get:Input + abstract val excludes: ListProperty @get:Classpath abstract val originalFiles: ConfigurableFileCollection From b1c8e27650340c4a2e5b02c15b413956c930c9ab Mon Sep 17 00:00:00 2001 From: Stefan Wolf Date: Tue, 12 Mar 2019 13:12:25 +0100 Subject: [PATCH 490/853] Support incremental transforms --- .../IncrementalInputsTaskAction.java | 54 ++--------------- .../transform/DefaultTransformer.java | 21 +++++-- .../transform/DefaultTransformerInvoker.java | 34 ++++++++++- .../transform/LegacyTransformer.java | 9 ++- .../artifacts/transform/Transformer.java | 9 ++- .../DefaultTransformerInvokerTest.groovy | 8 ++- .../impl/DefaultIncrementalInputs.java | 57 ++++++++++++++++++ .../impl/RebuildIncrementalInputs.java | 58 +++++++++++++++++++ 8 files changed, 190 insertions(+), 60 deletions(-) create mode 100644 subprojects/execution/src/main/java/org/gradle/internal/execution/history/impl/DefaultIncrementalInputs.java create mode 100644 subprojects/execution/src/main/java/org/gradle/internal/execution/history/impl/RebuildIncrementalInputs.java diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/project/taskfactory/IncrementalInputsTaskAction.java b/subprojects/core/src/main/java/org/gradle/api/internal/project/taskfactory/IncrementalInputsTaskAction.java index 8d3f25ccad00f..9e50ca2ac32da 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/project/taskfactory/IncrementalInputsTaskAction.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/project/taskfactory/IncrementalInputsTaskAction.java @@ -20,13 +20,12 @@ import org.gradle.api.Task; import org.gradle.api.execution.incremental.IncrementalInputs; import org.gradle.api.internal.tasks.properties.InputFilePropertySpec; -import org.gradle.api.tasks.incremental.InputFileDetails; -import org.gradle.internal.Cast; -import org.gradle.internal.change.CollectingChangeVisitor; +import org.gradle.internal.Describables; import org.gradle.internal.execution.history.changes.ExecutionStateChanges; import org.gradle.internal.execution.history.changes.InputFileChanges; +import org.gradle.internal.execution.history.impl.DefaultIncrementalInputs; +import org.gradle.internal.execution.history.impl.RebuildIncrementalInputs; import org.gradle.internal.fingerprint.CurrentFileCollectionFingerprint; -import org.gradle.internal.fingerprint.FileCollectionFingerprint; import org.gradle.internal.reflect.JavaMethod; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -55,59 +54,16 @@ protected void doExecute(final Task task, String methodName) { IncrementalInputs incrementalTaskInputs = changes.visitInputFileChanges(new ExecutionStateChanges.IncrementalInputsVisitor() { @Override public IncrementalInputs visitRebuild(ImmutableSortedMap allFileInputs) { - return createRebuildInputs(task, allFileInputs, propertyNameByValue); + return new RebuildIncrementalInputs(allFileInputs, propertyNameByValue, Describables.of(task)); } @Override public IncrementalInputs visitIncrementalChange(InputFileChanges inputFileChanges) { - return createIncrementalInputs(inputFileChanges, propertyNameByValue); + return new DefaultIncrementalInputs(inputFileChanges, propertyNameByValue); } }); getContext().setTaskExecutedIncrementally(incrementalTaskInputs.isIncremental()); JavaMethod.of(task, Object.class, methodName, IncrementalInputs.class).invoke(task, incrementalTaskInputs); } - - private IncrementalInputs createIncrementalInputs(final InputFileChanges changes, final Map propertyNameByValue) { - return new IncrementalInputs() { - @Override - public boolean isIncremental() { - return true; - } - - @Override - public Iterable getChanges(Object property) { - String propertyName = determinePropertyName(property, propertyNameByValue); - CollectingChangeVisitor visitor = new CollectingChangeVisitor(); - changes.accept(propertyName, visitor); - return Cast.uncheckedNonnullCast(visitor.getChanges()); - } - }; - } - - private IncrementalInputs createRebuildInputs(Task task, final ImmutableSortedMap currentInputs, final Map propertyNameByValue) { - LOGGER.info("All input files are considered out-of-date for incremental {}.", task); - return new IncrementalInputs() { - @Override - public boolean isIncremental() { - return false; - } - - @Override - public Iterable getChanges(Object property) { - CollectingChangeVisitor visitor = new CollectingChangeVisitor(); - CurrentFileCollectionFingerprint currentFileCollectionFingerprint = currentInputs.get(determinePropertyName(property, propertyNameByValue)); - currentFileCollectionFingerprint.visitChangesSince(FileCollectionFingerprint.EMPTY, "Input", true, visitor); - return Cast.uncheckedNonnullCast(visitor.getChanges()); - } - }; - } - - private static String determinePropertyName(Object property, Map propertyNameByValue) { - String propertyName = propertyNameByValue.get(property); - if (propertyName == null) { - throw new UnsupportedOperationException("Cannot query incremental changes: No property found for " + property + "."); - } - return propertyName; - } } diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformer.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformer.java index 13c3cfe0b2ec8..b557cbae248a8 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformer.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformer.java @@ -25,6 +25,7 @@ import org.gradle.api.artifacts.transform.TransformAction; import org.gradle.api.artifacts.transform.TransformParameters; import org.gradle.api.artifacts.transform.VariantTransformConfigurationException; +import org.gradle.api.execution.incremental.IncrementalInputs; import org.gradle.api.file.FileCollection; import org.gradle.api.internal.attributes.ImmutableAttributes; import org.gradle.api.internal.file.FileCollectionFactory; @@ -86,6 +87,7 @@ public class DefaultTransformer extends AbstractTransformer { private final boolean cacheable; private IsolatedParameters isolatedParameters; + private final boolean incremental; public DefaultTransformer( Class implementationClass, @@ -112,6 +114,7 @@ public DefaultTransformer( this.parameterPropertyWalker = parameterPropertyWalker; this.instanceFactory = actionInstantiationScheme.forType(implementationClass); this.requiresDependencies = instanceFactory.serviceInjectionTriggeredByAnnotation(InputArtifactDependencies.class); + this.incremental = instanceFactory.requiresService(IncrementalInputs.class); this.cacheable = cacheable; } @@ -145,6 +148,11 @@ public boolean requiresDependencies() { return requiresDependencies; } + @Override + public boolean isIncremental() { + return incremental; + } + @Override public boolean isCacheable() { return cacheable; @@ -156,8 +164,8 @@ public HashCode getSecondaryInputHash() { } @Override - public ImmutableList transform(File inputArtifact, File outputDir, ArtifactTransformDependencies dependencies) { - TransformAction transformAction = newTransformAction(inputArtifact, dependencies); + public ImmutableList transform(File inputArtifact, File outputDir, ArtifactTransformDependencies dependencies, @Nullable IncrementalInputs incrementalInputs) { + TransformAction transformAction = newTransformAction(inputArtifact, dependencies, incrementalInputs); DefaultTransformOutputs transformOutputs = new DefaultTransformOutputs(inputArtifact, outputDir); transformAction.transform(transformOutputs); return transformOutputs.getRegisteredOutputs(); @@ -270,8 +278,8 @@ private static String getParameterObjectDisplayName(Object parameterObject) { return ModelType.of(new DslObject(parameterObject).getDeclaredType()).getDisplayName(); } - private TransformAction newTransformAction(File inputFile, ArtifactTransformDependencies artifactTransformDependencies) { - ServiceLookup services = new TransformServiceLookup(inputFile, getIsolatedParameters().getIsolatedParameterObject().isolate(), requiresDependencies ? artifactTransformDependencies : null); + private TransformAction newTransformAction(File inputFile, ArtifactTransformDependencies artifactTransformDependencies, @Nullable IncrementalInputs incrementalInputs) { + ServiceLookup services = new TransformServiceLookup(inputFile, getIsolatedParameters().getIsolatedParameterObject().isolate(), requiresDependencies ? artifactTransformDependencies : null, incrementalInputs); return instanceFactory.newInstance(services); } @@ -285,7 +293,7 @@ private IsolatedParameters getIsolatedParameters() { private static class TransformServiceLookup implements ServiceLookup { private final ImmutableList injectionPoints; - public TransformServiceLookup(File inputFile, @Nullable TransformParameters parameters, @Nullable ArtifactTransformDependencies artifactTransformDependencies) { + public TransformServiceLookup(File inputFile, @Nullable TransformParameters parameters, @Nullable ArtifactTransformDependencies artifactTransformDependencies, @Nullable IncrementalInputs incrementalInputs) { ImmutableList.Builder builder = ImmutableList.builder(); builder.add(InjectionPoint.injectedByAnnotation(InputArtifact.class, () -> inputFile)); if (parameters != null) { @@ -298,6 +306,9 @@ public TransformServiceLookup(File inputFile, @Nullable TransformParameters para if (artifactTransformDependencies != null) { builder.add(InjectionPoint.injectedByAnnotation(InputArtifactDependencies.class, () -> artifactTransformDependencies.getFiles())); } + if (incrementalInputs != null) { + builder.add(InjectionPoint.injectedByType(IncrementalInputs.class, () -> incrementalInputs)); + } this.injectionPoints = builder.build(); } diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvoker.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvoker.java index e87ba02e1454a..124a2aeb8cd70 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvoker.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvoker.java @@ -17,9 +17,11 @@ package org.gradle.api.internal.artifacts.transform; import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSortedMap; import org.gradle.api.UncheckedIOException; import org.gradle.api.artifacts.component.ProjectComponentIdentifier; +import org.gradle.api.execution.incremental.IncrementalInputs; import org.gradle.api.file.RelativePath; import org.gradle.api.internal.artifacts.dsl.dependencies.ProjectFinder; import org.gradle.api.internal.artifacts.transform.TransformationWorkspaceProvider.TransformationWorkspace; @@ -39,7 +41,11 @@ import org.gradle.internal.execution.history.AfterPreviousExecutionState; import org.gradle.internal.execution.history.BeforeExecutionState; import org.gradle.internal.execution.history.ExecutionHistoryStore; +import org.gradle.internal.execution.history.changes.ExecutionStateChanges; +import org.gradle.internal.execution.history.changes.InputFileChanges; import org.gradle.internal.execution.history.impl.DefaultBeforeExecutionState; +import org.gradle.internal.execution.history.impl.DefaultIncrementalInputs; +import org.gradle.internal.execution.history.impl.RebuildIncrementalInputs; import org.gradle.internal.file.TreeType; import org.gradle.internal.fingerprint.CurrentFileCollectionFingerprint; import org.gradle.internal.fingerprint.FileCollectionFingerprinter; @@ -262,13 +268,35 @@ public TransformerExecution( public ExecutionOutcome execute(IncrementalChangesContext context) { File outputDir = workspace.getOutputDirectory(); File resultsFile = workspace.getResultsFile(); - GFileUtils.cleanDirectory(outputDir); - GFileUtils.deleteFileQuietly(resultsFile); - ImmutableList result = transformer.transform(inputArtifact, outputDir, dependencies); + + IncrementalInputs incrementalInputs = transformer.isIncremental() ? createIncrementalInputs(context) : null; + + if (incrementalInputs == null || !incrementalInputs.isIncremental()) { + GFileUtils.cleanDirectory(outputDir); + GFileUtils.deleteFileQuietly(resultsFile); + } + ImmutableList result = transformer.transform(inputArtifact, outputDir, dependencies, incrementalInputs); writeResultsFile(outputDir, resultsFile, result); return ExecutionOutcome.EXECUTED_NON_INCREMENTALLY; } + private IncrementalInputs createIncrementalInputs(IncrementalChangesContext context) { + @SuppressWarnings("OptionalGetWithoutIsPresent") + ExecutionStateChanges executionStateChanges = context.getChanges().get(); + ImmutableMap propertyNameByValue = ImmutableMap.of(inputArtifact, INPUT_ARTIFACT_PROPERTY_NAME); + return executionStateChanges.visitInputFileChanges(new ExecutionStateChanges.IncrementalInputsVisitor() { + @Override + public IncrementalInputs visitRebuild(ImmutableSortedMap allFileInputs) { + return new RebuildIncrementalInputs(allFileInputs, propertyNameByValue, TransformerExecution.this); + } + + @Override + public IncrementalInputs visitIncrementalChange(InputFileChanges inputFileChanges) { + return new DefaultIncrementalInputs(inputFileChanges, propertyNameByValue); + } + }); + } + private void writeResultsFile(File outputDir, File resultsFile, ImmutableList result) { String outputDirPrefix = outputDir.getPath() + File.separator; String inputFilePrefix = inputArtifact.getPath() + File.separator; diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/LegacyTransformer.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/LegacyTransformer.java index 8e0abe1ff88ca..3d7bb74131d50 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/LegacyTransformer.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/LegacyTransformer.java @@ -19,6 +19,7 @@ import com.google.common.collect.ImmutableList; import org.gradle.api.InvalidUserDataException; import org.gradle.api.artifacts.transform.ArtifactTransform; +import org.gradle.api.execution.incremental.IncrementalInputs; import org.gradle.api.internal.attributes.ImmutableAttributes; import org.gradle.api.internal.tasks.TaskDependencyResolveContext; import org.gradle.api.tasks.FileNormalizer; @@ -33,6 +34,7 @@ import org.gradle.internal.isolation.IsolatableFactory; import org.gradle.internal.reflect.Instantiator; +import javax.annotation.Nullable; import java.io.File; import java.util.List; @@ -53,13 +55,18 @@ public boolean requiresDependencies() { return false; } + @Override + public boolean isIncremental() { + return false; + } + @Override public boolean isCacheable() { return false; } @Override - public ImmutableList transform(File inputArtifact, File outputDir, ArtifactTransformDependencies dependencies) { + public ImmutableList transform(File inputArtifact, File outputDir, ArtifactTransformDependencies dependencies, @Nullable IncrementalInputs incrementalInputs) { ArtifactTransform transformer = newTransformer(); transformer.setOutputDirectory(outputDir); List outputs = transformer.transform(inputArtifact); diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/Transformer.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/Transformer.java index 5781ae7fe34fe..c0d909cb9831c 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/Transformer.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/Transformer.java @@ -19,12 +19,14 @@ import com.google.common.collect.ImmutableList; import org.gradle.api.Describable; import org.gradle.api.artifacts.transform.ArtifactTransform; +import org.gradle.api.execution.incremental.IncrementalInputs; import org.gradle.api.internal.attributes.ImmutableAttributes; import org.gradle.api.internal.tasks.TaskDependencyContainer; import org.gradle.api.tasks.FileNormalizer; import org.gradle.internal.fingerprint.FileCollectionFingerprinterRegistry; import org.gradle.internal.hash.HashCode; +import javax.annotation.Nullable; import java.io.File; /** @@ -42,12 +44,17 @@ public interface Transformer extends Describable, TaskDependencyContainer { */ boolean requiresDependencies(); + /** + * Whether the transformer supports incremental execution. + */ + boolean isIncremental(); + /** * Whether the transformer is cacheable. */ boolean isCacheable(); - ImmutableList transform(File inputArtifact, File outputDir, ArtifactTransformDependencies dependencies); + ImmutableList transform(File inputArtifact, File outputDir, ArtifactTransformDependencies dependencies, @Nullable IncrementalInputs incrementalInputs); /** * The hash of the secondary inputs of the transformer. diff --git a/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvokerTest.groovy b/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvokerTest.groovy index e99a9fd57f066..4a1fa06c01812 100644 --- a/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvokerTest.groovy +++ b/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvokerTest.groovy @@ -18,6 +18,7 @@ package org.gradle.api.internal.artifacts.transform import com.google.common.collect.ImmutableList import org.gradle.api.artifacts.transform.ArtifactTransform +import org.gradle.api.execution.incremental.IncrementalInputs import org.gradle.api.internal.artifacts.DefaultBuildIdentifier import org.gradle.api.internal.artifacts.DefaultProjectComponentIdentifier import org.gradle.api.internal.artifacts.dsl.dependencies.ProjectFinder @@ -125,13 +126,18 @@ class DefaultTransformerInvokerTest extends AbstractProjectBuilderSpec { return false } + @Override + boolean isIncremental() { + return false + } + @Override boolean isCacheable() { return false } @Override - ImmutableList transform(File inputArtifact, File outputDir, ArtifactTransformDependencies dependencies) { + ImmutableList transform(File inputArtifact, File outputDir, ArtifactTransformDependencies dependencies, IncrementalInputs incrementalInputs) { return ImmutableList.copyOf(transformationAction.apply(inputArtifact, outputDir)) } diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/impl/DefaultIncrementalInputs.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/impl/DefaultIncrementalInputs.java new file mode 100644 index 0000000000000..6085a57efcb6b --- /dev/null +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/impl/DefaultIncrementalInputs.java @@ -0,0 +1,57 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.internal.execution.history.impl; + +import org.gradle.api.execution.incremental.IncrementalInputs; +import org.gradle.api.tasks.incremental.InputFileDetails; +import org.gradle.internal.Cast; +import org.gradle.internal.change.CollectingChangeVisitor; +import org.gradle.internal.execution.history.changes.InputFileChanges; + +import java.util.Map; + +public class DefaultIncrementalInputs implements IncrementalInputs { + + private final InputFileChanges changes; + private final Map propertyNameByValue; + + public DefaultIncrementalInputs(InputFileChanges changes, Map propertyNameByValue) { + this.changes = changes; + this.propertyNameByValue = propertyNameByValue; + } + + @Override + public boolean isIncremental() { + return true; + } + + @Override + public Iterable getChanges(Object property) { + String propertyName = determinePropertyName(property, propertyNameByValue); + CollectingChangeVisitor visitor = new CollectingChangeVisitor(); + changes.accept(propertyName, visitor); + return Cast.uncheckedNonnullCast(visitor.getChanges()); + } + + public static String determinePropertyName(Object property, Map propertyNameByValue) { + String propertyName = propertyNameByValue.get(property); + if (propertyName == null) { + throw new UnsupportedOperationException("Cannot query incremental changes: No property found for " + property + "."); + } + return propertyName; + } +} diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/impl/RebuildIncrementalInputs.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/impl/RebuildIncrementalInputs.java new file mode 100644 index 0000000000000..496896fcaf97a --- /dev/null +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/impl/RebuildIncrementalInputs.java @@ -0,0 +1,58 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.internal.execution.history.impl; + +import com.google.common.collect.ImmutableSortedMap; +import org.gradle.api.Describable; +import org.gradle.api.execution.incremental.IncrementalInputs; +import org.gradle.api.tasks.incremental.InputFileDetails; +import org.gradle.internal.Cast; +import org.gradle.internal.change.CollectingChangeVisitor; +import org.gradle.internal.fingerprint.CurrentFileCollectionFingerprint; +import org.gradle.internal.fingerprint.FileCollectionFingerprint; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Map; + +import static org.gradle.internal.execution.history.impl.DefaultIncrementalInputs.determinePropertyName; + +public class RebuildIncrementalInputs implements IncrementalInputs { + private static final Logger LOGGER = LoggerFactory.getLogger(RebuildIncrementalInputs.class); + + private final ImmutableSortedMap currentInputs; + private final Map propertyNameByValue; + + public RebuildIncrementalInputs(ImmutableSortedMap currentInputs, Map propertyNameByValue, Describable owner) { + this.currentInputs = currentInputs; + this.propertyNameByValue = propertyNameByValue; + LOGGER.info("All input files are considered out-of-date for incremental {}.", owner.getDisplayName()); + } + + @Override + public boolean isIncremental() { + return false; + } + + @Override + public Iterable getChanges(Object property) { + CollectingChangeVisitor visitor = new CollectingChangeVisitor(); + CurrentFileCollectionFingerprint currentFileCollectionFingerprint = currentInputs.get(determinePropertyName(property, propertyNameByValue)); + currentFileCollectionFingerprint.visitChangesSince(FileCollectionFingerprint.EMPTY, "Input", true, visitor); + return Cast.uncheckedNonnullCast(visitor.getChanges()); + } +} From a8080f5bc0bf5e471ad6390c656200b76626c7e0 Mon Sep 17 00:00:00 2001 From: Stefan Wolf Date: Tue, 12 Mar 2019 14:15:20 +0100 Subject: [PATCH 491/853] Upgradle to latest RC wrapper --- gradle/wrapper/gradle-wrapper.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 26ec2316bf4a1..a257a1753dd88 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions-snapshots/gradle-5.4-20190311000052+0000-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-5.3-rc-2-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists From 1b8a8b119f66a813276ab87772f4b2fe30ac220d Mon Sep 17 00:00:00 2001 From: Stefan Wolf Date: Tue, 12 Mar 2019 17:25:00 +0100 Subject: [PATCH 492/853] Add more test coverage --- ...TransformIncrementalIntegrationTest.groovy | 136 +++++++++++++++--- .../ArtifactTransformTestFixture.groovy | 3 + 2 files changed, 121 insertions(+), 18 deletions(-) diff --git a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformIncrementalIntegrationTest.groovy b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformIncrementalIntegrationTest.groovy index a953985a85ff6..3b8a8cfce6821 100644 --- a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformIncrementalIntegrationTest.groovy +++ b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformIncrementalIntegrationTest.groovy @@ -22,20 +22,33 @@ class ArtifactTransformIncrementalIntegrationTest extends AbstractDependencyReso def "can query incremental changes"() { settingsFile << """ - include 'a', 'b', 'c' + include 'a', 'b' """ - setupBuildWithColorTransform { - produceDirs() - } - buildFile << """ - project(':a') { - dependencies { - implementation project(':b') - implementation project(':c') + + file("buildSrc/src/main/groovy/MakeGreen.groovy") << """ + import java.io.File + import javax.inject.Inject + import groovy.transform.CompileStatic + import org.gradle.api.provider.* + import org.gradle.api.tasks.* + import org.gradle.api.tasks.incremental.* + import org.gradle.api.artifacts.transform.* + import org.gradle.api.execution.incremental.* + + abstract class MakeGreen implements TransformAction { + + interface Parameters extends TransformParameters { + @Internal + ListProperty getAddedFiles() + @Internal + ListProperty getModifiedFiles() + @Internal + ListProperty getRemovedFiles() + @Internal + Property getIncrementalExecution() + @Internal + Property getRegisterNewOutput() } - } - - abstract class MakeGreen implements TransformAction { @Inject abstract IncrementalInputs getIncrementalInputs() @@ -44,22 +57,109 @@ class ArtifactTransformIncrementalIntegrationTest extends AbstractDependencyReso abstract File getInput() void transform(TransformOutputs outputs) { + println "Transforming " + input.name println "incremental: " + incrementalInputs.incremental - println "changes: \\n" + incrementalInputs.getChanges(input).join("\\n") + assert parameters.incrementalExecution.get() == incrementalInputs.incremental + def changes = incrementalInputs.getChanges(input) + println "changes: \\n" + changes.join("\\n") + assert changes.findAll { it.added }*.file as Set == resolveFiles(parameters.addedFiles.get()) + assert changes.findAll { it.removed }*.file as Set == resolveFiles(parameters.removedFiles.get()) + assert changes.findAll { it.modified }*.file as Set == resolveFiles(parameters.modifiedFiles.get()) + def outputDirectory = outputs.dir("output") + changes.each { change -> + if (change.file != input) { + File outputFile = new File(outputDirectory, change.file.name) + if (change.added || change.modified) { + outputFile.text = change.file.text + } else { + outputFile.delete() + } + } + } + } + + private resolveFiles(List files) { + files.collect { new File(input, it) } as Set } } """ + setupBuildFile() + when: - run(":a:resolve") + previousExecution() + executer.withArguments("-PbContent=changed") then: - outputContains("incremental: false") + executesIncrementally("ext.modified=['b']") when: - executer.withArguments("-PbContent=changed") - run(":a:resolve") + executer.withArguments('-PbNames=first,second,third') then: - outputContains("incremental: true") + executesIncrementally(""" + ext.removed = ['b'] + ext.added = ['first', 'second', 'third'] + """) + + when: + executer.withArguments("-PbNames=first,second", "-PbContent=different") + then: + executesIncrementally(""" + ext.removed = ['third'] + ext.modified = ['first', 'second'] + """) } + private void setupBuildFile() { + buildFile .text = """ + ext { + added = [] + modified = [] + removed = [] + incremental = true + registerNewOutput = false + } + """ + setupBuildWithColorTransform { + produceDirs() + params(""" + addedFiles.set(provider { added }) + modifiedFiles.set(provider { modified }) + removedFiles.set(provider { removed }) + incrementalExecution.set(provider { incremental }) + incrementalExecution.set(provider { incremental }) + registerNewOutput.set(provider { project.registerNewOutput }) + """) + } + buildFile << """ + project(':a') { + dependencies { + implementation project(':b') + } + } + """ + } + + void executesNonIncrementally(String fileChanges = "ext.added = ['', 'b']") { + setupBuildFile() + buildFile << """ + ext.incremental = false + $fileChanges + """ + succeeds ":a:resolve" + outputContains("Transforming") + } + + void executesIncrementally(String fileChanges) { + setupBuildFile() + buildFile << """ + ext.incremental = true + $fileChanges + """ + succeeds ":a:resolve" + outputContains("Transforming") + } + + void previousExecution() { + executesNonIncrementally() + } } diff --git a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformTestFixture.groovy b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformTestFixture.groovy index 2f646d735afc0..7bc3dc5a838c2 100644 --- a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformTestFixture.groovy +++ b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformTestFixture.groovy @@ -299,6 +299,9 @@ allprojects { p -> if (project.hasProperty("\${project.name}Name")) { names = [project.property("\${project.name}Name")] } + if (project.hasProperty("\${project.name}Names")) { + names.set(project.property("\${project.name}Names").split(',') as List) + } if (project.hasProperty("\${project.name}DirName")) { output = layout.buildDir.dir(project.property("\${project.name}DirName")) } From b654b8e89891152a9b288acf5f598bb64c6b4165 Mon Sep 17 00:00:00 2001 From: "Rodrigo B. de Oliveira" Date: Tue, 12 Mar 2019 14:46:10 -0300 Subject: [PATCH 493/853] Polish `GenerateKotlinDependencyExtensions` - Make all task inputs `Property` - Let Gradle provide the properties --- .../codegen/GenerateKotlinDependencyExtensions.kt | 12 ++++++++---- subprojects/kotlin-dsl/kotlin-dsl.gradle.kts | 4 ++-- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/buildSrc/subprojects/kotlin-dsl/src/main/kotlin/codegen/GenerateKotlinDependencyExtensions.kt b/buildSrc/subprojects/kotlin-dsl/src/main/kotlin/codegen/GenerateKotlinDependencyExtensions.kt index f9e79e5d1c2cc..4921d821a8627 100644 --- a/buildSrc/subprojects/kotlin-dsl/src/main/kotlin/codegen/GenerateKotlinDependencyExtensions.kt +++ b/buildSrc/subprojects/kotlin-dsl/src/main/kotlin/codegen/GenerateKotlinDependencyExtensions.kt @@ -17,6 +17,8 @@ package codegen import org.gradle.api.DefaultTask +import org.gradle.api.file.RegularFileProperty +import org.gradle.api.provider.Property import org.gradle.api.tasks.Input import org.gradle.api.tasks.OutputFile @@ -24,20 +26,22 @@ import org.gradle.api.tasks.TaskAction @Suppress("unused") -open class GenerateKotlinDependencyExtensions : DefaultTask() { +abstract class GenerateKotlinDependencyExtensions : DefaultTask() { @get:OutputFile - val outputFile = project.objects.fileProperty() + abstract val outputFile: RegularFileProperty @get:Input - var embeddedKotlinVersion: String? = null + abstract val embeddedKotlinVersion: Property @get:Input - var kotlinDslPluginsVersion: String? = null + abstract val kotlinDslPluginsVersion: Property @Suppress("unused") @TaskAction fun generate() { + val kotlinDslPluginsVersion = this.kotlinDslPluginsVersion.get() + val embeddedKotlinVersion = this.embeddedKotlinVersion.get() outputFile.get().asFile.writeText( """$licenseHeader diff --git a/subprojects/kotlin-dsl/kotlin-dsl.gradle.kts b/subprojects/kotlin-dsl/kotlin-dsl.gradle.kts index 9d281cf33c9a1..d31958b0a47ed 100644 --- a/subprojects/kotlin-dsl/kotlin-dsl.gradle.kts +++ b/subprojects/kotlin-dsl/kotlin-dsl.gradle.kts @@ -83,8 +83,8 @@ tasks { val generateKotlinDependencyExtensions by registering(GenerateKotlinDependencyExtensions::class) { outputFile.set(apiExtensionsOutputDir.get().file("org/gradle/kotlin/dsl/KotlinDependencyExtensions.kt")) - embeddedKotlinVersion = kotlinVersion - kotlinDslPluginsVersion = publishedKotlinDslPluginVersion + embeddedKotlinVersion.set(kotlinVersion) + kotlinDslPluginsVersion.set(publishedKotlinDslPluginVersion) } val generateExtensions by registering { From 648979e3252cb63108cc6881ace5f97d56bb51ef Mon Sep 17 00:00:00 2001 From: "Rodrigo B. de Oliveira" Date: Tue, 12 Mar 2019 15:45:35 -0300 Subject: [PATCH 494/853] Remove unnecessary backticks --- .../main/kotlin/gradlebuild/publish-public-libraries.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/buildSrc/subprojects/plugins/src/main/kotlin/gradlebuild/publish-public-libraries.gradle.kts b/buildSrc/subprojects/plugins/src/main/kotlin/gradlebuild/publish-public-libraries.gradle.kts index d037e0ade76c3..ba353b1725d4b 100644 --- a/buildSrc/subprojects/plugins/src/main/kotlin/gradlebuild/publish-public-libraries.gradle.kts +++ b/buildSrc/subprojects/plugins/src/main/kotlin/gradlebuild/publish-public-libraries.gradle.kts @@ -27,7 +27,7 @@ import org.gradle.plugins.publish.createArtifactPattern import java.util.* plugins { - `maven` + maven } val generatePom = tasks.register("generatePom", GeneratePom::class.java) From d9fc7c0ab34d8e108009bc745d0061ec2c5504d6 Mon Sep 17 00:00:00 2001 From: Stefan Wolf Date: Tue, 12 Mar 2019 21:00:26 +0100 Subject: [PATCH 495/853] Create InputChanges in the execution engine --- .../changes/RebuildIncrementalTaskInputs.java | 22 ++++------- .../IncrementalInputsTaskAction.java | 34 +++-------------- .../IncrementalTaskInputsTaskAction.java | 38 +++++++------------ .../execution/ExecuteActionsTaskExecuter.java | 16 ++++++++ .../transform/DefaultTransformerInvoker.java | 36 ++++++------------ ...IncrementalExecutionIntegrationTest.groovy | 12 ++++++ .../gradle/internal/execution/UnitOfWork.java | 3 ++ .../DefaultExecutionStateChangeDetector.java | 38 ++++++++++++------- .../changes/ExecutionStateChangeDetector.java | 4 +- .../changes/ExecutionStateChanges.java | 10 +---- .../history/changes/InputChangesInternal.java | 24 ++++++++++++ ...puts.java => IncrementalInputChanges.java} | 14 +++++-- ...s.java => NonIncrementalInputChanges.java} | 26 ++++++++++--- .../execution/steps/ResolveChangesStep.java | 19 +++++----- .../execution/steps/ExecuteStepTest.groovy | 11 ++++-- .../steps/ResolveChangesStepTest.groovy | 25 +++--------- 16 files changed, 175 insertions(+), 157 deletions(-) create mode 100644 subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/InputChangesInternal.java rename subprojects/execution/src/main/java/org/gradle/internal/execution/history/impl/{DefaultIncrementalInputs.java => IncrementalInputChanges.java} (79%) rename subprojects/execution/src/main/java/org/gradle/internal/execution/history/impl/{RebuildIncrementalInputs.java => NonIncrementalInputChanges.java} (66%) diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/changedetection/changes/RebuildIncrementalTaskInputs.java b/subprojects/core/src/main/java/org/gradle/api/internal/changedetection/changes/RebuildIncrementalTaskInputs.java index faf56ad06835f..a682b76e2a9ef 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/changedetection/changes/RebuildIncrementalTaskInputs.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/changedetection/changes/RebuildIncrementalTaskInputs.java @@ -17,22 +17,17 @@ package org.gradle.api.internal.changedetection.changes; import org.gradle.api.Action; -import org.gradle.api.Task; import org.gradle.api.tasks.incremental.InputFileDetails; -import org.gradle.internal.fingerprint.FileCollectionFingerprint; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import org.gradle.internal.change.Change; +import org.gradle.internal.execution.history.changes.InputChangesInternal; import java.io.File; public class RebuildIncrementalTaskInputs extends StatefulIncrementalTaskInputs { - private static final Logger LOGGER = LoggerFactory.getLogger(RebuildIncrementalTaskInputs.class); + private final InputChangesInternal inputChanges; - private final Iterable fingerprints; - - public RebuildIncrementalTaskInputs(Task task, Iterable fingerprints) { - LOGGER.info("All input files are considered out-of-date for incremental {}.", task); - this.fingerprints = fingerprints; + public RebuildIncrementalTaskInputs(InputChangesInternal inputChanges) { + this.inputChanges = inputChanges; } public boolean isIncremental() { @@ -40,10 +35,9 @@ public boolean isIncremental() { } public void doOutOfDate(final Action outOfDateAction) { - for (FileCollectionFingerprint fingerprint : fingerprints) { - for (String path : fingerprint.getFingerprints().keySet()) { - outOfDateAction.execute(new RebuildInputFile(new File(path))); - } + for (Change change : inputChanges.getInputFileChanges()) { + InputFileDetails inputFileChange = (InputFileDetails) change; + outOfDateAction.execute(new RebuildInputFile(inputFileChange.getFile())); } } diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/project/taskfactory/IncrementalInputsTaskAction.java b/subprojects/core/src/main/java/org/gradle/api/internal/project/taskfactory/IncrementalInputsTaskAction.java index 9e50ca2ac32da..735bd98306fa9 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/project/taskfactory/IncrementalInputsTaskAction.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/project/taskfactory/IncrementalInputsTaskAction.java @@ -16,23 +16,14 @@ package org.gradle.api.internal.project.taskfactory; -import com.google.common.collect.ImmutableSortedMap; import org.gradle.api.Task; import org.gradle.api.execution.incremental.IncrementalInputs; -import org.gradle.api.internal.tasks.properties.InputFilePropertySpec; -import org.gradle.internal.Describables; import org.gradle.internal.execution.history.changes.ExecutionStateChanges; -import org.gradle.internal.execution.history.changes.InputFileChanges; -import org.gradle.internal.execution.history.impl.DefaultIncrementalInputs; -import org.gradle.internal.execution.history.impl.RebuildIncrementalInputs; -import org.gradle.internal.fingerprint.CurrentFileCollectionFingerprint; import org.gradle.internal.reflect.JavaMethod; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.lang.reflect.Method; -import java.util.HashMap; -import java.util.Map; public class IncrementalInputsTaskAction extends AbstractIncrementalTaskAction { private static final Logger LOGGER = LoggerFactory.getLogger(IncrementalInputsTaskAction.class); @@ -42,27 +33,12 @@ public IncrementalInputsTaskAction(Class type, Method method) { } protected void doExecute(final Task task, String methodName) { - final Map propertyNameByValue = new HashMap(); - for (InputFilePropertySpec inputFileProperty : getContext().getTaskProperties().getInputFileProperties()) { - Object value = inputFileProperty.getValue().call(); - if (value != null) { - propertyNameByValue.put(value, inputFileProperty.getPropertyName()); - } + @SuppressWarnings("OptionalGetWithoutIsPresent") + ExecutionStateChanges changes = getContext().getExecutionStateChanges().get(); + IncrementalInputs incrementalTaskInputs = changes.getInputChanges(); + if (!incrementalTaskInputs.isIncremental()) { + LOGGER.info("All inputs are considered out-of-date for incremental {}.", task); } - - @SuppressWarnings("OptionalGetWithoutIsPresent") final ExecutionStateChanges changes = getContext().getExecutionStateChanges().get(); - IncrementalInputs incrementalTaskInputs = changes.visitInputFileChanges(new ExecutionStateChanges.IncrementalInputsVisitor() { - @Override - public IncrementalInputs visitRebuild(ImmutableSortedMap allFileInputs) { - return new RebuildIncrementalInputs(allFileInputs, propertyNameByValue, Describables.of(task)); - } - - @Override - public IncrementalInputs visitIncrementalChange(InputFileChanges inputFileChanges) { - return new DefaultIncrementalInputs(inputFileChanges, propertyNameByValue); - } - }); - getContext().setTaskExecutedIncrementally(incrementalTaskInputs.isIncremental()); JavaMethod.of(task, Object.class, methodName, IncrementalInputs.class).invoke(task, incrementalTaskInputs); } diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/project/taskfactory/IncrementalTaskInputsTaskAction.java b/subprojects/core/src/main/java/org/gradle/api/internal/project/taskfactory/IncrementalTaskInputsTaskAction.java index 968ecbc4cc8d5..a57664d7e82e5 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/project/taskfactory/IncrementalTaskInputsTaskAction.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/project/taskfactory/IncrementalTaskInputsTaskAction.java @@ -16,22 +16,21 @@ package org.gradle.api.internal.project.taskfactory; -import com.google.common.collect.ImmutableSortedMap; import org.gradle.api.Task; import org.gradle.api.internal.changedetection.changes.ChangesOnlyIncrementalTaskInputs; import org.gradle.api.internal.changedetection.changes.RebuildIncrementalTaskInputs; import org.gradle.api.tasks.incremental.IncrementalTaskInputs; -import org.gradle.internal.change.Change; -import org.gradle.internal.change.CollectingChangeVisitor; import org.gradle.internal.execution.history.changes.ExecutionStateChanges; -import org.gradle.internal.execution.history.changes.InputFileChanges; -import org.gradle.internal.fingerprint.CurrentFileCollectionFingerprint; +import org.gradle.internal.execution.history.changes.InputChangesInternal; import org.gradle.internal.reflect.Instantiator; import org.gradle.internal.reflect.JavaMethod; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.lang.reflect.Method; class IncrementalTaskInputsTaskAction extends AbstractIncrementalTaskAction { + private static final Logger LOGGER = LoggerFactory.getLogger(IncrementalTaskInputsTaskAction.class); private final Instantiator instantiator; @@ -43,33 +42,22 @@ public IncrementalTaskInputsTaskAction(Instantiator instantiator, Class() { - @Override - public IncrementalTaskInputs visitRebuild(ImmutableSortedMap allFileInputs) { - return createRebuildInputs(task, allFileInputs); - } + InputChangesInternal inputChanges = changes.getInputChanges(); - @Override - public IncrementalTaskInputs visitIncrementalChange(InputFileChanges inputFileChanges) { - return createIncrementalInputs(inputFileChanges); - } - }); + IncrementalTaskInputs incrementalTaskInputs = inputChanges.isIncremental() + ? createIncrementalInputs(inputChanges) + : createRebuildInputs(task, inputChanges); getContext().setTaskExecutedIncrementally(incrementalTaskInputs.isIncremental()); JavaMethod.of(task, Object.class, methodName, IncrementalTaskInputs.class).invoke(task, incrementalTaskInputs); } - private ChangesOnlyIncrementalTaskInputs createIncrementalInputs(InputFileChanges inputFilesChanges) { - return instantiator.newInstance(ChangesOnlyIncrementalTaskInputs.class, collectInputFileChanges(inputFilesChanges)); + private ChangesOnlyIncrementalTaskInputs createIncrementalInputs(InputChangesInternal inputChanges) { + return instantiator.newInstance(ChangesOnlyIncrementalTaskInputs.class, inputChanges.getInputFileChanges()); } - private Iterable collectInputFileChanges(InputFileChanges inputFileChanges) { - CollectingChangeVisitor visitor = new CollectingChangeVisitor(); - inputFileChanges.accept(visitor); - return visitor.getChanges(); - } - - private RebuildIncrementalTaskInputs createRebuildInputs(Task task, ImmutableSortedMap currentInputs) { - return instantiator.newInstance(RebuildIncrementalTaskInputs.class, task, currentInputs.values()); + private RebuildIncrementalTaskInputs createRebuildInputs(Task task, InputChangesInternal inputChanges) { + LOGGER.info("All input files are considered out-of-date for incremental {}.", task); + return instantiator.newInstance(RebuildIncrementalTaskInputs.class, inputChanges); } } diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuter.java b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuter.java index fe48c7ae3b2cf..544a6834bc612 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuter.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuter.java @@ -15,6 +15,7 @@ */ package org.gradle.api.internal.tasks.execution; +import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSortedMap; import com.google.common.collect.Lists; import org.gradle.api.execution.TaskActionListener; @@ -27,6 +28,7 @@ import org.gradle.api.internal.tasks.TaskExecutionOutcome; import org.gradle.api.internal.tasks.TaskStateInternal; import org.gradle.api.internal.tasks.properties.CacheableOutputFilePropertySpec; +import org.gradle.api.internal.tasks.properties.InputFilePropertySpec; import org.gradle.api.internal.tasks.properties.OutputFilePropertySpec; import org.gradle.api.logging.Logger; import org.gradle.api.logging.Logging; @@ -63,7 +65,9 @@ import java.io.File; import java.time.Duration; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.Optional; import java.util.function.Consumer; import java.util.function.Function; @@ -313,6 +317,18 @@ public ImmutableSortedMap apply(Overla }).orElse(outputsAfterExecution); } + @Override + public ImmutableMap getInputToPropertyNames() { + Map propertyNameByValue = new HashMap(); + for (InputFilePropertySpec inputFileProperty : context.getTaskProperties().getInputFileProperties()) { + Object value = inputFileProperty.getValue().call(); + if (value != null) { + propertyNameByValue.put(value, inputFileProperty.getPropertyName()); + } + } + return ImmutableMap.copyOf(propertyNameByValue); + } + @Override public long markExecutionTime() { return context.markExecutionTime(); diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvoker.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvoker.java index 124a2aeb8cd70..e719a59841544 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvoker.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvoker.java @@ -41,11 +41,7 @@ import org.gradle.internal.execution.history.AfterPreviousExecutionState; import org.gradle.internal.execution.history.BeforeExecutionState; import org.gradle.internal.execution.history.ExecutionHistoryStore; -import org.gradle.internal.execution.history.changes.ExecutionStateChanges; -import org.gradle.internal.execution.history.changes.InputFileChanges; import org.gradle.internal.execution.history.impl.DefaultBeforeExecutionState; -import org.gradle.internal.execution.history.impl.DefaultIncrementalInputs; -import org.gradle.internal.execution.history.impl.RebuildIncrementalInputs; import org.gradle.internal.file.TreeType; import org.gradle.internal.fingerprint.CurrentFileCollectionFingerprint; import org.gradle.internal.fingerprint.FileCollectionFingerprinter; @@ -269,32 +265,19 @@ public ExecutionOutcome execute(IncrementalChangesContext context) { File outputDir = workspace.getOutputDirectory(); File resultsFile = workspace.getResultsFile(); - IncrementalInputs incrementalInputs = transformer.isIncremental() ? createIncrementalInputs(context) : null; + @SuppressWarnings("OptionalGetWithoutIsPresent") + IncrementalInputs incrementalInputs = transformer.isIncremental() + ? context.getChanges().get().getInputChanges() + : null; - if (incrementalInputs == null || !incrementalInputs.isIncremental()) { + boolean incremental = incrementalInputs != null && incrementalInputs.isIncremental(); + if (!incremental) { GFileUtils.cleanDirectory(outputDir); GFileUtils.deleteFileQuietly(resultsFile); } ImmutableList result = transformer.transform(inputArtifact, outputDir, dependencies, incrementalInputs); writeResultsFile(outputDir, resultsFile, result); - return ExecutionOutcome.EXECUTED_NON_INCREMENTALLY; - } - - private IncrementalInputs createIncrementalInputs(IncrementalChangesContext context) { - @SuppressWarnings("OptionalGetWithoutIsPresent") - ExecutionStateChanges executionStateChanges = context.getChanges().get(); - ImmutableMap propertyNameByValue = ImmutableMap.of(inputArtifact, INPUT_ARTIFACT_PROPERTY_NAME); - return executionStateChanges.visitInputFileChanges(new ExecutionStateChanges.IncrementalInputsVisitor() { - @Override - public IncrementalInputs visitRebuild(ImmutableSortedMap allFileInputs) { - return new RebuildIncrementalInputs(allFileInputs, propertyNameByValue, TransformerExecution.this); - } - - @Override - public IncrementalInputs visitIncrementalChange(InputFileChanges inputFileChanges) { - return new DefaultIncrementalInputs(inputFileChanges, propertyNameByValue); - } - }); + return incremental ? ExecutionOutcome.EXECUTED_INCREMENTALLY : ExecutionOutcome.EXECUTED_NON_INCREMENTALLY; } private void writeResultsFile(File outputDir, File resultsFile, ImmutableList result) { @@ -414,6 +397,11 @@ public ImmutableSortedMap snapshotAfte return snapshotOutputs(outputFingerprinter, fileCollectionFactory, workspace); } + @Override + public ImmutableMap getInputToPropertyNames() { + return ImmutableMap.of(inputArtifact, INPUT_ARTIFACT_PROPERTY_NAME); + } + @Override public String getIdentity() { return identityString; diff --git a/subprojects/execution/src/integTest/groovy/org/gradle/internal/execution/IncrementalExecutionIntegrationTest.groovy b/subprojects/execution/src/integTest/groovy/org/gradle/internal/execution/IncrementalExecutionIntegrationTest.groovy index 7901515517728..e1b9467323091 100644 --- a/subprojects/execution/src/integTest/groovy/org/gradle/internal/execution/IncrementalExecutionIntegrationTest.groovy +++ b/subprojects/execution/src/integTest/groovy/org/gradle/internal/execution/IncrementalExecutionIntegrationTest.groovy @@ -17,6 +17,7 @@ package org.gradle.internal.execution import com.google.common.collect.ImmutableList +import com.google.common.collect.ImmutableMap import com.google.common.collect.ImmutableSortedMap import com.google.common.collect.Iterables import org.gradle.api.file.FileCollection @@ -874,6 +875,17 @@ class IncrementalExecutionIntegrationTest extends Specification { snapshotOutputs() } + @Override + ImmutableMap getInputToPropertyNames() { + Map inputToPropertyNames = [:] + for (entry in inputs.entrySet()) { + if (entry.value != null) { + inputToPropertyNames.put(entry.value, entry.key) + } + } + return ImmutableMap.copyOf(inputToPropertyNames) + } + private ImmutableSortedMap snapshotOutputs() { def builder = ImmutableSortedMap.naturalOrder() outputs.each { propertyName, spec -> diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/UnitOfWork.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/UnitOfWork.java index 96622f82b862a..652bf2ec2af2d 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/UnitOfWork.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/UnitOfWork.java @@ -16,6 +16,7 @@ package org.gradle.internal.execution; +import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSortedMap; import org.gradle.api.file.FileCollection; import org.gradle.caching.internal.CacheableEntity; @@ -71,4 +72,6 @@ interface OutputPropertyVisitor { ExecutionHistoryStore getExecutionHistoryStore(); ImmutableSortedMap snapshotAfterOutputsGenerated(); + + ImmutableMap getInputToPropertyNames(); } diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/DefaultExecutionStateChangeDetector.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/DefaultExecutionStateChangeDetector.java index 25518afea6742..38bdb8ff0a178 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/DefaultExecutionStateChangeDetector.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/DefaultExecutionStateChangeDetector.java @@ -16,6 +16,7 @@ package org.gradle.internal.execution.history.changes; +import com.google.common.collect.ImmutableMap; import org.gradle.api.Describable; import org.gradle.internal.change.CachingChangeContainer; import org.gradle.internal.change.ChangeContainer; @@ -23,12 +24,15 @@ import org.gradle.internal.change.ChangeVisitor; import org.gradle.internal.change.ErrorHandlingChangeContainer; import org.gradle.internal.change.SummarizingChangeContainer; +import org.gradle.internal.execution.UnitOfWork; import org.gradle.internal.execution.history.AfterPreviousExecutionState; import org.gradle.internal.execution.history.BeforeExecutionState; +import org.gradle.internal.execution.history.impl.IncrementalInputChanges; +import org.gradle.internal.execution.history.impl.NonIncrementalInputChanges; public class DefaultExecutionStateChangeDetector implements ExecutionStateChangeDetector { @Override - public ExecutionStateChanges detectChanges(AfterPreviousExecutionState lastExecution, BeforeExecutionState thisExecution, Describable executable, boolean allowOverlappingOutputs) { + public ExecutionStateChanges detectChanges(AfterPreviousExecutionState lastExecution, BeforeExecutionState thisExecution, UnitOfWork work, boolean allowOverlappingOutputs) { // Capture changes in execution outcome ChangeContainer previousSuccessState = new PreviousSuccessChanges( lastExecution.isSuccessful()); @@ -37,25 +41,25 @@ public ExecutionStateChanges detectChanges(AfterPreviousExecutionState lastExecu ChangeContainer implementationChanges = new ImplementationChanges( lastExecution.getImplementation(), lastExecution.getAdditionalImplementations(), thisExecution.getImplementation(), thisExecution.getAdditionalImplementations(), - executable); + work); // Capture non-file input changes ChangeContainer inputPropertyChanges = new PropertyChanges( lastExecution.getInputProperties(), thisExecution.getInputProperties(), "Input", - executable); + work); ChangeContainer inputPropertyValueChanges = new InputValueChanges( lastExecution.getInputProperties(), thisExecution.getInputProperties(), - executable); + work); // Capture input files state ChangeContainer inputFilePropertyChanges = new PropertyChanges( lastExecution.getInputFileProperties(), thisExecution.getInputFileProperties(), "Input file", - executable); + work); InputFileChanges directInputFileChanges = new DefaultInputFileChanges( lastExecution.getInputFileProperties(), thisExecution.getInputFileProperties()); @@ -66,7 +70,7 @@ public ExecutionStateChanges detectChanges(AfterPreviousExecutionState lastExecu lastExecution.getOutputFileProperties(), thisExecution.getOutputFileProperties(), "Output", - executable); + work); OutputFileChanges uncachedOutputChanges = new OutputFileChanges( lastExecution.getOutputFileProperties(), thisExecution.getOutputFileProperties(), @@ -74,10 +78,11 @@ public ExecutionStateChanges detectChanges(AfterPreviousExecutionState lastExecu ChangeContainer outputFileChanges = caching(uncachedOutputChanges); return new DetectedExecutionStateChanges( - errorHandling(executable, inputFileChanges), - errorHandling(executable, new SummarizingChangeContainer(previousSuccessState, implementationChanges, inputPropertyChanges, inputPropertyValueChanges, outputFilePropertyChanges, outputFileChanges, inputFilePropertyChanges, inputFileChanges)), - errorHandling(executable, new SummarizingChangeContainer(previousSuccessState, implementationChanges, inputPropertyChanges, inputPropertyValueChanges, inputFilePropertyChanges, outputFilePropertyChanges, outputFileChanges)), - thisExecution + errorHandling(work, inputFileChanges), + errorHandling(work, new SummarizingChangeContainer(previousSuccessState, implementationChanges, inputPropertyChanges, inputPropertyValueChanges, outputFilePropertyChanges, outputFileChanges, inputFilePropertyChanges, inputFileChanges)), + errorHandling(work, new SummarizingChangeContainer(previousSuccessState, implementationChanges, inputPropertyChanges, inputPropertyValueChanges, inputFilePropertyChanges, outputFilePropertyChanges, outputFileChanges)), + thisExecution, + work ); } @@ -124,17 +129,20 @@ private static class DetectedExecutionStateChanges implements ExecutionStateChan private final ChangeContainer allChanges; private final ChangeContainer rebuildTriggeringChanges; private final BeforeExecutionState thisExecution; + private final UnitOfWork work; public DetectedExecutionStateChanges( InputFileChanges inputFileChanges, ChangeContainer allChanges, ChangeContainer rebuildTriggeringChanges, - BeforeExecutionState thisExecution + BeforeExecutionState thisExecution, + UnitOfWork work ) { this.inputFileChanges = inputFileChanges; this.allChanges = allChanges; this.rebuildTriggeringChanges = rebuildTriggeringChanges; this.thisExecution = thisExecution; + this.work = work; } @Override @@ -143,9 +151,11 @@ public void visitAllChanges(ChangeVisitor visitor) { } @Override - public T visitInputFileChanges(IncrementalInputsVisitor visitor) { - return isRebuildRequired() ? - visitor.visitRebuild(thisExecution.getInputFileProperties()) : visitor.visitIncrementalChange(inputFileChanges); + public InputChangesInternal getInputChanges() { + ImmutableMap inputToPropertyNames = work.getInputToPropertyNames(); + return isRebuildRequired() + ? new NonIncrementalInputChanges(thisExecution.getInputFileProperties(), inputToPropertyNames, work) + : new IncrementalInputChanges(inputFileChanges, inputToPropertyNames); } private boolean isRebuildRequired() { diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/ExecutionStateChangeDetector.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/ExecutionStateChangeDetector.java index 3afdc307c2313..1808140b74056 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/ExecutionStateChangeDetector.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/ExecutionStateChangeDetector.java @@ -16,7 +16,7 @@ package org.gradle.internal.execution.history.changes; -import org.gradle.api.Describable; +import org.gradle.internal.execution.UnitOfWork; import org.gradle.internal.execution.history.AfterPreviousExecutionState; import org.gradle.internal.execution.history.BeforeExecutionState; @@ -26,7 +26,7 @@ public interface ExecutionStateChangeDetector { ExecutionStateChanges detectChanges( AfterPreviousExecutionState lastExecution, BeforeExecutionState thisExecution, - Describable executable, + UnitOfWork work, boolean allowOverlappingOutputs ); } diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/ExecutionStateChanges.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/ExecutionStateChanges.java index 9c11fb53824f8..cece1751ef041 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/ExecutionStateChanges.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/ExecutionStateChanges.java @@ -16,9 +16,7 @@ package org.gradle.internal.execution.history.changes; -import com.google.common.collect.ImmutableSortedMap; import org.gradle.internal.change.ChangeVisitor; -import org.gradle.internal.fingerprint.CurrentFileCollectionFingerprint; /** * Represents the complete changes in execution state @@ -30,11 +28,5 @@ public interface ExecutionStateChanges { */ void visitAllChanges(ChangeVisitor visitor); - T visitInputFileChanges(IncrementalInputsVisitor visitor); - - interface IncrementalInputsVisitor { - T visitRebuild(ImmutableSortedMap allFileInputs); - - T visitIncrementalChange(InputFileChanges inputFileChanges); - } + InputChangesInternal getInputChanges(); } diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/InputChangesInternal.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/InputChangesInternal.java new file mode 100644 index 0000000000000..26136d0f2eeba --- /dev/null +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/InputChangesInternal.java @@ -0,0 +1,24 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.internal.execution.history.changes; + +import org.gradle.api.execution.incremental.IncrementalInputs; +import org.gradle.internal.change.Change; + +public interface InputChangesInternal extends IncrementalInputs { + Iterable getInputFileChanges(); +} diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/impl/DefaultIncrementalInputs.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/impl/IncrementalInputChanges.java similarity index 79% rename from subprojects/execution/src/main/java/org/gradle/internal/execution/history/impl/DefaultIncrementalInputs.java rename to subprojects/execution/src/main/java/org/gradle/internal/execution/history/impl/IncrementalInputChanges.java index 6085a57efcb6b..7a99ac8ce564c 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/impl/DefaultIncrementalInputs.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/impl/IncrementalInputChanges.java @@ -16,20 +16,21 @@ package org.gradle.internal.execution.history.impl; -import org.gradle.api.execution.incremental.IncrementalInputs; import org.gradle.api.tasks.incremental.InputFileDetails; import org.gradle.internal.Cast; +import org.gradle.internal.change.Change; import org.gradle.internal.change.CollectingChangeVisitor; +import org.gradle.internal.execution.history.changes.InputChangesInternal; import org.gradle.internal.execution.history.changes.InputFileChanges; import java.util.Map; -public class DefaultIncrementalInputs implements IncrementalInputs { +public class IncrementalInputChanges implements InputChangesInternal { private final InputFileChanges changes; private final Map propertyNameByValue; - public DefaultIncrementalInputs(InputFileChanges changes, Map propertyNameByValue) { + public IncrementalInputChanges(InputFileChanges changes, Map propertyNameByValue) { this.changes = changes; this.propertyNameByValue = propertyNameByValue; } @@ -54,4 +55,11 @@ public static String determinePropertyName(Object property, Map } return propertyName; } + + @Override + public Iterable getInputFileChanges() { + CollectingChangeVisitor visitor = new CollectingChangeVisitor(); + changes.accept(visitor); + return visitor.getChanges(); + } } diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/impl/RebuildIncrementalInputs.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/impl/NonIncrementalInputChanges.java similarity index 66% rename from subprojects/execution/src/main/java/org/gradle/internal/execution/history/impl/RebuildIncrementalInputs.java rename to subprojects/execution/src/main/java/org/gradle/internal/execution/history/impl/NonIncrementalInputChanges.java index 496896fcaf97a..82381af4b80a8 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/impl/RebuildIncrementalInputs.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/impl/NonIncrementalInputChanges.java @@ -18,10 +18,11 @@ import com.google.common.collect.ImmutableSortedMap; import org.gradle.api.Describable; -import org.gradle.api.execution.incremental.IncrementalInputs; import org.gradle.api.tasks.incremental.InputFileDetails; import org.gradle.internal.Cast; +import org.gradle.internal.change.Change; import org.gradle.internal.change.CollectingChangeVisitor; +import org.gradle.internal.execution.history.changes.InputChangesInternal; import org.gradle.internal.fingerprint.CurrentFileCollectionFingerprint; import org.gradle.internal.fingerprint.FileCollectionFingerprint; import org.slf4j.Logger; @@ -29,15 +30,15 @@ import java.util.Map; -import static org.gradle.internal.execution.history.impl.DefaultIncrementalInputs.determinePropertyName; +import static org.gradle.internal.execution.history.impl.IncrementalInputChanges.determinePropertyName; -public class RebuildIncrementalInputs implements IncrementalInputs { - private static final Logger LOGGER = LoggerFactory.getLogger(RebuildIncrementalInputs.class); +public class NonIncrementalInputChanges implements InputChangesInternal { + private static final Logger LOGGER = LoggerFactory.getLogger(NonIncrementalInputChanges.class); private final ImmutableSortedMap currentInputs; private final Map propertyNameByValue; - public RebuildIncrementalInputs(ImmutableSortedMap currentInputs, Map propertyNameByValue, Describable owner) { + public NonIncrementalInputChanges(ImmutableSortedMap currentInputs, Map propertyNameByValue, Describable owner) { this.currentInputs = currentInputs; this.propertyNameByValue = propertyNameByValue; LOGGER.info("All input files are considered out-of-date for incremental {}.", owner.getDisplayName()); @@ -52,7 +53,20 @@ public boolean isIncremental() { public Iterable getChanges(Object property) { CollectingChangeVisitor visitor = new CollectingChangeVisitor(); CurrentFileCollectionFingerprint currentFileCollectionFingerprint = currentInputs.get(determinePropertyName(property, propertyNameByValue)); - currentFileCollectionFingerprint.visitChangesSince(FileCollectionFingerprint.EMPTY, "Input", true, visitor); + visitAllFileChanges(currentFileCollectionFingerprint, visitor); return Cast.uncheckedNonnullCast(visitor.getChanges()); } + + @Override + public Iterable getInputFileChanges() { + CollectingChangeVisitor changeVisitor = new CollectingChangeVisitor(); + for (CurrentFileCollectionFingerprint fingerprint : currentInputs.values()) { + visitAllFileChanges(fingerprint, changeVisitor); + } + return changeVisitor.getChanges(); + } + + private void visitAllFileChanges(CurrentFileCollectionFingerprint currentFileCollectionFingerprint, CollectingChangeVisitor visitor) { + currentFileCollectionFingerprint.visitChangesSince(FileCollectionFingerprint.EMPTY, "Input", true, visitor); + } } diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/ResolveChangesStep.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/ResolveChangesStep.java index 7108f987f7dd3..4c8d7d5de098a 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/ResolveChangesStep.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/ResolveChangesStep.java @@ -16,7 +16,6 @@ package org.gradle.internal.execution.steps; -import com.google.common.collect.ImmutableSortedMap; import org.gradle.internal.change.Change; import org.gradle.internal.change.ChangeVisitor; import org.gradle.internal.change.DescriptiveChange; @@ -29,7 +28,8 @@ import org.gradle.internal.execution.history.BeforeExecutionState; import org.gradle.internal.execution.history.changes.ExecutionStateChangeDetector; import org.gradle.internal.execution.history.changes.ExecutionStateChanges; -import org.gradle.internal.fingerprint.CurrentFileCollectionFingerprint; +import org.gradle.internal.execution.history.changes.InputChangesInternal; +import org.gradle.internal.execution.history.impl.NonIncrementalInputChanges; import javax.annotation.Nullable; import java.util.Optional; @@ -54,7 +54,7 @@ public R execute(IncrementalContext context) { Optional beforeExecutionState = context.getBeforeExecutionState(); ExecutionStateChanges changes = context.getRebuildReason() .map(rebuildReason -> - new RebuildExecutionStateChanges(new DescriptiveChange(rebuildReason), beforeExecutionState.orElse(null)) + new RebuildExecutionStateChanges(new DescriptiveChange(rebuildReason), beforeExecutionState.orElse(null), work) ) .orElseGet(() -> beforeExecutionState @@ -65,7 +65,7 @@ public R execute(IncrementalContext context) { work, !work.isAllowOverlappingOutputs()) ) - .orElseGet(() -> new RebuildExecutionStateChanges(NO_HISTORY, beforeExecution)) + .orElseGet(() -> new RebuildExecutionStateChanges(NO_HISTORY, beforeExecution, work)) ) .orElse(null) ); @@ -101,10 +101,12 @@ public UnitOfWork getWork() { private static class RebuildExecutionStateChanges implements ExecutionStateChanges { private final Change rebuildChange; private final BeforeExecutionState beforeExecutionState; + private final UnitOfWork work; - public RebuildExecutionStateChanges(Change rebuildChange, @Nullable BeforeExecutionState beforeExecutionState) { + public RebuildExecutionStateChanges(Change rebuildChange, @Nullable BeforeExecutionState beforeExecutionState, UnitOfWork work) { this.rebuildChange = rebuildChange; this.beforeExecutionState = beforeExecutionState; + this.work = work; } @Override @@ -113,12 +115,11 @@ public void visitAllChanges(ChangeVisitor visitor) { } @Override - public T visitInputFileChanges(IncrementalInputsVisitor visitor) { + public InputChangesInternal getInputChanges() { if (beforeExecutionState == null) { - throw new UnsupportedOperationException("Cannot query incremental inputs when input tracking is disabled."); + throw new UnsupportedOperationException("Cannot query input changes when input tracking is disabled."); } - ImmutableSortedMap inputFileProperties = beforeExecutionState.getInputFileProperties(); - return visitor.visitRebuild(inputFileProperties); + return new NonIncrementalInputChanges(beforeExecutionState.getInputFileProperties(), work.getInputToPropertyNames(), work); } } } diff --git a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/ExecuteStepTest.groovy b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/ExecuteStepTest.groovy index d20f3ea0debb1..e4a169b54fac3 100644 --- a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/ExecuteStepTest.groovy +++ b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/ExecuteStepTest.groovy @@ -19,6 +19,7 @@ package org.gradle.internal.execution.steps import org.gradle.internal.execution.ExecutionOutcome import org.gradle.internal.execution.IncrementalChangesContext import org.gradle.internal.execution.UnitOfWork +import org.gradle.internal.execution.history.changes.ExecutionStateChanges import spock.lang.Specification import spock.lang.Unroll @@ -26,6 +27,7 @@ class ExecuteStepTest extends Specification { def step = new ExecuteStep() def context = Mock(IncrementalChangesContext) def work = Mock(UnitOfWork) + def changes = Optional.of(Mock(ExecutionStateChanges)) @Unroll def "#outcome outcome is preserved"() { @@ -36,7 +38,9 @@ class ExecuteStepTest extends Specification { result.outcome.get() == outcome 1 * context.work >> work - 1 * work.execute(context) >> { outcome } + 1 * context.changes >> changes + 1 * work.execute(changes) >> { outcome } + 0 * _ where: outcome << ExecutionOutcome.values() @@ -45,14 +49,15 @@ class ExecuteStepTest extends Specification { @Unroll def "failure #failure.class.simpleName is not caught"() { when: - def result = step.execute(context) + step.execute(context) then: def ex = thrown Throwable ex == failure 1 * context.work >> work - 1 * work.execute(context) >> { throw failure } + 1 * context.changes >> changes + 1 * work.execute(changes) >> { throw failure } where: failure << [new RuntimeException(), new Error()] diff --git a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/ResolveChangesStepTest.groovy b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/ResolveChangesStepTest.groovy index 17486b82bce22..9557ccbc45c0f 100644 --- a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/ResolveChangesStepTest.groovy +++ b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/ResolveChangesStepTest.groovy @@ -16,6 +16,7 @@ package org.gradle.internal.execution.steps +import com.google.common.collect.ImmutableMap import com.google.common.collect.ImmutableSortedMap import org.gradle.internal.execution.IncrementalChangesContext import org.gradle.internal.execution.IncrementalContext @@ -24,8 +25,6 @@ import org.gradle.internal.execution.history.AfterPreviousExecutionState import org.gradle.internal.execution.history.BeforeExecutionState import org.gradle.internal.execution.history.changes.ExecutionStateChangeDetector import org.gradle.internal.execution.history.changes.ExecutionStateChanges -import org.gradle.internal.execution.history.changes.InputFileChanges -import org.gradle.internal.fingerprint.CurrentFileCollectionFingerprint class ResolveChangesStepTest extends StepSpec { def changeDetector = Mock(ExecutionStateChangeDetector) @@ -46,10 +45,10 @@ class ResolveChangesStepTest extends StepSpec { def changes = delegateContext.changes.get() assert getRebuildReason(changes) == "Forced rebuild." try { - changes.visitInputFileChanges(Mock(ExecutionStateChanges.IncrementalInputsVisitor)) + changes.getInputChanges() assert false } catch (UnsupportedOperationException e) { - assert e.message == 'Cannot query incremental inputs when input tracking is disabled.' + assert e.message == 'Cannot query input changes when input tracking is disabled.' } return delegateResult } @@ -85,7 +84,7 @@ class ResolveChangesStepTest extends StepSpec { 1 * context.work >> work 1 * delegate.execute(_) >> { IncrementalChangesContext delegateContext -> def changes = delegateContext.changes.get() - assert !isIncremental(changes) + assert !changes.getInputChanges().incremental assert getRebuildReason(changes) == "No history is available." return delegateResult } @@ -93,6 +92,8 @@ class ResolveChangesStepTest extends StepSpec { 1 * context.beforeExecutionState >> Optional.of(beforeExecutionState) 1 * beforeExecutionState.getInputFileProperties() >> ImmutableSortedMap.of() 1 * context.afterPreviousExecutionState >> Optional.empty() + 1 * work.inputToPropertyNames >> ImmutableMap.of() + 1 * work.displayName >> "Some unit of work" 0 * _ } @@ -120,20 +121,6 @@ class ResolveChangesStepTest extends StepSpec { 0 * _ } - private static boolean isIncremental(ExecutionStateChanges changes) { - return changes.visitInputFileChanges(new ExecutionStateChanges.IncrementalInputsVisitor() { - @Override - Boolean visitRebuild(ImmutableSortedMap allFileInputs) { - return false - } - - @Override - Boolean visitIncrementalChange(InputFileChanges inputFileChanges) { - return true - } - }) - } - private static String getRebuildReason(ExecutionStateChanges changes) { String change = null changes.visitAllChanges({ change = it.message; false }) From b783efd0876085d0f396183c26c5d9548b291f98 Mon Sep 17 00:00:00 2001 From: Stefan Wolf Date: Tue, 12 Mar 2019 21:17:29 +0100 Subject: [PATCH 496/853] Rename IncrementalInputs -> InputChanges --- ...ncrementalInputs.java => InputChanges.java} | 10 +++++----- .../IncrementalInputsIntegrationTest.groovy | 10 +++++----- .../taskfactory/DefaultTaskClassInfoStore.java | 4 ++-- .../IncrementalInputsTaskAction.java | 10 +++++----- ...tTransformIncrementalIntegrationTest.groovy | 8 ++++---- .../transform/DefaultTransformer.java | 18 +++++++++--------- .../transform/DefaultTransformerInvoker.java | 8 ++++---- .../artifacts/transform/LegacyTransformer.java | 4 ++-- .../artifacts/transform/Transformer.java | 4 ++-- .../DefaultTransformerInvokerTest.groovy | 4 ++-- .../history/changes/InputChangesInternal.java | 4 ++-- 11 files changed, 42 insertions(+), 42 deletions(-) rename subprojects/core-api/src/main/java/org/gradle/api/execution/incremental/{IncrementalInputs.java => InputChanges.java} (94%) diff --git a/subprojects/core-api/src/main/java/org/gradle/api/execution/incremental/IncrementalInputs.java b/subprojects/core-api/src/main/java/org/gradle/api/execution/incremental/InputChanges.java similarity index 94% rename from subprojects/core-api/src/main/java/org/gradle/api/execution/incremental/IncrementalInputs.java rename to subprojects/core-api/src/main/java/org/gradle/api/execution/incremental/InputChanges.java index 03fb40bbdc6e1..12088e61b28b2 100644 --- a/subprojects/core-api/src/main/java/org/gradle/api/execution/incremental/IncrementalInputs.java +++ b/subprojects/core-api/src/main/java/org/gradle/api/execution/incremental/InputChanges.java @@ -24,7 +24,7 @@ * Provides access to any input files that need to be processed by an incremental work action. * *

    - * An incremental work action is one that accepts a single {@link IncrementalInputs} parameter. + * An incremental work action is one that accepts a single {@link InputChanges} parameter. * The work action can then query what changed for an input property since the last execution to only process the changes. * *

    @@ -36,11 +36,11 @@
      *     def File outputDir
      *
      *     {@literal @}TaskAction
    - *     void execute(IncrementalInputs inputs) {
    - *         if (!inputs.incremental)
    + *     void execute(InputChanges inputChanges) {
    + *         if (!inputChanges.incremental)
      *             project.delete(outputDir.listFiles())
      *
    - *         inputs.getChanges(inputDir).each { change ->
    + *         inputChanges.getChanges(inputDir).each { change ->
      *             if (change.removed) {
      *                 def targetFile = project.file("$outputDir/${change.file.name}")
      *                 if (targetFile.exists()) {
    @@ -68,7 +68,7 @@
      */
     @NonExtensible
     @Incubating
    -public interface IncrementalInputs {
    +public interface InputChanges {
         /**
          * Indicates if it was possible for Gradle to determine which input files were out of date compared to a previous execution.
          * Incremental inputs are unavailable when history is unavailable (i.e. this piece of work has never been executed before), or if there are changes to non-file input properties, or output files.
    diff --git a/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/IncrementalInputsIntegrationTest.groovy b/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/IncrementalInputsIntegrationTest.groovy
    index 12f4286075f3a..7b656d7a6f35a 100644
    --- a/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/IncrementalInputsIntegrationTest.groovy
    +++ b/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/IncrementalInputsIntegrationTest.groovy
    @@ -22,16 +22,16 @@ class IncrementalInputsIntegrationTest extends IncrementalTasksIntegrationTest {
     
         String getTaskAction() {
             """
    -            void execute(IncrementalInputs inputs) {
    -                assert !(inputs instanceof ExtensionAware)
    +            void execute(InputChanges inputChanges) {
    +                assert !(inputChanges instanceof ExtensionAware)
         
                     if (project.hasProperty('forceFail')) {
                         throw new RuntimeException('failed')
                     }
         
    -                incrementalExecution = inputs.incremental
    +                incrementalExecution = inputChanges.incremental
         
    -                inputs.getChanges(inputDir).each { change ->
    +                inputChanges.getChanges(inputDir).each { change ->
                         switch (change) {
                             case { it.added }:
                                 addedFiles << change.file
    @@ -47,7 +47,7 @@ class IncrementalInputsIntegrationTest extends IncrementalTasksIntegrationTest {
                         }
                     }
         
    -                if (!inputs.incremental) {
    +                if (!inputChanges.incremental) {
                         createOutputsNonIncremental()
                     }
                     
    diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/project/taskfactory/DefaultTaskClassInfoStore.java b/subprojects/core/src/main/java/org/gradle/api/internal/project/taskfactory/DefaultTaskClassInfoStore.java
    index ea6b806ea9895..7ab6833c353d4 100644
    --- a/subprojects/core/src/main/java/org/gradle/api/internal/project/taskfactory/DefaultTaskClassInfoStore.java
    +++ b/subprojects/core/src/main/java/org/gradle/api/internal/project/taskfactory/DefaultTaskClassInfoStore.java
    @@ -23,7 +23,7 @@
     import org.gradle.api.NonNullApi;
     import org.gradle.api.Task;
     import org.gradle.api.Transformer;
    -import org.gradle.api.execution.incremental.IncrementalInputs;
    +import org.gradle.api.execution.incremental.InputChanges;
     import org.gradle.api.tasks.CacheableTask;
     import org.gradle.api.tasks.TaskAction;
     import org.gradle.api.tasks.incremental.IncrementalTaskInputs;
    @@ -101,7 +101,7 @@ private static TaskActionFactory createTaskAction(Class taskType
                 Class parameterType = parameterTypes[0];
                 if (parameterType.equals(IncrementalTaskInputs.class)) {
                     taskActionFactory = new IncrementalTaskInputsTaskActionFactory(taskType, method);
    -            } else if (parameterType.equals(IncrementalInputs.class)) {
    +            } else if (parameterType.equals(InputChanges.class)) {
                     taskActionFactory = new IncrementalInputsTaskActionFactory(taskType, method);
                 } else {
                     throw new GradleException(String.format(
    diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/project/taskfactory/IncrementalInputsTaskAction.java b/subprojects/core/src/main/java/org/gradle/api/internal/project/taskfactory/IncrementalInputsTaskAction.java
    index 735bd98306fa9..21b57d3dbc60f 100644
    --- a/subprojects/core/src/main/java/org/gradle/api/internal/project/taskfactory/IncrementalInputsTaskAction.java
    +++ b/subprojects/core/src/main/java/org/gradle/api/internal/project/taskfactory/IncrementalInputsTaskAction.java
    @@ -17,7 +17,7 @@
     package org.gradle.api.internal.project.taskfactory;
     
     import org.gradle.api.Task;
    -import org.gradle.api.execution.incremental.IncrementalInputs;
    +import org.gradle.api.execution.incremental.InputChanges;
     import org.gradle.internal.execution.history.changes.ExecutionStateChanges;
     import org.gradle.internal.reflect.JavaMethod;
     import org.slf4j.Logger;
    @@ -35,11 +35,11 @@ public IncrementalInputsTaskAction(Class type, Method method) {
         protected void doExecute(final Task task, String methodName) {
             @SuppressWarnings("OptionalGetWithoutIsPresent")
             ExecutionStateChanges changes = getContext().getExecutionStateChanges().get();
    -        IncrementalInputs incrementalTaskInputs = changes.getInputChanges();
    -        if (!incrementalTaskInputs.isIncremental()) {
    +        InputChanges inputChanges = changes.getInputChanges();
    +        if (!inputChanges.isIncremental()) {
                 LOGGER.info("All inputs are considered out-of-date for incremental {}.", task);
             }
    -        getContext().setTaskExecutedIncrementally(incrementalTaskInputs.isIncremental());
    -        JavaMethod.of(task, Object.class, methodName, IncrementalInputs.class).invoke(task, incrementalTaskInputs);
    +        getContext().setTaskExecutedIncrementally(inputChanges.isIncremental());
    +        JavaMethod.of(task, Object.class, methodName, InputChanges.class).invoke(task, inputChanges);
         }
     }
    diff --git a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformIncrementalIntegrationTest.groovy b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformIncrementalIntegrationTest.groovy
    index 3b8a8cfce6821..d2fb7f39efd2c 100644
    --- a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformIncrementalIntegrationTest.groovy
    +++ b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformIncrementalIntegrationTest.groovy
    @@ -51,16 +51,16 @@ class ArtifactTransformIncrementalIntegrationTest extends AbstractDependencyReso
                     }
     
                     @Inject
    -                abstract IncrementalInputs getIncrementalInputs()
    +                abstract InputChanges getInputChanges()
                     
                     @InputArtifact
                     abstract File getInput()
                 
                     void transform(TransformOutputs outputs) {
                         println "Transforming " + input.name
    -                    println "incremental: " + incrementalInputs.incremental
    -                    assert parameters.incrementalExecution.get() == incrementalInputs.incremental
    -                    def changes = incrementalInputs.getChanges(input)
    +                    println "incremental: " + inputChanges.incremental
    +                    assert parameters.incrementalExecution.get() == inputChanges.incremental
    +                    def changes = inputChanges.getChanges(input)
                         println "changes: \\n" + changes.join("\\n")
                         assert changes.findAll { it.added }*.file as Set == resolveFiles(parameters.addedFiles.get())                    
                         assert changes.findAll { it.removed }*.file as Set == resolveFiles(parameters.removedFiles.get())                    
    diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformer.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformer.java
    index b557cbae248a8..bf4da5ab93de3 100644
    --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformer.java
    +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformer.java
    @@ -25,7 +25,7 @@
     import org.gradle.api.artifacts.transform.TransformAction;
     import org.gradle.api.artifacts.transform.TransformParameters;
     import org.gradle.api.artifacts.transform.VariantTransformConfigurationException;
    -import org.gradle.api.execution.incremental.IncrementalInputs;
    +import org.gradle.api.execution.incremental.InputChanges;
     import org.gradle.api.file.FileCollection;
     import org.gradle.api.internal.attributes.ImmutableAttributes;
     import org.gradle.api.internal.file.FileCollectionFactory;
    @@ -114,7 +114,7 @@ public DefaultTransformer(
             this.parameterPropertyWalker = parameterPropertyWalker;
             this.instanceFactory = actionInstantiationScheme.forType(implementationClass);
             this.requiresDependencies = instanceFactory.serviceInjectionTriggeredByAnnotation(InputArtifactDependencies.class);
    -        this.incremental = instanceFactory.requiresService(IncrementalInputs.class);
    +        this.incremental = instanceFactory.requiresService(InputChanges.class);
             this.cacheable = cacheable;
         }
     
    @@ -164,8 +164,8 @@ public HashCode getSecondaryInputHash() {
         }
     
         @Override
    -    public ImmutableList transform(File inputArtifact, File outputDir, ArtifactTransformDependencies dependencies, @Nullable IncrementalInputs incrementalInputs) {
    -        TransformAction transformAction = newTransformAction(inputArtifact, dependencies, incrementalInputs);
    +    public ImmutableList transform(File inputArtifact, File outputDir, ArtifactTransformDependencies dependencies, @Nullable InputChanges inputChanges) {
    +        TransformAction transformAction = newTransformAction(inputArtifact, dependencies, inputChanges);
             DefaultTransformOutputs transformOutputs = new DefaultTransformOutputs(inputArtifact, outputDir);
             transformAction.transform(transformOutputs);
             return transformOutputs.getRegisteredOutputs();
    @@ -278,8 +278,8 @@ private static String getParameterObjectDisplayName(Object parameterObject) {
             return ModelType.of(new DslObject(parameterObject).getDeclaredType()).getDisplayName();
         }
     
    -    private TransformAction newTransformAction(File inputFile, ArtifactTransformDependencies artifactTransformDependencies, @Nullable IncrementalInputs incrementalInputs) {
    -        ServiceLookup services = new TransformServiceLookup(inputFile, getIsolatedParameters().getIsolatedParameterObject().isolate(), requiresDependencies ? artifactTransformDependencies : null, incrementalInputs);
    +    private TransformAction newTransformAction(File inputFile, ArtifactTransformDependencies artifactTransformDependencies, @Nullable InputChanges inputChanges) {
    +        ServiceLookup services = new TransformServiceLookup(inputFile, getIsolatedParameters().getIsolatedParameterObject().isolate(), requiresDependencies ? artifactTransformDependencies : null, inputChanges);
             return instanceFactory.newInstance(services);
         }
     
    @@ -293,7 +293,7 @@ private IsolatedParameters getIsolatedParameters() {
         private static class TransformServiceLookup implements ServiceLookup {
             private final ImmutableList injectionPoints;
     
    -        public TransformServiceLookup(File inputFile, @Nullable TransformParameters parameters, @Nullable ArtifactTransformDependencies artifactTransformDependencies, @Nullable IncrementalInputs incrementalInputs) {
    +        public TransformServiceLookup(File inputFile, @Nullable TransformParameters parameters, @Nullable ArtifactTransformDependencies artifactTransformDependencies, @Nullable InputChanges inputChanges) {
                 ImmutableList.Builder builder = ImmutableList.builder();
                 builder.add(InjectionPoint.injectedByAnnotation(InputArtifact.class, () -> inputFile));
                 if (parameters != null) {
    @@ -306,8 +306,8 @@ public TransformServiceLookup(File inputFile, @Nullable TransformParameters para
                 if (artifactTransformDependencies != null) {
                     builder.add(InjectionPoint.injectedByAnnotation(InputArtifactDependencies.class, () -> artifactTransformDependencies.getFiles()));
                 }
    -            if (incrementalInputs != null) {
    -                builder.add(InjectionPoint.injectedByType(IncrementalInputs.class, () -> incrementalInputs));
    +            if (inputChanges != null) {
    +                builder.add(InjectionPoint.injectedByType(InputChanges.class, () -> inputChanges));
                 }
                 this.injectionPoints = builder.build();
             }
    diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvoker.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvoker.java
    index e719a59841544..8e16f1b2cad02 100644
    --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvoker.java
    +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvoker.java
    @@ -21,7 +21,7 @@
     import com.google.common.collect.ImmutableSortedMap;
     import org.gradle.api.UncheckedIOException;
     import org.gradle.api.artifacts.component.ProjectComponentIdentifier;
    -import org.gradle.api.execution.incremental.IncrementalInputs;
    +import org.gradle.api.execution.incremental.InputChanges;
     import org.gradle.api.file.RelativePath;
     import org.gradle.api.internal.artifacts.dsl.dependencies.ProjectFinder;
     import org.gradle.api.internal.artifacts.transform.TransformationWorkspaceProvider.TransformationWorkspace;
    @@ -266,16 +266,16 @@ public ExecutionOutcome execute(IncrementalChangesContext context) {
                 File resultsFile = workspace.getResultsFile();
     
                 @SuppressWarnings("OptionalGetWithoutIsPresent")
    -            IncrementalInputs incrementalInputs = transformer.isIncremental()
    +            InputChanges inputChanges = transformer.isIncremental()
                     ? context.getChanges().get().getInputChanges()
                     : null;
     
    -            boolean incremental = incrementalInputs != null && incrementalInputs.isIncremental();
    +            boolean incremental = inputChanges != null && inputChanges.isIncremental();
                 if (!incremental) {
                     GFileUtils.cleanDirectory(outputDir);
                     GFileUtils.deleteFileQuietly(resultsFile);
                 }
    -            ImmutableList result = transformer.transform(inputArtifact, outputDir, dependencies, incrementalInputs);
    +            ImmutableList result = transformer.transform(inputArtifact, outputDir, dependencies, inputChanges);
                 writeResultsFile(outputDir, resultsFile, result);
                 return incremental ? ExecutionOutcome.EXECUTED_INCREMENTALLY : ExecutionOutcome.EXECUTED_NON_INCREMENTALLY;
             }
    diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/LegacyTransformer.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/LegacyTransformer.java
    index 3d7bb74131d50..518d7fa43d637 100644
    --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/LegacyTransformer.java
    +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/LegacyTransformer.java
    @@ -19,7 +19,7 @@
     import com.google.common.collect.ImmutableList;
     import org.gradle.api.InvalidUserDataException;
     import org.gradle.api.artifacts.transform.ArtifactTransform;
    -import org.gradle.api.execution.incremental.IncrementalInputs;
    +import org.gradle.api.execution.incremental.InputChanges;
     import org.gradle.api.internal.attributes.ImmutableAttributes;
     import org.gradle.api.internal.tasks.TaskDependencyResolveContext;
     import org.gradle.api.tasks.FileNormalizer;
    @@ -66,7 +66,7 @@ public boolean isCacheable() {
         }
     
         @Override
    -    public ImmutableList transform(File inputArtifact, File outputDir, ArtifactTransformDependencies dependencies, @Nullable IncrementalInputs incrementalInputs) {
    +    public ImmutableList transform(File inputArtifact, File outputDir, ArtifactTransformDependencies dependencies, @Nullable InputChanges inputChanges) {
             ArtifactTransform transformer = newTransformer();
             transformer.setOutputDirectory(outputDir);
             List outputs = transformer.transform(inputArtifact);
    diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/Transformer.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/Transformer.java
    index c0d909cb9831c..1c6e6ba772db9 100644
    --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/Transformer.java
    +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/Transformer.java
    @@ -19,7 +19,7 @@
     import com.google.common.collect.ImmutableList;
     import org.gradle.api.Describable;
     import org.gradle.api.artifacts.transform.ArtifactTransform;
    -import org.gradle.api.execution.incremental.IncrementalInputs;
    +import org.gradle.api.execution.incremental.InputChanges;
     import org.gradle.api.internal.attributes.ImmutableAttributes;
     import org.gradle.api.internal.tasks.TaskDependencyContainer;
     import org.gradle.api.tasks.FileNormalizer;
    @@ -54,7 +54,7 @@ public interface Transformer extends Describable, TaskDependencyContainer {
          */
         boolean isCacheable();
     
    -    ImmutableList transform(File inputArtifact, File outputDir, ArtifactTransformDependencies dependencies, @Nullable IncrementalInputs incrementalInputs);
    +    ImmutableList transform(File inputArtifact, File outputDir, ArtifactTransformDependencies dependencies, @Nullable InputChanges inputChanges);
     
         /**
          * The hash of the secondary inputs of the transformer.
    diff --git a/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvokerTest.groovy b/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvokerTest.groovy
    index 4a1fa06c01812..1ad8308d9764d 100644
    --- a/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvokerTest.groovy
    +++ b/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvokerTest.groovy
    @@ -18,7 +18,7 @@ package org.gradle.api.internal.artifacts.transform
     
     import com.google.common.collect.ImmutableList
     import org.gradle.api.artifacts.transform.ArtifactTransform
    -import org.gradle.api.execution.incremental.IncrementalInputs
    +import org.gradle.api.execution.incremental.InputChanges
     import org.gradle.api.internal.artifacts.DefaultBuildIdentifier
     import org.gradle.api.internal.artifacts.DefaultProjectComponentIdentifier
     import org.gradle.api.internal.artifacts.dsl.dependencies.ProjectFinder
    @@ -137,7 +137,7 @@ class DefaultTransformerInvokerTest extends AbstractProjectBuilderSpec {
             }
     
             @Override
    -        ImmutableList transform(File inputArtifact, File outputDir, ArtifactTransformDependencies dependencies, IncrementalInputs incrementalInputs) {
    +        ImmutableList transform(File inputArtifact, File outputDir, ArtifactTransformDependencies dependencies, InputChanges inputChanges) {
                 return ImmutableList.copyOf(transformationAction.apply(inputArtifact, outputDir))
             }
     
    diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/InputChangesInternal.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/InputChangesInternal.java
    index 26136d0f2eeba..e122e8a541603 100644
    --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/InputChangesInternal.java
    +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/InputChangesInternal.java
    @@ -16,9 +16,9 @@
     
     package org.gradle.internal.execution.history.changes;
     
    -import org.gradle.api.execution.incremental.IncrementalInputs;
    +import org.gradle.api.execution.incremental.InputChanges;
     import org.gradle.internal.change.Change;
     
    -public interface InputChangesInternal extends IncrementalInputs {
    +public interface InputChangesInternal extends InputChanges {
         Iterable getInputFileChanges();
     }
    
    From b7140cba6b152494623b47390d5f8c0e1ec54211 Mon Sep 17 00:00:00 2001
    From: Stefan Wolf 
    Date: Tue, 12 Mar 2019 21:28:28 +0100
    Subject: [PATCH 497/853] Rename `getChanges -> getFileChanges`
    
    ---
     .../gradle/api/execution/incremental/InputChanges.java    | 8 ++++----
     .../api/tasks/IncrementalInputsIntegrationTest.groovy     | 2 +-
     .../changes/RebuildIncrementalTaskInputs.java             | 2 +-
     .../taskfactory/IncrementalTaskInputsTaskAction.java      | 2 +-
     .../ArtifactTransformIncrementalIntegrationTest.groovy    | 2 +-
     .../execution/history/changes/InputChangesInternal.java   | 2 +-
     .../execution/history/impl/IncrementalInputChanges.java   | 4 ++--
     .../history/impl/NonIncrementalInputChanges.java          | 4 ++--
     8 files changed, 13 insertions(+), 13 deletions(-)
    
    diff --git a/subprojects/core-api/src/main/java/org/gradle/api/execution/incremental/InputChanges.java b/subprojects/core-api/src/main/java/org/gradle/api/execution/incremental/InputChanges.java
    index 12088e61b28b2..6889f3a5e44e8 100644
    --- a/subprojects/core-api/src/main/java/org/gradle/api/execution/incremental/InputChanges.java
    +++ b/subprojects/core-api/src/main/java/org/gradle/api/execution/incremental/InputChanges.java
    @@ -40,7 +40,7 @@
      *         if (!inputChanges.incremental)
      *             project.delete(outputDir.listFiles())
      *
    - *         inputChanges.getChanges(inputDir).each { change ->
    + *         inputChanges.getFileChanges(inputDir).each { change ->
      *             if (change.removed) {
      *                 def targetFile = project.file("$outputDir/${change.file.name}")
      *                 if (targetFile.exists()) {
    @@ -76,13 +76,13 @@ public interface InputChanges {
          * When true:
          * 

    *
      - *
    • {@link #getChanges(Object)} reports changes to the input files compared to the previous execution.
    • + *
    • {@link #getFileChanges(Object)} reports changes to the input files compared to the previous execution.
    • *
    *

    * When false: *

    *
      - *
    • Every input file is reported via {@link #getChanges(Object)} as if it was 'added'.
    • + *
    • Every input file is reported via {@link #getFileChanges(Object)} as if it was 'added'.
    • *
    */ boolean isIncremental(); @@ -94,5 +94,5 @@ public interface InputChanges { * * @param property The instance of the property to query. */ - Iterable getChanges(Object property); + Iterable getFileChanges(Object property); } diff --git a/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/IncrementalInputsIntegrationTest.groovy b/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/IncrementalInputsIntegrationTest.groovy index 7b656d7a6f35a..43aaab974f5e4 100644 --- a/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/IncrementalInputsIntegrationTest.groovy +++ b/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/IncrementalInputsIntegrationTest.groovy @@ -31,7 +31,7 @@ class IncrementalInputsIntegrationTest extends IncrementalTasksIntegrationTest { incrementalExecution = inputChanges.incremental - inputChanges.getChanges(inputDir).each { change -> + inputChanges.getFileChanges(inputDir).each { change -> switch (change) { case { it.added }: addedFiles << change.file diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/changedetection/changes/RebuildIncrementalTaskInputs.java b/subprojects/core/src/main/java/org/gradle/api/internal/changedetection/changes/RebuildIncrementalTaskInputs.java index a682b76e2a9ef..ff28008e1f98a 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/changedetection/changes/RebuildIncrementalTaskInputs.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/changedetection/changes/RebuildIncrementalTaskInputs.java @@ -35,7 +35,7 @@ public boolean isIncremental() { } public void doOutOfDate(final Action outOfDateAction) { - for (Change change : inputChanges.getInputFileChanges()) { + for (Change change : inputChanges.getAllFileChanges()) { InputFileDetails inputFileChange = (InputFileDetails) change; outOfDateAction.execute(new RebuildInputFile(inputFileChange.getFile())); } diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/project/taskfactory/IncrementalTaskInputsTaskAction.java b/subprojects/core/src/main/java/org/gradle/api/internal/project/taskfactory/IncrementalTaskInputsTaskAction.java index a57664d7e82e5..99bd15b9a9c57 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/project/taskfactory/IncrementalTaskInputsTaskAction.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/project/taskfactory/IncrementalTaskInputsTaskAction.java @@ -53,7 +53,7 @@ protected void doExecute(final Task task, String methodName) { } private ChangesOnlyIncrementalTaskInputs createIncrementalInputs(InputChangesInternal inputChanges) { - return instantiator.newInstance(ChangesOnlyIncrementalTaskInputs.class, inputChanges.getInputFileChanges()); + return instantiator.newInstance(ChangesOnlyIncrementalTaskInputs.class, inputChanges.getAllFileChanges()); } private RebuildIncrementalTaskInputs createRebuildInputs(Task task, InputChangesInternal inputChanges) { diff --git a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformIncrementalIntegrationTest.groovy b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformIncrementalIntegrationTest.groovy index d2fb7f39efd2c..8173b7f62d6ae 100644 --- a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformIncrementalIntegrationTest.groovy +++ b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformIncrementalIntegrationTest.groovy @@ -60,7 +60,7 @@ class ArtifactTransformIncrementalIntegrationTest extends AbstractDependencyReso println "Transforming " + input.name println "incremental: " + inputChanges.incremental assert parameters.incrementalExecution.get() == inputChanges.incremental - def changes = inputChanges.getChanges(input) + def changes = inputChanges.getFileChanges(input) println "changes: \\n" + changes.join("\\n") assert changes.findAll { it.added }*.file as Set == resolveFiles(parameters.addedFiles.get()) assert changes.findAll { it.removed }*.file as Set == resolveFiles(parameters.removedFiles.get()) diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/InputChangesInternal.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/InputChangesInternal.java index e122e8a541603..42eb3158b117c 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/InputChangesInternal.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/InputChangesInternal.java @@ -20,5 +20,5 @@ import org.gradle.internal.change.Change; public interface InputChangesInternal extends InputChanges { - Iterable getInputFileChanges(); + Iterable getAllFileChanges(); } diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/impl/IncrementalInputChanges.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/impl/IncrementalInputChanges.java index 7a99ac8ce564c..802f26b4804e0 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/impl/IncrementalInputChanges.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/impl/IncrementalInputChanges.java @@ -41,7 +41,7 @@ public boolean isIncremental() { } @Override - public Iterable getChanges(Object property) { + public Iterable getFileChanges(Object property) { String propertyName = determinePropertyName(property, propertyNameByValue); CollectingChangeVisitor visitor = new CollectingChangeVisitor(); changes.accept(propertyName, visitor); @@ -57,7 +57,7 @@ public static String determinePropertyName(Object property, Map } @Override - public Iterable getInputFileChanges() { + public Iterable getAllFileChanges() { CollectingChangeVisitor visitor = new CollectingChangeVisitor(); changes.accept(visitor); return visitor.getChanges(); diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/impl/NonIncrementalInputChanges.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/impl/NonIncrementalInputChanges.java index 82381af4b80a8..110a2d2ecf469 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/impl/NonIncrementalInputChanges.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/impl/NonIncrementalInputChanges.java @@ -50,7 +50,7 @@ public boolean isIncremental() { } @Override - public Iterable getChanges(Object property) { + public Iterable getFileChanges(Object property) { CollectingChangeVisitor visitor = new CollectingChangeVisitor(); CurrentFileCollectionFingerprint currentFileCollectionFingerprint = currentInputs.get(determinePropertyName(property, propertyNameByValue)); visitAllFileChanges(currentFileCollectionFingerprint, visitor); @@ -58,7 +58,7 @@ public Iterable getChanges(Object property) { } @Override - public Iterable getInputFileChanges() { + public Iterable getAllFileChanges() { CollectingChangeVisitor changeVisitor = new CollectingChangeVisitor(); for (CurrentFileCollectionFingerprint fingerprint : currentInputs.values()) { visitAllFileChanges(fingerprint, changeVisitor); From 14d18fa09dac2bf51d59f001266a8b4ac2c66c82 Mon Sep 17 00:00:00 2001 From: Stefan Wolf Date: Tue, 12 Mar 2019 22:08:11 +0100 Subject: [PATCH 498/853] Remove class/package cycles --- .../execution/ExecuteActionsTaskExecuter.java | 5 +-- .../transform/DefaultTransformerInvoker.java | 6 +-- ...IncrementalExecutionIntegrationTest.groovy | 3 +- .../gradle/internal/execution/UnitOfWork.java | 9 ++--- .../DefaultExecutionStateChangeDetector.java | 37 ++++++++++--------- .../changes/ExecutionStateChangeDetector.java | 7 ++-- .../IncrementalInputChanges.java | 4 +- .../changes/InputToPropertyMapping.java | 24 ++++++++++++ .../NonIncrementalInputChanges.java | 5 +-- .../internal/execution/steps/ExecuteStep.java | 2 +- .../execution/steps/ResolveChangesStep.java | 5 ++- .../steps/ResolveChangesStepTest.groovy | 2 +- 12 files changed, 66 insertions(+), 43 deletions(-) rename subprojects/execution/src/main/java/org/gradle/internal/execution/history/{impl => changes}/IncrementalInputChanges.java (91%) create mode 100644 subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/InputToPropertyMapping.java rename subprojects/execution/src/main/java/org/gradle/internal/execution/history/{impl => changes}/NonIncrementalInputChanges.java (92%) diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuter.java b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuter.java index 544a6834bc612..ebf65874863d3 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuter.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuter.java @@ -44,7 +44,6 @@ import org.gradle.internal.execution.CacheHandler; import org.gradle.internal.execution.ExecutionException; import org.gradle.internal.execution.ExecutionOutcome; -import org.gradle.internal.execution.IncrementalChangesContext; import org.gradle.internal.execution.IncrementalContext; import org.gradle.internal.execution.UnitOfWork; import org.gradle.internal.execution.UpToDateResult; @@ -192,12 +191,12 @@ public String getIdentity() { } @Override - public ExecutionOutcome execute(IncrementalChangesContext context) { + public ExecutionOutcome execute(Optional changes) { task.getState().setExecuting(true); try { LOGGER.debug("Executing actions for {}.", task); actionListener.beforeActions(task); - context.getChanges().ifPresent(new Consumer() { + changes.ifPresent(new Consumer() { @Override public void accept(ExecutionStateChanges changes) { TaskExecution.this.context.setExecutionStateChanges(changes); diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvoker.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvoker.java index 8e16f1b2cad02..cd5e1ad311970 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvoker.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvoker.java @@ -33,7 +33,6 @@ import org.gradle.internal.classloader.ClassLoaderHierarchyHasher; import org.gradle.internal.execution.CacheHandler; import org.gradle.internal.execution.ExecutionOutcome; -import org.gradle.internal.execution.IncrementalChangesContext; import org.gradle.internal.execution.IncrementalContext; import org.gradle.internal.execution.UnitOfWork; import org.gradle.internal.execution.UpToDateResult; @@ -41,6 +40,7 @@ import org.gradle.internal.execution.history.AfterPreviousExecutionState; import org.gradle.internal.execution.history.BeforeExecutionState; import org.gradle.internal.execution.history.ExecutionHistoryStore; +import org.gradle.internal.execution.history.changes.ExecutionStateChanges; import org.gradle.internal.execution.history.impl.DefaultBeforeExecutionState; import org.gradle.internal.file.TreeType; import org.gradle.internal.fingerprint.CurrentFileCollectionFingerprint; @@ -261,13 +261,13 @@ public TransformerExecution( } @Override - public ExecutionOutcome execute(IncrementalChangesContext context) { + public ExecutionOutcome execute(Optional changes) { File outputDir = workspace.getOutputDirectory(); File resultsFile = workspace.getResultsFile(); @SuppressWarnings("OptionalGetWithoutIsPresent") InputChanges inputChanges = transformer.isIncremental() - ? context.getChanges().get().getInputChanges() + ? changes.get().getInputChanges() : null; boolean incremental = inputChanges != null && inputChanges.isIncremental(); diff --git a/subprojects/execution/src/integTest/groovy/org/gradle/internal/execution/IncrementalExecutionIntegrationTest.groovy b/subprojects/execution/src/integTest/groovy/org/gradle/internal/execution/IncrementalExecutionIntegrationTest.groovy index e1b9467323091..7169bd74c194d 100644 --- a/subprojects/execution/src/integTest/groovy/org/gradle/internal/execution/IncrementalExecutionIntegrationTest.groovy +++ b/subprojects/execution/src/integTest/groovy/org/gradle/internal/execution/IncrementalExecutionIntegrationTest.groovy @@ -31,6 +31,7 @@ import org.gradle.internal.execution.history.BeforeExecutionState import org.gradle.internal.execution.history.ExecutionHistoryStore import org.gradle.internal.execution.history.OutputFilesRepository import org.gradle.internal.execution.history.changes.DefaultExecutionStateChangeDetector +import org.gradle.internal.execution.history.changes.ExecutionStateChanges import org.gradle.internal.execution.history.impl.DefaultBeforeExecutionState import org.gradle.internal.execution.impl.DefaultWorkExecutor import org.gradle.internal.execution.steps.BroadcastChangingOutputsStep @@ -772,7 +773,7 @@ class IncrementalExecutionIntegrationTest extends Specification { boolean executed @Override - ExecutionOutcome execute(IncrementalChangesContext context) { + ExecutionOutcome execute(Optional changes) { executed = true return work.get() } diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/UnitOfWork.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/UnitOfWork.java index 652bf2ec2af2d..88ad7cbfe716c 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/UnitOfWork.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/UnitOfWork.java @@ -16,23 +16,24 @@ package org.gradle.internal.execution; -import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSortedMap; import org.gradle.api.file.FileCollection; import org.gradle.caching.internal.CacheableEntity; import org.gradle.internal.execution.history.ExecutionHistoryStore; +import org.gradle.internal.execution.history.changes.ExecutionStateChanges; +import org.gradle.internal.execution.history.changes.InputToPropertyMapping; import org.gradle.internal.file.TreeType; import org.gradle.internal.fingerprint.CurrentFileCollectionFingerprint; import java.time.Duration; import java.util.Optional; -public interface UnitOfWork extends CacheableEntity { +public interface UnitOfWork extends CacheableEntity, InputToPropertyMapping { /** * Executes the work synchronously. */ - ExecutionOutcome execute(IncrementalChangesContext context); + ExecutionOutcome execute(Optional changes); Optional getTimeout(); @@ -72,6 +73,4 @@ interface OutputPropertyVisitor { ExecutionHistoryStore getExecutionHistoryStore(); ImmutableSortedMap snapshotAfterOutputsGenerated(); - - ImmutableMap getInputToPropertyNames(); } diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/DefaultExecutionStateChangeDetector.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/DefaultExecutionStateChangeDetector.java index 38bdb8ff0a178..1de531de27884 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/DefaultExecutionStateChangeDetector.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/DefaultExecutionStateChangeDetector.java @@ -24,15 +24,12 @@ import org.gradle.internal.change.ChangeVisitor; import org.gradle.internal.change.ErrorHandlingChangeContainer; import org.gradle.internal.change.SummarizingChangeContainer; -import org.gradle.internal.execution.UnitOfWork; import org.gradle.internal.execution.history.AfterPreviousExecutionState; import org.gradle.internal.execution.history.BeforeExecutionState; -import org.gradle.internal.execution.history.impl.IncrementalInputChanges; -import org.gradle.internal.execution.history.impl.NonIncrementalInputChanges; public class DefaultExecutionStateChangeDetector implements ExecutionStateChangeDetector { @Override - public ExecutionStateChanges detectChanges(AfterPreviousExecutionState lastExecution, BeforeExecutionState thisExecution, UnitOfWork work, boolean allowOverlappingOutputs) { + public ExecutionStateChanges detectChanges(AfterPreviousExecutionState lastExecution, BeforeExecutionState thisExecution, Describable executable, boolean allowOverlappingOutputs, InputToPropertyMapping inputToPropertyMapping) { // Capture changes in execution outcome ChangeContainer previousSuccessState = new PreviousSuccessChanges( lastExecution.isSuccessful()); @@ -41,25 +38,25 @@ public ExecutionStateChanges detectChanges(AfterPreviousExecutionState lastExecu ChangeContainer implementationChanges = new ImplementationChanges( lastExecution.getImplementation(), lastExecution.getAdditionalImplementations(), thisExecution.getImplementation(), thisExecution.getAdditionalImplementations(), - work); + executable); // Capture non-file input changes ChangeContainer inputPropertyChanges = new PropertyChanges( lastExecution.getInputProperties(), thisExecution.getInputProperties(), "Input", - work); + executable); ChangeContainer inputPropertyValueChanges = new InputValueChanges( lastExecution.getInputProperties(), thisExecution.getInputProperties(), - work); + executable); // Capture input files state ChangeContainer inputFilePropertyChanges = new PropertyChanges( lastExecution.getInputFileProperties(), thisExecution.getInputFileProperties(), "Input file", - work); + executable); InputFileChanges directInputFileChanges = new DefaultInputFileChanges( lastExecution.getInputFileProperties(), thisExecution.getInputFileProperties()); @@ -70,7 +67,7 @@ public ExecutionStateChanges detectChanges(AfterPreviousExecutionState lastExecu lastExecution.getOutputFileProperties(), thisExecution.getOutputFileProperties(), "Output", - work); + executable); OutputFileChanges uncachedOutputChanges = new OutputFileChanges( lastExecution.getOutputFileProperties(), thisExecution.getOutputFileProperties(), @@ -78,11 +75,12 @@ public ExecutionStateChanges detectChanges(AfterPreviousExecutionState lastExecu ChangeContainer outputFileChanges = caching(uncachedOutputChanges); return new DetectedExecutionStateChanges( - errorHandling(work, inputFileChanges), - errorHandling(work, new SummarizingChangeContainer(previousSuccessState, implementationChanges, inputPropertyChanges, inputPropertyValueChanges, outputFilePropertyChanges, outputFileChanges, inputFilePropertyChanges, inputFileChanges)), - errorHandling(work, new SummarizingChangeContainer(previousSuccessState, implementationChanges, inputPropertyChanges, inputPropertyValueChanges, inputFilePropertyChanges, outputFilePropertyChanges, outputFileChanges)), + errorHandling(executable, inputFileChanges), + errorHandling(executable, new SummarizingChangeContainer(previousSuccessState, implementationChanges, inputPropertyChanges, inputPropertyValueChanges, outputFilePropertyChanges, outputFileChanges, inputFilePropertyChanges, inputFileChanges)), + errorHandling(executable, new SummarizingChangeContainer(previousSuccessState, implementationChanges, inputPropertyChanges, inputPropertyValueChanges, inputFilePropertyChanges, outputFilePropertyChanges, outputFileChanges)), thisExecution, - work + executable, + inputToPropertyMapping ); } @@ -129,20 +127,23 @@ private static class DetectedExecutionStateChanges implements ExecutionStateChan private final ChangeContainer allChanges; private final ChangeContainer rebuildTriggeringChanges; private final BeforeExecutionState thisExecution; - private final UnitOfWork work; + private final Describable owner; + private final InputToPropertyMapping inputToPropertyMapping; public DetectedExecutionStateChanges( InputFileChanges inputFileChanges, ChangeContainer allChanges, ChangeContainer rebuildTriggeringChanges, BeforeExecutionState thisExecution, - UnitOfWork work + Describable owner, + InputToPropertyMapping inputToPropertyMapping ) { this.inputFileChanges = inputFileChanges; this.allChanges = allChanges; this.rebuildTriggeringChanges = rebuildTriggeringChanges; this.thisExecution = thisExecution; - this.work = work; + this.owner = owner; + this.inputToPropertyMapping = inputToPropertyMapping; } @Override @@ -152,9 +153,9 @@ public void visitAllChanges(ChangeVisitor visitor) { @Override public InputChangesInternal getInputChanges() { - ImmutableMap inputToPropertyNames = work.getInputToPropertyNames(); + ImmutableMap inputToPropertyNames = inputToPropertyMapping.getInputToPropertyNames(); return isRebuildRequired() - ? new NonIncrementalInputChanges(thisExecution.getInputFileProperties(), inputToPropertyNames, work) + ? new NonIncrementalInputChanges(thisExecution.getInputFileProperties(), inputToPropertyNames, owner) : new IncrementalInputChanges(inputFileChanges, inputToPropertyNames); } diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/ExecutionStateChangeDetector.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/ExecutionStateChangeDetector.java index 1808140b74056..8ac883be7f939 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/ExecutionStateChangeDetector.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/ExecutionStateChangeDetector.java @@ -16,7 +16,7 @@ package org.gradle.internal.execution.history.changes; -import org.gradle.internal.execution.UnitOfWork; +import org.gradle.api.Describable; import org.gradle.internal.execution.history.AfterPreviousExecutionState; import org.gradle.internal.execution.history.BeforeExecutionState; @@ -26,7 +26,8 @@ public interface ExecutionStateChangeDetector { ExecutionStateChanges detectChanges( AfterPreviousExecutionState lastExecution, BeforeExecutionState thisExecution, - UnitOfWork work, - boolean allowOverlappingOutputs + Describable executable, + boolean allowOverlappingOutputs, + InputToPropertyMapping inputToPropertyMapping ); } diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/impl/IncrementalInputChanges.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/IncrementalInputChanges.java similarity index 91% rename from subprojects/execution/src/main/java/org/gradle/internal/execution/history/impl/IncrementalInputChanges.java rename to subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/IncrementalInputChanges.java index 802f26b4804e0..a2452f53f9dcb 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/impl/IncrementalInputChanges.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/IncrementalInputChanges.java @@ -14,14 +14,12 @@ * limitations under the License. */ -package org.gradle.internal.execution.history.impl; +package org.gradle.internal.execution.history.changes; import org.gradle.api.tasks.incremental.InputFileDetails; import org.gradle.internal.Cast; import org.gradle.internal.change.Change; import org.gradle.internal.change.CollectingChangeVisitor; -import org.gradle.internal.execution.history.changes.InputChangesInternal; -import org.gradle.internal.execution.history.changes.InputFileChanges; import java.util.Map; diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/InputToPropertyMapping.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/InputToPropertyMapping.java new file mode 100644 index 0000000000000..28ef6cb0e9b8f --- /dev/null +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/InputToPropertyMapping.java @@ -0,0 +1,24 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.internal.execution.history.changes; + +import com.google.common.collect.ImmutableMap; + +public interface InputToPropertyMapping { + ImmutableMap getInputToPropertyNames(); + +} diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/impl/NonIncrementalInputChanges.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/NonIncrementalInputChanges.java similarity index 92% rename from subprojects/execution/src/main/java/org/gradle/internal/execution/history/impl/NonIncrementalInputChanges.java rename to subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/NonIncrementalInputChanges.java index 110a2d2ecf469..224bffa9b9896 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/impl/NonIncrementalInputChanges.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/NonIncrementalInputChanges.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.gradle.internal.execution.history.impl; +package org.gradle.internal.execution.history.changes; import com.google.common.collect.ImmutableSortedMap; import org.gradle.api.Describable; @@ -22,7 +22,6 @@ import org.gradle.internal.Cast; import org.gradle.internal.change.Change; import org.gradle.internal.change.CollectingChangeVisitor; -import org.gradle.internal.execution.history.changes.InputChangesInternal; import org.gradle.internal.fingerprint.CurrentFileCollectionFingerprint; import org.gradle.internal.fingerprint.FileCollectionFingerprint; import org.slf4j.Logger; @@ -30,7 +29,7 @@ import java.util.Map; -import static org.gradle.internal.execution.history.impl.IncrementalInputChanges.determinePropertyName; +import static org.gradle.internal.execution.history.changes.IncrementalInputChanges.determinePropertyName; public class NonIncrementalInputChanges implements InputChangesInternal { private static final Logger LOGGER = LoggerFactory.getLogger(NonIncrementalInputChanges.class); diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/ExecuteStep.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/ExecuteStep.java index f9bfe368716b9..6a390639e38e1 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/ExecuteStep.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/ExecuteStep.java @@ -25,7 +25,7 @@ public class ExecuteStep implements Step { @Override public Result execute(C context) { - ExecutionOutcome outcome = context.getWork().execute(context); + ExecutionOutcome outcome = context.getWork().execute(context.getChanges()); return new Result() { @Override public Try getOutcome() { diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/ResolveChangesStep.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/ResolveChangesStep.java index 4c8d7d5de098a..42edfbd308f6b 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/ResolveChangesStep.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/ResolveChangesStep.java @@ -29,7 +29,7 @@ import org.gradle.internal.execution.history.changes.ExecutionStateChangeDetector; import org.gradle.internal.execution.history.changes.ExecutionStateChanges; import org.gradle.internal.execution.history.changes.InputChangesInternal; -import org.gradle.internal.execution.history.impl.NonIncrementalInputChanges; +import org.gradle.internal.execution.history.changes.NonIncrementalInputChanges; import javax.annotation.Nullable; import java.util.Optional; @@ -63,7 +63,8 @@ public R execute(IncrementalContext context) { afterPreviousExecution, beforeExecution, work, - !work.isAllowOverlappingOutputs()) + !work.isAllowOverlappingOutputs(), + work) ) .orElseGet(() -> new RebuildExecutionStateChanges(NO_HISTORY, beforeExecution, work)) ) diff --git a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/ResolveChangesStepTest.groovy b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/ResolveChangesStepTest.groovy index 9557ccbc45c0f..a2c03bb531e36 100644 --- a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/ResolveChangesStepTest.groovy +++ b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/ResolveChangesStepTest.groovy @@ -117,7 +117,7 @@ class ResolveChangesStepTest extends StepSpec { 1 * context.beforeExecutionState >> Optional.of(beforeExecutionState) 1 * context.afterPreviousExecutionState >> Optional.of(afterPreviousExecutionState) 1 * work.allowOverlappingOutputs >> true - 1 * changeDetector.detectChanges(afterPreviousExecutionState, beforeExecutionState, work, false) >> changes + 1 * changeDetector.detectChanges(afterPreviousExecutionState, beforeExecutionState, work, false, work) >> changes 0 * _ } From e8c26f20ca9ad9b3fc05613c64f3c3bb5fe3e578 Mon Sep 17 00:00:00 2001 From: "Rodrigo B. de Oliveira" Date: Tue, 12 Mar 2019 19:23:13 -0300 Subject: [PATCH 499/853] Polish `KotlinScriptDependenciesResolverTest` --- .../KotlinScriptDependenciesResolverTest.kt | 28 ++++++++----------- 1 file changed, 11 insertions(+), 17 deletions(-) diff --git a/subprojects/kotlin-dsl/src/integTest/kotlin/org/gradle/kotlin/dsl/resolver/KotlinScriptDependenciesResolverTest.kt b/subprojects/kotlin-dsl/src/integTest/kotlin/org/gradle/kotlin/dsl/resolver/KotlinScriptDependenciesResolverTest.kt index c536229009514..13386afb8f711 100644 --- a/subprojects/kotlin-dsl/src/integTest/kotlin/org/gradle/kotlin/dsl/resolver/KotlinScriptDependenciesResolverTest.kt +++ b/subprojects/kotlin-dsl/src/integTest/kotlin/org/gradle/kotlin/dsl/resolver/KotlinScriptDependenciesResolverTest.kt @@ -31,7 +31,7 @@ import org.hamcrest.Matcher import org.junit.Assert.assertSame import org.junit.Assert.assertThat import org.junit.Assert.assertTrue - +import org.junit.Before import org.junit.Test import java.io.File @@ -46,17 +46,21 @@ import kotlin.script.dependencies.ScriptDependenciesResolver.ReportSeverity class KotlinScriptDependenciesResolverTest : AbstractKotlinIntegrationTest() { + @Before + fun setUpSettings() { + + withDefaultSettings() + } + @Test fun `succeeds with no script`() { - withDefaultSettings() assertSucceeds() } @Test fun `succeeds on init script`() { - withDefaultSettings() assertSucceeds(withFile("my.init.gradle.kts", """ require(this is Gradle) """)) @@ -79,7 +83,6 @@ class KotlinScriptDependenciesResolverTest : AbstractKotlinIntegrationTest() { @Test fun `succeeds on project script`() { - withDefaultSettings() assertSucceeds(withFile("build.gradle.kts", """ require(this is Project) """)) @@ -96,8 +99,6 @@ class KotlinScriptDependenciesResolverTest : AbstractKotlinIntegrationTest() { withKotlinBuildSrc() - withDefaultSettings() - assertSucceeds(withFile("buildSrc/src/main/kotlin/my-plugin.init.gradle.kts", """ require(this is Gradle) """)) @@ -108,7 +109,7 @@ class KotlinScriptDependenciesResolverTest : AbstractKotlinIntegrationTest() { withKotlinBuildSrc() - withSettings(""" + withDefaultSettings().appendText(""" apply(plugin = "my-plugin") """) @@ -122,7 +123,6 @@ class KotlinScriptDependenciesResolverTest : AbstractKotlinIntegrationTest() { withKotlinBuildSrc() - withDefaultSettings() withBuildScript(""" plugins { id("my-plugin") @@ -138,7 +138,6 @@ class KotlinScriptDependenciesResolverTest : AbstractKotlinIntegrationTest() { fun `report file fatality on TAPI failure`() { // thus disabling syntax highlighting - withDefaultSettings() val editedScript = withBuildScript("") val wrongEnv = arrayOf("gradleHome" to existing("absent")) @@ -155,7 +154,6 @@ class KotlinScriptDependenciesResolverTest : AbstractKotlinIntegrationTest() { @Test fun `report file error on TAPI failure when reusing previous dependencies`() { - withDefaultSettings() val editedScript = withBuildScript("") val previous = resolvedScriptDependencies(editedScript).apply { @@ -182,7 +180,6 @@ class KotlinScriptDependenciesResolverTest : AbstractKotlinIntegrationTest() { BOOM """) - withDefaultSettings() val editedScript = withBuildScript("") resolvedScriptDependencies(editedScript).apply { @@ -201,7 +198,6 @@ class KotlinScriptDependenciesResolverTest : AbstractKotlinIntegrationTest() { withKotlinBuildSrc() val buildSrcKotlinSource = withFile("buildSrc/src/main/kotlin/Foo.kt", "") - withDefaultSettings() val editedScript = withBuildScript("") val previous = resolvedScriptDependencies(editedScript).apply { @@ -224,7 +220,6 @@ class KotlinScriptDependenciesResolverTest : AbstractKotlinIntegrationTest() { fun `do not report file warning on script compilation failure in currently edited script`() { // because the IDE already provides user feedback for those - withDefaultSettings() val editedScript = withBuildScript(""" doNotExists() """) @@ -242,7 +237,7 @@ class KotlinScriptDependenciesResolverTest : AbstractKotlinIntegrationTest() { @Test fun `report file warning on script compilation failure in another script`() { - withSettings(""" + withDefaultSettings().appendText(""" include("a", "b") """) withBuildScript("") @@ -263,7 +258,7 @@ class KotlinScriptDependenciesResolverTest : AbstractKotlinIntegrationTest() { @Test fun `report file warning on runtime failure in currently edited script`() { - withDefaultSettings() + val editedScript = withBuildScript(""" configurations.getByName("doNotExists") """) @@ -281,7 +276,6 @@ class KotlinScriptDependenciesResolverTest : AbstractKotlinIntegrationTest() { @Test fun `report line warning on runtime failure in currently edited script when location aware hints are enabled`() { - withDefaultSettings() withFile("gradle.properties", """ ${EditorReports.locationAwareEditorHintsPropertyName}=true """) @@ -302,7 +296,7 @@ class KotlinScriptDependenciesResolverTest : AbstractKotlinIntegrationTest() { @Test fun `report file warning on runtime failure in another script`() { - withSettings(""" + withDefaultSettings().appendText(""" include("a", "b") """) withBuildScript("") From f95e23427cddfb3141d92d6dd5aca8c327047643 Mon Sep 17 00:00:00 2001 From: "Rodrigo B. de Oliveira" Date: Tue, 12 Mar 2019 19:45:05 -0300 Subject: [PATCH 500/853] Let Kotlin DSL resolver return given Java home Resolves gradle/kotlin-dsl#1354 --- .../KotlinScriptDependenciesResolverTest.kt | 12 +++++++++++ .../KotlinBuildScriptDependenciesResolver.kt | 20 ++++++++++--------- 2 files changed, 23 insertions(+), 9 deletions(-) diff --git a/subprojects/kotlin-dsl/src/integTest/kotlin/org/gradle/kotlin/dsl/resolver/KotlinScriptDependenciesResolverTest.kt b/subprojects/kotlin-dsl/src/integTest/kotlin/org/gradle/kotlin/dsl/resolver/KotlinScriptDependenciesResolverTest.kt index 13386afb8f711..19903fc6ae883 100644 --- a/subprojects/kotlin-dsl/src/integTest/kotlin/org/gradle/kotlin/dsl/resolver/KotlinScriptDependenciesResolverTest.kt +++ b/subprojects/kotlin-dsl/src/integTest/kotlin/org/gradle/kotlin/dsl/resolver/KotlinScriptDependenciesResolverTest.kt @@ -58,6 +58,18 @@ class KotlinScriptDependenciesResolverTest : AbstractKotlinIntegrationTest() { assertSucceeds() } + @Test + fun `returns given Java home`() { + + val javaHome = System.getProperty("java.home") + val env = arrayOf("gradleJavaHome" to javaHome) + assertThat( + resolvedScriptDependencies(env = *env)?.javaHome, + equalTo(javaHome) + ) + } + + @Test fun `succeeds on init script`() { diff --git a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/resolver/KotlinBuildScriptDependenciesResolver.kt b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/resolver/KotlinBuildScriptDependenciesResolver.kt index 7fce79031c470..971cc3f924cf5 100644 --- a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/resolver/KotlinBuildScriptDependenciesResolver.kt +++ b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/resolver/KotlinBuildScriptDependenciesResolver.kt @@ -139,12 +139,12 @@ class KotlinBuildScriptDependenciesResolver @VisibleForTesting constructor( previousDependencies: KotlinScriptExternalDependencies? ): KotlinScriptExternalDependencies? { - val scriptModelRequest = scriptModelRequestFrom(scriptFile, environment, cid) - log(SubmittedModelRequest(cid, scriptFile, scriptModelRequest)) + val request = scriptModelRequestFrom(scriptFile, environment, cid) + log(SubmittedModelRequest(cid, scriptFile, request)) - val response = DefaultKotlinBuildScriptModelRepository.scriptModelFor(scriptModelRequest) + val response = DefaultKotlinBuildScriptModelRepository.scriptModelFor(request) if (response == null) { - log(RequestCancelled(cid, scriptFile, scriptModelRequest)) + log(RequestCancelled(cid, scriptFile, request)) return null } log(ReceivedModelResponse(cid, scriptFile, response)) @@ -155,7 +155,7 @@ class KotlinBuildScriptDependenciesResolver @VisibleForTesting constructor( return when { response.exceptions.isEmpty() -> - dependenciesFrom(response).also { + dependenciesFrom(request, response).also { log(ResolvedDependencies(cid, scriptFile, it)) } previousDependencies != null && previousDependencies.classpath.count() > response.classPath.size -> @@ -163,7 +163,7 @@ class KotlinBuildScriptDependenciesResolver @VisibleForTesting constructor( log(ResolvedToPreviousWithErrors(cid, scriptFile, previousDependencies, response.exceptions)) } else -> - dependenciesFrom(response).also { + dependenciesFrom(request, response).also { log(ResolvedDependenciesWithErrors(cid, scriptFile, it, response.exceptions)) } } @@ -207,11 +207,12 @@ class KotlinBuildScriptDependenciesResolver @VisibleForTesting constructor( ?: GradleInstallation.Wrapper private - fun dependenciesFrom(response: KotlinBuildScriptModel) = + fun dependenciesFrom(request: KotlinBuildScriptModelRequest, response: KotlinBuildScriptModel) = KotlinBuildScriptDependencies( response.classPath, response.sourcePath, - response.implicitImports + response.implicitImports, + request.javaHome?.path ) } @@ -220,7 +221,8 @@ internal class KotlinBuildScriptDependencies( override val classpath: Iterable, override val sources: Iterable, - override val imports: Iterable + override val imports: Iterable, + override val javaHome: String? = null ) : KotlinScriptExternalDependencies From fadddde59683004637540e3f35238cd6e4cfa92d Mon Sep 17 00:00:00 2001 From: Sterling Greene Date: Tue, 12 Mar 2019 18:21:49 -0400 Subject: [PATCH 501/853] Use proper replacement tokens in release notes and template --- subprojects/docs/src/docs/release/notes-template.md | 10 ++++------ subprojects/docs/src/docs/release/notes.md | 12 +++++------- 2 files changed, 9 insertions(+), 13 deletions(-) diff --git a/subprojects/docs/src/docs/release/notes-template.md b/subprojects/docs/src/docs/release/notes-template.md index 3ce4d2ff63e43..1045880aa6246 100644 --- a/subprojects/docs/src/docs/release/notes-template.md +++ b/subprojects/docs/src/docs/release/notes-template.md @@ -1,4 +1,4 @@ -The Gradle team is excited to announce Gradle {gradleVersion}. +The Gradle team is excited to announce Gradle @version@. This release features [1](), [2](), ... [n](), and more. @@ -22,11 +22,9 @@ details of 2 ## Upgrade Instructions -Switch your build to use Gradle {gradleVersion} by updating your wrapper properties: +Switch your build to use Gradle @version@ by updating your wrapper: -`./gradlew wrapper --gradle-version={gradleVersion}` - -Standalone downloads are available at [gradle.org/releases](https://gradle.org/releases). +`./gradlew wrapper --gradle-version=@version@` ## Promoted features Promoted features are features that were incubating in previous versions of Gradle but are now supported and subject to backwards compatibility. @@ -59,7 +57,7 @@ The following are the newly deprecated items in this Gradle release. If you have -See the [Gradle 5.x upgrade guide](userguide/upgrading_version_5.html#changes_{gradleVersion}) to learn about breaking changes and considerations when upgrading to Gradle {gradleVersion}. +See the [Gradle 5.x upgrade guide](userguide/upgrading_version_5.html#changes_@baseVersion@) to learn about breaking changes and considerations when upgrading to Gradle @version@. diff --git a/subprojects/docs/src/docs/release/notes.md b/subprojects/docs/src/docs/release/notes.md index 2dba45d459e5f..3bd2ca61c227e 100644 --- a/subprojects/docs/src/docs/release/notes.md +++ b/subprojects/docs/src/docs/release/notes.md @@ -1,4 +1,4 @@ -The Gradle team is excited to announce Gradle 5.3. +The Gradle team is excited to announce Gradle @version@. This release features support for publishing and consuming Gradle Module Metadata, [feature variants or "optional dependencies"](#feature-variants), @@ -20,11 +20,9 @@ and [Josh Soref](https://github.com/jsoref). ## Upgrade Instructions -Switch your build to use Gradle 5.3 RC1 by updating your wrapper properties: +Switch your build to use Gradle @version@ by updating your wrapper: -`./gradlew wrapper --gradle-version=5.3-rc-1` - -Standalone downloads are available at [gradle.org/release-candidate](https://gradle.org/release-candidate). +`./gradlew wrapper --gradle-version=@version@` @@ -79,7 +77,7 @@ Please see the [Kotlin 1.3.21 announcement](https://github.com/JetBrains/kotlin/ ### Type-safe accessors in precompiled script plugins -Starting with Gradle 5.3, Kotlin precompiled project script plugins now have type-safe accessors, just like regular project build scripts. +Starting with Gradle @version@, Kotlin precompiled project script plugins now have type-safe accessors, just like regular project build scripts. For example, here is how an hypothetical plugin that sets up a Java project according to some convention would be written as a Kotlin precompiled project script plugin in `buildSrc`: @@ -209,7 +207,7 @@ The method `ProjectLayout.configurableFiles()` is now deprecated, and will be re -See the [Gradle 5.x upgrade guide](userguide/upgrading_version_5.html#changes_5.3) to learn about breaking changes and considerations when upgrading to Gradle 5.3. +See the [Gradle 5.x upgrade guide](userguide/upgrading_version_5.html#changes_@baseVersion@) to learn about breaking changes and considerations when upgrading to Gradle @version@. From 78cd428ff88d8c35110c2ebe9248263a62c6913e Mon Sep 17 00:00:00 2001 From: Louis Jacomet Date: Tue, 12 Mar 2019 18:33:09 +0100 Subject: [PATCH 502/853] Temporary ignore of samples relying on spring repo The repository is currently inaccessible. --- .../SamplesDeclaringDependenciesIntegrationTest.groovy | 2 ++ ...ubleshootingDependencyResolutionIntegrationTest.groovy | 8 +++++--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/samples/dependencymanagement/SamplesDeclaringDependenciesIntegrationTest.groovy b/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/samples/dependencymanagement/SamplesDeclaringDependenciesIntegrationTest.groovy index 504534d83bcc2..cc4e5ae4515fc 100644 --- a/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/samples/dependencymanagement/SamplesDeclaringDependenciesIntegrationTest.groovy +++ b/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/samples/dependencymanagement/SamplesDeclaringDependenciesIntegrationTest.groovy @@ -22,6 +22,7 @@ import org.gradle.integtests.fixtures.UsesSample import org.gradle.test.fixtures.file.TestFile import org.gradle.util.Requires import org.junit.Rule +import spock.lang.Ignore import spock.lang.Unroll import static org.gradle.util.TestPrecondition.KOTLIN_SCRIPT @@ -82,6 +83,7 @@ class SamplesDeclaringDependenciesIntegrationTest extends AbstractSampleIntegrat dsl << ['groovy', 'kotlin'] } + @Ignore("Spring repo down and not mirrored") @Unroll @UsesSample("userguide/dependencyManagement/declaringDependencies/changingVersion") def "can use declare and resolve dependency with changing version with #dsl dsl"() { diff --git a/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/samples/dependencymanagement/SamplesTroubleshootingDependencyResolutionIntegrationTest.groovy b/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/samples/dependencymanagement/SamplesTroubleshootingDependencyResolutionIntegrationTest.groovy index 0f534430ae7ed..8561a9b8ac68a 100644 --- a/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/samples/dependencymanagement/SamplesTroubleshootingDependencyResolutionIntegrationTest.groovy +++ b/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/samples/dependencymanagement/SamplesTroubleshootingDependencyResolutionIntegrationTest.groovy @@ -20,6 +20,7 @@ import org.gradle.integtests.fixtures.AbstractSampleIntegrationTest import org.gradle.integtests.fixtures.Sample import org.gradle.integtests.fixtures.UsesSample import org.junit.Rule +import spock.lang.Ignore import spock.lang.Unroll class SamplesTroubleshootingDependencyResolutionIntegrationTest extends AbstractSampleIntegrationTest { @@ -29,9 +30,10 @@ class SamplesTroubleshootingDependencyResolutionIntegrationTest extends Abstract @Rule Sample sample = new Sample(testDirectoryProvider) + @Ignore("Spring repo down and not mirrored") @Unroll @UsesSample("userguide/dependencyManagement/troubleshooting/cache/changing") - def "can declare custom TTL for dependency with dynamic version"() { + def "can declare custom TTL for dependency with changing version"() { given: def sampleDir = sample.dir.file(dsl) @@ -48,8 +50,8 @@ class SamplesTroubleshootingDependencyResolutionIntegrationTest extends Abstract } @Unroll - @UsesSample("userguide/dependencyManagement/troubleshooting/cache/changing") - def "can declare custom TTL for dependency with changing version"() { + @UsesSample("userguide/dependencyManagement/troubleshooting/cache/dynamic") + def "can declare custom TTL for dependency with dynamic version"() { given: def sampleDir = sample.dir.file(dsl) From 981a9fd831299cdb6d1a3ee63eee4e3e445071d7 Mon Sep 17 00:00:00 2001 From: Louis Jacomet Date: Tue, 12 Mar 2019 16:03:59 +0100 Subject: [PATCH 503/853] Restore JavaExecHandleBuilder.classpath contract The contract is to append the passed in parameters to the existing classpath. This was broken in refactoring and instead would behave as if JavaExecHandleBuilder.setClasspath had been called. Issue #8748 --- .../internal/JavaExecHandleBuilder.java | 2 +- .../internal/JavaExecHandleBuilderTest.groovy | 38 ++++++++++++++++++- 2 files changed, 37 insertions(+), 3 deletions(-) diff --git a/subprojects/core/src/main/java/org/gradle/process/internal/JavaExecHandleBuilder.java b/subprojects/core/src/main/java/org/gradle/process/internal/JavaExecHandleBuilder.java index 27801c337567b..f45fdebb39005 100644 --- a/subprojects/core/src/main/java/org/gradle/process/internal/JavaExecHandleBuilder.java +++ b/subprojects/core/src/main/java/org/gradle/process/internal/JavaExecHandleBuilder.java @@ -212,7 +212,7 @@ public JavaExecHandleBuilder setClasspath(FileCollection classpath) { } public JavaExecHandleBuilder classpath(Object... paths) { - doGetClasspath().setFrom(paths); + doGetClasspath().from(paths); return this; } diff --git a/subprojects/core/src/test/groovy/org/gradle/process/internal/JavaExecHandleBuilderTest.groovy b/subprojects/core/src/test/groovy/org/gradle/process/internal/JavaExecHandleBuilderTest.groovy index fde428621e47c..a8c958e35d881 100644 --- a/subprojects/core/src/test/groovy/org/gradle/process/internal/JavaExecHandleBuilderTest.groovy +++ b/subprojects/core/src/test/groovy/org/gradle/process/internal/JavaExecHandleBuilderTest.groovy @@ -15,6 +15,8 @@ */ package org.gradle.process.internal +import org.gradle.api.internal.file.DefaultFileCollectionFactory +import org.gradle.api.internal.file.FileCollectionFactory import org.gradle.api.internal.file.TestFiles import org.gradle.initialization.DefaultBuildCancellationToken import org.gradle.internal.jvm.Jvm @@ -29,7 +31,9 @@ import static java.util.Arrays.asList class JavaExecHandleBuilderTest extends Specification { JavaExecHandleBuilder builder = new JavaExecHandleBuilder(TestFiles.resolver(), TestFiles.fileCollectionFactory(), Mock(Executor), new DefaultBuildCancellationToken()) - public void cannotSetAllJvmArgs() { + FileCollectionFactory fileCollectionFactory = new DefaultFileCollectionFactory() + + def cannotSetAllJvmArgs() { when: builder.setAllJvmArgs(asList("arg")) @@ -38,7 +42,7 @@ class JavaExecHandleBuilderTest extends Specification { } @Unroll("buildsCommandLineForJavaProcess - input encoding #inputEncoding") - public void buildsCommandLineForJavaProcess() { + def buildsCommandLineForJavaProcess() { File jar1 = new File("file1.jar").canonicalFile File jar2 = new File("file2.jar").canonicalFile @@ -70,6 +74,36 @@ class JavaExecHandleBuilderTest extends Specification { "UTF-16" | "UTF-16" } + def "can append to classpath"() { + given: + File jar1 = new File("file1.jar").canonicalFile + File jar2 = new File("file2.jar").canonicalFile + + builder.classpath(jar1) + + when: + builder.classpath(jar2) + + then: + builder.classpath.contains(jar1) + builder.classpath.contains(jar2) + } + + def "can replace classpath"() { + given: + File jar1 = new File("file1.jar").canonicalFile + File jar2 = new File("file2.jar").canonicalFile + + builder.classpath(jar1) + + when: + builder.setClasspath(fileCollectionFactory.resolving(jar2)) + + then: + !builder.classpath.contains(jar1) + builder.classpath.contains(jar2) + } + def "detects null entries early"() { when: builder.args(1, null) then: thrown(IllegalArgumentException) From c467e825b24f60317fa23b0541bee1204303530b Mon Sep 17 00:00:00 2001 From: Sterling Greene Date: Tue, 12 Mar 2019 19:30:21 -0400 Subject: [PATCH 504/853] Remove other package managers --- .../docs/src/docs/userguide/installation.adoc | 29 +++---------------- 1 file changed, 4 insertions(+), 25 deletions(-) diff --git a/subprojects/docs/src/docs/userguide/installation.adoc b/subprojects/docs/src/docs/userguide/installation.adoc index fb3b16e0680c1..04bda07ee6b7d 100644 --- a/subprojects/docs/src/docs/userguide/installation.adoc +++ b/subprojects/docs/src/docs/userguide/installation.adoc @@ -16,7 +16,7 @@ = Installing Gradle You can install the Gradle build tool on Linux, macOS, or Windows. -This document covers installing using a package manager like SDKMAN!, Homebrew, or Scoop, as well as manual installation. +This document covers installing using a package manager like SDKMAN! or Homebrew, as well as manual installation. Use of the <> is the recommended way to upgrade Gradle. @@ -39,7 +39,7 @@ Gradle uses whatever JDK it finds in your path. Alternatively, you can set the ` == Installing with a package manager -link:http://sdkman.io[SDKMAN!] is a tool for managing parallel versions of multiple Software Development Kits on most Unix-based systems. +link:http://sdkman.io[SDKMAN!] is a tool for managing parallel versions of multiple Software Development Kits on most Unix-like systems (macOS, Linux, Cygwin, Solaris and FreeBSD). We deploy and maintain the versions available from SDKMAN!. ---- ❯ sdk install gradle @@ -51,23 +51,7 @@ link:http://brew.sh[Homebrew] is "the missing package manager for macOS". ❯ brew install gradle ---- -link:http://scoop.sh[Scoop] is a command-line installer for Windows inspired by Homebrew. - ----- -❯ scoop install gradle ----- - -link:https://chocolatey.org[Chocolatey] is "the package manager for Windows". - ----- -❯ choco install gradle ----- - -link:https://www.macports.org[MacPorts] is a system for managing tools on macOS: - ----- -❯ sudo port install gradle ----- +Other package managers are available, but the version of Gradle distributed by them is not controlled by Gradle, Inc. Linux package managers may distribute a modified version of Gradle that is incompatible or incomplete when compared to the official version (available from SDKMAN! or below). <<#sec:installation_next_steps,↓ Proceed to next steps>> @@ -140,13 +124,8 @@ Open a console (or a Windows command prompt) and run `gradle -v` to run gradle a Gradle {gradleVersion} ------------------------------------------------------------ -Build time: 2018-02-21 15:28:42 UTC -Revision: 819e0059da49f469d3e9b2896dc4e72537c4847d +(environment specific information) -Groovy: 2.4.15 -Ant: Apache Ant(TM) version 1.9.9 compiled on February 2 2017 -JVM: 1.8.0_151 (Oracle Corporation 25.151-b12) -OS: Mac OS X 10.13.3 x86_64 ---- If you run into any trouble, see the <>. From f8bfb53739bc66f38bd2571964790d3986bc8a15 Mon Sep 17 00:00:00 2001 From: "Rodrigo B. de Oliveira" Date: Tue, 12 Mar 2019 22:12:49 -0300 Subject: [PATCH 505/853] Don't star import Kotlin DSL subpackages --- .idea/codeStyles/Project.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml index 7d467a0fdf1ad..b1223ec682481 100644 --- a/.idea/codeStyles/Project.xml +++ b/.idea/codeStyles/Project.xml @@ -32,7 +32,7 @@ From 35a8e41e78c3a96b4167c7c4ee2734e48777300f Mon Sep 17 00:00:00 2001 From: Gradleware Git Bot Date: Wed, 13 Mar 2019 02:22:46 +0100 Subject: [PATCH 506/853] Publish 5.3-20190313010512+0000 --- released-versions.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/released-versions.json b/released-versions.json index 4cd37e6fe6308..4033adb61426c 100644 --- a/released-versions.json +++ b/released-versions.json @@ -1,7 +1,7 @@ { "latestReleaseSnapshot": { - "version": "5.3-20190312011340+0000", - "buildTime": "20190312011340+0000" + "version": "5.3-20190313010512+0000", + "buildTime": "20190313010512+0000" }, "latestRc": { "version": "5.3-rc-2", From a6bf1ca809d0b8588564ea7e60402205e6e50d85 Mon Sep 17 00:00:00 2001 From: "Rodrigo B. de Oliveira" Date: Wed, 13 Mar 2019 00:20:12 -0300 Subject: [PATCH 507/853] Prefer `precompiled` spelling for consistency with the existing docs Signed-off-by: Rodrigo B. de Oliveira --- subprojects/docs/src/docs/release/notes.md | 2 +- subprojects/docs/src/docs/release/release-features.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/subprojects/docs/src/docs/release/notes.md b/subprojects/docs/src/docs/release/notes.md index 3bd2ca61c227e..b66aaa83f5bdf 100644 --- a/subprojects/docs/src/docs/release/notes.md +++ b/subprojects/docs/src/docs/release/notes.md @@ -2,7 +2,7 @@ The Gradle team is excited to announce Gradle @version@. This release features support for publishing and consuming Gradle Module Metadata, [feature variants or "optional dependencies"](#feature-variants), -[type-safe accessors in Kotlin pre-compiled script plugins](#type-safe-accessors-in-precompiled-script-plugins), and more. +[type-safe accessors in Kotlin precompiled script plugins](#type-safe-accessors-in-precompiled-script-plugins), and more. We would like to thank the following community contributors to this release of Gradle: diff --git a/subprojects/docs/src/docs/release/release-features.txt b/subprojects/docs/src/docs/release/release-features.txt index 6f466d0b4d7cb..a47d337af97b8 100644 --- a/subprojects/docs/src/docs/release/release-features.txt +++ b/subprojects/docs/src/docs/release/release-features.txt @@ -1,3 +1,3 @@ - Feature variants AKA "optional dependencies" - - Type-safe accessors in Kotlin pre-compiled script plugins + - Type-safe accessors in Kotlin precompiled script plugins - Gradle Module Metadata 1.0 From 1250c3a53b1ae9e3b507af52b338f5cf79379abf Mon Sep 17 00:00:00 2001 From: "Rodrigo B. de Oliveira" Date: Wed, 13 Mar 2019 01:53:11 -0300 Subject: [PATCH 508/853] Remove the API parameter names JARs In order to enable code navigation and refactoring across Kotlin DSL project boundaries. The need for parameter names JARs has been mitigated by removing usages of Kotlin interface delegation from the public API and implementing the required interfaces explicitly. Resolves #1360 --- .../build/AddGradleApiParameterNames.kt | 238 --------- .../kotlin-dsl-plugins.gradle.kts | 4 +- .../kotlin-dsl-provider-plugins.gradle.kts | 8 +- .../kotlin-dsl-tooling-builders.gradle.kts | 4 +- subprojects/kotlin-dsl/kotlin-dsl.gradle.kts | 5 +- .../gradle/kotlin/dsl/ArtifactHandlerScope.kt | 7 +- .../dsl/DependencyConstraintHandlerScope.kt | 7 +- .../kotlin/dsl/DependencyHandlerScope.kt | 7 +- .../gradle/kotlin/dsl/KotlinBuildScript.kt | 6 +- .../org/gradle/kotlin/dsl/KotlinInitScript.kt | 5 +- .../gradle/kotlin/dsl/KotlinSettingsScript.kt | 5 +- .../NamedDomainObjectContainerExtensions.kt | 16 +- .../kotlin/dsl/PluginDependenciesSpecScope.kt | 8 +- .../gradle/kotlin/dsl/ScriptHandlerScope.kt | 7 +- .../precompile/PrecompiledProjectScript.kt | 5 +- .../kotlin/dsl/support/KotlinPluginsBlock.kt | 6 +- .../decorators/ArtifactHandlerDecorator.kt | 40 ++ .../DependencyConstraintHandlerDecorator.kt | 52 ++ .../decorators/DependencyHandlerDecorator.kt | 121 +++++ .../dsl/support/decorators/GradleDecorator.kt | 153 ++++++ .../NamedDomainObjectContainerDecorator.kt | 189 ++++++++ .../support/decorators/ProjectDecorator.kt | 456 ++++++++++++++++++ .../decorators/ScriptHandlerDecorator.kt | 59 +++ .../support/decorators/SettingsDecorator.kt | 127 +++++ 24 files changed, 1265 insertions(+), 270 deletions(-) delete mode 100644 buildSrc/subprojects/kotlin-dsl/src/main/kotlin/build/AddGradleApiParameterNames.kt create mode 100644 subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/decorators/ArtifactHandlerDecorator.kt create mode 100644 subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/decorators/DependencyConstraintHandlerDecorator.kt create mode 100644 subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/decorators/DependencyHandlerDecorator.kt create mode 100644 subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/decorators/GradleDecorator.kt create mode 100644 subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/decorators/NamedDomainObjectContainerDecorator.kt create mode 100644 subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/decorators/ProjectDecorator.kt create mode 100644 subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/decorators/ScriptHandlerDecorator.kt create mode 100644 subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/decorators/SettingsDecorator.kt diff --git a/buildSrc/subprojects/kotlin-dsl/src/main/kotlin/build/AddGradleApiParameterNames.kt b/buildSrc/subprojects/kotlin-dsl/src/main/kotlin/build/AddGradleApiParameterNames.kt deleted file mode 100644 index eb51a99b30163..0000000000000 --- a/buildSrc/subprojects/kotlin-dsl/src/main/kotlin/build/AddGradleApiParameterNames.kt +++ /dev/null @@ -1,238 +0,0 @@ -/* - * Copyright 2018 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package build - -import accessors.sourceSets -import org.gradle.api.Project -import org.gradle.api.artifacts.transform.InputArtifact -import org.gradle.api.artifacts.transform.TransformAction -import org.gradle.api.artifacts.transform.TransformOutputs -import org.gradle.api.artifacts.transform.TransformParameters -import org.gradle.api.attributes.Attribute -import org.gradle.api.file.RelativePath -import org.gradle.api.tasks.Input -import org.gradle.api.tasks.PathSensitive -import org.gradle.api.tasks.PathSensitivity -import org.gradle.gradlebuild.PublicApi -import org.gradle.kotlin.dsl.* - -import org.gradle.kotlin.dsl.codegen.ParameterNamesSupplier -import org.gradle.kotlin.dsl.codegen.parameterNamesFor - -import org.gradle.kotlin.dsl.support.GradleApiMetadata - -import org.objectweb.asm.ClassReader -import org.objectweb.asm.ClassVisitor -import org.objectweb.asm.ClassWriter -import org.objectweb.asm.MethodVisitor -import org.objectweb.asm.Opcodes.ASM6 -import org.objectweb.asm.Type -import java.io.File -import java.io.InputStream -import java.util.Properties -import java.util.jar.JarEntry -import java.util.jar.JarFile -import java.util.zip.ZipOutputStream - - -// TODO:kotlin-dsl dedupe, see MinifyPlugin -private -val minified = Attribute.of("minified", Boolean::class.javaObjectType) - - -fun Project.withCompileOnlyGradleApiModulesWithParameterNames(vararg gradleModuleNames: String) { - - val artifactType = Attribute.of("artifactType", String::class.java) - val jarWithGradleApiParameterNames = "jar-with-gradle-api-parameter-names" - - val gradleApiWithParameterNames by configurations.registering { - attributes { - attribute(artifactType, jarWithGradleApiParameterNames) - } - } - - dependencies { - registerTransform(AddGradleApiParameterNames::class) { - from.attribute(artifactType, "jar").attribute(minified, true) - to.attribute(artifactType, jarWithGradleApiParameterNames) - parameters { - publicApiIncludes = PublicApi.includes - publicApiExcludes = PublicApi.excludes - } - } - - for (gradleModuleName in gradleModuleNames) { - gradleApiWithParameterNames.name(project(gradleModuleName)) - } - } - - sourceSets { - "main" { - compileClasspath += gradleApiWithParameterNames.get() - } - } -} - - -internal -abstract class AddGradleApiParameterNames : TransformAction { - - interface Parameters : TransformParameters { - @get:Input - var publicApiIncludes: List - @get:Input - var publicApiExcludes: List - } - - @get:PathSensitive(PathSensitivity.NAME_ONLY) - @get:InputArtifact - abstract val input: File - - override fun transform(outputs: TransformOutputs) { - if (input.name.startsWith("gradle-")) { - transformGradleApiJar(input, outputs.file(outputFileNameFor(input))) - } else { - outputs.file(input) - } - } - - private - fun outputFileNameFor(input: File) = - "${input.nameWithoutExtension}-with-parameter-names.jar" - - private - fun transformGradleApiJar(inputFile: File, outputFile: File) { - JarFile(inputFile).use { inputJar -> - val gradleApiMetadata = gradleApiMetadataFor(inputFile.gradleModuleName, inputJar) - writingJar(outputFile) { zipOutputStream -> - transformGradleApiJarEntries(gradleApiMetadata, inputJar, zipOutputStream) - } - } - } - - private - fun writingJar(outputJarFile: File, action: (ZipOutputStream) -> Unit) { - outputJarFile.outputStream().buffered().use { fileStream -> - ZipOutputStream(fileStream).use(action) - } - } - - private - fun transformGradleApiJarEntries(gradleApiMetadata: GradleApiMetadata, inputJar: JarFile, zipOutputStream: ZipOutputStream) { - inputJar.entries().asSequence().filterNot { it.isDirectory }.forEach { entry -> - if (gradleApiMetadata.isGradleApi(entry)) inputJar.transformJarEntry(gradleApiMetadata, entry, zipOutputStream) - else inputJar.copyJarEntry(entry, zipOutputStream) - } - } - - private - fun gradleApiMetadataFor(moduleName: String, inputJar: JarFile): GradleApiMetadata { - val parameterNamesIndex = Properties().apply { - inputJar.getJarEntry("$moduleName-parameter-names.properties")?.let { entry -> - inputJar.getInputStream(entry).buffered().use { input -> load(input) } - } - } - return GradleApiMetadata( - parameters.publicApiIncludes, - parameters.publicApiExcludes, - { key: String -> parameterNamesIndex.getProperty(key, null)?.split(",") } - ) - } - - private - fun GradleApiMetadata.isGradleApi(entry: JarEntry) = - entry.name.endsWith(".class") - && !entry.name.endsWith("package-info.class") - && spec.isSatisfiedBy(RelativePath.parse(true, entry.name)) - - private - fun JarFile.transformJarEntry(gradleApiMetadata: GradleApiMetadata, entry: JarEntry, zipOutputStream: ZipOutputStream) { - getInputStream(entry).buffered().use { input -> - zipOutputStream.run { - putNextEntry(JarEntry(entry.name)) - write(transformClass(gradleApiMetadata, input)) - closeEntry() - } - } - } - - private - fun transformClass(gradleApiMetadata: GradleApiMetadata, input: InputStream): ByteArray { - val writer = ClassWriter(0) - val transformer = ParameterNamesClassVisitor(writer, gradleApiMetadata.parameterNamesSupplier) - ClassReader(input).accept(transformer, 0) - return writer.toByteArray() - } - - private - fun JarFile.copyJarEntry(entry: JarEntry, zipOutputStream: ZipOutputStream) { - getInputStream(entry).buffered().use { input -> - zipOutputStream.putNextEntry(JarEntry(entry.name)) - input.copyTo(zipOutputStream) - zipOutputStream.closeEntry() - } - } -} - - -private -val gradleModuleNameRegex = Regex("-\\d.*") - - -private -val File.gradleModuleName: String - get() = nameWithoutExtension.replace(gradleModuleNameRegex, "") - - -private -class ParameterNamesClassVisitor( - delegate: ClassVisitor, - private val parameterNamesSupplier: ParameterNamesSupplier -) : ClassVisitor(ASM6, delegate) { - - private - lateinit var typeName: String - - override fun visit(version: Int, access: Int, name: String, signature: String?, superName: String?, interfaces: Array?) { - typeName = name - super.visit(version, access, name, signature, superName, interfaces) - } - - override fun visitMethod(access: Int, name: String, desc: String, signature: String?, exceptions: Array?): MethodVisitor { - return super.visitMethod(access, name, desc, signature, exceptions).apply { - parameterNamesSupplier.parameterNamesForBinaryNames(typeName, name, desc)?.forEach { parameterName -> - visitParameter(parameterName, 0) - } - } - } - - private - fun ParameterNamesSupplier.parameterNamesForBinaryNames(typeName: String, methodName: String, methodDescriptor: String) = - parameterNamesFor( - typeBinaryNameFor(typeName), - methodName, - parameterTypesBinaryNamesFor(methodDescriptor) - ) - - private - fun typeBinaryNameFor(internalName: String): String = - Type.getObjectType(internalName).className - - private - fun parameterTypesBinaryNamesFor(methodDescriptor: String) = - Type.getArgumentTypes(methodDescriptor).map { it.className } -} diff --git a/subprojects/kotlin-dsl-plugins/kotlin-dsl-plugins.gradle.kts b/subprojects/kotlin-dsl-plugins/kotlin-dsl-plugins.gradle.kts index cf2aa2477f5ee..bf24e68198bbd 100644 --- a/subprojects/kotlin-dsl-plugins/kotlin-dsl-plugins.gradle.kts +++ b/subprojects/kotlin-dsl-plugins/kotlin-dsl-plugins.gradle.kts @@ -17,7 +17,6 @@ import org.gradle.gradlebuild.test.integrationtests.IntegrationTest import org.gradle.gradlebuild.unittestandcompile.ModuleType import build.futureKotlin -import build.withCompileOnlyGradleApiModulesWithParameterNames import plugins.bundledGradlePlugin plugins { @@ -35,10 +34,9 @@ gradlebuildJava { moduleType = ModuleType.INTERNAL } -withCompileOnlyGradleApiModulesWithParameterNames(":pluginDevelopment") - dependencies { compileOnly(project(":kotlinDsl")) + compileOnly(project(":pluginDevelopment")) implementation(futureKotlin("stdlib-jdk8")) implementation(futureKotlin("gradle-plugin")) diff --git a/subprojects/kotlin-dsl-provider-plugins/kotlin-dsl-provider-plugins.gradle.kts b/subprojects/kotlin-dsl-provider-plugins/kotlin-dsl-provider-plugins.gradle.kts index 6d670b4325a3a..6899939b59b2f 100644 --- a/subprojects/kotlin-dsl-provider-plugins/kotlin-dsl-provider-plugins.gradle.kts +++ b/subprojects/kotlin-dsl-provider-plugins/kotlin-dsl-provider-plugins.gradle.kts @@ -14,7 +14,6 @@ * limitations under the License. */ -import build.withCompileOnlyGradleApiModulesWithParameterNames import org.gradle.gradlebuild.unittestandcompile.ModuleType plugins { @@ -27,10 +26,6 @@ gradlebuildJava { moduleType = ModuleType.CORE } -withCompileOnlyGradleApiModulesWithParameterNames( - ":plugins", - ":pluginDevelopment" -) dependencies { @@ -38,6 +33,9 @@ dependencies { compile(project(":kotlinDsl")) + compileOnly(project(":plugins")) + compileOnly(project(":pluginDevelopment")) + testImplementation(project(":kotlinDslTestFixtures")) testImplementation(project(":plugins")) } diff --git a/subprojects/kotlin-dsl-tooling-builders/kotlin-dsl-tooling-builders.gradle.kts b/subprojects/kotlin-dsl-tooling-builders/kotlin-dsl-tooling-builders.gradle.kts index 35d1d892e5e0b..28fdc0bc8c97f 100644 --- a/subprojects/kotlin-dsl-tooling-builders/kotlin-dsl-tooling-builders.gradle.kts +++ b/subprojects/kotlin-dsl-tooling-builders/kotlin-dsl-tooling-builders.gradle.kts @@ -14,7 +14,6 @@ * limitations under the License. */ -import build.withCompileOnlyGradleApiModulesWithParameterNames import org.gradle.gradlebuild.unittestandcompile.ModuleType plugins { @@ -27,7 +26,6 @@ gradlebuildJava { moduleType = ModuleType.CORE } -withCompileOnlyGradleApiModulesWithParameterNames(":plugins") dependencies { @@ -35,6 +33,8 @@ dependencies { compile(project(":kotlinDsl")) + compileOnly(project(":plugins")) + testImplementation(project(":kotlinDslTestFixtures")) integTestImplementation(project(":kotlinDslTestFixtures")) diff --git a/subprojects/kotlin-dsl/kotlin-dsl.gradle.kts b/subprojects/kotlin-dsl/kotlin-dsl.gradle.kts index d31958b0a47ed..9e27674eb537c 100644 --- a/subprojects/kotlin-dsl/kotlin-dsl.gradle.kts +++ b/subprojects/kotlin-dsl/kotlin-dsl.gradle.kts @@ -18,7 +18,6 @@ import org.gradle.gradlebuild.unittestandcompile.ModuleType import build.futureKotlin import build.kotlin import build.kotlinVersion -import build.withCompileOnlyGradleApiModulesWithParameterNames import codegen.GenerateKotlinDependencyExtensions plugins { @@ -31,12 +30,12 @@ gradlebuildJava { moduleType = ModuleType.CORE } -withCompileOnlyGradleApiModulesWithParameterNames(":toolingApi") - dependencies { api(project(":distributionsDependencies")) + compileOnly(project(":toolingApi")) + compile(project(":kotlinDslToolingModels")) compile(project(":kotlinCompilerEmbeddable")) diff --git a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/ArtifactHandlerScope.kt b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/ArtifactHandlerScope.kt index ff5ecb388edc6..e50957df72c44 100644 --- a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/ArtifactHandlerScope.kt +++ b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/ArtifactHandlerScope.kt @@ -21,6 +21,8 @@ import org.gradle.api.artifacts.Configuration import org.gradle.api.artifacts.PublishArtifact import org.gradle.api.artifacts.dsl.ArtifactHandler +import org.gradle.kotlin.dsl.support.decorators.ArtifactHandlerDecorator + /** * Receiver for `artifacts` block providing convenient utilities for configuring artifacts. @@ -30,7 +32,7 @@ import org.gradle.api.artifacts.dsl.ArtifactHandler class ArtifactHandlerScope private constructor( val artifacts: ArtifactHandler -) : ArtifactHandler by artifacts { +) : ArtifactHandlerDecorator() { companion object { /** @@ -41,6 +43,9 @@ private constructor( ArtifactHandlerScope(artifacts) } + override val delegate: ArtifactHandler + get() = artifacts + /** * Adds an artifact to the given configuration. * diff --git a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/DependencyConstraintHandlerScope.kt b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/DependencyConstraintHandlerScope.kt index aae1e8b2066f1..08f9be527a5e6 100644 --- a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/DependencyConstraintHandlerScope.kt +++ b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/DependencyConstraintHandlerScope.kt @@ -21,6 +21,8 @@ import org.gradle.api.artifacts.Configuration import org.gradle.api.artifacts.DependencyConstraint import org.gradle.api.artifacts.dsl.DependencyConstraintHandler +import org.gradle.kotlin.dsl.support.decorators.DependencyConstraintHandlerDecorator + /** * Receiver for `dependencies.constraints` block providing convenient utilities for configuring dependency constraints. @@ -32,13 +34,16 @@ import org.gradle.api.artifacts.dsl.DependencyConstraintHandler class DependencyConstraintHandlerScope private constructor( val constraints: DependencyConstraintHandler -) : DependencyConstraintHandler by constraints { +) : DependencyConstraintHandlerDecorator() { companion object { fun of(constraints: DependencyConstraintHandler) = DependencyConstraintHandlerScope(constraints) } + override val delegate: DependencyConstraintHandler + get() = constraints + /** * Adds a dependency constraint to the given configuration. * diff --git a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/DependencyHandlerScope.kt b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/DependencyHandlerScope.kt index 99784b5216198..d604e715eaabd 100644 --- a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/DependencyHandlerScope.kt +++ b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/DependencyHandlerScope.kt @@ -23,6 +23,8 @@ import org.gradle.api.artifacts.ModuleDependency import org.gradle.api.artifacts.dsl.DependencyHandler import org.gradle.api.plugins.ExtensionAware +import org.gradle.kotlin.dsl.support.decorators.DependencyHandlerDecorator + /** * Receiver for `dependencies` block providing convenient utilities for configuring dependencies. @@ -32,7 +34,7 @@ import org.gradle.api.plugins.ExtensionAware open class DependencyHandlerScope private constructor( val dependencies: DependencyHandler -) : DependencyHandler by dependencies { +) : DependencyHandlerDecorator() { companion object { fun of(dependencies: DependencyHandler): DependencyHandlerScope = @@ -44,6 +46,9 @@ private constructor( ) : DependencyHandlerScope(dependencies), ExtensionAware by (dependencies as ExtensionAware) } + override val delegate: DependencyHandler + get() = dependencies + /** * Adds a dependency to the given configuration. * diff --git a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/KotlinBuildScript.kt b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/KotlinBuildScript.kt index 8aa3a34835e41..a24c771025d5a 100644 --- a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/KotlinBuildScript.kt +++ b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/KotlinBuildScript.kt @@ -21,6 +21,7 @@ import org.gradle.api.initialization.dsl.ScriptHandler import org.gradle.kotlin.dsl.resolver.KotlinBuildScriptDependenciesResolver import org.gradle.kotlin.dsl.support.KotlinScriptHost +import org.gradle.kotlin.dsl.support.decorators.ProjectDecorator import org.gradle.kotlin.dsl.support.internalError import org.gradle.plugin.use.PluginDependenciesSpec @@ -55,7 +56,10 @@ annotation class KotlinScriptTemplate @GradleDsl abstract class KotlinBuildScript( private val host: KotlinScriptHost -) : Project by host.target { +) : ProjectDecorator() { + + override val delegate: Project + get() = host.target /** * The [ScriptHandler] for this script. diff --git a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/KotlinInitScript.kt b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/KotlinInitScript.kt index 1609b0bc4980b..7b343b4008b0e 100644 --- a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/KotlinInitScript.kt +++ b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/KotlinInitScript.kt @@ -37,6 +37,7 @@ import org.gradle.api.tasks.WorkResult import org.gradle.kotlin.dsl.resolver.KotlinBuildScriptDependenciesResolver import org.gradle.kotlin.dsl.support.KotlinScriptHost +import org.gradle.kotlin.dsl.support.decorators.GradleDecorator import org.gradle.kotlin.dsl.support.internalError import org.gradle.kotlin.dsl.support.serviceOf import org.gradle.kotlin.dsl.support.unsafeLazy @@ -100,7 +101,9 @@ abstract class KotlinInitScript( * Standard implementation of the API exposed to all types of [Gradle] scripts, * precompiled and otherwise. */ -abstract class InitScriptApi(target: Gradle) : Gradle by target { +abstract class InitScriptApi( + override val delegate: Gradle +) : GradleDecorator() { protected abstract val fileOperations: FileOperations diff --git a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/KotlinSettingsScript.kt b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/KotlinSettingsScript.kt index e2a9d8c79bec0..791a6a946bf6c 100644 --- a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/KotlinSettingsScript.kt +++ b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/KotlinSettingsScript.kt @@ -49,6 +49,7 @@ import org.gradle.internal.time.Clock import org.gradle.kotlin.dsl.resolver.KotlinBuildScriptDependenciesResolver import org.gradle.kotlin.dsl.support.KotlinScriptHost +import org.gradle.kotlin.dsl.support.decorators.SettingsDecorator import org.gradle.kotlin.dsl.support.get import org.gradle.kotlin.dsl.support.internalError import org.gradle.kotlin.dsl.support.serviceOf @@ -105,7 +106,9 @@ abstract class KotlinSettingsScript( * Standard implementation of the API exposed to all types of [Settings] scripts, * precompiled and otherwise. */ -abstract class SettingsScriptApi(settings: Settings) : Settings by settings { +abstract class SettingsScriptApi( + override val delegate: Settings +) : SettingsDecorator() { protected abstract val fileOperations: FileOperations diff --git a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/NamedDomainObjectContainerExtensions.kt b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/NamedDomainObjectContainerExtensions.kt index 3c295e5918811..3e715bb2ecbba 100644 --- a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/NamedDomainObjectContainerExtensions.kt +++ b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/NamedDomainObjectContainerExtensions.kt @@ -21,6 +21,8 @@ import org.gradle.api.NamedDomainObjectContainer import org.gradle.api.NamedDomainObjectProvider import org.gradle.api.PolymorphicDomainObjectContainer +import org.gradle.kotlin.dsl.support.decorators.NamedDomainObjectContainerDecorator + import kotlin.reflect.KClass import kotlin.reflect.KProperty @@ -219,8 +221,8 @@ private constructor( */ class NamedDomainObjectContainerScope private constructor( - private val container: NamedDomainObjectContainer -) : NamedDomainObjectContainer by container, PolymorphicDomainObjectContainer { + override val delegate: NamedDomainObjectContainer +) : NamedDomainObjectContainerDecorator(), PolymorphicDomainObjectContainer { companion object { fun of(container: NamedDomainObjectContainer) = @@ -260,7 +262,7 @@ private constructor( * @see [NamedDomainObjectContainer.named] */ operator fun String.invoke(): NamedDomainObjectProvider = - container.named(this) + delegate.named(this) /** * Configures an object by name, without triggering its creation or configuration, failing if there is no such object. @@ -269,7 +271,7 @@ private constructor( * @see [NamedDomainObjectProvider.configure] */ operator fun String.invoke(type: KClass, configuration: U.() -> Unit): NamedDomainObjectProvider = - container.named(this, type, configuration) + delegate.named(this, type, configuration) /** * Locates an object by name and type, without triggering its creation or configuration, failing if there is no such object. @@ -277,7 +279,7 @@ private constructor( * @see [PolymorphicDomainObjectContainer.named] */ operator fun String.invoke(type: KClass): NamedDomainObjectProvider = - container.named(this, type) + delegate.named(this, type) /** * Cast this to [PolymorphicDomainObjectContainer] or throw [IllegalArgumentException]. @@ -289,8 +291,8 @@ private constructor( */ private fun polymorphicDomainObjectContainer() = - container as? PolymorphicDomainObjectContainer - ?: throw IllegalArgumentException("Container '$container' is not polymorphic.") + delegate as? PolymorphicDomainObjectContainer + ?: throw IllegalArgumentException("Container '$delegate' is not polymorphic.") } diff --git a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/PluginDependenciesSpecScope.kt b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/PluginDependenciesSpecScope.kt index c2ec6a85e4c56..f7bbfb8b6e631 100644 --- a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/PluginDependenciesSpecScope.kt +++ b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/PluginDependenciesSpecScope.kt @@ -29,7 +29,13 @@ import org.gradle.plugin.use.PluginDependencySpec * @see [PluginDependenciesSpec] */ @GradleDsl -class PluginDependenciesSpecScope internal constructor(plugins: PluginDependenciesSpec) : PluginDependenciesSpec by plugins +class PluginDependenciesSpecScope internal constructor( + private val plugins: PluginDependenciesSpec +) : PluginDependenciesSpec { + + override fun id(id: String): PluginDependencySpec = + plugins.id(id) +} /** diff --git a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/ScriptHandlerScope.kt b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/ScriptHandlerScope.kt index 3eb7a53faf91b..c9502321f0e0c 100644 --- a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/ScriptHandlerScope.kt +++ b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/ScriptHandlerScope.kt @@ -31,6 +31,7 @@ import org.gradle.api.artifacts.dsl.DependencyHandler import org.gradle.api.initialization.dsl.ScriptHandler import org.gradle.api.initialization.dsl.ScriptHandler.CLASSPATH_CONFIGURATION +import org.gradle.kotlin.dsl.support.decorators.ScriptHandlerDecorator import org.gradle.kotlin.dsl.support.unsafeLazy @@ -39,8 +40,8 @@ import org.gradle.kotlin.dsl.support.unsafeLazy */ class ScriptHandlerScope private constructor( - scriptHandler: ScriptHandler -) : ScriptHandler by scriptHandler { + override val delegate: ScriptHandler +) : ScriptHandlerDecorator() { companion object { fun of(scriptHandler: ScriptHandler) = @@ -50,7 +51,7 @@ private constructor( /** * The dependencies of the script. */ - val dependencies by unsafeLazy { DependencyHandlerScope.of(scriptHandler.dependencies) } + val dependencies by unsafeLazy { DependencyHandlerScope.of(delegate.dependencies) } /** * The script classpath configuration. diff --git a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/precompile/PrecompiledProjectScript.kt b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/precompile/PrecompiledProjectScript.kt index aed4f50ada4ea..6f1c28ca62f78 100644 --- a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/precompile/PrecompiledProjectScript.kt +++ b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/precompile/PrecompiledProjectScript.kt @@ -21,6 +21,7 @@ import org.gradle.api.Project import org.gradle.kotlin.dsl.GradleDsl import org.gradle.kotlin.dsl.KotlinScriptTemplate import org.gradle.kotlin.dsl.ScriptHandlerScope +import org.gradle.kotlin.dsl.support.decorators.ProjectDecorator import org.gradle.plugin.use.PluginDependenciesSpec import org.gradle.plugin.use.PluginDependencySpec @@ -55,7 +56,9 @@ import kotlin.script.templates.ScriptTemplateDefinition scriptFilePattern = "^.*\\.gradle\\.kts$") @SamWithReceiverAnnotations("org.gradle.api.HasImplicitReceiver") @GradleDsl -abstract class PrecompiledProjectScript(project: Project) : Project by project { +abstract class PrecompiledProjectScript( + override val delegate: Project +) : ProjectDecorator() { /** * Configures the build script classpath for this project. diff --git a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/KotlinPluginsBlock.kt b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/KotlinPluginsBlock.kt index 666c2ef7236b2..297bc49620fb1 100644 --- a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/KotlinPluginsBlock.kt +++ b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/KotlinPluginsBlock.kt @@ -20,6 +20,7 @@ import org.gradle.api.Project import org.gradle.api.initialization.dsl.ScriptHandler import org.gradle.kotlin.dsl.ScriptHandlerScope +import org.gradle.kotlin.dsl.support.decorators.ProjectDecorator import org.gradle.plugin.use.PluginDependenciesSpec @@ -41,7 +42,10 @@ abstract class KotlinPluginsBlock(val pluginDependencies: PluginDependenciesSpec abstract class KotlinBuildscriptAndPluginsBlock( private val host: KotlinScriptHost, val pluginDependencies: PluginDependenciesSpec -) : Project by host.target { +) : ProjectDecorator() { + + override val delegate: Project + get() = host.target /** * The [ScriptHandler] for this script. diff --git a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/decorators/ArtifactHandlerDecorator.kt b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/decorators/ArtifactHandlerDecorator.kt new file mode 100644 index 0000000000000..960ce1d74778b --- /dev/null +++ b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/decorators/ArtifactHandlerDecorator.kt @@ -0,0 +1,40 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.kotlin.dsl.support.decorators + +import groovy.lang.Closure + +import org.gradle.api.Action +import org.gradle.api.artifacts.ConfigurablePublishArtifact +import org.gradle.api.artifacts.PublishArtifact +import org.gradle.api.artifacts.dsl.ArtifactHandler + + +abstract class ArtifactHandlerDecorator : ArtifactHandler { + + internal + abstract val delegate: ArtifactHandler + + override fun add(configurationName: String, artifactNotation: Any): PublishArtifact = + delegate.add(configurationName, artifactNotation) + + override fun add(configurationName: String, artifactNotation: Any, configureClosure: Closure): PublishArtifact = + delegate.add(configurationName, artifactNotation, configureClosure) + + override fun add(configurationName: String, artifactNotation: Any, configureAction: Action): PublishArtifact = + delegate.add(configurationName, artifactNotation, configureAction) +} diff --git a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/decorators/DependencyConstraintHandlerDecorator.kt b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/decorators/DependencyConstraintHandlerDecorator.kt new file mode 100644 index 0000000000000..cb8ebf3c48381 --- /dev/null +++ b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/decorators/DependencyConstraintHandlerDecorator.kt @@ -0,0 +1,52 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.kotlin.dsl.support.decorators + +import org.gradle.api.Action +import org.gradle.api.artifacts.DependencyConstraint +import org.gradle.api.artifacts.dsl.DependencyConstraintHandler + + +abstract class DependencyConstraintHandlerDecorator : DependencyConstraintHandler { + + internal + abstract val delegate: DependencyConstraintHandler + + override fun add(configurationName: String, dependencyConstraintNotation: Any): DependencyConstraint = + delegate.add(configurationName, dependencyConstraintNotation) + + override fun add(configurationName: String, dependencyNotation: Any, configureAction: Action): DependencyConstraint = + delegate.add(configurationName, dependencyNotation, configureAction) + + override fun create(dependencyConstraintNotation: Any): DependencyConstraint = + delegate.create(dependencyConstraintNotation) + + override fun create(dependencyConstraintNotation: Any, configureAction: Action): DependencyConstraint = + delegate.create(dependencyConstraintNotation, configureAction) + + override fun platform(notation: Any): DependencyConstraint = + delegate.platform(notation) + + override fun platform(notation: Any, configureAction: Action): DependencyConstraint = + delegate.platform(notation, configureAction) + + override fun enforcedPlatform(notation: Any): DependencyConstraint = + delegate.enforcedPlatform(notation) + + override fun enforcedPlatform(notation: Any, configureAction: Action): DependencyConstraint = + delegate.enforcedPlatform(notation, configureAction) +} diff --git a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/decorators/DependencyHandlerDecorator.kt b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/decorators/DependencyHandlerDecorator.kt new file mode 100644 index 0000000000000..2dd0ba4ef4784 --- /dev/null +++ b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/decorators/DependencyHandlerDecorator.kt @@ -0,0 +1,121 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.kotlin.dsl.support.decorators + +import groovy.lang.Closure + +import org.gradle.api.Action +import org.gradle.api.artifacts.Dependency +import org.gradle.api.artifacts.dsl.ComponentMetadataHandler +import org.gradle.api.artifacts.dsl.ComponentModuleMetadataHandler +import org.gradle.api.artifacts.dsl.DependencyConstraintHandler +import org.gradle.api.artifacts.dsl.DependencyHandler +import org.gradle.api.artifacts.query.ArtifactResolutionQuery +import org.gradle.api.artifacts.transform.TransformAction +import org.gradle.api.artifacts.transform.TransformParameters +import org.gradle.api.artifacts.transform.TransformSpec +import org.gradle.api.artifacts.transform.VariantTransform +import org.gradle.api.artifacts.type.ArtifactTypeContainer +import org.gradle.api.attributes.AttributesSchema + + +abstract class DependencyHandlerDecorator : DependencyHandler { + + internal + abstract val delegate: DependencyHandler + + override fun add(configurationName: String, dependencyNotation: Any): Dependency? = + delegate.add(configurationName, dependencyNotation) + + override fun add(configurationName: String, dependencyNotation: Any, configureClosure: Closure): Dependency = + delegate.add(configurationName, dependencyNotation, configureClosure) + + override fun create(dependencyNotation: Any): Dependency = + delegate.create(dependencyNotation) + + override fun create(dependencyNotation: Any, configureClosure: Closure): Dependency = + delegate.create(dependencyNotation, configureClosure) + + override fun module(notation: Any): Dependency = + delegate.module(notation) + + override fun module(notation: Any, configureClosure: Closure): Dependency = + delegate.module(notation, configureClosure) + + override fun project(notation: MutableMap): Dependency = + delegate.project(notation) + + override fun gradleApi(): Dependency = + delegate.gradleApi() + + override fun gradleTestKit(): Dependency = + delegate.gradleTestKit() + + override fun localGroovy(): Dependency = + delegate.localGroovy() + + override fun getConstraints(): DependencyConstraintHandler = + delegate.constraints + + override fun constraints(configureAction: Action) = + delegate.constraints(configureAction) + + override fun getComponents(): ComponentMetadataHandler = + delegate.components + + override fun components(configureAction: Action) = + delegate.components(configureAction) + + override fun getModules(): ComponentModuleMetadataHandler = + delegate.modules + + override fun modules(configureAction: Action) = + delegate.modules(configureAction) + + override fun createArtifactResolutionQuery(): ArtifactResolutionQuery = + delegate.createArtifactResolutionQuery() + + override fun attributesSchema(configureAction: Action): AttributesSchema = + delegate.attributesSchema(configureAction) + + override fun getAttributesSchema(): AttributesSchema = + delegate.attributesSchema + + override fun getArtifactTypes(): ArtifactTypeContainer = + delegate.artifactTypes + + override fun artifactTypes(configureAction: Action) = + delegate.artifactTypes(configureAction) + + override fun registerTransform(registrationAction: Action) = + delegate.registerTransform(registrationAction) + + override fun registerTransform(actionType: Class>, registrationAction: Action>) = + delegate.registerTransform(actionType, registrationAction) + + override fun platform(notation: Any): Dependency = + delegate.platform(notation) + + override fun platform(notation: Any, configureAction: Action): Dependency = + delegate.platform(notation, configureAction) + + override fun enforcedPlatform(notation: Any): Dependency = + delegate.enforcedPlatform(notation) + + override fun enforcedPlatform(notation: Any, configureAction: Action): Dependency = + delegate.enforcedPlatform(notation, configureAction) +} diff --git a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/decorators/GradleDecorator.kt b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/decorators/GradleDecorator.kt new file mode 100644 index 0000000000000..6671ca073dddc --- /dev/null +++ b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/decorators/GradleDecorator.kt @@ -0,0 +1,153 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.kotlin.dsl.support.decorators + +import groovy.lang.Closure + +import org.gradle.BuildListener +import org.gradle.BuildResult +import org.gradle.StartParameter +import org.gradle.api.Action +import org.gradle.api.Project +import org.gradle.api.ProjectEvaluationListener +import org.gradle.api.execution.TaskExecutionGraph +import org.gradle.api.initialization.IncludedBuild +import org.gradle.api.initialization.Settings +import org.gradle.api.invocation.Gradle +import org.gradle.api.plugins.ObjectConfigurationAction +import org.gradle.api.plugins.PluginContainer +import org.gradle.api.plugins.PluginManager + +import java.io.File + + +abstract class GradleDecorator : Gradle { + + internal + abstract val delegate: Gradle + + override fun getGradleVersion(): String = + delegate.gradleVersion + + override fun getGradleUserHomeDir(): File = + delegate.gradleUserHomeDir + + override fun getGradleHomeDir(): File? = + delegate.gradleHomeDir + + override fun getParent(): Gradle? = + delegate.parent + + override fun getRootProject(): Project = + delegate.rootProject + + override fun rootProject(action: Action) = + delegate.rootProject(action) + + override fun allprojects(action: Action) = + delegate.allprojects(action) + + override fun getTaskGraph(): TaskExecutionGraph = + delegate.taskGraph + + override fun getStartParameter(): StartParameter = + delegate.startParameter + + override fun addProjectEvaluationListener(listener: ProjectEvaluationListener): ProjectEvaluationListener = + delegate.addProjectEvaluationListener(listener) + + override fun removeProjectEvaluationListener(listener: ProjectEvaluationListener) = + delegate.removeProjectEvaluationListener(listener) + + override fun beforeProject(closure: Closure) = + delegate.beforeProject(closure) + + override fun beforeProject(action: Action) = + delegate.beforeProject(action) + + override fun afterProject(closure: Closure) = + delegate.afterProject(closure) + + override fun afterProject(action: Action) = + delegate.afterProject(action) + + override fun buildStarted(closure: Closure) = + delegate.buildStarted(closure) + + override fun buildStarted(action: Action) = + delegate.buildStarted(action) + + override fun settingsEvaluated(closure: Closure) = + delegate.settingsEvaluated(closure) + + override fun settingsEvaluated(action: Action) = + delegate.settingsEvaluated(action) + + override fun projectsLoaded(closure: Closure) = + delegate.projectsLoaded(closure) + + override fun projectsLoaded(action: Action) = + delegate.projectsLoaded(action) + + override fun projectsEvaluated(closure: Closure) = + delegate.projectsEvaluated(closure) + + override fun projectsEvaluated(action: Action) = + delegate.projectsEvaluated(action) + + override fun buildFinished(closure: Closure) = + delegate.buildFinished(closure) + + override fun buildFinished(action: Action) = + delegate.buildFinished(action) + + override fun addBuildListener(buildListener: BuildListener) = + delegate.addBuildListener(buildListener) + + override fun addListener(listener: Any) = + delegate.addListener(listener) + + override fun removeListener(listener: Any) = + delegate.removeListener(listener) + + override fun useLogger(logger: Any) = + delegate.useLogger(logger) + + override fun getGradle(): Gradle = + delegate.gradle + + override fun getIncludedBuilds(): MutableCollection = + delegate.includedBuilds + + override fun includedBuild(name: String): IncludedBuild = + delegate.includedBuild(name) + + override fun getPlugins(): PluginContainer = + delegate.plugins + + override fun apply(closure: Closure) = + delegate.apply(closure) + + override fun apply(action: Action) = + delegate.apply(action) + + override fun apply(options: MutableMap) = + delegate.apply(options) + + override fun getPluginManager(): PluginManager = + delegate.pluginManager +} diff --git a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/decorators/NamedDomainObjectContainerDecorator.kt b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/decorators/NamedDomainObjectContainerDecorator.kt new file mode 100644 index 0000000000000..66aed27377c3d --- /dev/null +++ b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/decorators/NamedDomainObjectContainerDecorator.kt @@ -0,0 +1,189 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.kotlin.dsl.support.decorators + +import groovy.lang.Closure + +import org.gradle.api.Action +import org.gradle.api.DomainObjectCollection +import org.gradle.api.NamedDomainObjectCollectionSchema +import org.gradle.api.NamedDomainObjectContainer +import org.gradle.api.NamedDomainObjectProvider +import org.gradle.api.NamedDomainObjectSet +import org.gradle.api.Namer +import org.gradle.api.Rule +import org.gradle.api.provider.Provider +import org.gradle.api.specs.Spec + +import java.util.SortedMap +import java.util.SortedSet + + +abstract class NamedDomainObjectContainerDecorator : NamedDomainObjectContainer { + + abstract val delegate: NamedDomainObjectContainer + + override fun contains(element: T): Boolean = + delegate.contains(element) + + override fun addAll(elements: Collection): Boolean = + delegate.addAll(elements) + + override fun matching(spec: Spec): NamedDomainObjectSet = + delegate.matching(spec) + + override fun matching(spec: Closure): NamedDomainObjectSet = + delegate.matching(spec) + + override fun clear() = + delegate.clear() + + override fun addRule(rule: Rule): Rule = + delegate.addRule(rule) + + override fun addRule(description: String, ruleAction: Closure): Rule = + delegate.addRule(description, ruleAction) + + override fun addRule(description: String, ruleAction: Action): Rule = + delegate.addRule(description, ruleAction) + + override fun configure(configureClosure: Closure): NamedDomainObjectContainer = + delegate.configure(configureClosure) + + override fun addAllLater(provider: Provider>) = + delegate.addAllLater(provider) + + override fun create(name: String): T = + delegate.create(name) + + override fun create(name: String, configureClosure: Closure): T = + delegate.create(name, configureClosure) + + override fun create(name: String, configureAction: Action): T = + delegate.create(name, configureAction) + + override fun removeAll(elements: Collection): Boolean = + delegate.removeAll(elements) + + override fun add(element: T): Boolean = + delegate.add(element) + + override fun all(action: Action) = + delegate.all(action) + + override fun all(action: Closure) = + delegate.all(action) + + override fun register(name: String, configurationAction: Action): NamedDomainObjectProvider = + delegate.register(name, configurationAction) + + override fun register(name: String): NamedDomainObjectProvider = + delegate.register(name) + + override fun iterator(): MutableIterator = + delegate.iterator() + + override fun getNamer(): Namer = + delegate.namer + + override fun getRules(): MutableList = + delegate.rules + + override fun named(name: String): NamedDomainObjectProvider = + delegate.named(name) + + override fun named(name: String, configurationAction: Action): NamedDomainObjectProvider = + delegate.named(name, configurationAction) + + override fun named(name: String, type: Class): NamedDomainObjectProvider = + delegate.named(name, type) + + override fun getCollectionSchema(): NamedDomainObjectCollectionSchema = + delegate.collectionSchema + + override fun whenObjectRemoved(action: Action): Action = + delegate.whenObjectRemoved(action) + + override fun whenObjectRemoved(action: Closure) = + delegate.whenObjectRemoved(action) + + override fun findAll(spec: Closure): MutableSet = + delegate.findAll(spec) + + override fun addLater(provider: Provider) = + delegate.addLater(provider) + + override fun containsAll(elements: Collection): Boolean = + delegate.containsAll(elements) + + override fun isEmpty(): Boolean = + delegate.isEmpty() + + override fun remove(element: T): Boolean = + delegate.remove(element) + + override fun getAsMap(): SortedMap = + delegate.asMap + + override fun getNames(): SortedSet = + delegate.names + + override fun getByName(name: String): T = + delegate.getByName(name) + + override fun getByName(name: String, configureClosure: Closure): T = + delegate.getByName(name, configureClosure) + + override fun getByName(name: String, configureAction: Action): T = + delegate.getByName(name, configureAction) + + override fun withType(type: Class, configureClosure: Closure): DomainObjectCollection = + delegate.withType(type, configureClosure) + + override fun configureEach(action: Action) = + delegate.configureEach(action) + + override fun maybeCreate(name: String): T = + delegate.maybeCreate(name) + + override fun withType(type: Class): NamedDomainObjectSet = + delegate.withType(type) + + override fun withType(type: Class, configureAction: Action): DomainObjectCollection = + delegate.withType(type, configureAction) + + override fun findByName(name: String): T? = + delegate.findByName(name) + + override fun whenObjectAdded(action: Action): Action = + delegate.whenObjectAdded(action) + + override fun whenObjectAdded(action: Closure) = + delegate.whenObjectAdded(action) + + override fun retainAll(elements: Collection): Boolean = + delegate.retainAll(elements) + + override fun getAt(name: String): T = + delegate.getAt(name) + + override fun named(name: String, type: Class, configurationAction: Action): NamedDomainObjectProvider = + delegate.named(name, type, configurationAction) + + override val size: Int + get() = delegate.size +} diff --git a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/decorators/ProjectDecorator.kt b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/decorators/ProjectDecorator.kt new file mode 100644 index 0000000000000..cc1483b3f8a95 --- /dev/null +++ b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/decorators/ProjectDecorator.kt @@ -0,0 +1,456 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.kotlin.dsl.support.decorators + +import groovy.lang.Closure + +import org.gradle.api.Action +import org.gradle.api.AntBuilder +import org.gradle.api.NamedDomainObjectContainer +import org.gradle.api.NamedDomainObjectFactory +import org.gradle.api.PathValidation +import org.gradle.api.Project +import org.gradle.api.ProjectState +import org.gradle.api.Task +import org.gradle.api.artifacts.ConfigurationContainer +import org.gradle.api.artifacts.dsl.ArtifactHandler +import org.gradle.api.artifacts.dsl.DependencyHandler +import org.gradle.api.artifacts.dsl.DependencyLockingHandler +import org.gradle.api.artifacts.dsl.RepositoryHandler +import org.gradle.api.component.SoftwareComponentContainer +import org.gradle.api.file.ConfigurableFileCollection +import org.gradle.api.file.ConfigurableFileTree +import org.gradle.api.file.CopySpec +import org.gradle.api.file.DeleteSpec +import org.gradle.api.file.FileTree +import org.gradle.api.file.ProjectLayout +import org.gradle.api.initialization.dsl.ScriptHandler +import org.gradle.api.invocation.Gradle +import org.gradle.api.logging.Logger +import org.gradle.api.logging.LoggingManager +import org.gradle.api.model.ObjectFactory +import org.gradle.api.plugins.Convention +import org.gradle.api.plugins.ExtensionContainer +import org.gradle.api.plugins.ObjectConfigurationAction +import org.gradle.api.plugins.PluginContainer +import org.gradle.api.plugins.PluginManager +import org.gradle.api.provider.Provider +import org.gradle.api.provider.ProviderFactory +import org.gradle.api.resources.ResourceHandler +import org.gradle.api.tasks.TaskContainer +import org.gradle.api.tasks.WorkResult +import org.gradle.normalization.InputNormalizationHandler +import org.gradle.process.ExecResult +import org.gradle.process.ExecSpec +import org.gradle.process.JavaExecSpec + +import java.io.File + +import java.net.URI + +import java.util.concurrent.Callable + + +abstract class ProjectDecorator() : Project { + + internal + abstract val delegate: Project + + override fun getGroup(): Any = + delegate.group + + override fun afterEvaluate(action: Action) = + delegate.afterEvaluate(action) + + override fun afterEvaluate(closure: Closure<*>) = + delegate.afterEvaluate(closure) + + override fun getDefaultTasks(): MutableList = + delegate.defaultTasks + + override fun getConvention(): Convention = + delegate.convention + + override fun getLogger(): Logger = + delegate.logger + + override fun getBuildDir(): File = + delegate.buildDir + + override fun getAnt(): AntBuilder = + delegate.ant + + override fun getVersion(): Any = + delegate.version + + override fun getRootProject(): Project = + delegate.rootProject + + override fun depthCompare(otherProject: Project): Int = + delegate.depthCompare(otherProject) + + override fun getGradle(): Gradle = + delegate.gradle + + override fun getAllTasks(recursive: Boolean): MutableMap> = + delegate.getAllTasks(recursive) + + override fun uri(path: Any): URI = + delegate.uri(path) + + override fun copySpec(closure: Closure<*>): CopySpec = + delegate.copySpec(closure) + + override fun copySpec(action: Action): CopySpec = + delegate.copySpec(action) + + override fun copySpec(): CopySpec = + delegate.copySpec() + + override fun relativePath(path: Any): String = + delegate.relativePath(path) + + override fun setProperty(name: String, value: Any?) = + delegate.setProperty(name, value) + + override fun beforeEvaluate(action: Action) = + delegate.beforeEvaluate(action) + + override fun beforeEvaluate(closure: Closure<*>) = + delegate.beforeEvaluate(closure) + + override fun property(propertyName: String): Any? = + delegate.property(propertyName) + + override fun buildscript(configureClosure: Closure<*>) = + delegate.buildscript(configureClosure) + + override fun getProject(): Project = + delegate.project + + override fun dependencies(configureClosure: Closure<*>) = + delegate.dependencies(configureClosure) + + override fun getPath(): String = + delegate.path + + override fun zipTree(zipPath: Any): FileTree = + delegate.zipTree(zipPath) + + override fun allprojects(action: Action) = + delegate.allprojects(action) + + override fun allprojects(configureClosure: Closure<*>) = + delegate.allprojects(configureClosure) + + override fun container(type: Class): NamedDomainObjectContainer = + delegate.container(type) + + override fun container(type: Class, factory: NamedDomainObjectFactory): NamedDomainObjectContainer = + delegate.container(type, factory) + + override fun container(type: Class, factoryClosure: Closure<*>): NamedDomainObjectContainer = + delegate.container(type, factoryClosure) + + override fun repositories(configureClosure: Closure<*>) = + delegate.repositories(configureClosure) + + override fun evaluationDependsOnChildren() = + delegate.evaluationDependsOnChildren() + + override fun configure(`object`: Any, configureClosure: Closure<*>): Any = + delegate.configure(`object`, configureClosure) + + override fun configure(objects: MutableIterable<*>, configureClosure: Closure<*>): MutableIterable<*> = + delegate.configure(objects, configureClosure) + + override fun configure(objects: MutableIterable, configureAction: Action): MutableIterable = + delegate.configure(objects, configureAction) + + override fun exec(closure: Closure<*>): ExecResult = + delegate.exec(closure) + + override fun exec(action: Action): ExecResult = + delegate.exec(action) + + override fun sync(action: Action): WorkResult = + delegate.sync(action) + + override fun configurations(configureClosure: Closure<*>) = + delegate.configurations(configureClosure) + + override fun getExtensions(): ExtensionContainer = + delegate.extensions + + override fun getProperties(): MutableMap = + delegate.properties + + override fun absoluteProjectPath(path: String): String = + delegate.absoluteProjectPath(path) + + override fun getProjectDir(): File = + delegate.projectDir + + override fun files(vararg paths: Any?): ConfigurableFileCollection = + delegate.files(paths) + + override fun files(paths: Any, configureClosure: Closure<*>): ConfigurableFileCollection = + delegate.files(paths, configureClosure) + + override fun files(paths: Any, configureAction: Action): ConfigurableFileCollection = + delegate.files(paths, configureAction) + + override fun hasProperty(propertyName: String): Boolean = + delegate.hasProperty(propertyName) + + override fun getState(): ProjectState = + delegate.state + + override fun getComponents(): SoftwareComponentContainer = + delegate.components + + override fun setBuildDir(path: File) { + delegate.buildDir = path + } + + override fun setBuildDir(path: Any) = + delegate.setBuildDir(path) + + override fun defaultTasks(vararg defaultTasks: String?) = + delegate.defaultTasks(*defaultTasks) + + override fun compareTo(other: Project?): Int = + delegate.compareTo(other) + + override fun artifacts(configureClosure: Closure<*>) = + delegate.artifacts(configureClosure) + + override fun artifacts(configureAction: Action) = + delegate.artifacts(configureAction) + + override fun getRootDir(): File = + delegate.rootDir + + override fun getDependencyLocking(): DependencyLockingHandler = + delegate.dependencyLocking + + override fun provider(value: Callable): Provider = + delegate.provider(value) + + override fun findProperty(propertyName: String): Any? = + delegate.findProperty(propertyName) + + override fun getDependencies(): DependencyHandler = + delegate.dependencies + + override fun getResources(): ResourceHandler = + delegate.resources + + override fun setDefaultTasks(defaultTasks: MutableList) { + delegate.defaultTasks = defaultTasks + } + + override fun normalization(configuration: Action) = + delegate.normalization(configuration) + + override fun project(path: String): Project = + delegate.project(path) + + override fun project(path: String, configureClosure: Closure<*>): Project = + delegate.project(path, configureClosure) + + override fun project(path: String, configureAction: Action): Project = + delegate.project(path, configureAction) + + override fun task(name: String): Task = + delegate.task(name) + + override fun task(args: MutableMap, name: String): Task = + delegate.task(args, name) + + override fun task(args: MutableMap, name: String, configureClosure: Closure<*>): Task = + delegate.task(args, name, configureClosure) + + override fun task(name: String, configureClosure: Closure<*>): Task = + delegate.task(name, configureClosure) + + override fun task(name: String, configureAction: Action): Task = + delegate.task(name, configureAction) + + override fun copy(closure: Closure<*>): WorkResult = + delegate.copy(closure) + + override fun copy(action: Action): WorkResult = + delegate.copy(action) + + override fun getDescription(): String? = + delegate.description + + override fun subprojects(action: Action) = + delegate.subprojects(action) + + override fun subprojects(configureClosure: Closure<*>) = + delegate.subprojects(configureClosure) + + override fun getBuildscript(): ScriptHandler = + delegate.buildscript + + override fun getStatus(): Any = + delegate.status + + override fun mkdir(path: Any): File = + delegate.mkdir(path) + + override fun setStatus(status: Any) { + delegate.status = status + } + + override fun getConfigurations(): ConfigurationContainer = + delegate.configurations + + override fun getArtifacts(): ArtifactHandler = + delegate.artifacts + + override fun setDescription(description: String?) { + delegate.description = description + } + + override fun getLayout(): ProjectLayout = + delegate.layout + + override fun apply(closure: Closure<*>) = + delegate.apply(closure) + + override fun apply(action: Action) = + delegate.apply(action) + + override fun apply(options: MutableMap) = + delegate.apply(options) + + override fun evaluationDependsOn(path: String): Project = + delegate.evaluationDependsOn(path) + + override fun javaexec(closure: Closure<*>): ExecResult = + delegate.javaexec(closure) + + override fun javaexec(action: Action): ExecResult = + delegate.javaexec(action) + + override fun getChildProjects(): MutableMap = + delegate.childProjects + + override fun getLogging(): LoggingManager = + delegate.logging + + override fun getTasks(): TaskContainer = + delegate.tasks + + override fun getName(): String = + delegate.name + + override fun file(path: Any): File = + delegate.file(path) + + override fun file(path: Any, validation: PathValidation): File = + delegate.file(path, validation) + + override fun findProject(path: String): Project? = + delegate.findProject(path) + + override fun getPlugins(): PluginContainer = + delegate.plugins + + override fun ant(configureClosure: Closure<*>): AntBuilder = + delegate.ant(configureClosure) + + override fun ant(configureAction: Action): AntBuilder = + delegate.ant(configureAction) + + override fun getAllprojects(): MutableSet = + delegate.allprojects + + override fun createAntBuilder(): AntBuilder = + delegate.createAntBuilder() + + override fun getObjects(): ObjectFactory = + delegate.objects + + override fun dependencyLocking(configuration: Action) = + delegate.dependencyLocking(configuration) + + override fun tarTree(tarPath: Any): FileTree = + delegate.tarTree(tarPath) + + override fun delete(vararg paths: Any?): Boolean = + delegate.delete(*paths) + + override fun delete(action: Action): WorkResult = + delegate.delete(action) + + override fun getRepositories(): RepositoryHandler = + delegate.repositories + + override fun getTasksByName(name: String, recursive: Boolean): MutableSet = + delegate.getTasksByName(name, recursive) + + override fun getParent(): Project? = + delegate.parent + + override fun getDisplayName(): String = + delegate.displayName + + override fun relativeProjectPath(path: String): String = + delegate.relativeProjectPath(path) + + override fun getPluginManager(): PluginManager = + delegate.pluginManager + + override fun setGroup(group: Any) { + delegate.group = group + } + + override fun fileTree(baseDir: Any): ConfigurableFileTree = + delegate.fileTree(baseDir) + + override fun fileTree(baseDir: Any, configureClosure: Closure<*>): ConfigurableFileTree = + delegate.fileTree(baseDir, configureClosure) + + override fun fileTree(baseDir: Any, configureAction: Action): ConfigurableFileTree = + delegate.fileTree(baseDir, configureAction) + + override fun fileTree(args: MutableMap): ConfigurableFileTree = + delegate.fileTree(args) + + override fun getNormalization(): InputNormalizationHandler = + delegate.normalization + + override fun setVersion(version: Any) { + delegate.version = version + } + + override fun getDepth(): Int = + delegate.depth + + override fun getProviders(): ProviderFactory = + delegate.providers + + override fun getSubprojects(): MutableSet = + delegate.subprojects + + override fun getBuildFile(): File = + delegate.buildFile +} diff --git a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/decorators/ScriptHandlerDecorator.kt b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/decorators/ScriptHandlerDecorator.kt new file mode 100644 index 0000000000000..1de8b52045bec --- /dev/null +++ b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/decorators/ScriptHandlerDecorator.kt @@ -0,0 +1,59 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.kotlin.dsl.support.decorators + +import groovy.lang.Closure + +import org.gradle.api.artifacts.ConfigurationContainer +import org.gradle.api.artifacts.dsl.DependencyHandler +import org.gradle.api.artifacts.dsl.RepositoryHandler +import org.gradle.api.initialization.dsl.ScriptHandler + +import java.io.File + +import java.net.URI + + +abstract class ScriptHandlerDecorator : ScriptHandler { + + internal + abstract val delegate: ScriptHandler + + override fun getSourceFile(): File? = + delegate.sourceFile + + override fun getSourceURI(): URI? = + delegate.sourceURI + + override fun getRepositories(): RepositoryHandler = + delegate.repositories + + override fun repositories(configureClosure: Closure) = + delegate.repositories(configureClosure) + + override fun getDependencies(): DependencyHandler = + delegate.dependencies + + override fun dependencies(configureClosure: Closure) = + delegate.dependencies(configureClosure) + + override fun getConfigurations(): ConfigurationContainer = + delegate.configurations + + override fun getClassLoader(): ClassLoader = + delegate.classLoader +} diff --git a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/decorators/SettingsDecorator.kt b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/decorators/SettingsDecorator.kt new file mode 100644 index 0000000000000..f715e0a7b5c60 --- /dev/null +++ b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/decorators/SettingsDecorator.kt @@ -0,0 +1,127 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.kotlin.dsl.support.decorators + +import groovy.lang.Closure + +import org.gradle.StartParameter +import org.gradle.api.Action +import org.gradle.api.initialization.ConfigurableIncludedBuild +import org.gradle.api.initialization.ProjectDescriptor +import org.gradle.api.initialization.Settings +import org.gradle.api.initialization.dsl.ScriptHandler +import org.gradle.api.invocation.Gradle +import org.gradle.api.plugins.ExtensionContainer +import org.gradle.api.plugins.ObjectConfigurationAction +import org.gradle.api.plugins.PluginContainer +import org.gradle.api.plugins.PluginManager +import org.gradle.caching.configuration.BuildCacheConfiguration +import org.gradle.plugin.management.PluginManagementSpec +import org.gradle.vcs.SourceControl + +import java.io.File + + +abstract class SettingsDecorator : Settings { + + internal + abstract val delegate: Settings + + override fun getSettings(): Settings = + delegate.settings + + override fun getBuildscript(): ScriptHandler = + delegate.buildscript + + override fun getSettingsDir(): File = + delegate.settingsDir + + override fun getRootDir(): File = + delegate.rootDir + + override fun getRootProject(): ProjectDescriptor = + delegate.rootProject + + override fun project(path: String): ProjectDescriptor = + delegate.project(path) + + override fun findProject(path: String): ProjectDescriptor? = + delegate.findProject(path) + + override fun project(projectDir: File): ProjectDescriptor = + delegate.project(projectDir) + + override fun findProject(projectDir: File): ProjectDescriptor? = + delegate.findProject(projectDir) + + override fun getGradle(): Gradle = + delegate.gradle + + override fun includeBuild(rootProject: Any) = + delegate.includeBuild(rootProject) + + override fun includeBuild(rootProject: Any, configuration: Action) = + delegate.includeBuild(rootProject, configuration) + + override fun enableFeaturePreview(name: String) = + delegate.enableFeaturePreview(name) + + override fun getExtensions(): ExtensionContainer = + delegate.extensions + + override fun getBuildCache(): BuildCacheConfiguration = + delegate.buildCache + + override fun pluginManagement(pluginManagementSpec: Action) = + delegate.pluginManagement(pluginManagementSpec) + + override fun getPluginManagement(): PluginManagementSpec = + delegate.pluginManagement + + override fun sourceControl(configuration: Action) = + delegate.sourceControl(configuration) + + override fun getPlugins(): PluginContainer = + delegate.plugins + + override fun apply(closure: Closure) = + delegate.apply(closure) + + override fun apply(action: Action) = + delegate.apply(action) + + override fun apply(options: MutableMap) = + delegate.apply(options) + + override fun getPluginManager(): PluginManager = + delegate.pluginManager + + override fun include(vararg projectPaths: String?) = + delegate.include(*projectPaths) + + override fun includeFlat(vararg projectNames: String?) = + delegate.includeFlat(*projectNames) + + override fun getStartParameter(): StartParameter = + delegate.startParameter + + override fun buildCache(action: Action) = + delegate.buildCache(action) + + override fun getSourceControl(): SourceControl = + delegate.sourceControl +} From 550612d37ab679d15642a696de2b2ddf87596cb9 Mon Sep 17 00:00:00 2001 From: "Rodrigo B. de Oliveira" Date: Wed, 13 Mar 2019 02:15:22 -0300 Subject: [PATCH 509/853] Accept read-only collections wherever possible --- .../support/decorators/DependencyHandlerDecorator.kt | 2 +- .../kotlin/dsl/support/decorators/GradleDecorator.kt | 2 +- .../NamedDomainObjectContainerDecorator.kt | 2 +- .../dsl/support/decorators/ProjectDecorator.kt | 12 ++++++------ .../dsl/support/decorators/SettingsDecorator.kt | 2 +- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/decorators/DependencyHandlerDecorator.kt b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/decorators/DependencyHandlerDecorator.kt index 2dd0ba4ef4784..de0915ba26988 100644 --- a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/decorators/DependencyHandlerDecorator.kt +++ b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/decorators/DependencyHandlerDecorator.kt @@ -56,7 +56,7 @@ abstract class DependencyHandlerDecorator : DependencyHandler { override fun module(notation: Any, configureClosure: Closure): Dependency = delegate.module(notation, configureClosure) - override fun project(notation: MutableMap): Dependency = + override fun project(notation: Map): Dependency = delegate.project(notation) override fun gradleApi(): Dependency = diff --git a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/decorators/GradleDecorator.kt b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/decorators/GradleDecorator.kt index 6671ca073dddc..9e0212f293951 100644 --- a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/decorators/GradleDecorator.kt +++ b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/decorators/GradleDecorator.kt @@ -145,7 +145,7 @@ abstract class GradleDecorator : Gradle { override fun apply(action: Action) = delegate.apply(action) - override fun apply(options: MutableMap) = + override fun apply(options: Map) = delegate.apply(options) override fun getPluginManager(): PluginManager = diff --git a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/decorators/NamedDomainObjectContainerDecorator.kt b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/decorators/NamedDomainObjectContainerDecorator.kt index 66aed27377c3d..d4574cf469d97 100644 --- a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/decorators/NamedDomainObjectContainerDecorator.kt +++ b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/decorators/NamedDomainObjectContainerDecorator.kt @@ -64,7 +64,7 @@ abstract class NamedDomainObjectContainerDecorator : NamedDomainObjectContain override fun configure(configureClosure: Closure): NamedDomainObjectContainer = delegate.configure(configureClosure) - override fun addAllLater(provider: Provider>) = + override fun addAllLater(provider: Provider>) = delegate.addAllLater(provider) override fun create(name: String): T = diff --git a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/decorators/ProjectDecorator.kt b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/decorators/ProjectDecorator.kt index cc1483b3f8a95..e1d9966712130 100644 --- a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/decorators/ProjectDecorator.kt +++ b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/decorators/ProjectDecorator.kt @@ -175,10 +175,10 @@ abstract class ProjectDecorator() : Project { override fun configure(`object`: Any, configureClosure: Closure<*>): Any = delegate.configure(`object`, configureClosure) - override fun configure(objects: MutableIterable<*>, configureClosure: Closure<*>): MutableIterable<*> = + override fun configure(objects: Iterable<*>, configureClosure: Closure<*>): Iterable<*> = delegate.configure(objects, configureClosure) - override fun configure(objects: MutableIterable, configureAction: Action): MutableIterable = + override fun configure(objects: Iterable, configureAction: Action): Iterable = delegate.configure(objects, configureAction) override fun exec(closure: Closure<*>): ExecResult = @@ -279,10 +279,10 @@ abstract class ProjectDecorator() : Project { override fun task(name: String): Task = delegate.task(name) - override fun task(args: MutableMap, name: String): Task = + override fun task(args: Map, name: String): Task = delegate.task(args, name) - override fun task(args: MutableMap, name: String, configureClosure: Closure<*>): Task = + override fun task(args: Map, name: String, configureClosure: Closure<*>): Task = delegate.task(args, name, configureClosure) override fun task(name: String, configureClosure: Closure<*>): Task = @@ -338,7 +338,7 @@ abstract class ProjectDecorator() : Project { override fun apply(action: Action) = delegate.apply(action) - override fun apply(options: MutableMap) = + override fun apply(options: Map) = delegate.apply(options) override fun evaluationDependsOn(path: String): Project = @@ -432,7 +432,7 @@ abstract class ProjectDecorator() : Project { override fun fileTree(baseDir: Any, configureAction: Action): ConfigurableFileTree = delegate.fileTree(baseDir, configureAction) - override fun fileTree(args: MutableMap): ConfigurableFileTree = + override fun fileTree(args: Map): ConfigurableFileTree = delegate.fileTree(args) override fun getNormalization(): InputNormalizationHandler = diff --git a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/decorators/SettingsDecorator.kt b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/decorators/SettingsDecorator.kt index f715e0a7b5c60..0bbca58bbb8de 100644 --- a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/decorators/SettingsDecorator.kt +++ b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/decorators/SettingsDecorator.kt @@ -104,7 +104,7 @@ abstract class SettingsDecorator : Settings { override fun apply(action: Action) = delegate.apply(action) - override fun apply(options: MutableMap) = + override fun apply(options: Map) = delegate.apply(options) override fun getPluginManager(): PluginManager = From 396b3ae39ee3ffe853dd09a31a4c98215e34332d Mon Sep 17 00:00:00 2001 From: Louis Jacomet Date: Wed, 13 Mar 2019 10:25:55 +0100 Subject: [PATCH 510/853] Restore tests now that repo is back Repository available again and also mirrored for CI --- .../SamplesDeclaringDependenciesIntegrationTest.groovy | 2 -- ...lesTroubleshootingDependencyResolutionIntegrationTest.groovy | 2 -- 2 files changed, 4 deletions(-) diff --git a/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/samples/dependencymanagement/SamplesDeclaringDependenciesIntegrationTest.groovy b/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/samples/dependencymanagement/SamplesDeclaringDependenciesIntegrationTest.groovy index cc4e5ae4515fc..504534d83bcc2 100644 --- a/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/samples/dependencymanagement/SamplesDeclaringDependenciesIntegrationTest.groovy +++ b/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/samples/dependencymanagement/SamplesDeclaringDependenciesIntegrationTest.groovy @@ -22,7 +22,6 @@ import org.gradle.integtests.fixtures.UsesSample import org.gradle.test.fixtures.file.TestFile import org.gradle.util.Requires import org.junit.Rule -import spock.lang.Ignore import spock.lang.Unroll import static org.gradle.util.TestPrecondition.KOTLIN_SCRIPT @@ -83,7 +82,6 @@ class SamplesDeclaringDependenciesIntegrationTest extends AbstractSampleIntegrat dsl << ['groovy', 'kotlin'] } - @Ignore("Spring repo down and not mirrored") @Unroll @UsesSample("userguide/dependencyManagement/declaringDependencies/changingVersion") def "can use declare and resolve dependency with changing version with #dsl dsl"() { diff --git a/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/samples/dependencymanagement/SamplesTroubleshootingDependencyResolutionIntegrationTest.groovy b/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/samples/dependencymanagement/SamplesTroubleshootingDependencyResolutionIntegrationTest.groovy index 8561a9b8ac68a..bb59d410d66bb 100644 --- a/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/samples/dependencymanagement/SamplesTroubleshootingDependencyResolutionIntegrationTest.groovy +++ b/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/samples/dependencymanagement/SamplesTroubleshootingDependencyResolutionIntegrationTest.groovy @@ -20,7 +20,6 @@ import org.gradle.integtests.fixtures.AbstractSampleIntegrationTest import org.gradle.integtests.fixtures.Sample import org.gradle.integtests.fixtures.UsesSample import org.junit.Rule -import spock.lang.Ignore import spock.lang.Unroll class SamplesTroubleshootingDependencyResolutionIntegrationTest extends AbstractSampleIntegrationTest { @@ -30,7 +29,6 @@ class SamplesTroubleshootingDependencyResolutionIntegrationTest extends Abstract @Rule Sample sample = new Sample(testDirectoryProvider) - @Ignore("Spring repo down and not mirrored") @Unroll @UsesSample("userguide/dependencyManagement/troubleshooting/cache/changing") def "can declare custom TTL for dependency with changing version"() { From bb31473a4ffea0e77138ca761143f488445f4fc2 Mon Sep 17 00:00:00 2001 From: Stefan Wolf Date: Wed, 13 Mar 2019 10:30:30 +0100 Subject: [PATCH 511/853] Log rebuild message only once It is already logged by the execution engine. --- .../taskfactory/IncrementalInputsTaskAction.java | 9 +-------- .../taskfactory/IncrementalTaskInputsTaskAction.java | 11 +++-------- 2 files changed, 4 insertions(+), 16 deletions(-) diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/project/taskfactory/IncrementalInputsTaskAction.java b/subprojects/core/src/main/java/org/gradle/api/internal/project/taskfactory/IncrementalInputsTaskAction.java index 21b57d3dbc60f..f91368c9d47a1 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/project/taskfactory/IncrementalInputsTaskAction.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/project/taskfactory/IncrementalInputsTaskAction.java @@ -20,25 +20,18 @@ import org.gradle.api.execution.incremental.InputChanges; import org.gradle.internal.execution.history.changes.ExecutionStateChanges; import org.gradle.internal.reflect.JavaMethod; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import java.lang.reflect.Method; public class IncrementalInputsTaskAction extends AbstractIncrementalTaskAction { - private static final Logger LOGGER = LoggerFactory.getLogger(IncrementalInputsTaskAction.class); - public IncrementalInputsTaskAction(Class type, Method method) { super(type, method); } - protected void doExecute(final Task task, String methodName) { + protected void doExecute(Task task, String methodName) { @SuppressWarnings("OptionalGetWithoutIsPresent") ExecutionStateChanges changes = getContext().getExecutionStateChanges().get(); InputChanges inputChanges = changes.getInputChanges(); - if (!inputChanges.isIncremental()) { - LOGGER.info("All inputs are considered out-of-date for incremental {}.", task); - } getContext().setTaskExecutedIncrementally(inputChanges.isIncremental()); JavaMethod.of(task, Object.class, methodName, InputChanges.class).invoke(task, inputChanges); } diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/project/taskfactory/IncrementalTaskInputsTaskAction.java b/subprojects/core/src/main/java/org/gradle/api/internal/project/taskfactory/IncrementalTaskInputsTaskAction.java index 99bd15b9a9c57..52c1b158324e1 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/project/taskfactory/IncrementalTaskInputsTaskAction.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/project/taskfactory/IncrementalTaskInputsTaskAction.java @@ -24,14 +24,10 @@ import org.gradle.internal.execution.history.changes.InputChangesInternal; import org.gradle.internal.reflect.Instantiator; import org.gradle.internal.reflect.JavaMethod; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import java.lang.reflect.Method; class IncrementalTaskInputsTaskAction extends AbstractIncrementalTaskAction { - private static final Logger LOGGER = LoggerFactory.getLogger(IncrementalTaskInputsTaskAction.class); - private final Instantiator instantiator; public IncrementalTaskInputsTaskAction(Instantiator instantiator, Class type, Method method) { @@ -39,14 +35,14 @@ public IncrementalTaskInputsTaskAction(Instantiator instantiator, Class Date: Tue, 12 Mar 2019 21:44:28 +0100 Subject: [PATCH 512/853] Re-initialise field on setClasspath Without that change, it became illegal to do something like `setClasspath(files(someFile, getClasspath())` which can be used to prepend values to the classpath. Fixes #8748 --- .../process/internal/JavaExecHandleBuilder.java | 4 +++- .../internal/JavaExecHandleBuilderTest.groovy | 17 +++++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/subprojects/core/src/main/java/org/gradle/process/internal/JavaExecHandleBuilder.java b/subprojects/core/src/main/java/org/gradle/process/internal/JavaExecHandleBuilder.java index f45fdebb39005..369cd193b30d4 100644 --- a/subprojects/core/src/main/java/org/gradle/process/internal/JavaExecHandleBuilder.java +++ b/subprojects/core/src/main/java/org/gradle/process/internal/JavaExecHandleBuilder.java @@ -207,7 +207,9 @@ public List getArgumentProviders() { } public JavaExecHandleBuilder setClasspath(FileCollection classpath) { - doGetClasspath().setFrom(classpath); + ConfigurableFileCollection newClasspath = fileCollectionFactory.configurableFiles("classpath"); + newClasspath.setFrom(classpath); + this.classpath = newClasspath; return this; } diff --git a/subprojects/core/src/test/groovy/org/gradle/process/internal/JavaExecHandleBuilderTest.groovy b/subprojects/core/src/test/groovy/org/gradle/process/internal/JavaExecHandleBuilderTest.groovy index a8c958e35d881..a7574b9043b23 100644 --- a/subprojects/core/src/test/groovy/org/gradle/process/internal/JavaExecHandleBuilderTest.groovy +++ b/subprojects/core/src/test/groovy/org/gradle/process/internal/JavaExecHandleBuilderTest.groovy @@ -20,6 +20,7 @@ import org.gradle.api.internal.file.FileCollectionFactory import org.gradle.api.internal.file.TestFiles import org.gradle.initialization.DefaultBuildCancellationToken import org.gradle.internal.jvm.Jvm +import spock.lang.Issue import spock.lang.Specification import spock.lang.Unroll @@ -104,6 +105,22 @@ class JavaExecHandleBuilderTest extends Specification { builder.classpath.contains(jar2) } + @Issue("gradle/gradle#8748") + def "can prepend to classpath"() { + given: + File jar1 = new File("file1.jar").canonicalFile + File jar2 = new File("file2.jar").canonicalFile + + builder.classpath(jar1) + + when: + builder.setClasspath(fileCollectionFactory.resolving(jar2, builder.getClasspath())) + + then: + builder.commandLine.contains("$jar2$File.pathSeparator$jar1".toString()) + + } + def "detects null entries early"() { when: builder.args(1, null) then: thrown(IllegalArgumentException) From 38a624027f325a60dc85641201a347dc438e4811 Mon Sep 17 00:00:00 2001 From: "Rodrigo B. de Oliveira" Date: Wed, 13 Mar 2019 10:50:08 -0300 Subject: [PATCH 513/853] Adapt Kotlin DSL test expectations to stricter Gradle interface impls Implementing interfaces explicitly instead of doing it by delegation as before causes the Kotlin compiler to introduce `null` checks that enforce the declared interface contract. The tests were assuming returning `null` from non-nullable functions was always valid. --- .../PrecompiledScriptPluginTemplatesTest.kt | 15 ++++++++++++--- .../SimplifiedKotlinScriptEvaluatorTest.kt | 8 +++++++- .../kotlin/dsl/DependencyHandlerExtensionsTest.kt | 14 ++++++++------ 3 files changed, 27 insertions(+), 10 deletions(-) diff --git a/subprojects/kotlin-dsl-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPluginTemplatesTest.kt b/subprojects/kotlin-dsl-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPluginTemplatesTest.kt index 6dbb7996f8f6d..8341ae8cde393 100644 --- a/subprojects/kotlin-dsl-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPluginTemplatesTest.kt +++ b/subprojects/kotlin-dsl-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPluginTemplatesTest.kt @@ -2,6 +2,7 @@ package org.gradle.kotlin.dsl.plugins.precompiled import com.nhaarman.mockito_kotlin.any import com.nhaarman.mockito_kotlin.doReturn +import com.nhaarman.mockito_kotlin.inOrder import com.nhaarman.mockito_kotlin.mock import com.nhaarman.mockito_kotlin.verify @@ -44,14 +45,22 @@ class PrecompiledScriptPluginTemplatesTest : AbstractPrecompiledScriptPluginTest """) - val project = mock() + val task = mock() + val project = mock { + on { task(any()) } doReturn task + } assertInstanceOf( instantiatePrecompiledScriptOf( project, - "My_project_script_gradle")) + "My_project_script_gradle" + ) + ) - verify(project).task("my-task") + inOrder(project, task) { + verify(project).task("my-task") + verifyNoMoreInteractions() + } } @Test diff --git a/subprojects/kotlin-dsl-test-fixtures/src/test/kotlin/org/gradle/kotlin/dsl/fixtures/SimplifiedKotlinScriptEvaluatorTest.kt b/subprojects/kotlin-dsl-test-fixtures/src/test/kotlin/org/gradle/kotlin/dsl/fixtures/SimplifiedKotlinScriptEvaluatorTest.kt index 5151c746dd8e4..7bbf0a85f1e1b 100644 --- a/subprojects/kotlin-dsl-test-fixtures/src/test/kotlin/org/gradle/kotlin/dsl/fixtures/SimplifiedKotlinScriptEvaluatorTest.kt +++ b/subprojects/kotlin-dsl-test-fixtures/src/test/kotlin/org/gradle/kotlin/dsl/fixtures/SimplifiedKotlinScriptEvaluatorTest.kt @@ -16,10 +16,13 @@ package org.gradle.kotlin.dsl.fixtures +import com.nhaarman.mockito_kotlin.any +import com.nhaarman.mockito_kotlin.doReturn import com.nhaarman.mockito_kotlin.mock import com.nhaarman.mockito_kotlin.verify import org.gradle.api.Project +import org.gradle.api.initialization.IncludedBuild import org.gradle.api.initialization.Settings import org.gradle.api.invocation.Gradle @@ -57,7 +60,10 @@ class SimplifiedKotlinScriptEvaluatorTest : TestWithTempFiles() { @Test fun `can eval script against Gradle mock`() { - val gradle = mock() + val includedBuild = mock() + val gradle = mock() { + on { includedBuild(any()) } doReturn includedBuild + } eval( script = """ includedBuild("foo") diff --git a/subprojects/kotlin-dsl/src/test/kotlin/org/gradle/kotlin/dsl/DependencyHandlerExtensionsTest.kt b/subprojects/kotlin-dsl/src/test/kotlin/org/gradle/kotlin/dsl/DependencyHandlerExtensionsTest.kt index cd5c67be61aff..a91ed8d837139 100644 --- a/subprojects/kotlin-dsl/src/test/kotlin/org/gradle/kotlin/dsl/DependencyHandlerExtensionsTest.kt +++ b/subprojects/kotlin-dsl/src/test/kotlin/org/gradle/kotlin/dsl/DependencyHandlerExtensionsTest.kt @@ -60,10 +60,11 @@ class DependencyHandlerExtensionsTest { @Test fun `given group and module, 'exclude' extension will build corresponding map`() { - val dependencies = DependencyHandlerScope.of(newDependencyHandlerMock()) + val dependencyHandlerMock = newDependencyHandlerMock() + val dependencies = DependencyHandlerScope.of(dependencyHandlerMock) val dependency: ExternalModuleDependency = mock() val events = mutableListOf() - whenever(dependencies.create("dependency")).then { + whenever(dependencyHandlerMock.create("dependency")).then { events.add("created") dependency } @@ -71,7 +72,7 @@ class DependencyHandlerExtensionsTest { events.add("configured") dependency } - whenever(dependencies.add("configuration", dependency)).then { + whenever(dependencyHandlerMock.add("configuration", dependency)).then { events.add("added") dependency } @@ -95,15 +96,16 @@ class DependencyHandlerExtensionsTest { @Test fun `given path and configuration, 'project' extension will build corresponding map`() { - val dependencies = DependencyHandlerScope.of(newDependencyHandlerMock()) + val dependencyHandlerMock = newDependencyHandlerMock() + val dependencies = DependencyHandlerScope.of(dependencyHandlerMock) val dependency: ProjectDependency = mock() val events = mutableListOf() val expectedProjectMap = mapOf("path" to ":project", "configuration" to "default") - whenever(dependencies.project(expectedProjectMap)).then { + whenever(dependencyHandlerMock.project(expectedProjectMap)).then { events.add("created") dependency } - whenever(dependencies.add("configuration", dependency)).then { + whenever(dependencyHandlerMock.add("configuration", dependency)).then { events.add("added") dependency } From fa26af6e71ac3f19dbeb1c49467f5455ceadf9ce Mon Sep 17 00:00:00 2001 From: Stefan Oehme Date: Wed, 13 Mar 2019 15:49:40 +0100 Subject: [PATCH 514/853] Detect changes to transitive dependencies on incremental compilation The incremental compiler was completely ignoring changes in transitive dependencies, except for changes to supertypes, which seems like a really weird decision. It has been fixed to instead take all possible transitive references into account. As a result the code is also simpler. --- ...entalJavaCompilationIntegrationTest.groovy | 43 ++++++++++++++++--- ...nUsingClassDirectoryIntegrationTest.groovy | 6 ++- .../analyzer/ClassAnalysisSerializer.java | 4 +- .../asm/ClassDependenciesVisitor.java | 18 +------- .../incremental/deps/ClassAnalysis.java | 8 +--- .../deps/ClassDependentsAccumulator.java | 11 ++--- .../deps/ClassSetAnalysisData.java | 34 +-------------- .../ClasspathChangeDependentsFinder.java | 10 ++--- .../ClassDependentsAccumulatorTest.groovy | 38 ++++++++-------- .../ClassSetAnalysisDataSerializerTest.groovy | 4 +- .../deps/ClassSetAnalysisTest.groovy | 10 ++--- 11 files changed, 80 insertions(+), 106 deletions(-) diff --git a/subprojects/language-java/src/integTest/groovy/org/gradle/java/compile/incremental/AbstractCrossTaskIncrementalJavaCompilationIntegrationTest.groovy b/subprojects/language-java/src/integTest/groovy/org/gradle/java/compile/incremental/AbstractCrossTaskIncrementalJavaCompilationIntegrationTest.groovy index acc49f14e9412..635c4981c175d 100644 --- a/subprojects/language-java/src/integTest/groovy/org/gradle/java/compile/incremental/AbstractCrossTaskIncrementalJavaCompilationIntegrationTest.groovy +++ b/subprojects/language-java/src/integTest/groovy/org/gradle/java/compile/incremental/AbstractCrossTaskIncrementalJavaCompilationIntegrationTest.groovy @@ -71,17 +71,50 @@ abstract class AbstractCrossTaskIncrementalJavaCompilationIntegrationTest extend impl.recompiledClasses("ImplA") } + def "detects change to transitive superclass in an upstream project"() { + settingsFile << """ + include 'app' + """ + buildFile << """ + project(':app') { + dependencies { compile project(path:':impl', configuration: 'classesDir') } + } + """ + def app = new CompilationOutputsFixture(file("app/build/classes")) + java api: ["class A {}"] + java impl: ["class B extends A {}"] + java app: ["class Unrelated {}", "class C extends B {}", "class D extends C {}"] + app.snapshot { run "compileJava" } + + when: + java api: ["class A { String change; }"] + run "app:compileJava" + + then: + app.recompiledClasses("C", "D") + } + def "detects change to transitive dependency in an upstream project"() { - java api: ["class A {}", "class B extends A {}"] - java impl: ["class SomeImpl {}", "class ImplB extends B {}", "class ImplB2 extends ImplB {}"] - impl.snapshot { run "compileJava" } + settingsFile << """ + include 'app' + """ + buildFile << """ + project(':app') { + dependencies { compile project(path:':impl', configuration: 'classesDir') } + } + """ + def app = new CompilationOutputsFixture(file("app/build/classes")) + java api: ["class A {}"] + java impl: ["class B { public A a;}"] + java app: ["class Unrelated {}", "class C { public B b; }"] + app.snapshot { run "compileJava" } when: java api: ["class A { String change; }"] - run "impl:compileJava" + run "app:compileJava" then: - impl.recompiledClasses("ImplB", "ImplB2") + app.recompiledClasses("C") } def "deletion of jar without dependents does not recompile any classes"() { diff --git a/subprojects/language-java/src/integTest/groovy/org/gradle/java/compile/incremental/CrossTaskIncrementalJavaCompilationUsingClassDirectoryIntegrationTest.groovy b/subprojects/language-java/src/integTest/groovy/org/gradle/java/compile/incremental/CrossTaskIncrementalJavaCompilationUsingClassDirectoryIntegrationTest.groovy index 6c82b29058d74..891bbc3a1a610 100644 --- a/subprojects/language-java/src/integTest/groovy/org/gradle/java/compile/incremental/CrossTaskIncrementalJavaCompilationUsingClassDirectoryIntegrationTest.groovy +++ b/subprojects/language-java/src/integTest/groovy/org/gradle/java/compile/incremental/CrossTaskIncrementalJavaCompilationUsingClassDirectoryIntegrationTest.groovy @@ -22,9 +22,11 @@ class CrossTaskIncrementalJavaCompilationUsingClassDirectoryIntegrationTest exte @Override protected String getProjectDependencyBlock() { ''' - project(':api') { + subprojects { configurations { - classesDir + classesDir { + extendsFrom(compile) + } } artifacts { classesDir file: compileJava.destinationDir, builtBy:compileJava diff --git a/subprojects/language-java/src/main/java/org/gradle/api/internal/tasks/compile/incremental/analyzer/ClassAnalysisSerializer.java b/subprojects/language-java/src/main/java/org/gradle/api/internal/tasks/compile/incremental/analyzer/ClassAnalysisSerializer.java index 5156626cfd57f..fc66e58958fa8 100644 --- a/subprojects/language-java/src/main/java/org/gradle/api/internal/tasks/compile/incremental/analyzer/ClassAnalysisSerializer.java +++ b/subprojects/language-java/src/main/java/org/gradle/api/internal/tasks/compile/incremental/analyzer/ClassAnalysisSerializer.java @@ -44,8 +44,7 @@ public ClassAnalysis read(Decoder decoder) throws Exception { boolean relatedToAll = decoder.readBoolean(); Set classes = stringSetSerializer.read(decoder); IntSet constants = IntSetSerializer.INSTANCE.read(decoder); - Set superTypes = stringSetSerializer.read(decoder); - return new ClassAnalysis(className, classes, relatedToAll, constants, superTypes); + return new ClassAnalysis(className, classes, relatedToAll, constants); } @Override @@ -54,7 +53,6 @@ public void write(Encoder encoder, ClassAnalysis value) throws Exception { encoder.writeBoolean(value.isDependencyToAll()); stringSetSerializer.write(encoder, value.getClassDependencies()); IntSetSerializer.INSTANCE.write(encoder, value.getConstants()); - stringSetSerializer.write(encoder, value.getSuperTypes()); } } diff --git a/subprojects/language-java/src/main/java/org/gradle/api/internal/tasks/compile/incremental/asm/ClassDependenciesVisitor.java b/subprojects/language-java/src/main/java/org/gradle/api/internal/tasks/compile/incremental/asm/ClassDependenciesVisitor.java index a5b97897805ec..21a5d2156d54a 100644 --- a/subprojects/language-java/src/main/java/org/gradle/api/internal/tasks/compile/incremental/asm/ClassDependenciesVisitor.java +++ b/subprojects/language-java/src/main/java/org/gradle/api/internal/tasks/compile/incremental/asm/ClassDependenciesVisitor.java @@ -21,8 +21,8 @@ import it.unimi.dsi.fastutil.ints.IntOpenHashSet; import it.unimi.dsi.fastutil.ints.IntSet; import org.gradle.api.internal.cache.StringInterner; -import org.gradle.internal.classanalysis.AsmConstants; import org.gradle.api.internal.tasks.compile.incremental.deps.ClassAnalysis; +import org.gradle.internal.classanalysis.AsmConstants; import org.objectweb.asm.ClassReader; import org.objectweb.asm.ClassVisitor; import org.objectweb.asm.Label; @@ -41,7 +41,6 @@ public class ClassDependenciesVisitor extends ClassVisitor { private final MethodVisitor methodVisitor; private final FieldVisitor fieldVisitor; private final IntSet constants; - private final Set superTypes; private final Set types; private final Predicate typeFilter; private final StringInterner interner; @@ -54,7 +53,6 @@ private ClassDependenciesVisitor(Predicate typeFilter, ClassReader reade super(API); this.constants = new IntOpenHashSet(2); this.types = Sets.newHashSet(); - this.superTypes = Sets.newHashSet(); this.methodVisitor = new MethodVisitor(); this.fieldVisitor = new FieldVisitor(); this.retentionPolicyVisitor = new RetentionPolicyVisitor(); @@ -67,7 +65,7 @@ private ClassDependenciesVisitor(Predicate typeFilter, ClassReader reade public static ClassAnalysis analyze(String className, ClassReader reader, StringInterner interner) { ClassDependenciesVisitor visitor = new ClassDependenciesVisitor(new ClassRelevancyFilter(className), reader, interner); reader.accept(visitor, ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES); - return new ClassAnalysis(interner.intern(className), visitor.getClassDependencies(), visitor.isDependencyToAll(), visitor.getConstants(), visitor.getSuperTypes()); + return new ClassAnalysis(interner.intern(className), visitor.getClassDependencies(), visitor.isDependencyToAll(), visitor.getConstants()); } @Override @@ -77,13 +75,11 @@ public void visit(int version, int access, String name, String signature, String // superName can be null if what we are analyzing is `java.lang.Object` // which can happen when a custom Java SDK is on classpath (typically, android.jar) String type = typeOfFromSlashyString(superName); - maybeAddSuperType(type); maybeAddDependentType(type); } for (String s : interfaces) { String interfaceType = typeOfFromSlashyString(s); maybeAddDependentType(interfaceType); - maybeAddSuperType(interfaceType); } } @@ -117,12 +113,6 @@ private void collectClassDependencies(ClassReader reader) { } } - protected void maybeAddSuperType(String type) { - if (typeFilter.apply(type)) { - superTypes.add(intern(type)); - } - } - protected void maybeAddDependentType(String type) { if (typeFilter.apply(type)) { types.add(intern(type)); @@ -137,10 +127,6 @@ protected String typeOfFromSlashyString(String slashyStyleDesc) { return Type.getObjectType(slashyStyleDesc).getClassName(); } - public Set getSuperTypes() { - return superTypes; - } - public Set getClassDependencies() { return types; } diff --git a/subprojects/language-java/src/main/java/org/gradle/api/internal/tasks/compile/incremental/deps/ClassAnalysis.java b/subprojects/language-java/src/main/java/org/gradle/api/internal/tasks/compile/incremental/deps/ClassAnalysis.java index 298f6102ab82f..43fbf93b44458 100644 --- a/subprojects/language-java/src/main/java/org/gradle/api/internal/tasks/compile/incremental/deps/ClassAnalysis.java +++ b/subprojects/language-java/src/main/java/org/gradle/api/internal/tasks/compile/incremental/deps/ClassAnalysis.java @@ -30,14 +30,12 @@ public class ClassAnalysis { private final Set classDependencies; private final boolean dependencyToAll; private final IntSet constants; - private final Set superTypes; - public ClassAnalysis(String className, Set classDependencies, boolean dependencyToAll, IntSet constants, Set superTypes) { + public ClassAnalysis(String className, Set classDependencies, boolean dependencyToAll, IntSet constants) { this.className = className; this.classDependencies = ImmutableSet.copyOf(classDependencies); this.dependencyToAll = dependencyToAll; this.constants = constants.isEmpty() ? IntSets.EMPTY_SET : constants; - this.superTypes = ImmutableSet.copyOf(superTypes); } public String getClassName() { @@ -55,8 +53,4 @@ public IntSet getConstants() { public boolean isDependencyToAll() { return dependencyToAll; } - - public Set getSuperTypes() { - return superTypes; - } } diff --git a/subprojects/language-java/src/main/java/org/gradle/api/internal/tasks/compile/incremental/deps/ClassDependentsAccumulator.java b/subprojects/language-java/src/main/java/org/gradle/api/internal/tasks/compile/incremental/deps/ClassDependentsAccumulator.java index d915f986fc278..c779e06deb53d 100644 --- a/subprojects/language-java/src/main/java/org/gradle/api/internal/tasks/compile/incremental/deps/ClassDependentsAccumulator.java +++ b/subprojects/language-java/src/main/java/org/gradle/api/internal/tasks/compile/incremental/deps/ClassDependentsAccumulator.java @@ -17,7 +17,6 @@ package org.gradle.api.internal.tasks.compile.incremental.deps; import com.google.common.annotations.VisibleForTesting; -import com.google.common.collect.HashMultimap; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Multimap; @@ -35,14 +34,13 @@ public class ClassDependentsAccumulator { private final Map> dependents = new HashMap>(); private final ImmutableMap.Builder classesToConstants = ImmutableMap.builder(); private final Set seenClasses = Sets.newHashSet(); - private final Multimap parentToChildren = HashMultimap.create(); private String fullRebuildCause; public void addClass(ClassAnalysis classAnalysis) { - addClass(classAnalysis.getClassName(), classAnalysis.isDependencyToAll(), classAnalysis.getClassDependencies(), classAnalysis.getConstants(), classAnalysis.getSuperTypes()); + addClass(classAnalysis.getClassName(), classAnalysis.isDependencyToAll(), classAnalysis.getClassDependencies(), classAnalysis.getConstants()); } - public void addClass(String className, boolean dependencyToAll, Iterable classDependencies, IntSet constants, Set superTypes) { + public void addClass(String className, boolean dependencyToAll, Iterable classDependencies, IntSet constants) { if (seenClasses.contains(className)) { // same classes may be found in different classpath trees/jars // and we keep only the first one @@ -61,9 +59,6 @@ public void addClass(String className, boolean dependencyToAll, Iterable addDependency(dependency, className); } } - for (String superType : superTypes) { - parentToChildren.put(superType, className); - } } private Set rememberClass(String className) { @@ -105,7 +100,7 @@ public void fullRebuildNeeded(String fullRebuildCause) { } public ClassSetAnalysisData getAnalysis() { - return new ClassSetAnalysisData(ImmutableSet.copyOf(seenClasses), getDependentsMap(), getClassesToConstants(), asMap(parentToChildren), fullRebuildCause); + return new ClassSetAnalysisData(ImmutableSet.copyOf(seenClasses), getDependentsMap(), getClassesToConstants(), fullRebuildCause); } private static Map> asMap(Multimap multimap) { diff --git a/subprojects/language-java/src/main/java/org/gradle/api/internal/tasks/compile/incremental/deps/ClassSetAnalysisData.java b/subprojects/language-java/src/main/java/org/gradle/api/internal/tasks/compile/incremental/deps/ClassSetAnalysisData.java index 79c90bb3088ad..27f584449f831 100644 --- a/subprojects/language-java/src/main/java/org/gradle/api/internal/tasks/compile/incremental/deps/ClassSetAnalysisData.java +++ b/subprojects/language-java/src/main/java/org/gradle/api/internal/tasks/compile/incremental/deps/ClassSetAnalysisData.java @@ -29,7 +29,6 @@ import org.gradle.internal.serialize.IntSetSerializer; import java.io.IOException; -import java.util.Collections; import java.util.HashMap; import java.util.Map; import java.util.Set; @@ -40,14 +39,12 @@ public class ClassSetAnalysisData { private final Set classes; private final Map dependents; private final Map classesToConstants; - private final Map> classesToChildren; private final String fullRebuildCause; - public ClassSetAnalysisData(Set classes, Map dependents, Map classesToConstants, Map> classesToChildren, String fullRebuildCause) { + public ClassSetAnalysisData(Set classes, Map dependents, Map classesToConstants, String fullRebuildCause) { this.classes = classes; this.dependents = dependents; this.classesToConstants = classesToConstants; - this.classesToChildren = classesToChildren; this.fullRebuildCause = fullRebuildCause; } @@ -82,11 +79,6 @@ public IntSet getConstants(String className) { return integers; } - public Set getChildren(String className) { - Set children = classesToChildren.get(className); - return children == null ? Collections.emptySet() : children; - } - public static class Serializer extends AbstractSerializer { private final StringInterner interner; @@ -121,21 +113,9 @@ public ClassSetAnalysisData read(Decoder decoder) throws Exception { classesToConstantsBuilder.put(className, constants); } - count = decoder.readSmallInt(); - ImmutableMap.Builder> classNameToChildren = ImmutableMap.builder(); - for (int i = 0; i < count; i++) { - String parent = readClassName(decoder, classNameMap); - int nameCount = decoder.readSmallInt(); - ImmutableSet.Builder namesBuilder = ImmutableSet.builder(); - for (int j = 0; j < nameCount; j++) { - namesBuilder.add(readClassName(decoder, classNameMap)); - } - classNameToChildren.put(parent, namesBuilder.build()); - } - String fullRebuildCause = decoder.readNullableString(); - return new ClassSetAnalysisData(classes.build(), dependentsBuilder.build(), classesToConstantsBuilder.build(), classNameToChildren.build(), fullRebuildCause); + return new ClassSetAnalysisData(classes.build(), dependentsBuilder.build(), classesToConstantsBuilder.build(), fullRebuildCause); } @Override @@ -157,16 +137,6 @@ public void write(Encoder encoder, ClassSetAnalysisData value) throws Exception writeClassName(entry.getKey(), classNameMap, encoder); IntSetSerializer.INSTANCE.write(encoder, entry.getValue()); } - - encoder.writeSmallInt(value.classesToChildren.size()); - for (Map.Entry> entry : value.classesToChildren.entrySet()) { - writeClassName(entry.getKey(), classNameMap, encoder); - encoder.writeSmallInt(entry.getValue().size()); - for (String className : entry.getValue()) { - writeClassName(className, classNameMap, encoder); - } - } - encoder.writeNullableString(value.fullRebuildCause); } diff --git a/subprojects/language-java/src/main/java/org/gradle/api/internal/tasks/compile/incremental/recomp/ClasspathChangeDependentsFinder.java b/subprojects/language-java/src/main/java/org/gradle/api/internal/tasks/compile/incremental/recomp/ClasspathChangeDependentsFinder.java index ac202471f37a0..548a1c53655ea 100644 --- a/subprojects/language-java/src/main/java/org/gradle/api/internal/tasks/compile/incremental/recomp/ClasspathChangeDependentsFinder.java +++ b/subprojects/language-java/src/main/java/org/gradle/api/internal/tasks/compile/incremental/recomp/ClasspathChangeDependentsFinder.java @@ -93,13 +93,11 @@ public DependentsSet getActualDependents(InputFileDetails entryChangeDetails, Fi @Override public void execute(ClasspathEntrySnapshot classpathEntrySnapshot) { if (classpathEntrySnapshot != previous) { - // we need to find classes in other entries that would potentially extend classes changed - // in the current snapshot (they are intermediates) ClassSetAnalysisData data = classpathEntrySnapshot.getData().getClassAnalysis(); - Set children = data.getChildren(dependentClass); - for (String child : children) { - if (dependentClasses.add(child)) { - queue.add(child); + Set intermediates = data.getDependents(dependentClass).getDependentClasses(); + for (String intermediate : intermediates) { + if (dependentClasses.add(intermediate)) { + queue.add(intermediate); } } } diff --git a/subprojects/language-java/src/test/groovy/org/gradle/api/internal/tasks/compile/incremental/deps/ClassDependentsAccumulatorTest.groovy b/subprojects/language-java/src/test/groovy/org/gradle/api/internal/tasks/compile/incremental/deps/ClassDependentsAccumulatorTest.groovy index ba71a3b5ea0da..1e96836bf2f9d 100644 --- a/subprojects/language-java/src/test/groovy/org/gradle/api/internal/tasks/compile/incremental/deps/ClassDependentsAccumulatorTest.groovy +++ b/subprojects/language-java/src/test/groovy/org/gradle/api/internal/tasks/compile/incremental/deps/ClassDependentsAccumulatorTest.groovy @@ -31,9 +31,9 @@ class ClassDependentsAccumulatorTest extends Specification { def "remembers if class is dependency to all"() { // a -> b -> c - accumulator.addClass("a", false, ["b"], IntSets.EMPTY_SET, [] as Set) - accumulator.addClass("b", true, ["c"], IntSets.EMPTY_SET, [] as Set) - accumulator.addClass("c", false, ["a"] as Set, IntSets.EMPTY_SET, [] as Set) + accumulator.addClass("a", false, ["b"], IntSets.EMPTY_SET) + accumulator.addClass("b", true, ["c"], IntSets.EMPTY_SET) + accumulator.addClass("c", false, ["a"] as Set, IntSets.EMPTY_SET) expect: !accumulator.dependentsMap.a.dependencyToAll @@ -43,9 +43,9 @@ class ClassDependentsAccumulatorTest extends Specification { def "remembers if class declares non-private constants"() { // a -> b -> c - accumulator.addClass("a", false, ["b"], new IntOpenHashSet(1, 2, 3, 5, 8), [] as Set) - accumulator.addClass("b", false, ["c"], new IntOpenHashSet([0, 8]), [] as Set) - accumulator.addClass("c", false, [], new IntOpenHashSet([3, 4]), [] as Set) + accumulator.addClass("a", false, ["b"], new IntOpenHashSet(1, 2, 3, 5, 8)) + accumulator.addClass("b", false, ["c"], new IntOpenHashSet([0, 8])) + accumulator.addClass("c", false, [], new IntOpenHashSet([3, 4])) expect: accumulator.classesToConstants.get('a') == [1, 2, 3, 5, 8] as Set @@ -54,10 +54,10 @@ class ClassDependentsAccumulatorTest extends Specification { } def "accumulates dependents"() { - accumulator.addClass("d", true, ['x'], IntSets.EMPTY_SET, [] as Set) - accumulator.addClass("a", false, ["b", "c"], IntSets.EMPTY_SET, [] as Set) - accumulator.addClass("b", true, ["c", "a"], IntSets.EMPTY_SET, [] as Set) - accumulator.addClass("c", false, [] as Set, IntSets.EMPTY_SET, [] as Set) + accumulator.addClass("d", true, ['x'], IntSets.EMPTY_SET) + accumulator.addClass("a", false, ["b", "c"], IntSets.EMPTY_SET) + accumulator.addClass("b", true, ["c", "a"], IntSets.EMPTY_SET) + accumulator.addClass("c", false, [] as Set, IntSets.EMPTY_SET) expect: accumulator.dependentsMap.a.dependentClasses == ['b'] as Set @@ -68,33 +68,33 @@ class ClassDependentsAccumulatorTest extends Specification { } def "creates keys for all encountered classes which are dependency to another"() { - accumulator.addClass("a", false, ["x"], IntSets.EMPTY_SET, [] as Set) - accumulator.addClass("b", true, ["a", "b"], IntSets.EMPTY_SET, [] as Set) - accumulator.addClass("c", true, [] as Set, IntSets.EMPTY_SET, [] as Set) - accumulator.addClass("e", false, [] as Set, IntSets.EMPTY_SET, [] as Set) + accumulator.addClass("a", false, ["x"], IntSets.EMPTY_SET) + accumulator.addClass("b", true, ["a", "b"], IntSets.EMPTY_SET) + accumulator.addClass("c", true, [] as Set, IntSets.EMPTY_SET) + accumulator.addClass("e", false, [] as Set, IntSets.EMPTY_SET) expect: accumulator.dependentsMap.keySet() == ["a", "b", "c", "x"] as Set } def "knows when class is dependent to all if that class is added first"() { - accumulator.addClass("b", true, [] as Set, IntSets.EMPTY_SET, [] as Set) - accumulator.addClass("a", false, ["b"], IntSets.EMPTY_SET, [] as Set) + accumulator.addClass("b", true, [] as Set, IntSets.EMPTY_SET) + accumulator.addClass("a", false, ["b"], IntSets.EMPTY_SET) expect: accumulator.dependentsMap.b.dependencyToAll } def "knows when class is dependent to all even if that class is added last"() { - accumulator.addClass("a", false, ["b"], IntSets.EMPTY_SET, [] as Set) - accumulator.addClass("b", true, [] as Set, IntSets.EMPTY_SET, [] as Set) + accumulator.addClass("a", false, ["b"], IntSets.EMPTY_SET) + accumulator.addClass("b", true, [] as Set, IntSets.EMPTY_SET) expect: accumulator.dependentsMap.b.dependencyToAll } def "filters out self dependencies"() { - accumulator.addClass("a", false, ["a", "b"], IntSets.EMPTY_SET, [] as Set) + accumulator.addClass("a", false, ["a", "b"], IntSets.EMPTY_SET) expect: accumulator.dependentsMap["b"].dependentClasses == ["a"] as Set diff --git a/subprojects/language-java/src/test/groovy/org/gradle/api/internal/tasks/compile/incremental/deps/ClassSetAnalysisDataSerializerTest.groovy b/subprojects/language-java/src/test/groovy/org/gradle/api/internal/tasks/compile/incremental/deps/ClassSetAnalysisDataSerializerTest.groovy index 447fc6256faf8..cd3ec7f71a0ee 100644 --- a/subprojects/language-java/src/test/groovy/org/gradle/api/internal/tasks/compile/incremental/deps/ClassSetAnalysisDataSerializerTest.groovy +++ b/subprojects/language-java/src/test/groovy/org/gradle/api/internal/tasks/compile/incremental/deps/ClassSetAnalysisDataSerializerTest.groovy @@ -36,8 +36,7 @@ class ClassSetAnalysisDataSerializerTest extends Specification { def data = new ClassSetAnalysisData(["A", "B", "C", "D"] as Set, ["A": dependents("B", "C"), "B": dependents("C"), "C": dependents(), "D": dependencyToAll(),], [C: new IntOpenHashSet([1, 2]) as IntSet, D: IntSets.EMPTY_SET] - , - ['A': ['SA'] as Set, B: ['SB1', 'SB2'] as Set], "Because" + ,"Because" ) def os = new ByteArrayOutputStream() def e = new OutputStreamBackedEncoder(os) @@ -56,7 +55,6 @@ class ClassSetAnalysisDataSerializerTest extends Specification { read.dependents["D"].dependencyToAll read.classesToConstants == [C: [1,2] as Set, D: [] as Set] - read.classesToChildren == ['A': ['SA'] as Set, B: ['SB1', 'SB2'] as Set] read.fullRebuildCause == "Because" } } diff --git a/subprojects/language-java/src/test/groovy/org/gradle/api/internal/tasks/compile/incremental/deps/ClassSetAnalysisTest.groovy b/subprojects/language-java/src/test/groovy/org/gradle/api/internal/tasks/compile/incremental/deps/ClassSetAnalysisTest.groovy index 0d2c15da10be4..66b2e7ee26b13 100644 --- a/subprojects/language-java/src/test/groovy/org/gradle/api/internal/tasks/compile/incremental/deps/ClassSetAnalysisTest.groovy +++ b/subprojects/language-java/src/test/groovy/org/gradle/api/internal/tasks/compile/incremental/deps/ClassSetAnalysisTest.groovy @@ -27,9 +27,9 @@ class ClassSetAnalysisTest extends Specification { ClassSetAnalysis analysis(Map dependents, Map classToConstants = [:], - Map> classesToChildren = [:], DependentsSet aggregatedTypes = empty(), DependentsSet dependentsOnAll = empty(), String fullRebuildCause = null) { + DependentsSet aggregatedTypes = empty(), DependentsSet dependentsOnAll = empty(), String fullRebuildCause = null) { new ClassSetAnalysis( - new ClassSetAnalysisData(dependents.keySet(), dependents, classToConstants, classesToChildren, fullRebuildCause), + new ClassSetAnalysisData(dependents.keySet(), dependents, classToConstants, fullRebuildCause), new AnnotationProcessingData([:], aggregatedTypes.dependentClasses, dependentsOnAll.dependentClasses, null) ) } @@ -164,8 +164,8 @@ class ClassSetAnalysisTest extends Specification { def "some classes may depend on any change"() { def a = analysis([ - "A": dependents("B"), "B": empty(), "DependsOnAny" : dependents("C") - ], [:], [:], empty(), dependents("DependsOnAny") ) + "A": dependents("B"), "B": empty(), "DependsOnAny": dependents("C") + ], [:], empty(), dependents("DependsOnAny")) def deps = a.getRelevantDependents(["A"], IntSets.EMPTY_SET) expect: @@ -197,7 +197,7 @@ class ClassSetAnalysisTest extends Specification { def "all classes are dependencies to all if a full rebuild cause is given"() { def a = analysis( - [:], [:], [:], empty(), empty(), "Some cause" + [:], [:], empty(), empty(), "Some cause" ) expect: From e6d72d68e845e198a0f13d7c0a41cad126fbfd22 Mon Sep 17 00:00:00 2001 From: "Rodrigo B. de Oliveira" Date: Wed, 13 Mar 2019 12:27:22 -0300 Subject: [PATCH 515/853] Explain the purpose of the decorator types --- .../dsl/support/decorators/ArtifactHandlerDecorator.kt | 5 +++++ .../decorators/DependencyConstraintHandlerDecorator.kt | 5 +++++ .../support/decorators/DependencyHandlerDecorator.kt | 5 +++++ .../kotlin/dsl/support/decorators/GradleDecorator.kt | 10 ++++++++++ .../decorators/NamedDomainObjectContainerDecorator.kt | 5 +++++ .../kotlin/dsl/support/decorators/ProjectDecorator.kt | 5 +++++ .../dsl/support/decorators/ScriptHandlerDecorator.kt | 5 +++++ .../kotlin/dsl/support/decorators/SettingsDecorator.kt | 5 +++++ 8 files changed, 45 insertions(+) diff --git a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/decorators/ArtifactHandlerDecorator.kt b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/decorators/ArtifactHandlerDecorator.kt index 960ce1d74778b..af2bd1c6aaccf 100644 --- a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/decorators/ArtifactHandlerDecorator.kt +++ b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/decorators/ArtifactHandlerDecorator.kt @@ -24,6 +24,11 @@ import org.gradle.api.artifacts.PublishArtifact import org.gradle.api.artifacts.dsl.ArtifactHandler +/** + * Facilitates the implementation of the [ArtifactHandler] interface by delegation via subclassing. + * + * See [GradleDecorator] for details why this is currently necessary. + */ abstract class ArtifactHandlerDecorator : ArtifactHandler { internal diff --git a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/decorators/DependencyConstraintHandlerDecorator.kt b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/decorators/DependencyConstraintHandlerDecorator.kt index cb8ebf3c48381..c0d42dc2b71df 100644 --- a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/decorators/DependencyConstraintHandlerDecorator.kt +++ b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/decorators/DependencyConstraintHandlerDecorator.kt @@ -21,6 +21,11 @@ import org.gradle.api.artifacts.DependencyConstraint import org.gradle.api.artifacts.dsl.DependencyConstraintHandler +/** + * Facilitates the implementation of the [DependencyConstraintHandler] interface by delegation via subclassing. + * + * See [GradleDecorator] for details why this is currently necessary. + */ abstract class DependencyConstraintHandlerDecorator : DependencyConstraintHandler { internal diff --git a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/decorators/DependencyHandlerDecorator.kt b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/decorators/DependencyHandlerDecorator.kt index de0915ba26988..f24b2427ce908 100644 --- a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/decorators/DependencyHandlerDecorator.kt +++ b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/decorators/DependencyHandlerDecorator.kt @@ -33,6 +33,11 @@ import org.gradle.api.artifacts.type.ArtifactTypeContainer import org.gradle.api.attributes.AttributesSchema +/** + * Facilitates the implementation of the [DependencyHandler] interface by delegation via subclassing. + * + * See [GradleDecorator] for details why this is currently necessary. + */ abstract class DependencyHandlerDecorator : DependencyHandler { internal diff --git a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/decorators/GradleDecorator.kt b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/decorators/GradleDecorator.kt index 9e0212f293951..0b9d5f1723f74 100644 --- a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/decorators/GradleDecorator.kt +++ b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/decorators/GradleDecorator.kt @@ -35,6 +35,16 @@ import org.gradle.api.plugins.PluginManager import java.io.File +/** + * Facilitates the implementation of the [Gradle] interface by delegation via subclassing. + * + * So we can avoid Kotlin's [implementation by delegation](https://kotlinlang.org/docs/reference/delegation.html#implementation-by-delegation) + * until all required interfaces have been compiled with Java 8 parameter names (otherwise parameter names + * are lost in the exposed implementation). + * + * Once the required interfaces are compiled with Java 8 parameter names these classes can be removed in favor + * of Kotlin's implementation by delegation. + */ abstract class GradleDecorator : Gradle { internal diff --git a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/decorators/NamedDomainObjectContainerDecorator.kt b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/decorators/NamedDomainObjectContainerDecorator.kt index d4574cf469d97..dae4520637d67 100644 --- a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/decorators/NamedDomainObjectContainerDecorator.kt +++ b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/decorators/NamedDomainObjectContainerDecorator.kt @@ -33,6 +33,11 @@ import java.util.SortedMap import java.util.SortedSet +/** + * Facilitates the implementation of the [NamedDomainObjectContainer] interface by delegation via subclassing. + * + * See [GradleDecorator] for details why this is currently necessary. + */ abstract class NamedDomainObjectContainerDecorator : NamedDomainObjectContainer { abstract val delegate: NamedDomainObjectContainer diff --git a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/decorators/ProjectDecorator.kt b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/decorators/ProjectDecorator.kt index e1d9966712130..8acc980afc38e 100644 --- a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/decorators/ProjectDecorator.kt +++ b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/decorators/ProjectDecorator.kt @@ -65,6 +65,11 @@ import java.net.URI import java.util.concurrent.Callable +/** + * Facilitates the implementation of the [Project] interface by delegation via subclassing. + * + * See [GradleDecorator] for details why this is currently necessary. + */ abstract class ProjectDecorator() : Project { internal diff --git a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/decorators/ScriptHandlerDecorator.kt b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/decorators/ScriptHandlerDecorator.kt index 1de8b52045bec..a933638fede6b 100644 --- a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/decorators/ScriptHandlerDecorator.kt +++ b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/decorators/ScriptHandlerDecorator.kt @@ -28,6 +28,11 @@ import java.io.File import java.net.URI +/** + * Facilitates the implementation of the [ScriptHandler] interface by delegation via subclassing. + * + * See [GradleDecorator] for details why this is currently necessary. + */ abstract class ScriptHandlerDecorator : ScriptHandler { internal diff --git a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/decorators/SettingsDecorator.kt b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/decorators/SettingsDecorator.kt index 0bbca58bbb8de..8dd05fa885652 100644 --- a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/decorators/SettingsDecorator.kt +++ b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/decorators/SettingsDecorator.kt @@ -36,6 +36,11 @@ import org.gradle.vcs.SourceControl import java.io.File +/** + * Facilitates the implementation of the [Settings] interface by delegation via subclassing. + * + * See [GradleDecorator] for details why this is currently necessary. + */ abstract class SettingsDecorator : Settings { internal From e07e6e565321137a9328e38e00210ee38e677d7d Mon Sep 17 00:00:00 2001 From: Stefan Oehme Date: Wed, 13 Mar 2019 16:29:47 +0100 Subject: [PATCH 516/853] Handle removals of classes transitively After further cleaning up our class change detection logic, I noticed that we were handling additions and removals very differently. This has been corrected and we now detect transitive removals too. This doesn't happen often in practice, as one needs to deliberately exclude a task to trigger the bug that was fixed. Nevertheless, it's good to have symmetric logic. --- ...entalJavaCompilationIntegrationTest.groovy | 28 +++++ .../classpath/ClasspathEntrySnapshot.java | 32 ++--- .../classpath/ClasspathSnapshot.java | 8 -- ...AffectedClasses.java => ClassChanges.java} | 12 +- .../ClasspathChangeDependentsFinder.java | 118 ++++++++++-------- .../ClasspathEntrySnapshotTest.groovy | 58 ++------- 6 files changed, 117 insertions(+), 139 deletions(-) rename subprojects/language-java/src/main/java/org/gradle/api/internal/tasks/compile/incremental/deps/{AffectedClasses.java => ClassChanges.java} (78%) diff --git a/subprojects/language-java/src/integTest/groovy/org/gradle/java/compile/incremental/AbstractCrossTaskIncrementalJavaCompilationIntegrationTest.groovy b/subprojects/language-java/src/integTest/groovy/org/gradle/java/compile/incremental/AbstractCrossTaskIncrementalJavaCompilationIntegrationTest.groovy index 635c4981c175d..2356199917e97 100644 --- a/subprojects/language-java/src/integTest/groovy/org/gradle/java/compile/incremental/AbstractCrossTaskIncrementalJavaCompilationIntegrationTest.groovy +++ b/subprojects/language-java/src/integTest/groovy/org/gradle/java/compile/incremental/AbstractCrossTaskIncrementalJavaCompilationIntegrationTest.groovy @@ -117,6 +117,34 @@ abstract class AbstractCrossTaskIncrementalJavaCompilationIntegrationTest extend app.recompiledClasses("C") } + def "detects deletions of transitive dependency in an upstream project"() { + settingsFile << """ + include 'app' + """ + buildFile << """ + project(':app') { + dependencies { compile project(path:':impl', configuration: 'classesDir') } + } + """ + def app = new CompilationOutputsFixture(file("app/build/classes")) + java api: ["class A {}"] + java impl: ["class B { public A a;}"] + java app: ["class Unrelated {}", "class C { public B b; }"] + app.snapshot { + impl.snapshot { + run "compileJava" + } + } + + when: + file("api/src/main/java/A.java").delete() + fails "app:compileJava", "-X", "impl:compileJava" + + then: + impl.noneRecompiled() + app.recompiledClasses("C") + } + def "deletion of jar without dependents does not recompile any classes"() { java api: ["class A {}"], impl: ["class SomeImpl {}"] impl.snapshot { run "compileJava" } diff --git a/subprojects/language-java/src/main/java/org/gradle/api/internal/tasks/compile/incremental/classpath/ClasspathEntrySnapshot.java b/subprojects/language-java/src/main/java/org/gradle/api/internal/tasks/compile/incremental/classpath/ClasspathEntrySnapshot.java index 7234271dfc4f5..0fbea8060795a 100644 --- a/subprojects/language-java/src/main/java/org/gradle/api/internal/tasks/compile/incremental/classpath/ClasspathEntrySnapshot.java +++ b/subprojects/language-java/src/main/java/org/gradle/api/internal/tasks/compile/incremental/classpath/ClasspathEntrySnapshot.java @@ -19,9 +19,8 @@ import it.unimi.dsi.fastutil.ints.IntOpenHashSet; import it.unimi.dsi.fastutil.ints.IntSet; import it.unimi.dsi.fastutil.ints.IntSets; -import org.gradle.api.internal.tasks.compile.incremental.deps.AffectedClasses; +import org.gradle.api.internal.tasks.compile.incremental.deps.ClassChanges; import org.gradle.api.internal.tasks.compile.incremental.deps.ClassSetAnalysis; -import org.gradle.api.internal.tasks.compile.incremental.deps.ClassSetAnalysisData; import org.gradle.api.internal.tasks.compile.incremental.deps.DependentsSet; import org.gradle.internal.hash.HashCode; @@ -70,38 +69,23 @@ public IntSet getRelevantConstants(ClasspathEntrySnapshot other, Set aff return result; } - public AffectedClasses getAffectedClassesSince(ClasspathEntrySnapshot other) { - DependentsSet affectedClasses = affectedSince(other); + public ClassChanges getChangedClassesSince(ClasspathEntrySnapshot other) { + Set modifiedClasses = modifiedSince(other); Set addedClasses = addedSince(other); - return new AffectedClasses(affectedClasses, addedClasses); + return new ClassChanges(modifiedClasses, addedClasses); } - private DependentsSet affectedSince(ClasspathEntrySnapshot other) { - final Set affected = new HashSet(); + private Set modifiedSince(ClasspathEntrySnapshot other) { + final Set modified = new HashSet(); for (Map.Entry otherClass : other.getHashes().entrySet()) { String otherClassName = otherClass.getKey(); HashCode otherClassBytes = otherClass.getValue(); HashCode thisClsBytes = getHashes().get(otherClassName); if (thisClsBytes == null || !thisClsBytes.equals(otherClassBytes)) { - affected.add(otherClassName); - DependentsSet dependents = other.getClassAnalysis().getRelevantDependents(otherClassName, IntSets.EMPTY_SET); - if (dependents.isDependencyToAll()) { - return dependents; - } - affected.addAll(dependents.getDependentClasses()); + modified.add(otherClassName); } } - for (String added : addedSince(other)) { - if (added.endsWith(ClassSetAnalysisData.PACKAGE_INFO)) { - affected.add(added); - DependentsSet dependents = other.getClassAnalysis().getRelevantDependents(added, IntSets.EMPTY_SET); - if (dependents.isDependencyToAll()) { - return dependents; - } - affected.addAll(dependents.getDependentClasses()); - } - } - return DependentsSet.dependents(affected); + return modified; } private Set addedSince(ClasspathEntrySnapshot other) { diff --git a/subprojects/language-java/src/main/java/org/gradle/api/internal/tasks/compile/incremental/classpath/ClasspathSnapshot.java b/subprojects/language-java/src/main/java/org/gradle/api/internal/tasks/compile/incremental/classpath/ClasspathSnapshot.java index f4451d9fa3e58..74af0d04b29aa 100644 --- a/subprojects/language-java/src/main/java/org/gradle/api/internal/tasks/compile/incremental/classpath/ClasspathSnapshot.java +++ b/subprojects/language-java/src/main/java/org/gradle/api/internal/tasks/compile/incremental/classpath/ClasspathSnapshot.java @@ -16,8 +16,6 @@ package org.gradle.api.internal.tasks.compile.incremental.classpath; -import org.gradle.api.Action; - import java.io.File; import java.util.Collections; import java.util.LinkedHashMap; @@ -54,10 +52,4 @@ public boolean isAnyClassDuplicated(File classpathEntry) { ClasspathEntrySnapshot snapshot = getSnapshot(classpathEntry); return isAnyClassDuplicated(snapshot.getClasses()); } - - public void forEachSnapshot(Action action) { - for (ClasspathEntrySnapshot classpathEntrySnapshot : entrySnapshots.values()) { - action.execute(classpathEntrySnapshot); - } - } } diff --git a/subprojects/language-java/src/main/java/org/gradle/api/internal/tasks/compile/incremental/deps/AffectedClasses.java b/subprojects/language-java/src/main/java/org/gradle/api/internal/tasks/compile/incremental/deps/ClassChanges.java similarity index 78% rename from subprojects/language-java/src/main/java/org/gradle/api/internal/tasks/compile/incremental/deps/AffectedClasses.java rename to subprojects/language-java/src/main/java/org/gradle/api/internal/tasks/compile/incremental/deps/ClassChanges.java index 574e954b37966..6188904a6a85f 100644 --- a/subprojects/language-java/src/main/java/org/gradle/api/internal/tasks/compile/incremental/deps/AffectedClasses.java +++ b/subprojects/language-java/src/main/java/org/gradle/api/internal/tasks/compile/incremental/deps/ClassChanges.java @@ -18,18 +18,18 @@ import java.util.Set; -public class AffectedClasses { +public class ClassChanges { - private final DependentsSet altered; + private final Set modified; private final Set addedClasses; - public AffectedClasses(DependentsSet altered, Set addedClasses) { - this.altered = altered; + public ClassChanges(Set modified, Set addedClasses) { + this.modified = modified; this.addedClasses = addedClasses; } - public DependentsSet getAltered() { - return altered; + public Set getModified() { + return modified; } public Set getAdded() { diff --git a/subprojects/language-java/src/main/java/org/gradle/api/internal/tasks/compile/incremental/recomp/ClasspathChangeDependentsFinder.java b/subprojects/language-java/src/main/java/org/gradle/api/internal/tasks/compile/incremental/recomp/ClasspathChangeDependentsFinder.java index 548a1c53655ea..5e307fc2520c2 100644 --- a/subprojects/language-java/src/main/java/org/gradle/api/internal/tasks/compile/incremental/recomp/ClasspathChangeDependentsFinder.java +++ b/subprojects/language-java/src/main/java/org/gradle/api/internal/tasks/compile/incremental/recomp/ClasspathChangeDependentsFinder.java @@ -18,10 +18,9 @@ import com.google.common.collect.Lists; import com.google.common.collect.Sets; -import org.gradle.api.Action; import org.gradle.api.internal.tasks.compile.incremental.classpath.ClasspathEntrySnapshot; import org.gradle.api.internal.tasks.compile.incremental.classpath.ClasspathSnapshot; -import org.gradle.api.internal.tasks.compile.incremental.deps.AffectedClasses; +import org.gradle.api.internal.tasks.compile.incremental.deps.ClassChanges; import org.gradle.api.internal.tasks.compile.incremental.deps.ClassSetAnalysisData; import org.gradle.api.internal.tasks.compile.incremental.deps.DependentsSet; import org.gradle.api.tasks.incremental.InputFileDetails; @@ -42,71 +41,84 @@ public ClasspathChangeDependentsFinder(ClasspathSnapshot classpathSnapshot, Prev public DependentsSet getActualDependents(InputFileDetails entryChangeDetails, File classpathEntry) { if (entryChangeDetails.isAdded()) { - if (classpathSnapshot.isAnyClassDuplicated(classpathEntry)) { - //at least one of the classes from the new entry is already present in classpath - //to avoid calculation which class gets on the classpath first, rebuild all - return DependentsSet.dependencyToAll("at least one of the classes of '" + classpathEntry + "' is already present in classpath"); - } else { - //none of the new classes in the entry are duplicated on classpath, don't rebuild - return DependentsSet.empty(); - } + return handleAdded(classpathEntry); } - final ClasspathEntrySnapshot previous = previousCompilation.getClasspathEntrySnapshot(entryChangeDetails.getFile()); + + ClasspathEntrySnapshot previous = previousCompilation.getClasspathEntrySnapshot(entryChangeDetails.getFile()); if (previous == null) { - //we don't know what classes were dependents of the entry in the previous build - //for example, a class with a constant might have changed into a class without a constant - we need to rebuild everything return DependentsSet.dependencyToAll("missing classpath entry snapshot of '" + classpathEntry + "' from previous build"); + } else if (entryChangeDetails.isRemoved()) { + return handleRemoved(previous); + } else if (entryChangeDetails.isModified()) { + return handleModified(classpathEntry, previous); + } else { + throw new IllegalArgumentException("Unknown input file details provided: " + entryChangeDetails); } + } - if (entryChangeDetails.isRemoved()) { - DependentsSet allClasses = previous.getAllClasses(); - if (allClasses.isDependencyToAll()) { - return allClasses; - } - //recompile all dependents of all the classes from this entry - return previousCompilation.getDependents(allClasses.getDependentClasses(), previous.getAllConstants(allClasses)); + private DependentsSet handleAdded(File classpathEntry) { + if (classpathSnapshot.isAnyClassDuplicated(classpathEntry)) { + return DependentsSet.dependencyToAll("at least one of the classes of '" + classpathEntry + "' is already present in classpath"); + } else { + return DependentsSet.empty(); } + } - if (entryChangeDetails.isModified()) { - final ClasspathEntrySnapshot currentSnapshot = classpathSnapshot.getSnapshot(classpathEntry); - AffectedClasses affected = currentSnapshot.getAffectedClassesSince(previous); - DependentsSet altered = affected.getAltered(); - if (altered.isDependencyToAll()) { - //at least one of the classes changed in the entry is a 'dependency-to-all' - return altered; - } + private DependentsSet handleRemoved(ClasspathEntrySnapshot previous) { + DependentsSet allClasses = previous.getAllClasses(); + if (allClasses.isDependencyToAll()) { + return allClasses; + } + DependentsSet affectedOnClasspath = collectDependentsFromClasspath(allClasses.getDependentClasses()); + if (affectedOnClasspath.isDependencyToAll()) { + return affectedOnClasspath; + } else { + return previousCompilation.getDependents(affectedOnClasspath.getDependentClasses(), previous.getAllConstants(affectedOnClasspath)); + } + } - if (classpathSnapshot.isAnyClassDuplicated(affected.getAdded())) { - //A new duplicate class on classpath. As we don't fancy-handle classpath order right now, we don't know which class is on classpath first. - //For safe measure rebuild everything - return DependentsSet.dependencyToAll("at least one of the classes of modified classpath entry '" + classpathEntry + "' is already present in the classpath"); - } + private DependentsSet handleModified(File classpathEntry, final ClasspathEntrySnapshot previous) { + final ClasspathEntrySnapshot currentSnapshot = classpathSnapshot.getSnapshot(classpathEntry); + ClassChanges classChanges = currentSnapshot.getChangedClassesSince(previous); + + if (classpathSnapshot.isAnyClassDuplicated(classChanges.getAdded())) { + return DependentsSet.dependencyToAll("at least one of the classes of modified classpath entry '" + classpathEntry + "' is already present in the classpath"); + } + + DependentsSet affectedOnClasspath = collectDependentsFromClasspath(Sets.union(classChanges.getModified(), classChanges.getAdded())); + if (affectedOnClasspath.isDependencyToAll()) { + return affectedOnClasspath; + } else { + return previousCompilation.getDependents(affectedOnClasspath.getDependentClasses(), currentSnapshot.getRelevantConstants(previous, affectedOnClasspath.getDependentClasses())); + } + } - //recompile all dependents of the classes changed in the entry - - final Set dependentClasses = Sets.newHashSet(altered.getDependentClasses()); - final Deque queue = Lists.newLinkedList(dependentClasses); - while (!queue.isEmpty()) { - final String dependentClass = queue.poll(); - classpathSnapshot.forEachSnapshot(new Action() { - @Override - public void execute(ClasspathEntrySnapshot classpathEntrySnapshot) { - if (classpathEntrySnapshot != previous) { - ClassSetAnalysisData data = classpathEntrySnapshot.getData().getClassAnalysis(); - Set intermediates = data.getDependents(dependentClass).getDependentClasses(); - for (String intermediate : intermediates) { - if (dependentClasses.add(intermediate)) { - queue.add(intermediate); - } - } + private DependentsSet collectDependentsFromClasspath(Set modified) { + final Set dependentClasses = Sets.newHashSet(modified); + final Deque queue = Lists.newLinkedList(dependentClasses); + while (!queue.isEmpty()) { + final String dependentClass = queue.poll(); + for (File entry : classpathSnapshot.getEntries()) { + DependentsSet dependents = collectDependentsFromClasspathEntry(dependentClass, entry); + if (dependents.isDependencyToAll()) { + return dependents; + } else { + for (String intermediate : dependents.getDependentClasses()) { + if (dependentClasses.add(intermediate)) { + queue.add(intermediate); } } - }); + } } - return previousCompilation.getDependents(dependentClasses, currentSnapshot.getRelevantConstants(previous, dependentClasses)); } + return DependentsSet.dependents(dependentClasses); + } - throw new IllegalArgumentException("Unknown input file details provided: " + entryChangeDetails); + private DependentsSet collectDependentsFromClasspathEntry(String dependentClass, File entry) { + ClasspathEntrySnapshot entrySnapshot = classpathSnapshot.getSnapshot(entry); + ClassSetAnalysisData data = entrySnapshot.getData().getClassAnalysis(); + return data.getDependents(dependentClass); } + } diff --git a/subprojects/language-java/src/test/groovy/org/gradle/api/internal/tasks/compile/incremental/classpath/ClasspathEntrySnapshotTest.groovy b/subprojects/language-java/src/test/groovy/org/gradle/api/internal/tasks/compile/incremental/classpath/ClasspathEntrySnapshotTest.groovy index fd1010c11a2a5..d6ad5d7ade2d3 100644 --- a/subprojects/language-java/src/test/groovy/org/gradle/api/internal/tasks/compile/incremental/classpath/ClasspathEntrySnapshotTest.groovy +++ b/subprojects/language-java/src/test/groovy/org/gradle/api/internal/tasks/compile/incremental/classpath/ClasspathEntrySnapshotTest.groovy @@ -31,8 +31,8 @@ class ClasspathEntrySnapshotTest extends Specification { new ClasspathEntrySnapshot(new ClasspathEntrySnapshotData(HashCode.fromInt(0x1234), hashes, a)) } - private DependentsSet altered(ClasspathEntrySnapshot s1, ClasspathEntrySnapshot s2) { - s1.getAffectedClassesSince(s2).altered + private Set altered(ClasspathEntrySnapshot s1, ClasspathEntrySnapshot s2) { + s1.getChangedClassesSince(s2).modified } def "knows when there are no affected classes since some other snapshot"() { @@ -40,7 +40,7 @@ class ClasspathEntrySnapshotTest extends Specification { ClasspathEntrySnapshot s2 = snapshot(["A": HashCode.fromInt(0xaa), "B": HashCode.fromInt(0xbb)], analysis) expect: - altered(s1, s2).dependentClasses.isEmpty() + altered(s1, s2).isEmpty() } def "knows when there are extra/missing classes since some other snapshot"() { @@ -48,8 +48,8 @@ class ClasspathEntrySnapshotTest extends Specification { ClasspathEntrySnapshot s2 = snapshot(["A": HashCode.fromInt(0xaa)], analysis) expect: - altered(s1, s2).dependentClasses.isEmpty() //ignore class additions - altered(s2, s1).dependentClasses == ["B", "C"] as Set + altered(s1, s2).isEmpty() //ignore class additions + altered(s2, s1) == ["B", "C"] as Set } def "knows when there are changed classes since other snapshot"() { @@ -57,46 +57,8 @@ class ClasspathEntrySnapshotTest extends Specification { ClasspathEntrySnapshot s2 = snapshot(["A": HashCode.fromInt(0xaa), "B": HashCode.fromInt(0xbbbb)], analysis) expect: - altered(s1, s2).dependentClasses == ["B"] as Set - altered(s2, s1).dependentClasses == ["B", "C"] as Set - } - - def "knows when transitive class is affected transitively via class change"() { - def analysis = Stub(ClassSetAnalysisData) - ClasspathEntrySnapshot s1 = snapshot(["A": HashCode.fromInt(0xaa), "B": HashCode.fromInt(0xbb), "C": HashCode.fromInt(0xcc)], analysis) - ClasspathEntrySnapshot s2 = snapshot(["A": HashCode.fromInt(0xaa), "B": HashCode.fromInt(0xbb), "C": HashCode.fromInt(0xcccc)], analysis) - - analysis.getDependents("C") >> dependents("B") - analysis.getDependents("B") >> dependents() - - expect: - altered(s1, s2).dependentClasses == ["B", "C"] as Set - altered(s2, s1).dependentClasses == ["B", "C"] as Set - } - - def "knows when transitive class is affected transitively via class removal"() { - def analysis = Stub(ClassSetAnalysisData) - ClasspathEntrySnapshot s1 = snapshot(["A": HashCode.fromInt(0xaa), "B": HashCode.fromInt(0xbb), "C": HashCode.fromInt(0xcc)], analysis) - ClasspathEntrySnapshot s2 = snapshot(["A": HashCode.fromInt(0xaa), "B": HashCode.fromInt(0xbb)], analysis) - - analysis.getDependents("C") >> dependents("B") - analysis.getDependents("B") >> dependents() - - expect: - altered(s1, s2).dependentClasses.isEmpty() - altered(s2, s1).dependentClasses == ["B", "C"] as Set - } - - def "knows when class is dependency to all"() { - def analysis = Mock(ClassSetAnalysisData) - ClasspathEntrySnapshot s1 = snapshot(["A": HashCode.fromInt(0xaa), "B": HashCode.fromInt(0xbb)], analysis) - ClasspathEntrySnapshot s2 = snapshot(["A": HashCode.fromInt(0xaa), "B": HashCode.fromInt(0xbbbb)], analysis) - - analysis.getDependents("B") >> DependentsSet.dependencyToAll() - - expect: - altered(s1, s2).isDependencyToAll() - altered(s2, s1).isDependencyToAll() + altered(s1, s2) == ["B"] as Set + altered(s2, s1) == ["B", "C"] as Set } def "knows added classes"() { @@ -105,8 +67,8 @@ class ClasspathEntrySnapshotTest extends Specification { ClasspathEntrySnapshot s3 = snapshot([:], analysis) expect: - s1.getAffectedClassesSince(s2).added == ["B", "C"] as Set - s2.getAffectedClassesSince(s1).added == [] as Set - s1.getAffectedClassesSince(s3).added == ["A", "B", "C"] as Set + s1.getChangedClassesSince(s2).added == ["B", "C"] as Set + s2.getChangedClassesSince(s1).added == [] as Set + s1.getChangedClassesSince(s3).added == ["A", "B", "C"] as Set } } From 42033bc403bacdcd2a92234bdd61dde0dcdedf32 Mon Sep 17 00:00:00 2001 From: "Rodrigo B. de Oliveira" Date: Wed, 13 Mar 2019 12:43:49 -0300 Subject: [PATCH 517/853] Rename `o.g.k.dsl.decorators.*Decorator` to `o.g.k.dsl.delegates.*Delegate` --- .../kotlin/org/gradle/kotlin/dsl/ArtifactHandlerScope.kt | 4 ++-- .../gradle/kotlin/dsl/DependencyConstraintHandlerScope.kt | 4 ++-- .../kotlin/org/gradle/kotlin/dsl/DependencyHandlerScope.kt | 4 ++-- .../main/kotlin/org/gradle/kotlin/dsl/KotlinBuildScript.kt | 4 ++-- .../main/kotlin/org/gradle/kotlin/dsl/KotlinInitScript.kt | 4 ++-- .../kotlin/org/gradle/kotlin/dsl/KotlinSettingsScript.kt | 4 ++-- .../kotlin/dsl/NamedDomainObjectContainerExtensions.kt | 4 ++-- .../main/kotlin/org/gradle/kotlin/dsl/ScriptHandlerScope.kt | 4 ++-- .../kotlin/dsl/precompile/PrecompiledProjectScript.kt | 4 ++-- .../org/gradle/kotlin/dsl/support/KotlinPluginsBlock.kt | 4 ++-- .../ArtifactHandlerDelegate.kt} | 6 +++--- .../DependencyConstraintHandlerDelegate.kt} | 6 +++--- .../DependencyHandlerDelegate.kt} | 6 +++--- .../GradleDecorator.kt => delegates/GradleDelegate.kt} | 4 ++-- .../NamedDomainObjectContainerDelegate.kt} | 6 +++--- .../ProjectDecorator.kt => delegates/ProjectDelegate.kt} | 6 +++--- .../ScriptHandlerDelegate.kt} | 6 +++--- .../SettingsDecorator.kt => delegates/SettingsDelegate.kt} | 6 +++--- 18 files changed, 43 insertions(+), 43 deletions(-) rename subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/{decorators/ArtifactHandlerDecorator.kt => delegates/ArtifactHandlerDelegate.kt} (89%) rename subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/{decorators/DependencyConstraintHandlerDecorator.kt => delegates/DependencyConstraintHandlerDelegate.kt} (91%) rename subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/{decorators/DependencyHandlerDecorator.kt => delegates/DependencyHandlerDelegate.kt} (96%) rename subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/{decorators/GradleDecorator.kt => delegates/GradleDelegate.kt} (98%) rename subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/{decorators/NamedDomainObjectContainerDecorator.kt => delegates/NamedDomainObjectContainerDelegate.kt} (96%) rename subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/{decorators/ProjectDecorator.kt => delegates/ProjectDelegate.kt} (98%) rename subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/{decorators/ScriptHandlerDecorator.kt => delegates/ScriptHandlerDelegate.kt} (91%) rename subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/{decorators/SettingsDecorator.kt => delegates/SettingsDelegate.kt} (96%) diff --git a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/ArtifactHandlerScope.kt b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/ArtifactHandlerScope.kt index e50957df72c44..3bc5df2966266 100644 --- a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/ArtifactHandlerScope.kt +++ b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/ArtifactHandlerScope.kt @@ -21,7 +21,7 @@ import org.gradle.api.artifacts.Configuration import org.gradle.api.artifacts.PublishArtifact import org.gradle.api.artifacts.dsl.ArtifactHandler -import org.gradle.kotlin.dsl.support.decorators.ArtifactHandlerDecorator +import org.gradle.kotlin.dsl.support.delegates.ArtifactHandlerDelegate /** @@ -32,7 +32,7 @@ import org.gradle.kotlin.dsl.support.decorators.ArtifactHandlerDecorator class ArtifactHandlerScope private constructor( val artifacts: ArtifactHandler -) : ArtifactHandlerDecorator() { +) : ArtifactHandlerDelegate() { companion object { /** diff --git a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/DependencyConstraintHandlerScope.kt b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/DependencyConstraintHandlerScope.kt index 08f9be527a5e6..f934a4f9afd06 100644 --- a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/DependencyConstraintHandlerScope.kt +++ b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/DependencyConstraintHandlerScope.kt @@ -21,7 +21,7 @@ import org.gradle.api.artifacts.Configuration import org.gradle.api.artifacts.DependencyConstraint import org.gradle.api.artifacts.dsl.DependencyConstraintHandler -import org.gradle.kotlin.dsl.support.decorators.DependencyConstraintHandlerDecorator +import org.gradle.kotlin.dsl.support.delegates.DependencyConstraintHandlerDelegate /** @@ -34,7 +34,7 @@ import org.gradle.kotlin.dsl.support.decorators.DependencyConstraintHandlerDecor class DependencyConstraintHandlerScope private constructor( val constraints: DependencyConstraintHandler -) : DependencyConstraintHandlerDecorator() { +) : DependencyConstraintHandlerDelegate() { companion object { fun of(constraints: DependencyConstraintHandler) = diff --git a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/DependencyHandlerScope.kt b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/DependencyHandlerScope.kt index d604e715eaabd..e115b67d8dc35 100644 --- a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/DependencyHandlerScope.kt +++ b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/DependencyHandlerScope.kt @@ -23,7 +23,7 @@ import org.gradle.api.artifacts.ModuleDependency import org.gradle.api.artifacts.dsl.DependencyHandler import org.gradle.api.plugins.ExtensionAware -import org.gradle.kotlin.dsl.support.decorators.DependencyHandlerDecorator +import org.gradle.kotlin.dsl.support.delegates.DependencyHandlerDelegate /** @@ -34,7 +34,7 @@ import org.gradle.kotlin.dsl.support.decorators.DependencyHandlerDecorator open class DependencyHandlerScope private constructor( val dependencies: DependencyHandler -) : DependencyHandlerDecorator() { +) : DependencyHandlerDelegate() { companion object { fun of(dependencies: DependencyHandler): DependencyHandlerScope = diff --git a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/KotlinBuildScript.kt b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/KotlinBuildScript.kt index a24c771025d5a..a99b8f6151f0d 100644 --- a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/KotlinBuildScript.kt +++ b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/KotlinBuildScript.kt @@ -21,7 +21,7 @@ import org.gradle.api.initialization.dsl.ScriptHandler import org.gradle.kotlin.dsl.resolver.KotlinBuildScriptDependenciesResolver import org.gradle.kotlin.dsl.support.KotlinScriptHost -import org.gradle.kotlin.dsl.support.decorators.ProjectDecorator +import org.gradle.kotlin.dsl.support.delegates.ProjectDelegate import org.gradle.kotlin.dsl.support.internalError import org.gradle.plugin.use.PluginDependenciesSpec @@ -56,7 +56,7 @@ annotation class KotlinScriptTemplate @GradleDsl abstract class KotlinBuildScript( private val host: KotlinScriptHost -) : ProjectDecorator() { +) : ProjectDelegate() { override val delegate: Project get() = host.target diff --git a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/KotlinInitScript.kt b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/KotlinInitScript.kt index 7b343b4008b0e..bbbed2d64d4ce 100644 --- a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/KotlinInitScript.kt +++ b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/KotlinInitScript.kt @@ -37,7 +37,7 @@ import org.gradle.api.tasks.WorkResult import org.gradle.kotlin.dsl.resolver.KotlinBuildScriptDependenciesResolver import org.gradle.kotlin.dsl.support.KotlinScriptHost -import org.gradle.kotlin.dsl.support.decorators.GradleDecorator +import org.gradle.kotlin.dsl.support.delegates.GradleDelegate import org.gradle.kotlin.dsl.support.internalError import org.gradle.kotlin.dsl.support.serviceOf import org.gradle.kotlin.dsl.support.unsafeLazy @@ -103,7 +103,7 @@ abstract class KotlinInitScript( */ abstract class InitScriptApi( override val delegate: Gradle -) : GradleDecorator() { +) : GradleDelegate() { protected abstract val fileOperations: FileOperations diff --git a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/KotlinSettingsScript.kt b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/KotlinSettingsScript.kt index 791a6a946bf6c..ac149d911a6ed 100644 --- a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/KotlinSettingsScript.kt +++ b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/KotlinSettingsScript.kt @@ -49,7 +49,7 @@ import org.gradle.internal.time.Clock import org.gradle.kotlin.dsl.resolver.KotlinBuildScriptDependenciesResolver import org.gradle.kotlin.dsl.support.KotlinScriptHost -import org.gradle.kotlin.dsl.support.decorators.SettingsDecorator +import org.gradle.kotlin.dsl.support.delegates.SettingsDelegate import org.gradle.kotlin.dsl.support.get import org.gradle.kotlin.dsl.support.internalError import org.gradle.kotlin.dsl.support.serviceOf @@ -108,7 +108,7 @@ abstract class KotlinSettingsScript( */ abstract class SettingsScriptApi( override val delegate: Settings -) : SettingsDecorator() { +) : SettingsDelegate() { protected abstract val fileOperations: FileOperations diff --git a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/NamedDomainObjectContainerExtensions.kt b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/NamedDomainObjectContainerExtensions.kt index 3e715bb2ecbba..61fb88c92e368 100644 --- a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/NamedDomainObjectContainerExtensions.kt +++ b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/NamedDomainObjectContainerExtensions.kt @@ -21,7 +21,7 @@ import org.gradle.api.NamedDomainObjectContainer import org.gradle.api.NamedDomainObjectProvider import org.gradle.api.PolymorphicDomainObjectContainer -import org.gradle.kotlin.dsl.support.decorators.NamedDomainObjectContainerDecorator +import org.gradle.kotlin.dsl.support.delegates.NamedDomainObjectContainerDelegate import kotlin.reflect.KClass import kotlin.reflect.KProperty @@ -222,7 +222,7 @@ private constructor( class NamedDomainObjectContainerScope private constructor( override val delegate: NamedDomainObjectContainer -) : NamedDomainObjectContainerDecorator(), PolymorphicDomainObjectContainer { +) : NamedDomainObjectContainerDelegate(), PolymorphicDomainObjectContainer { companion object { fun of(container: NamedDomainObjectContainer) = diff --git a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/ScriptHandlerScope.kt b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/ScriptHandlerScope.kt index c9502321f0e0c..499b86927b4bd 100644 --- a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/ScriptHandlerScope.kt +++ b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/ScriptHandlerScope.kt @@ -31,7 +31,7 @@ import org.gradle.api.artifacts.dsl.DependencyHandler import org.gradle.api.initialization.dsl.ScriptHandler import org.gradle.api.initialization.dsl.ScriptHandler.CLASSPATH_CONFIGURATION -import org.gradle.kotlin.dsl.support.decorators.ScriptHandlerDecorator +import org.gradle.kotlin.dsl.support.delegates.ScriptHandlerDelegate import org.gradle.kotlin.dsl.support.unsafeLazy @@ -41,7 +41,7 @@ import org.gradle.kotlin.dsl.support.unsafeLazy class ScriptHandlerScope private constructor( override val delegate: ScriptHandler -) : ScriptHandlerDecorator() { +) : ScriptHandlerDelegate() { companion object { fun of(scriptHandler: ScriptHandler) = diff --git a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/precompile/PrecompiledProjectScript.kt b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/precompile/PrecompiledProjectScript.kt index 6f1c28ca62f78..1df0e0d81922d 100644 --- a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/precompile/PrecompiledProjectScript.kt +++ b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/precompile/PrecompiledProjectScript.kt @@ -21,7 +21,7 @@ import org.gradle.api.Project import org.gradle.kotlin.dsl.GradleDsl import org.gradle.kotlin.dsl.KotlinScriptTemplate import org.gradle.kotlin.dsl.ScriptHandlerScope -import org.gradle.kotlin.dsl.support.decorators.ProjectDecorator +import org.gradle.kotlin.dsl.support.delegates.ProjectDelegate import org.gradle.plugin.use.PluginDependenciesSpec import org.gradle.plugin.use.PluginDependencySpec @@ -58,7 +58,7 @@ import kotlin.script.templates.ScriptTemplateDefinition @GradleDsl abstract class PrecompiledProjectScript( override val delegate: Project -) : ProjectDecorator() { +) : ProjectDelegate() { /** * Configures the build script classpath for this project. diff --git a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/KotlinPluginsBlock.kt b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/KotlinPluginsBlock.kt index 297bc49620fb1..24e97bfe05b55 100644 --- a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/KotlinPluginsBlock.kt +++ b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/KotlinPluginsBlock.kt @@ -20,7 +20,7 @@ import org.gradle.api.Project import org.gradle.api.initialization.dsl.ScriptHandler import org.gradle.kotlin.dsl.ScriptHandlerScope -import org.gradle.kotlin.dsl.support.decorators.ProjectDecorator +import org.gradle.kotlin.dsl.support.delegates.ProjectDelegate import org.gradle.plugin.use.PluginDependenciesSpec @@ -42,7 +42,7 @@ abstract class KotlinPluginsBlock(val pluginDependencies: PluginDependenciesSpec abstract class KotlinBuildscriptAndPluginsBlock( private val host: KotlinScriptHost, val pluginDependencies: PluginDependenciesSpec -) : ProjectDecorator() { +) : ProjectDelegate() { override val delegate: Project get() = host.target diff --git a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/decorators/ArtifactHandlerDecorator.kt b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/delegates/ArtifactHandlerDelegate.kt similarity index 89% rename from subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/decorators/ArtifactHandlerDecorator.kt rename to subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/delegates/ArtifactHandlerDelegate.kt index af2bd1c6aaccf..58deb1c99c244 100644 --- a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/decorators/ArtifactHandlerDecorator.kt +++ b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/delegates/ArtifactHandlerDelegate.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.gradle.kotlin.dsl.support.decorators +package org.gradle.kotlin.dsl.support.delegates import groovy.lang.Closure @@ -27,9 +27,9 @@ import org.gradle.api.artifacts.dsl.ArtifactHandler /** * Facilitates the implementation of the [ArtifactHandler] interface by delegation via subclassing. * - * See [GradleDecorator] for details why this is currently necessary. + * See [GradleDelegate] for details why this is currently necessary. */ -abstract class ArtifactHandlerDecorator : ArtifactHandler { +abstract class ArtifactHandlerDelegate : ArtifactHandler { internal abstract val delegate: ArtifactHandler diff --git a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/decorators/DependencyConstraintHandlerDecorator.kt b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/delegates/DependencyConstraintHandlerDelegate.kt similarity index 91% rename from subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/decorators/DependencyConstraintHandlerDecorator.kt rename to subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/delegates/DependencyConstraintHandlerDelegate.kt index c0d42dc2b71df..6f12e9d92d021 100644 --- a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/decorators/DependencyConstraintHandlerDecorator.kt +++ b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/delegates/DependencyConstraintHandlerDelegate.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.gradle.kotlin.dsl.support.decorators +package org.gradle.kotlin.dsl.support.delegates import org.gradle.api.Action import org.gradle.api.artifacts.DependencyConstraint @@ -24,9 +24,9 @@ import org.gradle.api.artifacts.dsl.DependencyConstraintHandler /** * Facilitates the implementation of the [DependencyConstraintHandler] interface by delegation via subclassing. * - * See [GradleDecorator] for details why this is currently necessary. + * See [GradleDelegate] for details why this is currently necessary. */ -abstract class DependencyConstraintHandlerDecorator : DependencyConstraintHandler { +abstract class DependencyConstraintHandlerDelegate : DependencyConstraintHandler { internal abstract val delegate: DependencyConstraintHandler diff --git a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/decorators/DependencyHandlerDecorator.kt b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/delegates/DependencyHandlerDelegate.kt similarity index 96% rename from subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/decorators/DependencyHandlerDecorator.kt rename to subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/delegates/DependencyHandlerDelegate.kt index f24b2427ce908..8ff90ad1fa5b1 100644 --- a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/decorators/DependencyHandlerDecorator.kt +++ b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/delegates/DependencyHandlerDelegate.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.gradle.kotlin.dsl.support.decorators +package org.gradle.kotlin.dsl.support.delegates import groovy.lang.Closure @@ -36,9 +36,9 @@ import org.gradle.api.attributes.AttributesSchema /** * Facilitates the implementation of the [DependencyHandler] interface by delegation via subclassing. * - * See [GradleDecorator] for details why this is currently necessary. + * See [GradleDelegate] for details why this is currently necessary. */ -abstract class DependencyHandlerDecorator : DependencyHandler { +abstract class DependencyHandlerDelegate : DependencyHandler { internal abstract val delegate: DependencyHandler diff --git a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/decorators/GradleDecorator.kt b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/delegates/GradleDelegate.kt similarity index 98% rename from subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/decorators/GradleDecorator.kt rename to subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/delegates/GradleDelegate.kt index 0b9d5f1723f74..d757351cdcbf7 100644 --- a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/decorators/GradleDecorator.kt +++ b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/delegates/GradleDelegate.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.gradle.kotlin.dsl.support.decorators +package org.gradle.kotlin.dsl.support.delegates import groovy.lang.Closure @@ -45,7 +45,7 @@ import java.io.File * Once the required interfaces are compiled with Java 8 parameter names these classes can be removed in favor * of Kotlin's implementation by delegation. */ -abstract class GradleDecorator : Gradle { +abstract class GradleDelegate : Gradle { internal abstract val delegate: Gradle diff --git a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/decorators/NamedDomainObjectContainerDecorator.kt b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/delegates/NamedDomainObjectContainerDelegate.kt similarity index 96% rename from subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/decorators/NamedDomainObjectContainerDecorator.kt rename to subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/delegates/NamedDomainObjectContainerDelegate.kt index dae4520637d67..9e0c5a944ecab 100644 --- a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/decorators/NamedDomainObjectContainerDecorator.kt +++ b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/delegates/NamedDomainObjectContainerDelegate.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.gradle.kotlin.dsl.support.decorators +package org.gradle.kotlin.dsl.support.delegates import groovy.lang.Closure @@ -36,9 +36,9 @@ import java.util.SortedSet /** * Facilitates the implementation of the [NamedDomainObjectContainer] interface by delegation via subclassing. * - * See [GradleDecorator] for details why this is currently necessary. + * See [GradleDelegate] for details why this is currently necessary. */ -abstract class NamedDomainObjectContainerDecorator : NamedDomainObjectContainer { +abstract class NamedDomainObjectContainerDelegate : NamedDomainObjectContainer { abstract val delegate: NamedDomainObjectContainer diff --git a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/decorators/ProjectDecorator.kt b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/delegates/ProjectDelegate.kt similarity index 98% rename from subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/decorators/ProjectDecorator.kt rename to subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/delegates/ProjectDelegate.kt index 8acc980afc38e..7735f2e6b9311 100644 --- a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/decorators/ProjectDecorator.kt +++ b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/delegates/ProjectDelegate.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.gradle.kotlin.dsl.support.decorators +package org.gradle.kotlin.dsl.support.delegates import groovy.lang.Closure @@ -68,9 +68,9 @@ import java.util.concurrent.Callable /** * Facilitates the implementation of the [Project] interface by delegation via subclassing. * - * See [GradleDecorator] for details why this is currently necessary. + * See [GradleDelegate] for details why this is currently necessary. */ -abstract class ProjectDecorator() : Project { +abstract class ProjectDelegate() : Project { internal abstract val delegate: Project diff --git a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/decorators/ScriptHandlerDecorator.kt b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/delegates/ScriptHandlerDelegate.kt similarity index 91% rename from subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/decorators/ScriptHandlerDecorator.kt rename to subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/delegates/ScriptHandlerDelegate.kt index a933638fede6b..db889e42eac13 100644 --- a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/decorators/ScriptHandlerDecorator.kt +++ b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/delegates/ScriptHandlerDelegate.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.gradle.kotlin.dsl.support.decorators +package org.gradle.kotlin.dsl.support.delegates import groovy.lang.Closure @@ -31,9 +31,9 @@ import java.net.URI /** * Facilitates the implementation of the [ScriptHandler] interface by delegation via subclassing. * - * See [GradleDecorator] for details why this is currently necessary. + * See [GradleDelegate] for details why this is currently necessary. */ -abstract class ScriptHandlerDecorator : ScriptHandler { +abstract class ScriptHandlerDelegate : ScriptHandler { internal abstract val delegate: ScriptHandler diff --git a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/decorators/SettingsDecorator.kt b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/delegates/SettingsDelegate.kt similarity index 96% rename from subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/decorators/SettingsDecorator.kt rename to subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/delegates/SettingsDelegate.kt index 8dd05fa885652..cdec543c495b9 100644 --- a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/decorators/SettingsDecorator.kt +++ b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/delegates/SettingsDelegate.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.gradle.kotlin.dsl.support.decorators +package org.gradle.kotlin.dsl.support.delegates import groovy.lang.Closure @@ -39,9 +39,9 @@ import java.io.File /** * Facilitates the implementation of the [Settings] interface by delegation via subclassing. * - * See [GradleDecorator] for details why this is currently necessary. + * See [GradleDelegate] for details why this is currently necessary. */ -abstract class SettingsDecorator : Settings { +abstract class SettingsDelegate : Settings { internal abstract val delegate: Settings From 50f0c86b32d702a79d03b5b2a07c2086ec585173 Mon Sep 17 00:00:00 2001 From: "Rodrigo B. de Oliveira" Date: Tue, 12 Mar 2019 19:45:05 -0300 Subject: [PATCH 518/853] Let Kotlin DSL resolver return given Java home Resolves gradle/kotlin-dsl#1354 --- .../KotlinScriptDependenciesResolverTest.kt | 12 +++++++++++ .../KotlinBuildScriptDependenciesResolver.kt | 20 ++++++++++--------- 2 files changed, 23 insertions(+), 9 deletions(-) diff --git a/subprojects/kotlin-dsl/src/integTest/kotlin/org/gradle/kotlin/dsl/resolver/KotlinScriptDependenciesResolverTest.kt b/subprojects/kotlin-dsl/src/integTest/kotlin/org/gradle/kotlin/dsl/resolver/KotlinScriptDependenciesResolverTest.kt index c536229009514..2f42626db3c2c 100644 --- a/subprojects/kotlin-dsl/src/integTest/kotlin/org/gradle/kotlin/dsl/resolver/KotlinScriptDependenciesResolverTest.kt +++ b/subprojects/kotlin-dsl/src/integTest/kotlin/org/gradle/kotlin/dsl/resolver/KotlinScriptDependenciesResolverTest.kt @@ -53,6 +53,18 @@ class KotlinScriptDependenciesResolverTest : AbstractKotlinIntegrationTest() { assertSucceeds() } + @Test + fun `returns given Java home`() { + + val javaHome = System.getProperty("java.home") + val env = arrayOf("gradleJavaHome" to javaHome) + assertThat( + resolvedScriptDependencies(env = *env)?.javaHome, + equalTo(javaHome) + ) + } + + @Test fun `succeeds on init script`() { diff --git a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/resolver/KotlinBuildScriptDependenciesResolver.kt b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/resolver/KotlinBuildScriptDependenciesResolver.kt index 7fce79031c470..971cc3f924cf5 100644 --- a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/resolver/KotlinBuildScriptDependenciesResolver.kt +++ b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/resolver/KotlinBuildScriptDependenciesResolver.kt @@ -139,12 +139,12 @@ class KotlinBuildScriptDependenciesResolver @VisibleForTesting constructor( previousDependencies: KotlinScriptExternalDependencies? ): KotlinScriptExternalDependencies? { - val scriptModelRequest = scriptModelRequestFrom(scriptFile, environment, cid) - log(SubmittedModelRequest(cid, scriptFile, scriptModelRequest)) + val request = scriptModelRequestFrom(scriptFile, environment, cid) + log(SubmittedModelRequest(cid, scriptFile, request)) - val response = DefaultKotlinBuildScriptModelRepository.scriptModelFor(scriptModelRequest) + val response = DefaultKotlinBuildScriptModelRepository.scriptModelFor(request) if (response == null) { - log(RequestCancelled(cid, scriptFile, scriptModelRequest)) + log(RequestCancelled(cid, scriptFile, request)) return null } log(ReceivedModelResponse(cid, scriptFile, response)) @@ -155,7 +155,7 @@ class KotlinBuildScriptDependenciesResolver @VisibleForTesting constructor( return when { response.exceptions.isEmpty() -> - dependenciesFrom(response).also { + dependenciesFrom(request, response).also { log(ResolvedDependencies(cid, scriptFile, it)) } previousDependencies != null && previousDependencies.classpath.count() > response.classPath.size -> @@ -163,7 +163,7 @@ class KotlinBuildScriptDependenciesResolver @VisibleForTesting constructor( log(ResolvedToPreviousWithErrors(cid, scriptFile, previousDependencies, response.exceptions)) } else -> - dependenciesFrom(response).also { + dependenciesFrom(request, response).also { log(ResolvedDependenciesWithErrors(cid, scriptFile, it, response.exceptions)) } } @@ -207,11 +207,12 @@ class KotlinBuildScriptDependenciesResolver @VisibleForTesting constructor( ?: GradleInstallation.Wrapper private - fun dependenciesFrom(response: KotlinBuildScriptModel) = + fun dependenciesFrom(request: KotlinBuildScriptModelRequest, response: KotlinBuildScriptModel) = KotlinBuildScriptDependencies( response.classPath, response.sourcePath, - response.implicitImports + response.implicitImports, + request.javaHome?.path ) } @@ -220,7 +221,8 @@ internal class KotlinBuildScriptDependencies( override val classpath: Iterable, override val sources: Iterable, - override val imports: Iterable + override val imports: Iterable, + override val javaHome: String? = null ) : KotlinScriptExternalDependencies From a1149a5a044732ab6c66b6cd403c2ff99d17e8d6 Mon Sep 17 00:00:00 2001 From: Stefan Wolf Date: Wed, 13 Mar 2019 17:23:05 +0100 Subject: [PATCH 519/853] Address review comments --- .../org/gradle/api/execution/incremental/InputChanges.java | 7 +++---- .../api/tasks/incremental/IncrementalTaskInputs.java | 4 ++-- ...oovy => AbstractIncrementalTasksIntegrationTest.groovy} | 2 +- .../api/tasks/IncrementalInputsIntegrationTest.groovy | 2 +- .../api/tasks/IncrementalTaskInputsIntegrationTest.groovy | 2 +- 5 files changed, 8 insertions(+), 9 deletions(-) rename subprojects/core/src/integTest/groovy/org/gradle/api/tasks/{IncrementalTasksIntegrationTest.groovy => AbstractIncrementalTasksIntegrationTest.groovy} (99%) diff --git a/subprojects/core-api/src/main/java/org/gradle/api/execution/incremental/InputChanges.java b/subprojects/core-api/src/main/java/org/gradle/api/execution/incremental/InputChanges.java index 6889f3a5e44e8..21b50444c3d60 100644 --- a/subprojects/core-api/src/main/java/org/gradle/api/execution/incremental/InputChanges.java +++ b/subprojects/core-api/src/main/java/org/gradle/api/execution/incremental/InputChanges.java @@ -17,7 +17,6 @@ package org.gradle.api.execution.incremental; import org.gradle.api.Incubating; -import org.gradle.api.NonExtensible; import org.gradle.api.tasks.incremental.InputFileDetails; /** @@ -37,8 +36,9 @@ * * {@literal @}TaskAction * void execute(InputChanges inputChanges) { - * if (!inputChanges.incremental) + * if (!inputChanges.incremental) { * project.delete(outputDir.listFiles()) + * } * * inputChanges.getFileChanges(inputDir).each { change -> * if (change.removed) { @@ -60,13 +60,12 @@ * Cases where this occurs include: *
      *
    • There is no history available from a previous execution.
    • - *
    • An non-file input property has changed since the previous execution.
    • + *
    • A non-file input property has changed since the previous execution.
    • *
    • One or more output files have changed since the previous execution.
    • *
    * * @since 5.4 */ -@NonExtensible @Incubating public interface InputChanges { /** diff --git a/subprojects/core-api/src/main/java/org/gradle/api/tasks/incremental/IncrementalTaskInputs.java b/subprojects/core-api/src/main/java/org/gradle/api/tasks/incremental/IncrementalTaskInputs.java index 0a41e5aae0942..8987cb8d86877 100644 --- a/subprojects/core-api/src/main/java/org/gradle/api/tasks/incremental/IncrementalTaskInputs.java +++ b/subprojects/core-api/src/main/java/org/gradle/api/tasks/incremental/IncrementalTaskInputs.java @@ -36,9 +36,9 @@ * * {@literal @}TaskAction * void execute(IncrementalTaskInputs inputs) { - * if (!inputs.incremental) + * if (!inputs.incremental) { * project.delete(outputDir.listFiles()) - * + * } * inputs.outOfDate { change -> * def targetFile = project.file("$outputDir/${change.file.name}") * targetFile.text = change.file.text.reverse() diff --git a/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/IncrementalTasksIntegrationTest.groovy b/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/AbstractIncrementalTasksIntegrationTest.groovy similarity index 99% rename from subprojects/core/src/integTest/groovy/org/gradle/api/tasks/IncrementalTasksIntegrationTest.groovy rename to subprojects/core/src/integTest/groovy/org/gradle/api/tasks/AbstractIncrementalTasksIntegrationTest.groovy index d6d24081a69bd..d2be6ba7908d2 100644 --- a/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/IncrementalTasksIntegrationTest.groovy +++ b/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/AbstractIncrementalTasksIntegrationTest.groovy @@ -21,7 +21,7 @@ import org.gradle.internal.change.ChangeType import spock.lang.Issue import spock.lang.Unroll -abstract class IncrementalTasksIntegrationTest extends AbstractIntegrationSpec { +abstract class AbstractIncrementalTasksIntegrationTest extends AbstractIntegrationSpec { abstract String getTaskAction() diff --git a/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/IncrementalInputsIntegrationTest.groovy b/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/IncrementalInputsIntegrationTest.groovy index 43aaab974f5e4..16e10cf278263 100644 --- a/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/IncrementalInputsIntegrationTest.groovy +++ b/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/IncrementalInputsIntegrationTest.groovy @@ -18,7 +18,7 @@ package org.gradle.api.tasks import org.gradle.internal.change.ChangeType -class IncrementalInputsIntegrationTest extends IncrementalTasksIntegrationTest { +class IncrementalInputsIntegrationTest extends AbstractIncrementalTasksIntegrationTest { String getTaskAction() { """ diff --git a/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/IncrementalTaskInputsIntegrationTest.groovy b/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/IncrementalTaskInputsIntegrationTest.groovy index 6d27937103d65..79e3c79ed08d9 100644 --- a/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/IncrementalTaskInputsIntegrationTest.groovy +++ b/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/IncrementalTaskInputsIntegrationTest.groovy @@ -18,7 +18,7 @@ package org.gradle.api.tasks import org.gradle.internal.change.ChangeType -class IncrementalTaskInputsIntegrationTest extends IncrementalTasksIntegrationTest { +class IncrementalTaskInputsIntegrationTest extends AbstractIncrementalTasksIntegrationTest { String getTaskAction() { """ From 12c6bc62e118fb6c2449b7c79d0694e97633c5db Mon Sep 17 00:00:00 2001 From: Paul Merlin Date: Wed, 13 Mar 2019 17:43:02 +0100 Subject: [PATCH 520/853] Revert "Let Kotlin DSL resolver return given Java home" This reverts commit 50f0c86b32d702a79d03b5b2a07c2086ec585173. --- .../KotlinScriptDependenciesResolverTest.kt | 12 ----------- .../KotlinBuildScriptDependenciesResolver.kt | 20 +++++++++---------- 2 files changed, 9 insertions(+), 23 deletions(-) diff --git a/subprojects/kotlin-dsl/src/integTest/kotlin/org/gradle/kotlin/dsl/resolver/KotlinScriptDependenciesResolverTest.kt b/subprojects/kotlin-dsl/src/integTest/kotlin/org/gradle/kotlin/dsl/resolver/KotlinScriptDependenciesResolverTest.kt index 2f42626db3c2c..c536229009514 100644 --- a/subprojects/kotlin-dsl/src/integTest/kotlin/org/gradle/kotlin/dsl/resolver/KotlinScriptDependenciesResolverTest.kt +++ b/subprojects/kotlin-dsl/src/integTest/kotlin/org/gradle/kotlin/dsl/resolver/KotlinScriptDependenciesResolverTest.kt @@ -53,18 +53,6 @@ class KotlinScriptDependenciesResolverTest : AbstractKotlinIntegrationTest() { assertSucceeds() } - @Test - fun `returns given Java home`() { - - val javaHome = System.getProperty("java.home") - val env = arrayOf("gradleJavaHome" to javaHome) - assertThat( - resolvedScriptDependencies(env = *env)?.javaHome, - equalTo(javaHome) - ) - } - - @Test fun `succeeds on init script`() { diff --git a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/resolver/KotlinBuildScriptDependenciesResolver.kt b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/resolver/KotlinBuildScriptDependenciesResolver.kt index 971cc3f924cf5..7fce79031c470 100644 --- a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/resolver/KotlinBuildScriptDependenciesResolver.kt +++ b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/resolver/KotlinBuildScriptDependenciesResolver.kt @@ -139,12 +139,12 @@ class KotlinBuildScriptDependenciesResolver @VisibleForTesting constructor( previousDependencies: KotlinScriptExternalDependencies? ): KotlinScriptExternalDependencies? { - val request = scriptModelRequestFrom(scriptFile, environment, cid) - log(SubmittedModelRequest(cid, scriptFile, request)) + val scriptModelRequest = scriptModelRequestFrom(scriptFile, environment, cid) + log(SubmittedModelRequest(cid, scriptFile, scriptModelRequest)) - val response = DefaultKotlinBuildScriptModelRepository.scriptModelFor(request) + val response = DefaultKotlinBuildScriptModelRepository.scriptModelFor(scriptModelRequest) if (response == null) { - log(RequestCancelled(cid, scriptFile, request)) + log(RequestCancelled(cid, scriptFile, scriptModelRequest)) return null } log(ReceivedModelResponse(cid, scriptFile, response)) @@ -155,7 +155,7 @@ class KotlinBuildScriptDependenciesResolver @VisibleForTesting constructor( return when { response.exceptions.isEmpty() -> - dependenciesFrom(request, response).also { + dependenciesFrom(response).also { log(ResolvedDependencies(cid, scriptFile, it)) } previousDependencies != null && previousDependencies.classpath.count() > response.classPath.size -> @@ -163,7 +163,7 @@ class KotlinBuildScriptDependenciesResolver @VisibleForTesting constructor( log(ResolvedToPreviousWithErrors(cid, scriptFile, previousDependencies, response.exceptions)) } else -> - dependenciesFrom(request, response).also { + dependenciesFrom(response).also { log(ResolvedDependenciesWithErrors(cid, scriptFile, it, response.exceptions)) } } @@ -207,12 +207,11 @@ class KotlinBuildScriptDependenciesResolver @VisibleForTesting constructor( ?: GradleInstallation.Wrapper private - fun dependenciesFrom(request: KotlinBuildScriptModelRequest, response: KotlinBuildScriptModel) = + fun dependenciesFrom(response: KotlinBuildScriptModel) = KotlinBuildScriptDependencies( response.classPath, response.sourcePath, - response.implicitImports, - request.javaHome?.path + response.implicitImports ) } @@ -221,8 +220,7 @@ internal class KotlinBuildScriptDependencies( override val classpath: Iterable, override val sources: Iterable, - override val imports: Iterable, - override val javaHome: String? = null + override val imports: Iterable ) : KotlinScriptExternalDependencies From 4b3a8d84d9a8983836f9bb3006c39baec692ca4b Mon Sep 17 00:00:00 2001 From: Louis Jacomet Date: Wed, 13 Mar 2019 16:51:50 +0100 Subject: [PATCH 521/853] Document potential breaking change for Ivy publication --- .../docs/src/docs/userguide/upgrading_version_5.adoc | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/subprojects/docs/src/docs/userguide/upgrading_version_5.adoc b/subprojects/docs/src/docs/userguide/upgrading_version_5.adoc index 9844ab6f659ca..e0a0038788b4d 100644 --- a/subprojects/docs/src/docs/userguide/upgrading_version_5.adoc +++ b/subprojects/docs/src/docs/userguide/upgrading_version_5.adoc @@ -84,6 +84,15 @@ The legacy behaviour of Gradle, prior to 5.0, was still in place instead of bein Gradle no longer ignores the `followSymlink` option on Windows for the `clean` task, all `Delete` tasks, and `project.delete {}` operations in the presence of junction points and symbolic links. +==== Fix in publication of additional artifacts + +In previous Gradle versions, additional artifacts registered at the project level were not published by `maven-publish` or `ivy-publish` unless they were also added as artifacts in the publication configuration. + +With Gradle 5.3, these artifacts are now properly accounted for and published. + +This means that artifacts that are registered both on the project _and_ the publication, Ivy or Maven, will cause publication to fail since it will create duplicate entries. +The fix is to remove these artifacts from the publication configuration. + [[changes_5.2]] == Upgrading from 5.1 and earlier From ed7b52ddf5fbf31ce40dc613b988cf90ec9d7f08 Mon Sep 17 00:00:00 2001 From: Sterling Greene Date: Wed, 13 Mar 2019 21:41:51 +0100 Subject: [PATCH 522/853] Publish 5.3-rc-3 --- released-versions.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/released-versions.json b/released-versions.json index 4033adb61426c..403fbcc5a5bd8 100644 --- a/released-versions.json +++ b/released-versions.json @@ -4,8 +4,8 @@ "buildTime": "20190313010512+0000" }, "latestRc": { - "version": "5.3-rc-2", - "buildTime": "20190311210726+0000" + "version": "5.3-rc-3", + "buildTime": "20190313202708+0000" }, "finalReleases": [ { From f5c64796748a98efdbf6f99f44b6afe08492c2a0 Mon Sep 17 00:00:00 2001 From: Sterling Greene Date: Wed, 13 Mar 2019 17:01:36 -0400 Subject: [PATCH 523/853] Bump to latest RC --- gradle/wrapper/gradle-wrapper.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index a257a1753dd88..11c592cb636fa 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-5.3-rc-2-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-5.3-rc-3-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists From f57205c4a61a7fd71efb3de6841c4a1b1bb85750 Mon Sep 17 00:00:00 2001 From: Adam Murdoch Date: Wed, 13 Mar 2019 12:14:40 +1100 Subject: [PATCH 524/853] Add some more trace to flaky test. --- .../BuildSourceBuilderIntegrationTest.groovy | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/BuildSourceBuilderIntegrationTest.groovy b/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/BuildSourceBuilderIntegrationTest.groovy index ca923d26c0146..d60b422dd522b 100644 --- a/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/BuildSourceBuilderIntegrationTest.groovy +++ b/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/BuildSourceBuilderIntegrationTest.groovy @@ -26,6 +26,8 @@ import org.gradle.internal.operations.OperationFinishEvent import org.gradle.internal.operations.OperationIdentifier import org.gradle.internal.operations.OperationProgressEvent import org.gradle.internal.operations.OperationStartEvent +import org.gradle.internal.time.Time +import org.gradle.internal.time.Timer import org.gradle.test.fixtures.file.TestFile import org.gradle.test.fixtures.server.http.BlockingHttpServer import org.junit.Rule @@ -48,19 +50,23 @@ class BuildSourceBuilderIntegrationTest extends AbstractIntegrationSpec { import ${OperationFinishEvent.name} import ${OperationIdentifier.name} import ${ProcessEnvironment.name} + import ${Time.name} + import ${Timer.name} def pid = gradle.services.get(ProcessEnvironment).maybeGetPid() + def timer = Time.startTimer() - def listener = new TraceListener(pid: pid) + def listener = new TraceListener(pid: pid, timer: timer) def manager = gradle.services.get(BuildOperationListenerManager) manager.addListener(listener) gradle.buildFinished { manager.removeListener(listener) } class TraceListener implements BuildOperationListener { Long pid + Timer timer void started(BuildOperationDescriptor buildOperation, OperationStartEvent startEvent) { - println("[\$pid] start " + buildOperation.displayName) + println("[\$pid] [\$timer.elapsed] start " + buildOperation.displayName) } void progress(OperationIdentifier operationIdentifier, OperationProgressEvent progressEvent) { From 519d85e19d36f240dbdcaebaa6128f7278c9a462 Mon Sep 17 00:00:00 2001 From: Bo Zhang Date: Thu, 14 Mar 2019 09:40:12 +0800 Subject: [PATCH 525/853] Rebaseline improved scenarios --- .../regression/java/JavaFirstUsePerformanceTest.groovy | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/subprojects/performance/src/performanceTest/groovy/org/gradle/performance/regression/java/JavaFirstUsePerformanceTest.groovy b/subprojects/performance/src/performanceTest/groovy/org/gradle/performance/regression/java/JavaFirstUsePerformanceTest.groovy index 97fe13f59d1cc..d925cd2f88ca4 100644 --- a/subprojects/performance/src/performanceTest/groovy/org/gradle/performance/regression/java/JavaFirstUsePerformanceTest.groovy +++ b/subprojects/performance/src/performanceTest/groovy/org/gradle/performance/regression/java/JavaFirstUsePerformanceTest.groovy @@ -73,7 +73,7 @@ class JavaFirstUsePerformanceTest extends AbstractCrossVersionPerformanceTest { runner.gradleOpts = ["-Xms${testProject.daemonMemory}", "-Xmx${testProject.daemonMemory}"] runner.tasksToRun = ['tasks'] runner.useDaemon = false - runner.targetVersions = ["5.3-20190131161420+0000"] + runner.targetVersions = ["5.4-20190314000100+0000"] runner.addBuildExperimentListener(new BuildExperimentListenerAdapter() { @Override void afterInvocation(BuildExperimentInvocationInfo invocationInfo, MeasuredOperation operation, BuildExperimentListener.MeasurementCallback measurementCallback) { @@ -104,7 +104,7 @@ class JavaFirstUsePerformanceTest extends AbstractCrossVersionPerformanceTest { runner.gradleOpts = ["-Xms${testProject.daemonMemory}", "-Xmx${testProject.daemonMemory}"] runner.tasksToRun = ['tasks'] runner.useDaemon = false - runner.targetVersions = ["5.3-20190131161420+0000"] + runner.targetVersions = ["5.4-20190314000100+0000"] when: def result = runner.run() From 5e280a9fc512045d2c53bf44a27cc697fc395214 Mon Sep 17 00:00:00 2001 From: Gradleware Git Bot Date: Thu, 14 Mar 2019 03:34:08 +0100 Subject: [PATCH 526/853] Publish 5.3-20190314021933+0000 --- released-versions.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/released-versions.json b/released-versions.json index 403fbcc5a5bd8..b3421993a9b18 100644 --- a/released-versions.json +++ b/released-versions.json @@ -1,7 +1,7 @@ { "latestReleaseSnapshot": { - "version": "5.3-20190313010512+0000", - "buildTime": "20190313010512+0000" + "version": "5.3-20190314021933+0000", + "buildTime": "20190314021933+0000" }, "latestRc": { "version": "5.3-rc-3", From 3bd5a6ea24a550594b1f437fe095e8d59586e4ba Mon Sep 17 00:00:00 2001 From: Adam Murdoch Date: Fri, 8 Mar 2019 06:49:17 +1100 Subject: [PATCH 527/853] Change the test fixtures to interpret ANSI control characters in the console output, rather than attempting to strip them out in complex and unreliable ways. --- gradle/dependencies.gradle | 1 + .../internal-integ-testing.gradle.kts | 1 + .../fixtures/executer/LogContent.java | 72 ++++++++----------- .../OutputScrapingExecutionResult.java | 2 +- .../logging/GroupedOutputFixture.java | 16 ++--- ...actConsoleBuildResultFunctionalTest.groovy | 2 +- 6 files changed, 41 insertions(+), 53 deletions(-) diff --git a/gradle/dependencies.gradle b/gradle/dependencies.gradle index dc3243f684be7..ab647234d8653 100755 --- a/gradle/dependencies.gradle +++ b/gradle/dependencies.gradle @@ -95,6 +95,7 @@ libraries.slf4j_api = [coordinates: 'org.slf4j:slf4j-api', version: '1 libraries.jcl_to_slf4j = [coordinates: 'org.slf4j:jcl-over-slf4j', version: libraries.slf4j_api.version] libraries.jul_to_slf4j = [coordinates: 'org.slf4j:jul-to-slf4j', version: libraries.slf4j_api.version] libraries.log4j_to_slf4j = [coordinates: 'org.slf4j:log4j-over-slf4j', version: libraries.slf4j_api.version] +libraries.ansi_control_sequence_util = [coordinates: 'net.rubygrapefruit:ansi-control-sequence-util', version: '0.2'] // these are transitive dependencies that are part of the Gradle distribution libraries.jetbrains_annotations = [coordinates: 'org.jetbrains:annotations', version: '13.0'] diff --git a/subprojects/internal-integ-testing/internal-integ-testing.gradle.kts b/subprojects/internal-integ-testing/internal-integ-testing.gradle.kts index 562fe01c9781d..7e71aa5dedbd8 100644 --- a/subprojects/internal-integ-testing/internal-integ-testing.gradle.kts +++ b/subprojects/internal-integ-testing/internal-integ-testing.gradle.kts @@ -45,6 +45,7 @@ dependencies { compile(library("jcifs")) compile(library("jansi")) compile(library("commons_collections")) + compile(library("ansi_control_sequence_util")) compile("org.apache.mina:mina-core") compile(testLibrary("sampleCheck")) { exclude(module = "groovy-all") diff --git a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/LogContent.java b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/LogContent.java index 41c2d3a0ab368..2a60846d89528 100644 --- a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/LogContent.java +++ b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/LogContent.java @@ -18,48 +18,45 @@ import com.google.common.base.Joiner; import com.google.common.collect.ImmutableList; -import org.apache.commons.lang.StringUtils; -import org.fusesource.jansi.AnsiOutputStream; +import net.rubygrapefruit.ansi.AnsiParser; +import net.rubygrapefruit.ansi.console.AnsiConsole; +import net.rubygrapefruit.ansi.token.NewLine; +import net.rubygrapefruit.ansi.token.Text; import org.gradle.api.Action; import org.gradle.api.UncheckedIOException; import org.gradle.internal.Pair; import javax.annotation.Nullable; -import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.OutputStreamWriter; import java.io.Writer; import java.util.ArrayList; import java.util.List; import java.util.regex.Pattern; -import java.util.stream.Collectors; public class LogContent { private final static Pattern DEBUG_PREFIX = Pattern.compile("\\d{2}:\\d{2}:\\d{2}\\.\\d{3} \\[\\w+] \\[.+?] "); - private final static String PROGRESS_BAR_PATTERN = "<[-=(\u001b\\[\\d+[a-zA-Z;])]*> \\d+% (INITIALIZ|CONFIGUR|EXECUT|WAIT)ING( \\[((\\d+h )? \\d+m )?\\d+s\\])?"; - private final static String WORK_IN_PROGRESS_PATTERN = "\u001b\\[\\d+[a-zA-Z]> (IDLE|[:a-z][\\w\\s\\d:>/\\\\\\.]+)\u001b\\[\\d*[a-zA-Z]"; - private final static String DOWN_MOVEMENT_WITH_NEW_LINE_PATTERN = "\u001b\\[\\d+B\\n"; - private final static Pattern WORK_IN_PROGRESS_AREA_PATTERN = Pattern.compile(PROGRESS_BAR_PATTERN + "|" + WORK_IN_PROGRESS_PATTERN + "|" + DOWN_MOVEMENT_WITH_NEW_LINE_PATTERN); private final static Pattern JAVA_ILLEGAL_ACCESS_WARNING_PATTERN = Pattern.compile("(?ms)WARNING: An illegal reflective access operation has occurred$.+?" + "^WARNING: All illegal access operations will be denied in a future release\r?\n"); private final ImmutableList lines; private final boolean definitelyNoDebugPrefix; + private final boolean definitelyNoAnsiChars; private final LogContent rawContent; - private LogContent(ImmutableList lines, boolean definitelyNoDebugPrefix, LogContent rawContent) { + private LogContent(ImmutableList lines, boolean definitelyNoDebugPrefix, boolean definitelyNoAnsiChars, LogContent rawContent) { this.lines = lines; this.rawContent = rawContent == null ? this : rawContent; this.definitelyNoDebugPrefix = definitelyNoDebugPrefix || lines.isEmpty(); + this.definitelyNoAnsiChars = definitelyNoAnsiChars || lines.isEmpty(); } /** * Creates a new instance, from raw characters. */ public static LogContent of(String chars) { - String stripped = stripWorkInProgressArea(chars); - LogContent raw = new LogContent(toLines(stripped), false, null); - return new LogContent(toLines(stripJavaIllegalAccessWarnings(stripped)), false, raw); + LogContent raw = new LogContent(toLines(chars), false, false, null); + return new LogContent(toLines(stripJavaIllegalAccessWarnings(chars)), false, false, raw); } private static ImmutableList toLines(String chars) { @@ -91,11 +88,11 @@ private static ImmutableList toLines(String chars) { * Creates a new instance from a sequence of lines (without the line separators). */ public static LogContent of(List lines) { - return new LogContent(ImmutableList.copyOf(lines), false, null); + return new LogContent(ImmutableList.copyOf(lines), false, false,null); } public static LogContent empty() { - return new LogContent(ImmutableList.of(), true, null); + return new LogContent(ImmutableList.of(), true, true, null); } /** @@ -135,7 +132,7 @@ private LogContent lines(int startLine, int endLine) { if (rawContent != this) { throw new UnsupportedOperationException("not implemented"); } - return new LogContent(lines.subList(startLine, endLine), definitelyNoDebugPrefix, null); + return new LogContent(lines.subList(startLine, endLine), definitelyNoDebugPrefix, definitelyNoAnsiChars, null); } /** @@ -157,8 +154,8 @@ Pair splitOnFirstMatchingLine(Pattern pattern) { for (int i = 0; i < lines.size(); i++) { String line = lines.get(i); if (pattern.matcher(line).matches()) { - LogContent before = new LogContent(lines.subList(0, i), definitelyNoDebugPrefix, rawContent.lines(0, i)); - LogContent after = new LogContent(lines.subList(i, lines.size()), definitelyNoDebugPrefix, rawContent.lines(i, lines.size())); + LogContent before = new LogContent(lines.subList(0, i), definitelyNoDebugPrefix, definitelyNoAnsiChars, rawContent); + LogContent after = new LogContent(lines.subList(i, lines.size()), definitelyNoDebugPrefix, definitelyNoAnsiChars, rawContent); return Pair.of(before, after); } } @@ -182,7 +179,7 @@ public int countMatches(Pattern pattern) { * Drops the first n lines. */ public LogContent drop(int i) { - return new LogContent(lines.subList(i, lines.size()), definitelyNoDebugPrefix, rawContent.lines(i, lines.size())); + return new LogContent(lines.subList(i, lines.size()), definitelyNoDebugPrefix, definitelyNoAnsiChars, rawContent); } /** @@ -201,19 +198,20 @@ public LogContent removeDebugPrefix() { result.add(line); } } - return new LogContent(ImmutableList.copyOf(result), true, rawContent); + return new LogContent(ImmutableList.copyOf(result), true, definitelyNoAnsiChars, rawContent); } /** * Returns a copy of this log content with ANSI control characters removed. */ public LogContent removeAnsiChars() { - if (lines.isEmpty()) { + if (definitelyNoAnsiChars) { return this; } try { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - Writer writer = new OutputStreamWriter(new AnsiOutputStream(baos)); + AnsiConsole console = new AnsiConsole(); + AnsiParser parser = new AnsiParser(); + Writer writer = new OutputStreamWriter(parser.newParser("utf-8", console)); for (int i = 0; i < lines.size(); i++) { if (i > 0) { writer.write("\n"); @@ -221,33 +219,21 @@ public LogContent removeAnsiChars() { writer.write(lines.get(i)); } writer.flush(); - return new LogContent(toLines(baos.toString()), definitelyNoDebugPrefix, rawContent); + StringBuilder result = new StringBuilder(); + console.contents(token -> { + if (token instanceof Text) { + result.append(((Text) token).getText()); + } else if (token instanceof NewLine) { + result.append("\n"); + } + }); + return new LogContent(toLines(result.toString()), definitelyNoDebugPrefix, true, rawContent); } catch (IOException e) { throw new UncheckedIOException(e); } } - /** - * Remove all blank lines. - */ - public LogContent removeBlankLines() { - List nonBlankLines = lines.stream().filter(StringUtils::isNotBlank).collect(Collectors.toList()); - return new LogContent(ImmutableList.copyOf(nonBlankLines), definitelyNoDebugPrefix, rawContent); - } - - public static String stripWorkInProgressArea(String output) { - String result = output; - for (int i = 1; i <= 10; ++i) { - result = result.replaceAll(workInProgressAreaScrollingPattern(i), ""); - } - return WORK_IN_PROGRESS_AREA_PATTERN.matcher(result).replaceAll(""); - } - public static String stripJavaIllegalAccessWarnings(String result) { return JAVA_ILLEGAL_ACCESS_WARNING_PATTERN.matcher(result).replaceAll(""); } - - private static String workInProgressAreaScrollingPattern(int scroll) { - return "(\u001b\\[0K\\n){" + scroll + "}\u001b\\[" + scroll + "A"; - } } diff --git a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/OutputScrapingExecutionResult.java b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/OutputScrapingExecutionResult.java index 8a920392162d2..63a0929c57c5d 100644 --- a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/OutputScrapingExecutionResult.java +++ b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/OutputScrapingExecutionResult.java @@ -114,7 +114,7 @@ public String getNormalizedOutput() { @Override public GroupedOutputFixture getGroupedOutput() { if (groupedOutputFixture == null) { - groupedOutputFixture = new GroupedOutputFixture(getMainContent().getRawContent().withNormalizedEol()); + groupedOutputFixture = new GroupedOutputFixture(getMainContent()); } return groupedOutputFixture; } diff --git a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/logging/GroupedOutputFixture.java b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/logging/GroupedOutputFixture.java index 0ec5e1eb2765f..dbde7a0818fe6 100644 --- a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/logging/GroupedOutputFixture.java +++ b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/logging/GroupedOutputFixture.java @@ -32,10 +32,10 @@ */ public class GroupedOutputFixture { /** - * All tasks will start with > Task, captures everything starting with : and going until a control char + * All tasks will start with > Task, captures everything starting with : and going until end of line */ - private final static String TASK_HEADER = "> Task (:[\\w:]*) ?(FAILED|FROM-CACHE|UP-TO-DATE|SKIPPED|NO-SOURCE)?\\n?"; - private final static String TRANSFORMATION_HEADER = "> Transform (artifact|file) ([^\\n]+) with ([^\\n]+)\\n?"; + private final static String TASK_HEADER = "> Task (:[\\w:]*) ?(FAILED|FROM-CACHE|UP-TO-DATE|SKIPPED|NO-SOURCE)?\\n"; + private final static String TRANSFORMATION_HEADER = "> Transform (artifact|file) ([^\\n]+) with ([^\\n]+)\\n"; private final static String EMBEDDED_BUILD_START = "> :\\w* > [:\\w]+"; private final static String BUILD_STATUS_FOOTER = "BUILD SUCCESSFUL"; @@ -65,21 +65,21 @@ private static Pattern patternForHeader(String header) { return Pattern.compile(pattern); } - private final String originalOutput; + private final LogContent originalOutput; private final String strippedOutput; private Map tasks; private Map transformations; - public GroupedOutputFixture(String output) { + public GroupedOutputFixture(LogContent output) { this.originalOutput = output; this.strippedOutput = parse(output); } - private String parse(String output) { + private String parse(LogContent output) { tasks = new HashMap(); transformations = new HashMap(); - String strippedOutput = LogContent.of(output).removeAnsiChars().withNormalizedEol(); + String strippedOutput = output.removeAnsiChars().withNormalizedEol(); findOutputs(strippedOutput, TASK_OUTPUT_PATTERN, this::consumeTaskOutput); findOutputs(strippedOutput, TRANSFORMATION_OUTPUT_PATTERN, this::consumeTransformationOutput); @@ -127,7 +127,7 @@ public String getStrippedOutput() { } public String toString() { - return originalOutput; + return originalOutput.withNormalizedEol(); } private void consumeTaskOutput(Matcher matcher) { diff --git a/subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/taskgrouping/AbstractConsoleBuildResultFunctionalTest.groovy b/subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/taskgrouping/AbstractConsoleBuildResultFunctionalTest.groovy index a3bdab91fc2ca..b5a0cba2fc5a9 100644 --- a/subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/taskgrouping/AbstractConsoleBuildResultFunctionalTest.groovy +++ b/subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/taskgrouping/AbstractConsoleBuildResultFunctionalTest.groovy @@ -123,7 +123,7 @@ BUILD SUCCESSFUL in \\d+s\\n* // Check that the failure text appears either stdout or stderr def outputWithFailure = errorsShouldAppearOnStdout() ? failure.output : failure.error def outputWithoutFailure = errorsShouldAppearOnStdout() ? failure.error : failure.output - def outputWithFailureAndNoDebugging = LogContent.of(outputWithFailure).removeAnsiChars().removeDebugPrefix().removeBlankLines().withNormalizedEol() + def outputWithFailureAndNoDebugging = LogContent.of(outputWithFailure).removeAnsiChars().removeDebugPrefix().withNormalizedEol() outputWithFailure.contains("Build failed with an exception.") outputWithFailureAndNoDebugging.contains(""" From 25d38770fc2814e3dec733c7d8de21e192d83ab0 Mon Sep 17 00:00:00 2001 From: Adam Murdoch Date: Fri, 8 Mar 2019 12:20:07 +1100 Subject: [PATCH 528/853] Remove some duplication from the logic that sets up logging to the console. Also simplify some of the console functional tests. --- ...WithMetadataSupplierIntegrationTest.groovy | 6 +- ...rocessGradleExecuterIntegrationTest.groovy | 4 +- .../fixtures/RichConsoleStyling.groovy | 31 ------ ...actConsoleGroupedTaskFunctionalTest.groovy | 96 +++++++++++++++---- .../executer/AbstractGradleExecuter.java | 9 +- .../fixtures/executer/ConsoleAttachment.java | 1 - ...ErrorsOnStdoutScrapingExecutionResult.java | 12 --- .../fixtures/executer/ExecutionResult.java | 14 --- .../executer/InProcessGradleExecuter.java | 12 --- .../fixtures/executer/LogContent.java | 55 ++++++++--- .../OutputScrapingExecutionFailure.java | 4 +- .../OutputScrapingExecutionResult.java | 14 +-- .../logging/GroupedOutputFixture.java | 2 +- .../OutputScrapingExecutionFailureTest.groovy | 15 ++- .../logging/GroupedOutputFixtureTest.groovy | 88 ++++++++--------- .../PrecompiledScriptPluginAccessorsTest.kt | 4 +- ...ractConsoleBuildPhaseFunctionalTest.groovy | 11 ++- ...actConsoleBuildResultFunctionalTest.groovy | 30 +++--- ...ojectConfigureLoggingFunctionalTest.groovy | 2 +- ...sicGroupedTaskLoggingFunctionalTest.groovy | 15 +-- .../logging/sink/ConsoleConfigureAction.java | 81 +++++++--------- .../logging/sink/OutputEventRenderer.java | 51 +++------- .../sink/OutputEventRendererTest.groovy | 14 +-- .../console/ConsoleMetaData.java | 2 + .../console/FallbackConsoleMetaData.java | 5 + .../NativePlatformConsoleMetaData.java | 5 + .../console/TestConsoleMetadata.java | 6 +- 27 files changed, 291 insertions(+), 298 deletions(-) diff --git a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/suppliers/DynamicRevisionRemoteResolveWithMetadataSupplierIntegrationTest.groovy b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/suppliers/DynamicRevisionRemoteResolveWithMetadataSupplierIntegrationTest.groovy index b9de31e9bd478..349b8aa2cd41f 100644 --- a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/suppliers/DynamicRevisionRemoteResolveWithMetadataSupplierIntegrationTest.groovy +++ b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/suppliers/DynamicRevisionRemoteResolveWithMetadataSupplierIntegrationTest.groovy @@ -16,10 +16,10 @@ package org.gradle.integtests.resolve.suppliers import org.gradle.api.internal.artifacts.ivyservice.CacheLayout -import org.gradle.integtests.fixtures.cache.CachingIntegrationFixture import org.gradle.integtests.fixtures.GradleMetadataResolveRunner import org.gradle.integtests.fixtures.RequiredFeature import org.gradle.integtests.fixtures.RequiredFeatures +import org.gradle.integtests.fixtures.cache.CachingIntegrationFixture import org.gradle.integtests.resolve.AbstractModuleDependencyResolveTest import org.gradle.test.fixtures.HttpModule import org.gradle.test.fixtures.file.TestFile @@ -1040,8 +1040,8 @@ group:projectB:2.2;release then: noExceptionThrown() - result.assertRawOutputContains "Found result for rule [DefaultConfigurableRule{rule=class MP, ruleParams=[]}] and key group:projectB:2.2" - result.assertRawOutputContains "Found result for rule [DefaultConfigurableRule{rule=class MP, ruleParams=[]}] and key group:projectB:1.1" + result.assertOutputContains "Found result for rule [DefaultConfigurableRule{rule=class MP, ruleParams=[]}] and key group:projectB:2.2" + result.assertOutputContains "Found result for rule [DefaultConfigurableRule{rule=class MP, ruleParams=[]}] and key group:projectB:1.1" } def "changing the implementation of a rule invalidates the cache"() { diff --git a/subprojects/internal-integ-testing/src/integTest/groovy/org/gradle/integtests/fixtures/executer/InProcessGradleExecuterIntegrationTest.groovy b/subprojects/internal-integ-testing/src/integTest/groovy/org/gradle/integtests/fixtures/executer/InProcessGradleExecuterIntegrationTest.groovy index 43fdb95222c71..9326527a18ab1 100644 --- a/subprojects/internal-integ-testing/src/integTest/groovy/org/gradle/integtests/fixtures/executer/InProcessGradleExecuterIntegrationTest.groovy +++ b/subprojects/internal-integ-testing/src/integTest/groovy/org/gradle/integtests/fixtures/executer/InProcessGradleExecuterIntegrationTest.groovy @@ -23,8 +23,6 @@ import org.junit.Rule import spock.lang.Specification import spock.lang.Unroll -import static org.gradle.util.TextUtil.normaliseLineSeparators - class InProcessGradleExecuterIntegrationTest extends Specification { @Rule RedirectStdOutAndErr outputs = new RedirectStdOutAndErr() @@ -146,6 +144,6 @@ class InProcessGradleExecuterIntegrationTest extends Specification { } def stripped(String output) { - return normaliseLineSeparators(LogContent.stripWorkInProgressArea(output)) + return LogContent.of(output).withNormalizedEol() } } diff --git a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/RichConsoleStyling.groovy b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/RichConsoleStyling.groovy index 4925a6f932e45..87725c849f001 100644 --- a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/RichConsoleStyling.groovy +++ b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/RichConsoleStyling.groovy @@ -15,9 +15,6 @@ */ package org.gradle.integtests.fixtures - -import org.fusesource.jansi.Ansi - /** * A trait for testing console behavior. *

    @@ -25,34 +22,6 @@ import org.fusesource.jansi.Ansi */ trait RichConsoleStyling { public final static String CONTROL_SEQUENCE_START = "\u001B[" - public final static String CONTROL_SEQUENCE_SEPARATOR = ";" - public final static String CONTROL_SEQUENCE_END = "m" - public final static String DEFAULT_TEXT = "0;39" - - /** - * Wraps the text in the proper control characters for styled output in the rich console - */ - static String styledText(String plainText, Ansi.Color color, Ansi.Attribute... attributes) { - String styledString = CONTROL_SEQUENCE_START - if (color) { - styledString += color.fg() - } - if (attributes) { - attributes.each { attribute -> - if (styledString.length() > CONTROL_SEQUENCE_START.length()) { - styledString += CONTROL_SEQUENCE_SEPARATOR - } - styledString += attribute.value() - } - } - styledString += CONTROL_SEQUENCE_END + plainText + CONTROL_SEQUENCE_START - if (color) { - styledString += DEFAULT_TEXT - } - styledString += CONTROL_SEQUENCE_END - - return styledString - } static String workInProgressLine(String plainText) { return boldOn() + plainText + reset() diff --git a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/console/AbstractConsoleGroupedTaskFunctionalTest.groovy b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/console/AbstractConsoleGroupedTaskFunctionalTest.groovy index aecce379bb5cc..b42e55073da47 100644 --- a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/console/AbstractConsoleGroupedTaskFunctionalTest.groovy +++ b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/console/AbstractConsoleGroupedTaskFunctionalTest.groovy @@ -38,35 +38,99 @@ abstract class AbstractConsoleGroupedTaskFunctionalTest extends AbstractIntegrat } boolean errorsShouldAppearOnStdout() { - // If stderr is attached to the console or if we'll use the fallback console - return (consoleAttachment.isStderrAttached() && consoleAttachment.isStdoutAttached()) || usesFallbackConsole() + // If both stdout and stderr is attached to the console, they are merged together + return consoleAttachment.isStderrAttached() && consoleAttachment.isStdoutAttached() } - boolean usesFallbackConsole() { - return consoleAttachment == ConsoleAttachment.NOT_ATTACHED && (consoleType == ConsoleOutput.Rich || consoleType == ConsoleOutput.Verbose) + boolean stdoutUsesStyledText() { + if (!consoleAttachment.stdoutAttached && consoleAttachment.stderrAttached) { + // Can currently write rich text to one stream at a time, and we prefer stderr when it is attached to the console and stdout is not + return false + } + return consoleType == ConsoleOutput.Rich || consoleType == ConsoleOutput.Verbose || consoleType == ConsoleOutput.Auto && consoleAttachment.stdoutAttached + } + + boolean stderrUsesStyledText() { + // Can currently write rich text to one stream at a time, and we prefer stdout when it is attached to the console + if (!consoleAttachment.stdoutAttached && consoleAttachment.stderrAttached) { + return consoleType == ConsoleOutput.Rich || consoleType == ConsoleOutput.Verbose || consoleType == ConsoleOutput.Auto && consoleAttachment.stderrAttached + } + return false } abstract ConsoleOutput getConsoleType() - protected StyledOutput styled(String plainOutput, Ansi.Color color, Ansi.Attribute... attributes) { - return new StyledOutput(plainOutput, color, attributes) + protected StyledOutput styled(Ansi.Color color, Ansi.Attribute attribute) { + return new StyledOutput(null, color, attribute) } - public class StyledOutput { - private final String plainOutput - private final String styledOutput + protected StyledOutput styled(Ansi.Attribute attribute) { + return new StyledOutput(null, null, attribute) + } + + class StyledOutput { + final String plainOutput + final String styledOutput + private final Ansi.Color color + private final Ansi.Attribute attribute + + private StyledOutput(StyledOutput previous, Ansi.Color color, Ansi.Attribute attribute) { + if (attribute != Ansi.Attribute.INTENSITY_BOLD && attribute != null) { + throw new UnsupportedOperationException() + } + this.color = color + this.attribute = attribute + def previousColor = null + def previousAttribute = null + def styled = "" + if (previous == null) { + this.plainOutput = "" + } else { + this.plainOutput = previous.plainOutput + previousColor = previous.color + previousAttribute = previous.attribute + styled = previous.styledOutput + } + if (attribute != null && previousAttribute == null) { + styled += "{bold-on}" + } + if (attribute == null && previousAttribute != null) { + styled += "{bold-off}" + } + if (color != null && color != previousColor) { + styled += "{foreground-color " + color.name().toLowerCase() + "}" + } + if (color == null && previousColor != null) { + styled += "{foreground-color default}" + } + this.styledOutput = styled + } + + private StyledOutput(StyledOutput previous, String text) { + this.color = previous.color + this.attribute = previous.attribute + this.plainOutput = previous.plainOutput + text + this.styledOutput = previous.styledOutput + text + } + + StyledOutput text(String text) { + return new StyledOutput(this, text) + } + + StyledOutput styled(Ansi.Attribute attribute) { + return new StyledOutput(this, color, attribute) + } - StyledOutput(String plainOutput, Ansi.Color color, Ansi.Attribute... attributes) { - this.plainOutput = plainOutput - this.styledOutput = styledText(plainOutput, color, attributes) + StyledOutput off() { + return new StyledOutput(this, null, null) } - public String getOutput() { - return consoleAttachment.stdoutAttached ? styledOutput : plainOutput + String getOutput() { + return stdoutUsesStyledText() ? styledOutput : plainOutput } - public String getErrorOutput() { - return consoleAttachment.stderrAttached ? styledOutput : plainOutput + String getErrorOutput() { + return stderrUsesStyledText() ? styledOutput : plainOutput } } } diff --git a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/AbstractGradleExecuter.java b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/AbstractGradleExecuter.java index 17c518eec01b6..cf666a0ab9151 100644 --- a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/AbstractGradleExecuter.java +++ b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/AbstractGradleExecuter.java @@ -76,7 +76,10 @@ import static org.gradle.api.internal.artifacts.BaseRepositoryFactory.PLUGIN_PORTAL_OVERRIDE_URL_PROPERTY; import static org.gradle.integtests.fixtures.RepoScriptBlockUtil.gradlePluginRepositoryMirrorUrl; -import static org.gradle.integtests.fixtures.executer.AbstractGradleExecuter.CliDaemonArgument.*; +import static org.gradle.integtests.fixtures.executer.AbstractGradleExecuter.CliDaemonArgument.DAEMON; +import static org.gradle.integtests.fixtures.executer.AbstractGradleExecuter.CliDaemonArgument.FOREGROUND; +import static org.gradle.integtests.fixtures.executer.AbstractGradleExecuter.CliDaemonArgument.NOT_DEFINED; +import static org.gradle.integtests.fixtures.executer.AbstractGradleExecuter.CliDaemonArgument.NO_DAEMON; import static org.gradle.integtests.fixtures.executer.OutputScrapingExecutionResult.STACK_TRACE_ELEMENT; import static org.gradle.internal.service.scopes.DefaultGradleUserHomeScopeServiceRegistry.REUSE_USER_HOME_SERVICES; import static org.gradle.util.CollectionUtils.collect; @@ -1403,7 +1406,7 @@ protected GradleExecuter configureConsoleCommandLineArgs() { } private boolean errorsShouldAppearOnStdout() { - // If stderr is attached to the console or if we'll use the fallback console - return (consoleAttachment.isStderrAttached() && consoleAttachment.isStdoutAttached()) || (consoleAttachment == ConsoleAttachment.NOT_ATTACHED && (consoleType == ConsoleOutput.Rich || consoleType == ConsoleOutput.Verbose)); + // If stdout and stderr are attached to the console + return consoleAttachment.isStderrAttached() && consoleAttachment.isStdoutAttached(); } } diff --git a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/ConsoleAttachment.java b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/ConsoleAttachment.java index fd1525b89bcec..31bacb8d63efe 100644 --- a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/ConsoleAttachment.java +++ b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/ConsoleAttachment.java @@ -21,7 +21,6 @@ public enum ConsoleAttachment { NOT_ATTACHED("not attached to a console", null), ATTACHED("console attached to both stdout and stderr", TestConsoleMetadata.BOTH), - ATTACHED_NEITHER("console detected but not attached to either stdout or stderr", TestConsoleMetadata.NEITHER), ATTACHED_STDOUT_ONLY("console attached to stdout only", TestConsoleMetadata.STDOUT_ONLY), ATTACHED_STDERR_ONLY("console attached to stderr only", TestConsoleMetadata.STDERR_ONLY); diff --git a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/ErrorsOnStdoutScrapingExecutionResult.java b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/ErrorsOnStdoutScrapingExecutionResult.java index d47456d83f78a..87e75ae88dc91 100644 --- a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/ErrorsOnStdoutScrapingExecutionResult.java +++ b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/ErrorsOnStdoutScrapingExecutionResult.java @@ -59,18 +59,6 @@ public boolean hasErrorOutput(String expectedOutput) { return getOutput().contains(expectedOutput); } - @Override - public ExecutionResult assertHasRawErrorOutput(String expectedOutput) { - delegate.assertRawOutputContains(expectedOutput); - return this; - } - - @Override - public ExecutionResult assertRawOutputContains(String expectedOutput) { - delegate.assertRawOutputContains(expectedOutput); - return this; - } - @Override public ExecutionResult assertOutputEquals(String expectedOutput, boolean ignoreExtraLines, boolean ignoreLineOrder) { delegate.assertOutputEquals(expectedOutput, ignoreExtraLines, ignoreLineOrder); diff --git a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/ExecutionResult.java b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/ExecutionResult.java index 6bda1a9fb55e9..4cb4f635f5865 100644 --- a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/ExecutionResult.java +++ b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/ExecutionResult.java @@ -61,13 +61,6 @@ public interface ExecutionResult { */ ExecutionResult assertHasErrorOutput(String expectedOutput); - /** - * Asserts that this result includes the given error log message in the raw output (including ANSI characters and build result message). - * - * @param expectedOutput The expected log message, with line endings normalized to a newline character. - */ - ExecutionResult assertHasRawErrorOutput(String expectedOutput); - /** * Returns true when this result includes the given error log message. Does not consider any text in or following the build result message (use {@link #assertHasPostBuildOutput(String)} instead). * @@ -84,13 +77,6 @@ public interface ExecutionResult { */ ExecutionResult assertOutputContains(String expectedOutput); - /** - * Asserts that this result includes the given non-error log message (including ANSI characters and build result message). - * - * @param expectedOutput The expected log message, with line endings normalized to a newline character. - */ - ExecutionResult assertRawOutputContains(String expectedOutput); - /** * Asserts that the given content includes the given log message. * diff --git a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/InProcessGradleExecuter.java b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/InProcessGradleExecuter.java index e5bb1eff18471..4fe676a22a8fe 100755 --- a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/InProcessGradleExecuter.java +++ b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/InProcessGradleExecuter.java @@ -557,18 +557,6 @@ public ExecutionResult assertHasErrorOutput(String expectedOutput) { return this; } - @Override - public ExecutionResult assertHasRawErrorOutput(String expectedOutput) { - outputResult.assertHasRawErrorOutput(expectedOutput); - return this; - } - - @Override - public ExecutionResult assertRawOutputContains(String expectedOutput) { - outputResult.assertRawOutputContains(expectedOutput); - return this; - } - public String getError() { return outputResult.getError(); } diff --git a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/LogContent.java b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/LogContent.java index 2a60846d89528..5118c43364b77 100644 --- a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/LogContent.java +++ b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/LogContent.java @@ -20,6 +20,7 @@ import com.google.common.collect.ImmutableList; import net.rubygrapefruit.ansi.AnsiParser; import net.rubygrapefruit.ansi.console.AnsiConsole; +import net.rubygrapefruit.ansi.console.DiagnosticConsole; import net.rubygrapefruit.ansi.token.NewLine; import net.rubygrapefruit.ansi.token.Text; import org.gradle.api.Action; @@ -88,7 +89,7 @@ private static ImmutableList toLines(String chars) { * Creates a new instance from a sequence of lines (without the line separators). */ public static LogContent of(List lines) { - return new LogContent(ImmutableList.copyOf(lines), false, false,null); + return new LogContent(ImmutableList.copyOf(lines), false, false, null); } public static LogContent empty() { @@ -202,23 +203,14 @@ public LogContent removeDebugPrefix() { } /** - * Returns a copy of this log content with ANSI control characters removed. + * Returns a copy of this log content with ANSI control characters interpreted to produce plain text. */ - public LogContent removeAnsiChars() { + public LogContent ansiCharsToPlainText() { if (definitelyNoAnsiChars) { return this; } try { - AnsiConsole console = new AnsiConsole(); - AnsiParser parser = new AnsiParser(); - Writer writer = new OutputStreamWriter(parser.newParser("utf-8", console)); - for (int i = 0; i < lines.size(); i++) { - if (i > 0) { - writer.write("\n"); - } - writer.write(lines.get(i)); - } - writer.flush(); + AnsiConsole console = interpretAnsiChars(); StringBuilder result = new StringBuilder(); console.contents(token -> { if (token instanceof Text) { @@ -233,6 +225,43 @@ public LogContent removeAnsiChars() { } } + /** + * Returns a copy of this log content with ANSI control characters interpreted to produce plain text with text attributes included. + */ + public LogContent ansiCharsToColorText() { + if (definitelyNoAnsiChars) { + return this; + } + try { + AnsiConsole console = interpretAnsiChars(); + DiagnosticConsole diagnosticConsole = new DiagnosticConsole(); + for (int i = 0; i < console.getRows().size(); i++) { + AnsiConsole.Row row = console.getRows().get(i); + if (i > 0) { + diagnosticConsole.visit(NewLine.INSTANCE); + } + row.visit(diagnosticConsole); + } + return new LogContent(toLines(diagnosticConsole.toString()), definitelyNoDebugPrefix, true, rawContent); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + + private AnsiConsole interpretAnsiChars() throws IOException { + AnsiConsole console = new AnsiConsole(); + AnsiParser parser = new AnsiParser(); + Writer writer = new OutputStreamWriter(parser.newParser("utf-8", console)); + for (int i = 0; i < lines.size(); i++) { + if (i > 0) { + writer.write("\n"); + } + writer.write(lines.get(i)); + } + writer.flush(); + return console; + } + public static String stripJavaIllegalAccessWarnings(String result) { return JAVA_ILLEGAL_ACCESS_WARNING_PATTERN.matcher(result).replaceAll(""); } diff --git a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/OutputScrapingExecutionFailure.java b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/OutputScrapingExecutionFailure.java index d285303ea575c..f2a47c2b89758 100644 --- a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/OutputScrapingExecutionFailure.java +++ b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/OutputScrapingExecutionFailure.java @@ -63,13 +63,13 @@ public static OutputScrapingExecutionFailure from(String output, String error) { protected OutputScrapingExecutionFailure(String output, String error) { super(LogContent.of(output), LogContent.of(error)); - LogContent withoutDebug = LogContent.of(output).removeAnsiChars().removeDebugPrefix(); + LogContent withoutDebug = LogContent.of(output).ansiCharsToPlainText().removeDebugPrefix(); // Find failure section Pair match = withoutDebug.splitOnFirstMatchingLine(FAILURE_PATTERN); if (match == null) { // Not present in output, check error output. - match = LogContent.of(error).removeAnsiChars().removeDebugPrefix().splitOnFirstMatchingLine(FAILURE_PATTERN); + match = LogContent.of(error).ansiCharsToPlainText().removeDebugPrefix().splitOnFirstMatchingLine(FAILURE_PATTERN); if (match != null) { match = Pair.of(withoutDebug, match.getRight()); } else { diff --git a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/OutputScrapingExecutionResult.java b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/OutputScrapingExecutionResult.java index 63a0929c57c5d..a4c1260a585eb 100644 --- a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/OutputScrapingExecutionResult.java +++ b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/OutputScrapingExecutionResult.java @@ -83,7 +83,7 @@ protected OutputScrapingExecutionResult(LogContent output, LogContent error) { this.error = error; // Split out up the output into main content and post build content - LogContent filteredOutput = this.output.removeAnsiChars().removeDebugPrefix(); + LogContent filteredOutput = this.output.ansiCharsToPlainText().removeDebugPrefix(); Pair match = filteredOutput.splitOnFirstMatchingLine(BUILD_RESULT_PATTERN); if (match == null) { this.mainContent = filteredOutput; @@ -92,7 +92,7 @@ protected OutputScrapingExecutionResult(LogContent output, LogContent error) { this.mainContent = match.getLeft(); this.postBuild = match.getRight().drop(1); } - this.errorContent = error.removeAnsiChars(); + this.errorContent = error.ansiCharsToPlainText(); } public String getOutput() { @@ -193,16 +193,6 @@ public ExecutionResult assertHasErrorOutput(String expectedOutput) { return assertContentContains(errorContent.withNormalizedEol(), expectedOutput, "Error output"); } - @Override - public ExecutionResult assertHasRawErrorOutput(String expectedOutput) { - return assertContentContains(getError(), expectedOutput, "Error output"); - } - - @Override - public ExecutionResult assertRawOutputContains(String expectedOutput) { - return assertContentContains(getOutput(), expectedOutput, "Build output"); - } - public String getError() { return error.withNormalizedEol(); } diff --git a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/logging/GroupedOutputFixture.java b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/logging/GroupedOutputFixture.java index dbde7a0818fe6..790e00acd3d2f 100644 --- a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/logging/GroupedOutputFixture.java +++ b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/logging/GroupedOutputFixture.java @@ -79,7 +79,7 @@ private String parse(LogContent output) { tasks = new HashMap(); transformations = new HashMap(); - String strippedOutput = output.removeAnsiChars().withNormalizedEol(); + String strippedOutput = output.ansiCharsToPlainText().withNormalizedEol(); findOutputs(strippedOutput, TASK_OUTPUT_PATTERN, this::consumeTaskOutput); findOutputs(strippedOutput, TRANSFORMATION_OUTPUT_PATTERN, this::consumeTransformationOutput); diff --git a/subprojects/internal-integ-testing/src/test/groovy/org/gradle/integtests/fixtures/executer/OutputScrapingExecutionFailureTest.groovy b/subprojects/internal-integ-testing/src/test/groovy/org/gradle/integtests/fixtures/executer/OutputScrapingExecutionFailureTest.groovy index feb6cf40ba4c4..fec2b05f35722 100644 --- a/subprojects/internal-integ-testing/src/test/groovy/org/gradle/integtests/fixtures/executer/OutputScrapingExecutionFailureTest.groovy +++ b/subprojects/internal-integ-testing/src/test/groovy/org/gradle/integtests/fixtures/executer/OutputScrapingExecutionFailureTest.groovy @@ -356,6 +356,13 @@ Some.Failure failure.assertOutputContains("Some sort of output") failure.assertOutputContains "Some more output" + and: + !failure.mainContent.withNormalizedEol().contains("INITIALIZING") + !failure.mainContent.withNormalizedEol().contains("IDLE") + + and: + !failure.mainContent.withNormalizedEol().contains("DEBUG") + where: output << [rawOutput, debugOutput] } @@ -393,11 +400,11 @@ WARNING: All illegal access operations will be denied in a future release def static getRawOutput() { return """ -\u001B[2A\u001B[1m<\u001B[0;32;1;0;39;1m-------------> 0% INITIALIZING [0s]\u001B[m\u001B[36D\u001B[1B\u001B[1m> Evaluating settings\u001B[m\u001B[21D\u001B[1B\u001B[2A\u001B[1m<\u001B[0;32;1;0;39;1m-------------> 0% INITIALIZING [0s]\u001B[m\u001B[36D\u001B[1B\u001B[1m> Evaluating settings\u001B[m\u001B[21D\u001B[1B\u001B[2A\u001B[1m<\u001B[0;32;1;0;39;1m-------------> 0% INITIALIZING [0s]\u001B[m\u001B[36D\u001B[1B\u001B[1m> Evaluating settings\u001B[m\u001B[21D\u001B[1B\u001B[2A\u001B[1m<\u001B[0;32;1;0;39;1m-------------> 0% INITIALIZING [0s]\u001B[m\u001B[36D\u001B[1B\u001B[1m> Evaluating settings\u001B[m\u001B[21D\u001B[1B\u001B[2A\u001B[1m<\u001B[0;32;1;0;39;1m-------------> 0% INITIALIZING [0s]\u001B[m\u001B[36D\u001B[1B\u001B[1m> Evaluating settings\u001B[m\u001B[21D\u001B[1B\u001B[2A\u001B[1m<\u001B[0;32;1;0;39;1m-------------> 0% INITIALIZING [0s]\u001B[m\u001B[36D\u001B[1B\u001B[1m> Evaluating settings\u001B[m\u001B[21D\u001B[1B\u001BSome sort of output\u001B[0K -Some sort of FAILURE: without status bar or work in progress +\u001B[1m<\u001B[0;32;1;0;39;1m-------------> 0% INITIALIZING [0s]\u001B[m\u001B[36D\u001B[1B\u001B[1m> Evaluating settings\u001B[m\u001B[21D\u001B[1B\u001B[2A\u001B[1m<\u001B[0;32;1;0;39;1m-------------> 0% INITIALIZING [0s]\u001B[m\u001B[36D\u001B[1B\u001B[1m> Evaluating settings\u001B[m\u001B[21D\u001B[1B\u001B[2A\u001B[1m<\u001B[0;32;1;0;39;1m-------------> 0% INITIALIZING [0s]\u001B[m\u001B[36D\u001B[1B\u001B[1m> Evaluating settings\u001B[m\u001B[21D\u001B[1B\u001B[2ASome sort of output\u001B[0K +Some sort of FAILURE: without status bar or work in progress\u001B[0K Some more output -\u001B[2A\u001B[1m<\u001B[0;32;1;0;39;1m-------------> 0% EXECUTING [2s]\u001B[m\u001B[33D\u001B[1B> IDLE\u001B[6D\u001B[1B\u001B[2AFAILURE: \u001B[39m\u001B[31mBuild failed with an exception. \u001B[39m\u001B[0K - +\u001B[1m<\u001B[0;32;1;0;39;1m-------------> 0% EXECUTING [2s]\u001B[m\u001B[33D\u001B[1B> IDLE\u001B[6D\u001B[1B\u001B[2AFAILURE: \u001B[39m\u001B[31mBuild failed with an exception. \u001B[39m\u001B[0K +\u001B[0K * Where: Build file 'build.gradle' line: 4 diff --git a/subprojects/internal-integ-testing/src/test/groovy/org/gradle/integtests/fixtures/logging/GroupedOutputFixtureTest.groovy b/subprojects/internal-integ-testing/src/test/groovy/org/gradle/integtests/fixtures/logging/GroupedOutputFixtureTest.groovy index 32e7e65e2ef54..297d2df9815ac 100644 --- a/subprojects/internal-integ-testing/src/test/groovy/org/gradle/integtests/fixtures/logging/GroupedOutputFixtureTest.groovy +++ b/subprojects/internal-integ-testing/src/test/groovy/org/gradle/integtests/fixtures/logging/GroupedOutputFixtureTest.groovy @@ -16,6 +16,7 @@ package org.gradle.integtests.fixtures.logging +import org.gradle.integtests.fixtures.executer.LogContent import spock.lang.Specification class GroupedOutputFixtureTest extends Specification { @@ -44,7 +45,7 @@ Handles lots of newline characters \u001B[2K """ when: - GroupedOutputFixture groupedOutput = new GroupedOutputFixture(consoleOutput) + GroupedOutputFixture groupedOutput = new GroupedOutputFixture(LogContent.of(consoleOutput)) then: groupedOutput.taskCount == 3 @@ -56,21 +57,22 @@ Handles lots of newline characters def "parses incremental tasks"() { given: def consoleOutput = """ -\u001B[2A\u001B[1m<-------------> 0% INITIALIZING [0s]\u001B[m\u001B[36D\u001B[1B\u001B[1m> settings\u001B[m\u001B[10D\u001B[1B\u001B[1A\u001B[90m> IDLE\u001B[39m\u001B[0K\u001B[6D\u001B[1B\u001B[2A\u001B[1m<-------------> 0% CONFIGURING [0s]\u001B[m\u001B[0K\u001B[35D\u001B[2B\u001B[1A\u001B[1m> root project\u001B[m\u001B[14D\u001B[1B\u001B[2A\u001B[1m<-------------> 0% EXECUTING [0s]\u001B[m\u001B[0K\u001B[33D\u001B[1B\u001B[90m> IDLE\u001B[39m\u001B[0K\u001B[6D\u001B[1B\u001B[1A\u001B[1m> :longRunningTask\u001B[m\u001B[6D\u001B[1B\u001B[2A\u001B[1m<-------------> 0% EXECUTING [1s]\u001B[m\u001B[33D\u001B[2B\u001B[2A\u001B[1m<-------------> 0% EXECUTING [2s]\u001B[m\u001B[33D\u001B[2B\u001B[2A\u001B[1m<-------------> 0% EXECUTING [3s]\u001B[m\u001B[33D\u001B[2B\u001B[2A\u001B[1m<-------------> 0% EXECUTING [4s]\u001B[m\u001B[33D\u001B[2B\u001B[2A\u001B[1m<-------------> 0% EXECUTING [5s]\u001B[m\u001B[33D\u001B[2B\u001B[2A\u001B[0K +\u001B[1m<-------------> 0% INITIALIZING [0s]\u001B[m\u001B[36D\u001B[1B\u001B[1m> settings\u001B[m\u001B[10D\u001B[1B\u001B[1A\u001B[90m> IDLE\u001B[39m\u001B[0K\u001B[6D\u001B[1B\u001B[2A\u001B[1m<-------------> 0% CONFIGURING [0s]\u001B[m\u001B[0K\u001B[35D\u001B[2B\u001B[1A\u001B[1m> root project\u001B[m\u001B[14D\u001B[1B\u001B[2A\u001B[1m<-------------> 0% EXECUTING [0s]\u001B[m\u001B[0K\u001B[33D\u001B[1B\u001B[90m> IDLE\u001B[39m\u001B[0K\u001B[6D\u001B[1B\u001B[1A\u001B[1m> :longRunningTask\u001B[m\u001B[18D\u001B[1B\u001B[2A\u001B[1m<-------------> 0% EXECUTING [1s]\u001B[m\u001B[33D\u001B[2B\u001B[2A\u001B[1m<-------------> 0% EXECUTING [2s]\u001B[m\u001B[33D\u001B[2B\u001B[2A\u001B[1m<-------------> 0% EXECUTING [3s]\u001B[m\u001B[33D\u001B[2B\u001B[2A\u001B[1m<-------------> 0% EXECUTING [4s]\u001B[m\u001B[33D\u001B[2B\u001B[2A\u001B[1m<-------------> 0% EXECUTING [5s]\u001B[m\u001B[33D\u001B[2B\u001B[2A\u001B[0K \u001B[1m> Task :longRunningTask\u001B[m\u001B[0K First incremental output \u001B[0K \u001B[0K -\u001B[2A\u001B[1m<-------------> 0% EXECUTING [6s]\u001B[m\u001B[33D\u001B[1B\u001B[1m> :longRunningTask\u001B[m\u001B[6D\u001B[1B\u001B[2A\u001B[1m<-------------> 0% EXECUTING [7s]\u001B[m\u001B[33D\u001B[2B\u001B[2A\u001B[1m<-------------> 0% EXECUTING [8s]\u001B[m\u001B[33D\u001B[2B\u001B[2ASecond incremental output\u001B[0K -\u001B[1B\u001B[0K -\u001B[2A\u001B[1m<-------------> 0% EXECUTING [8s]\u001B[m\u001B[33D\u001B[1B\u001B[1m> :longRunningTask\u001B[m\u001B[6D\u001B[1B\u001B[2A\u001B[0K +\u001B[2A\u001B[1m<-------------> 0% EXECUTING [6s]\u001B[m\u001B[33D\u001B[1B\u001B[1m> :longRunningTask\u001B[m\u001B[18D\u001B[1B\u001B[2A\u001B[1m<-------------> 0% EXECUTING [7s]\u001B[m\u001B[33D\u001B[2B\u001B[2A\u001B[1m<-------------> 0% EXECUTING [8s]\u001B[m\u001B[33D\u001B[2B\u001B[2ASecond incremental output\u001B[0K +\u001B[0K +\u001B[0K +\u001B[1A\u001B[1m<-------------> 0% EXECUTING [8s]\u001B[m\u001B[33D\u001B[1B\u001B[1m> :longRunningTask\u001B[m\u001B[18D\u001B[1B\u001B[2A\u001B[0K \u001B[0K \u001B[32;1mBUILD SUCCESSFUL\u001B[0;39m in 9s 1 actionable task: 1 executed \u001B[2K """ when: - GroupedOutputFixture fixture = new GroupedOutputFixture(consoleOutput) + GroupedOutputFixture fixture = new GroupedOutputFixture(LogContent.of(consoleOutput)) then: fixture.taskCount == 1 @@ -98,7 +100,7 @@ Output from 3 \u001B[2K """ when: - GroupedOutputFixture groupedOutput = new GroupedOutputFixture(consoleOutput) + GroupedOutputFixture groupedOutput = new GroupedOutputFixture(LogContent.of(consoleOutput)) then: groupedOutput.taskCount == 3 @@ -134,7 +136,7 @@ Last line of text """ when: - GroupedOutputFixture groupedOutput = new GroupedOutputFixture(consoleOutput) + GroupedOutputFixture groupedOutput = new GroupedOutputFixture(LogContent.of(consoleOutput)) then: groupedOutput.task(':log').output == 'First line of text\n\n\n\nLast line of text' @@ -155,7 +157,7 @@ Output from 1 \u001B[2K """ when: - GroupedOutputFixture groupedOutput = new GroupedOutputFixture(consoleOutput) + GroupedOutputFixture groupedOutput = new GroupedOutputFixture(LogContent.of(consoleOutput)) then: groupedOutput.task(':1:log').output == "Output from 1" @@ -184,7 +186,7 @@ Output from 2 \u001B[2K """ when: - GroupedOutputFixture groupedOutput = new GroupedOutputFixture(consoleOutput) + GroupedOutputFixture groupedOutput = new GroupedOutputFixture(LogContent.of(consoleOutput)) then: groupedOutput.taskCount == 3 @@ -208,7 +210,7 @@ Output from 2 3 actionable tasks: 3 executed \u001B[2K """ - GroupedOutputFixture groupedOutput = new GroupedOutputFixture(consoleOutput) + GroupedOutputFixture groupedOutput = new GroupedOutputFixture(LogContent.of(consoleOutput)) when: groupedOutput.task(':doesNotExist') @@ -233,7 +235,7 @@ Output from :log \u001B[2K """ when: - GroupedOutputFixture groupedOutput = new GroupedOutputFixture(consoleOutput) + GroupedOutputFixture groupedOutput = new GroupedOutputFixture(LogContent.of(consoleOutput)) then: groupedOutput.task(':log').output == 'Output from :log' @@ -241,29 +243,26 @@ Output from :log def "handles output interleaved with end-of-line erasing"() { given: - def consoleOutput = """\u001B[1A\u001B[1m> Connecting to Daemon\u001B[m\u001B[22D\u001B[1B -\u001B[1A\u001B[90m> IDLE\u001B[39m\u001B[0K\u001B[6D\u001B[1B -\u001B[2A\u001B[1m<-------------> 0% CONFIGURING [0s]\u001B[m\u001B[35D\u001B[1B\u001B[1m> root project\u001B[m\u001B[14D\u001B[1B -\u001B[1A\u001B[1m> root project > Compiling /home/tcagent2/agent/work/1c72cb73edd79150/subprojects/logging/build/tmp/test files/BasicGroupedTaskLoggingFunctionalSpec/long_running_task_o..._5s_delay/m5mh7/build.gradle into local compilation cache\u001B[m\u001B[228D\u001B[1B -\u001B[2A\u001B[1m<-------------> 0% CONFIGURING [1s]\u001B[m\u001B[35D\u001B[2B -\u001B[2A\u001B[1m<-------------> 0% EXECUTING [1s]\u001B[m\u001B[0K\u001B[33D\u001B[1B\u001B[1m> :log\u001B[m\u001B[0K\u001B[6D\u001B[1B -\u001B[2A\u001B[1m<-------------> 0% EXECUTING [2s]\u001B[m\u001B[33D\u001B[2B -\u001B[2A\u001B[1m<-------------> 0% EXECUTING [3s]\u001B[m\u001B[33D\u001B[2B -\u001B[2A\u001B[1m<-------------> 0% EXECUTING [4s]\u001B[m\u001B[33D\u001B[2B -\u001B[2A\u001B[1m<-------------> 0% EXECUTING [5s]\u001B[m\u001B[33D\u001B[2B -\u001B[2A\u001B[0K -\u001B[1B\u001B[0K -\u001B[2A\u001B[1m<-------------> 0% EXECUTING [6s]\u001B[m\u001B[33D\u001B[1B\u001B[1m> :log\u001B[m\u001B[6D\u001B[1B + def consoleOutput = """\u001B[1A\u001B[1m> Connecting to Daemon\u001B[m\u001B[22D +\u001B[1A\u001B[90m> IDLE\u001B[39m\u001B[0K\u001B[6D +\u001B[1A\u001B[1m<-------------> 0% CONFIGURING [0s]\u001B[m\u001B[35D\u001B[1B\u001B[1m> root project\u001B[m\u001B[14D +\u001B[1A\u001B[1m> root project > Compiling /home/tcagent2/agent/work/1c72cb73edd79150/subprojects/logging/build/tmp/test files/BasicGroupedTaskLoggingFunctionalSpec/long_running_task_o..._5s_delay/m5mh7/build.gradle into local compilation cache\u001B[m\u001B[228D +\u001B[2A\u001B[1m<-------------> 0% CONFIGURING [1s]\u001B[m\u001B[35D\u001B[1B +\u001B[2A\u001B[1m<-------------> 0% EXECUTING [1s]\u001B[m\u001B[0K\u001B[33D\u001B[1B\u001B[1m> :log\u001B[m\u001B[0K\u001B[6D +\u001B[2A\u001B[1m<-------------> 0% EXECUTING [2s]\u001B[m\u001B[33D\u001B[1B +\u001B[2A\u001B[1m<-------------> 0% EXECUTING [3s]\u001B[m\u001B[33D\u001B[1B +\u001B[2A\u001B[1m<-------------> 0% EXECUTING [4s]\u001B[m\u001B[33D\u001B[1B \u001B[2A\u001B[1m> Task :log\u001B[m\u001B[0K Before\u001B[0K \u001B[0K \u001B[0K -\u001B[2A\u001B[1m<-------------> 0% EXECUTING [6s]\u001B[m\u001B[33D\u001B[1B\u001B[1m> :log\u001B[m\u001B[6D\u001B[1B -\u001B[2A\u001B[1m<-------------> 0% EXECUTING [7s]\u001B[m\u001B[33D\u001B[2B -\u001B[2A\u001B[1m<-------------> 0% EXECUTING [8s]\u001B[m\u001B[33D\u001B[2B +\u001B[2A\u001B[1m<-------------> 0% EXECUTING [6s]\u001B[m\u001B[33D\u001B[1B\u001B[1m> :log\u001B[m\u001B[6D +\u001B[2A\u001B[1m<-------------> 0% EXECUTING [7s]\u001B[m\u001B[33D\u001B[1B +\u001B[2A\u001B[1m<-------------> 0% EXECUTING [8s]\u001B[m\u001B[33D\u001B[1B \u001B[2AAfter\u001B[0K -\u001B[1B\u001B[0K -\u001B[2A\u001B[1m<-------------> 0% EXECUTING [8s]\u001B[m\u001B[33D\u001B[1B\u001B[1m> :log\u001B[m\u001B[6D\u001B[1B +\u001B[0K +\u001B[0K +\u001B[2A\u001B[1m<-------------> 0% EXECUTING [8s]\u001B[m\u001B[33D\u001B[1B\u001B[1m> :log\u001B[m\u001B[6D \u001B[2A\u001B[0K \u001B[0K \u001B[32;1mBUILD SUCCESSFUL\u001B[0;39m in 9s @@ -271,7 +270,7 @@ Before\u001B[0K \u001B[2K""" when: - GroupedOutputFixture groupedOutput = new GroupedOutputFixture(consoleOutput) + GroupedOutputFixture groupedOutput = new GroupedOutputFixture(LogContent.of(consoleOutput)) then: groupedOutput.task(':log').output == 'Before\nAfter' @@ -294,7 +293,7 @@ Bye world \u001B[2K""" when: - GroupedOutputFixture groupedOutput = new GroupedOutputFixture(consoleOutput) + GroupedOutputFixture groupedOutput = new GroupedOutputFixture(LogContent.of(consoleOutput)) then: groupedOutput.task(':buildSrc:helloWorld').output == 'Hello world' @@ -316,15 +315,13 @@ Bye world \u001B[2K""" when: - GroupedOutputFixture groupedOutput = new GroupedOutputFixture(consoleOutput) + GroupedOutputFixture groupedOutput = new GroupedOutputFixture(LogContent.of(consoleOutput)) then: groupedOutput.strippedOutput == ''' > Task :buildSrc:helloWorld Hello world - - > Task :byeWorld Bye world @@ -336,17 +333,17 @@ BUILD SUCCESSFUL in 0s def "strip output removes formatted work in-progress items"() { def consoleOutput = """ -\u001B[2A\u001B[1m<-------------> 0% INITIALIZING [0s]\u001B[m\u001B[36D\u001B[1B\u001B[1m> settings\u001B[m\u001B[10D\u001B[1B -\u001B[1A> IDLE\u001B[0K\u001B[6D\u001B[1B -\u001B[2A\u001B[1m<-------------> 0% CONFIGURING [1s]\u001B[m\u001B[0K\u001B[35D\u001B[1B\u001B[1m> root project\u001B[m\u001B[14D\u001B[1B -\u001B[2A\u001B[1m<-------------> 0% EXECUTING [2s]\u001B[m\u001B[0K\u001B[33D\u001B[1B> IDLE\u001B[0K\u001B[6D\u001B[1B -\u001B[1A\u001B[1m> :run\u001B[m\u001B[6D\u001B[1B +\u001B[2A\u001B[1m<-------------> 0% INITIALIZING [0s]\u001B[m\u001B[36D\u001B[1B\u001B[1m> settings\u001B[m\u001B[10D +\u001B[1A> IDLE\u001B[0K\u001B[6D +\u001B[2A\u001B[1m<-------------> 0% CONFIGURING [1s]\u001B[m\u001B[0K\u001B[35D\u001B[1B\u001B[1m> root project\u001B[m\u001B[14D +\u001B[2A\u001B[1m<-------------> 0% EXECUTING [2s]\u001B[m\u001B[0K\u001B[33D\u001B[1B> IDLE\u001B[0K\u001B[6D +\u001B[1A\u001B[1m> :run\u001B[m\u001B[6D \u001B[2A\u001B[0K \u001B[1m> Task :run\u001B[m\u001B[0K Hello, World! \u001B[0K \u001B[0K -\u001B[2A\u001B[1m<=============> 100% EXECUTING [3s]\u001B[m\u001B[35D\u001B[1B> IDLE\u001B[6D\u001B[1B +\u001B[2A\u001B[1m<=============> 100% EXECUTING [3s]\u001B[m\u001B[35D\u001B[1B> IDLE\u001B[6D \u001B[2A\u001B[0K \u001B[0K \u001B[32;1mBUILD SUCCESSFUL\u001B[0;39m in 6s @@ -354,11 +351,10 @@ Hello, World! \u001B[2K""" when: - GroupedOutputFixture groupedOutput = new GroupedOutputFixture(consoleOutput) + GroupedOutputFixture groupedOutput = new GroupedOutputFixture(LogContent.of(consoleOutput)) then: groupedOutput.strippedOutput == ''' - > Task :run Hello, World! @@ -377,7 +373,7 @@ Hello, World! > :otherBuild > :abc""" when: - GroupedOutputFixture groupedOutput = new GroupedOutputFixture(consoleOutput) + GroupedOutputFixture groupedOutput = new GroupedOutputFixture(LogContent.of(consoleOutput)) then: groupedOutput.task(':helloWorld').output == 'Hello, World!' @@ -391,7 +387,7 @@ Hello, World! > :otherBuild > Doing some work""" when: - GroupedOutputFixture groupedOutput = new GroupedOutputFixture(consoleOutput) + GroupedOutputFixture groupedOutput = new GroupedOutputFixture(LogContent.of(consoleOutput)) then: groupedOutput.task(':helloWorld').output == 'Hello, World!' @@ -406,7 +402,7 @@ Hello, World! [3A [1m< [0;32;1;0;39;1m-------------> 0% CONFIGURING [5s] [m [35D [1B [1m> root project > Compiling C:\\tcagent1\\work\\4b92f910977a653d\\subprojects\\logging\\build\\tmp\\test files\\ConsoleBuildSrcFunctionalTest\\can_group_task_outp..._buildSrc\\j2q4s\\build.gradle into local compilation cache > Compiling build file 'C:\\tcagent1\\work\\4b92f910977a653d\\subprojects\\logging\\build\\tmp\\test files\\ConsoleBuildSrcFunctionalTest\\can_group_task_outp..._buildSrc\\j2q4s\\build.gradle' to cross build script cache [m [420D [2B """ when: - new GroupedOutputFixture(consoleOutput) + new GroupedOutputFixture(LogContent.of(consoleOutput)) then: noExceptionThrown() diff --git a/subprojects/kotlin-dsl-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPluginAccessorsTest.kt b/subprojects/kotlin-dsl-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPluginAccessorsTest.kt index d0d21645cd009..14be37be530ba 100644 --- a/subprojects/kotlin-dsl-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPluginAccessorsTest.kt +++ b/subprojects/kotlin-dsl-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPluginAccessorsTest.kt @@ -373,8 +373,8 @@ class PrecompiledScriptPluginAccessorsTest : AbstractPrecompiledScriptPluginTest withPrecompiledScriptApplying(pluginId, pluginJar) gradleExecuterFor(arrayOf("classes")).withStackTraceChecksDisabled().run().apply { - assertRawOutputContains("An exception occurred applying plugin request [id: '$pluginId']") - assertRawOutputContains("'InvalidPlugin' is neither a plugin or a rule source and cannot be applied.") + assertOutputContains("An exception occurred applying plugin request [id: '$pluginId']") + assertOutputContains("'InvalidPlugin' is neither a plugin or a rule source and cannot be applied.") } } diff --git a/subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/AbstractConsoleBuildPhaseFunctionalTest.groovy b/subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/AbstractConsoleBuildPhaseFunctionalTest.groovy index 3b36307d5a9a7..a598b935d11ee 100644 --- a/subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/AbstractConsoleBuildPhaseFunctionalTest.groovy +++ b/subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/AbstractConsoleBuildPhaseFunctionalTest.groovy @@ -129,7 +129,7 @@ abstract class AbstractConsoleBuildPhaseFunctionalTest extends AbstractIntegrati gradle.waitForFinish() where: - attachment << [ConsoleAttachment.ATTACHED, ConsoleAttachment.ATTACHED_STDOUT_ONLY] + attachment << [ConsoleAttachment.ATTACHED, ConsoleAttachment.ATTACHED_STDOUT_ONLY, ConsoleAttachment.NOT_ATTACHED] } @Unroll @@ -217,7 +217,7 @@ abstract class AbstractConsoleBuildPhaseFunctionalTest extends AbstractIntegrati gradle.waitForFinish() where: - attachment << [ConsoleAttachment.ATTACHED, ConsoleAttachment.ATTACHED_STDOUT_ONLY] + attachment << [ConsoleAttachment.ATTACHED, ConsoleAttachment.ATTACHED_STDOUT_ONLY, ConsoleAttachment.NOT_ATTACHED] } @Unroll @@ -312,7 +312,7 @@ abstract class AbstractConsoleBuildPhaseFunctionalTest extends AbstractIntegrati gradle.waitForFinish() where: - attachment << [ConsoleAttachment.ATTACHED, ConsoleAttachment.ATTACHED_STDOUT_ONLY] + attachment << [ConsoleAttachment.ATTACHED, ConsoleAttachment.ATTACHED_STDOUT_ONLY, ConsoleAttachment.NOT_ATTACHED] } @Unroll @@ -451,12 +451,13 @@ abstract class AbstractConsoleBuildPhaseFunctionalTest extends AbstractIntegrati gradle.waitForFinish() where: - attachment << [ConsoleAttachment.ATTACHED, ConsoleAttachment.ATTACHED_STDOUT_ONLY] + attachment << [ConsoleAttachment.ATTACHED, ConsoleAttachment.ATTACHED_STDOUT_ONLY, ConsoleAttachment.NOT_ATTACHED] } @Unroll def "does not show progress bar when stdout is #attachment"() { when: + executer.withTestConsoleAttached(attachment) succeeds() then: @@ -465,7 +466,7 @@ abstract class AbstractConsoleBuildPhaseFunctionalTest extends AbstractIntegrati result.assertNotOutput("EXECUTING") where: - attachment << [ConsoleAttachment.ATTACHED_STDERR_ONLY, ConsoleAttachment.NOT_ATTACHED] + attachment << [ConsoleAttachment.ATTACHED_STDERR_ONLY] } void assertHasBuildPhase(String message) { diff --git a/subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/taskgrouping/AbstractConsoleBuildResultFunctionalTest.groovy b/subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/taskgrouping/AbstractConsoleBuildResultFunctionalTest.groovy index b5a0cba2fc5a9..eabc05ee88651 100644 --- a/subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/taskgrouping/AbstractConsoleBuildResultFunctionalTest.groovy +++ b/subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/taskgrouping/AbstractConsoleBuildResultFunctionalTest.groovy @@ -25,8 +25,8 @@ import spock.lang.Unroll abstract class AbstractConsoleBuildResultFunctionalTest extends AbstractConsoleGroupedTaskFunctionalTest { protected final String buildFailed = 'BUILD FAILED' protected final String buildSuccess = 'BUILD SUCCESSFUL' - protected final StyledOutput buildFailedStyled = styled(buildFailed, Ansi.Color.RED, Ansi.Attribute.INTENSITY_BOLD) - protected final StyledOutput buildSuccessStyled = styled(buildSuccess, Ansi.Color.GREEN, Ansi.Attribute.INTENSITY_BOLD) + protected final StyledOutput buildFailedStyled = styled(Ansi.Color.RED, Ansi.Attribute.INTENSITY_BOLD).text(buildFailed).off() + protected final StyledOutput buildSuccessStyled = styled(Ansi.Color.GREEN, Ansi.Attribute.INTENSITY_BOLD).text(buildSuccess).off() abstract String getFailureMessage() @@ -50,9 +50,9 @@ abstract class AbstractConsoleBuildResultFunctionalTest extends AbstractConsoleG succeeds('all') then: - result.assertRawOutputContains(successMessage) - LogContent.of(result.output).removeAnsiChars().withNormalizedEol().matches """(?s).* -BUILD SUCCESSFUL in \\d+s\\n* + LogContent.of(result.output).ansiCharsToColorText().withNormalizedEol().contains(successMessage) + LogContent.of(result.output).ansiCharsToPlainText().withNormalizedEol().matches """(?s).* +BUILD SUCCESSFUL in \\d+s 2 actionable tasks: 2 executed .*""" @@ -60,9 +60,9 @@ BUILD SUCCESSFUL in \\d+s\\n* succeeds('all') then: - result.assertRawOutputContains(successMessage) - LogContent.of(result.output).removeAnsiChars().withNormalizedEol().matches """(?s).* -BUILD SUCCESSFUL in \\d+s\\n* + LogContent.of(result.output).ansiCharsToColorText().withNormalizedEol().contains(successMessage) + LogContent.of(result.output).ansiCharsToPlainText().withNormalizedEol().matches """(?s).* +BUILD SUCCESSFUL in \\d+s 2 actionable tasks: 1 executed, 1 up-to-date .*""" } @@ -95,8 +95,9 @@ BUILD SUCCESSFUL in \\d+s\\n* succeeds('success') then: - LogContent.of(result.output).removeAnsiChars().withNormalizedEol().matches """(?s).*build finished\\n* -BUILD SUCCESSFUL in \\d+s\\n* + LogContent.of(result.output).ansiCharsToPlainText().withNormalizedEol().matches """(?s).*build finished + +BUILD SUCCESSFUL in \\d+s 1 actionable task: 1 executed .*""" } @@ -123,9 +124,9 @@ BUILD SUCCESSFUL in \\d+s\\n* // Check that the failure text appears either stdout or stderr def outputWithFailure = errorsShouldAppearOnStdout() ? failure.output : failure.error def outputWithoutFailure = errorsShouldAppearOnStdout() ? failure.error : failure.output - def outputWithFailureAndNoDebugging = LogContent.of(outputWithFailure).removeAnsiChars().removeDebugPrefix().withNormalizedEol() + def outputWithFailureAndNoDebugging = LogContent.of(outputWithFailure).ansiCharsToColorText().removeDebugPrefix().withNormalizedEol() - outputWithFailure.contains("Build failed with an exception.") + outputWithFailureAndNoDebugging.contains("FAILURE: Build failed with an exception.") outputWithFailureAndNoDebugging.contains(""" * What went wrong: Execution failed for task ':broken'. @@ -134,8 +135,7 @@ BUILD SUCCESSFUL in \\d+s\\n* !outputWithoutFailure.contains("Build failed with an exception.") !outputWithoutFailure.contains("* What went wrong:") - outputWithFailure.contains("BUILD FAILED") - failure.assertHasRawErrorOutput(failureMessage) + outputWithFailureAndNoDebugging.contains(failureMessage) where: level << [LogLevel.DEBUG, LogLevel.INFO, LogLevel.LIFECYCLE, LogLevel.WARN, LogLevel.QUIET] @@ -156,7 +156,7 @@ BUILD SUCCESSFUL in \\d+s\\n* fails("broken") and: - result.assertRawOutputContains("1 actionable task: 1 executed") + LogContent.of(result.output).ansiCharsToPlainText().withNormalizedEol().contains("1 actionable task: 1 executed") where: level << [LogLevel.DEBUG, LogLevel.INFO, LogLevel.LIFECYCLE] diff --git a/subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/taskgrouping/AbstractGroupedProjectConfigureLoggingFunctionalTest.groovy b/subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/taskgrouping/AbstractGroupedProjectConfigureLoggingFunctionalTest.groovy index 150f212319d0b..b171e13c6be77 100644 --- a/subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/taskgrouping/AbstractGroupedProjectConfigureLoggingFunctionalTest.groovy +++ b/subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/taskgrouping/AbstractGroupedProjectConfigureLoggingFunctionalTest.groovy @@ -47,7 +47,7 @@ abstract class AbstractGroupedProjectConfigureLoggingFunctionalTest extends Abst run() then: - def normalizedOutput = LogContent.of(result.output).removeAnsiChars().withNormalizedEol() + def normalizedOutput = LogContent.of(result.output).ansiCharsToPlainText().withNormalizedEol() normalizedOutput.contains(""" > Configure project : root project diff --git a/subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/taskgrouping/rich/RichConsoleBasicGroupedTaskLoggingFunctionalTest.groovy b/subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/taskgrouping/rich/RichConsoleBasicGroupedTaskLoggingFunctionalTest.groovy index 6be503ede6ca8..679fc2fedb463 100644 --- a/subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/taskgrouping/rich/RichConsoleBasicGroupedTaskLoggingFunctionalTest.groovy +++ b/subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/taskgrouping/rich/RichConsoleBasicGroupedTaskLoggingFunctionalTest.groovy @@ -19,6 +19,7 @@ package org.gradle.internal.logging.console.taskgrouping.rich import org.fusesource.jansi.Ansi import org.gradle.api.logging.configuration.ConsoleOutput import org.gradle.integtests.fixtures.console.AbstractConsoleGroupedTaskFunctionalTest.StyledOutput +import org.gradle.integtests.fixtures.executer.LogContent import org.gradle.internal.logging.console.taskgrouping.AbstractBasicGroupedTaskLoggingFunctionalTest import spock.lang.Issue @@ -26,9 +27,9 @@ import spock.lang.Issue class RichConsoleBasicGroupedTaskLoggingFunctionalTest extends AbstractBasicGroupedTaskLoggingFunctionalTest { ConsoleOutput consoleType = ConsoleOutput.Rich - private final StyledOutput failingTask = styled("> Task :failing", Ansi.Color.RED, Ansi.Attribute.INTENSITY_BOLD) - private final StyledOutput succeedingTask = styled("> Task :succeeding", null, Ansi.Attribute.INTENSITY_BOLD) - private final StyledOutput configuringProject = styled("> Configure project :", Ansi.Color.RED, Ansi.Attribute.INTENSITY_BOLD) + private final StyledOutput failingTask = styled(Ansi.Color.RED, Ansi.Attribute.INTENSITY_BOLD).text("> Task :failing").styled(null).text(" FAILED").off() + private final StyledOutput succeedingTask = styled(Ansi.Attribute.INTENSITY_BOLD).text("> Task :succeeding").off() + private final StyledOutput configuringProject = styled(Ansi.Color.RED, Ansi.Attribute.INTENSITY_BOLD).text("> Configure project :").off() @Issue("gradle/gradle#2038") def "tasks with no actions are not displayed"() { @@ -56,7 +57,7 @@ class RichConsoleBasicGroupedTaskLoggingFunctionalTest extends AbstractBasicGrou then: result.groupedOutput.task(':failing').output == 'hello' - result.assertRawOutputContains(failingTask.output) + LogContent.of(result.output).ansiCharsToColorText().withNormalizedEol().contains(failingTask.output) } def "group header is printed red if task failed and there is no output"() { @@ -71,7 +72,7 @@ class RichConsoleBasicGroupedTaskLoggingFunctionalTest extends AbstractBasicGrou fails('failing') then: - result.assertRawOutputContains(failingTask.output) + LogContent.of(result.output).ansiCharsToColorText().withNormalizedEol().contains(failingTask.output) } def "group header is printed white if task succeeds"() { @@ -86,7 +87,7 @@ class RichConsoleBasicGroupedTaskLoggingFunctionalTest extends AbstractBasicGrou succeeds('succeeding') then: - result.assertRawOutputContains(succeedingTask.output) + LogContent.of(result.output).ansiCharsToColorText().withNormalizedEol().contains(succeedingTask.output) } def "configure project group header is printed red if configuration fails with additional failures"() { @@ -104,7 +105,7 @@ class RichConsoleBasicGroupedTaskLoggingFunctionalTest extends AbstractBasicGrou fails('failing') then: - result.assertRawOutputContains(configuringProject.output) + LogContent.of(result.output).ansiCharsToColorText().withNormalizedEol().contains(configuringProject.output) } def "tasks that complete without output do not break up other task output"() { diff --git a/subprojects/logging/src/main/java/org/gradle/internal/logging/sink/ConsoleConfigureAction.java b/subprojects/logging/src/main/java/org/gradle/internal/logging/sink/ConsoleConfigureAction.java index 766a6f2119fdb..1b7229993bc40 100644 --- a/subprojects/logging/src/main/java/org/gradle/internal/logging/sink/ConsoleConfigureAction.java +++ b/subprojects/logging/src/main/java/org/gradle/internal/logging/sink/ConsoleConfigureAction.java @@ -25,78 +25,65 @@ import org.gradle.internal.nativeintegration.console.TestConsoleMetadata; import org.gradle.internal.nativeintegration.services.NativeServices; -import javax.annotation.Nullable; import java.io.OutputStream; import java.io.OutputStreamWriter; public class ConsoleConfigureAction { public static void execute(OutputEventRenderer renderer, ConsoleOutput consoleOutput) { + execute(renderer, consoleOutput, getConsoleMetaData(), renderer.getOriginalStdOut(), renderer.getOriginalStdErr()); + } + + public static void execute(OutputEventRenderer renderer, ConsoleOutput consoleOutput, ConsoleMetaData consoleMetadata, OutputStream stdout, OutputStream stderr) { if (consoleOutput == ConsoleOutput.Auto) { - configureAutoConsole(renderer); + configureAutoConsole(renderer, consoleMetadata, stdout, stderr); } else if (consoleOutput == ConsoleOutput.Rich) { - configureRichConsole(renderer, false); + configureRichConsole(renderer, consoleMetadata, stdout, stderr, false); } else if (consoleOutput == ConsoleOutput.Verbose) { - configureRichConsole(renderer, true); + configureRichConsole(renderer, consoleMetadata, stdout, stderr, true); } else if (consoleOutput == ConsoleOutput.Plain) { - configurePlainConsole(renderer); - } - } - - private static void configureRichConsole(OutputEventRenderer renderer, boolean verbose) { - ConsoleMetaData consoleMetaData = getConsoleMetaData(); - configureRichConsole(renderer, consoleMetaData, shouldForce(consoleMetaData), verbose); - } - - private static boolean shouldForce(ConsoleMetaData consoleMetaData) { - return consoleMetaData == null || consoleMetaData instanceof TestConsoleMetadata; - } - - private static void configureAutoConsole(OutputEventRenderer renderer) { - ConsoleMetaData consoleMetaData = getConsoleMetaData(); - if (consoleMetaData != null) { - configureRichConsole(renderer, consoleMetaData, false, false); - } else { - configurePlainConsole(renderer, null); + configurePlainConsole(renderer, consoleMetadata, stdout, stderr); } } - private static void configurePlainConsole(OutputEventRenderer renderer) { - ConsoleMetaData consoleMetaData = getConsoleMetaData(); - configurePlainConsole(renderer, consoleMetaData); - } - - @Nullable private static ConsoleMetaData getConsoleMetaData() { String testConsole = System.getProperty(TestConsoleMetadata.TEST_CONSOLE_PROPERTY); if (testConsole != null) { return TestConsoleMetadata.valueOf(testConsole); } ConsoleDetector consoleDetector = NativeServices.getInstance().get(ConsoleDetector.class); - return consoleDetector.getConsole(); + ConsoleMetaData metaData = consoleDetector.getConsole(); + if (metaData != null) { + return metaData; + } + return FallbackConsoleMetaData.NOT_ATTACHED; + } + + private static void configureAutoConsole(OutputEventRenderer renderer, ConsoleMetaData consoleMetaData, OutputStream stdout, OutputStream stderr) { + if (consoleMetaData.isStdOut() || consoleMetaData.isStdErr()) { + configureRichConsole(renderer, consoleMetaData, stdout, stderr, false); + } else { + configurePlainConsole(renderer, consoleMetaData, stdout, stderr); + } } - private static void configurePlainConsole(OutputEventRenderer renderer, ConsoleMetaData consoleMetaData) { + private static void configurePlainConsole(OutputEventRenderer renderer, ConsoleMetaData consoleMetaData, OutputStream stdout, OutputStream stderr) { // Redirect stderr to stdout if a console is attached to both stdout and stderr - renderer.addPlainConsole(consoleMetaData != null && consoleMetaData.isStdOut() && consoleMetaData.isStdErr()); + // This avoids interleaving problems when stdout and stderr end up at the same location + renderer.addPlainConsole(stdout, stderr, consoleMetaData != null && consoleMetaData.isStdOut() && consoleMetaData.isStdErr()); } - private static void configureRichConsole(OutputEventRenderer renderer, @Nullable ConsoleMetaData consoleMetaData, boolean force, boolean verbose) { - if (consoleMetaData == null) { - consoleMetaData = FallbackConsoleMetaData.ATTACHED; - } - if (consoleMetaData.isStdOut()) { - OutputStream originalStdOut = renderer.getOriginalStdOut(); - OutputStreamWriter outStr = new OutputStreamWriter(force ? originalStdOut : AnsiConsoleUtil.wrapOutputStream(originalStdOut)); - Console console = new AnsiConsole(outStr, outStr, renderer.getColourMap(), consoleMetaData, force); - renderer.addRichConsole(console, consoleMetaData, verbose); - } else if (consoleMetaData.isStdErr()) { - // Only stderr is connected to a terminal - OutputStream originalStdErr = renderer.getOriginalStdErr(); - OutputStreamWriter errStr = new OutputStreamWriter(force ? originalStdErr : AnsiConsoleUtil.wrapOutputStream(originalStdErr)); + private static void configureRichConsole(OutputEventRenderer renderer, ConsoleMetaData consoleMetaData, OutputStream stdout, OutputStream stderr, boolean verbose) { + boolean force = !consoleMetaData.isWrapStreams(); + if (consoleMetaData.isStdErr() && !consoleMetaData.isStdOut()) { + // Only stderr is connected to a console. Currently we can write rich text to one stream only, so prefer stderr in this case + OutputStreamWriter errStr = new OutputStreamWriter(force ? stderr : AnsiConsoleUtil.wrapOutputStream(stderr)); Console console = new AnsiConsole(errStr, errStr, renderer.getColourMap(), consoleMetaData, force); - renderer.addRichConsole(console, consoleMetaData, verbose); + renderer.addRichConsole(console, consoleMetaData, stdout, stderr, verbose); } else { - renderer.addRichConsole(null, consoleMetaData, verbose); + // Prefer stdout when is connected to a console or neither stream connected to a console + OutputStreamWriter outStr = new OutputStreamWriter(force ? stdout : AnsiConsoleUtil.wrapOutputStream(stdout)); + Console console = new AnsiConsole(outStr, outStr, renderer.getColourMap(), consoleMetaData, force); + renderer.addRichConsole(console, consoleMetaData, stdout, stderr, verbose); } } } diff --git a/subprojects/logging/src/main/java/org/gradle/internal/logging/sink/OutputEventRenderer.java b/subprojects/logging/src/main/java/org/gradle/internal/logging/sink/OutputEventRenderer.java index 4be5ecf128ac3..3310aa010a1d6 100644 --- a/subprojects/logging/src/main/java/org/gradle/internal/logging/sink/OutputEventRenderer.java +++ b/subprojects/logging/src/main/java/org/gradle/internal/logging/sink/OutputEventRenderer.java @@ -23,7 +23,6 @@ import org.gradle.internal.Factory; import org.gradle.internal.event.ListenerBroadcast; import org.gradle.internal.logging.config.LoggingRouter; -import org.gradle.internal.logging.console.AnsiConsole; import org.gradle.internal.logging.console.BuildLogLevelFilterRenderer; import org.gradle.internal.logging.console.BuildStatusRenderer; import org.gradle.internal.logging.console.ColorMap; @@ -55,7 +54,6 @@ import javax.annotation.Nullable; import java.io.OutputStream; -import java.io.OutputStreamWriter; import java.util.concurrent.atomic.AtomicReference; /** @@ -159,25 +157,9 @@ public void attachConsole(OutputStream outputStream, OutputStream errorStream, C public void attachConsole(OutputStream outputStream, OutputStream errorStream, ConsoleOutput consoleOutput, @Nullable ConsoleMetaData consoleMetadata) { synchronized (lock) { if (consoleMetadata == null) { - consoleMetadata = consoleOutput == ConsoleOutput.Plain ? FallbackConsoleMetaData.NOT_ATTACHED : FallbackConsoleMetaData.ATTACHED; - } - StandardOutputListener outputListener = new StreamBackedStandardOutputListener(outputStream); - StandardOutputListener errorListener = new StreamBackedStandardOutputListener(errorStream); - if (consoleOutput == ConsoleOutput.Plain) { - addPlainConsole(outputListener, errorListener, consoleMetadata.isStdOut() && consoleMetadata.isStdErr()); - } else { - Console console; - if (consoleMetadata.isStdOut()) { - OutputStreamWriter writer = new OutputStreamWriter(outputStream); - console = new AnsiConsole(writer, writer, getColourMap(), consoleMetadata, true); - } else if (consoleMetadata.isStdErr()) { - OutputStreamWriter writer = new OutputStreamWriter(errorStream); - console = new AnsiConsole(writer, writer, getColourMap(), consoleMetadata, true); - } else { - console = null; - } - addRichConsole(console, outputListener, errorListener, consoleMetadata, consoleOutput == ConsoleOutput.Verbose); + consoleMetadata = FallbackConsoleMetaData.NOT_ATTACHED; } + ConsoleConfigureAction.execute(this, consoleOutput, consoleMetadata, outputStream, errorStream); } } @@ -248,31 +230,24 @@ public void removeOutputEventListener(OutputEventListener listener) { } } - public OutputEventRenderer addRichConsole(Console console, ConsoleMetaData consoleMetaData) { - return addRichConsole(console, consoleMetaData, false); - } - - public OutputEventRenderer addRichConsole(Console console, ConsoleMetaData consoleMetaData, boolean verbose) { - return addRichConsole(console, new StreamBackedStandardOutputListener((Appendable) originalStdOut), new StreamBackedStandardOutputListener((Appendable) originalStdErr), consoleMetaData, verbose); - } - - private OutputEventRenderer addRichConsole(Console console, StandardOutputListener outputListener, StandardOutputListener errorListener, ConsoleMetaData consoleMetaData, boolean verbose) { + public OutputEventRenderer addRichConsole(Console console, ConsoleMetaData consoleMetaData, OutputStream stdout, OutputStream stderr, boolean verbose) { OutputEventListener consoleChain; boolean stdoutAttachedToConsole = consoleMetaData.isStdOut(); boolean stderrAttachedToConsole = consoleMetaData.isStdErr(); + StandardOutputListener outputListener = new StreamBackedStandardOutputListener(stdout); + StandardOutputListener errorListener = new StreamBackedStandardOutputListener(stderr); if (stdoutAttachedToConsole && stderrAttachedToConsole) { OutputEventListener consoleListener = new StyledTextOutputBackedRenderer(console.getBuildOutputArea()); consoleChain = getRichConsoleChain(console, consoleMetaData, verbose, consoleListener); - } else if (stdoutAttachedToConsole) { - OutputEventListener stderrChain = new StyledTextOutputBackedRenderer(new StreamingStyledTextOutput(errorListener)); - OutputEventListener consoleListener = new ErrorOutputDispatchingListener(stderrChain, new StyledTextOutputBackedRenderer(console.getBuildOutputArea()), false); - consoleChain = getRichConsoleChain(console, consoleMetaData, verbose, consoleListener); } else if (stderrAttachedToConsole) { OutputEventListener stdoutChain = new StyledTextOutputBackedRenderer(new StreamingStyledTextOutput(outputListener)); OutputEventListener stderrChain = new FlushConsoleListener(console, new StyledTextOutputBackedRenderer(console.getBuildOutputArea())); consoleChain = getPlainConsoleChain(stdoutChain, stderrChain, false, verbose); } else { - consoleChain = getPlainConsoleChain(outputListener, errorListener, false, verbose); + OutputEventListener stdoutChain = new StyledTextOutputBackedRenderer(console.getBuildOutputArea()); + OutputEventListener stderrChain = new StyledTextOutputBackedRenderer(new StreamingStyledTextOutput(errorListener)); + OutputEventListener consoleListener = new ErrorOutputDispatchingListener(stderrChain, stdoutChain, false); + consoleChain = getRichConsoleChain(console, consoleMetaData, verbose, consoleListener); } return addConsoleChain(consoleChain); @@ -295,12 +270,8 @@ private OutputEventListener getRichConsoleChain(Console console, ConsoleMetaData ); } - public OutputEventRenderer addPlainConsole(boolean redirectStderr) { - return addPlainConsole(new StreamBackedStandardOutputListener((Appendable) originalStdOut), new StreamBackedStandardOutputListener((Appendable) originalStdErr), redirectStderr); - } - - private OutputEventRenderer addPlainConsole(StandardOutputListener outputListener, StandardOutputListener errorListener, boolean redirectStderr) { - return addConsoleChain(getPlainConsoleChain(outputListener, errorListener, redirectStderr, true)); + public OutputEventRenderer addPlainConsole(OutputStream stdout, OutputStream stderr, boolean redirectStderr) { + return addConsoleChain(getPlainConsoleChain(new StreamBackedStandardOutputListener(stdout), new StreamBackedStandardOutputListener(stderr), redirectStderr, true)); } private OutputEventListener getPlainConsoleChain(StandardOutputListener outputListener, StandardOutputListener errorListener, boolean redirectStderr, boolean verbose) { diff --git a/subprojects/logging/src/test/groovy/org/gradle/internal/logging/sink/OutputEventRendererTest.groovy b/subprojects/logging/src/test/groovy/org/gradle/internal/logging/sink/OutputEventRendererTest.groovy index 4a1538fa375cb..76b88f0f7981d 100644 --- a/subprojects/logging/src/test/groovy/org/gradle/internal/logging/sink/OutputEventRendererTest.groovy +++ b/subprojects/logging/src/test/groovy/org/gradle/internal/logging/sink/OutputEventRendererTest.groovy @@ -288,7 +288,7 @@ class OutputEventRendererTest extends OutputSpecification { def snapshot = renderer.snapshot() metaData.stdOut >> true metaData.stdErr >> true - renderer.addRichConsole(console, metaData) + renderer.addRichConsole(console, metaData, outputs.stdOutPrintStream, outputs.stdErrPrintStream, false) when: renderer.onOutput(start(description: 'description', buildOperationStart: true, id: 1L, buildOperationId: 1L, buildOperationCategory: BuildOperationCategory.TASK)) @@ -306,7 +306,7 @@ class OutputEventRendererTest extends OutputSpecification { metaData.stdOut >> true metaData.stdErr >> false renderer.attachSystemOutAndErr() - renderer.addRichConsole(console, metaData) + renderer.addRichConsole(console, metaData, outputs.stdOutPrintStream, outputs.stdErrPrintStream, false) when: renderer.onOutput(start(description: 'description', buildOperationStart: true, id: 1L, buildOperationId: 1L, buildOperationCategory: BuildOperationCategory.TASK)) @@ -324,7 +324,7 @@ class OutputEventRendererTest extends OutputSpecification { metaData.stdOut >> false metaData.stdErr >> true renderer.attachSystemOutAndErr() - renderer.addRichConsole(console, metaData) + renderer.addRichConsole(console, metaData, outputs.stdOutPrintStream, outputs.stdErrPrintStream, false) when: renderer.onOutput(start('description')) @@ -342,7 +342,7 @@ class OutputEventRendererTest extends OutputSpecification { def snapshot = renderer.snapshot() metaData.stdOut >> true metaData.stdErr >> true - renderer.addRichConsole(console, metaData) + renderer.addRichConsole(console, metaData, outputs.stdOutPrintStream, outputs.stdErrPrintStream, false) when: renderer.onOutput(event(tenAm, 'info', LogLevel.INFO)) @@ -359,7 +359,7 @@ class OutputEventRendererTest extends OutputSpecification { def snapshot = renderer.snapshot() metaData.stdOut >> true metaData.stdErr >> true - renderer.addRichConsole(console, metaData) + renderer.addRichConsole(console, metaData, outputs.stdOutPrintStream, outputs.stdErrPrintStream, false) renderer.onOutput(event('info', LogLevel.INFO)) renderer.onOutput(event('error', LogLevel.ERROR)) renderer.restore(snapshot) // close console to flush @@ -376,7 +376,7 @@ class OutputEventRendererTest extends OutputSpecification { def snapshot = renderer.snapshot() metaData.stdOut >> true metaData.stdErr >> false - renderer.addRichConsole(console, metaData) + renderer.addRichConsole(console, metaData, outputs.stdOutPrintStream, outputs.stdErrPrintStream, false) renderer.onOutput(event('info', LogLevel.INFO)) renderer.onOutput(event('error', LogLevel.ERROR)) renderer.restore(snapshot) // close console to flush @@ -393,7 +393,7 @@ class OutputEventRendererTest extends OutputSpecification { def snapshot = renderer.snapshot() metaData.stdOut >> false metaData.stdErr >> true - renderer.addRichConsole(console, metaData) + renderer.addRichConsole(console, metaData, outputs.stdOutPrintStream, outputs.stdErrPrintStream, false) renderer.onOutput(event('info', LogLevel.INFO)) renderer.onOutput(event('error', LogLevel.ERROR)) renderer.restore(snapshot) // close console to flush diff --git a/subprojects/native/src/main/java/org/gradle/internal/nativeintegration/console/ConsoleMetaData.java b/subprojects/native/src/main/java/org/gradle/internal/nativeintegration/console/ConsoleMetaData.java index 62a77f43222fa..6c0cb3a2ba13f 100644 --- a/subprojects/native/src/main/java/org/gradle/internal/nativeintegration/console/ConsoleMetaData.java +++ b/subprojects/native/src/main/java/org/gradle/internal/nativeintegration/console/ConsoleMetaData.java @@ -40,4 +40,6 @@ public interface ConsoleMetaData { * @return The height of the console (rows). If no information is available return 0. */ int getRows(); + + boolean isWrapStreams(); } diff --git a/subprojects/native/src/main/java/org/gradle/internal/nativeintegration/console/FallbackConsoleMetaData.java b/subprojects/native/src/main/java/org/gradle/internal/nativeintegration/console/FallbackConsoleMetaData.java index 67528711c7bd3..0902f614378c8 100644 --- a/subprojects/native/src/main/java/org/gradle/internal/nativeintegration/console/FallbackConsoleMetaData.java +++ b/subprojects/native/src/main/java/org/gradle/internal/nativeintegration/console/FallbackConsoleMetaData.java @@ -45,4 +45,9 @@ public int getCols() { public int getRows() { return 0; } + + @Override + public boolean isWrapStreams() { + return attached; + } } diff --git a/subprojects/native/src/main/java/org/gradle/internal/nativeintegration/console/NativePlatformConsoleMetaData.java b/subprojects/native/src/main/java/org/gradle/internal/nativeintegration/console/NativePlatformConsoleMetaData.java index f7ae2077dc5d6..38458dcc0ab33 100644 --- a/subprojects/native/src/main/java/org/gradle/internal/nativeintegration/console/NativePlatformConsoleMetaData.java +++ b/subprojects/native/src/main/java/org/gradle/internal/nativeintegration/console/NativePlatformConsoleMetaData.java @@ -48,4 +48,9 @@ public int getCols() { public int getRows() { return terminal.getTerminalSize().getRows(); } + + @Override + public boolean isWrapStreams() { + return true; + } } diff --git a/subprojects/native/src/main/java/org/gradle/internal/nativeintegration/console/TestConsoleMetadata.java b/subprojects/native/src/main/java/org/gradle/internal/nativeintegration/console/TestConsoleMetadata.java index 721a06262e64b..0086e07955c87 100644 --- a/subprojects/native/src/main/java/org/gradle/internal/nativeintegration/console/TestConsoleMetadata.java +++ b/subprojects/native/src/main/java/org/gradle/internal/nativeintegration/console/TestConsoleMetadata.java @@ -18,7 +18,6 @@ public enum TestConsoleMetadata implements ConsoleMetaData { BOTH(true, true), - NEITHER(false, false), STDOUT_ONLY(true, false), STDERR_ONLY(false, true); @@ -52,6 +51,11 @@ public int getRows() { return 40; } + @Override + public boolean isWrapStreams() { + return false; + } + public String getCommandLineArgument() { return "-D" + TEST_CONSOLE_PROPERTY + "=" + name(); } From 0dd90dfa1a685b0e90e39f7cda9257f32e1a1a6b Mon Sep 17 00:00:00 2001 From: Adam Murdoch Date: Fri, 8 Mar 2019 13:49:25 +1100 Subject: [PATCH 529/853] Simplify tests that look for rich content in the console output. --- .../ClassLoaderUtilsIntegrationTest.groovy | 96 ------------------- ...ndencyResolveConsoleIntegrationTest.groovy | 10 +- ...WithMetadataSupplierIntegrationTest.groovy | 4 +- .../fixtures/RichConsoleStyling.groovy | 16 ++-- .../executer/AbstractGradleExecuter.java | 1 - ...ErrorsOnStdoutScrapingExecutionResult.java | 10 ++ .../fixtures/executer/ExecutionResult.java | 10 ++ .../executer/InProcessGradleExecuter.java | 10 ++ .../fixtures/executer/LogContent.java | 16 +--- .../OutputScrapingExecutionResult.java | 16 +++- ...ConfigurationProgressFunctionalTest.groovy | 2 +- ...tConsoleJvmTestWorkerFunctionalTest.groovy | 8 +- .../console/jvm/TestedProjectFixture.groovy | 4 +- ...actConsoleBuildResultFunctionalTest.groovy | 10 +- ...sicGroupedTaskLoggingFunctionalTest.groovy | 10 +- .../MavenPublishConsoleIntegrationTest.groovy | 14 +-- .../AbstractJvmFailFastIntegrationSpec.groovy | 4 +- 17 files changed, 82 insertions(+), 159 deletions(-) delete mode 100644 subprojects/base-services/src/integTest/groovy/org/gradle/internal/classloader/ClassLoaderUtilsIntegrationTest.groovy diff --git a/subprojects/base-services/src/integTest/groovy/org/gradle/internal/classloader/ClassLoaderUtilsIntegrationTest.groovy b/subprojects/base-services/src/integTest/groovy/org/gradle/internal/classloader/ClassLoaderUtilsIntegrationTest.groovy deleted file mode 100644 index d3dfd2f70b04a..0000000000000 --- a/subprojects/base-services/src/integTest/groovy/org/gradle/internal/classloader/ClassLoaderUtilsIntegrationTest.groovy +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright 2018 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.gradle.internal.classloader - -import com.google.common.io.Files -import org.gradle.integtests.fixtures.AbstractIntegrationSpec -import org.gradle.util.Requires -import org.gradle.util.TestPrecondition -import org.objectweb.asm.ClassWriter -import org.objectweb.asm.MethodVisitor -import org.objectweb.asm.Type -import spock.lang.Unroll - -import static org.objectweb.asm.Opcodes.ACC_PUBLIC -import static org.objectweb.asm.Opcodes.ALOAD -import static org.objectweb.asm.Opcodes.H_INVOKESPECIAL -import static org.objectweb.asm.Opcodes.RETURN -import static org.objectweb.asm.Opcodes.V1_5 - -@Requires(TestPrecondition.JDK9_OR_LATER) -class ClassLoaderUtilsIntegrationTest extends AbstractIntegrationSpec { - private String packageName = ClassLoaderUtils.getPackageName() - - @Unroll - def 'have illegal access warning when trying to inject into #classLoader'() { - given: - buildFile << """ - apply plugin:'java' - - ${jcenterRepository()} - - dependencies { - testCompile gradleApi() - testCompile 'junit:junit:4.12' - } - """ - - file("src/test/java/${packageName.replace('.', '/')}/Test.java") << """ - package ${packageName}; - import java.nio.file.*; - - public class Test { - @org.junit.Test - public void test() throws Exception { - Path path = Paths.get("${file('MyClass.class').absolutePath.replace('\\', '/')}"); - byte[] bytes = Files.readAllBytes(path); - ClassLoaderUtils.define(${classLoader}, "MyClass", bytes); - } - - private static class MyClassLoader extends ClassLoader { } - } - """ - - createClassFile() - - when: - succeeds('test') - - then: - result.hasErrorOutput("Illegal reflective access using Lookup on ${ClassLoaderUtils.name}") == hasWarning - - where: - classLoader | hasWarning - 'ClassLoader.getSystemClassLoader()' | true - 'new MyClassLoader()' | false - } - - void createClassFile() { - ClassWriter cw = new ClassWriter(0) - cw.visit(V1_5, ACC_PUBLIC, "MyClass", null, 'java/lang/Object', null) - MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "", "()V", null, null) - mv.visitMaxs(2, 1) - mv.visitVarInsn(ALOAD, 0) // push `this` to the operand stack - mv.visitMethodInsn(H_INVOKESPECIAL, Type.getInternalName(Object.class), "", "()V", false) - mv.visitInsn(RETURN) - mv.visitEnd() - cw.visitEnd() - - Files.write(cw.toByteArray(), file('MyClass.class')) - } - -} diff --git a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/RemoteDependencyResolveConsoleIntegrationTest.groovy b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/RemoteDependencyResolveConsoleIntegrationTest.groovy index 1339cefa225b8..f4f51c2a6141b 100644 --- a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/RemoteDependencyResolveConsoleIntegrationTest.groovy +++ b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/RemoteDependencyResolveConsoleIntegrationTest.groovy @@ -20,6 +20,7 @@ import org.gradle.api.logging.configuration.ConsoleOutput import org.gradle.integtests.fixtures.AbstractDependencyResolutionTest import org.gradle.integtests.fixtures.RichConsoleStyling import org.gradle.integtests.fixtures.executer.GradleHandle +import org.gradle.integtests.fixtures.executer.LogContent import org.gradle.test.fixtures.ConcurrentTestUtil import org.gradle.test.fixtures.server.http.BlockingHttpServer import org.junit.Rule @@ -119,12 +120,13 @@ class RemoteDependencyResolveConsoleIntegrationTest extends AbstractDependencyRe } void outputContainsProgress(GradleHandle build, String taskProgressLine, String... progressOutputLines) { - assert build.standardOutput.contains(workInProgressLine(taskProgressLine)) || - progressOutputLines.any { build.standardOutput.contains(workInProgressLine(taskProgressLine + " " + it)) } + def output = LogContent.of(build.standardOutput).ansiCharsToColorText().withNormalizedEol() + assert output.contains(workInProgressLine(taskProgressLine)) || + progressOutputLines.any { output.contains(workInProgressLine(taskProgressLine + " " + it)) } assert progressOutputLines.every { - build.standardOutput.contains(workInProgressLine(it)) || - build.standardOutput.contains(workInProgressLine(taskProgressLine + " " + it)) + output.contains(workInProgressLine(it)) || + output.contains(workInProgressLine(taskProgressLine + " " + it)) } } diff --git a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/suppliers/DynamicRevisionRemoteResolveWithMetadataSupplierIntegrationTest.groovy b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/suppliers/DynamicRevisionRemoteResolveWithMetadataSupplierIntegrationTest.groovy index 349b8aa2cd41f..c3618b9cc2c19 100644 --- a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/suppliers/DynamicRevisionRemoteResolveWithMetadataSupplierIntegrationTest.groovy +++ b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/suppliers/DynamicRevisionRemoteResolveWithMetadataSupplierIntegrationTest.groovy @@ -1040,8 +1040,8 @@ group:projectB:2.2;release then: noExceptionThrown() - result.assertOutputContains "Found result for rule [DefaultConfigurableRule{rule=class MP, ruleParams=[]}] and key group:projectB:2.2" - result.assertOutputContains "Found result for rule [DefaultConfigurableRule{rule=class MP, ruleParams=[]}] and key group:projectB:1.1" + outputContains "Found result for rule [DefaultConfigurableRule{rule=class MP, ruleParams=[]}] and key group:projectB:2.2" + outputContains "Found result for rule [DefaultConfigurableRule{rule=class MP, ruleParams=[]}] and key group:projectB:1.1" } def "changing the implementation of a rule invalidates the cache"() { diff --git a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/RichConsoleStyling.groovy b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/RichConsoleStyling.groovy index 87725c849f001..58938734911eb 100644 --- a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/RichConsoleStyling.groovy +++ b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/RichConsoleStyling.groovy @@ -15,23 +15,21 @@ */ package org.gradle.integtests.fixtures + +import org.gradle.integtests.fixtures.executer.GradleHandle +import org.gradle.integtests.fixtures.executer.LogContent + /** * A trait for testing console behavior. *

    * Note: The console output contains formatting characters. */ trait RichConsoleStyling { - public final static String CONTROL_SEQUENCE_START = "\u001B[" - static String workInProgressLine(String plainText) { - return boldOn() + plainText + reset() - } - - private static String boldOn() { - "${CONTROL_SEQUENCE_START}1m" + return "{bold-on}" + plainText + "{bold-off}" } - private static String reset() { - "${CONTROL_SEQUENCE_START}m" + static void assertHasWorkInProgress(GradleHandle handle, String plainText) { + assert LogContent.of(handle.standardOutput).ansiCharsToColorText().withNormalizedEol().contains(workInProgressLine(plainText)) } } diff --git a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/AbstractGradleExecuter.java b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/AbstractGradleExecuter.java index cf666a0ab9151..250c1e23be97a 100644 --- a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/AbstractGradleExecuter.java +++ b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/AbstractGradleExecuter.java @@ -1381,7 +1381,6 @@ protected DurationMeasurement getDurationMeasurement() { private static LoggingServiceRegistry newCommandLineProcessLogging() { LoggingServiceRegistry loggingServices = LoggingServiceRegistry.newEmbeddableLogging(); LoggingManagerInternal rootLoggingManager = loggingServices.get(DefaultLoggingManagerFactory.class).getRoot(); -// rootLoggingManager.captureSystemSources(); rootLoggingManager.attachSystemOutAndErr(); return loggingServices; } diff --git a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/ErrorsOnStdoutScrapingExecutionResult.java b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/ErrorsOnStdoutScrapingExecutionResult.java index 87e75ae88dc91..47880ccbfd3f7 100644 --- a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/ErrorsOnStdoutScrapingExecutionResult.java +++ b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/ErrorsOnStdoutScrapingExecutionResult.java @@ -38,6 +38,16 @@ public String getNormalizedOutput() { return delegate.getNormalizedOutput(); } + @Override + public String getFormattedOutput() { + return delegate.getFormattedOutput(); + } + + @Override + public String getPlainTextOutput() { + return delegate.getPlainTextOutput(); + } + @Override public GroupedOutputFixture getGroupedOutput() { return delegate.getGroupedOutput(); diff --git a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/ExecutionResult.java b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/ExecutionResult.java index 4cb4f635f5865..bccf67ca12112 100644 --- a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/ExecutionResult.java +++ b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/ExecutionResult.java @@ -42,6 +42,16 @@ public interface ExecutionResult { */ String getNormalizedOutput(); + /** + * Stdout of the Gradle execution, with ANSI characters interpreted and text attributes rendered as plain text. + */ + String getFormattedOutput(); + + /** + * Stdout of the Gradle execution, with ANSI characters interpreted and text attributes discarded. + */ + String getPlainTextOutput(); + /** * Returns a fixture that parses the output and forms them into the expected groups */ diff --git a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/InProcessGradleExecuter.java b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/InProcessGradleExecuter.java index 4fe676a22a8fe..1e2624a0ce01b 100755 --- a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/InProcessGradleExecuter.java +++ b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/InProcessGradleExecuter.java @@ -512,6 +512,16 @@ public String getNormalizedOutput() { return outputResult.getNormalizedOutput(); } + @Override + public String getFormattedOutput() { + return outputResult.getFormattedOutput(); + } + + @Override + public String getPlainTextOutput() { + return outputResult.getPlainTextOutput(); + } + @Override public GroupedOutputFixture getGroupedOutput() { return outputResult.getGroupedOutput(); diff --git a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/LogContent.java b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/LogContent.java index 5118c43364b77..227ef5fe72e3d 100644 --- a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/LogContent.java +++ b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/LogContent.java @@ -93,14 +93,7 @@ public static LogContent of(List lines) { } public static LogContent empty() { - return new LogContent(ImmutableList.of(), true, true, null); - } - - /** - * Returns the original content that this content was built from, after transforms such as {@link #removeDebugPrefix()} or {@link #splitOnFirstMatchingLine(Pattern)}. - */ - public LogContent getRawContent() { - return rawContent; + return new LogContent(ImmutableList.of(), true, true, null); } /** @@ -129,13 +122,6 @@ public ImmutableList getLines() { return lines; } - private LogContent lines(int startLine, int endLine) { - if (rawContent != this) { - throw new UnsupportedOperationException("not implemented"); - } - return new LogContent(lines.subList(startLine, endLine), definitelyNoDebugPrefix, definitelyNoAnsiChars, null); - } - /** * Visits each line in this content. The line does not include the line separator. */ diff --git a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/OutputScrapingExecutionResult.java b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/OutputScrapingExecutionResult.java index a4c1260a585eb..94d62a2b1858f 100644 --- a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/OutputScrapingExecutionResult.java +++ b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/OutputScrapingExecutionResult.java @@ -111,6 +111,16 @@ public String getNormalizedOutput() { return normalize(output); } + @Override + public String getFormattedOutput() { + return output.ansiCharsToColorText().withNormalizedEol(); + } + + @Override + public String getPlainTextOutput() { + return output.ansiCharsToPlainText().withNormalizedEol(); + } + @Override public GroupedOutputFixture getGroupedOutput() { if (groupedOutputFixture == null) { @@ -185,7 +195,7 @@ public ExecutionResult assertOutputContains(String expectedOutput) { @Override public boolean hasErrorOutput(String expectedOutput) { - return getError().contains(expectedOutput) || getRawError().contains(expectedOutput); + return getError().contains(expectedOutput); } @Override @@ -197,10 +207,6 @@ public String getError() { return error.withNormalizedEol(); } - public String getRawError() { - return errorContent.getRawContent().withNormalizedEol(); - } - public List getExecutedTasks() { return ImmutableList.copyOf(findExecutedTasksInOrderStarted()); } diff --git a/subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/AbstractConsoleConfigurationProgressFunctionalTest.groovy b/subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/AbstractConsoleConfigurationProgressFunctionalTest.groovy index 741c48b590dd3..438d3e3341f8b 100644 --- a/subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/AbstractConsoleConfigurationProgressFunctionalTest.groovy +++ b/subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/AbstractConsoleConfigurationProgressFunctionalTest.groovy @@ -156,7 +156,7 @@ abstract class AbstractConsoleConfigurationProgressFunctionalTest extends Abstra void assertHasWorkInProgress(String message) { ConcurrentTestUtil.poll { - assert gradle.standardOutput.contains(workInProgressLine("> " + message)) + assertHasWorkInProgress(gradle, "> " + message) } } } diff --git a/subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/jvm/AbstractConsoleJvmTestWorkerFunctionalTest.groovy b/subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/jvm/AbstractConsoleJvmTestWorkerFunctionalTest.groovy index c6e24c915f797..b2bc160ebfe98 100644 --- a/subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/jvm/AbstractConsoleJvmTestWorkerFunctionalTest.groovy +++ b/subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/jvm/AbstractConsoleJvmTestWorkerFunctionalTest.groovy @@ -60,8 +60,8 @@ abstract class AbstractConsoleJvmTestWorkerFunctionalTest extends AbstractIntegr then: ConcurrentTestUtil.poll { - assert containsTestExecutionWorkInProgressLine(gradleHandle, ':test', testClass1.renderedClassName) - assert containsTestExecutionWorkInProgressLine(gradleHandle, ':test', testClass2.renderedClassName) + containsTestExecutionWorkInProgressLine(gradleHandle, ':test', testClass1.renderedClassName) + containsTestExecutionWorkInProgressLine(gradleHandle, ':test', testClass2.renderedClassName) } testExecution.release(2) @@ -93,8 +93,8 @@ abstract class AbstractConsoleJvmTestWorkerFunctionalTest extends AbstractIntegr then: ConcurrentTestUtil.poll { - assert containsTestExecutionWorkInProgressLine(gradleHandle, ':project1:test', testClass1.renderedClassName) - assert containsTestExecutionWorkInProgressLine(gradleHandle, ':project2:test', testClass2.renderedClassName) + containsTestExecutionWorkInProgressLine(gradleHandle, ':project1:test', testClass1.renderedClassName) + containsTestExecutionWorkInProgressLine(gradleHandle, ':project2:test', testClass2.renderedClassName) } testExecution.release(2) diff --git a/subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/jvm/TestedProjectFixture.groovy b/subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/jvm/TestedProjectFixture.groovy index 5e9da72eb9376..55b8691f0184b 100644 --- a/subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/jvm/TestedProjectFixture.groovy +++ b/subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/jvm/TestedProjectFixture.groovy @@ -62,8 +62,8 @@ class TestedProjectFixture implements RichConsoleStyling { """ } - static boolean containsTestExecutionWorkInProgressLine(GradleHandle gradleHandle, String taskPath, String testName) { - gradleHandle.standardOutput.contains(workInProgressLine("> $taskPath > Executing test $testName")) + static void containsTestExecutionWorkInProgressLine(GradleHandle gradleHandle, String taskPath, String testName) { + assertHasWorkInProgress(gradleHandle, "> $taskPath > Executing test $testName") } static class JavaTestClass { diff --git a/subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/taskgrouping/AbstractConsoleBuildResultFunctionalTest.groovy b/subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/taskgrouping/AbstractConsoleBuildResultFunctionalTest.groovy index eabc05ee88651..6d1e017cccab0 100644 --- a/subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/taskgrouping/AbstractConsoleBuildResultFunctionalTest.groovy +++ b/subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/taskgrouping/AbstractConsoleBuildResultFunctionalTest.groovy @@ -50,8 +50,8 @@ abstract class AbstractConsoleBuildResultFunctionalTest extends AbstractConsoleG succeeds('all') then: - LogContent.of(result.output).ansiCharsToColorText().withNormalizedEol().contains(successMessage) - LogContent.of(result.output).ansiCharsToPlainText().withNormalizedEol().matches """(?s).* + result.formattedOutput.contains(successMessage) + result.plainTextOutput.matches """(?s).* BUILD SUCCESSFUL in \\d+s 2 actionable tasks: 2 executed .*""" @@ -60,8 +60,8 @@ BUILD SUCCESSFUL in \\d+s succeeds('all') then: - LogContent.of(result.output).ansiCharsToColorText().withNormalizedEol().contains(successMessage) - LogContent.of(result.output).ansiCharsToPlainText().withNormalizedEol().matches """(?s).* + result.formattedOutput.contains(successMessage) + result.plainTextOutput.matches """(?s).* BUILD SUCCESSFUL in \\d+s 2 actionable tasks: 1 executed, 1 up-to-date .*""" @@ -95,7 +95,7 @@ BUILD SUCCESSFUL in \\d+s succeeds('success') then: - LogContent.of(result.output).ansiCharsToPlainText().withNormalizedEol().matches """(?s).*build finished + result.plainTextOutput.matches """(?s).*build finished BUILD SUCCESSFUL in \\d+s 1 actionable task: 1 executed diff --git a/subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/taskgrouping/rich/RichConsoleBasicGroupedTaskLoggingFunctionalTest.groovy b/subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/taskgrouping/rich/RichConsoleBasicGroupedTaskLoggingFunctionalTest.groovy index 679fc2fedb463..77c87e89a88b1 100644 --- a/subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/taskgrouping/rich/RichConsoleBasicGroupedTaskLoggingFunctionalTest.groovy +++ b/subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/taskgrouping/rich/RichConsoleBasicGroupedTaskLoggingFunctionalTest.groovy @@ -18,8 +18,6 @@ package org.gradle.internal.logging.console.taskgrouping.rich import org.fusesource.jansi.Ansi import org.gradle.api.logging.configuration.ConsoleOutput -import org.gradle.integtests.fixtures.console.AbstractConsoleGroupedTaskFunctionalTest.StyledOutput -import org.gradle.integtests.fixtures.executer.LogContent import org.gradle.internal.logging.console.taskgrouping.AbstractBasicGroupedTaskLoggingFunctionalTest import spock.lang.Issue @@ -57,7 +55,7 @@ class RichConsoleBasicGroupedTaskLoggingFunctionalTest extends AbstractBasicGrou then: result.groupedOutput.task(':failing').output == 'hello' - LogContent.of(result.output).ansiCharsToColorText().withNormalizedEol().contains(failingTask.output) + result.formattedOutput.contains(failingTask.output) } def "group header is printed red if task failed and there is no output"() { @@ -72,7 +70,7 @@ class RichConsoleBasicGroupedTaskLoggingFunctionalTest extends AbstractBasicGrou fails('failing') then: - LogContent.of(result.output).ansiCharsToColorText().withNormalizedEol().contains(failingTask.output) + result.formattedOutput.contains(failingTask.output) } def "group header is printed white if task succeeds"() { @@ -87,7 +85,7 @@ class RichConsoleBasicGroupedTaskLoggingFunctionalTest extends AbstractBasicGrou succeeds('succeeding') then: - LogContent.of(result.output).ansiCharsToColorText().withNormalizedEol().contains(succeedingTask.output) + result.formattedOutput.contains(succeedingTask.output) } def "configure project group header is printed red if configuration fails with additional failures"() { @@ -105,7 +103,7 @@ class RichConsoleBasicGroupedTaskLoggingFunctionalTest extends AbstractBasicGrou fails('failing') then: - LogContent.of(result.output).ansiCharsToColorText().withNormalizedEol().contains(configuringProject.output) + result.formattedOutput.contains(configuringProject.output) } def "tasks that complete without output do not break up other task output"() { diff --git a/subprojects/maven/src/integTest/groovy/org/gradle/api/publish/maven/MavenPublishConsoleIntegrationTest.groovy b/subprojects/maven/src/integTest/groovy/org/gradle/api/publish/maven/MavenPublishConsoleIntegrationTest.groovy index 5f9610317a1ac..dc6b433b071a8 100644 --- a/subprojects/maven/src/integTest/groovy/org/gradle/api/publish/maven/MavenPublishConsoleIntegrationTest.groovy +++ b/subprojects/maven/src/integTest/groovy/org/gradle/api/publish/maven/MavenPublishConsoleIntegrationTest.groovy @@ -77,7 +77,7 @@ class MavenPublishConsoleIntegrationTest extends AbstractMavenPublishIntegTest i then: ConcurrentTestUtil.poll { - assert build.standardOutput.contains(workInProgressLine("> :publishMavenPublicationToMavenRepository > test-1.2.jar")) + assertHasWorkInProgress(build, "> :publishMavenPublicationToMavenRepository > test-1.2.jar") } when: @@ -86,7 +86,7 @@ class MavenPublishConsoleIntegrationTest extends AbstractMavenPublishIntegTest i then: ConcurrentTestUtil.poll { - assert build.standardOutput.contains(workInProgressLine("> :publishMavenPublicationToMavenRepository > test-1.2.jar.sha1")) + assertHasWorkInProgress(build, "> :publishMavenPublicationToMavenRepository > test-1.2.jar.sha1") } when: @@ -95,7 +95,7 @@ class MavenPublishConsoleIntegrationTest extends AbstractMavenPublishIntegTest i then: ConcurrentTestUtil.poll { - assert build.standardOutput.contains(workInProgressLine("> :publishMavenPublicationToMavenRepository > test-1.2.pom")) + assertHasWorkInProgress(build, "> :publishMavenPublicationToMavenRepository > test-1.2.pom") } when: @@ -104,7 +104,7 @@ class MavenPublishConsoleIntegrationTest extends AbstractMavenPublishIntegTest i then: ConcurrentTestUtil.poll { - assert build.standardOutput.contains(workInProgressLine("> :publishMavenPublicationToMavenRepository > test-1.2.pom.sha1")) + assertHasWorkInProgress(build, "> :publishMavenPublicationToMavenRepository > test-1.2.pom.sha1") } when: @@ -113,7 +113,7 @@ class MavenPublishConsoleIntegrationTest extends AbstractMavenPublishIntegTest i then: ConcurrentTestUtil.poll { - assert build.standardOutput.contains(workInProgressLine("> :publishMavenPublicationToMavenRepository > test-1.2.module > 1 KB/1 KB uploaded")) + assertHasWorkInProgress(build, "> :publishMavenPublicationToMavenRepository > test-1.2.module > 1 KB/1 KB uploaded") } when: @@ -123,7 +123,7 @@ class MavenPublishConsoleIntegrationTest extends AbstractMavenPublishIntegTest i then: ConcurrentTestUtil.poll { // TODO - where did this one go? -// assert build.standardOutput.contains(workInProgressLine("> :publishMavenPublicationToMavenRepository > maven-metadata.xml")) +// assertHasWorkInProgress(build, "> :publishMavenPublicationToMavenRepository > maven-metadata.xml") } when: @@ -132,7 +132,7 @@ class MavenPublishConsoleIntegrationTest extends AbstractMavenPublishIntegTest i then: ConcurrentTestUtil.poll { - assert build.standardOutput.contains(workInProgressLine("> :publishMavenPublicationToMavenRepository > maven-metadata.xml")) + assertHasWorkInProgress(build, "> :publishMavenPublicationToMavenRepository > maven-metadata.xml") } putMetaData.releaseAll() diff --git a/subprojects/testing-jvm/src/integTest/groovy/org/gradle/testing/fixture/AbstractJvmFailFastIntegrationSpec.groovy b/subprojects/testing-jvm/src/integTest/groovy/org/gradle/testing/fixture/AbstractJvmFailFastIntegrationSpec.groovy index 3080d52633c50..624f30e6f3bdc 100644 --- a/subprojects/testing-jvm/src/integTest/groovy/org/gradle/testing/fixture/AbstractJvmFailFastIntegrationSpec.groovy +++ b/subprojects/testing-jvm/src/integTest/groovy/org/gradle/testing/fixture/AbstractJvmFailFastIntegrationSpec.groovy @@ -158,8 +158,8 @@ abstract class AbstractJvmFailFastIntegrationSpec extends AbstractIntegrationSpe then: ConcurrentTestUtil.poll { - assert gradleHandle.standardOutput.contains(workInProgressLine('> :test > Executing test pkg.FailedTest')) - assert gradleHandle.standardOutput.contains(workInProgressLine('> :test > Executing test pkg.OtherTest')) + assertHasWorkInProgress(gradleHandle, '> :test > Executing test pkg.FailedTest') + assertHasWorkInProgress(gradleHandle, '> :test > Executing test pkg.OtherTest') } testExecution.release(FAILED_RESOURCE) From 7676df34d6f5f4643da5fdbd003ddb67b17eaf59 Mon Sep 17 00:00:00 2001 From: Adam Murdoch Date: Wed, 13 Mar 2019 17:30:37 +1100 Subject: [PATCH 530/853] Fix `--console rich` and `--console verbose` so that they always write rich content to stdout and stderr, regardless of whether they are attached to a console or not. Previously, only one of these would have rich content written to them and the other plain, depending on which of these were connected to a console. Fix `--console auto` to use verbose task headers when stdout is not attached to a console but stderr is. Add test coverage for `--console auto`. --- ...utoConsoleExecOutputIntegrationTest.groovy | 23 +++++ ...ransformationLoggingIntegrationTest.groovy | 2 +- ...actConsoleGroupedTaskFunctionalTest.groovy | 10 +- .../executer/InProcessGradleExecuter.java | 5 - ...ractConsoleBuildPhaseFunctionalTest.groovy | 55 ++--------- ...AutoConsoleBuildPhaseFunctionalTest.groovy | 31 +++++++ ...sicGroupedTaskLoggingFunctionalTest.groovy | 4 +- ...actConsoleBuildResultFunctionalTest.groovy | 16 +--- ...ctConsoleVerboseBasicFunctionalTest.groovy | 20 +++- ...nsoleVerboseRenderingFunctionalTest.groovy | 16 ---- ...sicGroupedTaskLoggingFunctionalTest.groovy | 24 +++++ ...ositeBuildGroupedTaskFunctionalTest.groovy | 24 +++++ ...eBuildResultReportingFunctionalTest.groovy | 2 - ...ionMessageGroupedTaskFunctionalTest.groovy | 24 +++++ ...radleBuildGroupedTaskFunctionalTest.groovy | 24 +++++ ...ojectConfigureLoggingFunctionalTest.groovy | 25 +++++ ...toConsoleLoggingHooksFunctionalTest.groovy | 25 +++++ ...toConsoleVerboseBasicFunctionalTest.groovy | 24 +++++ ...eBuildResultReportingFunctionalTest.groovy | 2 - ...eBuildResultReportingFunctionalTest.groovy | 25 +++++ ...leBuildSrcGroupedTaskFunctionalTest.groovy | 24 +++++ ...eBuildResultReportingFunctionalTest.groovy | 2 - .../logging/sink/ConsoleConfigureAction.java | 53 +++++++---- .../sink/ErrorOutputDispatchingListener.java | 14 +-- .../logging/sink/OutputEventRenderer.java | 92 ++++++++++--------- .../sink/OutputEventRendererTest.groovy | 57 +++++++----- 26 files changed, 435 insertions(+), 188 deletions(-) create mode 100644 subprojects/core/src/integTest/groovy/org/gradle/api/tasks/console/AutoConsoleExecOutputIntegrationTest.groovy create mode 100644 subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/AutoConsoleBuildPhaseFunctionalTest.groovy create mode 100644 subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/taskgrouping/plain/AutoConsoleBasicGroupedTaskLoggingFunctionalTest.groovy create mode 100644 subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/taskgrouping/plain/AutoConsoleCompositeBuildGroupedTaskFunctionalTest.groovy create mode 100644 subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/taskgrouping/rich/AutoConsoleDeprecationMessageGroupedTaskFunctionalTest.groovy create mode 100644 subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/taskgrouping/rich/AutoConsoleGradleBuildGroupedTaskFunctionalTest.groovy create mode 100644 subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/taskgrouping/rich/AutoConsoleGroupedProjectConfigureLoggingFunctionalTest.groovy create mode 100644 subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/taskgrouping/rich/AutoConsoleLoggingHooksFunctionalTest.groovy create mode 100644 subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/taskgrouping/rich/AutoConsoleVerboseBasicFunctionalTest.groovy create mode 100644 subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/taskgrouping/verbose/AutoConsoleBuildResultReportingFunctionalTest.groovy create mode 100644 subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/taskgrouping/verbose/AutoConsoleBuildSrcGroupedTaskFunctionalTest.groovy diff --git a/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/console/AutoConsoleExecOutputIntegrationTest.groovy b/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/console/AutoConsoleExecOutputIntegrationTest.groovy new file mode 100644 index 0000000000000..36a3a59928e41 --- /dev/null +++ b/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/console/AutoConsoleExecOutputIntegrationTest.groovy @@ -0,0 +1,23 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.api.tasks.console + +import org.gradle.api.logging.configuration.ConsoleOutput + +class AutoConsoleExecOutputIntegrationTest extends AbstractExecOutputIntegrationTest { + ConsoleOutput consoleType = ConsoleOutput.Auto +} diff --git a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/TransformationLoggingIntegrationTest.groovy b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/TransformationLoggingIntegrationTest.groovy index 8eb5229b16afb..b861deec58033 100644 --- a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/TransformationLoggingIntegrationTest.groovy +++ b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/TransformationLoggingIntegrationTest.groovy @@ -23,7 +23,7 @@ import spock.lang.Unroll class TransformationLoggingIntegrationTest extends AbstractConsoleGroupedTaskFunctionalTest { ConsoleOutput consoleType - private static final List TESTED_CONSOLE_TYPES = [ConsoleOutput.Plain, ConsoleOutput.Verbose, ConsoleOutput.Rich] + private static final List TESTED_CONSOLE_TYPES = [ConsoleOutput.Plain, ConsoleOutput.Verbose, ConsoleOutput.Rich, ConsoleOutput.Auto] def setup() { settingsFile << """ diff --git a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/console/AbstractConsoleGroupedTaskFunctionalTest.groovy b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/console/AbstractConsoleGroupedTaskFunctionalTest.groovy index b42e55073da47..a8996e678c3f2 100644 --- a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/console/AbstractConsoleGroupedTaskFunctionalTest.groovy +++ b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/console/AbstractConsoleGroupedTaskFunctionalTest.groovy @@ -43,19 +43,11 @@ abstract class AbstractConsoleGroupedTaskFunctionalTest extends AbstractIntegrat } boolean stdoutUsesStyledText() { - if (!consoleAttachment.stdoutAttached && consoleAttachment.stderrAttached) { - // Can currently write rich text to one stream at a time, and we prefer stderr when it is attached to the console and stdout is not - return false - } return consoleType == ConsoleOutput.Rich || consoleType == ConsoleOutput.Verbose || consoleType == ConsoleOutput.Auto && consoleAttachment.stdoutAttached } boolean stderrUsesStyledText() { - // Can currently write rich text to one stream at a time, and we prefer stdout when it is attached to the console - if (!consoleAttachment.stdoutAttached && consoleAttachment.stderrAttached) { - return consoleType == ConsoleOutput.Rich || consoleType == ConsoleOutput.Verbose || consoleType == ConsoleOutput.Auto && consoleAttachment.stderrAttached - } - return false + return consoleType == ConsoleOutput.Rich || consoleType == ConsoleOutput.Verbose || consoleType == ConsoleOutput.Auto && consoleAttachment.stderrAttached } abstract ConsoleOutput getConsoleType() diff --git a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/InProcessGradleExecuter.java b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/InProcessGradleExecuter.java index 1e2624a0ce01b..e0727d90e46a8 100755 --- a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/InProcessGradleExecuter.java +++ b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/InProcessGradleExecuter.java @@ -319,11 +319,6 @@ private LoggingManagerInternal createLoggingManager(StartParameter startParamete loggingManager.captureSystemSources(); ConsoleOutput consoleOutput = startParameter.getConsoleOutput(); - if (consoleOutput == ConsoleOutput.Auto) { - // IDEA runs tests attached to a console, use plain so test can assume never attached to a console - // Should really run all tests against a plain and a rich console to make these assumptions explicit - consoleOutput = ConsoleOutput.Plain; - } loggingManager.attachConsole(new TeeOutputStream(System.out, outputStream), new TeeOutputStream(System.err, errorStream), consoleOutput, consoleAttachment.getConsoleMetaData()); return loggingManager; diff --git a/subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/AbstractConsoleBuildPhaseFunctionalTest.groovy b/subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/AbstractConsoleBuildPhaseFunctionalTest.groovy index a598b935d11ee..3ee4297254ceb 100644 --- a/subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/AbstractConsoleBuildPhaseFunctionalTest.groovy +++ b/subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/AbstractConsoleBuildPhaseFunctionalTest.groovy @@ -16,30 +16,23 @@ package org.gradle.internal.logging.console -import org.gradle.api.logging.configuration.ConsoleOutput -import org.gradle.integtests.fixtures.AbstractIntegrationSpec -import org.gradle.integtests.fixtures.RichConsoleStyling -import org.gradle.integtests.fixtures.executer.ConsoleAttachment + +import org.gradle.integtests.fixtures.console.AbstractConsoleGroupedTaskFunctionalTest import org.gradle.integtests.fixtures.executer.GradleHandle import org.gradle.test.fixtures.ConcurrentTestUtil import org.gradle.test.fixtures.server.http.BlockingHttpServer import org.junit.Rule -import spock.lang.Unroll -abstract class AbstractConsoleBuildPhaseFunctionalTest extends AbstractIntegrationSpec implements RichConsoleStyling { +abstract class AbstractConsoleBuildPhaseFunctionalTest extends AbstractConsoleGroupedTaskFunctionalTest { @Rule BlockingHttpServer server = new BlockingHttpServer() GradleHandle gradle def setup() { - executer.withConsole(consoleType) server.start() } - abstract ConsoleOutput getConsoleType() - - @Unroll - def "shows progress bar and percent phase completion when #attachment"() { + def "shows progress bar and percent phase completion"() { settingsFile << """ ${server.callFromBuild('settings')} include "a", "b", "c", "d" @@ -82,7 +75,6 @@ abstract class AbstractConsoleBuildPhaseFunctionalTest extends AbstractIntegrati def task1 = server.expectAndBlock('task1') def task2 = server.expectAndBlock('task2') def buildFinished = server.expectAndBlock('build-finished') - executer.withTestConsoleAttached(attachment) gradle = executer.withTasks("hello2").start() expect: @@ -127,13 +119,9 @@ abstract class AbstractConsoleBuildPhaseFunctionalTest extends AbstractIntegrati and: gradle.waitForFinish() - - where: - attachment << [ConsoleAttachment.ATTACHED, ConsoleAttachment.ATTACHED_STDOUT_ONLY, ConsoleAttachment.NOT_ATTACHED] } - @Unroll - def "shows progress bar and percent phase completion with included build when #attachment"() { + def "shows progress bar and percent phase completion with included build"() { settingsFile << """ ${server.callFromBuild('settings')} includeBuild "child" @@ -175,7 +163,6 @@ abstract class AbstractConsoleBuildPhaseFunctionalTest extends AbstractIntegrati def task1 = server.expectAndBlock('task1') def task2 = server.expectAndBlock('task2') def rootBuildFinished = server.expectAndBlock('root-build-finished') - executer.withTestConsoleAttached(attachment) gradle = executer.withTasks("hello2").start() expect: @@ -215,13 +202,9 @@ abstract class AbstractConsoleBuildPhaseFunctionalTest extends AbstractIntegrati and: gradle.waitForFinish() - - where: - attachment << [ConsoleAttachment.ATTACHED, ConsoleAttachment.ATTACHED_STDOUT_ONLY, ConsoleAttachment.NOT_ATTACHED] } - @Unroll - def "shows progress bar and percent phase completion with buildSrc build when #attachment"() { + def "shows progress bar and percent phase completion with buildSrc build"() { settingsFile << """ ${server.callFromBuild('settings')} """ @@ -265,7 +248,6 @@ abstract class AbstractConsoleBuildPhaseFunctionalTest extends AbstractIntegrati def rootBuildScript = server.expectAndBlock('root-build-script') def task2 = server.expectAndBlock('task2') def rootBuildFinished = server.expectAndBlock('root-build-finished') - executer.withTestConsoleAttached(attachment) gradle = executer.withTasks("hello").start() expect: @@ -310,13 +292,9 @@ abstract class AbstractConsoleBuildPhaseFunctionalTest extends AbstractIntegrati and: gradle.waitForFinish() - - where: - attachment << [ConsoleAttachment.ATTACHED, ConsoleAttachment.ATTACHED_STDOUT_ONLY, ConsoleAttachment.NOT_ATTACHED] } - @Unroll - def "shows progress bar and percent phase completion with artifact transforms with #attachment"() { + def "shows progress bar and percent phase completion with artifact transforms"() { given: settingsFile << """ include 'lib' @@ -419,7 +397,6 @@ abstract class AbstractConsoleBuildPhaseFunctionalTest extends AbstractIntegrati def buildFinished = server.expectAndBlock('build-finished') when: - executer.withTestConsoleAttached(attachment) gradle = executer.withTasks(":util:resolve").start() then: @@ -449,24 +426,6 @@ abstract class AbstractConsoleBuildPhaseFunctionalTest extends AbstractIntegrati and: gradle.waitForFinish() - - where: - attachment << [ConsoleAttachment.ATTACHED, ConsoleAttachment.ATTACHED_STDOUT_ONLY, ConsoleAttachment.NOT_ATTACHED] - } - - @Unroll - def "does not show progress bar when stdout is #attachment"() { - when: - executer.withTestConsoleAttached(attachment) - succeeds() - - then: - result.assertNotOutput("INITIALIZING") - result.assertNotOutput("CONFIGURING") - result.assertNotOutput("EXECUTING") - - where: - attachment << [ConsoleAttachment.ATTACHED_STDERR_ONLY] } void assertHasBuildPhase(String message) { diff --git a/subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/AutoConsoleBuildPhaseFunctionalTest.groovy b/subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/AutoConsoleBuildPhaseFunctionalTest.groovy new file mode 100644 index 0000000000000..41c9e492e52e1 --- /dev/null +++ b/subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/AutoConsoleBuildPhaseFunctionalTest.groovy @@ -0,0 +1,31 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.internal.logging.console + +import org.gradle.api.logging.configuration.ConsoleOutput +import org.junit.Assume + + +class AutoConsoleBuildPhaseFunctionalTest extends AbstractConsoleBuildPhaseFunctionalTest { + ConsoleOutput consoleType = ConsoleOutput.Auto + + @Override + def setup() { + // The dynamic content is written to stdout only when it is attached to a console + Assume.assumeTrue(consoleAttachment.stdoutAttached) + } +} diff --git a/subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/taskgrouping/AbstractBasicGroupedTaskLoggingFunctionalTest.groovy b/subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/taskgrouping/AbstractBasicGroupedTaskLoggingFunctionalTest.groovy index 184c8009c3912..233eed53bbca4 100644 --- a/subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/taskgrouping/AbstractBasicGroupedTaskLoggingFunctionalTest.groovy +++ b/subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/taskgrouping/AbstractBasicGroupedTaskLoggingFunctionalTest.groovy @@ -53,7 +53,9 @@ abstract class AbstractBasicGroupedTaskLoggingFunctionalTest extends AbstractCon when: server.expectConcurrent("log1", "log2", "log3") - result = executer.withArgument("--parallel").withTasks("log").start().waitForFinish() + executer.withArgument("--parallel") + // run build in another process to avoid interference from logging from test fixtures + result = executer.withTasks("log").start().waitForFinish() then: result.groupedOutput.taskCount == 3 diff --git a/subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/taskgrouping/AbstractConsoleBuildResultFunctionalTest.groovy b/subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/taskgrouping/AbstractConsoleBuildResultFunctionalTest.groovy index 6d1e017cccab0..2a7fc732eec6f 100644 --- a/subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/taskgrouping/AbstractConsoleBuildResultFunctionalTest.groovy +++ b/subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/taskgrouping/AbstractConsoleBuildResultFunctionalTest.groovy @@ -23,14 +23,8 @@ import org.gradle.integtests.fixtures.executer.LogContent import spock.lang.Unroll abstract class AbstractConsoleBuildResultFunctionalTest extends AbstractConsoleGroupedTaskFunctionalTest { - protected final String buildFailed = 'BUILD FAILED' - protected final String buildSuccess = 'BUILD SUCCESSFUL' - protected final StyledOutput buildFailedStyled = styled(Ansi.Color.RED, Ansi.Attribute.INTENSITY_BOLD).text(buildFailed).off() - protected final StyledOutput buildSuccessStyled = styled(Ansi.Color.GREEN, Ansi.Attribute.INTENSITY_BOLD).text(buildSuccess).off() - - abstract String getFailureMessage() - - abstract String getSuccessMessage() + protected final StyledOutput buildFailed = styled(Ansi.Color.RED, Ansi.Attribute.INTENSITY_BOLD).text('BUILD FAILED').off() + protected final StyledOutput buildSuccessful = styled(Ansi.Color.GREEN, Ansi.Attribute.INTENSITY_BOLD).text('BUILD SUCCESSFUL').off() def "outcome for successful build is logged with appropriate styling"() { given: @@ -50,7 +44,7 @@ abstract class AbstractConsoleBuildResultFunctionalTest extends AbstractConsoleG succeeds('all') then: - result.formattedOutput.contains(successMessage) + result.formattedOutput.contains(buildSuccessful.output) result.plainTextOutput.matches """(?s).* BUILD SUCCESSFUL in \\d+s 2 actionable tasks: 2 executed @@ -60,7 +54,7 @@ BUILD SUCCESSFUL in \\d+s succeeds('all') then: - result.formattedOutput.contains(successMessage) + result.formattedOutput.contains(buildSuccessful.output) result.plainTextOutput.matches """(?s).* BUILD SUCCESSFUL in \\d+s 2 actionable tasks: 1 executed, 1 up-to-date @@ -135,7 +129,7 @@ BUILD SUCCESSFUL in \\d+s !outputWithoutFailure.contains("Build failed with an exception.") !outputWithoutFailure.contains("* What went wrong:") - outputWithFailureAndNoDebugging.contains(failureMessage) + outputWithFailureAndNoDebugging.contains(buildFailed.errorOutput) where: level << [LogLevel.DEBUG, LogLevel.INFO, LogLevel.LIFECYCLE, LogLevel.WARN, LogLevel.QUIET] diff --git a/subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/taskgrouping/AbstractConsoleVerboseBasicFunctionalTest.groovy b/subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/taskgrouping/AbstractConsoleVerboseBasicFunctionalTest.groovy index f3d34bd857912..eb83432210a4c 100644 --- a/subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/taskgrouping/AbstractConsoleVerboseBasicFunctionalTest.groovy +++ b/subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/taskgrouping/AbstractConsoleVerboseBasicFunctionalTest.groovy @@ -18,6 +18,7 @@ package org.gradle.internal.logging.console.taskgrouping import org.gradle.integtests.fixtures.console.AbstractConsoleGroupedTaskFunctionalTest +import static org.gradle.api.logging.configuration.ConsoleOutput.Auto import static org.gradle.api.logging.configuration.ConsoleOutput.Plain import static org.gradle.api.logging.configuration.ConsoleOutput.Verbose @@ -26,7 +27,7 @@ abstract class AbstractConsoleVerboseBasicFunctionalTest extends AbstractConsole given: def helloWorldMessage= 'Hello world' def byeWorldMessage= 'Bye world' - def hasSilenceTaskOutput = consoleType in [Verbose, Plain] + def hasSilenceTaskOutput = consoleType in [Verbose, Plain] || consoleType == Auto && !consoleAttachment.stdoutAttached buildFile << """ task helloWorld { @@ -55,4 +56,21 @@ abstract class AbstractConsoleVerboseBasicFunctionalTest extends AbstractConsole hasSilenceTaskOutput == result.groupedOutput.hasTask(':silence') } + def 'failed task result can be rendered'() { + given: + buildFile << ''' + task myFailure { + doLast { + assert false + } + } + ''' + + when: + fails('myFailure') + + then: + result.groupedOutput.task(':myFailure').outcome == 'FAILED' + } + } diff --git a/subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/taskgrouping/AbstractConsoleVerboseRenderingFunctionalTest.groovy b/subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/taskgrouping/AbstractConsoleVerboseRenderingFunctionalTest.groovy index ad65b8289d2ba..3df8d47ae775f 100644 --- a/subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/taskgrouping/AbstractConsoleVerboseRenderingFunctionalTest.groovy +++ b/subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/taskgrouping/AbstractConsoleVerboseRenderingFunctionalTest.groovy @@ -20,22 +20,6 @@ import org.gradle.integtests.fixtures.executer.GradleContextualExecuter import spock.lang.IgnoreIf abstract class AbstractConsoleVerboseRenderingFunctionalTest extends AbstractConsoleVerboseBasicFunctionalTest { - def 'failed task result can be rendered'() { - given: - buildFile << ''' - task myFailure { - doLast { - assert false - } - } - ''' - - when: - fails('myFailure') - - then: - result.groupedOutput.task(':myFailure').outcome == 'FAILED' - } def 'up-to-date task result can be rendered'() { given: diff --git a/subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/taskgrouping/plain/AutoConsoleBasicGroupedTaskLoggingFunctionalTest.groovy b/subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/taskgrouping/plain/AutoConsoleBasicGroupedTaskLoggingFunctionalTest.groovy new file mode 100644 index 0000000000000..e14a5f980a101 --- /dev/null +++ b/subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/taskgrouping/plain/AutoConsoleBasicGroupedTaskLoggingFunctionalTest.groovy @@ -0,0 +1,24 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.internal.logging.console.taskgrouping.plain + +import org.gradle.api.logging.configuration.ConsoleOutput +import org.gradle.internal.logging.console.taskgrouping.AbstractBasicGroupedTaskLoggingFunctionalTest + +class AutoConsoleBasicGroupedTaskLoggingFunctionalTest extends AbstractBasicGroupedTaskLoggingFunctionalTest { + ConsoleOutput consoleType = ConsoleOutput.Auto +} diff --git a/subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/taskgrouping/plain/AutoConsoleCompositeBuildGroupedTaskFunctionalTest.groovy b/subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/taskgrouping/plain/AutoConsoleCompositeBuildGroupedTaskFunctionalTest.groovy new file mode 100644 index 0000000000000..9633eef30e930 --- /dev/null +++ b/subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/taskgrouping/plain/AutoConsoleCompositeBuildGroupedTaskFunctionalTest.groovy @@ -0,0 +1,24 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.internal.logging.console.taskgrouping.plain + +import org.gradle.api.logging.configuration.ConsoleOutput +import org.gradle.internal.logging.console.taskgrouping.AbstractConsoleCompositeBuildGroupedTaskFunctionalTest + +class AutoConsoleCompositeBuildGroupedTaskFunctionalTest extends AbstractConsoleCompositeBuildGroupedTaskFunctionalTest { + ConsoleOutput consoleType = ConsoleOutput.Auto +} diff --git a/subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/taskgrouping/plain/PlainConsoleBuildResultReportingFunctionalTest.groovy b/subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/taskgrouping/plain/PlainConsoleBuildResultReportingFunctionalTest.groovy index d310ff4fe85ee..760f8894b4f2f 100644 --- a/subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/taskgrouping/plain/PlainConsoleBuildResultReportingFunctionalTest.groovy +++ b/subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/taskgrouping/plain/PlainConsoleBuildResultReportingFunctionalTest.groovy @@ -21,6 +21,4 @@ import org.gradle.internal.logging.console.taskgrouping.AbstractConsoleBuildResu class PlainConsoleBuildResultReportingFunctionalTest extends AbstractConsoleBuildResultFunctionalTest { ConsoleOutput consoleType = ConsoleOutput.Plain - String failureMessage = buildFailed - String successMessage = buildSuccess } diff --git a/subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/taskgrouping/rich/AutoConsoleDeprecationMessageGroupedTaskFunctionalTest.groovy b/subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/taskgrouping/rich/AutoConsoleDeprecationMessageGroupedTaskFunctionalTest.groovy new file mode 100644 index 0000000000000..ae2a131bd7ea9 --- /dev/null +++ b/subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/taskgrouping/rich/AutoConsoleDeprecationMessageGroupedTaskFunctionalTest.groovy @@ -0,0 +1,24 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.internal.logging.console.taskgrouping.rich + +import org.gradle.api.logging.configuration.ConsoleOutput +import org.gradle.internal.logging.console.taskgrouping.AbstractConsoleDeprecationMessageGroupedTaskFunctionalTest + +class AutoConsoleDeprecationMessageGroupedTaskFunctionalTest extends AbstractConsoleDeprecationMessageGroupedTaskFunctionalTest { + ConsoleOutput consoleType = ConsoleOutput.Auto +} diff --git a/subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/taskgrouping/rich/AutoConsoleGradleBuildGroupedTaskFunctionalTest.groovy b/subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/taskgrouping/rich/AutoConsoleGradleBuildGroupedTaskFunctionalTest.groovy new file mode 100644 index 0000000000000..53a5e322cec46 --- /dev/null +++ b/subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/taskgrouping/rich/AutoConsoleGradleBuildGroupedTaskFunctionalTest.groovy @@ -0,0 +1,24 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.internal.logging.console.taskgrouping.rich + +import org.gradle.api.logging.configuration.ConsoleOutput +import org.gradle.internal.logging.console.taskgrouping.AbstractConsoleGradleBuildGroupedTaskFunctionalTest + +class AutoConsoleGradleBuildGroupedTaskFunctionalTest extends AbstractConsoleGradleBuildGroupedTaskFunctionalTest { + ConsoleOutput consoleType = ConsoleOutput.Auto +} diff --git a/subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/taskgrouping/rich/AutoConsoleGroupedProjectConfigureLoggingFunctionalTest.groovy b/subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/taskgrouping/rich/AutoConsoleGroupedProjectConfigureLoggingFunctionalTest.groovy new file mode 100644 index 0000000000000..e5e86bb772618 --- /dev/null +++ b/subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/taskgrouping/rich/AutoConsoleGroupedProjectConfigureLoggingFunctionalTest.groovy @@ -0,0 +1,25 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.internal.logging.console.taskgrouping.rich + +import org.gradle.api.logging.configuration.ConsoleOutput +import org.gradle.internal.logging.console.taskgrouping.AbstractGroupedProjectConfigureLoggingFunctionalTest + + +class AutoConsoleGroupedProjectConfigureLoggingFunctionalTest extends AbstractGroupedProjectConfigureLoggingFunctionalTest { + ConsoleOutput consoleType = ConsoleOutput.Auto +} diff --git a/subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/taskgrouping/rich/AutoConsoleLoggingHooksFunctionalTest.groovy b/subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/taskgrouping/rich/AutoConsoleLoggingHooksFunctionalTest.groovy new file mode 100644 index 0000000000000..2bac0db5a6c91 --- /dev/null +++ b/subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/taskgrouping/rich/AutoConsoleLoggingHooksFunctionalTest.groovy @@ -0,0 +1,25 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.internal.logging.console.taskgrouping.rich + +import org.gradle.api.logging.configuration.ConsoleOutput +import org.gradle.internal.logging.console.taskgrouping.AbstractLoggingHooksFunctionalTest + + +class AutoConsoleLoggingHooksFunctionalTest extends AbstractLoggingHooksFunctionalTest { + ConsoleOutput consoleType = ConsoleOutput.Auto +} diff --git a/subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/taskgrouping/rich/AutoConsoleVerboseBasicFunctionalTest.groovy b/subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/taskgrouping/rich/AutoConsoleVerboseBasicFunctionalTest.groovy new file mode 100644 index 0000000000000..dd9bbe520c2bf --- /dev/null +++ b/subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/taskgrouping/rich/AutoConsoleVerboseBasicFunctionalTest.groovy @@ -0,0 +1,24 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.internal.logging.console.taskgrouping.rich + +import org.gradle.api.logging.configuration.ConsoleOutput +import org.gradle.internal.logging.console.taskgrouping.AbstractConsoleVerboseBasicFunctionalTest + +class AutoConsoleVerboseBasicFunctionalTest extends AbstractConsoleVerboseBasicFunctionalTest { + ConsoleOutput consoleType = ConsoleOutput.Auto +} diff --git a/subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/taskgrouping/rich/RichConsoleBuildResultReportingFunctionalTest.groovy b/subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/taskgrouping/rich/RichConsoleBuildResultReportingFunctionalTest.groovy index 0c04297b0b39c..afe1a09b49d40 100644 --- a/subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/taskgrouping/rich/RichConsoleBuildResultReportingFunctionalTest.groovy +++ b/subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/taskgrouping/rich/RichConsoleBuildResultReportingFunctionalTest.groovy @@ -22,6 +22,4 @@ import org.gradle.internal.logging.console.taskgrouping.AbstractConsoleBuildResu class RichConsoleBuildResultReportingFunctionalTest extends AbstractConsoleBuildResultFunctionalTest { ConsoleOutput consoleType = ConsoleOutput.Rich - String failureMessage = buildFailedStyled.errorOutput - String successMessage = buildSuccessStyled.output } diff --git a/subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/taskgrouping/verbose/AutoConsoleBuildResultReportingFunctionalTest.groovy b/subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/taskgrouping/verbose/AutoConsoleBuildResultReportingFunctionalTest.groovy new file mode 100644 index 0000000000000..1f58c1e6541b3 --- /dev/null +++ b/subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/taskgrouping/verbose/AutoConsoleBuildResultReportingFunctionalTest.groovy @@ -0,0 +1,25 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.internal.logging.console.taskgrouping.verbose + +import org.gradle.api.logging.configuration.ConsoleOutput +import org.gradle.internal.logging.console.taskgrouping.AbstractConsoleBuildResultFunctionalTest + + +class AutoConsoleBuildResultReportingFunctionalTest extends AbstractConsoleBuildResultFunctionalTest { + ConsoleOutput consoleType = ConsoleOutput.Auto +} diff --git a/subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/taskgrouping/verbose/AutoConsoleBuildSrcGroupedTaskFunctionalTest.groovy b/subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/taskgrouping/verbose/AutoConsoleBuildSrcGroupedTaskFunctionalTest.groovy new file mode 100644 index 0000000000000..00e8c9309b9be --- /dev/null +++ b/subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/taskgrouping/verbose/AutoConsoleBuildSrcGroupedTaskFunctionalTest.groovy @@ -0,0 +1,24 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.internal.logging.console.taskgrouping.verbose + +import org.gradle.api.logging.configuration.ConsoleOutput +import org.gradle.internal.logging.console.taskgrouping.AbstractConsoleBuildSrcGroupedTaskFunctionalTest + +class AutoConsoleBuildSrcGroupedTaskFunctionalTest extends AbstractConsoleBuildSrcGroupedTaskFunctionalTest { + ConsoleOutput consoleType = ConsoleOutput.Auto +} diff --git a/subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/taskgrouping/verbose/VerboseConsoleBuildResultReportingFunctionalTest.groovy b/subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/taskgrouping/verbose/VerboseConsoleBuildResultReportingFunctionalTest.groovy index c7f7a09f2cd8a..085b9a53019d2 100644 --- a/subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/taskgrouping/verbose/VerboseConsoleBuildResultReportingFunctionalTest.groovy +++ b/subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/taskgrouping/verbose/VerboseConsoleBuildResultReportingFunctionalTest.groovy @@ -22,6 +22,4 @@ import org.gradle.internal.logging.console.taskgrouping.AbstractConsoleBuildResu class VerboseConsoleBuildResultReportingFunctionalTest extends AbstractConsoleBuildResultFunctionalTest { ConsoleOutput consoleType = ConsoleOutput.Verbose - String failureMessage = buildFailedStyled.errorOutput - String successMessage = buildSuccessStyled.output } diff --git a/subprojects/logging/src/main/java/org/gradle/internal/logging/sink/ConsoleConfigureAction.java b/subprojects/logging/src/main/java/org/gradle/internal/logging/sink/ConsoleConfigureAction.java index 1b7229993bc40..e18340c046bc3 100644 --- a/subprojects/logging/src/main/java/org/gradle/internal/logging/sink/ConsoleConfigureAction.java +++ b/subprojects/logging/src/main/java/org/gradle/internal/logging/sink/ConsoleConfigureAction.java @@ -18,6 +18,7 @@ import org.gradle.api.logging.configuration.ConsoleOutput; import org.gradle.internal.logging.console.AnsiConsole; +import org.gradle.internal.logging.console.ColorMap; import org.gradle.internal.logging.console.Console; import org.gradle.internal.nativeintegration.console.ConsoleDetector; import org.gradle.internal.nativeintegration.console.ConsoleMetaData; @@ -59,31 +60,51 @@ private static ConsoleMetaData getConsoleMetaData() { } private static void configureAutoConsole(OutputEventRenderer renderer, ConsoleMetaData consoleMetaData, OutputStream stdout, OutputStream stderr) { - if (consoleMetaData.isStdOut() || consoleMetaData.isStdErr()) { - configureRichConsole(renderer, consoleMetaData, stdout, stderr, false); + if (consoleMetaData.isStdOut() && consoleMetaData.isStdErr()) { + // Redirect stderr to stdout when both stdout and stderr are attached to a console. Assume that they are attached to the same console + // This avoids interleaving problems when stdout and stderr end up at the same location + Console console = consoleFor(stdout, consoleMetaData, renderer.getColourMap()); + renderer.addRichConsoleWithErrorOutputOnStdout(console, consoleMetaData, false); + } else if (consoleMetaData.isStdOut()) { + // Write rich content to stdout and plain content to stderr + Console console = consoleFor(stdout, consoleMetaData, renderer.getColourMap()); + renderer.addRichConsole(console, stderr, consoleMetaData, false); + } else if (consoleMetaData.isStdErr()) { + // Write plain content to stdout and rich content to stderr + Console stderrConsole = consoleFor(stderr, consoleMetaData, renderer.getColourMap()); + renderer.addRichConsole(stdout, stderrConsole, true); } else { - configurePlainConsole(renderer, consoleMetaData, stdout, stderr); + renderer.addPlainConsole(stdout, stderr); } } private static void configurePlainConsole(OutputEventRenderer renderer, ConsoleMetaData consoleMetaData, OutputStream stdout, OutputStream stderr) { - // Redirect stderr to stdout if a console is attached to both stdout and stderr - // This avoids interleaving problems when stdout and stderr end up at the same location - renderer.addPlainConsole(stdout, stderr, consoleMetaData != null && consoleMetaData.isStdOut() && consoleMetaData.isStdErr()); + if (consoleMetaData.isStdOut() && consoleMetaData.isStdErr()) { + // Redirect stderr to stdout when both stdout and stderr are attached to a console. Assume that they are attached to the same console + // This avoids interleaving problems when stdout and stderr end up at the same location + renderer.addPlainConsoleWithErrorOutputOnStdout(stdout); + } else { + renderer.addPlainConsole(stdout, stderr); + } } private static void configureRichConsole(OutputEventRenderer renderer, ConsoleMetaData consoleMetaData, OutputStream stdout, OutputStream stderr, boolean verbose) { - boolean force = !consoleMetaData.isWrapStreams(); - if (consoleMetaData.isStdErr() && !consoleMetaData.isStdOut()) { - // Only stderr is connected to a console. Currently we can write rich text to one stream only, so prefer stderr in this case - OutputStreamWriter errStr = new OutputStreamWriter(force ? stderr : AnsiConsoleUtil.wrapOutputStream(stderr)); - Console console = new AnsiConsole(errStr, errStr, renderer.getColourMap(), consoleMetaData, force); - renderer.addRichConsole(console, consoleMetaData, stdout, stderr, verbose); + if (consoleMetaData.isStdOut() && consoleMetaData.isStdErr()) { + // Redirect stderr to stdout when both stdout and stderr are attached to a console. Assume that they are attached to the same console + // This avoids interleaving problems when stdout and stderr end up at the same location + Console console = consoleFor(stdout, consoleMetaData, renderer.getColourMap()); + renderer.addRichConsoleWithErrorOutputOnStdout(console, consoleMetaData, verbose); } else { - // Prefer stdout when is connected to a console or neither stream connected to a console - OutputStreamWriter outStr = new OutputStreamWriter(force ? stdout : AnsiConsoleUtil.wrapOutputStream(stdout)); - Console console = new AnsiConsole(outStr, outStr, renderer.getColourMap(), consoleMetaData, force); - renderer.addRichConsole(console, consoleMetaData, stdout, stderr, verbose); + // Write rich content to both stdout and stderr + Console stdoutConsole = consoleFor(stdout, consoleMetaData, renderer.getColourMap()); + Console stderrConsole = consoleFor(stderr, consoleMetaData, renderer.getColourMap()); + renderer.addRichConsole(stdoutConsole, stderrConsole, consoleMetaData, verbose); } } + + private static Console consoleFor(OutputStream stdout, ConsoleMetaData consoleMetaData, ColorMap colourMap) { + boolean force = !consoleMetaData.isWrapStreams(); + OutputStreamWriter outStr = new OutputStreamWriter(force ? stdout : AnsiConsoleUtil.wrapOutputStream(stdout)); + return new AnsiConsole(outStr, outStr, colourMap, consoleMetaData, force); + } } diff --git a/subprojects/logging/src/main/java/org/gradle/internal/logging/sink/ErrorOutputDispatchingListener.java b/subprojects/logging/src/main/java/org/gradle/internal/logging/sink/ErrorOutputDispatchingListener.java index f6e43e428723e..0f183c1117a25 100644 --- a/subprojects/logging/src/main/java/org/gradle/internal/logging/sink/ErrorOutputDispatchingListener.java +++ b/subprojects/logging/src/main/java/org/gradle/internal/logging/sink/ErrorOutputDispatchingListener.java @@ -23,12 +23,10 @@ class ErrorOutputDispatchingListener implements OutputEventListener { private final OutputEventListener stderrChain; private final OutputEventListener stdoutChain; - private final boolean redirectStderr; - public ErrorOutputDispatchingListener(OutputEventListener stderrChain, OutputEventListener stdoutChain, boolean redirectStderr) { + public ErrorOutputDispatchingListener(OutputEventListener stderrChain, OutputEventListener stdoutChain) { this.stderrChain = stderrChain; this.stdoutChain = stdoutChain; - this.redirectStderr = redirectStderr; } @Override @@ -39,14 +37,8 @@ public void onOutput(OutputEvent event) { } else if (event.getLogLevel() != LogLevel.ERROR) { stdoutChain.onOutput(event); } else { - // Write anything that isn't the build failure report to the output stream if there is a console attached. - // This is to avoid interleaving of error and non-error output generated at approximately the same time, as the process stdout and stderr may be forwarded on different pipes and so ordering is lost - // TODO - should attempt to flush the output stream prior to writing to the error stream - if (redirectStderr) { - stdoutChain.onOutput(event); - } else { - stderrChain.onOutput(event); - } + // TODO - should attempt to flush the output stream prior to writing to the error stream (and vice versa) + stderrChain.onOutput(event); } } } diff --git a/subprojects/logging/src/main/java/org/gradle/internal/logging/sink/OutputEventRenderer.java b/subprojects/logging/src/main/java/org/gradle/internal/logging/sink/OutputEventRenderer.java index 3310aa010a1d6..58f1c86a84eff 100644 --- a/subprojects/logging/src/main/java/org/gradle/internal/logging/sink/OutputEventRenderer.java +++ b/subprojects/logging/src/main/java/org/gradle/internal/logging/sink/OutputEventRenderer.java @@ -230,30 +230,49 @@ public void removeOutputEventListener(OutputEventListener listener) { } } - public OutputEventRenderer addRichConsole(Console console, ConsoleMetaData consoleMetaData, OutputStream stdout, OutputStream stderr, boolean verbose) { - OutputEventListener consoleChain; - boolean stdoutAttachedToConsole = consoleMetaData.isStdOut(); - boolean stderrAttachedToConsole = consoleMetaData.isStdErr(); - StandardOutputListener outputListener = new StreamBackedStandardOutputListener(stdout); - StandardOutputListener errorListener = new StreamBackedStandardOutputListener(stderr); - if (stdoutAttachedToConsole && stderrAttachedToConsole) { - OutputEventListener consoleListener = new StyledTextOutputBackedRenderer(console.getBuildOutputArea()); - consoleChain = getRichConsoleChain(console, consoleMetaData, verbose, consoleListener); - } else if (stderrAttachedToConsole) { - OutputEventListener stdoutChain = new StyledTextOutputBackedRenderer(new StreamingStyledTextOutput(outputListener)); - OutputEventListener stderrChain = new FlushConsoleListener(console, new StyledTextOutputBackedRenderer(console.getBuildOutputArea())); - consoleChain = getPlainConsoleChain(stdoutChain, stderrChain, false, verbose); - } else { - OutputEventListener stdoutChain = new StyledTextOutputBackedRenderer(console.getBuildOutputArea()); - OutputEventListener stderrChain = new StyledTextOutputBackedRenderer(new StreamingStyledTextOutput(errorListener)); - OutputEventListener consoleListener = new ErrorOutputDispatchingListener(stderrChain, stdoutChain, false); - consoleChain = getRichConsoleChain(console, consoleMetaData, verbose, consoleListener); - } + public void addRichConsoleWithErrorOutputOnStdout(Console stdout, ConsoleMetaData consoleMetaData, boolean verbose) { + OutputEventListener consoleListener = new StyledTextOutputBackedRenderer(stdout.getBuildOutputArea()); + OutputEventListener consoleChain = getConsoleChainWithDynamicStdout(stdout, consoleMetaData, verbose, consoleListener); + addConsoleChain(consoleChain); + } + + public void addRichConsole(Console stdout, Console stderr, ConsoleMetaData consoleMetaData, boolean verbose) { + OutputEventListener stdoutChain = new StyledTextOutputBackedRenderer(stdout.getBuildOutputArea()); + OutputEventListener stderrChain = new FlushConsoleListener(stderr, new StyledTextOutputBackedRenderer(stderr.getBuildOutputArea())); + OutputEventListener consoleListener = new ErrorOutputDispatchingListener(stderrChain, stdoutChain); + OutputEventListener consoleChain = getConsoleChainWithDynamicStdout(stdout, consoleMetaData, verbose, consoleListener); + addConsoleChain(consoleChain); + } + + public void addRichConsole(Console stdout, OutputStream stderr, ConsoleMetaData consoleMetaData, boolean verbose) { + OutputEventListener stdoutChain = new StyledTextOutputBackedRenderer(stdout.getBuildOutputArea()); + OutputEventListener stderrChain = new StyledTextOutputBackedRenderer(new StreamingStyledTextOutput(new StreamBackedStandardOutputListener(stderr))); + OutputEventListener consoleListener = new ErrorOutputDispatchingListener(stderrChain, stdoutChain); + OutputEventListener consoleChain = getConsoleChainWithDynamicStdout(stdout, consoleMetaData, verbose, consoleListener); + addConsoleChain(consoleChain); + } + + public void addRichConsole(OutputStream stdout, Console stderr, boolean verbose) { + OutputEventListener stdoutChain = new StyledTextOutputBackedRenderer(new StreamingStyledTextOutput(new StreamBackedStandardOutputListener(stdout))); + OutputEventListener stderrChain = new FlushConsoleListener(stderr, new StyledTextOutputBackedRenderer(stderr.getBuildOutputArea())); + OutputEventListener consoleListener = new ErrorOutputDispatchingListener(stderrChain, stdoutChain); + OutputEventListener consoleChain = getConsoleChainWithoutDynamicStdout(consoleListener, verbose); + addConsoleChain(consoleChain); + } - return addConsoleChain(consoleChain); + public void addPlainConsoleWithErrorOutputOnStdout(OutputStream stdout) { + OutputEventListener stdoutChain = new StyledTextOutputBackedRenderer(new StreamingStyledTextOutput(new StreamBackedStandardOutputListener(stdout))); + addConsoleChain(getConsoleChainWithoutDynamicStdout(stdoutChain, true)); } - private OutputEventListener getRichConsoleChain(Console console, ConsoleMetaData consoleMetaData, boolean verbose, OutputEventListener consoleListener) { + public void addPlainConsole(OutputStream stdout, OutputStream stderr) { + OutputEventListener stdoutChain = new StyledTextOutputBackedRenderer(new StreamingStyledTextOutput(new StreamBackedStandardOutputListener(stdout))); + OutputEventListener stderrChain = new StyledTextOutputBackedRenderer(new StreamingStyledTextOutput(new StreamBackedStandardOutputListener(stderr))); + OutputEventListener outputListener = new ErrorOutputDispatchingListener(stderrChain, stdoutChain); + addConsoleChain(getConsoleChainWithoutDynamicStdout(outputListener, true)); + } + + private OutputEventListener getConsoleChainWithDynamicStdout(Console console, ConsoleMetaData consoleMetaData, boolean verbose, OutputEventListener consoleListener) { return throttled( new UserInputConsoleRenderer( new BuildStatusRenderer( @@ -265,31 +284,22 @@ private OutputEventListener getRichConsoleChain(Console console, ConsoleMetaData new DefaultWorkInProgressFormatter(consoleMetaData), new ConsoleLayoutCalculator(consoleMetaData) ), - console.getStatusBar(), console, consoleMetaData), - console) + console.getStatusBar(), console, consoleMetaData), + console) ); } - public OutputEventRenderer addPlainConsole(OutputStream stdout, OutputStream stderr, boolean redirectStderr) { - return addConsoleChain(getPlainConsoleChain(new StreamBackedStandardOutputListener(stdout), new StreamBackedStandardOutputListener(stderr), redirectStderr, true)); - } - - private OutputEventListener getPlainConsoleChain(StandardOutputListener outputListener, StandardOutputListener errorListener, boolean redirectStderr, boolean verbose) { - final OutputEventListener stdoutChain = new UserInputStandardOutputRenderer(new StyledTextOutputBackedRenderer(new StreamingStyledTextOutput(outputListener))); - final OutputEventListener stderrChain = new StyledTextOutputBackedRenderer(new StreamingStyledTextOutput(errorListener)); - return getPlainConsoleChain(stdoutChain, stderrChain, redirectStderr, verbose); - } - - private OutputEventListener getPlainConsoleChain(OutputEventListener stdoutChain, OutputEventListener stderrChain, boolean redirectStderr, boolean verbose) { + private OutputEventListener getConsoleChainWithoutDynamicStdout(OutputEventListener outputListener, boolean verbose) { return throttled( - new BuildLogLevelFilterRenderer( - new GroupingProgressLogEventGenerator( - new ErrorOutputDispatchingListener(stderrChain, stdoutChain, redirectStderr), - new PrettyPrefixedLogHeaderFormatter(), - verbose + new UserInputStandardOutputRenderer( + new BuildLogLevelFilterRenderer( + new GroupingProgressLogEventGenerator( + outputListener, + new PrettyPrefixedLogHeaderFormatter(), + verbose + ) ) - ) - ); + )); } private OutputEventListener throttled(OutputEventListener consoleChain) { diff --git a/subprojects/logging/src/test/groovy/org/gradle/internal/logging/sink/OutputEventRendererTest.groovy b/subprojects/logging/src/test/groovy/org/gradle/internal/logging/sink/OutputEventRendererTest.groovy index 76b88f0f7981d..8a524eaf031ea 100644 --- a/subprojects/logging/src/test/groovy/org/gradle/internal/logging/sink/OutputEventRendererTest.groovy +++ b/subprojects/logging/src/test/groovy/org/gradle/internal/logging/sink/OutputEventRendererTest.groovy @@ -286,9 +286,7 @@ class OutputEventRendererTest extends OutputSpecification { def rendersLogEventsWhenStdOutAndStdErrAreConsole() { def snapshot = renderer.snapshot() - metaData.stdOut >> true - metaData.stdErr >> true - renderer.addRichConsole(console, metaData, outputs.stdOutPrintStream, outputs.stdErrPrintStream, false) + renderer.addRichConsoleWithErrorOutputOnStdout(console, metaData, true) when: renderer.onOutput(start(description: 'description', buildOperationStart: true, id: 1L, buildOperationId: 1L, buildOperationCategory: BuildOperationCategory.TASK)) @@ -299,14 +297,33 @@ class OutputEventRendererTest extends OutputSpecification { then: console.buildOutputArea.toString().readLines() == ['', '{header}> description{info} status{normal}', 'info', '{error}error', '{normal}'] + outputs.stdOut == '' + outputs.stdErr == '' + } + + def rendersLogEventsWhenStdOutAndStdErrAreSeparateConsoles() { + def snapshot = renderer.snapshot() + def stderrConsole = new ConsoleStub() + renderer.addRichConsole(console, stderrConsole, metaData, true) + + when: + renderer.onOutput(start(description: 'description', buildOperationStart: true, id: 1L, buildOperationId: 1L, buildOperationCategory: BuildOperationCategory.TASK)) + renderer.onOutput(event('info', LogLevel.INFO, 1L)) + renderer.onOutput(event('error', LogLevel.ERROR, 1L)) + renderer.onOutput(complete('status')) + renderer.restore(snapshot) // close console to flush + + then: + console.buildOutputArea.toString().readLines() == ['', '{header}> description{info} status{normal}', 'info'] + stderrConsole.buildOutputArea.toString().readLines() == ['{error}error', '{normal}'] + outputs.stdOut == '' + outputs.stdErr == '' } def rendersLogEventsWhenOnlyStdOutIsConsole() { def snapshot = renderer.snapshot() - metaData.stdOut >> true - metaData.stdErr >> false renderer.attachSystemOutAndErr() - renderer.addRichConsole(console, metaData, outputs.stdOutPrintStream, outputs.stdErrPrintStream, false) + renderer.addRichConsole(console, outputs.stdErrPrintStream, metaData, true) when: renderer.onOutput(start(description: 'description', buildOperationStart: true, id: 1L, buildOperationId: 1L, buildOperationCategory: BuildOperationCategory.TASK)) @@ -317,17 +334,17 @@ class OutputEventRendererTest extends OutputSpecification { then: console.buildOutputArea.toString().readLines() == ['', '{header}> description{info} status{normal}', 'info'] + outputs.stdOut == '' + outputs.stdErr.readLines() == ['error'] } def rendersLogEventsWhenOnlyStdErrIsConsole() { def snapshot = renderer.snapshot() - metaData.stdOut >> false - metaData.stdErr >> true renderer.attachSystemOutAndErr() - renderer.addRichConsole(console, metaData, outputs.stdOutPrintStream, outputs.stdErrPrintStream, false) + renderer.addRichConsole(outputs.stdOutPrintStream, console, true) when: - renderer.onOutput(start('description')) + renderer.onOutput(start(description: 'description', buildOperationStart: true, id: 1L, buildOperationId: 1L, buildOperationCategory: BuildOperationCategory.TASK)) renderer.onOutput(event('info', LogLevel.INFO)) renderer.onOutput(event('error', LogLevel.ERROR)) renderer.onOutput(complete('status')) @@ -335,14 +352,14 @@ class OutputEventRendererTest extends OutputSpecification { then: console.buildOutputArea.toString().readLines() == ['{error}error', '{normal}'] + outputs.stdOut.readLines() == ['info', '> description status'] + outputs.stdErr == '' } def rendersLogEventsInConsoleWhenLogLevelIsDebug() { renderer.configure(LogLevel.DEBUG) def snapshot = renderer.snapshot() - metaData.stdOut >> true - metaData.stdErr >> true - renderer.addRichConsole(console, metaData, outputs.stdOutPrintStream, outputs.stdErrPrintStream, false) + renderer.addRichConsoleWithErrorOutputOnStdout(console, metaData, false) when: renderer.onOutput(event(tenAm, 'info', LogLevel.INFO)) @@ -351,15 +368,15 @@ class OutputEventRendererTest extends OutputSpecification { then: console.buildOutputArea.toString().readLines() == ['10:00:00.000 [INFO] [category] info', '{error}10:00:00.000 [ERROR] [category] error', '{normal}'] + outputs.stdOut == '' + outputs.stdErr == '' } def attachesConsoleWhenStdOutAndStdErrAreAttachedToConsole() { when: renderer.attachSystemOutAndErr() def snapshot = renderer.snapshot() - metaData.stdOut >> true - metaData.stdErr >> true - renderer.addRichConsole(console, metaData, outputs.stdOutPrintStream, outputs.stdErrPrintStream, false) + renderer.addRichConsoleWithErrorOutputOnStdout(console, metaData, false) renderer.onOutput(event('info', LogLevel.INFO)) renderer.onOutput(event('error', LogLevel.ERROR)) renderer.restore(snapshot) // close console to flush @@ -374,9 +391,7 @@ class OutputEventRendererTest extends OutputSpecification { when: renderer.attachSystemOutAndErr() def snapshot = renderer.snapshot() - metaData.stdOut >> true - metaData.stdErr >> false - renderer.addRichConsole(console, metaData, outputs.stdOutPrintStream, outputs.stdErrPrintStream, false) + renderer.addRichConsole(console, outputs.stdErrPrintStream, metaData, false) renderer.onOutput(event('info', LogLevel.INFO)) renderer.onOutput(event('error', LogLevel.ERROR)) renderer.restore(snapshot) // close console to flush @@ -391,9 +406,7 @@ class OutputEventRendererTest extends OutputSpecification { when: renderer.attachSystemOutAndErr() def snapshot = renderer.snapshot() - metaData.stdOut >> false - metaData.stdErr >> true - renderer.addRichConsole(console, metaData, outputs.stdOutPrintStream, outputs.stdErrPrintStream, false) + renderer.addRichConsole(outputs.stdOutPrintStream, console, false) renderer.onOutput(event('info', LogLevel.INFO)) renderer.onOutput(event('error', LogLevel.ERROR)) renderer.restore(snapshot) // close console to flush From 1ca1552de336eb63caeef2751d1a98d06a92a896 Mon Sep 17 00:00:00 2001 From: Stefan Wolf Date: Wed, 13 Mar 2019 19:11:29 +0100 Subject: [PATCH 531/853] Determine input changes in ExecuteStep --- .../org/gradle/api/internal/AbstractTask.java | 8 +-- .../AbstractIncrementalTaskAction.java | 14 ++--- .../IncrementalInputsTaskAction.java | 7 +-- .../IncrementalTaskInputsTaskAction.java | 6 +-- .../tasks/ContextAwareTaskAction.java | 3 +- .../internal/tasks/TaskExecutionContext.java | 15 ------ .../DefaultTaskExecutionContext.java | 23 -------- .../execution/ExecuteActionsTaskExecuter.java | 52 ++++++++++--------- .../ExecuteActionsTaskExecuterTest.groovy | 21 -------- .../transform/DefaultTransformerInvoker.java | 20 ++++--- ...IncrementalExecutionIntegrationTest.groovy | 25 +++++---- .../gradle/internal/execution/UnitOfWork.java | 17 ++++-- .../DefaultExecutionStateChangeDetector.java | 23 +++----- .../changes/ExecutionStateChangeDetector.java | 3 +- .../changes/ExecutionStateChanges.java | 3 +- .../changes/IncrementalInputChanges.java | 25 +++++---- .../changes/InputToPropertyMapping.java | 24 --------- .../changes/NonIncrementalInputChanges.java | 11 ++-- .../internal/execution/steps/ExecuteStep.java | 37 ++++++++++++- .../execution/steps/ResolveChangesStep.java | 16 +++--- .../changes/ImplementationChangesTest.groovy | 3 +- .../execution/steps/ExecuteStepTest.groovy | 32 ++++++++++-- .../steps/ResolveChangesStepTest.groovy | 10 ++-- 23 files changed, 182 insertions(+), 216 deletions(-) delete mode 100644 subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/InputToPropertyMapping.java diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/AbstractTask.java b/subprojects/core/src/main/java/org/gradle/api/internal/AbstractTask.java index bedf3ec4fb7ca..56e5d1d941982 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/AbstractTask.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/AbstractTask.java @@ -42,7 +42,6 @@ import org.gradle.api.internal.tasks.ImplementationAwareTaskAction; import org.gradle.api.internal.tasks.TaskContainerInternal; import org.gradle.api.internal.tasks.TaskDependencyInternal; -import org.gradle.api.internal.tasks.TaskExecutionContext; import org.gradle.api.internal.tasks.TaskLocalStateInternal; import org.gradle.api.internal.tasks.TaskMutator; import org.gradle.api.internal.tasks.TaskStateInternal; @@ -61,6 +60,7 @@ import org.gradle.api.tasks.TaskLocalState; import org.gradle.internal.Factory; import org.gradle.internal.classloader.ClassLoaderHierarchyHasher; +import org.gradle.internal.execution.history.changes.InputChangesInternal; import org.gradle.internal.extensibility.ExtensibleDynamicObject; import org.gradle.internal.logging.compatbridge.LoggingManagerInternalCompatibilityBridge; import org.gradle.internal.metaobject.DynamicObject; @@ -624,7 +624,7 @@ private ClosureTaskAction(Closure closure, String actionName) { } @Override - public void contextualise(TaskExecutionContext context) { + public void contextualise(InputChangesInternal inputChanges) { } @Override @@ -680,9 +680,9 @@ public TaskActionWrapper(Action action, String maybeActionName) { } @Override - public void contextualise(TaskExecutionContext context) { + public void contextualise(InputChangesInternal inputChanges) { if (action instanceof ContextAwareTaskAction) { - ((ContextAwareTaskAction) action).contextualise(context); + ((ContextAwareTaskAction) action).contextualise(inputChanges); } } diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/project/taskfactory/AbstractIncrementalTaskAction.java b/subprojects/core/src/main/java/org/gradle/api/internal/project/taskfactory/AbstractIncrementalTaskAction.java index c7d55f9fb3ca7..19e45590c5ec1 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/project/taskfactory/AbstractIncrementalTaskAction.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/project/taskfactory/AbstractIncrementalTaskAction.java @@ -18,28 +18,28 @@ import org.gradle.api.Task; import org.gradle.api.internal.tasks.ContextAwareTaskAction; -import org.gradle.api.internal.tasks.TaskExecutionContext; +import org.gradle.internal.execution.history.changes.InputChangesInternal; import java.lang.reflect.Method; public abstract class AbstractIncrementalTaskAction extends StandardTaskAction implements ContextAwareTaskAction { - private TaskExecutionContext context; + private InputChangesInternal inputChanges; public AbstractIncrementalTaskAction(Class type, Method method) { super(type, method); } @Override - public void contextualise(TaskExecutionContext context) { - this.context = context; + public void contextualise(InputChangesInternal inputChanges) { + this.inputChanges = inputChanges; } @Override public void releaseContext() { - this.context = null; + this.inputChanges = null; } - protected TaskExecutionContext getContext() { - return context; + protected InputChangesInternal getInputChanges() { + return inputChanges; } } diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/project/taskfactory/IncrementalInputsTaskAction.java b/subprojects/core/src/main/java/org/gradle/api/internal/project/taskfactory/IncrementalInputsTaskAction.java index f91368c9d47a1..7ebf7c47a6d22 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/project/taskfactory/IncrementalInputsTaskAction.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/project/taskfactory/IncrementalInputsTaskAction.java @@ -18,7 +18,6 @@ import org.gradle.api.Task; import org.gradle.api.execution.incremental.InputChanges; -import org.gradle.internal.execution.history.changes.ExecutionStateChanges; import org.gradle.internal.reflect.JavaMethod; import java.lang.reflect.Method; @@ -29,10 +28,6 @@ public IncrementalInputsTaskAction(Class type, Method method) { } protected void doExecute(Task task, String methodName) { - @SuppressWarnings("OptionalGetWithoutIsPresent") - ExecutionStateChanges changes = getContext().getExecutionStateChanges().get(); - InputChanges inputChanges = changes.getInputChanges(); - getContext().setTaskExecutedIncrementally(inputChanges.isIncremental()); - JavaMethod.of(task, Object.class, methodName, InputChanges.class).invoke(task, inputChanges); + JavaMethod.of(task, Object.class, methodName, InputChanges.class).invoke(task, getInputChanges()); } } diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/project/taskfactory/IncrementalTaskInputsTaskAction.java b/subprojects/core/src/main/java/org/gradle/api/internal/project/taskfactory/IncrementalTaskInputsTaskAction.java index 52c1b158324e1..787257318e151 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/project/taskfactory/IncrementalTaskInputsTaskAction.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/project/taskfactory/IncrementalTaskInputsTaskAction.java @@ -20,7 +20,6 @@ import org.gradle.api.internal.changedetection.changes.ChangesOnlyIncrementalTaskInputs; import org.gradle.api.internal.changedetection.changes.RebuildIncrementalTaskInputs; import org.gradle.api.tasks.incremental.IncrementalTaskInputs; -import org.gradle.internal.execution.history.changes.ExecutionStateChanges; import org.gradle.internal.execution.history.changes.InputChangesInternal; import org.gradle.internal.reflect.Instantiator; import org.gradle.internal.reflect.JavaMethod; @@ -36,15 +35,12 @@ public IncrementalTaskInputsTaskAction(Instantiator instantiator, Class getExecutionStateChanges(); - - void setExecutionStateChanges(ExecutionStateChanges executionStateChanges); - Optional getOverlappingOutputs(); void setOverlappingOutputs(OverlappingOutputs overlappingOutputs); diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/DefaultTaskExecutionContext.java b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/DefaultTaskExecutionContext.java index a9e937a789577..cd1e8da21f7af 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/DefaultTaskExecutionContext.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/DefaultTaskExecutionContext.java @@ -24,7 +24,6 @@ import org.gradle.execution.plan.LocalTaskNode; import org.gradle.internal.execution.history.AfterPreviousExecutionState; import org.gradle.internal.execution.history.BeforeExecutionState; -import org.gradle.internal.execution.history.changes.ExecutionStateChanges; import org.gradle.internal.fingerprint.CurrentFileCollectionFingerprint; import org.gradle.internal.operations.ExecutingBuildOperation; import org.gradle.internal.time.Time; @@ -38,7 +37,6 @@ public class DefaultTaskExecutionContext implements TaskExecutionContext { private final LocalTaskNode localTaskNode; private AfterPreviousExecutionState afterPreviousExecution; private OverlappingOutputs overlappingOutputs; - private ExecutionStateChanges executionStateChanges; private ImmutableSortedMap outputFilesBeforeExecution; private BeforeExecutionState beforeExecutionState; private TaskExecutionMode taskExecutionMode; @@ -50,7 +48,6 @@ public class DefaultTaskExecutionContext implements TaskExecutionContext { private ExecutingBuildOperation snapshotTaskInputsBuildOperation; private final Timer executionTimer; - private boolean taskExecutedIncrementally; public DefaultTaskExecutionContext(LocalTaskNode localTaskNode) { this.localTaskNode = localTaskNode; @@ -122,16 +119,6 @@ public void setOutputRemovedBeforeExecution(boolean outputRemovedBeforeExecution this.outputRemovedBeforeExecution = outputRemovedBeforeExecution; } - @Override - public Optional getExecutionStateChanges() { - return Optional.ofNullable(executionStateChanges); - } - - @Override - public void setExecutionStateChanges(ExecutionStateChanges executionStateChanges) { - this.executionStateChanges = executionStateChanges; - } - @Override public TaskOutputCachingBuildCacheKey getBuildCacheKey() { return buildCacheKey; @@ -170,16 +157,6 @@ public void setTaskCachingEnabled(boolean taskCachingEnabled) { this.taskCachingEnabled = taskCachingEnabled; } - @Override - public boolean isTaskExecutedIncrementally() { - return taskExecutedIncrementally; - } - - @Override - public void setTaskExecutedIncrementally(boolean taskExecutedIncrementally) { - this.taskExecutedIncrementally = taskExecutedIncrementally; - } - @Override public Optional removeSnapshotTaskInputsBuildOperation() { Optional result = Optional.ofNullable(snapshotTaskInputsBuildOperation); diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuter.java b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuter.java index ebf65874863d3..8bb4d12216f76 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuter.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuter.java @@ -15,12 +15,12 @@ */ package org.gradle.api.internal.tasks.execution; -import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSortedMap; import com.google.common.collect.Lists; import org.gradle.api.execution.TaskActionListener; import org.gradle.api.internal.OverlappingOutputs; import org.gradle.api.internal.TaskInternal; +import org.gradle.api.internal.project.taskfactory.AbstractIncrementalTaskAction; import org.gradle.api.internal.tasks.ContextAwareTaskAction; import org.gradle.api.internal.tasks.TaskExecuter; import org.gradle.api.internal.tasks.TaskExecuterResult; @@ -51,7 +51,7 @@ import org.gradle.internal.execution.history.AfterPreviousExecutionState; import org.gradle.internal.execution.history.BeforeExecutionState; import org.gradle.internal.execution.history.ExecutionHistoryStore; -import org.gradle.internal.execution.history.changes.ExecutionStateChanges; +import org.gradle.internal.execution.history.changes.InputChangesInternal; import org.gradle.internal.execution.impl.OutputFilterUtil; import org.gradle.internal.fingerprint.CurrentFileCollectionFingerprint; import org.gradle.internal.operations.BuildOperationContext; @@ -61,12 +61,11 @@ import org.gradle.internal.operations.RunnableBuildOperation; import org.gradle.internal.work.AsyncWorkTracker; +import javax.annotation.Nullable; import java.io.File; import java.time.Duration; import java.util.ArrayList; -import java.util.HashMap; import java.util.List; -import java.util.Map; import java.util.Optional; import java.util.function.Consumer; import java.util.function.Function; @@ -191,20 +190,15 @@ public String getIdentity() { } @Override - public ExecutionOutcome execute(Optional changes) { + public ExecutionOutcome execute(@Nullable InputChangesInternal inputChanges) { task.getState().setExecuting(true); try { LOGGER.debug("Executing actions for {}.", task); actionListener.beforeActions(task); - changes.ifPresent(new Consumer() { - @Override - public void accept(ExecutionStateChanges changes) { - TaskExecution.this.context.setExecutionStateChanges(changes); - } - }); - executeActions(task, this.context); + boolean incremental = inputChanges != null && inputChanges.isIncremental(); + executeActions(task, inputChanges); return task.getState().getDidWork() - ? this.context.isTaskExecutedIncrementally() + ? incremental ? ExecutionOutcome.EXECUTED_INCREMENTALLY : ExecutionOutcome.EXECUTED_NON_INCREMENTALLY : ExecutionOutcome.UP_TO_DATE; @@ -299,6 +293,16 @@ public Optional getTimeout() { return Optional.ofNullable(task.getTimeout().getOrNull()); } + @Override + public void visitIncrementalFileInputs(InputFilePropertyVisitor visitor) { + for (InputFilePropertySpec inputFileProperty : context.getTaskProperties().getInputFileProperties()) { + Object value = inputFileProperty.getValue().call(); + if (value != null) { + visitor.visitInputFileProperty(inputFileProperty.getPropertyName(), value); + } + } + } + @Override public ImmutableSortedMap snapshotAfterOutputsGenerated() { final AfterPreviousExecutionState afterPreviousExecutionState = context.getAfterPreviousExecution(); @@ -317,15 +321,13 @@ public ImmutableSortedMap apply(Overla } @Override - public ImmutableMap getInputToPropertyNames() { - Map propertyNameByValue = new HashMap(); - for (InputFilePropertySpec inputFileProperty : context.getTaskProperties().getInputFileProperties()) { - Object value = inputFileProperty.getValue().call(); - if (value != null) { - propertyNameByValue.put(value, inputFileProperty.getPropertyName()); + public boolean isIncremental() { + for (ContextAwareTaskAction taskAction : task.getTaskActions()) { + if (taskAction instanceof AbstractIncrementalTaskAction) { + return true; } } - return ImmutableMap.copyOf(propertyNameByValue); + return false; } @Override @@ -339,12 +341,12 @@ public String getDisplayName() { } } - private void executeActions(TaskInternal task, TaskExecutionContext context) { + private void executeActions(TaskInternal task, @Nullable InputChangesInternal inputChanges) { for (ContextAwareTaskAction action : new ArrayList(task.getTaskActions())) { task.getState().setDidWork(true); task.getStandardOutputCapture().start(); try { - executeAction(action.getDisplayName(), task, action, context); + executeAction(action.getDisplayName(), task, action, inputChanges); } catch (StopActionException e) { // Ignore LOGGER.debug("Action stopped by some action with message: {}", e.getMessage()); @@ -357,8 +359,10 @@ private void executeActions(TaskInternal task, TaskExecutionContext context) { } } - private void executeAction(final String actionDisplayName, final TaskInternal task, final ContextAwareTaskAction action, TaskExecutionContext context) { - action.contextualise(context); + private void executeAction(final String actionDisplayName, final TaskInternal task, final ContextAwareTaskAction action, @Nullable InputChangesInternal inputChanges) { + if (inputChanges != null) { + action.contextualise(inputChanges); + } buildOperationExecutor.run(new RunnableBuildOperation() { @Override public BuildOperationDescriptor.Builder description() { diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuterTest.groovy b/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuterTest.groovy index 3e0b645a7a8b6..b4b70acdb115e 100644 --- a/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuterTest.groovy +++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuterTest.groovy @@ -102,7 +102,6 @@ class ExecuteActionsTaskExecuterTest extends Specification { task.getStandardOutputCapture() >> standardOutputCapture executionContext.getOutputFilesBeforeExecution() >> ImmutableSortedMap.of() executionContext.getOverlappingOutputs() >> Optional.empty() - executionContext.getExecutionStateChanges() >> Optional.empty() executionContext.getTaskExecutionMode() >> TaskExecutionMode.INCREMENTAL executionContext.getBeforeExecutionState() >> Optional.empty() @@ -147,8 +146,6 @@ class ExecuteActionsTaskExecuterTest extends Specification { then: 1 * standardOutputCapture.start() then: - 1 * action1.contextualise(executionContext) - then: 1 * buildOperationExecutor.run(_ as RunnableBuildOperation) >> { args -> args[0].run(Stub(BuildOperationContext)) } then: 1 * action1.execute(task) >> { @@ -163,8 +160,6 @@ class ExecuteActionsTaskExecuterTest extends Specification { then: 1 * standardOutputCapture.start() then: - 1 * action2.contextualise(executionContext) - then: 1 * buildOperationExecutor.run(_ as RunnableBuildOperation) >> { args -> args[0].run(Stub(BuildOperationContext)) } then: 1 * action2.execute(task) @@ -198,8 +193,6 @@ class ExecuteActionsTaskExecuterTest extends Specification { then: 1 * standardOutputCapture.start() - then: - 1 * action1.contextualise(executionContext) then: 1 * buildOperationExecutor.run(_ as RunnableBuildOperation) >> { args -> args[0].run(Stub(BuildOperationContext)) } then: @@ -231,8 +224,6 @@ class ExecuteActionsTaskExecuterTest extends Specification { then: 1 * standardOutputCapture.start() then: - 1 * action1.contextualise(executionContext) - then: 1 * buildOperationExecutor.run(_ as RunnableBuildOperation) >> { args -> args[0].run(Stub(BuildOperationContext)) } then: 1 * action1.releaseContext() @@ -264,8 +255,6 @@ class ExecuteActionsTaskExecuterTest extends Specification { then: 1 * standardOutputCapture.start() then: - 1 * action1.contextualise(executionContext) - then: 1 * action1.execute(task) >> { throw new StopExecutionException('stop') } @@ -295,8 +284,6 @@ class ExecuteActionsTaskExecuterTest extends Specification { then: 1 * standardOutputCapture.start() then: - 1 * action1.contextualise(executionContext) - then: 1 * buildOperationExecutor.run(_ as RunnableBuildOperation) >> { args -> args[0].run(Stub(BuildOperationContext)) } then: 1 * action1.execute(task) >> { @@ -311,8 +298,6 @@ class ExecuteActionsTaskExecuterTest extends Specification { then: 1 * standardOutputCapture.start() then: - 1 * action2.contextualise(executionContext) - then: 1 * buildOperationExecutor.run(_ as RunnableBuildOperation) >> { args -> args[0].run(Stub(BuildOperationContext)) } then: 1 * action2.execute(task) @@ -343,8 +328,6 @@ class ExecuteActionsTaskExecuterTest extends Specification { then: 1 * standardOutputCapture.start() then: - 1 * action1.contextualise(executionContext) - then: 1 * buildOperationExecutor.run(_ as RunnableBuildOperation) >> { args -> args[0].run(Stub(BuildOperationContext)) } then: 1 * action1.releaseContext() @@ -383,8 +366,6 @@ class ExecuteActionsTaskExecuterTest extends Specification { then: 1 * standardOutputCapture.start() then: - 1 * action1.contextualise(executionContext) - then: 1 * buildOperationExecutor.run(_ as RunnableBuildOperation) >> { args -> args[0].run(Stub(BuildOperationContext)) } then: 1 * action1.releaseContext() @@ -422,8 +403,6 @@ class ExecuteActionsTaskExecuterTest extends Specification { then: 1 * standardOutputCapture.start() then: - 1 * action1.contextualise(executionContext) - then: 1 * buildOperationExecutor.run(_ as RunnableBuildOperation) >> { args -> args[0].run(Stub(BuildOperationContext)) } then: 1 * action1.releaseContext() diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvoker.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvoker.java index cd5e1ad311970..28454f913a9cc 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvoker.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvoker.java @@ -17,11 +17,9 @@ package org.gradle.api.internal.artifacts.transform; import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSortedMap; import org.gradle.api.UncheckedIOException; import org.gradle.api.artifacts.component.ProjectComponentIdentifier; -import org.gradle.api.execution.incremental.InputChanges; import org.gradle.api.file.RelativePath; import org.gradle.api.internal.artifacts.dsl.dependencies.ProjectFinder; import org.gradle.api.internal.artifacts.transform.TransformationWorkspaceProvider.TransformationWorkspace; @@ -40,7 +38,7 @@ import org.gradle.internal.execution.history.AfterPreviousExecutionState; import org.gradle.internal.execution.history.BeforeExecutionState; import org.gradle.internal.execution.history.ExecutionHistoryStore; -import org.gradle.internal.execution.history.changes.ExecutionStateChanges; +import org.gradle.internal.execution.history.changes.InputChangesInternal; import org.gradle.internal.execution.history.impl.DefaultBeforeExecutionState; import org.gradle.internal.file.TreeType; import org.gradle.internal.fingerprint.CurrentFileCollectionFingerprint; @@ -261,15 +259,10 @@ public TransformerExecution( } @Override - public ExecutionOutcome execute(Optional changes) { + public ExecutionOutcome execute(@Nullable InputChangesInternal inputChanges) { File outputDir = workspace.getOutputDirectory(); File resultsFile = workspace.getResultsFile(); - @SuppressWarnings("OptionalGetWithoutIsPresent") - InputChanges inputChanges = transformer.isIncremental() - ? changes.get().getInputChanges() - : null; - boolean incremental = inputChanges != null && inputChanges.isIncremental(); if (!incremental) { GFileUtils.cleanDirectory(outputDir); @@ -332,6 +325,11 @@ public Optional getTimeout() { return Optional.empty(); } + @Override + public void visitIncrementalFileInputs(InputFilePropertyVisitor visitor) { + visitor.visitInputFileProperty(INPUT_ARTIFACT_PROPERTY_NAME, inputArtifact); + } + @Override public void visitOutputProperties(OutputPropertyVisitor visitor) { visitor.visitOutputProperty(OUTPUT_DIRECTORY_PROPERTY_NAME, TreeType.DIRECTORY, fileCollectionFactory.fixed(workspace.getOutputDirectory())); @@ -398,8 +396,8 @@ public ImmutableSortedMap snapshotAfte } @Override - public ImmutableMap getInputToPropertyNames() { - return ImmutableMap.of(inputArtifact, INPUT_ARTIFACT_PROPERTY_NAME); + public boolean isIncremental() { + return transformer.isIncremental(); } @Override diff --git a/subprojects/execution/src/integTest/groovy/org/gradle/internal/execution/IncrementalExecutionIntegrationTest.groovy b/subprojects/execution/src/integTest/groovy/org/gradle/internal/execution/IncrementalExecutionIntegrationTest.groovy index 7169bd74c194d..e9635301695b7 100644 --- a/subprojects/execution/src/integTest/groovy/org/gradle/internal/execution/IncrementalExecutionIntegrationTest.groovy +++ b/subprojects/execution/src/integTest/groovy/org/gradle/internal/execution/IncrementalExecutionIntegrationTest.groovy @@ -17,7 +17,6 @@ package org.gradle.internal.execution import com.google.common.collect.ImmutableList -import com.google.common.collect.ImmutableMap import com.google.common.collect.ImmutableSortedMap import com.google.common.collect.Iterables import org.gradle.api.file.FileCollection @@ -31,7 +30,7 @@ import org.gradle.internal.execution.history.BeforeExecutionState import org.gradle.internal.execution.history.ExecutionHistoryStore import org.gradle.internal.execution.history.OutputFilesRepository import org.gradle.internal.execution.history.changes.DefaultExecutionStateChangeDetector -import org.gradle.internal.execution.history.changes.ExecutionStateChanges +import org.gradle.internal.execution.history.changes.InputChangesInternal import org.gradle.internal.execution.history.impl.DefaultBeforeExecutionState import org.gradle.internal.execution.impl.DefaultWorkExecutor import org.gradle.internal.execution.steps.BroadcastChangingOutputsStep @@ -62,6 +61,7 @@ import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider import org.gradle.testing.internal.util.Specification import org.junit.Rule +import javax.annotation.Nullable import java.time.Duration import java.util.function.Supplier @@ -773,7 +773,7 @@ class IncrementalExecutionIntegrationTest extends Specification { boolean executed @Override - ExecutionOutcome execute(Optional changes) { + ExecutionOutcome execute(@Nullable InputChangesInternal inputChanges) { executed = true return work.get() } @@ -799,6 +799,15 @@ class IncrementalExecutionIntegrationTest extends Specification { throw new UnsupportedOperationException() } + @Override + void visitIncrementalFileInputs(UnitOfWork.InputFilePropertyVisitor visitor) { + for (entry in inputs.entrySet()) { + if (entry.value != null) { + visitor.visitInputFileProperty(entry.key, entry.value) + } + } + } + @Override void visitOutputProperties(UnitOfWork.OutputPropertyVisitor visitor) { outputs.forEach { name, spec -> @@ -877,14 +886,8 @@ class IncrementalExecutionIntegrationTest extends Specification { } @Override - ImmutableMap getInputToPropertyNames() { - Map inputToPropertyNames = [:] - for (entry in inputs.entrySet()) { - if (entry.value != null) { - inputToPropertyNames.put(entry.value, entry.key) - } - } - return ImmutableMap.copyOf(inputToPropertyNames) + boolean isIncremental() { + return false } private ImmutableSortedMap snapshotOutputs() { diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/UnitOfWork.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/UnitOfWork.java index 88ad7cbfe716c..109e8d425c62f 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/UnitOfWork.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/UnitOfWork.java @@ -20,23 +20,27 @@ import org.gradle.api.file.FileCollection; import org.gradle.caching.internal.CacheableEntity; import org.gradle.internal.execution.history.ExecutionHistoryStore; -import org.gradle.internal.execution.history.changes.ExecutionStateChanges; -import org.gradle.internal.execution.history.changes.InputToPropertyMapping; +import org.gradle.internal.execution.history.changes.InputChangesInternal; import org.gradle.internal.file.TreeType; import org.gradle.internal.fingerprint.CurrentFileCollectionFingerprint; +import javax.annotation.Nullable; import java.time.Duration; import java.util.Optional; -public interface UnitOfWork extends CacheableEntity, InputToPropertyMapping { +public interface UnitOfWork extends CacheableEntity { /** * Executes the work synchronously. */ - ExecutionOutcome execute(Optional changes); + ExecutionOutcome execute(@Nullable InputChangesInternal inputChanges); Optional getTimeout(); + boolean isIncremental(); + + void visitIncrementalFileInputs(InputFilePropertyVisitor visitor); + void visitOutputProperties(OutputPropertyVisitor visitor); long markExecutionTime(); @@ -65,6 +69,11 @@ public interface UnitOfWork extends CacheableEntity, InputToPropertyMapping { */ boolean isAllowOverlappingOutputs(); + @FunctionalInterface + interface InputFilePropertyVisitor { + void visitInputFileProperty(String name, Object value); + } + @FunctionalInterface interface OutputPropertyVisitor { void visitOutputProperty(String name, TreeType type, FileCollection roots); diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/DefaultExecutionStateChangeDetector.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/DefaultExecutionStateChangeDetector.java index 1de531de27884..5ace1240c0aaf 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/DefaultExecutionStateChangeDetector.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/DefaultExecutionStateChangeDetector.java @@ -16,7 +16,7 @@ package org.gradle.internal.execution.history.changes; -import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableListMultimap; import org.gradle.api.Describable; import org.gradle.internal.change.CachingChangeContainer; import org.gradle.internal.change.ChangeContainer; @@ -29,7 +29,7 @@ public class DefaultExecutionStateChangeDetector implements ExecutionStateChangeDetector { @Override - public ExecutionStateChanges detectChanges(AfterPreviousExecutionState lastExecution, BeforeExecutionState thisExecution, Describable executable, boolean allowOverlappingOutputs, InputToPropertyMapping inputToPropertyMapping) { + public ExecutionStateChanges detectChanges(AfterPreviousExecutionState lastExecution, BeforeExecutionState thisExecution, Describable executable, boolean allowOverlappingOutputs) { // Capture changes in execution outcome ChangeContainer previousSuccessState = new PreviousSuccessChanges( lastExecution.isSuccessful()); @@ -78,9 +78,7 @@ public ExecutionStateChanges detectChanges(AfterPreviousExecutionState lastExecu errorHandling(executable, inputFileChanges), errorHandling(executable, new SummarizingChangeContainer(previousSuccessState, implementationChanges, inputPropertyChanges, inputPropertyValueChanges, outputFilePropertyChanges, outputFileChanges, inputFilePropertyChanges, inputFileChanges)), errorHandling(executable, new SummarizingChangeContainer(previousSuccessState, implementationChanges, inputPropertyChanges, inputPropertyValueChanges, inputFilePropertyChanges, outputFilePropertyChanges, outputFileChanges)), - thisExecution, - executable, - inputToPropertyMapping + thisExecution ); } @@ -127,23 +125,17 @@ private static class DetectedExecutionStateChanges implements ExecutionStateChan private final ChangeContainer allChanges; private final ChangeContainer rebuildTriggeringChanges; private final BeforeExecutionState thisExecution; - private final Describable owner; - private final InputToPropertyMapping inputToPropertyMapping; public DetectedExecutionStateChanges( InputFileChanges inputFileChanges, ChangeContainer allChanges, ChangeContainer rebuildTriggeringChanges, - BeforeExecutionState thisExecution, - Describable owner, - InputToPropertyMapping inputToPropertyMapping + BeforeExecutionState thisExecution ) { this.inputFileChanges = inputFileChanges; this.allChanges = allChanges; this.rebuildTriggeringChanges = rebuildTriggeringChanges; this.thisExecution = thisExecution; - this.owner = owner; - this.inputToPropertyMapping = inputToPropertyMapping; } @Override @@ -152,11 +144,10 @@ public void visitAllChanges(ChangeVisitor visitor) { } @Override - public InputChangesInternal getInputChanges() { - ImmutableMap inputToPropertyNames = inputToPropertyMapping.getInputToPropertyNames(); + public InputChangesInternal getInputChanges(ImmutableListMultimap incrementalInputs) { return isRebuildRequired() - ? new NonIncrementalInputChanges(thisExecution.getInputFileProperties(), inputToPropertyNames, owner) - : new IncrementalInputChanges(inputFileChanges, inputToPropertyNames); + ? new NonIncrementalInputChanges(thisExecution.getInputFileProperties(), incrementalInputs) + : new IncrementalInputChanges(inputFileChanges, incrementalInputs); } private boolean isRebuildRequired() { diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/ExecutionStateChangeDetector.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/ExecutionStateChangeDetector.java index 8ac883be7f939..3afdc307c2313 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/ExecutionStateChangeDetector.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/ExecutionStateChangeDetector.java @@ -27,7 +27,6 @@ ExecutionStateChanges detectChanges( AfterPreviousExecutionState lastExecution, BeforeExecutionState thisExecution, Describable executable, - boolean allowOverlappingOutputs, - InputToPropertyMapping inputToPropertyMapping + boolean allowOverlappingOutputs ); } diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/ExecutionStateChanges.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/ExecutionStateChanges.java index cece1751ef041..547c0c0e332d4 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/ExecutionStateChanges.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/ExecutionStateChanges.java @@ -16,6 +16,7 @@ package org.gradle.internal.execution.history.changes; +import com.google.common.collect.ImmutableListMultimap; import org.gradle.internal.change.ChangeVisitor; /** @@ -28,5 +29,5 @@ public interface ExecutionStateChanges { */ void visitAllChanges(ChangeVisitor visitor); - InputChangesInternal getInputChanges(); + InputChangesInternal getInputChanges(ImmutableListMultimap incrementalInputs); } diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/IncrementalInputChanges.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/IncrementalInputChanges.java index a2452f53f9dcb..3b84d83d71def 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/IncrementalInputChanges.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/IncrementalInputChanges.java @@ -16,21 +16,21 @@ package org.gradle.internal.execution.history.changes; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableListMultimap; import org.gradle.api.tasks.incremental.InputFileDetails; import org.gradle.internal.Cast; import org.gradle.internal.change.Change; import org.gradle.internal.change.CollectingChangeVisitor; -import java.util.Map; - public class IncrementalInputChanges implements InputChangesInternal { private final InputFileChanges changes; - private final Map propertyNameByValue; + private final ImmutableListMultimap propertyNamesByValue; - public IncrementalInputChanges(InputFileChanges changes, Map propertyNameByValue) { + public IncrementalInputChanges(InputFileChanges changes, ImmutableListMultimap propertyNamesByValue) { this.changes = changes; - this.propertyNameByValue = propertyNameByValue; + this.propertyNamesByValue = propertyNamesByValue; } @Override @@ -40,18 +40,21 @@ public boolean isIncremental() { @Override public Iterable getFileChanges(Object property) { - String propertyName = determinePropertyName(property, propertyNameByValue); + String propertyName = determinePropertyName(property, propertyNamesByValue); CollectingChangeVisitor visitor = new CollectingChangeVisitor(); changes.accept(propertyName, visitor); return Cast.uncheckedNonnullCast(visitor.getChanges()); } - public static String determinePropertyName(Object property, Map propertyNameByValue) { - String propertyName = propertyNameByValue.get(property); - if (propertyName == null) { - throw new UnsupportedOperationException("Cannot query incremental changes: No property found for " + property + "."); + public static String determinePropertyName(Object propertyValue, ImmutableListMultimap propertyNameByValue) { + ImmutableList propertyNames = propertyNameByValue.get(propertyValue); + if (propertyNames.isEmpty()) { + throw new UnsupportedOperationException("Cannot query incremental changes: No property found for value " + propertyValue + "."); + } + if (propertyNames.size() > 1) { + throw new UnsupportedOperationException(String.format("Cannot query incremental changes: More that one property found with value %s: %s.", propertyValue, propertyNames)); } - return propertyName; + return propertyNames.get(0); } @Override diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/InputToPropertyMapping.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/InputToPropertyMapping.java deleted file mode 100644 index 28ef6cb0e9b8f..0000000000000 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/InputToPropertyMapping.java +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright 2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.gradle.internal.execution.history.changes; - -import com.google.common.collect.ImmutableMap; - -public interface InputToPropertyMapping { - ImmutableMap getInputToPropertyNames(); - -} diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/NonIncrementalInputChanges.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/NonIncrementalInputChanges.java index 224bffa9b9896..81464602f57f5 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/NonIncrementalInputChanges.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/NonIncrementalInputChanges.java @@ -16,8 +16,8 @@ package org.gradle.internal.execution.history.changes; +import com.google.common.collect.ImmutableListMultimap; import com.google.common.collect.ImmutableSortedMap; -import org.gradle.api.Describable; import org.gradle.api.tasks.incremental.InputFileDetails; import org.gradle.internal.Cast; import org.gradle.internal.change.Change; @@ -27,20 +27,17 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.util.Map; - import static org.gradle.internal.execution.history.changes.IncrementalInputChanges.determinePropertyName; public class NonIncrementalInputChanges implements InputChangesInternal { private static final Logger LOGGER = LoggerFactory.getLogger(NonIncrementalInputChanges.class); private final ImmutableSortedMap currentInputs; - private final Map propertyNameByValue; + private final ImmutableListMultimap propertyNameByValue; - public NonIncrementalInputChanges(ImmutableSortedMap currentInputs, Map propertyNameByValue, Describable owner) { + public NonIncrementalInputChanges(ImmutableSortedMap currentInputs, ImmutableListMultimap propertyNamesByValue) { this.currentInputs = currentInputs; - this.propertyNameByValue = propertyNameByValue; - LOGGER.info("All input files are considered out-of-date for incremental {}.", owner.getDisplayName()); + this.propertyNameByValue = propertyNamesByValue; } @Override diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/ExecuteStep.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/ExecuteStep.java index 6a390639e38e1..58caac49c703d 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/ExecuteStep.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/ExecuteStep.java @@ -16,16 +16,31 @@ package org.gradle.internal.execution.steps; +import com.google.common.collect.ImmutableListMultimap; import org.gradle.internal.Try; import org.gradle.internal.execution.ExecutionOutcome; import org.gradle.internal.execution.IncrementalChangesContext; import org.gradle.internal.execution.Result; import org.gradle.internal.execution.Step; +import org.gradle.internal.execution.UnitOfWork; +import org.gradle.internal.execution.history.changes.ExecutionStateChanges; +import org.gradle.internal.execution.history.changes.InputChangesInternal; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Optional; public class ExecuteStep implements Step { + private static final Logger LOGGER = LoggerFactory.getLogger(ExecuteStep.class); + @Override public Result execute(C context) { - ExecutionOutcome outcome = context.getWork().execute(context.getChanges()); + UnitOfWork work = context.getWork(); + InputChangesInternal inputChanges = work.isIncremental() + ? determineInputChanges(work, context) + : null; + + ExecutionOutcome outcome = work.execute(inputChanges); return new Result() { @Override public Try getOutcome() { @@ -33,4 +48,24 @@ public Try getOutcome() { } }; } + + private InputChangesInternal determineInputChanges(UnitOfWork work, IncrementalChangesContext context) { + Optional changes = context.getChanges(); + if (!changes.isPresent()) { + throw new UnsupportedOperationException("Cannot use input changes when input tracking is disabled."); + } + + ImmutableListMultimap incrementalInputs = determineIncrementalInputs(work); + InputChangesInternal inputChanges = changes.get().getInputChanges(incrementalInputs); + if (!inputChanges.isIncremental()) { + LOGGER.info("All input files are considered out-of-date for incremental {}.", work.getDisplayName()); + } + return inputChanges; + } + + private ImmutableListMultimap determineIncrementalInputs(UnitOfWork work) { + ImmutableListMultimap.Builder builder = ImmutableListMultimap.builder(); + work.visitIncrementalFileInputs((name, value) -> builder.put(value, name)); + return builder.build(); + } } diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/ResolveChangesStep.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/ResolveChangesStep.java index 42edfbd308f6b..fae499f17ff45 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/ResolveChangesStep.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/ResolveChangesStep.java @@ -16,6 +16,7 @@ package org.gradle.internal.execution.steps; +import com.google.common.collect.ImmutableListMultimap; import org.gradle.internal.change.Change; import org.gradle.internal.change.ChangeVisitor; import org.gradle.internal.change.DescriptiveChange; @@ -54,7 +55,7 @@ public R execute(IncrementalContext context) { Optional beforeExecutionState = context.getBeforeExecutionState(); ExecutionStateChanges changes = context.getRebuildReason() .map(rebuildReason -> - new RebuildExecutionStateChanges(new DescriptiveChange(rebuildReason), beforeExecutionState.orElse(null), work) + new RebuildExecutionStateChanges(new DescriptiveChange(rebuildReason), beforeExecutionState.orElse(null)) ) .orElseGet(() -> beforeExecutionState @@ -63,10 +64,9 @@ public R execute(IncrementalContext context) { afterPreviousExecution, beforeExecution, work, - !work.isAllowOverlappingOutputs(), - work) + !work.isAllowOverlappingOutputs()) ) - .orElseGet(() -> new RebuildExecutionStateChanges(NO_HISTORY, beforeExecution, work)) + .orElseGet(() -> new RebuildExecutionStateChanges(NO_HISTORY, beforeExecution)) ) .orElse(null) ); @@ -102,12 +102,10 @@ public UnitOfWork getWork() { private static class RebuildExecutionStateChanges implements ExecutionStateChanges { private final Change rebuildChange; private final BeforeExecutionState beforeExecutionState; - private final UnitOfWork work; - public RebuildExecutionStateChanges(Change rebuildChange, @Nullable BeforeExecutionState beforeExecutionState, UnitOfWork work) { + public RebuildExecutionStateChanges(Change rebuildChange, @Nullable BeforeExecutionState beforeExecutionState) { this.rebuildChange = rebuildChange; this.beforeExecutionState = beforeExecutionState; - this.work = work; } @Override @@ -116,11 +114,11 @@ public void visitAllChanges(ChangeVisitor visitor) { } @Override - public InputChangesInternal getInputChanges() { + public InputChangesInternal getInputChanges(ImmutableListMultimap incrementalInputs) { if (beforeExecutionState == null) { throw new UnsupportedOperationException("Cannot query input changes when input tracking is disabled."); } - return new NonIncrementalInputChanges(beforeExecutionState.getInputFileProperties(), work.getInputToPropertyNames(), work); + return new NonIncrementalInputChanges(beforeExecutionState.getInputFileProperties(), incrementalInputs); } } } diff --git a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/history/changes/ImplementationChangesTest.groovy b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/history/changes/ImplementationChangesTest.groovy index fa178a9c228e9..3dce6153aa8a6 100644 --- a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/history/changes/ImplementationChangesTest.groovy +++ b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/history/changes/ImplementationChangesTest.groovy @@ -22,7 +22,6 @@ import org.gradle.api.Describable import org.gradle.api.Task import org.gradle.api.internal.TaskInternal import org.gradle.api.internal.tasks.ContextAwareTaskAction -import org.gradle.api.internal.tasks.TaskExecutionContext import org.gradle.internal.Cast import org.gradle.internal.change.CollectingChangeVisitor import org.gradle.internal.classloader.ClassLoaderHierarchyHasher @@ -155,7 +154,7 @@ class ImplementationChangesTest extends Specification { private static class TestAction implements ContextAwareTaskAction { @Override - void contextualise(TaskExecutionContext context) { + void contextualise(InputChangesInternal inputChanges) { } @Override diff --git a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/ExecuteStepTest.groovy b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/ExecuteStepTest.groovy index e4a169b54fac3..f0660595c291b 100644 --- a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/ExecuteStepTest.groovy +++ b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/ExecuteStepTest.groovy @@ -16,10 +16,12 @@ package org.gradle.internal.execution.steps +import com.google.common.collect.ImmutableListMultimap import org.gradle.internal.execution.ExecutionOutcome import org.gradle.internal.execution.IncrementalChangesContext import org.gradle.internal.execution.UnitOfWork import org.gradle.internal.execution.history.changes.ExecutionStateChanges +import org.gradle.internal.execution.history.changes.InputChangesInternal import spock.lang.Specification import spock.lang.Unroll @@ -27,7 +29,9 @@ class ExecuteStepTest extends Specification { def step = new ExecuteStep() def context = Mock(IncrementalChangesContext) def work = Mock(UnitOfWork) - def changes = Optional.of(Mock(ExecutionStateChanges)) + def changes = Mock(ExecutionStateChanges) + def optionalChanges = Optional.of(changes) + def inputChanges = Mock(InputChangesInternal) @Unroll def "#outcome outcome is preserved"() { @@ -38,8 +42,8 @@ class ExecuteStepTest extends Specification { result.outcome.get() == outcome 1 * context.work >> work - 1 * context.changes >> changes - 1 * work.execute(changes) >> { outcome } + 1 * work.incremental >> false + 1 * work.execute(null) >> { outcome } 0 * _ where: @@ -56,10 +60,28 @@ class ExecuteStepTest extends Specification { ex == failure 1 * context.work >> work - 1 * context.changes >> changes - 1 * work.execute(changes) >> { throw failure } + 1 * work.incremental >> false + 1 * work.execute(null) >> { throw failure } + 0 * _ where: failure << [new RuntimeException(), new Error()] } + + def "determines input changes for incremental work"() { + when: + step.execute(context) + + then: + 1 * context.work >> work + 1 * work.incremental >> true + 1 * context.changes >> optionalChanges + 1 * work.visitIncrementalFileInputs(_) >> { args -> + ((UnitOfWork.InputFilePropertyVisitor) args[0]).visitInputFileProperty("fileInput", "some/path") + } + 1 * changes.getInputChanges(ImmutableListMultimap.of("some/path", "fileInput")) >> inputChanges + 1 * work.execute(inputChanges) + 1 * inputChanges.incremental >> true + 0 * _ + } } diff --git a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/ResolveChangesStepTest.groovy b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/ResolveChangesStepTest.groovy index a2c03bb531e36..9707fe0d19883 100644 --- a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/ResolveChangesStepTest.groovy +++ b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/ResolveChangesStepTest.groovy @@ -16,7 +16,7 @@ package org.gradle.internal.execution.steps -import com.google.common.collect.ImmutableMap +import com.google.common.collect.ImmutableListMultimap import com.google.common.collect.ImmutableSortedMap import org.gradle.internal.execution.IncrementalChangesContext import org.gradle.internal.execution.IncrementalContext @@ -45,7 +45,7 @@ class ResolveChangesStepTest extends StepSpec { def changes = delegateContext.changes.get() assert getRebuildReason(changes) == "Forced rebuild." try { - changes.getInputChanges() + changes.getInputChanges(ImmutableListMultimap.of()) assert false } catch (UnsupportedOperationException e) { assert e.message == 'Cannot query input changes when input tracking is disabled.' @@ -84,7 +84,7 @@ class ResolveChangesStepTest extends StepSpec { 1 * context.work >> work 1 * delegate.execute(_) >> { IncrementalChangesContext delegateContext -> def changes = delegateContext.changes.get() - assert !changes.getInputChanges().incremental + assert !changes.getInputChanges(ImmutableListMultimap.of()).incremental assert getRebuildReason(changes) == "No history is available." return delegateResult } @@ -92,8 +92,6 @@ class ResolveChangesStepTest extends StepSpec { 1 * context.beforeExecutionState >> Optional.of(beforeExecutionState) 1 * beforeExecutionState.getInputFileProperties() >> ImmutableSortedMap.of() 1 * context.afterPreviousExecutionState >> Optional.empty() - 1 * work.inputToPropertyNames >> ImmutableMap.of() - 1 * work.displayName >> "Some unit of work" 0 * _ } @@ -117,7 +115,7 @@ class ResolveChangesStepTest extends StepSpec { 1 * context.beforeExecutionState >> Optional.of(beforeExecutionState) 1 * context.afterPreviousExecutionState >> Optional.of(afterPreviousExecutionState) 1 * work.allowOverlappingOutputs >> true - 1 * changeDetector.detectChanges(afterPreviousExecutionState, beforeExecutionState, work, false, work) >> changes + 1 * changeDetector.detectChanges(afterPreviousExecutionState, beforeExecutionState, work, false) >> changes 0 * _ } From 0e87c883b2ccdfd24145ae6cbac22ce13386f5d6 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Fri, 8 Mar 2019 17:13:28 +0100 Subject: [PATCH 532/853] Introduce SigningExtension.useInMemoryPgpKeys() This commit adds an alternative signatory provider that works with ascii-armored in-memory PGP keys instead of keyring files. This is often easier to setup on CI servers and more secure because there never is a persistent file that contains the secret key. The user manual is updated with a sample that demonstrates how to pass key and password using environment variables. --- .../src/docs/userguide/signing_plugin.adoc | 13 ++ .../signing/in-memory/groovy/build.gradle | 17 ++ .../signing/in-memory/groovy/settings.gradle | 1 + .../in-memory/groovy/src/stuff/hello.txt | 0 .../signing/in-memory/kotlin/build.gradle.kts | 17 ++ .../in-memory/kotlin/settings.gradle.kts | 1 + .../in-memory/kotlin/src/stuff/hello.txt | 0 ...PgpSignatoryProviderIntegrationSpec.groovy | 206 ++++++++++++++++++ .../plugins/signing/SigningSamplesSpec.groovy | 84 +++++++ .../plugins/signing/SigningExtension.java | 21 ++ .../pgp/InMemoryPgpSignatoryProvider.java | 103 +++++++++ 11 files changed, 463 insertions(+) create mode 100644 subprojects/docs/src/samples/signing/in-memory/groovy/build.gradle create mode 100644 subprojects/docs/src/samples/signing/in-memory/groovy/settings.gradle create mode 100644 subprojects/docs/src/samples/signing/in-memory/groovy/src/stuff/hello.txt create mode 100644 subprojects/docs/src/samples/signing/in-memory/kotlin/build.gradle.kts create mode 100644 subprojects/docs/src/samples/signing/in-memory/kotlin/settings.gradle.kts create mode 100644 subprojects/docs/src/samples/signing/in-memory/kotlin/src/stuff/hello.txt create mode 100644 subprojects/signing/src/integTest/groovy/org/gradle/plugins/signing/InMemoryPgpSignatoryProviderIntegrationSpec.groovy create mode 100644 subprojects/signing/src/main/java/org/gradle/plugins/signing/signatory/internal/pgp/InMemoryPgpSignatoryProvider.java diff --git a/subprojects/docs/src/docs/userguide/signing_plugin.adoc b/subprojects/docs/src/docs/userguide/signing_plugin.adoc index a8a4d7bea91c2..ac11272bdc268 100644 --- a/subprojects/docs/src/docs/userguide/signing_plugin.adoc +++ b/subprojects/docs/src/docs/userguide/signing_plugin.adoc @@ -111,6 +111,19 @@ gradle.taskGraph.whenReady { Note that the presence of a null value for any these three properties will cause an exception. +[[sec:in-memory-keys]] +=== Using in-memory ascii-armored keys + +In some setups it is easier to use environment variables to pass the secret key and password used for signing. +For instance, when using a CI server to sign artifacts, securely providing the keyring file is often troublesome. +On the other hand, most CI servers provide means to securely store environment variables and provide them to builds. +Using the following setup, you can pass the secret key (in ascii-armored format) and the password using the `ORG_GRADLE_PROJECT_signingKey` and `ORG_GRADLE_PROJECT_signingPassword` environment variables, respectively: + +==== +include::sample[dir="signing/in-memory/groovy",files="build.gradle[tags=signing]"] +include::sample[dir="signing/in-memory/kotlin",files="build.gradle.kts[tags=signing]"] +==== + [[sec:subkeys]] === Using OpenPGP subkeys diff --git a/subprojects/docs/src/samples/signing/in-memory/groovy/build.gradle b/subprojects/docs/src/samples/signing/in-memory/groovy/build.gradle new file mode 100644 index 0000000000000..15ee9723fe3ca --- /dev/null +++ b/subprojects/docs/src/samples/signing/in-memory/groovy/build.gradle @@ -0,0 +1,17 @@ +plugins { + id 'signing' +} + +task stuffZip(type: Zip) { + archiveBaseName = 'stuff' + from 'src/stuff' +} + +// tag::signing[] +signing { + def signingKey = findProperty("signingKey") + def signingPassword = findProperty("signingPassword") + useInMemoryPgpKeys(signingKey, signingPassword) + sign stuffZip +} +// end::signing[] diff --git a/subprojects/docs/src/samples/signing/in-memory/groovy/settings.gradle b/subprojects/docs/src/samples/signing/in-memory/groovy/settings.gradle new file mode 100644 index 0000000000000..1466302c71b23 --- /dev/null +++ b/subprojects/docs/src/samples/signing/in-memory/groovy/settings.gradle @@ -0,0 +1 @@ +rootProject.name = 'in-memory' diff --git a/subprojects/docs/src/samples/signing/in-memory/groovy/src/stuff/hello.txt b/subprojects/docs/src/samples/signing/in-memory/groovy/src/stuff/hello.txt new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/subprojects/docs/src/samples/signing/in-memory/kotlin/build.gradle.kts b/subprojects/docs/src/samples/signing/in-memory/kotlin/build.gradle.kts new file mode 100644 index 0000000000000..5363e20381593 --- /dev/null +++ b/subprojects/docs/src/samples/signing/in-memory/kotlin/build.gradle.kts @@ -0,0 +1,17 @@ +plugins { + signing +} + +tasks.register("stuffZip") { + archiveBaseName.set("stuff") + from("src/stuff") +} + +// tag::signing[] +signing { + val signingKey: String? by project + val signingPassword: String? by project + useInMemoryPgpKeys(signingKey, signingPassword) + sign(tasks["stuffZip"]) +} +// end::sign-task[] diff --git a/subprojects/docs/src/samples/signing/in-memory/kotlin/settings.gradle.kts b/subprojects/docs/src/samples/signing/in-memory/kotlin/settings.gradle.kts new file mode 100644 index 0000000000000..32316f96b142c --- /dev/null +++ b/subprojects/docs/src/samples/signing/in-memory/kotlin/settings.gradle.kts @@ -0,0 +1 @@ +rootProject.name = "in-memory" diff --git a/subprojects/docs/src/samples/signing/in-memory/kotlin/src/stuff/hello.txt b/subprojects/docs/src/samples/signing/in-memory/kotlin/src/stuff/hello.txt new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/subprojects/signing/src/integTest/groovy/org/gradle/plugins/signing/InMemoryPgpSignatoryProviderIntegrationSpec.groovy b/subprojects/signing/src/integTest/groovy/org/gradle/plugins/signing/InMemoryPgpSignatoryProviderIntegrationSpec.groovy new file mode 100644 index 0000000000000..ae1bc883e3241 --- /dev/null +++ b/subprojects/signing/src/integTest/groovy/org/gradle/plugins/signing/InMemoryPgpSignatoryProviderIntegrationSpec.groovy @@ -0,0 +1,206 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.gradle.plugins.signing + +class InMemoryPgpSignatoryProviderIntegrationSpec extends SigningIntegrationSpec { + + def "signs with default signatory"() { + given: + buildFile << """ + signing { + useInMemoryPgpKeys(project.properties['secretKey'], project.properties['password']) + sign(jar) + } + """ + + when: + executer.withEnvironmentVars([ + ORG_GRADLE_PROJECT_secretKey: secretKeyWithPassword, + ORG_GRADLE_PROJECT_password: password + ]) + succeeds("signJar") + + then: + executed(":signJar") + file("build", "libs", "sign-1.0.jar.asc").exists() + } + + def "signs with custom signatory"() { + given: + buildFile << """ + signing { + useInMemoryPgpKeys('foo', 'bar') + signatories { + custom(project.properties['secretKey'], project.properties['password']) + } + sign(jar)*.signatory = signatories.custom + } + """ + + when: + executer.withEnvironmentVars([ + ORG_GRADLE_PROJECT_secretKey: secretKeyWithPassword, + ORG_GRADLE_PROJECT_password: password + ]) + succeeds("signJar") + + then: + executed(":signJar") + file("build", "libs", "sign-1.0.jar.asc").exists() + } + + def "supports keys without passwords"() { + given: + buildFile << """ + signing { + useInMemoryPgpKeys(project.properties['secretKey'], '') + sign(jar) + } + """ + + when: + executer.withEnvironmentVars([ + ORG_GRADLE_PROJECT_secretKey: secretKeyWithoutPassword + ]) + succeeds("signJar") + + then: + executed(":signJar") + file("build", "libs", "sign-1.0.jar.asc").exists() + } + + final secretKeyWithPassword = '''\ +-----BEGIN PGP PRIVATE KEY BLOCK----- + +lQPGBFxb6KEBCAC/lBOqM5Qx116XOWIK3vavHF3eSNx9PbCtGZCRiYeB0xbGvKPw +mSg4j2YMxpxOazdeD24KNExvR5EGUdI/4LTqZLiF/o37sY/GDbYdgSrKo99DCbqC +DsX6loXe9tJQGMFXMhm+ILy+YzmzGZD+4JGxn4Dro8zndIkKUP1OgTEUNEl5Y03c +lcpYPg60o57RkFUqSCAw+Pr4w18nyI6yVw3eX48M1fpf7YAsLURtRjKRbWuDumae +YC5zRpK7fYMkCMTEwP0yzvvGPRusFD7BNORWItjAv3O0sGwctAsF1GWCS9aLAD3E +piYYS4UBFgqiAblYokWNmlwbfqmA4SDM4HAFABEBAAH+BwMCsGT03PkwWrPp7rqS +DjnWsKW5dO6L2jT9jNK6kg1/HcvKQWN2olm/PvJrOcLAZ2qX1qxWQhxuq5NubTk8 +h8zUN5weshuqj/9hUsITSb0YyJEb+sXnUU3NTiPZZZlKaLeYyXCWInNk8SOk7mph +pBTv+4JIe2Z3H3Rfkp+UcjCn6+CSry7zLxmb1jYwBlITZwzU55EYl5k6Q48uFwIZ +FD/oSatolB97pC1JzrxV+LTqDicfHYuIjhcFKVhMtUW9ZUbN9jgn1H/kXbkK6zog +CAkkpydTNZZtF/mTy1K0x57KlL097RDGLxOfEuHFXPq+cluRJRlS/sNXfLmswOk7 +p5aHTXst2/NzzL69xc6sgFzDIuJgi48s5QTzqF+VM5k1LjO8qLONIC7c5wveuZsg +BP7OawBYknpXuZtjwRBShp2/JUPtUAjtU8tLHWUrYdd2+0lqtBTGMWEYvzUr3DuH +vaV6Bg5/jAXMDvv4besse799IM8B/BLO5zuzE195+MBGeKyR8k5tgvI7UEmdgOUA +b/lWRldVaCICTLa7BYyjGDmuw7yF/bzYk5kUmdKKnUd3QcyqVr3czJ4meso4YD57 +PQY2JbXXIp33kWaWvAFuSv8g/aCytj/7L4ImIE6kbO1QWlxUQ3pq/XuaRKzqEO07 +ZkoWm0B6fbjh3DrcHAIfdi11H5lgBuYyRUpgJigL4OO04schmI0hfnFhv/T5Ovnd +tu56h7ToP/PpqlnP11IxRk1Nf9pgYezDKq8agLy+2x66si171lzxSzf4mXzg80CH +z8ldMDtBR2G9+4PhguqvygTLHSbBGuu7STzvsQaN2hmtM+RWj1gAch4HlQ2XhZ6y +fDA/fbG2tJnUvEdBoK6uhjSHcct9M79iyaNrxYWCu2PJcIK0ayEFytWNLO0SSmoj +lUeEGJLQ8kahtBlGb28gQmFyIDxmb29AZXhhbXBsZS5jb20+iQFUBBMBCAA+FiEE +QtS6pb0ASq/RhzRI/Urkj6otOZIFAlxb6KECGwMFCQPCZwAFCwkIBwIGFQoJCAsC +BBYCAwECHgECF4AACgkQ/Urkj6otOZJHhAf+MrWpiWDGsu9yW0lbln7FQpXvhNim +mO4aykYcLRnttr4fbbTaTiq1S+Vn/5/zmcfkGnjdCM5RCO/nZA1mcXpg8pmd+emX +SS72owHVDq1we2QD+/WQljUDY4Qdf0AxqPQm+ARGWC2RwgNA6CSH3Q72fE2por5H +FXti3kjq79NRt8OG+iUZ7W00/v//wzVkQw4m3iTjy2G1Ih8tPEkxEjKoNTfXUNMP +TIHLAdo5/mwj/4M1aK3DeSQkdJtkK2RUTUghrOTZus1Gu+5jJjCbjJp7W1Gl5qsZ ++hS68rh4FgGxdo3V8e/dKuXMff0eKEaf8qter8V+32V2esMXr8rJKWT5j50DxgRc +W+ihAQgAwfN8rOSnX0fZ7bbzGulXW8D5qv+y4w5Mel7Us+2jBOB5sGNWikw0agIv +CSjpGnKX2Ucr9uQET46LIH1P1ZV/kxGNme2VEgntVwKn2OcVAQugsPaqpgVihw0S +cUyFtQ/UP1x5SrUk8TNyzI2hXfa1s7qRDl30gsEI3T7bOQEa7vgZcDCYx7dT5YRG +6KpfuoMli7LAA0YqH8aDzAV1bLCEJTgcV1+CsQ9oR0VRXp3EwIBuGvhF5lsUnHXR +lq3G0yY54fysgyOj6+/bzZZiAj2qlJ62nLi7IpQpvwirgkNlHZ4GfyON5hYC0H7M +FSlcvMjcYUxKtwHS5TGmEW1/0/O9xwARAQAB/gcDAn5HnUC9rymY6fiMOrqhGtmF +IPn2VD5paHYHbqgY70hRe+7ufgEPHVLW4AOvcwCX75+iOB9rIclLoXyiX/dRtwlE +Cl8GKGIDP6gRmsDwReROYg+kMyFieFLXZ7pETxgkwJP98ZQwSDNpxsMltdXlvY42 +DrbnZfMPY35Zf+81QKDFqbUSTaZSQpEgNUhkBxPXA68bEvKU565/n7mRRp8tuu2q +PSTzU6uw7NQJEtxiVPswmO2E6n7nZ7E19K3JVW6BYhV+IhFBwN2z72cWUYncJaTa +c/BPPr+WGzTgO1wAwk6+T2wILuAo+nCKQ1RjUCZ4ViRKIv06Aq5LotW+tn572pL9 +Enj/8cZ91YunAAleoInVNOrc6JfIxDtdkZjFhTC+0AA2zH8N4YNfY3CUAQWNEOab +Ysn4On15JZypVAqtWMyCkcWm2pBdMOk2iLiITyZCd7o2wTjz43JzdXE9GFQCBcw1 +ZzN3zPa47/ymRqqYSUKNFYkfhWI6+Hk6mfATBJWiMF8UNv8D1JNPX6S7UM/ZGFGq +tZdXqlayrlC6XBETs6GmQFfyTWRsSqxuax4k3Z+FNoqGUEqwGanw+fob4tfV9xaC +1wN55KbEz47qinBR1f103clRxwneZM/KgSckRF5KzP4hSTgtl+iVZZKqDjvxzenU +1z8/APp8vh64bUaqDXnWui98edgitdYNT/XXUXDBgfDrtbAC+NGP015FMuBc0Mxh +ygMxrdBn3gMKGHGq7T3SdDuc2YC56bQxDdoBbfiG9MtfdOGljjJzr3o3ALgmSj6s +NE3rTIoDXQKhpXMTJdTDPHgcsY6Cjrb7Q92gIuZ8tf3zDvA14ttIkTc/luJIlheu +tWc0Jy0gxbrjSuv5L3iXiG/Abdo3r31dzg7rE5LQK5zR1a8gwUaPHLXrtqPl1Dy/ +y1QVmokBPAQYAQgAJhYhBELUuqW9AEqv0Yc0SP1K5I+qLTmSBQJcW+ihAhsMBQkD +wmcAAAoJEP1K5I+qLTmS3KwH/RXvVUpChQ+c4AnoBiJfiHfrHM18kil2sl8e+Yah +6Q0m0UX3G5kyWkDNK/mIrcrLFj0SSKNudMNwF7XHUZ+NDe+B+i+0BG7mH/VjbTt4 +NJqM6mfUyEECsPtbNXbCyboi06M/BJLnFI05HYIXI3LwnBKrg3Hicd8L+RXujMGH +UtgJrAsMmQXaKEc1oYMq/dgjGfpfbOc2O5Y72dCjMzj5LQkWtw/yEMWFOmPT4YVD +7t3qmbZy2RRhhqtELIYyPYFdz4JuOnNdRkanosYsKdjMssnV6+4YLcOcX7s5VZvY +ZZ8X/eH+PzjPrhshJR+f4lP7gh1k34mWtw9vlnvhQEdUQw8= +=AXAR +-----END PGP PRIVATE KEY BLOCK-----''' + final password = 'foo' + + final secretKeyWithoutPassword = '''\ +-----BEGIN PGP PRIVATE KEY BLOCK----- + +lQOYBFyI758BCACn1dO3pid06f4lGcRrLxEVmVi4jNgJgSAuUlciMV6QiIuM8VZ5 +bq6F04XJDJZgnqFOXlrIK83Rf+MwhIfgu20zCS+E7CsEX1uVE7k+9rN90sA9sPrE +q0TKZFwjWzOrpc1IGwxa+NOUTweiYIRyXV88cqB0xpux+WDU7W1CrqO6FgpXD8f7 +emWbcB/E47KJSN5L9YeQrb65wqhspIfucHTZLaUO5Afl0mlR1mLT2B2ejaRhAWJX +4jXLNGZChCnSGkBfgSu6akCYwrh8quO17s0iKzDF+dNbWji18JDYRAxOj01EM7V/ +CHNYTmRHnor8BiDhSDWL4ztI4E5xcaU8HvWvABEBAAEAB/0eZz3TJuY+56SCVAig +4gXWQ9EunVUFY77QpVnjd84JoLKm9ZEUrlgvJgI2SXF0T0gpSi5n1IeUS/Z784Yp +z8oYVLGnAqFISX3to4ULQuWBBYyNoGHM/rmXcFbAkOTrUz28simq0SiC1U4svA9C +KGf4K0ul29SYiPRhniEM01YVf11Ya42weOCrXIHFNSvIUEuSg05GWOWP3i/Y5CSx +VZvfPJyuxvMMYbGQ0WJCEkbnkm3EqYMdMqCCHyH3fTS4aKt0Q3HTT18mJhlLUP35 +VYBcrIxDWmqgIlbwwS9AQU/XQzsNz0N067G/m4zeo6Cw16y8Kx1quvHu9D+HabPD +NlsBBADBYeI1+qFpe5EuVGG4MWeMnW0iWtu7pquuX6UYFTODS+n1n2aNUPlHmeaZ +SBevsVFwisueVhwNEA90kNS9C9c+RkK65hUzgxhLyAFgXucGTnoFFh2s+wZk2Wih +7i+jKOOBLqcllNpKS1C1gLYmm+05ExsFmcwbL349YYmI87AwAwQA3i5CI69IZkwX +7qR0gENDkGnmONchzF+aFojFhtirwMzosJHpxhFLuG9rlK8wtdJ3xlCIZrVm/B80 +ugEOYqXjAtrR+ad0ZPGr0RL5WxiCDCCyW6VdktP4772mS1jRIYtiQma/8R5LsA1k +6u9DfXcIZacFTdX2xByzLXJhqMUcAeUD/0JpnESj/cj2WsAj4QSOg0qMv1v0A0AQ +0E11tTFu1FsMpVCV9AQx5h3bUbZeDiO00/0o70w17iHciz0nI3si375c0gHsSUyj +paS/5c86gaeFHrTEr0UA1PJqZIHo+tieZ9Gvn8beHKaVDWZZTtnSCCkHc2dGy30J +NDpQLhY28BLwOw+0GVRlc3RpbmcgPHRlc3RAZ3JhZGxlLm9yZz6JAVQEEwEIAD4W +IQR+ADFmwHrj3vOohgOFqMMFox2drAUCXIjvnwIbAwUJA8JnAAULCQgHAgYVCgkI +CwIEFgIDAQIeAQIXgAAKCRCFqMMFox2drPFtB/9K80qF0bmqgT/9HT50oyP7SsdR +K6aof36xSSNpBGhTqSTCzA/u6TZPD9uT3nrBp77uFRAu6y1+Ry9sQt2UWf0R9HWK +PkSkfVF59hrRchBCqCw3HdREVbjQqCT0K/B0EHoOOoZ2IQbvNpvxEBjenENj4o7q +HjpL9LZWmhtJNy9EDDsE8WCMkIdzBng9TQTdPmvfKIjiwjmCtSL4e8MNDIGh8JpP +2p2fnS1DHTyCkbi3uBf65hr9zR+FDv22OhGRJPRv50Wvi4BL2sRusaiyrCubNydt +GXqE8dYOG8pAbNMTbBM7Ncj/wriDENxqDcOFIjXB4ghQMdlncxxKUVgXzPajnQOY +BFyI758BCAC0dNOZ+95havJEHLQMB5bA0wf0Owy4C2h24MAyHk+PKIUuEVsDr/nf +kLRAz+2XeEiitcqYybzDPgIknBgcZcVGaIWVdojHsawm4py/upjG1ZRh4dajjLct +bV9/uijBdIHLCrLeRhyibkMSD3NHebjdxBr72uORc9jC8r98jBLsSDlKC6ayjnPb +fQrc3ujfhpthzXaTv9eanB8uSbUUVJmYb2SxQ2KTyjFt7/UwzO708JKaMjud/4Iw +qhHmUfxeg+xtWkr0Wx/TseNbJfXWPfmA1LSgj1L/AnQ7KkDv8sjLAe3Wv7u3PqTf +irI+e1Jb13GpJ/bWVP+4nE35s7aBMlRjABEBAAEAB/4z6cXz7urPIKqYYJ+FNGuw +hiUsJA6pJZMEW+y+nkyp9PC3S4Pg4C+kmqbYXFjP8ekHcf/aC3MzwbNxH7yp8rcZ +ZblEQajgteK9/wQz/fS0gr3gmM0cGL+boHLQNlhCKwepxyak3gufyNOfrvUtcz11 +AtT2bkZ4UhjiIF5o8I0DDtmo5ThqXjtTrdQMbScs4mp9kjodf55DP7HDhgm7OPdJ +PorA8hhv8vkdg+JzPJzzg8gn+WxPRaAlcZ9j22qiQMF1hc0hnBih6LVHFol/278i +3TDsrrCXlYcW30rlW0+G1+1Jc4p8fC7R5BC8fko9wtNoIJ4G1FK6e60+ATtp4CqZ +BADCE+p8MdzvmIp7tbdo8bZQZy2n1qY2P9GEqLdzPnN5mBaU1DnaCn7D+ME1cal+ +FKkgT5fB4nZEB1ClgZ8GRvJZEKzdBEVwzkBvl4zsFdTkVGYBBG47BlSjl7X6z6Rt +OOaaycqoPPfQUCmrBCbN2yvcnfnEnkSOwBvLWf0qeQXTqQQA7ghTE3BJ6vFDv37M +zTI73orPY/ZGh8uPefN4e2CKBQLvmZPFNWG3Ahm2PAxbmvejNPKWWAWGjHJdB924 +ER/TaFQO9fsX+19XTDaHGZCm57frLyzDvs4kn5u6zZ2015R6DxsmKavQqsdE6Zec +/uyy7QMIeSxt+aWDILimbjnV7ysD/3QRHljpSCYOYO25hrifoER/VJH4RW5i6m5p +D6MBo3FkmIYy94oHdVXaBKqlXieZfaRwzMAmArcgldHYMxTIVX1HDeSd+ya/jAuy +lEZMI5hTXmnUSfPTdLRn265jXxiJNxirZjw/8CFnwVAGDP9jAAnGjc6cl5TJIocy +IcTP7/55RvKJATwEGAEIACYWIQR+ADFmwHrj3vOohgOFqMMFox2drAUCXIjvnwIb +DAUJA8JnAAAKCRCFqMMFox2drBE5B/kBbIQfNrHSqX8DLgpSUsFJVna3/Yp7jTEA +ZfZhbgTorqvCTNyaZs9BNi6jaZ/GdkEv7dt9WMtcdm76r6LTgjpEMFGXQRAyTq9Z +A/4Op5poa+dMHPRj7FvJTX792XRau5iAUTS9N1PeITF+kT1sU/BC5jqCi8dghwEe +5B9Pc6JbQLxVxBHOa8eSg3wi+jUeEHYzWQ9xH6O1PQ4fyAHT31P1VZqEvKB0i02C +5D76SJrUXr6cRi9JE/+/rJ34SM7oZdCVKSyoZbsHIbvdCoW6gRe6vHm6i/sGGAxC +t39qTMnx9LG1EdsZJ1KMUMau1/h15WVWUK10cK7IPSQ2vV+dThEj +=Y8Fu +-----END PGP PRIVATE KEY BLOCK-----''' + +} diff --git a/subprojects/signing/src/integTest/groovy/org/gradle/plugins/signing/SigningSamplesSpec.groovy b/subprojects/signing/src/integTest/groovy/org/gradle/plugins/signing/SigningSamplesSpec.groovy index 931718db632c7..5a1a054aab96e 100644 --- a/subprojects/signing/src/integTest/groovy/org/gradle/plugins/signing/SigningSamplesSpec.groovy +++ b/subprojects/signing/src/integTest/groovy/org/gradle/plugins/signing/SigningSamplesSpec.groovy @@ -138,7 +138,91 @@ class SigningSamplesSpec extends AbstractSampleIntegrationTest { dsl << ['groovy', 'kotlin'] } + @Unroll + @UsesSample('signing/in-memory') + def "uses in-memory PGP keys with dsl #dsl"() { + given: + def projectDir = sample.dir.file(dsl) + inDirectory(projectDir) + + when: + executer.withEnvironmentVars([ + ORG_GRADLE_PROJECT_signingKey: secretKey, + ORG_GRADLE_PROJECT_signingPassword: password + ]) + succeeds("signStuffZip") + + then: + projectDir.file('build/distributions/stuff.zip.asc').exists() + + where: + dsl << ['groovy', 'kotlin'] + } + MavenFileRepository repoFor(String dsl) { return maven(sample.dir.file("$dsl/build/repo")) } + + final secretKey = '''\ +-----BEGIN PGP PRIVATE KEY BLOCK----- + +lQPGBFxb6KEBCAC/lBOqM5Qx116XOWIK3vavHF3eSNx9PbCtGZCRiYeB0xbGvKPw +mSg4j2YMxpxOazdeD24KNExvR5EGUdI/4LTqZLiF/o37sY/GDbYdgSrKo99DCbqC +DsX6loXe9tJQGMFXMhm+ILy+YzmzGZD+4JGxn4Dro8zndIkKUP1OgTEUNEl5Y03c +lcpYPg60o57RkFUqSCAw+Pr4w18nyI6yVw3eX48M1fpf7YAsLURtRjKRbWuDumae +YC5zRpK7fYMkCMTEwP0yzvvGPRusFD7BNORWItjAv3O0sGwctAsF1GWCS9aLAD3E +piYYS4UBFgqiAblYokWNmlwbfqmA4SDM4HAFABEBAAH+BwMCsGT03PkwWrPp7rqS +DjnWsKW5dO6L2jT9jNK6kg1/HcvKQWN2olm/PvJrOcLAZ2qX1qxWQhxuq5NubTk8 +h8zUN5weshuqj/9hUsITSb0YyJEb+sXnUU3NTiPZZZlKaLeYyXCWInNk8SOk7mph +pBTv+4JIe2Z3H3Rfkp+UcjCn6+CSry7zLxmb1jYwBlITZwzU55EYl5k6Q48uFwIZ +FD/oSatolB97pC1JzrxV+LTqDicfHYuIjhcFKVhMtUW9ZUbN9jgn1H/kXbkK6zog +CAkkpydTNZZtF/mTy1K0x57KlL097RDGLxOfEuHFXPq+cluRJRlS/sNXfLmswOk7 +p5aHTXst2/NzzL69xc6sgFzDIuJgi48s5QTzqF+VM5k1LjO8qLONIC7c5wveuZsg +BP7OawBYknpXuZtjwRBShp2/JUPtUAjtU8tLHWUrYdd2+0lqtBTGMWEYvzUr3DuH +vaV6Bg5/jAXMDvv4besse799IM8B/BLO5zuzE195+MBGeKyR8k5tgvI7UEmdgOUA +b/lWRldVaCICTLa7BYyjGDmuw7yF/bzYk5kUmdKKnUd3QcyqVr3czJ4meso4YD57 +PQY2JbXXIp33kWaWvAFuSv8g/aCytj/7L4ImIE6kbO1QWlxUQ3pq/XuaRKzqEO07 +ZkoWm0B6fbjh3DrcHAIfdi11H5lgBuYyRUpgJigL4OO04schmI0hfnFhv/T5Ovnd +tu56h7ToP/PpqlnP11IxRk1Nf9pgYezDKq8agLy+2x66si171lzxSzf4mXzg80CH +z8ldMDtBR2G9+4PhguqvygTLHSbBGuu7STzvsQaN2hmtM+RWj1gAch4HlQ2XhZ6y +fDA/fbG2tJnUvEdBoK6uhjSHcct9M79iyaNrxYWCu2PJcIK0ayEFytWNLO0SSmoj +lUeEGJLQ8kahtBlGb28gQmFyIDxmb29AZXhhbXBsZS5jb20+iQFUBBMBCAA+FiEE +QtS6pb0ASq/RhzRI/Urkj6otOZIFAlxb6KECGwMFCQPCZwAFCwkIBwIGFQoJCAsC +BBYCAwECHgECF4AACgkQ/Urkj6otOZJHhAf+MrWpiWDGsu9yW0lbln7FQpXvhNim +mO4aykYcLRnttr4fbbTaTiq1S+Vn/5/zmcfkGnjdCM5RCO/nZA1mcXpg8pmd+emX +SS72owHVDq1we2QD+/WQljUDY4Qdf0AxqPQm+ARGWC2RwgNA6CSH3Q72fE2por5H +FXti3kjq79NRt8OG+iUZ7W00/v//wzVkQw4m3iTjy2G1Ih8tPEkxEjKoNTfXUNMP +TIHLAdo5/mwj/4M1aK3DeSQkdJtkK2RUTUghrOTZus1Gu+5jJjCbjJp7W1Gl5qsZ ++hS68rh4FgGxdo3V8e/dKuXMff0eKEaf8qter8V+32V2esMXr8rJKWT5j50DxgRc +W+ihAQgAwfN8rOSnX0fZ7bbzGulXW8D5qv+y4w5Mel7Us+2jBOB5sGNWikw0agIv +CSjpGnKX2Ucr9uQET46LIH1P1ZV/kxGNme2VEgntVwKn2OcVAQugsPaqpgVihw0S +cUyFtQ/UP1x5SrUk8TNyzI2hXfa1s7qRDl30gsEI3T7bOQEa7vgZcDCYx7dT5YRG +6KpfuoMli7LAA0YqH8aDzAV1bLCEJTgcV1+CsQ9oR0VRXp3EwIBuGvhF5lsUnHXR +lq3G0yY54fysgyOj6+/bzZZiAj2qlJ62nLi7IpQpvwirgkNlHZ4GfyON5hYC0H7M +FSlcvMjcYUxKtwHS5TGmEW1/0/O9xwARAQAB/gcDAn5HnUC9rymY6fiMOrqhGtmF +IPn2VD5paHYHbqgY70hRe+7ufgEPHVLW4AOvcwCX75+iOB9rIclLoXyiX/dRtwlE +Cl8GKGIDP6gRmsDwReROYg+kMyFieFLXZ7pETxgkwJP98ZQwSDNpxsMltdXlvY42 +DrbnZfMPY35Zf+81QKDFqbUSTaZSQpEgNUhkBxPXA68bEvKU565/n7mRRp8tuu2q +PSTzU6uw7NQJEtxiVPswmO2E6n7nZ7E19K3JVW6BYhV+IhFBwN2z72cWUYncJaTa +c/BPPr+WGzTgO1wAwk6+T2wILuAo+nCKQ1RjUCZ4ViRKIv06Aq5LotW+tn572pL9 +Enj/8cZ91YunAAleoInVNOrc6JfIxDtdkZjFhTC+0AA2zH8N4YNfY3CUAQWNEOab +Ysn4On15JZypVAqtWMyCkcWm2pBdMOk2iLiITyZCd7o2wTjz43JzdXE9GFQCBcw1 +ZzN3zPa47/ymRqqYSUKNFYkfhWI6+Hk6mfATBJWiMF8UNv8D1JNPX6S7UM/ZGFGq +tZdXqlayrlC6XBETs6GmQFfyTWRsSqxuax4k3Z+FNoqGUEqwGanw+fob4tfV9xaC +1wN55KbEz47qinBR1f103clRxwneZM/KgSckRF5KzP4hSTgtl+iVZZKqDjvxzenU +1z8/APp8vh64bUaqDXnWui98edgitdYNT/XXUXDBgfDrtbAC+NGP015FMuBc0Mxh +ygMxrdBn3gMKGHGq7T3SdDuc2YC56bQxDdoBbfiG9MtfdOGljjJzr3o3ALgmSj6s +NE3rTIoDXQKhpXMTJdTDPHgcsY6Cjrb7Q92gIuZ8tf3zDvA14ttIkTc/luJIlheu +tWc0Jy0gxbrjSuv5L3iXiG/Abdo3r31dzg7rE5LQK5zR1a8gwUaPHLXrtqPl1Dy/ +y1QVmokBPAQYAQgAJhYhBELUuqW9AEqv0Yc0SP1K5I+qLTmSBQJcW+ihAhsMBQkD +wmcAAAoJEP1K5I+qLTmS3KwH/RXvVUpChQ+c4AnoBiJfiHfrHM18kil2sl8e+Yah +6Q0m0UX3G5kyWkDNK/mIrcrLFj0SSKNudMNwF7XHUZ+NDe+B+i+0BG7mH/VjbTt4 +NJqM6mfUyEECsPtbNXbCyboi06M/BJLnFI05HYIXI3LwnBKrg3Hicd8L+RXujMGH +UtgJrAsMmQXaKEc1oYMq/dgjGfpfbOc2O5Y72dCjMzj5LQkWtw/yEMWFOmPT4YVD +7t3qmbZy2RRhhqtELIYyPYFdz4JuOnNdRkanosYsKdjMssnV6+4YLcOcX7s5VZvY +ZZ8X/eH+PzjPrhshJR+f4lP7gh1k34mWtw9vlnvhQEdUQw8= +=AXAR +-----END PGP PRIVATE KEY BLOCK-----''' + final password = 'foo' + } diff --git a/subprojects/signing/src/main/java/org/gradle/plugins/signing/SigningExtension.java b/subprojects/signing/src/main/java/org/gradle/plugins/signing/SigningExtension.java index 336c714f73fab..5e8306aa649a2 100644 --- a/subprojects/signing/src/main/java/org/gradle/plugins/signing/SigningExtension.java +++ b/subprojects/signing/src/main/java/org/gradle/plugins/signing/SigningExtension.java @@ -38,12 +38,14 @@ import org.gradle.plugins.signing.signatory.Signatory; import org.gradle.plugins.signing.signatory.SignatoryProvider; import org.gradle.plugins.signing.signatory.internal.gnupg.GnupgSignatoryProvider; +import org.gradle.plugins.signing.signatory.internal.pgp.InMemoryPgpSignatoryProvider; import org.gradle.plugins.signing.signatory.pgp.PgpSignatoryProvider; import org.gradle.plugins.signing.type.DefaultSignatureTypeProvider; import org.gradle.plugins.signing.type.SignatureType; import org.gradle.plugins.signing.type.SignatureTypeProvider; import org.gradle.util.DeferredUtil; +import javax.annotation.Nullable; import java.io.File; import java.util.ArrayList; import java.util.HashMap; @@ -232,6 +234,25 @@ public void useGpgCmd() { setSignatories(new GnupgSignatoryProvider()); } + /** + * Use the supplied ascii-armored in-memory PGP secret key and password + * instead of reading it from a keyring. + * + *

    
    +     * signing {
    +     *     def secretKey = findProperty("mySigningKey")
    +     *     def password = findProperty("mySigningPassword")
    +     *     useInMemoryPgpKeys(secretKey, password)
    +     * }
    +     * 
    + * + * @since 5.4 + */ + @Incubating + public void useInMemoryPgpKeys(@Nullable String defaultSecretKey, @Nullable String defaultPassword) { + setSignatories(new InMemoryPgpSignatoryProvider(defaultSecretKey, defaultPassword)); + } + /** * The configuration that signature artifacts are added to. */ diff --git a/subprojects/signing/src/main/java/org/gradle/plugins/signing/signatory/internal/pgp/InMemoryPgpSignatoryProvider.java b/subprojects/signing/src/main/java/org/gradle/plugins/signing/signatory/internal/pgp/InMemoryPgpSignatoryProvider.java new file mode 100644 index 0000000000000..6cb27ccded55e --- /dev/null +++ b/subprojects/signing/src/main/java/org/gradle/plugins/signing/signatory/internal/pgp/InMemoryPgpSignatoryProvider.java @@ -0,0 +1,103 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.plugins.signing.signatory.internal.pgp; + +import groovy.lang.Closure; +import org.bouncycastle.openpgp.PGPSecretKey; +import org.bouncycastle.openpgp.PGPUtil; +import org.bouncycastle.openpgp.jcajce.JcaPGPSecretKeyRing; +import org.gradle.api.InvalidUserDataException; +import org.gradle.api.Project; +import org.gradle.plugins.signing.SigningExtension; +import org.gradle.plugins.signing.signatory.SignatoryProvider; +import org.gradle.plugins.signing.signatory.pgp.PgpSignatory; +import org.gradle.plugins.signing.signatory.pgp.PgpSignatoryFactory; +import org.gradle.util.ConfigureUtil; + +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.util.Arrays; +import java.util.LinkedHashMap; +import java.util.Map; + +import static java.nio.charset.StandardCharsets.UTF_8; +import static org.codehaus.groovy.runtime.DefaultGroovyMethods.asType; + +/** + * A {@link SignatoryProvider} of {@link PgpSignatory} instances read from + * ascii-armored in-memory secret keys instead of a keyring. + */ +public class InMemoryPgpSignatoryProvider implements SignatoryProvider { + + private final PgpSignatoryFactory factory = new PgpSignatoryFactory(); + private final Map signatories = new LinkedHashMap<>(); + private final String defaultSecretKey; + private final String defaultPassword; + + public InMemoryPgpSignatoryProvider(String defaultSecretKey, String defaultPassword) { + this.defaultSecretKey = defaultSecretKey; + this.defaultPassword = defaultPassword; + } + + @Override + public PgpSignatory getDefaultSignatory(Project project) { + if (defaultSecretKey != null && defaultPassword != null) { + return createSignatory("default", defaultSecretKey, defaultPassword); + } + return null; + } + + @Override + public PgpSignatory getSignatory(String name) { + return signatories.get(name); + } + + @SuppressWarnings("unused") // invoked by Groovy + public PgpSignatory propertyMissing(String signatoryName) { + return getSignatory(signatoryName); + } + + @Override + @SuppressWarnings("rawtypes") + public void configure(SigningExtension settings, Closure closure) { + ConfigureUtil.configure(closure, new Object() { + @SuppressWarnings("unused") // invoked by Groovy + public void methodMissing(String name, Object args) { + createSignatoryFor(name, asType(args, Object[].class)); + } + }); + } + + private void createSignatoryFor(String name, Object[] args) { + if (args.length != 2) { + throw new IllegalArgumentException("Invalid args (" + name + ": " + Arrays.toString(args) + ")"); + } + String secretKey = args[0].toString(); + String password = args[1].toString(); + signatories.put(name, createSignatory(name, secretKey, password)); + } + + private PgpSignatory createSignatory(String name, String secretKey, String password) { + try (InputStream in = PGPUtil.getDecoderStream(new ByteArrayInputStream(secretKey.getBytes(UTF_8)))) { + PGPSecretKey key = new JcaPGPSecretKeyRing(in).getSecretKey(); + return factory.createSignatory(name, key, password); + } catch (Exception e) { + throw new InvalidUserDataException("Could not read PGP secret key", e); + } + } + +} From dec4a3bc68c27b5966e6f9aa800000e3e3b0f269 Mon Sep 17 00:00:00 2001 From: Stefan Wolf Date: Thu, 14 Mar 2019 10:09:57 +0100 Subject: [PATCH 533/853] Eagerly detect change messages That allows us to determine whether or not a rebuild is required more easily. --- .../DefaultExecutionStateChangeDetector.java | 61 +++++++++++++------ .../changes/ExecutionStateChanges.java | 6 +- .../execution/steps/ResolveChangesStep.java | 18 +++--- .../execution/steps/SkipUpToDateStep.java | 25 +------- .../steps/ResolveChangesStepTest.groovy | 11 +--- .../steps/SkipUpToDateStepTest.groovy | 9 +-- 6 files changed, 61 insertions(+), 69 deletions(-) diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/DefaultExecutionStateChangeDetector.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/DefaultExecutionStateChangeDetector.java index 5ace1240c0aaf..5f0005069cced 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/DefaultExecutionStateChangeDetector.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/DefaultExecutionStateChangeDetector.java @@ -16,11 +16,13 @@ package org.gradle.internal.execution.history.changes; +import com.google.common.collect.ImmutableCollection; +import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableListMultimap; import org.gradle.api.Describable; import org.gradle.internal.change.CachingChangeContainer; +import org.gradle.internal.change.Change; import org.gradle.internal.change.ChangeContainer; -import org.gradle.internal.change.ChangeDetectorVisitor; import org.gradle.internal.change.ChangeVisitor; import org.gradle.internal.change.ErrorHandlingChangeContainer; import org.gradle.internal.change.SummarizingChangeContainer; @@ -60,7 +62,7 @@ public ExecutionStateChanges detectChanges(AfterPreviousExecutionState lastExecu InputFileChanges directInputFileChanges = new DefaultInputFileChanges( lastExecution.getInputFileProperties(), thisExecution.getInputFileProperties()); - InputFileChanges inputFileChanges = caching(directInputFileChanges); + InputFileChanges inputFileChanges = errorHandling(executable, caching(directInputFileChanges)); // Capture output files state ChangeContainer outputFilePropertyChanges = new PropertyChanges( @@ -74,10 +76,22 @@ public ExecutionStateChanges detectChanges(AfterPreviousExecutionState lastExecu allowOverlappingOutputs); ChangeContainer outputFileChanges = caching(uncachedOutputChanges); + ChangeContainer rebuildTriggeringChanges = errorHandling(executable, new SummarizingChangeContainer(previousSuccessState, implementationChanges, inputPropertyChanges, inputPropertyValueChanges, outputFilePropertyChanges, outputFileChanges, inputFilePropertyChanges)); + ImmutableList.Builder builder = ImmutableList.builder(); + MessageCollectingChangeVisitor visitor = new MessageCollectingChangeVisitor(builder, ExecutionStateChangeDetector.MAX_OUT_OF_DATE_MESSAGES); + rebuildTriggeringChanges.accept(visitor); + ImmutableList rebuildReasons = builder.build(); + + boolean rebuildRequired = !rebuildReasons.isEmpty(); + + if (!rebuildRequired) { + inputFileChanges.accept(visitor); + } + return new DetectedExecutionStateChanges( - errorHandling(executable, inputFileChanges), - errorHandling(executable, new SummarizingChangeContainer(previousSuccessState, implementationChanges, inputPropertyChanges, inputPropertyValueChanges, outputFilePropertyChanges, outputFileChanges, inputFilePropertyChanges, inputFileChanges)), - errorHandling(executable, new SummarizingChangeContainer(previousSuccessState, implementationChanges, inputPropertyChanges, inputPropertyValueChanges, inputFilePropertyChanges, outputFilePropertyChanges, outputFileChanges)), + inputFileChanges, + builder.build(), + rebuildRequired, thisExecution ); } @@ -122,38 +136,49 @@ public boolean accept(ChangeVisitor visitor) { private static class DetectedExecutionStateChanges implements ExecutionStateChanges { private final InputFileChanges inputFileChanges; - private final ChangeContainer allChanges; - private final ChangeContainer rebuildTriggeringChanges; + private final ImmutableList allChangeMessages; + private final boolean rebuildRequired; private final BeforeExecutionState thisExecution; public DetectedExecutionStateChanges( InputFileChanges inputFileChanges, - ChangeContainer allChanges, - ChangeContainer rebuildTriggeringChanges, + ImmutableList allChangeMessages, + boolean rebuildRequired, BeforeExecutionState thisExecution ) { this.inputFileChanges = inputFileChanges; - this.allChanges = allChanges; - this.rebuildTriggeringChanges = rebuildTriggeringChanges; + this.allChangeMessages = allChangeMessages; + this.rebuildRequired = rebuildRequired; this.thisExecution = thisExecution; } @Override - public void visitAllChanges(ChangeVisitor visitor) { - allChanges.accept(visitor); + public ImmutableList getAllChangeMessages() { + return allChangeMessages; } @Override public InputChangesInternal getInputChanges(ImmutableListMultimap incrementalInputs) { - return isRebuildRequired() + return rebuildRequired ? new NonIncrementalInputChanges(thisExecution.getInputFileProperties(), incrementalInputs) : new IncrementalInputChanges(inputFileChanges, incrementalInputs); } + } - private boolean isRebuildRequired() { - ChangeDetectorVisitor changeDetectorVisitor = new ChangeDetectorVisitor(); - rebuildTriggeringChanges.accept(changeDetectorVisitor); - return changeDetectorVisitor.hasAnyChanges(); + private static class MessageCollectingChangeVisitor implements ChangeVisitor { + private final ImmutableCollection.Builder messages; + private final int max; + private int count; + + public MessageCollectingChangeVisitor(ImmutableCollection.Builder messages, int max) { + this.messages = messages; + this.max = max; + } + + @Override + public boolean visitChange(Change change) { + messages.add(change.getMessage()); + return ++count < max; } } } diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/ExecutionStateChanges.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/ExecutionStateChanges.java index 547c0c0e332d4..b5535ba8f4144 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/ExecutionStateChanges.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/ExecutionStateChanges.java @@ -16,8 +16,8 @@ package org.gradle.internal.execution.history.changes; +import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableListMultimap; -import org.gradle.internal.change.ChangeVisitor; /** * Represents the complete changes in execution state @@ -25,9 +25,9 @@ public interface ExecutionStateChanges { /** - * Visits any change to inputs or outputs. + * Returns all change messages for inputs and outputs. */ - void visitAllChanges(ChangeVisitor visitor); + ImmutableList getAllChangeMessages(); InputChangesInternal getInputChanges(ImmutableListMultimap incrementalInputs); } diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/ResolveChangesStep.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/ResolveChangesStep.java index fae499f17ff45..6ee4c8af8fd9a 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/ResolveChangesStep.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/ResolveChangesStep.java @@ -16,10 +16,8 @@ package org.gradle.internal.execution.steps; +import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableListMultimap; -import org.gradle.internal.change.Change; -import org.gradle.internal.change.ChangeVisitor; -import org.gradle.internal.change.DescriptiveChange; import org.gradle.internal.execution.IncrementalChangesContext; import org.gradle.internal.execution.IncrementalContext; import org.gradle.internal.execution.Result; @@ -37,7 +35,7 @@ public class ResolveChangesStep implements Step { private final ExecutionStateChangeDetector changeDetector; - private static final Change NO_HISTORY = new DescriptiveChange("No history is available."); + private static final String NO_HISTORY = "No history is available."; private final Step delegate; @@ -55,7 +53,7 @@ public R execute(IncrementalContext context) { Optional beforeExecutionState = context.getBeforeExecutionState(); ExecutionStateChanges changes = context.getRebuildReason() .map(rebuildReason -> - new RebuildExecutionStateChanges(new DescriptiveChange(rebuildReason), beforeExecutionState.orElse(null)) + new RebuildExecutionStateChanges(rebuildReason, beforeExecutionState.orElse(null)) ) .orElseGet(() -> beforeExecutionState @@ -100,17 +98,17 @@ public UnitOfWork getWork() { } private static class RebuildExecutionStateChanges implements ExecutionStateChanges { - private final Change rebuildChange; + private final String rebuildReason; private final BeforeExecutionState beforeExecutionState; - public RebuildExecutionStateChanges(Change rebuildChange, @Nullable BeforeExecutionState beforeExecutionState) { - this.rebuildChange = rebuildChange; + public RebuildExecutionStateChanges(String rebuildReason, @Nullable BeforeExecutionState beforeExecutionState) { + this.rebuildReason = rebuildReason; this.beforeExecutionState = beforeExecutionState; } @Override - public void visitAllChanges(ChangeVisitor visitor) { - visitor.visitChange(rebuildChange); + public ImmutableList getAllChangeMessages() { + return ImmutableList.of(rebuildReason); } @Override diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/SkipUpToDateStep.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/SkipUpToDateStep.java index fba313ab5fc30..1fde0ab7084e2 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/SkipUpToDateStep.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/SkipUpToDateStep.java @@ -16,14 +16,11 @@ package org.gradle.internal.execution.steps; -import com.google.common.collect.ImmutableCollection; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSortedMap; import org.apache.commons.lang.StringUtils; import org.gradle.caching.internal.origin.OriginMetadata; import org.gradle.internal.Try; -import org.gradle.internal.change.Change; -import org.gradle.internal.change.ChangeVisitor; import org.gradle.internal.execution.ExecutionOutcome; import org.gradle.internal.execution.IncrementalChangesContext; import org.gradle.internal.execution.SnapshotResult; @@ -55,10 +52,7 @@ public UpToDateResult execute(C context) { LOGGER.debug("Determining if {} is up-to-date", context.getWork().getDisplayName()); } return context.getChanges().map(changes -> { - ImmutableList.Builder builder = ImmutableList.builder(); - MessageCollectingChangeVisitor visitor = new MessageCollectingChangeVisitor(builder, 3); - changes.visitAllChanges(visitor); - ImmutableList reasons = builder.build(); + ImmutableList reasons = changes.getAllChangeMessages(); if (reasons.isEmpty()) { if (LOGGER.isInfoEnabled()) { LOGGER.info("Skipping {} as it is up-to-date.", context.getWork().getDisplayName()); @@ -138,21 +132,4 @@ private void logExecutionReasons(List reasons, UnitOfWork work) { LOGGER.info(formatter.toString()); } } - - private static class MessageCollectingChangeVisitor implements ChangeVisitor { - private final ImmutableCollection.Builder messages; - private final int max; - private int count; - - public MessageCollectingChangeVisitor(ImmutableCollection.Builder messages, int max) { - this.messages = messages; - this.max = max; - } - - @Override - public boolean visitChange(Change change) { - messages.add(change.getMessage()); - return ++count < max; - } - } } diff --git a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/ResolveChangesStepTest.groovy b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/ResolveChangesStepTest.groovy index 9707fe0d19883..3587166c31bfd 100644 --- a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/ResolveChangesStepTest.groovy +++ b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/ResolveChangesStepTest.groovy @@ -16,6 +16,7 @@ package org.gradle.internal.execution.steps +import com.google.common.collect.ImmutableList import com.google.common.collect.ImmutableListMultimap import com.google.common.collect.ImmutableSortedMap import org.gradle.internal.execution.IncrementalChangesContext @@ -43,7 +44,7 @@ class ResolveChangesStepTest extends StepSpec { 1 * context.work >> work 1 * delegate.execute(_) >> { IncrementalChangesContext delegateContext -> def changes = delegateContext.changes.get() - assert getRebuildReason(changes) == "Forced rebuild." + assert changes.getAllChangeMessages() == ImmutableList.of("Forced rebuild.") try { changes.getInputChanges(ImmutableListMultimap.of()) assert false @@ -85,7 +86,7 @@ class ResolveChangesStepTest extends StepSpec { 1 * delegate.execute(_) >> { IncrementalChangesContext delegateContext -> def changes = delegateContext.changes.get() assert !changes.getInputChanges(ImmutableListMultimap.of()).incremental - assert getRebuildReason(changes) == "No history is available." + assert changes.getAllChangeMessages() == ImmutableList.of("No history is available.") return delegateResult } 1 * context.rebuildReason >> Optional.empty() @@ -118,10 +119,4 @@ class ResolveChangesStepTest extends StepSpec { 1 * changeDetector.detectChanges(afterPreviousExecutionState, beforeExecutionState, work, false) >> changes 0 * _ } - - private static String getRebuildReason(ExecutionStateChanges changes) { - String change = null - changes.visitAllChanges({ change = it.message; false }) - return change - } } diff --git a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/SkipUpToDateStepTest.groovy b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/SkipUpToDateStepTest.groovy index 2b8c3d71a284d..1adcd791d28c6 100644 --- a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/SkipUpToDateStepTest.groovy +++ b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/SkipUpToDateStepTest.groovy @@ -16,11 +16,10 @@ package org.gradle.internal.execution.steps +import com.google.common.collect.ImmutableList import com.google.common.collect.ImmutableSortedMap import org.gradle.caching.internal.origin.OriginMetadata import org.gradle.internal.Try -import org.gradle.internal.change.ChangeVisitor -import org.gradle.internal.change.DescriptiveChange import org.gradle.internal.execution.ExecutionOutcome import org.gradle.internal.execution.IncrementalChangesContext import org.gradle.internal.execution.SnapshotResult @@ -43,7 +42,7 @@ class SkipUpToDateStepTest extends StepSpec { result.executionReasons.empty 1 * context.changes >> Optional.of(changes) - 1 * changes.visitAllChanges(_) >> {} + 1 * changes.getAllChangeMessages() >> ImmutableList.of() 1 * context.afterPreviousExecutionState >> Optional.of(Mock(AfterPreviousExecutionState)) 0 * _ } @@ -62,9 +61,7 @@ class SkipUpToDateStepTest extends StepSpec { 1 * context.getWork() >> work 1 * context.changes >> Optional.of(changes) - 1 * changes.visitAllChanges(_) >> { ChangeVisitor visitor -> - visitor.visitChange(new DescriptiveChange("change")) - } + 1 * changes.getAllChangeMessages() >> ImmutableList.of("change") 1 * delegate.execute(context) >> delegateResult 0 * _ From 3a897acd2e45d759232dde359c6d63897d8b9890 Mon Sep 17 00:00:00 2001 From: Stefan Wolf Date: Thu, 14 Mar 2019 11:01:05 +0100 Subject: [PATCH 534/853] Move `InputChanges` to work package --- .../src/main/kotlin/org/gradle/gradlebuild/PublicApi.kt | 1 + .../{api/execution/incremental => work}/InputChanges.java | 2 +- .../{api/execution/incremental => work}/package-info.java | 4 ++-- .../api/tasks/AbstractIncrementalTasksIntegrationTest.groovy | 2 +- .../project/taskfactory/DefaultTaskClassInfoStore.java | 2 +- .../project/taskfactory/IncrementalInputsTaskAction.java | 2 +- .../ArtifactTransformIncrementalIntegrationTest.groovy | 2 +- .../api/internal/artifacts/transform/DefaultTransformer.java | 2 +- .../api/internal/artifacts/transform/LegacyTransformer.java | 2 +- .../gradle/api/internal/artifacts/transform/Transformer.java | 2 +- .../artifacts/transform/DefaultTransformerInvokerTest.groovy | 2 +- .../execution/history/changes/InputChangesInternal.java | 2 +- 12 files changed, 13 insertions(+), 12 deletions(-) rename subprojects/core-api/src/main/java/org/gradle/{api/execution/incremental => work}/InputChanges.java (98%) rename subprojects/core-api/src/main/java/org/gradle/{api/execution/incremental => work}/package-info.java (87%) diff --git a/buildSrc/subprojects/configuration/src/main/kotlin/org/gradle/gradlebuild/PublicApi.kt b/buildSrc/subprojects/configuration/src/main/kotlin/org/gradle/gradlebuild/PublicApi.kt index 34414ee4e54ca..beb3bc22214c6 100644 --- a/buildSrc/subprojects/configuration/src/main/kotlin/org/gradle/gradlebuild/PublicApi.kt +++ b/buildSrc/subprojects/configuration/src/main/kotlin/org/gradle/gradlebuild/PublicApi.kt @@ -33,6 +33,7 @@ object PublicApi { "org/gradle/testkit/**", "org/gradle/testing/**", "org/gradle/vcs/**", + "org/gradle/work/**", "org/gradle/workers/**") val excludes = listOf("**/internal/**") diff --git a/subprojects/core-api/src/main/java/org/gradle/api/execution/incremental/InputChanges.java b/subprojects/core-api/src/main/java/org/gradle/work/InputChanges.java similarity index 98% rename from subprojects/core-api/src/main/java/org/gradle/api/execution/incremental/InputChanges.java rename to subprojects/core-api/src/main/java/org/gradle/work/InputChanges.java index 21b50444c3d60..e62f24eaaf07e 100644 --- a/subprojects/core-api/src/main/java/org/gradle/api/execution/incremental/InputChanges.java +++ b/subprojects/core-api/src/main/java/org/gradle/work/InputChanges.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.gradle.api.execution.incremental; +package org.gradle.work; import org.gradle.api.Incubating; import org.gradle.api.tasks.incremental.InputFileDetails; diff --git a/subprojects/core-api/src/main/java/org/gradle/api/execution/incremental/package-info.java b/subprojects/core-api/src/main/java/org/gradle/work/package-info.java similarity index 87% rename from subprojects/core-api/src/main/java/org/gradle/api/execution/incremental/package-info.java rename to subprojects/core-api/src/main/java/org/gradle/work/package-info.java index 3c492261fba50..e3171b5216419 100644 --- a/subprojects/core-api/src/main/java/org/gradle/api/execution/incremental/package-info.java +++ b/subprojects/core-api/src/main/java/org/gradle/work/package-info.java @@ -15,9 +15,9 @@ */ /** - * Classes for dealing with incremental execution. + * Classes used for implementing units of work. */ @NonNullApi -package org.gradle.api.execution.incremental; +package org.gradle.work; import org.gradle.api.NonNullApi; diff --git a/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/AbstractIncrementalTasksIntegrationTest.groovy b/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/AbstractIncrementalTasksIntegrationTest.groovy index d2be6ba7908d2..c11f9c9f09431 100644 --- a/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/AbstractIncrementalTasksIntegrationTest.groovy +++ b/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/AbstractIncrementalTasksIntegrationTest.groovy @@ -51,7 +51,7 @@ abstract class AbstractIncrementalTasksIntegrationTest extends AbstractIntegrati import org.gradle.api.plugins.* import org.gradle.api.tasks.* import org.gradle.api.tasks.incremental.* - import org.gradle.api.execution.incremental.* + import org.gradle.work.* class BaseIncrementalTask extends DefaultTask { @InputDirectory diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/project/taskfactory/DefaultTaskClassInfoStore.java b/subprojects/core/src/main/java/org/gradle/api/internal/project/taskfactory/DefaultTaskClassInfoStore.java index 7ab6833c353d4..522ea474c03ac 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/project/taskfactory/DefaultTaskClassInfoStore.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/project/taskfactory/DefaultTaskClassInfoStore.java @@ -23,13 +23,13 @@ import org.gradle.api.NonNullApi; import org.gradle.api.Task; import org.gradle.api.Transformer; -import org.gradle.api.execution.incremental.InputChanges; import org.gradle.api.tasks.CacheableTask; import org.gradle.api.tasks.TaskAction; import org.gradle.api.tasks.incremental.IncrementalTaskInputs; import org.gradle.cache.internal.CrossBuildInMemoryCache; import org.gradle.cache.internal.CrossBuildInMemoryCacheFactory; import org.gradle.internal.reflect.Instantiator; +import org.gradle.work.InputChanges; import javax.annotation.Nullable; import java.lang.reflect.Method; diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/project/taskfactory/IncrementalInputsTaskAction.java b/subprojects/core/src/main/java/org/gradle/api/internal/project/taskfactory/IncrementalInputsTaskAction.java index 7ebf7c47a6d22..ba67030eead39 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/project/taskfactory/IncrementalInputsTaskAction.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/project/taskfactory/IncrementalInputsTaskAction.java @@ -17,8 +17,8 @@ package org.gradle.api.internal.project.taskfactory; import org.gradle.api.Task; -import org.gradle.api.execution.incremental.InputChanges; import org.gradle.internal.reflect.JavaMethod; +import org.gradle.work.InputChanges; import java.lang.reflect.Method; diff --git a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformIncrementalIntegrationTest.groovy b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformIncrementalIntegrationTest.groovy index 8173b7f62d6ae..24d094971f1d7 100644 --- a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformIncrementalIntegrationTest.groovy +++ b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformIncrementalIntegrationTest.groovy @@ -33,7 +33,7 @@ class ArtifactTransformIncrementalIntegrationTest extends AbstractDependencyReso import org.gradle.api.tasks.* import org.gradle.api.tasks.incremental.* import org.gradle.api.artifacts.transform.* - import org.gradle.api.execution.incremental.* + import org.gradle.work.* abstract class MakeGreen implements TransformAction { diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformer.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformer.java index bf4da5ab93de3..fe37685377b52 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformer.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformer.java @@ -25,7 +25,6 @@ import org.gradle.api.artifacts.transform.TransformAction; import org.gradle.api.artifacts.transform.TransformParameters; import org.gradle.api.artifacts.transform.VariantTransformConfigurationException; -import org.gradle.api.execution.incremental.InputChanges; import org.gradle.api.file.FileCollection; import org.gradle.api.internal.attributes.ImmutableAttributes; import org.gradle.api.internal.file.FileCollectionFactory; @@ -61,6 +60,7 @@ import org.gradle.internal.snapshot.ValueSnapshot; import org.gradle.internal.snapshot.ValueSnapshotter; import org.gradle.model.internal.type.ModelType; +import org.gradle.work.InputChanges; import javax.annotation.Nullable; import java.io.File; diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/LegacyTransformer.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/LegacyTransformer.java index 518d7fa43d637..1e76b426a559e 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/LegacyTransformer.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/LegacyTransformer.java @@ -19,7 +19,6 @@ import com.google.common.collect.ImmutableList; import org.gradle.api.InvalidUserDataException; import org.gradle.api.artifacts.transform.ArtifactTransform; -import org.gradle.api.execution.incremental.InputChanges; import org.gradle.api.internal.attributes.ImmutableAttributes; import org.gradle.api.internal.tasks.TaskDependencyResolveContext; import org.gradle.api.tasks.FileNormalizer; @@ -33,6 +32,7 @@ import org.gradle.internal.isolation.Isolatable; import org.gradle.internal.isolation.IsolatableFactory; import org.gradle.internal.reflect.Instantiator; +import org.gradle.work.InputChanges; import javax.annotation.Nullable; import java.io.File; diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/Transformer.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/Transformer.java index 1c6e6ba772db9..d167a2e7e9776 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/Transformer.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/Transformer.java @@ -19,12 +19,12 @@ import com.google.common.collect.ImmutableList; import org.gradle.api.Describable; import org.gradle.api.artifacts.transform.ArtifactTransform; -import org.gradle.api.execution.incremental.InputChanges; import org.gradle.api.internal.attributes.ImmutableAttributes; import org.gradle.api.internal.tasks.TaskDependencyContainer; import org.gradle.api.tasks.FileNormalizer; import org.gradle.internal.fingerprint.FileCollectionFingerprinterRegistry; import org.gradle.internal.hash.HashCode; +import org.gradle.work.InputChanges; import javax.annotation.Nullable; import java.io.File; diff --git a/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvokerTest.groovy b/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvokerTest.groovy index 1ad8308d9764d..af54e9eadfcb9 100644 --- a/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvokerTest.groovy +++ b/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvokerTest.groovy @@ -18,7 +18,6 @@ package org.gradle.api.internal.artifacts.transform import com.google.common.collect.ImmutableList import org.gradle.api.artifacts.transform.ArtifactTransform -import org.gradle.api.execution.incremental.InputChanges import org.gradle.api.internal.artifacts.DefaultBuildIdentifier import org.gradle.api.internal.artifacts.DefaultProjectComponentIdentifier import org.gradle.api.internal.artifacts.dsl.dependencies.ProjectFinder @@ -44,6 +43,7 @@ import org.gradle.internal.snapshot.impl.DefaultFileSystemMirror import org.gradle.internal.snapshot.impl.DefaultFileSystemSnapshotter import org.gradle.test.fixtures.AbstractProjectBuilderSpec import org.gradle.util.Path +import org.gradle.work.InputChanges import spock.lang.Unroll import java.util.function.BiFunction diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/InputChangesInternal.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/InputChangesInternal.java index 42eb3158b117c..a0bc15b2ab833 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/InputChangesInternal.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/InputChangesInternal.java @@ -16,8 +16,8 @@ package org.gradle.internal.execution.history.changes; -import org.gradle.api.execution.incremental.InputChanges; import org.gradle.internal.change.Change; +import org.gradle.work.InputChanges; public interface InputChangesInternal extends InputChanges { Iterable getAllFileChanges(); From dc11c83f64ed1b3f484b9082f322a87a92abcef5 Mon Sep 17 00:00:00 2001 From: Stefan Wolf Date: Thu, 14 Mar 2019 11:35:53 +0100 Subject: [PATCH 535/853] Remove LOGGER --- .../history/changes/NonIncrementalInputChanges.java | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/NonIncrementalInputChanges.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/NonIncrementalInputChanges.java index 81464602f57f5..9e2ec73a072f4 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/NonIncrementalInputChanges.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/NonIncrementalInputChanges.java @@ -24,14 +24,11 @@ import org.gradle.internal.change.CollectingChangeVisitor; import org.gradle.internal.fingerprint.CurrentFileCollectionFingerprint; import org.gradle.internal.fingerprint.FileCollectionFingerprint; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import org.gradle.work.FileChange; import static org.gradle.internal.execution.history.changes.IncrementalInputChanges.determinePropertyName; public class NonIncrementalInputChanges implements InputChangesInternal { - private static final Logger LOGGER = LoggerFactory.getLogger(NonIncrementalInputChanges.class); - private final ImmutableSortedMap currentInputs; private final ImmutableListMultimap propertyNameByValue; From f6400df9e50a6d1625a1ae00ad761806f1d242d9 Mon Sep 17 00:00:00 2001 From: Stefan Wolf Date: Thu, 14 Mar 2019 11:48:51 +0100 Subject: [PATCH 536/853] Introduce FileChange in public API This replaces `InputFileDetails` from the old incremental task API. --- .../main/java/org/gradle/work/ChangeType.java | 31 ++++++++++++ .../main/java/org/gradle/work/FileChange.java | 40 ++++++++++++++++ .../java/org/gradle/work/InputChanges.java | 35 +++++++------- ...ractIncrementalTasksIntegrationTest.groovy | 4 +- .../IncrementalInputsIntegrationTest.groovy | 14 +++--- ...ncrementalTaskInputsIntegrationTest.groovy | 6 +-- .../impl/ClasspathCompareStrategy.java | 8 ++-- ...spathFingerprintCompareStrategyTest.groovy | 8 ++-- ...TransformIncrementalIntegrationTest.groovy | 22 +++++---- .../changes/IncrementalInputChanges.java | 6 +-- .../changes/NonIncrementalInputChanges.java | 5 +- .../recomp/RecompilationSpecProvider.java | 8 ++-- ...hangeType.java => ChangeTypeInternal.java} | 18 +++++-- ...FileChange.java => DefaultFileChange.java} | 47 +++++++++++-------- ...bsolutePathFingerprintCompareStrategy.java | 8 ++-- .../AbstractFingerprintCompareStrategy.java | 12 ++--- ...EmptyCurrentFileCollectionFingerprint.java | 4 +- .../fingerprint/impl/FilePathWithType.java | 4 +- .../impl/IgnoredPathCompareStrategy.java | 6 +-- ...malizedPathFingerprintCompareStrategy.java | 8 ++-- ...st.groovy => DefaultFileChangeTest.groovy} | 14 +++--- ...PathFileCollectionFingerprinterTest.groovy | 12 ++--- ...urrentFileCollectionFingerprintTest.groovy | 6 +-- .../FingerprintCompareStrategyTest.groovy | 8 ++-- 24 files changed, 214 insertions(+), 120 deletions(-) create mode 100644 subprojects/core-api/src/main/java/org/gradle/work/ChangeType.java create mode 100644 subprojects/core-api/src/main/java/org/gradle/work/FileChange.java rename subprojects/snapshots/src/main/java/org/gradle/internal/change/{ChangeType.java => ChangeTypeInternal.java} (64%) rename subprojects/snapshots/src/main/java/org/gradle/internal/change/{FileChange.java => DefaultFileChange.java} (59%) rename subprojects/snapshots/src/test/groovy/org/gradle/internal/change/{FileChangeTest.groovy => DefaultFileChangeTest.groovy} (72%) diff --git a/subprojects/core-api/src/main/java/org/gradle/work/ChangeType.java b/subprojects/core-api/src/main/java/org/gradle/work/ChangeType.java new file mode 100644 index 0000000000000..5082372681dff --- /dev/null +++ b/subprojects/core-api/src/main/java/org/gradle/work/ChangeType.java @@ -0,0 +1,31 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.work; + +import org.gradle.api.Incubating; + +/** + * The type of change for e.g. an input file. + * + * @since 5.4 + */ +@Incubating +public enum ChangeType { + ADDED, + MODIFIED, + REMOVED +} diff --git a/subprojects/core-api/src/main/java/org/gradle/work/FileChange.java b/subprojects/core-api/src/main/java/org/gradle/work/FileChange.java new file mode 100644 index 0000000000000..e5df3b423f847 --- /dev/null +++ b/subprojects/core-api/src/main/java/org/gradle/work/FileChange.java @@ -0,0 +1,40 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.work; + +import org.gradle.api.Incubating; + +import java.io.File; + +/** + * A change to a file. + * + * @since 5.4 + */ +@Incubating +public interface FileChange { + + /** + * The file, which may no longer exist. + */ + File getFile(); + + /** + * The type of change to the file. + */ + ChangeType getChangeType(); +} diff --git a/subprojects/core-api/src/main/java/org/gradle/work/InputChanges.java b/subprojects/core-api/src/main/java/org/gradle/work/InputChanges.java index e62f24eaaf07e..d6d76aa37ed91 100644 --- a/subprojects/core-api/src/main/java/org/gradle/work/InputChanges.java +++ b/subprojects/core-api/src/main/java/org/gradle/work/InputChanges.java @@ -17,14 +17,13 @@ package org.gradle.work; import org.gradle.api.Incubating; -import org.gradle.api.tasks.incremental.InputFileDetails; /** * Provides access to any input files that need to be processed by an incremental work action. * *

    * An incremental work action is one that accepts a single {@link InputChanges} parameter. - * The work action can then query what changed for an input property since the last execution to only process the changes. + * The work action can then query what changed for an input parameter since the last execution to only process the changes. * *

      * class IncrementalReverseTask extends DefaultTask {
    @@ -41,14 +40,16 @@
      *         }
      *
      *         inputChanges.getFileChanges(inputDir).each { change ->
    - *             if (change.removed) {
    - *                 def targetFile = project.file("$outputDir/${change.file.name}")
    - *                 if (targetFile.exists()) {
    - *                     targetFile.delete()
    - *                 }
    - *             } else {
    - *                 def targetFile = project.file("$outputDir/${change.file.name}")
    - *                 targetFile.text = change.file.text.reverse()
    + *             switch (change.changeType) {
    + *                 case REMOVED:
    + *                     def targetFile = project.file("$outputDir/${change.file.name}")
    + *                     if (targetFile.exists()) {
    + *                         targetFile.delete()
    + *                     }
    + *                     break
    + *                 default:
    + *                     def targetFile = project.file("$outputDir/${change.file.name}")
    + *                     targetFile.text = change.file.text.reverse()
      *             }
      *         }
      *     }
    @@ -56,11 +57,11 @@
      * 
    * *

    - * In the case where Gradle is unable to determine which input files need to be reprocessed, then all of the input files will be reported as added. + * In the case where Gradle is unable to determine which input files need to be reprocessed, then all of the input files will be reported as {@link ChangeType#ADDED}. * Cases where this occurs include: *

      *
    • There is no history available from a previous execution.
    • - *
    • A non-file input property has changed since the previous execution.
    • + *
    • A non-file input parameter has changed since the previous execution.
    • *
    • One or more output files have changed since the previous execution.
    • *
    * @@ -81,17 +82,17 @@ public interface InputChanges { * When false: *

    *
      - *
    • Every input file is reported via {@link #getFileChanges(Object)} as if it was 'added'.
    • + *
    • Every input file is reported via {@link #getFileChanges(Object)} as if it was {@link ChangeType#ADDED}.
    • *
    */ boolean isIncremental(); /** - * Changes for the property. + * Changes for a parameter. * - *

    When {@link #isIncremental()} is {@code false}, then all elements of the property are returned as added.

    + *

    When {@link #isIncremental()} is {@code false}, then all elements of the parameter are returned as {@link ChangeType#ADDED}.

    * - * @param property The instance of the property to query. + * @param parameterValue The value of the parameter to query. */ - Iterable getFileChanges(Object property); + Iterable getFileChanges(Object parameterValue); } diff --git a/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/AbstractIncrementalTasksIntegrationTest.groovy b/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/AbstractIncrementalTasksIntegrationTest.groovy index c11f9c9f09431..27d8ac1c4c96f 100644 --- a/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/AbstractIncrementalTasksIntegrationTest.groovy +++ b/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/AbstractIncrementalTasksIntegrationTest.groovy @@ -17,7 +17,7 @@ package org.gradle.api.tasks import org.gradle.integtests.fixtures.AbstractIntegrationSpec -import org.gradle.internal.change.ChangeType +import org.gradle.internal.change.ChangeTypeInternal import spock.lang.Issue import spock.lang.Unroll @@ -25,7 +25,7 @@ abstract class AbstractIncrementalTasksIntegrationTest extends AbstractIntegrati abstract String getTaskAction() - abstract ChangeType getRebuildChangeType(); + abstract ChangeTypeInternal getRebuildChangeType(); def "setup"() { setupTaskSources() diff --git a/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/IncrementalInputsIntegrationTest.groovy b/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/IncrementalInputsIntegrationTest.groovy index 16e10cf278263..2f17e59eecff8 100644 --- a/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/IncrementalInputsIntegrationTest.groovy +++ b/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/IncrementalInputsIntegrationTest.groovy @@ -16,7 +16,7 @@ package org.gradle.api.tasks -import org.gradle.internal.change.ChangeType +import org.gradle.internal.change.ChangeTypeInternal class IncrementalInputsIntegrationTest extends AbstractIncrementalTasksIntegrationTest { @@ -32,14 +32,14 @@ class IncrementalInputsIntegrationTest extends AbstractIncrementalTasksIntegrati incrementalExecution = inputChanges.incremental inputChanges.getFileChanges(inputDir).each { change -> - switch (change) { - case { it.added }: + switch (change.changeType) { + case ChangeType.ADDED: addedFiles << change.file break - case { it.modified }: + case ChangeType.MODIFIED: modifiedFiles << change.file break - case { it.removed }: + case ChangeType.REMOVED: removedFiles << change.file break default: @@ -57,8 +57,8 @@ class IncrementalInputsIntegrationTest extends AbstractIncrementalTasksIntegrati } @Override - ChangeType getRebuildChangeType() { - return ChangeType.ADDED + ChangeTypeInternal getRebuildChangeType() { + return ChangeTypeInternal.ADDED } def "incremental task is executed non-incrementally when input file property has been added"() { diff --git a/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/IncrementalTaskInputsIntegrationTest.groovy b/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/IncrementalTaskInputsIntegrationTest.groovy index 79e3c79ed08d9..19f1c599f3ed1 100644 --- a/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/IncrementalTaskInputsIntegrationTest.groovy +++ b/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/IncrementalTaskInputsIntegrationTest.groovy @@ -16,7 +16,7 @@ package org.gradle.api.tasks -import org.gradle.internal.change.ChangeType +import org.gradle.internal.change.ChangeTypeInternal class IncrementalTaskInputsIntegrationTest extends AbstractIncrementalTasksIntegrationTest { @@ -53,8 +53,8 @@ class IncrementalTaskInputsIntegrationTest extends AbstractIncrementalTasksInteg } @Override - ChangeType getRebuildChangeType() { - ChangeType.MODIFIED + ChangeTypeInternal getRebuildChangeType() { + ChangeTypeInternal.MODIFIED } def "incremental task is executed non-incrementally when input file property has been added"() { diff --git a/subprojects/core/src/main/java/org/gradle/internal/fingerprint/classpath/impl/ClasspathCompareStrategy.java b/subprojects/core/src/main/java/org/gradle/internal/fingerprint/classpath/impl/ClasspathCompareStrategy.java index 96abe290abec2..d9ab2345dd56f 100644 --- a/subprojects/core/src/main/java/org/gradle/internal/fingerprint/classpath/impl/ClasspathCompareStrategy.java +++ b/subprojects/core/src/main/java/org/gradle/internal/fingerprint/classpath/impl/ClasspathCompareStrategy.java @@ -18,7 +18,7 @@ import org.gradle.internal.change.Change; import org.gradle.internal.change.ChangeVisitor; -import org.gradle.internal.change.FileChange; +import org.gradle.internal.change.DefaultFileChange; import org.gradle.internal.fingerprint.FileCollectionFingerprint; import org.gradle.internal.fingerprint.FileSystemLocationFingerprint; import org.gradle.internal.fingerprint.FingerprintCompareStrategy; @@ -137,18 +137,18 @@ void processChange() { void added() { if (includeAdded) { - changeConsumer.visitChange(FileChange.added(current.getKey(), propertyTitle, current.getValue().getType())); + changeConsumer.visitChange(DefaultFileChange.added(current.getKey(), propertyTitle, current.getValue().getType())); } current = nextEntry(currentEntries); } void removed() { - changeConsumer.visitChange(FileChange.removed(previous.getKey(), propertyTitle, previous.getValue().getType())); + changeConsumer.visitChange(DefaultFileChange.removed(previous.getKey(), propertyTitle, previous.getValue().getType())); previous = nextEntry(previousEntries); } void modified() { - changeConsumer.visitChange(FileChange.modified(current.getKey(), propertyTitle, previous.getValue().getType(), current.getValue().getType())); + changeConsumer.visitChange(DefaultFileChange.modified(current.getKey(), propertyTitle, previous.getValue().getType(), current.getValue().getType())); previous = nextEntry(previousEntries); current = nextEntry(currentEntries); } diff --git a/subprojects/core/src/test/groovy/org/gradle/internal/fingerprint/classpath/impl/ClasspathFingerprintCompareStrategyTest.groovy b/subprojects/core/src/test/groovy/org/gradle/internal/fingerprint/classpath/impl/ClasspathFingerprintCompareStrategyTest.groovy index d524ee5890881..036b77ef13680 100644 --- a/subprojects/core/src/test/groovy/org/gradle/internal/fingerprint/classpath/impl/ClasspathFingerprintCompareStrategyTest.groovy +++ b/subprojects/core/src/test/groovy/org/gradle/internal/fingerprint/classpath/impl/ClasspathFingerprintCompareStrategyTest.groovy @@ -17,7 +17,7 @@ package org.gradle.internal.fingerprint.classpath.impl import org.gradle.internal.change.CollectingChangeVisitor -import org.gradle.internal.change.FileChange +import org.gradle.internal.change.DefaultFileChange import org.gradle.internal.file.FileType import org.gradle.internal.fingerprint.FileSystemLocationFingerprint import org.gradle.internal.fingerprint.FingerprintCompareStrategy @@ -251,14 +251,14 @@ class ClasspathFingerprintCompareStrategyTest extends Specification { } def added(String path) { - FileChange.added(path, "test", FileType.RegularFile) + DefaultFileChange.added(path, "test", FileType.RegularFile) } def removed(String path) { - FileChange.removed(path, "test", FileType.RegularFile) + DefaultFileChange.removed(path, "test", FileType.RegularFile) } def modified(String path, FileType previous = FileType.RegularFile, FileType current = FileType.RegularFile) { - FileChange.modified(path, "test", previous, current) + DefaultFileChange.modified(path, "test", previous, current) } } diff --git a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformIncrementalIntegrationTest.groovy b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformIncrementalIntegrationTest.groovy index 24d094971f1d7..8caa7842a86a5 100644 --- a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformIncrementalIntegrationTest.groovy +++ b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformIncrementalIntegrationTest.groovy @@ -62,18 +62,24 @@ class ArtifactTransformIncrementalIntegrationTest extends AbstractDependencyReso assert parameters.incrementalExecution.get() == inputChanges.incremental def changes = inputChanges.getFileChanges(input) println "changes: \\n" + changes.join("\\n") - assert changes.findAll { it.added }*.file as Set == resolveFiles(parameters.addedFiles.get()) - assert changes.findAll { it.removed }*.file as Set == resolveFiles(parameters.removedFiles.get()) - assert changes.findAll { it.modified }*.file as Set == resolveFiles(parameters.modifiedFiles.get()) + assert changes.findAll { it.changeType == ChangeType.ADDED }*.file as Set == resolveFiles(parameters.addedFiles.get()) + assert changes.findAll { it.changeType == ChangeType.REMOVED }*.file as Set == resolveFiles(parameters.removedFiles.get()) + assert changes.findAll { it.changeType == ChangeType.MODIFIED }*.file as Set == resolveFiles(parameters.modifiedFiles.get()) def outputDirectory = outputs.dir("output") changes.each { change -> if (change.file != input) { File outputFile = new File(outputDirectory, change.file.name) - if (change.added || change.modified) { - outputFile.text = change.file.text - } else { - outputFile.delete() - } + switch (change.changeType) { + case ChangeType.ADDED: + case ChangeType.MODIFIED: + outputFile.text = change.file.text + break + case ChangeType.REMOVED: + outputFile.delete() + break + default: + throw new IllegalArgumentException() + } } } } diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/IncrementalInputChanges.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/IncrementalInputChanges.java index 3b84d83d71def..0b34b85561838 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/IncrementalInputChanges.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/IncrementalInputChanges.java @@ -18,10 +18,10 @@ import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableListMultimap; -import org.gradle.api.tasks.incremental.InputFileDetails; import org.gradle.internal.Cast; import org.gradle.internal.change.Change; import org.gradle.internal.change.CollectingChangeVisitor; +import org.gradle.work.FileChange; public class IncrementalInputChanges implements InputChangesInternal { @@ -39,8 +39,8 @@ public boolean isIncremental() { } @Override - public Iterable getFileChanges(Object property) { - String propertyName = determinePropertyName(property, propertyNamesByValue); + public Iterable getFileChanges(Object parameterValue) { + String propertyName = determinePropertyName(parameterValue, propertyNamesByValue); CollectingChangeVisitor visitor = new CollectingChangeVisitor(); changes.accept(propertyName, visitor); return Cast.uncheckedNonnullCast(visitor.getChanges()); diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/NonIncrementalInputChanges.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/NonIncrementalInputChanges.java index 9e2ec73a072f4..41785fba4ab38 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/NonIncrementalInputChanges.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/NonIncrementalInputChanges.java @@ -18,7 +18,6 @@ import com.google.common.collect.ImmutableListMultimap; import com.google.common.collect.ImmutableSortedMap; -import org.gradle.api.tasks.incremental.InputFileDetails; import org.gradle.internal.Cast; import org.gradle.internal.change.Change; import org.gradle.internal.change.CollectingChangeVisitor; @@ -43,9 +42,9 @@ public boolean isIncremental() { } @Override - public Iterable getFileChanges(Object property) { + public Iterable getFileChanges(Object parameterValue) { CollectingChangeVisitor visitor = new CollectingChangeVisitor(); - CurrentFileCollectionFingerprint currentFileCollectionFingerprint = currentInputs.get(determinePropertyName(property, propertyNameByValue)); + CurrentFileCollectionFingerprint currentFileCollectionFingerprint = currentInputs.get(determinePropertyName(parameterValue, propertyNameByValue)); visitAllFileChanges(currentFileCollectionFingerprint, visitor); return Cast.uncheckedNonnullCast(visitor.getChanges()); } diff --git a/subprojects/language-java/src/main/java/org/gradle/api/internal/tasks/compile/incremental/recomp/RecompilationSpecProvider.java b/subprojects/language-java/src/main/java/org/gradle/api/internal/tasks/compile/incremental/recomp/RecompilationSpecProvider.java index 2e5978d8d7d8e..f66e45d249f1a 100644 --- a/subprojects/language-java/src/main/java/org/gradle/api/internal/tasks/compile/incremental/recomp/RecompilationSpecProvider.java +++ b/subprojects/language-java/src/main/java/org/gradle/api/internal/tasks/compile/incremental/recomp/RecompilationSpecProvider.java @@ -18,7 +18,7 @@ import org.gradle.api.internal.tasks.compile.incremental.classpath.ClasspathEntrySnapshot; import org.gradle.api.internal.tasks.compile.incremental.classpath.ClasspathSnapshot; -import org.gradle.internal.change.FileChange; +import org.gradle.internal.change.DefaultFileChange; import org.gradle.internal.file.FileType; import org.gradle.internal.util.Alignment; @@ -52,10 +52,10 @@ private void processClasspathChanges(CurrentCompilation current, PreviousCompila for (Alignment fileAlignment : alignment) { switch (fileAlignment.getKind()) { case added: - classpathEntryChangeProcessor.processChange(FileChange.added(fileAlignment.getCurrentValue().getAbsolutePath(), "classpathEntry", FileType.RegularFile), spec); + classpathEntryChangeProcessor.processChange(DefaultFileChange.added(fileAlignment.getCurrentValue().getAbsolutePath(), "classpathEntry", FileType.RegularFile), spec); break; case removed: - classpathEntryChangeProcessor.processChange(FileChange.removed(fileAlignment.getPreviousValue().getAbsolutePath(), "classpathEntry", FileType.RegularFile), spec); + classpathEntryChangeProcessor.processChange(DefaultFileChange.removed(fileAlignment.getPreviousValue().getAbsolutePath(), "classpathEntry", FileType.RegularFile), spec); break; case transformed: // If we detect a transformation in the classpath, we need to recompile, because we could typically be facing the case where @@ -67,7 +67,7 @@ private void processClasspathChanges(CurrentCompilation current, PreviousCompila ClasspathEntrySnapshot previousSnapshot = previous.getClasspathEntrySnapshot(key); ClasspathEntrySnapshot snapshot = currentSnapshots.getSnapshot(key); if (previousSnapshot == null || !snapshot.getHash().equals(previousSnapshot.getHash())) { - classpathEntryChangeProcessor.processChange(FileChange.modified(key.getAbsolutePath(), "classpathEntry", FileType.RegularFile, FileType.RegularFile), spec); + classpathEntryChangeProcessor.processChange(DefaultFileChange.modified(key.getAbsolutePath(), "classpathEntry", FileType.RegularFile, FileType.RegularFile), spec); } break; } diff --git a/subprojects/snapshots/src/main/java/org/gradle/internal/change/ChangeType.java b/subprojects/snapshots/src/main/java/org/gradle/internal/change/ChangeTypeInternal.java similarity index 64% rename from subprojects/snapshots/src/main/java/org/gradle/internal/change/ChangeType.java rename to subprojects/snapshots/src/main/java/org/gradle/internal/change/ChangeTypeInternal.java index 76a876a8212aa..3e45417582111 100644 --- a/subprojects/snapshots/src/main/java/org/gradle/internal/change/ChangeType.java +++ b/subprojects/snapshots/src/main/java/org/gradle/internal/change/ChangeTypeInternal.java @@ -16,18 +16,26 @@ package org.gradle.internal.change; -public enum ChangeType { - ADDED("has been added"), - MODIFIED("has changed"), - REMOVED("has been removed"); +import org.gradle.work.ChangeType; + +public enum ChangeTypeInternal { + ADDED("has been added", ChangeType.ADDED), + MODIFIED("has changed", ChangeType.MODIFIED), + REMOVED("has been removed", ChangeType.REMOVED); private final String description; + private final ChangeType publicType; - ChangeType(String description) { + ChangeTypeInternal(String description, ChangeType publicType) { this.description = description; + this.publicType = publicType; } public String describe() { return description; } + + public ChangeType getPublicType() { + return publicType; + } } diff --git a/subprojects/snapshots/src/main/java/org/gradle/internal/change/FileChange.java b/subprojects/snapshots/src/main/java/org/gradle/internal/change/DefaultFileChange.java similarity index 59% rename from subprojects/snapshots/src/main/java/org/gradle/internal/change/FileChange.java rename to subprojects/snapshots/src/main/java/org/gradle/internal/change/DefaultFileChange.java index 063d84319732a..aa88d1e192cbc 100644 --- a/subprojects/snapshots/src/main/java/org/gradle/internal/change/FileChange.java +++ b/subprojects/snapshots/src/main/java/org/gradle/internal/change/DefaultFileChange.java @@ -19,29 +19,31 @@ import com.google.common.base.Objects; import org.gradle.api.tasks.incremental.InputFileDetails; import org.gradle.internal.file.FileType; +import org.gradle.work.ChangeType; +import org.gradle.work.FileChange; import java.io.File; -public class FileChange implements Change, InputFileDetails { +public class DefaultFileChange implements Change, FileChange, InputFileDetails { private final String path; - private final ChangeType change; + private final ChangeTypeInternal change; private final String title; private final FileType previousFileType; private final FileType currentFileType; - public static FileChange added(String path, String title, FileType currentFileType) { - return new FileChange(path, ChangeType.ADDED, title, FileType.Missing, currentFileType); + public static DefaultFileChange added(String path, String title, FileType currentFileType) { + return new DefaultFileChange(path, ChangeTypeInternal.ADDED, title, FileType.Missing, currentFileType); } - public static FileChange removed(String path, String title, FileType previousFileType) { - return new FileChange(path, ChangeType.REMOVED, title, previousFileType, FileType.Missing); + public static DefaultFileChange removed(String path, String title, FileType previousFileType) { + return new DefaultFileChange(path, ChangeTypeInternal.REMOVED, title, previousFileType, FileType.Missing); } - public static FileChange modified(String path, String title, FileType previousFileType, FileType currentFileType) { - return new FileChange(path, ChangeType.MODIFIED, title, previousFileType, currentFileType); + public static DefaultFileChange modified(String path, String title, FileType previousFileType, FileType currentFileType) { + return new DefaultFileChange(path, ChangeTypeInternal.MODIFIED, title, previousFileType, currentFileType); } - private FileChange(String path, ChangeType change, String title, FileType previousFileType, FileType currentFileType) { + private DefaultFileChange(String path, ChangeTypeInternal change, String title, FileType previousFileType, FileType currentFileType) { this.path = path; this.change = change; this.title = title; @@ -54,17 +56,17 @@ public String getMessage() { return title + " file " + path + " " + getDisplayedChangeType().describe() + "."; } - private ChangeType getDisplayedChangeType() { - if (change != ChangeType.MODIFIED) { + private ChangeTypeInternal getDisplayedChangeType() { + if (change != ChangeTypeInternal.MODIFIED) { return change; } if (previousFileType == FileType.Missing) { - return ChangeType.ADDED; + return ChangeTypeInternal.ADDED; } if (currentFileType == FileType.Missing) { - return ChangeType.REMOVED; + return ChangeTypeInternal.REMOVED; } - return ChangeType.MODIFIED; + return ChangeTypeInternal.MODIFIED; } @Override @@ -81,23 +83,30 @@ public File getFile() { return new File(path); } - public ChangeType getType() { + @Override + public ChangeType getChangeType() { + // TODO wolfs: Shall we do something about file type Missing -> File + // should this be file type ADDED instead of MODIFIED + return change.getPublicType(); + } + + public ChangeTypeInternal getType() { return change; } @Override public boolean isAdded() { - return change == ChangeType.ADDED; + return change == ChangeTypeInternal.ADDED; } @Override public boolean isModified() { - return change == ChangeType.MODIFIED; + return change == ChangeTypeInternal.MODIFIED; } @Override public boolean isRemoved() { - return change == ChangeType.REMOVED; + return change == ChangeTypeInternal.REMOVED; } @Override @@ -108,7 +117,7 @@ public boolean equals(Object o) { if (o == null || getClass() != o.getClass()) { return false; } - FileChange that = (FileChange) o; + DefaultFileChange that = (DefaultFileChange) o; return Objects.equal(path, that.path) && change == that.change && Objects.equal(title, that.title) diff --git a/subprojects/snapshots/src/main/java/org/gradle/internal/fingerprint/impl/AbsolutePathFingerprintCompareStrategy.java b/subprojects/snapshots/src/main/java/org/gradle/internal/fingerprint/impl/AbsolutePathFingerprintCompareStrategy.java index 63ab8ba48cb48..74be319899259 100644 --- a/subprojects/snapshots/src/main/java/org/gradle/internal/fingerprint/impl/AbsolutePathFingerprintCompareStrategy.java +++ b/subprojects/snapshots/src/main/java/org/gradle/internal/fingerprint/impl/AbsolutePathFingerprintCompareStrategy.java @@ -17,7 +17,7 @@ package org.gradle.internal.fingerprint.impl; import org.gradle.internal.change.ChangeVisitor; -import org.gradle.internal.change.FileChange; +import org.gradle.internal.change.DefaultFileChange; import org.gradle.internal.fingerprint.FileSystemLocationFingerprint; import org.gradle.internal.fingerprint.FingerprintCompareStrategy; import org.gradle.internal.hash.HashCode; @@ -50,20 +50,20 @@ protected boolean doVisitChangesSince(ChangeVisitor visitor, Map entry : previous.entrySet()) { - Change change = FileChange.removed(entry.getKey(), propertyTitle, entry.getValue().getType()); + Change change = DefaultFileChange.removed(entry.getKey(), propertyTitle, entry.getValue().getType()); if (!visitor.visitChange(change)) { return false; } @@ -89,7 +89,7 @@ static Boolean compareTrivialFingerprints(ChangeVisitor visitor, Map current, String propertyTitle, boolean includeAdded) { if (includeAdded) { for (Map.Entry entry : current.entrySet()) { - Change change = FileChange.added(entry.getKey(), propertyTitle, entry.getValue().getType()); + Change change = DefaultFileChange.added(entry.getKey(), propertyTitle, entry.getValue().getType()); if (!visitor.visitChange(change)) { return false; } @@ -106,16 +106,16 @@ private static boolean compareTrivialFingerprintEntries(ChangeVisitor visitor, M HashCode currentContent = currentFingerprint.getNormalizedContentHash(); if (!currentContent.equals(previousContent)) { String path = currentEntry.getKey(); - Change change = FileChange.modified(path, propertyTitle, previousFingerprint.getType(), currentFingerprint.getType()); + Change change = DefaultFileChange.modified(path, propertyTitle, previousFingerprint.getType(), currentFingerprint.getType()); return visitor.visitChange(change); } return true; } else { String previousPath = previousEntry.getKey(); - Change remove = FileChange.removed(previousPath, propertyTitle, previousFingerprint.getType()); + Change remove = DefaultFileChange.removed(previousPath, propertyTitle, previousFingerprint.getType()); if (includeAdded) { String currentPath = currentEntry.getKey(); - Change add = FileChange.added(currentPath, propertyTitle, currentFingerprint.getType()); + Change add = DefaultFileChange.added(currentPath, propertyTitle, currentFingerprint.getType()); return visitor.visitChange(remove) && visitor.visitChange(add); } else { return visitor.visitChange(remove); diff --git a/subprojects/snapshots/src/main/java/org/gradle/internal/fingerprint/impl/EmptyCurrentFileCollectionFingerprint.java b/subprojects/snapshots/src/main/java/org/gradle/internal/fingerprint/impl/EmptyCurrentFileCollectionFingerprint.java index d7094c1a5dad5..2803080b25f90 100644 --- a/subprojects/snapshots/src/main/java/org/gradle/internal/fingerprint/impl/EmptyCurrentFileCollectionFingerprint.java +++ b/subprojects/snapshots/src/main/java/org/gradle/internal/fingerprint/impl/EmptyCurrentFileCollectionFingerprint.java @@ -18,7 +18,7 @@ import com.google.common.collect.ImmutableMultimap; import org.gradle.internal.change.ChangeVisitor; -import org.gradle.internal.change.FileChange; +import org.gradle.internal.change.DefaultFileChange; import org.gradle.internal.fingerprint.CurrentFileCollectionFingerprint; import org.gradle.internal.fingerprint.FileCollectionFingerprint; import org.gradle.internal.fingerprint.FileSystemLocationFingerprint; @@ -42,7 +42,7 @@ public EmptyCurrentFileCollectionFingerprint(String identifier) { @Override public boolean visitChangesSince(FileCollectionFingerprint oldFingerprint, final String title, boolean includeAdded, ChangeVisitor visitor) { for (Map.Entry entry : oldFingerprint.getFingerprints().entrySet()) { - if (!visitor.visitChange(FileChange.removed(entry.getKey(), title, entry.getValue().getType()))) { + if (!visitor.visitChange(DefaultFileChange.removed(entry.getKey(), title, entry.getValue().getType()))) { return false; } } diff --git a/subprojects/snapshots/src/main/java/org/gradle/internal/fingerprint/impl/FilePathWithType.java b/subprojects/snapshots/src/main/java/org/gradle/internal/fingerprint/impl/FilePathWithType.java index de48ce6bd1349..75749e4feb048 100644 --- a/subprojects/snapshots/src/main/java/org/gradle/internal/fingerprint/impl/FilePathWithType.java +++ b/subprojects/snapshots/src/main/java/org/gradle/internal/fingerprint/impl/FilePathWithType.java @@ -16,13 +16,13 @@ package org.gradle.internal.fingerprint.impl; -import org.gradle.internal.change.FileChange; +import org.gradle.internal.change.DefaultFileChange; import org.gradle.internal.file.FileType; /** * The absolute path and the type of a file. * - * Used to construct {@link FileChange}s. + * Used to construct {@link DefaultFileChange}s. */ public class FilePathWithType { private final String absolutePath; diff --git a/subprojects/snapshots/src/main/java/org/gradle/internal/fingerprint/impl/IgnoredPathCompareStrategy.java b/subprojects/snapshots/src/main/java/org/gradle/internal/fingerprint/impl/IgnoredPathCompareStrategy.java index d1ec386d7a1b5..a11cb37ec1cd2 100644 --- a/subprojects/snapshots/src/main/java/org/gradle/internal/fingerprint/impl/IgnoredPathCompareStrategy.java +++ b/subprojects/snapshots/src/main/java/org/gradle/internal/fingerprint/impl/IgnoredPathCompareStrategy.java @@ -20,7 +20,7 @@ import com.google.common.collect.Lists; import com.google.common.collect.MultimapBuilder; import org.gradle.internal.change.ChangeVisitor; -import org.gradle.internal.change.FileChange; +import org.gradle.internal.change.DefaultFileChange; import org.gradle.internal.fingerprint.FileCollectionFingerprint; import org.gradle.internal.fingerprint.FileSystemLocationFingerprint; import org.gradle.internal.fingerprint.FingerprintCompareStrategy; @@ -74,7 +74,7 @@ protected boolean doVisitChangesSince(ChangeVisitor visitor, Map previousFilesForContent = unaccountedForPreviousFiles.get(normalizedContentHash); if (previousFilesForContent.isEmpty()) { if (includeAdded) { - if (!visitor.visitChange(FileChange.added(currentAbsolutePath, propertyTitle, currentFingerprint.getType()))) { + if (!visitor.visitChange(DefaultFileChange.added(currentAbsolutePath, propertyTitle, currentFingerprint.getType()))) { return false; } } @@ -87,7 +87,7 @@ protected boolean doVisitChangesSince(ChangeVisitor visitor, Map unaccountedForPreviousEntry : unaccountedForPreviousEntries) { FilePathWithType removedFile = unaccountedForPreviousEntry.getValue(); - if (!visitor.visitChange(FileChange.removed(removedFile.getAbsolutePath(), propertyTitle, removedFile.getFileType()))) { + if (!visitor.visitChange(DefaultFileChange.removed(removedFile.getAbsolutePath(), propertyTitle, removedFile.getFileType()))) { return false; } } diff --git a/subprojects/snapshots/src/main/java/org/gradle/internal/fingerprint/impl/NormalizedPathFingerprintCompareStrategy.java b/subprojects/snapshots/src/main/java/org/gradle/internal/fingerprint/impl/NormalizedPathFingerprintCompareStrategy.java index 489310073ee6e..f7f532d23f696 100644 --- a/subprojects/snapshots/src/main/java/org/gradle/internal/fingerprint/impl/NormalizedPathFingerprintCompareStrategy.java +++ b/subprojects/snapshots/src/main/java/org/gradle/internal/fingerprint/impl/NormalizedPathFingerprintCompareStrategy.java @@ -20,7 +20,7 @@ import com.google.common.collect.Lists; import com.google.common.collect.MultimapBuilder; import org.gradle.internal.change.ChangeVisitor; -import org.gradle.internal.change.FileChange; +import org.gradle.internal.change.DefaultFileChange; import org.gradle.internal.fingerprint.FileSystemLocationFingerprint; import org.gradle.internal.fingerprint.FingerprintCompareStrategy; import org.gradle.internal.hash.Hasher; @@ -88,12 +88,12 @@ protected boolean doVisitChangesSince(ChangeVisitor visitor, Map listener) { - newFingerprint.visitChangesSince(oldFingerprint, "TYPE", true) { FileChange change -> + newFingerprint.visitChangesSince(oldFingerprint, "TYPE", true) { DefaultFileChange change -> switch (change.type) { - case ChangeType.ADDED: + case ChangeTypeInternal.ADDED: listener.added(change.path) break - case ChangeType.MODIFIED: + case ChangeTypeInternal.MODIFIED: listener.changed(change.path) break - case ChangeType.REMOVED: + case ChangeTypeInternal.REMOVED: listener.removed(change.path) break } diff --git a/subprojects/snapshots/src/test/groovy/org/gradle/internal/fingerprint/impl/EmptyCurrentFileCollectionFingerprintTest.groovy b/subprojects/snapshots/src/test/groovy/org/gradle/internal/fingerprint/impl/EmptyCurrentFileCollectionFingerprintTest.groovy index 6b374650f3ff8..955045e3698bb 100644 --- a/subprojects/snapshots/src/test/groovy/org/gradle/internal/fingerprint/impl/EmptyCurrentFileCollectionFingerprintTest.groovy +++ b/subprojects/snapshots/src/test/groovy/org/gradle/internal/fingerprint/impl/EmptyCurrentFileCollectionFingerprintTest.groovy @@ -19,7 +19,7 @@ package org.gradle.internal.fingerprint.impl import com.google.common.collect.ImmutableMultimap import org.gradle.internal.change.Change import org.gradle.internal.change.CollectingChangeVisitor -import org.gradle.internal.change.FileChange +import org.gradle.internal.change.DefaultFileChange import org.gradle.internal.file.FileType import org.gradle.internal.fingerprint.CurrentFileCollectionFingerprint import org.gradle.internal.fingerprint.FileCollectionFingerprint @@ -42,8 +42,8 @@ class EmptyCurrentFileCollectionFingerprintTest extends Specification { } expect: getChanges(fingerprint, empty, includeAdded).toList() == [ - FileChange.removed("file1.txt", "test", FileType.RegularFile), - FileChange.removed("file2.txt", "test", FileType.RegularFile) + DefaultFileChange.removed("file1.txt", "test", FileType.RegularFile), + DefaultFileChange.removed("file2.txt", "test", FileType.RegularFile) ] where: diff --git a/subprojects/snapshots/src/test/groovy/org/gradle/internal/fingerprint/impl/FingerprintCompareStrategyTest.groovy b/subprojects/snapshots/src/test/groovy/org/gradle/internal/fingerprint/impl/FingerprintCompareStrategyTest.groovy index 5c3ba518b8fdd..8264cb96b0d6c 100644 --- a/subprojects/snapshots/src/test/groovy/org/gradle/internal/fingerprint/impl/FingerprintCompareStrategyTest.groovy +++ b/subprojects/snapshots/src/test/groovy/org/gradle/internal/fingerprint/impl/FingerprintCompareStrategyTest.groovy @@ -17,7 +17,7 @@ package org.gradle.internal.fingerprint.impl import org.gradle.internal.change.CollectingChangeVisitor -import org.gradle.internal.change.FileChange +import org.gradle.internal.change.DefaultFileChange import org.gradle.internal.file.FileType import org.gradle.internal.fingerprint.FileSystemLocationFingerprint import org.gradle.internal.fingerprint.FingerprintCompareStrategy @@ -294,14 +294,14 @@ class FingerprintCompareStrategyTest extends Specification { } def added(String path) { - FileChange.added(path, "test", FileType.RegularFile) + DefaultFileChange.added(path, "test", FileType.RegularFile) } def removed(String path) { - FileChange.removed(path, "test", FileType.RegularFile) + DefaultFileChange.removed(path, "test", FileType.RegularFile) } def modified(String path, FileType previous, FileType current) { - FileChange.modified(path, "test", previous, current) + DefaultFileChange.modified(path, "test", previous, current) } } From 73c794c88ba784d040b0a92be0770d7fcc0c2e50 Mon Sep 17 00:00:00 2001 From: Gary Hale Date: Tue, 12 Mar 2019 14:12:01 -0400 Subject: [PATCH 537/853] Disable reset of temp file for JDK12 --- .../NativeServicesIntegrationTest.groovy | 3 + .../executer/InProcessGradleExecuter.java | 7 -- .../org/gradle/util/SetSystemProperties.java | 35 --------- .../org/gradle/util/TestPrecondition.groovy | 3 + .../util/SetSystemPropertiesTest.groovy | 78 ------------------- 5 files changed, 6 insertions(+), 120 deletions(-) delete mode 100644 subprojects/internal-testing/src/test/groovy/org/gradle/util/SetSystemPropertiesTest.groovy diff --git a/subprojects/core/src/integTest/groovy/org/gradle/NativeServicesIntegrationTest.groovy b/subprojects/core/src/integTest/groovy/org/gradle/NativeServicesIntegrationTest.groovy index e2eeca1cb9d7b..41bac1f3f454e 100644 --- a/subprojects/core/src/integTest/groovy/org/gradle/NativeServicesIntegrationTest.groovy +++ b/subprojects/core/src/integTest/groovy/org/gradle/NativeServicesIntegrationTest.groovy @@ -17,9 +17,11 @@ package org.gradle import org.gradle.integtests.fixtures.AbstractIntegrationSpec +import org.gradle.integtests.fixtures.executer.GradleContextualExecuter import org.gradle.internal.nativeintegration.jansi.JansiStorageLocator import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider import org.junit.Rule +import spock.lang.IgnoreIf import spock.lang.Issue class NativeServicesIntegrationTest extends AbstractIntegrationSpec { @@ -50,6 +52,7 @@ class NativeServicesIntegrationTest extends AbstractIntegrationSpec { } @Issue("GRADLE-3573") + @IgnoreIf({ GradleContextualExecuter.embedded }) def "jansi library is unpacked to gradle user home dir and isn't overwritten if existing"() { String tmpDirJvmOpt = "-Djava.io.tmpdir=$tmpDir.testDirectory.absolutePath" executer.withBuildJvmOpts(tmpDirJvmOpt) diff --git a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/InProcessGradleExecuter.java b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/InProcessGradleExecuter.java index e5bb1eff18471..592c4ad6d670a 100755 --- a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/InProcessGradleExecuter.java +++ b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/InProcessGradleExecuter.java @@ -77,7 +77,6 @@ import org.gradle.util.DeprecationLogger; import org.gradle.util.GUtil; import org.gradle.util.GradleVersion; -import org.gradle.util.SetSystemProperties; import org.hamcrest.Matcher; import java.io.ByteArrayOutputStream; @@ -295,7 +294,6 @@ private BuildResult doRun(OutputStream outputStream, OutputStream errorStream, B } finally { // Restore the environment System.setProperties(originalSysProperties); - resetTempDirLocation(); processEnvironment.maybeSetProcessDir(originalUserDir); for (String envVar : changedEnvVars) { String oldValue = originalEnv.get(envVar); @@ -310,10 +308,6 @@ private BuildResult doRun(OutputStream outputStream, OutputStream errorStream, B } } - private void resetTempDirLocation() { - SetSystemProperties.resetTempDirLocation(); - } - private LoggingManagerInternal createLoggingManager(StartParameter startParameter, OutputStream outputStream, OutputStream errorStream) { LoggingManagerInternal loggingManager = GLOBAL_SERVICES.getFactory(LoggingManagerInternal.class).create(); loggingManager.captureSystemSources(); @@ -338,7 +332,6 @@ private BuildResult executeBuild(GradleInvocation invocation, OutputStream outpu } Map implicitJvmSystemProperties = getImplicitJvmSystemProperties(); System.getProperties().putAll(implicitJvmSystemProperties); - resetTempDirLocation(); // TODO: Fix tests that rely on this being set before we process arguments like this... StartParameterInternal startParameter = new StartParameterInternal(); diff --git a/subprojects/internal-testing/src/main/groovy/org/gradle/util/SetSystemProperties.java b/subprojects/internal-testing/src/main/groovy/org/gradle/util/SetSystemProperties.java index 6b5b644daeb39..ba05206d97164 100644 --- a/subprojects/internal-testing/src/main/groovy/org/gradle/util/SetSystemProperties.java +++ b/subprojects/internal-testing/src/main/groovy/org/gradle/util/SetSystemProperties.java @@ -19,12 +19,7 @@ import org.junit.rules.TestRule; import org.junit.runner.Description; import org.junit.runners.model.Statement; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import java.io.File; -import java.lang.reflect.Field; -import java.lang.reflect.Modifier; import java.util.HashMap; import java.util.Map; import java.util.Properties; @@ -33,7 +28,6 @@ * A JUnit rule which restores system properties at the end of the test. */ public class SetSystemProperties implements TestRule { - private final static Logger LOGGER = LoggerFactory.getLogger(SetSystemProperties.class); private final Properties properties; private final Map customProperties = new HashMap(); @@ -53,41 +47,12 @@ public Statement apply(final Statement base, Description description) { @Override public void evaluate() throws Throwable { System.getProperties().putAll(customProperties); - resetTempDirLocation(); try { base.evaluate(); } finally { System.setProperties(properties); - resetTempDirLocation(); } } }; } - - public static void resetTempDirLocation() { - File tmpdirFile = new File(System.getProperty("java.io.tmpdir")); - // reset cache in File.createTempFile - try { - Field tmpdirField = Class.forName("java.io.File$TempDirectory").getDeclaredField("tmpdir"); - makeFinalFieldAccessible(tmpdirField); - tmpdirField.set(null, tmpdirFile); - } catch (Exception e) { - LOGGER.warn("Cannot reset tmpdir field used by java.io.File.createTempFile"); - } - // reset cache in Files.createTempFile - try { - Field tmpdirField = Class.forName("java.nio.file.TempFileHelper").getDeclaredField("tmpdir"); - makeFinalFieldAccessible(tmpdirField); - tmpdirField.set(null, tmpdirFile.toPath()); - } catch (Exception e) { - LOGGER.warn("Cannot reset tmpdir field used by java.nio.file.Files.createTempFile"); - } - } - - private static void makeFinalFieldAccessible(Field field) throws NoSuchFieldException, IllegalAccessException { - field.setAccessible(true); - Field modifiersField = Field.class.getDeclaredField("modifiers"); - modifiersField.setAccessible(true); - modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL); - } } diff --git a/subprojects/internal-testing/src/main/groovy/org/gradle/util/TestPrecondition.groovy b/subprojects/internal-testing/src/main/groovy/org/gradle/util/TestPrecondition.groovy index d7095acca0d69..b7e5fb428f08a 100644 --- a/subprojects/internal-testing/src/main/groovy/org/gradle/util/TestPrecondition.groovy +++ b/subprojects/internal-testing/src/main/groovy/org/gradle/util/TestPrecondition.groovy @@ -112,6 +112,9 @@ enum TestPrecondition implements org.gradle.internal.Factory { JDK10_OR_EARLIER({ JavaVersion.current() <= JavaVersion.VERSION_1_10 }), + JDK11_OR_EARLIER({ + JavaVersion.current() <= JavaVersion.VERSION_11 + }), JDK12_OR_LATER({ JavaVersion.current() >= JavaVersion.VERSION_12 }), diff --git a/subprojects/internal-testing/src/test/groovy/org/gradle/util/SetSystemPropertiesTest.groovy b/subprojects/internal-testing/src/test/groovy/org/gradle/util/SetSystemPropertiesTest.groovy deleted file mode 100644 index 47ed9c2166d94..0000000000000 --- a/subprojects/internal-testing/src/test/groovy/org/gradle/util/SetSystemPropertiesTest.groovy +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright 2016 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.gradle.util - - -import org.junit.Rule -import org.junit.rules.TemporaryFolder -import spock.lang.Specification - -import java.nio.file.Files - - -class SetSystemPropertiesTest extends Specification { - @Rule - TemporaryFolder tempRoot - - def originalTempDir - - def setup() { - originalTempDir = System.getProperty('java.io.tmpdir') - } - - def cleanup() { - System.setProperty('java.io.tmpdir', originalTempDir) - SetSystemProperties.resetTempDirLocation() - } - - - def "cached java.io.tmpdir location used by File.createTempFile should get resetted"() { - given: - def tempDir1 = tempRoot.newFolder('temp1') - def tempDir2 = tempRoot.newFolder('temp2') - when: - System.setProperty('java.io.tmpdir', tempDir1.absolutePath) - SetSystemProperties.resetTempDirLocation() - File.createTempFile("file", null).text = 'content' - then: - tempDir1.listFiles().size() == 1 - when: - System.setProperty('java.io.tmpdir', tempDir2.absolutePath) - SetSystemProperties.resetTempDirLocation() - File.createTempFile("file", null).text = 'content' - then: - tempDir2.listFiles().size() == 1 - } - - def "cached java.io.tmpdir location used by Files.createTempFile should get resetted"() { - given: - def tempDir1 = tempRoot.newFolder('temp1') - def tempDir2 = tempRoot.newFolder('temp2') - when: - System.setProperty('java.io.tmpdir', tempDir1.absolutePath) - SetSystemProperties.resetTempDirLocation() - Files.createTempFile("file", null).toFile().text = 'content' - then: - tempDir1.listFiles().size() == 1 - when: - System.setProperty('java.io.tmpdir', tempDir2.absolutePath) - SetSystemProperties.resetTempDirLocation() - Files.createTempFile("file", null).toFile().text = 'content' - then: - tempDir2.listFiles().size() == 1 - } -} From 13ed8acefb78057b7f17b1c64bc2cdf0184d45a1 Mon Sep 17 00:00:00 2001 From: Gary Hale Date: Wed, 13 Mar 2019 18:44:28 -0400 Subject: [PATCH 538/853] Error when SetSystemProperties rule is used with tmpdir --- .../util/SetSystemPropertiesTest.groovy | 56 +++++++++++++++++++ .../org/gradle/util/SetSystemProperties.java | 7 +++ 2 files changed, 63 insertions(+) create mode 100644 subprojects/base-services/src/test/groovy/org/gradle/util/SetSystemPropertiesTest.groovy diff --git a/subprojects/base-services/src/test/groovy/org/gradle/util/SetSystemPropertiesTest.groovy b/subprojects/base-services/src/test/groovy/org/gradle/util/SetSystemPropertiesTest.groovy new file mode 100644 index 0000000000000..1e1a102d0327b --- /dev/null +++ b/subprojects/base-services/src/test/groovy/org/gradle/util/SetSystemPropertiesTest.groovy @@ -0,0 +1,56 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.util + +import org.junit.runner.Description +import org.junit.runners.model.Statement +import spock.lang.Specification + +class SetSystemPropertiesTest extends Specification { + public static final String TEST_PROPERTY = 'org.gradle.foo' + def base = Mock(Statement) + + def "can set system properties for the duration of a test"() { + def properties = [:] + + given: + System.setProperty(TEST_PROPERTY, "bar") + properties[TEST_PROPERTY] = "baz" + SetSystemProperties setSystemProperties = new SetSystemProperties(properties) + + when: + setSystemProperties.apply(base, Stub(Description)).evaluate() + + then: + 1 * base.evaluate() >> { assert System.getProperty(TEST_PROPERTY) == "baz" } + + and: + System.getProperty(TEST_PROPERTY) == "bar" + } + + def "cannot set java.io.tmpdir"() { + given: + SetSystemProperties setSystemProperties = new SetSystemProperties(["java.io.tmpdir": "/some/path"]) + + when: + setSystemProperties.apply(base, Stub(Description)).evaluate() + + then: + def e = thrown(IllegalArgumentException) + e.message == "'java.io.tmpdir' should not be set via a rule as its value cannot be changed once it is initialized" + } +} diff --git a/subprojects/internal-testing/src/main/groovy/org/gradle/util/SetSystemProperties.java b/subprojects/internal-testing/src/main/groovy/org/gradle/util/SetSystemProperties.java index ba05206d97164..382a1848def55 100644 --- a/subprojects/internal-testing/src/main/groovy/org/gradle/util/SetSystemProperties.java +++ b/subprojects/internal-testing/src/main/groovy/org/gradle/util/SetSystemProperties.java @@ -30,6 +30,7 @@ public class SetSystemProperties implements TestRule { private final Properties properties; private final Map customProperties = new HashMap(); + private static final String[] IMMUTABLE_SYSTEM_PROPERTIES = new String[] {"java.io.tmpdir"}; public SetSystemProperties() { properties = new Properties(); @@ -46,6 +47,12 @@ public Statement apply(final Statement base, Description description) { return new Statement() { @Override public void evaluate() throws Throwable { + for (String immutableProperty : IMMUTABLE_SYSTEM_PROPERTIES) { + if (customProperties.containsKey(immutableProperty)) { + throw new IllegalArgumentException("'" + immutableProperty + "' should not be set via a rule as its value cannot be changed once it is initialized"); + } + } + System.getProperties().putAll(customProperties); try { base.evaluate(); From 3a188cd82a4dbb04ed75d2b25b1bf87b39d5bcaa Mon Sep 17 00:00:00 2001 From: Stefan Wolf Date: Thu, 14 Mar 2019 13:45:06 +0100 Subject: [PATCH 539/853] Simplify getting rebuild file changes --- .../ChangesOnlyIncrementalTaskInputs.java | 8 +-- .../changes/RebuildIncrementalTaskInputs.java | 37 ++---------- .../IncrementalTaskInputsTaskAction.java | 14 +++-- ...TransformIncrementalIntegrationTest.groovy | 2 +- .../changes/IncrementalInputChanges.java | 6 +- .../history/changes/InputChangesInternal.java | 4 +- .../changes/NonIncrementalInputChanges.java | 58 ++++++++++++++----- 7 files changed, 65 insertions(+), 64 deletions(-) diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/changedetection/changes/ChangesOnlyIncrementalTaskInputs.java b/subprojects/core/src/main/java/org/gradle/api/internal/changedetection/changes/ChangesOnlyIncrementalTaskInputs.java index 52901bcf649ee..2907471675f19 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/changedetection/changes/ChangesOnlyIncrementalTaskInputs.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/changedetection/changes/ChangesOnlyIncrementalTaskInputs.java @@ -18,16 +18,15 @@ import org.gradle.api.Action; import org.gradle.api.tasks.incremental.InputFileDetails; -import org.gradle.internal.change.Change; import java.util.ArrayList; import java.util.List; public class ChangesOnlyIncrementalTaskInputs extends StatefulIncrementalTaskInputs { - private final Iterable inputFilesState; + private final Iterable inputFilesState; private final List removedFiles = new ArrayList(); - public ChangesOnlyIncrementalTaskInputs(Iterable inputFilesState) { + public ChangesOnlyIncrementalTaskInputs(Iterable inputFilesState) { this.inputFilesState = inputFilesState; } @@ -37,8 +36,7 @@ public boolean isIncremental() { @Override protected void doOutOfDate(final Action outOfDateAction) { - for (Change change : inputFilesState) { - InputFileDetails fileChange = (InputFileDetails) change; + for (InputFileDetails fileChange : inputFilesState) { if (fileChange.isRemoved()) { removedFiles.add(fileChange); } else { diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/changedetection/changes/RebuildIncrementalTaskInputs.java b/subprojects/core/src/main/java/org/gradle/api/internal/changedetection/changes/RebuildIncrementalTaskInputs.java index ff28008e1f98a..5f77306a69a42 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/changedetection/changes/RebuildIncrementalTaskInputs.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/changedetection/changes/RebuildIncrementalTaskInputs.java @@ -18,15 +18,11 @@ import org.gradle.api.Action; import org.gradle.api.tasks.incremental.InputFileDetails; -import org.gradle.internal.change.Change; -import org.gradle.internal.execution.history.changes.InputChangesInternal; - -import java.io.File; public class RebuildIncrementalTaskInputs extends StatefulIncrementalTaskInputs { - private final InputChangesInternal inputChanges; + private final Iterable inputChanges; - public RebuildIncrementalTaskInputs(InputChangesInternal inputChanges) { + public RebuildIncrementalTaskInputs(Iterable inputChanges) { this.inputChanges = inputChanges; } @@ -35,36 +31,11 @@ public boolean isIncremental() { } public void doOutOfDate(final Action outOfDateAction) { - for (Change change : inputChanges.getAllFileChanges()) { - InputFileDetails inputFileChange = (InputFileDetails) change; - outOfDateAction.execute(new RebuildInputFile(inputFileChange.getFile())); + for (InputFileDetails inputFileChange : inputChanges) { + outOfDateAction.execute(inputFileChange); } } public void doRemoved(Action removedAction) { } - - private static class RebuildInputFile implements InputFileDetails { - private final File file; - - private RebuildInputFile(File file) { - this.file = file; - } - - public File getFile() { - return file; - } - - public boolean isAdded() { - return false; - } - - public boolean isModified() { - return false; - } - - public boolean isRemoved() { - return false; - } - } } diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/project/taskfactory/IncrementalTaskInputsTaskAction.java b/subprojects/core/src/main/java/org/gradle/api/internal/project/taskfactory/IncrementalTaskInputsTaskAction.java index 787257318e151..a3e1aa1b32fd2 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/project/taskfactory/IncrementalTaskInputsTaskAction.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/project/taskfactory/IncrementalTaskInputsTaskAction.java @@ -20,6 +20,7 @@ import org.gradle.api.internal.changedetection.changes.ChangesOnlyIncrementalTaskInputs; import org.gradle.api.internal.changedetection.changes.RebuildIncrementalTaskInputs; import org.gradle.api.tasks.incremental.IncrementalTaskInputs; +import org.gradle.api.tasks.incremental.InputFileDetails; import org.gradle.internal.execution.history.changes.InputChangesInternal; import org.gradle.internal.reflect.Instantiator; import org.gradle.internal.reflect.JavaMethod; @@ -37,18 +38,19 @@ public IncrementalTaskInputsTaskAction(Instantiator instantiator, Class allFileChanges = inputChanges.getAllFileChanges(); IncrementalTaskInputs incrementalTaskInputs = inputChanges.isIncremental() - ? createIncrementalInputs(inputChanges) - : createRebuildInputs(inputChanges); + ? createIncrementalInputs(allFileChanges) + : createRebuildInputs(allFileChanges); JavaMethod.of(task, Object.class, methodName, IncrementalTaskInputs.class).invoke(task, incrementalTaskInputs); } - private ChangesOnlyIncrementalTaskInputs createIncrementalInputs(InputChangesInternal inputChanges) { - return instantiator.newInstance(ChangesOnlyIncrementalTaskInputs.class, inputChanges.getAllFileChanges()); + private ChangesOnlyIncrementalTaskInputs createIncrementalInputs(Iterable allFileChanges) { + return instantiator.newInstance(ChangesOnlyIncrementalTaskInputs.class, allFileChanges); } - private RebuildIncrementalTaskInputs createRebuildInputs(InputChangesInternal inputChanges) { - return instantiator.newInstance(RebuildIncrementalTaskInputs.class, inputChanges); + private RebuildIncrementalTaskInputs createRebuildInputs(Iterable allFileChanges) { + return instantiator.newInstance(RebuildIncrementalTaskInputs.class, allFileChanges); } } diff --git a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformIncrementalIntegrationTest.groovy b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformIncrementalIntegrationTest.groovy index 8caa7842a86a5..2828230216a77 100644 --- a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformIncrementalIntegrationTest.groovy +++ b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformIncrementalIntegrationTest.groovy @@ -60,7 +60,7 @@ class ArtifactTransformIncrementalIntegrationTest extends AbstractDependencyReso println "Transforming " + input.name println "incremental: " + inputChanges.incremental assert parameters.incrementalExecution.get() == inputChanges.incremental - def changes = inputChanges.getFileChanges(input) + def changes = inputChanges.getFileChanges(input) as List println "changes: \\n" + changes.join("\\n") assert changes.findAll { it.changeType == ChangeType.ADDED }*.file as Set == resolveFiles(parameters.addedFiles.get()) assert changes.findAll { it.changeType == ChangeType.REMOVED }*.file as Set == resolveFiles(parameters.removedFiles.get()) diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/IncrementalInputChanges.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/IncrementalInputChanges.java index 0b34b85561838..65dbf18aa0c86 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/IncrementalInputChanges.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/IncrementalInputChanges.java @@ -18,8 +18,8 @@ import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableListMultimap; +import org.gradle.api.tasks.incremental.InputFileDetails; import org.gradle.internal.Cast; -import org.gradle.internal.change.Change; import org.gradle.internal.change.CollectingChangeVisitor; import org.gradle.work.FileChange; @@ -58,9 +58,9 @@ public static String determinePropertyName(Object propertyValue, ImmutableListMu } @Override - public Iterable getAllFileChanges() { + public Iterable getAllFileChanges() { CollectingChangeVisitor visitor = new CollectingChangeVisitor(); changes.accept(visitor); - return visitor.getChanges(); + return Cast.uncheckedNonnullCast(visitor.getChanges()); } } diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/InputChangesInternal.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/InputChangesInternal.java index a0bc15b2ab833..896e73265359d 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/InputChangesInternal.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/InputChangesInternal.java @@ -16,9 +16,9 @@ package org.gradle.internal.execution.history.changes; -import org.gradle.internal.change.Change; +import org.gradle.api.tasks.incremental.InputFileDetails; import org.gradle.work.InputChanges; public interface InputChangesInternal extends InputChanges { - Iterable getAllFileChanges(); + Iterable getAllFileChanges(); } diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/NonIncrementalInputChanges.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/NonIncrementalInputChanges.java index 41785fba4ab38..42d266e1db9ce 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/NonIncrementalInputChanges.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/NonIncrementalInputChanges.java @@ -18,13 +18,15 @@ import com.google.common.collect.ImmutableListMultimap; import com.google.common.collect.ImmutableSortedMap; +import org.gradle.api.tasks.incremental.InputFileDetails; import org.gradle.internal.Cast; -import org.gradle.internal.change.Change; -import org.gradle.internal.change.CollectingChangeVisitor; import org.gradle.internal.fingerprint.CurrentFileCollectionFingerprint; -import org.gradle.internal.fingerprint.FileCollectionFingerprint; +import org.gradle.work.ChangeType; import org.gradle.work.FileChange; +import java.io.File; +import java.util.stream.Stream; + import static org.gradle.internal.execution.history.changes.IncrementalInputChanges.determinePropertyName; public class NonIncrementalInputChanges implements InputChangesInternal { @@ -43,22 +45,50 @@ public boolean isIncremental() { @Override public Iterable getFileChanges(Object parameterValue) { - CollectingChangeVisitor visitor = new CollectingChangeVisitor(); CurrentFileCollectionFingerprint currentFileCollectionFingerprint = currentInputs.get(determinePropertyName(parameterValue, propertyNameByValue)); - visitAllFileChanges(currentFileCollectionFingerprint, visitor); - return Cast.uncheckedNonnullCast(visitor.getChanges()); + return getAllFileChanges(currentFileCollectionFingerprint)::iterator; } @Override - public Iterable getAllFileChanges() { - CollectingChangeVisitor changeVisitor = new CollectingChangeVisitor(); - for (CurrentFileCollectionFingerprint fingerprint : currentInputs.values()) { - visitAllFileChanges(fingerprint, changeVisitor); - } - return changeVisitor.getChanges(); + public Iterable getAllFileChanges() { + Iterable changes = currentInputs.values().stream().flatMap(NonIncrementalInputChanges::getAllFileChanges)::iterator; + return Cast.uncheckedNonnullCast(changes); + } + + private static Stream getAllFileChanges(CurrentFileCollectionFingerprint currentFileCollectionFingerprint) { + return currentFileCollectionFingerprint.getFingerprints().keySet().stream().map(RebuildFileChange::new); } - private void visitAllFileChanges(CurrentFileCollectionFingerprint currentFileCollectionFingerprint, CollectingChangeVisitor visitor) { - currentFileCollectionFingerprint.visitChangesSince(FileCollectionFingerprint.EMPTY, "Input", true, visitor); + private static class RebuildFileChange implements FileChange, InputFileDetails { + private final String path; + + public RebuildFileChange(String path) { + this.path = path; + } + + @Override + public File getFile() { + return new File(path); + } + + @Override + public ChangeType getChangeType() { + return ChangeType.ADDED; + } + + @Override + public boolean isAdded() { + return false; + } + + @Override + public boolean isModified() { + return false; + } + + @Override + public boolean isRemoved() { + return false; + } } } From 777ba26f110e7d30dc527eddf305459d92ce63e2 Mon Sep 17 00:00:00 2001 From: "Rodrigo B. de Oliveira" Date: Thu, 14 Mar 2019 11:54:13 -0300 Subject: [PATCH 540/853] Introduce `ClientModuleDelegate` --- .../kotlin/dsl/DependencyHandlerExtensions.kt | 6 +- .../support/delegates/ClientModuleDelegate.kt | 144 ++++++++++++++++++ 2 files changed, 149 insertions(+), 1 deletion(-) create mode 100644 subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/delegates/ClientModuleDelegate.kt diff --git a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/DependencyHandlerExtensions.kt b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/DependencyHandlerExtensions.kt index 2a5856784a3c0..84a107b333089 100644 --- a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/DependencyHandlerExtensions.kt +++ b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/DependencyHandlerExtensions.kt @@ -26,6 +26,7 @@ import org.gradle.api.artifacts.dsl.DependencyHandler import org.gradle.kotlin.dsl.accessors.runtime.externalModuleDependencyFor +import org.gradle.kotlin.dsl.support.delegates.ClientModuleDelegate import org.gradle.kotlin.dsl.support.excludeMapFor import org.gradle.kotlin.dsl.support.mapOfNonNullValuesOf import org.gradle.kotlin.dsl.support.uncheckedCast @@ -163,7 +164,10 @@ inline fun DependencyHandler.configureClientModule( class ClientModuleScope( private val dependencyHandler: DependencyHandler, val clientModule: ClientModule -) : ClientModule by clientModule { +) : ClientModuleDelegate() { + + override val delegate: ClientModule + get() = clientModule fun module( group: String, diff --git a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/delegates/ClientModuleDelegate.kt b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/delegates/ClientModuleDelegate.kt new file mode 100644 index 0000000000000..23af3e2624010 --- /dev/null +++ b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/delegates/ClientModuleDelegate.kt @@ -0,0 +1,144 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.kotlin.dsl.support.delegates + +import groovy.lang.Closure + +import org.gradle.api.Action +import org.gradle.api.artifacts.ClientModule +import org.gradle.api.artifacts.Dependency +import org.gradle.api.artifacts.DependencyArtifact +import org.gradle.api.artifacts.ExcludeRule +import org.gradle.api.artifacts.ExternalDependency +import org.gradle.api.artifacts.ExternalModuleDependency +import org.gradle.api.artifacts.ModuleDependency +import org.gradle.api.artifacts.ModuleDependencyCapabilitiesHandler +import org.gradle.api.artifacts.ModuleIdentifier +import org.gradle.api.artifacts.ModuleVersionIdentifier +import org.gradle.api.artifacts.MutableVersionConstraint +import org.gradle.api.artifacts.VersionConstraint +import org.gradle.api.attributes.AttributeContainer +import org.gradle.api.capabilities.Capability + + +/** + * Facilitates the implementation of the [ClientModule] interface by delegation via subclassing. + * + * See [GradleDelegate] for details why this is currently necessary. + */ +abstract class ClientModuleDelegate : ClientModule { + + internal + abstract val delegate: ClientModule + + override fun getGroup(): String? = + delegate.group + + override fun addDependency(dependency: ModuleDependency) = + delegate.addDependency(dependency) + + override fun getName(): String = + delegate.name + + override fun getExcludeRules(): MutableSet = + delegate.excludeRules + + override fun addArtifact(artifact: DependencyArtifact): ModuleDependency = + delegate.addArtifact(artifact) + + override fun artifact(configureClosure: Closure): DependencyArtifact = + delegate.artifact(configureClosure) + + override fun artifact(configureAction: Action): DependencyArtifact = + delegate.artifact(configureAction) + + override fun getAttributes(): AttributeContainer = + delegate.attributes + + override fun capabilities(configureAction: Action): ModuleDependency = + delegate.capabilities(configureAction) + + override fun version(configureAction: Action) = + delegate.version(configureAction) + + override fun getId(): String = + delegate.id + + override fun getTargetConfiguration(): String? = + delegate.targetConfiguration + + override fun copy(): ClientModule = + delegate.copy() + + override fun attributes(configureAction: Action): ModuleDependency = + delegate.attributes(configureAction) + + override fun matchesStrictly(identifier: ModuleVersionIdentifier): Boolean = + delegate.matchesStrictly(identifier) + + override fun isChanging(): Boolean = + delegate.isChanging + + override fun getVersion(): String? = + delegate.version + + override fun isTransitive(): Boolean = + delegate.isTransitive + + override fun setTransitive(transitive: Boolean): ModuleDependency = + delegate.setTransitive(transitive) + + override fun setForce(force: Boolean): ExternalDependency = + delegate.setForce(force) + + override fun contentEquals(dependency: Dependency): Boolean = + delegate.contentEquals(dependency) + + override fun getRequestedCapabilities(): MutableList = + delegate.requestedCapabilities + + override fun getVersionConstraint(): VersionConstraint = + delegate.versionConstraint + + override fun getModule(): ModuleIdentifier = + delegate.module + + override fun getArtifacts(): MutableSet = + delegate.artifacts + + override fun setTargetConfiguration(name: String?) { + delegate.targetConfiguration = name + } + + override fun setChanging(changing: Boolean): ExternalModuleDependency = + delegate.setChanging(changing) + + override fun isForce(): Boolean = + delegate.isForce + + override fun getDependencies(): MutableSet = + delegate.dependencies + + override fun because(reason: String?) = + delegate.because(reason) + + override fun exclude(excludeProperties: Map): ModuleDependency = + delegate.exclude(excludeProperties) + + override fun getReason(): String? = + delegate.reason +} From cfb018a441d71076084ed76cd259222eb853e5c9 Mon Sep 17 00:00:00 2001 From: "Rodrigo B. de Oliveira" Date: Thu, 14 Mar 2019 11:54:53 -0300 Subject: [PATCH 541/853] Introduce `TaskContainerDelegate` --- .../kotlin/dsl/TaskContainerExtensions.kt | 7 +- .../delegates/TaskContainerDelegate.kt | 245 ++++++++++++++++++ 2 files changed, 251 insertions(+), 1 deletion(-) create mode 100644 subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/delegates/TaskContainerDelegate.kt diff --git a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/TaskContainerExtensions.kt b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/TaskContainerExtensions.kt index 74f5f6b7cce19..26a959bebe0c1 100644 --- a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/TaskContainerExtensions.kt +++ b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/TaskContainerExtensions.kt @@ -20,6 +20,8 @@ import org.gradle.api.tasks.TaskCollection import org.gradle.api.tasks.TaskContainer import org.gradle.api.tasks.TaskProvider +import org.gradle.kotlin.dsl.support.delegates.TaskContainerDelegate + import kotlin.reflect.KClass import kotlin.reflect.KProperty @@ -145,13 +147,16 @@ operator fun RegisteringDomainObjectDelegateProviderWithTypeAndAction class TaskContainerScope private constructor( val container: TaskContainer -) : TaskContainer by container { +) : TaskContainerDelegate() { companion object { fun of(container: TaskContainer) = TaskContainerScope(container) } + override val delegate: TaskContainer + get() = container + /** * Configures a task by name, without triggering its creation or configuration, failing if there is no such task. * diff --git a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/delegates/TaskContainerDelegate.kt b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/delegates/TaskContainerDelegate.kt new file mode 100644 index 0000000000000..94b49d45d23bf --- /dev/null +++ b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/delegates/TaskContainerDelegate.kt @@ -0,0 +1,245 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.kotlin.dsl.support.delegates + +import groovy.lang.Closure + +import org.gradle.api.Action +import org.gradle.api.DomainObjectCollection +import org.gradle.api.NamedDomainObjectCollectionSchema +import org.gradle.api.NamedDomainObjectContainer +import org.gradle.api.Namer +import org.gradle.api.Rule +import org.gradle.api.Task +import org.gradle.api.provider.Provider +import org.gradle.api.specs.Spec +import org.gradle.api.tasks.TaskCollection +import org.gradle.api.tasks.TaskContainer +import org.gradle.api.tasks.TaskProvider + +import java.util.SortedMap +import java.util.SortedSet + + +/** + * Facilitates the implementation of the [TaskContainer] interface by delegation via subclassing. + * + * See [GradleDelegate] for details why this is currently necessary. + */ +abstract class TaskContainerDelegate : TaskContainer { + + internal + abstract val delegate: TaskContainer + + override fun contains(element: Task): Boolean = + delegate.contains(element) + + override fun addAll(elements: Collection): Boolean = + delegate.addAll(elements) + + override fun matching(spec: Spec): TaskCollection = + delegate.matching(spec) + + override fun matching(closure: Closure): TaskCollection = + delegate.matching(closure) + + override fun clear() = + delegate.clear() + + override fun addRule(rule: Rule): Rule = + delegate.addRule(rule) + + override fun addRule(description: String, ruleAction: Closure): Rule = + delegate.addRule(description, ruleAction) + + override fun addRule(description: String, ruleAction: Action): Rule = + delegate.addRule(description, ruleAction) + + override fun configure(configureClosure: Closure): NamedDomainObjectContainer = + delegate.configure(configureClosure) + + override fun addAllLater(provider: Provider>) = + delegate.addAllLater(provider) + + override fun create(options: Map): Task = + delegate.create(options) + + override fun create(options: Map, configureClosure: Closure): Task = + delegate.create(options, configureClosure) + + override fun create(name: String, configureClosure: Closure): Task = + delegate.create(name, configureClosure) + + override fun create(name: String): Task = + delegate.create(name) + + override fun create(name: String, type: Class): T = + delegate.create(name, type) + + override fun create(name: String, type: Class, vararg constructorArgs: Any?): T = + delegate.create(name, type, constructorArgs) + + override fun create(name: String, type: Class, configuration: Action): T = + delegate.create(name, type, configuration) + + override fun create(name: String, configureAction: Action): Task = + delegate.create(name, configureAction) + + override fun whenTaskAdded(action: Action): Action = + delegate.whenTaskAdded(action) + + override fun whenTaskAdded(closure: Closure) = + delegate.whenTaskAdded(closure) + + override fun removeAll(elements: Collection): Boolean = + delegate.removeAll(elements) + + override fun getByPath(path: String): Task = + delegate.getByPath(path) + + override fun add(element: Task): Boolean = + delegate.add(element) + + override fun all(action: Action) = + delegate.all(action) + + override fun all(action: Closure) = + delegate.all(action) + + override fun register(name: String, configurationAction: Action): TaskProvider = + delegate.register(name, configurationAction) + + override fun register(name: String, type: Class, configurationAction: Action): TaskProvider = + delegate.register(name, type, configurationAction) + + override fun register(name: String, type: Class): TaskProvider = + delegate.register(name, type) + + override fun register(name: String, type: Class, vararg constructorArgs: Any?): TaskProvider = + delegate.register(name, type, constructorArgs) + + override fun register(name: String): TaskProvider = + delegate.register(name) + + override fun replace(name: String): Task = + delegate.replace(name) + + override fun replace(name: String, type: Class): T = + delegate.replace(name, type) + + override fun iterator(): MutableIterator = + delegate.iterator() + + override fun named(name: String): TaskProvider = + delegate.named(name) + + override fun named(name: String, configurationAction: Action): TaskProvider = + delegate.named(name, configurationAction) + + override fun named(name: String, type: Class): TaskProvider = + delegate.named(name, type) + + override fun named(name: String, type: Class, configurationAction: Action): TaskProvider = + delegate.named(name, type, configurationAction) + + override fun getNamer(): Namer = + delegate.namer + + override fun getRules(): MutableList = + delegate.rules + + override fun getCollectionSchema(): NamedDomainObjectCollectionSchema = + delegate.collectionSchema + + override fun whenObjectRemoved(action: Action): Action = + delegate.whenObjectRemoved(action) + + override fun whenObjectRemoved(action: Closure) = + delegate.whenObjectRemoved(action) + + override fun findAll(spec: Closure): MutableSet = + delegate.findAll(spec) + + override fun addLater(provider: Provider) = + delegate.addLater(provider) + + override fun containsAll(elements: Collection): Boolean = + delegate.containsAll(elements) + + override fun isEmpty(): Boolean = + delegate.isEmpty() + + override fun containerWithType(type: Class): NamedDomainObjectContainer = + delegate.containerWithType(type) + + override fun getByName(name: String, configureClosure: Closure): Task = + delegate.getByName(name, configureClosure) + + override fun getByName(name: String): Task = + delegate.getByName(name) + + override fun getByName(name: String, configureAction: Action): Task = + delegate.getByName(name, configureAction) + + override fun configureEach(action: Action) = + delegate.configureEach(action) + + override fun maybeCreate(name: String, type: Class): U = + delegate.maybeCreate(name, type) + + override fun maybeCreate(name: String): Task = + delegate.maybeCreate(name) + + override fun findByPath(path: String): Task? = + delegate.findByPath(path) + + override fun withType(type: Class): TaskCollection = + delegate.withType(type) + + override fun withType(type: Class, configureAction: Action): DomainObjectCollection = + delegate.withType(type, configureAction) + + override fun withType(type: Class, configureClosure: Closure): DomainObjectCollection = + delegate.withType(type, configureClosure) + + override fun findByName(name: String): Task? = + delegate.findByName(name) + + override fun whenObjectAdded(action: Action): Action = + delegate.whenObjectAdded(action) + + override fun whenObjectAdded(action: Closure) = + delegate.whenObjectAdded(action) + + override fun retainAll(elements: Collection): Boolean = + delegate.retainAll(elements) + + override fun getAsMap(): SortedMap = + delegate.asMap + + override fun getNames(): SortedSet = + delegate.names + + override fun getAt(name: String): Task = + delegate.getAt(name) + + override val size: Int + get() = delegate.size + + override fun remove(element: Task): Boolean = + delegate.remove(element) +} From 920c6135a2eacdc4e967d4fad832b39e2fc518bd Mon Sep 17 00:00:00 2001 From: "Rodrigo B. de Oliveira" Date: Thu, 14 Mar 2019 12:20:51 -0300 Subject: [PATCH 542/853] Inspect only `*.properties` entries under `META-INF/gradle-plugins/` Resolves gradle/kotlin-dsl#1363 --- .../PrecompiledScriptPluginAccessorsTest.kt | 32 ++++++++++++++++++- .../kotlin/dsl/codegen/PluginIdExtensions.kt | 9 +++++- 2 files changed, 39 insertions(+), 2 deletions(-) diff --git a/subprojects/kotlin-dsl-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPluginAccessorsTest.kt b/subprojects/kotlin-dsl-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPluginAccessorsTest.kt index 14be37be530ba..16b79ac5f7a73 100644 --- a/subprojects/kotlin-dsl-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPluginAccessorsTest.kt +++ b/subprojects/kotlin-dsl-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPluginAccessorsTest.kt @@ -348,13 +348,22 @@ class PrecompiledScriptPluginAccessorsTest : AbstractPrecompiledScriptPluginTest val pluginJar = jarForPlugin(pluginId, "MyPlugin") withPrecompiledScriptApplying(pluginId, pluginJar) + assertPrecompiledScriptPluginApplies( + pluginId, + "Plugin_gradle" + ) + } + + private + fun assertPrecompiledScriptPluginApplies(pluginId: String, precompiledScriptClassName: String) { + compileKotlin() val (project, pluginManager) = projectAndPluginManagerMocks() instantiatePrecompiledScriptOf( project, - "Plugin_gradle" + precompiledScriptClassName ) inOrder(pluginManager) { @@ -363,6 +372,27 @@ class PrecompiledScriptPluginAccessorsTest : AbstractPrecompiledScriptPluginTest } } + @Test + fun `can use plugin specs with jruby-gradle-plugin`() { + + withKotlinDslPlugin().appendText(""" + dependencies { + compile("com.github.jruby-gradle:jruby-gradle-plugin:1.4.0") + } + """) + + withPrecompiledKotlinScript("plugin.gradle.kts", """ + plugins { + com.github.`jruby-gradle`.base + } + """) + + assertPrecompiledScriptPluginApplies( + "com.github.jruby-gradle.base", + "Plugin_gradle" + ) + } + @Test fun `plugin application errors are reported but don't cause the build to fail`() { diff --git a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/codegen/PluginIdExtensions.kt b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/codegen/PluginIdExtensions.kt index 4d6dafc6e76a6..2b5259406701c 100644 --- a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/codegen/PluginIdExtensions.kt +++ b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/codegen/PluginIdExtensions.kt @@ -22,6 +22,7 @@ import org.gradle.plugin.use.PluginDependencySpec import java.io.File import java.util.Properties +import java.util.jar.JarEntry import java.util.jar.JarFile @@ -248,7 +249,7 @@ internal fun pluginEntriesFrom(jar: File): List = JarFile(jar).use { jarFile -> jarFile.entries().asSequence().filter { - it.isFile && it.name.startsWith("META-INF/gradle-plugins/") + isGradlePluginPropertiesFile(it) }.map { pluginEntry -> val pluginProperties = jarFile.getInputStream(pluginEntry).use { Properties().apply { load(it) } } val id = pluginEntry.name.substringAfterLast("/").substringBeforeLast(".properties") @@ -256,3 +257,9 @@ fun pluginEntriesFrom(jar: File): List = PluginEntry(id, implementationClass) }.toList() } + + +private +fun isGradlePluginPropertiesFile(entry: JarEntry) = entry.run { + isFile && name.run { startsWith("META-INF/gradle-plugins/") && endsWith(".properties") } +} From c160dea6a1481fe945fb7e4e3488fd78704ace3e Mon Sep 17 00:00:00 2001 From: "Rodrigo B. de Oliveira" Date: Thu, 14 Mar 2019 12:49:06 -0300 Subject: [PATCH 543/853] Fix `ClientModuleDelegate.getGroup()` not to return `null` Because it also implements `ModuleVersionSelector.getGroup()` which does not allow `null` return values. --- .../kotlin/dsl/support/delegates/ClientModuleDelegate.kt | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/delegates/ClientModuleDelegate.kt b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/delegates/ClientModuleDelegate.kt index 23af3e2624010..869af40b6b89a 100644 --- a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/delegates/ClientModuleDelegate.kt +++ b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/delegates/ClientModuleDelegate.kt @@ -26,6 +26,7 @@ import org.gradle.api.artifacts.ExcludeRule import org.gradle.api.artifacts.ExternalDependency import org.gradle.api.artifacts.ExternalModuleDependency import org.gradle.api.artifacts.ModuleDependency +import org.gradle.api.artifacts.ModuleVersionSelector import org.gradle.api.artifacts.ModuleDependencyCapabilitiesHandler import org.gradle.api.artifacts.ModuleIdentifier import org.gradle.api.artifacts.ModuleVersionIdentifier @@ -45,8 +46,9 @@ abstract class ClientModuleDelegate : ClientModule { internal abstract val delegate: ClientModule - override fun getGroup(): String? = - delegate.group + override fun getGroup(): String = + /** Because this also implements [ModuleVersionSelector.getGroup] it must not return `null` */ + delegate.group ?: "" override fun addDependency(dependency: ModuleDependency) = delegate.addDependency(dependency) From d534876a4c40d99c6c0bc9a15dd0f38615ece068 Mon Sep 17 00:00:00 2001 From: Stefan Oehme Date: Wed, 13 Mar 2019 16:49:13 +0100 Subject: [PATCH 544/853] Fix non-classdir tests --- ...entalJavaCompilationIntegrationTest.groovy | 22 +++++-------------- ...entalJavaCompilationIntegrationTest.groovy | 9 ++++++++ ...nUsingClassDirectoryIntegrationTest.groovy | 9 ++++++++ .../ClasspathEntrySnapshotTest.groovy | 3 --- 4 files changed, 24 insertions(+), 19 deletions(-) diff --git a/subprojects/language-java/src/integTest/groovy/org/gradle/java/compile/incremental/AbstractCrossTaskIncrementalJavaCompilationIntegrationTest.groovy b/subprojects/language-java/src/integTest/groovy/org/gradle/java/compile/incremental/AbstractCrossTaskIncrementalJavaCompilationIntegrationTest.groovy index 2356199917e97..dd77f79a7156c 100644 --- a/subprojects/language-java/src/integTest/groovy/org/gradle/java/compile/incremental/AbstractCrossTaskIncrementalJavaCompilationIntegrationTest.groovy +++ b/subprojects/language-java/src/integTest/groovy/org/gradle/java/compile/incremental/AbstractCrossTaskIncrementalJavaCompilationIntegrationTest.groovy @@ -44,6 +44,8 @@ abstract class AbstractCrossTaskIncrementalJavaCompilationIntegrationTest extend protected abstract String getProjectDependencyBlock() + protected abstract void addDependency(String from, String to) + private File java(Map projectToClassBodies) { File out projectToClassBodies.each { project, bodies -> @@ -75,11 +77,7 @@ abstract class AbstractCrossTaskIncrementalJavaCompilationIntegrationTest extend settingsFile << """ include 'app' """ - buildFile << """ - project(':app') { - dependencies { compile project(path:':impl', configuration: 'classesDir') } - } - """ + addDependency("app", "impl") def app = new CompilationOutputsFixture(file("app/build/classes")) java api: ["class A {}"] java impl: ["class B extends A {}"] @@ -98,11 +96,7 @@ abstract class AbstractCrossTaskIncrementalJavaCompilationIntegrationTest extend settingsFile << """ include 'app' """ - buildFile << """ - project(':app') { - dependencies { compile project(path:':impl', configuration: 'classesDir') } - } - """ + addDependency("app", "impl") def app = new CompilationOutputsFixture(file("app/build/classes")) java api: ["class A {}"] java impl: ["class B { public A a;}"] @@ -121,11 +115,7 @@ abstract class AbstractCrossTaskIncrementalJavaCompilationIntegrationTest extend settingsFile << """ include 'app' """ - buildFile << """ - project(':app') { - dependencies { compile project(path:':impl', configuration: 'classesDir') } - } - """ + addDependency("app", "impl") def app = new CompilationOutputsFixture(file("app/build/classes")) java api: ["class A {}"] java impl: ["class B { public A a;}"] @@ -138,7 +128,7 @@ abstract class AbstractCrossTaskIncrementalJavaCompilationIntegrationTest extend when: file("api/src/main/java/A.java").delete() - fails "app:compileJava", "-X", "impl:compileJava" + run "app:compileJava", "-x", "impl:compileJava" then: impl.noneRecompiled() diff --git a/subprojects/language-java/src/integTest/groovy/org/gradle/java/compile/incremental/CrossTaskIncrementalJavaCompilationIntegrationTest.groovy b/subprojects/language-java/src/integTest/groovy/org/gradle/java/compile/incremental/CrossTaskIncrementalJavaCompilationIntegrationTest.groovy index 799a81208e737..6b54347d22da1 100644 --- a/subprojects/language-java/src/integTest/groovy/org/gradle/java/compile/incremental/CrossTaskIncrementalJavaCompilationIntegrationTest.groovy +++ b/subprojects/language-java/src/integTest/groovy/org/gradle/java/compile/incremental/CrossTaskIncrementalJavaCompilationIntegrationTest.groovy @@ -27,4 +27,13 @@ class CrossTaskIncrementalJavaCompilationIntegrationTest extends AbstractCrossTa } ''' } + + @Override + protected void addDependency(String from, String to) { + buildFile << """ + project(':$from') { + dependencies { compile project(':$to') } + } + """ + } } diff --git a/subprojects/language-java/src/integTest/groovy/org/gradle/java/compile/incremental/CrossTaskIncrementalJavaCompilationUsingClassDirectoryIntegrationTest.groovy b/subprojects/language-java/src/integTest/groovy/org/gradle/java/compile/incremental/CrossTaskIncrementalJavaCompilationUsingClassDirectoryIntegrationTest.groovy index 891bbc3a1a610..f6ca1d0264c0f 100644 --- a/subprojects/language-java/src/integTest/groovy/org/gradle/java/compile/incremental/CrossTaskIncrementalJavaCompilationUsingClassDirectoryIntegrationTest.groovy +++ b/subprojects/language-java/src/integTest/groovy/org/gradle/java/compile/incremental/CrossTaskIncrementalJavaCompilationUsingClassDirectoryIntegrationTest.groovy @@ -37,4 +37,13 @@ class CrossTaskIncrementalJavaCompilationUsingClassDirectoryIntegrationTest exte } ''' } + + @Override + protected void addDependency(String from, String to) { + buildFile << """ + project(':$from') { + dependencies { compile project(path:':$to', configuration: 'classesDir') } + } + """ + } } diff --git a/subprojects/language-java/src/test/groovy/org/gradle/api/internal/tasks/compile/incremental/classpath/ClasspathEntrySnapshotTest.groovy b/subprojects/language-java/src/test/groovy/org/gradle/api/internal/tasks/compile/incremental/classpath/ClasspathEntrySnapshotTest.groovy index d6ad5d7ade2d3..ff5c1a2f4fa07 100644 --- a/subprojects/language-java/src/test/groovy/org/gradle/api/internal/tasks/compile/incremental/classpath/ClasspathEntrySnapshotTest.groovy +++ b/subprojects/language-java/src/test/groovy/org/gradle/api/internal/tasks/compile/incremental/classpath/ClasspathEntrySnapshotTest.groovy @@ -17,12 +17,9 @@ package org.gradle.api.internal.tasks.compile.incremental.classpath import org.gradle.api.internal.tasks.compile.incremental.deps.ClassSetAnalysisData -import org.gradle.api.internal.tasks.compile.incremental.deps.DependentsSet import org.gradle.internal.hash.HashCode import spock.lang.Specification -import static org.gradle.api.internal.tasks.compile.incremental.deps.DependentsSet.dependents - class ClasspathEntrySnapshotTest extends Specification { def analysis = Stub(ClassSetAnalysisData) From 33824978f6c83a99697b1ef5fe1dd202d0c5ae71 Mon Sep 17 00:00:00 2001 From: "Rodrigo B. de Oliveira" Date: Thu, 14 Mar 2019 13:42:26 -0300 Subject: [PATCH 545/853] Fix delegation of `vararg` methods --- .../gradle/kotlin/dsl/support/delegates/ProjectDelegate.kt | 2 +- .../kotlin/dsl/support/delegates/TaskContainerDelegate.kt | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/delegates/ProjectDelegate.kt b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/delegates/ProjectDelegate.kt index 7735f2e6b9311..3b0bdf704341c 100644 --- a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/delegates/ProjectDelegate.kt +++ b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/delegates/ProjectDelegate.kt @@ -211,7 +211,7 @@ abstract class ProjectDelegate() : Project { delegate.projectDir override fun files(vararg paths: Any?): ConfigurableFileCollection = - delegate.files(paths) + delegate.files(*paths) override fun files(paths: Any, configureClosure: Closure<*>): ConfigurableFileCollection = delegate.files(paths, configureClosure) diff --git a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/delegates/TaskContainerDelegate.kt b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/delegates/TaskContainerDelegate.kt index 94b49d45d23bf..85f59db625484 100644 --- a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/delegates/TaskContainerDelegate.kt +++ b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/delegates/TaskContainerDelegate.kt @@ -91,7 +91,7 @@ abstract class TaskContainerDelegate : TaskContainer { delegate.create(name, type) override fun create(name: String, type: Class, vararg constructorArgs: Any?): T = - delegate.create(name, type, constructorArgs) + delegate.create(name, type, *constructorArgs) override fun create(name: String, type: Class, configuration: Action): T = delegate.create(name, type, configuration) @@ -130,7 +130,7 @@ abstract class TaskContainerDelegate : TaskContainer { delegate.register(name, type) override fun register(name: String, type: Class, vararg constructorArgs: Any?): TaskProvider = - delegate.register(name, type, constructorArgs) + delegate.register(name, type, *constructorArgs) override fun register(name: String): TaskProvider = delegate.register(name) From 88484189c818533cb324bdb305d88db3a6177be1 Mon Sep 17 00:00:00 2001 From: "Rodrigo B. de Oliveira" Date: Thu, 14 Mar 2019 13:43:03 -0300 Subject: [PATCH 546/853] Fix `DependencyHandlerExtensionsTest` `setTransitive` must return a `Dependency` (not null). --- .../org/gradle/kotlin/dsl/DependencyHandlerExtensionsTest.kt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/subprojects/kotlin-dsl/src/test/kotlin/org/gradle/kotlin/dsl/DependencyHandlerExtensionsTest.kt b/subprojects/kotlin-dsl/src/test/kotlin/org/gradle/kotlin/dsl/DependencyHandlerExtensionsTest.kt index a91ed8d837139..6351e9278740c 100644 --- a/subprojects/kotlin-dsl/src/test/kotlin/org/gradle/kotlin/dsl/DependencyHandlerExtensionsTest.kt +++ b/subprojects/kotlin-dsl/src/test/kotlin/org/gradle/kotlin/dsl/DependencyHandlerExtensionsTest.kt @@ -163,7 +163,9 @@ class DependencyHandlerExtensionsTest { @Test fun `client module configuration`() { - val clientModule = mock() + val clientModule = mock { + on { setTransitive(any()) }.thenAnswer { it.mock } + } val commonsCliDependency = mock(name = "commonsCliDependency") From 118736c9e62e40fe7ab23337b8a365761398975d Mon Sep 17 00:00:00 2001 From: "Rodrigo B. de Oliveira" Date: Thu, 14 Mar 2019 13:43:42 -0300 Subject: [PATCH 547/853] Fix `TaskContainerExtensionsTest` `register` must return a `TaskProvider` (not null). --- .../kotlin/org/gradle/kotlin/dsl/TaskContainerExtensionsTest.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subprojects/kotlin-dsl/src/test/kotlin/org/gradle/kotlin/dsl/TaskContainerExtensionsTest.kt b/subprojects/kotlin-dsl/src/test/kotlin/org/gradle/kotlin/dsl/TaskContainerExtensionsTest.kt index a693eb182a9e3..3e024507de86d 100644 --- a/subprojects/kotlin-dsl/src/test/kotlin/org/gradle/kotlin/dsl/TaskContainerExtensionsTest.kt +++ b/subprojects/kotlin-dsl/src/test/kotlin/org/gradle/kotlin/dsl/TaskContainerExtensionsTest.kt @@ -80,7 +80,7 @@ class TaskContainerExtensionsTest { val taskProvider = mock>() val tasks = mock { - on { register(eq("name"), any>()) } doReturn taskProvider + on { register(eq("clean"), any>()) } doReturn taskProvider } tasks { From ae9ee8e5a43350e210993c4e052e031db045cf93 Mon Sep 17 00:00:00 2001 From: Stefan Wolf Date: Thu, 14 Mar 2019 15:55:00 +0100 Subject: [PATCH 548/853] Address more review changes --- .../execution/ExecuteActionsTaskExecuter.java | 4 +- .../DefaultInputFilePropertySpec.java | 7 +- .../properties/InputFilePropertySpec.java | 5 +- .../transform/DefaultTransformerInvoker.java | 2 +- ...IncrementalExecutionIntegrationTest.groovy | 2 +- .../gradle/internal/execution/UnitOfWork.java | 2 +- .../DefaultExecutionStateChangeDetector.java | 64 ++++++++++++------- .../changes/ExecutionStateChanges.java | 9 ++- .../changes/IncrementalInputChanges.java | 14 ++-- .../changes/NonIncrementalInputChanges.java | 6 +- .../internal/execution/steps/ExecuteStep.java | 32 ++++------ .../execution/steps/ResolveChangesStep.java | 6 +- .../execution/steps/ExecuteStepTest.groovy | 6 +- .../steps/ResolveChangesStepTest.groovy | 9 +-- .../steps/SkipUpToDateStepTest.groovy | 4 +- 15 files changed, 98 insertions(+), 74 deletions(-) diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuter.java b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuter.java index 8bb4d12216f76..fffc5ce8f2d98 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuter.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuter.java @@ -294,9 +294,9 @@ public Optional getTimeout() { } @Override - public void visitIncrementalFileInputs(InputFilePropertyVisitor visitor) { + public void visitFileInputs(InputFilePropertyVisitor visitor) { for (InputFilePropertySpec inputFileProperty : context.getTaskProperties().getInputFileProperties()) { - Object value = inputFileProperty.getValue().call(); + Object value = inputFileProperty.getValue(); if (value != null) { visitor.visitInputFileProperty(inputFileProperty.getPropertyName(), value); } diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/DefaultInputFilePropertySpec.java b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/DefaultInputFilePropertySpec.java index 27fd792ff16ae..aaff1069f182e 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/DefaultInputFilePropertySpec.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/DefaultInputFilePropertySpec.java @@ -19,6 +19,8 @@ import org.gradle.api.file.FileCollection; import org.gradle.api.tasks.FileNormalizer; +import javax.annotation.Nullable; + public class DefaultInputFilePropertySpec extends AbstractFilePropertySpec implements InputFilePropertySpec { private final boolean skipWhenEmpty; private final PropertyValue value; @@ -35,7 +37,8 @@ public boolean isSkipWhenEmpty() { } @Override - public PropertyValue getValue() { - return value; + @Nullable + public Object getValue() { + return value.call(); } } diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/InputFilePropertySpec.java b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/InputFilePropertySpec.java index c5d464ef55b16..54e505fa3ffe3 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/InputFilePropertySpec.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/InputFilePropertySpec.java @@ -16,7 +16,10 @@ package org.gradle.api.internal.tasks.properties; +import javax.annotation.Nullable; + public interface InputFilePropertySpec extends FilePropertySpec { boolean isSkipWhenEmpty(); - PropertyValue getValue(); + @Nullable + Object getValue(); } diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvoker.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvoker.java index 28454f913a9cc..2c7fd9a49968a 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvoker.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvoker.java @@ -326,7 +326,7 @@ public Optional getTimeout() { } @Override - public void visitIncrementalFileInputs(InputFilePropertyVisitor visitor) { + public void visitFileInputs(InputFilePropertyVisitor visitor) { visitor.visitInputFileProperty(INPUT_ARTIFACT_PROPERTY_NAME, inputArtifact); } diff --git a/subprojects/execution/src/integTest/groovy/org/gradle/internal/execution/IncrementalExecutionIntegrationTest.groovy b/subprojects/execution/src/integTest/groovy/org/gradle/internal/execution/IncrementalExecutionIntegrationTest.groovy index e9635301695b7..8230d573959de 100644 --- a/subprojects/execution/src/integTest/groovy/org/gradle/internal/execution/IncrementalExecutionIntegrationTest.groovy +++ b/subprojects/execution/src/integTest/groovy/org/gradle/internal/execution/IncrementalExecutionIntegrationTest.groovy @@ -800,7 +800,7 @@ class IncrementalExecutionIntegrationTest extends Specification { } @Override - void visitIncrementalFileInputs(UnitOfWork.InputFilePropertyVisitor visitor) { + void visitFileInputs(UnitOfWork.InputFilePropertyVisitor visitor) { for (entry in inputs.entrySet()) { if (entry.value != null) { visitor.visitInputFileProperty(entry.key, entry.value) diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/UnitOfWork.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/UnitOfWork.java index 109e8d425c62f..16e551056f4fd 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/UnitOfWork.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/UnitOfWork.java @@ -39,7 +39,7 @@ public interface UnitOfWork extends CacheableEntity { boolean isIncremental(); - void visitIncrementalFileInputs(InputFilePropertyVisitor visitor); + void visitFileInputs(InputFilePropertyVisitor visitor); void visitOutputProperties(OutputPropertyVisitor visitor); diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/DefaultExecutionStateChangeDetector.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/DefaultExecutionStateChangeDetector.java index 5f0005069cced..14ac54455ed22 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/DefaultExecutionStateChangeDetector.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/DefaultExecutionStateChangeDetector.java @@ -18,7 +18,8 @@ import com.google.common.collect.ImmutableCollection; import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableListMultimap; +import com.google.common.collect.ImmutableMultimap; +import com.google.common.collect.ImmutableSortedMap; import org.gradle.api.Describable; import org.gradle.internal.change.CachingChangeContainer; import org.gradle.internal.change.Change; @@ -28,6 +29,7 @@ import org.gradle.internal.change.SummarizingChangeContainer; import org.gradle.internal.execution.history.AfterPreviousExecutionState; import org.gradle.internal.execution.history.BeforeExecutionState; +import org.gradle.internal.fingerprint.CurrentFileCollectionFingerprint; public class DefaultExecutionStateChangeDetector implements ExecutionStateChangeDetector { @Override @@ -77,6 +79,7 @@ public ExecutionStateChanges detectChanges(AfterPreviousExecutionState lastExecu ChangeContainer outputFileChanges = caching(uncachedOutputChanges); ChangeContainer rebuildTriggeringChanges = errorHandling(executable, new SummarizingChangeContainer(previousSuccessState, implementationChanges, inputPropertyChanges, inputPropertyValueChanges, outputFilePropertyChanges, outputFileChanges, inputFilePropertyChanges)); + ImmutableList.Builder builder = ImmutableList.builder(); MessageCollectingChangeVisitor visitor = new MessageCollectingChangeVisitor(builder, ExecutionStateChangeDetector.MAX_OUT_OF_DATE_MESSAGES); rebuildTriggeringChanges.accept(visitor); @@ -88,12 +91,10 @@ public ExecutionStateChanges detectChanges(AfterPreviousExecutionState lastExecu inputFileChanges.accept(visitor); } - return new DetectedExecutionStateChanges( - inputFileChanges, - builder.build(), - rebuildRequired, - thisExecution - ); + ImmutableList allChangeMessages = builder.build(); + return rebuildRequired + ? new NonIncrementalDetectedExecutionStateChanges(allChangeMessages, thisExecution.getInputFileProperties()) + : new IncrementalDetectedExecutionStateChanges(inputFileChanges, allChangeMessages); } private static ChangeContainer caching(ChangeContainer wrapped) { @@ -134,34 +135,49 @@ public boolean accept(ChangeVisitor visitor) { } } - private static class DetectedExecutionStateChanges implements ExecutionStateChanges { + private static class IncrementalDetectedExecutionStateChanges extends AbstractDetectedExecutionStateChanges implements ExecutionStateChanges { private final InputFileChanges inputFileChanges; - private final ImmutableList allChangeMessages; - private final boolean rebuildRequired; - private final BeforeExecutionState thisExecution; - public DetectedExecutionStateChanges( + public IncrementalDetectedExecutionStateChanges( InputFileChanges inputFileChanges, - ImmutableList allChangeMessages, - boolean rebuildRequired, - BeforeExecutionState thisExecution + ImmutableList allChangeMessages ) { + super(allChangeMessages); this.inputFileChanges = inputFileChanges; - this.allChangeMessages = allChangeMessages; - this.rebuildRequired = rebuildRequired; - this.thisExecution = thisExecution; } @Override - public ImmutableList getAllChangeMessages() { - return allChangeMessages; + public InputChangesInternal createInputChanges(ImmutableMultimap incrementalParameterNameByValue) { + return new IncrementalInputChanges(inputFileChanges, incrementalParameterNameByValue); + } + } + + private static class NonIncrementalDetectedExecutionStateChanges extends AbstractDetectedExecutionStateChanges implements ExecutionStateChanges { + private final ImmutableSortedMap inputFileProperties; + + public NonIncrementalDetectedExecutionStateChanges( + ImmutableList allChangeMessages, + ImmutableSortedMap inputFileProperties + ) { + super(allChangeMessages); + this.inputFileProperties = inputFileProperties; } @Override - public InputChangesInternal getInputChanges(ImmutableListMultimap incrementalInputs) { - return rebuildRequired - ? new NonIncrementalInputChanges(thisExecution.getInputFileProperties(), incrementalInputs) - : new IncrementalInputChanges(inputFileChanges, incrementalInputs); + public InputChangesInternal createInputChanges(ImmutableMultimap incrementalParameterNameByValue) { + return new NonIncrementalInputChanges(inputFileProperties, incrementalParameterNameByValue); + } + } + + private static class AbstractDetectedExecutionStateChanges { + private final ImmutableList allChangeMessages; + + public AbstractDetectedExecutionStateChanges(ImmutableList allChangeMessages) { + this.allChangeMessages = allChangeMessages; + } + + public ImmutableList getAllChangeMessages() { + return allChangeMessages; } } diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/ExecutionStateChanges.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/ExecutionStateChanges.java index b5535ba8f4144..9a90cfe610f6b 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/ExecutionStateChanges.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/ExecutionStateChanges.java @@ -17,7 +17,7 @@ package org.gradle.internal.execution.history.changes; import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableListMultimap; +import com.google.common.collect.ImmutableMultimap; /** * Represents the complete changes in execution state @@ -29,5 +29,10 @@ public interface ExecutionStateChanges { */ ImmutableList getAllChangeMessages(); - InputChangesInternal getInputChanges(ImmutableListMultimap incrementalInputs); + /** + * Creates the input changes for the given. + * + * @param incrementalParameterNameByValue Mapping from the actual value of to the parameter name. + */ + InputChangesInternal createInputChanges(ImmutableMultimap incrementalParameterNameByValue); } diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/IncrementalInputChanges.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/IncrementalInputChanges.java index 65dbf18aa0c86..56fa44a666782 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/IncrementalInputChanges.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/IncrementalInputChanges.java @@ -16,8 +16,8 @@ package org.gradle.internal.execution.history.changes; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableListMultimap; +import com.google.common.collect.ImmutableCollection; +import com.google.common.collect.ImmutableMultimap; import org.gradle.api.tasks.incremental.InputFileDetails; import org.gradle.internal.Cast; import org.gradle.internal.change.CollectingChangeVisitor; @@ -26,9 +26,9 @@ public class IncrementalInputChanges implements InputChangesInternal { private final InputFileChanges changes; - private final ImmutableListMultimap propertyNamesByValue; + private final ImmutableMultimap propertyNamesByValue; - public IncrementalInputChanges(InputFileChanges changes, ImmutableListMultimap propertyNamesByValue) { + public IncrementalInputChanges(InputFileChanges changes, ImmutableMultimap propertyNamesByValue) { this.changes = changes; this.propertyNamesByValue = propertyNamesByValue; } @@ -46,15 +46,15 @@ public Iterable getFileChanges(Object parameterValue) { return Cast.uncheckedNonnullCast(visitor.getChanges()); } - public static String determinePropertyName(Object propertyValue, ImmutableListMultimap propertyNameByValue) { - ImmutableList propertyNames = propertyNameByValue.get(propertyValue); + public static String determinePropertyName(Object propertyValue, ImmutableMultimap propertyNameByValue) { + ImmutableCollection propertyNames = propertyNameByValue.get(propertyValue); if (propertyNames.isEmpty()) { throw new UnsupportedOperationException("Cannot query incremental changes: No property found for value " + propertyValue + "."); } if (propertyNames.size() > 1) { throw new UnsupportedOperationException(String.format("Cannot query incremental changes: More that one property found with value %s: %s.", propertyValue, propertyNames)); } - return propertyNames.get(0); + return propertyNames.iterator().next(); } @Override diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/NonIncrementalInputChanges.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/NonIncrementalInputChanges.java index 42d266e1db9ce..3db91f3c8ccdb 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/NonIncrementalInputChanges.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/NonIncrementalInputChanges.java @@ -16,7 +16,7 @@ package org.gradle.internal.execution.history.changes; -import com.google.common.collect.ImmutableListMultimap; +import com.google.common.collect.ImmutableMultimap; import com.google.common.collect.ImmutableSortedMap; import org.gradle.api.tasks.incremental.InputFileDetails; import org.gradle.internal.Cast; @@ -31,9 +31,9 @@ public class NonIncrementalInputChanges implements InputChangesInternal { private final ImmutableSortedMap currentInputs; - private final ImmutableListMultimap propertyNameByValue; + private final ImmutableMultimap propertyNameByValue; - public NonIncrementalInputChanges(ImmutableSortedMap currentInputs, ImmutableListMultimap propertyNamesByValue) { + public NonIncrementalInputChanges(ImmutableSortedMap currentInputs, ImmutableMultimap propertyNamesByValue) { this.currentInputs = currentInputs; this.propertyNameByValue = propertyNamesByValue; } diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/ExecuteStep.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/ExecuteStep.java index 58caac49c703d..c965a6ff925e3 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/ExecuteStep.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/ExecuteStep.java @@ -16,20 +16,17 @@ package org.gradle.internal.execution.steps; -import com.google.common.collect.ImmutableListMultimap; +import com.google.common.collect.ImmutableMultimap; import org.gradle.internal.Try; import org.gradle.internal.execution.ExecutionOutcome; import org.gradle.internal.execution.IncrementalChangesContext; import org.gradle.internal.execution.Result; import org.gradle.internal.execution.Step; import org.gradle.internal.execution.UnitOfWork; -import org.gradle.internal.execution.history.changes.ExecutionStateChanges; import org.gradle.internal.execution.history.changes.InputChangesInternal; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.util.Optional; - public class ExecuteStep implements Step { private static final Logger LOGGER = LoggerFactory.getLogger(ExecuteStep.class); @@ -50,22 +47,21 @@ public Try getOutcome() { } private InputChangesInternal determineInputChanges(UnitOfWork work, IncrementalChangesContext context) { - Optional changes = context.getChanges(); - if (!changes.isPresent()) { - throw new UnsupportedOperationException("Cannot use input changes when input tracking is disabled."); - } - - ImmutableListMultimap incrementalInputs = determineIncrementalInputs(work); - InputChangesInternal inputChanges = changes.get().getInputChanges(incrementalInputs); - if (!inputChanges.isIncremental()) { - LOGGER.info("All input files are considered out-of-date for incremental {}.", work.getDisplayName()); - } - return inputChanges; + return context.getChanges() + .map(changes -> { + ImmutableMultimap incrementalParameterNameByValue = determineIncrementalParameterNameByValue(work); + InputChangesInternal inputChanges = changes.createInputChanges(incrementalParameterNameByValue); + if (!inputChanges.isIncremental()) { + LOGGER.info("All input files are considered out-of-date for incremental {}.", work.getDisplayName()); + } + return inputChanges; + }) + .orElseThrow(() -> new UnsupportedOperationException("Cannot use input changes when input tracking is disabled.")); } - private ImmutableListMultimap determineIncrementalInputs(UnitOfWork work) { - ImmutableListMultimap.Builder builder = ImmutableListMultimap.builder(); - work.visitIncrementalFileInputs((name, value) -> builder.put(value, name)); + private ImmutableMultimap determineIncrementalParameterNameByValue(UnitOfWork work) { + ImmutableMultimap.Builder builder = ImmutableMultimap.builder(); + work.visitFileInputs((name, value) -> builder.put(value, name)); return builder.build(); } } diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/ResolveChangesStep.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/ResolveChangesStep.java index 6ee4c8af8fd9a..b99c976d830e2 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/ResolveChangesStep.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/ResolveChangesStep.java @@ -17,7 +17,7 @@ package org.gradle.internal.execution.steps; import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableListMultimap; +import com.google.common.collect.ImmutableMultimap; import org.gradle.internal.execution.IncrementalChangesContext; import org.gradle.internal.execution.IncrementalContext; import org.gradle.internal.execution.Result; @@ -112,11 +112,11 @@ public ImmutableList getAllChangeMessages() { } @Override - public InputChangesInternal getInputChanges(ImmutableListMultimap incrementalInputs) { + public InputChangesInternal createInputChanges(ImmutableMultimap incrementalParameterNameByValue) { if (beforeExecutionState == null) { throw new UnsupportedOperationException("Cannot query input changes when input tracking is disabled."); } - return new NonIncrementalInputChanges(beforeExecutionState.getInputFileProperties(), incrementalInputs); + return new NonIncrementalInputChanges(beforeExecutionState.getInputFileProperties(), incrementalParameterNameByValue); } } } diff --git a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/ExecuteStepTest.groovy b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/ExecuteStepTest.groovy index f0660595c291b..3089036b0ee03 100644 --- a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/ExecuteStepTest.groovy +++ b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/ExecuteStepTest.groovy @@ -16,7 +16,7 @@ package org.gradle.internal.execution.steps -import com.google.common.collect.ImmutableListMultimap +import com.google.common.collect.ImmutableMultimap import org.gradle.internal.execution.ExecutionOutcome import org.gradle.internal.execution.IncrementalChangesContext import org.gradle.internal.execution.UnitOfWork @@ -76,10 +76,10 @@ class ExecuteStepTest extends Specification { 1 * context.work >> work 1 * work.incremental >> true 1 * context.changes >> optionalChanges - 1 * work.visitIncrementalFileInputs(_) >> { args -> + 1 * work.visitFileInputs(_) >> { args -> ((UnitOfWork.InputFilePropertyVisitor) args[0]).visitInputFileProperty("fileInput", "some/path") } - 1 * changes.getInputChanges(ImmutableListMultimap.of("some/path", "fileInput")) >> inputChanges + 1 * changes.createInputChanges(ImmutableMultimap.of("some/path", "fileInput")) >> inputChanges 1 * work.execute(inputChanges) 1 * inputChanges.incremental >> true 0 * _ diff --git a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/ResolveChangesStepTest.groovy b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/ResolveChangesStepTest.groovy index 3587166c31bfd..6e6bf30121f5b 100644 --- a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/ResolveChangesStepTest.groovy +++ b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/ResolveChangesStepTest.groovy @@ -18,6 +18,7 @@ package org.gradle.internal.execution.steps import com.google.common.collect.ImmutableList import com.google.common.collect.ImmutableListMultimap +import com.google.common.collect.ImmutableMultimap import com.google.common.collect.ImmutableSortedMap import org.gradle.internal.execution.IncrementalChangesContext import org.gradle.internal.execution.IncrementalContext @@ -44,9 +45,9 @@ class ResolveChangesStepTest extends StepSpec { 1 * context.work >> work 1 * delegate.execute(_) >> { IncrementalChangesContext delegateContext -> def changes = delegateContext.changes.get() - assert changes.getAllChangeMessages() == ImmutableList.of("Forced rebuild.") + assert changes.allChangeMessages == ImmutableList.of("Forced rebuild.") try { - changes.getInputChanges(ImmutableListMultimap.of()) + changes.createInputChanges(ImmutableListMultimap.of()) assert false } catch (UnsupportedOperationException e) { assert e.message == 'Cannot query input changes when input tracking is disabled.' @@ -85,8 +86,8 @@ class ResolveChangesStepTest extends StepSpec { 1 * context.work >> work 1 * delegate.execute(_) >> { IncrementalChangesContext delegateContext -> def changes = delegateContext.changes.get() - assert !changes.getInputChanges(ImmutableListMultimap.of()).incremental - assert changes.getAllChangeMessages() == ImmutableList.of("No history is available.") + assert !changes.createInputChanges(ImmutableMultimap.of()).incremental + assert changes.allChangeMessages == ImmutableList.of("No history is available.") return delegateResult } 1 * context.rebuildReason >> Optional.empty() diff --git a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/SkipUpToDateStepTest.groovy b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/SkipUpToDateStepTest.groovy index 1adcd791d28c6..765c6de23f43a 100644 --- a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/SkipUpToDateStepTest.groovy +++ b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/SkipUpToDateStepTest.groovy @@ -42,7 +42,7 @@ class SkipUpToDateStepTest extends StepSpec { result.executionReasons.empty 1 * context.changes >> Optional.of(changes) - 1 * changes.getAllChangeMessages() >> ImmutableList.of() + 1 * changes.allChangeMessages >> ImmutableList.of() 1 * context.afterPreviousExecutionState >> Optional.of(Mock(AfterPreviousExecutionState)) 0 * _ } @@ -61,7 +61,7 @@ class SkipUpToDateStepTest extends StepSpec { 1 * context.getWork() >> work 1 * context.changes >> Optional.of(changes) - 1 * changes.getAllChangeMessages() >> ImmutableList.of("change") + 1 * changes.allChangeMessages >> ImmutableList.of("change") 1 * delegate.execute(context) >> delegateResult 0 * _ From 5e08aaad9dbddfda762904006127f2662af33453 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=B3r=C3=A1nt=20Pint=C3=A9r?= Date: Thu, 14 Mar 2019 18:19:52 +0100 Subject: [PATCH 549/853] Deprecate the use of custom local build caches We are removing this option because custom local caches complicate the architecture unnecessarily. By always expecting a DirectoryBuildCache we can simplify things a lot. We'll remove the option completely in 6.0. --- ...ldCacheConfigurationIntegrationTest.groovy | 33 ++++++++++++++++++- ...rationBuildOperationIntegrationTest.groovy | 1 + .../DefaultBuildCacheConfiguration.java | 13 ++++++-- .../caching/local/internal/package-info.java | 20 +++++++++++ .../BuildCacheConfiguration.java | 4 +++ .../caching/local/DirectoryBuildCache.java | 0 .../gradle/caching/local/package-info.java | 0 subprojects/docs/src/docs/release/notes.md | 6 ++++ 8 files changed, 73 insertions(+), 4 deletions(-) create mode 100644 subprojects/build-cache/src/main/java/org/gradle/caching/local/internal/package-info.java rename subprojects/{build-cache => core-api}/src/main/java/org/gradle/caching/local/DirectoryBuildCache.java (100%) rename subprojects/{build-cache => core-api}/src/main/java/org/gradle/caching/local/package-info.java (100%) diff --git a/subprojects/build-cache/src/integTest/groovy/org/gradle/caching/configuration/BuildCacheConfigurationIntegrationTest.groovy b/subprojects/build-cache/src/integTest/groovy/org/gradle/caching/configuration/BuildCacheConfigurationIntegrationTest.groovy index daccf3be15998..e710f72fb595e 100644 --- a/subprojects/build-cache/src/integTest/groovy/org/gradle/caching/configuration/BuildCacheConfigurationIntegrationTest.groovy +++ b/subprojects/build-cache/src/integTest/groovy/org/gradle/caching/configuration/BuildCacheConfigurationIntegrationTest.groovy @@ -194,7 +194,7 @@ class BuildCacheConfigurationIntegrationTest extends AbstractIntegrationSpec { failureHasCause("Build cache type 'CustomBuildCache' has not been registered.") } - def "emits a useful incubating message when using the build cache"() { + def "emits a useful message when using the build cache"() { when: executer.withBuildCacheEnabled() succeeds("tasks", "--info") @@ -269,6 +269,37 @@ class BuildCacheConfigurationIntegrationTest extends AbstractIntegrationSpec { localBuildCache.empty } + @Unroll + def "shows deprecation warning when using custom local cache using #customCacheConfig"() { + settingsFile << """ + class CustomBuildCache extends AbstractBuildCache {} + class CustomBuildCacheFactory implements BuildCacheServiceFactory { + @Override BuildCacheService createBuildCacheService(CustomBuildCache configuration, Describer describer) { + throw new UnsupportedOperationException() + } + } + + buildCache { + registerBuildCacheService(CustomBuildCache, CustomBuildCacheFactory) + + $customCacheConfig + } + """ + executer.expectDeprecationWarning() + + when: + run "help" + + then: + output.contains("Using a local cache type other than DirectoryBuildCache has been deprecated. This is scheduled to be removed in Gradle 6.0.") + + where: + customCacheConfig << [ + "local(CustomBuildCache).enabled = false", + "local(CustomBuildCache) { enabled = false }" + ] + } + private static String customTaskCode() { """ @CacheableTask diff --git a/subprojects/build-cache/src/integTest/groovy/org/gradle/caching/internal/FinalizeBuildCacheConfigurationBuildOperationIntegrationTest.groovy b/subprojects/build-cache/src/integTest/groovy/org/gradle/caching/internal/FinalizeBuildCacheConfigurationBuildOperationIntegrationTest.groovy index b99becef08e9a..a4483ca881caf 100644 --- a/subprojects/build-cache/src/integTest/groovy/org/gradle/caching/internal/FinalizeBuildCacheConfigurationBuildOperationIntegrationTest.groovy +++ b/subprojects/build-cache/src/integTest/groovy/org/gradle/caching/internal/FinalizeBuildCacheConfigurationBuildOperationIntegrationTest.groovy @@ -81,6 +81,7 @@ class FinalizeBuildCacheConfigurationBuildOperationIntegrationTest extends Abstr } """ executer.withBuildCacheEnabled() + executer.expectDeprecationWarning() when: succeeds("help") diff --git a/subprojects/build-cache/src/main/java/org/gradle/caching/configuration/internal/DefaultBuildCacheConfiguration.java b/subprojects/build-cache/src/main/java/org/gradle/caching/configuration/internal/DefaultBuildCacheConfiguration.java index 4cf1e683172b8..12cd0d0e8c71e 100644 --- a/subprojects/build-cache/src/main/java/org/gradle/caching/configuration/internal/DefaultBuildCacheConfiguration.java +++ b/subprojects/build-cache/src/main/java/org/gradle/caching/configuration/internal/DefaultBuildCacheConfiguration.java @@ -26,6 +26,7 @@ import org.gradle.internal.Actions; import org.gradle.internal.Cast; import org.gradle.internal.reflect.Instantiator; +import org.gradle.util.DeprecationLogger; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -57,18 +58,24 @@ public BuildCache getLocal() { @Override public T local(Class type) { + if (!type.equals(DirectoryBuildCache.class)) { + DeprecationLogger.nagUserOfDeprecated("Using a local cache type other than " + DirectoryBuildCache.class.getSimpleName()); + } return local(type, Actions.doNothing()); } @Override public T local(Class type, Action configuration) { + if (!type.equals(DirectoryBuildCache.class)) { + DeprecationLogger.nagUserOfDeprecated("Using a local cache type other than " + DirectoryBuildCache.class.getSimpleName()); + } if (!type.isInstance(local)) { if (local != null) { LOGGER.info("Replacing local build cache type {} with {}", local.getClass().getCanonicalName(), type.getCanonicalName()); } local = createLocalCacheConfiguration(instantiator, type, registrations); } - T configurationObject = Cast.uncheckedCast(local); + T configurationObject = Cast.uncheckedNonnullCast(local); configuration.execute(configurationObject); return configurationObject; } @@ -96,7 +103,7 @@ public T remote(Class type, Action configur } remote = createRemoteCacheConfiguration(instantiator, type, registrations); } - T configurationObject = Cast.uncheckedCast(remote); + T configurationObject = Cast.uncheckedNonnullCast(remote); configuration.execute(configurationObject); return configurationObject; } @@ -147,7 +154,7 @@ private static Class> buildCacheServiceFactoryType = registration.getFactoryType(); LOGGER.debug("Found {} registered for {}", buildCacheServiceFactoryType, registeredConfigurationType); - return Cast.uncheckedCast(buildCacheServiceFactoryType); + return Cast.uncheckedNonnullCast(buildCacheServiceFactoryType); } } // Couldn't find a registration for the given type diff --git a/subprojects/build-cache/src/main/java/org/gradle/caching/local/internal/package-info.java b/subprojects/build-cache/src/main/java/org/gradle/caching/local/internal/package-info.java new file mode 100644 index 0000000000000..701443b7c03b5 --- /dev/null +++ b/subprojects/build-cache/src/main/java/org/gradle/caching/local/internal/package-info.java @@ -0,0 +1,20 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +@NonNullApi +package org.gradle.caching.local.internal; + +import org.gradle.api.NonNullApi; diff --git a/subprojects/core-api/src/main/java/org/gradle/caching/configuration/BuildCacheConfiguration.java b/subprojects/core-api/src/main/java/org/gradle/caching/configuration/BuildCacheConfiguration.java index a622f41e8e7f1..9dcf56961b395 100644 --- a/subprojects/core-api/src/main/java/org/gradle/caching/configuration/BuildCacheConfiguration.java +++ b/subprojects/core-api/src/main/java/org/gradle/caching/configuration/BuildCacheConfiguration.java @@ -46,6 +46,8 @@ public interface BuildCacheConfiguration { /** * Configures the local cache with the given type. * + *

    Note: using any type except {@link org.gradle.caching.local.DirectoryBuildCache} is deprecated.

    + * *

    If a local build cache has already been configured with a different type, this method replaces it.

    *

    Storing ("push") in the local build cache is enabled by default.

    * @@ -56,6 +58,8 @@ public interface BuildCacheConfiguration { /** * Configures the local cache with the given type. * + *

    Note: using any type except {@link org.gradle.caching.local.DirectoryBuildCache} is deprecated.

    + * *

    If a local build cache has already been configured with a different type, this method replaces it.

    *

    If a local build cache has already been configured with the same type, this method configures it.

    *

    Storing ("push") in the local build cache is enabled by default.

    diff --git a/subprojects/build-cache/src/main/java/org/gradle/caching/local/DirectoryBuildCache.java b/subprojects/core-api/src/main/java/org/gradle/caching/local/DirectoryBuildCache.java similarity index 100% rename from subprojects/build-cache/src/main/java/org/gradle/caching/local/DirectoryBuildCache.java rename to subprojects/core-api/src/main/java/org/gradle/caching/local/DirectoryBuildCache.java diff --git a/subprojects/build-cache/src/main/java/org/gradle/caching/local/package-info.java b/subprojects/core-api/src/main/java/org/gradle/caching/local/package-info.java similarity index 100% rename from subprojects/build-cache/src/main/java/org/gradle/caching/local/package-info.java rename to subprojects/core-api/src/main/java/org/gradle/caching/local/package-info.java diff --git a/subprojects/docs/src/docs/release/notes.md b/subprojects/docs/src/docs/release/notes.md index 961dbe4424fa0..155cd36cfcdbe 100644 --- a/subprojects/docs/src/docs/release/notes.md +++ b/subprojects/docs/src/docs/release/notes.md @@ -53,6 +53,12 @@ The following are the newly deprecated items in this Gradle release. If you have ### Example deprecation --> +### Using custom local build cache implementations + +Using a custom build cache implementation for the local build cache is now deprecated. +The only allowed type will be `DirectoryBuildCache` going forward. +There is no change in the support for using custom build cache implementations as the remote build cache. + ### Breaking changes From 95f93d76d5985996e9c523de4df8510a5e9d0388 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=B3r=C3=A1nt=20Pint=C3=A9r?= Date: Mon, 11 Mar 2019 05:53:29 +0100 Subject: [PATCH 550/853] Notify about changing outputs early We can do this as soon as we've decided that the outputs will change, i.e. when we already know that we can't entirely skip executing the work. This removes some duplicate code, too. --- .../command/BuildCacheCommandFactory.java | 1 - .../command/BuildCacheLoadListener.java | 1 - .../BuildCacheCommandFactoryTest.groovy | 3 --- .../scopes/ExecutionGradleServices.java | 15 ++++++++------- .../ExecuteActionsTaskExecuterTest.groovy | 16 ++++++++-------- .../DefaultDependencyManagementServices.java | 14 +++++++------- .../IncrementalExecutionIntegrationTest.groovy | 18 +++++++++--------- .../steps/BroadcastChangingOutputsStep.java | 8 ++++---- .../internal/execution/steps/CacheStep.java | 10 ---------- .../BroadcastChangingOutputsStepTest.groovy | 2 +- 10 files changed, 37 insertions(+), 51 deletions(-) diff --git a/subprojects/build-cache-packaging/src/main/java/org/gradle/caching/internal/command/BuildCacheCommandFactory.java b/subprojects/build-cache-packaging/src/main/java/org/gradle/caching/internal/command/BuildCacheCommandFactory.java index 34dd3284b6c03..f5803aa65eaf2 100644 --- a/subprojects/build-cache-packaging/src/main/java/org/gradle/caching/internal/command/BuildCacheCommandFactory.java +++ b/subprojects/build-cache-packaging/src/main/java/org/gradle/caching/internal/command/BuildCacheCommandFactory.java @@ -98,7 +98,6 @@ public BuildCacheKey getKey() { @Override public BuildCacheLoadCommand.Result load(InputStream input) { - loadListener.beforeLoad(); try { BuildCacheEntryPacker.UnpackResult unpackResult = packer.unpack(entity, input, originMetadataFactory.createReader(entity)); ImmutableSortedMap snapshots = snapshotUnpackedData(unpackResult.getSnapshots()); diff --git a/subprojects/build-cache-packaging/src/main/java/org/gradle/caching/internal/command/BuildCacheLoadListener.java b/subprojects/build-cache-packaging/src/main/java/org/gradle/caching/internal/command/BuildCacheLoadListener.java index a6aa2ed88071e..e929739c6fca1 100644 --- a/subprojects/build-cache-packaging/src/main/java/org/gradle/caching/internal/command/BuildCacheLoadListener.java +++ b/subprojects/build-cache-packaging/src/main/java/org/gradle/caching/internal/command/BuildCacheLoadListener.java @@ -17,6 +17,5 @@ package org.gradle.caching.internal.command; public interface BuildCacheLoadListener { - void beforeLoad(); void afterLoadFailedAndWasCleanedUp(Throwable error); } diff --git a/subprojects/build-cache-packaging/src/test/groovy/org/gradle/caching/internal/command/BuildCacheCommandFactoryTest.groovy b/subprojects/build-cache-packaging/src/test/groovy/org/gradle/caching/internal/command/BuildCacheCommandFactoryTest.groovy index 155eeffe51367..7025e4bd94a76 100644 --- a/subprojects/build-cache-packaging/src/test/groovy/org/gradle/caching/internal/command/BuildCacheCommandFactoryTest.groovy +++ b/subprojects/build-cache-packaging/src/test/groovy/org/gradle/caching/internal/command/BuildCacheCommandFactoryTest.groovy @@ -83,7 +83,6 @@ class BuildCacheCommandFactoryTest extends Specification { def result = load.load(input) then: - 1 * loadListener.beforeLoad() 1 * originFactory.createReader(entity) >> originReader then: @@ -125,7 +124,6 @@ class BuildCacheCommandFactoryTest extends Specification { command.load(input) then: - 1 * loadListener.beforeLoad() 1 * originFactory.createReader(entity) >> originReader then: @@ -157,7 +155,6 @@ class BuildCacheCommandFactoryTest extends Specification { command.load(input) then: - 1 * loadListener.beforeLoad() 1 * originFactory.createReader(entity) >> originReader then: diff --git a/subprojects/core/src/main/java/org/gradle/internal/service/scopes/ExecutionGradleServices.java b/subprojects/core/src/main/java/org/gradle/internal/service/scopes/ExecutionGradleServices.java index c0578910dc1f3..4a0ab50cec139 100644 --- a/subprojects/core/src/main/java/org/gradle/internal/service/scopes/ExecutionGradleServices.java +++ b/subprojects/core/src/main/java/org/gradle/internal/service/scopes/ExecutionGradleServices.java @@ -31,6 +31,7 @@ import org.gradle.internal.concurrent.ExecutorFactory; import org.gradle.internal.concurrent.ParallelismConfigurationManager; import org.gradle.internal.event.ListenerManager; +import org.gradle.internal.execution.CurrentSnapshotResult; import org.gradle.internal.execution.IncrementalChangesContext; import org.gradle.internal.execution.IncrementalContext; import org.gradle.internal.execution.OutputChangeListener; @@ -126,13 +127,13 @@ public WorkExecutor createWorkExecutor( new SkipUpToDateStep( new RecordOutputsStep(outputFilesRepository, new StoreSnapshotsStep( - new CacheStep(buildCacheController, outputChangeListener, buildCacheCommandFactory, - new SnapshotOutputsStep(buildInvocationScopeId.getId(), - new CreateOutputsStep( - new CatchExceptionStep( - new TimeoutStep(timeoutHandler, - new CancelExecutionStep(cancellationToken, - new BroadcastChangingOutputsStep(outputChangeListener, + new BroadcastChangingOutputsStep(outputChangeListener, + new CacheStep(buildCacheController, outputChangeListener, buildCacheCommandFactory, + new SnapshotOutputsStep(buildInvocationScopeId.getId(), + new CreateOutputsStep( + new CatchExceptionStep( + new TimeoutStep(timeoutHandler, + new CancelExecutionStep(cancellationToken, new ExecuteStep() ) ) diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuterTest.groovy b/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuterTest.groovy index 3e0b645a7a8b6..8ac45641d077a 100644 --- a/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuterTest.groovy +++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuterTest.groovy @@ -33,7 +33,6 @@ import org.gradle.groovy.scripts.ScriptSource import org.gradle.initialization.DefaultBuildCancellationToken import org.gradle.internal.exceptions.DefaultMultiCauseException import org.gradle.internal.exceptions.MultiCauseException -import org.gradle.internal.execution.IncrementalChangesContext import org.gradle.internal.execution.IncrementalContext import org.gradle.internal.execution.OutputChangeListener import org.gradle.internal.execution.UpToDateResult @@ -77,14 +76,15 @@ class ExecuteActionsTaskExecuterTest extends Specification { def actionListener = Mock(TaskActionListener) def outputChangeListener = Mock(OutputChangeListener) def cancellationToken = new DefaultBuildCancellationToken() + def changeDetector = new DefaultExecutionStateChangeDetector() def workExecutor = new DefaultWorkExecutor( - new ResolveChangesStep(new DefaultExecutionStateChangeDetector(), - new SkipUpToDateStep( - new SnapshotOutputsStep(buildId, - new CatchExceptionStep( - new CancelExecutionStep(cancellationToken, - new BroadcastChangingOutputsStep(outputChangeListener, - new ExecuteStep() + new ResolveChangesStep<>(changeDetector, + new SkipUpToDateStep<>( + new BroadcastChangingOutputsStep<>(outputChangeListener, + new SnapshotOutputsStep<>(buildId, + new CatchExceptionStep<>( + new CancelExecutionStep<>(cancellationToken, + new ExecuteStep<>() ) ) ) diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/DefaultDependencyManagementServices.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/DefaultDependencyManagementServices.java index 0a2734134a8ba..373b2a713ac30 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/DefaultDependencyManagementServices.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/DefaultDependencyManagementServices.java @@ -228,13 +228,13 @@ WorkExecutor createWorkExecutor( return new DefaultWorkExecutor<>( new ResolveChangesStep<>(changeDetector, new SkipUpToDateStep<>( - new StoreSnapshotsStep<>( - new SnapshotOutputsStep<>(fixedUniqueId, - new CreateOutputsStep<>( - new CatchExceptionStep<>( - new TimeoutStep<>(timeoutHandler, - new BroadcastChangingOutputsStep<>(outputChangeListener, - new ExecuteStep<>() + new BroadcastChangingOutputsStep<>(outputChangeListener, + new StoreSnapshotsStep<>( + new SnapshotOutputsStep<>(fixedUniqueId, + new CreateOutputsStep<>( + new CatchExceptionStep<>( + new TimeoutStep<>(timeoutHandler, + new ExecuteStep<>() ) ) ) diff --git a/subprojects/execution/src/integTest/groovy/org/gradle/internal/execution/IncrementalExecutionIntegrationTest.groovy b/subprojects/execution/src/integTest/groovy/org/gradle/internal/execution/IncrementalExecutionIntegrationTest.groovy index 7901515517728..299c47988064b 100644 --- a/subprojects/execution/src/integTest/groovy/org/gradle/internal/execution/IncrementalExecutionIntegrationTest.groovy +++ b/subprojects/execution/src/integTest/groovy/org/gradle/internal/execution/IncrementalExecutionIntegrationTest.groovy @@ -122,15 +122,15 @@ class IncrementalExecutionIntegrationTest extends Specification { WorkExecutor getExecutor() { new DefaultWorkExecutor<>( - new ResolveChangesStep(changeDetector, - new SkipUpToDateStep( - new RecordOutputsStep(outputFilesRepository, - new StoreSnapshotsStep( - new SnapshotOutputsStep(buildInvocationScopeId.getId(), - new CreateOutputsStep( - new CatchExceptionStep( - new BroadcastChangingOutputsStep(outputChangeListener, - new ExecuteStep() + new ResolveChangesStep<>(changeDetector, + new SkipUpToDateStep<>( + new RecordOutputsStep<>(outputFilesRepository, + new BroadcastChangingOutputsStep<>(outputChangeListener, + new StoreSnapshotsStep<>( + new SnapshotOutputsStep<>(buildInvocationScopeId.getId(), + new CreateOutputsStep<>( + new CatchExceptionStep<>( + new ExecuteStep<>() ) ) ) diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/BroadcastChangingOutputsStep.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/BroadcastChangingOutputsStep.java index 348ae64bb0bde..8e390cc4cd55c 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/BroadcastChangingOutputsStep.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/BroadcastChangingOutputsStep.java @@ -24,21 +24,21 @@ import java.util.Optional; -public class BroadcastChangingOutputsStep implements Step { +public class BroadcastChangingOutputsStep implements Step { private final OutputChangeListener outputChangeListener; - private final Step delegate; + private final Step delegate; public BroadcastChangingOutputsStep( OutputChangeListener outputChangeListener, - Step delegate + Step delegate ) { this.outputChangeListener = outputChangeListener; this.delegate = delegate; } @Override - public Result execute(C context) { + public R execute(C context) { UnitOfWork work = context.getWork(); Optional> changingOutputs = work.getChangingOutputs(); diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/CacheStep.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/CacheStep.java index e9ef608fa1f75..37a75d9ab1ebe 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/CacheStep.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/CacheStep.java @@ -36,7 +36,6 @@ import org.slf4j.LoggerFactory; import javax.annotation.Nullable; -import java.util.Optional; public class CacheStep implements Step { private static final Logger LOGGER = LoggerFactory.getLogger(CacheStep.class); @@ -106,15 +105,6 @@ private BuildCacheCommandFactory.LoadMetadata load(UnitOfWork work, BuildCacheKe try { return buildCache.load( commandFactory.createLoad(cacheKey, work, new BuildCacheLoadListener() { - @Override - public void beforeLoad() { - Optional> changingOutputs = work.getChangingOutputs(); - changingOutputs.ifPresent(affectedPaths -> outputChangeListener.beforeOutputChange(affectedPaths)); - if (!changingOutputs.isPresent()) { - outputChangeListener.beforeOutputChange(); - } - } - @Override public void afterLoadFailedAndWasCleanedUp(Throwable error) { work.outputsRemovedAfterFailureToLoadFromCache(); diff --git a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/BroadcastChangingOutputsStepTest.groovy b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/BroadcastChangingOutputsStepTest.groovy index 470151b317fb8..7b031af4bdd3b 100644 --- a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/BroadcastChangingOutputsStepTest.groovy +++ b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/BroadcastChangingOutputsStepTest.groovy @@ -22,7 +22,7 @@ import org.gradle.internal.execution.Result class BroadcastChangingOutputsStepTest extends StepSpec { def outputChangeListener = Mock(OutputChangeListener) - def step = new BroadcastChangingOutputsStep(outputChangeListener, delegate) + def step = new BroadcastChangingOutputsStep<>(outputChangeListener, delegate) def context = Mock(Context) def delegateResult = Mock(Result) From b057abf07aa3c406def91cd0740abcea1d19b430 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=B3r=C3=A1nt=20Pint=C3=A9r?= Date: Thu, 14 Mar 2019 18:30:57 +0100 Subject: [PATCH 551/853] Add Try.getSuccessfulOrElse() --- .../src/main/java/org/gradle/internal/Try.java | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/subprojects/base-services/src/main/java/org/gradle/internal/Try.java b/subprojects/base-services/src/main/java/org/gradle/internal/Try.java index cba4f99c364b6..058f10d75fed3 100644 --- a/subprojects/base-services/src/main/java/org/gradle/internal/Try.java +++ b/subprojects/base-services/src/main/java/org/gradle/internal/Try.java @@ -65,7 +65,9 @@ public Try apply(T input) { public abstract void ifSuccessful(Consumer consumer); - public abstract void ifSuccessfulOrElse(Consumer successConsumer, Consumer failureConsumer); + public abstract void ifSuccessfulOrElse(Consumer successConsumer, Consumer failureConsumer); + + public abstract R getSuccessfulOrElse(Function successFunction, Function failureFunction); private static class Success extends Try { private final T value; @@ -114,10 +116,15 @@ public void ifSuccessful(Consumer consumer) { } @Override - public void ifSuccessfulOrElse(Consumer successConsumer, Consumer failureConsumer) { + public void ifSuccessfulOrElse(Consumer successConsumer, Consumer failureConsumer) { successConsumer.accept(value); } + @Override + public R getSuccessfulOrElse(Function successFunction, Function failureFunction) { + return successFunction.apply(value); + } + @Override public boolean equals(Object o) { if (this == o) { @@ -180,10 +187,15 @@ public void ifSuccessful(Consumer consumer) { } @Override - public void ifSuccessfulOrElse(Consumer successConsumer, Consumer failureConsumer) { + public void ifSuccessfulOrElse(Consumer successConsumer, Consumer failureConsumer) { failureConsumer.accept(failure); } + @Override + public R getSuccessfulOrElse(Function successFunction, Function failureFunction) { + return failureFunction.apply(failure); + } + @Override public boolean equals(Object o) { if (this == o) { From 65482521fa23610e8e7e148d5bac4bf56797b93d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=B3r=C3=A1nt=20Pint=C3=A9r?= Date: Thu, 14 Mar 2019 19:11:17 +0100 Subject: [PATCH 552/853] Fix tests --- ...ldCacheConfigurationIntegrationTest.groovy | 8 ++++- ...CacheBuildOperationsIntegrationTest.groovy | 29 ++++++++++++++----- 2 files changed, 29 insertions(+), 8 deletions(-) diff --git a/subprojects/build-cache/src/integTest/groovy/org/gradle/caching/configuration/BuildCacheConfigurationIntegrationTest.groovy b/subprojects/build-cache/src/integTest/groovy/org/gradle/caching/configuration/BuildCacheConfigurationIntegrationTest.groovy index e710f72fb595e..4a98053312954 100644 --- a/subprojects/build-cache/src/integTest/groovy/org/gradle/caching/configuration/BuildCacheConfigurationIntegrationTest.groovy +++ b/subprojects/build-cache/src/integTest/groovy/org/gradle/caching/configuration/BuildCacheConfigurationIntegrationTest.groovy @@ -150,11 +150,17 @@ class BuildCacheConfigurationIntegrationTest extends AbstractIntegrationSpec { assert buildCache.$cache instanceof AnotherBuildCache """ + if (expectDeprecation) { + executer.expectDeprecationWarning() + } + expect: succeeds("help") where: - cache << ["local", "remote"] + cache | expectDeprecation + "local" | true + "remote" | false } def "disables remote cache with --offline"() { diff --git a/subprojects/build-cache/src/integTest/groovy/org/gradle/caching/internal/BuildCacheBuildOperationsIntegrationTest.groovy b/subprojects/build-cache/src/integTest/groovy/org/gradle/caching/internal/BuildCacheBuildOperationsIntegrationTest.groovy index 16f7e1a256bf3..4ffe730c2a01a 100644 --- a/subprojects/build-cache/src/integTest/groovy/org/gradle/caching/internal/BuildCacheBuildOperationsIntegrationTest.groovy +++ b/subprojects/build-cache/src/integTest/groovy/org/gradle/caching/internal/BuildCacheBuildOperationsIntegrationTest.groovy @@ -227,24 +227,30 @@ class BuildCacheBuildOperationsIntegrationTest extends AbstractIntegrationSpec { } def "records unpack failure"() { - when: - local("reader.execute(new File('not.there'))", "writer.writeTo(new ${NullOutputStream.name}())") - settingsFile << """ - buildCache { local($localCacheClass) } - """ + def localCache = new TestBuildCache(file("local-cache")) + settingsFile << localCache.localCacheConfiguration() + buildFile << cacheableTask() << """ apply plugin: "base" tasks.create("t", CustomTask).paths << "out1" << "out2" """ + run("t") + + // Corrupt cached artifact + localCache.listCacheFiles().each { + it.bytes = [1, 2, 3, 4] + } + + when: executer.withStackTraceChecksDisabled() - succeeds("t") + succeeds("clean", "t") then: def failedUnpackOp = operations.only(BuildCacheArchiveUnpackBuildOperationType) failedUnpackOp.details.cacheKey != null failedUnpackOp.result == null - failedUnpackOp.failure =~ /org.gradle.api.UncheckedIOException:.* not.there/ + failedUnpackOp.failure =~ /Failed to unpack trees for task ':t'/ } def "records ops for miss then store"() { @@ -265,6 +271,10 @@ class BuildCacheBuildOperationsIntegrationTest extends AbstractIntegrationSpec { tasks.create("t", CustomTask).paths << "out1" << "out2" """ + if (expectDeprecation) { + executer.expectDeprecationWarning() + } + when: succeeds("t") @@ -296,6 +306,9 @@ class BuildCacheBuildOperationsIntegrationTest extends AbstractIntegrationSpec { localStore << [ true, false, false, false ] + expectDeprecation << [ + false, false, false, true + ] } def "records ops for remote hit"() { @@ -374,6 +387,8 @@ class BuildCacheBuildOperationsIntegrationTest extends AbstractIntegrationSpec { tasks.create("t", CustomTask).paths << "out1" << "out2" """ + executer.expectDeprecationWarning() + when: succeeds("t") From f7f65238139877f73c95c9fb5c5a9b546f870743 Mon Sep 17 00:00:00 2001 From: Paul Merlin Date: Thu, 14 Mar 2019 19:48:14 +0100 Subject: [PATCH 553/853] Fix Kotlin DSL sample in Organizing Gradle Projects Signed-off-by: Paul Merlin --- .../kotlin/gradle/integration-test.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subprojects/docs/src/samples/userguide/organizingGradleProjects/separatedTestTypes/kotlin/gradle/integration-test.gradle.kts b/subprojects/docs/src/samples/userguide/organizingGradleProjects/separatedTestTypes/kotlin/gradle/integration-test.gradle.kts index 1106fd8c9ebee..edad36b7cb9a9 100644 --- a/subprojects/docs/src/samples/userguide/organizingGradleProjects/separatedTestTypes/kotlin/gradle/integration-test.gradle.kts +++ b/subprojects/docs/src/samples/userguide/organizingGradleProjects/separatedTestTypes/kotlin/gradle/integration-test.gradle.kts @@ -1,6 +1,6 @@ +// tag::custom-source-set[] val sourceSets = the() -// tag::custom-source-set[] sourceSets { create("integTest") { java.srcDir(file("src/integTest/java")) From e112f38b862164b48b5dff1729e8ac94ae6e11f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=B3r=C3=A1nt=20Pint=C3=A9r?= Date: Thu, 14 Mar 2019 21:43:00 +0100 Subject: [PATCH 554/853] Use optional in CacheHandler.load() --- .../tasks/execution/ExecuteActionsTaskExecuter.java | 4 ++-- .../transform/DefaultTransformerInvoker.java | 4 ++-- .../org/gradle/internal/execution/CacheHandler.java | 2 +- .../gradle/internal/execution/steps/CacheStep.java | 11 +++++------ 4 files changed, 10 insertions(+), 11 deletions(-) diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuter.java b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuter.java index fe48c7ae3b2cf..6567867848de4 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuter.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuter.java @@ -259,7 +259,7 @@ public Optional> getChangingOutputs() { public CacheHandler createCacheHandler() { return new CacheHandler() { @Override - public Optional load(Function loader) { + public Optional load(Function> loader) { // TODO Log this when creating the build cache key perhaps? if (task.isHasCustomActions()) { LOGGER.info("Custom actions are attached to {}.", task); @@ -268,7 +268,7 @@ public Optional load(Function loader) { && context.getTaskExecutionMode().isAllowedToUseCachedResults() && context.getBuildCacheKey().isValid() ) { - return Optional.ofNullable(loader.apply(context.getBuildCacheKey())); + return loader.apply(context.getBuildCacheKey()); } else { return Optional.empty(); } diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvoker.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvoker.java index e87ba02e1454a..34bb93c041137 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvoker.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvoker.java @@ -359,11 +359,11 @@ public CacheHandler createCacheHandler() { TransformerExecutionBuildCacheKey cacheKey = new TransformerExecutionBuildCacheKey(hasher.hash()); return new CacheHandler() { @Override - public Optional load(Function loader) { + public Optional load(Function> loader) { if (!transformer.isCacheable()) { return Optional.empty(); } - return Optional.ofNullable(loader.apply(cacheKey)); + return loader.apply(cacheKey); } @Override diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/CacheHandler.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/CacheHandler.java index 2b459a5283733..7c19fca7f882a 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/CacheHandler.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/CacheHandler.java @@ -23,6 +23,6 @@ import java.util.function.Function; public interface CacheHandler { - Optional load(Function loader); + Optional load(Function> loader); void store(Consumer storer); } diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/CacheStep.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/CacheStep.java index 37a75d9ab1ebe..0191af5f53e5a 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/CacheStep.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/CacheStep.java @@ -35,7 +35,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import javax.annotation.Nullable; +import java.util.Optional; public class CacheStep implements Step { private static final Logger LOGGER = LoggerFactory.getLogger(CacheStep.class); @@ -100,17 +100,16 @@ public ImmutableSortedMap getFinalOutp }); } - @Nullable - private BuildCacheCommandFactory.LoadMetadata load(UnitOfWork work, BuildCacheKey cacheKey) { + private Optional load(UnitOfWork work, BuildCacheKey cacheKey) { try { - return buildCache.load( + return Optional.ofNullable(buildCache.load( commandFactory.createLoad(cacheKey, work, new BuildCacheLoadListener() { @Override public void afterLoadFailedAndWasCleanedUp(Throwable error) { work.outputsRemovedAfterFailureToLoadFromCache(); } }) - ); + )); } catch (UnrecoverableUnpackingException e) { // We didn't manage to recover from the unpacking error, there might be leftover // garbage among the task's outputs, thus we must fail the build @@ -118,7 +117,7 @@ public void afterLoadFailedAndWasCleanedUp(Throwable error) { } catch (Exception e) { // There was a failure during downloading, previous task outputs should be unaffected LOGGER.warn("Failed to load cache entry for {}, falling back to executing task", work.getDisplayName(), e); - return null; + return Optional.empty(); } } From efc36d4e9de590bb7547928dee9fedacccdc218b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=B3r=C3=A1nt=20Pint=C3=A9r?= Date: Thu, 14 Mar 2019 21:44:16 +0100 Subject: [PATCH 555/853] Remove unnecessary listener --- .../internal/service/scopes/ExecutionGradleServices.java | 2 +- .../java/org/gradle/internal/execution/steps/CacheStep.java | 4 ---- .../org/gradle/internal/execution/steps/CacheStepTest.groovy | 4 +--- 3 files changed, 2 insertions(+), 8 deletions(-) diff --git a/subprojects/core/src/main/java/org/gradle/internal/service/scopes/ExecutionGradleServices.java b/subprojects/core/src/main/java/org/gradle/internal/service/scopes/ExecutionGradleServices.java index 4a0ab50cec139..408d80671fee5 100644 --- a/subprojects/core/src/main/java/org/gradle/internal/service/scopes/ExecutionGradleServices.java +++ b/subprojects/core/src/main/java/org/gradle/internal/service/scopes/ExecutionGradleServices.java @@ -128,7 +128,7 @@ public WorkExecutor createWorkExecutor( new RecordOutputsStep(outputFilesRepository, new StoreSnapshotsStep( new BroadcastChangingOutputsStep(outputChangeListener, - new CacheStep(buildCacheController, outputChangeListener, buildCacheCommandFactory, + new CacheStep(buildCacheController, buildCacheCommandFactory, new SnapshotOutputsStep(buildInvocationScopeId.getId(), new CreateOutputsStep( new CatchExceptionStep( diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/CacheStep.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/CacheStep.java index 0191af5f53e5a..09314d15fa839 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/CacheStep.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/CacheStep.java @@ -28,7 +28,6 @@ import org.gradle.internal.execution.CurrentSnapshotResult; import org.gradle.internal.execution.ExecutionOutcome; import org.gradle.internal.execution.IncrementalChangesContext; -import org.gradle.internal.execution.OutputChangeListener; import org.gradle.internal.execution.Step; import org.gradle.internal.execution.UnitOfWork; import org.gradle.internal.fingerprint.CurrentFileCollectionFingerprint; @@ -41,18 +40,15 @@ public class CacheStep implements Step delegate; public CacheStep( BuildCacheController buildCache, - OutputChangeListener outputChangeListener, BuildCacheCommandFactory commandFactory, Step delegate ) { this.buildCache = buildCache; - this.outputChangeListener = outputChangeListener; this.commandFactory = commandFactory; this.delegate = delegate; } diff --git a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/CacheStepTest.groovy b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/CacheStepTest.groovy index 9c04666139643..01dc500c6633c 100644 --- a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/CacheStepTest.groovy +++ b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/CacheStepTest.groovy @@ -24,13 +24,11 @@ import org.gradle.internal.execution.CacheHandler import org.gradle.internal.execution.CurrentSnapshotResult import org.gradle.internal.execution.ExecutionOutcome import org.gradle.internal.execution.IncrementalChangesContext -import org.gradle.internal.execution.OutputChangeListener class CacheStepTest extends StepSpec implements FingerprinterFixture { def buildCacheController = Mock(BuildCacheController) def buildCacheCommandFactory = Mock(BuildCacheCommandFactory) - def outputChangeListener = Mock(OutputChangeListener) - def step = new CacheStep(buildCacheController, outputChangeListener, buildCacheCommandFactory, delegate) + def step = new CacheStep(buildCacheController, buildCacheCommandFactory, delegate) def cacheHandler = Mock(CacheHandler) def loadMetadata = Mock(BuildCacheCommandFactory.LoadMetadata) From 984a04459da2dd29c6662729dda16e051847cecf Mon Sep 17 00:00:00 2001 From: Stefan Wolf Date: Thu, 14 Mar 2019 22:34:35 +0100 Subject: [PATCH 556/853] Determine outcome of work in execution step By using the information if the work did any work or not. --- .../execution/ExecuteActionsTaskExecuter.java | 9 ++----- .../transform/DefaultTransformerInvoker.java | 5 ++-- ...IncrementalExecutionIntegrationTest.groovy | 10 +++---- .../gradle/internal/execution/UnitOfWork.java | 7 ++++- .../internal/execution/steps/ExecuteStep.java | 15 ++++++++++- .../execution/steps/ExecuteStepTest.groovy | 27 ++++++++++++++----- 6 files changed, 49 insertions(+), 24 deletions(-) diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuter.java b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuter.java index fffc5ce8f2d98..06a4c6f17028d 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuter.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuter.java @@ -190,18 +190,13 @@ public String getIdentity() { } @Override - public ExecutionOutcome execute(@Nullable InputChangesInternal inputChanges) { + public WorkResult execute(@Nullable InputChangesInternal inputChanges) { task.getState().setExecuting(true); try { LOGGER.debug("Executing actions for {}.", task); actionListener.beforeActions(task); - boolean incremental = inputChanges != null && inputChanges.isIncremental(); executeActions(task, inputChanges); - return task.getState().getDidWork() - ? incremental - ? ExecutionOutcome.EXECUTED_INCREMENTALLY - : ExecutionOutcome.EXECUTED_NON_INCREMENTALLY - : ExecutionOutcome.UP_TO_DATE; + return task.getState().getDidWork() ? WorkResult.DID_WORK : WorkResult.DID_NO_WORK; } finally { task.getState().setExecuting(false); actionListener.afterActions(task); diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvoker.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvoker.java index 2c7fd9a49968a..447af964125d7 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvoker.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvoker.java @@ -30,7 +30,6 @@ import org.gradle.internal.UncheckedException; import org.gradle.internal.classloader.ClassLoaderHierarchyHasher; import org.gradle.internal.execution.CacheHandler; -import org.gradle.internal.execution.ExecutionOutcome; import org.gradle.internal.execution.IncrementalContext; import org.gradle.internal.execution.UnitOfWork; import org.gradle.internal.execution.UpToDateResult; @@ -259,7 +258,7 @@ public TransformerExecution( } @Override - public ExecutionOutcome execute(@Nullable InputChangesInternal inputChanges) { + public WorkResult execute(@Nullable InputChangesInternal inputChanges) { File outputDir = workspace.getOutputDirectory(); File resultsFile = workspace.getResultsFile(); @@ -270,7 +269,7 @@ public ExecutionOutcome execute(@Nullable InputChangesInternal inputChanges) { } ImmutableList result = transformer.transform(inputArtifact, outputDir, dependencies, inputChanges); writeResultsFile(outputDir, resultsFile, result); - return incremental ? ExecutionOutcome.EXECUTED_INCREMENTALLY : ExecutionOutcome.EXECUTED_NON_INCREMENTALLY; + return WorkResult.DID_WORK; } private void writeResultsFile(File outputDir, File resultsFile, ImmutableList result) { diff --git a/subprojects/execution/src/integTest/groovy/org/gradle/internal/execution/IncrementalExecutionIntegrationTest.groovy b/subprojects/execution/src/integTest/groovy/org/gradle/internal/execution/IncrementalExecutionIntegrationTest.groovy index 8230d573959de..34dffc197efc3 100644 --- a/subprojects/execution/src/integTest/groovy/org/gradle/internal/execution/IncrementalExecutionIntegrationTest.groovy +++ b/subprojects/execution/src/integTest/groovy/org/gradle/internal/execution/IncrementalExecutionIntegrationTest.groovy @@ -152,7 +152,7 @@ class IncrementalExecutionIntegrationTest extends Specification { "file": [file("parent/outFile")], "files": [file("parent1/outFile"), file("parent2/outputFile1"), file("parent2/outputFile2")], ).withWork { -> - EXECUTED_NON_INCREMENTALLY + UnitOfWork.WorkResult.DID_WORK }.build() when: @@ -697,11 +697,11 @@ class IncrementalExecutionIntegrationTest extends Specification { } class UnitOfWorkBuilder { - private Supplier work = { -> + private Supplier work = { -> create.each { it -> it.createFile() } - return EXECUTED_NON_INCREMENTALLY + return UnitOfWork.WorkResult.DID_WORK } private Map inputProperties = [prop: "value"] private Map> inputs = inputFiles @@ -711,7 +711,7 @@ class IncrementalExecutionIntegrationTest extends Specification { private ImplementationSnapshot implementation = ImplementationSnapshot.of(UnitOfWork.name, HashCode.fromInt(1234)) private - UnitOfWorkBuilder withWork(Supplier closure) { + UnitOfWorkBuilder withWork(Supplier closure) { work = closure return this } @@ -773,7 +773,7 @@ class IncrementalExecutionIntegrationTest extends Specification { boolean executed @Override - ExecutionOutcome execute(@Nullable InputChangesInternal inputChanges) { + UnitOfWork.WorkResult execute(@Nullable InputChangesInternal inputChanges) { executed = true return work.get() } diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/UnitOfWork.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/UnitOfWork.java index 16e551056f4fd..2a4709bb98660 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/UnitOfWork.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/UnitOfWork.java @@ -33,7 +33,7 @@ public interface UnitOfWork extends CacheableEntity { /** * Executes the work synchronously. */ - ExecutionOutcome execute(@Nullable InputChangesInternal inputChanges); + WorkResult execute(@Nullable InputChangesInternal inputChanges); Optional getTimeout(); @@ -79,6 +79,11 @@ interface OutputPropertyVisitor { void visitOutputProperty(String name, TreeType type, FileCollection roots); } + enum WorkResult { + DID_WORK, + DID_NO_WORK + } + ExecutionHistoryStore getExecutionHistoryStore(); ImmutableSortedMap snapshotAfterOutputsGenerated(); diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/ExecuteStep.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/ExecuteStep.java index c965a6ff925e3..292470429de61 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/ExecuteStep.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/ExecuteStep.java @@ -37,7 +37,9 @@ public Result execute(C context) { ? determineInputChanges(work, context) : null; - ExecutionOutcome outcome = work.execute(inputChanges); + boolean incremental = inputChanges != null && inputChanges.isIncremental(); + UnitOfWork.WorkResult result = work.execute(inputChanges); + ExecutionOutcome outcome = determineOutcome(result, incremental); return new Result() { @Override public Try getOutcome() { @@ -46,6 +48,17 @@ public Try getOutcome() { }; } + private ExecutionOutcome determineOutcome(UnitOfWork.WorkResult result, boolean incremental) { + switch (result) { + case DID_NO_WORK: + return ExecutionOutcome.UP_TO_DATE; + case DID_WORK: + return incremental ? ExecutionOutcome.EXECUTED_INCREMENTALLY : ExecutionOutcome.EXECUTED_NON_INCREMENTALLY; + default: + throw new IllegalArgumentException("Unknown result: " + result); + } + } + private InputChangesInternal determineInputChanges(UnitOfWork work, IncrementalChangesContext context) { return context.getChanges() .map(changes -> { diff --git a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/ExecuteStepTest.groovy b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/ExecuteStepTest.groovy index 3089036b0ee03..e0524e1c5b97f 100644 --- a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/ExecuteStepTest.groovy +++ b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/ExecuteStepTest.groovy @@ -34,7 +34,7 @@ class ExecuteStepTest extends Specification { def inputChanges = Mock(InputChangesInternal) @Unroll - def "#outcome outcome is preserved"() { + def "result #workResult yields outcome #outcome (incremental false)"() { when: def result = step.execute(context) @@ -43,11 +43,13 @@ class ExecuteStepTest extends Specification { 1 * context.work >> work 1 * work.incremental >> false - 1 * work.execute(null) >> { outcome } + 1 * work.execute(null) >> workResult 0 * _ where: - outcome << ExecutionOutcome.values() + workResult | outcome + UnitOfWork.WorkResult.DID_WORK | ExecutionOutcome.EXECUTED_NON_INCREMENTALLY + UnitOfWork.WorkResult.DID_NO_WORK | ExecutionOutcome.UP_TO_DATE } @Unroll @@ -68,11 +70,14 @@ class ExecuteStepTest extends Specification { failure << [new RuntimeException(), new Error()] } - def "determines input changes for incremental work"() { + @Unroll + def "incremental work with result #workResult yields outcome #outcome (executed incrementally: #incrementalExecution)"() { when: - step.execute(context) + def result = step.execute(context) then: + result.outcome.get() == outcome + 1 * context.work >> work 1 * work.incremental >> true 1 * context.changes >> optionalChanges @@ -80,8 +85,16 @@ class ExecuteStepTest extends Specification { ((UnitOfWork.InputFilePropertyVisitor) args[0]).visitInputFileProperty("fileInput", "some/path") } 1 * changes.createInputChanges(ImmutableMultimap.of("some/path", "fileInput")) >> inputChanges - 1 * work.execute(inputChanges) - 1 * inputChanges.incremental >> true + 1 * work.execute(inputChanges) >> workResult + _ * work.getDisplayName() + 2 * inputChanges.incremental >> incrementalExecution 0 * _ + + where: + incrementalExecution | workResult | outcome + true | UnitOfWork.WorkResult.DID_WORK | ExecutionOutcome.EXECUTED_INCREMENTALLY + false | UnitOfWork.WorkResult.DID_WORK | ExecutionOutcome.EXECUTED_NON_INCREMENTALLY + true | UnitOfWork.WorkResult.DID_NO_WORK | ExecutionOutcome.UP_TO_DATE + false | UnitOfWork.WorkResult.DID_NO_WORK | ExecutionOutcome.UP_TO_DATE } } From ab03825a049d8dbb87077374b2ebd677477810d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=B3r=C3=A1nt=20Pint=C3=A9r?= Date: Thu, 14 Mar 2019 23:13:57 +0100 Subject: [PATCH 557/853] Force non-incremental execution after cache load failure Previously when handling a failed load we did clean the outputs of the work, but ended up allowing incremental execution nevertheless. This is now fixed. --- .../command/BuildCacheCommandFactory.java | 47 +------ .../command/BuildCacheLoadListener.java | 21 --- .../UnrecoverableUnpackingException.java | 32 ----- .../BuildCacheCommandFactoryTest.groovy | 46 +------ .../tasks/OriginTaskExecutionMetadata.java | 33 ----- .../controller/BuildCacheController.java | 5 +- .../DefaultBuildCacheController.java | 9 +- .../controller/NoOpBuildCacheController.java | 6 +- .../RootBuildCacheControllerRef.java | 3 +- ...acheTaskArchiveErrorIntegrationTest.groovy | 3 +- .../internal/tasks/TaskExecutionContext.java | 4 - .../DefaultTaskExecutionContext.java | 11 -- .../execution/ExecuteActionsTaskExecuter.java | 8 +- .../scopes/ExecutionGradleServices.java | 2 +- .../SkipCachedTaskExecuterTest.groovy | 5 +- .../transform/DefaultTransformerInvoker.java | 6 +- .../transform/WorkExecutorTestFixture.java | 7 +- subprojects/execution/execution.gradle.kts | 1 + ...IncrementalExecutionIntegrationTest.groovy | 5 - .../internal/execution/CacheHandler.java | 3 +- .../gradle/internal/execution/UnitOfWork.java | 5 - .../internal/execution/steps/CacheStep.java | 130 ++++++++++++------ .../execution/steps/CacheStepTest.groovy | 48 ++++++- .../gradle/kotlin/dsl/cache/ScriptCache.kt | 2 +- 24 files changed, 170 insertions(+), 272 deletions(-) delete mode 100644 subprojects/build-cache-packaging/src/main/java/org/gradle/caching/internal/command/BuildCacheLoadListener.java delete mode 100644 subprojects/build-cache-packaging/src/main/java/org/gradle/caching/internal/packaging/UnrecoverableUnpackingException.java delete mode 100644 subprojects/build-cache/src/main/java/org/gradle/api/internal/tasks/OriginTaskExecutionMetadata.java diff --git a/subprojects/build-cache-packaging/src/main/java/org/gradle/caching/internal/command/BuildCacheCommandFactory.java b/subprojects/build-cache-packaging/src/main/java/org/gradle/caching/internal/command/BuildCacheCommandFactory.java index f5803aa65eaf2..2d2f174452cb2 100644 --- a/subprojects/build-cache-packaging/src/main/java/org/gradle/caching/internal/command/BuildCacheCommandFactory.java +++ b/subprojects/build-cache-packaging/src/main/java/org/gradle/caching/internal/command/BuildCacheCommandFactory.java @@ -18,7 +18,6 @@ import com.google.common.collect.ImmutableSortedMap; import org.apache.commons.io.FileUtils; -import org.gradle.api.GradleException; import org.gradle.api.UncheckedIOException; import org.gradle.api.internal.cache.StringInterner; import org.gradle.api.logging.Logger; @@ -30,7 +29,6 @@ import org.gradle.caching.internal.origin.OriginMetadata; import org.gradle.caching.internal.origin.OriginMetadataFactory; import org.gradle.caching.internal.packaging.BuildCacheEntryPacker; -import org.gradle.caching.internal.packaging.UnrecoverableUnpackingException; import org.gradle.internal.file.FileType; import org.gradle.internal.fingerprint.CurrentFileCollectionFingerprint; import org.gradle.internal.fingerprint.FingerprintingStrategy; @@ -42,7 +40,6 @@ import org.gradle.internal.snapshot.FileSystemSnapshot; import org.gradle.internal.snapshot.MissingFileSnapshot; -import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; @@ -66,8 +63,8 @@ public BuildCacheCommandFactory(BuildCacheEntryPacker packer, OriginMetadataFact this.stringInterner = stringInterner; } - public BuildCacheLoadCommand createLoad(BuildCacheKey cacheKey, CacheableEntity entity, BuildCacheLoadListener loadListener) { - return new LoadCommand(cacheKey, entity, loadListener); + public BuildCacheLoadCommand createLoad(BuildCacheKey cacheKey, CacheableEntity entity) { + return new LoadCommand(cacheKey, entity); } public BuildCacheStoreCommand createStore(BuildCacheKey cacheKey, CacheableEntity entity, Map fingerprints, long executionTime) { @@ -83,12 +80,10 @@ private class LoadCommand implements BuildCacheLoadCommand { private final BuildCacheKey cacheKey; private final CacheableEntity entity; - private final BuildCacheLoadListener loadListener; - private LoadCommand(BuildCacheKey cacheKey, CacheableEntity entity, BuildCacheLoadListener loadListener) { + private LoadCommand(BuildCacheKey cacheKey, CacheableEntity entity) { this.cacheKey = cacheKey; this.entity = entity; - this.loadListener = loadListener; } @Override @@ -97,7 +92,7 @@ public BuildCacheKey getKey() { } @Override - public BuildCacheLoadCommand.Result load(InputStream input) { + public BuildCacheLoadCommand.Result load(InputStream input) throws IOException { try { BuildCacheEntryPacker.UnpackResult unpackResult = packer.unpack(entity, input, originMetadataFactory.createReader(entity)); ImmutableSortedMap snapshots = snapshotUnpackedData(unpackResult.getSnapshots()); @@ -123,16 +118,6 @@ public ImmutableSortedMap getResulting }; } }; - } catch (Exception e) { - LOGGER.warn("Cleaning {} after failed load from cache.", entity.getDisplayName()); - try { - cleanupTreesAfterUnpackFailure(); - loadListener.afterLoadFailedAndWasCleanedUp(e); - } catch (Exception eCleanup) { - LOGGER.warn("Unrecoverable error during cleaning up after unpack failure", eCleanup); - throw new UnrecoverableUnpackingException(String.format("Failed to unpack trees for %s, and then failed to clean up; see log above for details", entity.getDisplayName()), e); - } - throw new GradleException(String.format("Failed to unpack trees for %s", entity.getDisplayName()), e); } finally { cleanLocalState(); } @@ -177,32 +162,14 @@ private ImmutableSortedMap snapshotUnp private void cleanLocalState() { entity.visitLocalState(localStateFile -> { try { - remove(localStateFile); + if (localStateFile.exists()) { + FileUtils.forceDelete(localStateFile); + } } catch (IOException ex) { throw new UncheckedIOException(String.format("Failed to clean up local state files for %s: %s", entity.getDisplayName(), localStateFile), ex); } }); } - - private void cleanupTreesAfterUnpackFailure() { - entity.visitOutputTrees((name, type, root) -> { - try { - remove(root); - } catch (IOException ex) { - throw new UncheckedIOException(String.format("Failed to clean up files for tree '%s' of %s: %s", name, entity.getDisplayName(), root), ex); - } - }); - } - - private void remove(File file) throws IOException { - if (file.exists()) { - if (file.isDirectory()) { - FileUtils.cleanDirectory(file); - } else { - FileUtils.forceDelete(file); - } - } - } } private class StoreCommand implements BuildCacheStoreCommand { diff --git a/subprojects/build-cache-packaging/src/main/java/org/gradle/caching/internal/command/BuildCacheLoadListener.java b/subprojects/build-cache-packaging/src/main/java/org/gradle/caching/internal/command/BuildCacheLoadListener.java deleted file mode 100644 index e929739c6fca1..0000000000000 --- a/subprojects/build-cache-packaging/src/main/java/org/gradle/caching/internal/command/BuildCacheLoadListener.java +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright 2018 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.gradle.caching.internal.command; - -public interface BuildCacheLoadListener { - void afterLoadFailedAndWasCleanedUp(Throwable error); -} diff --git a/subprojects/build-cache-packaging/src/main/java/org/gradle/caching/internal/packaging/UnrecoverableUnpackingException.java b/subprojects/build-cache-packaging/src/main/java/org/gradle/caching/internal/packaging/UnrecoverableUnpackingException.java deleted file mode 100644 index d341d1d425844..0000000000000 --- a/subprojects/build-cache-packaging/src/main/java/org/gradle/caching/internal/packaging/UnrecoverableUnpackingException.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 2017 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.gradle.caching.internal.packaging; - -import org.gradle.api.GradleException; - -/** - * Thrown after unpacking failed, when the attempt to clean up unpacked outputs also failed. - */ -public class UnrecoverableUnpackingException extends GradleException { - public UnrecoverableUnpackingException(String message) { - super(message); - } - - public UnrecoverableUnpackingException(String message, Throwable cause) { - super(message, cause); - } -} diff --git a/subprojects/build-cache-packaging/src/test/groovy/org/gradle/caching/internal/command/BuildCacheCommandFactoryTest.groovy b/subprojects/build-cache-packaging/src/test/groovy/org/gradle/caching/internal/command/BuildCacheCommandFactoryTest.groovy index 7025e4bd94a76..e0e14ff33cc16 100644 --- a/subprojects/build-cache-packaging/src/test/groovy/org/gradle/caching/internal/command/BuildCacheCommandFactoryTest.groovy +++ b/subprojects/build-cache-packaging/src/test/groovy/org/gradle/caching/internal/command/BuildCacheCommandFactoryTest.groovy @@ -27,14 +27,12 @@ import org.gradle.caching.internal.origin.OriginMetadataFactory import org.gradle.caching.internal.origin.OriginReader import org.gradle.caching.internal.origin.OriginWriter import org.gradle.caching.internal.packaging.BuildCacheEntryPacker -import org.gradle.caching.internal.packaging.UnrecoverableUnpackingException import org.gradle.internal.file.TreeType import org.gradle.internal.hash.HashCode import org.gradle.internal.nativeintegration.filesystem.DefaultFileMetadata import org.gradle.internal.snapshot.DirectorySnapshot import org.gradle.internal.snapshot.FileSystemMirror import org.gradle.internal.snapshot.RegularFileSnapshot -import org.gradle.internal.time.Timer import org.gradle.test.fixtures.file.CleanupTestDirectory import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider import org.gradle.testing.internal.util.Specification @@ -52,8 +50,6 @@ class BuildCacheCommandFactoryTest extends Specification { def commandFactory = new BuildCacheCommandFactory(packer, originFactory, fileSystemMirror, stringInterner) def key = Mock(BuildCacheKey) - def loadListener = Mock(BuildCacheLoadListener) - def timer = Stub(Timer) def originMetadata = Mock(OriginMetadata) def originReader = Mock(OriginReader) @@ -72,7 +68,7 @@ class BuildCacheCommandFactoryTest extends Specification { prop("outputDir", DIRECTORY, outputDir), prop("outputFile", FILE, outputFile) ) - def load = commandFactory.createLoad(key, entity, loadListener) + def load = commandFactory.createLoad(key, entity) def outputFileSnapshot = new RegularFileSnapshot(outputFile.absolutePath, outputFile.name, HashCode.fromInt(234), 234) def fileSnapshots = ImmutableMap.of( @@ -114,11 +110,11 @@ class BuildCacheCommandFactoryTest extends Specification { !localStateFile.exists() } - def "after failed unpacking output is cleaned up"() { + def "after failed unpacking error is propagated and output is not removed"() { def input = Mock(InputStream) def outputFile = temporaryFolder.file("output.txt") def entity = this.entity(prop("output", FILE, outputFile)) - def command = commandFactory.createLoad(key, entity, loadListener) + def command = commandFactory.createLoad(key, entity) when: command.load(input) @@ -132,42 +128,10 @@ class BuildCacheCommandFactoryTest extends Specification { throw new RuntimeException("unpacking error") } - then: - 1 * loadListener.afterLoadFailedAndWasCleanedUp(_ as Throwable) - then: def ex = thrown Exception - !(ex instanceof UnrecoverableUnpackingException) - ex.cause.message == "unpacking error" - !outputFile.exists() - 0 * _ - - then: - !localStateFile.exists() - } - - def "error during cleanup of failed unpacking is reported"() { - def input = Mock(InputStream) - def entity = entity() - def command = commandFactory.createLoad(key, entity, loadListener) - - when: - command.load(input) - - then: - 1 * originFactory.createReader(entity) >> originReader - - then: - 1 * packer.unpack(entity, input, originReader) >> { - throw new RuntimeException("unpacking error") - } - - then: - entity.visitOutputTrees(_) >> { throw new RuntimeException("cleanup error") } - - then: - def ex = thrown UnrecoverableUnpackingException - ex.cause.message == "unpacking error" + ex.message == "unpacking error" + outputFile.exists() 0 * _ then: diff --git a/subprojects/build-cache/src/main/java/org/gradle/api/internal/tasks/OriginTaskExecutionMetadata.java b/subprojects/build-cache/src/main/java/org/gradle/api/internal/tasks/OriginTaskExecutionMetadata.java deleted file mode 100644 index c5e54d3c1423b..0000000000000 --- a/subprojects/build-cache/src/main/java/org/gradle/api/internal/tasks/OriginTaskExecutionMetadata.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright 2018 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.gradle.api.internal.tasks; - -import org.gradle.caching.internal.origin.OriginMetadata; -import org.gradle.internal.id.UniqueId; - -/** - * Old location of {@link OriginMetadata}. - * - * This type is used for Kotlin DSL caching. - * Let's keep it for now until the usage in the Kotlin DSL has been removed. - */ -@Deprecated -public class OriginTaskExecutionMetadata extends OriginMetadata { - public OriginTaskExecutionMetadata(UniqueId buildInvocationId, long executionTime) { - super(buildInvocationId, executionTime); - } -} diff --git a/subprojects/build-cache/src/main/java/org/gradle/caching/internal/controller/BuildCacheController.java b/subprojects/build-cache/src/main/java/org/gradle/caching/internal/controller/BuildCacheController.java index afa03af240309..2ae5a7a282091 100644 --- a/subprojects/build-cache/src/main/java/org/gradle/caching/internal/controller/BuildCacheController.java +++ b/subprojects/build-cache/src/main/java/org/gradle/caching/internal/controller/BuildCacheController.java @@ -18,8 +18,8 @@ import org.gradle.caching.BuildCacheService; -import javax.annotation.Nullable; import java.io.Closeable; +import java.util.Optional; /** * Internal coordinator of build cache operations. @@ -32,8 +32,7 @@ public interface BuildCacheController extends Closeable { boolean isEmitDebugLogging(); - @Nullable - T load(BuildCacheLoadCommand command); + Optional load(BuildCacheLoadCommand command); void store(BuildCacheStoreCommand command); diff --git a/subprojects/build-cache/src/main/java/org/gradle/caching/internal/controller/DefaultBuildCacheController.java b/subprojects/build-cache/src/main/java/org/gradle/caching/internal/controller/DefaultBuildCacheController.java index e196e43983a8c..f9f0725b29403 100644 --- a/subprojects/build-cache/src/main/java/org/gradle/caching/internal/controller/DefaultBuildCacheController.java +++ b/subprojects/build-cache/src/main/java/org/gradle/caching/internal/controller/DefaultBuildCacheController.java @@ -53,6 +53,7 @@ import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; +import java.util.Optional; public class DefaultBuildCacheController implements BuildCacheController { @@ -107,7 +108,7 @@ public boolean isEmitDebugLogging() { @Nullable @Override - public T load(final BuildCacheLoadCommand command) { + public Optional load(final BuildCacheLoadCommand command) { final Unpack unpack = new Unpack(command); if (local.canLoad()) { @@ -118,7 +119,7 @@ public T load(final BuildCacheLoadCommand command) { } if (unpack.result != null) { - return unpack.result.getMetadata(); + return Optional.of(unpack.result.getMetadata()); } } @@ -155,9 +156,9 @@ public void execute(File file) { BuildCacheLoadCommand.Result result = unpack.result; if (result == null) { - return null; + return Optional.empty(); } else { - return result.getMetadata(); + return Optional.of(result.getMetadata()); } } diff --git a/subprojects/build-cache/src/main/java/org/gradle/caching/internal/controller/NoOpBuildCacheController.java b/subprojects/build-cache/src/main/java/org/gradle/caching/internal/controller/NoOpBuildCacheController.java index 594118b31650f..c36fedff215ca 100644 --- a/subprojects/build-cache/src/main/java/org/gradle/caching/internal/controller/NoOpBuildCacheController.java +++ b/subprojects/build-cache/src/main/java/org/gradle/caching/internal/controller/NoOpBuildCacheController.java @@ -16,6 +16,8 @@ package org.gradle.caching.internal.controller; +import java.util.Optional; + public class NoOpBuildCacheController implements BuildCacheController { public static final BuildCacheController INSTANCE = new NoOpBuildCacheController(); @@ -34,8 +36,8 @@ public boolean isEmitDebugLogging() { } @Override - public T load(BuildCacheLoadCommand command) { - return null; + public Optional load(BuildCacheLoadCommand command) { + return Optional.empty(); } @Override diff --git a/subprojects/build-cache/src/main/java/org/gradle/caching/internal/controller/RootBuildCacheControllerRef.java b/subprojects/build-cache/src/main/java/org/gradle/caching/internal/controller/RootBuildCacheControllerRef.java index b07ffd8045002..c1c73dde7b576 100644 --- a/subprojects/build-cache/src/main/java/org/gradle/caching/internal/controller/RootBuildCacheControllerRef.java +++ b/subprojects/build-cache/src/main/java/org/gradle/caching/internal/controller/RootBuildCacheControllerRef.java @@ -17,6 +17,7 @@ package org.gradle.caching.internal.controller; import javax.annotation.Nullable; +import java.util.Optional; public class RootBuildCacheControllerRef { @@ -60,7 +61,7 @@ public boolean isEmitDebugLogging() { @Override @Nullable - public T load(BuildCacheLoadCommand command) { + public Optional load(BuildCacheLoadCommand command) { return delegate.load(command); } diff --git a/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/CacheTaskArchiveErrorIntegrationTest.groovy b/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/CacheTaskArchiveErrorIntegrationTest.groovy index 8c1f7515a8be5..c46001b13b955 100644 --- a/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/CacheTaskArchiveErrorIntegrationTest.groovy +++ b/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/CacheTaskArchiveErrorIntegrationTest.groovy @@ -173,8 +173,7 @@ class CacheTaskArchiveErrorIntegrationTest extends AbstractIntegrationSpec { then: executer.withStackTraceChecksDisabled() succeeds("clean", "customTask") - output =~ /Cleaning task ':customTask' after failed load from cache/ - output =~ /Failed to load cache entry for task ':customTask', falling back to executing task/ + output =~ /Failed to load cache entry for task ':customTask', cleaning outputs and falling back to \(non-incremental\) execution/ output =~ /Build cache entry .+ from local build cache is invalid/ output =~ /java.io.EOFException: Unexpected end of ZLIB input stream/ diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/TaskExecutionContext.java b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/TaskExecutionContext.java index 6a1d54cacc73d..d338e8e0213ea 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/TaskExecutionContext.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/TaskExecutionContext.java @@ -90,10 +90,6 @@ public interface TaskExecutionContext { void setTaskExecutedIncrementally(boolean taskExecutedIncrementally); - boolean isOutputRemovedBeforeExecution(); - - void setOutputRemovedBeforeExecution(boolean outputRemovedBeforeExecution); - Optional getExecutionStateChanges(); void setExecutionStateChanges(ExecutionStateChanges executionStateChanges); diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/DefaultTaskExecutionContext.java b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/DefaultTaskExecutionContext.java index a9e937a789577..62297cd697649 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/DefaultTaskExecutionContext.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/DefaultTaskExecutionContext.java @@ -42,7 +42,6 @@ public class DefaultTaskExecutionContext implements TaskExecutionContext { private ImmutableSortedMap outputFilesBeforeExecution; private BeforeExecutionState beforeExecutionState; private TaskExecutionMode taskExecutionMode; - private boolean outputRemovedBeforeExecution; private TaskOutputCachingBuildCacheKey buildCacheKey; private TaskProperties properties; private boolean taskCachingEnabled; @@ -112,16 +111,6 @@ public void setTaskExecutionMode(TaskExecutionMode taskExecutionMode) { this.taskExecutionMode = taskExecutionMode; } - @Override - public boolean isOutputRemovedBeforeExecution() { - return outputRemovedBeforeExecution; - } - - @Override - public void setOutputRemovedBeforeExecution(boolean outputRemovedBeforeExecution) { - this.outputRemovedBeforeExecution = outputRemovedBeforeExecution; - } - @Override public Optional getExecutionStateChanges() { return Optional.ofNullable(executionStateChanges); diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuter.java b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuter.java index 6567867848de4..2af6f1de44be2 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuter.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuter.java @@ -35,6 +35,7 @@ import org.gradle.api.tasks.TaskExecutionException; import org.gradle.caching.BuildCacheKey; import org.gradle.caching.internal.origin.OriginMetadata; +import org.gradle.internal.Try; import org.gradle.internal.UncheckedException; import org.gradle.internal.exceptions.Contextual; import org.gradle.internal.exceptions.DefaultMultiCauseException; @@ -259,7 +260,7 @@ public Optional> getChangingOutputs() { public CacheHandler createCacheHandler() { return new CacheHandler() { @Override - public Optional load(Function> loader) { + public Optional> load(Function>> loader) { // TODO Log this when creating the build cache key perhaps? if (task.isHasCustomActions()) { LOGGER.info("Custom actions are attached to {}.", task); @@ -286,11 +287,6 @@ public void store(Consumer storer) { }; } - @Override - public void outputsRemovedAfterFailureToLoadFromCache() { - context.setOutputRemovedBeforeExecution(true); - } - @Override public Optional getTimeout() { return Optional.ofNullable(task.getTimeout().getOrNull()); diff --git a/subprojects/core/src/main/java/org/gradle/internal/service/scopes/ExecutionGradleServices.java b/subprojects/core/src/main/java/org/gradle/internal/service/scopes/ExecutionGradleServices.java index 408d80671fee5..828681101c53f 100644 --- a/subprojects/core/src/main/java/org/gradle/internal/service/scopes/ExecutionGradleServices.java +++ b/subprojects/core/src/main/java/org/gradle/internal/service/scopes/ExecutionGradleServices.java @@ -128,7 +128,7 @@ public WorkExecutor createWorkExecutor( new RecordOutputsStep(outputFilesRepository, new StoreSnapshotsStep( new BroadcastChangingOutputsStep(outputChangeListener, - new CacheStep(buildCacheController, buildCacheCommandFactory, + new CacheStep(buildCacheController, buildCacheCommandFactory, new SnapshotOutputsStep(buildInvocationScopeId.getId(), new CreateOutputsStep( new CatchExceptionStep( diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/execution/SkipCachedTaskExecuterTest.groovy b/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/execution/SkipCachedTaskExecuterTest.groovy index 7540f97fcbc8a..1b58f4cb34684 100644 --- a/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/execution/SkipCachedTaskExecuterTest.groovy +++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/execution/SkipCachedTaskExecuterTest.groovy @@ -30,7 +30,6 @@ import org.gradle.api.internal.tasks.properties.TaskProperties import org.gradle.caching.internal.command.BuildCacheCommandFactory import org.gradle.caching.internal.controller.BuildCacheController import org.gradle.caching.internal.controller.BuildCacheStoreCommand -import org.gradle.caching.internal.packaging.UnrecoverableUnpackingException import org.gradle.caching.internal.tasks.TaskOutputCachingBuildCacheKey import org.gradle.testing.internal.util.Specification import spock.lang.Ignore @@ -150,12 +149,12 @@ class SkipCachedTaskExecuterTest extends Specification { then: 1 * buildCacheCommandFactory.createLoad(*_) - 1 * buildCacheController.load(_) >> { throw new UnrecoverableUnpackingException("unknown error") } + 1 * buildCacheController.load(_) >> { throw new RuntimeException("unknown error") } then: 0 * _ then: - def e = thrown UnrecoverableUnpackingException + def e = thrown RuntimeException e.message == "unknown error" } diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvoker.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvoker.java index 34bb93c041137..aaa4812346fbe 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvoker.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvoker.java @@ -341,10 +341,6 @@ public long markExecutionTime() { public void visitLocalState(LocalStateVisitor visitor) { } - @Override - public void outputsRemovedAfterFailureToLoadFromCache() { - } - @Override public CacheHandler createCacheHandler() { Hasher hasher = Hashing.newHasher(); @@ -359,7 +355,7 @@ public CacheHandler createCacheHandler() { TransformerExecutionBuildCacheKey cacheKey = new TransformerExecutionBuildCacheKey(hasher.hash()); return new CacheHandler() { @Override - public Optional load(Function> loader) { + public Optional> load(Function>> loader) { if (!transformer.isCacheable()) { return Optional.empty(); } diff --git a/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/WorkExecutorTestFixture.java b/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/WorkExecutorTestFixture.java index e8dcc74b55372..54d4185b72e90 100644 --- a/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/WorkExecutorTestFixture.java +++ b/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/WorkExecutorTestFixture.java @@ -36,8 +36,8 @@ import org.gradle.internal.snapshot.FileSystemSnapshot; import org.gradle.internal.snapshot.impl.DefaultFileSystemMirror; -import javax.annotation.Nullable; import java.io.File; +import java.util.Optional; public class WorkExecutorTestFixture { @@ -52,10 +52,9 @@ public boolean isEmitDebugLogging() { return false; } - @Nullable @Override - public T load(BuildCacheLoadCommand command) { - return null; + public Optional load(BuildCacheLoadCommand command) { + return Optional.empty(); } @Override diff --git a/subprojects/execution/execution.gradle.kts b/subprojects/execution/execution.gradle.kts index 2c3964740bb3b..44d2e50955281 100644 --- a/subprojects/execution/execution.gradle.kts +++ b/subprojects/execution/execution.gradle.kts @@ -32,6 +32,7 @@ dependencies { implementation(project(":baseServices")) implementation(project(":snapshots")) implementation(project(":buildCachePackaging")) + implementation(library("commons_io")) implementation(library("commons_lang")) testImplementation(project(":internalTesting")) diff --git a/subprojects/execution/src/integTest/groovy/org/gradle/internal/execution/IncrementalExecutionIntegrationTest.groovy b/subprojects/execution/src/integTest/groovy/org/gradle/internal/execution/IncrementalExecutionIntegrationTest.groovy index 299c47988064b..da2ba22590ea5 100644 --- a/subprojects/execution/src/integTest/groovy/org/gradle/internal/execution/IncrementalExecutionIntegrationTest.groovy +++ b/subprojects/execution/src/integTest/groovy/org/gradle/internal/execution/IncrementalExecutionIntegrationTest.groovy @@ -819,11 +819,6 @@ class IncrementalExecutionIntegrationTest extends Specification { throw new UnsupportedOperationException() } - @Override - void outputsRemovedAfterFailureToLoadFromCache() { - throw new UnsupportedOperationException() - } - @Override CacheHandler createCacheHandler() { throw new UnsupportedOperationException() diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/CacheHandler.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/CacheHandler.java index 7c19fca7f882a..9b4a2bab7c78d 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/CacheHandler.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/CacheHandler.java @@ -17,12 +17,13 @@ package org.gradle.internal.execution; import org.gradle.caching.BuildCacheKey; +import org.gradle.internal.Try; import java.util.Optional; import java.util.function.Consumer; import java.util.function.Function; public interface CacheHandler { - Optional load(Function> loader); + Optional> load(Function>> loader); void store(Consumer storer); } diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/UnitOfWork.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/UnitOfWork.java index 96622f82b862a..8cc2f4023c693 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/UnitOfWork.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/UnitOfWork.java @@ -39,11 +39,6 @@ public interface UnitOfWork extends CacheableEntity { long markExecutionTime(); - /** - * Loading from cache failed and all outputs were removed. - */ - void outputsRemovedAfterFailureToLoadFromCache(); - CacheHandler createCacheHandler(); /** diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/CacheStep.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/CacheStep.java index 09314d15fa839..bddac8edf32bf 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/CacheStep.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/CacheStep.java @@ -17,12 +17,12 @@ package org.gradle.internal.execution.steps; import com.google.common.collect.ImmutableSortedMap; +import org.apache.commons.io.FileUtils; +import org.gradle.api.UncheckedIOException; import org.gradle.caching.BuildCacheKey; import org.gradle.caching.internal.command.BuildCacheCommandFactory; -import org.gradle.caching.internal.command.BuildCacheLoadListener; import org.gradle.caching.internal.controller.BuildCacheController; import org.gradle.caching.internal.origin.OriginMetadata; -import org.gradle.caching.internal.packaging.UnrecoverableUnpackingException; import org.gradle.internal.Try; import org.gradle.internal.execution.CacheHandler; import org.gradle.internal.execution.CurrentSnapshotResult; @@ -30,23 +30,27 @@ import org.gradle.internal.execution.IncrementalChangesContext; import org.gradle.internal.execution.Step; import org.gradle.internal.execution.UnitOfWork; +import org.gradle.internal.execution.history.AfterPreviousExecutionState; +import org.gradle.internal.execution.history.BeforeExecutionState; +import org.gradle.internal.execution.history.changes.ExecutionStateChanges; import org.gradle.internal.fingerprint.CurrentFileCollectionFingerprint; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.io.IOException; import java.util.Optional; -public class CacheStep implements Step { +public class CacheStep implements Step { private static final Logger LOGGER = LoggerFactory.getLogger(CacheStep.class); private final BuildCacheController buildCache; private final BuildCacheCommandFactory commandFactory; - private final Step delegate; + private final Step delegate; public CacheStep( BuildCacheController buildCache, BuildCacheCommandFactory commandFactory, - Step delegate + Step delegate ) { this.buildCache = buildCache; this.commandFactory = commandFactory; @@ -54,69 +58,107 @@ public CacheStep( } @Override - public CurrentSnapshotResult execute(C context) { + public CurrentSnapshotResult execute(IncrementalChangesContext context) { if (!buildCache.isEnabled()) { return executeWithoutCache(context); } CacheHandler cacheHandler = context.getWork().createCacheHandler(); return cacheHandler .load(cacheKey -> load(context.getWork(), cacheKey)) - .map(loadResult -> { - OriginMetadata originMetadata = loadResult.getOriginMetadata(); - ImmutableSortedMap finalOutputs = loadResult.getResultingSnapshots(); - return (CurrentSnapshotResult) new CurrentSnapshotResult() { + .map(cacheHit -> cacheHit + .map(loadResult -> { + OriginMetadata originMetadata = loadResult.getOriginMetadata(); + ImmutableSortedMap finalOutputs = loadResult.getResultingSnapshots(); + return (CurrentSnapshotResult) new CurrentSnapshotResult() { + @Override + public Try getOutcome() { + return Try.successful(ExecutionOutcome.FROM_CACHE); + } + + @Override + public OriginMetadata getOriginMetadata() { + return originMetadata; + } + + @Override + public boolean isReused() { + return true; + } + + @Override + public ImmutableSortedMap getFinalOutputs() { + return finalOutputs; + } + }; + }) + .orElseMapFailure(loadFailure -> executeWithCache(cacheHandler, new IncrementalChangesContext() { @Override - public Try getOutcome() { - return Try.successful(ExecutionOutcome.FROM_CACHE); + public Optional getChanges() { + // Clear change information to avoid incremental execution after failed load + return Optional.empty(); } @Override - public OriginMetadata getOriginMetadata() { - return originMetadata; + public Optional getRebuildReason() { + return context.getRebuildReason(); } @Override - public boolean isReused() { - return true; + public Optional getAfterPreviousExecutionState() { + return context.getAfterPreviousExecutionState(); } @Override - public ImmutableSortedMap getFinalOutputs() { - return finalOutputs; + public Optional getBeforeExecutionState() { + return context.getBeforeExecutionState(); } - }; - }) - .orElseGet(() -> { - CurrentSnapshotResult executionResult = executeWithoutCache(context); - executionResult.getOutcome().ifSuccessfulOrElse( - outcome -> cacheHandler.store(cacheKey -> store(context.getWork(), cacheKey, executionResult)), - failure -> LOGGER.debug("Not storing result of {} in cache because the execution failed", context.getWork().getDisplayName()) - ); - return executionResult; - }); + + @Override + public UnitOfWork getWork() { + return context.getWork(); + } + })) + ) + .orElseGet(() -> executeWithCache(cacheHandler, context)); } - private Optional load(UnitOfWork work, BuildCacheKey cacheKey) { + private Optional> load(UnitOfWork work, BuildCacheKey cacheKey) { try { - return Optional.ofNullable(buildCache.load( - commandFactory.createLoad(cacheKey, work, new BuildCacheLoadListener() { - @Override - public void afterLoadFailedAndWasCleanedUp(Throwable error) { - work.outputsRemovedAfterFailureToLoadFromCache(); - } - }) - )); - } catch (UnrecoverableUnpackingException e) { - // We didn't manage to recover from the unpacking error, there might be leftover - // garbage among the task's outputs, thus we must fail the build - throw e; + return buildCache.load(commandFactory.createLoad(cacheKey, work)) + .map(loadResult -> Try.successful(loadResult)); } catch (Exception e) { // There was a failure during downloading, previous task outputs should be unaffected - LOGGER.warn("Failed to load cache entry for {}, falling back to executing task", work.getDisplayName(), e); - return Optional.empty(); + LOGGER.warn("Failed to load cache entry for {}, cleaning outputs and falling back to (non-incremental) execution", work.getDisplayName(), e); + cleanupTreesAfterUnpackFailure(work); + return Optional.of(Try.failure(e)); } } + private static void cleanupTreesAfterUnpackFailure(UnitOfWork work) { + work.visitOutputTrees((name, type, root) -> { + try { + if (root.exists()) { + if (root.isDirectory()) { + FileUtils.cleanDirectory(root); + } else { + FileUtils.forceDelete(root); + } + } + } catch (IOException ex) { + throw new UncheckedIOException(String.format("Failed to clean up files for tree '%s' of %s: %s", name, work.getDisplayName(), root), ex); + } + }); + } + + private CurrentSnapshotResult executeWithCache(CacheHandler cacheHandler, IncrementalChangesContext context) { + CurrentSnapshotResult executionResult = executeWithoutCache(context); + executionResult.getOutcome().ifSuccessfulOrElse( + outcome -> cacheHandler.store(cacheKey -> store(context.getWork(), cacheKey, executionResult)), + failure -> LOGGER.debug("Not storing result of {} in cache because the execution failed", context.getWork().getDisplayName()) + ); + return executionResult; + } + private void store(UnitOfWork work, BuildCacheKey cacheKey, CurrentSnapshotResult result) { try { // TODO This could send in the whole origin metadata @@ -126,7 +168,7 @@ private void store(UnitOfWork work, BuildCacheKey cacheKey, CurrentSnapshotResul } } - private CurrentSnapshotResult executeWithoutCache(C context) { + private CurrentSnapshotResult executeWithoutCache(IncrementalChangesContext context) { return delegate.execute(context); } } diff --git a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/CacheStepTest.groovy b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/CacheStepTest.groovy index 01dc500c6633c..c29c32aecb4de 100644 --- a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/CacheStepTest.groovy +++ b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/CacheStepTest.groovy @@ -28,7 +28,7 @@ import org.gradle.internal.execution.IncrementalChangesContext class CacheStepTest extends StepSpec implements FingerprinterFixture { def buildCacheController = Mock(BuildCacheController) def buildCacheCommandFactory = Mock(BuildCacheCommandFactory) - def step = new CacheStep(buildCacheController, buildCacheCommandFactory, delegate) + def step = new CacheStep(buildCacheController, buildCacheCommandFactory, delegate) def cacheHandler = Mock(CacheHandler) def loadMetadata = Mock(BuildCacheCommandFactory.LoadMetadata) @@ -51,7 +51,7 @@ class CacheStepTest extends StepSpec implements FingerprinterFixture { 1 * buildCacheController.isEnabled() >> true 1 * context.work >> work 1 * work.createCacheHandler() >> cacheHandler - 1 * cacheHandler.load(_) >> Optional.of(loadMetadata) + 1 * cacheHandler.load(_) >> Optional.of(Try.successful(loadMetadata)) 1 * loadMetadata.originMetadata >> cachedOriginMetadata 1 * loadMetadata.resultingSnapshots >> outputsFromCache 0 * _ @@ -78,7 +78,49 @@ class CacheStepTest extends StepSpec implements FingerprinterFixture { 0 * _ } - def "failures are not stored in the cache"() { + def "executes work non-incrementally after recoverable unpack failure"() { + when: + def result = step.execute(context) + + then: + result == delegateResult + + 1 * buildCacheController.isEnabled() >> true + 1 * context.work >> work + 1 * work.createCacheHandler() >> cacheHandler + 1 * cacheHandler.load(_) >> Optional.of(Try.failure(new RuntimeException("unpack failure"))) + + then: + 1 * delegate.execute(_) >> { IncrementalChangesContext delegateContext -> + assert delegateContext != context + assert !delegateContext.getChanges().present + delegateResult + } + 1 * delegateResult.outcome >> Try.successful(ExecutionOutcome.EXECUTED_NON_INCREMENTALLY) + + then: + 1 * cacheHandler.store(_) + 0 * _ + } + + def "propagates non-recoverable unpack failure"() { + def unrecoverableUnpackFailure = new RuntimeException("unrecoverable unpack failure") + + when: + step.execute(context) + + then: + def ex = thrown Exception + ex == unrecoverableUnpackFailure + + 1 * buildCacheController.isEnabled() >> true + 1 * context.work >> work + 1 * work.createCacheHandler() >> cacheHandler + 1 * cacheHandler.load(_) >> { throw unrecoverableUnpackFailure } + 0 * _ + } + + def "does not store result of failed execution in cache"() { when: def result = step.execute(context) diff --git a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/cache/ScriptCache.kt b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/cache/ScriptCache.kt index 29c3a83367010..15d154695c391 100644 --- a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/cache/ScriptCache.kt +++ b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/cache/ScriptCache.kt @@ -96,7 +96,7 @@ class ScriptCache( val buildCacheKey = ScriptBuildCacheKey(displayName, cacheKey) val buildInvocationId = buildInvocationIdOf(scriptTarget) val existing = cacheController.load(LoadDirectory(cacheDir, buildCacheKey, buildInvocationId)) - if (existing === null) { + if (!existing.isPresent) { val executionTime = executionTimeMillisOf { initializer(cacheDir) From 2dd6fc3f081a34fb9572dcefadb7dea64cfcf2db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=B3r=C3=A1nt=20Pint=C3=A9r?= Date: Fri, 15 Mar 2019 00:23:32 +0100 Subject: [PATCH 558/853] Migrate remaining tests from SkipCachedTaskExecuterTest to CacheStepTest --- .../SkipCachedTaskExecuterTest.groovy | 205 ------------------ .../execution/steps/CacheStepTest.groovy | 121 ++++++++++- .../FileCollectionFingerprint.java | 5 + 3 files changed, 114 insertions(+), 217 deletions(-) delete mode 100644 subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/execution/SkipCachedTaskExecuterTest.groovy diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/execution/SkipCachedTaskExecuterTest.groovy b/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/execution/SkipCachedTaskExecuterTest.groovy deleted file mode 100644 index 1b58f4cb34684..0000000000000 --- a/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/execution/SkipCachedTaskExecuterTest.groovy +++ /dev/null @@ -1,205 +0,0 @@ -/* - * Copyright 2016 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.gradle.api.internal.tasks.execution - -import com.google.common.collect.ImmutableSortedSet -import org.gradle.api.Project -import org.gradle.api.file.FileCollection -import org.gradle.api.internal.TaskInternal -import org.gradle.api.internal.TaskOutputCachingState -import org.gradle.api.internal.changedetection.TaskExecutionMode -import org.gradle.api.internal.tasks.TaskExecuter -import org.gradle.api.internal.tasks.TaskExecuterResult -import org.gradle.api.internal.tasks.TaskExecutionContext -import org.gradle.api.internal.tasks.TaskStateInternal -import org.gradle.api.internal.tasks.properties.TaskProperties -import org.gradle.caching.internal.command.BuildCacheCommandFactory -import org.gradle.caching.internal.controller.BuildCacheController -import org.gradle.caching.internal.controller.BuildCacheStoreCommand -import org.gradle.caching.internal.tasks.TaskOutputCachingBuildCacheKey -import org.gradle.testing.internal.util.Specification -import spock.lang.Ignore - -// TODO rewrite this better before the PR is merged -@Ignore("I, lptr, promise to rewrite this better before this PR is merged") -class SkipCachedTaskExecuterTest extends Specification { - def delegate = Mock(TaskExecuter) - def project = Mock(Project) - def projectDir = Mock(File) - def taskOutputCaching = Mock(TaskOutputCachingState) - def localStateFiles = Stub(FileCollection) - def taskProperties = Mock(TaskProperties) - def task = Stub(TaskInternal) - def taskState = Mock(TaskStateInternal) - def taskContext = Mock(TaskExecutionContext) - def taskExecutionMode = Mock(TaskExecutionMode) - def buildCacheController = Mock(BuildCacheController) - def cacheKey = Mock(TaskOutputCachingBuildCacheKey) - def storeCommand = Mock(BuildCacheStoreCommand) - def buildCacheCommandFactory = Mock(BuildCacheCommandFactory) - def outputFingerprints = [:] - - // def executer = new SkipCachedTaskExecuter(buildCacheController, outputChangeListener, buildCacheCommandFactory, delegate) - - def "executes task and stores result when use of cached result is not allowed"() { - when: - executer.execute(task, taskState, taskContext) - - then: - 1 * taskContext.taskProperties >> taskProperties - 1 * taskContext.buildCacheKey >> cacheKey - interaction { cachingEnabled() } - - then: - 1 * taskProperties.getOutputFileProperties() >> ImmutableSortedSet.of() - 1 * taskContext.getTaskExecutionMode() >> taskExecutionMode - 1 * taskExecutionMode.isAllowedToUseCachedResults() >> false - - then: - 1 * delegate.execute(task, taskState, taskContext) >> TaskExecuterResult.WITHOUT_OUTPUTS - - then: - 1 * taskState.getFailure() >> null - - then: - 1 * taskContext.getTaskExecutionMode() >> taskExecutionMode - 1 * buildCacheCommandFactory.createStore(cacheKey, task, outputFingerprints, 1) >> storeCommand - - then: - 1 * buildCacheController.store(storeCommand) - 0 * _ - } - - def "executes task and does not cache results when caching was disabled"() { - when: - executer.execute(task, taskState, taskContext) - - then: - 1 * taskContext.taskProperties >> taskProperties - 1 * taskContext.buildCacheKey >> cacheKey - interaction { cachingDisabled() } - - then: - 1 * delegate.execute(task, taskState, taskContext) >> TaskExecuterResult.WITHOUT_OUTPUTS - 0 * _ - } - - def "stores result when cache backend throws recoverable exception while loading result"() { - when: - executer.execute(task, taskState, taskContext) - - then: - 1 * taskContext.taskProperties >> taskProperties - 1 * taskContext.buildCacheKey >> cacheKey - interaction { cachingEnabled() } - - then: - 1 * taskProperties.outputFileProperties >> ImmutableSortedSet.of() - 1 * taskProperties.localStateFiles >> localStateFiles - 1 * taskContext.getTaskExecutionMode() >> taskExecutionMode - 1 * taskExecutionMode.isAllowedToUseCachedResults() >> true - - then: - 1 * buildCacheCommandFactory.createLoad(*_) - 1 * buildCacheController.load(_) >> { throw new RuntimeException("unknown error") } - - then: - 1 * delegate.execute(task, taskState, taskContext) >> TaskExecuterResult.WITHOUT_OUTPUTS - - then: - 1 * taskState.getFailure() >> null - - then: - 1 * taskContext.getTaskExecutionMode() >> taskExecutionMode - 1 * buildCacheCommandFactory.createStore(cacheKey, task, outputFingerprints, 1) >> storeCommand - - then: - 1 * buildCacheController.store(storeCommand) - 0 * _ - } - - def "fails when cache backend throws unrecoverable exception while finding result"() { - when: - executer.execute(task, taskState, taskContext) - - then: - 1 * taskContext.taskProperties >> taskProperties - 1 * taskContext.buildCacheKey >> cacheKey - interaction { cachingEnabled() } - - then: - 1 * taskProperties.outputFileProperties >> ImmutableSortedSet.of() - 1 * taskProperties.localStateFiles >> localStateFiles - 1 * taskContext.getTaskExecutionMode() >> taskExecutionMode - 1 * taskExecutionMode.isAllowedToUseCachedResults() >> true - - then: - 1 * buildCacheCommandFactory.createLoad(*_) - 1 * buildCacheController.load(_) >> { throw new RuntimeException("unknown error") } - - then: - 0 * _ - then: - def e = thrown RuntimeException - e.message == "unknown error" - } - - def "does not fail when cache backend throws exception while storing cached result"() { - when: - executer.execute(task, taskState, taskContext) - - then: - 1 * taskContext.taskProperties >> taskProperties - 1 * taskContext.buildCacheKey >> cacheKey - interaction { cachingEnabled() } - - then: - 1 * taskProperties.outputFileProperties >> ImmutableSortedSet.of() - 1 * taskProperties.localStateFiles >> localStateFiles - 1 * taskContext.getTaskExecutionMode() >> taskExecutionMode - 1 * taskExecutionMode.isAllowedToUseCachedResults() >> true - - then: - 1 * buildCacheCommandFactory.createLoad(*_) - 1 * buildCacheController.load(_) - - then: - 1 * delegate.execute(task, taskState, taskContext) >> TaskExecuterResult.WITHOUT_OUTPUTS - - then: - 1 * taskState.getFailure() >> null - - then: - 1 * cacheKey.getDisplayName() >> "cache key" - 1 * taskContext.getTaskExecutionMode() >> taskExecutionMode - 1 * buildCacheCommandFactory.createStore(*_) - 1 * buildCacheController.store(_) >> { throw new RuntimeException("unknown error") } - - then: - 0 * _ - } - - private void cachingEnabled() { - 1 * taskState.getTaskOutputCaching() >> taskOutputCaching - 1 * taskOutputCaching.isEnabled() >> true - } - - private void cachingDisabled() { - 1 * taskState.getTaskOutputCaching() >> taskOutputCaching - 1 * taskOutputCaching.isEnabled() >> false - } -} diff --git a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/CacheStepTest.groovy b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/CacheStepTest.groovy index c29c32aecb4de..58ca522d185bf 100644 --- a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/CacheStepTest.groovy +++ b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/CacheStepTest.groovy @@ -16,28 +16,42 @@ package org.gradle.internal.execution.steps +import com.google.common.collect.ImmutableSortedMap +import org.gradle.caching.BuildCacheKey +import org.gradle.caching.internal.CacheableEntity import org.gradle.caching.internal.command.BuildCacheCommandFactory import org.gradle.caching.internal.controller.BuildCacheController +import org.gradle.caching.internal.controller.BuildCacheLoadCommand +import org.gradle.caching.internal.controller.BuildCacheStoreCommand import org.gradle.caching.internal.origin.OriginMetadata import org.gradle.internal.Try import org.gradle.internal.execution.CacheHandler import org.gradle.internal.execution.CurrentSnapshotResult import org.gradle.internal.execution.ExecutionOutcome import org.gradle.internal.execution.IncrementalChangesContext +import org.gradle.internal.file.TreeType + +import java.util.function.Consumer +import java.util.function.Function + +import static org.gradle.internal.fingerprint.FileCollectionFingerprint.EMPTY class CacheStepTest extends StepSpec implements FingerprinterFixture { def buildCacheController = Mock(BuildCacheController) def buildCacheCommandFactory = Mock(BuildCacheCommandFactory) - def step = new CacheStep(buildCacheController, buildCacheCommandFactory, delegate) def cacheHandler = Mock(CacheHandler) + + def cacheKey = Stub(BuildCacheKey) def loadMetadata = Mock(BuildCacheCommandFactory.LoadMetadata) + def step = new CacheStep(buildCacheController, buildCacheCommandFactory, delegate) def delegateResult = Mock(CurrentSnapshotResult) def context = Mock(IncrementalChangesContext) def "loads from cache"() { def cachedOriginMetadata = Mock(OriginMetadata) def outputsFromCache = fingerprintsOf("test": []) + def loadCommand = Mock(BuildCacheLoadCommand) when: def result = step.execute(context) @@ -48,23 +62,36 @@ class CacheStepTest extends StepSpec implements FingerprinterFixture { result.originMetadata == cachedOriginMetadata result.finalOutputs == outputsFromCache - 1 * buildCacheController.isEnabled() >> true + 1 * buildCacheController.enabled >> true 1 * context.work >> work 1 * work.createCacheHandler() >> cacheHandler - 1 * cacheHandler.load(_) >> Optional.of(Try.successful(loadMetadata)) + 1 * cacheHandler.load(_) >> { Function>> loader -> + loader.apply(cacheKey) + } + + then: + 1 * context.work >> work + 1 * buildCacheCommandFactory.createLoad(cacheKey, work) >> loadCommand + 1 * buildCacheController.load(loadCommand) >> Optional.of(loadMetadata) + + then: 1 * loadMetadata.originMetadata >> cachedOriginMetadata 1 * loadMetadata.resultingSnapshots >> outputsFromCache 0 * _ } def "executes work and stores in cache on cache miss"() { + def storeCommand = Mock(BuildCacheStoreCommand) + def finalOutputs = ImmutableSortedMap.of("test", EMPTY) + def originMetadata = Mock(OriginMetadata) + when: def result = step.execute(context) then: result == delegateResult - 1 * buildCacheController.isEnabled() >> true + 1 * buildCacheController.enabled >> true 1 * context.work >> work 1 * work.createCacheHandler() >> cacheHandler 1 * cacheHandler.load(_) >> Optional.empty() @@ -74,21 +101,58 @@ class CacheStepTest extends StepSpec implements FingerprinterFixture { 1 * delegateResult.outcome >> Try.successful(ExecutionOutcome.EXECUTED_NON_INCREMENTALLY) then: - 1 * cacheHandler.store(_) + 1 * cacheHandler.store(_) >> { Consumer storer -> storer.accept(cacheKey) } + + then: + 1 * context.work >> work + 1 * delegateResult.finalOutputs >> finalOutputs + 1 * delegateResult.originMetadata >> originMetadata + 1 * originMetadata.executionTime >> 123L + 1 * buildCacheCommandFactory.createStore(cacheKey, work, finalOutputs, 123L) >> storeCommand + 1 * buildCacheController.store(storeCommand) 0 * _ } - def "executes work non-incrementally after recoverable unpack failure"() { + def "executes work non-incrementally and stores after recoverable unpack failure"() { + def loadCommand = Mock(BuildCacheLoadCommand) + def loadedOutputFile = file("output.txt") + def loadedOutputDir = file("output") + when: def result = step.execute(context) then: result == delegateResult - 1 * buildCacheController.isEnabled() >> true + 1 * buildCacheController.enabled >> true 1 * context.work >> work 1 * work.createCacheHandler() >> cacheHandler - 1 * cacheHandler.load(_) >> Optional.of(Try.failure(new RuntimeException("unpack failure"))) + 1 * cacheHandler.load(_) >> { Function>> loader -> + loader.apply(cacheKey) + } + + then: + 1 * context.work >> work + 1 * buildCacheCommandFactory.createLoad(cacheKey, work) >> loadCommand + 1 * buildCacheController.load(loadCommand) >> { + loadedOutputFile << "output" + loadedOutputDir.mkdirs() + loadedOutputDir.file("output.txt") << "output" + throw new RuntimeException("unpack failure") + } + + then: + 1 * work.displayName >> "work" + 1 * work.visitOutputTrees(_) >> { CacheableEntity.CacheableTreeVisitor visitor -> + visitor.visitOutputTree("outputFile", TreeType.FILE, loadedOutputFile) + visitor.visitOutputTree("outputDir", TreeType.DIRECTORY, loadedOutputDir) + visitor.visitOutputTree("missingOutputFile", TreeType.FILE, file("missing.txt")) + visitor.visitOutputTree("missingOutputDir", TreeType.DIRECTORY, file("missing")) + } + + then: + loadedOutputFile.assertDoesNotExist() + loadedOutputDir.assertIsEmptyDir() then: 1 * delegate.execute(_) >> { IncrementalChangesContext delegateContext -> @@ -113,7 +177,7 @@ class CacheStepTest extends StepSpec implements FingerprinterFixture { def ex = thrown Exception ex == unrecoverableUnpackFailure - 1 * buildCacheController.isEnabled() >> true + 1 * buildCacheController.enabled >> true 1 * context.work >> work 1 * work.createCacheHandler() >> cacheHandler 1 * cacheHandler.load(_) >> { throw unrecoverableUnpackFailure } @@ -128,7 +192,7 @@ class CacheStepTest extends StepSpec implements FingerprinterFixture { result == delegateResult !result.reused - 1 * buildCacheController.isEnabled() >> true + 1 * buildCacheController.enabled >> true 1 * context.work >> work 1 * work.createCacheHandler() >> cacheHandler 1 * cacheHandler.load(_) >> Optional.empty() @@ -144,7 +208,40 @@ class CacheStepTest extends StepSpec implements FingerprinterFixture { 0 * _ } - def "executes when caching is disabled"() { + def "does not fail when cache backend throws exception while storing cached result"() { + def storeCommand = Mock(BuildCacheStoreCommand) + def finalOutputs = ImmutableSortedMap.of("test", EMPTY) + def originMetadata = Mock(OriginMetadata) + + when: + def result = step.execute(context) + + then: + result == delegateResult + + 1 * buildCacheController.enabled >> true + 1 * context.work >> work + 1 * work.createCacheHandler() >> cacheHandler + 1 * cacheHandler.load(_) >> Optional.empty() + + then: + 1 * delegate.execute(context) >> delegateResult + 1 * delegateResult.outcome >> Try.successful(ExecutionOutcome.EXECUTED_NON_INCREMENTALLY) + + then: + 1 * cacheHandler.store(_) >> { Consumer storer -> storer.accept(cacheKey) } + + then: + 1 * context.work >> work + 1 * delegateResult.finalOutputs >> finalOutputs + 1 * delegateResult.originMetadata >> originMetadata + 1 * originMetadata.executionTime >> 123L + 1 * buildCacheCommandFactory.createStore(cacheKey, work, finalOutputs, 123L) >> storeCommand + 1 * buildCacheController.store(storeCommand) >> { throw new RuntimeException("store failure") } + 0 * _ + } + + def "executes and doesn't store when caching is disabled"() { when: def result = step.execute(context) @@ -152,7 +249,7 @@ class CacheStepTest extends StepSpec implements FingerprinterFixture { result == delegateResult !result.reused - 1 * buildCacheController.isEnabled() >> false + 1 * buildCacheController.enabled >> false 1 * delegate.execute(_) >> delegateResult 0 * _ } diff --git a/subprojects/snapshots/src/main/java/org/gradle/internal/fingerprint/FileCollectionFingerprint.java b/subprojects/snapshots/src/main/java/org/gradle/internal/fingerprint/FileCollectionFingerprint.java index f4cecce2075f3..03b66dc9fbfa0 100644 --- a/subprojects/snapshots/src/main/java/org/gradle/internal/fingerprint/FileCollectionFingerprint.java +++ b/subprojects/snapshots/src/main/java/org/gradle/internal/fingerprint/FileCollectionFingerprint.java @@ -47,5 +47,10 @@ public Map getFingerprints() { public ImmutableMultimap getRootHashes() { return ImmutableMultimap.of(); } + + @Override + public String toString() { + return "EMPTY"; + } }; } From 4d5b5a543340d5a1bef23d1069d254f0013875ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=B3r=C3=A1nt=20Pint=C3=A9r?= Date: Fri, 15 Mar 2019 00:28:43 +0100 Subject: [PATCH 559/853] Fix test --- .../internal/controller/DefaultBuildCacheControllerTest.groovy | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/subprojects/build-cache/src/test/groovy/org/gradle/caching/internal/controller/DefaultBuildCacheControllerTest.groovy b/subprojects/build-cache/src/test/groovy/org/gradle/caching/internal/controller/DefaultBuildCacheControllerTest.groovy index 871f805949e36..9e44ac4f95ed3 100644 --- a/subprojects/build-cache/src/test/groovy/org/gradle/caching/internal/controller/DefaultBuildCacheControllerTest.groovy +++ b/subprojects/build-cache/src/test/groovy/org/gradle/caching/internal/controller/DefaultBuildCacheControllerTest.groovy @@ -43,6 +43,7 @@ class DefaultBuildCacheControllerTest extends Specification { def localPush = true def remote = Mock(BuildCacheService) def remotePush = true + def loadmetadata = Mock(Object) BuildCacheService legacyLocal = null @@ -71,7 +72,7 @@ class DefaultBuildCacheControllerTest extends Specification { @Override Object getMetadata() { - return null + return loadmetadata } } } From cb41575e214a422efc0619051b665303ff86ca2d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=B3r=C3=A1nt=20Pint=C3=A9r?= Date: Fri, 15 Mar 2019 00:33:59 +0100 Subject: [PATCH 560/853] Remove now-incorrect `@Nullable` annotations --- .../internal/controller/DefaultBuildCacheController.java | 2 -- .../internal/controller/RootBuildCacheControllerRef.java | 2 -- 2 files changed, 4 deletions(-) diff --git a/subprojects/build-cache/src/main/java/org/gradle/caching/internal/controller/DefaultBuildCacheController.java b/subprojects/build-cache/src/main/java/org/gradle/caching/internal/controller/DefaultBuildCacheController.java index f9f0725b29403..f7e42076a97a1 100644 --- a/subprojects/build-cache/src/main/java/org/gradle/caching/internal/controller/DefaultBuildCacheController.java +++ b/subprojects/build-cache/src/main/java/org/gradle/caching/internal/controller/DefaultBuildCacheController.java @@ -47,7 +47,6 @@ import org.gradle.internal.operations.BuildOperationExecutor; import org.gradle.internal.operations.RunnableBuildOperation; -import javax.annotation.Nullable; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; @@ -106,7 +105,6 @@ public boolean isEmitDebugLogging() { return emitDebugLogging; } - @Nullable @Override public Optional load(final BuildCacheLoadCommand command) { final Unpack unpack = new Unpack(command); diff --git a/subprojects/build-cache/src/main/java/org/gradle/caching/internal/controller/RootBuildCacheControllerRef.java b/subprojects/build-cache/src/main/java/org/gradle/caching/internal/controller/RootBuildCacheControllerRef.java index c1c73dde7b576..1b83dd9c28e40 100644 --- a/subprojects/build-cache/src/main/java/org/gradle/caching/internal/controller/RootBuildCacheControllerRef.java +++ b/subprojects/build-cache/src/main/java/org/gradle/caching/internal/controller/RootBuildCacheControllerRef.java @@ -16,7 +16,6 @@ package org.gradle.caching.internal.controller; -import javax.annotation.Nullable; import java.util.Optional; public class RootBuildCacheControllerRef { @@ -60,7 +59,6 @@ public boolean isEmitDebugLogging() { } @Override - @Nullable public Optional load(BuildCacheLoadCommand command) { return delegate.load(command); } From 115d03dde2e95bef5a125f208d6f41142efd557a Mon Sep 17 00:00:00 2001 From: Gradleware Git Bot Date: Fri, 15 Mar 2019 02:25:19 +0100 Subject: [PATCH 561/853] Publish 5.3-20190315010557+0000 --- released-versions.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/released-versions.json b/released-versions.json index b3421993a9b18..8ff2a9bf425e7 100644 --- a/released-versions.json +++ b/released-versions.json @@ -1,7 +1,7 @@ { "latestReleaseSnapshot": { - "version": "5.3-20190314021933+0000", - "buildTime": "20190314021933+0000" + "version": "5.3-20190315010557+0000", + "buildTime": "20190315010557+0000" }, "latestRc": { "version": "5.3-rc-3", From 23150d980eea4bd5dabace0dd36350f523a32a5b Mon Sep 17 00:00:00 2001 From: Adam Murdoch Date: Thu, 14 Mar 2019 13:14:12 +1100 Subject: [PATCH 562/853] Change `BlockingHttpServer` test fixture so that client reads the entire response from the server. --- .../groovy/org/gradle/util/TestUtil.groovy | 1 - .../server/http/BlockingHttpServer.java | 56 +++++++++---------- .../server/http/BlockingHttpServerTest.groovy | 49 ++++++++++++++++ 3 files changed, 76 insertions(+), 30 deletions(-) diff --git a/subprojects/core/src/testFixtures/groovy/org/gradle/util/TestUtil.groovy b/subprojects/core/src/testFixtures/groovy/org/gradle/util/TestUtil.groovy index 1f109308bb842..1f31a911473ac 100644 --- a/subprojects/core/src/testFixtures/groovy/org/gradle/util/TestUtil.groovy +++ b/subprojects/core/src/testFixtures/groovy/org/gradle/util/TestUtil.groovy @@ -76,7 +76,6 @@ class TestUtil { return new DefaultObjectFactory(instantiatorFactory().injectAndDecorate(services), NamedObjectInstantiator.INSTANCE, fileResolver, TestFiles.directoryFileTreeFactory(), new DefaultFilePropertyFactory(fileResolver), TestFiles.fileCollectionFactory()) } - static NamedObjectInstantiator objectInstantiator() { return NamedObjectInstantiator.INSTANCE } diff --git a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/server/http/BlockingHttpServer.java b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/server/http/BlockingHttpServer.java index 776eeb4b4b920..ef15bb97fef4f 100644 --- a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/server/http/BlockingHttpServer.java +++ b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/test/fixtures/server/http/BlockingHttpServer.java @@ -98,46 +98,44 @@ public URI uri(String resource) { * Returns Java statements to get the given resource. */ public String callFromBuild(String resource) { - URI uri = uri(resource); - String var = "connection" + (clientVarCounter++); - StringWriter result = new StringWriter(); - PrintWriter writer = new PrintWriter(result); - writer.println("System.out.println(\"[G] calling " + uri + "\");"); - writer.println("try {"); - writer.println(" java.net.URLConnection " + var + " = new java.net.URL(\"" + uri + "\").openConnection();"); - writer.println(" " + var + ".setReadTimeout(0);"); // to avoid silent retry - writer.println(" " + var + ".getContentLength();"); - writer.println("} catch(Exception e) {"); - writer.println(" throw new RuntimeException(e);"); - writer.println("}"); - writer.println("System.out.println(\"[G] response received for " + uri + "\");"); - return result.toString(); - } - - public String callFromTaskAction(String resource) { - return "getServices().get(" + WorkerLeaseService.class.getCanonicalName() + ".class).withoutProjectLock(new Runnable() { void run() { " + callFromBuild(resource) + " } });"; - } + return callFromBuildUsingExpression("\"" + resource + "\""); + } /** * Returns Java statements to get the given resource, using the given expression to calculate the resource to get. */ public String callFromBuildUsingExpression(String expression) { String uriExpression = "\"" + getUri() + "/\" + " + expression; - String var = "connection" + (clientVarCounter++); + int count = clientVarCounter++; + String connectionVar = "connection" + count; + String urlVar = "url" + count; + String streamVar = "inputStream" + count; StringWriter result = new StringWriter(); PrintWriter writer = new PrintWriter(result); - writer.println("System.out.println(\"[G] calling \" + " + uriExpression + ");"); - writer.println("try {"); - writer.println(" java.net.URLConnection " + var + " = new java.net.URL(" + uriExpression + ").openConnection();"); - writer.println(" " + var + ".setReadTimeout(0);"); // to avoid silent retry - writer.println(" " + var + ".getContentLength();"); - writer.println("} catch(Exception e) {"); - writer.println(" throw new RuntimeException(e);"); - writer.println("}"); - writer.println("System.out.println(\"[G] response received for \" + " + uriExpression + ");"); + writer.print("String " + urlVar + " = " + uriExpression + ";"); + writer.print("System.out.println(\"[G] calling \" + " + urlVar + ");"); + writer.print("try {"); + writer.print(" java.net.URLConnection " + connectionVar + " = new java.net.URL(" + urlVar + ").openConnection();"); + writer.print(" " + connectionVar + ".setReadTimeout(0);"); // to avoid silent retry + writer.print(" " + connectionVar + ".connect();"); + writer.print(" java.io.InputStream " + streamVar + " = " + connectionVar + ".getInputStream();"); + writer.print(" try {"); + writer.print(" while (" + streamVar + ".read() >= 0) {}"); // read entire response + writer.print(" } finally {"); + writer.print(" " + streamVar + ".close();"); + writer.print(" }"); + writer.print("} catch(Exception e) {"); + writer.print(" System.out.println(\"[G] error response received for \" + " + urlVar + ");"); + writer.print(" throw new RuntimeException(\"Received error response from \" + " + urlVar + ", e);"); + writer.print("};"); + writer.println("System.out.println(\"[G] response received for \" + " + urlVar + ");"); return result.toString(); } + public String callFromTaskAction(String resource) { + return "getServices().get(" + WorkerLeaseService.class.getCanonicalName() + ".class).withoutProjectLock(new Runnable() { void run() { " + callFromBuild(resource) + " } });"; + } + /** * Expects that all requests use the basic authentication with the given credentials. */ diff --git a/subprojects/internal-integ-testing/src/test/groovy/org/gradle/test/fixtures/server/http/BlockingHttpServerTest.groovy b/subprojects/internal-integ-testing/src/test/groovy/org/gradle/test/fixtures/server/http/BlockingHttpServerTest.groovy index 4cbef694ef4cb..5548ec3c288d7 100644 --- a/subprojects/internal-integ-testing/src/test/groovy/org/gradle/test/fixtures/server/http/BlockingHttpServerTest.groovy +++ b/subprojects/internal-integ-testing/src/test/groovy/org/gradle/test/fixtures/server/http/BlockingHttpServerTest.groovy @@ -18,6 +18,7 @@ package org.gradle.test.fixtures.server.http import org.gradle.test.fixtures.concurrent.ConcurrentSpec import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider +import org.gradle.util.TestUtil import org.hamcrest.Matchers import org.junit.Rule @@ -263,6 +264,54 @@ class BlockingHttpServerTest extends ConcurrentSpec { instant.aDone > instant.aBlocked } + def "can call from client code"() { + server.start() + def script = TestUtil.createScript """ + def prefix = "a" + ${server.callFromBuild("a1")} + ${server.callFromBuildUsingExpression("prefix + '2'")} + """ + + given: + server.expect("a1") + server.expect("a2") + + when: + script.run() + server.stop() + + then: + noExceptionThrown() + } + + def "client code fails when making unexpected request"() { + server.start() + def script = TestUtil.createScript """ + def prefix = "a" + ${server.callFromBuild("a1")} + ${server.callFromBuildUsingExpression("prefix + '2'")} + """ + + given: + server.expect("a1") + server.expect("other") + + when: + script.run() + + then: + def e = thrown(RuntimeException) + e.message == "Received error response from ${server.uri}/a2" + + when: + server.stop() + + then: + def e2 = thrown(RuntimeException) + e2.message == 'Failed to handle all HTTP requests.' + e2.causes.message == ['Unexpected request GET /a2 received. Waiting for [GET /other], already received []'] + } + def "succeeds when expected concurrent requests are made"() { given: server.expectConcurrent("a", "b", "c") From aeee016bcce5ea34a9eecc6c3ebcbc5d328115c0 Mon Sep 17 00:00:00 2001 From: Stefan Wolf Date: Fri, 15 Mar 2019 08:07:54 +0100 Subject: [PATCH 563/853] Allow iterating changes more than once. --- ...TransformIncrementalIntegrationTest.groovy | 2 +- .../changes/NonIncrementalInputChanges.java | 4 +- .../NonIncrementalInputChangesTest.groovy | 48 +++++++++++++++++++ 3 files changed, 51 insertions(+), 3 deletions(-) create mode 100644 subprojects/execution/src/test/groovy/org/gradle/internal/execution/history/changes/NonIncrementalInputChangesTest.groovy diff --git a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformIncrementalIntegrationTest.groovy b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformIncrementalIntegrationTest.groovy index 2828230216a77..8caa7842a86a5 100644 --- a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformIncrementalIntegrationTest.groovy +++ b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformIncrementalIntegrationTest.groovy @@ -60,7 +60,7 @@ class ArtifactTransformIncrementalIntegrationTest extends AbstractDependencyReso println "Transforming " + input.name println "incremental: " + inputChanges.incremental assert parameters.incrementalExecution.get() == inputChanges.incremental - def changes = inputChanges.getFileChanges(input) as List + def changes = inputChanges.getFileChanges(input) println "changes: \\n" + changes.join("\\n") assert changes.findAll { it.changeType == ChangeType.ADDED }*.file as Set == resolveFiles(parameters.addedFiles.get()) assert changes.findAll { it.changeType == ChangeType.REMOVED }*.file as Set == resolveFiles(parameters.removedFiles.get()) diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/NonIncrementalInputChanges.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/NonIncrementalInputChanges.java index 3db91f3c8ccdb..0367e88d68326 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/NonIncrementalInputChanges.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/NonIncrementalInputChanges.java @@ -46,12 +46,12 @@ public boolean isIncremental() { @Override public Iterable getFileChanges(Object parameterValue) { CurrentFileCollectionFingerprint currentFileCollectionFingerprint = currentInputs.get(determinePropertyName(parameterValue, propertyNameByValue)); - return getAllFileChanges(currentFileCollectionFingerprint)::iterator; + return () -> getAllFileChanges(currentFileCollectionFingerprint).iterator(); } @Override public Iterable getAllFileChanges() { - Iterable changes = currentInputs.values().stream().flatMap(NonIncrementalInputChanges::getAllFileChanges)::iterator; + Iterable changes = () -> currentInputs.values().stream().flatMap(NonIncrementalInputChanges::getAllFileChanges).iterator(); return Cast.uncheckedNonnullCast(changes); } diff --git a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/history/changes/NonIncrementalInputChangesTest.groovy b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/history/changes/NonIncrementalInputChangesTest.groovy new file mode 100644 index 0000000000000..e9f90acaf8668 --- /dev/null +++ b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/history/changes/NonIncrementalInputChangesTest.groovy @@ -0,0 +1,48 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.internal.execution.history.changes + +import com.google.common.collect.ImmutableMultimap +import com.google.common.collect.ImmutableSortedMap +import org.gradle.internal.fingerprint.CurrentFileCollectionFingerprint +import org.gradle.internal.fingerprint.impl.AbsolutePathFingerprintingStrategy +import org.gradle.internal.fingerprint.impl.DefaultCurrentFileCollectionFingerprint +import org.gradle.internal.hash.HashCode +import org.gradle.internal.snapshot.RegularFileSnapshot +import spock.lang.Specification + +class NonIncrementalInputChangesTest extends Specification { + + def "can iterate changes more than once"() { + def fingerprint = DefaultCurrentFileCollectionFingerprint.from([new RegularFileSnapshot("/some/where", "where", HashCode.fromInt(1234), 0)], AbsolutePathFingerprintingStrategy.INCLUDE_MISSING) + + def changes = new NonIncrementalInputChanges(ImmutableSortedMap.of("input", fingerprint), ImmutableMultimap.of("value", "input")) + def expectedChangedFiles = [new File("/some/where")] + + when: + def allFileChanges = changes.allFileChanges + def fileChanges = changes.getFileChanges("value") + + then: + allFileChanges*.file == expectedChangedFiles + allFileChanges*.file == expectedChangedFiles + + fileChanges*.file == expectedChangedFiles + fileChanges*.file == expectedChangedFiles + } + +} From a85472cdcdad4cee7d04cfa48b7bf68a840db486 Mon Sep 17 00:00:00 2001 From: Stefan Wolf Date: Fri, 15 Mar 2019 08:15:29 +0100 Subject: [PATCH 564/853] Rename {Context -> InputChanges}AwareTaskAction --- .../org/gradle/api/internal/AbstractTask.java | 44 +++++++++---------- .../org/gradle/api/internal/TaskInternal.java | 4 +- .../AbstractIncrementalTaskAction.java | 8 ++-- ....java => InputChangesAwareTaskAction.java} | 6 +-- .../execution/ExecuteActionsTaskExecuter.java | 12 ++--- ...solveBeforeExecutionStateTaskExecuter.java | 8 ++-- .../api/internal/DefaultTaskTest.groovy | 4 +- .../ExecuteActionsTaskExecuterTest.groovy | 26 +++++------ .../changes/ImplementationChangesTest.groovy | 8 ++-- 9 files changed, 60 insertions(+), 60 deletions(-) rename subprojects/core/src/main/java/org/gradle/api/internal/tasks/{ContextAwareTaskAction.java => InputChangesAwareTaskAction.java} (80%) diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/AbstractTask.java b/subprojects/core/src/main/java/org/gradle/api/internal/AbstractTask.java index 56e5d1d941982..8b4b8cc21b327 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/AbstractTask.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/AbstractTask.java @@ -33,13 +33,13 @@ import org.gradle.api.internal.file.TemporaryFileProvider; import org.gradle.api.internal.project.ProjectInternal; import org.gradle.api.internal.project.taskfactory.TaskIdentity; -import org.gradle.api.internal.tasks.ContextAwareTaskAction; import org.gradle.api.internal.tasks.DefaultTaskDependency; import org.gradle.api.internal.tasks.DefaultTaskDestroyables; import org.gradle.api.internal.tasks.DefaultTaskInputs; import org.gradle.api.internal.tasks.DefaultTaskLocalState; import org.gradle.api.internal.tasks.DefaultTaskOutputs; import org.gradle.api.internal.tasks.ImplementationAwareTaskAction; +import org.gradle.api.internal.tasks.InputChangesAwareTaskAction; import org.gradle.api.internal.tasks.TaskContainerInternal; import org.gradle.api.internal.tasks.TaskDependencyInternal; import org.gradle.api.internal.tasks.TaskLocalStateInternal; @@ -95,7 +95,7 @@ public abstract class AbstractTask implements TaskInternal, DynamicObjectAware { private final ProjectInternal project; - private List actions; + private List actions; private boolean enabled = true; @@ -227,9 +227,9 @@ public void propertyChange(PropertyChangeEvent evt) { } @Override - public List getTaskActions() { + public List getTaskActions() { if (actions == null) { - actions = new ArrayList(3); + actions = new ArrayList(3); } return actions; } @@ -589,17 +589,17 @@ public File create() { }; } - private ContextAwareTaskAction convertClosureToAction(Closure actionClosure, String actionName) { + private InputChangesAwareTaskAction convertClosureToAction(Closure actionClosure, String actionName) { return new ClosureTaskAction(actionClosure, actionName); } - private ContextAwareTaskAction wrap(final Action action) { + private InputChangesAwareTaskAction wrap(final Action action) { return wrap(action, "unnamed action"); } - private ContextAwareTaskAction wrap(final Action action, String actionName) { - if (action instanceof ContextAwareTaskAction) { - return (ContextAwareTaskAction) action; + private InputChangesAwareTaskAction wrap(final Action action, String actionName) { + if (action instanceof InputChangesAwareTaskAction) { + return (InputChangesAwareTaskAction) action; } return new TaskActionWrapper(action, actionName); } @@ -614,7 +614,7 @@ private TaskInfo(TaskIdentity identity, ProjectInternal project) { } } - private static class ClosureTaskAction implements ContextAwareTaskAction { + private static class ClosureTaskAction implements InputChangesAwareTaskAction { private final Closure closure; private final String actionName; @@ -624,11 +624,11 @@ private ClosureTaskAction(Closure closure, String actionName) { } @Override - public void contextualise(InputChangesInternal inputChanges) { + public void setInputChanges(InputChangesInternal inputChanges) { } @Override - public void releaseContext() { + public void clearInputChanges() { } @Override @@ -665,7 +665,7 @@ public String getDisplayName() { } } - private static class TaskActionWrapper implements ContextAwareTaskAction { + private static class TaskActionWrapper implements InputChangesAwareTaskAction { private final Action action; private final String maybeActionName; @@ -680,16 +680,16 @@ public TaskActionWrapper(Action action, String maybeActionName) { } @Override - public void contextualise(InputChangesInternal inputChanges) { - if (action instanceof ContextAwareTaskAction) { - ((ContextAwareTaskAction) action).contextualise(inputChanges); + public void setInputChanges(InputChangesInternal inputChanges) { + if (action instanceof InputChangesAwareTaskAction) { + ((InputChangesAwareTaskAction) action).setInputChanges(inputChanges); } } @Override - public void releaseContext() { - if (action instanceof ContextAwareTaskAction) { - ((ContextAwareTaskAction) action).releaseContext(); + public void clearInputChanges() { + if (action instanceof InputChangesAwareTaskAction) { + ((InputChangesAwareTaskAction) action).clearInputChanges(); } } @@ -872,9 +872,9 @@ public boolean remove(Object action) { return super.remove(wrap((Action) action)); } - private Collection transformToContextAwareTaskActions(Collection c) { - return Collections2.transform(c, new Function() { - public ContextAwareTaskAction apply(@Nullable Object input) { + private Collection transformToContextAwareTaskActions(Collection c) { + return Collections2.transform(c, new Function() { + public InputChangesAwareTaskAction apply(@Nullable Object input) { return wrap((Action) input); } }); diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/TaskInternal.java b/subprojects/core/src/main/java/org/gradle/api/internal/TaskInternal.java index c9bea9245c4ff..73edce572febe 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/TaskInternal.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/TaskInternal.java @@ -19,7 +19,7 @@ import org.gradle.api.Action; import org.gradle.api.Task; import org.gradle.api.internal.project.taskfactory.TaskIdentity; -import org.gradle.api.internal.tasks.ContextAwareTaskAction; +import org.gradle.api.internal.tasks.InputChangesAwareTaskAction; import org.gradle.api.internal.tasks.TaskStateInternal; import org.gradle.api.logging.Logger; import org.gradle.api.specs.Spec; @@ -40,7 +40,7 @@ public interface TaskInternal extends Task, Configurable { * once they start executing. */ @Internal - List getTaskActions(); + List getTaskActions(); @Internal boolean hasTaskActions(); diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/project/taskfactory/AbstractIncrementalTaskAction.java b/subprojects/core/src/main/java/org/gradle/api/internal/project/taskfactory/AbstractIncrementalTaskAction.java index 19e45590c5ec1..abcd23bfdedbb 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/project/taskfactory/AbstractIncrementalTaskAction.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/project/taskfactory/AbstractIncrementalTaskAction.java @@ -17,12 +17,12 @@ package org.gradle.api.internal.project.taskfactory; import org.gradle.api.Task; -import org.gradle.api.internal.tasks.ContextAwareTaskAction; +import org.gradle.api.internal.tasks.InputChangesAwareTaskAction; import org.gradle.internal.execution.history.changes.InputChangesInternal; import java.lang.reflect.Method; -public abstract class AbstractIncrementalTaskAction extends StandardTaskAction implements ContextAwareTaskAction { +public abstract class AbstractIncrementalTaskAction extends StandardTaskAction implements InputChangesAwareTaskAction { private InputChangesInternal inputChanges; public AbstractIncrementalTaskAction(Class type, Method method) { @@ -30,12 +30,12 @@ public AbstractIncrementalTaskAction(Class type, Method method) } @Override - public void contextualise(InputChangesInternal inputChanges) { + public void setInputChanges(InputChangesInternal inputChanges) { this.inputChanges = inputChanges; } @Override - public void releaseContext() { + public void clearInputChanges() { this.inputChanges = null; } diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/ContextAwareTaskAction.java b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/InputChangesAwareTaskAction.java similarity index 80% rename from subprojects/core/src/main/java/org/gradle/api/internal/tasks/ContextAwareTaskAction.java rename to subprojects/core/src/main/java/org/gradle/api/internal/tasks/InputChangesAwareTaskAction.java index e070c0a383f10..fa8e96fa5aec5 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/ContextAwareTaskAction.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/InputChangesAwareTaskAction.java @@ -19,7 +19,7 @@ import org.gradle.api.Describable; import org.gradle.internal.execution.history.changes.InputChangesInternal; -public interface ContextAwareTaskAction extends ImplementationAwareTaskAction, Describable { - void contextualise(InputChangesInternal inputChanges); - void releaseContext(); +public interface InputChangesAwareTaskAction extends ImplementationAwareTaskAction, Describable { + void setInputChanges(InputChangesInternal inputChanges); + void clearInputChanges(); } diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuter.java b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuter.java index 06a4c6f17028d..bdbcc804cb06f 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuter.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuter.java @@ -21,7 +21,7 @@ import org.gradle.api.internal.OverlappingOutputs; import org.gradle.api.internal.TaskInternal; import org.gradle.api.internal.project.taskfactory.AbstractIncrementalTaskAction; -import org.gradle.api.internal.tasks.ContextAwareTaskAction; +import org.gradle.api.internal.tasks.InputChangesAwareTaskAction; import org.gradle.api.internal.tasks.TaskExecuter; import org.gradle.api.internal.tasks.TaskExecuterResult; import org.gradle.api.internal.tasks.TaskExecutionContext; @@ -317,7 +317,7 @@ public ImmutableSortedMap apply(Overla @Override public boolean isIncremental() { - for (ContextAwareTaskAction taskAction : task.getTaskActions()) { + for (InputChangesAwareTaskAction taskAction : task.getTaskActions()) { if (taskAction instanceof AbstractIncrementalTaskAction) { return true; } @@ -337,7 +337,7 @@ public String getDisplayName() { } private void executeActions(TaskInternal task, @Nullable InputChangesInternal inputChanges) { - for (ContextAwareTaskAction action : new ArrayList(task.getTaskActions())) { + for (InputChangesAwareTaskAction action : new ArrayList(task.getTaskActions())) { task.getState().setDidWork(true); task.getStandardOutputCapture().start(); try { @@ -354,9 +354,9 @@ private void executeActions(TaskInternal task, @Nullable InputChangesInternal in } } - private void executeAction(final String actionDisplayName, final TaskInternal task, final ContextAwareTaskAction action, @Nullable InputChangesInternal inputChanges) { + private void executeAction(final String actionDisplayName, final TaskInternal task, final InputChangesAwareTaskAction action, @Nullable InputChangesInternal inputChanges) { if (inputChanges != null) { - action.contextualise(inputChanges); + action.setInputChanges(inputChanges); } buildOperationExecutor.run(new RunnableBuildOperation() { @Override @@ -373,7 +373,7 @@ public void run(BuildOperationContext context) { } catch (Throwable t) { actionFailure = t; } finally { - action.releaseContext(); + action.clearInputChanges(); } try { diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/ResolveBeforeExecutionStateTaskExecuter.java b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/ResolveBeforeExecutionStateTaskExecuter.java index f2b495e56534e..7f9b34362e4f6 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/ResolveBeforeExecutionStateTaskExecuter.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/ResolveBeforeExecutionStateTaskExecuter.java @@ -20,7 +20,7 @@ import com.google.common.collect.ImmutableSortedMap; import org.gradle.api.UncheckedIOException; import org.gradle.api.internal.TaskInternal; -import org.gradle.api.internal.tasks.ContextAwareTaskAction; +import org.gradle.api.internal.tasks.InputChangesAwareTaskAction; import org.gradle.api.internal.tasks.TaskExecuter; import org.gradle.api.internal.tasks.TaskExecuterResult; import org.gradle.api.internal.tasks.TaskExecutionContext; @@ -77,7 +77,7 @@ public TaskExecuterResult execute(TaskInternal task, TaskStateInternal state, Ta private BeforeExecutionState createExecutionState(TaskInternal task, TaskProperties properties, @Nullable AfterPreviousExecutionState afterPreviousExecutionState, ImmutableSortedMap outputFiles) { Class taskClass = task.getClass(); - List taskActions = task.getTaskActions(); + List taskActions = task.getTaskActions(); ImplementationSnapshot taskImplementation = ImplementationSnapshot.of(taskClass, classLoaderHierarchyHasher); ImmutableList taskActionImplementations = collectActionImplementations(taskActions, classLoaderHierarchyHasher); @@ -101,12 +101,12 @@ private BeforeExecutionState createExecutionState(TaskInternal task, TaskPropert ); } - private static ImmutableList collectActionImplementations(Collection taskActions, ClassLoaderHierarchyHasher classLoaderHierarchyHasher) { + private static ImmutableList collectActionImplementations(Collection taskActions, ClassLoaderHierarchyHasher classLoaderHierarchyHasher) { if (taskActions.isEmpty()) { return ImmutableList.of(); } ImmutableList.Builder actionImplementations = ImmutableList.builder(); - for (ContextAwareTaskAction taskAction : taskActions) { + for (InputChangesAwareTaskAction taskAction : taskActions) { actionImplementations.add(taskAction.getActionImplementation(classLoaderHierarchyHasher)); } return actionImplementations.build(); diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/DefaultTaskTest.groovy b/subprojects/core/src/test/groovy/org/gradle/api/internal/DefaultTaskTest.groovy index da363bd969075..253d6f3ffa00d 100644 --- a/subprojects/core/src/test/groovy/org/gradle/api/internal/DefaultTaskTest.groovy +++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/DefaultTaskTest.groovy @@ -23,7 +23,7 @@ import org.gradle.api.InvalidUserDataException import org.gradle.api.Project import org.gradle.api.Task import org.gradle.api.internal.project.taskfactory.TaskIdentity -import org.gradle.api.internal.tasks.ContextAwareTaskAction +import org.gradle.api.internal.tasks.InputChangesAwareTaskAction import org.gradle.api.logging.Logger import org.gradle.api.tasks.AbstractTaskTest import org.gradle.api.tasks.TaskExecutionException @@ -495,7 +495,7 @@ class DefaultTaskTest extends AbstractTaskTest { def "describable actions are not renamed"() { setup: - def namedAction = Mock(ContextAwareTaskAction) + def namedAction = Mock(InputChangesAwareTaskAction) namedAction.displayName >> "I have a name" when: diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuterTest.groovy b/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuterTest.groovy index b4b70acdb115e..7cb07edae761c 100644 --- a/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuterTest.groovy +++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuterTest.groovy @@ -21,7 +21,7 @@ import org.gradle.api.execution.TaskActionListener import org.gradle.api.internal.TaskInternal import org.gradle.api.internal.changedetection.TaskExecutionMode import org.gradle.api.internal.project.ProjectInternal -import org.gradle.api.internal.tasks.ContextAwareTaskAction +import org.gradle.api.internal.tasks.InputChangesAwareTaskAction import org.gradle.api.internal.tasks.TaskExecutionContext import org.gradle.api.internal.tasks.TaskExecutionOutcome import org.gradle.api.internal.tasks.TaskStateInternal @@ -59,8 +59,8 @@ import static java.util.Collections.emptyList class ExecuteActionsTaskExecuterTest extends Specification { def task = Mock(TaskInternal) - def action1 = Mock(ContextAwareTaskAction) - def action2 = Mock(ContextAwareTaskAction) + def action1 = Mock(InputChangesAwareTaskAction) + def action2 = Mock(InputChangesAwareTaskAction) def state = new TaskStateInternal() def executionContext = Mock(TaskExecutionContext) def taskProperties = Mock(TaskProperties) @@ -152,7 +152,7 @@ class ExecuteActionsTaskExecuterTest extends Specification { assert state.executing } then: - 1 * action1.releaseContext() + 1 * action1.clearInputChanges() then: 1 * asyncWorkTracker.waitForCompletion(_, true) then: @@ -164,7 +164,7 @@ class ExecuteActionsTaskExecuterTest extends Specification { then: 1 * action2.execute(task) then: - 1 * action2.releaseContext() + 1 * action2.clearInputChanges() then: 1 * asyncWorkTracker.waitForCompletion(_, true) then: @@ -200,7 +200,7 @@ class ExecuteActionsTaskExecuterTest extends Specification { task.getActions().add(action2) } then: - 1 * action1.releaseContext() + 1 * action1.clearInputChanges() then: 1 * asyncWorkTracker.waitForCompletion(_, true) then: @@ -226,7 +226,7 @@ class ExecuteActionsTaskExecuterTest extends Specification { then: 1 * buildOperationExecutor.run(_ as RunnableBuildOperation) >> { args -> args[0].run(Stub(BuildOperationContext)) } then: - 1 * action1.releaseContext() + 1 * action1.clearInputChanges() then: 1 * asyncWorkTracker.waitForCompletion(_, true) then: @@ -259,7 +259,7 @@ class ExecuteActionsTaskExecuterTest extends Specification { throw new StopExecutionException('stop') } then: - 1 * action1.releaseContext() + 1 * action1.clearInputChanges() then: 1 * asyncWorkTracker.waitForCompletion(_, true) then: @@ -290,7 +290,7 @@ class ExecuteActionsTaskExecuterTest extends Specification { throw new StopActionException('stop') } then: - 1 * action1.releaseContext() + 1 * action1.clearInputChanges() then: 1 * asyncWorkTracker.waitForCompletion(_, true) then: @@ -302,7 +302,7 @@ class ExecuteActionsTaskExecuterTest extends Specification { then: 1 * action2.execute(task) then: - 1 * action2.releaseContext() + 1 * action2.clearInputChanges() then: 1 * asyncWorkTracker.waitForCompletion(_, true) then: @@ -330,7 +330,7 @@ class ExecuteActionsTaskExecuterTest extends Specification { then: 1 * buildOperationExecutor.run(_ as RunnableBuildOperation) >> { args -> args[0].run(Stub(BuildOperationContext)) } then: - 1 * action1.releaseContext() + 1 * action1.clearInputChanges() then: 1 * asyncWorkTracker.waitForCompletion(_, true) >> { throw new DefaultMultiCauseException("mock failures", new RuntimeException("failure 1"), new RuntimeException("failure 2")) @@ -368,7 +368,7 @@ class ExecuteActionsTaskExecuterTest extends Specification { then: 1 * buildOperationExecutor.run(_ as RunnableBuildOperation) >> { args -> args[0].run(Stub(BuildOperationContext)) } then: - 1 * action1.releaseContext() + 1 * action1.clearInputChanges() then: 1 * asyncWorkTracker.waitForCompletion(_, true) >> { throw new DefaultMultiCauseException("mock failures", new RuntimeException("failure 1"), new RuntimeException("failure 2")) @@ -405,7 +405,7 @@ class ExecuteActionsTaskExecuterTest extends Specification { then: 1 * buildOperationExecutor.run(_ as RunnableBuildOperation) >> { args -> args[0].run(Stub(BuildOperationContext)) } then: - 1 * action1.releaseContext() + 1 * action1.clearInputChanges() then: 1 * asyncWorkTracker.waitForCompletion(_, true) >> { throw new DefaultMultiCauseException("mock failures", failure) diff --git a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/history/changes/ImplementationChangesTest.groovy b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/history/changes/ImplementationChangesTest.groovy index 3dce6153aa8a6..dafff9f384c4b 100644 --- a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/history/changes/ImplementationChangesTest.groovy +++ b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/history/changes/ImplementationChangesTest.groovy @@ -21,7 +21,7 @@ import org.gradle.api.DefaultTask import org.gradle.api.Describable import org.gradle.api.Task import org.gradle.api.internal.TaskInternal -import org.gradle.api.internal.tasks.ContextAwareTaskAction +import org.gradle.api.internal.tasks.InputChangesAwareTaskAction import org.gradle.internal.Cast import org.gradle.internal.change.CollectingChangeVisitor import org.gradle.internal.classloader.ClassLoaderHierarchyHasher @@ -152,13 +152,13 @@ class ImplementationChangesTest extends Specification { private class SimpleTask extends DefaultTask {} private class PreviousTask extends DefaultTask {} - private static class TestAction implements ContextAwareTaskAction { + private static class TestAction implements InputChangesAwareTaskAction { @Override - void contextualise(InputChangesInternal inputChanges) { + void setInputChanges(InputChangesInternal inputChanges) { } @Override - void releaseContext() { + void clearInputChanges() { } @Override From e2c9f16de57198be0e3eb4cd6994a6b54566fc24 Mon Sep 17 00:00:00 2001 From: Stefan Wolf Date: Fri, 15 Mar 2019 08:29:37 +0100 Subject: [PATCH 565/853] Rename UnitOfWork.{incremental -> requiresInputChanges} --- .../tasks/execution/ExecuteActionsTaskExecuter.java | 2 +- .../internal/artifacts/transform/DefaultTransformer.java | 8 ++++---- .../artifacts/transform/DefaultTransformerInvoker.java | 4 ++-- .../internal/artifacts/transform/LegacyTransformer.java | 2 +- .../api/internal/artifacts/transform/Transformer.java | 4 ++-- .../transform/DefaultTransformerInvokerTest.groovy | 2 +- .../execution/IncrementalExecutionIntegrationTest.groovy | 2 +- .../java/org/gradle/internal/execution/UnitOfWork.java | 2 +- .../org/gradle/internal/execution/steps/ExecuteStep.java | 2 +- .../internal/execution/steps/ExecuteStepTest.groovy | 6 +++--- 10 files changed, 17 insertions(+), 17 deletions(-) diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuter.java b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuter.java index bdbcc804cb06f..8924cab4c39ef 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuter.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuter.java @@ -316,7 +316,7 @@ public ImmutableSortedMap apply(Overla } @Override - public boolean isIncremental() { + public boolean isRequiresInputChanges() { for (InputChangesAwareTaskAction taskAction : task.getTaskActions()) { if (taskAction instanceof AbstractIncrementalTaskAction) { return true; diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformer.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformer.java index fe37685377b52..5839aeaabe11b 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformer.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformer.java @@ -83,11 +83,11 @@ public class DefaultTransformer extends AbstractTransformer { private final FileCollectionFactory fileCollectionFactory; private final PropertyWalker parameterPropertyWalker; private final boolean requiresDependencies; + private final boolean requiresInputChanges; private final InstanceFactory instanceFactory; private final boolean cacheable; private IsolatedParameters isolatedParameters; - private final boolean incremental; public DefaultTransformer( Class implementationClass, @@ -114,7 +114,7 @@ public DefaultTransformer( this.parameterPropertyWalker = parameterPropertyWalker; this.instanceFactory = actionInstantiationScheme.forType(implementationClass); this.requiresDependencies = instanceFactory.serviceInjectionTriggeredByAnnotation(InputArtifactDependencies.class); - this.incremental = instanceFactory.requiresService(InputChanges.class); + this.requiresInputChanges = instanceFactory.requiresService(InputChanges.class); this.cacheable = cacheable; } @@ -149,8 +149,8 @@ public boolean requiresDependencies() { } @Override - public boolean isIncremental() { - return incremental; + public boolean requiresInputChanges() { + return requiresInputChanges; } @Override diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvoker.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvoker.java index 447af964125d7..dff8d46227069 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvoker.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvoker.java @@ -395,8 +395,8 @@ public ImmutableSortedMap snapshotAfte } @Override - public boolean isIncremental() { - return transformer.isIncremental(); + public boolean isRequiresInputChanges() { + return transformer.requiresInputChanges(); } @Override diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/LegacyTransformer.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/LegacyTransformer.java index 1e76b426a559e..cdcf1d59b67fd 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/LegacyTransformer.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/LegacyTransformer.java @@ -56,7 +56,7 @@ public boolean requiresDependencies() { } @Override - public boolean isIncremental() { + public boolean requiresInputChanges() { return false; } diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/Transformer.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/Transformer.java index d167a2e7e9776..95b0b07695fde 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/Transformer.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/Transformer.java @@ -45,9 +45,9 @@ public interface Transformer extends Describable, TaskDependencyContainer { boolean requiresDependencies(); /** - * Whether the transformer supports incremental execution. + * Whether the transformer requires {@link InputChanges} to be injected. */ - boolean isIncremental(); + boolean requiresInputChanges(); /** * Whether the transformer is cacheable. diff --git a/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvokerTest.groovy b/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvokerTest.groovy index af54e9eadfcb9..8d317b41bcf30 100644 --- a/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvokerTest.groovy +++ b/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvokerTest.groovy @@ -127,7 +127,7 @@ class DefaultTransformerInvokerTest extends AbstractProjectBuilderSpec { } @Override - boolean isIncremental() { + boolean requiresInputChanges() { return false } diff --git a/subprojects/execution/src/integTest/groovy/org/gradle/internal/execution/IncrementalExecutionIntegrationTest.groovy b/subprojects/execution/src/integTest/groovy/org/gradle/internal/execution/IncrementalExecutionIntegrationTest.groovy index 34dffc197efc3..f003a83fed357 100644 --- a/subprojects/execution/src/integTest/groovy/org/gradle/internal/execution/IncrementalExecutionIntegrationTest.groovy +++ b/subprojects/execution/src/integTest/groovy/org/gradle/internal/execution/IncrementalExecutionIntegrationTest.groovy @@ -886,7 +886,7 @@ class IncrementalExecutionIntegrationTest extends Specification { } @Override - boolean isIncremental() { + boolean isRequiresInputChanges() { return false } diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/UnitOfWork.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/UnitOfWork.java index 2a4709bb98660..aa45456ec0868 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/UnitOfWork.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/UnitOfWork.java @@ -37,7 +37,7 @@ public interface UnitOfWork extends CacheableEntity { Optional getTimeout(); - boolean isIncremental(); + boolean isRequiresInputChanges(); void visitFileInputs(InputFilePropertyVisitor visitor); diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/ExecuteStep.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/ExecuteStep.java index 292470429de61..9f4acb2fe8132 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/ExecuteStep.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/ExecuteStep.java @@ -33,7 +33,7 @@ public class ExecuteStep implements Step> work - 1 * work.incremental >> false + 1 * work.requiresInputChanges >> false 1 * work.execute(null) >> workResult 0 * _ @@ -62,7 +62,7 @@ class ExecuteStepTest extends Specification { ex == failure 1 * context.work >> work - 1 * work.incremental >> false + 1 * work.requiresInputChanges >> false 1 * work.execute(null) >> { throw failure } 0 * _ @@ -79,7 +79,7 @@ class ExecuteStepTest extends Specification { result.outcome.get() == outcome 1 * context.work >> work - 1 * work.incremental >> true + 1 * work.requiresInputChanges >> true 1 * context.changes >> optionalChanges 1 * work.visitFileInputs(_) >> { args -> ((UnitOfWork.InputFilePropertyVisitor) args[0]).visitInputFileProperty("fileInput", "some/path") From b2b87a350b3c4b97416eacdd43b6848ff7c7be2d Mon Sep 17 00:00:00 2001 From: Cedric Champeau Date: Thu, 14 Mar 2019 10:55:01 +0100 Subject: [PATCH 566/853] Optimize `ModuleVersionResolveException` During resolution, we may throw a lot of `ModuleVersionResolveException` or `ModuleVersionNotFoundException`. Often, one per repository, when a version is not found in that repository. But in the end, the version may be found, or a different version may be selected, in which case we don't care about the failure, which is only used if _no version_ could be selected. As a consequence, we had a lot of overhead in both generating a stack trace **and** an error message, that would never be used. This commit reworks those special exceptions used during resolution so that we avoid filling the stack trace (we don't care) and we create the message lazily (only if it will actually be used). --- .../DefaultMultiCauseException.java | 36 +++++++++ ...efaultMultiCauseExceptionNoStackTrace.java | 42 +++++++++++ ...CompositeBuildDependencySubstitutions.java | 18 +++-- .../DefaultIncludedBuildTaskGraph.java | 2 +- .../DefaultComponentMetadataProcessor.java | 4 +- ...rrorHandlingModuleComponentRepository.java | 7 +- .../ivyresolve/NoRepositoriesResolver.java | 2 +- .../StartParameterResolutionOverride.java | 4 +- .../ProjectDependencyResolver.java | 4 +- .../DefaultResolutionResultBuilder.java | 2 +- .../ModuleVersionNotFoundException.java | 75 ++++++++++--------- .../ModuleVersionResolveException.java | 28 ++++--- ...oviderComponentMetaDataResolverTest.groovy | 9 ++- .../DependencyGraphBuilderTest.groovy | 6 +- .../CachingDependencyResultFactoryTest.groovy | 13 ++-- .../result/DefaultResolutionResultTest.groovy | 3 +- ...ildableComponentIdResolveResultTest.groovy | 3 +- ...BuildableComponentResolveResultTest.groovy | 9 ++- ...eComponentMetaDataResolveResultTest.groovy | 6 +- ...duleVersionListingResolveResultTest.groovy | 3 +- .../result/ResolutionResultDataBuilder.groovy | 3 +- .../LocalLibraryDependencyResolver.java | 21 +++++- .../OfflineVcsVersionWorkingDirResolver.java | 2 +- .../resolver/VcsDependencyResolver.java | 2 +- 24 files changed, 211 insertions(+), 93 deletions(-) create mode 100644 subprojects/base-services/src/main/java/org/gradle/internal/exceptions/DefaultMultiCauseExceptionNoStackTrace.java diff --git a/subprojects/base-services/src/main/java/org/gradle/internal/exceptions/DefaultMultiCauseException.java b/subprojects/base-services/src/main/java/org/gradle/internal/exceptions/DefaultMultiCauseException.java index 45a03676fcb84..bda9388362e7c 100644 --- a/subprojects/base-services/src/main/java/org/gradle/internal/exceptions/DefaultMultiCauseException.java +++ b/subprojects/base-services/src/main/java/org/gradle/internal/exceptions/DefaultMultiCauseException.java @@ -16,6 +16,8 @@ package org.gradle.internal.exceptions; import org.gradle.api.GradleException; +import org.gradle.internal.Factory; + import java.io.IOException; import java.io.ObjectInputStream; import java.io.PrintStream; @@ -27,18 +29,37 @@ public class DefaultMultiCauseException extends GradleException implements MultiCauseException { private final List causes = new CopyOnWriteArrayList(); private transient ThreadLocal hideCause = threadLocal(); + private transient Factory messageFactory; + private String message; public DefaultMultiCauseException(String message) { super(message); + this.message = message; } public DefaultMultiCauseException(String message, Throwable... causes) { super(message); + this.message = message; this.causes.addAll(Arrays.asList(causes)); } public DefaultMultiCauseException(String message, Iterable causes) { super(message); + this.message = message; + initCauses(causes); + } + + public DefaultMultiCauseException(Factory messageFactory) { + this.messageFactory = messageFactory; + } + + public DefaultMultiCauseException(Factory messageFactory, Throwable... causes) { + this(messageFactory); + this.causes.addAll(Arrays.asList(causes)); + } + + public DefaultMultiCauseException(Factory messageFactory, Iterable causes) { + this(messageFactory); initCauses(causes); } @@ -47,6 +68,11 @@ private void readObject(ObjectInputStream inputStream) throws IOException, Class hideCause = threadLocal(); } + private void writeObject(java.io.ObjectOutputStream out) throws IOException { + getMessage(); + out.defaultWriteObject(); + } + private ThreadLocal threadLocal() { return new ThreadLocal() { @Override @@ -108,4 +134,14 @@ public void printStackTrace(PrintWriter printWriter) { hideCause.set(false); } } + + @Override + public String getMessage() { + if (messageFactory != null) { + message = messageFactory.create(); + messageFactory = null; + return message; + } + return message; + } } diff --git a/subprojects/base-services/src/main/java/org/gradle/internal/exceptions/DefaultMultiCauseExceptionNoStackTrace.java b/subprojects/base-services/src/main/java/org/gradle/internal/exceptions/DefaultMultiCauseExceptionNoStackTrace.java new file mode 100644 index 0000000000000..5a741747a22ec --- /dev/null +++ b/subprojects/base-services/src/main/java/org/gradle/internal/exceptions/DefaultMultiCauseExceptionNoStackTrace.java @@ -0,0 +1,42 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.gradle.internal.exceptions; + +import org.gradle.internal.Factory; + +/** + * A specialized version of multi cause exception that is cheaper to create + * because we avoid to fill a stack trace, and the message MUST be generated lazily. + */ +@Contextual +public class DefaultMultiCauseExceptionNoStackTrace extends DefaultMultiCauseException { + public DefaultMultiCauseExceptionNoStackTrace(Factory messageFactory) { + super(messageFactory); + } + + public DefaultMultiCauseExceptionNoStackTrace(Factory messageFactory, Throwable... causes) { + super(messageFactory, causes); + } + + public DefaultMultiCauseExceptionNoStackTrace(Factory messageFactory, Iterable causes) { + super(messageFactory, causes); + } + + @Override + public synchronized Throwable fillInStackTrace() { + return this; + } +} diff --git a/subprojects/composite-builds/src/main/java/org/gradle/composite/internal/CompositeBuildDependencySubstitutions.java b/subprojects/composite-builds/src/main/java/org/gradle/composite/internal/CompositeBuildDependencySubstitutions.java index e1f9812955221..45b2d8a95b8a4 100644 --- a/subprojects/composite-builds/src/main/java/org/gradle/composite/internal/CompositeBuildDependencySubstitutions.java +++ b/subprojects/composite-builds/src/main/java/org/gradle/composite/internal/CompositeBuildDependencySubstitutions.java @@ -82,13 +82,15 @@ private ProjectComponentIdentifier getReplacementFor(ModuleComponentSelector sel LOGGER.info("Found project '" + match + "' as substitute for module '" + candidateId + "'."); return match; } - SortedSet sortedProjects = Sets.newTreeSet(CollectionUtils.collect(providingProjects, new Transformer() { - @Override - public String transform(ProjectComponentIdentifier projectComponentIdentifier) { - return projectComponentIdentifier.getDisplayName(); - } - })); - String failureMessage = String.format("Module version '%s' is not unique in composite: can be provided by %s.", selector.getDisplayName(), sortedProjects); - throw new ModuleVersionResolveException(selector, failureMessage); + throw new ModuleVersionResolveException(selector, () -> { + SortedSet sortedProjects = Sets.newTreeSet(CollectionUtils.collect(providingProjects, new Transformer() { + @Override + public String transform(ProjectComponentIdentifier projectComponentIdentifier) { + return projectComponentIdentifier.getDisplayName(); + } + })); + + return String.format("Module version '%s' is not unique in composite: can be provided by %s.", selector.getDisplayName(), sortedProjects); + }); } } diff --git a/subprojects/composite-builds/src/main/java/org/gradle/composite/internal/DefaultIncludedBuildTaskGraph.java b/subprojects/composite-builds/src/main/java/org/gradle/composite/internal/DefaultIncludedBuildTaskGraph.java index 6413781409d52..25b7c3979e709 100644 --- a/subprojects/composite-builds/src/main/java/org/gradle/composite/internal/DefaultIncludedBuildTaskGraph.java +++ b/subprojects/composite-builds/src/main/java/org/gradle/composite/internal/DefaultIncludedBuildTaskGraph.java @@ -73,7 +73,7 @@ private void checkNoCycles(BuildIdentifier sourceBuild, BuildIdentifier targetBu if (sourceBuild.equals(nextTarget)) { candidateCycle.add(nextTarget); ProjectComponentSelector selector = new DefaultProjectComponentSelector(candidateCycle.get(0), Path.ROOT, Path.ROOT, ":", ImmutableAttributes.EMPTY, Collections.emptyList()); - throw new ModuleVersionResolveException(selector, "Included build dependency cycle: " + reportCycle(candidateCycle)); + throw new ModuleVersionResolveException(selector, () -> "Included build dependency cycle: " + reportCycle(candidateCycle)); } checkNoCycles(sourceBuild, nextTarget, candidateCycle); diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/dsl/DefaultComponentMetadataProcessor.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/dsl/DefaultComponentMetadataProcessor.java index f7e79a86c91e6..af525c61d1ec7 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/dsl/DefaultComponentMetadataProcessor.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/dsl/DefaultComponentMetadataProcessor.java @@ -181,7 +181,7 @@ public ModuleComponentResolveMetadata processMetadata(ModuleComponentResolveMeta } if (!updatedMetadata.getStatusScheme().contains(updatedMetadata.getStatus())) { - throw new ModuleVersionResolveException(updatedMetadata.getModuleVersionId(), String.format("Unexpected status '%s' specified for %s. Expected one of: %s", updatedMetadata.getStatus(), updatedMetadata.getId().getDisplayName(), updatedMetadata.getStatusScheme())); + throw new ModuleVersionResolveException(updatedMetadata.getModuleVersionId(), () -> String.format("Unexpected status '%s' specified for %s. Expected one of: %s", updatedMetadata.getStatus(), updatedMetadata.getId().getDisplayName(), updatedMetadata.getStatusScheme())); } return updatedMetadata; } @@ -201,7 +201,7 @@ public ComponentMetadata processMetadata(ComponentMetadata metadata) { updatedMetadata = details.asImmutable(); } if (!updatedMetadata.getStatusScheme().contains(updatedMetadata.getStatus())) { - throw new ModuleVersionResolveException(updatedMetadata.getId(), String.format("Unexpected status '%s' specified for %s. Expected one of: %s", updatedMetadata.getStatus(), updatedMetadata.getId().toString(), updatedMetadata.getStatusScheme())); + throw new ModuleVersionResolveException(updatedMetadata.getId(), () -> String.format("Unexpected status '%s' specified for %s. Expected one of: %s", updatedMetadata.getStatus(), updatedMetadata.getId().toString(), updatedMetadata.getStatusScheme())); } return updatedMetadata; } diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/ErrorHandlingModuleComponentRepository.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/ErrorHandlingModuleComponentRepository.java index 93bc275adcd88..060d83571f636 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/ErrorHandlingModuleComponentRepository.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/ErrorHandlingModuleComponentRepository.java @@ -145,11 +145,10 @@ public String toString() { public void listModuleVersions(ModuleDependencyMetadata dependency, BuildableModuleVersionListingResolveResult result) { performOperationWithRetries(result, () -> delegate.listModuleVersions(dependency, result), - () -> new ModuleVersionResolveException(dependency.getSelector(), BLACKLISTED_REPOSITORY_ERROR_MESSAGE), + () -> new ModuleVersionResolveException(dependency.getSelector(), () -> BLACKLISTED_REPOSITORY_ERROR_MESSAGE), throwable -> { ModuleComponentSelector selector = dependency.getSelector(); - String message = "Failed to list versions for " + selector.getGroup() + ":" + selector.getModule() + "."; - return new ModuleVersionResolveException(selector, message, throwable); + return new ModuleVersionResolveException(selector, () -> "Failed to list versions for " + selector.getGroup() + ":" + selector.getModule() + ".", throwable); }); } @@ -157,7 +156,7 @@ public void listModuleVersions(ModuleDependencyMetadata dependency, BuildableMod public void resolveComponentMetaData(ModuleComponentIdentifier moduleComponentIdentifier, ComponentOverrideMetadata requestMetaData, BuildableModuleComponentMetaDataResolveResult result) { performOperationWithRetries(result, () -> delegate.resolveComponentMetaData(moduleComponentIdentifier, requestMetaData, result), - () -> new ModuleVersionResolveException(moduleComponentIdentifier, BLACKLISTED_REPOSITORY_ERROR_MESSAGE), + () -> new ModuleVersionResolveException(moduleComponentIdentifier, () -> BLACKLISTED_REPOSITORY_ERROR_MESSAGE), throwable -> new ModuleVersionResolveException(moduleComponentIdentifier, throwable) ); } diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/NoRepositoriesResolver.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/NoRepositoriesResolver.java index 053783651f39b..bfd43681d9a16 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/NoRepositoriesResolver.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/NoRepositoriesResolver.java @@ -67,7 +67,7 @@ public OriginArtifactSelector getArtifactSelector() { @Override public void resolve(DependencyMetadata dependency, VersionSelector acceptor, VersionSelector rejector, BuildableComponentIdResolveResult result) { - result.failed(new ModuleVersionNotFoundException(dependency.getSelector(), String.format("Cannot resolve external dependency %s because no repositories are defined.", dependency.getSelector()))); + result.failed(new ModuleVersionNotFoundException(dependency.getSelector(), () -> String.format("Cannot resolve external dependency %s because no repositories are defined.", dependency.getSelector()))); } @Override diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/StartParameterResolutionOverride.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/StartParameterResolutionOverride.java index 0beab7d6b0970..6ea2b26643d5f 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/StartParameterResolutionOverride.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/StartParameterResolutionOverride.java @@ -88,12 +88,12 @@ public String toString() { @Override public void listModuleVersions(ModuleDependencyMetadata dependency, BuildableModuleVersionListingResolveResult result) { - result.failed(new ModuleVersionResolveException(dependency.getSelector(), String.format("No cached version listing for %s available for offline mode.", dependency.getSelector()))); + result.failed(new ModuleVersionResolveException(dependency.getSelector(), () -> String.format("No cached version listing for %s available for offline mode.", dependency.getSelector()))); } @Override public void resolveComponentMetaData(ModuleComponentIdentifier moduleComponentIdentifier, ComponentOverrideMetadata requestMetaData, BuildableModuleComponentMetaDataResolveResult result) { - result.failed(new ModuleVersionResolveException(moduleComponentIdentifier, String.format("No cached version of %s available for offline mode.", moduleComponentIdentifier.getDisplayName()))); + result.failed(new ModuleVersionResolveException(moduleComponentIdentifier, () -> String.format("No cached version of %s available for offline mode.", moduleComponentIdentifier.getDisplayName()))); } @Override diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/projectmodule/ProjectDependencyResolver.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/projectmodule/ProjectDependencyResolver.java index a3677f1cec003..bdb29c4ea06d1 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/projectmodule/ProjectDependencyResolver.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/projectmodule/ProjectDependencyResolver.java @@ -97,7 +97,7 @@ public void resolve(DependencyMetadata dependency, VersionSelector acceptor, Ver ProjectComponentIdentifier projectId = componentIdentifierFactory.createProjectComponentIdentifier(selector); LocalComponentMetadata componentMetaData = localComponentRegistry.getComponent(projectId); if (componentMetaData == null) { - result.failed(new ModuleVersionResolveException(selector, projectId + " not found.")); + result.failed(new ModuleVersionResolveException(selector, () -> projectId + " not found.")); } else { result.resolved(componentMetaData); } @@ -110,7 +110,7 @@ public void resolve(ComponentIdentifier identifier, ComponentOverrideMetadata co ProjectComponentIdentifier projectId = (ProjectComponentIdentifier) identifier; LocalComponentMetadata componentMetaData = localComponentRegistry.getComponent(projectId); if (componentMetaData == null) { - result.failed(new ModuleVersionResolveException(DefaultProjectComponentSelector.newSelector(projectId), projectId + " not found.")); + result.failed(new ModuleVersionResolveException(DefaultProjectComponentSelector.newSelector(projectId), () -> projectId + " not found.")); } else { result.resolved(componentMetaData); } diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/result/DefaultResolutionResultBuilder.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/result/DefaultResolutionResultBuilder.java index cf95a7c0b2e07..37c89f20d77a8 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/result/DefaultResolutionResultBuilder.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/result/DefaultResolutionResultBuilder.java @@ -102,7 +102,7 @@ public void addExtraFailures(Long rootId, Set extraFailure ModuleComponentSelector failureComponentSelector = DefaultModuleComponentSelector.newSelector(failureSelector.getModule(), failureSelector.getVersion()); root.addDependency(dependencyResultFactory.createUnresolvedDependency(failureComponentSelector, root, true, ComponentSelectionReasons.of(new DefaultComponentSelectionDescriptor(ComponentSelectionCause.CONSTRAINT, Describables.of("Dependency locking"))), - new ModuleVersionResolveException(failureComponentSelector, "Dependency lock state out of date", failure.getProblem()))); + new ModuleVersionResolveException(failureComponentSelector, () -> "Dependency lock state out of date", failure.getProblem()))); } } diff --git a/subprojects/dependency-management/src/main/java/org/gradle/internal/resolve/ModuleVersionNotFoundException.java b/subprojects/dependency-management/src/main/java/org/gradle/internal/resolve/ModuleVersionNotFoundException.java index 6b000093cbd55..e09ebb466eae6 100755 --- a/subprojects/dependency-management/src/main/java/org/gradle/internal/resolve/ModuleVersionNotFoundException.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/internal/resolve/ModuleVersionNotFoundException.java @@ -19,6 +19,7 @@ import org.gradle.api.artifacts.ModuleVersionIdentifier; import org.gradle.api.artifacts.component.ComponentSelector; import org.gradle.api.artifacts.component.ModuleComponentSelector; +import org.gradle.internal.Factory; import org.gradle.internal.logging.text.TreeFormatter; import java.util.Collection; @@ -29,7 +30,7 @@ public class ModuleVersionNotFoundException extends ModuleVersionResolveExceptio * This is used by {@link ModuleVersionResolveException#withIncomingPaths(java.util.Collection)}. */ @SuppressWarnings("UnusedDeclaration") - public ModuleVersionNotFoundException(ComponentSelector selector, String message) { + public ModuleVersionNotFoundException(ComponentSelector selector, Factory message) { super(selector, message); } @@ -45,32 +46,34 @@ public ModuleVersionNotFoundException(ModuleComponentSelector selector, Collecti super(selector, format(selector, attemptedLocations)); } - private static String format(ModuleComponentSelector selector, Collection locations, Collection unmatchedVersions, Collection rejectedVersions) { - TreeFormatter builder = new TreeFormatter(); - if (unmatchedVersions.isEmpty() && rejectedVersions.isEmpty()) { - builder.node(String.format("Could not find any matches for %s as no versions of %s:%s are available.", selector, selector.getGroup(), selector.getModule())); - } else { - builder.node(String.format("Could not find any version that matches %s.", selector)); - if (!unmatchedVersions.isEmpty()) { - builder.node("Versions that do not match"); - appendSizeLimited(builder, unmatchedVersions); - } - if (!rejectedVersions.isEmpty()) { - Collection byRule = Lists.newArrayListWithExpectedSize(rejectedVersions.size()); - Collection byAttributes = Lists.newArrayListWithExpectedSize(rejectedVersions.size()); - mapRejections(rejectedVersions, byRule, byAttributes); - if (!byRule.isEmpty()) { - builder.node("Versions rejected by component selection rules"); - appendSizeLimited(builder, byRule); + private static Factory format(ModuleComponentSelector selector, Collection locations, Collection unmatchedVersions, Collection rejectedVersions) { + return () -> { + TreeFormatter builder = new TreeFormatter(); + if (unmatchedVersions.isEmpty() && rejectedVersions.isEmpty()) { + builder.node(String.format("Could not find any matches for %s as no versions of %s:%s are available.", selector, selector.getGroup(), selector.getModule())); + } else { + builder.node(String.format("Could not find any version that matches %s.", selector)); + if (!unmatchedVersions.isEmpty()) { + builder.node("Versions that do not match"); + appendSizeLimited(builder, unmatchedVersions); } - if (!byAttributes.isEmpty()) { - builder.node("Versions rejected by attribute matching"); - appendSizeLimited(builder, byAttributes); + if (!rejectedVersions.isEmpty()) { + Collection byRule = Lists.newArrayListWithExpectedSize(rejectedVersions.size()); + Collection byAttributes = Lists.newArrayListWithExpectedSize(rejectedVersions.size()); + mapRejections(rejectedVersions, byRule, byAttributes); + if (!byRule.isEmpty()) { + builder.node("Versions rejected by component selection rules"); + appendSizeLimited(builder, byRule); + } + if (!byAttributes.isEmpty()) { + builder.node("Versions rejected by attribute matching"); + appendSizeLimited(builder, byAttributes); + } } } - } - addLocations(builder, locations); - return builder.toString(); + addLocations(builder, locations); + return builder.toString(); + }; } private static void mapRejections(Collection in, Collection outByRule, Collection outByAttributes) { @@ -83,18 +86,22 @@ private static void mapRejections(Collection in, Collection locations) { - TreeFormatter builder = new TreeFormatter(); - builder.node(String.format("Could not find %s.", id)); - addLocations(builder, locations); - return builder.toString(); + private static Factory format(ModuleVersionIdentifier id, Collection locations) { + return () -> { + TreeFormatter builder = new TreeFormatter(); + builder.node(String.format("Could not find %s.", id)); + addLocations(builder, locations); + return builder.toString(); + }; } - private static String format(ModuleComponentSelector selector, Collection locations) { - TreeFormatter builder = new TreeFormatter(); - builder.node(String.format("Could not find any version that matches %s.", selector)); - addLocations(builder, locations); - return builder.toString(); + private static Factory format(ModuleComponentSelector selector, Collection locations) { + return () -> { + TreeFormatter builder = new TreeFormatter(); + builder.node(String.format("Could not find any version that matches %s.", selector)); + addLocations(builder, locations); + return builder.toString(); + }; } private static void appendSizeLimited(TreeFormatter builder, Collection values) { diff --git a/subprojects/dependency-management/src/main/java/org/gradle/internal/resolve/ModuleVersionResolveException.java b/subprojects/dependency-management/src/main/java/org/gradle/internal/resolve/ModuleVersionResolveException.java index 73182e5c4c0a2..4836904f341d5 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/internal/resolve/ModuleVersionResolveException.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/internal/resolve/ModuleVersionResolveException.java @@ -22,10 +22,11 @@ import org.gradle.api.artifacts.component.ModuleComponentIdentifier; import org.gradle.api.internal.artifacts.DefaultModuleIdentifier; import org.gradle.api.internal.artifacts.dependencies.DefaultImmutableVersionConstraint; +import org.gradle.internal.Factory; import org.gradle.internal.UncheckedException; import org.gradle.internal.component.external.model.DefaultModuleComponentSelector; import org.gradle.internal.exceptions.Contextual; -import org.gradle.internal.exceptions.DefaultMultiCauseException; +import org.gradle.internal.exceptions.DefaultMultiCauseExceptionNoStackTrace; import java.util.ArrayList; import java.util.Arrays; @@ -34,16 +35,16 @@ import java.util.List; @Contextual -public class ModuleVersionResolveException extends DefaultMultiCauseException { +public class ModuleVersionResolveException extends DefaultMultiCauseExceptionNoStackTrace { private final List> paths = new ArrayList>(); private final ComponentSelector selector; - public ModuleVersionResolveException(ComponentSelector selector, String message, Throwable cause) { + public ModuleVersionResolveException(ComponentSelector selector, Factory message, Throwable cause) { super(message, cause); this.selector = selector; } - public ModuleVersionResolveException(ComponentSelector selector, String message) { + public ModuleVersionResolveException(ComponentSelector selector, Factory message) { super(message); this.selector = selector; } @@ -58,15 +59,15 @@ public ModuleVersionResolveException(ComponentSelector selector, Iterable message) { this(DefaultModuleComponentSelector.newSelector(selector), message); } - public ModuleVersionResolveException(ModuleVersionIdentifier id, String message) { + public ModuleVersionResolveException(ModuleVersionIdentifier id, Factory message) { this(DefaultModuleComponentSelector.newSelector(id.getModule(), DefaultImmutableVersionConstraint.of(id.getVersion())), message); } - public ModuleVersionResolveException(ModuleComponentIdentifier id, String messageFormat) { + public ModuleVersionResolveException(ModuleComponentIdentifier id, Factory messageFormat) { this(DefaultModuleComponentSelector.newSelector(DefaultModuleIdentifier.newId(id.getGroup(), id.getModule()), DefaultImmutableVersionConstraint.of(id.getVersion())), messageFormat); } @@ -93,8 +94,8 @@ public ComponentSelector getSelector() { return selector; } - protected static String format(String messageFormat, ComponentSelector selector) { - return String.format(messageFormat, selector.getDisplayName()); + protected static Factory format(String messageFormat, ComponentSelector selector) { + return () -> String.format(messageFormat, selector.getDisplayName()); } /** @@ -130,10 +131,15 @@ private String toString(ComponentIdentifier identifier) { protected ModuleVersionResolveException createCopy() { try { - return getClass().getConstructor(ComponentSelector.class, String.class).newInstance(selector, getMessage()); + String message = getMessage(); + return getClass().getConstructor(ComponentSelector.class, Factory.class).newInstance(selector, new Factory() { + @Override + public String create() { + return message; + } + }); } catch (Exception e) { throw UncheckedException.throwAsUncheckedException(e); } } - } diff --git a/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/ResolverProviderComponentMetaDataResolverTest.groovy b/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/ResolverProviderComponentMetaDataResolverTest.groovy index 1442572dade65..8096b23a678be 100644 --- a/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/ResolverProviderComponentMetaDataResolverTest.groovy +++ b/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/ResolverProviderComponentMetaDataResolverTest.groovy @@ -31,6 +31,7 @@ import org.gradle.internal.resolve.result.BuildableComponentResolveResult import spock.lang.Specification class ResolverProviderComponentMetaDataResolverTest extends Specification { + final org.gradle.internal.Factory broken = { "broken" } final metaData = metaData("1.2") final moduleComponentId = DefaultModuleComponentIdentifier.newId(DefaultModuleIdentifier.newId("group", "project"), "1.0") final componentRequestMetaData = Mock(ComponentOverrideMetadata) @@ -445,7 +446,7 @@ class ResolverProviderComponentMetaDataResolverTest extends Specification { then: 1 * localAccess.resolveComponentMetaData(moduleComponentId, componentRequestMetaData, _) >> { id, meta, result -> - result.failed(new ModuleVersionResolveException(id, "broken")) + result.failed(new ModuleVersionResolveException(id, broken)) } 1 * localAccess2.resolveComponentMetaData(moduleComponentId, componentRequestMetaData, _) >> { id, meta, result -> result.resolved(metaData) @@ -478,7 +479,7 @@ class ResolverProviderComponentMetaDataResolverTest extends Specification { then: 1 * localAccess.resolveComponentMetaData(moduleComponentId, componentRequestMetaData, _) 1 * remoteAccess.resolveComponentMetaData(moduleComponentId, componentRequestMetaData, _) >> { id, meta, result -> - result.failed(new ModuleVersionResolveException(id, "broken")) + result.failed(new ModuleVersionResolveException(id, broken)) } 1 * localAccess2.resolveComponentMetaData(moduleComponentId, componentRequestMetaData, _) 1 * remoteAccess2.resolveComponentMetaData(moduleComponentId, componentRequestMetaData, _) >> { id, meta, result -> @@ -503,7 +504,7 @@ class ResolverProviderComponentMetaDataResolverTest extends Specification { def "rethrows failure to resolve local dependency when not available in any repository"() { given: - def failure = new ModuleVersionResolveException(Stub(ModuleVersionSelector), "broken") + def failure = new ModuleVersionResolveException(Stub(ModuleVersionSelector), broken) def repo1 = addRepo1() def repo2 = addRepo2() @@ -530,7 +531,7 @@ class ResolverProviderComponentMetaDataResolverTest extends Specification { def "rethrows failure to resolve remote dependency when not available in any repository"() { given: - def failure = new ModuleVersionResolveException(Stub(ModuleVersionSelector), "broken") + def failure = new ModuleVersionResolveException(Stub(ModuleVersionSelector), broken) def repo1 = addRepo1() def repo2 = addRepo2() diff --git a/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/DependencyGraphBuilderTest.groovy b/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/DependencyGraphBuilderTest.groovy index 89def6245adb6..e21f954881879 100644 --- a/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/DependencyGraphBuilderTest.groovy +++ b/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/DependencyGraphBuilderTest.groovy @@ -1069,7 +1069,8 @@ class DependencyGraphBuilderTest extends Specification { def dependencyMetaData = dependsOn(args, from, to.moduleVersionId) selectorResolvesTo(dependencyMetaData, to.id, to.moduleVersionId) 1 * metaDataResolver.resolve(to.id, _, _) >> { ComponentIdentifier id, ComponentOverrideMetadata requestMetaData, BuildableComponentResolveResult result -> - result.failed(new ModuleVersionResolveException(newSelector(DefaultModuleIdentifier.newId("a", "b"), new DefaultMutableVersionConstraint("c")), "broken")) + org.gradle.internal.Factory broken = { "broken" } + result.failed(new ModuleVersionResolveException(newSelector(DefaultModuleIdentifier.newId("a", "b"), new DefaultMutableVersionConstraint("c")), broken)) } } @@ -1084,7 +1085,8 @@ class DependencyGraphBuilderTest extends Specification { def brokenSelector(Map args = [:], def from, String to) { def dependencyMetaData = dependsOn(args, from, newId("group", to, "1.0")) 1 * idResolver.resolve(dependencyMetaData, _, _, _) >> { DependencyMetadata dep, VersionSelector acceptor, VersionSelector rejector, BuildableComponentIdResolveResult result -> - result.failed(new ModuleVersionResolveException(newSelector(DefaultModuleIdentifier.newId("a", "b"), new DefaultMutableVersionConstraint("c")), "broken")) + org.gradle.internal.Factory broken = { "broken" } + result.failed(new ModuleVersionResolveException(newSelector(DefaultModuleIdentifier.newId("a", "b"), new DefaultMutableVersionConstraint("c")), broken)) } } diff --git a/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/result/CachingDependencyResultFactoryTest.groovy b/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/result/CachingDependencyResultFactoryTest.groovy index ff8ff1afc5a34..a2b8057391209 100644 --- a/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/result/CachingDependencyResultFactoryTest.groovy +++ b/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/result/CachingDependencyResultFactoryTest.groovy @@ -74,15 +74,16 @@ class CachingDependencyResultFactoryTest extends Specification { def "creates and caches unresolved dependencies"() { def fromModule = newModule('from') def selectedModule = Mock(ComponentSelectionReason) + org.gradle.internal.Factory broken = { " foo" } when: - def dep = factory.createUnresolvedDependency(selector('requested'), fromModule, false, selectedModule, new ModuleVersionResolveException(moduleVersionSelector('requested'), "foo")) - def same = factory.createUnresolvedDependency(selector('requested'), fromModule, false, selectedModule, new ModuleVersionResolveException(moduleVersionSelector('requested'), "foo")) + def dep = factory.createUnresolvedDependency(selector('requested'), fromModule, false, selectedModule, new ModuleVersionResolveException(moduleVersionSelector('requested'), broken)) + def same = factory.createUnresolvedDependency(selector('requested'), fromModule, false, selectedModule, new ModuleVersionResolveException(moduleVersionSelector('requested'), broken)) - def differentRequested = factory.createUnresolvedDependency(selector('xxx'), fromModule, false, selectedModule, new ModuleVersionResolveException(moduleVersionSelector('xxx'), "foo")) - def differentFrom = factory.createUnresolvedDependency(selector('requested'), newModule('xxx'), false, selectedModule, new ModuleVersionResolveException(moduleVersionSelector('requested'), "foo")) - def differentConstraint = factory.createUnresolvedDependency(selector('requested'), fromModule, true, selectedModule, new ModuleVersionResolveException(moduleVersionSelector('requested'), "foo")) - def differentFailure = factory.createUnresolvedDependency(selector('requested'), fromModule, false, selectedModule, new ModuleVersionResolveException(moduleVersionSelector('requested'), "foo")) + def differentRequested = factory.createUnresolvedDependency(selector('xxx'), fromModule, false, selectedModule, new ModuleVersionResolveException(moduleVersionSelector('xxx'), broken)) + def differentFrom = factory.createUnresolvedDependency(selector('requested'), newModule('xxx'), false, selectedModule, new ModuleVersionResolveException(moduleVersionSelector('requested'), broken)) + def differentConstraint = factory.createUnresolvedDependency(selector('requested'), fromModule, true, selectedModule, new ModuleVersionResolveException(moduleVersionSelector('requested'), broken)) + def differentFailure = factory.createUnresolvedDependency(selector('requested'), fromModule, false, selectedModule, new ModuleVersionResolveException(moduleVersionSelector('requested'), broken)) then: dep.is(same) diff --git a/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/result/DefaultResolutionResultTest.groovy b/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/result/DefaultResolutionResultTest.groovy index 5c1a7893f3ae3..a141ee8da1455 100644 --- a/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/result/DefaultResolutionResultTest.groovy +++ b/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/result/DefaultResolutionResultTest.groovy @@ -132,11 +132,12 @@ class DefaultResolutionResultTest extends Specification { 'test project' ) def mid = DefaultModuleVersionIdentifier.newId("foo", "bar", "1.0") + org.gradle.internal.Factory broken = { "too bad" } def dep = new DefaultUnresolvedDependencyResult( Stub(ComponentSelector), false, Stub(ComponentSelectionReason), new DefaultResolvedComponentResult(mid, Stub(ComponentSelectionReason), projectId, [Stub(ResolvedVariantResult)], null), - new ModuleVersionNotFoundException(Stub(ModuleComponentSelector), "too bad") + new ModuleVersionNotFoundException(Stub(ModuleComponentSelector), broken) ) def edge = new UnresolvedDependencyEdge(dep) diff --git a/subprojects/dependency-management/src/test/groovy/org/gradle/internal/resolve/result/DefaultBuildableComponentIdResolveResultTest.groovy b/subprojects/dependency-management/src/test/groovy/org/gradle/internal/resolve/result/DefaultBuildableComponentIdResolveResultTest.groovy index c6e76d89944e4..56bd149a91d1c 100644 --- a/subprojects/dependency-management/src/test/groovy/org/gradle/internal/resolve/result/DefaultBuildableComponentIdResolveResultTest.groovy +++ b/subprojects/dependency-management/src/test/groovy/org/gradle/internal/resolve/result/DefaultBuildableComponentIdResolveResultTest.groovy @@ -61,7 +61,8 @@ class DefaultBuildableComponentIdResolveResultTest extends Specification { } def "can mark as failed"() { - def failure = new ModuleVersionResolveException(Stub(ModuleVersionSelector), "broken") + org.gradle.internal.Factory broken = { "too bad" } + def failure = new ModuleVersionResolveException(Stub(ModuleVersionSelector), broken) when: result.failed(failure) diff --git a/subprojects/dependency-management/src/test/groovy/org/gradle/internal/resolve/result/DefaultBuildableComponentResolveResultTest.groovy b/subprojects/dependency-management/src/test/groovy/org/gradle/internal/resolve/result/DefaultBuildableComponentResolveResultTest.groovy index 354572be7d14d..525e421bb7809 100644 --- a/subprojects/dependency-management/src/test/groovy/org/gradle/internal/resolve/result/DefaultBuildableComponentResolveResultTest.groovy +++ b/subprojects/dependency-management/src/test/groovy/org/gradle/internal/resolve/result/DefaultBuildableComponentResolveResultTest.groovy @@ -73,7 +73,8 @@ class DefaultBuildableComponentResolveResultTest extends Specification { } def "cannot get id when resolve failed"() { - def failure = new ModuleVersionResolveException(newSelector(DefaultModuleIdentifier.newId("a", "b"), "c"), "broken") + org.gradle.internal.Factory broken = { "too bad" } + def failure = new ModuleVersionResolveException(newSelector(DefaultModuleIdentifier.newId("a", "b"), "c"), broken) when: result.failed(failure) @@ -85,7 +86,8 @@ class DefaultBuildableComponentResolveResultTest extends Specification { } def "cannot get meta-data when resolve failed"() { - def failure = new ModuleVersionResolveException(newSelector(DefaultModuleIdentifier.newId("a", "b"), "c"), "broken") + org.gradle.internal.Factory broken = { "too bad" } + def failure = new ModuleVersionResolveException(newSelector(DefaultModuleIdentifier.newId("a", "b"), "c"), broken) when: result.failed(failure) @@ -137,8 +139,9 @@ class DefaultBuildableComponentResolveResultTest extends Specification { } def "copies failure result to an id resolve result"() { + org.gradle.internal.Factory broken = { "too bad" } def idResult = Mock(BuildableComponentIdResolveResult) - def failure = new ModuleVersionResolveException(Stub(ModuleVersionSelector), "broken") + def failure = new ModuleVersionResolveException(Stub(ModuleVersionSelector), broken) given: result.attempted("a") diff --git a/subprojects/dependency-management/src/test/groovy/org/gradle/internal/resolve/result/DefaultBuildableModuleComponentMetaDataResolveResultTest.groovy b/subprojects/dependency-management/src/test/groovy/org/gradle/internal/resolve/result/DefaultBuildableModuleComponentMetaDataResolveResultTest.groovy index 751c19ecd66e3..eec02f9f65fd2 100644 --- a/subprojects/dependency-management/src/test/groovy/org/gradle/internal/resolve/result/DefaultBuildableModuleComponentMetaDataResolveResultTest.groovy +++ b/subprojects/dependency-management/src/test/groovy/org/gradle/internal/resolve/result/DefaultBuildableModuleComponentMetaDataResolveResultTest.groovy @@ -44,7 +44,8 @@ class DefaultBuildableModuleComponentMetaDataResolveResultTest extends Specifica } def "can mark as failed"() { - def failure = new ModuleVersionResolveException(newSelector(DefaultModuleIdentifier.newId("a", "b"), "c"), "broken") + org.gradle.internal.Factory broken = { "too bad" } + def failure = new ModuleVersionResolveException(newSelector(DefaultModuleIdentifier.newId("a", "b"), "c"), broken) when: descriptor.failed(failure) @@ -112,8 +113,9 @@ class DefaultBuildableModuleComponentMetaDataResolveResultTest extends Specifica } def "cannot get meta-data when failed"() { + org.gradle.internal.Factory broken = { "too bad" } given: - def failure = new ModuleVersionResolveException(newSelector(DefaultModuleIdentifier.newId("a", "b"), "c"), "broken") + def failure = new ModuleVersionResolveException(newSelector(DefaultModuleIdentifier.newId("a", "b"), "c"), broken) descriptor.failed(failure) when: diff --git a/subprojects/dependency-management/src/test/groovy/org/gradle/internal/resolve/result/DefaultBuildableModuleVersionListingResolveResultTest.groovy b/subprojects/dependency-management/src/test/groovy/org/gradle/internal/resolve/result/DefaultBuildableModuleVersionListingResolveResultTest.groovy index 6bf5eda266e05..196e9d0389746 100644 --- a/subprojects/dependency-management/src/test/groovy/org/gradle/internal/resolve/result/DefaultBuildableModuleVersionListingResolveResultTest.groovy +++ b/subprojects/dependency-management/src/test/groovy/org/gradle/internal/resolve/result/DefaultBuildableModuleVersionListingResolveResultTest.groovy @@ -45,7 +45,8 @@ class DefaultBuildableModuleVersionListingResolveResultTest extends Specificatio } def "can mark as failed"() { - def failure = new ModuleVersionResolveException(newSelector(DefaultModuleIdentifier.newId("a", "b"), "c"), "broken") + org.gradle.internal.Factory broken = { "too bad" } + def failure = new ModuleVersionResolveException(newSelector(DefaultModuleIdentifier.newId("a", "b"), "c"), broken) when: descriptor.failed(failure) diff --git a/subprojects/dependency-management/src/testFixtures/groovy/org/gradle/api/internal/artifacts/result/ResolutionResultDataBuilder.groovy b/subprojects/dependency-management/src/testFixtures/groovy/org/gradle/api/internal/artifacts/result/ResolutionResultDataBuilder.groovy index 5ac6e1e476aad..64f740531eb97 100644 --- a/subprojects/dependency-management/src/testFixtures/groovy/org/gradle/api/internal/artifacts/result/ResolutionResultDataBuilder.groovy +++ b/subprojects/dependency-management/src/testFixtures/groovy/org/gradle/api/internal/artifacts/result/ResolutionResultDataBuilder.groovy @@ -40,7 +40,8 @@ class ResolutionResultDataBuilder { static DefaultUnresolvedDependencyResult newUnresolvedDependency(String group='x', String module='x', String version='1', String selectedVersion='1') { def requested = newSelector(group, module, version) - new DefaultUnresolvedDependencyResult(requested, false, ComponentSelectionReasons.requested(), newModule(group, module, selectedVersion), new ModuleVersionResolveException(newSelector(DefaultModuleIdentifier.newId(group, module), version), "broken")) + org.gradle.internal.Factory broken = { "broken" } + new DefaultUnresolvedDependencyResult(requested, false, ComponentSelectionReasons.requested(), newModule(group, module, selectedVersion), new ModuleVersionResolveException(newSelector(DefaultModuleIdentifier.newId(group, module), version), broken)) } static DefaultResolvedComponentResult newModule(String group='a', String module='a', String version='1', ComponentSelectionReason selectionReason = ComponentSelectionReasons.requested(), ResolvedVariantResult variant = newVariant(), String repoId = null) { diff --git a/subprojects/platform-base/src/main/java/org/gradle/api/internal/resolve/LocalLibraryDependencyResolver.java b/subprojects/platform-base/src/main/java/org/gradle/api/internal/resolve/LocalLibraryDependencyResolver.java index 8eb86342ec118..001af7d81153b 100644 --- a/subprojects/platform-base/src/main/java/org/gradle/api/internal/resolve/LocalLibraryDependencyResolver.java +++ b/subprojects/platform-base/src/main/java/org/gradle/api/internal/resolve/LocalLibraryDependencyResolver.java @@ -30,6 +30,7 @@ import org.gradle.api.internal.artifacts.type.ArtifactTypeRegistry; import org.gradle.api.internal.attributes.ImmutableAttributes; import org.gradle.api.internal.component.ArtifactType; +import org.gradle.internal.Factory; import org.gradle.internal.component.external.model.MetadataSourcedComponentArtifacts; import org.gradle.internal.component.local.model.LocalComponentMetadata; import org.gradle.internal.component.local.model.PublishArtifactLocalArtifactMetadata; @@ -135,13 +136,25 @@ private void resolveLibraryAndChooseBinary(BuildableComponentIdResolveResult res return; } - Collection matchingVariants = chooseMatchingVariants(selectedLibrary, variant); + final Collection matchingVariants = chooseMatchingVariants(selectedLibrary, variant); if (matchingVariants.isEmpty()) { // no compatible variant found - Iterable values = selectedLibrary.getVariants(); - result.failed(new ModuleVersionResolveException(selector, errorMessageBuilder.noCompatibleVariantErrorMessage(libraryName, values))); + final Iterable values = selectedLibrary.getVariants(); + result.failed(new ModuleVersionResolveException(selector, new Factory() { + @Nullable + @Override + public String create() { + return errorMessageBuilder.noCompatibleVariantErrorMessage(libraryName, values); + } + })); } else if (matchingVariants.size() > 1) { - result.failed(new ModuleVersionResolveException(selector, errorMessageBuilder.multipleCompatibleVariantsErrorMessage(libraryName, matchingVariants))); + result.failed(new ModuleVersionResolveException(selector, new Factory() { + @Nullable + @Override + public String create() { + return errorMessageBuilder.multipleCompatibleVariantsErrorMessage(libraryName, matchingVariants); + } + })); } else { Binary selectedBinary = matchingVariants.iterator().next(); // TODO:Cedric This is not quite right. We assume that if we are asking for a specific binary, then we resolve to the assembly instead diff --git a/subprojects/version-control/src/main/java/org/gradle/vcs/internal/resolver/OfflineVcsVersionWorkingDirResolver.java b/subprojects/version-control/src/main/java/org/gradle/vcs/internal/resolver/OfflineVcsVersionWorkingDirResolver.java index 00df1d8e2618b..b9c8842591d1f 100644 --- a/subprojects/version-control/src/main/java/org/gradle/vcs/internal/resolver/OfflineVcsVersionWorkingDirResolver.java +++ b/subprojects/version-control/src/main/java/org/gradle/vcs/internal/resolver/OfflineVcsVersionWorkingDirResolver.java @@ -36,7 +36,7 @@ public OfflineVcsVersionWorkingDirResolver(PersistentVcsMetadataCache persistent public File selectVersion(ModuleComponentSelector selector, VersionControlRepositoryConnection repository) { VersionRef previousVersion = persistentCache.getVersionForSelector(repository, selector.getVersionConstraint()); if (previousVersion == null) { - throw new ModuleVersionResolveException(selector, String.format("Cannot resolve %s from %s in offline mode.", selector.getDisplayName(), repository.getDisplayName())); + throw new ModuleVersionResolveException(selector, () -> String.format("Cannot resolve %s from %s in offline mode.", selector.getDisplayName(), repository.getDisplayName())); } // Reuse the same version as last build diff --git a/subprojects/version-control/src/main/java/org/gradle/vcs/internal/resolver/VcsDependencyResolver.java b/subprojects/version-control/src/main/java/org/gradle/vcs/internal/resolver/VcsDependencyResolver.java index a9ec2b8e9ddd9..b1c8f446b86eb 100644 --- a/subprojects/version-control/src/main/java/org/gradle/vcs/internal/resolver/VcsDependencyResolver.java +++ b/subprojects/version-control/src/main/java/org/gradle/vcs/internal/resolver/VcsDependencyResolver.java @@ -119,7 +119,7 @@ public boolean isSatisfiedBy(Pair spec.getDisplayName() + " did not contain a project publishing the specified dependency.")); } else { LocalComponentMetadata componentMetaData = localComponentRegistry.getComponent(entry.right); result.resolved(componentMetaData); From 2a2f035909833ff7776e9037d293e79d9cc63764 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=B3r=C3=A1nt=20Pint=C3=A9r?= Date: Fri, 15 Mar 2019 11:25:09 +0100 Subject: [PATCH 567/853] Address review comments --- ...ldCacheConfigurationIntegrationTest.groovy | 2 +- ...CacheBuildOperationsIntegrationTest.groovy | 17 +++++------------ .../DefaultBuildCacheConfiguration.java | 5 +---- .../configuration/internal/package-info.java | 19 +++++++++++++++++++ .../docs/userguide/upgrading_version_5.adoc | 9 +++++++++ 5 files changed, 35 insertions(+), 17 deletions(-) create mode 100644 subprojects/build-cache/src/main/java/org/gradle/caching/configuration/internal/package-info.java diff --git a/subprojects/build-cache/src/integTest/groovy/org/gradle/caching/configuration/BuildCacheConfigurationIntegrationTest.groovy b/subprojects/build-cache/src/integTest/groovy/org/gradle/caching/configuration/BuildCacheConfigurationIntegrationTest.groovy index 4a98053312954..7a3204b110227 100644 --- a/subprojects/build-cache/src/integTest/groovy/org/gradle/caching/configuration/BuildCacheConfigurationIntegrationTest.groovy +++ b/subprojects/build-cache/src/integTest/groovy/org/gradle/caching/configuration/BuildCacheConfigurationIntegrationTest.groovy @@ -297,7 +297,7 @@ class BuildCacheConfigurationIntegrationTest extends AbstractIntegrationSpec { run "help" then: - output.contains("Using a local cache type other than DirectoryBuildCache has been deprecated. This is scheduled to be removed in Gradle 6.0.") + output.contains("Using a local build cache type other than DirectoryBuildCache has been deprecated. This is scheduled to be removed in Gradle 6.0.") where: customCacheConfig << [ diff --git a/subprojects/build-cache/src/integTest/groovy/org/gradle/caching/internal/BuildCacheBuildOperationsIntegrationTest.groovy b/subprojects/build-cache/src/integTest/groovy/org/gradle/caching/internal/BuildCacheBuildOperationsIntegrationTest.groovy index 4ffe730c2a01a..190a1350adfe6 100644 --- a/subprojects/build-cache/src/integTest/groovy/org/gradle/caching/internal/BuildCacheBuildOperationsIntegrationTest.groovy +++ b/subprojects/build-cache/src/integTest/groovy/org/gradle/caching/internal/BuildCacheBuildOperationsIntegrationTest.groovy @@ -297,18 +297,11 @@ class BuildCacheBuildOperationsIntegrationTest extends AbstractIntegrationSpec { operations.orderedSerialSiblings(remoteMissLoadOp, packOp, remoteStoreOp) where: - config << [ - "remote($remoteCacheClass) { push = true }", - "local.push = false; remote($remoteCacheClass) { push = true }", - "local.enabled = false; remote($remoteCacheClass) { push = true }", - "local($remoteCacheClass) { push = true }; remote($remoteCacheClass) { push = true }; " - ] - localStore << [ - true, false, false, false - ] - expectDeprecation << [ - false, false, false, true - ] + localStore | expectDeprecation | config + true | false | "remote($remoteCacheClass) { push = true }" + false | false | "local.push = false; remote($remoteCacheClass) { push = true }" + false | false | "local.enabled = false; remote($remoteCacheClass) { push = true }" + false | true | "local($remoteCacheClass) { push = true }; remote($remoteCacheClass) { push = true }; " } def "records ops for remote hit"() { diff --git a/subprojects/build-cache/src/main/java/org/gradle/caching/configuration/internal/DefaultBuildCacheConfiguration.java b/subprojects/build-cache/src/main/java/org/gradle/caching/configuration/internal/DefaultBuildCacheConfiguration.java index 12cd0d0e8c71e..74193cd5e23ce 100644 --- a/subprojects/build-cache/src/main/java/org/gradle/caching/configuration/internal/DefaultBuildCacheConfiguration.java +++ b/subprojects/build-cache/src/main/java/org/gradle/caching/configuration/internal/DefaultBuildCacheConfiguration.java @@ -58,16 +58,13 @@ public BuildCache getLocal() { @Override public T local(Class type) { - if (!type.equals(DirectoryBuildCache.class)) { - DeprecationLogger.nagUserOfDeprecated("Using a local cache type other than " + DirectoryBuildCache.class.getSimpleName()); - } return local(type, Actions.doNothing()); } @Override public T local(Class type, Action configuration) { if (!type.equals(DirectoryBuildCache.class)) { - DeprecationLogger.nagUserOfDeprecated("Using a local cache type other than " + DirectoryBuildCache.class.getSimpleName()); + DeprecationLogger.nagUserOfDeprecated("Using a local build cache type other than " + DirectoryBuildCache.class.getSimpleName()); } if (!type.isInstance(local)) { if (local != null) { diff --git a/subprojects/build-cache/src/main/java/org/gradle/caching/configuration/internal/package-info.java b/subprojects/build-cache/src/main/java/org/gradle/caching/configuration/internal/package-info.java new file mode 100644 index 0000000000000..4021cbf1807cc --- /dev/null +++ b/subprojects/build-cache/src/main/java/org/gradle/caching/configuration/internal/package-info.java @@ -0,0 +1,19 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +@NonNullApi +package org.gradle.caching.configuration.internal; + +import org.gradle.api.NonNullApi; diff --git a/subprojects/docs/src/docs/userguide/upgrading_version_5.adoc b/subprojects/docs/src/docs/userguide/upgrading_version_5.adoc index 9844ab6f659ca..3515f79c1703c 100644 --- a/subprojects/docs/src/docs/userguide/upgrading_version_5.adoc +++ b/subprojects/docs/src/docs/userguide/upgrading_version_5.adoc @@ -33,6 +33,15 @@ Some plugins will break with this new version of Gradle, for example because the . Run `gradle wrapper --gradle-version {gradleVersion}` to update the project to {gradleVersion}. . Try to run the project and debug any errors using the <>. +[[changes_5.4]] +== Upgrading from 5.3 and earlier + +=== Deprecated classes, methods and properties + +==== Using custom local build cache implementations + +Using an implementation other than the default `DirectoryBuildCache` for the local build cache is now deprecated. + [[changes_5.3]] == Upgrading from 5.2 and earlier From 79d2e33bf924ffd2b84bdf66b6acf03486dd79ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=B3r=C3=A1nt=20Pint=C3=A9r?= Date: Fri, 15 Mar 2019 12:10:56 +0100 Subject: [PATCH 568/853] Rename method --- .../java/org/gradle/internal/execution/steps/CacheStep.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/CacheStep.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/CacheStep.java index bddac8edf32bf..ff159455c175f 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/CacheStep.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/CacheStep.java @@ -91,7 +91,7 @@ public ImmutableSortedMap getFinalOutp } }; }) - .orElseMapFailure(loadFailure -> executeWithCache(cacheHandler, new IncrementalChangesContext() { + .orElseMapFailure(loadFailure -> executeAndStoreInCache(cacheHandler, new IncrementalChangesContext() { @Override public Optional getChanges() { // Clear change information to avoid incremental execution after failed load @@ -119,7 +119,7 @@ public UnitOfWork getWork() { } })) ) - .orElseGet(() -> executeWithCache(cacheHandler, context)); + .orElseGet(() -> executeAndStoreInCache(cacheHandler, context)); } private Optional> load(UnitOfWork work, BuildCacheKey cacheKey) { @@ -150,7 +150,7 @@ private static void cleanupTreesAfterUnpackFailure(UnitOfWork work) { }); } - private CurrentSnapshotResult executeWithCache(CacheHandler cacheHandler, IncrementalChangesContext context) { + private CurrentSnapshotResult executeAndStoreInCache(CacheHandler cacheHandler, IncrementalChangesContext context) { CurrentSnapshotResult executionResult = executeWithoutCache(context); executionResult.getOutcome().ifSuccessfulOrElse( outcome -> cacheHandler.store(cacheKey -> store(context.getWork(), cacheKey, executionResult)), From 9f8aa6d348f58b360327773b15d320160da4692b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=B3r=C3=A1nt=20Pint=C3=A9r?= Date: Fri, 15 Mar 2019 12:30:59 +0100 Subject: [PATCH 569/853] Handle all load failures as recoverable --- .../execution/ExecuteActionsTaskExecuter.java | 4 +- .../transform/DefaultTransformerInvoker.java | 4 +- .../internal/execution/CacheHandler.java | 2 +- .../internal/execution/steps/CacheStep.java | 43 ++++++++----------- .../execution/steps/CacheStepTest.groovy | 10 ++--- 5 files changed, 28 insertions(+), 35 deletions(-) diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuter.java b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuter.java index 00c6d669a34c2..035e653a08e0c 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuter.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuter.java @@ -252,7 +252,7 @@ public Optional> getChangingOutputs() { public CacheHandler createCacheHandler() { return new CacheHandler() { @Override - public Optional> load(Function>> loader) { + public Try> load(Function>> loader) { // TODO Log this when creating the build cache key perhaps? if (task.isHasCustomActions()) { LOGGER.info("Custom actions are attached to {}.", task); @@ -263,7 +263,7 @@ public Optional> load(Function>> loade ) { return loader.apply(context.getBuildCacheKey()); } else { - return Optional.empty(); + return Try.successful(Optional.empty()); } } diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvoker.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvoker.java index 6f423a35300f8..6a613d7cf92d9 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvoker.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvoker.java @@ -363,9 +363,9 @@ public CacheHandler createCacheHandler() { TransformerExecutionBuildCacheKey cacheKey = new TransformerExecutionBuildCacheKey(hasher.hash()); return new CacheHandler() { @Override - public Optional> load(Function>> loader) { + public Try> load(Function>> loader) { if (!transformer.isCacheable()) { - return Optional.empty(); + return Try.successful(Optional.empty()); } return loader.apply(cacheKey); } diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/CacheHandler.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/CacheHandler.java index 9b4a2bab7c78d..70b06e256c840 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/CacheHandler.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/CacheHandler.java @@ -24,6 +24,6 @@ import java.util.function.Function; public interface CacheHandler { - Optional> load(Function>> loader); + Try> load(Function>> loader); void store(Consumer storer); } diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/CacheStep.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/CacheStep.java index ff159455c175f..464c329da6c9f 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/CacheStep.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/CacheStep.java @@ -62,13 +62,14 @@ public CurrentSnapshotResult execute(IncrementalChangesContext context) { if (!buildCache.isEnabled()) { return executeWithoutCache(context); } - CacheHandler cacheHandler = context.getWork().createCacheHandler(); + UnitOfWork work = context.getWork(); + CacheHandler cacheHandler = work.createCacheHandler(); return cacheHandler - .load(cacheKey -> load(context.getWork(), cacheKey)) - .map(cacheHit -> cacheHit - .map(loadResult -> { - OriginMetadata originMetadata = loadResult.getOriginMetadata(); - ImmutableSortedMap finalOutputs = loadResult.getResultingSnapshots(); + .load(cacheKey -> Try.ofFailable(() -> buildCache.load(commandFactory.createLoad(cacheKey, work)))) + .map(successfulLoad -> successfulLoad + .map(cacheHit -> { + OriginMetadata originMetadata = cacheHit.getOriginMetadata(); + ImmutableSortedMap finalOutputs = cacheHit.getResultingSnapshots(); return (CurrentSnapshotResult) new CurrentSnapshotResult() { @Override public Try getOutcome() { @@ -91,7 +92,14 @@ public ImmutableSortedMap getFinalOutp } }; }) - .orElseMapFailure(loadFailure -> executeAndStoreInCache(cacheHandler, new IncrementalChangesContext() { + .orElseGet(() -> executeAndStoreInCache(cacheHandler, context)) + ) + .orElseMapFailure(loadFailure -> { + LOGGER.warn("Failed to load cache entry for {}, cleaning outputs and falling back to (non-incremental) execution", + work.getDisplayName(), loadFailure); + cleanupTreesAfterLoadFailure(work); + + return executeAndStoreInCache(cacheHandler, new IncrementalChangesContext() { @Override public Optional getChanges() { // Clear change information to avoid incremental execution after failed load @@ -115,26 +123,13 @@ public Optional getBeforeExecutionState() { @Override public UnitOfWork getWork() { - return context.getWork(); + return work; } - })) - ) - .orElseGet(() -> executeAndStoreInCache(cacheHandler, context)); - } - - private Optional> load(UnitOfWork work, BuildCacheKey cacheKey) { - try { - return buildCache.load(commandFactory.createLoad(cacheKey, work)) - .map(loadResult -> Try.successful(loadResult)); - } catch (Exception e) { - // There was a failure during downloading, previous task outputs should be unaffected - LOGGER.warn("Failed to load cache entry for {}, cleaning outputs and falling back to (non-incremental) execution", work.getDisplayName(), e); - cleanupTreesAfterUnpackFailure(work); - return Optional.of(Try.failure(e)); - } + }); + }); } - private static void cleanupTreesAfterUnpackFailure(UnitOfWork work) { + private static void cleanupTreesAfterLoadFailure(UnitOfWork work) { work.visitOutputTrees((name, type, root) -> { try { if (root.exists()) { diff --git a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/CacheStepTest.groovy b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/CacheStepTest.groovy index 58ca522d185bf..e2a1317a42f31 100644 --- a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/CacheStepTest.groovy +++ b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/CacheStepTest.groovy @@ -70,7 +70,6 @@ class CacheStepTest extends StepSpec implements FingerprinterFixture { } then: - 1 * context.work >> work 1 * buildCacheCommandFactory.createLoad(cacheKey, work) >> loadCommand 1 * buildCacheController.load(loadCommand) >> Optional.of(loadMetadata) @@ -94,7 +93,7 @@ class CacheStepTest extends StepSpec implements FingerprinterFixture { 1 * buildCacheController.enabled >> true 1 * context.work >> work 1 * work.createCacheHandler() >> cacheHandler - 1 * cacheHandler.load(_) >> Optional.empty() + 1 * cacheHandler.load(_) >> Try.successful(Optional.empty()) then: 1 * delegate.execute(context) >> delegateResult @@ -127,12 +126,11 @@ class CacheStepTest extends StepSpec implements FingerprinterFixture { 1 * buildCacheController.enabled >> true 1 * context.work >> work 1 * work.createCacheHandler() >> cacheHandler - 1 * cacheHandler.load(_) >> { Function>> loader -> + 1 * cacheHandler.load(_) >> { Function>> loader -> loader.apply(cacheKey) } then: - 1 * context.work >> work 1 * buildCacheCommandFactory.createLoad(cacheKey, work) >> loadCommand 1 * buildCacheController.load(loadCommand) >> { loadedOutputFile << "output" @@ -195,7 +193,7 @@ class CacheStepTest extends StepSpec implements FingerprinterFixture { 1 * buildCacheController.enabled >> true 1 * context.work >> work 1 * work.createCacheHandler() >> cacheHandler - 1 * cacheHandler.load(_) >> Optional.empty() + 1 * cacheHandler.load(_) >> Try.successful(Optional.empty()) then: 1 * delegate.execute(context) >> delegateResult @@ -222,7 +220,7 @@ class CacheStepTest extends StepSpec implements FingerprinterFixture { 1 * buildCacheController.enabled >> true 1 * context.work >> work 1 * work.createCacheHandler() >> cacheHandler - 1 * cacheHandler.load(_) >> Optional.empty() + 1 * cacheHandler.load(_) >> Try.successful(Optional.empty()) then: 1 * delegate.execute(context) >> delegateResult From 5cc7b1a2db3f1780382b5d3bf84064f3e248fb67 Mon Sep 17 00:00:00 2001 From: "Rodrigo B. de Oliveira" Date: Fri, 15 Mar 2019 09:34:52 -0300 Subject: [PATCH 570/853] Simplify sentence in documentation comment --- .../kotlin/dsl/support/delegates/ArtifactHandlerDelegate.kt | 2 +- .../gradle/kotlin/dsl/support/delegates/ClientModuleDelegate.kt | 2 +- .../support/delegates/DependencyConstraintHandlerDelegate.kt | 2 +- .../kotlin/dsl/support/delegates/DependencyHandlerDelegate.kt | 2 +- .../dsl/support/delegates/NamedDomainObjectContainerDelegate.kt | 2 +- .../org/gradle/kotlin/dsl/support/delegates/ProjectDelegate.kt | 2 +- .../kotlin/dsl/support/delegates/ScriptHandlerDelegate.kt | 2 +- .../org/gradle/kotlin/dsl/support/delegates/SettingsDelegate.kt | 2 +- .../kotlin/dsl/support/delegates/TaskContainerDelegate.kt | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/delegates/ArtifactHandlerDelegate.kt b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/delegates/ArtifactHandlerDelegate.kt index 58deb1c99c244..d1de924fc126f 100644 --- a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/delegates/ArtifactHandlerDelegate.kt +++ b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/delegates/ArtifactHandlerDelegate.kt @@ -27,7 +27,7 @@ import org.gradle.api.artifacts.dsl.ArtifactHandler /** * Facilitates the implementation of the [ArtifactHandler] interface by delegation via subclassing. * - * See [GradleDelegate] for details why this is currently necessary. + * See [GradleDelegate] for why this is currently necessary. */ abstract class ArtifactHandlerDelegate : ArtifactHandler { diff --git a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/delegates/ClientModuleDelegate.kt b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/delegates/ClientModuleDelegate.kt index 869af40b6b89a..847fbd4119c3c 100644 --- a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/delegates/ClientModuleDelegate.kt +++ b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/delegates/ClientModuleDelegate.kt @@ -39,7 +39,7 @@ import org.gradle.api.capabilities.Capability /** * Facilitates the implementation of the [ClientModule] interface by delegation via subclassing. * - * See [GradleDelegate] for details why this is currently necessary. + * See [GradleDelegate] for why this is currently necessary. */ abstract class ClientModuleDelegate : ClientModule { diff --git a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/delegates/DependencyConstraintHandlerDelegate.kt b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/delegates/DependencyConstraintHandlerDelegate.kt index 6f12e9d92d021..84bf2385351ae 100644 --- a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/delegates/DependencyConstraintHandlerDelegate.kt +++ b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/delegates/DependencyConstraintHandlerDelegate.kt @@ -24,7 +24,7 @@ import org.gradle.api.artifacts.dsl.DependencyConstraintHandler /** * Facilitates the implementation of the [DependencyConstraintHandler] interface by delegation via subclassing. * - * See [GradleDelegate] for details why this is currently necessary. + * See [GradleDelegate] for why this is currently necessary. */ abstract class DependencyConstraintHandlerDelegate : DependencyConstraintHandler { diff --git a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/delegates/DependencyHandlerDelegate.kt b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/delegates/DependencyHandlerDelegate.kt index 8ff90ad1fa5b1..0c2bddb217c44 100644 --- a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/delegates/DependencyHandlerDelegate.kt +++ b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/delegates/DependencyHandlerDelegate.kt @@ -36,7 +36,7 @@ import org.gradle.api.attributes.AttributesSchema /** * Facilitates the implementation of the [DependencyHandler] interface by delegation via subclassing. * - * See [GradleDelegate] for details why this is currently necessary. + * See [GradleDelegate] for why this is currently necessary. */ abstract class DependencyHandlerDelegate : DependencyHandler { diff --git a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/delegates/NamedDomainObjectContainerDelegate.kt b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/delegates/NamedDomainObjectContainerDelegate.kt index 9e0c5a944ecab..190291618c710 100644 --- a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/delegates/NamedDomainObjectContainerDelegate.kt +++ b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/delegates/NamedDomainObjectContainerDelegate.kt @@ -36,7 +36,7 @@ import java.util.SortedSet /** * Facilitates the implementation of the [NamedDomainObjectContainer] interface by delegation via subclassing. * - * See [GradleDelegate] for details why this is currently necessary. + * See [GradleDelegate] for why this is currently necessary. */ abstract class NamedDomainObjectContainerDelegate : NamedDomainObjectContainer { diff --git a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/delegates/ProjectDelegate.kt b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/delegates/ProjectDelegate.kt index 3b0bdf704341c..b95d97bbec0ac 100644 --- a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/delegates/ProjectDelegate.kt +++ b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/delegates/ProjectDelegate.kt @@ -68,7 +68,7 @@ import java.util.concurrent.Callable /** * Facilitates the implementation of the [Project] interface by delegation via subclassing. * - * See [GradleDelegate] for details why this is currently necessary. + * See [GradleDelegate] for why this is currently necessary. */ abstract class ProjectDelegate() : Project { diff --git a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/delegates/ScriptHandlerDelegate.kt b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/delegates/ScriptHandlerDelegate.kt index db889e42eac13..6f66792fbbda4 100644 --- a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/delegates/ScriptHandlerDelegate.kt +++ b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/delegates/ScriptHandlerDelegate.kt @@ -31,7 +31,7 @@ import java.net.URI /** * Facilitates the implementation of the [ScriptHandler] interface by delegation via subclassing. * - * See [GradleDelegate] for details why this is currently necessary. + * See [GradleDelegate] for why this is currently necessary. */ abstract class ScriptHandlerDelegate : ScriptHandler { diff --git a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/delegates/SettingsDelegate.kt b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/delegates/SettingsDelegate.kt index cdec543c495b9..7d785b00feb2a 100644 --- a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/delegates/SettingsDelegate.kt +++ b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/delegates/SettingsDelegate.kt @@ -39,7 +39,7 @@ import java.io.File /** * Facilitates the implementation of the [Settings] interface by delegation via subclassing. * - * See [GradleDelegate] for details why this is currently necessary. + * See [GradleDelegate] for why this is currently necessary. */ abstract class SettingsDelegate : Settings { diff --git a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/delegates/TaskContainerDelegate.kt b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/delegates/TaskContainerDelegate.kt index 85f59db625484..e347d662d0fd9 100644 --- a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/delegates/TaskContainerDelegate.kt +++ b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/support/delegates/TaskContainerDelegate.kt @@ -38,7 +38,7 @@ import java.util.SortedSet /** * Facilitates the implementation of the [TaskContainer] interface by delegation via subclassing. * - * See [GradleDelegate] for details why this is currently necessary. + * See [GradleDelegate] for why this is currently necessary. */ abstract class TaskContainerDelegate : TaskContainer { From d2e6b8f52c69a31edccd2314908a2c61d8babc02 Mon Sep 17 00:00:00 2001 From: Stefan Wolf Date: Fri, 15 Mar 2019 16:06:08 +0100 Subject: [PATCH 571/853] Require `@Incremental` for incremental inputs Only properties annotated with `@Incremental` can be queried for incremental changes. The other properties are considered non-incremental and changes to those cause the unit of work run non-incrementally. --- .../java/org/gradle/work/Incremental.java | 41 +++++++++++++ .../TaskPropertyNamingIntegrationTest.groovy | 4 +- ...ractIncrementalTasksIntegrationTest.groovy | 9 ++- .../IncrementalInputsIntegrationTest.groovy | 58 +++++++++++++++++++ ...ncrementalTaskInputsIntegrationTest.groovy | 5 ++ .../IncrementalTaskInputsTaskAction.java | 2 +- .../PropertyAssociationTaskFactory.java | 2 +- .../api/internal/tasks/DefaultTaskInputs.java | 5 +- .../execution/ExecuteActionsTaskExecuter.java | 20 ++++++- .../properties/CompositePropertyVisitor.java | 4 +- .../DefaultInputFilePropertySpec.java | 10 +++- .../properties/DefaultTaskProperties.java | 2 +- .../properties/DefaultTypeMetadataStore.java | 2 + .../properties/GetInputFilesVisitor.java | 5 +- .../properties/InputFilePropertySpec.java | 3 + .../tasks/properties/PropertyVisitor.java | 4 +- ...actInputFilePropertyAnnotationHandler.java | 2 + .../ClasspathPropertyAnnotationHandler.java | 2 + ...ileClasspathPropertyAnnotationHandler.java | 2 + .../execution/plan/DefaultExecutionPlan.java | 2 +- .../tasks/DefaultTaskInputsTest.groovy | 4 +- .../DefaultPropertyWalkerTest.groovy | 8 +-- ...aultTransformationRegistrationFactory.java | 2 +- .../transform/DefaultTransformer.java | 4 +- .../transform/DefaultTransformerInvoker.java | 4 +- ...IncrementalExecutionIntegrationTest.groovy | 4 +- .../gradle/internal/execution/UnitOfWork.java | 4 +- .../changes/AbstractFingerprintChanges.java | 9 +-- .../DefaultExecutionStateChangeDetector.java | 22 +++---- .../changes/DefaultInputFileChanges.java | 34 ++++++++++- .../changes/ExecutionStateChangeDetector.java | 5 +- .../changes/ExecutionStateChanges.java | 4 +- .../changes/IncrementalInputChanges.java | 6 +- .../history/changes/InputFileChanges.java | 14 +++++ .../internal/execution/steps/ExecuteStep.java | 12 ++-- .../execution/steps/ResolveChangesStep.java | 21 ++++++- .../execution/steps/ExecuteStepTest.groovy | 4 +- .../steps/ResolveChangesStepTest.groovy | 3 +- 38 files changed, 280 insertions(+), 68 deletions(-) create mode 100644 subprojects/core-api/src/main/java/org/gradle/work/Incremental.java diff --git a/subprojects/core-api/src/main/java/org/gradle/work/Incremental.java b/subprojects/core-api/src/main/java/org/gradle/work/Incremental.java new file mode 100644 index 0000000000000..67d165487586b --- /dev/null +++ b/subprojects/core-api/src/main/java/org/gradle/work/Incremental.java @@ -0,0 +1,41 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.work; + +import org.gradle.api.Incubating; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Track input changes for the annotated parameter. + * + *

    + * Parameters annotated with {@link Incremental} can be queried via {@link InputChanges#getFileChanges(Object)}. + *

    + * + * @since 5.4 + */ +@Incubating +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.METHOD, ElementType.FIELD}) +@Documented +public @interface Incremental { +} diff --git a/subprojects/core/src/integTest/groovy/org/gradle/api/internal/project/taskfactory/TaskPropertyNamingIntegrationTest.groovy b/subprojects/core/src/integTest/groovy/org/gradle/api/internal/project/taskfactory/TaskPropertyNamingIntegrationTest.groovy index 0577bc408996d..f9885aba3cc88 100644 --- a/subprojects/core/src/integTest/groovy/org/gradle/api/internal/project/taskfactory/TaskPropertyNamingIntegrationTest.groovy +++ b/subprojects/core/src/integTest/groovy/org/gradle/api/internal/project/taskfactory/TaskPropertyNamingIntegrationTest.groovy @@ -81,7 +81,7 @@ class TaskPropertyNamingIntegrationTest extends AbstractIntegrationSpec { def inputFiles = [:] TaskPropertyUtils.visitProperties(project.services.get(PropertyWalker), it, new PropertyVisitor.Adapter() { @Override - void visitInputFileProperty(String propertyName, boolean optional, boolean skipWhenEmpty, Class fileNormalizer, PropertyValue value, InputFilePropertyType filePropertyType) { + void visitInputFileProperty(String propertyName, boolean optional, boolean skipWhenEmpty, boolean isIncrementalInput, Class fileNormalizer, PropertyValue value, InputFilePropertyType filePropertyType) { inputFiles[propertyName] = project.files(value) } @@ -398,7 +398,7 @@ class TaskPropertyNamingIntegrationTest extends AbstractIntegrationSpec { } @Override - void visitInputFileProperty(String propertyName, boolean optional, boolean skipWhenEmpty, Class fileNormalizer, PropertyValue value, InputFilePropertyType filePropertyType) { + void visitInputFileProperty(String propertyName, boolean optional, boolean skipWhenEmpty, boolean incrementalInput, Class fileNormalizer, PropertyValue value, InputFilePropertyType filePropertyType) { println "Input file property '\${propertyName}'" } diff --git a/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/AbstractIncrementalTasksIntegrationTest.groovy b/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/AbstractIncrementalTasksIntegrationTest.groovy index 27d8ac1c4c96f..c3c9982d0eb32 100644 --- a/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/AbstractIncrementalTasksIntegrationTest.groovy +++ b/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/AbstractIncrementalTasksIntegrationTest.groovy @@ -27,7 +27,9 @@ abstract class AbstractIncrementalTasksIntegrationTest extends AbstractIntegrati abstract ChangeTypeInternal getRebuildChangeType(); - def "setup"() { + abstract String getPrimaryInputAnnotation(); + + def setup() { setupTaskSources() buildFile << buildFileBase buildFile << """ @@ -45,8 +47,8 @@ abstract class AbstractIncrementalTasksIntegrationTest extends AbstractIntegrati file('outputs/file2.txt') << "outputFile2" } - private void setupTaskSources() { - file("buildSrc/src/main/groovy/BaseIncrementalTask.groovy") << """ + private void setupTaskSources(String inputDirAnnotation = primaryInputAnnotation) { + file("buildSrc/src/main/groovy/BaseIncrementalTask.groovy").text = """ import org.gradle.api.* import org.gradle.api.plugins.* import org.gradle.api.tasks.* @@ -54,6 +56,7 @@ abstract class AbstractIncrementalTasksIntegrationTest extends AbstractIntegrati import org.gradle.work.* class BaseIncrementalTask extends DefaultTask { + ${inputDirAnnotation} @InputDirectory def File inputDir diff --git a/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/IncrementalInputsIntegrationTest.groovy b/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/IncrementalInputsIntegrationTest.groovy index 2f17e59eecff8..b378dcf8ec4b7 100644 --- a/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/IncrementalInputsIntegrationTest.groovy +++ b/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/IncrementalInputsIntegrationTest.groovy @@ -30,6 +30,9 @@ class IncrementalInputsIntegrationTest extends AbstractIncrementalTasksIntegrati } incrementalExecution = inputChanges.incremental + queryChangesFor.each { parameterName -> + inputChanges.getFileChanges(this."\$parameterName") + } inputChanges.getFileChanges(inputDir).each { change -> switch (change.changeType) { @@ -53,6 +56,18 @@ class IncrementalInputsIntegrationTest extends AbstractIncrementalTasksIntegrati touchOutputs() } + + @Optional + @Incremental + @InputFile + File anotherIncrementalInput + + @Optional + @InputFile + File nonIncrementalInput + + @Internal + List queryChangesFor = ["inputDir"] """ } @@ -61,6 +76,22 @@ class IncrementalInputsIntegrationTest extends AbstractIncrementalTasksIntegrati return ChangeTypeInternal.ADDED } + @Override + String getPrimaryInputAnnotation() { + return "@Incremental" + } + + def setup() { + buildFile << """ + tasks.withType(IncrementalTask).configureEach { + anotherIncrementalInput = project.file('anotherIncrementalInput') + nonIncrementalInput = project.file('nonIncrementalInput') + } + """ + file('anotherIncrementalInput').text = "anotherIncrementalInput" + file('nonIncrementalInput').text = "nonIncrementalInput" + } + def "incremental task is executed non-incrementally when input file property has been added"() { given: file('new-input.txt').text = "new input file" @@ -73,4 +104,31 @@ class IncrementalInputsIntegrationTest extends AbstractIncrementalTasksIntegrati executesWithRebuildContext() } + def "cannot query non-incremental file input parameters"() { + given: + previousExecution() + + when: + file("inputs/new-input-file.txt") << "new file" + buildFile << """ + tasks.withType(IncrementalTask).configureEach { + queryChangesFor.add("nonIncrementalInput") + } + """ + then: + fails("incremental") + failure.assertHasCause("Cannot query incremental changes: No property found for value ${file("nonIncrementalInput").absolutePath}. Incremental properties: anotherIncrementalInput, inputDir.") + } + + def "changes to non-incremental input parameters cause a rebuild"() { + given: + file("nonIncrementalInput").makeOlder() + previousExecution() + + when: + file("inputs/new-input-file.txt") << "new file" + file("nonIncrementalInput").text = 'changed' + then: + executesWithRebuildContext("ext.added += ['new-input-file.txt']") + } } diff --git a/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/IncrementalTaskInputsIntegrationTest.groovy b/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/IncrementalTaskInputsIntegrationTest.groovy index 19f1c599f3ed1..b667569dcced0 100644 --- a/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/IncrementalTaskInputsIntegrationTest.groovy +++ b/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/IncrementalTaskInputsIntegrationTest.groovy @@ -57,6 +57,11 @@ class IncrementalTaskInputsIntegrationTest extends AbstractIncrementalTasksInteg ChangeTypeInternal.MODIFIED } + @Override + String getPrimaryInputAnnotation() { + return "" + } + def "incremental task is executed non-incrementally when input file property has been added"() { given: file('new-input.txt').text = "new input file" diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/project/taskfactory/IncrementalTaskInputsTaskAction.java b/subprojects/core/src/main/java/org/gradle/api/internal/project/taskfactory/IncrementalTaskInputsTaskAction.java index a3e1aa1b32fd2..73f0319bdd199 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/project/taskfactory/IncrementalTaskInputsTaskAction.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/project/taskfactory/IncrementalTaskInputsTaskAction.java @@ -27,7 +27,7 @@ import java.lang.reflect.Method; -class IncrementalTaskInputsTaskAction extends AbstractIncrementalTaskAction { +public class IncrementalTaskInputsTaskAction extends AbstractIncrementalTaskAction { private final Instantiator instantiator; public IncrementalTaskInputsTaskAction(Instantiator instantiator, Class type, Method method) { diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/project/taskfactory/PropertyAssociationTaskFactory.java b/subprojects/core/src/main/java/org/gradle/api/internal/project/taskfactory/PropertyAssociationTaskFactory.java index 52d92cf097843..9f28357639a1e 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/project/taskfactory/PropertyAssociationTaskFactory.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/project/taskfactory/PropertyAssociationTaskFactory.java @@ -64,7 +64,7 @@ public boolean visitOutputFilePropertiesOnly() { } @Override - public void visitInputFileProperty(String propertyName, boolean optional, boolean skipWhenEmpty, @Nullable Class fileNormalizer, PropertyValue value, InputFilePropertyType filePropertyType) { + public void visitInputFileProperty(String propertyName, boolean optional, boolean skipWhenEmpty, boolean incremental, @Nullable Class fileNormalizer, PropertyValue value, InputFilePropertyType filePropertyType) { throw new UnsupportedOperationException(); } diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/DefaultTaskInputs.java b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/DefaultTaskInputs.java index 7a7af93ab3ba5..7c5d530137110 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/DefaultTaskInputs.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/DefaultTaskInputs.java @@ -78,6 +78,7 @@ public void visitRegisteredProperties(PropertyVisitor visitor) { registration.getPropertyName(), registration.isOptional(), registration.isSkipWhenEmpty(), + false, registration.getNormalizer(), registration.getValue(), registration.getFilePropertyType()); @@ -212,7 +213,7 @@ public String getDisplayName() { public void visitContents(final FileCollectionResolveContext context) { TaskPropertyUtils.visitProperties(propertyWalker, task, new PropertyVisitor.Adapter() { @Override - public void visitInputFileProperty(final String propertyName, boolean optional, boolean skipWhenEmpty, @Nullable Class fileNormalizer, PropertyValue value, InputFilePropertyType filePropertyType) { + public void visitInputFileProperty(final String propertyName, boolean optional, boolean skipWhenEmpty, boolean incremental, @Nullable Class fileNormalizer, PropertyValue value, InputFilePropertyType filePropertyType) { if (!TaskInputUnionFileCollection.this.skipWhenEmptyOnly || skipWhenEmpty) { FileCollection actualValue = FileParameterUtils.resolveInputFileValue(fileCollectionFactory, filePropertyType, value); context.add(new PropertyFileCollection(task.toString(), propertyName, "input", actualValue)); @@ -230,7 +231,7 @@ public boolean hasInputs() { } @Override - public void visitInputFileProperty(String propertyName, boolean optional, boolean skipWhenEmpty, @Nullable Class fileNormalizer, PropertyValue value, InputFilePropertyType filePropertyType) { + public void visitInputFileProperty(String propertyName, boolean optional, boolean skipWhenEmpty, boolean incremental, @Nullable Class fileNormalizer, PropertyValue value, InputFilePropertyType filePropertyType) { hasInputs = true; } diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuter.java b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuter.java index 8924cab4c39ef..04f6abf28a075 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuter.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuter.java @@ -16,11 +16,13 @@ package org.gradle.api.internal.tasks.execution; import com.google.common.collect.ImmutableSortedMap; +import com.google.common.collect.ImmutableSortedSet; import com.google.common.collect.Lists; import org.gradle.api.execution.TaskActionListener; import org.gradle.api.internal.OverlappingOutputs; import org.gradle.api.internal.TaskInternal; import org.gradle.api.internal.project.taskfactory.AbstractIncrementalTaskAction; +import org.gradle.api.internal.project.taskfactory.IncrementalTaskInputsTaskAction; import org.gradle.api.internal.tasks.InputChangesAwareTaskAction; import org.gradle.api.internal.tasks.TaskExecuter; import org.gradle.api.internal.tasks.TaskExecuterResult; @@ -289,11 +291,14 @@ public Optional getTimeout() { } @Override - public void visitFileInputs(InputFilePropertyVisitor visitor) { - for (InputFilePropertySpec inputFileProperty : context.getTaskProperties().getInputFileProperties()) { + public void visitInputFileProperties(InputFilePropertyVisitor visitor) { + boolean requiresInputChanges = isRequiresInputChanges(); + boolean usesIncrementalTaskInputs = requiresInputChanges && isUsesIncrementalTaskInputs(); + ImmutableSortedSet inputFileProperties = context.getTaskProperties().getInputFileProperties(); + for (InputFilePropertySpec inputFileProperty : inputFileProperties) { Object value = inputFileProperty.getValue(); if (value != null) { - visitor.visitInputFileProperty(inputFileProperty.getPropertyName(), value); + visitor.visitInputFileProperty(inputFileProperty.getPropertyName(), value, usesIncrementalTaskInputs || inputFileProperty.isIncremental()); } } } @@ -325,6 +330,15 @@ public boolean isRequiresInputChanges() { return false; } + private boolean isUsesIncrementalTaskInputs() { + for (InputChangesAwareTaskAction taskAction : task.getTaskActions()) { + if (taskAction instanceof IncrementalTaskInputsTaskAction) { + return true; + } + } + return false; + } + @Override public long markExecutionTime() { return context.markExecutionTime(); diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/CompositePropertyVisitor.java b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/CompositePropertyVisitor.java index 1f3d1d4d1ad55..fd5a710faaef0 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/CompositePropertyVisitor.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/CompositePropertyVisitor.java @@ -38,9 +38,9 @@ public boolean visitOutputFilePropertiesOnly() { } @Override - public void visitInputFileProperty(String propertyName, boolean optional, boolean skipWhenEmpty, @Nullable Class fileNormalizer, PropertyValue value, InputFilePropertyType filePropertyType) { + public void visitInputFileProperty(String propertyName, boolean optional, boolean skipWhenEmpty, boolean incremental, @Nullable Class fileNormalizer, PropertyValue value, InputFilePropertyType filePropertyType) { for (PropertyVisitor visitor : visitors) { - visitor.visitInputFileProperty(propertyName, optional, skipWhenEmpty, fileNormalizer, value, filePropertyType); + visitor.visitInputFileProperty(propertyName, optional, skipWhenEmpty, incremental, fileNormalizer, value, filePropertyType); } } diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/DefaultInputFilePropertySpec.java b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/DefaultInputFilePropertySpec.java index aaff1069f182e..8b55a28aec2b1 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/DefaultInputFilePropertySpec.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/DefaultInputFilePropertySpec.java @@ -23,12 +23,14 @@ public class DefaultInputFilePropertySpec extends AbstractFilePropertySpec implements InputFilePropertySpec { private final boolean skipWhenEmpty; + private final boolean incremental; private final PropertyValue value; - public DefaultInputFilePropertySpec(String propertyName, Class normalizer, FileCollection files, PropertyValue value, boolean skipWhenEmpty) { + public DefaultInputFilePropertySpec(String propertyName, Class normalizer, FileCollection files, PropertyValue value, boolean skipWhenEmpty, boolean incremental) { super(propertyName, normalizer, files); - this.value = value; this.skipWhenEmpty = skipWhenEmpty; + this.incremental = incremental; + this.value = value; } @Override @@ -36,6 +38,10 @@ public boolean isSkipWhenEmpty() { return skipWhenEmpty; } + public boolean isIncremental() { + return incremental; + } + @Override @Nullable public Object getValue() { diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/DefaultTaskProperties.java b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/DefaultTaskProperties.java index 9b93f1985b212..169cdc603fea9 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/DefaultTaskProperties.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/DefaultTaskProperties.java @@ -249,7 +249,7 @@ private static class ValidationVisitor extends PropertyVisitor.Adapter { private final List taskPropertySpecs = new ArrayList(); @Override - public void visitInputFileProperty(String propertyName, boolean optional, boolean skipWhenEmpty, @Nullable Class fileNormalizer, PropertyValue value, InputFilePropertyType filePropertyType) { + public void visitInputFileProperty(String propertyName, boolean optional, boolean skipWhenEmpty, boolean incremental, @Nullable Class fileNormalizer, PropertyValue value, InputFilePropertyType filePropertyType) { taskPropertySpecs.add(new DefaultFinalizingValidatingProperty(propertyName, value, optional, filePropertyType.getValidationAction())); } diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/DefaultTypeMetadataStore.java b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/DefaultTypeMetadataStore.java index d1ecdfa603244..6bee320a7e368 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/DefaultTypeMetadataStore.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/DefaultTypeMetadataStore.java @@ -48,6 +48,7 @@ import org.gradle.internal.reflect.PropertyMetadata; import org.gradle.internal.reflect.ValidationProblem; import org.gradle.internal.scripts.ScriptOrigin; +import org.gradle.work.Incremental; import javax.annotation.Nullable; import java.lang.annotation.Annotation; @@ -121,6 +122,7 @@ private static Set> collectRelevantAnnotationTypes(S .add(Optional.class) .add(SkipWhenEmpty.class) .add(PathSensitive.class) + .add(Incremental.class) .build(); } diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/GetInputFilesVisitor.java b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/GetInputFilesVisitor.java index 1ae8a9c153d15..f72e7db768218 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/GetInputFilesVisitor.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/GetInputFilesVisitor.java @@ -40,14 +40,15 @@ public GetInputFilesVisitor(String ownerDisplayName, FileCollectionFactory fileC } @Override - public void visitInputFileProperty(final String propertyName, boolean optional, boolean skipWhenEmpty, @Nullable Class fileNormalizer, PropertyValue value, InputFilePropertyType filePropertyType) { + public void visitInputFileProperty(final String propertyName, boolean optional, boolean skipWhenEmpty, boolean incremental, @Nullable Class fileNormalizer, PropertyValue value, InputFilePropertyType filePropertyType) { FileCollection actualValue = FileParameterUtils.resolveInputFileValue(fileCollectionFactory, filePropertyType, value); specs.add(new DefaultInputFilePropertySpec( propertyName, FileParameterUtils.normalizerOrDefault(fileNormalizer), new PropertyFileCollection(ownerDisplayName, propertyName, "input", actualValue), value, - skipWhenEmpty + skipWhenEmpty, + incremental )); if (skipWhenEmpty) { hasSourceFiles = true; diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/InputFilePropertySpec.java b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/InputFilePropertySpec.java index 54e505fa3ffe3..c1856614be7be 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/InputFilePropertySpec.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/InputFilePropertySpec.java @@ -20,6 +20,9 @@ public interface InputFilePropertySpec extends FilePropertySpec { boolean isSkipWhenEmpty(); + + boolean isIncremental(); + @Nullable Object getValue(); } diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/PropertyVisitor.java b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/PropertyVisitor.java index bc68c861636be..5ee8a61df67f7 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/PropertyVisitor.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/PropertyVisitor.java @@ -35,7 +35,7 @@ public interface PropertyVisitor { */ boolean visitOutputFilePropertiesOnly(); - void visitInputFileProperty(String propertyName, boolean optional, boolean skipWhenEmpty, @Nullable Class fileNormalizer, PropertyValue value, InputFilePropertyType filePropertyType); + void visitInputFileProperty(String propertyName, boolean optional, boolean skipWhenEmpty, boolean incremental, @Nullable Class fileNormalizer, PropertyValue value, InputFilePropertyType filePropertyType); void visitInputProperty(String propertyName, PropertyValue value, boolean optional); @@ -52,7 +52,7 @@ public boolean visitOutputFilePropertiesOnly() { } @Override - public void visitInputFileProperty(String propertyName, boolean optional, boolean skipWhenEmpty, @Nullable Class fileNormalizer, PropertyValue value, InputFilePropertyType filePropertyType) { + public void visitInputFileProperty(String propertyName, boolean optional, boolean skipWhenEmpty, boolean incremental, @Nullable Class fileNormalizer, PropertyValue value, InputFilePropertyType filePropertyType) { } @Override diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/annotations/AbstractInputFilePropertyAnnotationHandler.java b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/annotations/AbstractInputFilePropertyAnnotationHandler.java index 63aae95786526..700ce398a86f3 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/annotations/AbstractInputFilePropertyAnnotationHandler.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/annotations/AbstractInputFilePropertyAnnotationHandler.java @@ -27,6 +27,7 @@ import org.gradle.api.tasks.SkipWhenEmpty; import org.gradle.internal.reflect.ParameterValidationContext; import org.gradle.internal.reflect.PropertyMetadata; +import org.gradle.work.Incremental; public abstract class AbstractInputFilePropertyAnnotationHandler implements PropertyAnnotationHandler { @Override @@ -47,6 +48,7 @@ public void visitPropertyValue(String propertyName, PropertyValue value, Propert propertyName, propertyMetadata.isAnnotationPresent(Optional.class), propertyMetadata.isAnnotationPresent(SkipWhenEmpty.class), + propertyMetadata.isAnnotationPresent(Incremental.class), fileNormalizer, value, getFilePropertyType() diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/annotations/ClasspathPropertyAnnotationHandler.java b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/annotations/ClasspathPropertyAnnotationHandler.java index 706f1a455b407..318d322564878 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/annotations/ClasspathPropertyAnnotationHandler.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/annotations/ClasspathPropertyAnnotationHandler.java @@ -30,6 +30,7 @@ import org.gradle.api.tasks.SkipWhenEmpty; import org.gradle.internal.reflect.ParameterValidationContext; import org.gradle.internal.reflect.PropertyMetadata; +import org.gradle.work.Incremental; import java.lang.annotation.Annotation; @@ -60,6 +61,7 @@ public void visitPropertyValue(String propertyName, PropertyValue value, Propert propertyName, propertyMetadata.isAnnotationPresent(Optional.class), propertyMetadata.isAnnotationPresent(SkipWhenEmpty.class), + propertyMetadata.isAnnotationPresent(Incremental.class), ClasspathNormalizer.class, value, InputFilePropertyType.FILES diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/annotations/CompileClasspathPropertyAnnotationHandler.java b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/annotations/CompileClasspathPropertyAnnotationHandler.java index 7c914bf8f9b42..869964a21b2d9 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/annotations/CompileClasspathPropertyAnnotationHandler.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/properties/annotations/CompileClasspathPropertyAnnotationHandler.java @@ -30,6 +30,7 @@ import org.gradle.api.tasks.SkipWhenEmpty; import org.gradle.internal.reflect.ParameterValidationContext; import org.gradle.internal.reflect.PropertyMetadata; +import org.gradle.work.Incremental; import java.lang.annotation.Annotation; @@ -60,6 +61,7 @@ public void visitPropertyValue(String propertyName, PropertyValue value, Propert propertyName, propertyMetadata.isAnnotationPresent(Optional.class), propertyMetadata.isAnnotationPresent(SkipWhenEmpty.class), + propertyMetadata.isAnnotationPresent(Incremental.class), CompileClasspathNormalizer.class, value, InputFilePropertyType.FILES diff --git a/subprojects/core/src/main/java/org/gradle/execution/plan/DefaultExecutionPlan.java b/subprojects/core/src/main/java/org/gradle/execution/plan/DefaultExecutionPlan.java index 19af2f79012e4..c7412216e1396 100644 --- a/subprojects/core/src/main/java/org/gradle/execution/plan/DefaultExecutionPlan.java +++ b/subprojects/core/src/main/java/org/gradle/execution/plan/DefaultExecutionPlan.java @@ -648,7 +648,7 @@ public void run() { } @Override - public void visitInputFileProperty(String propertyName, boolean optional, boolean skipWhenEmpty, @Nullable Class fileNormalizer, PropertyValue value, InputFilePropertyType filePropertyType) { + public void visitInputFileProperty(String propertyName, boolean optional, boolean skipWhenEmpty, boolean incremental, @Nullable Class fileNormalizer, PropertyValue value, InputFilePropertyType filePropertyType) { mutations.hasFileInputs = true; } }); diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/DefaultTaskInputsTest.groovy b/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/DefaultTaskInputsTest.groovy index fc822aa062400..541326675dcdb 100644 --- a/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/DefaultTaskInputsTest.groovy +++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/DefaultTaskInputsTest.groovy @@ -298,7 +298,7 @@ class DefaultTaskInputsTest extends Specification { when: inputs.visitRegisteredProperties(new PropertyVisitor.Adapter() { @Override - void visitInputFileProperty(String propertyName, boolean optional, boolean skipWhenEmpty, @Nullable Class fileNormalizer, PropertyValue value, InputFilePropertyType filePropertyType) { + void visitInputFileProperty(String propertyName, boolean optional, boolean skipWhenEmpty, boolean incremental, @Nullable Class fileNormalizer, PropertyValue value, InputFilePropertyType filePropertyType) { names += propertyName } }) @@ -327,7 +327,7 @@ class DefaultTaskInputsTest extends Specification { def inputFiles = [:] TaskPropertyUtils.visitProperties(walker, task, new PropertyVisitor.Adapter() { @Override - void visitInputFileProperty(String propertyName, boolean optional, boolean skipWhenEmpty, @Nullable Class fileNormalizer, PropertyValue value, InputFilePropertyType filePropertyType) { + void visitInputFileProperty(String propertyName, boolean optional, boolean skipWhenEmpty, boolean incremental, @Nullable Class fileNormalizer, PropertyValue value, InputFilePropertyType filePropertyType) { inputFiles[propertyName] = value.call() } }) diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/properties/DefaultPropertyWalkerTest.groovy b/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/properties/DefaultPropertyWalkerTest.groovy index 41cc353cdae67..27a7f7678f3da 100644 --- a/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/properties/DefaultPropertyWalkerTest.groovy +++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/tasks/properties/DefaultPropertyWalkerTest.groovy @@ -53,11 +53,11 @@ class DefaultPropertyWalkerTest extends AbstractProjectBuilderSpec { then: _ * visitor.visitOutputFilePropertiesOnly() >> false 1 * visitor.visitInputProperty('myProperty', { it.call() == 'myValue' }, false) - 1 * visitor.visitInputFileProperty('inputFile', _, _, _, _, InputFilePropertyType.FILE) - 1 * visitor.visitInputFileProperty('inputFiles', _, _, _, _, InputFilePropertyType.FILES) + 1 * visitor.visitInputFileProperty('inputFile', _, _, _, _, _, InputFilePropertyType.FILE) + 1 * visitor.visitInputFileProperty('inputFiles', _, _, _, _, _, InputFilePropertyType.FILES) 1 * visitor.visitInputProperty('bean', { it.call() == NestedBean }, false) 1 * visitor.visitInputProperty('bean.nestedInput', { it.call() == 'nested' }, false) - 1 * visitor.visitInputFileProperty('bean.inputDir', _, _, _, _, InputFilePropertyType.DIRECTORY) + 1 * visitor.visitInputFileProperty('bean.inputDir', _, _, _, _, _, InputFilePropertyType.DIRECTORY) 1 * visitor.visitOutputFileProperty('outputFile', false, { it.call().path == 'output' }, OutputFilePropertyType.FILE) 1 * visitor.visitOutputFileProperty('bean.outputDir', false, { it.call().path == 'outputDir' }, OutputFilePropertyType.DIRECTORY) @@ -195,7 +195,7 @@ class DefaultPropertyWalkerTest extends AbstractProjectBuilderSpec { _ * visitor.visitOutputFilePropertiesOnly() >> false 1 * visitor.visitInputProperty("nested" , _, false) 1 * visitor.visitInputProperty("nested.nestedInput", _, false) - 1 * visitor.visitInputFileProperty("nested.inputDir", _, _, _, _, InputFilePropertyType.DIRECTORY) + 1 * visitor.visitInputFileProperty("nested.inputDir", _, _, _, _, _, InputFilePropertyType.DIRECTORY) 1 * visitor.visitOutputFileProperty("nested.outputDir", false, _, OutputFilePropertyType.DIRECTORY) 0 * _ diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformationRegistrationFactory.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformationRegistrationFactory.java index 596c06beef82f..ef26de0272956 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformationRegistrationFactory.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformationRegistrationFactory.java @@ -173,7 +173,7 @@ private static class NormalizerCollectingVisitor extends PropertyVisitor.Adapter private Class normalizer; @Override - public void visitInputFileProperty(String propertyName, boolean optional, boolean skipWhenEmpty, @Nullable Class fileNormalizer, PropertyValue value, InputFilePropertyType filePropertyType) { + public void visitInputFileProperty(String propertyName, boolean optional, boolean skipWhenEmpty, boolean incremental, @Nullable Class fileNormalizer, PropertyValue value, InputFilePropertyType filePropertyType) { this.normalizer = fileNormalizer; } } diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformer.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformer.java index 5839aeaabe11b..eae67487ea0f4 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformer.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformer.java @@ -176,7 +176,7 @@ public void visitDependencies(TaskDependencyResolveContext context) { if (parameterObject != null) { parameterPropertyWalker.visitProperties(parameterObject, ParameterValidationContext.NOOP, new PropertyVisitor.Adapter() { @Override - public void visitInputFileProperty(String propertyName, boolean optional, boolean skipWhenEmpty, @Nullable Class fileNormalizer, PropertyValue value, InputFilePropertyType filePropertyType) { + public void visitInputFileProperty(String propertyName, boolean optional, boolean skipWhenEmpty, boolean incremental, @Nullable Class fileNormalizer, PropertyValue value, InputFilePropertyType filePropertyType) { Object unpacked = value.call(); if (unpacked != null) { context.maybeAdd(unpacked); @@ -248,7 +248,7 @@ public void visitOutputFileProperty(String propertyName, boolean optional, Prope } @Override - public void visitInputFileProperty(String propertyName, boolean optional, boolean skipWhenEmpty, @Nullable Class fileNormalizer, PropertyValue value, InputFilePropertyType filePropertyType) { + public void visitInputFileProperty(String propertyName, boolean optional, boolean skipWhenEmpty, boolean incremental, @Nullable Class fileNormalizer, PropertyValue value, InputFilePropertyType filePropertyType) { validateInputFileNormalizer(propertyName, fileNormalizer, cacheable, validationContext); FileCollectionFingerprinter fingerprinter = fingerprinterRegistry.getFingerprinter(FileParameterUtils.normalizerOrDefault(fileNormalizer)); FileCollection inputFileValue = FileParameterUtils.resolveInputFileValue(fileCollectionFactory, filePropertyType, value); diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvoker.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvoker.java index dff8d46227069..34fbc89d3445a 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvoker.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvoker.java @@ -325,8 +325,8 @@ public Optional getTimeout() { } @Override - public void visitFileInputs(InputFilePropertyVisitor visitor) { - visitor.visitInputFileProperty(INPUT_ARTIFACT_PROPERTY_NAME, inputArtifact); + public void visitInputFileProperties(InputFilePropertyVisitor visitor) { + visitor.visitInputFileProperty(INPUT_ARTIFACT_PROPERTY_NAME, inputArtifact, true); } @Override diff --git a/subprojects/execution/src/integTest/groovy/org/gradle/internal/execution/IncrementalExecutionIntegrationTest.groovy b/subprojects/execution/src/integTest/groovy/org/gradle/internal/execution/IncrementalExecutionIntegrationTest.groovy index f003a83fed357..8151124ea7d5b 100644 --- a/subprojects/execution/src/integTest/groovy/org/gradle/internal/execution/IncrementalExecutionIntegrationTest.groovy +++ b/subprojects/execution/src/integTest/groovy/org/gradle/internal/execution/IncrementalExecutionIntegrationTest.groovy @@ -800,10 +800,10 @@ class IncrementalExecutionIntegrationTest extends Specification { } @Override - void visitFileInputs(UnitOfWork.InputFilePropertyVisitor visitor) { + void visitInputFileProperties(UnitOfWork.InputFilePropertyVisitor visitor) { for (entry in inputs.entrySet()) { if (entry.value != null) { - visitor.visitInputFileProperty(entry.key, entry.value) + visitor.visitInputFileProperty(entry.key, entry.value, false) } } } diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/UnitOfWork.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/UnitOfWork.java index aa45456ec0868..3578001183dd8 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/UnitOfWork.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/UnitOfWork.java @@ -39,7 +39,7 @@ public interface UnitOfWork extends CacheableEntity { boolean isRequiresInputChanges(); - void visitFileInputs(InputFilePropertyVisitor visitor); + void visitInputFileProperties(InputFilePropertyVisitor visitor); void visitOutputProperties(OutputPropertyVisitor visitor); @@ -71,7 +71,7 @@ public interface UnitOfWork extends CacheableEntity { @FunctionalInterface interface InputFilePropertyVisitor { - void visitInputFileProperty(String name, Object value); + void visitInputFileProperty(String name, Object value, boolean incremental); } @FunctionalInterface diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/AbstractFingerprintChanges.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/AbstractFingerprintChanges.java index 15ae9a4c347f1..16cd101df6942 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/AbstractFingerprintChanges.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/AbstractFingerprintChanges.java @@ -16,18 +16,19 @@ package org.gradle.internal.execution.history.changes; -import com.google.common.collect.ImmutableSortedMap; import org.gradle.internal.change.ChangeContainer; import org.gradle.internal.change.ChangeVisitor; import org.gradle.internal.fingerprint.CurrentFileCollectionFingerprint; import org.gradle.internal.fingerprint.FileCollectionFingerprint; +import java.util.SortedMap; + public abstract class AbstractFingerprintChanges implements ChangeContainer { - protected final ImmutableSortedMap previous; - protected final ImmutableSortedMap current; + protected final SortedMap previous; + protected final SortedMap current; private final String title; - protected AbstractFingerprintChanges(ImmutableSortedMap previous, ImmutableSortedMap current, String title) { + protected AbstractFingerprintChanges(SortedMap previous, SortedMap current, String title) { this.previous = previous; this.current = current; this.title = title; diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/DefaultExecutionStateChangeDetector.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/DefaultExecutionStateChangeDetector.java index 14ac54455ed22..5601642357c91 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/DefaultExecutionStateChangeDetector.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/DefaultExecutionStateChangeDetector.java @@ -19,6 +19,7 @@ import com.google.common.collect.ImmutableCollection; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMultimap; +import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSortedMap; import org.gradle.api.Describable; import org.gradle.internal.change.CachingChangeContainer; @@ -33,7 +34,7 @@ public class DefaultExecutionStateChangeDetector implements ExecutionStateChangeDetector { @Override - public ExecutionStateChanges detectChanges(AfterPreviousExecutionState lastExecution, BeforeExecutionState thisExecution, Describable executable, boolean allowOverlappingOutputs) { + public ExecutionStateChanges detectChanges(AfterPreviousExecutionState lastExecution, BeforeExecutionState thisExecution, Describable executable, boolean allowOverlappingOutputs, ImmutableSet incrementalPropertyNames) { // Capture changes in execution outcome ChangeContainer previousSuccessState = new PreviousSuccessChanges( lastExecution.isSuccessful()); @@ -61,10 +62,11 @@ public ExecutionStateChanges detectChanges(AfterPreviousExecutionState lastExecu thisExecution.getInputFileProperties(), "Input file", executable); - InputFileChanges directInputFileChanges = new DefaultInputFileChanges( + DefaultInputFileChanges allInputFileChanges = new DefaultInputFileChanges( lastExecution.getInputFileProperties(), thisExecution.getInputFileProperties()); - InputFileChanges inputFileChanges = errorHandling(executable, caching(directInputFileChanges)); + InputFileChanges nonIncrementalInputFileChanges = allInputFileChanges.nonIncrementalChanges(incrementalPropertyNames); + InputFileChanges incrementalInputFileChanges = errorHandling(executable, caching(allInputFileChanges.incrementalChanges(incrementalPropertyNames))); // Capture output files state ChangeContainer outputFilePropertyChanges = new PropertyChanges( @@ -78,7 +80,7 @@ public ExecutionStateChanges detectChanges(AfterPreviousExecutionState lastExecu allowOverlappingOutputs); ChangeContainer outputFileChanges = caching(uncachedOutputChanges); - ChangeContainer rebuildTriggeringChanges = errorHandling(executable, new SummarizingChangeContainer(previousSuccessState, implementationChanges, inputPropertyChanges, inputPropertyValueChanges, outputFilePropertyChanges, outputFileChanges, inputFilePropertyChanges)); + ChangeContainer rebuildTriggeringChanges = errorHandling(executable, new SummarizingChangeContainer(previousSuccessState, implementationChanges, inputPropertyChanges, inputPropertyValueChanges, outputFilePropertyChanges, outputFileChanges, inputFilePropertyChanges, nonIncrementalInputFileChanges)); ImmutableList.Builder builder = ImmutableList.builder(); MessageCollectingChangeVisitor visitor = new MessageCollectingChangeVisitor(builder, ExecutionStateChangeDetector.MAX_OUT_OF_DATE_MESSAGES); @@ -88,13 +90,13 @@ public ExecutionStateChanges detectChanges(AfterPreviousExecutionState lastExecu boolean rebuildRequired = !rebuildReasons.isEmpty(); if (!rebuildRequired) { - inputFileChanges.accept(visitor); + incrementalInputFileChanges.accept(visitor); } ImmutableList allChangeMessages = builder.build(); return rebuildRequired ? new NonIncrementalDetectedExecutionStateChanges(allChangeMessages, thisExecution.getInputFileProperties()) - : new IncrementalDetectedExecutionStateChanges(inputFileChanges, allChangeMessages); + : new IncrementalDetectedExecutionStateChanges(incrementalInputFileChanges, allChangeMessages); } private static ChangeContainer caching(ChangeContainer wrapped) { @@ -147,8 +149,8 @@ public IncrementalDetectedExecutionStateChanges( } @Override - public InputChangesInternal createInputChanges(ImmutableMultimap incrementalParameterNameByValue) { - return new IncrementalInputChanges(inputFileChanges, incrementalParameterNameByValue); + public InputChangesInternal createInputChanges(ImmutableMultimap incrementalParameterNamesByValue) { + return new IncrementalInputChanges(inputFileChanges, incrementalParameterNamesByValue); } } @@ -164,8 +166,8 @@ public NonIncrementalDetectedExecutionStateChanges( } @Override - public InputChangesInternal createInputChanges(ImmutableMultimap incrementalParameterNameByValue) { - return new NonIncrementalInputChanges(inputFileProperties, incrementalParameterNameByValue); + public InputChangesInternal createInputChanges(ImmutableMultimap incrementalParameterNamesByValue) { + return new NonIncrementalInputChanges(inputFileProperties, incrementalParameterNamesByValue); } } diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/DefaultInputFileChanges.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/DefaultInputFileChanges.java index 77640b28a1d1a..130df86d1f060 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/DefaultInputFileChanges.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/DefaultInputFileChanges.java @@ -16,15 +16,19 @@ package org.gradle.internal.execution.history.changes; +import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSortedMap; +import com.google.common.collect.Maps; import org.gradle.internal.change.ChangeVisitor; import org.gradle.internal.fingerprint.CurrentFileCollectionFingerprint; import org.gradle.internal.fingerprint.FileCollectionFingerprint; +import java.util.SortedMap; + public class DefaultInputFileChanges extends AbstractFingerprintChanges implements InputFileChanges { private static final String TITLE = "Input"; - public DefaultInputFileChanges(ImmutableSortedMap previous, ImmutableSortedMap current) { + public DefaultInputFileChanges(SortedMap previous, SortedMap current) { super(previous, current, TITLE); } @@ -39,4 +43,32 @@ public boolean accept(String propertyName, ChangeVisitor visitor) { FileCollectionFingerprint previousFileCollectionFingerprint = previous.get(propertyName); return currentFileCollectionFingerprint.visitChangesSince(previousFileCollectionFingerprint, TITLE, true, visitor); } + + public InputFileChanges nonIncrementalChanges(ImmutableSet incrementalPropertyNames) { + if (incrementalPropertyNames.isEmpty()) { + return this; + } + if (current.keySet().equals(incrementalPropertyNames)) { + return InputFileChanges.EMPTY; + } + + return new DefaultInputFileChanges( + Maps.filterKeys(previous, propertyName -> !incrementalPropertyNames.contains(propertyName)), + Maps.filterKeys(current, propertyName -> !incrementalPropertyNames.contains(propertyName)) + ); + } + + public InputFileChanges incrementalChanges(ImmutableSet incrementalPropertyNames) { + if (incrementalPropertyNames.isEmpty()) { + return InputFileChanges.EMPTY; + } + if (current.keySet().equals(incrementalPropertyNames)) { + return this; + } + + return new DefaultInputFileChanges( + ImmutableSortedMap.copyOfSorted(Maps.filterKeys(previous, propertyName -> incrementalPropertyNames.contains(propertyName))), + ImmutableSortedMap.copyOfSorted(Maps.filterKeys(current, propertyName -> incrementalPropertyNames.contains(propertyName))) + ); + } } diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/ExecutionStateChangeDetector.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/ExecutionStateChangeDetector.java index 3afdc307c2313..f38ca5eea703a 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/ExecutionStateChangeDetector.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/ExecutionStateChangeDetector.java @@ -16,6 +16,7 @@ package org.gradle.internal.execution.history.changes; +import com.google.common.collect.ImmutableSet; import org.gradle.api.Describable; import org.gradle.internal.execution.history.AfterPreviousExecutionState; import org.gradle.internal.execution.history.BeforeExecutionState; @@ -27,6 +28,6 @@ ExecutionStateChanges detectChanges( AfterPreviousExecutionState lastExecution, BeforeExecutionState thisExecution, Describable executable, - boolean allowOverlappingOutputs - ); + boolean allowOverlappingOutputs, + ImmutableSet incrementalPropertyNames); } diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/ExecutionStateChanges.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/ExecutionStateChanges.java index 9a90cfe610f6b..53bbcd4a804c5 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/ExecutionStateChanges.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/ExecutionStateChanges.java @@ -32,7 +32,7 @@ public interface ExecutionStateChanges { /** * Creates the input changes for the given. * - * @param incrementalParameterNameByValue Mapping from the actual value of to the parameter name. + * @param incrementalParameterNamesByValue Mapping from the actual value of to the parameter name. */ - InputChangesInternal createInputChanges(ImmutableMultimap incrementalParameterNameByValue); + InputChangesInternal createInputChanges(ImmutableMultimap incrementalParameterNamesByValue); } diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/IncrementalInputChanges.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/IncrementalInputChanges.java index 56fa44a666782..98cdd04efa513 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/IncrementalInputChanges.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/IncrementalInputChanges.java @@ -16,8 +16,10 @@ package org.gradle.internal.execution.history.changes; +import com.google.common.base.Joiner; import com.google.common.collect.ImmutableCollection; import com.google.common.collect.ImmutableMultimap; +import org.gradle.api.InvalidUserDataException; import org.gradle.api.tasks.incremental.InputFileDetails; import org.gradle.internal.Cast; import org.gradle.internal.change.CollectingChangeVisitor; @@ -49,10 +51,10 @@ public Iterable getFileChanges(Object parameterValue) { public static String determinePropertyName(Object propertyValue, ImmutableMultimap propertyNameByValue) { ImmutableCollection propertyNames = propertyNameByValue.get(propertyValue); if (propertyNames.isEmpty()) { - throw new UnsupportedOperationException("Cannot query incremental changes: No property found for value " + propertyValue + "."); + throw new InvalidUserDataException("Cannot query incremental changes: No property found for value " + propertyValue + ". Incremental properties: " + Joiner.on(", ").join(propertyNameByValue.values()) + "."); } if (propertyNames.size() > 1) { - throw new UnsupportedOperationException(String.format("Cannot query incremental changes: More that one property found with value %s: %s.", propertyValue, propertyNames)); + throw new InvalidUserDataException(String.format("Cannot query incremental changes: More that one property found with value %s: %s.", propertyValue, propertyNames)); } return propertyNames.iterator().next(); } diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/InputFileChanges.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/InputFileChanges.java index c8d3c291e8e96..a8683c99b95fb 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/InputFileChanges.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/InputFileChanges.java @@ -16,9 +16,23 @@ package org.gradle.internal.execution.history.changes; +import org.gradle.api.InvalidUserDataException; import org.gradle.internal.change.ChangeContainer; import org.gradle.internal.change.ChangeVisitor; public interface InputFileChanges extends ChangeContainer { boolean accept(String propertyName, ChangeVisitor visitor); + + InputFileChanges EMPTY = new InputFileChanges() { + + @Override + public boolean accept(ChangeVisitor visitor) { + return true; + } + + @Override + public boolean accept(String propertyName, ChangeVisitor visitor) { + throw new InvalidUserDataException("Cannot query incremental changes: No incremental properties declared."); + } + }; } diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/ExecuteStep.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/ExecuteStep.java index 9f4acb2fe8132..5a5554ad6169e 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/ExecuteStep.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/ExecuteStep.java @@ -62,8 +62,8 @@ private ExecutionOutcome determineOutcome(UnitOfWork.WorkResult result, boolean private InputChangesInternal determineInputChanges(UnitOfWork work, IncrementalChangesContext context) { return context.getChanges() .map(changes -> { - ImmutableMultimap incrementalParameterNameByValue = determineIncrementalParameterNameByValue(work); - InputChangesInternal inputChanges = changes.createInputChanges(incrementalParameterNameByValue); + ImmutableMultimap incrementalParameterNamesByValue = determineIncrementalParameterNamesByValue(work); + InputChangesInternal inputChanges = changes.createInputChanges(incrementalParameterNamesByValue); if (!inputChanges.isIncremental()) { LOGGER.info("All input files are considered out-of-date for incremental {}.", work.getDisplayName()); } @@ -72,9 +72,13 @@ private InputChangesInternal determineInputChanges(UnitOfWork work, IncrementalC .orElseThrow(() -> new UnsupportedOperationException("Cannot use input changes when input tracking is disabled.")); } - private ImmutableMultimap determineIncrementalParameterNameByValue(UnitOfWork work) { + private ImmutableMultimap determineIncrementalParameterNamesByValue(UnitOfWork work) { ImmutableMultimap.Builder builder = ImmutableMultimap.builder(); - work.visitFileInputs((name, value) -> builder.put(value, name)); + work.visitInputFileProperties((name, value, incremental) -> { + if (incremental) { + builder.put(value, name); + } + }); return builder.build(); } } diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/ResolveChangesStep.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/ResolveChangesStep.java index b99c976d830e2..5c4ee51567496 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/ResolveChangesStep.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/ResolveChangesStep.java @@ -18,6 +18,7 @@ import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMultimap; +import com.google.common.collect.ImmutableSet; import org.gradle.internal.execution.IncrementalChangesContext; import org.gradle.internal.execution.IncrementalContext; import org.gradle.internal.execution.Result; @@ -62,7 +63,8 @@ public R execute(IncrementalContext context) { afterPreviousExecution, beforeExecution, work, - !work.isAllowOverlappingOutputs()) + !work.isAllowOverlappingOutputs(), + determineIncrementalPropertyNames(work)) ) .orElseGet(() -> new RebuildExecutionStateChanges(NO_HISTORY, beforeExecution)) ) @@ -97,6 +99,19 @@ public UnitOfWork getWork() { }); } + private static ImmutableSet determineIncrementalPropertyNames(UnitOfWork work) { + if (work.isRequiresInputChanges()) { + ImmutableSet.Builder builder = ImmutableSet.builder(); + work.visitInputFileProperties((name, value, incremental) -> { + if (incremental) { + builder.add(name); + } + }); + return builder.build(); + } + return ImmutableSet.of(); + } + private static class RebuildExecutionStateChanges implements ExecutionStateChanges { private final String rebuildReason; private final BeforeExecutionState beforeExecutionState; @@ -112,11 +127,11 @@ public ImmutableList getAllChangeMessages() { } @Override - public InputChangesInternal createInputChanges(ImmutableMultimap incrementalParameterNameByValue) { + public InputChangesInternal createInputChanges(ImmutableMultimap incrementalParameterNamesByValue) { if (beforeExecutionState == null) { throw new UnsupportedOperationException("Cannot query input changes when input tracking is disabled."); } - return new NonIncrementalInputChanges(beforeExecutionState.getInputFileProperties(), incrementalParameterNameByValue); + return new NonIncrementalInputChanges(beforeExecutionState.getInputFileProperties(), incrementalParameterNamesByValue); } } } diff --git a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/ExecuteStepTest.groovy b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/ExecuteStepTest.groovy index b045eb0f8ebd8..7ba8ec14c556d 100644 --- a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/ExecuteStepTest.groovy +++ b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/ExecuteStepTest.groovy @@ -81,8 +81,8 @@ class ExecuteStepTest extends Specification { 1 * context.work >> work 1 * work.requiresInputChanges >> true 1 * context.changes >> optionalChanges - 1 * work.visitFileInputs(_) >> { args -> - ((UnitOfWork.InputFilePropertyVisitor) args[0]).visitInputFileProperty("fileInput", "some/path") + 1 * work.visitInputFileProperties(_) >> { args -> + ((UnitOfWork.InputFilePropertyVisitor) args[0]).visitInputFileProperty("fileInput", "some/path", true) } 1 * changes.createInputChanges(ImmutableMultimap.of("some/path", "fileInput")) >> inputChanges 1 * work.execute(inputChanges) >> workResult diff --git a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/ResolveChangesStepTest.groovy b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/ResolveChangesStepTest.groovy index 6e6bf30121f5b..80e9dffd92d65 100644 --- a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/ResolveChangesStepTest.groovy +++ b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/ResolveChangesStepTest.groovy @@ -116,8 +116,9 @@ class ResolveChangesStepTest extends StepSpec { 1 * context.rebuildReason >> Optional.empty() 1 * context.beforeExecutionState >> Optional.of(beforeExecutionState) 1 * context.afterPreviousExecutionState >> Optional.of(afterPreviousExecutionState) + 1 * work.requiresInputChanges >> false 1 * work.allowOverlappingOutputs >> true - 1 * changeDetector.detectChanges(afterPreviousExecutionState, beforeExecutionState, work, false) >> changes + 1 * changeDetector.detectChanges(afterPreviousExecutionState, beforeExecutionState, work, false, _) >> changes 0 * _ } } From 575eb59af1336b7b3ad4dcb021093d06f4317570 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=B3r=C3=A1nt=20Pint=C3=A9r?= Date: Fri, 15 Mar 2019 14:09:37 +0100 Subject: [PATCH 572/853] Further simplify CacheHandler CacheHandler doesn't need to be concerned with errors at all. --- .../execution/ExecuteActionsTaskExecuter.java | 5 ++- .../transform/DefaultTransformerInvoker.java | 4 +-- .../internal/execution/CacheHandler.java | 3 +- .../internal/execution/steps/CacheStep.java | 3 +- .../execution/steps/CacheStepTest.groovy | 31 +++++++++---------- 5 files changed, 20 insertions(+), 26 deletions(-) diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuter.java b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuter.java index 035e653a08e0c..43fe182f1beff 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuter.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuter.java @@ -37,7 +37,6 @@ import org.gradle.api.tasks.TaskExecutionException; import org.gradle.caching.BuildCacheKey; import org.gradle.caching.internal.origin.OriginMetadata; -import org.gradle.internal.Try; import org.gradle.internal.UncheckedException; import org.gradle.internal.exceptions.Contextual; import org.gradle.internal.exceptions.DefaultMultiCauseException; @@ -252,7 +251,7 @@ public Optional> getChangingOutputs() { public CacheHandler createCacheHandler() { return new CacheHandler() { @Override - public Try> load(Function>> loader) { + public Optional load(Function> loader) { // TODO Log this when creating the build cache key perhaps? if (task.isHasCustomActions()) { LOGGER.info("Custom actions are attached to {}.", task); @@ -263,7 +262,7 @@ public Try> load(Function>> loade ) { return loader.apply(context.getBuildCacheKey()); } else { - return Try.successful(Optional.empty()); + return Optional.empty(); } } diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvoker.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvoker.java index 6a613d7cf92d9..28cc858d522e3 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvoker.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvoker.java @@ -363,9 +363,9 @@ public CacheHandler createCacheHandler() { TransformerExecutionBuildCacheKey cacheKey = new TransformerExecutionBuildCacheKey(hasher.hash()); return new CacheHandler() { @Override - public Try> load(Function>> loader) { + public Optional load(Function> loader) { if (!transformer.isCacheable()) { - return Try.successful(Optional.empty()); + return Optional.empty(); } return loader.apply(cacheKey); } diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/CacheHandler.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/CacheHandler.java index 70b06e256c840..7c19fca7f882a 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/CacheHandler.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/CacheHandler.java @@ -17,13 +17,12 @@ package org.gradle.internal.execution; import org.gradle.caching.BuildCacheKey; -import org.gradle.internal.Try; import java.util.Optional; import java.util.function.Consumer; import java.util.function.Function; public interface CacheHandler { - Try> load(Function>> loader); + Optional load(Function> loader); void store(Consumer storer); } diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/CacheStep.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/CacheStep.java index 464c329da6c9f..4005c73def9af 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/CacheStep.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/CacheStep.java @@ -64,8 +64,7 @@ public CurrentSnapshotResult execute(IncrementalChangesContext context) { } UnitOfWork work = context.getWork(); CacheHandler cacheHandler = work.createCacheHandler(); - return cacheHandler - .load(cacheKey -> Try.ofFailable(() -> buildCache.load(commandFactory.createLoad(cacheKey, work)))) + return Try.ofFailable(() -> cacheHandler.load(cacheKey -> buildCache.load(commandFactory.createLoad(cacheKey, work)))) .map(successfulLoad -> successfulLoad .map(cacheHit -> { OriginMetadata originMetadata = cacheHit.getOriginMetadata(); diff --git a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/CacheStepTest.groovy b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/CacheStepTest.groovy index e2a1317a42f31..f43613cdd652c 100644 --- a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/CacheStepTest.groovy +++ b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/CacheStepTest.groovy @@ -65,7 +65,7 @@ class CacheStepTest extends StepSpec implements FingerprinterFixture { 1 * buildCacheController.enabled >> true 1 * context.work >> work 1 * work.createCacheHandler() >> cacheHandler - 1 * cacheHandler.load(_) >> { Function>> loader -> + 1 * cacheHandler.load(_) >> { Function> loader -> loader.apply(cacheKey) } @@ -93,7 +93,7 @@ class CacheStepTest extends StepSpec implements FingerprinterFixture { 1 * buildCacheController.enabled >> true 1 * context.work >> work 1 * work.createCacheHandler() >> cacheHandler - 1 * cacheHandler.load(_) >> Try.successful(Optional.empty()) + 1 * cacheHandler.load(_) >> Optional.empty() then: 1 * delegate.execute(context) >> delegateResult @@ -112,8 +112,7 @@ class CacheStepTest extends StepSpec implements FingerprinterFixture { 0 * _ } - def "executes work non-incrementally and stores after recoverable unpack failure"() { - def loadCommand = Mock(BuildCacheLoadCommand) + def "executes work non-incrementally and stores after unpack failure"() { def loadedOutputFile = file("output.txt") def loadedOutputDir = file("output") @@ -126,13 +125,7 @@ class CacheStepTest extends StepSpec implements FingerprinterFixture { 1 * buildCacheController.enabled >> true 1 * context.work >> work 1 * work.createCacheHandler() >> cacheHandler - 1 * cacheHandler.load(_) >> { Function>> loader -> - loader.apply(cacheKey) - } - - then: - 1 * buildCacheCommandFactory.createLoad(cacheKey, work) >> loadCommand - 1 * buildCacheController.load(loadCommand) >> { + 1 * cacheHandler.load(_) >> { Function> loader -> loadedOutputFile << "output" loadedOutputDir.mkdirs() loadedOutputDir.file("output.txt") << "output" @@ -166,19 +159,23 @@ class CacheStepTest extends StepSpec implements FingerprinterFixture { } def "propagates non-recoverable unpack failure"() { - def unrecoverableUnpackFailure = new RuntimeException("unrecoverable unpack failure") - when: step.execute(context) then: def ex = thrown Exception - ex == unrecoverableUnpackFailure + ex.message == "cleanup failure" 1 * buildCacheController.enabled >> true 1 * context.work >> work 1 * work.createCacheHandler() >> cacheHandler - 1 * cacheHandler.load(_) >> { throw unrecoverableUnpackFailure } + 1 * cacheHandler.load(_) >> { throw new RuntimeException("unpack failure") } + + then: + 1 * work.displayName >> "work" + 1 * work.visitOutputTrees(_) >> { CacheableEntity.CacheableTreeVisitor visitor -> + throw new RuntimeException("cleanup failure") + } 0 * _ } @@ -193,7 +190,7 @@ class CacheStepTest extends StepSpec implements FingerprinterFixture { 1 * buildCacheController.enabled >> true 1 * context.work >> work 1 * work.createCacheHandler() >> cacheHandler - 1 * cacheHandler.load(_) >> Try.successful(Optional.empty()) + 1 * cacheHandler.load(_) >> Optional.empty() then: 1 * delegate.execute(context) >> delegateResult @@ -220,7 +217,7 @@ class CacheStepTest extends StepSpec implements FingerprinterFixture { 1 * buildCacheController.enabled >> true 1 * context.work >> work 1 * work.createCacheHandler() >> cacheHandler - 1 * cacheHandler.load(_) >> Try.successful(Optional.empty()) + 1 * cacheHandler.load(_) >> Optional.empty() then: 1 * delegate.execute(context) >> delegateResult From 9bbcd45fcc4bca38e767f190e58fb19aa3df2846 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=B3r=C3=A1nt=20Pint=C3=A9r?= Date: Fri, 15 Mar 2019 16:19:03 +0100 Subject: [PATCH 573/853] Actually enforce rebuilding the work Previously we removed the history, too, which is incorrect. --- ...acheTaskArchiveErrorIntegrationTest.groovy | 36 ++++++++++++- .../DefaultExecutionStateChangeDetector.java | 30 ++++++----- .../changes/ExecutionStateChanges.java | 5 ++ .../changes/RebuildExecutionStateChanges.java | 52 +++++++++++++++++++ .../internal/execution/steps/CacheStep.java | 35 ++++++++----- .../execution/steps/ResolveChangesStep.java | 34 ++---------- .../execution/steps/CacheStepTest.groovy | 32 ++++++++---- 7 files changed, 159 insertions(+), 65 deletions(-) create mode 100644 subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/RebuildExecutionStateChanges.java diff --git a/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/CacheTaskArchiveErrorIntegrationTest.groovy b/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/CacheTaskArchiveErrorIntegrationTest.groovy index c46001b13b955..445de9a45f3ee 100644 --- a/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/CacheTaskArchiveErrorIntegrationTest.groovy +++ b/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/CacheTaskArchiveErrorIntegrationTest.groovy @@ -29,7 +29,7 @@ class CacheTaskArchiveErrorIntegrationTest extends AbstractIntegrationSpec { def remoteCache = new TestBuildCache(file("remote-cache")) def setup() { - executer.beforeExecute { it.withBuildCacheEnabled() } + executer.beforeExecute { withBuildCacheEnabled() } settingsFile << localCache.localCacheConfiguration() } @@ -224,6 +224,40 @@ class CacheTaskArchiveErrorIntegrationTest extends AbstractIntegrationSpec { succeeds("cacheable") } + def "corrupted cache disables incremental execution"() { + when: + buildFile << """ + @CacheableTask + class CustomTask extends DefaultTask { + @OutputDirectory File outputDir = new File(temporaryDir, 'output') + @TaskAction + void generate(IncrementalTaskInputs inputs) { + println "> Incremental: \${inputs.incremental}" + new File(outputDir, "output").text = "OK" + } + } + + task cacheable(type: CustomTask) + """ + succeeds("cacheable") + + then: + localCache.listCacheFiles().size() == 1 + + when: + cleanBuildDir() + + and: + executer.withStackTraceChecksDisabled() + corruptMetadata({ metadata -> metadata.text = "corrupt" }) + succeeds("cacheable") + + then: + output =~ /Cached result format error, corrupted origin metadata\./ + output =~ /> Incremental: false/ + localCache.listCacheFailedFiles().size() == 1 + } + @Unroll def "local state declared via #api API is destroyed when task fails to load from cache"() { def localStateFile = file("local-state.json") diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/DefaultExecutionStateChangeDetector.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/DefaultExecutionStateChangeDetector.java index 14ac54455ed22..89d98cb87c89a 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/DefaultExecutionStateChangeDetector.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/DefaultExecutionStateChangeDetector.java @@ -94,7 +94,7 @@ public ExecutionStateChanges detectChanges(AfterPreviousExecutionState lastExecu ImmutableList allChangeMessages = builder.build(); return rebuildRequired ? new NonIncrementalDetectedExecutionStateChanges(allChangeMessages, thisExecution.getInputFileProperties()) - : new IncrementalDetectedExecutionStateChanges(inputFileChanges, allChangeMessages); + : new IncrementalDetectedExecutionStateChanges(inputFileChanges, allChangeMessages, thisExecution.getInputFileProperties()); } private static ChangeContainer caching(ChangeContainer wrapped) { @@ -135,14 +135,14 @@ public boolean accept(ChangeVisitor visitor) { } } - private static class IncrementalDetectedExecutionStateChanges extends AbstractDetectedExecutionStateChanges implements ExecutionStateChanges { + private static class IncrementalDetectedExecutionStateChanges extends AbstractDetectedExecutionStateChanges { private final InputFileChanges inputFileChanges; public IncrementalDetectedExecutionStateChanges( InputFileChanges inputFileChanges, - ImmutableList allChangeMessages - ) { - super(allChangeMessages); + ImmutableList allChangeMessages, + ImmutableSortedMap inputFileProperties) { + super(allChangeMessages, inputFileProperties); this.inputFileChanges = inputFileChanges; } @@ -152,15 +152,12 @@ public InputChangesInternal createInputChanges(ImmutableMultimap } } - private static class NonIncrementalDetectedExecutionStateChanges extends AbstractDetectedExecutionStateChanges implements ExecutionStateChanges { - private final ImmutableSortedMap inputFileProperties; - + private static class NonIncrementalDetectedExecutionStateChanges extends AbstractDetectedExecutionStateChanges { public NonIncrementalDetectedExecutionStateChanges( ImmutableList allChangeMessages, ImmutableSortedMap inputFileProperties ) { - super(allChangeMessages); - this.inputFileProperties = inputFileProperties; + super(allChangeMessages, inputFileProperties); } @Override @@ -169,16 +166,25 @@ public InputChangesInternal createInputChanges(ImmutableMultimap } } - private static class AbstractDetectedExecutionStateChanges { + private static abstract class AbstractDetectedExecutionStateChanges implements ExecutionStateChanges { private final ImmutableList allChangeMessages; + protected final ImmutableSortedMap inputFileProperties; - public AbstractDetectedExecutionStateChanges(ImmutableList allChangeMessages) { + public AbstractDetectedExecutionStateChanges( + ImmutableList allChangeMessages, + ImmutableSortedMap inputFileProperties) { this.allChangeMessages = allChangeMessages; + this.inputFileProperties = inputFileProperties; } public ImmutableList getAllChangeMessages() { return allChangeMessages; } + + @Override + public ExecutionStateChanges withEnforcedRebuild(String rebuildReason) { + return new RebuildExecutionStateChanges(rebuildReason, inputFileProperties); + } } private static class MessageCollectingChangeVisitor implements ChangeVisitor { diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/ExecutionStateChanges.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/ExecutionStateChanges.java index 9a90cfe610f6b..e096c1c8a38b5 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/ExecutionStateChanges.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/ExecutionStateChanges.java @@ -35,4 +35,9 @@ public interface ExecutionStateChanges { * @param incrementalParameterNameByValue Mapping from the actual value of to the parameter name. */ InputChangesInternal createInputChanges(ImmutableMultimap incrementalParameterNameByValue); + + /** + * Turn these changes into ones forcing a rebuild with the given reason. + */ + ExecutionStateChanges withEnforcedRebuild(String rebuildReason); } diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/RebuildExecutionStateChanges.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/RebuildExecutionStateChanges.java new file mode 100644 index 0000000000000..9e6f905520139 --- /dev/null +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/RebuildExecutionStateChanges.java @@ -0,0 +1,52 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.internal.execution.history.changes; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMultimap; +import com.google.common.collect.ImmutableSortedMap; +import org.gradle.internal.fingerprint.CurrentFileCollectionFingerprint; + +import javax.annotation.Nullable; + +public class RebuildExecutionStateChanges implements ExecutionStateChanges { + private final String rebuildReason; + private final ImmutableSortedMap inputFileProperties; + + public RebuildExecutionStateChanges(String rebuildReason, @Nullable ImmutableSortedMap inputFileProperties) { + this.rebuildReason = rebuildReason; + this.inputFileProperties = inputFileProperties; + } + + @Override + public ImmutableList getAllChangeMessages() { + return ImmutableList.of(rebuildReason); + } + + @Override + public InputChangesInternal createInputChanges(ImmutableMultimap incrementalParameterNameByValue) { + if (inputFileProperties == null) { + throw new UnsupportedOperationException("Cannot query input changes when input tracking is disabled."); + } + return new NonIncrementalInputChanges(inputFileProperties, incrementalParameterNameByValue); + } + + @Override + public ExecutionStateChanges withEnforcedRebuild(String rebuildReason) { + return new RebuildExecutionStateChanges(rebuildReason, inputFileProperties); + } +} diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/CacheStep.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/CacheStep.java index 4005c73def9af..68d8b421663c0 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/CacheStep.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/CacheStep.java @@ -37,12 +37,15 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.io.File; import java.io.IOException; import java.util.Optional; public class CacheStep implements Step { private static final Logger LOGGER = LoggerFactory.getLogger(CacheStep.class); + private static final String FAILED_LOAD_REBUILD_REASON = "Outputs removed due to failed load from cache"; + private final BuildCacheController buildCache; private final BuildCacheCommandFactory commandFactory; private final Step delegate; @@ -62,6 +65,7 @@ public CurrentSnapshotResult execute(IncrementalChangesContext context) { if (!buildCache.isEnabled()) { return executeWithoutCache(context); } + UnitOfWork work = context.getWork(); CacheHandler cacheHandler = work.createCacheHandler(); return Try.ofFailable(() -> cacheHandler.load(cacheKey -> buildCache.load(commandFactory.createLoad(cacheKey, work)))) @@ -96,18 +100,19 @@ public ImmutableSortedMap getFinalOutp .orElseMapFailure(loadFailure -> { LOGGER.warn("Failed to load cache entry for {}, cleaning outputs and falling back to (non-incremental) execution", work.getDisplayName(), loadFailure); - cleanupTreesAfterLoadFailure(work); + + cleanOutputsAfterLoadFailure(work); + Optional rebuildChanges = context.getChanges().map(changes -> changes.withEnforcedRebuild(FAILED_LOAD_REBUILD_REASON)); return executeAndStoreInCache(cacheHandler, new IncrementalChangesContext() { @Override public Optional getChanges() { - // Clear change information to avoid incremental execution after failed load - return Optional.empty(); + return rebuildChanges; } @Override public Optional getRebuildReason() { - return context.getRebuildReason(); + return Optional.of(FAILED_LOAD_REBUILD_REASON); } @Override @@ -128,18 +133,20 @@ public UnitOfWork getWork() { }); } - private static void cleanupTreesAfterLoadFailure(UnitOfWork work) { - work.visitOutputTrees((name, type, root) -> { - try { - if (root.exists()) { - if (root.isDirectory()) { - FileUtils.cleanDirectory(root); - } else { - FileUtils.forceDelete(root); + private static void cleanOutputsAfterLoadFailure(UnitOfWork work) { + work.visitOutputProperties((name, type, roots) -> { + for (File root : roots) { + try { + if (root.exists()) { + if (root.isDirectory()) { + FileUtils.cleanDirectory(root); + } else { + FileUtils.forceDelete(root); + } } + } catch (IOException ex) { + throw new UncheckedIOException(String.format("Failed to clean up files for tree '%s' of %s: %s", name, work.getDisplayName(), root), ex); } - } catch (IOException ex) { - throw new UncheckedIOException(String.format("Failed to clean up files for tree '%s' of %s: %s", name, work.getDisplayName(), root), ex); } }); } diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/ResolveChangesStep.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/ResolveChangesStep.java index b99c976d830e2..87eb485cc62ad 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/ResolveChangesStep.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/ResolveChangesStep.java @@ -16,8 +16,6 @@ package org.gradle.internal.execution.steps; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMultimap; import org.gradle.internal.execution.IncrementalChangesContext; import org.gradle.internal.execution.IncrementalContext; import org.gradle.internal.execution.Result; @@ -27,10 +25,8 @@ import org.gradle.internal.execution.history.BeforeExecutionState; import org.gradle.internal.execution.history.changes.ExecutionStateChangeDetector; import org.gradle.internal.execution.history.changes.ExecutionStateChanges; -import org.gradle.internal.execution.history.changes.InputChangesInternal; -import org.gradle.internal.execution.history.changes.NonIncrementalInputChanges; +import org.gradle.internal.execution.history.changes.RebuildExecutionStateChanges; -import javax.annotation.Nullable; import java.util.Optional; public class ResolveChangesStep implements Step { @@ -53,7 +49,9 @@ public R execute(IncrementalContext context) { Optional beforeExecutionState = context.getBeforeExecutionState(); ExecutionStateChanges changes = context.getRebuildReason() .map(rebuildReason -> - new RebuildExecutionStateChanges(rebuildReason, beforeExecutionState.orElse(null)) + new RebuildExecutionStateChanges(rebuildReason, beforeExecutionState + .map(beforeExecution -> beforeExecution.getInputFileProperties()) + .orElse(null)) ) .orElseGet(() -> beforeExecutionState @@ -64,7 +62,7 @@ public R execute(IncrementalContext context) { work, !work.isAllowOverlappingOutputs()) ) - .orElseGet(() -> new RebuildExecutionStateChanges(NO_HISTORY, beforeExecution)) + .orElseGet(() -> new RebuildExecutionStateChanges(NO_HISTORY, beforeExecution.getInputFileProperties())) ) .orElse(null) ); @@ -97,26 +95,4 @@ public UnitOfWork getWork() { }); } - private static class RebuildExecutionStateChanges implements ExecutionStateChanges { - private final String rebuildReason; - private final BeforeExecutionState beforeExecutionState; - - public RebuildExecutionStateChanges(String rebuildReason, @Nullable BeforeExecutionState beforeExecutionState) { - this.rebuildReason = rebuildReason; - this.beforeExecutionState = beforeExecutionState; - } - - @Override - public ImmutableList getAllChangeMessages() { - return ImmutableList.of(rebuildReason); - } - - @Override - public InputChangesInternal createInputChanges(ImmutableMultimap incrementalParameterNameByValue) { - if (beforeExecutionState == null) { - throw new UnsupportedOperationException("Cannot query input changes when input tracking is disabled."); - } - return new NonIncrementalInputChanges(beforeExecutionState.getInputFileProperties(), incrementalParameterNameByValue); - } - } } diff --git a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/CacheStepTest.groovy b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/CacheStepTest.groovy index f43613cdd652c..d521c09cb9690 100644 --- a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/CacheStepTest.groovy +++ b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/CacheStepTest.groovy @@ -17,8 +17,8 @@ package org.gradle.internal.execution.steps import com.google.common.collect.ImmutableSortedMap +import org.gradle.api.internal.file.collections.ImmutableFileCollection import org.gradle.caching.BuildCacheKey -import org.gradle.caching.internal.CacheableEntity import org.gradle.caching.internal.command.BuildCacheCommandFactory import org.gradle.caching.internal.controller.BuildCacheController import org.gradle.caching.internal.controller.BuildCacheLoadCommand @@ -29,7 +29,11 @@ import org.gradle.internal.execution.CacheHandler import org.gradle.internal.execution.CurrentSnapshotResult import org.gradle.internal.execution.ExecutionOutcome import org.gradle.internal.execution.IncrementalChangesContext +import org.gradle.internal.execution.UnitOfWork +import org.gradle.internal.execution.history.changes.ExecutionStateChanges import org.gradle.internal.file.TreeType +import spock.lang.Shared +import spock.lang.Unroll import java.util.function.Consumer import java.util.function.Function @@ -43,6 +47,7 @@ class CacheStepTest extends StepSpec implements FingerprinterFixture { def cacheKey = Stub(BuildCacheKey) def loadMetadata = Mock(BuildCacheCommandFactory.LoadMetadata) + @Shared def rebuildChanges = Mock(ExecutionStateChanges) def step = new CacheStep(buildCacheController, buildCacheCommandFactory, delegate) def delegateResult = Mock(CurrentSnapshotResult) @@ -112,7 +117,8 @@ class CacheStepTest extends StepSpec implements FingerprinterFixture { 0 * _ } - def "executes work non-incrementally and stores after unpack failure"() { + @Unroll + def "executes work #description non-incrementally and stores after unpack failure"() { def loadedOutputFile = file("output.txt") def loadedOutputDir = file("output") @@ -134,11 +140,11 @@ class CacheStepTest extends StepSpec implements FingerprinterFixture { then: 1 * work.displayName >> "work" - 1 * work.visitOutputTrees(_) >> { CacheableEntity.CacheableTreeVisitor visitor -> - visitor.visitOutputTree("outputFile", TreeType.FILE, loadedOutputFile) - visitor.visitOutputTree("outputDir", TreeType.DIRECTORY, loadedOutputDir) - visitor.visitOutputTree("missingOutputFile", TreeType.FILE, file("missing.txt")) - visitor.visitOutputTree("missingOutputDir", TreeType.DIRECTORY, file("missing")) + 1 * work.visitOutputProperties(_) >> { UnitOfWork.OutputPropertyVisitor visitor -> + visitor.visitOutputProperty("outputFile", TreeType.FILE, ImmutableFileCollection.of(loadedOutputFile)) + visitor.visitOutputProperty("outputDir", TreeType.DIRECTORY, ImmutableFileCollection.of(loadedOutputDir)) + visitor.visitOutputProperty("missingOutputFile", TreeType.FILE, ImmutableFileCollection.of(file("missing.txt"))) + visitor.visitOutputProperty("missingOutputDir", TreeType.DIRECTORY, ImmutableFileCollection.of(file("missing"))) } then: @@ -146,9 +152,10 @@ class CacheStepTest extends StepSpec implements FingerprinterFixture { loadedOutputDir.assertIsEmptyDir() then: + 1 * context.changes >> Optional.ofNullable(changes) 1 * delegate.execute(_) >> { IncrementalChangesContext delegateContext -> assert delegateContext != context - assert !delegateContext.getChanges().present + check(delegateContext) delegateResult } 1 * delegateResult.outcome >> Try.successful(ExecutionOutcome.EXECUTED_NON_INCREMENTALLY) @@ -156,6 +163,13 @@ class CacheStepTest extends StepSpec implements FingerprinterFixture { then: 1 * cacheHandler.store(_) 0 * _ + + where: + description | check | changes + "without changes" | { IncrementalChangesContext context -> assert !context.getChanges().present } | null + "with changes" | { IncrementalChangesContext context -> assert context.getChanges().get() == rebuildChanges } | Mock(ExecutionStateChanges) { + 1 * withEnforcedRebuild("Outputs removed due to failed load from cache") >> rebuildChanges + } } def "propagates non-recoverable unpack failure"() { @@ -173,7 +187,7 @@ class CacheStepTest extends StepSpec implements FingerprinterFixture { then: 1 * work.displayName >> "work" - 1 * work.visitOutputTrees(_) >> { CacheableEntity.CacheableTreeVisitor visitor -> + 1 * work.visitOutputProperties(_) >> { throw new RuntimeException("cleanup failure") } 0 * _ From a9a4757c1db5d9ed37389f7ef8d742001fd51eea Mon Sep 17 00:00:00 2001 From: Stefan Wolf Date: Fri, 15 Mar 2019 16:51:05 +0100 Subject: [PATCH 574/853] SkipWhenEmpty should imply incremental --- ...stractIncrementalTasksIntegrationTest.groovy | 4 ++-- .../IncrementalInputsIntegrationTest.groovy | 17 ++++++++++++++++- .../execution/ExecuteActionsTaskExecuter.java | 2 +- 3 files changed, 19 insertions(+), 4 deletions(-) diff --git a/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/AbstractIncrementalTasksIntegrationTest.groovy b/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/AbstractIncrementalTasksIntegrationTest.groovy index c3c9982d0eb32..d64d880edacbf 100644 --- a/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/AbstractIncrementalTasksIntegrationTest.groovy +++ b/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/AbstractIncrementalTasksIntegrationTest.groovy @@ -47,7 +47,7 @@ abstract class AbstractIncrementalTasksIntegrationTest extends AbstractIntegrati file('outputs/file2.txt') << "outputFile2" } - private void setupTaskSources(String inputDirAnnotation = primaryInputAnnotation) { + void setupTaskSources(String inputDirAnnotation = primaryInputAnnotation) { file("buildSrc/src/main/groovy/BaseIncrementalTask.groovy").text = """ import org.gradle.api.* import org.gradle.api.plugins.* @@ -75,7 +75,7 @@ abstract class AbstractIncrementalTasksIntegrationTest extends AbstractIntegrati def incrementalExecution } """ - file("buildSrc/src/main/groovy/IncrementalTask.groovy") << """ + file("buildSrc/src/main/groovy/IncrementalTask.groovy").text = """ import org.gradle.api.* import org.gradle.api.plugins.* import org.gradle.api.tasks.* diff --git a/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/IncrementalInputsIntegrationTest.groovy b/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/IncrementalInputsIntegrationTest.groovy index b378dcf8ec4b7..0670ffbc684d6 100644 --- a/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/IncrementalInputsIntegrationTest.groovy +++ b/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/IncrementalInputsIntegrationTest.groovy @@ -17,6 +17,7 @@ package org.gradle.api.tasks import org.gradle.internal.change.ChangeTypeInternal +import org.gradle.work.Incremental class IncrementalInputsIntegrationTest extends AbstractIncrementalTasksIntegrationTest { @@ -78,7 +79,7 @@ class IncrementalInputsIntegrationTest extends AbstractIncrementalTasksIntegrati @Override String getPrimaryInputAnnotation() { - return "@Incremental" + return "@${Incremental.simpleName}" } def setup() { @@ -131,4 +132,18 @@ class IncrementalInputsIntegrationTest extends AbstractIncrementalTasksIntegrati then: executesWithRebuildContext("ext.added += ['new-input-file.txt']") } + + def "properties annotated with SkipWhenEmpty are incremental"() { + setupTaskSources("@${SkipWhenEmpty.simpleName}") + + given: + previousExecution() + + when: + file('inputs/file1.txt') << "changed content" + + then: + executesWithIncrementalContext("ext.modified = ['file1.txt']") + } + } diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuter.java b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuter.java index 04f6abf28a075..7e0c2fd20a6ac 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuter.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuter.java @@ -298,7 +298,7 @@ public void visitInputFileProperties(InputFilePropertyVisitor visitor) { for (InputFilePropertySpec inputFileProperty : inputFileProperties) { Object value = inputFileProperty.getValue(); if (value != null) { - visitor.visitInputFileProperty(inputFileProperty.getPropertyName(), value, usesIncrementalTaskInputs || inputFileProperty.isIncremental()); + visitor.visitInputFileProperty(inputFileProperty.getPropertyName(), value, usesIncrementalTaskInputs || inputFileProperty.isIncremental() || inputFileProperty.isSkipWhenEmpty()); } } } From 6e0aa5547c360633dc864a68f470e87d1c834da9 Mon Sep 17 00:00:00 2001 From: Stefan Wolf Date: Fri, 15 Mar 2019 17:56:59 +0100 Subject: [PATCH 575/853] Create incremental changes in change detector --- .../DefaultExecutionStateChangeDetector.java | 44 +++++++++++++++++-- .../changes/DefaultInputFileChanges.java | 31 ------------- 2 files changed, 40 insertions(+), 35 deletions(-) diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/DefaultExecutionStateChangeDetector.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/DefaultExecutionStateChangeDetector.java index 5601642357c91..86489af8e67a1 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/DefaultExecutionStateChangeDetector.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/DefaultExecutionStateChangeDetector.java @@ -21,6 +21,7 @@ import com.google.common.collect.ImmutableMultimap; import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSortedMap; +import com.google.common.collect.Maps; import org.gradle.api.Describable; import org.gradle.internal.change.CachingChangeContainer; import org.gradle.internal.change.Change; @@ -31,6 +32,7 @@ import org.gradle.internal.execution.history.AfterPreviousExecutionState; import org.gradle.internal.execution.history.BeforeExecutionState; import org.gradle.internal.fingerprint.CurrentFileCollectionFingerprint; +import org.gradle.internal.fingerprint.FileCollectionFingerprint; public class DefaultExecutionStateChangeDetector implements ExecutionStateChangeDetector { @Override @@ -62,11 +64,17 @@ public ExecutionStateChanges detectChanges(AfterPreviousExecutionState lastExecu thisExecution.getInputFileProperties(), "Input file", executable); - DefaultInputFileChanges allInputFileChanges = new DefaultInputFileChanges( + InputFileChanges nonIncrementalInputFileChanges = nonIncrementalChanges( + incrementalPropertyNames, lastExecution.getInputFileProperties(), - thisExecution.getInputFileProperties()); - InputFileChanges nonIncrementalInputFileChanges = allInputFileChanges.nonIncrementalChanges(incrementalPropertyNames); - InputFileChanges incrementalInputFileChanges = errorHandling(executable, caching(allInputFileChanges.incrementalChanges(incrementalPropertyNames))); + thisExecution.getInputFileProperties() + ); + InputFileChanges directIncrementalInputFileChanges = incrementalChanges( + incrementalPropertyNames, + lastExecution.getInputFileProperties(), + thisExecution.getInputFileProperties() + ); + InputFileChanges incrementalInputFileChanges = errorHandling(executable, caching(directIncrementalInputFileChanges)); // Capture output files state ChangeContainer outputFilePropertyChanges = new PropertyChanges( @@ -117,6 +125,34 @@ private static InputFileChanges errorHandling(Describable executable, InputFileC return new InputFileChangesWrapper(wrapped, errorHandlingChangeContainer); } + public static InputFileChanges incrementalChanges(ImmutableSet incrementalPropertyNames, ImmutableSortedMap previous, ImmutableSortedMap current) { + if (incrementalPropertyNames.isEmpty()) { + return InputFileChanges.EMPTY; + } + if (current.keySet().equals(incrementalPropertyNames)) { + return new DefaultInputFileChanges(previous, current); + } + + return new DefaultInputFileChanges( + ImmutableSortedMap.copyOfSorted(Maps.filterKeys(previous, propertyName -> incrementalPropertyNames.contains(propertyName))), + ImmutableSortedMap.copyOfSorted(Maps.filterKeys(current, propertyName -> incrementalPropertyNames.contains(propertyName))) + ); + } + + public static InputFileChanges nonIncrementalChanges(ImmutableSet incrementalPropertyNames, ImmutableSortedMap previous, ImmutableSortedMap current) { + if (incrementalPropertyNames.isEmpty()) { + return new DefaultInputFileChanges(previous, current); + } + if (current.keySet().equals(incrementalPropertyNames)) { + return InputFileChanges.EMPTY; + } + + return new DefaultInputFileChanges( + Maps.filterKeys(previous, propertyName -> !incrementalPropertyNames.contains(propertyName)), + Maps.filterKeys(current, propertyName -> !incrementalPropertyNames.contains(propertyName)) + ); + } + private static class InputFileChangesWrapper implements InputFileChanges { private final InputFileChanges inputFileChangesDelegate; private final ChangeContainer changeContainerDelegate; diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/DefaultInputFileChanges.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/DefaultInputFileChanges.java index 130df86d1f060..ec4c1dadc6e96 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/DefaultInputFileChanges.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/DefaultInputFileChanges.java @@ -16,9 +16,6 @@ package org.gradle.internal.execution.history.changes; -import com.google.common.collect.ImmutableSet; -import com.google.common.collect.ImmutableSortedMap; -import com.google.common.collect.Maps; import org.gradle.internal.change.ChangeVisitor; import org.gradle.internal.fingerprint.CurrentFileCollectionFingerprint; import org.gradle.internal.fingerprint.FileCollectionFingerprint; @@ -43,32 +40,4 @@ public boolean accept(String propertyName, ChangeVisitor visitor) { FileCollectionFingerprint previousFileCollectionFingerprint = previous.get(propertyName); return currentFileCollectionFingerprint.visitChangesSince(previousFileCollectionFingerprint, TITLE, true, visitor); } - - public InputFileChanges nonIncrementalChanges(ImmutableSet incrementalPropertyNames) { - if (incrementalPropertyNames.isEmpty()) { - return this; - } - if (current.keySet().equals(incrementalPropertyNames)) { - return InputFileChanges.EMPTY; - } - - return new DefaultInputFileChanges( - Maps.filterKeys(previous, propertyName -> !incrementalPropertyNames.contains(propertyName)), - Maps.filterKeys(current, propertyName -> !incrementalPropertyNames.contains(propertyName)) - ); - } - - public InputFileChanges incrementalChanges(ImmutableSet incrementalPropertyNames) { - if (incrementalPropertyNames.isEmpty()) { - return InputFileChanges.EMPTY; - } - if (current.keySet().equals(incrementalPropertyNames)) { - return this; - } - - return new DefaultInputFileChanges( - ImmutableSortedMap.copyOfSorted(Maps.filterKeys(previous, propertyName -> incrementalPropertyNames.contains(propertyName))), - ImmutableSortedMap.copyOfSorted(Maps.filterKeys(current, propertyName -> incrementalPropertyNames.contains(propertyName))) - ); - } } From 9a3481d7818fc4b6bd36c6471df78ee25725e511 Mon Sep 17 00:00:00 2001 From: Stefan Wolf Date: Fri, 15 Mar 2019 18:12:26 +0100 Subject: [PATCH 576/853] Address more review feedback --- .../org/gradle/api/tasks/SkipWhenEmpty.java | 8 +++++++- .../main/java/org/gradle/work/InputChanges.java | 4 ++++ .../execution/ExecuteActionsTaskExecuter.java | 17 ++++++++++++++--- .../history/changes/InputFileChanges.java | 2 +- 4 files changed, 26 insertions(+), 5 deletions(-) diff --git a/subprojects/core-api/src/main/java/org/gradle/api/tasks/SkipWhenEmpty.java b/subprojects/core-api/src/main/java/org/gradle/api/tasks/SkipWhenEmpty.java index af1b0c4d945c6..97faadd7ab761 100644 --- a/subprojects/core-api/src/main/java/org/gradle/api/tasks/SkipWhenEmpty.java +++ b/subprojects/core-api/src/main/java/org/gradle/api/tasks/SkipWhenEmpty.java @@ -15,7 +15,11 @@ */ package org.gradle.api.tasks; -import java.lang.annotation.*; +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; /** *

    Attached to a task property to indicate that the task should be skipped when the value of the property is an empty @@ -23,6 +27,8 @@ * *

    If all of the inputs declared with this annotation are empty, the task will be skipped with a "NO-SOURCE" message.

    * + *

    Input annotated with this annotation, can be queried for changes via {@link org.gradle.work.InputChanges#getFileChanges(Object)}.

    + * *

    This annotation should be attached to the getter method in Java or the property in Groovy. * Annotations on setters or just the field in Java are ignored.

    * diff --git a/subprojects/core-api/src/main/java/org/gradle/work/InputChanges.java b/subprojects/core-api/src/main/java/org/gradle/work/InputChanges.java index d6d76aa37ed91..679aa710d7715 100644 --- a/subprojects/core-api/src/main/java/org/gradle/work/InputChanges.java +++ b/subprojects/core-api/src/main/java/org/gradle/work/InputChanges.java @@ -92,6 +92,10 @@ public interface InputChanges { * *

    When {@link #isIncremental()} is {@code false}, then all elements of the parameter are returned as {@link ChangeType#ADDED}.

    * + *

    + * Only input file properties annotated with {@link Incremental} or {@link org.gradle.api.tasks.SkipWhenEmpty} can be queried for changes. + *

    + * * @param parameterValue The value of the parameter to query. */ Iterable getFileChanges(Object parameterValue); diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuter.java b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuter.java index 7e0c2fd20a6ac..68e490cb4e0f7 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuter.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuter.java @@ -293,12 +293,12 @@ public Optional getTimeout() { @Override public void visitInputFileProperties(InputFilePropertyVisitor visitor) { boolean requiresInputChanges = isRequiresInputChanges(); - boolean usesIncrementalTaskInputs = requiresInputChanges && isUsesIncrementalTaskInputs(); + boolean usesLegacyIncrementalTaskInputs = requiresInputChanges && isUsesLegacyIncrementalTaskInputs(); ImmutableSortedSet inputFileProperties = context.getTaskProperties().getInputFileProperties(); for (InputFilePropertySpec inputFileProperty : inputFileProperties) { Object value = inputFileProperty.getValue(); if (value != null) { - visitor.visitInputFileProperty(inputFileProperty.getPropertyName(), value, usesIncrementalTaskInputs || inputFileProperty.isIncremental() || inputFileProperty.isSkipWhenEmpty()); + visitor.visitInputFileProperty(inputFileProperty.getPropertyName(), value, isIncremental(usesLegacyIncrementalTaskInputs, inputFileProperty)); } } } @@ -330,7 +330,7 @@ public boolean isRequiresInputChanges() { return false; } - private boolean isUsesIncrementalTaskInputs() { + private boolean isUsesLegacyIncrementalTaskInputs() { for (InputChangesAwareTaskAction taskAction : task.getTaskActions()) { if (taskAction instanceof IncrementalTaskInputsTaskAction) { return true; @@ -419,6 +419,17 @@ public void run(BuildOperationContext context) { }); } + private static boolean isIncremental(boolean usesLegacyIncrementalTaskInputs, InputFilePropertySpec inputFileProperty) { + return + // When using IncrementalTaskInputs, keep the old behaviour of all file inputs being incremental + usesLegacyIncrementalTaskInputs + || inputFileProperty.isIncremental() + // SkipWhenEmpty implies incremental. + // If this file property is empty, then we clean up the previously generated outputs. + // That means that there is a very close relation between the file property and the output. + || inputFileProperty.isSkipWhenEmpty(); + } + @Contextual private static class MultipleTaskActionFailures extends DefaultMultiCauseException { public MultipleTaskActionFailures(String message, Iterable causes) { diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/InputFileChanges.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/InputFileChanges.java index a8683c99b95fb..f18fc52edffe7 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/InputFileChanges.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/InputFileChanges.java @@ -32,7 +32,7 @@ public boolean accept(ChangeVisitor visitor) { @Override public boolean accept(String propertyName, ChangeVisitor visitor) { - throw new InvalidUserDataException("Cannot query incremental changes: No incremental properties declared."); + throw new InvalidUserDataException("Cannot query incremental changes for property " + propertyName + ": No incremental properties declared."); } }; } From 1e89f743d1beca12ebdb8a040798a2f214ee8b05 Mon Sep 17 00:00:00 2001 From: Sterling Greene Date: Fri, 15 Mar 2019 18:27:48 -0400 Subject: [PATCH 577/853] Do not hide delete errors from Sync operations --- .../file/copy/SyncCopyActionDecorator.java | 9 ++---- .../integtests/SyncTaskIntegrationTest.groovy | 30 +++++++++++++++++++ 2 files changed, 33 insertions(+), 6 deletions(-) diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/file/copy/SyncCopyActionDecorator.java b/subprojects/core/src/main/java/org/gradle/api/internal/file/copy/SyncCopyActionDecorator.java index 002d9dd99ea38..ebc1530900204 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/file/copy/SyncCopyActionDecorator.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/file/copy/SyncCopyActionDecorator.java @@ -29,6 +29,7 @@ import org.gradle.api.tasks.util.PatternSet; import org.gradle.util.GFileUtils; +import javax.annotation.Nullable; import java.io.File; import java.util.HashSet; import java.util.Set; @@ -79,7 +80,7 @@ private static class SyncCopyActionDecoratorFileVisitor implements FileVisitor { private final PatternSet preserveSet; private boolean didWork; - private SyncCopyActionDecoratorFileVisitor(Set visited, PatternFilterable preserveSpec) { + private SyncCopyActionDecoratorFileVisitor(Set visited, @Nullable PatternFilterable preserveSpec) { this.visited = visited; PatternSet preserveSet = new PatternSet(); if (preserveSpec != null) { @@ -102,11 +103,7 @@ private void maybeDelete(FileVisitDetails fileDetails, boolean isDir) { RelativePath path = fileDetails.getRelativePath(); if (!visited.contains(path)) { if (preserveSet.isEmpty() || !preserveSpec.isSatisfiedBy(fileDetails)) { - if (isDir) { - GFileUtils.deleteDirectory(fileDetails.getFile()); - } else { - GFileUtils.deleteQuietly(fileDetails.getFile()); - } + GFileUtils.forceDelete(fileDetails.getFile()); didWork = true; } } diff --git a/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/SyncTaskIntegrationTest.groovy b/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/SyncTaskIntegrationTest.groovy index eb933706487bd..08e84ab424954 100644 --- a/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/SyncTaskIntegrationTest.groovy +++ b/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/SyncTaskIntegrationTest.groovy @@ -17,6 +17,8 @@ package org.gradle.integtests import groovy.transform.NotYetImplemented import org.gradle.integtests.fixtures.AbstractIntegrationSpec +import org.gradle.util.Requires +import org.gradle.util.TestPrecondition class SyncTaskIntegrationTest extends AbstractIntegrationSpec { @@ -362,6 +364,34 @@ class SyncTaskIntegrationTest extends AbstractIntegrationSpec { !file('dest/extra.txt').exists() } + @Requires(TestPrecondition.WINDOWS) + def "sync fails when unable to clean-up files"() { + given: + file('source').create { + file 'file1.txt' + file 'file2.txt' + } + file('dest').create { + file 'extra.txt' + } + // Intentionally hold open a file + def ins = new FileInputStream(file("dest/extra.txt")) + buildScript ''' + task syncIt { + doLast { + project.sync { + from 'source' + into 'dest' + } + } + } + '''.stripIndent() + + expect: + fails 'syncIt' + ins.close() + } + def "sync from file tree"() { given: file('source').create { From abae44c7f7d009321531a12110660fb1eb5ed3d7 Mon Sep 17 00:00:00 2001 From: Gradleware Git Bot Date: Sat, 16 Mar 2019 02:44:43 +0100 Subject: [PATCH 578/853] Publish 5.3-20190316012556+0000 --- released-versions.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/released-versions.json b/released-versions.json index 8ff2a9bf425e7..5b39f17de6ae2 100644 --- a/released-versions.json +++ b/released-versions.json @@ -1,7 +1,7 @@ { "latestReleaseSnapshot": { - "version": "5.3-20190315010557+0000", - "buildTime": "20190315010557+0000" + "version": "5.3-20190316012556+0000", + "buildTime": "20190316012556+0000" }, "latestRc": { "version": "5.3-rc-3", From 67c6d636158a4a62a478694a04e546f3177da2db Mon Sep 17 00:00:00 2001 From: Stefan Wolf Date: Fri, 15 Mar 2019 23:15:19 +0100 Subject: [PATCH 579/853] Require incremental input values to be distinct --- .../execution/ExecuteActionsTaskExecuter.java | 23 +++------ .../transform/DefaultTransformerInvoker.java | 5 ++ ...IncrementalExecutionIntegrationTest.groovy | 5 ++ .../gradle/internal/execution/UnitOfWork.java | 2 + .../DefaultExecutionStateChangeDetector.java | 50 ++++++++++--------- .../DefaultIncrementalInputProperties.java | 43 ++++++++++++++++ .../changes/ExecutionStateChangeDetector.java | 3 +- .../changes/ExecutionStateChanges.java | 8 +-- .../changes/IncrementalInputChanges.java | 23 ++------- .../changes/IncrementalInputProperties.java | 48 ++++++++++++++++++ .../changes/NonIncrementalInputChanges.java | 11 ++-- .../internal/execution/steps/ExecuteStep.java | 14 +----- .../execution/steps/ResolveChangesStep.java | 43 +++++++++------- .../NonIncrementalInputChangesTest.groovy | 4 +- .../execution/steps/ExecuteStepTest.groovy | 6 +-- .../steps/ResolveChangesStepTest.groovy | 8 +-- 16 files changed, 181 insertions(+), 115 deletions(-) create mode 100644 subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/DefaultIncrementalInputProperties.java create mode 100644 subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/IncrementalInputProperties.java diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuter.java b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuter.java index 68e490cb4e0f7..4e0f46f4438cb 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuter.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuter.java @@ -292,13 +292,16 @@ public Optional getTimeout() { @Override public void visitInputFileProperties(InputFilePropertyVisitor visitor) { - boolean requiresInputChanges = isRequiresInputChanges(); - boolean usesLegacyIncrementalTaskInputs = requiresInputChanges && isUsesLegacyIncrementalTaskInputs(); ImmutableSortedSet inputFileProperties = context.getTaskProperties().getInputFileProperties(); for (InputFilePropertySpec inputFileProperty : inputFileProperties) { Object value = inputFileProperty.getValue(); if (value != null) { - visitor.visitInputFileProperty(inputFileProperty.getPropertyName(), value, isIncremental(usesLegacyIncrementalTaskInputs, inputFileProperty)); + boolean incremental = inputFileProperty.isIncremental() + // SkipWhenEmpty implies incremental. + // If this file property is empty, then we clean up the previously generated outputs. + // That means that there is a very close relation between the file property and the output. + || inputFileProperty.isSkipWhenEmpty(); + visitor.visitInputFileProperty(inputFileProperty.getPropertyName(), value, incremental); } } } @@ -330,7 +333,8 @@ public boolean isRequiresInputChanges() { return false; } - private boolean isUsesLegacyIncrementalTaskInputs() { + @Override + public boolean isRequiresLegacyInputChanges() { for (InputChangesAwareTaskAction taskAction : task.getTaskActions()) { if (taskAction instanceof IncrementalTaskInputsTaskAction) { return true; @@ -419,17 +423,6 @@ public void run(BuildOperationContext context) { }); } - private static boolean isIncremental(boolean usesLegacyIncrementalTaskInputs, InputFilePropertySpec inputFileProperty) { - return - // When using IncrementalTaskInputs, keep the old behaviour of all file inputs being incremental - usesLegacyIncrementalTaskInputs - || inputFileProperty.isIncremental() - // SkipWhenEmpty implies incremental. - // If this file property is empty, then we clean up the previously generated outputs. - // That means that there is a very close relation between the file property and the output. - || inputFileProperty.isSkipWhenEmpty(); - } - @Contextual private static class MultipleTaskActionFailures extends DefaultMultiCauseException { public MultipleTaskActionFailures(String message, Iterable causes) { diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvoker.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvoker.java index 34fbc89d3445a..bd503c2813aaa 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvoker.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvoker.java @@ -399,6 +399,11 @@ public boolean isRequiresInputChanges() { return transformer.requiresInputChanges(); } + @Override + public boolean isRequiresLegacyInputChanges() { + return false; + } + @Override public String getIdentity() { return identityString; diff --git a/subprojects/execution/src/integTest/groovy/org/gradle/internal/execution/IncrementalExecutionIntegrationTest.groovy b/subprojects/execution/src/integTest/groovy/org/gradle/internal/execution/IncrementalExecutionIntegrationTest.groovy index 8151124ea7d5b..b18340ac88696 100644 --- a/subprojects/execution/src/integTest/groovy/org/gradle/internal/execution/IncrementalExecutionIntegrationTest.groovy +++ b/subprojects/execution/src/integTest/groovy/org/gradle/internal/execution/IncrementalExecutionIntegrationTest.groovy @@ -890,6 +890,11 @@ class IncrementalExecutionIntegrationTest extends Specification { return false } + @Override + boolean isRequiresLegacyInputChanges() { + return false + } + private ImmutableSortedMap snapshotOutputs() { def builder = ImmutableSortedMap.naturalOrder() outputs.each { propertyName, spec -> diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/UnitOfWork.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/UnitOfWork.java index 3578001183dd8..82fb28fcba87b 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/UnitOfWork.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/UnitOfWork.java @@ -39,6 +39,8 @@ public interface UnitOfWork extends CacheableEntity { boolean isRequiresInputChanges(); + boolean isRequiresLegacyInputChanges(); + void visitInputFileProperties(InputFilePropertyVisitor visitor); void visitOutputProperties(OutputPropertyVisitor visitor); diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/DefaultExecutionStateChangeDetector.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/DefaultExecutionStateChangeDetector.java index 86489af8e67a1..1298f88b2f4cf 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/DefaultExecutionStateChangeDetector.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/DefaultExecutionStateChangeDetector.java @@ -18,8 +18,6 @@ import com.google.common.collect.ImmutableCollection; import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMultimap; -import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSortedMap; import com.google.common.collect.Maps; import org.gradle.api.Describable; @@ -36,7 +34,7 @@ public class DefaultExecutionStateChangeDetector implements ExecutionStateChangeDetector { @Override - public ExecutionStateChanges detectChanges(AfterPreviousExecutionState lastExecution, BeforeExecutionState thisExecution, Describable executable, boolean allowOverlappingOutputs, ImmutableSet incrementalPropertyNames) { + public ExecutionStateChanges detectChanges(AfterPreviousExecutionState lastExecution, BeforeExecutionState thisExecution, Describable executable, boolean allowOverlappingOutputs, IncrementalInputProperties incrementalInputProperties) { // Capture changes in execution outcome ChangeContainer previousSuccessState = new PreviousSuccessChanges( lastExecution.isSuccessful()); @@ -65,12 +63,12 @@ public ExecutionStateChanges detectChanges(AfterPreviousExecutionState lastExecu "Input file", executable); InputFileChanges nonIncrementalInputFileChanges = nonIncrementalChanges( - incrementalPropertyNames, + incrementalInputProperties, lastExecution.getInputFileProperties(), thisExecution.getInputFileProperties() ); InputFileChanges directIncrementalInputFileChanges = incrementalChanges( - incrementalPropertyNames, + incrementalInputProperties, lastExecution.getInputFileProperties(), thisExecution.getInputFileProperties() ); @@ -103,8 +101,8 @@ public ExecutionStateChanges detectChanges(AfterPreviousExecutionState lastExecu ImmutableList allChangeMessages = builder.build(); return rebuildRequired - ? new NonIncrementalDetectedExecutionStateChanges(allChangeMessages, thisExecution.getInputFileProperties()) - : new IncrementalDetectedExecutionStateChanges(incrementalInputFileChanges, allChangeMessages); + ? new NonIncrementalDetectedExecutionStateChanges(allChangeMessages, thisExecution.getInputFileProperties(), incrementalInputProperties) + : new IncrementalDetectedExecutionStateChanges(incrementalInputFileChanges, allChangeMessages, incrementalInputProperties); } private static ChangeContainer caching(ChangeContainer wrapped) { @@ -125,31 +123,31 @@ private static InputFileChanges errorHandling(Describable executable, InputFileC return new InputFileChangesWrapper(wrapped, errorHandlingChangeContainer); } - public static InputFileChanges incrementalChanges(ImmutableSet incrementalPropertyNames, ImmutableSortedMap previous, ImmutableSortedMap current) { - if (incrementalPropertyNames.isEmpty()) { + public static InputFileChanges incrementalChanges(IncrementalInputProperties incrementalInputProperties, ImmutableSortedMap previous, ImmutableSortedMap current) { + if (incrementalInputProperties == IncrementalInputProperties.NONE) { return InputFileChanges.EMPTY; } - if (current.keySet().equals(incrementalPropertyNames)) { + if (incrementalInputProperties == IncrementalInputProperties.ALL) { return new DefaultInputFileChanges(previous, current); } return new DefaultInputFileChanges( - ImmutableSortedMap.copyOfSorted(Maps.filterKeys(previous, propertyName -> incrementalPropertyNames.contains(propertyName))), - ImmutableSortedMap.copyOfSorted(Maps.filterKeys(current, propertyName -> incrementalPropertyNames.contains(propertyName))) + ImmutableSortedMap.copyOfSorted(Maps.filterKeys(previous, propertyName -> incrementalInputProperties.isIncrementalProperty(propertyName))), + ImmutableSortedMap.copyOfSorted(Maps.filterKeys(current, propertyName -> incrementalInputProperties.isIncrementalProperty(propertyName))) ); } - public static InputFileChanges nonIncrementalChanges(ImmutableSet incrementalPropertyNames, ImmutableSortedMap previous, ImmutableSortedMap current) { - if (incrementalPropertyNames.isEmpty()) { + public static InputFileChanges nonIncrementalChanges(IncrementalInputProperties incrementalInputProperties, ImmutableSortedMap previous, ImmutableSortedMap current) { + if (incrementalInputProperties == IncrementalInputProperties.NONE) { return new DefaultInputFileChanges(previous, current); } - if (current.keySet().equals(incrementalPropertyNames)) { + if (incrementalInputProperties == IncrementalInputProperties.ALL) { return InputFileChanges.EMPTY; } return new DefaultInputFileChanges( - Maps.filterKeys(previous, propertyName -> !incrementalPropertyNames.contains(propertyName)), - Maps.filterKeys(current, propertyName -> !incrementalPropertyNames.contains(propertyName)) + Maps.filterKeys(previous, propertyName -> !incrementalInputProperties.isIncrementalProperty(propertyName)), + Maps.filterKeys(current, propertyName -> !incrementalInputProperties.isIncrementalProperty(propertyName)) ); } @@ -175,35 +173,41 @@ public boolean accept(ChangeVisitor visitor) { private static class IncrementalDetectedExecutionStateChanges extends AbstractDetectedExecutionStateChanges implements ExecutionStateChanges { private final InputFileChanges inputFileChanges; + private final IncrementalInputProperties incrementalInputProperties; public IncrementalDetectedExecutionStateChanges( InputFileChanges inputFileChanges, - ImmutableList allChangeMessages + ImmutableList allChangeMessages, + IncrementalInputProperties incrementalInputProperties ) { super(allChangeMessages); this.inputFileChanges = inputFileChanges; + this.incrementalInputProperties = incrementalInputProperties; } @Override - public InputChangesInternal createInputChanges(ImmutableMultimap incrementalParameterNamesByValue) { - return new IncrementalInputChanges(inputFileChanges, incrementalParameterNamesByValue); + public InputChangesInternal createInputChanges() { + return new IncrementalInputChanges(inputFileChanges, incrementalInputProperties); } } private static class NonIncrementalDetectedExecutionStateChanges extends AbstractDetectedExecutionStateChanges implements ExecutionStateChanges { private final ImmutableSortedMap inputFileProperties; + private final IncrementalInputProperties incrementalInputProperties; public NonIncrementalDetectedExecutionStateChanges( ImmutableList allChangeMessages, - ImmutableSortedMap inputFileProperties + ImmutableSortedMap inputFileProperties, + IncrementalInputProperties incrementalInputProperties ) { super(allChangeMessages); this.inputFileProperties = inputFileProperties; + this.incrementalInputProperties = incrementalInputProperties; } @Override - public InputChangesInternal createInputChanges(ImmutableMultimap incrementalParameterNamesByValue) { - return new NonIncrementalInputChanges(inputFileProperties, incrementalParameterNamesByValue); + public InputChangesInternal createInputChanges() { + return new NonIncrementalInputChanges(inputFileProperties, incrementalInputProperties); } } diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/DefaultIncrementalInputProperties.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/DefaultIncrementalInputProperties.java new file mode 100644 index 0000000000000..b89472795d4fc --- /dev/null +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/DefaultIncrementalInputProperties.java @@ -0,0 +1,43 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.internal.execution.history.changes; + +import com.google.common.base.Joiner; +import com.google.common.collect.ImmutableBiMap; +import org.gradle.api.InvalidUserDataException; + +public class DefaultIncrementalInputProperties implements IncrementalInputProperties { + private final ImmutableBiMap incrementalInputProperties; + + public DefaultIncrementalInputProperties(ImmutableBiMap incrementalInputProperties) { + this.incrementalInputProperties = incrementalInputProperties; + } + + @Override + public boolean isIncrementalProperty(String propertyName) { + return incrementalInputProperties.containsKey(propertyName); + } + + @Override + public String getPropertyNameFor(Object propertyValue) { + String propertyName = incrementalInputProperties.inverse().get(propertyValue); + if (propertyName == null) { + throw new InvalidUserDataException("Cannot query incremental changes: No property found for value " + propertyValue + ". Incremental properties: " + Joiner.on(", ").join(incrementalInputProperties.keySet()) + "."); + } + return propertyName; + } +} diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/ExecutionStateChangeDetector.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/ExecutionStateChangeDetector.java index f38ca5eea703a..85187762613af 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/ExecutionStateChangeDetector.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/ExecutionStateChangeDetector.java @@ -16,7 +16,6 @@ package org.gradle.internal.execution.history.changes; -import com.google.common.collect.ImmutableSet; import org.gradle.api.Describable; import org.gradle.internal.execution.history.AfterPreviousExecutionState; import org.gradle.internal.execution.history.BeforeExecutionState; @@ -29,5 +28,5 @@ ExecutionStateChanges detectChanges( BeforeExecutionState thisExecution, Describable executable, boolean allowOverlappingOutputs, - ImmutableSet incrementalPropertyNames); + IncrementalInputProperties incrementalInputProperties); } diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/ExecutionStateChanges.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/ExecutionStateChanges.java index 53bbcd4a804c5..1de9302edbad8 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/ExecutionStateChanges.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/ExecutionStateChanges.java @@ -17,7 +17,6 @@ package org.gradle.internal.execution.history.changes; import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMultimap; /** * Represents the complete changes in execution state @@ -29,10 +28,5 @@ public interface ExecutionStateChanges { */ ImmutableList getAllChangeMessages(); - /** - * Creates the input changes for the given. - * - * @param incrementalParameterNamesByValue Mapping from the actual value of to the parameter name. - */ - InputChangesInternal createInputChanges(ImmutableMultimap incrementalParameterNamesByValue); + InputChangesInternal createInputChanges(); } diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/IncrementalInputChanges.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/IncrementalInputChanges.java index 98cdd04efa513..1be651e8a21a0 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/IncrementalInputChanges.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/IncrementalInputChanges.java @@ -16,10 +16,6 @@ package org.gradle.internal.execution.history.changes; -import com.google.common.base.Joiner; -import com.google.common.collect.ImmutableCollection; -import com.google.common.collect.ImmutableMultimap; -import org.gradle.api.InvalidUserDataException; import org.gradle.api.tasks.incremental.InputFileDetails; import org.gradle.internal.Cast; import org.gradle.internal.change.CollectingChangeVisitor; @@ -28,11 +24,11 @@ public class IncrementalInputChanges implements InputChangesInternal { private final InputFileChanges changes; - private final ImmutableMultimap propertyNamesByValue; + private final IncrementalInputProperties incrementalInputProperties; - public IncrementalInputChanges(InputFileChanges changes, ImmutableMultimap propertyNamesByValue) { + public IncrementalInputChanges(InputFileChanges changes, IncrementalInputProperties incrementalInputProperties) { this.changes = changes; - this.propertyNamesByValue = propertyNamesByValue; + this.incrementalInputProperties = incrementalInputProperties; } @Override @@ -42,23 +38,12 @@ public boolean isIncremental() { @Override public Iterable getFileChanges(Object parameterValue) { - String propertyName = determinePropertyName(parameterValue, propertyNamesByValue); + String propertyName = incrementalInputProperties.getPropertyNameFor(parameterValue); CollectingChangeVisitor visitor = new CollectingChangeVisitor(); changes.accept(propertyName, visitor); return Cast.uncheckedNonnullCast(visitor.getChanges()); } - public static String determinePropertyName(Object propertyValue, ImmutableMultimap propertyNameByValue) { - ImmutableCollection propertyNames = propertyNameByValue.get(propertyValue); - if (propertyNames.isEmpty()) { - throw new InvalidUserDataException("Cannot query incremental changes: No property found for value " + propertyValue + ". Incremental properties: " + Joiner.on(", ").join(propertyNameByValue.values()) + "."); - } - if (propertyNames.size() > 1) { - throw new InvalidUserDataException(String.format("Cannot query incremental changes: More that one property found with value %s: %s.", propertyValue, propertyNames)); - } - return propertyNames.iterator().next(); - } - @Override public Iterable getAllFileChanges() { CollectingChangeVisitor visitor = new CollectingChangeVisitor(); diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/IncrementalInputProperties.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/IncrementalInputProperties.java new file mode 100644 index 0000000000000..e9a4d69390f73 --- /dev/null +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/IncrementalInputProperties.java @@ -0,0 +1,48 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.internal.execution.history.changes; + +import org.gradle.api.InvalidUserDataException; + +public interface IncrementalInputProperties { + boolean isIncrementalProperty(String propertyName); + String getPropertyNameFor(Object value); + + IncrementalInputProperties NONE = new IncrementalInputProperties() { + @Override + public boolean isIncrementalProperty(String propertyName) { + return false; + } + + @Override + public String getPropertyNameFor(Object value) { + throw new InvalidUserDataException("Cannot query incremental changes for property " + value + ": No incremental properties declared."); + } + }; + + IncrementalInputProperties ALL = new IncrementalInputProperties() { + @Override + public boolean isIncrementalProperty(String propertyName) { + return true; + } + + @Override + public String getPropertyNameFor(Object value) { + throw new InvalidUserDataException("Cannot query incremental changes for property " + value + ": Requires using 'InputChanges'."); + } + }; +} diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/NonIncrementalInputChanges.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/NonIncrementalInputChanges.java index 0367e88d68326..08a6c6ad399fc 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/NonIncrementalInputChanges.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/NonIncrementalInputChanges.java @@ -16,7 +16,6 @@ package org.gradle.internal.execution.history.changes; -import com.google.common.collect.ImmutableMultimap; import com.google.common.collect.ImmutableSortedMap; import org.gradle.api.tasks.incremental.InputFileDetails; import org.gradle.internal.Cast; @@ -27,15 +26,13 @@ import java.io.File; import java.util.stream.Stream; -import static org.gradle.internal.execution.history.changes.IncrementalInputChanges.determinePropertyName; - public class NonIncrementalInputChanges implements InputChangesInternal { private final ImmutableSortedMap currentInputs; - private final ImmutableMultimap propertyNameByValue; + private final IncrementalInputProperties incrementalInputProperties; - public NonIncrementalInputChanges(ImmutableSortedMap currentInputs, ImmutableMultimap propertyNamesByValue) { + public NonIncrementalInputChanges(ImmutableSortedMap currentInputs, IncrementalInputProperties incrementalInputProperties) { this.currentInputs = currentInputs; - this.propertyNameByValue = propertyNamesByValue; + this.incrementalInputProperties = incrementalInputProperties; } @Override @@ -45,7 +42,7 @@ public boolean isIncremental() { @Override public Iterable getFileChanges(Object parameterValue) { - CurrentFileCollectionFingerprint currentFileCollectionFingerprint = currentInputs.get(determinePropertyName(parameterValue, propertyNameByValue)); + CurrentFileCollectionFingerprint currentFileCollectionFingerprint = currentInputs.get(incrementalInputProperties.getPropertyNameFor(parameterValue)); return () -> getAllFileChanges(currentFileCollectionFingerprint).iterator(); } diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/ExecuteStep.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/ExecuteStep.java index 5a5554ad6169e..e18077feddce4 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/ExecuteStep.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/ExecuteStep.java @@ -16,7 +16,6 @@ package org.gradle.internal.execution.steps; -import com.google.common.collect.ImmutableMultimap; import org.gradle.internal.Try; import org.gradle.internal.execution.ExecutionOutcome; import org.gradle.internal.execution.IncrementalChangesContext; @@ -62,8 +61,7 @@ private ExecutionOutcome determineOutcome(UnitOfWork.WorkResult result, boolean private InputChangesInternal determineInputChanges(UnitOfWork work, IncrementalChangesContext context) { return context.getChanges() .map(changes -> { - ImmutableMultimap incrementalParameterNamesByValue = determineIncrementalParameterNamesByValue(work); - InputChangesInternal inputChanges = changes.createInputChanges(incrementalParameterNamesByValue); + InputChangesInternal inputChanges = changes.createInputChanges(); if (!inputChanges.isIncremental()) { LOGGER.info("All input files are considered out-of-date for incremental {}.", work.getDisplayName()); } @@ -71,14 +69,4 @@ private InputChangesInternal determineInputChanges(UnitOfWork work, IncrementalC }) .orElseThrow(() -> new UnsupportedOperationException("Cannot use input changes when input tracking is disabled.")); } - - private ImmutableMultimap determineIncrementalParameterNamesByValue(UnitOfWork work) { - ImmutableMultimap.Builder builder = ImmutableMultimap.builder(); - work.visitInputFileProperties((name, value, incremental) -> { - if (incremental) { - builder.put(value, name); - } - }); - return builder.build(); - } } diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/ResolveChangesStep.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/ResolveChangesStep.java index 5c4ee51567496..1e3bd6529b938 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/ResolveChangesStep.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/ResolveChangesStep.java @@ -16,9 +16,8 @@ package org.gradle.internal.execution.steps; +import com.google.common.collect.ImmutableBiMap; import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMultimap; -import com.google.common.collect.ImmutableSet; import org.gradle.internal.execution.IncrementalChangesContext; import org.gradle.internal.execution.IncrementalContext; import org.gradle.internal.execution.Result; @@ -26,8 +25,10 @@ import org.gradle.internal.execution.UnitOfWork; import org.gradle.internal.execution.history.AfterPreviousExecutionState; import org.gradle.internal.execution.history.BeforeExecutionState; +import org.gradle.internal.execution.history.changes.DefaultIncrementalInputProperties; import org.gradle.internal.execution.history.changes.ExecutionStateChangeDetector; import org.gradle.internal.execution.history.changes.ExecutionStateChanges; +import org.gradle.internal.execution.history.changes.IncrementalInputProperties; import org.gradle.internal.execution.history.changes.InputChangesInternal; import org.gradle.internal.execution.history.changes.NonIncrementalInputChanges; @@ -54,7 +55,7 @@ public R execute(IncrementalContext context) { Optional beforeExecutionState = context.getBeforeExecutionState(); ExecutionStateChanges changes = context.getRebuildReason() .map(rebuildReason -> - new RebuildExecutionStateChanges(rebuildReason, beforeExecutionState.orElse(null)) + new RebuildExecutionStateChanges(rebuildReason, beforeExecutionState.orElse(null), createIncrementalInputProperties(work)) ) .orElseGet(() -> beforeExecutionState @@ -64,9 +65,9 @@ public R execute(IncrementalContext context) { beforeExecution, work, !work.isAllowOverlappingOutputs(), - determineIncrementalPropertyNames(work)) + createIncrementalInputProperties(work)) ) - .orElseGet(() -> new RebuildExecutionStateChanges(NO_HISTORY, beforeExecution)) + .orElseGet(() -> new RebuildExecutionStateChanges(NO_HISTORY, beforeExecution, createIncrementalInputProperties(work))) ) .orElse(null) ); @@ -99,26 +100,32 @@ public UnitOfWork getWork() { }); } - private static ImmutableSet determineIncrementalPropertyNames(UnitOfWork work) { - if (work.isRequiresInputChanges()) { - ImmutableSet.Builder builder = ImmutableSet.builder(); - work.visitInputFileProperties((name, value, incremental) -> { - if (incremental) { - builder.add(name); - } - }); - return builder.build(); + private static IncrementalInputProperties createIncrementalInputProperties(UnitOfWork work) { + if (!work.isRequiresInputChanges()) { + return IncrementalInputProperties.NONE; } - return ImmutableSet.of(); + if (work.isRequiresLegacyInputChanges()) { + // When using IncrementalTaskInputs, keep the old behaviour of all file inputs being incremental + return IncrementalInputProperties.ALL; + } + ImmutableBiMap.Builder builder = ImmutableBiMap.builder(); + work.visitInputFileProperties((name, value, incremental) -> { + if (incremental) { + builder.put(name, value); + } + }); + return new DefaultIncrementalInputProperties(builder.build()); } private static class RebuildExecutionStateChanges implements ExecutionStateChanges { private final String rebuildReason; private final BeforeExecutionState beforeExecutionState; + private final IncrementalInputProperties incrementalInputProperties; - public RebuildExecutionStateChanges(String rebuildReason, @Nullable BeforeExecutionState beforeExecutionState) { + public RebuildExecutionStateChanges(String rebuildReason, @Nullable BeforeExecutionState beforeExecutionState, IncrementalInputProperties incrementalInputProperties) { this.rebuildReason = rebuildReason; this.beforeExecutionState = beforeExecutionState; + this.incrementalInputProperties = incrementalInputProperties; } @Override @@ -127,11 +134,11 @@ public ImmutableList getAllChangeMessages() { } @Override - public InputChangesInternal createInputChanges(ImmutableMultimap incrementalParameterNamesByValue) { + public InputChangesInternal createInputChanges() { if (beforeExecutionState == null) { throw new UnsupportedOperationException("Cannot query input changes when input tracking is disabled."); } - return new NonIncrementalInputChanges(beforeExecutionState.getInputFileProperties(), incrementalParameterNamesByValue); + return new NonIncrementalInputChanges(beforeExecutionState.getInputFileProperties(), incrementalInputProperties); } } } diff --git a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/history/changes/NonIncrementalInputChangesTest.groovy b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/history/changes/NonIncrementalInputChangesTest.groovy index e9f90acaf8668..f932b01a1d521 100644 --- a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/history/changes/NonIncrementalInputChangesTest.groovy +++ b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/history/changes/NonIncrementalInputChangesTest.groovy @@ -16,7 +16,7 @@ package org.gradle.internal.execution.history.changes -import com.google.common.collect.ImmutableMultimap +import com.google.common.collect.ImmutableBiMap import com.google.common.collect.ImmutableSortedMap import org.gradle.internal.fingerprint.CurrentFileCollectionFingerprint import org.gradle.internal.fingerprint.impl.AbsolutePathFingerprintingStrategy @@ -30,7 +30,7 @@ class NonIncrementalInputChangesTest extends Specification { def "can iterate changes more than once"() { def fingerprint = DefaultCurrentFileCollectionFingerprint.from([new RegularFileSnapshot("/some/where", "where", HashCode.fromInt(1234), 0)], AbsolutePathFingerprintingStrategy.INCLUDE_MISSING) - def changes = new NonIncrementalInputChanges(ImmutableSortedMap.of("input", fingerprint), ImmutableMultimap.of("value", "input")) + def changes = new NonIncrementalInputChanges(ImmutableSortedMap.of("input", fingerprint), new DefaultIncrementalInputProperties(ImmutableBiMap.of("input", "value"))) def expectedChangedFiles = [new File("/some/where")] when: diff --git a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/ExecuteStepTest.groovy b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/ExecuteStepTest.groovy index 7ba8ec14c556d..bd39b206ca5fc 100644 --- a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/ExecuteStepTest.groovy +++ b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/ExecuteStepTest.groovy @@ -16,7 +16,6 @@ package org.gradle.internal.execution.steps -import com.google.common.collect.ImmutableMultimap import org.gradle.internal.execution.ExecutionOutcome import org.gradle.internal.execution.IncrementalChangesContext import org.gradle.internal.execution.UnitOfWork @@ -81,10 +80,7 @@ class ExecuteStepTest extends Specification { 1 * context.work >> work 1 * work.requiresInputChanges >> true 1 * context.changes >> optionalChanges - 1 * work.visitInputFileProperties(_) >> { args -> - ((UnitOfWork.InputFilePropertyVisitor) args[0]).visitInputFileProperty("fileInput", "some/path", true) - } - 1 * changes.createInputChanges(ImmutableMultimap.of("some/path", "fileInput")) >> inputChanges + 1 * changes.createInputChanges() >> inputChanges 1 * work.execute(inputChanges) >> workResult _ * work.getDisplayName() 2 * inputChanges.incremental >> incrementalExecution diff --git a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/ResolveChangesStepTest.groovy b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/ResolveChangesStepTest.groovy index 80e9dffd92d65..6d90e116ca32b 100644 --- a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/ResolveChangesStepTest.groovy +++ b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/ResolveChangesStepTest.groovy @@ -17,8 +17,6 @@ package org.gradle.internal.execution.steps import com.google.common.collect.ImmutableList -import com.google.common.collect.ImmutableListMultimap -import com.google.common.collect.ImmutableMultimap import com.google.common.collect.ImmutableSortedMap import org.gradle.internal.execution.IncrementalChangesContext import org.gradle.internal.execution.IncrementalContext @@ -43,11 +41,12 @@ class ResolveChangesStepTest extends StepSpec { result == delegateResult 1 * context.work >> work + 1 * work.requiresInputChanges >> false 1 * delegate.execute(_) >> { IncrementalChangesContext delegateContext -> def changes = delegateContext.changes.get() assert changes.allChangeMessages == ImmutableList.of("Forced rebuild.") try { - changes.createInputChanges(ImmutableListMultimap.of()) + changes.createInputChanges() assert false } catch (UnsupportedOperationException e) { assert e.message == 'Cannot query input changes when input tracking is disabled.' @@ -84,9 +83,10 @@ class ResolveChangesStepTest extends StepSpec { result == delegateResult 1 * context.work >> work + 1 * work.requiresInputChanges >> false 1 * delegate.execute(_) >> { IncrementalChangesContext delegateContext -> def changes = delegateContext.changes.get() - assert !changes.createInputChanges(ImmutableMultimap.of()).incremental + assert !changes.createInputChanges().incremental assert changes.allChangeMessages == ImmutableList.of("No history is available.") return delegateResult } From 50c43e2da817c80656e62a960a2b63ea5c66c028 Mon Sep 17 00:00:00 2001 From: Stefan Wolf Date: Sat, 16 Mar 2019 11:14:16 +0100 Subject: [PATCH 580/853] Move {nonI,i}ncrementalChanges to IncrementalInputProperties --- .../DefaultExecutionStateChangeDetector.java | 36 ++----------------- .../DefaultIncrementalInputProperties.java | 26 +++++++++++--- .../changes/IncrementalInputProperties.java | 32 ++++++++++++----- 3 files changed, 46 insertions(+), 48 deletions(-) diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/DefaultExecutionStateChangeDetector.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/DefaultExecutionStateChangeDetector.java index 1298f88b2f4cf..cbcbe5c1df7e8 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/DefaultExecutionStateChangeDetector.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/DefaultExecutionStateChangeDetector.java @@ -19,7 +19,6 @@ import com.google.common.collect.ImmutableCollection; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSortedMap; -import com.google.common.collect.Maps; import org.gradle.api.Describable; import org.gradle.internal.change.CachingChangeContainer; import org.gradle.internal.change.Change; @@ -30,7 +29,6 @@ import org.gradle.internal.execution.history.AfterPreviousExecutionState; import org.gradle.internal.execution.history.BeforeExecutionState; import org.gradle.internal.fingerprint.CurrentFileCollectionFingerprint; -import org.gradle.internal.fingerprint.FileCollectionFingerprint; public class DefaultExecutionStateChangeDetector implements ExecutionStateChangeDetector { @Override @@ -62,13 +60,11 @@ public ExecutionStateChanges detectChanges(AfterPreviousExecutionState lastExecu thisExecution.getInputFileProperties(), "Input file", executable); - InputFileChanges nonIncrementalInputFileChanges = nonIncrementalChanges( - incrementalInputProperties, + InputFileChanges nonIncrementalInputFileChanges = incrementalInputProperties.nonIncrementalChanges( lastExecution.getInputFileProperties(), thisExecution.getInputFileProperties() ); - InputFileChanges directIncrementalInputFileChanges = incrementalChanges( - incrementalInputProperties, + InputFileChanges directIncrementalInputFileChanges = incrementalInputProperties.incrementalChanges( lastExecution.getInputFileProperties(), thisExecution.getInputFileProperties() ); @@ -123,34 +119,6 @@ private static InputFileChanges errorHandling(Describable executable, InputFileC return new InputFileChangesWrapper(wrapped, errorHandlingChangeContainer); } - public static InputFileChanges incrementalChanges(IncrementalInputProperties incrementalInputProperties, ImmutableSortedMap previous, ImmutableSortedMap current) { - if (incrementalInputProperties == IncrementalInputProperties.NONE) { - return InputFileChanges.EMPTY; - } - if (incrementalInputProperties == IncrementalInputProperties.ALL) { - return new DefaultInputFileChanges(previous, current); - } - - return new DefaultInputFileChanges( - ImmutableSortedMap.copyOfSorted(Maps.filterKeys(previous, propertyName -> incrementalInputProperties.isIncrementalProperty(propertyName))), - ImmutableSortedMap.copyOfSorted(Maps.filterKeys(current, propertyName -> incrementalInputProperties.isIncrementalProperty(propertyName))) - ); - } - - public static InputFileChanges nonIncrementalChanges(IncrementalInputProperties incrementalInputProperties, ImmutableSortedMap previous, ImmutableSortedMap current) { - if (incrementalInputProperties == IncrementalInputProperties.NONE) { - return new DefaultInputFileChanges(previous, current); - } - if (incrementalInputProperties == IncrementalInputProperties.ALL) { - return InputFileChanges.EMPTY; - } - - return new DefaultInputFileChanges( - Maps.filterKeys(previous, propertyName -> !incrementalInputProperties.isIncrementalProperty(propertyName)), - Maps.filterKeys(current, propertyName -> !incrementalInputProperties.isIncrementalProperty(propertyName)) - ); - } - private static class InputFileChangesWrapper implements InputFileChanges { private final InputFileChanges inputFileChangesDelegate; private final ChangeContainer changeContainerDelegate; diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/DefaultIncrementalInputProperties.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/DefaultIncrementalInputProperties.java index b89472795d4fc..d5cf478dc7bb0 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/DefaultIncrementalInputProperties.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/DefaultIncrementalInputProperties.java @@ -18,7 +18,11 @@ import com.google.common.base.Joiner; import com.google.common.collect.ImmutableBiMap; +import com.google.common.collect.ImmutableSortedMap; +import com.google.common.collect.Maps; import org.gradle.api.InvalidUserDataException; +import org.gradle.internal.fingerprint.CurrentFileCollectionFingerprint; +import org.gradle.internal.fingerprint.FileCollectionFingerprint; public class DefaultIncrementalInputProperties implements IncrementalInputProperties { private final ImmutableBiMap incrementalInputProperties; @@ -27,11 +31,6 @@ public DefaultIncrementalInputProperties(ImmutableBiMap incremen this.incrementalInputProperties = incrementalInputProperties; } - @Override - public boolean isIncrementalProperty(String propertyName) { - return incrementalInputProperties.containsKey(propertyName); - } - @Override public String getPropertyNameFor(Object propertyValue) { String propertyName = incrementalInputProperties.inverse().get(propertyValue); @@ -40,4 +39,21 @@ public String getPropertyNameFor(Object propertyValue) { } return propertyName; } + + @Override + public InputFileChanges nonIncrementalChanges(ImmutableSortedMap previous, ImmutableSortedMap current) { + return new DefaultInputFileChanges( + Maps.filterKeys(previous, propertyName -> !incrementalInputProperties.containsKey(propertyName)), + Maps.filterKeys(current, propertyName -> !incrementalInputProperties.containsKey(propertyName)) + ); + + } + + @Override + public InputFileChanges incrementalChanges(ImmutableSortedMap previous, ImmutableSortedMap current) { + return new DefaultInputFileChanges( + ImmutableSortedMap.copyOfSorted(Maps.filterKeys(previous, propertyName -> incrementalInputProperties.containsKey(propertyName))), + ImmutableSortedMap.copyOfSorted(Maps.filterKeys(current, propertyName -> incrementalInputProperties.containsKey(propertyName))) + ); + } } diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/IncrementalInputProperties.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/IncrementalInputProperties.java index e9a4d69390f73..08d6083ba6c90 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/IncrementalInputProperties.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/IncrementalInputProperties.java @@ -16,33 +16,47 @@ package org.gradle.internal.execution.history.changes; +import com.google.common.collect.ImmutableSortedMap; import org.gradle.api.InvalidUserDataException; +import org.gradle.internal.fingerprint.CurrentFileCollectionFingerprint; +import org.gradle.internal.fingerprint.FileCollectionFingerprint; public interface IncrementalInputProperties { - boolean isIncrementalProperty(String propertyName); String getPropertyNameFor(Object value); + InputFileChanges nonIncrementalChanges(ImmutableSortedMap previous, ImmutableSortedMap current); + InputFileChanges incrementalChanges(ImmutableSortedMap previous, ImmutableSortedMap current); IncrementalInputProperties NONE = new IncrementalInputProperties() { @Override - public boolean isIncrementalProperty(String propertyName) { - return false; + public String getPropertyNameFor(Object value) { + throw new InvalidUserDataException("Cannot query incremental changes for property " + value + ": No incremental properties declared."); } @Override - public String getPropertyNameFor(Object value) { - throw new InvalidUserDataException("Cannot query incremental changes for property " + value + ": No incremental properties declared."); + public InputFileChanges nonIncrementalChanges(ImmutableSortedMap previous, ImmutableSortedMap current) { + return new DefaultInputFileChanges(previous, current); } - }; - IncrementalInputProperties ALL = new IncrementalInputProperties() { @Override - public boolean isIncrementalProperty(String propertyName) { - return true; + public InputFileChanges incrementalChanges(ImmutableSortedMap previous, ImmutableSortedMap current) { + return InputFileChanges.EMPTY; } + }; + IncrementalInputProperties ALL = new IncrementalInputProperties() { @Override public String getPropertyNameFor(Object value) { throw new InvalidUserDataException("Cannot query incremental changes for property " + value + ": Requires using 'InputChanges'."); } + + @Override + public InputFileChanges nonIncrementalChanges(ImmutableSortedMap previous, ImmutableSortedMap current) { + return InputFileChanges.EMPTY; + } + + @Override + public InputFileChanges incrementalChanges(ImmutableSortedMap previous, ImmutableSortedMap current) { + return new DefaultInputFileChanges(previous, current); + } }; } From a33d1b69ded847c5b99cbd7abe54ef8df0b9791a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=B3r=C3=A1nt=20Pint=C3=A9r?= Date: Fri, 15 Mar 2019 16:43:22 +0100 Subject: [PATCH 581/853] Clean local state in CacheStep --- .../command/BuildCacheCommandFactory.java | 66 +++++++------------ .../BuildCacheCommandFactoryTest.groovy | 11 ---- .../caching/internal/CacheableEntity.java | 7 -- ...IncrementalExecutionIntegrationTest.groovy | 2 +- .../gradle/internal/execution/UnitOfWork.java | 8 +++ .../internal/execution/steps/CacheStep.java | 30 +++++++-- .../execution/steps/CacheStepTest.groovy | 13 +++- 7 files changed, 67 insertions(+), 70 deletions(-) diff --git a/subprojects/build-cache-packaging/src/main/java/org/gradle/caching/internal/command/BuildCacheCommandFactory.java b/subprojects/build-cache-packaging/src/main/java/org/gradle/caching/internal/command/BuildCacheCommandFactory.java index 2d2f174452cb2..ef6e9c4c3402c 100644 --- a/subprojects/build-cache-packaging/src/main/java/org/gradle/caching/internal/command/BuildCacheCommandFactory.java +++ b/subprojects/build-cache-packaging/src/main/java/org/gradle/caching/internal/command/BuildCacheCommandFactory.java @@ -17,8 +17,6 @@ package org.gradle.caching.internal.command; import com.google.common.collect.ImmutableSortedMap; -import org.apache.commons.io.FileUtils; -import org.gradle.api.UncheckedIOException; import org.gradle.api.internal.cache.StringInterner; import org.gradle.api.logging.Logger; import org.gradle.api.logging.Logging; @@ -93,34 +91,30 @@ public BuildCacheKey getKey() { @Override public BuildCacheLoadCommand.Result load(InputStream input) throws IOException { - try { - BuildCacheEntryPacker.UnpackResult unpackResult = packer.unpack(entity, input, originMetadataFactory.createReader(entity)); - ImmutableSortedMap snapshots = snapshotUnpackedData(unpackResult.getSnapshots()); - LOGGER.info("Unpacked trees for {} from cache.", entity.getDisplayName()); - return new Result() { - @Override - public long getArtifactEntryCount() { - return unpackResult.getEntries(); - } - - @Override - public LoadMetadata getMetadata() { - return new LoadMetadata() { - @Override - public OriginMetadata getOriginMetadata() { - return unpackResult.getOriginMetadata(); - } - - @Override - public ImmutableSortedMap getResultingSnapshots() { - return snapshots; - } - }; - } - }; - } finally { - cleanLocalState(); - } + BuildCacheEntryPacker.UnpackResult unpackResult = packer.unpack(entity, input, originMetadataFactory.createReader(entity)); + ImmutableSortedMap snapshots = snapshotUnpackedData(unpackResult.getSnapshots()); + LOGGER.info("Unpacked trees for {} from cache.", entity.getDisplayName()); + return new Result() { + @Override + public long getArtifactEntryCount() { + return unpackResult.getEntries(); + } + + @Override + public LoadMetadata getMetadata() { + return new LoadMetadata() { + @Override + public OriginMetadata getOriginMetadata() { + return unpackResult.getOriginMetadata(); + } + + @Override + public ImmutableSortedMap getResultingSnapshots() { + return snapshots; + } + }; + } + }; } private ImmutableSortedMap snapshotUnpackedData(Map treeSnapshots) { @@ -158,18 +152,6 @@ private ImmutableSortedMap snapshotUnp }); return builder.build(); } - - private void cleanLocalState() { - entity.visitLocalState(localStateFile -> { - try { - if (localStateFile.exists()) { - FileUtils.forceDelete(localStateFile); - } - } catch (IOException ex) { - throw new UncheckedIOException(String.format("Failed to clean up local state files for %s: %s", entity.getDisplayName(), localStateFile), ex); - } - }); - } } private class StoreCommand implements BuildCacheStoreCommand { diff --git a/subprojects/build-cache-packaging/src/test/groovy/org/gradle/caching/internal/command/BuildCacheCommandFactoryTest.groovy b/subprojects/build-cache-packaging/src/test/groovy/org/gradle/caching/internal/command/BuildCacheCommandFactoryTest.groovy index e0e14ff33cc16..77da94db93893 100644 --- a/subprojects/build-cache-packaging/src/test/groovy/org/gradle/caching/internal/command/BuildCacheCommandFactoryTest.groovy +++ b/subprojects/build-cache-packaging/src/test/groovy/org/gradle/caching/internal/command/BuildCacheCommandFactoryTest.groovy @@ -57,8 +57,6 @@ class BuildCacheCommandFactoryTest extends Specification { @Rule TestNameTestDirectoryProvider temporaryFolder = new TestNameTestDirectoryProvider() - def localStateFile = temporaryFolder.file("local-state.txt").createFile() - def "load invokes unpacker and fingerprints trees"() { def outputFile = temporaryFolder.file("output.txt") def outputDir = temporaryFolder.file("outputDir") @@ -105,9 +103,6 @@ class BuildCacheCommandFactoryTest extends Specification { result.metadata.resultingSnapshots["outputFile"].fingerprints.keySet() == [outputFile.absolutePath] as Set result.metadata.resultingSnapshots["outputDir"].fingerprints.keySet() == [outputDir, outputDirFile]*.absolutePath as Set 0 * _ - - then: - !localStateFile.exists() } def "after failed unpacking error is propagated and output is not removed"() { @@ -133,9 +128,6 @@ class BuildCacheCommandFactoryTest extends Specification { ex.message == "unpacking error" outputFile.exists() 0 * _ - - then: - !localStateFile.exists() } def "store invokes packer"() { @@ -163,9 +155,6 @@ class BuildCacheCommandFactoryTest extends Specification { visitOutputTrees(_) >> { CacheableEntity.CacheableTreeVisitor visitor -> trees.each { visitor.visitOutputTree(it.name, it.type, it.root) } } - visitLocalState(_) >> { CacheableEntity.LocalStateVisitor visitor -> - visitor.visitLocalStateRoot(localStateFile) - } } } diff --git a/subprojects/build-cache/src/main/java/org/gradle/caching/internal/CacheableEntity.java b/subprojects/build-cache/src/main/java/org/gradle/caching/internal/CacheableEntity.java index 8ee258528f4b8..bf41a5bf23a46 100644 --- a/subprojects/build-cache/src/main/java/org/gradle/caching/internal/CacheableEntity.java +++ b/subprojects/build-cache/src/main/java/org/gradle/caching/internal/CacheableEntity.java @@ -29,15 +29,8 @@ public interface CacheableEntity extends Describable { void visitOutputTrees(CacheableTreeVisitor visitor); - void visitLocalState(LocalStateVisitor visitor); - @FunctionalInterface interface CacheableTreeVisitor { void visitOutputTree(String name, TreeType type, File root); } - - @FunctionalInterface - interface LocalStateVisitor { - void visitLocalStateRoot(File localStateRoot); - } } diff --git a/subprojects/execution/src/integTest/groovy/org/gradle/internal/execution/IncrementalExecutionIntegrationTest.groovy b/subprojects/execution/src/integTest/groovy/org/gradle/internal/execution/IncrementalExecutionIntegrationTest.groovy index df8bc9432c798..50af0e0652085 100644 --- a/subprojects/execution/src/integTest/groovy/org/gradle/internal/execution/IncrementalExecutionIntegrationTest.groovy +++ b/subprojects/execution/src/integTest/groovy/org/gradle/internal/execution/IncrementalExecutionIntegrationTest.groovy @@ -826,7 +826,7 @@ class IncrementalExecutionIntegrationTest extends Specification { } @Override - void visitLocalState(CacheableEntity.LocalStateVisitor visitor) { + void visitLocalState(UnitOfWork.LocalStateVisitor visitor) { throw new UnsupportedOperationException() } diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/UnitOfWork.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/UnitOfWork.java index d3863d354ac0f..0741b93ea7547 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/UnitOfWork.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/UnitOfWork.java @@ -25,6 +25,7 @@ import org.gradle.internal.fingerprint.CurrentFileCollectionFingerprint; import javax.annotation.Nullable; +import java.io.File; import java.time.Duration; import java.util.Optional; @@ -43,6 +44,13 @@ public interface UnitOfWork extends CacheableEntity { void visitOutputProperties(OutputPropertyVisitor visitor); + void visitLocalState(LocalStateVisitor visitor); + + @FunctionalInterface + interface LocalStateVisitor { + void visitLocalStateRoot(File localStateRoot); + } + long markExecutionTime(); CacheHandler createCacheHandler(); diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/CacheStep.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/CacheStep.java index 68d8b421663c0..35d597208baeb 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/CacheStep.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/CacheStep.java @@ -71,6 +71,7 @@ public CurrentSnapshotResult execute(IncrementalChangesContext context) { return Try.ofFailable(() -> cacheHandler.load(cacheKey -> buildCache.load(commandFactory.createLoad(cacheKey, work)))) .map(successfulLoad -> successfulLoad .map(cacheHit -> { + cleanLocalState(work); OriginMetadata originMetadata = cacheHit.getOriginMetadata(); ImmutableSortedMap finalOutputs = cacheHit.getResultingSnapshots(); return (CurrentSnapshotResult) new CurrentSnapshotResult() { @@ -101,6 +102,7 @@ public ImmutableSortedMap getFinalOutp LOGGER.warn("Failed to load cache entry for {}, cleaning outputs and falling back to (non-incremental) execution", work.getDisplayName(), loadFailure); + cleanLocalState(work); cleanOutputsAfterLoadFailure(work); Optional rebuildChanges = context.getChanges().map(changes -> changes.withEnforcedRebuild(FAILED_LOAD_REBUILD_REASON)); @@ -133,17 +135,21 @@ public UnitOfWork getWork() { }); } + private static void cleanLocalState(UnitOfWork work) { + work.visitLocalState(localStateFile -> { + try { + remove(localStateFile); + } catch (IOException ex) { + throw new UncheckedIOException(String.format("Failed to clean up local state files for %s: %s", work.getDisplayName(), localStateFile), ex); + } + }); + } + private static void cleanOutputsAfterLoadFailure(UnitOfWork work) { work.visitOutputProperties((name, type, roots) -> { for (File root : roots) { try { - if (root.exists()) { - if (root.isDirectory()) { - FileUtils.cleanDirectory(root); - } else { - FileUtils.forceDelete(root); - } - } + remove(root); } catch (IOException ex) { throw new UncheckedIOException(String.format("Failed to clean up files for tree '%s' of %s: %s", name, work.getDisplayName(), root), ex); } @@ -151,6 +157,16 @@ private static void cleanOutputsAfterLoadFailure(UnitOfWork work) { }); } + private static void remove(File root) throws IOException { + if (root.exists()) { + if (root.isDirectory()) { + FileUtils.cleanDirectory(root); + } else { + FileUtils.forceDelete(root); + } + } + } + private CurrentSnapshotResult executeAndStoreInCache(CacheHandler cacheHandler, IncrementalChangesContext context) { CurrentSnapshotResult executionResult = executeWithoutCache(context); executionResult.getOutcome().ifSuccessfulOrElse( diff --git a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/CacheStepTest.groovy b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/CacheStepTest.groovy index d521c09cb9690..425c232a59308 100644 --- a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/CacheStepTest.groovy +++ b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/CacheStepTest.groovy @@ -48,6 +48,7 @@ class CacheStepTest extends StepSpec implements FingerprinterFixture { def cacheKey = Stub(BuildCacheKey) def loadMetadata = Mock(BuildCacheCommandFactory.LoadMetadata) @Shared def rebuildChanges = Mock(ExecutionStateChanges) + def localStateFile = file("local-state.txt") << "local state" def step = new CacheStep(buildCacheController, buildCacheCommandFactory, delegate) def delegateResult = Mock(CurrentSnapshotResult) @@ -81,6 +82,7 @@ class CacheStepTest extends StepSpec implements FingerprinterFixture { then: 1 * loadMetadata.originMetadata >> cachedOriginMetadata 1 * loadMetadata.resultingSnapshots >> outputsFromCache + interaction { localStateIsRemoved() } 0 * _ } @@ -146,10 +148,9 @@ class CacheStepTest extends StepSpec implements FingerprinterFixture { visitor.visitOutputProperty("missingOutputFile", TreeType.FILE, ImmutableFileCollection.of(file("missing.txt"))) visitor.visitOutputProperty("missingOutputDir", TreeType.DIRECTORY, ImmutableFileCollection.of(file("missing"))) } - - then: loadedOutputFile.assertDoesNotExist() loadedOutputDir.assertIsEmptyDir() + interaction { localStateIsRemoved() } then: 1 * context.changes >> Optional.ofNullable(changes) @@ -190,6 +191,7 @@ class CacheStepTest extends StepSpec implements FingerprinterFixture { 1 * work.visitOutputProperties(_) >> { throw new RuntimeException("cleanup failure") } + interaction { localStateIsRemoved() } 0 * _ } @@ -262,4 +264,11 @@ class CacheStepTest extends StepSpec implements FingerprinterFixture { 1 * delegate.execute(_) >> delegateResult 0 * _ } + + private void localStateIsRemoved() { + 1 * work.visitLocalState(_) >> { UnitOfWork.LocalStateVisitor visitor -> + visitor.visitLocalStateRoot(localStateFile) + } + !localStateFile.exists() + } } From 748c7e6fed18e60c2cdd3b709d6458ae82af91ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=B3r=C3=A1nt=20Pint=C3=A9r?= Date: Sat, 16 Mar 2019 20:57:39 +0100 Subject: [PATCH 582/853] Improve upgrade documentation --- subprojects/docs/src/docs/userguide/upgrading_version_5.adoc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/subprojects/docs/src/docs/userguide/upgrading_version_5.adoc b/subprojects/docs/src/docs/userguide/upgrading_version_5.adoc index 3515f79c1703c..bf2cb42663c72 100644 --- a/subprojects/docs/src/docs/userguide/upgrading_version_5.adoc +++ b/subprojects/docs/src/docs/userguide/upgrading_version_5.adoc @@ -40,7 +40,9 @@ Some plugins will break with this new version of Gradle, for example because the ==== Using custom local build cache implementations -Using an implementation other than the default `DirectoryBuildCache` for the local build cache is now deprecated. +Using a custom build cache implementation for the local build cache is now deprecated. +The only allowed type will be `DirectoryBuildCache` going forward. +There is no change in the support for using custom build cache implementations as the remote build cache. [[changes_5.3]] == Upgrading from 5.2 and earlier From c7e0c5fdf3eaf84841435d56cb658016888e8868 Mon Sep 17 00:00:00 2001 From: Gradleware Git Bot Date: Sun, 17 Mar 2019 02:21:27 +0100 Subject: [PATCH 583/853] Publish 5.3-20190317010058+0000 --- released-versions.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/released-versions.json b/released-versions.json index 5b39f17de6ae2..2bb02953a94de 100644 --- a/released-versions.json +++ b/released-versions.json @@ -1,7 +1,7 @@ { "latestReleaseSnapshot": { - "version": "5.3-20190316012556+0000", - "buildTime": "20190316012556+0000" + "version": "5.3-20190317010058+0000", + "buildTime": "20190317010058+0000" }, "latestRc": { "version": "5.3-rc-3", From 2d906361b946fb558489f40ffd548f874757ab81 Mon Sep 17 00:00:00 2001 From: Gradleware Git Bot Date: Mon, 18 Mar 2019 02:15:32 +0100 Subject: [PATCH 584/853] Publish 5.3-20190318010052+0000 --- released-versions.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/released-versions.json b/released-versions.json index 2bb02953a94de..a2a89574fc41a 100644 --- a/released-versions.json +++ b/released-versions.json @@ -1,7 +1,7 @@ { "latestReleaseSnapshot": { - "version": "5.3-20190317010058+0000", - "buildTime": "20190317010058+0000" + "version": "5.3-20190318010052+0000", + "buildTime": "20190318010052+0000" }, "latestRc": { "version": "5.3-rc-3", From efc3f9e1bbe4980a98b1558e3dd2b714551bafad Mon Sep 17 00:00:00 2001 From: Stefan Wolf Date: Sat, 16 Mar 2019 23:29:28 +0100 Subject: [PATCH 585/853] Add test for duplicate incremental input values --- .../IncrementalInputsIntegrationTest.groovy | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/IncrementalInputsIntegrationTest.groovy b/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/IncrementalInputsIntegrationTest.groovy index 0670ffbc684d6..14dc1a754e4ab 100644 --- a/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/IncrementalInputsIntegrationTest.groovy +++ b/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/IncrementalInputsIntegrationTest.groovy @@ -63,6 +63,11 @@ class IncrementalInputsIntegrationTest extends AbstractIncrementalTasksIntegrati @InputFile File anotherIncrementalInput + @Optional + @Incremental + @InputDirectory + File anotherIncrementalInputDirectory + @Optional @InputFile File nonIncrementalInput @@ -146,4 +151,16 @@ class IncrementalInputsIntegrationTest extends AbstractIncrementalTasksIntegrati executesWithIncrementalContext("ext.modified = ['file1.txt']") } + def "two incremental inputs cannot have the same value"() { + buildFile << """ + tasks.withType(IncrementalTask).configureEach { + anotherIncrementalInputDirectory = inputDir + } + """ + + expect: + fails("incremental") + failureHasCause("Multiple entries with same key: ${file('inputs').absolutePath}=inputDir and ${file('inputs').absolutePath}=anotherIncrementalInputDirectory") + } + } From 7ca16613ad13358d6eab71c3bddb4711ae60a3b0 Mon Sep 17 00:00:00 2001 From: Paul Merlin Date: Fri, 22 Feb 2019 15:47:16 +0100 Subject: [PATCH 586/853] Minor refinements in cross-version TAPI fixtures mostly small edits and a few explaining comments Signed-off-by: Paul Merlin --- .../tooling/fixture/ToolingApi.groovy | 2 +- .../ToolingApiCompatibilitySuiteRunner.groovy | 20 +++++++++++-------- .../fixture/ToolingApiExecution.groovy | 4 ++-- .../fixture/ToolingApiSpecification.groovy | 1 + 4 files changed, 16 insertions(+), 11 deletions(-) diff --git a/subprojects/tooling-api/src/testFixtures/groovy/org/gradle/integtests/tooling/fixture/ToolingApi.groovy b/subprojects/tooling-api/src/testFixtures/groovy/org/gradle/integtests/tooling/fixture/ToolingApi.groovy index e37af9f9d6c5a..d26c350671c99 100644 --- a/subprojects/tooling-api/src/testFixtures/groovy/org/gradle/integtests/tooling/fixture/ToolingApi.groovy +++ b/subprojects/tooling-api/src/testFixtures/groovy/org/gradle/integtests/tooling/fixture/ToolingApi.groovy @@ -182,7 +182,7 @@ class ToolingApi implements TestRule { if (gradleUserHomeDir != context.gradleUserHomeDir) { // When using an isolated user home, first initialise the Gradle instance using the default user home dir - // This sets some some static state that uses files from the use home dir, such as DLLs + // This sets some static state that uses files from the user home dir, such as DLLs connector.useGradleUserHomeDir(new File(context.gradleUserHomeDir.path)) def connection = connector.connect() try { diff --git a/subprojects/tooling-api/src/testFixtures/groovy/org/gradle/integtests/tooling/fixture/ToolingApiCompatibilitySuiteRunner.groovy b/subprojects/tooling-api/src/testFixtures/groovy/org/gradle/integtests/tooling/fixture/ToolingApiCompatibilitySuiteRunner.groovy index 708dda00838e3..8de4a895016a1 100755 --- a/subprojects/tooling-api/src/testFixtures/groovy/org/gradle/integtests/tooling/fixture/ToolingApiCompatibilitySuiteRunner.groovy +++ b/subprojects/tooling-api/src/testFixtures/groovy/org/gradle/integtests/tooling/fixture/ToolingApiCompatibilitySuiteRunner.groovy @@ -21,7 +21,15 @@ import org.gradle.integtests.fixtures.executer.GradleDistribution import org.gradle.integtests.fixtures.versions.ReleasedVersionDistributions class ToolingApiCompatibilitySuiteRunner extends AbstractCompatibilityTestRunner { - static ToolingApiDistributionResolver resolver + + private static ToolingApiDistributionResolver resolver + + private static ToolingApiDistributionResolver getResolver() { + if (resolver == null) { + resolver = new ToolingApiDistributionResolver().withDefaultRepository() + } + return resolver + } ToolingApiCompatibilitySuiteRunner(Class target) { super(target) @@ -35,15 +43,9 @@ class ToolingApiCompatibilitySuiteRunner extends AbstractCompatibilityTestRunner return previousVersions.all } - private static ToolingApiDistributionResolver getResolver() { - if (resolver == null) { - resolver = new ToolingApiDistributionResolver().withDefaultRepository() - } - return resolver - } - @Override protected void createExecutionsForContext(CoverageContext coverageContext) { + // current vs. current add(new ToolingApiExecution(getResolver().resolve(current.version.version), current)) super.createExecutionsForContext(coverageContext) } @@ -54,7 +56,9 @@ class ToolingApiCompatibilitySuiteRunner extends AbstractCompatibilityTestRunner def distribution = versionedTool.distribution if (distribution.toolingApiSupported) { + // current vs. target executions.add(new ToolingApiExecution(getResolver().resolve(current.version.version), distribution)) + // target vs. current executions.add(new ToolingApiExecution(getResolver().resolve(distribution.version.version), current)) } diff --git a/subprojects/tooling-api/src/testFixtures/groovy/org/gradle/integtests/tooling/fixture/ToolingApiExecution.groovy b/subprojects/tooling-api/src/testFixtures/groovy/org/gradle/integtests/tooling/fixture/ToolingApiExecution.groovy index 45779375fff74..8cb404e3badda 100644 --- a/subprojects/tooling-api/src/testFixtures/groovy/org/gradle/integtests/tooling/fixture/ToolingApiExecution.groovy +++ b/subprojects/tooling-api/src/testFixtures/groovy/org/gradle/integtests/tooling/fixture/ToolingApiExecution.groovy @@ -58,12 +58,12 @@ class ToolingApiExecution extends AbstractMultiTestRunner.Execution implements T // Trying to use @Unroll with a tooling api runner causes NPEs in the test fixtures // Fail early with a message until we can fix this properly. Unroll unroll = testDetails.getAnnotation(Unroll) - if (unroll!=null) { + if (unroll != null) { throw new IllegalArgumentException("Cannot use @Unroll with Tooling Api tests") } if (!gradle.daemonIdleTimeoutConfigurable && OperatingSystem.current().isWindows()) { - //Older daemon don't have configurable ttl and they hung for 3 hours afterwards. + // Older daemon don't have configurable ttl and they hung for 3 hours afterwards. // This is a real problem on windows due to eager file locking and continuous CI failures. // On linux it's a lesser problem - long-lived daemons hung and steal resources but don't lock files. // So, for windows we'll only run tests against target gradle that supports ttl diff --git a/subprojects/tooling-api/src/testFixtures/groovy/org/gradle/integtests/tooling/fixture/ToolingApiSpecification.groovy b/subprojects/tooling-api/src/testFixtures/groovy/org/gradle/integtests/tooling/fixture/ToolingApiSpecification.groovy index 19af086d9de2e..2f5ee9237dfdd 100644 --- a/subprojects/tooling-api/src/testFixtures/groovy/org/gradle/integtests/tooling/fixture/ToolingApiSpecification.groovy +++ b/subprojects/tooling-api/src/testFixtures/groovy/org/gradle/integtests/tooling/fixture/ToolingApiSpecification.groovy @@ -85,6 +85,7 @@ abstract class ToolingApiSpecification extends Specification { @Rule public RuleChain chain = RuleChain.outerRule(temporaryFolder).around(temporaryDistributionFolder).around(toolingApi) + // reflectively invoked by ToolingApiCompatibilitySuiteRunner static void selectTargetDist(GradleDistribution version) { VERSION.set(version) } From 88b20d772e0ac0e58548646654539e097daf7520 Mon Sep 17 00:00:00 2001 From: Paul Merlin Date: Fri, 22 Feb 2019 16:58:58 +0100 Subject: [PATCH 587/853] Allow TAPI cross-version tests to inject additional client-side classpath Signed-off-by: Paul Merlin --- .../ToolingApiAdditionalClasspath.groovy | 36 +++++++++++++++++++ ...olingApiAdditionalClasspathProvider.groovy | 31 ++++++++++++++++ .../fixture/ToolingApiExecution.groovy | 8 +++++ 3 files changed, 75 insertions(+) create mode 100644 subprojects/tooling-api/src/testFixtures/groovy/org/gradle/integtests/tooling/fixture/ToolingApiAdditionalClasspath.groovy create mode 100644 subprojects/tooling-api/src/testFixtures/groovy/org/gradle/integtests/tooling/fixture/ToolingApiAdditionalClasspathProvider.groovy diff --git a/subprojects/tooling-api/src/testFixtures/groovy/org/gradle/integtests/tooling/fixture/ToolingApiAdditionalClasspath.groovy b/subprojects/tooling-api/src/testFixtures/groovy/org/gradle/integtests/tooling/fixture/ToolingApiAdditionalClasspath.groovy new file mode 100644 index 0000000000000..0e3841a3b7601 --- /dev/null +++ b/subprojects/tooling-api/src/testFixtures/groovy/org/gradle/integtests/tooling/fixture/ToolingApiAdditionalClasspath.groovy @@ -0,0 +1,36 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.integtests.tooling.fixture + +import java.lang.annotation.ElementType +import java.lang.annotation.Inherited +import java.lang.annotation.Retention +import java.lang.annotation.RetentionPolicy +import java.lang.annotation.Target + + +/** + * Declares the provider to use for TAPI client additional classpath. + * + * @see ToolingApiAdditionalClasspathProvider + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.TYPE) +@Inherited +@interface ToolingApiAdditionalClasspath { + Class value() +} diff --git a/subprojects/tooling-api/src/testFixtures/groovy/org/gradle/integtests/tooling/fixture/ToolingApiAdditionalClasspathProvider.groovy b/subprojects/tooling-api/src/testFixtures/groovy/org/gradle/integtests/tooling/fixture/ToolingApiAdditionalClasspathProvider.groovy new file mode 100644 index 0000000000000..18e7291596289 --- /dev/null +++ b/subprojects/tooling-api/src/testFixtures/groovy/org/gradle/integtests/tooling/fixture/ToolingApiAdditionalClasspathProvider.groovy @@ -0,0 +1,31 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.integtests.tooling.fixture + +import org.gradle.integtests.fixtures.executer.GradleDistribution + + +/** + * Provides TAPI client additional classpath. + */ +interface ToolingApiAdditionalClasspathProvider { + + /** + * Additional classpath for given target Gradle distribution to be added to the loader of the test class. + */ + List additionalClasspathFor(GradleDistribution distribution) +} diff --git a/subprojects/tooling-api/src/testFixtures/groovy/org/gradle/integtests/tooling/fixture/ToolingApiExecution.groovy b/subprojects/tooling-api/src/testFixtures/groovy/org/gradle/integtests/tooling/fixture/ToolingApiExecution.groovy index 8cb404e3badda..fcc462307392e 100644 --- a/subprojects/tooling-api/src/testFixtures/groovy/org/gradle/integtests/tooling/fixture/ToolingApiExecution.groovy +++ b/subprojects/tooling-api/src/testFixtures/groovy/org/gradle/integtests/tooling/fixture/ToolingApiExecution.groovy @@ -99,11 +99,19 @@ class ToolingApiExecution extends AbstractMultiTestRunner.Execution implements T testClassPath << ClasspathUtil.getClasspathForClass(target) testClassPath << ClasspathUtil.getClasspathForClass(TestResultHandler) + testClassPath.addAll(collectAdditionalClasspath()) + getTestClassLoader(TEST_CLASS_LOADERS, toolingApi, testClassPath) { it.allowResources(target.name.replace('.', '/')) } } + private List collectAdditionalClasspath() { + target.annotations.findAll { it instanceof ToolingApiAdditionalClasspath }.collectMany { annotation -> + (annotation as ToolingApiAdditionalClasspath).value().newInstance().additionalClasspathFor(gradle) + } + } + @Override protected void before() { def testClazz = testClassLoader.loadClass(ToolingApiSpecification.name) From 65c33d87be140a6d97bba7d88c0fc559d78278a9 Mon Sep 17 00:00:00 2001 From: Paul Merlin Date: Fri, 22 Feb 2019 17:30:20 +0100 Subject: [PATCH 588/853] Introduce KotlinBuildScriptTemplateModelCrossVersionSpec Signed-off-by: Paul Merlin --- ...inDslToolingModelsClasspathProvider.groovy | 36 ++++++++++++ ...ScriptTemplateModelCrossVersionSpec.groovy | 58 +++++++++++++++++++ .../ToolingApiAdditionalClasspath.groovy | 2 +- 3 files changed, 95 insertions(+), 1 deletion(-) create mode 100644 subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/KotlinDslToolingModelsClasspathProvider.groovy create mode 100644 subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/r41/KotlinBuildScriptTemplateModelCrossVersionSpec.groovy diff --git a/subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/KotlinDslToolingModelsClasspathProvider.groovy b/subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/KotlinDslToolingModelsClasspathProvider.groovy new file mode 100644 index 0000000000000..bbc96df8baad8 --- /dev/null +++ b/subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/KotlinDslToolingModelsClasspathProvider.groovy @@ -0,0 +1,36 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.kotlin.dsl.tooling.builders + +import org.gradle.integtests.fixtures.executer.GradleDistribution +import org.gradle.integtests.tooling.fixture.ToolingApiAdditionalClasspathProvider + + +/** + * Provides TAPI client additional classpath as found in Kotlin IDEs. + */ +class KotlinDslToolingModelsClasspathProvider implements ToolingApiAdditionalClasspathProvider { + + @Override + List additionalClasspathFor(GradleDistribution distribution) { + distribution.gradleHomeDir.file("lib").listFiles().findAll { file -> + file.name.startsWith("gradle-kotlin-dsl-tooling-models-") || file.name.startsWith("kotlin-stdlib-") + }.tap { classpath -> + assert classpath.size() >= 2 + } + } +} diff --git a/subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/r41/KotlinBuildScriptTemplateModelCrossVersionSpec.groovy b/subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/r41/KotlinBuildScriptTemplateModelCrossVersionSpec.groovy new file mode 100644 index 0000000000000..8f50b0124c87c --- /dev/null +++ b/subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/r41/KotlinBuildScriptTemplateModelCrossVersionSpec.groovy @@ -0,0 +1,58 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.kotlin.dsl.tooling.builders.r41 + +import org.gradle.integtests.tooling.fixture.TargetGradleVersion +import org.gradle.integtests.tooling.fixture.ToolingApiAdditionalClasspath +import org.gradle.integtests.tooling.fixture.ToolingApiSpecification +import org.gradle.integtests.tooling.fixture.ToolingApiVersion +import org.gradle.kotlin.dsl.tooling.builders.KotlinDslToolingModelsClasspathProvider +import org.gradle.kotlin.dsl.tooling.models.KotlinBuildScriptTemplateModel + + +@ToolingApiVersion(">=4.1") +@TargetGradleVersion(">=4.1") +@ToolingApiAdditionalClasspath(KotlinDslToolingModelsClasspathProvider) +class KotlinBuildScriptTemplateModelCrossVersionSpec extends ToolingApiSpecification { + + def "can load script template using classpath model"() { + + given: + settingsFile << "" + + when: + def model = loadToolingModel(KotlinBuildScriptTemplateModel) + + then: + loadClassesFrom( + model.classPath, + "org.gradle.kotlin.dsl.KotlinBuildScript", + "org.gradle.kotlin.dsl.resolver.KotlinBuildScriptDependenciesResolver") + } + + private static void loadClassesFrom(List classPath, String... classNames) { + classLoaderFor(classPath).withCloseable { loader -> + classNames.each { + loader.loadClass(it) + } + } + } + + private static URLClassLoader classLoaderFor(List classPath) { + new URLClassLoader(classPath.collect { it.toURI().toURL() } as URL[]) + } +} diff --git a/subprojects/tooling-api/src/testFixtures/groovy/org/gradle/integtests/tooling/fixture/ToolingApiAdditionalClasspath.groovy b/subprojects/tooling-api/src/testFixtures/groovy/org/gradle/integtests/tooling/fixture/ToolingApiAdditionalClasspath.groovy index 0e3841a3b7601..9c4ee083b405b 100644 --- a/subprojects/tooling-api/src/testFixtures/groovy/org/gradle/integtests/tooling/fixture/ToolingApiAdditionalClasspath.groovy +++ b/subprojects/tooling-api/src/testFixtures/groovy/org/gradle/integtests/tooling/fixture/ToolingApiAdditionalClasspath.groovy @@ -32,5 +32,5 @@ import java.lang.annotation.Target @Target(ElementType.TYPE) @Inherited @interface ToolingApiAdditionalClasspath { - Class value() + Class value() } From 455d2d1f85395134aab8b0d83ab67a3fb009c38b Mon Sep 17 00:00:00 2001 From: Paul Merlin Date: Tue, 26 Feb 2019 15:24:32 +0100 Subject: [PATCH 589/853] Move Kotlin DSL TAPI model tests for init scripts as cross-version tests Signed-off-by: Paul Merlin --- ...ctKotlinScriptModelCrossVersionTest.groovy | 121 ++++++++++++++++++ ...ScriptTemplateModelCrossVersionSpec.groovy | 8 +- ...tlinInitScriptModelCrossVersionSpec.groovy | 82 ++++++++++++ .../KotlinInitScriptModelIntegrationTest.kt | 50 -------- 4 files changed, 206 insertions(+), 55 deletions(-) create mode 100644 subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/AbstractKotlinScriptModelCrossVersionTest.groovy create mode 100644 subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/r41/KotlinInitScriptModelCrossVersionSpec.groovy delete mode 100644 subprojects/kotlin-dsl/src/integTest/kotlin/org/gradle/kotlin/dsl/integration/KotlinInitScriptModelIntegrationTest.kt diff --git a/subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/AbstractKotlinScriptModelCrossVersionTest.groovy b/subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/AbstractKotlinScriptModelCrossVersionTest.groovy new file mode 100644 index 0000000000000..b809d6999e738 --- /dev/null +++ b/subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/AbstractKotlinScriptModelCrossVersionTest.groovy @@ -0,0 +1,121 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.kotlin.dsl.tooling.builders + +import org.gradle.integtests.tooling.fixture.ToolingApiAdditionalClasspath +import org.gradle.integtests.tooling.fixture.ToolingApiSpecification +import org.gradle.test.fixtures.file.TestFile + +import org.gradle.kotlin.dsl.tooling.models.KotlinBuildScriptModel + +import org.hamcrest.Description +import org.hamcrest.Matcher +import org.hamcrest.TypeSafeMatcher + +import java.util.regex.Pattern + +import static org.hamcrest.CoreMatchers.hasItem +import static org.hamcrest.CoreMatchers.hasItems +import static org.junit.Assert.assertThat + + +@ToolingApiAdditionalClasspath(KotlinDslToolingModelsClasspathProvider) +abstract class AbstractKotlinScriptModelCrossVersionTest extends ToolingApiSpecification { + + def setup() { + // Required for the lenient classpath mode + toolingApi.requireDaemons() + } + + protected TestFile withDefaultSettings() { + return file("settings.gradle.kts") << "" + } + + protected TestFile withFile(String path, String text = "") { + return file(path) << text + } + + protected void withBuildSrc() { + projectDir.createFile("buildSrc/src/main/groovy/build/Foo.groovy") << """ + package build + class Foo {} + """.stripIndent() + } + + protected List canonicalClassPathFor(File projectDir, File scriptFile = null) { + return canonicalClasspathOf(kotlinBuildScriptModelFor(projectDir, scriptFile)) + } + + protected KotlinBuildScriptModel kotlinBuildScriptModelFor(File projectDir, File scriptFile = null) { + withConnector { + it.forProjectDirectory(projectDir) + } + return withConnection { + model(KotlinBuildScriptModel).tap { + setJvmArguments("-Dorg.gradle.kotlin.dsl.provider.mode=classpath") + if (scriptFile != null) { + withArguments("-Porg.gradle.kotlin.dsl.provider.script=${scriptFile.canonicalPath}") + } + }.get() + } + } + + private static List canonicalClasspathOf(KotlinBuildScriptModel model) { + return model.classPath.collect { it.canonicalFile } + } + + protected static void assertClassPathContains(List classPath, File... expectedFiles) { + assertThat( + classPath.collect { it.name }, + hasItems(fileNameSetOf(expectedFiles)) + ) + } + + private static String[] fileNameSetOf(File... files) { + return files.collect { it.name }.toSet() + } + + protected static void assertContainsGradleKotlinDslJars(List classPath) { + def version = "[0-9.]+(-.+?)?" + assertThat( + classPath.collect { it.name } as List, + hasItems( + matching("gradle-kotlin-dsl-$version\\.jar"), + matching("gradle-api-$version\\.jar"), + matching("gradle-kotlin-dsl-extensions-$version\\.jar"))) + } + + protected static Matcher> hasBuildSrc() { + hasItem("buildSrc.jar") + } + + private static Matcher matching(String pattern) { + def compiledPattern = Pattern.compile(pattern) + return new TypeSafeMatcher() { + + @Override + protected boolean matchesSafely(String item) { + return compiledPattern.matcher(item).matches() + } + + @Override + void describeTo(Description description) { + description.appendText("a string matching the pattern").appendValue(pattern) + } + } + } +} diff --git a/subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/r41/KotlinBuildScriptTemplateModelCrossVersionSpec.groovy b/subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/r41/KotlinBuildScriptTemplateModelCrossVersionSpec.groovy index 8f50b0124c87c..c0387564a8522 100644 --- a/subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/r41/KotlinBuildScriptTemplateModelCrossVersionSpec.groovy +++ b/subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/r41/KotlinBuildScriptTemplateModelCrossVersionSpec.groovy @@ -17,17 +17,15 @@ package org.gradle.kotlin.dsl.tooling.builders.r41 import org.gradle.integtests.tooling.fixture.TargetGradleVersion -import org.gradle.integtests.tooling.fixture.ToolingApiAdditionalClasspath -import org.gradle.integtests.tooling.fixture.ToolingApiSpecification import org.gradle.integtests.tooling.fixture.ToolingApiVersion -import org.gradle.kotlin.dsl.tooling.builders.KotlinDslToolingModelsClasspathProvider + +import org.gradle.kotlin.dsl.tooling.builders.AbstractKotlinScriptModelCrossVersionTest import org.gradle.kotlin.dsl.tooling.models.KotlinBuildScriptTemplateModel @ToolingApiVersion(">=4.1") @TargetGradleVersion(">=4.1") -@ToolingApiAdditionalClasspath(KotlinDslToolingModelsClasspathProvider) -class KotlinBuildScriptTemplateModelCrossVersionSpec extends ToolingApiSpecification { +class KotlinBuildScriptTemplateModelCrossVersionSpec extends AbstractKotlinScriptModelCrossVersionTest { def "can load script template using classpath model"() { diff --git a/subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/r41/KotlinInitScriptModelCrossVersionSpec.groovy b/subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/r41/KotlinInitScriptModelCrossVersionSpec.groovy new file mode 100644 index 0000000000000..e8d43e62b47bf --- /dev/null +++ b/subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/r41/KotlinInitScriptModelCrossVersionSpec.groovy @@ -0,0 +1,82 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.kotlin.dsl.tooling.builders.r41 + +import org.gradle.integtests.tooling.fixture.TargetGradleVersion +import org.gradle.integtests.tooling.fixture.ToolingApiVersion + +import org.gradle.kotlin.dsl.tooling.builders.AbstractKotlinScriptModelCrossVersionTest + +import static org.junit.Assert.assertThat +import static org.hamcrest.CoreMatchers.not + + +@ToolingApiVersion(">=4.1") +@TargetGradleVersion(">=4.1") +class KotlinInitScriptModelCrossVersionSpec extends AbstractKotlinScriptModelCrossVersionTest { + + def "initscript classpath does not include buildSrc"() { + + given: + withBuildSrc() + withDefaultSettings() + + and: + def initScript = withFile("my.init.gradle.kts") + + when: + def classPath = canonicalClassPathFor(initScript) + + then: + assertContainsGradleKotlinDslJars(classPath) + assertThat( + classPath.collect { it.name }, + not(hasBuildSrc())) + } + + def "can fetch initscript classpath in face of compilation errors"() { + + given: + withDefaultSettings() + withFile("classes.jar") + + and: + def initScript = + withFile("my.init.gradle.kts") << """ + initscript { + dependencies { + classpath(files("classes.jar")) + } + } + + val p = + """ + + when: + def classPath = canonicalClassPathFor(initScript) + + then: + assertContainsGradleKotlinDslJars(classPath) + assertClassPathContains( + classPath, + file("classes.jar")) + } + + List canonicalClassPathFor(File initScript) { + canonicalClassPathFor(projectDir, initScript) + } +} diff --git a/subprojects/kotlin-dsl/src/integTest/kotlin/org/gradle/kotlin/dsl/integration/KotlinInitScriptModelIntegrationTest.kt b/subprojects/kotlin-dsl/src/integTest/kotlin/org/gradle/kotlin/dsl/integration/KotlinInitScriptModelIntegrationTest.kt deleted file mode 100644 index af10ce428cb2e..0000000000000 --- a/subprojects/kotlin-dsl/src/integTest/kotlin/org/gradle/kotlin/dsl/integration/KotlinInitScriptModelIntegrationTest.kt +++ /dev/null @@ -1,50 +0,0 @@ -package org.gradle.kotlin.dsl.integration - -import org.hamcrest.CoreMatchers.not -import org.hamcrest.MatcherAssert.assertThat - -import org.junit.Test - - -class KotlinInitScriptModelIntegrationTest : ScriptModelIntegrationTest() { - - @Test - fun `initscript classpath does not include buildSrc`() { - - withBuildSrc() - withDefaultSettings() - - val initScript = withFile("my.init.gradle.kts") - val classPath = canonicalClassPathFor(initScript) - - assertContainsGradleKotlinDslJars(classPath) - assertThat( - classPath.map { it.name }, - not(hasBuildSrc())) - } - - @Test - fun `can fetch initscript classpath in face of compilation errors`() { - - withDefaultSettings() - withFile("classes.jar") - - val initScript = - withFile("my.init.gradle.kts", """ - initscript { - dependencies { - classpath(files("classes.jar")) - } - } - - val p = - """) - - val classPath = canonicalClassPathFor(initScript) - - assertContainsGradleKotlinDslJars(classPath) - assertClassPathContains( - classPath, - existing("classes.jar")) - } -} From 3c44ef42fec978bae5670716b8e21d0ff9ea416d Mon Sep 17 00:00:00 2001 From: Paul Merlin Date: Tue, 26 Feb 2019 18:39:12 +0100 Subject: [PATCH 590/853] Move Kotlin DSL TAPI model tests for settings scripts as cross-version tests Signed-off-by: Paul Merlin --- .../kotlin-dsl-tooling-builders.gradle.kts | 2 + ...ctKotlinScriptModelCrossVersionTest.groovy | 166 +++++++++++++++++- ...SettingsScriptModelCrossVersionSpec.groovy | 125 +++++++++++++ ...otlinSettingsScriptModelIntegrationTest.kt | 98 ----------- 4 files changed, 291 insertions(+), 100 deletions(-) create mode 100644 subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/r41/KotlinSettingsScriptModelCrossVersionSpec.groovy delete mode 100644 subprojects/kotlin-dsl/src/integTest/kotlin/org/gradle/kotlin/dsl/integration/KotlinSettingsScriptModelIntegrationTest.kt diff --git a/subprojects/kotlin-dsl-tooling-builders/kotlin-dsl-tooling-builders.gradle.kts b/subprojects/kotlin-dsl-tooling-builders/kotlin-dsl-tooling-builders.gradle.kts index 28fdc0bc8c97f..1e53667c926e6 100644 --- a/subprojects/kotlin-dsl-tooling-builders/kotlin-dsl-tooling-builders.gradle.kts +++ b/subprojects/kotlin-dsl-tooling-builders/kotlin-dsl-tooling-builders.gradle.kts @@ -40,4 +40,6 @@ dependencies { integTestImplementation(project(":kotlinDslTestFixtures")) integTestRuntimeOnly(project(":toolingApiBuilders")) + + crossVersionTestRuntimeOnly(project(":pluginDevelopment")) } diff --git a/subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/AbstractKotlinScriptModelCrossVersionTest.groovy b/subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/AbstractKotlinScriptModelCrossVersionTest.groovy index b809d6999e738..19a9d22debd0e 100644 --- a/subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/AbstractKotlinScriptModelCrossVersionTest.groovy +++ b/subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/AbstractKotlinScriptModelCrossVersionTest.groovy @@ -16,6 +16,7 @@ package org.gradle.kotlin.dsl.tooling.builders +import org.gradle.integtests.tooling.fixture.TextUtil import org.gradle.integtests.tooling.fixture.ToolingApiAdditionalClasspath import org.gradle.integtests.tooling.fixture.ToolingApiSpecification import org.gradle.test.fixtures.file.TestFile @@ -28,11 +29,27 @@ import org.hamcrest.TypeSafeMatcher import java.util.regex.Pattern +import static org.hamcrest.CoreMatchers.allOf import static org.hamcrest.CoreMatchers.hasItem import static org.hamcrest.CoreMatchers.hasItems +import static org.hamcrest.CoreMatchers.not import static org.junit.Assert.assertThat +class ProjectSourceRoots { + + final File projectDir + final List sourceSets + final List languages + + ProjectSourceRoots(File projectDir, List sourceSets, List languages) { + this.projectDir = projectDir + this.sourceSets = sourceSets + this.languages = languages + } +} + + @ToolingApiAdditionalClasspath(KotlinDslToolingModelsClasspathProvider) abstract class AbstractKotlinScriptModelCrossVersionTest extends ToolingApiSpecification { @@ -41,12 +58,36 @@ abstract class AbstractKotlinScriptModelCrossVersionTest extends ToolingApiSpeci toolingApi.requireDaemons() } + private String defaultSettingsScript = "" + + private String repositoriesBlock = """ + repositories { + gradlePluginPortal() + } + """.stripIndent() + protected TestFile withDefaultSettings() { - return file("settings.gradle.kts") << "" + return withSettings(defaultSettingsScript) + } + + protected TestFile withSettings(String script) { + return withSettingsIn(".", script) + } + + protected TestFile withDefaultSettingsIn(String baseDir) { + return withSettingsIn(baseDir, defaultSettingsScript) + } + + protected TestFile withSettingsIn(String baseDir, String script) { + return withFile("$baseDir/settings.gradle.kts", script) + } + + protected TestFile withBuildScriptIn(String baseDir, String script = "") { + return withFile("$baseDir/build.gradle.kts", script) } protected TestFile withFile(String path, String text = "") { - return file(path) << text + return file(path) << text.stripIndent() } protected void withBuildSrc() { @@ -56,10 +97,66 @@ abstract class AbstractKotlinScriptModelCrossVersionTest extends ToolingApiSpeci """.stripIndent() } + protected void withKotlinBuildSrc() { + withDefaultSettingsIn("buildSrc") + withBuildScriptIn("buildSrc", """ + plugins { + `kotlin-dsl` + } + + $repositoriesBlock + """) + } + + protected ProjectSourceRoots[] withMultiProjectKotlinBuildSrc() { + withSettingsIn("buildSrc", """ + include(":a", ":b", ":c") + """) + withFile("buildSrc/build.gradle.kts", """ + plugins { + java + `kotlin-dsl` apply false + } + + val kotlinDslProjects = listOf(project.project(":a"), project.project(":b")) + + kotlinDslProjects.forEach { + it.apply(plugin = "org.gradle.kotlin.kotlin-dsl") + } + + dependencies { + kotlinDslProjects.forEach { + "runtime"(project(it.path)) + } + } + """) + withFile("buildSrc/b/build.gradle.kts", """dependencies { implementation(project(":c")) }""") + withFile("buildSrc/c/build.gradle.kts", "plugins { java }") + + return [ + withMainSourceSetJavaIn("buildSrc"), + withMainSourceSetJavaKotlinIn("buildSrc/a"), + withMainSourceSetJavaKotlinIn("buildSrc/b"), + withMainSourceSetJavaIn("buildSrc/c") + ] + } + + protected List canonicalClassPath() { + return canonicalClassPathFor(projectDir) + } + protected List canonicalClassPathFor(File projectDir, File scriptFile = null) { return canonicalClasspathOf(kotlinBuildScriptModelFor(projectDir, scriptFile)) } + protected List classPathFor(File projectDir, File scriptFile = null) { + return kotlinBuildScriptModelFor(projectDir, scriptFile).classPath + } + + protected List sourcePathFor(File scriptFile) { + kotlinBuildScriptModelFor(projectDir, scriptFile).sourcePath + } + protected KotlinBuildScriptModel kotlinBuildScriptModelFor(File projectDir, File scriptFile = null) { withConnector { it.forProjectDirectory(projectDir) @@ -85,6 +182,25 @@ abstract class AbstractKotlinScriptModelCrossVersionTest extends ToolingApiSpeci ) } + protected void assertClassPathContains(File... expectedFiles) { + assertThat( + canonicalClassPath().collect { it.name } as List, + hasItems(fileNameSetOf(expectedFiles)) + ) + } + + protected void assertIncludes(List classPath, File... files) { + assertThat( + classPath.collect { it.name } as List, + hasItems(fileNameSetOf(*files))) + } + + protected void assertExcludes(List classPath, File... files) { + assertThat( + classPath.collect { it.name } as List, + not(hasItems(*fileNameSetOf(*files)))) + } + private static String[] fileNameSetOf(File... files) { return files.collect { it.name }.toSet() } @@ -99,10 +215,52 @@ abstract class AbstractKotlinScriptModelCrossVersionTest extends ToolingApiSpeci matching("gradle-kotlin-dsl-extensions-$version\\.jar"))) } + protected void assertContainsBuildSrc(List classPath) { + assertThat( + classPath.collect { it.name } as List, + hasBuildSrc()) + } + protected static Matcher> hasBuildSrc() { hasItem("buildSrc.jar") } + protected ProjectSourceRoots withMainSourceSetJavaIn(String projectDir) { + return new ProjectSourceRoots(file(projectDir), ["main"], ["java"]) + } + + protected ProjectSourceRoots withMainSourceSetJavaKotlinIn(String projectDir) { + return new ProjectSourceRoots(file(projectDir), ["main"], ["java", "kotlin"]) + } + + protected static Matcher> matchesProjectsSourceRoots(ProjectSourceRoots... projectSourceRoots) { + return allOf(projectSourceRoots.findAll { !it.languages.isEmpty() }.collectMany { sourceRoots -> + + def languageDirs = + sourceRoots.sourceSets.collectMany { sourceSet -> + ["java", "kotlin"].collect { language -> + def hasLanguageDir = hasLanguageDir(sourceRoots.projectDir, sourceSet, language) + if (language in sourceRoots.languages) { + hasLanguageDir + } else { + not(hasLanguageDir) + } + } + } + + def resourceDirs = + sourceRoots.sourceSets.collect { sourceSet -> + hasLanguageDir(sourceRoots.projectDir, sourceSet, "resources") + } + + languageDirs + resourceDirs + }) + } + + protected static Matcher> hasLanguageDir(File base, String set, String lang) { + return hasItem(new File(base, "src/$set/$lang")) + } + private static Matcher matching(String pattern) { def compiledPattern = Pattern.compile(pattern) return new TypeSafeMatcher() { @@ -118,4 +276,8 @@ abstract class AbstractKotlinScriptModelCrossVersionTest extends ToolingApiSpeci } } } + + protected static String normalizedPathOf(File file) { + return TextUtil.normaliseFileSeparators(file.path) + } } diff --git a/subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/r41/KotlinSettingsScriptModelCrossVersionSpec.groovy b/subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/r41/KotlinSettingsScriptModelCrossVersionSpec.groovy new file mode 100644 index 0000000000000..8ec3fc1cd0134 --- /dev/null +++ b/subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/r41/KotlinSettingsScriptModelCrossVersionSpec.groovy @@ -0,0 +1,125 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.kotlin.dsl.tooling.builders.r41 + +import org.gradle.integtests.tooling.fixture.TargetGradleVersion +import org.gradle.integtests.tooling.fixture.ToolingApiVersion + +import org.gradle.kotlin.dsl.tooling.builders.AbstractKotlinScriptModelCrossVersionTest + +import static org.junit.Assert.assertThat + + +@ToolingApiVersion(">=4.1") +@TargetGradleVersion(">=4.1") +class KotlinSettingsScriptModelCrossVersionSpec extends AbstractKotlinScriptModelCrossVersionTest { + + def "can fetch classpath of settings script"() { + + given: + withBuildSrc() + + and: + def settingsDependency = withFile("settings-dependency.jar") + def settings = withSettings(""" + buildscript { + dependencies { + classpath(files("${normalizedPathOf(settingsDependency)}")) + } + } + """) + + and: + def projectDependency = withFile("project-dependency.jar") + file("build.gradle") << """ + buildscript { + dependencies { + classpath(files("${normalizedPathOf(projectDependency)}")) + } + } + """ + + when: + def classPath = canonicalClassPathFor(projectDir, settings) + + then: + assertContainsBuildSrc(classPath) + assertContainsGradleKotlinDslJars(classPath) + assertIncludes(classPath, settingsDependency) + assertExcludes(classPath, projectDependency) + } + + def "can fetch classpath of settings script plugin"() { + + given: + withBuildSrc() + withDefaultSettings() + + and: + def settingsDependency = withFile("settings-dependency.jar", "") + def settings = withFile("my.settings.gradle.kts", """ + buildscript { + dependencies { + classpath(files("${normalizedPathOf(settingsDependency)}")) + } + } + """) + + and: + def projectDependency = withFile("project-dependency.jar", "") + withFile("build.gradle", """ + buildscript { + dependencies { + classpath(files("${normalizedPathOf(projectDependency)}")) + } + } + """) + + when: + def classPath = canonicalClassPathFor(projectDir, settings) + + then: + assertContainsBuildSrc(classPath) + assertContainsGradleKotlinDslJars(classPath) + assertIncludes(classPath, settingsDependency) + assertExcludes(classPath, projectDependency) + } + + def "sourcePath includes buildSrc source roots"() { + + given: + withKotlinBuildSrc() + def settings = withSettings("""include(":sub")""") + + expect: + assertThat( + sourcePathFor(settings), + matchesProjectsSourceRoots(withMainSourceSetJavaKotlinIn("buildSrc"))) + } + + def "sourcePath includes buildSrc project dependencies source roots"() { + + given: + def sourceRoots = withMultiProjectKotlinBuildSrc() + def settings = withSettings("""include(":sub")""") + + expect: + assertThat( + sourcePathFor(settings), + matchesProjectsSourceRoots(sourceRoots)) + } +} diff --git a/subprojects/kotlin-dsl/src/integTest/kotlin/org/gradle/kotlin/dsl/integration/KotlinSettingsScriptModelIntegrationTest.kt b/subprojects/kotlin-dsl/src/integTest/kotlin/org/gradle/kotlin/dsl/integration/KotlinSettingsScriptModelIntegrationTest.kt deleted file mode 100644 index a7d23777366a9..0000000000000 --- a/subprojects/kotlin-dsl/src/integTest/kotlin/org/gradle/kotlin/dsl/integration/KotlinSettingsScriptModelIntegrationTest.kt +++ /dev/null @@ -1,98 +0,0 @@ -package org.gradle.kotlin.dsl.integration - -import org.gradle.kotlin.dsl.fixtures.normalisedPath - -import org.gradle.test.fixtures.file.LeaksFileHandles - -import org.junit.Assert.assertThat -import org.junit.Test - - -class KotlinSettingsScriptModelIntegrationTest : ScriptModelIntegrationTest() { - - @Test - fun `can fetch classpath of settings script`() { - - withBuildSrc() - - val settingsDependency = withFile("settings-dependency.jar", "") - val settings = withSettings(""" - buildscript { - dependencies { - classpath(files("${settingsDependency.normalisedPath}")) - } - } - """) - - val projectDependency = withFile("project-dependency.jar", "") - withFile("build.gradle", """ - buildscript { - dependencies { - classpath(files("${projectDependency.normalisedPath}")) - } - } - """) - - val classPath = canonicalClassPathFor(settings) - - assertContainsBuildSrc(classPath) - assertContainsGradleKotlinDslJars(classPath) - assertIncludes(classPath, settingsDependency) - assertExcludes(classPath, projectDependency) - } - - @Test - fun `can fetch classpath of settings script plugin`() { - - withBuildSrc() - withDefaultSettings() - - val settingsDependency = withFile("settings-dependency.jar", "") - val settings = withFile("my.settings.gradle.kts", """ - buildscript { - dependencies { - classpath(files("${settingsDependency.normalisedPath}")) - } - } - """) - - val projectDependency = withFile("project-dependency.jar", "") - withFile("build.gradle", """ - buildscript { - dependencies { - classpath(files("${projectDependency.normalisedPath}")) - } - } - """) - - val classPath = canonicalClassPathFor(settings) - - assertContainsBuildSrc(classPath) - assertContainsGradleKotlinDslJars(classPath) - assertIncludes(classPath, settingsDependency) - assertExcludes(classPath, projectDependency) - } - - @Test - fun `sourcePath includes buildSrc source roots`() { - - withKotlinBuildSrc() - val settings = withSettings("""include(":sub")""") - - assertThat( - sourcePathFor(settings), - matchesProjectsSourceRoots(withMainSourceSetJavaKotlinIn("buildSrc"))) - } - - @LeaksFileHandles("Kotlin Compiler Daemon working directory") - @Test - fun `sourcePath includes buildSrc project dependencies source roots`() { - - val sourceRoots = withMultiProjectKotlinBuildSrc() - val settings = withSettings("""include(":sub")""") - - assertThat( - sourcePathFor(settings), - matchesProjectsSourceRoots(*sourceRoots)) - } -} From 09ad9515e891e5106795b990259cd5ac7cd5d0ac Mon Sep 17 00:00:00 2001 From: Paul Merlin Date: Wed, 27 Feb 2019 09:35:51 +0100 Subject: [PATCH 591/853] Split kotlin init & settings script tapi tests across supported versions Signed-off-by: Paul Merlin --- ...ctKotlinScriptModelCrossVersionTest.groovy | 2 + ...ScriptTemplateModelCrossVersionSpec.groovy | 2 - ...SettingsScriptModelCrossVersionSpec.groovy | 61 +++++++++++++++++ ...tlinInitScriptModelCrossVersionSpec.groovy | 6 +- ...SettingsScriptModelCrossVersionSpec.groovy | 51 ++++++++++++++ ...SettingsScriptModelCrossVersionSpec.groovy | 68 +------------------ 6 files changed, 118 insertions(+), 72 deletions(-) create mode 100644 subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/r44/KotlinSettingsScriptModelCrossVersionSpec.groovy rename subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/{r41 => r46}/KotlinInitScriptModelCrossVersionSpec.groovy (92%) create mode 100644 subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/r47/KotlinSettingsScriptModelCrossVersionSpec.groovy rename subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/{r41 => r48}/KotlinSettingsScriptModelCrossVersionSpec.groovy (50%) diff --git a/subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/AbstractKotlinScriptModelCrossVersionTest.groovy b/subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/AbstractKotlinScriptModelCrossVersionTest.groovy index 19a9d22debd0e..f80d5ba95d1ac 100644 --- a/subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/AbstractKotlinScriptModelCrossVersionTest.groovy +++ b/subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/AbstractKotlinScriptModelCrossVersionTest.groovy @@ -19,6 +19,7 @@ package org.gradle.kotlin.dsl.tooling.builders import org.gradle.integtests.tooling.fixture.TextUtil import org.gradle.integtests.tooling.fixture.ToolingApiAdditionalClasspath import org.gradle.integtests.tooling.fixture.ToolingApiSpecification +import org.gradle.integtests.tooling.fixture.ToolingApiVersion import org.gradle.test.fixtures.file.TestFile import org.gradle.kotlin.dsl.tooling.models.KotlinBuildScriptModel @@ -50,6 +51,7 @@ class ProjectSourceRoots { } +@ToolingApiVersion(">=4.1") @ToolingApiAdditionalClasspath(KotlinDslToolingModelsClasspathProvider) abstract class AbstractKotlinScriptModelCrossVersionTest extends ToolingApiSpecification { diff --git a/subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/r41/KotlinBuildScriptTemplateModelCrossVersionSpec.groovy b/subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/r41/KotlinBuildScriptTemplateModelCrossVersionSpec.groovy index c0387564a8522..90735b762330d 100644 --- a/subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/r41/KotlinBuildScriptTemplateModelCrossVersionSpec.groovy +++ b/subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/r41/KotlinBuildScriptTemplateModelCrossVersionSpec.groovy @@ -17,13 +17,11 @@ package org.gradle.kotlin.dsl.tooling.builders.r41 import org.gradle.integtests.tooling.fixture.TargetGradleVersion -import org.gradle.integtests.tooling.fixture.ToolingApiVersion import org.gradle.kotlin.dsl.tooling.builders.AbstractKotlinScriptModelCrossVersionTest import org.gradle.kotlin.dsl.tooling.models.KotlinBuildScriptTemplateModel -@ToolingApiVersion(">=4.1") @TargetGradleVersion(">=4.1") class KotlinBuildScriptTemplateModelCrossVersionSpec extends AbstractKotlinScriptModelCrossVersionTest { diff --git a/subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/r44/KotlinSettingsScriptModelCrossVersionSpec.groovy b/subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/r44/KotlinSettingsScriptModelCrossVersionSpec.groovy new file mode 100644 index 0000000000000..71e4c3c279e93 --- /dev/null +++ b/subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/r44/KotlinSettingsScriptModelCrossVersionSpec.groovy @@ -0,0 +1,61 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.kotlin.dsl.tooling.builders.r44 + +import org.gradle.integtests.tooling.fixture.TargetGradleVersion + +import org.gradle.kotlin.dsl.tooling.builders.AbstractKotlinScriptModelCrossVersionTest + + +@TargetGradleVersion(">=4.4") +class KotlinSettingsScriptModelCrossVersionSpec extends AbstractKotlinScriptModelCrossVersionTest { + + def "can fetch classpath of settings script"() { + + given: + withBuildSrc() + + and: + def settingsDependency = withFile("settings-dependency.jar") + def settings = withSettings(""" + buildscript { + dependencies { + classpath(files("${normalizedPathOf(settingsDependency)}")) + } + } + """) + + and: + def projectDependency = withFile("project-dependency.jar") + file("build.gradle") << """ + buildscript { + dependencies { + classpath(files("${normalizedPathOf(projectDependency)}")) + } + } + """ + + when: + def classPath = canonicalClassPathFor(projectDir, settings) + + then: + assertContainsBuildSrc(classPath) + assertContainsGradleKotlinDslJars(classPath) + assertIncludes(classPath, settingsDependency) + assertExcludes(classPath, projectDependency) + } +} diff --git a/subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/r41/KotlinInitScriptModelCrossVersionSpec.groovy b/subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/r46/KotlinInitScriptModelCrossVersionSpec.groovy similarity index 92% rename from subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/r41/KotlinInitScriptModelCrossVersionSpec.groovy rename to subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/r46/KotlinInitScriptModelCrossVersionSpec.groovy index e8d43e62b47bf..ed3f90f0ff90f 100644 --- a/subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/r41/KotlinInitScriptModelCrossVersionSpec.groovy +++ b/subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/r46/KotlinInitScriptModelCrossVersionSpec.groovy @@ -14,10 +14,9 @@ * limitations under the License. */ -package org.gradle.kotlin.dsl.tooling.builders.r41 +package org.gradle.kotlin.dsl.tooling.builders.r46 import org.gradle.integtests.tooling.fixture.TargetGradleVersion -import org.gradle.integtests.tooling.fixture.ToolingApiVersion import org.gradle.kotlin.dsl.tooling.builders.AbstractKotlinScriptModelCrossVersionTest @@ -25,8 +24,7 @@ import static org.junit.Assert.assertThat import static org.hamcrest.CoreMatchers.not -@ToolingApiVersion(">=4.1") -@TargetGradleVersion(">=4.1") +@TargetGradleVersion(">=4.6") class KotlinInitScriptModelCrossVersionSpec extends AbstractKotlinScriptModelCrossVersionTest { def "initscript classpath does not include buildSrc"() { diff --git a/subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/r47/KotlinSettingsScriptModelCrossVersionSpec.groovy b/subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/r47/KotlinSettingsScriptModelCrossVersionSpec.groovy new file mode 100644 index 0000000000000..9ee6bea264bad --- /dev/null +++ b/subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/r47/KotlinSettingsScriptModelCrossVersionSpec.groovy @@ -0,0 +1,51 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.kotlin.dsl.tooling.builders.r47 + +import org.gradle.integtests.tooling.fixture.TargetGradleVersion +import org.gradle.kotlin.dsl.tooling.builders.AbstractKotlinScriptModelCrossVersionTest + +import static org.junit.Assert.assertThat + + +@TargetGradleVersion(">=4.7") +class KotlinSettingsScriptModelCrossVersionSpec extends AbstractKotlinScriptModelCrossVersionTest { + + def "sourcePath includes buildSrc source roots"() { + + given: + withKotlinBuildSrc() + def settings = withSettings("""include(":sub")""") + + expect: + assertThat( + sourcePathFor(settings), + matchesProjectsSourceRoots(withMainSourceSetJavaKotlinIn("buildSrc"))) + } + + def "sourcePath includes buildSrc project dependencies source roots"() { + + given: + def sourceRoots = withMultiProjectKotlinBuildSrc() + def settings = withSettings("""include(":sub")""") + + expect: + assertThat( + sourcePathFor(settings), + matchesProjectsSourceRoots(sourceRoots)) + } +} diff --git a/subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/r41/KotlinSettingsScriptModelCrossVersionSpec.groovy b/subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/r48/KotlinSettingsScriptModelCrossVersionSpec.groovy similarity index 50% rename from subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/r41/KotlinSettingsScriptModelCrossVersionSpec.groovy rename to subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/r48/KotlinSettingsScriptModelCrossVersionSpec.groovy index 8ec3fc1cd0134..fbb5efd6b0764 100644 --- a/subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/r41/KotlinSettingsScriptModelCrossVersionSpec.groovy +++ b/subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/r48/KotlinSettingsScriptModelCrossVersionSpec.groovy @@ -14,55 +14,15 @@ * limitations under the License. */ -package org.gradle.kotlin.dsl.tooling.builders.r41 +package org.gradle.kotlin.dsl.tooling.builders.r48 import org.gradle.integtests.tooling.fixture.TargetGradleVersion -import org.gradle.integtests.tooling.fixture.ToolingApiVersion - import org.gradle.kotlin.dsl.tooling.builders.AbstractKotlinScriptModelCrossVersionTest -import static org.junit.Assert.assertThat - -@ToolingApiVersion(">=4.1") -@TargetGradleVersion(">=4.1") +@TargetGradleVersion(">=4.8") class KotlinSettingsScriptModelCrossVersionSpec extends AbstractKotlinScriptModelCrossVersionTest { - def "can fetch classpath of settings script"() { - - given: - withBuildSrc() - - and: - def settingsDependency = withFile("settings-dependency.jar") - def settings = withSettings(""" - buildscript { - dependencies { - classpath(files("${normalizedPathOf(settingsDependency)}")) - } - } - """) - - and: - def projectDependency = withFile("project-dependency.jar") - file("build.gradle") << """ - buildscript { - dependencies { - classpath(files("${normalizedPathOf(projectDependency)}")) - } - } - """ - - when: - def classPath = canonicalClassPathFor(projectDir, settings) - - then: - assertContainsBuildSrc(classPath) - assertContainsGradleKotlinDslJars(classPath) - assertIncludes(classPath, settingsDependency) - assertExcludes(classPath, projectDependency) - } - def "can fetch classpath of settings script plugin"() { given: @@ -98,28 +58,4 @@ class KotlinSettingsScriptModelCrossVersionSpec extends AbstractKotlinScriptMode assertIncludes(classPath, settingsDependency) assertExcludes(classPath, projectDependency) } - - def "sourcePath includes buildSrc source roots"() { - - given: - withKotlinBuildSrc() - def settings = withSettings("""include(":sub")""") - - expect: - assertThat( - sourcePathFor(settings), - matchesProjectsSourceRoots(withMainSourceSetJavaKotlinIn("buildSrc"))) - } - - def "sourcePath includes buildSrc project dependencies source roots"() { - - given: - def sourceRoots = withMultiProjectKotlinBuildSrc() - def settings = withSettings("""include(":sub")""") - - expect: - assertThat( - sourcePathFor(settings), - matchesProjectsSourceRoots(sourceRoots)) - } } From cc5973d1de7f752c355de5ec985285c4fa4aaa70 Mon Sep 17 00:00:00 2001 From: Paul Merlin Date: Thu, 28 Feb 2019 12:31:39 +0100 Subject: [PATCH 592/853] Add missing repository Signed-off-by: Paul Merlin --- .../builders/AbstractKotlinScriptModelCrossVersionTest.groovy | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/AbstractKotlinScriptModelCrossVersionTest.groovy b/subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/AbstractKotlinScriptModelCrossVersionTest.groovy index f80d5ba95d1ac..2249b14ce73a6 100644 --- a/subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/AbstractKotlinScriptModelCrossVersionTest.groovy +++ b/subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/AbstractKotlinScriptModelCrossVersionTest.groovy @@ -131,6 +131,10 @@ abstract class AbstractKotlinScriptModelCrossVersionTest extends ToolingApiSpeci "runtime"(project(it.path)) } } + + allprojects { + $repositoriesBlock + } """) withFile("buildSrc/b/build.gradle.kts", """dependencies { implementation(project(":c")) }""") withFile("buildSrc/c/build.gradle.kts", "plugins { java }") From c7139a215639921f4eac60ac635741e8a82fb506 Mon Sep 17 00:00:00 2001 From: Paul Merlin Date: Thu, 28 Feb 2019 16:37:45 +0100 Subject: [PATCH 593/853] Extract function to fetch script model with a provided tapi connector intended for usage by cross-version tests Signed-off-by: Paul Merlin --- .../resolver/KotlinBuildScriptModelRequest.kt | 148 +++++++++++------- 1 file changed, 91 insertions(+), 57 deletions(-) diff --git a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/resolver/KotlinBuildScriptModelRequest.kt b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/resolver/KotlinBuildScriptModelRequest.kt index 514d62e1645cd..20d410ea0b92a 100644 --- a/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/resolver/KotlinBuildScriptModelRequest.kt +++ b/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/resolver/KotlinBuildScriptModelRequest.kt @@ -29,6 +29,7 @@ import org.gradle.tooling.ProjectConnection import com.google.common.annotations.VisibleForTesting import java.io.File +import java.util.function.Function @VisibleForTesting @@ -69,45 +70,99 @@ typealias ModelBuilderCustomization = ModelBuilder.() -> fun fetchKotlinBuildScriptModelFor( request: KotlinBuildScriptModelRequest, modelBuilderCustomization: ModelBuilderCustomization = {} -): KotlinBuildScriptModel { +): KotlinBuildScriptModel = + + fetchKotlinBuildScriptModelFor(request.toFetchParametersWith { + setJavaHome(request.javaHome) + modelBuilderCustomization() + }) + + +@VisibleForTesting +fun fetchKotlinBuildScriptModelFor( + importedProjectDir: File, + scriptFile: File?, + connectorForProject: Function +): KotlinBuildScriptModel = - val importedProjectDir = request.projectDir - val scriptFile = request.scriptFile - ?: return fetchKotlinBuildScriptModelFrom(importedProjectDir, request, modelBuilderCustomization) + fetchKotlinBuildScriptModelFor(FetchParameters(importedProjectDir, scriptFile, connectorForProject)) - val effectiveProjectDir = buildSrcProjectDirOf(scriptFile, importedProjectDir) - ?: importedProjectDir - val scriptModel = fetchKotlinBuildScriptModelFrom(effectiveProjectDir, request, modelBuilderCustomization) - if (scriptModel.enclosingScriptProjectDir == null && hasProjectDependentClassPath(scriptFile)) { - val externalProjectRoot = projectRootOf(scriptFile, importedProjectDir) - if (externalProjectRoot != importedProjectDir) { - return fetchKotlinBuildScriptModelFrom(externalProjectRoot, request, modelBuilderCustomization) +private +data class FetchParameters( + val importedProjectDir: File, + val scriptFile: File?, + val connectorForProject: Function, + val options: List = emptyList(), + val jvmOptions: List = emptyList(), + val correlationId: String = newCorrelationId(), + val modelBuilderCustomization: ModelBuilderCustomization = {} +) + + +private +fun KotlinBuildScriptModelRequest.toFetchParametersWith(modelBuilderCustomization: ModelBuilderCustomization) = + FetchParameters( + projectDir, + scriptFile, + Function { projectDir -> connectorFor(this).forProjectDirectory(projectDir) }, + options, + jvmOptions, + correlationId, + modelBuilderCustomization + ) + + +private +fun connectorFor(request: KotlinBuildScriptModelRequest): GradleConnector = + GradleConnector.newConnector() + .useGradleFrom(request.gradleInstallation) + .useGradleUserHomeDir(request.gradleUserHome) + + +private +fun GradleConnector.useGradleFrom(gradleInstallation: GradleInstallation): GradleConnector = + gradleInstallation.run { + when (this) { + is GradleInstallation.Local -> useInstallation(dir) + is GradleInstallation.Remote -> useDistribution(uri) + is GradleInstallation.Version -> useGradleVersion(number) + GradleInstallation.Wrapper -> useBuildDistribution() } } - return scriptModel -} private -fun hasProjectDependentClassPath(scriptFile: File): Boolean = - when (kotlinScriptTypeFor(scriptFile)) { - KotlinScriptType.INIT -> false - else -> true +fun fetchKotlinBuildScriptModelFor(parameters: FetchParameters): KotlinBuildScriptModel { + + if (parameters.scriptFile == null) { + return fetchKotlinBuildScriptModelFrom(parameters.importedProjectDir, parameters) } + val effectiveProjectDir = buildSrcProjectDirOf(parameters.scriptFile, parameters.importedProjectDir) + ?: parameters.importedProjectDir + + val scriptModel = fetchKotlinBuildScriptModelFrom(effectiveProjectDir, parameters) + if (scriptModel.enclosingScriptProjectDir == null && hasProjectDependentClassPath(parameters.scriptFile)) { + val externalProjectRoot = projectRootOf(parameters.scriptFile, parameters.importedProjectDir) + if (externalProjectRoot != parameters.importedProjectDir) { + return fetchKotlinBuildScriptModelFrom(externalProjectRoot, parameters) + } + } + return scriptModel +} + private fun fetchKotlinBuildScriptModelFrom( projectDir: File, - request: KotlinBuildScriptModelRequest, - modelBuilderCustomization: ModelBuilderCustomization + parameters: FetchParameters ): KotlinBuildScriptModel = - projectConnectionFor(request, projectDir).let { connection -> + connectionForProjectDir(projectDir, parameters).let { connection -> @Suppress("ConvertTryFinallyToUseCall") try { - connection.modelBuilderFor(request).apply(modelBuilderCustomization).get() + connection.modelBuilderFor(parameters).apply(parameters.modelBuilderCustomization).get() } finally { connection.close() } @@ -115,21 +170,20 @@ fun fetchKotlinBuildScriptModelFrom( private -fun projectConnectionFor(request: KotlinBuildScriptModelRequest, projectDir: File): ProjectConnection = - connectorFor(request, projectDir).connect() +fun connectionForProjectDir(projectDir: File, parameters: FetchParameters): ProjectConnection = + parameters.connectorForProject.apply(projectDir).connect() private -fun ProjectConnection.modelBuilderFor(request: KotlinBuildScriptModelRequest) = +fun ProjectConnection.modelBuilderFor(parameters: FetchParameters) = model(KotlinBuildScriptModel::class.java).apply { - setJavaHome(request.javaHome) - setJvmArguments(request.jvmOptions + modelSpecificJvmOptions) + setJvmArguments(parameters.jvmOptions + modelSpecificJvmOptions) forTasks(kotlinBuildScriptModelTask) - val arguments = request.options.toMutableList() - arguments += "-P$kotlinBuildScriptModelCorrelationId=${request.correlationId}" + val arguments = parameters.options.toMutableList() + arguments += "-P$kotlinBuildScriptModelCorrelationId=${parameters.correlationId}" - request.scriptFile?.let { + parameters.scriptFile?.let { arguments += "-P$kotlinBuildScriptModelTarget=${it.canonicalPath}" } @@ -151,12 +205,6 @@ const val kotlinBuildScriptModelCorrelationId = "org.gradle.kotlin.dsl.provider. const val kotlinBuildScriptModelTask = "prepareKotlinBuildScriptModel" -private -fun connectorFor(request: KotlinBuildScriptModelRequest, projectDir: File): GradleConnector = - connectorFor(projectDir, request.gradleInstallation) - .useGradleUserHomeDir(request.gradleUserHome) - - private fun buildSrcProjectDirOf(scriptFile: File, importedProjectDir: File): File? = importedProjectDir.resolve("buildSrc").takeIf { buildSrc -> @@ -164,6 +212,14 @@ fun buildSrcProjectDirOf(scriptFile: File, importedProjectDir: File): File? = } +private +fun hasProjectDependentClassPath(scriptFile: File): Boolean = + when (kotlinScriptTypeFor(scriptFile)) { + KotlinScriptType.INIT -> false + else -> true + } + + internal fun projectRootOf(scriptFile: File, importedProjectRoot: File, stopAt: File? = null): File { @@ -188,25 +244,3 @@ fun projectRootOf(scriptFile: File, importedProjectRoot: File, stopAt: File? = n return test(scriptFile.parentFile) } - - -private -fun connectorFor(projectDir: File, gradleInstallation: GradleInstallation): GradleConnector = - GradleConnector - .newConnector() - .forProjectDirectory(projectDir) - .let { connector -> - applyGradleInstallationTo(connector, gradleInstallation) - } - - -private -fun applyGradleInstallationTo(connector: GradleConnector, gradleInstallation: GradleInstallation): GradleConnector = - gradleInstallation.run { - when (this) { - is GradleInstallation.Local -> connector.useInstallation(dir) - is GradleInstallation.Remote -> connector.useDistribution(uri) - is GradleInstallation.Version -> connector.useGradleVersion(number) - GradleInstallation.Wrapper -> connector.useBuildDistribution() - } - } From 272cdca946f568e6bca7f0691e4785ea5afaed67 Mon Sep 17 00:00:00 2001 From: Paul Merlin Date: Thu, 28 Feb 2019 16:38:40 +0100 Subject: [PATCH 594/853] Include kotlin provider in tapi classpath for cross-version tests from target distro, like IJ does Signed-off-by: Paul Merlin --- .../builders/KotlinDslToolingModelsClasspathProvider.groovy | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/KotlinDslToolingModelsClasspathProvider.groovy b/subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/KotlinDslToolingModelsClasspathProvider.groovy index bbc96df8baad8..34ebfa32c3574 100644 --- a/subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/KotlinDslToolingModelsClasspathProvider.groovy +++ b/subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/KotlinDslToolingModelsClasspathProvider.groovy @@ -28,9 +28,9 @@ class KotlinDslToolingModelsClasspathProvider implements ToolingApiAdditionalCla @Override List additionalClasspathFor(GradleDistribution distribution) { distribution.gradleHomeDir.file("lib").listFiles().findAll { file -> - file.name.startsWith("gradle-kotlin-dsl-tooling-models-") || file.name.startsWith("kotlin-stdlib-") + file.name.startsWith("gradle-kotlin-dsl-") || file.name.startsWith("kotlin-stdlib-") }.tap { classpath -> - assert classpath.size() >= 2 + assert classpath.size() >= 3 } } } From 71ece9314151d5bf5b5e4b7b763cb37f02dfb14f Mon Sep 17 00:00:00 2001 From: Paul Merlin Date: Thu, 28 Feb 2019 16:40:17 +0100 Subject: [PATCH 595/853] Let kotlin tapi cross-version tests use kotlin fetch function from the provider, like IJ does Signed-off-by: Paul Merlin --- ...ctKotlinScriptModelCrossVersionTest.groovy | 20 ++++++++----------- 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/AbstractKotlinScriptModelCrossVersionTest.groovy b/subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/AbstractKotlinScriptModelCrossVersionTest.groovy index 2249b14ce73a6..9ddd61a142658 100644 --- a/subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/AbstractKotlinScriptModelCrossVersionTest.groovy +++ b/subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/AbstractKotlinScriptModelCrossVersionTest.groovy @@ -30,6 +30,8 @@ import org.hamcrest.TypeSafeMatcher import java.util.regex.Pattern +import static org.gradle.kotlin.dsl.resolver.KotlinBuildScriptModelRequestKt.fetchKotlinBuildScriptModelFor + import static org.hamcrest.CoreMatchers.allOf import static org.hamcrest.CoreMatchers.hasItem import static org.hamcrest.CoreMatchers.hasItems @@ -163,18 +165,12 @@ abstract class AbstractKotlinScriptModelCrossVersionTest extends ToolingApiSpeci kotlinBuildScriptModelFor(projectDir, scriptFile).sourcePath } - protected KotlinBuildScriptModel kotlinBuildScriptModelFor(File projectDir, File scriptFile = null) { - withConnector { - it.forProjectDirectory(projectDir) - } - return withConnection { - model(KotlinBuildScriptModel).tap { - setJvmArguments("-Dorg.gradle.kotlin.dsl.provider.mode=classpath") - if (scriptFile != null) { - withArguments("-Porg.gradle.kotlin.dsl.provider.script=${scriptFile.canonicalPath}") - } - }.get() - } + private KotlinBuildScriptModel kotlinBuildScriptModelFor(File projectDir, File scriptFile = null) { + return fetchKotlinBuildScriptModelFor( + projectDir, + scriptFile, + { selectedProjectDir -> connector().forProjectDirectory(selectedProjectDir) } + ) } private static List canonicalClasspathOf(KotlinBuildScriptModel model) { From ae2f7e347d562ca94d7a3f4d1ba7e46b80663633 Mon Sep 17 00:00:00 2001 From: Paul Merlin Date: Thu, 28 Feb 2019 16:41:55 +0100 Subject: [PATCH 596/853] Let kotlin tapi x-version tests require target >= 5.3 Signed-off-by: Paul Merlin --- ...SettingsScriptModelCrossVersionSpec.groovy | 61 ----------------- ...SettingsScriptModelCrossVersionSpec.groovy | 51 --------------- ...tlinInitScriptModelCrossVersionSpec.groovy | 4 +- ...SettingsScriptModelCrossVersionSpec.groovy | 65 ++++++++++++++++++- 4 files changed, 65 insertions(+), 116 deletions(-) delete mode 100644 subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/r44/KotlinSettingsScriptModelCrossVersionSpec.groovy delete mode 100644 subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/r47/KotlinSettingsScriptModelCrossVersionSpec.groovy rename subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/{r46 => r54}/KotlinInitScriptModelCrossVersionSpec.groovy (96%) rename subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/{r48 => r54}/KotlinSettingsScriptModelCrossVersionSpec.groovy (52%) diff --git a/subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/r44/KotlinSettingsScriptModelCrossVersionSpec.groovy b/subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/r44/KotlinSettingsScriptModelCrossVersionSpec.groovy deleted file mode 100644 index 71e4c3c279e93..0000000000000 --- a/subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/r44/KotlinSettingsScriptModelCrossVersionSpec.groovy +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright 2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.gradle.kotlin.dsl.tooling.builders.r44 - -import org.gradle.integtests.tooling.fixture.TargetGradleVersion - -import org.gradle.kotlin.dsl.tooling.builders.AbstractKotlinScriptModelCrossVersionTest - - -@TargetGradleVersion(">=4.4") -class KotlinSettingsScriptModelCrossVersionSpec extends AbstractKotlinScriptModelCrossVersionTest { - - def "can fetch classpath of settings script"() { - - given: - withBuildSrc() - - and: - def settingsDependency = withFile("settings-dependency.jar") - def settings = withSettings(""" - buildscript { - dependencies { - classpath(files("${normalizedPathOf(settingsDependency)}")) - } - } - """) - - and: - def projectDependency = withFile("project-dependency.jar") - file("build.gradle") << """ - buildscript { - dependencies { - classpath(files("${normalizedPathOf(projectDependency)}")) - } - } - """ - - when: - def classPath = canonicalClassPathFor(projectDir, settings) - - then: - assertContainsBuildSrc(classPath) - assertContainsGradleKotlinDslJars(classPath) - assertIncludes(classPath, settingsDependency) - assertExcludes(classPath, projectDependency) - } -} diff --git a/subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/r47/KotlinSettingsScriptModelCrossVersionSpec.groovy b/subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/r47/KotlinSettingsScriptModelCrossVersionSpec.groovy deleted file mode 100644 index 9ee6bea264bad..0000000000000 --- a/subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/r47/KotlinSettingsScriptModelCrossVersionSpec.groovy +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright 2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.gradle.kotlin.dsl.tooling.builders.r47 - -import org.gradle.integtests.tooling.fixture.TargetGradleVersion -import org.gradle.kotlin.dsl.tooling.builders.AbstractKotlinScriptModelCrossVersionTest - -import static org.junit.Assert.assertThat - - -@TargetGradleVersion(">=4.7") -class KotlinSettingsScriptModelCrossVersionSpec extends AbstractKotlinScriptModelCrossVersionTest { - - def "sourcePath includes buildSrc source roots"() { - - given: - withKotlinBuildSrc() - def settings = withSettings("""include(":sub")""") - - expect: - assertThat( - sourcePathFor(settings), - matchesProjectsSourceRoots(withMainSourceSetJavaKotlinIn("buildSrc"))) - } - - def "sourcePath includes buildSrc project dependencies source roots"() { - - given: - def sourceRoots = withMultiProjectKotlinBuildSrc() - def settings = withSettings("""include(":sub")""") - - expect: - assertThat( - sourcePathFor(settings), - matchesProjectsSourceRoots(sourceRoots)) - } -} diff --git a/subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/r46/KotlinInitScriptModelCrossVersionSpec.groovy b/subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/r54/KotlinInitScriptModelCrossVersionSpec.groovy similarity index 96% rename from subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/r46/KotlinInitScriptModelCrossVersionSpec.groovy rename to subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/r54/KotlinInitScriptModelCrossVersionSpec.groovy index ed3f90f0ff90f..30898c4b0324c 100644 --- a/subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/r46/KotlinInitScriptModelCrossVersionSpec.groovy +++ b/subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/r54/KotlinInitScriptModelCrossVersionSpec.groovy @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.gradle.kotlin.dsl.tooling.builders.r46 +package org.gradle.kotlin.dsl.tooling.builders.r54 import org.gradle.integtests.tooling.fixture.TargetGradleVersion @@ -24,7 +24,7 @@ import static org.junit.Assert.assertThat import static org.hamcrest.CoreMatchers.not -@TargetGradleVersion(">=4.6") +@TargetGradleVersion(">=5.3") class KotlinInitScriptModelCrossVersionSpec extends AbstractKotlinScriptModelCrossVersionTest { def "initscript classpath does not include buildSrc"() { diff --git a/subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/r48/KotlinSettingsScriptModelCrossVersionSpec.groovy b/subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/r54/KotlinSettingsScriptModelCrossVersionSpec.groovy similarity index 52% rename from subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/r48/KotlinSettingsScriptModelCrossVersionSpec.groovy rename to subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/r54/KotlinSettingsScriptModelCrossVersionSpec.groovy index fbb5efd6b0764..8b6a383aa448a 100644 --- a/subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/r48/KotlinSettingsScriptModelCrossVersionSpec.groovy +++ b/subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/r54/KotlinSettingsScriptModelCrossVersionSpec.groovy @@ -14,15 +14,52 @@ * limitations under the License. */ -package org.gradle.kotlin.dsl.tooling.builders.r48 +package org.gradle.kotlin.dsl.tooling.builders.r54 import org.gradle.integtests.tooling.fixture.TargetGradleVersion import org.gradle.kotlin.dsl.tooling.builders.AbstractKotlinScriptModelCrossVersionTest +import static org.junit.Assert.assertThat -@TargetGradleVersion(">=4.8") + +@TargetGradleVersion(">=5.3") class KotlinSettingsScriptModelCrossVersionSpec extends AbstractKotlinScriptModelCrossVersionTest { + def "can fetch classpath of settings script"() { + + given: + withBuildSrc() + + and: + def settingsDependency = withFile("settings-dependency.jar") + def settings = withSettings(""" + buildscript { + dependencies { + classpath(files("${normalizedPathOf(settingsDependency)}")) + } + } + """) + + and: + def projectDependency = withFile("project-dependency.jar") + file("build.gradle") << """ + buildscript { + dependencies { + classpath(files("${normalizedPathOf(projectDependency)}")) + } + } + """ + + when: + def classPath = canonicalClassPathFor(projectDir, settings) + + then: + assertContainsBuildSrc(classPath) + assertContainsGradleKotlinDslJars(classPath) + assertIncludes(classPath, settingsDependency) + assertExcludes(classPath, projectDependency) + } + def "can fetch classpath of settings script plugin"() { given: @@ -58,4 +95,28 @@ class KotlinSettingsScriptModelCrossVersionSpec extends AbstractKotlinScriptMode assertIncludes(classPath, settingsDependency) assertExcludes(classPath, projectDependency) } + + def "sourcePath includes buildSrc source roots"() { + + given: + withKotlinBuildSrc() + def settings = withSettings("""include(":sub")""") + + expect: + assertThat( + sourcePathFor(settings), + matchesProjectsSourceRoots(withMainSourceSetJavaKotlinIn("buildSrc"))) + } + + def "sourcePath includes buildSrc project dependencies source roots"() { + + given: + def sourceRoots = withMultiProjectKotlinBuildSrc() + def settings = withSettings("""include(":sub")""") + + expect: + assertThat( + sourcePathFor(settings), + matchesProjectsSourceRoots(sourceRoots)) + } } From b5c24fdbd93a42935dd2a1d7d77cdb4e3afe345f Mon Sep 17 00:00:00 2001 From: Paul Merlin Date: Thu, 28 Feb 2019 17:25:46 +0100 Subject: [PATCH 597/853] Move Kotlin DSL TAPI model tests for build scripts as cross-version tests Signed-off-by: Paul Merlin --- ...ctKotlinScriptModelCrossVersionTest.groovy | 100 +++- ...linBuildScriptModelCrossVersionSpec.groovy | 429 ++++++++++++++++++ .../KotlinBuildScriptModelIntegrationTest.kt | 383 ---------------- .../fixture/ToolingApiSpecification.groovy | 2 +- 4 files changed, 511 insertions(+), 403 deletions(-) create mode 100644 subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/r54/KotlinBuildScriptModelCrossVersionSpec.groovy diff --git a/subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/AbstractKotlinScriptModelCrossVersionTest.groovy b/subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/AbstractKotlinScriptModelCrossVersionTest.groovy index 9ddd61a142658..082b5fcf29cea 100644 --- a/subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/AbstractKotlinScriptModelCrossVersionTest.groovy +++ b/subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/AbstractKotlinScriptModelCrossVersionTest.groovy @@ -16,6 +16,9 @@ package org.gradle.kotlin.dsl.tooling.builders +import groovy.transform.CompileStatic + +import org.gradle.api.internal.file.archive.ZipCopyAction import org.gradle.integtests.tooling.fixture.TextUtil import org.gradle.integtests.tooling.fixture.ToolingApiAdditionalClasspath import org.gradle.integtests.tooling.fixture.ToolingApiSpecification @@ -29,6 +32,8 @@ import org.hamcrest.Matcher import org.hamcrest.TypeSafeMatcher import java.util.regex.Pattern +import java.util.zip.ZipEntry +import java.util.zip.ZipOutputStream import static org.gradle.kotlin.dsl.resolver.KotlinBuildScriptModelRequestKt.fetchKotlinBuildScriptModelFor @@ -55,6 +60,7 @@ class ProjectSourceRoots { @ToolingApiVersion(">=4.1") @ToolingApiAdditionalClasspath(KotlinDslToolingModelsClasspathProvider) +@CompileStatic abstract class AbstractKotlinScriptModelCrossVersionTest extends ToolingApiSpecification { def setup() { @@ -78,7 +84,7 @@ abstract class AbstractKotlinScriptModelCrossVersionTest extends ToolingApiSpeci return withSettingsIn(".", script) } - protected TestFile withDefaultSettingsIn(String baseDir) { + private TestFile withDefaultSettingsIn(String baseDir) { return withSettingsIn(baseDir, defaultSettingsScript) } @@ -86,7 +92,11 @@ abstract class AbstractKotlinScriptModelCrossVersionTest extends ToolingApiSpeci return withFile("$baseDir/settings.gradle.kts", script) } - protected TestFile withBuildScriptIn(String baseDir, String script = "") { + protected TestFile withBuildScript(String script = "") { + return withBuildScriptIn(".", script) + } + + private TestFile withBuildScriptIn(String baseDir, String script = "") { return withFile("$baseDir/build.gradle.kts", script) } @@ -94,6 +104,38 @@ abstract class AbstractKotlinScriptModelCrossVersionTest extends ToolingApiSpeci return file(path) << text.stripIndent() } + protected TestFile withClassJar(String path, Class... classes) { + return withZip(path, classEntriesFor(classes)) + } + + // TODO rewrite invoking the kotlin impl + protected TestFile withZip(String zipPath, Iterable> entries) { + return file(zipPath).tap { zip -> + zip.parentFile.mkdirs() + new ZipOutputStream(zip.newOutputStream()).withCloseable { zos -> + entries.each { tuple -> + def path = tuple.first + def bytes = tuple.second + zos.putNextEntry(new ZipEntry(path).tap { + time = ZipCopyAction.CONSTANT_TIME_FOR_ZIP_ENTRIES + size = bytes.size() + }) + zos.write(bytes) + zos.closeEntry() + } + } + } + } + + // TODO rewrite invoking the kotlin impl + private static Iterable> classEntriesFor(Class... classes) { + + return classes.collect { clazz -> + def classFilePath = clazz.name.replace('.', '/') + ".class" + new Tuple2(classFilePath, clazz.getResource("/$classFilePath").bytes) + } + } + protected void withBuildSrc() { projectDir.createFile("buildSrc/src/main/groovy/build/Foo.groovy") << """ package build @@ -146,7 +188,7 @@ abstract class AbstractKotlinScriptModelCrossVersionTest extends ToolingApiSpeci withMainSourceSetJavaKotlinIn("buildSrc/a"), withMainSourceSetJavaKotlinIn("buildSrc/b"), withMainSourceSetJavaIn("buildSrc/c") - ] + ] as ProjectSourceRoots[] } protected List canonicalClassPath() { @@ -157,7 +199,7 @@ abstract class AbstractKotlinScriptModelCrossVersionTest extends ToolingApiSpeci return canonicalClasspathOf(kotlinBuildScriptModelFor(projectDir, scriptFile)) } - protected List classPathFor(File projectDir, File scriptFile = null) { + private List classPathFor(File projectDir, File scriptFile = null) { return kotlinBuildScriptModelFor(projectDir, scriptFile).classPath } @@ -165,7 +207,7 @@ abstract class AbstractKotlinScriptModelCrossVersionTest extends ToolingApiSpeci kotlinBuildScriptModelFor(projectDir, scriptFile).sourcePath } - private KotlinBuildScriptModel kotlinBuildScriptModelFor(File projectDir, File scriptFile = null) { + protected KotlinBuildScriptModel kotlinBuildScriptModelFor(File projectDir, File scriptFile = null) { return fetchKotlinBuildScriptModelFor( projectDir, scriptFile, @@ -173,13 +215,13 @@ abstract class AbstractKotlinScriptModelCrossVersionTest extends ToolingApiSpeci ) } - private static List canonicalClasspathOf(KotlinBuildScriptModel model) { + protected static List canonicalClasspathOf(KotlinBuildScriptModel model) { return model.classPath.collect { it.canonicalFile } } protected static void assertClassPathContains(List classPath, File... expectedFiles) { assertThat( - classPath.collect { it.name }, + classPath.collect { it.name } as List, hasItems(fileNameSetOf(expectedFiles)) ) } @@ -191,20 +233,22 @@ abstract class AbstractKotlinScriptModelCrossVersionTest extends ToolingApiSpeci ) } - protected void assertIncludes(List classPath, File... files) { + protected static void assertIncludes(List classPath, File... files) { assertThat( classPath.collect { it.name } as List, - hasItems(fileNameSetOf(*files))) + hasItems(fileNameSetOf(files)) + ) } - protected void assertExcludes(List classPath, File... files) { + protected static void assertExcludes(List classPath, File... files) { assertThat( classPath.collect { it.name } as List, - not(hasItems(*fileNameSetOf(*files)))) + not(hasItems(fileNameSetOf(files))) + ) } private static String[] fileNameSetOf(File... files) { - return files.collect { it.name }.toSet() + return files.collect { it.name }.toSet() as String[] } protected static void assertContainsGradleKotlinDslJars(List classPath) { @@ -214,20 +258,38 @@ abstract class AbstractKotlinScriptModelCrossVersionTest extends ToolingApiSpeci hasItems( matching("gradle-kotlin-dsl-$version\\.jar"), matching("gradle-api-$version\\.jar"), - matching("gradle-kotlin-dsl-extensions-$version\\.jar"))) + matching("gradle-kotlin-dsl-extensions-$version\\.jar") + ) + ) } - protected void assertContainsBuildSrc(List classPath) { + protected void assertClassPathFor( + File buildScript, + Set includes, + Set excludes, + File importedProjectDir = projectDir + ) { + def includeItems = hasItems(includes.collect { it.name } as String[]) + def excludeItems = not(hasItems(excludes.collect { it.name } as String[])) + def condition = excludes.isEmpty() ? includeItems : allOf(includeItems, excludeItems) + assertThat( + classPathFor(importedProjectDir, buildScript).collect { it.name }, + condition + ) + } + + protected static void assertContainsBuildSrc(List classPath) { assertThat( classPath.collect { it.name } as List, - hasBuildSrc()) + hasBuildSrc() + ) } protected static Matcher> hasBuildSrc() { hasItem("buildSrc.jar") } - protected ProjectSourceRoots withMainSourceSetJavaIn(String projectDir) { + private ProjectSourceRoots withMainSourceSetJavaIn(String projectDir) { return new ProjectSourceRoots(file(projectDir), ["main"], ["java"]) } @@ -247,19 +309,19 @@ abstract class AbstractKotlinScriptModelCrossVersionTest extends ToolingApiSpeci } else { not(hasLanguageDir) } - } + } as Collection } def resourceDirs = sourceRoots.sourceSets.collect { sourceSet -> hasLanguageDir(sourceRoots.projectDir, sourceSet, "resources") - } + } as Collection languageDirs + resourceDirs }) } - protected static Matcher> hasLanguageDir(File base, String set, String lang) { + private static Matcher> hasLanguageDir(File base, String set, String lang) { return hasItem(new File(base, "src/$set/$lang")) } diff --git a/subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/r54/KotlinBuildScriptModelCrossVersionSpec.groovy b/subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/r54/KotlinBuildScriptModelCrossVersionSpec.groovy new file mode 100644 index 0000000000000..9274106b7a26e --- /dev/null +++ b/subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/r54/KotlinBuildScriptModelCrossVersionSpec.groovy @@ -0,0 +1,429 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.kotlin.dsl.tooling.builders.r54 + +import groovy.transform.CompileStatic + +import org.gradle.integtests.tooling.fixture.TargetGradleVersion + +import org.gradle.kotlin.dsl.tooling.builders.AbstractKotlinScriptModelCrossVersionTest + +import static org.hamcrest.CoreMatchers.allOf +import static org.hamcrest.CoreMatchers.equalTo +import static org.hamcrest.CoreMatchers.not +import static org.hamcrest.CoreMatchers.hasItem +import static org.hamcrest.CoreMatchers.hasItems +import static org.junit.Assert.assertThat +import static org.junit.Assert.assertTrue + + +@TargetGradleVersion(">=5.3") +class KotlinBuildScriptModelCrossVersionSpec extends AbstractKotlinScriptModelCrossVersionTest { + + def "can fetch buildSrc classpath in face of compilation errors"() { + + given: + withBuildSrc() + + and: + withDefaultSettings() + withBuildScript(""" + val p = + """) + + expect: + assertContainsBuildSrc(canonicalClassPath()) + } + + def "can fetch buildSrc classpath in face of buildscript exceptions"() { + + given: + withBuildSrc() + + and: + withDefaultSettings() + withBuildScript(""" + buildscript { TODO() } + """) + + expect: + assertContainsBuildSrc(canonicalClassPath()) + } + + def "can fetch buildscript classpath in face of compilation errors"() { + + given: + projectDir.createFile("classes.jar") + settingsFile << "" + buildFileKts << """ + buildscript { + dependencies { + classpath(files("classes.jar")) + } + } + + val p = + """.stripIndent() + + expect: + assertClassPathContains( + file("classes.jar")) + } + + def "can fetch classpath in face of buildSrc test failures"() { + + given: + withKotlinBuildSrc() + withFile("buildSrc/build.gradle.kts").tap { buildSrcScript -> + buildSrcScript.text = buildSrcScript.text + """ + dependencies { + testImplementation("junit:junit:4.12") + } + """ + } + withFile("buildSrc/src/test/kotlin/FailingTest.kt", """ + class FailingTest { + @org.junit.Test fun test() { + throw Exception("BOOM") + } + } + """) + withDefaultSettings() + + expect: + assertContainsBuildSrc(canonicalClassPath()) + } + + def "can fetch buildscript classpath of top level Groovy script"() { + + given: + withBuildSrc() + + withFile("classes.jar") + + withDefaultSettings() + withFile("build.gradle", """ + buildscript { + dependencies { + classpath(files("classes.jar")) + } + } + """) + + when: + def classPath = canonicalClassPath() + + then: + assertThat( + classPath.collect { it.name } as List, + hasItems("classes.jar")) + + assertContainsBuildSrc(classPath) + + assertContainsGradleKotlinDslJars(classPath) + } + + def "can fetch buildscript classpath for sub-project script when parent has errors"() { + + given: + withSettings("""include("sub")""") + + withDefaultSettings() + withBuildScript("val p =") + + def jar = withFile("libs/jar.jar") + + def subProjectScript = + withFile("sub/build.gradle.kts", """ + buildscript { + dependencies { classpath(files("${normalizedPathOf(jar)}")) } + } + """) + + expect: + assertClassPathFor( + subProjectScript, + [jar] as Set, + [] as Set + ) + } + + def "can fetch buildscript classpath for sub-project script"() { + + expect: + assertCanFetchClassPathForSubProjectScriptIn(".") + } + + def "can fetch buildscript classpath for sub-project script of nested project"() { + + given: + withDefaultSettings() + + expect: + assertCanFetchClassPathForSubProjectScriptIn("nested-project") + } + + @CompileStatic + private void assertCanFetchClassPathForSubProjectScriptIn(String location) { + + withSettingsIn(location, "include(\"foo\", \"bar\")") + + def parentJar = withClassJar("$location/libs/parent.jar") + def fooJar = withClassJar("$location/libs/foo.jar") + def barJar = withClassJar("$location/libs/bar.jar") + + assertTrue parentJar.isFile() + assertTrue fooJar.isFile() + assertTrue barJar.isFile() + + def parentBuildScript = withFile("$location/build.gradle.kts", buildScriptDependencyOn(parentJar)) + def fooBuildScript = withFile("$location/foo/build.gradle.kts", buildScriptDependencyOn(fooJar)) + def barBuildScript = withFile("$location/bar/build.gradle.kts", buildScriptDependencyOn(barJar)) + + assertTrue parentBuildScript.text.contains(normalizedPathOf(parentJar)) + assertTrue fooBuildScript.text.contains(normalizedPathOf(fooJar)) + assertTrue barBuildScript.text.contains(normalizedPathOf(barJar)) + + assertClassPathFor( + parentBuildScript, + [parentJar] as Set, + [fooJar, barJar] as Set, + projectDir + ) + + assertClassPathFor( + fooBuildScript, + [parentJar, fooJar] as Set, + [barJar] as Set, + projectDir + ) + + assertClassPathFor( + barBuildScript, + [parentJar, barJar] as Set, + [fooJar] as Set, + projectDir + ) + } + + def "can fetch buildscript classpath for sub-project script outside root project dir"() { + + given: + def rootDependency = withClassJar("libs/root.jar") + def subDependency = withClassJar("libs/sub.jar") + + and: + withSettingsIn("root", """ + include("sub") + project(":sub").apply { + projectDir = file("../sub") + buildFileName = "sub.gradle.kts" + } + """) + file("sub").mkdirs() + + and: + def rootBuildScript = withFile("root/build.gradle", buildScriptDependencyOn(rootDependency)) + def subBuildScript = withFile("sub/sub.gradle.kts", buildScriptDependencyOn(subDependency)) + def rootProjectDir = rootBuildScript.parentFile + + expect: + assertClassPathFor( + rootBuildScript, + [rootDependency] as Set, + [subDependency] as Set, + rootProjectDir + ) + + and: + assertClassPathFor( + subBuildScript, + [rootDependency, subDependency] as Set, + [] as Set, + rootProjectDir + ) + } + + def "can fetch buildscript classpath for buildSrc sub-project script outside buildSrc root"() { + + expect: + assertCanFetchClassPathForSubProjectScriptOfNestedProjectOutsideProjectRoot("buildSrc") + } + + def "can fetch buildscript classpath for sub-project script of nested project outside nested project root"() { + + when: + // This use-case was never supported and continues not to be supported + assertCanFetchClassPathForSubProjectScriptOfNestedProjectOutsideProjectRoot("nested-project") + + then: + thrown(AssertionError) + } + + private void assertCanFetchClassPathForSubProjectScriptOfNestedProjectOutsideProjectRoot(String nestedProjectName) { + + withDefaultSettings() + + def rootDependency = withClassJar("libs/root-dep.jar") + def nestedRootDependency = withClassJar("libs/$nestedProjectName-root-dep.jar") + def nestedSubDependency = withClassJar("libs/$nestedProjectName-sub-dep.jar") + + withSettingsIn(nestedProjectName, """ + include("sub") + project(":sub").apply { + projectDir = file("../$nestedProjectName-sub") + buildFileName = "sub.gradle.kts" + } + """) + file("$nestedProjectName-sub").mkdirs() + + def rootBuildScript = withFile("build.gradle", buildScriptDependencyOn(rootDependency)) + def nestedBuildScript = withFile("$nestedProjectName/build.gradle.kts", buildScriptDependencyOn(nestedRootDependency)) + def nestedSubBuildScript = withFile("$nestedProjectName-sub/sub.gradle.kts", buildScriptDependencyOn(nestedSubDependency)) + + assertClassPathFor( + rootBuildScript, + [rootDependency] as Set, + [nestedRootDependency, nestedSubDependency] as Set + ) + + assertClassPathFor( + nestedBuildScript, + [nestedRootDependency] as Set, + [rootDependency, nestedSubDependency] as Set + ) + + assertClassPathFor( + nestedSubBuildScript, + [nestedRootDependency, nestedSubDependency] as Set, + [rootDependency] as Set + ) + } + + def "can fetch classpath of script plugin"() { + + expect: + assertCanFetchClassPathOfScriptPlugin("") + } + + def "can fetch classpath of script plugin with compilation errors"() { + + expect: + assertCanFetchClassPathOfScriptPlugin("val p = ") + } + + def "can fetch classpath of script plugin with buildscript block compilation errors"() { + + expect: + assertCanFetchClassPathOfScriptPlugin("buildscript { val p = }") + } + + private void assertCanFetchClassPathOfScriptPlugin(String scriptPluginCode) { + + withBuildSrc() + + def buildSrcDependency = + withFile("buildSrc-dependency.jar") + + withFile("buildSrc/build.gradle", """ + dependencies { compile(files("../${buildSrcDependency.name}")) } + """) + + def rootProjectDependency = withFile("rootProject-dependency.jar") + + withDefaultSettings() + withFile("build.gradle", """ + buildscript { + dependencies { classpath(files("${rootProjectDependency.name}")) } + } + """) + + def scriptPlugin = withFile("plugin.gradle.kts", scriptPluginCode) + + def scriptPluginClassPath = canonicalClassPathFor(projectDir, scriptPlugin) + assertThat( + scriptPluginClassPath.collect { it.name }, + allOf( + not(hasItem(rootProjectDependency.name)), + hasItem(buildSrcDependency.name) + ) + ) + assertContainsBuildSrc(scriptPluginClassPath) + assertContainsGradleKotlinDslJars(scriptPluginClassPath) + } + + + def "can fetch classpath of plugin portal plugin in plugins block"() { + + given: + withDefaultSettings() + withBuildScript(""" + plugins { + id("org.gradle.hello-world") version "0.2" + } + """) + + expect: + assertThat( + canonicalClassPath().collect { it.name } as List, + hasItems("gradle-hello-world-plugin-0.2.jar") + ) + } + + def "can fetch classpath of script plugin with buildscript block"() { + + given: + withDefaultSettings() + + def scriptPluginDependency = + withFile("script-plugin-dependency.jar") + + def scriptPlugin = withFile("plugin.gradle.kts", """ + buildscript { + dependencies { classpath(files("${scriptPluginDependency.name}")) } + } + + // Shouldn't be evaluated + throw IllegalStateException() + """) + + when: + def model = kotlinBuildScriptModelFor(projectDir, scriptPlugin) + + then: + assertThat( + "Script body shouldn't be evaluated", + model.exceptions, + equalTo([])) + + and: + def scriptPluginClassPath = canonicalClasspathOf(model) + assertThat( + scriptPluginClassPath.map { it.name } as List, + hasItem(scriptPluginDependency.name)) + + assertContainsGradleKotlinDslJars(scriptPluginClassPath) + } + + private static String buildScriptDependencyOn(File jar) { + return """ + buildscript { + dependencies { classpath(files("${normalizedPathOf(jar)}")) } + } + """ + } +} diff --git a/subprojects/kotlin-dsl/src/integTest/kotlin/org/gradle/kotlin/dsl/integration/KotlinBuildScriptModelIntegrationTest.kt b/subprojects/kotlin-dsl/src/integTest/kotlin/org/gradle/kotlin/dsl/integration/KotlinBuildScriptModelIntegrationTest.kt index e1e8bc41c5ae0..81b48bf5c05f0 100644 --- a/subprojects/kotlin-dsl/src/integTest/kotlin/org/gradle/kotlin/dsl/integration/KotlinBuildScriptModelIntegrationTest.kt +++ b/subprojects/kotlin-dsl/src/integTest/kotlin/org/gradle/kotlin/dsl/integration/KotlinBuildScriptModelIntegrationTest.kt @@ -1,403 +1,20 @@ package org.gradle.kotlin.dsl.integration import org.gradle.kotlin.dsl.embeddedKotlinVersion -import org.gradle.kotlin.dsl.fixtures.DeepThought import org.gradle.kotlin.dsl.fixtures.matching -import org.gradle.kotlin.dsl.fixtures.normalisedPath import org.gradle.test.fixtures.file.LeaksFileHandles -import org.hamcrest.CoreMatchers.allOf import org.hamcrest.CoreMatchers.equalTo -import org.hamcrest.CoreMatchers.hasItem import org.hamcrest.CoreMatchers.hasItems -import org.hamcrest.CoreMatchers.not import org.hamcrest.Matcher import org.hamcrest.MatcherAssert.assertThat import org.junit.Test -import java.io.File - class KotlinBuildScriptModelIntegrationTest : ScriptModelIntegrationTest() { - @Test - fun `can fetch buildSrc classpath in face of compilation errors`() { - - withBuildSrc() - - withDefaultSettings() - val buildScript = withBuildScript(""" - val p = - """) - - assertContainsBuildSrc(canonicalClassPathFor(buildScript)) - } - - @Test - fun `can fetch buildSrc classpath in face of buildscript exceptions`() { - - withBuildSrc() - - withDefaultSettings() - val buildScript = withBuildScript(""" - buildscript { TODO() } - """) - - assertContainsBuildSrc(canonicalClassPathFor(buildScript)) - } - - @Test - fun `can fetch buildscript classpath in face of compilation errors`() { - - withFile("classes.jar") - - withDefaultSettings() - val buildScript = withBuildScript(""" - buildscript { - dependencies { - classpath(files("classes.jar")) - } - } - - val p = - """) - - assertClassPathContains( - canonicalClassPathFor(buildScript), - existing("classes.jar") - ) - } - - @Test - fun `can fetch classpath in face of buildSrc test failures`() { - withKotlinBuildSrc() - existing("buildSrc/build.gradle.kts").let { buildSrcScript -> - buildSrcScript.writeText(buildSrcScript.readText() + """ - dependencies { - testImplementation("junit:junit:4.12") - } - """) - } - withFile("buildSrc/src/test/kotlin/FailingTest.kt", """ - class FailingTest { - @org.junit.Test fun test() { - throw Exception("BOOM") - } - } - """) - withDefaultSettings() - - assertContainsBuildSrc(canonicalClassPathFor(file("build.gradle.kts"))) - } - - @Test - fun `can fetch buildscript classpath of top level Groovy script`() { - - withBuildSrc() - - withFile("classes.jar", "") - - withDefaultSettings() - val buildScript = withFile("build.gradle", """ - buildscript { - dependencies { - classpath(files("classes.jar")) - } - } - """) - - val classPath = canonicalClassPathFor(buildScript) - assertThat( - classPath.map { it.name }, - hasItem("classes.jar")) - - assertContainsBuildSrc(classPath) - - assertContainsGradleKotlinDslJars(classPath) - } - - @Test - fun `can fetch buildscript classpath for sub-project script when parent has errors`() { - - withSettings("""include("sub")""") - - withDefaultSettings() - withBuildScript("val p =") - - val jar = withClassJar("libs/jar.jar") - - val subProjectScript = - withFile("sub/build.gradle.kts", """ - buildscript { - dependencies { classpath(files("${jar.normalisedPath}")) } - } - """) - - assertClassPathFor( - subProjectScript, - includes = setOf(jar), - excludes = setOf() - ) - } - - @Test - fun `can fetch buildscript classpath for sub-project script`() { - - assertCanFetchClassPathForSubProjectScriptIn(".") - } - - @Test - fun `can fetch buildscript classpath for sub-project script of nested project`() { - - withDefaultSettings() - - assertCanFetchClassPathForSubProjectScriptIn("nested-project") - } - - private - fun assertCanFetchClassPathForSubProjectScriptIn(location: String) { - withSettingsIn(location, "include(\"foo\", \"bar\")") - - fun withFixture(fixture: String) = - withClassJar("$location/libs/$fixture.jar", DeepThought::class.java) - - val parentJar = withFixture("parent") - val fooJar = withFixture("foo") - val barJar = withFixture("bar") - - val parentBuildScript = "$location/build.gradle".withBuildscriptDependencyOn(parentJar) - val fooBuildScript = "$location/foo/build.gradle.kts".withBuildscriptDependencyOn(fooJar) - val barBuildScript = "$location/bar/build.gradle.kts".withBuildscriptDependencyOn(barJar) - - assertClassPathFor( - parentBuildScript, - includes = setOf(parentJar), - excludes = setOf(fooJar, barJar) - ) - - assertClassPathFor( - fooBuildScript, - includes = setOf(parentJar, fooJar), - excludes = setOf(barJar) - ) - - assertClassPathFor( - barBuildScript, - includes = setOf(parentJar, barJar), - excludes = setOf(fooJar) - ) - } - - @Test - fun `can fetch buildscript classpath for sub-project script outside root project dir`() { - - val rootDependency = withDeepThoughtJar("libs/root.jar") - val subDependency = withDeepThoughtJar("libs/sub.jar") - - withFolders { - - "root" { - withFile("settings.gradle.kts", """ - include("sub") - project(":sub").apply { - projectDir = file("../sub") - buildFileName = "sub.gradle.kts" - } - """) - } - - "sub" { - } - } - - - val rootBuildScript = "root/build.gradle".withBuildscriptDependencyOn(rootDependency) - val subBuildScript = "sub/sub.gradle.kts".withBuildscriptDependencyOn(subDependency) - val rootProjectDir = rootBuildScript.parentFile - - assertClassPathFor( - rootBuildScript, - includes = setOf(rootDependency), - excludes = setOf(subDependency), - importedProjectDir = rootProjectDir - ) - - assertClassPathFor( - subBuildScript, - includes = setOf(rootDependency, subDependency), - excludes = emptySet(), - importedProjectDir = rootProjectDir - ) - } - - @Test - fun `can fetch buildscript classpath for buildSrc sub-project script outside buildSrc root`() { - - assertCanFetchClassPathForSubProjectScriptOfNestedProjectOutsideProjectRoot("buildSrc") - } - - @Test(expected = AssertionError::class) - fun `can fetch buildscript classpath for sub-project script of nested project outside nested project root`() { - - // This use-case was never supported and continues not to be supported - assertCanFetchClassPathForSubProjectScriptOfNestedProjectOutsideProjectRoot("nested-project") - } - - private - fun assertCanFetchClassPathForSubProjectScriptOfNestedProjectOutsideProjectRoot(nestedProjectName: String) { - withDefaultSettings() - - val rootDependency = withDeepThoughtJar("libs/root-dep.jar") - val nestedRootDependency = withDeepThoughtJar("libs/$nestedProjectName-root-dep.jar") - val nestedSubDependency = withDeepThoughtJar("libs/$nestedProjectName-sub-dep.jar") - - withFolders { - nestedProjectName { - withFile("settings.gradle.kts", """ - include("sub") - project(":sub").apply { - projectDir = file("../$nestedProjectName-sub") - buildFileName = "sub.gradle.kts" - } - """) - } - - "$nestedProjectName-sub" { - } - } - - - val rootBuildScript = "build.gradle".withBuildscriptDependencyOn(rootDependency) - val nestedBuildScript = "$nestedProjectName/build.gradle.kts".withBuildscriptDependencyOn(nestedRootDependency) - val nestedSubBuildScript = "$nestedProjectName-sub/sub.gradle.kts".withBuildscriptDependencyOn(nestedSubDependency) - - assertClassPathFor( - rootBuildScript, - includes = setOf(rootDependency), - excludes = setOf(nestedRootDependency, nestedSubDependency) - ) - - assertClassPathFor( - nestedBuildScript, - includes = setOf(nestedRootDependency), - excludes = setOf(rootDependency, nestedSubDependency) - ) - - assertClassPathFor( - nestedSubBuildScript, - includes = setOf(nestedRootDependency, nestedSubDependency), - excludes = setOf(rootDependency) - ) - } - - private - fun String.withBuildscriptDependencyOn(file: File) = - withFile(this, """ - buildscript { - dependencies { classpath(files("${file.normalisedPath}")) } - } - """) - - @Test - fun `can fetch classpath of script plugin`() { - - assertCanFetchClassPathOfScriptPlugin("") - } - - @Test - fun `can fetch classpath of script plugin with compilation errors`() { - - assertCanFetchClassPathOfScriptPlugin("val p = ") - } - - @Test - fun `can fetch classpath of script plugin with buildscript block compilation errors`() { - - withDefaultSettings() - assertCanFetchClassPathOfScriptPlugin("buildscript { val p = }") - } - - private - fun assertCanFetchClassPathOfScriptPlugin(scriptPluginCode: String) { - withBuildSrc() - - val buildSrcDependency = - withFile("buildSrc-dependency.jar") - - withFile("buildSrc/build.gradle", """ - dependencies { compile(files("../${buildSrcDependency.name}")) } - """) - - val rootProjectDependency = withFile("rootProject-dependency.jar") - - withDefaultSettings() - withFile("build.gradle", """ - buildscript { - dependencies { classpath(files("${rootProjectDependency.name}")) } - } - """) - - val scriptPlugin = withFile("plugin.gradle.kts", scriptPluginCode) - - val scriptPluginClassPath = canonicalClassPathFor(scriptPlugin) - assertThat( - scriptPluginClassPath.map { it.name }, - allOf( - not(hasItem(rootProjectDependency.name)), - hasItem(buildSrcDependency.name) - ) - ) - assertContainsBuildSrc(scriptPluginClassPath) - assertContainsGradleKotlinDslJars(scriptPluginClassPath) - } - - @Test - fun `can fetch classpath of script plugin with buildscript block`() { - - withDefaultSettings() - - val scriptPluginDependency = - withFile("script-plugin-dependency.jar") - - val scriptPlugin = withFile("plugin.gradle.kts", """ - buildscript { - dependencies { classpath(files("${scriptPluginDependency.name}")) } - } - - // Shouldn't be evaluated - throw IllegalStateException() - """) - - val model = kotlinBuildScriptModelFor(scriptPlugin) - assertThat( - "Script body shouldn't be evaluated", - model.exceptions, - equalTo(emptyList())) - - val scriptPluginClassPath = model.canonicalClassPath - assertThat( - scriptPluginClassPath.map { it.name }, - hasItem(scriptPluginDependency.name)) - - assertContainsGradleKotlinDslJars(scriptPluginClassPath) - } - - @Test - fun `can fetch classpath of plugin portal plugin in plugins block`() { - withDefaultSettings() - val buildScript = withBuildScript(""" - plugins { - id("org.gradle.hello-world") version "0.2" - } - """) - - assertThat( - canonicalClassPathFor(buildScript).map { it.name }, - hasItems("gradle-hello-world-plugin-0.2.jar")) - } - @Test fun `sourcePath includes Gradle sources`() { diff --git a/subprojects/tooling-api/src/testFixtures/groovy/org/gradle/integtests/tooling/fixture/ToolingApiSpecification.groovy b/subprojects/tooling-api/src/testFixtures/groovy/org/gradle/integtests/tooling/fixture/ToolingApiSpecification.groovy index 2f5ee9237dfdd..20be71327c94e 100644 --- a/subprojects/tooling-api/src/testFixtures/groovy/org/gradle/integtests/tooling/fixture/ToolingApiSpecification.groovy +++ b/subprojects/tooling-api/src/testFixtures/groovy/org/gradle/integtests/tooling/fixture/ToolingApiSpecification.groovy @@ -156,7 +156,7 @@ abstract class ToolingApiSpecification extends Specification { } } - def connector() { + GradleConnector connector() { toolingApi.connector() } From 47ef946bfacf2c36b0daf359a6bd7b2c6df5c8d8 Mon Sep 17 00:00:00 2001 From: Paul Merlin Date: Thu, 28 Feb 2019 17:37:24 +0100 Subject: [PATCH 598/853] @LeaksFileHandles("Kotlin compiler daemon on buildSrc jar") Signed-off-by: Paul Merlin --- .../r54/KotlinBuildScriptModelCrossVersionSpec.groovy | 2 ++ .../r54/KotlinSettingsScriptModelCrossVersionSpec.groovy | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/r54/KotlinBuildScriptModelCrossVersionSpec.groovy b/subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/r54/KotlinBuildScriptModelCrossVersionSpec.groovy index 9274106b7a26e..6c0e301bd26f7 100644 --- a/subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/r54/KotlinBuildScriptModelCrossVersionSpec.groovy +++ b/subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/r54/KotlinBuildScriptModelCrossVersionSpec.groovy @@ -19,6 +19,7 @@ package org.gradle.kotlin.dsl.tooling.builders.r54 import groovy.transform.CompileStatic import org.gradle.integtests.tooling.fixture.TargetGradleVersion +import org.gradle.test.fixtures.file.LeaksFileHandles import org.gradle.kotlin.dsl.tooling.builders.AbstractKotlinScriptModelCrossVersionTest @@ -84,6 +85,7 @@ class KotlinBuildScriptModelCrossVersionSpec extends AbstractKotlinScriptModelCr file("classes.jar")) } + @LeaksFileHandles("Kotlin compiler daemon on buildSrc jar") def "can fetch classpath in face of buildSrc test failures"() { given: diff --git a/subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/r54/KotlinSettingsScriptModelCrossVersionSpec.groovy b/subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/r54/KotlinSettingsScriptModelCrossVersionSpec.groovy index 8b6a383aa448a..7b95a24ed27de 100644 --- a/subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/r54/KotlinSettingsScriptModelCrossVersionSpec.groovy +++ b/subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/r54/KotlinSettingsScriptModelCrossVersionSpec.groovy @@ -17,6 +17,8 @@ package org.gradle.kotlin.dsl.tooling.builders.r54 import org.gradle.integtests.tooling.fixture.TargetGradleVersion +import org.gradle.test.fixtures.file.LeaksFileHandles + import org.gradle.kotlin.dsl.tooling.builders.AbstractKotlinScriptModelCrossVersionTest import static org.junit.Assert.assertThat @@ -96,6 +98,7 @@ class KotlinSettingsScriptModelCrossVersionSpec extends AbstractKotlinScriptMode assertExcludes(classPath, projectDependency) } + @LeaksFileHandles("Kotlin compiler daemon on buildSrc jar") def "sourcePath includes buildSrc source roots"() { given: @@ -108,6 +111,7 @@ class KotlinSettingsScriptModelCrossVersionSpec extends AbstractKotlinScriptMode matchesProjectsSourceRoots(withMainSourceSetJavaKotlinIn("buildSrc"))) } + @LeaksFileHandles("Kotlin compiler daemon on buildSrc jar") def "sourcePath includes buildSrc project dependencies source roots"() { given: From 957c12bc0e037472e57d433f1b084eb8774014dc Mon Sep 17 00:00:00 2001 From: Paul Merlin Date: Thu, 28 Feb 2019 17:45:42 +0100 Subject: [PATCH 599/853] Fix test Signed-off-by: Paul Merlin --- .../builders/r54/KotlinBuildScriptModelCrossVersionSpec.groovy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/r54/KotlinBuildScriptModelCrossVersionSpec.groovy b/subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/r54/KotlinBuildScriptModelCrossVersionSpec.groovy index 6c0e301bd26f7..7bc0619e9926a 100644 --- a/subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/r54/KotlinBuildScriptModelCrossVersionSpec.groovy +++ b/subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/r54/KotlinBuildScriptModelCrossVersionSpec.groovy @@ -415,7 +415,7 @@ class KotlinBuildScriptModelCrossVersionSpec extends AbstractKotlinScriptModelCr and: def scriptPluginClassPath = canonicalClasspathOf(model) assertThat( - scriptPluginClassPath.map { it.name } as List, + scriptPluginClassPath.collect { it.name } as List, hasItem(scriptPluginDependency.name)) assertContainsGradleKotlinDslJars(scriptPluginClassPath) From 723a4d0c62c39f6a00d9ea18db6885c55ca779f9 Mon Sep 17 00:00:00 2001 From: Paul Merlin Date: Thu, 28 Feb 2019 18:33:05 +0100 Subject: [PATCH 600/853] Move Kotlin DSL TAPI model tests for build scripts as cross-version tests Signed-off-by: Paul Merlin --- ...ctKotlinScriptModelCrossVersionTest.groovy | 19 ++- ...linBuildScriptModelCrossVersionSpec.groovy | 143 ++++++++++++++++ .../AccessorsClassPathIntegrationTest.kt | 5 +- .../KotlinBuildScriptModelIntegrationTest.kt | 152 ----------------- .../integration/ScriptModelIntegrationTest.kt | 158 ------------------ 5 files changed, 161 insertions(+), 316 deletions(-) delete mode 100644 subprojects/kotlin-dsl/src/integTest/kotlin/org/gradle/kotlin/dsl/integration/KotlinBuildScriptModelIntegrationTest.kt delete mode 100644 subprojects/kotlin-dsl/src/integTest/kotlin/org/gradle/kotlin/dsl/integration/ScriptModelIntegrationTest.kt diff --git a/subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/AbstractKotlinScriptModelCrossVersionTest.groovy b/subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/AbstractKotlinScriptModelCrossVersionTest.groovy index 082b5fcf29cea..50c974354e0dc 100644 --- a/subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/AbstractKotlinScriptModelCrossVersionTest.groovy +++ b/subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/AbstractKotlinScriptModelCrossVersionTest.groovy @@ -23,6 +23,7 @@ import org.gradle.integtests.tooling.fixture.TextUtil import org.gradle.integtests.tooling.fixture.ToolingApiAdditionalClasspath import org.gradle.integtests.tooling.fixture.ToolingApiSpecification import org.gradle.integtests.tooling.fixture.ToolingApiVersion +import org.gradle.test.fixtures.archive.JarTestFixture import org.gradle.test.fixtures.file.TestFile import org.gradle.kotlin.dsl.tooling.models.KotlinBuildScriptModel @@ -70,12 +71,24 @@ abstract class AbstractKotlinScriptModelCrossVersionTest extends ToolingApiSpeci private String defaultSettingsScript = "" - private String repositoriesBlock = """ + protected String repositoriesBlock = """ repositories { gradlePluginPortal() } """.stripIndent() + private String targetKotlinVersion + + protected String getTargetKotlinVersion() { + if (targetKotlinVersion == null) { + def props = new JarTestFixture(targetDist.gradleHomeDir.file("lib").listFiles().find { + it.name.startsWith("gradle-kotlin-dsl-${targetVersion.baseVersion.version}") + }).content("gradle-kotlin-dsl-versions.properties") + targetKotlinVersion = new Properties().tap { load(new StringReader(props)) }.getProperty("kotlin") + } + return targetKotlinVersion + } + protected TestFile withDefaultSettings() { return withSettings(defaultSettingsScript) } @@ -96,7 +109,7 @@ abstract class AbstractKotlinScriptModelCrossVersionTest extends ToolingApiSpeci return withBuildScriptIn(".", script) } - private TestFile withBuildScriptIn(String baseDir, String script = "") { + protected TestFile withBuildScriptIn(String baseDir, String script = "") { return withFile("$baseDir/build.gradle.kts", script) } @@ -325,7 +338,7 @@ abstract class AbstractKotlinScriptModelCrossVersionTest extends ToolingApiSpeci return hasItem(new File(base, "src/$set/$lang")) } - private static Matcher matching(String pattern) { + protected static Matcher matching(String pattern) { def compiledPattern = Pattern.compile(pattern) return new TypeSafeMatcher() { diff --git a/subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/r54/KotlinBuildScriptModelCrossVersionSpec.groovy b/subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/r54/KotlinBuildScriptModelCrossVersionSpec.groovy index 7bc0619e9926a..42c9ced605efa 100644 --- a/subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/r54/KotlinBuildScriptModelCrossVersionSpec.groovy +++ b/subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/r54/KotlinBuildScriptModelCrossVersionSpec.groovy @@ -23,6 +23,8 @@ import org.gradle.test.fixtures.file.LeaksFileHandles import org.gradle.kotlin.dsl.tooling.builders.AbstractKotlinScriptModelCrossVersionTest +import org.hamcrest.Matcher + import static org.hamcrest.CoreMatchers.allOf import static org.hamcrest.CoreMatchers.equalTo import static org.hamcrest.CoreMatchers.not @@ -421,6 +423,147 @@ class KotlinBuildScriptModelCrossVersionSpec extends AbstractKotlinScriptModelCr assertContainsGradleKotlinDslJars(scriptPluginClassPath) } + def "sourcePath includes Gradle sources"() { + + expect: + assertSourcePathIncludesGradleSourcesGiven("", "") + } + + def "sourcePath includes kotlin-stdlib sources resolved against project"() { + + expect: + assertSourcePathIncludesKotlinStdlibSourcesGiven( + "", + "buildscript { $repositoriesBlock }" + ) + } + + def "sourcePath includes kotlin-stdlib sources resolved against project hierarchy"() { + + expect: + assertSourcePathIncludesKotlinStdlibSourcesGiven( + "buildscript { $repositoriesBlock }", + "" + ) + } + + def "sourcePath includes buildscript classpath sources resolved against project"() { + + expect: + assertSourcePathIncludesKotlinPluginSourcesGiven( + "", + """ + buildscript { + dependencies { classpath(embeddedKotlin("gradle-plugin")) } + $repositoriesBlock + } + """ + ) + } + + def "sourcePath includes buildscript classpath sources resolved against project hierarchy"() { + + expect: + assertSourcePathIncludesKotlinPluginSourcesGiven( + """ + buildscript { + dependencies { classpath(embeddedKotlin("gradle-plugin")) } + $repositoriesBlock + } + """, + "" + ) + } + + def "sourcePath includes plugins classpath sources resolved against project"() { + + expect: + assertSourcePathIncludesKotlinPluginSourcesGiven( + "", + """ plugins { kotlin("jvm") version "$targetKotlinVersion" } """ + ) + } + + @LeaksFileHandles("Kotlin compiler daemon on buildSrc jar") + def "sourcePath includes buildSrc source roots"() { + + given: + withKotlinBuildSrc() + withSettings("""include(":sub")""") + + expect: + assertThat( + sourcePathFor(withFile("sub/build.gradle.kts")), + matchesProjectsSourceRoots(withMainSourceSetJavaKotlinIn("buildSrc")) + ) + } + + @LeaksFileHandles("Kotlin compiler daemon on buildSrc jar") + def "sourcePath includes buildSrc project dependencies source roots"() { + + given: + def sourceRoots = withMultiProjectKotlinBuildSrc() + withSettings("""include(":sub")""") + + expect: + assertThat( + sourcePathFor(withFile("sub/build.gradle.kts")), + matchesProjectsSourceRoots(sourceRoots) + ) + } + + private void assertSourcePathIncludesGradleSourcesGiven(String rootProjectScript, String subProjectScript) { + assertSourcePathGiven( + rootProjectScript, + subProjectScript, + hasItems("core-api") + ) + } + + private void assertSourcePathIncludesKotlinStdlibSourcesGiven(String rootProjectScript, String subProjectScript) { + assertSourcePathGiven( + rootProjectScript, + subProjectScript, + hasItems("kotlin-stdlib-jdk8-${targetKotlinVersion}-sources.jar".toString()) + ) + } + + private void assertSourcePathIncludesKotlinPluginSourcesGiven(String rootProjectScript, String subProjectScript) { + assertSourcePathGiven( + rootProjectScript, + subProjectScript, + hasItems( + equalTo("kotlin-gradle-plugin-${targetKotlinVersion}-sources.jar".toString()), + matching("annotations-[0-9.]+-sources\\.jar") + ) + ) + } + + private void assertSourcePathGiven( + String rootProjectScript, + String subProjectScript, + Matcher> matches + ) { + + def subProjectName = "sub" + withSettings(""" + include("$subProjectName") + """) + + withBuildScript(rootProjectScript) + def subProjectScriptFile = withBuildScriptIn(subProjectName, subProjectScript) + + def srcConventionalPathDirNames = ["java", "groovy", "kotlin", "resources"] + def sourcePath = sourcePathFor(subProjectScriptFile).collect { path -> + if (srcConventionalPathDirNames.contains(path.name)) { + path.parentFile.parentFile.parentFile.name + } else { + path.name + } + }.unique() + assertThat(sourcePath, matches) + } + private static String buildScriptDependencyOn(File jar) { return """ buildscript { diff --git a/subprojects/kotlin-dsl/src/integTest/kotlin/org/gradle/kotlin/dsl/accessors/AccessorsClassPathIntegrationTest.kt b/subprojects/kotlin-dsl/src/integTest/kotlin/org/gradle/kotlin/dsl/accessors/AccessorsClassPathIntegrationTest.kt index 409ab224bef0a..d89b0e603ade1 100644 --- a/subprojects/kotlin-dsl/src/integTest/kotlin/org/gradle/kotlin/dsl/accessors/AccessorsClassPathIntegrationTest.kt +++ b/subprojects/kotlin-dsl/src/integTest/kotlin/org/gradle/kotlin/dsl/accessors/AccessorsClassPathIntegrationTest.kt @@ -16,10 +16,9 @@ package org.gradle.kotlin.dsl.accessors +import org.gradle.kotlin.dsl.fixtures.AbstractKotlinIntegrationTest import org.gradle.kotlin.dsl.fixtures.matching -import org.gradle.kotlin.dsl.integration.ScriptModelIntegrationTest - import org.hamcrest.CoreMatchers.containsString import org.hamcrest.CoreMatchers.equalTo import org.hamcrest.CoreMatchers.hasItem @@ -31,7 +30,7 @@ import org.junit.Test import java.io.File -class AccessorsClassPathIntegrationTest : ScriptModelIntegrationTest() { +class AccessorsClassPathIntegrationTest : AbstractKotlinIntegrationTest() { @Test fun `classpath model includes jit accessors by default`() { diff --git a/subprojects/kotlin-dsl/src/integTest/kotlin/org/gradle/kotlin/dsl/integration/KotlinBuildScriptModelIntegrationTest.kt b/subprojects/kotlin-dsl/src/integTest/kotlin/org/gradle/kotlin/dsl/integration/KotlinBuildScriptModelIntegrationTest.kt deleted file mode 100644 index 81b48bf5c05f0..0000000000000 --- a/subprojects/kotlin-dsl/src/integTest/kotlin/org/gradle/kotlin/dsl/integration/KotlinBuildScriptModelIntegrationTest.kt +++ /dev/null @@ -1,152 +0,0 @@ -package org.gradle.kotlin.dsl.integration - -import org.gradle.kotlin.dsl.embeddedKotlinVersion -import org.gradle.kotlin.dsl.fixtures.matching - -import org.gradle.test.fixtures.file.LeaksFileHandles - -import org.hamcrest.CoreMatchers.equalTo -import org.hamcrest.CoreMatchers.hasItems -import org.hamcrest.Matcher -import org.hamcrest.MatcherAssert.assertThat - -import org.junit.Test - - -class KotlinBuildScriptModelIntegrationTest : ScriptModelIntegrationTest() { - - @Test - fun `sourcePath includes Gradle sources`() { - - assertSourcePathIncludesGradleSourcesGiven( - rootProjectScript = "", - subProjectScript = "") - } - - @Test - fun `sourcePath includes kotlin-stdlib sources resolved against project`() { - - assertSourcePathIncludesKotlinStdlibSourcesGiven( - rootProjectScript = "", - subProjectScript = "buildscript { $repositoriesBlock }") - } - - @Test - fun `sourcePath includes kotlin-stdlib sources resolved against project hierarchy`() { - - assertSourcePathIncludesKotlinStdlibSourcesGiven( - rootProjectScript = "buildscript { $repositoriesBlock }", - subProjectScript = "") - } - - @Test - fun `sourcePath includes buildscript classpath sources resolved against project`() { - - assertSourcePathIncludesKotlinPluginSourcesGiven( - rootProjectScript = "", - subProjectScript = """ - buildscript { - dependencies { classpath(embeddedKotlin("gradle-plugin")) } - $repositoriesBlock - } - """) - } - - @Test - fun `sourcePath includes buildscript classpath sources resolved against project hierarchy`() { - - assertSourcePathIncludesKotlinPluginSourcesGiven( - rootProjectScript = """ - buildscript { - dependencies { classpath(embeddedKotlin("gradle-plugin")) } - $repositoriesBlock - } - """, - subProjectScript = "") - } - - @Test - fun `sourcePath includes plugins classpath sources resolved against project`() { - - assertSourcePathIncludesKotlinPluginSourcesGiven( - rootProjectScript = "", - subProjectScript = """ plugins { kotlin("jvm") version "$embeddedKotlinVersion" } """) - } - - @Test - fun `sourcePath includes buildSrc source roots`() { - - withKotlinBuildSrc() - withSettings("""include(":sub")""") - - assertThat( - sourcePathFor(withFile("sub/build.gradle.kts")), - matchesProjectsSourceRoots(withMainSourceSetJavaKotlinIn("buildSrc"))) - } - - @LeaksFileHandles("Kotlin Compiler Daemon working directory") - @Test - fun `sourcePath includes buildSrc project dependencies source roots`() { - - val sourceRoots = withMultiProjectKotlinBuildSrc() - withSettings("""include(":sub")""") - - assertThat( - sourcePathFor(withFile("sub/build.gradle.kts")), - matchesProjectsSourceRoots(*sourceRoots)) - } - - private - fun assertSourcePathIncludesGradleSourcesGiven(rootProjectScript: String, subProjectScript: String) { - - assertSourcePathGiven( - rootProjectScript, - subProjectScript, - hasItems("core-api")) - } - - private - fun assertSourcePathIncludesKotlinStdlibSourcesGiven(rootProjectScript: String, subProjectScript: String) { - - assertSourcePathGiven( - rootProjectScript, - subProjectScript, - hasItems("kotlin-stdlib-jdk8-$embeddedKotlinVersion-sources.jar")) - } - - private - fun assertSourcePathIncludesKotlinPluginSourcesGiven(rootProjectScript: String, subProjectScript: String) { - - assertSourcePathGiven( - rootProjectScript, - subProjectScript, - hasItems( - equalTo("kotlin-gradle-plugin-$embeddedKotlinVersion-sources.jar"), - matching("annotations-[0-9.]+-sources\\.jar"))) - } - - private - fun assertSourcePathGiven( - rootProjectScript: String, - subProjectScript: String, - matches: Matcher> - ) { - - val subProjectName = "sub" - withSettings(""" - include("$subProjectName") - """) - - withBuildScript(rootProjectScript) - val subProjectScriptFile = withBuildScriptIn(subProjectName, subProjectScript) - - val srcConventionalPathDirNames = listOf("java", "groovy", "kotlin", "resources") - val sourcePath = sourcePathFor(subProjectScriptFile).map { path -> - when { - srcConventionalPathDirNames.contains(path.name) -> path.parentFile.parentFile.parentFile.name - else -> path.name - } - }.distinct() - assertThat(sourcePath, matches) - } -} diff --git a/subprojects/kotlin-dsl/src/integTest/kotlin/org/gradle/kotlin/dsl/integration/ScriptModelIntegrationTest.kt b/subprojects/kotlin-dsl/src/integTest/kotlin/org/gradle/kotlin/dsl/integration/ScriptModelIntegrationTest.kt deleted file mode 100644 index cd867a88b1638..0000000000000 --- a/subprojects/kotlin-dsl/src/integTest/kotlin/org/gradle/kotlin/dsl/integration/ScriptModelIntegrationTest.kt +++ /dev/null @@ -1,158 +0,0 @@ -package org.gradle.kotlin.dsl.integration - -import org.gradle.kotlin.dsl.fixtures.AbstractKotlinIntegrationTest -import org.gradle.kotlin.dsl.fixtures.matching - -import org.gradle.kotlin.dsl.tooling.models.KotlinBuildScriptModel - -import org.hamcrest.CoreMatchers.allOf -import org.hamcrest.CoreMatchers.hasItem -import org.hamcrest.CoreMatchers.hasItems -import org.hamcrest.CoreMatchers.not - -import org.hamcrest.Matcher -import org.hamcrest.MatcherAssert.assertThat - -import java.io.File - - -/** - * Base class for [KotlinBuildScriptModel] integration tests. - */ -abstract class ScriptModelIntegrationTest : AbstractKotlinIntegrationTest() { - - protected - fun sourcePathFor(scriptFile: File) = - kotlinBuildScriptModelFor(scriptFile).sourcePath - - protected - class ProjectSourceRoots(val projectDir: File, val sourceSets: List, val languages: List) - - protected - fun withMainSourceSetJavaIn(projectDir: String) = - ProjectSourceRoots(existing(projectDir), listOf("main"), listOf("java")) - - protected - fun withMainSourceSetJavaKotlinIn(projectDir: String) = - ProjectSourceRoots(existing(projectDir), listOf("main"), listOf("java", "kotlin")) - - protected - fun matchesProjectsSourceRoots(vararg projectSourceRoots: ProjectSourceRoots): Matcher> { - - fun hasLanguageDir(base: File, set: String, lang: String): Matcher> = - hasItem(base.resolve("src/$set/$lang")) - - return allOf( - *projectSourceRoots - .filter { it.languages.isNotEmpty() } - .flatMap { sourceRoots -> - val languageDirs = - sourceRoots.sourceSets.flatMap { sourceSet -> - listOf("java", "kotlin").map { language -> - val hasLanguageDir = hasLanguageDir(sourceRoots.projectDir, sourceSet, language) - if (language in sourceRoots.languages) hasLanguageDir - else not(hasLanguageDir) - } - } - - val resourceDirs = - sourceRoots.sourceSets.map { sourceSet -> - hasLanguageDir(sourceRoots.projectDir, sourceSet, "resources") - } - - languageDirs + resourceDirs - }.toTypedArray()) - } - - protected - fun withMultiProjectKotlinBuildSrc(): Array { - withDefaultSettingsIn("buildSrc").appendText(""" - include(":a", ":b", ":c") - """) - withFile("buildSrc/build.gradle.kts", """ - plugins { - java - `kotlin-dsl` apply false - } - - val kotlinDslProjects = listOf( - project(":a"), - project(":b") - ) - - configure(kotlinDslProjects) { - apply(plugin = "org.gradle.kotlin.kotlin-dsl") - $repositoriesBlock - } - - dependencies { - kotlinDslProjects.forEach { - "runtime"(project(it.path)) - } - } - - """) - withFile("buildSrc/b/build.gradle.kts", """dependencies { implementation(project(":c")) }""") - withFile("buildSrc/c/build.gradle.kts", "plugins { java }") - - return arrayOf( - withMainSourceSetJavaIn("buildSrc"), - withMainSourceSetJavaKotlinIn("buildSrc/a"), - withMainSourceSetJavaKotlinIn("buildSrc/b"), - withMainSourceSetJavaIn("buildSrc/c") - ) - } - - protected - fun assertContainsGradleKotlinDslJars(classPath: List) { - val version = "[0-9.]+(-.+?)?" - assertThat( - classPath.map { it.name }, - hasItems( - matching("gradle-kotlin-dsl-$version\\.jar"), - matching("gradle-api-$version\\.jar"), - matching("gradle-kotlin-dsl-extensions-$version\\.jar"))) - } - - protected - fun assertClassPathContains(classPath: List, vararg files: File) = - assertThat( - classPath.map { it.name }, - hasItems(*fileNameSetOf(*files))) - - protected - fun assertContainsBuildSrc(classPath: List) = - assertThat( - classPath.map { it.name }, - hasBuildSrc()) - - protected - fun hasBuildSrc() = - hasItem("buildSrc.jar") - - protected - fun assertIncludes(classPath: List, vararg files: File) = - assertThat( - classPath.map { it.name }, - hasItems(*fileNameSetOf(*files))) - - protected - fun assertExcludes(classPath: List, vararg files: File) = - assertThat( - classPath.map { it.name }, - not(hasItems(*fileNameSetOf(*files)))) - - private - fun fileNameSetOf(vararg files: File) = - files.map { it.name }.toSet().toTypedArray().also { - assert(it.size == files.size) - } - - internal - fun canonicalClassPathFor(scriptFile: File, projectDir: File = projectRoot) = - kotlinBuildScriptModelFor(scriptFile, projectDir).canonicalClassPath - - internal - val KotlinBuildScriptModel.canonicalClassPath - get() = classPath.map(File::getCanonicalFile) -} From 94463f7b315137887fdd1a497c485af4a04e4c72 Mon Sep 17 00:00:00 2001 From: Paul Merlin Date: Thu, 28 Feb 2019 18:43:20 +0100 Subject: [PATCH 601/853] Temporarily disable :kotlinDslToolingBuilders:verifyTestFilesCleanup Signed-off-by: Paul Merlin --- .../kotlin-dsl-tooling-builders.gradle.kts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/subprojects/kotlin-dsl-tooling-builders/kotlin-dsl-tooling-builders.gradle.kts b/subprojects/kotlin-dsl-tooling-builders/kotlin-dsl-tooling-builders.gradle.kts index 1e53667c926e6..236bd33c50b47 100644 --- a/subprojects/kotlin-dsl-tooling-builders/kotlin-dsl-tooling-builders.gradle.kts +++ b/subprojects/kotlin-dsl-tooling-builders/kotlin-dsl-tooling-builders.gradle.kts @@ -43,3 +43,11 @@ dependencies { crossVersionTestRuntimeOnly(project(":pluginDevelopment")) } + +tasks { + + // TODO:kotlin-dsl + verifyTestFilesCleanup { + enabled = false + } +} From bcbd2c6a718eb620635c2067435f73d124b87f1e Mon Sep 17 00:00:00 2001 From: Paul Merlin Date: Tue, 12 Mar 2019 19:32:58 +0100 Subject: [PATCH 602/853] @TargetGradleVersion(">=5.4") Signed-off-by: Paul Merlin --- .../builders/r54/KotlinBuildScriptModelCrossVersionSpec.groovy | 2 +- .../builders/r54/KotlinInitScriptModelCrossVersionSpec.groovy | 2 +- .../r54/KotlinSettingsScriptModelCrossVersionSpec.groovy | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/r54/KotlinBuildScriptModelCrossVersionSpec.groovy b/subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/r54/KotlinBuildScriptModelCrossVersionSpec.groovy index 42c9ced605efa..e4d23f0f5b978 100644 --- a/subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/r54/KotlinBuildScriptModelCrossVersionSpec.groovy +++ b/subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/r54/KotlinBuildScriptModelCrossVersionSpec.groovy @@ -34,7 +34,7 @@ import static org.junit.Assert.assertThat import static org.junit.Assert.assertTrue -@TargetGradleVersion(">=5.3") +@TargetGradleVersion(">=5.4") class KotlinBuildScriptModelCrossVersionSpec extends AbstractKotlinScriptModelCrossVersionTest { def "can fetch buildSrc classpath in face of compilation errors"() { diff --git a/subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/r54/KotlinInitScriptModelCrossVersionSpec.groovy b/subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/r54/KotlinInitScriptModelCrossVersionSpec.groovy index 30898c4b0324c..c1affa642130d 100644 --- a/subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/r54/KotlinInitScriptModelCrossVersionSpec.groovy +++ b/subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/r54/KotlinInitScriptModelCrossVersionSpec.groovy @@ -24,7 +24,7 @@ import static org.junit.Assert.assertThat import static org.hamcrest.CoreMatchers.not -@TargetGradleVersion(">=5.3") +@TargetGradleVersion(">=5.4") class KotlinInitScriptModelCrossVersionSpec extends AbstractKotlinScriptModelCrossVersionTest { def "initscript classpath does not include buildSrc"() { diff --git a/subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/r54/KotlinSettingsScriptModelCrossVersionSpec.groovy b/subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/r54/KotlinSettingsScriptModelCrossVersionSpec.groovy index 7b95a24ed27de..f7821e8d8ad98 100644 --- a/subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/r54/KotlinSettingsScriptModelCrossVersionSpec.groovy +++ b/subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/r54/KotlinSettingsScriptModelCrossVersionSpec.groovy @@ -24,7 +24,7 @@ import org.gradle.kotlin.dsl.tooling.builders.AbstractKotlinScriptModelCrossVers import static org.junit.Assert.assertThat -@TargetGradleVersion(">=5.3") +@TargetGradleVersion(">=5.4") class KotlinSettingsScriptModelCrossVersionSpec extends AbstractKotlinScriptModelCrossVersionTest { def "can fetch classpath of settings script"() { From 8d54b4758b30142116df9ecccab54f4cb3170f0f Mon Sep 17 00:00:00 2001 From: Paul Merlin Date: Tue, 12 Mar 2019 19:35:00 +0100 Subject: [PATCH 603/853] Move Kotlin DSL TAPI model tests for accessors as cross-version tests Signed-off-by: Paul Merlin --- .../fixtures/AbstractKotlinIntegrationTest.kt | 2 +- ...ctKotlinScriptModelCrossVersionTest.groovy | 23 ++-- ...ssorsClassPathModelCrossVersionSpec.groovy | 122 ++++++++++++++++++ .../AccessorsClassPathIntegrationTest.kt | 92 ------------- 4 files changed, 138 insertions(+), 101 deletions(-) create mode 100644 subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/r54/AccessorsClassPathModelCrossVersionSpec.groovy diff --git a/subprojects/kotlin-dsl-test-fixtures/src/main/kotlin/org/gradle/kotlin/dsl/fixtures/AbstractKotlinIntegrationTest.kt b/subprojects/kotlin-dsl-test-fixtures/src/main/kotlin/org/gradle/kotlin/dsl/fixtures/AbstractKotlinIntegrationTest.kt index ea12a90742d19..4a7e62495dd32 100644 --- a/subprojects/kotlin-dsl-test-fixtures/src/main/kotlin/org/gradle/kotlin/dsl/fixtures/AbstractKotlinIntegrationTest.kt +++ b/subprojects/kotlin-dsl-test-fixtures/src/main/kotlin/org/gradle/kotlin/dsl/fixtures/AbstractKotlinIntegrationTest.kt @@ -183,7 +183,7 @@ abstract class AbstractKotlinIntegrationTest : AbstractIntegrationTest() { ) } - protected + private fun classPathFor(scriptFile: File, projectDir: File = projectRoot) = kotlinBuildScriptModelFor(scriptFile, projectDir).classPath diff --git a/subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/AbstractKotlinScriptModelCrossVersionTest.groovy b/subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/AbstractKotlinScriptModelCrossVersionTest.groovy index 50c974354e0dc..6550f2421edc8 100644 --- a/subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/AbstractKotlinScriptModelCrossVersionTest.groovy +++ b/subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/AbstractKotlinScriptModelCrossVersionTest.groovy @@ -32,6 +32,8 @@ import org.hamcrest.Description import org.hamcrest.Matcher import org.hamcrest.TypeSafeMatcher +import java.util.function.Consumer +import java.util.function.Predicate import java.util.regex.Pattern import java.util.zip.ZipEntry import java.util.zip.ZipOutputStream @@ -113,8 +115,8 @@ abstract class AbstractKotlinScriptModelCrossVersionTest extends ToolingApiSpeci return withFile("$baseDir/build.gradle.kts", script) } - protected TestFile withFile(String path, String text = "") { - return file(path) << text.stripIndent() + protected TestFile withFile(String path, String content = "") { + return file(path).tap { text = content.stripIndent() } } protected TestFile withClassJar(String path, Class... classes) { @@ -212,7 +214,7 @@ abstract class AbstractKotlinScriptModelCrossVersionTest extends ToolingApiSpeci return canonicalClasspathOf(kotlinBuildScriptModelFor(projectDir, scriptFile)) } - private List classPathFor(File projectDir, File scriptFile = null) { + protected List classPathFor(File projectDir, File scriptFile = null) { return kotlinBuildScriptModelFor(projectDir, scriptFile).classPath } @@ -338,18 +340,23 @@ abstract class AbstractKotlinScriptModelCrossVersionTest extends ToolingApiSpeci return hasItem(new File(base, "src/$set/$lang")) } - protected static Matcher matching(String pattern) { + protected static Matcher matching(String pattern) { def compiledPattern = Pattern.compile(pattern) - return new TypeSafeMatcher() { + return matching({ it.appendText("a string matching the pattern").appendValue(pattern) }) { String item -> + compiledPattern.matcher(item).matches() + } + } + protected static Matcher matching(Consumer describe, Predicate match) { + return new TypeSafeMatcher() { @Override - protected boolean matchesSafely(String item) { - return compiledPattern.matcher(item).matches() + protected boolean matchesSafely(T item) { + return match.test(item) } @Override void describeTo(Description description) { - description.appendText("a string matching the pattern").appendValue(pattern) + describe.accept(description) } } } diff --git a/subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/r54/AccessorsClassPathModelCrossVersionSpec.groovy b/subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/r54/AccessorsClassPathModelCrossVersionSpec.groovy new file mode 100644 index 0000000000000..0dc64411c68e7 --- /dev/null +++ b/subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/r54/AccessorsClassPathModelCrossVersionSpec.groovy @@ -0,0 +1,122 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.kotlin.dsl.tooling.builders.r54 + +import org.gradle.integtests.tooling.fixture.TargetGradleVersion + +import org.gradle.kotlin.dsl.tooling.builders.AbstractKotlinScriptModelCrossVersionTest + +import org.hamcrest.Matcher + +import javax.annotation.Nullable + +import static org.hamcrest.CoreMatchers.equalTo +import static org.hamcrest.CoreMatchers.hasItem +import static org.hamcrest.CoreMatchers.not +import static org.junit.Assert.assertThat + + +@TargetGradleVersion(">=5.4") +class AccessorsClassPathModelCrossVersionSpec extends AbstractKotlinScriptModelCrossVersionTest { + + def "classpath model includes jit accessors by default"() { + + given: + withDefaultSettings() + withBuildScript(""" + plugins { java } + """) + + expect: + assertAccessorsInClassPathOf(buildFileKts) + } + + def "jit accessors can be turned off"() { + + given: + withDefaultSettings() + withBuildScript(""" + plugins { java } + """) + + and: + withFile("gradle.properties", "org.gradle.kotlin.dsl.accessors=off") + + expect: + assertThat( + classPathFor(projectDir, buildFile), + not(hasAccessorsClasses()) + ) + } + + def "the set of jit accessors is a function of the set of applied plugins"() { + + given: + // TODO:accessors - rework this test to ensure it's providing enough coverage + def s1 = setOfAutomaticAccessorsFor(["application"]) + def s2 = setOfAutomaticAccessorsFor(["java"]) + def s3 = setOfAutomaticAccessorsFor(["application"]) + def s4 = setOfAutomaticAccessorsFor(["application", "java"]) + def s5 = setOfAutomaticAccessorsFor(["java"]) + + expect: + assertThat(s1, not(equalTo(s2))) // application ≠ java + assertThat(s1, equalTo(s3)) // application = application + assertThat(s2, equalTo(s5)) // java = java + assertThat(s1, equalTo(s4)) // application ⊇ java + } + + private void assertAccessorsInClassPathOf(File buildFile) { + def model = kotlinBuildScriptModelFor(projectDir, buildFile) + assertThat(model.classPath, hasAccessorsClasses()) + assertThat(model.sourcePath, hasAccessorsSource()) + } + + private Matcher> hasAccessorsClasses() { + return hasItem( + matching({ it.appendText("accessors classes") }) { File file -> + new File(file, accessorsClassFilePath).isFile() + } + ) + } + + private Matcher> hasAccessorsSource() { + return hasItem( + matching({ it.appendText("accessors source") }) { File file -> + new File(file, accessorsSourceFilePath).isFile() + } + ) + } + + private File setOfAutomaticAccessorsFor(Iterable plugins) { + withDefaultSettings() + def buildFile = withBuildScript("plugins {\n${plugins.join("\n")}\n}") + def classFilePath = accessorsClassFor(buildFile).toPath() + return projectDir.toPath().relativize(classFilePath).toFile() + } + + @Nullable + private File accessorsClassFor(File buildFile) { + return classPathFor(projectDir, buildFile) + .tap { println(it) } + .find { it.isDirectory() && new File(it, accessorsClassFilePath).isFile() } + } + + private String accessorsClassFilePath = "org/gradle/kotlin/dsl/ArchivesConfigurationAccessorsKt.class" + + private String accessorsSourceFilePath = "org/gradle/kotlin/dsl/ArchivesConfigurationAccessors.kt" +} diff --git a/subprojects/kotlin-dsl/src/integTest/kotlin/org/gradle/kotlin/dsl/accessors/AccessorsClassPathIntegrationTest.kt b/subprojects/kotlin-dsl/src/integTest/kotlin/org/gradle/kotlin/dsl/accessors/AccessorsClassPathIntegrationTest.kt index d89b0e603ade1..dc8c232c430ca 100644 --- a/subprojects/kotlin-dsl/src/integTest/kotlin/org/gradle/kotlin/dsl/accessors/AccessorsClassPathIntegrationTest.kt +++ b/subprojects/kotlin-dsl/src/integTest/kotlin/org/gradle/kotlin/dsl/accessors/AccessorsClassPathIntegrationTest.kt @@ -17,64 +17,15 @@ package org.gradle.kotlin.dsl.accessors import org.gradle.kotlin.dsl.fixtures.AbstractKotlinIntegrationTest -import org.gradle.kotlin.dsl.fixtures.matching import org.hamcrest.CoreMatchers.containsString -import org.hamcrest.CoreMatchers.equalTo -import org.hamcrest.CoreMatchers.hasItem -import org.hamcrest.CoreMatchers.not import org.hamcrest.MatcherAssert.assertThat import org.junit.Test -import java.io.File - class AccessorsClassPathIntegrationTest : AbstractKotlinIntegrationTest() { - @Test - fun `classpath model includes jit accessors by default`() { - - withDefaultSettings() - val buildFile = withBuildScript(""" - plugins { java } - """) - - assertAccessorsInClassPathOf(buildFile) - } - - @Test - fun `jit accessors can be turned off`() { - - withDefaultSettings() - val buildFile = withBuildScript(""" - plugins { java } - """) - - withFile("gradle.properties", "org.gradle.kotlin.dsl.accessors=off") - - assertThat( - classPathFor(buildFile), - not(hasAccessorsClasses()) - ) - } - - @Test - fun `the set of jit accessors is a function of the set of applied plugins`() { - - // TODO:accessors - rework this test to ensure it's providing enough coverage - val s1 = setOfAutomaticAccessorsFor(setOf("application")) - val s2 = setOfAutomaticAccessorsFor(setOf("java")) - val s3 = setOfAutomaticAccessorsFor(setOf("application")) - val s4 = setOfAutomaticAccessorsFor(setOf("application", "java")) - val s5 = setOfAutomaticAccessorsFor(setOf("java")) - - assertThat(s1, not(equalTo(s2))) // application ≠ java - assertThat(s1, equalTo(s3)) // application = application - assertThat(s2, equalTo(s5)) // java = java - assertThat(s1, equalTo(s4)) // application ⊇ java - } - @Test fun `warning is emitted if a gradle slash project dash schema dot json file is present`() { @@ -85,47 +36,4 @@ class AccessorsClassPathIntegrationTest : AbstractKotlinIntegrationTest() { assertThat(build("help").output, containsString(projectSchemaResourceDiscontinuedWarning)) } - - private - fun setOfAutomaticAccessorsFor(plugins: Set): File { - withDefaultSettings() - val script = "plugins {\n${plugins.joinToString(separator = "\n")}\n}" - val buildFile = withBuildScript(script, produceFile = ::newOrExisting) - return accessorsClassFor(buildFile)!!.relativeTo(buildFile.parentFile) - } - - private - fun assertAccessorsInClassPathOf(buildFile: File) { - val model = kotlinBuildScriptModelFor(buildFile) - assertThat(model.classPath, hasAccessorsClasses()) - assertThat(model.sourcePath, hasAccessorsSource()) - } - - private - fun hasAccessorsSource() = - hasItem( - matching({ appendText("accessors source") }) { - resolve(accessorsSourceFilePath).isFile - } - ) - - private - fun hasAccessorsClasses() = - hasItem( - matching({ appendText("accessors classes") }) { - resolve(accessorsClassFilePath).isFile - } - ) - - private - fun accessorsClassFor(buildFile: File) = - classPathFor(buildFile).find { - it.isDirectory && it.resolve(accessorsClassFilePath).isFile - } - - private - val accessorsSourceFilePath = "org/gradle/kotlin/dsl/ArchivesConfigurationAccessors.kt" - - private - val accessorsClassFilePath = "org/gradle/kotlin/dsl/ArchivesConfigurationAccessorsKt.class" } From 0bb1ffb71d9519c11d6a7d037449ba2a9ad03abd Mon Sep 17 00:00:00 2001 From: Paul Merlin Date: Wed, 13 Mar 2019 09:52:02 +0100 Subject: [PATCH 604/853] Move Kotlin DSL TAPI model tests for precompiled scripts as cross-version tests Signed-off-by: Paul Merlin --- ...ompiledScriptPluginModelIntegrationTest.kt | 141 ------------------ .../fixtures/AbstractKotlinIntegrationTest.kt | 50 ------- ...edScriptPluginModelCrossVersionSpec.groovy | 141 ++++++++++++++++++ 3 files changed, 141 insertions(+), 191 deletions(-) delete mode 100644 subprojects/kotlin-dsl-integ-tests/src/integTest/kotlin/org/gradle/kotlin/dsl/integration/PrecompiledScriptPluginModelIntegrationTest.kt create mode 100644 subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/r54/PrecompiledScriptPluginModelCrossVersionSpec.groovy diff --git a/subprojects/kotlin-dsl-integ-tests/src/integTest/kotlin/org/gradle/kotlin/dsl/integration/PrecompiledScriptPluginModelIntegrationTest.kt b/subprojects/kotlin-dsl-integ-tests/src/integTest/kotlin/org/gradle/kotlin/dsl/integration/PrecompiledScriptPluginModelIntegrationTest.kt deleted file mode 100644 index eec6f6b785da6..0000000000000 --- a/subprojects/kotlin-dsl-integ-tests/src/integTest/kotlin/org/gradle/kotlin/dsl/integration/PrecompiledScriptPluginModelIntegrationTest.kt +++ /dev/null @@ -1,141 +0,0 @@ -/* - * Copyright 2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.gradle.kotlin.dsl.integration - -import org.gradle.kotlin.dsl.fixtures.FoldersDsl - -import org.gradle.test.fixtures.file.LeaksFileHandles - -import org.hamcrest.MatcherAssert.assertThat -import org.hamcrest.Matchers.hasItem -import org.hamcrest.Matchers.startsWith - -import org.junit.Test - -import java.io.File - - -class PrecompiledScriptPluginModelIntegrationTest : AbstractPluginIntegrationTest() { - - @LeaksFileHandles("Kotlin Compiler Daemon working directory") - @Test - fun `given a single project build, the classpath of a precompiled script plugin is the compile classpath of its enclosing source-set`() { - - val implementationDependency = - withDeepThoughtJar("implementation.jar") - - val classpathDependency = - withDeepThoughtJar("classpath.jar") - - withBuildScript(""" - plugins { - `kotlin-dsl` - } - - buildscript { - dependencies { - classpath(files("${classpathDependency.name}")) - } - } - - dependencies { - implementation(files("${implementationDependency.name}")) - } - """) - - val precompiledScriptPlugin = - withPrecompiledKotlinScript("my-plugin.gradle.kts", "") - - assertClassPathFor( - precompiledScriptPlugin, - includes = setOf(implementationDependency), - excludes = setOf(classpathDependency) - ) - } - - @Test - fun `given a multi-project build, the classpath of a precompiled script plugin is the compile classpath of its enclosing source-set`() { - - val dependencyA = - withFile("a.jar") - - val dependencyB = - withFile("b.jar") - - withDefaultSettings().appendText(""" - include("project-a") - include("project-b") - """) - - withFolders { - - "project-a" { - "src/main/kotlin" { - withFile("my-plugin-a.gradle.kts") - } - withImplementationDependencyOn(dependencyA) - } - - "project-b" { - "src/main/kotlin" { - withFile("my-plugin-b.gradle.kts") - } - withImplementationDependencyOn(dependencyB) - } - } - - assertClassPathFor( - existing("project-a/src/main/kotlin/my-plugin-a.gradle.kts"), - includes = setOf(dependencyA), - excludes = setOf(dependencyB) - ) - - assertClassPathFor( - existing("project-b/src/main/kotlin/my-plugin-b.gradle.kts"), - includes = setOf(dependencyB), - excludes = setOf(dependencyA) - ) - } - - @Test - fun `implicit imports include type-safe accessors packages`() { - - withKotlinDslPlugin() - - val pluginFile = withPrecompiledKotlinScript("plugin.gradle.kts", """ - plugins { java } - """) - - assertThat( - kotlinBuildScriptModelFor(pluginFile).implicitImports, - hasItem(startsWith("gradle.kotlin.dsl.accessors._")) - ) - } - - private - fun FoldersDsl.withImplementationDependencyOn(file: File) { - withFile("build.gradle.kts", """ - plugins { - `kotlin-dsl` - } - - dependencies { - implementation(files("${file.name}")) - } - """) - } -} diff --git a/subprojects/kotlin-dsl-test-fixtures/src/main/kotlin/org/gradle/kotlin/dsl/fixtures/AbstractKotlinIntegrationTest.kt b/subprojects/kotlin-dsl-test-fixtures/src/main/kotlin/org/gradle/kotlin/dsl/fixtures/AbstractKotlinIntegrationTest.kt index 4a7e62495dd32..73c2b90bbca81 100644 --- a/subprojects/kotlin-dsl-test-fixtures/src/main/kotlin/org/gradle/kotlin/dsl/fixtures/AbstractKotlinIntegrationTest.kt +++ b/subprojects/kotlin-dsl-test-fixtures/src/main/kotlin/org/gradle/kotlin/dsl/fixtures/AbstractKotlinIntegrationTest.kt @@ -23,20 +23,14 @@ import org.gradle.integtests.fixtures.executer.ExecutionFailure import org.gradle.integtests.fixtures.executer.ExecutionResult import org.gradle.integtests.fixtures.executer.GradleContextualExecuter -import org.gradle.kotlin.dsl.concurrent.future - import org.gradle.kotlin.dsl.resolver.GradleInstallation -import org.gradle.kotlin.dsl.resolver.KotlinBuildScriptModelRequest -import org.gradle.kotlin.dsl.resolver.fetchKotlinBuildScriptModelFor import org.gradle.kotlin.dsl.support.zipTo -import org.gradle.kotlin.dsl.tooling.models.KotlinBuildScriptModel import org.hamcrest.CoreMatchers.allOf import org.hamcrest.CoreMatchers.containsString import org.hamcrest.CoreMatchers.not import org.hamcrest.Matcher -import org.hamcrest.Matchers.hasItems import org.junit.Assert.assertThat import org.junit.Assume.assumeFalse @@ -167,46 +161,6 @@ abstract class AbstractKotlinIntegrationTest : AbstractIntegrationTest() { $repositoriesBlock """ - protected - fun assertClassPathFor( - buildScript: File, - includes: Set, - excludes: Set, - importedProjectDir: File = projectRoot - ) { - val includeItems = hasItems(*includes.map { it.name }.toTypedArray()) - val excludeItems = not(hasItems(*excludes.map { it.name }.toTypedArray())) - val condition = if (excludes.isEmpty()) includeItems else allOf(includeItems, excludeItems) - assertThat( - classPathFor(buildScript, importedProjectDir).map { it.name }, - condition - ) - } - - private - fun classPathFor(scriptFile: File, projectDir: File = projectRoot) = - kotlinBuildScriptModelFor(scriptFile, projectDir).classPath - - protected - fun kotlinBuildScriptModelFor( - scriptFile: File, - importedProjectDir: File = projectRoot - ): KotlinBuildScriptModel = future { - - fetchKotlinBuildScriptModelFor( - KotlinBuildScriptModelRequest( - projectDir = importedProjectDir, - scriptFile = scriptFile, - gradleInstallation = testGradleInstallation(), - gradleUserHome = buildContext.gradleUserHomeDir - ) - ) { - - setStandardOutput(System.out) - setStandardError(System.err) - } - }.get() - private fun testGradleInstallation() = GradleInstallation.Local(distribution.gradleHomeDir) @@ -215,10 +169,6 @@ abstract class AbstractKotlinIntegrationTest : AbstractIntegrationTest() { fun compileKotlin(taskName: String = "classes"): ExecutionResult = build(taskName).assertTaskExecuted(":compileKotlin") - protected - fun withDeepThoughtJar(named: String): File = - withClassJar(named, DeepThought::class.java) - protected fun withClassJar(fileName: String, vararg classes: Class<*>) = withZip(fileName, classEntriesFor(*classes)) diff --git a/subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/r54/PrecompiledScriptPluginModelCrossVersionSpec.groovy b/subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/r54/PrecompiledScriptPluginModelCrossVersionSpec.groovy new file mode 100644 index 0000000000000..e97e5499f9639 --- /dev/null +++ b/subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/r54/PrecompiledScriptPluginModelCrossVersionSpec.groovy @@ -0,0 +1,141 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.kotlin.dsl.tooling.builders.r54 + +import org.gradle.integtests.tooling.fixture.TargetGradleVersion +import org.gradle.test.fixtures.file.LeaksFileHandles +import org.gradle.test.fixtures.file.TestFile + +import org.gradle.kotlin.dsl.tooling.builders.AbstractKotlinScriptModelCrossVersionTest + +import static org.hamcrest.CoreMatchers.hasItem +import static org.hamcrest.CoreMatchers.startsWith +import static org.junit.Assert.assertThat + + +@TargetGradleVersion(">=5.4") +class PrecompiledScriptPluginModelCrossVersionSpec extends AbstractKotlinScriptModelCrossVersionTest { + + @LeaksFileHandles("Kotlin Compiler Daemon working directory") + def "given a single project build, the classpath of a precompiled script plugin is the compile classpath of its enclosing source-set"() { + + given: + def implementationDependency = withClassJar("implementation.jar") + def classpathDependency = withClassJar("classpath.jar") + + and: + withDefaultSettings() + withBuildScript(""" + plugins { + `kotlin-dsl` + } + + buildscript { + dependencies { + classpath(files("${classpathDependency.name}")) + } + } + + dependencies { + implementation(files("${implementationDependency.name}")) + } + """) + + and: + def precompiledScriptPlugin = withPrecompiledKotlinScript("my-plugin.gradle.kts", "") + + expect: + assertClassPathFor( + precompiledScriptPlugin, + [implementationDependency] as Set, + [classpathDependency] as Set + ) + } + + def "given a multi-project build, the classpath of a precompiled script plugin is the compile classpath of its enclosing source-set"() { + + given: + def dependencyA = withClassJar("a.jar") + def dependencyB = withClassJar("b.jar") + + and: + withDefaultSettings().append(""" + include("project-a") + include("project-b") + """.stripIndent()) + + and: + withImplementationDependencyOn("project-a", dependencyA) + withFile("project-a/src/main/kotlin/my-plugin-a.gradle.kts") + + and: + withImplementationDependencyOn("project-b", dependencyB) + withFile("project-b/src/main/kotlin/my-plugin-b.gradle.kts") + + expect: + assertClassPathFor( + file("project-a/src/main/kotlin/my-plugin-a.gradle.kts"), + [dependencyA] as Set, + [dependencyB] as Set + ) + + and: + assertClassPathFor( + file("project-b/src/main/kotlin/my-plugin-b.gradle.kts"), + [dependencyB] as Set, + [dependencyA] as Set + ) + } + + def "implicit imports include type-safe accessors packages"() { + + given: + withDefaultSettings() + withBuildScript(""" + plugins { + `kotlin-dsl` + } + """) + + and: + def pluginFile = withPrecompiledKotlinScript("plugin.gradle.kts", """ + plugins { java } + """) + + expect: + assertThat( + kotlinBuildScriptModelFor(projectDir, pluginFile).implicitImports, + hasItem(startsWith("gradle.kotlin.dsl.accessors._")) + ) + } + + private TestFile withPrecompiledKotlinScript(String fileName, String code) { + return withFile("src/main/kotlin/$fileName", code) + } + + private TestFile withImplementationDependencyOn(String basedir, TestFile jar) { + return withBuildScriptIn(basedir, """ + plugins { + `kotlin-dsl` + } + + dependencies { + implementation(files("${jar.name}")) + } + """) + } +} From 16f1d1dabd42f863ed7aa393615c9786abefdbe7 Mon Sep 17 00:00:00 2001 From: Paul Merlin Date: Wed, 13 Mar 2019 10:35:41 +0100 Subject: [PATCH 605/853] Simplify fixtures and remove dead fixture code Signed-off-by: Paul Merlin --- .../kotlin/dsl/fixtures/PatternMatcher.kt | 27 -------------- ...ctKotlinScriptModelCrossVersionTest.groovy | 35 +++---------------- ...linBuildScriptModelCrossVersionSpec.groovy | 16 ++++----- ...edScriptPluginModelCrossVersionSpec.groovy | 8 ++--- 4 files changed, 16 insertions(+), 70 deletions(-) delete mode 100644 subprojects/kotlin-dsl-test-fixtures/src/main/kotlin/org/gradle/kotlin/dsl/fixtures/PatternMatcher.kt diff --git a/subprojects/kotlin-dsl-test-fixtures/src/main/kotlin/org/gradle/kotlin/dsl/fixtures/PatternMatcher.kt b/subprojects/kotlin-dsl-test-fixtures/src/main/kotlin/org/gradle/kotlin/dsl/fixtures/PatternMatcher.kt deleted file mode 100644 index c487d6ad2349f..0000000000000 --- a/subprojects/kotlin-dsl-test-fixtures/src/main/kotlin/org/gradle/kotlin/dsl/fixtures/PatternMatcher.kt +++ /dev/null @@ -1,27 +0,0 @@ -package org.gradle.kotlin.dsl.fixtures - -import org.hamcrest.Description -import org.hamcrest.TypeSafeMatcher - -import java.util.regex.Pattern - - -fun matches(pattern: String) = - matching(pattern) - - -fun matching(pattern: String) = - matching(pattern.toPattern()) - - -fun matching(pattern: Pattern) = - matching({ appendText("a string matching the pattern ").appendValue(pattern) }) { - pattern.matcher(this).matches() - } - - -fun matching(describe: Description.() -> Unit, match: T.() -> Boolean) = - object : TypeSafeMatcher() { - override fun matchesSafely(item: T) = match(item) - override fun describeTo(description: Description) = describe(description) - } diff --git a/subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/AbstractKotlinScriptModelCrossVersionTest.groovy b/subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/AbstractKotlinScriptModelCrossVersionTest.groovy index 6550f2421edc8..c534dad6f43e7 100644 --- a/subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/AbstractKotlinScriptModelCrossVersionTest.groovy +++ b/subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/AbstractKotlinScriptModelCrossVersionTest.groovy @@ -18,7 +18,6 @@ package org.gradle.kotlin.dsl.tooling.builders import groovy.transform.CompileStatic -import org.gradle.api.internal.file.archive.ZipCopyAction import org.gradle.integtests.tooling.fixture.TextUtil import org.gradle.integtests.tooling.fixture.ToolingApiAdditionalClasspath import org.gradle.integtests.tooling.fixture.ToolingApiSpecification @@ -35,7 +34,6 @@ import org.hamcrest.TypeSafeMatcher import java.util.function.Consumer import java.util.function.Predicate import java.util.regex.Pattern -import java.util.zip.ZipEntry import java.util.zip.ZipOutputStream import static org.gradle.kotlin.dsl.resolver.KotlinBuildScriptModelRequestKt.fetchKotlinBuildScriptModelFor @@ -119,35 +117,10 @@ abstract class AbstractKotlinScriptModelCrossVersionTest extends ToolingApiSpeci return file(path).tap { text = content.stripIndent() } } - protected TestFile withClassJar(String path, Class... classes) { - return withZip(path, classEntriesFor(classes)) - } - - // TODO rewrite invoking the kotlin impl - protected TestFile withZip(String zipPath, Iterable> entries) { - return file(zipPath).tap { zip -> - zip.parentFile.mkdirs() - new ZipOutputStream(zip.newOutputStream()).withCloseable { zos -> - entries.each { tuple -> - def path = tuple.first - def bytes = tuple.second - zos.putNextEntry(new ZipEntry(path).tap { - time = ZipCopyAction.CONSTANT_TIME_FOR_ZIP_ENTRIES - size = bytes.size() - }) - zos.write(bytes) - zos.closeEntry() - } - } - } - } - - // TODO rewrite invoking the kotlin impl - private static Iterable> classEntriesFor(Class... classes) { - - return classes.collect { clazz -> - def classFilePath = clazz.name.replace('.', '/') + ".class" - new Tuple2(classFilePath, clazz.getResource("/$classFilePath").bytes) + protected TestFile withEmptyJar(String path) { + return file(path).tap { jarFile -> + jarFile.parentFile.mkdirs() + new ZipOutputStream(jarFile.newOutputStream()).close() } } diff --git a/subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/r54/KotlinBuildScriptModelCrossVersionSpec.groovy b/subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/r54/KotlinBuildScriptModelCrossVersionSpec.groovy index e4d23f0f5b978..b5b38e89882b6 100644 --- a/subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/r54/KotlinBuildScriptModelCrossVersionSpec.groovy +++ b/subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/r54/KotlinBuildScriptModelCrossVersionSpec.groovy @@ -186,9 +186,9 @@ class KotlinBuildScriptModelCrossVersionSpec extends AbstractKotlinScriptModelCr withSettingsIn(location, "include(\"foo\", \"bar\")") - def parentJar = withClassJar("$location/libs/parent.jar") - def fooJar = withClassJar("$location/libs/foo.jar") - def barJar = withClassJar("$location/libs/bar.jar") + def parentJar = withEmptyJar("$location/libs/parent.jar") + def fooJar = withEmptyJar("$location/libs/foo.jar") + def barJar = withEmptyJar("$location/libs/bar.jar") assertTrue parentJar.isFile() assertTrue fooJar.isFile() @@ -227,8 +227,8 @@ class KotlinBuildScriptModelCrossVersionSpec extends AbstractKotlinScriptModelCr def "can fetch buildscript classpath for sub-project script outside root project dir"() { given: - def rootDependency = withClassJar("libs/root.jar") - def subDependency = withClassJar("libs/sub.jar") + def rootDependency = withEmptyJar("libs/root.jar") + def subDependency = withEmptyJar("libs/sub.jar") and: withSettingsIn("root", """ @@ -282,9 +282,9 @@ class KotlinBuildScriptModelCrossVersionSpec extends AbstractKotlinScriptModelCr withDefaultSettings() - def rootDependency = withClassJar("libs/root-dep.jar") - def nestedRootDependency = withClassJar("libs/$nestedProjectName-root-dep.jar") - def nestedSubDependency = withClassJar("libs/$nestedProjectName-sub-dep.jar") + def rootDependency = withEmptyJar("libs/root-dep.jar") + def nestedRootDependency = withEmptyJar("libs/$nestedProjectName-root-dep.jar") + def nestedSubDependency = withEmptyJar("libs/$nestedProjectName-sub-dep.jar") withSettingsIn(nestedProjectName, """ include("sub") diff --git a/subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/r54/PrecompiledScriptPluginModelCrossVersionSpec.groovy b/subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/r54/PrecompiledScriptPluginModelCrossVersionSpec.groovy index e97e5499f9639..51d6e39b83030 100644 --- a/subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/r54/PrecompiledScriptPluginModelCrossVersionSpec.groovy +++ b/subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/r54/PrecompiledScriptPluginModelCrossVersionSpec.groovy @@ -34,8 +34,8 @@ class PrecompiledScriptPluginModelCrossVersionSpec extends AbstractKotlinScriptM def "given a single project build, the classpath of a precompiled script plugin is the compile classpath of its enclosing source-set"() { given: - def implementationDependency = withClassJar("implementation.jar") - def classpathDependency = withClassJar("classpath.jar") + def implementationDependency = withEmptyJar("implementation.jar") + def classpathDependency = withEmptyJar("classpath.jar") and: withDefaultSettings() @@ -69,8 +69,8 @@ class PrecompiledScriptPluginModelCrossVersionSpec extends AbstractKotlinScriptM def "given a multi-project build, the classpath of a precompiled script plugin is the compile classpath of its enclosing source-set"() { given: - def dependencyA = withClassJar("a.jar") - def dependencyB = withClassJar("b.jar") + def dependencyA = withEmptyJar("a.jar") + def dependencyB = withEmptyJar("b.jar") and: withDefaultSettings().append(""" From da69c028ea9f4260fdbf61a92c1301759a0a859b Mon Sep 17 00:00:00 2001 From: Paul Merlin Date: Thu, 14 Mar 2019 16:56:41 +0100 Subject: [PATCH 606/853] Fix TestKitIntegrationTest Signed-off-by: Paul Merlin --- .../gradle/kotlin/dsl/integration/TestKitIntegrationTest.kt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/subprojects/kotlin-dsl/src/integTest/kotlin/org/gradle/kotlin/dsl/integration/TestKitIntegrationTest.kt b/subprojects/kotlin-dsl/src/integTest/kotlin/org/gradle/kotlin/dsl/integration/TestKitIntegrationTest.kt index b409eefe9dbbb..fa404a88c9cbd 100644 --- a/subprojects/kotlin-dsl/src/integTest/kotlin/org/gradle/kotlin/dsl/integration/TestKitIntegrationTest.kt +++ b/subprojects/kotlin-dsl/src/integTest/kotlin/org/gradle/kotlin/dsl/integration/TestKitIntegrationTest.kt @@ -18,12 +18,15 @@ package org.gradle.kotlin.dsl.integration import org.gradle.kotlin.dsl.fixtures.AbstractKotlinIntegrationTest +import org.gradle.test.fixtures.file.LeaksFileHandles + import org.junit.Test class TestKitIntegrationTest : AbstractKotlinIntegrationTest() { @Test + @LeaksFileHandles("Kotlin Compiler Daemon working directory") fun `withPluginClasspath works`() { requireGradleDistributionOnEmbeddedExecuter() From 8b60a993cd976861c294f4f91bb0841fd49a808c Mon Sep 17 00:00:00 2001 From: Paul Merlin Date: Mon, 18 Mar 2019 09:38:52 +0100 Subject: [PATCH 607/853] Refine Kotlin DSL TAPI cross-version tests Signed-off-by: Paul Merlin --- ...ctKotlinScriptModelCrossVersionTest.groovy | 18 ++++--- ...linBuildScriptModelCrossVersionSpec.groovy | 53 +++++++++++-------- ...tlinInitScriptModelCrossVersionSpec.groovy | 8 +-- ...SettingsScriptModelCrossVersionSpec.groovy | 16 +++--- 4 files changed, 58 insertions(+), 37 deletions(-) diff --git a/subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/AbstractKotlinScriptModelCrossVersionTest.groovy b/subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/AbstractKotlinScriptModelCrossVersionTest.groovy index c534dad6f43e7..d73ae5bdc3817 100644 --- a/subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/AbstractKotlinScriptModelCrossVersionTest.groovy +++ b/subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/AbstractKotlinScriptModelCrossVersionTest.groovy @@ -81,14 +81,18 @@ abstract class AbstractKotlinScriptModelCrossVersionTest extends ToolingApiSpeci protected String getTargetKotlinVersion() { if (targetKotlinVersion == null) { - def props = new JarTestFixture(targetDist.gradleHomeDir.file("lib").listFiles().find { - it.name.startsWith("gradle-kotlin-dsl-${targetVersion.baseVersion.version}") - }).content("gradle-kotlin-dsl-versions.properties") - targetKotlinVersion = new Properties().tap { load(new StringReader(props)) }.getProperty("kotlin") + targetKotlinVersion = loadTargetDistKotlinVersion() } return targetKotlinVersion } + private static String loadTargetDistKotlinVersion() { + def props = new JarTestFixture(targetDist.gradleHomeDir.file("lib").listFiles().find { + it.name.startsWith("gradle-kotlin-dsl-${targetVersion.baseVersion.version}") + }).content("gradle-kotlin-dsl-versions.properties") + return new Properties().tap { load(new StringReader(props)) }.getProperty("kotlin") + } + protected TestFile withDefaultSettings() { return withSettings(defaultSettingsScript) } @@ -97,11 +101,11 @@ abstract class AbstractKotlinScriptModelCrossVersionTest extends ToolingApiSpeci return withSettingsIn(".", script) } - private TestFile withDefaultSettingsIn(String baseDir) { + protected TestFile withDefaultSettingsIn(String baseDir) { return withSettingsIn(baseDir, defaultSettingsScript) } - protected TestFile withSettingsIn(String baseDir, String script) { + private TestFile withSettingsIn(String baseDir, String script) { return withFile("$baseDir/settings.gradle.kts", script) } @@ -143,7 +147,7 @@ abstract class AbstractKotlinScriptModelCrossVersionTest extends ToolingApiSpeci } protected ProjectSourceRoots[] withMultiProjectKotlinBuildSrc() { - withSettingsIn("buildSrc", """ + withDefaultSettingsIn("buildSrc").append(""" include(":a", ":b", ":c") """) withFile("buildSrc/build.gradle.kts", """ diff --git a/subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/r54/KotlinBuildScriptModelCrossVersionSpec.groovy b/subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/r54/KotlinBuildScriptModelCrossVersionSpec.groovy index b5b38e89882b6..88bec082afc83 100644 --- a/subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/r54/KotlinBuildScriptModelCrossVersionSpec.groovy +++ b/subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/r54/KotlinBuildScriptModelCrossVersionSpec.groovy @@ -70,9 +70,9 @@ class KotlinBuildScriptModelCrossVersionSpec extends AbstractKotlinScriptModelCr def "can fetch buildscript classpath in face of compilation errors"() { given: - projectDir.createFile("classes.jar") - settingsFile << "" - buildFileKts << """ + withEmptyJar("classes.jar") + withDefaultSettings() + withBuildScript(""" buildscript { dependencies { classpath(files("classes.jar")) @@ -80,11 +80,12 @@ class KotlinBuildScriptModelCrossVersionSpec extends AbstractKotlinScriptModelCr } val p = - """.stripIndent() + """) expect: assertClassPathContains( - file("classes.jar")) + file("classes.jar") + ) } @LeaksFileHandles("Kotlin compiler daemon on buildSrc jar") @@ -117,7 +118,7 @@ class KotlinBuildScriptModelCrossVersionSpec extends AbstractKotlinScriptModelCr given: withBuildSrc() - withFile("classes.jar") + withEmptyJar("classes.jar") withDefaultSettings() withFile("build.gradle", """ @@ -134,7 +135,8 @@ class KotlinBuildScriptModelCrossVersionSpec extends AbstractKotlinScriptModelCr then: assertThat( classPath.collect { it.name } as List, - hasItems("classes.jar")) + hasItems("classes.jar") + ) assertContainsBuildSrc(classPath) @@ -144,12 +146,13 @@ class KotlinBuildScriptModelCrossVersionSpec extends AbstractKotlinScriptModelCr def "can fetch buildscript classpath for sub-project script when parent has errors"() { given: - withSettings("""include("sub")""") + withDefaultSettings().append(""" + include("sub") + """) - withDefaultSettings() withBuildScript("val p =") - def jar = withFile("libs/jar.jar") + def jar = withEmptyJar("libs/jar.jar") def subProjectScript = withFile("sub/build.gradle.kts", """ @@ -184,7 +187,9 @@ class KotlinBuildScriptModelCrossVersionSpec extends AbstractKotlinScriptModelCr @CompileStatic private void assertCanFetchClassPathForSubProjectScriptIn(String location) { - withSettingsIn(location, "include(\"foo\", \"bar\")") + withDefaultSettingsIn(location).append(""" + include("foo", "bar") + """) def parentJar = withEmptyJar("$location/libs/parent.jar") def fooJar = withEmptyJar("$location/libs/foo.jar") @@ -231,7 +236,7 @@ class KotlinBuildScriptModelCrossVersionSpec extends AbstractKotlinScriptModelCr def subDependency = withEmptyJar("libs/sub.jar") and: - withSettingsIn("root", """ + withDefaultSettingsIn("root").append(""" include("sub") project(":sub").apply { projectDir = file("../sub") @@ -286,7 +291,7 @@ class KotlinBuildScriptModelCrossVersionSpec extends AbstractKotlinScriptModelCr def nestedRootDependency = withEmptyJar("libs/$nestedProjectName-root-dep.jar") def nestedSubDependency = withEmptyJar("libs/$nestedProjectName-sub-dep.jar") - withSettingsIn(nestedProjectName, """ + withDefaultSettingsIn(nestedProjectName).append(""" include("sub") project(":sub").apply { projectDir = file("../$nestedProjectName-sub") @@ -341,13 +346,13 @@ class KotlinBuildScriptModelCrossVersionSpec extends AbstractKotlinScriptModelCr withBuildSrc() def buildSrcDependency = - withFile("buildSrc-dependency.jar") + withEmptyJar("buildSrc-dependency.jar") withFile("buildSrc/build.gradle", """ dependencies { compile(files("../${buildSrcDependency.name}")) } """) - def rootProjectDependency = withFile("rootProject-dependency.jar") + def rootProjectDependency = withEmptyJar("rootProject-dependency.jar") withDefaultSettings() withFile("build.gradle", """ @@ -394,7 +399,7 @@ class KotlinBuildScriptModelCrossVersionSpec extends AbstractKotlinScriptModelCr withDefaultSettings() def scriptPluginDependency = - withFile("script-plugin-dependency.jar") + withEmptyJar("script-plugin-dependency.jar") def scriptPlugin = withFile("plugin.gradle.kts", """ buildscript { @@ -412,13 +417,15 @@ class KotlinBuildScriptModelCrossVersionSpec extends AbstractKotlinScriptModelCr assertThat( "Script body shouldn't be evaluated", model.exceptions, - equalTo([])) + equalTo([]) + ) and: def scriptPluginClassPath = canonicalClasspathOf(model) assertThat( scriptPluginClassPath.collect { it.name } as List, - hasItem(scriptPluginDependency.name)) + hasItem(scriptPluginDependency.name) + ) assertContainsGradleKotlinDslJars(scriptPluginClassPath) } @@ -489,7 +496,9 @@ class KotlinBuildScriptModelCrossVersionSpec extends AbstractKotlinScriptModelCr given: withKotlinBuildSrc() - withSettings("""include(":sub")""") + withDefaultSettings().append(""" + include(":sub") + """) expect: assertThat( @@ -503,7 +512,9 @@ class KotlinBuildScriptModelCrossVersionSpec extends AbstractKotlinScriptModelCr given: def sourceRoots = withMultiProjectKotlinBuildSrc() - withSettings("""include(":sub")""") + withDefaultSettings().append(""" + include(":sub") + """) expect: assertThat( @@ -546,7 +557,7 @@ class KotlinBuildScriptModelCrossVersionSpec extends AbstractKotlinScriptModelCr ) { def subProjectName = "sub" - withSettings(""" + withDefaultSettings().append(""" include("$subProjectName") """) diff --git a/subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/r54/KotlinInitScriptModelCrossVersionSpec.groovy b/subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/r54/KotlinInitScriptModelCrossVersionSpec.groovy index c1affa642130d..d8270efacf3f2 100644 --- a/subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/r54/KotlinInitScriptModelCrossVersionSpec.groovy +++ b/subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/r54/KotlinInitScriptModelCrossVersionSpec.groovy @@ -43,14 +43,15 @@ class KotlinInitScriptModelCrossVersionSpec extends AbstractKotlinScriptModelCro assertContainsGradleKotlinDslJars(classPath) assertThat( classPath.collect { it.name }, - not(hasBuildSrc())) + not(hasBuildSrc()) + ) } def "can fetch initscript classpath in face of compilation errors"() { given: withDefaultSettings() - withFile("classes.jar") + withEmptyJar("classes.jar") and: def initScript = @@ -71,7 +72,8 @@ class KotlinInitScriptModelCrossVersionSpec extends AbstractKotlinScriptModelCro assertContainsGradleKotlinDslJars(classPath) assertClassPathContains( classPath, - file("classes.jar")) + file("classes.jar") + ) } List canonicalClassPathFor(File initScript) { diff --git a/subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/r54/KotlinSettingsScriptModelCrossVersionSpec.groovy b/subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/r54/KotlinSettingsScriptModelCrossVersionSpec.groovy index f7821e8d8ad98..d3b1d93c4564e 100644 --- a/subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/r54/KotlinSettingsScriptModelCrossVersionSpec.groovy +++ b/subprojects/kotlin-dsl-tooling-builders/src/crossVersionTest/groovy/org/gradle/kotlin/dsl/tooling/builders/r54/KotlinSettingsScriptModelCrossVersionSpec.groovy @@ -33,7 +33,7 @@ class KotlinSettingsScriptModelCrossVersionSpec extends AbstractKotlinScriptMode withBuildSrc() and: - def settingsDependency = withFile("settings-dependency.jar") + def settingsDependency = withEmptyJar("settings-dependency.jar") def settings = withSettings(""" buildscript { dependencies { @@ -43,7 +43,7 @@ class KotlinSettingsScriptModelCrossVersionSpec extends AbstractKotlinScriptMode """) and: - def projectDependency = withFile("project-dependency.jar") + def projectDependency = withEmptyJar("project-dependency.jar") file("build.gradle") << """ buildscript { dependencies { @@ -69,7 +69,7 @@ class KotlinSettingsScriptModelCrossVersionSpec extends AbstractKotlinScriptMode withDefaultSettings() and: - def settingsDependency = withFile("settings-dependency.jar", "") + def settingsDependency = withEmptyJar("settings-dependency.jar") def settings = withFile("my.settings.gradle.kts", """ buildscript { dependencies { @@ -79,7 +79,7 @@ class KotlinSettingsScriptModelCrossVersionSpec extends AbstractKotlinScriptMode """) and: - def projectDependency = withFile("project-dependency.jar", "") + def projectDependency = withEmptyJar("project-dependency.jar") withFile("build.gradle", """ buildscript { dependencies { @@ -103,7 +103,9 @@ class KotlinSettingsScriptModelCrossVersionSpec extends AbstractKotlinScriptMode given: withKotlinBuildSrc() - def settings = withSettings("""include(":sub")""") + def settings = withDefaultSettings().append(""" + include(":sub") + """) expect: assertThat( @@ -116,7 +118,9 @@ class KotlinSettingsScriptModelCrossVersionSpec extends AbstractKotlinScriptMode given: def sourceRoots = withMultiProjectKotlinBuildSrc() - def settings = withSettings("""include(":sub")""") + def settings = withDefaultSettings().append(""" + include(":sub") + """) expect: assertThat( From 287a20c206d2f69f9cd6bbb8230b4d317a052c9b Mon Sep 17 00:00:00 2001 From: Stefan Wolf Date: Mon, 18 Mar 2019 10:07:51 +0100 Subject: [PATCH 608/853] Fix test Follow up for #8783 --- .../internal/BuildCacheBuildOperationsIntegrationTest.groovy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subprojects/build-cache/src/integTest/groovy/org/gradle/caching/internal/BuildCacheBuildOperationsIntegrationTest.groovy b/subprojects/build-cache/src/integTest/groovy/org/gradle/caching/internal/BuildCacheBuildOperationsIntegrationTest.groovy index 190a1350adfe6..2b8dc571c84ae 100644 --- a/subprojects/build-cache/src/integTest/groovy/org/gradle/caching/internal/BuildCacheBuildOperationsIntegrationTest.groovy +++ b/subprojects/build-cache/src/integTest/groovy/org/gradle/caching/internal/BuildCacheBuildOperationsIntegrationTest.groovy @@ -250,7 +250,7 @@ class BuildCacheBuildOperationsIntegrationTest extends AbstractIntegrationSpec { def failedUnpackOp = operations.only(BuildCacheArchiveUnpackBuildOperationType) failedUnpackOp.details.cacheKey != null failedUnpackOp.result == null - failedUnpackOp.failure =~ /Failed to unpack trees for task ':t'/ + failedUnpackOp.failure =~ /java.util.zip.ZipException: Not in GZIP format/ } def "records ops for miss then store"() { From 6fe5d8fd547a5af873875bcce62bc91d7e9def14 Mon Sep 17 00:00:00 2001 From: Stefan Wolf Date: Mon, 18 Mar 2019 10:54:36 +0100 Subject: [PATCH 609/853] Require incremental inputs to have a value Instead of silently ignoring incremental inputs without a value, we now fail when the work requires incremental execution. --- ...ractIncrementalTasksIntegrationTest.groovy | 53 +--- .../IncrementalInputsIntegrationTest.groovy | 230 ++++++++++++++---- ...ncrementalTaskInputsIntegrationTest.groovy | 46 ++++ .../execution/ExecuteActionsTaskExecuter.java | 14 +- ...IncrementalExecutionIntegrationTest.groovy | 4 +- .../gradle/internal/execution/UnitOfWork.java | 2 +- .../execution/steps/ResolveChangesStep.java | 4 + 7 files changed, 243 insertions(+), 110 deletions(-) diff --git a/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/AbstractIncrementalTasksIntegrationTest.groovy b/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/AbstractIncrementalTasksIntegrationTest.groovy index d64d880edacbf..84656842aa838 100644 --- a/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/AbstractIncrementalTasksIntegrationTest.groovy +++ b/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/AbstractIncrementalTasksIntegrationTest.groovy @@ -18,8 +18,6 @@ package org.gradle.api.tasks import org.gradle.integtests.fixtures.AbstractIntegrationSpec import org.gradle.internal.change.ChangeTypeInternal -import spock.lang.Issue -import spock.lang.Unroll abstract class AbstractIncrementalTasksIntegrationTest extends AbstractIntegrationSpec { @@ -50,12 +48,13 @@ abstract class AbstractIncrementalTasksIntegrationTest extends AbstractIntegrati void setupTaskSources(String inputDirAnnotation = primaryInputAnnotation) { file("buildSrc/src/main/groovy/BaseIncrementalTask.groovy").text = """ import org.gradle.api.* + import org.gradle.api.file.* import org.gradle.api.plugins.* import org.gradle.api.tasks.* import org.gradle.api.tasks.incremental.* import org.gradle.work.* - class BaseIncrementalTask extends DefaultTask { + abstract class BaseIncrementalTask extends DefaultTask { ${inputDirAnnotation} @InputDirectory def File inputDir @@ -81,7 +80,7 @@ abstract class AbstractIncrementalTasksIntegrationTest extends AbstractIntegrati import org.gradle.api.tasks.* import org.gradle.api.tasks.incremental.* - class IncrementalTask extends BaseIncrementalTask { + abstract class IncrementalTask extends BaseIncrementalTask { @Input def String prop @@ -258,7 +257,7 @@ ext.added = ['file3.txt', 'file4.txt'] when: buildFile.text = buildFileBase buildFile << """ - class IncrementalTask2 extends BaseIncrementalTask {} + abstract class IncrementalTask2 extends BaseIncrementalTask {} task incremental(type: IncrementalTask2) { inputDir = project.mkdir('inputs') } @@ -348,50 +347,6 @@ ext.added = ['file3.txt', 'file4.txt'] executesWithIncrementalContext("ext.modified = ['file1.txt']") } - @Unroll - @Issue("https://github.com/gradle/gradle/issues/4166") - def "file in input dir appears in task inputs for #inputAnnotation"() { - buildFile << """ - class MyTask extends DefaultTask { - @${inputAnnotation} - File input - @OutputFile - File output - - @TaskAction - void doStuff(IncrementalTaskInputs inputs) { - def out = [] - inputs.outOfDate { - out << file.name - } - assert out.contains('child') - output.text = out.join('\\n') - } - } - - task myTask(type: MyTask) { - input = mkdir(inputDir) - output = file("build/output.txt") - } - """ - String myTask = ':myTask' - - when: - file("inputDir1/child") << "inputFile1" - run myTask, '-PinputDir=inputDir1' - then: - executedAndNotSkipped(myTask) - - when: - file("inputDir2/child") << "inputFile2" - run myTask, '-PinputDir=inputDir2' - then: - executedAndNotSkipped(myTask) - - where: - inputAnnotation << [InputFiles.name, InputDirectory.name] - } - /* 7. Sad-day cases - Incremental task has input files declared diff --git a/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/IncrementalInputsIntegrationTest.groovy b/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/IncrementalInputsIntegrationTest.groovy index 14dc1a754e4ab..3f283596872e4 100644 --- a/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/IncrementalInputsIntegrationTest.groovy +++ b/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/IncrementalInputsIntegrationTest.groovy @@ -18,6 +18,8 @@ package org.gradle.api.tasks import org.gradle.internal.change.ChangeTypeInternal import org.gradle.work.Incremental +import spock.lang.Issue +import spock.lang.Unroll class IncrementalInputsIntegrationTest extends AbstractIncrementalTasksIntegrationTest { @@ -31,9 +33,6 @@ class IncrementalInputsIntegrationTest extends AbstractIncrementalTasksIntegrati } incrementalExecution = inputChanges.incremental - queryChangesFor.each { parameterName -> - inputChanges.getFileChanges(this."\$parameterName") - } inputChanges.getFileChanges(inputDir).each { change -> switch (change.changeType) { @@ -57,23 +56,6 @@ class IncrementalInputsIntegrationTest extends AbstractIncrementalTasksIntegrati touchOutputs() } - - @Optional - @Incremental - @InputFile - File anotherIncrementalInput - - @Optional - @Incremental - @InputDirectory - File anotherIncrementalInputDirectory - - @Optional - @InputFile - File nonIncrementalInput - - @Internal - List queryChangesFor = ["inputDir"] """ } @@ -87,17 +69,6 @@ class IncrementalInputsIntegrationTest extends AbstractIncrementalTasksIntegrati return "@${Incremental.simpleName}" } - def setup() { - buildFile << """ - tasks.withType(IncrementalTask).configureEach { - anotherIncrementalInput = project.file('anotherIncrementalInput') - nonIncrementalInput = project.file('nonIncrementalInput') - } - """ - file('anotherIncrementalInput').text = "anotherIncrementalInput" - file('nonIncrementalInput').text = "nonIncrementalInput" - } - def "incremental task is executed non-incrementally when input file property has been added"() { given: file('new-input.txt').text = "new input file" @@ -110,32 +81,102 @@ class IncrementalInputsIntegrationTest extends AbstractIncrementalTasksIntegrati executesWithRebuildContext() } - def "cannot query non-incremental file input parameters"() { - given: - previousExecution() + @Unroll + @Issue("https://github.com/gradle/gradle/issues/4166") + def "file in input dir appears in task inputs for #inputAnnotation"() { + buildFile << """ + class MyTask extends DefaultTask { + @${inputAnnotation} + @Incremental + File input + @OutputFile + File output + + @TaskAction + void doStuff(InputChanges changes) { + def changed = changes.getFileChanges(input)*.file*.name as List + assert changed.contains('child') + output.text = changed.join('\\n') + } + } + + task myTask(type: MyTask) { + input = mkdir(inputDir) + output = file("build/output.txt") + } + """ + String myTask = ':myTask' when: - file("inputs/new-input-file.txt") << "new file" + file("inputDir1/child") << "inputFile1" + run myTask, '-PinputDir=inputDir1' + then: + executedAndNotSkipped(myTask) + + when: + file("inputDir2/child") << "inputFile2" + run myTask, '-PinputDir=inputDir2' + then: + executedAndNotSkipped(myTask) + + where: + inputAnnotation << [InputFiles.name, InputDirectory.name] + } + + def "cannot query non-incremental file input parameters"() { + given: buildFile << """ - tasks.withType(IncrementalTask).configureEach { - queryChangesFor.add("nonIncrementalInput") + abstract class WithNonIncrementalInput extends BaseIncrementalTask { + + @InputFile + File nonIncrementalInput + + @Override + void execute(InputChanges inputChanges) { + inputChanges.getFileChanges(nonIncrementalInput) + } + } + + task withNonIncrementalInput(type: WithNonIncrementalInput) { + inputDir = file("inputs") + nonIncrementalInput = file("nonIncremental") } """ - then: - fails("incremental") - failure.assertHasCause("Cannot query incremental changes: No property found for value ${file("nonIncrementalInput").absolutePath}. Incremental properties: anotherIncrementalInput, inputDir.") + file("nonIncremental").text = "input" + + expect: + fails("withNonIncrementalInput") + failure.assertHasCause("Cannot query incremental changes: No property found for value ${file("nonIncremental").absolutePath}. Incremental properties: inputDir.") } def "changes to non-incremental input parameters cause a rebuild"() { given: - file("nonIncrementalInput").makeOlder() - previousExecution() + buildFile << """ + abstract class WithNonIncrementalInput extends BaseIncrementalTask { + + @InputFile + File nonIncrementalInput + + @Override + void execute(InputChanges changes) { + super.execute(changes) + assert !changes.incremental + } + } + + task withNonIncrementalInput(type: WithNonIncrementalInput) { + inputDir = file("inputs") + nonIncrementalInput = file("nonIncremental") + } + """ + file("nonIncremental").text = "input" + run("withNonIncrementalInput") when: file("inputs/new-input-file.txt") << "new file" - file("nonIncrementalInput").text = 'changed' - then: - executesWithRebuildContext("ext.added += ['new-input-file.txt']") + file("nonIncremental").text = 'changed' + then: + succeeds("withNonIncrementalInput") } def "properties annotated with SkipWhenEmpty are incremental"() { @@ -153,14 +194,105 @@ class IncrementalInputsIntegrationTest extends AbstractIncrementalTasksIntegrati def "two incremental inputs cannot have the same value"() { buildFile << """ - tasks.withType(IncrementalTask).configureEach { - anotherIncrementalInputDirectory = inputDir + + class MyTask extends DefaultTask { + @Incremental + @InputDirectory + File inputOne + + @Incremental + @InputDirectory + File inputTwo + + @OutputDirectory + File outputDirectory + + @TaskAction + void run(InputChanges changes) { + new File(outputDirectory, "one.txt").text = changes.getFileChanges(inputOne)*.file*.name.join("\\n") + new File(outputDirectory, "two.txt").text = changes.getFileChanges(inputTwo)*.file*.name.join("\\n") + } + } + + task myTask(type: MyTask) { + inputOne = file("input") + inputTwo = file("input") + outputDirectory = file("build/output") } """ + + file("input").createDir() expect: - fails("incremental") - failureHasCause("Multiple entries with same key: ${file('inputs').absolutePath}=inputDir and ${file('inputs').absolutePath}=anotherIncrementalInputDirectory") + fails("myTask") + failureHasCause("Multiple entries with same key: ${file('input').absolutePath}=inputTwo and ${file('input').absolutePath}=inputOne") } + def "two incremental file properties can point to the same file"() { + buildFile << """ + abstract class MyTask extends DefaultTask { + @Incremental + @InputDirectory + abstract DirectoryProperty getInputOne() + + @Incremental + @InputDirectory + abstract DirectoryProperty getInputTwo() + + @OutputDirectory + File outputDirectory + + @TaskAction + void run(InputChanges changes) { + new File(outputDirectory, "one.txt").text = changes.getFileChanges(inputOne)*.file*.name.join("\\n") + new File(outputDirectory, "two.txt").text = changes.getFileChanges(inputTwo)*.file*.name.join("\\n") + } + } + + task myTask(type: MyTask) { + inputOne = file("input") + inputTwo = file("input") + outputDirectory = file("build/output") + } + """ + + file("input").createDir() + + expect: + succeeds("myTask") + } + + def "values are required for incremental inputs"() { + buildFile << """ + + abstract class MyTask extends DefaultTask { + @Incremental + @Optional + @InputDirectory + ${propertyDefinition} + + @OutputDirectory + File outputDirectory + + @TaskAction + void run(InputChanges changes) { + new File(outputDirectory, "output.txt").text = "Success" + } + } + + task myTask(type: MyTask) { + outputDirectory = file("build/output") + } + """ + + file("input").createDir() + + expect: + fails("myTask") + failure.assertHasDescription("Execution failed for task ':myTask'.") + failure.assertHasCause("Must specify a value for incremental input property 'input'.") + + where: + propertyDefinition << ["abstract DirectoryProperty getInput()", "abstract RegularFileProperty getInput()", "File input"] + } } diff --git a/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/IncrementalTaskInputsIntegrationTest.groovy b/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/IncrementalTaskInputsIntegrationTest.groovy index b667569dcced0..8bd5c6403ef72 100644 --- a/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/IncrementalTaskInputsIntegrationTest.groovy +++ b/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/IncrementalTaskInputsIntegrationTest.groovy @@ -17,6 +17,8 @@ package org.gradle.api.tasks import org.gradle.internal.change.ChangeTypeInternal +import spock.lang.Issue +import spock.lang.Unroll class IncrementalTaskInputsIntegrationTest extends AbstractIncrementalTasksIntegrationTest { @@ -73,4 +75,48 @@ class IncrementalTaskInputsIntegrationTest extends AbstractIncrementalTasksInteg then: executesWithRebuildContext("ext.modified += ['new-input.txt']") } + + @Unroll + @Issue("https://github.com/gradle/gradle/issues/4166") + def "file in input dir appears in task inputs for #inputAnnotation"() { + buildFile << """ + class MyTask extends DefaultTask { + @${inputAnnotation} + File input + @OutputFile + File output + + @TaskAction + void doStuff(IncrementalTaskInputs inputs) { + def out = [] + inputs.outOfDate { + out << file.name + } + assert out.contains('child') + output.text = out.join('\\n') + } + } + + task myTask(type: MyTask) { + input = mkdir(inputDir) + output = file("build/output.txt") + } + """ + String myTask = ':myTask' + + when: + file("inputDir1/child") << "inputFile1" + run myTask, '-PinputDir=inputDir1' + then: + executedAndNotSkipped(myTask) + + when: + file("inputDir2/child") << "inputFile2" + run myTask, '-PinputDir=inputDir2' + then: + executedAndNotSkipped(myTask) + + where: + inputAnnotation << [InputFiles.name, InputDirectory.name] + } } diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuter.java b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuter.java index ac376776d0bee..00362e6d53df3 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuter.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuter.java @@ -290,14 +290,12 @@ public void visitInputFileProperties(InputFilePropertyVisitor visitor) { ImmutableSortedSet inputFileProperties = context.getTaskProperties().getInputFileProperties(); for (InputFilePropertySpec inputFileProperty : inputFileProperties) { Object value = inputFileProperty.getValue(); - if (value != null) { - boolean incremental = inputFileProperty.isIncremental() - // SkipWhenEmpty implies incremental. - // If this file property is empty, then we clean up the previously generated outputs. - // That means that there is a very close relation between the file property and the output. - || inputFileProperty.isSkipWhenEmpty(); - visitor.visitInputFileProperty(inputFileProperty.getPropertyName(), value, incremental); - } + boolean incremental = inputFileProperty.isIncremental() + // SkipWhenEmpty implies incremental. + // If this file property is empty, then we clean up the previously generated outputs. + // That means that there is a very close relation between the file property and the output. + || inputFileProperty.isSkipWhenEmpty(); + visitor.visitInputFileProperty(inputFileProperty.getPropertyName(), value, incremental); } } diff --git a/subprojects/execution/src/integTest/groovy/org/gradle/internal/execution/IncrementalExecutionIntegrationTest.groovy b/subprojects/execution/src/integTest/groovy/org/gradle/internal/execution/IncrementalExecutionIntegrationTest.groovy index f908b6b09419e..68a6c82be3bed 100644 --- a/subprojects/execution/src/integTest/groovy/org/gradle/internal/execution/IncrementalExecutionIntegrationTest.groovy +++ b/subprojects/execution/src/integTest/groovy/org/gradle/internal/execution/IncrementalExecutionIntegrationTest.groovy @@ -802,9 +802,7 @@ class IncrementalExecutionIntegrationTest extends Specification { @Override void visitInputFileProperties(UnitOfWork.InputFilePropertyVisitor visitor) { for (entry in inputs.entrySet()) { - if (entry.value != null) { - visitor.visitInputFileProperty(entry.key, entry.value, false) - } + visitor.visitInputFileProperty(entry.key, entry.value, false) } } diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/UnitOfWork.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/UnitOfWork.java index 90c438bfdf231..d6122d6b67448 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/UnitOfWork.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/UnitOfWork.java @@ -76,7 +76,7 @@ interface LocalStateVisitor { @FunctionalInterface interface InputFilePropertyVisitor { - void visitInputFileProperty(String name, Object value, boolean incremental); + void visitInputFileProperty(String name, @Nullable Object value, boolean incremental); } @FunctionalInterface diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/ResolveChangesStep.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/ResolveChangesStep.java index 0b35cff8970ba..6e4e432fde727 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/ResolveChangesStep.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/ResolveChangesStep.java @@ -17,6 +17,7 @@ package org.gradle.internal.execution.steps; import com.google.common.collect.ImmutableBiMap; +import org.gradle.api.InvalidUserDataException; import org.gradle.internal.execution.IncrementalChangesContext; import org.gradle.internal.execution.IncrementalContext; import org.gradle.internal.execution.Result; @@ -111,6 +112,9 @@ private static IncrementalInputProperties createIncrementalInputProperties(UnitO ImmutableBiMap.Builder builder = ImmutableBiMap.builder(); work.visitInputFileProperties((name, value, incremental) -> { if (incremental) { + if (value == null) { + throw new InvalidUserDataException("Must specify a value for incremental input property '" + name + "'."); + } builder.put(name, value); } }); From 7e36de81835024805c2deb22603deaad70531d1e Mon Sep 17 00:00:00 2001 From: Stefan Wolf Date: Mon, 18 Mar 2019 14:29:50 +0100 Subject: [PATCH 610/853] Improve incremental input tests --- .../TaskPropertyNamingIntegrationTest.groovy | 4 +- ...ractIncrementalTasksIntegrationTest.groovy | 74 +++++++++++-------- .../IncrementalInputsIntegrationTest.groovy | 4 +- ...ncrementalTaskInputsIntegrationTest.groovy | 2 +- 4 files changed, 49 insertions(+), 35 deletions(-) diff --git a/subprojects/core/src/integTest/groovy/org/gradle/api/internal/project/taskfactory/TaskPropertyNamingIntegrationTest.groovy b/subprojects/core/src/integTest/groovy/org/gradle/api/internal/project/taskfactory/TaskPropertyNamingIntegrationTest.groovy index f9885aba3cc88..b2d4e7b9e440e 100644 --- a/subprojects/core/src/integTest/groovy/org/gradle/api/internal/project/taskfactory/TaskPropertyNamingIntegrationTest.groovy +++ b/subprojects/core/src/integTest/groovy/org/gradle/api/internal/project/taskfactory/TaskPropertyNamingIntegrationTest.groovy @@ -81,7 +81,7 @@ class TaskPropertyNamingIntegrationTest extends AbstractIntegrationSpec { def inputFiles = [:] TaskPropertyUtils.visitProperties(project.services.get(PropertyWalker), it, new PropertyVisitor.Adapter() { @Override - void visitInputFileProperty(String propertyName, boolean optional, boolean skipWhenEmpty, boolean isIncrementalInput, Class fileNormalizer, PropertyValue value, InputFilePropertyType filePropertyType) { + void visitInputFileProperty(String propertyName, boolean optional, boolean skipWhenEmpty, boolean incremental, Class fileNormalizer, PropertyValue value, InputFilePropertyType filePropertyType) { inputFiles[propertyName] = project.files(value) } @@ -398,7 +398,7 @@ class TaskPropertyNamingIntegrationTest extends AbstractIntegrationSpec { } @Override - void visitInputFileProperty(String propertyName, boolean optional, boolean skipWhenEmpty, boolean incrementalInput, Class fileNormalizer, PropertyValue value, InputFilePropertyType filePropertyType) { + void visitInputFileProperty(String propertyName, boolean optional, boolean skipWhenEmpty, boolean incremental, Class fileNormalizer, PropertyValue value, InputFilePropertyType filePropertyType) { println "Input file property '\${propertyName}'" } diff --git a/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/AbstractIncrementalTasksIntegrationTest.groovy b/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/AbstractIncrementalTasksIntegrationTest.groovy index 84656842aa838..caaa44535397a 100644 --- a/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/AbstractIncrementalTasksIntegrationTest.groovy +++ b/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/AbstractIncrementalTasksIntegrationTest.groovy @@ -125,7 +125,7 @@ abstract class AbstractIncrementalTasksIntegrationTest extends AbstractIntegrati def "incremental task is informed that all input files are 'out-of-date' when run for the first time"() { expect: - executesWithRebuildContext() + executesNonIncrementally() } def "incremental task is skipped when run with no changes since last execution"() { @@ -147,7 +147,7 @@ abstract class AbstractIncrementalTasksIntegrationTest extends AbstractIntegrati file('inputs/file1.txt') << "changed content" then: - executesWithIncrementalContext("ext.modified = ['file1.txt']") + executesIncrementally(modified: ['file1.txt']) } def "incremental task is informed of 'out-of-date' files when input file added"() { @@ -158,7 +158,7 @@ abstract class AbstractIncrementalTasksIntegrationTest extends AbstractIntegrati file('inputs/file3.txt') << "file3 content" then: - executesWithIncrementalContext("ext.added = ['file3.txt']") + executesIncrementally(added: ['file3.txt']) } def "incremental task is informed of 'out-of-date' files when input file removed"() { @@ -169,7 +169,7 @@ abstract class AbstractIncrementalTasksIntegrationTest extends AbstractIntegrati file('inputs/file2.txt').delete() then: - executesWithIncrementalContext("ext.removed = ['file2.txt']") + executesIncrementally(removed: ['file2.txt']) } def "incremental task is informed of 'out-of-date' files when all input files removed"() { @@ -182,7 +182,7 @@ abstract class AbstractIncrementalTasksIntegrationTest extends AbstractIntegrati file('inputs/file2.txt').delete() then: - executesWithIncrementalContext("ext.removed = ['file0.txt', 'file1.txt', 'file2.txt']") + executesIncrementally(removed: ['file0.txt', 'file1.txt', 'file2.txt']) } def "incremental task is informed of 'out-of-date' files with added, removed and modified files"() { @@ -196,11 +196,11 @@ abstract class AbstractIncrementalTasksIntegrationTest extends AbstractIntegrati file('inputs/file4.txt') << "new file 4" then: - executesWithIncrementalContext(""" -ext.modified = ['file1.txt'] -ext.removed = ['file2.txt'] -ext.added = ['file3.txt', 'file4.txt'] -""") + executesIncrementally( + modified: ['file1.txt'], + removed: ['file2.txt'], + added: ['file3.txt', 'file4.txt'] + ) } def "incremental task is informed of 'out-of-date' files when task has no declared outputs or properties"() { @@ -218,7 +218,7 @@ ext.added = ['file3.txt', 'file4.txt'] file('inputs/file3.txt') << "file3 content" then: - executesWithIncrementalContext("ext.added = ['file3.txt']") + executesIncrementally(added: ['file3.txt']) } def "incremental task is informed that all input files are 'out-of-date' when input property has changed"() { @@ -229,7 +229,7 @@ ext.added = ['file3.txt', 'file4.txt'] buildFile << "incremental.prop = 'changed'" then: - executesWithRebuildContext() + executesNonIncrementally() } def "incremental task is informed that all input files are 'out-of-date' when input file property has been removed"() { @@ -247,7 +247,7 @@ ext.added = ['file3.txt', 'file4.txt'] toBeRemovedInputFile.delete() then: - executesWithRebuildContext() + executesNonIncrementally() } def "incremental task is informed that all input files are 'out-of-date' when task class has changed"() { @@ -264,7 +264,7 @@ ext.added = ['file3.txt', 'file4.txt'] """ then: - executesWithRebuildContext() + executesNonIncrementally() } def "incremental task is informed that all input files are 'out-of-date' when output directory is changed"() { @@ -275,7 +275,7 @@ ext.added = ['file3.txt', 'file4.txt'] buildFile << "incremental.outputDir = project.mkdir('new-outputs')" then: - executesWithRebuildContext() + executesNonIncrementally() } def "incremental task is informed that all input files are 'out-of-date' when output file has changed"() { @@ -286,7 +286,7 @@ ext.added = ['file3.txt', 'file4.txt'] file("outputs/file1.txt") << "further change" then: - executesWithRebuildContext() + executesNonIncrementally() } def "incremental task is informed that all input files are 'out-of-date' when output file has been removed"() { @@ -297,7 +297,7 @@ ext.added = ['file3.txt', 'file4.txt'] file("outputs/file1.txt").delete() then: - executesWithRebuildContext() + executesNonIncrementally() } def "incremental task is informed that all input files are 'out-of-date' when all output files have been removed"() { @@ -308,7 +308,7 @@ ext.added = ['file3.txt', 'file4.txt'] file("outputs").deleteDir() then: - executesWithRebuildContext() + executesNonIncrementally() } def "incremental task is informed that all input files are 'out-of-date' when Task.upToDate() is false"() { @@ -319,7 +319,7 @@ ext.added = ['file3.txt', 'file4.txt'] buildFile << "incremental.outputs.upToDateWhen { false }" then: - executesWithRebuildContext() + executesNonIncrementally() } def "incremental task is informed that all input files are 'out-of-date' when gradle is executed with --rerun-tasks"() { @@ -330,7 +330,7 @@ ext.added = ['file3.txt', 'file4.txt'] executer.withArgument("--rerun-tasks") then: - executesWithRebuildContext() + executesNonIncrementally() } def "incremental task is informed of 'out-of-date' files since previous successful execution"() { @@ -344,7 +344,7 @@ ext.added = ['file3.txt', 'file4.txt'] failedExecution() then: - executesWithIncrementalContext("ext.modified = ['file1.txt']") + executesIncrementally(modified: ['file1.txt']) } /* @@ -365,17 +365,31 @@ ext.added = ['file3.txt', 'file4.txt'] executer.withArguments() } - def executesWithIncrementalContext(String fileChanges) { - buildFile << fileChanges - succeeds "incrementalCheck" + def executesIncrementally(Map changes) { + executesIncrementalTask(incremental: true, *:changes) } - def executesWithRebuildContext(String fileChanges = "") { + def executesNonIncrementally(List rebuiltFiles = preexistingInputs) { + executesIncrementalTask( + incremental: false, + (rebuildChangeType.name().toLowerCase(Locale.US)): rebuiltFiles + ) + } + + List preexistingInputs = ['file0.txt', 'file1.txt', 'file2.txt', 'inputs'] + + def executesIncrementalTask(Map options) { + boolean incremental = options.incremental != false + List added = options.added ?: [] + List modified = options.modified ?: [] + List removed = options.removed ?: [] + buildFile << """ - ext.${rebuildChangeType.name().toLowerCase(Locale.US)} = ['file0.txt', 'file1.txt', 'file2.txt', 'inputs'] - ext.incrementalExecution = false -""" - buildFile << fileChanges - succeeds "incrementalCheck" + ext.added = ${added.collect { "'${it}'"}} + ext.modified = ${modified.collect { "'${it}'"}} + ext.removed = ${removed.collect { "'${it}'"}} + ext.incrementalExecution = ${incremental} + """ + succeeds("incrementalCheck") } } diff --git a/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/IncrementalInputsIntegrationTest.groovy b/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/IncrementalInputsIntegrationTest.groovy index 3f283596872e4..151f0a427f1eb 100644 --- a/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/IncrementalInputsIntegrationTest.groovy +++ b/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/IncrementalInputsIntegrationTest.groovy @@ -78,7 +78,7 @@ class IncrementalInputsIntegrationTest extends AbstractIncrementalTasksIntegrati buildFile << "incremental.inputs.file('new-input.txt')" then: - executesWithRebuildContext() + executesNonIncrementally() } @Unroll @@ -189,7 +189,7 @@ class IncrementalInputsIntegrationTest extends AbstractIncrementalTasksIntegrati file('inputs/file1.txt') << "changed content" then: - executesWithIncrementalContext("ext.modified = ['file1.txt']") + executesIncrementally(modified: ['file1.txt']) } def "two incremental inputs cannot have the same value"() { diff --git a/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/IncrementalTaskInputsIntegrationTest.groovy b/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/IncrementalTaskInputsIntegrationTest.groovy index 8bd5c6403ef72..a9e1b3049013d 100644 --- a/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/IncrementalTaskInputsIntegrationTest.groovy +++ b/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/IncrementalTaskInputsIntegrationTest.groovy @@ -73,7 +73,7 @@ class IncrementalTaskInputsIntegrationTest extends AbstractIncrementalTasksInteg buildFile << "incremental.inputs.file('new-input.txt')" then: - executesWithRebuildContext("ext.modified += ['new-input.txt']") + executesNonIncrementally(preexistingInputs + ['new-input.txt']) } @Unroll From 25a4da813046ffc571706d450ac883708cd047d0 Mon Sep 17 00:00:00 2001 From: Sterling Greene Date: Fri, 15 Mar 2019 18:27:48 -0400 Subject: [PATCH 611/853] Do not hide delete errors from Sync operations --- .../file/copy/SyncCopyActionDecorator.java | 9 ++---- .../integtests/SyncTaskIntegrationTest.groovy | 30 +++++++++++++++++++ 2 files changed, 33 insertions(+), 6 deletions(-) diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/file/copy/SyncCopyActionDecorator.java b/subprojects/core/src/main/java/org/gradle/api/internal/file/copy/SyncCopyActionDecorator.java index 002d9dd99ea38..ebc1530900204 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/file/copy/SyncCopyActionDecorator.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/file/copy/SyncCopyActionDecorator.java @@ -29,6 +29,7 @@ import org.gradle.api.tasks.util.PatternSet; import org.gradle.util.GFileUtils; +import javax.annotation.Nullable; import java.io.File; import java.util.HashSet; import java.util.Set; @@ -79,7 +80,7 @@ private static class SyncCopyActionDecoratorFileVisitor implements FileVisitor { private final PatternSet preserveSet; private boolean didWork; - private SyncCopyActionDecoratorFileVisitor(Set visited, PatternFilterable preserveSpec) { + private SyncCopyActionDecoratorFileVisitor(Set visited, @Nullable PatternFilterable preserveSpec) { this.visited = visited; PatternSet preserveSet = new PatternSet(); if (preserveSpec != null) { @@ -102,11 +103,7 @@ private void maybeDelete(FileVisitDetails fileDetails, boolean isDir) { RelativePath path = fileDetails.getRelativePath(); if (!visited.contains(path)) { if (preserveSet.isEmpty() || !preserveSpec.isSatisfiedBy(fileDetails)) { - if (isDir) { - GFileUtils.deleteDirectory(fileDetails.getFile()); - } else { - GFileUtils.deleteQuietly(fileDetails.getFile()); - } + GFileUtils.forceDelete(fileDetails.getFile()); didWork = true; } } diff --git a/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/SyncTaskIntegrationTest.groovy b/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/SyncTaskIntegrationTest.groovy index eb933706487bd..08e84ab424954 100644 --- a/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/SyncTaskIntegrationTest.groovy +++ b/subprojects/integ-test/src/integTest/groovy/org/gradle/integtests/SyncTaskIntegrationTest.groovy @@ -17,6 +17,8 @@ package org.gradle.integtests import groovy.transform.NotYetImplemented import org.gradle.integtests.fixtures.AbstractIntegrationSpec +import org.gradle.util.Requires +import org.gradle.util.TestPrecondition class SyncTaskIntegrationTest extends AbstractIntegrationSpec { @@ -362,6 +364,34 @@ class SyncTaskIntegrationTest extends AbstractIntegrationSpec { !file('dest/extra.txt').exists() } + @Requires(TestPrecondition.WINDOWS) + def "sync fails when unable to clean-up files"() { + given: + file('source').create { + file 'file1.txt' + file 'file2.txt' + } + file('dest').create { + file 'extra.txt' + } + // Intentionally hold open a file + def ins = new FileInputStream(file("dest/extra.txt")) + buildScript ''' + task syncIt { + doLast { + project.sync { + from 'source' + into 'dest' + } + } + } + '''.stripIndent() + + expect: + fails 'syncIt' + ins.close() + } + def "sync from file tree"() { given: file('source').create { From 31590cef40cdadf7fa58fce6852638288e512528 Mon Sep 17 00:00:00 2001 From: Stefan Wolf Date: Mon, 18 Mar 2019 14:57:13 +0100 Subject: [PATCH 612/853] Do not cache output file changes The changes will be queried at most once, so there is no need to cache them anymore. --- .../src/main/java/org/gradle/api/tasks/SkipWhenEmpty.java | 2 +- .../src/main/java/org/gradle/work/Incremental.java | 2 +- .../changes/DefaultExecutionStateChangeDetector.java | 7 +------ 3 files changed, 3 insertions(+), 8 deletions(-) diff --git a/subprojects/core-api/src/main/java/org/gradle/api/tasks/SkipWhenEmpty.java b/subprojects/core-api/src/main/java/org/gradle/api/tasks/SkipWhenEmpty.java index 97faadd7ab761..87e89fa44b44c 100644 --- a/subprojects/core-api/src/main/java/org/gradle/api/tasks/SkipWhenEmpty.java +++ b/subprojects/core-api/src/main/java/org/gradle/api/tasks/SkipWhenEmpty.java @@ -27,7 +27,7 @@ * *

    If all of the inputs declared with this annotation are empty, the task will be skipped with a "NO-SOURCE" message.

    * - *

    Input annotated with this annotation, can be queried for changes via {@link org.gradle.work.InputChanges#getFileChanges(Object)}.

    + *

    Inputs annotated with this annotation can be queried for changes via {@link org.gradle.work.InputChanges#getFileChanges(Object)}.

    * *

    This annotation should be attached to the getter method in Java or the property in Groovy. * Annotations on setters or just the field in Java are ignored.

    diff --git a/subprojects/core-api/src/main/java/org/gradle/work/Incremental.java b/subprojects/core-api/src/main/java/org/gradle/work/Incremental.java index 67d165487586b..62b1f54bfc870 100644 --- a/subprojects/core-api/src/main/java/org/gradle/work/Incremental.java +++ b/subprojects/core-api/src/main/java/org/gradle/work/Incremental.java @@ -28,7 +28,7 @@ * Track input changes for the annotated parameter. * *

    - * Parameters annotated with {@link Incremental} can be queried via {@link InputChanges#getFileChanges(Object)}. + * Inputs annotated with {@link Incremental} can be queried for changes via {@link InputChanges#getFileChanges(Object)}. *

    * * @since 5.4 diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/DefaultExecutionStateChangeDetector.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/DefaultExecutionStateChangeDetector.java index 58afd15ef4e8a..30ce08e57d977 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/DefaultExecutionStateChangeDetector.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/DefaultExecutionStateChangeDetector.java @@ -76,11 +76,10 @@ public ExecutionStateChanges detectChanges(AfterPreviousExecutionState lastExecu thisExecution.getOutputFileProperties(), "Output", executable); - OutputFileChanges uncachedOutputChanges = new OutputFileChanges( + OutputFileChanges outputFileChanges = new OutputFileChanges( lastExecution.getOutputFileProperties(), thisExecution.getOutputFileProperties(), allowOverlappingOutputs); - ChangeContainer outputFileChanges = caching(uncachedOutputChanges); ChangeContainer rebuildTriggeringChanges = errorHandling(executable, new SummarizingChangeContainer(previousSuccessState, implementationChanges, inputPropertyChanges, inputPropertyValueChanges, outputFilePropertyChanges, outputFileChanges, inputFilePropertyChanges, nonIncrementalInputFileChanges)); @@ -101,10 +100,6 @@ public ExecutionStateChanges detectChanges(AfterPreviousExecutionState lastExecu : new IncrementalDetectedExecutionStateChanges(allChangeMessages, thisExecution.getInputFileProperties(), incrementalInputFileChanges, incrementalInputProperties); } - private static ChangeContainer caching(ChangeContainer wrapped) { - return new CachingChangeContainer(MAX_OUT_OF_DATE_MESSAGES, wrapped); - } - private static InputFileChanges caching(InputFileChanges wrapped) { CachingChangeContainer cachingChangeContainer = new CachingChangeContainer(MAX_OUT_OF_DATE_MESSAGES, wrapped); return new InputFileChangesWrapper(wrapped, cachingChangeContainer); From 01949dd860779a496e9789fc4efd041f0d956428 Mon Sep 17 00:00:00 2001 From: Gary Hale Date: Mon, 18 Mar 2019 10:06:09 -0400 Subject: [PATCH 613/853] Tweak test to remove some flakiness --- .../GarbageCollectionMonitoringIntegrationTest.groovy | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/subprojects/launcher/src/integTest/groovy/org/gradle/launcher/daemon/server/health/gc/GarbageCollectionMonitoringIntegrationTest.groovy b/subprojects/launcher/src/integTest/groovy/org/gradle/launcher/daemon/server/health/gc/GarbageCollectionMonitoringIntegrationTest.groovy index 5e0a6765d7833..6b9f062725ac1 100644 --- a/subprojects/launcher/src/integTest/groovy/org/gradle/launcher/daemon/server/health/gc/GarbageCollectionMonitoringIntegrationTest.groovy +++ b/subprojects/launcher/src/integTest/groovy/org/gradle/launcher/daemon/server/health/gc/GarbageCollectionMonitoringIntegrationTest.groovy @@ -58,7 +58,7 @@ class GarbageCollectionMonitoringIntegrationTest extends DaemonIntegrationSpec { def "expires daemon immediately when garbage collector is thrashing"() { given: configureGarbageCollectionHeapEventsFor(256, 512, 100, garbageCollector.monitoringStrategy.thrashingThreshold + 0.2) - waitForDaemonExpiration() + waitForImmediateDaemonExpiration() when: fails "injectEvents" @@ -191,7 +191,7 @@ class GarbageCollectionMonitoringIntegrationTest extends DaemonIntegrationSpec { """ } - void waitForDaemonExpiration() { + void waitForImmediateDaemonExpiration() { buildFile << """ import org.gradle.internal.event.ListenerManager import org.gradle.launcher.daemon.server.expiry.DaemonExpirationListener @@ -206,7 +206,12 @@ class GarbageCollectionMonitoringIntegrationTest extends DaemonIntegrationSpec { } }) - injectEvents.doLast { latch.await(6, TimeUnit.SECONDS) } + injectEvents.doLast { + // Wait for a daemon expiration event to occur + latch.await(6, TimeUnit.SECONDS) + // Give the monitor a chance to stop the daemon abruptly + sleep 6000 + } """ } From 203d9a82d855533649f70f04f2f1904a028f41ad Mon Sep 17 00:00:00 2001 From: Stefan Wolf Date: Tue, 5 Mar 2019 10:42:10 +0100 Subject: [PATCH 614/853] Check fewer times if dependencies complete If a unit of work finishes, only anything which depends on that unit of work can become ready for execution. There is the special case of tasks in other builds which do not notify the current task execution plan when they finish executing. So we need to keep polling for those. --- .../org/gradle/execution/plan/ActionNode.java | 5 +++ .../execution/plan/DefaultExecutionPlan.java | 39 +++++++++++++++++-- .../gradle/execution/plan/LocalTaskNode.java | 7 +++- .../java/org/gradle/execution/plan/Node.java | 13 ++++++- .../org/gradle/execution/plan/TaskNode.java | 9 ++++- .../execution/plan/TaskNodeFactory.java | 5 +++ .../transform/TransformationNode.java | 5 +++ .../transform/TransformationNodeSpec.groovy | 5 +++ 8 files changed, 81 insertions(+), 7 deletions(-) diff --git a/subprojects/core/src/main/java/org/gradle/execution/plan/ActionNode.java b/subprojects/core/src/main/java/org/gradle/execution/plan/ActionNode.java index 08ddf609cd398..392bce2152150 100644 --- a/subprojects/core/src/main/java/org/gradle/execution/plan/ActionNode.java +++ b/subprojects/core/src/main/java/org/gradle/execution/plan/ActionNode.java @@ -62,6 +62,11 @@ public boolean isPublicNode() { return false; } + @Override + public boolean requiresMonitoring() { + return false; + } + @Override public String toString() { return "work action " + action; diff --git a/subprojects/core/src/main/java/org/gradle/execution/plan/DefaultExecutionPlan.java b/subprojects/core/src/main/java/org/gradle/execution/plan/DefaultExecutionPlan.java index c7412216e1396..5f9aed9a90b96 100644 --- a/subprojects/core/src/main/java/org/gradle/execution/plan/DefaultExecutionPlan.java +++ b/subprojects/core/src/main/java/org/gradle/execution/plan/DefaultExecutionPlan.java @@ -75,6 +75,7 @@ import java.util.Collection; import java.util.Collections; import java.util.Deque; +import java.util.HashSet; import java.util.Iterator; import java.util.LinkedHashSet; import java.util.List; @@ -104,6 +105,8 @@ public class DefaultExecutionPlan implements ExecutionPlan { private final Map canonicalizedFileCache = Maps.newIdentityHashMap(); private final Map, Boolean> reachableCache = Maps.newHashMap(); private final Set dependenciesCompleteCache = Sets.newHashSet(); + private final Set dependenciesWithChanges = Sets.newHashSet(); + private final Set dependenciesWhichRequireMonitoring = Sets.newHashSet(); private final WorkerLeaseService workerLeaseService; private final GradleInternal gradle; @@ -269,10 +272,13 @@ public NodeInVisitingSegment apply(TaskNode taskNode) { int currentSegment = nodeInVisitingSegment.visitingSegment; Node node = nodeInVisitingSegment.node; - if (node.isIncludeInGraph() || nodeMapping.contains(node)) { + if (!node.isIncludeInGraph() || nodeMapping.contains(node)) { nodeQueue.remove(0); visitingNodes.remove(node, currentSegment); maybeRemoveProcessedShouldRunAfterEdge(walkedShouldRunAfterEdges, node); + if (node.requiresMonitoring()) { + dependenciesWhichRequireMonitoring.add(node); + } continue; } @@ -313,6 +319,9 @@ public NodeInVisitingSegment apply(TaskNode taskNode) { visitingNodes.remove(node, currentSegment); path.pop(); nodeMapping.add(node); + if (node.requiresMonitoring()) { + dependenciesWhichRequireMonitoring.add(node); + } MutationInfo mutations = getOrCreateMutationsOf(node); for (Node dependency : node.getDependencySuccessors()) { @@ -335,6 +344,7 @@ public NodeInVisitingSegment apply(TaskNode taskNode) { } executionQueue.clear(); Iterables.addAll(executionQueue, nodeMapping); + Iterables.addAll(dependenciesWithChanges, nodeMapping); } private MutationInfo getOrCreateMutationsOf(Node node) { @@ -506,6 +516,8 @@ public void clear() { canonicalizedFileCache.clear(); reachableCache.clear(); dependenciesCompleteCache.clear(); + dependenciesWithChanges.clear(); + dependenciesWhichRequireMonitoring.clear(); runningNodes.clear(); } @@ -540,6 +552,15 @@ public Node selectNext(WorkerLeaseRegistry.WorkerLease workerLease, ResourceLock return null; } + for (Node node : dependenciesWhichRequireMonitoring) { + if (dependenciesCompleteCache.contains(node)) { + continue; + } + if (node.isComplete()) { + dependenciesCompleteCache.add(node); + Iterables.addAll(dependenciesWithChanges, node.getAllPredecessors()); + } + } Iterator iterator = executionQueue.iterator(); while (iterator.hasNext()) { Node node = iterator.next(); @@ -558,6 +579,7 @@ public Node selectNext(WorkerLeaseRegistry.WorkerLease workerLease, ResourceLock recordNodeStarted(node); node.startExecution(); } else { + Iterables.addAll(dependenciesWithChanges, node.getAllPredecessors()); node.skipExecution(); } iterator.remove(); @@ -685,7 +707,11 @@ private boolean allDependenciesComplete(Node node) { return true; } + if (!dependenciesWithChanges.contains(node)) { + return false; + } boolean dependenciesComplete = node.allDependenciesComplete(); + dependenciesWithChanges.remove(node); if (dependenciesComplete) { dependenciesCompleteCache.add(node); } @@ -852,6 +878,7 @@ private void recordNodeStarted(Node node) { private void recordNodeCompleted(Node node) { runningNodes.remove(node); + Iterables.addAll(dependenciesWithChanges, node.getAllPredecessors()); MutationInfo mutations = this.mutations.get(node); for (Node producer : mutations.producingNodes) { MutationInfo producerMutations = this.mutations.get(producer); @@ -873,7 +900,7 @@ private static boolean canRemoveMutation(@Nullable MutationInfo mutations) { public void nodeComplete(Node node) { try { if (!node.isComplete()) { - enforceFinalizers(node); + enforceFinalizers(node, dependenciesWithChanges); if (node.isFailed()) { handleFailure(node); } @@ -886,10 +913,13 @@ public void nodeComplete(Node node) { } } - private static void enforceFinalizers(Node node) { + private static void enforceFinalizers(Node node, Set nodesWithDependencyChanges) { for (Node finalizerNode : node.getFinalizers()) { + nodesWithDependencyChanges.add(finalizerNode); if (finalizerNode.isRequired() || finalizerNode.isMustNotRun()) { - enforceWithDependencies(finalizerNode, Sets.newHashSet()); + HashSet enforcedNodes = Sets.newHashSet(); + enforceWithDependencies(finalizerNode, enforcedNodes); + nodesWithDependencyChanges.addAll(enforcedNodes); } } } @@ -952,6 +982,7 @@ public void cancelExecution() { private boolean abortExecution(boolean abortAll) { boolean aborted = false; for (Node node : nodeMapping) { + Iterables.addAll(dependenciesWithChanges, node.getAllPredecessors()); // Allow currently executing and enforced tasks to complete, but skip everything else. if (node.isRequired()) { node.skipExecution(); diff --git a/subprojects/core/src/main/java/org/gradle/execution/plan/LocalTaskNode.java b/subprojects/core/src/main/java/org/gradle/execution/plan/LocalTaskNode.java index c1e73c3746a2b..c21c5ecc3fc56 100644 --- a/subprojects/core/src/main/java/org/gradle/execution/plan/LocalTaskNode.java +++ b/subprojects/core/src/main/java/org/gradle/execution/plan/LocalTaskNode.java @@ -88,13 +88,18 @@ public void resolveDependencies(TaskDependencyResolver dependencyResolver, Actio processHardSuccessor.execute(targetNode); } for (Node targetNode : getMustRunAfter(dependencyResolver)) { - addMustSuccessor(targetNode); + addMustSuccessor((TaskNode) targetNode); } for (Node targetNode : getShouldRunAfter(dependencyResolver)) { addShouldSuccessor(targetNode); } } + @Override + public boolean requiresMonitoring() { + return false; + } + private void addFinalizerNode(TaskNode finalizerNode) { addFinalizer(finalizerNode); if (!finalizerNode.isInKnownState()) { diff --git a/subprojects/core/src/main/java/org/gradle/execution/plan/Node.java b/subprojects/core/src/main/java/org/gradle/execution/plan/Node.java index 655268aecc074..0221e67ae9a00 100644 --- a/subprojects/core/src/main/java/org/gradle/execution/plan/Node.java +++ b/subprojects/core/src/main/java/org/gradle/execution/plan/Node.java @@ -31,6 +31,10 @@ */ public abstract class Node implements Comparable { + protected Iterable getAllPredecessors() { + return getDependencyPredecessors(); + } + @VisibleForTesting enum ExecutionState { UNKNOWN, NOT_REQUIRED, SHOULD_RUN, MUST_RUN, MUST_NOT_RUN, EXECUTING, EXECUTED, SKIPPED @@ -60,7 +64,7 @@ public boolean isMustNotRun() { } public boolean isIncludeInGraph() { - return state == ExecutionState.NOT_REQUIRED || state == ExecutionState.UNKNOWN; + return state != ExecutionState.NOT_REQUIRED && state != ExecutionState.UNKNOWN; } public boolean isReady() { @@ -221,6 +225,13 @@ public boolean hasHardSuccessor(Node successor) { public abstract boolean isPublicNode(); + /** + * Whether the task needs to be queried if it is completed. + * + * Everything where the value of {@link #isComplete()} depends on some other state, like another task in an included build. + */ + public abstract boolean requiresMonitoring(); + /** * Returns the project which the node requires access to, if any. * diff --git a/subprojects/core/src/main/java/org/gradle/execution/plan/TaskNode.java b/subprojects/core/src/main/java/org/gradle/execution/plan/TaskNode.java index cc1c0f20cf77c..96a2e92d76f51 100644 --- a/subprojects/core/src/main/java/org/gradle/execution/plan/TaskNode.java +++ b/subprojects/core/src/main/java/org/gradle/execution/plan/TaskNode.java @@ -28,6 +28,7 @@ public abstract class TaskNode extends Node { private final NavigableSet mustSuccessors = Sets.newTreeSet(); + private final Set mustPredecessors = Sets.newHashSet(); private final NavigableSet shouldSuccessors = Sets.newTreeSet(); private final NavigableSet finalizers = Sets.newTreeSet(); private final NavigableSet finalizingSuccessors = Sets.newTreeSet(); @@ -68,8 +69,9 @@ public Set getShouldSuccessors() { return shouldSuccessors; } - protected void addMustSuccessor(Node toNode) { + protected void addMustSuccessor(TaskNode toNode) { mustSuccessors.add(toNode); + toNode.mustPredecessors.add(this); } protected void addFinalizingSuccessor(TaskNode finalized) { @@ -103,6 +105,11 @@ public Iterable getAllSuccessorsInReverseOrder() { ); } + @Override + public Iterable getAllPredecessors() { + return Iterables.concat(mustPredecessors, super.getAllPredecessors()); + } + @Override public boolean hasHardSuccessor(Node successor) { if (super.hasHardSuccessor(successor)) { diff --git a/subprojects/core/src/main/java/org/gradle/execution/plan/TaskNodeFactory.java b/subprojects/core/src/main/java/org/gradle/execution/plan/TaskNodeFactory.java index 4789dcb83141a..29def83f4ab8e 100644 --- a/subprojects/core/src/main/java/org/gradle/execution/plan/TaskNodeFactory.java +++ b/subprojects/core/src/main/java/org/gradle/execution/plan/TaskNodeFactory.java @@ -127,6 +127,11 @@ public void prepareForExecution() { public void resolveDependencies(TaskDependencyResolver dependencyResolver, Action processHardSuccessor) { } + @Override + public boolean requiresMonitoring() { + return true; + } + @Override public void require() { // Ignore diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/TransformationNode.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/TransformationNode.java index 21acefb35a698..240e58c204485 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/TransformationNode.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/TransformationNode.java @@ -65,6 +65,11 @@ public boolean isPublicNode() { return true; } + @Override + public boolean requiresMonitoring() { + return false; + } + @Override public String toString() { return transformationStep.getDisplayName(); diff --git a/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/TransformationNodeSpec.groovy b/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/TransformationNodeSpec.groovy index e779b92a62153..1d23992b3736e 100644 --- a/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/TransformationNodeSpec.groovy +++ b/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/TransformationNodeSpec.groovy @@ -118,6 +118,11 @@ class TransformationNodeSpec extends Specification { return true } + @Override + boolean requiresMonitoring() { + return false + } + @Override String toString() { return null From 0818d05c3674f9c3808b5f71600f3f39ad917ce4 Mon Sep 17 00:00:00 2001 From: Stefan Wolf Date: Tue, 5 Mar 2019 14:02:16 +0100 Subject: [PATCH 615/853] Even fewer iterating the execution queue We only can find something to execute, if there is already something to execute or something finished executing. --- .../org/gradle/execution/plan/DefaultExecutionPlan.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/subprojects/core/src/main/java/org/gradle/execution/plan/DefaultExecutionPlan.java b/subprojects/core/src/main/java/org/gradle/execution/plan/DefaultExecutionPlan.java index 5f9aed9a90b96..0b7e7ccb17dba 100644 --- a/subprojects/core/src/main/java/org/gradle/execution/plan/DefaultExecutionPlan.java +++ b/subprojects/core/src/main/java/org/gradle/execution/plan/DefaultExecutionPlan.java @@ -107,6 +107,7 @@ public class DefaultExecutionPlan implements ExecutionPlan { private final Set dependenciesCompleteCache = Sets.newHashSet(); private final Set dependenciesWithChanges = Sets.newHashSet(); private final Set dependenciesWhichRequireMonitoring = Sets.newHashSet(); + private final Set readyToExecute = Sets.newHashSet(); private final WorkerLeaseService workerLeaseService; private final GradleInternal gradle; @@ -561,6 +562,9 @@ public Node selectNext(WorkerLeaseRegistry.WorkerLease workerLease, ResourceLock Iterables.addAll(dependenciesWithChanges, node.getAllPredecessors()); } } + if (readyToExecute.isEmpty() && dependenciesWithChanges.isEmpty()) { + return null; + } Iterator iterator = executionQueue.iterator(); while (iterator.hasNext()) { Node node = iterator.next(); @@ -572,6 +576,7 @@ public Node selectNext(WorkerLeaseRegistry.WorkerLease workerLease, ResourceLock || !workerLease.tryLock() || !canRunWithCurrentlyExecutedNodes(node, mutations)) { resourceLockState.releaseLocks(); + readyToExecute.add(node); continue; } @@ -583,7 +588,7 @@ public Node selectNext(WorkerLeaseRegistry.WorkerLease workerLease, ResourceLock node.skipExecution(); } iterator.remove(); - + readyToExecute.remove(node); return node; } } From 575b6bf1c26afe0889a5789a78be3abecf49452d Mon Sep 17 00:00:00 2001 From: Stefan Wolf Date: Tue, 5 Mar 2019 14:38:25 +0100 Subject: [PATCH 616/853] Use a list for remembering monitoring nodes This should improve iteration speed. --- .../java/org/gradle/execution/plan/DefaultExecutionPlan.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/subprojects/core/src/main/java/org/gradle/execution/plan/DefaultExecutionPlan.java b/subprojects/core/src/main/java/org/gradle/execution/plan/DefaultExecutionPlan.java index 0b7e7ccb17dba..844e18c8cce17 100644 --- a/subprojects/core/src/main/java/org/gradle/execution/plan/DefaultExecutionPlan.java +++ b/subprojects/core/src/main/java/org/gradle/execution/plan/DefaultExecutionPlan.java @@ -106,7 +106,7 @@ public class DefaultExecutionPlan implements ExecutionPlan { private final Map, Boolean> reachableCache = Maps.newHashMap(); private final Set dependenciesCompleteCache = Sets.newHashSet(); private final Set dependenciesWithChanges = Sets.newHashSet(); - private final Set dependenciesWhichRequireMonitoring = Sets.newHashSet(); + private final List dependenciesWhichRequireMonitoring = Lists.newArrayList(); private final Set readyToExecute = Sets.newHashSet(); private final WorkerLeaseService workerLeaseService; private final GradleInternal gradle; @@ -262,6 +262,7 @@ public NodeInVisitingSegment apply(TaskNode taskNode) { } })); int visitingSegmentCounter = nodeQueue.size(); + Set dependenciesWhichRequireMonitoring = Sets.newHashSet(); HashMultimap visitingNodes = HashMultimap.create(); Deque walkedShouldRunAfterEdges = new ArrayDeque(); @@ -346,6 +347,7 @@ public NodeInVisitingSegment apply(TaskNode taskNode) { executionQueue.clear(); Iterables.addAll(executionQueue, nodeMapping); Iterables.addAll(dependenciesWithChanges, nodeMapping); + this.dependenciesWhichRequireMonitoring.addAll(dependenciesWhichRequireMonitoring); } private MutationInfo getOrCreateMutationsOf(Node node) { @@ -519,6 +521,7 @@ public void clear() { dependenciesCompleteCache.clear(); dependenciesWithChanges.clear(); dependenciesWhichRequireMonitoring.clear(); + readyToExecute.clear(); runningNodes.clear(); } From 650a1b72543ae932b50b40e952bb1adab0b3772f Mon Sep 17 00:00:00 2001 From: Stefan Wolf Date: Mon, 18 Mar 2019 23:15:57 +0100 Subject: [PATCH 617/853] Enable caching for Minify transform The minify transform seems to be expensive at times. Let's cache it! --- .../src/main/kotlin/org/gradle/gradlebuild/packaging/Minify.kt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/buildSrc/subprojects/packaging/src/main/kotlin/org/gradle/gradlebuild/packaging/Minify.kt b/buildSrc/subprojects/packaging/src/main/kotlin/org/gradle/gradlebuild/packaging/Minify.kt index 659f9ad01b347..5098cd5f2f5b7 100644 --- a/buildSrc/subprojects/packaging/src/main/kotlin/org/gradle/gradlebuild/packaging/Minify.kt +++ b/buildSrc/subprojects/packaging/src/main/kotlin/org/gradle/gradlebuild/packaging/Minify.kt @@ -17,6 +17,7 @@ package org.gradle.gradlebuild.packaging import com.google.common.io.Files +import org.gradle.api.artifacts.transform.CacheableTransform import org.gradle.api.artifacts.transform.InputArtifact import org.gradle.api.artifacts.transform.TransformAction import org.gradle.api.artifacts.transform.TransformOutputs @@ -31,6 +32,7 @@ import java.util.jar.JarFile import java.util.jar.JarOutputStream +@CacheableTransform abstract class Minify : TransformAction { interface Parameters : TransformParameters { From 96c497ba6128286ac9b123b8c04d0e9eec78fe4f Mon Sep 17 00:00:00 2001 From: Gradleware Git Bot Date: Tue, 19 Mar 2019 02:22:54 +0100 Subject: [PATCH 618/853] Publish 5.3-20190319010128+0000 --- released-versions.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/released-versions.json b/released-versions.json index a2a89574fc41a..8432d7afc51b3 100644 --- a/released-versions.json +++ b/released-versions.json @@ -1,7 +1,7 @@ { "latestReleaseSnapshot": { - "version": "5.3-20190318010052+0000", - "buildTime": "20190318010052+0000" + "version": "5.3-20190319010128+0000", + "buildTime": "20190319010128+0000" }, "latestRc": { "version": "5.3-rc-3", From 10959fbcfb088eaae863db8cb7b41cfe60953563 Mon Sep 17 00:00:00 2001 From: Paul Merlin Date: Tue, 19 Mar 2019 09:24:03 +0100 Subject: [PATCH 619/853] Let GradleKotlinDslIntegrationTest exercise under dev `kotlin-dsl` plugin Signed-off-by: Paul Merlin --- .../kotlin/dsl/integration/GradleKotlinDslIntegrationTest.kt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/subprojects/kotlin-dsl-integ-tests/src/integTest/kotlin/org/gradle/kotlin/dsl/integration/GradleKotlinDslIntegrationTest.kt b/subprojects/kotlin-dsl-integ-tests/src/integTest/kotlin/org/gradle/kotlin/dsl/integration/GradleKotlinDslIntegrationTest.kt index f440f2950bae5..95cfaf7989afb 100644 --- a/subprojects/kotlin-dsl-integ-tests/src/integTest/kotlin/org/gradle/kotlin/dsl/integration/GradleKotlinDslIntegrationTest.kt +++ b/subprojects/kotlin-dsl-integ-tests/src/integTest/kotlin/org/gradle/kotlin/dsl/integration/GradleKotlinDslIntegrationTest.kt @@ -22,7 +22,6 @@ import okhttp3.mockwebserver.MockWebServer import org.gradle.test.fixtures.file.LeaksFileHandles import org.gradle.kotlin.dsl.embeddedKotlinVersion -import org.gradle.kotlin.dsl.fixtures.AbstractKotlinIntegrationTest import org.gradle.kotlin.dsl.fixtures.DeepThought import org.gradle.kotlin.dsl.fixtures.LightThought import org.gradle.kotlin.dsl.fixtures.ZeroThought @@ -38,7 +37,7 @@ import org.junit.Assert.assertNotEquals import org.junit.Test -class GradleKotlinDslIntegrationTest : AbstractKotlinIntegrationTest() { +class GradleKotlinDslIntegrationTest : AbstractPluginIntegrationTest() { @Test fun `given a buildscript block, it will be used to compute the runtime classpath`() { From f4d7a9d486115081cf4f91c74116f429c4e5217a Mon Sep 17 00:00:00 2001 From: Bo Zhang Date: Tue, 19 Mar 2019 17:41:06 +0800 Subject: [PATCH 620/853] Fix failed TC configuration test This commit fixes failed TC configuration test by adding crossVersionTests=true to CIBuildModel. --- .teamcity/Gradle_Check/model/CIBuildModel.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.teamcity/Gradle_Check/model/CIBuildModel.kt b/.teamcity/Gradle_Check/model/CIBuildModel.kt index 4659a816131b0..c8d2a14c906b1 100644 --- a/.teamcity/Gradle_Check/model/CIBuildModel.kt +++ b/.teamcity/Gradle_Check/model/CIBuildModel.kt @@ -173,7 +173,7 @@ data class CIBuildModel ( GradleSubproject("kotlinDsl", unitTests = true, functionalTests = true), GradleSubproject("kotlinDslProviderPlugins", unitTests = true, functionalTests = true), GradleSubproject("kotlinDslToolingModels", unitTests = false, functionalTests = false), - GradleSubproject("kotlinDslToolingBuilders", unitTests = true, functionalTests = true), + GradleSubproject("kotlinDslToolingBuilders", unitTests = true, functionalTests = true, crossVersionTests = true), GradleSubproject("kotlinDslPlugins", unitTests = true, functionalTests = true), GradleSubproject("kotlinDslTestFixtures", unitTests = true, functionalTests = false), GradleSubproject("kotlinDslIntegTests", unitTests = false, functionalTests = true), From 68075580b3c75ec65e6a206a4b6ba5beca028a4e Mon Sep 17 00:00:00 2001 From: Daniel Lacasse Date: Mon, 18 Mar 2019 14:11:04 +0100 Subject: [PATCH 621/853] Unlink the software model chapters from multi page userguide The software model chapters are left intact for the single page given we don't want to remove the chapters from the PDF version of the user documentation. --- subprojects/docs/src/docs/userguide/native_software.adoc | 7 +++---- subprojects/docs/src/docs/userguide/rule_source.adoc | 7 +++++++ subprojects/docs/src/docs/userguide/software_model.adoc | 4 +++- .../docs/src/docs/userguide/software_model_concepts.adoc | 6 +++++- .../docs/src/docs/userguide/software_model_extend.adoc | 4 +++- subprojects/docs/src/main/resources/header.html | 5 ----- 6 files changed, 21 insertions(+), 12 deletions(-) diff --git a/subprojects/docs/src/docs/userguide/native_software.adoc b/subprojects/docs/src/docs/userguide/native_software.adoc index c910ad1e43fed..34dbd68a5e832 100644 --- a/subprojects/docs/src/docs/userguide/native_software.adoc +++ b/subprojects/docs/src/docs/userguide/native_software.adoc @@ -16,11 +16,10 @@ = Building native software -[NOTE] +[CAUTION] ==== - -The https://blog.gradle.org/state-and-future-of-the-gradle-software-model[software model] is being retired and the plugins mentioned in this chapter will eventually be deprecated and removed. We recommend new projects looking to build C++ applications and libraries use the newer <>. - +The https://blog.gradle.org/state-and-future-of-the-gradle-software-model[software model] is being retired and the plugins mentioned in this chapter will eventually be deprecated and removed. +We recommend new projects looking to build C++ applications and libraries use the newer <>. ==== The native software plugins add support for building native software components, such as executables or shared libraries, from code written in C++, C and other languages. While many excellent build tools exist for this space of software development, Gradle offers developers its trademark power and flexibility together with dependency management practices more traditionally found in the JVM development space. diff --git a/subprojects/docs/src/docs/userguide/rule_source.adoc b/subprojects/docs/src/docs/userguide/rule_source.adoc index 431010b591654..3583562839980 100644 --- a/subprojects/docs/src/docs/userguide/rule_source.adoc +++ b/subprojects/docs/src/docs/userguide/rule_source.adoc @@ -15,6 +15,13 @@ [[rule_source]] = Implementing model rules in a plugin +[CAUTION] +==== +Rule based configuration link:https://blog.gradle.org/state-and-future-of-the-gradle-software-model[will be deprecated]. +New plugins should not use this concept. +Instead, use the standard approach described in the <> chapter. +==== + A plugin can define rules by extending link:{javadocPath}/org/gradle/model/RuleSource.html[RuleSource] and adding methods that define the rules. The plugin class can either extend link:{javadocPath}/org/gradle/model/RuleSource.html[RuleSource] directly or can implement link:{javadocPath}/org/gradle/api/Plugin.html[Plugin] and include a nested link:{javadocPath}/org/gradle/model/RuleSource.html[RuleSource] subclass. Refer to the API docs for link:{javadocPath}/org/gradle/model/RuleSource.html[RuleSource] for more details. diff --git a/subprojects/docs/src/docs/userguide/software_model.adoc b/subprojects/docs/src/docs/userguide/software_model.adoc index d3384afec18e8..96c26f2fbc6f8 100644 --- a/subprojects/docs/src/docs/userguide/software_model.adoc +++ b/subprojects/docs/src/docs/userguide/software_model.adoc @@ -17,7 +17,9 @@ [CAUTION] ==== -Rule based configuration link:https://blog.gradle.org/state-and-future-of-the-gradle-software-model[will be deprecated]. New plugins should not use this concept. +Rule based configuration link:https://blog.gradle.org/state-and-future-of-the-gradle-software-model[will be deprecated]. +New plugins should not use this concept. +Instead, use the standard approach described in the <> chapter. ==== Rule based model configuration enables _configuration logic to itself have dependencies_ on other elements of configuration, and to make use of the resolved states of those other elements of configuration while performing its own configuration. diff --git a/subprojects/docs/src/docs/userguide/software_model_concepts.adoc b/subprojects/docs/src/docs/userguide/software_model_concepts.adoc index 72f2cdcad9e82..16ae490f17f42 100644 --- a/subprojects/docs/src/docs/userguide/software_model_concepts.adoc +++ b/subprojects/docs/src/docs/userguide/software_model_concepts.adoc @@ -17,7 +17,9 @@ [CAUTION] ==== -Rule based configuration link:https://blog.gradle.org/state-and-future-of-the-gradle-software-model[will be deprecated]. New plugins should not use this concept. +Rule based configuration link:https://blog.gradle.org/state-and-future-of-the-gradle-software-model[will be deprecated]. +New plugins should not use this concept. +Instead, use the standard approach described in the <> chapter. ==== The software model describes how a piece of software is built and how the components of the software relate to each other. The software model is organized around some key concepts: @@ -28,3 +30,5 @@ The software model describes how a piece of software is built and how the compon * A _binary_ represents some output that is built for a component. A component may produce multiple different output binaries. For example, for a C++ library, both a shared library and a static library binary may be produced. Each binary is initially configured to be built from the component sources, but additional source sets can be added to specific binary variants. * A _variant_ represents some mutually exclusive binary of a component. A library, for example, might target Java 7 and Java 8, effectively producing two distinct binaries: a Java 7 Jar and a Java 8 Jar. These are different variants of the library. * The _API_ of a library represents the artifacts and dependencies that are required to compile against that library. The API typically consists of a binary together with a set of dependencies. + +The <>, enabling deep modeling of specific domains via richly typed DSLs. \ No newline at end of file diff --git a/subprojects/docs/src/docs/userguide/software_model_extend.adoc b/subprojects/docs/src/docs/userguide/software_model_extend.adoc index f075ca90fe5df..f8bfa2cd55de2 100644 --- a/subprojects/docs/src/docs/userguide/software_model_extend.adoc +++ b/subprojects/docs/src/docs/userguide/software_model_extend.adoc @@ -17,7 +17,9 @@ [CAUTION] ==== -Rule based configuration link:https://blog.gradle.org/state-and-future-of-the-gradle-software-model[will be deprecated]. New plugins should not use this concept. +Rule based configuration link:https://blog.gradle.org/state-and-future-of-the-gradle-software-model[will be deprecated]. +New plugins should not use this concept. +Instead, use the standard approach described in the <> chapter. ==== == Introduction diff --git a/subprojects/docs/src/main/resources/header.html b/subprojects/docs/src/main/resources/header.html index f7396deaec1f8..b0b6f9453a09e 100644 --- a/subprojects/docs/src/main/resources/header.html +++ b/subprojects/docs/src/main/resources/header.html @@ -197,11 +197,6 @@

    Authoring Gradle Builds

  • From 1c253e9c9dd0eb8d11829fe9e46917b6b80c162e Mon Sep 17 00:00:00 2001 From: Rene Groeschke Date: Sun, 10 Feb 2019 20:21:18 +0100 Subject: [PATCH 622/853] Decorate task logger with build operation id so usage from external thread is linked to correct task --- ...gingBuildOperationProgressIntegTest.groovy | 75 ++- .../org/gradle/api/internal/AbstractTask.java | 3 +- .../execution/EventFiringTaskExecuter.java | 13 + .../execution/ExecuteActionsTaskExecuter.java | 9 +- .../api/internal/DefaultTaskTest.groovy | 4 +- .../slf4j/BuildOperationAwareLogger.java | 27 + .../slf4j/ContextAwareBuildLogger.java | 481 ++++++++++++++++++ .../OutputEventListenerBackedLogger.java | 18 +- 8 files changed, 605 insertions(+), 25 deletions(-) create mode 100644 subprojects/logging/src/main/java/org/gradle/internal/logging/slf4j/BuildOperationAwareLogger.java create mode 100644 subprojects/logging/src/main/java/org/gradle/internal/logging/slf4j/ContextAwareBuildLogger.java diff --git a/subprojects/core/src/integTest/groovy/org/gradle/internal/operations/logging/LoggingBuildOperationProgressIntegTest.groovy b/subprojects/core/src/integTest/groovy/org/gradle/internal/operations/logging/LoggingBuildOperationProgressIntegTest.groovy index 0bef423163a3a..5b20659ae9f02 100644 --- a/subprojects/core/src/integTest/groovy/org/gradle/internal/operations/logging/LoggingBuildOperationProgressIntegTest.groovy +++ b/subprojects/core/src/integTest/groovy/org/gradle/internal/operations/logging/LoggingBuildOperationProgressIntegTest.groovy @@ -19,6 +19,7 @@ package org.gradle.internal.operations.logging import org.gradle.api.internal.tasks.execution.ExecuteTaskBuildOperationType import org.gradle.integtests.fixtures.AbstractIntegrationSpec import org.gradle.integtests.fixtures.BuildOperationsFixture +import org.gradle.internal.logging.events.LogEvent import org.gradle.internal.logging.events.operations.LogEventBuildOperationProgressDetails import org.gradle.internal.logging.events.operations.ProgressStartBuildOperationProgressDetails import org.gradle.internal.logging.events.operations.StyledTextBuildOperationProgressDetails @@ -61,8 +62,6 @@ class LoggingBuildOperationProgressIntegTest extends AbstractIntegrationSpec { """ file("build.gradle") << """ - import java.util.concurrent.CountDownLatch - apply plugin: 'java' repositories { @@ -76,14 +75,6 @@ class LoggingBuildOperationProgressIntegTest extends AbstractIntegrationSpec { jar.doLast { println 'from jar task' } - - classes.doLast { - CountDownLatch latch = new CountDownLatch(1); - - def t = new Thread({ println 'from classes task external thread'; latch.countDown(); } as Runnable) - t.start() // Output: hello - latch.await(); - } task resolve { doLast { @@ -148,13 +139,65 @@ class LoggingBuildOperationProgressIntegTest extends AbstractIntegrationSpec { operations.parentsOf(downloadEvent).find { it.hasDetailsOfType(ExecuteTaskBuildOperationType.Details) && it.details.taskPath == ":resolve" } + } + + def "captures threaded output sources with context"() { + given: + executer.requireOwnGradleUserHomeDir() + settingsFile << """ + rootProject.name = 'root' + 10.times { + include "project-\${it}" + } + """ + file("build.gradle") << """ + import java.util.concurrent.CountDownLatch + + subprojects { + 10.times { + task("myTask\$it") { tsk -> + doLast { + threaded { + logger.lifecycle("from \${tsk.path} task external thread") + } + } + } + } + task all(dependsOn: tasks.matching{it.name.startsWith('myTask')}) + } + + + threaded { + println("threaded configuration output") + } + + def threaded(Closure action) { + CountDownLatch latch = new CountDownLatch(1); + def t = new Thread({ action.call(); latch.countDown(); } as Runnable) + t.start() + latch.await(); + } + """ + + when: + succeeds("all") + + then: + 10.times { projectCount -> + 10.times { taskCount -> + def taskExecutionOp = operations.only("Task :project-${projectCount}:myTask$taskCount") + def classesTaskProgresses = taskExecutionOp.progress + def threadedTaskLoggingProgress = classesTaskProgresses.find { it.detailsType == LogEvent && it.details.message == "from :project-${projectCount}:myTask$taskCount task external thread" } + assert threadedTaskLoggingProgress.details.logLevel == 'LIFECYCLE' + } + } def runBuildProgress = operations.only('Run build').progress - def threadedProgress = runBuildProgress.find { it.details.spans[0].text == "from classes task external thread${getPlatformLineSeparator()}" } - threadedProgress.details.category == 'system.out' - threadedProgress.details.spans.size == 1 - threadedProgress.details.spans[0].styleName == 'Normal' - threadedProgress.details.spans[0].text == "from classes task external thread${getPlatformLineSeparator()}" + def threadedConfigurationProgress = runBuildProgress.find { it.details.spans[0].text == "threaded configuration output${getPlatformLineSeparator()}" } + threadedConfigurationProgress.details.category == 'system.out' + threadedConfigurationProgress.details.spans.size == 1 + threadedConfigurationProgress.details.spans[0].styleName == 'Normal' + threadedConfigurationProgress.details.spans[0].text == "threaded configuration output${getPlatformLineSeparator()}" } def "captures output from buildSrc"() { @@ -364,7 +407,7 @@ class LoggingBuildOperationProgressIntegTest extends AbstractIntegrationSpec { assert nestedTaskProgress[0].details.spans[0].text == "foo println${getPlatformLineSeparator()}" assert nestedTaskProgress[1].details.logLevel == 'LIFECYCLE' - assert nestedTaskProgress[1].details.category == 'org.gradle.api.Task' + assert nestedTaskProgress[1].details.category == "org.gradle.api.Task" assert nestedTaskProgress[1].details.message == 'foo from logger' } diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/AbstractTask.java b/subprojects/core/src/main/java/org/gradle/api/internal/AbstractTask.java index 8b4b8cc21b327..d498ab95e1c29 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/AbstractTask.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/AbstractTask.java @@ -63,6 +63,7 @@ import org.gradle.internal.execution.history.changes.InputChangesInternal; import org.gradle.internal.extensibility.ExtensibleDynamicObject; import org.gradle.internal.logging.compatbridge.LoggingManagerInternalCompatibilityBridge; +import org.gradle.internal.logging.slf4j.ContextAwareBuildLogger; import org.gradle.internal.metaobject.DynamicObject; import org.gradle.internal.reflect.Instantiator; import org.gradle.internal.scripts.ScriptOrigin; @@ -121,7 +122,7 @@ public abstract class AbstractTask implements TaskInternal, DynamicObjectAware { private final TaskStateInternal state; - private Logger logger = BUILD_LOGGER; + private Logger logger = new ContextAwareBuildLogger(BUILD_LOGGER); private final TaskMutator taskMutator; private ObservableList observableActionList; diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/EventFiringTaskExecuter.java b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/EventFiringTaskExecuter.java index e3928998c8d0c..15861d7707759 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/EventFiringTaskExecuter.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/EventFiringTaskExecuter.java @@ -22,11 +22,14 @@ import org.gradle.api.internal.tasks.TaskExecuterResult; import org.gradle.api.internal.tasks.TaskExecutionContext; import org.gradle.api.internal.tasks.TaskStateInternal; +import org.gradle.api.logging.Logger; import org.gradle.api.tasks.TaskExecutionException; +import org.gradle.internal.logging.slf4j.ContextAwareBuildLogger; import org.gradle.internal.operations.BuildOperationCategory; import org.gradle.internal.operations.BuildOperationContext; import org.gradle.internal.operations.BuildOperationDescriptor; import org.gradle.internal.operations.BuildOperationExecutor; +import org.gradle.internal.operations.BuildOperationRef; import org.gradle.internal.operations.CallableBuildOperation; public class EventFiringTaskExecuter implements TaskExecuter { @@ -53,8 +56,15 @@ public TaskExecuterResult call(BuildOperationContext operationContext) { } private TaskExecuterResult executeTask(BuildOperationContext operationContext) { + Logger logger = task.getLogger(); + ContextAwareBuildLogger contextAwareBuildLogger = null; try { taskExecutionListener.beforeExecute(task); + BuildOperationRef currentOperation = buildOperationExecutor.getCurrentOperation(); + if(logger instanceof ContextAwareBuildLogger) { + contextAwareBuildLogger = (ContextAwareBuildLogger) logger; + contextAwareBuildLogger.setFallbackBuildOperationId(currentOperation.getId()); + } } catch (Throwable t) { state.setOutcome(new TaskExecutionException(task, t)); return TaskExecuterResult.WITHOUT_OUTPUTS; @@ -62,6 +72,9 @@ private TaskExecuterResult executeTask(BuildOperationContext operationContext) { TaskExecuterResult result = delegate.execute(task, state, context); + if(contextAwareBuildLogger != null){ + contextAwareBuildLogger.setFallbackBuildOperationId(null); + } operationContext.setResult(new ExecuteTaskBuildOperationResult( state, result.getReusedOutputOriginMetadata().orElse(null), diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuter.java b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuter.java index 00362e6d53df3..653703624bc7a 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuter.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuter.java @@ -259,8 +259,8 @@ public Optional load(Function> loader) { LOGGER.info("Custom actions are attached to {}.", task); } if (context.isTaskCachingEnabled() - && context.getTaskExecutionMode().isAllowedToUseCachedResults() - && context.getBuildCacheKey().isValid() + && context.getTaskExecutionMode().isAllowedToUseCachedResults() + && context.getBuildCacheKey().isValid() ) { return loader.apply(context.getBuildCacheKey()); } else { @@ -271,8 +271,8 @@ public Optional load(Function> loader) { @Override public void store(Consumer storer) { if (buildCacheEnabled - && context.isTaskCachingEnabled() - && context.getBuildCacheKey().isValid() + && context.isTaskCachingEnabled() + && context.getBuildCacheKey().isValid() ) { storer.accept(context.getBuildCacheKey()); } @@ -422,4 +422,5 @@ public MultipleTaskActionFailures(String message, Iterable super(message, causes); } } + } diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/DefaultTaskTest.groovy b/subprojects/core/src/test/groovy/org/gradle/api/internal/DefaultTaskTest.groovy index 253d6f3ffa00d..9d64c5790cf2d 100644 --- a/subprojects/core/src/test/groovy/org/gradle/api/internal/DefaultTaskTest.groovy +++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/DefaultTaskTest.groovy @@ -30,6 +30,7 @@ import org.gradle.api.tasks.TaskExecutionException import org.gradle.api.tasks.TaskInstantiationException import org.gradle.internal.Actions import org.gradle.internal.event.ListenerManager +import org.gradle.internal.logging.slf4j.ContextAwareBuildLogger import spock.lang.Issue import java.util.concurrent.Callable @@ -526,7 +527,8 @@ class DefaultTaskTest extends AbstractTaskTest { def "can replace task logger"() { expect: - task.logger == AbstractTask.BUILD_LOGGER + task.logger instanceof ContextAwareBuildLogger + task.logger.delegate == AbstractTask.BUILD_LOGGER when: def logger = Mock(Logger) diff --git a/subprojects/logging/src/main/java/org/gradle/internal/logging/slf4j/BuildOperationAwareLogger.java b/subprojects/logging/src/main/java/org/gradle/internal/logging/slf4j/BuildOperationAwareLogger.java new file mode 100644 index 0000000000000..8b009131902a9 --- /dev/null +++ b/subprojects/logging/src/main/java/org/gradle/internal/logging/slf4j/BuildOperationAwareLogger.java @@ -0,0 +1,27 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.internal.logging.slf4j; + +import org.gradle.api.logging.LogLevel; +import org.gradle.api.logging.Logger; +import org.gradle.internal.operations.OperationIdentifier; + +abstract class BuildOperationAwareLogger implements Logger { + + abstract void log(LogLevel logLevel, Throwable throwable, String message, OperationIdentifier operationIdentifier); + +} diff --git a/subprojects/logging/src/main/java/org/gradle/internal/logging/slf4j/ContextAwareBuildLogger.java b/subprojects/logging/src/main/java/org/gradle/internal/logging/slf4j/ContextAwareBuildLogger.java new file mode 100644 index 0000000000000..f6ac7c5c9e211 --- /dev/null +++ b/subprojects/logging/src/main/java/org/gradle/internal/logging/slf4j/ContextAwareBuildLogger.java @@ -0,0 +1,481 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.internal.logging.slf4j; + +import org.gradle.api.logging.LogLevel; +import org.gradle.api.logging.Logger; +import org.gradle.api.logging.Logging; +import org.gradle.internal.operations.CurrentBuildOperationRef; +import org.gradle.internal.operations.OperationIdentifier; +import org.slf4j.Marker; +import org.slf4j.helpers.FormattingTuple; +import org.slf4j.helpers.MessageFormatter; + +public class ContextAwareBuildLogger implements Logger { + + private final BuildOperationAwareLogger delegate; + private OperationIdentifier fallbackOperationIdentifier = null; + + public ContextAwareBuildLogger(Logger delegate) { + this.delegate = (BuildOperationAwareLogger) delegate; + } + + public void setFallbackBuildOperationId(OperationIdentifier operationIdentifier) { + this.fallbackOperationIdentifier = operationIdentifier; + } + + @Override + public boolean isLifecycleEnabled() { + return delegate.isLifecycleEnabled(); + } + + @Override + public boolean isQuietEnabled() { + return delegate.isQuietEnabled(); + } + + @Override + public boolean isEnabled(LogLevel level) { + return delegate.isEnabled(level); + } + + @Override + public String getName() { + return delegate.getName(); + } + + @Override + public boolean isTraceEnabled() { + return delegate.isTraceEnabled(); + } + + @Override + public boolean isTraceEnabled(Marker marker) { + return delegate.isTraceEnabled(marker); + } + + @Override + public boolean isDebugEnabled() { + return delegate.isDebugEnabled(); + } + + @Override + public boolean isDebugEnabled(Marker marker) { + return delegate.isDebugEnabled(marker); + } + + @Override + public boolean isInfoEnabled() { + return delegate.isInfoEnabled(); + } + + @Override + public boolean isInfoEnabled(Marker marker) { + return delegate.isInfoEnabled(marker); + } + + @Override + public boolean isWarnEnabled() { + return delegate.isWarnEnabled(); + } + + @Override + public boolean isWarnEnabled(Marker marker) { + return delegate.isWarnEnabled(marker); + } + + @Override + public boolean isErrorEnabled() { + return delegate.isErrorEnabled(); + } + + @Override + public boolean isErrorEnabled(Marker marker) { + return delegate.isErrorEnabled(marker); + } + + public void trace(String msg) { + } + + public void trace(String format, Object arg) { + } + + public void trace(String format, Object arg1, Object arg2) { + } + + public void trace(String format, Object... arguments) { + } + + public void trace(String msg, Throwable t) { + } + + public void trace(Marker marker, String msg) { + } + + public void trace(Marker marker, String format, Object arg) { + } + + public void trace(Marker marker, String format, Object arg1, Object arg2) { + } + + public void trace(Marker marker, String format, Object... argArray) { + } + + public void trace(Marker marker, String msg, Throwable t) { + } + + private void log(LogLevel logLevel, Throwable throwable, String message) { + OperationIdentifier buildOperationId = CurrentBuildOperationRef.instance().getId(); + if (buildOperationId == null) { + buildOperationId = fallbackOperationIdentifier; + } + delegate.log(logLevel, throwable, message, buildOperationId); + } + + private void log(LogLevel logLevel, Throwable throwable, String format, Object arg) { + log(logLevel, throwable, format, new Object[]{arg}); + } + + private void log(LogLevel logLevel, Throwable throwable, String format, Object arg1, Object arg2) { + log(logLevel, throwable, format, new Object[]{arg1, arg2}); + } + + private void log(LogLevel logLevel, Throwable throwable, String format, Object[] args) { + FormattingTuple tuple = MessageFormatter.arrayFormat(format, args); + Throwable loggedThrowable = throwable == null ? tuple.getThrowable() : throwable; + + log(logLevel, loggedThrowable, tuple.getMessage()); + } + + public void debug(String message) { + if (isDebugEnabled()) { + log(LogLevel.DEBUG, null, message); + } + } + + public void debug(String format, Object arg) { + if (isDebugEnabled()) { + log(LogLevel.DEBUG, null, format, arg); + } + } + + public void debug(String format, Object arg1, Object arg2) { + if (isDebugEnabled()) { + log(LogLevel.DEBUG, null, format, arg1, arg2); + } + } + + public void debug(String format, Object... arguments) { + if (isDebugEnabled()) { + log(LogLevel.DEBUG, null, format, arguments); + } + } + + public void debug(String msg, Throwable t) { + if (isDebugEnabled()) { + log(LogLevel.DEBUG, t, msg); + } + } + + public void debug(Marker marker, String msg) { + if (isDebugEnabled(marker)) { + log(LogLevel.DEBUG, null, msg); + } + } + + public void debug(Marker marker, String format, Object arg) { + if (isDebugEnabled(marker)) { + log(LogLevel.DEBUG, null, format, arg); + } + } + + public void debug(Marker marker, String format, Object arg1, Object arg2) { + if (isDebugEnabled(marker)) { + log(LogLevel.DEBUG, null, format, arg1, arg2); + } + } + + public void debug(Marker marker, String format, Object... argArray) { + if (isDebugEnabled(marker)) { + log(LogLevel.DEBUG, null, format, argArray); + } + } + + public void debug(Marker marker, String msg, Throwable t) { + if (isDebugEnabled(marker)) { + log(LogLevel.DEBUG, t, msg); + } + } + + public void info(String message) { + if (isInfoEnabled()) { + log(LogLevel.INFO, null, message); + } + } + + public void info(String format, Object arg) { + if (isInfoEnabled()) { + log(LogLevel.INFO, null, format, arg); + } + } + + public void info(String format, Object arg1, Object arg2) { + if (isInfoEnabled()) { + log(LogLevel.INFO, null, format, arg1, arg2); + } + } + + public void info(String format, Object... arguments) { + if (isInfoEnabled()) { + log(LogLevel.INFO, null, format, arguments); + } + } + + @Override + public void lifecycle(String message) { + if (isLifecycleEnabled()) { + log(LogLevel.LIFECYCLE, null, message); + } + } + + @Override + public void lifecycle(String message, Object... objects) { + if (isLifecycleEnabled()) { + log(LogLevel.LIFECYCLE, null, message, objects); + } + } + + @Override + public void lifecycle(String message, Throwable throwable) { + if (isLifecycleEnabled()) { + log(LogLevel.LIFECYCLE, throwable, message); + } + } + + + @Override + public void quiet(String message) { + if (isQuietEnabled()) { + log(LogLevel.QUIET, null, message); + } + } + + @Override + public void quiet(String message, Object... objects) { + if (isQuietEnabled()) { + log(LogLevel.QUIET, null, message, objects); + } + } + + @Override + public void quiet(String message, Throwable throwable) { + if (isQuietEnabled()) { + log(LogLevel.QUIET, throwable, message); + } + } + + @Override + public void log(LogLevel level, String message) { + if (isEnabled(level)) { + log(level, null, message); + } + } + + @Override + public void log(LogLevel level, String message, Object... objects) { + if (isEnabled(level)) { + log(level, null, message, objects); + } + } + + @Override + public void log(LogLevel level, String message, Throwable throwable) { + if (isEnabled(level)) { + log(level, throwable, message); + } + } + + public void info(String msg, Throwable t) { + if (isInfoEnabled()) { + log(LogLevel.INFO, t, msg); + } + } + + private LogLevel toLogLevel(Marker marker) { + if (marker == null) { + return LogLevel.INFO; + } + if (marker == Logging.LIFECYCLE) { + return LogLevel.LIFECYCLE; + } + if (marker == Logging.QUIET) { + return LogLevel.QUIET; + } + return LogLevel.INFO; + } + + public void info(Marker marker, String msg) { + if (isInfoEnabled(marker)) { + log(toLogLevel(marker), null, msg); + } + } + + public void info(Marker marker, String format, Object arg) { + if (isInfoEnabled(marker)) { + log(toLogLevel(marker), null, format, arg); + } + } + + public void info(Marker marker, String format, Object arg1, Object arg2) { + if (isInfoEnabled(marker)) { + log(toLogLevel(marker), null, format, arg1, arg2); + } + } + + public void info(Marker marker, String format, Object... argArray) { + if (isInfoEnabled(marker)) { + log(toLogLevel(marker), null, format, argArray); + } + } + + public void info(Marker marker, String msg, Throwable t) { + if (isInfoEnabled(marker)) { + log(toLogLevel(marker), t, msg); + } + } + + public void warn(String message) { + if (isWarnEnabled()) { + log(LogLevel.WARN, null, message); + } + } + + public void warn(String format, Object arg) { + if (isWarnEnabled()) { + log(LogLevel.WARN, null, format, arg); + } + } + + public void warn(String format, Object arg1, Object arg2) { + if (isWarnEnabled()) { + log(LogLevel.WARN, null, format, arg1, arg2); + } + } + + public void warn(String format, Object... arguments) { + if (isWarnEnabled()) { + log(LogLevel.WARN, null, format, arguments); + } + } + + public void warn(String msg, Throwable t) { + if (isWarnEnabled()) { + log(LogLevel.WARN, t, msg); + } + } + + public void warn(Marker marker, String msg) { + if (isWarnEnabled(marker)) { + log(LogLevel.WARN, null, msg); + } + } + + public void warn(Marker marker, String format, Object arg) { + if (isWarnEnabled(marker)) { + log(LogLevel.WARN, null, format, arg); + } + } + + public void warn(Marker marker, String format, Object arg1, Object arg2) { + if (isWarnEnabled(marker)) { + log(LogLevel.WARN, null, format, arg1, arg2); + } + } + + public void warn(Marker marker, String format, Object... argArray) { + if (isWarnEnabled(marker)) { + log(LogLevel.WARN, null, format, argArray); + } + } + + public void warn(Marker marker, String msg, Throwable t) { + if (isWarnEnabled(marker)) { + log(LogLevel.WARN, t, msg); + } + } + + public void error(String message) { + if (isErrorEnabled()) { + log(LogLevel.ERROR, null, message); + } + } + + public void error(String format, Object arg) { + if (isErrorEnabled()) { + log(LogLevel.ERROR, null, format, arg); + } + } + + public void error(String format, Object arg1, Object arg2) { + if (isErrorEnabled()) { + log(LogLevel.ERROR, null, format, arg1, arg2); + } + } + + public void error(String format, Object... arguments) { + if (isErrorEnabled()) { + log(LogLevel.ERROR, null, format, arguments); + } + } + + public void error(String msg, Throwable t) { + if (isErrorEnabled()) { + log(LogLevel.ERROR, t, msg); + } + } + + public void error(Marker marker, String msg) { + if (isErrorEnabled(marker)) { + log(LogLevel.ERROR, null, msg); + } + } + + public void error(Marker marker, String format, Object arg) { + if (isErrorEnabled(marker)) { + log(LogLevel.ERROR, null, format, arg); + } + } + + public void error(Marker marker, String format, Object arg1, Object arg2) { + if (isErrorEnabled(marker)) { + log(LogLevel.ERROR, null, format, arg1, arg2); + } + } + + public void error(Marker marker, String format, Object... argArray) { + if (isErrorEnabled(marker)) { + log(LogLevel.ERROR, null, format, argArray); + } + } + + public void error(Marker marker, String msg, Throwable t) { + if (isErrorEnabled(marker)) { + log(LogLevel.ERROR, t, msg); + } + } + +} diff --git a/subprojects/logging/src/main/java/org/gradle/internal/logging/slf4j/OutputEventListenerBackedLogger.java b/subprojects/logging/src/main/java/org/gradle/internal/logging/slf4j/OutputEventListenerBackedLogger.java index 408539b939b74..2ab1cf2308170 100644 --- a/subprojects/logging/src/main/java/org/gradle/internal/logging/slf4j/OutputEventListenerBackedLogger.java +++ b/subprojects/logging/src/main/java/org/gradle/internal/logging/slf4j/OutputEventListenerBackedLogger.java @@ -17,7 +17,6 @@ package org.gradle.internal.logging.slf4j; import org.gradle.api.logging.LogLevel; -import org.gradle.api.logging.Logger; import org.gradle.api.logging.Logging; import org.gradle.internal.logging.events.LogEvent; import org.gradle.internal.logging.events.OutputEventListener; @@ -28,7 +27,7 @@ import org.slf4j.helpers.FormattingTuple; import org.slf4j.helpers.MessageFormatter; -public class OutputEventListenerBackedLogger implements Logger { +public class OutputEventListenerBackedLogger extends BuildOperationAwareLogger { private final String name; private final OutputEventListenerBackedLoggerContext context; @@ -130,7 +129,11 @@ public void trace(Marker marker, String msg, Throwable t) { private void log(LogLevel logLevel, Throwable throwable, String message) { OperationIdentifier buildOperationId = CurrentBuildOperationRef.instance().getId(); - LogEvent logEvent = new LogEvent(clock.getCurrentTime(), name, logLevel, message, throwable, buildOperationId); + log(logLevel, throwable, message, buildOperationId); + } + + void log(LogLevel logLevel, Throwable throwable, String message, OperationIdentifier operationIdentifier) { + LogEvent logEvent = new LogEvent(clock.getCurrentTime(), name, logLevel, message, throwable, operationIdentifier); OutputEventListener outputEventListener = context.getOutputEventListener(); try { outputEventListener.onOutput(logEvent); @@ -476,4 +479,13 @@ public void error(Marker marker, String msg, Throwable t) { log(LogLevel.ERROR, t, msg); } } + + public OutputEventListenerBackedLoggerContext getContext() { + return context; + } + + public Clock getClock() { + return clock; + } + } From 53d1f58fec6a26eaeaa72c8fd163519443689dff Mon Sep 17 00:00:00 2001 From: Rene Groeschke Date: Mon, 18 Mar 2019 15:51:15 +0100 Subject: [PATCH 623/853] Handle KotlinCompile task logger decoration --- .../org/gradle/api/internal/AbstractTask.java | 4 ++-- .../execution/EventFiringTaskExecuter.java | 10 ++++---- .../api/internal/DefaultTaskTest.groovy | 4 ++-- .../plugins/dsl/KotlinDslCompilerPlugins.kt | 13 +++++----- .../logging/slf4j/ContextAwareTaskLogger.java | 24 +++++++++++++++++++ ...ava => DefaultContextAwareTaskLogger.java} | 6 ++--- 6 files changed, 43 insertions(+), 18 deletions(-) create mode 100644 subprojects/logging/src/main/java/org/gradle/internal/logging/slf4j/ContextAwareTaskLogger.java rename subprojects/logging/src/main/java/org/gradle/internal/logging/slf4j/{ContextAwareBuildLogger.java => DefaultContextAwareTaskLogger.java} (98%) diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/AbstractTask.java b/subprojects/core/src/main/java/org/gradle/api/internal/AbstractTask.java index d498ab95e1c29..1179ad25665bc 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/AbstractTask.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/AbstractTask.java @@ -63,7 +63,7 @@ import org.gradle.internal.execution.history.changes.InputChangesInternal; import org.gradle.internal.extensibility.ExtensibleDynamicObject; import org.gradle.internal.logging.compatbridge.LoggingManagerInternalCompatibilityBridge; -import org.gradle.internal.logging.slf4j.ContextAwareBuildLogger; +import org.gradle.internal.logging.slf4j.DefaultContextAwareTaskLogger; import org.gradle.internal.metaobject.DynamicObject; import org.gradle.internal.reflect.Instantiator; import org.gradle.internal.scripts.ScriptOrigin; @@ -122,7 +122,7 @@ public abstract class AbstractTask implements TaskInternal, DynamicObjectAware { private final TaskStateInternal state; - private Logger logger = new ContextAwareBuildLogger(BUILD_LOGGER); + private Logger logger = new DefaultContextAwareTaskLogger(BUILD_LOGGER); private final TaskMutator taskMutator; private ObservableList observableActionList; diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/EventFiringTaskExecuter.java b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/EventFiringTaskExecuter.java index 15861d7707759..7be6b2abfbb3b 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/EventFiringTaskExecuter.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/EventFiringTaskExecuter.java @@ -24,7 +24,7 @@ import org.gradle.api.internal.tasks.TaskStateInternal; import org.gradle.api.logging.Logger; import org.gradle.api.tasks.TaskExecutionException; -import org.gradle.internal.logging.slf4j.ContextAwareBuildLogger; +import org.gradle.internal.logging.slf4j.ContextAwareTaskLogger; import org.gradle.internal.operations.BuildOperationCategory; import org.gradle.internal.operations.BuildOperationContext; import org.gradle.internal.operations.BuildOperationDescriptor; @@ -57,14 +57,14 @@ public TaskExecuterResult call(BuildOperationContext operationContext) { private TaskExecuterResult executeTask(BuildOperationContext operationContext) { Logger logger = task.getLogger(); - ContextAwareBuildLogger contextAwareBuildLogger = null; + ContextAwareTaskLogger contextAwareBuildLogger = null; try { taskExecutionListener.beforeExecute(task); BuildOperationRef currentOperation = buildOperationExecutor.getCurrentOperation(); - if(logger instanceof ContextAwareBuildLogger) { - contextAwareBuildLogger = (ContextAwareBuildLogger) logger; +// if(logger instanceof ContextAwareTaskLogger) { + contextAwareBuildLogger = (ContextAwareTaskLogger) logger; contextAwareBuildLogger.setFallbackBuildOperationId(currentOperation.getId()); - } +// } } catch (Throwable t) { state.setOutcome(new TaskExecutionException(task, t)); return TaskExecuterResult.WITHOUT_OUTPUTS; diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/DefaultTaskTest.groovy b/subprojects/core/src/test/groovy/org/gradle/api/internal/DefaultTaskTest.groovy index 9d64c5790cf2d..51fab1c368f39 100644 --- a/subprojects/core/src/test/groovy/org/gradle/api/internal/DefaultTaskTest.groovy +++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/DefaultTaskTest.groovy @@ -30,7 +30,7 @@ import org.gradle.api.tasks.TaskExecutionException import org.gradle.api.tasks.TaskInstantiationException import org.gradle.internal.Actions import org.gradle.internal.event.ListenerManager -import org.gradle.internal.logging.slf4j.ContextAwareBuildLogger +import org.gradle.internal.logging.slf4j.ContextAwareTaskLogger import spock.lang.Issue import java.util.concurrent.Callable @@ -527,7 +527,7 @@ class DefaultTaskTest extends AbstractTaskTest { def "can replace task logger"() { expect: - task.logger instanceof ContextAwareBuildLogger + task.logger instanceof ContextAwareTaskLogger task.logger.delegate == AbstractTask.BUILD_LOGGER when: diff --git a/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/dsl/KotlinDslCompilerPlugins.kt b/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/dsl/KotlinDslCompilerPlugins.kt index 518de7e76d8e5..5c0b792df38c0 100644 --- a/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/dsl/KotlinDslCompilerPlugins.kt +++ b/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/dsl/KotlinDslCompilerPlugins.kt @@ -23,6 +23,7 @@ import org.gradle.api.logging.Logger import org.gradle.api.internal.DocumentationRegistry import org.gradle.api.internal.TaskInternal +import org.gradle.internal.logging.slf4j.ContextAwareTaskLogger import org.jetbrains.kotlin.gradle.tasks.KotlinCompile @@ -72,8 +73,8 @@ class KotlinDslCompilerPlugins : Plugin { private fun KotlinCompile.applyExperimentalWarning(experimentalWarning: Boolean) = replaceLoggerWith( - if (experimentalWarning) KotlinCompilerWarningSubstitutingLogger(logger, project.toString(), project.experimentalWarningLink) - else KotlinCompilerWarningSilencingLogger(logger) + if (experimentalWarning) KotlinCompilerWarningSubstitutingLogger(logger as ContextAwareTaskLogger, project.toString(), project.experimentalWarningLink) + else KotlinCompilerWarningSilencingLogger(logger as ContextAwareTaskLogger) ) @@ -93,10 +94,10 @@ fun KotlinCompile.replaceLoggerWith(logger: Logger) { private class KotlinCompilerWarningSubstitutingLogger( - private val delegate: Logger, + private val delegate: ContextAwareTaskLogger, private val target: String, private val link: String -) : Logger by delegate { +) : ContextAwareTaskLogger by delegate { override fun warn(message: String) { if (message.contains(KotlinCompilerArguments.samConversionForKotlinFunctions)) delegate.warn(kotlinDslPluginExperimentalWarning(target, link)) @@ -107,8 +108,8 @@ class KotlinCompilerWarningSubstitutingLogger( private class KotlinCompilerWarningSilencingLogger( - private val delegate: Logger -) : Logger by delegate { + private val delegate: ContextAwareTaskLogger +) : ContextAwareTaskLogger by delegate { override fun warn(message: String) { if (!message.contains(KotlinCompilerArguments.samConversionForKotlinFunctions)) { diff --git a/subprojects/logging/src/main/java/org/gradle/internal/logging/slf4j/ContextAwareTaskLogger.java b/subprojects/logging/src/main/java/org/gradle/internal/logging/slf4j/ContextAwareTaskLogger.java new file mode 100644 index 0000000000000..e210f9cf229d3 --- /dev/null +++ b/subprojects/logging/src/main/java/org/gradle/internal/logging/slf4j/ContextAwareTaskLogger.java @@ -0,0 +1,24 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.internal.logging.slf4j; + +import org.gradle.api.logging.Logger; +import org.gradle.internal.operations.OperationIdentifier; + +public interface ContextAwareTaskLogger extends Logger { + void setFallbackBuildOperationId(OperationIdentifier operationIdentifier); +} diff --git a/subprojects/logging/src/main/java/org/gradle/internal/logging/slf4j/ContextAwareBuildLogger.java b/subprojects/logging/src/main/java/org/gradle/internal/logging/slf4j/DefaultContextAwareTaskLogger.java similarity index 98% rename from subprojects/logging/src/main/java/org/gradle/internal/logging/slf4j/ContextAwareBuildLogger.java rename to subprojects/logging/src/main/java/org/gradle/internal/logging/slf4j/DefaultContextAwareTaskLogger.java index f6ac7c5c9e211..f586ad2f5d467 100644 --- a/subprojects/logging/src/main/java/org/gradle/internal/logging/slf4j/ContextAwareBuildLogger.java +++ b/subprojects/logging/src/main/java/org/gradle/internal/logging/slf4j/DefaultContextAwareTaskLogger.java @@ -25,12 +25,12 @@ import org.slf4j.helpers.FormattingTuple; import org.slf4j.helpers.MessageFormatter; -public class ContextAwareBuildLogger implements Logger { +public class DefaultContextAwareTaskLogger implements ContextAwareTaskLogger { - private final BuildOperationAwareLogger delegate; + private BuildOperationAwareLogger delegate; private OperationIdentifier fallbackOperationIdentifier = null; - public ContextAwareBuildLogger(Logger delegate) { + public DefaultContextAwareTaskLogger(Logger delegate) { this.delegate = (BuildOperationAwareLogger) delegate; } From 615cb58e549355b3d32d1fe3547f93b7abc2ac0a Mon Sep 17 00:00:00 2001 From: Rene Groeschke Date: Mon, 18 Mar 2019 23:11:26 +0100 Subject: [PATCH 624/853] Try fixing kotlin logger decoration --- .../execution/EventFiringTaskExecuter.java | 18 +++++++++++------- .../plugins/dsl/KotlinDslCompilerPlugins.kt | 3 ++- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/EventFiringTaskExecuter.java b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/EventFiringTaskExecuter.java index 7be6b2abfbb3b..6df6016e3e17e 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/EventFiringTaskExecuter.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/EventFiringTaskExecuter.java @@ -57,14 +57,18 @@ public TaskExecuterResult call(BuildOperationContext operationContext) { private TaskExecuterResult executeTask(BuildOperationContext operationContext) { Logger logger = task.getLogger(); - ContextAwareTaskLogger contextAwareBuildLogger = null; + ContextAwareTaskLogger contextAwareTaskLogger = null; try { taskExecutionListener.beforeExecute(task); BuildOperationRef currentOperation = buildOperationExecutor.getCurrentOperation(); -// if(logger instanceof ContextAwareTaskLogger) { - contextAwareBuildLogger = (ContextAwareTaskLogger) logger; - contextAwareBuildLogger.setFallbackBuildOperationId(currentOperation.getId()); -// } + if (logger != null){ + contextAwareTaskLogger = (ContextAwareTaskLogger) logger; + contextAwareTaskLogger.setFallbackBuildOperationId(currentOperation.getId()); + } else { + for (Class anInterface : logger.getClass().getInterfaces()) { + System.out.println("### = " + anInterface); + } + } } catch (Throwable t) { state.setOutcome(new TaskExecutionException(task, t)); return TaskExecuterResult.WITHOUT_OUTPUTS; @@ -72,8 +76,8 @@ private TaskExecuterResult executeTask(BuildOperationContext operationContext) { TaskExecuterResult result = delegate.execute(task, state, context); - if(contextAwareBuildLogger != null){ - contextAwareBuildLogger.setFallbackBuildOperationId(null); + if (contextAwareTaskLogger != null) { + contextAwareTaskLogger.setFallbackBuildOperationId(null); } operationContext.setResult(new ExecuteTaskBuildOperationResult( state, diff --git a/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/dsl/KotlinDslCompilerPlugins.kt b/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/dsl/KotlinDslCompilerPlugins.kt index 5c0b792df38c0..b445c2eda3569 100644 --- a/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/dsl/KotlinDslCompilerPlugins.kt +++ b/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/dsl/KotlinDslCompilerPlugins.kt @@ -71,11 +71,12 @@ class KotlinDslCompilerPlugins : Plugin { private -fun KotlinCompile.applyExperimentalWarning(experimentalWarning: Boolean) = +fun KotlinCompile.applyExperimentalWarning(experimentalWarning: Boolean) { replaceLoggerWith( if (experimentalWarning) KotlinCompilerWarningSubstitutingLogger(logger as ContextAwareTaskLogger, project.toString(), project.experimentalWarningLink) else KotlinCompilerWarningSilencingLogger(logger as ContextAwareTaskLogger) ) +} object KotlinCompilerArguments { From c2159d768e0788f3c0f9d6403e88ad0bdb895688 Mon Sep 17 00:00:00 2001 From: Rene Groeschke Date: Tue, 19 Mar 2019 12:21:41 +0100 Subject: [PATCH 625/853] Some cleanup --- .../internal/tasks/execution/EventFiringTaskExecuter.java | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/EventFiringTaskExecuter.java b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/EventFiringTaskExecuter.java index 6df6016e3e17e..22c46a29ec483 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/EventFiringTaskExecuter.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/EventFiringTaskExecuter.java @@ -64,11 +64,7 @@ private TaskExecuterResult executeTask(BuildOperationContext operationContext) { if (logger != null){ contextAwareTaskLogger = (ContextAwareTaskLogger) logger; contextAwareTaskLogger.setFallbackBuildOperationId(currentOperation.getId()); - } else { - for (Class anInterface : logger.getClass().getInterfaces()) { - System.out.println("### = " + anInterface); - } - } + } } catch (Throwable t) { state.setOutcome(new TaskExecutionException(task, t)); return TaskExecuterResult.WITHOUT_OUTPUTS; From 869299a1453061baa6e3fa5b50dcdc9387a39075 Mon Sep 17 00:00:00 2001 From: wolf Date: Tue, 19 Mar 2019 11:38:24 +0000 Subject: [PATCH 626/853] TeamCity change in 'Gradle / Util' project: Versioned settings configuration updated --- .teamcity/Gradle_Util/Project.kt | 29 +++++ .../Gradle_Util_AdHocFunctionalTestLinux.kt | 99 +++++++++++++++++ .../Gradle_Util_AdHocFunctionalTestLinux.xml | 101 ----------------- .../Gradle_Util_AdHocFunctionalTestWindows.kt | 95 ++++++++++++++++ ...Gradle_Util_AdHocFunctionalTestWindows.xml | 97 ----------------- .../pluginData/plugin-settings.xml | 3 - .teamcity/Gradle_Util/project-config.xml | 18 --- .teamcity/Gradle_Util/settings.kts | 35 ++++++ .teamcity/Gradle_Util_Performance/Project.kt | 15 +++ ...rformance_AdHocPerformanceScenarioLinux.kt | 71 ++++++++++++ ...formance_AdHocPerformanceScenarioLinux.xml | 67 ------------ ...ormance_PerformanceTestCoordinatorLinux.kt | 103 ++++++++++++++++++ ...rmance_PerformanceTestCoordinatorLinux.xml | 102 ----------------- .../pluginData/plugin-settings.xml | 3 - .../project-config.xml | 7 -- .../Gradle_Util_Performance/settings.kts | 35 ++++++ 16 files changed, 482 insertions(+), 398 deletions(-) create mode 100644 .teamcity/Gradle_Util/Project.kt create mode 100644 .teamcity/Gradle_Util/buildTypes/Gradle_Util_AdHocFunctionalTestLinux.kt delete mode 100644 .teamcity/Gradle_Util/buildTypes/Gradle_Util_AdHocFunctionalTestLinux.xml create mode 100644 .teamcity/Gradle_Util/buildTypes/Gradle_Util_AdHocFunctionalTestWindows.kt delete mode 100644 .teamcity/Gradle_Util/buildTypes/Gradle_Util_AdHocFunctionalTestWindows.xml delete mode 100644 .teamcity/Gradle_Util/pluginData/plugin-settings.xml delete mode 100644 .teamcity/Gradle_Util/project-config.xml create mode 100644 .teamcity/Gradle_Util/settings.kts create mode 100644 .teamcity/Gradle_Util_Performance/Project.kt create mode 100644 .teamcity/Gradle_Util_Performance/buildTypes/Gradle_Util_Performance_AdHocPerformanceScenarioLinux.kt delete mode 100644 .teamcity/Gradle_Util_Performance/buildTypes/Gradle_Util_Performance_AdHocPerformanceScenarioLinux.xml create mode 100644 .teamcity/Gradle_Util_Performance/buildTypes/Gradle_Util_Performance_PerformanceTestCoordinatorLinux.kt delete mode 100644 .teamcity/Gradle_Util_Performance/buildTypes/Gradle_Util_Performance_PerformanceTestCoordinatorLinux.xml delete mode 100644 .teamcity/Gradle_Util_Performance/pluginData/plugin-settings.xml delete mode 100644 .teamcity/Gradle_Util_Performance/project-config.xml create mode 100644 .teamcity/Gradle_Util_Performance/settings.kts diff --git a/.teamcity/Gradle_Util/Project.kt b/.teamcity/Gradle_Util/Project.kt new file mode 100644 index 0000000000000..068cdc5088e6a --- /dev/null +++ b/.teamcity/Gradle_Util/Project.kt @@ -0,0 +1,29 @@ +package Gradle_Util + +import Gradle_Util.buildTypes.* +import jetbrains.buildServer.configs.kotlin.v2018_2.* +import jetbrains.buildServer.configs.kotlin.v2018_2.Project +import jetbrains.buildServer.configs.kotlin.v2018_2.projectFeatures.VersionedSettings +import jetbrains.buildServer.configs.kotlin.v2018_2.projectFeatures.versionedSettings + +object Project : Project({ + uuid = "077cff89-d1d3-407b-acc0-88446a99dec7" + id("Gradle_Util") + parentId("Gradle") + name = "Util" + + buildType(Gradle_Util_AdHocFunctionalTestWindows) + buildType(Gradle_Util_AdHocFunctionalTestLinux) + + features { + versionedSettings { + id = "PROJECT_EXT_16" + mode = VersionedSettings.Mode.ENABLED + buildSettingsMode = VersionedSettings.BuildSettingsMode.PREFER_SETTINGS_FROM_VCS + rootExtId = "Gradle_Branches_VersionedSettings" + showChanges = false + settingsFormat = VersionedSettings.Format.KOTLIN + storeSecureParamsOutsideOfVcs = true + } + } +}) diff --git a/.teamcity/Gradle_Util/buildTypes/Gradle_Util_AdHocFunctionalTestLinux.kt b/.teamcity/Gradle_Util/buildTypes/Gradle_Util_AdHocFunctionalTestLinux.kt new file mode 100644 index 0000000000000..31625640f2282 --- /dev/null +++ b/.teamcity/Gradle_Util/buildTypes/Gradle_Util_AdHocFunctionalTestLinux.kt @@ -0,0 +1,99 @@ +package Gradle_Util.buildTypes + +import jetbrains.buildServer.configs.kotlin.v2018_2.* +import jetbrains.buildServer.configs.kotlin.v2018_2.buildSteps.gradle +import jetbrains.buildServer.configs.kotlin.v2018_2.buildSteps.script + +object Gradle_Util_AdHocFunctionalTestLinux : BuildType({ + uuid = "5d59fee9-be42-4f6d-9e0b-fe103e0d2765" + name = "AdHoc Functional Test - Linux" + + artifactRules = """ + build/report-* => . + buildSrc/build/report-* => . + subprojects/*/build/tmp/test files/** => test-files + build/errorLogs/** => errorLogs + """.trimIndent() + + params { + param("maxParallelForks", "4") + select("subproject", "", display = ParameterDisplay.PROMPT, + options = listOf("announce", "antlr", "baseServices", "baseServicesGroovy", "buildCache", "buildCacheHttp", "buildComparison", "buildInit", "buildScanPerformance", "cli", "codeQuality", "compositeBuilds", "core", "coreApi", "dependencyManagement", "diagnostics", "distributions", "docs", "ear", "ide", "ideNative", "idePlay", "installationBeacon", "integTest", "internalAndroidPerformanceTesting", "internalIntegTesting", "internalPerformanceTesting", "internalTesting", "ivy", "jacoco", "javascript", "jvmServices", "languageGroovy", "languageJava", "languageJvm", "languageNative", "languageScala", "launcher", "logging", "maven", "messaging", "modelCore", "modelGroovy", "native", "osgi", "performance", "persistentCache", "platformBase", "platformJvm", "platformNative", "platformPlay", "pluginDevelopment", "pluginUse", "plugins", "processServices", "publish", "reporting", "resources", "resourcesGcs", "resourcesHttp", "resourcesS3", "resourcesSftp", "runtimeApiInfo", "scala", "signing", "smokeTest", "soak", "testKit", "testingBase", "testingJvm", "testingNative", "toolingApi", "toolingApiBuilders", "workers", "wrapper")) + param("env.ANDROID_HOME", "/opt/android/sdk") + select("buildType", "", display = ParameterDisplay.PROMPT, + options = listOf("quickTest", "platformTest", "crossVersionTest", "quickFeedbackCrossVersionTest", "parallelTest", "noDaemonTest", "java9SmokeTest")) + } + + vcs { + root(AbsoluteId("Gradle_Branches_GradlePersonalBranches")) + + checkoutMode = CheckoutMode.ON_AGENT + buildDefaultBranch = false + } + + steps { + gradle { + name = "GRADLE_RUNNER" + tasks = "clean %subproject%:%buildType%" + buildFile = "" + gradleParams = "-PmaxParallelForks=%maxParallelForks% -s --no-daemon --continue -I ./gradle/init-scripts/build-scan.init.gradle.kts" + param("org.jfrog.artifactory.selectedDeployableServer.defaultModuleVersionConfiguration", "GLOBAL") + param("ui.gradleRunner.gradle.build.file", "") + } + script { + name = "CHECK_CLEAN_M2" + executionMode = BuildStep.ExecutionMode.ALWAYS + scriptContent = """ + REPO=/home/%env.USER%/.m2/repository + if [ -e ${'$'}REPO ] ; then + tree ${'$'}REPO + rm -rf ${'$'}REPO + echo "${'$'}REPO was polluted during the build" + exit 1 + else + echo "${'$'}REPO does not exist" + fi + """.trimIndent() + } + gradle { + name = "VERIFY_TEST_FILES_CLEANUP" + tasks = "verifyTestFilesCleanup" + buildFile = "" + gradleParams = "-PmaxParallelForks=%maxParallelForks% -s --no-daemon --continue -I ./gradle/init-scripts/build-scan.init.gradle.kts" + param("ui.gradleRunner.gradle.build.file", "") + } + gradle { + name = "TAG_BUILD" + executionMode = BuildStep.ExecutionMode.ALWAYS + tasks = "tagBuild" + buildFile = "" + gradleParams = "-PteamCityUsername=%teamcity.username.restbot% -PteamCityPassword=%teamcity.password.restbot% -PteamCityBuildId=%teamcity.build.id% -PgithubToken=%github.ci.oauth.token%" + param("ui.gradleRunner.gradle.build.file", "") + } + } + + failureConditions { + executionTimeoutMin = 180 + } + + dependencies { + dependency(AbsoluteId("Gradle_Check_BuildDistributions")) { + snapshot { + onDependencyFailure = FailureAction.CANCEL + onDependencyCancel = FailureAction.CANCEL + } + + artifacts { + cleanDestination = true + artifactRules = """ + distributions/*-all.zip => incoming-distributions + build-receipt.properties => incoming-distributions + """.trimIndent() + } + } + } + + requirements { + contains("teamcity.agent.jvm.os.name", "Linux") + } +}) diff --git a/.teamcity/Gradle_Util/buildTypes/Gradle_Util_AdHocFunctionalTestLinux.xml b/.teamcity/Gradle_Util/buildTypes/Gradle_Util_AdHocFunctionalTestLinux.xml deleted file mode 100644 index 1267633ad724c..0000000000000 --- a/.teamcity/Gradle_Util/buildTypes/Gradle_Util_AdHocFunctionalTestLinux.xml +++ /dev/null @@ -1,101 +0,0 @@ - - - AdHoc Functional Test - Linux - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.teamcity/Gradle_Util/buildTypes/Gradle_Util_AdHocFunctionalTestWindows.kt b/.teamcity/Gradle_Util/buildTypes/Gradle_Util_AdHocFunctionalTestWindows.kt new file mode 100644 index 0000000000000..d2f4cd2e4d9d1 --- /dev/null +++ b/.teamcity/Gradle_Util/buildTypes/Gradle_Util_AdHocFunctionalTestWindows.kt @@ -0,0 +1,95 @@ +package Gradle_Util.buildTypes + +import jetbrains.buildServer.configs.kotlin.v2018_2.* +import jetbrains.buildServer.configs.kotlin.v2018_2.buildSteps.gradle +import jetbrains.buildServer.configs.kotlin.v2018_2.buildSteps.script + +object Gradle_Util_AdHocFunctionalTestWindows : BuildType({ + uuid = "944be583-446e-4ecc-b2f2-15f04dd0cfe9" + name = "AdHoc Functional Test - Windows" + + artifactRules = """ + build/report-* => . + buildSrc/build/report-* => . + subprojects/*/build/tmp/test files/** => test-files + build/errorLogs/** => errorLogs + """.trimIndent() + + params { + param("maxParallelForks", "4") + select("subproject", "", display = ParameterDisplay.PROMPT, + options = listOf("announce", "antlr", "baseServices", "baseServicesGroovy", "buildCache", "buildCacheHttp", "buildComparison", "buildInit", "buildScanPerformance", "cli", "codeQuality", "compositeBuilds", "core", "coreApi", "dependencyManagement", "diagnostics", "distributions", "docs", "ear", "ide", "ideNative", "idePlay", "installationBeacon", "integTest", "internalAndroidPerformanceTesting", "internalIntegTesting", "internalPerformanceTesting", "internalTesting", "ivy", "jacoco", "javascript", "jvmServices", "languageGroovy", "languageJava", "languageJvm", "languageNative", "languageScala", "launcher", "logging", "maven", "messaging", "modelCore", "modelGroovy", "native", "osgi", "performance", "persistentCache", "platformBase", "platformJvm", "platformNative", "platformPlay", "pluginDevelopment", "pluginUse", "plugins", "processServices", "publish", "reporting", "resources", "resourcesGcs", "resourcesHttp", "resourcesS3", "resourcesSftp", "runtimeApiInfo", "scala", "signing", "smokeTest", "soak", "testKit", "testingBase", "testingJvm", "testingNative", "toolingApi", "toolingApiBuilders", "workers", "wrapper")) + param("env.JAVA_HOME", "%windows.java9.oracle.64bit%") + select("buildType", "", display = ParameterDisplay.PROMPT, + options = listOf("quickTest", "platformTest", "crossVersionTest", "quickFeedbackCrossVersionTest", "parallelTest", "noDaemonTest", "java9SmokeTest")) + } + + vcs { + root(AbsoluteId("Gradle_Branches_GradlePersonalBranches")) + + checkoutMode = CheckoutMode.ON_AGENT + buildDefaultBranch = false + } + + steps { + gradle { + name = "GRADLE_RUNNER" + tasks = "clean %subproject%:%buildType%" + buildFile = "" + gradleParams = """-PmaxParallelForks=%maxParallelForks% -s --no-daemon --continue -I ./gradle/init-scripts/build-scan.init.gradle.kts "-PtestJavaHome=%windows.java8.oracle.64bit%"""" + param("org.jfrog.artifactory.selectedDeployableServer.defaultModuleVersionConfiguration", "GLOBAL") + param("ui.gradleRunner.gradle.build.file", "") + } + script { + name = "CHECK_CLEAN_M2" + executionMode = BuildStep.ExecutionMode.ALWAYS + scriptContent = """ + IF exist %teamcity.agent.jvm.user.home%\.m2\repository ( + TREE %teamcity.agent.jvm.user.home%\.m2\repository + RMDIR /S /Q %teamcity.agent.jvm.user.home%\.m2\repository + EXIT 1 + ) + """.trimIndent() + } + gradle { + name = "VERIFY_TEST_FILES_CLEANUP" + tasks = "verifyTestFilesCleanup" + buildFile = "" + gradleParams = "-PmaxParallelForks=%maxParallelForks% -s --no-daemon --continue -I ./gradle/init-scripts/build-scan.init.gradle.kts" + param("ui.gradleRunner.gradle.build.file", "") + } + gradle { + name = "TAG_BUILD" + executionMode = BuildStep.ExecutionMode.ALWAYS + tasks = "tagBuild" + buildFile = "" + gradleParams = "-PteamCityUsername=%teamcity.username.restbot% -PteamCityPassword=%teamcity.password.restbot% -PteamCityBuildId=%teamcity.build.id% -PgithubToken=%github.ci.oauth.token%" + param("ui.gradleRunner.gradle.build.file", "") + } + } + + failureConditions { + executionTimeoutMin = 180 + } + + dependencies { + dependency(AbsoluteId("Gradle_Check_BuildDistributions")) { + snapshot { + onDependencyFailure = FailureAction.CANCEL + onDependencyCancel = FailureAction.CANCEL + } + + artifacts { + cleanDestination = true + artifactRules = """ + distributions/*-all.zip => incoming-distributions + build-receipt.properties => incoming-distributions + """.trimIndent() + } + } + } + + requirements { + contains("teamcity.agent.jvm.os.name", "Windows") + } +}) diff --git a/.teamcity/Gradle_Util/buildTypes/Gradle_Util_AdHocFunctionalTestWindows.xml b/.teamcity/Gradle_Util/buildTypes/Gradle_Util_AdHocFunctionalTestWindows.xml deleted file mode 100644 index 96f9f9de3fb2b..0000000000000 --- a/.teamcity/Gradle_Util/buildTypes/Gradle_Util_AdHocFunctionalTestWindows.xml +++ /dev/null @@ -1,97 +0,0 @@ - - - AdHoc Functional Test - Windows - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.teamcity/Gradle_Util/pluginData/plugin-settings.xml b/.teamcity/Gradle_Util/pluginData/plugin-settings.xml deleted file mode 100644 index 677e924ad523a..0000000000000 --- a/.teamcity/Gradle_Util/pluginData/plugin-settings.xml +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/.teamcity/Gradle_Util/project-config.xml b/.teamcity/Gradle_Util/project-config.xml deleted file mode 100644 index 5cfe45692ba2f..0000000000000 --- a/.teamcity/Gradle_Util/project-config.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - Util - - - - - - - - - - - - - - - diff --git a/.teamcity/Gradle_Util/settings.kts b/.teamcity/Gradle_Util/settings.kts new file mode 100644 index 0000000000000..45adc3598e791 --- /dev/null +++ b/.teamcity/Gradle_Util/settings.kts @@ -0,0 +1,35 @@ +package Gradle_Util + +import jetbrains.buildServer.configs.kotlin.v2018_2.* + +/* +The settings script is an entry point for defining a single +TeamCity project. TeamCity looks for the 'settings.kts' file in a +project directory and runs it if it's found, so the script name +shouldn't be changed and its package should be the same as the +project's id. + +The script should contain a single call to the project() function +with a Project instance or an init function as an argument. + +VcsRoots, BuildTypes, and Templates of this project must be +registered inside project using the vcsRoot(), buildType(), and +template() methods respectively. + +Subprojects can be defined either in their own settings.kts or by +calling the subProjects() method in this project. + +To debug settings scripts in command-line, run the + + mvnDebug org.jetbrains.teamcity:teamcity-configs-maven-plugin:generate + +command and attach your debugger to the port 8000. + +To debug in IntelliJ Idea, open the 'Maven Projects' tool window (View -> +Tool Windows -> Maven Projects), find the generate task +node (Plugins -> teamcity-configs -> teamcity-configs:generate), +the 'Debug' option is available in the context menu for the task. +*/ + +version = "2018.2" +project(Gradle_Util.Project) \ No newline at end of file diff --git a/.teamcity/Gradle_Util_Performance/Project.kt b/.teamcity/Gradle_Util_Performance/Project.kt new file mode 100644 index 0000000000000..4d03105ce5028 --- /dev/null +++ b/.teamcity/Gradle_Util_Performance/Project.kt @@ -0,0 +1,15 @@ +package Gradle_Util_Performance + +import Gradle_Util_Performance.buildTypes.* +import jetbrains.buildServer.configs.kotlin.v2018_2.* +import jetbrains.buildServer.configs.kotlin.v2018_2.Project + +object Project : Project({ + uuid = "fdc4f15a-e253-4744-a1b3-bcac37b18189" + id("Gradle_Util_Performance") + parentId("Gradle_Util") + name = "Performance" + + buildType(Gradle_Util_Performance_AdHocPerformanceScenarioLinux) + buildType(Gradle_Util_Performance_PerformanceTestCoordinatorLinux) +}) diff --git a/.teamcity/Gradle_Util_Performance/buildTypes/Gradle_Util_Performance_AdHocPerformanceScenarioLinux.kt b/.teamcity/Gradle_Util_Performance/buildTypes/Gradle_Util_Performance_AdHocPerformanceScenarioLinux.kt new file mode 100644 index 0000000000000..f85102c9c8f73 --- /dev/null +++ b/.teamcity/Gradle_Util_Performance/buildTypes/Gradle_Util_Performance_AdHocPerformanceScenarioLinux.kt @@ -0,0 +1,71 @@ +package Gradle_Util_Performance.buildTypes + +import jetbrains.buildServer.configs.kotlin.v2018_2.* +import jetbrains.buildServer.configs.kotlin.v2018_2.buildSteps.gradle +import jetbrains.buildServer.configs.kotlin.v2018_2.buildSteps.script + +object Gradle_Util_Performance_AdHocPerformanceScenarioLinux : BuildType({ + uuid = "a3183d81-e07d-475c-8ef6-04ed60bf4053" + name = "AdHoc Performance Scenario - Linux" + + artifactRules = """ + subprojects/*/build/test-results-*.zip => results + subprojects/*/build/tmp/**/log.txt => failure-logs + """.trimIndent() + + params { + text("baselines", "defaults", display = ParameterDisplay.PROMPT, allowEmpty = false) + text("templates", "", display = ParameterDisplay.PROMPT, allowEmpty = false) + param("channel", "adhoc") + param("env.ANDROID_HOME", "/opt/android/sdk") + param("env.PATH", "%env.PATH%:/opt/swift/latest/usr/bin") + param("env.JAVA_HOME", "%linux.java11.openjdk.64bit%") + param("flamegraphs", "--flamegraphs true") + param("checks", "all") + param("env.FG_HOME_DIR", "/opt/FlameGraph") + param("additional.gradle.parameters", "") + param("env.HP_HOME_DIR", "/opt/honest-profiler") + text("scenario", "", display = ParameterDisplay.PROMPT, allowEmpty = false) + text("warmups", "3", display = ParameterDisplay.PROMPT, allowEmpty = false) + param("performance.db.username", "tcagent") + param("env.GRADLE_OPTS", "-Xmx1536m -XX:MaxPermSize=384m") + text("runs", "10", display = ParameterDisplay.PROMPT, allowEmpty = false) + param("performance.db.url", "jdbc:h2:ssl://dev61.gradle.org:9092") + } + + vcs { + root(AbsoluteId("Gradle_Branches_GradlePersonalBranches")) + + checkoutMode = CheckoutMode.ON_AGENT + } + + steps { + gradle { + name = "GRADLE_RUNNER" + buildFile = "" + gradleParams = """clean %templates% performance:performanceAdHocTest --scenarios "%scenario%" --baselines %baselines% --warmups %warmups% --runs %runs% --checks %checks% --channel %channel% %flamegraphs% -x prepareSamples -PmaxParallelForks=%maxParallelForks% %additional.gradle.parameters% -Dorg.gradle.logging.level=LIFECYCLE -s --no-daemon --continue -I ./gradle/init-scripts/build-scan.init.gradle.kts --build-cache "-Dgradle.cache.remote.url=%gradle.cache.remote.url%" "-Dgradle.cache.remote.username=%gradle.cache.remote.username%" "-Dgradle.cache.remote.password=%gradle.cache.remote.password%" -PtestJavaHome=%linux.java8.oracle.64bit% -Porg.gradle.performance.branchName=%teamcity.build.branch%""" + } + script { + name = "CHECK_CLEAN_M2" + executionMode = BuildStep.ExecutionMode.ALWAYS + scriptContent = """ + REPO=/home/%env.USER%/.m2/repository + if [ -e ${'$'}REPO ] ; then + rm -rf ${'$'}REPO + echo "${'$'}REPO was polluted during the build" + exit 1 + else + echo "${'$'}REPO does not exist" + fi + """.trimIndent() + } + } + + failureConditions { + executionTimeoutMin = 420 + } + + requirements { + contains("teamcity.agent.jvm.os.name", "Linux") + } +}) diff --git a/.teamcity/Gradle_Util_Performance/buildTypes/Gradle_Util_Performance_AdHocPerformanceScenarioLinux.xml b/.teamcity/Gradle_Util_Performance/buildTypes/Gradle_Util_Performance_AdHocPerformanceScenarioLinux.xml deleted file mode 100644 index 880e8d5c6b58d..0000000000000 --- a/.teamcity/Gradle_Util_Performance/buildTypes/Gradle_Util_Performance_AdHocPerformanceScenarioLinux.xml +++ /dev/null @@ -1,67 +0,0 @@ - - - AdHoc Performance Scenario - Linux - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.teamcity/Gradle_Util_Performance/buildTypes/Gradle_Util_Performance_PerformanceTestCoordinatorLinux.kt b/.teamcity/Gradle_Util_Performance/buildTypes/Gradle_Util_Performance_PerformanceTestCoordinatorLinux.kt new file mode 100644 index 0000000000000..16677655dff69 --- /dev/null +++ b/.teamcity/Gradle_Util_Performance/buildTypes/Gradle_Util_Performance_PerformanceTestCoordinatorLinux.kt @@ -0,0 +1,103 @@ +package Gradle_Util_Performance.buildTypes + +import jetbrains.buildServer.configs.kotlin.v2018_2.* +import jetbrains.buildServer.configs.kotlin.v2018_2.buildFeatures.commitStatusPublisher +import jetbrains.buildServer.configs.kotlin.v2018_2.buildSteps.gradle +import jetbrains.buildServer.configs.kotlin.v2018_2.buildSteps.script + +object Gradle_Util_Performance_PerformanceTestCoordinatorLinux : BuildType({ + uuid = "a28ced77-77d1-41fd-bc3b-fe9c9016bf7b" + name = "AdHoc Performance Test Coordinator - Linux" + + artifactRules = """ + build/report-* => . + buildSrc/build/report-* => . + subprojects/*/build/tmp/test files/** => test-files + build/errorLogs/** => errorLogs + """.trimIndent() + detectHangingBuilds = false + maxRunningBuilds = 2 + + params { + param("performance.baselines", "defaults") + param("performance.db.username", "tcagent") + param("TC_USERNAME", "TeamcityRestBot") + param("env.JAVA_HOME", "%linux.java11.openjdk.64bit%") + param("env.GRADLE_OPTS", "-Xmx1536m -XX:MaxPermSize=384m") + param("performance.db.url", "jdbc:h2:ssl://dev61.gradle.org:9092") + } + + vcs { + root(AbsoluteId("Gradle_Branches_GradlePersonalBranches")) + + checkoutMode = CheckoutMode.ON_AGENT + buildDefaultBranch = false + } + + steps { + gradle { + name = "GRADLE_RUNNER" + tasks = "" + buildFile = "" + gradleParams = "clean distributedPerformanceTests -x prepareSamples --baselines %performance.baselines% -PtimestampedVersion -Porg.gradle.performance.branchName=%teamcity.build.branch% -Porg.gradle.performance.db.url=%performance.db.url% -Porg.gradle.performance.db.username=%performance.db.username% -PteamCityUsername=%TC_USERNAME% -PteamCityPassword=%teamcity.password.restbot% -Porg.gradle.performance.buildTypeId=Gradle_Check_IndividualPerformanceScenarioWorkersLinux -Porg.gradle.performance.workerTestTaskName=fullPerformanceTest -Porg.gradle.performance.coordinatorBuildId=%teamcity.build.id% -Porg.gradle.performance.db.password=%performance.db.password.tcagent% -PmaxParallelForks=%maxParallelForks% -s --no-daemon --continue -I ./gradle/init-scripts/build-scan.init.gradle.kts --build-cache -Dgradle.cache.remote.url=%gradle.cache.remote.url% -Dgradle.cache.remote.username=%gradle.cache.remote.username% -Dgradle.cache.remote.password=%gradle.cache.remote.password% -PtestJavaHome=%linux.java8.oracle.64bit%" + param("ui.gradleRunner.gradle.build.file", "") + } + script { + name = "CHECK_CLEAN_M2" + executionMode = BuildStep.ExecutionMode.ALWAYS + scriptContent = """ + REPO=/home/%env.USER%/.m2/repository + if [ -e ${'$'}REPO ] ; then + tree ${'$'}REPO + rm -rf ${'$'}REPO + echo "${'$'}REPO was polluted during the build" + exit 1 + else + echo "${'$'}REPO does not exist" + fi + """.trimIndent() + } + gradle { + name = "TAG_BUILD" + executionMode = BuildStep.ExecutionMode.ALWAYS + tasks = "tagBuild" + buildFile = "" + gradleParams = "-PteamCityUsername=%teamcity.username.restbot% -PteamCityPassword=%teamcity.password.restbot% -PteamCityBuildId=%teamcity.build.id% -PgithubToken=%github.ci.oauth.token%" + param("ui.gradleRunner.gradle.build.file", "") + } + } + + failureConditions { + executionTimeoutMin = 420 + } + + features { + commitStatusPublisher { + vcsRootExtId = "Gradle_Branches_GradlePersonalBranches" + publisher = github { + githubUrl = "https://api.github.com" + authType = personalToken { + token = "credentialsJSON:5306bfc7-041e-46e8-8d61-1d49424e7b04" + } + } + } + } + + dependencies { + dependency(AbsoluteId("Gradle_Check_CompileAll")) { + snapshot { + onDependencyFailure = FailureAction.CANCEL + onDependencyCancel = FailureAction.CANCEL + } + + artifacts { + cleanDestination = true + artifactRules = "build-receipt.properties => incoming-distributions" + } + } + } + + requirements { + contains("teamcity.agent.jvm.os.name", "Linux") + } +}) diff --git a/.teamcity/Gradle_Util_Performance/buildTypes/Gradle_Util_Performance_PerformanceTestCoordinatorLinux.xml b/.teamcity/Gradle_Util_Performance/buildTypes/Gradle_Util_Performance_PerformanceTestCoordinatorLinux.xml deleted file mode 100644 index 36adaa2ce2a51..0000000000000 --- a/.teamcity/Gradle_Util_Performance/buildTypes/Gradle_Util_Performance_PerformanceTestCoordinatorLinux.xml +++ /dev/null @@ -1,102 +0,0 @@ - - - AdHoc Performance Test Coordinator - Linux - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.teamcity/Gradle_Util_Performance/pluginData/plugin-settings.xml b/.teamcity/Gradle_Util_Performance/pluginData/plugin-settings.xml deleted file mode 100644 index 677e924ad523a..0000000000000 --- a/.teamcity/Gradle_Util_Performance/pluginData/plugin-settings.xml +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/.teamcity/Gradle_Util_Performance/project-config.xml b/.teamcity/Gradle_Util_Performance/project-config.xml deleted file mode 100644 index 842ef873cfae2..0000000000000 --- a/.teamcity/Gradle_Util_Performance/project-config.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - Performance - - - - diff --git a/.teamcity/Gradle_Util_Performance/settings.kts b/.teamcity/Gradle_Util_Performance/settings.kts new file mode 100644 index 0000000000000..b136aefa9183e --- /dev/null +++ b/.teamcity/Gradle_Util_Performance/settings.kts @@ -0,0 +1,35 @@ +package Gradle_Util_Performance + +import jetbrains.buildServer.configs.kotlin.v2018_2.* + +/* +The settings script is an entry point for defining a single +TeamCity project. TeamCity looks for the 'settings.kts' file in a +project directory and runs it if it's found, so the script name +shouldn't be changed and its package should be the same as the +project's id. + +The script should contain a single call to the project() function +with a Project instance or an init function as an argument. + +VcsRoots, BuildTypes, and Templates of this project must be +registered inside project using the vcsRoot(), buildType(), and +template() methods respectively. + +Subprojects can be defined either in their own settings.kts or by +calling the subProjects() method in this project. + +To debug settings scripts in command-line, run the + + mvnDebug org.jetbrains.teamcity:teamcity-configs-maven-plugin:generate + +command and attach your debugger to the port 8000. + +To debug in IntelliJ Idea, open the 'Maven Projects' tool window (View -> +Tool Windows -> Maven Projects), find the generate task +node (Plugins -> teamcity-configs -> teamcity-configs:generate), +the 'Debug' option is available in the context menu for the task. +*/ + +version = "2018.2" +project(Gradle_Util_Performance.Project) \ No newline at end of file From a022121e6edbdc48ea1eb26dc4e33b3a13ffb32d Mon Sep 17 00:00:00 2001 From: Rene Groeschke Date: Tue, 19 Mar 2019 13:32:23 +0100 Subject: [PATCH 627/853] Check logger type for decorating --- .../api/internal/tasks/execution/EventFiringTaskExecuter.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/EventFiringTaskExecuter.java b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/EventFiringTaskExecuter.java index 22c46a29ec483..cf721d879e05f 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/EventFiringTaskExecuter.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/EventFiringTaskExecuter.java @@ -61,10 +61,10 @@ private TaskExecuterResult executeTask(BuildOperationContext operationContext) { try { taskExecutionListener.beforeExecute(task); BuildOperationRef currentOperation = buildOperationExecutor.getCurrentOperation(); - if (logger != null){ + if (logger instanceof ContextAwareTaskLogger) { contextAwareTaskLogger = (ContextAwareTaskLogger) logger; contextAwareTaskLogger.setFallbackBuildOperationId(currentOperation.getId()); - } + } } catch (Throwable t) { state.setOutcome(new TaskExecutionException(task, t)); return TaskExecuterResult.WITHOUT_OUTPUTS; From cedae68ccd4970b26003bd579a989eaef5f92854 Mon Sep 17 00:00:00 2001 From: Stefan Wolf Date: Tue, 19 Mar 2019 11:55:14 +0100 Subject: [PATCH 628/853] Store node dependencies complete information in node To avoid a possibly expensive hash set lookup. --- .../execution/plan/DefaultExecutionPlan.java | 70 ++++++++----------- .../java/org/gradle/execution/plan/Node.java | 22 +++++- .../org/gradle/execution/plan/TaskNode.java | 6 +- 3 files changed, 53 insertions(+), 45 deletions(-) diff --git a/subprojects/core/src/main/java/org/gradle/execution/plan/DefaultExecutionPlan.java b/subprojects/core/src/main/java/org/gradle/execution/plan/DefaultExecutionPlan.java index 844e18c8cce17..a63461e964b20 100644 --- a/subprojects/core/src/main/java/org/gradle/execution/plan/DefaultExecutionPlan.java +++ b/subprojects/core/src/main/java/org/gradle/execution/plan/DefaultExecutionPlan.java @@ -104,10 +104,8 @@ public class DefaultExecutionPlan implements ExecutionPlan { private final Map mutations = Maps.newIdentityHashMap(); private final Map canonicalizedFileCache = Maps.newIdentityHashMap(); private final Map, Boolean> reachableCache = Maps.newHashMap(); - private final Set dependenciesCompleteCache = Sets.newHashSet(); - private final Set dependenciesWithChanges = Sets.newHashSet(); private final List dependenciesWhichRequireMonitoring = Lists.newArrayList(); - private final Set readyToExecute = Sets.newHashSet(); + private boolean maybeNodesReady; private final WorkerLeaseService workerLeaseService; private final GradleInternal gradle; @@ -346,7 +344,9 @@ public NodeInVisitingSegment apply(TaskNode taskNode) { } executionQueue.clear(); Iterables.addAll(executionQueue, nodeMapping); - Iterables.addAll(dependenciesWithChanges, nodeMapping); + for (Node node : executionQueue) { + maybeNodesReady |= node.updateAllDependenciesComplete() && node.isReady(); + } this.dependenciesWhichRequireMonitoring.addAll(dependenciesWhichRequireMonitoring); } @@ -518,10 +518,7 @@ public void clear() { mutations.clear(); canonicalizedFileCache.clear(); reachableCache.clear(); - dependenciesCompleteCache.clear(); - dependenciesWithChanges.clear(); dependenciesWhichRequireMonitoring.clear(); - readyToExecute.clear(); runningNodes.clear(); } @@ -556,22 +553,22 @@ public Node selectNext(WorkerLeaseRegistry.WorkerLease workerLease, ResourceLock return null; } - for (Node node : dependenciesWhichRequireMonitoring) { - if (dependenciesCompleteCache.contains(node)) { - continue; - } + for (Iterator iterator = dependenciesWhichRequireMonitoring.iterator(); iterator.hasNext();) { + Node node = iterator.next(); if (node.isComplete()) { - dependenciesCompleteCache.add(node); - Iterables.addAll(dependenciesWithChanges, node.getAllPredecessors()); + updateAllDependenciesCompleteForPredecessors(node); + iterator.remove(); } } - if (readyToExecute.isEmpty() && dependenciesWithChanges.isEmpty()) { + if (!maybeNodesReady) { return null; } Iterator iterator = executionQueue.iterator(); + boolean foundReadyNode = false; while (iterator.hasNext()) { Node node = iterator.next(); - if (node.isReady() && allDependenciesComplete(node)) { + if (node.isReady() && node.allDependenciesComplete()) { + foundReadyNode = true; MutationInfo mutations = getResolvedMutationInfo(node); // TODO: convert output file checks to a resource lock @@ -579,7 +576,6 @@ public Node selectNext(WorkerLeaseRegistry.WorkerLease workerLease, ResourceLock || !workerLease.tryLock() || !canRunWithCurrentlyExecutedNodes(node, mutations)) { resourceLockState.releaseLocks(); - readyToExecute.add(node); continue; } @@ -587,17 +583,23 @@ public Node selectNext(WorkerLeaseRegistry.WorkerLease workerLease, ResourceLock recordNodeStarted(node); node.startExecution(); } else { - Iterables.addAll(dependenciesWithChanges, node.getAllPredecessors()); node.skipExecution(); + updateAllDependenciesCompleteForPredecessors(node); } iterator.remove(); - readyToExecute.remove(node); return node; } } + maybeNodesReady = foundReadyNode; return null; } + private void updateAllDependenciesCompleteForPredecessors(Node node) { + for (Node predecessor : node.getAllPredecessors()) { + maybeNodesReady |= predecessor.updateAllDependenciesComplete() && predecessor.isReady(); + } + } + private boolean tryLockProjectFor(Node node) { if (node.getProject() != null) { return getProjectLock(node.getProject()).tryLock(); @@ -710,23 +712,6 @@ private void withDeadlockHandling(TaskNode task, String singular, String descrip } } - private boolean allDependenciesComplete(Node node) { - if (dependenciesCompleteCache.contains(node)) { - return true; - } - - if (!dependenciesWithChanges.contains(node)) { - return false; - } - boolean dependenciesComplete = node.allDependenciesComplete(); - dependenciesWithChanges.remove(node); - if (dependenciesComplete) { - dependenciesCompleteCache.add(node); - } - - return dependenciesComplete; - } - private boolean allProjectsLocked() { for (ResourceLock lock : projectLocks.values()) { if (!lock.isLocked()) { @@ -886,7 +871,6 @@ private void recordNodeStarted(Node node) { private void recordNodeCompleted(Node node) { runningNodes.remove(node); - Iterables.addAll(dependenciesWithChanges, node.getAllPredecessors()); MutationInfo mutations = this.mutations.get(node); for (Node producer : mutations.producingNodes) { MutationInfo producerMutations = this.mutations.get(producer); @@ -898,6 +882,7 @@ private void recordNodeCompleted(Node node) { if (canRemoveMutation(mutations)) { this.mutations.remove(node); } + updateAllDependenciesCompleteForPredecessors(node); } private static boolean canRemoveMutation(@Nullable MutationInfo mutations) { @@ -908,7 +893,8 @@ private static boolean canRemoveMutation(@Nullable MutationInfo mutations) { public void nodeComplete(Node node) { try { if (!node.isComplete()) { - enforceFinalizers(node, dependenciesWithChanges); + enforceFinalizers(node); + maybeNodesReady = true; if (node.isFailed()) { handleFailure(node); } @@ -921,13 +907,11 @@ public void nodeComplete(Node node) { } } - private static void enforceFinalizers(Node node, Set nodesWithDependencyChanges) { + private static void enforceFinalizers(Node node) { for (Node finalizerNode : node.getFinalizers()) { - nodesWithDependencyChanges.add(finalizerNode); if (finalizerNode.isRequired() || finalizerNode.isMustNotRun()) { HashSet enforcedNodes = Sets.newHashSet(); enforceWithDependencies(finalizerNode, enforcedNodes); - nodesWithDependencyChanges.addAll(enforcedNodes); } } } @@ -945,6 +929,10 @@ private static void enforceWithDependencies(Node nodeInfo, Set enforcedNod if (node.isMustNotRun() || node.isRequired()) { node.enforceRun(); + // Completed changed from true to false - inform all nodes depending on this one. + for (Node predecessor : node.getAllPredecessors()) { + predecessor.forceAllDependenciesCompleteUpdate(); + } } } } @@ -990,7 +978,6 @@ public void cancelExecution() { private boolean abortExecution(boolean abortAll) { boolean aborted = false; for (Node node : nodeMapping) { - Iterables.addAll(dependenciesWithChanges, node.getAllPredecessors()); // Allow currently executing and enforced tasks to complete, but skip everything else. if (node.isRequired()) { node.skipExecution(); @@ -1002,6 +989,7 @@ private boolean abortExecution(boolean abortAll) { node.abortExecution(); aborted = true; } + updateAllDependenciesCompleteForPredecessors(node); } return aborted; } diff --git a/subprojects/core/src/main/java/org/gradle/execution/plan/Node.java b/subprojects/core/src/main/java/org/gradle/execution/plan/Node.java index 0221e67ae9a00..48208c21f1a6d 100644 --- a/subprojects/core/src/main/java/org/gradle/execution/plan/Node.java +++ b/subprojects/core/src/main/java/org/gradle/execution/plan/Node.java @@ -42,6 +42,7 @@ enum ExecutionState { private ExecutionState state; private boolean dependenciesProcessed; + private boolean allDependenciesComplete; private Throwable executionFailure; private final NavigableSet dependencySuccessors = Sets.newTreeSet(); private final NavigableSet dependencyPredecessors = Sets.newTreeSet(); @@ -172,7 +173,7 @@ protected void addDependencySuccessor(Node toNode) { } @OverridingMethodsMustInvokeSuper - public boolean allDependenciesComplete() { + protected boolean doCheckDependenciesComplete() { for (Node dependency : dependencySuccessors) { if (!dependency.isComplete()) { return false; @@ -182,6 +183,25 @@ public boolean allDependenciesComplete() { return true; } + /** + * Returns if all dependencies completed, but have not been completed in the last check. + */ + public boolean updateAllDependenciesComplete() { + if (!allDependenciesComplete) { + forceAllDependenciesCompleteUpdate(); + return allDependenciesComplete; + } + return false; + } + + public void forceAllDependenciesCompleteUpdate() { + allDependenciesComplete = doCheckDependenciesComplete(); + } + + public boolean allDependenciesComplete() { + return allDependenciesComplete; + } + public boolean allDependenciesSuccessful() { for (Node dependency : dependencySuccessors) { if (!dependency.isSuccessful()) { diff --git a/subprojects/core/src/main/java/org/gradle/execution/plan/TaskNode.java b/subprojects/core/src/main/java/org/gradle/execution/plan/TaskNode.java index 96a2e92d76f51..3104af2fa2c03 100644 --- a/subprojects/core/src/main/java/org/gradle/execution/plan/TaskNode.java +++ b/subprojects/core/src/main/java/org/gradle/execution/plan/TaskNode.java @@ -34,8 +34,8 @@ public abstract class TaskNode extends Node { private final NavigableSet finalizingSuccessors = Sets.newTreeSet(); @Override - public boolean allDependenciesComplete() { - if (!super.allDependenciesComplete()) { + public boolean doCheckDependenciesComplete() { + if (!super.doCheckDependenciesComplete()) { return false; } for (Node dependency : mustSuccessors) { @@ -107,7 +107,7 @@ public Iterable getAllSuccessorsInReverseOrder() { @Override public Iterable getAllPredecessors() { - return Iterables.concat(mustPredecessors, super.getAllPredecessors()); + return Iterables.concat(mustPredecessors, finalizers, super.getAllPredecessors()); } @Override From ac3511180fb5cb895b0377bc7f57890e37ded828 Mon Sep 17 00:00:00 2001 From: Stefan Wolf Date: Tue, 19 Mar 2019 15:39:03 +0100 Subject: [PATCH 629/853] Add test for strange finalizer behaviour When there is a finalizer with some other tasks which needs to run after the finalizer, then depending on how many executers there are, the tasks may run in different order. Situation: dependency -> finalized -finalizedBy-> finalizer -mustRunBefore -> mustRunAfter mustRunAfter can run right at the beginning, since its dependencies are completed. Though when the finalized task finished, causing the finalizer task to must run, mustRunAfter needs to wait until finalizer finishes to start executing. --- .../DefaultExecutionPlanParallelTest.groovy | 82 +++++++++++++++++++ 1 file changed, 82 insertions(+) diff --git a/subprojects/core/src/test/groovy/org/gradle/execution/plan/DefaultExecutionPlanParallelTest.groovy b/subprojects/core/src/test/groovy/org/gradle/execution/plan/DefaultExecutionPlanParallelTest.groovy index 278e34f733dbb..8f146dc4022b6 100644 --- a/subprojects/core/src/test/groovy/org/gradle/execution/plan/DefaultExecutionPlanParallelTest.groovy +++ b/subprojects/core/src/test/groovy/org/gradle/execution/plan/DefaultExecutionPlanParallelTest.groovy @@ -673,6 +673,88 @@ class DefaultExecutionPlanParallelTest extends AbstractProjectBuilderSpec { selectNextTask() == null } + def "must run after is sometimes not respected for finalizers"() { + Task dependency = project.task("dependency", type: Async) + Task finalized = project.task("finalized", type: Async) + Task finalizer = project.task("finalizer", type: Async) + Task mustRunAfter = project.task("mustRunAfter", type: Async) + + finalized.dependsOn(dependency) + finalized.finalizedBy(finalizer) + mustRunAfter.mustRunAfter(finalizer) + + when: + executionPlan.addEntryTasks([finalized]) + executionPlan.addEntryTasks([mustRunAfter]) + executionPlan.determineExecutionPlan() + + and: + def dependencyNode = selectNextTaskNode() + def mustRunAfterNode = selectNextTaskNode() + then: + selectNextTaskNode() == null + dependencyNode.task == dependency + mustRunAfterNode.task == mustRunAfter + + when: + executionPlan.nodeComplete(dependencyNode) + + def finalizedNode = selectNextTaskNode() + then: + selectNextTaskNode() == null + finalizedNode.task == finalized + + when: + executionPlan.nodeComplete(finalizedNode) + + def finalizerNode = selectNextTaskNode() + then: + selectNextTaskNode() == null + finalizerNode.task == finalizer + } + + def "must run after is sometimes respected for finalizers"() { + Task dependency = project.task("dependency", type: Async) + Task finalized = project.task("finalized", type: Async) + Task finalizer = project.task("finalizer", type: Async) + Task mustRunAfter = project.task("mustRunAfter", type: Async) + + finalized.dependsOn(dependency) + finalized.finalizedBy(finalizer) + mustRunAfter.mustRunAfter(finalizer) + + when: + executionPlan.addEntryTasks([finalized]) + executionPlan.addEntryTasks([mustRunAfter]) + executionPlan.determineExecutionPlan() + + and: + def dependencyNode = selectNextTaskNode() + then: + dependencyNode.task == dependency + + when: + executionPlan.nodeComplete(dependencyNode) + + def finalizedNode = selectNextTaskNode() + then: + finalizedNode.task == finalized + + when: + executionPlan.nodeComplete(finalizedNode) + + def finalizerNode = selectNextTaskNode() + then: + selectNextTaskNode() == null + finalizerNode.task == finalizer + + when: + executionPlan.nodeComplete(finalizerNode) + then: + selectNextTask() == mustRunAfter + selectNextTask() == null + } + def "handles an exception while walking the task graph when an enforced task is present"() { given: Task finalizer = project.task("finalizer", type: BrokenTask) From 15ff01c114ef7315bfed287d223685711b879e59 Mon Sep 17 00:00:00 2001 From: Stefan Wolf Date: Tue, 19 Mar 2019 21:40:30 +0100 Subject: [PATCH 630/853] Move new method to a better place --- .../src/main/java/org/gradle/execution/plan/Node.java | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/subprojects/core/src/main/java/org/gradle/execution/plan/Node.java b/subprojects/core/src/main/java/org/gradle/execution/plan/Node.java index 48208c21f1a6d..61ea78decedf5 100644 --- a/subprojects/core/src/main/java/org/gradle/execution/plan/Node.java +++ b/subprojects/core/src/main/java/org/gradle/execution/plan/Node.java @@ -31,10 +31,6 @@ */ public abstract class Node implements Comparable { - protected Iterable getAllPredecessors() { - return getDependencyPredecessors(); - } - @VisibleForTesting enum ExecutionState { UNKNOWN, NOT_REQUIRED, SHOULD_RUN, MUST_RUN, MUST_NOT_RUN, EXECUTING, EXECUTED, SKIPPED @@ -211,6 +207,11 @@ public boolean allDependenciesSuccessful() { return true; } + @OverridingMethodsMustInvokeSuper + protected Iterable getAllPredecessors() { + return getDependencyPredecessors(); + } + public abstract void prepareForExecution(); public abstract void resolveDependencies(TaskDependencyResolver dependencyResolver, Action processHardSuccessor); From 796504edffe1d4b8c085cbb37edbbc848d2c9a73 Mon Sep 17 00:00:00 2001 From: Sterling Greene Date: Tue, 19 Mar 2019 16:48:46 -0400 Subject: [PATCH 631/853] Fix null handling of DirectoryProperty/RegularFileProperty.set(File) Previously, we failed in a strange way if you explicitly called set(File) with a null. set(Directory) or set(RegularFile) were OK. --- .../gradle/api/file/DirectoryProperty.java | 3 ++- .../gradle/api/file/RegularFileProperty.java | 3 ++- .../file/FilePropertiesIntegrationTest.groovy | 21 +++++++++++++++++++ .../file/DefaultFilePropertyFactory.java | 8 +++++++ .../tasks/bundling/AbstractArchiveTask.java | 2 +- 5 files changed, 34 insertions(+), 3 deletions(-) diff --git a/subprojects/core-api/src/main/java/org/gradle/api/file/DirectoryProperty.java b/subprojects/core-api/src/main/java/org/gradle/api/file/DirectoryProperty.java index 0707d9969f38f..a74a3c29b3fd3 100644 --- a/subprojects/core-api/src/main/java/org/gradle/api/file/DirectoryProperty.java +++ b/subprojects/core-api/src/main/java/org/gradle/api/file/DirectoryProperty.java @@ -21,6 +21,7 @@ import org.gradle.api.provider.Property; import org.gradle.api.provider.Provider; +import javax.annotation.Nullable; import java.io.File; /** @@ -49,7 +50,7 @@ public interface DirectoryProperty extends Property { /** * Sets the location of this directory. */ - void set(File dir); + void set(@Nullable File dir); /** * {@inheritDoc} diff --git a/subprojects/core-api/src/main/java/org/gradle/api/file/RegularFileProperty.java b/subprojects/core-api/src/main/java/org/gradle/api/file/RegularFileProperty.java index 873245e568d07..f786f6e2ac106 100644 --- a/subprojects/core-api/src/main/java/org/gradle/api/file/RegularFileProperty.java +++ b/subprojects/core-api/src/main/java/org/gradle/api/file/RegularFileProperty.java @@ -21,6 +21,7 @@ import org.gradle.api.provider.Property; import org.gradle.api.provider.Provider; +import javax.annotation.Nullable; import java.io.File; /** @@ -44,7 +45,7 @@ public interface RegularFileProperty extends Property { /** * Sets the location of this file, using a {@link File} instance. */ - void set(File file); + void set(@Nullable File file); /** * {@inheritDoc} diff --git a/subprojects/core/src/integTest/groovy/org/gradle/api/file/FilePropertiesIntegrationTest.groovy b/subprojects/core/src/integTest/groovy/org/gradle/api/file/FilePropertiesIntegrationTest.groovy index f8297bd42cbac..91cf39d7b17fa 100644 --- a/subprojects/core/src/integTest/groovy/org/gradle/api/file/FilePropertiesIntegrationTest.groovy +++ b/subprojects/core/src/integTest/groovy/org/gradle/api/file/FilePropertiesIntegrationTest.groovy @@ -100,6 +100,17 @@ assert custom.prop.get().asFile == file("build/dir3") custom.prop = file("dir4") assert custom.prop.get().asFile == file("dir4") +custom.prop.set((Directory)null) +assert custom.prop.getOrNull() == null + +custom.prop = file("foo") +custom.prop.set(null) +assert custom.prop.getOrNull() == null + +custom.prop = file("foo") +custom.prop.set((File)null) +assert custom.prop.getOrNull() == null + """ expect: @@ -131,6 +142,16 @@ assert custom.prop.get().asFile == file("build/file3") custom.prop = file("file4") assert custom.prop.get().asFile == file("file4") +custom.prop.set((RegularFile)null) +assert custom.prop.getOrNull() == null + +custom.prop = file("foo") +custom.prop.set(null) +assert custom.prop.getOrNull() == null + +custom.prop = file("foo") +custom.prop.set((File)null) +assert custom.prop.getOrNull() == null """ expect: diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/file/DefaultFilePropertyFactory.java b/subprojects/core/src/main/java/org/gradle/api/internal/file/DefaultFilePropertyFactory.java index 4524855cbfda1..cb85b60196319 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/file/DefaultFilePropertyFactory.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/file/DefaultFilePropertyFactory.java @@ -290,6 +290,10 @@ public Provider getAsFile() { @Override public void set(File file) { + if (file == null) { + value(null); + return; + } set(new FixedFile(fileResolver.resolve(file))); } @@ -376,6 +380,10 @@ void resolveAndSet(Object value) { @Override public void set(File dir) { + if (dir == null) { + value(null); + return; + } File resolved = resolver.resolve(dir); set(new FixedDirectory(resolved, resolver.newResolver(resolved))); } diff --git a/subprojects/core/src/main/java/org/gradle/api/tasks/bundling/AbstractArchiveTask.java b/subprojects/core/src/main/java/org/gradle/api/tasks/bundling/AbstractArchiveTask.java index e0f05da0e5180..f8d31eddaa581 100644 --- a/subprojects/core/src/main/java/org/gradle/api/tasks/bundling/AbstractArchiveTask.java +++ b/subprojects/core/src/main/java/org/gradle/api/tasks/bundling/AbstractArchiveTask.java @@ -189,7 +189,7 @@ public File getDestinationDir() { */ @Deprecated public void setDestinationDir(File destinationDir) { - archiveDestinationDirectory.set(destinationDir); + archiveDestinationDirectory.set(getProject().file(destinationDir)); } /** From 871dd09b7ac5c12c3c5c5c11a816b9780343b1cd Mon Sep 17 00:00:00 2001 From: Gradleware Git Bot Date: Wed, 20 Mar 2019 02:54:46 +0100 Subject: [PATCH 632/853] Publish 5.3-20190320013427+0000 --- released-versions.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/released-versions.json b/released-versions.json index 8432d7afc51b3..565619b8d6452 100644 --- a/released-versions.json +++ b/released-versions.json @@ -1,7 +1,7 @@ { "latestReleaseSnapshot": { - "version": "5.3-20190319010128+0000", - "buildTime": "20190319010128+0000" + "version": "5.3-20190320013427+0000", + "buildTime": "20190320013427+0000" }, "latestRc": { "version": "5.3-rc-3", From 12c09a771e0129b9c41b8de1a86e91a1bf6fe7f7 Mon Sep 17 00:00:00 2001 From: Bo Zhang Date: Wed, 20 Mar 2019 13:49:02 +0800 Subject: [PATCH 633/853] Update tagging plugin (#8800) This PR applies latest tagging plugin (which runs tagging in `GRADLE_RERUN` step) and removes `TAG_BUILD` steps in configurations. --- .../GradleBuildConfigurationDefaults.kt | 21 +++---------------- .../ApplyDefaultConfigurationTest.kt | 13 +++++------- build.gradle.kts | 2 +- 3 files changed, 9 insertions(+), 27 deletions(-) diff --git a/.teamcity/Gradle_Check/configurations/GradleBuildConfigurationDefaults.kt b/.teamcity/Gradle_Check/configurations/GradleBuildConfigurationDefaults.kt index 1e2cb4c1ac87e..d998f6863c415 100644 --- a/.teamcity/Gradle_Check/configurations/GradleBuildConfigurationDefaults.kt +++ b/.teamcity/Gradle_Check/configurations/GradleBuildConfigurationDefaults.kt @@ -132,20 +132,6 @@ fun BaseGradleBuildType.verifyTestFilesCleanupStep(daemon: Boolean = true) { } } -private -fun BaseGradleBuildType.tagBuildStep(model: CIBuildModel, daemon: Boolean = true) { - steps { - if (model.tagBuilds) { - gradleWrapper { - name = "TAG_BUILD" - executionMode = BuildStep.ExecutionMode.ALWAYS - tasks = "tagBuild" - gradleParams = "${gradleParameterString(daemon)} -PteamCityUsername=%teamcity.username.restbot% -PteamCityPassword=%teamcity.password.restbot% -PteamCityBuildId=%teamcity.build.id% -PgithubToken=%github.ci.oauth.token%" - } - } - } -} - private fun BaseGradleBuildType.gradleRunnerStep(model: CIBuildModel, gradleTasks: String, os: Os = Os.linux, extraParameters: String = "", daemon: Boolean = true) { val buildScanTags = model.buildScanTags + listOfNotNull(stage?.id) @@ -174,7 +160,7 @@ fun BaseGradleBuildType.gradleRerunnerStep(model: CIBuildModel, gradleTasks: Str steps { gradleWrapper { name = "GRADLE_RERUNNER" - tasks = gradleTasks + tasks = "$gradleTasks tagBuild" executionMode = BuildStep.ExecutionMode.RUN_ON_FAILURE gradleParams = ( listOf(gradleParameterString(daemon)) + @@ -184,7 +170,8 @@ fun BaseGradleBuildType.gradleRerunnerStep(model: CIBuildModel, gradleTasks: Str "-PteamCityPassword=%teamcity.password.restbot%" + "-PteamCityBuildId=%teamcity.build.id%" + buildScanTags.map { configurations.buildScanTag(it) } + - "-PonlyPreviousFailedTestClasses=true" + "-PonlyPreviousFailedTestClasses=true" + + "-PgithubToken=%github.ci.oauth.token%" ).joinToString(separator = " ") } } @@ -213,7 +200,6 @@ fun applyDefaults(model: CIBuildModel, buildType: BaseGradleBuildType, gradleTas buildType.checkCleanM2Step(os) buildType.verifyTestFilesCleanupStep(daemon) - buildType.tagBuildStep(model, daemon) applyDefaultDependencies(model, buildType, notQuick) } @@ -230,7 +216,6 @@ fun applyTestDefaults(model: CIBuildModel, buildType: BaseGradleBuildType, gradl buildType.checkCleanM2Step(os) buildType.verifyTestFilesCleanupStep(daemon) - buildType.tagBuildStep(model, daemon) applyDefaultDependencies(model, buildType, notQuick) } diff --git a/.teamcityTest/Gradle_Check_Tests/ApplyDefaultConfigurationTest.kt b/.teamcityTest/Gradle_Check_Tests/ApplyDefaultConfigurationTest.kt index 259d1b65221a9..19e6842db68c2 100644 --- a/.teamcityTest/Gradle_Check_Tests/ApplyDefaultConfigurationTest.kt +++ b/.teamcityTest/Gradle_Check_Tests/ApplyDefaultConfigurationTest.kt @@ -62,8 +62,7 @@ class ApplyDefaultConfigurationTest { assertEquals(listOf( "GRADLE_RUNNER", "CHECK_CLEAN_M2", - "VERIFY_TEST_FILES_CLEANUP", - "TAG_BUILD" + "VERIFY_TEST_FILES_CLEANUP" ), steps.items.map(BuildStep::name)) assertEquals(expectedRunnerParam(), getGradleStep("GRADLE_RUNNER").gradleParams) } @@ -82,8 +81,7 @@ class ApplyDefaultConfigurationTest { "GRADLE_RUNNER", "GRADLE_RERUNNER", "CHECK_CLEAN_M2", - "VERIFY_TEST_FILES_CLEANUP", - "TAG_BUILD" + "VERIFY_TEST_FILES_CLEANUP" ), steps.items.map(BuildStep::name)) verifyGradleRunnerParams(extraParameters, daemon, expectedDaemonParam) } @@ -104,8 +102,7 @@ class ApplyDefaultConfigurationTest { "GRADLE_RERUNNER", "KILL_PROCESSES_STARTED_BY_GRADLE_RERUN", "CHECK_CLEAN_M2", - "VERIFY_TEST_FILES_CLEANUP", - "TAG_BUILD" + "VERIFY_TEST_FILES_CLEANUP" ), steps.items.map(BuildStep::name)) verifyGradleRunnerParams(extraParameters, daemon, expectedDaemonParam) } @@ -116,9 +113,9 @@ class ApplyDefaultConfigurationTest { assertEquals(BuildStep.ExecutionMode.RUN_ON_FAILURE, getGradleStep("GRADLE_RERUNNER").executionMode) assertEquals(expectedRunnerParam(expectedDaemonParam, extraParameters), getGradleStep("GRADLE_RUNNER").gradleParams) - assertEquals(expectedRunnerParam(expectedDaemonParam, extraParameters) + " -PonlyPreviousFailedTestClasses=true", getGradleStep("GRADLE_RERUNNER").gradleParams) + assertEquals(expectedRunnerParam(expectedDaemonParam, extraParameters) + " -PonlyPreviousFailedTestClasses=true -PteamCityBuildId=%teamcity.build.id%", getGradleStep("GRADLE_RERUNNER").gradleParams) assertEquals("clean myTask", getGradleStep("GRADLE_RUNNER").tasks) - assertEquals("myTask", getGradleStep("GRADLE_RERUNNER").tasks) + assertEquals("myTask tagBuild", getGradleStep("GRADLE_RERUNNER").tasks) } private diff --git a/build.gradle.kts b/build.gradle.kts index a86661ab7a462..d0989755ac27f 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -32,7 +32,7 @@ plugins { // We have to apply it here at the moment, so that when the build scan plugin is auto-applied via --scan can detect that // the plugin has been already applied. For that the plugin has to be applied with the new plugin DSL syntax. com.gradle.`build-scan` - id("org.gradle.ci.tag-single-build") version("0.58") + id("org.gradle.ci.tag-single-build") version("0.62") } defaultTasks("assemble") From 2eba75eddc71d9557986780701c372a674b80257 Mon Sep 17 00:00:00 2001 From: Bo Zhang Date: Wed, 20 Mar 2019 14:01:28 +0800 Subject: [PATCH 634/853] Fix failed TC Kotlin DSL test --- .../Gradle_Check_Tests/ApplyDefaultConfigurationTest.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.teamcityTest/Gradle_Check_Tests/ApplyDefaultConfigurationTest.kt b/.teamcityTest/Gradle_Check_Tests/ApplyDefaultConfigurationTest.kt index 19e6842db68c2..ebfcf23fdccdf 100644 --- a/.teamcityTest/Gradle_Check_Tests/ApplyDefaultConfigurationTest.kt +++ b/.teamcityTest/Gradle_Check_Tests/ApplyDefaultConfigurationTest.kt @@ -113,7 +113,7 @@ class ApplyDefaultConfigurationTest { assertEquals(BuildStep.ExecutionMode.RUN_ON_FAILURE, getGradleStep("GRADLE_RERUNNER").executionMode) assertEquals(expectedRunnerParam(expectedDaemonParam, extraParameters), getGradleStep("GRADLE_RUNNER").gradleParams) - assertEquals(expectedRunnerParam(expectedDaemonParam, extraParameters) + " -PonlyPreviousFailedTestClasses=true -PteamCityBuildId=%teamcity.build.id%", getGradleStep("GRADLE_RERUNNER").gradleParams) + assertEquals(expectedRunnerParam(expectedDaemonParam, extraParameters) + " -PonlyPreviousFailedTestClasses=true -PgithubToken=%github.ci.oauth.token%", getGradleStep("GRADLE_RERUNNER").gradleParams) assertEquals("clean myTask", getGradleStep("GRADLE_RUNNER").tasks) assertEquals("myTask tagBuild", getGradleStep("GRADLE_RERUNNER").tasks) } From bc87ce25cdb676baf679bba3c66c3baf5b193d9c Mon Sep 17 00:00:00 2001 From: Stefan Wolf Date: Tue, 19 Mar 2019 21:38:43 +0100 Subject: [PATCH 635/853] Extract common code for AdHoc Coordinator Job --- .../GradleBuildConfigurationDefaults.kt | 99 +++++------------ .../configurations/Gradleception.kt | 3 +- .../IndividualPerformanceScenarioWorkers.kt | 6 +- .../configurations/PerformanceTest.kt | 48 +++----- .../configurations/StagePasses.kt | 3 +- .teamcity/Gradle_Util_Performance/Project.kt | 6 +- .../AdHocPerformanceTestCoordinatorLinux.kt | 43 ++++++++ ...rformance_AdHocPerformanceScenarioLinux.kt | 11 +- ...ormance_PerformanceTestCoordinatorLinux.kt | 103 ------------------ .teamcity/common/extensions.kt | 75 +++++++++++++ .../common/performance-test-extensions.kt | 55 ++++++++++ 11 files changed, 229 insertions(+), 223 deletions(-) create mode 100644 .teamcity/Gradle_Util_Performance/buildTypes/AdHocPerformanceTestCoordinatorLinux.kt delete mode 100644 .teamcity/Gradle_Util_Performance/buildTypes/Gradle_Util_Performance_PerformanceTestCoordinatorLinux.kt create mode 100644 .teamcity/common/performance-test-extensions.kt diff --git a/.teamcity/Gradle_Check/configurations/GradleBuildConfigurationDefaults.kt b/.teamcity/Gradle_Check/configurations/GradleBuildConfigurationDefaults.kt index d998f6863c415..6b3dd19026f01 100644 --- a/.teamcity/Gradle_Check/configurations/GradleBuildConfigurationDefaults.kt +++ b/.teamcity/Gradle_Check/configurations/GradleBuildConfigurationDefaults.kt @@ -1,18 +1,19 @@ package configurations import common.Os +import common.applyDefaultSettings +import common.buildToolGradleParameters +import common.checkCleanM2 +import common.compileAllDependency import common.gradleWrapper -import common.requiresOs import jetbrains.buildServer.configs.kotlin.v2018_2.AbsoluteId import jetbrains.buildServer.configs.kotlin.v2018_2.BuildFeatures import jetbrains.buildServer.configs.kotlin.v2018_2.BuildStep import jetbrains.buildServer.configs.kotlin.v2018_2.BuildSteps import jetbrains.buildServer.configs.kotlin.v2018_2.BuildType -import jetbrains.buildServer.configs.kotlin.v2018_2.CheckoutMode import jetbrains.buildServer.configs.kotlin.v2018_2.FailureAction import jetbrains.buildServer.configs.kotlin.v2018_2.ProjectFeatures import jetbrains.buildServer.configs.kotlin.v2018_2.buildFeatures.commitStatusPublisher -import jetbrains.buildServer.configs.kotlin.v2018_2.buildSteps.script import model.CIBuildModel import model.GradleSubproject import model.TestCoverage @@ -25,19 +26,7 @@ fun shouldBeSkipped(subProject: GradleSubproject, testConfig: TestCoverage): Boo return testConfig.os.ignoredSubprojects.contains(subProject.name) } -fun gradleParameterString(daemon: Boolean = true) = gradleParameters(daemon).joinToString(separator = " ") - -fun gradleParameters(daemon: Boolean = true, isContinue: Boolean = true): List = - listOf( - "-PmaxParallelForks=%maxParallelForks%", - "-s", - if (daemon) "--daemon" else "--no-daemon", - if (isContinue) "--continue" else "", - """-I "%teamcity.build.checkoutDir%/gradle/init-scripts/build-scan.init.gradle.kts"""", - "-Dorg.gradle.internal.tasks.createops", - "-Dorg.gradle.internal.plugins.portal.url.override=%gradle.plugins.portal.url%" - ) - +fun gradleParameterString(daemon: Boolean = true) = buildToolGradleParameters(daemon).joinToString(separator = " ") val m2CleanScriptUnixLike = """ REPO=%teamcity.agent.jvm.user.home%/.m2/repository @@ -59,36 +48,6 @@ val m2CleanScriptWindows = """ ) """.trimIndent() -fun applyDefaultSettings(buildType: BuildType, os: Os = Os.linux, timeout: Int = 30, vcsRoot: String = "Gradle_Branches_GradlePersonalBranches") { - buildType.artifactRules = """ - build/report-* => . - buildSrc/build/report-* => . - subprojects/*/build/tmp/test files/** => test-files - build/errorLogs/** => errorLogs - build/reports/incubation/** => incubation-reports - """.trimIndent() - - buildType.vcs { - root(AbsoluteId(vcsRoot)) - checkoutMode = CheckoutMode.ON_AGENT - buildDefaultBranch = !vcsRoot.contains("Branches") - } - - buildType.requirements { - requiresOs(os) - } - - buildType.failureConditions { - executionTimeoutMin = timeout - } - - if (os == Os.linux || os == Os.macos) { - buildType.params { - param("env.LC_ALL", "en_US.UTF-8") - } - } -} - fun BuildFeatures.publishBuildStatusToGithub() { commitStatusPublisher { vcsRootExtId = "Gradle_Branches_GradlePersonalBranches" @@ -111,27 +70,32 @@ fun ProjectFeatures.buildReportTab(title: String, startPage: String) { } private -fun BaseGradleBuildType.checkCleanM2Step(os: Os = Os.linux) { +fun BaseGradleBuildType.verifyTestFilesCleanupStep(daemon: Boolean = true) { steps { - script { - name = "CHECK_CLEAN_M2" - executionMode = BuildStep.ExecutionMode.ALWAYS - scriptContent = if (os == Os.windows) m2CleanScriptWindows else m2CleanScriptUnixLike + gradleWrapper { + name = "VERIFY_TEST_FILES_CLEANUP" + tasks = "verifyTestFilesCleanup" + gradleParams = gradleParameterString(daemon) } } } private -fun BaseGradleBuildType.verifyTestFilesCleanupStep(daemon: Boolean = true) { - steps { +fun BuildSteps.tagBuild(tagBuild: Boolean = true, daemon: Boolean = true) { + if (tagBuild) { gradleWrapper { - name = "VERIFY_TEST_FILES_CLEANUP" - tasks = "verifyTestFilesCleanup" - gradleParams = gradleParameterString(daemon) + name = "TAG_BUILD" + executionMode = BuildStep.ExecutionMode.ALWAYS + tasks = "tagBuild" + gradleParams = "${gradleParameterString(daemon)} -PteamCityUsername=%teamcity.username.restbot% -PteamCityPassword=%teamcity.password.restbot% -PteamCityBuildId=%teamcity.build.id% -PgithubToken=%github.ci.oauth.token%" } } } +fun BuildSteps.tagBuild(model: CIBuildModel, daemon: Boolean = true) { + tagBuild(tagBuild = model.tagBuilds, daemon = daemon) +} + private fun BaseGradleBuildType.gradleRunnerStep(model: CIBuildModel, gradleTasks: String, os: Os = Os.linux, extraParameters: String = "", daemon: Boolean = true) { val buildScanTags = model.buildScanTags + listOfNotNull(stage?.id) @@ -192,20 +156,20 @@ fun BaseGradleBuildType.killProcessStepIfNecessary(stepName: String, os: Os = Os } fun applyDefaults(model: CIBuildModel, buildType: BaseGradleBuildType, gradleTasks: String, notQuick: Boolean = false, os: Os = Os.linux, extraParameters: String = "", timeout: Int = 90, extraSteps: BuildSteps.() -> Unit = {}, daemon: Boolean = true) { - applyDefaultSettings(buildType, os, timeout) + buildType.applyDefaultSettings(os, timeout) buildType.gradleRunnerStep(model, gradleTasks, os, extraParameters, daemon) buildType.steps.extraSteps() - buildType.checkCleanM2Step(os) + buildType.steps.checkCleanM2(os) buildType.verifyTestFilesCleanupStep(daemon) applyDefaultDependencies(model, buildType, notQuick) } fun applyTestDefaults(model: CIBuildModel, buildType: BaseGradleBuildType, gradleTasks: String, notQuick: Boolean = false, os: Os = Os.linux, extraParameters: String = "", timeout: Int = 90, extraSteps: BuildSteps.() -> Unit = {}, daemon: Boolean = true) { - applyDefaultSettings(buildType, os, timeout) + buildType.applyDefaultSettings(os, timeout) buildType.gradleRunnerStep(model, gradleTasks, os, extraParameters, daemon) buildType.killProcessStepIfNecessary("KILL_PROCESSES_STARTED_BY_GRADLE", os) @@ -214,7 +178,7 @@ fun applyTestDefaults(model: CIBuildModel, buildType: BaseGradleBuildType, gradl buildType.steps.extraSteps() - buildType.checkCleanM2Step(os) + buildType.steps.checkCleanM2(os) buildType.verifyTestFilesCleanupStep(daemon) applyDefaultDependencies(model, buildType, notQuick) @@ -239,20 +203,7 @@ fun applyDefaultDependencies(model: CIBuildModel, buildType: BuildType, notQuick if (buildType !is CompileAll) { buildType.dependencies { - val compileAllId = CompileAll.buildTypeId(model) - // Compile All has to succeed before anything else is started - dependency(AbsoluteId(compileAllId)) { - snapshot { - onDependencyFailure = FailureAction.CANCEL - onDependencyCancel = FailureAction.CANCEL - } - } - // Get the build receipt from sanity check to reuse the timestamp - artifacts(AbsoluteId(compileAllId)) { - id = "ARTIFACT_DEPENDENCY_$compileAllId" - cleanDestination = true - artifactRules = "build-receipt.properties => incoming-distributions" - } + compileAllDependency(CompileAll.buildTypeId(model)) } } } diff --git a/.teamcity/Gradle_Check/configurations/Gradleception.kt b/.teamcity/Gradle_Check/configurations/Gradleception.kt index d9ed5b4a485e3..f4fc785c5e7be 100644 --- a/.teamcity/Gradle_Check/configurations/Gradleception.kt +++ b/.teamcity/Gradle_Check/configurations/Gradleception.kt @@ -1,5 +1,6 @@ package configurations +import common.buildToolGradleParameters import common.customGradle import jetbrains.buildServer.configs.kotlin.v2018_2.AbsoluteId import jetbrains.buildServer.configs.kotlin.v2018_2.BuildSteps @@ -18,7 +19,7 @@ class Gradleception(model: CIBuildModel, stage: Stage) : BaseGradleBuildType(mod } val buildScanTagForType = buildScanTag("Gradleception") - val defaultParameters = (gradleParameters() + listOf(buildScanTagForType)).joinToString(separator = " ") + val defaultParameters = (buildToolGradleParameters() + listOf(buildScanTagForType)).joinToString(separator = " ") applyDefaults(model, this, ":install", notQuick = true, extraParameters = "-Pgradle_installPath=dogfood-first $buildScanTagForType", extraSteps = { localGradle { diff --git a/.teamcity/Gradle_Check/configurations/IndividualPerformanceScenarioWorkers.kt b/.teamcity/Gradle_Check/configurations/IndividualPerformanceScenarioWorkers.kt index 42bc613cd8b79..52f806459dfdc 100644 --- a/.teamcity/Gradle_Check/configurations/IndividualPerformanceScenarioWorkers.kt +++ b/.teamcity/Gradle_Check/configurations/IndividualPerformanceScenarioWorkers.kt @@ -1,6 +1,8 @@ package configurations import common.Os +import common.applyDefaultSettings +import common.buildToolGradleParameters import common.gradleWrapper import jetbrains.buildServer.configs.kotlin.v2018_2.AbsoluteId import jetbrains.buildServer.configs.kotlin.v2018_2.BuildStep @@ -12,7 +14,7 @@ class IndividualPerformanceScenarioWorkers(model: CIBuildModel) : BaseGradleBuil id = AbsoluteId(uuid) name = "Individual Performance Scenario Workers - Linux" - applyDefaultSettings(this, timeout = 420) + applyDefaultSettings(timeout = 420) artifactRules = """ subprojects/*/build/test-results-*.zip => results subprojects/*/build/tmp/**/log.txt => failure-logs @@ -42,7 +44,7 @@ class IndividualPerformanceScenarioWorkers(model: CIBuildModel) : BaseGradleBuil name = "GRADLE_RUNNER" tasks = "" gradleParams = ( - gradleParameters(isContinue = false) + buildToolGradleParameters(isContinue = false) + listOf("""clean %templates% fullPerformanceTests --scenarios "%scenario%" --baselines %baselines% --warmups %warmups% --runs %runs% --checks %checks% --channel %channel% -x prepareSamples -Porg.gradle.performance.branchName=%teamcity.build.branch% -Porg.gradle.performance.db.url=%performance.db.url% -Porg.gradle.performance.db.username=%performance.db.username% -Porg.gradle.performance.db.password=%performance.db.password.tcagent% -PtimestampedVersion""", buildScanTag("IndividualPerformanceScenarioWorkers"), "-PtestJavaHome=${individualPerformanceTestJavaHome}") + model.parentBuildCache.gradleParameters(Os.linux) diff --git a/.teamcity/Gradle_Check/configurations/PerformanceTest.kt b/.teamcity/Gradle_Check/configurations/PerformanceTest.kt index 7d2ab2ce07922..783eba46bd749 100644 --- a/.teamcity/Gradle_Check/configurations/PerformanceTest.kt +++ b/.teamcity/Gradle_Check/configurations/PerformanceTest.kt @@ -1,10 +1,13 @@ package configurations import common.Os +import common.applyPerformanceTestSettings +import common.buildToolGradleParameters +import common.checkCleanM2 +import common.distributedPerformanceTestParameters import common.gradleWrapper +import common.performanceTestCommandLine import jetbrains.buildServer.configs.kotlin.v2018_2.AbsoluteId -import jetbrains.buildServer.configs.kotlin.v2018_2.BuildStep -import jetbrains.buildServer.configs.kotlin.v2018_2.buildSteps.script import model.CIBuildModel import model.PerformanceTestType import model.Stage @@ -14,11 +17,7 @@ class PerformanceTest(model: CIBuildModel, type: PerformanceTestType, stage: Sta id = AbsoluteId(uuid) name = "Performance ${type.name.capitalize()} Coordinator - Linux" - applyDefaultSettings(this, timeout = type.timeout) - artifactRules = """ - build/report-*-performance-tests.zip => . - """.trimIndent() - detectHangingBuilds = false + applyPerformanceTestSettings(timeout = type.timeout) if (type == PerformanceTestType.test) { features { @@ -26,19 +25,8 @@ class PerformanceTest(model: CIBuildModel, type: PerformanceTestType, stage: Sta } } - requirements { - // TODO this can be removed once https://github.com/gradle/gradle-private/issues/1861 is closed - doesNotContain("teamcity.agent.name", "ec2") - } - params { param("performance.baselines", type.defaultBaselines) - param("env.GRADLE_OPTS", "-Xmx1536m -XX:MaxPermSize=384m") - param("env.JAVA_HOME", buildJavaHome) - param("env.BUILD_BRANCH", "%teamcity.build.branch%") - param("performance.db.url", "jdbc:h2:ssl://dev61.gradle.org:9092") - param("performance.db.username", "tcagent") - param("TC_USERNAME", "TeamcityRestBot") } steps { @@ -46,25 +34,15 @@ class PerformanceTest(model: CIBuildModel, type: PerformanceTestType, stage: Sta name = "GRADLE_RUNNER" tasks = "" gradleParams = ( - gradleParameters() - + listOf("clean distributed${type.taskId}s -x prepareSamples --baselines %performance.baselines% ${type.extraParameters} -PtimestampedVersion -Porg.gradle.performance.branchName=%teamcity.build.branch% -Porg.gradle.performance.db.url=%performance.db.url% -Porg.gradle.performance.db.username=%performance.db.username% -PteamCityUsername=%TC_USERNAME% -PteamCityPassword=%teamcity.password.restbot% -Porg.gradle.performance.buildTypeId=${IndividualPerformanceScenarioWorkers(model).id} -Porg.gradle.performance.workerTestTaskName=fullPerformanceTest -Porg.gradle.performance.coordinatorBuildId=%teamcity.build.id% -Porg.gradle.performance.db.password=%performance.db.password.tcagent%", - buildScanTag("PerformanceTest"), "-PtestJavaHome=${coordinatorPerformanceTestJavaHome}") - + model.parentBuildCache.gradleParameters(Os.linux) + buildToolGradleParameters(isContinue = false) + + performanceTestCommandLine(task = "distributed${type.taskId}s", baselines = "%performance.baselines%", extraParameters = type.extraParameters) + + distributedPerformanceTestParameters(IndividualPerformanceScenarioWorkers(model).id.toString()) + + listOf(buildScanTag("PerformanceTest")) + + model.parentBuildCache.gradleParameters(Os.linux) ).joinToString(separator = " ") } - script { - name = "CHECK_CLEAN_M2" - executionMode = BuildStep.ExecutionMode.ALWAYS - scriptContent = m2CleanScriptUnixLike - } - if (model.tagBuilds) { - gradleWrapper { - name = "TAG_BUILD" - executionMode = BuildStep.ExecutionMode.ALWAYS - tasks = "tagBuild" - gradleParams = "-PteamCityUsername=%teamcity.username.restbot% -PteamCityPassword=%teamcity.password.restbot% -PteamCityBuildId=%teamcity.build.id% -PgithubToken=%github.ci.oauth.token% --daemon" - } - } + checkCleanM2() + tagBuild(model, true) } applyDefaultDependencies(model, this, true) diff --git a/.teamcity/Gradle_Check/configurations/StagePasses.kt b/.teamcity/Gradle_Check/configurations/StagePasses.kt index 0eb43d49bef45..8a4e80c4e3122 100644 --- a/.teamcity/Gradle_Check/configurations/StagePasses.kt +++ b/.teamcity/Gradle_Check/configurations/StagePasses.kt @@ -1,5 +1,6 @@ package configurations +import common.applyDefaultSettings import common.gradleWrapper import jetbrains.buildServer.configs.kotlin.v2018_2.AbsoluteId import jetbrains.buildServer.configs.kotlin.v2018_2.BuildStep @@ -20,7 +21,7 @@ class StagePasses(model: CIBuildModel, stage: Stage, prevStage: Stage?, contains id = stageTriggerId(model, stage) name = stage.stageName.stageName + " (Trigger)" - applyDefaultSettings(this) + applyDefaultSettings() artifactRules = "build/build-receipt.properties" val triggerExcludes = """ diff --git a/.teamcity/Gradle_Util_Performance/Project.kt b/.teamcity/Gradle_Util_Performance/Project.kt index 4d03105ce5028..1bbd3aee369b8 100644 --- a/.teamcity/Gradle_Util_Performance/Project.kt +++ b/.teamcity/Gradle_Util_Performance/Project.kt @@ -1,7 +1,7 @@ package Gradle_Util_Performance -import Gradle_Util_Performance.buildTypes.* -import jetbrains.buildServer.configs.kotlin.v2018_2.* +import Gradle_Util_Performance.buildTypes.AdHocPerformanceTestCoordinatorLinux +import Gradle_Util_Performance.buildTypes.Gradle_Util_Performance_AdHocPerformanceScenarioLinux import jetbrains.buildServer.configs.kotlin.v2018_2.Project object Project : Project({ @@ -11,5 +11,5 @@ object Project : Project({ name = "Performance" buildType(Gradle_Util_Performance_AdHocPerformanceScenarioLinux) - buildType(Gradle_Util_Performance_PerformanceTestCoordinatorLinux) + buildType(AdHocPerformanceTestCoordinatorLinux) }) diff --git a/.teamcity/Gradle_Util_Performance/buildTypes/AdHocPerformanceTestCoordinatorLinux.kt b/.teamcity/Gradle_Util_Performance/buildTypes/AdHocPerformanceTestCoordinatorLinux.kt new file mode 100644 index 0000000000000..e61c17c1da592 --- /dev/null +++ b/.teamcity/Gradle_Util_Performance/buildTypes/AdHocPerformanceTestCoordinatorLinux.kt @@ -0,0 +1,43 @@ +package Gradle_Util_Performance.buildTypes + +import common.Os +import common.applyPerformanceTestSettings +import common.buildToolGradleParameters +import common.builtInRemoteBuildCacheNode +import common.checkCleanM2 +import common.compileAllDependency +import common.distributedPerformanceTestParameters +import common.gradleWrapper +import common.performanceTestCommandLine +import jetbrains.buildServer.configs.kotlin.v2018_2.BuildType + +object AdHocPerformanceTestCoordinatorLinux : BuildType({ + uuid = "a28ced77-77d1-41fd-bc3b-fe9c9016bf7b" + name = "AdHoc Performance Test Coordinator - Linux" + + applyPerformanceTestSettings(os = Os.linux, timeout = 420) + + maxRunningBuilds = 2 + + params { + param("performance.baselines", "defaults") + } + + steps { + gradleWrapper { + name = "GRADLE_RUNNER" + tasks = "" + gradleParams = ( + buildToolGradleParameters(isContinue = false) + + performanceTestCommandLine(task = "distributedPerformanceTests", baselines = "%performance.baselines%") + + distributedPerformanceTestParameters("Gradle_Check_IndividualPerformanceScenarioWorkersLinux") + + builtInRemoteBuildCacheNode.gradleParameters(Os.linux) + ).joinToString(separator = " ") + } + checkCleanM2(Os.linux) + } + + dependencies { + compileAllDependency() + } +}) diff --git a/.teamcity/Gradle_Util_Performance/buildTypes/Gradle_Util_Performance_AdHocPerformanceScenarioLinux.kt b/.teamcity/Gradle_Util_Performance/buildTypes/Gradle_Util_Performance_AdHocPerformanceScenarioLinux.kt index f85102c9c8f73..ebf747a590f3b 100644 --- a/.teamcity/Gradle_Util_Performance/buildTypes/Gradle_Util_Performance_AdHocPerformanceScenarioLinux.kt +++ b/.teamcity/Gradle_Util_Performance/buildTypes/Gradle_Util_Performance_AdHocPerformanceScenarioLinux.kt @@ -1,7 +1,11 @@ package Gradle_Util_Performance.buildTypes -import jetbrains.buildServer.configs.kotlin.v2018_2.* -import jetbrains.buildServer.configs.kotlin.v2018_2.buildSteps.gradle +import common.gradleWrapper +import jetbrains.buildServer.configs.kotlin.v2018_2.AbsoluteId +import jetbrains.buildServer.configs.kotlin.v2018_2.BuildStep +import jetbrains.buildServer.configs.kotlin.v2018_2.BuildType +import jetbrains.buildServer.configs.kotlin.v2018_2.CheckoutMode +import jetbrains.buildServer.configs.kotlin.v2018_2.ParameterDisplay import jetbrains.buildServer.configs.kotlin.v2018_2.buildSteps.script object Gradle_Util_Performance_AdHocPerformanceScenarioLinux : BuildType({ @@ -40,9 +44,8 @@ object Gradle_Util_Performance_AdHocPerformanceScenarioLinux : BuildType({ } steps { - gradle { + gradleWrapper { name = "GRADLE_RUNNER" - buildFile = "" gradleParams = """clean %templates% performance:performanceAdHocTest --scenarios "%scenario%" --baselines %baselines% --warmups %warmups% --runs %runs% --checks %checks% --channel %channel% %flamegraphs% -x prepareSamples -PmaxParallelForks=%maxParallelForks% %additional.gradle.parameters% -Dorg.gradle.logging.level=LIFECYCLE -s --no-daemon --continue -I ./gradle/init-scripts/build-scan.init.gradle.kts --build-cache "-Dgradle.cache.remote.url=%gradle.cache.remote.url%" "-Dgradle.cache.remote.username=%gradle.cache.remote.username%" "-Dgradle.cache.remote.password=%gradle.cache.remote.password%" -PtestJavaHome=%linux.java8.oracle.64bit% -Porg.gradle.performance.branchName=%teamcity.build.branch%""" } script { diff --git a/.teamcity/Gradle_Util_Performance/buildTypes/Gradle_Util_Performance_PerformanceTestCoordinatorLinux.kt b/.teamcity/Gradle_Util_Performance/buildTypes/Gradle_Util_Performance_PerformanceTestCoordinatorLinux.kt deleted file mode 100644 index 16677655dff69..0000000000000 --- a/.teamcity/Gradle_Util_Performance/buildTypes/Gradle_Util_Performance_PerformanceTestCoordinatorLinux.kt +++ /dev/null @@ -1,103 +0,0 @@ -package Gradle_Util_Performance.buildTypes - -import jetbrains.buildServer.configs.kotlin.v2018_2.* -import jetbrains.buildServer.configs.kotlin.v2018_2.buildFeatures.commitStatusPublisher -import jetbrains.buildServer.configs.kotlin.v2018_2.buildSteps.gradle -import jetbrains.buildServer.configs.kotlin.v2018_2.buildSteps.script - -object Gradle_Util_Performance_PerformanceTestCoordinatorLinux : BuildType({ - uuid = "a28ced77-77d1-41fd-bc3b-fe9c9016bf7b" - name = "AdHoc Performance Test Coordinator - Linux" - - artifactRules = """ - build/report-* => . - buildSrc/build/report-* => . - subprojects/*/build/tmp/test files/** => test-files - build/errorLogs/** => errorLogs - """.trimIndent() - detectHangingBuilds = false - maxRunningBuilds = 2 - - params { - param("performance.baselines", "defaults") - param("performance.db.username", "tcagent") - param("TC_USERNAME", "TeamcityRestBot") - param("env.JAVA_HOME", "%linux.java11.openjdk.64bit%") - param("env.GRADLE_OPTS", "-Xmx1536m -XX:MaxPermSize=384m") - param("performance.db.url", "jdbc:h2:ssl://dev61.gradle.org:9092") - } - - vcs { - root(AbsoluteId("Gradle_Branches_GradlePersonalBranches")) - - checkoutMode = CheckoutMode.ON_AGENT - buildDefaultBranch = false - } - - steps { - gradle { - name = "GRADLE_RUNNER" - tasks = "" - buildFile = "" - gradleParams = "clean distributedPerformanceTests -x prepareSamples --baselines %performance.baselines% -PtimestampedVersion -Porg.gradle.performance.branchName=%teamcity.build.branch% -Porg.gradle.performance.db.url=%performance.db.url% -Porg.gradle.performance.db.username=%performance.db.username% -PteamCityUsername=%TC_USERNAME% -PteamCityPassword=%teamcity.password.restbot% -Porg.gradle.performance.buildTypeId=Gradle_Check_IndividualPerformanceScenarioWorkersLinux -Porg.gradle.performance.workerTestTaskName=fullPerformanceTest -Porg.gradle.performance.coordinatorBuildId=%teamcity.build.id% -Porg.gradle.performance.db.password=%performance.db.password.tcagent% -PmaxParallelForks=%maxParallelForks% -s --no-daemon --continue -I ./gradle/init-scripts/build-scan.init.gradle.kts --build-cache -Dgradle.cache.remote.url=%gradle.cache.remote.url% -Dgradle.cache.remote.username=%gradle.cache.remote.username% -Dgradle.cache.remote.password=%gradle.cache.remote.password% -PtestJavaHome=%linux.java8.oracle.64bit%" - param("ui.gradleRunner.gradle.build.file", "") - } - script { - name = "CHECK_CLEAN_M2" - executionMode = BuildStep.ExecutionMode.ALWAYS - scriptContent = """ - REPO=/home/%env.USER%/.m2/repository - if [ -e ${'$'}REPO ] ; then - tree ${'$'}REPO - rm -rf ${'$'}REPO - echo "${'$'}REPO was polluted during the build" - exit 1 - else - echo "${'$'}REPO does not exist" - fi - """.trimIndent() - } - gradle { - name = "TAG_BUILD" - executionMode = BuildStep.ExecutionMode.ALWAYS - tasks = "tagBuild" - buildFile = "" - gradleParams = "-PteamCityUsername=%teamcity.username.restbot% -PteamCityPassword=%teamcity.password.restbot% -PteamCityBuildId=%teamcity.build.id% -PgithubToken=%github.ci.oauth.token%" - param("ui.gradleRunner.gradle.build.file", "") - } - } - - failureConditions { - executionTimeoutMin = 420 - } - - features { - commitStatusPublisher { - vcsRootExtId = "Gradle_Branches_GradlePersonalBranches" - publisher = github { - githubUrl = "https://api.github.com" - authType = personalToken { - token = "credentialsJSON:5306bfc7-041e-46e8-8d61-1d49424e7b04" - } - } - } - } - - dependencies { - dependency(AbsoluteId("Gradle_Check_CompileAll")) { - snapshot { - onDependencyFailure = FailureAction.CANCEL - onDependencyCancel = FailureAction.CANCEL - } - - artifacts { - cleanDestination = true - artifactRules = "build-receipt.properties => incoming-distributions" - } - } - } - - requirements { - contains("teamcity.agent.jvm.os.name", "Linux") - } -}) diff --git a/.teamcity/common/extensions.kt b/.teamcity/common/extensions.kt index 1086e30403ec2..e853b3e210569 100644 --- a/.teamcity/common/extensions.kt +++ b/.teamcity/common/extensions.kt @@ -16,9 +16,18 @@ package common +import configurations.m2CleanScriptUnixLike +import configurations.m2CleanScriptWindows +import jetbrains.buildServer.configs.kotlin.v2018_2.AbsoluteId +import jetbrains.buildServer.configs.kotlin.v2018_2.BuildStep import jetbrains.buildServer.configs.kotlin.v2018_2.BuildSteps +import jetbrains.buildServer.configs.kotlin.v2018_2.BuildType +import jetbrains.buildServer.configs.kotlin.v2018_2.CheckoutMode +import jetbrains.buildServer.configs.kotlin.v2018_2.Dependencies +import jetbrains.buildServer.configs.kotlin.v2018_2.FailureAction import jetbrains.buildServer.configs.kotlin.v2018_2.Requirements import jetbrains.buildServer.configs.kotlin.v2018_2.buildSteps.GradleBuildStep +import jetbrains.buildServer.configs.kotlin.v2018_2.buildSteps.script fun BuildSteps.customGradle(init: GradleBuildStep.() -> Unit, custom: GradleBuildStep.() -> Unit): GradleBuildStep = GradleBuildStep(init) @@ -42,3 +51,69 @@ fun BuildSteps.gradleWrapper(init: GradleBuildStep.() -> Unit): GradleBuildStep fun Requirements.requiresOs(os: Os) { contains("teamcity.agent.jvm.os.name", os.agentRequirement) } + +fun BuildType.applyDefaultSettings(os: Os = Os.linux, timeout: Int = 30, vcsRoot: String = "Gradle_Branches_GradlePersonalBranches") { + artifactRules = """ + build/report-* => . + buildSrc/build/report-* => . + subprojects/*/build/tmp/test files/** => test-files + build/errorLogs/** => errorLogs + build/reports/incubation/** => incubation-reports + """.trimIndent() + + vcs { + root(AbsoluteId(vcsRoot)) + checkoutMode = CheckoutMode.ON_AGENT + buildDefaultBranch = !vcsRoot.contains("Branches") + } + + requirements { + requiresOs(os) + } + + failureConditions { + executionTimeoutMin = timeout + } + + if (os == Os.linux || os == Os.macos) { + params { + param("env.LC_ALL", "en_US.UTF-8") + } + } +} + +fun BuildSteps.checkCleanM2(os: Os = Os.linux) { + script { + name = "CHECK_CLEAN_M2" + executionMode = BuildStep.ExecutionMode.ALWAYS + scriptContent = if (os == Os.windows) m2CleanScriptWindows else m2CleanScriptUnixLike + } +} + +fun buildToolGradleParameters(daemon: Boolean = true, isContinue: Boolean = true): List = + listOf( + "-PmaxParallelForks=%maxParallelForks%", + "-s", + if (daemon) "--daemon" else "--no-daemon", + if (isContinue) "--continue" else "", + """-I "%teamcity.build.checkoutDir%/gradle/init-scripts/build-scan.init.gradle.kts"""", + "-Dorg.gradle.internal.tasks.createops", + "-Dorg.gradle.internal.plugins.portal.url.override=%gradle.plugins.portal.url%" + ) + + +fun Dependencies.compileAllDependency(compileAllId: String = "Gradle_Check_CompileAll") { + // Compile All has to succeed before anything else is started + dependency(AbsoluteId(compileAllId)) { + snapshot { + onDependencyFailure = FailureAction.CANCEL + onDependencyCancel = FailureAction.CANCEL + } + } + // Get the build receipt from sanity check to reuse the timestamp + artifacts(AbsoluteId(compileAllId)) { + id = "ARTIFACT_DEPENDENCY_$compileAllId" + cleanDestination = true + artifactRules = "build-receipt.properties => incoming-distributions" + } +} diff --git a/.teamcity/common/performance-test-extensions.kt b/.teamcity/common/performance-test-extensions.kt new file mode 100644 index 0000000000000..8646f4c364385 --- /dev/null +++ b/.teamcity/common/performance-test-extensions.kt @@ -0,0 +1,55 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package common + +import configurations.buildJavaHome +import configurations.coordinatorPerformanceTestJavaHome +import jetbrains.buildServer.configs.kotlin.v2018_2.BuildType + +fun BuildType.applyPerformanceTestSettings(os: Os = Os.linux, timeout: Int = 30) { + applyDefaultSettings(os = os, timeout = timeout) + artifactRules = """ + build/report-*-performance-tests.zip => . + """.trimIndent() + detectHangingBuilds = false + requirements { + // TODO this can be removed once https://github.com/gradle/gradle-private/issues/1861 is closed + doesNotContain("teamcity.agent.name", "ec2") + } + params { + param("env.GRADLE_OPTS", "-Xmx1536m -XX:MaxPermSize=384m") + param("env.JAVA_HOME", buildJavaHome) + param("env.BUILD_BRANCH", "%teamcity.build.branch%") + param("performance.db.url", "jdbc:h2:ssl://dev61.gradle.org:9092") + param("performance.db.username", "tcagent") + param("TC_USERNAME", "TeamcityRestBot") + } +} + +fun performanceTestCommandLine(task: String, baselines: String, extraParameters: String = "", testJavaHome: String = coordinatorPerformanceTestJavaHome) = listOf( + "clean $task --baselines $baselines $extraParameters", + "-x prepareSamples", + "-Porg.gradle.performance.branchName=%teamcity.build.branch%", + "-Porg.gradle.performance.db.url=%performance.db.url% -Porg.gradle.performance.db.username=%performance.db.username% -Porg.gradle.performance.db.password=%performance.db.password.tcagent%", + "-PteamCityUsername=%TC_USERNAME% -PteamCityPassword=%teamcity.password.restbot%", + "-PtestJavaHome=$testJavaHome" +) + +fun distributedPerformanceTestParameters(workerId: String = "Gradle_Check_IndividualPerformanceScenarioWorkersLinux") = listOf( + "-Porg.gradle.performance.buildTypeId=${workerId} -Porg.gradle.performance.workerTestTaskName=fullPerformanceTest -Porg.gradle.performance.coordinatorBuildId=%teamcity.build.id%" +) + From 326c69bca4cc4d4728c6d40eab24ba90ad9c5ce1 Mon Sep 17 00:00:00 2001 From: Stefan Wolf Date: Tue, 19 Mar 2019 23:16:56 +0100 Subject: [PATCH 636/853] Use common methods in AdHoc performance job --- .../IndividualPerformanceScenarioWorkers.kt | 9 +-- .teamcity/Gradle_Util_Performance/Project.kt | 4 +- .../AdHocPerformanceScenarioLinux.kt | 53 +++++++++++++ .../AdHocPerformanceTestCoordinatorLinux.kt | 1 + ...rformance_AdHocPerformanceScenarioLinux.kt | 74 ------------------- .../common/performance-test-extensions.kt | 1 - 6 files changed, 58 insertions(+), 84 deletions(-) create mode 100644 .teamcity/Gradle_Util_Performance/buildTypes/AdHocPerformanceScenarioLinux.kt delete mode 100644 .teamcity/Gradle_Util_Performance/buildTypes/Gradle_Util_Performance_AdHocPerformanceScenarioLinux.kt diff --git a/.teamcity/Gradle_Check/configurations/IndividualPerformanceScenarioWorkers.kt b/.teamcity/Gradle_Check/configurations/IndividualPerformanceScenarioWorkers.kt index 52f806459dfdc..b56a110890a13 100644 --- a/.teamcity/Gradle_Check/configurations/IndividualPerformanceScenarioWorkers.kt +++ b/.teamcity/Gradle_Check/configurations/IndividualPerformanceScenarioWorkers.kt @@ -3,10 +3,9 @@ package configurations import common.Os import common.applyDefaultSettings import common.buildToolGradleParameters +import common.checkCleanM2 import common.gradleWrapper import jetbrains.buildServer.configs.kotlin.v2018_2.AbsoluteId -import jetbrains.buildServer.configs.kotlin.v2018_2.BuildStep -import jetbrains.buildServer.configs.kotlin.v2018_2.buildSteps.script import model.CIBuildModel class IndividualPerformanceScenarioWorkers(model: CIBuildModel) : BaseGradleBuildType(model, init = { @@ -50,11 +49,7 @@ class IndividualPerformanceScenarioWorkers(model: CIBuildModel) : BaseGradleBuil + model.parentBuildCache.gradleParameters(Os.linux) ).joinToString(separator = " ") } - script { - name = "CHECK_CLEAN_M2" - executionMode = BuildStep.ExecutionMode.ALWAYS - scriptContent = m2CleanScriptUnixLike - } + checkCleanM2() } applyDefaultDependencies(model, this) diff --git a/.teamcity/Gradle_Util_Performance/Project.kt b/.teamcity/Gradle_Util_Performance/Project.kt index 1bbd3aee369b8..940095e88c6b4 100644 --- a/.teamcity/Gradle_Util_Performance/Project.kt +++ b/.teamcity/Gradle_Util_Performance/Project.kt @@ -1,7 +1,7 @@ package Gradle_Util_Performance +import Gradle_Util_Performance.buildTypes.AdHocPerformanceScenarioLinux import Gradle_Util_Performance.buildTypes.AdHocPerformanceTestCoordinatorLinux -import Gradle_Util_Performance.buildTypes.Gradle_Util_Performance_AdHocPerformanceScenarioLinux import jetbrains.buildServer.configs.kotlin.v2018_2.Project object Project : Project({ @@ -10,6 +10,6 @@ object Project : Project({ parentId("Gradle_Util") name = "Performance" - buildType(Gradle_Util_Performance_AdHocPerformanceScenarioLinux) + buildType(AdHocPerformanceScenarioLinux) buildType(AdHocPerformanceTestCoordinatorLinux) }) diff --git a/.teamcity/Gradle_Util_Performance/buildTypes/AdHocPerformanceScenarioLinux.kt b/.teamcity/Gradle_Util_Performance/buildTypes/AdHocPerformanceScenarioLinux.kt new file mode 100644 index 0000000000000..20a7fdf18082f --- /dev/null +++ b/.teamcity/Gradle_Util_Performance/buildTypes/AdHocPerformanceScenarioLinux.kt @@ -0,0 +1,53 @@ +package Gradle_Util_Performance.buildTypes + +import common.Os +import common.applyPerformanceTestSettings +import common.buildToolGradleParameters +import common.builtInRemoteBuildCacheNode +import common.checkCleanM2 +import common.gradleWrapper +import common.performanceTestCommandLine +import jetbrains.buildServer.configs.kotlin.v2018_2.BuildType +import jetbrains.buildServer.configs.kotlin.v2018_2.ParameterDisplay + +object AdHocPerformanceScenarioLinux : BuildType({ + uuid = "a3183d81-e07d-475c-8ef6-04ed60bf4053" + name = "AdHoc Performance Scenario - Linux" + id("Gradle_Util_Performance_AdHocPerformanceScenarioLinux") + + applyPerformanceTestSettings(timeout = 420) + artifactRules = """ + subprojects/*/build/test-results-*.zip => results + subprojects/*/build/tmp/**/log.txt => failure-logs + """.trimIndent() + + params { + text("baselines", "defaults", display = ParameterDisplay.PROMPT, allowEmpty = false) + text("templates", "", display = ParameterDisplay.PROMPT, allowEmpty = false) + param("channel", "adhoc") + param("checks", "all") + text("runs", "10", display = ParameterDisplay.PROMPT, allowEmpty = false) + text("warmups", "3", display = ParameterDisplay.PROMPT, allowEmpty = false) + text("scenario", "", display = ParameterDisplay.PROMPT, allowEmpty = false) + param("flamegraphs", "--flamegraphs true") + param("env.FG_HOME_DIR", "/opt/FlameGraph") + param("additional.gradle.parameters", "") + + param("env.ANDROID_HOME", "/opt/android/sdk") + param("env.PATH", "%env.PATH%:/opt/swift/latest/usr/bin") + param("env.HP_HOME_DIR", "/opt/honest-profiler") + } + + steps { + gradleWrapper { + name = "GRADLE_RUNNER" + gradleParams = ( + performanceTestCommandLine("%templates% performance:performanceAdHocTest", "%baselines%", + """--scenarios "%scenario%" --warmups %warmups% --runs %runs% --checks %checks% --channel %channel% %flamegraphs% %additional.gradle.parameters%""") + + buildToolGradleParameters() + + builtInRemoteBuildCacheNode.gradleParameters(Os.linux) + ).joinToString(separator = " ") + } + checkCleanM2() + } +}) diff --git a/.teamcity/Gradle_Util_Performance/buildTypes/AdHocPerformanceTestCoordinatorLinux.kt b/.teamcity/Gradle_Util_Performance/buildTypes/AdHocPerformanceTestCoordinatorLinux.kt index e61c17c1da592..d5d78e47c647b 100644 --- a/.teamcity/Gradle_Util_Performance/buildTypes/AdHocPerformanceTestCoordinatorLinux.kt +++ b/.teamcity/Gradle_Util_Performance/buildTypes/AdHocPerformanceTestCoordinatorLinux.kt @@ -13,6 +13,7 @@ import jetbrains.buildServer.configs.kotlin.v2018_2.BuildType object AdHocPerformanceTestCoordinatorLinux : BuildType({ uuid = "a28ced77-77d1-41fd-bc3b-fe9c9016bf7b" + id("Gradle_Util_Performance_PerformanceTestCoordinatorLinux") name = "AdHoc Performance Test Coordinator - Linux" applyPerformanceTestSettings(os = Os.linux, timeout = 420) diff --git a/.teamcity/Gradle_Util_Performance/buildTypes/Gradle_Util_Performance_AdHocPerformanceScenarioLinux.kt b/.teamcity/Gradle_Util_Performance/buildTypes/Gradle_Util_Performance_AdHocPerformanceScenarioLinux.kt deleted file mode 100644 index ebf747a590f3b..0000000000000 --- a/.teamcity/Gradle_Util_Performance/buildTypes/Gradle_Util_Performance_AdHocPerformanceScenarioLinux.kt +++ /dev/null @@ -1,74 +0,0 @@ -package Gradle_Util_Performance.buildTypes - -import common.gradleWrapper -import jetbrains.buildServer.configs.kotlin.v2018_2.AbsoluteId -import jetbrains.buildServer.configs.kotlin.v2018_2.BuildStep -import jetbrains.buildServer.configs.kotlin.v2018_2.BuildType -import jetbrains.buildServer.configs.kotlin.v2018_2.CheckoutMode -import jetbrains.buildServer.configs.kotlin.v2018_2.ParameterDisplay -import jetbrains.buildServer.configs.kotlin.v2018_2.buildSteps.script - -object Gradle_Util_Performance_AdHocPerformanceScenarioLinux : BuildType({ - uuid = "a3183d81-e07d-475c-8ef6-04ed60bf4053" - name = "AdHoc Performance Scenario - Linux" - - artifactRules = """ - subprojects/*/build/test-results-*.zip => results - subprojects/*/build/tmp/**/log.txt => failure-logs - """.trimIndent() - - params { - text("baselines", "defaults", display = ParameterDisplay.PROMPT, allowEmpty = false) - text("templates", "", display = ParameterDisplay.PROMPT, allowEmpty = false) - param("channel", "adhoc") - param("env.ANDROID_HOME", "/opt/android/sdk") - param("env.PATH", "%env.PATH%:/opt/swift/latest/usr/bin") - param("env.JAVA_HOME", "%linux.java11.openjdk.64bit%") - param("flamegraphs", "--flamegraphs true") - param("checks", "all") - param("env.FG_HOME_DIR", "/opt/FlameGraph") - param("additional.gradle.parameters", "") - param("env.HP_HOME_DIR", "/opt/honest-profiler") - text("scenario", "", display = ParameterDisplay.PROMPT, allowEmpty = false) - text("warmups", "3", display = ParameterDisplay.PROMPT, allowEmpty = false) - param("performance.db.username", "tcagent") - param("env.GRADLE_OPTS", "-Xmx1536m -XX:MaxPermSize=384m") - text("runs", "10", display = ParameterDisplay.PROMPT, allowEmpty = false) - param("performance.db.url", "jdbc:h2:ssl://dev61.gradle.org:9092") - } - - vcs { - root(AbsoluteId("Gradle_Branches_GradlePersonalBranches")) - - checkoutMode = CheckoutMode.ON_AGENT - } - - steps { - gradleWrapper { - name = "GRADLE_RUNNER" - gradleParams = """clean %templates% performance:performanceAdHocTest --scenarios "%scenario%" --baselines %baselines% --warmups %warmups% --runs %runs% --checks %checks% --channel %channel% %flamegraphs% -x prepareSamples -PmaxParallelForks=%maxParallelForks% %additional.gradle.parameters% -Dorg.gradle.logging.level=LIFECYCLE -s --no-daemon --continue -I ./gradle/init-scripts/build-scan.init.gradle.kts --build-cache "-Dgradle.cache.remote.url=%gradle.cache.remote.url%" "-Dgradle.cache.remote.username=%gradle.cache.remote.username%" "-Dgradle.cache.remote.password=%gradle.cache.remote.password%" -PtestJavaHome=%linux.java8.oracle.64bit% -Porg.gradle.performance.branchName=%teamcity.build.branch%""" - } - script { - name = "CHECK_CLEAN_M2" - executionMode = BuildStep.ExecutionMode.ALWAYS - scriptContent = """ - REPO=/home/%env.USER%/.m2/repository - if [ -e ${'$'}REPO ] ; then - rm -rf ${'$'}REPO - echo "${'$'}REPO was polluted during the build" - exit 1 - else - echo "${'$'}REPO does not exist" - fi - """.trimIndent() - } - } - - failureConditions { - executionTimeoutMin = 420 - } - - requirements { - contains("teamcity.agent.jvm.os.name", "Linux") - } -}) diff --git a/.teamcity/common/performance-test-extensions.kt b/.teamcity/common/performance-test-extensions.kt index 8646f4c364385..ec2e04cc730ea 100644 --- a/.teamcity/common/performance-test-extensions.kt +++ b/.teamcity/common/performance-test-extensions.kt @@ -27,7 +27,6 @@ fun BuildType.applyPerformanceTestSettings(os: Os = Os.linux, timeout: Int = 30) """.trimIndent() detectHangingBuilds = false requirements { - // TODO this can be removed once https://github.com/gradle/gradle-private/issues/1861 is closed doesNotContain("teamcity.agent.name", "ec2") } params { From 1de42fae0a7e9ae59d15c43dba86a362eadb1a94 Mon Sep 17 00:00:00 2001 From: Stefan Wolf Date: Wed, 20 Mar 2019 08:57:20 +0100 Subject: [PATCH 637/853] Move more common functions to extensions.kt --- .../GradleBuildConfigurationDefaults.kt | 73 ++++++++----------- .../Gradle_Util_AdHocFunctionalTestLinux.kt | 49 +++---------- .../Gradle_Util_AdHocFunctionalTestWindows.kt | 45 +++--------- .teamcity/common/extensions.kt | 9 +++ 4 files changed, 65 insertions(+), 111 deletions(-) diff --git a/.teamcity/Gradle_Check/configurations/GradleBuildConfigurationDefaults.kt b/.teamcity/Gradle_Check/configurations/GradleBuildConfigurationDefaults.kt index 6b3dd19026f01..eec9af2ee9447 100644 --- a/.teamcity/Gradle_Check/configurations/GradleBuildConfigurationDefaults.kt +++ b/.teamcity/Gradle_Check/configurations/GradleBuildConfigurationDefaults.kt @@ -3,9 +3,11 @@ package configurations import common.Os import common.applyDefaultSettings import common.buildToolGradleParameters +import common.buildToolParametersString import common.checkCleanM2 import common.compileAllDependency import common.gradleWrapper +import common.verifyTestFilesCleanup import jetbrains.buildServer.configs.kotlin.v2018_2.AbsoluteId import jetbrains.buildServer.configs.kotlin.v2018_2.BuildFeatures import jetbrains.buildServer.configs.kotlin.v2018_2.BuildStep @@ -26,8 +28,6 @@ fun shouldBeSkipped(subProject: GradleSubproject, testConfig: TestCoverage): Boo return testConfig.os.ignoredSubprojects.contains(subProject.name) } -fun gradleParameterString(daemon: Boolean = true) = buildToolGradleParameters(daemon).joinToString(separator = " ") - val m2CleanScriptUnixLike = """ REPO=%teamcity.agent.jvm.user.home%/.m2/repository if [ -e ${'$'}REPO ] ; then @@ -69,17 +69,6 @@ fun ProjectFeatures.buildReportTab(title: String, startPage: String) { } } -private -fun BaseGradleBuildType.verifyTestFilesCleanupStep(daemon: Boolean = true) { - steps { - gradleWrapper { - name = "VERIFY_TEST_FILES_CLEANUP" - tasks = "verifyTestFilesCleanup" - gradleParams = gradleParameterString(daemon) - } - } -} - private fun BuildSteps.tagBuild(tagBuild: Boolean = true, daemon: Boolean = true) { if (tagBuild) { @@ -87,7 +76,7 @@ fun BuildSteps.tagBuild(tagBuild: Boolean = true, daemon: Boolean = true) { name = "TAG_BUILD" executionMode = BuildStep.ExecutionMode.ALWAYS tasks = "tagBuild" - gradleParams = "${gradleParameterString(daemon)} -PteamCityUsername=%teamcity.username.restbot% -PteamCityPassword=%teamcity.password.restbot% -PteamCityBuildId=%teamcity.build.id% -PgithubToken=%github.ci.oauth.token%" + gradleParams = "${buildToolParametersString(daemon)} -PteamCityUsername=%teamcity.username.restbot% -PteamCityPassword=%teamcity.password.restbot% -PteamCityBuildId=%teamcity.build.id% -PgithubToken=%github.ci.oauth.token%" } } } @@ -105,14 +94,14 @@ fun BaseGradleBuildType.gradleRunnerStep(model: CIBuildModel, gradleTasks: Strin name = "GRADLE_RUNNER" tasks = "clean $gradleTasks" gradleParams = ( - listOf(gradleParameterString(daemon)) + - this@gradleRunnerStep.buildCache.gradleParameters(os) + - listOf(extraParameters) + - "-PteamCityUsername=%teamcity.username.restbot%" + - "-PteamCityPassword=%teamcity.password.restbot%" + - "-PteamCityBuildId=%teamcity.build.id%" + - buildScanTags.map { configurations.buildScanTag(it) } - ).joinToString(separator = " ") + buildToolGradleParameters(daemon) + + this@gradleRunnerStep.buildCache.gradleParameters(os) + + listOf(extraParameters) + + "-PteamCityUsername=%teamcity.username.restbot%" + + "-PteamCityPassword=%teamcity.password.restbot%" + + "-PteamCityBuildId=%teamcity.build.id%" + + buildScanTags.map { configurations.buildScanTag(it) } + ).joinToString(separator = " ") } } } @@ -127,16 +116,16 @@ fun BaseGradleBuildType.gradleRerunnerStep(model: CIBuildModel, gradleTasks: Str tasks = "$gradleTasks tagBuild" executionMode = BuildStep.ExecutionMode.RUN_ON_FAILURE gradleParams = ( - listOf(gradleParameterString(daemon)) + - this@gradleRerunnerStep.buildCache.gradleParameters(os) + - listOf(extraParameters) + - "-PteamCityUsername=%teamcity.username.restbot%" + - "-PteamCityPassword=%teamcity.password.restbot%" + - "-PteamCityBuildId=%teamcity.build.id%" + - buildScanTags.map { configurations.buildScanTag(it) } + - "-PonlyPreviousFailedTestClasses=true" + - "-PgithubToken=%github.ci.oauth.token%" - ).joinToString(separator = " ") + buildToolGradleParameters(daemon) + + this@gradleRerunnerStep.buildCache.gradleParameters(os) + + listOf(extraParameters) + + "-PteamCityUsername=%teamcity.username.restbot%" + + "-PteamCityPassword=%teamcity.password.restbot%" + + "-PteamCityBuildId=%teamcity.build.id%" + + buildScanTags.map { configurations.buildScanTag(it) } + + "-PonlyPreviousFailedTestClasses=true" + + "-PgithubToken=%github.ci.oauth.token%" + ).joinToString(separator = " ") } } } @@ -149,7 +138,7 @@ fun BaseGradleBuildType.killProcessStepIfNecessary(stepName: String, os: Os = Os name = stepName executionMode = BuildStep.ExecutionMode.ALWAYS tasks = "killExistingProcessesStartedByGradle" - gradleParams = gradleParameterString(daemon) + gradleParams = buildToolParametersString(daemon) } } } @@ -160,10 +149,11 @@ fun applyDefaults(model: CIBuildModel, buildType: BaseGradleBuildType, gradleTas buildType.gradleRunnerStep(model, gradleTasks, os, extraParameters, daemon) - buildType.steps.extraSteps() - - buildType.steps.checkCleanM2(os) - buildType.verifyTestFilesCleanupStep(daemon) + buildType.steps { + extraSteps() + checkCleanM2(os) + verifyTestFilesCleanup(daemon) + } applyDefaultDependencies(model, buildType, notQuick) } @@ -176,10 +166,11 @@ fun applyTestDefaults(model: CIBuildModel, buildType: BaseGradleBuildType, gradl buildType.gradleRerunnerStep(model, gradleTasks, os, extraParameters, daemon) buildType.killProcessStepIfNecessary("KILL_PROCESSES_STARTED_BY_GRADLE_RERUN", os) - buildType.steps.extraSteps() - - buildType.steps.checkCleanM2(os) - buildType.verifyTestFilesCleanupStep(daemon) + buildType.steps { + extraSteps() + checkCleanM2(os) + verifyTestFilesCleanup(daemon) + } applyDefaultDependencies(model, buildType, notQuick) } diff --git a/.teamcity/Gradle_Util/buildTypes/Gradle_Util_AdHocFunctionalTestLinux.kt b/.teamcity/Gradle_Util/buildTypes/Gradle_Util_AdHocFunctionalTestLinux.kt index 31625640f2282..0cc845bbc2703 100644 --- a/.teamcity/Gradle_Util/buildTypes/Gradle_Util_AdHocFunctionalTestLinux.kt +++ b/.teamcity/Gradle_Util/buildTypes/Gradle_Util_AdHocFunctionalTestLinux.kt @@ -1,8 +1,14 @@ package Gradle_Util.buildTypes -import jetbrains.buildServer.configs.kotlin.v2018_2.* -import jetbrains.buildServer.configs.kotlin.v2018_2.buildSteps.gradle -import jetbrains.buildServer.configs.kotlin.v2018_2.buildSteps.script +import common.Os +import common.checkCleanM2 +import common.gradleWrapper +import common.verifyTestFilesCleanup +import jetbrains.buildServer.configs.kotlin.v2018_2.AbsoluteId +import jetbrains.buildServer.configs.kotlin.v2018_2.BuildType +import jetbrains.buildServer.configs.kotlin.v2018_2.CheckoutMode +import jetbrains.buildServer.configs.kotlin.v2018_2.FailureAction +import jetbrains.buildServer.configs.kotlin.v2018_2.ParameterDisplay object Gradle_Util_AdHocFunctionalTestLinux : BuildType({ uuid = "5d59fee9-be42-4f6d-9e0b-fe103e0d2765" @@ -32,44 +38,13 @@ object Gradle_Util_AdHocFunctionalTestLinux : BuildType({ } steps { - gradle { + gradleWrapper { name = "GRADLE_RUNNER" tasks = "clean %subproject%:%buildType%" - buildFile = "" gradleParams = "-PmaxParallelForks=%maxParallelForks% -s --no-daemon --continue -I ./gradle/init-scripts/build-scan.init.gradle.kts" - param("org.jfrog.artifactory.selectedDeployableServer.defaultModuleVersionConfiguration", "GLOBAL") - param("ui.gradleRunner.gradle.build.file", "") - } - script { - name = "CHECK_CLEAN_M2" - executionMode = BuildStep.ExecutionMode.ALWAYS - scriptContent = """ - REPO=/home/%env.USER%/.m2/repository - if [ -e ${'$'}REPO ] ; then - tree ${'$'}REPO - rm -rf ${'$'}REPO - echo "${'$'}REPO was polluted during the build" - exit 1 - else - echo "${'$'}REPO does not exist" - fi - """.trimIndent() - } - gradle { - name = "VERIFY_TEST_FILES_CLEANUP" - tasks = "verifyTestFilesCleanup" - buildFile = "" - gradleParams = "-PmaxParallelForks=%maxParallelForks% -s --no-daemon --continue -I ./gradle/init-scripts/build-scan.init.gradle.kts" - param("ui.gradleRunner.gradle.build.file", "") - } - gradle { - name = "TAG_BUILD" - executionMode = BuildStep.ExecutionMode.ALWAYS - tasks = "tagBuild" - buildFile = "" - gradleParams = "-PteamCityUsername=%teamcity.username.restbot% -PteamCityPassword=%teamcity.password.restbot% -PteamCityBuildId=%teamcity.build.id% -PgithubToken=%github.ci.oauth.token%" - param("ui.gradleRunner.gradle.build.file", "") } + checkCleanM2(Os.linux) + verifyTestFilesCleanup() } failureConditions { diff --git a/.teamcity/Gradle_Util/buildTypes/Gradle_Util_AdHocFunctionalTestWindows.kt b/.teamcity/Gradle_Util/buildTypes/Gradle_Util_AdHocFunctionalTestWindows.kt index d2f4cd2e4d9d1..e4d7dbee84e60 100644 --- a/.teamcity/Gradle_Util/buildTypes/Gradle_Util_AdHocFunctionalTestWindows.kt +++ b/.teamcity/Gradle_Util/buildTypes/Gradle_Util_AdHocFunctionalTestWindows.kt @@ -1,8 +1,14 @@ package Gradle_Util.buildTypes -import jetbrains.buildServer.configs.kotlin.v2018_2.* -import jetbrains.buildServer.configs.kotlin.v2018_2.buildSteps.gradle -import jetbrains.buildServer.configs.kotlin.v2018_2.buildSteps.script +import common.Os +import common.checkCleanM2 +import common.gradleWrapper +import common.verifyTestFilesCleanup +import jetbrains.buildServer.configs.kotlin.v2018_2.AbsoluteId +import jetbrains.buildServer.configs.kotlin.v2018_2.BuildType +import jetbrains.buildServer.configs.kotlin.v2018_2.CheckoutMode +import jetbrains.buildServer.configs.kotlin.v2018_2.FailureAction +import jetbrains.buildServer.configs.kotlin.v2018_2.ParameterDisplay object Gradle_Util_AdHocFunctionalTestWindows : BuildType({ uuid = "944be583-446e-4ecc-b2f2-15f04dd0cfe9" @@ -32,40 +38,13 @@ object Gradle_Util_AdHocFunctionalTestWindows : BuildType({ } steps { - gradle { + gradleWrapper { name = "GRADLE_RUNNER" tasks = "clean %subproject%:%buildType%" - buildFile = "" gradleParams = """-PmaxParallelForks=%maxParallelForks% -s --no-daemon --continue -I ./gradle/init-scripts/build-scan.init.gradle.kts "-PtestJavaHome=%windows.java8.oracle.64bit%"""" - param("org.jfrog.artifactory.selectedDeployableServer.defaultModuleVersionConfiguration", "GLOBAL") - param("ui.gradleRunner.gradle.build.file", "") - } - script { - name = "CHECK_CLEAN_M2" - executionMode = BuildStep.ExecutionMode.ALWAYS - scriptContent = """ - IF exist %teamcity.agent.jvm.user.home%\.m2\repository ( - TREE %teamcity.agent.jvm.user.home%\.m2\repository - RMDIR /S /Q %teamcity.agent.jvm.user.home%\.m2\repository - EXIT 1 - ) - """.trimIndent() - } - gradle { - name = "VERIFY_TEST_FILES_CLEANUP" - tasks = "verifyTestFilesCleanup" - buildFile = "" - gradleParams = "-PmaxParallelForks=%maxParallelForks% -s --no-daemon --continue -I ./gradle/init-scripts/build-scan.init.gradle.kts" - param("ui.gradleRunner.gradle.build.file", "") - } - gradle { - name = "TAG_BUILD" - executionMode = BuildStep.ExecutionMode.ALWAYS - tasks = "tagBuild" - buildFile = "" - gradleParams = "-PteamCityUsername=%teamcity.username.restbot% -PteamCityPassword=%teamcity.password.restbot% -PteamCityBuildId=%teamcity.build.id% -PgithubToken=%github.ci.oauth.token%" - param("ui.gradleRunner.gradle.build.file", "") } + checkCleanM2(Os.windows) + verifyTestFilesCleanup() } failureConditions { diff --git a/.teamcity/common/extensions.kt b/.teamcity/common/extensions.kt index e853b3e210569..7fd339f0f6b12 100644 --- a/.teamcity/common/extensions.kt +++ b/.teamcity/common/extensions.kt @@ -101,6 +101,7 @@ fun buildToolGradleParameters(daemon: Boolean = true, isContinue: Boolean = true "-Dorg.gradle.internal.plugins.portal.url.override=%gradle.plugins.portal.url%" ) +fun buildToolParametersString(daemon: Boolean = true) = buildToolGradleParameters(daemon).joinToString(separator = " ") fun Dependencies.compileAllDependency(compileAllId: String = "Gradle_Check_CompileAll") { // Compile All has to succeed before anything else is started @@ -117,3 +118,11 @@ fun Dependencies.compileAllDependency(compileAllId: String = "Gradle_Check_Compi artifactRules = "build-receipt.properties => incoming-distributions" } } + +fun BuildSteps.verifyTestFilesCleanup(daemon: Boolean = true) { + gradleWrapper { + name = "VERIFY_TEST_FILES_CLEANUP" + tasks = "verifyTestFilesCleanup" + gradleParams = buildToolParametersString(daemon) + } +} From 1e755d8c0f688d24d5f3f05ec378aa10c6f1eae6 Mon Sep 17 00:00:00 2001 From: Rene Groeschke Date: Wed, 20 Mar 2019 09:21:18 +0100 Subject: [PATCH 638/853] Some cleanup on removing unrequired methods --- .../gradle/kotlin/dsl/plugins/base/KotlinDslBasePlugin.kt | 1 - .../logging/slf4j/OutputEventListenerBackedLogger.java | 7 ------- 2 files changed, 8 deletions(-) diff --git a/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/base/KotlinDslBasePlugin.kt b/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/base/KotlinDslBasePlugin.kt index 8d2780faf2f44..012c02f872e9f 100644 --- a/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/base/KotlinDslBasePlugin.kt +++ b/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/base/KotlinDslBasePlugin.kt @@ -42,7 +42,6 @@ import org.gradle.kotlin.dsl.* class KotlinDslBasePlugin : Plugin { override fun apply(project: Project): Unit = project.run { - apply() createOptionsExtension() apply() diff --git a/subprojects/logging/src/main/java/org/gradle/internal/logging/slf4j/OutputEventListenerBackedLogger.java b/subprojects/logging/src/main/java/org/gradle/internal/logging/slf4j/OutputEventListenerBackedLogger.java index 2ab1cf2308170..49a571a81934d 100644 --- a/subprojects/logging/src/main/java/org/gradle/internal/logging/slf4j/OutputEventListenerBackedLogger.java +++ b/subprojects/logging/src/main/java/org/gradle/internal/logging/slf4j/OutputEventListenerBackedLogger.java @@ -480,12 +480,5 @@ public void error(Marker marker, String msg, Throwable t) { } } - public OutputEventListenerBackedLoggerContext getContext() { - return context; - } - - public Clock getClock() { - return clock; - } } From 706cbb017d055955954e2b1f7a6b6084d42fef69 Mon Sep 17 00:00:00 2001 From: Daniel Lacasse Date: Wed, 20 Mar 2019 12:26:30 +0100 Subject: [PATCH 639/853] Publish 5.3 --- released-versions.json | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/released-versions.json b/released-versions.json index 565619b8d6452..ab0682f1671ab 100644 --- a/released-versions.json +++ b/released-versions.json @@ -8,6 +8,10 @@ "buildTime": "20190313202708+0000" }, "finalReleases": [ + { + "version": "5.3", + "buildTime": "20190320110329+0000" + }, { "version": "5.2.1", "buildTime": "20190208190010+0000" From 39e295c51f4b84d24d0a61de4c987ea245715912 Mon Sep 17 00:00:00 2001 From: Daniel Lacasse Date: Wed, 20 Mar 2019 13:42:42 +0100 Subject: [PATCH 640/853] Update Gradle wrapper to 5.3 GA --- gradle/wrapper/gradle-wrapper.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 11c592cb636fa..838e6bc85a8e7 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-5.3-rc-3-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-5.3-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists From 75ff45f56256b121b30c9ee2e1dd573f20ef4273 Mon Sep 17 00:00:00 2001 From: "Rodrigo B. de Oliveira" Date: Tue, 12 Mar 2019 22:15:02 -0300 Subject: [PATCH 641/853] Take advantage of type-safe accessors in precompiled script plugins --- .../src/main/kotlin/plugins/kotlin-dsl-module.gradle.kts | 5 ++--- .../main/kotlin/plugins/kotlin-dsl-plugin-bundle.gradle.kts | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/buildSrc/subprojects/kotlin-dsl/src/main/kotlin/plugins/kotlin-dsl-module.gradle.kts b/buildSrc/subprojects/kotlin-dsl/src/main/kotlin/plugins/kotlin-dsl-module.gradle.kts index 5f813ac1fcfc3..b8a289cf4e792 100644 --- a/buildSrc/subprojects/kotlin-dsl/src/main/kotlin/plugins/kotlin-dsl-module.gradle.kts +++ b/buildSrc/subprojects/kotlin-dsl/src/main/kotlin/plugins/kotlin-dsl-module.gradle.kts @@ -29,9 +29,8 @@ plugins { } // including all sources -val main by sourceSets -tasks.named("jar") { - from(main.allSource) +tasks.jar { + from(sourceSets.main.get().allSource) manifest.attributes.apply { put("Implementation-Title", "Gradle Kotlin DSL (${project.name})") put("Implementation-Version", archiveVersion.get()) diff --git a/buildSrc/subprojects/kotlin-dsl/src/main/kotlin/plugins/kotlin-dsl-plugin-bundle.gradle.kts b/buildSrc/subprojects/kotlin-dsl/src/main/kotlin/plugins/kotlin-dsl-plugin-bundle.gradle.kts index 3e77884e4eb73..82ba52227d762 100644 --- a/buildSrc/subprojects/kotlin-dsl/src/main/kotlin/plugins/kotlin-dsl-plugin-bundle.gradle.kts +++ b/buildSrc/subprojects/kotlin-dsl/src/main/kotlin/plugins/kotlin-dsl-plugin-bundle.gradle.kts @@ -44,7 +44,7 @@ afterEvaluate { tasks { - "validateTaskProperties"(ValidateTaskProperties::class) { + validateTaskProperties { failOnWarning = true enableStricterValidation = true } From 733737e478fd3897e5f1d2fffade77f524da9585 Mon Sep 17 00:00:00 2001 From: "Rodrigo B. de Oliveira" Date: Fri, 15 Mar 2019 10:50:10 -0300 Subject: [PATCH 642/853] Take advantage of type-safe accessors in `jmh.gradle.kts` --- .../profiling/src/main/kotlin/gradlebuild/jmh.gradle.kts | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/buildSrc/subprojects/profiling/src/main/kotlin/gradlebuild/jmh.gradle.kts b/buildSrc/subprojects/profiling/src/main/kotlin/gradlebuild/jmh.gradle.kts index 495069b114405..ad595d66c13ef 100644 --- a/buildSrc/subprojects/profiling/src/main/kotlin/gradlebuild/jmh.gradle.kts +++ b/buildSrc/subprojects/profiling/src/main/kotlin/gradlebuild/jmh.gradle.kts @@ -16,20 +16,17 @@ package gradlebuild -import me.champeau.gradle.JMHPluginExtension - plugins { id("me.champeau.gradle.jmh") } configurations { - - getByName("jmhImplementation") { - extendsFrom(configurations["implementation"]) + jmhImplementation { + extendsFrom(configurations.implementation.get()) } } -configure { +jmh { isIncludeTests = false resultFormat = "CSV" } From 4950e6a89ecf6d1a536c3cd586d40b2e781c692f Mon Sep 17 00:00:00 2001 From: "Rodrigo B. de Oliveira" Date: Fri, 15 Mar 2019 10:50:51 -0300 Subject: [PATCH 643/853] Polish `java-projects.gradle.kts` - Prefer the `plugins` block over `apply(plugin = ...)` --- .../main/kotlin/gradlebuild/java-projects.gradle.kts | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/buildSrc/subprojects/uber-plugins/src/main/kotlin/gradlebuild/java-projects.gradle.kts b/buildSrc/subprojects/uber-plugins/src/main/kotlin/gradlebuild/java-projects.gradle.kts index d2a0f24fb084e..fe66ffba546b6 100644 --- a/buildSrc/subprojects/uber-plugins/src/main/kotlin/gradlebuild/java-projects.gradle.kts +++ b/buildSrc/subprojects/uber-plugins/src/main/kotlin/gradlebuild/java-projects.gradle.kts @@ -15,11 +15,13 @@ */ package gradlebuild -apply(plugin = "gradlebuild.unittest-and-compile") -apply(plugin = "gradlebuild.test-fixtures") -apply(plugin = "gradlebuild.distribution-testing") -apply(plugin = "gradlebuild.int-test-image") -apply(plugin = "gradlebuild.incubation-report") +plugins { + id("gradlebuild.unittest-and-compile") + id("gradlebuild.test-fixtures") + id("gradlebuild.distribution-testing") + id("gradlebuild.int-test-image") + id("gradlebuild.incubation-report") +} if (file("src/integTest").isDirectory) { apply(plugin = "gradlebuild.integration-tests") From 8ee2076e2972a096254504c6b0cb046cb7d772d6 Mon Sep 17 00:00:00 2001 From: "Rodrigo B. de Oliveira" Date: Wed, 20 Mar 2019 11:46:42 -0300 Subject: [PATCH 644/853] Polish `api-parameter-names-index.gradle.kts` --- .../gradlebuild/api-parameter-names-index.gradle.kts | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/buildSrc/subprojects/plugins/src/main/kotlin/gradlebuild/api-parameter-names-index.gradle.kts b/buildSrc/subprojects/plugins/src/main/kotlin/gradlebuild/api-parameter-names-index.gradle.kts index 0330e3a049d7e..a6b5b1b353276 100644 --- a/buildSrc/subprojects/plugins/src/main/kotlin/gradlebuild/api-parameter-names-index.gradle.kts +++ b/buildSrc/subprojects/plugins/src/main/kotlin/gradlebuild/api-parameter-names-index.gradle.kts @@ -35,7 +35,12 @@ val parameterNamesIndex by tasks.registering(ParameterNamesIndex::class) { if (file("src/main/groovy").isDirectory) { classpath.from(tasks.named("compileGroovy")) } - destinationFile.set(gradlebuildJava.generatedResourcesDir.resolve("${base.archivesBaseName}-parameter-names.properties")) + destinationFile.set( + gradlebuildJava.generatedResourcesDir.resolve("${base.archivesBaseName}-parameter-names.properties") + ) } -main.output.dir(gradlebuildJava.generatedResourcesDir, "builtBy" to parameterNamesIndex) +main.output.dir( + gradlebuildJava.generatedResourcesDir, + "builtBy" to parameterNamesIndex +) From 55f2399a80158d9b6242ee58f3137b520e0699a6 Mon Sep 17 00:00:00 2001 From: "Rodrigo B. de Oliveira" Date: Wed, 20 Mar 2019 11:47:07 -0300 Subject: [PATCH 645/853] Add missing dependency to `buildSrc/uber-plugins` The implementation dependency on `project(":buildquality")` is required because the script plugin `java-projects.gradle.kts` applies the `gradlebuild.incubation-report` plugin defined on it. --- buildSrc/subprojects/uber-plugins/uber-plugins.gradle.kts | 1 + 1 file changed, 1 insertion(+) diff --git a/buildSrc/subprojects/uber-plugins/uber-plugins.gradle.kts b/buildSrc/subprojects/uber-plugins/uber-plugins.gradle.kts index 5f3b98f189571..638966d400e1b 100644 --- a/buildSrc/subprojects/uber-plugins/uber-plugins.gradle.kts +++ b/buildSrc/subprojects/uber-plugins/uber-plugins.gradle.kts @@ -1,5 +1,6 @@ dependencies { implementation(project(":binaryCompatibility")) + implementation(project(":buildquality")) implementation(project(":cleanup")) implementation(project(":configuration")) implementation(project(":kotlinDsl")) From 71bbecfb84996973345d5b543e982346bf6af0f2 Mon Sep 17 00:00:00 2001 From: "Rodrigo B. de Oliveira" Date: Wed, 20 Mar 2019 12:04:48 -0300 Subject: [PATCH 646/853] Revert "Polish `java-projects.gradle.kts`" This reverts commit 4950e6a89ecf6d1a536c3cd586d40b2e781c692f. --- .../main/kotlin/gradlebuild/java-projects.gradle.kts | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/buildSrc/subprojects/uber-plugins/src/main/kotlin/gradlebuild/java-projects.gradle.kts b/buildSrc/subprojects/uber-plugins/src/main/kotlin/gradlebuild/java-projects.gradle.kts index fe66ffba546b6..d2a0f24fb084e 100644 --- a/buildSrc/subprojects/uber-plugins/src/main/kotlin/gradlebuild/java-projects.gradle.kts +++ b/buildSrc/subprojects/uber-plugins/src/main/kotlin/gradlebuild/java-projects.gradle.kts @@ -15,13 +15,11 @@ */ package gradlebuild -plugins { - id("gradlebuild.unittest-and-compile") - id("gradlebuild.test-fixtures") - id("gradlebuild.distribution-testing") - id("gradlebuild.int-test-image") - id("gradlebuild.incubation-report") -} +apply(plugin = "gradlebuild.unittest-and-compile") +apply(plugin = "gradlebuild.test-fixtures") +apply(plugin = "gradlebuild.distribution-testing") +apply(plugin = "gradlebuild.int-test-image") +apply(plugin = "gradlebuild.incubation-report") if (file("src/integTest").isDirectory) { apply(plugin = "gradlebuild.integration-tests") From 57e3f0cf46c3ede0e0787c2c45efc3e506115fa3 Mon Sep 17 00:00:00 2001 From: Daniel Lacasse Date: Wed, 20 Mar 2019 19:32:51 +0100 Subject: [PATCH 647/853] Unlink software model from DSL reference navigation bar --- subprojects/docs/docs.gradle | 1 + subprojects/docs/src/docs/dsl/dsl.xml | 61 +++++++++++++++++---------- 2 files changed, 40 insertions(+), 22 deletions(-) diff --git a/subprojects/docs/docs.gradle b/subprojects/docs/docs.gradle index b6365b1b589f5..ba45ec853a836 100755 --- a/subprojects/docs/docs.gradle +++ b/subprojects/docs/docs.gradle @@ -263,6 +263,7 @@ def dslStandaloneDocbook = tasks.register("dslStandaloneDocbook", UserGuideTrans javadocUrl = '../javadoc' dsldocUrl = '../dsl' websiteUrl = 'https://gradle.org' + tags = ["noNavBar"] } def dslHtml = tasks.register("dslHtml", Docbook2Xhtml) { diff --git a/subprojects/docs/src/docs/dsl/dsl.xml b/subprojects/docs/src/docs/dsl/dsl.xml index 982321f7f0e97..b4701e43cca2c 100644 --- a/subprojects/docs/src/docs/dsl/dsl.xml +++ b/subprojects/docs/src/docs/dsl/dsl.xml @@ -665,6 +665,23 @@
    + Native tool chains model types + Used to configure tool chains for building C++ components. + + Native tool chain types + + + + + + + + + +
    org.gradle.nativeplatform.toolchain.Gcc
    org.gradle.nativeplatform.toolchain.Clang
    org.gradle.nativeplatform.toolchain.VisualCpp
    +
    + +
    Native software model types Used to configure software components developed with native code. @@ -729,15 +746,6 @@ - - - - - - - - - @@ -782,43 +790,52 @@
    org.gradle.nativeplatform.Flavor
    org.gradle.nativeplatform.toolchain.Gcc
    org.gradle.nativeplatform.toolchain.Clang
    org.gradle.nativeplatform.toolchain.VisualCpp
    org.gradle.language.assembler.AssemblerSourceSet
    +
    - Native binary task types - Tasks used to build native binaries. + C++ binary task types + Tasks used to build C++ binaries. - Native component task types + C++ component task types - + - + - + - + - + +
    org.gradle.language.cpp.tasks.CppCompile
    org.gradle.language.c.tasks.CCompileorg.gradle.nativeplatform.tasks.LinkExecutable
    org.gradle.language.assembler.tasks.Assembleorg.gradle.nativeplatform.tasks.LinkSharedLibrary
    org.gradle.language.objectivec.tasks.ObjectiveCCompileorg.gradle.nativeplatform.tasks.CreateStaticLibrary
    org.gradle.language.objectivecpp.tasks.ObjectiveCppCompileorg.gradle.nativeplatform.tasks.InstallExecutable
    org.gradle.language.rc.tasks.WindowsResourceCompileorg.gradle.nativeplatform.test.tasks.RunTestExecutable
    +
    + +
    + Native binary task types + Tasks used to build native binaries. + + Native component task types - + - + - + - + - +
    org.gradle.nativeplatform.tasks.LinkExecutableorg.gradle.language.c.tasks.CCompile
    org.gradle.nativeplatform.tasks.LinkSharedLibraryorg.gradle.language.assembler.tasks.Assemble
    org.gradle.nativeplatform.tasks.CreateStaticLibraryorg.gradle.language.objectivec.tasks.ObjectiveCCompile
    org.gradle.nativeplatform.tasks.InstallExecutableorg.gradle.language.objectivecpp.tasks.ObjectiveCppCompile
    org.gradle.nativeplatform.test.tasks.RunTestExecutableorg.gradle.language.rc.tasks.WindowsResourceCompile
    From 43d8f98a3a3582b4ba3050c273f5bf0c1191b34a Mon Sep 17 00:00:00 2001 From: Sterling Greene Date: Wed, 20 Mar 2019 15:36:20 -0400 Subject: [PATCH 648/853] Update subprojects/docs/docs.gradle --- subprojects/docs/docs.gradle | 1 - 1 file changed, 1 deletion(-) diff --git a/subprojects/docs/docs.gradle b/subprojects/docs/docs.gradle index ba45ec853a836..b6365b1b589f5 100755 --- a/subprojects/docs/docs.gradle +++ b/subprojects/docs/docs.gradle @@ -263,7 +263,6 @@ def dslStandaloneDocbook = tasks.register("dslStandaloneDocbook", UserGuideTrans javadocUrl = '../javadoc' dsldocUrl = '../dsl' websiteUrl = 'https://gradle.org' - tags = ["noNavBar"] } def dslHtml = tasks.register("dslHtml", Docbook2Xhtml) { From 5a28fc0ae8dd08cc06336f77a0ebf6a06f51dc2f Mon Sep 17 00:00:00 2001 From: Stefan Wolf Date: Wed, 20 Mar 2019 10:35:09 +0100 Subject: [PATCH 649/853] Update ExecuteTaskBuildOperationType Javadoc to reference new API type. --- .../tasks/execution/ExecuteTaskBuildOperationType.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/ExecuteTaskBuildOperationType.java b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/ExecuteTaskBuildOperationType.java index 5e39049e187a0..e3050f486e43b 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/ExecuteTaskBuildOperationType.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/ExecuteTaskBuildOperationType.java @@ -16,7 +16,6 @@ package org.gradle.api.internal.tasks.execution; -import org.gradle.api.tasks.incremental.IncrementalTaskInputs; import org.gradle.internal.operations.BuildOperationType; import org.gradle.internal.scan.NotUsedByScanPlugin; import org.gradle.internal.scan.UsedByScanPlugin; @@ -124,7 +123,7 @@ public interface Result { /** * Returns if this task was executed incrementally. * - * @see IncrementalTaskInputs#isIncremental() + * @see org.gradle.work.InputChanges#isIncremental() */ @NotUsedByScanPlugin("used to report incrementality to TAPI progress listeners") boolean isIncremental(); From dfa362f4cf1720e35315b8a9dc5221724c859a0a Mon Sep 17 00:00:00 2001 From: Stefan Wolf Date: Wed, 20 Mar 2019 14:05:29 +0100 Subject: [PATCH 650/853] Update AnnotationProcessingTaskFactoryTest to also test InputChanges. --- .../DefaultTaskClassInfoStore.java | 2 +- ...AnnotationProcessingTaskFactoryTest.groovy | 50 ++++++++++++-- .../AnnotationProcessingTasks.java | 69 ++++++++++++++++++- 3 files changed, 113 insertions(+), 8 deletions(-) diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/project/taskfactory/DefaultTaskClassInfoStore.java b/subprojects/core/src/main/java/org/gradle/api/internal/project/taskfactory/DefaultTaskClassInfoStore.java index 522ea474c03ac..fd239b9a88017 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/project/taskfactory/DefaultTaskClassInfoStore.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/project/taskfactory/DefaultTaskClassInfoStore.java @@ -68,7 +68,7 @@ private TaskClassInfo createTaskClassInfo(Class type) { } if (taskActionFactory instanceof AbstractIncrementalTaskActionFactory) { if (incremental) { - throw new GradleException(String.format("Cannot have multiple @TaskAction methods accepting an %s parameter.", IncrementalTaskInputs.class.getSimpleName())); + throw new GradleException(String.format("Cannot have multiple @TaskAction methods accepting an %s or %s parameter.", InputChanges.class.getSimpleName(), IncrementalTaskInputs.class.getSimpleName())); } incremental = true; } diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/project/taskfactory/AnnotationProcessingTaskFactoryTest.groovy b/subprojects/core/src/test/groovy/org/gradle/api/internal/project/taskfactory/AnnotationProcessingTaskFactoryTest.groovy index a403b4a701268..15f8d6a08c0ca 100644 --- a/subprojects/core/src/test/groovy/org/gradle/api/internal/project/taskfactory/AnnotationProcessingTaskFactoryTest.groovy +++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/project/taskfactory/AnnotationProcessingTaskFactoryTest.groovy @@ -38,6 +38,7 @@ import org.gradle.internal.service.ServiceRegistryBuilder import org.gradle.internal.service.scopes.ExecutionGlobalServices import org.gradle.test.fixtures.AbstractProjectBuilderSpec import org.gradle.test.fixtures.file.TestFile +import org.gradle.work.InputChanges import spock.lang.Unroll import java.util.concurrent.Callable @@ -48,6 +49,7 @@ import static org.gradle.api.internal.project.taskfactory.AnnotationProcessingTa import static org.gradle.api.internal.project.taskfactory.AnnotationProcessingTasks.BrokenTaskWithInputDir import static org.gradle.api.internal.project.taskfactory.AnnotationProcessingTasks.BrokenTaskWithInputFiles import static org.gradle.api.internal.project.taskfactory.AnnotationProcessingTasks.NamedBean +import static org.gradle.api.internal.project.taskfactory.AnnotationProcessingTasks.TaskUsingInputChanges import static org.gradle.api.internal.project.taskfactory.AnnotationProcessingTasks.TaskWithBooleanInput import static org.gradle.api.internal.project.taskfactory.AnnotationProcessingTasks.TaskWithBridgeMethod import static org.gradle.api.internal.project.taskfactory.AnnotationProcessingTasks.TaskWithDestroyable @@ -59,8 +61,10 @@ import static org.gradle.api.internal.project.taskfactory.AnnotationProcessingTa import static org.gradle.api.internal.project.taskfactory.AnnotationProcessingTasks.TaskWithInputFiles import static org.gradle.api.internal.project.taskfactory.AnnotationProcessingTasks.TaskWithJavaBeanCornerCaseProperties import static org.gradle.api.internal.project.taskfactory.AnnotationProcessingTasks.TaskWithLocalState +import static org.gradle.api.internal.project.taskfactory.AnnotationProcessingTasks.TaskWithMixedMultipleIncrementalActions import static org.gradle.api.internal.project.taskfactory.AnnotationProcessingTasks.TaskWithMultiParamAction import static org.gradle.api.internal.project.taskfactory.AnnotationProcessingTasks.TaskWithMultipleIncrementalActions +import static org.gradle.api.internal.project.taskfactory.AnnotationProcessingTasks.TaskWithMultipleInputChangesActions import static org.gradle.api.internal.project.taskfactory.AnnotationProcessingTasks.TaskWithMultipleMethods import static org.gradle.api.internal.project.taskfactory.AnnotationProcessingTasks.TaskWithMultipleProperties import static org.gradle.api.internal.project.taskfactory.AnnotationProcessingTasks.TaskWithNestedBean @@ -79,7 +83,10 @@ import static org.gradle.api.internal.project.taskfactory.AnnotationProcessingTa import static org.gradle.api.internal.project.taskfactory.AnnotationProcessingTasks.TaskWithOutputFile import static org.gradle.api.internal.project.taskfactory.AnnotationProcessingTasks.TaskWithOutputFiles import static org.gradle.api.internal.project.taskfactory.AnnotationProcessingTasks.TaskWithOverloadedActions +import static org.gradle.api.internal.project.taskfactory.AnnotationProcessingTasks.TaskWithOverloadedIncrementalAndInputChangesActions +import static org.gradle.api.internal.project.taskfactory.AnnotationProcessingTasks.TaskWithOverloadedInputChangesActions import static org.gradle.api.internal.project.taskfactory.AnnotationProcessingTasks.TaskWithOverriddenIncrementalAction +import static org.gradle.api.internal.project.taskfactory.AnnotationProcessingTasks.TaskWithOverriddenInputChangesAction import static org.gradle.api.internal.project.taskfactory.AnnotationProcessingTasks.TaskWithOverriddenMethod import static org.gradle.api.internal.project.taskfactory.AnnotationProcessingTasks.TaskWithProtectedMethod import static org.gradle.api.internal.project.taskfactory.AnnotationProcessingTasks.TaskWithSingleParamAction @@ -158,6 +165,19 @@ class AnnotationProcessingTaskFactoryTest extends AbstractProjectBuilderSpec { 0 * _ } + def createsContextualActionForInputChangesTaskAction() { + given: + def action = Mock(Action) + def task = expectTaskCreated(TaskUsingInputChanges, action) + + when: + execute(task) + + then: + 1 * action.execute(_ as InputChanges) + 0 * _ + } + def createsContextualActionForOverriddenIncrementalTaskAction() { given: def action = Mock(Action) @@ -172,6 +192,20 @@ class AnnotationProcessingTaskFactoryTest extends AbstractProjectBuilderSpec { 0 * _ } + def createsContextualActionForOverriddenInputChangesTaskAction() { + given: + def action = Mock(Action) + def superAction = Mock(Action) + def task = expectTaskCreated(TaskWithOverriddenInputChangesAction, action, superAction) + + when: + execute(task) + + then: + 1 * action.execute(_ as InputChanges) + 0 * _ + } + def cachesClassMetaInfo() { given: def taskInfo1 = taskClassInfoStore.getTaskClassInfo(TaskWithInputFile) @@ -191,12 +225,16 @@ class AnnotationProcessingTaskFactoryTest extends AbstractProjectBuilderSpec { e.message == failureMessage where: - type | failureMessage - TaskWithMultipleIncrementalActions | "Cannot have multiple @TaskAction methods accepting an IncrementalTaskInputs parameter." - TaskWithStaticMethod | "Cannot use @TaskAction annotation on static method TaskWithStaticMethod.doStuff()." - TaskWithMultiParamAction | "Cannot use @TaskAction annotation on method TaskWithMultiParamAction.doStuff() as this method takes multiple parameters." - TaskWithSingleParamAction | "Cannot use @TaskAction annotation on method TaskWithSingleParamAction.doStuff() because int is not a valid parameter to an action method." - TaskWithOverloadedActions | "Cannot use @TaskAction annotation on multiple overloads of method TaskWithOverloadedActions.doStuff()" + type | failureMessage + TaskWithMultipleIncrementalActions | "Cannot have multiple @TaskAction methods accepting an InputChanges or IncrementalTaskInputs parameter." + TaskWithStaticMethod | "Cannot use @TaskAction annotation on static method TaskWithStaticMethod.doStuff()." + TaskWithMultiParamAction | "Cannot use @TaskAction annotation on method TaskWithMultiParamAction.doStuff() as this method takes multiple parameters." + TaskWithSingleParamAction | "Cannot use @TaskAction annotation on method TaskWithSingleParamAction.doStuff() because int is not a valid parameter to an action method." + TaskWithOverloadedActions | "Cannot use @TaskAction annotation on multiple overloads of method TaskWithOverloadedActions.doStuff()" + TaskWithOverloadedInputChangesActions | "Cannot use @TaskAction annotation on multiple overloads of method TaskWithOverloadedInputChangesActions.doStuff()" + TaskWithOverloadedIncrementalAndInputChangesActions | "Cannot use @TaskAction annotation on multiple overloads of method TaskWithOverloadedIncrementalAndInputChangesActions.doStuff()" + TaskWithMultipleInputChangesActions | "Cannot have multiple @TaskAction methods accepting an InputChanges or IncrementalTaskInputs parameter." + TaskWithMixedMultipleIncrementalActions | "Cannot have multiple @TaskAction methods accepting an InputChanges or IncrementalTaskInputs parameter." } @Unroll diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/project/taskfactory/AnnotationProcessingTasks.java b/subprojects/core/src/test/groovy/org/gradle/api/internal/project/taskfactory/AnnotationProcessingTasks.java index 1b7a1b9d20291..ec56e4fa803ae 100644 --- a/subprojects/core/src/test/groovy/org/gradle/api/internal/project/taskfactory/AnnotationProcessingTasks.java +++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/project/taskfactory/AnnotationProcessingTasks.java @@ -34,6 +34,7 @@ import org.gradle.api.tasks.SkipWhenEmpty; import org.gradle.api.tasks.TaskAction; import org.gradle.api.tasks.incremental.IncrementalTaskInputs; +import org.gradle.work.InputChanges; import java.io.File; import java.util.List; @@ -146,6 +147,53 @@ public void doStuff(IncrementalTaskInputs changes) { } } + public static class TaskWithOverloadedActions extends DefaultTask { + @TaskAction + public void doStuff() {} + + @TaskAction + public void doStuff(IncrementalTaskInputs changes) {} + } + + public static class TaskUsingInputChanges extends DefaultTask { + private final Action action; + + public TaskUsingInputChanges(Action action) { + this.action = action; + } + + @TaskAction + public void doStuff(InputChanges changes) { + action.execute(changes); + } + } + + public static class TaskWithOverriddenInputChangesAction extends TaskUsingInputChanges { + private final Action action; + + public TaskWithOverriddenInputChangesAction(Action action, Action superAction) { + super(superAction); + this.action = action; + } + + @Override + @TaskAction + public void doStuff(InputChanges changes) { + action.execute(changes); + } + } + + public static class TaskWithMultipleInputChangesActions extends DefaultTask { + + @TaskAction + public void doStuff(InputChanges changes) { + } + + @TaskAction + public void doStuff2(InputChanges changes) { + } + } + public static class TaskWithMultipleIncrementalActions extends DefaultTask { @TaskAction @@ -157,12 +205,31 @@ public void doStuff2(IncrementalTaskInputs changes) { } } - public static class TaskWithOverloadedActions extends DefaultTask { + public static class TaskWithMixedMultipleIncrementalActions extends DefaultTask { + + @TaskAction + public void doStuff(IncrementalTaskInputs changes) { + } + + @TaskAction + public void doStuff2(InputChanges changes) { + } + } + + public static class TaskWithOverloadedInputChangesActions extends DefaultTask { @TaskAction public void doStuff() {} + @TaskAction + public void doStuff(InputChanges changes) {} + } + + public static class TaskWithOverloadedIncrementalAndInputChangesActions extends DefaultTask { @TaskAction public void doStuff(IncrementalTaskInputs changes) {} + + @TaskAction + public void doStuff(InputChanges changes) {} } public static class TaskWithSingleParamAction extends DefaultTask { From bab39c360cb55474ae52077e8b687ec195596266 Mon Sep 17 00:00:00 2001 From: Stefan Wolf Date: Wed, 20 Mar 2019 11:30:58 +0100 Subject: [PATCH 651/853] Convert WindowsResourceCompile to new incremental API --- .../src/changes/accepted-public-api-changes.json | 11 +++++++++-- .../language/rc/tasks/WindowsResourceCompile.java | 10 +++++++--- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/subprojects/distributions/src/changes/accepted-public-api-changes.json b/subprojects/distributions/src/changes/accepted-public-api-changes.json index 4017e10029272..87877214e5362 100644 --- a/subprojects/distributions/src/changes/accepted-public-api-changes.json +++ b/subprojects/distributions/src/changes/accepted-public-api-changes.json @@ -1,3 +1,10 @@ { - "acceptedApiChanges": [] -} \ No newline at end of file + "acceptedApiChanges": [ + { + "type": "org.gradle.language.rc.tasks.WindowsResourceCompile", + "member": "Method org.gradle.language.rc.tasks.WindowsResourceCompile.compile(org.gradle.work.InputChanges)", + "acceptation": "Migrated to the new incremental tasks API", + "changes": [] + } + ] +} diff --git a/subprojects/language-native/src/main/java/org/gradle/language/rc/tasks/WindowsResourceCompile.java b/subprojects/language-native/src/main/java/org/gradle/language/rc/tasks/WindowsResourceCompile.java index 4e56afed1497c..f30193070caa7 100644 --- a/subprojects/language-native/src/main/java/org/gradle/language/rc/tasks/WindowsResourceCompile.java +++ b/subprojects/language-native/src/main/java/org/gradle/language/rc/tasks/WindowsResourceCompile.java @@ -32,7 +32,6 @@ import org.gradle.api.tasks.PathSensitivity; import org.gradle.api.tasks.TaskAction; import org.gradle.api.tasks.WorkResult; -import org.gradle.api.tasks.incremental.IncrementalTaskInputs; import org.gradle.internal.Cast; import org.gradle.internal.operations.logging.BuildOperationLogger; import org.gradle.internal.operations.logging.BuildOperationLoggerFactory; @@ -47,6 +46,8 @@ import org.gradle.nativeplatform.toolchain.internal.NativeCompileSpec; import org.gradle.nativeplatform.toolchain.internal.NativeToolChainInternal; import org.gradle.nativeplatform.toolchain.internal.PlatformToolProvider; +import org.gradle.work.Incremental; +import org.gradle.work.InputChanges; import javax.inject.Inject; import java.io.File; @@ -79,7 +80,7 @@ public WindowsResourceCompile() { incrementalCompiler = getIncrementalCompilerBuilder().newCompiler(this, source, includes, macros, Providers.FALSE); getInputs().property("outputType", new Callable() { @Override - public String call() throws Exception { + public String call() { NativeToolChainInternal nativeToolChain = (NativeToolChainInternal) toolChain.get(); NativePlatformInternal nativePlatform = (NativePlatformInternal) targetPlatform.get(); return NativeToolChainInternal.Identifier.identify(nativeToolChain, nativePlatform); @@ -98,7 +99,7 @@ public BuildOperationLoggerFactory getOperationLoggerFactory() { } @TaskAction - public void compile(IncrementalTaskInputs inputs) { + public void compile(InputChanges inputs) { BuildOperationLogger operationLogger = getOperationLoggerFactory().newOperationLogger(getName(), getTemporaryDir()); NativeCompileSpec spec = new DefaultWindowsResourceCompileSpec(); @@ -161,6 +162,7 @@ public void setOutputDir(File outputDir) { /** * Returns the header directories to be used for compilation. */ + @Incremental @PathSensitive(PathSensitivity.RELATIVE) @InputFiles public ConfigurableFileCollection getIncludes() { @@ -177,6 +179,7 @@ public void includes(Object includeRoots) { /** * Returns the source files to be compiled. */ + @Incremental @PathSensitive(PathSensitivity.RELATIVE) @InputFiles public ConfigurableFileCollection getSource() { @@ -218,6 +221,7 @@ public ListProperty getCompilerArgs() { * * @since 4.5 */ + @Incremental @InputFiles @PathSensitive(PathSensitivity.NAME_ONLY) protected FileCollection getHeaderDependencies() { From 897f5f93a04530ad4b763311a433b6a018110c53 Mon Sep 17 00:00:00 2001 From: Stefan Wolf Date: Wed, 20 Mar 2019 11:55:32 +0100 Subject: [PATCH 652/853] Convert SwiftCompile to new incremental API --- .../language/swift/tasks/SwiftCompile.java | 38 ++++++------------- 1 file changed, 12 insertions(+), 26 deletions(-) diff --git a/subprojects/language-native/src/main/java/org/gradle/language/swift/tasks/SwiftCompile.java b/subprojects/language-native/src/main/java/org/gradle/language/swift/tasks/SwiftCompile.java index a386b037e9e12..1238a96dd1ab1 100644 --- a/subprojects/language-native/src/main/java/org/gradle/language/swift/tasks/SwiftCompile.java +++ b/subprojects/language-native/src/main/java/org/gradle/language/swift/tasks/SwiftCompile.java @@ -18,7 +18,6 @@ import com.google.common.collect.Lists; import com.google.common.collect.Sets; -import org.gradle.api.Action; import org.gradle.api.DefaultTask; import org.gradle.api.Incubating; import org.gradle.api.file.ConfigurableFileCollection; @@ -40,8 +39,6 @@ import org.gradle.api.tasks.SkipWhenEmpty; import org.gradle.api.tasks.TaskAction; import org.gradle.api.tasks.WorkResult; -import org.gradle.api.tasks.incremental.IncrementalTaskInputs; -import org.gradle.api.tasks.incremental.InputFileDetails; import org.gradle.internal.Cast; import org.gradle.internal.operations.logging.BuildOperationLogger; import org.gradle.internal.operations.logging.BuildOperationLoggerFactory; @@ -59,6 +56,9 @@ import org.gradle.nativeplatform.toolchain.internal.PlatformToolProvider; import org.gradle.nativeplatform.toolchain.internal.compilespec.SwiftCompileSpec; import org.gradle.nativeplatform.toolchain.internal.swift.IncrementalSwiftCompiler; +import org.gradle.work.ChangeType; +import org.gradle.work.FileChange; +import org.gradle.work.InputChanges; import javax.inject.Inject; import java.io.File; @@ -272,36 +272,22 @@ private Compiler createCompiler() { } @TaskAction - void compile(IncrementalTaskInputs inputs) { + void compile(InputChanges inputs) { final List removedFiles = Lists.newArrayList(); final Set changedFiles = Sets.newHashSet(); boolean isIncremental = inputs.isIncremental(); // TODO: This should become smarter and move into the compiler infrastructure instead - // of the task, similar to how the other native languages are done. - // For now, this does a rudimentary incremental build analysis by looking at - // which files changed and marking the compilation incremental or not. + // of the task, similar to how the other native languages are done. + // For now, this does a rudimentary incremental build analysis by looking at + // which files changed . if (isIncremental) { - inputs.outOfDate(new Action() { - @Override - public void execute(InputFileDetails inputFileDetails) { - if (inputFileDetails.isModified()) { - changedFiles.add(inputFileDetails.getFile()); - } + for (FileChange fileChange : inputs.getFileChanges(getSource())) { + if (fileChange.getChangeType() == ChangeType.REMOVED) { + removedFiles.add(fileChange.getFile()); + } else { + changedFiles.add(fileChange.getFile()); } - }); - inputs.removed(new Action() { - @Override - public void execute(InputFileDetails removed) { - removedFiles.add(removed.getFile()); - } - }); - - Set allSourceFiles = getSource().getFiles(); - if (!allSourceFiles.containsAll(changedFiles)) { - // If a non-source file changed, the compilation cannot be incremental - // due to the way the Swift compiler detects changes from other modules - isIncremental = false; } } From 47d0e527d206b6210b1d255882eb005d329ee0d3 Mon Sep 17 00:00:00 2001 From: Stefan Wolf Date: Wed, 20 Mar 2019 13:26:55 +0100 Subject: [PATCH 653/853] Convert AbstractNativeCompileTask to new incremental API --- .../changes/accepted-public-api-changes.json | 22 +++++++++++++++++++ .../tasks/AbstractNativeCompileTask.java | 7 ++++-- 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/subprojects/distributions/src/changes/accepted-public-api-changes.json b/subprojects/distributions/src/changes/accepted-public-api-changes.json index 87877214e5362..f90808e3818c8 100644 --- a/subprojects/distributions/src/changes/accepted-public-api-changes.json +++ b/subprojects/distributions/src/changes/accepted-public-api-changes.json @@ -5,6 +5,28 @@ "member": "Method org.gradle.language.rc.tasks.WindowsResourceCompile.compile(org.gradle.work.InputChanges)", "acceptation": "Migrated to the new incremental tasks API", "changes": [] + }, + { + "type": "org.gradle.language.nativeplatform.tasks.AbstractNativeCompileTask", + "member": "Method org.gradle.language.nativeplatform.tasks.AbstractNativeCompileTask.compile(org.gradle.work.InputChanges)", + "acceptation": "Migrated to the new incremental tasks API", + "changes": [] + }, + { + "type": "org.gradle.language.nativeplatform.tasks.AbstractNativePCHCompileTask", + "member": "Class org.gradle.language.nativeplatform.tasks.AbstractNativePCHCompileTask", + "acceptation": "Migrated to the new incremental tasks API", + "changes": [ + "org.gradle.language.nativeplatform.tasks.AbstractNativeCompileTask.compile(org.gradle.api.tasks.incremental.IncrementalTaskInputs)" + ] + }, + { + "type": "org.gradle.language.nativeplatform.tasks.AbstractNativeSourceCompileTask", + "member": "Class org.gradle.language.nativeplatform.tasks.AbstractNativeSourceCompileTask", + "acceptation": "Migrated to the new incremental tasks API", + "changes": [ + "org.gradle.language.nativeplatform.tasks.AbstractNativeCompileTask.compile(org.gradle.api.tasks.incremental.IncrementalTaskInputs)" + ] } ] } diff --git a/subprojects/language-native/src/main/java/org/gradle/language/nativeplatform/tasks/AbstractNativeCompileTask.java b/subprojects/language-native/src/main/java/org/gradle/language/nativeplatform/tasks/AbstractNativeCompileTask.java index 1402efe2c49c4..d8e1128a8796c 100644 --- a/subprojects/language-native/src/main/java/org/gradle/language/nativeplatform/tasks/AbstractNativeCompileTask.java +++ b/subprojects/language-native/src/main/java/org/gradle/language/nativeplatform/tasks/AbstractNativeCompileTask.java @@ -35,7 +35,6 @@ import org.gradle.api.tasks.PathSensitivity; import org.gradle.api.tasks.TaskAction; import org.gradle.api.tasks.WorkResult; -import org.gradle.api.tasks.incremental.IncrementalTaskInputs; import org.gradle.internal.Cast; import org.gradle.internal.operations.logging.BuildOperationLogger; import org.gradle.internal.operations.logging.BuildOperationLoggerFactory; @@ -50,6 +49,8 @@ import org.gradle.nativeplatform.toolchain.internal.NativeCompileSpec; import org.gradle.nativeplatform.toolchain.internal.NativeToolChainInternal; import org.gradle.nativeplatform.toolchain.internal.PlatformToolProvider; +import org.gradle.work.Incremental; +import org.gradle.work.InputChanges; import javax.inject.Inject; import java.util.LinkedHashMap; @@ -114,7 +115,7 @@ protected FileCollectionFactory getFileCollectionFactory() { } @TaskAction - public void compile(IncrementalTaskInputs inputs) { + public void compile(InputChanges inputs) { BuildOperationLogger operationLogger = getOperationLoggerFactory().newOperationLogger(getName(), getTemporaryDir()); NativeCompileSpec spec = createCompileSpec(); spec.setTargetPlatform(targetPlatform.get()); @@ -260,6 +261,7 @@ public ConfigurableFileCollection getSystemIncludes() { /** * Returns the source files to be compiled. */ + @Incremental @InputFiles @PathSensitive(PathSensitivity.RELATIVE) public ConfigurableFileCollection getSource() { @@ -301,6 +303,7 @@ public ListProperty getCompilerArgs() { * * @since 4.3 */ + @Incremental @InputFiles @PathSensitive(PathSensitivity.NAME_ONLY) protected FileCollection getHeaderDependencies() { From 39c4e82198b541e5b7550803f12c9dcd73e8d71e Mon Sep 17 00:00:00 2001 From: Stefan Wolf Date: Wed, 20 Mar 2019 14:25:47 +0100 Subject: [PATCH 654/853] Use SkipWhenEmpty for native sources --- .../CppIncrementalBuildStaleOutputsIntegrationTest.groovy | 6 +++--- .../nativeplatform/tasks/AbstractNativeCompileTask.java | 3 ++- .../gradle/language/rc/tasks/WindowsResourceCompile.java | 3 ++- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/subprojects/language-native/src/integTest/groovy/org/gradle/language/cpp/CppIncrementalBuildStaleOutputsIntegrationTest.groovy b/subprojects/language-native/src/integTest/groovy/org/gradle/language/cpp/CppIncrementalBuildStaleOutputsIntegrationTest.groovy index 2de4f7c4cc3ee..520c7a45986cf 100644 --- a/subprojects/language-native/src/integTest/groovy/org/gradle/language/cpp/CppIncrementalBuildStaleOutputsIntegrationTest.groovy +++ b/subprojects/language-native/src/integTest/groovy/org/gradle/language/cpp/CppIncrementalBuildStaleOutputsIntegrationTest.groovy @@ -122,7 +122,7 @@ class CppIncrementalBuildStaleOutputsIntegrationTest extends AbstractInstalledTo executable("app/build/exe/main/debug/app").assertDoesNotExist() file("app/build/exe/main/debug").assertDoesNotExist() - file("app/build/obj/main/debug").assertHasDescendants() + file("app/build/obj/main/debug").assertDoesNotExist() installation("app/build/install/main/debug").assertNotInstalled() sharedLibrary("greeter/build/lib/main/debug/greeter").assertExists() @@ -159,7 +159,7 @@ class CppIncrementalBuildStaleOutputsIntegrationTest extends AbstractInstalledTo executable("build/exe/main/debug/app").assertDoesNotExist() file("build/exe/main/debug").assertDoesNotExist() - file("build/obj/main/debug").assertHasDescendants() + file("build/obj/main/debug").assertDoesNotExist() installation("build/install/main/debug").assertNotInstalled() } @@ -192,7 +192,7 @@ class CppIncrementalBuildStaleOutputsIntegrationTest extends AbstractInstalledTo sharedLibrary("build/lib/main/debug/hello").assertDoesNotExist() file("build/lib/main/debug").assertDoesNotExist() - file("build/obj/main/debug").assertHasDescendants() + file("build/obj/main/debug").assertDoesNotExist() } private List expectIntermediateDescendants(SourceElement sourceElement) { diff --git a/subprojects/language-native/src/main/java/org/gradle/language/nativeplatform/tasks/AbstractNativeCompileTask.java b/subprojects/language-native/src/main/java/org/gradle/language/nativeplatform/tasks/AbstractNativeCompileTask.java index d8e1128a8796c..c09cf79a44cc4 100644 --- a/subprojects/language-native/src/main/java/org/gradle/language/nativeplatform/tasks/AbstractNativeCompileTask.java +++ b/subprojects/language-native/src/main/java/org/gradle/language/nativeplatform/tasks/AbstractNativeCompileTask.java @@ -33,6 +33,7 @@ import org.gradle.api.tasks.OutputDirectory; import org.gradle.api.tasks.PathSensitive; import org.gradle.api.tasks.PathSensitivity; +import org.gradle.api.tasks.SkipWhenEmpty; import org.gradle.api.tasks.TaskAction; import org.gradle.api.tasks.WorkResult; import org.gradle.internal.Cast; @@ -261,7 +262,7 @@ public ConfigurableFileCollection getSystemIncludes() { /** * Returns the source files to be compiled. */ - @Incremental + @SkipWhenEmpty @InputFiles @PathSensitive(PathSensitivity.RELATIVE) public ConfigurableFileCollection getSource() { diff --git a/subprojects/language-native/src/main/java/org/gradle/language/rc/tasks/WindowsResourceCompile.java b/subprojects/language-native/src/main/java/org/gradle/language/rc/tasks/WindowsResourceCompile.java index f30193070caa7..be061688d45df 100644 --- a/subprojects/language-native/src/main/java/org/gradle/language/rc/tasks/WindowsResourceCompile.java +++ b/subprojects/language-native/src/main/java/org/gradle/language/rc/tasks/WindowsResourceCompile.java @@ -30,6 +30,7 @@ import org.gradle.api.tasks.OutputDirectory; import org.gradle.api.tasks.PathSensitive; import org.gradle.api.tasks.PathSensitivity; +import org.gradle.api.tasks.SkipWhenEmpty; import org.gradle.api.tasks.TaskAction; import org.gradle.api.tasks.WorkResult; import org.gradle.internal.Cast; @@ -179,7 +180,7 @@ public void includes(Object includeRoots) { /** * Returns the source files to be compiled. */ - @Incremental + @SkipWhenEmpty @PathSensitive(PathSensitivity.RELATIVE) @InputFiles public ConfigurableFileCollection getSource() { From d94095508e0c9e11bfbc017bc8252e807d7849b0 Mon Sep 17 00:00:00 2001 From: Adam Murdoch Date: Thu, 21 Mar 2019 08:22:40 +1100 Subject: [PATCH 655/853] Fix the native unit test plugins so that they generate the relocated object files for the component under test into a separate directory for each variant of the component under test. Previously the object files for all variants were mixed together and Gradle would try to link them into each test binary. --- .../nativeplatform/test/cpp/plugins/CppUnitTestPlugin.java | 6 +++--- .../test/xctest/plugins/XCTestConventionPlugin.java | 5 ++--- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/subprojects/testing-native/src/main/java/org/gradle/nativeplatform/test/cpp/plugins/CppUnitTestPlugin.java b/subprojects/testing-native/src/main/java/org/gradle/nativeplatform/test/cpp/plugins/CppUnitTestPlugin.java index 86ec3a9690231..683331ca6e3c4 100644 --- a/subprojects/testing-native/src/main/java/org/gradle/nativeplatform/test/cpp/plugins/CppUnitTestPlugin.java +++ b/subprojects/testing-native/src/main/java/org/gradle/nativeplatform/test/cpp/plugins/CppUnitTestPlugin.java @@ -192,12 +192,12 @@ private void configureTestSuiteWithTestedComponentWhenAvailable(Project project, // Configure test binary to link against tested component compiled objects ConfigurableFileCollection testableObjects = project.files(); if (target instanceof CppApplication) { + // TODO - this should be an outgoing variant of the component under test TaskProvider unexportMainSymbol = tasks.register(testExecutable.getNames().getTaskName("relocateMainFor"), UnexportMainSymbol.class, task -> { - task.getOutputDirectory().set(project.getLayout().getBuildDirectory().dir("obj/main/for-test")); + String dirName = ((DefaultCppBinary) testedBinary).getNames().getDirName(); + task.getOutputDirectory().set(project.getLayout().getBuildDirectory().dir("obj/for-test/" + dirName)); task.getObjects().from(testedBinary.getObjects()); }); - // TODO: builtBy unnecessary? - testableObjects.builtBy(unexportMainSymbol); testableObjects.from(unexportMainSymbol.map(task -> task.getRelocatedObjects())); } else { testableObjects.from(testedBinary.getObjects()); diff --git a/subprojects/testing-native/src/main/java/org/gradle/nativeplatform/test/xctest/plugins/XCTestConventionPlugin.java b/subprojects/testing-native/src/main/java/org/gradle/nativeplatform/test/xctest/plugins/XCTestConventionPlugin.java index ef3e487a60a64..80cf51923e1fd 100644 --- a/subprojects/testing-native/src/main/java/org/gradle/nativeplatform/test/xctest/plugins/XCTestConventionPlugin.java +++ b/subprojects/testing-native/src/main/java/org/gradle/nativeplatform/test/xctest/plugins/XCTestConventionPlugin.java @@ -261,11 +261,10 @@ private void configureTestSuiteWithTestedComponentWhenAvailable(final Project pr ConfigurableFileCollection testableObjects = project.files(); if (testedComponent instanceof SwiftApplication) { TaskProvider unexportMainSymbol = tasks.register("relocateMainForTest", UnexportMainSymbol.class, task -> { - task.getOutputDirectory().set(project.getLayout().getBuildDirectory().dir("obj/main/for-test")); + String dirName = ((DefaultSwiftBinary) testedBinary).getNames().getDirName(); + task.getOutputDirectory().set(project.getLayout().getBuildDirectory().dir("obj/for-test/" + dirName)); task.getObjects().from(testedBinary.getObjects()); }); - // TODO: builtBy unnecessary? - testableObjects.builtBy(unexportMainSymbol); testableObjects.from(unexportMainSymbol.map(task -> task.getRelocatedObjects())); } else { testableObjects.from(testedBinary.getObjects()); From 1f71725ea686b8941f80b18f7ae398a604174b8a Mon Sep 17 00:00:00 2001 From: Gradleware Git Bot Date: Thu, 21 Mar 2019 02:23:47 +0100 Subject: [PATCH 656/853] Publish 5.3-20190321010135+0000 --- released-versions.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/released-versions.json b/released-versions.json index ab0682f1671ab..2237595589fda 100644 --- a/released-versions.json +++ b/released-versions.json @@ -1,7 +1,7 @@ { "latestReleaseSnapshot": { - "version": "5.3-20190320013427+0000", - "buildTime": "20190320013427+0000" + "version": "5.3-20190321010135+0000", + "buildTime": "20190321010135+0000" }, "latestRc": { "version": "5.3-rc-3", From cbe1b9ed3f28e6fb39feaba56e8140f490dc5a6b Mon Sep 17 00:00:00 2001 From: "Rodrigo B. de Oliveira" Date: Thu, 21 Mar 2019 12:31:16 -0300 Subject: [PATCH 657/853] Revert "Take advantage of type-safe accessors in precompiled script plugins" --- .../src/main/kotlin/plugins/kotlin-dsl-module.gradle.kts | 5 +++-- .../kotlin/plugins/kotlin-dsl-plugin-bundle.gradle.kts | 2 +- .../gradlebuild/api-parameter-names-index.gradle.kts | 9 ++------- .../profiling/src/main/kotlin/gradlebuild/jmh.gradle.kts | 9 ++++++--- .../subprojects/uber-plugins/uber-plugins.gradle.kts | 1 - 5 files changed, 12 insertions(+), 14 deletions(-) diff --git a/buildSrc/subprojects/kotlin-dsl/src/main/kotlin/plugins/kotlin-dsl-module.gradle.kts b/buildSrc/subprojects/kotlin-dsl/src/main/kotlin/plugins/kotlin-dsl-module.gradle.kts index b8a289cf4e792..5f813ac1fcfc3 100644 --- a/buildSrc/subprojects/kotlin-dsl/src/main/kotlin/plugins/kotlin-dsl-module.gradle.kts +++ b/buildSrc/subprojects/kotlin-dsl/src/main/kotlin/plugins/kotlin-dsl-module.gradle.kts @@ -29,8 +29,9 @@ plugins { } // including all sources -tasks.jar { - from(sourceSets.main.get().allSource) +val main by sourceSets +tasks.named("jar") { + from(main.allSource) manifest.attributes.apply { put("Implementation-Title", "Gradle Kotlin DSL (${project.name})") put("Implementation-Version", archiveVersion.get()) diff --git a/buildSrc/subprojects/kotlin-dsl/src/main/kotlin/plugins/kotlin-dsl-plugin-bundle.gradle.kts b/buildSrc/subprojects/kotlin-dsl/src/main/kotlin/plugins/kotlin-dsl-plugin-bundle.gradle.kts index 82ba52227d762..3e77884e4eb73 100644 --- a/buildSrc/subprojects/kotlin-dsl/src/main/kotlin/plugins/kotlin-dsl-plugin-bundle.gradle.kts +++ b/buildSrc/subprojects/kotlin-dsl/src/main/kotlin/plugins/kotlin-dsl-plugin-bundle.gradle.kts @@ -44,7 +44,7 @@ afterEvaluate { tasks { - validateTaskProperties { + "validateTaskProperties"(ValidateTaskProperties::class) { failOnWarning = true enableStricterValidation = true } diff --git a/buildSrc/subprojects/plugins/src/main/kotlin/gradlebuild/api-parameter-names-index.gradle.kts b/buildSrc/subprojects/plugins/src/main/kotlin/gradlebuild/api-parameter-names-index.gradle.kts index a6b5b1b353276..0330e3a049d7e 100644 --- a/buildSrc/subprojects/plugins/src/main/kotlin/gradlebuild/api-parameter-names-index.gradle.kts +++ b/buildSrc/subprojects/plugins/src/main/kotlin/gradlebuild/api-parameter-names-index.gradle.kts @@ -35,12 +35,7 @@ val parameterNamesIndex by tasks.registering(ParameterNamesIndex::class) { if (file("src/main/groovy").isDirectory) { classpath.from(tasks.named("compileGroovy")) } - destinationFile.set( - gradlebuildJava.generatedResourcesDir.resolve("${base.archivesBaseName}-parameter-names.properties") - ) + destinationFile.set(gradlebuildJava.generatedResourcesDir.resolve("${base.archivesBaseName}-parameter-names.properties")) } -main.output.dir( - gradlebuildJava.generatedResourcesDir, - "builtBy" to parameterNamesIndex -) +main.output.dir(gradlebuildJava.generatedResourcesDir, "builtBy" to parameterNamesIndex) diff --git a/buildSrc/subprojects/profiling/src/main/kotlin/gradlebuild/jmh.gradle.kts b/buildSrc/subprojects/profiling/src/main/kotlin/gradlebuild/jmh.gradle.kts index ad595d66c13ef..495069b114405 100644 --- a/buildSrc/subprojects/profiling/src/main/kotlin/gradlebuild/jmh.gradle.kts +++ b/buildSrc/subprojects/profiling/src/main/kotlin/gradlebuild/jmh.gradle.kts @@ -16,17 +16,20 @@ package gradlebuild +import me.champeau.gradle.JMHPluginExtension + plugins { id("me.champeau.gradle.jmh") } configurations { - jmhImplementation { - extendsFrom(configurations.implementation.get()) + + getByName("jmhImplementation") { + extendsFrom(configurations["implementation"]) } } -jmh { +configure { isIncludeTests = false resultFormat = "CSV" } diff --git a/buildSrc/subprojects/uber-plugins/uber-plugins.gradle.kts b/buildSrc/subprojects/uber-plugins/uber-plugins.gradle.kts index 638966d400e1b..5f3b98f189571 100644 --- a/buildSrc/subprojects/uber-plugins/uber-plugins.gradle.kts +++ b/buildSrc/subprojects/uber-plugins/uber-plugins.gradle.kts @@ -1,6 +1,5 @@ dependencies { implementation(project(":binaryCompatibility")) - implementation(project(":buildquality")) implementation(project(":cleanup")) implementation(project(":configuration")) implementation(project(":kotlinDsl")) From 96a6145ae99a7384b0cc48f91fe7f1428492d584 Mon Sep 17 00:00:00 2001 From: "Rodrigo B. de Oliveira" Date: Thu, 21 Mar 2019 12:36:39 -0300 Subject: [PATCH 658/853] Revert "Revert "Take advantage of type-safe accessors in precompiled script plugins"" This reverts commit cbe1b9ed3f28e6fb39feaba56e8140f490dc5a6b. --- .../src/main/kotlin/plugins/kotlin-dsl-module.gradle.kts | 5 ++--- .../kotlin/plugins/kotlin-dsl-plugin-bundle.gradle.kts | 2 +- .../gradlebuild/api-parameter-names-index.gradle.kts | 9 +++++++-- .../profiling/src/main/kotlin/gradlebuild/jmh.gradle.kts | 9 +++------ .../subprojects/uber-plugins/uber-plugins.gradle.kts | 1 + 5 files changed, 14 insertions(+), 12 deletions(-) diff --git a/buildSrc/subprojects/kotlin-dsl/src/main/kotlin/plugins/kotlin-dsl-module.gradle.kts b/buildSrc/subprojects/kotlin-dsl/src/main/kotlin/plugins/kotlin-dsl-module.gradle.kts index 5f813ac1fcfc3..b8a289cf4e792 100644 --- a/buildSrc/subprojects/kotlin-dsl/src/main/kotlin/plugins/kotlin-dsl-module.gradle.kts +++ b/buildSrc/subprojects/kotlin-dsl/src/main/kotlin/plugins/kotlin-dsl-module.gradle.kts @@ -29,9 +29,8 @@ plugins { } // including all sources -val main by sourceSets -tasks.named("jar") { - from(main.allSource) +tasks.jar { + from(sourceSets.main.get().allSource) manifest.attributes.apply { put("Implementation-Title", "Gradle Kotlin DSL (${project.name})") put("Implementation-Version", archiveVersion.get()) diff --git a/buildSrc/subprojects/kotlin-dsl/src/main/kotlin/plugins/kotlin-dsl-plugin-bundle.gradle.kts b/buildSrc/subprojects/kotlin-dsl/src/main/kotlin/plugins/kotlin-dsl-plugin-bundle.gradle.kts index 3e77884e4eb73..82ba52227d762 100644 --- a/buildSrc/subprojects/kotlin-dsl/src/main/kotlin/plugins/kotlin-dsl-plugin-bundle.gradle.kts +++ b/buildSrc/subprojects/kotlin-dsl/src/main/kotlin/plugins/kotlin-dsl-plugin-bundle.gradle.kts @@ -44,7 +44,7 @@ afterEvaluate { tasks { - "validateTaskProperties"(ValidateTaskProperties::class) { + validateTaskProperties { failOnWarning = true enableStricterValidation = true } diff --git a/buildSrc/subprojects/plugins/src/main/kotlin/gradlebuild/api-parameter-names-index.gradle.kts b/buildSrc/subprojects/plugins/src/main/kotlin/gradlebuild/api-parameter-names-index.gradle.kts index 0330e3a049d7e..a6b5b1b353276 100644 --- a/buildSrc/subprojects/plugins/src/main/kotlin/gradlebuild/api-parameter-names-index.gradle.kts +++ b/buildSrc/subprojects/plugins/src/main/kotlin/gradlebuild/api-parameter-names-index.gradle.kts @@ -35,7 +35,12 @@ val parameterNamesIndex by tasks.registering(ParameterNamesIndex::class) { if (file("src/main/groovy").isDirectory) { classpath.from(tasks.named("compileGroovy")) } - destinationFile.set(gradlebuildJava.generatedResourcesDir.resolve("${base.archivesBaseName}-parameter-names.properties")) + destinationFile.set( + gradlebuildJava.generatedResourcesDir.resolve("${base.archivesBaseName}-parameter-names.properties") + ) } -main.output.dir(gradlebuildJava.generatedResourcesDir, "builtBy" to parameterNamesIndex) +main.output.dir( + gradlebuildJava.generatedResourcesDir, + "builtBy" to parameterNamesIndex +) diff --git a/buildSrc/subprojects/profiling/src/main/kotlin/gradlebuild/jmh.gradle.kts b/buildSrc/subprojects/profiling/src/main/kotlin/gradlebuild/jmh.gradle.kts index 495069b114405..ad595d66c13ef 100644 --- a/buildSrc/subprojects/profiling/src/main/kotlin/gradlebuild/jmh.gradle.kts +++ b/buildSrc/subprojects/profiling/src/main/kotlin/gradlebuild/jmh.gradle.kts @@ -16,20 +16,17 @@ package gradlebuild -import me.champeau.gradle.JMHPluginExtension - plugins { id("me.champeau.gradle.jmh") } configurations { - - getByName("jmhImplementation") { - extendsFrom(configurations["implementation"]) + jmhImplementation { + extendsFrom(configurations.implementation.get()) } } -configure { +jmh { isIncludeTests = false resultFormat = "CSV" } diff --git a/buildSrc/subprojects/uber-plugins/uber-plugins.gradle.kts b/buildSrc/subprojects/uber-plugins/uber-plugins.gradle.kts index 5f3b98f189571..638966d400e1b 100644 --- a/buildSrc/subprojects/uber-plugins/uber-plugins.gradle.kts +++ b/buildSrc/subprojects/uber-plugins/uber-plugins.gradle.kts @@ -1,5 +1,6 @@ dependencies { implementation(project(":binaryCompatibility")) + implementation(project(":buildquality")) implementation(project(":cleanup")) implementation(project(":configuration")) implementation(project(":kotlinDsl")) From 3f711be2dcbeae74cf33742e78cec9a1a75cc4a2 Mon Sep 17 00:00:00 2001 From: Stefan Wolf Date: Thu, 21 Mar 2019 15:20:06 +0100 Subject: [PATCH 659/853] Allow receiving Provider for InputArtifact --- .../artifacts/transform/InputArtifact.java | 7 ++++- ...TransformIncrementalIntegrationTest.groovy | 10 +++---- ...sformValuesInjectionIntegrationTest.groovy | 29 +++++++++++++------ .../transform/DefaultTransformer.java | 29 ++++++++++++------- .../transform/DefaultTransformerInvoker.java | 19 ++++++++++-- .../transform/LegacyTransformer.java | 5 +++- .../artifacts/transform/Transformer.java | 4 ++- .../DefaultTransformerInvokerTest.groovy | 6 ++-- 8 files changed, 78 insertions(+), 31 deletions(-) diff --git a/subprojects/core-api/src/main/java/org/gradle/api/artifacts/transform/InputArtifact.java b/subprojects/core-api/src/main/java/org/gradle/api/artifacts/transform/InputArtifact.java index df27d71c1540d..478a3564dccb4 100644 --- a/subprojects/core-api/src/main/java/org/gradle/api/artifacts/transform/InputArtifact.java +++ b/subprojects/core-api/src/main/java/org/gradle/api/artifacts/transform/InputArtifact.java @@ -17,6 +17,7 @@ package org.gradle.api.artifacts.transform; import org.gradle.api.Incubating; +import org.gradle.api.provider.Provider; import org.gradle.api.reflect.InjectionPointQualifier; import java.io.File; @@ -29,12 +30,16 @@ /** * Attached to a property that should receive the input artifact for an artifact transform. This is the artifact that the transform should be applied to. * + *

    + * The input artifact can be injected as a plain {@link File} or a {@link Provider}<{@link org.gradle.api.file.FileSystemLocation}>. + *

    + * * @since 5.3 */ @Incubating @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.METHOD}) @Documented -@InjectionPointQualifier(supportedTypes = File.class) +@InjectionPointQualifier(supportedTypes = { File.class, Provider.class }) public @interface InputArtifact { } diff --git a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformIncrementalIntegrationTest.groovy b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformIncrementalIntegrationTest.groovy index 8caa7842a86a5..936e1135cd0b1 100644 --- a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformIncrementalIntegrationTest.groovy +++ b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformIncrementalIntegrationTest.groovy @@ -30,8 +30,8 @@ class ArtifactTransformIncrementalIntegrationTest extends AbstractDependencyReso import javax.inject.Inject import groovy.transform.CompileStatic import org.gradle.api.provider.* + import org.gradle.api.file.* import org.gradle.api.tasks.* - import org.gradle.api.tasks.incremental.* import org.gradle.api.artifacts.transform.* import org.gradle.work.* @@ -54,10 +54,10 @@ class ArtifactTransformIncrementalIntegrationTest extends AbstractDependencyReso abstract InputChanges getInputChanges() @InputArtifact - abstract File getInput() + abstract Provider getInput() void transform(TransformOutputs outputs) { - println "Transforming " + input.name + println "Transforming " + input.get().asFile.name println "incremental: " + inputChanges.incremental assert parameters.incrementalExecution.get() == inputChanges.incremental def changes = inputChanges.getFileChanges(input) @@ -67,7 +67,7 @@ class ArtifactTransformIncrementalIntegrationTest extends AbstractDependencyReso assert changes.findAll { it.changeType == ChangeType.MODIFIED }*.file as Set == resolveFiles(parameters.modifiedFiles.get()) def outputDirectory = outputs.dir("output") changes.each { change -> - if (change.file != input) { + if (change.file != input.get().asFile) { File outputFile = new File(outputDirectory, change.file.name) switch (change.changeType) { case ChangeType.ADDED: @@ -85,7 +85,7 @@ class ArtifactTransformIncrementalIntegrationTest extends AbstractDependencyReso } private resolveFiles(List files) { - files.collect { new File(input, it) } as Set + files.collect { new File(input.get().asFile, it) } as Set } } """ diff --git a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformValuesInjectionIntegrationTest.groovy b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformValuesInjectionIntegrationTest.groovy index a8d7d42e1141b..9fdd1190d9ab8 100644 --- a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformValuesInjectionIntegrationTest.groovy +++ b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/transform/ArtifactTransformValuesInjectionIntegrationTest.groovy @@ -16,10 +16,11 @@ package org.gradle.integtests.resolve.transform - +import com.google.common.reflect.TypeToken import org.gradle.api.artifacts.transform.InputArtifact import org.gradle.api.artifacts.transform.InputArtifactDependencies import org.gradle.api.file.FileCollection +import org.gradle.api.provider.Provider import org.gradle.api.tasks.Console import org.gradle.api.tasks.Destroys import org.gradle.api.tasks.Input @@ -40,7 +41,8 @@ import static org.gradle.util.Matchers.matchesRegexp class ArtifactTransformValuesInjectionIntegrationTest extends AbstractDependencyResolutionTest implements ArtifactTransformTestFixture { - def "transform can receive parameters, workspace and input artifact via abstract getter"() { + @Unroll + def "transform can receive parameters, workspace and input artifact (#inputArtifactType) via abstract getter"() { settingsFile << """ include 'a', 'b', 'c' """ @@ -73,11 +75,12 @@ class ArtifactTransformValuesInjectionIntegrationTest extends AbstractDependency } @InputArtifact - abstract File getInput() + abstract ${inputArtifactType} getInput() void transform(TransformOutputs outputs) { - println "processing \${input.name}" - def output = outputs.file(input.name + "." + parameters.extension) + File inputFile = input${convertToFile} + println "processing \${inputFile.name}" + def output = outputs.file(inputFile.name + "." + parameters.extension) output.text = "ok" } } @@ -90,6 +93,11 @@ class ArtifactTransformValuesInjectionIntegrationTest extends AbstractDependency outputContains("processing b.jar") outputContains("processing c.jar") outputContains("result = [b.jar.green, c.jar.green]") + + where: + inputArtifactType | convertToFile + 'File' | '' + 'Provider' | '.get().asFile' } @Unroll @@ -651,7 +659,7 @@ abstract class MakeGreen extends ArtifactTransform { } @Unroll - def "transform cannot use @InputArtifact to receive dependencies"() { + def "transform cannot use @InputArtifact to receive #propertyType"() { settingsFile << """ include 'a', 'b', 'c' """ @@ -666,10 +674,10 @@ project(':a') { abstract class MakeGreen implements TransformAction { @InputArtifact - abstract FileCollection getDependencies() + abstract ${propertyType instanceof Class ? propertyType.name : propertyType} getInput() void transform(TransformOutputs outputs) { - dependencies.files + input throw new RuntimeException("broken") } } @@ -682,7 +690,10 @@ abstract class MakeGreen implements TransformAction { // Documents existing behaviour. Should fail eagerly and with a better error message failure.assertHasDescription("Execution failed for task ':a:resolve'.") failure.assertHasCause("Execution failed for MakeGreen: ${file('b/build/b.jar')}.") - failure.assertHasCause("No service of type interface ${FileCollection.name} available.") + failure.assertHasCause("No service of type ${propertyType} available.") + + where: + propertyType << [FileCollection, new TypeToken>() {}.getType(), new TypeToken>() {}.getType()] } def "transform cannot use @Inject to receive input file"() { diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformer.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformer.java index eae67487ea0f4..4db3862926c98 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformer.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformer.java @@ -26,6 +26,7 @@ import org.gradle.api.artifacts.transform.TransformParameters; import org.gradle.api.artifacts.transform.VariantTransformConfigurationException; import org.gradle.api.file.FileCollection; +import org.gradle.api.file.FileSystemLocation; import org.gradle.api.internal.attributes.ImmutableAttributes; import org.gradle.api.internal.file.FileCollectionFactory; import org.gradle.api.internal.plugins.DslObject; @@ -38,6 +39,7 @@ import org.gradle.api.internal.tasks.properties.PropertyValue; import org.gradle.api.internal.tasks.properties.PropertyVisitor; import org.gradle.api.internal.tasks.properties.PropertyWalker; +import org.gradle.api.provider.Provider; import org.gradle.api.reflect.InjectionPointQualifier; import org.gradle.api.tasks.FileNormalizer; import org.gradle.internal.classloader.ClassLoaderHierarchyHasher; @@ -164,9 +166,9 @@ public HashCode getSecondaryInputHash() { } @Override - public ImmutableList transform(File inputArtifact, File outputDir, ArtifactTransformDependencies dependencies, @Nullable InputChanges inputChanges) { - TransformAction transformAction = newTransformAction(inputArtifact, dependencies, inputChanges); - DefaultTransformOutputs transformOutputs = new DefaultTransformOutputs(inputArtifact, outputDir); + public ImmutableList transform(Provider inputArtifactProvider, File outputDir, ArtifactTransformDependencies dependencies, @Nullable InputChanges inputChanges) { + TransformAction transformAction = newTransformAction(inputArtifactProvider, dependencies, inputChanges); + DefaultTransformOutputs transformOutputs = new DefaultTransformOutputs(inputArtifactProvider.get().getAsFile(), outputDir); transformAction.transform(transformOutputs); return transformOutputs.getRegisteredOutputs(); } @@ -278,8 +280,8 @@ private static String getParameterObjectDisplayName(Object parameterObject) { return ModelType.of(new DslObject(parameterObject).getDeclaredType()).getDisplayName(); } - private TransformAction newTransformAction(File inputFile, ArtifactTransformDependencies artifactTransformDependencies, @Nullable InputChanges inputChanges) { - ServiceLookup services = new TransformServiceLookup(inputFile, getIsolatedParameters().getIsolatedParameterObject().isolate(), requiresDependencies ? artifactTransformDependencies : null, inputChanges); + private TransformAction newTransformAction(Provider inputArtifactProvider, ArtifactTransformDependencies artifactTransformDependencies, @Nullable InputChanges inputChanges) { + ServiceLookup services = new TransformServiceLookup(inputArtifactProvider, getIsolatedParameters().getIsolatedParameterObject().isolate(), requiresDependencies ? artifactTransformDependencies : null, inputChanges); return instanceFactory.newInstance(services); } @@ -291,11 +293,14 @@ private IsolatedParameters getIsolatedParameters() { } private static class TransformServiceLookup implements ServiceLookup { + private static final Type FILE_SYSTEM_LOCATION_PROVIDER = new TypeToken>() {}.getType(); + private final ImmutableList injectionPoints; - public TransformServiceLookup(File inputFile, @Nullable TransformParameters parameters, @Nullable ArtifactTransformDependencies artifactTransformDependencies, @Nullable InputChanges inputChanges) { + public TransformServiceLookup(Provider inputFileProvider, @Nullable TransformParameters parameters, @Nullable ArtifactTransformDependencies artifactTransformDependencies, @Nullable InputChanges inputChanges) { ImmutableList.Builder builder = ImmutableList.builder(); - builder.add(InjectionPoint.injectedByAnnotation(InputArtifact.class, () -> inputFile)); + builder.add(InjectionPoint.injectedByAnnotation(InputArtifact.class, File.class, () -> inputFileProvider.get().getAsFile())); + builder.add(InjectionPoint.injectedByAnnotation(InputArtifact.class, FILE_SYSTEM_LOCATION_PROVIDER, () -> inputFileProvider)); if (parameters != null) { builder.add(InjectionPoint.injectedByType(parameters.getClass(), () -> parameters)); } else { @@ -349,18 +354,22 @@ public Object get(Type serviceType, Class annotatedWith) t private static class InjectionPoint { private final Class annotation; - private final Class injectedType; + private final Type injectedType; private final Supplier valueToInject; public static InjectionPoint injectedByAnnotation(Class annotation, Supplier valueToInject) { return new InjectionPoint(annotation, determineTypeFromAnnotation(annotation), valueToInject); } + public static InjectionPoint injectedByAnnotation(Class annotation, Type injectedType, Supplier valueToInject) { + return new InjectionPoint(annotation, injectedType, valueToInject); + } + public static InjectionPoint injectedByType(Class injectedType, Supplier valueToInject) { return new InjectionPoint(null, injectedType, valueToInject); } - private InjectionPoint(@Nullable Class annotation, Class injectedType, Supplier valueToInject) { + private InjectionPoint(@Nullable Class annotation, Type injectedType, Supplier valueToInject) { this.annotation = annotation; this.injectedType = injectedType; this.valueToInject = valueToInject; @@ -379,7 +388,7 @@ public Class getAnnotation() { return annotation; } - public Class getInjectedType() { + public Type getInjectedType() { return injectedType; } diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvoker.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvoker.java index 08d90ed4f097b..4bb5456cfb769 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvoker.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvoker.java @@ -20,11 +20,14 @@ import com.google.common.collect.ImmutableSortedMap; import org.gradle.api.UncheckedIOException; import org.gradle.api.artifacts.component.ProjectComponentIdentifier; +import org.gradle.api.file.FileSystemLocation; import org.gradle.api.file.RelativePath; import org.gradle.api.internal.artifacts.dsl.dependencies.ProjectFinder; import org.gradle.api.internal.artifacts.transform.TransformationWorkspaceProvider.TransformationWorkspace; import org.gradle.api.internal.file.FileCollectionFactory; import org.gradle.api.internal.project.ProjectInternal; +import org.gradle.api.internal.provider.Providers; +import org.gradle.api.provider.Provider; import org.gradle.caching.BuildCacheKey; import org.gradle.internal.Try; import org.gradle.internal.UncheckedException; @@ -233,6 +236,7 @@ private static class TransformerExecution implements UnitOfWork { private final ArtifactTransformDependencies dependencies; private final FileCollectionFingerprinter outputFingerprinter; private final Timer executionTimer; + private final Provider inputArtifactProvider; public TransformerExecution( Transformer transformer, @@ -255,6 +259,17 @@ public TransformerExecution( this.dependencies = dependencies; this.outputFingerprinter = outputFingerprinter; this.executionTimer = Time.startTimer(); + this.inputArtifactProvider = Providers.of(new FileSystemLocation() { + @Override + public File getAsFile() { + return inputArtifact; + } + + @Override + public String toString() { + return inputArtifact.toString(); + } + }); } @Override @@ -267,7 +282,7 @@ public WorkResult execute(@Nullable InputChangesInternal inputChanges) { GFileUtils.cleanDirectory(outputDir); GFileUtils.deleteFileQuietly(resultsFile); } - ImmutableList result = transformer.transform(inputArtifact, outputDir, dependencies, inputChanges); + ImmutableList result = transformer.transform(inputArtifactProvider, outputDir, dependencies, inputChanges); writeResultsFile(outputDir, resultsFile, result); return WorkResult.DID_WORK; } @@ -326,7 +341,7 @@ public Optional getTimeout() { @Override public void visitInputFileProperties(InputFilePropertyVisitor visitor) { - visitor.visitInputFileProperty(INPUT_ARTIFACT_PROPERTY_NAME, inputArtifact, true); + visitor.visitInputFileProperty(INPUT_ARTIFACT_PROPERTY_NAME, inputArtifactProvider, true); } @Override diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/LegacyTransformer.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/LegacyTransformer.java index cdcf1d59b67fd..4f6d5ea606c9d 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/LegacyTransformer.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/LegacyTransformer.java @@ -19,8 +19,10 @@ import com.google.common.collect.ImmutableList; import org.gradle.api.InvalidUserDataException; import org.gradle.api.artifacts.transform.ArtifactTransform; +import org.gradle.api.file.FileSystemLocation; import org.gradle.api.internal.attributes.ImmutableAttributes; import org.gradle.api.internal.tasks.TaskDependencyResolveContext; +import org.gradle.api.provider.Provider; import org.gradle.api.tasks.FileNormalizer; import org.gradle.internal.classloader.ClassLoaderHierarchyHasher; import org.gradle.internal.fingerprint.AbsolutePathInputNormalizer; @@ -66,7 +68,8 @@ public boolean isCacheable() { } @Override - public ImmutableList transform(File inputArtifact, File outputDir, ArtifactTransformDependencies dependencies, @Nullable InputChanges inputChanges) { + public ImmutableList transform(Provider inputArtifactProvider, File outputDir, ArtifactTransformDependencies dependencies, @Nullable InputChanges inputChanges) { + File inputArtifact = inputArtifactProvider.get().getAsFile(); ArtifactTransform transformer = newTransformer(); transformer.setOutputDirectory(outputDir); List outputs = transformer.transform(inputArtifact); diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/Transformer.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/Transformer.java index 95b0b07695fde..360405f66073e 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/Transformer.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/Transformer.java @@ -19,8 +19,10 @@ import com.google.common.collect.ImmutableList; import org.gradle.api.Describable; import org.gradle.api.artifacts.transform.ArtifactTransform; +import org.gradle.api.file.FileSystemLocation; import org.gradle.api.internal.attributes.ImmutableAttributes; import org.gradle.api.internal.tasks.TaskDependencyContainer; +import org.gradle.api.provider.Provider; import org.gradle.api.tasks.FileNormalizer; import org.gradle.internal.fingerprint.FileCollectionFingerprinterRegistry; import org.gradle.internal.hash.HashCode; @@ -54,7 +56,7 @@ public interface Transformer extends Describable, TaskDependencyContainer { */ boolean isCacheable(); - ImmutableList transform(File inputArtifact, File outputDir, ArtifactTransformDependencies dependencies, @Nullable InputChanges inputChanges); + ImmutableList transform(Provider inputArtifactProvider, File outputDir, ArtifactTransformDependencies dependencies, @Nullable InputChanges inputChanges); /** * The hash of the secondary inputs of the transformer. diff --git a/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvokerTest.groovy b/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvokerTest.groovy index 8d317b41bcf30..6766be675c48a 100644 --- a/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvokerTest.groovy +++ b/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvokerTest.groovy @@ -18,6 +18,7 @@ package org.gradle.api.internal.artifacts.transform import com.google.common.collect.ImmutableList import org.gradle.api.artifacts.transform.ArtifactTransform +import org.gradle.api.file.FileSystemLocation import org.gradle.api.internal.artifacts.DefaultBuildIdentifier import org.gradle.api.internal.artifacts.DefaultProjectComponentIdentifier import org.gradle.api.internal.artifacts.dsl.dependencies.ProjectFinder @@ -27,6 +28,7 @@ import org.gradle.api.internal.changedetection.state.DefaultWellKnownFileLocatio import org.gradle.api.internal.file.TestFiles import org.gradle.api.internal.project.ProjectInternal import org.gradle.api.internal.tasks.TaskDependencyResolveContext +import org.gradle.api.provider.Provider import org.gradle.api.tasks.FileNormalizer import org.gradle.internal.classloader.ClassLoaderHierarchyHasher import org.gradle.internal.component.local.model.ComponentFileArtifactIdentifier @@ -137,8 +139,8 @@ class DefaultTransformerInvokerTest extends AbstractProjectBuilderSpec { } @Override - ImmutableList transform(File inputArtifact, File outputDir, ArtifactTransformDependencies dependencies, InputChanges inputChanges) { - return ImmutableList.copyOf(transformationAction.apply(inputArtifact, outputDir)) + ImmutableList transform(Provider inputArtifactProvider, File outputDir, ArtifactTransformDependencies dependencies, InputChanges inputChanges) { + return ImmutableList.copyOf(transformationAction.apply(inputArtifactProvider.get().asFile, outputDir)) } @Override From 4b9501879dc3684e91492768a18375e3ed26255e Mon Sep 17 00:00:00 2001 From: Stefan Wolf Date: Thu, 21 Mar 2019 16:36:31 +0100 Subject: [PATCH 660/853] Require lazy types for querying input changes --- .../org/gradle/api/tasks/SkipWhenEmpty.java | 2 +- .../java/org/gradle/work/Incremental.java | 2 +- .../java/org/gradle/work/InputChanges.java | 44 ++++++++++++------- ...ractIncrementalTasksIntegrationTest.groovy | 2 +- .../IncrementalInputsIntegrationTest.groovy | 8 ++-- .../changes/IncrementalInputChanges.java | 14 +++++- .../changes/NonIncrementalInputChanges.java | 14 +++++- .../NonIncrementalInputChangesTest.groovy | 7 ++- 8 files changed, 67 insertions(+), 26 deletions(-) diff --git a/subprojects/core-api/src/main/java/org/gradle/api/tasks/SkipWhenEmpty.java b/subprojects/core-api/src/main/java/org/gradle/api/tasks/SkipWhenEmpty.java index 87e89fa44b44c..96c8200999aa6 100644 --- a/subprojects/core-api/src/main/java/org/gradle/api/tasks/SkipWhenEmpty.java +++ b/subprojects/core-api/src/main/java/org/gradle/api/tasks/SkipWhenEmpty.java @@ -27,7 +27,7 @@ * *

    If all of the inputs declared with this annotation are empty, the task will be skipped with a "NO-SOURCE" message.

    * - *

    Inputs annotated with this annotation can be queried for changes via {@link org.gradle.work.InputChanges#getFileChanges(Object)}.

    + *

    Inputs annotated with this annotation can be queried for changes via {@link org.gradle.work.InputChanges#getFileChanges(org.gradle.api.file.FileCollection)}.

    * *

    This annotation should be attached to the getter method in Java or the property in Groovy. * Annotations on setters or just the field in Java are ignored.

    diff --git a/subprojects/core-api/src/main/java/org/gradle/work/Incremental.java b/subprojects/core-api/src/main/java/org/gradle/work/Incremental.java index 62b1f54bfc870..e2f1abbc8d7ff 100644 --- a/subprojects/core-api/src/main/java/org/gradle/work/Incremental.java +++ b/subprojects/core-api/src/main/java/org/gradle/work/Incremental.java @@ -28,7 +28,7 @@ * Track input changes for the annotated parameter. * *

    - * Inputs annotated with {@link Incremental} can be queried for changes via {@link InputChanges#getFileChanges(Object)}. + * Inputs annotated with {@link Incremental} can be queried for changes via {@link InputChanges#getFileChanges(org.gradle.api.file.FileCollection)}. *

    * * @since 5.4 diff --git a/subprojects/core-api/src/main/java/org/gradle/work/InputChanges.java b/subprojects/core-api/src/main/java/org/gradle/work/InputChanges.java index 679aa710d7715..f802743734ff9 100644 --- a/subprojects/core-api/src/main/java/org/gradle/work/InputChanges.java +++ b/subprojects/core-api/src/main/java/org/gradle/work/InputChanges.java @@ -17,6 +17,9 @@ package org.gradle.work; import org.gradle.api.Incubating; +import org.gradle.api.file.FileCollection; +import org.gradle.api.file.FileSystemLocation; +import org.gradle.api.provider.Provider; /** * Provides access to any input files that need to be processed by an incremental work action. @@ -26,9 +29,9 @@ * The work action can then query what changed for an input parameter since the last execution to only process the changes. * *
    - * class IncrementalReverseTask extends DefaultTask {
    + * abstract class IncrementalReverseTask extends DefaultTask {
      *     {@literal @}InputDirectory
    - *     def File inputDir
    + *     abstract DirectoryProperty getInputDir()
      *
      *     {@literal @}OutputDirectory
      *     def File outputDir
    @@ -40,16 +43,14 @@
      *         }
      *
      *         inputChanges.getFileChanges(inputDir).each { change ->
    - *             switch (change.changeType) {
    - *                 case REMOVED:
    - *                     def targetFile = project.file("$outputDir/${change.file.name}")
    - *                     if (targetFile.exists()) {
    - *                         targetFile.delete()
    - *                     }
    - *                     break
    - *                 default:
    - *                     def targetFile = project.file("$outputDir/${change.file.name}")
    - *                     targetFile.text = change.file.text.reverse()
    + *             if (change.changeType == ChangeType.REMOVED) {
    + *                 def targetFile = project.file("$outputDir/${change.file.name}")
    + *                 if (targetFile.exists()) {
    + *                     targetFile.delete()
    + *                 }
    + *             } else {
    + *                 def targetFile = project.file("$outputDir/${change.file.name}")
    + *                 targetFile.text = change.file.text.reverse()
      *             }
      *         }
      *     }
    @@ -76,13 +77,13 @@ public interface InputChanges {
          * When true:
          * 

    *
      - *
    • {@link #getFileChanges(Object)} reports changes to the input files compared to the previous execution.
    • + *
    • {@link #getFileChanges(FileCollection)} and {@link #getFileChanges(Provider)} report changes to the input files compared to the previous execution.
    • *
    *

    * When false: *

    *
      - *
    • Every input file is reported via {@link #getFileChanges(Object)} as if it was {@link ChangeType#ADDED}.
    • + *
    • Every input file is reported via {@link #getFileChanges(FileCollection)} and {@link #getFileChanges(Provider)} as if it was {@link ChangeType#ADDED}.
    • *
    */ boolean isIncremental(); @@ -98,5 +99,18 @@ public interface InputChanges { * * @param parameterValue The value of the parameter to query. */ - Iterable getFileChanges(Object parameterValue); + Iterable getFileChanges(FileCollection parameterValue); + + /** + * Changes for a parameter. + * + *

    When {@link #isIncremental()} is {@code false}, then all elements of the parameter are returned as {@link ChangeType#ADDED}.

    + * + *

    + * Only input file properties annotated with {@link Incremental} or {@link org.gradle.api.tasks.SkipWhenEmpty} can be queried for changes. + *

    + * + * @param parameterValue The value of the parameter to query. + */ + Iterable getFileChanges(Provider parameterValue); } diff --git a/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/AbstractIncrementalTasksIntegrationTest.groovy b/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/AbstractIncrementalTasksIntegrationTest.groovy index caaa44535397a..00898644e735b 100644 --- a/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/AbstractIncrementalTasksIntegrationTest.groovy +++ b/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/AbstractIncrementalTasksIntegrationTest.groovy @@ -57,7 +57,7 @@ abstract class AbstractIncrementalTasksIntegrationTest extends AbstractIntegrati abstract class BaseIncrementalTask extends DefaultTask { ${inputDirAnnotation} @InputDirectory - def File inputDir + abstract DirectoryProperty getInputDir() @TaskAction $taskAction diff --git a/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/IncrementalInputsIntegrationTest.groovy b/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/IncrementalInputsIntegrationTest.groovy index 151f0a427f1eb..c31c295eaa4f1 100644 --- a/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/IncrementalInputsIntegrationTest.groovy +++ b/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/IncrementalInputsIntegrationTest.groovy @@ -85,10 +85,10 @@ class IncrementalInputsIntegrationTest extends AbstractIncrementalTasksIntegrati @Issue("https://github.com/gradle/gradle/issues/4166") def "file in input dir appears in task inputs for #inputAnnotation"() { buildFile << """ - class MyTask extends DefaultTask { + abstract class MyTask extends DefaultTask { @${inputAnnotation} @Incremental - File input + abstract DirectoryProperty getInput() @OutputFile File output @@ -129,7 +129,7 @@ class IncrementalInputsIntegrationTest extends AbstractIncrementalTasksIntegrati abstract class WithNonIncrementalInput extends BaseIncrementalTask { @InputFile - File nonIncrementalInput + abstract RegularFileProperty getNonIncrementalInput() @Override void execute(InputChanges inputChanges) { @@ -146,7 +146,7 @@ class IncrementalInputsIntegrationTest extends AbstractIncrementalTasksIntegrati expect: fails("withNonIncrementalInput") - failure.assertHasCause("Cannot query incremental changes: No property found for value ${file("nonIncremental").absolutePath}. Incremental properties: inputDir.") + failure.assertHasCause("Cannot query incremental changes: No property found for value property(interface org.gradle.api.file.RegularFile, fixed(class org.gradle.api.internal.file.DefaultFilePropertyFactory\$FixedFile, ${file( "nonIncremental").absolutePath})). Incremental properties: inputDir.") } def "changes to non-incremental input parameters cause a rebuild"() { diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/IncrementalInputChanges.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/IncrementalInputChanges.java index 1be651e8a21a0..10b9a2b419682 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/IncrementalInputChanges.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/IncrementalInputChanges.java @@ -16,6 +16,9 @@ package org.gradle.internal.execution.history.changes; +import org.gradle.api.file.FileCollection; +import org.gradle.api.file.FileSystemLocation; +import org.gradle.api.provider.Provider; import org.gradle.api.tasks.incremental.InputFileDetails; import org.gradle.internal.Cast; import org.gradle.internal.change.CollectingChangeVisitor; @@ -37,7 +40,16 @@ public boolean isIncremental() { } @Override - public Iterable getFileChanges(Object parameterValue) { + public Iterable getFileChanges(FileCollection parameterValue) { + return getObjectFileChanges(parameterValue); + } + + @Override + public Iterable getFileChanges(Provider parameterValue) { + return getObjectFileChanges(parameterValue); + } + + private Iterable getObjectFileChanges(Object parameterValue) { String propertyName = incrementalInputProperties.getPropertyNameFor(parameterValue); CollectingChangeVisitor visitor = new CollectingChangeVisitor(); changes.accept(propertyName, visitor); diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/NonIncrementalInputChanges.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/NonIncrementalInputChanges.java index 08a6c6ad399fc..1e302d7f5aab9 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/NonIncrementalInputChanges.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/NonIncrementalInputChanges.java @@ -17,6 +17,9 @@ package org.gradle.internal.execution.history.changes; import com.google.common.collect.ImmutableSortedMap; +import org.gradle.api.file.FileCollection; +import org.gradle.api.file.FileSystemLocation; +import org.gradle.api.provider.Provider; import org.gradle.api.tasks.incremental.InputFileDetails; import org.gradle.internal.Cast; import org.gradle.internal.fingerprint.CurrentFileCollectionFingerprint; @@ -41,7 +44,16 @@ public boolean isIncremental() { } @Override - public Iterable getFileChanges(Object parameterValue) { + public Iterable getFileChanges(FileCollection parameterValue) { + return getObjectFileChanges(parameterValue); + } + + @Override + public Iterable getFileChanges(Provider parameterValue) { + return getObjectFileChanges(parameterValue); + } + + public Iterable getObjectFileChanges(Object parameterValue) { CurrentFileCollectionFingerprint currentFileCollectionFingerprint = currentInputs.get(incrementalInputProperties.getPropertyNameFor(parameterValue)); return () -> getAllFileChanges(currentFileCollectionFingerprint).iterator(); } diff --git a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/history/changes/NonIncrementalInputChangesTest.groovy b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/history/changes/NonIncrementalInputChangesTest.groovy index f932b01a1d521..f77a4b6213937 100644 --- a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/history/changes/NonIncrementalInputChangesTest.groovy +++ b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/history/changes/NonIncrementalInputChangesTest.groovy @@ -18,6 +18,8 @@ package org.gradle.internal.execution.history.changes import com.google.common.collect.ImmutableBiMap import com.google.common.collect.ImmutableSortedMap +import org.gradle.api.file.FileSystemLocation +import org.gradle.api.provider.Provider import org.gradle.internal.fingerprint.CurrentFileCollectionFingerprint import org.gradle.internal.fingerprint.impl.AbsolutePathFingerprintingStrategy import org.gradle.internal.fingerprint.impl.DefaultCurrentFileCollectionFingerprint @@ -30,12 +32,13 @@ class NonIncrementalInputChangesTest extends Specification { def "can iterate changes more than once"() { def fingerprint = DefaultCurrentFileCollectionFingerprint.from([new RegularFileSnapshot("/some/where", "where", HashCode.fromInt(1234), 0)], AbsolutePathFingerprintingStrategy.INCLUDE_MISSING) - def changes = new NonIncrementalInputChanges(ImmutableSortedMap.of("input", fingerprint), new DefaultIncrementalInputProperties(ImmutableBiMap.of("input", "value"))) + Provider value = Mock() + def changes = new NonIncrementalInputChanges(ImmutableSortedMap.of("input", fingerprint), new DefaultIncrementalInputProperties(ImmutableBiMap.of("input", value))) def expectedChangedFiles = [new File("/some/where")] when: def allFileChanges = changes.allFileChanges - def fileChanges = changes.getFileChanges("value") + def fileChanges = changes.getFileChanges(value) then: allFileChanges*.file == expectedChangedFiles From 32d844260586e831d01db6a767a9747eec7dd486 Mon Sep 17 00:00:00 2001 From: Paul Merlin Date: Thu, 21 Mar 2019 17:34:48 +0100 Subject: [PATCH 661/853] Disable buildSrc verification tasks by default enable them on CI by default allow to control whether they are enabled via a project property Signed-off-by: Paul Merlin --- buildSrc/build.gradle.kts | 23 +++++++++++++++---- .../GradleInceptionPerformanceTest.groovy | 2 +- 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts index 109fc924a69d4..ea7c3c8bcc1bd 100644 --- a/buildSrc/build.gradle.kts +++ b/buildSrc/build.gradle.kts @@ -95,8 +95,25 @@ dependencies { } } -// Set gradlebuild.skipBuildSrcChecks Gradle property to "true" to disable all buildSrc verification tasks -if (findProperty("gradlebuild.skipBuildSrcChecks") == "true") { + +// TODO Avoid duplication of what defines a CI Server with BuildEnvironment +val isCiServer: Boolean by extra { "CI" in System.getenv() } + + +/** + * Controls whether verification tasks are skipped. + * + * Set the `buildSrcCheck` Gradle property to `true` to run the verification tasks. + * Set it to `false` to skip the verification tasks. + * + * When that property is unset, defaults to `false` on CI, to `true` otherwise. + */ +val isSkipBuildSrcVerification: Boolean = + (findProperty("buildSrcCheck") as String?) + ?.let { it == "false" } + ?: !isCiServer + +if (isSkipBuildSrcVerification) { allprojects { tasks.matching { it.group == LifecycleBasePlugin.VERIFICATION_GROUP }.configureEach { enabled = false @@ -104,8 +121,6 @@ if (findProperty("gradlebuild.skipBuildSrcChecks") == "true") { } } -// TODO Avoid duplication of what defines a CI Server with BuildEnvironment -val isCiServer: Boolean by extra { "CI" in System.getenv() } if (isCiServer) { gradle.buildFinished { allprojects.forEach { project -> diff --git a/subprojects/performance/src/performanceTest/groovy/org/gradle/performance/regression/inception/GradleInceptionPerformanceTest.groovy b/subprojects/performance/src/performanceTest/groovy/org/gradle/performance/regression/inception/GradleInceptionPerformanceTest.groovy index 20443abaede98..f82cf48c3663b 100644 --- a/subprojects/performance/src/performanceTest/groovy/org/gradle/performance/regression/inception/GradleInceptionPerformanceTest.groovy +++ b/subprojects/performance/src/performanceTest/groovy/org/gradle/performance/regression/inception/GradleInceptionPerformanceTest.groovy @@ -82,7 +82,7 @@ class GradleInceptionPerformanceTest extends AbstractCrossVersionPerformanceTest runner.testProject = testProject runner.tasksToRun = ['help'] runner.runs = runs - runner.args = extraGradleBuildArguments() + ["-Pgradlebuild.skipBuildSrcChecks=true"] + runner.args = extraGradleBuildArguments() + ["-buildSrcCheck=false"] and: def changingClassFilePath = "buildSrc/${buildSrcProjectDir}src/main/groovy/ChangingClass.groovy" From 1ceefbf5fd711a013e7d6a12c64ca17814a7e06b Mon Sep 17 00:00:00 2001 From: Paul Merlin Date: Thu, 21 Mar 2019 17:46:15 +0100 Subject: [PATCH 662/853] Mention how to run buildSrc checks in CONTRIBUTING Signed-off-by: Paul Merlin --- CONTRIBUTING.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 8ead4df62f0b5..e22eb13c049c8 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -100,6 +100,8 @@ Install: `./gradlew install -Pgradle_installPath=/any/path`. Use: `/any/path/bin You can debug Gradle by adding `-Dorg.gradle.debug=true` when executing. Gradle will wait for you to attach a debugger at `localhost:5005` by default. +If you made changes to build logic in `buildSrc`, you can test them by executing `./gradlew help -PbuildSrcCheck=true`. + ### Creating Commits And Writing Commit Messages The commit messages that accompany your code changes are an important piece of documentation, please follow these guidelines when writing commit messages: From 5fbadd36f19fac4ec4dfca2c69d634233223385c Mon Sep 17 00:00:00 2001 From: Stefan Oehme Date: Thu, 21 Mar 2019 20:23:49 +0100 Subject: [PATCH 663/853] Move Maven plugin configuration to parent POM That way it can be easily changed in one place to do quick experiments. --- .../generator/FileContentGenerator.groovy | 34 +++++++++++-------- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/subprojects/internal-performance-testing/src/main/groovy/org/gradle/performance/generator/FileContentGenerator.groovy b/subprojects/internal-performance-testing/src/main/groovy/org/gradle/performance/generator/FileContentGenerator.groovy index d6beac944176d..a1b98f86e4ebd 100644 --- a/subprojects/internal-performance-testing/src/main/groovy/org/gradle/performance/generator/FileContentGenerator.groovy +++ b/subprojects/internal-performance-testing/src/main/groovy/org/gradle/performance/generator/FileContentGenerator.groovy @@ -119,20 +119,7 @@ abstract class FileContentGenerator { ${(0..config.subProjects - 1).collect { "project$it" }.join("\n ")} - """ - } else { - def subProjectNumbers = dependencyTree.getChildProjectIds(subProjectNumber) - def subProjectDependencies = '' - if (subProjectNumbers?.size() > 0) { - subProjectDependencies = subProjectNumbers.collect { convertToPomDependency("org.gradle.test.performance:project$it:1.0") }.join() - } - body = """ - - ${config.externalApiDependencies.collect { convertToPomDependency(it) }.join()} - ${config.externalImplementationDependencies.collect { convertToPomDependency(it) }.join()} - ${convertToPomDependency('junit:junit:4.12', 'test')} - ${subProjectDependencies} - + @@ -174,6 +161,25 @@ abstract class FileContentGenerator { """ + } else { + def subProjectNumbers = dependencyTree.getChildProjectIds(subProjectNumber) + def subProjectDependencies = '' + if (subProjectNumbers?.size() > 0) { + subProjectDependencies = subProjectNumbers.collect { convertToPomDependency("org.gradle.test.performance:project$it:1.0") }.join() + } + body = """ + + org.gradle.test.performance + project + 1.0 + + + ${config.externalApiDependencies.collect { convertToPomDependency(it) }.join()} + ${config.externalImplementationDependencies.collect { convertToPomDependency(it) }.join()} + ${convertToPomDependency('junit:junit:4.12', 'test')} + ${subProjectDependencies} + + """ } """ Date: Thu, 21 Mar 2019 17:53:36 -0400 Subject: [PATCH 664/853] Use convention instead of set to set default value for AbstractArchiveTasks Fixes https://github.com/gradle/gradle/issues/8831 --- .../plugins/BasePluginIntegrationTest.groovy | 20 +++++++++++++++++++ .../org/gradle/api/plugins/BasePlugin.java | 4 ++-- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/subprojects/plugins/src/integTest/groovy/org/gradle/api/plugins/BasePluginIntegrationTest.groovy b/subprojects/plugins/src/integTest/groovy/org/gradle/api/plugins/BasePluginIntegrationTest.groovy index 326970bae51d3..4cd54a0b7be75 100644 --- a/subprojects/plugins/src/integTest/groovy/org/gradle/api/plugins/BasePluginIntegrationTest.groovy +++ b/subprojects/plugins/src/integTest/groovy/org/gradle/api/plugins/BasePluginIntegrationTest.groovy @@ -79,4 +79,24 @@ class BasePluginIntegrationTest extends AbstractIntegrationSpec { expect: succeeds "tasks" } + + def "can override archiveBaseName in custom Jar task"() { + buildFile << """ + apply plugin: 'base' + class MyJar extends Jar { + MyJar() { + super() + archiveBaseName.set("myjar") + } + } + task myJar(type: MyJar) + task assertCheck { + doLast { + assert tasks.myJar.archiveBaseName.get() == "myjar" + } + } + """ + expect: + succeeds("assertCheck") + } } diff --git a/subprojects/plugins/src/main/java/org/gradle/api/plugins/BasePlugin.java b/subprojects/plugins/src/main/java/org/gradle/api/plugins/BasePlugin.java index c3577dd3c2952..4f0203071cb06 100644 --- a/subprojects/plugins/src/main/java/org/gradle/api/plugins/BasePlugin.java +++ b/subprojects/plugins/src/main/java/org/gradle/api/plugins/BasePlugin.java @@ -103,14 +103,14 @@ public String call() { } task.getDestinationDirectory().convention(project.getLayout().getBuildDirectory().dir(project.provider(destinationDir))); - task.getArchiveVersion().set(project.provider(new Callable() { + task.getArchiveVersion().convention(project.provider(new Callable() { @Nullable public String call() { return project.getVersion() == Project.DEFAULT_VERSION ? null : project.getVersion().toString(); } })); - task.getArchiveBaseName().set(project.provider(new Callable() { + task.getArchiveBaseName().convention(project.provider(new Callable() { public String call() { return pluginConvention.getArchivesBaseName(); } From fd7796c3c068becf103fe7b3e39903e6bf7c4742 Mon Sep 17 00:00:00 2001 From: Sterling Greene Date: Thu, 21 Mar 2019 17:29:47 -0400 Subject: [PATCH 665/853] Synchronize access to System Properties when creating SSLContexts --- .../SystemPropertiesIntegrationTest.groovy | 25 +++++++- .../org/gradle/internal/SystemProperties.java | 63 ++++++++++++++++--- .../http/DefaultSslContextFactory.java | 36 ++++++++++- 3 files changed, 115 insertions(+), 9 deletions(-) diff --git a/subprojects/base-services/src/integTest/groovy/org/gradle/internal/SystemPropertiesIntegrationTest.groovy b/subprojects/base-services/src/integTest/groovy/org/gradle/internal/SystemPropertiesIntegrationTest.groovy index 6f662b5142ca3..aa57b7cb26964 100644 --- a/subprojects/base-services/src/integTest/groovy/org/gradle/internal/SystemPropertiesIntegrationTest.groovy +++ b/subprojects/base-services/src/integTest/groovy/org/gradle/internal/SystemPropertiesIntegrationTest.groovy @@ -88,7 +88,6 @@ class SystemPropertiesIntegrationTest extends ConcurrentSpec { assert System.getProperty(notsetPropertyName) == null } - def "withProperty and withProperties are never run concurrently"() { final int threadCount = 100 def id = UUID.randomUUID().toString() @@ -112,4 +111,28 @@ class SystemPropertiesIntegrationTest extends ConcurrentSpec { then: noExceptionThrown() } + + def "withProperties(Map) and withProperties are never run concurrently"() { + final int threadCount = 100 + def id = UUID.randomUUID().toString() + + when: + async { + threadCount.times { i -> + start { + SystemProperties.instance.withSystemProperties((id): "bar", {"baz"}) + } + start { + SystemProperties.instance.withSystemProperties { + System.properties.each { + assert it.key != id + } + } + } + } + } + + then: + noExceptionThrown() + } } diff --git a/subprojects/base-services/src/main/java/org/gradle/internal/SystemProperties.java b/subprojects/base-services/src/main/java/org/gradle/internal/SystemProperties.java index 7910c23d89da7..d1b8f057c64c9 100644 --- a/subprojects/base-services/src/main/java/org/gradle/internal/SystemProperties.java +++ b/subprojects/base-services/src/main/java/org/gradle/internal/SystemProperties.java @@ -15,9 +15,13 @@ */ package org.gradle.internal; +import com.google.common.collect.Maps; + +import javax.annotation.Nullable; import java.io.File; import java.util.Collections; import java.util.HashSet; +import java.util.Map; import java.util.Set; @@ -116,28 +120,73 @@ public T withJavaHome(File javaHomeDir, Factory factory) { * @param factory Instance created by the Factory implementation */ public synchronized T withSystemProperty(String propertyName, String value, Factory factory) { - String originalValue = System.getProperty(propertyName); - System.setProperty(propertyName, value); + String originalValue = overrideProperty(propertyName, value); try { return factory.create(); } finally { - if (originalValue != null) { - System.setProperty(propertyName, originalValue); - } else { - System.clearProperty(propertyName); - } + restoreProperty(propertyName, originalValue); } } /** * Provides safe access to the system properties, preventing concurrent {@link #withSystemProperty(String, String, Factory)} calls. + * * This can be used to wrap 3rd party APIs that iterate over the system properties, so they won't result in {@link java.util.ConcurrentModificationException}s. + * + * This method should not be used when you need to temporarily change system properties. */ public synchronized T withSystemProperties(Factory factory) { return factory.create(); } + /** + * Provides safe access to the system properties, preventing concurrent calls to change system properties. + * + * This can be used to wrap 3rd party APIs that iterate over the system properties, so they won't result in {@link java.util.ConcurrentModificationException}s. + * + * This method can be used to override system properties temporarily. The original values of the given system properties are restored before returning. + */ + public synchronized T withSystemProperties(Map properties, Factory factory) { + Map originalProperties = Maps.newHashMap(); + for (Map.Entry property : properties.entrySet()) { + String propertyName = property.getKey(); + String value = property.getValue(); + String originalValue = overrideProperty(propertyName, value); + originalProperties.put(propertyName, originalValue); + } + + try { + return factory.create(); + } finally { + for (Map.Entry property : originalProperties.entrySet()) { + String propertyName = property.getKey(); + String originalValue = property.getValue(); + restoreProperty(propertyName, originalValue); + } + } + } + + @Nullable + private String overrideProperty(String propertyName, String value) { + // Overwrite property + String originalValue = System.getProperty(propertyName); + if (value != null) { + System.setProperty(propertyName, value); + } else { + System.clearProperty(propertyName); + } + return originalValue; + } + + private void restoreProperty(String propertyName, @Nullable String originalValue) { + if (originalValue != null) { + System.setProperty(propertyName, originalValue); + } else { + System.clearProperty(propertyName); + } + } + /** * Returns true if the given key is guaranteed to be contained in System.getProperties() by default, * as specified in the Javadoc for that method. diff --git a/subprojects/resources-http/src/main/java/org/gradle/internal/resource/transport/http/DefaultSslContextFactory.java b/subprojects/resources-http/src/main/java/org/gradle/internal/resource/transport/http/DefaultSslContextFactory.java index 477b088876163..f8435f11df258 100644 --- a/subprojects/resources-http/src/main/java/org/gradle/internal/resource/transport/http/DefaultSslContextFactory.java +++ b/subprojects/resources-http/src/main/java/org/gradle/internal/resource/transport/http/DefaultSslContextFactory.java @@ -52,7 +52,9 @@ public class DefaultSslContextFactory implements SslContextFactory { "java.home" ); - private LoadingCache, SSLContext> cache = CacheBuilder.newBuilder().softValues().build(new SslContextCacheLoader()); + private LoadingCache, SSLContext> cache = CacheBuilder.newBuilder().softValues().build( + new SynchronizedSystemPropertiesCacheLoader(new SslContextCacheLoader()) + ); @Override public SSLContext createSslContext() { @@ -72,9 +74,41 @@ public Map create() { }); } + private static class SynchronizedSystemPropertiesCacheLoader extends CacheLoader, SSLContext> { + private final SslContextCacheLoader delegate; + + private SynchronizedSystemPropertiesCacheLoader(SslContextCacheLoader delegate) { + this.delegate = delegate; + } + + @Override + public SSLContext load(Map props) { + /* + * NOTE! The JDK code to create SSLContexts relies on the values of the given system properties. + * + * To prevent concurrent changes to system properties from interfering with this, we need to synchronize access/modifications + * to system properties. This is best effort since we can't prevent user code from modifying system properties willy-nilly. + * + * The most critical system property is java.home. Changing this property while trying to create a SSLContext can cause many strange + * problems: + * https://github.com/gradle/gradle/issues/8830 + * https://github.com/gradle/gradle/issues/8039 + * https://github.com/gradle/gradle/issues/7842 + * https://github.com/gradle/gradle/issues/2588 + */ + return SystemProperties.getInstance().withSystemProperties(props, new Factory() { + @Override + public SSLContext create() { + return delegate.load(props); + } + }); + } + } + private static class SslContextCacheLoader extends CacheLoader, SSLContext> { @Override public SSLContext load(Map props) { + // TODO: We should see if we can go back to using HttpClient again. // This implementation is borrowed from the Apache HttpClient project // https://github.com/apache/httpclient/blob/4.2.2/httpclient/src/main/java/org/apache/http/conn/ssl/SSLSocketFactory.java#L246-L354 try { From c35877528be63106e36ee5244f4afc10cde3017e Mon Sep 17 00:00:00 2001 From: Sterling Greene Date: Thu, 21 Mar 2019 18:21:50 -0400 Subject: [PATCH 666/853] Add release notes for JDK12 support --- subprojects/docs/src/docs/release/notes-template.md | 4 ++++ subprojects/docs/src/docs/release/release-features.txt | 4 +--- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/subprojects/docs/src/docs/release/notes-template.md b/subprojects/docs/src/docs/release/notes-template.md index 1045880aa6246..06e7f985490d4 100644 --- a/subprojects/docs/src/docs/release/notes-template.md +++ b/subprojects/docs/src/docs/release/notes-template.md @@ -26,6 +26,10 @@ Switch your build to use Gradle @version@ by updating your wrapper: `./gradlew wrapper --gradle-version=@version@` +## Support for JDK12 + +Gradle now supports running on [JDK12](https://jdk.java.net/12/). + ## Promoted features Promoted features are features that were incubating in previous versions of Gradle but are now supported and subject to backwards compatibility. See the User Manual section on the “[Feature Lifecycle](userguide/feature_lifecycle.html)” for more information. diff --git a/subprojects/docs/src/docs/release/release-features.txt b/subprojects/docs/src/docs/release/release-features.txt index a47d337af97b8..fb463396b8d31 100644 --- a/subprojects/docs/src/docs/release/release-features.txt +++ b/subprojects/docs/src/docs/release/release-features.txt @@ -1,3 +1 @@ - - Feature variants AKA "optional dependencies" - - Type-safe accessors in Kotlin precompiled script plugins - - Gradle Module Metadata 1.0 + - JDK12 support From 3e6ebe6d824994e0baf6d7ac8c5434e3611e2ba2 Mon Sep 17 00:00:00 2001 From: Gradleware Git Bot Date: Fri, 22 Mar 2019 02:20:42 +0100 Subject: [PATCH 667/853] Publish 5.3-20190322010027+0000 --- released-versions.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/released-versions.json b/released-versions.json index 2237595589fda..e7ef08ca5f45f 100644 --- a/released-versions.json +++ b/released-versions.json @@ -1,7 +1,7 @@ { "latestReleaseSnapshot": { - "version": "5.3-20190321010135+0000", - "buildTime": "20190321010135+0000" + "version": "5.3-20190322010027+0000", + "buildTime": "20190322010027+0000" }, "latestRc": { "version": "5.3-rc-3", From db84310c3fdf18d0bcc6996d6a76c31a8a850e8b Mon Sep 17 00:00:00 2001 From: Sterling Greene Date: Thu, 21 Mar 2019 04:29:48 -0400 Subject: [PATCH 668/853] Convert list of annotation processors into table in user manual Instead of keeping track of which AP supports incremental compilation on GH, document this directly in our user manual. --- .../docs/src/docs/userguide/java_plugin.adoc | 123 ++++++++++++++++++ 1 file changed, 123 insertions(+) diff --git a/subprojects/docs/src/docs/userguide/java_plugin.adoc b/subprojects/docs/src/docs/userguide/java_plugin.adoc index ff089e8cc7351..e5b13f62e1f80 100644 --- a/subprojects/docs/src/docs/userguide/java_plugin.adoc +++ b/subprojects/docs/src/docs/userguide/java_plugin.adoc @@ -652,6 +652,129 @@ include::{samplesPath}/java/incrementalAnnotationProcessing/processor/src/main/j Gradle will always reprocess (but not recompile) all annotated files that the processor was registered for. Gradle will always recompile any files the processor generates. +=== State of support in popular annotation processors + +[NOTE] +==== +Many popular annotation processors support incremental compilation (see the table below). Check with the annotation processor project directly for the most up-to-date information and documentation. +==== + +[cols="a,a,a", options="header"] +|=== +| Annotation Processor +| Supported since +| Details + +| link:https://github.com/google/auto[Auto Value] +| link:https://github.com/google/auto/releases/tag/auto-value-1.6.3[1.6.3] +| N/A + +| link:https://github.com/google/auto[Auto Service] +| link:https://github.com/google/auto/releases/tag/auto-value-1.6.3[1.6.3] +| N/A + +| link:https://github.com/google/auto[Auto Value extensions] +| Partly supported. +| link:https://github.com/google/auto/issues/673[Details in issue] + +| link:https://github.com/JakeWharton/butterknife[Butterknife] +| Unsupported. +| link:https://github.com/stephanenicolas/butterknife[Community fork supports incremental compilation] + +| link:https://github.com/rzwitserloot/lombok[Lombok] +| link:https://github.com/rzwitserloot/lombok/releases/tag/v1.16.22[1.16.22] +| N/A + +| DataBinding +| link:https://issuetracker.google.com/issues/110061530#comment28[AGP 3.5.0-alpha5] +| Hidden behind a feature toggle + +| Dagger +| link:https://github.com/google/dagger/issues/1120[2.18] +| Hidden behind a feature toggle + +| kapt +| link:https://youtrack.jetbrains.com/issue/KT-23880[1.3.30] +| Hidden behind a feature toggle + +| Toothpick +| link:https://github.com/stephanenicolas/toothpick/pull/320[2.0] +| N/A + +| Glide +| link:https://github.com/bumptech/glide/releases/tag/v4.9.0[4.9.0] +| N/A + +| Toothpick +| link:https://github.com/stephanenicolas/toothpick/pull/320[2.0] +| N/A + +| Android-State +| link:https://github.com/evernote/android-state/releases/tag/v1.3.0[1.3.0] +| N/A + +| Parceler +| link:https://github.com/johncarl81/parceler/releases/tag/parceler-project-1.1.11[1.1.11] +| N/A + +| Dart and Henson +| link:https://github.com/f2prateek/dart/releases/tag/3.1.0[3.1.0] +| N/A + +| MapStruct +| link:https://github.com/mapstruct/mapstruct/issues/1420[Open issue] +| N/A + +| Realm +| link:https://github.com/realm/realm-java/issues/5906[Open issue] +| N/A + +| Requery +| link:https://github.com/requery/requery/issues/773[Open issue] +| N/A + +| EventBus +| link:https://github.com/greenrobot/EventBus/issues/528[Open issue] +| N/A + +| EclipseLink +| link:https://bugs.eclipse.org/bugs/show_bug.cgi?id=535985[Open issue] +| N/A + +| PermissionsDispatcher +| link:https://github.com/permissions-dispatcher/PermissionsDispatcher/issues/473[PR merged, waiting for release] +| N/A + +| Immutables +| link:https://github.com/immutables/immutables/issues/804[Open issue] +| N/A + +| link:https://developer.android.com/topic/libraries/architecture/room)[Room] +| Unsupported +| Unlikely to be incremental + +| Android Annotations +| link:https://github.com/androidannotations/androidannotations/issues/2193[Open issue] +| N/A + +| DBFlow +| link:https://github.com/agrosner/DBFlow/issues/1648[Open issue] +| N/A + +| AndServer +| link:https://github.com/yanzhenjie/AndServer/issues/152[Open issue] +| N/A + +| Litho +| link:https://github.com/facebook/litho/issues/482[Open issue] +| N/A + +| Moxy +| link:https://github.com/Arello-Mobile/Moxy/issues/240[Open issue] +| N/A + +|=== + [[sec:java_compile_avoidance]] === Compile avoidance From b2d6103a9d350d46be3ec425505687b34149325e Mon Sep 17 00:00:00 2001 From: Sterling Greene Date: Fri, 22 Mar 2019 00:38:43 -0400 Subject: [PATCH 669/853] Add epoxy to annotation processor list --- subprojects/docs/src/docs/userguide/java_plugin.adoc | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/subprojects/docs/src/docs/userguide/java_plugin.adoc b/subprojects/docs/src/docs/userguide/java_plugin.adoc index e5b13f62e1f80..adf1f6591a249 100644 --- a/subprojects/docs/src/docs/userguide/java_plugin.adoc +++ b/subprojects/docs/src/docs/userguide/java_plugin.adoc @@ -656,7 +656,7 @@ Gradle will always recompile any files the processor generates. [NOTE] ==== -Many popular annotation processors support incremental compilation (see the table below). Check with the annotation processor project directly for the most up-to-date information and documentation. +Many popular annotation processors support incremental annotation processing (see the table below). Check with the annotation processor project directly for the most up-to-date information and documentation. ==== [cols="a,a,a", options="header"] @@ -679,7 +679,7 @@ Many popular annotation processors support incremental compilation (see the tabl | link:https://github.com/JakeWharton/butterknife[Butterknife] | Unsupported. -| link:https://github.com/stephanenicolas/butterknife[Community fork supports incremental compilation] +| link:https://github.com/stephanenicolas/butterknife[Community fork supports incremental annotation processing] | link:https://github.com/rzwitserloot/lombok[Lombok] | link:https://github.com/rzwitserloot/lombok/releases/tag/v1.16.22[1.16.22] @@ -773,6 +773,10 @@ Many popular annotation processors support incremental compilation (see the tabl | link:https://github.com/Arello-Mobile/Moxy/issues/240[Open issue] | N/A +| Epoxy +| link:https://github.com/airbnb/epoxy/issues/423[Open issue] +| N/A + |=== [[sec:java_compile_avoidance]] From fa1a6404fbe4edc77519aa2564113b9a12e657e6 Mon Sep 17 00:00:00 2001 From: Sterling Greene Date: Fri, 22 Mar 2019 00:09:35 -0400 Subject: [PATCH 670/853] Remove duplicated DSL property references in Java plugin chapter --- .../docs/src/docs/userguide/java_plugin.adoc | 60 ------------------- 1 file changed, 60 deletions(-) diff --git a/subprojects/docs/src/docs/userguide/java_plugin.adoc b/subprojects/docs/src/docs/userguide/java_plugin.adoc index ff089e8cc7351..eba8e73fe8d07 100644 --- a/subprojects/docs/src/docs/userguide/java_plugin.adoc +++ b/subprojects/docs/src/docs/userguide/java_plugin.adoc @@ -462,66 +462,6 @@ The manifest to include in all JAR files. Default value: an empty manifest. These properties are provided by convention objects of type link:{javadocPath}/org/gradle/api/plugins/JavaPluginConvention.html[JavaPluginConvention], and link:{javadocPath}/org/gradle/api/plugins/BasePluginConvention.html[BasePluginConvention]. -[[sec:javadoc]] -== Javadoc - -The `javadoc` task is an instance of link:{groovyDslPath}/org.gradle.api.tasks.javadoc.Javadoc.html[Javadoc]. It supports the core Javadoc options and the options of the standard doclet described in the link:{javadocReferenceUrl}[reference documentation] of the Javadoc executable. For a complete list of supported Javadoc options consult the API documentation of the following classes: link:{javadocPath}/org/gradle/external/javadoc/CoreJavadocOptions.html[CoreJavadocOptions] and link:{javadocPath}/org/gradle/external/javadoc/StandardJavadocDocletOptions.html[StandardJavadocDocletOptions]. - -=== Javadoc properties - -`link:{javadocPath}/org/gradle/api/file/FileCollection.html[FileCollection] classpath`:: -Default value: `sourceSets.main.output` + `sourceSets.main.compileClasspath` - -`link:{javadocPath}/org/gradle/api/file/FileTree.html[FileTree] source`:: -Default value: `sourceSets.main.allJava`. Can set using anything described in <>. - -`File destinationDir`:: -Default value: `__docsDir__/javadoc` - -`String title`:: -Default value: The name and version of the project - -[[sec:clean]] -== Clean - -The `clean` task is an instance of link:{groovyDslPath}/org.gradle.api.tasks.Delete.html[Delete]. It simply removes the directory denoted by its `dir` property. - -=== Clean properties - -`File dir`:: -Default value: `__buildDir__` - - -== Resources - -The Java plugin uses the link:{groovyDslPath}/org.gradle.api.tasks.Copy.html[Copy] task for resource handling. It adds an instance for each source set in the project. You can find out more about the copy task in <>. - -=== ProcessResources properties - -`Object srcDirs`:: -Default value: `__sourceSet__.resources`. Can set using anything described in <>. - -`File destinationDir`:: -Default value: `__sourceSet__.output.resourcesDir`. Can set using anything described in <>. - - -== CompileJava - -The Java plugin adds a link:{groovyDslPath}/org.gradle.api.tasks.compile.JavaCompile.html[JavaCompile] instance for each source set in the project. Some of the most common configuration options are shown below. - -=== Compile properties - -`link:{javadocPath}/org/gradle/api/file/FileCollection.html[FileCollection] classpath`:: -Default value: `__sourceSet__.compileClasspath` - -`link:{javadocPath}/org/gradle/api/file/FileTree.html[FileTree] source`:: -Default value: `__sourceSet__.java`. Can set using anything described in <>. - -`File destinationDir`:: -Default value: `__sourceSet__.java.outputDir` - -By default, the Java compiler runs in the Gradle process. Setting `options.fork` to `true` causes compilation to occur in a separate process. In the case of the Ant javac task, this means that a new process will be forked for each compile task, which can slow down compilation. Conversely, Gradle's direct compiler integration (see above) will reuse the same compiler process as much as possible. In both cases, all fork options specified with `options.forkOptions` will be honored. - [[sec:incremental_compile]] === Incremental Java compilation From a09412d088aaa9d6356a62f67f03076616f3b4b7 Mon Sep 17 00:00:00 2001 From: Sterling Greene Date: Fri, 22 Mar 2019 00:30:15 -0400 Subject: [PATCH 671/853] Reorder sections of Java plugin chapter Tasks are not as important as major plugin features: - Incremental compilation - Incremental annotation processing - Compilation avoidance --- .../docs/src/docs/userguide/java_plugin.adoc | 247 +++++++++--------- 1 file changed, 123 insertions(+), 124 deletions(-) diff --git a/subprojects/docs/src/docs/userguide/java_plugin.adoc b/subprojects/docs/src/docs/userguide/java_plugin.adoc index eba8e73fe8d07..f0cfd725c3dce 100644 --- a/subprojects/docs/src/docs/userguide/java_plugin.adoc +++ b/subprojects/docs/src/docs/userguide/java_plugin.adoc @@ -41,6 +41,71 @@ include::javaProjectTestLayout.adoc[] include::javaProjectGenericLayout.adoc[] +[[sec:java_convention_properties]] +== Convention properties + +The Java Plugin adds a number of convention properties to the project, shown below. You can use these properties in your build script as though they were properties of the project object. + +=== Directory properties + +`String reporting.baseDir`:: +The name of the directory to generate reports into, relative to the build directory. Default value: `reports` + +`(read-only) File reportsDir`:: +The directory to generate reports into. Default value: `__buildDir__/__reporting.baseDir__` + +`String testResultsDirName`:: +The name of the directory to generate test result .xml files into, relative to the build directory. Default value: `test-results` + +`(read-only) File testResultsDir`:: +The directory to generate test result .xml files into. Default value: `__buildDir__/__testResultsDirName__` + +`String testReportDirName`:: +The name of the directory to generate the test report into, relative to the reports directory. Default value: `tests` + +`(read-only) File testReportDir`:: +The directory to generate the test report into. Default value: `__reportsDir__/testReportDirName` + +`String libsDirName`:: +The name of the directory to generate libraries into, relative to the build directory. Default value: `libs` + +`(read-only) File libsDir`:: +The directory to generate libraries into. Default value: `__buildDir__/__libsDirName__` + +`String distsDirName`:: +The name of the directory to generate distributions into, relative to the build directory. Default value: `distributions` + +`(read-only) File distsDir`:: +The directory to generate distributions into. Default value: `__buildDir__/__distsDirName__` + +`String docsDirName`:: +The name of the directory to generate documentation into, relative to the build directory. Default value: `docs` + +`(read-only) File docsDir`:: +The directory to generate documentation into. Default value: `__buildDir__/__docsDirName__` + +`String dependencyCacheDirName`:: +The name of the directory to use to cache source dependency information, relative to the build directory. Default value: `dependency-cache` + +=== Other convention properties + +`(read-only) link:{javadocPath}/org/gradle/api/tasks/SourceSetContainer.html[SourceSetContainer] sourceSets`:: +Contains the project's source sets. Default value: Not null link:{javadocPath}/org/gradle/api/tasks/SourceSetContainer.html[SourceSetContainer] + +`link:{javadocPath}/org/gradle/api/JavaVersion.html[JavaVersion] sourceCompatibility`:: +Java version compatibility to use when compiling Java source. Default value: version of the current JVM in use link:{javadocPath}/org/gradle/api/JavaVersion.html[JavaVersion]. Can also set using a String or a Number, e.g. `'1.5'` or `1.5`. + +`link:{javadocPath}/org/gradle/api/JavaVersion.html[JavaVersion] targetCompatibility`:: +Java version to generate classes for. Default value: `__sourceCompatibility__`. Can also set using a String or Number, e.g. `'1.5'` or `1.5`. + +`String archivesBaseName`:: +The basename to use for archives, such as JAR or ZIP files. Default value: `__projectName__` + +`link:{javadocPath}/org/gradle/api/java/archives/Manifest.html[Manifest] manifest`:: +The manifest to include in all JAR files. Default value: an empty manifest. + +These properties are provided by convention objects of type link:{javadocPath}/org/gradle/api/plugins/JavaPluginConvention.html[JavaPluginConvention], and link:{javadocPath}/org/gradle/api/plugins/BasePluginConvention.html[BasePluginConvention]. + [[sec:changing_java_project_layout]] === Changing the project layout @@ -282,6 +347,57 @@ The following diagram shows the relationships between these tasks. image::javaPluginTasks.png[] +[[sec:java_test]] +=== Test + +The `test` task is an instance of link:{groovyDslPath}/org.gradle.api.tasks.testing.Test.html[Test]. It automatically detects and executes all unit tests in the `test` source set. It also generates a report once test execution is complete. JUnit and TestNG are both supported. Have a look at link:{groovyDslPath}/org.gradle.api.tasks.testing.Test.html[Test] for the complete API. + +See the <> chapter for more details. + + +[[sec:jar]] +=== Jar + +The `jar` task creates a JAR file containing the class files and resources of the project. The JAR file is declared as an artifact in the `archives` dependency configuration. This means that the JAR is available in the classpath of a dependent project. If you upload your project into a repository, this JAR is declared as part of the dependency descriptor. You can learn more about how to work with archives in <> and artifact configurations in <>. + + +[[sub:manifest]] +==== Manifest + +Each jar or war object has a `manifest` property with a separate instance of link:{javadocPath}/org/gradle/api/java/archives/Manifest.html[Manifest]. When the archive is generated, a corresponding `MANIFEST.MF` file is written into the archive. + +.Customization of MANIFEST.MF +==== +include::sample[dir="userguide/tutorial/manifest/groovy",files="build.gradle[tags=add-to-manifest]"] +include::sample[dir="userguide/tutorial/manifest/kotlin",files="build.gradle.kts[tags=add-to-manifest]"] +==== + +You can create stand-alone instances of a `Manifest`. You can use that for example, to share manifest information between jars. + +.Creating a manifest object. +==== +include::sample[dir="userguide/tutorial/manifest/groovy",files="build.gradle[tags=custom-manifest]"] +include::sample[dir="userguide/tutorial/manifest/kotlin",files="build.gradle.kts[tags=custom-manifest]"] +==== + +You can merge other manifests into any `Manifest` object. The other manifests might be either described by a file path or, like in the example above, by a reference to another `Manifest` object. + +.Separate MANIFEST.MF for a particular archive +==== +include::sample[dir="userguide/tutorial/manifest/groovy",files="build.gradle[tags=merge]"] +include::sample[dir="userguide/tutorial/manifest/kotlin",files="build.gradle.kts[tags=merge]"] +==== + +Manifests are merged in the order they are declared by the `from` statement. If the base manifest and the merged manifest both define values for the same key, the merged manifest wins by default. You can fully customize the merge behavior by adding `eachEntry` actions in which you have access to a link:{javadocPath}/org/gradle/api/java/archives/ManifestMergeDetails.html[ManifestMergeDetails] instance for each entry of the resulting manifest. The merge is not immediately triggered by the from statement. It is done lazily, either when generating the jar, or by calling `writeTo` or `effectiveManifest` + +You can easily write a manifest to disk. + +.Saving a MANIFEST.MF to disk +==== +include::sample[dir="userguide/tutorial/manifest/groovy",files="build.gradle[tags=write]"] +include::sample[dir="userguide/tutorial/manifest/kotlin",files="build.gradle.kts[tags=write]"] +==== + [[sec:java_plugin_and_dependency_management]] == Dependency management @@ -397,73 +513,8 @@ Runtime classpath contains elements of the implementation, as well as runtime on `components.java`:: A link:{javadocPath}/org/gradle/api/component/SoftwareComponent.html[SoftwareComponent] for <> the production JAR created by the `jar` task. This component includes the runtime dependency information for the JAR. -[[sec:java_convention_properties]] -== Convention properties - -The Java Plugin adds a number of convention properties to the project, shown below. You can use these properties in your build script as though they were properties of the project object. - -=== Directory properties - -`String reporting.baseDir`:: -The name of the directory to generate reports into, relative to the build directory. Default value: `reports` - -`(read-only) File reportsDir`:: -The directory to generate reports into. Default value: `__buildDir__/__reporting.baseDir__` - -`String testResultsDirName`:: -The name of the directory to generate test result .xml files into, relative to the build directory. Default value: `test-results` - -`(read-only) File testResultsDir`:: -The directory to generate test result .xml files into. Default value: `__buildDir__/__testResultsDirName__` - -`String testReportDirName`:: -The name of the directory to generate the test report into, relative to the reports directory. Default value: `tests` - -`(read-only) File testReportDir`:: -The directory to generate the test report into. Default value: `__reportsDir__/testReportDirName` - -`String libsDirName`:: -The name of the directory to generate libraries into, relative to the build directory. Default value: `libs` - -`(read-only) File libsDir`:: -The directory to generate libraries into. Default value: `__buildDir__/__libsDirName__` - -`String distsDirName`:: -The name of the directory to generate distributions into, relative to the build directory. Default value: `distributions` - -`(read-only) File distsDir`:: -The directory to generate distributions into. Default value: `__buildDir__/__distsDirName__` - -`String docsDirName`:: -The name of the directory to generate documentation into, relative to the build directory. Default value: `docs` - -`(read-only) File docsDir`:: -The directory to generate documentation into. Default value: `__buildDir__/__docsDirName__` - -`String dependencyCacheDirName`:: -The name of the directory to use to cache source dependency information, relative to the build directory. Default value: `dependency-cache` - -=== Other convention properties - -`(read-only) link:{javadocPath}/org/gradle/api/tasks/SourceSetContainer.html[SourceSetContainer] sourceSets`:: -Contains the project's source sets. Default value: Not null link:{javadocPath}/org/gradle/api/tasks/SourceSetContainer.html[SourceSetContainer] - -`link:{javadocPath}/org/gradle/api/JavaVersion.html[JavaVersion] sourceCompatibility`:: -Java version compatibility to use when compiling Java source. Default value: version of the current JVM in use link:{javadocPath}/org/gradle/api/JavaVersion.html[JavaVersion]. Can also set using a String or a Number, e.g. `'1.5'` or `1.5`. - -`link:{javadocPath}/org/gradle/api/JavaVersion.html[JavaVersion] targetCompatibility`:: -Java version to generate classes for. Default value: `__sourceCompatibility__`. Can also set using a String or Number, e.g. `'1.5'` or `1.5`. - -`String archivesBaseName`:: -The basename to use for archives, such as JAR or ZIP files. Default value: `__projectName__` - -`link:{javadocPath}/org/gradle/api/java/archives/Manifest.html[Manifest] manifest`:: -The manifest to include in all JAR files. Default value: an empty manifest. - -These properties are provided by convention objects of type link:{javadocPath}/org/gradle/api/plugins/JavaPluginConvention.html[JavaPluginConvention], and link:{javadocPath}/org/gradle/api/plugins/BasePluginConvention.html[BasePluginConvention]. - [[sec:incremental_compile]] -=== Incremental Java compilation +== Incremental Java compilation Gradle comes with a sophisticated incremental Java compiler that is active by default. @@ -488,14 +539,14 @@ To help you understand how incremental compilation works, the following provides * The class analysis is cached in the project directory, so the first build after a clean checkout can be slower. Consider turning off the incremental compiler on your build server. [[sec:incremental_compilation_known_issues]] -==== Known issues +=== Known issues * If a compile task fails due to a compile error, it will do a full compilation again the next time it is invoked. * If you are using an annotation processor that reads resources (e.g. a configuration file), you need to declare those resources as an input of the compile task. * If a resource file is changed, Gradle will trigger a full recompilation. [[sec:incremental_annotation_processing]] -=== Incremental annotation processing +== Incremental annotation processing Starting with Gradle 4.7, the incremental compiler also supports incremental annotation processing. All annotation processors need to opt in to this feature, otherwise they will trigger a full recompilation. @@ -503,7 +554,7 @@ All annotation processors need to opt in to this feature, otherwise they will tr As a user you can see which annotation processors are triggering full recompilations in the `--info` log. Incremental annotation processing will be deactivated if a custom `executable` or `javaHome` is configured on the compile task. -==== Making an annotation processor incremental +=== Making an annotation processor incremental Please first have a look at <<#sec:incremental_compile,incremental Java compilation>>, as incremental annotation processing builds on top of it. @@ -544,7 +595,7 @@ Both categories have the following limitations: * If they use link:{javaApi}/javax/annotation/processing/Filer.html#createResource(javax.tools.JavaFileManager.Location,java.lang.CharSequence,java.lang.CharSequence,javax.lang.model.element.Element++...++)[Filer#createResource], Gradle will recompile all source files. See https://github.com/gradle/gradle/issues/4702[gradle/issues/4702] -==== "Isolating" annotation processors +=== "Isolating" annotation processors The fastest category, these look at each annotated element in isolation, creating generated files or validation messages for it. For instance an `EntityProcessor` could create a `Repository` for each type annotated with `@Entity`. @@ -571,7 +622,7 @@ include::{samplesPath}/java/incrementalAnnotationProcessing/processor/src/main/j When a source file is recompiled, Gradle will recompile all files generated from it. When a source file is deleted, the files generated from it are deleted. -==== "Aggregating" annotation processors +=== "Aggregating" annotation processors These can aggregate several source files into one ore more output files or validation messages. For instance, a `ServiceRegistryProcessor` could create a single `ServiceRegistry` with one method for each type annotated with `@Service` @@ -593,7 +644,7 @@ Gradle will always reprocess (but not recompile) all annotated files that the pr Gradle will always recompile any files the processor generates. [[sec:java_compile_avoidance]] -=== Compile avoidance +== Compilation avoidance If a dependent project has changed in an https://en.wikipedia.org/wiki/Application_binary_interface[ABI]-compatible way (only its private API has changed), then Java compilation tasks will be up-to-date. This means that if project `A` depends on project `B` and a class in `B` is changed in an ABI-compatible way (typically, changing only the body of a method), then Gradle won't recompile `A`. @@ -615,55 +666,3 @@ Gradle ignores annotation processors on the compile classpath. include::sample[dir="java/apt/groovy", files="build.gradle[tags=annotation-processing]"] include::sample[dir="java/apt/kotlin", files="build.gradle.kts[tags=annotation-processing]"] ==== - -[[sec:java_test]] -== Test - -The `test` task is an instance of link:{groovyDslPath}/org.gradle.api.tasks.testing.Test.html[Test]. It automatically detects and executes all unit tests in the `test` source set. It also generates a report once test execution is complete. JUnit and TestNG are both supported. Have a look at link:{groovyDslPath}/org.gradle.api.tasks.testing.Test.html[Test] for the complete API. - -See the <> chapter for more details. - - -[[sec:jar]] -== Jar - -The `jar` task creates a JAR file containing the class files and resources of the project. The JAR file is declared as an artifact in the `archives` dependency configuration. This means that the JAR is available in the classpath of a dependent project. If you upload your project into a repository, this JAR is declared as part of the dependency descriptor. You can learn more about how to work with archives in <> and artifact configurations in <>. - - -[[sub:manifest]] -=== Manifest - -Each jar or war object has a `manifest` property with a separate instance of link:{javadocPath}/org/gradle/api/java/archives/Manifest.html[Manifest]. When the archive is generated, a corresponding `MANIFEST.MF` file is written into the archive. - -.Customization of MANIFEST.MF -==== -include::sample[dir="userguide/tutorial/manifest/groovy",files="build.gradle[tags=add-to-manifest]"] -include::sample[dir="userguide/tutorial/manifest/kotlin",files="build.gradle.kts[tags=add-to-manifest]"] -==== - -You can create stand-alone instances of a `Manifest`. You can use that for example, to share manifest information between jars. - -.Creating a manifest object. -==== -include::sample[dir="userguide/tutorial/manifest/groovy",files="build.gradle[tags=custom-manifest]"] -include::sample[dir="userguide/tutorial/manifest/kotlin",files="build.gradle.kts[tags=custom-manifest]"] -==== - -You can merge other manifests into any `Manifest` object. The other manifests might be either described by a file path or, like in the example above, by a reference to another `Manifest` object. - -.Separate MANIFEST.MF for a particular archive -==== -include::sample[dir="userguide/tutorial/manifest/groovy",files="build.gradle[tags=merge]"] -include::sample[dir="userguide/tutorial/manifest/kotlin",files="build.gradle.kts[tags=merge]"] -==== - -Manifests are merged in the order they are declared by the `from` statement. If the base manifest and the merged manifest both define values for the same key, the merged manifest wins by default. You can fully customize the merge behavior by adding `eachEntry` actions in which you have access to a link:{javadocPath}/org/gradle/api/java/archives/ManifestMergeDetails.html[ManifestMergeDetails] instance for each entry of the resulting manifest. The merge is not immediately triggered by the from statement. It is done lazily, either when generating the jar, or by calling `writeTo` or `effectiveManifest` - -You can easily write a manifest to disk. - -.Saving a MANIFEST.MF to disk -==== -include::sample[dir="userguide/tutorial/manifest/groovy",files="build.gradle[tags=write]"] -include::sample[dir="userguide/tutorial/manifest/kotlin",files="build.gradle.kts[tags=write]"] -==== - From 411581a39c90a12afab71472e1590d77244dd97d Mon Sep 17 00:00:00 2001 From: Stefan Oehme Date: Fri, 22 Mar 2019 08:14:30 +0100 Subject: [PATCH 672/853] Fix Maven project generation --- .../generator/FileContentGenerator.groovy | 34 ++++++++++++------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/subprojects/internal-performance-testing/src/main/groovy/org/gradle/performance/generator/FileContentGenerator.groovy b/subprojects/internal-performance-testing/src/main/groovy/org/gradle/performance/generator/FileContentGenerator.groovy index a1b98f86e4ebd..b5cc55d3f25bc 100644 --- a/subprojects/internal-performance-testing/src/main/groovy/org/gradle/performance/generator/FileContentGenerator.groovy +++ b/subprojects/internal-performance-testing/src/main/groovy/org/gradle/performance/generator/FileContentGenerator.groovy @@ -112,14 +112,18 @@ abstract class FileContentGenerator { } def generatePomXML(Integer subProjectNumber, DependencyTree dependencyTree) { - def body + def body = "" + def isParent = subProjectNumber == null || config.subProjects == 0 def hasSources = subProjectNumber != null || config.subProjects == 0 - if (!hasSources) { - body = """ - - ${(0..config.subProjects - 1).collect { "project$it" }.join("\n ")} - - + if (isParent) { + if (config.subProjects != 0) { + body += """ + + ${(0..config.subProjects - 1).collect { "project$it" }.join("\n ")} + + """ + } + body += """ @@ -162,17 +166,21 @@ abstract class FileContentGenerator { """ } else { + body += """ + + org.gradle.test.performance + project + 1.0 + + """ + } + if (hasSources) { def subProjectNumbers = dependencyTree.getChildProjectIds(subProjectNumber) def subProjectDependencies = '' if (subProjectNumbers?.size() > 0) { subProjectDependencies = subProjectNumbers.collect { convertToPomDependency("org.gradle.test.performance:project$it:1.0") }.join() } - body = """ - - org.gradle.test.performance - project - 1.0 - + body += """ ${config.externalApiDependencies.collect { convertToPomDependency(it) }.join()} ${config.externalImplementationDependencies.collect { convertToPomDependency(it) }.join()} From 3d57d99c0168a6ccc23a61df12dd6faf9c86e5f2 Mon Sep 17 00:00:00 2001 From: Stefan Wolf Date: Fri, 22 Mar 2019 08:15:48 +0100 Subject: [PATCH 673/853] Improve Javadoc --- .../java/org/gradle/api/tasks/SkipWhenEmpty.java | 2 +- .../src/main/java/org/gradle/work/Incremental.java | 2 +- .../src/main/java/org/gradle/work/InputChanges.java | 13 +++++++++---- .../history/changes/IncrementalInputChanges.java | 12 ++++++------ .../history/changes/NonIncrementalInputChanges.java | 12 ++++++------ 5 files changed, 23 insertions(+), 18 deletions(-) diff --git a/subprojects/core-api/src/main/java/org/gradle/api/tasks/SkipWhenEmpty.java b/subprojects/core-api/src/main/java/org/gradle/api/tasks/SkipWhenEmpty.java index 96c8200999aa6..4cc37c151e6bc 100644 --- a/subprojects/core-api/src/main/java/org/gradle/api/tasks/SkipWhenEmpty.java +++ b/subprojects/core-api/src/main/java/org/gradle/api/tasks/SkipWhenEmpty.java @@ -27,7 +27,7 @@ * *

    If all of the inputs declared with this annotation are empty, the task will be skipped with a "NO-SOURCE" message.

    * - *

    Inputs annotated with this annotation can be queried for changes via {@link org.gradle.work.InputChanges#getFileChanges(org.gradle.api.file.FileCollection)}.

    + *

    Inputs annotated with this annotation can be queried for changes via {@link org.gradle.work.InputChanges#getFileChanges(org.gradle.api.file.FileCollection)} or {@link org.gradle.work.InputChanges#getFileChanges(org.gradle.api.provider.Provider)}.

    * *

    This annotation should be attached to the getter method in Java or the property in Groovy. * Annotations on setters or just the field in Java are ignored.

    diff --git a/subprojects/core-api/src/main/java/org/gradle/work/Incremental.java b/subprojects/core-api/src/main/java/org/gradle/work/Incremental.java index e2f1abbc8d7ff..c44b3688794cb 100644 --- a/subprojects/core-api/src/main/java/org/gradle/work/Incremental.java +++ b/subprojects/core-api/src/main/java/org/gradle/work/Incremental.java @@ -28,7 +28,7 @@ * Track input changes for the annotated parameter. * *

    - * Inputs annotated with {@link Incremental} can be queried for changes via {@link InputChanges#getFileChanges(org.gradle.api.file.FileCollection)}. + * Inputs annotated with {@link Incremental} can be queried for changes via {@link InputChanges#getFileChanges(org.gradle.api.file.FileCollection)} or {@link org.gradle.work.InputChanges#getFileChanges(org.gradle.api.provider.Provider)}. *

    * * @since 5.4 diff --git a/subprojects/core-api/src/main/java/org/gradle/work/InputChanges.java b/subprojects/core-api/src/main/java/org/gradle/work/InputChanges.java index f802743734ff9..2876373416c2d 100644 --- a/subprojects/core-api/src/main/java/org/gradle/work/InputChanges.java +++ b/subprojects/core-api/src/main/java/org/gradle/work/InputChanges.java @@ -97,9 +97,9 @@ public interface InputChanges { * Only input file properties annotated with {@link Incremental} or {@link org.gradle.api.tasks.SkipWhenEmpty} can be queried for changes. *

    * - * @param parameterValue The value of the parameter to query. + * @param parameter The value of the parameter to query. */ - Iterable getFileChanges(FileCollection parameterValue); + Iterable getFileChanges(FileCollection parameter); /** * Changes for a parameter. @@ -107,10 +107,15 @@ public interface InputChanges { *

    When {@link #isIncremental()} is {@code false}, then all elements of the parameter are returned as {@link ChangeType#ADDED}.

    * *

    + * This method allows querying properties of type {@link org.gradle.api.file.RegularFileProperty} and {@link org.gradle.api.file.DirectoryProperty} for changes. + * These two types are typically used for {@link org.gradle.api.tasks.InputFile} and {@link org.gradle.api.tasks.InputDirectory} properties. + *

    + * + *

    * Only input file properties annotated with {@link Incremental} or {@link org.gradle.api.tasks.SkipWhenEmpty} can be queried for changes. *

    * - * @param parameterValue The value of the parameter to query. + * @param parameter The value of the parameter to query. */ - Iterable getFileChanges(Provider parameterValue); + Iterable getFileChanges(Provider parameter); } diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/IncrementalInputChanges.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/IncrementalInputChanges.java index 10b9a2b419682..899fa7248e15d 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/IncrementalInputChanges.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/IncrementalInputChanges.java @@ -40,17 +40,17 @@ public boolean isIncremental() { } @Override - public Iterable getFileChanges(FileCollection parameterValue) { - return getObjectFileChanges(parameterValue); + public Iterable getFileChanges(FileCollection parameter) { + return getObjectFileChanges(parameter); } @Override - public Iterable getFileChanges(Provider parameterValue) { - return getObjectFileChanges(parameterValue); + public Iterable getFileChanges(Provider parameter) { + return getObjectFileChanges(parameter); } - private Iterable getObjectFileChanges(Object parameterValue) { - String propertyName = incrementalInputProperties.getPropertyNameFor(parameterValue); + private Iterable getObjectFileChanges(Object parameter) { + String propertyName = incrementalInputProperties.getPropertyNameFor(parameter); CollectingChangeVisitor visitor = new CollectingChangeVisitor(); changes.accept(propertyName, visitor); return Cast.uncheckedNonnullCast(visitor.getChanges()); diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/NonIncrementalInputChanges.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/NonIncrementalInputChanges.java index 1e302d7f5aab9..34ceccbcb8f84 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/NonIncrementalInputChanges.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/history/changes/NonIncrementalInputChanges.java @@ -44,17 +44,17 @@ public boolean isIncremental() { } @Override - public Iterable getFileChanges(FileCollection parameterValue) { - return getObjectFileChanges(parameterValue); + public Iterable getFileChanges(FileCollection parameter) { + return getObjectFileChanges(parameter); } @Override - public Iterable getFileChanges(Provider parameterValue) { - return getObjectFileChanges(parameterValue); + public Iterable getFileChanges(Provider parameter) { + return getObjectFileChanges(parameter); } - public Iterable getObjectFileChanges(Object parameterValue) { - CurrentFileCollectionFingerprint currentFileCollectionFingerprint = currentInputs.get(incrementalInputProperties.getPropertyNameFor(parameterValue)); + public Iterable getObjectFileChanges(Object parameter) { + CurrentFileCollectionFingerprint currentFileCollectionFingerprint = currentInputs.get(incrementalInputProperties.getPropertyNameFor(parameter)); return () -> getAllFileChanges(currentFileCollectionFingerprint).iterator(); } From c1f1f72c3752ab3993e56c59b658b44e3f4c24b8 Mon Sep 17 00:00:00 2001 From: Paul Merlin Date: Fri, 22 Mar 2019 09:21:30 +0100 Subject: [PATCH 674/853] Fix typo! Signed-off-by: Paul Merlin --- .../regression/inception/GradleInceptionPerformanceTest.groovy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subprojects/performance/src/performanceTest/groovy/org/gradle/performance/regression/inception/GradleInceptionPerformanceTest.groovy b/subprojects/performance/src/performanceTest/groovy/org/gradle/performance/regression/inception/GradleInceptionPerformanceTest.groovy index f82cf48c3663b..b91054344455a 100644 --- a/subprojects/performance/src/performanceTest/groovy/org/gradle/performance/regression/inception/GradleInceptionPerformanceTest.groovy +++ b/subprojects/performance/src/performanceTest/groovy/org/gradle/performance/regression/inception/GradleInceptionPerformanceTest.groovy @@ -82,7 +82,7 @@ class GradleInceptionPerformanceTest extends AbstractCrossVersionPerformanceTest runner.testProject = testProject runner.tasksToRun = ['help'] runner.runs = runs - runner.args = extraGradleBuildArguments() + ["-buildSrcCheck=false"] + runner.args = extraGradleBuildArguments() + ["-PbuildSrcCheck=false"] and: def changingClassFilePath = "buildSrc/${buildSrcProjectDir}src/main/groovy/ChangingClass.groovy" From 58ff08ce87c74d4b10d939cbb0ec80350845ca8f Mon Sep 17 00:00:00 2001 From: Paul Merlin Date: Fri, 22 Mar 2019 09:22:38 +0100 Subject: [PATCH 675/853] Performance test also use previous property for baseline to work Signed-off-by: Paul Merlin --- .../regression/inception/GradleInceptionPerformanceTest.groovy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subprojects/performance/src/performanceTest/groovy/org/gradle/performance/regression/inception/GradleInceptionPerformanceTest.groovy b/subprojects/performance/src/performanceTest/groovy/org/gradle/performance/regression/inception/GradleInceptionPerformanceTest.groovy index b91054344455a..cc9e312fc35eb 100644 --- a/subprojects/performance/src/performanceTest/groovy/org/gradle/performance/regression/inception/GradleInceptionPerformanceTest.groovy +++ b/subprojects/performance/src/performanceTest/groovy/org/gradle/performance/regression/inception/GradleInceptionPerformanceTest.groovy @@ -82,7 +82,7 @@ class GradleInceptionPerformanceTest extends AbstractCrossVersionPerformanceTest runner.testProject = testProject runner.tasksToRun = ['help'] runner.runs = runs - runner.args = extraGradleBuildArguments() + ["-PbuildSrcCheck=false"] + runner.args = extraGradleBuildArguments() + ["-PbuildSrcCheck=false", "-Pgradlebuild.skipBuildSrcChecks=true"] and: def changingClassFilePath = "buildSrc/${buildSrcProjectDir}src/main/groovy/ChangingClass.groovy" From 1de9e26cac9bcd48a14ef9e20e5fac4559ff9b8e Mon Sep 17 00:00:00 2001 From: Paul Merlin Date: Fri, 22 Mar 2019 14:40:39 +0100 Subject: [PATCH 676/853] Revert "Performance test also use previous property for baseline to work" Wasn't actually needed as this test will compare Gradle but always use `gradleBuildCurrent`. This reverts commit 58ff08ce87c74d4b10d939cbb0ec80350845ca8f. --- .../regression/inception/GradleInceptionPerformanceTest.groovy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subprojects/performance/src/performanceTest/groovy/org/gradle/performance/regression/inception/GradleInceptionPerformanceTest.groovy b/subprojects/performance/src/performanceTest/groovy/org/gradle/performance/regression/inception/GradleInceptionPerformanceTest.groovy index cc9e312fc35eb..b91054344455a 100644 --- a/subprojects/performance/src/performanceTest/groovy/org/gradle/performance/regression/inception/GradleInceptionPerformanceTest.groovy +++ b/subprojects/performance/src/performanceTest/groovy/org/gradle/performance/regression/inception/GradleInceptionPerformanceTest.groovy @@ -82,7 +82,7 @@ class GradleInceptionPerformanceTest extends AbstractCrossVersionPerformanceTest runner.testProject = testProject runner.tasksToRun = ['help'] runner.runs = runs - runner.args = extraGradleBuildArguments() + ["-PbuildSrcCheck=false", "-Pgradlebuild.skipBuildSrcChecks=true"] + runner.args = extraGradleBuildArguments() + ["-PbuildSrcCheck=false"] and: def changingClassFilePath = "buildSrc/${buildSrcProjectDir}src/main/groovy/ChangingClass.groovy" From 18f1439db471b941747d223fbfa60923dec706f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=B3r=C3=A1nt=20Pint=C3=A9r?= Date: Fri, 22 Mar 2019 14:43:16 +0100 Subject: [PATCH 677/853] Remove ExecutionException It is not necessary to use this type to wrap execution exceptions. Instead, we can use the Try around outcome to return execution exceptions. --- .../execution/ExecuteActionsTaskExecuter.java | 5 +--- ...IncrementalExecutionIntegrationTest.groovy | 7 ++--- .../execution/ExecutionException.java | 30 ------------------- .../execution/steps/CatchExceptionStep.java | 4 +-- .../steps/CatchExceptionStepTest.groovy | 6 +--- 5 files changed, 6 insertions(+), 46 deletions(-) delete mode 100644 subprojects/execution/src/main/java/org/gradle/internal/execution/ExecutionException.java diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuter.java b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuter.java index 00362e6d53df3..10087200afc9f 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuter.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/tasks/execution/ExecuteActionsTaskExecuter.java @@ -44,7 +44,6 @@ import org.gradle.internal.exceptions.DefaultMultiCauseException; import org.gradle.internal.exceptions.MultiCauseException; import org.gradle.internal.execution.CacheHandler; -import org.gradle.internal.execution.ExecutionException; import org.gradle.internal.execution.ExecutionOutcome; import org.gradle.internal.execution.IncrementalContext; import org.gradle.internal.execution.UnitOfWork; @@ -138,9 +137,7 @@ public void accept(ExecutionOutcome outcome) { new Consumer() { @Override public void accept(Throwable failure) { - state.setOutcome(failure instanceof ExecutionException - ? new TaskExecutionException(task, failure.getCause()) - : new TaskExecutionException(task, failure)); + state.setOutcome(new TaskExecutionException(task, failure)); } } ); diff --git a/subprojects/execution/src/integTest/groovy/org/gradle/internal/execution/IncrementalExecutionIntegrationTest.groovy b/subprojects/execution/src/integTest/groovy/org/gradle/internal/execution/IncrementalExecutionIntegrationTest.groovy index 68a6c82be3bed..3bfc1a7377f80 100644 --- a/subprojects/execution/src/integTest/groovy/org/gradle/internal/execution/IncrementalExecutionIntegrationTest.groovy +++ b/subprojects/execution/src/integTest/groovy/org/gradle/internal/execution/IncrementalExecutionIntegrationTest.groovy @@ -244,8 +244,7 @@ class IncrementalExecutionIntegrationTest extends Specification { throw failure }.build()) then: - result.outcome.failure.get() instanceof ExecutionException - result.outcome.failure.get().cause == failure + result.outcome.failure.get() == failure !result.reused def origin = result.originMetadata.buildInvocationId @@ -308,7 +307,7 @@ class IncrementalExecutionIntegrationTest extends Specification { def result = execute(unitOfWork) then: - result.outcome.failure.get().message == "Execution failed for Test unit of work." + !result.outcome.successful !result.reused result.executionReasons == ["Output property 'file' file ${outputFile.absolutePath} has changed."] } @@ -323,7 +322,7 @@ class IncrementalExecutionIntegrationTest extends Specification { def result = execute(unitOfWork) then: - result.outcome.failure.get().message == "Execution failed for Test unit of work." + !result.outcome.successful !result.reused result.executionReasons == ["Output property 'dir' file ${outputDirFile.absolutePath} has changed."] } diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/ExecutionException.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/ExecutionException.java deleted file mode 100644 index 149feb7665df4..0000000000000 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/ExecutionException.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright 2018 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.gradle.internal.execution; - -import org.gradle.api.GradleException; -import org.gradle.internal.exceptions.Contextual; - -/** - * An {@code ExecutionException} is thrown when a unit of work fails to execute successfully. - */ -@Contextual -public class ExecutionException extends GradleException { - public ExecutionException(UnitOfWork work, Throwable cause) { - super(String.format("Execution failed for %s.", work.getDisplayName()), cause); - } -} diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/CatchExceptionStep.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/CatchExceptionStep.java index 5f71c8c3eae47..f54376950a597 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/CatchExceptionStep.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/CatchExceptionStep.java @@ -18,7 +18,6 @@ import org.gradle.internal.Try; import org.gradle.internal.execution.Context; -import org.gradle.internal.execution.ExecutionException; import org.gradle.internal.execution.ExecutionOutcome; import org.gradle.internal.execution.Result; import org.gradle.internal.execution.Step; @@ -34,8 +33,7 @@ public CatchExceptionStep(Step delegate) { public Result execute(C context) { try { return delegate.execute(context); - } catch (Throwable t) { - ExecutionException failure = new ExecutionException(context.getWork(), t); + } catch (Throwable failure) { return new Result() { @Override public Try getOutcome() { diff --git a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/CatchExceptionStepTest.groovy b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/CatchExceptionStepTest.groovy index 632f67976d0cd..50c8a826fffed 100644 --- a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/CatchExceptionStepTest.groovy +++ b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/CatchExceptionStepTest.groovy @@ -17,7 +17,6 @@ package org.gradle.internal.execution.steps import org.gradle.internal.execution.Context -import org.gradle.internal.execution.ExecutionException import org.gradle.internal.execution.IncrementalChangesContext import org.gradle.internal.execution.Result import spock.lang.Unroll @@ -45,12 +44,9 @@ class CatchExceptionStepTest extends StepSpec { def result = step.execute(context) then: - result.outcome.failure.get() instanceof ExecutionException - result.outcome.failure.get().cause == failure + result.outcome.failure.get() == failure 1 * delegate.execute(context) >> { throw failure } - 1 * context.work >> work - 1 * work.displayName >> "Failing work" 0 * _ where: From 8f125a9cd143451d6d62123df40bf65899b38c52 Mon Sep 17 00:00:00 2001 From: Sterling Greene Date: Fri, 22 Mar 2019 10:44:22 -0400 Subject: [PATCH 678/853] Update Room/Lifecycle annotation processor notes --- subprojects/docs/src/docs/userguide/java_plugin.adoc | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/subprojects/docs/src/docs/userguide/java_plugin.adoc b/subprojects/docs/src/docs/userguide/java_plugin.adoc index adf1f6591a249..eb26a2ab666a6 100644 --- a/subprojects/docs/src/docs/userguide/java_plugin.adoc +++ b/subprojects/docs/src/docs/userguide/java_plugin.adoc @@ -750,8 +750,12 @@ Many popular annotation processors support incremental annotation processing (se | N/A | link:https://developer.android.com/topic/libraries/architecture/room)[Room] -| Unsupported -| Unlikely to be incremental +| link:https://issuetracker.google.com/issues/112110217[Open Issue] +| N/A + +| link:https://developer.android.com/jetpack/androidx/releases/lifecycle)[Lifecycle] +| link:https://issuetracker.google.com/issues/129115778[Open Issue] +| N/A | Android Annotations | link:https://github.com/androidannotations/androidannotations/issues/2193[Open issue] From 1538c78c4ff50c621a3f23a5090cf6d07e187887 Mon Sep 17 00:00:00 2001 From: Stefan Wolf Date: Fri, 22 Mar 2019 16:39:57 +0100 Subject: [PATCH 679/853] Improve Javadoc for annotation types --- .../src/main/java/org/gradle/work/InputChanges.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/subprojects/core-api/src/main/java/org/gradle/work/InputChanges.java b/subprojects/core-api/src/main/java/org/gradle/work/InputChanges.java index 2876373416c2d..900be5659607b 100644 --- a/subprojects/core-api/src/main/java/org/gradle/work/InputChanges.java +++ b/subprojects/core-api/src/main/java/org/gradle/work/InputChanges.java @@ -94,7 +94,7 @@ public interface InputChanges { *

    When {@link #isIncremental()} is {@code false}, then all elements of the parameter are returned as {@link ChangeType#ADDED}.

    * *

    - * Only input file properties annotated with {@link Incremental} or {@link org.gradle.api.tasks.SkipWhenEmpty} can be queried for changes. + * Only input file properties annotated with {@literal @}{@link Incremental} or {@literal @}{@link org.gradle.api.tasks.SkipWhenEmpty} can be queried for changes. *

    * * @param parameter The value of the parameter to query. @@ -108,11 +108,11 @@ public interface InputChanges { * *

    * This method allows querying properties of type {@link org.gradle.api.file.RegularFileProperty} and {@link org.gradle.api.file.DirectoryProperty} for changes. - * These two types are typically used for {@link org.gradle.api.tasks.InputFile} and {@link org.gradle.api.tasks.InputDirectory} properties. + * These two types are typically used for {@literal @}{@link org.gradle.api.tasks.InputFile} and {@literal @}{@link org.gradle.api.tasks.InputDirectory} properties. *

    * *

    - * Only input file properties annotated with {@link Incremental} or {@link org.gradle.api.tasks.SkipWhenEmpty} can be queried for changes. + * Only input file properties annotated with {@literal @}{@link Incremental} or {@literal @}{@link org.gradle.api.tasks.SkipWhenEmpty} can be queried for changes. *

    * * @param parameter The value of the parameter to query. From b6c3c457fa46446a666e327940f312a9176960a2 Mon Sep 17 00:00:00 2001 From: Stefan Wolf Date: Fri, 22 Mar 2019 10:59:14 +0100 Subject: [PATCH 680/853] Convert UnexportMainSymbol to an incremental task --- .../changes/accepted-public-api-changes.json | 6 ++ .../UnexportMainSymbolIntegrationTest.groovy | 41 +++++++++ .../swift/tasks/UnexportMainSymbol.java | 88 ++++++++++++------- 3 files changed, 102 insertions(+), 33 deletions(-) diff --git a/subprojects/distributions/src/changes/accepted-public-api-changes.json b/subprojects/distributions/src/changes/accepted-public-api-changes.json index f90808e3818c8..93b3238102699 100644 --- a/subprojects/distributions/src/changes/accepted-public-api-changes.json +++ b/subprojects/distributions/src/changes/accepted-public-api-changes.json @@ -27,6 +27,12 @@ "changes": [ "org.gradle.language.nativeplatform.tasks.AbstractNativeCompileTask.compile(org.gradle.api.tasks.incremental.IncrementalTaskInputs)" ] + }, + { + "type": "org.gradle.language.swift.tasks.UnexportMainSymbol", + "member": "Method org.gradle.language.swift.tasks.UnexportMainSymbol.unexport(org.gradle.work.InputChanges)", + "acceptation": "Migrated to the new incremental tasks API", + "changes": [] } ] } diff --git a/subprojects/language-native/src/integTest/groovy/org/gradle/language/swift/tasks/UnexportMainSymbolIntegrationTest.groovy b/subprojects/language-native/src/integTest/groovy/org/gradle/language/swift/tasks/UnexportMainSymbolIntegrationTest.groovy index 5583ecce694a9..e350b11071744 100644 --- a/subprojects/language-native/src/integTest/groovy/org/gradle/language/swift/tasks/UnexportMainSymbolIntegrationTest.groovy +++ b/subprojects/language-native/src/integTest/groovy/org/gradle/language/swift/tasks/UnexportMainSymbolIntegrationTest.groovy @@ -98,6 +98,47 @@ class UnexportMainSymbolIntegrationTest extends AbstractInstalledToolChainIntegr file("build/relocated").assertHasDescendants("main.o", "other.o") } + def "relocate _main symbol works incrementally"() { + writeMainSwift() + + when: + succeeds("unexport") + then: + assertMainSymbolIsNotExported("build/relocated/main.o") + file("build/relocated").assertHasDescendants("main.o") + + when: + def mainObject = file("build/relocated/main.o") + def oldTimestamp = mainObject.lastModified() + def otherFile = file("src/main/swift/other.swift") + otherFile << """ + class Other {} + """ + succeeds("unexport") + then: + assertMainSymbolIsNotExported("build/relocated/main.o") + file("build/relocated").assertHasDescendants("main.o", "other.o") + mainObject.lastModified() == oldTimestamp + + when: + assert otherFile.delete() + succeeds("unexport") + then: + assertMainSymbolIsNotExported("build/relocated/main.o") + file("build/relocated").assertHasDescendants("main.o") + mainObject.lastModified() == oldTimestamp + + when: + otherFile << """ + class Other {} + """ + succeeds("unexport") + assert file("build/relocated/other.o").delete() + succeeds("unexport") + then: + mainObject.lastModified() > oldTimestamp + } + def "can relocate when there is no main symbol"() { file("src/main/swift/notMain.swift") << """ class NotMain {} diff --git a/subprojects/language-native/src/main/java/org/gradle/language/swift/tasks/UnexportMainSymbol.java b/subprojects/language-native/src/main/java/org/gradle/language/swift/tasks/UnexportMainSymbol.java index 96405543578ab..7809fdbafd331 100644 --- a/subprojects/language-native/src/main/java/org/gradle/language/swift/tasks/UnexportMainSymbol.java +++ b/subprojects/language-native/src/main/java/org/gradle/language/swift/tasks/UnexportMainSymbol.java @@ -30,10 +30,14 @@ import org.gradle.api.tasks.PathSensitivity; import org.gradle.api.tasks.SkipWhenEmpty; import org.gradle.api.tasks.TaskAction; -import org.gradle.internal.os.OperatingSystem; import org.gradle.internal.UncheckedException; +import org.gradle.internal.os.OperatingSystem; import org.gradle.language.swift.tasks.internal.SymbolHider; import org.gradle.process.ExecSpec; +import org.gradle.util.GFileUtils; +import org.gradle.work.ChangeType; +import org.gradle.work.FileChange; +import org.gradle.work.InputChanges; import java.io.File; import java.io.IOException; @@ -82,40 +86,58 @@ public DirectoryProperty getOutputDirectory() { } @TaskAction - public void unexport() { - for (final File file: source) { - final File relocatedObject = outputDirectory.file(file.getName()).get().getAsFile(); - if (OperatingSystem.current().isWindows()) { - try { - final SymbolHider symbolHider = new SymbolHider(file); - symbolHider.hideSymbol("main"); // 64 bit - symbolHider.hideSymbol("_main"); // 32 bit - symbolHider.saveTo(relocatedObject); - } catch (IOException e) { - throw UncheckedException.throwAsUncheckedException(e); - } + public void unexport(InputChanges inputChanges) { + if (!inputChanges.isIncremental()) { + GFileUtils.cleanDirectory(outputDirectory.get().getAsFile()); + } + for (FileChange change : inputChanges.getFileChanges(getObjects())) { + if (change.getChangeType() == ChangeType.REMOVED) { + File relocatedFileLocation = relocatedObject(change.getFile()); + relocatedFileLocation.delete(); } else { - getProject().exec(new Action() { - @Override - public void execute(ExecSpec execSpec) { - // TODO: should use target platform to make this decision - if (OperatingSystem.current().isMacOsX()) { - execSpec.executable("ld"); // TODO: Locate this tool from a tool provider - execSpec.args(file); - execSpec.args("-o", relocatedObject); - execSpec.args("-r"); // relink, produce another object file - execSpec.args("-unexported_symbol", "_main"); // hide _main symbol - } else if (OperatingSystem.current().isLinux()) { - execSpec.executable("objcopy"); // TODO: Locate this tool from a tool provider - execSpec.args("-L", "main"); // hide main symbol - execSpec.args(file); - execSpec.args(relocatedObject); - } else { - throw new IllegalStateException("Do not know how to unexport a main symbol on " + OperatingSystem.current()); - } - } - }); + if (change.getFile().isFile()) { + unexportMainSymbol(change.getFile()); + } } } } + + private void unexportMainSymbol(File object) { + final File relocatedObject = relocatedObject(object); + if (OperatingSystem.current().isWindows()) { + try { + final SymbolHider symbolHider = new SymbolHider(object); + symbolHider.hideSymbol("main"); // 64 bit + symbolHider.hideSymbol("_main"); // 32 bit + symbolHider.saveTo(relocatedObject); + } catch (IOException e) { + throw UncheckedException.throwAsUncheckedException(e); + } + } else { + getProject().exec(new Action() { + @Override + public void execute(ExecSpec execSpec) { + // TODO: should use target platform to make this decision + if (OperatingSystem.current().isMacOsX()) { + execSpec.executable("ld"); // TODO: Locate this tool from a tool provider + execSpec.args(object); + execSpec.args("-o", relocatedObject); + execSpec.args("-r"); // relink, produce another object file + execSpec.args("-unexported_symbol", "_main"); // hide _main symbol + } else if (OperatingSystem.current().isLinux()) { + execSpec.executable("objcopy"); // TODO: Locate this tool from a tool provider + execSpec.args("-L", "main"); // hide main symbol + execSpec.args(object); + execSpec.args(relocatedObject); + } else { + throw new IllegalStateException("Do not know how to unexport a main symbol on " + OperatingSystem.current()); + } + } + }); + } + } + + private File relocatedObject(File object) { + return outputDirectory.file(object.getName()).get().getAsFile(); + } } From c146a852a57ef0fda80efbf3f30b26f3b4d2eae2 Mon Sep 17 00:00:00 2001 From: Paul Merlin Date: Fri, 22 Mar 2019 16:59:57 +0100 Subject: [PATCH 681/853] Rebaseline broken performance test Signed-off-by: Paul Merlin --- .../regression/inception/GradleInceptionPerformanceTest.groovy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subprojects/performance/src/performanceTest/groovy/org/gradle/performance/regression/inception/GradleInceptionPerformanceTest.groovy b/subprojects/performance/src/performanceTest/groovy/org/gradle/performance/regression/inception/GradleInceptionPerformanceTest.groovy index b91054344455a..c2943df222078 100644 --- a/subprojects/performance/src/performanceTest/groovy/org/gradle/performance/regression/inception/GradleInceptionPerformanceTest.groovy +++ b/subprojects/performance/src/performanceTest/groovy/org/gradle/performance/regression/inception/GradleInceptionPerformanceTest.groovy @@ -52,7 +52,7 @@ class GradleInceptionPerformanceTest extends AbstractCrossVersionPerformanceTest } def setup() { - def targetVersion = "5.3-20190226212742+0000" + def targetVersion = "5.4-20190322154513+0000" runner.targetVersions = [targetVersion] runner.minimumVersion = targetVersion } From b66f9526e927be7cc7d9e5e9ced98c93c18cd5ff Mon Sep 17 00:00:00 2001 From: Paul Merlin Date: Fri, 22 Mar 2019 17:00:25 +0100 Subject: [PATCH 682/853] Unignore disabled performance test Signed-off-by: Paul Merlin --- .../regression/inception/GradleInceptionPerformanceTest.groovy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subprojects/performance/src/performanceTest/groovy/org/gradle/performance/regression/inception/GradleInceptionPerformanceTest.groovy b/subprojects/performance/src/performanceTest/groovy/org/gradle/performance/regression/inception/GradleInceptionPerformanceTest.groovy index c2943df222078..fe5ae611c1adc 100644 --- a/subprojects/performance/src/performanceTest/groovy/org/gradle/performance/regression/inception/GradleInceptionPerformanceTest.groovy +++ b/subprojects/performance/src/performanceTest/groovy/org/gradle/performance/regression/inception/GradleInceptionPerformanceTest.groovy @@ -111,6 +111,6 @@ class GradleInceptionPerformanceTest extends AbstractCrossVersionPerformanceTest MEDIUM_MONOLITHIC_JAVA_PROJECT | "" | 40 LARGE_JAVA_MULTI_PROJECT | "" | 20 LARGE_JAVA_MULTI_PROJECT_KOTLIN_DSL | "" | 10 - // TODO:kotlin-dsl 'gradleBuildCurrent' | "subprojects/build/" | 10 + 'gradleBuildCurrent' | "subprojects/build/" | 10 } } From 69028fcb9be8e98205b25aa29ca0cae94909c13f Mon Sep 17 00:00:00 2001 From: Daniel Lacasse Date: Fri, 22 Mar 2019 18:51:24 +0100 Subject: [PATCH 683/853] Fix test failures for Swift 4.2 The ~moduleonly files appeared in Swift 4.2 releases. It's an extra file that we need to assert for. --- .../swift/SwiftIncrementalBuildIntegrationTest.groovy | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/subprojects/language-native/src/integTest/groovy/org/gradle/language/swift/SwiftIncrementalBuildIntegrationTest.groovy b/subprojects/language-native/src/integTest/groovy/org/gradle/language/swift/SwiftIncrementalBuildIntegrationTest.groovy index 6a011931b733d..0f4e75fe0541b 100644 --- a/subprojects/language-native/src/integTest/groovy/org/gradle/language/swift/SwiftIncrementalBuildIntegrationTest.groovy +++ b/subprojects/language-native/src/integTest/groovy/org/gradle/language/swift/SwiftIncrementalBuildIntegrationTest.groovy @@ -32,6 +32,7 @@ import org.gradle.nativeplatform.fixtures.app.SourceElement import org.gradle.nativeplatform.fixtures.app.SwiftApp import org.gradle.nativeplatform.fixtures.app.SwiftLib import org.gradle.test.fixtures.file.TestFile +import org.gradle.util.VersionNumber @RequiresInstalledToolChain(ToolChainRequirement.SWIFTC) class SwiftIncrementalBuildIntegrationTest extends AbstractInstalledToolChainIntegrationSpec { @@ -348,6 +349,9 @@ class SwiftIncrementalBuildIntegrationTest extends AbstractInstalledToolChainInt result.add(dependFileFor(swiftFile).relativizeFrom(intermediateFilesDir).path) result.add(swiftDepsFileFor(swiftFile).relativizeFrom(intermediateFilesDir).path) } + if (toolChain.version.compareTo(VersionNumber.parse("4.2")) >= 0) { + result.add("module.swiftdeps~moduleonly") + } result.add("module.swiftdeps") result.add("output-file-map.json") return result From de88b30e5374ede4dc393f5709fa71a7f349785e Mon Sep 17 00:00:00 2001 From: Gradleware Git Bot Date: Sat, 23 Mar 2019 02:16:36 +0100 Subject: [PATCH 684/853] Publish 5.3-20190323010048+0000 --- released-versions.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/released-versions.json b/released-versions.json index e7ef08ca5f45f..424d67e90cda0 100644 --- a/released-versions.json +++ b/released-versions.json @@ -1,7 +1,7 @@ { "latestReleaseSnapshot": { - "version": "5.3-20190322010027+0000", - "buildTime": "20190322010027+0000" + "version": "5.3-20190323010048+0000", + "buildTime": "20190323010048+0000" }, "latestRc": { "version": "5.3-rc-3", From 753a01b8f1d21cb9010fe689ffdab661a0eb81fa Mon Sep 17 00:00:00 2001 From: Sterling Greene Date: Sat, 23 Mar 2019 02:23:31 -0400 Subject: [PATCH 685/853] Convert net.jcip.annotations to javax.annotation.concurrent annotations --- .../gradle/internal/operations/BuildOperationExecutor.java | 2 +- .../main/java/org/gradle/model/internal/type/ModelType.java | 2 +- .../org/gradle/api/internal/plugins/DefaultPluginManager.java | 2 +- .../java/org/gradle/api/internal/plugins/PluginInspector.java | 2 +- .../java/org/gradle/api/internal/plugins/PluginRegistry.java | 2 +- .../api/internal/project/DeferredProjectConfiguration.java | 2 +- .../cache/internal/DefaultCrossBuildInMemoryCacheFactory.java | 2 +- .../org/gradle/deployment/internal/DeploymentRegistry.java | 2 +- .../featurelifecycle/ScriptUsageLocationReporter.java | 2 +- .../core/src/main/java/org/gradle/internal/file/JarCache.java | 2 +- .../main/java/org/gradle/internal/filewatch/FileWatcher.java | 2 +- .../service/scopes/GradleUserHomeScopeServiceRegistry.java | 2 +- .../artifacts/ivyservice/ArtifactCacheLockingManager.java | 2 +- .../api/internal/artifacts/ivyservice/IvyContextManager.java | 2 +- .../api/internal/artifacts/transform/TransformerInvoker.java | 2 +- .../java/org/gradle/api/internal/file/FileSystemSubset.java | 2 +- .../org/gradle/launcher/daemon/registry/DaemonRegistry.java | 2 +- .../internal/provider/serialization/ClassLoaderCache.java | 2 +- .../internal/provider/serialization/ClasspathInferer.java | 2 +- .../serialization/ClientSidePayloadClassLoaderRegistry.java | 2 +- .../serialization/DefaultPayloadClassLoaderRegistry.java | 2 +- .../provider/serialization/PayloadClassLoaderRegistry.java | 2 +- .../internal/provider/serialization/PayloadSerializer.java | 2 +- .../org/gradle/internal/logging/sink/OutputEventRenderer.java | 2 +- .../src/main/java/org/gradle/util/SingleMessageLogger.java | 2 +- .../gradle/model/internal/core/DefaultModelRegistration.java | 2 +- .../org/gradle/model/internal/core/DefaultModelViewState.java | 2 +- .../org/gradle/model/internal/core/InstanceModelView.java | 2 +- .../main/java/org/gradle/model/internal/core/ModelPath.java | 2 +- .../java/org/gradle/model/internal/core/ModelReference.java | 2 +- .../org/gradle/model/internal/core/ModelRegistrations.java | 4 ++-- .../core/TypeCompatibilityModelProjectionSupport.java | 2 +- .../gradle/model/internal/core/UnmanagedModelProjection.java | 2 +- .../core/rule/describe/AbstractModelRuleDescriptor.java | 2 +- .../core/rule/describe/MethodModelRuleDescriptor.java | 2 +- .../core/rule/describe/NestedModelRuleDescriptor.java | 2 +- .../core/rule/describe/SimpleModelRuleDescriptor.java | 2 +- .../model/internal/inspect/DefaultMethodRuleDefinition.java | 2 +- .../model/internal/inspect/DefaultsModelRuleExtractor.java | 2 +- .../model/internal/inspect/FinalizeModelRuleExtractor.java | 2 +- .../model/internal/inspect/MethodModelRuleExtractors.java | 2 +- .../org/gradle/model/internal/inspect/ModelRuleExtractor.java | 2 +- .../model/internal/inspect/ModelRuleSourceDetector.java | 2 +- .../model/internal/inspect/MutateModelRuleExtractor.java | 2 +- .../model/internal/inspect/ValidateModelRuleExtractor.java | 2 +- .../model/internal/manage/schema/AbstractModelSchema.java | 2 +- .../gradle/model/internal/manage/schema/ModelProperty.java | 2 +- .../gradle/model/internal/manage/schema/ModelSchemaStore.java | 2 +- .../manage/schema/extract/DefaultModelSchemaStore.java | 2 +- .../gradle/model/internal/registry/DefaultModelRegistry.java | 2 +- .../model/internal/registry/ModelPathSuggestionProvider.java | 2 +- .../java/org/gradle/model/internal/registry/RuleBinder.java | 2 +- .../gradle/model/internal/registry/UnboundRulesProcessor.java | 2 +- .../model/internal/report/AmbiguousBindingReporter.java | 2 +- .../internal/report/IncompatibleTypeReferenceReporter.java | 2 +- .../org/gradle/model/internal/report/unbound/UnboundRule.java | 4 ++-- .../model/internal/report/unbound/UnboundRuleInput.java | 4 ++-- .../model/internal/report/unbound/UnboundRulesReporter.java | 2 +- .../model/dsl/internal/NonTransformedModelDslBacking.java | 2 +- .../gradle/model/dsl/internal/TransformedModelDslBacking.java | 2 +- .../transform/ClosureCreationInterceptingVerifier.java | 2 +- .../org/gradle/cache/internal/CrossBuildInMemoryCache.java | 2 +- .../gradle/cache/internal/CrossBuildInMemoryCacheFactory.java | 2 +- .../java/org/gradle/cache/internal/DefaultCacheAccess.java | 2 +- .../main/java/org/gradle/cache/internal/FileContentCache.java | 2 +- .../internal/resource/transport/sftp/SftpClientFactory.java | 2 +- .../org/gradle/tooling/internal/adapter/TypeInspector.java | 2 +- .../java/org/gradle/workers/internal/WorkerDaemonFactory.java | 2 +- 68 files changed, 71 insertions(+), 71 deletions(-) diff --git a/subprojects/base-services/src/main/java/org/gradle/internal/operations/BuildOperationExecutor.java b/subprojects/base-services/src/main/java/org/gradle/internal/operations/BuildOperationExecutor.java index b3894ca910085..2be3733165b32 100644 --- a/subprojects/base-services/src/main/java/org/gradle/internal/operations/BuildOperationExecutor.java +++ b/subprojects/base-services/src/main/java/org/gradle/internal/operations/BuildOperationExecutor.java @@ -16,7 +16,7 @@ package org.gradle.internal.operations; -import net.jcip.annotations.ThreadSafe; +import javax.annotation.concurrent.ThreadSafe; import org.gradle.api.Action; /** diff --git a/subprojects/core-api/src/main/java/org/gradle/model/internal/type/ModelType.java b/subprojects/core-api/src/main/java/org/gradle/model/internal/type/ModelType.java index 17747b824a7ed..30c25877ebc40 100644 --- a/subprojects/core-api/src/main/java/org/gradle/model/internal/type/ModelType.java +++ b/subprojects/core-api/src/main/java/org/gradle/model/internal/type/ModelType.java @@ -18,7 +18,7 @@ import com.google.common.collect.ImmutableList; import com.google.common.reflect.TypeToken; -import net.jcip.annotations.ThreadSafe; +import javax.annotation.concurrent.ThreadSafe; import org.gradle.internal.Cast; import javax.annotation.Nullable; diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/plugins/DefaultPluginManager.java b/subprojects/core/src/main/java/org/gradle/api/internal/plugins/DefaultPluginManager.java index da9567dbb1a05..d1d89a4aba84c 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/plugins/DefaultPluginManager.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/plugins/DefaultPluginManager.java @@ -18,7 +18,7 @@ import com.google.common.collect.Lists; import com.google.common.collect.Maps; -import net.jcip.annotations.NotThreadSafe; +import javax.annotation.concurrent.NotThreadSafe; import org.gradle.api.Action; import org.gradle.api.DomainObjectSet; import org.gradle.api.Plugin; diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/plugins/PluginInspector.java b/subprojects/core/src/main/java/org/gradle/api/internal/plugins/PluginInspector.java index 9dfcf7a9777dd..7853af662f00e 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/plugins/PluginInspector.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/plugins/PluginInspector.java @@ -16,7 +16,7 @@ package org.gradle.api.internal.plugins; -import net.jcip.annotations.ThreadSafe; +import javax.annotation.concurrent.ThreadSafe; import org.gradle.api.Plugin; import org.gradle.internal.Cast; import org.gradle.model.internal.inspect.ModelRuleSourceDetector; diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/plugins/PluginRegistry.java b/subprojects/core/src/main/java/org/gradle/api/internal/plugins/PluginRegistry.java index ccbd926a6f3a3..9ad8c8a95f0f7 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/plugins/PluginRegistry.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/plugins/PluginRegistry.java @@ -16,7 +16,7 @@ package org.gradle.api.internal.plugins; -import net.jcip.annotations.ThreadSafe; +import javax.annotation.concurrent.ThreadSafe; import org.gradle.api.internal.initialization.ClassLoaderScope; import org.gradle.plugin.use.PluginId; diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/project/DeferredProjectConfiguration.java b/subprojects/core/src/main/java/org/gradle/api/internal/project/DeferredProjectConfiguration.java index c1f59f6a11ba2..502ba0590fbe3 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/project/DeferredProjectConfiguration.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/project/DeferredProjectConfiguration.java @@ -17,7 +17,7 @@ package org.gradle.api.internal.project; import com.google.common.collect.Lists; -import net.jcip.annotations.NotThreadSafe; +import javax.annotation.concurrent.NotThreadSafe; import org.gradle.api.Project; import java.util.List; diff --git a/subprojects/core/src/main/java/org/gradle/cache/internal/DefaultCrossBuildInMemoryCacheFactory.java b/subprojects/core/src/main/java/org/gradle/cache/internal/DefaultCrossBuildInMemoryCacheFactory.java index 929d69cc03e28..4d1bb524cae06 100644 --- a/subprojects/core/src/main/java/org/gradle/cache/internal/DefaultCrossBuildInMemoryCacheFactory.java +++ b/subprojects/core/src/main/java/org/gradle/cache/internal/DefaultCrossBuildInMemoryCacheFactory.java @@ -16,7 +16,7 @@ package org.gradle.cache.internal; -import net.jcip.annotations.ThreadSafe; +import javax.annotation.concurrent.ThreadSafe; import org.gradle.api.Transformer; import org.gradle.initialization.SessionLifecycleListener; import org.gradle.internal.event.ListenerManager; diff --git a/subprojects/core/src/main/java/org/gradle/deployment/internal/DeploymentRegistry.java b/subprojects/core/src/main/java/org/gradle/deployment/internal/DeploymentRegistry.java index fdc280a65c07f..9b071cc504afb 100644 --- a/subprojects/core/src/main/java/org/gradle/deployment/internal/DeploymentRegistry.java +++ b/subprojects/core/src/main/java/org/gradle/deployment/internal/DeploymentRegistry.java @@ -16,7 +16,7 @@ package org.gradle.deployment.internal; -import net.jcip.annotations.ThreadSafe; +import javax.annotation.concurrent.ThreadSafe; import javax.annotation.Nullable; diff --git a/subprojects/core/src/main/java/org/gradle/internal/featurelifecycle/ScriptUsageLocationReporter.java b/subprojects/core/src/main/java/org/gradle/internal/featurelifecycle/ScriptUsageLocationReporter.java index bd6588e3352df..b35e72efa08af 100644 --- a/subprojects/core/src/main/java/org/gradle/internal/featurelifecycle/ScriptUsageLocationReporter.java +++ b/subprojects/core/src/main/java/org/gradle/internal/featurelifecycle/ScriptUsageLocationReporter.java @@ -16,7 +16,7 @@ package org.gradle.internal.featurelifecycle; -import net.jcip.annotations.ThreadSafe; +import javax.annotation.concurrent.ThreadSafe; import org.apache.commons.lang.StringUtils; import org.gradle.groovy.scripts.Script; import org.gradle.groovy.scripts.ScriptExecutionListener; diff --git a/subprojects/core/src/main/java/org/gradle/internal/file/JarCache.java b/subprojects/core/src/main/java/org/gradle/internal/file/JarCache.java index ce18e6e02a7b2..4d285fb5beff8 100644 --- a/subprojects/core/src/main/java/org/gradle/internal/file/JarCache.java +++ b/subprojects/core/src/main/java/org/gradle/internal/file/JarCache.java @@ -16,7 +16,7 @@ package org.gradle.internal.file; -import net.jcip.annotations.ThreadSafe; +import javax.annotation.concurrent.ThreadSafe; import org.gradle.internal.Factory; import org.gradle.internal.hash.FileHasher; import org.gradle.internal.hash.HashCode; diff --git a/subprojects/core/src/main/java/org/gradle/internal/filewatch/FileWatcher.java b/subprojects/core/src/main/java/org/gradle/internal/filewatch/FileWatcher.java index a5ce92090780e..3ec9a03b8bd7c 100644 --- a/subprojects/core/src/main/java/org/gradle/internal/filewatch/FileWatcher.java +++ b/subprojects/core/src/main/java/org/gradle/internal/filewatch/FileWatcher.java @@ -16,7 +16,7 @@ package org.gradle.internal.filewatch; -import net.jcip.annotations.ThreadSafe; +import javax.annotation.concurrent.ThreadSafe; import org.gradle.api.internal.file.FileSystemSubset; import org.gradle.internal.concurrent.Stoppable; diff --git a/subprojects/core/src/main/java/org/gradle/internal/service/scopes/GradleUserHomeScopeServiceRegistry.java b/subprojects/core/src/main/java/org/gradle/internal/service/scopes/GradleUserHomeScopeServiceRegistry.java index d37c4fcd001bc..0bc8ba72fd058 100644 --- a/subprojects/core/src/main/java/org/gradle/internal/service/scopes/GradleUserHomeScopeServiceRegistry.java +++ b/subprojects/core/src/main/java/org/gradle/internal/service/scopes/GradleUserHomeScopeServiceRegistry.java @@ -16,7 +16,7 @@ package org.gradle.internal.service.scopes; -import net.jcip.annotations.ThreadSafe; +import javax.annotation.concurrent.ThreadSafe; import org.gradle.internal.service.ServiceRegistry; import java.io.File; diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/ArtifactCacheLockingManager.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/ArtifactCacheLockingManager.java index 470f4e60c8040..20863811d5e31 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/ArtifactCacheLockingManager.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/ArtifactCacheLockingManager.java @@ -15,7 +15,7 @@ */ package org.gradle.api.internal.artifacts.ivyservice; -import net.jcip.annotations.ThreadSafe; +import javax.annotation.concurrent.ThreadSafe; import org.gradle.cache.CacheAccess; import org.gradle.cache.PersistentIndexedCache; import org.gradle.internal.serialize.Serializer; diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/IvyContextManager.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/IvyContextManager.java index 660f384ff0323..904b7ac350052 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/IvyContextManager.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/IvyContextManager.java @@ -16,7 +16,7 @@ package org.gradle.api.internal.artifacts.ivyservice; -import net.jcip.annotations.ThreadSafe; +import javax.annotation.concurrent.ThreadSafe; import org.apache.ivy.Ivy; import org.gradle.api.Action; import org.gradle.api.Transformer; diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/TransformerInvoker.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/TransformerInvoker.java index d2abe8934efda..83fc9c88b5183 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/TransformerInvoker.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/TransformerInvoker.java @@ -17,7 +17,7 @@ package org.gradle.api.internal.artifacts.transform; import com.google.common.collect.ImmutableList; -import net.jcip.annotations.ThreadSafe; +import javax.annotation.concurrent.ThreadSafe; import org.gradle.internal.Try; import org.gradle.internal.fingerprint.FileCollectionFingerprinterRegistry; diff --git a/subprojects/files/src/main/java/org/gradle/api/internal/file/FileSystemSubset.java b/subprojects/files/src/main/java/org/gradle/api/internal/file/FileSystemSubset.java index 7f835e8575559..0994237fa0538 100644 --- a/subprojects/files/src/main/java/org/gradle/api/internal/file/FileSystemSubset.java +++ b/subprojects/files/src/main/java/org/gradle/api/internal/file/FileSystemSubset.java @@ -21,7 +21,7 @@ import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Iterables; -import net.jcip.annotations.ThreadSafe; +import javax.annotation.concurrent.ThreadSafe; import org.gradle.api.file.DirectoryTree; import org.gradle.api.internal.file.collections.DirectoryTrees; import org.gradle.api.tasks.util.PatternSet; diff --git a/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/registry/DaemonRegistry.java b/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/registry/DaemonRegistry.java index 54b74f8c7d38d..a284c4d6d7354 100644 --- a/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/registry/DaemonRegistry.java +++ b/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/registry/DaemonRegistry.java @@ -16,7 +16,7 @@ package org.gradle.launcher.daemon.registry; -import net.jcip.annotations.ThreadSafe; +import javax.annotation.concurrent.ThreadSafe; import org.gradle.internal.remote.Address; import java.util.Collection; diff --git a/subprojects/launcher/src/main/java/org/gradle/tooling/internal/provider/serialization/ClassLoaderCache.java b/subprojects/launcher/src/main/java/org/gradle/tooling/internal/provider/serialization/ClassLoaderCache.java index 9726b918e49b1..e3859446a2dcb 100644 --- a/subprojects/launcher/src/main/java/org/gradle/tooling/internal/provider/serialization/ClassLoaderCache.java +++ b/subprojects/launcher/src/main/java/org/gradle/tooling/internal/provider/serialization/ClassLoaderCache.java @@ -18,7 +18,7 @@ import com.google.common.cache.Cache; import com.google.common.cache.CacheBuilder; -import net.jcip.annotations.ThreadSafe; +import javax.annotation.concurrent.ThreadSafe; import org.gradle.api.Transformer; import org.gradle.internal.classloader.ClassLoaderUtils; diff --git a/subprojects/launcher/src/main/java/org/gradle/tooling/internal/provider/serialization/ClasspathInferer.java b/subprojects/launcher/src/main/java/org/gradle/tooling/internal/provider/serialization/ClasspathInferer.java index 5a39110ec5f79..446a4cabb817a 100644 --- a/subprojects/launcher/src/main/java/org/gradle/tooling/internal/provider/serialization/ClasspathInferer.java +++ b/subprojects/launcher/src/main/java/org/gradle/tooling/internal/provider/serialization/ClasspathInferer.java @@ -18,7 +18,7 @@ import com.google.common.collect.MapMaker; import com.google.common.io.ByteStreams; -import net.jcip.annotations.ThreadSafe; +import javax.annotation.concurrent.ThreadSafe; import org.gradle.api.GradleException; import org.gradle.internal.classloader.ClassLoaderUtils; import org.gradle.internal.classloader.ClasspathUtil; diff --git a/subprojects/launcher/src/main/java/org/gradle/tooling/internal/provider/serialization/ClientSidePayloadClassLoaderRegistry.java b/subprojects/launcher/src/main/java/org/gradle/tooling/internal/provider/serialization/ClientSidePayloadClassLoaderRegistry.java index ed81ea59cf28c..de6d5ccea6632 100644 --- a/subprojects/launcher/src/main/java/org/gradle/tooling/internal/provider/serialization/ClientSidePayloadClassLoaderRegistry.java +++ b/subprojects/launcher/src/main/java/org/gradle/tooling/internal/provider/serialization/ClientSidePayloadClassLoaderRegistry.java @@ -17,7 +17,7 @@ package org.gradle.tooling.internal.provider.serialization; import com.google.common.collect.Sets; -import net.jcip.annotations.ThreadSafe; +import javax.annotation.concurrent.ThreadSafe; import java.lang.ref.WeakReference; import java.net.URL; diff --git a/subprojects/launcher/src/main/java/org/gradle/tooling/internal/provider/serialization/DefaultPayloadClassLoaderRegistry.java b/subprojects/launcher/src/main/java/org/gradle/tooling/internal/provider/serialization/DefaultPayloadClassLoaderRegistry.java index 637ca3eaf6cfa..d481aebff9ce8 100644 --- a/subprojects/launcher/src/main/java/org/gradle/tooling/internal/provider/serialization/DefaultPayloadClassLoaderRegistry.java +++ b/subprojects/launcher/src/main/java/org/gradle/tooling/internal/provider/serialization/DefaultPayloadClassLoaderRegistry.java @@ -18,7 +18,7 @@ import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; -import net.jcip.annotations.ThreadSafe; +import javax.annotation.concurrent.ThreadSafe; import org.gradle.api.Transformer; import org.gradle.internal.classloader.ClassLoaderSpec; import org.gradle.internal.classloader.ClassLoaderVisitor; diff --git a/subprojects/launcher/src/main/java/org/gradle/tooling/internal/provider/serialization/PayloadClassLoaderRegistry.java b/subprojects/launcher/src/main/java/org/gradle/tooling/internal/provider/serialization/PayloadClassLoaderRegistry.java index 2cdb3d8d4da36..c91bda53f754a 100644 --- a/subprojects/launcher/src/main/java/org/gradle/tooling/internal/provider/serialization/PayloadClassLoaderRegistry.java +++ b/subprojects/launcher/src/main/java/org/gradle/tooling/internal/provider/serialization/PayloadClassLoaderRegistry.java @@ -16,7 +16,7 @@ package org.gradle.tooling.internal.provider.serialization; -import net.jcip.annotations.ThreadSafe; +import javax.annotation.concurrent.ThreadSafe; /** *

    Implementations must allow concurrent sessions. diff --git a/subprojects/launcher/src/main/java/org/gradle/tooling/internal/provider/serialization/PayloadSerializer.java b/subprojects/launcher/src/main/java/org/gradle/tooling/internal/provider/serialization/PayloadSerializer.java index cab1e79cf11a5..8401c537787e0 100644 --- a/subprojects/launcher/src/main/java/org/gradle/tooling/internal/provider/serialization/PayloadSerializer.java +++ b/subprojects/launcher/src/main/java/org/gradle/tooling/internal/provider/serialization/PayloadSerializer.java @@ -16,7 +16,7 @@ package org.gradle.tooling.internal.provider.serialization; -import net.jcip.annotations.ThreadSafe; +import javax.annotation.concurrent.ThreadSafe; import org.gradle.internal.IoActions; import org.gradle.internal.UncheckedException; import org.gradle.internal.io.StreamByteBuffer; diff --git a/subprojects/logging/src/main/java/org/gradle/internal/logging/sink/OutputEventRenderer.java b/subprojects/logging/src/main/java/org/gradle/internal/logging/sink/OutputEventRenderer.java index 58f1c86a84eff..654b0241f7f56 100644 --- a/subprojects/logging/src/main/java/org/gradle/internal/logging/sink/OutputEventRenderer.java +++ b/subprojects/logging/src/main/java/org/gradle/internal/logging/sink/OutputEventRenderer.java @@ -16,7 +16,7 @@ package org.gradle.internal.logging.sink; -import net.jcip.annotations.ThreadSafe; +import javax.annotation.concurrent.ThreadSafe; import org.gradle.api.logging.LogLevel; import org.gradle.api.logging.StandardOutputListener; import org.gradle.api.logging.configuration.ConsoleOutput; diff --git a/subprojects/logging/src/main/java/org/gradle/util/SingleMessageLogger.java b/subprojects/logging/src/main/java/org/gradle/util/SingleMessageLogger.java index 246e79860b52c..7af2969a5b2ae 100644 --- a/subprojects/logging/src/main/java/org/gradle/util/SingleMessageLogger.java +++ b/subprojects/logging/src/main/java/org/gradle/util/SingleMessageLogger.java @@ -17,7 +17,7 @@ package org.gradle.util; import com.google.common.annotations.VisibleForTesting; -import net.jcip.annotations.ThreadSafe; +import javax.annotation.concurrent.ThreadSafe; import org.gradle.api.logging.configuration.WarningMode; import org.gradle.internal.Factory; import org.gradle.internal.featurelifecycle.DeprecatedFeatureUsage; diff --git a/subprojects/model-core/src/main/java/org/gradle/model/internal/core/DefaultModelRegistration.java b/subprojects/model-core/src/main/java/org/gradle/model/internal/core/DefaultModelRegistration.java index 330fff71efc11..f28fea16d2519 100644 --- a/subprojects/model-core/src/main/java/org/gradle/model/internal/core/DefaultModelRegistration.java +++ b/subprojects/model-core/src/main/java/org/gradle/model/internal/core/DefaultModelRegistration.java @@ -18,7 +18,7 @@ import com.google.common.base.Preconditions; import com.google.common.collect.Multimap; -import net.jcip.annotations.ThreadSafe; +import javax.annotation.concurrent.ThreadSafe; import org.gradle.model.internal.core.rule.describe.ModelRuleDescriptor; @ThreadSafe diff --git a/subprojects/model-core/src/main/java/org/gradle/model/internal/core/DefaultModelViewState.java b/subprojects/model-core/src/main/java/org/gradle/model/internal/core/DefaultModelViewState.java index 198dd06f76314..337ea300b0471 100644 --- a/subprojects/model-core/src/main/java/org/gradle/model/internal/core/DefaultModelViewState.java +++ b/subprojects/model-core/src/main/java/org/gradle/model/internal/core/DefaultModelViewState.java @@ -16,7 +16,7 @@ package org.gradle.model.internal.core; -import net.jcip.annotations.NotThreadSafe; +import javax.annotation.concurrent.NotThreadSafe; import org.gradle.api.Action; import org.gradle.model.ModelViewClosedException; import org.gradle.model.ReadOnlyModelViewException; diff --git a/subprojects/model-core/src/main/java/org/gradle/model/internal/core/InstanceModelView.java b/subprojects/model-core/src/main/java/org/gradle/model/internal/core/InstanceModelView.java index 7884fa021a300..3eada97de0829 100644 --- a/subprojects/model-core/src/main/java/org/gradle/model/internal/core/InstanceModelView.java +++ b/subprojects/model-core/src/main/java/org/gradle/model/internal/core/InstanceModelView.java @@ -16,7 +16,7 @@ package org.gradle.model.internal.core; -import net.jcip.annotations.ThreadSafe; +import javax.annotation.concurrent.ThreadSafe; import org.gradle.api.Action; import org.gradle.internal.Actions; import org.gradle.model.internal.type.ModelType; diff --git a/subprojects/model-core/src/main/java/org/gradle/model/internal/core/ModelPath.java b/subprojects/model-core/src/main/java/org/gradle/model/internal/core/ModelPath.java index 468d3a6aed094..f24a4da523954 100644 --- a/subprojects/model-core/src/main/java/org/gradle/model/internal/core/ModelPath.java +++ b/subprojects/model-core/src/main/java/org/gradle/model/internal/core/ModelPath.java @@ -21,7 +21,7 @@ import com.google.common.collect.Iterables; import com.google.common.collect.Iterators; import com.google.common.collect.Lists; -import net.jcip.annotations.ThreadSafe; +import javax.annotation.concurrent.ThreadSafe; import org.gradle.api.GradleException; import org.gradle.internal.exceptions.Contextual; diff --git a/subprojects/model-core/src/main/java/org/gradle/model/internal/core/ModelReference.java b/subprojects/model-core/src/main/java/org/gradle/model/internal/core/ModelReference.java index ede8585c2d760..ea1593a3eaa03 100644 --- a/subprojects/model-core/src/main/java/org/gradle/model/internal/core/ModelReference.java +++ b/subprojects/model-core/src/main/java/org/gradle/model/internal/core/ModelReference.java @@ -18,7 +18,7 @@ import com.google.common.base.Objects; import com.google.common.base.Preconditions; -import net.jcip.annotations.ThreadSafe; +import javax.annotation.concurrent.ThreadSafe; import org.gradle.internal.Cast; import org.gradle.model.internal.type.ModelType; diff --git a/subprojects/model-core/src/main/java/org/gradle/model/internal/core/ModelRegistrations.java b/subprojects/model-core/src/main/java/org/gradle/model/internal/core/ModelRegistrations.java index 17c40811e23a9..4000fefd9d2f1 100644 --- a/subprojects/model-core/src/main/java/org/gradle/model/internal/core/ModelRegistrations.java +++ b/subprojects/model-core/src/main/java/org/gradle/model/internal/core/ModelRegistrations.java @@ -20,8 +20,8 @@ import com.google.common.collect.ImmutableList; import com.google.common.collect.ListMultimap; import com.google.common.collect.Multimap; -import net.jcip.annotations.NotThreadSafe; -import net.jcip.annotations.ThreadSafe; +import javax.annotation.concurrent.NotThreadSafe; +import javax.annotation.concurrent.ThreadSafe; import org.gradle.api.Action; import org.gradle.api.Transformer; import org.gradle.internal.Actions; diff --git a/subprojects/model-core/src/main/java/org/gradle/model/internal/core/TypeCompatibilityModelProjectionSupport.java b/subprojects/model-core/src/main/java/org/gradle/model/internal/core/TypeCompatibilityModelProjectionSupport.java index c3493ff7d3b97..d906e47ded1be 100644 --- a/subprojects/model-core/src/main/java/org/gradle/model/internal/core/TypeCompatibilityModelProjectionSupport.java +++ b/subprojects/model-core/src/main/java/org/gradle/model/internal/core/TypeCompatibilityModelProjectionSupport.java @@ -16,7 +16,7 @@ package org.gradle.model.internal.core; -import net.jcip.annotations.ThreadSafe; +import javax.annotation.concurrent.ThreadSafe; import org.gradle.internal.Cast; import org.gradle.model.internal.core.rule.describe.ModelRuleDescriptor; import org.gradle.model.internal.type.ModelType; diff --git a/subprojects/model-core/src/main/java/org/gradle/model/internal/core/UnmanagedModelProjection.java b/subprojects/model-core/src/main/java/org/gradle/model/internal/core/UnmanagedModelProjection.java index 46100d87b645a..af3faa11683b3 100644 --- a/subprojects/model-core/src/main/java/org/gradle/model/internal/core/UnmanagedModelProjection.java +++ b/subprojects/model-core/src/main/java/org/gradle/model/internal/core/UnmanagedModelProjection.java @@ -17,7 +17,7 @@ package org.gradle.model.internal.core; import com.google.common.base.Optional; -import net.jcip.annotations.ThreadSafe; +import javax.annotation.concurrent.ThreadSafe; import org.gradle.internal.Cast; import org.gradle.model.internal.core.rule.describe.ModelRuleDescriptor; import org.gradle.model.internal.type.ModelType; diff --git a/subprojects/model-core/src/main/java/org/gradle/model/internal/core/rule/describe/AbstractModelRuleDescriptor.java b/subprojects/model-core/src/main/java/org/gradle/model/internal/core/rule/describe/AbstractModelRuleDescriptor.java index 813bb855627b3..4fe61e736c4bd 100644 --- a/subprojects/model-core/src/main/java/org/gradle/model/internal/core/rule/describe/AbstractModelRuleDescriptor.java +++ b/subprojects/model-core/src/main/java/org/gradle/model/internal/core/rule/describe/AbstractModelRuleDescriptor.java @@ -16,7 +16,7 @@ package org.gradle.model.internal.core.rule.describe; -import net.jcip.annotations.ThreadSafe; +import javax.annotation.concurrent.ThreadSafe; import org.gradle.api.internal.cache.StringInterner; @ThreadSafe diff --git a/subprojects/model-core/src/main/java/org/gradle/model/internal/core/rule/describe/MethodModelRuleDescriptor.java b/subprojects/model-core/src/main/java/org/gradle/model/internal/core/rule/describe/MethodModelRuleDescriptor.java index 887ae12c995f8..8b24bbd54bb73 100644 --- a/subprojects/model-core/src/main/java/org/gradle/model/internal/core/rule/describe/MethodModelRuleDescriptor.java +++ b/subprojects/model-core/src/main/java/org/gradle/model/internal/core/rule/describe/MethodModelRuleDescriptor.java @@ -20,7 +20,7 @@ import com.google.common.base.Joiner; import com.google.common.base.Objects; import com.google.common.collect.Iterables; -import net.jcip.annotations.ThreadSafe; +import javax.annotation.concurrent.ThreadSafe; import org.gradle.api.UncheckedIOException; import org.gradle.model.internal.method.WeaklyTypeReferencingMethod; import org.gradle.model.internal.type.ModelType; diff --git a/subprojects/model-core/src/main/java/org/gradle/model/internal/core/rule/describe/NestedModelRuleDescriptor.java b/subprojects/model-core/src/main/java/org/gradle/model/internal/core/rule/describe/NestedModelRuleDescriptor.java index fe014c04901c3..01a15d2fc9a84 100644 --- a/subprojects/model-core/src/main/java/org/gradle/model/internal/core/rule/describe/NestedModelRuleDescriptor.java +++ b/subprojects/model-core/src/main/java/org/gradle/model/internal/core/rule/describe/NestedModelRuleDescriptor.java @@ -17,7 +17,7 @@ package org.gradle.model.internal.core.rule.describe; import com.google.common.base.Objects; -import net.jcip.annotations.ThreadSafe; +import javax.annotation.concurrent.ThreadSafe; import org.gradle.api.UncheckedIOException; import java.io.IOException; diff --git a/subprojects/model-core/src/main/java/org/gradle/model/internal/core/rule/describe/SimpleModelRuleDescriptor.java b/subprojects/model-core/src/main/java/org/gradle/model/internal/core/rule/describe/SimpleModelRuleDescriptor.java index bba5d0322e9ca..07973e6937e27 100644 --- a/subprojects/model-core/src/main/java/org/gradle/model/internal/core/rule/describe/SimpleModelRuleDescriptor.java +++ b/subprojects/model-core/src/main/java/org/gradle/model/internal/core/rule/describe/SimpleModelRuleDescriptor.java @@ -17,7 +17,7 @@ package org.gradle.model.internal.core.rule.describe; import com.google.common.base.Objects; -import net.jcip.annotations.ThreadSafe; +import javax.annotation.concurrent.ThreadSafe; import org.gradle.api.UncheckedIOException; import org.gradle.internal.Factories; import org.gradle.internal.Factory; diff --git a/subprojects/model-core/src/main/java/org/gradle/model/internal/inspect/DefaultMethodRuleDefinition.java b/subprojects/model-core/src/main/java/org/gradle/model/internal/inspect/DefaultMethodRuleDefinition.java index e9a921c243f9c..c3155cae838d4 100644 --- a/subprojects/model-core/src/main/java/org/gradle/model/internal/inspect/DefaultMethodRuleDefinition.java +++ b/subprojects/model-core/src/main/java/org/gradle/model/internal/inspect/DefaultMethodRuleDefinition.java @@ -17,7 +17,7 @@ package org.gradle.model.internal.inspect; import com.google.common.collect.ImmutableList; -import net.jcip.annotations.ThreadSafe; +import javax.annotation.concurrent.ThreadSafe; import org.gradle.api.specs.Spec; import org.gradle.internal.Cast; import org.gradle.model.Path; diff --git a/subprojects/model-core/src/main/java/org/gradle/model/internal/inspect/DefaultsModelRuleExtractor.java b/subprojects/model-core/src/main/java/org/gradle/model/internal/inspect/DefaultsModelRuleExtractor.java index 631092203f34b..1728ea6f1b4f7 100644 --- a/subprojects/model-core/src/main/java/org/gradle/model/internal/inspect/DefaultsModelRuleExtractor.java +++ b/subprojects/model-core/src/main/java/org/gradle/model/internal/inspect/DefaultsModelRuleExtractor.java @@ -16,7 +16,7 @@ package org.gradle.model.internal.inspect; -import net.jcip.annotations.ThreadSafe; +import javax.annotation.concurrent.ThreadSafe; import org.gradle.model.Defaults; import org.gradle.model.internal.core.ModelActionRole; diff --git a/subprojects/model-core/src/main/java/org/gradle/model/internal/inspect/FinalizeModelRuleExtractor.java b/subprojects/model-core/src/main/java/org/gradle/model/internal/inspect/FinalizeModelRuleExtractor.java index 4657021211151..93aeca82dfa4a 100644 --- a/subprojects/model-core/src/main/java/org/gradle/model/internal/inspect/FinalizeModelRuleExtractor.java +++ b/subprojects/model-core/src/main/java/org/gradle/model/internal/inspect/FinalizeModelRuleExtractor.java @@ -16,7 +16,7 @@ package org.gradle.model.internal.inspect; -import net.jcip.annotations.ThreadSafe; +import javax.annotation.concurrent.ThreadSafe; import org.gradle.model.Finalize; import org.gradle.model.internal.core.ModelActionRole; diff --git a/subprojects/model-core/src/main/java/org/gradle/model/internal/inspect/MethodModelRuleExtractors.java b/subprojects/model-core/src/main/java/org/gradle/model/internal/inspect/MethodModelRuleExtractors.java index ed6bf1d92260d..85989ccb6d10f 100644 --- a/subprojects/model-core/src/main/java/org/gradle/model/internal/inspect/MethodModelRuleExtractors.java +++ b/subprojects/model-core/src/main/java/org/gradle/model/internal/inspect/MethodModelRuleExtractors.java @@ -17,7 +17,7 @@ package org.gradle.model.internal.inspect; import com.google.common.collect.ImmutableList; -import net.jcip.annotations.ThreadSafe; +import javax.annotation.concurrent.ThreadSafe; import org.gradle.model.internal.manage.schema.ModelSchemaStore; import java.util.List; diff --git a/subprojects/model-core/src/main/java/org/gradle/model/internal/inspect/ModelRuleExtractor.java b/subprojects/model-core/src/main/java/org/gradle/model/internal/inspect/ModelRuleExtractor.java index 0c88fd3801dee..c98ee033d3369 100644 --- a/subprojects/model-core/src/main/java/org/gradle/model/internal/inspect/ModelRuleExtractor.java +++ b/subprojects/model-core/src/main/java/org/gradle/model/internal/inspect/ModelRuleExtractor.java @@ -23,7 +23,7 @@ import com.google.common.collect.ImmutableList; import com.google.common.collect.Ordering; import com.google.common.util.concurrent.UncheckedExecutionException; -import net.jcip.annotations.ThreadSafe; +import javax.annotation.concurrent.ThreadSafe; import org.gradle.api.Transformer; import org.gradle.internal.Cast; import org.gradle.internal.Factory; diff --git a/subprojects/model-core/src/main/java/org/gradle/model/internal/inspect/ModelRuleSourceDetector.java b/subprojects/model-core/src/main/java/org/gradle/model/internal/inspect/ModelRuleSourceDetector.java index 12eb516c8cccb..c77ec764e7e19 100644 --- a/subprojects/model-core/src/main/java/org/gradle/model/internal/inspect/ModelRuleSourceDetector.java +++ b/subprojects/model-core/src/main/java/org/gradle/model/internal/inspect/ModelRuleSourceDetector.java @@ -25,7 +25,7 @@ import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Iterables; -import net.jcip.annotations.ThreadSafe; +import javax.annotation.concurrent.ThreadSafe; import org.gradle.internal.Cast; import org.gradle.internal.UncheckedException; import org.gradle.model.RuleSource; diff --git a/subprojects/model-core/src/main/java/org/gradle/model/internal/inspect/MutateModelRuleExtractor.java b/subprojects/model-core/src/main/java/org/gradle/model/internal/inspect/MutateModelRuleExtractor.java index a6bd6dc30b944..86bafb310bf48 100644 --- a/subprojects/model-core/src/main/java/org/gradle/model/internal/inspect/MutateModelRuleExtractor.java +++ b/subprojects/model-core/src/main/java/org/gradle/model/internal/inspect/MutateModelRuleExtractor.java @@ -16,7 +16,7 @@ package org.gradle.model.internal.inspect; -import net.jcip.annotations.ThreadSafe; +import javax.annotation.concurrent.ThreadSafe; import org.gradle.model.Mutate; import org.gradle.model.internal.core.ModelActionRole; diff --git a/subprojects/model-core/src/main/java/org/gradle/model/internal/inspect/ValidateModelRuleExtractor.java b/subprojects/model-core/src/main/java/org/gradle/model/internal/inspect/ValidateModelRuleExtractor.java index c91b8c95592f3..031bd1331f39d 100644 --- a/subprojects/model-core/src/main/java/org/gradle/model/internal/inspect/ValidateModelRuleExtractor.java +++ b/subprojects/model-core/src/main/java/org/gradle/model/internal/inspect/ValidateModelRuleExtractor.java @@ -16,7 +16,7 @@ package org.gradle.model.internal.inspect; -import net.jcip.annotations.ThreadSafe; +import javax.annotation.concurrent.ThreadSafe; import org.gradle.model.Validate; import org.gradle.model.internal.core.ModelActionRole; diff --git a/subprojects/model-core/src/main/java/org/gradle/model/internal/manage/schema/AbstractModelSchema.java b/subprojects/model-core/src/main/java/org/gradle/model/internal/manage/schema/AbstractModelSchema.java index f853f1157b5f4..22e4a712c7d8d 100644 --- a/subprojects/model-core/src/main/java/org/gradle/model/internal/manage/schema/AbstractModelSchema.java +++ b/subprojects/model-core/src/main/java/org/gradle/model/internal/manage/schema/AbstractModelSchema.java @@ -16,7 +16,7 @@ package org.gradle.model.internal.manage.schema; -import net.jcip.annotations.ThreadSafe; +import javax.annotation.concurrent.ThreadSafe; import org.gradle.model.internal.type.ModelType; @ThreadSafe diff --git a/subprojects/model-core/src/main/java/org/gradle/model/internal/manage/schema/ModelProperty.java b/subprojects/model-core/src/main/java/org/gradle/model/internal/manage/schema/ModelProperty.java index bea59ad81b1f1..46aa3e2d1a69c 100644 --- a/subprojects/model-core/src/main/java/org/gradle/model/internal/manage/schema/ModelProperty.java +++ b/subprojects/model-core/src/main/java/org/gradle/model/internal/manage/schema/ModelProperty.java @@ -20,7 +20,7 @@ import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Maps; -import net.jcip.annotations.ThreadSafe; +import javax.annotation.concurrent.ThreadSafe; import org.gradle.internal.Cast; import org.gradle.internal.reflect.PropertyAccessorType; import org.gradle.model.internal.method.WeaklyTypeReferencingMethod; diff --git a/subprojects/model-core/src/main/java/org/gradle/model/internal/manage/schema/ModelSchemaStore.java b/subprojects/model-core/src/main/java/org/gradle/model/internal/manage/schema/ModelSchemaStore.java index 275d4f5f8c145..3baa61a357c97 100644 --- a/subprojects/model-core/src/main/java/org/gradle/model/internal/manage/schema/ModelSchemaStore.java +++ b/subprojects/model-core/src/main/java/org/gradle/model/internal/manage/schema/ModelSchemaStore.java @@ -16,7 +16,7 @@ package org.gradle.model.internal.manage.schema; -import net.jcip.annotations.ThreadSafe; +import javax.annotation.concurrent.ThreadSafe; import org.gradle.model.internal.type.ModelType; @ThreadSafe diff --git a/subprojects/model-core/src/main/java/org/gradle/model/internal/manage/schema/extract/DefaultModelSchemaStore.java b/subprojects/model-core/src/main/java/org/gradle/model/internal/manage/schema/extract/DefaultModelSchemaStore.java index 46455b9829922..81de1e1f9c2dc 100644 --- a/subprojects/model-core/src/main/java/org/gradle/model/internal/manage/schema/extract/DefaultModelSchemaStore.java +++ b/subprojects/model-core/src/main/java/org/gradle/model/internal/manage/schema/extract/DefaultModelSchemaStore.java @@ -16,7 +16,7 @@ package org.gradle.model.internal.manage.schema.extract; -import net.jcip.annotations.ThreadSafe; +import javax.annotation.concurrent.ThreadSafe; import org.gradle.model.internal.manage.schema.ModelSchema; import org.gradle.model.internal.manage.schema.ModelSchemaStore; import org.gradle.model.internal.manage.schema.cache.ModelSchemaCache; diff --git a/subprojects/model-core/src/main/java/org/gradle/model/internal/registry/DefaultModelRegistry.java b/subprojects/model-core/src/main/java/org/gradle/model/internal/registry/DefaultModelRegistry.java index 636986e9cbf90..a7463e39051b7 100644 --- a/subprojects/model-core/src/main/java/org/gradle/model/internal/registry/DefaultModelRegistry.java +++ b/subprojects/model-core/src/main/java/org/gradle/model/internal/registry/DefaultModelRegistry.java @@ -21,7 +21,7 @@ import com.google.common.collect.Iterables; import com.google.common.collect.Lists; import com.google.common.collect.Multimap; -import net.jcip.annotations.NotThreadSafe; +import javax.annotation.concurrent.NotThreadSafe; import org.gradle.model.ConfigurationCycleException; import org.gradle.model.InvalidModelRuleDeclarationException; import org.gradle.model.RuleSource; diff --git a/subprojects/model-core/src/main/java/org/gradle/model/internal/registry/ModelPathSuggestionProvider.java b/subprojects/model-core/src/main/java/org/gradle/model/internal/registry/ModelPathSuggestionProvider.java index 5318db41493b3..e3b3ca6b2b92c 100644 --- a/subprojects/model-core/src/main/java/org/gradle/model/internal/registry/ModelPathSuggestionProvider.java +++ b/subprojects/model-core/src/main/java/org/gradle/model/internal/registry/ModelPathSuggestionProvider.java @@ -19,7 +19,7 @@ import com.google.common.base.Function; import com.google.common.base.Predicate; import com.google.common.collect.Iterables; -import net.jcip.annotations.ThreadSafe; +import javax.annotation.concurrent.ThreadSafe; import org.apache.commons.lang.StringUtils; import org.gradle.api.Transformer; import org.gradle.model.internal.core.ModelPath; diff --git a/subprojects/model-core/src/main/java/org/gradle/model/internal/registry/RuleBinder.java b/subprojects/model-core/src/main/java/org/gradle/model/internal/registry/RuleBinder.java index 23adf071e2ec5..becb29b5ef6aa 100644 --- a/subprojects/model-core/src/main/java/org/gradle/model/internal/registry/RuleBinder.java +++ b/subprojects/model-core/src/main/java/org/gradle/model/internal/registry/RuleBinder.java @@ -16,7 +16,7 @@ package org.gradle.model.internal.registry; -import net.jcip.annotations.NotThreadSafe; +import javax.annotation.concurrent.NotThreadSafe; import org.gradle.api.Action; import org.gradle.model.internal.core.ModelAction; import org.gradle.model.internal.core.rule.describe.ModelRuleDescriptor; diff --git a/subprojects/model-core/src/main/java/org/gradle/model/internal/registry/UnboundRulesProcessor.java b/subprojects/model-core/src/main/java/org/gradle/model/internal/registry/UnboundRulesProcessor.java index 8bb3386f5c0f0..12ddeb7d7e1df 100644 --- a/subprojects/model-core/src/main/java/org/gradle/model/internal/registry/UnboundRulesProcessor.java +++ b/subprojects/model-core/src/main/java/org/gradle/model/internal/registry/UnboundRulesProcessor.java @@ -16,7 +16,7 @@ package org.gradle.model.internal.registry; -import net.jcip.annotations.ThreadSafe; +import javax.annotation.concurrent.ThreadSafe; import org.gradle.api.Transformer; import org.gradle.model.internal.core.ModelNode; import org.gradle.model.internal.core.ModelPath; diff --git a/subprojects/model-core/src/main/java/org/gradle/model/internal/report/AmbiguousBindingReporter.java b/subprojects/model-core/src/main/java/org/gradle/model/internal/report/AmbiguousBindingReporter.java index f905274040a3c..fef4950f41be3 100644 --- a/subprojects/model-core/src/main/java/org/gradle/model/internal/report/AmbiguousBindingReporter.java +++ b/subprojects/model-core/src/main/java/org/gradle/model/internal/report/AmbiguousBindingReporter.java @@ -17,7 +17,7 @@ package org.gradle.model.internal.report; import com.google.common.collect.ImmutableList; -import net.jcip.annotations.ThreadSafe; +import javax.annotation.concurrent.ThreadSafe; import org.gradle.model.internal.core.ModelPath; import org.gradle.model.internal.core.ModelReference; import org.gradle.model.internal.core.rule.describe.ModelRuleDescriptor; diff --git a/subprojects/model-core/src/main/java/org/gradle/model/internal/report/IncompatibleTypeReferenceReporter.java b/subprojects/model-core/src/main/java/org/gradle/model/internal/report/IncompatibleTypeReferenceReporter.java index d29f266a2beb7..88c8e40427fac 100644 --- a/subprojects/model-core/src/main/java/org/gradle/model/internal/report/IncompatibleTypeReferenceReporter.java +++ b/subprojects/model-core/src/main/java/org/gradle/model/internal/report/IncompatibleTypeReferenceReporter.java @@ -16,7 +16,7 @@ package org.gradle.model.internal.report; -import net.jcip.annotations.ThreadSafe; +import javax.annotation.concurrent.ThreadSafe; import org.gradle.model.internal.core.ModelPath; import org.gradle.model.internal.core.MutableModelNode; import org.gradle.model.internal.core.rule.describe.ModelRuleDescriptor; diff --git a/subprojects/model-core/src/main/java/org/gradle/model/internal/report/unbound/UnboundRule.java b/subprojects/model-core/src/main/java/org/gradle/model/internal/report/unbound/UnboundRule.java index d76fe5fbccb0e..73798c488dca3 100644 --- a/subprojects/model-core/src/main/java/org/gradle/model/internal/report/unbound/UnboundRule.java +++ b/subprojects/model-core/src/main/java/org/gradle/model/internal/report/unbound/UnboundRule.java @@ -17,8 +17,8 @@ package org.gradle.model.internal.report.unbound; import com.google.common.collect.ImmutableList; -import net.jcip.annotations.NotThreadSafe; -import net.jcip.annotations.ThreadSafe; +import javax.annotation.concurrent.NotThreadSafe; +import javax.annotation.concurrent.ThreadSafe; import java.io.File; import java.util.List; diff --git a/subprojects/model-core/src/main/java/org/gradle/model/internal/report/unbound/UnboundRuleInput.java b/subprojects/model-core/src/main/java/org/gradle/model/internal/report/unbound/UnboundRuleInput.java index b6c2e5664c610..95934e50085c3 100644 --- a/subprojects/model-core/src/main/java/org/gradle/model/internal/report/unbound/UnboundRuleInput.java +++ b/subprojects/model-core/src/main/java/org/gradle/model/internal/report/unbound/UnboundRuleInput.java @@ -17,8 +17,8 @@ package org.gradle.model.internal.report.unbound; import com.google.common.collect.ImmutableList; -import net.jcip.annotations.NotThreadSafe; -import net.jcip.annotations.ThreadSafe; +import javax.annotation.concurrent.NotThreadSafe; +import javax.annotation.concurrent.ThreadSafe; import org.gradle.model.internal.core.ModelPath; import org.gradle.model.internal.type.ModelType; diff --git a/subprojects/model-core/src/main/java/org/gradle/model/internal/report/unbound/UnboundRulesReporter.java b/subprojects/model-core/src/main/java/org/gradle/model/internal/report/unbound/UnboundRulesReporter.java index ec362da93cc79..9d826bfad37f1 100644 --- a/subprojects/model-core/src/main/java/org/gradle/model/internal/report/unbound/UnboundRulesReporter.java +++ b/subprojects/model-core/src/main/java/org/gradle/model/internal/report/unbound/UnboundRulesReporter.java @@ -17,7 +17,7 @@ package org.gradle.model.internal.report.unbound; import com.google.common.base.Joiner; -import net.jcip.annotations.NotThreadSafe; +import javax.annotation.concurrent.NotThreadSafe; import java.io.PrintWriter; diff --git a/subprojects/model-groovy/src/main/java/org/gradle/model/dsl/internal/NonTransformedModelDslBacking.java b/subprojects/model-groovy/src/main/java/org/gradle/model/dsl/internal/NonTransformedModelDslBacking.java index 158d2950fbcad..f5261c7218578 100644 --- a/subprojects/model-groovy/src/main/java/org/gradle/model/dsl/internal/NonTransformedModelDslBacking.java +++ b/subprojects/model-groovy/src/main/java/org/gradle/model/dsl/internal/NonTransformedModelDslBacking.java @@ -20,7 +20,7 @@ import groovy.lang.GroovyObjectSupport; import groovy.lang.MissingMethodException; import groovy.lang.MissingPropertyException; -import net.jcip.annotations.NotThreadSafe; +import javax.annotation.concurrent.NotThreadSafe; import org.gradle.api.Action; import org.gradle.api.GradleException; import org.gradle.internal.Actions; diff --git a/subprojects/model-groovy/src/main/java/org/gradle/model/dsl/internal/TransformedModelDslBacking.java b/subprojects/model-groovy/src/main/java/org/gradle/model/dsl/internal/TransformedModelDslBacking.java index ee274be1b6c1d..4ea0a034e6e84 100644 --- a/subprojects/model-groovy/src/main/java/org/gradle/model/dsl/internal/TransformedModelDslBacking.java +++ b/subprojects/model-groovy/src/main/java/org/gradle/model/dsl/internal/TransformedModelDslBacking.java @@ -17,7 +17,7 @@ package org.gradle.model.dsl.internal; import groovy.lang.Closure; -import net.jcip.annotations.ThreadSafe; +import javax.annotation.concurrent.ThreadSafe; import org.gradle.api.Action; import org.gradle.internal.file.RelativeFilePathResolver; import org.gradle.model.InvalidModelRuleDeclarationException; diff --git a/subprojects/model-groovy/src/main/java/org/gradle/model/dsl/internal/transform/ClosureCreationInterceptingVerifier.java b/subprojects/model-groovy/src/main/java/org/gradle/model/dsl/internal/transform/ClosureCreationInterceptingVerifier.java index c01ebbf474062..ddbc0e61bbde5 100644 --- a/subprojects/model-groovy/src/main/java/org/gradle/model/dsl/internal/transform/ClosureCreationInterceptingVerifier.java +++ b/subprojects/model-groovy/src/main/java/org/gradle/model/dsl/internal/transform/ClosureCreationInterceptingVerifier.java @@ -16,7 +16,7 @@ package org.gradle.model.dsl.internal.transform; -import net.jcip.annotations.ThreadSafe; +import javax.annotation.concurrent.ThreadSafe; import org.codehaus.groovy.ast.ClassHelper; import org.codehaus.groovy.ast.ClassNode; import org.gradle.api.Action; diff --git a/subprojects/persistent-cache/src/main/java/org/gradle/cache/internal/CrossBuildInMemoryCache.java b/subprojects/persistent-cache/src/main/java/org/gradle/cache/internal/CrossBuildInMemoryCache.java index 94a12c4acded5..b220c1631736f 100644 --- a/subprojects/persistent-cache/src/main/java/org/gradle/cache/internal/CrossBuildInMemoryCache.java +++ b/subprojects/persistent-cache/src/main/java/org/gradle/cache/internal/CrossBuildInMemoryCache.java @@ -16,7 +16,7 @@ package org.gradle.cache.internal; -import net.jcip.annotations.ThreadSafe; +import javax.annotation.concurrent.ThreadSafe; import org.gradle.api.Transformer; import javax.annotation.Nullable; diff --git a/subprojects/persistent-cache/src/main/java/org/gradle/cache/internal/CrossBuildInMemoryCacheFactory.java b/subprojects/persistent-cache/src/main/java/org/gradle/cache/internal/CrossBuildInMemoryCacheFactory.java index f23b4eec64fbe..f296fa4d2f0da 100644 --- a/subprojects/persistent-cache/src/main/java/org/gradle/cache/internal/CrossBuildInMemoryCacheFactory.java +++ b/subprojects/persistent-cache/src/main/java/org/gradle/cache/internal/CrossBuildInMemoryCacheFactory.java @@ -16,7 +16,7 @@ package org.gradle.cache.internal; -import net.jcip.annotations.ThreadSafe; +import javax.annotation.concurrent.ThreadSafe; /** * A factory for {@link CrossBuildInMemoryCache} instances. diff --git a/subprojects/persistent-cache/src/main/java/org/gradle/cache/internal/DefaultCacheAccess.java b/subprojects/persistent-cache/src/main/java/org/gradle/cache/internal/DefaultCacheAccess.java index eddc374b7f6dd..593b2995bcaaa 100644 --- a/subprojects/persistent-cache/src/main/java/org/gradle/cache/internal/DefaultCacheAccess.java +++ b/subprojects/persistent-cache/src/main/java/org/gradle/cache/internal/DefaultCacheAccess.java @@ -17,7 +17,7 @@ import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Objects; -import net.jcip.annotations.ThreadSafe; +import javax.annotation.concurrent.ThreadSafe; import org.gradle.api.Action; import org.gradle.api.GradleException; import org.gradle.cache.AsyncCacheAccess; diff --git a/subprojects/persistent-cache/src/main/java/org/gradle/cache/internal/FileContentCache.java b/subprojects/persistent-cache/src/main/java/org/gradle/cache/internal/FileContentCache.java index 9d76c9dfd2da1..aefb4187dfb4c 100644 --- a/subprojects/persistent-cache/src/main/java/org/gradle/cache/internal/FileContentCache.java +++ b/subprojects/persistent-cache/src/main/java/org/gradle/cache/internal/FileContentCache.java @@ -16,7 +16,7 @@ package org.gradle.cache.internal; -import net.jcip.annotations.ThreadSafe; +import javax.annotation.concurrent.ThreadSafe; import java.io.File; diff --git a/subprojects/resources-sftp/src/main/java/org/gradle/internal/resource/transport/sftp/SftpClientFactory.java b/subprojects/resources-sftp/src/main/java/org/gradle/internal/resource/transport/sftp/SftpClientFactory.java index f554e82ac27c0..6a0ea29ba2240 100644 --- a/subprojects/resources-sftp/src/main/java/org/gradle/internal/resource/transport/sftp/SftpClientFactory.java +++ b/subprojects/resources-sftp/src/main/java/org/gradle/internal/resource/transport/sftp/SftpClientFactory.java @@ -20,7 +20,7 @@ import com.google.common.collect.ListMultimap; import com.google.common.collect.Lists; import com.jcraft.jsch.*; -import net.jcip.annotations.ThreadSafe; +import javax.annotation.concurrent.ThreadSafe; import org.gradle.api.artifacts.repositories.PasswordCredentials; import org.gradle.api.resources.ResourceException; import org.gradle.internal.concurrent.CompositeStoppable; diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/adapter/TypeInspector.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/adapter/TypeInspector.java index 4a64757a2786c..886a30ed014b9 100644 --- a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/adapter/TypeInspector.java +++ b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/adapter/TypeInspector.java @@ -16,7 +16,7 @@ package org.gradle.tooling.internal.adapter; -import net.jcip.annotations.ThreadSafe; +import javax.annotation.concurrent.ThreadSafe; import java.lang.reflect.GenericArrayType; import java.lang.reflect.Method; diff --git a/subprojects/workers/src/main/java/org/gradle/workers/internal/WorkerDaemonFactory.java b/subprojects/workers/src/main/java/org/gradle/workers/internal/WorkerDaemonFactory.java index 2d97f3945b3a1..5a4c440aa4c7b 100644 --- a/subprojects/workers/src/main/java/org/gradle/workers/internal/WorkerDaemonFactory.java +++ b/subprojects/workers/src/main/java/org/gradle/workers/internal/WorkerDaemonFactory.java @@ -16,7 +16,7 @@ package org.gradle.workers.internal; -import net.jcip.annotations.ThreadSafe; +import javax.annotation.concurrent.ThreadSafe; import org.gradle.internal.operations.BuildOperationExecutor; import org.gradle.internal.operations.BuildOperationRef; import org.gradle.workers.IsolationMode; From b3c1c2bd13a39beee8fef10110bf00d753427017 Mon Sep 17 00:00:00 2001 From: Sterling Greene Date: Sat, 23 Mar 2019 02:40:25 -0400 Subject: [PATCH 686/853] Fix spelling of class name --- ...rametrizedActionRunner.java => ParameterizedActionRunner.java} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/connection/{ParametrizedActionRunner.java => ParameterizedActionRunner.java} (100%) diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/connection/ParametrizedActionRunner.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/connection/ParameterizedActionRunner.java similarity index 100% rename from subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/connection/ParametrizedActionRunner.java rename to subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/connection/ParameterizedActionRunner.java From 61c21e844d065e0be2305a5ba9e59d8c9c27fbfe Mon Sep 17 00:00:00 2001 From: "Rodrigo B. de Oliveira" Date: Sat, 23 Mar 2019 11:19:59 -0300 Subject: [PATCH 687/853] Let `TaskPropertyValidationPlugin` configure existing task For compatibility with projects which make use of `java-gradle-plugin` such as `:kotlinDslPlugins`. --- .../TaskPropertyValidationPlugin.kt | 52 +++++++++++++------ 1 file changed, 35 insertions(+), 17 deletions(-) diff --git a/buildSrc/subprojects/buildquality/src/main/kotlin/org/gradle/gradlebuild/buildquality/TaskPropertyValidationPlugin.kt b/buildSrc/subprojects/buildquality/src/main/kotlin/org/gradle/gradlebuild/buildquality/TaskPropertyValidationPlugin.kt index 11ffcbe9a9d71..6b1157ade0615 100644 --- a/buildSrc/subprojects/buildquality/src/main/kotlin/org/gradle/gradlebuild/buildquality/TaskPropertyValidationPlugin.kt +++ b/buildSrc/subprojects/buildquality/src/main/kotlin/org/gradle/gradlebuild/buildquality/TaskPropertyValidationPlugin.kt @@ -17,10 +17,13 @@ package org.gradle.gradlebuild.buildquality import accessors.java import accessors.reporting + import org.gradle.api.Plugin import org.gradle.api.Project +import org.gradle.api.artifacts.Configuration import org.gradle.api.attributes.Usage import org.gradle.api.tasks.testing.Test + import org.gradle.kotlin.dsl.* import org.gradle.plugin.devel.tasks.ValidateTaskProperties @@ -36,28 +39,29 @@ const val reportFileName = "task-properties/report.txt" open class TaskPropertyValidationPlugin : Plugin { override fun apply(project: Project): Unit = project.run { - project.afterEvaluate { + afterEvaluate { // This is in an after evaluate block to defer the decision until after the `java-gradle-plugin` may have been applied, so as to not collide with it // It would be better to use some convention plugins instead, that apply a fixes set of plugins (including this one) - if (plugins.hasPlugin("java-base") && !plugins.hasPlugin("java-gradle-plugin")) { - configurations.create("validationRuntime") { + if (plugins.hasPlugin("java-base")) { + val validationRuntime by configurations.creating { isCanBeConsumed = false - attributes.attribute(Usage.USAGE_ATTRIBUTE, project.objects.named(Usage.JAVA_RUNTIME)) + attributes.attribute(Usage.USAGE_ATTRIBUTE, objects.named(Usage.JAVA_RUNTIME)) } - dependencies.add("validationRuntime", dependencies.project(":distributions")) - val validateTask = tasks.register(validateTaskName, ValidateTaskProperties::class) { - val main by java.sourceSets - dependsOn(main.output) - classes.setFrom(main.output.classesDirs) - classpath.from(main.output) // to pick up resources too - classpath.from(main.runtimeClasspath) - classpath.from(configurations["validationRuntime"]) - // TODO Should we provide a more intuitive way in the task definition to configure this property from Kotlin? - outputFile.set(reporting.baseDirectory.file(reportFileName)) - failOnWarning = true - enableStricterValidation = true + dependencies.add( + validationRuntime.name, + dependencies.project(":distributions") + ) + + val validateTask = if (plugins.hasPlugin("java-gradle-plugin")) { + tasks.named(validateTaskName, ValidateTaskProperties::class) + } else { + tasks.register(validateTaskName, ValidateTaskProperties::class) } - tasks.named("codeQuality").configure { + + validateTask { + configureValidateTask(validationRuntime) + } + tasks.named("codeQuality") { dependsOn(validateTask) } tasks.withType(Test::class).configureEach { @@ -66,4 +70,18 @@ open class TaskPropertyValidationPlugin : Plugin { } } } + + private + fun ValidateTaskProperties.configureValidateTask(validationRuntime: Configuration) { + val main by project.java.sourceSets + dependsOn(main.output) + classes.setFrom(main.output.classesDirs) + classpath.from(main.output) // to pick up resources too + classpath.from(main.runtimeClasspath) + classpath.from(validationRuntime) + // TODO Should we provide a more intuitive way in the task definition to configure this property from Kotlin? + outputFile.set(project.reporting.baseDirectory.file(reportFileName)) + failOnWarning = true + enableStricterValidation = true + } } From c3777d69f879fe7349549eb582dc61bd3d66546d Mon Sep 17 00:00:00 2001 From: Gradleware Git Bot Date: Sun, 24 Mar 2019 02:20:03 +0100 Subject: [PATCH 688/853] Publish 5.3-20190324010045+0000 --- released-versions.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/released-versions.json b/released-versions.json index 424d67e90cda0..523009243831d 100644 --- a/released-versions.json +++ b/released-versions.json @@ -1,7 +1,7 @@ { "latestReleaseSnapshot": { - "version": "5.3-20190323010048+0000", - "buildTime": "20190323010048+0000" + "version": "5.3-20190324010045+0000", + "buildTime": "20190324010045+0000" }, "latestRc": { "version": "5.3-rc-3", From b6fe036e7fc6bd966a6ced0b887d6f963bfcce13 Mon Sep 17 00:00:00 2001 From: Sterling Greene Date: Sun, 24 Mar 2019 19:47:08 -0400 Subject: [PATCH 689/853] Add defaultTasks to Project DSL ref --- subprojects/docs/src/docs/dsl/org.gradle.api.Project.xml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/subprojects/docs/src/docs/dsl/org.gradle.api.Project.xml b/subprojects/docs/src/docs/dsl/org.gradle.api.Project.xml index 3f8684f94a9a0..fe5ee1b3622c6 100644 --- a/subprojects/docs/src/docs/dsl/org.gradle.api.Project.xml +++ b/subprojects/docs/src/docs/dsl/org.gradle.api.Project.xml @@ -233,6 +233,9 @@ normalization + + defaultTasks + From 7d6ff017ec104767f7fd098e9af71ad2c6c41048 Mon Sep 17 00:00:00 2001 From: Sterling Greene Date: Sun, 24 Mar 2019 19:52:16 -0400 Subject: [PATCH 690/853] remove dependency on jcip --- gradle/dependencies.gradle | 1 - subprojects/base-services/base-services.gradle.kts | 1 - subprojects/core-api/core-api.gradle.kts | 1 - subprojects/core/core.gradle.kts | 1 - .../dependency-management/dependency-management.gradle.kts | 1 - subprojects/logging/logging.gradle.kts | 1 - subprojects/model-groovy/model-groovy.gradle.kts | 1 - subprojects/persistent-cache/persistent-cache.gradle | 1 - subprojects/resources-sftp/resources-sftp.gradle | 1 - subprojects/tooling-api/tooling-api.gradle.kts | 1 - subprojects/workers/workers.gradle.kts | 1 - 11 files changed, 11 deletions(-) diff --git a/gradle/dependencies.gradle b/gradle/dependencies.gradle index ab647234d8653..454eef68d34fe 100755 --- a/gradle/dependencies.gradle +++ b/gradle/dependencies.gradle @@ -67,7 +67,6 @@ libraries.jansi = [coordinates: 'org.fusesource.jansi:jansi', vers libraries.jatl = [coordinates: 'com.googlecode.jatl:jatl', version: '0.2.3'] libraries.jaxb = [coordinates: 'com.sun.xml.bind:jaxb-impl', version: '2.3.1'] libraries.jcifs = [coordinates: 'org.samba.jcifs:jcifs', version: '1.3.17'] -libraries.jcip = [coordinates: 'net.jcip:jcip-annotations', version: '1.0'] libraries.jgit = [coordinates: 'org.eclipse.jgit:org.eclipse.jgit', version: '5.0.3.201809091024-r'] libraries.joda = [coordinates: 'joda-time:joda-time', version: '2.10'] libraries.jsch = [coordinates: 'com.jcraft:jsch', version: '0.1.54'] diff --git a/subprojects/base-services/base-services.gradle.kts b/subprojects/base-services/base-services.gradle.kts index 0e41356b8dda3..3e198fbf5bcd5 100644 --- a/subprojects/base-services/base-services.gradle.kts +++ b/subprojects/base-services/base-services.gradle.kts @@ -27,7 +27,6 @@ dependencies { implementation(library("slf4j_api")) implementation(library("commons_lang")) implementation(library("commons_io")) - implementation(library("jcip")) implementation(library("asm")) jmh(library("bouncycastle_provider")) { diff --git a/subprojects/core-api/core-api.gradle.kts b/subprojects/core-api/core-api.gradle.kts index 367fc59afbbb7..a873b83be2369 100644 --- a/subprojects/core-api/core-api.gradle.kts +++ b/subprojects/core-api/core-api.gradle.kts @@ -32,7 +32,6 @@ dependencies { implementation(library("ant")) implementation(library("commons_io")) implementation(library("commons_lang")) - implementation(library("jcip")) implementation(library("inject")) testFixturesImplementation(project(":internalTesting")) diff --git a/subprojects/core/core.gradle.kts b/subprojects/core/core.gradle.kts index d570d40ec541a..29358741e2dc9 100755 --- a/subprojects/core/core.gradle.kts +++ b/subprojects/core/core.gradle.kts @@ -65,7 +65,6 @@ dependencies { implementation(library("commons_collections")) implementation(library("commons_io")) implementation(library("commons_lang")) - implementation(library("jcip")) implementation(library("nativePlatform")) implementation(library("commons_compress")) implementation(library("xmlApis")) diff --git a/subprojects/dependency-management/dependency-management.gradle.kts b/subprojects/dependency-management/dependency-management.gradle.kts index 52512a4e1eabc..830c30039c94e 100644 --- a/subprojects/dependency-management/dependency-management.gradle.kts +++ b/subprojects/dependency-management/dependency-management.gradle.kts @@ -37,7 +37,6 @@ dependencies { implementation(library("ivy")) implementation(library("slf4j_api")) implementation(library("gson")) - implementation(library("jcip")) implementation(library("maven3")) runtimeOnly(library("bouncycastle_provider")) diff --git a/subprojects/logging/logging.gradle.kts b/subprojects/logging/logging.gradle.kts index 734770fd3ff08..ed99d53996c2b 100644 --- a/subprojects/logging/logging.gradle.kts +++ b/subprojects/logging/logging.gradle.kts @@ -21,7 +21,6 @@ dependencies { implementation(library("commons_lang")) implementation(library("guava")) implementation(library("jansi")) - implementation(library("jcip")) runtimeOnly(library("log4j_to_slf4j")) runtimeOnly(library("jcl_to_slf4j")) diff --git a/subprojects/model-groovy/model-groovy.gradle.kts b/subprojects/model-groovy/model-groovy.gradle.kts index 3be14d2a2d536..ea7a4b6bd62e6 100644 --- a/subprojects/model-groovy/model-groovy.gradle.kts +++ b/subprojects/model-groovy/model-groovy.gradle.kts @@ -31,7 +31,6 @@ dependencies { api(library("groovy")) implementation(project(":baseServicesGroovy")) - implementation(library("jcip")) implementation(library("guava")) } diff --git a/subprojects/persistent-cache/persistent-cache.gradle b/subprojects/persistent-cache/persistent-cache.gradle index 1e32799d8163a..0a50a7ad5a22f 100644 --- a/subprojects/persistent-cache/persistent-cache.gradle +++ b/subprojects/persistent-cache/persistent-cache.gradle @@ -27,7 +27,6 @@ dependencies { api project(":native") api project(":resources") api project(":logging") - api libraries.jcip.coordinates implementation libraries.commons_collections.coordinates implementation libraries.commons_io.coordinates diff --git a/subprojects/resources-sftp/resources-sftp.gradle b/subprojects/resources-sftp/resources-sftp.gradle index ee202064e914d..b8037ab3db51a 100644 --- a/subprojects/resources-sftp/resources-sftp.gradle +++ b/subprojects/resources-sftp/resources-sftp.gradle @@ -28,7 +28,6 @@ dependencies { implementation libraries.slf4j_api.coordinates implementation libraries.guava.coordinates implementation libraries.jsch.coordinates - implementation libraries.jcip.coordinates implementation libraries.commons_io.coordinates } diff --git a/subprojects/tooling-api/tooling-api.gradle.kts b/subprojects/tooling-api/tooling-api.gradle.kts index 92ed24e9ba7cf..860aea0a6f110 100644 --- a/subprojects/tooling-api/tooling-api.gradle.kts +++ b/subprojects/tooling-api/tooling-api.gradle.kts @@ -46,7 +46,6 @@ dependencies { compile(project(":wrapper")) compile(project(":baseServices")) publishCompile(library("slf4j_api")) { version { prefer(libraryVersion("slf4j_api")) } } - compile(library("jcip")) testFixturesApi(project(":baseServicesGroovy")) testFixturesApi(project(":internalIntegTesting")) diff --git a/subprojects/workers/workers.gradle.kts b/subprojects/workers/workers.gradle.kts index bbdfc0cc13cf1..fb87aa319cae4 100644 --- a/subprojects/workers/workers.gradle.kts +++ b/subprojects/workers/workers.gradle.kts @@ -6,7 +6,6 @@ plugins { dependencies { compile(project(":core")) - compile(library("jcip")) integTestCompile(project(":internalIntegTesting")) testFixturesApi(project(":internalTesting")) From 59750635b9e2a4de98b9161eb2bdb9a104a96753 Mon Sep 17 00:00:00 2001 From: Gradleware Git Bot Date: Mon, 25 Mar 2019 02:35:40 +0100 Subject: [PATCH 691/853] Publish 5.3-20190325011929+0000 --- released-versions.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/released-versions.json b/released-versions.json index 523009243831d..cb81b8b921fc7 100644 --- a/released-versions.json +++ b/released-versions.json @@ -1,7 +1,7 @@ { "latestReleaseSnapshot": { - "version": "5.3-20190324010045+0000", - "buildTime": "20190324010045+0000" + "version": "5.3-20190325011929+0000", + "buildTime": "20190325011929+0000" }, "latestRc": { "version": "5.3-rc-3", From 084e6406e4166acc67dd0d420ed9dde8b3dd330f Mon Sep 17 00:00:00 2001 From: Bo Zhang Date: Mon, 25 Mar 2019 10:06:30 +0800 Subject: [PATCH 692/853] Fix jar count after removing jcip In https://github.com/gradle/gradle/commit/7d6ff017ec104767f7fd098e9af71ad2c6c41048 we removed jcip. This commit decrements the lib jar count. --- .../groovy/org/gradle/DistributionIntegrationSpec.groovy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subprojects/distributions/src/integTest/groovy/org/gradle/DistributionIntegrationSpec.groovy b/subprojects/distributions/src/integTest/groovy/org/gradle/DistributionIntegrationSpec.groovy index 7538b3f6b359d..ca7496b3ab3e2 100644 --- a/subprojects/distributions/src/integTest/groovy/org/gradle/DistributionIntegrationSpec.groovy +++ b/subprojects/distributions/src/integTest/groovy/org/gradle/DistributionIntegrationSpec.groovy @@ -51,7 +51,7 @@ abstract class DistributionIntegrationSpec extends AbstractIntegrationSpec { * Change this if you added or removed dependencies. */ int getThirdPartyLibJarsCount() { - 180 + 179 } int getLibJarsCount() { From 5104026acc199bfb7ac9429594eebc151fc995c6 Mon Sep 17 00:00:00 2001 From: Sterling Greene Date: Sun, 24 Mar 2019 22:15:21 -0400 Subject: [PATCH 693/853] Decrease expected count of 3rd party jars --- .../groovy/org/gradle/DistributionIntegrationSpec.groovy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subprojects/distributions/src/integTest/groovy/org/gradle/DistributionIntegrationSpec.groovy b/subprojects/distributions/src/integTest/groovy/org/gradle/DistributionIntegrationSpec.groovy index ca7496b3ab3e2..07a4ae2a7a11c 100644 --- a/subprojects/distributions/src/integTest/groovy/org/gradle/DistributionIntegrationSpec.groovy +++ b/subprojects/distributions/src/integTest/groovy/org/gradle/DistributionIntegrationSpec.groovy @@ -51,7 +51,7 @@ abstract class DistributionIntegrationSpec extends AbstractIntegrationSpec { * Change this if you added or removed dependencies. */ int getThirdPartyLibJarsCount() { - 179 + 178 } int getLibJarsCount() { From 2358dc1b8317bffc2e744ca548a9bff3459e8c82 Mon Sep 17 00:00:00 2001 From: Bo Zhang Date: Mon, 25 Mar 2019 10:25:41 +0800 Subject: [PATCH 694/853] Upgrade tagging plugin to 0.63 --- build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle.kts b/build.gradle.kts index d0989755ac27f..b8b86a1570559 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -32,7 +32,7 @@ plugins { // We have to apply it here at the moment, so that when the build scan plugin is auto-applied via --scan can detect that // the plugin has been already applied. For that the plugin has to be applied with the new plugin DSL syntax. com.gradle.`build-scan` - id("org.gradle.ci.tag-single-build") version("0.62") + id("org.gradle.ci.tag-single-build") version("0.63") } defaultTasks("assemble") From 2973a25445ca16aa657754d130902c62ff45d137 Mon Sep 17 00:00:00 2001 From: Bo Zhang Date: Mon, 25 Mar 2019 10:27:50 +0800 Subject: [PATCH 695/853] Revert "Decrease expected count of 3rd party jars" This reverts commit 5104026acc199bfb7ac9429594eebc151fc995c6. --- .../groovy/org/gradle/DistributionIntegrationSpec.groovy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subprojects/distributions/src/integTest/groovy/org/gradle/DistributionIntegrationSpec.groovy b/subprojects/distributions/src/integTest/groovy/org/gradle/DistributionIntegrationSpec.groovy index 07a4ae2a7a11c..ca7496b3ab3e2 100644 --- a/subprojects/distributions/src/integTest/groovy/org/gradle/DistributionIntegrationSpec.groovy +++ b/subprojects/distributions/src/integTest/groovy/org/gradle/DistributionIntegrationSpec.groovy @@ -51,7 +51,7 @@ abstract class DistributionIntegrationSpec extends AbstractIntegrationSpec { * Change this if you added or removed dependencies. */ int getThirdPartyLibJarsCount() { - 178 + 179 } int getLibJarsCount() { From 5b4fc4e42a162a1d811d9d66318ebe62d207fd93 Mon Sep 17 00:00:00 2001 From: Sterling Greene Date: Mon, 25 Mar 2019 01:45:08 -0400 Subject: [PATCH 696/853] Put release notes in the release notes and not the template... --- subprojects/docs/src/docs/release/notes-template.md | 4 ---- subprojects/docs/src/docs/release/notes.md | 4 ++++ 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/subprojects/docs/src/docs/release/notes-template.md b/subprojects/docs/src/docs/release/notes-template.md index 06e7f985490d4..1045880aa6246 100644 --- a/subprojects/docs/src/docs/release/notes-template.md +++ b/subprojects/docs/src/docs/release/notes-template.md @@ -26,10 +26,6 @@ Switch your build to use Gradle @version@ by updating your wrapper: `./gradlew wrapper --gradle-version=@version@` -## Support for JDK12 - -Gradle now supports running on [JDK12](https://jdk.java.net/12/). - ## Promoted features Promoted features are features that were incubating in previous versions of Gradle but are now supported and subject to backwards compatibility. See the User Manual section on the “[Feature Lifecycle](userguide/feature_lifecycle.html)” for more information. diff --git a/subprojects/docs/src/docs/release/notes.md b/subprojects/docs/src/docs/release/notes.md index 155cd36cfcdbe..c0612b401bbde 100644 --- a/subprojects/docs/src/docs/release/notes.md +++ b/subprojects/docs/src/docs/release/notes.md @@ -26,6 +26,10 @@ Switch your build to use Gradle @version@ by updating your wrapper properties: `./gradlew wrapper --gradle-version=@version@` +## Support for JDK12 + +Gradle now supports running on [JDK12](https://jdk.java.net/12/). + ## Promoted features Promoted features are features that were incubating in previous versions of Gradle but are now supported and subject to backwards compatibility. See the User Manual section on the “[Feature Lifecycle](userguide/feature_lifecycle.html)” for more information. From 09d01372f92cb404af1b804d7bf4e5e453bf1f8e Mon Sep 17 00:00:00 2001 From: Sterling Greene Date: Mon, 25 Mar 2019 02:05:04 -0400 Subject: [PATCH 697/853] Create SUPPORT.md --- .github/SUPPORT.md | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 .github/SUPPORT.md diff --git a/.github/SUPPORT.md b/.github/SUPPORT.md new file mode 100644 index 0000000000000..1f89f0370daa3 --- /dev/null +++ b/.github/SUPPORT.md @@ -0,0 +1,9 @@ +# Getting Help with Gradle + +You can search for [help](https://gradle.org/help/) across our website, forums and StackOverflow. + +You can attend one of our [FREE online classes](https://gradle.org/training/). + +You can subscribe to our [monthly newsletter](https://newsletter.gradle.com/). + +We have lots of [other resources](https://gradle.org/resources/) to help you learn more about Gradle. From 1e905b0c56d7ad9319e15567dc428537cb58c687 Mon Sep 17 00:00:00 2001 From: Sterling Greene Date: Mon, 25 Mar 2019 02:19:15 -0400 Subject: [PATCH 698/853] Add detailed issue templates --- .github/ISSUE_TEMPLATE/bug_report.md | 37 ++++++++++++++++++++++ .github/ISSUE_TEMPLATE/feature_request.md | 28 +++++++++++++++++ .github/ISSUE_TEMPLATE/regression.md | 38 +++++++++++++++++++++++ 3 files changed, 103 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE/bug_report.md create mode 100644 .github/ISSUE_TEMPLATE/feature_request.md create mode 100644 .github/ISSUE_TEMPLATE/regression.md diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 0000000000000..38ca8d8d47a4e --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,37 @@ +--- +name: Bug report +about: Create a report to help us improve +title: '' +labels: '' +assignees: '' + +--- + + + + + +### Expected Behavior + + +### Current Behavior + + +### Context + + + +### Steps to Reproduce + + + +### Your Environment + + +Build scan URL: diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 0000000000000..c9f03625b66d6 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,28 @@ +--- +name: Feature request +about: Suggest an idea for this project +title: '' +labels: '' +assignees: '' + +--- + + + + + +### Expected Behavior + + +### Current Behavior + + +### Context + + diff --git a/.github/ISSUE_TEMPLATE/regression.md b/.github/ISSUE_TEMPLATE/regression.md new file mode 100644 index 0000000000000..c961c4ee47331 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/regression.md @@ -0,0 +1,38 @@ +--- +name: Regression +about: Report a problem about something that used to work. +title: '' +labels: '' +assignees: '' + +--- + + + + + +### Expected Behavior + + +### Current Behavior + + +### Context + + + + +### Steps to Reproduce + + + +### Your Environment + + +Build scan URL: From c4f884b2ad513490f49943bc2e22f74b363ecebb Mon Sep 17 00:00:00 2001 From: Sterling Greene Date: Mon, 25 Mar 2019 02:19:28 -0400 Subject: [PATCH 699/853] Delete ISSUE_TEMPLATE.md --- .github/ISSUE_TEMPLATE.md | 30 ------------------------------ 1 file changed, 30 deletions(-) delete mode 100644 .github/ISSUE_TEMPLATE.md diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md deleted file mode 100644 index 0d9dead258039..0000000000000 --- a/.github/ISSUE_TEMPLATE.md +++ /dev/null @@ -1,30 +0,0 @@ - - - - -### Expected Behavior - - - -### Current Behavior - - - -### Context - - - -### Steps to Reproduce (for bugs) - - - -### Your Environment - - - * Build scan URL: From 0c5fbfcaff53c68d4cec5c484d4a96fa2f62e4f4 Mon Sep 17 00:00:00 2001 From: Sterling Greene Date: Mon, 25 Mar 2019 02:22:11 -0400 Subject: [PATCH 700/853] Update regression template --- .github/ISSUE_TEMPLATE/regression.md | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/regression.md b/.github/ISSUE_TEMPLATE/regression.md index c961c4ee47331..9cb1fa40e500b 100644 --- a/.github/ISSUE_TEMPLATE/regression.md +++ b/.github/ISSUE_TEMPLATE/regression.md @@ -1,18 +1,14 @@ --- name: Regression -about: Report a problem about something that used to work. +about: Report a problem about something that used to work title: '' -labels: '' +labels: a:regression assignees: '' --- From dea7412537e43dc364facaae81c35afdf53d4e95 Mon Sep 17 00:00:00 2001 From: Stefan Wolf Date: Mon, 25 Mar 2019 08:48:37 +0100 Subject: [PATCH 701/853] Fix flakiness in UnexportMainSymbolIntegrationTest Fixes gradle/gradle-private#1989 --- .../swift/tasks/UnexportMainSymbolIntegrationTest.groovy | 1 + 1 file changed, 1 insertion(+) diff --git a/subprojects/language-native/src/integTest/groovy/org/gradle/language/swift/tasks/UnexportMainSymbolIntegrationTest.groovy b/subprojects/language-native/src/integTest/groovy/org/gradle/language/swift/tasks/UnexportMainSymbolIntegrationTest.groovy index e350b11071744..9e985801d5b4b 100644 --- a/subprojects/language-native/src/integTest/groovy/org/gradle/language/swift/tasks/UnexportMainSymbolIntegrationTest.groovy +++ b/subprojects/language-native/src/integTest/groovy/org/gradle/language/swift/tasks/UnexportMainSymbolIntegrationTest.groovy @@ -109,6 +109,7 @@ class UnexportMainSymbolIntegrationTest extends AbstractInstalledToolChainIntegr when: def mainObject = file("build/relocated/main.o") + mainObject.makeOlder() def oldTimestamp = mainObject.lastModified() def otherFile = file("src/main/swift/other.swift") otherFile << """ From 3acd573a38de1cc69ca3971df05b3a432e9dc3e7 Mon Sep 17 00:00:00 2001 From: Donat Csikos Date: Wed, 20 Mar 2019 17:45:24 +0100 Subject: [PATCH 702/853] Run tasks upon Eclipse synchronization This commit implements the Gradle side of the 'Run tasks upon synchronization' story for Buildship: https://github.com/eclipse/buildship/issues/265 It contributes a new `eclipse.synchronizationTasks` configuration. By using the phased build action API, clients can execute the configured tasks and load the Eclipse model in one step. Also, the task information never needs to leave the Gradle process. --- .../plugins/ide/eclipse/EclipsePlugin.java | 2 +- .../ide/eclipse/model/EclipseModel.java | 37 ++++ ...RunEclipseSynchronizationTasksBuilder.java | 68 ++++++ .../tooling/ToolingModelServices.java | 1 + .../ide/eclipse/model/EclipseModelTest.groovy | 3 +- .../IntermediateResultHandlerCollector.java | 32 +++ .../tooling/r54/LoadEclipseModel.java | 31 +++ ...ynchronizationTasksCrossVersionSpec.groovy | 201 ++++++++++++++++++ .../tooling/r54/TellGradleToRunSyncTasks.java | 32 +++ .../RunEclipseSynchronizationTasks.java | 33 +++ 10 files changed, 438 insertions(+), 2 deletions(-) create mode 100644 subprojects/ide/src/main/java/org/gradle/plugins/ide/internal/tooling/RunEclipseSynchronizationTasksBuilder.java create mode 100644 subprojects/tooling-api/src/crossVersionTest/groovy/org/gradle/integtests/tooling/r54/IntermediateResultHandlerCollector.java create mode 100644 subprojects/tooling-api/src/crossVersionTest/groovy/org/gradle/integtests/tooling/r54/LoadEclipseModel.java create mode 100644 subprojects/tooling-api/src/crossVersionTest/groovy/org/gradle/integtests/tooling/r54/RunEclipseSynchronizationTasksCrossVersionSpec.groovy create mode 100644 subprojects/tooling-api/src/crossVersionTest/groovy/org/gradle/integtests/tooling/r54/TellGradleToRunSyncTasks.java create mode 100644 subprojects/tooling-api/src/main/java/org/gradle/tooling/model/eclipse/RunEclipseSynchronizationTasks.java diff --git a/subprojects/ide/src/main/java/org/gradle/plugins/ide/eclipse/EclipsePlugin.java b/subprojects/ide/src/main/java/org/gradle/plugins/ide/eclipse/EclipsePlugin.java index b100560ade406..4ed24b6b650fa 100644 --- a/subprojects/ide/src/main/java/org/gradle/plugins/ide/eclipse/EclipsePlugin.java +++ b/subprojects/ide/src/main/java/org/gradle/plugins/ide/eclipse/EclipsePlugin.java @@ -95,7 +95,7 @@ protected void onApply(Project project) { getLifecycleTask().configure(withDescription("Generates all Eclipse files.")); getCleanTask().configure(withDescription("Cleans all Eclipse files.")); - EclipseModel model = project.getExtensions().create("eclipse", EclipseModel.class); + EclipseModel model = project.getExtensions().create("eclipse", EclipseModel.class, project); configureEclipseProject((ProjectInternal) project, model); configureEclipseJdt(project, model); diff --git a/subprojects/ide/src/main/java/org/gradle/plugins/ide/eclipse/model/EclipseModel.java b/subprojects/ide/src/main/java/org/gradle/plugins/ide/eclipse/model/EclipseModel.java index 50d12f9ec1367..4a1b971ae7b2e 100644 --- a/subprojects/ide/src/main/java/org/gradle/plugins/ide/eclipse/model/EclipseModel.java +++ b/subprojects/ide/src/main/java/org/gradle/plugins/ide/eclipse/model/EclipseModel.java @@ -19,7 +19,12 @@ import com.google.common.base.Preconditions; import groovy.lang.Closure; import org.gradle.api.Action; +import org.gradle.api.Incubating; +import org.gradle.api.Project; +import org.gradle.api.internal.project.ProjectInternal; +import org.gradle.api.internal.tasks.DefaultTaskDependency; import org.gradle.api.model.ObjectFactory; +import org.gradle.api.tasks.TaskDependency; import org.gradle.internal.xml.XmlTransformer; import org.gradle.plugins.ide.api.XmlFileContentMerger; @@ -67,6 +72,12 @@ public class EclipseModel { private EclipseWtp wtp; + private final DefaultTaskDependency synchronizationTasks; + + public EclipseModel(Project project) { + this.synchronizationTasks = new DefaultTaskDependency(((ProjectInternal) project).getTasks()); + } + /** * Injects and returns an instance of {@link ObjectFactory}. * @@ -217,6 +228,32 @@ public void jdt(Action action) { action.execute(getJdt()); } + /** + * The tasks to execute before the Eclipse synchronization starts. + *

    + * This property doesn't have a direct effect to the Gradle Eclipse plugin's behaviour. It is used, however, by + * Buildship to execute the configured tasks each time before the user imports the project or before a project + * synchronization starts. + * + * @return the tasks names + * @since 5.4 + */ + @Incubating + public TaskDependency getSynchronizationTasks() { + return synchronizationTasks; + } + + /** + * Set tasks to be executed before the Eclipse synchronization. + * + * @see #getSynchronizationTasks() + * @since 5.4 + */ + @Incubating + public void synchronizationTasks(Object... synchronizationTasks) { + this.synchronizationTasks.add(synchronizationTasks); + } + /** * Adds path variables to be used for replacing absolute paths in classpath entries. *

    diff --git a/subprojects/ide/src/main/java/org/gradle/plugins/ide/internal/tooling/RunEclipseSynchronizationTasksBuilder.java b/subprojects/ide/src/main/java/org/gradle/plugins/ide/internal/tooling/RunEclipseSynchronizationTasksBuilder.java new file mode 100644 index 0000000000000..f6a5a933e5322 --- /dev/null +++ b/subprojects/ide/src/main/java/org/gradle/plugins/ide/internal/tooling/RunEclipseSynchronizationTasksBuilder.java @@ -0,0 +1,68 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.plugins.ide.internal.tooling; + +import org.gradle.StartParameter; +import org.gradle.api.Project; +import org.gradle.api.Task; +import org.gradle.plugins.ide.eclipse.model.EclipseModel; +import org.gradle.tooling.provider.model.ToolingModelBuilder; + +import java.util.ArrayList; +import java.util.List; + +public class RunEclipseSynchronizationTasksBuilder implements ToolingModelBuilder { + @Override + public boolean canBuild(String modelName) { + return modelName.equals("org.gradle.tooling.model.eclipse.RunEclipseSynchronizationTasks"); + } + + @Override + public Object buildAll(String modelName, Project project) { + StartParameter startParameter = project.getGradle().getStartParameter(); + List taskPaths = new ArrayList(); + taskPaths.addAll(startParameter.getTaskNames()); + + for (Project p : project.getAllprojects()) { + EclipseModel model = p.getExtensions().findByType(EclipseModel.class); + if (model != null) { + for (Task t : model.getSynchronizationTasks().getDependencies(null)) { + taskPaths.add(t.getPath()); + } + } + } + + if (taskPaths.isEmpty()) { + // If no tasks is specified then the default tasks will be executed. + // To work around this, we assign a new empty task for execution. + String placeHolderTaskName = placeHolderTaskName(project, "nothing"); + project.task(placeHolderTaskName); + taskPaths.add(placeHolderTaskName); + } + + project.getGradle().getStartParameter().setTaskNames(taskPaths); + return null; + } + + private String placeHolderTaskName(Project project, String baseName) { + if (project.getTasks().findByName(baseName) == null) { + return baseName; + } else { + return placeHolderTaskName(project, baseName + "_"); + } + } +} diff --git a/subprojects/ide/src/main/java/org/gradle/plugins/ide/internal/tooling/ToolingModelServices.java b/subprojects/ide/src/main/java/org/gradle/plugins/ide/internal/tooling/ToolingModelServices.java index 165704307ea5c..034c774531d26 100644 --- a/subprojects/ide/src/main/java/org/gradle/plugins/ide/internal/tooling/ToolingModelServices.java +++ b/subprojects/ide/src/main/java/org/gradle/plugins/ide/internal/tooling/ToolingModelServices.java @@ -51,6 +51,7 @@ protected BuildScopeToolingModelBuilderRegistryAction createIdeBuildScopeTooling public void execute(ToolingModelBuilderRegistry registry) { GradleProjectBuilder gradleProjectBuilder = new GradleProjectBuilder(); IdeaModelBuilder ideaModelBuilder = new IdeaModelBuilder(gradleProjectBuilder, services); + registry.register(new RunEclipseSynchronizationTasksBuilder()); registry.register(new EclipseModelBuilder(gradleProjectBuilder, services)); registry.register(ideaModelBuilder); registry.register(gradleProjectBuilder); diff --git a/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/eclipse/model/EclipseModelTest.groovy b/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/eclipse/model/EclipseModelTest.groovy index 6b1806cf8508a..d8069cb7fe796 100644 --- a/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/eclipse/model/EclipseModelTest.groovy +++ b/subprojects/ide/src/test/groovy/org/gradle/plugins/ide/eclipse/model/EclipseModelTest.groovy @@ -20,6 +20,7 @@ import org.gradle.api.Action import org.gradle.api.JavaVersion import org.gradle.api.XmlProvider import org.gradle.api.internal.PropertiesTransformer +import org.gradle.api.internal.project.ProjectInternal import org.gradle.internal.xml.XmlTransformer import org.gradle.plugins.ide.api.PropertiesFileContentMerger import org.gradle.plugins.ide.api.XmlFileContentMerger @@ -27,7 +28,7 @@ import spock.lang.Specification class EclipseModelTest extends Specification { - EclipseModel model = new EclipseModel() + EclipseModel model = new EclipseModel(Mock(ProjectInternal)) def setup() { model.classpath = new EclipseClasspath(null) diff --git a/subprojects/tooling-api/src/crossVersionTest/groovy/org/gradle/integtests/tooling/r54/IntermediateResultHandlerCollector.java b/subprojects/tooling-api/src/crossVersionTest/groovy/org/gradle/integtests/tooling/r54/IntermediateResultHandlerCollector.java new file mode 100644 index 0000000000000..caef0103cc24e --- /dev/null +++ b/subprojects/tooling-api/src/crossVersionTest/groovy/org/gradle/integtests/tooling/r54/IntermediateResultHandlerCollector.java @@ -0,0 +1,32 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.integtests.tooling.r54; + +import org.gradle.tooling.IntermediateResultHandler; + +public class IntermediateResultHandlerCollector implements IntermediateResultHandler { + private T result = null; + + @Override + public void onComplete(T result) { + this.result = result; + } + + public T getResult() { + return result; + } +} diff --git a/subprojects/tooling-api/src/crossVersionTest/groovy/org/gradle/integtests/tooling/r54/LoadEclipseModel.java b/subprojects/tooling-api/src/crossVersionTest/groovy/org/gradle/integtests/tooling/r54/LoadEclipseModel.java new file mode 100644 index 0000000000000..2a61f09cef353 --- /dev/null +++ b/subprojects/tooling-api/src/crossVersionTest/groovy/org/gradle/integtests/tooling/r54/LoadEclipseModel.java @@ -0,0 +1,31 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.integtests.tooling.r54; + +import org.gradle.tooling.BuildAction; +import org.gradle.tooling.BuildController; +import org.gradle.tooling.model.eclipse.EclipseProject; + +import java.io.Serializable; + +public class LoadEclipseModel implements BuildAction, Serializable { + + @Override + public EclipseProject execute(BuildController controller) { + return controller.getModel(EclipseProject.class); + } +} diff --git a/subprojects/tooling-api/src/crossVersionTest/groovy/org/gradle/integtests/tooling/r54/RunEclipseSynchronizationTasksCrossVersionSpec.groovy b/subprojects/tooling-api/src/crossVersionTest/groovy/org/gradle/integtests/tooling/r54/RunEclipseSynchronizationTasksCrossVersionSpec.groovy new file mode 100644 index 0000000000000..9d33ba3045fe6 --- /dev/null +++ b/subprojects/tooling-api/src/crossVersionTest/groovy/org/gradle/integtests/tooling/r54/RunEclipseSynchronizationTasksCrossVersionSpec.groovy @@ -0,0 +1,201 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.integtests.tooling.r54 + + +import org.gradle.integtests.tooling.fixture.TargetGradleVersion +import org.gradle.integtests.tooling.fixture.ToolingApiSpecification +import org.gradle.integtests.tooling.fixture.ToolingApiVersion +import org.gradle.plugins.ide.eclipse.model.EclipseModel + +@TargetGradleVersion(">=5.4") +@ToolingApiVersion(">=5.4") +class RunEclipseSynchronizationTasksCrossVersionSpec extends ToolingApiSpecification { + def setup() { + file("sub1").mkdirs() + + buildFile << """ + apply plugin: 'eclipse' + + task foo { + } + + task bar { + } + + project(":sub") { + apply plugin: 'eclipse' + + task bar { + } + } + """ + settingsFile << "include 'sub'" + } + + def "can run tasks upon Eclipse synchronization"() { + setup: + buildFile << "eclipse { synchronizationTasks 'foo' }" + + def projectsLoadedHandler = new IntermediateResultHandlerCollector() + def buildFinishedHandler = new IntermediateResultHandlerCollector() + def out = new ByteArrayOutputStream() + + when: + withConnection { connection -> + connection.action().projectsLoaded(new TellGradleToRunSyncTasks(), projectsLoadedHandler) + .buildFinished(new LoadEclipseModel(), buildFinishedHandler) + .build() + .setStandardOutput(out) + .forTasks() + .run() + } + + then: + taskExecuted(out, ":foo") + } + + def "can use task reference in sync task list"() { + setup: + buildFile << "eclipse { synchronizationTasks foo }" + + def projectsLoadedHandler = new IntermediateResultHandlerCollector() + def buildFinishedHandler = new IntermediateResultHandlerCollector() + def out = new ByteArrayOutputStream() + + when: + withConnection { connection -> + connection.action().projectsLoaded(new TellGradleToRunSyncTasks(), projectsLoadedHandler) + .buildFinished(new LoadEclipseModel(), buildFinishedHandler) + .build() + .setStandardOutput(out) + .forTasks() + .run() + } + + then: + taskExecuted(out, ":foo") + } + + def "task paths are resolved correctly"() { + setup: + buildFile << """ + project(':sub') { + eclipse { + synchronizationTasks 'bar' + } + } + """ + + def projectsLoadedHandler = new IntermediateResultHandlerCollector() + def buildFinishedHandler = new IntermediateResultHandlerCollector() + def out = new ByteArrayOutputStream() + + when: + withConnection { connection -> + connection.action().projectsLoaded(new TellGradleToRunSyncTasks(), projectsLoadedHandler) + .buildFinished(new LoadEclipseModel(), buildFinishedHandler) + .build() + .setStandardOutput(out) + .forTasks() + .run() + } + + then: + taskExecuted(out, ":sub:bar") + } + + + def "execute placeholder task when no task is configured for synchronization"() { + setup: + def projectsLoadedHandler = new IntermediateResultHandlerCollector() + def buildFinishedHandler = new IntermediateResultHandlerCollector() + def out = new ByteArrayOutputStream() + + when: + withConnection { connection -> + connection.action().projectsLoaded(new TellGradleToRunSyncTasks(), projectsLoadedHandler) + .buildFinished(new LoadEclipseModel(), buildFinishedHandler) + .build() + .setStandardOutput(out) + .forTasks() + .run() + } + + then: + taskExecuted(out, ":nothing") + } + + def "does not override client-specified tasks"() { + setup: + buildFile << "eclipse { synchronizationTasks bar }" + + def projectsLoadedHandler = new IntermediateResultHandlerCollector() + def buildFinishedHandler = new IntermediateResultHandlerCollector() + def out = new ByteArrayOutputStream() + + when: + withConnection { connection -> + connection.action().projectsLoaded(new TellGradleToRunSyncTasks(), projectsLoadedHandler) + .buildFinished(new LoadEclipseModel(), buildFinishedHandler) + .build() + .setStandardOutput(out) + .forTasks("foo") + .run() + } + + then: + taskExecuted(out, ":foo") + taskExecuted(out, ":bar") + } + + + def "placeholder task never overlaps with project task"() { + setup: + buildFile << """ + task nothing { + } + + task nothing_ { + } + """ + + def projectsLoadedHandler = new IntermediateResultHandlerCollector() + def buildFinishedHandler = new IntermediateResultHandlerCollector() + def out = new ByteArrayOutputStream() + + when: + withConnection { connection -> + connection.action().projectsLoaded(new TellGradleToRunSyncTasks(), projectsLoadedHandler) + .buildFinished(new LoadEclipseModel(), buildFinishedHandler) + .build() + .setStandardOutput(out) + .forTasks() + .run() + } + + then: + !taskExecuted(out, ":nothing") + !taskExecuted(out, ":nothing_") + taskExecuted(out, ":nothing__") + } + + private def taskExecuted(ByteArrayOutputStream out, String taskPath) { + out.toString().contains("> Task $taskPath ") + } + +} diff --git a/subprojects/tooling-api/src/crossVersionTest/groovy/org/gradle/integtests/tooling/r54/TellGradleToRunSyncTasks.java b/subprojects/tooling-api/src/crossVersionTest/groovy/org/gradle/integtests/tooling/r54/TellGradleToRunSyncTasks.java new file mode 100644 index 0000000000000..a79894ce3becf --- /dev/null +++ b/subprojects/tooling-api/src/crossVersionTest/groovy/org/gradle/integtests/tooling/r54/TellGradleToRunSyncTasks.java @@ -0,0 +1,32 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.integtests.tooling.r54; + +import org.gradle.tooling.BuildAction; +import org.gradle.tooling.BuildController; +import org.gradle.tooling.model.eclipse.RunEclipseSynchronizationTasks; + +import java.io.Serializable; + +public class TellGradleToRunSyncTasks implements BuildAction, Serializable { + + @Override + public Void execute(BuildController controller) { + controller.getModel(RunEclipseSynchronizationTasks.class); + return null; + } +} diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/model/eclipse/RunEclipseSynchronizationTasks.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/model/eclipse/RunEclipseSynchronizationTasks.java new file mode 100644 index 0000000000000..20f57bae8ed94 --- /dev/null +++ b/subprojects/tooling-api/src/main/java/org/gradle/tooling/model/eclipse/RunEclipseSynchronizationTasks.java @@ -0,0 +1,33 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.tooling.model.eclipse; + +import org.gradle.api.Incubating; + +/** + * A tooling model that instructs Gradle to run tasks from the Eclipse plugin configuration. + * + * This is a special tooling model as it does not provide any information. However, when requested, Gradle will + * override the client-provided tasks with the ones stored in the {@code eclipse.synchronizationTasks} property. + * + * This allows Buildship to run tasks before the model loading and load the models in a single step. + * + * @since 5.4 + */ +@Incubating +public interface RunEclipseSynchronizationTasks { +} From d53427b9474c5a950a7a010b2c874e4871ce335f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=B3r=C3=A1nt=20Pint=C3=A9r?= Date: Mon, 25 Mar 2019 10:05:17 +0100 Subject: [PATCH 703/853] Use an internal exception for artifact transform failures --- .../transform/ArtifactTransformException.java | 1 + .../transform/DefaultTransformerInvoker.java | 3 +- .../transform/TransformException.java | 28 +++++++++++++++++++ .../TransformingArtifactVisitor.java | 8 ++++-- 4 files changed, 36 insertions(+), 4 deletions(-) create mode 100644 subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/TransformException.java diff --git a/subprojects/core-api/src/main/java/org/gradle/api/artifacts/transform/ArtifactTransformException.java b/subprojects/core-api/src/main/java/org/gradle/api/artifacts/transform/ArtifactTransformException.java index 5f3bbd34fd767..8e852dfed6c2b 100644 --- a/subprojects/core-api/src/main/java/org/gradle/api/artifacts/transform/ArtifactTransformException.java +++ b/subprojects/core-api/src/main/java/org/gradle/api/artifacts/transform/ArtifactTransformException.java @@ -29,6 +29,7 @@ * * @since 3.4 */ +@Deprecated @Contextual public class ArtifactTransformException extends GradleException { diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvoker.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvoker.java index 08d90ed4f097b..6f5c9ffdf2ea6 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvoker.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultTransformerInvoker.java @@ -169,7 +169,8 @@ public Optional getBeforeExecutionState() { }); return outcome.getOutcome() - .map(outcome1 -> execution.loadResultsFile()); + .map(outcome1 -> execution.loadResultsFile()) + .mapFailure(failure -> new TransformException(String.format("Execution failed for %s.", execution.getDisplayName()), failure)); }); }); } diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/TransformException.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/TransformException.java new file mode 100644 index 0000000000000..2c9a674ed6cf9 --- /dev/null +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/TransformException.java @@ -0,0 +1,28 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.api.internal.artifacts.transform; + +import org.gradle.api.GradleException; +import org.gradle.internal.exceptions.Contextual; + +@Contextual +public class TransformException extends GradleException { + + public TransformException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/TransformingArtifactVisitor.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/TransformingArtifactVisitor.java index 540de65df2cdf..b5d1b38432a3b 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/TransformingArtifactVisitor.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/TransformingArtifactVisitor.java @@ -18,7 +18,6 @@ import org.gradle.api.artifacts.ResolvedArtifact; import org.gradle.api.artifacts.component.ComponentArtifactIdentifier; -import org.gradle.api.artifacts.transform.ArtifactTransformException; import org.gradle.api.attributes.AttributeContainer; import org.gradle.api.internal.artifacts.DefaultResolvedArtifact; import org.gradle.api.internal.artifacts.ivyservice.resolveengine.artifact.ArtifactVisitor; @@ -58,7 +57,9 @@ public void visitArtifact(DisplayName variantName, AttributeContainer variantAtt visitor.visitArtifact(variantName, target, resolvedArtifact); } }, - failure -> visitor.visitFailure(new ArtifactTransformException(artifact.getId(), target, failure)) + failure -> visitor.visitFailure( + new TransformException(String.format("Failed to transform artifact '%s' to match attributes %s.", + artifact.getId(), target), failure)) ); } @@ -86,7 +87,8 @@ public void visitFile(ComponentArtifactIdentifier artifactIdentifier, DisplayNam visitor.visitFile(new ComponentFileArtifactIdentifier(artifactIdentifier.getComponentIdentifier(), outputFile.getName()), variantName, target, outputFile); } }, - failure -> visitor.visitFailure(new ArtifactTransformException(file, target, failure)) + failure -> visitor.visitFailure(new TransformException(String.format("Failed to transform file '%s' to match attributes %s", + file.getName(), target), failure)) ); } } From ff6cf1b83c95f3a0eb2199361817ce9e3c568fee Mon Sep 17 00:00:00 2001 From: Donat Csikos Date: Mon, 25 Mar 2019 10:30:06 +0100 Subject: [PATCH 704/853] Fix binary compatibility --- .../gradle/plugins/ide/eclipse/model/EclipseModel.java | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/subprojects/ide/src/main/java/org/gradle/plugins/ide/eclipse/model/EclipseModel.java b/subprojects/ide/src/main/java/org/gradle/plugins/ide/eclipse/model/EclipseModel.java index 4a1b971ae7b2e..f2136f0cb6084 100644 --- a/subprojects/ide/src/main/java/org/gradle/plugins/ide/eclipse/model/EclipseModel.java +++ b/subprojects/ide/src/main/java/org/gradle/plugins/ide/eclipse/model/EclipseModel.java @@ -74,6 +74,16 @@ public class EclipseModel { private final DefaultTaskDependency synchronizationTasks; + public EclipseModel() { + synchronizationTasks = new DefaultTaskDependency(); + } + + /** + * Constructor. + * + * @since 5.4 + */ + @Incubating public EclipseModel(Project project) { this.synchronizationTasks = new DefaultTaskDependency(((ProjectInternal) project).getTasks()); } From 0a20449d4e5ae484d31221a65987175f5d316b03 Mon Sep 17 00:00:00 2001 From: Donat Csikos Date: Mon, 25 Mar 2019 11:43:56 +0100 Subject: [PATCH 705/853] Run tasks upon Eclipse auto-build --- .../ide/eclipse/model/EclipseModel.java | 31 ++- ...ilder.java => RunEclipseTasksBuilder.java} | 30 ++- .../tooling/ToolingModelServices.java | 2 +- ...lipseAutoBuildTasksCrossVersionSpec.groovy | 188 ++++++++++++++++++ .../r54/TellGradleToRunAutoBuildTasks.java | 32 +++ .../eclipse/RunEclipseAutoBuildTasks.java | 32 +++ 6 files changed, 308 insertions(+), 7 deletions(-) rename subprojects/ide/src/main/java/org/gradle/plugins/ide/internal/tooling/{RunEclipseSynchronizationTasksBuilder.java => RunEclipseTasksBuilder.java} (69%) create mode 100644 subprojects/tooling-api/src/crossVersionTest/groovy/org/gradle/integtests/tooling/r54/RunEclipseAutoBuildTasksCrossVersionSpec.groovy create mode 100644 subprojects/tooling-api/src/crossVersionTest/groovy/org/gradle/integtests/tooling/r54/TellGradleToRunAutoBuildTasks.java create mode 100644 subprojects/tooling-api/src/main/java/org/gradle/tooling/model/eclipse/RunEclipseAutoBuildTasks.java diff --git a/subprojects/ide/src/main/java/org/gradle/plugins/ide/eclipse/model/EclipseModel.java b/subprojects/ide/src/main/java/org/gradle/plugins/ide/eclipse/model/EclipseModel.java index f2136f0cb6084..1d4acff08a33a 100644 --- a/subprojects/ide/src/main/java/org/gradle/plugins/ide/eclipse/model/EclipseModel.java +++ b/subprojects/ide/src/main/java/org/gradle/plugins/ide/eclipse/model/EclipseModel.java @@ -74,8 +74,11 @@ public class EclipseModel { private final DefaultTaskDependency synchronizationTasks; + private final DefaultTaskDependency autoBuildTasks; + public EclipseModel() { synchronizationTasks = new DefaultTaskDependency(); + autoBuildTasks = new DefaultTaskDependency(); } /** @@ -86,6 +89,7 @@ public EclipseModel() { @Incubating public EclipseModel(Project project) { this.synchronizationTasks = new DefaultTaskDependency(((ProjectInternal) project).getTasks()); + this.autoBuildTasks = new DefaultTaskDependency(((ProjectInternal) project).getTasks()); } /** @@ -239,7 +243,7 @@ public void jdt(Action action) { } /** - * The tasks to execute before the Eclipse synchronization starts. + * Returns the tasks to be executed before the Eclipse synchronization starts. *

    * This property doesn't have a direct effect to the Gradle Eclipse plugin's behaviour. It is used, however, by * Buildship to execute the configured tasks each time before the user imports the project or before a project @@ -264,6 +268,31 @@ public void synchronizationTasks(Object... synchronizationTasks) { this.synchronizationTasks.add(synchronizationTasks); } + /** + * Returns the tasks to be executed during the Eclipse auto-build. + *

    + * This property doesn't have a direct effect to the Gradle Eclipse plugin's behaviour. It is used, however, by + * Buildship to execute the configured tasks each time when the Eclipse automatic build is triggered for the project. + * + * @return the tasks names + * @since 5.4 + */ + @Incubating + public TaskDependency getAutoBuildTasks() { + return autoBuildTasks; + } + + /** + * Set tasks to be executed during the Eclipse auto-build. + * + * @see #getAutoBuildTasks() + * @since 5.4 + */ + @Incubating + public void autoBuildTasks(Object... autoBuildTasks) { + this.autoBuildTasks.add(autoBuildTasks); + } + /** * Adds path variables to be used for replacing absolute paths in classpath entries. *

    diff --git a/subprojects/ide/src/main/java/org/gradle/plugins/ide/internal/tooling/RunEclipseSynchronizationTasksBuilder.java b/subprojects/ide/src/main/java/org/gradle/plugins/ide/internal/tooling/RunEclipseTasksBuilder.java similarity index 69% rename from subprojects/ide/src/main/java/org/gradle/plugins/ide/internal/tooling/RunEclipseSynchronizationTasksBuilder.java rename to subprojects/ide/src/main/java/org/gradle/plugins/ide/internal/tooling/RunEclipseTasksBuilder.java index f6a5a933e5322..c0678b1de1136 100644 --- a/subprojects/ide/src/main/java/org/gradle/plugins/ide/internal/tooling/RunEclipseSynchronizationTasksBuilder.java +++ b/subprojects/ide/src/main/java/org/gradle/plugins/ide/internal/tooling/RunEclipseTasksBuilder.java @@ -25,10 +25,11 @@ import java.util.ArrayList; import java.util.List; -public class RunEclipseSynchronizationTasksBuilder implements ToolingModelBuilder { +public class RunEclipseTasksBuilder implements ToolingModelBuilder { + @Override public boolean canBuild(String modelName) { - return modelName.equals("org.gradle.tooling.model.eclipse.RunEclipseSynchronizationTasks"); + return isSyncModel(modelName) || isAutoBuildModel(modelName); } @Override @@ -37,11 +38,21 @@ public Object buildAll(String modelName, Project project) { List taskPaths = new ArrayList(); taskPaths.addAll(startParameter.getTaskNames()); + boolean isSyncModel = isSyncModel(modelName); + boolean isAutoBuildModel = isAutoBuildModel(modelName); + for (Project p : project.getAllprojects()) { EclipseModel model = p.getExtensions().findByType(EclipseModel.class); if (model != null) { - for (Task t : model.getSynchronizationTasks().getDependencies(null)) { - taskPaths.add(t.getPath()); + if (isSyncModel) { + for (Task t : model.getSynchronizationTasks().getDependencies(null)) { + taskPaths.add(t.getPath()); + } + } + if (isAutoBuildModel) { + for (Task t : model.getAutoBuildTasks().getDependencies(null)) { + taskPaths.add(t.getPath()); + } } } } @@ -58,7 +69,16 @@ public Object buildAll(String modelName, Project project) { return null; } - private String placeHolderTaskName(Project project, String baseName) { + private static boolean isSyncModel(String modelName) { + return modelName.equals("org.gradle.tooling.model.eclipse.RunEclipseSynchronizationTasks"); + } + + + private static boolean isAutoBuildModel(String modelName) { + return modelName.equals("org.gradle.tooling.model.eclipse.RunEclipseAutoBuildTasks"); + } + + private static String placeHolderTaskName(Project project, String baseName) { if (project.getTasks().findByName(baseName) == null) { return baseName; } else { diff --git a/subprojects/ide/src/main/java/org/gradle/plugins/ide/internal/tooling/ToolingModelServices.java b/subprojects/ide/src/main/java/org/gradle/plugins/ide/internal/tooling/ToolingModelServices.java index 034c774531d26..aa2754484a0f5 100644 --- a/subprojects/ide/src/main/java/org/gradle/plugins/ide/internal/tooling/ToolingModelServices.java +++ b/subprojects/ide/src/main/java/org/gradle/plugins/ide/internal/tooling/ToolingModelServices.java @@ -51,7 +51,7 @@ protected BuildScopeToolingModelBuilderRegistryAction createIdeBuildScopeTooling public void execute(ToolingModelBuilderRegistry registry) { GradleProjectBuilder gradleProjectBuilder = new GradleProjectBuilder(); IdeaModelBuilder ideaModelBuilder = new IdeaModelBuilder(gradleProjectBuilder, services); - registry.register(new RunEclipseSynchronizationTasksBuilder()); + registry.register(new RunEclipseTasksBuilder()); registry.register(new EclipseModelBuilder(gradleProjectBuilder, services)); registry.register(ideaModelBuilder); registry.register(gradleProjectBuilder); diff --git a/subprojects/tooling-api/src/crossVersionTest/groovy/org/gradle/integtests/tooling/r54/RunEclipseAutoBuildTasksCrossVersionSpec.groovy b/subprojects/tooling-api/src/crossVersionTest/groovy/org/gradle/integtests/tooling/r54/RunEclipseAutoBuildTasksCrossVersionSpec.groovy new file mode 100644 index 0000000000000..5f5219f5a7262 --- /dev/null +++ b/subprojects/tooling-api/src/crossVersionTest/groovy/org/gradle/integtests/tooling/r54/RunEclipseAutoBuildTasksCrossVersionSpec.groovy @@ -0,0 +1,188 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.integtests.tooling.r54 + + +import org.gradle.integtests.tooling.fixture.TargetGradleVersion +import org.gradle.integtests.tooling.fixture.ToolingApiSpecification +import org.gradle.integtests.tooling.fixture.ToolingApiVersion + +@TargetGradleVersion(">=5.4") +@ToolingApiVersion(">=5.4") +class RunEclipseAutoBuildTasksCrossVersionSpec extends ToolingApiSpecification { + def setup() { + file("sub1").mkdirs() + + buildFile << """ + apply plugin: 'eclipse' + + task foo { + } + + task bar { + } + + project(":sub") { + apply plugin: 'eclipse' + + task bar { + } + } + """ + settingsFile << "include 'sub'" + } + + def "can run tasks upon Eclipse auto-build"() { + setup: + buildFile << "eclipse { autoBuildTasks 'foo' }" + + def projectsLoadedHandler = new IntermediateResultHandlerCollector() + def out = new ByteArrayOutputStream() + + when: + withConnection { connection -> + connection.action().projectsLoaded(new TellGradleToRunAutoBuildTasks(), projectsLoadedHandler) + .build() + .setStandardOutput(out) + .forTasks() + .run() + } + + then: + taskExecuted(out, ":foo") + } + + def "can use task reference in sync task list"() { + setup: + buildFile << "eclipse { autoBuildTasks foo }" + + def projectsLoadedHandler = new IntermediateResultHandlerCollector() + def out = new ByteArrayOutputStream() + + when: + withConnection { connection -> + connection.action().projectsLoaded(new TellGradleToRunAutoBuildTasks(), projectsLoadedHandler) + .build() + .setStandardOutput(out) + .forTasks() + .run() + } + + then: + taskExecuted(out, ":foo") + } + + def "task paths are resolved correctly"() { + setup: + buildFile << """ + project(':sub') { + eclipse { + autoBuildTasks 'bar' + } + } + """ + + def projectsLoadedHandler = new IntermediateResultHandlerCollector() + def out = new ByteArrayOutputStream() + + when: + withConnection { connection -> + connection.action().projectsLoaded(new TellGradleToRunAutoBuildTasks(), projectsLoadedHandler) + .build() + .setStandardOutput(out) + .forTasks() + .run() + } + + then: + taskExecuted(out, ":sub:bar") + } + + + def "execute placeholder task when no task is configured for auto-build"() { + setup: + def projectsLoadedHandler = new IntermediateResultHandlerCollector() + def out = new ByteArrayOutputStream() + + when: + withConnection { connection -> + connection.action().projectsLoaded(new TellGradleToRunAutoBuildTasks(), projectsLoadedHandler) + .build() + .setStandardOutput(out) + .forTasks() + .run() + } + + then: + taskExecuted(out, ":nothing") + } + + def "does not override client-specified tasks"() { + setup: + buildFile << "eclipse { autoBuildTasks bar }" + + def projectsLoadedHandler = new IntermediateResultHandlerCollector() + def out = new ByteArrayOutputStream() + + when: + withConnection { connection -> + connection.action().projectsLoaded(new TellGradleToRunAutoBuildTasks(), projectsLoadedHandler) + .build() + .setStandardOutput(out) + .forTasks("foo") + .run() + } + + then: + taskExecuted(out, ":foo") + taskExecuted(out, ":bar") + } + + + def "placeholder task never overlaps with project task"() { + setup: + buildFile << """ + task nothing { + } + + task nothing_ { + } + """ + + def projectsLoadedHandler = new IntermediateResultHandlerCollector() + def out = new ByteArrayOutputStream() + + when: + withConnection { connection -> + connection.action().projectsLoaded(new TellGradleToRunAutoBuildTasks(), projectsLoadedHandler) + .build() + .setStandardOutput(out) + .forTasks() + .run() + } + + then: + !taskExecuted(out, ":nothing") + !taskExecuted(out, ":nothing_") + taskExecuted(out, ":nothing__") + } + + private def taskExecuted(ByteArrayOutputStream out, String taskPath) { + out.toString().contains("> Task $taskPath ") + } + +} diff --git a/subprojects/tooling-api/src/crossVersionTest/groovy/org/gradle/integtests/tooling/r54/TellGradleToRunAutoBuildTasks.java b/subprojects/tooling-api/src/crossVersionTest/groovy/org/gradle/integtests/tooling/r54/TellGradleToRunAutoBuildTasks.java new file mode 100644 index 0000000000000..9d1ac85b2d4eb --- /dev/null +++ b/subprojects/tooling-api/src/crossVersionTest/groovy/org/gradle/integtests/tooling/r54/TellGradleToRunAutoBuildTasks.java @@ -0,0 +1,32 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.integtests.tooling.r54; + +import org.gradle.tooling.BuildAction; +import org.gradle.tooling.BuildController; +import org.gradle.tooling.model.eclipse.RunEclipseAutoBuildTasks; + +import java.io.Serializable; + +public class TellGradleToRunAutoBuildTasks implements BuildAction, Serializable { + + @Override + public Void execute(BuildController controller) { + controller.getModel(RunEclipseAutoBuildTasks.class); + return null; + } +} diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/model/eclipse/RunEclipseAutoBuildTasks.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/model/eclipse/RunEclipseAutoBuildTasks.java new file mode 100644 index 0000000000000..3dd28ee18d1e9 --- /dev/null +++ b/subprojects/tooling-api/src/main/java/org/gradle/tooling/model/eclipse/RunEclipseAutoBuildTasks.java @@ -0,0 +1,32 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.tooling.model.eclipse; + +import org.gradle.api.Incubating; + +/** + * A tooling model that instructs Gradle to run tasks from the Eclipse plugin configuration. + * + * Similarly to {@link RunEclipseSynchronizationTasks}, this is a special tooling model as it does + * not provide any information. However, when requested, Gradle will override the client-provided + * tasks with the ones stored in the {@code eclipse.autoBuildTasks} property. + * + * @since 5.4 + */ +@Incubating +public interface RunEclipseAutoBuildTasks { +} From e7dd3baaa593ddc164de05e56134344c69a0568d Mon Sep 17 00:00:00 2001 From: Ian Kerins Date: Sun, 3 Mar 2019 22:34:02 -0500 Subject: [PATCH 706/853] Support resource creation in incremental annotation processors Allow resources to be created by incremental annotation processors using `Filer#createResource`. Allow resources to be created in the three currently existing output locations on `StandardLocation`: `SOURCE_OUTPUT`, `CLASS_OUTPUT`, and `NATIVE_HEADER_OUTPUT`. A generated resource is uniquely identified by its `Location` and its path relative to that `Location`. A new type `GeneratedResource` is created to that effect. Data of that type is then plumbed through the existing annotation processing infrastructure, ultimately reaching `IncrementalCompilationInitializer` so that cleaning may be done. Resolves #4702. Signed-off-by: Ian Kerins --- .../docs/src/docs/userguide/java_plugin.adoc | 5 +- .../fixtures/CompilationOutputsFixture.groovy | 7 ++ ...AnnotationProcessingIntegrationTest.groovy | 1 - ...AnnotationProcessingIntegrationTest.groovy | 62 +++++++--- ...AnnotationProcessingIntegrationTest.groovy | 111 +++++++++++++++--- .../IncrementalCompilationInitializer.java | 28 ++++- .../IncrementalResultStoringCompiler.java | 7 +- .../classpath/ClasspathEntrySnapshot.java | 2 +- .../deps/ClassDependentsAccumulator.java | 2 +- .../incremental/deps/ClassSetAnalysis.java | 77 ++++++++---- .../deps/ClassSetAnalysisData.java | 4 +- .../incremental/deps/DependentsSet.java | 36 +++++- .../processing/AnnotationProcessingData.java | 31 ++++- .../AnnotationProcessingResult.java | 28 +++++ .../processing/AnnotationProcessorResult.java | 8 ++ .../processing/GeneratedResource.java | 99 ++++++++++++++++ .../GeneratedResourceSerializer.java | 45 +++++++ .../ClasspathChangeDependentsFinder.java | 2 +- .../recomp/ClasspathEntryChangeProcessor.java | 1 + .../recomp/JavaChangeProcessor.java | 1 + .../incremental/recomp/RecompilationSpec.java | 7 ++ .../AggregatingProcessingStrategy.java | 12 ++ .../processing/DynamicProcessingStrategy.java | 6 + .../compile/processing/IncrementalFiler.java | 10 +- .../IncrementalProcessingStrategy.java | 4 +- .../IsolatingProcessingStrategy.java | 19 +++ .../NonIncrementalProcessingStrategy.java | 6 + .../ClassSetAnalysisDataSerializerTest.groovy | 4 +- .../deps/ClassSetAnalysisTest.groovy | 66 +++++------ .../processing/AggregatingFilerTest.groovy | 36 ++++++ .../processing/IncrementalFilerTest.groovy | 14 +-- .../processing/IsolatingFilerTest.groovy | 53 ++++++++- .../AnnotationProcessorFixture.groovy | 4 +- .../fixtures/HelperProcessorFixture.groovy | 28 ++++- .../NonIncrementalProcessorFixture.groovy | 20 ---- .../ResourceGeneratingProcessorFixture.groovy | 75 ++++++++++++ .../ServiceRegistryProcessorFixture.groovy | 26 +++- 37 files changed, 788 insertions(+), 159 deletions(-) create mode 100644 subprojects/language-java/src/main/java/org/gradle/api/internal/tasks/compile/incremental/processing/GeneratedResource.java create mode 100644 subprojects/language-java/src/main/java/org/gradle/api/internal/tasks/compile/incremental/processing/GeneratedResourceSerializer.java create mode 100644 subprojects/language-java/src/testFixtures/groovy/org/gradle/language/fixtures/ResourceGeneratingProcessorFixture.groovy diff --git a/subprojects/docs/src/docs/userguide/java_plugin.adoc b/subprojects/docs/src/docs/userguide/java_plugin.adoc index ff089e8cc7351..c6104cd891a8b 100644 --- a/subprojects/docs/src/docs/userguide/java_plugin.adoc +++ b/subprojects/docs/src/docs/userguide/java_plugin.adoc @@ -601,8 +601,9 @@ Both categories have the following limitations: * They must not depend on compiler-specific APIs like `com.sun.source.util.Trees`. Gradle wraps the processing APIs, so attempts to cast to compiler-specific types will fail. If your processor does this, it cannot be incremental, unless you have some fallback mechanism. -* If they use link:{javaApi}/javax/annotation/processing/Filer.html#createResource(javax.tools.JavaFileManager.Location,java.lang.CharSequence,java.lang.CharSequence,javax.lang.model.element.Element++...++)[Filer#createResource], Gradle will recompile all source files. - See https://github.com/gradle/gradle/issues/4702[gradle/issues/4702] +* If they use link:{javaApi}/javax/annotation/processing/Filer.html#createResource(javax.tools.JavaFileManager.Location,java.lang.CharSequence,java.lang.CharSequence,javax.lang.model.element.Element++...++)[Filer#createResource], + the `location` argument must be one of these values from link:{javaApi}/javax/tools/StandardLocation.html[StandardLocation]: `CLASS_OUTPUT`, `SOURCE_OUTPUT`, or `NATIVE_HEADER_OUTPUT`. + Any other argument will disable incremental processing. ==== "Isolating" annotation processors diff --git a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/CompilationOutputsFixture.groovy b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/CompilationOutputsFixture.groovy index 3e5c7101bf0fc..5e3759c935218 100644 --- a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/CompilationOutputsFixture.groovy +++ b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/CompilationOutputsFixture.groovy @@ -105,6 +105,13 @@ class CompilationOutputsFixture { assert changedFileNames == asSet(classNames) } + //asserts files deleted since last snapshot. + void deletedFiles(String... fileNames) { + def expectedNames = fileNames.collect({ removeExtension(it) }) as Set + def deleted = snapshot.findAll { !it.exists() }.collect { removeExtension(it.name) } as Set + assert deleted == expectedNames + } + //asserts classes deleted since last snapshot. Class means file name without extension. void deletedClasses(String... classNames) { def deleted = snapshot.findAll { !it.exists() }.collect { removeExtension(it.name) } as Set diff --git a/subprojects/language-java/src/integTest/groovy/org/gradle/api/tasks/compile/AbstractIncrementalAnnotationProcessingIntegrationTest.groovy b/subprojects/language-java/src/integTest/groovy/org/gradle/api/tasks/compile/AbstractIncrementalAnnotationProcessingIntegrationTest.groovy index edf80fb1db295..840868e52644f 100644 --- a/subprojects/language-java/src/integTest/groovy/org/gradle/api/tasks/compile/AbstractIncrementalAnnotationProcessingIntegrationTest.groovy +++ b/subprojects/language-java/src/integTest/groovy/org/gradle/api/tasks/compile/AbstractIncrementalAnnotationProcessingIntegrationTest.groovy @@ -149,5 +149,4 @@ abstract class AbstractIncrementalAnnotationProcessingIntegrationTest extends Ab succeeds 'compileJava' outputs.recompiledClasses("A") } - } diff --git a/subprojects/language-java/src/integTest/groovy/org/gradle/api/tasks/compile/AggregatingIncrementalAnnotationProcessingIntegrationTest.groovy b/subprojects/language-java/src/integTest/groovy/org/gradle/api/tasks/compile/AggregatingIncrementalAnnotationProcessingIntegrationTest.groovy index b2bfa6f6cdcb1..c849215f0492b 100644 --- a/subprojects/language-java/src/integTest/groovy/org/gradle/api/tasks/compile/AggregatingIncrementalAnnotationProcessingIntegrationTest.groovy +++ b/subprojects/language-java/src/integTest/groovy/org/gradle/api/tasks/compile/AggregatingIncrementalAnnotationProcessingIntegrationTest.groovy @@ -19,16 +19,24 @@ package org.gradle.api.tasks.compile import org.gradle.api.internal.tasks.compile.CompileJavaBuildOperationType import org.gradle.api.internal.tasks.compile.incremental.processing.IncrementalAnnotationProcessorType import org.gradle.language.fixtures.HelperProcessorFixture -import org.gradle.language.fixtures.NonIncrementalProcessorFixture +import org.gradle.language.fixtures.ResourceGeneratingProcessorFixture import org.gradle.language.fixtures.ServiceRegistryProcessorFixture +import javax.tools.StandardLocation + import static org.gradle.api.internal.tasks.compile.CompileJavaBuildOperationType.Result.AnnotationProcessorDetails.Type.AGGREGATING class AggregatingIncrementalAnnotationProcessingIntegrationTest extends AbstractIncrementalAnnotationProcessingIntegrationTest { + private static ServiceRegistryProcessorFixture writingResourcesTo(String location) { + def serviceRegistryProcessor = new ServiceRegistryProcessorFixture() + serviceRegistryProcessor.writeResources = true + serviceRegistryProcessor.resourceLocation = location + return serviceRegistryProcessor + } @Override def setup() { - withProcessor(new ServiceRegistryProcessorFixture()) + withProcessor(writingResourcesTo(StandardLocation.CLASS_OUTPUT.toString())) } def "generated files are recompiled when any annotated file changes"() { @@ -43,7 +51,7 @@ class AggregatingIncrementalAnnotationProcessingIntegrationTest extends Abstract run "compileJava" then: - outputs.recompiledClasses("A", "ServiceRegistry") + outputs.recompiledFiles("A", "ServiceRegistry", "ServiceRegistryResource.txt") serviceRegistryReferences("A", "B") } @@ -58,7 +66,7 @@ class AggregatingIncrementalAnnotationProcessingIntegrationTest extends Abstract run "compileJava" then: - outputs.recompiledClasses("A", "ServiceRegistry") + outputs.recompiledFiles("A", "ServiceRegistry", "ServiceRegistryResource.txt") } def "annotated files are reprocessed when an unrelated file changes"() { @@ -72,7 +80,7 @@ class AggregatingIncrementalAnnotationProcessingIntegrationTest extends Abstract run "compileJava" then: - outputs.recompiledClasses("Unrelated", "ServiceRegistry") + outputs.recompiledFiles("Unrelated", "ServiceRegistry", "ServiceRegistryResource.txt") } def "annotated files are reprocessed when a new file is added"() { @@ -86,7 +94,7 @@ class AggregatingIncrementalAnnotationProcessingIntegrationTest extends Abstract run "compileJava" then: - outputs.recompiledClasses("ServiceRegistry", "B") + outputs.recompiledFiles("ServiceRegistry", "ServiceRegistryResource.txt", "B") serviceRegistryReferences("A", "B") } @@ -103,7 +111,7 @@ class AggregatingIncrementalAnnotationProcessingIntegrationTest extends Abstract then: outputs.deletedClasses("A") - outputs.recompiledClasses("ServiceRegistry") + outputs.recompiledFiles("ServiceRegistry", "ServiceRegistryResource.txt") serviceRegistryReferences("B") !serviceRegistryReferences("A") } @@ -123,7 +131,7 @@ class AggregatingIncrementalAnnotationProcessingIntegrationTest extends Abstract run "compileJava" then: - outputs.recompiledClasses("A", "ServiceRegistry", "Dependent") + outputs.recompiledFiles("A", "ServiceRegistry", "ServiceRegistryResource.txt", "Dependent") } def "classes files of generated sources are deleted when annotated file is deleted"() { @@ -138,11 +146,12 @@ class AggregatingIncrementalAnnotationProcessingIntegrationTest extends Abstract run "compileJava" then: - outputs.deletedClasses("A", "ServiceRegistry") + outputs.deletedFiles("A", "ServiceRegistry", "ServiceRegistryResource.txt") } def "generated files are deleted when annotated file is deleted"() { given: + withProcessor(writingResourcesTo(StandardLocation.SOURCE_OUTPUT.toString())) def a = java "@Service class A {}" java "class Unrelated {}" @@ -151,6 +160,7 @@ class AggregatingIncrementalAnnotationProcessingIntegrationTest extends Abstract then: file("build/generated/sources/annotationProcessor/java/main/ServiceRegistry.java").exists() + file("build/generated/sources/annotationProcessor/java/main/ServiceRegistryResource.txt").exists() when: a.delete() @@ -158,17 +168,20 @@ class AggregatingIncrementalAnnotationProcessingIntegrationTest extends Abstract then: !file("build/generated/sources/annotationProcessor/java/main/ServiceRegistry.java").exists() + !file("build/generated/sources/annotationProcessor/java/main/ServiceRegistryResource.txt").exists() } def "generated files and classes are deleted when processor is removed"() { given: - def a = java "@Service class A {}" + withProcessor(writingResourcesTo(StandardLocation.SOURCE_OUTPUT.toString())) + java "@Service class A {}" when: outputs.snapshot { run "compileJava" } then: file("build/generated/sources/annotationProcessor/java/main/ServiceRegistry.java").exists() + file("build/generated/sources/annotationProcessor/java/main/ServiceRegistryResource.txt").exists() when: buildFile << "compileJava.options.annotationProcessorPath = files()" @@ -176,25 +189,40 @@ class AggregatingIncrementalAnnotationProcessingIntegrationTest extends Abstract then: !file("build/generated/sources/annotationProcessor/java/main/ServiceRegistry.java").exists() + !file("build/generated/sources/annotationProcessor/java/main/ServiceRegistryResource.txt").exists() and: outputs.deletedClasses("ServiceRegistry") } - def "writing resources triggers a full recompilation"() { + def "processors can generate identical resources in different locations"() { given: - withProcessor(new NonIncrementalProcessorFixture().writingResources().withDeclaredType(IncrementalAnnotationProcessorType.AGGREGATING)) + // Have to configure a native header output directory otherwise there will be errors; javac NPEs when files are created in NATIVE_HEADER_OUTPUT without any location set. + buildFile << ''' +compileJava.options.headerOutputDirectory = file("build/headers/java/main") +''' + def locations = [StandardLocation.SOURCE_OUTPUT.toString(), StandardLocation.NATIVE_HEADER_OUTPUT.toString(), StandardLocation.CLASS_OUTPUT.toString()] + withProcessor(new ResourceGeneratingProcessorFixture().withOutputLocations(locations).withDeclaredType(IncrementalAnnotationProcessorType.AGGREGATING)) def a = java "@Thing class A {}" - outputs.snapshot { succeeds "compileJava" } + java "class Unrelated {}" when: - a.text = "@Thing class A { void foo() {} }" + outputs.snapshot { succeeds "compileJava" } then: - succeeds "compileJava", "--info" + file("build/generated/sources/annotationProcessor/java/main/A.txt").exists() + file("build/headers/java/main/A.txt").exists() + file("build/classes/java/main/A.txt").exists() - and: - outputContains("Full recompilation is required because an annotation processor generated a resource.") + when: + a.delete() + succeeds "compileJava" + + then: "they all get cleaned" + outputs.deletedClasses("A") + !file("build/generated/sources/annotationProcessor/java/main/A.txt").exists() + !file("build/headers/java/main/A.txt").exists() + !file("build/classes/java/main/A.txt").exists() } def "an isolating processor is also a valid aggregating processor"() { diff --git a/subprojects/language-java/src/integTest/groovy/org/gradle/api/tasks/compile/IsolatingIncrementalAnnotationProcessingIntegrationTest.groovy b/subprojects/language-java/src/integTest/groovy/org/gradle/api/tasks/compile/IsolatingIncrementalAnnotationProcessingIntegrationTest.groovy index 04abceb3f4514..633fcb6aafa76 100644 --- a/subprojects/language-java/src/integTest/groovy/org/gradle/api/tasks/compile/IsolatingIncrementalAnnotationProcessingIntegrationTest.groovy +++ b/subprojects/language-java/src/integTest/groovy/org/gradle/api/tasks/compile/IsolatingIncrementalAnnotationProcessingIntegrationTest.groovy @@ -23,18 +23,28 @@ import org.gradle.integtests.fixtures.AvailableJavaHomes import org.gradle.language.fixtures.AnnotationProcessorFixture import org.gradle.language.fixtures.HelperProcessorFixture import org.gradle.language.fixtures.NonIncrementalProcessorFixture +import org.gradle.language.fixtures.ResourceGeneratingProcessorFixture import org.gradle.language.fixtures.ServiceRegistryProcessorFixture import org.gradle.util.TextUtil import spock.lang.Issue +import javax.tools.StandardLocation + import static org.gradle.api.internal.tasks.compile.CompileJavaBuildOperationType.Result.AnnotationProcessorDetails.Type.ISOLATING class IsolatingIncrementalAnnotationProcessingIntegrationTest extends AbstractIncrementalAnnotationProcessingIntegrationTest { + private static HelperProcessorFixture writingResourcesTo(String location) { + def helperProcessorFixture = new HelperProcessorFixture() + helperProcessorFixture.writeResources = true + helperProcessorFixture.resourceLocation = location + return helperProcessorFixture + } + private HelperProcessorFixture helperProcessor @Override def setup() { - helperProcessor = new HelperProcessorFixture() + helperProcessor = writingResourcesTo(StandardLocation.CLASS_OUTPUT.toString()) withProcessor(helperProcessor) } @@ -50,7 +60,7 @@ class IsolatingIncrementalAnnotationProcessingIntegrationTest extends AbstractIn run "compileJava" then: - outputs.recompiledClasses("A", "AHelper") + outputs.recompiledFiles("A", "AHelper", "AHelperResource.txt") } def "annotated files are not recompiled on unrelated changes"() { @@ -83,7 +93,7 @@ class IsolatingIncrementalAnnotationProcessingIntegrationTest extends AbstractIn run "compileJava" then: - outputs.recompiledClasses("A", "AHelper", "Dependent") + outputs.recompiledFiles("A", "AHelper", "Dependent", "AHelperResource.txt") } def "source file is recompiled when dependency of generated file changes"() { @@ -114,11 +124,12 @@ class IsolatingIncrementalAnnotationProcessingIntegrationTest extends AbstractIn run "compileJava" then: - outputs.deletedClasses("A", "AHelper") + outputs.deletedFiles("A", "AHelper", "AHelperResource.txt") } def "generated files are deleted when annotated file is deleted"() { given: + withProcessor(writingResourcesTo(StandardLocation.SOURCE_OUTPUT.toString())) def a = java "@Helper class A {}" java "class Unrelated {}" @@ -127,6 +138,7 @@ class IsolatingIncrementalAnnotationProcessingIntegrationTest extends AbstractIn then: file("build/generated/sources/annotationProcessor/java/main/AHelper.java").exists() + file("build/generated/sources/annotationProcessor/java/main/AHelperResource.txt").exists() when: a.delete() @@ -134,17 +146,20 @@ class IsolatingIncrementalAnnotationProcessingIntegrationTest extends AbstractIn then: !file("build/generated/sources/annotationProcessor/java/main/AHelper.java").exists() + !file("build/generated/sources/annotationProcessor/java/main/AHelperResource.txt").exists() } def "generated files and classes are deleted when processor is removed"() { given: - def a = java "@Helper class A {}" + withProcessor(writingResourcesTo(StandardLocation.SOURCE_OUTPUT.toString())) + java "@Helper class A {}" when: outputs.snapshot { run "compileJava" } then: file("build/generated/sources/annotationProcessor/java/main/AHelper.java").exists() + file("build/generated/sources/annotationProcessor/java/main/AHelperResource.txt").exists() when: buildFile << "compileJava.options.annotationProcessorPath = files()" @@ -152,14 +167,15 @@ class IsolatingIncrementalAnnotationProcessingIntegrationTest extends AbstractIn then: !file("build/generated/sources/annotationProcessor/java/main/AHelper.java").exists() + !file("build/generated/sources/annotationProcessor/java/main/AHelperResource.txt").exists() and: - outputs.deletedClasses("AHelper") + outputs.deletedFiles("AHelper") } def "all files are recompiled when processor changes"() { given: - def a = java "@Helper class A {}" + java "@Helper class A {}" outputs.snapshot { run "compileJava" } when: @@ -168,7 +184,7 @@ class IsolatingIncrementalAnnotationProcessingIntegrationTest extends AbstractIn run "compileJava" then: - outputs.recompiledClasses("A", "AHelper") + outputs.recompiledFiles("A", "AHelper", "AHelperResource.txt") } def "all files are recompiled if compiler does not support incremental annotation processing"() { @@ -189,7 +205,7 @@ class IsolatingIncrementalAnnotationProcessingIntegrationTest extends AbstractIn run "compileJava", "--info" then: - outputs.recompiledClasses("A", "AHelper", "Unrelated") + outputs.recompiledFiles("A", "AHelper", "Unrelated", "AHelperResource.txt") and: outputContains("the chosen compiler did not support incremental annotation processing") @@ -207,7 +223,7 @@ class IsolatingIncrementalAnnotationProcessingIntegrationTest extends AbstractIn run "compileJava" then: - outputs.recompiledClasses('A', "AHelper", "Unrelated") + outputs.recompiledFiles('A', "AHelper", "AHelperResource.txt", "Unrelated") } def "all files are recompiled if a generated class is deleted"() { @@ -222,7 +238,22 @@ class IsolatingIncrementalAnnotationProcessingIntegrationTest extends AbstractIn run "compileJava" then: - outputs.recompiledClasses('A', "AHelper", "Unrelated") + outputs.recompiledFiles('A', "AHelper", "AHelperResource.txt", "Unrelated") + } + + def "all files are recompiled if a generated resource is deleted"() { + given: + java "@Helper class A {}" + java "class Unrelated {}" + + outputs.snapshot { run "compileJava" } + + when: + file("build/classes/java/main/AHelperResource.txt").delete() + run "compileJava" + + then: + outputs.recompiledFiles('A', "AHelper", "AHelperResource.txt", "Unrelated") } def "processors must provide an originating element for each source element"() { @@ -241,9 +272,9 @@ class IsolatingIncrementalAnnotationProcessingIntegrationTest extends AbstractIn outputContains("Full recompilation is required because the generated type 'AThing' must have exactly one originating element, but had 0.") } - def "writing resources triggers a full recompilation"() { + def "processors must provide an originating element for each resource"() { given: - withProcessor(new NonIncrementalProcessorFixture().writingResources().withDeclaredType(IncrementalAnnotationProcessorType.ISOLATING)) + withProcessor(new ResourceGeneratingProcessorFixture().providingNoOriginatingElements().withDeclaredType(IncrementalAnnotationProcessorType.ISOLATING)) def a = java "@Thing class A {}" outputs.snapshot { succeeds "compileJava" } @@ -254,10 +285,10 @@ class IsolatingIncrementalAnnotationProcessingIntegrationTest extends AbstractIn succeeds "compileJava", "--info" and: - outputContains("Full recompilation is required because an annotation processor generated a resource.") + outputContains("Full recompilation is required because the generated resource 'A.txt in SOURCE_OUTPUT' must have exactly one originating element, but had 0.") } - def "processors cannot provide multiple originating elements"() { + def "processors cannot provide multiple originating elements for types"() { given: withProcessor(new ServiceRegistryProcessorFixture().withDeclaredType(IncrementalAnnotationProcessorType.ISOLATING)) def a = java "@Service class A {}" @@ -275,6 +306,56 @@ class IsolatingIncrementalAnnotationProcessingIntegrationTest extends AbstractIn outputContains("Full recompilation is required because the generated type 'ServiceRegistry' must have exactly one originating element, but had 2.") } + def "processors cannot provide multiple originating elements for resources"() { + given: + def proc = new ServiceRegistryProcessorFixture() + proc.writeResources = true + withProcessor(proc.withDeclaredType(IncrementalAnnotationProcessorType.ISOLATING)) + def a = java "@Service class A {}" + java "@Service class B {}" + + outputs.snapshot { succeeds "compileJava" } + + when: + a.text = "@Service class A { void foo() {} }" + + then: + succeeds "compileJava", "--info" + + and: + outputContains("Full recompilation is required because the generated resource 'ServiceRegistryResource.txt in CLASS_OUTPUT' must have exactly one originating element, but had 2.") + } + + def "processors can generate identical resources in different locations"() { + given: + // Have to configure a native header output directory otherwise there will be errors; javac NPEs when files are created in NATIVE_HEADER_OUTPUT without any location set. + buildFile << ''' +compileJava.options.headerOutputDirectory = file("build/headers/java/main") +''' + def locations = [StandardLocation.SOURCE_OUTPUT.toString(), StandardLocation.NATIVE_HEADER_OUTPUT.toString(), StandardLocation.CLASS_OUTPUT.toString()] + withProcessor(new ResourceGeneratingProcessorFixture().withOutputLocations(locations).withDeclaredType(IncrementalAnnotationProcessorType.ISOLATING)) + def a = java "@Thing class A {}" + java "class Unrelated {}" + + when: + outputs.snapshot { succeeds "compileJava" } + + then: + file("build/generated/sources/annotationProcessor/java/main/A.txt").exists() + file("build/headers/java/main/A.txt").exists() + file("build/classes/java/main/A.txt").exists() + + when: + a.delete() + succeeds "compileJava" + + then: "they all get cleaned" + outputs.deletedClasses("A") + !file("build/generated/sources/annotationProcessor/java/main/A.txt").exists() + !file("build/headers/java/main/A.txt").exists() + !file("build/classes/java/main/A.txt").exists() + } + @Issue(["https://github.com/gradle/gradle/issues/8128", "https://bugs.openjdk.java.net/browse/JDK-8162455"]) def "incremental processing doesn't trigger unmatched processor option warning"() { buildFile << """ diff --git a/subprojects/language-java/src/main/java/org/gradle/api/internal/tasks/compile/incremental/IncrementalCompilationInitializer.java b/subprojects/language-java/src/main/java/org/gradle/api/internal/tasks/compile/incremental/IncrementalCompilationInitializer.java index d190ac9d932c5..777b2d377a85f 100644 --- a/subprojects/language-java/src/main/java/org/gradle/api/internal/tasks/compile/incremental/IncrementalCompilationInitializer.java +++ b/subprojects/language-java/src/main/java/org/gradle/api/internal/tasks/compile/incremental/IncrementalCompilationInitializer.java @@ -16,12 +16,14 @@ package org.gradle.api.internal.tasks.compile.incremental; +import com.google.common.base.MoreObjects; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Lists; import com.google.common.collect.Sets; import org.gradle.api.file.FileTree; import org.gradle.api.internal.file.FileOperations; import org.gradle.api.internal.tasks.compile.JavaCompileSpec; +import org.gradle.api.internal.tasks.compile.incremental.processing.GeneratedResource; import org.gradle.api.internal.tasks.compile.incremental.recomp.RecompilationSpec; import org.gradle.api.tasks.util.PatternSet; import org.gradle.internal.Factory; @@ -30,7 +32,9 @@ import java.io.File; import java.util.Collection; import java.util.Collections; +import java.util.EnumMap; import java.util.List; +import java.util.Map; import java.util.Set; class IncrementalCompilationInitializer { @@ -52,13 +56,20 @@ public void initializeCompilation(JavaCompileSpec spec, RecompilationSpec recomp PatternSet classesToDelete = patternSetFactory.create(); PatternSet sourceToCompile = patternSetFactory.create(); - preparePatterns(recompilationSpec.getClassesToCompile(), classesToDelete, sourceToCompile); + prepareJavaPatterns(recompilationSpec.getClassesToCompile(), classesToDelete, sourceToCompile); spec.setSourceFiles(narrowDownSourcesToCompile(sourceTree, sourceToCompile)); includePreviousCompilationOutputOnClasspath(spec); addClassesToProcess(spec, recompilationSpec); deleteStaleFilesIn(classesToDelete, spec.getDestinationDir()); deleteStaleFilesIn(classesToDelete, spec.getCompileOptions().getAnnotationProcessorGeneratedSourcesDirectory()); deleteStaleFilesIn(classesToDelete, spec.getCompileOptions().getHeaderOutputDirectory()); + + Map resourcesToDelete = prepareResourcePatterns(recompilationSpec.getResourcesToGenerate(), patternSetFactory); + deleteStaleFilesIn(resourcesToDelete.get(GeneratedResource.Location.CLASS_OUTPUT), spec.getDestinationDir()); + // If the client has not set a location for SOURCE_OUTPUT, javac outputs those files to the CLASS_OUTPUT directory, so clean that instead. + deleteStaleFilesIn(resourcesToDelete.get(GeneratedResource.Location.SOURCE_OUTPUT), MoreObjects.firstNonNull(spec.getCompileOptions().getAnnotationProcessorGeneratedSourcesDirectory(), spec.getDestinationDir())); + // In the same situation with NATIVE_HEADER_OUTPUT, javac just NPEs. Don't bother. + deleteStaleFilesIn(resourcesToDelete.get(GeneratedResource.Location.NATIVE_HEADER_OUTPUT), spec.getCompileOptions().getHeaderOutputDirectory()); } private Iterable narrowDownSourcesToCompile(FileTree sourceTree, PatternSet sourceToCompile) { @@ -79,7 +90,7 @@ private void addClassesToProcess(JavaCompileSpec spec, RecompilationSpec recompi } private void deleteStaleFilesIn(PatternSet filesToDelete, final File destinationDir) { - if (destinationDir == null) { + if (filesToDelete == null || filesToDelete.isEmpty() || destinationDir == null) { return; } Set toDelete = fileOperations.fileTree(destinationDir).matching(filesToDelete).getFiles(); @@ -88,7 +99,7 @@ private void deleteStaleFilesIn(PatternSet filesToDelete, final File destination cleaner.execute(); } - private void preparePatterns(Collection staleClasses, PatternSet filesToDelete, PatternSet sourceToCompile) { + private void prepareJavaPatterns(Collection staleClasses, PatternSet filesToDelete, PatternSet sourceToCompile) { for (String staleClass : staleClasses) { String path = staleClass.replaceAll("\\.", "/"); filesToDelete.include(path.concat(".class")); @@ -102,4 +113,15 @@ private void preparePatterns(Collection staleClasses, PatternSet filesTo sourceToCompile.include(path.concat("$*.java")); } } + + private static Map prepareResourcePatterns(Collection staleResources, Factory patternSetFactory) { + Map resourcesByLocation = new EnumMap(GeneratedResource.Location.class); + for (GeneratedResource.Location location : GeneratedResource.Location.values()) { + resourcesByLocation.put(location, patternSetFactory.create()); + } + for (GeneratedResource resource : staleResources) { + resourcesByLocation.get(resource.getLocation()).include(resource.getPath()); + } + return resourcesByLocation; + } } diff --git a/subprojects/language-java/src/main/java/org/gradle/api/internal/tasks/compile/incremental/IncrementalResultStoringCompiler.java b/subprojects/language-java/src/main/java/org/gradle/api/internal/tasks/compile/incremental/IncrementalResultStoringCompiler.java index 2ece6241ede06..19adf72f6dabc 100644 --- a/subprojects/language-java/src/main/java/org/gradle/api/internal/tasks/compile/incremental/IncrementalResultStoringCompiler.java +++ b/subprojects/language-java/src/main/java/org/gradle/api/internal/tasks/compile/incremental/IncrementalResultStoringCompiler.java @@ -28,6 +28,7 @@ import org.gradle.api.internal.tasks.compile.incremental.classpath.ClasspathSnapshotProvider; import org.gradle.api.internal.tasks.compile.incremental.processing.AnnotationProcessingData; import org.gradle.api.internal.tasks.compile.incremental.processing.AnnotationProcessingResult; +import org.gradle.api.internal.tasks.compile.incremental.processing.GeneratedResource; import org.gradle.api.internal.tasks.compile.incremental.recomp.PreviousCompilationData; import org.gradle.api.internal.tasks.compile.processing.AnnotationProcessorDeclaration; import org.gradle.api.tasks.WorkResult; @@ -80,14 +81,16 @@ private AnnotationProcessingData getAnnotationProcessingResult(JavaCompileSpec s AnnotationProcessingResult processingResult = ((JdkJavaCompilerResult) result).getAnnotationProcessingResult(); return convertProcessingResult(processingResult); } - return new AnnotationProcessingData(ImmutableMap.>of(), ImmutableSet.of(), ImmutableSet.of(), "the chosen compiler did not support incremental annotation processing"); + return new AnnotationProcessingData(ImmutableMap.>of(), ImmutableSet.of(), ImmutableSet.of(), ImmutableMap.>of(), ImmutableSet.of(), "the chosen compiler did not support incremental annotation processing"); } private AnnotationProcessingData convertProcessingResult(AnnotationProcessingResult processingResult) { Map> generatedTypesByOrigin = processingResult.getGeneratedTypesWithIsolatedOrigin(); + Map> generatedResourcesByOrigin = processingResult.getGeneratedResourcesWithIsolatedOrigin(); Set aggregatedTypes = processingResult.getAggregatedTypes(); Set aggregatingTypes = processingResult.getGeneratedAggregatingTypes(); - return new AnnotationProcessingData(intern(generatedTypesByOrigin), intern(aggregatedTypes), intern(aggregatingTypes), processingResult.getFullRebuildCause()); + Set aggregatingResources = processingResult.getGeneratedAggregatingResources(); + return new AnnotationProcessingData(intern(generatedTypesByOrigin), intern(aggregatedTypes), intern(aggregatingTypes), generatedResourcesByOrigin, aggregatingResources, processingResult.getFullRebuildCause()); } private Set intern(Set types) { diff --git a/subprojects/language-java/src/main/java/org/gradle/api/internal/tasks/compile/incremental/classpath/ClasspathEntrySnapshot.java b/subprojects/language-java/src/main/java/org/gradle/api/internal/tasks/compile/incremental/classpath/ClasspathEntrySnapshot.java index 0fbea8060795a..2b3a294a318c1 100644 --- a/subprojects/language-java/src/main/java/org/gradle/api/internal/tasks/compile/incremental/classpath/ClasspathEntrySnapshot.java +++ b/subprojects/language-java/src/main/java/org/gradle/api/internal/tasks/compile/incremental/classpath/ClasspathEntrySnapshot.java @@ -48,7 +48,7 @@ public DependentsSet getAllClasses() { } result.add(className); } - return DependentsSet.dependents(result); + return DependentsSet.dependentClasses(result); } public IntSet getAllConstants(DependentsSet dependents) { diff --git a/subprojects/language-java/src/main/java/org/gradle/api/internal/tasks/compile/incremental/deps/ClassDependentsAccumulator.java b/subprojects/language-java/src/main/java/org/gradle/api/internal/tasks/compile/incremental/deps/ClassDependentsAccumulator.java index c779e06deb53d..61a3307cebdc9 100644 --- a/subprojects/language-java/src/main/java/org/gradle/api/internal/tasks/compile/incremental/deps/ClassDependentsAccumulator.java +++ b/subprojects/language-java/src/main/java/org/gradle/api/internal/tasks/compile/incremental/deps/ClassDependentsAccumulator.java @@ -80,7 +80,7 @@ Map getDependentsMap() { builder.put(s, DependentsSet.dependencyToAll()); } for (Map.Entry> entry : dependents.entrySet()) { - builder.put(entry.getKey(), DependentsSet.dependents(entry.getValue())); + builder.put(entry.getKey(), DependentsSet.dependentClasses(entry.getValue())); } return builder.build(); } diff --git a/subprojects/language-java/src/main/java/org/gradle/api/internal/tasks/compile/incremental/deps/ClassSetAnalysis.java b/subprojects/language-java/src/main/java/org/gradle/api/internal/tasks/compile/incremental/deps/ClassSetAnalysis.java index 0acc432b7e964..f1f2243caf854 100644 --- a/subprojects/language-java/src/main/java/org/gradle/api/internal/tasks/compile/incremental/deps/ClassSetAnalysis.java +++ b/subprojects/language-java/src/main/java/org/gradle/api/internal/tasks/compile/incremental/deps/ClassSetAnalysis.java @@ -21,6 +21,7 @@ import com.google.common.collect.Sets; import it.unimi.dsi.fastutil.ints.IntSet; import org.gradle.api.internal.tasks.compile.incremental.processing.AnnotationProcessingData; +import org.gradle.api.internal.tasks.compile.incremental.processing.GeneratedResource; import java.util.HashSet; import java.util.Map; @@ -30,7 +31,8 @@ public class ClassSetAnalysis { private final ClassSetAnalysisData classAnalysis; private final AnnotationProcessingData annotationProcessingData; - private final ImmutableSetMultimap dependenciesFromAnnotationProcessing; + private final ImmutableSetMultimap classDependenciesFromAnnotationProcessing; + private final ImmutableSetMultimap resourceDependenciesFromAnnotationProcessing; public ClassSetAnalysis(ClassSetAnalysisData classAnalysis) { this(classAnalysis, new AnnotationProcessingData()); @@ -39,15 +41,24 @@ public ClassSetAnalysis(ClassSetAnalysisData classAnalysis) { public ClassSetAnalysis(ClassSetAnalysisData classAnalysis, AnnotationProcessingData annotationProcessingData) { this.classAnalysis = classAnalysis; this.annotationProcessingData = annotationProcessingData; - ImmutableSetMultimap.Builder dependenciesFromAnnotationProcessing = ImmutableSetMultimap.builder(); + ImmutableSetMultimap.Builder classDependenciesFromAnnotationProcessing = ImmutableSetMultimap.builder(); for (Map.Entry> entry : annotationProcessingData.getGeneratedTypesByOrigin().entrySet()) { for (String generated : entry.getValue()) { String origin = entry.getKey(); - dependenciesFromAnnotationProcessing.put(origin, generated); - dependenciesFromAnnotationProcessing.put(generated, origin); + classDependenciesFromAnnotationProcessing.put(origin, generated); + classDependenciesFromAnnotationProcessing.put(generated, origin); } } - this.dependenciesFromAnnotationProcessing = dependenciesFromAnnotationProcessing.build(); + this.classDependenciesFromAnnotationProcessing = classDependenciesFromAnnotationProcessing.build(); + + ImmutableSetMultimap.Builder resourceDependenciesFromAnnotationProcessing = ImmutableSetMultimap.builder(); + for (Map.Entry> entry : annotationProcessingData.getGeneratedResourcesByOrigin().entrySet()) { + for (GeneratedResource generated : entry.getValue()) { + String origin = entry.getKey(); + resourceDependenciesFromAnnotationProcessing.put(origin, generated); + } + } + this.resourceDependenciesFromAnnotationProcessing = resourceDependenciesFromAnnotationProcessing.build(); } public ClassSetAnalysis withAnnotationProcessingData(AnnotationProcessingData annotationProcessingData) { @@ -55,22 +66,28 @@ public ClassSetAnalysis withAnnotationProcessingData(AnnotationProcessingData an } public DependentsSet getRelevantDependents(Iterable classes, IntSet constants) { - Set result = null; + Set resultClasses = null; + Set resultResources = null; for (String cls : classes) { DependentsSet d = getRelevantDependents(cls, constants); if (d.isDependencyToAll()) { return d; } Set dependentClasses = d.getDependentClasses(); - if (dependentClasses.isEmpty()) { + Set dependentResources = d.getDependentResources(); + if (dependentClasses.isEmpty() && dependentResources.isEmpty()) { continue; } - if (result == null) { - result = Sets.newLinkedHashSet(); + if (resultClasses == null) { + resultClasses = Sets.newLinkedHashSet(); } - result.addAll(dependentClasses); + resultClasses.addAll(dependentClasses); + if (resultResources == null) { + resultResources = Sets.newLinkedHashSet(); + } + resultResources.addAll(dependentResources); } - return result == null ? DependentsSet.empty() : DependentsSet.dependents(result); + return resultClasses == null ? DependentsSet.empty() : DependentsSet.dependents(resultClasses, resultResources); } public DependentsSet getRelevantDependents(String className, IntSet constants) { @@ -85,15 +102,19 @@ public DependentsSet getRelevantDependents(String className, IntSet constants) { if (!constants.isEmpty()) { return DependentsSet.dependencyToAll(); } - Set dependingOnAllOthers = annotationProcessingData.getGeneratedTypesDependingOnAllOthers(); - if (deps.getDependentClasses().isEmpty() && dependingOnAllOthers.isEmpty()) { + Set classesDependingOnAllOthers = annotationProcessingData.getGeneratedTypesDependingOnAllOthers(); + Set resourcesDependingOnAllOthers = annotationProcessingData.getGeneratedResourcesDependingOnAllOthers(); + if (deps.getDependentClasses().isEmpty() && classesDependingOnAllOthers.isEmpty() && resourcesDependingOnAllOthers.isEmpty()) { return deps; } - Set result = new HashSet(); - recurseDependents(new HashSet(), result, deps.getDependentClasses()); - recurseDependents(new HashSet(), result, dependingOnAllOthers); - result.remove(className); - return DependentsSet.dependents(result); + + Set resultClasses = new HashSet(); + Set resultResources = new HashSet(resourcesDependingOnAllOthers); + recurseDependentClasses(new HashSet(), resultClasses, resultResources, deps.getDependentClasses()); + recurseDependentClasses(new HashSet(), resultClasses, resultResources, classesDependingOnAllOthers); + resultClasses.remove(className); + + return DependentsSet.dependents(resultClasses, resultResources); } public Set getTypesToReprocess() { @@ -104,17 +125,22 @@ public boolean isDependencyToAll(String className) { return classAnalysis.getDependents(className).isDependencyToAll(); } - private void recurseDependents(Set visited, Set result, Iterable dependentClasses) { + /** + * Recursively accumulate dependent classes and resources. Dependent classes discovered can themselves be used to query + * further dependents, while resources are just data accumulated along the way. + */ + private void recurseDependentClasses(Set visitedClasses, Set resultClasses, Set resultResources, Iterable dependentClasses) { for (String d : dependentClasses) { - if (!visited.add(d)) { + if (!visitedClasses.add(d)) { continue; } if (!isNestedClass(d)) { - result.add(d); + resultClasses.add(d); } DependentsSet currentDependents = getDependents(d); if (!currentDependents.isDependencyToAll()) { - recurseDependents(visited, result, currentDependents.getDependentClasses()); + resultResources.addAll(currentDependents.getDependentResources()); + recurseDependentClasses(visitedClasses, resultClasses, resultResources, currentDependents.getDependentClasses()); } } } @@ -124,11 +150,12 @@ private DependentsSet getDependents(String className) { if (dependents.isDependencyToAll()) { return dependents; } - ImmutableSet additionalDeps = dependenciesFromAnnotationProcessing.get(className); - if (additionalDeps.isEmpty()) { + ImmutableSet additionalClassDeps = classDependenciesFromAnnotationProcessing.get(className); + ImmutableSet additionalResourceDeps = resourceDependenciesFromAnnotationProcessing.get(className); + if (additionalClassDeps.isEmpty() && additionalResourceDeps.isEmpty()) { return dependents; } - return DependentsSet.dependents(Sets.union(dependents.getDependentClasses(), additionalDeps)); + return DependentsSet.dependents(Sets.union(dependents.getDependentClasses(), additionalClassDeps), Sets.union(dependents.getDependentResources(), additionalResourceDeps)); } private boolean isNestedClass(String d) { diff --git a/subprojects/language-java/src/main/java/org/gradle/api/internal/tasks/compile/incremental/deps/ClassSetAnalysisData.java b/subprojects/language-java/src/main/java/org/gradle/api/internal/tasks/compile/incremental/deps/ClassSetAnalysisData.java index 27f584449f831..d482b0fddca4c 100644 --- a/subprojects/language-java/src/main/java/org/gradle/api/internal/tasks/compile/incremental/deps/ClassSetAnalysisData.java +++ b/subprojects/language-java/src/main/java/org/gradle/api/internal/tasks/compile/incremental/deps/ClassSetAnalysisData.java @@ -68,7 +68,7 @@ private DependentsSet getDependentsOfPackage(String packageName) { typesInPackage.add(type); } } - return DependentsSet.dependents(typesInPackage); + return DependentsSet.dependentClasses(typesInPackage); } public IntSet getConstants(String className) { @@ -150,7 +150,7 @@ private DependentsSet readDependentsSet(Decoder decoder, Map cl for (int i = 0; i < count; i++) { builder.add(readClassName(decoder, classNameMap)); } - return DependentsSet.dependents(builder.build()); + return DependentsSet.dependentClasses(builder.build()); } private void writeDependentSet(DependentsSet dependentsSet, Map classNameMap, Encoder encoder) throws IOException { diff --git a/subprojects/language-java/src/main/java/org/gradle/api/internal/tasks/compile/incremental/deps/DependentsSet.java b/subprojects/language-java/src/main/java/org/gradle/api/internal/tasks/compile/incremental/deps/DependentsSet.java index fe782ef8b0e81..7e1a35b1f453f 100644 --- a/subprojects/language-java/src/main/java/org/gradle/api/internal/tasks/compile/incremental/deps/DependentsSet.java +++ b/subprojects/language-java/src/main/java/org/gradle/api/internal/tasks/compile/incremental/deps/DependentsSet.java @@ -17,6 +17,7 @@ package org.gradle.api.internal.tasks.compile.incremental.deps; import com.google.common.collect.ImmutableSet; +import org.gradle.api.internal.tasks.compile.incremental.processing.GeneratedResource; import javax.annotation.Nullable; import java.util.Collections; @@ -24,19 +25,23 @@ public abstract class DependentsSet { - public static DependentsSet dependents(String... dependentClasses) { + public static DependentsSet dependentClasses(String... dependentClasses) { if (dependentClasses.length == 0) { return empty(); } else { - return new DefaultDependentsSet(ImmutableSet.copyOf(dependentClasses)); + return new DefaultDependentsSet(ImmutableSet.copyOf(dependentClasses), Collections.emptySet()); } } - public static DependentsSet dependents(Set dependentClasses) { - if (dependentClasses.isEmpty()) { + public static DependentsSet dependentClasses(Set dependentClasses) { + return dependents(dependentClasses, Collections.emptySet()); + } + + public static DependentsSet dependents(Set dependentClasses, Set dependentResources) { + if (dependentClasses.isEmpty() && dependentResources.isEmpty()) { return empty(); } else { - return new DefaultDependentsSet(ImmutableSet.copyOf(dependentClasses)); + return new DefaultDependentsSet(ImmutableSet.copyOf(dependentClasses), ImmutableSet.copyOf(dependentResources)); } } @@ -54,6 +59,8 @@ public static DependentsSet empty() { public abstract Set getDependentClasses(); + public abstract Set getDependentResources(); + public abstract boolean isDependencyToAll(); public abstract @Nullable String getDescription(); @@ -69,6 +76,11 @@ public Set getDependentClasses() { return Collections.emptySet(); } + @Override + public Set getDependentResources() { + return Collections.emptySet(); + } + @Override public boolean isDependencyToAll() { return false; @@ -84,9 +96,11 @@ public String getDescription() { private static class DefaultDependentsSet extends DependentsSet { private final Set dependentClasses; + private final Set dependentResources; - private DefaultDependentsSet(Set dependentClasses) { + private DefaultDependentsSet(Set dependentClasses, Set dependentResources) { this.dependentClasses = dependentClasses; + this.dependentResources = dependentResources; } @Override @@ -94,6 +108,11 @@ public Set getDependentClasses() { return dependentClasses; } + @Override + public Set getDependentResources() { + return dependentResources; + } + @Override public boolean isDependencyToAll() { return false; @@ -123,6 +142,11 @@ public Set getDependentClasses() { throw new UnsupportedOperationException("This instance of dependents set does not have dependent classes information."); } + @Override + public Set getDependentResources() { + throw new UnsupportedOperationException("This instance of dependents set does not have dependent resources information."); + } + @Override public boolean isDependencyToAll() { return true; diff --git a/subprojects/language-java/src/main/java/org/gradle/api/internal/tasks/compile/incremental/processing/AnnotationProcessingData.java b/subprojects/language-java/src/main/java/org/gradle/api/internal/tasks/compile/incremental/processing/AnnotationProcessingData.java index 40562c4ff6d42..d26101c63f3d5 100644 --- a/subprojects/language-java/src/main/java/org/gradle/api/internal/tasks/compile/incremental/processing/AnnotationProcessingData.java +++ b/subprojects/language-java/src/main/java/org/gradle/api/internal/tasks/compile/incremental/processing/AnnotationProcessingData.java @@ -33,16 +33,22 @@ public class AnnotationProcessingData { private final Map> generatedTypesByOrigin; private final Set aggregatedTypes; private final Set generatedTypesDependingOnAllOthers; + private final Map> generatedResourcesByOrigin; + private final Set generatedResourcesDependingOnAllOthers; private final String fullRebuildCause; public AnnotationProcessingData() { - this(ImmutableMap.>of(), ImmutableSet.of(), ImmutableSet.of(), null); + this(ImmutableMap.>of(), ImmutableSet.of(), ImmutableSet.of(), ImmutableMap.>of(), ImmutableSet.of(), null); } - public AnnotationProcessingData(Map> generatedTypesByOrigin, Set aggregatedTypes, Set generatedTypesDependingOnAllOthers, String fullRebuildCause) { + public AnnotationProcessingData(Map> generatedTypesByOrigin, Set aggregatedTypes, Set generatedTypesDependingOnAllOthers, Map> generatedResourcesByOrigin, Set generatedResourcesDependingOnAllOthers, String fullRebuildCause) { + this.generatedTypesByOrigin = ImmutableMap.copyOf(generatedTypesByOrigin); this.aggregatedTypes = ImmutableSet.copyOf(aggregatedTypes); this.generatedTypesDependingOnAllOthers = ImmutableSet.copyOf(generatedTypesDependingOnAllOthers); + this.generatedResourcesByOrigin = ImmutableMap.copyOf(generatedResourcesByOrigin); + this.generatedResourcesDependingOnAllOthers = ImmutableSet.copyOf(generatedResourcesDependingOnAllOthers); this.fullRebuildCause = fullRebuildCause; } @@ -58,6 +64,14 @@ public Set getGeneratedTypesDependingOnAllOthers() { return generatedTypesDependingOnAllOthers; } + public Map> getGeneratedResourcesByOrigin() { + return generatedResourcesByOrigin; + } + + public Set getGeneratedResourcesDependingOnAllOthers() { + return generatedResourcesDependingOnAllOthers; + } + public String getFullRebuildCause() { return fullRebuildCause; } @@ -65,11 +79,17 @@ public String getFullRebuildCause() { public static final class Serializer extends AbstractSerializer { private final SetSerializer typesSerializer; private final MapSerializer> generatedTypesSerializer; + private final SetSerializer resourcesSerializer; + private final MapSerializer> generatedResourcesSerializer; public Serializer(StringInterner interner) { InterningStringSerializer stringSerializer = new InterningStringSerializer(interner); typesSerializer = new SetSerializer(stringSerializer); generatedTypesSerializer = new MapSerializer>(stringSerializer, typesSerializer); + + GeneratedResourceSerializer resourceSerializer = new GeneratedResourceSerializer(stringSerializer); + this.resourcesSerializer = new SetSerializer(resourceSerializer); + this.generatedResourcesSerializer = new MapSerializer>(stringSerializer, resourcesSerializer); } @Override @@ -78,7 +98,10 @@ public AnnotationProcessingData read(Decoder decoder) throws Exception { Set aggregatedTypes = typesSerializer.read(decoder); Set generatedTypesDependingOnAllOthers = typesSerializer.read(decoder); String fullRebuildCause = decoder.readNullableString(); - return new AnnotationProcessingData(generatedTypes, aggregatedTypes, generatedTypesDependingOnAllOthers, fullRebuildCause); + Map> generatedResources = generatedResourcesSerializer.read(decoder); + Set generatedResourcesDependingOnAllOthers = resourcesSerializer.read(decoder); + + return new AnnotationProcessingData(generatedTypes, aggregatedTypes, generatedTypesDependingOnAllOthers, generatedResources, generatedResourcesDependingOnAllOthers, fullRebuildCause); } @Override @@ -87,6 +110,8 @@ public void write(Encoder encoder, AnnotationProcessingData value) throws Except typesSerializer.write(encoder, value.aggregatedTypes); typesSerializer.write(encoder, value.generatedTypesDependingOnAllOthers); encoder.writeNullableString(value.fullRebuildCause); + generatedResourcesSerializer.write(encoder, value.generatedResourcesByOrigin); + resourcesSerializer.write(encoder, value.generatedResourcesDependingOnAllOthers); } } } diff --git a/subprojects/language-java/src/main/java/org/gradle/api/internal/tasks/compile/incremental/processing/AnnotationProcessingResult.java b/subprojects/language-java/src/main/java/org/gradle/api/internal/tasks/compile/incremental/processing/AnnotationProcessingResult.java index 37056a805ded6..de53eb32d012c 100644 --- a/subprojects/language-java/src/main/java/org/gradle/api/internal/tasks/compile/incremental/processing/AnnotationProcessingResult.java +++ b/subprojects/language-java/src/main/java/org/gradle/api/internal/tasks/compile/incremental/processing/AnnotationProcessingResult.java @@ -31,8 +31,10 @@ public class AnnotationProcessingResult implements Serializable { private final Map> generatedTypesByOrigin = new LinkedHashMap>(); + private final Map> generatedResourcesByOrigin = new LinkedHashMap>(); private final Set aggregatedTypes = new HashSet(); private final Set generatedTypesDependingOnAllOthers = new HashSet(); + private final Set getGeneratedResourcesDependingOnAllOthers = new HashSet(); private final List annotationProcessorResults = new ArrayList(); private String fullRebuildCause; @@ -47,6 +49,17 @@ public void addGeneratedType(String name, Set originatingElements) { } } + public void addGeneratedResource(GeneratedResource resource, Set originatingElements) { + for (String originatingElement : originatingElements) { + Set derived = generatedResourcesByOrigin.get(originatingElement); + if (derived == null) { + derived = new LinkedHashSet(); + generatedResourcesByOrigin.put(originatingElement, derived); + } + derived.add(resource); + } + } + /** * Contains the types generated by isolating annotation processors, grouped by the type they were generated from. */ @@ -54,6 +67,13 @@ public Map> getGeneratedTypesWithIsolatedOrigin() { return generatedTypesByOrigin; } + /** + * Contains the resources generated by isolating annotation processors, grouped by the type they were generated from. + */ + public Map> getGeneratedResourcesWithIsolatedOrigin() { + return generatedResourcesByOrigin; + } + /** * Contains the types that aggregating annotation processors registered themselves for. * These types need to be reprocessed no matter what source changes are made to ensure that the generated types contain all relevant information. @@ -70,6 +90,14 @@ public Set getGeneratedAggregatingTypes() { return generatedTypesDependingOnAllOthers; } + /** + * Contains the resources that aggregating annotation processors generated. + * These resources need to be recreated on any source change, because it may not be clear where these resources came from and whether they are now stale. + */ + public Set getGeneratedAggregatingResources() { + return getGeneratedResourcesDependingOnAllOthers; + } + public void setFullRebuildCause(String fullRebuildCause) { this.fullRebuildCause = fullRebuildCause; } diff --git a/subprojects/language-java/src/main/java/org/gradle/api/internal/tasks/compile/incremental/processing/AnnotationProcessorResult.java b/subprojects/language-java/src/main/java/org/gradle/api/internal/tasks/compile/incremental/processing/AnnotationProcessorResult.java index 2d64a03030a6f..3ea68201cdd5c 100644 --- a/subprojects/language-java/src/main/java/org/gradle/api/internal/tasks/compile/incremental/processing/AnnotationProcessorResult.java +++ b/subprojects/language-java/src/main/java/org/gradle/api/internal/tasks/compile/incremental/processing/AnnotationProcessorResult.java @@ -55,6 +55,10 @@ public void addGeneratedType(String name, Set originatingElements) { processingResult.addGeneratedType(name, originatingElements); } + public void addGeneratedResource(GeneratedResource resource, Set originatingElements) { + processingResult.addGeneratedResource(resource, originatingElements); + } + public Set getAggregatedTypes() { return processingResult.getAggregatedTypes(); } @@ -63,6 +67,10 @@ public Set getGeneratedAggregatingTypes() { return processingResult.getGeneratedAggregatingTypes(); } + public Set getGeneratedAggregatingResources() { + return processingResult.getGeneratedAggregatingResources(); + } + public void setFullRebuildCause(String fullRebuildCause) { processingResult.setFullRebuildCause(fullRebuildCause); } diff --git a/subprojects/language-java/src/main/java/org/gradle/api/internal/tasks/compile/incremental/processing/GeneratedResource.java b/subprojects/language-java/src/main/java/org/gradle/api/internal/tasks/compile/incremental/processing/GeneratedResource.java new file mode 100644 index 0000000000000..d98ff3e36aaa7 --- /dev/null +++ b/subprojects/language-java/src/main/java/org/gradle/api/internal/tasks/compile/incremental/processing/GeneratedResource.java @@ -0,0 +1,99 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.api.internal.tasks.compile.incremental.processing; + +import com.google.common.base.Objects; + +import javax.annotation.Nullable; +import javax.tools.JavaFileManager; +import javax.tools.StandardLocation; +import java.io.Serializable; + +/** + * Uniquely identifies a resource that was generated by an annotation processor. + */ +public final class GeneratedResource implements Serializable { + /** + * The supported locations into which generated resources may be placed. + */ + public enum Location { + CLASS_OUTPUT, + SOURCE_OUTPUT, + NATIVE_HEADER_OUTPUT,; + + /** + * @return null if the given location is not supported. + */ + @Nullable + public static Location from(JavaFileManager.Location location) { + if (location instanceof StandardLocation) { + switch ((StandardLocation) location) { + case CLASS_OUTPUT: + return CLASS_OUTPUT; + case SOURCE_OUTPUT: + return SOURCE_OUTPUT; + case NATIVE_HEADER_OUTPUT: + return NATIVE_HEADER_OUTPUT; + } + } + return null; + } + } + + private final Location location; + private final String path; + + public GeneratedResource(Location location, CharSequence pkg, CharSequence relativeName) { + this(location, pkg.length() == 0 ? relativeName.toString() : pkg.toString().replace('.', '/') + '/' + relativeName); + } + + public GeneratedResource(Location location, String path) { + this.location = location; + this.path = path; + } + + public Location getLocation() { + return location; + } + + public String getPath() { + return path; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + GeneratedResource that = (GeneratedResource) o; + return location == that.location && + path.equals(that.path); + } + + @Override + public int hashCode() { + return Objects.hashCode(location, path); + } + + @Override + public String toString() { + return path + " in " + location; + } +} diff --git a/subprojects/language-java/src/main/java/org/gradle/api/internal/tasks/compile/incremental/processing/GeneratedResourceSerializer.java b/subprojects/language-java/src/main/java/org/gradle/api/internal/tasks/compile/incremental/processing/GeneratedResourceSerializer.java new file mode 100644 index 0000000000000..da3ec093b9e86 --- /dev/null +++ b/subprojects/language-java/src/main/java/org/gradle/api/internal/tasks/compile/incremental/processing/GeneratedResourceSerializer.java @@ -0,0 +1,45 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.api.internal.tasks.compile.incremental.processing; + +import org.gradle.internal.serialize.AbstractSerializer; +import org.gradle.internal.serialize.BaseSerializerFactory; +import org.gradle.internal.serialize.Decoder; +import org.gradle.internal.serialize.Encoder; +import org.gradle.internal.serialize.Serializer; + +import java.io.EOFException; + +public class GeneratedResourceSerializer extends AbstractSerializer { + private static final Serializer LOCATION_SERIALIZER = new BaseSerializerFactory().getSerializerFor(GeneratedResource.Location.class); + private final Serializer stringSerializer; + + public GeneratedResourceSerializer(Serializer stringSerializer) { + this.stringSerializer = stringSerializer; + } + + @Override + public GeneratedResource read(Decoder decoder) throws EOFException, Exception { + return new GeneratedResource(LOCATION_SERIALIZER.read(decoder), stringSerializer.read(decoder)); + } + + @Override + public void write(Encoder encoder, GeneratedResource value) throws Exception { + LOCATION_SERIALIZER.write(encoder, value.getLocation()); + stringSerializer.write(encoder, value.getPath()); + } +} diff --git a/subprojects/language-java/src/main/java/org/gradle/api/internal/tasks/compile/incremental/recomp/ClasspathChangeDependentsFinder.java b/subprojects/language-java/src/main/java/org/gradle/api/internal/tasks/compile/incremental/recomp/ClasspathChangeDependentsFinder.java index 5e307fc2520c2..dc5e8d3f0be50 100644 --- a/subprojects/language-java/src/main/java/org/gradle/api/internal/tasks/compile/incremental/recomp/ClasspathChangeDependentsFinder.java +++ b/subprojects/language-java/src/main/java/org/gradle/api/internal/tasks/compile/incremental/recomp/ClasspathChangeDependentsFinder.java @@ -112,7 +112,7 @@ private DependentsSet collectDependentsFromClasspath(Set modified) { } } } - return DependentsSet.dependents(dependentClasses); + return DependentsSet.dependentClasses(dependentClasses); } private DependentsSet collectDependentsFromClasspathEntry(String dependentClass, File entry) { diff --git a/subprojects/language-java/src/main/java/org/gradle/api/internal/tasks/compile/incremental/recomp/ClasspathEntryChangeProcessor.java b/subprojects/language-java/src/main/java/org/gradle/api/internal/tasks/compile/incremental/recomp/ClasspathEntryChangeProcessor.java index 929a66601d282..79ae0642fb55d 100644 --- a/subprojects/language-java/src/main/java/org/gradle/api/internal/tasks/compile/incremental/recomp/ClasspathEntryChangeProcessor.java +++ b/subprojects/language-java/src/main/java/org/gradle/api/internal/tasks/compile/incremental/recomp/ClasspathEntryChangeProcessor.java @@ -35,5 +35,6 @@ public void processChange(InputFileDetails input, RecompilationSpec spec) { return; } spec.getClassesToCompile().addAll(actualDependents.getDependentClasses()); + spec.getResourcesToGenerate().addAll(actualDependents.getDependentResources()); } } diff --git a/subprojects/language-java/src/main/java/org/gradle/api/internal/tasks/compile/incremental/recomp/JavaChangeProcessor.java b/subprojects/language-java/src/main/java/org/gradle/api/internal/tasks/compile/incremental/recomp/JavaChangeProcessor.java index f74df2bdd9526..5d5f4e990aaab 100644 --- a/subprojects/language-java/src/main/java/org/gradle/api/internal/tasks/compile/incremental/recomp/JavaChangeProcessor.java +++ b/subprojects/language-java/src/main/java/org/gradle/api/internal/tasks/compile/incremental/recomp/JavaChangeProcessor.java @@ -39,5 +39,6 @@ public void processChange(InputFileDetails input, RecompilationSpec spec) { return; } spec.getClassesToCompile().addAll(actualDependents.getDependentClasses()); + spec.getResourcesToGenerate().addAll(actualDependents.getDependentResources()); } } diff --git a/subprojects/language-java/src/main/java/org/gradle/api/internal/tasks/compile/incremental/recomp/RecompilationSpec.java b/subprojects/language-java/src/main/java/org/gradle/api/internal/tasks/compile/incremental/recomp/RecompilationSpec.java index abc22d7b348a5..56617e8c1ea4c 100644 --- a/subprojects/language-java/src/main/java/org/gradle/api/internal/tasks/compile/incremental/recomp/RecompilationSpec.java +++ b/subprojects/language-java/src/main/java/org/gradle/api/internal/tasks/compile/incremental/recomp/RecompilationSpec.java @@ -16,6 +16,8 @@ package org.gradle.api.internal.tasks.compile.incremental.recomp; +import org.gradle.api.internal.tasks.compile.incremental.processing.GeneratedResource; + import java.io.File; import java.util.Collection; import java.util.LinkedHashSet; @@ -24,6 +26,7 @@ public class RecompilationSpec { private final Collection classesToCompile = new NormalizingClassNamesSet(); private final Collection classesToProcess = new NormalizingClassNamesSet(); + private final Collection resourcesToGenerate = new LinkedHashSet(); private String fullRebuildCause; public Collection getClassesToCompile() { @@ -34,6 +37,10 @@ public Collection getClassesToProcess() { return classesToProcess; } + public Collection getResourcesToGenerate() { + return resourcesToGenerate; + } + public boolean isBuildNeeded() { return isFullRebuildNeeded() || !classesToCompile.isEmpty() || !classesToProcess.isEmpty(); } diff --git a/subprojects/language-java/src/main/java/org/gradle/api/internal/tasks/compile/processing/AggregatingProcessingStrategy.java b/subprojects/language-java/src/main/java/org/gradle/api/internal/tasks/compile/processing/AggregatingProcessingStrategy.java index 3c7eba69777ee..60cb3a55465f9 100644 --- a/subprojects/language-java/src/main/java/org/gradle/api/internal/tasks/compile/processing/AggregatingProcessingStrategy.java +++ b/subprojects/language-java/src/main/java/org/gradle/api/internal/tasks/compile/processing/AggregatingProcessingStrategy.java @@ -17,10 +17,12 @@ package org.gradle.api.internal.tasks.compile.processing; import org.gradle.api.internal.tasks.compile.incremental.processing.AnnotationProcessorResult; +import org.gradle.api.internal.tasks.compile.incremental.processing.GeneratedResource; import javax.annotation.processing.RoundEnvironment; import javax.lang.model.element.Element; import javax.lang.model.element.TypeElement; +import javax.tools.JavaFileManager; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.Set; @@ -67,4 +69,14 @@ private void recordAggregatedTypes(Set supportedAnnotationTypes, Set supportedAnnotationTypes, Set originatingTypes = ElementUtils.getTopLevelTypeNames(originatingElements); + int size = originatingTypes.size(); + if (size != 1) { + result.setFullRebuildCause("the generated resource '" + generatedResource + "' must have exactly one originating element, but had " + size); + } + result.addGeneratedResource(generatedResource, originatingTypes); + } } diff --git a/subprojects/language-java/src/main/java/org/gradle/api/internal/tasks/compile/processing/NonIncrementalProcessingStrategy.java b/subprojects/language-java/src/main/java/org/gradle/api/internal/tasks/compile/processing/NonIncrementalProcessingStrategy.java index 0dd437771ca36..f4c920bf4a929 100644 --- a/subprojects/language-java/src/main/java/org/gradle/api/internal/tasks/compile/processing/NonIncrementalProcessingStrategy.java +++ b/subprojects/language-java/src/main/java/org/gradle/api/internal/tasks/compile/processing/NonIncrementalProcessingStrategy.java @@ -21,6 +21,7 @@ import javax.annotation.processing.RoundEnvironment; import javax.lang.model.element.Element; import javax.lang.model.element.TypeElement; +import javax.tools.JavaFileManager; import java.util.Set; import static org.gradle.api.internal.tasks.compile.incremental.processing.IncrementalAnnotationProcessorType.UNKNOWN; @@ -47,4 +48,9 @@ public void recordProcessingInputs(Set supportedAnnotationTypes, Set dependentClasses) { - dependencyToAll ? DependentsSet.dependencyToAll() : dependents(dependentClasses as Set) + private static DependentsSet dependentSet(boolean dependencyToAll, Collection classes) { + dependencyToAll ? DependentsSet.dependencyToAll() : dependentClasses(classes as Set) } } diff --git a/subprojects/language-java/src/test/groovy/org/gradle/api/internal/tasks/compile/processing/AggregatingFilerTest.groovy b/subprojects/language-java/src/test/groovy/org/gradle/api/internal/tasks/compile/processing/AggregatingFilerTest.groovy index 77acb4c672ff9..f3dbb6fb99c9c 100644 --- a/subprojects/language-java/src/test/groovy/org/gradle/api/internal/tasks/compile/processing/AggregatingFilerTest.groovy +++ b/subprojects/language-java/src/test/groovy/org/gradle/api/internal/tasks/compile/processing/AggregatingFilerTest.groovy @@ -17,6 +17,9 @@ package org.gradle.api.internal.tasks.compile.processing import org.gradle.api.internal.tasks.compile.incremental.processing.AnnotationProcessorResult +import org.gradle.api.internal.tasks.compile.incremental.processing.GeneratedResource + +import javax.tools.StandardLocation class AggregatingFilerTest extends IncrementalFilerTest { @@ -28,6 +31,7 @@ class AggregatingFilerTest extends IncrementalFilerTest { def "can have zero originating elements"() { when: filer.createSourceFile("Foo") + filer.createResource(StandardLocation.SOURCE_OUTPUT, "", "foo.txt") then: !result.fullRebuildCause @@ -36,6 +40,7 @@ class AggregatingFilerTest extends IncrementalFilerTest { def "can have many originating elements"() { when: filer.createSourceFile("Foo", type("Bar"), type("Baz")) + filer.createResource(StandardLocation.SOURCE_OUTPUT, "", "foo.txt", type("Bar"), type("Baz")) then: !result.fullRebuildCause @@ -46,8 +51,39 @@ class AggregatingFilerTest extends IncrementalFilerTest { filer.createSourceFile("Foo", pkg("pkg"), type("A"), methodInside("B")) filer.createSourceFile("Bar", type("B")) + filer.createResource(StandardLocation.SOURCE_OUTPUT, "", "foo.txt", pkg("pkg"), type("A"), methodInside("B")) + filer.createResource(StandardLocation.SOURCE_OUTPUT, "", "bar.txt", type("B")) + then: result.generatedTypesWithIsolatedOrigin.isEmpty() result.generatedAggregatingTypes == ["Foo", "Bar"] as Set + + result.generatedResourcesWithIsolatedOrigin.isEmpty() + result.generatedAggregatingResources == [sourceResource("foo.txt"), sourceResource("bar.txt")] as Set + } + + def "handles resources in the three StandardLocation output locations"() { + when: + filer.createResource(inputLocation, "com.enterprise.software", "foo.txt", type("A")) + + then: + result.generatedAggregatingResources == [new GeneratedResource(resultLocation, "com/enterprise/software/foo.txt")] as Set + + where: + inputLocation | resultLocation + StandardLocation.SOURCE_OUTPUT | GeneratedResource.Location.SOURCE_OUTPUT + StandardLocation.CLASS_OUTPUT | GeneratedResource.Location.CLASS_OUTPUT + StandardLocation.NATIVE_HEADER_OUTPUT | GeneratedResource.Location.NATIVE_HEADER_OUTPUT + } + + def "resources with same path but different location are distinct"() { + when: + filer.createResource(StandardLocation.SOURCE_OUTPUT, "com.enterprise.software", "foo.txt", type("A")) + filer.createResource(StandardLocation.CLASS_OUTPUT, "com.enterprise.software", "foo.txt", type("A")) + filer.createResource(StandardLocation.NATIVE_HEADER_OUTPUT, "com.enterprise.software", "foo.txt", type("A")) + + then: + result.generatedAggregatingResources == [GeneratedResource.Location.SOURCE_OUTPUT, GeneratedResource.Location.CLASS_OUTPUT, GeneratedResource.Location.NATIVE_HEADER_OUTPUT] + .collect { new GeneratedResource(it, "com/enterprise/software/foo.txt") } as Set } } diff --git a/subprojects/language-java/src/test/groovy/org/gradle/api/internal/tasks/compile/processing/IncrementalFilerTest.groovy b/subprojects/language-java/src/test/groovy/org/gradle/api/internal/tasks/compile/processing/IncrementalFilerTest.groovy index fab4004d2e518..b7b3397e5e99f 100644 --- a/subprojects/language-java/src/test/groovy/org/gradle/api/internal/tasks/compile/processing/IncrementalFilerTest.groovy +++ b/subprojects/language-java/src/test/groovy/org/gradle/api/internal/tasks/compile/processing/IncrementalFilerTest.groovy @@ -18,6 +18,7 @@ package org.gradle.api.internal.tasks.compile.processing import org.gradle.api.internal.tasks.compile.incremental.processing.AnnotationProcessingResult import org.gradle.api.internal.tasks.compile.incremental.processing.AnnotationProcessorResult +import org.gradle.api.internal.tasks.compile.incremental.processing.GeneratedResource import spock.lang.Specification import javax.annotation.processing.Filer @@ -25,7 +26,6 @@ import javax.lang.model.element.ExecutableElement import javax.lang.model.element.Name import javax.lang.model.element.PackageElement import javax.lang.model.element.TypeElement -import javax.tools.StandardLocation abstract class IncrementalFilerTest extends Specification { Filer delegate = Stub(Filer) @@ -38,14 +38,6 @@ abstract class IncrementalFilerTest extends Specification { abstract IncrementalProcessingStrategy getStrategy(AnnotationProcessorResult result) - def "does a full rebuild when trying to write resources"() { - when: - filer.createResource(StandardLocation.SOURCE_OUTPUT, "", "foo.txt") - - then: - result.fullRebuildCause == "an annotation processor generated a resource" - } - PackageElement pkg(String packageName) { Stub(PackageElement) { getQualifiedName() >> Stub(Name) { @@ -69,4 +61,8 @@ abstract class IncrementalFilerTest extends Specification { getEnclosingElement() >> type(typeName) } } + + GeneratedResource sourceResource(String path) { + new GeneratedResource(GeneratedResource.Location.SOURCE_OUTPUT, path) + } } diff --git a/subprojects/language-java/src/test/groovy/org/gradle/api/internal/tasks/compile/processing/IsolatingFilerTest.groovy b/subprojects/language-java/src/test/groovy/org/gradle/api/internal/tasks/compile/processing/IsolatingFilerTest.groovy index 5ce16bfe2cae0..6c1bef760abda 100644 --- a/subprojects/language-java/src/test/groovy/org/gradle/api/internal/tasks/compile/processing/IsolatingFilerTest.groovy +++ b/subprojects/language-java/src/test/groovy/org/gradle/api/internal/tasks/compile/processing/IsolatingFilerTest.groovy @@ -17,6 +17,9 @@ package org.gradle.api.internal.tasks.compile.processing import org.gradle.api.internal.tasks.compile.incremental.processing.AnnotationProcessorResult +import org.gradle.api.internal.tasks.compile.incremental.processing.GeneratedResource + +import javax.tools.StandardLocation class IsolatingFilerTest extends IncrementalFilerTest { @@ -25,7 +28,7 @@ class IsolatingFilerTest extends IncrementalFilerTest { new IsolatingProcessingStrategy(result) } - def "does a full rebuild when no originating elements are given"() { + def "does a full rebuild when no originating elements are given for a type"() { when: filer.createSourceFile("Foo") @@ -33,7 +36,15 @@ class IsolatingFilerTest extends IncrementalFilerTest { result.fullRebuildCause == "the generated type 'Foo' must have exactly one originating element, but had 0" } - def "does a full rebuild when too many originating elements are given"() { + def "does a full rebuild when no originating elements are given for a resource"() { + when: + filer.createResource(StandardLocation.SOURCE_OUTPUT, "", "foo.txt") + + then: + result.fullRebuildCause == "the generated resource 'foo.txt in SOURCE_OUTPUT' must have exactly one originating element, but had 0" + } + + def "does a full rebuild when too many originating elements are given for a type"() { when: filer.createSourceFile("Foo", type("Bar"), type("Baz")) @@ -41,9 +52,18 @@ class IsolatingFilerTest extends IncrementalFilerTest { result.fullRebuildCause == "the generated type 'Foo' must have exactly one originating element, but had 2" } - def "can have multiple originating elements coming from the same tpye"() { + def "does a full rebuild when too many originating elements are given for a resource"() { + when: + filer.createResource(StandardLocation.SOURCE_OUTPUT, "", "foo.txt", type("Bar"), type("Baz")) + + then: + result.fullRebuildCause == "the generated resource 'foo.txt in SOURCE_OUTPUT' must have exactly one originating element, but had 2" + } + + def "can have multiple originating elements coming from the same type"() { when: filer.createSourceFile("Foo", methodInside("Bar"), methodInside("Bar")) + filer.createResource(StandardLocation.SOURCE_OUTPUT, "", "foo.txt", methodInside("Bar"), methodInside("Bar")) then: !result.fullRebuildCause @@ -52,10 +72,13 @@ class IsolatingFilerTest extends IncrementalFilerTest { def "packages are valid originating elements"() { when: filer.createSourceFile("Foo", pkg("fizz")) + filer.createResource(StandardLocation.SOURCE_OUTPUT, "", "foo.txt", pkg("fizz")) then: result.generatedTypesWithIsolatedOrigin.size() == 1 result.generatedTypesWithIsolatedOrigin["fizz.package-info"] == ["Foo"] as Set + result.generatedResourcesWithIsolatedOrigin.size() == 1 + result.generatedResourcesWithIsolatedOrigin["fizz.package-info"] == [sourceResource("foo.txt")] as Set } def "adds originating types to the processing result"() { @@ -63,10 +86,34 @@ class IsolatingFilerTest extends IncrementalFilerTest { filer.createSourceFile("Foo", pkg("pkg"), type("A"), methodInside("B")) filer.createSourceFile("Bar", type("B")) + filer.createResource(StandardLocation.SOURCE_OUTPUT, "", "foo.txt", pkg("pkg"), type("A"), methodInside("B")) + filer.createResource(StandardLocation.SOURCE_OUTPUT, "", "bar.txt", type("B")) + then: result.generatedTypesWithIsolatedOrigin.size() == 3 result.generatedTypesWithIsolatedOrigin["A"] == ["Foo"] as Set result.generatedTypesWithIsolatedOrigin["pkg.package-info"] == ["Foo"] as Set result.generatedTypesWithIsolatedOrigin["B"] == ["Foo", "Bar"] as Set + + def foo = sourceResource("foo.txt") + def bar = sourceResource("bar.txt") + result.generatedResourcesWithIsolatedOrigin.size() == 3 + result.generatedResourcesWithIsolatedOrigin["A"] == [foo] as Set + result.generatedResourcesWithIsolatedOrigin["pkg.package-info"] == [foo] as Set + result.generatedResourcesWithIsolatedOrigin["B"] == [foo, bar] as Set + } + + def "handles resources in the three StandardLocation output locations"() { + when: + filer.createResource(inputLocation, "", "foo.txt", type("A")) + + then: + result.generatedResourcesWithIsolatedOrigin["A"] == [new GeneratedResource(resultLocation, "foo.txt")] as Set + + where: + inputLocation | resultLocation + StandardLocation.SOURCE_OUTPUT | GeneratedResource.Location.SOURCE_OUTPUT + StandardLocation.CLASS_OUTPUT | GeneratedResource.Location.CLASS_OUTPUT + StandardLocation.NATIVE_HEADER_OUTPUT | GeneratedResource.Location.NATIVE_HEADER_OUTPUT } } diff --git a/subprojects/language-java/src/testFixtures/groovy/org/gradle/language/fixtures/AnnotationProcessorFixture.groovy b/subprojects/language-java/src/testFixtures/groovy/org/gradle/language/fixtures/AnnotationProcessorFixture.groovy index c652d305a0b3b..6165cb67790b5 100644 --- a/subprojects/language-java/src/testFixtures/groovy/org/gradle/language/fixtures/AnnotationProcessorFixture.groovy +++ b/subprojects/language-java/src/testFixtures/groovy/org/gradle/language/fixtures/AnnotationProcessorFixture.groovy @@ -65,7 +65,9 @@ abstract class AnnotationProcessorFixture { import javax.lang.model.element.*; import javax.lang.model.util.*; import javax.tools.*; - + + import static javax.tools.StandardLocation.*; + @SupportedOptions({ "message" }) public class ${annotationName}Processor extends AbstractProcessor { private Map options; diff --git a/subprojects/language-java/src/testFixtures/groovy/org/gradle/language/fixtures/HelperProcessorFixture.groovy b/subprojects/language-java/src/testFixtures/groovy/org/gradle/language/fixtures/HelperProcessorFixture.groovy index e53cf0a50a03d..f0cdc4b7dac06 100644 --- a/subprojects/language-java/src/testFixtures/groovy/org/gradle/language/fixtures/HelperProcessorFixture.groovy +++ b/subprojects/language-java/src/testFixtures/groovy/org/gradle/language/fixtures/HelperProcessorFixture.groovy @@ -20,6 +20,8 @@ import groovy.transform.CompileStatic import org.gradle.api.internal.tasks.compile.incremental.processing.IncrementalAnnotationProcessorType import org.gradle.test.fixtures.file.TestFile +import javax.tools.StandardLocation + /** * Generates a "Helper" class for each annotated type. The helper has a "getValue()" method that returns * a greeting. The greeting is composed of a message and a suffix. The message is compiled into a support @@ -29,6 +31,8 @@ import org.gradle.test.fixtures.file.TestFile @CompileStatic class HelperProcessorFixture extends AnnotationProcessorFixture { String message = "greetings" + boolean writeResources + String resourceLocation = StandardLocation.CLASS_OUTPUT.toString() private String suffix = "" HelperProcessorFixture() { @@ -51,7 +55,7 @@ class HelperProcessorFixture extends AnnotationProcessorFixture { } String getGeneratorCode() { - """ + def baseCode = """ for (Element element : elements) { TypeElement typeElement = (TypeElement) element; String className = typeElement.getSimpleName().toString() + "Helper"; @@ -75,8 +79,28 @@ for (Element element : elements) { } catch (IOException e) { messager.printMessage(Diagnostic.Kind.ERROR, "Failed to generate source file " + className, element); } -} """ + def resourceCode = writeResources ? """ + try { + FileObject resourceFile = filer.createResource($resourceLocation, \"\", className + \"Resource.txt\", element); + Writer writer = resourceFile.openWriter(); + try { + String messageFromOptions = options.get("message"); + if (messageFromOptions == null) { + writer.write(HelperUtil.getValue() + "${suffix}"); + } else { + writer.write(messageFromOptions); + } + } finally { + writer.close(); + } + } catch (Exception e) { + messager.printMessage(Diagnostic.Kind.ERROR, "Failed to write resource file .txt"); + } +} +""" : "}" + + return baseCode + resourceCode } @Override diff --git a/subprojects/language-java/src/testFixtures/groovy/org/gradle/language/fixtures/NonIncrementalProcessorFixture.groovy b/subprojects/language-java/src/testFixtures/groovy/org/gradle/language/fixtures/NonIncrementalProcessorFixture.groovy index ba9e5893a6260..4c2ff69deb491 100644 --- a/subprojects/language-java/src/testFixtures/groovy/org/gradle/language/fixtures/NonIncrementalProcessorFixture.groovy +++ b/subprojects/language-java/src/testFixtures/groovy/org/gradle/language/fixtures/NonIncrementalProcessorFixture.groovy @@ -22,8 +22,6 @@ import groovy.transform.CompileStatic * An annotation processor which does all the things that we don't support for * incremental compilation: * - * - reading resources - * - writing resources * - generating files without originating elements * * Useful for testing error reporting. @@ -32,8 +30,6 @@ import groovy.transform.CompileStatic class NonIncrementalProcessorFixture extends AnnotationProcessorFixture { private boolean providesNoOriginatingElements - private boolean readsResources - private boolean writesResources NonIncrementalProcessorFixture() { super("Thing") @@ -44,16 +40,6 @@ class NonIncrementalProcessorFixture extends AnnotationProcessorFixture { this } - NonIncrementalProcessorFixture readingResources() { - readsResources = true - this - } - - NonIncrementalProcessorFixture writingResources() { - writesResources = true - this - } - String getGeneratorCode() { """ for (Element element : elements) { @@ -74,12 +60,6 @@ for (Element element : elements) { } catch (IOException e) { messager.printMessage(Diagnostic.Kind.ERROR, "Failed to generate source file " + className); } - try { - ${readsResources ? 'filer.getResource(StandardLocation.SOURCE_OUTPUT, "", "thing.txt");' : ""} - ${writesResources ? 'filer.createResource(StandardLocation.SOURCE_OUTPUT, "", "thing.txt");' : ""} - } catch (Exception e) { - messager.printMessage(Diagnostic.Kind.ERROR, "Failed to generate resource file thing.txt"); - } } """ } diff --git a/subprojects/language-java/src/testFixtures/groovy/org/gradle/language/fixtures/ResourceGeneratingProcessorFixture.groovy b/subprojects/language-java/src/testFixtures/groovy/org/gradle/language/fixtures/ResourceGeneratingProcessorFixture.groovy new file mode 100644 index 0000000000000..baaca5f2dfa91 --- /dev/null +++ b/subprojects/language-java/src/testFixtures/groovy/org/gradle/language/fixtures/ResourceGeneratingProcessorFixture.groovy @@ -0,0 +1,75 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.language.fixtures + +import groovy.transform.CompileStatic + +import javax.tools.StandardLocation + +/** + * An annotation processor that exclusively generates resources. Like {@link NonIncrementalProcessorFixture}, can be configured to trigger error cases. + */ +@CompileStatic +class ResourceGeneratingProcessorFixture extends AnnotationProcessorFixture { + private boolean providesNoOriginatingElements + private List outputLocations = [StandardLocation.SOURCE_OUTPUT.toString()] + + ResourceGeneratingProcessorFixture() { + super("Thing") + } + + ResourceGeneratingProcessorFixture providingNoOriginatingElements() { + providesNoOriginatingElements = true + this + } + + ResourceGeneratingProcessorFixture withOutputLocations(String... locations) { + outputLocations = Arrays.asList(locations) + this + } + + ResourceGeneratingProcessorFixture withOutputLocations(List locations) { + outputLocations = locations + this + } + + String getGeneratorCode() { + def outputs = outputLocations.collect { """ + resourceFile = filer.createResource($it, \"\", resourceName${providesNoOriginatingElements ? '' : ', element'}); + writer = resourceFile.openWriter(); + try { + writer.write("We did it."); + } finally { + writer.close(); + } +""" }.join("\n ") + + """ +for (Element element : elements) { + TypeElement typeElement = (TypeElement) element; + String resourceName = typeElement.getSimpleName().toString() + ".txt"; + FileObject resourceFile; + Writer writer; + try { + $outputs + } catch (Exception e) { + messager.printMessage(Diagnostic.Kind.ERROR, "Failed to generate resource file " + resourceName + ": " + e.getMessage()); + } +} +""" + } +} diff --git a/subprojects/language-java/src/testFixtures/groovy/org/gradle/language/fixtures/ServiceRegistryProcessorFixture.groovy b/subprojects/language-java/src/testFixtures/groovy/org/gradle/language/fixtures/ServiceRegistryProcessorFixture.groovy index 82d0319ef7450..de6c9b575e6c2 100644 --- a/subprojects/language-java/src/testFixtures/groovy/org/gradle/language/fixtures/ServiceRegistryProcessorFixture.groovy +++ b/subprojects/language-java/src/testFixtures/groovy/org/gradle/language/fixtures/ServiceRegistryProcessorFixture.groovy @@ -19,6 +19,8 @@ package org.gradle.language.fixtures import groovy.transform.CompileStatic import org.gradle.api.internal.tasks.compile.incremental.processing.IncrementalAnnotationProcessorType +import javax.tools.StandardLocation + /** * A processor that collects all types annotated with the @Service annotation * and generates a single ServiceRegistry class from them. The registry has @@ -27,6 +29,8 @@ import org.gradle.api.internal.tasks.compile.incremental.processing.IncrementalA */ @CompileStatic class ServiceRegistryProcessorFixture extends AnnotationProcessorFixture { + boolean writeResources + String resourceLocation = StandardLocation.CLASS_OUTPUT.toString() ServiceRegistryProcessorFixture() { super("Service") @@ -34,7 +38,7 @@ class ServiceRegistryProcessorFixture extends AnnotationProcessorFixture { } String getGeneratorCode() { - """ + def baseCode = """ String className = "ServiceRegistry"; try { JavaFileObject sourceFile = filer.createSourceFile(className, elements.toArray(new Element[0])); @@ -56,5 +60,25 @@ try { messager.printMessage(Diagnostic.Kind.ERROR, "Failed to generate source file " + className); } """ + def resourceCode = writeResources ? """ + try { + FileObject resourceFile = filer.createResource($resourceLocation, \"\", className + \"Resource.txt\", elements.toArray(new Element[0])); + Writer writer = resourceFile.openWriter(); + try { + for (Element element : elements) { + TypeElement typeElement = (TypeElement) element; + String name = typeElement.getQualifiedName().toString(); + writer.write(name); + writer.write('\\n'); + } + } finally { + writer.close(); + } + } catch (Exception e) { + messager.printMessage(Diagnostic.Kind.ERROR, "Failed to write resource file .txt"); + } +""" : "" + + return baseCode + resourceCode } } From 9e95f3c1e1b692099f5a5e9756bdba49d9a24810 Mon Sep 17 00:00:00 2001 From: Stefan Oehme Date: Mon, 25 Mar 2019 14:46:41 +0100 Subject: [PATCH 707/853] Mention Ian Kerins in the release notes --- subprojects/docs/src/docs/release/notes.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/subprojects/docs/src/docs/release/notes.md b/subprojects/docs/src/docs/release/notes.md index c0612b401bbde..a68d97de76feb 100644 --- a/subprojects/docs/src/docs/release/notes.md +++ b/subprojects/docs/src/docs/release/notes.md @@ -8,6 +8,8 @@ Include only their name, impactful features should be called out separately belo [Some person](https://github.com/some-person) --> +[Ian Kerins](https://github.com/isker) + -[Ian Kerins](https://github.com/isker) +[Ian Kerins](https://github.com/isker), +and [Stefan M.](https://github.com/StefMa). [Ian Kerins](https://github.com/isker), +[Rodolfo Forte](https://github.com/Tschis), and [Stefan M.](https://github.com/StefMa). -[Ian Kerins](https://github.com/isker), -[Rodolfo Forte](https://github.com/Tschis), -and [Stefan M.](https://github.com/StefMa). - -### Using custom local build cache implementations - -Using a custom build cache implementation for the local build cache is now deprecated. -The only allowed type will be `DirectoryBuildCache` going forward. -There is no change in the support for using custom build cache implementations as the remote build cache. - ### Breaking changes diff --git a/subprojects/docs/src/docs/release/release-features.txt b/subprojects/docs/src/docs/release/release-features.txt index fb463396b8d31..e69de29bb2d1d 100644 --- a/subprojects/docs/src/docs/release/release-features.txt +++ b/subprojects/docs/src/docs/release/release-features.txt @@ -1 +0,0 @@ - - JDK12 support From b80170a3a7e7ea09b60fd5136d9a13610dc35a42 Mon Sep 17 00:00:00 2001 From: Daniel Lacasse Date: Fri, 29 Mar 2019 19:12:47 +0100 Subject: [PATCH 834/853] Update library versions in build init to latest for 5.5 --- .../buildinit/tasks/templates/library-versions.properties | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/subprojects/build-init/src/main/resources/org/gradle/buildinit/tasks/templates/library-versions.properties b/subprojects/build-init/src/main/resources/org/gradle/buildinit/tasks/templates/library-versions.properties index 49dfcbd595b2b..b7504b2d24d66 100644 --- a/subprojects/build-init/src/main/resources/org/gradle/buildinit/tasks/templates/library-versions.properties +++ b/subprojects/build-init/src/main/resources/org/gradle/buildinit/tasks/templates/library-versions.properties @@ -1,13 +1,13 @@ #Generated file, please do not edit - Version values used in build-init templates commons-math=3.6.1 groovy=2.5.6 -guava=27.0.1-jre +guava=27.1-jre junit=4.12 kotlin=1.3.21 scala-library=2.12.8 scala-xml=1.1.1 scala=2.12 -scalatest=3.0.5 +scalatest=3.1.0-RC1 slf4j=1.7.26 spock=1.2-groovy-2.5 testng=6.14.3 From c9a2319faecdf8174c30f13d0e3d102393b6518a Mon Sep 17 00:00:00 2001 From: Daniel Lacasse Date: Fri, 29 Mar 2019 19:12:49 +0100 Subject: [PATCH 835/853] Update released version to latest snapshot --- released-versions.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/released-versions.json b/released-versions.json index df51dfa2852fe..340eda80f191b 100644 --- a/released-versions.json +++ b/released-versions.json @@ -1,7 +1,7 @@ { "latestReleaseSnapshot": { - "version": "5.3.1-20190329012514+0000", - "buildTime": "20190329012514+0000" + "version": "5.4-20190329080509+0000", + "buildTime": "20190329080509+0000" }, "latestRc": { "version": "5.3-rc-3", From 89ea0aa47a16cc0b2e741154476d0847a9c4161a Mon Sep 17 00:00:00 2001 From: Daniel Lacasse Date: Mon, 25 Mar 2019 20:09:42 +0100 Subject: [PATCH 836/853] Add support and test coverage for Swift 5 --- ...actXcodeSwiftProjectIntegrationTest.groovy | 8 + ...iftWithXCTestProjectIntegrationTest.groovy | 10 ++ .../AbstractXcodeIntegrationSpec.groovy | 2 +- .../swift/AbstractSwiftIntegrationTest.groovy | 6 + ...wiftIncrementalBuildIntegrationTest.groovy | 18 ++- ...ftIncrementalCompileIntegrationTest.groovy | 21 +++ ...PackageManagerExportIntegrationTest.groovy | 6 + ...agerSwiftBuildExportIntegrationTest.groovy | 4 + .../toolchains/DefaultToolChainSelector.java | 11 +- .../DefaultToolChainSelectorTest.groovy | 5 + ...stractSwiftComponentIntegrationTest.groovy | 149 +++++++++++++++++- ...ativePlatformSamplesIntegrationTest.groovy | 6 + ...BinaryNativePlatformIntegrationTest.groovy | 10 +- .../GeneratedSourcesIntegrationTest.groovy | 2 + ...olChainCustomisationIntegrationTest.groovy | 2 + .../gradle/language/swift/SwiftVersion.java | 9 +- .../gcc/AbstractGccCompatibleToolChain.java | 10 +- .../internal/gcc/GccPlatformToolProvider.java | 2 +- .../metadata/AbstractMetadataProvider.java | 44 +++++- .../metadata/CompilerMetaDataProvider.java | 8 +- .../CompilerMetaDataProviderFactory.java | 18 ++- .../internal/swift/SwiftCompiler.java | 3 +- .../swift/SwiftPlatformToolProvider.java | 5 + .../internal/swift/SwiftcToolChain.java | 3 +- .../CommandLineToolConfigurationInternal.java | 2 +- .../internal/xcode/AbstractLocator.java | 5 + .../AbstractGccCompatibleToolChainTest.groovy | 22 +-- .../gcc/GccPlatformToolProviderTest.groovy | 28 +++- .../metadata/GccMetadataProviderTest.groovy | 6 +- ...CompilerMetaDataProviderFactoryTest.groovy | 22 +-- .../SwiftcMetadataProviderTest.groovy | 4 +- ...ctInstalledToolChainIntegrationSpec.groovy | 1 + .../fixtures/AvailableToolChains.java | 98 ++++++++++-- .../fixtures/NativeBinaryFixture.groovy | 8 +- .../fixtures/ToolChainRequirement.java | 4 + .../nativeplatform/fixtures/app/Swift5.groovy | 60 +++++++ .../fixtures/app/Swift5Test.groovy | 40 +++++ .../app/Swift5WithSwift4XCTest.groovy | 33 ++++ .../fixtures/app/Swift5WithXCTest.groovy | 33 ++++ .../fixtures/app/Swift5XCTest.groovy | 36 +++++ .../app/SwiftCompilerDetectingApp.groovy | 4 +- .../fixtures/binaryinfo/BinaryInfo.java | 5 + .../binaryinfo/OtoolBinaryInfo.groovy | 23 +-- ...SwiftXCTestComponentIntegrationTest.groovy | 7 + ...tWithTestedComponentIntegrationTest.groovy | 15 +- 45 files changed, 722 insertions(+), 96 deletions(-) create mode 100644 subprojects/platform-native/src/testFixtures/groovy/org/gradle/nativeplatform/fixtures/app/Swift5.groovy create mode 100644 subprojects/platform-native/src/testFixtures/groovy/org/gradle/nativeplatform/fixtures/app/Swift5Test.groovy create mode 100644 subprojects/platform-native/src/testFixtures/groovy/org/gradle/nativeplatform/fixtures/app/Swift5WithSwift4XCTest.groovy create mode 100644 subprojects/platform-native/src/testFixtures/groovy/org/gradle/nativeplatform/fixtures/app/Swift5WithXCTest.groovy create mode 100644 subprojects/platform-native/src/testFixtures/groovy/org/gradle/nativeplatform/fixtures/app/Swift5XCTest.groovy diff --git a/subprojects/ide-native/src/integTest/groovy/org/gradle/ide/xcode/AbstractXcodeSwiftProjectIntegrationTest.groovy b/subprojects/ide-native/src/integTest/groovy/org/gradle/ide/xcode/AbstractXcodeSwiftProjectIntegrationTest.groovy index f951c31b302c0..12ce200469143 100644 --- a/subprojects/ide-native/src/integTest/groovy/org/gradle/ide/xcode/AbstractXcodeSwiftProjectIntegrationTest.groovy +++ b/subprojects/ide-native/src/integTest/groovy/org/gradle/ide/xcode/AbstractXcodeSwiftProjectIntegrationTest.groovy @@ -20,6 +20,7 @@ import org.gradle.ide.xcode.fixtures.ProjectFile import org.gradle.language.swift.SwiftVersion import org.gradle.nativeplatform.fixtures.app.Swift3 import org.gradle.nativeplatform.fixtures.app.Swift4 +import org.gradle.nativeplatform.fixtures.app.Swift5 import org.gradle.nativeplatform.fixtures.app.SwiftSourceElement import spock.lang.Unroll @@ -49,6 +50,7 @@ abstract class AbstractXcodeSwiftProjectIntegrationTest extends AbstractXcodeNat fixture | sourceCompatibility swift3Component | SwiftVersion.SWIFT3 swift4Component | SwiftVersion.SWIFT4 + swift5Component | SwiftVersion.SWIFT5 } @Unroll @@ -74,6 +76,7 @@ abstract class AbstractXcodeSwiftProjectIntegrationTest extends AbstractXcodeNat fixture | sourceCompatibility swift3Component | SwiftVersion.SWIFT3 swift4Component | SwiftVersion.SWIFT4 + swift5Component | SwiftVersion.SWIFT5 } @Unroll @@ -102,6 +105,7 @@ abstract class AbstractXcodeSwiftProjectIntegrationTest extends AbstractXcodeNat "null" | null "SwiftVersion.SWIFT3" | "3.0" "SwiftVersion.SWIFT4" | "4.0" + "SwiftVersion.SWIFT5" | "5.0" } SwiftSourceElement getSwift3Component() { @@ -112,6 +116,10 @@ abstract class AbstractXcodeSwiftProjectIntegrationTest extends AbstractXcodeNat return new Swift4(rootProjectName) } + SwiftSourceElement getSwift5Component() { + return new Swift5(rootProjectName); + } + void assertHasSwiftVersion(SwiftVersion expectedSwiftVersion, List targets) { assert !targets.empty targets.each { target -> diff --git a/subprojects/ide-native/src/integTest/groovy/org/gradle/ide/xcode/AbstractXcodeSwiftWithXCTestProjectIntegrationTest.groovy b/subprojects/ide-native/src/integTest/groovy/org/gradle/ide/xcode/AbstractXcodeSwiftWithXCTestProjectIntegrationTest.groovy index 98b933ab51c3d..3aaf070bf609d 100644 --- a/subprojects/ide-native/src/integTest/groovy/org/gradle/ide/xcode/AbstractXcodeSwiftWithXCTestProjectIntegrationTest.groovy +++ b/subprojects/ide-native/src/integTest/groovy/org/gradle/ide/xcode/AbstractXcodeSwiftWithXCTestProjectIntegrationTest.groovy @@ -21,6 +21,8 @@ import org.gradle.nativeplatform.fixtures.app.Swift3WithSwift4XCTest import org.gradle.nativeplatform.fixtures.app.Swift3WithXCTest import org.gradle.nativeplatform.fixtures.app.Swift4WithSwift3XCTest import org.gradle.nativeplatform.fixtures.app.Swift4WithXCTest +import org.gradle.nativeplatform.fixtures.app.Swift5WithSwift4XCTest +import org.gradle.nativeplatform.fixtures.app.Swift5WithXCTest import org.gradle.nativeplatform.fixtures.app.SwiftSourceElement import spock.lang.Unroll @@ -35,6 +37,11 @@ abstract class AbstractXcodeSwiftWithXCTestProjectIntegrationTest extends Abstra return new Swift4WithXCTest(rootProjectName) } + @Override + SwiftSourceElement getSwift5Component() { + return new Swift5WithXCTest(rootProjectName) + } + @Override String getComponentUnderTestDsl() { return "xctest" @@ -65,6 +72,8 @@ abstract class AbstractXcodeSwiftWithXCTestProjectIntegrationTest extends Abstra @Unroll def "honors Swift source compatibility difference on both tested component (#componentSourceCompatibility) and XCTest component (#xctestSourceCompatibility)"() { given: + // TODO: Generating the Xcode files for incompatible source compatibility shouldn't fail the build + // Thus, we should be able to remove the assumption below. assumeSwiftCompilerSupportsLanguageVersion(componentSourceCompatibility) fixture.writeToProject(testDirectory) makeSingleProject() @@ -85,5 +94,6 @@ abstract class AbstractXcodeSwiftWithXCTestProjectIntegrationTest extends Abstra fixture | componentSourceCompatibility | xctestSourceCompatibility new Swift3WithSwift4XCTest(rootProjectName) | SwiftVersion.SWIFT3 | SwiftVersion.SWIFT4 new Swift4WithSwift3XCTest(rootProjectName) | SwiftVersion.SWIFT4 | SwiftVersion.SWIFT3 + new Swift5WithSwift4XCTest(rootProjectName) | SwiftVersion.SWIFT5 | SwiftVersion.SWIFT4 } } diff --git a/subprojects/ide-native/src/integTest/groovy/org/gradle/ide/xcode/fixtures/AbstractXcodeIntegrationSpec.groovy b/subprojects/ide-native/src/integTest/groovy/org/gradle/ide/xcode/fixtures/AbstractXcodeIntegrationSpec.groovy index 2b43f04903c96..4f84c3a7ca7dc 100644 --- a/subprojects/ide-native/src/integTest/groovy/org/gradle/ide/xcode/fixtures/AbstractXcodeIntegrationSpec.groovy +++ b/subprojects/ide-native/src/integTest/groovy/org/gradle/ide/xcode/fixtures/AbstractXcodeIntegrationSpec.groovy @@ -146,7 +146,7 @@ rootProject.name = "${rootProjectName}" // TODO: Use @RequiresInstalledToolChain instead once Xcode test are sorted out void assumeSwiftCompilerSupportsLanguageVersion(SwiftVersion swiftVersion) { assert toolChain != null, "You need to specify Swift tool chain requirement with 'requireSwiftToolChain()'" - assumeTrue(toolChain.version.major >= swiftVersion.version) + assumeTrue((toolChain.version.major == 5 && swiftVersion.version in [5, 4]) || (toolChain.version.major == 4 && swiftVersion.version in [4, 3]) || (toolChain.version.major == 3 && swiftVersion.version == 3)) } void assertTargetIsUnitTest(ProjectFile.PBXTarget target, String expectedProductName) { diff --git a/subprojects/language-native/src/integTest/groovy/org/gradle/language/swift/AbstractSwiftIntegrationTest.groovy b/subprojects/language-native/src/integTest/groovy/org/gradle/language/swift/AbstractSwiftIntegrationTest.groovy index 89bd76e3b8e69..6b5dc81aae060 100644 --- a/subprojects/language-native/src/integTest/groovy/org/gradle/language/swift/AbstractSwiftIntegrationTest.groovy +++ b/subprojects/language-native/src/integTest/groovy/org/gradle/language/swift/AbstractSwiftIntegrationTest.groovy @@ -21,6 +21,7 @@ import org.gradle.nativeplatform.fixtures.ToolChainRequirement import org.gradle.nativeplatform.fixtures.app.SourceElement import org.gradle.nativeplatform.fixtures.app.Swift3 import org.gradle.nativeplatform.fixtures.app.Swift4 +import org.gradle.nativeplatform.fixtures.app.Swift5 import org.gradle.util.Matchers @RequiresInstalledToolChain(ToolChainRequirement.SWIFTC) @@ -121,6 +122,11 @@ abstract class AbstractSwiftIntegrationTest extends AbstractSwiftComponentIntegr return new Swift4('project') } + @Override + SourceElement getSwift5Component() { + return new Swift5('project') + } + @Override String getTaskNameToAssembleDevelopmentBinary() { return "assemble" diff --git a/subprojects/language-native/src/integTest/groovy/org/gradle/language/swift/SwiftIncrementalBuildIntegrationTest.groovy b/subprojects/language-native/src/integTest/groovy/org/gradle/language/swift/SwiftIncrementalBuildIntegrationTest.groovy index 0f4e75fe0541b..a185d20a5e187 100644 --- a/subprojects/language-native/src/integTest/groovy/org/gradle/language/swift/SwiftIncrementalBuildIntegrationTest.groovy +++ b/subprojects/language-native/src/integTest/groovy/org/gradle/language/swift/SwiftIncrementalBuildIntegrationTest.groovy @@ -141,7 +141,14 @@ class SwiftIncrementalBuildIntegrationTest extends AbstractInstalledToolChainInt result.assertTasksNotSkipped(assembleAppTasks) outputs.deletedClasses("multiply", "sum") - outputs.recompiledClasses('greeter', 'renamed-sum', 'main') + + // See https://github.com/gradle/gradle-native/issues/1004 + if (toolchainUnderTest.version.major < 5) { + outputs.recompiledClasses('greeter', 'renamed-sum', 'main') + } else { + outputs.recompiledClasses('renamed-sum') + } + outputDirectory.assertContainsDescendants(expectedIntermediateDescendants(app.alternate)) installation("build/install/main/debug").exec().out == app.expectedAlternateOutput } @@ -169,7 +176,14 @@ class SwiftIncrementalBuildIntegrationTest extends AbstractInstalledToolChainInt result.assertTasksExecuted(assembleLibTasks) result.assertTasksNotSkipped(assembleLibTasks) outputs.deletedClasses("multiply", "sum") - outputs.recompiledClasses('greeter', 'renamed-sum') + + // See https://github.com/gradle/gradle-native/issues/1004 + if (toolchainUnderTest.version.major < 5) { + outputs.recompiledClasses('greeter', 'renamed-sum') + } else { + outputs.recompiledClasses('renamed-sum') + } + outputDirectory.assertContainsDescendants(expectedIntermediateDescendants(lib.alternate)) sharedLibrary("build/lib/main/debug/Hello").assertExists() } diff --git a/subprojects/language-native/src/integTest/groovy/org/gradle/language/swift/SwiftIncrementalCompileIntegrationTest.groovy b/subprojects/language-native/src/integTest/groovy/org/gradle/language/swift/SwiftIncrementalCompileIntegrationTest.groovy index 6154d16e982ca..3b59572bf7c32 100644 --- a/subprojects/language-native/src/integTest/groovy/org/gradle/language/swift/SwiftIncrementalCompileIntegrationTest.groovy +++ b/subprojects/language-native/src/integTest/groovy/org/gradle/language/swift/SwiftIncrementalCompileIntegrationTest.groovy @@ -109,6 +109,7 @@ class SwiftIncrementalCompileIntegrationTest extends AbstractInstalledToolChainI failure.assertHasErrorOutput("error: invalid redeclaration of 'sum(a:b:)'") } + @RequiresInstalledToolChain(ToolChainRequirement.SWIFTC_4_OR_OLDER) def 'removing a file rebuilds everything'() { given: def outputs = new CompilationOutputsFixture(file("build/obj/main/debug"), [ ".o" ]) @@ -128,6 +129,26 @@ class SwiftIncrementalCompileIntegrationTest extends AbstractInstalledToolChainI outputs.deletedClasses("multiply") } + @RequiresInstalledToolChain(ToolChainRequirement.SWIFTC_5) + def 'removing an isolated file does not rebuild anything'() { + given: + def outputs = new CompilationOutputsFixture(file("build/obj/main/debug"), [ ".o" ]) + def app = new SwiftApp() + settingsFile << "rootProject.name = 'app'" + app.writeToProject(testDirectory) + buildFile << """ + apply plugin: 'swift-application' + """ + + outputs.snapshot { succeeds("compileDebugSwift") } + file("src/main/swift/multiply.swift").delete() + + expect: + succeeds("compileDebugSwift") + outputs.recompiledClasses() + outputs.deletedClasses("multiply") + } + def 'changing compiler arguments rebuilds everything'() { given: def outputs = new CompilationOutputsFixture(file("build/obj/main/debug"), [ ".o" ]) diff --git a/subprojects/language-native/src/integTest/groovy/org/gradle/swiftpm/SwiftPackageManagerExportIntegrationTest.groovy b/subprojects/language-native/src/integTest/groovy/org/gradle/swiftpm/SwiftPackageManagerExportIntegrationTest.groovy index bf59eec5dffff..579f9151bf5bd 100644 --- a/subprojects/language-native/src/integTest/groovy/org/gradle/swiftpm/SwiftPackageManagerExportIntegrationTest.groovy +++ b/subprojects/language-native/src/integTest/groovy/org/gradle/swiftpm/SwiftPackageManagerExportIntegrationTest.groovy @@ -16,8 +16,14 @@ package org.gradle.swiftpm + +import spock.lang.Ignore + class SwiftPackageManagerExportIntegrationTest extends AbstractSwiftPackageManagerExportIntegrationTest { + // Swift Package Manager returns an error code when no target are available: + // See https://github.com/gradle/gradle-native/issues/1006 + @Ignore def "produces manifest for build with no native components"() { given: settingsFile << "include 'lib1', 'lib2'" diff --git a/subprojects/language-native/src/integTest/groovy/org/gradle/swiftpm/SwiftPackageManagerSwiftBuildExportIntegrationTest.groovy b/subprojects/language-native/src/integTest/groovy/org/gradle/swiftpm/SwiftPackageManagerSwiftBuildExportIntegrationTest.groovy index 716cbc3ed2e1a..c68a939d1334f 100644 --- a/subprojects/language-native/src/integTest/groovy/org/gradle/swiftpm/SwiftPackageManagerSwiftBuildExportIntegrationTest.groovy +++ b/subprojects/language-native/src/integTest/groovy/org/gradle/swiftpm/SwiftPackageManagerSwiftBuildExportIntegrationTest.groovy @@ -16,6 +16,8 @@ package org.gradle.swiftpm +import org.gradle.nativeplatform.fixtures.RequiresInstalledToolChain +import org.gradle.nativeplatform.fixtures.ToolChainRequirement import org.gradle.nativeplatform.fixtures.app.SwiftAppWithLibraries import org.gradle.nativeplatform.fixtures.app.SwiftLib @@ -187,6 +189,8 @@ let package = Package( swiftPmBuildSucceeds() } + // See https://github.com/gradle/gradle-native/issues/1007 + @RequiresInstalledToolChain(ToolChainRequirement.SWIFTC_4_OR_OLDER) def "produces manifest for Swift component with declared Swift language version"() { given: buildFile << """ diff --git a/subprojects/language-native/src/main/java/org/gradle/language/nativeplatform/internal/toolchains/DefaultToolChainSelector.java b/subprojects/language-native/src/main/java/org/gradle/language/nativeplatform/internal/toolchains/DefaultToolChainSelector.java index b8925e6e54b7f..fca940989b841 100644 --- a/subprojects/language-native/src/main/java/org/gradle/language/nativeplatform/internal/toolchains/DefaultToolChainSelector.java +++ b/subprojects/language-native/src/main/java/org/gradle/language/nativeplatform/internal/toolchains/DefaultToolChainSelector.java @@ -105,13 +105,12 @@ private NativeToolChainInternal getToolChain(NativeLanguage sourceLanguage, Nati } static SwiftVersion toSwiftVersion(VersionNumber swiftCompilerVersion) { - if (swiftCompilerVersion.getMajor() == 3) { - return SwiftVersion.SWIFT3; - } else if (swiftCompilerVersion.getMajor() == 4) { - return SwiftVersion.SWIFT4; - } else { - throw new IllegalArgumentException(String.format("Swift language version is unknown for the specified Swift compiler version (%s)", swiftCompilerVersion.toString())); + for (SwiftVersion version : SwiftVersion.values()) { + if (version.getVersion() == swiftCompilerVersion.getMajor()) { + return version; + } } + throw new IllegalArgumentException(String.format("Swift language version is unknown for the specified Swift compiler version (%s)", swiftCompilerVersion.toString())); } class DefaultResult implements Result { diff --git a/subprojects/language-native/src/test/groovy/org/gradle/language/nativeplatform/internal/toolchains/DefaultToolChainSelectorTest.groovy b/subprojects/language-native/src/test/groovy/org/gradle/language/nativeplatform/internal/toolchains/DefaultToolChainSelectorTest.groovy index 0ebfb5d37f495..7a3f2206717a0 100644 --- a/subprojects/language-native/src/test/groovy/org/gradle/language/nativeplatform/internal/toolchains/DefaultToolChainSelectorTest.groovy +++ b/subprojects/language-native/src/test/groovy/org/gradle/language/nativeplatform/internal/toolchains/DefaultToolChainSelectorTest.groovy @@ -36,6 +36,7 @@ import spock.lang.Unroll import static org.gradle.language.swift.SwiftVersion.SWIFT3 import static org.gradle.language.swift.SwiftVersion.SWIFT4 +import static org.gradle.language.swift.SwiftVersion.SWIFT5 @UsesNativeServices class DefaultToolChainSelectorTest extends Specification { @@ -102,6 +103,10 @@ class DefaultToolChainSelectorTest extends Specification { where: // See https://swift.org/download compilerVersion | languageVersion + '5.0.0' | SWIFT5 + '4.2.3' | SWIFT4 + '4.1.3' | SWIFT4 + '4.1' | SWIFT4 '4.0.3' | SWIFT4 '4.0.2' | SWIFT4 '4.0' | SWIFT4 diff --git a/subprojects/language-native/src/testFixtures/groovy/org/gradle/language/swift/AbstractSwiftComponentIntegrationTest.groovy b/subprojects/language-native/src/testFixtures/groovy/org/gradle/language/swift/AbstractSwiftComponentIntegrationTest.groovy index 4a9939b42c59a..be1ea8d25d2fd 100644 --- a/subprojects/language-native/src/testFixtures/groovy/org/gradle/language/swift/AbstractSwiftComponentIntegrationTest.groovy +++ b/subprojects/language-native/src/testFixtures/groovy/org/gradle/language/swift/AbstractSwiftComponentIntegrationTest.groovy @@ -95,6 +95,34 @@ abstract class AbstractSwiftComponentIntegrationTest extends AbstractNativeLangu result.assertTasksExecuted(tasksToAssembleDevelopmentBinaryOfComponentUnderTest, ":$taskNameToAssembleDevelopmentBinary") } + @RequiresInstalledToolChain(ToolChainRequirement.SWIFTC_5) + def "can build Swift 4 source code on Swift 5 compiler"() { + given: + makeSingleProject() + swift4Component.writeToProject(testDirectory) + buildFile << """ + ${componentUnderTestDsl} { + sourceCompatibility = SwiftVersion.SWIFT4 + } + + task verifyBinariesSwiftVersion { + doLast { + ${componentUnderTestDsl}.binaries.get().each { + assert it.targetPlatform.sourceCompatibility == SwiftVersion.SWIFT4 + } + } + } + """ + settingsFile << "rootProject.name = '${swift4Component.projectName}'" + + when: + succeeds "verifyBinariesSwiftVersion" + succeeds taskNameToAssembleDevelopmentBinary + + then: + result.assertTasksExecuted(tasksToAssembleDevelopmentBinaryOfComponentUnderTest, ":$taskNameToAssembleDevelopmentBinary") + } + @RequiresInstalledToolChain(ToolChainRequirement.SWIFTC_3) def "throws exception with meaningful message when building Swift 4 source code on Swift 3 compiler"() { given: @@ -124,6 +152,93 @@ abstract class AbstractSwiftComponentIntegrationTest extends AbstractNativeLangu failure.assertHasCause("Swift compiler version '${toolChain.version}' doesn't support Swift language version '${SwiftVersion.SWIFT4.version}'") } + @RequiresInstalledToolChain(ToolChainRequirement.SWIFTC_3) + def "throws exception with meaningful message when building Swift 5 source code on Swift 3 compiler"() { + given: + makeSingleProject() + swift5Component.writeToProject(testDirectory) + buildFile << """ + ${componentUnderTestDsl} { + sourceCompatibility = SwiftVersion.SWIFT5 + } + + task verifyBinariesSwiftVersion { + doLast { + ${componentUnderTestDsl}.binaries.get().each { + assert it.targetPlatform.sourceCompatibility == SwiftVersion.SWIFT5 + } + } + } + """ + settingsFile << "rootProject.name = '${swift5Component.projectName}'" + + when: + succeeds "verifyBinariesSwiftVersion" + fails taskNameToAssembleDevelopmentBinary + + then: + failure.assertHasDescription("Execution failed for task '$developmentBinaryCompileTask'.") + failure.assertHasCause("Swift compiler version '${toolChain.version}' doesn't support Swift language version '${SwiftVersion.SWIFT5.version}'") + } + + @RequiresInstalledToolChain(ToolChainRequirement.SWIFTC_4) + def "throws exception with meaningful message when building Swift 5 source code on Swift 4 compiler"() { + given: + makeSingleProject() + swift5Component.writeToProject(testDirectory) + buildFile << """ + ${componentUnderTestDsl} { + sourceCompatibility = SwiftVersion.SWIFT5 + } + + task verifyBinariesSwiftVersion { + doLast { + ${componentUnderTestDsl}.binaries.get().each { + assert it.targetPlatform.sourceCompatibility == SwiftVersion.SWIFT5 + } + } + } + """ + settingsFile << "rootProject.name = '${swift5Component.projectName}'" + + when: + succeeds "verifyBinariesSwiftVersion" + fails taskNameToAssembleDevelopmentBinary + + then: + failure.assertHasDescription("Execution failed for task '$developmentBinaryCompileTask'.") + failure.assertHasCause("Swift compiler version '${toolChain.version}' doesn't support Swift language version '${SwiftVersion.SWIFT5.version}'") + } + + @RequiresInstalledToolChain(ToolChainRequirement.SWIFTC_5) + def "throws exception with meaningful message when building Swift 3 source code on Swift 5 compiler"() { + given: + makeSingleProject() + swift3Component.writeToProject(testDirectory) + buildFile << """ + ${componentUnderTestDsl} { + sourceCompatibility = SwiftVersion.SWIFT3 + } + + task verifyBinariesSwiftVersion { + doLast { + ${componentUnderTestDsl}.binaries.get().each { + assert it.targetPlatform.sourceCompatibility == SwiftVersion.SWIFT3 + } + } + } + """ + settingsFile << "rootProject.name = '${swift3Component.projectName}'" + + when: + succeeds "verifyBinariesSwiftVersion" + fails taskNameToAssembleDevelopmentBinary + + then: + failure.assertHasDescription("Execution failed for task '$developmentBinaryCompileTask'.") + failure.assertHasCause("Swift compiler version '${toolChain.version}' doesn't support Swift language version '${SwiftVersion.SWIFT3.version}'") + } + @RequiresInstalledToolChain(ToolChainRequirement.SWIFTC_3) def "can compile Swift 3 component on Swift 3 compiler"() { given: @@ -172,10 +287,34 @@ abstract class AbstractSwiftComponentIntegrationTest extends AbstractNativeLangu result.assertTasksExecuted(tasksToAssembleDevelopmentBinaryOfComponentUnderTest, ":$taskNameToAssembleDevelopmentBinary") } + @RequiresInstalledToolChain(ToolChainRequirement.SWIFTC_5) + def "can compile Swift 5 component on Swift 5 compiler"() { + given: + makeSingleProject() + swift5Component.writeToProject(testDirectory) + buildFile << """ + task verifyBinariesSwiftVersion { + doLast { + ${componentUnderTestDsl}.binaries.get().each { + assert it.targetPlatform.sourceCompatibility == SwiftVersion.SWIFT5 + } + } + } + """ + settingsFile << "rootProject.name = '${swift5Component.projectName}'" + + when: + succeeds "verifyBinariesSwiftVersion" + succeeds taskNameToAssembleDevelopmentBinary + + then: + result.assertTasksExecuted(tasksToAssembleDevelopmentBinaryOfComponentUnderTest, ":$taskNameToAssembleDevelopmentBinary") + } + def "assemble task warns when current operating system family is excluded"() { given: makeSingleProject() - swift4Component.writeToProject(testDirectory) + componentUnderTest.writeToProject(testDirectory) and: buildFile << configureTargetMachines("machines.os('some-other-family')") @@ -190,7 +329,7 @@ abstract class AbstractSwiftComponentIntegrationTest extends AbstractNativeLangu def "build task warns when current operating system family is excluded"() { given: makeSingleProject() - swift4Component.writeToProject(testDirectory) + componentUnderTest.writeToProject(testDirectory) and: buildFile << configureTargetMachines("machines.os('some-other-family')") @@ -205,7 +344,7 @@ abstract class AbstractSwiftComponentIntegrationTest extends AbstractNativeLangu def "does not fail when current operating system family is excluded but assemble is not invoked"() { given: makeSingleProject() - swift4Component.writeToProject(testDirectory) + componentUnderTest.writeToProject(testDirectory) and: buildFile << configureTargetMachines("machines.os('some-other-family')") @@ -217,7 +356,7 @@ abstract class AbstractSwiftComponentIntegrationTest extends AbstractNativeLangu def "fails configuration when no target machine is configured"() { given: makeSingleProject() - swift4Component.writeToProject(testDirectory) + componentUnderTest.writeToProject(testDirectory) and: buildFile << configureTargetMachines('') @@ -243,6 +382,8 @@ abstract class AbstractSwiftComponentIntegrationTest extends AbstractNativeLangu abstract SourceElement getSwift4Component() + abstract SourceElement getSwift5Component() + abstract List getTasksToAssembleDevelopmentBinaryOfComponentUnderTest() abstract String getComponentName() diff --git a/subprojects/platform-native/src/integTest/groovy/org/gradle/nativeplatform/NativePlatformSamplesIntegrationTest.groovy b/subprojects/platform-native/src/integTest/groovy/org/gradle/nativeplatform/NativePlatformSamplesIntegrationTest.groovy index 2396cb8c5735b..6d8f08998aa8f 100644 --- a/subprojects/platform-native/src/integTest/groovy/org/gradle/nativeplatform/NativePlatformSamplesIntegrationTest.groovy +++ b/subprojects/platform-native/src/integTest/groovy/org/gradle/nativeplatform/NativePlatformSamplesIntegrationTest.groovy @@ -25,6 +25,9 @@ import org.gradle.util.TestPrecondition import org.junit.Rule import static org.gradle.nativeplatform.fixtures.ToolChainRequirement.GCC_COMPATIBLE +import static org.gradle.nativeplatform.fixtures.ToolChainRequirement.SUPPORTS_32 +import static org.gradle.nativeplatform.fixtures.ToolChainRequirement.SUPPORTS_32_AND_64 +import static org.junit.Assume.assumeTrue @Requires(TestPrecondition.CAN_INSTALL_EXECUTABLE) class NativePlatformSamplesIntegrationTest extends AbstractInstalledToolChainIntegrationSpec { @@ -123,6 +126,7 @@ class NativePlatformSamplesIntegrationTest extends AbstractInstalledToolChainInt installation(flavors.dir.file("build/install/main/french")).exec().out == "Bonjour monde!\n" } + @RequiresInstalledToolChain(SUPPORTS_32_AND_64) def variants() { given: sample variants @@ -183,6 +187,8 @@ class NativePlatformSamplesIntegrationTest extends AbstractInstalledToolChainInt @RequiresInstalledToolChain(GCC_COMPATIBLE) def "target platforms"() { + assumeTrue(toolchainUnderTest.meets(SUPPORTS_32)) + given: sample targetPlatforms diff --git a/subprojects/platform-native/src/integTest/groovy/org/gradle/nativeplatform/platform/BinaryNativePlatformIntegrationTest.groovy b/subprojects/platform-native/src/integTest/groovy/org/gradle/nativeplatform/platform/BinaryNativePlatformIntegrationTest.groovy index 5d4e35d839064..c11161bf71073 100755 --- a/subprojects/platform-native/src/integTest/groovy/org/gradle/nativeplatform/platform/BinaryNativePlatformIntegrationTest.groovy +++ b/subprojects/platform-native/src/integTest/groovy/org/gradle/nativeplatform/platform/BinaryNativePlatformIntegrationTest.groovy @@ -19,6 +19,7 @@ import net.rubygrapefruit.platform.Native import net.rubygrapefruit.platform.SystemInfo import org.gradle.internal.os.OperatingSystem import org.gradle.nativeplatform.fixtures.AbstractInstalledToolChainIntegrationSpec +import org.gradle.nativeplatform.fixtures.RequiresInstalledToolChain import org.gradle.nativeplatform.fixtures.ToolChainRequirement import org.gradle.nativeplatform.fixtures.app.PlatformDetectingTestApp import org.gradle.nativeplatform.fixtures.binaryinfo.DumpbinBinaryInfo @@ -31,6 +32,9 @@ import org.gradle.util.TestPrecondition import spock.lang.Issue import spock.lang.Unroll +import static org.gradle.nativeplatform.fixtures.ToolChainRequirement.SUPPORTS_32 +import static org.gradle.nativeplatform.fixtures.ToolChainRequirement.SUPPORTS_32_AND_64 + @Requires(TestPrecondition.NOT_UNKNOWN_OS) class BinaryNativePlatformIntegrationTest extends AbstractInstalledToolChainIntegrationSpec { def testApp = new PlatformDetectingTestApp() @@ -74,6 +78,7 @@ model { binaryInfo(objectFileFor(file("src/main/cpp/main.cpp"), "build/objs/main/mainCpp")).arch.name == arch.name } + @RequiresInstalledToolChain(SUPPORTS_32) def "configure component for a single target platform"() { when: buildFile << """ @@ -131,6 +136,7 @@ model { executable("build/exe/main/main").exec().out == "${arch.altName} ${os.familyName}" * 2 } + @RequiresInstalledToolChain(SUPPORTS_32) def "library with matching platform is enforced by dependency resolution"() { given: testApp.executable.writeSources(file("src/exe")) @@ -202,6 +208,7 @@ model { executable("build/exe/exe/exe").exec().out == "${arch.altName} ${os.familyName}" * 2 } + @RequiresInstalledToolChain(SUPPORTS_32_AND_64) def "build binary for multiple target architectures"() { when: buildFile << """ @@ -249,6 +256,7 @@ model { } } + @RequiresInstalledToolChain(SUPPORTS_32) def "can configure binary for multiple target operating systems"() { String currentOs if (os.windows) { @@ -410,7 +418,7 @@ model { // Only the arch functionality is needed for this test, so fall back to the file utility if nothing else works. file.assertIsFile() if (os.macOsX) { - return new OtoolBinaryInfo(file) + return new OtoolBinaryInfo(file, toolchainUnderTest.runtimeEnv) } if (os.windows) { return DumpbinBinaryInfo.findVisualStudio() ? new DumpbinBinaryInfo(file) : new FileArchOnlyBinaryInfo(file) diff --git a/subprojects/platform-native/src/integTest/groovy/org/gradle/nativeplatform/sourceset/GeneratedSourcesIntegrationTest.groovy b/subprojects/platform-native/src/integTest/groovy/org/gradle/nativeplatform/sourceset/GeneratedSourcesIntegrationTest.groovy index bd3c974b038f6..be2b15e5455ae 100755 --- a/subprojects/platform-native/src/integTest/groovy/org/gradle/nativeplatform/sourceset/GeneratedSourcesIntegrationTest.groovy +++ b/subprojects/platform-native/src/integTest/groovy/org/gradle/nativeplatform/sourceset/GeneratedSourcesIntegrationTest.groovy @@ -25,6 +25,7 @@ import org.gradle.nativeplatform.fixtures.app.CppHelloWorldApp import org.gradle.nativeplatform.fixtures.app.MixedLanguageHelloWorldApp import org.gradle.nativeplatform.fixtures.app.WindowsResourceHelloWorldApp +import static org.gradle.nativeplatform.fixtures.ToolChainRequirement.SUPPORTS_32 import static org.gradle.nativeplatform.fixtures.ToolChainRequirement.VISUALCPP // TODO: Test incremental class GeneratedSourcesIntegrationTest extends AbstractInstalledToolChainIntegrationSpec { @@ -250,6 +251,7 @@ model { executableBuilt(app) } + @RequiresInstalledToolChain(SUPPORTS_32) def "generator task produces assembler sources"() { given: def app = new MixedLanguageHelloWorldApp(AbstractInstalledToolChainIntegrationSpec.toolChain) diff --git a/subprojects/platform-native/src/integTest/groovy/org/gradle/nativeplatform/toolchain/GccToolChainCustomisationIntegrationTest.groovy b/subprojects/platform-native/src/integTest/groovy/org/gradle/nativeplatform/toolchain/GccToolChainCustomisationIntegrationTest.groovy index 574cf1ca2263e..a0cf3829ccba5 100755 --- a/subprojects/platform-native/src/integTest/groovy/org/gradle/nativeplatform/toolchain/GccToolChainCustomisationIntegrationTest.groovy +++ b/subprojects/platform-native/src/integTest/groovy/org/gradle/nativeplatform/toolchain/GccToolChainCustomisationIntegrationTest.groovy @@ -25,6 +25,7 @@ import org.gradle.util.Requires import org.gradle.util.TestPrecondition import static org.gradle.nativeplatform.fixtures.ToolChainRequirement.GCC_COMPATIBLE +import static org.gradle.nativeplatform.fixtures.ToolChainRequirement.SUPPORTS_32 @RequiresInstalledToolChain(GCC_COMPATIBLE) class GccToolChainCustomisationIntegrationTest extends AbstractInstalledToolChainIntegrationSpec { @@ -53,6 +54,7 @@ model { helloWorldApp.library.writeSources(file("src/hello")) } + @RequiresInstalledToolChain(SUPPORTS_32) def "can configure platform specific args"() { when: buildFile << """ diff --git a/subprojects/platform-native/src/main/java/org/gradle/language/swift/SwiftVersion.java b/subprojects/platform-native/src/main/java/org/gradle/language/swift/SwiftVersion.java index d34624964757b..32a30976847ba 100644 --- a/subprojects/platform-native/src/main/java/org/gradle/language/swift/SwiftVersion.java +++ b/subprojects/platform-native/src/main/java/org/gradle/language/swift/SwiftVersion.java @@ -25,7 +25,14 @@ */ @Incubating public enum SwiftVersion { - SWIFT3(3), SWIFT4(4); + SWIFT3(3), SWIFT4(4), + + /** + * Swift 5 major version. + * + * @since 5.4 + */ + SWIFT5(5); private final int version; diff --git a/subprojects/platform-native/src/main/java/org/gradle/nativeplatform/toolchain/internal/gcc/AbstractGccCompatibleToolChain.java b/subprojects/platform-native/src/main/java/org/gradle/nativeplatform/toolchain/internal/gcc/AbstractGccCompatibleToolChain.java index 50abf19fdad33..43c68be40cc01 100644 --- a/subprojects/platform-native/src/main/java/org/gradle/nativeplatform/toolchain/internal/gcc/AbstractGccCompatibleToolChain.java +++ b/subprojects/platform-native/src/main/java/org/gradle/nativeplatform/toolchain/internal/gcc/AbstractGccCompatibleToolChain.java @@ -15,7 +15,6 @@ */ package org.gradle.nativeplatform.toolchain.internal.gcc; -import com.google.common.collect.ImmutableList; import com.google.common.collect.Maps; import org.gradle.api.Action; import org.gradle.api.NonNullApi; @@ -228,7 +227,7 @@ protected void initTools(DefaultGccPlatformToolChain platformToolChain, ToolChai for (GccCommandLineToolConfigurationInternal tool : platformToolChain.getCompilers()) { CommandLineToolSearchResult compiler = locate(tool); if (compiler.isAvailable()) { - SearchResult gccMetadata = getMetaDataProvider().getCompilerMetaData(compiler.getTool(), platformToolChain.getCompilerProbeArgs(), toolSearchPath.getPath()); + SearchResult gccMetadata = getMetaDataProvider().getCompilerMetaData(toolSearchPath.getPath(), spec -> spec.executable(compiler.getTool()).args(platformToolChain.getCompilerProbeArgs())); availability.mustBeAvailable(gccMetadata); if (!gccMetadata.isAvailable()) { return; @@ -350,8 +349,11 @@ public CompilerMetaDataProviderWithDefaultArgs(List compilerProbeArgs, C } @Override - public SearchResult getCompilerMetaData(File binary, List additionalArgs, List searchPath) { - return delegate.getCompilerMetaData(binary, ImmutableList.builder().addAll(compilerProbeArgs).addAll(additionalArgs).build(), searchPath); + public SearchResult getCompilerMetaData(List searchPath, Action configureAction) { + return delegate.getCompilerMetaData(searchPath, execSpec -> { + execSpec.args(compilerProbeArgs); + configureAction.execute(execSpec); + }); } @Override diff --git a/subprojects/platform-native/src/main/java/org/gradle/nativeplatform/toolchain/internal/gcc/GccPlatformToolProvider.java b/subprojects/platform-native/src/main/java/org/gradle/nativeplatform/toolchain/internal/gcc/GccPlatformToolProvider.java index 489241cf33bf1..d614505b9ff40 100644 --- a/subprojects/platform-native/src/main/java/org/gradle/nativeplatform/toolchain/internal/gcc/GccPlatformToolProvider.java +++ b/subprojects/platform-native/src/main/java/org/gradle/nativeplatform/toolchain/internal/gcc/GccPlatformToolProvider.java @@ -228,7 +228,7 @@ private SearchResult getGccMetadata(ToolType compilerType) { CommandLineToolSearchResult searchResult = toolSearchPath.locate(compiler.getToolType(), compiler.getExecutable()); String language = LANGUAGE_FOR_COMPILER.get(compilerType); List languageArgs = language == null ? Collections.emptyList() : ImmutableList.of("-x", language); - return metadataProvider.getCompilerMetaData(searchResult.getTool(), languageArgs, toolSearchPath.getPath()); + return metadataProvider.getCompilerMetaData(toolSearchPath.getPath(), spec -> spec.executable(searchResult.getTool()).args(languageArgs)); } @Override diff --git a/subprojects/platform-native/src/main/java/org/gradle/nativeplatform/toolchain/internal/metadata/AbstractMetadataProvider.java b/subprojects/platform-native/src/main/java/org/gradle/nativeplatform/toolchain/internal/metadata/AbstractMetadataProvider.java index b8a2643f84c69..0e34071ee756f 100644 --- a/subprojects/platform-native/src/main/java/org/gradle/nativeplatform/toolchain/internal/metadata/AbstractMetadataProvider.java +++ b/subprojects/platform-native/src/main/java/org/gradle/nativeplatform/toolchain/internal/metadata/AbstractMetadataProvider.java @@ -18,6 +18,7 @@ import com.google.common.base.Joiner; import com.google.common.collect.ImmutableList; +import org.gradle.api.Action; import org.gradle.internal.Pair; import org.gradle.internal.io.StreamByteBuffer; import org.gradle.platform.base.internal.toolchain.ComponentFound; @@ -28,7 +29,10 @@ import org.gradle.process.internal.ExecActionFactory; import java.io.File; +import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; public abstract class AbstractMetadataProvider implements CompilerMetaDataProvider { private final ExecActionFactory execActionFactory; @@ -38,16 +42,19 @@ public AbstractMetadataProvider(ExecActionFactory execActionFactory) { } @Override - public SearchResult getCompilerMetaData(File binary, List additionalArgs, List path) { - List allArgs = ImmutableList.builder().addAll(additionalArgs).addAll(compilerArgs()).build(); - Pair transform = runCompiler(binary, allArgs); + public SearchResult getCompilerMetaData(List path, Action configureAction) { + DefaultCompilerExecSpec execSpec = new DefaultCompilerExecSpec(); + configureAction.execute(execSpec); + + List allArgs = ImmutableList.builder().addAll(execSpec.args).addAll(compilerArgs()).build(); + Pair transform = runCompiler(execSpec.executable, allArgs, execSpec.environments); if (transform == null) { - return new ComponentNotFound(String.format("Could not determine %s metadata: failed to execute %s %s.", getCompilerType().getDescription(), binary.getName(), Joiner.on(' ').join(allArgs))); + return new ComponentNotFound(String.format("Could not determine %s metadata: failed to execute %s %s.", getCompilerType().getDescription(), execSpec.executable.getName(), Joiner.on(' ').join(allArgs))); } String output = transform.getLeft(); String error = transform.getRight(); try { - return new ComponentFound(parseCompilerOutput(output, error, binary, path)); + return new ComponentFound(parseCompilerOutput(output, error, execSpec.executable, path)); } catch (BrokenResultException e) { return new ComponentNotFound(e.getMessage()); } @@ -59,11 +66,12 @@ protected ExecActionFactory getExecActionFactory() { protected abstract T parseCompilerOutput(String output, String error, File binary, List path) throws BrokenResultException; - private Pair runCompiler(File gccBinary, List args) { + private Pair runCompiler(File gccBinary, List args, Map environmentVariables) { ExecAction exec = execActionFactory.newExecAction(); exec.executable(gccBinary.getAbsolutePath()); exec.setWorkingDir(gccBinary.getParentFile()); exec.args(args); + exec.environment(environmentVariables); StreamByteBuffer buffer = new StreamByteBuffer(); StreamByteBuffer errorBuffer = new StreamByteBuffer(); exec.setStandardOutput(buffer.getOutputStream()); @@ -87,4 +95,28 @@ public BrokenResultException(String message) { } } + public static class DefaultCompilerExecSpec implements CompilerExecSpec { + public final Map environments = new HashMap<>(); + public final List args = new ArrayList<>(); + public File executable; + + @Override + public CompilerExecSpec environment(String key, String value) { + environments.put(key, value); + return this; + } + + @Override + public CompilerExecSpec executable(File executable) { + this.executable = executable; + return this; + } + + @Override + public CompilerExecSpec args(Iterable args) { + this.args.addAll(ImmutableList.copyOf(args)); + return this; + } + } + } diff --git a/subprojects/platform-native/src/main/java/org/gradle/nativeplatform/toolchain/internal/metadata/CompilerMetaDataProvider.java b/subprojects/platform-native/src/main/java/org/gradle/nativeplatform/toolchain/internal/metadata/CompilerMetaDataProvider.java index 6cd90ddb20447..80079719bcf89 100644 --- a/subprojects/platform-native/src/main/java/org/gradle/nativeplatform/toolchain/internal/metadata/CompilerMetaDataProvider.java +++ b/subprojects/platform-native/src/main/java/org/gradle/nativeplatform/toolchain/internal/metadata/CompilerMetaDataProvider.java @@ -16,6 +16,7 @@ package org.gradle.nativeplatform.toolchain.internal.metadata; +import org.gradle.api.Action; import org.gradle.platform.base.internal.toolchain.SearchResult; import java.io.File; @@ -23,8 +24,13 @@ public interface CompilerMetaDataProvider { - SearchResult getCompilerMetaData(File binary, List additionalArgs, List searchPath); + SearchResult getCompilerMetaData(List searchPath, Action configureAction); CompilerType getCompilerType(); + interface CompilerExecSpec { + CompilerExecSpec environment(String key, String value); + CompilerExecSpec executable(File executable); + CompilerExecSpec args(Iterable args); + } } diff --git a/subprojects/platform-native/src/main/java/org/gradle/nativeplatform/toolchain/internal/metadata/CompilerMetaDataProviderFactory.java b/subprojects/platform-native/src/main/java/org/gradle/nativeplatform/toolchain/internal/metadata/CompilerMetaDataProviderFactory.java index ea77e73b42e03..2584fc7ac7b5b 100644 --- a/subprojects/platform-native/src/main/java/org/gradle/nativeplatform/toolchain/internal/metadata/CompilerMetaDataProviderFactory.java +++ b/subprojects/platform-native/src/main/java/org/gradle/nativeplatform/toolchain/internal/metadata/CompilerMetaDataProviderFactory.java @@ -16,6 +16,7 @@ package org.gradle.nativeplatform.toolchain.internal.metadata; +import org.gradle.api.Action; import org.gradle.nativeplatform.toolchain.internal.gcc.metadata.GccMetadata; import org.gradle.nativeplatform.toolchain.internal.gcc.metadata.GccMetadataProvider; import org.gradle.nativeplatform.toolchain.internal.swift.metadata.SwiftcMetadata; @@ -60,11 +61,14 @@ private CachingCompilerMetaDataProvider(CompilerMetaDataProvider delegate) { } @Override - public SearchResult getCompilerMetaData(File binary, List additionalArgs, List path) { - Key key = new Key(binary, additionalArgs, path); + public SearchResult getCompilerMetaData(List path, Action configureAction) { + AbstractMetadataProvider.DefaultCompilerExecSpec execSpec = new AbstractMetadataProvider.DefaultCompilerExecSpec(); + configureAction.execute(execSpec); + + Key key = new Key(execSpec.executable, execSpec.args, path, execSpec.environments); SearchResult result = resultMap.get(key); if (result == null) { - result = delegate.getCompilerMetaData(binary, additionalArgs, path); + result = delegate.getCompilerMetaData(path, configureAction); resultMap.put(key, result); } return result; @@ -80,22 +84,24 @@ private static class Key { final File gccBinary; final List args; final List path; + private final Map environmentVariables; - private Key(File gccBinary, List args, List path) { + private Key(File gccBinary, List args, List path, Map environmentVariables) { this.gccBinary = gccBinary; this.args = args; this.path = path; + this.environmentVariables = environmentVariables; } @Override public boolean equals(Object obj) { Key other = (Key) obj; - return other.gccBinary.equals(gccBinary) && other.args.equals(args) && other.path.equals(path); + return other.gccBinary.equals(gccBinary) && other.args.equals(args) && other.path.equals(path) && other.environmentVariables.equals(environmentVariables); } @Override public int hashCode() { - return gccBinary.hashCode() ^ args.hashCode() ^ path.hashCode(); + return gccBinary.hashCode() ^ args.hashCode() ^ path.hashCode() ^ environmentVariables.hashCode(); } } } diff --git a/subprojects/platform-native/src/main/java/org/gradle/nativeplatform/toolchain/internal/swift/SwiftCompiler.java b/subprojects/platform-native/src/main/java/org/gradle/nativeplatform/toolchain/internal/swift/SwiftCompiler.java index 3412988dbcc32..0ad296575a6d3 100644 --- a/subprojects/platform-native/src/main/java/org/gradle/nativeplatform/toolchain/internal/swift/SwiftCompiler.java +++ b/subprojects/platform-native/src/main/java/org/gradle/nativeplatform/toolchain/internal/swift/SwiftCompiler.java @@ -30,6 +30,7 @@ import org.gradle.internal.operations.BuildOperationQueue; import org.gradle.internal.os.OperatingSystem; import org.gradle.internal.work.WorkerLeaseService; +import org.gradle.language.swift.SwiftVersion; import org.gradle.nativeplatform.internal.CompilerOutputFileNamingSchemeFactory; import org.gradle.nativeplatform.toolchain.internal.AbstractCompiler; import org.gradle.nativeplatform.toolchain.internal.ArgsTransformer; @@ -71,7 +72,7 @@ protected void addOptionsFileArgs(List args, File tempDir) { @Override public WorkResult execute(SwiftCompileSpec spec) { - if (swiftCompilerVersion.getMajor() < spec.getSourceCompatibility().getVersion()) { + if (swiftCompilerVersion.getMajor() < spec.getSourceCompatibility().getVersion() || (swiftCompilerVersion.getMajor() >= 5 && spec.getSourceCompatibility().equals(SwiftVersion.SWIFT3))) { throw new IllegalArgumentException(String.format("Swift compiler version '%s' doesn't support Swift language version '%d'", swiftCompilerVersion.toString(), spec.getSourceCompatibility().getVersion())); } return super.execute(spec); diff --git a/subprojects/platform-native/src/main/java/org/gradle/nativeplatform/toolchain/internal/swift/SwiftPlatformToolProvider.java b/subprojects/platform-native/src/main/java/org/gradle/nativeplatform/toolchain/internal/swift/SwiftPlatformToolProvider.java index e650670da636f..921d86e41e000 100644 --- a/subprojects/platform-native/src/main/java/org/gradle/nativeplatform/toolchain/internal/swift/SwiftPlatformToolProvider.java +++ b/subprojects/platform-native/src/main/java/org/gradle/nativeplatform/toolchain/internal/swift/SwiftPlatformToolProvider.java @@ -129,6 +129,11 @@ private CommandLineToolInvocationWorker commandLineTool(ToolType key, String exe private CommandLineToolContext context(CommandLineToolConfigurationInternal toolConfiguration) { MutableCommandLineToolContext baseInvocation = new DefaultMutableCommandLineToolContext(); baseInvocation.setArgAction(toolConfiguration.getArgAction()); + + String developerDir = System.getenv("DEVELOPER_DIR"); + if (developerDir != null) { + baseInvocation.addEnvironmentVar("DEVELOPER_DIR", developerDir); + } return baseInvocation; } diff --git a/subprojects/platform-native/src/main/java/org/gradle/nativeplatform/toolchain/internal/swift/SwiftcToolChain.java b/subprojects/platform-native/src/main/java/org/gradle/nativeplatform/toolchain/internal/swift/SwiftcToolChain.java index 82c232c83e90d..c389984530f11 100644 --- a/subprojects/platform-native/src/main/java/org/gradle/nativeplatform/toolchain/internal/swift/SwiftcToolChain.java +++ b/subprojects/platform-native/src/main/java/org/gradle/nativeplatform/toolchain/internal/swift/SwiftcToolChain.java @@ -44,7 +44,6 @@ import org.gradle.process.internal.ExecActionFactory; import java.io.File; -import java.util.Collections; import java.util.List; import java.util.Map; @@ -101,7 +100,7 @@ private PlatformToolProvider createPlatformToolProvider(NativePlatformInternal t if (!result.isAvailable()) { return new UnavailablePlatformToolProvider(targetPlatform.getOperatingSystem(), result); } - SearchResult swiftcMetaData = compilerMetaDataProvider.getCompilerMetaData(compiler.getTool(), Collections.emptyList(), toolSearchPath.getPath()); + SearchResult swiftcMetaData = compilerMetaDataProvider.getCompilerMetaData(toolSearchPath.getPath(), spec -> spec.executable(compiler.getTool())); result.mustBeAvailable(swiftcMetaData); if (!result.isAvailable()) { return new UnavailablePlatformToolProvider(targetPlatform.getOperatingSystem(), result); diff --git a/subprojects/platform-native/src/main/java/org/gradle/nativeplatform/toolchain/internal/tools/CommandLineToolConfigurationInternal.java b/subprojects/platform-native/src/main/java/org/gradle/nativeplatform/toolchain/internal/tools/CommandLineToolConfigurationInternal.java index 9faa367cdd76d..87d888ed9898d 100644 --- a/subprojects/platform-native/src/main/java/org/gradle/nativeplatform/toolchain/internal/tools/CommandLineToolConfigurationInternal.java +++ b/subprojects/platform-native/src/main/java/org/gradle/nativeplatform/toolchain/internal/tools/CommandLineToolConfigurationInternal.java @@ -21,7 +21,7 @@ import java.util.List; -public interface CommandLineToolConfigurationInternal extends CommandLineToolConfiguration{ +public interface CommandLineToolConfigurationInternal extends CommandLineToolConfiguration { public Action> getArgAction(); } diff --git a/subprojects/platform-native/src/main/java/org/gradle/nativeplatform/toolchain/internal/xcode/AbstractLocator.java b/subprojects/platform-native/src/main/java/org/gradle/nativeplatform/toolchain/internal/xcode/AbstractLocator.java index 4caeea05a1397..55ff6ab380e46 100644 --- a/subprojects/platform-native/src/main/java/org/gradle/nativeplatform/toolchain/internal/xcode/AbstractLocator.java +++ b/subprojects/platform-native/src/main/java/org/gradle/nativeplatform/toolchain/internal/xcode/AbstractLocator.java @@ -41,6 +41,11 @@ public File find() { execAction.executable("xcrun"); execAction.workingDir(System.getProperty("user.dir")); execAction.args(getXcrunFlags()); + + String developerDir = System.getenv("DEVELOPER_DIR"); + if (developerDir != null) { + execAction.environment("DEVELOPER_DIR", developerDir); + } execAction.setStandardOutput(outputStream); execAction.execute().assertNormalExitValue(); diff --git a/subprojects/platform-native/src/test/groovy/org/gradle/nativeplatform/toolchain/internal/gcc/AbstractGccCompatibleToolChainTest.groovy b/subprojects/platform-native/src/test/groovy/org/gradle/nativeplatform/toolchain/internal/gcc/AbstractGccCompatibleToolChainTest.groovy index d1b842733633d..43a267c4eaf9c 100644 --- a/subprojects/platform-native/src/test/groovy/org/gradle/nativeplatform/toolchain/internal/gcc/AbstractGccCompatibleToolChainTest.groovy +++ b/subprojects/platform-native/src/test/groovy/org/gradle/nativeplatform/toolchain/internal/gcc/AbstractGccCompatibleToolChainTest.groovy @@ -134,7 +134,7 @@ class AbstractGccCompatibleToolChainTest extends Specification { and: toolSearchPath.locate(ToolType.CPP_COMPILER, "g++") >> compilerMissing toolSearchPath.locate(_, _) >> tool - metaDataProvider.getCompilerMetaData(_, _, _) >> correctCompiler + metaDataProvider.getCompilerMetaData(_, _) >> correctCompiler expect: def platformToolChain = toolChain.select(NativeLanguage.CPP, platform) @@ -154,7 +154,7 @@ class AbstractGccCompatibleToolChainTest extends Specification { and: toolSearchPath.locate(_, _) >> tool - metaDataProvider.getCompilerMetaData(_, _, _) >> wrongCompiler + metaDataProvider.getCompilerMetaData(_, _) >> wrongCompiler expect: def platformToolChain = toolChain.select(language, platform) @@ -173,7 +173,7 @@ class AbstractGccCompatibleToolChainTest extends Specification { and: toolSearchPath.locate(toolType, _) >> tool toolSearchPath.locate(_, _) >> missing - metaDataProvider.getCompilerMetaData(_, _, _) >> correctCompiler + metaDataProvider.getCompilerMetaData(_, _) >> correctCompiler expect: toolChain.select(platform).available @@ -190,7 +190,7 @@ class AbstractGccCompatibleToolChainTest extends Specification { and: toolSearchPath.locate(ToolType.CPP_COMPILER, _) >> tool toolSearchPath.locate(_, _) >> missing - metaDataProvider.getCompilerMetaData(_, _, _) >> correctCompiler + metaDataProvider.getCompilerMetaData(_, _) >> correctCompiler expect: toolChain.select(platform).available @@ -203,7 +203,7 @@ class AbstractGccCompatibleToolChainTest extends Specification { and: toolSearchPath.locate(_, _) >> tool - metaDataProvider.getCompilerMetaData(_, _, _) >> correctCompiler + metaDataProvider.getCompilerMetaData(_, _) >> correctCompiler expect: toolChain.select(platform).available @@ -229,7 +229,7 @@ class AbstractGccCompatibleToolChainTest extends Specification { platform2.operatingSystem >> dummyOs toolSearchPath.locate(_, _) >> tool - metaDataProvider.getCompilerMetaData(_, _, _) >> correctCompiler + metaDataProvider.getCompilerMetaData(_, _) >> correctCompiler given: int platformActionApplied = 0 @@ -262,7 +262,7 @@ class AbstractGccCompatibleToolChainTest extends Specification { platform.getOperatingSystem() >> dummyOs platform.getArchitecture() >> dummyArch toolChain.eachPlatform(action) - metaDataProvider.getCompilerMetaData(_, _, _) >> correctCompiler + metaDataProvider.getCompilerMetaData(_, _) >> correctCompiler when: toolChain.select(platform) @@ -287,7 +287,7 @@ class AbstractGccCompatibleToolChainTest extends Specification { platform.operatingSystem >> dummyOs platform.architecture >> Architectures.forInput(arch) toolChain.eachPlatform(action) - metaDataProvider.getCompilerMetaData(_, _, _) >> correctCompiler + metaDataProvider.getCompilerMetaData(_, _) >> correctCompiler when: toolChain.select(platform) @@ -316,7 +316,7 @@ class AbstractGccCompatibleToolChainTest extends Specification { toolSearchPath.locate(_, _) >> tool platform.operatingSystem >> new DefaultOperatingSystem("osx", OperatingSystem.MAC_OS) platform.architecture >> new DefaultArchitecture(arch) - metaDataProvider.getCompilerMetaData(_, _, _) >> correctCompiler + metaDataProvider.getCompilerMetaData(_, _) >> correctCompiler toolChain.target(platform.name) toolChain.eachPlatform(action) @@ -348,7 +348,7 @@ class AbstractGccCompatibleToolChainTest extends Specification { def platformConfig2 = Mock(Action) toolSearchPath.locate(_, _) >> tool - metaDataProvider.getCompilerMetaData(_, _, _) >> correctCompiler + metaDataProvider.getCompilerMetaData(_, _) >> correctCompiler toolChain.target("platform1", platformConfig1) toolChain.target("platform2", platformConfig2) @@ -370,7 +370,7 @@ class AbstractGccCompatibleToolChainTest extends Specification { when: toolSearchPath.locate(_, _) >> tool - metaDataProvider.getCompilerMetaData(_, _, _) >> correctCompiler + metaDataProvider.getCompilerMetaData(_, _) >> correctCompiler and: toolChain.target(platform.getName(), new Action() { diff --git a/subprojects/platform-native/src/test/groovy/org/gradle/nativeplatform/toolchain/internal/gcc/GccPlatformToolProviderTest.groovy b/subprojects/platform-native/src/test/groovy/org/gradle/nativeplatform/toolchain/internal/gcc/GccPlatformToolProviderTest.groovy index 8bb31946d90e9..57f6be4686cdd 100644 --- a/subprojects/platform-native/src/test/groovy/org/gradle/nativeplatform/toolchain/internal/gcc/GccPlatformToolProviderTest.groovy +++ b/subprojects/platform-native/src/test/groovy/org/gradle/nativeplatform/toolchain/internal/gcc/GccPlatformToolProviderTest.groovy @@ -58,8 +58,8 @@ class GccPlatformToolProviderTest extends Specification { then: result == libs - 1 * metaDataProvider.getCompilerMetaData(_, _, _) >> { - assert arguments[1] == args + 1 * metaDataProvider.getCompilerMetaData(_, _) >> { + arguments[1].execute(assertingCompilerExecSpecArguments(args)) new ComponentFound(metaData) } 1 * toolRegistry.getTool(toolType) >> new DefaultGccCommandLineToolConfiguration(toolType, 'exe') @@ -81,8 +81,8 @@ class GccPlatformToolProviderTest extends Specification { platformToolProvider.getCompilerMetadata(toolType) then: - 1 * metaDataProvider.getCompilerMetaData(_, _, _) >> { - assert arguments[1] == args + 1 * metaDataProvider.getCompilerMetaData(_, _) >> { + arguments[1].execute(assertingCompilerExecSpecArguments(args)) Mock(SearchResult) } 1 * toolRegistry.getTool(toolType) >> new DefaultGccCommandLineToolConfiguration(toolType, 'exe') @@ -96,4 +96,24 @@ class GccPlatformToolProviderTest extends Specification { ToolType.OBJECTIVECPP_COMPILER | ['-x', 'objective-c++'] ToolType.ASSEMBLER | [] } + + CompilerMetaDataProvider.CompilerExecSpec assertingCompilerExecSpecArguments(Iterable expectedArgs) { + return new CompilerMetaDataProvider.CompilerExecSpec() { + @Override + CompilerMetaDataProvider.CompilerExecSpec environment(String key, String value) { + return this + } + + @Override + CompilerMetaDataProvider.CompilerExecSpec executable(File executable) { + return this + } + + @Override + CompilerMetaDataProvider.CompilerExecSpec args(Iterable args) { + assert args == expectedArgs + return this + } + } + } } diff --git a/subprojects/platform-native/src/test/groovy/org/gradle/nativeplatform/toolchain/internal/gcc/metadata/GccMetadataProviderTest.groovy b/subprojects/platform-native/src/test/groovy/org/gradle/nativeplatform/toolchain/internal/gcc/metadata/GccMetadataProviderTest.groovy index 7a551e55d7797..862ed8396c295 100644 --- a/subprojects/platform-native/src/test/groovy/org/gradle/nativeplatform/toolchain/internal/gcc/metadata/GccMetadataProviderTest.groovy +++ b/subprojects/platform-native/src/test/groovy/org/gradle/nativeplatform/toolchain/internal/gcc/metadata/GccMetadataProviderTest.groovy @@ -247,7 +247,7 @@ End of search list. def binary = new File("g++") when: - def result = metadataProvider.getCompilerMetaData(binary, [], []) + def result = metadataProvider.getCompilerMetaData([]) { it.executable(binary) } then: 1 * execActionFactory.newExecAction() >> action @@ -354,7 +354,7 @@ End of search list. mapsPath(cygpath, '/usr/include', 'C:\\cygwin\\usr\\include') mapsPath(cygpath, '/usr/local/include', 'C:\\cygwin\\usr\\local\\include') def provider = new GccMetadataProvider(execActionFactory, GCC) - def result = provider.getCompilerMetaData(new File("gcc"), [], [binDir]) + def result = provider.getCompilerMetaData([binDir]) { it.executable(new File("gcc")) } result.component.systemIncludes*.path == mapped } @@ -369,7 +369,7 @@ End of search list. SearchResult output(String output, String error, GccCompilerType compilerType = GCC, List path = []) { runsCompiler(output, error) def provider = new GccMetadataProvider(execActionFactory, compilerType) - provider.getCompilerMetaData(new File("g++"), [], path) + provider.getCompilerMetaData(path) { it.executable(new File("g++")) } } void runsCompiler(String output, String error) { diff --git a/subprojects/platform-native/src/test/groovy/org/gradle/nativeplatform/toolchain/internal/metadata/CompilerMetaDataProviderFactoryTest.groovy b/subprojects/platform-native/src/test/groovy/org/gradle/nativeplatform/toolchain/internal/metadata/CompilerMetaDataProviderFactoryTest.groovy index 8b1b6f4975599..22364a382a975 100644 --- a/subprojects/platform-native/src/test/groovy/org/gradle/nativeplatform/toolchain/internal/metadata/CompilerMetaDataProviderFactoryTest.groovy +++ b/subprojects/platform-native/src/test/groovy/org/gradle/nativeplatform/toolchain/internal/metadata/CompilerMetaDataProviderFactoryTest.groovy @@ -33,13 +33,13 @@ class CompilerMetaDataProviderFactoryTest extends Specification { def "caches result of actual #compiler metadata provider"() { def binary = new File("any") when: - def metadata = metadataProvider(compiler).getCompilerMetaData(binary, [], []) + def metadata = metadataProvider(compiler).getCompilerMetaData([]) { it.executable(binary) } then: interaction compilerShouldBeExecuted when: - def newMetadata = metadataProvider(compiler).getCompilerMetaData(binary, [], []) + def newMetadata = metadataProvider(compiler).getCompilerMetaData([]) { it.executable(binary) } then: 0 * _ @@ -54,20 +54,20 @@ class CompilerMetaDataProviderFactoryTest extends Specification { def firstBinary = new File("first") def secondBinary = new File("second") when: - def firstMetadata = metadataProvider(compiler).getCompilerMetaData(firstBinary, [], []) + def firstMetadata = metadataProvider(compiler).getCompilerMetaData([]) { it.executable(firstBinary) } then: interaction compilerShouldBeExecuted when: - def secondMetadata = metadataProvider(compiler).getCompilerMetaData(secondBinary, [], []) + def secondMetadata = metadataProvider(compiler).getCompilerMetaData([]) { it.executable(secondBinary) } then: interaction compilerShouldBeExecuted firstMetadata != secondMetadata when: - def firstMetadataAgain = metadataProvider(compiler).getCompilerMetaData(firstBinary, [], []) + def firstMetadataAgain = metadataProvider(compiler).getCompilerMetaData([]) { it.executable(firstBinary) } then: 0 * _ @@ -83,20 +83,20 @@ class CompilerMetaDataProviderFactoryTest extends Specification { def firstArgs = ["-m32"] def secondArgs = ["-m64"] when: - def firstMetadata = metadataProvider(compiler).getCompilerMetaData(binary, firstArgs, []) + def firstMetadata = metadataProvider(compiler).getCompilerMetaData([]) { it.executable(binary).args(firstArgs) } then: interaction compilerShouldBeExecuted when: - def secondMetadata = metadataProvider(compiler).getCompilerMetaData(binary, secondArgs, []) + def secondMetadata = metadataProvider(compiler).getCompilerMetaData([]) { it.executable(binary).args(secondArgs) } then: interaction compilerShouldBeExecuted firstMetadata != secondMetadata when: - def firstMetadataAgain = metadataProvider(compiler).getCompilerMetaData(binary, firstArgs, []) + def firstMetadataAgain = metadataProvider(compiler).getCompilerMetaData([]) { it.executable(binary).args(firstArgs) } then: 0 * _ @@ -112,20 +112,20 @@ class CompilerMetaDataProviderFactoryTest extends Specification { def firstPath = [] def secondPath = [new File("/usr/local/bin")] when: - def firstMetadata = metadataProvider(compiler).getCompilerMetaData(binary, [], firstPath) + def firstMetadata = metadataProvider(compiler).getCompilerMetaData(firstPath) { it.executable(binary) } then: interaction compilerShouldBeExecuted when: - def secondMetadata = metadataProvider(compiler).getCompilerMetaData(binary, [], secondPath) + def secondMetadata = metadataProvider(compiler).getCompilerMetaData(secondPath) { it.executable(binary) } then: interaction compilerShouldBeExecuted firstMetadata != secondMetadata when: - def firstMetadataAgain = metadataProvider(compiler).getCompilerMetaData(binary, [], firstPath) + def firstMetadataAgain = metadataProvider(compiler).getCompilerMetaData(firstPath) { it.executable(binary) } then: 0 * _ diff --git a/subprojects/platform-native/src/test/groovy/org/gradle/nativeplatform/toolchain/internal/swift/metadata/SwiftcMetadataProviderTest.groovy b/subprojects/platform-native/src/test/groovy/org/gradle/nativeplatform/toolchain/internal/swift/metadata/SwiftcMetadataProviderTest.groovy index 58837acc78348..f347f56e25a30 100644 --- a/subprojects/platform-native/src/test/groovy/org/gradle/nativeplatform/toolchain/internal/swift/metadata/SwiftcMetadataProviderTest.groovy +++ b/subprojects/platform-native/src/test/groovy/org/gradle/nativeplatform/toolchain/internal/swift/metadata/SwiftcMetadataProviderTest.groovy @@ -75,7 +75,7 @@ Target: x86_64-unknown-linux-gnu def binary = new File("swiftc") when: - def result = metadataProvider.getCompilerMetaData(binary, [], []) + def result = metadataProvider.getCompilerMetaData([]) { it.executable(binary) } then: 1 * execActionFactory.newExecAction() >> action @@ -99,7 +99,7 @@ Target: x86_64-unknown-linux-gnu 1 * action.setStandardOutput(_) >> { OutputStream outstr -> outstr << output; action } 1 * action.execute() >> result def provider = new SwiftcMetadataProvider(execActionFactory) - provider.getCompilerMetaData(new File("swiftc"), [], []) + provider.getCompilerMetaData([]) { it.executable(new File("swiftc")) } } } diff --git a/subprojects/platform-native/src/testFixtures/groovy/org/gradle/nativeplatform/fixtures/AbstractInstalledToolChainIntegrationSpec.groovy b/subprojects/platform-native/src/testFixtures/groovy/org/gradle/nativeplatform/fixtures/AbstractInstalledToolChainIntegrationSpec.groovy index 29cafa580af39..6d98a7a5476fb 100755 --- a/subprojects/platform-native/src/testFixtures/groovy/org/gradle/nativeplatform/fixtures/AbstractInstalledToolChainIntegrationSpec.groovy +++ b/subprojects/platform-native/src/testFixtures/groovy/org/gradle/nativeplatform/fixtures/AbstractInstalledToolChainIntegrationSpec.groovy @@ -54,6 +54,7 @@ abstract class AbstractInstalledToolChainIntegrationSpec extends AbstractIntegra """ executer.beforeExecute({ usingInitScript(initScript) + toolChain.configureExecuter(it) }) } diff --git a/subprojects/platform-native/src/testFixtures/groovy/org/gradle/nativeplatform/fixtures/AvailableToolChains.java b/subprojects/platform-native/src/testFixtures/groovy/org/gradle/nativeplatform/fixtures/AvailableToolChains.java index 499d8e05b2e4c..fc716722097b6 100755 --- a/subprojects/platform-native/src/testFixtures/groovy/org/gradle/nativeplatform/fixtures/AvailableToolChains.java +++ b/subprojects/platform-native/src/testFixtures/groovy/org/gradle/nativeplatform/fixtures/AvailableToolChains.java @@ -17,11 +17,13 @@ package org.gradle.nativeplatform.fixtures; import com.google.common.base.Joiner; +import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Lists; import org.gradle.api.internal.file.TestFiles; import org.gradle.api.specs.Spec; import org.gradle.integtests.fixtures.AbstractContextualMultiVersionSpecRunner; +import org.gradle.integtests.fixtures.executer.GradleExecuter; import org.gradle.internal.nativeintegration.ProcessEnvironment; import org.gradle.internal.os.OperatingSystem; import org.gradle.nativeplatform.fixtures.msvcpp.VisualStudioLocatorTestFixture; @@ -62,7 +64,7 @@ import static org.gradle.nativeplatform.fixtures.msvcpp.VisualStudioVersion.VISUALSTUDIO_2017; public class AvailableToolChains { - private static final Comparator LATEST_FIRST = Collections.reverseOrder(new Comparator() { + private static final Comparator LATEST_RELEASED_FIRST = Collections.reverseOrder(new Comparator() { @Override public int compare(ToolChainCandidate toolchain1, ToolChainCandidate toolchain2) { return toolchain1.getVersion().compareTo(toolchain2.getVersion()); @@ -133,7 +135,7 @@ static private List findClangs(boolean mustFind) { if (!clangCandidates.isEmpty()) { File firstInPath = clangCandidates.iterator().next(); for (File candidate : clangCandidates) { - SearchResult version = versionDeterminer.getCompilerMetaData(candidate, Collections.emptyList(), Collections.emptyList()); + SearchResult version = versionDeterminer.getCompilerMetaData(Collections.emptyList(), spec -> spec.executable(candidate)); if (version.isAvailable()) { InstalledClang clang = new InstalledClang(version.getComponent().getVersion()); if (!candidate.equals(firstInPath)) { @@ -149,7 +151,7 @@ static private List findClangs(boolean mustFind) { toolChains.add(new UnavailableToolChain(ToolFamily.CLANG)); } - toolChains.sort(LATEST_FIRST); + toolChains.sort(LATEST_RELEASED_FIRST); return toolChains; } @@ -183,7 +185,7 @@ static private List findVisualCpps() { toolChains.add(new UnavailableToolChain(ToolFamily.VISUAL_CPP)); } - toolChains.sort(LATEST_FIRST); + toolChains.sort(LATEST_RELEASED_FIRST); return toolChains; } @@ -225,7 +227,7 @@ static private List findGccs(boolean mustFind) { if (!gppCandidates.isEmpty()) { File firstInPath = gppCandidates.iterator().next(); for (File candidate : gppCandidates) { - SearchResult version = versionDeterminer.getCompilerMetaData(candidate, Collections.emptyList(), Collections.emptyList()); + SearchResult version = versionDeterminer.getCompilerMetaData(Collections.emptyList(), spec -> spec.executable(candidate)); if (version.isAvailable()) { InstalledGcc gcc = new InstalledGcc(ToolFamily.GCC, version.getComponent().getVersion()); if (!candidate.equals(firstInPath)) { @@ -241,7 +243,7 @@ static private List findGccs(boolean mustFind) { toolChains.add(new UnavailableToolChain(ToolFamily.GCC)); } - toolChains.sort(LATEST_FIRST); + toolChains.sort(LATEST_RELEASED_FIRST); return toolChains; } @@ -253,25 +255,37 @@ static List findSwiftcs() { // On Linux, we assume swift is installed into /opt/swift File rootSwiftInstall = new File("/opt/swift"); - File[] candidates = GUtil.elvis(rootSwiftInstall.listFiles(new FileFilter() { + File[] swiftCandidates = GUtil.elvis(rootSwiftInstall.listFiles(new FileFilter() { @Override public boolean accept(File swiftInstall) { return swiftInstall.isDirectory() && !swiftInstall.getName().equals("latest"); } }), new File[0]); - for (File swiftInstall : candidates) { + for (File swiftInstall : swiftCandidates) { File swiftc = new File(swiftInstall, "/usr/bin/swiftc"); - SearchResult version = versionDeterminer.getCompilerMetaData(swiftc, Collections.emptyList(), Collections.emptyList()); + SearchResult version = versionDeterminer.getCompilerMetaData(Collections.emptyList(), spec -> spec.executable(swiftc)); if (version.isAvailable()) { File binDir = swiftc.getParentFile(); toolChains.add(new InstalledSwiftc(binDir, version.getComponent().getVersion()).inPath(binDir, new File("/usr/bin"))); } } + // On macOS, we assume co-located Xcode is installed into /opt/xcode + File rootXcodeInstall = new File("/opt/xcode"); + File[] xcodeCandidates = GUtil.elvis(rootXcodeInstall.listFiles(xcodeInstall -> xcodeInstall.isDirectory()), new File[0]); + for (File xcodeInstall : xcodeCandidates) { + File swiftc = new File("/usr/bin/swiftc"); + SearchResult version = versionDeterminer.getCompilerMetaData(Collections.emptyList(), spec -> spec.executable(swiftc).environment("DEVELOPER_DIR", xcodeInstall.getAbsolutePath())); + if (version.isAvailable()) { + File binDir = swiftc.getParentFile(); + toolChains.add(new InstalledXcode(xcodeInstall, version.getComponent().getVersion()).inPath(binDir, new File("/usr/bin"))); + } + } + List swiftcCandidates = OperatingSystem.current().findAllInPath("swiftc"); for (File candidate : swiftcCandidates) { - SearchResult version = versionDeterminer.getCompilerMetaData(candidate, Collections.emptyList(), Collections.emptyList()); + SearchResult version = versionDeterminer.getCompilerMetaData(Collections.emptyList(), spec -> spec.executable(candidate)); if (version.isAvailable()) { File binDir = candidate.getParentFile(); InstalledSwiftc swiftc = new InstalledSwiftc(binDir, version.getComponent().getVersion()); @@ -283,7 +297,7 @@ public boolean accept(File swiftInstall) { if (toolChains.isEmpty()) { toolChains.add(new UnavailableToolChain(ToolFamily.SWIFTC)); } else { - toolChains.sort(LATEST_FIRST); + toolChains.sort(LATEST_RELEASED_FIRST); } return toolChains; @@ -464,6 +478,10 @@ public boolean matches(String criteria) { public String platformSpecificToolChainConfiguration() { return ""; } + + public void configureExecuter(GradleExecuter executer) { + // Toolchains should be using default configuration + } } public static abstract class GccCompatibleToolChain extends InstalledToolChain { @@ -697,7 +715,63 @@ public String getUnitTestPlatform() { @Override public boolean meets(ToolChainRequirement requirement) { - return requirement == ToolChainRequirement.SWIFTC || (requirement == ToolChainRequirement.SWIFTC_3 && getVersion().getMajor() == 3) || (requirement == ToolChainRequirement.SWIFTC_4 && getVersion().getMajor() == 4); + switch (requirement) { + case SWIFTC: + return true; + case SWIFTC_3: + return getVersion().getMajor() == 3; + case SWIFTC_4: + return getVersion().getMajor() == 4; + case SWIFTC_5: + return getVersion().getMajor() == 5; + case SWIFTC_4_OR_OLDER: + return getVersion().getMajor() < 5; + default: + return false; + } + } + } + + public static class InstalledXcode extends InstalledSwiftc { + private static final ProcessEnvironment PROCESS_ENVIRONMENT = NativeServicesTestFixture.getInstance().get(ProcessEnvironment.class); + private final File xcodeDir; + private String originalDeveloperDir; + + public InstalledXcode(File xcodeDir, VersionNumber compilerVersion) { + super(new File("/usr/bin"), compilerVersion); + this.xcodeDir = xcodeDir; + } + + @Override + public List getRuntimeEnv() { + List result = new ArrayList<>(); + result.addAll(super.getRuntimeEnv()); + result.add("DEVELOPER_DIR=" + xcodeDir.getAbsolutePath()); + return result; + } + + @Override + public void initialiseEnvironment() { + super.initialiseEnvironment(); + + originalDeveloperDir = System.getenv("DEVELOPER_DIR"); + System.out.println(String.format("Using DEVELOPER_DIR %s", xcodeDir.getAbsolutePath())); + PROCESS_ENVIRONMENT.setEnvironmentVariable("DEVELOPER_DIR", xcodeDir.getAbsolutePath()); + } + + @Override + public void resetEnvironment() { + if (originalDeveloperDir != null) { + PROCESS_ENVIRONMENT.setEnvironmentVariable("DEVELOPER_DIR", xcodeDir.getAbsolutePath()); + } + + super.resetEnvironment(); + } + + @Override + public void configureExecuter(GradleExecuter executer) { + super.configureExecuter(executer); + executer.withEnvironmentVars(ImmutableMap.of("DEVELOPER_DIR", xcodeDir.getAbsolutePath())); } } diff --git a/subprojects/platform-native/src/testFixtures/groovy/org/gradle/nativeplatform/fixtures/NativeBinaryFixture.groovy b/subprojects/platform-native/src/testFixtures/groovy/org/gradle/nativeplatform/fixtures/NativeBinaryFixture.groovy index 2016474094f66..e6c7eb6d1301a 100644 --- a/subprojects/platform-native/src/testFixtures/groovy/org/gradle/nativeplatform/fixtures/NativeBinaryFixture.groovy +++ b/subprojects/platform-native/src/testFixtures/groovy/org/gradle/nativeplatform/fixtures/NativeBinaryFixture.groovy @@ -154,14 +154,14 @@ class NativeBinaryFixture { BinaryInfo getBinaryInfo() { file.assertExists() if (OperatingSystem.current().isMacOsX()) { - return new OtoolBinaryInfo(file); + return new OtoolBinaryInfo(file, toolChain.runtimeEnv) } if (OperatingSystem.current().isWindows()) { if (toolChain.meets(ToolChainRequirement.GCC)) { - return new DumpbinGccProducedBinaryInfo(file); + return new DumpbinGccProducedBinaryInfo(file) } - return new DumpbinBinaryInfo(file); + return new DumpbinBinaryInfo(file) } - return new ReadelfBinaryInfo(file); + return new ReadelfBinaryInfo(file) } } diff --git a/subprojects/platform-native/src/testFixtures/groovy/org/gradle/nativeplatform/fixtures/ToolChainRequirement.java b/subprojects/platform-native/src/testFixtures/groovy/org/gradle/nativeplatform/fixtures/ToolChainRequirement.java index ee54adf8ca60e..45e746b5df411 100644 --- a/subprojects/platform-native/src/testFixtures/groovy/org/gradle/nativeplatform/fixtures/ToolChainRequirement.java +++ b/subprojects/platform-native/src/testFixtures/groovy/org/gradle/nativeplatform/fixtures/ToolChainRequirement.java @@ -49,6 +49,10 @@ public enum ToolChainRequirement { SWIFTC_3, // Any Swift 4.x compiler SWIFTC_4, + // Any available Swift compiler <= 4 + SWIFTC_4_OR_OLDER, + // Any Swift 5.x compiler + SWIFTC_5, // Supports building 32-bit binaries SUPPORTS_32, // Supports building both 32-bit and 64-bit binaries diff --git a/subprojects/platform-native/src/testFixtures/groovy/org/gradle/nativeplatform/fixtures/app/Swift5.groovy b/subprojects/platform-native/src/testFixtures/groovy/org/gradle/nativeplatform/fixtures/app/Swift5.groovy new file mode 100644 index 0000000000000..cbbe417f4aff7 --- /dev/null +++ b/subprojects/platform-native/src/testFixtures/groovy/org/gradle/nativeplatform/fixtures/app/Swift5.groovy @@ -0,0 +1,60 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.nativeplatform.fixtures.app + +import org.gradle.integtests.fixtures.SourceFile + +class Swift5 extends SwiftSourceElement { + Swift5(String projectName) { + super(projectName) + } + + @Override + List getFiles() { + return [sourceFile("swift", "swift5-code.swift", ''' + public typealias Name = (firstName: String, lastName: String) + + public func getNames() -> [Name] { + return [("Bart", "den Hollander")] + } + + public func getLastNameOfFirstEntry(names: [Name]) -> String { + var result: String = "" + names.forEach({ name in + result = name.lastName // "den Hollander" + }) + return result + } + + public func getLongMessage() -> String { + return """ + When you write a string that spans multiple + lines make sure you start its content on a + line all of its own, and end it with three + quotes also on a line of their own. + Multi-line strings also let you write "quote marks" + freely inside your strings, which is great! + """ + } + + public func getRawString() -> String { + let value = 42 + return #"Raw string are ones with "quotes", backslash (\\), but can do special string interpolation (\\#(value))"# + } + ''')] + } +} diff --git a/subprojects/platform-native/src/testFixtures/groovy/org/gradle/nativeplatform/fixtures/app/Swift5Test.groovy b/subprojects/platform-native/src/testFixtures/groovy/org/gradle/nativeplatform/fixtures/app/Swift5Test.groovy new file mode 100644 index 0000000000000..84fad22658f01 --- /dev/null +++ b/subprojects/platform-native/src/testFixtures/groovy/org/gradle/nativeplatform/fixtures/app/Swift5Test.groovy @@ -0,0 +1,40 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.nativeplatform.fixtures.app + +class Swift5Test extends XCTestSourceFileElement { + Swift5Test() { + super("Swift5Test") + } + + @Override + List getTestCases() { + return [ + testCase("testRawStrings", + '''XCTAssertEqual(getRawString(), "Raw string are ones with \\"quotes\\", backslash (\\\\), but can do special string interpolation (42)"))'''), + testCase("testCodeWasCompiledWithSwift5Compiler", + """#if swift(>=6.0) + XCTFail("Compilation unit compiled with Swift 6+ instead of Swift 5.x"); + #elseif swift(>=5.0) + // Do nothing + #else + XCTFail("Compilation unit compiled with Swift 4- instead of Swift 5.x"); + #endif + """) + ] + } +} diff --git a/subprojects/platform-native/src/testFixtures/groovy/org/gradle/nativeplatform/fixtures/app/Swift5WithSwift4XCTest.groovy b/subprojects/platform-native/src/testFixtures/groovy/org/gradle/nativeplatform/fixtures/app/Swift5WithSwift4XCTest.groovy new file mode 100644 index 0000000000000..d80709f52982d --- /dev/null +++ b/subprojects/platform-native/src/testFixtures/groovy/org/gradle/nativeplatform/fixtures/app/Swift5WithSwift4XCTest.groovy @@ -0,0 +1,33 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.nativeplatform.fixtures.app + +class Swift5WithSwift4XCTest extends MainWithXCTestSourceElement { + final Swift5 main + final XCTestSourceElement test + + Swift5WithSwift4XCTest(String projectName) { + super(projectName) + this.main = new Swift5(projectName) + this.test = new XCTestSourceElement(projectName) { + @Override + List getTestSuites() { + return [new Swift4Test().withImport(main.moduleName)] + } + } + } +} diff --git a/subprojects/platform-native/src/testFixtures/groovy/org/gradle/nativeplatform/fixtures/app/Swift5WithXCTest.groovy b/subprojects/platform-native/src/testFixtures/groovy/org/gradle/nativeplatform/fixtures/app/Swift5WithXCTest.groovy new file mode 100644 index 0000000000000..077f42601a9c5 --- /dev/null +++ b/subprojects/platform-native/src/testFixtures/groovy/org/gradle/nativeplatform/fixtures/app/Swift5WithXCTest.groovy @@ -0,0 +1,33 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.nativeplatform.fixtures.app + +class Swift5WithXCTest extends MainWithXCTestSourceElement { + final Swift5 main + final XCTestSourceElement test + + Swift5WithXCTest(String projectName) { + super(projectName) + this.main = new Swift5(projectName) + this.test = new XCTestSourceElement(projectName) { + @Override + List getTestSuites() { + return [new Swift5Test().withImport(main.moduleName)] + } + } + } +} diff --git a/subprojects/platform-native/src/testFixtures/groovy/org/gradle/nativeplatform/fixtures/app/Swift5XCTest.groovy b/subprojects/platform-native/src/testFixtures/groovy/org/gradle/nativeplatform/fixtures/app/Swift5XCTest.groovy new file mode 100644 index 0000000000000..2c3d4d98108ab --- /dev/null +++ b/subprojects/platform-native/src/testFixtures/groovy/org/gradle/nativeplatform/fixtures/app/Swift5XCTest.groovy @@ -0,0 +1,36 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.nativeplatform.fixtures.app + +class Swift5XCTest extends XCTestSourceElement { + Swift5XCTest(String projectName) { + super(projectName) + } + + @Override + List getTestSuites() { + return [new XCTestSourceFileElement("Swift5Test") { + @Override + List getTestCases() { + return [testCase("testRawString", + '''let value = 42 + let rawString = #"Raw string are ones with "quotes", backslash (\\), but can do special string interpolation (\\#(value))"# + XCTAssertEqual(rawString, "Raw string are ones with \\"quotes\\", backslash (\\\\), but can do special string interpolation (42)")''')] + } + }] + } +} diff --git a/subprojects/platform-native/src/testFixtures/groovy/org/gradle/nativeplatform/fixtures/app/SwiftCompilerDetectingApp.groovy b/subprojects/platform-native/src/testFixtures/groovy/org/gradle/nativeplatform/fixtures/app/SwiftCompilerDetectingApp.groovy index d0bffe9e2215b..9b5ae16dafbff 100644 --- a/subprojects/platform-native/src/testFixtures/groovy/org/gradle/nativeplatform/fixtures/app/SwiftCompilerDetectingApp.groovy +++ b/subprojects/platform-native/src/testFixtures/groovy/org/gradle/nativeplatform/fixtures/app/SwiftCompilerDetectingApp.groovy @@ -28,7 +28,9 @@ class SwiftCompilerDetectingApp extends SourceFileElement implements AppElement @Override SourceFile getSourceFile() { return sourceFile('swift', 'main.swift', """ - #if swift(>=4.0) + #if swift(>=5.0) + print("Compiled using Swift 5.x compiler") + #elseif swift(>=4.0) print("Compiled using Swift 4.x compiler") #elseif swift(>=3.0) print("Compiled using Swift 3.x compiler") diff --git a/subprojects/platform-native/src/testFixtures/groovy/org/gradle/nativeplatform/fixtures/binaryinfo/BinaryInfo.java b/subprojects/platform-native/src/testFixtures/groovy/org/gradle/nativeplatform/fixtures/binaryinfo/BinaryInfo.java index d586890adbfac..5dba881a91490 100644 --- a/subprojects/platform-native/src/testFixtures/groovy/org/gradle/nativeplatform/fixtures/binaryinfo/BinaryInfo.java +++ b/subprojects/platform-native/src/testFixtures/groovy/org/gradle/nativeplatform/fixtures/binaryinfo/BinaryInfo.java @@ -16,6 +16,7 @@ package org.gradle.nativeplatform.fixtures.binaryinfo; +import com.google.api.client.util.Objects; import org.gradle.nativeplatform.platform.internal.ArchitectureInternal; import java.util.List; @@ -50,5 +51,9 @@ public char getType() { public boolean isExported() { return exported; } + + public String toString() { + return Objects.toStringHelper(this).add("name", name).add("type", type).add("exported", exported).toString(); + } } } diff --git a/subprojects/platform-native/src/testFixtures/groovy/org/gradle/nativeplatform/fixtures/binaryinfo/OtoolBinaryInfo.groovy b/subprojects/platform-native/src/testFixtures/groovy/org/gradle/nativeplatform/fixtures/binaryinfo/OtoolBinaryInfo.groovy index 8da014fc59c9e..7803e588e9ee3 100644 --- a/subprojects/platform-native/src/testFixtures/groovy/org/gradle/nativeplatform/fixtures/binaryinfo/OtoolBinaryInfo.groovy +++ b/subprojects/platform-native/src/testFixtures/groovy/org/gradle/nativeplatform/fixtures/binaryinfo/OtoolBinaryInfo.groovy @@ -21,13 +21,15 @@ import org.gradle.nativeplatform.platform.internal.Architectures class OtoolBinaryInfo implements BinaryInfo { def binaryFile + private final List environments - OtoolBinaryInfo(File binaryFile) { + OtoolBinaryInfo(File binaryFile, List environments) { this.binaryFile = binaryFile + this.environments = environments } ArchitectureInternal getArch() { - def process = ['otool', '-hv', binaryFile.absolutePath].execute() + def process = ['otool', '-hv', binaryFile.absolutePath].execute(environments, null) def lines = process.inputStream.readLines() def archString = lines.last().split()[1] @@ -42,18 +44,18 @@ class OtoolBinaryInfo implements BinaryInfo { } List listObjectFiles() { - def process = ['ar', '-t', binaryFile.getAbsolutePath()].execute() + def process = ['ar', '-t', binaryFile.getAbsolutePath()].execute(environments, null) return process.inputStream.readLines().drop(1) } List listLinkedLibraries() { - def process = ['otool', '-L', binaryFile.absolutePath].execute() + def process = ['otool', '-L', binaryFile.absolutePath].execute(environments, null) def lines = process.inputStream.readLines() return lines } List listSymbols() { - def process = ['nm', '-a', '-f', 'posix', binaryFile.absolutePath].execute() + def process = ['nm', '-a', '-f', 'posix', binaryFile.absolutePath].execute(environments, null) def lines = process.inputStream.readLines() return lines.collect { line -> // Looks like: @@ -71,14 +73,17 @@ class OtoolBinaryInfo implements BinaryInfo { } List listDwarfSymbols() { - def process = ['dwarfdump', '--diff', binaryFile.absolutePath].execute() + def process = ['dwarfdump', '--diff', binaryFile.absolutePath].execute(environments, null) def lines = process.inputStream.readLines() def symbols = [] lines.each { line -> - def findSymbol = (line =~ /.*AT_name\(\s+"(.*)"\s+\)/) + // The output changed on Apple toolchain (Xcode): + // 10.1 and earlier: ` AT_name( "<...>" )` + // 10.2 (and maybe later): ` DW_AT_NAME ("<...>")` + def findSymbol = (line =~ /.*(DW_)?AT_name\s*\(\s*"(.*)"\s*\)/) if (findSymbol.matches()) { - def name = new File(findSymbol[0][1] as String).name.trim() + def name = new File(findSymbol[0][2] as String).name.trim() symbols << new BinaryInfo.Symbol(name, 'D' as char, true) } } @@ -86,7 +91,7 @@ class OtoolBinaryInfo implements BinaryInfo { } String getSoName() { - def process = ['otool', '-D', binaryFile.absolutePath].execute() + def process = ['otool', '-D', binaryFile.absolutePath].execute(environments, null) def lines = process.inputStream.readLines() return lines[1] } diff --git a/subprojects/testing-native/src/integTest/groovy/org/gradle/nativeplatform/test/xctest/AbstractSwiftXCTestComponentIntegrationTest.groovy b/subprojects/testing-native/src/integTest/groovy/org/gradle/nativeplatform/test/xctest/AbstractSwiftXCTestComponentIntegrationTest.groovy index fb12eb2f3d09a..3cf47452cc398 100644 --- a/subprojects/testing-native/src/integTest/groovy/org/gradle/nativeplatform/test/xctest/AbstractSwiftXCTestComponentIntegrationTest.groovy +++ b/subprojects/testing-native/src/integTest/groovy/org/gradle/nativeplatform/test/xctest/AbstractSwiftXCTestComponentIntegrationTest.groovy @@ -18,8 +18,10 @@ package org.gradle.nativeplatform.test.xctest import org.gradle.internal.os.OperatingSystem import org.gradle.language.swift.AbstractSwiftComponentIntegrationTest +import org.gradle.nativeplatform.fixtures.app.SourceElement import org.gradle.nativeplatform.fixtures.app.Swift3XCTest import org.gradle.nativeplatform.fixtures.app.Swift4XCTest +import org.gradle.nativeplatform.fixtures.app.Swift5XCTest import org.gradle.nativeplatform.fixtures.app.XCTestSourceElement import org.junit.Assume @@ -70,6 +72,11 @@ abstract class AbstractSwiftXCTestComponentIntegrationTest extends AbstractSwift return new Swift4XCTest('project') } + @Override + SourceElement getSwift5Component() { + return new Swift5XCTest('project') + } + @Override List getTasksToAssembleDevelopmentBinaryOfComponentUnderTest() { return [":compileTestSwift", ":linkTest", ":installTest", ":xcTest"] diff --git a/subprojects/testing-native/src/integTest/groovy/org/gradle/nativeplatform/test/xctest/AbstractSwiftXCTestComponentWithTestedComponentIntegrationTest.groovy b/subprojects/testing-native/src/integTest/groovy/org/gradle/nativeplatform/test/xctest/AbstractSwiftXCTestComponentWithTestedComponentIntegrationTest.groovy index 20f373f4a526b..1d31bcf2d98f1 100644 --- a/subprojects/testing-native/src/integTest/groovy/org/gradle/nativeplatform/test/xctest/AbstractSwiftXCTestComponentWithTestedComponentIntegrationTest.groovy +++ b/subprojects/testing-native/src/integTest/groovy/org/gradle/nativeplatform/test/xctest/AbstractSwiftXCTestComponentWithTestedComponentIntegrationTest.groovy @@ -21,9 +21,13 @@ import org.gradle.nativeplatform.fixtures.RequiresInstalledToolChain import org.gradle.nativeplatform.fixtures.ToolChainRequirement import org.gradle.nativeplatform.fixtures.app.Swift3WithSwift4XCTest import org.gradle.nativeplatform.fixtures.app.Swift4WithSwift3XCTest +import org.gradle.nativeplatform.fixtures.app.Swift5WithSwift4XCTest import spock.lang.Unroll +import static org.junit.Assume.assumeTrue + abstract class AbstractSwiftXCTestComponentWithTestedComponentIntegrationTest extends AbstractSwiftXCTestComponentIntegrationTest implements XCTestExecutionResult { + // TODO: This test can be generalized so it's not opinionated on Swift 4.x but could also work on Swift 5.x @RequiresInstalledToolChain(ToolChainRequirement.SWIFTC_4) def "take swift source compatibility from tested component"() { given: @@ -53,10 +57,11 @@ abstract class AbstractSwiftXCTestComponentWithTestedComponentIntegrationTest ex swift3Component.assertTestCasesRan(testExecutionResult) } - @RequiresInstalledToolChain(ToolChainRequirement.SWIFTC_4) @Unroll def "honors Swift source compatibility difference on both tested component (#componentSourceCompatibility) and XCTest component (#xctestSourceCompatibility)"() { given: + assumeSwiftCompilerSupportsLanguageVersion(componentSourceCompatibility) + assumeSwiftCompilerSupportsLanguageVersion(xctestSourceCompatibility) makeSingleProject() fixture.writeToProject(testDirectory) buildFile << """ @@ -85,9 +90,15 @@ abstract class AbstractSwiftXCTestComponentWithTestedComponentIntegrationTest ex fixture.assertTestCasesRan(testExecutionResult) where: - fixture | componentSourceCompatibility | xctestSourceCompatibility + fixture | componentSourceCompatibility | xctestSourceCompatibility new Swift3WithSwift4XCTest('project') | SwiftVersion.SWIFT3 | SwiftVersion.SWIFT4 new Swift4WithSwift3XCTest('project') | SwiftVersion.SWIFT4 | SwiftVersion.SWIFT3 + new Swift5WithSwift4XCTest('project') | SwiftVersion.SWIFT5 | SwiftVersion.SWIFT4 + } + + void assumeSwiftCompilerSupportsLanguageVersion(SwiftVersion swiftVersion) { + assert toolChain != null, "You need to specify Swift tool chain requirement with 'requireSwiftToolChain()'" + assumeTrue((toolChain.version.major == 5 && swiftVersion.version in [5, 4]) || (toolChain.version.major == 4 && swiftVersion.version in [4, 3]) || (toolChain.version.major == 3 && swiftVersion.version == 3)) } abstract String getTestedComponentDsl() From 2a8ffcef8cff2ca349c1838e434229a74d47a612 Mon Sep 17 00:00:00 2001 From: Sterling Greene Date: Fri, 29 Mar 2019 17:52:44 -0400 Subject: [PATCH 837/853] Remove commons-cli --- gradle/dependencies.gradle | 1 - .../java/org/gradle/api/internal/DefaultClassPathProvider.java | 3 --- .../groovy/org/gradle/DistributionIntegrationSpec.groovy | 2 +- subprojects/plugins/plugins.gradle | 2 -- 4 files changed, 1 insertion(+), 7 deletions(-) diff --git a/gradle/dependencies.gradle b/gradle/dependencies.gradle index 201f3fc45934c..4b6667adfadfc 100755 --- a/gradle/dependencies.gradle +++ b/gradle/dependencies.gradle @@ -44,7 +44,6 @@ libraries.bouncycastle_provider = [coordinates: 'org.bouncycastle:bcprov-jdk15on libraries.bouncycastle_pgp = [coordinates: 'org.bouncycastle:bcpg-jdk15on', version: libraries.bouncycastle_provider.version] libraries.bndlib = [coordinates: 'biz.aQute.bnd:biz.aQute.bndlib', version: '4.0.0'] libraries.bsh = [coordinates: 'org.apache-extras.beanshell:bsh', version: '2.0b6'] -libraries.commons_cli = [coordinates: 'commons-cli:commons-cli', version: '1.4'] libraries.commons_codec = [coordinates: 'commons-codec:commons-codec', version: '1.11'] libraries.commons_compress = [coordinates: 'org.apache.commons:commons-compress', version: '1.18'] libraries.commons_httpclient = [coordinates: 'org.apache.httpcomponents:httpclient', version: '4.5.6'] diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/DefaultClassPathProvider.java b/subprojects/core/src/main/java/org/gradle/api/internal/DefaultClassPathProvider.java index 5746767474af0..a89ac310da63d 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/DefaultClassPathProvider.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/DefaultClassPathProvider.java @@ -32,9 +32,6 @@ public ClassPath findClassPath(String name) { if (name.equals("GRADLE_INSTALLATION_BEACON")) { return moduleRegistry.getModule("gradle-installation-beacon").getImplementationClasspath(); } - if (name.equals("COMMONS_CLI")) { - return moduleRegistry.getExternalModule("commons-cli").getClasspath(); - } if (name.equals("ANT")) { ClassPath classpath = ClassPath.EMPTY; classpath = classpath.plus(moduleRegistry.getExternalModule("ant").getClasspath()); diff --git a/subprojects/distributions/src/integTest/groovy/org/gradle/DistributionIntegrationSpec.groovy b/subprojects/distributions/src/integTest/groovy/org/gradle/DistributionIntegrationSpec.groovy index 07a4ae2a7a11c..2574e2e693512 100644 --- a/subprojects/distributions/src/integTest/groovy/org/gradle/DistributionIntegrationSpec.groovy +++ b/subprojects/distributions/src/integTest/groovy/org/gradle/DistributionIntegrationSpec.groovy @@ -51,7 +51,7 @@ abstract class DistributionIntegrationSpec extends AbstractIntegrationSpec { * Change this if you added or removed dependencies. */ int getThirdPartyLibJarsCount() { - 178 + 177 } int getLibJarsCount() { diff --git a/subprojects/plugins/plugins.gradle b/subprojects/plugins/plugins.gradle index 4c6c105033f00..2622b07679568 100644 --- a/subprojects/plugins/plugins.gradle +++ b/subprojects/plugins/plugins.gradle @@ -38,8 +38,6 @@ dependencies { compile libraries.commons_lang.coordinates compile libraries.slf4j_api.coordinates - runtime libraries.commons_cli.coordinates - // This dependency makes the services provided by `:compositeBuilds` available at runtime for all integration tests in all subprojects // Making this better would likely involve a separate `:gradleRuntime` module that brings in `:core`, `:dependencyManagement` and other key subprojects runtime project(":compositeBuilds") From d3bf410e8c360d64b61aeb3f9c6426d4cf8ce66e Mon Sep 17 00:00:00 2001 From: Gradleware Git Bot Date: Fri, 29 Mar 2019 22:55:11 +0100 Subject: [PATCH 838/853] Publish 5.4-20190329214043+0000 --- released-versions.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/released-versions.json b/released-versions.json index 340eda80f191b..e2ad2505113d5 100644 --- a/released-versions.json +++ b/released-versions.json @@ -1,7 +1,7 @@ { "latestReleaseSnapshot": { - "version": "5.4-20190329080509+0000", - "buildTime": "20190329080509+0000" + "version": "5.4-20190329214043+0000", + "buildTime": "20190329214043+0000" }, "latestRc": { "version": "5.3-rc-3", From b063f6da075cef8a8e343ce7f0d6fd5ffb6d9fe7 Mon Sep 17 00:00:00 2001 From: Gradleware Git Bot Date: Sat, 30 Mar 2019 02:35:16 +0100 Subject: [PATCH 839/853] Publish 5.4-20190330012157+0000 --- released-versions.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/released-versions.json b/released-versions.json index e2ad2505113d5..00653928e04f0 100644 --- a/released-versions.json +++ b/released-versions.json @@ -1,7 +1,7 @@ { "latestReleaseSnapshot": { - "version": "5.4-20190329214043+0000", - "buildTime": "20190329214043+0000" + "version": "5.4-20190330012157+0000", + "buildTime": "20190330012157+0000" }, "latestRc": { "version": "5.3-rc-3", From badc9af8a42d17b7652b2cc13557bc84e76aab3c Mon Sep 17 00:00:00 2001 From: Sterling Greene Date: Fri, 29 Mar 2019 18:37:16 -0400 Subject: [PATCH 840/853] Use ExecFactory in context with a base directory for settings Before 5.3, settings.gradle's exec/javaexec were shared with FileOperations, which operated relative to rootDir. In 5.3, we accidentally switched to a different file resolver, which broke some people. --- ...tingsScriptExecutionIntegrationTest.groovy | 42 +++++++++++++++++++ .../gradle/groovy/scripts/DefaultScript.java | 6 ++- 2 files changed, 46 insertions(+), 2 deletions(-) diff --git a/subprojects/core/src/integTest/groovy/org/gradle/api/SettingsScriptExecutionIntegrationTest.groovy b/subprojects/core/src/integTest/groovy/org/gradle/api/SettingsScriptExecutionIntegrationTest.groovy index 4b5875ca60f42..7e6360faaa42c 100644 --- a/subprojects/core/src/integTest/groovy/org/gradle/api/SettingsScriptExecutionIntegrationTest.groovy +++ b/subprojects/core/src/integTest/groovy/org/gradle/api/SettingsScriptExecutionIntegrationTest.groovy @@ -18,7 +18,9 @@ package org.gradle.api import org.gradle.integtests.fixtures.AbstractIntegrationSpec import org.gradle.integtests.fixtures.FeaturePreviewsFixture import org.gradle.integtests.fixtures.executer.ArtifactBuilder +import org.gradle.internal.os.OperatingSystem import org.gradle.test.fixtures.file.TestFile +import spock.lang.Issue import spock.lang.Unroll class SettingsScriptExecutionIntegrationTest extends AbstractIntegrationSpec { @@ -42,6 +44,46 @@ class SettingsScriptExecutionIntegrationTest extends AbstractIntegrationSpec { feature << FeaturePreviewsFixture.inactiveFeatures() } + @Issue("https://github.com/gradle/gradle/issues/8840") + def "can use exec in settings"() { + addExecToScript(settingsFile) + when: + succeeds() + then: + outputContains("hello from settings") + } + + @Issue("https://github.com/gradle/gradle/issues/8840") + def "can use exec in settings applied from another script"() { + settingsFile << """ + apply from: 'other.gradle' + """ + addExecToScript(file("other.gradle")) + when: + succeeds() + then: + outputContains("hello from settings") + } + + private void addExecToScript(TestFile scriptFile) { + file("message") << """ + hello from settings + """ + if (OperatingSystem.current().windows) { + scriptFile << """ + exec { + commandLine "cmd", "/c", "type", "message" + } + """ + } else { + scriptFile << """ + exec { + commandLine "cat", "message" + } + """ + } + } + def "notices changes to settings scripts that do not change the file length"() { settingsFile.text = "println 'counter: __'" long before = settingsFile.length() diff --git a/subprojects/core/src/main/java/org/gradle/groovy/scripts/DefaultScript.java b/subprojects/core/src/main/java/org/gradle/groovy/scripts/DefaultScript.java index c9eb16a624962..997b11894c721 100755 --- a/subprojects/core/src/main/java/org/gradle/groovy/scripts/DefaultScript.java +++ b/subprojects/core/src/main/java/org/gradle/groovy/scripts/DefaultScript.java @@ -97,11 +97,13 @@ public void init(final Object target, ServiceRegistry services) { File sourceFile = getScriptSource().getResource().getLocation().getFile(); if (sourceFile != null) { FileResolver resolver = fileLookup.getFileResolver(sourceFile.getParentFile()); - fileOperations = new DefaultFileOperations(resolver, null, null, instantiator, fileLookup, directoryFileTreeFactory, streamHasher, fileHasher, textResourceLoader, new DefaultFileCollectionFactory(resolver, null), fileSystem, clock); + DefaultFileCollectionFactory fileCollectionFactoryWithBase = new DefaultFileCollectionFactory(resolver, null); + fileOperations = new DefaultFileOperations(resolver, null, null, instantiator, fileLookup, directoryFileTreeFactory, streamHasher, fileHasher, textResourceLoader, fileCollectionFactoryWithBase, fileSystem, clock); + processOperations = services.get(ExecFactory.class).forContext(resolver, fileCollectionFactoryWithBase, instantiator); } else { fileOperations = new DefaultFileOperations(fileLookup.getFileResolver(), null, null, instantiator, fileLookup, directoryFileTreeFactory, streamHasher, fileHasher, textResourceLoader, fileCollectionFactory, fileSystem, clock); + processOperations = services.get(ExecFactory.class); } - processOperations = services.get(ExecFactory.class); } providerFactory = services.get(ProviderFactory.class); From 8cf5127fabaa1469678b08187bdf7e83e02d8aa8 Mon Sep 17 00:00:00 2001 From: Gradleware Git Bot Date: Sun, 31 Mar 2019 03:22:37 +0200 Subject: [PATCH 841/853] Publish 5.4-20190331010914+0000 --- released-versions.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/released-versions.json b/released-versions.json index 00653928e04f0..a59330f200979 100644 --- a/released-versions.json +++ b/released-versions.json @@ -1,7 +1,7 @@ { "latestReleaseSnapshot": { - "version": "5.4-20190330012157+0000", - "buildTime": "20190330012157+0000" + "version": "5.4-20190331010914+0000", + "buildTime": "20190331010914+0000" }, "latestRc": { "version": "5.3-rc-3", From 8527d3f4694f9e63147d96a71ed8bd3fe0ccf0c5 Mon Sep 17 00:00:00 2001 From: Gradleware Git Bot Date: Mon, 1 Apr 2019 03:14:22 +0200 Subject: [PATCH 842/853] Publish 5.4-20190401010050+0000 --- released-versions.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/released-versions.json b/released-versions.json index a59330f200979..a85002d3e756b 100644 --- a/released-versions.json +++ b/released-versions.json @@ -1,7 +1,7 @@ { "latestReleaseSnapshot": { - "version": "5.4-20190331010914+0000", - "buildTime": "20190331010914+0000" + "version": "5.4-20190401010050+0000", + "buildTime": "20190401010050+0000" }, "latestRc": { "version": "5.3-rc-3", From 0fbe87fad31b1e45ee8d09a28fe3284a65b9a0f1 Mon Sep 17 00:00:00 2001 From: Daniel Lacasse Date: Mon, 1 Apr 2019 09:57:23 +0200 Subject: [PATCH 843/853] Mention Swift 5 support in release note Also point to native release notes. --- subprojects/docs/src/docs/release/notes.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/subprojects/docs/src/docs/release/notes.md b/subprojects/docs/src/docs/release/notes.md index 23c7029412fcb..6a88844141419 100644 --- a/subprojects/docs/src/docs/release/notes.md +++ b/subprojects/docs/src/docs/release/notes.md @@ -30,6 +30,16 @@ Switch your build to use Gradle @version@ by updating your wrapper properties: `./gradlew wrapper --gradle-version=@version@` +## Building native software with Gradle + +See more information about the [Gradle native project](https://github.com/gradle/gradle-native/blob/master/docs/RELEASE-NOTES.md#changes-included-in-gradle-54). + +### Swift 5 Support + +Gradle now supports [Swift 5](https://swift.org/blog/swift-5-released/) officially [release with the Xcode 10.2](https://developer.apple.com/documentation/xcode_release_notes/xcode_10_2_release_notes). +Specifying the source compatibility to Swift 5 instruct the compiler to expect Swift 5 compatible source file. +Have a look at the [Swift samples](https://github.com/gradle/native-samples) to learn more about common use cases. + ## Support for JDK12 Gradle now supports running on [JDK12](https://jdk.java.net/12/). From 45b63d909b314b65c344c9cb63f7c42de997d59c Mon Sep 17 00:00:00 2001 From: Stefan Wolf Date: Mon, 1 Apr 2019 10:40:48 +0200 Subject: [PATCH 844/853] Fix non-cacheable reason when scan plugin is applied (#8908) --- ...skCacheabilityReasonIntegrationTest.groovy | 21 ++++--- .../steps/ResolveCachingStateStep.java | 2 +- .../steps/ResolveCachingStateStepTest.groovy | 63 +++++++++++++++++++ 3 files changed, 78 insertions(+), 8 deletions(-) create mode 100644 subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/ResolveCachingStateStepTest.groovy diff --git a/subprojects/core/src/integTest/groovy/org/gradle/api/internal/tasks/TaskCacheabilityReasonIntegrationTest.groovy b/subprojects/core/src/integTest/groovy/org/gradle/api/internal/tasks/TaskCacheabilityReasonIntegrationTest.groovy index 3f04b18fdca50..c919792b2ddcf 100644 --- a/subprojects/core/src/integTest/groovy/org/gradle/api/internal/tasks/TaskCacheabilityReasonIntegrationTest.groovy +++ b/subprojects/core/src/integTest/groovy/org/gradle/api/internal/tasks/TaskCacheabilityReasonIntegrationTest.groovy @@ -56,6 +56,12 @@ class TaskCacheabilityReasonIntegrationTest extends AbstractIntegrationSpec impl @CacheableTask class Cacheable extends NotCacheable {} + + class NoOutputs extends DefaultTask { + @TaskAction + void generate() {} + } + """ } @@ -63,6 +69,7 @@ class TaskCacheabilityReasonIntegrationTest extends AbstractIntegrationSpec impl buildFile << """ task cacheable(type: Cacheable) {} task notcacheable(type: NotCacheable) {} + task noOutputs(type: NoOutputs) {} """ when: run "cacheable" @@ -73,6 +80,11 @@ class TaskCacheabilityReasonIntegrationTest extends AbstractIntegrationSpec impl run "notcacheable" then: assertCachingDisabledFor BUILD_CACHE_DISABLED, "Build cache is disabled" + + when: + run "noOutputs" + then: + assertCachingDisabledFor BUILD_CACHE_DISABLED, "Build cache is disabled" } def "cacheability for non-cacheable task is NOT_ENABLED_FOR_TASK"() { @@ -98,12 +110,12 @@ class TaskCacheabilityReasonIntegrationTest extends AbstractIntegrationSpec impl def "cacheability for a cacheable task with no outputs is NO_OUTPUTS_DECLARED"() { buildFile << """ @CacheableTask - class NoOutputs extends DefaultTask { + class CacheableNoOutputs extends DefaultTask { @TaskAction void generate() {} } - task noOutputs(type: NoOutputs) {} + task noOutputs(type: CacheableNoOutputs) {} """ when: withBuildCache().run "noOutputs" @@ -113,11 +125,6 @@ class TaskCacheabilityReasonIntegrationTest extends AbstractIntegrationSpec impl def "cacheability for a non-cacheable task with no outputs is NOT_ENABLED_FOR_TASK"() { buildFile << """ - class NoOutputs extends DefaultTask { - @TaskAction - void generate() {} - } - task noOutputs(type: NoOutputs) {} """ when: diff --git a/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/ResolveCachingStateStep.java b/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/ResolveCachingStateStep.java index b16d6046772c7..76e5e00d27262 100644 --- a/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/ResolveCachingStateStep.java +++ b/subprojects/execution/src/main/java/org/gradle/internal/execution/steps/ResolveCachingStateStep.java @@ -73,7 +73,7 @@ public CachingResult execute(IncrementalContext context) { } else { cachingState = context.getBeforeExecutionState() .map(beforeExecutionState -> calculateCachingState(beforeExecutionState, work)) - .orElseGet(() -> work.shouldDisableCaching() + .orElseGet(() -> (buildCache.isEnabled() ? work.shouldDisableCaching() : Optional.of(BUILD_CACHE_DISABLED_REASON)) .map(disabledReason -> CachingState.disabledWithoutInputs(disabledReason)) .orElse(CachingState.NOT_DETERMINED) ); diff --git a/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/ResolveCachingStateStepTest.groovy b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/ResolveCachingStateStepTest.groovy new file mode 100644 index 0000000000000..037f30cdf8751 --- /dev/null +++ b/subprojects/execution/src/test/groovy/org/gradle/internal/execution/steps/ResolveCachingStateStepTest.groovy @@ -0,0 +1,63 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.internal.execution.steps + + +import org.gradle.caching.internal.controller.BuildCacheController +import org.gradle.internal.execution.CachingContext +import org.gradle.internal.execution.IncrementalContext +import org.gradle.internal.execution.Step +import org.gradle.internal.execution.UnitOfWork +import org.gradle.internal.execution.caching.CachingDisabledReason +import org.gradle.internal.execution.caching.CachingDisabledReasonCategory +import spock.lang.Specification + +class ResolveCachingStateStepTest extends Specification { + + def work = Mock(UnitOfWork) + def context = Mock(IncrementalContext) + def buildCache = Mock(BuildCacheController) + def delegateStep = Mock(Step) + + def step = new ResolveCachingStateStep(buildCache, true, delegateStep) + + def "build cache disabled reason is reported when build cache is disabled"() { + when: + step.execute(context) + then: + _ * buildCache.enabled >> false + 1 * context.beforeExecutionState >> Optional.empty() + 1 * delegateStep.execute(_) >> { CachingContext context -> + assert context.cachingState.disabledReasons.get(0).category == CachingDisabledReasonCategory.BUILD_CACHE_DISABLED + } + } + + def "build cache disabled reason is determined without execution state"() { + def disabledReason = new CachingDisabledReason(CachingDisabledReasonCategory.DISABLE_CONDITION_SATISFIED, "Something disabled") + + when: + step.execute(context) + then: + _ * buildCache.enabled >> true + 1 * context.beforeExecutionState >> Optional.empty() + 1 * context.work >> work + 1 * work.shouldDisableCaching() >> Optional.of(disabledReason) + 1 * delegateStep.execute(_) >> { CachingContext context -> + assert context.cachingState.disabledReasons.get(0) == disabledReason + } + } +} From 0c708fe08a8492035da48d09ac84b87c19bcabc1 Mon Sep 17 00:00:00 2001 From: Donat Csikos Date: Mon, 1 Apr 2019 10:49:57 +0200 Subject: [PATCH 845/853] Use Java 12 for TC build pipeline --- .teamcity/common/JvmCategory.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.teamcity/common/JvmCategory.kt b/.teamcity/common/JvmCategory.kt index 8776ee5cf8761..2280ef02bb942 100644 --- a/.teamcity/common/JvmCategory.kt +++ b/.teamcity/common/JvmCategory.kt @@ -18,6 +18,6 @@ package common enum class JvmCategory(val vendor: JvmVendor, val version: JvmVersion) { MIN_VERSION(JvmVendor.oracle, JvmVersion.java8), - MAX_VERSION(JvmVendor.openjdk, JvmVersion.java11), + MAX_VERSION(JvmVendor.openjdk, JvmVersion.java12), EXPERIMENTAL_VERSION(JvmVendor.openjdk, JvmVersion.java12) } From 0b36ba8c396749aea267e8a659dd4cd1c826856c Mon Sep 17 00:00:00 2001 From: Donat Csikos Date: Mon, 1 Apr 2019 10:49:57 +0200 Subject: [PATCH 846/853] Use Java 12 for TC build pipeline --- .teamcity/common/JvmCategory.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.teamcity/common/JvmCategory.kt b/.teamcity/common/JvmCategory.kt index 8776ee5cf8761..2280ef02bb942 100644 --- a/.teamcity/common/JvmCategory.kt +++ b/.teamcity/common/JvmCategory.kt @@ -18,6 +18,6 @@ package common enum class JvmCategory(val vendor: JvmVendor, val version: JvmVersion) { MIN_VERSION(JvmVendor.oracle, JvmVersion.java8), - MAX_VERSION(JvmVendor.openjdk, JvmVersion.java11), + MAX_VERSION(JvmVendor.openjdk, JvmVersion.java12), EXPERIMENTAL_VERSION(JvmVendor.openjdk, JvmVersion.java12) } From eb57579621d266f458e7eb0c510629d025f80ae6 Mon Sep 17 00:00:00 2001 From: Donat Csikos Date: Mon, 1 Apr 2019 15:06:50 +0200 Subject: [PATCH 847/853] Add method to EclipseProject to query whether there are auto-build tasks configured --- ...ModelAutoBuildTasksCrossVersionSpec.groovy | 61 +++++++++++++++++++ .../internal/tooling/EclipseModelBuilder.java | 1 + .../eclipse/DefaultEclipseProject.java | 9 +++ .../connection/HasCompatibilityMapping.java | 3 + .../EclipseProjectHasAutoBuildMixin.java | 32 ++++++++++ .../tooling/model/eclipse/EclipseProject.java | 10 +++ 6 files changed, 116 insertions(+) create mode 100644 subprojects/ide/src/crossVersionTest/groovy/org/gradle/plugins/ide/tooling/r54/ToolingApiEclipseModelAutoBuildTasksCrossVersionSpec.groovy create mode 100644 subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/converters/EclipseProjectHasAutoBuildMixin.java diff --git a/subprojects/ide/src/crossVersionTest/groovy/org/gradle/plugins/ide/tooling/r54/ToolingApiEclipseModelAutoBuildTasksCrossVersionSpec.groovy b/subprojects/ide/src/crossVersionTest/groovy/org/gradle/plugins/ide/tooling/r54/ToolingApiEclipseModelAutoBuildTasksCrossVersionSpec.groovy new file mode 100644 index 0000000000000..84f27e2653422 --- /dev/null +++ b/subprojects/ide/src/crossVersionTest/groovy/org/gradle/plugins/ide/tooling/r54/ToolingApiEclipseModelAutoBuildTasksCrossVersionSpec.groovy @@ -0,0 +1,61 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.plugins.ide.tooling.r54 + +import org.gradle.integtests.tooling.fixture.TargetGradleVersion +import org.gradle.integtests.tooling.fixture.ToolingApiSpecification +import org.gradle.integtests.tooling.fixture.ToolingApiVersion +import org.gradle.tooling.model.eclipse.EclipseProject + +@ToolingApiVersion('>=5.4') +@TargetGradleVersion('>=5.4') +class ToolingApiEclipseModelAutoBuildTasksCrossVersionSpec extends ToolingApiSpecification { + + @TargetGradleVersion('>=2.6 <5.4') + def "returns false for old versions"() { + setup: + EclipseProject eclipseProject = loadToolingModel(EclipseProject) + + expect: + !eclipseProject.hasAutoBuildTasks() + } + + def "can query if Eclipse model contains tasks configured for auto-sync"() { + when: + EclipseProject eclipseProject = loadToolingModel(EclipseProject) + + then: + !eclipseProject.hasAutoBuildTasks() + + when: + buildFile << """ + plugins { + id 'eclipse' + } + + task foo { } + + eclipse { + autoBuildTasks foo + } + """ + eclipseProject = loadToolingModel(EclipseProject) + + then: + eclipseProject.hasAutoBuildTasks() + } +} diff --git a/subprojects/ide/src/main/java/org/gradle/plugins/ide/internal/tooling/EclipseModelBuilder.java b/subprojects/ide/src/main/java/org/gradle/plugins/ide/internal/tooling/EclipseModelBuilder.java index 1379ede16ce7d..f413b6c39bef3 100644 --- a/subprojects/ide/src/main/java/org/gradle/plugins/ide/internal/tooling/EclipseModelBuilder.java +++ b/subprojects/ide/src/main/java/org/gradle/plugins/ide/internal/tooling/EclipseModelBuilder.java @@ -203,6 +203,7 @@ private void populate(Project project) { eclipseProject.setSourceDirectories(sourceDirectories); eclipseProject.setClasspathContainers(classpathContainers); eclipseProject.setOutputLocation(outputLocation != null ? outputLocation : new DefaultEclipseOutputLocation("bin")); + eclipseProject.setAutoBuildTasks(!eclipseModel.getAutoBuildTasks().getDependencies(null).isEmpty()); org.gradle.plugins.ide.eclipse.model.Project xmlProject = new org.gradle.plugins.ide.eclipse.model.Project(new XmlTransformer()); diff --git a/subprojects/ide/src/main/java/org/gradle/plugins/ide/internal/tooling/eclipse/DefaultEclipseProject.java b/subprojects/ide/src/main/java/org/gradle/plugins/ide/internal/tooling/eclipse/DefaultEclipseProject.java index d7095caa44ac7..01fee29be4c71 100644 --- a/subprojects/ide/src/main/java/org/gradle/plugins/ide/internal/tooling/eclipse/DefaultEclipseProject.java +++ b/subprojects/ide/src/main/java/org/gradle/plugins/ide/internal/tooling/eclipse/DefaultEclipseProject.java @@ -46,6 +46,7 @@ public class DefaultEclipseProject implements Serializable, GradleProjectIdentit private DefaultEclipseJavaSourceSettings javaSourceSettings; private List classpathContainers; private DefaultEclipseOutputLocation outputLocation; + private boolean hasAutoBuildTasks; public DefaultEclipseProject(String name, String path, String description, File projectDirectory, Iterable children) { this.name = name; @@ -197,4 +198,12 @@ public String getProjectPath() { public File getRootDir() { return getProjectIdentifier().getBuildIdentifier().getRootDir(); } + + public boolean hasAutoBuildTasks() { + return hasAutoBuildTasks; + } + + public void setAutoBuildTasks(boolean hasAutoBuildTasks) { + this.hasAutoBuildTasks = hasAutoBuildTasks; + } } diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/connection/HasCompatibilityMapping.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/connection/HasCompatibilityMapping.java index 28f452c407dcf..e12c423633853 100644 --- a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/connection/HasCompatibilityMapping.java +++ b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/connection/HasCompatibilityMapping.java @@ -18,6 +18,7 @@ import org.gradle.tooling.internal.adapter.ViewBuilder; import org.gradle.tooling.internal.consumer.converters.BasicGradleProjectIdentifierMixin; +import org.gradle.tooling.internal.consumer.converters.EclipseProjectHasAutoBuildMixin; import org.gradle.tooling.internal.consumer.converters.FixedBuildIdentifierProvider; import org.gradle.tooling.internal.consumer.converters.GradleProjectIdentifierMixin; import org.gradle.tooling.internal.consumer.converters.IdeaModuleDependencyTargetNameMixin; @@ -26,6 +27,7 @@ import org.gradle.tooling.internal.consumer.parameters.ConsumerOperationParameters; import org.gradle.tooling.internal.gradle.DefaultProjectIdentifier; import org.gradle.tooling.model.GradleProject; +import org.gradle.tooling.model.eclipse.EclipseProject; import org.gradle.tooling.model.gradle.BasicGradleProject; import org.gradle.tooling.model.gradle.GradleBuild; import org.gradle.tooling.model.idea.IdeaDependency; @@ -46,6 +48,7 @@ public ViewBuilder applyCompatibilityMapping(ViewBuilder viewBuilder, viewBuilder.mixInTo(IdeaProject.class, IdeaProjectJavaLanguageSettingsMixin.class); viewBuilder.mixInTo(IdeaDependency.class, IdeaModuleDependencyTargetNameMixin.class); viewBuilder.mixInTo(GradleBuild.class, IncludedBuildsMixin.class); + viewBuilder.mixInTo(EclipseProject.class, EclipseProjectHasAutoBuildMixin.class); return viewBuilder; } } diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/converters/EclipseProjectHasAutoBuildMixin.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/converters/EclipseProjectHasAutoBuildMixin.java new file mode 100644 index 0000000000000..92266b7839400 --- /dev/null +++ b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/converters/EclipseProjectHasAutoBuildMixin.java @@ -0,0 +1,32 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.tooling.internal.consumer.converters; + +import org.gradle.tooling.model.eclipse.EclipseProject; + +/** + * This is used for compatibility with clients <5.4 + */ +public class EclipseProjectHasAutoBuildMixin { + + public EclipseProjectHasAutoBuildMixin(EclipseProject eclipseProject) { + } + + public boolean hasAutoBuildTasks() { + return false; + } +} diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/model/eclipse/EclipseProject.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/model/eclipse/EclipseProject.java index 26bc664aff5e0..8b331757f4890 100644 --- a/subprojects/tooling-api/src/main/java/org/gradle/tooling/model/eclipse/EclipseProject.java +++ b/subprojects/tooling-api/src/main/java/org/gradle/tooling/model/eclipse/EclipseProject.java @@ -118,4 +118,14 @@ public interface EclipseProject extends HierarchicalEclipseProject { * @throws UnsupportedMethodException For Gradle versions older than 3.0, where this method is not supported. */ EclipseOutputLocation getOutputLocation() throws UnsupportedMethodException; + + /** + * If this method returns true then Eclipse should execute the tasks configured at {@code eclipse.autoBuildTasks} + * every time the auto-build is triggered for the target project. + * + * @return whether the project has auto-build tasks configured + * @since 5.4 + * @see RunEclipseAutoBuildTasks + */ + boolean hasAutoBuildTasks(); } From 0d6ef2084de8aaf8b8a1c6a8173a3a17899901fc Mon Sep 17 00:00:00 2001 From: Donat Csikos Date: Mon, 1 Apr 2019 15:17:37 +0200 Subject: [PATCH 848/853] Fix ParallelTestTaskIntegrationTest test failure --- .../org/gradle/java/ParallelTestTaskIntegrationTest.groovy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subprojects/plugins/src/integTest/groovy/org/gradle/java/ParallelTestTaskIntegrationTest.groovy b/subprojects/plugins/src/integTest/groovy/org/gradle/java/ParallelTestTaskIntegrationTest.groovy index f163ce4d12fd4..9e331d13b3464 100644 --- a/subprojects/plugins/src/integTest/groovy/org/gradle/java/ParallelTestTaskIntegrationTest.groovy +++ b/subprojects/plugins/src/integTest/groovy/org/gradle/java/ParallelTestTaskIntegrationTest.groovy @@ -30,7 +30,7 @@ import java.util.concurrent.CountDownLatch @IgnoreIf({ !GradleContextualExecuter.isParallel() }) class ParallelTestTaskIntegrationTest extends AbstractIntegrationSpec { String getVersion() { - return "1.6" + return "1.7" } JavaVersion getJavaVersion() { From 45725539675c413109bdacb2bc1ff74ea2d1bea2 Mon Sep 17 00:00:00 2001 From: Donat Csikos Date: Mon, 1 Apr 2019 16:47:49 +0200 Subject: [PATCH 849/853] Revert "Add method to EclipseProject to query whether there are auto-build tasks configured" This reverts commit eb57579621d266f458e7eb0c510629d025f80ae6. --- ...ModelAutoBuildTasksCrossVersionSpec.groovy | 61 ------------------- .../internal/tooling/EclipseModelBuilder.java | 1 - .../eclipse/DefaultEclipseProject.java | 9 --- .../connection/HasCompatibilityMapping.java | 3 - .../EclipseProjectHasAutoBuildMixin.java | 32 ---------- .../tooling/model/eclipse/EclipseProject.java | 10 --- 6 files changed, 116 deletions(-) delete mode 100644 subprojects/ide/src/crossVersionTest/groovy/org/gradle/plugins/ide/tooling/r54/ToolingApiEclipseModelAutoBuildTasksCrossVersionSpec.groovy delete mode 100644 subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/converters/EclipseProjectHasAutoBuildMixin.java diff --git a/subprojects/ide/src/crossVersionTest/groovy/org/gradle/plugins/ide/tooling/r54/ToolingApiEclipseModelAutoBuildTasksCrossVersionSpec.groovy b/subprojects/ide/src/crossVersionTest/groovy/org/gradle/plugins/ide/tooling/r54/ToolingApiEclipseModelAutoBuildTasksCrossVersionSpec.groovy deleted file mode 100644 index 84f27e2653422..0000000000000 --- a/subprojects/ide/src/crossVersionTest/groovy/org/gradle/plugins/ide/tooling/r54/ToolingApiEclipseModelAutoBuildTasksCrossVersionSpec.groovy +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright 2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.gradle.plugins.ide.tooling.r54 - -import org.gradle.integtests.tooling.fixture.TargetGradleVersion -import org.gradle.integtests.tooling.fixture.ToolingApiSpecification -import org.gradle.integtests.tooling.fixture.ToolingApiVersion -import org.gradle.tooling.model.eclipse.EclipseProject - -@ToolingApiVersion('>=5.4') -@TargetGradleVersion('>=5.4') -class ToolingApiEclipseModelAutoBuildTasksCrossVersionSpec extends ToolingApiSpecification { - - @TargetGradleVersion('>=2.6 <5.4') - def "returns false for old versions"() { - setup: - EclipseProject eclipseProject = loadToolingModel(EclipseProject) - - expect: - !eclipseProject.hasAutoBuildTasks() - } - - def "can query if Eclipse model contains tasks configured for auto-sync"() { - when: - EclipseProject eclipseProject = loadToolingModel(EclipseProject) - - then: - !eclipseProject.hasAutoBuildTasks() - - when: - buildFile << """ - plugins { - id 'eclipse' - } - - task foo { } - - eclipse { - autoBuildTasks foo - } - """ - eclipseProject = loadToolingModel(EclipseProject) - - then: - eclipseProject.hasAutoBuildTasks() - } -} diff --git a/subprojects/ide/src/main/java/org/gradle/plugins/ide/internal/tooling/EclipseModelBuilder.java b/subprojects/ide/src/main/java/org/gradle/plugins/ide/internal/tooling/EclipseModelBuilder.java index f413b6c39bef3..1379ede16ce7d 100644 --- a/subprojects/ide/src/main/java/org/gradle/plugins/ide/internal/tooling/EclipseModelBuilder.java +++ b/subprojects/ide/src/main/java/org/gradle/plugins/ide/internal/tooling/EclipseModelBuilder.java @@ -203,7 +203,6 @@ private void populate(Project project) { eclipseProject.setSourceDirectories(sourceDirectories); eclipseProject.setClasspathContainers(classpathContainers); eclipseProject.setOutputLocation(outputLocation != null ? outputLocation : new DefaultEclipseOutputLocation("bin")); - eclipseProject.setAutoBuildTasks(!eclipseModel.getAutoBuildTasks().getDependencies(null).isEmpty()); org.gradle.plugins.ide.eclipse.model.Project xmlProject = new org.gradle.plugins.ide.eclipse.model.Project(new XmlTransformer()); diff --git a/subprojects/ide/src/main/java/org/gradle/plugins/ide/internal/tooling/eclipse/DefaultEclipseProject.java b/subprojects/ide/src/main/java/org/gradle/plugins/ide/internal/tooling/eclipse/DefaultEclipseProject.java index 01fee29be4c71..d7095caa44ac7 100644 --- a/subprojects/ide/src/main/java/org/gradle/plugins/ide/internal/tooling/eclipse/DefaultEclipseProject.java +++ b/subprojects/ide/src/main/java/org/gradle/plugins/ide/internal/tooling/eclipse/DefaultEclipseProject.java @@ -46,7 +46,6 @@ public class DefaultEclipseProject implements Serializable, GradleProjectIdentit private DefaultEclipseJavaSourceSettings javaSourceSettings; private List classpathContainers; private DefaultEclipseOutputLocation outputLocation; - private boolean hasAutoBuildTasks; public DefaultEclipseProject(String name, String path, String description, File projectDirectory, Iterable children) { this.name = name; @@ -198,12 +197,4 @@ public String getProjectPath() { public File getRootDir() { return getProjectIdentifier().getBuildIdentifier().getRootDir(); } - - public boolean hasAutoBuildTasks() { - return hasAutoBuildTasks; - } - - public void setAutoBuildTasks(boolean hasAutoBuildTasks) { - this.hasAutoBuildTasks = hasAutoBuildTasks; - } } diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/connection/HasCompatibilityMapping.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/connection/HasCompatibilityMapping.java index e12c423633853..28f452c407dcf 100644 --- a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/connection/HasCompatibilityMapping.java +++ b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/connection/HasCompatibilityMapping.java @@ -18,7 +18,6 @@ import org.gradle.tooling.internal.adapter.ViewBuilder; import org.gradle.tooling.internal.consumer.converters.BasicGradleProjectIdentifierMixin; -import org.gradle.tooling.internal.consumer.converters.EclipseProjectHasAutoBuildMixin; import org.gradle.tooling.internal.consumer.converters.FixedBuildIdentifierProvider; import org.gradle.tooling.internal.consumer.converters.GradleProjectIdentifierMixin; import org.gradle.tooling.internal.consumer.converters.IdeaModuleDependencyTargetNameMixin; @@ -27,7 +26,6 @@ import org.gradle.tooling.internal.consumer.parameters.ConsumerOperationParameters; import org.gradle.tooling.internal.gradle.DefaultProjectIdentifier; import org.gradle.tooling.model.GradleProject; -import org.gradle.tooling.model.eclipse.EclipseProject; import org.gradle.tooling.model.gradle.BasicGradleProject; import org.gradle.tooling.model.gradle.GradleBuild; import org.gradle.tooling.model.idea.IdeaDependency; @@ -48,7 +46,6 @@ public ViewBuilder applyCompatibilityMapping(ViewBuilder viewBuilder, viewBuilder.mixInTo(IdeaProject.class, IdeaProjectJavaLanguageSettingsMixin.class); viewBuilder.mixInTo(IdeaDependency.class, IdeaModuleDependencyTargetNameMixin.class); viewBuilder.mixInTo(GradleBuild.class, IncludedBuildsMixin.class); - viewBuilder.mixInTo(EclipseProject.class, EclipseProjectHasAutoBuildMixin.class); return viewBuilder; } } diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/converters/EclipseProjectHasAutoBuildMixin.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/converters/EclipseProjectHasAutoBuildMixin.java deleted file mode 100644 index 92266b7839400..0000000000000 --- a/subprojects/tooling-api/src/main/java/org/gradle/tooling/internal/consumer/converters/EclipseProjectHasAutoBuildMixin.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.gradle.tooling.internal.consumer.converters; - -import org.gradle.tooling.model.eclipse.EclipseProject; - -/** - * This is used for compatibility with clients <5.4 - */ -public class EclipseProjectHasAutoBuildMixin { - - public EclipseProjectHasAutoBuildMixin(EclipseProject eclipseProject) { - } - - public boolean hasAutoBuildTasks() { - return false; - } -} diff --git a/subprojects/tooling-api/src/main/java/org/gradle/tooling/model/eclipse/EclipseProject.java b/subprojects/tooling-api/src/main/java/org/gradle/tooling/model/eclipse/EclipseProject.java index 8b331757f4890..26bc664aff5e0 100644 --- a/subprojects/tooling-api/src/main/java/org/gradle/tooling/model/eclipse/EclipseProject.java +++ b/subprojects/tooling-api/src/main/java/org/gradle/tooling/model/eclipse/EclipseProject.java @@ -118,14 +118,4 @@ public interface EclipseProject extends HierarchicalEclipseProject { * @throws UnsupportedMethodException For Gradle versions older than 3.0, where this method is not supported. */ EclipseOutputLocation getOutputLocation() throws UnsupportedMethodException; - - /** - * If this method returns true then Eclipse should execute the tasks configured at {@code eclipse.autoBuildTasks} - * every time the auto-build is triggered for the target project. - * - * @return whether the project has auto-build tasks configured - * @since 5.4 - * @see RunEclipseAutoBuildTasks - */ - boolean hasAutoBuildTasks(); } From 678cfc199d1d5bd8f64ec48587fe55e02ab81c50 Mon Sep 17 00:00:00 2001 From: Gradleware Git Bot Date: Mon, 1 Apr 2019 22:55:15 +0200 Subject: [PATCH 850/853] Publish 5.4-20190401204159+0000 --- released-versions.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/released-versions.json b/released-versions.json index a85002d3e756b..a969a43d61ce8 100644 --- a/released-versions.json +++ b/released-versions.json @@ -1,7 +1,7 @@ { "latestReleaseSnapshot": { - "version": "5.4-20190401010050+0000", - "buildTime": "20190401010050+0000" + "version": "5.4-20190401204159+0000", + "buildTime": "20190401204159+0000" }, "latestRc": { "version": "5.3-rc-3", From 531f749c62b5567543f6edde8973c47e76e3e360 Mon Sep 17 00:00:00 2001 From: Gradleware Git Bot Date: Tue, 2 Apr 2019 03:26:03 +0200 Subject: [PATCH 851/853] Publish 5.4-20190402011228+0000 --- released-versions.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/released-versions.json b/released-versions.json index a969a43d61ce8..88c10471f30c3 100644 --- a/released-versions.json +++ b/released-versions.json @@ -1,7 +1,7 @@ { "latestReleaseSnapshot": { - "version": "5.4-20190401204159+0000", - "buildTime": "20190401204159+0000" + "version": "5.4-20190402011228+0000", + "buildTime": "20190402011228+0000" }, "latestRc": { "version": "5.3-rc-3", From d681896f6730f5710163ab99a73755a7c8b3b1b6 Mon Sep 17 00:00:00 2001 From: Bo Zhang Date: Tue, 2 Apr 2019 14:47:05 +0800 Subject: [PATCH 852/853] Report flaky performance test to issue tracker (#8870) This closes https://github.com/gradle/gradle-private/issues/1793 We want to report flaky performance scenarios to private issue tracker, as we did for all other functional flaky tests. This PR adds a step to `FlakinessReportGenerator`, which creates/comments issues in `gradle-private`. --- .../testing/DistributedPerformanceTest.groovy | 10 +- .../ReportGenerationPerformanceTest.groovy | 4 + .../internal-performance-testing.gradle.kts | 3 +- .../results/AbstractTablePageGenerator.java | 2 - .../results/FlakinessIndexPageGenerator.java | 10 +- .../results/FlakinessIssueReporter.groovy | 109 +++++++++++++++ .../results/FlakinessReportGenerator.java | 9 +- .../results/ScenarioBuildResultData.groovy | 7 + .../results/FlakinessIssueReporterTest.groovy | 125 ++++++++++++++++++ 9 files changed, 271 insertions(+), 8 deletions(-) create mode 100644 subprojects/internal-performance-testing/src/main/groovy/org/gradle/performance/results/FlakinessIssueReporter.groovy create mode 100644 subprojects/internal-performance-testing/src/test/groovy/org/gradle/performance/results/FlakinessIssueReporterTest.groovy diff --git a/buildSrc/subprojects/performance/src/main/groovy/org/gradle/testing/DistributedPerformanceTest.groovy b/buildSrc/subprojects/performance/src/main/groovy/org/gradle/testing/DistributedPerformanceTest.groovy index f07edd3b40121..d227adcf28a0d 100644 --- a/buildSrc/subprojects/performance/src/main/groovy/org/gradle/testing/DistributedPerformanceTest.groovy +++ b/buildSrc/subprojects/performance/src/main/groovy/org/gradle/testing/DistributedPerformanceTest.groovy @@ -84,7 +84,7 @@ class DistributedPerformanceTest extends ReportGenerationPerformanceTest { private RESTClient client - private Map scheduledBuilds = [:] + protected Map scheduledBuilds = [:] private Map finishedBuilds = [:] @@ -134,13 +134,17 @@ class DistributedPerformanceTest extends ReportGenerationPerformanceTest { } @Override + @TypeChecked(TypeCheckingMode.SKIP) protected List generateResultsForReport() { finishedBuilds.collect { workerBuildId, scenarioResult -> new ScenarioBuildResultData( teamCityBuildId: workerBuildId, scenarioName: scheduledBuilds.get(workerBuildId).id, - webUrl: scenarioResult.buildResult.webUrl.toString(), - status: scenarioResult.buildResult.status.toString(), + scenarioClass: scenarioResult.testSuite.name, + webUrl: scenarioResult.buildResult.webUrl, + status: scenarioResult.buildResult.status, + agentName: scenarioResult.buildResult.agent.name, + agentUrl: scenarioResult.buildResult.agent.webUrl, testFailure: collectFailures(scenarioResult.testSuite)) } } diff --git a/buildSrc/subprojects/performance/src/main/groovy/org/gradle/testing/ReportGenerationPerformanceTest.groovy b/buildSrc/subprojects/performance/src/main/groovy/org/gradle/testing/ReportGenerationPerformanceTest.groovy index 8ad84f3354533..3a2cde6b73b25 100644 --- a/buildSrc/subprojects/performance/src/main/groovy/org/gradle/testing/ReportGenerationPerformanceTest.groovy +++ b/buildSrc/subprojects/performance/src/main/groovy/org/gradle/testing/ReportGenerationPerformanceTest.groovy @@ -51,6 +51,7 @@ abstract class ReportGenerationPerformanceTest extends PerformanceTest { spec.args(reportDir.path, resultJson.path, getProject().getName()) spec.systemProperties(databaseParameters) spec.systemProperty("org.gradle.performance.execution.channel", channel) + spec.systemProperty("githubToken", project.findProperty("githubToken")) spec.setClasspath(ReportGenerationPerformanceTest.this.getClasspath()) } }) @@ -76,9 +77,12 @@ abstract class ReportGenerationPerformanceTest extends PerformanceTest { static class ScenarioBuildResultData { String teamCityBuildId String scenarioName + String scenarioClass String webUrl String testFailure // SUCCESS/FAILURE/UNKNOWN String status + String agentName + String agentUrl } } diff --git a/subprojects/internal-performance-testing/internal-performance-testing.gradle.kts b/subprojects/internal-performance-testing/internal-performance-testing.gradle.kts index 5edb56b2b0b86..c83fc49ae1745 100644 --- a/subprojects/internal-performance-testing/internal-performance-testing.gradle.kts +++ b/subprojects/internal-performance-testing/internal-performance-testing.gradle.kts @@ -44,6 +44,7 @@ dependencies { compile(library("commons_math")) compile(library("jcl_to_slf4j")) compile("org.openjdk.jmc:flightrecorder:7.0.0-SNAPSHOT") + compile("org.gradle.ci.health:tagging:0.63") runtime("com.h2database:h2:1.4.192") } @@ -69,4 +70,4 @@ tasks.jar { testFixtures { from(":core", "main") from(":toolingApi", "main") -} \ No newline at end of file +} diff --git a/subprojects/internal-performance-testing/src/main/groovy/org/gradle/performance/results/AbstractTablePageGenerator.java b/subprojects/internal-performance-testing/src/main/groovy/org/gradle/performance/results/AbstractTablePageGenerator.java index 511738fd70660..e044ada813dbe 100644 --- a/subprojects/internal-performance-testing/src/main/groovy/org/gradle/performance/results/AbstractTablePageGenerator.java +++ b/subprojects/internal-performance-testing/src/main/groovy/org/gradle/performance/results/AbstractTablePageGenerator.java @@ -197,8 +197,6 @@ private void renderTable(String title, String description, List renderScenario(counter.incrementAndGet(), scenario)); } - - private String getTextColorCss(ScenarioBuildResultData scenario, ScenarioBuildResultData.ExecutionData executionData) { if(scenario.isCrossBuild()) { return "text-dark"; diff --git a/subprojects/internal-performance-testing/src/main/groovy/org/gradle/performance/results/FlakinessIndexPageGenerator.java b/subprojects/internal-performance-testing/src/main/groovy/org/gradle/performance/results/FlakinessIndexPageGenerator.java index 906c316a85dd3..f787272f0f584 100644 --- a/subprojects/internal-performance-testing/src/main/groovy/org/gradle/performance/results/FlakinessIndexPageGenerator.java +++ b/subprojects/internal-performance-testing/src/main/groovy/org/gradle/performance/results/FlakinessIndexPageGenerator.java @@ -17,6 +17,8 @@ package org.gradle.performance.results; import com.google.common.collect.Sets; +import org.gradle.ci.github.GitHubIssuesClient; +import org.gradle.ci.tagging.flaky.GitHubKnownIssuesProvider; import java.io.File; import java.io.IOException; @@ -39,9 +41,11 @@ public class FlakinessIndexPageGenerator extends AbstractTablePageGenerator { .thenComparing(comparing(ScenarioBuildResultData::isFlaky).reversed()) .thenComparing(comparing(ScenarioBuildResultData::getDifferencePercentage).reversed()) .thenComparing(ScenarioBuildResultData::getScenarioName); + private final FlakinessIssueReporter issueReporter; - public FlakinessIndexPageGenerator(ResultsStore resultsStore, File resultJson) { + public FlakinessIndexPageGenerator(ResultsStore resultsStore, File resultJson, GitHubIssuesClient gitHubIssuesClient) { super(resultsStore, resultJson); + issueReporter = new FlakinessIssueReporter(gitHubIssuesClient, new GitHubKnownIssuesProvider(gitHubIssuesClient)); } @Override @@ -107,4 +111,8 @@ protected void renderScenarioButtons(int index, ScenarioBuildResultData scenario } }; } + + public void reportToIssueTracker() { + scenarios.stream().filter(ScenarioBuildResultData::isFlaky).forEach(issueReporter::report); + } } diff --git a/subprojects/internal-performance-testing/src/main/groovy/org/gradle/performance/results/FlakinessIssueReporter.groovy b/subprojects/internal-performance-testing/src/main/groovy/org/gradle/performance/results/FlakinessIssueReporter.groovy new file mode 100644 index 0000000000000..5c64b8edee797 --- /dev/null +++ b/subprojects/internal-performance-testing/src/main/groovy/org/gradle/performance/results/FlakinessIssueReporter.groovy @@ -0,0 +1,109 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.performance.results + +import groovy.transform.CompileStatic +import groovy.transform.TypeChecked +import groovy.transform.TypeCheckingMode +import org.gradle.ci.common.model.FlakyTest +import org.gradle.ci.github.GitHubIssuesClient +import org.gradle.ci.tagging.flaky.KnownFlakyTestProvider +import org.gradle.performance.results.ScenarioBuildResultData.ExecutionData +import org.kohsuke.github.GHIssue +import org.kohsuke.github.GHIssueState + +import static org.gradle.ci.github.GitHubIssuesClient.CI_TRACKED_FLAKINESS_LABEL +import static org.gradle.ci.github.GitHubIssuesClient.FROM_BOT_PREFIX +import static org.gradle.ci.github.GitHubIssuesClient.MESSAGE_PREFIX +import static org.gradle.ci.github.GitHubIssuesClient.TEST_NAME_PREFIX + +@CompileStatic +class FlakinessIssueReporter { + static final String GITHUB_FIX_IT_LABEL = "fix-it" + private final KnownFlakyTestProvider provider + private final GitHubIssuesClient gitHubIssuesClient + + FlakinessIssueReporter(GitHubIssuesClient gitHubIssuesClient, KnownFlakyTestProvider provider) { + this.provider = provider + this.gitHubIssuesClient = gitHubIssuesClient + } + + void report(ScenarioBuildResultData flakyScenario) { + FlakyTest knownFlakyTest = findKnownFlakyTest(flakyScenario) + if (knownFlakyTest) { + if (issueClosed(knownFlakyTest)) { + knownFlakyTest.issue.reopen() + } + if (!hasFixItLabel(knownFlakyTest)) { + knownFlakyTest.issue.addLabels(GITHUB_FIX_IT_LABEL) + } + } else { + knownFlakyTest = openNewFlakyTestIssue(flakyScenario) + } + + commentCurrentFailureToIssue(flakyScenario, knownFlakyTest.issue) + } + + @TypeChecked(TypeCheckingMode.SKIP) + static void commentCurrentFailureToIssue(ScenarioBuildResultData scenario, GHIssue issue) { + issue.comment(""" +${FROM_BOT_PREFIX} + +Coordinator url: https://builds.gradle.org/viewLog.html?buildId=${System.getenv("BUILD_ID")} +Worker url: ${scenario.webUrl} +Agent: [${scenario.agentName}](${scenario.agentUrl}) +Details: + +| Iteration | Difference | Confidence | +|---|---|---| +${assembleTable(scenario)} +""") + } + + private static String assembleTable(ScenarioBuildResultData scenario) { + scenario.executions.withIndex().collect { ExecutionData execution, int index -> + "|${index + 1}|${execution.differenceDisplay}|${execution.formattedConfidence}|" + }.join('\n') + } + + private FlakyTest openNewFlakyTestIssue(ScenarioBuildResultData flakyScenario) { + String title = "Flaky performance test: ${flakyScenario.flakyIssueTestName}" + String message = "we're slower than" + String body = """ +${FROM_BOT_PREFIX} + +${TEST_NAME_PREFIX}${flakyScenario.flakyIssueTestName} + +${MESSAGE_PREFIX}$message +""" + + GHIssue issue = gitHubIssuesClient.createBuildToolInvalidFailureIssue(title, body, [CI_TRACKED_FLAKINESS_LABEL]) + return new FlakyTest(issue: issue) + } + + private FlakyTest findKnownFlakyTest(ScenarioBuildResultData scenario) { + return provider.knownInvalidFailures.find { scenario.flakyIssueTestName.contains(it.name) } + } + + private static boolean issueClosed(FlakyTest flakyTest) { + return flakyTest.issue.state == GHIssueState.CLOSED + } + + private static boolean hasFixItLabel(FlakyTest flakyTest) { + return flakyTest.issue.getLabels().collect { it.name }.contains(GITHUB_FIX_IT_LABEL) + } +} diff --git a/subprojects/internal-performance-testing/src/main/groovy/org/gradle/performance/results/FlakinessReportGenerator.java b/subprojects/internal-performance-testing/src/main/groovy/org/gradle/performance/results/FlakinessReportGenerator.java index f13c7b20df7da..413f39c549b1d 100644 --- a/subprojects/internal-performance-testing/src/main/groovy/org/gradle/performance/results/FlakinessReportGenerator.java +++ b/subprojects/internal-performance-testing/src/main/groovy/org/gradle/performance/results/FlakinessReportGenerator.java @@ -16,6 +16,9 @@ package org.gradle.performance.results; +import org.gradle.ci.github.DefaultGitHubIssuesClient; +import org.gradle.ci.github.GitHubIssuesClient; + import java.io.File; import java.io.IOException; @@ -26,7 +29,11 @@ public static void main(String[] args) throws Exception { @Override protected void renderIndexPage(ResultsStore store, File resultJson, File outputDirectory) throws IOException { - new FileRenderer().render(store, new FlakinessIndexPageGenerator(store, resultJson), new File(outputDirectory, "index.html")); + GitHubIssuesClient gitHubIssuesClient = new DefaultGitHubIssuesClient(System.getProperty("githubToken")); + FlakinessIndexPageGenerator reporter = new FlakinessIndexPageGenerator(store, resultJson, gitHubIssuesClient); + new FileRenderer().render(store, reporter, new File(outputDirectory, "index.html")); + + reporter.reportToIssueTracker(); } @Override diff --git a/subprojects/internal-performance-testing/src/main/groovy/org/gradle/performance/results/ScenarioBuildResultData.groovy b/subprojects/internal-performance-testing/src/main/groovy/org/gradle/performance/results/ScenarioBuildResultData.groovy index c720ba59ca1ba..acc80f47f2c9b 100644 --- a/subprojects/internal-performance-testing/src/main/groovy/org/gradle/performance/results/ScenarioBuildResultData.groovy +++ b/subprojects/internal-performance-testing/src/main/groovy/org/gradle/performance/results/ScenarioBuildResultData.groovy @@ -25,13 +25,20 @@ class ScenarioBuildResultData { private static final int FLAKINESS_DETECTION_THRESHOLD = 99 String teamCityBuildId String scenarioName + String scenarioClass String webUrl + String agentName + String agentUrl String testFailure String status boolean crossBuild List currentBuildExecutions = [] List recentExecutions = [] + String getFlakyIssueTestName() { + return "${scenarioClass}.${scenarioName}" + } + boolean isCrossVersion() { return !crossBuild } diff --git a/subprojects/internal-performance-testing/src/test/groovy/org/gradle/performance/results/FlakinessIssueReporterTest.groovy b/subprojects/internal-performance-testing/src/test/groovy/org/gradle/performance/results/FlakinessIssueReporterTest.groovy new file mode 100644 index 0000000000000..2ea1c0b9e6afb --- /dev/null +++ b/subprojects/internal-performance-testing/src/test/groovy/org/gradle/performance/results/FlakinessIssueReporterTest.groovy @@ -0,0 +1,125 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.performance.results + +import org.gradle.ci.common.model.FlakyTest +import org.gradle.ci.github.GitHubIssuesClient +import org.gradle.ci.tagging.flaky.KnownFlakyTestProvider +import org.kohsuke.github.GHIssue +import org.kohsuke.github.GHIssueState +import spock.lang.Specification +import spock.lang.Subject + +import static org.gradle.ci.github.GitHubIssuesClient.CI_TRACKED_FLAKINESS_LABEL +import static org.gradle.performance.results.FlakinessIssueReporter.GITHUB_FIX_IT_LABEL + +class FlakinessIssueReporterTest extends Specification { + GitHubIssuesClient issuesClient = Mock(GitHubIssuesClient) + KnownFlakyTestProvider flakyTestProvider = Mock(KnownFlakyTestProvider) + + @Subject + FlakinessIssueReporter reporter = new FlakinessIssueReporter(issuesClient, flakyTestProvider) + + ScenarioBuildResultData scenario = new ScenarioBuildResultData( + scenarioName: 'myScenario', + scenarioClass: 'my.AwesomeClass', + webUrl: 'myUrl', + agentName: 'myAgent', + agentUrl: 'myAgentUrl', + currentBuildExecutions: [ + new MockExecutionData(100, 1), + new MockExecutionData(98, -1) + ] + ) + + def 'known flaky issue gets commented, reopened and labeled as fix-it'() { + given: + GHIssue issue = Mock(GHIssue) + 1 * flakyTestProvider.knownInvalidFailures >> [new FlakyTest(name: 'my.AwesomeClass.otherScenario'), new FlakyTest(name: 'my.AwesomeClass.myScenario', issue: issue)] + 1 * issue.state >> GHIssueState.CLOSED + 1 * issue.labels >> [] + + when: + reporter.report(scenario) + + then: + 1 * issue.reopen() + 1 * issue.addLabels(GITHUB_FIX_IT_LABEL) + 1 * issue.comment(""" +FROM-BOT + +Coordinator url: https://builds.gradle.org/viewLog.html?buildId=${System.getenv("BUILD_ID")} +Worker url: myUrl +Agent: [myAgent](myAgentUrl) +Details: + +| Iteration | Difference | Confidence | +|---|---|---| +|1|1.0 %|100.0%| +|2|-1.0 %|98.0%| +""") + } + + def 'new issue is created if none found'() { + given: + GHIssue issue = Mock(GHIssue) + 1 * flakyTestProvider.knownInvalidFailures >> [new FlakyTest(name: 'otherScenario')] + + when: + reporter.report(scenario) + + then: + 1 * issuesClient.createBuildToolInvalidFailureIssue('Flaky performance test: my.AwesomeClass.myScenario', + """ +FROM-BOT + +TEST_NAME: my.AwesomeClass.myScenario + +MESSAGE: we're slower than +""" + , [CI_TRACKED_FLAKINESS_LABEL]) >> issue + 1 * issue.comment(""" +FROM-BOT + +Coordinator url: https://builds.gradle.org/viewLog.html?buildId=${System.getenv("BUILD_ID")} +Worker url: myUrl +Agent: [myAgent](myAgentUrl) +Details: + +| Iteration | Difference | Confidence | +|---|---|---| +|1|1.0 %|100.0%| +|2|-1.0 %|98.0%| +""") + } + + class MockExecutionData extends ScenarioBuildResultData.ExecutionData { + double confidencePercentage + double differencePercentage + + MockExecutionData(double confidencePercentage, double differencePercentage) { + super(System.currentTimeMillis(), "commitId", null, null) + this.confidencePercentage = confidencePercentage + this.differencePercentage = differencePercentage + } + + @Override + String getDifferenceDisplay() { + return "${differencePercentage} %" + } + } +} From f0c8724acff933dedafc2915895538f01516cf4e Mon Sep 17 00:00:00 2001 From: Gradleware Git Bot Date: Wed, 3 Apr 2019 03:41:21 +0200 Subject: [PATCH 853/853] Publish 5.4-20190403012714+0000 --- released-versions.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/released-versions.json b/released-versions.json index 88c10471f30c3..478dc1670801c 100644 --- a/released-versions.json +++ b/released-versions.json @@ -1,7 +1,7 @@ { "latestReleaseSnapshot": { - "version": "5.4-20190402011228+0000", - "buildTime": "20190402011228+0000" + "version": "5.4-20190403012714+0000", + "buildTime": "20190403012714+0000" }, "latestRc": { "version": "5.3-rc-3",