Skip to main content

pacsea/logic/
aur_official_catalog_dup.rs

1//! Detect AUR-selected installs whose `pkgname` also appears as an official/sync row in a catalog.
2
3use std::collections::HashSet;
4
5use crate::state::types::{PackageItem, Source};
6
7/// What: Names of AUR-sourced install items that also have an official/sync row in `catalog`.
8///
9/// Inputs:
10/// - `install`: Packages queued for install.
11/// - `catalog`: Result rows to scan (typically `all_results` chained with `results`).
12///
13/// Output:
14/// - Sorted unique names for stable UI.
15///
16/// Details:
17/// - Uses exact `pkgname` equality; does not compare `pkgbase` or providers.
18#[must_use]
19pub fn aur_pkgnames_also_in_official_catalog(
20    install: &[PackageItem],
21    catalog: &[PackageItem],
22) -> Vec<String> {
23    let official: HashSet<&str> = catalog
24        .iter()
25        .filter_map(|p| matches!(p.source, Source::Official { .. }).then_some(p.name.as_str()))
26        .collect();
27    let mut names: Vec<String> = install
28        .iter()
29        .filter(|p| matches!(p.source, Source::Aur) && official.contains(p.name.as_str()))
30        .map(|p| p.name.clone())
31        .collect();
32    names.sort();
33    names.dedup();
34    names
35}
36
37#[cfg(test)]
38mod tests {
39    use super::*;
40
41    fn off(name: &str) -> PackageItem {
42        PackageItem {
43            name: name.into(),
44            version: String::new(),
45            description: String::new(),
46            source: Source::Official {
47                repo: "extra".into(),
48                arch: "x86_64".into(),
49            },
50            popularity: None,
51            out_of_date: None,
52            orphaned: false,
53        }
54    }
55
56    fn aur(name: &str) -> PackageItem {
57        PackageItem {
58            name: name.into(),
59            version: String::new(),
60            description: String::new(),
61            source: Source::Aur,
62            popularity: None,
63            out_of_date: None,
64            orphaned: false,
65        }
66    }
67
68    #[test]
69    fn detects_aur_when_official_same_name_in_catalog() {
70        let catalog = vec![off("foo"), aur("bar")];
71        let install = vec![aur("foo")];
72        let d = aur_pkgnames_also_in_official_catalog(&install, &catalog);
73        assert_eq!(d, vec!["foo".to_string()]);
74    }
75
76    #[test]
77    fn empty_when_no_official_sibling() {
78        let catalog = vec![aur("foo")];
79        let install = vec![aur("foo")];
80        assert!(aur_pkgnames_also_in_official_catalog(&install, &catalog).is_empty());
81    }
82}