From 8b648a2e2562f43b40e70ade1302ec4c9709bc73 Mon Sep 17 00:00:00 2001 From: daz Date: Mon, 1 Apr 2024 14:07:40 -0600 Subject: [PATCH] Apply the configuration filter for 'resolve-all-dependencies' Previously, excluded configurations would be excluded from the graph, but they would still be resolved. By avoiding resolution altogether, we allow users to exclude any unresolvable dependency configurations. Fixes #126 --- ...rationFilterDependencyExtractorTest.groovy | 39 +++++++++++++++++++ .../ForceDependencyResolutionPlugin.kt | 27 +++++++++---- .../LegacyResolveProjectDependenciesTask.kt | 9 ++++- .../ResolveProjectDependenciesTask.kt | 9 ++++- 4 files changed, 75 insertions(+), 9 deletions(-) diff --git a/plugin-test/src/test/groovy/org/gradle/github/dependencygraph/ConfigurationFilterDependencyExtractorTest.groovy b/plugin-test/src/test/groovy/org/gradle/github/dependencygraph/ConfigurationFilterDependencyExtractorTest.groovy index b4da125e..da06a4ae 100644 --- a/plugin-test/src/test/groovy/org/gradle/github/dependencygraph/ConfigurationFilterDependencyExtractorTest.groovy +++ b/plugin-test/src/test/groovy/org/gradle/github/dependencygraph/ConfigurationFilterDependencyExtractorTest.groovy @@ -284,4 +284,43 @@ class ConfigurationFilterDependencyExtractorTest extends BaseExtractorTest { ]) } + def "does not attempt to resolve excluded configurations"() { + given: + settingsFile << "include 'a', 'b'" + + buildFile << """ + project(':a') { + apply plugin: 'java-library' + dependencies { + api 'org.test:foo:1.0' + } + configurations.all { + incoming.beforeResolve { + throw new RuntimeException("Should not resolve project :a") + } + } + } + project(':b') { + apply plugin: 'java-library' + dependencies { + api 'org.test:bar:1.0' + testImplementation 'org.test:baz:1.0' + } + configurations.testCompileClasspath { + incoming.beforeResolve { + throw new RuntimeException("Should not resolve configuration 'testCompileClasspath'") + } + } + } + """ + + when: + executer.withArgument("-DDEPENDENCY_GRAPH_EXCLUDE_PROJECTS=:a") + executer.withArgument("-DDEPENDENCY_GRAPH_EXCLUDE_CONFIGURATIONS=test(Compile|Runtime)Classpath") + run() + + then: + gitHubManifest().assertResolved(["org.test:bar:1.0"]) + } + } diff --git a/plugin/src/main/kotlin/org/gradle/forceresolve/ForceDependencyResolutionPlugin.kt b/plugin/src/main/kotlin/org/gradle/forceresolve/ForceDependencyResolutionPlugin.kt index 8a4d1749..eafecd96 100644 --- a/plugin/src/main/kotlin/org/gradle/forceresolve/ForceDependencyResolutionPlugin.kt +++ b/plugin/src/main/kotlin/org/gradle/forceresolve/ForceDependencyResolutionPlugin.kt @@ -5,6 +5,8 @@ import org.gradle.api.Project import org.gradle.api.Task import org.gradle.api.invocation.Gradle import org.gradle.api.tasks.TaskProvider +import org.gradle.dependencygraph.extractor.ResolvedConfigurationFilter +import org.gradle.dependencygraph.util.PluginParameters import org.gradle.util.GradleVersion private const val RESOLVE_PROJECT_TASK = "ForceDependencyResolutionPlugin_resolveProjectDependencies" @@ -14,6 +16,14 @@ private const val RESOLVE_ALL_TASK = "ForceDependencyResolutionPlugin_resolveAll * Adds a task to resolve all dependencies in a Gradle build tree. */ class ForceDependencyResolutionPlugin : Plugin { + + // Properties are lazily initialized so that System Properties are initialized by the time + // the values are used. This is required due to a bug in older Gradle versions. (https://github.com/gradle/gradle/issues/6825) + private val pluginParameters = PluginParameters() + private val configurationFilter by lazy { + ResolvedConfigurationFilter(pluginParameters) + } + override fun apply(gradle: Gradle) { gradle.projectsEvaluated { val resolveAllDeps = gradle.rootProject.tasks.register(RESOLVE_ALL_TASK) @@ -21,7 +31,7 @@ class ForceDependencyResolutionPlugin : Plugin { // Depend on "dependencies" task in all projects gradle.allprojects { project -> val projectTaskFactory = getResolveProjectDependenciesTaskFactory() - val resolveProjectDeps = projectTaskFactory.create(project) + val resolveProjectDeps = projectTaskFactory.create(project, configurationFilter) resolveAllDeps.configure { it.dependsOn(resolveProjectDeps) } @@ -47,19 +57,22 @@ class ForceDependencyResolutionPlugin : Plugin { } private interface ResolveProjectDependenciesTaskFactory { - fun create(project: Project): TaskProvider + fun create(project: Project, filter: ResolvedConfigurationFilter): TaskProvider object Current : ResolveProjectDependenciesTaskFactory { - override fun create(project: Project): TaskProvider { - return project.tasks.register(RESOLVE_PROJECT_TASK, ResolveProjectDependenciesTask::class.java) + override fun create(project: Project, filter: ResolvedConfigurationFilter): TaskProvider { + return project.tasks.register(RESOLVE_PROJECT_TASK, ResolveProjectDependenciesTask::class.java) { + it.configurationFilter = filter + } } } object Legacy : ResolveProjectDependenciesTaskFactory { - override fun create(project: Project): TaskProvider { - return project.tasks.register(RESOLVE_PROJECT_TASK, LegacyResolveProjectDependenciesTask::class.java) + override fun create(project: Project, filter: ResolvedConfigurationFilter): TaskProvider { + return project.tasks.register(RESOLVE_PROJECT_TASK, LegacyResolveProjectDependenciesTask::class.java) { + it.configurationFilter = filter + } } } } - } \ No newline at end of file diff --git a/plugin/src/main/kotlin/org/gradle/forceresolve/LegacyResolveProjectDependenciesTask.kt b/plugin/src/main/kotlin/org/gradle/forceresolve/LegacyResolveProjectDependenciesTask.kt index af6c45a8..f08bc39c 100644 --- a/plugin/src/main/kotlin/org/gradle/forceresolve/LegacyResolveProjectDependenciesTask.kt +++ b/plugin/src/main/kotlin/org/gradle/forceresolve/LegacyResolveProjectDependenciesTask.kt @@ -2,13 +2,20 @@ package org.gradle.forceresolve import org.gradle.api.DefaultTask import org.gradle.api.artifacts.Configuration +import org.gradle.api.tasks.Internal import org.gradle.api.tasks.TaskAction +import org.gradle.dependencygraph.extractor.ResolvedConfigurationFilter import org.gradle.work.DisableCachingByDefault @DisableCachingByDefault(because = "Not worth caching") abstract class LegacyResolveProjectDependenciesTask: DefaultTask() { + @Internal + var configurationFilter: ResolvedConfigurationFilter? = null + private fun getReportableConfigurations(): List { - return project.configurations.filter { it.isCanBeResolved } + return project.configurations.filter { + it.isCanBeResolved && configurationFilter!!.include(project.path, it.name) + } } @TaskAction diff --git a/plugin/src/main/kotlin/org/gradle/forceresolve/ResolveProjectDependenciesTask.kt b/plugin/src/main/kotlin/org/gradle/forceresolve/ResolveProjectDependenciesTask.kt index 4fc06619..5c486eda 100644 --- a/plugin/src/main/kotlin/org/gradle/forceresolve/ResolveProjectDependenciesTask.kt +++ b/plugin/src/main/kotlin/org/gradle/forceresolve/ResolveProjectDependenciesTask.kt @@ -4,7 +4,9 @@ import org.gradle.api.DefaultTask import org.gradle.api.artifacts.Configuration import org.gradle.api.artifacts.result.ResolvedComponentResult import org.gradle.api.provider.Provider +import org.gradle.api.tasks.Internal import org.gradle.api.tasks.TaskAction +import org.gradle.dependencygraph.extractor.ResolvedConfigurationFilter import org.gradle.internal.serialization.Cached import org.gradle.work.DisableCachingByDefault @@ -12,6 +14,9 @@ import org.gradle.work.DisableCachingByDefault abstract class ResolveProjectDependenciesTask: DefaultTask() { private val configurationResolvers = Cached.of { createConfigurationResolvers() } + @Internal + var configurationFilter: ResolvedConfigurationFilter? = null + private fun createConfigurationResolvers(): List> { return getReportableConfigurations().map { it.incoming.resolutionResult.rootComponent @@ -19,7 +24,9 @@ abstract class ResolveProjectDependenciesTask: DefaultTask() { } private fun getReportableConfigurations(): List { - return project.configurations.filter { it.isCanBeResolved } + return project.configurations.filter { + it.isCanBeResolved && configurationFilter!!.include(project.path, it.name) + } } @TaskAction