diff --git a/docs/src/checks/licenses/cfg.md b/docs/src/checks/licenses/cfg.md index 57a29319..0c49c52a 100644 --- a/docs/src/checks/licenses/cfg.md +++ b/docs/src/checks/licenses/cfg.md @@ -235,3 +235,11 @@ private = { ignore = true, registries = ["sauce"] } ``` [SPDX-expr]: https://spdx.org/spdx-specification-21-web-version#h.jxpfx0ykyb60 + +### The `unused-allowed-license` field (optional) + +Determines what happens when one of the licenses that appears in the `allow` list is not encountered in the dependency graph. + +* `warn` (default) - A warning is emitted for each license that appears in `license.allow` but which is not used in any crate. +* `allow` - Unused licenses in the `licenses.allow` list are ignored. +* `deny` - An unused license in the `licenses.allow` list triggers an error, and cause the license check to fail. diff --git a/docs/src/checks/licenses/diags.md b/docs/src/checks/licenses/diags.md index 410c67b0..a8070009 100644 --- a/docs/src/checks/licenses/diags.md +++ b/docs/src/checks/licenses/diags.md @@ -23,3 +23,5 @@ A [`licenses.exception`](cfg.md#the-exceptions-field-optional) was not used as t ### `L006` - license was not encountered A license in [`licenses.allow`](cfg.md#the-allow-and-deny-fields-optional) was not found in any crate. + +This diagnostic can be silenced by configuring the [`licenses.unused-allowed-license`](cfg.md#the-unused-allowed-license-field-optional) field to "allow". diff --git a/src/licenses.rs b/src/licenses.rs index 80782f60..6788f03a 100644 --- a/src/licenses.rs +++ b/src/licenses.rs @@ -354,7 +354,7 @@ pub fn check( { let mut pack = Pack::new(Check::Licenses); - // Print out warnings for allowed licenses that weren't encountered. + // Print diagnostics for allowed licenses that weren't encountered. // Note that we don't do the same for denied licenses for allowed in hits .allowed @@ -363,6 +363,7 @@ pub fn check( .filter_map(|(hit, allowed)| if !hit { Some(allowed) } else { None }) { pack.push(diags::UnmatchedLicenseAllowance { + severity: ctx.cfg.unused_allowed_license.into(), allowed_license_cfg: CfgCoord { file: ctx.cfg.file_id, span: allowed.span, diff --git a/src/licenses/cfg.rs b/src/licenses/cfg.rs index d1b5f647..922ffbcd 100644 --- a/src/licenses/cfg.rs +++ b/src/licenses/cfg.rs @@ -155,6 +155,10 @@ pub struct Config { /// Licenses that will be allowed in a license expression #[serde(default)] pub allow: Vec>, + /// Determines the response to licenses in th `allow`ed list which do not + /// exist in the dependency tree. + #[serde(default = "crate::lint_warn")] + pub unused_allowed_license: LintLevel, /// Overrides the license expression used for a particular crate as long as /// it exactly matches the specified license files and hashes #[serde(default)] @@ -173,6 +177,7 @@ impl Default for Config { allow_osi_fsf_free: BlanketAgreement::default(), copyleft: LintLevel::Warn, default: LintLevel::Deny, + unused_allowed_license: LintLevel::Warn, confidence_threshold: confidence_threshold(), deny: Vec::new(), allow: Vec::new(), @@ -294,6 +299,7 @@ impl crate::cfg::UnvalidatedConfig for Config { unlicensed: self.unlicensed, copyleft: self.copyleft, default: self.default, + unused_allowed_license: self.unused_allowed_license, allow_osi_fsf_free: self.allow_osi_fsf_free, confidence_threshold: self.confidence_threshold, clarifications, @@ -330,6 +336,7 @@ pub struct ValidConfig { pub private: Private, pub unlicensed: LintLevel, pub copyleft: LintLevel, + pub unused_allowed_license: LintLevel, pub allow_osi_fsf_free: BlanketAgreement, pub default: LintLevel, pub confidence_threshold: f32, @@ -363,6 +370,7 @@ mod test { assert_eq!(validated.private.registries, vec!["sekrets".to_owned()]); assert_eq!(validated.unlicensed, LintLevel::Warn); assert_eq!(validated.copyleft, LintLevel::Deny); + assert_eq!(validated.unused_allowed_license, LintLevel::Warn); assert_eq!(validated.default, LintLevel::Warn); assert_eq!(validated.allow_osi_fsf_free, BlanketAgreement::Both); assert_eq!( @@ -398,7 +406,7 @@ mod test { path: p.fake(), hash: 0xbd0e_ed23, }], - expr_offset: 432, + expr_offset: 464, }] ); } diff --git a/src/licenses/diags.rs b/src/licenses/diags.rs index ca17601f..f080a127 100644 --- a/src/licenses/diags.rs +++ b/src/licenses/diags.rs @@ -50,12 +50,13 @@ impl Into for UnmatchedLicenseException { } pub(crate) struct UnmatchedLicenseAllowance { + pub(crate) severity: Severity, pub(crate) allowed_license_cfg: CfgCoord, } impl Into for UnmatchedLicenseAllowance { fn into(self) -> Diag { - Diagnostic::new(Severity::Warning) + Diagnostic::new(self.severity) .with_message("license was not encountered") .with_code("L006") .with_labels(vec![self diff --git a/tests/cfg/licenses.toml b/tests/cfg/licenses.toml index 3f42ec7d..b55b54b5 100644 --- a/tests/cfg/licenses.toml +++ b/tests/cfg/licenses.toml @@ -3,6 +3,7 @@ unlicensed = "warn" allow-osi-fsf-free = "both" copyleft = "deny" default = "warn" +unused-allowed-license = "warn" confidence-threshold = 0.95 deny = [ "Nokia",