cli: add `rad patch show`
Show patch information with `rad patch show`. Signed-off-by: Slack Coder <slackcoder@server.ky>
This commit is contained in:
parent
f5cb86dabd
commit
2295bb4ea4
|
|
@ -62,4 +62,16 @@ define power requirements b9bb418c6f5 R0 9dad201 (flux-capacitor-power) ahead 1,
|
||||||
|
|
||||||
Nothing to show.
|
Nothing to show.
|
||||||
|
|
||||||
|
$ rad patch show b9bb418c6f504ee91e54c555bdc8fc37b4d9b28b
|
||||||
|
|
||||||
|
patch b9bb418c6f504ee91e54c555bdc8fc37b4d9b28b
|
||||||
|
|
||||||
|
╭─ define power requirements ───────
|
||||||
|
|
||||||
|
No description provided.
|
||||||
|
|
||||||
|
╰───────────────────────────────────
|
||||||
|
|
||||||
|
9dad201 Define power requirements
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,8 @@ mod common;
|
||||||
mod create;
|
mod create;
|
||||||
#[path = "patch/list.rs"]
|
#[path = "patch/list.rs"]
|
||||||
mod list;
|
mod list;
|
||||||
|
#[path = "patch/show.rs"]
|
||||||
|
mod show;
|
||||||
|
|
||||||
use std::ffi::OsString;
|
use std::ffi::OsString;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
@ -50,9 +52,19 @@ pub enum OptPatch {
|
||||||
Patch(PatchId),
|
Patch(PatchId),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<OptPatch> for Option<PatchId> {
|
||||||
|
fn from(opt: OptPatch) -> Self {
|
||||||
|
match opt {
|
||||||
|
OptPatch::Patch(patch_id) => Some(patch_id),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Default, PartialEq, Eq)]
|
#[derive(Debug, Default, PartialEq, Eq)]
|
||||||
pub enum OperationName {
|
pub enum OperationName {
|
||||||
Open,
|
Open,
|
||||||
|
Show,
|
||||||
Update,
|
Update,
|
||||||
#[default]
|
#[default]
|
||||||
List,
|
List,
|
||||||
|
|
@ -63,6 +75,9 @@ pub enum Operation {
|
||||||
Open {
|
Open {
|
||||||
message: Comment,
|
message: Comment,
|
||||||
},
|
},
|
||||||
|
Show {
|
||||||
|
patch_id: PatchId,
|
||||||
|
},
|
||||||
Update {
|
Update {
|
||||||
patch_id: OptPatch,
|
patch_id: OptPatch,
|
||||||
message: Comment,
|
message: Comment,
|
||||||
|
|
@ -79,6 +94,14 @@ pub struct Options {
|
||||||
pub verbose: bool,
|
pub verbose: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn parse_patch_id(val: OsString) -> Result<OptPatch, anyhow::Error> {
|
||||||
|
let val = val
|
||||||
|
.to_str()
|
||||||
|
.ok_or_else(|| anyhow!("patch id specified is not UTF-8"))?;
|
||||||
|
let patch_id = PatchId::from_str(val).map_err(|_| anyhow!("invalid patch id '{}'", val))?;
|
||||||
|
Ok(OptPatch::Patch(patch_id))
|
||||||
|
}
|
||||||
|
|
||||||
impl Args for Options {
|
impl Args for Options {
|
||||||
fn from_args(args: Vec<OsString>) -> anyhow::Result<(Self, Vec<OsString>)> {
|
fn from_args(args: Vec<OsString>) -> anyhow::Result<(Self, Vec<OsString>)> {
|
||||||
use lexopt::prelude::*;
|
use lexopt::prelude::*;
|
||||||
|
|
@ -88,7 +111,7 @@ impl Args for Options {
|
||||||
let mut op: Option<OperationName> = None;
|
let mut op: Option<OperationName> = None;
|
||||||
let mut verbose = false;
|
let mut verbose = false;
|
||||||
let mut sync = true;
|
let mut sync = true;
|
||||||
let mut id = OptPatch::default();
|
let mut patch_id = OptPatch::default();
|
||||||
let mut message = Comment::default();
|
let mut message = Comment::default();
|
||||||
let mut push = true;
|
let mut push = true;
|
||||||
|
|
||||||
|
|
@ -137,19 +160,16 @@ impl Args for Options {
|
||||||
Value(val) if op.is_none() => match val.to_string_lossy().as_ref() {
|
Value(val) if op.is_none() => match val.to_string_lossy().as_ref() {
|
||||||
"l" | "list" => op = Some(OperationName::List),
|
"l" | "list" => op = Some(OperationName::List),
|
||||||
"o" | "open" => op = Some(OperationName::Open),
|
"o" | "open" => op = Some(OperationName::Open),
|
||||||
|
"s" | "show" => op = Some(OperationName::Show),
|
||||||
"u" | "update" => op = Some(OperationName::Update),
|
"u" | "update" => op = Some(OperationName::Update),
|
||||||
|
|
||||||
unknown => anyhow::bail!("unknown operation '{}'", unknown),
|
unknown => anyhow::bail!("unknown operation '{}'", unknown),
|
||||||
},
|
},
|
||||||
Value(val) if op == Some(OperationName::Update) && id == OptPatch::Any => {
|
Value(val) if op == Some(OperationName::Show) && patch_id == OptPatch::Any => {
|
||||||
let val = val
|
patch_id = parse_patch_id(val)?;
|
||||||
.to_str()
|
}
|
||||||
.ok_or_else(|| anyhow!("patch id specified is not UTF-8"))?;
|
Value(val) if op == Some(OperationName::Update) && patch_id == OptPatch::Any => {
|
||||||
|
patch_id = parse_patch_id(val)?;
|
||||||
id = OptPatch::Patch(
|
|
||||||
PatchId::from_str(val)
|
|
||||||
.map_err(|_| anyhow!("invalid patch id '{}'", val))?,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
_ => return Err(anyhow::anyhow!(arg.unexpected())),
|
_ => return Err(anyhow::anyhow!(arg.unexpected())),
|
||||||
}
|
}
|
||||||
|
|
@ -158,10 +178,11 @@ impl Args for Options {
|
||||||
let op = match op.unwrap_or_default() {
|
let op = match op.unwrap_or_default() {
|
||||||
OperationName::Open => Operation::Open { message },
|
OperationName::Open => Operation::Open { message },
|
||||||
OperationName::List => Operation::List,
|
OperationName::List => Operation::List,
|
||||||
OperationName::Update => Operation::Update {
|
OperationName::Show => Operation::Show {
|
||||||
patch_id: id,
|
patch_id: Option::from(patch_id)
|
||||||
message,
|
.ok_or_else(|| anyhow!("a patch id must be provided"))?,
|
||||||
},
|
},
|
||||||
|
OperationName::Update => Operation::Update { patch_id, message },
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok((
|
Ok((
|
||||||
|
|
@ -198,6 +219,9 @@ pub fn run(options: Options, ctx: impl term::Context) -> anyhow::Result<()> {
|
||||||
Operation::List => {
|
Operation::List => {
|
||||||
list::run(&storage, &profile, Some(workdir), options)?;
|
list::run(&storage, &profile, Some(workdir), options)?;
|
||||||
}
|
}
|
||||||
|
Operation::Show { ref patch_id } => {
|
||||||
|
show::run(&storage, &profile, &workdir, patch_id)?;
|
||||||
|
}
|
||||||
Operation::Update {
|
Operation::Update {
|
||||||
ref patch_id,
|
ref patch_id,
|
||||||
ref message,
|
ref message,
|
||||||
|
|
|
||||||
|
|
@ -238,23 +238,8 @@ pub fn run(
|
||||||
anyhow::bail!("a title must be given");
|
anyhow::bail!("a title must be given");
|
||||||
}
|
}
|
||||||
|
|
||||||
let title_pretty = &term::format::dim(format!("╭─ {} ───────", title));
|
|
||||||
|
|
||||||
term::blank();
|
term::blank();
|
||||||
term::print(title_pretty);
|
term::patch::print_title_desc(title, &description);
|
||||||
term::blank();
|
|
||||||
|
|
||||||
if description.is_empty() {
|
|
||||||
term::print(term::format::italic("No description provided."));
|
|
||||||
} else {
|
|
||||||
term::markdown(&description);
|
|
||||||
}
|
|
||||||
|
|
||||||
term::blank();
|
|
||||||
term::print(term::format::dim(format!(
|
|
||||||
"╰{}",
|
|
||||||
"─".repeat(term::text_width(title_pretty) - 1)
|
|
||||||
)));
|
|
||||||
term::blank();
|
term::blank();
|
||||||
|
|
||||||
if !confirm("Create patch?", &options) {
|
if !confirm("Create patch?", &options) {
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,35 @@
|
||||||
|
use super::common::*;
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
use crate::terminal as term;
|
||||||
|
use radicle::cob::patch;
|
||||||
|
use radicle::git;
|
||||||
|
use radicle::prelude::*;
|
||||||
|
use radicle::storage::git::Repository;
|
||||||
|
|
||||||
|
pub fn run(
|
||||||
|
storage: &Repository,
|
||||||
|
profile: &Profile,
|
||||||
|
workdir: &git::raw::Repository,
|
||||||
|
patch_id: &PatchId,
|
||||||
|
) -> anyhow::Result<()> {
|
||||||
|
let patches = patch::Patches::open(profile.public_key, storage)?;
|
||||||
|
let Some(patch) = patches.get(patch_id)? else {
|
||||||
|
anyhow::bail!("Patch `{}` not found", patch_id);
|
||||||
|
};
|
||||||
|
|
||||||
|
term::blank();
|
||||||
|
term::print(format!("patch {}", patch_id));
|
||||||
|
term::blank();
|
||||||
|
|
||||||
|
term::patch::print_title_desc(patch.title(), patch.description().unwrap_or(""));
|
||||||
|
term::blank();
|
||||||
|
|
||||||
|
let target_head = patch_merge_target_oid(patch.target(), storage)?;
|
||||||
|
let base_oid = workdir.merge_base(target_head, **patch.head())?;
|
||||||
|
let commits = patch_commits(workdir, &base_oid, patch.head())?;
|
||||||
|
term::patch::list_commits(&commits)?;
|
||||||
|
term::blank();
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
@ -84,3 +84,22 @@ pub fn print_commits_ahead_behind(
|
||||||
);
|
);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Print title and description in a text box.
|
||||||
|
pub fn print_title_desc(title: &str, description: &str) {
|
||||||
|
let title_pretty = &term::format::dim(format!("╭─ {} ───────", title));
|
||||||
|
term::print(title_pretty);
|
||||||
|
term::blank();
|
||||||
|
|
||||||
|
if description.is_empty() {
|
||||||
|
term::print(term::format::italic("No description provided."));
|
||||||
|
} else {
|
||||||
|
term::markdown(description);
|
||||||
|
}
|
||||||
|
|
||||||
|
term::blank();
|
||||||
|
term::print(term::format::dim(format!(
|
||||||
|
"╰{}",
|
||||||
|
"─".repeat(term::text_width(title_pretty) - 1)
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue