use anyhow::{bail, Context, Result};
use stout_index::Database;
use stout_state::{InstalledPackages, Paths};
use clap::Args as ClapArgs;
use console::style;
#[derive(ClapArgs)]
pub struct Args {
pub formula: String,
#[arg(long)]
pub installed: bool,
#[arg(long)]
pub include_build: bool,
#[arg(long)]
pub include_test: bool,
#[arg(long)]
pub include_optional: bool,
#[arg(long, short = 'r')]
pub recursive: bool,
}
pub async fn run(args: Args) -> Result<()> {
let paths = Paths::default();
let db = Database::open(paths.index_db())
.context("Failed to open index. Run 'stout update' first.")?;
if !db.is_initialized()? {
bail!("Index not initialized. Run 'stout update' first.");
}
if db.get_formula(&args.formula)?.is_none() {
bail!("Formula '{}' not found", args.formula);
}
let installed = InstalledPackages::load(&paths)?;
let mut dependents: Vec<String> = Vec::new();
if args.installed {
for name in installed.names() {
let pkg = installed.get(name)
.with_context(|| format!("package '{}' is in installed list but not found", name))?;
if pkg.dependencies.contains(&args.formula) {
dependents.push(name.to_string());
}
}
} else {
for name in installed.names() {
let pkg = installed.get(name)
.with_context(|| format!("package '{}' is in installed list but not found", name))?;
if pkg.dependencies.contains(&args.formula) {
dependents.push(name.to_string());
}
}
}
dependents.sort();
if dependents.is_empty() {
println!(
"No {} packages depend on {}",
if args.installed { "installed" } else { "" },
style(&args.formula).cyan()
);
return Ok(());
}
println!(
"{} {} {} package{} that {} {}:",
style("==>").blue().bold(),
dependents.len(),
if args.installed { "installed" } else { "" },
if dependents.len() == 1 { "" } else { "s" },
if dependents.len() == 1 { "uses" } else { "use" },
style(&args.formula).cyan()
);
for dep in &dependents {
let version = installed
.get(dep)
.map(|p| p.version.as_str())
.unwrap_or_default();
println!(
" {} {} {}",
style("•").dim(),
dep,
style(version).dim()
);
}
Ok(())
}