canic_cli/backup/options/
mod.rs1use super::{BackupCommandError, usage};
2use clap::{Arg, ArgAction, ArgMatches, Command as ClapCommand};
3use std::{ffi::OsString, path::PathBuf};
4
5#[derive(Clone, Debug, Eq, PartialEq)]
10pub struct BackupPreflightOptions {
11 pub dir: PathBuf,
12 pub out_dir: PathBuf,
13 pub mapping: Option<PathBuf>,
14 pub require_design_v1: bool,
15 pub require_restore_ready: bool,
16}
17
18impl BackupPreflightOptions {
19 pub fn parse<I>(args: I) -> Result<Self, BackupCommandError>
21 where
22 I: IntoIterator<Item = OsString>,
23 {
24 let matches = parse_backup_options(backup_preflight_command(), args)?;
25
26 Ok(Self {
27 dir: required_path_option(&matches, "dir", "--dir")?,
28 out_dir: required_path_option(&matches, "out-dir", "--out-dir")?,
29 mapping: path_option(&matches, "mapping"),
30 require_design_v1: matches.get_flag("require-design"),
31 require_restore_ready: matches.get_flag("require-restore-ready"),
32 })
33 }
34}
35
36fn backup_preflight_command() -> ClapCommand {
38 backup_dir_out_dir_command("backup-preflight")
39 .arg(value_arg("mapping").long("mapping"))
40 .arg(require_design_arg())
41 .arg(flag_arg("require-restore-ready").long("require-restore-ready"))
42}
43
44#[derive(Clone, Debug, Eq, PartialEq)]
49pub struct BackupSmokeOptions {
50 pub dir: PathBuf,
51 pub out_dir: PathBuf,
52 pub mapping: Option<PathBuf>,
53 pub dfx: String,
54 pub network: Option<String>,
55 pub require_design_v1: bool,
56 pub require_restore_ready: bool,
57}
58
59impl BackupSmokeOptions {
60 pub fn parse<I>(args: I) -> Result<Self, BackupCommandError>
62 where
63 I: IntoIterator<Item = OsString>,
64 {
65 let matches = parse_backup_options(backup_smoke_command(), args)?;
66
67 Ok(Self {
68 dir: required_path_option(&matches, "dir", "--dir")?,
69 out_dir: required_path_option(&matches, "out-dir", "--out-dir")?,
70 mapping: path_option(&matches, "mapping"),
71 dfx: string_option(&matches, "dfx").unwrap_or_else(|| "dfx".to_string()),
72 network: string_option(&matches, "network"),
73 require_design_v1: matches.get_flag("require-design"),
74 require_restore_ready: matches.get_flag("require-restore-ready"),
75 })
76 }
77}
78
79fn backup_smoke_command() -> ClapCommand {
81 backup_dir_out_dir_command("backup-smoke")
82 .arg(value_arg("mapping").long("mapping"))
83 .arg(value_arg("dfx").long("dfx"))
84 .arg(value_arg("network").long("network"))
85 .arg(require_design_arg())
86 .arg(flag_arg("require-restore-ready").long("require-restore-ready"))
87}
88
89#[derive(Clone, Debug, Eq, PartialEq)]
94pub struct BackupInspectOptions {
95 pub dir: PathBuf,
96 pub out: Option<PathBuf>,
97 pub require_ready: bool,
98}
99
100impl BackupInspectOptions {
101 pub fn parse<I>(args: I) -> Result<Self, BackupCommandError>
103 where
104 I: IntoIterator<Item = OsString>,
105 {
106 let matches = parse_backup_options(backup_inspect_command(), args)?;
107
108 Ok(Self {
109 dir: required_path_option(&matches, "dir", "--dir")?,
110 out: path_option(&matches, "out"),
111 require_ready: matches.get_flag("require-ready"),
112 })
113 }
114}
115
116fn backup_inspect_command() -> ClapCommand {
118 backup_dir_out_command("backup-inspect").arg(flag_arg("require-ready").long("require-ready"))
119}
120
121#[derive(Clone, Debug, Eq, PartialEq)]
126pub struct BackupProvenanceOptions {
127 pub dir: PathBuf,
128 pub out: Option<PathBuf>,
129 pub require_consistent: bool,
130}
131
132impl BackupProvenanceOptions {
133 pub fn parse<I>(args: I) -> Result<Self, BackupCommandError>
135 where
136 I: IntoIterator<Item = OsString>,
137 {
138 let matches = parse_backup_options(backup_provenance_command(), args)?;
139
140 Ok(Self {
141 dir: required_path_option(&matches, "dir", "--dir")?,
142 out: path_option(&matches, "out"),
143 require_consistent: matches.get_flag("require-consistent"),
144 })
145 }
146}
147
148fn backup_provenance_command() -> ClapCommand {
150 backup_dir_out_command("backup-provenance")
151 .arg(flag_arg("require-consistent").long("require-consistent"))
152}
153
154#[derive(Clone, Debug, Eq, PartialEq)]
159pub struct BackupVerifyOptions {
160 pub dir: PathBuf,
161 pub out: Option<PathBuf>,
162}
163
164impl BackupVerifyOptions {
165 pub fn parse<I>(args: I) -> Result<Self, BackupCommandError>
167 where
168 I: IntoIterator<Item = OsString>,
169 {
170 let matches = parse_backup_options(backup_verify_command(), args)?;
171
172 Ok(Self {
173 dir: required_path_option(&matches, "dir", "--dir")?,
174 out: path_option(&matches, "out"),
175 })
176 }
177}
178
179fn backup_verify_command() -> ClapCommand {
181 backup_dir_out_command("backup-verify")
182}
183
184#[derive(Clone, Debug, Eq, PartialEq)]
189pub struct BackupStatusOptions {
190 pub dir: PathBuf,
191 pub out: Option<PathBuf>,
192 pub require_complete: bool,
193}
194
195impl BackupStatusOptions {
196 pub fn parse<I>(args: I) -> Result<Self, BackupCommandError>
198 where
199 I: IntoIterator<Item = OsString>,
200 {
201 let matches = parse_backup_options(backup_status_command(), args)?;
202
203 Ok(Self {
204 dir: required_path_option(&matches, "dir", "--dir")?,
205 out: path_option(&matches, "out"),
206 require_complete: matches.get_flag("require-complete"),
207 })
208 }
209}
210
211fn backup_status_command() -> ClapCommand {
213 backup_dir_out_command("backup-status")
214 .arg(flag_arg("require-complete").long("require-complete"))
215}
216
217fn parse_backup_options<I>(command: ClapCommand, args: I) -> Result<ArgMatches, BackupCommandError>
219where
220 I: IntoIterator<Item = OsString>,
221{
222 let name = command.get_name().to_string();
223 command
224 .try_get_matches_from(std::iter::once(OsString::from(name)).chain(args))
225 .map_err(|_| BackupCommandError::Usage(usage()))
226}
227
228fn backup_dir_out_command(name: &'static str) -> ClapCommand {
230 ClapCommand::new(name)
231 .disable_help_flag(true)
232 .arg(value_arg("dir").long("dir"))
233 .arg(value_arg("out").long("out"))
234}
235
236fn backup_dir_out_dir_command(name: &'static str) -> ClapCommand {
238 ClapCommand::new(name)
239 .disable_help_flag(true)
240 .arg(value_arg("dir").long("dir"))
241 .arg(value_arg("out-dir").long("out-dir"))
242}
243
244fn value_arg(id: &'static str) -> Arg {
246 Arg::new(id).num_args(1)
247}
248
249fn flag_arg(id: &'static str) -> Arg {
251 Arg::new(id).action(ArgAction::SetTrue)
252}
253
254fn require_design_arg() -> Arg {
256 flag_arg("require-design")
257 .long("require-design")
258 .alias("require-design-v1")
259}
260
261fn string_option(matches: &ArgMatches, id: &str) -> Option<String> {
263 matches.get_one::<String>(id).cloned()
264}
265
266fn path_option(matches: &ArgMatches, id: &str) -> Option<PathBuf> {
268 string_option(matches, id).map(PathBuf::from)
269}
270
271fn required_path_option(
273 matches: &ArgMatches,
274 id: &str,
275 option: &'static str,
276) -> Result<PathBuf, BackupCommandError> {
277 path_option(matches, id).ok_or(BackupCommandError::MissingOption(option))
278}