use anyhow::{Context, Result};
use clap::{Parser, Subcommand};
use std::path::PathBuf;
mod analyzer;
mod dependency_graph;
mod scanner;
use analyzer::DependencyAnalyzer;
#[derive(Parser)]
#[command(name = "cargo-why")]
#[command(bin_name = "cargo")]
#[command(version, about = "Explains why dependencies are in your tree", long_about = None)]
struct Cli {
#[command(subcommand)]
command: Commands,
}
#[derive(Subcommand)]
enum Commands {
#[command(about = "Explains why dependencies are in your tree")]
Why {
#[arg(help = "The dependency name to analyze")]
dependency: String,
#[arg(
long,
help = "Show where in the codebase the dependency is used"
)]
where_used: bool,
#[arg(
long,
default_value = ".",
help = "Path to the Cargo project directory"
)]
manifest_path: PathBuf,
#[arg(
long,
help = "Show all versions of the dependency in the tree"
)]
all_versions: bool,
#[arg(long, help = "Output in JSON format")]
json: bool,
},
}
fn main() -> Result<()> {
let cli = Cli::parse();
match cli.command {
Commands::Why {
dependency,
where_used,
manifest_path,
all_versions,
json,
} => {
let analyzer = DependencyAnalyzer::new(manifest_path)
.context("Failed to initialize dependency analyzer")?;
let result = analyzer
.analyze(&dependency, where_used, all_versions)
.context("Failed to analyze dependency")?;
if json {
println!("{}", serde_json::to_string_pretty(&result)?);
} else {
result.print();
}
Ok(())
}
}
}