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) ``` (stderr)
$ git push $ git push
4b6618a6ccb0b406659364a70a00bb60e4cd7cf0 ✓ Patch 8678aaf updated to 4b6618a6ccb0b406659364a70a00bb60e4cd7cf0
To rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi To rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
b94a835..662843e feature/2 -> patches/8678aafff1d1e28430952abf431e60b87e28023c b94a835..662843e feature/2 -> patches/8678aafff1d1e28430952abf431e60b87e28023c
``` ```
@ -203,7 +203,7 @@ use `--force` to force the update.
``` (stderr) ``` (stderr)
$ git push --force $ git push --force
983f2d21c9fbe91c21ddfbcd3e3d6cd13db0a944 ✓ Patch 8678aaf updated to 983f2d21c9fbe91c21ddfbcd3e3d6cd13db0a944
To rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi To rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
+ 662843e...3507cd5 feature/2 -> patches/8678aafff1d1e28430952abf431e60b87e28023c (forced update) + 662843e...3507cd5 feature/2 -> patches/8678aafff1d1e28430952abf431e60b87e28023c (forced update)
``` ```

View File

@ -7,13 +7,6 @@ use super::common::*;
use super::Options; use super::Options;
use crate::terminal as term; 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( fn select_patch(
patches: &patch::Patches, patches: &patch::Patches,
storage: &Repository, storage: &Repository,
@ -100,9 +93,7 @@ pub fn run(
let head_oid = branch_oid(&head_branch)?; let head_oid = branch_oid(&head_branch)?;
let base_oid = storage.backend.merge_base(*target_oid, *head_oid)?; let base_oid = storage.backend.merge_base(*target_oid, *head_oid)?;
let message = message.get(REVISION_MSG)?; let message = term::patch::get_update_message(message)?;
let message = message.replace(REVISION_MSG.trim(), "");
let message = message.trim();
let signer = term::signer(profile)?; let signer = term::signer(profile)?;
let revision = patch.update(message, base_oid, *head_oid, &signer)?; 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. /// Combine the title and description fields to display to the user.
#[inline] #[inline]
pub fn message(title: &str, description: &str) -> String { pub fn message(title: &str, description: &str) -> String {
@ -95,6 +102,15 @@ pub fn get_message(
Ok((title, description)) 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. /// List the given commits in a table.
pub fn list_commits(commits: &[git::raw::Commit]) -> anyhow::Result<()> { pub fn list_commits(commits: &[git::raw::Commit]) -> anyhow::Result<()> {
let mut table = term::Table::default(); let mut table = term::Table::default();

View File

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

View File

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