cli: Use library for updating patch

Also improves the message from a bare revision id.
This commit is contained in:
Alexis Sellier 2023-05-12 16:28:58 +02:00
parent 51dced4808
commit a9c0152a99
No known key found for this signature in database
5 changed files with 52 additions and 29 deletions

View File

@ -114,7 +114,7 @@ $ git commit -a -m "Improve code" -q --allow-empty
``` (stderr)
$ git push
4b6618a6ccb0b406659364a70a00bb60e4cd7cf0
✓ Patch 8678aaf updated to 4b6618a6ccb0b406659364a70a00bb60e4cd7cf0
To rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
b94a835..662843e feature/2 -> patches/8678aafff1d1e28430952abf431e60b87e28023c
```
@ -203,7 +203,7 @@ use `--force` to force the update.
``` (stderr)
$ git push --force
983f2d21c9fbe91c21ddfbcd3e3d6cd13db0a944
✓ Patch 8678aaf updated to 983f2d21c9fbe91c21ddfbcd3e3d6cd13db0a944
To rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
+ 662843e...3507cd5 feature/2 -> patches/8678aafff1d1e28430952abf431e60b87e28023c (forced update)
```

View File

@ -7,13 +7,6 @@ use super::common::*;
use super::Options;
use crate::terminal as term;
const REVISION_MSG: &str = r#"
<!--
Please enter a comment for your patch update. Leaving this
blank is also okay.
-->
"#;
fn select_patch(
patches: &patch::Patches,
storage: &Repository,
@ -100,9 +93,7 @@ pub fn run(
let head_oid = branch_oid(&head_branch)?;
let base_oid = storage.backend.merge_base(*target_oid, *head_oid)?;
let message = message.get(REVISION_MSG)?;
let message = message.replace(REVISION_MSG.trim(), "");
let message = message.trim();
let message = term::patch::get_update_message(message)?;
let signer = term::signer(profile)?;
let revision = patch.update(message, base_oid, *head_oid, &signer)?;

View File

@ -63,6 +63,13 @@ and description.
-->
"#;
const REVISION_MSG: &str = r#"
<!--
Please enter a comment for your patch update. Leaving this
blank is also okay.
-->
"#;
/// Combine the title and description fields to display to the user.
#[inline]
pub fn message(title: &str, description: &str) -> String {
@ -95,6 +102,15 @@ pub fn get_message(
Ok((title, description))
}
/// Get a patch update message.
pub fn get_update_message(message: term::patch::Message) -> io::Result<String> {
let message = message.get(REVISION_MSG)?;
let message = message.replace(REVISION_MSG.trim(), "");
let message = message.trim();
Ok(message.to_owned())
}
/// List the given commits in a table.
pub fn list_commits(commits: &[git::raw::Commit]) -> anyhow::Result<()> {
let mut table = term::Table::default();

View File

@ -1,3 +1,4 @@
#![warn(clippy::unwrap_used)]
//! The Radicle Git remote helper.
//!
//! Communication with the user is done via `stderr` (`eprintln`).

View File

@ -58,6 +58,12 @@ pub enum Error {
/// Patch COB error.
#[error(transparent)]
Patch(#[from] radicle::cob::patch::Error),
/// Patch not found in store.
#[error("patch `{0}` not found")]
NotFound(patch::PatchId),
/// COB store error.
#[error(transparent)]
Cob(#[from] radicle::cob::store::Error),
}
enum Command {
@ -158,7 +164,7 @@ pub fn run(
if let Some(oid) = dst.strip_prefix(git::refname!("refs/heads/patches")) {
let oid = git::Oid::from_str(oid)?;
patch_update(src, dst, *force, &oid, &nid, &working, stored.raw())
patch_update(src, dst, *force, &oid, &nid, &working, stored, &signer)
} else if dst == &*rad::PATCHES_REFNAME {
patch_open(src, &nid, &working, stored, &signer)
} else {
@ -224,7 +230,7 @@ fn patch_open<G: Signer>(
// not fail, since the reference will already exist with the correct OID.
push_ref(src, dst, false, nid, working, stored.raw())?;
let mut patches = patch::Patches::open(stored).unwrap();
let mut patches = patch::Patches::open(stored)?;
let message = commit.message().unwrap_or_default();
let (title, description) = cli::patch::get_message(cli::patch::Message::Edit, message)?;
let (_, target) = stored.canonical_head()?;
@ -303,31 +309,40 @@ fn patch_open<G: Signer>(
}
/// Update an existing patch.
fn patch_update(
#[allow(clippy::too_many_arguments)]
fn patch_update<G: Signer>(
src: &git::RefStr,
dst: &git::RefStr,
force: bool,
oid: &git::Oid,
nid: &NodeId,
working: &git::raw::Repository,
stored: &git::raw::Repository,
stored: &storage::git::Repository,
signer: &G,
) -> Result<(), Error> {
push_ref(src, dst, force, nid, working, stored)?;
let reference = working.find_reference(src.as_str())?;
let commit = reference.peel_to_commit()?;
let patch_id = radicle::cob::ObjectId::from(oid);
// Patch ID.
let oid = radicle::cob::ObjectId::from(oid);
let stderr = io::stderr().as_raw_fd();
push_ref(src, dst, force, nid, working, stored.raw())?;
// Nb. Git tooling checks that we aren't attempting a forced update without the `--force`
// option of `git push`. There's no need for us to check here.
let mut patches = patch::Patches::open(stored)?;
let Ok(mut patch) = patches.get_mut(&patch_id) else {
return Err(Error::NotFound(patch_id));
};
let message = cli::patch::get_update_message(cli::patch::Message::Edit)?;
let (_, target) = stored.canonical_head()?;
let base = stored.backend.merge_base(*target, commit.id())?;
let revision = patch.update(message, base, commit.id(), signer)?;
execute(
"rad",
["patch", "update", "--quiet", "--no-push", &oid.to_string()],
unsafe { process::Stdio::from_raw_fd(stderr) },
)
.map(|_| ())
.map_err(Error::from)
eprintln!(
"{} Patch {} updated to {}",
cli::format::positive(""),
cli::format::dim(cli::format::cob(&patch_id)),
cli::format::tertiary(revision)
);
Ok(())
}
/// Push a single reference to storage.