use eyre::Result;
use inquire::Confirm;
use itertools::Itertools;
use lux_lib::{
build::BuildBehaviour,
config::Config,
lockfile::{LocalPackageId, OptState, PinnedState},
operations::install::PackageInstallSpec,
package::PackageReq,
tree::{self, RockMatches, Tree},
};
pub fn apply_build_behaviour(
package_reqs: Vec<PackageReq>,
pin: PinnedState,
force: bool,
tree: &Tree,
config: &Config,
) -> Result<Vec<PackageInstallSpec>> {
let lockfile = tree.lockfile()?;
Ok(package_reqs
.into_iter()
.filter_map(|req| {
let existing_packages: Vec<LocalPackageId> =
match tree.match_rocks_and(&req, |rock| pin == rock.pinned()) {
Ok(RockMatches::Single(id)) => vec![id],
Ok(RockMatches::Many(ids)) => ids.into_iter().collect_vec(),
_ => Vec::new(),
};
let force = force
|| existing_packages
.iter()
.all(|pkg_id| !lockfile.is_entrypoint(pkg_id));
let build_behaviour: Option<BuildBehaviour> = if force || existing_packages.is_empty() {
Some(if force {
BuildBehaviour::Force
} else {
BuildBehaviour::NoForce
})
} else if !config.no_prompt()
&& Confirm::new(&format!("Package {req} already exists. Overwrite?"))
.with_default(false)
.prompt()
.is_ok_and(|is_overwrite_confirmed| is_overwrite_confirmed)
{
Some(BuildBehaviour::Force)
} else {
None
};
build_behaviour.map(|build_behaviour| {
PackageInstallSpec::new(req, tree::EntryType::Entrypoint)
.build_behaviour(build_behaviour)
.pin(pin)
.opt(OptState::Required)
.build()
})
})
.collect())
}