diff --git a/model/src/main/kotlin/licenses/ResolvedLicenseInfo.kt b/model/src/main/kotlin/licenses/ResolvedLicenseInfo.kt index 1fd6e840b3ca3..30bc85cdeb458 100644 --- a/model/src/main/kotlin/licenses/ResolvedLicenseInfo.kt +++ b/model/src/main/kotlin/licenses/ResolvedLicenseInfo.kt @@ -28,6 +28,7 @@ import org.ossreviewtoolkit.model.config.CopyrightGarbage import org.ossreviewtoolkit.model.config.LicenseFilePatterns import org.ossreviewtoolkit.model.config.PathExclude import org.ossreviewtoolkit.model.utils.PathLicenseMatcher +import org.ossreviewtoolkit.utils.common.FileMatcher import org.ossreviewtoolkit.utils.ort.CopyrightStatementsProcessor import org.ossreviewtoolkit.utils.spdx.SpdxExpression import org.ossreviewtoolkit.utils.spdx.SpdxLicenseChoice @@ -83,22 +84,30 @@ data class ResolvedLicenseInfo( * in any of the configured [LicenseFilePatterns] matched against the root path of the package (or project). */ fun mainLicense(): SpdxExpression? { - val matcher = PathLicenseMatcher(LicenseFilePatterns.getInstance()) - val licensePaths = flatMap { resolvedLicense -> + val licenseFilePatterns = LicenseFilePatterns.getInstance() + val fileMatcher = FileMatcher(licenseFilePatterns.allLicenseFilenames, ignoreCase = true) + val licenseMatcher = PathLicenseMatcher(licenseFilePatterns) + + // Only keep those resolved licenses that can contribute to the main license as they match the configured + // license file patterns. This vastly reduces the search for applicable license files for scan results with a + // lot of detected license findings, like from file headers in a large code base. + val relevantResolvedLicenses = mapNotNull { resolvedLicense -> + val locations = resolvedLicense.locations.filterTo(mutableSetOf()) { fileMatcher.matches(it.location.path) } + if (locations.isNotEmpty()) resolvedLicense.copy(locations = locations) else null + } + + val licensePaths = relevantResolvedLicenses.flatMap { resolvedLicense -> resolvedLicense.locations.map { it.location.path } } - val applicablePathsCache = mutableMapOf>>() - val detectedLicenses = filterTo(mutableSetOf()) { resolvedLicense -> + val detectedLicenses = relevantResolvedLicenses.filterTo(mutableSetOf()) { resolvedLicense -> resolvedLicense.locations.any { val rootPath = (it.provenance as? RepositoryProvenance)?.vcsInfo?.path.orEmpty() - val applicableLicensePaths = applicablePathsCache.getOrPut(rootPath) { - matcher.getApplicableLicenseFilesForDirectories( - licensePaths, - listOf(rootPath) - ) - } + val applicableLicensePaths = licenseMatcher.getApplicableLicenseFilesForDirectories( + licensePaths, + listOf(rootPath) + ) val applicableLicenseFiles = applicableLicensePaths[rootPath].orEmpty() diff --git a/model/src/main/kotlin/utils/PathLicenseMatcher.kt b/model/src/main/kotlin/utils/PathLicenseMatcher.kt index 26427ca94892e..c4c23146e99fd 100644 --- a/model/src/main/kotlin/utils/PathLicenseMatcher.kt +++ b/model/src/main/kotlin/utils/PathLicenseMatcher.kt @@ -115,4 +115,4 @@ class PathLicenseMatcher(licenseFilePatterns: LicenseFilePatterns = LicenseFileP } private fun createFileMatcher(filenamePatterns: Collection): FileMatcher = - FileMatcher(filenamePatterns.map { "/**/$it" }, true) + FileMatcher(filenamePatterns.map { "/**/$it" }, ignoreCase = true)