cli: Setup tracking branch on `rad patch checkout`

Just like when opening a new patch, we setup a tracking branch on patch
checkout, so that patches can be updated via a push.
This commit is contained in:
Alexis Sellier 2023-06-21 13:09:30 +02:00
parent 1e948485be
commit b25c2e452b
No known key found for this signature in database
6 changed files with 80 additions and 54 deletions

View File

@ -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:

View File

@ -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) [ ... ] │
╰──────────────────────────────────────────────────────────────────────────────╯
```

View File

@ -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
```

View File

@ -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)?;

View File

@ -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());
// Setup current branch so that pushing updates the patch.
rad::setup_patch_upstream(&patch, commit.id().into(), working)?;
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),
)?;
}
}
}
}
Ok(())
}
Err(e) => Err(e),

View File

@ -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;