rad:z3gqcJUoA1n9HaHKufZs5FCSGazv5 heartwood35d0387b06018762e6617df83a24da28b18901a9
{
"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": "121effd0bdd0275ac409afc17df7f9f4c7f0574f",
"author": {
"id": "did:key:z6MkkPvBfjP4bQmco5Dm7UGsX2ruDBieEHi8n9DVJWX5sTEz",
"alias": null
},
"title": "cli: Dynamic Completions",
"state": {
"status": "draft",
"conflicts": []
},
"before": "4641c342c689dd9c549af6c0235256fe225b53a7",
"after": "35d0387b06018762e6617df83a24da28b18901a9",
"commits": [
"35d0387b06018762e6617df83a24da28b18901a9",
"8348bc4f11cb0a9a74a84ad7cec01c09ce7cd19c"
],
"target": "4641c342c689dd9c549af6c0235256fe225b53a7",
"labels": [],
"assignees": [],
"revisions": [
{
"id": "121effd0bdd0275ac409afc17df7f9f4c7f0574f",
"author": {
"id": "did:key:z6MkkPvBfjP4bQmco5Dm7UGsX2ruDBieEHi8n9DVJWX5sTEz",
"alias": null
},
"description": "",
"base": "4641c342c689dd9c549af6c0235256fe225b53a7",
"oid": "35d0387b06018762e6617df83a24da28b18901a9",
"timestamp": 1786099611
}
]
}
}
{
"response": "triggered",
"run_id": {
"id": "7efd60ce-81f8-4590-b98d-c6df7f2e77fd"
},
"info_url": "https://cci.rad.levitte.org//7efd60ce-81f8-4590-b98d-c6df7f2e77fd.html"
}
Started at: 2026-08-07 12:47:15.693906+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/7efd60ce-81f8-4590-b98d-c6df7f2e77fd/w/
╭────────────────────────────────────╮
│ heartwood │
│ Radicle Heartwood Protocol & Stack │
│ 188 issues · 42 patches │
╰────────────────────────────────────╯
Run `cd ./.` to go to the repository directory.
Exit code: 0
$ rad patch checkout 121effd0bdd0275ac409afc17df7f9f4c7f0574f
✓ Switched to branch patch/121effd at revision 121effd
✓ Branch patch/121effd setup to track rad/patches/121effd0bdd0275ac409afc17df7f9f4c7f0574f
Exit code: 0
$ git config advice.detachedHead false
Exit code: 0
$ git checkout 35d0387b06018762e6617df83a24da28b18901a9
HEAD is now at 35d0387b cli: Dynamic Completions
Exit code: 0
$ rad patch show 121effd0bdd0275ac409afc17df7f9f4c7f0574f -p
╭────────────────────────────────────────────────────────────────────────────────╮
│ Title cli: Dynamic Completions │
│ Patch 121effd0bdd0275ac409afc17df7f9f4c7f0574f │
│ Author lorenz z6MkkPv…WX5sTEz │
│ Head 35d0387b06018762e6617df83a24da28b18901a9 │
│ Base 4641c342c689dd9c549af6c0235256fe225b53a7 │
│ Branches patch/121effd │
│ Commits ahead 2, behind 0 │
│ Status draft │
├────────────────────────────────────────────────────────────────────────────────┤
│ 35d0387 cli: Dynamic Completions │
│ 8348bc4 cob: Enable finding objects by prefix of ID │
├────────────────────────────────────────────────────────────────────────────────┤
│ ● Revision 121effd @ 4641c34..35d0387 by lorenz z6MkkPv…WX5sTEz 26 seconds ago │
╰────────────────────────────────────────────────────────────────────────────────╯
commit 35d0387b06018762e6617df83a24da28b18901a9
Author: Lorenz Leutgeb <lorenz.leutgeb@radicle.dev>
Date: Thu Aug 6 21:56:17 2026 +0200
cli: Dynamic Completions
diff --git a/Cargo.lock b/Cargo.lock
index 900ecf434a..a267e43eeb 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -513,6 +513,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "19c9f1dde76b736e3681f28cec9d5a61299cbaae0fce80a68e43724ad56031eb"
dependencies = [
"clap",
+ "clap_lex",
+ "is_executable",
+ "shlex",
]
[[package]]
@@ -1986,6 +1989,15 @@ dependencies = [
"unicode-width",
]
+[[package]]
+name = "is_executable"
+version = "1.0.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "82cb6a9f675da968c63b6208c641b9dca58fc0133ae53375736b1767b0cab8bd"
+dependencies = [
+ "windows-sys 0.59.0",
+]
+
[[package]]
name = "is_terminal_polyfill"
version = "1.70.2"
diff --git a/crates/radicle-cli/Cargo.toml b/crates/radicle-cli/Cargo.toml
index 11e77aadde..e1a6171f20 100644
--- a/crates/radicle-cli/Cargo.toml
+++ b/crates/radicle-cli/Cargo.toml
@@ -23,7 +23,7 @@ tor = ["radicle/tor"]
anyhow = "1"
chrono = { workspace = true, features = ["clock", "std"] }
clap = { version = "4.5.44", features = ["derive"] }
-clap_complete = "4.5"
+clap_complete = { version = "4.5", features = ["unstable-dynamic"] }
dunce = { workspace = true }
getrandom = "0.4.3"
human-panic.workspace = true
diff --git a/crates/radicle-cli/src/commands.rs b/crates/radicle-cli/src/commands.rs
index 7995a39a79..850c9692bd 100644
--- a/crates/radicle-cli/src/commands.rs
+++ b/crates/radicle-cli/src/commands.rs
@@ -4,6 +4,7 @@ pub mod checkout;
pub mod clean;
pub mod clone;
pub mod cob;
+pub(crate) mod completion;
pub mod config;
pub mod debug;
pub mod diff;
diff --git a/crates/radicle-cli/src/commands/checkout/args.rs b/crates/radicle-cli/src/commands/checkout/args.rs
index f6654ad201..6f8e271809 100644
--- a/crates/radicle-cli/src/commands/checkout/args.rs
+++ b/crates/radicle-cli/src/commands/checkout/args.rs
@@ -1,6 +1,8 @@
use clap::Parser;
use radicle::prelude::{Did, RepoId};
+use crate::commands::completion::repo_id;
+
const ABOUT: &str = "Checkout a repository into the local directory";
const LONG_ABOUT: &str = r#"
Creates a working copy from a repository in local storage.
@@ -11,6 +13,7 @@ Creates a working copy from a repository in local storage.
pub struct Args {
/// Repository ID of the repository to checkout
#[arg(value_name = "RID")]
+ #[arg(add = repo_id())]
pub(super) repo: RepoId,
/// The DID of the remote peer to checkout
diff --git a/crates/radicle-cli/src/commands/clean/args.rs b/crates/radicle-cli/src/commands/clean/args.rs
index fc836ae4c1..f9dbf24e80 100644
--- a/crates/radicle-cli/src/commands/clean/args.rs
+++ b/crates/radicle-cli/src/commands/clean/args.rs
@@ -2,6 +2,8 @@ use clap::Parser;
use radicle::prelude::RepoId;
+use crate::commands::completion::repo_id;
+
const ABOUT: &str = "Remove all remotes from a repository";
const LONG_ABOUT: &str = r#"
@@ -17,6 +19,7 @@ followed and/or the follow scope is "all".
pub struct Args {
/// Operate on the given repository
#[arg(value_name = "RID")]
+ #[arg(add = repo_id())]
pub(super) repo: RepoId,
/// Do not ask for confirmation before removal
diff --git a/crates/radicle-cli/src/commands/clone/args.rs b/crates/radicle-cli/src/commands/clone/args.rs
index 2a8ddf460d..d1b17731cb 100644
--- a/crates/radicle-cli/src/commands/clone/args.rs
+++ b/crates/radicle-cli/src/commands/clone/args.rs
@@ -8,6 +8,7 @@ use radicle::node::policy::Scope;
use radicle::prelude::*;
use radicle::storage::refs;
+use crate::commands::completion::repo_id;
use crate::common_args::{
ABOUT_FETCH_SIGNED_REFERENCES_FEATURE_LEVEL_MINIMUM, SignedReferencesFeatureLevel,
SignedReferencesFeatureLevelParser,
@@ -69,6 +70,7 @@ pub struct Args {
///
/// [example values: rad:z3Tr6bC7ctEg2EHmLvknUr29mEDLH, rad://z3Tr6bC7ctEg2EHmLvknUr29mEDLH]
#[arg(value_name = "RID", value_parser = parse_rid)]
+ #[arg(add = repo_id())]
pub(super) repo: RepoId,
/// The target directory for the repository to be cloned into
diff --git a/crates/radicle-cli/src/commands/cob/args.rs b/crates/radicle-cli/src/commands/cob/args.rs
index 704bc74fbd..6624e13bc3 100644
--- a/crates/radicle-cli/src/commands/cob/args.rs
+++ b/crates/radicle-cli/src/commands/cob/args.rs
@@ -12,6 +12,7 @@ use radicle::git;
use radicle::prelude::*;
use radicle::storage;
+use crate::commands::completion::repo_id;
use crate::git::Rev;
#[derive(Parser, Debug)]
@@ -30,6 +31,7 @@ pub(super) enum Command {
List {
/// Repository ID of the repository to operate on
#[arg(long, short, value_name = "RID")]
+ #[arg(add = repo_id())]
repo: RepoId,
/// Typename of the object(s) to list
@@ -41,6 +43,7 @@ pub(super) enum Command {
Log {
/// Repository ID of the repository to operate on
#[arg(long, short, value_name = "RID")]
+ #[arg(add = repo_id())]
repo: RepoId,
/// Typename of the object(s) to show
@@ -71,6 +74,7 @@ pub(super) enum Command {
Show {
/// Repository ID of the repository to operate on
#[arg(long, short, value_name = "RID")]
+ #[arg(add = repo_id())]
repo: RepoId,
/// Typename of the object(s) to show
@@ -113,6 +117,7 @@ pub(super) struct Operation {
pub(super) struct Create {
/// Repository ID of the repository to operate on
#[arg(long, short, value_name = "RID")]
+ #[arg(add = repo_id())]
pub(super) repo: RepoId,
/// Typename of the object to create
@@ -127,6 +132,7 @@ pub(super) struct Create {
pub(super) struct Update {
/// Repository ID of the repository to operate on
#[arg(long, short)]
+ #[arg(add = repo_id())]
pub(super) repo: RepoId,
/// Typename of the object to update
diff --git a/crates/radicle-cli/src/commands/completion.rs b/crates/radicle-cli/src/commands/completion.rs
new file mode 100644
index 0000000000..b8d4e5dfe7
--- /dev/null
+++ b/crates/radicle-cli/src/commands/completion.rs
@@ -0,0 +1,290 @@
+use std::ffi::OsStr;
+
+use clap::Parser as _;
+use clap_complete::{ArgValueCompleter, CompletionCandidate};
+use nonempty::NonEmpty;
+
+use radicle::storage::ReadStorage as _;
+use radicle_cob::{Entry, TypeName};
+
+/// Complete repository IDs from local storage.
+pub(crate) fn repo_id() -> ArgValueCompleter {
+ ArgValueCompleter::new(repo_id_candidates)
+}
+
+/// Complete identity revision IDs in the current repository.
+pub(crate) fn identity_revision_id() -> ArgValueCompleter {
+ ArgValueCompleter::new(identity_revision_id_candidates)
+}
+
+/// Complete issue IDs in the current repository.
+pub(crate) fn issue_id() -> ArgValueCompleter {
+ cob_id_with_preview::<radicle::cob::issue::Issue>(
+ &radicle::cob::issue::TYPENAME,
+ radicle::cob::issue::Issue::title,
+ )
+}
+
+/// Complete comment IDs for the issue in the current command line.
+pub(crate) fn issue_comment_id() -> ArgValueCompleter {
+ ArgValueCompleter::new(issue_comment_id_candidates)
+}
+
+/// Complete patch IDs in the current repository.
+pub(crate) fn patch_id() -> ArgValueCompleter {
+ cob_id_with_preview::<radicle::cob::patch::Patch>(
+ &radicle::cob::patch::TYPENAME,
+ radicle::cob::patch::Patch::title,
+ )
+}
+
+fn repo_id_candidates(current: &OsStr) -> Vec<CompletionCandidate> {
+ let Some(current) = current.to_str() else {
+ return Vec::new();
+ };
+ let Ok(profile) = radicle::Profile::load() else {
+ return Vec::new();
+ };
+ let Ok(repositories) = profile.storage.repositories() else {
+ return Vec::new();
+ };
+
+ repositories
+ .into_iter()
+ .filter_map(|repository| {
+ let rid = repo_id_value(repository.rid, current);
+ let help = repository
+ .doc
+ .project()
+ .ok()
+ .map(|project| project.name().to_string().into());
+
+ rid.starts_with(current)
+ .then(|| CompletionCandidate::new(rid).help(help))
+ })
+ .collect()
+}
+
+fn repo_id_value(rid: radicle::identity::RepoId, current: &str) -> String {
+ if current.starts_with("rad://") {
+ format!("rad://{}", rid.canonical())
+ } else if current.starts_with("rad:") || current.is_empty() {
+ rid.urn()
+ } else {
+ rid.canonical()
+ }
+}
+
+fn cob_id_with_preview<T>(typename: &'static TypeName, preview: fn(&T) -> &str) -> ArgValueCompleter
+where
+ T: radicle_cob::Evaluate<radicle::storage::git::Repository> + 'static,
+{
+ ArgValueCompleter::new(move |current: &OsStr| {
+ cob_id_candidates_with_preview::<T>(current, typename, preview)
+ })
+}
+
+#[allow(dead_code)]
+fn cob_id_candidates(current: &OsStr, typename: &TypeName) -> Vec<CompletionCandidate> {
+ let Some(current) = current.to_str() else {
+ return Vec::new();
+ };
+ let Some(repository) = current_repository() else {
+ return Vec::new();
+ };
+ let Ok(objects) = radicle_cob::list::<NonEmpty<Entry>, _>(&repository, typename, Some(current))
+ else {
+ return Vec::new();
+ };
+
+ objects
+ .into_iter()
+ .map(|object| object.id.to_string())
+ .filter(|id| id.starts_with(current))
+ .map(CompletionCandidate::new)
+ .collect()
+}
+
+fn identity_revision_id_candidates(current: &OsStr) -> Vec<CompletionCandidate> {
+ let Some(current) = current.to_str() else {
+ return Vec::new();
+ };
+ let Some(repository) = current_repository() else {
+ return Vec::new();
+ };
+ let Ok(identity) = radicle::cob::identity::Identity::load(&repository) else {
+ return Vec::new();
+ };
+
+ identity
+ .revisions()
+ .filter_map(|revision| {
+ let id = revision.id.to_string();
+
+ id.starts_with(current)
+ .then(|| CompletionCandidate::new(id).help(Some(revision.title.to_string().into())))
+ })
+ .collect()
+}
+
+fn issue_comment_id_candidates(current: &OsStr) -> Vec<CompletionCandidate> {
+ let Some(current) = current.to_str() else {
+ return Vec::new();
+ };
+ let Some(args) = issue_args(std::env::args_os()) else {
+ return Vec::new();
+ };
+ let Some(issue_id) = args.issue_id().map(|id| id.as_str().to_owned()) else {
+ return Vec::new();
+ };
+ let Some(repository) = repository(args.repo) else {
+ return Vec::new();
+ };
+ let Some(issue_id) = repository
+ .backend
+ .revparse_single(&issue_id)
+ .ok()
+ .map(|object| object.id().into())
+ else {
+ return Vec::new();
+ };
+ let Ok(Some(issue)) = radicle_cob::get::<radicle::cob::issue::Issue, _>(
+ &repository,
+ &radicle::cob::issue::TYPENAME,
+ &issue_id,
+ ) else {
+ return Vec::new();
+ };
+
+ issue
+ .object
+ .comments()
+ .filter_map(|(id, comment)| {
+ let id = id.to_string();
+
+ id.starts_with(current)
+ .then(|| CompletionCandidate::new(id).help(Some(comment.body().to_owned().into())))
+ })
+ .collect()
+}
+
+fn issue_args(
+ args: impl IntoIterator<Item = impl Into<std::ffi::OsString>>,
+) -> Option<crate::commands::issue::Args> {
+ let args = args
+ .into_iter()
+ .map(Into::into)
+ .collect::<Vec<std::ffi::OsString>>();
+ let issue = args.iter().position(|arg| arg == "issue")?;
+ let mut args = args.into_iter().skip(issue).peekable();
+ let mut parse_args = Vec::new();
+
+ while let Some(arg) = args.next() {
+ if matches!(arg.to_str(), Some("--to" | "--reply-to" | "--edit")) {
+ args.next();
+ } else if !matches!(
+ arg.to_str(),
+ Some(arg) if arg.starts_with("--to=")
+ || arg.starts_with("--reply-to=")
+ || arg.starts_with("--edit=")
+ ) {
+ parse_args.push(arg);
+ }
+ }
+
+ crate::commands::issue::Args::try_parse_from(parse_args).ok()
+}
+
+fn cob_id_candidates_with_preview<T>(
+ current: &OsStr,
+ typename: &TypeName,
+ preview: fn(&T) -> &str,
+) -> Vec<CompletionCandidate>
+where
+ T: radicle_cob::Evaluate<radicle::storage::git::Repository>,
+{
+ let Some(current) = current.to_str() else {
+ return Vec::new();
+ };
+ let Some(repository) = current_repository() else {
+ return Vec::new();
+ };
+ let Ok(objects) = radicle_cob::list::<T, _>(&repository, typename, Some(current)) else {
+ return Vec::new();
+ };
+
+ objects
+ .into_iter()
+ .filter_map(|object| {
+ let id = object.id.to_string();
+
+ id.starts_with(current).then(|| {
+ CompletionCandidate::new(id).help(Some(preview(&object.object).to_owned().into()))
+ })
+ })
+ .collect()
+}
+
+fn current_repository() -> Option<radicle::storage::git::Repository> {
+ repository(None)
+}
+
+fn repository(rid: Option<radicle::identity::RepoId>) -> Option<radicle::storage::git::Repository> {
+ let profile = radicle::Profile::load().ok()?;
+ let rid = match rid {
+ Some(rid) => rid,
+ None => radicle::rad::cwd().ok()?.1,
+ };
+
+ profile.storage.repository(rid).ok()
+}
+
+#[cfg(test)]
+mod test {
+ use super::{issue_args, repo_id_value};
+
+ #[test]
+ fn preserves_repository_id_spelling() {
+ let rid = "rad:z3Tr6bC7ctEg2EHmLvknUr29mEDLH".parse().unwrap();
+
+ assert_eq!(repo_id_value(rid, ""), "rad:z3Tr6bC7ctEg2EHmLvknUr29mEDLH");
+ assert_eq!(
+ repo_id_value(rid, "rad:z3"),
+ "rad:z3Tr6bC7ctEg2EHmLvknUr29mEDLH"
+ );
+ assert_eq!(
+ repo_id_value(rid, "rad://z3"),
+ "rad://z3Tr6bC7ctEg2EHmLvknUr29mEDLH"
+ );
+ assert_eq!(repo_id_value(rid, "z3"), "z3Tr6bC7ctEg2EHmLvknUr29mEDLH");
+ }
+
+ #[test]
+ fn parses_issue_completion_arguments() {
+ assert_eq!(
+ issue_args(["rad", "issue", "comment", "abc", "--reply-to", ""])
+ .unwrap()
+ .issue_id()
+ .unwrap()
+ .as_str(),
+ "abc"
+ );
+ assert_eq!(
+ issue_args([
+ "rad",
+ "issue",
+ "--repo",
+ "rad:z3Tr6bC7ctEg2EHmLvknUr29mEDLH",
+ "react",
+ "def",
+ "--to",
+ "",
+ ])
+ .unwrap()
+ .issue_id()
+ .unwrap()
+ .as_str(),
+ "def"
+ );
+ }
+}
diff --git a/crates/radicle-cli/src/commands/fork/args.rs b/crates/radicle-cli/src/commands/fork/args.rs
index 5ca9d1b942..c429e728d0 100644
--- a/crates/radicle-cli/src/commands/fork/args.rs
+++ b/crates/radicle-cli/src/commands/fork/args.rs
@@ -1,5 +1,7 @@
use radicle::identity::RepoId;
+use crate::commands::completion::repo_id;
+
const ABOUT: &str = "Create a fork of a repository
This command is deprecated and will be removed.
@@ -19,6 +21,7 @@ pub struct Args {
///
/// [example values: rad:z3Tr6bC7ctEg2EHmLvknUr29mEDLH, z3Tr6bC7ctEg2EHmLvknUr29mEDLH]
#[arg(value_name = "RID")]
+ #[arg(add = repo_id())]
pub(super) repo: Option<RepoId>,
}
diff --git a/crates/radicle-cli/src/commands/id/args.rs b/crates/radicle-cli/src/commands/id/args.rs
index 5b248b8da3..bfe7f8cb27 100644
--- a/crates/radicle-cli/src/commands/id/args.rs
+++ b/crates/radicle-cli/src/commands/id/args.rs
@@ -13,6 +13,7 @@ use radicle::identity::doc::update::EditVisibility;
use radicle::identity::doc::update::PayloadUpsert;
use radicle::prelude::{Did, RepoId};
+use crate::commands::completion::{identity_revision_id, repo_id};
use crate::git::Rev;
use crate::terminal::Interactive;
@@ -100,6 +101,7 @@ pub struct Args {
/// [example values: rad:z3Tr6bC7ctEg2EHmLvknUr29mEDLH, z3Tr6bC7ctEg2EHmLvknUr29mEDLH]
#[arg(long)]
#[arg(value_name = "RID", global = true)]
+ #[arg(add = repo_id())]
pub(super) repo: Option<RepoId>,
/// Do not ask for confirmation
@@ -135,6 +137,7 @@ pub(super) enum Command {
Accept {
/// Proposed revision to accept
#[arg(value_name = "REVISION_ID")]
+ #[arg(add = identity_revision_id())]
revision: Rev,
},
@@ -143,6 +146,7 @@ pub(super) enum Command {
Reject {
/// Proposed revision to reject
#[arg(value_name = "REVISION_ID")]
+ #[arg(add = identity_revision_id())]
revision: Rev,
},
@@ -151,6 +155,7 @@ pub(super) enum Command {
Edit {
/// Proposed revision to edit
#[arg(value_name = "REVISION_ID")]
+ #[arg(add = identity_revision_id())]
revision: Rev,
/// Title of the edit
@@ -231,6 +236,7 @@ pub(super) enum Command {
Show {
/// Proposed revision to show
#[arg(value_name = "REVISION_ID")]
+ #[arg(add = identity_revision_id())]
revision: Rev,
},
@@ -239,6 +245,7 @@ pub(super) enum Command {
Redact {
/// Proposed revision to redact
#[arg(value_name = "REVISION_ID")]
+ #[arg(add = identity_revision_id())]
revision: Rev,
},
@@ -252,8 +259,27 @@ pub(super) enum Command {
#[cfg(test)]
mod test {
use super::{Args, parse_many_upserts};
- use clap::Parser;
use clap::error::ErrorKind;
+ use clap::{CommandFactory as _, Parser};
+ use clap_complete::ArgValueCompleter;
+
+ #[test]
+ fn identity_revision_ids_have_dynamic_completion() {
+ let command = Args::command();
+
+ for name in ["accept", "edit", "redact", "reject", "show"] {
+ let command = command.find_subcommand(name).unwrap();
+ let revision = command
+ .get_arguments()
+ .find(|arg| arg.get_id() == "revision")
+ .unwrap();
+
+ assert!(
+ revision.get::<ArgValueCompleter>().is_some(),
+ "identity revision ID for `{name}` has no dynamic completer"
+ );
+ }
+ }
#[test]
fn should_parse_single_payload() {
diff --git a/crates/radicle-cli/src/commands/inbox/args.rs b/crates/radicle-cli/src/commands/inbox/args.rs
index 2fe9a9b9df..e852295e8c 100644
--- a/crates/radicle-cli/src/commands/inbox/args.rs
+++ b/crates/radicle-cli/src/commands/inbox/args.rs
@@ -3,6 +3,8 @@ use std::{fmt::Display, str::FromStr};
use clap::{Parser, Subcommand, ValueEnum};
use radicle::{node::notifications::NotificationId, prelude::RepoId};
+use crate::commands::completion::repo_id;
+
const ABOUT: &str = "Manage your Radicle notifications";
const LONG_ABOUT: &str = r#"
@@ -68,6 +70,7 @@ pub(super) struct EmptyArgs {
/// Operate on a given repository [default: cwd]
#[arg(value_name = "RID")]
#[arg(long, hide = true)]
+ #[arg(add = repo_id())]
repo: Option<RepoId>,
/// Operate on all repositories
@@ -91,6 +94,7 @@ pub(super) struct ListArgs {
/// Operate on a given repository [default: cwd]
#[arg(long, value_name = "RID")]
+ #[arg(add = repo_id())]
pub(super) repo: Option<RepoId>,
/// Operate on all repositories
@@ -137,6 +141,7 @@ impl From<EmptyArgs> for ListArgs {
pub(super) struct ClearArgs {
/// Operate on a given repository [default: cwd]
#[arg(long, value_name = "RID")]
+ #[arg(add = repo_id())]
repo: Option<RepoId>,
/// Operate on all repositories
diff --git a/crates/radicle-cli/src/commands/init/args.rs b/crates/radicle-cli/src/commands/init/args.rs
index 88831bce1f..aef332f1e6 100644
--- a/crates/radicle-cli/src/commands/init/args.rs
+++ b/crates/radicle-cli/src/commands/init/args.rs
@@ -8,7 +8,7 @@ use radicle::{
};
use radicle_term::Interactive;
-use crate::terminal::args::ScopeParser;
+use crate::{commands::completion::repo_id, terminal::args::ScopeParser};
const ABOUT: &str = "Initialize a Radicle repository";
@@ -44,6 +44,7 @@ pub struct Args {
///
/// [example values: rad:z3Tr6bC7ctEg2EHmLvknUr29mEDLH, z3Tr6bC7ctEg2EHmLvknUr29mEDLH]
#[arg(long, value_name = "RID")]
+ #[arg(add = repo_id())]
pub(super) existing: Option<RepoId>,
/// Set up the upstream of the default branch
#[arg(short = 'u', long)]
diff --git a/crates/radicle-cli/src/commands/issue/args.rs b/crates/radicle-cli/src/commands/issue/args.rs
index e48a974f8e..9d4b44a4d2 100644
--- a/crates/radicle-cli/src/commands/issue/args.rs
+++ b/crates/radicle-cli/src/commands/issue/args.rs
@@ -8,7 +8,11 @@ use radicle::{
issue::{CloseReason, State},
};
-use crate::{git::Rev, terminal::patch::Message};
+use crate::{
+ commands::completion::{issue_comment_id, issue_id, repo_id},
+ git::Rev,
+ terminal::patch::Message,
+};
#[derive(Default, Debug, Clone, PartialEq, Eq)]
pub enum Assigned {
@@ -43,6 +47,7 @@ pub struct Args {
#[arg(value_name = "RID")]
#[arg(long, short)]
#[clap(global = true)]
+ #[arg(add = repo_id())]
pub(crate) repo: Option<RepoId>,
/// Enable verbose output
@@ -56,12 +61,24 @@ pub struct Args {
pub(crate) empty: EmptyArgs,
}
+impl Args {
+ /// Return the issue ID supplied to a command that operates on comments.
+ pub(crate) fn issue_id(&self) -> Option<&Rev> {
+ match self.command.as_ref()? {
+ Command::Comment(args) => Some(&args.id),
+ Command::React { id, .. } => Some(id),
+ _ => None,
+ }
+ }
+}
+
#[derive(Subcommand, Debug)]
pub(crate) enum Command {
/// Add or delete assignees from an issue
Assign {
/// ID of the issue
#[arg(value_name = "ISSUE_ID")]
+ #[arg(add = issue_id())]
id: Rev,
/// Add an assignee (may be specified multiple times, takes precedence over `--delete`)
@@ -80,6 +97,7 @@ pub(crate) enum Command {
Cache {
/// Optionally choose an issue to re-cache
#[arg(value_name = "ISSUE_ID")]
+ #[arg(add = issue_id())]
id: Option<Rev>,
/// Operate on storage
@@ -93,6 +111,7 @@ pub(crate) enum Command {
Edit {
/// ID of the issue
#[arg(value_name = "ISSUE_ID")]
+ #[arg(add = issue_id())]
id: Rev,
/// The new title to set
@@ -107,12 +126,14 @@ pub(crate) enum Command {
Delete {
/// ID of the issue
#[arg(value_name = "ISSUE_ID")]
+ #[arg(add = issue_id())]
id: Rev,
},
/// Add or delete labels from an issue
Label {
/// ID of the issue
#[arg(value_name = "ISSUE_ID")]
+ #[arg(add = issue_id())]
id: Rev,
/// Add a label (may be specified multiple times, takes precedence over `--delete`)
@@ -152,6 +173,7 @@ pub(crate) enum Command {
React {
/// ID of the issue
#[arg(value_name = "ISSUE_ID")]
+ #[arg(add = issue_id())]
id: Rev,
/// The emoji reaction
@@ -162,18 +184,21 @@ pub(crate) enum Command {
/// Optionally react to a comment
#[arg(long = "to")]
#[arg(value_name = "COMMENT_ID")]
+ #[arg(add = issue_comment_id())]
comment_id: Option<Rev>,
},
/// Show a specific issue
Show {
/// ID of the issue
#[arg(value_name = "ISSUE_ID")]
+ #[arg(add = issue_id())]
id: Rev,
},
/// Transition the state of an issue
State {
/// ID of the issue
#[arg(value_name = "ISSUE_ID")]
+ #[arg(add = issue_id())]
id: Rev,
/// The desired target state
@@ -305,6 +330,7 @@ impl From<EmptyArgs> for ListArgs {
pub(crate) struct CommentArgs {
/// ID of the issue
#[arg(value_name = "ISSUE_ID")]
+ #[arg(add = issue_id())]
id: Rev,
/// The body of the comment
@@ -316,11 +342,13 @@ pub(crate) struct CommentArgs {
/// will be in reply to the issue itself
#[arg(long, value_name = "COMMENT_ID")]
#[arg(conflicts_with = "edit")]
+ #[arg(add = issue_comment_id())]
reply_to: Option<Rev>,
/// Edit a comment by specifying its ID
#[arg(long, value_name = "COMMENT_ID")]
#[arg(conflicts_with = "reply_to")]
+ #[arg(add = issue_comment_id())]
edit: Option<Rev>,
}
@@ -460,3 +488,55 @@ impl From<CommentArgs> for CommentAction {
}
}
}
+
+#[cfg(test)]
+mod test {
+ use clap::CommandFactory as _;
+ use clap_complete::ArgValueCompleter;
+
+ use super::Args;
+
+ #[test]
+ fn issue_ids_have_dynamic_completion() {
+ let command = Args::command();
+
+ for name in [
+ "assign", "cache", "comment", "delete", "edit", "label", "react", "show", "state",
+ ] {
+ let command = command.find_subcommand(name).unwrap();
+ let id = command
+ .get_arguments()
+ .find(|arg| arg.get_id() == "id")
+ .unwrap();
+
+ assert!(
+ id.get::<ArgValueCompleter>().is_some(),
+ "issue ID for `{name}` has no dynamic completer"
+ );
+ }
+ }
+
+ #[test]
+ fn issue_comment_ids_have_dynamic_completion() {
+ let command = Args::command();
+ let react = command.find_subcommand("react").unwrap();
+ let comment = command.find_subcommand("comment").unwrap();
+
+ for arg in [
+ react
+ .get_arguments()
+ .find(|arg| arg.get_id() == "comment_id")
+ .unwrap(),
+ comment
+ .get_arguments()
+ .find(|arg| arg.get_id() == "reply_to")
+ .unwrap(),
+ comment
+ .get_arguments()
+ .find(|arg| arg.get_id() == "edit")
+ .unwrap(),
+ ] {
+ assert!(arg.get::<ArgValueCompleter>().is_some());
+ }
+ }
+}
diff --git a/crates/radicle-cli/src/commands/node/args.rs b/crates/radicle-cli/src/commands/node/args.rs
index 904fb2618c..43ee4b66ae 100644
--- a/crates/radicle-cli/src/commands/node/args.rs
+++ b/crates/radicle-cli/src/commands/node/args.rs
@@ -11,6 +11,8 @@ use radicle::crypto::{PublicKey, PublicKeyError};
use radicle::node::{Address, NodeId, PeerAddr, PeerAddrParseError};
use radicle::prelude::RepoId;
+use crate::commands::completion::repo_id;
+
const ABOUT: &str = "Control and query the Radicle Node";
#[derive(Parser, Debug)]
@@ -148,6 +150,7 @@ pub(super) enum Command {
/// Show the routing table entries for the given RID
#[arg(long = "rid", value_name = "RID")]
+ #[arg(add = repo_id())]
repo: Option<RepoId>,
/// Show the routing table entries for the given NID
diff --git a/crates/radicle-cli/src/commands/patch/args.rs b/crates/radicle-cli/src/commands/patch/args.rs
index 0db3a6e71c..29394ea9da 100644
--- a/crates/radicle-cli/src/commands/patch/args.rs
+++ b/crates/radicle-cli/src/commands/patch/args.rs
@@ -10,6 +10,7 @@ use radicle::patch::Verdict;
use radicle::prelude::Did;
use radicle::prelude::RepoId;
+use crate::commands::completion::{patch_id, repo_id};
use crate::commands::patch::checkout;
use crate::commands::patch::review;
@@ -38,6 +39,7 @@ pub struct Args {
/// Operate on the given repository [default: cwd]
#[arg(long, global = true, value_name = "RID")]
+ #[arg(add = repo_id())]
pub(super) repo: Option<RepoId>,
/// Verbose output
@@ -68,6 +70,7 @@ pub(super) enum Command {
Show {
/// ID of the patch
#[arg(value_name = "PATCH_ID")]
+ #[arg(add = patch_id())]
id: Rev,
/// Show the diff of the changes in the patch
@@ -85,6 +88,7 @@ pub(super) enum Command {
Diff {
/// ID of the patch
#[arg(value_name = "PATCH_ID")]
+ #[arg(add = patch_id())]
id: Rev,
/// The revision to diff
@@ -100,6 +104,7 @@ pub(super) enum Command {
Archive {
/// ID of the patch
#[arg(value_name = "PATCH_ID")]
+ #[arg(add = patch_id())]
id: Rev,
/// Unarchive a patch
@@ -114,6 +119,7 @@ pub(super) enum Command {
Update {
/// ID of the patch
#[arg(value_name = "PATCH_ID")]
+ #[arg(add = patch_id())]
id: Rev,
/// Provide a Git revision as the base commit
@@ -133,6 +139,7 @@ pub(super) enum Command {
Checkout {
/// ID of the patch
#[arg(value_name = "PATCH_ID")]
+ #[arg(add = patch_id())]
id: Rev,
/// Checkout the given revision of the patch
@@ -147,6 +154,7 @@ pub(super) enum Command {
Review {
/// ID of the patch
#[arg(value_name = "PATCH_ID")]
+ #[arg(add = patch_id())]
id: Rev,
/// The particular revision to review
@@ -163,6 +171,7 @@ pub(super) enum Command {
Resolve {
/// ID of the patch
#[arg(value_name = "PATCH_ID")]
+ #[arg(add = patch_id())]
id: Rev,
/// The review id which the comment is under
@@ -187,6 +196,7 @@ pub(super) enum Command {
Delete {
/// ID of the patch
#[arg(value_name = "PATCH_ID")]
+ #[arg(add = patch_id())]
id: Rev,
},
@@ -202,6 +212,7 @@ pub(super) enum Command {
React {
/// ID of the patch or patch revision
#[arg(value_name = "PATCH_ID|REVISION_ID")]
+ #[arg(add = patch_id())]
id: Rev,
/// The reaction being used
@@ -217,6 +228,7 @@ pub(super) enum Command {
Assign {
/// ID of the patch
#[arg(value_name = "PATCH_ID")]
+ #[arg(add = patch_id())]
id: Rev,
#[clap(flatten)]
@@ -227,6 +239,7 @@ pub(super) enum Command {
Label {
/// ID of the patch
#[arg(value_name = "PATCH_ID")]
+ #[arg(add = patch_id())]
id: Rev,
#[clap(flatten)]
@@ -238,6 +251,7 @@ pub(super) enum Command {
Ready {
/// ID of the patch
#[arg(value_name = "PATCH_ID")]
+ #[arg(add = patch_id())]
id: Rev,
/// Convert a patch back to a draft
@@ -249,6 +263,7 @@ pub(super) enum Command {
Edit {
/// ID of the patch
#[arg(value_name = "PATCH_ID")]
+ #[arg(add = patch_id())]
id: Rev,
/// ID of the patch revision
@@ -263,6 +278,7 @@ pub(super) enum Command {
Set {
/// ID of the patch
#[arg(value_name = "PATCH_ID")]
+ #[arg(add = patch_id())]
id: Rev,
/// Provide the git remote to use as the upstream
@@ -277,6 +293,7 @@ pub(super) enum Command {
Cache {
/// ID of the patch
#[arg(value_name = "PATCH_ID")]
+ #[arg(add = patch_id())]
id: Option<Rev>,
/// Re-cache all patches in storage, as opposed to the current repository
@@ -771,3 +788,32 @@ pub(super) struct LabelArgs {
fn parse_refstr(refstr: &str) -> Result<RefString, git::fmt::Error> {
RefString::try_from(refstr)
}
+
+#[cfg(test)]
+mod test {
+ use clap::CommandFactory as _;
+ use clap_complete::ArgValueCompleter;
+
+ use super::Args;
+
+ #[test]
+ fn patch_ids_have_dynamic_completion() {
+ let command = Args::command();
+
+ for name in [
+ "archive", "assign", "cache", "checkout", "delete", "diff", "edit", "label", "react",
+ "ready", "resolve", "review", "set", "show", "update",
+ ] {
+ let command = command.find_subcommand(name).unwrap();
+ let id = command
+ .get_arguments()
+ .find(|arg| arg.get_id() == "id")
+ .unwrap();
+
+ assert!(
+ id.get::<ArgValueCompleter>().is_some(),
+ "patch ID for `{name}` has no dynamic completer"
+ );
+ }
+ }
+}
diff --git a/crates/radicle-cli/src/commands/publish/args.rs b/crates/radicle-cli/src/commands/publish/args.rs
index 51dfd036ea..d20ed2d195 100644
--- a/crates/radicle-cli/src/commands/publish/args.rs
+++ b/crates/radicle-cli/src/commands/publish/args.rs
@@ -1,5 +1,7 @@
use radicle::identity::RepoId;
+use crate::commands::completion::repo_id;
+
const ABOUT: &str = "Publish a repository to the network";
const LONG_ABOUT: &str = r#"
@@ -21,6 +23,7 @@ pub struct Args {
///
/// [example values: rad:z3Tr6bC7ctEg2EHmLvknUr29mEDLH, z3Tr6bC7ctEg2EHmLvknUr29mEDLH]
#[arg(value_name = "RID")]
+ #[arg(add = repo_id())]
pub(super) repo: Option<RepoId>,
}
diff --git a/crates/radicle-cli/src/commands/seed/args.rs b/crates/radicle-cli/src/commands/seed/args.rs
index cedf2b6ae1..fb2c0a57c4 100644
--- a/crates/radicle-cli/src/commands/seed/args.rs
+++ b/crates/radicle-cli/src/commands/seed/args.rs
@@ -6,6 +6,7 @@ use nonempty::NonEmpty;
use radicle::node::policy::Scope;
use radicle::prelude::*;
+use crate::commands::completion::repo_id;
use crate::node::SyncSettings;
use crate::terminal;
@@ -28,6 +29,7 @@ plus any remote that is explicitly followed via `rad follow <nid>`.
#[command(about = ABOUT, long_about = LONG_ABOUT, disable_version_flag = true)]
pub struct Args {
#[arg(value_name = "RID", num_args = 1..)]
+ #[arg(add = repo_id())]
pub(super) rids: Option<Vec<RepoId>>,
/// Fetch repository after updating seeding policy
diff --git a/crates/radicle-cli/src/commands/sync/args.rs b/crates/radicle-cli/src/commands/sync/args.rs
index 235c9cabcb..5654e016dc 100644
--- a/crates/radicle-cli/src/commands/sync/args.rs
+++ b/crates/radicle-cli/src/commands/sync/args.rs
@@ -9,6 +9,7 @@ use radicle::{
storage::refs,
};
+use crate::commands::completion::repo_id;
use crate::common_args::{
ABOUT_FETCH_SIGNED_REFERENCES_FEATURE_LEVEL_MINIMUM, SignedReferencesFeatureLevel,
SignedReferencesFeatureLevelParser,
@@ -108,6 +109,7 @@ pub(super) struct SyncArgs {
/// The repository to perform the synchronizing for [default: cwd]
#[arg(value_name = "RID")]
+ #[arg(add = repo_id())]
repo: Option<RepoId>,
/// Synchronize with a specific number of seeds
@@ -180,6 +182,7 @@ pub(super) enum Command {
Status {
/// The repository to display the status for [default: cwd]
#[arg(value_name = "RID")]
+ #[arg(add = repo_id())]
repo: Option<RepoId>,
/// Sort the table by column
#[arg(long, value_name = "FIELD", value_enum, default_value_t)]
diff --git a/crates/radicle-cli/src/commands/unseed/args.rs b/crates/radicle-cli/src/commands/unseed/args.rs
index 2c5792667a..2dabb9a93d 100644
--- a/crates/radicle-cli/src/commands/unseed/args.rs
+++ b/crates/radicle-cli/src/commands/unseed/args.rs
@@ -1,6 +1,8 @@
use clap::Parser;
use radicle::prelude::RepoId;
+use crate::commands::completion::repo_id;
+
const ABOUT: &str = "Remove repository seeding policies";
const LONG_ABOUT: &str = r#"
@@ -12,5 +14,6 @@ for the given repositories."#;
pub struct Args {
/// ID of the repository to remove the seeding policy for (may be repeated)
#[arg(value_name = "RID", required = true, action = clap::ArgAction::Append)]
+ #[arg(add = repo_id())]
pub rids: Vec<RepoId>,
}
diff --git a/crates/radicle-cli/src/commands/watch/args.rs b/crates/radicle-cli/src/commands/watch/args.rs
index 23b21b3dc9..1eb14a00ab 100644
--- a/crates/radicle-cli/src/commands/watch/args.rs
+++ b/crates/radicle-cli/src/commands/watch/args.rs
@@ -7,6 +7,8 @@ use radicle::git;
use radicle::git::fmt::RefString;
use radicle::prelude::{NodeId, RepoId};
+use crate::commands::completion::repo_id;
+
const ABOUT: &str = "Wait for some state to be updated";
const LONG_ABOUT: &str = r#"
@@ -22,6 +24,7 @@ fn parse_refstr(refstr: &str) -> Result<RefString, git::fmt::Error> {
pub struct Args {
/// The repository to watch, defaults to `rad .`
#[arg(long)]
+ #[arg(add = repo_id())]
pub(super) repo: Option<RepoId>,
/// The fully-qualified Git reference (branch, tag, etc.) to watch
diff --git a/crates/radicle-cli/src/main.rs b/crates/radicle-cli/src/main.rs
index 29bd54aae1..6706dc1826 100644
--- a/crates/radicle-cli/src/main.rs
+++ b/crates/radicle-cli/src/main.rs
@@ -99,10 +99,10 @@ enum Command {
json: bool,
},
- /// Print static completion information for a given shell
+ /// Print static and dynamic completion information for a given shell
#[command(hide = true)]
Completion {
- /// The type of shell to output a static completion script for.
+ /// The type of shell to output a completion script for.
shell: clap_complete::Shell,
},
@@ -111,6 +111,8 @@ enum Command {
}
fn main() {
+ clap_complete::CompleteEnv::with_factory(CliArgs::command).complete();
+
human_panic::setup_panic!(human_panic::Metadata::new(
env!("CARGO_PKG_NAME"),
env!("CARGO_PKG_VERSION")
@@ -287,20 +289,26 @@ fn run_command(command: Command, ctx: impl term::Context) -> Result<(), anyhow::
Command::Watch(args) => watch::run(args, ctx),
Command::Version { json } => write_version(json),
Command::Completion { shell } => {
- print_completion(shell, &mut CliArgs::command());
+ print_completion(shell, &mut CliArgs::command(), &mut io::stdout())?;
Ok(())
}
Command::External(args) => ExternalCommand::new(args).run(),
}
}
-fn print_completion<G: clap_complete::Generator>(generator: G, cmd: &mut clap::Command) {
- clap_complete::generate(
- generator,
- cmd,
- cmd.get_name().to_string(),
- &mut io::stdout(),
- );
+fn print_completion(
+ shell: clap_complete::Shell,
+ cmd: &mut clap::Command,
+ buf: &mut dyn Write,
+) -> io::Result<()> {
+ clap_complete::generate(shell, cmd, cmd.get_name().to_string(), &mut *buf);
+
+ let shells = clap_complete::env::Shells::builtins();
+ let shell = shells
+ .completer(&shell.to_string())
+ .expect("all statically supported shells support dynamic completion");
+
+ shell.write_registration("COMPLETE", NAME, NAME, NAME, buf)
}
struct ExternalCommand {
@@ -363,3 +371,35 @@ impl ExternalCommand {
}
}
}
+
+#[cfg(test)]
+mod test {
+ use clap::ValueEnum as _;
+
+ use clap::CommandFactory as _;
+
+ use super::{CliArgs, print_completion};
+
+ #[test]
+ fn completion_command_generates_static_scripts_and_dynamic_hooks() {
+ for shell in clap_complete::Shell::value_variants() {
+ let mut static_script = Vec::new();
+ let mut command = CliArgs::command();
+ let name = command.get_name().to_owned();
+ clap_complete::generate(*shell, &mut command, name, &mut static_script);
+ let mut buf = Vec::new();
+
+ print_completion(*shell, &mut CliArgs::command(), &mut buf).unwrap();
+
+ let script = String::from_utf8(buf).unwrap();
+ assert!(
+ script.as_bytes().starts_with(&static_script),
+ "script for {shell} does not start with static completion data"
+ );
+ assert!(
+ script.contains("COMPLETE"),
+ "script for {shell} has no dynamic completion hook"
+ );
+ }
+ }
+}
diff --git a/crates/radicle/src/storage/git/cob.rs b/crates/radicle/src/storage/git/cob.rs
index 070f0ebcbf..e2cd8ee549 100644
--- a/crates/radicle/src/storage/git/cob.rs
+++ b/crates/radicle/src/storage/git/cob.rs
@@ -124,14 +124,15 @@ impl cob::object::Storage for Repository {
};
if let Ok(name) = RefStr::try_from_str(name)
- && let Some((_, object_id)) = cob::object::parse_refstr(&name) {
- let obj_ref = cob::object::Reference::try_from(reference)
- .map_err(Self::ObjectsError::from)?;
- objects_map
- .entry(object_id)
- .and_modify(|objs: &mut Objects| objs.push(obj_ref.clone()))
- .or_insert_with(|| Objects::new(obj_ref));
- }
+ && let Some((_, object_id)) = cob::object::parse_refstr(&name)
+ {
+ let obj_ref = cob::object::Reference::try_from(reference)
+ .map_err(Self::ObjectsError::from)?;
+ objects_map
+ .entry(object_id)
+ .and_modify(|objs: &mut Objects| objs.push(obj_ref.clone()))
+ .or_insert_with(|| Objects::new(obj_ref));
+ }
}
Ok(objects_map)
commit 8348bc4f11cb0a9a74a84ad7cec01c09ce7cd19c
Author: Lorenz Leutgeb <lorenz.leutgeb@radicle.dev>
Date: Thu Aug 6 22:34:03 2026 +0200
cob: Enable finding objects by prefix of ID
diff --git a/crates/radicle-cli/src/commands/cob.rs b/crates/radicle-cli/src/commands/cob.rs
index b89ce39a80..0fb4d28a35 100644
--- a/crates/radicle-cli/src/commands/cob.rs
+++ b/crates/radicle-cli/src/commands/cob.rs
@@ -98,6 +98,7 @@ pub fn run(args: Args, ctx: impl term::Context) -> anyhow::Result<()> {
let cobs = radicle_cob::list::<NonEmpty<cob::Entry>, _>(
&repo,
FilteredTypeName::from(type_name).as_ref(),
+ None,
)?;
for cob in cobs {
term::println(cob.id);
diff --git a/crates/radicle-cob/src/object/collaboration/list.rs b/crates/radicle-cob/src/object/collaboration/list.rs
index 22910020c8..ae0cc59ee5 100644
--- a/crates/radicle-cob/src/object/collaboration/list.rs
+++ b/crates/radicle-cob/src/object/collaboration/list.rs
@@ -14,6 +14,7 @@ use super::error;
pub fn list<T, S>(
storage: &S,
typename: &TypeName,
+ prefix: Option<&str>,
) -> Result<Vec<CollaborativeObject<T>>, error::Retrieve>
where
T: Evaluate<S>,
@@ -25,9 +26,14 @@ where
Signature = crypto::Signature,
>,
{
- let references = storage
- .types(typename)
- .map_err(|err| error::Retrieve::Refs { err: Box::new(err) })?;
+ let references = match prefix {
+ None => storage
+ .types(typename)
+ .map_err(|err| error::Retrieve::Refs { err: Box::new(err) })?,
+ Some(prefix) => storage
+ .objects_by_prefix(typename, prefix)
+ .map_err(|err| error::Retrieve::Refs { err: Box::new(err) })?,
+ };
log::trace!(target: "cob", "Loaded {} references", references.len());
let mut result = Vec::new();
for (oid, tip_refs) in references {
diff --git a/crates/radicle-cob/src/object/storage.rs b/crates/radicle-cob/src/object/storage.rs
index f2b6bfab89..cb959a6530 100644
--- a/crates/radicle-cob/src/object/storage.rs
+++ b/crates/radicle-cob/src/object/storage.rs
@@ -74,6 +74,14 @@ pub trait Storage {
object_id: &ObjectId,
) -> Result<Objects, Self::ObjectsError>;
+ /// Get all references to objects of a given type with an object ID
+ /// that starts with a given prefix.
+ fn objects_by_prefix(
+ &self,
+ typename: &TypeName,
+ object_id_prefix: &str,
+ ) -> Result<BTreeMap<ObjectId, Objects>, Self::ObjectsError>;
+
/// Get all references to objects of a given type within a particular
/// identity
fn types(&self, typename: &TypeName) -> Result<BTreeMap<ObjectId, Objects>, Self::TypesError>;
diff --git a/crates/radicle-cob/src/test/storage.rs b/crates/radicle-cob/src/test/storage.rs
index ae5e35ec8a..5ad44b0035 100644
--- a/crates/radicle-cob/src/test/storage.rs
+++ b/crates/radicle-cob/src/test/storage.rs
@@ -142,6 +142,32 @@ impl object::Storage for Storage {
Ok(remotes.into())
}
+ fn objects_by_prefix(
+ &self,
+ typename: &crate::TypeName,
+ object_id_prefix: &str,
+ ) -> Result<BTreeMap<ObjectId, object::Objects>, Self::ObjectsError> {
+ let glob = format!("refs/rad/*/cobs/{typename}/{object_id_prefix}*");
+ let mut objects = BTreeMap::new();
+ for r in self.raw.references_glob(&glob)? {
+ let r = r?;
+ let Some(object_id) = r
+ .name()
+ .ok()
+ .and_then(|name| name.rsplit('/').next())
+ .and_then(|id| id.parse::<ObjectId>().ok())
+ else {
+ continue;
+ };
+ let reference = Reference::try_from(r)?;
+ objects
+ .entry(object_id)
+ .and_modify(|objs: &mut object::Objects| objs.push(reference.clone()))
+ .or_insert_with(|| object::Objects::new(reference));
+ }
+ Ok(objects)
+ }
+
fn types(
&self,
typename: &crate::TypeName,
diff --git a/crates/radicle-cob/src/tests.rs b/crates/radicle-cob/src/tests.rs
index 79a747029c..f099d2e608 100644
--- a/crates/radicle-cob/src/tests.rs
+++ b/crates/radicle-cob/src/tests.rs
@@ -99,13 +99,28 @@ mod git {
)
.unwrap();
- let mut expected = list(&storage, &typename).unwrap();
+ let mut expected = list(&storage, &typename, None).unwrap();
expected.sort_by(|x, y| x.id().cmp(y.id()));
let mut actual = vec![issue_1, issue_2];
- actual.sort_by(|x, y| x.id().cmp(y.id()));
- assert_eq!(actual, expected);
+ {
+ actual.sort_by(|x, y| x.id().cmp(y.id()));
+ assert_eq!(actual, expected);
+ }
+
+ {
+ let prefix = &actual[0].id().to_string()[..8];
+ let prefixed = list::<NonEmpty<Entry>, _>(&storage, &typename, Some(prefix)).unwrap();
+ let expected = actual
+ .iter()
+ .filter(|cob| cob.id().to_string().starts_with(prefix))
+ .map(|cob| *cob.id())
+ .collect::<Vec<_>>();
+ let actual = prefixed.iter().map(|cob| *cob.id()).collect::<Vec<_>>();
+
+ assert_eq!(actual, expected);
+ }
}
#[test]
diff --git a/crates/radicle/src/cob/store.rs b/crates/radicle/src/cob/store.rs
index 3a0fd102c9..681925f8fa 100644
--- a/crates/radicle/src/cob/store.rs
+++ b/crates/radicle/src/cob/store.rs
@@ -394,7 +394,7 @@ where
impl ExactSizeIterator<Item = Result<(ObjectId, T), Error>> + use<'a, T, Repo, Access>,
Error,
> {
- let raw = cob::list::<T, _>(self.repo, self.scope.type_name)?;
+ let raw = cob::list::<T, _>(self.repo, self.scope.type_name, None)?;
Ok(raw.into_iter().map(|o| Ok((*o.id(), o.object))))
}
@@ -406,7 +406,7 @@ where
/// Return objects count.
pub fn count(&self) -> Result<usize, Error> {
- let raw = cob::list::<T, _>(self.repo, self.scope.type_name)?;
+ let raw = cob::list::<T, _>(self.repo, self.scope.type_name, None)?;
Ok(raw.len())
}
diff --git a/crates/radicle/src/storage/git/cob.rs b/crates/radicle/src/storage/git/cob.rs
index 01f191e8fd..070f0ebcbf 100644
--- a/crates/radicle/src/storage/git/cob.rs
+++ b/crates/radicle/src/storage/git/cob.rs
@@ -108,6 +108,35 @@ impl cob::object::Storage for Repository {
Ok(refs.into())
}
+ fn objects_by_prefix(
+ &self,
+ typename: &cob::TypeName,
+ object_id_prefix: &str,
+ ) -> Result<BTreeMap<ObjectId, Objects>, Self::ObjectsError> {
+ let glob = format!("refs/namespaces/*/refs/cobs/{typename}/{object_id_prefix}*");
+ let references = self.backend.references_glob(&glob)?;
+ let mut objects_map: BTreeMap<ObjectId, Objects> = BTreeMap::new();
+
+ for reference in references {
+ let reference = reference.map_err(Self::ObjectsError::from)?;
+ let Ok(name) = reference.name() else {
+ continue;
+ };
+
+ if let Ok(name) = RefStr::try_from_str(name)
+ && let Some((_, object_id)) = cob::object::parse_refstr(&name) {
+ let obj_ref = cob::object::Reference::try_from(reference)
+ .map_err(Self::ObjectsError::from)?;
+ objects_map
+ .entry(object_id)
+ .and_modify(|objs: &mut Objects| objs.push(obj_ref.clone()))
+ .or_insert_with(|| Objects::new(obj_ref));
+ }
+ }
+
+ Ok(objects_map)
+ }
+
fn types(
&self,
typename: &cob::TypeName,
@@ -421,6 +450,45 @@ impl<R: storage::WriteRepository> cob::object::Storage for DraftStore<'_, R> {
Ok(objs)
}
+ fn objects_by_prefix(
+ &self,
+ typename: &cob::TypeName,
+ object_id_prefix: &str,
+ ) -> Result<BTreeMap<ObjectId, Objects>, Self::ObjectsError> {
+ let signed_glob = format!("refs/namespaces/*/refs/cobs/{typename}/{object_id_prefix}*");
+ let draft_glob = format!(
+ "refs/namespaces/{}/refs/drafts/cobs/{typename}/{object_id_prefix}*",
+ self.remote
+ );
+ let mut objects = BTreeMap::new();
+
+ for reference in self
+ .repo
+ .raw()
+ .references_glob(&signed_glob)?
+ .chain(self.repo.raw().references_glob(&draft_glob)?)
+ {
+ let reference = reference.map_err(Self::ObjectsError::from)?;
+ let Some(object_id) = reference
+ .name()
+ .ok()
+ .and_then(|name| name.rsplit('/').next())
+ .and_then(|id| id.parse::<ObjectId>().ok())
+ else {
+ continue;
+ };
+ let object_ref =
+ cob::object::Reference::try_from(reference).map_err(Self::ObjectsError::from)?;
+
+ objects
+ .entry(object_id)
+ .and_modify(|refs: &mut Objects| refs.push(object_ref.clone()))
+ .or_insert_with(|| Objects::new(object_ref));
+ }
+
+ Ok(objects)
+ }
+
fn types(
&self,
_typename: &cob::TypeName,
diff --git a/crates/radicle/src/test/storage.rs b/crates/radicle/src/test/storage.rs
index 7755828d1c..ee29d43049 100644
--- a/crates/radicle/src/test/storage.rs
+++ b/crates/radicle/src/test/storage.rs
@@ -413,6 +413,42 @@ impl radicle_cob::object::Storage for MockRepository {
todo!()
}
+ fn objects_by_prefix(
+ &self,
+ typename: &radicle_cob::TypeName,
+ object_id_prefix: &str,
+ ) -> Result<
+ std::collections::BTreeMap<radicle_cob::ObjectId, radicle_cob::object::Objects>,
+ Self::ObjectsError,
+ > {
+ let mut objects = std::collections::BTreeMap::new();
+
+ for refs in self.remotes.values() {
+ for (name, target) in refs.refs().clone() {
+ let Some((ref_typename, object_id)) = radicle_cob::object::parse_refstr(&name)
+ else {
+ continue;
+ };
+ if ref_typename != *typename || !object_id.to_string().starts_with(object_id_prefix)
+ {
+ continue;
+ }
+ let reference = radicle_cob::object::Reference {
+ name,
+ target: radicle_cob::object::Commit { id: target },
+ };
+ objects
+ .entry(object_id)
+ .and_modify(|refs: &mut radicle_cob::object::Objects| {
+ refs.push(reference.clone())
+ })
+ .or_insert_with(|| radicle_cob::object::Objects::new(reference));
+ }
+ }
+
+ Ok(objects)
+ }
+
fn types(
&self,
_typename: &radicle_cob::TypeName,
Exit code: 0
shell: 'export RUSTDOCFLAGS=''-D warnings'' cargo --version rustc --version cargo fmt --check cargo clippy --all-targets --workspace -- --deny warnings cargo build --all-targets --workspace cargo doc --workspace --no-deps --all-features cargo test --workspace --no-fail-fast '
Commands:
$ podman run --name 7efd60ce-81f8-4590-b98d-c6df7f2e77fd -v /opt/radcis/ci.rad.levitte.org/cci/state/7efd60ce-81f8-4590-b98d-c6df7f2e77fd/s:/7efd60ce-81f8-4590-b98d-c6df7f2e77fd/s:ro -v /opt/radcis/ci.rad.levitte.org/cci/state/7efd60ce-81f8-4590-b98d-c6df7f2e77fd/w:/7efd60ce-81f8-4590-b98d-c6df7f2e77fd/w -w /7efd60ce-81f8-4590-b98d-c6df7f2e77fd/w -v /opt/radcis/ci.rad.levitte.org/.radicle:/${id}/.radicle:ro -e RAD_HOME=/${id}/.radicle rust:trixie bash /7efd60ce-81f8-4590-b98d-c6df7f2e77fd/s/script.sh
+ export 'RUSTDOCFLAGS=-D warnings'
+ RUSTDOCFLAGS='-D warnings'
+ cargo --version
info: syncing channel updates for '1.97.1-x86_64-unknown-linux-gnu'
info: latest update on 2026-07-16, rust version 1.97.1 (8bab26f4f 2026-07-14)
info: downloading component 'cargo'
info: downloading component 'clippy'
info: downloading component 'rust-docs'
info: downloading component 'rust-src'
info: downloading component 'rust-std'
info: downloading component 'rustc'
info: downloading component 'rustfmt'
info: installing component 'cargo'
info: installing component 'clippy'
info: installing component 'rust-docs'
info: installing component 'rust-src'
info: installing component 'rust-std'
info: installing component 'rustc'
info: installing component 'rustfmt'
cargo 1.97.1 (c980f4866 2026-06-30)
+ rustc --version
rustc 1.97.1 (8bab26f4f 2026-07-14)
+ cargo fmt --check
+ cargo clippy --all-targets --workspace -- --deny warnings
Updating crates.io index
Downloading crates ...
Downloaded data-encoding-macro v0.1.19
Downloaded clap_lex v1.1.0
Downloaded colorchoice v1.0.5
Downloaded clap_derive v4.6.0
Downloaded flate2 v1.1.9
Downloaded crypto-common v0.1.7
Downloaded fnv v1.0.7
Downloaded gix-refspec v0.41.0
Downloaded curve25519-dalek-derive v0.1.1
Downloaded convert_case v0.10.0
Downloaded cipher v0.4.4
Downloaded const-str v0.4.3
Downloaded data-encoding v2.10.0
Downloaded console v0.16.3
Downloaded gix-sec v0.14.0
Downloaded gix-protocol v0.61.0
Downloaded cypheraddr v0.4.1
Downloaded data-encoding-macro-internal v0.1.17
Downloaded clap_complete v4.6.0
Downloaded cpufeatures v0.2.17
Downloaded clap v4.6.0
Downloaded addr2line v0.25.1
Downloaded der v0.7.10
Downloaded qcheck-macros v1.0.0
Downloaded rand v0.8.5
Downloaded derive_more v2.1.1
Downloaded colored v2.2.0
Downloaded const-oid v0.9.6
Downloaded crypto-bigint v0.5.5
Downloaded smallvec v1.15.1
Downloaded socket2 v0.5.10
Downloaded clap_builder v4.6.0
Downloaded ctr v0.9.2
Downloaded regex v1.12.3
Downloaded rfc6979 v0.4.0
Downloaded env_filter v1.0.0
Downloaded chrono v0.4.44
Downloaded cyphernet v0.5.4
Downloaded salsa20 v0.10.2
Downloaded ghash v0.5.1
Downloaded ed25519 v1.5.3
Downloaded escargot v0.5.15
Downloaded gix-fs v0.21.1
Downloaded gix-revwalk v0.31.0
Downloaded curve25519-dalek v4.1.3
Downloaded gix-path v0.12.0
Downloaded rusty-fork v0.3.1
Downloaded gix-credentials v0.38.0
Downloaded gix-negotiate v0.31.0
Downloaded crc32fast v1.5.0
Downloaded gix-features v0.48.0
Downloaded gix-lock v23.0.0
Downloaded rustc_version v0.4.1
Downloaded form_urlencoded v1.2.2
Downloaded env_logger v0.11.9
Downloaded equivalent v1.0.2
Downloaded dyn-clone v1.0.20
Downloaded quick-error v1.2.3
Downloaded qcheck v1.0.0
Downloaded gix-command v0.9.0
Downloaded gix-config-value v0.18.0
Downloaded ryu v1.0.23
Downloaded ff v0.13.1
Downloaded gix-actor v0.41.0
Downloaded generic-array v0.14.7
Downloaded errno v0.3.14
Downloaded displaydoc v0.2.5
Downloaded fancy-regex v0.14.0
Downloaded gix-commitgraph v0.37.0
Downloaded fastrand v2.3.0
Downloaded gix-quote v0.7.1
Downloaded fast-glob v0.3.3
Downloaded sem_safe v0.2.1
Downloaded derive_more-impl v2.1.1
Downloaded bytecount v0.6.9
Downloaded crossbeam-utils v0.8.21
Downloaded rustc-demangle v0.1.27
Downloaded same-file v1.0.6
Downloaded schemars v1.2.1
Downloaded gix-glob v0.26.0
Downloaded gix-prompt v0.15.0
Downloaded gix-hashtable v0.15.0
Downloaded schemars_derive v1.2.1
Downloaded faster-hex v0.10.0
Downloaded gix-utils v0.3.2
Downloaded scopeguard v1.2.0
Downloaded dunce v1.0.5
Downloaded gix-chunk v0.7.1
Downloaded siphasher v1.0.2
Downloaded fluent-uri v0.3.2
Downloaded getrandom v0.4.3
Downloaded gix-error v0.2.3
Downloaded quote v1.0.45
Downloaded rustversion v1.0.22
Downloaded cyphergraphy v0.3.1
Downloaded ed25519 v2.2.3
Downloaded find-msvc-tools v0.1.9
Downloaded gix-revision v0.45.0
Downloaded strsim v0.11.1
Downloaded subtle v2.6.1
Downloaded universal-hash v0.5.1
Downloaded num-cmp v0.1.0
Downloaded is_executable v1.0.6
Downloaded match-lookup v0.1.2
Downloaded outref v0.5.2
Downloaded serde-untagged v0.1.9
Downloaded snapbox-macros v1.1.0
Downloaded getrandom v0.2.17
Downloaded erased-serde v0.4.10
Downloaded document-features v0.2.12
Downloaded gix-packetline v0.21.3
Downloaded ssh-encoding v0.2.0
Downloaded scrypt v0.11.0
Downloaded cbc v0.1.2
Downloaded either v1.15.0
Downloaded gix-diff v0.63.0
Downloaded opaque-debug v0.3.1
Downloaded potential_utf v0.1.4
Downloaded sval_serde v2.17.0
Downloaded digest v0.10.7
Downloaded gix-hash v0.25.0
Downloaded referencing v0.30.0
Downloaded rand_core v0.9.5
Downloaded thiserror v2.0.18
Downloaded sval_ref v2.17.0
Downloaded ecdsa v0.16.9
Downloaded secrecy v0.10.3
Downloaded stable_deref_trait v1.2.1
Downloaded email_address v0.2.9
Downloaded signature v2.2.0
Downloaded jobserver v0.1.34
Downloaded diff v0.1.13
Downloaded ref-cast-impl v1.0.25
Downloaded shell-words v1.1.1
Downloaded sval_dynamic v2.17.0
Downloaded gix-date v0.15.3
Downloaded value-bag-sval2 v1.12.0
Downloaded sval_fmt v2.17.0
Downloaded getrandom v0.3.4
Downloaded gix-ref v0.63.0
Downloaded pkg-config v0.3.32
Downloaded nu-ansi-term v0.50.3
Downloaded signal-hook-mio v0.2.5
Downloaded wait-timeout v0.2.1
Downloaded ssh-cipher v0.2.0
Downloaded socks5-client v0.4.3
Downloaded test-log v0.2.19
Downloaded memmap2 v0.9.10
Downloaded test-log-macros v0.2.19
Downloaded ref-cast v1.0.25
Downloaded signature v1.6.4
Downloaded num-rational v0.4.2
Downloaded thread_local v1.1.9
Downloaded hmac v0.12.1
Downloaded rand_xorshift v0.4.0
Downloaded ec25519 v0.1.0
Downloaded elliptic-curve v0.13.8
Downloaded synstructure v0.13.2
Downloaded thiserror v1.0.69
Downloaded base16ct v0.2.0
Downloaded gix-validate v0.11.1
Downloaded base-x v0.2.11
Downloaded sha1 v0.10.6
Downloaded num-integer v0.1.46
Downloaded siphasher v0.3.11
Downloaded serde_fmt v1.1.0
Downloaded walkdir v2.5.0
Downloaded proc-macro2 v1.0.106
Downloaded gix-odb v0.80.0
Downloaded signal-hook-registry v1.4.8
Downloaded tinyvec_macros v0.1.1
Downloaded serde_spanned v1.0.4
Downloaded pbkdf2 v0.12.2
Downloaded sval_json v2.17.0
Downloaded rand_chacha v0.3.1
Downloaded systemd-journal-logger v2.2.2
Downloaded rand_chacha v0.9.0
Downloaded sqlite v0.37.0
Downloaded gix-tempfile v23.0.0
Downloaded keccak v0.1.6
Downloaded nonempty v0.9.0
Downloaded writeable v0.6.2
Downloaded zerovec-derive v0.11.2
Downloaded anstyle-parse v0.2.7
Downloaded base64ct v1.8.3
Downloaded bytesize v2.3.1
Downloaded chacha20poly1305 v0.10.1
Downloaded gix-object v0.60.0
Downloaded gix-transport v0.57.0
Downloaded icu_locale_core v2.1.1
Downloaded phf_shared v0.11.3
Downloaded sec1 v0.7.3
Downloaded semver v1.0.27
Downloaded sharded-slab v0.1.7
Downloaded structured-logger v1.0.5
Downloaded sval_buffer v2.17.0
Downloaded timeago v0.4.2
Downloaded block-buffer v0.10.4
Downloaded crossbeam-channel v0.5.15
Downloaded fraction v0.15.3
Downloaded gix-pack v0.70.0
Downloaded heapless v0.8.0
Downloaded itoa v1.0.17
Downloaded lazy_static v1.5.0
Downloaded typeid v1.0.3
Downloaded base256emoji v1.0.2
Downloaded lock_api v0.4.14
Downloaded maybe-async v0.2.10
Downloaded rand v0.9.2
Downloaded serde_derive_internals v0.29.1
Downloaded shlex v1.3.0
Downloaded streaming-iterator v0.1.9
Downloaded multibase v0.9.2
Downloaded sqlite3-sys v0.18.0
Downloaded gix-shallow v0.12.0
Downloaded tree-sitter-language v0.1.7
Downloaded thiserror-impl v2.0.18
Downloaded borrow-or-share v0.2.4
Downloaded yoke v0.8.1
Downloaded block-padding v0.3.3
Downloaded gix-trace v0.1.19
Downloaded memchr v2.8.0
Downloaded inquire v0.9.4
Downloaded ed25519-dalek v2.2.0
Downloaded anstyle-query v1.1.5
Downloaded thiserror-impl v1.0.69
Downloaded simd-adler32 v0.3.8
Downloaded spki v0.7.3
Downloaded version_check v0.9.5
Downloaded unicode-display-width v0.3.0
Downloaded zmij v1.0.21
Downloaded nonempty v0.12.0
Downloaded num-iter v0.1.45
Downloaded sha2 v0.10.9
Downloaded sval_nested v2.17.0
Downloaded inout v0.1.4
Downloaded zerofrom-derive v0.1.6
Downloaded vsimd v0.8.0
Downloaded once_cell v1.21.4
Downloaded signal-hook v0.3.18
Downloaded signals_receipts v0.2.5
Downloaded snapbox v1.2.2
Downloaded ppv-lite86 v0.2.21
Downloaded yansi v1.0.1
Downloaded tempfile v3.27.0
Downloaded gix-traverse v0.57.0
Downloaded icu_provider v2.1.1
Downloaded pem-rfc7468 v0.7.0
Downloaded rand_core v0.6.4
Downloaded toml_writer v1.0.7+spec-1.1.0
Downloaded unit-prefix v0.5.2
Downloaded heck v0.5.0
Downloaded num v0.4.3
Downloaded crossterm v0.29.0
Downloaded anyhow v1.0.102
Downloaded emojis v0.6.4
Downloaded percent-encoding v2.3.2
Downloaded gix-url v0.36.0
Downloaded anstream v0.6.21
Downloaded lexopt v0.3.2
Downloaded rsa v0.9.10
Downloaded bcrypt-pbkdf v0.10.0
Downloaded pkcs8 v0.10.2
Downloaded humantime v2.3.0
Downloaded icu_properties v2.1.2
Downloaded typenum v1.20.1
Downloaded anstream v1.0.0
Downloaded phf v0.11.3
Downloaded human-panic v2.0.6
Downloaded p256 v0.13.2
Downloaded is_terminal_polyfill v1.70.2
Downloaded uuid-simd v0.8.0
Downloaded indexmap v2.13.0
Downloaded anstyle-parse v1.0.0
Downloaded num-complex v0.4.6
Downloaded primeorder v0.13.6
Downloaded unarray v0.1.4
Downloaded idna_adapter v1.2.1
Downloaded tree-sitter-highlight v0.24.7
Downloaded noise-framework v0.4.1
Downloaded litrs v1.0.0
Downloaded amplify_num v0.5.3
Downloaded tree-sitter-go v0.23.4
Downloaded pretty_assertions v1.4.1
Downloaded zeroize v1.9.0
Downloaded spin v0.9.8
Downloaded unicode-normalization v0.1.25
Downloaded yoke-derive v0.8.1
Downloaded tree-sitter-html v0.23.2
Downloaded zerofrom v0.1.6
Downloaded parking_lot v0.12.5
Downloaded tree-sitter-toml-ng v0.6.0
Downloaded toml v0.9.12+spec-1.1.0
Downloaded unicode-ident v1.0.24
Downloaded utf8_iter v1.0.4
Downloaded utf8parse v0.2.2
Downloaded value-bag-serde1 v1.12.0
Downloaded arc-swap v1.9.1
Downloaded adler2 v2.0.1
Downloaded tree-sitter-css v0.23.2
Downloaded url v2.5.8
Downloaded hex-literal v1.1.0
Downloaded matchers v0.2.0
Downloaded tree-sitter-json v0.24.8
Downloaded aead v0.5.2
Downloaded base32 v0.4.0
Downloaded hash32 v0.3.1
Downloaded iana-time-zone v0.1.65
Downloaded group v0.13.0
Downloaded amplify_syn v2.0.1
Downloaded ssh-agent-lib v0.6.0
Downloaded anstyle v1.0.14
Downloaded backtrace v0.3.76
Downloaded pastey v0.2.1
Downloaded cfg-if v1.0.4
Downloaded normalize-line-endings v0.3.0
Downloaded pkcs1 v0.7.5
Downloaded byteorder v1.5.0
Downloaded litemap v0.8.1
Downloaded uuid v1.22.0
Downloaded icu_properties_data v2.1.2
Downloaded serde_core v1.0.228
Downloaded bitflags v2.11.0
Downloaded ahash v0.8.12
Downloaded autocfg v1.5.0
Downloaded pin-project-lite v0.2.17
Downloaded amplify_derive v4.0.1
Downloaded serde v1.0.228
Downloaded mio v1.1.1
Downloaded ascii v1.1.0
Downloaded serde_derive v1.0.228
Downloaded tracing-core v0.1.36
Downloaded num-bigint v0.4.6
Downloaded tinystr v0.8.2
Downloaded amplify v4.9.0
Downloaded value-bag v1.12.0
Downloaded toml_datetime v0.7.5+spec-1.1.0
Downloaded num-traits v0.2.19
Downloaded unicode-segmentation v1.12.0
Downloaded ssh-key v0.6.7
Downloaded zerotrie v0.2.3
Downloaded base64 v0.22.1
Downloaded chacha20 v0.9.1
Downloaded tree-sitter v0.24.7
Downloaded git2 v0.21.0
Downloaded parking_lot_core v0.9.12
Downloaded aes-gcm v0.10.3
Downloaded num-bigint-dig v0.8.6
Downloaded bit-set v0.8.0
Downloaded polyval v0.6.2
Downloaded tracing-log v0.2.0
Downloaded poly1305 v0.8.0
Downloaded jiff-static v0.2.23
Downloaded bit-vec v0.8.0
Downloaded blowfish v0.9.1
Downloaded sval v2.17.0
Downloaded aes v0.8.4
Downloaded icu_collections v2.1.1
Downloaded gimli v0.32.3
Downloaded libm v0.2.16
Downloaded log v0.4.29
Downloaded zlib-rs v0.6.5
Downloaded similar v3.1.1
Downloaded proptest v1.10.0
Downloaded indicatif v0.18.4
Downloaded p384 v0.13.1
Downloaded portable-atomic v1.13.1
Downloaded tinyvec v1.11.0
Downloaded tracing-subscriber v0.3.23
Downloaded vcpkg v0.2.15
Downloaded aho-corasick v1.1.4
Downloaded icu_normalizer_data v2.1.1
Downloaded bytes v1.11.1
Downloaded rustix v1.1.4
Downloaded bstr v1.12.1
Downloaded unicode-width v0.2.2
Downloaded zerocopy v0.8.42
Downloaded icu_normalizer v2.1.1
Downloaded base64 v0.21.7
Downloaded miniz_oxide v0.8.9
Downloaded cc v1.2.57
Downloaded object v0.37.3
Downloaded tree-sitter-md v0.3.2
Downloaded tree-sitter-rust v0.23.3
Downloaded prodash v31.0.0
Downloaded zerovec v0.11.5
Downloaded hashbrown v0.16.1
Downloaded jsonschema v0.30.0
Downloaded serde_json v1.0.149
Downloaded libc v0.2.183
Downloaded tree-sitter-typescript v0.23.2
Downloaded jiff v0.2.23
Downloaded tokio v1.50.0
Downloaded tree-sitter-python v0.23.6
Downloaded p521 v0.13.3
Downloaded idna v1.1.0
Downloaded itertools v0.14.0
Downloaded syn v1.0.109
Downloaded sysinfo v0.37.2
Downloaded tree-sitter-c v0.23.4
Downloaded syn v2.0.117
Downloaded regex-syntax v0.8.10
Downloaded bloomy v1.2.0
Downloaded tree-sitter-bash v0.23.3
Downloaded tracing v0.1.44
Downloaded tree-sitter-ruby v0.23.1
Downloaded regex-automata v0.4.14
Downloaded sha1-checked v0.10.0
Downloaded sha3 v0.10.8
Downloaded libz-sys v1.1.25
Downloaded libgit2-sys v0.18.4+1.9.3
Downloaded sqlite3-src v0.7.0
Downloaded linux-raw-sys v0.12.1
Compiling libc v0.2.183
Compiling proc-macro2 v1.0.106
Compiling quote v1.0.45
Compiling unicode-ident v1.0.24
Compiling serde_core v1.0.228
Checking cfg-if v1.0.4
Compiling serde v1.0.228
Compiling version_check v0.9.5
Compiling syn v2.0.117
Compiling generic-array v0.14.7
Checking typenum v1.20.1
Checking getrandom v0.2.17
Checking rand_core v0.6.4
Checking memchr v2.8.0
Compiling find-msvc-tools v0.1.9
Compiling shlex v1.3.0
Compiling jobserver v0.1.34
Checking subtle v2.6.1
Checking const-oid v0.9.6
Checking smallvec v1.15.1
Checking regex-syntax v0.8.10
Compiling cc v1.2.57
Checking aho-corasick v1.1.4
Checking cpufeatures v0.2.17
Compiling thiserror v2.0.18
Checking fastrand v2.3.0
Compiling parking_lot_core v0.9.12
Checking regex-automata v0.4.14
Checking scopeguard v1.2.0
Checking lock_api v0.4.14
Checking bitflags v2.11.0
Checking parking_lot v0.12.5
Checking stable_deref_trait v1.2.1
Compiling typeid v1.0.3
Compiling erased-serde v0.4.10
Checking tinyvec_macros v0.1.1
Checking gix-trace v0.1.19
Checking itoa v1.0.17
Checking tinyvec v1.11.0
Checking serde_fmt v1.1.0
Checking hashbrown v0.16.1
Checking unicode-normalization v0.1.25
Checking value-bag-serde1 v1.12.0
Checking byteorder v1.5.0
Checking value-bag v1.12.0
Checking gix-utils v0.3.2
Checking log v0.4.29
Compiling crc32fast v1.5.0
Checking bstr v1.12.1
Compiling serde_derive v1.0.228
Compiling thiserror-impl v2.0.18
Checking same-file v1.0.6
Checking walkdir v2.5.0
Checking prodash v31.0.0
Checking gix-validate v0.11.1
Checking zlib-rs v0.6.5
Compiling pkg-config v0.3.32
Compiling libm v0.2.16
Checking gix-path v0.12.0
Compiling heapless v0.8.0
Compiling autocfg v1.5.0
Checking hash32 v0.3.1
Checking gix-features v0.48.0
Compiling rustix v1.1.4
Compiling num-traits v0.2.19
Checking linux-raw-sys v0.12.1
Checking faster-hex v0.10.0
Compiling getrandom v0.4.3
Compiling zerocopy v0.8.42
Compiling zmij v1.0.21
Checking equivalent v1.0.2
Compiling serde_json v1.0.149
Checking zeroize v1.9.0
Checking indexmap v2.13.0
Checking crypto-common v0.1.7
Checking block-buffer v0.10.4
Checking digest v0.10.7
Checking sha1 v0.10.6
Compiling ref-cast v1.0.25
Checking sha1-checked v0.10.0
Checking once_cell v1.21.4
Checking gix-hash v0.25.0
Checking block-padding v0.3.3
Compiling ref-cast-impl v1.0.25
Checking inout v0.1.4
Checking sha2 v0.10.9
Checking dyn-clone v1.0.20
Compiling vcpkg v0.2.15
Checking cipher v0.4.4
Checking tempfile v3.27.0
Compiling serde_derive_internals v0.29.1
Checking der v0.7.10
Compiling libz-sys v1.1.25
Compiling libgit2-sys v0.18.4+1.9.3
Checking ppv-lite86 v0.2.21
Checking spin v0.9.8
Compiling schemars_derive v1.2.1
Checking lazy_static v1.5.0
Checking rand_chacha v0.3.1
Compiling syn v1.0.109
Checking rand v0.8.5
Compiling tree-sitter-language v0.1.7
Checking hmac v0.12.1
Checking universal-hash v0.5.1
Checking num-integer v0.1.46
Checking opaque-debug v0.3.1
Checking spki v0.7.3
Checking signature v2.2.0
Checking ff v0.13.1
Checking schemars v1.2.1
Checking base16ct v0.2.0
Checking sec1 v0.7.3
Checking group v0.13.0
Checking crypto-bigint v0.5.5
Compiling data-encoding v2.10.0
Compiling data-encoding-macro-internal v0.1.17
Checking elliptic-curve v0.13.8
Compiling amplify_syn v2.0.1
Checking num-iter v0.1.45
Checking aead v0.5.2
Compiling match-lookup v0.1.2
Checking const-str v0.4.3
Compiling semver v1.0.27
Checking signature v1.6.4
Checking ed25519 v1.5.3
Compiling rustc_version v0.4.1
Checking base256emoji v1.0.2
Checking data-encoding-macro v0.1.19
Compiling amplify_derive v4.0.1
Checking poly1305 v0.8.0
Checking rfc6979 v0.4.0
Checking qcheck v1.0.0
Checking chacha20 v0.9.1
Checking gix-error v0.2.3
Checking ascii v1.1.0
Checking base-x v0.2.11
Checking amplify_num v0.5.3
Checking multibase v0.9.2
Checking ecdsa v0.16.9
Compiling curve25519-dalek v4.1.3
Checking ec25519 v0.1.0
Checking primeorder v0.13.6
Checking amplify v4.9.0
Checking polyval v0.6.2
Compiling num-bigint-dig v0.8.6
Checking base64ct v1.8.3
Checking cyphergraphy v0.3.1
Checking ghash v0.5.1
Checking pkcs8 v0.10.2
Checking pem-rfc7468 v0.7.0
Checking pbkdf2 v0.12.2
Checking aes v0.8.4
Checking ctr v0.9.2
Checking radicle-git-ref-format v0.2.0 (/7efd60ce-81f8-4590-b98d-c6df7f2e77fd/w/crates/radicle-git-ref-format)
Compiling sqlite3-src v0.7.0
Compiling curve25519-dalek-derive v0.1.1
Compiling synstructure v0.13.2
Checking keccak v0.1.6
Checking sha3 v0.10.8
Checking aes-gcm v0.10.3
Checking ssh-encoding v0.2.0
Checking pkcs1 v0.7.5
Checking ed25519 v2.2.3
Checking blowfish v0.9.1
Checking cbc v0.1.2
Checking percent-encoding v2.3.2
Checking base32 v0.4.0
Checking rsa v0.9.10
Checking cypheraddr v0.4.1
Checking ssh-cipher v0.2.0
Checking bcrypt-pbkdf v0.10.0
Checking ed25519-dalek v2.2.0
Compiling zerofrom-derive v0.1.6
Checking p256 v0.13.2
Checking p384 v0.13.1
Checking p521 v0.13.3
Checking chacha20poly1305 v0.10.1
Checking noise-framework v0.4.1
Checking zerofrom v0.1.6
Checking ssh-key v0.6.7
Checking socks5-client v0.4.3
Compiling yoke-derive v0.8.1
Checking secrecy v0.10.3
Checking ssh-agent-lib v0.6.0
Checking yoke v0.8.1
Checking cyphernet v0.5.4
Checking nonempty v0.9.0
Checking anstyle-query v1.1.5
Checking utf8parse v0.2.2
Checking jiff v0.2.23
Compiling zerovec-derive v0.11.2
Checking zerovec v0.11.5
Checking radicle-localtime v0.1.0 (/7efd60ce-81f8-4590-b98d-c6df7f2e77fd/w/crates/radicle-localtime)
Compiling displaydoc v0.2.5
Checking errno v0.3.14
Checking anstyle v1.0.14
Checking base64 v0.21.7
Checking gix-date v0.15.3
Checking colorchoice v1.0.5
Checking is_terminal_polyfill v1.70.2
Checking gix-hashtable v0.15.0
Checking gix-actor v0.41.0
Checking siphasher v1.0.2
Checking gix-object v0.60.0
Checking radicle-dag v0.10.0 (/7efd60ce-81f8-4590-b98d-c6df7f2e77fd/w/crates/radicle-dag)
Checking memmap2 v0.9.10
Checking nonempty v0.12.0
Checking tinystr v0.8.2
Checking gix-chunk v0.7.1
Checking litemap v0.8.1
Checking writeable v0.6.2
Compiling radicle v0.25.1 (/7efd60ce-81f8-4590-b98d-c6df7f2e77fd/w/crates/radicle)
Checking icu_locale_core v2.1.1
Checking gix-commitgraph v0.37.0
Checking zerotrie v0.2.3
Checking potential_utf v0.1.4
Checking anstyle-parse v1.0.0
Checking serde-untagged v0.1.9
Checking bytesize v2.3.1
Compiling icu_normalizer_data v2.1.1
Checking fast-glob v0.3.3
Checking dunce v1.0.5
Compiling icu_properties_data v2.1.2
Checking anstream v1.0.0
Checking icu_provider v2.1.1
Checking icu_collections v2.1.1
Checking gix-revwalk v0.31.0
Checking gix-fs v0.21.1
Checking mio v1.1.1
Checking sem_safe v0.2.1
Checking adler2 v2.0.1
Checking simd-adler32 v0.3.8
Checking miniz_oxide v0.8.9
Checking signals_receipts v0.2.5
Checking gix-tempfile v23.0.0
Checking gix-quote v0.7.1
Checking icu_properties v2.1.2
Checking icu_normalizer v2.1.1
Checking either v1.15.0
Checking iana-time-zone v0.1.65
Checking shell-words v1.1.1
Compiling unicode-segmentation v1.12.0
Compiling signal-hook v0.3.18
Compiling convert_case v0.10.0
Checking idna_adapter v1.2.1
Checking gix-command v0.9.0
Checking chrono v0.4.44
Checking radicle-signals v0.12.1 (/7efd60ce-81f8-4590-b98d-c6df7f2e77fd/w/crates/radicle-signals)
Checking signal-hook-registry v1.4.8
Checking colored v2.2.0
Compiling getrandom v0.3.4
Compiling rustversion v1.0.22
Checking utf8_iter v1.0.4
Compiling object v0.37.3
Checking idna v1.1.0
Compiling derive_more-impl v2.1.1
Checking gix-lock v23.0.0
Checking gix-url v0.36.0
Checking gix-config-value v0.18.0
Checking gix-sec v0.14.0
Checking gimli v0.32.3
Checking unicode-width v0.2.2
Compiling thiserror v1.0.69
Compiling portable-atomic v1.13.1
Compiling litrs v1.0.0
Compiling document-features v0.2.12
Checking addr2line v0.25.1
Checking gix-prompt v0.15.0
Checking derive_more v2.1.1
Checking signal-hook-mio v0.2.5
Checking radicle-log v0.2.0 (/7efd60ce-81f8-4590-b98d-c6df7f2e77fd/w/crates/radicle-log)
Checking gix-traverse v0.57.0
Checking gix-revision v0.45.0
Checking gix-diff v0.63.0
Checking anstyle-parse v0.2.7
Checking gix-packetline v0.21.3
Checking gix-glob v0.26.0
Compiling thiserror-impl v1.0.69
Checking rustc-demangle v0.1.27
Checking gix-refspec v0.41.0
Checking backtrace v0.3.76
Checking gix-transport v0.57.0
Checking anstream v0.6.21
Checking gix-pack v0.70.0
Checking arc-swap v1.9.1
Checking crossterm v0.29.0
Checking gix-credentials v0.38.0
Checking console v0.16.3
Checking gix-ref v0.63.0
Checking gix-shallow v0.12.0
Checking gix-negotiate v0.31.0
Checking form_urlencoded v1.2.2
Compiling maybe-async v0.2.10
Checking regex v1.12.3
Compiling tree-sitter v0.24.7
Checking unit-prefix v0.5.2
Checking indicatif v0.18.4
Checking gix-protocol v0.61.0
Checking url v2.5.8
Checking gix-odb v0.80.0
Checking inquire v0.9.4
Checking unicode-display-width v0.3.0
Checking uuid v1.22.0
Checking bytes v1.11.1
Checking snapbox-macros v1.1.0
Checking salsa20 v0.10.2
Checking similar v3.1.1
Checking clap_lex v1.1.0
Compiling heck v0.5.0
Checking strsim v0.11.1
Checking normalize-line-endings v0.3.0
Checking streaming-iterator v0.1.9
Checking siphasher v0.3.11
Compiling crossbeam-utils v0.8.21
Checking bloomy v1.2.0
Checking snapbox v1.2.2
Checking clap_builder v4.6.0
Compiling clap_derive v4.6.0
Checking scrypt v0.11.0
Checking systemd-journal-logger v2.2.2
Compiling tree-sitter-md v0.3.2
Compiling tree-sitter-go v0.23.4
Compiling tree-sitter-bash v0.23.3
Compiling tree-sitter-python v0.23.6
Compiling tree-sitter-toml-ng v0.6.0
Compiling tree-sitter-ruby v0.23.1
Compiling tree-sitter-c v0.23.4
Compiling tree-sitter-css v0.23.2
Compiling tree-sitter-rust v0.23.3
Compiling tree-sitter-html v0.23.2
Compiling tree-sitter-typescript v0.23.2
Compiling tree-sitter-json v0.24.8
Checking serde_spanned v1.0.4
Checking toml_datetime v0.7.5+spec-1.1.0
Checking pin-project-lite v0.2.17
Compiling anyhow v1.0.102
Checking bit-vec v0.8.0
Checking toml_writer v1.0.7+spec-1.1.0
Checking bit-set v0.8.0
Checking toml v0.9.12+spec-1.1.0
Checking tokio v1.50.0
Checking sqlite3-sys v0.18.0
Checking sqlite v0.37.0
Checking radicle-crypto v0.19.0 (/7efd60ce-81f8-4590-b98d-c6df7f2e77fd/w/crates/radicle-crypto)
Checking clap v4.6.0
Checking rand_core v0.9.5
Checking sysinfo v0.37.2
Compiling radicle-node v0.21.1 (/7efd60ce-81f8-4590-b98d-c6df7f2e77fd/w/crates/radicle-node)
Compiling radicle-cli v0.23.0 (/7efd60ce-81f8-4590-b98d-c6df7f2e77fd/w/crates/radicle-cli)
Checking is_executable v1.0.6
Checking diff v0.1.13
Checking yansi v1.0.1
Checking clap_complete v4.6.0
Checking pretty_assertions v1.4.1
Checking human-panic v2.0.6
Checking crossbeam-channel v0.5.15
Checking structured-logger v1.0.5
Checking radicle-systemd v0.13.0 (/7efd60ce-81f8-4590-b98d-c6df7f2e77fd/w/crates/radicle-systemd)
Checking tree-sitter-highlight v0.24.7
Checking itertools v0.14.0
Checking socket2 v0.5.10
Checking humantime v2.3.0
Checking lexopt v0.3.2
Compiling escargot v0.5.15
Checking timeago v0.4.2
Checking wait-timeout v0.2.1
Checking fnv v1.0.7
Checking quick-error v1.2.3
Checking rusty-fork v0.3.1
Checking rand v0.9.2
Checking rand_xorshift v0.4.0
Checking rand_chacha v0.9.0
Compiling qcheck-macros v1.0.0
Checking num-bigint v0.4.6
Compiling ahash v0.8.12
Checking unarray v0.1.4
Checking proptest v1.10.0
Checking num-complex v0.4.6
Checking env_filter v1.0.0
Checking borrow-or-share v0.2.4
Checking fluent-uri v0.3.2
Checking num-rational v0.4.2
Checking env_logger v0.11.9
Checking num v0.4.3
Checking flate2 v1.1.9
Checking phf_shared v0.11.3
Compiling test-log-macros v0.2.19
Checking outref v0.5.2
Checking vsimd v0.8.0
Compiling radicle-remote-helper v0.18.1 (/7efd60ce-81f8-4590-b98d-c6df7f2e77fd/w/crates/radicle-remote-helper)
Checking hex-literal v1.1.0
Checking uuid-simd v0.8.0
Checking test-log v0.2.19
Checking phf v0.11.3
Checking referencing v0.30.0
Checking fraction v0.15.3
Checking fancy-regex v0.14.0
Checking email_address v0.2.9
Checking bytecount v0.6.9
Checking base64 v0.22.1
Checking num-cmp v0.1.0
Checking emojis v0.6.4
Compiling pastey v0.2.1
Checking jsonschema v0.30.0
Checking radicle-windows v0.1.0 (/7efd60ce-81f8-4590-b98d-c6df7f2e77fd/w/crates/radicle-windows)
Checking git2 v0.21.0
Checking radicle-oid v0.2.2 (/7efd60ce-81f8-4590-b98d-c6df7f2e77fd/w/crates/radicle-oid)
Checking radicle-git-metadata v0.2.1 (/7efd60ce-81f8-4590-b98d-c6df7f2e77fd/w/crates/radicle-git-metadata)
Checking radicle-term v0.19.1 (/7efd60ce-81f8-4590-b98d-c6df7f2e77fd/w/crates/radicle-term)
Checking radicle-core v0.4.1 (/7efd60ce-81f8-4590-b98d-c6df7f2e77fd/w/crates/radicle-core)
Checking radicle-cob v0.21.1 (/7efd60ce-81f8-4590-b98d-c6df7f2e77fd/w/crates/radicle-cob)
Checking radicle-surf v0.29.0 (/7efd60ce-81f8-4590-b98d-c6df7f2e77fd/w/crates/radicle-surf)
Checking radicle-cli-test v0.14.1 (/7efd60ce-81f8-4590-b98d-c6df7f2e77fd/w/crates/radicle-cli-test)
Checking radicle-fetch v0.21.1 (/7efd60ce-81f8-4590-b98d-c6df7f2e77fd/w/crates/radicle-fetch)
Checking radicle-schemars v0.9.1 (/7efd60ce-81f8-4590-b98d-c6df7f2e77fd/w/crates/radicle-schemars)
Checking radicle-protocol v0.9.1 (/7efd60ce-81f8-4590-b98d-c6df7f2e77fd/w/crates/radicle-protocol)
error: wildcard match will also match any future added variants
--> crates/radicle-cli/src/commands/issue/args.rs:70:13
|
70 | _ => None,
| ^ help: try: `Command::Assign { .. } | Command::Cache { .. } | Command::Edit { .. } | Command::Delete { .. } | Command::Label { .. } | Command::List(_) | Command::Open { .. } | Command::Show { .. } | Command::State { .. }`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/rust-1.97.0/index.html#wildcard_enum_match_arm
= note: requested on the command line with `-D clippy::wildcard-enum-match-arm`
error: could not compile `radicle-cli` (lib) due to 1 previous error
warning: build failed, waiting for other jobs to finish...
error: could not compile `radicle-cli` (lib test) due to 1 previous error
Exit code: 101
{
"response": "finished",
"result": "failure"
}