diff options
Diffstat (limited to 'tree.c')
-rw-r--r-- | tree.c | 137 |
1 files changed, 64 insertions, 73 deletions
@@ -29,7 +29,7 @@ static int read_one_entry_opt(const unsigned char *sha1, const char *base, int b return add_cache_entry(ce, opt); } -static int read_one_entry(const unsigned char *sha1, const char *base, int baselen, const char *pathname, unsigned mode, int stage) +static int read_one_entry(const unsigned char *sha1, const char *base, int baselen, const char *pathname, unsigned mode, int stage, void *context) { return read_one_entry_opt(sha1, base, baselen, pathname, mode, stage, ADD_CACHE_OK_TO_ADD|ADD_CACHE_SKIP_DFCHECK); @@ -39,63 +39,21 @@ static int read_one_entry(const unsigned char *sha1, const char *base, int basel * This is used when the caller knows there is no existing entries at * the stage that will conflict with the entry being added. */ -static int read_one_entry_quick(const unsigned char *sha1, const char *base, int baselen, const char *pathname, unsigned mode, int stage) +static int read_one_entry_quick(const unsigned char *sha1, const char *base, int baselen, const char *pathname, unsigned mode, int stage, void *context) { return read_one_entry_opt(sha1, base, baselen, pathname, mode, stage, 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; - /* The base is a subdirectory of a path which was specified. */ - return 1; - } - - /* 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) +static int read_tree_1(struct tree *tree, struct strbuf *base, + int stage, struct pathspec *pathspec, + read_tree_fn_t fn, void *context) { struct tree_desc desc; struct name_entry entry; + unsigned char sha1[20]; + int len, oldlen = base->len; + enum interesting retval = entry_not_interesting; if (parse_tree(tree)) return -1; @@ -103,39 +61,72 @@ int read_tree_recursive(struct tree *tree, 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; + if (retval != all_entries_interesting) { + retval = tree_entry_interesting(&entry, base, 0, pathspec); + if (retval == all_entries_not_interesting) + break; + if (retval == entry_not_interesting) + continue; + } - switch (fn(entry.sha1, base, baselen, entry.path, entry.mode, stage)) { + switch (fn(entry.sha1, base->buf, base->len, + entry.path, entry.mode, stage, context)) { case 0: continue; case READ_TREE_RECURSIVE: - break;; + break; default: return -1; } - if (S_ISDIR(entry.mode)) { - int retval; - char *newbase; - unsigned int pathlen = tree_entry_len(entry.path, entry.sha1); - - newbase = xmalloc(baselen + 1 + pathlen); - memcpy(newbase, base, baselen); - memcpy(newbase + baselen, entry.path, pathlen); - newbase[baselen + pathlen] = '/'; - retval = read_tree_recursive(lookup_tree(entry.sha1), - newbase, - baselen + pathlen + 1, - stage, match, fn); - free(newbase); - if (retval) - return -1; - continue; + + if (S_ISDIR(entry.mode)) + hashcpy(sha1, entry.sha1); + else if (S_ISGITLINK(entry.mode)) { + struct commit *commit; + + commit = lookup_commit(entry.sha1); + if (!commit) + die("Commit %s in submodule path %s%s not found", + sha1_to_hex(entry.sha1), + base->buf, entry.path); + + if (parse_commit(commit)) + die("Invalid commit %s in submodule path %s%s", + sha1_to_hex(entry.sha1), + base->buf, entry.path); + + hashcpy(sha1, commit->tree->object.sha1); } + else + continue; + + len = tree_entry_len(&entry); + strbuf_add(base, entry.path, len); + strbuf_addch(base, '/'); + retval = read_tree_1(lookup_tree(sha1), + base, stage, pathspec, + fn, context); + strbuf_setlen(base, oldlen); + if (retval) + return -1; } return 0; } +int read_tree_recursive(struct tree *tree, + const char *base, int baselen, + int stage, struct pathspec *pathspec, + read_tree_fn_t fn, void *context) +{ + struct strbuf sb = STRBUF_INIT; + int ret; + + strbuf_add(&sb, base, baselen); + ret = read_tree_1(tree, &sb, stage, pathspec, fn, context); + strbuf_release(&sb); + return ret; +} + static int cmp_cache_name_compare(const void *a_, const void *b_) { const struct cache_entry *ce1, *ce2; @@ -146,7 +137,7 @@ static int cmp_cache_name_compare(const void *a_, const void *b_) ce2->name, ce2->ce_flags); } -int read_tree(struct tree *tree, int stage, const char **match) +int read_tree(struct tree *tree, int stage, struct pathspec *match) { read_tree_fn_t fn = NULL; int i, err; @@ -174,7 +165,7 @@ int read_tree(struct tree *tree, int stage, const char **match) if (!fn) fn = read_one_entry_quick; - err = read_tree_recursive(tree, "", 0, stage, match, fn); + err = read_tree_recursive(tree, "", 0, stage, match, fn, NULL); if (fn == read_one_entry || err) return err; |