Skip to content

Commit 5df9fcf

Browse files
MadCodergitster
authored andcommitted
git send-email: interpret unknown files as revision lists
Filter out all the arguments git-send-email doesn't like to a git format-patch command, that dumps its content to a safe directory. Barf when a file/revision conflict occurs, allow it to be overriden --[no-]format-patch. Signed-off-by: Pierre Habouzit <madcoder@debian.org> Signed-off-by: Junio C Hamano <gitster@pobox.com>
1 parent caf0c3d commit 5df9fcf

File tree

3 files changed

+57
-6
lines changed

3 files changed

+57
-6
lines changed

Documentation/git-send-email.txt

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ git-send-email - Send a collection of patches as emails
88

99
SYNOPSIS
1010
--------
11-
'git send-email' [options] <file|directory> [... file|directory]
11+
'git send-email' [options] <file|directory|rev-list options>...
1212

1313

1414
DESCRIPTION
@@ -183,6 +183,12 @@ Administering
183183
--[no-]validate::
184184
Perform sanity checks on patches.
185185
Currently, validation means the following:
186+
187+
--[no-]format-patch::
188+
When an argument may be understood either as a reference or as a file name,
189+
choose to understand it as a format-patch argument ('--format-patch')
190+
or as a file name ('--no-format-patch'). By default, when such a conflict
191+
occurs, git send-email will fail.
186192
+
187193
--
188194
* Warn of patches that contain lines longer than 998 characters; this

git-send-email.perl

Lines changed: 42 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,12 @@
2222
use Getopt::Long;
2323
use Data::Dumper;
2424
use Term::ANSIColor;
25+
use File::Temp qw/ tempdir /;
26+
use Error qw(:try);
2527
use Git;
2628

29+
Getopt::Long::Configure qw/ pass_through /;
30+
2731
package FakeTerm;
2832
sub new {
2933
my ($class, $reason) = @_;
@@ -38,7 +42,7 @@ package main;
3842

3943
sub usage {
4044
print <<EOT;
41-
git send-email [options] <file | directory>...
45+
git send-email [options] <file | directory | rev-list options >
4246
4347
Composing:
4448
--from <str> * Email From:
@@ -73,6 +77,8 @@ sub usage {
7377
--quiet * Output one line of info per email.
7478
--dry-run * Don't actually send the emails.
7579
--[no-]validate * Perform patch sanity checks. Default on.
80+
--[no-]format-patch * understand any non optional arguments as
81+
`git format-patch` ones.
7682
7783
EOT
7884
exit(1);
@@ -146,6 +152,7 @@ sub format_2822_time {
146152

147153
# Behavior modification variables
148154
my ($quiet, $dry_run) = (0, 0);
155+
my $format_patch;
149156
my $compose_filename = $repo->repo_path() . "/.gitsendemail.msg.$$";
150157

151158
# Variables with corresponding config settings
@@ -229,6 +236,7 @@ sub signal_handler {
229236
"envelope-sender=s" => \$envelope_sender,
230237
"thread!" => \$thread,
231238
"validate!" => \$validate,
239+
"format-patch!" => \$format_patch,
232240
);
233241

234242
unless ($rc) {
@@ -363,23 +371,52 @@ sub read_config {
363371

364372
($sender) = expand_aliases($sender) if defined $sender;
365373

374+
# returns 1 if the conflict must be solved using it as a format-patch argument
375+
sub check_file_rev_conflict($) {
376+
my $f = shift;
377+
try {
378+
$repo->command('rev-parse', '--verify', '--quiet', $f);
379+
if (defined($format_patch)) {
380+
print "foo\n";
381+
return $format_patch;
382+
}
383+
die(<<EOF);
384+
File '$f' exists but it could also be the range of commits
385+
to produce patches for. Please disambiguate by...
386+
387+
* Saying "./$f" if you mean a file; or
388+
* Giving --format-patch option if you mean a range.
389+
EOF
390+
} catch Git::Error::Command with {
391+
return 0;
392+
}
393+
}
394+
366395
# Now that all the defaults are set, process the rest of the command line
367396
# arguments and collect up the files that need to be processed.
368-
for my $f (@ARGV) {
369-
if (-d $f) {
397+
my @rev_list_opts;
398+
while (my $f = pop @ARGV) {
399+
if ($f eq "--") {
400+
push @rev_list_opts, "--", @ARGV;
401+
@ARGV = ();
402+
} elsif (-d $f and !check_file_rev_conflict($f)) {
370403
opendir(DH,$f)
371404
or die "Failed to opendir $f: $!";
372405

373406
push @files, grep { -f $_ } map { +$f . "/" . $_ }
374407
sort readdir(DH);
375408
closedir(DH);
376-
} elsif (-f $f or -p $f) {
409+
} elsif ((-f $f or -p $f) and !check_file_rev_conflict($f)) {
377410
push @files, $f;
378411
} else {
379-
print STDERR "Skipping $f - not found.\n";
412+
push @rev_list_opts, $f;
380413
}
381414
}
382415

416+
if (@rev_list_opts) {
417+
push @files, $repo->command('format-patch', '-o', tempdir(CLEANUP => 1), @rev_list_opts);
418+
}
419+
383420
if ($validate) {
384421
foreach my $f (@files) {
385422
unless (-p $f) {

t/t9001-send-email.sh

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -292,4 +292,12 @@ test_expect_success '--compose adds MIME for utf8 subject' '
292292
grep "^Subject: =?utf-8?q?utf8-s=C3=BCbj=C3=ABct?=" msgtxt1
293293
'
294294

295+
test_expect_success 'detects ambiguous reference/file conflict' '
296+
echo master > master &&
297+
git add master &&
298+
git commit -m"add master" &&
299+
test_must_fail git send-email --dry-run master 2>errors &&
300+
grep disambiguate errors
301+
'
302+
295303
test_done

0 commit comments

Comments
 (0)