cli: Add `rad patch checkout`

This commit allows to checkout a patch created
with `rad patch open` in a new branch
named `patch/{short_patch_id}`.

Signed-off-by: Vincenzo Palazzo <vincenzopalazzodev@gmail.com>
This commit is contained in:
Vincenzo Palazzo 2023-02-15 10:18:22 +01:00 committed by Alexis Sellier
parent ff52ea7223
commit b9ed0bc4cb
No known key found for this signature in database
3 changed files with 65 additions and 1 deletions

View File

@ -117,3 +117,11 @@ z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi/5
$ rad comment d4ef85f57a849bd845915d7a66a2192cd23811f6 --message 'I cannot wait to get back to the 90s!' --reply-to z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi/5
z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi/6
```
Now, let's checkout the patch that we just created:
```
$ rad patch checkout d4ef85f57a849bd845915d7a66a2192cd23811f6
ok Performing patch checkout...
ok Switched to branch patch/d4ef85f57a8
```

View File

@ -1,3 +1,5 @@
#[path = "patch/checkout.rs"]
mod checkout;
#[path = "patch/common.rs"]
mod common;
#[path = "patch/create.rs"]
@ -32,6 +34,7 @@ Usage
rad patch show <id>
rad patch open [<option>...]
rad patch update <id> [<option>...]
rad patch checkout <id>
Create/Update options
@ -52,6 +55,7 @@ pub enum OperationName {
Open,
Show,
Update,
Checkout,
#[default]
List,
}
@ -68,6 +72,9 @@ pub enum Operation {
patch_id: Option<PatchId>,
message: Message,
},
Checkout {
patch_id: PatchId,
},
List,
}
@ -140,7 +147,7 @@ impl Args for Options {
"o" | "open" => op = Some(OperationName::Open),
"s" | "show" => op = Some(OperationName::Show),
"u" | "update" => op = Some(OperationName::Update),
"c" | "checkout" => op = Some(OperationName::Checkout),
unknown => anyhow::bail!("unknown operation '{}'", unknown),
},
Value(val) if op == Some(OperationName::Show) && patch_id.is_none() => {
@ -149,6 +156,9 @@ impl Args for Options {
Value(val) if op == Some(OperationName::Update) && patch_id.is_none() => {
patch_id = Some(term::cob::parse_patch_id(val)?);
}
Value(val) if op == Some(OperationName::Checkout) && patch_id.is_none() => {
patch_id = Some(term::cob::parse_patch_id(val)?);
}
_ => return Err(anyhow::anyhow!(arg.unexpected())),
}
}
@ -160,6 +170,9 @@ impl Args for Options {
patch_id: patch_id.ok_or_else(|| anyhow!("a patch id must be provided"))?,
},
OperationName::Update => Operation::Update { patch_id, message },
OperationName::Checkout => Operation::Checkout {
patch_id: patch_id.ok_or_else(|| anyhow!("a patch id must be provided"))?,
},
};
Ok((
@ -205,6 +218,9 @@ pub fn run(options: Options, ctx: impl term::Context) -> anyhow::Result<()> {
&options,
)?;
}
Operation::Checkout { ref patch_id } => {
checkout::run(&storage, &profile, &workdir, patch_id)?;
}
}
Ok(())
}

View File

@ -0,0 +1,40 @@
use crate::terminal as term;
use anyhow::anyhow;
use radicle::cob::patch::{self, PatchId};
use radicle::git::{self, RefString};
use radicle::profile::Profile;
use radicle::storage::git::Repository;
pub fn run(
storage: &Repository,
profile: &Profile,
git_workdir: &git::raw::Repository,
patch_id: &PatchId,
) -> anyhow::Result<()> {
let patches = patch::Patches::open(profile.public_key, storage)?;
let patch = patches
.get(patch_id)?
.ok_or_else(|| anyhow!("Patch `{patch_id}` not found"))?;
let spinner = term::spinner("Performing patch checkout...");
// Getting the patch obj!
let patch_head = *patch.head();
let commit = git_workdir.find_commit(patch_head.into())?;
let name = RefString::try_from(format!("patch/{}", term::format::cob(patch_id)))?;
let branch = git::refs::workdir::branch(&name);
// checkout the patch in a new branch!
git_workdir.branch(branch.as_str(), &commit, false)?;
// and then point the current `HEAD` inside the new branch.
git_workdir.set_head(branch.as_str())?;
spinner.finish();
// 3. Write to the UI Terminal
term::success!(
"Switched to branch {}",
term::format::highlight(name.as_str())
);
Ok(())
}