rad:z3gqcJUoA1n9HaHKufZs5FCSGazv5 heartwood6fe74305b6b274d0a1b4fdc4c81ff0b1f701fcd8
{
"request": "trigger",
"version": 1,
"event_type": "patch",
"repository": {
"id": "rad:z3gqcJUoA1n9HaHKufZs5FCSGazv5",
"name": "heartwood",
"description": "Radicle Heartwood Protocol & Stack",
"private": false,
"default_branch": "master",
"delegates": [
"did:key:z6MksFqXN3Yhqk8pTJdUGLwATkRfQvwZXPqR2qMEhbS9wzpT",
"did:key:z6MktaNvN1KVFMkSRAiN4qK5yvX1zuEEaseeX5sffhzPZRZW",
"did:key:z6MkireRatUThvd3qzfKht1S44wpm4FEWSSa4PRMTSQZ3voM",
"did:key:z6MkgFq6z5fkF2hioLLSNu1zP2qEL1aHXHZzGH1FLFGAnBGz",
"did:key:z6MkkPvBfjP4bQmco5Dm7UGsX2ruDBieEHi8n9DVJWX5sTEz"
]
},
"action": "Created",
"patch": {
"id": "8a35a73571d1bd204bdf82b6dd3b2ab18a10239e",
"author": {
"id": "did:key:z6MkhacU48u8if6RrgHFMriQL9aufp6EA6D161nuJE4evqHM",
"alias": null
},
"title": "cli: Add `--json` option to `rad ls`",
"state": {
"status": "archived",
"conflicts": []
},
"before": "574ac3566bd465d5306cd58d17ff9c87a5118ddd",
"after": "6fe74305b6b274d0a1b4fdc4c81ff0b1f701fcd8",
"commits": [
"6fe74305b6b274d0a1b4fdc4c81ff0b1f701fcd8"
],
"target": "6cfed884bf37cba1e0d8e97fa8b0e94df4a04b1f",
"labels": [],
"assignees": [],
"revisions": [
{
"id": "8a35a73571d1bd204bdf82b6dd3b2ab18a10239e",
"author": {
"id": "did:key:z6MkhacU48u8if6RrgHFMriQL9aufp6EA6D161nuJE4evqHM",
"alias": null
},
"description": "This was inspired by the `--json` option of the `rad node routing`\ncommand.",
"base": "574ac3566bd465d5306cd58d17ff9c87a5118ddd",
"oid": "6fe74305b6b274d0a1b4fdc4c81ff0b1f701fcd8",
"timestamp": 1712853959
}
]
}
}
{
"response": "triggered",
"run_id": {
"id": "a32fd18e-bcdd-4cf7-847b-84eead777d6f"
},
"info_url": "https://cci.rad.levitte.org//a32fd18e-bcdd-4cf7-847b-84eead777d6f.html"
}
Started at: 2025-10-21 17:38:45.640029+02:00
Commands:
$ rad clone rad:z3gqcJUoA1n9HaHKufZs5FCSGazv5 .
✓ Creating checkout in ./...
✓ Remote cloudhead@z6MksFqXN3Yhqk8pTJdUGLwATkRfQvwZXPqR2qMEhbS9wzpT added
✓ Remote-tracking branch cloudhead@z6MksFqXN3Yhqk8pTJdUGLwATkRfQvwZXPqR2qMEhbS9wzpT/master created for z6MksFqXN3Yhqk8pTJdUGLwATkRfQvwZXPqR2qMEhbS9wzpT
✓ Remote cloudhead@z6MktaNvN1KVFMkSRAiN4qK5yvX1zuEEaseeX5sffhzPZRZW added
✓ Remote-tracking branch cloudhead@z6MktaNvN1KVFMkSRAiN4qK5yvX1zuEEaseeX5sffhzPZRZW/master created for z6MktaNvN1KVFMkSRAiN4qK5yvX1zuEEaseeX5sffhzPZRZW
✓ Remote fintohaps@z6MkireRatUThvd3qzfKht1S44wpm4FEWSSa4PRMTSQZ3voM added
✓ Remote-tracking branch fintohaps@z6MkireRatUThvd3qzfKht1S44wpm4FEWSSa4PRMTSQZ3voM/master created for z6MkireRatUThvd3qzfKht1S44wpm4FEWSSa4PRMTSQZ3voM
✓ Remote erikli@z6MkgFq6z5fkF2hioLLSNu1zP2qEL1aHXHZzGH1FLFGAnBGz added
✓ Remote-tracking branch erikli@z6MkgFq6z5fkF2hioLLSNu1zP2qEL1aHXHZzGH1FLFGAnBGz/master created for z6MkgFq6z5fkF2hioLLSNu1zP2qEL1aHXHZzGH1FLFGAnBGz
✓ Remote lorenz@z6MkkPvBfjP4bQmco5Dm7UGsX2ruDBieEHi8n9DVJWX5sTEz added
✓ Remote-tracking branch lorenz@z6MkkPvBfjP4bQmco5Dm7UGsX2ruDBieEHi8n9DVJWX5sTEz/master created for z6MkkPvBfjP4bQmco5Dm7UGsX2ruDBieEHi8n9DVJWX5sTEz
✓ Repository successfully cloned under /opt/radcis/ci.rad.levitte.org/cci/state/a32fd18e-bcdd-4cf7-847b-84eead777d6f/w/
╭────────────────────────────────────╮
│ heartwood │
│ Radicle Heartwood Protocol & Stack │
│ 125 issues · 15 patches │
╰────────────────────────────────────╯
Run `cd ./.` to go to the repository directory.
Exit code: 0
$ rad patch checkout 8a35a73571d1bd204bdf82b6dd3b2ab18a10239e
✓ Switched to branch patch/8a35a73 at revision 8a35a73
✓ Branch patch/8a35a73 setup to track rad/patches/8a35a73571d1bd204bdf82b6dd3b2ab18a10239e
Exit code: 0
$ git config advice.detachedHead false
Exit code: 0
$ git checkout 6fe74305b6b274d0a1b4fdc4c81ff0b1f701fcd8
HEAD is now at 6fe74305 cli: Add `--json` option to `rad ls`
Exit code: 0
$ git show 6fe74305b6b274d0a1b4fdc4c81ff0b1f701fcd8
commit 6fe74305b6b274d0a1b4fdc4c81ff0b1f701fcd8
Author: Cyrill Schenkel <cyrill.schenkel@gmail.com>
Date: Thu Apr 11 18:41:17 2024 +0200
cli: Add `--json` option to `rad ls`
This was inspired by the `--json` option of the `rad node routing`
command.
diff --git a/radicle-cli/src/commands/ls.rs b/radicle-cli/src/commands/ls.rs
index 2161183a..c18884af 100644
--- a/radicle-cli/src/commands/ls.rs
+++ b/radicle-cli/src/commands/ls.rs
@@ -1,6 +1,7 @@
use std::ffi::OsString;
use radicle::storage::{ReadStorage, RepositoryInfo};
+use radicle_crypto::Verified;
use crate::terminal as term;
use crate::terminal::args::{Args, Error, Help};
@@ -26,6 +27,7 @@ Options
--seeded, -s Show all seeded repositories
--all, -a Show all repositories in storage
--verbose, -v Verbose output
+ --json JSON output
--help Print help
"#,
};
@@ -37,6 +39,7 @@ pub struct Options {
private: bool,
all: bool,
seeded: bool,
+ json: bool,
}
impl Args for Options {
@@ -49,6 +52,7 @@ impl Args for Options {
let mut public = false;
let mut all = false;
let mut seeded = false;
+ let mut json = false;
while let Some(arg) = parser.next()? {
match arg {
@@ -68,6 +72,7 @@ impl Args for Options {
public = true;
}
Long("verbose") | Short('v') => verbose = true,
+ Long("json") => json = true,
_ => return Err(anyhow::anyhow!(arg.unexpected())),
}
}
@@ -79,6 +84,7 @@ impl Args for Options {
public,
all,
seeded,
+ json,
},
vec![],
))
@@ -90,57 +96,77 @@ pub fn run(options: Options, ctx: impl term::Context) -> anyhow::Result<()> {
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
- {
+ let repos = repos.into_iter().filter_map(move |repo| {
+ let RepositoryInfo { rid, doc, refs, .. } = &repo;
if doc.visibility.is_public() && options.private && !options.public {
- continue;
+ return None;
}
if !doc.visibility.is_public() && !options.private && options.public {
- continue;
+ return None;
}
if refs.is_none() && !options.all && !options.seeded {
- continue;
- }
- let seeded = policy.is_seeding(&rid)?;
-
- if !seeded && !options.all {
- continue;
+ return None;
}
- if !seeded && options.seeded {
- continue;
+ match policy.is_seeding(rid) {
+ Ok(seeded) => {
+ if !seeded && !options.all {
+ return None;
+ }
+ if !seeded && options.seeded {
+ return None;
+ }
+ Some(Ok((repo, seeded)))
+ }
+ Err(e) => Some(Err(anyhow::anyhow!(e))),
}
- 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()),
- 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()),
- ]);
+ });
+
+ if options.json {
+ print_json(repos)?;
+ } else {
+ print_table(repos)?;
}
+
+ Ok(())
+}
+
+fn print_table(
+ repositories: impl Iterator<Item = anyhow::Result<(RepositoryInfo<Verified>, bool)>>,
+) -> anyhow::Result<()> {
+ let mut rows = repositories
+ .map(|repo| {
+ let (
+ RepositoryInfo {
+ rid,
+ head,
+ doc,
+ refs: _,
+ },
+ seeded,
+ ) = repo?;
+ let proj = doc.project()?;
+ let head = term::format::oid(head).into();
+
+ Ok([
+ 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()),
+ ])
+ })
+ .collect::<anyhow::Result<Vec<_>>>()?;
rows.sort();
if rows.is_empty() {
term::print(term::format::italic("Nothing to show."));
} else {
+ let mut table = term::Table::new(radicle_term::TableOptions::bordered());
table.push([
"Name".into(),
"RID".into(),
@@ -155,3 +181,39 @@ pub fn run(options: Options, ctx: impl term::Context) -> anyhow::Result<()> {
Ok(())
}
+
+fn print_json(
+ repositories: impl Iterator<Item = anyhow::Result<(RepositoryInfo<Verified>, bool)>>,
+) -> anyhow::Result<()> {
+ for repo in repositories {
+ let (
+ RepositoryInfo {
+ rid,
+ head,
+ doc,
+ refs: _,
+ },
+ seeded,
+ ) = repo?;
+ let proj = doc.project()?;
+ let visibility = if seeded {
+ match doc.visibility {
+ radicle::identity::Visibility::Public => "public",
+ radicle::identity::Visibility::Private { .. } => "private",
+ }
+ } else {
+ "local"
+ };
+ println!(
+ "{}",
+ serde_json::json!({
+ "name": proj.name(),
+ "rid": rid,
+ "visibility": visibility,
+ "head": head,
+ "description": proj.description()
+ })
+ );
+ }
+ Ok(())
+}
Exit code: 0
shell: 'cargo --version rustc --version cargo fmt --check cargo clippy --all-targets --workspace -- --deny clippy::all cargo build --all-targets --workspace cargo doc --workspace cargo test --workspace --no-fail-fast '
Commands:
$ podman run --name a32fd18e-bcdd-4cf7-847b-84eead777d6f -v /opt/radcis/ci.rad.levitte.org/cci/state/a32fd18e-bcdd-4cf7-847b-84eead777d6f/s:/a32fd18e-bcdd-4cf7-847b-84eead777d6f/s:ro -v /opt/radcis/ci.rad.levitte.org/cci/state/a32fd18e-bcdd-4cf7-847b-84eead777d6f/w:/a32fd18e-bcdd-4cf7-847b-84eead777d6f/w -w /a32fd18e-bcdd-4cf7-847b-84eead777d6f/w -v /opt/radcis/ci.rad.levitte.org/.radicle:/${id}/.radicle:ro -e RAD_HOME=/${id}/.radicle rust:bookworm bash /a32fd18e-bcdd-4cf7-847b-84eead777d6f/s/script.sh
+ cargo --version
info: syncing channel updates for '1.77-x86_64-unknown-linux-gnu'
info: latest update on 2024-04-09, rust version 1.77.2 (25ef9e3d8 2024-04-09)
info: downloading component 'cargo'
info: downloading component 'rust-std'
info: downloading component 'rustc'
info: installing component 'cargo'
info: installing component 'rust-std'
info: installing component 'rustc'
cargo 1.77.2 (e52e36006 2024-03-26)
+ rustc --version
rustc 1.77.2 (25ef9e3d8 2024-04-09)
+ cargo fmt --check
error: 'cargo-fmt' is not installed for the toolchain '1.77-x86_64-unknown-linux-gnu'.
To install, run `rustup component add --toolchain 1.77-x86_64-unknown-linux-gnu rustfmt`
Exit code: 1
{
"response": "finished",
"result": "failure"
}