From: Christoph Heiss <c.heiss@proxmox.com>
To: pve-devel@lists.proxmox.com
Subject: [pve-devel] [PATCH installer 2/5] chroot: replace clap with pico-args for command argument parsing
Date: Fri, 9 May 2025 14:09:14 +0200 [thread overview]
Message-ID: <20250509121007.1430080-3-c.heiss@proxmox.com> (raw)
In-Reply-To: <20250509121007.1430080-1-c.heiss@proxmox.com>
Drops clap for pico-args, as the former is pretty heavy-weight and
completely overhauls its API with ~every major release.
As for the resulting binary, there is a ~18% decrease in binary size,
from 2.9M to 2.4MiB (after stripping).
text data bss dec hex filename
2743595 274576 424 3018595 2e0f63 proxmox-chroot-clap
2208631 261224 408 2470263 25b177 proxmox-chroot-pico
Further, the dependency tree goes from 40 to 29 dependencies, as well as
the package compile time on my machine (on hot caches), roughly measured
with
`cargo clean && time cargo build --package proxmox-chroot --release`
from ~20s to ~16s, so a nice little change w.r.t. to that aspect too.
No functional changes intended.
Signed-off-by: Christoph Heiss <c.heiss@proxmox.com>
---
proxmox-chroot/Cargo.toml | 6 +-
proxmox-chroot/src/main.rs | 159 +++++++++++++++++++++++++++----------
2 files changed, 120 insertions(+), 45 deletions(-)
diff --git a/proxmox-chroot/Cargo.toml b/proxmox-chroot/Cargo.toml
index 7a1390a..c043938 100644
--- a/proxmox-chroot/Cargo.toml
+++ b/proxmox-chroot/Cargo.toml
@@ -9,8 +9,6 @@ homepage = "https://www.proxmox.com"
[dependencies]
anyhow.workspace = true
-proxmox-installer-common.workspace = true
-serde_json.workspace = true
regex.workspace = true
-
-clap = { version = "4.0", features = ["derive"] }
+proxmox-installer-common = { workspace = true, features = [ "cli" ] }
+serde_json.workspace = true
diff --git a/proxmox-chroot/src/main.rs b/proxmox-chroot/src/main.rs
index ef339ed..037f079 100644
--- a/proxmox-chroot/src/main.rs
+++ b/proxmox-chroot/src/main.rs
@@ -1,13 +1,20 @@
+//! Tool to help prepare a successfully installed target environment for
+//! chroot'ing.
+//!
+//! Can also be used in the rescue environment for mounting an existing system.
+
+#![forbid(unsafe_code)]
+
use std::{
- fs, io,
+ env, fs, io,
path::{self, Path, PathBuf},
- process::Command,
+ process::{self, Command},
+ str::FromStr,
};
use anyhow::{Result, bail};
-use clap::{Args, Parser, Subcommand, ValueEnum};
use proxmox_installer_common::{
- RUNTIME_DIR,
+ RUNTIME_DIR, cli,
options::FsType,
setup::{InstallConfig, SetupInfo},
};
@@ -18,46 +25,87 @@ static BINDMOUNTS: [&str; 4] = ["dev", "proc", "run", "sys"];
const TARGET_DIR: &str = "/target";
const ZPOOL_NAME: &str = "rpool";
-/// Helper tool to prepare everything to `chroot` into an installation
-#[derive(Parser, Debug)]
-#[command(author, version, about, long_about = None)]
-struct Cli {
- #[command(subcommand)]
- command: Commands,
-}
-
-#[derive(Subcommand, Debug)]
-enum Commands {
- Prepare(CommandPrepare),
- Cleanup(CommandCleanup),
-}
-
-/// Mount the root file system and bind mounts in preparation to chroot into the installation
-#[derive(Args, Debug)]
-struct CommandPrepare {
+/// Arguments for the `prepare` command.
+struct CommandPrepareArgs {
/// Filesystem used for the installation. Will try to automatically detect it after a
/// successful installation.
- #[arg(short, long, value_enum)]
filesystem: Option<Filesystems>,
- /// Numerical ID of `rpool` ZFS pool to import. Needed if multiple pools of name `rpool` are present.
- #[arg(long)]
+ /// Numerical ID of the `rpool` ZFS pool to import. Needed if multiple pools of name `rpool`
+ /// are present.
rpool_id: Option<u64>,
/// UUID of the BTRFS file system to mount. Needed if multiple BTRFS file systems are present.
- #[arg(long)]
btrfs_uuid: Option<String>,
}
-/// Unmount everything. Use once done with chroot.
-#[derive(Args, Debug)]
-struct CommandCleanup {
+impl cli::Subcommand for CommandPrepareArgs {
+ fn parse(args: &mut cli::Arguments) -> Result<Self> {
+ Ok(Self {
+ filesystem: args.opt_value_from_str(["-f", "--filesystem"])?,
+ rpool_id: args.opt_value_from_fn("--rpool-id", str::parse)?,
+ btrfs_uuid: args.opt_value_from_str("--btrfs-uuid")?,
+ })
+ }
+
+ fn print_usage() {
+ eprintln!(
+ r#"Mount the root file system and bind mounts in preparation to chroot into the installation.
+
+USAGE:
+ {} prepare <OPTIONS>
+
+OPTIONS:
+ -f, --filesystem <FILESYSTEM> Filesystem used for the installation. Will try to automatically detect it after a successful installation. [possible values: zfs, ext4, xfs, btrfs]
+ --rpool-id <RPOOL_ID> Numerical ID of `rpool` ZFS pool to import. Needed if multiple pools of name `rpool` are present.
+ --btrfs-uuid <BTRFS_UUID> UUID of the BTRFS file system to mount. Needed if multiple BTRFS file systems are present.
+ -h, --help Print this help
+ -V, --version Print version
+"#,
+ env!("CARGO_PKG_NAME")
+ );
+ }
+
+ fn run(&self) -> Result<()> {
+ prepare(self)
+ }
+}
+
+/// Arguments for the `cleanup` command.
+struct CommandCleanupArgs {
/// Filesystem used for the installation. Will try to automatically detect it by default.
- #[arg(short, long, value_enum)]
filesystem: Option<Filesystems>,
}
-#[derive(Copy, Clone, Debug, ValueEnum)]
+impl cli::Subcommand for CommandCleanupArgs {
+ fn parse(args: &mut cli::Arguments) -> Result<Self> {
+ Ok(Self {
+ filesystem: args.opt_value_from_str(["-f", "--filesystem"])?,
+ })
+ }
+
+ fn print_usage() {
+ eprintln!(
+ r#"Unmount everything. Use once done with the chroot.
+
+USAGE:
+ {} cleanup <OPTIONS>
+
+OPTIONS:
+ -f, --filesystem <FILESYSTEM> Filesystem used for the installation. Will try to automatically detect it after a successful installation. [possible values: zfs, ext4, xfs, btrfs]
+ -h, --help Print this help
+ -V, --version Print version
+"#,
+ env!("CARGO_PKG_NAME")
+ );
+ }
+
+ fn run(&self) -> Result<()> {
+ cleanup(self)
+ }
+}
+
+#[derive(Copy, Clone, Debug)]
enum Filesystems {
Zfs,
Ext4,
@@ -76,19 +124,48 @@ impl From<FsType> for Filesystems {
}
}
-fn main() {
- let args = Cli::parse();
- let res = match &args.command {
- Commands::Prepare(args) => prepare(args),
- Commands::Cleanup(args) => cleanup(args),
- };
- if let Err(err) = res {
- eprintln!("{err:#}");
- std::process::exit(1);
+impl FromStr for Filesystems {
+ type Err = anyhow::Error;
+
+ fn from_str(s: &str) -> Result<Self> {
+ match s {
+ "ext4" => Ok(Filesystems::Ext4),
+ "xfs" => Ok(Filesystems::Xfs),
+ _ if s.starts_with("zfs") => Ok(Filesystems::Zfs),
+ _ if s.starts_with("btrfs") => Ok(Filesystems::Btrfs),
+ _ => bail!("unknown filesystem"),
+ }
}
}
-fn prepare(args: &CommandPrepare) -> Result<()> {
+fn main() -> process::ExitCode {
+ cli::run(cli::AppInfo {
+ global_help: &format!(
+ r#"Helper tool to set up a `chroot` into an existing installation.
+
+USAGE:
+ {} <COMMAND> <OPTIONS>
+
+COMMANDS:
+ prepare Mount the root file system and bind mounts in preparation to chroot into the installation.
+ cleanup Unmount everything. Use once done with the chroot.
+
+GLOBAL OPTIONS:
+ -h, --help Print help
+ -V, --version Print version information
+"#,
+ env!("CARGO_PKG_NAME")
+ ),
+ on_command: |s, args| match s {
+ Some("prepare") => cli::handle_command::<CommandPrepareArgs>(args),
+ Some("cleanup") => cli::handle_command::<CommandCleanupArgs>(args),
+ Some(s) => bail!("unknown subcommand '{s}'"),
+ None => bail!("subcommand required"),
+ },
+ })
+}
+
+fn prepare(args: &CommandPrepareArgs) -> Result<()> {
let fs = get_fs(args.filesystem)?;
fs::create_dir_all(TARGET_DIR)?;
@@ -108,7 +185,7 @@ fn prepare(args: &CommandPrepare) -> Result<()> {
Ok(())
}
-fn cleanup(args: &CommandCleanup) -> Result<()> {
+fn cleanup(args: &CommandCleanupArgs) -> Result<()> {
let fs = get_fs(args.filesystem)?;
if let Err(e) = bind_umount() {
--
2.49.0
_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel
next prev parent reply other threads:[~2025-05-09 12:11 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-05-09 12:09 [pve-devel] [PATCH installer 0/5] chroot, assistant: replace clap with pico-args Christoph Heiss
2025-05-09 12:09 ` [pve-devel] [PATCH installer 1/5] common: introduce simple cli subcommand parser based on pico-args Christoph Heiss
2025-05-09 12:09 ` Christoph Heiss [this message]
2025-05-09 12:09 ` [pve-devel] [PATCH installer 3/5] assistant: replace clap with pico-args for command argument parsing Christoph Heiss
2025-05-09 12:09 ` [pve-devel] [PATCH installer 4/5] chroot: replace btrfs parsing regex with lsblk json parsing Christoph Heiss
2025-05-09 12:09 ` [pve-devel] [PATCH installer 5/5] tui: drop unused dependencies from manifest Christoph Heiss
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20250509121007.1430080-3-c.heiss@proxmox.com \
--to=c.heiss@proxmox.com \
--cc=pve-devel@lists.proxmox.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.
Service provided by Proxmox Server Solutions GmbH | Privacy | Legal