diff options
author | Junio C Hamano <gitster@pobox.com> | 2019-01-14 15:29:28 -0800 |
---|---|---|
committer | Junio C Hamano <gitster@pobox.com> | 2019-01-14 15:29:28 -0800 |
commit | d6f05a435f9c89f8c9860c7af692942768d81584 (patch) | |
tree | 7b43bdb292f9cda801778647a67ddc2662504067 | |
parent | Merge branch 'md/list-lazy-objects-fix' (diff) | |
parent | tree-walk: support :(attr) matching (diff) | |
download | tgif-d6f05a435f9c89f8c9860c7af692942768d81584.tar.xz |
Merge branch 'nd/attr-pathspec-in-tree-walk'
The traversal over tree objects has learned to honor
":(attr:label)" pathspec match, which has been implemented only for
enumerating paths on the filesystem.
* nd/attr-pathspec-in-tree-walk:
tree-walk: support :(attr) matching
dir.c: move, rename and export match_attrs()
pathspec.h: clean up "extern" in function declarations
tree-walk.c: make tree_entry_interesting() take an index
tree.c: make read_tree*() take 'struct repository *'
-rw-r--r-- | Documentation/glossary-content.txt | 2 | ||||
-rw-r--r-- | archive.c | 6 | ||||
-rw-r--r-- | builtin/checkout.c | 3 | ||||
-rw-r--r-- | builtin/grep.c | 3 | ||||
-rw-r--r-- | builtin/log.c | 5 | ||||
-rw-r--r-- | builtin/ls-files.c | 2 | ||||
-rw-r--r-- | builtin/ls-tree.c | 3 | ||||
-rw-r--r-- | builtin/merge-tree.c | 2 | ||||
-rw-r--r-- | dir.c | 41 | ||||
-rw-r--r-- | list-objects.c | 3 | ||||
-rw-r--r-- | merge-recursive.c | 3 | ||||
-rw-r--r-- | pathspec.c | 38 | ||||
-rw-r--r-- | pathspec.h | 27 | ||||
-rw-r--r-- | revision.c | 1 | ||||
-rwxr-xr-x | t/t6135-pathspec-with-attrs.sh | 58 | ||||
-rw-r--r-- | tree-diff.c | 3 | ||||
-rw-r--r-- | tree-walk.c | 89 | ||||
-rw-r--r-- | tree-walk.h | 10 | ||||
-rw-r--r-- | tree.c | 21 | ||||
-rw-r--r-- | tree.h | 18 | ||||
-rw-r--r-- | unpack-trees.c | 6 |
21 files changed, 235 insertions, 109 deletions
diff --git a/Documentation/glossary-content.txt b/Documentation/glossary-content.txt index 0d2aa48c63..023ca95e7c 100644 --- a/Documentation/glossary-content.txt +++ b/Documentation/glossary-content.txt @@ -404,6 +404,8 @@ these forms: - "`!ATTR`" requires that the attribute `ATTR` be unspecified. + +Note that when matching against a tree object, attributes are still +obtained from working tree, not from the given tree object. exclude;; After a path matches any non-exclude pathspec, it will be run @@ -285,7 +285,8 @@ int write_archive_entries(struct archiver_args *args, git_attr_set_direction(GIT_ATTR_INDEX); } - err = read_tree_recursive(args->tree, "", 0, 0, &args->pathspec, + err = read_tree_recursive(args->repo, args->tree, "", + 0, 0, &args->pathspec, queue_or_write_archive_entry, &context); if (err == READ_TREE_RECURSIVE) @@ -346,7 +347,8 @@ static int path_exists(struct archiver_args *args, const char *path) ctx.args = args; parse_pathspec(&ctx.pathspec, 0, 0, "", paths); ctx.pathspec.recursive = 1; - ret = read_tree_recursive(args->tree, "", 0, 0, &ctx.pathspec, + ret = read_tree_recursive(args->repo, args->tree, "", + 0, 0, &ctx.pathspec, reject_entry, &ctx); clear_pathspec(&ctx.pathspec); return ret != 0; diff --git a/builtin/checkout.c b/builtin/checkout.c index 08b0ac48f3..d338d96fe9 100644 --- a/builtin/checkout.c +++ b/builtin/checkout.c @@ -115,7 +115,8 @@ static int update_some(const struct object_id *oid, struct strbuf *base, static int read_tree_some(struct tree *tree, const struct pathspec *pathspec) { - read_tree_recursive(tree, "", 0, 0, pathspec, update_some, NULL); + read_tree_recursive(the_repository, tree, "", 0, 0, + pathspec, update_some, NULL); /* update the index with the given tree's info * for all args, expanding wildcards, and exit diff --git a/builtin/grep.c b/builtin/grep.c index bad9c0a3d5..4748195ae1 100644 --- a/builtin/grep.c +++ b/builtin/grep.c @@ -553,7 +553,8 @@ static int grep_tree(struct grep_opt *opt, const struct pathspec *pathspec, if (match != all_entries_interesting) { strbuf_addstr(&name, base->buf + tn_len); - match = tree_entry_interesting(&entry, &name, + match = tree_entry_interesting(repo->index, + &entry, &name, 0, pathspec); strbuf_setlen(&name, name_base_len); diff --git a/builtin/log.c b/builtin/log.c index e8e51068bd..3e145fe502 100644 --- a/builtin/log.c +++ b/builtin/log.c @@ -641,8 +641,9 @@ int cmd_show(int argc, const char **argv, const char *prefix) diff_get_color_opt(&rev.diffopt, DIFF_COMMIT), name, diff_get_color_opt(&rev.diffopt, DIFF_RESET)); - read_tree_recursive((struct tree *)o, "", 0, 0, &match_all, - show_tree_object, rev.diffopt.file); + read_tree_recursive(the_repository, (struct tree *)o, "", + 0, 0, &match_all, show_tree_object, + rev.diffopt.file); rev.shown_one = 1; break; case OBJ_COMMIT: diff --git a/builtin/ls-files.c b/builtin/ls-files.c index c70a9c7158..7e0dcaa359 100644 --- a/builtin/ls-files.c +++ b/builtin/ls-files.c @@ -441,7 +441,7 @@ void overlay_tree_on_index(struct index_state *istate, PATHSPEC_PREFER_CWD, prefix, matchbuf); } else memset(&pathspec, 0, sizeof(pathspec)); - if (read_tree(tree, 1, &pathspec, istate)) + if (read_tree(the_repository, tree, 1, &pathspec, istate)) die("unable to read tree entries %s", tree_name); for (i = 0; i < istate->cache_nr; i++) { diff --git a/builtin/ls-tree.c b/builtin/ls-tree.c index 7d581d6463..7cad3f24eb 100644 --- a/builtin/ls-tree.c +++ b/builtin/ls-tree.c @@ -185,5 +185,6 @@ int cmd_ls_tree(int argc, const char **argv, const char *prefix) tree = parse_tree_indirect(&oid); if (!tree) die("not a tree object"); - return !!read_tree_recursive(tree, "", 0, 0, &pathspec, show_tree, NULL); + return !!read_tree_recursive(the_repository, tree, "", 0, 0, + &pathspec, show_tree, NULL); } diff --git a/builtin/merge-tree.c b/builtin/merge-tree.c index 70f6fc9167..4984b7e12e 100644 --- a/builtin/merge-tree.c +++ b/builtin/merge-tree.c @@ -346,7 +346,7 @@ static void merge_trees(struct tree_desc t[3], const char *base) setup_traverse_info(&info, base); info.fn = threeway_callback; - traverse_trees(3, t, &info); + traverse_trees(&the_index, 3, t, &info); } static void *get_tree_descriptor(struct tree_desc *desc, const char *rev) @@ -276,44 +276,6 @@ static int do_read_blob(const struct object_id *oid, struct oid_stat *oid_stat, #define DO_MATCH_DIRECTORY (1<<1) #define DO_MATCH_SUBMODULE (1<<2) -static int match_attrs(const struct index_state *istate, - const char *name, int namelen, - const struct pathspec_item *item) -{ - int i; - char *to_free = NULL; - - if (name[namelen]) - name = to_free = xmemdupz(name, namelen); - - git_check_attr(istate, name, item->attr_check); - - free(to_free); - - for (i = 0; i < item->attr_match_nr; i++) { - const char *value; - int matched; - enum attr_match_mode match_mode; - - value = item->attr_check->items[i].value; - match_mode = item->attr_match[i].match_mode; - - if (ATTR_TRUE(value)) - matched = (match_mode == MATCH_SET); - else if (ATTR_FALSE(value)) - matched = (match_mode == MATCH_UNSET); - else if (ATTR_UNSET(value)) - matched = (match_mode == MATCH_UNSPECIFIED); - else - matched = (match_mode == MATCH_VALUE && - !strcmp(item->attr_match[i].value, value)); - if (!matched) - return 0; - } - - return 1; -} - /* * Does 'match' match the given name? * A match is found if @@ -367,7 +329,8 @@ static int match_pathspec_item(const struct index_state *istate, strncmp(item->match, name - prefix, item->prefix)) return 0; - if (item->attr_match_nr && !match_attrs(istate, name, namelen, item)) + if (item->attr_match_nr && + !match_pathspec_attrs(istate, name, namelen, item)) return 0; /* If the match was just the prefix, we matched */ diff --git a/list-objects.c b/list-objects.c index cf7f25bed3..4e2789768d 100644 --- a/list-objects.c +++ b/list-objects.c @@ -114,7 +114,8 @@ static void process_tree_contents(struct traversal_context *ctx, while (tree_entry(&desc, &entry)) { if (match != all_entries_interesting) { - match = tree_entry_interesting(&entry, base, 0, + match = tree_entry_interesting(ctx->revs->repo->index, + &entry, base, 0, &ctx->revs->diffopt.pathspec); if (match == all_entries_not_interesting) break; diff --git a/merge-recursive.c b/merge-recursive.c index ecf8db0b71..59ba4b4a1a 100644 --- a/merge-recursive.c +++ b/merge-recursive.c @@ -469,7 +469,8 @@ static void get_files_dirs(struct merge_options *o, struct tree *tree) { struct pathspec match_all; memset(&match_all, 0, sizeof(match_all)); - read_tree_recursive(tree, "", 0, 0, &match_all, save_files_dirs, o); + read_tree_recursive(the_repository, tree, "", 0, 0, + &match_all, save_files_dirs, o); } static int get_tree_entry_if_blob(const struct object_id *tree, diff --git a/pathspec.c b/pathspec.c index 6f005996fd..e85298f68c 100644 --- a/pathspec.c +++ b/pathspec.c @@ -659,3 +659,41 @@ void clear_pathspec(struct pathspec *pathspec) FREE_AND_NULL(pathspec->items); pathspec->nr = 0; } + +int match_pathspec_attrs(const struct index_state *istate, + const char *name, int namelen, + const struct pathspec_item *item) +{ + int i; + char *to_free = NULL; + + if (name[namelen]) + name = to_free = xmemdupz(name, namelen); + + git_check_attr(istate, name, item->attr_check); + + free(to_free); + + for (i = 0; i < item->attr_match_nr; i++) { + const char *value; + int matched; + enum attr_match_mode match_mode; + + value = item->attr_check->items[i].value; + match_mode = item->attr_match[i].match_mode; + + if (ATTR_TRUE(value)) + matched = (match_mode == MATCH_SET); + else if (ATTR_FALSE(value)) + matched = (match_mode == MATCH_UNSET); + else if (ATTR_UNSET(value)) + matched = (match_mode == MATCH_UNSPECIFIED); + else + matched = (match_mode == MATCH_VALUE && + !strcmp(item->attr_match[i].value, value)); + if (!matched) + return 0; + } + + return 1; +} diff --git a/pathspec.h b/pathspec.h index a6525a6551..1c18a2c90c 100644 --- a/pathspec.h +++ b/pathspec.h @@ -80,13 +80,13 @@ struct pathspec { * Any arguments used are copied. It is safe for the caller to modify * or free 'prefix' and 'args' after calling this function. */ -extern void parse_pathspec(struct pathspec *pathspec, - unsigned magic_mask, - unsigned flags, - const char *prefix, - const char **args); -extern void copy_pathspec(struct pathspec *dst, const struct pathspec *src); -extern void clear_pathspec(struct pathspec *); +void parse_pathspec(struct pathspec *pathspec, + unsigned magic_mask, + unsigned flags, + const char *prefix, + const char **args); +void copy_pathspec(struct pathspec *dst, const struct pathspec *src); +void clear_pathspec(struct pathspec *); static inline int ps_strncmp(const struct pathspec_item *item, const char *s1, const char *s2, size_t n) @@ -106,10 +106,13 @@ static inline int ps_strcmp(const struct pathspec_item *item, return strcmp(s1, s2); } -extern void add_pathspec_matches_against_index(const struct pathspec *pathspec, - const struct index_state *istate, - char *seen); -extern char *find_pathspecs_matching_against_index(const struct pathspec *pathspec, - const struct index_state *istate); +void add_pathspec_matches_against_index(const struct pathspec *pathspec, + const struct index_state *istate, + char *seen); +char *find_pathspecs_matching_against_index(const struct pathspec *pathspec, + const struct index_state *istate); +int match_pathspec_attrs(const struct index_state *istate, + const char *name, int namelen, + const struct pathspec_item *item); #endif /* PATHSPEC_H */ diff --git a/revision.c b/revision.c index 293303b67d..f1e6929d41 100644 --- a/revision.c +++ b/revision.c @@ -1463,6 +1463,7 @@ void repo_init_revisions(struct repository *r, revs->abbrev = DEFAULT_ABBREV; revs->ignore_merges = 1; revs->simplify_history = 1; + revs->pruning.repo = r; revs->pruning.flags.recursive = 1; revs->pruning.flags.quick = 1; revs->pruning.add_remove = file_add_remove; diff --git a/t/t6135-pathspec-with-attrs.sh b/t/t6135-pathspec-with-attrs.sh index e436a73962..457cc167c7 100755 --- a/t/t6135-pathspec-with-attrs.sh +++ b/t/t6135-pathspec-with-attrs.sh @@ -31,7 +31,7 @@ test_expect_success 'setup a tree' ' mkdir sub && while read path do - : >$path && + echo content >$path && git add $path || return 1 done <expect && git commit -m "initial commit" && @@ -48,6 +48,10 @@ test_expect_success 'pathspec with labels and non existent .gitattributes' ' test_must_be_empty actual ' +test_expect_success 'pathspec with labels and non existent .gitattributes (2)' ' + test_must_fail git grep content HEAD -- ":(attr:label)" +' + test_expect_success 'setup .gitattributes' ' cat <<-\EOF >.gitattributes && fileA labelA @@ -74,6 +78,15 @@ test_expect_success 'check specific set attr' ' test_cmp expect actual ' +test_expect_success 'check specific set attr (2)' ' + cat <<-\EOF >expect && + HEAD:fileSetLabel + HEAD:sub/fileSetLabel + EOF + git grep -l content HEAD ":(attr:label)" >actual && + test_cmp expect actual +' + test_expect_success 'check specific unset attr' ' cat <<-\EOF >expect && fileUnsetLabel @@ -83,6 +96,15 @@ test_expect_success 'check specific unset attr' ' test_cmp expect actual ' +test_expect_success 'check specific unset attr (2)' ' + cat <<-\EOF >expect && + HEAD:fileUnsetLabel + HEAD:sub/fileUnsetLabel + EOF + git grep -l content HEAD ":(attr:-label)" >actual && + test_cmp expect actual +' + test_expect_success 'check specific value attr' ' cat <<-\EOF >expect && fileValue @@ -94,6 +116,16 @@ test_expect_success 'check specific value attr' ' test_must_be_empty actual ' +test_expect_success 'check specific value attr (2)' ' + cat <<-\EOF >expect && + HEAD:fileValue + HEAD:sub/fileValue + EOF + git grep -l content HEAD ":(attr:label=foo)" >actual && + test_cmp expect actual && + test_must_fail git grep -l content HEAD ":(attr:label=bar)" +' + test_expect_success 'check unspecified attr' ' cat <<-\EOF >expect && .gitattributes @@ -118,6 +150,30 @@ test_expect_success 'check unspecified attr' ' test_cmp expect actual ' +test_expect_success 'check unspecified attr (2)' ' + cat <<-\EOF >expect && + HEAD:.gitattributes + HEAD:fileA + HEAD:fileAB + HEAD:fileAC + HEAD:fileB + HEAD:fileBC + HEAD:fileC + HEAD:fileNoLabel + HEAD:fileWrongLabel + HEAD:sub/fileA + HEAD:sub/fileAB + HEAD:sub/fileAC + HEAD:sub/fileB + HEAD:sub/fileBC + HEAD:sub/fileC + HEAD:sub/fileNoLabel + HEAD:sub/fileWrongLabel + EOF + git grep -l ^ HEAD ":(attr:!label)" >actual && + test_cmp expect actual +' + test_expect_success 'check multiple unspecified attr' ' cat <<-\EOF >expect && .gitattributes diff --git a/tree-diff.c b/tree-diff.c index 0e54324610..34ee3b13b8 100644 --- a/tree-diff.c +++ b/tree-diff.c @@ -299,7 +299,8 @@ static void skip_uninteresting(struct tree_desc *t, struct strbuf *base, enum interesting match; while (t->size) { - match = tree_entry_interesting(&t->entry, base, 0, &opt->pathspec); + match = tree_entry_interesting(opt->repo->index, &t->entry, + base, 0, &opt->pathspec); if (match) { if (match == all_entries_not_interesting) t->size = 0; diff --git a/tree-walk.c b/tree-walk.c index 79bafbd1a2..08210a4109 100644 --- a/tree-walk.c +++ b/tree-walk.c @@ -365,7 +365,8 @@ static void free_extended_entry(struct tree_desc_x *t) } } -static inline int prune_traversal(struct name_entry *e, +static inline int prune_traversal(struct index_state *istate, + struct name_entry *e, struct traverse_info *info, struct strbuf *base, int still_interesting) @@ -374,10 +375,13 @@ static inline int prune_traversal(struct name_entry *e, return 2; if (still_interesting < 0) return still_interesting; - return tree_entry_interesting(e, base, 0, info->pathspec); + return tree_entry_interesting(istate, e, base, + 0, info->pathspec); } -int traverse_trees(int n, struct tree_desc *t, struct traverse_info *info) +int traverse_trees(struct index_state *istate, + int n, struct tree_desc *t, + struct traverse_info *info) { int error = 0; struct name_entry *entry = xmalloc(n*sizeof(*entry)); @@ -461,7 +465,7 @@ int traverse_trees(int n, struct tree_desc *t, struct traverse_info *info) } if (!mask) break; - interesting = prune_traversal(e, info, &base, interesting); + interesting = prune_traversal(istate, e, info, &base, interesting); if (interesting < 0) break; if (interesting) { @@ -928,7 +932,8 @@ static int match_wildcard_base(const struct pathspec_item *item, * Pre-condition: either baselen == base_offset (i.e. empty path) * or base[baselen-1] == '/' (i.e. with trailing slash). */ -static enum interesting do_match(const struct name_entry *entry, +static enum interesting do_match(struct index_state *istate, + const struct name_entry *entry, struct strbuf *base, int base_offset, const struct pathspec *ps, int exclude) @@ -944,7 +949,8 @@ static enum interesting do_match(const struct name_entry *entry, PATHSPEC_LITERAL | PATHSPEC_GLOB | PATHSPEC_ICASE | - PATHSPEC_EXCLUDE); + PATHSPEC_EXCLUDE | + PATHSPEC_ATTR); if (!ps->nr) { if (!ps->recursive || @@ -976,14 +982,20 @@ static enum interesting do_match(const struct name_entry *entry, if (!ps->recursive || !(ps->magic & PATHSPEC_MAXDEPTH) || - ps->max_depth == -1) - return all_entries_interesting; - - return within_depth(base_str + matchlen + 1, - baselen - matchlen - 1, - !!S_ISDIR(entry->mode), - ps->max_depth) ? - entry_interesting : entry_not_interesting; + ps->max_depth == -1) { + if (!item->attr_match_nr) + return all_entries_interesting; + else + goto interesting; + } + + if (within_depth(base_str + matchlen + 1, + baselen - matchlen - 1, + !!S_ISDIR(entry->mode), + ps->max_depth)) + goto interesting; + else + return entry_not_interesting; } /* Either there must be no base, or the base must match. */ @@ -991,12 +1003,12 @@ static enum interesting do_match(const struct name_entry *entry, if (match_entry(item, entry, pathlen, match + baselen, matchlen - baselen, &never_interesting)) - return entry_interesting; + goto interesting; if (item->nowildcard_len < item->len) { if (!git_fnmatch(item, match + baselen, entry->path, item->nowildcard_len - baselen)) - return entry_interesting; + goto interesting; /* * Match all directories. We'll try to @@ -1017,7 +1029,7 @@ static enum interesting do_match(const struct name_entry *entry, !ps_strncmp(item, match + baselen, entry->path, item->nowildcard_len - baselen)) - return entry_interesting; + goto interesting; } continue; @@ -1052,7 +1064,7 @@ match_wildcards: if (!git_fnmatch(item, match, base->buf + base_offset, item->nowildcard_len)) { strbuf_setlen(base, base_offset + baselen); - return entry_interesting; + goto interesting; } /* @@ -1066,7 +1078,7 @@ match_wildcards: !ps_strncmp(item, match, base->buf + base_offset, item->nowildcard_len)) { strbuf_setlen(base, base_offset + baselen); - return entry_interesting; + goto interesting; } strbuf_setlen(base, base_offset + baselen); @@ -1080,6 +1092,38 @@ match_wildcards: */ if (ps->recursive && S_ISDIR(entry->mode)) return entry_interesting; + continue; +interesting: + if (item->attr_match_nr) { + int ret; + + /* + * Must not return all_entries_not_interesting + * prematurely. We do not know if all entries do not + * match some attributes with current attr API. + */ + never_interesting = entry_not_interesting; + + /* + * Consider all directories interesting (because some + * of those files inside may match some attributes + * even though the parent dir does not) + * + * FIXME: attributes _can_ match directories and we + * can probably return all_entries_interesting or + * all_entries_not_interesting here if matched. + */ + if (S_ISDIR(entry->mode)) + return entry_interesting; + + strbuf_add(base, entry->path, pathlen); + ret = match_pathspec_attrs(istate, base->buf + base_offset, + base->len - base_offset, item); + strbuf_setlen(base, base_offset + baselen); + if (!ret) + continue; + } + return entry_interesting; } return never_interesting; /* No matches */ } @@ -1090,12 +1134,13 @@ match_wildcards: * Pre-condition: either baselen == base_offset (i.e. empty path) * or base[baselen-1] == '/' (i.e. with trailing slash). */ -enum interesting tree_entry_interesting(const struct name_entry *entry, +enum interesting tree_entry_interesting(struct index_state *istate, + const struct name_entry *entry, struct strbuf *base, int base_offset, const struct pathspec *ps) { enum interesting positive, negative; - positive = do_match(entry, base, base_offset, ps, 0); + positive = do_match(istate, entry, base, base_offset, ps, 0); /* * case | entry | positive | negative | result @@ -1132,7 +1177,7 @@ enum interesting tree_entry_interesting(const struct name_entry *entry, positive <= entry_not_interesting) /* #1, #2, #11, #12 */ return positive; - negative = do_match(entry, base, base_offset, ps, 1); + negative = do_match(istate, entry, base, base_offset, ps, 1); /* #8, #18 */ if (positive == all_entries_interesting && diff --git a/tree-walk.h b/tree-walk.h index 196831007e..eefd26bb62 100644 --- a/tree-walk.h +++ b/tree-walk.h @@ -1,6 +1,7 @@ #ifndef TREE_WALK_H #define TREE_WALK_H +struct index_state; struct strbuf; struct name_entry { @@ -48,7 +49,7 @@ void *fill_tree_descriptor(struct tree_desc *desc, const struct object_id *oid); struct traverse_info; typedef int (*traverse_callback_t)(int n, unsigned long mask, unsigned long dirmask, struct name_entry *entry, struct traverse_info *); -int traverse_trees(int n, struct tree_desc *t, struct traverse_info *info); +int traverse_trees(struct index_state *istate, int n, struct tree_desc *t, struct traverse_info *info); enum follow_symlinks_result { FOUND = 0, /* This includes out-of-tree links */ @@ -98,8 +99,9 @@ enum interesting { all_entries_interesting = 2 /* yes, and all subsequent entries will be */ }; -extern enum interesting tree_entry_interesting(const struct name_entry *, - struct strbuf *, int, - const struct pathspec *ps); +enum interesting tree_entry_interesting(struct index_state *istate, + const struct name_entry *, + struct strbuf *, int, + const struct pathspec *ps); #endif @@ -60,7 +60,8 @@ static int read_one_entry_quick(const struct object_id *oid, struct strbuf *base ADD_CACHE_JUST_APPEND); } -static int read_tree_1(struct tree *tree, struct strbuf *base, +static int read_tree_1(struct repository *r, + struct tree *tree, struct strbuf *base, int stage, const struct pathspec *pathspec, read_tree_fn_t fn, void *context) { @@ -77,7 +78,8 @@ static int read_tree_1(struct tree *tree, struct strbuf *base, while (tree_entry(&desc, &entry)) { if (retval != all_entries_interesting) { - retval = tree_entry_interesting(&entry, base, 0, pathspec); + retval = tree_entry_interesting(r->index, &entry, + base, 0, pathspec); if (retval == all_entries_not_interesting) break; if (retval == entry_not_interesting) @@ -99,7 +101,7 @@ static int read_tree_1(struct tree *tree, struct strbuf *base, else if (S_ISGITLINK(entry.mode)) { struct commit *commit; - commit = lookup_commit(the_repository, entry.oid); + commit = lookup_commit(r, entry.oid); if (!commit) die("Commit %s in submodule path %s%s not found", oid_to_hex(entry.oid), @@ -118,7 +120,7 @@ static int read_tree_1(struct tree *tree, struct strbuf *base, len = tree_entry_len(&entry); strbuf_add(base, entry.path, len); strbuf_addch(base, '/'); - retval = read_tree_1(lookup_tree(the_repository, &oid), + retval = read_tree_1(r, lookup_tree(r, &oid), base, stage, pathspec, fn, context); strbuf_setlen(base, oldlen); @@ -128,7 +130,8 @@ static int read_tree_1(struct tree *tree, struct strbuf *base, return 0; } -int read_tree_recursive(struct tree *tree, +int read_tree_recursive(struct repository *r, + struct tree *tree, const char *base, int baselen, int stage, const struct pathspec *pathspec, read_tree_fn_t fn, void *context) @@ -137,7 +140,7 @@ int read_tree_recursive(struct tree *tree, int ret; strbuf_add(&sb, base, baselen); - ret = read_tree_1(tree, &sb, stage, pathspec, fn, context); + ret = read_tree_1(r, tree, &sb, stage, pathspec, fn, context); strbuf_release(&sb); return ret; } @@ -152,8 +155,8 @@ static int cmp_cache_name_compare(const void *a_, const void *b_) ce2->name, ce2->ce_namelen, ce_stage(ce2)); } -int read_tree(struct tree *tree, int stage, struct pathspec *match, - struct index_state *istate) +int read_tree(struct repository *r, struct tree *tree, int stage, + struct pathspec *match, struct index_state *istate) { read_tree_fn_t fn = NULL; int i, err; @@ -181,7 +184,7 @@ int read_tree(struct tree *tree, int stage, struct pathspec *match, if (!fn) fn = read_one_entry_quick; - err = read_tree_recursive(tree, "", 0, stage, match, fn, istate); + err = read_tree_recursive(r, tree, "", 0, stage, match, fn, istate); if (fn == read_one_entry || err) return err; @@ -3,7 +3,7 @@ #include "object.h" -extern const char *tree_type; +struct repository; struct strbuf; struct tree { @@ -12,6 +12,8 @@ struct tree { unsigned long size; }; +extern const char *tree_type; + struct tree *lookup_tree(struct repository *r, const struct object_id *oid); int parse_tree_buffer(struct tree *item, void *buffer, unsigned long size); @@ -29,12 +31,14 @@ struct tree *parse_tree_indirect(const struct object_id *oid); #define READ_TREE_RECURSIVE 1 typedef int (*read_tree_fn_t)(const struct object_id *, struct strbuf *, const char *, unsigned int, int, void *); -extern int read_tree_recursive(struct tree *tree, - const char *base, int baselen, - int stage, const struct pathspec *pathspec, - read_tree_fn_t fn, void *context); +int read_tree_recursive(struct repository *r, + struct tree *tree, + const char *base, int baselen, + int stage, const struct pathspec *pathspec, + read_tree_fn_t fn, void *context); -extern int read_tree(struct tree *tree, int stage, struct pathspec *pathspec, - struct index_state *istate); +int read_tree(struct repository *r, struct tree *tree, + int stage, struct pathspec *pathspec, + struct index_state *istate); #endif /* TREE_H */ diff --git a/unpack-trees.c b/unpack-trees.c index 6d53cbfc86..c70e9926e4 100644 --- a/unpack-trees.c +++ b/unpack-trees.c @@ -794,6 +794,7 @@ static int traverse_trees_recursive(int n, unsigned long dirmask, struct name_entry *names, struct traverse_info *info) { + struct unpack_trees_options *o = info->data; int i, ret, bottom; int nr_buf = 0; struct tree_desc t[MAX_UNPACK_TREES]; @@ -804,7 +805,6 @@ static int traverse_trees_recursive(int n, unsigned long dirmask, nr_entries = all_trees_same_as_cache_tree(n, dirmask, names, info); if (nr_entries > 0) { - struct unpack_trees_options *o = info->data; int pos = index_pos_by_traverse_info(names, info); if (!o->merge || df_conflicts) @@ -863,7 +863,7 @@ static int traverse_trees_recursive(int n, unsigned long dirmask, } bottom = switch_cache_bottom(&newinfo); - ret = traverse_trees(n, t, &newinfo); + ret = traverse_trees(o->src_index, n, t, &newinfo); restore_cache_bottom(&newinfo, bottom); for (i = 0; i < nr_buf; i++) @@ -1550,7 +1550,7 @@ int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_trees_options } trace_performance_enter(); - ret = traverse_trees(len, t, &info); + ret = traverse_trees(o->src_index, len, t, &info); trace_performance_leave("traverse_trees"); if (ret < 0) goto return_failed; |