remote-helper: Patch message option when pushing

Allows for setting a patch message during a push. Eg.:

    $ git push -o patch.message="My Title" -o patch.message="My description" \
      rad HEAD:refs/patches

Works the same way as the `-m` flag of `git commit`.
This commit is contained in:
Alexis Sellier 2023-06-06 12:26:30 +02:00
parent 6578fedfbb
commit e86e061a12
No known key found for this signature in database
3 changed files with 50 additions and 25 deletions

View File

@ -7,8 +7,8 @@ When we push to this ref, a patch is created from our commits.
$ git checkout -b feature/1 $ git checkout -b feature/1
Switched to a new branch 'feature/1' Switched to a new branch 'feature/1'
$ git commit -a -m "Add things" -q --allow-empty $ git commit -a -m "Add things" -q --allow-empty
$ git push rad HEAD:refs/patches $ git push -o patch.message="Add things #1" -o patch.message="See commits for details." rad HEAD:refs/patches
✓ Patch 37f53b4104edaafcf6beb65e7292147711a06ad0 opened ✓ Patch 2647168c23e7c2b2c1936d695443944e143bc3f7 opened
To rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi To rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
* [new reference] HEAD -> refs/patches * [new reference] HEAD -> refs/patches
``` ```
@ -16,15 +16,17 @@ To rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkE
We can see a patch was created: We can see a patch was created:
``` ```
$ rad patch show 37f53b4 $ rad patch show 2647168
╭────────────────────────────────────────────────────────────────────╮ ╭────────────────────────────────────────────────────────────────────╮
│ Title Add things │ Title Add things #1
│ Patch 37f53b4104edaafcf6beb65e7292147711a06ad0 │ Patch 2647168c23e7c2b2c1936d695443944e143bc3f7
│ Author did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi │ │ Author did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi │
│ Head 42d894a83c9c356552a57af09ccdbd5587a99045 │ │ Head 42d894a83c9c356552a57af09ccdbd5587a99045 │
│ Branches feature/1 │ │ Branches feature/1 │
│ Commits ahead 1, behind 0 │ │ Commits ahead 1, behind 0 │
│ Status open │ │ Status open │
│ │
│ See commits for details. │
├────────────────────────────────────────────────────────────────────┤ ├────────────────────────────────────────────────────────────────────┤
│ 42d894a Add things │ │ 42d894a Add things │
├────────────────────────────────────────────────────────────────────┤ ├────────────────────────────────────────────────────────────────────┤
@ -37,7 +39,7 @@ branch associated with this patch:
``` ```
$ git branch -vv $ git branch -vv
* feature/1 42d894a [rad/patches/37f53b4104edaafcf6beb65e7292147711a06ad0] Add things * feature/1 42d894a [rad/patches/2647168c23e7c2b2c1936d695443944e143bc3f7] Add things
master f2de534 [rad/master] Second commit master f2de534 [rad/master] Second commit
``` ```
@ -45,7 +47,7 @@ Let's check that it's up to date with our local head:
``` ```
$ git status --short --branch $ git status --short --branch
## feature/1...rad/patches/37f53b4104edaafcf6beb65e7292147711a06ad0 ## feature/1...rad/patches/2647168c23e7c2b2c1936d695443944e143bc3f7
$ git fetch $ git fetch
$ git push $ git push
``` ```
@ -57,13 +59,13 @@ $ git show-ref
42d894a83c9c356552a57af09ccdbd5587a99045 refs/heads/feature/1 42d894a83c9c356552a57af09ccdbd5587a99045 refs/heads/feature/1
f2de534b5e81d7c6e2dcaf58c3dd91573c0a0354 refs/heads/master f2de534b5e81d7c6e2dcaf58c3dd91573c0a0354 refs/heads/master
f2de534b5e81d7c6e2dcaf58c3dd91573c0a0354 refs/remotes/rad/master f2de534b5e81d7c6e2dcaf58c3dd91573c0a0354 refs/remotes/rad/master
42d894a83c9c356552a57af09ccdbd5587a99045 refs/remotes/rad/patches/37f53b4104edaafcf6beb65e7292147711a06ad0 42d894a83c9c356552a57af09ccdbd5587a99045 refs/remotes/rad/patches/2647168c23e7c2b2c1936d695443944e143bc3f7
``` ```
``` ```
$ git ls-remote rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi 'refs/heads/patches/*' $ git ls-remote rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi 'refs/heads/patches/*'
42d894a83c9c356552a57af09ccdbd5587a99045 refs/heads/patches/37f53b4104edaafcf6beb65e7292147711a06ad0 42d894a83c9c356552a57af09ccdbd5587a99045 refs/heads/patches/2647168c23e7c2b2c1936d695443944e143bc3f7
$ git ls-remote rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi 'refs/cobs/*' $ git ls-remote rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi 'refs/cobs/*'
37f53b4104edaafcf6beb65e7292147711a06ad0 refs/cobs/xyz.radicle.patch/37f53b4104edaafcf6beb65e7292147711a06ad0 2647168c23e7c2b2c1936d695443944e143bc3f7 refs/cobs/xyz.radicle.patch/2647168c23e7c2b2c1936d695443944e143bc3f7
``` ```
We can also create patches by pushing to the `rad/patches` remote. It's a bit We can also create patches by pushing to the `rad/patches` remote. It's a bit
@ -82,7 +84,7 @@ We see both branches with upstreams now:
``` ```
$ git branch -vv $ git branch -vv
feature/1 42d894a [rad/patches/37f53b4104edaafcf6beb65e7292147711a06ad0] Add things feature/1 42d894a [rad/patches/2647168c23e7c2b2c1936d695443944e143bc3f7] Add things
* feature/2 b94a835 [rad/patches/2af090f48003d86f735163794bfffdb2691f369e] Add more things * feature/2 b94a835 [rad/patches/2af090f48003d86f735163794bfffdb2691f369e] Add more things
master f2de534 [rad/master] Second commit master f2de534 [rad/master] Second commit
``` ```
@ -94,8 +96,8 @@ $ rad patch
╭────────────────────────────────────────────────────────────────────────────────────╮ ╭────────────────────────────────────────────────────────────────────────────────────╮
│ ● ID Title Author Head + - Updated │ │ ● ID Title Author Head + - Updated │
├────────────────────────────────────────────────────────────────────────────────────┤ ├────────────────────────────────────────────────────────────────────────────────────┤
│ ● 2647168 Add things #1 z6MknSL…StBU8Vi (you) 42d894a +0 -0 [ ... ] │
│ ● 2af090f Add more things z6MknSL…StBU8Vi (you) b94a835 +0 -0 [ ... ] │ │ ● 2af090f Add more things z6MknSL…StBU8Vi (you) b94a835 +0 -0 [ ... ] │
│ ● 37f53b4 Add things z6MknSL…StBU8Vi (you) 42d894a +0 -0 [ ... ] │
╰────────────────────────────────────────────────────────────────────────────────────╯ ╰────────────────────────────────────────────────────────────────────────────────────╯
``` ```

View File

@ -15,6 +15,7 @@ use thiserror::Error;
use radicle::git; use radicle::git;
use radicle::storage::git::transport::local::{Url, UrlError}; use radicle::storage::git::transport::local::{Url, UrlError};
use radicle::storage::{ReadRepository, WriteStorage}; use radicle::storage::{ReadRepository, WriteStorage};
use radicle_cli::terminal as cli;
#[derive(Debug, Error)] #[derive(Debug, Error)]
pub enum Error { pub enum Error {
@ -57,6 +58,8 @@ pub enum Error {
pub struct Options { pub struct Options {
/// Don't sync after push. /// Don't sync after push.
no_sync: bool, no_sync: bool,
/// Patch message.
message: cli::patch::Message,
} }
/// Run the radicle remote helper using the given profile. /// Run the radicle remote helper using the given profile.
@ -101,15 +104,23 @@ pub fn run(profile: radicle::Profile) -> Result<(), Error> {
["option", "verbosity"] => { ["option", "verbosity"] => {
println!("ok"); println!("ok");
} }
["option", "push-option", opt] => { ["option", "push-option", args @ ..] => {
match *opt { match *args {
"sync" => opts.no_sync = false, ["sync"] => opts.no_sync = false,
"no-sync" => opts.no_sync = true, ["no-sync"] => opts.no_sync = true,
_ => { _ => {
let args = args.join(" ");
if let Some((key, val)) = args.split_once('=') {
if key == "patch.message" {
opts.message.append(val);
}
} else {
println!("unsupported"); println!("unsupported");
continue; continue;
} }
} }
}
println!("ok"); println!("ok");
} }
["option", "progress", ..] => { ["option", "progress", ..] => {
@ -130,7 +141,7 @@ pub fn run(profile: radicle::Profile) -> Result<(), Error> {
&stored, &stored,
&profile, &profile,
&stdin, &stdin,
&opts, opts,
) )
.map_err(Error::from); .map_err(Error::from);
} }

View File

@ -120,7 +120,7 @@ pub fn run(
stored: &storage::git::Repository, stored: &storage::git::Repository,
profile: &Profile, profile: &Profile,
stdin: &io::Stdin, stdin: &io::Stdin,
opts: &Options, opts: Options,
) -> Result<(), Error> { ) -> Result<(), Error> {
// Don't allow push if either of these conditions is true: // Don't allow push if either of these conditions is true:
// //
@ -172,7 +172,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(src, &nid, &working, stored, &signer) patch_open(opts.message.clone(), src, &nid, &working, stored, &signer)
} 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()))?;
@ -180,7 +180,17 @@ 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, &signer) patch_update(
opts.message.clone(),
src,
&dst,
*force,
&oid,
&nid,
&working,
stored,
&signer,
)
} else { } else {
push(src, &dst, *force, &nid, &working, stored, &signer) push(src, &dst, *force, &nid, &working, stored, &signer)
} }
@ -224,6 +234,7 @@ 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,
@ -244,8 +255,8 @@ fn patch_open<G: Signer>(
push_ref(src, &dst, false, working, stored.raw())?; push_ref(src, &dst, false, working, stored.raw())?;
let mut patches = patch::Patches::open(stored)?; let mut patches = patch::Patches::open(stored)?;
let message = commit.message().unwrap_or_default(); let fallback = commit.message().unwrap_or_default();
let (title, description) = cli::patch::get_message(cli::patch::Message::Edit, message)?; let (title, description) = cli::patch::get_message(msg, fallback)?;
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 result = match patches.create( let result = match patches.create(
@ -324,6 +335,7 @@ 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,
@ -349,7 +361,7 @@ fn patch_update<G: Signer>(
if patch.revisions().any(|(_, r)| *r.head() == commit.id()) { if patch.revisions().any(|(_, r)| *r.head() == commit.id()) {
return Ok(()); return Ok(());
} }
let message = cli::patch::get_update_message(cli::patch::Message::Edit)?; let message = cli::patch::get_update_message(msg)?;
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 revision = patch.update(message, base, commit.id(), signer)?; let revision = patch.update(message, base, commit.id(), signer)?;