1use anyhow::Result;
13use clap::{Parser, ValueEnum};
14
15mod balance;
16mod check;
17mod device;
18mod filesystem;
19mod inspect;
20mod property;
21mod qgroup;
22mod quota;
23mod receive;
24mod replace;
25mod rescue;
26mod restore;
27mod scrub;
28mod send;
29mod subvolume;
30mod util;
31
32pub use crate::{
33 balance::*, check::*, device::*, filesystem::*, inspect::*, property::*,
34 qgroup::*, quota::*, receive::*, replace::*, rescue::*, restore::*,
35 scrub::*, send::*, subvolume::*,
36};
37
38#[derive(Default, Debug, Clone, Copy, PartialEq, Eq, ValueEnum)]
39pub enum Format {
40 #[default]
41 Text,
42 Json,
43}
44
45#[derive(
46 Default, Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, ValueEnum,
47)]
48pub enum Level {
49 Debug,
50 #[default]
51 Info,
52 Warn,
53 Error,
54}
55
56#[derive(Parser, Debug)]
66#[clap(version, infer_subcommands = true)]
67pub struct Arguments {
68 #[clap(flatten)]
69 pub global: GlobalOptions,
70
71 #[clap(subcommand)]
72 pub command: Command,
73}
74
75const GLOBAL_OPTIONS: &'static str = "Global options";
76
77#[derive(Parser, Debug)]
78pub struct GlobalOptions {
79 #[clap(global = true, short, long, help_heading = GLOBAL_OPTIONS)]
81 pub verbose: bool,
82
83 #[clap(global = true, short, long, help_heading = GLOBAL_OPTIONS)]
85 pub quiet: bool,
86
87 #[clap(global = true, long, help_heading = GLOBAL_OPTIONS)]
89 pub dry_run: bool,
90
91 #[clap(global = true, long, help_heading = GLOBAL_OPTIONS)]
93 pub log: Option<Level>,
94
95 #[clap(global = true, long, help_heading = GLOBAL_OPTIONS)]
97 pub format: Option<Format>,
98}
99
100pub trait Runnable {
101 fn run(&self, format: Format, dry_run: bool) -> Result<()>;
102}
103
104#[derive(Parser, Debug)]
105pub enum Command {
106 Balance(BalanceCommand),
107 Check(CheckCommand),
108 Device(DeviceCommand),
109 Filesystem(FilesystemCommand),
110 #[command(alias = "inspect-internal")]
111 Inspect(InspectCommand),
112 Property(PropertyCommand),
113 Qgroup(QgroupCommand),
114 Quota(QuotaCommand),
115 Receive(ReceiveCommand),
116 Replace(ReplaceCommand),
117 Rescue(RescueCommand),
118 Restore(RestoreCommand),
119 Scrub(ScrubCommand),
120 Send(SendCommand),
121 Subvolume(SubvolumeCommand),
122}
123
124impl Runnable for Command {
125 fn run(&self, format: Format, dry_run: bool) -> Result<()> {
126 match self {
127 Command::Balance(cmd) => cmd.run(format, dry_run),
128 Command::Check(cmd) => cmd.run(format, dry_run),
129 Command::Device(cmd) => cmd.run(format, dry_run),
130 Command::Filesystem(cmd) => cmd.run(format, dry_run),
131 Command::Inspect(cmd) => cmd.run(format, dry_run),
132 Command::Property(cmd) => cmd.run(format, dry_run),
133 Command::Qgroup(cmd) => cmd.run(format, dry_run),
134 Command::Quota(cmd) => cmd.run(format, dry_run),
135 Command::Receive(cmd) => cmd.run(format, dry_run),
136 Command::Replace(cmd) => cmd.run(format, dry_run),
137 Command::Rescue(cmd) => cmd.run(format, dry_run),
138 Command::Restore(cmd) => cmd.run(format, dry_run),
139 Command::Scrub(cmd) => cmd.run(format, dry_run),
140 Command::Send(cmd) => cmd.run(format, dry_run),
141 Command::Subvolume(cmd) => cmd.run(format, dry_run),
142 }
143 }
144}
145
146impl Arguments {
147 pub fn run(&self) -> Result<()> {
148 env_logger::init();
149 self.command
150 .run(self.global.format.unwrap_or_default(), self.global.dry_run)
151 }
152}