alpm_lint/lint_rules/source_info/
long_values_aurweb.rs1use std::collections::BTreeMap;
6
7use alpm_lint_config::LintRuleConfiguration;
8use alpm_srcinfo::source_info::v1::package::Override;
9use documented::Documented;
10
11use crate::{
12 internal_prelude::*,
13 issue::SourceInfoIssue,
14 lint_rules::source_info::source_info_from_resource,
15};
16
17type Field = (&'static str, String, usize);
23
24pub mod limits {
28 pub(super) fn docsrs_page() -> String {
33 const CARGO_PKG_NAME: &str = env!("CARGO_PKG_NAME");
34 let module_path = const { module_path!() }.replace("::", "/");
35
36 format!("https://docs.rs/{CARGO_PKG_NAME}/latest/{module_path}/index.html")
37 }
38
39 pub const PKGBASE: usize = 255;
44 pub const PKGNAME: usize = 255;
46 pub const PKGDESC: usize = 255;
48 pub const URL: usize = 8000;
50}
51
52#[derive(Clone, Debug, Documented)]
58pub struct LongValuesAurweb;
59
60impl LongValuesAurweb {
61 pub fn new_boxed(_config: &LintRuleConfiguration) -> Box<dyn LintRule> {
63 Box::new(Self {})
64 }
65}
66
67impl LintRule for LongValuesAurweb {
68 fn name(&self) -> &'static str {
69 "long_values_aurweb"
70 }
71
72 fn scope(&self) -> LintScope {
73 LintScope::SourceInfo
74 }
75
76 fn level(&self) -> Level {
77 Level::Warn
78 }
79 fn documentation(&self) -> String {
80 Self::DOCS.into()
81 }
82
83 fn help_text(&self) -> String {
84 "Value for SRCINFO keywords exceed the byte length restrictions enforced by the aurweb application."
85 .to_string()
86 }
87
88 fn run(&self, resources: &Resources, issues: &mut Vec<LintIssue>) -> Result<(), Error> {
89 let source_info = source_info_from_resource(resources, self.scoped_name())?;
91
92 let fields: Vec<Field> = {
93 let base = &source_info.base;
94 let mut fields = vec![("pkgbase", base.name.to_string(), limits::PKGBASE)];
95
96 if let Some(desc) = base.description.as_ref() {
97 fields.push(("pkgdesc", desc.to_string(), limits::PKGDESC));
98 }
99
100 if let Some(url) = base.url.as_ref() {
101 fields.push(("url", url.to_string(), limits::URL));
102 }
103
104 fields
105 };
106
107 for (keyword, value, limit) in fields {
108 if value.len() > limit {
109 issues.push(LintIssue::from_rule(
110 self,
111 SourceInfoIssue::BaseField {
112 field_name: keyword.into(),
113 value,
114 context: format!("`{keyword}` value exceeded {limit} bytes"),
115 architecture: None,
116 }
117 .into(),
118 ));
119 }
120 }
121
122 for package in &source_info.packages {
123 let fields: Vec<Field> = {
124 let mut fields = vec![("pkgname", package.name.to_string(), limits::PKGNAME)];
125
126 if let Override::Yes { ref value } = package.description {
127 fields.push(("pkgdesc", value.to_string(), limits::PKGDESC));
128 }
129
130 if let Override::Yes { ref value } = package.url {
131 fields.push(("url", value.to_string(), limits::URL));
132 }
133
134 fields
135 };
136
137 for (keyword, value, limit) in fields {
138 if value.len() > limit {
139 issues.push(LintIssue::from_rule(
140 self,
141 SourceInfoIssue::PackageField {
142 field_name: keyword.into(),
143 package_name: package.name.to_string(),
144 value,
145 context: format!("`{keyword}` value exceeded {limit} bytes"),
146 architecture: None,
147 }
148 .into(),
149 ));
150 }
151 }
152 }
153
154 Ok(())
155 }
156
157 fn extra_links(&self) -> Option<BTreeMap<String, String>> {
158 let mut links = BTreeMap::new();
159
160 links.insert("Byte limits".to_string(), limits::docsrs_page());
161 links.insert(
162 "SRCINFO".to_string(),
163 "https://alpm.archlinux.page/specifications/SRCINFO.5.html".to_string(),
164 );
165
166 Some(links)
167 }
168}