Files
packie/cli/src/install.rs
T
2026-06-25 05:41:09 +08:00

90 lines
2.8 KiB
Rust

use crate::common::{format_size, print_list, yesno};
use clap::Parser;
use indicatif::ProgressBar;
use packie::{
PackieBuilder, install::InstallOptions, package::PkgSpec, repo::DownloadPackageEvent,
};
use rust_i18n::t;
#[derive(Debug, Parser)]
pub struct Cli {
#[arg(short, long)]
file: bool,
#[arg(short, long)]
yes: bool,
items: Vec<String>,
}
pub fn main(cli: Cli) -> anyhow::Result<()> {
let mut packie = PackieBuilder::new().build()?;
if cli.file {
for item in cli.items {
packie.install_package_file(item, &InstallOptions::default())?;
}
return Ok(());
}
let mut packages = Vec::with_capacity(cli.items.len() * 4);
for i in cli.items {
packages.append(&mut packie.calculate_depgraph(i.parse::<PkgSpec>()?)?);
}
packages.dedup_by_key(|x| x.repo_pkg.pkg_manifest.pkg_ident());
if packages.is_empty() {
eprintln!("No packages to install.");
return Ok(());
}
let download_size: u64 = packages.iter().map(|x| x.repo_pkg.download_size).sum();
let installed_size: u64 = packages.iter().map(|x| x.repo_pkg.installed_size).sum();
println!("{}", t!("install.prompt_to_install"));
print_list(4, packages.iter().map(|x| x.pkgspec.to_string()));
println!(
"{}",
t!("install.download_size", size = format_size(download_size))
);
println!(
"{}",
t!("install.installed_size", size = format_size(installed_size))
);
if cli.yes {
eprintln!("y");
} else if !yesno(&t!("install.confirm_installation")) {
eprintln!("{}", t!("install.aborting"));
return Ok(());
}
let progress_bar = ProgressBar::new(download_size);
let mut package_files = Vec::with_capacity(packages.len());
for package in packages.iter() {
let init_pos = progress_bar.position();
progress_bar.println(format!("Downloading \"{}\"...", package.pkgspec));
let path = packie.download_package(
&package.repo_name,
&package.repo_pkg.pkg_manifest.pkg_ident(),
|ev| match ev {
DownloadPackageEvent::Progress(_, sum, _) => {
progress_bar.set_position(init_pos + sum);
}
DownloadPackageEvent::Error(url, err) => {
progress_bar
.println(format!("error: failed to download from \"{url}\": {err}"));
}
},
)?;
package_files.push(path);
}
let progress_bar = ProgressBar::new(package_files.len() as _);
for package in package_files.iter() {
progress_bar.println(format!("Installing \"{}\"...", package.display()));
packie.install_package_file(package, &InstallOptions::default())?;
progress_bar.inc(1);
}
Ok(())
}