Merge branch 'nd/struct-pathspec'

* nd/struct-pathspec:
  pathspec: rename per-item field has_wildcard to use_wildcard
  Improve tree_entry_interesting() handling code
  Convert read_tree{,_recursive} to support struct pathspec
  Reimplement read_tree_recursive() using tree_entry_interesting()
This commit is contained in:
Junio C Hamano 2011-05-06 10:50:06 -07:00
Родитель 9fdc1cc872 33e0f62ba9
Коммит 1273738f05
15 изменённых файлов: 148 добавлений и 169 удалений

Просмотреть файл

@ -157,6 +157,7 @@ int write_archive_entries(struct archiver_args *args,
struct archiver_context context;
struct unpack_trees_options opts;
struct tree_desc t;
struct pathspec pathspec;
int err;
if (args->baselen > 0 && args->base[args->baselen - 1] == '/') {
@ -191,8 +192,10 @@ int write_archive_entries(struct archiver_args *args,
git_attr_set_direction(GIT_ATTR_INDEX, &the_index);
}
err = read_tree_recursive(args->tree, "", 0, 0, args->pathspec,
init_pathspec(&pathspec, args->pathspec);
err = read_tree_recursive(args->tree, "", 0, 0, &pathspec,
write_archive_entry, &context);
free_pathspec(&pathspec);
if (err == READ_TREE_RECURSIVE)
err = 0;
return err;
@ -221,11 +224,14 @@ static int reject_entry(const unsigned char *sha1, const char *base,
static int path_exists(struct tree *tree, const char *path)
{
const char *pathspec[] = { path, NULL };
const char *paths[] = { path, NULL };
struct pathspec pathspec;
int ret;
if (read_tree_recursive(tree, "", 0, 0, pathspec, reject_entry, NULL))
return 1;
return 0;
init_pathspec(&pathspec, paths);
ret = read_tree_recursive(tree, "", 0, 0, &pathspec, reject_entry, NULL);
free_pathspec(&pathspec);
return ret != 0;
}
static void parse_pathspec_arg(const char **pathspec,

Просмотреть файл

@ -79,7 +79,10 @@ static int update_some(const unsigned char *sha1, const char *base, int baselen,
static int read_tree_some(struct tree *tree, const char **pathspec)
{
read_tree_recursive(tree, "", 0, 0, pathspec, update_some, NULL);
struct pathspec ps;
init_pathspec(&ps, pathspec);
read_tree_recursive(tree, "", 0, 0, &ps, update_some, NULL);
free_pathspec(&ps);
/* update the index with the given tree's info
* for all args, expanding wildcards, and exit

Просмотреть файл

@ -533,18 +533,18 @@ static int grep_cache(struct grep_opt *opt, const struct pathspec *pathspec, int
static int grep_tree(struct grep_opt *opt, const struct pathspec *pathspec,
struct tree_desc *tree, struct strbuf *base, int tn_len)
{
int hit = 0, matched = 0;
int hit = 0, match = 0;
struct name_entry entry;
int old_baselen = base->len;
while (tree_entry(tree, &entry)) {
int te_len = tree_entry_len(entry.path, entry.sha1);
if (matched != 2) {
matched = tree_entry_interesting(&entry, base, tn_len, pathspec);
if (matched == -1)
break; /* no more matches */
if (!matched)
if (match != 2) {
match = tree_entry_interesting(&entry, base, tn_len, pathspec);
if (match < 0)
break;
if (match == 0)
continue;
}

Просмотреть файл

@ -414,6 +414,7 @@ int cmd_show(int argc, const char **argv, const char *prefix)
struct rev_info rev;
struct object_array_entry *objects;
struct setup_revision_opt opt;
struct pathspec match_all;
int i, count, ret = 0;
git_config(git_log_config, NULL);
@ -421,6 +422,7 @@ int cmd_show(int argc, const char **argv, const char *prefix)
if (diff_use_color_default == -1)
diff_use_color_default = git_use_color_default;
init_pathspec(&match_all, NULL);
init_revisions(&rev, prefix);
rev.diff = 1;
rev.always_show_header = 1;
@ -467,7 +469,7 @@ 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, NULL,
read_tree_recursive((struct tree *)o, "", 0, 0, &match_all,
show_tree_object, NULL);
rev.shown_one = 1;
break;

Просмотреть файл

@ -338,7 +338,7 @@ void overlay_tree_on_cache(const char *tree_name, const char *prefix)
{
struct tree *tree;
unsigned char sha1[20];
const char **match;
struct pathspec pathspec;
struct cache_entry *last_stage0 = NULL;
int i;
@ -360,10 +360,11 @@ void overlay_tree_on_cache(const char *tree_name, const char *prefix)
static const char *(matchbuf[2]);
matchbuf[0] = prefix;
matchbuf[1] = NULL;
match = matchbuf;
init_pathspec(&pathspec, matchbuf);
pathspec.items[0].use_wildcard = 0;
} else
match = NULL;
if (read_tree(tree, 1, match))
init_pathspec(&pathspec, NULL);
if (read_tree(tree, 1, &pathspec))
die("unable to read tree entries %s", tree_name);
for (i = 0; i < active_nr; i++) {

Просмотреть файл

@ -19,7 +19,7 @@ static int line_termination = '\n';
#define LS_SHOW_SIZE 16
static int abbrev;
static int ls_options;
static const char **pathspec;
static struct pathspec pathspec;
static int chomp_prefix;
static const char *ls_tree_prefix;
@ -35,7 +35,7 @@ static int show_recursive(const char *base, int baselen, const char *pathname)
if (ls_options & LS_RECURSIVE)
return 1;
s = pathspec;
s = pathspec.raw;
if (!s)
return 0;
@ -120,7 +120,7 @@ int cmd_ls_tree(int argc, const char **argv, const char *prefix)
{
unsigned char sha1[20];
struct tree *tree;
int full_tree = 0;
int i, full_tree = 0;
const struct option ls_tree_options[] = {
OPT_BIT('d', NULL, &ls_options, "only show trees",
LS_TREE_ONLY),
@ -166,11 +166,14 @@ int cmd_ls_tree(int argc, const char **argv, const char *prefix)
if (get_sha1(argv[0], sha1))
die("Not a valid object name %s", argv[0]);
pathspec = get_pathspec(prefix, argv + 1);
init_pathspec(&pathspec, get_pathspec(prefix, argv + 1));
for (i = 0; i < pathspec.nr; i++)
pathspec.items[i].use_wildcard = 0;
pathspec.has_wildcard = 0;
tree = parse_tree_indirect(sha1);
if (!tree)
die("not a tree object");
read_tree_recursive(tree, "", 0, 0, pathspec, show_tree, NULL);
read_tree_recursive(tree, "", 0, 0, &pathspec, show_tree, NULL);
return 0;
}

Просмотреть файл

@ -511,7 +511,7 @@ struct pathspec {
struct pathspec_item {
const char *match;
int len;
unsigned int has_wildcard:1;
unsigned int use_wildcard:1;
} *items;
};

6
dir.c
Просмотреть файл

@ -230,7 +230,7 @@ static int match_pathspec_item(const struct pathspec_item *item, int prefix,
return MATCHED_RECURSIVELY;
}
if (item->has_wildcard && !fnmatch(match, name, 0))
if (item->use_wildcard && !fnmatch(match, name, 0))
return MATCHED_FNMATCH;
return 0;
@ -1274,8 +1274,8 @@ int init_pathspec(struct pathspec *pathspec, const char **paths)
item->match = path;
item->len = strlen(path);
item->has_wildcard = !no_wildcard(path);
if (item->has_wildcard)
item->use_wildcard = !no_wildcard(path);
if (item->use_wildcard)
pathspec->has_wildcard = 1;
}

Просмотреть файл

@ -68,7 +68,7 @@ static void process_tree(struct rev_info *revs,
struct tree_desc desc;
struct name_entry entry;
struct name_path me;
int all_interesting = (revs->diffopt.pathspec.nr == 0);
int match = revs->diffopt.pathspec.nr == 0 ? 2 : 0;
int baselen = base->len;
if (!revs->tree_objects)
@ -85,7 +85,7 @@ static void process_tree(struct rev_info *revs,
me.elem = name;
me.elem_len = strlen(name);
if (!all_interesting) {
if (!match) {
strbuf_addstr(base, name);
if (base->len)
strbuf_addch(base, '/');
@ -94,17 +94,13 @@ static void process_tree(struct rev_info *revs,
init_tree_desc(&desc, tree->buffer, tree->size);
while (tree_entry(&desc, &entry)) {
if (!all_interesting) {
int showit = tree_entry_interesting(&entry,
base, 0,
&revs->diffopt.pathspec);
if (showit < 0)
if (match != 2) {
match = tree_entry_interesting(&entry, base, 0,
&revs->diffopt.pathspec);
if (match < 0)
break;
else if (!showit)
if (match == 0)
continue;
else if (showit == 2)
all_interesting = 1;
}
if (S_ISDIR(entry.mode))

Просмотреть файл

@ -273,7 +273,9 @@ static int save_files_dirs(const unsigned char *sha1,
static int get_files_dirs(struct merge_options *o, struct tree *tree)
{
int n;
if (read_tree_recursive(tree, "", 0, 0, NULL, save_files_dirs, o))
struct pathspec match_all;
init_pathspec(&match_all, NULL);
if (read_tree_recursive(tree, "", 0, 0, &match_all, save_files_dirs, o))
return 0;
n = o->current_file_set.nr + o->current_directory_set.nr;
return n;

22
t/t3102-ls-tree-wildcards.sh Executable file
Просмотреть файл

@ -0,0 +1,22 @@
#!/bin/sh
test_description='ls-tree with(out) wildcards'
. ./test-lib.sh
test_expect_success 'setup' '
mkdir a aa "a*" &&
touch a/one aa/two "a*/three" &&
git add a/one aa/two "a*/three" &&
git commit -m test
'
test_expect_success 'ls-tree a* matches literally' '
cat >expected <<EOF &&
100644 blob e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 a*/three
EOF
git ls-tree -r HEAD "a*" >actual &&
test_cmp expected actual
'
test_done

Просмотреть файл

@ -64,23 +64,17 @@ static int compare_tree_entry(struct tree_desc *t1, struct tree_desc *t2,
static void show_tree(struct diff_options *opt, const char *prefix,
struct tree_desc *desc, struct strbuf *base)
{
int all_interesting = 0;
while (desc->size) {
int show;
if (all_interesting)
show = 1;
else {
show = tree_entry_interesting(&desc->entry, base, 0,
&opt->pathspec);
if (show == 2)
all_interesting = 1;
int match = 0;
for (; desc->size; update_tree_entry(desc)) {
if (match != 2) {
match = tree_entry_interesting(&desc->entry, base, 0,
&opt->pathspec);
if (match < 0)
break;
if (match == 0)
continue;
}
if (show < 0)
break;
if (show)
show_entry(opt, prefix, desc, base);
update_tree_entry(desc);
show_entry(opt, prefix, desc, base);
}
}
@ -120,20 +114,16 @@ static void show_entry(struct diff_options *opt, const char *prefix,
}
static void skip_uninteresting(struct tree_desc *t, struct strbuf *base,
struct diff_options *opt, int *all_interesting)
struct diff_options *opt, int *match)
{
while (t->size) {
int show = tree_entry_interesting(&t->entry, base, 0, &opt->pathspec);
if (show == 2)
*all_interesting = 1;
if (!show) {
update_tree_entry(t);
continue;
*match = tree_entry_interesting(&t->entry, base, 0, &opt->pathspec);
if (*match) {
if (*match < 0)
t->size = 0;
break;
}
/* Skip it all? */
if (show < 0)
t->size = 0;
return;
update_tree_entry(t);
}
}
@ -142,8 +132,7 @@ int diff_tree(struct tree_desc *t1, struct tree_desc *t2,
{
struct strbuf base;
int baselen = strlen(base_str);
int all_t1_interesting = 0;
int all_t2_interesting = 0;
int t1_match = 0, t2_match = 0;
/* Enable recursion indefinitely */
opt->pathspec.recursive = DIFF_OPT_TST(opt, RECURSIVE);
@ -157,10 +146,8 @@ int diff_tree(struct tree_desc *t1, struct tree_desc *t2,
DIFF_OPT_TST(opt, HAS_CHANGES))
break;
if (opt->pathspec.nr) {
if (!all_t1_interesting)
skip_uninteresting(t1, &base, opt, &all_t1_interesting);
if (!all_t2_interesting)
skip_uninteresting(t2, &base, opt, &all_t2_interesting);
skip_uninteresting(t1, &base, opt, &t1_match);
skip_uninteresting(t2, &base, opt, &t2_match);
}
if (!t1->size) {
if (!t2->size)

Просмотреть файл

@ -598,7 +598,7 @@ int tree_entry_interesting(const struct name_entry *entry,
&never_interesting))
return 1;
if (ps->items[i].has_wildcard) {
if (ps->items[i].use_wildcard) {
if (!fnmatch(match + baselen, entry->path, 0))
return 1;
@ -614,7 +614,7 @@ int tree_entry_interesting(const struct name_entry *entry,
}
match_wildcards:
if (!ps->items[i].has_wildcard)
if (!ps->items[i].use_wildcard)
continue;
/*

145
tree.c
Просмотреть файл

@ -45,62 +45,14 @@ static int read_one_entry_quick(const unsigned char *sha1, const char *base, int
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;
/* pathspecs match only at the directory boundaries */
if (!matchlen ||
baselen == matchlen ||
base[matchlen] == '/' ||
match[matchlen - 1] == '/')
return 1;
continue;
}
/* 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, void *context)
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, retval = 0, oldlen = base->len;
if (parse_tree(tree))
return -1;
@ -108,10 +60,16 @@ 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 != 2) {
retval = tree_entry_interesting(&entry, base, 0, pathspec);
if (retval < 0)
break;
if (retval == 0)
continue;
}
switch (fn(entry.sha1, base, baselen, entry.path, entry.mode, stage, context)) {
switch (fn(entry.sha1, base->buf, base->len,
entry.path, entry.mode, stage, context)) {
case 0:
continue;
case READ_TREE_RECURSIVE:
@ -119,56 +77,55 @@ int read_tree_recursive(struct tree *tree,
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, context);
free(newbase);
if (retval)
return -1;
continue;
} else if (S_ISGITLINK(entry.mode)) {
int retval;
struct strbuf path;
unsigned int entrylen;
if (S_ISDIR(entry.mode))
hashcpy(sha1, entry.sha1);
else if (S_ISGITLINK(entry.mode)) {
struct commit *commit;
entrylen = tree_entry_len(entry.path, entry.sha1);
strbuf_init(&path, baselen + entrylen + 1);
strbuf_add(&path, base, baselen);
strbuf_add(&path, entry.path, entrylen);
strbuf_addch(&path, '/');
commit = lookup_commit(entry.sha1);
if (!commit)
die("Commit %s in submodule path %s not found",
sha1_to_hex(entry.sha1), path.buf);
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",
sha1_to_hex(entry.sha1), path.buf);
die("Invalid commit %s in submodule path %s%s",
sha1_to_hex(entry.sha1),
base->buf, entry.path);
retval = read_tree_recursive(commit->tree,
path.buf, path.len,
stage, match, fn, context);
strbuf_release(&path);
if (retval)
return -1;
continue;
hashcpy(sha1, commit->tree->object.sha1);
}
else
continue;
len = tree_entry_len(entry.path, entry.sha1);
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;
@ -179,7 +136,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;

4
tree.h
Просмотреть файл

@ -25,9 +25,9 @@ typedef int (*read_tree_fn_t)(const unsigned char *, const char *, int, const ch
extern int read_tree_recursive(struct tree *tree,
const char *base, int baselen,
int stage, const char **match,
int stage, struct pathspec *pathspec,
read_tree_fn_t fn, void *context);
extern int read_tree(struct tree *tree, int stage, const char **paths);
extern int read_tree(struct tree *tree, int stage, struct pathspec *pathspec);
#endif /* TREE_H */