Show changes to 2 files +65 −4
diff.h, tree-diff.c
diff --git a/diff.h b/diff.h
index 8c66b59..51c8a5f 100644
--- a/diff.h
+++ b/diff.h
@@ -12,6 +12,7 @@ struct diff_queue_struct;
struct strbuf;
struct diff_filespec;
struct userdiff_driver;
+struct exclude_list;
typedef void (*change_fn_t)(struct diff_options *options,
unsigned old_mode, unsigned new_mode,
@@ -170,8 +171,18 @@ extern void diff_tree_setup_paths(const char **paths, struct diff_options *);
extern void diff_tree_release_paths(struct diff_options *);
extern int diff_tree(struct tree_desc *t1, struct tree_desc *t2,
const char *base, struct diff_options *opt);
+extern int diff_tree_with_exclude(struct tree_desc *t1, struct tree_desc *t2,
+ const char *base, struct diff_options *opt,
+ struct exclude_list *el,
+ int def_excl1, int def_excl2);
extern int diff_tree_sha1(const unsigned char *old, const unsigned char *new,
const char *base, struct diff_options *opt);
+extern int diff_tree_sha1_with_exclude(const unsigned char *old,
+ const unsigned char *new,
+ const char *base,
+ struct diff_options *opt,
+ struct exclude_list *el,
+ int def_excl1, int def_excl2);
extern int diff_root_tree_sha1(const unsigned char *new, const char *base,
struct diff_options *opt);
diff --git a/tree-diff.c b/tree-diff.c
index b3cc2e4..9938ccf 100644
--- a/tree-diff.c
+++ b/tree-diff.c
@@ -5,12 +5,14 @@
#include "diff.h"
#include "diffcore.h"
#include "tree.h"
+#include "dir.h"
static void show_entry(struct diff_options *opt, const char *prefix,
struct tree_desc *desc, struct strbuf *base);
static int compare_tree_entry(struct tree_desc *t1, struct tree_desc *t2,
- struct strbuf *base, struct diff_options *opt)
+ struct strbuf *base, struct diff_options *opt,
+ struct exclude_list *el, int def_excl1, int def_excl2)
{
unsigned mode1, mode2;
const char *path1, *path2;
@@ -52,7 +54,8 @@ static int compare_tree_entry(struct tree_desc *t1, struct tree_desc *t2,
sha1, sha2, base->buf, 0, 0);
}
strbuf_addch(base, '/');
- diff_tree_sha1(sha1, sha2, base->buf, opt);
+ diff_tree_sha1_with_exclude(sha1, sha2, base->buf, opt,
+ el, def_excl1, def_excl2);
} else {
opt->change(opt, mode1, mode2, sha1, sha2, base->buf, 0, 0);
}
@@ -113,6 +116,31 @@ static void show_entry(struct diff_options *opt, const char *prefix,
strbuf_setlen(base, old_baselen);
}
+static int skip_excludes(struct tree_desc *t, struct strbuf *base,
+ struct exclude_list *el, int defval)
+{
+ for (; t->size; update_tree_entry(t)) {
+ /*
+ * excluded_from_list only cares whether dtype is
+ * DT_DIR or something else (except DT_UNKNOWN). Any
+ * other value would do
+ */
+ int dtype = S_ISDIR(t->entry.mode) ? DT_DIR : DT_REG;
+ int ret = excluded_from_list(base->buf, base->len, t->entry.path,
+ &dtype, el);
+
+ /* If undecided, use matching result of parent dir in defval */
+ if (ret < 0)
+ ret = defval;
+
+ if (ret == 1 && dtype == DT_REG)
+ ;
+ else
+ return ret;
+ }
+ return defval;
+}
+
static void skip_uninteresting(struct tree_desc *t, struct strbuf *base,
struct diff_options *opt, int *match)
{
@@ -130,9 +158,17 @@ static void skip_uninteresting(struct tree_desc *t, struct strbuf *base,
int diff_tree(struct tree_desc *t1, struct tree_desc *t2,
const char *base_str, struct diff_options *opt)
{
+ return diff_tree_with_exclude(t1, t2, base_str, opt, NULL, 0, 0);
+}
+
+int diff_tree_with_exclude(struct tree_desc *t1, struct tree_desc *t2,
+ const char *base_str, struct diff_options *opt,
+ struct exclude_list *el, int def_excl1, int def_excl2)
+{
struct strbuf base;
int baselen = strlen(base_str);
int t1_match = 0, t2_match = 0;
+ int excl1 = 0, excl2 = 0;
/* Enable recursion indefinitely */
opt->pathspec.recursive = DIFF_OPT_TST(opt, RECURSIVE);
@@ -148,6 +184,10 @@ int diff_tree(struct tree_desc *t1, struct tree_desc *t2,
skip_uninteresting(t1, &base, opt, &t1_match);
skip_uninteresting(t2, &base, opt, &t2_match);
}
+ if (el && el->nr) {
+ excl1 = skip_excludes(t1, &base, el, def_excl1);
+ excl2 = skip_excludes(t2, &base, el, def_excl2);
+ }
if (!t1->size) {
if (!t2->size)
break;
@@ -160,7 +200,7 @@ int diff_tree(struct tree_desc *t1, struct tree_desc *t2,
update_tree_entry(t1);
continue;
}
- switch (compare_tree_entry(t1, t2, &base, opt)) {
+ switch (compare_tree_entry(t1, t2, &base, opt, el, excl1, excl2)) {
case -1:
update_tree_entry(t1);
continue;
@@ -267,6 +307,16 @@ static void try_to_follow_renames(struct tree_desc *t1, struct tree_desc *t2, co
int diff_tree_sha1(const unsigned char *old, const unsigned char *new, const char *base, struct diff_options *opt)
{
+ return diff_tree_sha1_with_exclude(old, new, base, opt, NULL, 0, 0);
+}
+
+int diff_tree_sha1_with_exclude(const unsigned char *old,
+ const unsigned char *new,
+ const char *base,
+ struct diff_options *opt,
+ struct exclude_list *el,
+ int def_excl1, int def_excl2)
+{
void *tree1, *tree2;
struct tree_desc t1, t2;
unsigned long size1, size2;
@@ -280,7 +330,7 @@ int diff_tree_sha1(const unsigned char *old, const unsigned char *new, const cha
die("unable to read destination tree (%s)", sha1_to_hex(new));
init_tree_desc(&t1, tree1, size1);
init_tree_desc(&t2, tree2, size2);
- retval = diff_tree(&t1, &t2, base, opt);
+ retval = diff_tree_with_exclude(&t1, &t2, base, opt, el, def_excl1, def_excl2);
if (!*base && DIFF_OPT_TST(opt, FOLLOW_RENAMES) && diff_might_be_rename()) {
init_tree_desc(&t1, tree1, size1);
init_tree_desc(&t2, tree2, size2);