Skip to main content

radicle_cli/commands/
ls.rs

1mod args;
2
3pub use args::Args;
4
5use radicle::storage::{ReadStorage, RepositoryInfo};
6
7use crate::terminal as term;
8
9use term::Element;
10
11pub fn run(args: Args, ctx: impl term::Context) -> anyhow::Result<()> {
12    let profile = ctx.profile()?;
13    let storage = &profile.storage;
14    let repos = storage.repositories()?;
15    let policy = profile.policies()?;
16    let mut table = term::Table::new(term::TableOptions::bordered());
17    let mut rows = Vec::new();
18
19    if repos.is_empty() {
20        return Ok(());
21    }
22
23    for RepositoryInfo {
24        rid,
25        head,
26        doc,
27        refs,
28        ..
29    } in repos
30    {
31        let refs = match refs {
32            Ok(refs) => refs,
33            Err(_) => {
34                term::warning(format!("Repository {rid} must be migrated by starting your node (e.g. via `rad node start`)."));
35                continue;
36            }
37        };
38
39        if doc.is_public() && args.private {
40            continue;
41        }
42        if !doc.is_public() && args.public {
43            continue;
44        }
45        if refs.is_none() && !args.all && !args.seeded {
46            continue;
47        }
48        let seeded = policy.is_seeding(&rid)?;
49
50        if !seeded && !args.all {
51            continue;
52        }
53        if !seeded && args.seeded {
54            continue;
55        }
56        let proj = match doc.project() {
57            Ok(p) => p,
58            Err(e) => {
59                log::error!(target: "cli", "Error loading project payload for {rid}: {e}");
60                continue;
61            }
62        };
63        let head = term::format::oid(head).into();
64
65        rows.push([
66            term::format::bold(proj.name().to_owned()),
67            term::format::tertiary(rid.urn()),
68            if seeded {
69                term::format::visibility(doc.visibility()).into()
70            } else {
71                term::format::dim("local").into()
72            },
73            term::format::secondary(head),
74            term::format::italic(proj.description().to_owned()),
75        ]);
76    }
77    rows.sort();
78
79    if rows.is_empty() {
80        term::print(term::format::italic("Nothing to show."));
81    } else {
82        table.header([
83            "Name".into(),
84            "RID".into(),
85            "Visibility".into(),
86            "Head".into(),
87            "Description".into(),
88        ]);
89        table.divider();
90        table.extend(rows);
91        table.print();
92    }
93
94    Ok(())
95}