cli: Improve `patch` command

Cleanup and simplify output of patch command.
This commit is contained in:
Alexis Sellier 2023-03-07 18:19:26 +01:00
parent db38f2df76
commit adbf6f5bf5
No known key found for this signature in database
8 changed files with 55 additions and 98 deletions

View File

@ -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) <- z6MknSLStBU8Vi/flux-capacitor-power (3e674d1)
z6MknSL…StBU8Vi/master (f2de534) <- z6MknSLStBU8Vi/flux-capacitor-power (3e674d1)
1 commit(s) ahead, 0 commit(s) behind
3e674d1 Define power requirements
✓ Patch d8584d098142d774211ac5cdc8d1df4a113875dd created 🌱
╭─ define power requirements ───────
To publish your patch to the network, run:
rad push
No description provided.
╰───────────────────────────────────
✓ 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
$ rad patch show d8584d098142d774211ac5cdc8d1df4a113875dd
patch f504e78d71e7c2d70569976ef9f6b37b6a3d0bfd
Define power requirements
╭─ define power requirements ───────
No description provided.
╰───────────────────────────────────
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
```

View File

@ -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,

View File

@ -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 {

View File

@ -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(())

View File

@ -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();

View File

@ -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);

View File

@ -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)
)));
}

View File

@ -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")