Skip to content

Commit 9945b32

Browse files
committed
Filter by exclusion as well as inclusion
Using a Regex include filter can be problematic when trying to _exclude_ a matching entry (or entries). Adding specific exclude filters matching the current include filters makes configuration more straightforward.
1 parent 7b2d392 commit 9945b32

File tree

5 files changed

+165
-206
lines changed

5 files changed

+165
-206
lines changed

plugin-test/src/test/groovy/org/gradle/github/dependencygraph/BaseExtractorTest.groovy

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,10 @@ abstract class BaseExtractorTest extends Specification {
113113
}
114114
apply plugin: GitHubDependencyGraphPlugin
115115
""".stripMargin()
116+
resetArguments()
117+
}
118+
119+
protected SimpleGradleExecuter resetArguments() {
116120
getExecuter().withArguments("--init-script", "init.gradle")
117121
}
118122

@@ -194,6 +198,12 @@ abstract class BaseExtractorTest extends Specification {
194198
return (manifestData.file as Map).source_location
195199
}
196200

201+
def assertResolved(List<String> expectedResolved) {
202+
def resolved = manifestData.resolved as Map<String, Map>
203+
assert resolved.keySet() == expectedResolved as Set
204+
return true
205+
}
206+
197207
def assertResolved(Map<String, Map> expectedResolved = [:]) {
198208
def resolved = manifestData.resolved as Map<String, Map>
199209

plugin-test/src/test/groovy/org/gradle/github/dependencygraph/ConfigurationFilterDependencyExtractorTest.groovy

Lines changed: 106 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ class ConfigurationFilterDependencyExtractorTest extends BaseExtractorTest {
3737

3838
def "can filter projects to extract dependencies"() {
3939
given:
40-
settingsFile << "include 'a', 'b'"
40+
settingsFile << "include 'a', 'b', 'c'"
4141

4242
buildFile << """
4343
project(':a') {
@@ -52,18 +52,45 @@ class ConfigurationFilterDependencyExtractorTest extends BaseExtractorTest {
5252
api 'org.test:bar:1.0'
5353
}
5454
}
55+
project(':c') {
56+
apply plugin: 'java-library'
57+
dependencies {
58+
api 'org.test:baz:1.0'
59+
}
60+
}
5561
"""
5662

5763
when:
5864
executer.withArgument("-DDEPENDENCY_GRAPH_INCLUDE_PROJECTS=:b")
5965
run()
6066

6167
then:
62-
def manifest = gitHubManifest()
63-
manifest.sourceFile == "settings.gradle"
64-
manifest.assertResolved([
65-
"org.test:bar:1.0": [package_url: purlFor(bar)]
66-
])
68+
gitHubManifest().assertResolved(["org.test:bar:1.0"])
69+
70+
when:
71+
resetArguments()
72+
executer.withArgument("-DDEPENDENCY_GRAPH_INCLUDE_PROJECTS=:[ab]")
73+
run()
74+
75+
then:
76+
gitHubManifest().assertResolved(["org.test:foo:1.0", "org.test:bar:1.0"])
77+
78+
when:
79+
resetArguments()
80+
executer.withArgument("-DDEPENDENCY_GRAPH_EXCLUDE_PROJECTS=:[bc]")
81+
run()
82+
83+
then:
84+
gitHubManifest().assertResolved(["org.test:foo:1.0"])
85+
86+
when:
87+
resetArguments()
88+
executer.withArgument("-DDEPENDENCY_GRAPH_INCLUDE_PROJECTS=:[ab]")
89+
executer.withArgument("-DDEPENDENCY_GRAPH_EXCLUDE_PROJECTS=:b")
90+
run()
91+
92+
then:
93+
gitHubManifest().assertResolved(["org.test:foo:1.0"])
6794
}
6895

6996
def "can filter configurations to extract dependencies"() {
@@ -92,12 +119,15 @@ class ConfigurationFilterDependencyExtractorTest extends BaseExtractorTest {
92119
run()
93120

94121
then:
95-
def manifest = gitHubManifest()
96-
manifest.sourceFile == "settings.gradle"
97-
manifest.assertResolved([
98-
"org.test:foo:1.0": [package_url: purlFor(foo)],
99-
"org.test:bar:1.0": [package_url: purlFor(bar)]
100-
])
122+
gitHubManifest().assertResolved(["org.test:foo:1.0", "org.test:bar:1.0"])
123+
124+
when:
125+
resetArguments()
126+
executer.withArgument("-DDEPENDENCY_GRAPH_EXCLUDE_CONFIGURATIONS=test(Compile|Runtime)Classpath")
127+
run()
128+
129+
then:
130+
gitHubManifest().assertResolved(["org.test:foo:1.0", "org.test:bar:1.0"])
101131
}
102132

103133
def "can filter runtime projects to determine scope"() {
@@ -120,50 +150,36 @@ class ConfigurationFilterDependencyExtractorTest extends BaseExtractorTest {
120150
"""
121151

122152
when:
123-
executer.withArgument("-DDEPENDENCY_GRAPH_RUNTIME_PROJECTS=:a")
153+
executer.withArgument("-DDEPENDENCY_GRAPH_RUNTIME_INCLUDE_PROJECTS=:a")
124154
run()
125155

126156
then:
127-
def manifest = gitHubManifest()
128-
manifest.sourceFile == "settings.gradle"
129-
manifest.assertResolved([
130-
"org.test:foo:1.0": [package_url: purlFor(foo), scope: "runtime"],
131-
"org.test:bar:1.0": [package_url: purlFor(bar), scope: "development"],
157+
gitHubManifest().assertResolved([
158+
"org.test:foo:1.0": [scope: "runtime"],
159+
"org.test:bar:1.0": [scope: "development"]
132160
])
133-
}
134161

135-
def "can filter runtime configurations to determine scope"() {
136-
given:
137-
settingsFile << "include 'a', 'b'"
162+
when:
163+
resetArguments()
164+
executer.withArgument("-DDEPENDENCY_GRAPH_RUNTIME_EXCLUDE_PROJECTS=:b")
165+
run()
138166

139-
buildFile << """
140-
project(':a') {
141-
apply plugin: 'java-library'
142-
dependencies {
143-
api 'org.test:foo:1.0'
144-
testImplementation 'org.test:baz:1.0'
145-
}
146-
}
147-
project(':b') {
148-
apply plugin: 'java-library'
149-
dependencies {
150-
implementation 'org.test:bar:1.0'
151-
testImplementation 'org.test:baz:1.0'
152-
}
153-
}
154-
"""
167+
then:
168+
gitHubManifest().assertResolved([
169+
"org.test:foo:1.0": [scope: "runtime"],
170+
"org.test:bar:1.0": [scope: "development"]
171+
])
155172

156173
when:
157-
executer.withArgument("-DDEPENDENCY_GRAPH_RUNTIME_CONFIGURATIONS=compileClasspath")
174+
resetArguments()
175+
executer.withArgument("-DDEPENDENCY_GRAPH_RUNTIME_INCLUDE_PROJECTS=:[ab]")
176+
executer.withArgument("-DDEPENDENCY_GRAPH_RUNTIME_EXCLUDE_PROJECTS=:b")
158177
run()
159178

160179
then:
161-
def manifest = gitHubManifest()
162-
manifest.sourceFile == "settings.gradle"
163-
manifest.assertResolved([
164-
"org.test:foo:1.0": [package_url: purlFor(foo), scope: "runtime"],
165-
"org.test:bar:1.0": [package_url: purlFor(bar), scope: "runtime"],
166-
"org.test:baz:1.0": [package_url: purlFor(baz), scope: "development", dependencies: ["org.test:bar:1.0"]]
180+
gitHubManifest().assertResolved([
181+
"org.test:foo:1.0": [scope: "runtime"],
182+
"org.test:bar:1.0": [scope: "development"]
167183
])
168184
}
169185

@@ -189,22 +205,45 @@ class ConfigurationFilterDependencyExtractorTest extends BaseExtractorTest {
189205
"""
190206

191207
when:
192-
executer.withArgument("-DDEPENDENCY_GRAPH_RUNTIME_CONFIGURATIONS=compileClasspath")
208+
executer.withArgument("-DDEPENDENCY_GRAPH_RUNTIME_INCLUDE_CONFIGURATIONS=compileClasspath")
209+
run()
210+
211+
then:
212+
gitHubManifest().assertResolved([
213+
"org.test:foo:1.0": [scope: "runtime"],
214+
"org.test:bar:1.0": [scope: "runtime"],
215+
"org.test:baz:1.0": [scope: "development", dependencies: ["org.test:bar:1.0"]]
216+
])
217+
218+
when:
219+
resetArguments()
220+
executer.withArgument("-DDEPENDENCY_GRAPH_RUNTIME_INCLUDE_CONFIGURATIONS=.*Classpath")
193221
run()
194222

195223
then:
196-
def manifest = gitHubManifest()
197-
manifest.sourceFile == "settings.gradle"
198-
manifest.assertResolved([
199-
"org.test:foo:1.0": [package_url: purlFor(foo), scope: "runtime"],
200-
"org.test:bar:1.0": [package_url: purlFor(bar), scope: "runtime"],
201-
"org.test:baz:1.0": [package_url: purlFor(baz), scope: "development", dependencies: ["org.test:bar:1.0"]]
224+
gitHubManifest().assertResolved([
225+
"org.test:foo:1.0": [scope: "runtime"],
226+
"org.test:bar:1.0": [scope: "runtime"],
227+
"org.test:baz:1.0": [scope: "runtime", dependencies: ["org.test:bar:1.0"]]
228+
])
229+
230+
when:
231+
resetArguments()
232+
executer.withArgument("-DDEPENDENCY_GRAPH_RUNTIME_INCLUDE_CONFIGURATIONS=.*Classpath")
233+
executer.withArgument("-DDEPENDENCY_GRAPH_RUNTIME_EXCLUDE_CONFIGURATIONS=test(Compile|Runtime)Classpath")
234+
run()
235+
236+
then:
237+
gitHubManifest().assertResolved([
238+
"org.test:foo:1.0": [scope: "runtime"],
239+
"org.test:bar:1.0": [scope: "runtime"],
240+
"org.test:baz:1.0": [scope: "development", dependencies: ["org.test:bar:1.0"]]
202241
])
203242
}
204243

205244
def "can filter runtime projects and configurations to determine scope"() {
206245
given:
207-
settingsFile << "include 'a', 'b'"
246+
settingsFile << "include 'a', 'b', 'c'"
208247

209248
buildFile << """
210249
project(':a') {
@@ -221,21 +260,27 @@ class ConfigurationFilterDependencyExtractorTest extends BaseExtractorTest {
221260
testImplementation 'org.test:baz:1.0'
222261
}
223262
}
263+
project(':b') {
264+
apply plugin: 'java-library'
265+
dependencies {
266+
api 'org.test:baz:1.0'
267+
}
268+
}
224269
"""
225270

226271
when:
227272
executer
228-
.withArgument("-DDEPENDENCY_GRAPH_RUNTIME_CONFIGURATIONS=compileClasspath")
229-
.withArgument("-DDEPENDENCY_GRAPH_RUNTIME_PROJECTS=:a")
273+
.withArgument("-DDEPENDENCY_GRAPH_RUNTIME_INCLUDE_PROJECTS=:[ab]")
274+
.withArgument("-DDEPENDENCY_GRAPH_RUNTIME_INCLUDE_CONFIGURATIONS=.*Classpath")
275+
.withArgument("-DDEPENDENCY_GRAPH_RUNTIME_EXCLUDE_PROJECTS=:b")
276+
.withArgument("-DDEPENDENCY_GRAPH_RUNTIME_EXCLUDE_CONFIGURATIONS=test(Compile|Runtime)Classpath")
230277
run()
231278

232279
then:
233-
def manifest = gitHubManifest()
234-
manifest.sourceFile == "settings.gradle"
235-
manifest.assertResolved([
236-
"org.test:foo:1.0": [package_url: purlFor(foo), scope: "runtime"],
237-
"org.test:bar:1.0": [package_url: purlFor(bar), scope: "development"],
238-
"org.test:baz:1.0": [package_url: purlFor(baz), scope: "development", dependencies: ["org.test:bar:1.0"]]
280+
gitHubManifest().assertResolved([
281+
"org.test:foo:1.0": [scope: "runtime"],
282+
"org.test:bar:1.0": [scope: "development"],
283+
"org.test:baz:1.0": [scope: "development", dependencies: ["org.test:bar:1.0"]]
239284
])
240285
}
241286

plugin/src/main/kotlin/org/gradle/dependencygraph/extractor/DependencyExtractor.kt

Lines changed: 13 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
package org.gradle.dependencygraph.extractor
22

3-
import org.gradle.api.GradleException
43
import org.gradle.api.artifacts.component.ProjectComponentIdentifier
54
import org.gradle.api.artifacts.result.ResolvedComponentResult
65
import org.gradle.api.artifacts.result.ResolvedDependencyResult
@@ -13,7 +12,6 @@ import org.gradle.dependencygraph.model.DependencyScope.*
1312
import org.gradle.dependencygraph.util.*
1413
import org.gradle.initialization.EvaluateSettingsBuildOperationType
1514
import org.gradle.initialization.LoadProjectsBuildOperationType
16-
import org.gradle.internal.exceptions.Contextual
1715
import org.gradle.internal.exceptions.DefaultMultiCauseException
1816
import org.gradle.internal.operations.*
1917
import java.io.File
@@ -22,8 +20,12 @@ import java.util.*
2220

2321
const val PARAM_INCLUDE_PROJECTS = "DEPENDENCY_GRAPH_INCLUDE_PROJECTS"
2422
const val PARAM_INCLUDE_CONFIGURATIONS = "DEPENDENCY_GRAPH_INCLUDE_CONFIGURATIONS"
25-
const val PARAM_RUNTIME_PROJECTS = "DEPENDENCY_GRAPH_RUNTIME_PROJECTS"
26-
const val PARAM_RUNTIME_CONFIGURATIONS = "DEPENDENCY_GRAPH_RUNTIME_CONFIGURATIONS"
23+
const val PARAM_EXCLUDE_PROJECTS = "DEPENDENCY_GRAPH_EXCLUDE_PROJECTS"
24+
const val PARAM_EXCLUDE_CONFIGURATIONS = "DEPENDENCY_GRAPH_EXCLUDE_CONFIGURATIONS"
25+
const val PARAM_RUNTIME_INCLUDE_PROJECTS = "DEPENDENCY_GRAPH_RUNTIME_INCLUDE_PROJECTS"
26+
const val PARAM_RUNTIME_INCLUDE_CONFIGURATIONS = "DEPENDENCY_GRAPH_RUNTIME_INCLUDE_CONFIGURATIONS"
27+
const val PARAM_RUNTIME_EXCLUDE_PROJECTS = "DEPENDENCY_GRAPH_RUNTIME_EXCLUDE_PROJECTS"
28+
const val PARAM_RUNTIME_EXCLUDE_CONFIGURATIONS = "DEPENDENCY_GRAPH_RUNTIME_EXCLUDE_CONFIGURATIONS"
2729

2830

2931
const val PARAM_REPORT_DIR = "DEPENDENCY_GRAPH_REPORT_DIR"
@@ -46,18 +48,8 @@ abstract class DependencyExtractor :
4648

4749
// Properties are lazily initialized so that System Properties are initialized by the time
4850
// the values are used. This is required due to a bug in older Gradle versions. (https://github.com/gradle/gradle/issues/6825)
49-
private val includeFilter by lazy {
50-
ResolvedConfigurationFilter(
51-
pluginParameters.loadOptional(PARAM_INCLUDE_PROJECTS),
52-
pluginParameters.loadOptional(PARAM_INCLUDE_CONFIGURATIONS)
53-
)
54-
}
55-
56-
private val runtimeFilter by lazy {
57-
ResolvedConfigurationFilter(
58-
pluginParameters.loadOptional(PARAM_RUNTIME_PROJECTS),
59-
pluginParameters.loadOptional(PARAM_RUNTIME_CONFIGURATIONS)
60-
)
51+
private val configurationFilter by lazy {
52+
ResolvedConfigurationFilter(pluginParameters)
6153
}
6254

6355
private val dependencyGraphReportDir by lazy {
@@ -67,12 +59,12 @@ abstract class DependencyExtractor :
6759
abstract fun getRendererClassName(): String
6860

6961
override fun started(buildOperation: BuildOperationDescriptor, startEvent: OperationStartEvent) {
70-
// This method will never be called when registered in a `BuildServiceRegistry` (ie. Gradle 6.1 & higher)
62+
// This method will never be called when registered in a `BuildServiceRegistry` (i.e. Gradle 6.1 & higher)
7163
// No-op
7264
}
7365

7466
override fun progress(operationIdentifier: OperationIdentifier, progressEvent: OperationProgressEvent) {
75-
// This method will never be called when registered in a `BuildServiceRegistry` (ie. Gradle 6.1 & higher)
67+
// This method will never be called when registered in a `BuildServiceRegistry` (i.e. Gradle 6.1 & higher)
7668
// No-op
7769
}
7870

@@ -170,7 +162,7 @@ abstract class DependencyExtractor :
170162
val rootPath = projectIdentityPath ?: details.buildPath
171163
val configurationName = details.configurationName
172164

173-
if (!includeFilter.include(rootPath, configurationName)) {
165+
if (!configurationFilter.include(rootPath, configurationName)) {
174166
LOGGER.debug("Ignoring resolved configuration: $rootPath - $configurationName")
175167
return
176168
}
@@ -201,8 +193,8 @@ abstract class DependencyExtractor :
201193
rootPath: String,
202194
configurationName: String
203195
): DependencyScope {
204-
if (runtimeFilter.isConfigured()) {
205-
return if (runtimeFilter.include(rootPath, configurationName)) RUNTIME else DEVELOPMENT
196+
if (configurationFilter.scopesAreConfigured()) {
197+
return if (configurationFilter.isRuntime(rootPath, configurationName)) RUNTIME else DEVELOPMENT
206198
}
207199
return UNKNOWN
208200
}

0 commit comments

Comments
 (0)