Optimize "diff-index --cached" using cache-tree
[gitweb.git] / unpack-trees.c
index e4eb8fa3afc7ad895ba925701ee3c6881b29bd91..8eb3ddb392499a41eaf6587b3ad717bc8a6ba041 100644 (file)
@@ -61,7 +61,7 @@ static void unlink_entry(struct cache_entry *ce)
 {
        if (has_symlink_or_noent_leading_path(ce->name, ce_namelen(ce)))
                return;
-       if (unlink(ce->name))
+       if (unlink_or_warn(ce->name))
                return;
        schedule_dir_for_removal(ce->name, ce_namelen(ce));
 }
@@ -326,6 +326,23 @@ static int unpack_callback(int n, unsigned long mask, unsigned long dirmask, str
                        if (src[0])
                                conflicts |= 1;
                }
+
+               /* special case: "diff-index --cached" looking at a tree */
+               if (o->diff_index_cached &&
+                   n == 1 && dirmask == 1 && S_ISDIR(names->mode)) {
+                       int matches;
+                       matches = cache_tree_matches_traversal(o->src_index->cache_tree,
+                                                              names, info);
+                       /*
+                        * Everything under the name matches.  Adjust o->pos to
+                        * skip the entire hierarchy.
+                        */
+                       if (matches) {
+                               o->pos += matches;
+                               return mask;
+                       }
+               }
+
                if (traverse_trees_recursive(n, dirmask, conflicts,
                                             names, info) < 0)
                        return -1;