X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=tree-walk.c;h=02e2aed7737207225f1b96eed774a1b75dd6d8d9;hb=e064c170b4abe21f50658f2ec3b07e4ec7520767;hp=f9f7d225e976a7da5c3a83aef08ed070aa492eb9;hpb=40d934df72eaf244c826d5c26da0896ce7185cb6;p=git.git diff --git a/tree-walk.c b/tree-walk.c index f9f7d225e..02e2aed77 100644 --- a/tree-walk.c +++ b/tree-walk.c @@ -62,7 +62,7 @@ void *fill_tree_descriptor(struct tree_desc *desc, const unsigned char *sha1) static int entry_compare(struct name_entry *a, struct name_entry *b) { - return base_name_compare( + return df_name_compare( a->path, tree_entry_len(a->path, a->sha1), a->mode, b->path, tree_entry_len(b->path, b->sha1), b->mode); } @@ -107,6 +107,7 @@ int tree_entry(struct tree_desc *desc, struct name_entry *entry) void setup_traverse_info(struct traverse_info *info, const char *base) { int pathlen = strlen(base); + static struct traverse_info dummy; memset(info, 0, sizeof(*info)); if (pathlen && base[pathlen-1] == '/') @@ -114,6 +115,8 @@ void setup_traverse_info(struct traverse_info *info, const char *base) info->pathlen = pathlen ? pathlen + 1 : 0; info->name.path = base; info->name.sha1 = (void *)(base + pathlen + 1); + if (pathlen) + info->prev = &dummy; } char *make_traverse_path(char *path, const struct traverse_info *info, const struct name_entry *n) @@ -135,12 +138,14 @@ char *make_traverse_path(char *path, const struct traverse_info *info, const str return path; } -void traverse_trees(int n, struct tree_desc *t, struct traverse_info *info) +int traverse_trees(int n, struct tree_desc *t, struct traverse_info *info) { + int ret = 0; struct name_entry *entry = xmalloc(n*sizeof(*entry)); for (;;) { unsigned long mask = 0; + unsigned long dirmask = 0; int i, last; last = -1; @@ -165,25 +170,35 @@ void traverse_trees(int n, struct tree_desc *t, struct traverse_info *info) mask = 0; } mask |= 1ul << i; + if (S_ISDIR(entry[i].mode)) + dirmask |= 1ul << i; last = i; } if (!mask) break; + dirmask &= mask; /* - * Update the tree entries we've walked, and clear - * all the unused name-entries. + * Clear all the unused name-entries. */ for (i = 0; i < n; i++) { - if (mask & (1ul << i)) { - update_tree_entry(t+i); + if (mask & (1ul << i)) continue; - } entry_clear(entry + i); } - info->fn(n, mask, entry, info); + ret = info->fn(n, mask, dirmask, entry, info); + if (ret < 0) + break; + if (ret) + mask &= ret; + ret = 0; + for (i = 0; i < n; i++) { + if (mask & (1ul << i)) + update_tree_entry(t + i); + } } free(entry); + return ret; } static int find_tree_entry(struct tree_desc *t, const char *name, unsigned char *result, unsigned *mode)