Radish alpha
h
Radicle Heartwood Protocol & Stack
Radicle
Git (anonymous pull)
Log in to clone via SSH
cli: sort-by flag for rad sync
Fintan Halpenny committed 2 years ago
commit 72b00e3d41aff7a09679356b0751360b621a2388
parent 9ae7fd702e5901ebbcd6ee346e28d1ace539dda0
3 files changed +73 -28
modified radicle-cli/examples/rad-sync.md
@@ -12,7 +12,7 @@ Our own node is also out of sync, since we used `--no-announce`.
It isn't aware of the updates to the repo.

```
-
$ rad sync status
+
$ rad sync status --sort-by alias
╭──────────────────────────────────────────────────────────────────────────────────────────╮
│ ●   NID               Alias   Address                  Status        At        Timestamp │
├──────────────────────────────────────────────────────────────────────────────────────────┤
@@ -76,7 +76,7 @@ $ rad sync --fetch --replicas 1
We can check the sync status again to make sure everything's in sync:

```
-
$ rad sync status
+
$ rad sync status --sort-by alias
╭─────────────────────────────────────────────────────────────────────────────────────╮
│ ●   NID               Alias   Address                  Status   At        Timestamp │
├─────────────────────────────────────────────────────────────────────────────────────┤
modified radicle-cli/src/commands/sync.rs
@@ -1,11 +1,13 @@
use std::cmp::Ordering;
use std::ffi::OsString;
+
use std::str::FromStr;
use std::time;

use anyhow::{anyhow, Context as _};

use radicle::node;
-
use radicle::node::AliasStore as _;
+
use radicle::node::AliasStore;
+
use radicle::node::Seed;
use radicle::node::{FetchResult, FetchResults, Handle as _, Node, SyncStatus};
use radicle::prelude::{Id, NodeId, Profile};
use radicle::storage::{ReadRepository, ReadStorage};
@@ -51,14 +53,15 @@ Commands

Options

-
    --fetch, -f               Turn on fetching (default: true)
-
    --announce, -a            Turn on ref announcing (default: true)
-
    --inventory, -i           Turn on inventory announcing (default: false)
-
    --timeout <secs>          How many seconds to wait while syncing
-
    --seed <nid>              Sync with the given node (may be specified multiple times)
-
    --replicas, -r <count>    Sync with a specific number of seeds
-
    --verbose, -v             Verbose output
-
    --help                    Print help
+
        --sort-by   <field>   Sort the table by column (options: nid, alias, status)
+
    -f, --fetch               Turn on fetching (default: true)
+
    -a, --announce            Turn on ref announcing (default: true)
+
    -i, --inventory           Turn on inventory announcing (default: false)
+
        --timeout   <secs>    How many seconds to wait while syncing
+
        --seed      <nid>     Sync with the given node (may be specified multiple times)
+
    -r, --replicas  <count>   Sync with a specific number of seeds
+
    -v, --verbose             Verbose output
+
        --help                Print help
"#,
};

@@ -69,6 +72,27 @@ pub enum Operation {
    Status,
}

+
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
+
pub enum SortBy {
+
    Nid,
+
    Alias,
+
    #[default]
+
    Status,
+
}
+

+
impl FromStr for SortBy {
+
    type Err = &'static str;
+

+
    fn from_str(s: &str) -> Result<Self, Self::Err> {
+
        match s {
+
            "nid" => Ok(Self::Nid),
+
            "alias" => Ok(Self::Alias),
+
            "status" => Ok(Self::Status),
+
            _ => Err("invalid `--sort-by` field"),
+
        }
+
    }
+
}
+

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum SyncMode {
    Repo {
@@ -115,6 +139,7 @@ pub struct Options {
    pub rid: Option<Id>,
    pub verbose: bool,
    pub timeout: time::Duration,
+
    pub sort_by: SortBy,
    pub op: Operation,
}

@@ -131,6 +156,7 @@ impl Args for Options {
        let mut inventory = false;
        let mut replicas = None;
        let mut seeds = Vec::new();
+
        let mut sort_by = SortBy::default();
        let mut op: Option<Operation> = None;

        while let Some(arg) = parser.next()? {
@@ -162,6 +188,10 @@ impl Args for Options {
                Long("inventory") | Short('i') => {
                    inventory = true;
                }
+
                Long("sort-by") if matches!(op, Some(Operation::Status)) => {
+
                    let value = parser.value()?;
+
                    sort_by = value.parse()?;
+
                }
                Long("timeout") | Short('t') => {
                    let value = parser.value()?;
                    let secs = term::args::parse_value("timeout", value)?;
@@ -217,6 +247,7 @@ impl Args for Options {
                rid,
                verbose,
                timeout,
+
                sort_by,
                op: op.unwrap_or(Operation::Synchronize(sync)),
            },
            vec![],
@@ -294,22 +325,7 @@ fn sync_status(
    ]);
    table.divider();

-
    // Always show our local node first.
-
    seeds.sort_by(|a, b| {
-
        if a.nid == local {
-
            Ordering::Less
-
        } else if b.nid == local {
-
            Ordering::Greater
-
        } else {
-
            match (&a.sync, &b.sync) {
-
                (Some(_), None) => Ordering::Less,
-
                (None, Some(_)) => Ordering::Greater,
-
                (Some(a), Some(b)) => a.cmp(b).reverse(),
-
                (None, None) => Ordering::Equal,
-
            }
-
            .then(a.nid.cmp(&b.nid))
-
        }
-
    });
+
    sort_seeds_by(local, &mut seeds, &aliases, &options.sort_by);

    for seed in seeds {
        let (icon, status, head, time) = match seed.sync {
@@ -553,3 +569,32 @@ fn fetch_from(
    }
    Ok(result)
}
+

+
fn sort_seeds_by(local: NodeId, seeds: &mut [Seed], aliases: &impl AliasStore, sort_by: &SortBy) {
+
    let compare = |a: &Seed, b: &Seed| match sort_by {
+
        SortBy::Nid => a.nid.cmp(&b.nid),
+
        SortBy::Alias => {
+
            let a = aliases.alias(&a.nid);
+
            let b = aliases.alias(&b.nid);
+
            a.cmp(&b)
+
        }
+
        SortBy::Status => a.sync.cmp(&b.sync),
+
    };
+

+
    // Always show our local node first.
+
    seeds.sort_by(|a, b| {
+
        if a.nid == local {
+
            Ordering::Less
+
        } else if b.nid == local {
+
            Ordering::Greater
+
        } else {
+
            match (&a.sync, &b.sync) {
+
                (Some(_), None) => Ordering::Less,
+
                (None, Some(_)) => Ordering::Greater,
+
                (Some(a), Some(b)) => a.cmp(b).reverse(),
+
                (None, None) => Ordering::Equal,
+
            }
+
            .then(compare(a, b))
+
        }
+
    });
+
}
modified radicle/src/node.rs
@@ -167,7 +167,7 @@ impl PartialOrd for SyncStatus {
}

/// Node alias.
-
#[derive(Debug, PartialEq, Eq, Clone, serde::Serialize, serde::Deserialize)]
+
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, serde::Serialize, serde::Deserialize)]
pub struct Alias(String);

impl Alias {