athena_rs 3.26.3

Hyper performant polyglot Database driver
//! Dedicated entrypoint binary for the `athena` CLI / toolchain.
//!
//! When built as `athena` (see `[[bin]]` in `Cargo.toml`), this becomes the
//! recommended user-facing command for operating Athena.
//!
//! Currently this binary acts mostly as a smart launcher that finds and
//! invokes the `athena_rs` runtime. The long term direction is to implement
//! more of the commands here as direct clients of the Athena HTTP surfaces.

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

    match resolve_and_run(&forwarded, &invoked) {
        Ok(exit_code) => exit_code,
        Err(err) => {
            eprintln!("{}: {}", invoked, err);
            eprintln!();
            eprintln!("Hints:");
            eprintln!("  • Build the runtime + CLI together:");
            eprintln!("      cargo build --bin athena --bin athena_rs --bin athena-cli --bin athena-server");
            eprintln!("  • Dev:");
            eprintln!("      cargo run --bin athena -- --help");
            eprintln!("      cargo run --bin athena_rs -- server");
            eprintln!("  • The `athena` CLI is the recommended interface to Athena surfaces.");
            ExitCode::from(1)
        }
    }
}

/// Resolve the target Athena runtime binary and execute the forwarded command.
///
/// Returns the exit code of the child process so that the CLI surface
/// preserves the semantics of the underlying `athena_rs` runtime.
fn resolve_and_run(args: &[String], invoked: &str) -> std::io::Result<ExitCode> {
    let athena = find_athena_binary()?;

    // Helpful for people who were confused which binary was actually running.
    // Only show when we fell back to PATH (sibling is the normal dev case and is silent).
    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-cli");
        eprintln!("[{}] → {}", label, athena.display());
    }

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

    // Preserve the real exit code from the child process.
    match status.code() {
        Some(code) if code >= 0 && code <= 255 => Ok(ExitCode::from(code as u8)),
        Some(_) => Ok(ExitCode::from(1)),
        None => Ok(ExitCode::from(1)), // terminated by signal
    }
}

/// Heuristic that checks whether `p` lives in the same directory as the
/// currently executing binary (used to decide whether to print delegation info).
fn is_sibling_path(p: &std::path::Path) -> bool {
    // Heuristic: if the parent dir of the target contains a file that looks like our own exe name
    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
}

/// Locate the `athena_rs` runtime binary that this CLI will interface with.
///
/// Search order:
/// 1. A sibling binary next to the current executable (ideal for `target/...` builds).
/// 2. `athena_rs` on `PATH`.
/// 3. `athena` on `PATH` (fallback).
fn find_athena_binary() -> std::io::Result<PathBuf> {
    // 1. Sibling (best when you built `athena` + `athena_rs` together)
    if let Some(sib) = sibling_candidate() {
        if sib.is_file() {
            return Ok(sib);
        }
    }

    // 2. The core runtime first (this is what the CLI interfaces with)
    if let Ok(p) = which::which("athena_rs") {
        return Ok(p);
    }

    // 3. Friendly name fallback
    if let Ok(p) = which::which("athena") {
        return Ok(p);
    }

    Err(std::io::Error::new(
        std::io::ErrorKind::NotFound,
        "could not find 'athena_rs' (the Athena runtime) or 'athena'. \
         Build both with: cargo build --bin athena --bin athena_rs",
    ))
}

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

    // Prefer the runtime when next to the CLI, then the friendly name.
    let names = if cfg!(windows) {
        ["athena_rs.exe", "athena.exe"]
    } else {
        ["athena_rs", "athena"]
    };

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