From f73d9043e441504bbbb341190049a31fbb4c0462 Mon Sep 17 00:00:00 2001 From: Aaron Manning Date: Tue, 15 Oct 2024 12:28:21 +1100 Subject: [PATCH] Check SPDX-2 expression and OSI compatibility for license --- Cargo.lock | 10 ++++++++++ Cargo.toml | 1 + src/check/manifest.rs | 35 +++++++++++++++++++++++++++++++++-- 3 files changed, 44 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 435c95e..55f797b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2792,6 +2792,15 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "spdx" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47317bbaf63785b53861e1ae2d11b80d6b624211d42cb20efcd210ee6f8a14bc" +dependencies = [ + "smallvec", +] + [[package]] name = "spin" version = "0.9.8" @@ -3465,6 +3474,7 @@ dependencies = [ "serde", "serde_json", "sha1", + "spdx", "stringcase", "tar", "tokio", diff --git a/Cargo.toml b/Cargo.toml index d8d903c..c119cf1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -26,6 +26,7 @@ reqwest = { version = "0.12.4", features = ["json"] } serde = { version = "1.0.198", features = ["derive"] } serde_json = "1.0.116" sha1 = "0.10.6" +spdx = "0.10" stringcase = "0.2.1" tar = "0.4.40" tokio = { version = "1.37.0", features = ["rt-multi-thread", "process", "fs"] } diff --git a/src/check/manifest.rs b/src/check/manifest.rs index 3faef81..aff1ce8 100644 --- a/src/check/manifest.rs +++ b/src/check/manifest.rs @@ -419,13 +419,44 @@ fn check_universe_fields( .as_table() .context("[package] is not a table")?; - if pkg.get("license").map(|l| !l.is_str()).unwrap_or(true) { + if let Some((license, span)) = pkg.get("license").and_then(|l| + l.as_str().map(|s| (s, l.span().unwrap_or_default())) + ) { + if let Ok(license) = spdx::Expression::parse(license) { + for requirement in license.requirements() { + if let Some(id) = requirement + .req + .license + .id() + { + if !id.is_osi_approved() { + diags.emit( + Diagnostic::error() + .with_message("The `license` field should be OSI approved") + .with_labels(vec![Label::primary(manifest_file_id, span.clone())]), + ); + } + } else { + diags.emit( + Diagnostic::error() + .with_message("The `license` field should not contain a referencer") + .with_labels(vec![Label::primary(manifest_file_id, span.clone())]), + ); + } + } + } else { + diags.emit( + Diagnostic::error() + .with_message("The `license` field should be a valid SPDX-2 expression") + .with_labels(vec![Label::primary(manifest_file_id, span.clone())]), + ); + } + } else { diags.emit( Diagnostic::error() .with_message("The `license` field should be a string") .with_labels(vec![Label::primary(manifest_file_id, 0..0)]), ); - // TODO: check that it is a valid SPDX identifier and that it is OSI approved? } if pkg.get("description").map(|d| !d.is_str()).unwrap_or(true) {