Skip to content

Commit b84683e

Browse files
committed
feat(spdx): Allow to deduce the ORT id from a PURL
Add an option to deduce the ORT id of a project / package from a PURL, if present. Enabling this allows to maintain e.g. package identifiers during round-trip conversions. The faeture is disabled by default to maintain backwards compatibility. Signed-off-by: Sebastian Schuberth <sebastian@doubleopen.org>
1 parent d929ebc commit b84683e

File tree

2 files changed

+34
-8
lines changed

2 files changed

+34
-8
lines changed

plugins/package-managers/spdx/src/main/kotlin/SpdxDocumentFile.kt

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,19 +42,24 @@ import org.ossreviewtoolkit.model.config.AnalyzerConfiguration
4242
import org.ossreviewtoolkit.model.config.Excludes
4343
import org.ossreviewtoolkit.model.config.Includes
4444
import org.ossreviewtoolkit.model.createAndLogIssue
45+
import org.ossreviewtoolkit.model.utils.toIdentifier
46+
import org.ossreviewtoolkit.model.utils.toPackageUrl
4547
import org.ossreviewtoolkit.plugins.api.OrtPlugin
48+
import org.ossreviewtoolkit.plugins.api.OrtPluginOption
4649
import org.ossreviewtoolkit.plugins.api.PluginConfig
4750
import org.ossreviewtoolkit.plugins.api.PluginDescriptor
4851
import org.ossreviewtoolkit.plugins.packagemanagers.spdx.utils.SpdxDocumentCache
4952
import org.ossreviewtoolkit.plugins.packagemanagers.spdx.utils.SpdxResolvedDocument
5053
import org.ossreviewtoolkit.plugins.packagemanagers.spdx.utils.extractScopeFromExternalReferences
5154
import org.ossreviewtoolkit.plugins.packagemanagers.spdx.utils.isExternalDocumentReferenceId
5255
import org.ossreviewtoolkit.plugins.packagemanagers.spdx.utils.locateCpe
56+
import org.ossreviewtoolkit.plugins.packagemanagers.spdx.utils.locateExternalReference
5357
import org.ossreviewtoolkit.plugins.packagemanagers.spdx.utils.mapNotPresentToEmpty
5458
import org.ossreviewtoolkit.plugins.packagemanagers.spdx.utils.projectPackage
5559
import org.ossreviewtoolkit.plugins.packagemanagers.spdx.utils.toIdentifier
5660
import org.ossreviewtoolkit.plugins.packagemanagers.spdx.utils.toPackage
5761
import org.ossreviewtoolkit.plugins.packagemanagers.spdx.utils.wrapPresentInSet
62+
import org.ossreviewtoolkit.utils.spdxdocument.model.SpdxExternalReference
5863
import org.ossreviewtoolkit.utils.spdxdocument.model.SpdxPackage
5964
import org.ossreviewtoolkit.utils.spdxdocument.model.SpdxRelationship
6065

@@ -70,6 +75,11 @@ private val SPDX_LINKAGE_RELATIONSHIPS = mapOf(
7075

7176
private val SPDX_SCOPE_RELATIONSHIPS = SpdxRelationship.Type.entries.filter { it.name.endsWith("_DEPENDENCY_OF") }
7277

78+
data class SpdxDocumentFileConfig(
79+
@OrtPluginOption(defaultValue = "false")
80+
val deduceOrtIdFromPurl: Boolean
81+
)
82+
7383
/**
7484
* A "fake" package manager implementation that uses SPDX documents as definition files to declare projects and describe
7585
* packages. See https://github.com/spdx/spdx-spec/issues/439 for details.
@@ -79,7 +89,10 @@ private val SPDX_SCOPE_RELATIONSHIPS = SpdxRelationship.Type.entries.filter { it
7989
description = "A package manager that uses SPDX documents as definition files.",
8090
factory = PackageManagerFactory::class
8191
)
82-
class SpdxDocumentFile(override val descriptor: PluginDescriptor = SpdxDocumentFileFactory.descriptor) :
92+
class SpdxDocumentFile(
93+
override val descriptor: PluginDescriptor = SpdxDocumentFileFactory.descriptor,
94+
private val config: SpdxDocumentFileConfig
95+
) :
8396
PackageManager(PROJECT_TYPE) {
8497
override val globsForDefinitionFiles = listOf("*.spdx.yml", "*.spdx.yaml", "*.spdx.json")
8598

@@ -116,7 +129,8 @@ class SpdxDocumentFile(override val descriptor: PluginDescriptor = SpdxDocumentF
116129
val issues = mutableListOf<Issue>()
117130
getPackageManagerDependency(target, doc, analyzerConfig) ?: doc.getSpdxPackageForId(target, issues)
118131
?.let { dependency ->
119-
val ortPackage = dependency.toPackage(doc.getDefinitionFile(target), doc)
132+
val targetFile = doc.getDefinitionFile(target)
133+
val ortPackage = dependency.toPackage(targetFile, doc, config.deduceOrtIdFromPurl)
120134
packages += ortPackage
121135

122136
PackageReference(
@@ -160,7 +174,8 @@ class SpdxDocumentFile(override val descriptor: PluginDescriptor = SpdxDocumentF
160174

161175
getPackageManagerDependency(source, doc, analyzerConfig) ?: doc.getSpdxPackageForId(source, issues)
162176
?.let { dependency ->
163-
val ortPackage = dependency.toPackage(doc.getDefinitionFile(source), doc)
177+
val sourceFile = doc.getDefinitionFile(source)
178+
val ortPackage = dependency.toPackage(sourceFile, doc, config.deduceOrtIdFromPurl)
164179
packages += ortPackage
165180

166181
PackageReference(
@@ -269,8 +284,12 @@ class SpdxDocumentFile(override val descriptor: PluginDescriptor = SpdxDocumentF
269284
)
270285
)
271286

287+
val purlReference = projectPackage.locateExternalReference(SpdxExternalReference.Type.Purl)
288+
val id = purlReference?.takeIf { config.deduceOrtIdFromPurl }?.run { toPackageUrl()?.toIdentifier() }
289+
?: projectPackage.toIdentifier(projectType)
290+
272291
val project = Project(
273-
id = projectPackage.toIdentifier(projectType),
292+
id = id,
274293
cpe = projectPackage.locateCpe(),
275294
definitionFilePath = VersionControlSystem.getPathInfo(definitionFile).path,
276295
authors = projectPackage.originator.wrapPresentInSet(),

plugins/package-managers/spdx/src/main/kotlin/utils/SpdxExtensions.kt

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ import org.ossreviewtoolkit.model.RemoteArtifact
3333
import org.ossreviewtoolkit.model.VcsInfo
3434
import org.ossreviewtoolkit.model.VcsType
3535
import org.ossreviewtoolkit.model.orEmpty
36+
import org.ossreviewtoolkit.model.utils.toIdentifier
3637
import org.ossreviewtoolkit.model.utils.toPackageUrl
3738
import org.ossreviewtoolkit.model.utils.toPurl
3839
import org.ossreviewtoolkit.plugins.packagemanagers.spdx.PACKAGE_TYPE_SPDX
@@ -158,7 +159,11 @@ internal fun SpdxPackage.toIdentifier(type: String) =
158159
/**
159160
* Create a [Package] out of this [SpdxPackage].
160161
*/
161-
internal fun SpdxPackage.toPackage(definitionFile: File?, doc: SpdxResolvedDocument): Package {
162+
internal fun SpdxPackage.toPackage(
163+
definitionFile: File?,
164+
doc: SpdxResolvedDocument,
165+
deduceOrtIdFromPurl: Boolean
166+
): Package {
162167
val packageDescription = description.ifEmpty { summary }
163168

164169
// If the VCS information cannot be determined from the VCS working tree itself, fall back to try getting it
@@ -173,10 +178,12 @@ internal fun SpdxPackage.toPackage(definitionFile: File?, doc: SpdxResolvedDocum
173178
val isBinaryArtifact = generatedFromRelations.any { it.spdxElementId == spdxId }
174179
&& generatedFromRelations.none { it.relatedSpdxElement == spdxId }
175180

176-
val id = toIdentifier(PACKAGE_TYPE_SPDX)
177-
val artifact = getRemoteArtifact()
181+
val purlReference = locateExternalReference(SpdxExternalReference.Type.Purl)
182+
val id = purlReference?.takeIf { deduceOrtIdFromPurl }?.run { toPackageUrl()?.toIdentifier() }
183+
?: toIdentifier(PACKAGE_TYPE_SPDX)
178184

179-
val purl = locateExternalReference(SpdxExternalReference.Type.Purl)
185+
val artifact = getRemoteArtifact()
186+
val purl = purlReference
180187
?: artifact
181188
?.let { if (it.hash.algorithm in HashAlgorithm.VERIFIABLE) it else it.copy(hash = Hash.NONE) }
182189
?.let { id.toPurl(ArtifactProvenance(it)) }

0 commit comments

Comments
 (0)