use std::path::PathBuf; use clap::{Args, Subcommand}; // each variant carries its own arguments as a struct rather than as fields // spread across the enum. the command that implements it takes that struct, so // main does not unpack what clap has already parsed and hand it on as a row of // booleans nothing but position tells apart #[derive(Subcommand, Debug)] pub enum Link { /// Move untracked paths into the store and symlink them back Add(Add), /// Move paths in the store back into the repository Restore(Restore), /// List what this repository keeps in the store List(List), /// List untracked paths a sandbox would still see Check(Check), /// Move this checkout's paths from the old store layout into its own directory Migrate(Migrate), } #[derive(Args, Debug)] pub struct Migrate { #[command(flatten)] pub store: Store, } #[derive(Args, Debug)] pub struct Add { /// Untracked or ignored paths inside the repository #[arg(required = true)] pub paths: Vec, /// Link to a store path that already exists #[arg(long)] pub force: bool, #[command(flatten)] pub store: Store, } #[derive(Args, Debug)] pub struct Restore { // said here rather than checked at runtime, so a mistake in the // arguments is reported as one, with the usage and the exit code clap // gives every other argument error #[arg(required_unless_present = "all", conflicts_with = "all")] pub paths: Vec, /// Restore every path this repository has in the store #[arg(long)] pub all: bool, #[command(flatten)] pub store: Store, } #[derive(Args, Debug)] pub struct List { #[command(flatten)] pub store: Store, } #[derive(Args, Debug)] pub struct Check { /// Limit the listing to these paths pub paths: Vec, /// Print ` ` for scripts, as `git status --porcelain` does #[arg(long)] pub porcelain: bool, /// Exit with 4 when anything is outside the store, for scripts #[arg(long)] pub exit_code: bool, /// Terminate porcelain entries with NUL #[arg(short = 'z')] pub null: bool, #[command(flatten)] pub store: Store, } #[derive(Args, Debug)] pub struct Store { /// Where the out-of-repo store lives /// /// Defaults to `${XDG_DATA_HOME:-$HOME/.local/share}/ahab`. #[arg(long = "store", env = "AHAB_LINK_ROOT", value_name = "DIR")] pub root: Option, } impl Store { pub fn root(&self) -> Option<&std::path::Path> { self.root.as_deref() } }