Code

Merge branch 'jk/diff-not-so-quick'
authorJunio C Hamano <gitster@pobox.com>
Mon, 6 Jun 2011 18:40:14 +0000 (11:40 -0700)
committerJunio C Hamano <gitster@pobox.com>
Mon, 6 Jun 2011 18:40:14 +0000 (11:40 -0700)
* jk/diff-not-so-quick:
  diff: futureproof "stop feeding the backend early" logic
  diff_tree: disable QUICK optimization with diff filter

Conflicts:
diff.c

1  2 
diff-lib.c
diff.c
diff.h
t/t4040-whitespace-status.sh
tree-diff.c

diff --cc diff-lib.c
index 3b5f2242a597ff1b44a3af6be72cb14e6e0d5455,869d8f0e77832385c6047dce48e28dcc91171fb3..9c29293bbc05d175ba13338813e8532c7ad677cf
@@@ -100,14 -72,11 +100,12 @@@ int run_diff_files(struct rev_info *rev
                unsigned int oldmode, newmode;
                struct cache_entry *ce = active_cache[i];
                int changed;
 +              unsigned dirty_submodule = 0;
  
-               if (DIFF_OPT_TST(&revs->diffopt, QUICK) &&
-                   !revs->diffopt.filter &&
-                   DIFF_OPT_TST(&revs->diffopt, HAS_CHANGES))
+               if (diff_can_quit_early(&revs->diffopt))
                        break;
  
 -              if (!ce_path_match(ce, revs->prune_data))
 +              if (!ce_path_match(ce, &revs->prune_data))
                        continue;
  
                if (ce_stage(ce)) {
diff --cc diff.c
index 8f4815bfd7d798f2a99131cd2e79155e933c7876,ae6853fcf1ea1e10c1d8f6750f69b71a7a5e73b4..61bedaed57216cadaf2716ef7aa0d63889571f8a
--- 1/diff.c
--- 2/diff.c
+++ b/diff.c
@@@ -4456,24 -3513,13 +4456,31 @@@ int diff_result_code(struct diff_option
        return result;
  }
  
+ int diff_can_quit_early(struct diff_options *opt)
+ {
+       return (DIFF_OPT_TST(opt, QUICK) &&
+               !opt->filter &&
+               DIFF_OPT_TST(opt, HAS_CHANGES));
+ }
 +/*
 + * Shall changes to this submodule be ignored?
 + *
 + * Submodule changes can be configured to be ignored separately for each path,
 + * but that configuration can be overridden from the command line.
 + */
 +static int is_submodule_ignored(const char *path, struct diff_options *options)
 +{
 +      int ignored = 0;
 +      unsigned orig_flags = options->flags;
 +      if (!DIFF_OPT_TST(options, OVERRIDE_SUBMODULE_CONFIG))
 +              set_diffopt_flags_from_submodule_config(options, path);
 +      if (DIFF_OPT_TST(options, IGNORE_SUBMODULES))
 +              ignored = 1;
 +      options->flags = orig_flags;
 +      return ignored;
 +}
 +
  void diff_addremove(struct diff_options *options,
                    int addremove, unsigned mode,
                    const unsigned char *sha1,
diff --cc diff.h
Simple merge
index abc49348b196cf0fec232b6f2399356e4fe324d5,0000000000000000000000000000000000000000..3c728a3ebf9ce52e5c24c81525d5cb749cfb2957
mode 100755,000000..100755
--- /dev/null
@@@ -1,70 -1,0 +1,75 @@@
 +#!/bin/sh
 +
 +test_description='diff --exit-code with whitespace'
 +. ./test-lib.sh
 +
 +test_expect_success setup '
 +      mkdir a b &&
 +      echo >c &&
 +      echo >a/d &&
 +      echo >b/e &&
 +      git add . &&
 +      test_tick &&
 +      git commit -m initial &&
 +      echo " " >a/d &&
 +      test_tick &&
 +      git commit -a -m second &&
 +      echo "  " >a/d &&
 +      echo " " >b/e &&
 +      git add a/d
 +'
 +
 +test_expect_success 'diff-tree --exit-code' '
 +      test_must_fail git diff --exit-code HEAD^ HEAD &&
 +      test_must_fail git diff-tree --exit-code HEAD^ HEAD
 +'
 +
 +test_expect_success 'diff-tree -b --exit-code' '
 +      git diff -b --exit-code HEAD^ HEAD &&
 +      git diff-tree -b -p --exit-code HEAD^ HEAD &&
 +      git diff-tree -b --exit-code HEAD^ HEAD
 +'
 +
 +test_expect_success 'diff-index --cached --exit-code' '
 +      test_must_fail git diff --cached --exit-code HEAD &&
 +      test_must_fail git diff-index --cached --exit-code HEAD
 +'
 +
 +test_expect_success 'diff-index -b -p --cached --exit-code' '
 +      git diff -b --cached --exit-code HEAD &&
 +      git diff-index -b -p --cached --exit-code HEAD
 +'
 +
 +test_expect_success 'diff-index --exit-code' '
 +      test_must_fail git diff --exit-code HEAD &&
 +      test_must_fail git diff-index --exit-code HEAD
 +'
 +
 +test_expect_success 'diff-index -b -p --exit-code' '
 +      git diff -b --exit-code HEAD &&
 +      git diff-index -b -p --exit-code HEAD
 +'
 +
 +test_expect_success 'diff-files --exit-code' '
 +      test_must_fail git diff --exit-code &&
 +      test_must_fail git diff-files --exit-code
 +'
 +
 +test_expect_success 'diff-files -b -p --exit-code' '
 +      git diff -b --exit-code &&
 +      git diff-files -b -p --exit-code
 +'
 +
 +test_expect_success 'diff-files --diff-filter --quiet' '
 +      git reset --hard &&
 +      rm a/d &&
 +      echo x >>b/e &&
 +      test_must_fail git diff-files --diff-filter=M --quiet
 +'
 +
++test_expect_success 'diff-tree --diff-filter --quiet' '
++      git commit -a -m "worktree state" &&
++      test_must_fail git diff-tree --diff-filter=M --quiet HEAD^ HEAD
++'
++
 +test_done
diff --cc tree-diff.c
index 3f4072525b9489a86b2231748abe13c611e05274,33881d1ad0b7381db4bd39c97e160d93f62a1cdb..b3cc2e4753447d4734ed08a70e3396771257dced
@@@ -127,27 -281,16 +127,26 @@@ static void skip_uninteresting(struct t
        }
  }
  
 -int diff_tree(struct tree_desc *t1, struct tree_desc *t2, const char *base, struct diff_options *opt)
 +int diff_tree(struct tree_desc *t1, struct tree_desc *t2,
 +            const char *base_str, struct diff_options *opt)
  {
 -      int baselen = strlen(base);
 +      struct strbuf base;
 +      int baselen = strlen(base_str);
 +      int t1_match = 0, t2_match = 0;
 +
 +      /* Enable recursion indefinitely */
 +      opt->pathspec.recursive = DIFF_OPT_TST(opt, RECURSIVE);
 +      opt->pathspec.max_depth = -1;
 +
 +      strbuf_init(&base, PATH_MAX);
 +      strbuf_add(&base, base_str, baselen);
  
        for (;;) {
-               if (DIFF_OPT_TST(opt, QUICK) &&
-                   DIFF_OPT_TST(opt, HAS_CHANGES))
+               if (diff_can_quit_early(opt))
                        break;
 -              if (opt->nr_paths) {
 -                      skip_uninteresting(t1, base, baselen, opt);
 -                      skip_uninteresting(t2, base, baselen, opt);
 +              if (opt->pathspec.nr) {
 +                      skip_uninteresting(t1, &base, opt, &t1_match);
 +                      skip_uninteresting(t2, &base, opt, &t2_match);
                }
                if (!t1->size) {
                        if (!t2->size)