use super::{BackupCommandError, usage};
use clap::{Arg, ArgAction, ArgMatches, Command as ClapCommand};
use std::{ffi::OsString, path::PathBuf};
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct BackupPreflightOptions {
pub dir: PathBuf,
pub out_dir: PathBuf,
pub mapping: Option<PathBuf>,
pub require_design_v1: bool,
pub require_restore_ready: bool,
}
impl BackupPreflightOptions {
pub fn parse<I>(args: I) -> Result<Self, BackupCommandError>
where
I: IntoIterator<Item = OsString>,
{
let matches = parse_backup_options(backup_preflight_command(), args)?;
Ok(Self {
dir: required_path_option(&matches, "dir", "--dir")?,
out_dir: required_path_option(&matches, "out-dir", "--out-dir")?,
mapping: path_option(&matches, "mapping"),
require_design_v1: matches.get_flag("require-design"),
require_restore_ready: matches.get_flag("require-restore-ready"),
})
}
}
fn backup_preflight_command() -> ClapCommand {
backup_dir_out_dir_command("backup-preflight")
.arg(value_arg("mapping").long("mapping"))
.arg(require_design_arg())
.arg(flag_arg("require-restore-ready").long("require-restore-ready"))
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct BackupSmokeOptions {
pub dir: PathBuf,
pub out_dir: PathBuf,
pub mapping: Option<PathBuf>,
pub dfx: String,
pub network: Option<String>,
pub require_design_v1: bool,
pub require_restore_ready: bool,
}
impl BackupSmokeOptions {
pub fn parse<I>(args: I) -> Result<Self, BackupCommandError>
where
I: IntoIterator<Item = OsString>,
{
let matches = parse_backup_options(backup_smoke_command(), args)?;
Ok(Self {
dir: required_path_option(&matches, "dir", "--dir")?,
out_dir: required_path_option(&matches, "out-dir", "--out-dir")?,
mapping: path_option(&matches, "mapping"),
dfx: string_option(&matches, "dfx").unwrap_or_else(|| "dfx".to_string()),
network: string_option(&matches, "network"),
require_design_v1: matches.get_flag("require-design"),
require_restore_ready: matches.get_flag("require-restore-ready"),
})
}
}
fn backup_smoke_command() -> ClapCommand {
backup_dir_out_dir_command("backup-smoke")
.arg(value_arg("mapping").long("mapping"))
.arg(value_arg("dfx").long("dfx"))
.arg(value_arg("network").long("network"))
.arg(require_design_arg())
.arg(flag_arg("require-restore-ready").long("require-restore-ready"))
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct BackupInspectOptions {
pub dir: PathBuf,
pub out: Option<PathBuf>,
pub require_ready: bool,
}
impl BackupInspectOptions {
pub fn parse<I>(args: I) -> Result<Self, BackupCommandError>
where
I: IntoIterator<Item = OsString>,
{
let matches = parse_backup_options(backup_inspect_command(), args)?;
Ok(Self {
dir: required_path_option(&matches, "dir", "--dir")?,
out: path_option(&matches, "out"),
require_ready: matches.get_flag("require-ready"),
})
}
}
fn backup_inspect_command() -> ClapCommand {
backup_dir_out_command("backup-inspect").arg(flag_arg("require-ready").long("require-ready"))
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct BackupProvenanceOptions {
pub dir: PathBuf,
pub out: Option<PathBuf>,
pub require_consistent: bool,
}
impl BackupProvenanceOptions {
pub fn parse<I>(args: I) -> Result<Self, BackupCommandError>
where
I: IntoIterator<Item = OsString>,
{
let matches = parse_backup_options(backup_provenance_command(), args)?;
Ok(Self {
dir: required_path_option(&matches, "dir", "--dir")?,
out: path_option(&matches, "out"),
require_consistent: matches.get_flag("require-consistent"),
})
}
}
fn backup_provenance_command() -> ClapCommand {
backup_dir_out_command("backup-provenance")
.arg(flag_arg("require-consistent").long("require-consistent"))
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct BackupVerifyOptions {
pub dir: PathBuf,
pub out: Option<PathBuf>,
}
impl BackupVerifyOptions {
pub fn parse<I>(args: I) -> Result<Self, BackupCommandError>
where
I: IntoIterator<Item = OsString>,
{
let matches = parse_backup_options(backup_verify_command(), args)?;
Ok(Self {
dir: required_path_option(&matches, "dir", "--dir")?,
out: path_option(&matches, "out"),
})
}
}
fn backup_verify_command() -> ClapCommand {
backup_dir_out_command("backup-verify")
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct BackupStatusOptions {
pub dir: PathBuf,
pub out: Option<PathBuf>,
pub require_complete: bool,
}
impl BackupStatusOptions {
pub fn parse<I>(args: I) -> Result<Self, BackupCommandError>
where
I: IntoIterator<Item = OsString>,
{
let matches = parse_backup_options(backup_status_command(), args)?;
Ok(Self {
dir: required_path_option(&matches, "dir", "--dir")?,
out: path_option(&matches, "out"),
require_complete: matches.get_flag("require-complete"),
})
}
}
fn backup_status_command() -> ClapCommand {
backup_dir_out_command("backup-status")
.arg(flag_arg("require-complete").long("require-complete"))
}
fn parse_backup_options<I>(command: ClapCommand, args: I) -> Result<ArgMatches, BackupCommandError>
where
I: IntoIterator<Item = OsString>,
{
let name = command.get_name().to_string();
command
.try_get_matches_from(std::iter::once(OsString::from(name)).chain(args))
.map_err(|_| BackupCommandError::Usage(usage()))
}
fn backup_dir_out_command(name: &'static str) -> ClapCommand {
ClapCommand::new(name)
.disable_help_flag(true)
.arg(value_arg("dir").long("dir"))
.arg(value_arg("out").long("out"))
}
fn backup_dir_out_dir_command(name: &'static str) -> ClapCommand {
ClapCommand::new(name)
.disable_help_flag(true)
.arg(value_arg("dir").long("dir"))
.arg(value_arg("out-dir").long("out-dir"))
}
fn value_arg(id: &'static str) -> Arg {
Arg::new(id).num_args(1)
}
fn flag_arg(id: &'static str) -> Arg {
Arg::new(id).action(ArgAction::SetTrue)
}
fn require_design_arg() -> Arg {
flag_arg("require-design").long("require-design")
}
fn string_option(matches: &ArgMatches, id: &str) -> Option<String> {
matches.get_one::<String>(id).cloned()
}
fn path_option(matches: &ArgMatches, id: &str) -> Option<PathBuf> {
string_option(matches, id).map(PathBuf::from)
}
fn required_path_option(
matches: &ArgMatches,
id: &str,
option: &'static str,
) -> Result<PathBuf, BackupCommandError> {
path_option(matches, id).ok_or(BackupCommandError::MissingOption(option))
}