mirror of
https://github.com/koverstreet/bcachefs-tools.git
synced 2025-02-23 00:00:02 +03:00
add command to generate Rust-part CLI completions
This commit is contained in:
parent
61134a06fa
commit
1d1fe7b0b6
@ -97,6 +97,9 @@ static void usage(void)
|
|||||||
" fusemount Mount a filesystem via FUSE\n"
|
" fusemount Mount a filesystem via FUSE\n"
|
||||||
"\n"
|
"\n"
|
||||||
"Miscellaneous:\n"
|
"Miscellaneous:\n"
|
||||||
|
#ifndef BCACHEFS_NO_RUST
|
||||||
|
" completions Generate shell completions\n"
|
||||||
|
#endif
|
||||||
" version Display the version of the invoked bcachefs tool\n");
|
" version Display the version of the invoked bcachefs tool\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -273,6 +276,8 @@ int main(int argc, char *argv[])
|
|||||||
#ifndef BCACHEFS_NO_RUST
|
#ifndef BCACHEFS_NO_RUST
|
||||||
if (!strcmp(cmd, "mount"))
|
if (!strcmp(cmd, "mount"))
|
||||||
return cmd_mount(argc, argv);
|
return cmd_mount(argc, argv);
|
||||||
|
if (strstr(cmd, "completions"))
|
||||||
|
return cmd_completions(argc, argv);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef BCACHEFS_FUSE
|
#ifdef BCACHEFS_FUSE
|
||||||
|
3
cmds.h
3
cmds.h
@ -60,6 +60,7 @@ int cmd_subvolume_delete(int argc, char *argv[]);
|
|||||||
int cmd_subvolume_snapshot(int argc, char *argv[]);
|
int cmd_subvolume_snapshot(int argc, char *argv[]);
|
||||||
|
|
||||||
int cmd_fusemount(int argc, char *argv[]);
|
int cmd_fusemount(int argc, char *argv[]);
|
||||||
int cmd_mount(int agc, char *argv[]);
|
int cmd_mount(int argc, char *argv[]);
|
||||||
|
int cmd_completions(int argc, char *argv[]);
|
||||||
|
|
||||||
#endif /* _CMDS_H */
|
#endif /* _CMDS_H */
|
||||||
|
10
rust-src/Cargo.lock
generated
10
rust-src/Cargo.lock
generated
@ -93,6 +93,7 @@ dependencies = [
|
|||||||
"byteorder",
|
"byteorder",
|
||||||
"chrono",
|
"chrono",
|
||||||
"clap",
|
"clap",
|
||||||
|
"clap_complete",
|
||||||
"colored",
|
"colored",
|
||||||
"either",
|
"either",
|
||||||
"errno 0.2.8",
|
"errno 0.2.8",
|
||||||
@ -237,6 +238,15 @@ dependencies = [
|
|||||||
"terminal_size",
|
"terminal_size",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "clap_complete"
|
||||||
|
version = "4.4.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bffe91f06a11b4b9420f62103854e90867812cd5d01557f853c5ee8e791b12ae"
|
||||||
|
dependencies = [
|
||||||
|
"clap",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "clap_derive"
|
name = "clap_derive"
|
||||||
version = "4.3.12"
|
version = "4.3.12"
|
||||||
|
@ -14,6 +14,7 @@ log = { version = "0.4", features = ["std"] }
|
|||||||
chrono = { version = "0.4", default-features = false }
|
chrono = { version = "0.4", default-features = false }
|
||||||
colored = "2"
|
colored = "2"
|
||||||
clap = { version = "4.0.32", features = ["derive", "wrap_help"] }
|
clap = { version = "4.0.32", features = ["derive", "wrap_help"] }
|
||||||
|
clap_complete = "4.4.4"
|
||||||
anyhow = "1.0"
|
anyhow = "1.0"
|
||||||
libc = "0.2.69"
|
libc = "0.2.69"
|
||||||
udev = "0.7.0"
|
udev = "0.7.0"
|
||||||
|
24
rust-src/src/cmd_completions.rs
Normal file
24
rust-src/src/cmd_completions.rs
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
use crate::transform_c_args;
|
||||||
|
use clap::{Command, CommandFactory, Parser};
|
||||||
|
use clap_complete::{generate, Generator, Shell};
|
||||||
|
use std::ffi::{c_char, c_int};
|
||||||
|
use std::io;
|
||||||
|
|
||||||
|
/// Generate shell completions
|
||||||
|
#[derive(clap::Parser, Debug)]
|
||||||
|
pub struct Cli {
|
||||||
|
shell: Shell,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn print_completions<G: Generator>(gen: G, cmd: &mut Command) {
|
||||||
|
generate(gen, cmd, cmd.get_name().to_string(), &mut io::stdout());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
#[allow(clippy::not_unsafe_ptr_arg_deref)]
|
||||||
|
pub extern "C" fn cmd_completions(argc: c_int, argv: *const *const c_char) -> c_int {
|
||||||
|
transform_c_args!(argv, argc, argv);
|
||||||
|
let cli = Cli::parse_from(argv);
|
||||||
|
print_completions(cli.shell, &mut super::Cli::command());
|
||||||
|
0
|
||||||
|
}
|
@ -8,9 +8,9 @@ use bch_bindgen::btree::BtreeTrans;
|
|||||||
use bch_bindgen::btree::BtreeIter;
|
use bch_bindgen::btree::BtreeIter;
|
||||||
use bch_bindgen::btree::BtreeNodeIter;
|
use bch_bindgen::btree::BtreeNodeIter;
|
||||||
use bch_bindgen::btree::BtreeIterFlags;
|
use bch_bindgen::btree::BtreeIterFlags;
|
||||||
use clap::Parser;
|
use clap::{Args, Parser};
|
||||||
use std::ffi::{CStr, OsStr, c_int, c_char};
|
use std::ffi::{c_int, c_char};
|
||||||
use std::os::unix::ffi::OsStrExt;
|
use crate::transform_c_args;
|
||||||
|
|
||||||
fn list_keys(fs: &Fs, opt: Cli) -> anyhow::Result<()> {
|
fn list_keys(fs: &Fs, opt: Cli) -> anyhow::Result<()> {
|
||||||
let trans = BtreeTrans::new(fs);
|
let trans = BtreeTrans::new(fs);
|
||||||
@ -84,7 +84,7 @@ fn list_nodes_ondisk(fs: &Fs, opt: Cli) -> anyhow::Result<()> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, clap::ValueEnum)]
|
#[derive(Clone, clap::ValueEnum, Debug)]
|
||||||
enum Mode {
|
enum Mode {
|
||||||
Keys,
|
Keys,
|
||||||
Formats,
|
Formats,
|
||||||
@ -92,8 +92,8 @@ enum Mode {
|
|||||||
NodesOndisk,
|
NodesOndisk,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Parser)]
|
#[derive(Parser, Debug)]
|
||||||
struct Cli {
|
pub struct Cli {
|
||||||
/// Btree to list from
|
/// Btree to list from
|
||||||
#[arg(short, long, default_value_t=bcachefs::btree_id::BTREE_ID_extents)]
|
#[arg(short, long, default_value_t=bcachefs::btree_id::BTREE_ID_extents)]
|
||||||
btree: bcachefs::btree_id,
|
btree: bcachefs::btree_id,
|
||||||
@ -120,7 +120,7 @@ struct Cli {
|
|||||||
/// Force color on/off. Default: autodetect tty
|
/// Force color on/off. Default: autodetect tty
|
||||||
#[arg(short, long, action = clap::ArgAction::Set, default_value_t=atty::is(Stream::Stdout))]
|
#[arg(short, long, action = clap::ArgAction::Set, default_value_t=atty::is(Stream::Stdout))]
|
||||||
colorize: bool,
|
colorize: bool,
|
||||||
|
|
||||||
/// Verbose mode
|
/// Verbose mode
|
||||||
#[arg(short, long)]
|
#[arg(short, long)]
|
||||||
verbose: bool,
|
verbose: bool,
|
||||||
@ -157,12 +157,9 @@ fn cmd_list_inner(opt: Cli) -> anyhow::Result<()> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
|
#[allow(clippy::not_unsafe_ptr_arg_deref)]
|
||||||
pub extern "C" fn cmd_list(argc: c_int, argv: *const *const c_char) {
|
pub extern "C" fn cmd_list(argc: c_int, argv: *const *const c_char) {
|
||||||
let argv: Vec<_> = (0..argc)
|
transform_c_args!(argv, argc, argv);
|
||||||
.map(|i| unsafe { CStr::from_ptr(*argv.add(i as usize)) })
|
|
||||||
.map(|i| OsStr::from_bytes(i.to_bytes()))
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
let opt = Cli::parse_from(argv);
|
let opt = Cli::parse_from(argv);
|
||||||
colored::control::set_override(opt.colorize);
|
colored::control::set_override(opt.colorize);
|
||||||
if let Err(e) = cmd_list_inner(opt) {
|
if let Err(e) = cmd_list_inner(opt) {
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
use atty::Stream;
|
use atty::Stream;
|
||||||
use bch_bindgen::{bcachefs, bcachefs::bch_sb_handle};
|
use bch_bindgen::{bcachefs, bcachefs::bch_sb_handle};
|
||||||
use log::{info, debug, error, LevelFilter};
|
use log::{info, debug, error, LevelFilter};
|
||||||
use clap::Parser;
|
use clap::{Parser, Subcommand};
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use crate::key;
|
use crate::{key, transform_c_args};
|
||||||
use crate::key::KeyLoc;
|
use crate::key::KeyLoc;
|
||||||
use crate::logger::SimpleLogger;
|
use crate::logger::SimpleLogger;
|
||||||
use std::ffi::{CStr, CString, OsStr, c_int, c_char, c_void};
|
use std::ffi::{CStr, CString, OsStr, c_int, c_char, c_void};
|
||||||
@ -129,7 +129,7 @@ fn get_devices_by_uuid(uuid: Uuid) -> anyhow::Result<Vec<(PathBuf, bch_sb_handle
|
|||||||
/// Mount a bcachefs filesystem by its UUID.
|
/// Mount a bcachefs filesystem by its UUID.
|
||||||
#[derive(Parser, Debug)]
|
#[derive(Parser, Debug)]
|
||||||
#[command(author, version, about, long_about = None)]
|
#[command(author, version, about, long_about = None)]
|
||||||
struct Cli {
|
pub struct Cli {
|
||||||
/// Where the password would be loaded from.
|
/// Where the password would be loaded from.
|
||||||
///
|
///
|
||||||
/// Possible values are:
|
/// Possible values are:
|
||||||
@ -228,12 +228,9 @@ fn cmd_mount_inner(opt: Cli) -> anyhow::Result<()> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
|
#[allow(clippy::not_unsafe_ptr_arg_deref)]
|
||||||
pub extern "C" fn cmd_mount(argc: c_int, argv: *const *const c_char) -> c_int {
|
pub extern "C" fn cmd_mount(argc: c_int, argv: *const *const c_char) -> c_int {
|
||||||
let argv: Vec<_> = (0..argc)
|
transform_c_args!(argv, argc, argv);
|
||||||
.map(|i| unsafe { CStr::from_ptr(*argv.add(i as usize)) })
|
|
||||||
.map(|i| OsStr::from_bytes(i.to_bytes()))
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
let opt = Cli::parse_from(argv);
|
let opt = Cli::parse_from(argv);
|
||||||
|
|
||||||
log::set_boxed_logger(Box::new(SimpleLogger)).unwrap();
|
log::set_boxed_logger(Box::new(SimpleLogger)).unwrap();
|
||||||
|
@ -1,7 +1,24 @@
|
|||||||
|
use clap::Subcommand;
|
||||||
|
|
||||||
pub mod key;
|
pub mod key;
|
||||||
pub mod logger;
|
pub mod logger;
|
||||||
pub mod cmd_mount;
|
pub mod cmd_mount;
|
||||||
pub mod cmd_list;
|
pub mod cmd_list;
|
||||||
|
pub mod cmd_completions;
|
||||||
|
|
||||||
|
#[derive(clap::Parser, Debug)]
|
||||||
|
#[command(name = "bcachefs")]
|
||||||
|
pub struct Cli {
|
||||||
|
#[command(subcommand)]
|
||||||
|
subcommands: Subcommands,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Subcommand, Debug)]
|
||||||
|
enum Subcommands {
|
||||||
|
List(cmd_list::Cli),
|
||||||
|
Mount(cmd_mount::Cli),
|
||||||
|
Completions(cmd_completions::Cli),
|
||||||
|
}
|
||||||
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! c_str {
|
macro_rules! c_str {
|
||||||
@ -14,6 +31,18 @@ macro_rules! c_str {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! transform_c_args {
|
||||||
|
($var:ident, $argc:expr, $argv:expr) => {
|
||||||
|
// TODO: `OsStr::from_bytes` only exists on *nix
|
||||||
|
use ::std::os::unix::ffi::OsStrExt;
|
||||||
|
let $var: Vec<_> = (0..$argc)
|
||||||
|
.map(|i| unsafe { ::std::ffi::CStr::from_ptr(*$argv.add(i as usize)) })
|
||||||
|
.map(|i| ::std::ffi::OsStr::from_bytes(i.to_bytes()))
|
||||||
|
.collect();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct ErrnoError(errno::Errno);
|
struct ErrnoError(errno::Errno);
|
||||||
impl std::fmt::Display for ErrnoError {
|
impl std::fmt::Display for ErrnoError {
|
||||||
|
Loading…
Reference in New Issue
Block a user