static struct cache_entry *create_ce_entry(const struct traverse_info *info, const struct name_entry *n, int stage) { int len = traverse_path_len(info, n); struct cache_entry *ce = xcalloc(1, cache_entry_size(len)); ce->ce_mode = create_ce_mode(n->mode); ce->ce_flags = create_ce_flags(stage); ce->ce_namelen = len; hashcpy(ce->sha1, n->sha1); make_traverse_path(ce->name, info, n); return ce; }
static char *traverse_path(const struct traverse_info *info, const struct name_entry *n) { char *path = xmallocz(traverse_path_len(info, n) + the_hash_algo->rawsz); return make_traverse_path(path, info, n); }
static char *traverse_path(const struct traverse_info *info, const struct name_entry *n) { char *path = xmalloc(traverse_path_len(info, n) + 1); return make_traverse_path(path, info, n); }
int traverse_trees(int n, struct tree_desc *t, struct traverse_info *info) { int error = 0; struct name_entry *entry = xmalloc(n*sizeof(*entry)); int i; struct tree_desc_x *tx = xcalloc(n, sizeof(*tx)); struct strbuf base = STRBUF_INIT; int interesting = 1; for (i = 0; i < n; i++) tx[i].d = t[i]; if (info->prev) { strbuf_grow(&base, info->pathlen); make_traverse_path(base.buf, info->prev, &info->name); base.buf[info->pathlen-1] = '/'; strbuf_setlen(&base, info->pathlen); } for (;;) { int trees_used; unsigned long mask, dirmask; const char *first = NULL; int first_len = 0; struct name_entry *e = NULL; int len; for (i = 0; i < n; i++) { e = entry + i; extended_entry_extract(tx + i, e, NULL, 0); } /* * A tree may have "t-2" at the current location even * though it may have "t" that is a subtree behind it, * and another tree may return "t". We want to grab * all "t" from all trees to match in such a case. */ for (i = 0; i < n; i++) { e = entry + i; if (!e->path) continue; len = tree_entry_len(e); if (!first) { first = e->path; first_len = len; continue; } if (name_compare(e->path, len, first, first_len) < 0) { first = e->path; first_len = len; } } if (first) { for (i = 0; i < n; i++) { e = entry + i; extended_entry_extract(tx + i, e, first, first_len); /* Cull the ones that are not the earliest */ if (!e->path) continue; len = tree_entry_len(e); if (name_compare(e->path, len, first, first_len)) entry_clear(e); } } /* Now we have in entry[i] the earliest name from the trees */ mask = 0; dirmask = 0; for (i = 0; i < n; i++) { if (!entry[i].path) continue; mask |= 1ul << i; if (S_ISDIR(entry[i].mode)) dirmask |= 1ul << i; e = &entry[i]; } if (!mask) break; interesting = prune_traversal(e, info, &base, interesting); if (interesting < 0) break; if (interesting) { trees_used = info->fn(n, mask, dirmask, entry, info); if (trees_used < 0) { error = trees_used; if (!info->show_all_errors) break; } mask &= trees_used; } for (i = 0; i < n; i++) if (mask & (1ul << i)) update_extended_entry(tx + i, entry + i); } free(entry); for (i = 0; i < n; i++) free_extended_entry(tx + i); free(tx); strbuf_release(&base); return error; }