1#![doc = include_str!("../README.md")]
2
3use anyhow::Result;
4use clap::{Parser, ValueEnum};
5
6pub mod balance;
7pub mod check;
8pub mod device;
9pub mod filesystem;
10pub mod inspect;
11pub mod property;
12pub mod qgroup;
13pub mod quota;
14pub mod receive;
15pub mod replace;
16pub mod rescue;
17pub mod restore;
18pub mod scrub;
19pub mod send;
20pub mod subvolume;
21pub mod util;
22
23use crate::{
24 balance::BalanceCommand, check::CheckCommand, device::DeviceCommand,
25 filesystem::FilesystemCommand, inspect::InspectCommand, property::PropertyCommand,
26 qgroup::QgroupCommand, quota::QuotaCommand, receive::ReceiveCommand, replace::ReplaceCommand,
27 rescue::RescueCommand, restore::RestoreCommand, scrub::ScrubCommand, send::SendCommand,
28 subvolume::SubvolumeCommand,
29};
30
31#[derive(Default, Debug, Clone, Copy, PartialEq, Eq, ValueEnum)]
32pub enum Format {
33 #[default]
34 Text,
35 Json,
36}
37
38#[derive(Default, Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, ValueEnum)]
39pub enum Level {
40 Debug,
41 #[default]
42 Info,
43 Warn,
44 Error,
45}
46
47#[derive(Parser, Debug)]
57#[clap(version, infer_subcommands = true)]
58pub struct Arguments {
59 #[clap(flatten)]
60 pub global: GlobalOptions,
61
62 #[clap(subcommand)]
63 pub command: Command,
64}
65
66#[derive(Parser, Debug)]
67pub struct GlobalOptions {
68 #[clap(global = true, short, long)]
70 pub verbose: bool,
71
72 #[clap(global = true, short, long)]
74 pub quiet: bool,
75
76 #[clap(global = true, long)]
78 pub dry_run: bool,
79
80 #[clap(global = true, long)]
82 pub log: Option<Level>,
83
84 #[clap(global = true, long)]
86 pub format: Option<Format>,
87}
88
89pub trait Runnable {
90 fn run(&self, format: Format, dry_run: bool) -> Result<()>;
91}
92
93#[derive(Parser, Debug)]
94pub enum Command {
95 Balance(BalanceCommand),
96 Check(CheckCommand),
97 Device(DeviceCommand),
98 Filesystem(FilesystemCommand),
99 #[command(alias = "inspect-internal")]
100 Inspect(InspectCommand),
101 Property(PropertyCommand),
102 Qgroup(QgroupCommand),
103 Quota(QuotaCommand),
104 Receive(ReceiveCommand),
105 Replace(ReplaceCommand),
106 Rescue(RescueCommand),
107 Restore(RestoreCommand),
108 Scrub(ScrubCommand),
109 Send(SendCommand),
110 Subvolume(SubvolumeCommand),
111}
112
113impl Runnable for Command {
114 fn run(&self, format: Format, dry_run: bool) -> Result<()> {
115 match self {
116 Command::Balance(cmd) => cmd.run(format, dry_run),
117 Command::Check(cmd) => cmd.run(format, dry_run),
118 Command::Device(cmd) => cmd.run(format, dry_run),
119 Command::Filesystem(cmd) => cmd.run(format, dry_run),
120 Command::Inspect(cmd) => cmd.run(format, dry_run),
121 Command::Property(cmd) => cmd.run(format, dry_run),
122 Command::Qgroup(cmd) => cmd.run(format, dry_run),
123 Command::Quota(cmd) => cmd.run(format, dry_run),
124 Command::Receive(cmd) => cmd.run(format, dry_run),
125 Command::Replace(cmd) => cmd.run(format, dry_run),
126 Command::Rescue(cmd) => cmd.run(format, dry_run),
127 Command::Restore(cmd) => cmd.run(format, dry_run),
128 Command::Scrub(cmd) => cmd.run(format, dry_run),
129 Command::Send(cmd) => cmd.run(format, dry_run),
130 Command::Subvolume(cmd) => cmd.run(format, dry_run),
131 }
132 }
133}
134
135impl Arguments {
136 pub fn run(&self) -> Result<()> {
137 env_logger::init();
138 self.command
139 .run(self.global.format.unwrap_or_default(), self.global.dry_run)
140 }
141}