Skip to content

Commit

Permalink
Apply the configuration filter for 'resolve-all-dependencies'
Browse files Browse the repository at this point in the history
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
  • Loading branch information
bigdaz committed Apr 1, 2024
1 parent a37a7f8 commit 8b648a2
Show file tree
Hide file tree
Showing 4 changed files with 75 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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"])
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -14,14 +16,22 @@ private const val RESOLVE_ALL_TASK = "ForceDependencyResolutionPlugin_resolveAll
* Adds a task to resolve all dependencies in a Gradle build tree.
*/
class ForceDependencyResolutionPlugin : Plugin<Gradle> {

// 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)

// 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)
}
Expand All @@ -47,19 +57,22 @@ class ForceDependencyResolutionPlugin : Plugin<Gradle> {
}

private interface ResolveProjectDependenciesTaskFactory {
fun create(project: Project): TaskProvider<out Task>
fun create(project: Project, filter: ResolvedConfigurationFilter): TaskProvider<out Task>

object Current : ResolveProjectDependenciesTaskFactory {
override fun create(project: Project): TaskProvider<out Task> {
return project.tasks.register(RESOLVE_PROJECT_TASK, ResolveProjectDependenciesTask::class.java)
override fun create(project: Project, filter: ResolvedConfigurationFilter): TaskProvider<out Task> {
return project.tasks.register(RESOLVE_PROJECT_TASK, ResolveProjectDependenciesTask::class.java) {
it.configurationFilter = filter
}
}
}

object Legacy : ResolveProjectDependenciesTaskFactory {
override fun create(project: Project): TaskProvider<out Task> {
return project.tasks.register(RESOLVE_PROJECT_TASK, LegacyResolveProjectDependenciesTask::class.java)
override fun create(project: Project, filter: ResolvedConfigurationFilter): TaskProvider<out Task> {
return project.tasks.register(RESOLVE_PROJECT_TASK, LegacyResolveProjectDependenciesTask::class.java) {
it.configurationFilter = filter
}
}
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -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<Configuration> {
return project.configurations.filter { it.isCanBeResolved }
return project.configurations.filter {
it.isCanBeResolved && configurationFilter!!.include(project.path, it.name)
}
}

@TaskAction
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,29 @@ 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

@DisableCachingByDefault(because = "Not worth caching")
abstract class ResolveProjectDependenciesTask: DefaultTask() {
private val configurationResolvers = Cached.of { createConfigurationResolvers() }

@Internal
var configurationFilter: ResolvedConfigurationFilter? = null

private fun createConfigurationResolvers(): List<Provider<ResolvedComponentResult>> {
return getReportableConfigurations().map {
it.incoming.resolutionResult.rootComponent
}
}

private fun getReportableConfigurations(): List<Configuration> {
return project.configurations.filter { it.isCanBeResolved }
return project.configurations.filter {
it.isCanBeResolved && configurationFilter!!.include(project.path, it.name)
}
}

@TaskAction
Expand Down

0 comments on commit 8b648a2

Please sign in to comment.