-
Notifications
You must be signed in to change notification settings - Fork 314
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Apply license choices specified for a package defined in the repository configuration file #3713
Changes from all commits
711179d
cdcec0d
e004460
0f5de06
fbd6ba7
ffad00d
ddff361
9a0f405
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
/* | ||
* Copyright (C) 2021 Bosch.IO GmbH | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
* | ||
* SPDX-License-Identifier: Apache-2.0 | ||
* License-Filename: LICENSE | ||
*/ | ||
|
||
package org.ossreviewtoolkit.model.config | ||
|
||
import com.fasterxml.jackson.annotation.JsonIgnore | ||
import com.fasterxml.jackson.annotation.JsonInclude | ||
|
||
import org.ossreviewtoolkit.model.Identifier | ||
import org.ossreviewtoolkit.spdx.model.LicenseChoice | ||
|
||
/** | ||
* The license choices configured for a repository. | ||
*/ | ||
data class LicenseChoices( | ||
@JsonInclude(JsonInclude.Include.NON_EMPTY) | ||
val packageLicenseChoices: List<PackageLicenseChoice> = emptyList() | ||
) { | ||
@JsonIgnore | ||
fun isEmpty() = packageLicenseChoices.isEmpty() | ||
} | ||
|
||
/** | ||
* [LicenseChoice]s defined for an artifact. | ||
*/ | ||
data class PackageLicenseChoice( | ||
val packageId: Identifier, | ||
@JsonInclude(JsonInclude.Include.NON_EMPTY) | ||
val licenseChoices: List<LicenseChoice> = emptyList() | ||
) |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -29,6 +29,7 @@ import org.ossreviewtoolkit.model.config.LicenseFindingCuration | |
import org.ossreviewtoolkit.model.config.PathExclude | ||
import org.ossreviewtoolkit.spdx.SpdxExpression | ||
import org.ossreviewtoolkit.spdx.SpdxSingleLicenseExpression | ||
import org.ossreviewtoolkit.spdx.model.LicenseChoice | ||
import org.ossreviewtoolkit.utils.CopyrightStatementsProcessor | ||
import org.ossreviewtoolkit.utils.DeclaredLicenseProcessor | ||
|
||
|
@@ -65,6 +66,23 @@ data class ResolvedLicenseInfo( | |
) : Iterable<ResolvedLicense> by licenses { | ||
operator fun get(license: SpdxSingleLicenseExpression): ResolvedLicense? = find { it.license == license } | ||
|
||
/** | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. IIUC this resolved license info class has all configuration relevant for computing the needed information in its attributes. So, what's the reason for not adding an attribute for the applicable license choices to the data model? For Note: I'm haven't myself yet fully understood this area of the code, so I rather want to get the discussion going, but don't intent to say it's wrong as-is. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes we thought about this. This implementation decision was a direct result of a discussion in the developers meeting on 2021-03-04, we developed it in pair programming with @mnonnenmacher. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Exactly, the problem is that the license choice can only be applied if the sub-expression matches, and if it does can depend on the used |
||
* Return the effective [SpdxExpression] of this [ResolvedLicenseInfo] based on their [licenses] filtered by the | ||
* [licenseView] and the applied [licenseChoices]. Effective, in this context, refers to an [SpdxExpression] that | ||
* can be used as a final license of this [ResolvedLicenseInfo]. | ||
*/ | ||
fun effectiveLicense(licenseView: LicenseView, licenseChoices: List<LicenseChoice> = emptyList()): SpdxExpression? { | ||
val resolvedLicenseInfo = filter(licenseView, filterSources = true) | ||
|
||
return resolvedLicenseInfo.licenses.flatMap { it.originalExpressions.values } | ||
.flatten() | ||
.toSet() | ||
.reduceOrNull(SpdxExpression::and) | ||
?.applyChoices(licenseChoices) | ||
?.validChoices() | ||
?.reduceOrNull(SpdxExpression::or) | ||
} | ||
|
||
/** | ||
* Return all copyright statements associated to this license info. Copyright findings that are excluded by | ||
* [PathExclude]s are [omitted][omitExcluded] by default. The copyrights are [processed][process] by default | ||
|
@@ -96,6 +114,15 @@ data class ResolvedLicenseInfo( | |
} | ||
} | ||
|
||
/** | ||
* Apply [licenseChoices] on the effective license of [LicenseView.ALL]. | ||
*/ | ||
fun applyChoices(licenseChoices: List<LicenseChoice>): ResolvedLicenseInfo { | ||
val licenses = effectiveLicense(LicenseView.ALL, licenseChoices)?.decompose().orEmpty() | ||
|
||
return this.copy(licenses = this.licenses.filter { it.license in licenses }) | ||
} | ||
|
||
/** | ||
* Filter all excluded licenses and copyrights. Licenses are removed if they are only | ||
* [detected][LicenseSource.DETECTED] and all [locations][ResolvedLicense.locations] have | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I assumed that in future we'll have license choices also defined elsewhere, so the license choices do not only come from the OrtResult. This is why I looked up how path excludes and license finding curations are retrieved.
I found that they get injected into
DefaultLicenseInfoProvider
to be used by theLicenseInfoResolver
.Have you considered processing license choices in a similar / analog way?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would it be ok for you to refactor this when other license choice configurations are added?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd actually like to also have @mnonnenmacher opinion on that as he has written the parts relevant here before diving deeper into this. I fear that it could be quite a bit of tech debt, but let's see.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree, the design idea is that the
LicenseInfoResolver
gets all required information from theLicenseInfo
and therefore it would make sense to also add the choices there. But I would be fine with changing this separately, because I currently cannot decide which would be the best way to integrate the choices there.