remote-helper: Create patch drafts via `git push`

This is now possible via the `-o patch.draft` push option.
This commit is contained in:
Alexis Sellier 2023-06-07 15:02:05 +02:00
parent 6bbdc574f0
commit 547fdcc03b
No known key found for this signature in database
3 changed files with 49 additions and 22 deletions

View File

@ -7,9 +7,11 @@ $ git commit -a -m "Nothing to see here.." -q --allow-empty
To open a patch in draft mode, we use the `--draft` option: To open a patch in draft mode, we use the `--draft` option:
``` ``` (stderr)
$ rad patch open --draft -m "Nothing yet" --quiet $ git push -o patch.draft -o patch.message="Nothing yet" rad HEAD:refs/patches
c639a0f9895a0fdf2ba2d04533290937cb6fd2f7 ✓ Patch c639a0f9895a0fdf2ba2d04533290937cb6fd2f7 drafted
To rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
* [new reference] HEAD -> refs/patches
``` ```
We can confirm it's a draft by running `show`: We can confirm it's a draft by running `show`:

View File

@ -54,10 +54,12 @@ pub enum Error {
List(#[from] list::Error), List(#[from] list::Error),
} }
#[derive(Debug, Default)] #[derive(Debug, Default, Clone)]
pub struct Options { pub struct Options {
/// Don't sync after push. /// Don't sync after push.
no_sync: bool, no_sync: bool,
/// Open patch in draft mode.
draft: bool,
/// Patch message. /// Patch message.
message: cli::patch::Message, message: cli::patch::Message,
} }
@ -108,6 +110,7 @@ pub fn run(profile: radicle::Profile) -> Result<(), Error> {
match *args { match *args {
["sync"] => opts.no_sync = false, ["sync"] => opts.no_sync = false,
["no-sync"] => opts.no_sync = true, ["no-sync"] => opts.no_sync = true,
["patch.draft"] => opts.draft = true,
_ => { _ => {
let args = args.join(" "); let args = args.join(" ");

View File

@ -175,7 +175,7 @@ pub fn run(
let working = git::raw::Repository::open(working)?; let working = git::raw::Repository::open(working)?;
if dst == &*rad::PATCHES_REFNAME { if dst == &*rad::PATCHES_REFNAME {
patch_open(opts.message.clone(), src, &nid, &working, stored, &signer) patch_open(src, &nid, &working, stored, &signer, opts.clone())
} else { } else {
let dst = git::Qualified::from_refstr(dst) let dst = git::Qualified::from_refstr(dst)
.ok_or_else(|| Error::InvalidQualifiedRef(dst.clone()))?; .ok_or_else(|| Error::InvalidQualifiedRef(dst.clone()))?;
@ -184,7 +184,6 @@ pub fn run(
let oid = git::Oid::from_str(oid)?; let oid = git::Oid::from_str(oid)?;
patch_update( patch_update(
opts.message.clone(),
src, src,
&dst, &dst,
*force, *force,
@ -193,6 +192,7 @@ pub fn run(
&working, &working,
stored, stored,
&signer, &signer,
opts.clone(),
) )
} else { } else {
push(src, &dst, *force, &nid, &working, stored, &signer) push(src, &dst, *force, &nid, &working, stored, &signer)
@ -237,12 +237,12 @@ pub fn run(
/// Open a new patch. /// Open a new patch.
fn patch_open<G: Signer>( fn patch_open<G: Signer>(
msg: cli::patch::Message,
src: &git::RefStr, src: &git::RefStr,
nid: &NodeId, nid: &NodeId,
working: &git::raw::Repository, working: &git::raw::Repository,
stored: &storage::git::Repository, stored: &storage::git::Repository,
signer: &G, signer: &G,
opts: Options,
) -> Result<(), Error> { ) -> Result<(), Error> {
let reference = working.find_reference(src.as_str())?; let reference = working.find_reference(src.as_str())?;
let commit = reference.peel_to_commit()?; let commit = reference.peel_to_commit()?;
@ -259,26 +259,48 @@ fn patch_open<G: Signer>(
let (_, target) = stored.canonical_head()?; let (_, target) = stored.canonical_head()?;
let base = stored.backend.merge_base(*target, commit.id())?; let base = stored.backend.merge_base(*target, commit.id())?;
let (title, description) = let (title, description) = cli::patch::get_create_message(
cli::patch::get_create_message(msg, &stored.backend, &base.into(), &commit.id().into())?; opts.message,
&stored.backend,
&base.into(),
&commit.id().into(),
)?;
let mut patches = patch::Patches::open(stored)?; let mut patches = patch::Patches::open(stored)?;
let result = match patches.create( let patch = if opts.draft {
&title, patches.draft(
&description, &title,
patch::MergeTarget::default(), &description,
base, patch::MergeTarget::default(),
commit.id(), base,
&[], commit.id(),
signer, &[],
) { signer,
)
} else {
patches.create(
&title,
&description,
patch::MergeTarget::default(),
base,
commit.id(),
&[],
signer,
)
};
let result = match patch {
Ok(patch) => { Ok(patch) => {
let action = if patch.is_draft() {
"drafted"
} else {
"opened"
};
let patch = patch.id; let patch = patch.id;
eprintln!( eprintln!(
"{} Patch {} opened", "{} Patch {} {action}",
cli::format::positive(""), cli::format::positive(""),
cli::format::tertiary(patch) cli::format::tertiary(patch),
); );
// Create long-lived patch head reference, now that we know the Patch ID. // Create long-lived patch head reference, now that we know the Patch ID.
@ -339,7 +361,6 @@ fn patch_open<G: Signer>(
/// Update an existing patch. /// Update an existing patch.
#[allow(clippy::too_many_arguments)] #[allow(clippy::too_many_arguments)]
fn patch_update<G: Signer>( fn patch_update<G: Signer>(
msg: cli::patch::Message,
src: &git::RefStr, src: &git::RefStr,
dst: &git::Qualified, dst: &git::Qualified,
force: bool, force: bool,
@ -348,6 +369,7 @@ fn patch_update<G: Signer>(
working: &git::raw::Repository, working: &git::raw::Repository,
stored: &storage::git::Repository, stored: &storage::git::Repository,
signer: &G, signer: &G,
opts: Options,
) -> Result<(), Error> { ) -> Result<(), Error> {
let reference = working.find_reference(src.as_str())?; let reference = working.find_reference(src.as_str())?;
let commit = reference.peel_to_commit()?; let commit = reference.peel_to_commit()?;
@ -366,7 +388,7 @@ fn patch_update<G: Signer>(
return Ok(()); return Ok(());
} }
let message = cli::patch::get_update_message( let message = cli::patch::get_update_message(
msg, opts.message,
&stored.backend, &stored.backend,
patch.latest().1, patch.latest().1,
&commit.id().into(), &commit.id().into(),