#![allow(dead_code)]
#[allow(dead_code)]
#[derive(Debug, Clone)]
pub struct LicenseEntry {
pub spdx_id: String,
pub name: String,
pub url: String,
pub osi_approved: bool,
}
#[allow(dead_code)]
pub struct LicenseManifest {
pub project: String,
pub entries: Vec<LicenseEntry>,
}
impl LicenseManifest {
#[allow(dead_code)]
pub fn new(project: &str) -> Self {
Self {
project: project.to_string(),
entries: Vec::new(),
}
}
}
#[allow(dead_code)]
pub fn add_license(
manifest: &mut LicenseManifest,
spdx_id: &str,
name: &str,
url: &str,
osi: bool,
) {
manifest.entries.push(LicenseEntry {
spdx_id: spdx_id.to_string(),
name: name.to_string(),
url: url.to_string(),
osi_approved: osi,
});
}
#[allow(dead_code)]
pub fn export_spdx_expression(manifest: &LicenseManifest) -> String {
manifest
.entries
.iter()
.map(|e| e.spdx_id.as_str())
.collect::<Vec<_>>()
.join(" OR ")
}
#[allow(dead_code)]
pub fn export_license_txt(manifest: &LicenseManifest) -> String {
let mut out = format!("Project: {}\n\nLicenses:\n", manifest.project);
for e in &manifest.entries {
out.push_str(&format!(
" {} ({})\n URL: {}\n OSI Approved: {}\n\n",
e.spdx_id, e.name, e.url, e.osi_approved
));
}
out
}
#[allow(dead_code)]
pub fn export_license_json(manifest: &LicenseManifest) -> String {
let mut out = format!("{{\"project\":\"{}\",\"licenses\":[", manifest.project);
for (i, e) in manifest.entries.iter().enumerate() {
if i > 0 {
out.push(',');
}
out.push_str(&format!(
"{{\"spdx_id\":\"{}\",\"name\":\"{}\",\"url\":\"{}\",\"osi_approved\":{}}}",
e.spdx_id, e.name, e.url, e.osi_approved
));
}
out.push_str("]}");
out
}
#[allow(dead_code)]
pub fn osi_approved_count(manifest: &LicenseManifest) -> usize {
manifest.entries.iter().filter(|e| e.osi_approved).count()
}
#[allow(dead_code)]
pub fn license_count(manifest: &LicenseManifest) -> usize {
manifest.entries.len()
}
#[allow(dead_code)]
pub fn find_by_spdx_id<'a>(
manifest: &'a LicenseManifest,
spdx_id: &str,
) -> Option<&'a LicenseEntry> {
manifest.entries.iter().find(|e| e.spdx_id == spdx_id)
}
#[allow(dead_code)]
pub fn has_license(manifest: &LicenseManifest, spdx_id: &str) -> bool {
manifest.entries.iter().any(|e| e.spdx_id == spdx_id)
}
#[allow(dead_code)]
pub fn remove_license(manifest: &mut LicenseManifest, spdx_id: &str) -> bool {
let before = manifest.entries.len();
manifest.entries.retain(|e| e.spdx_id != spdx_id);
manifest.entries.len() < before
}
#[cfg(test)]
mod tests {
use super::*;
fn sample_manifest() -> LicenseManifest {
let mut m = LicenseManifest::new("oxihuman");
add_license(
&mut m,
"MIT",
"MIT License",
"https://opensource.org/licenses/MIT",
true,
);
add_license(
&mut m,
"Apache-2.0",
"Apache License 2.0",
"https://www.apache.org/licenses/LICENSE-2.0",
true,
);
add_license(
&mut m,
"GPL-3.0-only",
"GNU General Public License v3.0 only",
"https://www.gnu.org/licenses/gpl-3.0.html",
true,
);
m
}
#[test]
fn license_count_correct() {
let m = sample_manifest();
assert_eq!(license_count(&m), 3);
}
#[test]
fn osi_approved_count_correct() {
let m = sample_manifest();
assert_eq!(osi_approved_count(&m), 3);
}
#[test]
fn spdx_expression_contains_or() {
let m = sample_manifest();
let expr = export_spdx_expression(&m);
assert!(expr.contains(" OR "));
}
#[test]
fn spdx_expression_contains_mit() {
let m = sample_manifest();
let expr = export_spdx_expression(&m);
assert!(expr.contains("MIT"));
}
#[test]
fn has_license_true() {
let m = sample_manifest();
assert!(has_license(&m, "MIT"));
}
#[test]
fn has_license_false() {
let m = sample_manifest();
assert!(!has_license(&m, "BSD-3-Clause"));
}
#[test]
fn find_by_spdx_id_some() {
let m = sample_manifest();
let e = find_by_spdx_id(&m, "Apache-2.0");
assert!(e.is_some());
}
#[test]
fn find_by_spdx_id_none() {
let m = sample_manifest();
assert!(find_by_spdx_id(&m, "LGPL-2.1").is_none());
}
#[test]
fn remove_license_success() {
let mut m = sample_manifest();
let removed = remove_license(&mut m, "GPL-3.0-only");
assert!(removed);
assert_eq!(license_count(&m), 2);
}
#[test]
fn txt_contains_project_name() {
let m = sample_manifest();
let txt = export_license_txt(&m);
assert!(txt.contains("oxihuman"));
}
}