alpm_lint/lint_rules/source_info/
duplicate_architecture.rs1use std::collections::{BTreeMap, HashSet};
4
5use documented::Documented;
6
7use crate::{
8 internal_prelude::*,
9 issue::SourceInfoIssue,
10 lint_rules::source_info::source_info_from_resource,
11};
12
13#[derive(Clone, Debug, Documented)]
44pub struct DuplicateArchitecture {}
45
46impl DuplicateArchitecture {
47 pub fn new_boxed(_: &LintRuleConfiguration) -> Box<dyn LintRule> {
51 Box::new(DuplicateArchitecture {})
52 }
53}
54
55impl LintRule for DuplicateArchitecture {
56 fn name(&self) -> &'static str {
57 "duplicate_architecture"
58 }
59
60 fn scope(&self) -> LintScope {
61 LintScope::SourceInfo
62 }
63
64 fn documentation(&self) -> String {
65 DuplicateArchitecture::DOCS.into()
66 }
67
68 fn help_text(&self) -> String {
69 r#"Architecture lists for packages should always be unique.
70
71Duplicate architecture declarations such as `arch=(x86_64 x86_64)` are ignored.
72"#
73 .into()
74 }
75
76 fn run(&self, resources: &Resources, issues: &mut Vec<LintIssue>) -> Result<(), Error> {
77 let source_info = source_info_from_resource(resources, self.scoped_name())?;
79
80 let mut known = HashSet::new();
81 for architecture in &source_info.base.architectures {
82 if known.contains(&architecture) {
83 issues.push(LintIssue::from_rule(
84 self,
85 SourceInfoIssue::BaseField {
86 field_name: "arch".to_string(),
87 value: architecture.to_string(),
88 context: "Found duplicate architecture".to_string(),
89 architecture: None,
90 }
91 .into(),
92 ));
93 }
94 known.insert(architecture);
95 }
96
97 Ok(())
98 }
99
100 fn extra_links(&self) -> Option<BTreeMap<String, String>> {
101 let mut links = BTreeMap::new();
102 links.insert(
103 "alpm-architecture specification".to_string(),
104 "https://alpm.archlinux.page/specifications/alpm-architecture.7.html".to_string(),
105 );
106 Some(links)
107 }
108}