Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions model/src/main/kotlin/config/PackageConfiguration.kt
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,12 @@ data class PackageConfiguration(
@JsonInclude(JsonInclude.Include.NON_EMPTY)
val pathExcludes: List<PathExclude> = emptyList(),

/**
* Path includes.
*/
@JsonInclude(JsonInclude.Include.NON_EMPTY)
val pathIncludes: List<PathInclude> = emptyList(),

/**
* License finding curations.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import org.ossreviewtoolkit.model.OrtResult
import org.ossreviewtoolkit.model.Provenance
import org.ossreviewtoolkit.model.config.LicenseFindingCuration
import org.ossreviewtoolkit.model.config.PathExclude
import org.ossreviewtoolkit.model.config.PathInclude
import org.ossreviewtoolkit.model.utils.filterByVcsPath
import org.ossreviewtoolkit.utils.ort.ProcessedDeclaredLicense

Expand Down Expand Up @@ -92,6 +93,7 @@ class DefaultLicenseInfoProvider(val ortResult: OrtResult) : LicenseInfoProvider
copyrights = it.summary.copyrightFindings,
licenseFindingCurations = config.licenseFindingCurations,
pathExcludes = config.pathExcludes,
pathIncludes = config.pathIncludes,
relativeFindingsPath = config.relativeFindingsPath
)
}
Expand All @@ -104,12 +106,14 @@ class DefaultLicenseInfoProvider(val ortResult: OrtResult) : LicenseInfoProvider
Configuration(
ortResult.repository.config.curations.licenseFindings,
ortResult.repository.config.excludes.paths,
ortResult.repository.config.includes.paths,
ortResult.repository.getRelativePath(project.vcsProcessed).orEmpty()
)
} ?: ortResult.getPackageConfigurations(id, provenance).let { packageConfigurations ->
Configuration(
packageConfigurations.flatMap { it.licenseFindingCurations },
packageConfigurations.flatMap { it.pathExcludes },
packageConfigurations.flatMap { it.pathIncludes },
""
)
}
Expand All @@ -118,5 +122,6 @@ class DefaultLicenseInfoProvider(val ortResult: OrtResult) : LicenseInfoProvider
private data class Configuration(
val licenseFindingCurations: List<LicenseFindingCuration>,
val pathExcludes: List<PathExclude>,
val pathIncludes: List<PathInclude>,
val relativeFindingsPath: String
)
6 changes: 6 additions & 0 deletions model/src/main/kotlin/licenses/LicenseInfo.kt
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import org.ossreviewtoolkit.model.Provenance
import org.ossreviewtoolkit.model.Repository
import org.ossreviewtoolkit.model.config.LicenseFindingCuration
import org.ossreviewtoolkit.model.config.PathExclude
import org.ossreviewtoolkit.model.config.PathInclude
import org.ossreviewtoolkit.model.config.RepositoryConfiguration
import org.ossreviewtoolkit.utils.ort.ProcessedDeclaredLicense
import org.ossreviewtoolkit.utils.spdx.SpdxExpression
Expand Down Expand Up @@ -136,6 +137,11 @@ data class Findings(
*/
val pathExcludes: List<PathExclude>,

/**
* The list of all path includes that apply to this [provenance].
*/
val pathIncludes: List<PathInclude>,

/**
* The root path of the locations of the [licenses] and [copyrights] relative to the paths used in the
* [licenseFindingCurations] and [pathExcludes]. An empty string, if all refer to the same root path.
Expand Down
47 changes: 44 additions & 3 deletions model/src/main/kotlin/licenses/LicenseInfoResolver.kt
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import org.ossreviewtoolkit.model.UnknownProvenance
import org.ossreviewtoolkit.model.config.CopyrightGarbage
import org.ossreviewtoolkit.model.config.LicenseFilePatterns
import org.ossreviewtoolkit.model.config.PathExclude
import org.ossreviewtoolkit.model.config.PathInclude
import org.ossreviewtoolkit.model.utils.FileArchiver
import org.ossreviewtoolkit.model.utils.FindingCurationMatcher
import org.ossreviewtoolkit.model.utils.FindingsMatcher
Expand Down Expand Up @@ -123,9 +124,16 @@ class LicenseInfoResolver(
).mapNotNull { curationResult ->
val licenseFinding = curationResult.curatedFinding ?: return@mapNotNull null

licenseFinding.license to findings.pathExcludes.any { pathExclude ->
val isExcludedByPathIncludes = licenseFinding.location.isExcludedByPathIncludes(
findings.pathIncludes,
findings.relativeFindingsPath
)

val isMatchedByPathExcludes = findings.pathExcludes.any { pathExclude ->
pathExclude.matches(licenseFinding.location.prependedPath(findings.relativeFindingsPath))
}

licenseFinding.license to (isMatchedByPathExcludes || isExcludedByPathIncludes)
}
}.groupBy(keySelector = { it.first }, valueTransform = { it.second }).mapValues { (_, excluded) ->
excluded.all { it }
Expand Down Expand Up @@ -190,6 +198,7 @@ class LicenseInfoResolver(
val resolvedCopyrightFindings = resolveCopyrights(
copyrightFindings,
findings.pathExcludes,
findings.pathIncludes,
findings.relativeFindingsPath
)

Expand All @@ -204,12 +213,18 @@ class LicenseInfoResolver(
it.matches(licenseFinding.location.prependedPath(findings.relativeFindingsPath))
}

val isExcludedByPathIncludes = licenseFinding.location.isExcludedByPathIncludes(
findings.pathIncludes,
findings.relativeFindingsPath
)

licenseFinding.license.decompose().forEach { singleLicense ->
resolvedLocations.getOrPut(singleLicense) { mutableSetOf() } += ResolvedLicenseLocation(
findings.provenance,
licenseFinding.location,
appliedCuration = appliedCuration,
matchingPathExcludes = matchingPathExcludes,
isExcludedByPathIncludes = isExcludedByPathIncludes,
copyrights = resolvedCopyrightFindings
)
}
Expand All @@ -218,6 +233,7 @@ class LicenseInfoResolver(
unmatchedCopyrights.getOrPut(findings.provenance) { mutableSetOf() } += resolveCopyrights(
copyrightFindings = matchResult.unmatchedCopyrights,
pathExcludes = findings.pathExcludes,
pathIncludes = findings.pathIncludes,
relativeFindingsPath = findings.relativeFindingsPath
)
}
Expand All @@ -228,14 +244,25 @@ class LicenseInfoResolver(
private fun resolveCopyrights(
copyrightFindings: Set<CopyrightFinding>,
pathExcludes: List<PathExclude>,
pathIncludes: List<PathInclude>,
relativeFindingsPath: String
): Set<ResolvedCopyrightFinding> =
copyrightFindings.mapTo(mutableSetOf()) { finding ->
val matchingPathExcludes = pathExcludes.filter {
it.matches(finding.location.prependedPath(relativeFindingsPath))
}

ResolvedCopyrightFinding(finding.statement, finding.location, matchingPathExcludes)
val isExcludedByPathIncludes = finding.location.isExcludedByPathIncludes(
pathIncludes,
relativeFindingsPath
)

ResolvedCopyrightFinding(
finding.statement,
finding.location,
matchingPathExcludes,
isExcludedByPathIncludes
)
}

private fun createLicenseFileInfo(id: Identifier): ResolvedLicenseFileInfo {
Expand Down Expand Up @@ -290,6 +317,7 @@ class LicenseInfoResolver(
location = UNDEFINED_TEXT_LOCATION,
appliedCuration = null,
matchingPathExcludes = emptyList(),
isExcludedByPathIncludes = false,
copyrights = authors.mapTo(mutableSetOf()) { author ->
val statement = "Copyright (C) $author".takeUnless {
author.contains("Copyright", ignoreCase = true)
Expand All @@ -298,10 +326,23 @@ class LicenseInfoResolver(
ResolvedCopyrightFinding(
statement = statement,
location = UNDEFINED_TEXT_LOCATION,
matchingPathExcludes = emptyList()
matchingPathExcludes = emptyList(),
isExcludedByPathIncludes = false
)
}
)

/**
* Return true if the [TextLocation] is excluded because some path includes are defined and none of them matches
* this [TextLocation] prepended with the [relativeFindingsPath].
*/
private fun TextLocation.isExcludedByPathIncludes(pathIncludes: List<PathInclude>, relativeFindingsPath: String) =
when {
pathIncludes.isEmpty() -> false
else -> pathIncludes.none {
it.matches(prependedPath(relativeFindingsPath))
}
}
}

private class ResolvedLicenseBuilder(val license: SpdxSingleLicenseExpression) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,5 +39,10 @@ data class ResolvedCopyrightFinding(
/**
* All [PathExclude]s matching this [location].
*/
val matchingPathExcludes: List<PathExclude>
val matchingPathExcludes: List<PathExclude>,

/**
* If true, some includes are defines and are not matching this [location].
*/
val isExcludedByPathIncludes: Boolean
)
11 changes: 8 additions & 3 deletions model/src/main/kotlin/licenses/ResolvedLicense.kt
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,9 @@ data class ResolvedLicense(
* True, if this license was [detected][LicenseSource.DETECTED] and all [locations] have matching path excludes.
*/
val isDetectedExcluded by lazy {
LicenseSource.DETECTED in sources && locations.all { it.matchingPathExcludes.isNotEmpty() }
LicenseSource.DETECTED in sources && locations.all {
it.matchingPathExcludes.isNotEmpty() || it.isExcludedByPathIncludes
}
}

init {
Expand Down Expand Up @@ -95,13 +97,16 @@ data class ResolvedLicense(

/**
* Filter all excluded copyrights. Copyrights which have
* [matching path excludes][ResolvedCopyrightFinding.matchingPathExcludes] are removed.
* [matching path excludes][ResolvedCopyrightFinding.matchingPathExcludes] or for which [no include are defined]
* [ResolvedCopyrightFinding.isExcludedByPathIncludes] are removed.
*/
fun filterExcludedCopyrights(): ResolvedLicense =
copy(
locations = locations.mapTo(mutableSetOf()) { location ->
location.copy(
copyrights = location.copyrights.filterTo(mutableSetOf()) { it.matchingPathExcludes.isEmpty() }
copyrights = location.copyrights.filterTo(mutableSetOf()) {
it.matchingPathExcludes.isEmpty() || it.isExcludedByPathIncludes
}
)
}
)
Expand Down
5 changes: 5 additions & 0 deletions model/src/main/kotlin/licenses/ResolvedLicenseLocation.kt
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,11 @@ data class ResolvedLicenseLocation(
*/
val matchingPathExcludes: List<PathExclude>,

/**
* If true, some includes are defines and are not matching this [location].
*/
val isExcludedByPathIncludes: Boolean,

/**
* All copyright findings associated to this license location, excluding copyright garbage.
*/
Expand Down
Loading
Loading