use std::ffi::OsString;
use std::path::PathBuf;
use clap::{Args, Parser, Subcommand};
#[derive(Debug, Parser)]
#[command(
name = "repobin",
about = "Install and dispatch repo-local Bazel tools"
)]
pub struct Cli {
#[command(subcommand)]
pub command: Command,
}
#[derive(Debug, Subcommand)]
pub enum Command {
Install(InstallArgs),
Doctor(DoctorArgs),
List,
Exec(ExecArgs),
}
#[derive(Debug, Clone, Args)]
pub struct BinDirArgs {
#[arg(long, value_name = "DIR")]
pub bin_dir: Option<PathBuf>,
}
#[derive(Debug, Clone, Args)]
pub struct InstallArgs {
#[command(flatten)]
pub bin_dir: BinDirArgs,
}
#[derive(Debug, Clone, Args)]
pub struct DoctorArgs {
#[command(flatten)]
pub bin_dir: BinDirArgs,
}
#[derive(Debug, Clone, Args)]
pub struct ExecArgs {
pub tool: String,
#[arg(trailing_var_arg = true, allow_hyphen_values = true)]
pub args: Vec<OsString>,
}
#[cfg(test)]
mod tests {
use std::ffi::OsString;
use clap::Parser;
use super::{Cli, Command};
#[test]
fn install_accepts_bin_dir_override() {
let cli = Cli::parse_from(["repobin", "install", "--bin-dir", "~/.local/bin"]);
match cli.command {
Command::Install(args) => {
assert_eq!(
args.bin_dir.bin_dir.as_deref(),
Some(std::path::Path::new("~/.local/bin"))
);
}
_ => panic!("expected install command"),
}
}
#[test]
fn exec_preserves_trailing_args() {
let cli = Cli::parse_from(["repobin", "exec", "boss", "--", "task", "list", "--json"]);
match cli.command {
Command::Exec(args) => {
assert_eq!(args.tool, "boss");
assert_eq!(
args.args,
vec![
OsString::from("task"),
OsString::from("list"),
OsString::from("--json"),
]
);
}
_ => panic!("expected exec command"),
}
}
}