use std::process::Command;
use std::path::Path;
use std::collections::HashSet;
use error::*;
use listener::Listener;
pub fn resolve(path: &Path, architecture: &str, listener: &mut Listener) -> CDResult<Vec<String>> {
let dependencies = {
let output = Command::new("ldd").arg(path)
.output().map_err(|e| CargoDebError::CommandFailed(e, "ldd"))?;
if !output.status.success() {
return Err(CargoDebError::CommandError("ldd", path.display().to_string(), output.stderr));
}
String::from_utf8(output.stdout).unwrap()
};
let dependencies: HashSet<_> = dependencies.lines()
.map(|line| line.split_whitespace().nth(2))
.filter(|x| x.is_some() && x.unwrap().starts_with('/'))
.filter_map(|path_str_opt|
get_package_name_with_fallback(path_str_opt.unwrap())
.map_err(|err|{
listener.warning(format!("{} (skip this auto dep for {})", err, path.display()));
err
}).ok()
)
.collect();
Ok(dependencies.iter().map(|package| {
let version = get_version(&format!("{}:{}", package, architecture)).unwrap();
format!("{} (>= {})", package, version)
}).collect())
}
fn get_package_name_with_fallback(path: &str) -> CDResult<String> {
match get_package_name(path) {
Ok(res) => Ok(res),
Err(e @ CargoDebError::PackageNotFound(..)) => {
let usr_path = format!("/usr{}", path);
match get_package_name(&usr_path) {
Ok(res) => Ok(res),
_ => Err(e),
}
},
Err(e) => Err(e),
}
}
fn get_package_name(path: &str) -> CDResult<String> {
let output = Command::new("dpkg").arg("-S").arg(path)
.output().map_err(|e| CargoDebError::CommandFailed(e, "dpkg -S"))?;
if !output.status.success() {
return Err(CargoDebError::PackageNotFound(path.to_owned(), output.stderr));
}
let package = output.stdout.iter().take_while(|&&x| x != b':').cloned().collect::<Vec<u8>>();
Ok(String::from_utf8(package).unwrap())
}
fn get_version(package: &str) -> CDResult<String> {
let output = Command::new("dpkg-query")
.arg("--showformat=${Version}")
.arg("--show")
.arg(package)
.output()
.map_err(|e| CargoDebError::CommandFailed(e, "dpkg-query (get package version)"))?;
if !output.status.success() {
return Err(CargoDebError::CommandError("dpkg-query (get package version)", package.to_owned(), output.stderr));
}
let version = ::std::str::from_utf8(&output.stdout).unwrap();
Ok(version.splitn(2, '-').next().unwrap().to_owned())
}