Radish alpha
h
Radicle Heartwood Protocol & Stack
Radicle
Git (anonymous pull)
Log in to clone via SSH
cli: Improve `patch` command
Alexis Sellier committed 3 years ago
commit adbf6f5bf5e5c9584304d0c839d7015d5f273e64
parent db38f2df76977168fa5621c395e1956c176fdec1
8 files changed +55 -98
modified radicle-cli/examples/rad-patch.md
@@ -25,27 +25,21 @@ $ git commit -v -m "Define power requirements"
Once the code is ready, we open (or create) a patch with our changes for the project.

```
-
$ rad patch open --message "define power requirements" --no-confirm
-

-
🌱 Creating patch for heartwood
-

+
$ rad patch open --message "Define power requirements" --message "See details."
βœ“ Pushing HEAD to storage...
βœ“ Analyzing remotes...

-
z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi/master (f2de534) <- z6MknSL…StBU8Vi/flux-capacitor-power (3e674d1)
+
z6MknSL…StBU8Vi/master (f2de534) <- z6MknSL…StBU8Vi/flux-capacitor-power (3e674d1)
+

1 commit(s) ahead, 0 commit(s) behind

3e674d1 Define power requirements

+
βœ“ Patch d8584d098142d774211ac5cdc8d1df4a113875dd created 🌱

-
╭─ define power requirements ───────
-

-
No description provided.
+
To publish your patch to the network, run:
+
    rad push

-
╰───────────────────────────────────
-

-

-
βœ“ Patch f504e78d71e7c2d70569976ef9f6b37b6a3d0bfd created 🌱
```

It will now be listed as one of the project's open patches.
@@ -55,23 +49,19 @@ $ rad patch

❲YOU PROPOSED❳

-
define power requirements f504e78d71e R0 3e674d1 (flux-capacitor-power) ahead 1, behind 0
+
Define power requirements d8584d09814 R0 3e674d1 (flux-capacitor-power) ahead 1, behind 0
└─ * opened by did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi (you) [..]
-
└─ * patch id f504e78d71e7c2d70569976ef9f6b37b6a3d0bfd
+
└─ * patch id d8584d098142d774211ac5cdc8d1df4a113875dd

❲OTHERS PROPOSED❳

Nothing to show.

-
$ rad patch show f504e78d71e7c2d70569976ef9f6b37b6a3d0bfd
-

-
patch f504e78d71e7c2d70569976ef9f6b37b6a3d0bfd
-

-
╭─ define power requirements ───────
+
$ rad patch show d8584d098142d774211ac5cdc8d1df4a113875dd

-
No description provided.
+
Define power requirements

-
╰───────────────────────────────────
+
See details.

commit 3e674d1a1df90807e934f9ae5da2591dd6848a33
Author: radicle <radicle@localhost>
@@ -94,34 +84,34 @@ $ git commit --message "Add README, just for the fun"
[flux-capacitor-power 27857ec] Add README, just for the fun
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 README.md
-
$ rad patch update --message "Add README, just for the fun" --no-confirm f504e78d71e7c2d70569976ef9f6b37b6a3d0bfd
+
$ rad patch update --message "Add README, just for the fun" d8584d098142d774211ac5cdc8d1df4a113875dd

🌱 Updating patch for heartwood

βœ“ Pushing HEAD to storage...
βœ“ Analyzing remotes...

-
f504e78d71e R0 (3e674d1) -> R1 (27857ec)
+
d8584d09814 R0 (3e674d1) -> R1 (27857ec)
1 commit(s) ahead, 0 commit(s) behind


-
βœ“ Patch f504e78d71e7c2d70569976ef9f6b37b6a3d0bfd updated 🌱
+
βœ“ Patch d8584d098142d774211ac5cdc8d1df4a113875dd updated 🌱

```

And lets leave a quick comment for our team:

```
-
$ rad comment f504e78d71e7c2d70569976ef9f6b37b6a3d0bfd --message 'I cannot wait to get back to the 90s!'
+
$ rad comment d8584d098142d774211ac5cdc8d1df4a113875dd --message 'I cannot wait to get back to the 90s!'
84ef44764de73695cf30e6b284585d2c50d6d0e5
-
$ rad comment f504e78d71e7c2d70569976ef9f6b37b6a3d0bfd --message 'I cannot wait to get back to the 90s!' --reply-to 84ef44764de73695cf30e6b284585d2c50d6d0e5
+
$ rad comment d8584d098142d774211ac5cdc8d1df4a113875dd --message 'I cannot wait to get back to the 90s!' --reply-to 84ef44764de73695cf30e6b284585d2c50d6d0e5
2fa3ac18d82ebdafe73484a15fa9823355c4664b
```

Now, let's checkout the patch that we just created:

```
-
$ rad patch checkout f504e78d71e7c2d70569976ef9f6b37b6a3d0bfd
+
$ rad patch checkout d8584d098142d774211ac5cdc8d1df4a113875dd
βœ“ Performing patch checkout...
-
βœ“ Switched to branch patch/f504e78d71e
+
βœ“ Switched to branch patch/d8584d09814
```
modified radicle-cli/src/commands/patch.rs
@@ -42,8 +42,7 @@ Usage

Create/Update options

-
        --[no-]confirm         Don't ask for confirmation during clone
-
        --[no-]sync            Sync patch to seed (default: sync)
+
        --[no-]announce        Announce patch to network (default: false)
        --[no-]push            Push patch head to storage (default: true)
    -m, --message [<string>]   Provide a comment message to the patch or revision (default: prompt)
        --no-message           Leave the patch or revision comment message blank
@@ -89,7 +88,6 @@ pub enum Operation {
#[derive(Debug)]
pub struct Options {
    pub op: Operation,
-
    pub confirm: bool,
    pub fetch: bool,
    pub announce: bool,
    pub push: bool,
@@ -101,11 +99,10 @@ impl Args for Options {
        use lexopt::prelude::*;

        let mut parser = lexopt::Parser::from_args(args);
-
        let mut confirm = true;
        let mut op: Option<OperationName> = None;
        let mut verbose = false;
        let mut fetch = false;
-
        let mut announce = true;
+
        let mut announce = false;
        let mut patch_id = None;
        let mut message = Message::default();
        let mut push = true;
@@ -113,12 +110,6 @@ impl Args for Options {
        while let Some(arg) = parser.next()? {
            match arg {
                // Options.
-
                Long("confirm") => {
-
                    confirm = true;
-
                }
-
                Long("no-confirm") => {
-
                    confirm = false;
-
                }
                Long("message") | Short('m') => {
                    if message != Message::Blank {
                        // We skip this code when `no-message` is specified.
@@ -174,6 +165,9 @@ impl Args for Options {
                Value(val) if op == Some(OperationName::Checkout) && patch_id.is_none() => {
                    patch_id = Some(term::cob::parse_patch_id(val)?);
                }
+
                Value(val) if op == Some(OperationName::Delete) && patch_id.is_none() => {
+
                    patch_id = Some(term::cob::parse_patch_id(val)?);
+
                }
                _ => return Err(anyhow::anyhow!(arg.unexpected())),
            }
        }
@@ -196,7 +190,6 @@ impl Args for Options {
        Ok((
            Options {
                op,
-
                confirm,
                fetch,
                push,
                verbose,
modified radicle-cli/src/commands/patch/common.rs
@@ -1,4 +1,3 @@
-
use std::fmt;
use std::path::Path;

use anyhow::anyhow;
@@ -34,11 +33,6 @@ pub fn branch_oid(branch: &git::raw::Branch) -> anyhow::Result<git::Oid> {
    Ok(oid.into())
}

-
#[inline]
-
pub fn confirm<D: fmt::Display>(prompt: D, options: &Options) -> bool {
-
    !options.confirm || term::confirm(prompt)
-
}
-

/// List of merge targets.
#[derive(Debug, Default)]
pub struct MergeTargets {
modified radicle-cli/src/commands/patch/create.rs
@@ -42,10 +42,6 @@ pub fn handle_patch_message(
        anyhow::bail!("a title must be given");
    }

-
    term::blank();
-
    term::patch::print_title_desc(title, description);
-
    term::blank();
-

    Ok((title.to_string(), description.to_owned()))
}

@@ -65,13 +61,14 @@ fn show_patch_commit_info(
    term::blank();
    term::info!(
        "{}/{} ({}) <- {}/{} ({})",
-
        term::format::dim(target_peer.id),
+
        term::format::dim(term::format::node(&target_peer.id)),
        term::format::highlight(project.default_branch().to_string()),
        term::format::secondary(term::format::oid(*target_oid)),
        term::format::dim(term::format::node(node_id)),
        term::format::highlight(branch_name(head_branch)?),
        term::format::secondary(term::format::oid(head_oid)),
    );
+
    term::blank();

    // TODO: Test case where the target branch has been re-written passed the merge-base, since the fork was created
    // This can also happen *after* the patch is created.
@@ -81,7 +78,6 @@ fn show_patch_commit_info(
    // List commits in patch that aren't in the target branch.
    term::blank();
    term::patch::list_commits(&commits)?;
-
    term::blank();

    Ok(())
}
@@ -100,12 +96,6 @@ pub fn run(
        storage.id
    ))?;
    let head_branch = try_branch(workdir.head()?)?;
-

-
    term::headline(format!(
-
        "🌱 Creating patch for {}",
-
        term::format::highlight(project.name())
-
    ));
-

    push_to_storage(storage, &head_branch, &options)?;
    let (target_peer, target_oid) = get_merge_target(&project, storage, &head_branch)?;

@@ -123,16 +113,14 @@ pub fn run(
        target_oid,
    )?;

+
    term::blank();
+

    // TODO: List matching working copy refs for all targets.

    let (title, description) = handle_patch_message(message, workdir, &head_branch)?;
-

-
    if !confirm("Continue?", &options) {
-
        anyhow::bail!("patch proposal aborted by user");
-
    }
-

    let head_oid = branch_oid(&head_branch)?;
    let base_oid = workdir.merge_base(*target_oid, *head_oid)?;
+
    let signer = term::signer(profile)?;
    let patch = patches.create(
        title,
        &description,
@@ -140,14 +128,18 @@ pub fn run(
        base_oid,
        head_oid,
        &[],
-
        &term::signer(profile)?,
+
        &signer,
    )?;

-
    term::blank();
    term::success!("Patch {} created 🌱", term::format::highlight(patch.id));
+
    term::blank();

    if options.announce {
        // TODO
+
    } else {
+
        term::info!("To publish your patch to the network, run:");
+
        term::indented(term::format::secondary("rad push"));
+
        term::blank();
    }

    Ok(())
modified radicle-cli/src/commands/patch/show.rs
@@ -1,3 +1,5 @@
+
use std::process;
+

use super::common::*;
use super::*;

@@ -16,8 +18,14 @@ fn show_patch_diff(
    let base_oid = workdir.merge_base(target_head, **patch.head())?;
    let diff = format!("{}..{}", base_oid, patch.head());

-
    let output = git::run::<_, _, &str, &str>(workdir.path(), ["log", "--patch", &diff], [])?;
-
    term::blob(output);
+
    process::Command::new("git")
+
        .current_dir(workdir.path())
+
        .args(["log", "--patch", &diff])
+
        .stdout(process::Stdio::inherit())
+
        .stderr(process::Stdio::inherit())
+
        .spawn()?
+
        .wait()?;
+

    Ok(())
}

@@ -32,11 +40,13 @@ pub fn run(
    };

    term::blank();
-
    term::print(format!("patch {patch_id}"));
+
    term::info!("{}", term::format::bold(patch.title()));
    term::blank();

-
    term::patch::print_title_desc(patch.title(), patch.description().unwrap_or(""));
-
    term::blank();
+
    if let Some(desc) = patch.description() {
+
        term::blob(desc.trim());
+
        term::blank();
+
    }

    show_patch_diff(&patch, storage, workdir)?;
    term::blank();
modified radicle-cli/src/commands/patch/update.rs
@@ -115,10 +115,6 @@ pub fn run(
        anyhow::bail!("Patch `{patch_id}` not found");
    };

-
    if !confirm("Update patch?", options) {
-
        anyhow::bail!("Patch update aborted by user");
-
    }
-

    // TODO(cloudhead): Handle error.
    let (_, current_revision) = patch.latest().unwrap();
    if *current_revision.oid == *branch_oid(&head_branch)? {
@@ -128,10 +124,6 @@ pub fn run(

    show_update_commit_info(workdir, &patch_id, &patch, current_revision, &head_branch)?;

-
    if !confirm("Continue?", options) {
-
        anyhow::bail!("patch update aborted by user");
-
    }
-

    let head_oid = branch_oid(&head_branch)?;
    let base_oid = workdir.merge_base(*target_oid, *head_oid)?;
    let message = message.get(REVISION_MSG);
modified radicle-cli/src/terminal/patch.rs
@@ -1,7 +1,6 @@
use radicle::git;

use crate::terminal as term;
-
use crate::terminal::cell::Cell as _;

/// The user supplied `Patch` description.
#[derive(Clone, Debug, PartialEq, Eq)]
@@ -84,22 +83,3 @@ 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(title_pretty.to_string().width() - 1)
-
    )));
-
}
modified radicle-tools/src/rad-cli-demo.rs
@@ -6,6 +6,7 @@ fn main() -> anyhow::Result<()> {
    let demo = terminal::io::select(
        "Choose something to try out:",
        &[
+
            "confirm",
            "spinner",
            "spinner-drop",
            "spinner-error",
@@ -16,6 +17,11 @@ fn main() -> anyhow::Result<()> {
    )?;

    match demo {
+
        Some(&"confirm") => {
+
            if terminal::confirm("Would you like to proceed?") {
+
                terminal::success!("You said 'yes'");
+
            }
+
        }
        Some(&"editor") => {
            let output = terminal::editor::Editor::new()
                .extension("rs")