cli: add name option to rad patch checkout
Add the `--name` option to `rad patch checkout`. This allows the user to name the branch they are checking out, rather than use the `patch/<short-id>` format. This change includes returning early for setting the upstream branch, if the upstream already existed. Signed-off-by: Fintan Halpenny <fintan.halpenny@gmail.com> X-Clacks-Overhead: GNU Terry Pratchett
This commit is contained in:
parent
30ad7e4d67
commit
81dc849bce
|
|
@ -26,9 +26,9 @@ $ cd heartwood
|
||||||
$ rad sync -f
|
$ rad sync -f
|
||||||
✓ Fetching rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji from z6MknSL…StBU8Vi..
|
✓ Fetching rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji from z6MknSL…StBU8Vi..
|
||||||
✓ Fetched repository from 1 seed(s)
|
✓ Fetched repository from 1 seed(s)
|
||||||
$ rad patch checkout 6ff4f09
|
$ rad patch checkout 6ff4f09 --name alice-init
|
||||||
✓ Switched to branch patch/6ff4f09
|
✓ Switched to branch alice-init
|
||||||
✓ Branch patch/6ff4f09 setup to track rad/patches/6ff4f09c1b5a81347981f59b02ef43a31a07cdae
|
✓ Branch alice-init setup to track rad/patches/6ff4f09c1b5a81347981f59b02ef43a31a07cdae
|
||||||
```
|
```
|
||||||
|
|
||||||
Meanwhile, we may see some more changes that we need to make, so we
|
Meanwhile, we may see some more changes that we need to make, so we
|
||||||
|
|
@ -62,7 +62,7 @@ From rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji
|
||||||
|
|
||||||
``` ~bob
|
``` ~bob
|
||||||
$ git status
|
$ git status
|
||||||
On branch patch/6ff4f09
|
On branch alice-init
|
||||||
Your branch is behind 'rad/patches/6ff4f09c1b5a81347981f59b02ef43a31a07cdae' by 1 commit, and can be fast-forwarded.
|
Your branch is behind 'rad/patches/6ff4f09c1b5a81347981f59b02ef43a31a07cdae' by 1 commit, and can be fast-forwarded.
|
||||||
(use "git pull" to update your local branch)
|
(use "git pull" to update your local branch)
|
||||||
|
|
||||||
|
|
@ -76,11 +76,10 @@ to use the `--force` (`-f`) flag to ensure that they are looking at
|
||||||
the latest changes:
|
the latest changes:
|
||||||
|
|
||||||
``` ~bob
|
``` ~bob
|
||||||
$ rad patch checkout 6ff4f09 -f
|
$ rad patch checkout 6ff4f09 -f --name alice-init
|
||||||
✓ Switched to branch patch/6ff4f09
|
✓ Switched to branch alice-init
|
||||||
✓ Branch patch/6ff4f09 setup to track rad/patches/6ff4f09c1b5a81347981f59b02ef43a31a07cdae
|
|
||||||
$ git status
|
$ git status
|
||||||
On branch patch/6ff4f09
|
On branch alice-init
|
||||||
Your branch is up to date with 'rad/patches/6ff4f09c1b5a81347981f59b02ef43a31a07cdae'.
|
Your branch is up to date with 'rad/patches/6ff4f09c1b5a81347981f59b02ef43a31a07cdae'.
|
||||||
|
|
||||||
nothing to commit, working tree clean
|
nothing to commit, working tree clean
|
||||||
|
|
|
||||||
|
|
@ -87,6 +87,7 @@ Ready options
|
||||||
|
|
||||||
Checkout options
|
Checkout options
|
||||||
|
|
||||||
|
--name <string> Provide a name for the branch to checkout
|
||||||
-f, --force Checkout the head of the revision, even if the branch already exists
|
-f, --force Checkout the head of the revision, even if the branch already exists
|
||||||
|
|
||||||
Other options
|
Other options
|
||||||
|
|
@ -155,7 +156,7 @@ pub enum Operation {
|
||||||
},
|
},
|
||||||
Checkout {
|
Checkout {
|
||||||
revision_id: Rev,
|
revision_id: Rev,
|
||||||
force: bool,
|
opts: checkout::Options,
|
||||||
},
|
},
|
||||||
Comment {
|
Comment {
|
||||||
revision_id: Rev,
|
revision_id: Rev,
|
||||||
|
|
@ -203,7 +204,7 @@ impl Args for Options {
|
||||||
let mut diff = false;
|
let mut diff = false;
|
||||||
let mut undo = false;
|
let mut undo = false;
|
||||||
let mut reply_to: Option<Rev> = None;
|
let mut reply_to: Option<Rev> = None;
|
||||||
let mut force = false;
|
let mut checkout_opts = checkout::Options::default();
|
||||||
|
|
||||||
while let Some(arg) = parser.next()? {
|
while let Some(arg) = parser.next()? {
|
||||||
match arg {
|
match arg {
|
||||||
|
|
@ -259,7 +260,12 @@ impl Args for Options {
|
||||||
|
|
||||||
// Checkout options
|
// Checkout options
|
||||||
Long("force") | Short('f') if op == Some(OperationName::Checkout) => {
|
Long("force") | Short('f') if op == Some(OperationName::Checkout) => {
|
||||||
force = true;
|
checkout_opts.force = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
Long("name") if op == Some(OperationName::Checkout) => {
|
||||||
|
let val = parser.value()?;
|
||||||
|
checkout_opts.name = Some(term::args::refstring("name", val)?);
|
||||||
}
|
}
|
||||||
|
|
||||||
// List options.
|
// List options.
|
||||||
|
|
@ -351,7 +357,7 @@ impl Args for Options {
|
||||||
},
|
},
|
||||||
OperationName::Checkout => Operation::Checkout {
|
OperationName::Checkout => Operation::Checkout {
|
||||||
revision_id: patch_id.ok_or_else(|| anyhow!("a patch must be provided"))?,
|
revision_id: patch_id.ok_or_else(|| anyhow!("a patch must be provided"))?,
|
||||||
force,
|
opts: checkout_opts,
|
||||||
},
|
},
|
||||||
OperationName::Comment => Operation::Comment {
|
OperationName::Comment => Operation::Comment {
|
||||||
revision_id: patch_id
|
revision_id: patch_id
|
||||||
|
|
@ -431,13 +437,13 @@ pub fn run(options: Options, ctx: impl term::Context) -> anyhow::Result<()> {
|
||||||
let patch_id = patch_id.resolve::<PatchId>(&repository.backend)?;
|
let patch_id = patch_id.resolve::<PatchId>(&repository.backend)?;
|
||||||
delete::run(&patch_id, &profile, &repository)?;
|
delete::run(&patch_id, &profile, &repository)?;
|
||||||
}
|
}
|
||||||
Operation::Checkout { revision_id, force } => {
|
Operation::Checkout { revision_id, opts } => {
|
||||||
let revision_id = revision_id.resolve::<radicle::git::Oid>(&repository.backend)?;
|
let revision_id = revision_id.resolve::<radicle::git::Oid>(&repository.backend)?;
|
||||||
checkout::run(
|
checkout::run(
|
||||||
&patch::RevisionId::from(revision_id),
|
&patch::RevisionId::from(revision_id),
|
||||||
&repository,
|
&repository,
|
||||||
&workdir,
|
&workdir,
|
||||||
force,
|
opts,
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
Operation::Comment {
|
Operation::Comment {
|
||||||
|
|
|
||||||
|
|
@ -1,19 +1,41 @@
|
||||||
use anyhow::anyhow;
|
use anyhow::anyhow;
|
||||||
|
|
||||||
|
use git_ref_format::Qualified;
|
||||||
use radicle::cob::patch;
|
use radicle::cob::patch;
|
||||||
use radicle::cob::patch::RevisionId;
|
use radicle::cob::patch::RevisionId;
|
||||||
use radicle::git::RefString;
|
use radicle::git::RefString;
|
||||||
|
use radicle::patch::PatchId;
|
||||||
use radicle::storage::git::Repository;
|
use radicle::storage::git::Repository;
|
||||||
use radicle::storage::ReadRepository;
|
use radicle::storage::ReadRepository;
|
||||||
use radicle::{git, rad};
|
use radicle::{git, rad};
|
||||||
|
|
||||||
use crate::terminal as term;
|
use crate::terminal as term;
|
||||||
|
|
||||||
|
#[derive(Debug, Default)]
|
||||||
|
pub struct Options {
|
||||||
|
pub name: Option<RefString>,
|
||||||
|
pub force: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Options {
|
||||||
|
fn branch(&self, id: PatchId) -> anyhow::Result<RefString> {
|
||||||
|
match &self.name {
|
||||||
|
Some(refname) => Ok(Qualified::from_refstr(refname)
|
||||||
|
.map_or_else(|| refname.clone(), |q| q.to_ref_string())),
|
||||||
|
// SAFETY: Patch IDs are valid refstrings.
|
||||||
|
None => {
|
||||||
|
Ok(git::refname!("patch")
|
||||||
|
.join(RefString::try_from(term::format::cob(&id)).unwrap()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn run(
|
pub fn run(
|
||||||
revision_id: &RevisionId,
|
revision_id: &RevisionId,
|
||||||
stored: &Repository,
|
stored: &Repository,
|
||||||
working: &git::raw::Repository,
|
working: &git::raw::Repository,
|
||||||
force: bool,
|
opts: Options,
|
||||||
) -> anyhow::Result<()> {
|
) -> anyhow::Result<()> {
|
||||||
let patches = patch::Patches::open(stored)?;
|
let patches = patch::Patches::open(stored)?;
|
||||||
|
|
||||||
|
|
@ -32,13 +54,11 @@ pub fn run(
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut spinner = term::spinner("Performing checkout...");
|
let mut spinner = term::spinner("Performing checkout...");
|
||||||
let patch_branch =
|
let patch_branch = opts.branch(patch_id)?;
|
||||||
// SAFETY: Patch IDs are valid refstrings.
|
|
||||||
git::refname!("patch").join(RefString::try_from(term::format::cob(&patch_id)).unwrap());
|
|
||||||
|
|
||||||
let commit =
|
let commit =
|
||||||
match working.find_branch(patch_branch.as_str(), radicle::git::raw::BranchType::Local) {
|
match working.find_branch(patch_branch.as_str(), radicle::git::raw::BranchType::Local) {
|
||||||
Ok(branch) if !force => branch.get().peel_to_commit()?,
|
Ok(branch) if !opts.force => branch.get().peel_to_commit()?,
|
||||||
Ok(branch) => {
|
Ok(branch) => {
|
||||||
let commit = find_patch_commit(revision, stored, working)?;
|
let commit = find_patch_commit(revision, stored, working)?;
|
||||||
let mut r = branch.into_reference();
|
let mut r = branch.into_reference();
|
||||||
|
|
@ -54,10 +74,10 @@ pub fn run(
|
||||||
Err(e) => return Err(e.into()),
|
Err(e) => return Err(e.into()),
|
||||||
};
|
};
|
||||||
|
|
||||||
if force {
|
if opts.force {
|
||||||
let mut opts = radicle::git::raw::build::CheckoutBuilder::new();
|
let mut builder = radicle::git::raw::build::CheckoutBuilder::new();
|
||||||
opts.force();
|
builder.force();
|
||||||
working.checkout_tree(commit.as_object(), Some(&mut opts))?;
|
working.checkout_tree(commit.as_object(), Some(&mut builder))?;
|
||||||
} else {
|
} else {
|
||||||
working.checkout_tree(commit.as_object(), None)?;
|
working.checkout_tree(commit.as_object(), None)?;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -325,6 +325,12 @@ pub fn setup_patch_upstream<'a>(
|
||||||
};
|
};
|
||||||
|
|
||||||
let branch = git::raw::Branch::wrap(r);
|
let branch = git::raw::Branch::wrap(r);
|
||||||
|
|
||||||
|
// Only set the upstream if it's missing or `force` is `true`
|
||||||
|
if branch.upstream().is_ok() && !force {
|
||||||
|
return Ok(None);
|
||||||
|
}
|
||||||
|
|
||||||
let name: Option<git::RefString> = branch.name()?.and_then(|b| b.try_into().ok());
|
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 = git::refs::workdir::patch_upstream(patch);
|
||||||
let remote_branch = working.reference(
|
let remote_branch = working.reference(
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue