rad:z3gqcJUoA1n9HaHKufZs5FCSGazv5 heartwood8ecdd70becef4ff20c0cb71fff0e365f785f4996
{
"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:z6MkireRatUThvd3qzfKht1S44wpm4FEWSSa4PRMTSQZ3voM",
"did:key:z6MkkPvBfjP4bQmco5Dm7UGsX2ruDBieEHi8n9DVJWX5sTEz"
]
},
"action": "Created",
"patch": {
"id": "9b206705cea420bfa505a4b435bf7288c3c8f5d3",
"author": {
"id": "did:key:z6MkireRatUThvd3qzfKht1S44wpm4FEWSSa4PRMTSQZ3voM",
"alias": null
},
"title": "cli: add `rad unblock` command",
"state": {
"status": "merged",
"conflicts": []
},
"before": "74336f961a5f6cfbb30f867a9eacfd5da579f597",
"after": "8ecdd70becef4ff20c0cb71fff0e365f785f4996",
"commits": [
"8ecdd70becef4ff20c0cb71fff0e365f785f4996"
],
"target": "3fc92f83fe089263c470b328414d923227cf0e4a",
"labels": [],
"assignees": [],
"revisions": [
{
"id": "9b206705cea420bfa505a4b435bf7288c3c8f5d3",
"author": {
"id": "did:key:z6MkireRatUThvd3qzfKht1S44wpm4FEWSSa4PRMTSQZ3voM",
"alias": null
},
"description": "Add the `rad unblock` command for reversing the effect of blocking an RID.\n\nNote that the `unblock` command also takes a `scope`, which defaults to `all`.\nIt was noticed that when adding the command without a `scope`, that the schema\ndefaults to `followed`. This seemed strange that the output of `rad seed` would\nshow the scope as `all` alongside the `block` policy, and then would change to\n`followed`.\n\nTo allow setting the `policy` and the `scope` in one SQL statement, a new method\n`set_seedinge` was also added.",
"base": "74336f961a5f6cfbb30f867a9eacfd5da579f597",
"oid": "272a012d1e45897cd9582c1310601d65643c8a2b",
"timestamp": 1722256988
},
{
"id": "591de57ff2ecac969818cfc522da52c13da8a097",
"author": {
"id": "did:key:z6MkireRatUThvd3qzfKht1S44wpm4FEWSSa4PRMTSQZ3voM",
"alias": null
},
"description": "Changes:\n- Removes entry in the case of an RID, as opposed to behaviour that is akin to\n seeding.",
"base": "74336f961a5f6cfbb30f867a9eacfd5da579f597",
"oid": "c32b06951e26c5088ea929a6caca46b7f9c0ff1c",
"timestamp": 1722270878
},
{
"id": "41f9db400f22480de19c00b6285254a7835c06f3",
"author": {
"id": "did:key:z6MkireRatUThvd3qzfKht1S44wpm4FEWSSa4PRMTSQZ3voM",
"alias": null
},
"description": "Changes:\n- Rename `unblock` to `unblock_rid`\n- Introduce `unblock_nid`\n- Use both of the above for unblocking",
"base": "74336f961a5f6cfbb30f867a9eacfd5da579f597",
"oid": "8ecdd70becef4ff20c0cb71fff0e365f785f4996",
"timestamp": 1722331198
},
{
"id": "09d43245e7bff231420baeb5540464bc3050b191",
"author": {
"id": "did:key:z6MkireRatUThvd3qzfKht1S44wpm4FEWSSa4PRMTSQZ3voM",
"alias": null
},
"description": "Minor copy edits and rebase.",
"base": "468d5a46ee9d40ed98868520406d1b8c8b1bb94f",
"oid": "bd557ec070dc50d38d5928b2e84faa59b57beeb8",
"timestamp": 1722946306
},
{
"id": "652cdbc1a0d47b33a8a987e6499a46ebe3bf423e",
"author": {
"id": "did:key:z6MkireRatUThvd3qzfKht1S44wpm4FEWSSa4PRMTSQZ3voM",
"alias": null
},
"description": "",
"base": "468d5a46ee9d40ed98868520406d1b8c8b1bb94f",
"oid": "52554af4f12d9cb8b46793dbccbcf2451a5995da",
"timestamp": 1722946368
}
]
}
}
{
"response": "triggered",
"run_id": {
"id": "0443b39e-24fa-4dfa-abb3-47b5fc7f5f03"
},
"info_url": "https://cci.rad.levitte.org//0443b39e-24fa-4dfa-abb3-47b5fc7f5f03.html"
}
Started at: 2026-09-08 01:28:36.564456+02:00
Commands:
$ rad clone rad:z3gqcJUoA1n9HaHKufZs5FCSGazv5 .
✓ Creating checkout in ./...
✓ Remote cloudhead@z6MksFqXN3Yhqk8pTJdUGLwATkRfQvwZXPqR2qMEhbS9wzpT added
✓ Remote-tracking branch cloudhead@z6MksFqXN3Yhqk8pTJdUGLwATkRfQvwZXPqR2qMEhbS9wzpT/master created for z6MksFqXN3Yhqk8pTJdUGLwATkRfQvwZXPqR2qMEhbS9wzpT
✓ Remote fintohaps@z6MkireRatUThvd3qzfKht1S44wpm4FEWSSa4PRMTSQZ3voM added
✓ Remote-tracking branch fintohaps@z6MkireRatUThvd3qzfKht1S44wpm4FEWSSa4PRMTSQZ3voM/master created for z6MkireRatUThvd3qzfKht1S44wpm4FEWSSa4PRMTSQZ3voM
✓ 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/0443b39e-24fa-4dfa-abb3-47b5fc7f5f03/w/
╭────────────────────────────────────╮
│ heartwood │
│ Radicle Heartwood Protocol & Stack │
│ 189 issues · 38 patches │
╰────────────────────────────────────╯
Run `cd ./.` to go to the repository directory.
Exit code: 0
$ rad patch checkout 9b206705cea420bfa505a4b435bf7288c3c8f5d3
✓ Switched to branch patch/9b20670 at revision 41f9db4
✓ Branch patch/9b20670 setup to track rad/patches/9b206705cea420bfa505a4b435bf7288c3c8f5d3
Exit code: 0
$ git config advice.detachedHead false
Exit code: 0
$ git checkout 8ecdd70becef4ff20c0cb71fff0e365f785f4996
HEAD is now at 8ecdd70b cli: add `rad unblock` command
Exit code: 0
$ rad patch show 9b206705cea420bfa505a4b435bf7288c3c8f5d3 -p
╭──────────────────────────────────────────────────────────────────────────────────╮
│ Title cli: add `rad unblock` command │
│ Patch 9b206705cea420bfa505a4b435bf7288c3c8f5d3 │
│ Author fintohaps z6Mkire…SQZ3voM │
│ Head 8ecdd70becef4ff20c0cb71fff0e365f785f4996 │
│ Base 74336f961a5f6cfbb30f867a9eacfd5da579f597 │
│ Target master │
│ Branches patch/9b20670 │
│ Commits ahead 1, behind 1236 │
│ Status merged │
│ │
│ Add the `rad unblock` command for reversing the effect of blocking an RID. │
│ │
│ Note that the `unblock` command also takes a `scope`, which defaults to `all`. │
│ It was noticed that when adding the command without a `scope`, that the schema │
│ defaults to `followed`. This seemed strange that the output of `rad seed` would │
│ show the scope as `all` alongside the `block` policy, and then would change to │
│ `followed`. │
│ │
│ To allow setting the `policy` and the `scope` in one SQL statement, a new method │
│ `set_seedinge` was also added. │
├──────────────────────────────────────────────────────────────────────────────────┤
│ 8ecdd70 cli: add `rad unblock` command │
├──────────────────────────────────────────────────────────────────────────────────┤
│ ● Revision 9b20670 @ 74336f9..272a012 by fintohaps z6Mkire…SQZ3voM 2 years ago │
│ ↑ Revision 591de57 @ 74336f9..c32b069 by fintohaps z6Mkire…SQZ3voM 2 years ago │
│ ↑ Revision 41f9db4 @ 74336f9..8ecdd70 by fintohaps z6Mkire…SQZ3voM 2 years ago │
│ ↑ Revision 09d4324 @ 468d5a4..bd557ec by cloudhead z6MksFq…bS9wzpT 2 years ago │
│ ↑ Revision 652cdbc @ 468d5a4..52554af by cloudhead z6MksFq…bS9wzpT 2 years ago │
│ └─ ✓ merged by cloudhead z6MksFq…bS9wzpT │
╰──────────────────────────────────────────────────────────────────────────────────╯
commit 8ecdd70becef4ff20c0cb71fff0e365f785f4996
Author: Fintan Halpenny <fintan.halpenny@gmail.com>
Date: Wed Jul 24 13:18:54 2024 +0100
cli: add `rad unblock` command
Add the `rad unblock` command for reversing the effect of blocking an NID or RID.
In both cases, the entry is removed from the DB, if the policy was set to block
-- otherwise it is a no-op.
diff --git a/radicle-cli/examples/rad-block.md b/radicle-cli/examples/rad-block.md
index 267229c7c..413350273 100644
--- a/radicle-cli/examples/rad-block.md
+++ b/radicle-cli/examples/rad-block.md
@@ -41,3 +41,15 @@ $ rad seed
│ rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji block all │
╰───────────────────────────────────────────────────────────╯
```
+
+If we want to reverse the blocking of the RID we can use `rad unblock`:
+
+```
+$ rad unblock rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji
+✓ The 'block' policy for rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji is removed
+```
+
+```
+$ rad seed
+No seeding policies to show.
+```
diff --git a/radicle-cli/src/commands.rs b/radicle-cli/src/commands.rs
index 6808f7ff7..e4df12c10 100644
--- a/radicle-cli/src/commands.rs
+++ b/radicle-cli/src/commands.rs
@@ -52,6 +52,8 @@ pub mod rad_self;
pub mod rad_stats;
#[path = "commands/sync.rs"]
pub mod rad_sync;
+#[path = "commands/unblock.rs"]
+pub mod rad_unblock;
#[path = "commands/unfollow.rs"]
pub mod rad_unfollow;
#[path = "commands/unseed.rs"]
diff --git a/radicle-cli/src/commands/help.rs b/radicle-cli/src/commands/help.rs
index 6027dd85b..79ba11bf5 100644
--- a/radicle-cli/src/commands/help.rs
+++ b/radicle-cli/src/commands/help.rs
@@ -33,6 +33,7 @@ const COMMANDS: &[Help] = &[
rad_self::HELP,
rad_seed::HELP,
rad_follow::HELP,
+ rad_unblock::HELP,
rad_unfollow::HELP,
rad_unseed::HELP,
rad_remote::HELP,
diff --git a/radicle-cli/src/commands/unblock.rs b/radicle-cli/src/commands/unblock.rs
new file mode 100644
index 000000000..c53bcfcb5
--- /dev/null
+++ b/radicle-cli/src/commands/unblock.rs
@@ -0,0 +1,97 @@
+use std::ffi::OsString;
+
+use radicle::prelude::{NodeId, RepoId};
+
+use crate::terminal as term;
+use crate::terminal::args;
+use crate::terminal::args::{Args, Error, Help};
+
+pub const HELP: Help = Help {
+ name: "block",
+ description: "Unblock repositories or nodes to allow them to be seeded or followed",
+ version: env!("RADICLE_VERSION"),
+ usage: r#"
+Usage
+
+ rad unblock <rid> [<option>...]
+ rad unblock <nid> [<option>...]
+
+ Unblock a repository to allow them to be seeded or a node to be followed.
+
+Options
+ --help Print help
+"#,
+};
+
+enum Target {
+ Node(NodeId),
+ Repo(RepoId),
+}
+
+impl std::fmt::Display for Target {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ match self {
+ Self::Node(nid) => nid.fmt(f),
+ Self::Repo(rid) => rid.fmt(f),
+ }
+ }
+}
+
+pub struct Options {
+ target: Target,
+}
+
+impl Args for Options {
+ fn from_args(args: Vec<OsString>) -> anyhow::Result<(Self, Vec<OsString>)> {
+ use lexopt::prelude::*;
+
+ let mut parser = lexopt::Parser::from_args(args);
+ let mut target = None;
+
+ while let Some(arg) = parser.next()? {
+ match arg {
+ Long("help") | Short('h') => {
+ return Err(Error::Help.into());
+ }
+ Value(val) if target.is_none() => {
+ if let Ok(rid) = args::rid(&val) {
+ target = Some(Target::Repo(rid));
+ } else if let Ok(nid) = args::nid(&val) {
+ target = Some(Target::Node(nid));
+ } else {
+ return Err(anyhow::anyhow!(
+ "invalid repository or node specified, see `rad unblock --help`"
+ ));
+ }
+ }
+ _ => return Err(anyhow::anyhow!(arg.unexpected())),
+ }
+ }
+
+ Ok((
+ Options {
+ target: target.ok_or(anyhow::anyhow!(
+ "a repository or node to unblock must be specified, see `rad unblock --help`"
+ ))?,
+ },
+ vec![],
+ ))
+ }
+}
+
+pub fn run(options: Options, ctx: impl term::Context) -> anyhow::Result<()> {
+ let profile = ctx.profile()?;
+ let mut policies = profile.policies_mut()?;
+
+ let updated = match options.target {
+ Target::Node(nid) => policies.unblock_nid(&nid)?,
+ Target::Repo(rid) => policies.unblock_rid(&rid)?,
+ };
+
+ if updated {
+ term::success!("The 'block' policy for {} is removed", options.target);
+ } else {
+ term::info!("No 'block' policy exists for {}", options.target)
+ }
+ Ok(())
+}
diff --git a/radicle-cli/src/main.rs b/radicle-cli/src/main.rs
index 1a1438630..3b3972273 100644
--- a/radicle-cli/src/main.rs
+++ b/radicle-cli/src/main.rs
@@ -291,6 +291,13 @@ fn run_other(exe: &str, args: &[OsString]) -> Result<(), Option<anyhow::Error>>
args.to_vec(),
);
}
+ "unblock" => {
+ term::run_command_args::<rad_unblock::Options, _>(
+ rad_unblock::HELP,
+ rad_unblock::run,
+ args.to_vec(),
+ );
+ }
"unfollow" => {
term::run_command_args::<rad_unfollow::Options, _>(
rad_unfollow::HELP,
diff --git a/radicle/src/node/policy.rs b/radicle/src/node/policy.rs
index cd97ce05b..8a1288167 100644
--- a/radicle/src/node/policy.rs
+++ b/radicle/src/node/policy.rs
@@ -139,11 +139,15 @@ impl TryFrom<&sqlite::Value> for Policy {
type Error = sqlite::Error;
fn try_from(value: &sqlite::Value) -> Result<Self, Self::Error> {
- let message = Some("sql: invalid policy".to_owned());
+ let message = Some("sql: invalid policy value".to_owned());
match value {
sqlite::Value::String(s) if s == "allow" => Ok(Policy::Allow),
sqlite::Value::String(s) if s == "block" => Ok(Policy::Block),
+ sqlite::Value::String(s) => Err(sqlite::Error {
+ code: None,
+ message: Some(format!("sql: invalid policy '{s}'")),
+ }),
_ => Err(sqlite::Error {
code: None,
message,
diff --git a/radicle/src/node/policy/store.rs b/radicle/src/node/policy/store.rs
index 76352d3aa..f5d2f5d03 100644
--- a/radicle/src/node/policy/store.rs
+++ b/radicle/src/node/policy/store.rs
@@ -198,6 +198,30 @@ impl Store<Write> {
Ok(self.db.change_count() > 0)
}
+
+ /// Unblock a repository.
+ pub fn unblock_rid(&mut self, id: &RepoId) -> Result<bool, Error> {
+ let mut stmt = self
+ .db
+ .prepare("DELETE FROM `seeding` WHERE id = ? AND policy = 'block'")?;
+
+ stmt.bind((1, id))?;
+ stmt.next()?;
+
+ Ok(self.db.change_count() > 0)
+ }
+
+ /// Unblock a node.
+ pub fn unblock_nid(&mut self, id: &NodeId) -> Result<bool, Error> {
+ let mut stmt = self
+ .db
+ .prepare("DELETE FROM `following` WHERE id = ? AND policy = 'block'")?;
+
+ stmt.bind((1, id))?;
+ stmt.next()?;
+
+ Ok(self.db.change_count() > 0)
+ }
}
/// `Read` methods for `Config`. This implies that a
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 0443b39e-24fa-4dfa-abb3-47b5fc7f5f03 -v /opt/radcis/ci.rad.levitte.org/cci/state/0443b39e-24fa-4dfa-abb3-47b5fc7f5f03/s:/0443b39e-24fa-4dfa-abb3-47b5fc7f5f03/s:ro -v /opt/radcis/ci.rad.levitte.org/cci/state/0443b39e-24fa-4dfa-abb3-47b5fc7f5f03/w:/0443b39e-24fa-4dfa-abb3-47b5fc7f5f03/w -w /0443b39e-24fa-4dfa-abb3-47b5fc7f5f03/w -v /opt/radcis/ci.rad.levitte.org/.radicle:/${id}/.radicle:ro -e RAD_HOME=/${id}/.radicle rust:trixie bash /0443b39e-24fa-4dfa-abb3-47b5fc7f5f03/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"
}