pub mod build;
pub mod hash;
pub mod info;
pub mod query;
pub mod source;
use clap::{Args, Parser, Subcommand};
#[derive(Parser)]
#[command(name = "shaha")]
#[command(about = "Hash database builder and reverse lookup tool (SHA + aha!)")]
#[command(version)]
pub struct Cli {
#[arg(short, long, global = true)]
pub quiet: bool,
#[command(subcommand)]
pub command: Commands,
}
#[derive(Subcommand)]
pub enum Commands {
Build(build::BuildArgs),
Hash(hash::HashArgs),
Query(query::QueryArgs),
Info(info::InfoArgs),
Source(source::SourceArgs),
}
use std::path::Path;
use anyhow::Result;
use crate::config::{Config, R2Overrides};
use crate::storage::R2Config;
#[derive(Args)]
pub struct R2Args {
#[arg(long = "r2")]
pub enabled: bool,
#[arg(long, env = "SHAHA_R2_ENDPOINT")]
pub endpoint: Option<String>,
#[arg(long, env = "SHAHA_R2_BUCKET")]
pub bucket: Option<String>,
#[arg(long, env = "SHAHA_R2_ACCESS_KEY_ID")]
pub access_key_id: Option<String>,
#[arg(long, env = "SHAHA_R2_SECRET_ACCESS_KEY")]
pub secret_access_key: Option<String>,
#[arg(long, env = "SHAHA_R2_PATH")]
pub r2_path: Option<String>,
#[arg(long, env = "SHAHA_R2_REGION", default_value = "auto")]
pub region: String,
}
impl R2Args {
pub fn build_config(&self, fallback_path: &Path) -> Result<R2Config> {
let default_path = fallback_path
.file_name()
.map(|n| n.to_string_lossy().to_string())
.unwrap_or_else(|| "hashes.parquet".to_string());
let overrides = R2Overrides {
endpoint: self.endpoint.as_deref(),
bucket: self.bucket.as_deref(),
access_key_id: self.access_key_id.as_deref(),
secret_access_key: self.secret_access_key.as_deref(),
path: self.r2_path.as_deref(),
region: &self.region,
default_path: &default_path,
};
Config::load()?.build_r2_config(overrides)
}
}