Merge branch 'jk/add-i-use-pathspecs'
authorJunio C Hamano <gitster@pobox.com>
Fri, 17 Mar 2017 20:50:26 +0000 (13:50 -0700)
committerJunio C Hamano <gitster@pobox.com>
Fri, 17 Mar 2017 20:50:26 +0000 (13:50 -0700)
"git add -p <pathspec>" unnecessarily expanded the pathspec to a
list of individual files that matches the pathspec by running "git
ls-files <pathspec>", before feeding it to "git diff-index" to see
which paths have changes, because historically the pathspec
language supported by "diff-index" was weaker.  These days they are
equivalent and there is no reason to internally expand it.  This
helps both performance and avoids command line argument limit on
some platforms.

* jk/add-i-use-pathspecs:
  add--interactive: do not expand pathspecs with ls-files

1  2 
git-add--interactive.perl
t/t3701-add-interactive.sh

@@@ -92,7 -92,7 +92,7 @@@ sub colored 
  }
  
  # command line options
 -my $cmd;
 +my $patch_mode_only;
  my $patch_mode;
  my $patch_mode_revision;
  
@@@ -275,20 -275,11 +275,11 @@@ sub list_modified 
        my ($only) = @_;
        my (%data, @return);
        my ($add, $del, $adddel, $file);
-       my @tracked = ();
-       if (@ARGV) {
-               @tracked = map {
-                       chomp $_;
-                       unquote_path($_);
-               } run_cmd_pipe(qw(git ls-files --), @ARGV);
-               return if (!@tracked);
-       }
  
        my $reference = get_diff_reference($patch_mode_revision);
        for (run_cmd_pipe(qw(git diff-index --cached
                             --numstat --summary), $reference,
-                            '--', @tracked)) {
+                            '--', @ARGV)) {
                if (($add, $del, $file) =
                    /^([-\d]+)  ([-\d]+)        (.*)/) {
                        my ($change, $bin);
                }
        }
  
-       for (run_cmd_pipe(qw(git diff-files --numstat --summary --raw --), @tracked)) {
+       for (run_cmd_pipe(qw(git diff-files --numstat --summary --raw --), @ARGV)) {
                if (($add, $del, $file) =
                    /^([-\d]+)  ([-\d]+)        (.*)/) {
                        $file = unquote_path($file);
@@@ -1299,7 -1290,7 +1290,7 @@@ sub patch_update_cmd 
                }
                return 0;
        }
 -      if ($patch_mode) {
 +      if ($patch_mode_only) {
                @them = @mods;
        }
        else {
@@@ -1721,7 -1712,7 +1712,7 @@@ sub process_args 
                die sprintf(__("invalid argument %s, expecting --"),
                               $arg) unless $arg eq "--";
                %patch_mode_flavour = %{$patch_modes{$patch_mode}};
 -              $cmd = 1;
 +              $patch_mode_only = 1;
        }
        elsif ($arg ne "--") {
                die sprintf(__("invalid argument %s, expecting --"), $arg);
@@@ -1758,7 -1749,7 +1749,7 @@@ sub main_loop 
  
  process_args();
  refresh();
 -if ($cmd) {
 +if ($patch_mode_only) {
        patch_update_cmd();
  }
  else {
@@@ -394,22 -394,47 +394,65 @@@ test_expect_success 'diffs can be color
        grep "$(printf "\\033")" output
  '
  
 +test_expect_success 'patch-mode via -i prompts for files' '
 +      git reset --hard &&
 +
 +      echo one >file &&
 +      echo two >test &&
 +      git add -i <<-\EOF &&
 +      patch
 +      test
 +
 +      y
 +      quit
 +      EOF
 +
 +      echo test >expect &&
 +      git diff --cached --name-only >actual &&
 +      test_cmp expect actual
 +'
 +
+ test_expect_success 'add -p handles globs' '
+       git reset --hard &&
+       mkdir -p subdir &&
+       echo base >one.c &&
+       echo base >subdir/two.c &&
+       git add "*.c" &&
+       git commit -m base &&
+       echo change >one.c &&
+       echo change >subdir/two.c &&
+       git add -p "*.c" <<-\EOF &&
+       y
+       y
+       EOF
+       cat >expect <<-\EOF &&
+       one.c
+       subdir/two.c
+       EOF
+       git diff --cached --name-only >actual &&
+       test_cmp expect actual
+ '
+ test_expect_success 'add -p does not expand argument lists' '
+       git reset --hard &&
+       echo content >not-changed &&
+       git add not-changed &&
+       git commit -m "add not-changed file" &&
+       echo change >file &&
+       GIT_TRACE=$(pwd)/trace.out git add -p . <<-\EOF &&
+       y
+       EOF
+       # we know that "file" must be mentioned since we actually
+       # update it, but we want to be sure that our "." pathspec
+       # was not expanded into the argument list of any command.
+       # So look only for "not-changed".
+       ! grep not-changed trace.out
+ '
  test_done