cli: Improve `rad ls`

Distinguish between repos that are simply tracked, vs. repos that are
cloned (and thus forked). By default, we don't show repos that don't
have a local fork.
This commit is contained in:
cloudhead 2023-11-23 13:49:40 +01:00
parent 2917198d1c
commit 53013f306f
No known key found for this signature in database
5 changed files with 76 additions and 15 deletions

View File

@ -58,3 +58,13 @@ Date: Mon Jan 1 14:39:16 2018 +0000
Second commit
```
Cloned repositories show up in `rad ls`:
```
$ rad ls
╭───────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ Name RID Visibility Head Description │
├───────────────────────────────────────────────────────────────────────────────────────────────────────────┤
│ heartwood rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji public f2de534 Radicle Heartwood Protocol & Stack │
╰───────────────────────────────────────────────────────────────────────────────────────────────────────────╯
```

View File

@ -1,5 +1,5 @@
Given a private repo `rad:z2ug5mwNKZB8KGpBDRTrWHAMbvHCu` belonging to Alice,
Bob tries to clone it, and even though he's connected to Alice, it fails.
Bob tries to fetch it, and even though he's connected to Alice, it fails.
``` ~bob
$ rad track rad:z2ug5mwNKZB8KGpBDRTrWHAMbvHCu
@ -28,10 +28,17 @@ Bob can now fetch the private repo:
$ rad sync rad:z2ug5mwNKZB8KGpBDRTrWHAMbvHCu --fetch
✓ Fetching rad:z2ug5mwNKZB8KGpBDRTrWHAMbvHCu from z6MknSL…StBU8Vi..
✓ Fetched repository from 1 seed(s)
$ rad ls --private
$ rad ls --private --all
╭───────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ Name RID Visibility Head Description │
├───────────────────────────────────────────────────────────────────────────────────────────────────────────┤
│ heartwood rad:z2ug5mwNKZB8KGpBDRTrWHAMbvHCu private f2de534 radicle heartwood protocol & stack │
╰───────────────────────────────────────────────────────────────────────────────────────────────────────────╯
```
Note that since we don't have our own fork of this repo, omitting the `--all` flag shows nothing:
``` ~bob
$ rad ls --private
Nothing to show.
```

View File

@ -16,10 +16,14 @@ Usage
rad ls [<option>...]
By default, this command shows you all repositories that you have forked or initialized.
If you wish to see all tracked repositories, use the `--all` option.
Options
--private Show only private repositories
--public Show only public repositories
--all Show all repositories in storage
--verbose, -v Verbose output
--help Print help
"#,
@ -30,6 +34,7 @@ pub struct Options {
verbose: bool,
public: bool,
private: bool,
all: bool,
}
impl Args for Options {
@ -40,12 +45,16 @@ impl Args for Options {
let mut verbose = false;
let mut private = false;
let mut public = false;
let mut all = false;
while let Some(arg) = parser.next()? {
match arg {
Long("help") | Short('h') => {
return Err(Error::Help.into());
}
Long("all") => {
all = true;
}
Long("private") => {
private = true;
}
@ -62,6 +71,7 @@ impl Args for Options {
verbose,
private,
public,
all,
},
vec![],
))
@ -71,32 +81,34 @@ impl Args for Options {
pub fn run(options: Options, ctx: impl term::Context) -> anyhow::Result<()> {
let profile = ctx.profile()?;
let storage = &profile.storage;
let mut table = term::Table::new(term::TableOptions::bordered());
let repos = storage.repositories()?;
let mut table = term::Table::new(term::TableOptions::bordered());
let mut rows = Vec::new();
if repos.is_empty() {
return Ok(());
}
table.push([
"Name".into(),
"RID".into(),
"Visibility".into(),
"Head".into(),
"Description".into(),
]);
table.divider();
for RepositoryInfo { rid, head, doc } in repos {
for RepositoryInfo {
rid,
head,
doc,
refs,
} in repos
{
if doc.visibility.is_public() && options.private && !options.public {
continue;
}
if !doc.visibility.is_public() && !options.private && options.public {
continue;
}
if refs.is_none() && !options.all {
continue;
}
let proj = doc.project()?;
let head = term::format::oid(head).into();
table.push([
rows.push([
term::format::bold(proj.name().to_owned()),
term::format::tertiary(rid.urn()),
term::format::visibility(&doc.visibility).into(),
@ -104,7 +116,22 @@ pub fn run(options: Options, ctx: impl term::Context) -> anyhow::Result<()> {
term::format::italic(proj.description().to_owned()),
]);
}
table.print();
rows.sort();
if rows.is_empty() {
term::print(term::format::italic("Nothing to show."));
} else {
table.push([
"Name".into(),
"RID".into(),
"Visibility".into(),
"Head".into(),
"Description".into(),
]);
table.divider();
table.extend(rows);
table.print();
}
Ok(())
}

View File

@ -178,6 +178,12 @@ impl<const W: usize, T: Cell> Table<W, T> {
self.rows.push(Row::Data(row));
}
pub fn extend(&mut self, rows: impl IntoIterator<Item = [T; W]>) {
for row in rows.into_iter() {
self.push(row);
}
}
fn inner(&self, c: Constraint) -> Size {
let mut outer = self.outer(c);

View File

@ -51,6 +51,9 @@ pub struct RepositoryInfo<V> {
pub head: Oid,
/// Identity document.
pub doc: Doc<V>,
/// Local signed refs, if any.
/// Repositories with this set to `None` are ones that are tracked but not forked.
pub refs: Option<refs::SignedRefsAt>,
}
/// A parsed Git reference.
@ -226,7 +229,15 @@ impl Storage {
continue;
}
};
repos.push(RepositoryInfo { rid, head, doc });
// Nb. This will be `None` if they were not found.
let refs = refs::SignedRefsAt::load(self.info.key, &repo)?;
repos.push(RepositoryInfo {
rid,
head,
doc,
refs,
});
}
Ok(repos)
}