use clap::Parser;
use ognibuild::buildsystem::{detect_buildsystems, DependencyCategory};
use ognibuild::debian::apt::{dependency_to_deb_dependency, AptManager};
use ognibuild::dependencies::debian::{
default_tie_breakers, DebianDependency, DebianDependencyCategory,
};
use ognibuild::dependency::Dependency;
use ognibuild::session::plain::PlainSession;
use ognibuild::session::Session;
use std::collections::HashMap;
use std::io::Write;
use std::path::PathBuf;
#[derive(Parser)]
struct Args {
#[clap(long)]
detailed: bool,
directory: PathBuf,
#[clap(long)]
debug: bool,
}
fn main() -> Result<(), i32> {
let args = Args::parse();
let mut session = PlainSession::new();
env_logger::builder()
.format(|buf, record| writeln!(buf, "{}", record.args()))
.filter(
None,
if args.debug {
log::LevelFilter::Debug
} else {
log::LevelFilter::Info
},
)
.init();
let directory = args.directory.canonicalize().unwrap();
session.chdir(&directory).unwrap();
let bss = detect_buildsystems(&directory);
if bss.is_empty() {
eprintln!("No build tools found");
std::process::exit(1);
}
log::debug!("Detected buildsystems: {:?}", bss);
let mut deps: HashMap<DependencyCategory, Vec<Box<dyn Dependency>>> = HashMap::new();
for buildsystem in bss {
match buildsystem.get_declared_dependencies(&session, Some(&[])) {
Ok(declared_reqs) => {
for (stage, req) in declared_reqs {
deps.entry(stage).or_default().push(req);
}
}
Err(_e) => {
log::warn!(
"Unable to get dependencies from buildsystem {:?}, skipping",
buildsystem
);
continue;
}
}
}
let tie_breakers = default_tie_breakers(&session);
let apt = AptManager::new(&mut session, None);
if args.detailed {
let mut unresolved = false;
for (stage, deps) in deps.iter() {
log::info!("Stage: {}", stage);
for dep in deps {
if let Some(deb_dep) =
dependency_to_deb_dependency(&apt, dep.as_ref(), &tie_breakers).unwrap()
{
log::info!("Dependency: {:?} → {}", dep, deb_dep.relation_string());
} else {
log::warn!("Dependency: {:?} → ??", dep);
unresolved = true;
}
}
log::info!("");
}
if unresolved {
Err(1)
} else {
Ok(())
}
} else {
let mut dep_depends: HashMap<DebianDependencyCategory, Vec<DebianDependency>> =
HashMap::new();
let mut unresolved = vec![];
for (stage, reqs) in deps.iter() {
for dep in reqs {
if let Some(deb_dep) =
dependency_to_deb_dependency(&apt, dep.as_ref(), &tie_breakers).unwrap()
{
match stage {
DependencyCategory::Universal => {
dep_depends
.entry(DebianDependencyCategory::Build)
.or_default()
.push(deb_dep.clone());
dep_depends
.entry(DebianDependencyCategory::Runtime)
.or_default()
.push(deb_dep);
}
DependencyCategory::Build => {
dep_depends
.entry(DebianDependencyCategory::Build)
.or_default()
.push(deb_dep);
}
DependencyCategory::Runtime => {
dep_depends
.entry(DebianDependencyCategory::Runtime)
.or_default()
.push(deb_dep);
}
DependencyCategory::BuildExtra(_name) => {
}
DependencyCategory::Test => {
dep_depends
.entry(DebianDependencyCategory::Test("test".to_string()))
.or_default()
.push(deb_dep);
}
DependencyCategory::Dev => {}
DependencyCategory::RuntimeExtra(_name) => {
}
}
} else {
unresolved.push(dep);
}
}
}
for (category, deps) in dep_depends.iter() {
match category {
DebianDependencyCategory::Build => {
log::info!(
"Build-Depends: {}",
deps.iter()
.map(|d| d.relation_string())
.collect::<Vec<_>>()
.join(", ")
);
}
DebianDependencyCategory::Runtime => {
log::info!(
"Depends: {}",
deps.iter()
.map(|d| d.relation_string())
.collect::<Vec<_>>()
.join(", ")
);
}
DebianDependencyCategory::Test(test) => {
log::info!(
"Test-Depends ({}): {}",
test,
deps.iter()
.map(|d| d.relation_string())
.collect::<Vec<_>>()
.join(", ")
);
}
DebianDependencyCategory::Install => {
log::info!(
"Pre-Depends: {}",
deps.iter()
.map(|d| d.relation_string())
.collect::<Vec<_>>()
.join(", ")
);
}
}
}
if !unresolved.is_empty() {
log::warn!("Unable to find apt packages for the following dependencies:");
for req in unresolved {
log::warn!("* {:?}", req);
}
Err(1)
} else {
Ok(())
}
}
}