Skip to main content

btrfs_cli/
lib.rs

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/// A Rust implementation of the btrfs command-line tool for managing Btrfs filesystems.
48///
49/// btrfs is a modern copy-on-write filesystem for Linux that provides advanced features
50/// including subvolumes, snapshots, RAID support, compression, quotas, and checksumming.
51/// This tool allows you to create and manage filesystems, devices, subvolumes, snapshots,
52/// quotas, and perform various maintenance operations.
53///
54/// Most operations require CAP_SYS_ADMIN (root privileges) or special permissions for
55/// the specific filesystem.
56#[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    /// Increase verbosity of the subcommand
69    #[clap(global = true, short, long)]
70    pub verbose: bool,
71
72    /// Print only errors
73    #[clap(global = true, short, long)]
74    pub quiet: bool,
75
76    /// If supported, do not do any active/changing actions
77    #[clap(global = true, long)]
78    pub dry_run: bool,
79
80    /// Set log level
81    #[clap(global = true, long)]
82    pub log: Option<Level>,
83
84    /// If supported, print subcommand output in that format
85    #[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}