use std::path::{Path, PathBuf};
use anyhow::{bail, Context, Result};
use archon_monitor::EventStore;
use archon_sandbox::SandboxRunner;
use crate::commands::install;
pub fn run(dir: &Path, report: bool) -> Result<()> {
let dir = dir
.canonicalize()
.with_context(|| format!("build directory {} does not exist", dir.display()))?;
if !dir.join("PKGBUILD").is_file() {
bail!("no PKGBUILD found in {} — is this an AUR package directory?", dir.display());
}
if !SandboxRunner::bwrap_available() {
bail!(
"bubblewrap (bwrap) is not installed — required to build packages safely.\n\
Install it with: sudo pacman -S bubblewrap"
);
}
let pkg_name = dir
.file_name()
.map(|n| n.to_string_lossy().into_owned())
.unwrap_or_else(|| "local-package".into());
if report {
run_monitored(&dir, &pkg_name)
} else {
run_plain(&dir, &pkg_name)
}
}
fn run_plain(dir: &Path, pkg_name: &str) -> Result<()> {
let runner = SandboxRunner::new(dir).capture_output(true);
install::build_in_sandbox(&runner, dir, pkg_name)?;
report_outputs(dir, pkg_name)?;
Ok(())
}
fn run_monitored(dir: &Path, pkg_name: &str) -> Result<()> {
let privileges = install::require_monitoring_privileges()?;
let mut monitor = install::load_monitor()?;
install::ensure_owned_recursive(dir, privileges.uid, privileges.gid)
.with_context(|| format!("failed to chown {} to the build user", dir.display()))?;
let user_home = install::home_dir_for_uid(privileges.uid)?;
let build_root = install::build_dir_under(&user_home);
std::fs::create_dir_all(&build_root)
.with_context(|| format!("failed to create {}", build_root.display()))?;
if let Some(cache_root) = build_root.parent() {
install::ensure_owned(cache_root, privileges.uid, privileges.gid)?;
}
install::ensure_owned(&build_root, privileges.uid, privileges.gid)?;
let store = EventStore::open(&build_root.join("monitor.db"))
.context("failed to open event store")?;
let report = install::run_monitored_build(&mut monitor, &store, dir, pkg_name, &privileges)?;
crate::ui::print_report(&report);
if report.is_clean() {
report_outputs(dir, pkg_name)?;
} else {
println!("{}", crate::color::red("not installed — this is `build`, which never installs anyway"));
}
Ok(())
}
fn report_outputs(dir: &Path, pkg_name: &str) -> Result<()> {
let files = install::find_package_files(dir, pkg_name)?;
for f in files {
println!(" {} {}", crate::color::dim("→"), f.display());
}
Ok(())
}
pub fn parse_dir(arg: &str) -> PathBuf {
PathBuf::from(arg)
}