@matheusbsbs / matheus-bagliano / commits / 40d934df72
Fork 0

Make 'traverse_tree()' use linked structure rather than 'const char *base'

This makes the calling convention a bit less obvious, but a lot more flexible. Instead of allocating and extending a new 'base' string, we just link the top-most name into a linked list of the 'info' structure when traversing a subdirectory, and we can generate the basename by following the list. Perhaps even more importantly, the linked list of info structures also gives us a place to naturally save off other information than just the directory name. Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Linus Torvalds committed Mar 5, 2008 at 18:59 UTC 40d934df72eaf244c826d5c26da0896ce7185cb6
3 files changed +78 -28
merge-tree.c
+27 -24
@@ -168,7 +168,13 @@ static struct merge_list *create_entry(unsigned stage, unsigned mode, const unsi
168 return res;
169 }
170
171 -static void resolve(const char *base, struct name_entry *branch1, struct name_entry *result)
171 +static char *traverse_path(const struct traverse_info *info, const struct name_entry *n)
172 +{
173 + char *path = xmalloc(traverse_path_len(info, n) + 1);
174 + return make_traverse_path(path, info, n);
175 +}
176 +
177 +static void resolve(const struct traverse_info *info, struct name_entry *branch1, struct name_entry *result)
178 {
179 struct merge_list *orig, *final;
180 const char *path;
@@ -177,7 +183,7 @@ static void resolve(const char *base, struct name_entry *branch1, struct name_en
183 if (!branch1)
184 return;
185
180 - path = xstrdup(mkpath("%s%s", base, result->path));
186 + path = traverse_path(info, result);
187 orig = create_entry(2, branch1->mode, branch1->sha1, path);
188 final = create_entry(0, result->mode, result->sha1, path);
189
@@ -186,9 +192,8 @@ static void resolve(const char *base, struct name_entry *branch1, struct name_en
192 add_merge_entry(final);
193 }
194
189 -static int unresolved_directory(const char *base, struct name_entry n[3])
195 +static int unresolved_directory(const struct traverse_info *info, struct name_entry n[3])
196 {
191 - int baselen, pathlen;
197 char *newbase;
198 struct name_entry *p;
199 struct tree_desc t[3];
@@ -204,13 +209,7 @@ static int unresolved_directory(const char *base, struct name_entry n[3])
209 }
210 if (!S_ISDIR(p->mode))
211 return 0;
207 - baselen = strlen(base);
208 - pathlen = tree_entry_len(p->path, p->sha1);
209 - newbase = xmalloc(baselen + pathlen + 2);
210 - memcpy(newbase, base, baselen);
211 - memcpy(newbase + baselen, p->path, pathlen);
212 - memcpy(newbase + baselen + pathlen, "/", 2);
213 -
212 + newbase = traverse_path(info, p);
213 buf0 = fill_tree_descriptor(t+0, n[0].sha1);
214 buf1 = fill_tree_descriptor(t+1, n[1].sha1);
215 buf2 = fill_tree_descriptor(t+2, n[2].sha1);
@@ -224,7 +223,7 @@ static int unresolved_directory(const char *base, struct name_entry n[3])
223 }
224
225
227 -static struct merge_list *link_entry(unsigned stage, const char *base, struct name_entry *n, struct merge_list *entry)
226 +static struct merge_list *link_entry(unsigned stage, const struct traverse_info *info, struct name_entry *n, struct merge_list *entry)
227 {
228 const char *path;
229 struct merge_list *link;
@@ -234,17 +233,17 @@ static struct merge_list *link_entry(unsigned stage, const char *base, struct na
233 if (entry)
234 path = entry->path;
235 else
237 - path = xstrdup(mkpath("%s%s", base, n->path));
236 + path = traverse_path(info, n);
237 link = create_entry(stage, n->mode, n->sha1, path);
238 link->link = entry;
239 return link;
240 }
241
243 -static void unresolved(const char *base, struct name_entry n[3])
242 +static void unresolved(const struct traverse_info *info, struct name_entry n[3])
243 {
244 struct merge_list *entry = NULL;
245
247 - if (unresolved_directory(base, n))
246 + if (unresolved_directory(info, n))
247 return;
248
249 /*
@@ -252,9 +251,9 @@ static void unresolved(const char *base, struct name_entry n[3])
251 * list has the stages in order - link_entry adds new
252 * links at the front.
253 */
255 - entry = link_entry(3, base, n + 2, entry);
256 - entry = link_entry(2, base, n + 1, entry);
257 - entry = link_entry(1, base, n + 0, entry);
254 + entry = link_entry(3, info, n + 2, entry);
255 + entry = link_entry(2, info, n + 1, entry);
256 + entry = link_entry(1, info, n + 0, entry);
257
258 add_merge_entry(entry);
259 }
@@ -288,36 +287,40 @@ static void unresolved(const char *base, struct name_entry n[3])
287 * The successful merge rules are the same as for the three-way merge
288 * in git-read-tree.
289 */
291 -static void threeway_callback(int n, unsigned long mask, struct name_entry *entry, const char *base)
290 +static void threeway_callback(int n, unsigned long mask, struct name_entry *entry, struct traverse_info *info)
291 {
292 /* Same in both? */
293 if (same_entry(entry+1, entry+2)) {
294 if (entry[0].sha1) {
296 - resolve(base, NULL, entry+1);
295 + resolve(info, NULL, entry+1);
296 return;
297 }
298 }
299
300 if (same_entry(entry+0, entry+1)) {
301 if (entry[2].sha1 && !S_ISDIR(entry[2].mode)) {
303 - resolve(base, entry+1, entry+2);
302 + resolve(info, entry+1, entry+2);
303 return;
304 }
305 }
306
307 if (same_entry(entry+0, entry+2)) {
308 if (entry[1].sha1 && !S_ISDIR(entry[1].mode)) {
310 - resolve(base, NULL, entry+1);
309 + resolve(info, NULL, entry+1);
310 return;
311 }
312 }
313
315 - unresolved(base, entry);
314 + unresolved(info, entry);
315 }
316
317 static void merge_trees(struct tree_desc t[3], const char *base)
318 {
320 - traverse_trees(3, t, base, threeway_callback);
319 + struct traverse_info info;
320 +
321 + setup_traverse_info(&info, base);
322 + info.fn = threeway_callback;
323 + traverse_trees(3, t, &info);
324 }
325
326 static void *get_tree_descriptor(struct tree_desc *desc, const char *rev)
tree-walk.c
+33 -2
@@ -104,7 +104,38 @@ int tree_entry(struct tree_desc *desc, struct name_entry *entry)
104 return 1;
105 }
106
107 -void traverse_trees(int n, struct tree_desc *t, const char *base, traverse_callback_t callback)
107 +void setup_traverse_info(struct traverse_info *info, const char *base)
108 +{
109 + int pathlen = strlen(base);
110 +
111 + memset(info, 0, sizeof(*info));
112 + if (pathlen && base[pathlen-1] == '/')
113 + pathlen--;
114 + info->pathlen = pathlen ? pathlen + 1 : 0;
115 + info->name.path = base;
116 + info->name.sha1 = (void *)(base + pathlen + 1);
117 +}
118 +
119 +char *make_traverse_path(char *path, const struct traverse_info *info, const struct name_entry *n)
120 +{
121 + int len = tree_entry_len(n->path, n->sha1);
122 + int pathlen = info->pathlen;
123 +
124 + path[pathlen + len] = 0;
125 + for (;;) {
126 + memcpy(path + pathlen, n->path, len);
127 + if (!pathlen)
128 + break;
129 + path[--pathlen] = '/';
130 + n = &info->name;
131 + len = tree_entry_len(n->path, n->sha1);
132 + info = info->prev;
133 + pathlen -= len;
134 + }
135 + return path;
136 +}
137 +
138 +void traverse_trees(int n, struct tree_desc *t, struct traverse_info *info)
139 {
140 struct name_entry *entry = xmalloc(n*sizeof(*entry));
141
@@ -150,7 +181,7 @@ void traverse_trees(int n, struct tree_desc *t, const char *base, traverse_callb
181 }
182 entry_clear(entry + i);
183 }
153 - callback(n, mask, entry, base);
184 + info->fn(n, mask, entry, info);
185 }
186 free(entry);
187 }
tree-walk.h
+18 -2
@@ -33,10 +33,26 @@ int tree_entry(struct tree_desc *, struct name_entry *);
33
34 void *fill_tree_descriptor(struct tree_desc *desc, const unsigned char *sha1);
35
36 -typedef void (*traverse_callback_t)(int n, unsigned long mask, struct name_entry *entry, const char *base);
36 +struct traverse_info;
37 +typedef void (*traverse_callback_t)(int n, unsigned long mask, struct name_entry *entry, struct traverse_info *);
38 +void traverse_trees(int n, struct tree_desc *t, struct traverse_info *info);
39
38 -void traverse_trees(int n, struct tree_desc *t, const char *base, traverse_callback_t callback);
40 +struct traverse_info {
41 + struct traverse_info *prev;
42 + struct name_entry name;
43 + int pathlen;
44 +
45 + traverse_callback_t fn;
46 + void *data;
47 +};
48
49 int get_tree_entry(const unsigned char *, const char *, unsigned char *, unsigned *);
50 +extern char *make_traverse_path(char *path, const struct traverse_info *info, const struct name_entry *n);
51 +extern void setup_traverse_info(struct traverse_info *info, const char *base);
52 +
53 +static inline int traverse_path_len(const struct traverse_info *info, const struct name_entry *n)
54 +{
55 + return info->pathlen + tree_entry_len(n->path, n->sha1);
56 +}
57
58 #endif