Radish alpha
h
Radicle Heartwood Protocol & Stack
Radicle
Git (anonymous pull)
Log in to clone via SSH
cli: Setup tracking branch on `rad patch checkout`
Alexis Sellier committed 2 years ago
commit b25c2e452b161aa000c3a0d8b58bd53090244fe2
parent 1e948485beaa216b2261d9d5fb58e8c43cdef078
6 files changed +81 -55
modified radicle-cli/examples/rad-patch.md
@@ -107,6 +107,7 @@ Now, let's checkout the patch that we just created:
```
$ rad patch checkout 077e4bb
✓ Switched to branch patch/077e4bb
+
✓ Branch patch/077e4bb setup to track rad/patches/077e4bbe9a6e5546f400ef5951768c37a76f13a4
```

We can also add a review verdict as such:
modified radicle-cli/examples/workflow/5-patching-maintainer.md
@@ -58,17 +58,20 @@ way will tell others about the corrections we needed before merging the
changes.

```
-
$ git checkout patches/50e29a111972f3b7d2123c5057de5bdf09bc7b1c
-
branch 'patches/50e29a111972f3b7d2123c5057de5bdf09bc7b1c' set up to track 'bob/patches/50e29a111972f3b7d2123c5057de5bdf09bc7b1c'.
+
$ rad patch checkout 50e29a111972f3b7d2123c5057de5bdf09bc7b1c
+
✓ Switched to branch patch/50e29a1
+
✓ Branch patch/50e29a1 setup to track rad/patches/50e29a111972f3b7d2123c5057de5bdf09bc7b1c
$ git mv REQUIREMENTS REQUIREMENTS.md
-
$ git commit --fixup HEAD~
-
[patches/50e29a111972f3b7d2123c5057de5bdf09bc7b1c f6484e0] fixup! Define power requirements
+
$ git commit -m "Use markdown for requirements"
+
[patch/50e29a1 f567f69] Use markdown for requirements
 1 file changed, 0 insertions(+), 0 deletions(-)
 rename REQUIREMENTS => REQUIREMENTS.md (100%)
-
$ rad patch update --message "Define power requirements" --message "See details." 50e29a111972f3b7d2123c5057de5bdf09bc7b1c
-
Updating 27857ec -> f6484e0
-
1 commit(s) ahead, 0 commit(s) behind
-
✓ Patch updated to revision a3405e8e174d9660fead6eea1dea5cdd2b728488
+
```
+
``` (stderr)
+
$ git push rad -o no-sync -o patch.message="Use markdown for requirements"
+
✓ Patch 50e29a1 updated to 744c1f0a75b1c42833c9aa32f79cd40443925d66
+
To rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
+
 * [new branch]      patch/50e29a1 -> patches/50e29a111972f3b7d2123c5057de5bdf09bc7b1c
```

Great, all fixed up, lets merge the code.
@@ -76,8 +79,8 @@ Great, all fixed up, lets merge the code.
```
$ git checkout master
Your branch is up to date with 'rad/master'.
-
$ git merge patches/50e29a111972f3b7d2123c5057de5bdf09bc7b1c
-
Updating f2de534..f6484e0
+
$ git merge patch/50e29a1
+
Updating f2de534..f567f69
Fast-forward
 README.md       | 0
 REQUIREMENTS.md | 0
@@ -95,20 +98,20 @@ $ rad patch show 50e29a1
│ Title     Define power requirements                                          │
│ Patch     50e29a111972f3b7d2123c5057de5bdf09bc7b1c                           │
│ Author    did:key:z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk           │
-
│ Head      f6484e0f43e48a8983b9b39bf9bd4cd889f1d520                           │
-
│ Branches  master, patches/50e29a111972f3b7d2123c5057de5bdf09bc7b1c           │
+
│ Head      f567f695d25b4e8fb63b5f5ad2a584529826e908                           │
+
│ Branches  master, patch/50e29a1                                              │
│ Commits   up to date                                                         │
│ Status    merged                                                             │
│                                                                              │
│ See details.                                                                 │
├──────────────────────────────────────────────────────────────────────────────┤
-
│ f6484e0 fixup! Define power requirements                                     │
+
│ f567f69 Use markdown for requirements                                        │
│ 27857ec Add README, just for the fun                                         │
│ 3e674d1 Define power requirements                                            │
├──────────────────────────────────────────────────────────────────────────────┤
│ ● opened by bob (z6Mkt67…v4N1tRk) [   ...    ]                               │
│ ↑ updated to 3530243d46a2e7a8e4eac7afcbb17cc7c56b3d29 (27857ec) [   ...    ] │
-
│ ↑ updated to a3405e8e174d9660fead6eea1dea5cdd2b728488 (f6484e0) [   ...    ] │
+
│ ↑ updated to 744c1f0a75b1c42833c9aa32f79cd40443925d66 (f567f69) [   ...    ] │
│ ✓ merged by (you) (z6MknSL…StBU8Vi) [   ...    ]                             │
╰──────────────────────────────────────────────────────────────────────────────╯
```
modified radicle-cli/examples/workflow/6-pulling-contributor.md
@@ -18,22 +18,19 @@ Now let's checkout `master` and pull the maintainer's changes:
```
$ git checkout master
Your branch is up to date with 'rad/master'.
+
```
+
``` (stderr)
$ git pull --all --ff
-
Fetching rad
-
Fetching z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
-
Updating f2de534..f6484e0
-
Fast-forward
-
 README.md       | 0
-
 REQUIREMENTS.md | 0
-
 2 files changed, 0 insertions(+), 0 deletions(-)
-
 create mode 100644 README.md
-
 create mode 100644 REQUIREMENTS.md
+
From rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji
+
   f2de534..f567f69  master     -> rad/master
+
From rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
+
   f2de534..f567f69  master     -> z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi/master
```

Now our master branch is up to date with the maintainer's master:

```
$ git rev-parse master
-
f6484e0f43e48a8983b9b39bf9bd4cd889f1d520
+
f567f695d25b4e8fb63b5f5ad2a584529826e908
$ git diff master..z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi/master
```
modified radicle-cli/src/commands/patch/checkout.rs
@@ -2,10 +2,10 @@ use anyhow::anyhow;

use radicle::cob::patch;
use radicle::cob::patch::{Patch, PatchId};
-
use radicle::git;
use radicle::git::RefString;
use radicle::storage::git::Repository;
use radicle::storage::ReadRepository;
+
use radicle::{git, rad};

use crate::terminal as term;

@@ -32,10 +32,20 @@ pub fn run(

    spinner.message(format!(
        "Switched to branch {}",
-
        term::format::highlight(patch_branch.as_str())
+
        term::format::highlight(&patch_branch)
    ));
    spinner.finish();

+
    if let Some(branch) = rad::setup_patch_upstream(patch_id, *patch.head(), working)? {
+
        let tracking = branch
+
            .name()?
+
            .ok_or_else(|| anyhow!("failed to create tracking branch: invalid name"))?;
+
        term::success!(
+
            "Branch {} setup to track {}",
+
            term::format::highlight(patch_branch),
+
            term::format::tertiary(tracking)
+
        );
+
    }
    Ok(())
}

@@ -52,7 +62,6 @@ fn find_patch_commit<'a>(
    match working.find_commit(patch_head.into()) {
        Ok(commit) => Ok(commit),
        Err(e) if git::ext::is_not_found_err(&e) => {
-
            // TODO: Handle case of concurrent revisions.
            let (_, rev) = patch.latest();
            let author = *rev.author().id();
            let remote = stored.remote(&author)?;
modified radicle-remote-helper/src/push.rs
@@ -325,34 +325,9 @@ fn patch_open<G: Signer>(
                "Create reference for patch head",
            )?;

-
            let head = working.head()?;
-
            if head.peel_to_commit()?.id() == commit.id() {
-
                if let Ok(r) = head.resolve() {
-
                    let branch = git::raw::Branch::wrap(r);
-
                    let name: Option<git::RefString> =
-
                        branch.name()?.and_then(|b| b.try_into().ok());
-

-
                    working.reference(
-
                        &git::refs::workdir::patch_upstream(&patch),
-
                        commit.id(),
-
                        // The patch shouldn't exist yet, and so neither should
-
                        // this ref.
-
                        false,
-
                        "Create remote tracking branch for patch",
-
                    )?;
-

-
                    if let Some(name) = name {
-
                        if branch.upstream().is_err() {
-
                            git::set_upstream(
-
                                working,
-
                                &*radicle::rad::REMOTE_NAME,
-
                                name.as_str(),
-
                                git::refs::workdir::patch(&patch),
-
                            )?;
-
                        }
-
                    }
-
                }
-
            }
+
            // Setup current branch so that pushing updates the patch.
+
            rad::setup_patch_upstream(&patch, commit.id().into(), working)?;
+

            Ok(())
        }
        Err(e) => Err(e),
modified radicle/src/rad.rs
@@ -6,6 +6,7 @@ use std::str::FromStr;
use once_cell::sync::Lazy;
use thiserror::Error;

+
use crate::cob::ObjectId;
use crate::crypto::{Signer, Verified};
use crate::git;
use crate::identity::doc::{DocError, Id};
@@ -317,6 +318,46 @@ pub fn repo(path: impl AsRef<Path>) -> Result<(git2::Repository, Id), RemoteErro
    Ok((repo, id))
}

+
/// Setup patch upstream branch such that `git push` updates the patch.
+
pub fn setup_patch_upstream<'a>(
+
    patch: &ObjectId,
+
    patch_head: git::Oid,
+
    working: &'a git::raw::Repository,
+
) -> Result<Option<git::raw::Branch<'a>>, git::ext::Error> {
+
    let head = working.head()?;
+

+
    // Don't do anything in case we're not on the patch branch.
+
    if head.peel_to_commit()?.id() != *patch_head {
+
        return Ok(None);
+
    }
+
    let Ok(r) = head.resolve() else {
+
        return Ok(None);
+
    };
+

+
    let branch = git::raw::Branch::wrap(r);
+
    let name: Option<git::RefString> = branch.name()?.and_then(|b| b.try_into().ok());
+
    let remote_branch = git::refs::workdir::patch_upstream(patch);
+
    let remote_branch = working.reference(
+
        &remote_branch,
+
        *patch_head,
+
        true,
+
        "Create remote tracking branch for patch",
+
    )?;
+
    assert!(remote_branch.is_remote());
+

+
    if let Some(name) = name {
+
        if branch.upstream().is_err() {
+
            git::set_upstream(
+
                working,
+
                &*REMOTE_NAME,
+
                name.as_str(),
+
                git::refs::workdir::patch(patch),
+
            )?;
+
        }
+
    }
+
    Ok(Some(git::raw::Branch::wrap(remote_branch)))
+
}
+

#[cfg(test)]
mod tests {
    use std::collections::HashMap;