Radish alpha
h
rad:z3gqcJUoA1n9HaHKufZs5FCSGazv5
Radicle Heartwood Protocol & Stack
Radicle
Git
Use humantime to parse timeouts
Merged did:key:z6MkoohH...AjJf opened 1 month ago

In issue

29c6c6fc8171287faa0079798ba2d6e3e7fd86f3

was noted that it would be nice to use value parsers for the timeouts in the CLI.

This patch implements this.

9 files changed +48 -31 52e55812 99d92421
modified Cargo.lock
@@ -181,7 +181,7 @@ checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d"
dependencies = [
 "anstyle",
 "once_cell_polyfill",
-
 "windows-sys 0.60.2",
+
 "windows-sys 0.61.2",
]

[[package]]
@@ -1855,6 +1855,12 @@ dependencies = [
]

[[package]]
+
name = "humantime"
+
version = "2.3.0"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "135b12329e5e3ce057a9f972339ea52bc954fe1e9358ef27f95e89716fbc5424"
+

+
[[package]]
name = "iana-time-zone"
version = "0.1.60"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2111,7 +2117,7 @@ dependencies = [
 "portable-atomic",
 "portable-atomic-util",
 "serde_core",
-
 "windows-sys 0.60.2",
+
 "windows-sys 0.61.2",
]

[[package]]
@@ -2426,7 +2432,7 @@ version = "0.50.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5"
dependencies = [
-
 "windows-sys 0.59.0",
+
 "windows-sys 0.61.2",
]

[[package]]
@@ -2939,6 +2945,7 @@ dependencies = [
 "clap_complete",
 "dunce",
 "human-panic",
+
 "humantime",
 "itertools",
 "log",
 "nonempty",
@@ -3513,7 +3520,7 @@ dependencies = [
 "errno",
 "libc",
 "linux-raw-sys 0.11.0",
-
 "windows-sys 0.60.2",
+
 "windows-sys 0.61.2",
]

[[package]]
@@ -4197,7 +4204,7 @@ dependencies = [
 "getrandom 0.3.3",
 "once_cell",
 "rustix 1.1.3",
-
 "windows-sys 0.60.2",
+
 "windows-sys 0.61.2",
]

[[package]]
modified Cargo.toml
@@ -33,6 +33,7 @@ git2 = { version = "0.20.4", default-features = false, features = ["vendored-lib
gix-hash = { version = "0.22.1", default-features = false, features = ["sha1"] }
gix-packetline = { version = "0.21.1", default-features = false }
human-panic = "2.0.6"
+
humantime = "2.3"
itertools = "0.14"
lexopt = "0.3.0"
libc = "0.2.137"
modified crates/radicle-cli/Cargo.toml
@@ -20,6 +20,7 @@ clap = { version = "4.5.44", features = ["derive"] }
clap_complete = "4.5"
dunce = { workspace = true }
human-panic.workspace = true
+
humantime.workspace = true
itertools.workspace = true
log = { workspace = true, features = ["std"] }
nonempty = { workspace = true }
modified crates/radicle-cli/src/commands/clone/args.rs
@@ -1,5 +1,4 @@
use std::path::PathBuf;
-
use std::time;

use clap::Parser;

@@ -31,15 +30,17 @@ pub(super) struct SyncArgs {
    #[arg(short, long = "seed", value_name = "NID", action = clap::ArgAction::Append)]
    seeds: Vec<NodeId>,

-
    /// Timeout for fetching repository in seconds
-
    #[arg(long, default_value_t = 9, value_name = "SECS")]
-
    timeout: usize,
+
    /// Timeout for fetching repository
+
    ///
+
    /// Valid arguments are for example "10s", "5min" or "2h 37min"
+
    #[arg(long, value_parser = humantime::parse_duration, default_value = "9s")]
+
    timeout: std::time::Duration,
}

impl From<SyncArgs> for SyncSettings {
    fn from(args: SyncArgs) -> Self {
        SyncSettings {
-
            timeout: time::Duration::from_secs(args.timeout as u64),
+
            timeout: args.timeout,
            seeds: args.seeds.into_iter().collect(),
            ..SyncSettings::default()
        }
modified crates/radicle-cli/src/commands/node.rs
@@ -29,9 +29,7 @@ pub fn run(args: Args, ctx: impl term::Context) -> anyhow::Result<()> {

    match command {
        Command::Connect { addr, timeout } => {
-
            let timeout = timeout
-
                .map(time::Duration::from_secs)
-
                .unwrap_or(time::Duration::MAX);
+
            let timeout = timeout.unwrap_or(time::Duration::MAX);
            match addr {
                Addr::Peer(addr) => control::connect(&mut node, addr.id, addr.addr, timeout)?,
                Addr::Node(nid) => {
@@ -70,9 +68,7 @@ pub fn run(args: Args, ctx: impl term::Context) -> anyhow::Result<()> {
        }
        Command::Events { timeout, count } => {
            let count = count.unwrap_or(usize::MAX);
-
            let timeout = timeout
-
                .map(time::Duration::from_secs)
-
                .unwrap_or(time::Duration::MAX);
+
            let timeout = timeout.unwrap_or(time::Duration::MAX);

            events::run(node, count, timeout)?;
        }
modified crates/radicle-cli/src/commands/node/args.rs
@@ -105,8 +105,10 @@ pub(super) enum Command {
        addr: Addr,

        /// How long to wait for the connection to be established
-
        #[arg(long, value_name = "SECS")]
-
        timeout: Option<u64>,
+
        ///
+
        /// Valid arguments are for example "10s", "5min" or "2h 37min"
+
        #[arg(long, value_parser = humantime::parse_duration)]
+
        timeout: Option<std::time::Duration>,
    },

    /// Show the config
@@ -128,8 +130,10 @@ pub(super) enum Command {
    /// If no timeout or count is specified, it will run indefinitely.
    Events {
        /// How long to wait to receive an event before giving up
-
        #[arg(long, value_name = "SECS")]
-
        timeout: Option<u64>,
+
        ///
+
        /// Valid arguments are for example "10s", "5min" or "2h 37min"
+
        #[arg(long, value_parser = humantime::parse_duration)]
+
        timeout: Option<std::time::Duration>,

        /// Exit after <COUNT> events
        #[arg(long, short = 'n')]
modified crates/radicle-cli/src/commands/seed/args.rs
@@ -43,8 +43,10 @@ pub struct Args {
    pub(super) from: Vec<NodeId>,

    /// Fetch timeout in seconds
-
    #[arg(long, short, value_name = "SECS", default_value_t = 9)]
-
    timeout: u64,
+
    ///
+
    /// Valid arguments are for example "10s", "5min" or "2h 37min"
+
    #[arg(long, short, value_parser = humantime::parse_duration, default_value = "9s")]
+
    timeout: std::time::Duration,

    /// Peer follow scope for this repository
    #[arg(
@@ -90,7 +92,7 @@ impl From<Args> for Operation {

impl Args {
    fn timeout(&self) -> time::Duration {
-
        time::Duration::from_secs(self.timeout)
+
        self.timeout
    }

    fn should_fetch(&self) -> bool {
modified crates/radicle-cli/src/commands/sync/args.rs
@@ -89,15 +89,17 @@ pub(super) struct SyncArgs {
    )]
    seeds: Vec<NodeId>,

-
    /// How many seconds to wait while synchronizing
+
    /// How long to wait while synchronizing
+
    ///
+
    /// Valid arguments are for example "10s", "5min" or "2h 37min"
    #[arg(
        long,
        short,
-
        default_value_t = 9,
-
        value_name = "SECS",
+
        default_value = "9s",
+
        value_parser = humantime::parse_duration,
        conflicts_with = "inventory"
    )]
-
    timeout: u64,
+
    timeout: std::time::Duration,

    /// The repository to perform the synchronizing for [default: cwd]
    rid: Option<RepoId>,
@@ -146,7 +148,7 @@ impl SyncArgs {
    }

    fn timeout(&self) -> time::Duration {
-
        time::Duration::from_secs(self.timeout)
+
        self.timeout
    }

    fn replication(&self) -> sync::ReplicationFactor {
modified crates/radicle-cli/src/commands/watch/args.rs
@@ -43,8 +43,10 @@ pub struct Args {
    interval: u64,

    /// Timeout, in milliseconds
-
    #[arg(long, value_name = "MILLIS")]
-
    timeout: Option<u64>,
+
    ///
+
    /// Valid arguments are for example "10s", "5min" or "2h 37min"
+
    #[arg(long, value_parser = humantime::parse_duration)]
+
    timeout: Option<std::time::Duration>,
}

impl Args {
@@ -55,7 +57,8 @@ impl Args {

    /// Provide the timeout duration in milliseconds.
    pub(super) fn timeout(&self) -> time::Duration {
-
        time::Duration::from_millis(self.timeout.unwrap_or(u64::MAX))
+
        self.timeout
+
            .unwrap_or_else(|| time::Duration::from_millis(u64::MAX))
    }
}