diff options
author | Oswald Buddenhagen <oswald.buddenhagen@gmx.de> | 2023-03-12 13:39:11 +0100 |
---|---|---|
committer | Oswald Buddenhagen <oswald.buddenhagen@gmx.de> | 2024-01-09 16:36:47 +0000 |
commit | bc2eaa3ec88eef320345aed8dc8d9be4b6c2b119 (patch) | |
tree | d06ac5f73cce400e2b171d668efcdc959ea1dd8c /bin | |
parent | 31cef4c662ac13c683a7f94ef854b01fa6b53cab (diff) |
gpush: make it possible to set format-patch options in mail mode
this is required for setting mail receivers and actual patch formatting
options.
the relevant options are identical for send-email and format-patch, so
we don't differentiate these.
Change-Id: Ie7f35b3402531ecec7762e07b32526c909589809
Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
Diffstat (limited to 'bin')
-rwxr-xr-x | bin/git-gpush | 61 | ||||
-rw-r--r-- | bin/git_gpush.pm | 54 |
2 files changed, 105 insertions, 10 deletions
diff --git a/bin/git-gpush b/bin/git-gpush index 6621c12..288f763 100755 --- a/bin/git-gpush +++ b/bin/git-gpush @@ -167,6 +167,11 @@ Options: This setting persists for the series, even when it grows. Use an empty topic to delete a previously set one. + -- <git option>... + In mail mode, set additional options for git format-patch and + git send-email for the specified series. All subsequent arguments + are consumed by this, so this must be the last option. + -o, --onto, --base <base> Specify the commit to rebase the pushed series onto. It is possible to specify upstream commits, commits pushed for review, or 'ROOT' to @@ -390,6 +395,7 @@ my $list_online = 0; my $send_email = 0; my $keep_version = 0; my $reset_version = 0; +my $format_opts; my $outdir; my @reviewers; @@ -467,6 +473,9 @@ sub parse_arguments(@) $list_online = 1; } elsif ($arg eq "--send") { $send_email = 1; + } elsif ($arg eq "--") { + $format_opts = \@_; + last; } elsif ($arg eq "--aliases") { foreach my $key (sort(keys %aliases)) { print "$key = $aliases{$key}\n"; @@ -532,7 +541,8 @@ sub parse_arguments(@) $commit_count || $from_base || $extend || $capture; my $series_modifying = $series_specifying || defined($ref_to) || defined($topic) - || $keep_version || $reset_version; + || $keep_version || $reset_version + || $format_opts; my $gerrit_specific = @reviewers || @CCs || defined($remote) || $force_branch; my $push_specific = @@ -552,6 +562,8 @@ sub parse_arguments(@) if ($send_email); fail("--keep-version/--reset-version is exclusive to mail mode.\n") if ($keep_version || $reset_version); + fail("-- ... is exclusive to mail mode.\n") + if ($format_opts); } if ($group_only) { @@ -923,6 +935,36 @@ sub determine_version($) $$group{version} = $ver; } +sub new_fmt_opt() +{ + return new_prop(quote_list_prop(@$format_opts)); +} + +sub determine_format_options($) +{ + my ($group) = @_; + + my ($fmt_opt, $fmt_opt_text); + if ($format_opts) { + $fmt_opt = new_fmt_opt(); + $fmt_opt_text = $fmt_opt && $format_opts; + } else { + $fmt_opt = aggregate_indirect_property( + $group, + # Loose Changes should inherit the series' options, + # while for grouped ones undef means empty. + sub { defined($$_{grp}) ? ($$_{fmt} // -1) : undef }, + sub { ("has inconsistent patch preparation options:\n", + map { " ".(length($_) ? format_cmd(unquote_list_prop($_)) + : "<none>")."\n" } @_) }); + $fmt_opt = undef if (($fmt_opt // 0) == -1); + $fmt_opt_text = [ unquote_list_prop($prop_by_key{$fmt_opt}) ] + if (defined($fmt_opt)); + } + $$group{fmt_opt} = $fmt_opt; + $$group{fmt_opt_text} = $fmt_opt_text; +} + sub scan_pushed_group($$) { my ($group, $commits) = @_; @@ -1996,7 +2038,9 @@ sub annotate_group($$) my @annot; if ($extra) { - # TODO + my $fmt_opt = $$group{fmt_opt_text}; + push @annot, "> Format options: ".format_cmd(@$fmt_opt)."\n" + if ($fmt_opt); } $$group{annotation} = \@annot if (@annot); } @@ -2221,9 +2265,11 @@ sub format_patches($) my $base = $$group{base}; my $tpc = $$group{topic}; my $ver = $$group{version}; + my $fmt_opt = $$group{fmt_opt_text}; my @gitopt = ('--binary'); push @gitopt, '--reroll-count', $ver if ($ver > 1); + push @gitopt, @$fmt_opt if ($fmt_opt); # Can't use the -<n> <tip> notation, as -8 is misunderstood # by git send-email. push @gitopt, (($base eq 'ROOT') ? '--root' : '^'.$base), $tip; @@ -2253,6 +2299,7 @@ sub update_state_grouping($) my ($group) = @_; my $gid = $$group{gid}; + my $fmt = $format_opts && new_fmt_opt(); foreach my $change (@{$$group{changes}}) { $$change{grp} = $gid; # We persist only explicitly specified values. Fallbacks @@ -2265,6 +2312,8 @@ sub update_state_grouping($) if (defined($ref_base) || $reset_props); $$change{ver} = 0 if ($reset_version); + $$change{fmt} = $fmt + if ($format_opts); $$change{exclude} = $exclude ? 1 : undef if ($include || $exclude); } @@ -2274,10 +2323,10 @@ sub update_state($) { my ($group) = @_; - my ($gid, $branch, $tpc, $ver, $base) = + my ($gid, $branch, $tpc, $ver, $fmt, $base) = ($$group{gid}, $$group{branch}, $$group{topic}, $$group{version}, - $$group{base}); + $$group{fmt_opt}, $$group{base}); # Setting an empty topic clears the previous topic from the server. $tpc = undef if (defined($tpc) && !length($tpc)); foreach my $change (@{$$group{changes}}) { @@ -2287,6 +2336,7 @@ sub update_state($) $$change{topic} = $tpc; $$change{ntopic} = undef; $$change{ver} = $ver; + $$change{fmt} = $fmt; $$change{tgt} = $branch; $$change{ntgt} = undef; my $commit = $$change{local}; @@ -2388,6 +2438,9 @@ sub execute_pushing() resolve_ref_base(); foreach my $group (@$annot_groups) { determine_topic($group); + if ($mail_mode) { + determine_format_options($group); + } } if ($rebase) { # Rebasing may take a while, so make sure all base determination diff --git a/bin/git_gpush.pm b/bin/git_gpush.pm index dce7400..06cf21a 100644 --- a/bin/git_gpush.pm +++ b/bin/git_gpush.pm @@ -17,7 +17,7 @@ use Carp; $SIG{__WARN__} = \&Carp::cluck; $SIG{__DIE__} = \&Carp::confess; -use List::Util qw(min max); +use List::Util qw(min max pairmap); use File::Spec; use File::Temp qw(mktemp); use IPC::Open3 qw(open3); @@ -125,7 +125,7 @@ use constant { DRY_RUN => 512 # Don't actually run the command if $dry_run is true }; -sub _format_cmd(@) +sub format_cmd(@) { return join(' ', map { /\s/ ? '"' . $_ . '"' : $_ } @_); } @@ -138,10 +138,10 @@ sub open_process($@) $flags &= ~DRY_RUN if (!$dry_run); $process{flags} = $flags; if ($flags & DRY_RUN) { - print "+ "._format_cmd(@cmd)." [DRY]\n" if ($debug); + print "+ ".format_cmd(@cmd)." [DRY]\n" if ($debug); return \%process; } - my $cmd = _format_cmd(@cmd); + my $cmd = format_cmd(@cmd); $process{cmd} = $cmd; my ($in, $out, $err); if ($flags & USE_STDIN) { @@ -708,6 +708,47 @@ our %gerrit_info_by_key; our %gerrit_info_by_sha1; our %gerrit_infos_by_id; +############################# +# state variable processing # +############################# + +{ # start text escape functions + +my @escapes = split //, "\\\\\"\"\aa\bb\tt\nn\rr\013v\ff\ee s"; +my %esc_to_char = pairmap { $b => $a } @escapes; +my %char_to_esc = pairmap { $a => $b } @escapes; + +sub quote_text_prop($;$) +{ + my ($in, $sp) = @_; + + my $re = $sp ? qr/(\p{Cc}|\\|\"| )/ : qr/(\p{Cc}|\\|\")/; + $in =~ s{$re}{"\\".($char_to_esc{$1} // sprintf("%03o", ord($1)))}ge; + return $in; +} + +sub unquote_text_prop($) +{ + my ($in) = @_; + + $in =~ s{(?>\\([\\\"a-z]|[0-3][0-7][0-7]))}{$esc_to_char{$1} // chr(oct($1))}ge; + return $in; +} + +} # end text escape functions + +sub quote_list_prop(@) +{ + return join(" ", map { quote_text_prop($_, 1) } @_); +} + +sub unquote_list_prop($) +{ + my ($in) = @_; + + return map { unquote_text_prop($_) } split(/ /, $in); +} + ################## # state handling # ################## @@ -721,6 +762,7 @@ our %gerrit_infos_by_id; # - src: Local branch name, or "-" if Change is on a detached HEAD. # - tgt: Target branch name. # - topic: Gerrit topic. Persisted only as a cache. +# - fmt: format-patch/send-email options (indirect). # - pushed: SHA1 of the commit this Change was pushed as last time # from this repository. # - rebased: prospective value for 'pushed'. @@ -807,9 +849,9 @@ sub save_state(;$$) print "Saving ".($new ? "new " : "")."state".($dry ? " [DRY]" : "")." ...\n" if ($debug); my %prop_hash; my (@lines, @updates); - my %ikeys = map { $_ => 1 } (); + my %ikeys = map { $_ => 1 } ('fmt'); my @fkeys = ('key', 'grp', 'id', 'base', 'src', 'tgt', - 'topic', 'ver', + 'topic', 'ver', 'fmt', 'nbase', 'ntgt', 'ntopic', 'exclude', 'hide'); my @rkeys = ('pushed', 'rebased', 'orig', 'rorig'); if ($new) { |