cargo-upgrades 2.0.1

Checks if dependencies in Cargo.toml are up to date. Compatible with workspaces and path dependencies.
Documentation
use std::process::ExitCode;
use std::error::Error as _;
use cargo_upgrades::*;

fn main() -> ExitCode {
    // When run via Cargo, the command name is present
    let args: Vec<_> = std::env::args().collect();

    let mut opts = getopts::Options::new();
    opts.optflag("", "pre", "Suggest upgrades from stable to pre-release (alpha, beta) versions");
    opts.optopt("", "manifest-path", "Check this Cargo project instead of the current dir", "Cargo.toml");
    opts.optflag("h", "help", "This help");
    let matches = match opts.parse(&args[1..]) {
        Ok(m) => m,
        Err(e) => {
            eprintln!("error: {}\n{}", e, opts.usage("https://gitlab.com/kornelski/cargo-upgrades"));
            return ExitCode::FAILURE;
        },
    };

    if matches.opt_present("h") {
        println!("cargo-upgrades v{}\n{}", env!("CARGO_PKG_VERSION"), opts.usage("https://gitlab.com/kornelski/cargo-upgrades"));
        return ExitCode::SUCCESS;
    }

    let pre = matches.opt_present("pre");
    let manifest_path = matches.opt_str("manifest-path");
    let u = match UpgradesChecker::new(manifest_path.as_deref()) {
        Ok(u) => u,
        Err(e) => {
            print_error(e);
            return ExitCode::FAILURE;
        },
    };

    let mut printed_anything = false;
    for (package, deps) in u.outdated_dependencies(pre) {
        if printed_anything {
            println!();
        }
        println!("{}: {}", package.name, package.manifest_path);
        for d in deps {
            let d = match d {
                Ok(d) => d,
                Err(e) => {
                    print_error(e);
                    continue;
                },
            };
            let matches = d.matches.map(|s| s.to_string());
            let dep = d.dependency;
            println!(
                "\t{} matches {};\tlatest is {}",
                dep.name,
                matches.as_deref().unwrap_or("nothing"),
                d.latest
            );
        }
        printed_anything = true;
    }

    if printed_anything {
        ExitCode::from(7)
    } else {
        println!("OK! Cargo.toml allows `cargo update` to use latest dependencies.");
        ExitCode::SUCCESS
    }
}

fn print_error(error: Error) {
    eprintln!("Error: {error}");
    let mut source = error.source();
    while let Some(error) = source {
        eprintln!("  because: {error}");
        source = error.source();
    }
}