This function can be potentially used in more places than just tree-diff.c. "struct diff_options" does not make much sense outside diff_tree_sha1(). Moreover people seem to be agree that diff machinery should learn proper pathspecs too (i.e. glob support [1] and stuff), not just treating pathspecs as tree prefix. So instead of using pathspecs in diff_options.{nr_paths,paths,pathlens}, tree_entry_interesting() now uses struct exclude_list. Struct exclude_list is also added to diff_options with the intention to replace {nr_paths,paths,pathlens} later on. But for now, it's just a temporary field. Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@xxxxxxxxx> --- diff.h | 3 +++ tree-diff.c | 31 ++++++++++++++++++++++++++++--- tree-walk.c | 26 +++++++++++--------------- tree-walk.h | 5 +++-- 4 files changed, 45 insertions(+), 20 deletions(-) diff --git a/diff.h b/diff.h index bf2f44d..bd8fe9e 100644 --- a/diff.h +++ b/diff.h @@ -5,6 +5,7 @@ #define DIFF_H #include "tree-walk.h" +#include "dir.h" struct rev_info; struct diff_options; @@ -136,6 +137,7 @@ struct diff_options { int nr_paths; const char **paths; int *pathlens; + struct exclude_list el; change_fn_t change; add_remove_fn_t add_remove; diff_format_fn_t format_callback; @@ -163,6 +165,7 @@ const char *diff_get_color(int diff_use_color, enum color_diff ix); extern const char mime_boundary_leader[]; extern void diff_tree_setup_paths(const char **paths, struct diff_options *); +extern void diff_tree_setup_exclude_list(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); diff --git a/tree-diff.c b/tree-diff.c index c74d0b5..c2951af 100644 --- a/tree-diff.c +++ b/tree-diff.c @@ -92,8 +92,7 @@ static void show_tree(struct diff_options *opt, const char *prefix, struct tree_ if (all_interesting) show = 1; else { - show = tree_entry_interesting(desc, base, baselen, - opt); + show = tree_entry_interesting(&desc->entry, base, baselen, &opt->el); if (show == 2) all_interesting = 1; } @@ -152,7 +151,7 @@ static void skip_uninteresting(struct tree_desc *t, const char *base, int basele if (all_interesting) show = 1; else { - show = tree_entry_interesting(t, base, baselen, opt); + show = tree_entry_interesting(&t->entry, base, baselen, &opt->el); if (show == 2) all_interesting = 1; } @@ -167,10 +166,34 @@ static void skip_uninteresting(struct tree_desc *t, const char *base, int basele } } +void diff_tree_setup_exclude_list(struct diff_options *opt) +{ + int i, size1, size2; + + memset(&opt->el, 0, sizeof(opt->el)); + opt->el.nr = opt->nr_paths; + if (!opt->el.nr) + return; + + size1 = opt->el.nr * sizeof(struct exclude *); + size2 = opt->el.nr * sizeof(struct exclude); + opt->el.excludes = xmalloc(size1+size2); + memset(opt->el.excludes, 0, size1+size2); + for (i=0; i < opt->el.nr; i++) { + struct exclude *exc = ((struct exclude *)((char*)opt->el.excludes+size1))+i; + exc->base = opt->paths[i]; + exc->baselen = opt->pathlens[i]; + opt->el.excludes[i] = exc; + } +} + int diff_tree(struct tree_desc *t1, struct tree_desc *t2, const char *base, struct diff_options *opt) { int baselen = strlen(base); + struct exclude_list el; + el = opt->el; /* diff_tree() can be nested, save and restore opt->el later */ + diff_tree_setup_exclude_list(opt); for (;;) { if (DIFF_OPT_TST(opt, QUICK) && DIFF_OPT_TST(opt, HAS_CHANGES)) @@ -204,6 +227,8 @@ int diff_tree(struct tree_desc *t1, struct tree_desc *t2, const char *base, stru } die("git diff-tree: internal error"); } + free(opt->el.excludes); + opt->el = el; return 0; } diff --git a/tree-walk.c b/tree-walk.c index bc83fa3..c915218 100644 --- a/tree-walk.c +++ b/tree-walk.c @@ -2,7 +2,7 @@ #include "tree-walk.h" #include "unpack-trees.h" #include "tree.h" -#include "diff.h" +#include "dir.h" static const char *get_mode(const char *str, unsigned int *modep) { @@ -466,25 +466,21 @@ int get_tree_entry(const unsigned char *tree_sha1, const char *name, unsigned ch * - zero for no * - negative for "no, and no subsequent entries will be either" */ -static int tree_entry_interesting(struct tree_desc *desc, const char *base, int baselen, struct diff_options *opt) +int tree_entry_interesting(const struct name_entry *entry, const char *base, int baselen, + const struct exclude_list *el) { - const char *path; - const unsigned char *sha1; - unsigned mode; int i; int pathlen; int never_interesting = -1; - if (!opt->nr_paths) + if (!el->nr) return 1; - sha1 = tree_entry_extract(desc, &path, &mode); - - pathlen = tree_entry_len(path, sha1); + pathlen = tree_entry_len(entry->path, entry->sha1); - for (i = 0; i < opt->nr_paths; i++) { - const char *match = opt->paths[i]; - int matchlen = opt->pathlens[i]; + for (i = 0; i < el->nr; i++) { + const char *match = el->excludes[i]->base; + int matchlen = el->excludes[i]->baselen; int m = -1; /* signals that we haven't called strncmp() */ if (baselen >= matchlen) { @@ -522,7 +518,7 @@ static int tree_entry_interesting(struct tree_desc *desc, const char *base, int * Does match sort strictly earlier than path * with their common parts? */ - m = strncmp(match, path, + m = strncmp(match, entry->path, (matchlen < pathlen) ? matchlen : pathlen); if (m < 0) continue; @@ -549,7 +545,7 @@ static int tree_entry_interesting(struct tree_desc *desc, const char *base, int if (matchlen > pathlen) { if (match[pathlen] != '/') continue; - if (!S_ISDIR(mode)) + if (!S_ISDIR(entry->mode)) continue; } @@ -558,7 +554,7 @@ static int tree_entry_interesting(struct tree_desc *desc, const char *base, int * we cheated and did not do strncmp(), so we do * that here. */ - m = strncmp(match, path, pathlen); + m = strncmp(match, entry->path, pathlen); /* * If common part matched earlier then it is a hit, diff --git a/tree-walk.h b/tree-walk.h index 0572721..4b37671 100644 --- a/tree-walk.h +++ b/tree-walk.h @@ -57,7 +57,8 @@ static inline int traverse_path_len(const struct traverse_info *info, const stru return info->pathlen + tree_entry_len(n->path, n->sha1); } -struct diff_options; -extern int tree_entry_interesting(struct tree_desc *desc, const char *base, int baselen, struct diff_options *opt); +struct exclude_list; +extern int tree_entry_interesting(const struct name_entry *entry, const char *base, int baselen, + const struct exclude_list *el); #endif -- 1.7.1.rc1.69.g24c2f7 -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html