Skip to content

Commit 4f7a99f

Browse files
nnobelismnonnenmacher
authored andcommitted
feat(model): Apply the scope includes to the DependencyGraphConverter
Signed-off-by: Nicolas Nobelis <nicolas.nobelis@bosch.com>
1 parent 991d476 commit 4f7a99f

5 files changed

Lines changed: 88 additions & 25 deletions

File tree

analyzer/src/main/kotlin/Analyzer.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,7 @@ class Analyzer(private val config: AnalyzerConfiguration, private val labels: Ma
198198

199199
logger.info { "Building analyzer result." }
200200

201-
return state.buildResult(excludes)
201+
return state.buildResult(excludes, includes)
202202
}
203203

204204
private fun determinePackageManagerDependencies(info: ManagedFileInfo): Map<PackageManager, Set<String>> {
@@ -273,7 +273,7 @@ private class AnalyzerState {
273273
}
274274
}
275275

276-
fun buildResult(excludes: Excludes) = builder.build(excludes)
276+
fun buildResult(excludes: Excludes, includes: Includes) = builder.build(excludes, includes)
277277
}
278278

279279
/**

analyzer/src/main/kotlin/AnalyzerResultBuilder.kt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ import org.ossreviewtoolkit.model.Package
3131
import org.ossreviewtoolkit.model.Project
3232
import org.ossreviewtoolkit.model.ProjectAnalyzerResult
3333
import org.ossreviewtoolkit.model.config.Excludes
34+
import org.ossreviewtoolkit.model.config.Includes
3435
import org.ossreviewtoolkit.model.createAndLogIssue
3536
import org.ossreviewtoolkit.model.utils.DependencyGraphBuilder
3637
import org.ossreviewtoolkit.model.utils.convertToDependencyGraph
@@ -42,15 +43,15 @@ class AnalyzerResultBuilder {
4243
private val issues = mutableMapOf<Identifier, List<Issue>>()
4344
private val dependencyGraphs = mutableMapOf<String, DependencyGraph>()
4445

45-
fun build(excludes: Excludes = Excludes.EMPTY): AnalyzerResult {
46+
fun build(excludes: Excludes = Excludes.EMPTY, includes: Includes = Includes.EMPTY): AnalyzerResult {
4647
val duplicates = (projects.map { it.toPackage() } + packages).getDuplicates { it.id }
4748
require(duplicates.isEmpty()) {
4849
"Unable to create the AnalyzerResult as it contains packages and projects with the same ids: " +
4950
duplicates.values
5051
}
5152

5253
return AnalyzerResult(projects, packages, issues, dependencyGraphs)
53-
.convertToDependencyGraph(excludes)
54+
.convertToDependencyGraph(excludes, includes)
5455
.resolvePackageManagerDependencies()
5556
}
5657

analyzer/src/test/kotlin/AnalyzerResultBuilderTest.kt

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,11 @@ import org.ossreviewtoolkit.model.ProjectAnalyzerResult
4848
import org.ossreviewtoolkit.model.RootDependencyIndex
4949
import org.ossreviewtoolkit.model.Scope
5050
import org.ossreviewtoolkit.model.config.Excludes
51+
import org.ossreviewtoolkit.model.config.Includes
5152
import org.ossreviewtoolkit.model.config.ScopeExclude
5253
import org.ossreviewtoolkit.model.config.ScopeExcludeReason
54+
import org.ossreviewtoolkit.model.config.ScopeInclude
55+
import org.ossreviewtoolkit.model.config.ScopeIncludeReason
5356
import org.ossreviewtoolkit.model.fromYaml
5457
import org.ossreviewtoolkit.model.toYaml
5558
import org.ossreviewtoolkit.model.yamlMapper
@@ -306,13 +309,44 @@ class AnalyzerResultBuilderTest : WordSpec() {
306309
val mergedResults = AnalyzerResultBuilder()
307310
.addResult(analyzerResult1)
308311
.addResult(analyzerResult2)
309-
.build(excludes)
312+
.build(excludes, Includes.EMPTY)
310313

311314
mergedResults.projects.forAll { project ->
312315
project.scopeNames.orEmpty() shouldNotContain "scope-2"
313316
}
314317
}
315318

319+
"apply scope includes" {
320+
val scopeInclude = ScopeInclude("scope-1", ScopeIncludeReason.SOURCE_OF)
321+
val includes = Includes(scopes = listOf(scopeInclude))
322+
323+
val mergedResults = AnalyzerResultBuilder()
324+
.addResult(analyzerResult1)
325+
.addResult(analyzerResult2)
326+
.build(Excludes.EMPTY, includes)
327+
328+
mergedResults.projects.forAll { project ->
329+
project.scopeNames?.single() shouldBe "scope-1"
330+
}
331+
}
332+
333+
"apply scope includes and excludes" {
334+
val scopeInclude = ScopeInclude("scope-1", ScopeIncludeReason.SOURCE_OF)
335+
val scopeExclude = ScopeExclude("scope-1", ScopeExcludeReason.DOCUMENTATION_DEPENDENCY_OF)
336+
val includes = Includes(scopes = listOf(scopeInclude))
337+
val excludes = Excludes(scopes = listOf(scopeExclude))
338+
339+
val mergedResults = AnalyzerResultBuilder()
340+
.addResult(analyzerResult1)
341+
.addResult(analyzerResult2)
342+
.build(excludes, includes)
343+
344+
mergedResults.projects.forAll { project ->
345+
project.scopeNames.orEmpty() shouldNotContain "scope-1"
346+
project.scopeNames.orEmpty() shouldNotContain "scope-2"
347+
}
348+
}
349+
316350
"throw if a result contains a project and a package with the same ID" {
317351
val packageWithProjectId = package1.copy(id = project1.id)
318352

model/src/main/kotlin/utils/DependencyGraphConverter.kt

Lines changed: 29 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import org.ossreviewtoolkit.model.PackageLinkage
2828
import org.ossreviewtoolkit.model.PackageReference
2929
import org.ossreviewtoolkit.model.Project
3030
import org.ossreviewtoolkit.model.config.Excludes
31+
import org.ossreviewtoolkit.model.config.Includes
3132

3233
/**
3334
* An object that supports the conversion of [AnalyzerResult]s to the dependency graph format.
@@ -45,42 +46,50 @@ import org.ossreviewtoolkit.model.config.Excludes
4546
object DependencyGraphConverter {
4647
/**
4748
* Convert the given [result], so that all dependencies are represented as dependency graphs. During conversion,
48-
* apply the scope excludes defined in [excludes]. If the [result] already contains a dependency graph that covers
49-
* all projects, it is returned as is.
49+
* apply the scope includes/excludes defined in [includes] and [excludes]. If the [result] already contains a
50+
* dependency graph that covers all projects, it is returned as is.
5051
*/
51-
fun convert(result: AnalyzerResult, excludes: Excludes = Excludes.EMPTY): AnalyzerResult {
52+
fun convert(
53+
result: AnalyzerResult,
54+
excludes: Excludes = Excludes.EMPTY,
55+
includes: Includes = Includes.EMPTY
56+
): AnalyzerResult {
5257
val projectsToConvert = result.projectsWithScopes()
5358
if (projectsToConvert.isEmpty()) return result
5459

55-
val graphs = buildDependencyGraphs(projectsToConvert, excludes)
60+
val graphs = buildDependencyGraphs(projectsToConvert, excludes, includes)
5661
val allGraphs = result.dependencyGraphs + graphs
5762

58-
val filteredPackages = if (excludes.scopes.isEmpty()) {
63+
val filteredPackages = if (includes.scopes.isEmpty() && excludes.scopes.isEmpty()) {
5964
result.packages
6065
} else {
6166
filterExcludedPackages(allGraphs.values, result.packages)
6267
}
6368

6469
return result.copy(
6570
dependencyGraphs = allGraphs,
66-
projects = result.projects.mapTo(mutableSetOf()) { it.convertToScopeNames(excludes) },
71+
projects = result.projects.mapTo(mutableSetOf()) { it.convertToScopeNames(excludes, includes) },
6772
packages = filteredPackages
6873
)
6974
}
7075

7176
/**
72-
* Create and populate [DependencyGraphBuilder]s for the given [projects] taking [excludes] into account. The
73-
* resulting map contains one fully initialized graph builder for each package manager involved which can be
74-
* used to obtain the [DependencyGraph] and all packages.
77+
* Create and populate [DependencyGraphBuilder]s for the given [projects] taking [includes] and [excludes] into
78+
* account. The resulting map contains one fully initialized graph builder for each package manager involved which
79+
* can be used to obtain the [DependencyGraph] and all packages.
7580
*/
76-
private fun buildDependencyGraphs(projects: Set<Project>, excludes: Excludes): Map<String, DependencyGraph> {
81+
private fun buildDependencyGraphs(
82+
projects: Set<Project>,
83+
excludes: Excludes,
84+
includes: Includes
85+
): Map<String, DependencyGraph> {
7786
val graphs = mutableMapOf<String, DependencyGraph>()
7887

7988
projects.groupBy { it.id.type }.forEach { (type, projectsForType) ->
8089
val builder = DependencyGraphBuilder(ScopesDependencyHandler)
8190

8291
projectsForType.forEach { project ->
83-
project.scopes.filterNot { excludes.isScopeExcluded(it.name) }.forEach { scope ->
92+
project.scopes.filter { isScopeIncluded(it.name, excludes, includes) }.forEach { scope ->
8493
val scopeName = DependencyGraph.qualifyScope(project.id, scope.name)
8594
scope.dependencies.forEach { dependency ->
8695
builder.addDependency(scopeName, dependency)
@@ -96,7 +105,7 @@ object DependencyGraphConverter {
96105

97106
/**
98107
* Filter out all [packages] that are no longer referenced by one of the given [dependency graphs][graphs]. These
99-
* packages have been subject of scope excludes.
108+
* packages have been subject of scope excludes or not included by scope includes.
100109
*/
101110
private fun filterExcludedPackages(
102111
graphs: Collection<DependencyGraph>,
@@ -115,12 +124,14 @@ object DependencyGraphConverter {
115124

116125
/**
117126
* Convert the dependency representation used by this [Project] to the dependency graph format, i.e. a set of
118-
* scope names. Use the given [excludes] to filter out excluded scopes. Return the same project if this format is
119-
* already in use.
127+
* scope names. Use the given [excludes] and [includes] to filter out excluded scopes. Return the same project if
128+
* this format is already in use.
120129
*/
121-
private fun Project.convertToScopeNames(excludes: Excludes): Project =
130+
private fun Project.convertToScopeNames(excludes: Excludes, includes: Includes): Project =
122131
takeIf { scopeNames != null } ?: copy(
123-
scopeNames = scopes.filterNot { excludes.isScopeExcluded(it.name) }.mapTo(mutableSetOf()) { it.name },
132+
scopeNames = scopes.filter {
133+
isScopeIncluded(it.name, excludes, includes)
134+
}.mapTo(mutableSetOf()) { it.name },
124135
scopeDependencies = null
125136
)
126137

@@ -143,5 +154,5 @@ object DependencyGraphConverter {
143154
}
144155
}
145156

146-
fun AnalyzerResult.convertToDependencyGraph(excludes: Excludes = Excludes.EMPTY) =
147-
DependencyGraphConverter.convert(this, excludes)
157+
fun AnalyzerResult.convertToDependencyGraph(excludes: Excludes = Excludes.EMPTY, includes: Includes = Includes.EMPTY) =
158+
DependencyGraphConverter.convert(this, excludes, includes)

model/src/test/kotlin/utils/DependencyGraphConverterTest.kt

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,11 @@ import org.ossreviewtoolkit.model.Project
4242
import org.ossreviewtoolkit.model.ProjectAnalyzerResult
4343
import org.ossreviewtoolkit.model.Scope
4444
import org.ossreviewtoolkit.model.config.Excludes
45+
import org.ossreviewtoolkit.model.config.Includes
4546
import org.ossreviewtoolkit.model.config.ScopeExclude
4647
import org.ossreviewtoolkit.model.config.ScopeExcludeReason
48+
import org.ossreviewtoolkit.model.config.ScopeInclude
49+
import org.ossreviewtoolkit.model.config.ScopeIncludeReason
4750
import org.ossreviewtoolkit.utils.test.readResourceValue
4851

4952
class DependencyGraphConverterTest : WordSpec({
@@ -67,7 +70,21 @@ class DependencyGraphConverterTest : WordSpec({
6770
val scopeExclude = ScopeExclude("test", ScopeExcludeReason.TEST_DEPENDENCY_OF)
6871
val excludes = Excludes(scopes = listOf(scopeExclude))
6972

70-
val convertedResult = DependencyGraphConverter.convert(result, excludes)
73+
val convertedResult = DependencyGraphConverter.convert(result, excludes, Includes.EMPTY)
74+
75+
convertedResult.projects.single().scopeNames shouldContainOnly listOf("main")
76+
convertedResult.packages.forAll { it.id.version.drop(2).toInt() shouldBeLessThan 110 }
77+
}
78+
79+
"exclude scopes due to scopes includes" {
80+
val project = createProject("Maven", index = 1)
81+
82+
val result = createAnalyzerResult(project.createResult())
83+
84+
val scopeInclude = ScopeInclude("main", ScopeIncludeReason.SOURCE_OF)
85+
val includes = Includes(scopes = listOf(scopeInclude))
86+
87+
val convertedResult = DependencyGraphConverter.convert(result, Excludes.EMPTY, includes)
7188

7289
convertedResult.projects.single().scopeNames shouldContainOnly listOf("main")
7390
convertedResult.packages.forAll { it.id.version.drop(2).toInt() shouldBeLessThan 110 }
@@ -87,7 +104,7 @@ class DependencyGraphConverterTest : WordSpec({
87104
val scopeExclude = ScopeExclude("main", ScopeExcludeReason.TEST_DEPENDENCY_OF)
88105
val excludes = Excludes(scopes = listOf(scopeExclude))
89106

90-
val convertedResult = DependencyGraphConverter.convert(analyzerResult, excludes)
107+
val convertedResult = DependencyGraphConverter.convert(analyzerResult, excludes, Includes.EMPTY)
91108

92109
val allPackagesTypes = convertedResult.packages.mapTo(mutableSetOf()) { it.id.type }
93110
allPackagesTypes should containExactlyInAnyOrder("Maven", "Go")

0 commit comments

Comments
 (0)