pacsea/logic/
distro.rs

1//! Distro-related logic helpers (filtering and labels).
2
3/// What: Determine whether results from a repository should be visible under current toggles.
4///
5/// Inputs:
6/// - `repo`: Name of the repository associated with a package result.
7/// - `app`: Application state providing the filter toggles for official repos.
8///
9/// Output:
10/// - `true` when the repository passes the active filters; otherwise `false`.
11///
12/// Details:
13/// - Normalizes repository names and applies special-handling for EOS/CachyOS/Artix classification helpers.
14/// - Unknown repositories are only allowed when every official filter is enabled simultaneously.
15#[must_use]
16pub fn repo_toggle_for(repo: &str, app: &crate::state::AppState) -> bool {
17    let r = repo.to_lowercase();
18    if r == "core" {
19        app.results_filter_show_core
20    } else if r == "extra" {
21        app.results_filter_show_extra
22    } else if r == "multilib" {
23        app.results_filter_show_multilib
24    } else if crate::index::is_eos_repo(&r) {
25        app.results_filter_show_eos
26    } else if crate::index::is_cachyos_repo(&r) {
27        app.results_filter_show_cachyos
28    } else if crate::index::is_artix_omniverse(&r) {
29        app.results_filter_show_artix_omniverse
30    } else if crate::index::is_artix_universe(&r) {
31        app.results_filter_show_artix_universe
32    } else if crate::index::is_artix_lib32(&r) {
33        app.results_filter_show_artix_lib32
34    } else if crate::index::is_artix_galaxy(&r) {
35        app.results_filter_show_artix_galaxy
36    } else if crate::index::is_artix_world(&r) {
37        app.results_filter_show_artix_world
38    } else if crate::index::is_artix_system(&r) {
39        app.results_filter_show_artix_system
40    } else if crate::index::is_artix_repo(&r) {
41        // Fallback for any other Artix repo (shouldn't happen, but safe)
42        app.results_filter_show_artix
43    } else {
44        // Unknown official repo: include only when all official filters are enabled
45        app.results_filter_show_core
46            && app.results_filter_show_extra
47            && app.results_filter_show_multilib
48            && app.results_filter_show_eos
49            && app.results_filter_show_cachyos
50            && app.results_filter_show_artix
51            && app.results_filter_show_artix_omniverse
52            && app.results_filter_show_artix_universe
53            && app.results_filter_show_artix_lib32
54            && app.results_filter_show_artix_galaxy
55            && app.results_filter_show_artix_world
56            && app.results_filter_show_artix_system
57    }
58}
59
60/// What: Produce a human-friendly label for an official package entry.
61///
62/// Inputs:
63/// - `repo`: Repository reported by the package source.
64/// - `name`: Package name used to detect Manjaro naming conventions.
65/// - `owner`: Optional upstream owner string available from package metadata.
66///
67/// Output:
68/// - Returns a display label describing the ecosystem the package belongs to.
69///
70/// Details:
71/// - Distinguishes `EndeavourOS`, `CachyOS`, and `Artix Linux` repos (with specific labels for each Artix repo:
72///   `OMNI`, `UNI`, `LIB32`, `GALAXY`, `WORLD`, `SYSTEM`), and detects `Manjaro` branding by name/owner heuristics.
73/// - Falls back to the raw repository string when no special classification matches.
74#[must_use]
75pub fn label_for_official(repo: &str, name: &str, owner: &str) -> String {
76    let r = repo.to_lowercase();
77    if crate::index::is_eos_repo(&r) {
78        "EOS".to_string()
79    } else if crate::index::is_cachyos_repo(&r) {
80        "CachyOS".to_string()
81    } else if crate::index::is_artix_omniverse(&r) {
82        "OMNI".to_string()
83    } else if crate::index::is_artix_universe(&r) {
84        "UNI".to_string()
85    } else if crate::index::is_artix_lib32(&r) {
86        "LIB32".to_string()
87    } else if crate::index::is_artix_galaxy(&r) {
88        "GALAXY".to_string()
89    } else if crate::index::is_artix_world(&r) {
90        "WORLD".to_string()
91    } else if crate::index::is_artix_system(&r) {
92        "SYSTEM".to_string()
93    } else if crate::index::is_artix_repo(&r) {
94        // Fallback for any other Artix repo (shouldn't happen, but safe)
95        "Artix".to_string()
96    } else if crate::index::is_manjaro_name_or_owner(name, owner) {
97        "Manjaro".to_string()
98    } else {
99        repo.to_string()
100    }
101}
102
103#[cfg(test)]
104mod tests {
105    use super::*;
106    use crate::state::AppState;
107
108    #[test]
109    /// What: Validate canonical repository toggles deny disabled repositories while permitting enabled ones.
110    ///
111    /// Inputs:
112    /// - `app`: Application state with `core` enabled and other official toggles disabled.
113    ///
114    /// Output:
115    /// - `repo_toggle_for` allows `core` entries but rejects `extra` and `multilib`.
116    ///
117    /// Details:
118    /// - Ensures the per-repository gate respects the individual boolean flags.
119    fn repo_toggle_respects_individual_flags() {
120        let app = AppState {
121            results_filter_show_core: true,
122            results_filter_show_extra: false,
123            results_filter_show_multilib: false,
124            results_filter_show_eos: false,
125            results_filter_show_cachyos: false,
126            results_filter_show_artix: false,
127            results_filter_show_artix_omniverse: false,
128            results_filter_show_artix_universe: false,
129            results_filter_show_artix_lib32: false,
130            results_filter_show_artix_galaxy: false,
131            results_filter_show_artix_world: false,
132            results_filter_show_artix_system: false,
133            ..Default::default()
134        };
135
136        assert!(repo_toggle_for("core", &app));
137        assert!(!repo_toggle_for("extra", &app));
138        assert!(!repo_toggle_for("multilib", &app));
139    }
140
141    #[test]
142    /// What: Ensure unknown official repositories require every official toggle to be enabled.
143    ///
144    /// Inputs:
145    /// - `app`: Application state with all official flags on, then one flag disabled.
146    ///
147    /// Output:
148    /// - Unknown repository accepted when fully enabled and rejected once any flag is turned off.
149    ///
150    /// Details:
151    /// - Exercises the fallback clause guarding unfamiliar repositories.
152    fn repo_toggle_unknown_only_with_full_whitelist() {
153        let mut app = AppState {
154            results_filter_show_core: true,
155            results_filter_show_extra: true,
156            results_filter_show_multilib: true,
157            results_filter_show_eos: true,
158            results_filter_show_cachyos: true,
159            results_filter_show_artix: true,
160            results_filter_show_artix_omniverse: true,
161            results_filter_show_artix_universe: true,
162            results_filter_show_artix_lib32: true,
163            results_filter_show_artix_galaxy: true,
164            results_filter_show_artix_world: true,
165            results_filter_show_artix_system: true,
166            ..Default::default()
167        };
168
169        assert!(repo_toggle_for("unlisted", &app));
170
171        app.results_filter_show_multilib = false;
172        assert!(!repo_toggle_for("unlisted", &app));
173    }
174
175    #[test]
176    /// What: Confirm label helper emits ecosystem-specific aliases for recognised repositories.
177    ///
178    /// Inputs:
179    /// - Repository/name permutations covering `EndeavourOS`, `CachyOS`, `Artix Linux` (with specific repo labels), `Manjaro`, and a generic repo.
180    ///
181    /// Output:
182    /// - Labels reduce to `EOS`, `CachyOS`, `OMNI`, `UNI` (for specific Artix repos), `Manjaro`, and the original repo name respectively.
183    ///
184    /// Details:
185    /// - Validates the Manjaro heuristic via package name and the repo classification helpers.
186    /// - Confirms specific Artix repos return their specific labels (OMNI, UNI, etc.) rather than the generic "Artix" label.
187    fn label_for_official_prefers_special_cases() {
188        assert_eq!(label_for_official("endeavouros", "pkg", ""), "EOS");
189        assert_eq!(label_for_official("cachyos-extra", "pkg", ""), "CachyOS");
190        assert_eq!(label_for_official("omniverse", "pkg", ""), "OMNI");
191        assert_eq!(label_for_official("universe", "pkg", ""), "UNI");
192        assert_eq!(label_for_official("extra", "manjaro-kernel", ""), "Manjaro");
193        assert_eq!(label_for_official("core", "glibc", ""), "core");
194    }
195}