summaryrefslogtreecommitdiff
path: root/tree.c
diff options
context:
space:
mode:
Diffstat (limited to 'tree.c')
-rw-r--r--tree.c137
1 files changed, 64 insertions, 73 deletions
diff --git a/tree.c b/tree.c
index 4b1825c2ad..676e9f710c 100644
--- a/tree.c
+++ b/tree.c
@@ -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;