use crate::config::Config;
use crate::util::fs::execute;
use clap::Parser;
use std::path::Path;
use std::process::ExitCode;
#[derive(Parser, Debug)]
#[command(version, about, override_usage = "upsft [OPTIONS]")]
pub struct Cli {
#[arg(short, long = "config")]
pub config_path: Option<String>,
#[arg(long, conflicts_with = "init")]
pub list: bool,
#[arg(long, conflicts_with = "list")]
pub init: bool,
}
impl Cli {
pub fn run() -> ExitCode {
let args = Cli::parse();
let config_path = args.config_path.as_deref().map(Path::new);
if args.init {
return match Config::init_config(config_path) {
Ok(path) => {
println!("Created config at: {}", path.display());
ExitCode::SUCCESS
}
Err(e) => {
eprintln!("Error: {e}");
ExitCode::FAILURE
}
};
}
if args.list {
return match Config::load(config_path) {
Ok(config) => {
Self::list_deps(config);
ExitCode::SUCCESS
}
Err(e) => {
eprintln!("Error: {e}");
ExitCode::FAILURE
}
};
}
match Config::load(config_path) {
Ok(config) => Self::execute_update_commands(config),
Err(e) => {
eprintln!("Error: {e}");
ExitCode::FAILURE
}
}
}
fn list_deps(config: Config) {
if config.deps.is_empty() {
println!("No dependencies added yet");
return;
}
let mut names: Vec<&String> = config.deps.keys().collect();
names.sort();
println!("Managed dependencies ({}):", names.len());
for name in names {
println!("- {name}");
}
}
fn execute_update_commands(config: Config) -> ExitCode {
if config.deps.is_empty() {
println!("No dependencies added yet");
return ExitCode::SUCCESS;
}
let mut deps: Vec<_> = config.deps.into_iter().collect();
deps.sort_unstable_by(|a, b| a.0.cmp(&b.0));
let mut failed = false;
for (name, update_command) in deps {
println!("Updating {name}...");
match execute(&update_command) {
Ok(status) if status.success() => {}
Ok(status) => {
failed = true;
match status.code() {
Some(code) => {
eprintln!("Error: update failed for {name} with exit code {code}")
}
None => eprintln!(
"Error: update failed for {name} because the process was terminated"
),
}
}
Err(error) => {
failed = true;
eprintln!("Error: failed to run update for {name}: {error}");
}
}
}
if failed {
ExitCode::FAILURE
} else {
ExitCode::SUCCESS
}
}
}