use crate::{
cli::*, collection::*, color::Color, constant::*, error::*, file::*, io::*, location::*,
reconcile::*,
};
use camino::Utf8PathBuf;
use std::{cell::RefCell, fs::create_dir_all};
pub fn install(
flags: CommonFlags,
pkgs: Vec<PkgPathUrlRepo>,
reinstall: bool,
) -> Result<String, Err> {
let bpt_conf = &BptConf::from_root_path(&flags.root_dir)?;
let plan = {
let pubkeys = &PublicKeys::from_common_flags(&flags)?;
let repository = &RepositoryPkgs::from_root_path(&flags.root_dir, pubkeys)?;
let installed = &InstalledPkgs::from_root_path_ro(&flags.root_dir)?;
let world = &World::from_root_path_ro(&flags.root_dir)?;
let netutil = &RefCell::new(NetUtil::new(bpt_conf, flags.netutil_stderr));
let query_credentials = &QueryCredentials::new(bpt_conf);
let pkgcache = &RefCell::new(Cache::from_root_path(
&flags.root_dir,
PKG_CACHE,
"package cache",
)?);
InstPkgReconciler {
world,
installed,
repository,
pubkeys,
netutil,
pkgcache,
general: &bpt_conf.general,
query_credentials,
command: CommandRequest::Install {
pkgs: &pkgs,
reinstall,
},
}
.plan()?
};
if plan.is_empty() {
return Ok("No changes needed".to_string());
}
if flags.dry_run {
println!("{}Would have:{}\n{plan}", Color::Warn, Color::Default);
return Ok(format!("Dry ran {}", plan.summary().to_lowercase()));
}
print!("Continuing will:\n{plan}");
if !flags.yes && !confirm()? {
return Err(Err::ConfirmDenied);
}
let pubkeys = &PublicKeys::from_common_flags(&flags)?;
let repository = &RepositoryPkgs::from_root_path(&flags.root_dir, pubkeys)?;
let installed = &InstalledPkgs::from_root_path_rw(&flags.root_dir)?;
let mut world = World::from_root_path_rw(&flags.root_dir)?;
let netutil = &RefCell::new(NetUtil::new(bpt_conf, flags.netutil_stderr));
let pkgcache = &RefCell::new(Cache::from_root_path(
&flags.root_dir,
PKG_CACHE,
"package cache",
)?);
let instpkg_dir = flags.root_dir.as_path().join(INSTPKG_DIR_PATH);
create_dir_all(&instpkg_dir).map_err(|e| Err::CreateDir(instpkg_dir.to_string(), e))?;
let available_bpts = &RefCell::new(AvailableBpts::new());
let build_support = if plan.needs_builds() {
let build_credentials = bpt_conf.build_credentials()?;
Some(InstallBuildSupport {
adjusted_root_dir: flags.root_dir.adjust_bedrock_prefix()?,
privkey: PrivKey::SkipSign,
build_credentials,
make_conf: MakeConf::from_root_path(&flags.root_dir)?,
make_common: MakeCommon::from_root_path(&flags.root_dir)?,
tmpdir: RefCell::new(TmpDir::new(bpt_conf)?),
src_cache: RefCell::new(Cache::from_root_path(
&flags.root_dir,
SRC_CACHE,
"source cache",
)?),
})
} else {
None
};
let buildargs = build_support
.as_ref()
.map(|support| support.as_build_args(&flags, netutil, installed, available_bpts));
let bptnew = plan.apply(InstPkgApplyArgs {
root: &flags.root_dir,
installed,
world: &mut world,
instpkg_dir: &instpkg_dir,
purge: false,
forget: false,
repository,
pubkeys,
netutil,
pkgcache,
available_bpts,
buildargs: buildargs.as_ref(),
})?;
if !bptnew.is_empty() {
for path in bptnew {
println!("{}Created{} {}.bptnew", Color::Warn, Color::Default, path);
}
}
Ok("Updated installed package set".to_string())
}
struct InstallBuildSupport {
adjusted_root_dir: Utf8PathBuf,
privkey: PrivKey,
build_credentials: Option<ProcessCredentials>,
make_conf: MakeConf,
make_common: MakeCommon,
tmpdir: RefCell<TmpDir>,
src_cache: RefCell<Cache>,
}
impl InstallBuildSupport {
fn as_build_args<'a>(
&'a self,
flags: &'a CommonFlags,
netutil: &'a RefCell<NetUtil<'a>>,
installed_pkgs: &'a InstalledPkgs,
available_bpts: &'a RefCell<AvailableBpts>,
) -> BuildArgs<'a> {
BuildArgs {
privkey: &self.privkey,
build_credentials: self.build_credentials.as_ref(),
make_conf: &self.make_conf,
make_common: &self.make_common,
root_dir: &self.adjusted_root_dir,
out_dir: &flags.out_dir,
tmpdir: &self.tmpdir,
netutil,
src_cache: &self.src_cache,
installed_pkgs,
available_bpts,
}
}
}