diff --git a/plugins/package-curation-providers/ort-config/src/funTest/kotlin/OrtConfigPackageCurationProviderFunTest.kt b/plugins/package-curation-providers/ort-config/src/funTest/kotlin/OrtConfigPackageCurationProviderFunTest.kt index 08bb72266a6d0..475bd59e1c133 100644 --- a/plugins/package-curation-providers/ort-config/src/funTest/kotlin/OrtConfigPackageCurationProviderFunTest.kt +++ b/plugins/package-curation-providers/ort-config/src/funTest/kotlin/OrtConfigPackageCurationProviderFunTest.kt @@ -39,6 +39,15 @@ class OrtConfigPackageCurationProviderFunTest : StringSpec({ curations.filter { it.isApplicable(azureCoreAmqp) } shouldNot beEmpty() } + "The provider returns curations that match the namespace of a package" { + val xrd4j = Identifier("Maven:org.niis.xrd4j:foo:0.0.0") + val packages = createPackagesFromIds(xrd4j) + + val curations = OrtConfigPackageCurationProvider().getCurationsFor(packages) + + curations.filter { it.isApplicable(xrd4j) } shouldNot beEmpty() + } + "The provider does not fail for packages which have no curations" { val packages = createPackagesFromIds(Identifier("Some:Bogus:Package:Id")) diff --git a/plugins/package-curation-providers/ort-config/src/main/kotlin/OrtConfigPackageCurationProvider.kt b/plugins/package-curation-providers/ort-config/src/main/kotlin/OrtConfigPackageCurationProvider.kt index fb4b8a319d4d6..cf41964bc17a6 100644 --- a/plugins/package-curation-providers/ort-config/src/main/kotlin/OrtConfigPackageCurationProvider.kt +++ b/plugins/package-curation-providers/ort-config/src/main/kotlin/OrtConfigPackageCurationProvider.kt @@ -64,15 +64,19 @@ open class OrtConfigPackageCurationProvider : PackageCurationProvider { packages.flatMapTo(mutableSetOf()) { pkg -> getCurationsFor(pkg.id) } private fun getCurationsFor(pkgId: Identifier): List { - val file = curationsDir.resolve("curations").resolve(pkgId.toCurationPath()) - return if (file.isFile) { + // The ORT config repository follows path layout conventions, so curations can be looked up directly. + val packageCurationsFile = curationsDir.resolve("curations").resolve(pkgId.toCurationPath()) + + // Also consider curations for all packages in a namespace. + val namespaceCurationsFile = packageCurationsFile.resolveSibling("_.yml") + + // Return namespace-level curations before package-level curations to allow overriding the former. + return listOf(namespaceCurationsFile, packageCurationsFile).filter { it.isFile }.flatMap { file -> runCatching { file.readValue>().filter { it.isApplicable(pkgId) } }.getOrElse { throw IOException("Failed parsing package curation from '${file.absolutePath}'.", it) } - } else { - emptyList() } } }