mod args; pub use args::Args; use radicle::storage::{ReadStorage, RepositoryInfo, SignedRefsInfo}; use crate::terminal as term; use term::Element; pub fn run(args: Args, ctx: impl term::Context) -> anyhow::Result<()> { let profile = ctx.profile()?; let storage = &profile.storage; let repos = storage.repositories()?; let policy = profile.policies()?; 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.is_public() && args.private { continue; } if !doc.is_public() && args.public { continue; } if matches!(refs, SignedRefsInfo::None) && !args.all && !args.seeded { continue; } let seeded = policy.is_seeding(&rid)?; if !seeded && !args.all { continue; } if !seeded && args.seeded { continue; } let proj = match doc.project() { Ok(p) => p, Err(e) => { log::error!(target: "cli", "Error loading project payload for {rid}: {e}"); continue; } }; let head = term::format::oid(head).into(); rows.push([ term::format::bold(proj.name().to_owned()), term::format::tertiary(rid.urn()), if seeded { term::format::visibility(doc.visibility()).into() } else { term::format::dim("local").into() }, term::format::secondary(head), term::format::italic(proj.description().to_owned()), ]); } rows.sort(); if rows.is_empty() { term::println(term::format::italic("Nothing to show.")); } else { table.header([ "Name".into(), "RID".into(), "Visibility".into(), "Head".into(), "Description".into(), ]); table.divider(); table.extend(rows); table.print(); } Ok(()) }