Commits

Linus Torvalds  committed fdee7d0

Make git-diff-cache skip any comparisons which don't match pathspec

This brings all the same pathspec optimizations that git-diff-tree does
to git-diff-cache.

  • Participants
  • Parent commits a74ba54

Comments (0)

Files changed (1)

File diff-cache.c

 	return 0;
 }
 
-static int diff_cache(struct cache_entry **ac, int entries)
+static int ce_path_match(const struct cache_entry *ce, const char **pathspec)
+{
+	const char *match, *name;
+	int len;
+
+	if (!pathspec)
+		return 1;
+
+	len = ce_namelen(ce);
+	name = ce->name;
+	while ((match = *pathspec++) != NULL) {
+		int matchlen = strlen(match);
+		if (matchlen > len)
+			continue;
+		if (memcmp(name, match, matchlen))
+			continue;
+		if (name[matchlen] == '/' || !name[matchlen])
+			return 1;
+	}
+	return 0;
+}
+
+static int diff_cache(struct cache_entry **ac, int entries, const char **pathspec)
 {
 	while (entries) {
 		struct cache_entry *ce = *ac;
 		int same = (entries > 1) && ce_same_name(ce, ac[1]);
 
+		if (!ce_path_match(ce, pathspec))
+			goto skip_entry;
+
 		switch (ce_stage(ce)) {
 		case 0:
 			/* No stage 1 entry? That means it's a new file */
 			die("impossible cache entry stage");
 		}
 
+skip_entry:
 		/*
 		 * Ignore all the different stages for this file,
 		 * we've handled the relevant cases now.
 	if (read_tree(tree, size, 1, pathspec))
 		die("unable to read tree object %s", tree_name);
 
-	ret = diff_cache(active_cache, active_nr);
+	ret = diff_cache(active_cache, active_nr, pathspec);
 
 	diffcore_std(pathspec,
 		     detect_rename, diff_score_opt,