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 00000000..ab0c3f8e --- /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 + +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 1eddcdd4..71bad40f 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 b2e5f37f..d27e29d8 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`