hygiea 0.1.0

Dev tool proxy for Claude skills — wraps java, mvn, find and more
use anyhow::{Context, Result, bail};
use clap::Args;
use console::style;
use std::path::PathBuf;
use which::which;

use crate::utils::jdk::{detect_java_version, find_jdk_home, find_pom};

#[derive(Args)]
pub struct MvnArgs {
    /// Arguments to forward to mvn (use -- to pass flags)
    #[arg(trailing_var_arg = true, allow_hyphen_values = true)]
    pub mvn_args: Vec<String>,

    /// Project directory (defaults to current directory)
    #[arg(short, long, default_value = ".")]
    pub dir: PathBuf,
}

pub fn run(args: MvnArgs) -> Result<()> {
    let pom = find_pom(&args.dir.canonicalize().unwrap_or_else(|_| args.dir.clone()))
        .with_context(|| format!("no pom.xml found under {}", args.dir.display()))?;

    let version = detect_java_version(&pom)
        .with_context(|| format!("while reading {}", pom.display()))?;

    let java_home = find_jdk_home(version)?;

    let mvn_bin = which("mvn").with_context(|| {
        format!(
            "{} mvn not found in PATH",
            style("").red().bold()
        )
    })?;

    if mvn_bin.as_os_str().is_empty() {
        bail!("mvn not found in PATH");
    }

    eprintln!(
        "{} Java {}{}",
        style("").blue().bold(),
        style(version).cyan(),
        style(java_home.display()).dim()
    );
    eprintln!(
        "{} mvn {}",
        style("").blue().bold(),
        style(args.mvn_args.join(" ")).dim()
    );

    let status = duct::cmd(&mvn_bin, &args.mvn_args)
        .env("JAVA_HOME", &java_home)
        .run()
        .with_context(|| "failed to execute mvn")?;

    if !status.status.success() {
        std::process::exit(status.status.code().unwrap_or(1));
    }

    Ok(())
}