cli: add un/resolve for patch review comments
Patch review comments can be resolved and unresolved as part of the Patch COB API. This functionality was missing from the `rad patch command`. Add a subcommand `rad patch resolve` which can resolve a review comment, and unresolve given the `--undo` flag. Signed-off-by: Fintan Halpenny <fintan.halpenny@gmail.com> X-Clacks-Overhead: GNU Terry Pratchett
This commit is contained in:
parent
84aaf9efd0
commit
fa19105f2f
|
|
@ -22,6 +22,8 @@ mod list;
|
|||
mod ready;
|
||||
#[path = "patch/redact.rs"]
|
||||
mod redact;
|
||||
#[path = "patch/resolve.rs"]
|
||||
mod resolve;
|
||||
#[path = "patch/review.rs"]
|
||||
mod review;
|
||||
#[path = "patch/show.rs"]
|
||||
|
|
@ -61,6 +63,7 @@ Usage
|
|||
rad patch update <patch-id> [<option>...]
|
||||
rad patch checkout <patch-id> [<option>...]
|
||||
rad patch review <patch-id> [--accept | --reject] [-m [<string>]] [-d | --delete] [<option>...]
|
||||
rad patch resolve <patch-id> [--review <review-id>] [--comment <comment-id>] [--unresolve] [<option>...]
|
||||
rad patch delete <patch-id> [<option>...]
|
||||
rad patch redact <revision-id> [<option>...]
|
||||
rad patch assign <revision-id> [--add <did>] [--delete <did>] [<option>...]
|
||||
|
|
@ -101,6 +104,12 @@ Review options
|
|||
-d, --delete Delete a review draft
|
||||
-m, --message [<string>] Provide a comment with the review (default: prompt)
|
||||
|
||||
Resolve options
|
||||
|
||||
--review <id> The review id which the comment is under
|
||||
--comment <id> The comment to (un)resolve
|
||||
--undo Unresolve the comment
|
||||
|
||||
Assign options
|
||||
|
||||
-a, --add <did> Add an assignee to the patch (may be specified multiple times).
|
||||
|
|
@ -169,6 +178,7 @@ pub enum OperationName {
|
|||
Comment,
|
||||
Ready,
|
||||
Review,
|
||||
Resolve,
|
||||
Label,
|
||||
#[default]
|
||||
List,
|
||||
|
|
@ -232,6 +242,12 @@ pub enum Operation {
|
|||
revision_id: Option<Rev>,
|
||||
opts: review::Options,
|
||||
},
|
||||
Resolve {
|
||||
patch_id: Rev,
|
||||
review_id: Rev,
|
||||
comment_id: Rev,
|
||||
undo: bool,
|
||||
},
|
||||
Assign {
|
||||
patch_id: Rev,
|
||||
opts: AssignOptions,
|
||||
|
|
@ -268,6 +284,7 @@ impl Operation {
|
|||
| Operation::Delete { .. }
|
||||
| Operation::Comment { .. }
|
||||
| Operation::Review { .. }
|
||||
| Operation::Resolve { .. }
|
||||
| Operation::Assign { .. }
|
||||
| Operation::Label { .. }
|
||||
| Operation::Edit { .. }
|
||||
|
|
@ -306,6 +323,8 @@ impl Args for Options {
|
|||
let mut announce = true;
|
||||
let mut patch_id = None;
|
||||
let mut revision_id = None;
|
||||
let mut review_id = None;
|
||||
let mut comment_id = None;
|
||||
let mut message = Message::default();
|
||||
let mut filter = Some(patch::Status::Open);
|
||||
let mut diff = false;
|
||||
|
|
@ -442,6 +461,23 @@ impl Args for Options {
|
|||
}
|
||||
}
|
||||
|
||||
// Resolve options
|
||||
Long("undo") if op == Some(OperationName::Resolve) => {
|
||||
undo = true;
|
||||
}
|
||||
Long("review") if op == Some(OperationName::Resolve) => {
|
||||
let val = parser.value()?;
|
||||
let rev = term::args::rev(&val)?;
|
||||
|
||||
review_id = Some(rev);
|
||||
}
|
||||
Long("comment") if op == Some(OperationName::Resolve) => {
|
||||
let val = parser.value()?;
|
||||
let rev = term::args::rev(&val)?;
|
||||
|
||||
comment_id = Some(rev);
|
||||
}
|
||||
|
||||
// Checkout options
|
||||
Long("revision") if op == Some(OperationName::Checkout) => {
|
||||
let val = parser.value()?;
|
||||
|
|
@ -545,6 +581,7 @@ impl Args for Options {
|
|||
"label" => op = Some(OperationName::Label),
|
||||
"comment" => op = Some(OperationName::Comment),
|
||||
"review" => op = Some(OperationName::Review),
|
||||
"resolve" => op = Some(OperationName::Resolve),
|
||||
"set" => op = Some(OperationName::Set),
|
||||
"cache" => op = Some(OperationName::Cache),
|
||||
unknown => anyhow::bail!("unknown operation '{}'", unknown),
|
||||
|
|
@ -565,6 +602,7 @@ impl Args for Options {
|
|||
Some(OperationName::Checkout),
|
||||
Some(OperationName::Comment),
|
||||
Some(OperationName::Review),
|
||||
Some(OperationName::Resolve),
|
||||
Some(OperationName::Edit),
|
||||
Some(OperationName::Set),
|
||||
Some(OperationName::Assign),
|
||||
|
|
@ -623,6 +661,13 @@ impl Args for Options {
|
|||
op: review_op,
|
||||
},
|
||||
},
|
||||
OperationName::Resolve => Operation::Resolve {
|
||||
patch_id: patch_id
|
||||
.ok_or_else(|| anyhow!("a patch or revision must be provided"))?,
|
||||
review_id: review_id.ok_or_else(|| anyhow!("a review must be provided"))?,
|
||||
comment_id: comment_id.ok_or_else(|| anyhow!("a comment must be provided"))?,
|
||||
undo,
|
||||
},
|
||||
OperationName::Ready => Operation::Ready {
|
||||
patch_id: patch_id.ok_or_else(|| anyhow!("a patch must be provided"))?,
|
||||
undo,
|
||||
|
|
@ -804,6 +849,25 @@ pub fn run(options: Options, ctx: impl term::Context) -> anyhow::Result<()> {
|
|||
.map(patch::RevisionId::from);
|
||||
review::run(patch_id, revision_id, opts, &profile, &repository)?;
|
||||
}
|
||||
Operation::Resolve {
|
||||
ref patch_id,
|
||||
ref review_id,
|
||||
ref comment_id,
|
||||
undo,
|
||||
} => {
|
||||
let patch = patch_id.resolve(&repository.backend)?;
|
||||
let review = patch::ReviewId::from(
|
||||
review_id.resolve::<radicle::cob::EntryId>(&repository.backend)?,
|
||||
);
|
||||
let comment = comment_id.resolve(&repository.backend)?;
|
||||
if undo {
|
||||
resolve::unresolve(patch, review, comment, &repository, &profile)?;
|
||||
term::success!("Unresolved comment {comment_id}");
|
||||
} else {
|
||||
resolve::resolve(patch, review, comment, &repository, &profile)?;
|
||||
term::success!("Resolved comment {comment_id}");
|
||||
}
|
||||
}
|
||||
Operation::Edit {
|
||||
patch_id,
|
||||
revision_id,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,42 @@
|
|||
use anyhow::anyhow;
|
||||
use radicle::cob::thread::CommentId;
|
||||
use radicle::patch::{self, PatchId};
|
||||
use radicle::patch::{cache::Patches as _, ReviewId};
|
||||
use radicle::storage::git::Repository;
|
||||
use radicle::Profile;
|
||||
|
||||
use crate::terminal as term;
|
||||
|
||||
pub fn resolve(
|
||||
patch_id: PatchId,
|
||||
review: ReviewId,
|
||||
comment: CommentId,
|
||||
repo: &Repository,
|
||||
profile: &Profile,
|
||||
) -> anyhow::Result<()> {
|
||||
let signer = term::signer(profile)?;
|
||||
let mut patches = profile.patches_mut(repo)?;
|
||||
let patch = patches
|
||||
.get(&patch_id)?
|
||||
.ok_or_else(|| anyhow!("Patch `{patch_id}` not found"))?;
|
||||
let mut patch = patch::PatchMut::new(patch_id, patch, &mut patches);
|
||||
patch.resolve_review_comment(review, comment, &signer)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn unresolve(
|
||||
patch_id: PatchId,
|
||||
review: ReviewId,
|
||||
comment: CommentId,
|
||||
repo: &Repository,
|
||||
profile: &Profile,
|
||||
) -> anyhow::Result<()> {
|
||||
let signer = term::signer(profile)?;
|
||||
let mut patches = profile.patches_mut(repo)?;
|
||||
let patch = patches
|
||||
.get(&patch_id)?
|
||||
.ok_or_else(|| anyhow!("Patch `{patch_id}` not found"))?;
|
||||
let mut patch = patch::PatchMut::new(patch_id, patch, &mut patches);
|
||||
patch.unresolve_review_comment(review, comment, &signer)?;
|
||||
Ok(())
|
||||
}
|
||||
Loading…
Reference in New Issue