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:
parent
2917198d1c
commit
53013f306f
|
|
@ -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 │
|
||||
╰───────────────────────────────────────────────────────────────────────────────────────────────────────────╯
|
||||
```
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
```
|
||||
|
|
|
|||
|
|
@ -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,12 +81,46 @@ 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(());
|
||||
}
|
||||
|
||||
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();
|
||||
|
||||
rows.push([
|
||||
term::format::bold(proj.name().to_owned()),
|
||||
term::format::tertiary(rid.urn()),
|
||||
term::format::visibility(&doc.visibility).into(),
|
||||
term::format::secondary(head),
|
||||
term::format::italic(proj.description().to_owned()),
|
||||
]);
|
||||
}
|
||||
rows.sort();
|
||||
|
||||
if rows.is_empty() {
|
||||
term::print(term::format::italic("Nothing to show."));
|
||||
} else {
|
||||
table.push([
|
||||
"Name".into(),
|
||||
"RID".into(),
|
||||
|
|
@ -85,26 +129,9 @@ pub fn run(options: Options, ctx: impl term::Context) -> anyhow::Result<()> {
|
|||
"Description".into(),
|
||||
]);
|
||||
table.divider();
|
||||
|
||||
for RepositoryInfo { rid, head, doc } in repos {
|
||||
if doc.visibility.is_public() && options.private && !options.public {
|
||||
continue;
|
||||
}
|
||||
if !doc.visibility.is_public() && !options.private && options.public {
|
||||
continue;
|
||||
}
|
||||
let proj = doc.project()?;
|
||||
let head = term::format::oid(head).into();
|
||||
|
||||
table.push([
|
||||
term::format::bold(proj.name().to_owned()),
|
||||
term::format::tertiary(rid.urn()),
|
||||
term::format::visibility(&doc.visibility).into(),
|
||||
term::format::secondary(head),
|
||||
term::format::italic(proj.description().to_owned()),
|
||||
]);
|
||||
}
|
||||
table.extend(rows);
|
||||
table.print();
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue