use crate::apt::Apt;
use crate::brew::Brew;
use crate::dnf::Dnf;
use crate::manager::PackageManager;
use crate::pacman::Pacman;
use crate::scoop::Scoop;
use crate::winget::Winget;
pub fn detect_all() -> Vec<Box<dyn PackageManager>> {
candidates_for_os(std::env::consts::OS)
.into_iter()
.filter(|m| m.is_available())
.collect()
}
fn candidates_for_os(os: &str) -> Vec<Box<dyn PackageManager>> {
match os {
"macos" => vec![Box::new(Brew)],
"windows" => vec![Box::new(Scoop), Box::new(Winget)],
_ => vec![Box::new(Pacman), Box::new(Dnf), Box::new(Apt)],
}
}
pub fn pick_default() -> Option<Box<dyn PackageManager>> {
detect_all().into_iter().next()
}
pub fn pick_by_name(name: &str) -> Option<Box<dyn PackageManager>> {
let all: Vec<Box<dyn PackageManager>> = vec![
Box::new(Pacman),
Box::new(Apt),
Box::new(Dnf),
Box::new(Brew),
Box::new(Scoop),
Box::new(Winget),
];
all.into_iter().find(|m| m.name() == name)
}
#[cfg(test)]
mod tests {
use super::*;
fn names(os: &str) -> Vec<&'static str> {
candidates_for_os(os).iter().map(|m| m.name()).collect()
}
#[test]
fn candidates_follow_each_platforms_preference_order() {
assert_eq!(names("macos"), ["brew"]);
assert_eq!(names("windows"), ["scoop", "winget"]);
assert_eq!(names("linux"), ["pacman", "dnf", "apt"]);
}
#[test]
fn unlisted_unix_likes_get_the_linux_order() {
assert_eq!(names("freebsd"), names("linux"));
}
}