use crate::aur::AurClient;
use crate::cli::Options;
use crate::download::{build_path, sync_aur_base};
use crate::localdb::LocalDb;
use crate::output;
use crate::pacman::Toolchain;
use crate::resolver;
use crate::upgrade;
use anyhow::Result;
use std::collections::HashSet;
use std::io;
pub async fn sync(
options: &Options,
tools: &Toolchain,
aur: &AurClient,
targets: &[String],
refresh: bool,
sysupgrade: bool,
) -> Result<i32> {
if (refresh || sysupgrade) && options.mode.repo() {
let code = tools
.system_upgrade(refresh, sysupgrade, options.no_confirm, options.dry_run)
.await?;
if code != 0 {
return Ok(code);
}
}
if targets.is_empty() {
if sysupgrade && options.mode.aur() {
let updates = upgrade::aur_update_targets(options, tools, aur).await?;
if updates.is_empty() {
return Ok(0);
}
output::status(
"AUR packages to upgrade",
output::join_inline(&updates, " "),
);
if !options.no_confirm && !confirm("Proceed with AUR upgrade? [Y/n] ")? {
return Ok(0);
}
return install_targets(options, tools, aur, &updates).await;
}
return Ok(0);
}
install_targets(options, tools, aur, targets).await
}
async fn install_targets(
options: &Options,
tools: &Toolchain,
aur: &AurClient,
targets: &[String],
) -> Result<i32> {
let mut repo_targets = Vec::new();
let mut aur_targets = Vec::new();
for target in targets {
if options.mode.repo()
&& !matches!(options.mode, crate::cli::TargetMode::Aur)
&& tools.repo_has_package(target).await
{
repo_targets.push(target.clone());
continue;
}
if options.mode.aur() {
aur_targets.push(target.clone());
} else {
repo_targets.push(target.clone());
}
}
if !repo_targets.is_empty() {
let code = tools
.install_repo_packages(
&repo_targets,
options.needed,
options.no_confirm,
false,
options.dry_run,
)
.await?;
if code != 0 {
return Ok(code);
}
}
if aur_targets.is_empty() {
return Ok(0);
}
let local = LocalDb::load_default().unwrap_or_else(|_| LocalDb::empty());
let plan = resolver::resolve(options, tools, aur, &local, &aur_targets).await?;
if !plan.repo_deps.is_empty() {
output::status(
"Repository dependencies",
output::join_inline(&plan.repo_deps, " "),
);
}
if !plan.aur.is_empty() {
output::status(
"AUR build order",
output::join_inline(plan.aur.iter().map(|pkg| pkg.name.as_str()), " "),
);
}
for dep in &plan.unresolved {
output::warning(format!(
"dependency '{dep}' was not resolved up front; makepkg may still resolve it"
));
}
if !options.no_confirm && !confirm("Proceed with installation? [Y/n] ")? {
return Ok(0);
}
if !plan.repo_deps.is_empty() {
let code = tools
.install_repo_packages(
&plan.repo_deps,
true,
options.no_confirm,
true,
options.dry_run,
)
.await?;
if code != 0 {
return Ok(code);
}
}
let mut built_bases = HashSet::new();
for pkg in &plan.aur {
if !built_bases.insert(pkg.base().to_string()) {
continue;
}
let path = build_path(tools, pkg.base());
let code = sync_aur_base(options, tools, aur, pkg.base(), &path).await?;
if code != 0 {
return Ok(code);
}
let code = tools
.build_install_aur(
&path,
options.needed,
options.no_confirm,
options.no_check,
options.dry_run,
)
.await?;
if code != 0 {
return Ok(code);
}
}
Ok(0)
}
fn confirm(prompt: &str) -> Result<bool> {
output::prompt(prompt)?;
let mut input = String::new();
io::stdin().read_line(&mut input)?;
let input = input.trim();
Ok(input.is_empty() || input.eq_ignore_ascii_case("y") || input.eq_ignore_ascii_case("yes"))
}