use clap::{Parser, Subcommand};
use std::path::PathBuf;
mod subcommands;
pub(crate) use subcommands::{
CacheCommands, CargoRegistryCommands, DefenderExclusionsCommands, FpCommands, GhaCacheCommands,
KvCommands, MesonCommands, RustPlanBackendArg, RustPlanCommands, SymbolsCommands,
};
const ENV_VARS_HELP: &str = "\
Environment variables:
ZCCACHE_PATH_REMAP=auto Inject compiler path-prefix maps so cached
artifacts are sharable across sibling clones /
worktrees. Opt-in; default is off. See README
'Path remapping' for guarantees and pitfalls.
ZCCACHE_STRICT_PATHS=MODE Same as --strict-paths (off | consistent | absolute).
ZCCACHE_CACHE_DIR=PATH Override the per-user cache root.
";
#[derive(Debug, Parser)]
#[command(name = "zccache", version, about, after_help = ENV_VARS_HELP)]
pub(crate) struct Cli {
#[arg(long)]
pub clear: bool,
#[arg(long)]
pub show_stats: bool,
#[arg(
long,
value_name = "MODE",
num_args = 0..=1,
default_missing_value = "absolute",
require_equals = true
)]
pub strict_paths: Option<String>,
#[command(subcommand)]
pub command: Option<Commands>,
}
#[derive(Debug, Subcommand)]
pub(crate) enum Commands {
Start,
#[command(visible_alias = "kill")]
Stop,
Status {
#[arg(long)]
json: bool,
},
Analyze {
journal: String,
#[arg(long)]
json: bool,
#[arg(long)]
session: Option<String>,
#[arg(long = "crate")]
crate_name: Option<String>,
#[arg(long)]
outcome: Option<String>,
#[arg(long, default_value = "wall-clock")]
sort: String,
#[arg(long)]
top: Option<usize>,
},
Clear,
#[command(name = "install-servicedef")]
InstallServicedef {
#[arg(long)]
daemon_binary: Option<String>,
#[arg(long)]
dir: Option<String>,
},
#[command(name = "session-start")]
SessionStart {
#[arg(long)]
cwd: Option<String>,
#[arg(long)]
log: Option<String>,
#[arg(long)]
endpoint: Option<String>,
#[arg(long)]
cache_dir: Option<String>,
#[arg(long)]
private_daemon: bool,
#[arg(long)]
daemon_name: Option<String>,
#[arg(long)]
owner_pid: Vec<u32>,
#[arg(long = "private-env", value_name = "KEY=VALUE")]
private_env: Vec<String>,
#[arg(long)]
stats: bool,
#[arg(long)]
journal: Option<String>,
#[arg(long)]
profile: bool,
},
#[command(name = "session-end")]
SessionEnd {
session_id: String,
#[arg(long)]
endpoint: Option<String>,
#[arg(long)]
json: bool,
},
#[command(name = "session-stats")]
SessionStatsCmd {
session_id: String,
#[arg(long)]
endpoint: Option<String>,
#[arg(long)]
json: bool,
},
Wrap {
#[arg(
long,
value_name = "MODE",
num_args = 0..=1,
default_missing_value = "absolute",
require_equals = true
)]
strict_paths: Option<String>,
#[arg(trailing_var_arg = true, allow_hyphen_values = true)]
args: Vec<String>,
},
Inspect {
key: String,
},
Crashes {
#[arg(long)]
clear: bool,
},
#[command(name = "fp")]
Fp {
#[arg(long)]
cache_file: String,
#[arg(long, default_value = "two-layer")]
cache_type: String,
#[arg(long)]
endpoint: Option<String>,
#[command(subcommand)]
fp_command: FpCommands,
},
#[command(name = "ino")]
Ino {
#[arg(long)]
input: String,
#[arg(long)]
output: String,
#[arg(long = "clang-arg")]
clang_args: Vec<String>,
#[arg(long)]
no_arduino_include: bool,
},
#[command(name = "gha-cache")]
GhaCache {
#[command(subcommand)]
action: GhaCacheCommands,
},
#[command(name = "rust-plan")]
RustPlan {
#[command(subcommand)]
action: RustPlanCommands,
},
Download {
#[arg(long)]
url: Option<String>,
#[arg(long = "part-url")]
part_urls: Vec<String>,
archive_path: Option<String>,
#[arg(long = "unarchive")]
unarchive_path: Option<String>,
#[arg(long = "sha256")]
expected_sha256: Option<String>,
#[arg(long)]
max_connections: Option<usize>,
#[arg(long)]
min_segment_size: Option<u64>,
#[arg(long)]
no_wait: bool,
#[arg(long)]
dry_run: bool,
#[arg(long)]
force: bool,
},
#[command(name = "cargo-registry")]
CargoRegistry {
#[command(subcommand)]
action: CargoRegistryCommands,
},
Kv {
#[command(subcommand)]
action: KvCommands,
},
Warm {
#[arg(long, default_value = "target")]
target_dir: String,
#[arg(long, default_value = "debug")]
profile: String,
#[arg(long)]
endpoint: Option<String>,
},
#[command(name = "snapshot-bytes")]
SnapshotBytes {
#[arg(long)]
target: PathBuf,
#[arg(long)]
prune_incremental: bool,
#[arg(long)]
prune_build_script_out: bool,
},
#[command(name = "snapshot-fp-record")]
SnapshotFpRecord {
#[arg(long, default_value = "target")]
target_dir: PathBuf,
#[arg(long)]
workspace_root: Option<PathBuf>,
#[arg(long, default_value = "debug")]
profile: String,
#[arg(long)]
manifest_path: Option<PathBuf>,
},
#[command(name = "snapshot-fp-validate")]
SnapshotFpValidate {
#[arg(long, default_value = "target")]
target_dir: PathBuf,
#[arg(long)]
workspace_root: Option<PathBuf>,
#[arg(long, default_value = "debug")]
profile: String,
#[arg(long)]
manifest_path: Option<PathBuf>,
#[arg(long, default_value_t = 60)]
stamp_seconds_ahead: u64,
},
Symbols {
#[command(subcommand)]
action: SymbolsCommands,
},
#[command(name = "cache-root")]
CacheRoot {
#[arg(long)]
json: bool,
},
#[command(name = "defender-exclusions")]
DefenderExclusions {
#[command(subcommand)]
action: DefenderExclusionsCommands,
},
Exec {
#[arg(long = "input-file", value_name = "PATH")]
input_file: Vec<String>,
#[arg(long = "input-env", value_name = "NAME")]
input_env: Vec<String>,
#[arg(long = "input-extra", value_name = "BYTES")]
input_extra: Option<String>,
#[arg(long = "output-stdout", default_value_t = true)]
output_stdout: bool,
#[arg(long = "output-stderr", default_value_t = true)]
output_stderr: bool,
#[arg(long = "output-file", value_name = "PATH")]
output_file: Vec<String>,
#[arg(long = "tool-hash", value_name = "HEX")]
tool_hash: Option<String>,
#[arg(long = "no-cache")]
no_cache: bool,
#[arg(long = "no-cwd-in-key")]
no_cwd_in_key: bool,
#[arg(long)]
endpoint: Option<String>,
#[arg(long = "include-scan", value_name = "PATH")]
include_scan: Vec<String>,
#[arg(long = "include-dir", value_name = "DIR")]
include_dir: Vec<String>,
#[arg(long = "system-include", value_name = "DIR")]
system_include: Vec<String>,
#[arg(long = "iquote-dir", value_name = "DIR")]
iquote_dir: Vec<String>,
#[arg(long = "depfile", value_name = "PATH")]
depfile: Option<String>,
#[arg(long = "non-deterministic")]
non_deterministic: bool,
#[arg(long = "key-args-filter", value_name = "REGEX")]
key_args_filter: Vec<String>,
#[arg(trailing_var_arg = true, allow_hyphen_values = true, last = true)]
tool_command: Vec<String>,
},
Cc {
#[arg(trailing_var_arg = true, allow_hyphen_values = true)]
args: Vec<String>,
},
Meson {
#[command(subcommand)]
command: MesonCommands,
},
Cache {
#[command(subcommand)]
command: CacheCommands,
},
#[command(name = "release-handles")]
ReleaseHandles {
#[arg(long)]
path: PathBuf,
#[arg(long)]
json: bool,
#[arg(long)]
endpoint: Option<String>,
},
}
pub(crate) const KNOWN_SUBCOMMANDS: &[&str] = &[
"start",
"stop",
"status",
"analyze",
"clear",
"install-servicedef",
"wrap",
"inspect",
"session-start",
"session-end",
"session-stats",
"crashes",
"fp",
"ino",
"download",
"cargo-registry",
"gha-cache",
"rust-plan",
"kv",
"meson",
"warm",
"snapshot-bytes",
"snapshot-fp-record",
"snapshot-fp-validate",
"symbols",
"cache",
"cache-root",
"release-handles",
"defender-exclusions",
"exec",
"cc",
"help",
"--help",
"-h",
"--version",
"-V",
];