pub(crate) fn detect_packages() -> Option<usize> {
#[cfg(target_os = "macos")]
{
let mut count = 0;
for cellar_path in &["/opt/homebrew/Cellar", "/usr/local/Cellar"] {
if let Ok(entries) = std::fs::read_dir(cellar_path) {
count += entries.filter_map(|e| e.ok()).count();
}
}
for cask_path in &["/opt/homebrew/Caskroom", "/usr/local/Caskroom"] {
if let Ok(entries) = std::fs::read_dir(cask_path) {
count += entries.filter_map(|e| e.ok()).count();
}
}
if let Ok(entries) = std::fs::read_dir("/opt/local/var/macports/software") {
count += entries.filter_map(|e| e.ok()).count();
}
if count > 0 {
Some(count)
} else {
None
}
}
#[cfg(target_os = "windows")]
{
let mut count = 0;
if let Some(home) = dirs::home_dir() {
let scoop_dir = std::env::var("SCOOP")
.map(std::path::PathBuf::from)
.unwrap_or_else(|_| home.join("scoop"));
if let Ok(entries) = std::fs::read_dir(scoop_dir.join("apps")) {
count += entries.filter_map(|e| e.ok()).count();
}
}
let choco_install = std::env::var("ChocolateyInstall")
.unwrap_or_else(|_| "C:\\ProgramData\\chocolatey".to_string());
if let Ok(entries) = std::fs::read_dir(std::path::Path::new(&choco_install).join("lib")) {
count += entries.filter_map(|e| e.ok()).count();
}
if count > 0 {
Some(count)
} else {
None
}
}
#[cfg(not(any(target_os = "macos", target_os = "windows")))]
{
if let Ok(entries) = std::fs::read_dir("/var/lib/pacman/local") {
let count = entries.filter_map(|e| e.ok()).count();
if count > 0 {
return Some(count);
}
}
if let Ok(entries) = std::fs::read_dir("/var/lib/dpkg/info") {
let count = entries
.filter_map(|e| e.ok())
.filter(|e| e.path().extension().is_some_and(|ext| ext == "list"))
.count();
if count > 0 {
return Some(count);
}
}
if let Ok(entries) = std::fs::read_dir("/var/db/pkg") {
let count: usize = entries
.filter_map(|e| e.ok())
.map(|e| {
std::fs::read_dir(e.path())
.map(|d| d.filter(|_| true).count())
.unwrap_or(0)
})
.sum();
if count > 0 {
return Some(count);
}
}
if let Ok(entries) = std::fs::read_dir("/var/db/xbps") {
let count = entries
.filter_map(|e| e.ok())
.filter(|e| e.path().extension().is_some_and(|ext| ext == "plist"))
.count();
if count > 0 {
return Some(count);
}
}
let rpm_db = "/var/lib/rpm/rpmdb.sqlite";
if std::path::Path::new(rpm_db).exists() {
match rusqlite::Connection::open(rpm_db) {
Ok(conn) => {
if let Ok(count) = conn.query_row("SELECT COUNT(*) FROM Packages", [], |row| {
row.get::<_, i64>(0)
}) {
if count > 0 {
return Some(count as usize);
}
}
}
Err(e) => {
eprintln!("warning: failed to open RPM database at {}: {}", rpm_db, e);
}
}
}
None
}
}