hygiea 0.1.0

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

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

#[derive(Args)]
pub struct JavaArgs {
    /// Arguments to forward to java
    #[arg(trailing_var_arg = true, allow_hyphen_values = true)]
    pub java_args: Vec<String>,

    /// Project directory used to auto-detect Java version via pom.xml
    #[arg(short, long, default_value = ".")]
    pub dir: PathBuf,
}

pub fn run(args: JavaArgs) -> Result<()> {
    let dir = args.dir.canonicalize().unwrap_or_else(|_| args.dir.clone());

    let java_home = if let Some(pom) = find_pom(&dir) {
        let version = detect_java_version(&pom)?;
        eprintln!(
            "{} Java {} (from pom.xml)",
            style("").blue().bold(),
            style(version).cyan()
        );
        find_jdk_home(version)?
    } else if let Ok(home) = std::env::var("JAVA_HOME") {
        eprintln!(
            "{} Java from $JAVA_HOME",
            style("").blue().bold()
        );
        PathBuf::from(home)
    } else {
        // Fall back to whatever java is on PATH
        eprintln!(
            "{} no pom.xml or $JAVA_HOME found, using system java",
            style("!").yellow().bold()
        );
        let java_bin = which::which("java")
            .with_context(|| "java not found in PATH")?;
        let status = duct::cmd(&java_bin, &args.java_args)
            .run()
            .with_context(|| "failed to execute java")?;
        if !status.status.success() {
            std::process::exit(status.status.code().unwrap_or(1));
        }
        return Ok(());
    };

    let java_bin = java_home.join("bin/java");

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

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

    Ok(())
}