cli: Polish the `rad sync status` output
This commit is contained in:
parent
b64fc22c18
commit
dfe0cb4342
|
|
@ -13,13 +13,13 @@ It isn't aware of the updates to the repo.
|
||||||
|
|
||||||
```
|
```
|
||||||
$ rad sync status
|
$ rad sync status
|
||||||
╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
|
╭──────────────────────────────────────────────────────────────────────────────────────────╮
|
||||||
│ ● NID Address Status At Timestamp │
|
│ ● NID Alias Address Status At Timestamp │
|
||||||
├───────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
|
├──────────────────────────────────────────────────────────────────────────────────────────┤
|
||||||
│ ● z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi alice.radicle.xyz:8776 out-of-sync f209c9f [ ... ] │
|
│ ● z6MknSL…StBU8Vi alice alice.radicle.xyz:8776 out-of-sync f209c9f [ ... ] │
|
||||||
│ ● z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk bob.radicle.xyz:8776 out-of-sync f209c9f [ ... ] │
|
│ ● z6Mkt67…v4N1tRk bob bob.radicle.xyz:8776 out-of-sync f209c9f [ ... ] │
|
||||||
│ ● z6Mkux1aUQD2voWWukVb5nNUR7thrHveQG4pDQua8nVhib7Z eve.radicle.xyz:8776 out-of-sync f209c9f [ ... ] │
|
│ ● z6Mkux1…nVhib7Z eve eve.radicle.xyz:8776 out-of-sync f209c9f [ ... ] │
|
||||||
╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
|
╰──────────────────────────────────────────────────────────────────────────────────────────╯
|
||||||
```
|
```
|
||||||
|
|
||||||
Now let's run `rad sync`. This will announce the issue refs to the network and
|
Now let's run `rad sync`. This will announce the issue refs to the network and
|
||||||
|
|
@ -77,11 +77,11 @@ We can check the sync status again to make sure everything's in sync:
|
||||||
|
|
||||||
```
|
```
|
||||||
$ rad sync status
|
$ rad sync status
|
||||||
╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
|
╭─────────────────────────────────────────────────────────────────────────────────────╮
|
||||||
│ ● NID Address Status At Timestamp │
|
│ ● NID Alias Address Status At Timestamp │
|
||||||
├──────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
|
├─────────────────────────────────────────────────────────────────────────────────────┤
|
||||||
│ ● z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi alice.radicle.xyz:8776 synced 9f615f9 [ ... ] │
|
│ ● z6MknSL…StBU8Vi alice alice.radicle.xyz:8776 synced 9f615f9 [ ... ] │
|
||||||
│ ● z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk bob.radicle.xyz:8776 synced 9f615f9 [ ... ] │
|
│ ● z6Mkt67…v4N1tRk bob bob.radicle.xyz:8776 synced 9f615f9 [ ... ] │
|
||||||
│ ● z6Mkux1aUQD2voWWukVb5nNUR7thrHveQG4pDQua8nVhib7Z eve.radicle.xyz:8776 synced 9f615f9 [ ... ] │
|
│ ● z6Mkux1…nVhib7Z eve eve.radicle.xyz:8776 synced 9f615f9 [ ... ] │
|
||||||
╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
|
╰─────────────────────────────────────────────────────────────────────────────────────╯
|
||||||
```
|
```
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ use std::time;
|
||||||
use anyhow::{anyhow, Context as _};
|
use anyhow::{anyhow, Context as _};
|
||||||
|
|
||||||
use radicle::node;
|
use radicle::node;
|
||||||
|
use radicle::node::AliasStore as _;
|
||||||
use radicle::node::{FetchResult, FetchResults, Handle as _, Node, SyncStatus};
|
use radicle::node::{FetchResult, FetchResults, Handle as _, Node, SyncStatus};
|
||||||
use radicle::prelude::{Id, NodeId, Profile};
|
use radicle::prelude::{Id, NodeId, Profile};
|
||||||
use radicle::storage::{ReadRepository, ReadStorage};
|
use radicle::storage::{ReadRepository, ReadStorage};
|
||||||
|
|
@ -243,7 +244,7 @@ pub fn run(options: Options, ctx: impl term::Context) -> anyhow::Result<()> {
|
||||||
|
|
||||||
match options.op {
|
match options.op {
|
||||||
Operation::Status => {
|
Operation::Status => {
|
||||||
sync_status(rid, &mut node)?;
|
sync_status(rid, &mut node, &profile, &options)?;
|
||||||
}
|
}
|
||||||
Operation::Synchronize(SyncMode::Repo { mode, direction }) => {
|
Operation::Synchronize(SyncMode::Repo { mode, direction }) => {
|
||||||
if [SyncDirection::Fetch, SyncDirection::Both].contains(&direction) {
|
if [SyncDirection::Fetch, SyncDirection::Both].contains(&direction) {
|
||||||
|
|
@ -271,14 +272,21 @@ pub fn run(options: Options, ctx: impl term::Context) -> anyhow::Result<()> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sync_status(rid: Id, node: &mut Node) -> anyhow::Result<()> {
|
fn sync_status(
|
||||||
let mut table = Table::<6, term::Label>::new(TableOptions::bordered());
|
rid: Id,
|
||||||
|
node: &mut Node,
|
||||||
|
profile: &Profile,
|
||||||
|
options: &Options,
|
||||||
|
) -> anyhow::Result<()> {
|
||||||
|
let mut table = Table::<7, term::Label>::new(TableOptions::bordered());
|
||||||
let mut seeds: Vec<_> = node.seeds(rid)?.into();
|
let mut seeds: Vec<_> = node.seeds(rid)?.into();
|
||||||
let local = node.nid()?;
|
let local = node.nid()?;
|
||||||
|
let aliases = profile.aliases();
|
||||||
|
|
||||||
table.push([
|
table.push([
|
||||||
term::format::dim(String::from("●")).into(),
|
term::format::dim(String::from("●")).into(),
|
||||||
term::format::bold(String::from("NID")).into(),
|
term::format::bold(String::from("NID")).into(),
|
||||||
|
term::format::bold(String::from("Alias")).into(),
|
||||||
term::format::bold(String::from("Address")).into(),
|
term::format::bold(String::from("Address")).into(),
|
||||||
term::format::bold(String::from("Status")).into(),
|
term::format::bold(String::from("Status")).into(),
|
||||||
term::format::bold(String::from("At")).into(),
|
term::format::bold(String::from("At")).into(),
|
||||||
|
|
@ -287,34 +295,43 @@ fn sync_status(rid: Id, node: &mut Node) -> anyhow::Result<()> {
|
||||||
table.divider();
|
table.divider();
|
||||||
|
|
||||||
// Always show our local node first.
|
// Always show our local node first.
|
||||||
seeds.sort_by(|a, _| {
|
seeds.sort_by(|a, b| {
|
||||||
if a.nid == local {
|
if a.nid == local {
|
||||||
Ordering::Less
|
Ordering::Less
|
||||||
|
} else if b.nid == local {
|
||||||
|
Ordering::Greater
|
||||||
} else {
|
} else {
|
||||||
Ordering::Equal
|
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))
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
for seed in seeds {
|
for seed in seeds {
|
||||||
let (icon, status, refs, time) = match seed.sync {
|
let (icon, status, head, time) = match seed.sync {
|
||||||
Some(SyncStatus::Synced { at }) => (
|
Some(SyncStatus::Synced { at }) => (
|
||||||
term::format::positive("●"),
|
term::format::positive("●"),
|
||||||
term::format::positive("synced"),
|
term::format::positive("synced"),
|
||||||
term::label(term::format::oid(at.oid)),
|
term::format::oid(at.oid),
|
||||||
term::format::timestamp(at.timestamp).into(),
|
term::format::timestamp(at.timestamp),
|
||||||
),
|
),
|
||||||
Some(SyncStatus::OutOfSync { remote, .. }) => (
|
Some(SyncStatus::OutOfSync { remote, .. }) => (
|
||||||
term::format::negative("●"),
|
term::format::negative("●"),
|
||||||
term::format::negative("out-of-sync"),
|
term::format::negative("out-of-sync"),
|
||||||
term::label(term::format::oid(remote.oid)),
|
term::format::oid(remote.oid),
|
||||||
term::format::timestamp(remote.timestamp).into(),
|
term::format::timestamp(remote.timestamp),
|
||||||
),
|
),
|
||||||
None => (
|
None if options.verbose => (
|
||||||
term::format::yellow("●"),
|
term::format::dim("●"),
|
||||||
term::format::yellow("?"),
|
term::format::dim("unknown"),
|
||||||
term::label("?"),
|
term::paint(String::new()),
|
||||||
term::label("?"),
|
term::paint(String::new()),
|
||||||
),
|
),
|
||||||
|
None => continue,
|
||||||
};
|
};
|
||||||
let addr = seed
|
let addr = seed
|
||||||
.addrs
|
.addrs
|
||||||
|
|
@ -322,14 +339,19 @@ fn sync_status(rid: Id, node: &mut Node) -> anyhow::Result<()> {
|
||||||
.map(|a| a.addr.to_string())
|
.map(|a| a.addr.to_string())
|
||||||
.unwrap_or_default()
|
.unwrap_or_default()
|
||||||
.into();
|
.into();
|
||||||
|
let alias = aliases
|
||||||
|
.alias(&seed.nid)
|
||||||
|
.map(|a| a.to_string())
|
||||||
|
.unwrap_or_default();
|
||||||
|
|
||||||
table.push([
|
table.push([
|
||||||
icon.into(),
|
icon.into(),
|
||||||
seed.nid.to_human().into(),
|
term::format::primary(term::format::node(&seed.nid)).into(),
|
||||||
|
term::format::primary(alias).dim().into(),
|
||||||
addr,
|
addr,
|
||||||
status.into(),
|
status.into(),
|
||||||
refs,
|
term::format::secondary(head).into(),
|
||||||
time,
|
time.dim().italic().into(),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
table.print();
|
table.print();
|
||||||
|
|
|
||||||
|
|
@ -147,6 +147,25 @@ pub enum SyncStatus {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Ord for SyncStatus {
|
||||||
|
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
|
||||||
|
match (self, other) {
|
||||||
|
(Self::Synced { at: left }, Self::Synced { at: right }) => left.cmp(right),
|
||||||
|
(Self::Synced { at }, Self::OutOfSync { remote, .. }) => at.cmp(remote),
|
||||||
|
(Self::OutOfSync { remote, .. }, Self::Synced { at }) => remote.cmp(at),
|
||||||
|
(Self::OutOfSync { remote: left, .. }, Self::OutOfSync { remote: right, .. }) => {
|
||||||
|
left.cmp(right)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PartialOrd for SyncStatus {
|
||||||
|
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
|
||||||
|
Some(self.cmp(other))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Node alias.
|
/// Node alias.
|
||||||
#[derive(Debug, PartialEq, Eq, Clone, serde::Serialize, serde::Deserialize)]
|
#[derive(Debug, PartialEq, Eq, Clone, serde::Serialize, serde::Deserialize)]
|
||||||
pub struct Alias(String);
|
pub struct Alias(String);
|
||||||
|
|
|
||||||
|
|
@ -213,6 +213,18 @@ impl SyncedAt {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Ord for SyncedAt {
|
||||||
|
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
|
||||||
|
self.timestamp.cmp(&other.timestamp)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PartialOrd for SyncedAt {
|
||||||
|
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
|
||||||
|
Some(self.cmp(other))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Seed of a specific repository.
|
/// Seed of a specific repository.
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
|
#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue