The function will reconstruct directory structure from index and feed excluded_from_list() with proper dtype. Another advantage over the old will_have_skip_worktree() is that when a directory is matched or not matched, we can go ahead and set ce_flags for all of its children without calling excluded_from_list() again. The old solution requires one excluded_from_list() call per index entry. Signed-off-by: Nguyán ThÃi Ngác Duy <pclouds@xxxxxxxxx> --- unpack-trees.c | 88 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 88 insertions(+), 0 deletions(-) diff --git a/unpack-trees.c b/unpack-trees.c index 9acd9be..6c266ef 100644 --- a/unpack-trees.c +++ b/unpack-trees.c @@ -834,6 +834,94 @@ static int unpack_callback(int n, unsigned long mask, unsigned long dirmask, str return mask; } +/* + * traverse the index, find every entry that matches according to + * o->el. Do "ce_flags &= ~clear_mask" on those entries. Return the + * number of traversed entries. + * + * If select_mask is non-zero, only entries whose ce_flags has on of + * those bits enabled are traversed. + */ +static int clear_ce_flags_1(struct cache_entry **cache, int nr, + int prefix_len, int match_all, + int select_mask, int clear_mask, + struct unpack_trees_options *o) +{ + const char *name, *slash; + struct cache_entry *ce = cache[0]; + const char *prefix = ce->name; + int processed, original_nr = nr; + + if (prefix_len && !match_all) { + int dtype = DT_DIR; + static char path[PATH_MAX]; + int pathlen = prefix_len - 1; + const char *basename; + + memcpy(path, prefix, pathlen); + path[pathlen] = '\0'; + basename = strrchr(path, '/'); + basename = basename ? basename+1 : path; + switch (excluded_from_list(path, pathlen, basename, &dtype, o->el)) { + case 0: + while (nr && !strncmp(ce->name, prefix, prefix_len)) { + cache++; + ce = *cache; + nr--; + } + return original_nr - nr; + case 1: + match_all = 1; + break; + default: /* case -1, undecided */ + break; + } + } + + while (nr) { + if (select_mask && !(ce->ce_flags & select_mask)) { + cache++; + ce = *cache; + nr--; + continue; + } + + if (prefix_len && strncmp(ce->name, prefix, prefix_len)) + break; + + name = ce->name + prefix_len; + slash = strchr(name, '/'); + + /* no slash, this is a file */ + if (!slash) { + int dtype = ce_to_dtype(ce); + if (match_all || + excluded_from_list(ce->name, ce_namelen(ce), name, &dtype, o->el) > 0) + ce->ce_flags &= ~clear_mask; + cache++; + ce = *cache; + nr--; + continue; + } + + /* has slash, this is a directory */ + processed = clear_ce_flags_1(cache, nr, + slash + 1 - ce->name, match_all, + select_mask, clear_mask, o); + cache += processed; + ce = *cache; + nr -= processed; + } + return original_nr - nr; +} + +static int clear_ce_flags(struct cache_entry **cache, int nr, + int select_mask, int clear_mask, + struct unpack_trees_options *o) +{ + return clear_ce_flags_1(cache, nr, 0, 0, select_mask, clear_mask, o); +} + static void set_new_skip_worktree_1(struct unpack_trees_options *o) { int i; -- 1.7.3.2.210.g045198 -- 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