@matheusbsbs / matheus-bagliano / commits / ffd31f661d
Fork 0

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;