tree-walk: add a strbuf wrapper for make_traverse_path()
All but one of the callers of make_traverse_path() allocate a new heap buffer to store the path. Let's give them an easy way to write to a strbuf, which saves them from computing the length themselves (which is especially tricky when they want to add to the path). It will also make it easier for us to change the make_traverse_path() interface in a future patch to improve its bounds-checking. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Jeff King committed
Jul 31, 2019 at 00:38 UTC
c43ab062598d0299ea6e0d115a6018189a7793bf
5 files changed
+32
-17
Documentation/technical/api-tree-walking.txt
+4
@@ -138,6 +138,10 @@ same in the next callback invocation.
138
This utilizes the memory structure of a tree entry to avoid the
139
overhead of using a generic strlen().
140
141
+`strbuf_make_traverse_path`::
142
+
143
+ Convenience wrapper to `make_traverse_path` into a strbuf.
144
+
145
Authors
146
-------
147
builtin/merge-tree.c
+3
-2
@@ -180,8 +180,9 @@ static struct merge_list *create_entry(unsigned stage, unsigned mode, const stru
180
181
static char *traverse_path(const struct traverse_info *info, const struct name_entry *n)
182
{
183
- char *path = xmallocz(traverse_path_len(info, tree_entry_len(n)));
184
- return make_traverse_path(path, info, n->path, n->pathlen);
183
+ struct strbuf buf = STRBUF_INIT;
184
+ strbuf_make_traverse_path(&buf, info, n->path, n->pathlen);
185
+ return strbuf_detach(&buf, NULL);
186
}
187
188
static void resolve(const struct traverse_info *info, struct name_entry *ours, struct name_entry *result)
tree-walk.c
+15
-6
@@ -200,6 +200,17 @@ char *make_traverse_path(char *path, const struct traverse_info *info,
200
return path;
201
}
202
203
+void strbuf_make_traverse_path(struct strbuf *out,
204
+ const struct traverse_info *info,
205
+ const char *name, size_t namelen)
206
+{
207
+ size_t len = traverse_path_len(info, namelen);
208
+
209
+ strbuf_grow(out, len);
210
+ make_traverse_path(out->buf + out->len, info, name, namelen);
211
+ strbuf_setlen(out, out->len + len);
212
+}
213
+
214
struct tree_desc_skip {
215
struct tree_desc_skip *prev;
216
const void *ptr;
@@ -396,12 +407,10 @@ int traverse_trees(struct index_state *istate,
407
tx[i].d = t[i];
408
409
if (info->prev) {
399
- strbuf_grow(&base, info->pathlen);
400
- make_traverse_path(base.buf, info->prev, info->name,
401
- info->namelen);
402
- base.buf[info->pathlen-1] = '/';
403
- strbuf_setlen(&base, info->pathlen);
404
- traverse_path = xstrndup(base.buf, info->pathlen);
410
+ strbuf_make_traverse_path(&base, info->prev,
411
+ info->name, info->namelen);
412
+ strbuf_addch(&base, '/');
413
+ traverse_path = xstrndup(base.buf, base.len);
414
} else {
415
traverse_path = xstrndup(info->name, info->pathlen);
416
}
tree-walk.h
+3
@@ -72,6 +72,9 @@ struct traverse_info {
72
int get_tree_entry(const struct object_id *, const char *, struct object_id *, unsigned short *);
73
char *make_traverse_path(char *path, const struct traverse_info *info,
74
const char *name, size_t namelen);
75
+void strbuf_make_traverse_path(struct strbuf *out,
76
+ const struct traverse_info *info,
77
+ const char *name, size_t namelen);
78
void setup_traverse_info(struct traverse_info *info, const char *base);
79
80
static inline size_t traverse_path_len(const struct traverse_info *info,
unpack-trees.c
+7
-9
@@ -686,21 +686,19 @@ static int index_pos_by_traverse_info(struct name_entry *names,
686
struct traverse_info *info)
687
{
688
struct unpack_trees_options *o = info->data;
689
- size_t len = traverse_path_len(info, tree_entry_len(names));
690
- char *name = xmalloc(len + 1 /* slash */ + 1 /* NUL */);
689
+ struct strbuf name = STRBUF_INIT;
690
int pos;
691
693
- make_traverse_path(name, info, names->path, names->pathlen);
694
- name[len++] = '/';
695
- name[len] = '\0';
696
- pos = index_name_pos(o->src_index, name, len);
692
+ strbuf_make_traverse_path(&name, info, names->path, names->pathlen);
693
+ strbuf_addch(&name, '/');
694
+ pos = index_name_pos(o->src_index, name.buf, name.len);
695
if (pos >= 0)
696
BUG("This is a directory and should not exist in index");
697
pos = -pos - 1;
700
- if (!starts_with(o->src_index->cache[pos]->name, name) ||
701
- (pos > 0 && starts_with(o->src_index->cache[pos-1]->name, name)))
698
+ if (!starts_with(o->src_index->cache[pos]->name, name.buf) ||
699
+ (pos > 0 && starts_with(o->src_index->cache[pos-1]->name, name.buf)))
700
BUG("pos must point at the first entry in this directory");
703
- free(name);
701
+ strbuf_release(&name);
702
return pos;
703
}
704