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:
parent
1e948485be
commit
b25c2e452b
|
|
@ -107,6 +107,7 @@ Now, let's checkout the patch that we just created:
|
||||||
```
|
```
|
||||||
$ rad patch checkout 077e4bb
|
$ rad patch checkout 077e4bb
|
||||||
✓ Switched to branch patch/077e4bb
|
✓ Switched to branch patch/077e4bb
|
||||||
|
✓ Branch patch/077e4bb setup to track rad/patches/077e4bbe9a6e5546f400ef5951768c37a76f13a4
|
||||||
```
|
```
|
||||||
|
|
||||||
We can also add a review verdict as such:
|
We can also add a review verdict as such:
|
||||||
|
|
|
||||||
|
|
@ -58,17 +58,20 @@ way will tell others about the corrections we needed before merging the
|
||||||
changes.
|
changes.
|
||||||
|
|
||||||
```
|
```
|
||||||
$ git checkout patches/50e29a111972f3b7d2123c5057de5bdf09bc7b1c
|
$ rad patch checkout 50e29a111972f3b7d2123c5057de5bdf09bc7b1c
|
||||||
branch 'patches/50e29a111972f3b7d2123c5057de5bdf09bc7b1c' set up to track 'bob/patches/50e29a111972f3b7d2123c5057de5bdf09bc7b1c'.
|
✓ Switched to branch patch/50e29a1
|
||||||
|
✓ Branch patch/50e29a1 setup to track rad/patches/50e29a111972f3b7d2123c5057de5bdf09bc7b1c
|
||||||
$ git mv REQUIREMENTS REQUIREMENTS.md
|
$ git mv REQUIREMENTS REQUIREMENTS.md
|
||||||
$ git commit --fixup HEAD~
|
$ git commit -m "Use markdown for requirements"
|
||||||
[patches/50e29a111972f3b7d2123c5057de5bdf09bc7b1c f6484e0] fixup! Define power requirements
|
[patch/50e29a1 f567f69] Use markdown for requirements
|
||||||
1 file changed, 0 insertions(+), 0 deletions(-)
|
1 file changed, 0 insertions(+), 0 deletions(-)
|
||||||
rename REQUIREMENTS => REQUIREMENTS.md (100%)
|
rename REQUIREMENTS => REQUIREMENTS.md (100%)
|
||||||
$ rad patch update --message "Define power requirements" --message "See details." 50e29a111972f3b7d2123c5057de5bdf09bc7b1c
|
```
|
||||||
Updating 27857ec -> f6484e0
|
``` (stderr)
|
||||||
1 commit(s) ahead, 0 commit(s) behind
|
$ git push rad -o no-sync -o patch.message="Use markdown for requirements"
|
||||||
✓ Patch updated to revision a3405e8e174d9660fead6eea1dea5cdd2b728488
|
✓ Patch 50e29a1 updated to 744c1f0a75b1c42833c9aa32f79cd40443925d66
|
||||||
|
To rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
|
||||||
|
* [new branch] patch/50e29a1 -> patches/50e29a111972f3b7d2123c5057de5bdf09bc7b1c
|
||||||
```
|
```
|
||||||
|
|
||||||
Great, all fixed up, lets merge the code.
|
Great, all fixed up, lets merge the code.
|
||||||
|
|
@ -76,8 +79,8 @@ Great, all fixed up, lets merge the code.
|
||||||
```
|
```
|
||||||
$ git checkout master
|
$ git checkout master
|
||||||
Your branch is up to date with 'rad/master'.
|
Your branch is up to date with 'rad/master'.
|
||||||
$ git merge patches/50e29a111972f3b7d2123c5057de5bdf09bc7b1c
|
$ git merge patch/50e29a1
|
||||||
Updating f2de534..f6484e0
|
Updating f2de534..f567f69
|
||||||
Fast-forward
|
Fast-forward
|
||||||
README.md | 0
|
README.md | 0
|
||||||
REQUIREMENTS.md | 0
|
REQUIREMENTS.md | 0
|
||||||
|
|
@ -95,20 +98,20 @@ $ rad patch show 50e29a1
|
||||||
│ Title Define power requirements │
|
│ Title Define power requirements │
|
||||||
│ Patch 50e29a111972f3b7d2123c5057de5bdf09bc7b1c │
|
│ Patch 50e29a111972f3b7d2123c5057de5bdf09bc7b1c │
|
||||||
│ Author did:key:z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk │
|
│ Author did:key:z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk │
|
||||||
│ Head f6484e0f43e48a8983b9b39bf9bd4cd889f1d520 │
|
│ Head f567f695d25b4e8fb63b5f5ad2a584529826e908 │
|
||||||
│ Branches master, patches/50e29a111972f3b7d2123c5057de5bdf09bc7b1c │
|
│ Branches master, patch/50e29a1 │
|
||||||
│ Commits up to date │
|
│ Commits up to date │
|
||||||
│ Status merged │
|
│ Status merged │
|
||||||
│ │
|
│ │
|
||||||
│ See details. │
|
│ See details. │
|
||||||
├──────────────────────────────────────────────────────────────────────────────┤
|
├──────────────────────────────────────────────────────────────────────────────┤
|
||||||
│ f6484e0 fixup! Define power requirements │
|
│ f567f69 Use markdown for requirements │
|
||||||
│ 27857ec Add README, just for the fun │
|
│ 27857ec Add README, just for the fun │
|
||||||
│ 3e674d1 Define power requirements │
|
│ 3e674d1 Define power requirements │
|
||||||
├──────────────────────────────────────────────────────────────────────────────┤
|
├──────────────────────────────────────────────────────────────────────────────┤
|
||||||
│ ● opened by bob (z6Mkt67…v4N1tRk) [ ... ] │
|
│ ● opened by bob (z6Mkt67…v4N1tRk) [ ... ] │
|
||||||
│ ↑ updated to 3530243d46a2e7a8e4eac7afcbb17cc7c56b3d29 (27857ec) [ ... ] │
|
│ ↑ updated to 3530243d46a2e7a8e4eac7afcbb17cc7c56b3d29 (27857ec) [ ... ] │
|
||||||
│ ↑ updated to a3405e8e174d9660fead6eea1dea5cdd2b728488 (f6484e0) [ ... ] │
|
│ ↑ updated to 744c1f0a75b1c42833c9aa32f79cd40443925d66 (f567f69) [ ... ] │
|
||||||
│ ✓ merged by (you) (z6MknSL…StBU8Vi) [ ... ] │
|
│ ✓ merged by (you) (z6MknSL…StBU8Vi) [ ... ] │
|
||||||
╰──────────────────────────────────────────────────────────────────────────────╯
|
╰──────────────────────────────────────────────────────────────────────────────╯
|
||||||
```
|
```
|
||||||
|
|
|
||||||
|
|
@ -18,22 +18,19 @@ Now let's checkout `master` and pull the maintainer's changes:
|
||||||
```
|
```
|
||||||
$ git checkout master
|
$ git checkout master
|
||||||
Your branch is up to date with 'rad/master'.
|
Your branch is up to date with 'rad/master'.
|
||||||
|
```
|
||||||
|
``` (stderr)
|
||||||
$ git pull --all --ff
|
$ git pull --all --ff
|
||||||
Fetching rad
|
From rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji
|
||||||
Fetching z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
|
f2de534..f567f69 master -> rad/master
|
||||||
Updating f2de534..f6484e0
|
From rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
|
||||||
Fast-forward
|
f2de534..f567f69 master -> z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi/master
|
||||||
README.md | 0
|
|
||||||
REQUIREMENTS.md | 0
|
|
||||||
2 files changed, 0 insertions(+), 0 deletions(-)
|
|
||||||
create mode 100644 README.md
|
|
||||||
create mode 100644 REQUIREMENTS.md
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Now our master branch is up to date with the maintainer's master:
|
Now our master branch is up to date with the maintainer's master:
|
||||||
|
|
||||||
```
|
```
|
||||||
$ git rev-parse master
|
$ git rev-parse master
|
||||||
f6484e0f43e48a8983b9b39bf9bd4cd889f1d520
|
f567f695d25b4e8fb63b5f5ad2a584529826e908
|
||||||
$ git diff master..z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi/master
|
$ git diff master..z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi/master
|
||||||
```
|
```
|
||||||
|
|
|
||||||
|
|
@ -2,10 +2,10 @@ use anyhow::anyhow;
|
||||||
|
|
||||||
use radicle::cob::patch;
|
use radicle::cob::patch;
|
||||||
use radicle::cob::patch::{Patch, PatchId};
|
use radicle::cob::patch::{Patch, PatchId};
|
||||||
use radicle::git;
|
|
||||||
use radicle::git::RefString;
|
use radicle::git::RefString;
|
||||||
use radicle::storage::git::Repository;
|
use radicle::storage::git::Repository;
|
||||||
use radicle::storage::ReadRepository;
|
use radicle::storage::ReadRepository;
|
||||||
|
use radicle::{git, rad};
|
||||||
|
|
||||||
use crate::terminal as term;
|
use crate::terminal as term;
|
||||||
|
|
||||||
|
|
@ -32,10 +32,20 @@ pub fn run(
|
||||||
|
|
||||||
spinner.message(format!(
|
spinner.message(format!(
|
||||||
"Switched to branch {}",
|
"Switched to branch {}",
|
||||||
term::format::highlight(patch_branch.as_str())
|
term::format::highlight(&patch_branch)
|
||||||
));
|
));
|
||||||
spinner.finish();
|
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(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -52,7 +62,6 @@ fn find_patch_commit<'a>(
|
||||||
match working.find_commit(patch_head.into()) {
|
match working.find_commit(patch_head.into()) {
|
||||||
Ok(commit) => Ok(commit),
|
Ok(commit) => Ok(commit),
|
||||||
Err(e) if git::ext::is_not_found_err(&e) => {
|
Err(e) if git::ext::is_not_found_err(&e) => {
|
||||||
// TODO: Handle case of concurrent revisions.
|
|
||||||
let (_, rev) = patch.latest();
|
let (_, rev) = patch.latest();
|
||||||
let author = *rev.author().id();
|
let author = *rev.author().id();
|
||||||
let remote = stored.remote(&author)?;
|
let remote = stored.remote(&author)?;
|
||||||
|
|
|
||||||
|
|
@ -325,34 +325,9 @@ fn patch_open<G: Signer>(
|
||||||
"Create reference for patch head",
|
"Create reference for patch head",
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
let head = working.head()?;
|
// Setup current branch so that pushing updates the patch.
|
||||||
if head.peel_to_commit()?.id() == commit.id() {
|
rad::setup_patch_upstream(&patch, commit.id().into(), working)?;
|
||||||
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),
|
|
||||||
)?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
Err(e) => Err(e),
|
Err(e) => Err(e),
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ use std::str::FromStr;
|
||||||
use once_cell::sync::Lazy;
|
use once_cell::sync::Lazy;
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
|
use crate::cob::ObjectId;
|
||||||
use crate::crypto::{Signer, Verified};
|
use crate::crypto::{Signer, Verified};
|
||||||
use crate::git;
|
use crate::git;
|
||||||
use crate::identity::doc::{DocError, Id};
|
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))
|
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)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue