Reimplement read_tree_recursive() using tree_entry_interesting()
read_tree_recursive() uses a very similar function, match_tree_entry, to tree_entry_interesting() to do its path matching. This patch kills match_tree_entry() in favor of tree_entry_interesting(). match_tree_entry(), like older version of tree_entry_interesting(), does not support wildcard matching. New read_tree_recursive() retains this behavior by forcing all pathspecs literal. Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Nguyễn Thái Ngọc Duy committed
Mar 25, 2011 at 16:34 UTC
ffd31f661d5c5dddc091750ca86cfaa5d9d04b38
1 file changed
+57
-95
tree.c
+57
-95
@@ -45,62 +45,14 @@ static int read_one_entry_quick(const unsigned char *sha1, const char *base, int
45
ADD_CACHE_JUST_APPEND);
46
}
47
48
-static int match_tree_entry(const char *base, int baselen, const char *path, unsigned int mode, const char **paths)
49
-{
50
- const char *match;
51
- int pathlen;
52
-
53
- if (!paths)
54
- return 1;
55
- pathlen = strlen(path);
56
- while ((match = *paths++) != NULL) {
57
- int matchlen = strlen(match);
58
-
59
- if (baselen >= matchlen) {
60
- /* If it doesn't match, move along... */
61
- if (strncmp(base, match, matchlen))
62
- continue;
63
- /* pathspecs match only at the directory boundaries */
64
- if (!matchlen ||
65
- baselen == matchlen ||
66
- base[matchlen] == '/' ||
67
- match[matchlen - 1] == '/')
68
- return 1;
69
- continue;
70
- }
71
-
72
- /* Does the base match? */
73
- if (strncmp(base, match, baselen))
74
- continue;
75
-
76
- match += baselen;
77
- matchlen -= baselen;
78
-
79
- if (pathlen > matchlen)
80
- continue;
81
-
82
- if (matchlen > pathlen) {
83
- if (match[pathlen] != '/')
84
- continue;
85
- if (!S_ISDIR(mode))
86
- continue;
87
- }
88
-
89
- if (strncmp(path, match, pathlen))
90
- continue;
91
-
92
- return 1;
93
- }
94
- return 0;
95
-}
96
-
97
-int read_tree_recursive(struct tree *tree,
98
- const char *base, int baselen,
99
- int stage, const char **match,
100
- read_tree_fn_t fn, void *context)
48
+static int read_tree_1(struct tree *tree, struct strbuf *base,
49
+ int stage, struct pathspec *pathspec,
50
+ read_tree_fn_t fn, void *context)
51
{
52
struct tree_desc desc;
53
struct name_entry entry;
54
+ unsigned char sha1[20];
55
+ int len, retval = 0, oldlen = base->len;
56
57
if (parse_tree(tree))
58
return -1;
@@ -108,10 +60,16 @@ int read_tree_recursive(struct tree *tree,
60
init_tree_desc(&desc, tree->buffer, tree->size);
61
62
while (tree_entry(&desc, &entry)) {
111
- if (!match_tree_entry(base, baselen, entry.path, entry.mode, match))
112
- continue;
63
+ if (retval != 2) {
64
+ retval = tree_entry_interesting(&entry, base, 0, pathspec);
65
+ if (retval < 0)
66
+ break;
67
+ if (retval == 0)
68
+ continue;
69
+ }
70
114
- switch (fn(entry.sha1, base, baselen, entry.path, entry.mode, stage, context)) {
71
+ switch (fn(entry.sha1, base->buf, base->len,
72
+ entry.path, entry.mode, stage, context)) {
73
case 0:
74
continue;
75
case READ_TREE_RECURSIVE:
@@ -119,56 +77,60 @@ int read_tree_recursive(struct tree *tree,
77
default:
78
return -1;
79
}
122
- if (S_ISDIR(entry.mode)) {
123
- int retval;
124
- char *newbase;
125
- unsigned int pathlen = tree_entry_len(entry.path, entry.sha1);
126
-
127
- newbase = xmalloc(baselen + 1 + pathlen);
128
- memcpy(newbase, base, baselen);
129
- memcpy(newbase + baselen, entry.path, pathlen);
130
- newbase[baselen + pathlen] = '/';
131
- retval = read_tree_recursive(lookup_tree(entry.sha1),
132
- newbase,
133
- baselen + pathlen + 1,
134
- stage, match, fn, context);
135
- free(newbase);
136
- if (retval)
137
- return -1;
138
- continue;
139
- } else if (S_ISGITLINK(entry.mode)) {
140
- int retval;
141
- struct strbuf path;
142
- unsigned int entrylen;
143
- struct commit *commit;
80
145
- entrylen = tree_entry_len(entry.path, entry.sha1);
146
- strbuf_init(&path, baselen + entrylen + 1);
147
- strbuf_add(&path, base, baselen);
148
- strbuf_add(&path, entry.path, entrylen);
149
- strbuf_addch(&path, '/');
81
+ if (S_ISDIR(entry.mode))
82
+ hashcpy(sha1, entry.sha1);
83
+ else if (S_ISGITLINK(entry.mode)) {
84
+ struct commit *commit;
85
86
commit = lookup_commit(entry.sha1);
87
if (!commit)
153
- die("Commit %s in submodule path %s not found",
154
- sha1_to_hex(entry.sha1), path.buf);
88
+ die("Commit %s in submodule path %s%s not found",
89
+ sha1_to_hex(entry.sha1),
90
+ base->buf, entry.path);
91
92
if (parse_commit(commit))
157
- die("Invalid commit %s in submodule path %s",
158
- sha1_to_hex(entry.sha1), path.buf);
159
-
160
- retval = read_tree_recursive(commit->tree,
161
- path.buf, path.len,
162
- stage, match, fn, context);
163
- strbuf_release(&path);
164
- if (retval)
165
- return -1;
166
- continue;
93
+ die("Invalid commit %s in submodule path %s%s",
94
+ sha1_to_hex(entry.sha1),
95
+ base->buf, entry.path);
96
+
97
+ hashcpy(sha1, commit->tree->object.sha1);
98
}
99
+ else
100
+ continue;
101
+
102
+ len = tree_entry_len(entry.path, entry.sha1);
103
+ strbuf_add(base, entry.path, len);
104
+ strbuf_addch(base, '/');
105
+ retval = read_tree_1(lookup_tree(sha1),
106
+ base, stage, pathspec,
107
+ fn, context);
108
+ strbuf_setlen(base, oldlen);
109
+ if (retval)
110
+ return -1;
111
}
112
return 0;
113
}
114
115
+int read_tree_recursive(struct tree *tree,
116
+ const char *base, int baselen,
117
+ int stage, const char **match,
118
+ read_tree_fn_t fn, void *context)
119
+{
120
+ struct strbuf sb = STRBUF_INIT;
121
+ struct pathspec pathspec;
122
+ int i, ret;
123
+
124
+ init_pathspec(&pathspec, match);
125
+ for (i = 0; i < pathspec.nr; i++)
126
+ pathspec.items[i].has_wildcard = 0;
127
+ strbuf_add(&sb, base, baselen);
128
+ ret = read_tree_1(tree, &sb, stage, &pathspec, fn, context);
129
+ strbuf_release(&sb);
130
+ free_pathspec(&pathspec);
131
+ return ret;
132
+}
133
+
134
static int cmp_cache_name_compare(const void *a_, const void *b_)
135
{
136
const struct cache_entry *ce1, *ce2;