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 *'
This commit is contained in:
commit
d6f05a435f
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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:
|
||||
|
@ -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++) {
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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)
|
||||
|
41
dir.c
41
dir.c
@ -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 */
|
||||
|
@ -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;
|
||||
|
@ -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,
|
||||
|
38
pathspec.c
38
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;
|
||||
}
|
||||
|
13
pathspec.h
13
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,
|
||||
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 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,
|
||||
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,
|
||||
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 */
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
81
tree-walk.c
81
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)
|
||||
ps->max_depth == -1) {
|
||||
if (!item->attr_match_nr)
|
||||
return all_entries_interesting;
|
||||
else
|
||||
goto interesting;
|
||||
}
|
||||
|
||||
return within_depth(base_str + matchlen + 1,
|
||||
if (within_depth(base_str + matchlen + 1,
|
||||
baselen - matchlen - 1,
|
||||
!!S_ISDIR(entry->mode),
|
||||
ps->max_depth) ?
|
||||
entry_interesting : entry_not_interesting;
|
||||
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 &&
|
||||
|
@ -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,7 +99,8 @@ enum interesting {
|
||||
all_entries_interesting = 2 /* yes, and all subsequent entries will be */
|
||||
};
|
||||
|
||||
extern enum interesting tree_entry_interesting(const struct name_entry *,
|
||||
enum interesting tree_entry_interesting(struct index_state *istate,
|
||||
const struct name_entry *,
|
||||
struct strbuf *, int,
|
||||
const struct pathspec *ps);
|
||||
|
||||
|
21
tree.c
21
tree.c
@ -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;
|
||||
|
||||
|
10
tree.h
10
tree.h
@ -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,
|
||||
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,
|
||||
int read_tree(struct repository *r, struct tree *tree,
|
||||
int stage, struct pathspec *pathspec,
|
||||
struct index_state *istate);
|
||||
|
||||
#endif /* TREE_H */
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user