Code

Fix lost-found to show commits only referenced by reflogs
[git.git] / tree-diff.c
index 35af569fb814c5305e816ed52dd03c702cf7970e..852498eb49fe0cba5e1cd21661288e8321a4b20e 100644 (file)
@@ -70,7 +70,8 @@ static int compare_tree_entry(struct tree_desc *t1, struct tree_desc *t2, const
  * Is a tree entry interesting given the pathspec we have?
  *
  * Return:
- *  - positive for yes
+ *  - 2 for "yes, and all subsequent entries will be"
+ *  - 1 for yes
  *  - zero for no
  *  - negative for "no, and no subsequent entries will be either"
  */
@@ -93,15 +94,18 @@ static int tree_entry_interesting(struct tree_desc *desc, const char *base, int
        for (i = 0; i < opt->nr_paths; i++) {
                const char *match = opt->paths[i];
                int matchlen = opt->pathlens[i];
-               int m;
+               int m = -1; /* signals that we haven't called strncmp() */
 
                if (baselen >= matchlen) {
                        /* If it doesn't match, move along... */
                        if (strncmp(base, match, matchlen))
                                continue;
 
-                       /* The base is a subdirectory of a path which was specified. */
-                       return 1;
+                       /*
+                        * The base is a subdirectory of a path which
+                        * was specified, so all of them are interesting.
+                        */
+                       return 2;
                }
 
                /* Does the base match? */
@@ -111,29 +115,36 @@ static int tree_entry_interesting(struct tree_desc *desc, const char *base, int
                match += baselen;
                matchlen -= baselen;
 
-               /*
-                * Does match sort strictly earlier than path with their
-                * common parts?
-                */
-               m = strncmp(match, path,
-                           (matchlen < pathlen) ? matchlen : pathlen);
-               if (m < 0)
-                       continue;
+               if (never_interesting) {
+                       /*
+                        * We have not seen any match that sorts later
+                        * than the current path.
+                        */
+
+                       /*
+                        * Does match sort strictly earlier than path
+                        * with their common parts?
+                        */
+                       m = strncmp(match, path,
+                                   (matchlen < pathlen) ? matchlen : pathlen);
+                       if (m < 0)
+                               continue;
 
-               /*
-                * If we come here even once, that means there is at
-                * least one pathspec that would sort equal to or
-                * later than the path we are currently looking at.
-                * In other words, if we have never reached this point
-                * after iterating all pathspecs, it means all
-                * pathspecs are either outside of base, or inside the
-                * base but sorts strictly earlier than the current
-                * one.  In either case, they will never match the
-                * subsequent entries.  In such a case, we initialized
-                * the variable to -1 and that is what will be
-                * returned, allowing the caller to terminate early.
-                */
-               never_interesting = 0;
+                       /*
+                        * If we come here even once, that means there is at
+                        * least one pathspec that would sort equal to or
+                        * later than the path we are currently looking at.
+                        * In other words, if we have never reached this point
+                        * after iterating all pathspecs, it means all
+                        * pathspecs are either outside of base, or inside the
+                        * base but sorts strictly earlier than the current
+                        * one.  In either case, they will never match the
+                        * subsequent entries.  In such a case, we initialized
+                        * the variable to -1 and that is what will be
+                        * returned, allowing the caller to terminate early.
+                        */
+                       never_interesting = 0;
+               }
 
                if (pathlen > matchlen)
                        continue;
@@ -145,6 +156,13 @@ static int tree_entry_interesting(struct tree_desc *desc, const char *base, int
                                continue;
                }
 
+               if (m == -1)
+                       /*
+                        * we cheated and did not do strncmp(), so we do
+                        * that here.
+                        */
+                       m = strncmp(match, path, pathlen);
+
                /*
                 * If common part matched earlier then it is a hit,
                 * because we rejected the case where path is not a
@@ -159,8 +177,18 @@ static int tree_entry_interesting(struct tree_desc *desc, const char *base, int
 /* A whole sub-tree went away or appeared */
 static void show_tree(struct diff_options *opt, const char *prefix, struct tree_desc *desc, const char *base, int baselen)
 {
+       int all_interesting = 0;
        while (desc->size) {
-               int show = tree_entry_interesting(desc, base, baselen, opt);
+               int show;
+
+               if (all_interesting)
+                       show = 1;
+               else {
+                       show = tree_entry_interesting(desc, base, baselen,
+                                                     opt);
+                       if (show == 2)
+                               all_interesting = 1;
+               }
                if (show < 0)
                        break;
                if (show)
@@ -201,8 +229,17 @@ static void show_entry(struct diff_options *opt, const char *prefix, struct tree
 
 static void skip_uninteresting(struct tree_desc *t, const char *base, int baselen, struct diff_options *opt)
 {
+       int all_interesting = 0;
        while (t->size) {
-               int show = tree_entry_interesting(t, base, baselen, opt);
+               int show;
+
+               if (all_interesting)
+                       show = 1;
+               else {
+                       show = tree_entry_interesting(t, base, baselen, opt);
+                       if (show == 2)
+                               all_interesting = 1;
+               }
                if (!show) {
                        update_tree_entry(t);
                        continue;