alpm_lint/lint_rules/source_info/
invalid_spdx_license.rs1use std::collections::BTreeMap;
7
8use alpm_srcinfo::source_info::v1::package::Override;
9use documented::Documented;
10
11use crate::{
12 Level,
13 internal_prelude::*,
14 issue::SourceInfoIssue,
15 lint_rules::source_info::source_info_from_resource,
16};
17
18#[derive(Clone, Debug, Documented)]
54pub struct NotSPDX {}
55
56impl NotSPDX {
57 pub fn new_boxed(_: &LintRuleConfiguration) -> Box<dyn LintRule> {
59 Box::new(Self {})
60 }
61}
62
63impl LintRule for NotSPDX {
64 fn name(&self) -> &'static str {
65 "invalid_spdx_license"
66 }
67
68 fn scope(&self) -> LintScope {
69 LintScope::SourceInfo
70 }
71
72 fn level(&self) -> Level {
73 Level::Deny
74 }
75
76 fn documentation(&self) -> String {
77 NotSPDX::DOCS.into()
78 }
79
80 fn help_text(&self) -> String {
81 r#"Licenses should use SPDX identifiers as specified in the Arch Linux RFC 0016.
82
83SPDX license identifiers provide a standardized way to identify licenses.
84- Apache-2.0 (instead of "Apache")
85- GPL-3.0-or-later or GPL-3.0-only (instead of "GPL3")
86- MIT (instead of "MIT License")
87"#
88 .into()
89 }
90
91 fn run(&self, resources: &Resources, issues: &mut Vec<LintIssue>) -> Result<(), Error> {
92 let source_info = source_info_from_resource(resources, self.scoped_name())?;
94
95 for license in &source_info.base.licenses {
97 if !license.is_spdx() {
98 issues.push(LintIssue::from_rule(
99 self,
100 SourceInfoIssue::BaseField {
101 field_name: "license".to_string(),
102 value: license.to_string(),
103 context: "License is not SPDX compliant".to_string(),
104 architecture: None,
105 }
106 .into(),
107 ));
108 }
109 }
110
111 for package in &source_info.packages {
113 let Override::Yes { value } = &package.licenses else {
115 continue;
116 };
117
118 for license in value {
119 if !license.is_spdx() {
120 issues.push(LintIssue::from_rule(
121 self,
122 SourceInfoIssue::PackageField {
123 package_name: package.name.to_string(),
124 field_name: "license".to_string(),
125 value: license.to_string(),
126 context: "License is not SPDX compliant".to_string(),
127 architecture: None,
128 }
129 .into(),
130 ));
131 }
132 }
133 }
134
135 Ok(())
136 }
137
138 fn extra_links(&self) -> Option<BTreeMap<String, String>> {
140 let mut links = BTreeMap::new();
141 links.insert(
142 "Arch Linux RFC 0016".to_string(),
143 "https://rfc.archlinux.page/0016-spdx-license-identifiers/".to_string(),
144 );
145 links.insert(
146 "SRCINFO specification".to_string(),
147 "https://alpm.archlinux.page/specifications/SRCINFO.5.html".to_string(),
148 );
149
150 Some(links)
151 }
152}