Radish alpha
h
Radicle Heartwood Protocol & Stack
Radicle
Git (anonymous pull)
Log in to clone via SSH
cli: add `rad patch show`
Slack Coder committed 3 years ago
commit 2295bb4ea4ad41df84fa2fd1c754d08ebb678582
parent f5cb86dabd1bd285e6fd99689e0369996b248fcb
5 files changed +104 -29
modified radicle-cli/examples/rad-patch.md
@@ -62,4 +62,16 @@ define power requirements b9bb418c6f5 R0 9dad201 (flux-capacitor-power) ahead 1,

Nothing to show.

+
$ rad patch show b9bb418c6f504ee91e54c555bdc8fc37b4d9b28b
+

+
patch b9bb418c6f504ee91e54c555bdc8fc37b4d9b28b
+

+
╭─ define power requirements ───────
+

+
No description provided.
+

+
╰───────────────────────────────────
+

+
9dad201 Define power requirements
+

```
modified radicle-cli/src/commands/patch.rs
@@ -4,6 +4,8 @@ mod common;
mod create;
#[path = "patch/list.rs"]
mod list;
+
#[path = "patch/show.rs"]
+
mod show;

use std::ffi::OsString;
use std::str::FromStr;
@@ -50,9 +52,19 @@ pub enum OptPatch {
    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)]
pub enum OperationName {
    Open,
+
    Show,
    Update,
    #[default]
    List,
@@ -63,6 +75,9 @@ pub enum Operation {
    Open {
        message: Comment,
    },
+
    Show {
+
        patch_id: PatchId,
+
    },
    Update {
        patch_id: OptPatch,
        message: Comment,
@@ -79,6 +94,14 @@ pub struct Options {
    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 {
    fn from_args(args: Vec<OsString>) -> anyhow::Result<(Self, Vec<OsString>)> {
        use lexopt::prelude::*;
@@ -88,7 +111,7 @@ impl Args for Options {
        let mut op: Option<OperationName> = None;
        let mut verbose = false;
        let mut sync = true;
-
        let mut id = OptPatch::default();
+
        let mut patch_id = OptPatch::default();
        let mut message = Comment::default();
        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() {
                    "l" | "list" => op = Some(OperationName::List),
                    "o" | "open" => op = Some(OperationName::Open),
+
                    "s" | "show" => op = Some(OperationName::Show),
                    "u" | "update" => op = Some(OperationName::Update),

                    unknown => anyhow::bail!("unknown operation '{}'", unknown),
                },
-
                Value(val) if op == Some(OperationName::Update) && id == OptPatch::Any => {
-
                    let val = val
-
                        .to_str()
-
                        .ok_or_else(|| anyhow!("patch id specified is not UTF-8"))?;
-

-
                    id = OptPatch::Patch(
-
                        PatchId::from_str(val)
-
                            .map_err(|_| anyhow!("invalid patch id '{}'", val))?,
-
                    );
+
                Value(val) if op == Some(OperationName::Show) && patch_id == OptPatch::Any => {
+
                    patch_id = parse_patch_id(val)?;
+
                }
+
                Value(val) if op == Some(OperationName::Update) && patch_id == OptPatch::Any => {
+
                    patch_id = parse_patch_id(val)?;
                }
                _ => return Err(anyhow::anyhow!(arg.unexpected())),
            }
@@ -158,10 +178,11 @@ impl Args for Options {
        let op = match op.unwrap_or_default() {
            OperationName::Open => Operation::Open { message },
            OperationName::List => Operation::List,
-
            OperationName::Update => Operation::Update {
-
                patch_id: id,
-
                message,
+
            OperationName::Show => Operation::Show {
+
                patch_id: Option::from(patch_id)
+
                    .ok_or_else(|| anyhow!("a patch id must be provided"))?,
            },
+
            OperationName::Update => Operation::Update { patch_id, message },
        };

        Ok((
@@ -198,6 +219,9 @@ pub fn run(options: Options, ctx: impl term::Context) -> anyhow::Result<()> {
        Operation::List => {
            list::run(&storage, &profile, Some(workdir), options)?;
        }
+
        Operation::Show { ref patch_id } => {
+
            show::run(&storage, &profile, &workdir, patch_id)?;
+
        }
        Operation::Update {
            ref patch_id,
            ref message,
modified radicle-cli/src/commands/patch/create.rs
@@ -238,23 +238,8 @@ pub fn run(
        anyhow::bail!("a title must be given");
    }

-
    let title_pretty = &term::format::dim(format!("╭─ {} ───────", title));
-

-
    term::blank();
-
    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)
-
    )));
+
    term::patch::print_title_desc(title, &description);
    term::blank();

    if !confirm("Create patch?", &options) {
added radicle-cli/src/commands/patch/show.rs
@@ -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(())
+
}
modified radicle-cli/src/terminal/patch.rs
@@ -84,3 +84,22 @@ pub fn print_commits_ahead_behind(
    );
    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)
+
    )));
+
}