[PATCH 03/10] unpack-trees: add function to update ce_flags based on sparse patterns
- From
Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
- Date
- Nov 15, 2010, 10:36 UTC
- Message-ID
- <1289817410-32470-4-git-send-email-pclouds@gmail.com>
- In-Reply-To
- <1289817410-32470-1-git-send-email-pclouds@gmail.com>
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@gmail.com> --- 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