athena_rs 3.26.3

Hyper performant polyglot Database driver
//! Convenience binary that forces the `server` subcommand.
//!
//! Normally users should invoke the server through the `athena` CLI
//! (`athena server` or just `athena`). This binary exists for symmetry
//! with `athena-cli` and for direct `athena-server` usage in scripts.

use std::env;
use std::path::PathBuf;
use std::process::{Command, ExitCode};
/// Entrypoint for the `athena-server` convenience binary.
fn main() -> ExitCode {
    let mut forwarded: Vec<String> = env::args().skip(1).collect();
    forwarded.insert(0, "server".to_string());
    let invoked = env::args().next().unwrap_or_else(|| "athena-server".to_string());

    match resolve_and_run(&forwarded, &invoked) {
        Ok(exit_code) => exit_code,
        Err(err) => {
            eprintln!("{}: {}", invoked, err);
            eprintln!();
            eprintln!("Hints:");
            eprintln!("  • Recommended:  athena server     (or just `athena`)");
            eprintln!("  • Runtime:      athena_rs server");
            eprintln!("  • Build:        cargo build --bin athena --bin athena_rs --bin athena-server");
            ExitCode::from(1)
        }
    }
}

/// Resolve the Athena runtime and invoke it with the "server" subcommand prepended.
///
/// This is a convenience wrapper so that `athena-server` behaves like
/// `athena server` or `athena_rs server`.
fn resolve_and_run(args: &[String], invoked: &str) -> std::io::Result<ExitCode> {
    let athena = find_athena_binary()?;

    if std::env::var("ATHENA_LAUNCHER_QUIET").is_err() && !is_sibling_path(&athena) {
        let label = std::path::Path::new(invoked)
            .file_name()
            .and_then(|n| n.to_str())
            .unwrap_or("athena-server");
        eprintln!("[{}] → {}", label, athena.display());
    }

    let status = Command::new(&athena)
        .args(args)
        .status()?;

    match status.code() {
        Some(code) if code >= 0 && code <= 255 => Ok(ExitCode::from(code as u8)),
        _ => Ok(ExitCode::from(1)),
    }
}

fn is_sibling_path(p: &std::path::Path) -> bool {
    if let Ok(me) = std::env::current_exe() {
        if let (Some(my_dir), Some(target_dir)) = (me.parent(), p.parent()) {
            return my_dir == target_dir;
        }
    }
    false
}

fn find_athena_binary() -> std::io::Result<PathBuf> {
    if let Some(sib) = sibling_candidate() {
        if sib.is_file() {
            return Ok(sib);
        }
    }

    // Prefer the runtime
    if let Ok(p) = which::which("athena_rs") {
        return Ok(p);
    }
    if let Ok(p) = which::which("athena") {
        return Ok(p);
    }

    Err(std::io::Error::new(
        std::io::ErrorKind::NotFound,
        "could not find 'athena_rs' (Athena runtime) or 'athena'",
    ))
}

fn sibling_candidate() -> Option<PathBuf> {
    let current = env::current_exe().ok()?;
    let dir = current.parent()?;

    let names = if cfg!(windows) {
        ["athena.exe", "athena_rs.exe"]
    } else {
        ["athena", "athena_rs"]
    };

    for name in names {
        let p = dir.join(name);
        if p.is_file() {
            return Some(p);
        }
    }
    None
}