Skip to main content

krypt_pkg/
detect.rs

1//! Auto-detection of available package managers.
2
3use crate::apt::Apt;
4use crate::brew::Brew;
5use crate::dnf::Dnf;
6use crate::manager::PackageManager;
7use crate::pacman::Pacman;
8use crate::scoop::Scoop;
9use crate::winget::Winget;
10
11/// Return every package manager whose binary is on `PATH`, ordered by
12/// platform preference.
13///
14/// Order:
15/// - macOS: brew
16/// - Windows: scoop, winget
17/// - Linux: pacman, dnf, apt
18pub fn detect_all() -> Vec<Box<dyn PackageManager>> {
19    let candidates: Vec<Box<dyn PackageManager>> = if cfg!(target_os = "macos") {
20        vec![Box::new(Brew)]
21    } else if cfg!(target_os = "windows") {
22        vec![Box::new(Scoop), Box::new(Winget)]
23    } else {
24        vec![Box::new(Pacman), Box::new(Dnf), Box::new(Apt)]
25    };
26    candidates
27        .into_iter()
28        .filter(|m| m.is_available())
29        .collect()
30}
31
32/// Return the first available manager for the current platform.
33pub fn pick_default() -> Option<Box<dyn PackageManager>> {
34    detect_all().into_iter().next()
35}
36
37/// Return the manager with the given name regardless of availability.
38///
39/// Returns `None` when no manager with that name is registered.
40pub fn pick_by_name(name: &str) -> Option<Box<dyn PackageManager>> {
41    let all: Vec<Box<dyn PackageManager>> = vec![
42        Box::new(Pacman),
43        Box::new(Apt),
44        Box::new(Dnf),
45        Box::new(Brew),
46        Box::new(Scoop),
47        Box::new(Winget),
48    ];
49    all.into_iter().find(|m| m.name() == name)
50}