cli: Improve patch command output
* Fix timeline ordering * Remove spinner noise * Add revisions to timeline
This commit is contained in:
parent
40eb6f2a6e
commit
8dba01d6ae
|
|
@ -26,11 +26,8 @@ Once the code is ready, we open (or create) a patch with our changes for the pro
|
||||||
|
|
||||||
```
|
```
|
||||||
$ rad patch open --message "Define power requirements" --message "See details."
|
$ rad patch open --message "Define power requirements" --message "See details."
|
||||||
✓ Pushing HEAD to storage...
|
|
||||||
✓ Analyzing remotes...
|
|
||||||
|
|
||||||
master <- z6MknSL…StBU8Vi/flux-capacitor-power (3e674d1)
|
master <- z6MknSL…StBU8Vi/flux-capacitor-power (3e674d1)
|
||||||
|
|
||||||
1 commit(s) ahead, 0 commit(s) behind
|
1 commit(s) ahead, 0 commit(s) behind
|
||||||
|
|
||||||
3e674d1 Define power requirements
|
3e674d1 Define power requirements
|
||||||
|
|
@ -46,11 +43,11 @@ It will now be listed as one of the project's open patches.
|
||||||
|
|
||||||
```
|
```
|
||||||
$ rad patch
|
$ rad patch
|
||||||
╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
|
╭─────────────────────────────────────────────────────────────────────────────────────────╮
|
||||||
│ Define power requirements 191a14e520f2eeff7c0e3ee0a5523c5217eecb89 R0 3e674d1 (flux-capacitor-power) ahead 1, behind 0 │
|
│ Define power requirements 191a14e R0 3e674d1 (flux-capacitor-power) ahead 1, behind 0 │
|
||||||
├────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
|
├─────────────────────────────────────────────────────────────────────────────────────────┤
|
||||||
│ ● opened by did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi (you) 3 months ago │
|
│ ● opened by did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi (you) 3 months ago │
|
||||||
╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
|
╰─────────────────────────────────────────────────────────────────────────────────────────╯
|
||||||
```
|
```
|
||||||
```
|
```
|
||||||
$ rad patch show 191a14e520f2eeff7c0e3ee0a5523c5217eecb89
|
$ rad patch show 191a14e520f2eeff7c0e3ee0a5523c5217eecb89
|
||||||
|
|
@ -85,18 +82,10 @@ $ git commit --message "Add README, just for the fun"
|
||||||
1 file changed, 0 insertions(+), 0 deletions(-)
|
1 file changed, 0 insertions(+), 0 deletions(-)
|
||||||
create mode 100644 README.md
|
create mode 100644 README.md
|
||||||
$ rad patch update --message "Add README, just for the fun" 191a14e520f2eeff7c0e3ee0a5523c5217eecb89
|
$ rad patch update --message "Add README, just for the fun" 191a14e520f2eeff7c0e3ee0a5523c5217eecb89
|
||||||
|
191a14e R0 (3e674d1) -> R1 (27857ec)
|
||||||
🌱 Updating patch for heartwood
|
|
||||||
|
|
||||||
✓ Pushing HEAD to storage...
|
|
||||||
✓ Analyzing remotes...
|
|
||||||
|
|
||||||
191a14e520f R0 (3e674d1) -> R1 (27857ec)
|
|
||||||
1 commit(s) ahead, 0 commit(s) behind
|
1 commit(s) ahead, 0 commit(s) behind
|
||||||
|
|
||||||
|
✓ Patch 191a14e updated to 56a5efc062b34a97a162a3a4d4468ce3e7ba1c84
|
||||||
✓ Patch 191a14e520f2eeff7c0e3ee0a5523c5217eecb89 updated 🌱
|
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
And let's leave a quick comment for our team:
|
And let's leave a quick comment for our team:
|
||||||
|
|
@ -112,24 +101,25 @@ Now, let's checkout the patch that we just created:
|
||||||
|
|
||||||
```
|
```
|
||||||
$ rad patch checkout 191a14e52
|
$ rad patch checkout 191a14e52
|
||||||
✓ Switched to branch patch/191a14e520f
|
✓ Switched to branch patch/191a14e
|
||||||
```
|
```
|
||||||
|
|
||||||
We can also add a review verdict as such:
|
We can also add a review verdict as such:
|
||||||
|
|
||||||
```
|
```
|
||||||
$ rad review 191a14e520f2eeff7c0e3ee0a5523c5217eecb89 --accept --no-confirm --no-message --no-sync
|
$ rad review 191a14e520f2eeff7c0e3ee0a5523c5217eecb89 --accept --no-confirm --no-message --no-sync
|
||||||
✓ Patch 191a14e520f accepted
|
✓ Patch 191a14e accepted
|
||||||
```
|
```
|
||||||
|
|
||||||
Showing the patch list now will reveal the favorable verdict:
|
Showing the patch list now will reveal the favorable verdict:
|
||||||
|
|
||||||
```
|
```
|
||||||
$ rad patch
|
$ rad patch
|
||||||
╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
|
╭──────────────────────────────────────────────────────────────────────────────────────────────────────╮
|
||||||
│ Define power requirements 191a14e520f2eeff7c0e3ee0a5523c5217eecb89 R1 27857ec (flux-capacitor-power, patch/191a14e520f) ahead 2, behind 0 │
|
│ Define power requirements 191a14e R1 27857ec (flux-capacitor-power, patch/191a14e) ahead 2, behind 0 │
|
||||||
├───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
|
├──────────────────────────────────────────────────────────────────────────────────────────────────────┤
|
||||||
│ ● opened by did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi (you) 3 months ago │
|
│ ● opened by did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi (you) 3 months ago │
|
||||||
│ ✓ accepted by z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi (you) 3 months ago │
|
│ ↑ updated to 191a14e520f2eeff7c0e3ee0a5523c5217eecb89 (3e674d1) 3 months ago │
|
||||||
╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
|
│ ✓ accepted by z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi (you) 3 months ago │
|
||||||
|
╰──────────────────────────────────────────────────────────────────────────────────────────────────────╯
|
||||||
```
|
```
|
||||||
|
|
|
||||||
|
|
@ -26,11 +26,8 @@ Once the code is ready, we open a patch with our changes.
|
||||||
|
|
||||||
```
|
```
|
||||||
$ rad patch open --message "Define power requirements" --message "See details."
|
$ rad patch open --message "Define power requirements" --message "See details."
|
||||||
✓ Pushing HEAD to storage...
|
|
||||||
✓ Analyzing remotes...
|
|
||||||
|
|
||||||
master <- z6Mkt67…v4N1tRk/flux-capacitor-power (3e674d1)
|
master <- z6Mkt67…v4N1tRk/flux-capacitor-power (3e674d1)
|
||||||
|
|
||||||
1 commit(s) ahead, 0 commit(s) behind
|
1 commit(s) ahead, 0 commit(s) behind
|
||||||
|
|
||||||
3e674d1 Define power requirements
|
3e674d1 Define power requirements
|
||||||
|
|
@ -46,11 +43,11 @@ It will now be listed as one of the project's open patches.
|
||||||
|
|
||||||
```
|
```
|
||||||
$ rad patch
|
$ rad patch
|
||||||
╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
|
╭─────────────────────────────────────────────────────────────────────────────────────────╮
|
||||||
│ Define power requirements a07ef7743a32a2e902672ea3526d1db6ee08108a R0 3e674d1 (flux-capacitor-power) ahead 1, behind 0 │
|
│ Define power requirements a07ef77 R0 3e674d1 (flux-capacitor-power) ahead 1, behind 0 │
|
||||||
├────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
|
├─────────────────────────────────────────────────────────────────────────────────────────┤
|
||||||
│ ● opened by did:key:z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk (you) 3 months ago │
|
│ ● opened by did:key:z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk (you) 3 months ago │
|
||||||
╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
|
╰─────────────────────────────────────────────────────────────────────────────────────────╯
|
||||||
$ rad patch show a07ef7743a32a2e902672ea3526d1db6ee08108a
|
$ rad patch show a07ef7743a32a2e902672ea3526d1db6ee08108a
|
||||||
╭────────────────────────────────────────────────────────────────────╮
|
╭────────────────────────────────────────────────────────────────────╮
|
||||||
│ Title Define power requirements │
|
│ Title Define power requirements │
|
||||||
|
|
@ -83,18 +80,10 @@ $ git commit --message "Add README, just for the fun"
|
||||||
1 file changed, 0 insertions(+), 0 deletions(-)
|
1 file changed, 0 insertions(+), 0 deletions(-)
|
||||||
create mode 100644 README.md
|
create mode 100644 README.md
|
||||||
$ rad patch update --message "Add README, just for the fun" a07ef7743a32a2e902672ea3526d1db6ee08108a
|
$ rad patch update --message "Add README, just for the fun" a07ef7743a32a2e902672ea3526d1db6ee08108a
|
||||||
|
a07ef77 R0 (3e674d1) -> R1 (27857ec)
|
||||||
🌱 Updating patch for heartwood
|
|
||||||
|
|
||||||
✓ Pushing HEAD to storage...
|
|
||||||
✓ Analyzing remotes...
|
|
||||||
|
|
||||||
a07ef7743a3 R0 (3e674d1) -> R1 (27857ec)
|
|
||||||
1 commit(s) ahead, 0 commit(s) behind
|
1 commit(s) ahead, 0 commit(s) behind
|
||||||
|
|
||||||
|
✓ Patch a07ef77 updated to 4f15eb5c994edd0bb6be29cb4801aa74308cc628
|
||||||
✓ Patch a07ef7743a32a2e902672ea3526d1db6ee08108a updated 🌱
|
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
And let's leave a quick comment for our team:
|
And let's leave a quick comment for our team:
|
||||||
|
|
|
||||||
|
|
@ -27,11 +27,12 @@ $ git branch -r
|
||||||
bob/master
|
bob/master
|
||||||
rad/master
|
rad/master
|
||||||
$ rad patch
|
$ rad patch
|
||||||
╭─────────────────────────────────────────────────────────────────────────────────────────────────╮
|
╭───────────────────────────────────────────────────────────────────────────────────╮
|
||||||
│ Define power requirements a07ef7743a32a2e902672ea3526d1db6ee08108a R1 27857ec ahead 2, behind 0 │
|
│ Define power requirements a07ef77 R1 27857ec ahead 2, behind 0 │
|
||||||
├─────────────────────────────────────────────────────────────────────────────────────────────────┤
|
├───────────────────────────────────────────────────────────────────────────────────┤
|
||||||
│ ● opened by did:key:z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk 3 months ago │
|
│ ● opened by did:key:z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk 3 months ago │
|
||||||
╰─────────────────────────────────────────────────────────────────────────────────────────────────╯
|
│ ↑ updated to a07ef7743a32a2e902672ea3526d1db6ee08108a (3e674d1) 3 months ago │
|
||||||
|
╰───────────────────────────────────────────────────────────────────────────────────╯
|
||||||
```
|
```
|
||||||
|
|
||||||
Wait! There's a mistake. The REQUIREMENTS should be a markdown file. Let's
|
Wait! There's a mistake. The REQUIREMENTS should be a markdown file. Let's
|
||||||
|
|
@ -48,16 +49,8 @@ $ git commit --fixup HEAD~
|
||||||
1 file changed, 0 insertions(+), 0 deletions(-)
|
1 file changed, 0 insertions(+), 0 deletions(-)
|
||||||
rename REQUIREMENTS => REQUIREMENTS.md (100%)
|
rename REQUIREMENTS => REQUIREMENTS.md (100%)
|
||||||
$ rad patch update --message "Define power requirements" --message "See details." a07ef7743a32a2e902672ea3526d1db6ee08108a
|
$ rad patch update --message "Define power requirements" --message "See details." a07ef7743a32a2e902672ea3526d1db6ee08108a
|
||||||
|
a07ef77 R1 (27857ec) -> R2 (f6484e0)
|
||||||
🌱 Updating patch for heartwood
|
|
||||||
|
|
||||||
✓ Pushing HEAD to storage...
|
|
||||||
✓ Analyzing remotes...
|
|
||||||
|
|
||||||
a07ef7743a3 R1 (27857ec) -> R2 (f6484e0)
|
|
||||||
1 commit(s) ahead, 0 commit(s) behind
|
1 commit(s) ahead, 0 commit(s) behind
|
||||||
|
|
||||||
|
✓ Patch a07ef77 updated to 737dc47d9eba730c5db8a8e33c41c7955f9093de
|
||||||
✓ Patch a07ef7743a32a2e902672ea3526d1db6ee08108a updated 🌱
|
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
|
||||||
|
|
@ -195,12 +195,11 @@ pub fn run(options: Options, ctx: impl term::Context) -> anyhow::Result<()> {
|
||||||
}
|
}
|
||||||
MergeStyle::Commit
|
MergeStyle::Commit
|
||||||
} else if merge.is_up_to_date() {
|
} else if merge.is_up_to_date() {
|
||||||
term::info!(
|
term::success!(
|
||||||
"✓ Patch {} is already part of {}",
|
"Patch {} is already part of current branch {}",
|
||||||
term::format::tertiary(patch_id),
|
term::format::tertiary(patch_id),
|
||||||
term::format::highlight(branch)
|
term::format::parens(term::format::yellow(branch))
|
||||||
);
|
);
|
||||||
|
|
||||||
return Ok(());
|
return Ok(());
|
||||||
} else if merge.is_unborn() {
|
} else if merge.is_unborn() {
|
||||||
anyhow::bail!("HEAD does not point to a valid commit");
|
anyhow::bail!("HEAD does not point to a valid commit");
|
||||||
|
|
@ -223,14 +222,14 @@ pub fn run(options: Options, ctx: impl term::Context) -> anyhow::Result<()> {
|
||||||
};
|
};
|
||||||
|
|
||||||
term::info!(
|
term::info!(
|
||||||
"{} {} {} ({}) by {} into {} ({}) via {}...",
|
"{} {} {} {} by {} into {} {} via {}...",
|
||||||
term::format::bold("Merging"),
|
term::format::bold("Merging"),
|
||||||
term::format::tertiary(term::format::cob(&patch_id)),
|
term::format::tertiary(term::format::cob(&patch_id)),
|
||||||
term::format::dim(format!("R{revision_ix}")),
|
term::format::dim(format!("R{revision_ix}")),
|
||||||
term::format::secondary(term::format::oid(revision.oid)),
|
term::format::parens(term::format::secondary(term::format::oid(revision.oid))),
|
||||||
term::format::tertiary(patch.author().id),
|
term::format::tertiary(patch.author().id),
|
||||||
term::format::highlight(branch),
|
term::format::highlight(branch),
|
||||||
term::format::secondary(term::format::oid(head_oid)),
|
term::format::parens(term::format::secondary(term::format::oid(head_oid))),
|
||||||
merge_style_pretty
|
merge_style_pretty
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -43,7 +43,6 @@ pub fn get_merge_target(
|
||||||
storage: &Repository,
|
storage: &Repository,
|
||||||
head_branch: &git::raw::Branch,
|
head_branch: &git::raw::Branch,
|
||||||
) -> anyhow::Result<(git::RefString, git::Oid)> {
|
) -> anyhow::Result<(git::RefString, git::Oid)> {
|
||||||
let spinner = term::spinner("Analyzing remotes...");
|
|
||||||
let (qualified_ref, target_oid) = storage.canonical_head()?;
|
let (qualified_ref, target_oid) = storage.canonical_head()?;
|
||||||
let head_oid = branch_oid(head_branch)?;
|
let head_oid = branch_oid(head_branch)?;
|
||||||
let merge_base = storage.raw().merge_base(*head_oid, *target_oid)?;
|
let merge_base = storage.raw().merge_base(*head_oid, *target_oid)?;
|
||||||
|
|
@ -52,11 +51,7 @@ pub fn get_merge_target(
|
||||||
anyhow::bail!("commits are already included in the target branch; nothing to do");
|
anyhow::bail!("commits are already included in the target branch; nothing to do");
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Tell user how many peers don't have this change.
|
Ok((get_branch(qualified_ref), (*target_oid).into()))
|
||||||
spinner.finish();
|
|
||||||
|
|
||||||
let branch = get_branch(qualified_ref);
|
|
||||||
Ok((branch, (*target_oid).into()))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return the [`Oid`] of the merge target.
|
/// Return the [`Oid`] of the merge target.
|
||||||
|
|
@ -146,13 +141,8 @@ pub fn push_to_storage(
|
||||||
options: &Options,
|
options: &Options,
|
||||||
) -> anyhow::Result<()> {
|
) -> anyhow::Result<()> {
|
||||||
let head_oid = branch_oid(head_branch)?;
|
let head_oid = branch_oid(head_branch)?;
|
||||||
let mut spinner = term::spinner(format!(
|
|
||||||
"Looking for HEAD ({}) in storage...",
|
|
||||||
term::format::secondary(term::format::oid(head_oid))
|
|
||||||
));
|
|
||||||
if storage.commit(head_oid).is_err() {
|
if storage.commit(head_oid).is_err() {
|
||||||
if !options.push {
|
if !options.push {
|
||||||
spinner.failed();
|
|
||||||
term::blank();
|
term::blank();
|
||||||
|
|
||||||
return Err(Error::WithHint {
|
return Err(Error::WithHint {
|
||||||
|
|
@ -161,7 +151,6 @@ pub fn push_to_storage(
|
||||||
}
|
}
|
||||||
.into());
|
.into());
|
||||||
}
|
}
|
||||||
spinner.message("Pushing HEAD to storage...");
|
|
||||||
|
|
||||||
let output = match head_branch.upstream() {
|
let output = match head_branch.upstream() {
|
||||||
Ok(_) => git::run::<_, _, &str, &str>(Path::new("."), ["push", "rad"], [])?,
|
Ok(_) => git::run::<_, _, &str, &str>(Path::new("."), ["push", "rad"], [])?,
|
||||||
|
|
@ -172,14 +161,11 @@ pub fn push_to_storage(
|
||||||
)?,
|
)?,
|
||||||
};
|
};
|
||||||
if options.verbose {
|
if options.verbose {
|
||||||
spinner.finish();
|
|
||||||
term::blob(output);
|
term::blob(output);
|
||||||
|
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
spinner.finish();
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -66,7 +66,6 @@ fn show_patch_commit_info(
|
||||||
term::format::highlight(branch_name(head_branch)?),
|
term::format::highlight(branch_name(head_branch)?),
|
||||||
term::format::secondary(term::format::oid(head_oid)),
|
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
|
// 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.
|
// This can also happen *after* the patch is created.
|
||||||
|
|
|
||||||
|
|
@ -75,14 +75,14 @@ fn print(
|
||||||
&patch.timestamp(),
|
&patch.timestamp(),
|
||||||
)));
|
)));
|
||||||
|
|
||||||
let (_, revision) = patch
|
let (latest, revision) = patch
|
||||||
.latest()
|
.latest()
|
||||||
.ok_or_else(|| anyhow!("patch is malformed: no revisions found"))?;
|
.ok_or_else(|| anyhow!("patch is malformed: no revisions found"))?;
|
||||||
let mut widget = term::VStack::default()
|
let mut widget = term::VStack::default()
|
||||||
.child(
|
.child(
|
||||||
term::Line::spaced([
|
term::Line::spaced([
|
||||||
term::format::bold(patch.title()).into(),
|
term::format::bold(patch.title()).into(),
|
||||||
term::format::highlight(patch_id).into(),
|
term::format::highlight(term::format::cob(patch_id)).into(),
|
||||||
term::format::dim(format!("R{}", patch.version())).into(),
|
term::format::dim(format!("R{}", patch.version())).into(),
|
||||||
])
|
])
|
||||||
.space()
|
.space()
|
||||||
|
|
@ -99,62 +99,84 @@ fn print(
|
||||||
.border(Some(term::colors::FAINT));
|
.border(Some(term::colors::FAINT));
|
||||||
|
|
||||||
let mut timeline = Vec::new();
|
let mut timeline = Vec::new();
|
||||||
for merge in revision.merges.iter() {
|
for (revision_id, revision) in patch.revisions() {
|
||||||
let peer = repository.remote(&merge.node)?;
|
// Don't show an "update" line for the first revision.
|
||||||
let mut badges = Vec::new();
|
if revision_id != latest {
|
||||||
|
timeline.push((
|
||||||
if peer.delegate {
|
revision.timestamp,
|
||||||
badges.push(term::format::secondary("(delegate)").into());
|
term::Line::spaced(
|
||||||
}
|
[
|
||||||
if peer.id == *whoami {
|
term::format::tertiary("↑").into(),
|
||||||
badges.push(term::format::primary("(you)").into());
|
term::format::default("updated to").into(),
|
||||||
|
term::format::dim(revision_id).into(),
|
||||||
|
term::format::parens(term::format::secondary(term::format::oid(
|
||||||
|
revision.oid,
|
||||||
|
)))
|
||||||
|
.into(),
|
||||||
|
]
|
||||||
|
.into_iter(),
|
||||||
|
),
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
timeline.push((
|
for merge in revision.merges.iter() {
|
||||||
merge.timestamp,
|
let peer = repository.remote(&merge.node)?;
|
||||||
term::Line::spaced(
|
let mut badges = Vec::new();
|
||||||
[
|
|
||||||
term::format::secondary(term::format::dim("✓ merged")).into(),
|
|
||||||
term::format::default("by").into(),
|
|
||||||
term::format::tertiary(peer.id).into(),
|
|
||||||
]
|
|
||||||
.into_iter()
|
|
||||||
.chain(badges),
|
|
||||||
),
|
|
||||||
));
|
|
||||||
}
|
|
||||||
for (reviewer, review) in revision.reviews.iter() {
|
|
||||||
let verdict = match review.verdict() {
|
|
||||||
Some(Verdict::Accept) => term::format::positive(term::format::dim("✓ accepted")),
|
|
||||||
Some(Verdict::Reject) => term::format::negative(term::format::dim("✗ rejected")),
|
|
||||||
None => term::format::negative(term::format::dim("⋄ reviewed")),
|
|
||||||
};
|
|
||||||
let peer = repository.remote(reviewer)?;
|
|
||||||
let mut badges = Vec::new();
|
|
||||||
|
|
||||||
if peer.delegate {
|
if peer.delegate {
|
||||||
badges.push(term::format::secondary("(delegate)").into());
|
badges.push(term::format::secondary("(delegate)").into());
|
||||||
}
|
}
|
||||||
if peer.id == *whoami {
|
if peer.id == *whoami {
|
||||||
badges.push(term::format::primary("(you)").into());
|
badges.push(term::format::primary("(you)").into());
|
||||||
}
|
}
|
||||||
|
|
||||||
timeline.push((
|
timeline.push((
|
||||||
review.timestamp(),
|
merge.timestamp,
|
||||||
term::Line::spaced(
|
term::Line::spaced(
|
||||||
[
|
[
|
||||||
verdict.into(),
|
term::format::primary("✓").bold().into(),
|
||||||
term::format::default("by").into(),
|
term::format::default("merged").into(),
|
||||||
term::format::tertiary(reviewer).into(),
|
term::format::default("by").into(),
|
||||||
]
|
term::format::tertiary(Did::from(peer.id)).into(),
|
||||||
.into_iter()
|
]
|
||||||
.chain(badges),
|
.into_iter()
|
||||||
),
|
.chain(badges),
|
||||||
));
|
),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
for (reviewer, review) in revision.reviews.iter() {
|
||||||
|
let verdict = match review.verdict() {
|
||||||
|
Some(Verdict::Accept) => term::format::positive(term::format::dim("✓ accepted")),
|
||||||
|
Some(Verdict::Reject) => term::format::negative(term::format::dim("✗ rejected")),
|
||||||
|
None => term::format::negative(term::format::dim("⋄ reviewed")),
|
||||||
|
};
|
||||||
|
let peer = repository.remote(reviewer)?;
|
||||||
|
let mut badges = Vec::new();
|
||||||
|
|
||||||
|
if peer.delegate {
|
||||||
|
badges.push(term::format::secondary("(delegate)").into());
|
||||||
|
}
|
||||||
|
if peer.id == *whoami {
|
||||||
|
badges.push(term::format::primary("(you)").into());
|
||||||
|
}
|
||||||
|
|
||||||
|
timeline.push((
|
||||||
|
review.timestamp(),
|
||||||
|
term::Line::spaced(
|
||||||
|
[
|
||||||
|
verdict.into(),
|
||||||
|
term::format::default("by").into(),
|
||||||
|
term::format::tertiary(reviewer).into(),
|
||||||
|
]
|
||||||
|
.into_iter()
|
||||||
|
.chain(badges),
|
||||||
|
),
|
||||||
|
));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
timeline.sort_by_key(|(t, _)| *t);
|
timeline.sort_by_key(|(t, _)| *t);
|
||||||
|
|
||||||
for (time, mut line) in timeline.into_iter().rev() {
|
for (time, mut line) in timeline.into_iter() {
|
||||||
line.push(term::Label::space());
|
line.push(term::Label::space());
|
||||||
line.push(term::format::dim(term::format::timestamp(&time)));
|
line.push(term::format::dim(term::format::timestamp(&time)));
|
||||||
widget.push(line);
|
widget.push(line);
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,3 @@
|
||||||
use anyhow::Context;
|
|
||||||
|
|
||||||
use radicle::cob::patch;
|
use radicle::cob::patch;
|
||||||
use radicle::git;
|
use radicle::git;
|
||||||
use radicle::prelude::*;
|
use radicle::prelude::*;
|
||||||
|
|
@ -11,7 +9,7 @@ use crate::terminal as term;
|
||||||
|
|
||||||
const REVISION_MSG: &str = r#"
|
const REVISION_MSG: &str = r#"
|
||||||
<!--
|
<!--
|
||||||
Please enter a comment message for your patch update. Leaving this
|
Please enter a comment for your patch update. Leaving this
|
||||||
blank is also okay.
|
blank is also okay.
|
||||||
-->
|
-->
|
||||||
"#;
|
"#;
|
||||||
|
|
@ -26,27 +24,18 @@ fn select_patch(
|
||||||
let head_oid = branch_oid(head_branch)?;
|
let head_oid = branch_oid(head_branch)?;
|
||||||
let base_oid = workdir.merge_base(*target_oid, *head_oid)?;
|
let base_oid = workdir.merge_base(*target_oid, *head_oid)?;
|
||||||
|
|
||||||
let mut spinner = term::spinner("Finding patches to update...");
|
|
||||||
let mut result =
|
let mut result =
|
||||||
find_unmerged_with_base(*head_oid, *target_oid, base_oid, patches, workdir, whoami)?;
|
find_unmerged_with_base(*head_oid, *target_oid, base_oid, patches, workdir, whoami)?;
|
||||||
|
|
||||||
let Some((id, patch, _)) = result.pop() else {
|
let Some((id, _, _)) = result.pop() else {
|
||||||
spinner.failed();
|
|
||||||
term::blank();
|
term::blank();
|
||||||
anyhow::bail!("No patches found that share a base, please create a new patch or specify the patch id manually");
|
anyhow::bail!("No patches found to update, please open a new patch or specify the patch id manually");
|
||||||
};
|
};
|
||||||
|
|
||||||
if !result.is_empty() {
|
if !result.is_empty() {
|
||||||
spinner.failed();
|
|
||||||
term::blank();
|
term::blank();
|
||||||
anyhow::bail!("More than one patch available to update, please specify an id with `rad patch --update <id>`");
|
anyhow::bail!("More than one patch available to update, please specify an id with `rad patch --update <id>`");
|
||||||
}
|
}
|
||||||
spinner.message(format!(
|
|
||||||
"Found existing patch {} {}",
|
|
||||||
term::format::tertiary(term::format::cob(&id)),
|
|
||||||
term::format::italic(patch.title())
|
|
||||||
));
|
|
||||||
spinner.finish();
|
|
||||||
term::blank();
|
term::blank();
|
||||||
|
|
||||||
Ok(id)
|
Ok(id)
|
||||||
|
|
@ -63,20 +52,20 @@ fn show_update_commit_info(
|
||||||
let current_version = patch.version();
|
let current_version = patch.version();
|
||||||
let head_oid = branch_oid(head_branch)?;
|
let head_oid = branch_oid(head_branch)?;
|
||||||
|
|
||||||
term::blank();
|
|
||||||
term::info!(
|
term::info!(
|
||||||
"{} {} ({}) -> {} ({})",
|
"{} {} {} -> {} {}",
|
||||||
term::format::tertiary(term::format::cob(patch_id)),
|
term::format::tertiary(term::format::cob(patch_id)),
|
||||||
term::format::dim(format!("R{current_version}")),
|
term::format::dim(format!("R{current_version}")),
|
||||||
term::format::secondary(term::format::oid(current_revision.oid)),
|
term::format::parens(term::format::secondary(term::format::oid(
|
||||||
|
current_revision.oid
|
||||||
|
))),
|
||||||
term::format::dim(format!("R{}", current_version + 1)),
|
term::format::dim(format!("R{}", current_version + 1)),
|
||||||
term::format::secondary(term::format::oid(*head_oid)),
|
term::format::parens(term::format::secondary(term::format::oid(*head_oid))),
|
||||||
);
|
);
|
||||||
|
|
||||||
// Difference between the two revisions.
|
// Difference between the two revisions.
|
||||||
let head_oid = branch_oid(head_branch)?;
|
let head_oid = branch_oid(head_branch)?;
|
||||||
term::patch::print_commits_ahead_behind(workdir, *head_oid, *current_revision.oid)?;
|
term::patch::print_commits_ahead_behind(workdir, *head_oid, *current_revision.oid)?;
|
||||||
term::blank();
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
@ -90,18 +79,9 @@ pub fn run(
|
||||||
message: term::patch::Message,
|
message: term::patch::Message,
|
||||||
options: &Options,
|
options: &Options,
|
||||||
) -> anyhow::Result<()> {
|
) -> anyhow::Result<()> {
|
||||||
let project = storage.project_of(&profile.public_key).context(format!(
|
|
||||||
"couldn't load project {} from local state",
|
|
||||||
storage.id
|
|
||||||
))?;
|
|
||||||
// `HEAD`; This is what we are proposing as a patch.
|
// `HEAD`; This is what we are proposing as a patch.
|
||||||
let head_branch = try_branch(workdir.head()?)?;
|
let head_branch = try_branch(workdir.head()?)?;
|
||||||
|
|
||||||
term::headline(format!(
|
|
||||||
"🌱 Updating patch for {}",
|
|
||||||
term::format::highlight(project.name())
|
|
||||||
));
|
|
||||||
|
|
||||||
push_to_storage(storage, &head_branch, options)?;
|
push_to_storage(storage, &head_branch, options)?;
|
||||||
|
|
||||||
let (_, target_oid) = get_merge_target(storage, &head_branch)?;
|
let (_, target_oid) = get_merge_target(storage, &head_branch)?;
|
||||||
|
|
@ -128,11 +108,14 @@ pub fn run(
|
||||||
let base_oid = workdir.merge_base(*target_oid, *head_oid)?;
|
let base_oid = workdir.merge_base(*target_oid, *head_oid)?;
|
||||||
let message = message.get(REVISION_MSG);
|
let message = message.get(REVISION_MSG);
|
||||||
let signer = term::signer(profile)?;
|
let signer = term::signer(profile)?;
|
||||||
patch.update(message, base_oid, *head_oid, &signer)?;
|
let revision = patch.update(message, base_oid, *head_oid, &signer)?;
|
||||||
|
|
||||||
term::blank();
|
term::blank();
|
||||||
term::success!("Patch {} updated 🌱", term::format::highlight(patch_id));
|
term::success!(
|
||||||
term::blank();
|
"Patch {} updated to {}",
|
||||||
|
term::format::highlight(term::format::cob(&patch_id)),
|
||||||
|
term::format::tertiary(revision),
|
||||||
|
);
|
||||||
|
|
||||||
if options.announce {
|
if options.announce {
|
||||||
// TODO
|
// TODO
|
||||||
|
|
|
||||||
|
|
@ -23,9 +23,14 @@ pub fn oid(oid: impl Into<radicle::git::Oid>) -> String {
|
||||||
format!("{:.7}", oid.into())
|
format!("{:.7}", oid.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Wrap parenthesis around styled input, eg. `"input"` -> `"(input)"`.
|
||||||
|
pub fn parens<D: fmt::Display>(input: Paint<D>) -> Paint<String> {
|
||||||
|
Paint::new(format!("({})", input.item)).with_style(input.style)
|
||||||
|
}
|
||||||
|
|
||||||
/// Format a COB id.
|
/// Format a COB id.
|
||||||
pub fn cob(id: &ObjectId) -> String {
|
pub fn cob(id: &ObjectId) -> String {
|
||||||
format!("{:.11}", id.to_string())
|
format!("{:.7}", id.to_string())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Format a timestamp.
|
/// Format a timestamp.
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue