@matheusbsbs / matheus-bagliano / commits / 5df9fcf695
Fork 0

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>

Pierre Habouzit committed Nov 11, 2008 at 00:54 UTC 5df9fcf695a0ba85abfeed68efb3b1c5890068d6
3 files changed +57 -6
Documentation/git-send-email.txt
+7 -1
@@ -8,7 +8,7 @@ git-send-email - Send a collection of patches as emails
8
9 SYNOPSIS
10 --------
11 -'git send-email' [options] <file|directory> [... file|directory]
11 +'git send-email' [options] <file|directory|rev-list options>...
12
13
14 DESCRIPTION
@@ -183,6 +183,12 @@ Administering
183 --[no-]validate::
184 Perform sanity checks on patches.
185 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.
192 +
193 --
194 * Warn of patches that contain lines longer than 998 characters; this
git-send-email.perl
+42 -5
@@ -22,8 +22,12 @@ use Term::ReadLine;
22 use Getopt::Long;
23 use Data::Dumper;
24 use Term::ANSIColor;
25 +use File::Temp qw/ tempdir /;
26 +use Error qw(:try);
27 use Git;
28
29 +Getopt::Long::Configure qw/ pass_through /;
30 +
31 package FakeTerm;
32 sub new {
33 my ($class, $reason) = @_;
@@ -38,7 +42,7 @@ package main;
42
43 sub usage {
44 print <<EOT;
41 -git send-email [options] <file | directory>...
45 +git send-email [options] <file | directory | rev-list options >
46
47 Composing:
48 --from <str> * Email From:
@@ -73,6 +77,8 @@ git send-email [options] <file | directory>...
77 --quiet * Output one line of info per email.
78 --dry-run * Don't actually send the emails.
79 --[no-]validate * Perform patch sanity checks. Default on.
80 + --[no-]format-patch * understand any non optional arguments as
81 + `git format-patch` ones.
82
83 EOT
84 exit(1);
@@ -146,6 +152,7 @@ if ($@) {
152
153 # Behavior modification variables
154 my ($quiet, $dry_run) = (0, 0);
155 +my $format_patch;
156 my $compose_filename = $repo->repo_path() . "/.gitsendemail.msg.$$";
157
158 # Variables with corresponding config settings
@@ -229,6 +236,7 @@ my $rc = GetOptions("sender|from=s" => \$sender,
236 "envelope-sender=s" => \$envelope_sender,
237 "thread!" => \$thread,
238 "validate!" => \$validate,
239 + "format-patch!" => \$format_patch,
240 );
241
242 unless ($rc) {
@@ -363,23 +371,52 @@ if (@alias_files and $aliasfiletype and defined $parse_alias{$aliasfiletype}) {
371
372 ($sender) = expand_aliases($sender) if defined $sender;
373
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 +
395 # Now that all the defaults are set, process the rest of the command line
396 # 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)) {
403 opendir(DH,$f)
404 or die "Failed to opendir $f: $!";
405
406 push @files, grep { -f $_ } map { +$f . "/" . $_ }
407 sort readdir(DH);
408 closedir(DH);
376 - } elsif (-f $f or -p $f) {
409 + } elsif ((-f $f or -p $f) and !check_file_rev_conflict($f)) {
410 push @files, $f;
411 } else {
379 - print STDERR "Skipping $f - not found.\n";
412 + push @rev_list_opts, $f;
413 }
414 }
415
416 +if (@rev_list_opts) {
417 + push @files, $repo->command('format-patch', '-o', tempdir(CLEANUP => 1), @rev_list_opts);
418 +}
419 +
420 if ($validate) {
421 foreach my $f (@files) {
422 unless (-p $f) {
t/t9001-send-email.sh
+8
@@ -292,4 +292,12 @@ test_expect_success '--compose adds MIME for utf8 subject' '
292 grep "^Subject: =?utf-8?q?utf8-s=C3=BCbj=C3=ABct?=" msgtxt1
293 '
294
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 +
303 test_done