From 91cd08abb1b932db7279257fd090d8288cb14952 Mon Sep 17 00:00:00 2001 From: Frank Viernau Date: Tue, 12 Sep 2023 11:33:11 +0200 Subject: [PATCH] fix(reporter): Fix the creation of first level dependency relationships As of [1] the SPDX reporter intends to associate any first level dependency with all root projects it corresponds to. The implementation introduced by [1] has the following issues: 1. Relationships to excluded packages are added, even though excluded packages are not contained in the report. For proof see [2] which adds such relationship. 2. Dependencies which are direct depdendencies of a sub-project, but not of any root project are not considered a first level dependency. Such dependencies may not be linked into the dependency tree of resulting SPDX document at all. Rewrite the algorithm in order to fix both of the above mentioned issues. Fixes #7487. [1] https://github.com/oss-review-toolkit/ort/commit/b47154482299b9b49c0e0c692e3f2dacdd53c395 [2] https://github.com/oss-review-toolkit/ort/commit/b47154482299b9b49c0e0c692e3f2dacdd53c395#diff-6de35dd2aff1f92b7f5ea558d3f77e02d0d596dd4ce2a8199056cfb31b47fcabR181-R184 Signed-off-by: Frank Viernau --- ...ocument-reporter-expected-output.spdx.json | 4 -- ...document-reporter-expected-output.spdx.yml | 3 -- .../main/kotlin/SpdxDocumentModelMapper.kt | 37 +++++++++++++++---- 3 files changed, 30 insertions(+), 14 deletions(-) diff --git a/plugins/reporters/spdx/src/funTest/assets/spdx-document-reporter-expected-output.spdx.json b/plugins/reporters/spdx/src/funTest/assets/spdx-document-reporter-expected-output.spdx.json index ba9f4876ed8ec..9ddc9622e09ef 100644 --- a/plugins/reporters/spdx/src/funTest/assets/spdx-document-reporter-expected-output.spdx.json +++ b/plugins/reporters/spdx/src/funTest/assets/spdx-document-reporter-expected-output.spdx.json @@ -240,10 +240,6 @@ "spdxElementId" : "SPDXRef-Package-Maven-seventh-package-group-seventh-package-0.0.1", "relationshipType" : "GENERATED_FROM", "relatedSpdxElement" : "SPDXRef-Package-Maven-seventh-package-group-seventh-package-0.0.1-source-artifact" - }, { - "spdxElementId" : "SPDXRef-Project-Maven-first-project-group-first-project-name-0.0.1", - "relationshipType" : "DEPENDS_ON", - "relatedSpdxElement" : "SPDXRef-Package-Maven-fifth-package-group-fifth-package-0.0.1" }, { "spdxElementId" : "SPDXRef-Project-Maven-first-project-group-first-project-name-0.0.1", "relationshipType" : "DEPENDS_ON", diff --git a/plugins/reporters/spdx/src/funTest/assets/spdx-document-reporter-expected-output.spdx.yml b/plugins/reporters/spdx/src/funTest/assets/spdx-document-reporter-expected-output.spdx.yml index e2ad5bdfedfc6..9eefa75bb61a2 100644 --- a/plugins/reporters/spdx/src/funTest/assets/spdx-document-reporter-expected-output.spdx.yml +++ b/plugins/reporters/spdx/src/funTest/assets/spdx-document-reporter-expected-output.spdx.yml @@ -241,9 +241,6 @@ relationships: - spdxElementId: "SPDXRef-Package-Maven-seventh-package-group-seventh-package-0.0.1" relationshipType: "GENERATED_FROM" relatedSpdxElement: "SPDXRef-Package-Maven-seventh-package-group-seventh-package-0.0.1-source-artifact" -- spdxElementId: "SPDXRef-Project-Maven-first-project-group-first-project-name-0.0.1" - relationshipType: "DEPENDS_ON" - relatedSpdxElement: "SPDXRef-Package-Maven-fifth-package-group-fifth-package-0.0.1" - spdxElementId: "SPDXRef-Project-Maven-first-project-group-first-project-name-0.0.1" relationshipType: "DEPENDS_ON" relatedSpdxElement: "SPDXRef-Package-Maven-first-package-group-first-package-0.0.1" diff --git a/plugins/reporters/spdx/src/main/kotlin/SpdxDocumentModelMapper.kt b/plugins/reporters/spdx/src/main/kotlin/SpdxDocumentModelMapper.kt index b01d0de2a9e86..6eef3eca19d1c 100644 --- a/plugins/reporters/spdx/src/main/kotlin/SpdxDocumentModelMapper.kt +++ b/plugins/reporters/spdx/src/main/kotlin/SpdxDocumentModelMapper.kt @@ -26,6 +26,7 @@ import java.util.concurrent.atomic.AtomicInteger import org.apache.logging.log4j.kotlin.Logging +import org.ossreviewtoolkit.model.Identifier import org.ossreviewtoolkit.model.OrtResult import org.ossreviewtoolkit.model.SourceCodeOrigin.ARTIFACT import org.ossreviewtoolkit.model.SourceCodeOrigin.VCS @@ -64,21 +65,21 @@ internal object SpdxDocumentModelMapper : Logging { val projects = ortResult.getProjects(omitExcluded = true, includeSubProjects = false).sortedBy { it.id } val projectPackages = projects.map { project -> - val spdxProjectPackage = project.toPackage().toSpdxPackage( + project.toPackage().toSpdxPackage( SpdxPackageType.PROJECT, licenseInfoResolver, ortResult ) + } - ortResult.getDependencies(project.id, 1).mapTo(relationships) { dependency -> - SpdxRelationship( - spdxElementId = spdxProjectPackage.spdxId, + ortResult.getRootProjectsForFirstLevelDependencies().forEach { (pkgId, rootProjectIds) -> + rootProjectIds.forEach { rootProjectId -> + relationships += SpdxRelationship( + spdxElementId = rootProjectId.toSpdxId(SpdxPackageType.PROJECT), relationshipType = SpdxRelationship.Type.DEPENDS_ON, - relatedSpdxElement = dependency.toSpdxId() + relatedSpdxElement = pkgId.toSpdxId(SpdxPackageType.BINARY_PACKAGE) ) } - - spdxProjectPackage } val files = mutableListOf() @@ -169,3 +170,25 @@ internal object SpdxDocumentModelMapper : Logging { ).addExtractedLicenseInfo(licenseTextProvider) } } + +/** + * Return a mapping from the identifiers of all non-excluded first level dependencies to the identifiers of the + * non-excluded root projects they correspond to. + */ +private fun OrtResult.getRootProjectsForFirstLevelDependencies(): Map> { + val result = mutableMapOf>() + + getProjects(omitExcluded = true).map { it.id }.forEach { rootProjectId -> + val subProjectIds = getDependencies(rootProjectId).filter { isProject(it) && !isExcluded(it) } + + val firstLevelDependencies = (subProjectIds + rootProjectId).flatMapTo(mutableSetOf()) { projectId -> + getDependencies(projectId, maxLevel = 1).filter { isPackage(it) && !isExcluded(it) } + } + + firstLevelDependencies.forEach { pkgId -> + result.getOrPut(pkgId) { mutableSetOf() } += rootProjectId + } + } + + return result +}