Radish alpha
h
Radicle Heartwood Protocol & Stack
Radicle
Git (anonymous pull)
Log in to clone via SSH
REVIEW
◌ CI pending Fintan Halpenny committed 7 months ago
commit 83ae778f1429fdd1e3002eef21f7a923b30bedbe
parent 4e6462f0bd92f6e18ccefc760f3ee819842a6a97
1 pending (1 total) View logs
4 files changed +136 -11
modified crates/radicle-cli/examples/rad-patch-via-push.md
@@ -239,6 +239,88 @@ $ rad patch show 9580891
╰────────────────────────────────────────────────────╯
```

+
## Detached HEAD
+

+
In some cases, we may be creating patches from a detached HEAD state, but we
+
still want to have tracking branch. We can do this using the
+
`patch.branch.create` and `patch.branch.name` options.
+

+
```
+
$ git commit --allow-empty -m "Going into detached HEAD"
+
[feature/2 831e838] Going into detached HEAD
+
```
+

+
``` (stderr)
+
$ git checkout 831e838
+
Note: switching to '831e838'.
+

+
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 831e838 Going into detached HEAD
+
$ git push rad HEAD:refs/patches -o patch.branch.create
+
✓ Patch e0fd879ac0a7d3ddcf3b440d8db656f5d7cebea3 opened
+
hint: to update, run `git push rad patches/e0fd879ac0a7d3ddcf3b440d8db656f5d7cebea3`
+
To rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
+
 * [new reference]   HEAD -> refs/patches
+
```
+

+
The default name used for the branch is `patches/<patch id>`. So let's checkout
+
the branch and push a new revision:
+

+
``` (stderr)
+
$ git checkout patches/e0fd879ac0a7d3ddcf3b440d8db656f5d7cebea3
+
Switched to branch 'patches/e0fd879ac0a7d3ddcf3b440d8db656f5d7cebea3'
+
$ git commit --allow-empty -m "Pushing new revision"
+
$ git push rad
+
✓ Patch e0fd879 updated to revision 943cbd9769e855d5e4eba419e68374c5141a2785
+
To compare against your previous revision e0fd879, run:
+

+
   git range-diff [..] [..] [..]
+

+
To rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
+
   831e838..d0ff2a1  patches/e0fd879ac0a7d3ddcf3b440d8db656f5d7cebea3 -> patches/e0fd879ac0a7d3ddcf3b440d8db656f5d7cebea3
+
```
+

+
However, we also allow you to name the branch yourself:
+

+
``` (stderr)
+
$ git checkout 831e838 -q
+
$ git push rad HEAD:refs/patches -o patch.branch.name='feature/3'
+
✓ Patch e0fd879ac0a7d3ddcf3b440d8db656f5d7cebea3 opened
+
hint: to update, run `git push rad patches/e0fd879ac0a7d3ddcf3b440d8db656f5d7cebea3`
+
To rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
+
 * [new reference]   HEAD -> refs/patches
+
```
+

+
Let's checkout this branch and also push a new revision:
+

+
``` (stderr)
+
$ git checkout feature/3
+
Switched to branch 'feature/3'
+
$ git commit --allow-empty -m "Pushing new revision"
+
$ git push rad
+
✓ Patch e0fd879 updated to revision 943cbd9769e855d5e4eba419e68374c5141a2785
+
To compare against your previous revision e0fd879, run:
+

+
   git range-diff [..] [..] [..]
+

+
To rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
+
   831e838..d0ff2a1  feature/3 -> patches/e0fd879ac0a7d3ddcf3b440d8db656f5d7cebea3
+
```
+

## Empty patch

If we try to open a patch without making any changes to our base branch (`master`),
modified crates/radicle-remote-helper/src/main.rs
@@ -153,6 +153,37 @@ impl FromStr for Verbosity {
    }
}

+
/// Branch creation options when creating a patch.
+
#[derive(Debug, Default, Clone)]
+
pub struct Branch {
+
    /// Ask to create the branch.
+
    ///
+
    /// If `name` is `None` and `create` is `true`, then a default branch name
+
    /// is used, that relates to the patch.
+
    ///
+
    /// Otherwise, the `name` provided is used.
+
    create: bool,
+
    /// The user supplied name for the branch.
+
    name: Option<git::RefString>,
+
}
+

+
impl Branch {
+
    /// Return the branch name to be used for the local branch when creating a
+
    /// patch.
+
    pub fn to_branch_name(self, object: &radicle::patch::PatchId) -> Option<git::Qualified> {
+
        match (self.create, self.name) {
+
            (true, None) => Some(git::refs::patch(object)),
+
            (false, None) => None,
+
            (_, Some(name)) => match name.clone().into_qualified() {
+
                None => Some(git::fmt::lit::refs_heads(&name).into()),
+
                // Ensure that if the reference is already qualified we do not
+
                // add `refs/heads`
+
                Some(name) => Some(name),
+
            },
+
        }
+
    }
+
}
+

#[derive(Debug, Default, Clone)]
pub struct Options {
    /// Don't sync after push.
@@ -167,8 +198,8 @@ pub struct Options {
    base: Option<git::Oid>,
    /// Patch message.
    message: cli::patch::Message,
-
    /// Create a branch when opening a patch.
-
    create_branch: bool,
+
    /// Create a branch and set its upstream when opening a patch.
+
    branch: Branch,
    verbosity: Verbosity,
}

@@ -291,7 +322,7 @@ fn push_option(args: &[&str], opts: &mut Options) -> Result<(), Error> {
        ["sync.debug"] => opts.sync_debug = true,
        ["no-sync"] => opts.no_sync = true,
        ["patch.draft"] => opts.draft = true,
-
        ["patch.create-branch"] => opts.create_branch = true,
+
        ["patch.branch.create"] => opts.branch.create = true,
        _ => {
            let args = args.join(" ");

@@ -318,6 +349,7 @@ fn push_option(args: &[&str], opts: &mut Options) -> Result<(), Error> {

                    opts.base = Some(git::Oid::from(commit.id()));
                }
+
                "patch.branch.name" => opts.branch.name = Some(git::RefString::try_from(val)?),
                other => {
                    return Err(Error::UnsupportedPushOption(other.to_owned()));
                }
modified crates/radicle-remote-helper/src/push.rs
@@ -564,9 +564,11 @@ where
            )?;

            if let Some(upstream) = upstream {
-
                if opts.create_branch {
-
                    let branch_name = format!("patches/{patch}");
-
                    let local_branch = git::refs::patch(&patch);
+
                if let Some(local_branch) = opts.branch.to_branch_name(&patch) {
+
                    let strip_refs_heads = |qualified: git::Qualified| {
+
                        let (_refs, _heads, x, xs) = qualified.non_empty_components();
+
                        std::iter::once(x).chain(xs).collect::<git::RefString>()
+
                    };
                    let _ = working.reference(
                        &local_branch,
                        *head,
@@ -581,11 +583,16 @@ where
                        true,
                        "Create remote tracking branch for patch",
                    )?;
-
                    assert!(remote_branch.is_remote());
+
                    debug_assert!(remote_branch.is_remote());

-
                    git::set_upstream(working, upstream, &branch_name, local_branch)?;
+
                    let local_branch = strip_refs_heads(local_branch);
+
                    let upstream_branch = git::refs::patch(&patch);
+
                    git::set_upstream(working, upstream, local_branch, &upstream_branch)?;

-
                    hint(format!("to update, run `git push rad {branch_name}`"));
+
                    let upstream_branch = strip_refs_heads(upstream_branch);
+
                    hint(format!(
+
                        "to update, run `git push {upstream} {upstream_branch}`"
+
                    ));
                }
                // Setup current branch so that pushing updates the patch.
                else if let Some(branch) =
@@ -597,7 +604,7 @@ where
                            // rad/patches/deadbeef -> patches/deadbeef
                            let name = name.split_once('/').unwrap_or_default().1;
                            hint(format!(
-
                                "to update, run `git push` or `git push rad -f HEAD:{name}`"
+
                                "to update, run `git push` or `git push {upstream} -f HEAD:{name}`"
                            ));
                        }
                    }
modified rad-patch.1.adoc
@@ -217,9 +217,13 @@ The full list of options follows:
*patch.draft*::
  Open the patch as a _draft_. Turned off by default.

-
*patch.create-branch*::
+
*patch.branch.create*::
  Create a branch when opening a patch. Turned off by default.

+
*patch.branch.name*::
+
  Use the provided branch name when opening a patch. Turned off by default.
+
  Note that this can be used without setting *patch.branch.create*.
+

*patch.message*=_<message>_::
  To prevent the editor from opening, you can specify the patch message via this
  option. Multiple *patch.message* options are concatenated with a blank line