rad:z3gqcJUoA1n9HaHKufZs5FCSGazv5 heartwood14f095e26b3396204f9cf8fb9f3c296ce1b835fb
{
"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": "50e1f0cb0fe8c0080cf0ead5c167431659f1549c",
"author": {
"id": "did:key:z6MkireRatUThvd3qzfKht1S44wpm4FEWSSa4PRMTSQZ3voM",
"alias": null
},
"title": "remote-helper: allow patch creation from detached HEAD",
"state": {
"status": "merged",
"conflicts": []
},
"before": "a04381f4e5fdff04a2f9bfa15a16d2addbcbe8a7",
"after": "14f095e26b3396204f9cf8fb9f3c296ce1b835fb",
"commits": [
"14f095e26b3396204f9cf8fb9f3c296ce1b835fb"
],
"target": "3fc92f83fe089263c470b328414d923227cf0e4a",
"labels": [],
"assignees": [],
"revisions": [
{
"id": "50e1f0cb0fe8c0080cf0ead5c167431659f1549c",
"author": {
"id": "did:key:z6MkireRatUThvd3qzfKht1S44wpm4FEWSSa4PRMTSQZ3voM",
"alias": null
},
"description": "The patch creation flow would be partially interrupted when creating a\npatch via a detached HEAD state. The creation of an upstream branch\nwould fail since there is no branch to set an upstream for. It would\nresult in the following error:\n\n \u2713 Patch 6035d2f582afbe01ff23ea87528ae523d76875b6 opened\n To rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi\n ! [remote rejected] HEAD -> refs/patches (git: reference 'HEAD' is neither a local nor a remote branch.; class=Invalid (3))\n error: failed to push some refs to 'rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi'\n\nTo fix this, the reference that's resolved is checked to see if it a\nlocal branch. If not, it will return early.\n\nThe behaviour is tested in the `rad-patch-detached-head` example.",
"base": "a04381f4e5fdff04a2f9bfa15a16d2addbcbe8a7",
"oid": "14f095e26b3396204f9cf8fb9f3c296ce1b835fb",
"timestamp": 1721746278
},
{
"id": "eca42ec5d4435da71b980d2bf02ef23b0b26528d",
"author": {
"id": "did:key:z6MkireRatUThvd3qzfKht1S44wpm4FEWSSa4PRMTSQZ3voM",
"alias": null
},
"description": "Rebase.",
"base": "1c46f19592d041919f18736cb45ec6046d7d3b00",
"oid": "dc34eafdf4677247b539ed5c0f83199e372ef594",
"timestamp": 1721747680
}
]
}
}
{
"response": "triggered",
"run_id": {
"id": "7f454be1-b378-433b-b7bf-ead21c6382b2"
},
"info_url": "https://cci.rad.levitte.org//7f454be1-b378-433b-b7bf-ead21c6382b2.html"
}
Started at: 2026-09-07 21:34:21.827343+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/7f454be1-b378-433b-b7bf-ead21c6382b2/w/
╭────────────────────────────────────╮
│ heartwood │
│ Radicle Heartwood Protocol & Stack │
│ 189 issues · 38 patches │
╰────────────────────────────────────╯
Run `cd ./.` to go to the repository directory.
Exit code: 0
$ rad patch checkout 50e1f0cb0fe8c0080cf0ead5c167431659f1549c
✓ Switched to branch patch/50e1f0c at revision 50e1f0c
✓ Branch patch/50e1f0c setup to track rad/patches/50e1f0cb0fe8c0080cf0ead5c167431659f1549c
Exit code: 0
$ git config advice.detachedHead false
Exit code: 0
$ git checkout 14f095e26b3396204f9cf8fb9f3c296ce1b835fb
HEAD is now at 14f095e2 remote-helper: allow patch creation from detached HEAD
Exit code: 0
$ rad patch show 50e1f0cb0fe8c0080cf0ead5c167431659f1549c -p
╭──────────────────────────────────────────────────────────────────────────────────╮
│ Title remote-helper: allow patch creation from detached HEAD │
│ Patch 50e1f0cb0fe8c0080cf0ead5c167431659f1549c │
│ Author fintohaps z6Mkire…SQZ3voM │
│ Head 14f095e26b3396204f9cf8fb9f3c296ce1b835fb │
│ Base a04381f4e5fdff04a2f9bfa15a16d2addbcbe8a7 │
│ Target master │
│ Branches patch/50e1f0c │
│ Commits ahead 1, behind 1241 │
│ Status merged │
│ │
│ The patch creation flow would be partially interrupted when creating a │
│ patch via a detached HEAD state. The creation of an upstream branch │
│ would fail since there is no branch to set an upstream for. It would │
│ result in the following error: │
│ │
│ ✓ Patch 6035d2f582afbe01ff23ea87528ae523d76875b6 opened │
│ To rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4k… │
│ ! [remote rejected] HEAD -> refs/patches (git: reference 'HEAD' is neither… │
│ error: failed to push some refs to 'rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6M… │
│ │
│ To fix this, the reference that's resolved is checked to see if it a │
│ local branch. If not, it will return early. │
│ │
│ The behaviour is tested in the `rad-patch-detached-head` example. │
├──────────────────────────────────────────────────────────────────────────────────┤
│ 14f095e remote-helper: allow patch creation from detached HEAD │
├──────────────────────────────────────────────────────────────────────────────────┤
│ ● Revision 50e1f0c @ a04381f..14f095e by fintohaps z6Mkire…SQZ3voM 2 years ago │
│ ↑ Revision eca42ec @ 1c46f19..dc34eaf by cloudhead z6MksFq…bS9wzpT 2 years ago │
│ └─ ✓ merged by cloudhead z6MksFq…bS9wzpT │
╰──────────────────────────────────────────────────────────────────────────────────╯
commit 14f095e26b3396204f9cf8fb9f3c296ce1b835fb
Author: Fintan Halpenny <fintan.halpenny@gmail.com>
Date: Tue Jul 23 15:10:27 2024 +0100
remote-helper: allow patch creation from detached HEAD
The patch creation flow would be partially interrupted when creating a
patch via a detached HEAD state. The creation of an upstream branch
would fail since there is no branch to set an upstream for. It would
result in the following error:
✓ Patch 6035d2f582afbe01ff23ea87528ae523d76875b6 opened
To rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
! [remote rejected] HEAD -> refs/patches (git: reference 'HEAD' is neither a local nor a remote branch.; class=Invalid (3))
error: failed to push some refs to 'rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi'
To fix this, the reference that's resolved is checked to see if it a
local branch. If not, it will return early.
The behaviour is tested in the `rad-patch-detached-head` example.
Signed-off-by: Fintan Halpenny <fintan.halpenny@gmail.com>
X-Clacks-Overhead: GNU Terry Pratchett
diff --git a/radicle-cli/examples/rad-patch-detached-head.md b/radicle-cli/examples/rad-patch-detached-head.md
new file mode 100644
index 000000000..ab0c3f8e1
--- /dev/null
+++ b/radicle-cli/examples/rad-patch-detached-head.md
@@ -0,0 +1,41 @@
+To ensure that we can handle diverse workflows, we also allow patches to be
+opened when we're in the infamous 'detached HEAD' state.
+
+First, we will enter this state by using `git checkout` on a commit object:
+
+``` (stderr) RAD_HINT=1
+$ git checkout f2de534b5e81d7c6e2dcaf58c3dd91573c0a0354
+Note: switching to 'f2de534b5e81d7c6e2dcaf58c3dd91573c0a0354'.
+
+You are in 'detached HEAD' state. You can look around, make experimental
+changes and commit them, and you can discard any commits you make in this
+state without impacting any branches by switching back to a branch.
+
+If you want to create a new branch to retain commits you create, you may
+do so (now or later) by using -c with the switch command. Example:
+
+ git switch -c <new-branch-name>
+
+Or undo this operation with:
+
+ git switch -
+
+Turn off this advice by setting config variable advice.detachedHead to false
+
+HEAD is now at f2de534 Second commit
+```
+
+Now, we can create a commit on top of this and create a patch, as usual:
+
+``` (stderr) RAD_HINT=1
+$ git commit -a -m "Add things" -q --allow-empty
+$ git push -o patch.message="Add things #1" -o patch.message="See commits for details." rad HEAD:refs/patches
+✓ Patch 6035d2f582afbe01ff23ea87528ae523d76875b6 opened
+hint: offline push, your node is not running
+hint: to sync with the network, run `rad node start`
+To rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
+ * [new reference] HEAD -> refs/patches
+```
+
+Note that there will be no upstream branch, since we did not have a branch to
+set an upstream for in the first place!
diff --git a/radicle-cli/tests/commands.rs b/radicle-cli/tests/commands.rs
index 1eddcdd40..71bad40fa 100644
--- a/radicle-cli/tests/commands.rs
+++ b/radicle-cli/tests/commands.rs
@@ -1044,6 +1044,26 @@ fn rad_patch_via_push() {
.unwrap();
}
+#[test]
+fn rad_patch_detached_head() {
+ let mut environment = Environment::new();
+ let profile = environment.profile(config::profile("alice"));
+ let working = tempfile::tempdir().unwrap();
+ let home = &profile.home;
+
+ // Setup a test repository.
+ fixtures::repository(working.path());
+
+ test("examples/rad-init.md", working.path(), Some(home), []).unwrap();
+ test(
+ "examples/rad-patch-detached-head.md",
+ working.path(),
+ Some(home),
+ [],
+ )
+ .unwrap();
+}
+
#[test]
fn rad_patch_merge_draft() {
let mut environment = Environment::new();
diff --git a/radicle/src/rad.rs b/radicle/src/rad.rs
index b2e5f37ff..d27e29d87 100644
--- a/radicle/src/rad.rs
+++ b/radicle/src/rad.rs
@@ -353,6 +353,11 @@ pub fn setup_patch_upstream<'a>(
return Ok(None);
};
+ // Can't set an upstream for something that's not a branch
+ if !r.is_branch() {
+ return Ok(None);
+ }
+
let branch = git::raw::Branch::wrap(r);
// Only set the upstream if it's missing or `force` is `true`
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 7f454be1-b378-433b-b7bf-ead21c6382b2 -v /opt/radcis/ci.rad.levitte.org/cci/state/7f454be1-b378-433b-b7bf-ead21c6382b2/s:/7f454be1-b378-433b-b7bf-ead21c6382b2/s:ro -v /opt/radcis/ci.rad.levitte.org/cci/state/7f454be1-b378-433b-b7bf-ead21c6382b2/w:/7f454be1-b378-433b-b7bf-ead21c6382b2/w -w /7f454be1-b378-433b-b7bf-ead21c6382b2/w -v /opt/radcis/ci.rad.levitte.org/.radicle:/${id}/.radicle:ro -e RAD_HOME=/${id}/.radicle rust:trixie bash /7f454be1-b378-433b-b7bf-ead21c6382b2/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"
}