tree-walk: add a strbuf wrapper for make_traverse_path()
authorJeff King <peff@peff.net>
Wed, 31 Jul 2019 04:38:23 +0000 (00:38 -0400)
committerJunio C Hamano <gitster@pobox.com>
Thu, 1 Aug 2019 20:06:52 +0000 (13:06 -0700)
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>
Documentation/technical/api-tree-walking.txt
builtin/merge-tree.c
tree-walk.c
tree-walk.h
unpack-trees.c
index 59d78e03624e77c3f63c5ef7bc899309c503280d..7962e3285499aa10309b5c88ffdcc434d679a709 100644 (file)
@@ -138,6 +138,10 @@ same in the next callback invocation.
        This utilizes the memory structure of a tree entry to avoid the
        overhead of using a generic strlen().
 
+`strbuf_make_traverse_path`::
+
+       Convenience wrapper to `make_traverse_path` into a strbuf.
+
 Authors
 -------
 
index 0629c87b19d59d7003f50fa9524953515b409909..87d949cf882d7285cd9fec13bc22fbe8b9138c1f 100644 (file)
@@ -180,8 +180,9 @@ static struct merge_list *create_entry(unsigned stage, unsigned mode, const stru
 
 static char *traverse_path(const struct traverse_info *info, const struct name_entry *n)
 {
-       char *path = xmallocz(traverse_path_len(info, tree_entry_len(n)));
-       return make_traverse_path(path, info, n->path, n->pathlen);
+       struct strbuf buf = STRBUF_INIT;
+       strbuf_make_traverse_path(&buf, info, n->path, n->pathlen);
+       return strbuf_detach(&buf, NULL);
 }
 
 static void resolve(const struct traverse_info *info, struct name_entry *ours, struct name_entry *result)
index 70f9eb5f1b449cfa59a871caa22010a7d9eae0a3..c2952f3793fd2f028b60ceb8764b8298189f054b 100644 (file)
@@ -200,6 +200,17 @@ char *make_traverse_path(char *path, const struct traverse_info *info,
        return path;
 }
 
+void strbuf_make_traverse_path(struct strbuf *out,
+                              const struct traverse_info *info,
+                              const char *name, size_t namelen)
+{
+       size_t len = traverse_path_len(info, namelen);
+
+       strbuf_grow(out, len);
+       make_traverse_path(out->buf + out->len, info, name, namelen);
+       strbuf_setlen(out, out->len + len);
+}
+
 struct tree_desc_skip {
        struct tree_desc_skip *prev;
        const void *ptr;
@@ -396,12 +407,10 @@ int traverse_trees(struct index_state *istate,
                tx[i].d = t[i];
 
        if (info->prev) {
-               strbuf_grow(&base, info->pathlen);
-               make_traverse_path(base.buf, info->prev, info->name,
-                                  info->namelen);
-               base.buf[info->pathlen-1] = '/';
-               strbuf_setlen(&base, info->pathlen);
-               traverse_path = xstrndup(base.buf, info->pathlen);
+               strbuf_make_traverse_path(&base, info->prev,
+                                         info->name, info->namelen);
+               strbuf_addch(&base, '/');
+               traverse_path = xstrndup(base.buf, base.len);
        } else {
                traverse_path = xstrndup(info->name, info->pathlen);
        }
index a25c751c1eae6fbd8c41c399571f9d350e8b1c7d..994c14a49964b3b3a27a73baeea892b4e168e98b 100644 (file)
@@ -72,6 +72,9 @@ struct traverse_info {
 int get_tree_entry(const struct object_id *, const char *, struct object_id *, unsigned short *);
 char *make_traverse_path(char *path, const struct traverse_info *info,
                         const char *name, size_t namelen);
+void strbuf_make_traverse_path(struct strbuf *out,
+                              const struct traverse_info *info,
+                              const char *name, size_t namelen);
 void setup_traverse_info(struct traverse_info *info, const char *base);
 
 static inline size_t traverse_path_len(const struct traverse_info *info,
index 492eff666a7979568202247c4306578223fe7eab..c3059c2440cec5808057ba99f2eb202ce3d5b27a 100644 (file)
@@ -686,21 +686,19 @@ static int index_pos_by_traverse_info(struct name_entry *names,
                                      struct traverse_info *info)
 {
        struct unpack_trees_options *o = info->data;
-       size_t len = traverse_path_len(info, tree_entry_len(names));
-       char *name = xmalloc(len + 1 /* slash */ + 1 /* NUL */);
+       struct strbuf name = STRBUF_INIT;
        int pos;
 
-       make_traverse_path(name, info, names->path, names->pathlen);
-       name[len++] = '/';
-       name[len] = '\0';
-       pos = index_name_pos(o->src_index, name, len);
+       strbuf_make_traverse_path(&name, info, names->path, names->pathlen);
+       strbuf_addch(&name, '/');
+       pos = index_name_pos(o->src_index, name.buf, name.len);
        if (pos >= 0)
                BUG("This is a directory and should not exist in index");
        pos = -pos - 1;
-       if (!starts_with(o->src_index->cache[pos]->name, name) ||
-           (pos > 0 && starts_with(o->src_index->cache[pos-1]->name, name)))
+       if (!starts_with(o->src_index->cache[pos]->name, name.buf) ||
+           (pos > 0 && starts_with(o->src_index->cache[pos-1]->name, name.buf)))
                BUG("pos must point at the first entry in this directory");
-       free(name);
+       strbuf_release(&name);
        return pos;
 }