use std::collections::HashSet;
use anyhow::Result;
use clap::Parser;
use walkdir::WalkDir;
use crate::{
dpkg::{find_packages_for_paths, get_package_versions},
elf::get_file_dependencies,
search::get_ld_cache,
};
mod dpkg;
mod elf;
mod search;
#[derive(Parser, Debug)]
#[command(version, about)]
struct Args {
paths: Vec<String>,
}
fn main() -> Result<()> {
let args = Args::parse();
let files = args
.paths
.iter()
.flat_map(|p| WalkDir::new(p))
.filter_map(|e| e.ok())
.filter(|e| e.file_type().is_file());
let mut libraries = HashSet::new();
for file in files {
let deps = get_file_dependencies(file.path())?;
libraries.extend(deps);
}
let ld_cache = get_ld_cache()?;
let library_paths = libraries
.iter()
.flat_map(|l| ld_cache.get(l))
.map(|s| s.as_str())
.collect::<HashSet<&str>>();
let path_to_package = find_packages_for_paths(library_paths.iter())?;
let packages: HashSet<&str> = library_paths
.iter()
.filter_map(|path| path_to_package.get(*path))
.map(|s| s.as_str())
.collect();
let package_versions = get_package_versions(packages.iter())?;
let deps = packages
.iter()
.map(|p| {
if let Some(version) = package_versions.get(*p) {
format!("{p} (>={version})")
} else {
p.to_string()
}
})
.collect::<Vec<String>>();
let deps = deps.join(", ");
println!("{deps}");
Ok(())
}