use std::io::Write;
use std::error::Error as _;
use std::process::ExitCode;
use cargo_upgrades::*;
use yansi::{Paint, Style, Condition, Color::Red};
pub const COLOR: Condition = Condition::from(|| {
(Condition::stdouterr_are_tty() || Condition::clicolor()) && Condition::no_color()
});
pub const ERROR: Style = Red.bold();
mod flags {
pub const HELP: &str = CargoUpgrades::HELP_;
xflags::xflags! {
cmd cargo-upgrades {
optional --pre
optional --manifest-path path: String
}
}
}
fn run() -> Result<ExitCode, ExitCode> {
if !COLOR() {
yansi::disable();
}
let args = std::env::args_os().skip(1).filter(|arg| arg != "upgrades").collect();
let flags = flags::CargoUpgrades::from_vec(args).map_err(|e| {
if e.is_help() {
println!("{e}");
ExitCode::SUCCESS
} else {
eprint!("{}: {e}\n\n{}", "error".paint(ERROR), flags::HELP);
ExitCode::FAILURE
}
})?;
let u = UpgradesChecker::new(flags.manifest_path.as_deref()).map_err(|e| {
print_error(e);
ExitCode::FAILURE
})?;
let mut printed_anything = false;
for (package, deps) in u.outdated_dependencies(flags.pre) {
if printed_anything {
println!("");
}
println!("{}\n{}", package.name.bold(), package.manifest_path.dim());
let mut stdout = std::io::stdout().lock();
let mut tw = tabwriter::TabWriter::new(&mut stdout).ansi(yansi::is_enabled());
let mut header_printed = false;
for dep in deps {
match dep {
Ok(dep) => {
if !header_printed {
let _ = writeln!(&mut tw, "{}\t{}\t{}", "dependency".underline(), "current".underline(), "upgrade".underline());
header_printed = true;
}
let _ = writeln!(&mut tw, "{}\t{}\t{}",
dep.dependency.rename.as_deref().unwrap_or(&dep.dependency.name),
dep.matches.map(|s| s.to_string()).as_deref().unwrap_or("nothing").yellow(),
dep.latest.green()
);
},
Err(e) => {
print_error(e);
},
}
}
let _ = tw.flush();
printed_anything = true;
}
if printed_anything {
return Ok(ExitCode::from(7));
}
println!("{}", "All dependencies match up-to-date releases.".green());
println!("Run `cargo update` to update to latest release.");
Ok(ExitCode::SUCCESS)
}
fn main() -> ExitCode {
run().unwrap_or_else(|e| e)
}
fn print_error(error: Error) {
eprintln!("{}: {error}", "error".paint(ERROR));
let mut source = error.source();
while let Some(error) = source {
eprintln!(" {error}");
source = error.source();
}
}