use cargo_toml::Manifest;
use cargo_wsdeps::{diff::generate_diff, partition_dependencies, show::print_changes};
use clap::{Parser, Subcommand};
#[cfg(all(feature = "jemalloc", target_env = "musl"))]
use jemallocator::Jemalloc;
#[cfg(all(feature = "jemalloc", target_env = "musl"))]
#[global_allocator]
static GLOBAL: Jemalloc = Jemalloc;
#[derive(Parser)]
#[command(name = "cargo")]
#[command(bin_name = "cargo")]
#[command(styles = clap_cargo::style::CLAP_STYLING)]
enum CargoCli {
Wsdeps(WsDepsArgs),
}
#[derive(clap::Args)]
#[command(version, about, long_about = None)]
struct WsDepsArgs {
#[command(flatten)]
manifest: clap_cargo::Manifest,
#[command(flatten)]
workspace: clap_cargo::Workspace,
#[command(flatten)]
features: clap_cargo::Features,
#[command(subcommand)]
cmd: Commands,
}
#[derive(Debug, Subcommand)]
enum Commands {
Show {
#[arg(long, default_value = "false")]
aggressive: bool,
},
Diff {
#[arg(long, default_value = "false")]
dotted: bool,
#[arg(long, default_value = "false")]
aggressive: bool,
},
}
fn main() -> anyhow::Result<()> {
let CargoCli::Wsdeps(args) = CargoCli::parse();
let mut metadata = args.manifest.metadata();
args.features.forward_metadata(&mut metadata);
let metadata = metadata.exec()?;
let manifest = Manifest::from_path(metadata.workspace_root.join("Cargo.toml"))?;
let Some(ref workspace) = manifest.workspace else {
return Ok(());
};
let (selected, _) = args.workspace.partition_packages(&metadata);
let aggressive = match args.cmd {
Commands::Show { aggressive } => aggressive,
Commands::Diff { aggressive, .. } => aggressive,
};
let (add, remove, inline) = partition_dependencies(workspace, &selected, aggressive)?;
match args.cmd {
Commands::Show { .. } => {
print_changes(&add, &remove, &inline);
if !add.is_empty() || !remove.is_empty() || !inline.is_empty() {
std::process::exit(1);
}
}
Commands::Diff { dotted, .. } => {
if !add.is_empty() || !remove.is_empty() || !inline.is_empty() {
generate_diff(&add, &remove, &inline, &metadata, dotted)?;
}
}
}
Ok(())
}