cli: Improve `patch` command
Cleanup and simplify output of patch command.
This commit is contained in:
parent
db38f2df76
commit
adbf6f5bf5
|
|
@ -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 ───────
|
||||
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
|
||||
```
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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(())
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
)));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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")
|
||||
|
|
|
|||
Loading…
Reference in New Issue