Merge branch 'en/tree-walk-optim'
authorJunio C Hamano <gitster@pobox.com>
Wed, 27 Oct 2010 04:37:49 +0000 (21:37 -0700)
committerJunio C Hamano <gitster@pobox.com>
Wed, 27 Oct 2010 04:37:49 +0000 (21:37 -0700)
* en/tree-walk-optim:
diff_tree(): Skip skip_uninteresting() when all remaining paths interesting
tree_entry_interesting(): Make return value more specific
tree-walk: Correct bitrotted comment about tree_entry()
Document pre-condition for tree_entry_interesting

1  2 
tree-diff.c
diff --combined tree-diff.c
index cd659c6fe447b6fcdedee2843113feb358f23849,f6a6b2f71fdde3367a2063933583b43f75893912..12c9a88884ec3bb70a1744e44235c578a44e08e6
@@@ -85,6 -85,8 +85,8 @@@ static int compare_tree_entry(struct tr
  /*
   * Is a tree entry interesting given the pathspec we have?
   *
+  * Pre-condition: baselen == 0 || base[baselen-1] == '/'
+  *
   * Return:
   *  - 2 for "yes, and all subsequent entries will be"
   *  - 1 for yes
@@@ -101,7 -103,7 +103,7 @@@ static int tree_entry_interesting(struc
        int never_interesting = -1;
  
        if (!opt->nr_paths)
-               return 1;
+               return 2;
  
        sha1 = tree_entry_extract(desc, &path, &mode);
  
@@@ -257,19 -259,12 +259,12 @@@ static void show_entry(struct diff_opti
        }
  }
  
- static void skip_uninteresting(struct tree_desc *t, const char *base, int baselen, struct diff_options *opt)
+ static void skip_uninteresting(struct tree_desc *t, const char *base, int baselen, struct diff_options *opt, int *all_interesting)
  {
-       int all_interesting = 0;
        while (t->size) {
-               int show;
-               if (all_interesting)
-                       show = 1;
-               else {
-                       show = tree_entry_interesting(t, base, baselen, opt);
-                       if (show == 2)
-                               all_interesting = 1;
-               }
+               int show = tree_entry_interesting(t, base, baselen, opt);
+               if (show == 2)
+                       *all_interesting = 1;
                if (!show) {
                        update_tree_entry(t);
                        continue;
  int diff_tree(struct tree_desc *t1, struct tree_desc *t2, const char *base, struct diff_options *opt)
  {
        int baselen = strlen(base);
+       int all_t1_interesting = 0;
+       int all_t2_interesting = 0;
  
        for (;;) {
                if (DIFF_OPT_TST(opt, QUICK) &&
                    DIFF_OPT_TST(opt, HAS_CHANGES))
                        break;
                if (opt->nr_paths) {
-                       skip_uninteresting(t1, base, baselen, opt);
-                       skip_uninteresting(t2, base, baselen, opt);
+                       if (!all_t1_interesting)
+                               skip_uninteresting(t1, base, baselen, opt,
+                                                  &all_t1_interesting);
+                       if (!all_t2_interesting)
+                               skip_uninteresting(t2, base, baselen, opt,
+                                                  &all_t2_interesting);
                }
                if (!t1->size) {
                        if (!t2->size)
@@@ -346,7 -347,7 +347,7 @@@ static void try_to_follow_renames(struc
  
        diff_setup(&diff_opts);
        DIFF_OPT_SET(&diff_opts, RECURSIVE);
 -      diff_opts.detect_rename = DIFF_DETECT_RENAME;
 +      DIFF_OPT_SET(&diff_opts, FIND_COPIES_HARDER);
        diff_opts.output_format = DIFF_FORMAT_NO_OUTPUT;
        diff_opts.single_follow = opt->paths[0];
        diff_opts.break_opt = opt->break_opt;
        diff_tree_release_paths(&diff_opts);
  
        /* Go through the new set of filepairing, and see if we find a more interesting one */
 +      opt->found_follow = 0;
        for (i = 0; i < q->nr; i++) {
                struct diff_filepair *p = q->queue[i];
  
                        diff_tree_release_paths(opt);
                        opt->paths[0] = xstrdup(p->one->path);
                        diff_tree_setup_paths(opt->paths, opt);
 +
 +                      /*
 +                       * The caller expects us to return a set of vanilla
 +                       * filepairs to let a later call to diffcore_std()
 +                       * it makes to sort the renames out (among other
 +                       * things), but we already have found renames
 +                       * ourselves; signal diffcore_std() not to muck with
 +                       * rename information.
 +                       */
 +                      opt->found_follow = 1;
                        break;
                }
        }
@@@ -423,7 -413,7 +424,7 @@@ int diff_tree_sha1(const unsigned char 
        init_tree_desc(&t1, tree1, size1);
        init_tree_desc(&t2, tree2, size2);
        retval = diff_tree(&t1, &t2, base, opt);
 -      if (DIFF_OPT_TST(opt, FOLLOW_RENAMES) && diff_might_be_rename()) {
 +      if (!*base && DIFF_OPT_TST(opt, FOLLOW_RENAMES) && diff_might_be_rename()) {
                init_tree_desc(&t1, tree1, size1);
                init_tree_desc(&t2, tree2, size2);
                try_to_follow_renames(&t1, &t2, base, opt);