WARNING: RFC because: This has a minor conflict with my sparse-clone series, and a less minor conflict with Nguyễn Thái Ngọc Duy's updates to the en/object-list-with-pathspec series. Duy's changes to en/object-list-with-pathspec, at least with my additional suggestions, should probably also be applied to en/tree-walk-optim for skip_uninteresting. If all that other stuff is done, this particular patch could be made smaller and we could nuke the FIXME. That'd make it into a simple code cleanup. I'm sending right now for comments, before I forget about this simple cleanup. I'll clean up and resend once Duy is done with his changes. --- tree-diff.c | 2 +- tree-walk.h | 3 ++ tree.c | 77 ++++++++++++++++++---------------------------------------- 3 files changed, 28 insertions(+), 54 deletions(-) diff --git a/tree-diff.c b/tree-diff.c index cd659c6..2fb670b 100644 --- a/tree-diff.c +++ b/tree-diff.c @@ -91,7 +91,7 @@ static int compare_tree_entry(struct tree_desc *t1, struct tree_desc *t2, const * - 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(struct tree_desc *desc, const char *base, int baselen, struct diff_options *opt) { const char *path; const unsigned char *sha1; diff --git a/tree-walk.h b/tree-walk.h index 7e3e0b5..e3e0137 100644 --- a/tree-walk.h +++ b/tree-walk.h @@ -60,4 +60,7 @@ 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); + #endif diff --git a/tree.c b/tree.c index 5ab90af..405f56b 100644 --- a/tree.c +++ b/tree.c @@ -5,6 +5,13 @@ #include "commit.h" #include "tag.h" #include "tree-walk.h" +/* + * FIXME: Shouldn't need diff.h, but need it now for skip_uninteresting and + * diff_options; Nguyen's pending update to en/object-list-with-pathspec may + * fix this need, if coupled with my suggestion and a similar fix for + * skip_uninteresting... + */ +#include "diff.h" const char *tree_type = "tree"; @@ -45,71 +52,35 @@ static int read_one_entry_quick(const unsigned char *sha1, const char *base, int ADD_CACHE_JUST_APPEND); } -static int match_tree_entry(const char *base, int baselen, const char *path, unsigned int mode, const char **paths) -{ - const char *match; - int pathlen; - - if (!paths) - return 1; - pathlen = strlen(path); - while ((match = *paths++) != NULL) { - int matchlen = strlen(match); - - if (baselen >= matchlen) { - /* If it doesn't match, move along... */ - if (strncmp(base, match, matchlen)) - continue; - /* pathspecs match only at the directory boundaries */ - if (!matchlen || - baselen == matchlen || - base[matchlen] == '/' || - match[matchlen - 1] == '/') - return 1; - continue; - } - - /* Does the base match? */ - if (strncmp(base, match, baselen)) - continue; - - match += baselen; - matchlen -= baselen; - - if (pathlen > matchlen) - continue; - - if (matchlen > pathlen) { - if (match[pathlen] != '/') - continue; - if (!S_ISDIR(mode)) - continue; - } - - if (strncmp(path, match, pathlen)) - continue; - - return 1; - } - return 0; -} - int read_tree_recursive(struct tree *tree, const char *base, int baselen, int stage, const char **match, read_tree_fn_t fn, void *context) { struct tree_desc desc; - struct name_entry entry; + struct diff_options diff_opts; + int all_interesting; if (parse_tree(tree)) return -1; + diff_tree_setup_paths(match, &diff_opts); + all_interesting = diff_opts.nr_paths == 0; + init_tree_desc(&desc, tree->buffer, tree->size); - while (tree_entry(&desc, &entry)) { - if (!match_tree_entry(base, baselen, entry.path, entry.mode, match)) - continue; + for (; desc.size; update_tree_entry(&desc)) { + struct name_entry entry; + if (!all_interesting) { + int show = tree_entry_interesting(&desc, base, baselen, &diff_opts); + if (show < 0) + return 0; + else if (!show) + continue; + else if (show == 2) + all_interesting = 1; + } + entry = desc.entry; switch (fn(entry.sha1, base, baselen, entry.path, entry.mode, stage, context)) { case 0: -- 1.7.3.rc0.1.g43ab -- 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