{"thread":{"id":"62313","subject":"[PATCH 00/10] reftable: stop using `struct strbuf`","startedAt":"2024-10-11T06:54:11Z","lastAt":"2024-10-18T21:41:52Z","messageCount":63,"participants":["Patrick Steinhardt","karthik nayak","Taylor Blau","Eric Sunshine","shejialuo"],"isPatch":true,"patchVersion":1,"patchTotal":10},"messages":[{"id":"504803","messageId":"cover.1728629612.git.ps@pks.im","threadId":"62313","inReplyTo":null,"subject":"[PATCH 00/10] reftable: stop using `struct strbuf`","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-10-11T06:54:07Z","receivedAt":"2024-10-11T06:54:11Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"Hi,\n\nthis is the second patch series on my quest to make the reftable library\nbecome a standalone library again that can be used by libgit2 without\npulling in all kinds of dependencies from the Git codebase. This part\nmakes us lose the dependency on `struct strbuf`, which is done due to\nthree reasons:\n\n  - To make us independent of libgit.a.\n\n  - To ensure that we use the pluggable allocators that users can set up\n    via `reftable_set_alloc()`.\n\n  - To make it possible to handle memory allocation failures.\n\nWhile this leads to some duplication, we're only talking about ~70 lines\nof code.\n\nThanks!\n\nPatrick\n\nPatrick Steinhardt (10):\n  reftable: stop using `strbuf_addbuf()`\n  reftable: stop using `strbuf_addf()`\n  reftable/basics: provide new `reftable_buf` interface\n  reftable: convert from `strbuf` to `reftable_buf`\n  reftable/blocksource: adapt interface name\n  t/unit-tests: check for `reftable_buf` allocation errors\n  reftable/stack: adapt `format_name()` to handle allocation failures\n  reftable/record: adapt `reftable_record_key()` to handle allocation\n    failures\n  reftable/stack: adapt `stack_filename()` to handle allocation failures\n  reftable: handle trivial `reftable_buf` errors\n\n reftable/basics.c                   |  75 +++++++++-\n reftable/basics.h                   |  19 ++-\n reftable/block.c                    |  61 +++++---\n reftable/block.h                    |  14 +-\n reftable/blocksource.c              |  30 ++--\n reftable/blocksource.h              |   5 +-\n reftable/iter.c                     |   9 +-\n reftable/iter.h                     |   8 +-\n reftable/reader.c                   |  27 ++--\n reftable/record.c                   | 114 ++++++++------\n reftable/record.h                   |  21 +--\n reftable/stack.c                    | 221 ++++++++++++++++++----------\n reftable/system.h                   |   1 -\n reftable/writer.c                   | 102 ++++++++-----\n reftable/writer.h                   |   2 +-\n t/unit-tests/lib-reftable.c         |   4 +-\n t/unit-tests/lib-reftable.h         |   7 +-\n t/unit-tests/t-reftable-basics.c    |  16 +-\n t/unit-tests/t-reftable-block.c     |  53 +++----\n t/unit-tests/t-reftable-merged.c    |  32 ++--\n t/unit-tests/t-reftable-reader.c    |  12 +-\n t/unit-tests/t-reftable-readwrite.c | 134 +++++++++--------\n t/unit-tests/t-reftable-record.c    |  74 +++++-----\n t/unit-tests/t-reftable-stack.c     |  96 ++++++------\n 24 files changed, 685 insertions(+), 452 deletions(-)\n\n-- \n2.47.0.dirty\n\n"},{"id":"504804","messageId":"7408482c152bbf465ecd098059b1477fd38c251a.1728629612.git.ps@pks.im","threadId":"62313","inReplyTo":"cover.1728629612.git.ps@pks.im","subject":"[PATCH 01/10] reftable: stop using `strbuf_addbuf()`","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-10-11T06:54:10Z","receivedAt":"2024-10-11T06:54:12Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"We're about to introduce our own `reftable_buf` type to replace\n`strbuf`. Get rid of the seldomly-used `strbuf_addbuf()` function such\nthat we have to reimplement one less function.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n reftable/block.c  | 2 +-\n reftable/record.c | 6 +++---\n reftable/writer.c | 7 ++++---\n 3 files changed, 8 insertions(+), 7 deletions(-)\n\ndiff --git a/reftable/block.c b/reftable/block.c\nindex 8d41a2f99ed..cd4180eac7b 100644\n--- a/reftable/block.c\n+++ b/reftable/block.c\n@@ -60,7 +60,7 @@ static int block_writer_register_restart(struct block_writer *w, int n,\n \tw->next += n;\n \n \tstrbuf_reset(&w->last_key);\n-\tstrbuf_addbuf(&w->last_key, key);\n+\tstrbuf_add(&w->last_key, key->buf, key->len);\n \tw->entries++;\n \treturn 0;\n }\ndiff --git a/reftable/record.c b/reftable/record.c\nindex 30d563e16d3..87157f2c386 100644\n--- a/reftable/record.c\n+++ b/reftable/record.c\n@@ -1031,7 +1031,7 @@ static void reftable_index_record_key(const void *r, struct strbuf *dest)\n {\n \tconst struct reftable_index_record *rec = r;\n \tstrbuf_reset(dest);\n-\tstrbuf_addbuf(dest, &rec->last_key);\n+\tstrbuf_add(dest, rec->last_key.buf, rec->last_key.len);\n }\n \n static int reftable_index_record_copy_from(void *rec, const void *src_rec,\n@@ -1041,7 +1041,7 @@ static int reftable_index_record_copy_from(void *rec, const void *src_rec,\n \tconst struct reftable_index_record *src = src_rec;\n \n \tstrbuf_reset(&dst->last_key);\n-\tstrbuf_addbuf(&dst->last_key, &src->last_key);\n+\tstrbuf_add(&dst->last_key, src->last_key.buf, src->last_key.len);\n \tdst->offset = src->offset;\n \n \treturn 0;\n@@ -1085,7 +1085,7 @@ static int reftable_index_record_decode(void *rec, struct strbuf key,\n \tint n = 0;\n \n \tstrbuf_reset(&r->last_key);\n-\tstrbuf_addbuf(&r->last_key, &key);\n+\tstrbuf_add(&r->last_key, key.buf, key.len);\n \n \tn = get_var_int(&r->offset, &in);\n \tif (n < 0)\ndiff --git a/reftable/writer.c b/reftable/writer.c\nindex b032a47decb..031d8149a9c 100644\n--- a/reftable/writer.c\n+++ b/reftable/writer.c\n@@ -225,7 +225,7 @@ static int writer_index_hash(struct reftable_writer *w, struct strbuf *hash)\n \t\t*key = empty;\n \n \t\tstrbuf_reset(&key->hash);\n-\t\tstrbuf_addbuf(&key->hash, hash);\n+\t\tstrbuf_add(&key->hash, hash->buf, hash->len);\n \t\ttree_insert(&w->obj_index_tree, key,\n \t\t\t    &obj_index_tree_node_compare);\n \t} else {\n@@ -256,7 +256,7 @@ static int writer_add_record(struct reftable_writer *w,\n \t}\n \n \tstrbuf_reset(&w->last_key);\n-\tstrbuf_addbuf(&w->last_key, &key);\n+\tstrbuf_add(&w->last_key, key.buf, key.len);\n \tif (!w->block_writer) {\n \t\terr = writer_reinit_block_writer(w, reftable_record_type(rec));\n \t\tif (err < 0)\n@@ -778,7 +778,8 @@ static int writer_flush_nonempty_block(struct reftable_writer *w)\n \n \tindex_record.offset = w->next;\n \tstrbuf_reset(&index_record.last_key);\n-\tstrbuf_addbuf(&index_record.last_key, &w->block_writer->last_key);\n+\tstrbuf_add(&index_record.last_key, w->block_writer->last_key.buf,\n+\t\t   w->block_writer->last_key.len);\n \tw->index[w->index_len] = index_record;\n \tw->index_len++;\n \n-- \n2.47.0.dirty\n\n"},{"id":"504805","messageId":"abc28d7664f151e00568a6a3d18bf8a2de46470d.1728629612.git.ps@pks.im","threadId":"62313","inReplyTo":"cover.1728629612.git.ps@pks.im","subject":"[PATCH 02/10] reftable: stop using `strbuf_addf()`","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-10-11T06:54:13Z","receivedAt":"2024-10-11T06:54:15Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"We're about to introduce our own `reftable_buf` type to replace\n`strbuf`. Get rid of the seldomly-used `strbuf_addf()` function such\nthat we have to reimplement one less function.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n reftable/stack.c                    | 18 ++++++++-----\n t/unit-tests/t-reftable-block.c     |  7 +++--\n t/unit-tests/t-reftable-readwrite.c | 20 +++++++-------\n t/unit-tests/t-reftable-stack.c     | 42 ++++++++++++++++-------------\n 4 files changed, 50 insertions(+), 37 deletions(-)\n\ndiff --git a/reftable/stack.c b/reftable/stack.c\nindex 7e617c25914..d7bc1187dfb 100644\n--- a/reftable/stack.c\n+++ b/reftable/stack.c\n@@ -1387,12 +1387,18 @@ static int stack_compact_range(struct reftable_stack *st,\n \t * have just written. In case the compacted table became empty we\n \t * simply skip writing it.\n \t */\n-\tfor (i = 0; i < first_to_replace; i++)\n-\t\tstrbuf_addf(&tables_list_buf, \"%s\\n\", names[i]);\n-\tif (!is_empty_table)\n-\t\tstrbuf_addf(&tables_list_buf, \"%s\\n\", new_table_name.buf);\n-\tfor (i = last_to_replace + 1; names[i]; i++)\n-\t\tstrbuf_addf(&tables_list_buf, \"%s\\n\", names[i]);\n+\tfor (i = 0; i < first_to_replace; i++) {\n+\t\tstrbuf_addstr(&tables_list_buf, names[i]);\n+\t\tstrbuf_addstr(&tables_list_buf, \"\\n\");\n+\t}\n+\tif (!is_empty_table) {\n+\t\tstrbuf_addstr(&tables_list_buf, new_table_name.buf);\n+\t\tstrbuf_addstr(&tables_list_buf, \"\\n\");\n+\t}\n+\tfor (i = last_to_replace + 1; names[i]; i++) {\n+\t\tstrbuf_addstr(&tables_list_buf, names[i]);\n+\t\tstrbuf_addstr(&tables_list_buf, \"\\n\");\n+\t}\n \n \terr = write_in_full(get_lock_file_fd(&tables_list_lock),\n \t\t\t    tables_list_buf.buf, tables_list_buf.len);\ndiff --git a/t/unit-tests/t-reftable-block.c b/t/unit-tests/t-reftable-block.c\nindex d470060e8be..8077bbc5e7a 100644\n--- a/t/unit-tests/t-reftable-block.c\n+++ b/t/unit-tests/t-reftable-block.c\n@@ -308,10 +308,13 @@ static void t_index_block_read_write(void)\n \tcheck(!ret);\n \n \tfor (i = 0; i < N; i++) {\n-\t\tstrbuf_init(&recs[i].u.idx.last_key, 9);\n+\t\tchar buf[128];\n+\n+\t\tsnprintf(buf, sizeof(buf), \"branch%02\"PRIuMAX, (uintmax_t)i);\n \n+\t\tstrbuf_init(&recs[i].u.idx.last_key, 9);\n \t\trecs[i].type = BLOCK_TYPE_INDEX;\n-\t\tstrbuf_addf(&recs[i].u.idx.last_key, \"branch%02\"PRIuMAX, (uintmax_t)i);\n+\t\tstrbuf_addstr(&recs[i].u.idx.last_key, buf);\n \t\trecs[i].u.idx.offset = i;\n \n \t\tret = block_writer_add(&bw, &recs[i]);\ndiff --git a/t/unit-tests/t-reftable-readwrite.c b/t/unit-tests/t-reftable-readwrite.c\nindex 27ce84445e8..5f59b0ad6ad 100644\n--- a/t/unit-tests/t-reftable-readwrite.c\n+++ b/t/unit-tests/t-reftable-readwrite.c\n@@ -753,12 +753,13 @@ static void t_write_multiple_indices(void)\n \tstruct reftable_write_options opts = {\n \t\t.block_size = 100,\n \t};\n-\tstruct strbuf writer_buf = STRBUF_INIT, buf = STRBUF_INIT;\n+\tstruct strbuf writer_buf = STRBUF_INIT;\n \tstruct reftable_block_source source = { 0 };\n \tstruct reftable_iterator it = { 0 };\n \tconst struct reftable_stats *stats;\n \tstruct reftable_writer *writer;\n \tstruct reftable_reader *reader;\n+\tchar buf[128];\n \tint err, i;\n \n \twriter = t_reftable_strbuf_writer(&writer_buf, &opts);\n@@ -770,9 +771,8 @@ static void t_write_multiple_indices(void)\n \t\t\t.value.val1 = {i},\n \t\t};\n \n-\t\tstrbuf_reset(&buf);\n-\t\tstrbuf_addf(&buf, \"refs/heads/%04d\", i);\n-\t\tref.refname = buf.buf,\n+\t\tsnprintf(buf, sizeof(buf), \"refs/heads/%04d\", i);\n+\t\tref.refname = buf;\n \n \t\terr = reftable_writer_add_ref(writer, &ref);\n \t\tcheck(!err);\n@@ -788,9 +788,8 @@ static void t_write_multiple_indices(void)\n \t\t\t},\n \t\t};\n \n-\t\tstrbuf_reset(&buf);\n-\t\tstrbuf_addf(&buf, \"refs/heads/%04d\", i);\n-\t\tlog.refname = buf.buf,\n+\t\tsnprintf(buf, sizeof(buf), \"refs/heads/%04d\", i);\n+\t\tlog.refname = buf;\n \n \t\terr = reftable_writer_add_log(writer, &log);\n \t\tcheck(!err);\n@@ -824,7 +823,6 @@ static void t_write_multiple_indices(void)\n \treftable_writer_free(writer);\n \treftable_reader_decref(reader);\n \tstrbuf_release(&writer_buf);\n-\tstrbuf_release(&buf);\n }\n \n static void t_write_multi_level_index(void)\n@@ -848,10 +846,10 @@ static void t_write_multi_level_index(void)\n \t\t\t.value_type = REFTABLE_REF_VAL1,\n \t\t\t.value.val1 = {i},\n \t\t};\n+\t\tchar buf[128];\n \n-\t\tstrbuf_reset(&buf);\n-\t\tstrbuf_addf(&buf, \"refs/heads/%03\" PRIuMAX, (uintmax_t)i);\n-\t\tref.refname = buf.buf,\n+\t\tsnprintf(buf, sizeof(buf), \"refs/heads/%03\" PRIuMAX, (uintmax_t)i);\n+\t\tref.refname = buf;\n \n \t\terr = reftable_writer_add_ref(writer, &ref);\n \t\tcheck(!err);\ndiff --git a/t/unit-tests/t-reftable-stack.c b/t/unit-tests/t-reftable-stack.c\nindex 874095b9ee2..b56ea774312 100644\n--- a/t/unit-tests/t-reftable-stack.c\n+++ b/t/unit-tests/t-reftable-stack.c\n@@ -105,7 +105,6 @@ static int write_test_ref(struct reftable_writer *wr, void *arg)\n static void write_n_ref_tables(struct reftable_stack *st,\n \t\t\t       size_t n)\n {\n-\tstruct strbuf buf = STRBUF_INIT;\n \tint disable_auto_compact;\n \tint err;\n \n@@ -117,10 +116,10 @@ static void write_n_ref_tables(struct reftable_stack *st,\n \t\t\t.update_index = reftable_stack_next_update_index(st),\n \t\t\t.value_type = REFTABLE_REF_VAL1,\n \t\t};\n+\t\tchar buf[128];\n \n-\t\tstrbuf_reset(&buf);\n-\t\tstrbuf_addf(&buf, \"refs/heads/branch-%04\"PRIuMAX, (uintmax_t)i);\n-\t\tref.refname = buf.buf;\n+\t\tsnprintf(buf, sizeof(buf), \"refs/heads/branch-%04\"PRIuMAX, (uintmax_t)i);\n+\t\tref.refname = buf;\n \t\tt_reftable_set_hash(ref.value.val1, i, GIT_SHA1_FORMAT_ID);\n \n \t\terr = reftable_stack_add(st, &write_test_ref, &ref);\n@@ -128,7 +127,6 @@ static void write_n_ref_tables(struct reftable_stack *st,\n \t}\n \n \tst->opts.disable_auto_compact = disable_auto_compact;\n-\tstrbuf_release(&buf);\n }\n \n struct write_log_arg {\n@@ -434,7 +432,10 @@ static void t_reftable_stack_auto_compaction_fails_gracefully(void)\n \t * Adding a new table to the stack should not be impacted by this, even\n \t * though auto-compaction will now fail.\n \t */\n-\tstrbuf_addf(&table_path, \"%s/%s.lock\", dir, st->readers[0]->name);\n+\tstrbuf_addstr(&table_path, dir);\n+\tstrbuf_addstr(&table_path, \"/\");\n+\tstrbuf_addstr(&table_path, st->readers[0]->name);\n+\tstrbuf_addstr(&table_path, \".lock\");\n \twrite_file_buf(table_path.buf, \"\", 0);\n \n \tref.update_index = 2;\n@@ -1077,8 +1078,10 @@ static void t_reftable_stack_auto_compaction_with_locked_tables(void)\n \t * size, we expect that auto-compaction will want to compact all of the\n \t * tables. Locking any of the tables will keep it from doing so.\n \t */\n-\tstrbuf_reset(&buf);\n-\tstrbuf_addf(&buf, \"%s/%s.lock\", dir, st->readers[2]->name);\n+\tstrbuf_addstr(&buf, dir);\n+\tstrbuf_addstr(&buf, \"/\");\n+\tstrbuf_addstr(&buf, st->readers[2]->name);\n+\tstrbuf_addstr(&buf, \".lock\");\n \twrite_file_buf(buf.buf, \"\", 0);\n \n \t/*\n@@ -1101,7 +1104,6 @@ static void t_reftable_stack_add_performs_auto_compaction(void)\n {\n \tstruct reftable_write_options opts = { 0 };\n \tstruct reftable_stack *st = NULL;\n-\tstruct strbuf refname = STRBUF_INIT;\n \tchar *dir = get_tmp_dir(__LINE__);\n \tint err;\n \tsize_t i, n = 20;\n@@ -1115,6 +1117,7 @@ static void t_reftable_stack_add_performs_auto_compaction(void)\n \t\t\t.value_type = REFTABLE_REF_SYMREF,\n \t\t\t.value.symref = (char *) \"master\",\n \t\t};\n+\t\tchar buf[128];\n \n \t\t/*\n \t\t * Disable auto-compaction for all but the last runs. Like this\n@@ -1123,9 +1126,8 @@ static void t_reftable_stack_add_performs_auto_compaction(void)\n \t\t */\n \t\tst->opts.disable_auto_compact = i != n;\n \n-\t\tstrbuf_reset(&refname);\n-\t\tstrbuf_addf(&refname, \"branch-%04\"PRIuMAX, (uintmax_t)i);\n-\t\tref.refname = refname.buf;\n+\t\tsnprintf(buf, sizeof(buf), \"branch-%04\"PRIuMAX, (uintmax_t)i);\n+\t\tref.refname = buf;\n \n \t\terr = reftable_stack_add(st, write_test_ref, &ref);\n \t\tcheck(!err);\n@@ -1142,7 +1144,6 @@ static void t_reftable_stack_add_performs_auto_compaction(void)\n \t}\n \n \treftable_stack_destroy(st);\n-\tstrbuf_release(&refname);\n \tclear_dir(dir);\n }\n \n@@ -1163,8 +1164,10 @@ static void t_reftable_stack_compaction_with_locked_tables(void)\n \tcheck_int(st->merged->readers_len, ==, 3);\n \n \t/* Lock one of the tables that we're about to compact. */\n-\tstrbuf_reset(&buf);\n-\tstrbuf_addf(&buf, \"%s/%s.lock\", dir, st->readers[1]->name);\n+\tstrbuf_addstr(&buf, dir);\n+\tstrbuf_addstr(&buf, \"/\");\n+\tstrbuf_addstr(&buf, st->readers[1]->name);\n+\tstrbuf_addstr(&buf, \".lock\");\n \twrite_file_buf(buf.buf, \"\", 0);\n \n \t/*\n@@ -1321,10 +1324,13 @@ static void t_reftable_stack_reload_with_missing_table(void)\n \t * our old readers. This should trigger a partial reload of the stack,\n \t * where we try to reuse our old readers.\n \t*/\n-\tstrbuf_addf(&content, \"%s\\n\", st->readers[0]->name);\n-\tstrbuf_addf(&content, \"%s\\n\", st->readers[1]->name);\n+\tstrbuf_addstr(&content, st->readers[0]->name);\n+\tstrbuf_addstr(&content, \"\\n\");\n+\tstrbuf_addstr(&content, st->readers[1]->name);\n+\tstrbuf_addstr(&content, \"\\n\");\n \tstrbuf_addstr(&content, \"garbage\\n\");\n-\tstrbuf_addf(&table_path, \"%s.lock\", st->list_file);\n+\tstrbuf_addstr(&table_path, st->list_file);\n+\tstrbuf_addstr(&table_path, \".lock\");\n \twrite_file_buf(table_path.buf, content.buf, content.len);\n \terr = rename(table_path.buf, st->list_file);\n \tcheck(!err);\n-- \n2.47.0.dirty\n\n"},{"id":"504806","messageId":"24e31619b936166404b801dde0e2bca478328386.1728629612.git.ps@pks.im","threadId":"62313","inReplyTo":"cover.1728629612.git.ps@pks.im","subject":"[PATCH 03/10] reftable/basics: provide new `reftable_buf` interface","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-10-11T06:54:15Z","receivedAt":"2024-10-11T06:54:18Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"Implement a new `reftable_buf` interface that will replace Git's own\n`strbuf` interface. This is done due to three reasons:\n\n  - The `strbuf` interfaces do not handle memory allocation failures and\n    instead causes us to die. This is okay in the context of Git, but is\n    not context of the reftable library, which is supposed to be usable\n    by third-party applications.\n\n  - The `strbuf` interface is quite deeply tied into Git, which makes it\n    hard to use the reftable library as a standalone library. Any\n    dependent would have to carefully extract the relevant parts of it\n    to make things work, which is not all that sensible.\n\n  - The `strbuf` interface does not use the pluggable allocators that\n    can be set up via `refatble_set_alloc()`.\n\nSo we have good reasons to use our own type, and the implementation is\nrather trivial. Implement our own type. Conversion of the reftable\nlibrary will be handled in subsequent commits.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n reftable/basics.c | 73 +++++++++++++++++++++++++++++++++++++++++++++++\n reftable/basics.h | 16 +++++++++++\n 2 files changed, 89 insertions(+)\n\ndiff --git a/reftable/basics.c b/reftable/basics.c\nindex 9a949e5cf80..a6abefe7f5d 100644\n--- a/reftable/basics.c\n+++ b/reftable/basics.c\n@@ -69,6 +69,79 @@ void reftable_set_alloc(void *(*malloc)(size_t),\n \treftable_free_ptr = free;\n }\n \n+void reftable_buf_init(struct reftable_buf *buf)\n+{\n+\tstruct reftable_buf empty = REFTABLE_BUF_INIT;\n+\t*buf = empty;\n+}\n+\n+void reftable_buf_release(struct reftable_buf *buf)\n+{\n+\treftable_free(buf->buf);\n+\treftable_buf_init(buf);\n+}\n+\n+void reftable_buf_reset(struct reftable_buf *buf)\n+{\n+\tif (buf->alloc) {\n+\t\tbuf->len = 0;\n+\t\tbuf->buf[0] = '\\0';\n+\t}\n+}\n+\n+int reftable_buf_setlen(struct reftable_buf *buf, size_t len)\n+{\n+\tif (len > buf->len)\n+\t\treturn -1;\n+\tif (len == buf->len)\n+\t\treturn 0;\n+\tbuf->buf[len] = '\\0';\n+\tbuf->len = len;\n+\treturn 0;\n+}\n+\n+int reftable_buf_cmp(const struct reftable_buf *a, const struct reftable_buf *b)\n+{\n+\tsize_t len = a->len < b->len ? a->len : b->len;\n+\tif (len) {\n+\t\tint cmp = memcmp(a->buf, b->buf, len);\n+\t\tif (cmp)\n+\t\t\treturn cmp;\n+\t}\n+\treturn a->len < b->len ? -1 : a->len != b->len;\n+}\n+\n+int reftable_buf_add(struct reftable_buf *buf, const void *data, size_t len)\n+{\n+\tsize_t newlen = buf->len + len;\n+\n+\tif (newlen + 1 > buf->alloc) {\n+\t\tchar *reallocated = buf->buf;\n+\t\tREFTABLE_ALLOC_GROW(reallocated, newlen + 1, buf->alloc);\n+\t\tif (!reallocated)\n+\t\t\treturn -1;\n+\t\tbuf->buf = reallocated;\n+\t}\n+\n+\tmemcpy(buf->buf + buf->len, data, len);\n+\tbuf->buf[newlen] = '\\0';\n+\tbuf->len = newlen;\n+\n+\treturn 0;\n+}\n+\n+int reftable_buf_addstr(struct reftable_buf *buf, const char *s)\n+{\n+\treturn reftable_buf_add(buf, s, strlen(s));\n+}\n+\n+char *reftable_buf_detach(struct reftable_buf *buf)\n+{\n+\tchar *result = buf->buf;\n+\treftable_buf_init(buf);\n+\treturn result;\n+}\n+\n void put_be24(uint8_t *out, uint32_t i)\n {\n \tout[0] = (uint8_t)((i >> 16) & 0xff);\ndiff --git a/reftable/basics.h b/reftable/basics.h\nindex 4c9ef0fe6c5..4cf3f0e7593 100644\n--- a/reftable/basics.h\n+++ b/reftable/basics.h\n@@ -16,6 +16,22 @@ license that can be found in the LICENSE file or at\n #include \"system.h\"\n #include \"reftable-basics.h\"\n \n+struct reftable_buf {\n+\tsize_t alloc;\n+\tsize_t len;\n+\tchar *buf;\n+};\n+#define REFTABLE_BUF_INIT { 0 }\n+\n+void reftable_buf_init(struct reftable_buf *buf);\n+void reftable_buf_release(struct reftable_buf *buf);\n+void reftable_buf_reset(struct reftable_buf *buf);\n+int reftable_buf_setlen(struct reftable_buf *buf, size_t len);\n+int reftable_buf_cmp(const struct reftable_buf *a, const struct reftable_buf *b);\n+int reftable_buf_add(struct reftable_buf *buf, const void *data, size_t len);\n+int reftable_buf_addstr(struct reftable_buf *buf, const char *s);\n+char *reftable_buf_detach(struct reftable_buf *buf);\n+\n /* Bigendian en/decoding of integers */\n \n void put_be24(uint8_t *out, uint32_t i);\n-- \n2.47.0.dirty\n\n"},{"id":"504807","messageId":"e2ac27dbca0956bc231ad2a866bd796170deacf4.1728629612.git.ps@pks.im","threadId":"62313","inReplyTo":"cover.1728629612.git.ps@pks.im","subject":"[PATCH 04/10] reftable: convert from `strbuf` to `reftable_buf`","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-10-11T06:54:18Z","receivedAt":"2024-10-11T06:54:25Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"Convert the reftable library to use the `reftable_buf` interface instead\nof the `strbuf` interface. This is a mechanical change via sed(1) and\ndoes not yet handle allocation failures. These will be addressed in\nsubsequent commits.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n reftable/basics.c                   |   2 +-\n reftable/basics.h                   |   3 +-\n reftable/block.c                    |  34 ++++----\n reftable/block.h                    |  14 ++--\n reftable/blocksource.c              |   6 +-\n reftable/blocksource.h              |   3 +-\n reftable/iter.c                     |   6 +-\n reftable/iter.h                     |   8 +-\n reftable/reader.c                   |  16 ++--\n reftable/record.c                   |  80 +++++++++----------\n reftable/record.h                   |  21 ++---\n reftable/stack.c                    | 120 ++++++++++++++--------------\n reftable/system.h                   |   1 -\n reftable/writer.c                   |  66 +++++++--------\n reftable/writer.h                   |   2 +-\n t/unit-tests/lib-reftable.c         |   4 +-\n t/unit-tests/lib-reftable.h         |   7 +-\n t/unit-tests/t-reftable-basics.c    |  16 ++--\n t/unit-tests/t-reftable-block.c     |  42 +++++-----\n t/unit-tests/t-reftable-merged.c    |  26 +++---\n t/unit-tests/t-reftable-reader.c    |   8 +-\n t/unit-tests/t-reftable-readwrite.c |  92 ++++++++++-----------\n t/unit-tests/t-reftable-record.c    |  74 ++++++++---------\n t/unit-tests/t-reftable-stack.c     |  90 ++++++++++-----------\n 24 files changed, 371 insertions(+), 370 deletions(-)\n\ndiff --git a/reftable/basics.c b/reftable/basics.c\nindex a6abefe7f5d..6fc4ef0964e 100644\n--- a/reftable/basics.c\n+++ b/reftable/basics.c\n@@ -259,7 +259,7 @@ int names_equal(const char **a, const char **b)\n \treturn a[i] == b[i];\n }\n \n-int common_prefix_size(struct strbuf *a, struct strbuf *b)\n+int common_prefix_size(struct reftable_buf *a, struct reftable_buf *b)\n {\n \tint p = 0;\n \tfor (; p < a->len && p < b->len; p++) {\ndiff --git a/reftable/basics.h b/reftable/basics.h\nindex 4cf3f0e7593..ac3100417ec 100644\n--- a/reftable/basics.h\n+++ b/reftable/basics.h\n@@ -104,8 +104,7 @@ char *reftable_strdup(const char *str);\n #endif\n \n /* Find the longest shared prefix size of `a` and `b` */\n-struct strbuf;\n-int common_prefix_size(struct strbuf *a, struct strbuf *b);\n+int common_prefix_size(struct reftable_buf *a, struct reftable_buf *b);\n \n int hash_size(uint32_t id);\n \ndiff --git a/reftable/block.c b/reftable/block.c\nindex cd4180eac7b..4f62b823db8 100644\n--- a/reftable/block.c\n+++ b/reftable/block.c\n@@ -38,7 +38,7 @@ int footer_size(int version)\n }\n \n static int block_writer_register_restart(struct block_writer *w, int n,\n-\t\t\t\t\t int is_restart, struct strbuf *key)\n+\t\t\t\t\t int is_restart, struct reftable_buf *key)\n {\n \tint rlen = w->restart_len;\n \tif (rlen >= MAX_RESTARTS) {\n@@ -59,8 +59,8 @@ static int block_writer_register_restart(struct block_writer *w, int n,\n \n \tw->next += n;\n \n-\tstrbuf_reset(&w->last_key);\n-\tstrbuf_add(&w->last_key, key->buf, key->len);\n+\treftable_buf_reset(&w->last_key);\n+\treftable_buf_add(&w->last_key, key->buf, key->len);\n \tw->entries++;\n \treturn 0;\n }\n@@ -98,8 +98,8 @@ uint8_t block_writer_type(struct block_writer *bw)\n    empty key. */\n int block_writer_add(struct block_writer *w, struct reftable_record *rec)\n {\n-\tstruct strbuf empty = STRBUF_INIT;\n-\tstruct strbuf last =\n+\tstruct reftable_buf empty = REFTABLE_BUF_INIT;\n+\tstruct reftable_buf last =\n \t\tw->entries % w->restart_interval == 0 ? empty : w->last_key;\n \tstruct string_view out = {\n \t\t.buf = w->buf + w->next,\n@@ -109,7 +109,7 @@ int block_writer_add(struct block_writer *w, struct reftable_record *rec)\n \tstruct string_view start = out;\n \n \tint is_restart = 0;\n-\tstruct strbuf key = STRBUF_INIT;\n+\tstruct reftable_buf key = REFTABLE_BUF_INIT;\n \tint n = 0;\n \tint err = -1;\n \n@@ -133,7 +133,7 @@ int block_writer_add(struct block_writer *w, struct reftable_record *rec)\n \terr = block_writer_register_restart(w, start.len - out.len, is_restart,\n \t\t\t\t\t    &key);\n done:\n-\tstrbuf_release(&key);\n+\treftable_buf_release(&key);\n \treturn err;\n }\n \n@@ -325,7 +325,7 @@ uint8_t block_reader_type(const struct block_reader *r)\n \treturn r->block.data[r->header_off];\n }\n \n-int block_reader_first_key(const struct block_reader *br, struct strbuf *key)\n+int block_reader_first_key(const struct block_reader *br, struct reftable_buf *key)\n {\n \tint off = br->header_off + 4, n;\n \tstruct string_view in = {\n@@ -334,7 +334,7 @@ int block_reader_first_key(const struct block_reader *br, struct strbuf *key)\n \t};\n \tuint8_t extra = 0;\n \n-\tstrbuf_reset(key);\n+\treftable_buf_reset(key);\n \n \tn = reftable_decode_key(key, &extra, in);\n \tif (n < 0)\n@@ -355,13 +355,13 @@ void block_iter_seek_start(struct block_iter *it, const struct block_reader *br)\n \tit->block = br->block.data;\n \tit->block_len = br->block_len;\n \tit->hash_size = br->hash_size;\n-\tstrbuf_reset(&it->last_key);\n+\treftable_buf_reset(&it->last_key);\n \tit->next_off = br->header_off + 4;\n }\n \n struct restart_needle_less_args {\n \tint error;\n-\tstruct strbuf needle;\n+\tstruct reftable_buf needle;\n \tconst struct block_reader *reader;\n };\n \n@@ -433,7 +433,7 @@ int block_iter_next(struct block_iter *it, struct reftable_record *rec)\n \n void block_iter_reset(struct block_iter *it)\n {\n-\tstrbuf_reset(&it->last_key);\n+\treftable_buf_reset(&it->last_key);\n \tit->next_off = 0;\n \tit->block = NULL;\n \tit->block_len = 0;\n@@ -442,12 +442,12 @@ void block_iter_reset(struct block_iter *it)\n \n void block_iter_close(struct block_iter *it)\n {\n-\tstrbuf_release(&it->last_key);\n-\tstrbuf_release(&it->scratch);\n+\treftable_buf_release(&it->last_key);\n+\treftable_buf_release(&it->scratch);\n }\n \n int block_iter_seek_key(struct block_iter *it, const struct block_reader *br,\n-\t\t\tstruct strbuf *want)\n+\t\t\tstruct reftable_buf *want)\n {\n \tstruct restart_needle_less_args args = {\n \t\t.needle = *want,\n@@ -537,7 +537,7 @@ int block_iter_seek_key(struct block_iter *it, const struct block_reader *br,\n \t\t * with themselves.\n \t\t */\n \t\treftable_record_key(&rec, &it->last_key);\n-\t\tif (strbuf_cmp(&it->last_key, want) >= 0) {\n+\t\tif (reftable_buf_cmp(&it->last_key, want) >= 0) {\n \t\t\tit->next_off = prev_off;\n \t\t\tgoto done;\n \t\t}\n@@ -554,7 +554,7 @@ void block_writer_release(struct block_writer *bw)\n \tREFTABLE_FREE_AND_NULL(bw->zstream);\n \tREFTABLE_FREE_AND_NULL(bw->restarts);\n \tREFTABLE_FREE_AND_NULL(bw->compressed);\n-\tstrbuf_release(&bw->last_key);\n+\treftable_buf_release(&bw->last_key);\n \t/* the block is not owned. */\n }\n \ndiff --git a/reftable/block.h b/reftable/block.h\nindex 18d7ea03373..9a3effa5134 100644\n--- a/reftable/block.h\n+++ b/reftable/block.h\n@@ -38,7 +38,7 @@ struct block_writer {\n \tuint32_t restart_len;\n \tuint32_t restart_cap;\n \n-\tstruct strbuf last_key;\n+\tstruct reftable_buf last_key;\n \tint entries;\n };\n \n@@ -98,7 +98,7 @@ void block_reader_release(struct block_reader *br);\n uint8_t block_reader_type(const struct block_reader *r);\n \n /* Decodes the first key in the block */\n-int block_reader_first_key(const struct block_reader *br, struct strbuf *key);\n+int block_reader_first_key(const struct block_reader *br, struct reftable_buf *key);\n \n /* Iterate over entries in a block */\n struct block_iter {\n@@ -109,13 +109,13 @@ struct block_iter {\n \tint hash_size;\n \n \t/* key for last entry we read. */\n-\tstruct strbuf last_key;\n-\tstruct strbuf scratch;\n+\tstruct reftable_buf last_key;\n+\tstruct reftable_buf scratch;\n };\n \n #define BLOCK_ITER_INIT { \\\n-\t.last_key = STRBUF_INIT, \\\n-\t.scratch = STRBUF_INIT, \\\n+\t.last_key = REFTABLE_BUF_INIT, \\\n+\t.scratch = REFTABLE_BUF_INIT, \\\n }\n \n /* Position `it` at start of the block */\n@@ -123,7 +123,7 @@ void block_iter_seek_start(struct block_iter *it, const struct block_reader *br)\n \n /* Position `it` to the `want` key in the block */\n int block_iter_seek_key(struct block_iter *it, const struct block_reader *br,\n-\t\t\tstruct strbuf *want);\n+\t\t\tstruct reftable_buf *want);\n \n /* return < 0 for error, 0 for OK, > 0 for EOF. */\n int block_iter_next(struct block_iter *it, struct reftable_record *rec);\ndiff --git a/reftable/blocksource.c b/reftable/blocksource.c\nindex a2a6a196d55..d6242d67900 100644\n--- a/reftable/blocksource.c\n+++ b/reftable/blocksource.c\n@@ -27,7 +27,7 @@ static void strbuf_close(void *b UNUSED)\n static int strbuf_read_block(void *v, struct reftable_block *dest, uint64_t off,\n \t\t\t     uint32_t size)\n {\n-\tstruct strbuf *b = v;\n+\tstruct reftable_buf *b = v;\n \tassert(off + size <= b->len);\n \tREFTABLE_CALLOC_ARRAY(dest->data, size);\n \tif (!dest->data)\n@@ -39,7 +39,7 @@ static int strbuf_read_block(void *v, struct reftable_block *dest, uint64_t off,\n \n static uint64_t strbuf_size(void *b)\n {\n-\treturn ((struct strbuf *)b)->len;\n+\treturn ((struct reftable_buf *)b)->len;\n }\n \n static struct reftable_block_source_vtable strbuf_vtable = {\n@@ -50,7 +50,7 @@ static struct reftable_block_source_vtable strbuf_vtable = {\n };\n \n void block_source_from_strbuf(struct reftable_block_source *bs,\n-\t\t\t      struct strbuf *buf)\n+\t\t\t      struct reftable_buf *buf)\n {\n \tassert(!bs->ops);\n \tbs->ops = &strbuf_vtable;\ndiff --git a/reftable/blocksource.h b/reftable/blocksource.h\nindex 659a27b4063..ee3647c6531 100644\n--- a/reftable/blocksource.h\n+++ b/reftable/blocksource.h\n@@ -12,9 +12,10 @@ license that can be found in the LICENSE file or at\n #include \"system.h\"\n \n struct reftable_block_source;\n+struct reftable_buf;\n \n /* Create an in-memory block source for reading reftables */\n void block_source_from_strbuf(struct reftable_block_source *bs,\n-\t\t\t      struct strbuf *buf);\n+\t\t\t      struct reftable_buf *buf);\n \n #endif\ndiff --git a/reftable/iter.c b/reftable/iter.c\nindex d926db653b1..6c193fd31a9 100644\n--- a/reftable/iter.c\n+++ b/reftable/iter.c\n@@ -55,7 +55,7 @@ void iterator_set_empty(struct reftable_iterator *it)\n static void filtering_ref_iterator_close(void *iter_arg)\n {\n \tstruct filtering_ref_iterator *fri = iter_arg;\n-\tstrbuf_release(&fri->oid);\n+\treftable_buf_release(&fri->oid);\n \treftable_iterator_destroy(&fri->it);\n }\n \n@@ -115,7 +115,7 @@ static void indexed_table_ref_iter_close(void *p)\n \tblock_iter_close(&it->cur);\n \treftable_block_done(&it->block_reader.block);\n \treftable_free(it->offsets);\n-\tstrbuf_release(&it->oid);\n+\treftable_buf_release(&it->oid);\n }\n \n static int indexed_table_ref_iter_next_block(struct indexed_table_ref_iter *it)\n@@ -197,7 +197,7 @@ int indexed_table_ref_iter_new(struct indexed_table_ref_iter **dest,\n \n \t*itr = empty;\n \titr->r = r;\n-\tstrbuf_add(&itr->oid, oid, oid_len);\n+\treftable_buf_add(&itr->oid, oid, oid_len);\n \n \titr->offsets = offsets;\n \titr->offset_len = offset_len;\ndiff --git a/reftable/iter.h b/reftable/iter.h\nindex b3225bc7add..40f98893b85 100644\n--- a/reftable/iter.h\n+++ b/reftable/iter.h\n@@ -44,12 +44,12 @@ void iterator_set_empty(struct reftable_iterator *it);\n \n /* iterator that produces only ref records that point to `oid` */\n struct filtering_ref_iterator {\n-\tstruct strbuf oid;\n+\tstruct reftable_buf oid;\n \tstruct reftable_iterator it;\n };\n #define FILTERING_REF_ITERATOR_INIT \\\n \t{                           \\\n-\t\t.oid = STRBUF_INIT  \\\n+\t\t.oid = REFTABLE_BUF_INIT  \\\n \t}\n \n void iterator_from_filtering_ref_iterator(struct reftable_iterator *,\n@@ -60,7 +60,7 @@ void iterator_from_filtering_ref_iterator(struct reftable_iterator *,\n  */\n struct indexed_table_ref_iter {\n \tstruct reftable_reader *r;\n-\tstruct strbuf oid;\n+\tstruct reftable_buf oid;\n \n \t/* mutable */\n \tuint64_t *offsets;\n@@ -75,7 +75,7 @@ struct indexed_table_ref_iter {\n \n #define INDEXED_TABLE_REF_ITER_INIT { \\\n \t.cur = BLOCK_ITER_INIT, \\\n-\t.oid = STRBUF_INIT, \\\n+\t.oid = REFTABLE_BUF_INIT, \\\n }\n \n void iterator_from_indexed_table_ref_iter(struct reftable_iterator *it,\ndiff --git a/reftable/reader.c b/reftable/reader.c\nindex 8d372539220..388f8bf6d7b 100644\n--- a/reftable/reader.c\n+++ b/reftable/reader.c\n@@ -350,8 +350,8 @@ static int table_iter_seek_start(struct table_iter *ti, uint8_t typ, int index)\n static int table_iter_seek_linear(struct table_iter *ti,\n \t\t\t\t  struct reftable_record *want)\n {\n-\tstruct strbuf want_key = STRBUF_INIT;\n-\tstruct strbuf got_key = STRBUF_INIT;\n+\tstruct reftable_buf want_key = REFTABLE_BUF_INIT;\n+\tstruct reftable_buf got_key = REFTABLE_BUF_INIT;\n \tstruct reftable_record rec;\n \tint err;\n \n@@ -401,7 +401,7 @@ static int table_iter_seek_linear(struct table_iter *ti,\n \t\tif (err < 0)\n \t\t\tgoto done;\n \n-\t\tif (strbuf_cmp(&got_key, &want_key) > 0) {\n+\t\tif (reftable_buf_cmp(&got_key, &want_key) > 0) {\n \t\t\ttable_iter_block_done(&next);\n \t\t\tbreak;\n \t\t}\n@@ -422,8 +422,8 @@ static int table_iter_seek_linear(struct table_iter *ti,\n \n done:\n \treftable_record_release(&rec);\n-\tstrbuf_release(&want_key);\n-\tstrbuf_release(&got_key);\n+\treftable_buf_release(&want_key);\n+\treftable_buf_release(&got_key);\n \treturn err;\n }\n \n@@ -431,11 +431,11 @@ static int table_iter_seek_indexed(struct table_iter *ti,\n \t\t\t\t   struct reftable_record *rec)\n {\n \tstruct reftable_record want_index = {\n-\t\t.type = BLOCK_TYPE_INDEX, .u.idx = { .last_key = STRBUF_INIT }\n+\t\t.type = BLOCK_TYPE_INDEX, .u.idx = { .last_key = REFTABLE_BUF_INIT }\n \t};\n \tstruct reftable_record index_result = {\n \t\t.type = BLOCK_TYPE_INDEX,\n-\t\t.u.idx = { .last_key = STRBUF_INIT },\n+\t\t.u.idx = { .last_key = REFTABLE_BUF_INIT },\n \t};\n \tint err;\n \n@@ -765,7 +765,7 @@ static int reftable_reader_refs_for_unindexed(struct reftable_reader *r,\n \t}\n \t*filter = empty;\n \n-\tstrbuf_add(&filter->oid, oid, oid_len);\n+\treftable_buf_add(&filter->oid, oid, oid_len);\n \titerator_from_table_iter(&filter->it, ti);\n \n \titerator_from_filtering_ref_iterator(it, filter);\ndiff --git a/reftable/record.c b/reftable/record.c\nindex 87157f2c386..0182c973437 100644\n--- a/reftable/record.c\n+++ b/reftable/record.c\n@@ -98,7 +98,7 @@ const unsigned char *reftable_ref_record_val2(const struct reftable_ref_record *\n \t}\n }\n \n-static int decode_string(struct strbuf *dest, struct string_view in)\n+static int decode_string(struct reftable_buf *dest, struct string_view in)\n {\n \tint start_len = in.len;\n \tuint64_t tsize = 0;\n@@ -109,8 +109,8 @@ static int decode_string(struct strbuf *dest, struct string_view in)\n \tif (in.len < tsize)\n \t\treturn -1;\n \n-\tstrbuf_reset(dest);\n-\tstrbuf_add(dest, in.buf, tsize);\n+\treftable_buf_reset(dest);\n+\treftable_buf_add(dest, in.buf, tsize);\n \tstring_view_consume(&in, tsize);\n \n \treturn start_len - in.len;\n@@ -133,7 +133,7 @@ static int encode_string(const char *str, struct string_view s)\n }\n \n int reftable_encode_key(int *restart, struct string_view dest,\n-\t\t\tstruct strbuf prev_key, struct strbuf key,\n+\t\t\tstruct reftable_buf prev_key, struct reftable_buf key,\n \t\t\tuint8_t extra)\n {\n \tstruct string_view start = dest;\n@@ -183,7 +183,7 @@ int reftable_decode_keylen(struct string_view in,\n \treturn start_len - in.len;\n }\n \n-int reftable_decode_key(struct strbuf *last_key, uint8_t *extra,\n+int reftable_decode_key(struct reftable_buf *last_key, uint8_t *extra,\n \t\t\tstruct string_view in)\n {\n \tint start_len = in.len;\n@@ -200,19 +200,19 @@ int reftable_decode_key(struct strbuf *last_key, uint8_t *extra,\n \t    prefix_len > last_key->len)\n \t\treturn -1;\n \n-\tstrbuf_setlen(last_key, prefix_len);\n-\tstrbuf_add(last_key, in.buf, suffix_len);\n+\treftable_buf_setlen(last_key, prefix_len);\n+\treftable_buf_add(last_key, in.buf, suffix_len);\n \tstring_view_consume(&in, suffix_len);\n \n \treturn start_len - in.len;\n }\n \n-static void reftable_ref_record_key(const void *r, struct strbuf *dest)\n+static void reftable_ref_record_key(const void *r, struct reftable_buf *dest)\n {\n \tconst struct reftable_ref_record *rec =\n \t\t(const struct reftable_ref_record *)r;\n-\tstrbuf_reset(dest);\n-\tstrbuf_addstr(dest, rec->refname);\n+\treftable_buf_reset(dest);\n+\treftable_buf_addstr(dest, rec->refname);\n }\n \n static int reftable_ref_record_copy_from(void *rec, const void *src_rec,\n@@ -350,9 +350,9 @@ static int reftable_ref_record_encode(const void *rec, struct string_view s,\n \treturn start.len - s.len;\n }\n \n-static int reftable_ref_record_decode(void *rec, struct strbuf key,\n+static int reftable_ref_record_decode(void *rec, struct reftable_buf key,\n \t\t\t\t      uint8_t val_type, struct string_view in,\n-\t\t\t\t      int hash_size, struct strbuf *scratch)\n+\t\t\t\t      int hash_size, struct reftable_buf *scratch)\n {\n \tstruct reftable_ref_record *r = rec;\n \tstruct string_view start = in;\n@@ -415,7 +415,7 @@ static int reftable_ref_record_decode(void *rec, struct strbuf key,\n \t\t\tgoto done;\n \t\t}\n \t\tstring_view_consume(&in, n);\n-\t\tr->value.symref = strbuf_detach(scratch, NULL);\n+\t\tr->value.symref = reftable_buf_detach(scratch);\n \t} break;\n \n \tcase REFTABLE_REF_DELETION:\n@@ -465,12 +465,12 @@ static struct reftable_record_vtable reftable_ref_record_vtable = {\n \t.cmp = &reftable_ref_record_cmp_void,\n };\n \n-static void reftable_obj_record_key(const void *r, struct strbuf *dest)\n+static void reftable_obj_record_key(const void *r, struct reftable_buf *dest)\n {\n \tconst struct reftable_obj_record *rec =\n \t\t(const struct reftable_obj_record *)r;\n-\tstrbuf_reset(dest);\n-\tstrbuf_add(dest, rec->hash_prefix, rec->hash_prefix_len);\n+\treftable_buf_reset(dest);\n+\treftable_buf_add(dest, rec->hash_prefix, rec->hash_prefix_len);\n }\n \n static void reftable_obj_record_release(void *rec)\n@@ -547,10 +547,10 @@ static int reftable_obj_record_encode(const void *rec, struct string_view s,\n \treturn start.len - s.len;\n }\n \n-static int reftable_obj_record_decode(void *rec, struct strbuf key,\n+static int reftable_obj_record_decode(void *rec, struct reftable_buf key,\n \t\t\t\t      uint8_t val_type, struct string_view in,\n \t\t\t\t      int hash_size UNUSED,\n-\t\t\t\t      struct strbuf *scratch UNUSED)\n+\t\t\t\t      struct reftable_buf *scratch UNUSED)\n {\n \tstruct string_view start = in;\n \tstruct reftable_obj_record *r = rec;\n@@ -664,19 +664,19 @@ static struct reftable_record_vtable reftable_obj_record_vtable = {\n \t.cmp = &reftable_obj_record_cmp_void,\n };\n \n-static void reftable_log_record_key(const void *r, struct strbuf *dest)\n+static void reftable_log_record_key(const void *r, struct reftable_buf *dest)\n {\n \tconst struct reftable_log_record *rec =\n \t\t(const struct reftable_log_record *)r;\n \tint len = strlen(rec->refname);\n \tuint8_t i64[8];\n \tuint64_t ts = 0;\n-\tstrbuf_reset(dest);\n-\tstrbuf_add(dest, (uint8_t *)rec->refname, len + 1);\n+\treftable_buf_reset(dest);\n+\treftable_buf_add(dest, (uint8_t *)rec->refname, len + 1);\n \n \tts = (~ts) - rec->update_index;\n \tput_be64(&i64[0], ts);\n-\tstrbuf_add(dest, i64, sizeof(i64));\n+\treftable_buf_add(dest, i64, sizeof(i64));\n }\n \n static int reftable_log_record_copy_from(void *rec, const void *src_rec,\n@@ -807,9 +807,9 @@ static int reftable_log_record_encode(const void *rec, struct string_view s,\n \treturn start.len - s.len;\n }\n \n-static int reftable_log_record_decode(void *rec, struct strbuf key,\n+static int reftable_log_record_decode(void *rec, struct reftable_buf key,\n \t\t\t\t      uint8_t val_type, struct string_view in,\n-\t\t\t\t      int hash_size, struct strbuf *scratch)\n+\t\t\t\t      int hash_size, struct reftable_buf *scratch)\n {\n \tstruct string_view start = in;\n \tstruct reftable_log_record *r = rec;\n@@ -1027,11 +1027,11 @@ static struct reftable_record_vtable reftable_log_record_vtable = {\n \t.cmp = &reftable_log_record_cmp_void,\n };\n \n-static void reftable_index_record_key(const void *r, struct strbuf *dest)\n+static void reftable_index_record_key(const void *r, struct reftable_buf *dest)\n {\n \tconst struct reftable_index_record *rec = r;\n-\tstrbuf_reset(dest);\n-\tstrbuf_add(dest, rec->last_key.buf, rec->last_key.len);\n+\treftable_buf_reset(dest);\n+\treftable_buf_add(dest, rec->last_key.buf, rec->last_key.len);\n }\n \n static int reftable_index_record_copy_from(void *rec, const void *src_rec,\n@@ -1040,8 +1040,8 @@ static int reftable_index_record_copy_from(void *rec, const void *src_rec,\n \tstruct reftable_index_record *dst = rec;\n \tconst struct reftable_index_record *src = src_rec;\n \n-\tstrbuf_reset(&dst->last_key);\n-\tstrbuf_add(&dst->last_key, src->last_key.buf, src->last_key.len);\n+\treftable_buf_reset(&dst->last_key);\n+\treftable_buf_add(&dst->last_key, src->last_key.buf, src->last_key.len);\n \tdst->offset = src->offset;\n \n \treturn 0;\n@@ -1050,7 +1050,7 @@ static int reftable_index_record_copy_from(void *rec, const void *src_rec,\n static void reftable_index_record_release(void *rec)\n {\n \tstruct reftable_index_record *idx = rec;\n-\tstrbuf_release(&idx->last_key);\n+\treftable_buf_release(&idx->last_key);\n }\n \n static uint8_t reftable_index_record_val_type(const void *rec UNUSED)\n@@ -1074,18 +1074,18 @@ static int reftable_index_record_encode(const void *rec, struct string_view out,\n \treturn start.len - out.len;\n }\n \n-static int reftable_index_record_decode(void *rec, struct strbuf key,\n+static int reftable_index_record_decode(void *rec, struct reftable_buf key,\n \t\t\t\t\tuint8_t val_type UNUSED,\n \t\t\t\t\tstruct string_view in,\n \t\t\t\t\tint hash_size UNUSED,\n-\t\t\t\t\tstruct strbuf *scratch UNUSED)\n+\t\t\t\t\tstruct reftable_buf *scratch UNUSED)\n {\n \tstruct string_view start = in;\n \tstruct reftable_index_record *r = rec;\n \tint n = 0;\n \n-\tstrbuf_reset(&r->last_key);\n-\tstrbuf_add(&r->last_key, key.buf, key.len);\n+\treftable_buf_reset(&r->last_key);\n+\treftable_buf_add(&r->last_key, key.buf, key.len);\n \n \tn = get_var_int(&r->offset, &in);\n \tif (n < 0)\n@@ -1101,14 +1101,14 @@ static int reftable_index_record_equal(const void *a, const void *b,\n \tstruct reftable_index_record *ia = (struct reftable_index_record *) a;\n \tstruct reftable_index_record *ib = (struct reftable_index_record *) b;\n \n-\treturn ia->offset == ib->offset && !strbuf_cmp(&ia->last_key, &ib->last_key);\n+\treturn ia->offset == ib->offset && !reftable_buf_cmp(&ia->last_key, &ib->last_key);\n }\n \n static int reftable_index_record_cmp(const void *_a, const void *_b)\n {\n \tconst struct reftable_index_record *a = _a;\n \tconst struct reftable_index_record *b = _b;\n-\treturn strbuf_cmp(&a->last_key, &b->last_key);\n+\treturn reftable_buf_cmp(&a->last_key, &b->last_key);\n }\n \n static struct reftable_record_vtable reftable_index_record_vtable = {\n@@ -1124,7 +1124,7 @@ static struct reftable_record_vtable reftable_index_record_vtable = {\n \t.cmp = &reftable_index_record_cmp,\n };\n \n-void reftable_record_key(struct reftable_record *rec, struct strbuf *dest)\n+void reftable_record_key(struct reftable_record *rec, struct reftable_buf *dest)\n {\n \treftable_record_vtable(rec)->key(reftable_record_data(rec), dest);\n }\n@@ -1151,9 +1151,9 @@ uint8_t reftable_record_val_type(struct reftable_record *rec)\n \treturn reftable_record_vtable(rec)->val_type(reftable_record_data(rec));\n }\n \n-int reftable_record_decode(struct reftable_record *rec, struct strbuf key,\n+int reftable_record_decode(struct reftable_record *rec, struct reftable_buf key,\n \t\t\t   uint8_t extra, struct string_view src, int hash_size,\n-\t\t\t   struct strbuf *scratch)\n+\t\t\t   struct reftable_buf *scratch)\n {\n \treturn reftable_record_vtable(rec)->decode(reftable_record_data(rec),\n \t\t\t\t\t\t   key, extra, src, hash_size,\n@@ -1294,7 +1294,7 @@ void reftable_record_init(struct reftable_record *rec, uint8_t typ)\n \tcase BLOCK_TYPE_OBJ:\n \t\treturn;\n \tcase BLOCK_TYPE_INDEX:\n-\t\tstrbuf_init(&rec->u.idx.last_key, 0);\n+\t\treftable_buf_init(&rec->u.idx.last_key);\n \t\treturn;\n \tdefault:\n \t\tBUG(\"unhandled record type\");\ndiff --git a/reftable/record.h b/reftable/record.h\nindex 0f53ba54434..271da3bf360 100644\n--- a/reftable/record.h\n+++ b/reftable/record.h\n@@ -9,6 +9,7 @@ license that can be found in the LICENSE file or at\n #ifndef RECORD_H\n #define RECORD_H\n \n+#include \"basics.h\"\n #include \"system.h\"\n \n #include <stdint.h>\n@@ -38,8 +39,8 @@ int put_var_int(struct string_view *dest, uint64_t val);\n \n /* Methods for records. */\n struct reftable_record_vtable {\n-\t/* encode the key of to a uint8_t strbuf. */\n-\tvoid (*key)(const void *rec, struct strbuf *dest);\n+\t/* encode the key of to a uint8_t reftable_buf. */\n+\tvoid (*key)(const void *rec, struct reftable_buf *dest);\n \n \t/* The record type of ('r' for ref). */\n \tuint8_t type;\n@@ -54,9 +55,9 @@ struct reftable_record_vtable {\n \tint (*encode)(const void *rec, struct string_view dest, int hash_size);\n \n \t/* decode data from `src` into the record. */\n-\tint (*decode)(void *rec, struct strbuf key, uint8_t extra,\n+\tint (*decode)(void *rec, struct reftable_buf key, uint8_t extra,\n \t\t      struct string_view src, int hash_size,\n-\t\t      struct strbuf *scratch);\n+\t\t      struct reftable_buf *scratch);\n \n \t/* deallocate and null the record. */\n \tvoid (*release)(void *rec);\n@@ -83,7 +84,7 @@ int reftable_is_block_type(uint8_t typ);\n /* Encode `key` into `dest`. Sets `is_restart` to indicate a restart. Returns\n  * number of bytes written. */\n int reftable_encode_key(int *is_restart, struct string_view dest,\n-\t\t\tstruct strbuf prev_key, struct strbuf key,\n+\t\t\tstruct reftable_buf prev_key, struct reftable_buf key,\n \t\t\tuint8_t extra);\n \n /* Decode a record's key lengths. */\n@@ -96,13 +97,13 @@ int reftable_decode_keylen(struct string_view in,\n  * Decode into `last_key` and `extra` from `in`. `last_key` is expected to\n  * contain the decoded key of the preceding record, if any.\n  */\n-int reftable_decode_key(struct strbuf *last_key, uint8_t *extra,\n+int reftable_decode_key(struct reftable_buf *last_key, uint8_t *extra,\n \t\t\tstruct string_view in);\n \n /* reftable_index_record are used internally to speed up lookups. */\n struct reftable_index_record {\n \tuint64_t offset; /* Offset of block */\n-\tstruct strbuf last_key; /* Last key of the block. */\n+\tstruct reftable_buf last_key; /* Last key of the block. */\n };\n \n /* reftable_obj_record stores an object ID => ref mapping. */\n@@ -136,15 +137,15 @@ void reftable_record_init(struct reftable_record *rec, uint8_t typ);\n /* see struct record_vtable */\n int reftable_record_cmp(struct reftable_record *a, struct reftable_record *b);\n int reftable_record_equal(struct reftable_record *a, struct reftable_record *b, int hash_size);\n-void reftable_record_key(struct reftable_record *rec, struct strbuf *dest);\n+void reftable_record_key(struct reftable_record *rec, struct reftable_buf *dest);\n int reftable_record_copy_from(struct reftable_record *rec,\n \t\t\t      struct reftable_record *src, int hash_size);\n uint8_t reftable_record_val_type(struct reftable_record *rec);\n int reftable_record_encode(struct reftable_record *rec, struct string_view dest,\n \t\t\t   int hash_size);\n-int reftable_record_decode(struct reftable_record *rec, struct strbuf key,\n+int reftable_record_decode(struct reftable_record *rec, struct reftable_buf key,\n \t\t\t   uint8_t extra, struct string_view src,\n-\t\t\t   int hash_size, struct strbuf *scratch);\n+\t\t\t   int hash_size, struct reftable_buf *scratch);\n int reftable_record_is_deletion(struct reftable_record *rec);\n \n static inline uint8_t reftable_record_type(struct reftable_record *rec)\ndiff --git a/reftable/stack.c b/reftable/stack.c\nindex d7bc1187dfb..6ba48ddce5d 100644\n--- a/reftable/stack.c\n+++ b/reftable/stack.c\n@@ -31,13 +31,13 @@ static void reftable_addition_close(struct reftable_addition *add);\n static int reftable_stack_reload_maybe_reuse(struct reftable_stack *st,\n \t\t\t\t\t     int reuse_open);\n \n-static void stack_filename(struct strbuf *dest, struct reftable_stack *st,\n+static void stack_filename(struct reftable_buf *dest, struct reftable_stack *st,\n \t\t\t   const char *name)\n {\n-\tstrbuf_reset(dest);\n-\tstrbuf_addstr(dest, st->reftable_dir);\n-\tstrbuf_addstr(dest, \"/\");\n-\tstrbuf_addstr(dest, name);\n+\treftable_buf_reset(dest);\n+\treftable_buf_addstr(dest, st->reftable_dir);\n+\treftable_buf_addstr(dest, \"/\");\n+\treftable_buf_addstr(dest, name);\n }\n \n static ssize_t reftable_fd_write(void *arg, const void *data, size_t sz)\n@@ -56,7 +56,7 @@ static int reftable_fd_flush(void *arg)\n int reftable_new_stack(struct reftable_stack **dest, const char *dir,\n \t\t       const struct reftable_write_options *_opts)\n {\n-\tstruct strbuf list_file_name = STRBUF_INIT;\n+\tstruct reftable_buf list_file_name = REFTABLE_BUF_INIT;\n \tstruct reftable_write_options opts = { 0 };\n \tstruct reftable_stack *p;\n \tint err;\n@@ -74,11 +74,11 @@ int reftable_new_stack(struct reftable_stack **dest, const char *dir,\n \n \t*dest = NULL;\n \n-\tstrbuf_reset(&list_file_name);\n-\tstrbuf_addstr(&list_file_name, dir);\n-\tstrbuf_addstr(&list_file_name, \"/tables.list\");\n+\treftable_buf_reset(&list_file_name);\n+\treftable_buf_addstr(&list_file_name, dir);\n+\treftable_buf_addstr(&list_file_name, \"/tables.list\");\n \n-\tp->list_file = strbuf_detach(&list_file_name, NULL);\n+\tp->list_file = reftable_buf_detach(&list_file_name);\n \tp->list_fd = -1;\n \tp->opts = opts;\n \tp->reftable_dir = reftable_strdup(dir);\n@@ -208,10 +208,10 @@ void reftable_stack_destroy(struct reftable_stack *st)\n \n \tif (st->readers) {\n \t\tint i = 0;\n-\t\tstruct strbuf filename = STRBUF_INIT;\n+\t\tstruct reftable_buf filename = REFTABLE_BUF_INIT;\n \t\tfor (i = 0; i < st->readers_len; i++) {\n \t\t\tconst char *name = reader_name(st->readers[i]);\n-\t\t\tstrbuf_reset(&filename);\n+\t\t\treftable_buf_reset(&filename);\n \t\t\tif (names && !has_name(names, name)) {\n \t\t\t\tstack_filename(&filename, st, name);\n \t\t\t}\n@@ -222,7 +222,7 @@ void reftable_stack_destroy(struct reftable_stack *st)\n \t\t\t\tunlink(filename.buf);\n \t\t\t}\n \t\t}\n-\t\tstrbuf_release(&filename);\n+\t\treftable_buf_release(&filename);\n \t\tst->readers_len = 0;\n \t\tREFTABLE_FREE_AND_NULL(st->readers);\n \t}\n@@ -260,7 +260,7 @@ static int reftable_stack_reload_once(struct reftable_stack *st,\n \tsize_t reused_len = 0, reused_alloc = 0, names_len;\n \tsize_t new_readers_len = 0;\n \tstruct reftable_merged_table *new_merged = NULL;\n-\tstruct strbuf table_path = STRBUF_INIT;\n+\tstruct reftable_buf table_path = REFTABLE_BUF_INIT;\n \tint err = 0;\n \tsize_t i;\n \n@@ -374,7 +374,7 @@ static int reftable_stack_reload_once(struct reftable_stack *st,\n \treftable_free(new_readers);\n \treftable_free(reused);\n \treftable_free(cur);\n-\tstrbuf_release(&table_path);\n+\treftable_buf_release(&table_path);\n \treturn err;\n }\n \n@@ -623,14 +623,14 @@ int reftable_stack_add(struct reftable_stack *st,\n \treturn 0;\n }\n \n-static void format_name(struct strbuf *dest, uint64_t min, uint64_t max)\n+static void format_name(struct reftable_buf *dest, uint64_t min, uint64_t max)\n {\n \tchar buf[100];\n \tuint32_t rnd = (uint32_t)git_rand();\n \tsnprintf(buf, sizeof(buf), \"0x%012\" PRIx64 \"-0x%012\" PRIx64 \"-%08x\",\n \t\t min, max, rnd);\n-\tstrbuf_reset(dest);\n-\tstrbuf_addstr(dest, buf);\n+\treftable_buf_reset(dest);\n+\treftable_buf_addstr(dest, buf);\n }\n \n struct reftable_addition {\n@@ -648,7 +648,7 @@ static int reftable_stack_init_addition(struct reftable_addition *add,\n \t\t\t\t\tstruct reftable_stack *st,\n \t\t\t\t\tunsigned int flags)\n {\n-\tstruct strbuf lock_file_name = STRBUF_INIT;\n+\tstruct reftable_buf lock_file_name = REFTABLE_BUF_INIT;\n \tint err;\n \n \tadd->stack = st;\n@@ -690,13 +690,13 @@ static int reftable_stack_init_addition(struct reftable_addition *add,\n done:\n \tif (err)\n \t\treftable_addition_close(add);\n-\tstrbuf_release(&lock_file_name);\n+\treftable_buf_release(&lock_file_name);\n \treturn err;\n }\n \n static void reftable_addition_close(struct reftable_addition *add)\n {\n-\tstruct strbuf nm = STRBUF_INIT;\n+\tstruct reftable_buf nm = REFTABLE_BUF_INIT;\n \tsize_t i;\n \n \tfor (i = 0; i < add->new_tables_len; i++) {\n@@ -711,7 +711,7 @@ static void reftable_addition_close(struct reftable_addition *add)\n \tadd->new_tables_cap = 0;\n \n \trollback_lock_file(&add->tables_list_lock);\n-\tstrbuf_release(&nm);\n+\treftable_buf_release(&nm);\n }\n \n void reftable_addition_destroy(struct reftable_addition *add)\n@@ -725,7 +725,7 @@ void reftable_addition_destroy(struct reftable_addition *add)\n \n int reftable_addition_commit(struct reftable_addition *add)\n {\n-\tstruct strbuf table_list = STRBUF_INIT;\n+\tstruct reftable_buf table_list = REFTABLE_BUF_INIT;\n \tint lock_file_fd = get_lock_file_fd(&add->tables_list_lock);\n \tint err = 0;\n \tsize_t i;\n@@ -734,16 +734,16 @@ int reftable_addition_commit(struct reftable_addition *add)\n \t\tgoto done;\n \n \tfor (i = 0; i < add->stack->merged->readers_len; i++) {\n-\t\tstrbuf_addstr(&table_list, add->stack->readers[i]->name);\n-\t\tstrbuf_addstr(&table_list, \"\\n\");\n+\t\treftable_buf_addstr(&table_list, add->stack->readers[i]->name);\n+\t\treftable_buf_addstr(&table_list, \"\\n\");\n \t}\n \tfor (i = 0; i < add->new_tables_len; i++) {\n-\t\tstrbuf_addstr(&table_list, add->new_tables[i]);\n-\t\tstrbuf_addstr(&table_list, \"\\n\");\n+\t\treftable_buf_addstr(&table_list, add->new_tables[i]);\n+\t\treftable_buf_addstr(&table_list, \"\\n\");\n \t}\n \n \terr = write_in_full(lock_file_fd, table_list.buf, table_list.len);\n-\tstrbuf_release(&table_list);\n+\treftable_buf_release(&table_list);\n \tif (err < 0) {\n \t\terr = REFTABLE_IO_ERROR;\n \t\tgoto done;\n@@ -837,19 +837,19 @@ int reftable_addition_add(struct reftable_addition *add,\n \t\t\t\t\t     void *arg),\n \t\t\t  void *arg)\n {\n-\tstruct strbuf temp_tab_file_name = STRBUF_INIT;\n-\tstruct strbuf tab_file_name = STRBUF_INIT;\n-\tstruct strbuf next_name = STRBUF_INIT;\n+\tstruct reftable_buf temp_tab_file_name = REFTABLE_BUF_INIT;\n+\tstruct reftable_buf tab_file_name = REFTABLE_BUF_INIT;\n+\tstruct reftable_buf next_name = REFTABLE_BUF_INIT;\n \tstruct reftable_writer *wr = NULL;\n \tstruct tempfile *tab_file = NULL;\n \tint err = 0;\n \tint tab_fd;\n \n-\tstrbuf_reset(&next_name);\n+\treftable_buf_reset(&next_name);\n \tformat_name(&next_name, add->next_update_index, add->next_update_index);\n \n \tstack_filename(&temp_tab_file_name, add->stack, next_name.buf);\n-\tstrbuf_addstr(&temp_tab_file_name, \".temp.XXXXXX\");\n+\treftable_buf_addstr(&temp_tab_file_name, \".temp.XXXXXX\");\n \n \ttab_file = mks_tempfile(temp_tab_file_name.buf);\n \tif (!tab_file) {\n@@ -894,7 +894,7 @@ int reftable_addition_add(struct reftable_addition *add,\n \t}\n \n \tformat_name(&next_name, wr->min_update_index, wr->max_update_index);\n-\tstrbuf_addstr(&next_name, \".ref\");\n+\treftable_buf_addstr(&next_name, \".ref\");\n \tstack_filename(&tab_file_name, add->stack, next_name.buf);\n \n \t/*\n@@ -913,13 +913,13 @@ int reftable_addition_add(struct reftable_addition *add,\n \t\terr = REFTABLE_OUT_OF_MEMORY_ERROR;\n \t\tgoto done;\n \t}\n-\tadd->new_tables[add->new_tables_len++] = strbuf_detach(&next_name, NULL);\n+\tadd->new_tables[add->new_tables_len++] = reftable_buf_detach(&next_name);\n \n done:\n \tdelete_tempfile(&tab_file);\n-\tstrbuf_release(&temp_tab_file_name);\n-\tstrbuf_release(&tab_file_name);\n-\tstrbuf_release(&next_name);\n+\treftable_buf_release(&temp_tab_file_name);\n+\treftable_buf_release(&tab_file_name);\n+\treftable_buf_release(&next_name);\n \treftable_writer_free(wr);\n \treturn err;\n }\n@@ -938,8 +938,8 @@ static int stack_compact_locked(struct reftable_stack *st,\n \t\t\t\tstruct reftable_log_expiry_config *config,\n \t\t\t\tstruct tempfile **tab_file_out)\n {\n-\tstruct strbuf next_name = STRBUF_INIT;\n-\tstruct strbuf tab_file_path = STRBUF_INIT;\n+\tstruct reftable_buf next_name = REFTABLE_BUF_INIT;\n+\tstruct reftable_buf tab_file_path = REFTABLE_BUF_INIT;\n \tstruct reftable_writer *wr = NULL;\n \tstruct tempfile *tab_file;\n \tint tab_fd, err = 0;\n@@ -948,7 +948,7 @@ static int stack_compact_locked(struct reftable_stack *st,\n \t\t    reftable_reader_min_update_index(st->readers[first]),\n \t\t    reftable_reader_max_update_index(st->readers[last]));\n \tstack_filename(&tab_file_path, st, next_name.buf);\n-\tstrbuf_addstr(&tab_file_path, \".temp.XXXXXX\");\n+\treftable_buf_addstr(&tab_file_path, \".temp.XXXXXX\");\n \n \ttab_file = mks_tempfile(tab_file_path.buf);\n \tif (!tab_file) {\n@@ -986,8 +986,8 @@ static int stack_compact_locked(struct reftable_stack *st,\n done:\n \tdelete_tempfile(&tab_file);\n \treftable_writer_free(wr);\n-\tstrbuf_release(&next_name);\n-\tstrbuf_release(&tab_file_path);\n+\treftable_buf_release(&next_name);\n+\treftable_buf_release(&tab_file_path);\n \treturn err;\n }\n \n@@ -1111,10 +1111,10 @@ static int stack_compact_range(struct reftable_stack *st,\n \t\t\t       struct reftable_log_expiry_config *expiry,\n \t\t\t       unsigned int flags)\n {\n-\tstruct strbuf tables_list_buf = STRBUF_INIT;\n-\tstruct strbuf new_table_name = STRBUF_INIT;\n-\tstruct strbuf new_table_path = STRBUF_INIT;\n-\tstruct strbuf table_name = STRBUF_INIT;\n+\tstruct reftable_buf tables_list_buf = REFTABLE_BUF_INIT;\n+\tstruct reftable_buf new_table_name = REFTABLE_BUF_INIT;\n+\tstruct reftable_buf new_table_path = REFTABLE_BUF_INIT;\n+\tstruct reftable_buf table_name = REFTABLE_BUF_INIT;\n \tstruct lock_file tables_list_lock = LOCK_INIT;\n \tstruct lock_file *table_locks = NULL;\n \tstruct tempfile *new_table = NULL;\n@@ -1372,7 +1372,7 @@ static int stack_compact_range(struct reftable_stack *st,\n \tif (!is_empty_table) {\n \t\tformat_name(&new_table_name, st->readers[first]->min_update_index,\n \t\t\t    st->readers[last]->max_update_index);\n-\t\tstrbuf_addstr(&new_table_name, \".ref\");\n+\t\treftable_buf_addstr(&new_table_name, \".ref\");\n \t\tstack_filename(&new_table_path, st, new_table_name.buf);\n \n \t\terr = rename_tempfile(&new_table, new_table_path.buf);\n@@ -1388,16 +1388,16 @@ static int stack_compact_range(struct reftable_stack *st,\n \t * simply skip writing it.\n \t */\n \tfor (i = 0; i < first_to_replace; i++) {\n-\t\tstrbuf_addstr(&tables_list_buf, names[i]);\n-\t\tstrbuf_addstr(&tables_list_buf, \"\\n\");\n+\t\treftable_buf_addstr(&tables_list_buf, names[i]);\n+\t\treftable_buf_addstr(&tables_list_buf, \"\\n\");\n \t}\n \tif (!is_empty_table) {\n-\t\tstrbuf_addstr(&tables_list_buf, new_table_name.buf);\n-\t\tstrbuf_addstr(&tables_list_buf, \"\\n\");\n+\t\treftable_buf_addstr(&tables_list_buf, new_table_name.buf);\n+\t\treftable_buf_addstr(&tables_list_buf, \"\\n\");\n \t}\n \tfor (i = last_to_replace + 1; names[i]; i++) {\n-\t\tstrbuf_addstr(&tables_list_buf, names[i]);\n-\t\tstrbuf_addstr(&tables_list_buf, \"\\n\");\n+\t\treftable_buf_addstr(&tables_list_buf, names[i]);\n+\t\treftable_buf_addstr(&tables_list_buf, \"\\n\");\n \t}\n \n \terr = write_in_full(get_lock_file_fd(&tables_list_lock),\n@@ -1449,10 +1449,10 @@ static int stack_compact_range(struct reftable_stack *st,\n \treftable_free(table_locks);\n \n \tdelete_tempfile(&new_table);\n-\tstrbuf_release(&new_table_name);\n-\tstrbuf_release(&new_table_path);\n-\tstrbuf_release(&tables_list_buf);\n-\tstrbuf_release(&table_name);\n+\treftable_buf_release(&new_table_name);\n+\treftable_buf_release(&new_table_path);\n+\treftable_buf_release(&tables_list_buf);\n+\treftable_buf_release(&table_name);\n \tfree_names(names);\n \n \tif (err == REFTABLE_LOCK_ERROR)\n@@ -1666,7 +1666,7 @@ static void remove_maybe_stale_table(struct reftable_stack *st, uint64_t max,\n \tuint64_t update_idx = 0;\n \tstruct reftable_block_source src = { NULL };\n \tstruct reftable_reader *rd = NULL;\n-\tstruct strbuf table_path = STRBUF_INIT;\n+\tstruct reftable_buf table_path = REFTABLE_BUF_INIT;\n \tstack_filename(&table_path, st, name);\n \n \terr = reftable_block_source_from_file(&src, table_path.buf);\n@@ -1684,7 +1684,7 @@ static void remove_maybe_stale_table(struct reftable_stack *st, uint64_t max,\n \t\tunlink(table_path.buf);\n \t}\n done:\n-\tstrbuf_release(&table_path);\n+\treftable_buf_release(&table_path);\n }\n \n static int reftable_stack_clean_locked(struct reftable_stack *st)\ndiff --git a/reftable/system.h b/reftable/system.h\nindex d0cabd5d171..5ec85833434 100644\n--- a/reftable/system.h\n+++ b/reftable/system.h\n@@ -13,7 +13,6 @@ license that can be found in the LICENSE file or at\n \n #include \"git-compat-util.h\"\n #include \"lockfile.h\"\n-#include \"strbuf.h\"\n #include \"tempfile.h\"\n #include \"hash.h\" /* hash ID, sizes.*/\n #include \"dir.h\" /* remove_dir_recursively, for tests.*/\ndiff --git a/reftable/writer.c b/reftable/writer.c\nindex 031d8149a9c..da6941a78ac 100644\n--- a/reftable/writer.c\n+++ b/reftable/writer.c\n@@ -115,7 +115,7 @@ static int writer_reinit_block_writer(struct reftable_writer *w, uint8_t typ)\n \tif (w->next == 0)\n \t\tblock_start = header_size(writer_version(w));\n \n-\tstrbuf_reset(&w->last_key);\n+\treftable_buf_reset(&w->last_key);\n \tret = block_writer_init(&w->block_writer_data, typ, w->block,\n \t\t\t\tw->opts.block_size, block_start,\n \t\t\t\thash_size(w->opts.hash_id));\n@@ -146,8 +146,8 @@ int reftable_writer_new(struct reftable_writer **out,\n \tif (opts.block_size >= (1 << 24))\n \t\tBUG(\"configured block size exceeds 16MB\");\n \n-\tstrbuf_init(&wp->block_writer_data.last_key, 0);\n-\tstrbuf_init(&wp->last_key, 0);\n+\treftable_buf_init(&wp->block_writer_data.last_key);\n+\treftable_buf_init(&wp->last_key);\n \tREFTABLE_CALLOC_ARRAY(wp->block, opts.block_size);\n \tif (!wp->block) {\n \t\treftable_free(wp);\n@@ -179,7 +179,7 @@ static void writer_release(struct reftable_writer *w)\n \t\tblock_writer_release(&w->block_writer_data);\n \t\tw->block_writer = NULL;\n \t\twriter_clear_index(w);\n-\t\tstrbuf_release(&w->last_key);\n+\t\treftable_buf_release(&w->last_key);\n \t}\n }\n \n@@ -190,7 +190,7 @@ void reftable_writer_free(struct reftable_writer *w)\n }\n \n struct obj_index_tree_node {\n-\tstruct strbuf hash;\n+\tstruct reftable_buf hash;\n \tuint64_t *offsets;\n \tsize_t offset_len;\n \tsize_t offset_cap;\n@@ -198,16 +198,16 @@ struct obj_index_tree_node {\n \n #define OBJ_INDEX_TREE_NODE_INIT    \\\n \t{                           \\\n-\t\t.hash = STRBUF_INIT \\\n+\t\t.hash = REFTABLE_BUF_INIT \\\n \t}\n \n static int obj_index_tree_node_compare(const void *a, const void *b)\n {\n-\treturn strbuf_cmp(&((const struct obj_index_tree_node *)a)->hash,\n+\treturn reftable_buf_cmp(&((const struct obj_index_tree_node *)a)->hash,\n \t\t\t  &((const struct obj_index_tree_node *)b)->hash);\n }\n \n-static int writer_index_hash(struct reftable_writer *w, struct strbuf *hash)\n+static int writer_index_hash(struct reftable_writer *w, struct reftable_buf *hash)\n {\n \tuint64_t off = w->next;\n \tstruct obj_index_tree_node want = { .hash = *hash };\n@@ -224,8 +224,8 @@ static int writer_index_hash(struct reftable_writer *w, struct strbuf *hash)\n \n \t\t*key = empty;\n \n-\t\tstrbuf_reset(&key->hash);\n-\t\tstrbuf_add(&key->hash, hash->buf, hash->len);\n+\t\treftable_buf_reset(&key->hash);\n+\t\treftable_buf_add(&key->hash, hash->buf, hash->len);\n \t\ttree_insert(&w->obj_index_tree, key,\n \t\t\t    &obj_index_tree_node_compare);\n \t} else {\n@@ -246,17 +246,17 @@ static int writer_index_hash(struct reftable_writer *w, struct strbuf *hash)\n static int writer_add_record(struct reftable_writer *w,\n \t\t\t     struct reftable_record *rec)\n {\n-\tstruct strbuf key = STRBUF_INIT;\n+\tstruct reftable_buf key = REFTABLE_BUF_INIT;\n \tint err;\n \n \treftable_record_key(rec, &key);\n-\tif (strbuf_cmp(&w->last_key, &key) >= 0) {\n+\tif (reftable_buf_cmp(&w->last_key, &key) >= 0) {\n \t\terr = REFTABLE_API_ERROR;\n \t\tgoto done;\n \t}\n \n-\tstrbuf_reset(&w->last_key);\n-\tstrbuf_add(&w->last_key, key.buf, key.len);\n+\treftable_buf_reset(&w->last_key);\n+\treftable_buf_add(&w->last_key, key.buf, key.len);\n \tif (!w->block_writer) {\n \t\terr = writer_reinit_block_writer(w, reftable_record_type(rec));\n \t\tif (err < 0)\n@@ -303,7 +303,7 @@ static int writer_add_record(struct reftable_writer *w,\n \t}\n \n done:\n-\tstrbuf_release(&key);\n+\treftable_buf_release(&key);\n \treturn err;\n }\n \n@@ -316,7 +316,7 @@ int reftable_writer_add_ref(struct reftable_writer *w,\n \t\t\t.ref = *ref\n \t\t},\n \t};\n-\tstruct strbuf buf = STRBUF_INIT;\n+\tstruct reftable_buf buf = REFTABLE_BUF_INIT;\n \tint err;\n \n \tif (!ref->refname ||\n@@ -331,7 +331,7 @@ int reftable_writer_add_ref(struct reftable_writer *w,\n \t\tgoto out;\n \n \tif (!w->opts.skip_index_objects && reftable_ref_record_val1(ref)) {\n-\t\tstrbuf_add(&buf, (char *)reftable_ref_record_val1(ref),\n+\t\treftable_buf_add(&buf, (char *)reftable_ref_record_val1(ref),\n \t\t\t   hash_size(w->opts.hash_id));\n \n \t\terr = writer_index_hash(w, &buf);\n@@ -340,8 +340,8 @@ int reftable_writer_add_ref(struct reftable_writer *w,\n \t}\n \n \tif (!w->opts.skip_index_objects && reftable_ref_record_val2(ref)) {\n-\t\tstrbuf_reset(&buf);\n-\t\tstrbuf_add(&buf, reftable_ref_record_val2(ref),\n+\t\treftable_buf_reset(&buf);\n+\t\treftable_buf_add(&buf, reftable_ref_record_val2(ref),\n \t\t\t   hash_size(w->opts.hash_id));\n \n \t\terr = writer_index_hash(w, &buf);\n@@ -352,7 +352,7 @@ int reftable_writer_add_ref(struct reftable_writer *w,\n \terr = 0;\n \n out:\n-\tstrbuf_release(&buf);\n+\treftable_buf_release(&buf);\n \treturn err;\n }\n \n@@ -393,7 +393,7 @@ int reftable_writer_add_log(struct reftable_writer *w,\n \t\t\t    struct reftable_log_record *log)\n {\n \tchar *input_log_message = NULL;\n-\tstruct strbuf cleaned_message = STRBUF_INIT;\n+\tstruct reftable_buf cleaned_message = REFTABLE_BUF_INIT;\n \tint err = 0;\n \n \tif (log->value_type == REFTABLE_LOG_DELETION)\n@@ -404,24 +404,24 @@ int reftable_writer_add_log(struct reftable_writer *w,\n \n \tinput_log_message = log->value.update.message;\n \tif (!w->opts.exact_log_message && log->value.update.message) {\n-\t\tstrbuf_addstr(&cleaned_message, log->value.update.message);\n+\t\treftable_buf_addstr(&cleaned_message, log->value.update.message);\n \t\twhile (cleaned_message.len &&\n \t\t       cleaned_message.buf[cleaned_message.len - 1] == '\\n')\n-\t\t\tstrbuf_setlen(&cleaned_message,\n+\t\t\treftable_buf_setlen(&cleaned_message,\n \t\t\t\t      cleaned_message.len - 1);\n \t\tif (strchr(cleaned_message.buf, '\\n')) {\n \t\t\t/* multiple lines not allowed. */\n \t\t\terr = REFTABLE_API_ERROR;\n \t\t\tgoto done;\n \t\t}\n-\t\tstrbuf_addstr(&cleaned_message, \"\\n\");\n+\t\treftable_buf_addstr(&cleaned_message, \"\\n\");\n \t\tlog->value.update.message = cleaned_message.buf;\n \t}\n \n \terr = reftable_writer_add_log_verbatim(w, log);\n \tlog->value.update.message = input_log_message;\n done:\n-\tstrbuf_release(&cleaned_message);\n+\treftable_buf_release(&cleaned_message);\n \treturn err;\n }\n \n@@ -504,7 +504,7 @@ static int writer_finish_section(struct reftable_writer *w)\n \t\t\treturn err;\n \n \t\tfor (i = 0; i < idx_len; i++)\n-\t\t\tstrbuf_release(&idx[i].last_key);\n+\t\t\treftable_buf_release(&idx[i].last_key);\n \t\treftable_free(idx);\n \t}\n \n@@ -521,13 +521,13 @@ static int writer_finish_section(struct reftable_writer *w)\n \tbstats->max_index_level = max_level;\n \n \t/* Reinit lastKey, as the next section can start with any key. */\n-\tstrbuf_reset(&w->last_key);\n+\treftable_buf_reset(&w->last_key);\n \n \treturn 0;\n }\n \n struct common_prefix_arg {\n-\tstruct strbuf *last;\n+\tstruct reftable_buf *last;\n \tint max;\n };\n \n@@ -594,7 +594,7 @@ static void object_record_free(void *void_arg UNUSED, void *key)\n \tstruct obj_index_tree_node *entry = key;\n \n \tREFTABLE_FREE_AND_NULL(entry->offsets);\n-\tstrbuf_release(&entry->hash);\n+\treftable_buf_release(&entry->hash);\n \treftable_free(entry);\n }\n \n@@ -708,7 +708,7 @@ int reftable_writer_close(struct reftable_writer *w)\n static void writer_clear_index(struct reftable_writer *w)\n {\n \tfor (size_t i = 0; w->index && i < w->index_len; i++)\n-\t\tstrbuf_release(&w->index[i].last_key);\n+\t\treftable_buf_release(&w->index[i].last_key);\n \tREFTABLE_FREE_AND_NULL(w->index);\n \tw->index_len = 0;\n \tw->index_cap = 0;\n@@ -717,7 +717,7 @@ static void writer_clear_index(struct reftable_writer *w)\n static int writer_flush_nonempty_block(struct reftable_writer *w)\n {\n \tstruct reftable_index_record index_record = {\n-\t\t.last_key = STRBUF_INIT,\n+\t\t.last_key = REFTABLE_BUF_INIT,\n \t};\n \tuint8_t typ = block_writer_type(w->block_writer);\n \tstruct reftable_block_stats *bstats;\n@@ -777,8 +777,8 @@ static int writer_flush_nonempty_block(struct reftable_writer *w)\n \t\treturn REFTABLE_OUT_OF_MEMORY_ERROR;\n \n \tindex_record.offset = w->next;\n-\tstrbuf_reset(&index_record.last_key);\n-\tstrbuf_add(&index_record.last_key, w->block_writer->last_key.buf,\n+\treftable_buf_reset(&index_record.last_key);\n+\treftable_buf_add(&index_record.last_key, w->block_writer->last_key.buf,\n \t\t   w->block_writer->last_key.len);\n \tw->index[w->index_len] = index_record;\n \tw->index_len++;\ndiff --git a/reftable/writer.h b/reftable/writer.h\nindex 8d0df9cc528..e8a6fbb7854 100644\n--- a/reftable/writer.h\n+++ b/reftable/writer.h\n@@ -19,7 +19,7 @@ struct reftable_writer {\n \tint (*flush)(void *);\n \tvoid *write_arg;\n \tint pending_padding;\n-\tstruct strbuf last_key;\n+\tstruct reftable_buf last_key;\n \n \t/* offset of next block to write. */\n \tuint64_t next;\ndiff --git a/t/unit-tests/lib-reftable.c b/t/unit-tests/lib-reftable.c\nindex 54c26c43e77..2ddf480588d 100644\n--- a/t/unit-tests/lib-reftable.c\n+++ b/t/unit-tests/lib-reftable.c\n@@ -19,7 +19,7 @@ static int strbuf_writer_flush(void *arg UNUSED)\n \treturn 0;\n }\n \n-struct reftable_writer *t_reftable_strbuf_writer(struct strbuf *buf,\n+struct reftable_writer *t_reftable_strbuf_writer(struct reftable_buf *buf,\n \t\t\t\t\t\t struct reftable_write_options *opts)\n {\n \tstruct reftable_writer *writer;\n@@ -29,7 +29,7 @@ struct reftable_writer *t_reftable_strbuf_writer(struct strbuf *buf,\n \treturn writer;\n }\n \n-void t_reftable_write_to_buf(struct strbuf *buf,\n+void t_reftable_write_to_buf(struct reftable_buf *buf,\n \t\t\t     struct reftable_ref_record *refs,\n \t\t\t     size_t nrefs,\n \t\t\t     struct reftable_log_record *logs,\ndiff --git a/t/unit-tests/lib-reftable.h b/t/unit-tests/lib-reftable.h\nindex d1154190847..d4950fed3da 100644\n--- a/t/unit-tests/lib-reftable.h\n+++ b/t/unit-tests/lib-reftable.h\n@@ -2,15 +2,16 @@\n #define LIB_REFTABLE_H\n \n #include \"git-compat-util.h\"\n-#include \"strbuf.h\"\n #include \"reftable/reftable-writer.h\"\n \n+struct reftable_buf;\n+\n void t_reftable_set_hash(uint8_t *p, int i, uint32_t id);\n \n-struct reftable_writer *t_reftable_strbuf_writer(struct strbuf *buf,\n+struct reftable_writer *t_reftable_strbuf_writer(struct reftable_buf *buf,\n \t\t\t\t\t\t struct reftable_write_options *opts);\n \n-void t_reftable_write_to_buf(struct strbuf *buf,\n+void t_reftable_write_to_buf(struct reftable_buf *buf,\n \t\t\t     struct reftable_ref_record *refs,\n \t\t\t     size_t nrecords,\n \t\t\t     struct reftable_log_record *logs,\ndiff --git a/t/unit-tests/t-reftable-basics.c b/t/unit-tests/t-reftable-basics.c\nindex 1fa77b6faff..a814e819756 100644\n--- a/t/unit-tests/t-reftable-basics.c\n+++ b/t/unit-tests/t-reftable-basics.c\n@@ -99,8 +99,8 @@ int cmd_main(int argc UNUSED, const char *argv[] UNUSED)\n \t}\n \n \tif_test (\"common_prefix_size works\") {\n-\t\tstruct strbuf a = STRBUF_INIT;\n-\t\tstruct strbuf b = STRBUF_INIT;\n+\t\tstruct reftable_buf a = REFTABLE_BUF_INIT;\n+\t\tstruct reftable_buf b = REFTABLE_BUF_INIT;\n \t\tstruct {\n \t\t\tconst char *a, *b;\n \t\t\tint want;\n@@ -113,14 +113,14 @@ int cmd_main(int argc UNUSED, const char *argv[] UNUSED)\n \t\t};\n \n \t\tfor (size_t i = 0; i < ARRAY_SIZE(cases); i++) {\n-\t\t\tstrbuf_addstr(&a, cases[i].a);\n-\t\t\tstrbuf_addstr(&b, cases[i].b);\n+\t\t\treftable_buf_addstr(&a, cases[i].a);\n+\t\t\treftable_buf_addstr(&b, cases[i].b);\n \t\t\tcheck_int(common_prefix_size(&a, &b), ==, cases[i].want);\n-\t\t\tstrbuf_reset(&a);\n-\t\t\tstrbuf_reset(&b);\n+\t\t\treftable_buf_reset(&a);\n+\t\t\treftable_buf_reset(&b);\n \t\t}\n-\t\tstrbuf_release(&a);\n-\t\tstrbuf_release(&b);\n+\t\treftable_buf_release(&a);\n+\t\treftable_buf_release(&b);\n \t}\n \n \tif_test (\"put_be24 and get_be24 work\") {\ndiff --git a/t/unit-tests/t-reftable-block.c b/t/unit-tests/t-reftable-block.c\nindex 8077bbc5e7a..56514b43630 100644\n--- a/t/unit-tests/t-reftable-block.c\n+++ b/t/unit-tests/t-reftable-block.c\n@@ -20,7 +20,7 @@ static void t_ref_block_read_write(void)\n \tconst size_t block_size = 1024;\n \tstruct reftable_block block = { 0 };\n \tstruct block_writer bw = {\n-\t\t.last_key = STRBUF_INIT,\n+\t\t.last_key = REFTABLE_BUF_INIT,\n \t};\n \tstruct reftable_record rec = {\n \t\t.type = BLOCK_TYPE_REF,\n@@ -29,7 +29,7 @@ static void t_ref_block_read_write(void)\n \tint ret;\n \tstruct block_reader br = { 0 };\n \tstruct block_iter it = BLOCK_ITER_INIT;\n-\tstruct strbuf want = STRBUF_INIT, buf = STRBUF_INIT;\n+\tstruct reftable_buf want = REFTABLE_BUF_INIT, buf = REFTABLE_BUF_INIT;\n \n \tREFTABLE_CALLOC_ARRAY(block.data, block_size);\n \tcheck(block.data != NULL);\n@@ -100,8 +100,8 @@ static void t_ref_block_read_write(void)\n \tblock_iter_close(&it);\n \treftable_record_release(&rec);\n \treftable_block_done(&br.block);\n-\tstrbuf_release(&want);\n-\tstrbuf_release(&buf);\n+\treftable_buf_release(&want);\n+\treftable_buf_release(&buf);\n \tfor (i = 0; i < N; i++)\n \t\treftable_record_release(&recs[i]);\n }\n@@ -114,7 +114,7 @@ static void t_log_block_read_write(void)\n \tconst size_t block_size = 2048;\n \tstruct reftable_block block = { 0 };\n \tstruct block_writer bw = {\n-\t\t.last_key = STRBUF_INIT,\n+\t\t.last_key = REFTABLE_BUF_INIT,\n \t};\n \tstruct reftable_record rec = {\n \t\t.type = BLOCK_TYPE_LOG,\n@@ -123,7 +123,7 @@ static void t_log_block_read_write(void)\n \tint ret;\n \tstruct block_reader br = { 0 };\n \tstruct block_iter it = BLOCK_ITER_INIT;\n-\tstruct strbuf want = STRBUF_INIT, buf = STRBUF_INIT;\n+\tstruct reftable_buf want = REFTABLE_BUF_INIT, buf = REFTABLE_BUF_INIT;\n \n \tREFTABLE_CALLOC_ARRAY(block.data, block_size);\n \tcheck(block.data != NULL);\n@@ -166,8 +166,8 @@ static void t_log_block_read_write(void)\n \n \tfor (i = 0; i < N; i++) {\n \t\tblock_iter_reset(&it);\n-\t\tstrbuf_reset(&want);\n-\t\tstrbuf_addstr(&want, recs[i].u.log.refname);\n+\t\treftable_buf_reset(&want);\n+\t\treftable_buf_addstr(&want, recs[i].u.log.refname);\n \n \t\tret = block_iter_seek_key(&it, &br, &want);\n \t\tcheck_int(ret, ==, 0);\n@@ -190,8 +190,8 @@ static void t_log_block_read_write(void)\n \tblock_iter_close(&it);\n \treftable_record_release(&rec);\n \treftable_block_done(&br.block);\n-\tstrbuf_release(&want);\n-\tstrbuf_release(&buf);\n+\treftable_buf_release(&want);\n+\treftable_buf_release(&buf);\n \tfor (i = 0; i < N; i++)\n \t\treftable_record_release(&recs[i]);\n }\n@@ -204,7 +204,7 @@ static void t_obj_block_read_write(void)\n \tconst size_t block_size = 1024;\n \tstruct reftable_block block = { 0 };\n \tstruct block_writer bw = {\n-\t\t.last_key = STRBUF_INIT,\n+\t\t.last_key = REFTABLE_BUF_INIT,\n \t};\n \tstruct reftable_record rec = {\n \t\t.type = BLOCK_TYPE_OBJ,\n@@ -213,7 +213,7 @@ static void t_obj_block_read_write(void)\n \tint ret;\n \tstruct block_reader br = { 0 };\n \tstruct block_iter it = BLOCK_ITER_INIT;\n-\tstruct strbuf want = STRBUF_INIT, buf = STRBUF_INIT;\n+\tstruct reftable_buf want = REFTABLE_BUF_INIT, buf = REFTABLE_BUF_INIT;\n \n \tREFTABLE_CALLOC_ARRAY(block.data, block_size);\n \tcheck(block.data != NULL);\n@@ -273,8 +273,8 @@ static void t_obj_block_read_write(void)\n \tblock_iter_close(&it);\n \treftable_record_release(&rec);\n \treftable_block_done(&br.block);\n-\tstrbuf_release(&want);\n-\tstrbuf_release(&buf);\n+\treftable_buf_release(&want);\n+\treftable_buf_release(&buf);\n \tfor (i = 0; i < N; i++)\n \t\treftable_record_release(&recs[i]);\n }\n@@ -287,17 +287,17 @@ static void t_index_block_read_write(void)\n \tconst size_t block_size = 1024;\n \tstruct reftable_block block = { 0 };\n \tstruct block_writer bw = {\n-\t\t.last_key = STRBUF_INIT,\n+\t\t.last_key = REFTABLE_BUF_INIT,\n \t};\n \tstruct reftable_record rec = {\n \t\t.type = BLOCK_TYPE_INDEX,\n-\t\t.u.idx.last_key = STRBUF_INIT,\n+\t\t.u.idx.last_key = REFTABLE_BUF_INIT,\n \t};\n \tsize_t i = 0;\n \tint ret;\n \tstruct block_reader br = { 0 };\n \tstruct block_iter it = BLOCK_ITER_INIT;\n-\tstruct strbuf want = STRBUF_INIT, buf = STRBUF_INIT;\n+\tstruct reftable_buf want = REFTABLE_BUF_INIT, buf = REFTABLE_BUF_INIT;\n \n \tREFTABLE_CALLOC_ARRAY(block.data, block_size);\n \tcheck(block.data != NULL);\n@@ -312,9 +312,9 @@ static void t_index_block_read_write(void)\n \n \t\tsnprintf(buf, sizeof(buf), \"branch%02\"PRIuMAX, (uintmax_t)i);\n \n-\t\tstrbuf_init(&recs[i].u.idx.last_key, 9);\n+\t\treftable_buf_init(&recs[i].u.idx.last_key);\n \t\trecs[i].type = BLOCK_TYPE_INDEX;\n-\t\tstrbuf_addstr(&recs[i].u.idx.last_key, buf);\n+\t\treftable_buf_addstr(&recs[i].u.idx.last_key, buf);\n \t\trecs[i].u.idx.offset = i;\n \n \t\tret = block_writer_add(&bw, &recs[i]);\n@@ -365,8 +365,8 @@ static void t_index_block_read_write(void)\n \tblock_iter_close(&it);\n \treftable_record_release(&rec);\n \treftable_block_done(&br.block);\n-\tstrbuf_release(&want);\n-\tstrbuf_release(&buf);\n+\treftable_buf_release(&want);\n+\treftable_buf_release(&buf);\n \tfor (i = 0; i < N; i++)\n \t\treftable_record_release(&recs[i]);\n }\ndiff --git a/t/unit-tests/t-reftable-merged.c b/t/unit-tests/t-reftable-merged.c\nindex 3c84363e980..9b0162a4b32 100644\n--- a/t/unit-tests/t-reftable-merged.c\n+++ b/t/unit-tests/t-reftable-merged.c\n@@ -20,7 +20,7 @@ static struct reftable_merged_table *\n merged_table_from_records(struct reftable_ref_record **refs,\n \t\t\t  struct reftable_block_source **source,\n \t\t\t  struct reftable_reader ***readers, const size_t *sizes,\n-\t\t\t  struct strbuf *buf, const size_t n)\n+\t\t\t  struct reftable_buf *buf, const size_t n)\n {\n \tstruct reftable_merged_table *mt = NULL;\n \tstruct reftable_write_options opts = {\n@@ -75,7 +75,7 @@ static void t_merged_single_record(void)\n \n \tstruct reftable_ref_record *refs[] = { r1, r2, r3 };\n \tsize_t sizes[] = { ARRAY_SIZE(r1), ARRAY_SIZE(r2), ARRAY_SIZE(r3) };\n-\tstruct strbuf bufs[3] = { STRBUF_INIT, STRBUF_INIT, STRBUF_INIT };\n+\tstruct reftable_buf bufs[3] = { REFTABLE_BUF_INIT, REFTABLE_BUF_INIT, REFTABLE_BUF_INIT };\n \tstruct reftable_block_source *bs = NULL;\n \tstruct reftable_reader **readers = NULL;\n \tstruct reftable_merged_table *mt =\n@@ -97,7 +97,7 @@ static void t_merged_single_record(void)\n \treaders_destroy(readers, 3);\n \treftable_merged_table_free(mt);\n \tfor (size_t i = 0; i < ARRAY_SIZE(bufs); i++)\n-\t\tstrbuf_release(&bufs[i]);\n+\t\treftable_buf_release(&bufs[i]);\n \treftable_free(bs);\n }\n \n@@ -152,7 +152,7 @@ static void t_merged_refs(void)\n \n \tstruct reftable_ref_record *refs[] = { r1, r2, r3 };\n \tsize_t sizes[3] = { ARRAY_SIZE(r1), ARRAY_SIZE(r2), ARRAY_SIZE(r3) };\n-\tstruct strbuf bufs[3] = { STRBUF_INIT, STRBUF_INIT, STRBUF_INIT };\n+\tstruct reftable_buf bufs[3] = { REFTABLE_BUF_INIT, REFTABLE_BUF_INIT, REFTABLE_BUF_INIT };\n \tstruct reftable_block_source *bs = NULL;\n \tstruct reftable_reader **readers = NULL;\n \tstruct reftable_merged_table *mt =\n@@ -192,7 +192,7 @@ static void t_merged_refs(void)\n \treftable_free(out);\n \n \tfor (i = 0; i < 3; i++)\n-\t\tstrbuf_release(&bufs[i]);\n+\t\treftable_buf_release(&bufs[i]);\n \treaders_destroy(readers, 3);\n \treftable_merged_table_free(mt);\n \treftable_free(bs);\n@@ -234,8 +234,8 @@ static void t_merged_seek_multiple_times(void)\n \tsize_t sizes[] = {\n \t\tARRAY_SIZE(r1), ARRAY_SIZE(r2),\n \t};\n-\tstruct strbuf bufs[] = {\n-\t\tSTRBUF_INIT, STRBUF_INIT,\n+\tstruct reftable_buf bufs[] = {\n+\t\tREFTABLE_BUF_INIT, REFTABLE_BUF_INIT,\n \t};\n \tstruct reftable_block_source *sources = NULL;\n \tstruct reftable_reader **readers = NULL;\n@@ -265,7 +265,7 @@ static void t_merged_seek_multiple_times(void)\n \t}\n \n \tfor (size_t i = 0; i < ARRAY_SIZE(bufs); i++)\n-\t\tstrbuf_release(&bufs[i]);\n+\t\treftable_buf_release(&bufs[i]);\n \treaders_destroy(readers, ARRAY_SIZE(refs));\n \treftable_ref_record_release(&rec);\n \treftable_iterator_destroy(&it);\n@@ -277,7 +277,7 @@ static struct reftable_merged_table *\n merged_table_from_log_records(struct reftable_log_record **logs,\n \t\t\t      struct reftable_block_source **source,\n \t\t\t      struct reftable_reader ***readers, const size_t *sizes,\n-\t\t\t      struct strbuf *buf, const size_t n)\n+\t\t\t      struct reftable_buf *buf, const size_t n)\n {\n \tstruct reftable_merged_table *mt = NULL;\n \tstruct reftable_write_options opts = {\n@@ -361,7 +361,7 @@ static void t_merged_logs(void)\n \n \tstruct reftable_log_record *logs[] = { r1, r2, r3 };\n \tsize_t sizes[3] = { ARRAY_SIZE(r1), ARRAY_SIZE(r2), ARRAY_SIZE(r3) };\n-\tstruct strbuf bufs[3] = { STRBUF_INIT, STRBUF_INIT, STRBUF_INIT };\n+\tstruct reftable_buf bufs[3] = { REFTABLE_BUF_INIT, REFTABLE_BUF_INIT, REFTABLE_BUF_INIT };\n \tstruct reftable_block_source *bs = NULL;\n \tstruct reftable_reader **readers = NULL;\n \tstruct reftable_merged_table *mt = merged_table_from_log_records(\n@@ -412,7 +412,7 @@ static void t_merged_logs(void)\n \treftable_free(out);\n \n \tfor (i = 0; i < 3; i++)\n-\t\tstrbuf_release(&bufs[i]);\n+\t\treftable_buf_release(&bufs[i]);\n \treaders_destroy(readers, 3);\n \treftable_merged_table_free(mt);\n \treftable_free(bs);\n@@ -421,7 +421,7 @@ static void t_merged_logs(void)\n static void t_default_write_opts(void)\n {\n \tstruct reftable_write_options opts = { 0 };\n-\tstruct strbuf buf = STRBUF_INIT;\n+\tstruct reftable_buf buf = REFTABLE_BUF_INIT;\n \tstruct reftable_writer *w = t_reftable_strbuf_writer(&buf, &opts);\n \tstruct reftable_ref_record rec = {\n \t\t.refname = (char *) \"master\",\n@@ -457,7 +457,7 @@ static void t_default_write_opts(void)\n \n \treftable_reader_decref(rd);\n \treftable_merged_table_free(merged);\n-\tstrbuf_release(&buf);\n+\treftable_buf_release(&buf);\n }\n \n \ndiff --git a/t/unit-tests/t-reftable-reader.c b/t/unit-tests/t-reftable-reader.c\nindex eea86966c0d..8a18d7f9be4 100644\n--- a/t/unit-tests/t-reftable-reader.c\n+++ b/t/unit-tests/t-reftable-reader.c\n@@ -16,7 +16,7 @@ static int t_reader_seek_once(void)\n \tstruct reftable_ref_record ref = { 0 };\n \tstruct reftable_iterator it = { 0 };\n \tstruct reftable_reader *reader;\n-\tstruct strbuf buf = STRBUF_INIT;\n+\tstruct reftable_buf buf = REFTABLE_BUF_INIT;\n \tint ret;\n \n \tt_reftable_write_to_buf(&buf, records, ARRAY_SIZE(records), NULL, 0, NULL);\n@@ -40,7 +40,7 @@ static int t_reader_seek_once(void)\n \treftable_ref_record_release(&ref);\n \treftable_iterator_destroy(&it);\n \treftable_reader_decref(reader);\n-\tstrbuf_release(&buf);\n+\treftable_buf_release(&buf);\n \treturn 0;\n }\n \n@@ -57,7 +57,7 @@ static int t_reader_reseek(void)\n \tstruct reftable_ref_record ref = { 0 };\n \tstruct reftable_iterator it = { 0 };\n \tstruct reftable_reader *reader;\n-\tstruct strbuf buf = STRBUF_INIT;\n+\tstruct reftable_buf buf = REFTABLE_BUF_INIT;\n \tint ret;\n \n \tt_reftable_write_to_buf(&buf, records, ARRAY_SIZE(records), NULL, 0, NULL);\n@@ -84,7 +84,7 @@ static int t_reader_reseek(void)\n \treftable_ref_record_release(&ref);\n \treftable_iterator_destroy(&it);\n \treftable_reader_decref(reader);\n-\tstrbuf_release(&buf);\n+\treftable_buf_release(&buf);\n \treturn 0;\n }\n \ndiff --git a/t/unit-tests/t-reftable-readwrite.c b/t/unit-tests/t-reftable-readwrite.c\nindex 5f59b0ad6ad..c56a33f1a1e 100644\n--- a/t/unit-tests/t-reftable-readwrite.c\n+++ b/t/unit-tests/t-reftable-readwrite.c\n@@ -18,12 +18,12 @@ static const int update_index = 5;\n \n static void t_buffer(void)\n {\n-\tstruct strbuf buf = STRBUF_INIT;\n+\tstruct reftable_buf buf = REFTABLE_BUF_INIT;\n \tstruct reftable_block_source source = { 0 };\n \tstruct reftable_block out = { 0 };\n \tint n;\n \tuint8_t in[] = \"hello\";\n-\tstrbuf_add(&buf, in, sizeof(in));\n+\treftable_buf_add(&buf, in, sizeof(in));\n \tblock_source_from_strbuf(&source, &buf);\n \tcheck_int(block_source_size(&source), ==, 6);\n \tn = block_source_read_block(&source, &out, 0, sizeof(in));\n@@ -37,10 +37,10 @@ static void t_buffer(void)\n \n \treftable_block_done(&out);\n \tblock_source_close(&source);\n-\tstrbuf_release(&buf);\n+\treftable_buf_release(&buf);\n }\n \n-static void write_table(char ***names, struct strbuf *buf, int N,\n+static void write_table(char ***names, struct reftable_buf *buf, int N,\n \t\t\tint block_size, uint32_t hash_id)\n {\n \tstruct reftable_write_options opts = {\n@@ -82,7 +82,7 @@ static void write_table(char ***names, struct strbuf *buf, int N,\n \n static void t_log_buffer_size(void)\n {\n-\tstruct strbuf buf = STRBUF_INIT;\n+\tstruct reftable_buf buf = REFTABLE_BUF_INIT;\n \tstruct reftable_write_options opts = {\n \t\t.block_size = 4096,\n \t};\n@@ -114,12 +114,12 @@ static void t_log_buffer_size(void)\n \terr = reftable_writer_close(w);\n \tcheck(!err);\n \treftable_writer_free(w);\n-\tstrbuf_release(&buf);\n+\treftable_buf_release(&buf);\n }\n \n static void t_log_overflow(void)\n {\n-\tstruct strbuf buf = STRBUF_INIT;\n+\tstruct reftable_buf buf = REFTABLE_BUF_INIT;\n \tchar msg[256] = { 0 };\n \tstruct reftable_write_options opts = {\n \t\t.block_size = ARRAY_SIZE(msg),\n@@ -148,7 +148,7 @@ static void t_log_overflow(void)\n \terr = reftable_writer_add_log(w, &log);\n \tcheck_int(err, ==, REFTABLE_ENTRY_TOO_BIG_ERROR);\n \treftable_writer_free(w);\n-\tstrbuf_release(&buf);\n+\treftable_buf_release(&buf);\n }\n \n static void t_log_write_read(void)\n@@ -161,7 +161,7 @@ static void t_log_write_read(void)\n \tstruct reftable_iterator it = { 0 };\n \tstruct reftable_reader *reader;\n \tstruct reftable_block_source source = { 0 };\n-\tstruct strbuf buf = STRBUF_INIT;\n+\tstruct reftable_buf buf = REFTABLE_BUF_INIT;\n \tstruct reftable_writer *w = t_reftable_strbuf_writer(&buf, &opts);\n \tconst struct reftable_stats *stats = NULL;\n \tint N = 2, err, i, n;\n@@ -247,7 +247,7 @@ static void t_log_write_read(void)\n \treftable_iterator_destroy(&it);\n \n \t/* cleanup. */\n-\tstrbuf_release(&buf);\n+\treftable_buf_release(&buf);\n \tfree_names(names);\n \treftable_reader_decref(reader);\n }\n@@ -260,7 +260,7 @@ static void t_log_zlib_corruption(void)\n \tstruct reftable_iterator it = { 0 };\n \tstruct reftable_reader *reader;\n \tstruct reftable_block_source source = { 0 };\n-\tstruct strbuf buf = STRBUF_INIT;\n+\tstruct reftable_buf buf = REFTABLE_BUF_INIT;\n \tstruct reftable_writer *w = t_reftable_strbuf_writer(&buf, &opts);\n \tconst struct reftable_stats *stats = NULL;\n \tchar message[100] = { 0 };\n@@ -312,13 +312,13 @@ static void t_log_zlib_corruption(void)\n \n \t/* cleanup. */\n \treftable_reader_decref(reader);\n-\tstrbuf_release(&buf);\n+\treftable_buf_release(&buf);\n }\n \n static void t_table_read_write_sequential(void)\n {\n \tchar **names;\n-\tstruct strbuf buf = STRBUF_INIT;\n+\tstruct reftable_buf buf = REFTABLE_BUF_INIT;\n \tint N = 50;\n \tstruct reftable_iterator it = { 0 };\n \tstruct reftable_block_source source = { 0 };\n@@ -352,25 +352,25 @@ static void t_table_read_write_sequential(void)\n \n \treftable_iterator_destroy(&it);\n \treftable_reader_decref(reader);\n-\tstrbuf_release(&buf);\n+\treftable_buf_release(&buf);\n \tfree_names(names);\n }\n \n static void t_table_write_small_table(void)\n {\n \tchar **names;\n-\tstruct strbuf buf = STRBUF_INIT;\n+\tstruct reftable_buf buf = REFTABLE_BUF_INIT;\n \tint N = 1;\n \twrite_table(&names, &buf, N, 4096, GIT_SHA1_FORMAT_ID);\n \tcheck_int(buf.len, <, 200);\n-\tstrbuf_release(&buf);\n+\treftable_buf_release(&buf);\n \tfree_names(names);\n }\n \n static void t_table_read_api(void)\n {\n \tchar **names;\n-\tstruct strbuf buf = STRBUF_INIT;\n+\tstruct reftable_buf buf = REFTABLE_BUF_INIT;\n \tint N = 50;\n \tstruct reftable_reader *reader;\n \tstruct reftable_block_source source = { 0 };\n@@ -393,17 +393,17 @@ static void t_table_read_api(void)\n \terr = reftable_iterator_next_log(&it, &log);\n \tcheck_int(err, ==, REFTABLE_API_ERROR);\n \n-\tstrbuf_release(&buf);\n+\treftable_buf_release(&buf);\n \tfree_names(names);\n \treftable_iterator_destroy(&it);\n \treftable_reader_decref(reader);\n-\tstrbuf_release(&buf);\n+\treftable_buf_release(&buf);\n }\n \n static void t_table_read_write_seek(int index, int hash_id)\n {\n \tchar **names;\n-\tstruct strbuf buf = STRBUF_INIT;\n+\tstruct reftable_buf buf = REFTABLE_BUF_INIT;\n \tint N = 50;\n \tstruct reftable_reader *reader;\n \tstruct reftable_block_source source = { 0 };\n@@ -411,7 +411,7 @@ static void t_table_read_write_seek(int index, int hash_id)\n \tint i = 0;\n \n \tstruct reftable_iterator it = { 0 };\n-\tstruct strbuf pastLast = STRBUF_INIT;\n+\tstruct reftable_buf pastLast = REFTABLE_BUF_INIT;\n \tstruct reftable_ref_record ref = { 0 };\n \n \twrite_table(&names, &buf, N, 256, hash_id);\n@@ -443,8 +443,8 @@ static void t_table_read_write_seek(int index, int hash_id)\n \t\treftable_iterator_destroy(&it);\n \t}\n \n-\tstrbuf_addstr(&pastLast, names[N - 1]);\n-\tstrbuf_addstr(&pastLast, \"/\");\n+\treftable_buf_addstr(&pastLast, names[N - 1]);\n+\treftable_buf_addstr(&pastLast, \"/\");\n \n \terr = reftable_reader_init_ref_iterator(reader, &it);\n \tcheck(!err);\n@@ -457,10 +457,10 @@ static void t_table_read_write_seek(int index, int hash_id)\n \t\tcheck_int(err, >, 0);\n \t}\n \n-\tstrbuf_release(&pastLast);\n+\treftable_buf_release(&pastLast);\n \treftable_iterator_destroy(&it);\n \n-\tstrbuf_release(&buf);\n+\treftable_buf_release(&buf);\n \tfree_names(names);\n \treftable_reader_decref(reader);\n }\n@@ -492,7 +492,7 @@ static void t_table_refs_for(int indexed)\n \tstruct reftable_ref_record ref = { 0 };\n \tstruct reftable_reader *reader;\n \tstruct reftable_block_source source = { 0 };\n-\tstruct strbuf buf = STRBUF_INIT;\n+\tstruct reftable_buf buf = REFTABLE_BUF_INIT;\n \tstruct reftable_writer *w = t_reftable_strbuf_writer(&buf, &opts);\n \tstruct reftable_iterator it = { 0 };\n \tint N = 50, n, j, err, i;\n@@ -565,7 +565,7 @@ static void t_table_refs_for(int indexed)\n \t}\n \tcheck_int(j, ==, want_names_len);\n \n-\tstrbuf_release(&buf);\n+\treftable_buf_release(&buf);\n \tfree_names(want_names);\n \treftable_iterator_destroy(&it);\n \treftable_reader_decref(reader);\n@@ -584,7 +584,7 @@ static void t_table_refs_for_obj_index(void)\n static void t_write_empty_table(void)\n {\n \tstruct reftable_write_options opts = { 0 };\n-\tstruct strbuf buf = STRBUF_INIT;\n+\tstruct reftable_buf buf = REFTABLE_BUF_INIT;\n \tstruct reftable_writer *w = t_reftable_strbuf_writer(&buf, &opts);\n \tstruct reftable_block_source source = { 0 };\n \tstruct reftable_reader *rd = NULL;\n@@ -615,7 +615,7 @@ static void t_write_empty_table(void)\n \n \treftable_iterator_destroy(&it);\n \treftable_reader_decref(rd);\n-\tstrbuf_release(&buf);\n+\treftable_buf_release(&buf);\n }\n \n static void t_write_object_id_min_length(void)\n@@ -623,7 +623,7 @@ static void t_write_object_id_min_length(void)\n \tstruct reftable_write_options opts = {\n \t\t.block_size = 75,\n \t};\n-\tstruct strbuf buf = STRBUF_INIT;\n+\tstruct reftable_buf buf = REFTABLE_BUF_INIT;\n \tstruct reftable_writer *w = t_reftable_strbuf_writer(&buf, &opts);\n \tstruct reftable_ref_record ref = {\n \t\t.update_index = 1,\n@@ -649,7 +649,7 @@ static void t_write_object_id_min_length(void)\n \tcheck(!err);\n \tcheck_int(reftable_writer_stats(w)->object_id_len, ==, 2);\n \treftable_writer_free(w);\n-\tstrbuf_release(&buf);\n+\treftable_buf_release(&buf);\n }\n \n static void t_write_object_id_length(void)\n@@ -657,7 +657,7 @@ static void t_write_object_id_length(void)\n \tstruct reftable_write_options opts = {\n \t\t.block_size = 75,\n \t};\n-\tstruct strbuf buf = STRBUF_INIT;\n+\tstruct reftable_buf buf = REFTABLE_BUF_INIT;\n \tstruct reftable_writer *w = t_reftable_strbuf_writer(&buf, &opts);\n \tstruct reftable_ref_record ref = {\n \t\t.update_index = 1,\n@@ -684,13 +684,13 @@ static void t_write_object_id_length(void)\n \tcheck(!err);\n \tcheck_int(reftable_writer_stats(w)->object_id_len, ==, 16);\n \treftable_writer_free(w);\n-\tstrbuf_release(&buf);\n+\treftable_buf_release(&buf);\n }\n \n static void t_write_empty_key(void)\n {\n \tstruct reftable_write_options opts = { 0 };\n-\tstruct strbuf buf = STRBUF_INIT;\n+\tstruct reftable_buf buf = REFTABLE_BUF_INIT;\n \tstruct reftable_writer *w = t_reftable_strbuf_writer(&buf, &opts);\n \tstruct reftable_ref_record ref = {\n \t\t.refname = (char *) \"\",\n@@ -706,13 +706,13 @@ static void t_write_empty_key(void)\n \terr = reftable_writer_close(w);\n \tcheck_int(err, ==, REFTABLE_EMPTY_TABLE_ERROR);\n \treftable_writer_free(w);\n-\tstrbuf_release(&buf);\n+\treftable_buf_release(&buf);\n }\n \n static void t_write_key_order(void)\n {\n \tstruct reftable_write_options opts = { 0 };\n-\tstruct strbuf buf = STRBUF_INIT;\n+\tstruct reftable_buf buf = REFTABLE_BUF_INIT;\n \tstruct reftable_writer *w = t_reftable_strbuf_writer(&buf, &opts);\n \tstruct reftable_ref_record refs[2] = {\n \t\t{\n@@ -745,7 +745,7 @@ static void t_write_key_order(void)\n \n \treftable_writer_close(w);\n \treftable_writer_free(w);\n-\tstrbuf_release(&buf);\n+\treftable_buf_release(&buf);\n }\n \n static void t_write_multiple_indices(void)\n@@ -753,7 +753,7 @@ static void t_write_multiple_indices(void)\n \tstruct reftable_write_options opts = {\n \t\t.block_size = 100,\n \t};\n-\tstruct strbuf writer_buf = STRBUF_INIT;\n+\tstruct reftable_buf writer_buf = REFTABLE_BUF_INIT;\n \tstruct reftable_block_source source = { 0 };\n \tstruct reftable_iterator it = { 0 };\n \tconst struct reftable_stats *stats;\n@@ -822,7 +822,7 @@ static void t_write_multiple_indices(void)\n \treftable_iterator_destroy(&it);\n \treftable_writer_free(writer);\n \treftable_reader_decref(reader);\n-\tstrbuf_release(&writer_buf);\n+\treftable_buf_release(&writer_buf);\n }\n \n static void t_write_multi_level_index(void)\n@@ -830,7 +830,7 @@ static void t_write_multi_level_index(void)\n \tstruct reftable_write_options opts = {\n \t\t.block_size = 100,\n \t};\n-\tstruct strbuf writer_buf = STRBUF_INIT, buf = STRBUF_INIT;\n+\tstruct reftable_buf writer_buf = REFTABLE_BUF_INIT, buf = REFTABLE_BUF_INIT;\n \tstruct reftable_block_source source = { 0 };\n \tstruct reftable_iterator it = { 0 };\n \tconst struct reftable_stats *stats;\n@@ -878,13 +878,13 @@ static void t_write_multi_level_index(void)\n \treftable_iterator_destroy(&it);\n \treftable_writer_free(writer);\n \treftable_reader_decref(reader);\n-\tstrbuf_release(&writer_buf);\n-\tstrbuf_release(&buf);\n+\treftable_buf_release(&writer_buf);\n+\treftable_buf_release(&buf);\n }\n \n static void t_corrupt_table_empty(void)\n {\n-\tstruct strbuf buf = STRBUF_INIT;\n+\tstruct reftable_buf buf = REFTABLE_BUF_INIT;\n \tstruct reftable_block_source source = { 0 };\n \tstruct reftable_reader *reader;\n \tint err;\n@@ -897,17 +897,17 @@ static void t_corrupt_table_empty(void)\n static void t_corrupt_table(void)\n {\n \tuint8_t zeros[1024] = { 0 };\n-\tstruct strbuf buf = STRBUF_INIT;\n+\tstruct reftable_buf buf = REFTABLE_BUF_INIT;\n \tstruct reftable_block_source source = { 0 };\n \tstruct reftable_reader *reader;\n \tint err;\n-\tstrbuf_add(&buf, zeros, sizeof(zeros));\n+\treftable_buf_add(&buf, zeros, sizeof(zeros));\n \n \tblock_source_from_strbuf(&source, &buf);\n \terr = reftable_reader_new(&reader, &source, \"file.log\");\n \tcheck_int(err, ==, REFTABLE_FORMAT_ERROR);\n \n-\tstrbuf_release(&buf);\n+\treftable_buf_release(&buf);\n }\n \n int cmd_main(int argc UNUSED, const char *argv[] UNUSED)\ndiff --git a/t/unit-tests/t-reftable-record.c b/t/unit-tests/t-reftable-record.c\nindex a7f67d4d9f2..f2dd01688f3 100644\n--- a/t/unit-tests/t-reftable-record.c\n+++ b/t/unit-tests/t-reftable-record.c\n@@ -116,7 +116,7 @@ static void t_reftable_ref_record_compare_name(void)\n \n static void t_reftable_ref_record_roundtrip(void)\n {\n-\tstruct strbuf scratch = STRBUF_INIT;\n+\tstruct reftable_buf scratch = REFTABLE_BUF_INIT;\n \n \tfor (int i = REFTABLE_REF_DELETION; i < REFTABLE_NR_REF_VALUETYPES; i++) {\n \t\tstruct reftable_record in = {\n@@ -124,7 +124,7 @@ static void t_reftable_ref_record_roundtrip(void)\n \t\t\t.u.ref.value_type = i,\n \t\t};\n \t\tstruct reftable_record out = { .type = BLOCK_TYPE_REF };\n-\t\tstruct strbuf key = STRBUF_INIT;\n+\t\tstruct reftable_buf key = REFTABLE_BUF_INIT;\n \t\tuint8_t buffer[1024] = { 0 };\n \t\tstruct string_view dest = {\n \t\t\t.buf = buffer,\n@@ -166,11 +166,11 @@ static void t_reftable_ref_record_roundtrip(void)\n \t\t\t\t\t\t GIT_SHA1_RAWSZ));\n \t\treftable_record_release(&in);\n \n-\t\tstrbuf_release(&key);\n+\t\treftable_buf_release(&key);\n \t\treftable_record_release(&out);\n \t}\n \n-\tstrbuf_release(&scratch);\n+\treftable_buf_release(&scratch);\n }\n \n static void t_reftable_log_record_comparison(void)\n@@ -262,7 +262,7 @@ static void t_reftable_log_record_roundtrip(void)\n \t\t\t.value_type = REFTABLE_LOG_UPDATE,\n \t\t}\n \t};\n-\tstruct strbuf scratch = STRBUF_INIT;\n+\tstruct reftable_buf scratch = REFTABLE_BUF_INIT;\n \tset_hash(in[0].value.update.new_hash, 1);\n \tset_hash(in[0].value.update.old_hash, 2);\n \tset_hash(in[2].value.update.new_hash, 3);\n@@ -274,7 +274,7 @@ static void t_reftable_log_record_roundtrip(void)\n \n \tfor (size_t i = 0; i < ARRAY_SIZE(in); i++) {\n \t\tstruct reftable_record rec = { .type = BLOCK_TYPE_LOG };\n-\t\tstruct strbuf key = STRBUF_INIT;\n+\t\tstruct reftable_buf key = REFTABLE_BUF_INIT;\n \t\tuint8_t buffer[1024] = { 0 };\n \t\tstruct string_view dest = {\n \t\t\t.buf = buffer,\n@@ -313,11 +313,11 @@ static void t_reftable_log_record_roundtrip(void)\n \t\tcheck(reftable_log_record_equal(&in[i], &out.u.log,\n \t\t\t\t\t\t GIT_SHA1_RAWSZ));\n \t\treftable_log_record_release(&in[i]);\n-\t\tstrbuf_release(&key);\n+\t\treftable_buf_release(&key);\n \t\treftable_record_release(&out);\n \t}\n \n-\tstrbuf_release(&scratch);\n+\treftable_buf_release(&scratch);\n }\n \n static void t_key_roundtrip(void)\n@@ -327,30 +327,30 @@ static void t_key_roundtrip(void)\n \t\t.buf = buffer,\n \t\t.len = sizeof(buffer),\n \t};\n-\tstruct strbuf last_key = STRBUF_INIT;\n-\tstruct strbuf key = STRBUF_INIT;\n-\tstruct strbuf roundtrip = STRBUF_INIT;\n+\tstruct reftable_buf last_key = REFTABLE_BUF_INIT;\n+\tstruct reftable_buf key = REFTABLE_BUF_INIT;\n+\tstruct reftable_buf roundtrip = REFTABLE_BUF_INIT;\n \tint restart;\n \tuint8_t extra;\n \tint n, m;\n \tuint8_t rt_extra;\n \n-\tstrbuf_addstr(&last_key, \"refs/heads/master\");\n-\tstrbuf_addstr(&key, \"refs/tags/bla\");\n+\treftable_buf_addstr(&last_key, \"refs/heads/master\");\n+\treftable_buf_addstr(&key, \"refs/tags/bla\");\n \textra = 6;\n \tn = reftable_encode_key(&restart, dest, last_key, key, extra);\n \tcheck(!restart);\n \tcheck_int(n, >, 0);\n \n-\tstrbuf_addstr(&roundtrip, \"refs/heads/master\");\n+\treftable_buf_addstr(&roundtrip, \"refs/heads/master\");\n \tm = reftable_decode_key(&roundtrip, &rt_extra, dest);\n \tcheck_int(n, ==, m);\n-\tcheck(!strbuf_cmp(&key, &roundtrip));\n+\tcheck(!reftable_buf_cmp(&key, &roundtrip));\n \tcheck_int(rt_extra, ==, extra);\n \n-\tstrbuf_release(&last_key);\n-\tstrbuf_release(&key);\n-\tstrbuf_release(&roundtrip);\n+\treftable_buf_release(&last_key);\n+\treftable_buf_release(&key);\n+\treftable_buf_release(&roundtrip);\n }\n \n static void t_reftable_obj_record_comparison(void)\n@@ -413,7 +413,7 @@ static void t_reftable_obj_record_roundtrip(void)\n \t\t\t.hash_prefix_len = 5,\n \t\t},\n \t};\n-\tstruct strbuf scratch = STRBUF_INIT;\n+\tstruct reftable_buf scratch = REFTABLE_BUF_INIT;\n \n \tfor (size_t i = 0; i < ARRAY_SIZE(recs); i++) {\n \t\tuint8_t buffer[1024] = { 0 };\n@@ -427,7 +427,7 @@ static void t_reftable_obj_record_roundtrip(void)\n \t\t\t\t.obj = recs[i],\n \t\t\t},\n \t\t};\n-\t\tstruct strbuf key = STRBUF_INIT;\n+\t\tstruct reftable_buf key = REFTABLE_BUF_INIT;\n \t\tstruct reftable_record out = { .type = BLOCK_TYPE_OBJ };\n \t\tint n, m;\n \t\tuint8_t extra;\n@@ -443,11 +443,11 @@ static void t_reftable_obj_record_roundtrip(void)\n \t\tcheck_int(n, ==, m);\n \n \t\tcheck(reftable_record_equal(&in, &out, GIT_SHA1_RAWSZ));\n-\t\tstrbuf_release(&key);\n+\t\treftable_buf_release(&key);\n \t\treftable_record_release(&out);\n \t}\n \n-\tstrbuf_release(&scratch);\n+\treftable_buf_release(&scratch);\n }\n \n static void t_reftable_index_record_comparison(void)\n@@ -456,22 +456,22 @@ static void t_reftable_index_record_comparison(void)\n \t\t{\n \t\t\t.type = BLOCK_TYPE_INDEX,\n \t\t\t.u.idx.offset = 22,\n-\t\t\t.u.idx.last_key = STRBUF_INIT,\n+\t\t\t.u.idx.last_key = REFTABLE_BUF_INIT,\n \t\t},\n \t\t{\n \t\t\t.type = BLOCK_TYPE_INDEX,\n \t\t\t.u.idx.offset = 32,\n-\t\t\t.u.idx.last_key = STRBUF_INIT,\n+\t\t\t.u.idx.last_key = REFTABLE_BUF_INIT,\n \t\t},\n \t\t{\n \t\t\t.type = BLOCK_TYPE_INDEX,\n \t\t\t.u.idx.offset = 32,\n-\t\t\t.u.idx.last_key = STRBUF_INIT,\n+\t\t\t.u.idx.last_key = REFTABLE_BUF_INIT,\n \t\t},\n \t};\n-\tstrbuf_addstr(&in[0].u.idx.last_key, \"refs/heads/master\");\n-\tstrbuf_addstr(&in[1].u.idx.last_key, \"refs/heads/master\");\n-\tstrbuf_addstr(&in[2].u.idx.last_key, \"refs/heads/branch\");\n+\treftable_buf_addstr(&in[0].u.idx.last_key, \"refs/heads/master\");\n+\treftable_buf_addstr(&in[1].u.idx.last_key, \"refs/heads/master\");\n+\treftable_buf_addstr(&in[2].u.idx.last_key, \"refs/heads/branch\");\n \n \tcheck(!reftable_record_equal(&in[0], &in[1], GIT_SHA1_RAWSZ));\n \tcheck(!reftable_record_cmp(&in[0], &in[1]));\n@@ -493,7 +493,7 @@ static void t_reftable_index_record_roundtrip(void)\n \t\t.type = BLOCK_TYPE_INDEX,\n \t\t.u.idx = {\n \t\t\t.offset = 42,\n-\t\t\t.last_key = STRBUF_INIT,\n+\t\t\t.last_key = REFTABLE_BUF_INIT,\n \t\t},\n \t};\n \tuint8_t buffer[1024] = { 0 };\n@@ -501,21 +501,21 @@ static void t_reftable_index_record_roundtrip(void)\n \t\t.buf = buffer,\n \t\t.len = sizeof(buffer),\n \t};\n-\tstruct strbuf scratch = STRBUF_INIT;\n-\tstruct strbuf key = STRBUF_INIT;\n+\tstruct reftable_buf scratch = REFTABLE_BUF_INIT;\n+\tstruct reftable_buf key = REFTABLE_BUF_INIT;\n \tstruct reftable_record out = {\n \t\t.type = BLOCK_TYPE_INDEX,\n-\t\t.u.idx = { .last_key = STRBUF_INIT },\n+\t\t.u.idx = { .last_key = REFTABLE_BUF_INIT },\n \t};\n \tint n, m;\n \tuint8_t extra;\n \n-\tstrbuf_addstr(&in.u.idx.last_key, \"refs/heads/master\");\n+\treftable_buf_addstr(&in.u.idx.last_key, \"refs/heads/master\");\n \treftable_record_key(&in, &key);\n \tt_copy(&in);\n \n \tcheck(!reftable_record_is_deletion(&in));\n-\tcheck(!strbuf_cmp(&key, &in.u.idx.last_key));\n+\tcheck(!reftable_buf_cmp(&key, &in.u.idx.last_key));\n \tn = reftable_record_encode(&in, dest, GIT_SHA1_RAWSZ);\n \tcheck_int(n, >, 0);\n \n@@ -527,9 +527,9 @@ static void t_reftable_index_record_roundtrip(void)\n \tcheck(reftable_record_equal(&in, &out, GIT_SHA1_RAWSZ));\n \n \treftable_record_release(&out);\n-\tstrbuf_release(&key);\n-\tstrbuf_release(&scratch);\n-\tstrbuf_release(&in.u.idx.last_key);\n+\treftable_buf_release(&key);\n+\treftable_buf_release(&scratch);\n+\treftable_buf_release(&in.u.idx.last_key);\n }\n \n int cmd_main(int argc UNUSED, const char *argv[] UNUSED)\ndiff --git a/t/unit-tests/t-reftable-stack.c b/t/unit-tests/t-reftable-stack.c\nindex b56ea774312..f49856270d6 100644\n--- a/t/unit-tests/t-reftable-stack.c\n+++ b/t/unit-tests/t-reftable-stack.c\n@@ -16,7 +16,7 @@ license that can be found in the LICENSE file or at\n \n static void clear_dir(const char *dirname)\n {\n-\tstruct strbuf path = STRBUF_INIT;\n+\tstruct strbuf path = REFTABLE_BUF_INIT;\n \tstrbuf_addstr(&path, dirname);\n \tremove_dir_recursively(&path, 0);\n \tstrbuf_release(&path);\n@@ -145,7 +145,7 @@ static int write_test_log(struct reftable_writer *wr, void *arg)\n static void t_reftable_stack_add_one(void)\n {\n \tchar *dir = get_tmp_dir(__LINE__);\n-\tstruct strbuf scratch = STRBUF_INIT;\n+\tstruct reftable_buf scratch = REFTABLE_BUF_INIT;\n \tint mask = umask(002);\n \tstruct reftable_write_options opts = {\n \t\t.default_permissions = 0660,\n@@ -172,17 +172,17 @@ static void t_reftable_stack_add_one(void)\n \tcheck_int(st->readers_len, >, 0);\n \n #ifndef GIT_WINDOWS_NATIVE\n-\tstrbuf_addstr(&scratch, dir);\n-\tstrbuf_addstr(&scratch, \"/tables.list\");\n+\treftable_buf_addstr(&scratch, dir);\n+\treftable_buf_addstr(&scratch, \"/tables.list\");\n \terr = stat(scratch.buf, &stat_result);\n \tcheck(!err);\n \tcheck_int((stat_result.st_mode & 0777), ==, opts.default_permissions);\n \n-\tstrbuf_reset(&scratch);\n-\tstrbuf_addstr(&scratch, dir);\n-\tstrbuf_addstr(&scratch, \"/\");\n+\treftable_buf_reset(&scratch);\n+\treftable_buf_addstr(&scratch, dir);\n+\treftable_buf_addstr(&scratch, \"/\");\n \t/* do not try at home; not an external API for reftable. */\n-\tstrbuf_addstr(&scratch, st->readers[0]->name);\n+\treftable_buf_addstr(&scratch, st->readers[0]->name);\n \terr = stat(scratch.buf, &stat_result);\n \tcheck(!err);\n \tcheck_int((stat_result.st_mode & 0777), ==, opts.default_permissions);\n@@ -192,7 +192,7 @@ static void t_reftable_stack_add_one(void)\n \n \treftable_ref_record_release(&dest);\n \treftable_stack_destroy(st);\n-\tstrbuf_release(&scratch);\n+\treftable_buf_release(&scratch);\n \tclear_dir(dir);\n \tumask(mask);\n }\n@@ -414,7 +414,7 @@ static void t_reftable_stack_auto_compaction_fails_gracefully(void)\n \t};\n \tstruct reftable_write_options opts = { 0 };\n \tstruct reftable_stack *st;\n-\tstruct strbuf table_path = STRBUF_INIT;\n+\tstruct reftable_buf table_path = REFTABLE_BUF_INIT;\n \tchar *dir = get_tmp_dir(__LINE__);\n \tint err;\n \n@@ -432,10 +432,10 @@ static void t_reftable_stack_auto_compaction_fails_gracefully(void)\n \t * Adding a new table to the stack should not be impacted by this, even\n \t * though auto-compaction will now fail.\n \t */\n-\tstrbuf_addstr(&table_path, dir);\n-\tstrbuf_addstr(&table_path, \"/\");\n-\tstrbuf_addstr(&table_path, st->readers[0]->name);\n-\tstrbuf_addstr(&table_path, \".lock\");\n+\treftable_buf_addstr(&table_path, dir);\n+\treftable_buf_addstr(&table_path, \"/\");\n+\treftable_buf_addstr(&table_path, st->readers[0]->name);\n+\treftable_buf_addstr(&table_path, \".lock\");\n \twrite_file_buf(table_path.buf, \"\", 0);\n \n \tref.update_index = 2;\n@@ -446,7 +446,7 @@ static void t_reftable_stack_auto_compaction_fails_gracefully(void)\n \tcheck_int(st->stats.failures, ==, 1);\n \n \treftable_stack_destroy(st);\n-\tstrbuf_release(&table_path);\n+\treftable_buf_release(&table_path);\n \tclear_dir(dir);\n }\n \n@@ -516,7 +516,7 @@ static void t_reftable_stack_add(void)\n \tchar *dir = get_tmp_dir(__LINE__);\n \tstruct reftable_ref_record refs[2] = { 0 };\n \tstruct reftable_log_record logs[2] = { 0 };\n-\tstruct strbuf path = STRBUF_INIT;\n+\tstruct reftable_buf path = REFTABLE_BUF_INIT;\n \tstruct stat stat_result;\n \tsize_t i, N = ARRAY_SIZE(refs);\n \n@@ -575,17 +575,17 @@ static void t_reftable_stack_add(void)\n \t}\n \n #ifndef GIT_WINDOWS_NATIVE\n-\tstrbuf_addstr(&path, dir);\n-\tstrbuf_addstr(&path, \"/tables.list\");\n+\treftable_buf_addstr(&path, dir);\n+\treftable_buf_addstr(&path, \"/tables.list\");\n \terr = stat(path.buf, &stat_result);\n \tcheck(!err);\n \tcheck_int((stat_result.st_mode & 0777), ==, opts.default_permissions);\n \n-\tstrbuf_reset(&path);\n-\tstrbuf_addstr(&path, dir);\n-\tstrbuf_addstr(&path, \"/\");\n+\treftable_buf_reset(&path);\n+\treftable_buf_addstr(&path, dir);\n+\treftable_buf_addstr(&path, \"/\");\n \t/* do not try at home; not an external API for reftable. */\n-\tstrbuf_addstr(&path, st->readers[0]->name);\n+\treftable_buf_addstr(&path, st->readers[0]->name);\n \terr = stat(path.buf, &stat_result);\n \tcheck(!err);\n \tcheck_int((stat_result.st_mode & 0777), ==, opts.default_permissions);\n@@ -599,7 +599,7 @@ static void t_reftable_stack_add(void)\n \t\treftable_ref_record_release(&refs[i]);\n \t\treftable_log_record_release(&logs[i]);\n \t}\n-\tstrbuf_release(&path);\n+\treftable_buf_release(&path);\n \tclear_dir(dir);\n }\n \n@@ -1063,7 +1063,7 @@ static void t_reftable_stack_auto_compaction_with_locked_tables(void)\n \t\t.disable_auto_compact = 1,\n \t};\n \tstruct reftable_stack *st = NULL;\n-\tstruct strbuf buf = STRBUF_INIT;\n+\tstruct reftable_buf buf = REFTABLE_BUF_INIT;\n \tchar *dir = get_tmp_dir(__LINE__);\n \tint err;\n \n@@ -1078,10 +1078,10 @@ static void t_reftable_stack_auto_compaction_with_locked_tables(void)\n \t * size, we expect that auto-compaction will want to compact all of the\n \t * tables. Locking any of the tables will keep it from doing so.\n \t */\n-\tstrbuf_addstr(&buf, dir);\n-\tstrbuf_addstr(&buf, \"/\");\n-\tstrbuf_addstr(&buf, st->readers[2]->name);\n-\tstrbuf_addstr(&buf, \".lock\");\n+\treftable_buf_addstr(&buf, dir);\n+\treftable_buf_addstr(&buf, \"/\");\n+\treftable_buf_addstr(&buf, st->readers[2]->name);\n+\treftable_buf_addstr(&buf, \".lock\");\n \twrite_file_buf(buf.buf, \"\", 0);\n \n \t/*\n@@ -1096,7 +1096,7 @@ static void t_reftable_stack_auto_compaction_with_locked_tables(void)\n \tcheck_int(st->merged->readers_len, ==, 4);\n \n \treftable_stack_destroy(st);\n-\tstrbuf_release(&buf);\n+\treftable_buf_release(&buf);\n \tclear_dir(dir);\n }\n \n@@ -1153,7 +1153,7 @@ static void t_reftable_stack_compaction_with_locked_tables(void)\n \t\t.disable_auto_compact = 1,\n \t};\n \tstruct reftable_stack *st = NULL;\n-\tstruct strbuf buf = STRBUF_INIT;\n+\tstruct reftable_buf buf = REFTABLE_BUF_INIT;\n \tchar *dir = get_tmp_dir(__LINE__);\n \tint err;\n \n@@ -1164,10 +1164,10 @@ static void t_reftable_stack_compaction_with_locked_tables(void)\n \tcheck_int(st->merged->readers_len, ==, 3);\n \n \t/* Lock one of the tables that we're about to compact. */\n-\tstrbuf_addstr(&buf, dir);\n-\tstrbuf_addstr(&buf, \"/\");\n-\tstrbuf_addstr(&buf, st->readers[1]->name);\n-\tstrbuf_addstr(&buf, \".lock\");\n+\treftable_buf_addstr(&buf, dir);\n+\treftable_buf_addstr(&buf, \"/\");\n+\treftable_buf_addstr(&buf, st->readers[1]->name);\n+\treftable_buf_addstr(&buf, \".lock\");\n \twrite_file_buf(buf.buf, \"\", 0);\n \n \t/*\n@@ -1180,7 +1180,7 @@ static void t_reftable_stack_compaction_with_locked_tables(void)\n \tcheck_int(st->merged->readers_len, ==, 3);\n \n \treftable_stack_destroy(st);\n-\tstrbuf_release(&buf);\n+\treftable_buf_release(&buf);\n \tclear_dir(dir);\n }\n \n@@ -1306,7 +1306,7 @@ static void t_reftable_stack_reload_with_missing_table(void)\n \tstruct reftable_stack *st = NULL;\n \tstruct reftable_ref_record rec = { 0 };\n \tstruct reftable_iterator it = { 0 };\n-\tstruct strbuf table_path = STRBUF_INIT, content = STRBUF_INIT;\n+\tstruct reftable_buf table_path = REFTABLE_BUF_INIT, content = REFTABLE_BUF_INIT;\n \tchar *dir = get_tmp_dir(__LINE__);\n \tint err;\n \n@@ -1324,13 +1324,13 @@ static void t_reftable_stack_reload_with_missing_table(void)\n \t * our old readers. This should trigger a partial reload of the stack,\n \t * where we try to reuse our old readers.\n \t*/\n-\tstrbuf_addstr(&content, st->readers[0]->name);\n-\tstrbuf_addstr(&content, \"\\n\");\n-\tstrbuf_addstr(&content, st->readers[1]->name);\n-\tstrbuf_addstr(&content, \"\\n\");\n-\tstrbuf_addstr(&content, \"garbage\\n\");\n-\tstrbuf_addstr(&table_path, st->list_file);\n-\tstrbuf_addstr(&table_path, \".lock\");\n+\treftable_buf_addstr(&content, st->readers[0]->name);\n+\treftable_buf_addstr(&content, \"\\n\");\n+\treftable_buf_addstr(&content, st->readers[1]->name);\n+\treftable_buf_addstr(&content, \"\\n\");\n+\treftable_buf_addstr(&content, \"garbage\\n\");\n+\treftable_buf_addstr(&table_path, st->list_file);\n+\treftable_buf_addstr(&table_path, \".lock\");\n \twrite_file_buf(table_path.buf, content.buf, content.len);\n \terr = rename(table_path.buf, st->list_file);\n \tcheck(!err);\n@@ -1355,8 +1355,8 @@ static void t_reftable_stack_reload_with_missing_table(void)\n \treftable_ref_record_release(&rec);\n \treftable_iterator_destroy(&it);\n \treftable_stack_destroy(st);\n-\tstrbuf_release(&table_path);\n-\tstrbuf_release(&content);\n+\treftable_buf_release(&table_path);\n+\treftable_buf_release(&content);\n \tclear_dir(dir);\n }\n \n-- \n2.47.0.dirty\n\n"},{"id":"504808","messageId":"da432d7a38468bc7d7420693d5dd894bcfcb7c41.1728629612.git.ps@pks.im","threadId":"62313","inReplyTo":"cover.1728629612.git.ps@pks.im","subject":"[PATCH 05/10] reftable/blocksource: adapt interface name","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-10-11T06:54:24Z","receivedAt":"2024-10-11T06:54:27Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"Adapt the name of the `strbuf` block source to no longer relate to this\ninterface, but instead to the `reftable_buf` interface.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n reftable/blocksource.c              | 26 +++++++++++++-------------\n reftable/blocksource.h              |  4 ++--\n t/unit-tests/t-reftable-block.c     |  8 ++++----\n t/unit-tests/t-reftable-merged.c    |  6 +++---\n t/unit-tests/t-reftable-reader.c    |  4 ++--\n t/unit-tests/t-reftable-readwrite.c | 24 ++++++++++++------------\n 6 files changed, 36 insertions(+), 36 deletions(-)\n\ndiff --git a/reftable/blocksource.c b/reftable/blocksource.c\nindex d6242d67900..52e0915a67b 100644\n--- a/reftable/blocksource.c\n+++ b/reftable/blocksource.c\n@@ -13,19 +13,19 @@ license that can be found in the LICENSE file or at\n #include \"reftable-blocksource.h\"\n #include \"reftable-error.h\"\n \n-static void strbuf_return_block(void *b UNUSED, struct reftable_block *dest)\n+static void reftable_buf_return_block(void *b UNUSED, struct reftable_block *dest)\n {\n \tif (dest->len)\n \t\tmemset(dest->data, 0xff, dest->len);\n \treftable_free(dest->data);\n }\n \n-static void strbuf_close(void *b UNUSED)\n+static void reftable_buf_close(void *b UNUSED)\n {\n }\n \n-static int strbuf_read_block(void *v, struct reftable_block *dest, uint64_t off,\n-\t\t\t     uint32_t size)\n+static int reftable_buf_read_block(void *v, struct reftable_block *dest,\n+\t\t\t\t   uint64_t off, uint32_t size)\n {\n \tstruct reftable_buf *b = v;\n \tassert(off + size <= b->len);\n@@ -37,23 +37,23 @@ static int strbuf_read_block(void *v, struct reftable_block *dest, uint64_t off,\n \treturn size;\n }\n \n-static uint64_t strbuf_size(void *b)\n+static uint64_t reftable_buf_size(void *b)\n {\n \treturn ((struct reftable_buf *)b)->len;\n }\n \n-static struct reftable_block_source_vtable strbuf_vtable = {\n-\t.size = &strbuf_size,\n-\t.read_block = &strbuf_read_block,\n-\t.return_block = &strbuf_return_block,\n-\t.close = &strbuf_close,\n+static struct reftable_block_source_vtable reftable_buf_vtable = {\n+\t.size = &reftable_buf_size,\n+\t.read_block = &reftable_buf_read_block,\n+\t.return_block = &reftable_buf_return_block,\n+\t.close = &reftable_buf_close,\n };\n \n-void block_source_from_strbuf(struct reftable_block_source *bs,\n-\t\t\t      struct reftable_buf *buf)\n+void block_source_from_buf(struct reftable_block_source *bs,\n+\t\t\t   struct reftable_buf *buf)\n {\n \tassert(!bs->ops);\n-\tbs->ops = &strbuf_vtable;\n+\tbs->ops = &reftable_buf_vtable;\n \tbs->arg = buf;\n }\n \ndiff --git a/reftable/blocksource.h b/reftable/blocksource.h\nindex ee3647c6531..a84a3ccd891 100644\n--- a/reftable/blocksource.h\n+++ b/reftable/blocksource.h\n@@ -15,7 +15,7 @@ struct reftable_block_source;\n struct reftable_buf;\n \n /* Create an in-memory block source for reading reftables */\n-void block_source_from_strbuf(struct reftable_block_source *bs,\n-\t\t\t      struct reftable_buf *buf);\n+void block_source_from_buf(struct reftable_block_source *bs,\n+\t\t\t   struct reftable_buf *buf);\n \n #endif\ndiff --git a/t/unit-tests/t-reftable-block.c b/t/unit-tests/t-reftable-block.c\nindex 56514b43630..df1d45fe8e4 100644\n--- a/t/unit-tests/t-reftable-block.c\n+++ b/t/unit-tests/t-reftable-block.c\n@@ -34,7 +34,7 @@ static void t_ref_block_read_write(void)\n \tREFTABLE_CALLOC_ARRAY(block.data, block_size);\n \tcheck(block.data != NULL);\n \tblock.len = block_size;\n-\tblock_source_from_strbuf(&block.source ,&buf);\n+\tblock_source_from_buf(&block.source ,&buf);\n \tret = block_writer_init(&bw, BLOCK_TYPE_REF, block.data, block_size,\n \t\t\t\theader_off, hash_size(GIT_SHA1_FORMAT_ID));\n \tcheck(!ret);\n@@ -128,7 +128,7 @@ static void t_log_block_read_write(void)\n \tREFTABLE_CALLOC_ARRAY(block.data, block_size);\n \tcheck(block.data != NULL);\n \tblock.len = block_size;\n-\tblock_source_from_strbuf(&block.source ,&buf);\n+\tblock_source_from_buf(&block.source ,&buf);\n \tret = block_writer_init(&bw, BLOCK_TYPE_LOG, block.data, block_size,\n \t\t\t\theader_off, hash_size(GIT_SHA1_FORMAT_ID));\n \tcheck(!ret);\n@@ -218,7 +218,7 @@ static void t_obj_block_read_write(void)\n \tREFTABLE_CALLOC_ARRAY(block.data, block_size);\n \tcheck(block.data != NULL);\n \tblock.len = block_size;\n-\tblock_source_from_strbuf(&block.source, &buf);\n+\tblock_source_from_buf(&block.source, &buf);\n \tret = block_writer_init(&bw, BLOCK_TYPE_OBJ, block.data, block_size,\n \t\t\t\theader_off, hash_size(GIT_SHA1_FORMAT_ID));\n \tcheck(!ret);\n@@ -302,7 +302,7 @@ static void t_index_block_read_write(void)\n \tREFTABLE_CALLOC_ARRAY(block.data, block_size);\n \tcheck(block.data != NULL);\n \tblock.len = block_size;\n-\tblock_source_from_strbuf(&block.source, &buf);\n+\tblock_source_from_buf(&block.source, &buf);\n \tret = block_writer_init(&bw, BLOCK_TYPE_INDEX, block.data, block_size,\n \t\t\t\theader_off, hash_size(GIT_SHA1_FORMAT_ID));\n \tcheck(!ret);\ndiff --git a/t/unit-tests/t-reftable-merged.c b/t/unit-tests/t-reftable-merged.c\nindex 9b0162a4b32..484c18251f3 100644\n--- a/t/unit-tests/t-reftable-merged.c\n+++ b/t/unit-tests/t-reftable-merged.c\n@@ -35,7 +35,7 @@ merged_table_from_records(struct reftable_ref_record **refs,\n \n \tfor (size_t i = 0; i < n; i++) {\n \t\tt_reftable_write_to_buf(&buf[i], refs[i], sizes[i], NULL, 0, &opts);\n-\t\tblock_source_from_strbuf(&(*source)[i], &buf[i]);\n+\t\tblock_source_from_buf(&(*source)[i], &buf[i]);\n \n \t\terr = reftable_reader_new(&(*readers)[i], &(*source)[i],\n \t\t\t\t\t  \"name\");\n@@ -293,7 +293,7 @@ merged_table_from_log_records(struct reftable_log_record **logs,\n \n \tfor (size_t i = 0; i < n; i++) {\n \t\tt_reftable_write_to_buf(&buf[i], NULL, 0, logs[i], sizes[i], &opts);\n-\t\tblock_source_from_strbuf(&(*source)[i], &buf[i]);\n+\t\tblock_source_from_buf(&(*source)[i], &buf[i]);\n \n \t\terr = reftable_reader_new(&(*readers)[i], &(*source)[i],\n \t\t\t\t\t  \"name\");\n@@ -442,7 +442,7 @@ static void t_default_write_opts(void)\n \tcheck(!err);\n \treftable_writer_free(w);\n \n-\tblock_source_from_strbuf(&source, &buf);\n+\tblock_source_from_buf(&source, &buf);\n \n \terr = reftable_reader_new(&rd, &source, \"filename\");\n \tcheck(!err);\ndiff --git a/t/unit-tests/t-reftable-reader.c b/t/unit-tests/t-reftable-reader.c\nindex 8a18d7f9be4..19cb53b6415 100644\n--- a/t/unit-tests/t-reftable-reader.c\n+++ b/t/unit-tests/t-reftable-reader.c\n@@ -20,7 +20,7 @@ static int t_reader_seek_once(void)\n \tint ret;\n \n \tt_reftable_write_to_buf(&buf, records, ARRAY_SIZE(records), NULL, 0, NULL);\n-\tblock_source_from_strbuf(&source, &buf);\n+\tblock_source_from_buf(&source, &buf);\n \n \tret = reftable_reader_new(&reader, &source, \"name\");\n \tcheck(!ret);\n@@ -61,7 +61,7 @@ static int t_reader_reseek(void)\n \tint ret;\n \n \tt_reftable_write_to_buf(&buf, records, ARRAY_SIZE(records), NULL, 0, NULL);\n-\tblock_source_from_strbuf(&source, &buf);\n+\tblock_source_from_buf(&source, &buf);\n \n \tret = reftable_reader_new(&reader, &source, \"name\");\n \tcheck(!ret);\ndiff --git a/t/unit-tests/t-reftable-readwrite.c b/t/unit-tests/t-reftable-readwrite.c\nindex c56a33f1a1e..7c7c72bb162 100644\n--- a/t/unit-tests/t-reftable-readwrite.c\n+++ b/t/unit-tests/t-reftable-readwrite.c\n@@ -24,7 +24,7 @@ static void t_buffer(void)\n \tint n;\n \tuint8_t in[] = \"hello\";\n \treftable_buf_add(&buf, in, sizeof(in));\n-\tblock_source_from_strbuf(&source, &buf);\n+\tblock_source_from_buf(&source, &buf);\n \tcheck_int(block_source_size(&source), ==, 6);\n \tn = block_source_read_block(&source, &out, 0, sizeof(in));\n \tcheck_int(n, ==, sizeof(in));\n@@ -207,7 +207,7 @@ static void t_log_write_read(void)\n \treftable_writer_free(w);\n \tw = NULL;\n \n-\tblock_source_from_strbuf(&source, &buf);\n+\tblock_source_from_buf(&source, &buf);\n \n \terr = reftable_reader_new(&reader, &source, \"file.log\");\n \tcheck(!err);\n@@ -298,7 +298,7 @@ static void t_log_zlib_corruption(void)\n \t/* corrupt the data. */\n \tbuf.buf[50] ^= 0x99;\n \n-\tblock_source_from_strbuf(&source, &buf);\n+\tblock_source_from_buf(&source, &buf);\n \n \terr = reftable_reader_new(&reader, &source, \"file.log\");\n \tcheck(!err);\n@@ -328,7 +328,7 @@ static void t_table_read_write_sequential(void)\n \n \twrite_table(&names, &buf, N, 256, GIT_SHA1_FORMAT_ID);\n \n-\tblock_source_from_strbuf(&source, &buf);\n+\tblock_source_from_buf(&source, &buf);\n \n \terr = reftable_reader_new(&reader, &source, \"file.ref\");\n \tcheck(!err);\n@@ -380,7 +380,7 @@ static void t_table_read_api(void)\n \n \twrite_table(&names, &buf, N, 256, GIT_SHA1_FORMAT_ID);\n \n-\tblock_source_from_strbuf(&source, &buf);\n+\tblock_source_from_buf(&source, &buf);\n \n \terr = reftable_reader_new(&reader, &source, \"file.ref\");\n \tcheck(!err);\n@@ -416,7 +416,7 @@ static void t_table_read_write_seek(int index, int hash_id)\n \n \twrite_table(&names, &buf, N, 256, hash_id);\n \n-\tblock_source_from_strbuf(&source, &buf);\n+\tblock_source_from_buf(&source, &buf);\n \n \terr = reftable_reader_new(&reader, &source, \"file.ref\");\n \tcheck(!err);\n@@ -538,7 +538,7 @@ static void t_table_refs_for(int indexed)\n \treftable_writer_free(w);\n \tw = NULL;\n \n-\tblock_source_from_strbuf(&source, &buf);\n+\tblock_source_from_buf(&source, &buf);\n \n \terr = reftable_reader_new(&reader, &source, \"file.ref\");\n \tcheck(!err);\n@@ -600,7 +600,7 @@ static void t_write_empty_table(void)\n \n \tcheck_int(buf.len, ==, header_size(1) + footer_size(1));\n \n-\tblock_source_from_strbuf(&source, &buf);\n+\tblock_source_from_buf(&source, &buf);\n \n \terr = reftable_reader_new(&rd, &source, \"filename\");\n \tcheck(!err);\n@@ -806,7 +806,7 @@ static void t_write_multiple_indices(void)\n \tcheck_int(stats->obj_stats.index_offset, >, 0);\n \tcheck_int(stats->log_stats.index_offset, >, 0);\n \n-\tblock_source_from_strbuf(&source, &writer_buf);\n+\tblock_source_from_buf(&source, &writer_buf);\n \terr = reftable_reader_new(&reader, &source, \"filename\");\n \tcheck(!err);\n \n@@ -863,7 +863,7 @@ static void t_write_multi_level_index(void)\n \tstats = reftable_writer_stats(writer);\n \tcheck_int(stats->ref_stats.max_index_level, ==, 2);\n \n-\tblock_source_from_strbuf(&source, &writer_buf);\n+\tblock_source_from_buf(&source, &writer_buf);\n \terr = reftable_reader_new(&reader, &source, \"filename\");\n \tcheck(!err);\n \n@@ -889,7 +889,7 @@ static void t_corrupt_table_empty(void)\n \tstruct reftable_reader *reader;\n \tint err;\n \n-\tblock_source_from_strbuf(&source, &buf);\n+\tblock_source_from_buf(&source, &buf);\n \terr = reftable_reader_new(&reader, &source, \"file.log\");\n \tcheck_int(err, ==, REFTABLE_FORMAT_ERROR);\n }\n@@ -903,7 +903,7 @@ static void t_corrupt_table(void)\n \tint err;\n \treftable_buf_add(&buf, zeros, sizeof(zeros));\n \n-\tblock_source_from_strbuf(&source, &buf);\n+\tblock_source_from_buf(&source, &buf);\n \terr = reftable_reader_new(&reader, &source, \"file.log\");\n \tcheck_int(err, ==, REFTABLE_FORMAT_ERROR);\n \n-- \n2.47.0.dirty\n\n"},{"id":"504809","messageId":"797e435ed2e2e6e074e960714de6b5eee2b53340.1728629612.git.ps@pks.im","threadId":"62313","inReplyTo":"cover.1728629612.git.ps@pks.im","subject":"[PATCH 06/10] t/unit-tests: check for `reftable_buf` allocation errors","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-10-11T06:54:27Z","receivedAt":"2024-10-11T06:54:30Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"Adapt our unit tests to check for allocations errors.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n t/unit-tests/t-reftable-basics.c    |  4 +-\n t/unit-tests/t-reftable-block.c     |  4 +-\n t/unit-tests/t-reftable-readwrite.c |  8 ++--\n t/unit-tests/t-reftable-record.c    | 14 +++----\n t/unit-tests/t-reftable-stack.c     | 58 ++++++++++++++---------------\n 5 files changed, 44 insertions(+), 44 deletions(-)\n\ndiff --git a/t/unit-tests/t-reftable-basics.c b/t/unit-tests/t-reftable-basics.c\nindex a814e819756..a329f552025 100644\n--- a/t/unit-tests/t-reftable-basics.c\n+++ b/t/unit-tests/t-reftable-basics.c\n@@ -113,8 +113,8 @@ int cmd_main(int argc UNUSED, const char *argv[] UNUSED)\n \t\t};\n \n \t\tfor (size_t i = 0; i < ARRAY_SIZE(cases); i++) {\n-\t\t\treftable_buf_addstr(&a, cases[i].a);\n-\t\t\treftable_buf_addstr(&b, cases[i].b);\n+\t\t\tcheck(!reftable_buf_addstr(&a, cases[i].a));\n+\t\t\tcheck(!reftable_buf_addstr(&b, cases[i].b));\n \t\t\tcheck_int(common_prefix_size(&a, &b), ==, cases[i].want);\n \t\t\treftable_buf_reset(&a);\n \t\t\treftable_buf_reset(&b);\ndiff --git a/t/unit-tests/t-reftable-block.c b/t/unit-tests/t-reftable-block.c\nindex df1d45fe8e4..f9af907117b 100644\n--- a/t/unit-tests/t-reftable-block.c\n+++ b/t/unit-tests/t-reftable-block.c\n@@ -167,7 +167,7 @@ static void t_log_block_read_write(void)\n \tfor (i = 0; i < N; i++) {\n \t\tblock_iter_reset(&it);\n \t\treftable_buf_reset(&want);\n-\t\treftable_buf_addstr(&want, recs[i].u.log.refname);\n+\t\tcheck(!reftable_buf_addstr(&want, recs[i].u.log.refname));\n \n \t\tret = block_iter_seek_key(&it, &br, &want);\n \t\tcheck_int(ret, ==, 0);\n@@ -314,7 +314,7 @@ static void t_index_block_read_write(void)\n \n \t\treftable_buf_init(&recs[i].u.idx.last_key);\n \t\trecs[i].type = BLOCK_TYPE_INDEX;\n-\t\treftable_buf_addstr(&recs[i].u.idx.last_key, buf);\n+\t\tcheck(!reftable_buf_addstr(&recs[i].u.idx.last_key, buf));\n \t\trecs[i].u.idx.offset = i;\n \n \t\tret = block_writer_add(&bw, &recs[i]);\ndiff --git a/t/unit-tests/t-reftable-readwrite.c b/t/unit-tests/t-reftable-readwrite.c\nindex 7c7c72bb162..d279b86df0a 100644\n--- a/t/unit-tests/t-reftable-readwrite.c\n+++ b/t/unit-tests/t-reftable-readwrite.c\n@@ -23,7 +23,7 @@ static void t_buffer(void)\n \tstruct reftable_block out = { 0 };\n \tint n;\n \tuint8_t in[] = \"hello\";\n-\treftable_buf_add(&buf, in, sizeof(in));\n+\tcheck(!reftable_buf_add(&buf, in, sizeof(in)));\n \tblock_source_from_buf(&source, &buf);\n \tcheck_int(block_source_size(&source), ==, 6);\n \tn = block_source_read_block(&source, &out, 0, sizeof(in));\n@@ -443,8 +443,8 @@ static void t_table_read_write_seek(int index, int hash_id)\n \t\treftable_iterator_destroy(&it);\n \t}\n \n-\treftable_buf_addstr(&pastLast, names[N - 1]);\n-\treftable_buf_addstr(&pastLast, \"/\");\n+\tcheck(!reftable_buf_addstr(&pastLast, names[N - 1]));\n+\tcheck(!reftable_buf_addstr(&pastLast, \"/\"));\n \n \terr = reftable_reader_init_ref_iterator(reader, &it);\n \tcheck(!err);\n@@ -901,7 +901,7 @@ static void t_corrupt_table(void)\n \tstruct reftable_block_source source = { 0 };\n \tstruct reftable_reader *reader;\n \tint err;\n-\treftable_buf_add(&buf, zeros, sizeof(zeros));\n+\tcheck(!reftable_buf_add(&buf, zeros, sizeof(zeros)));\n \n \tblock_source_from_buf(&source, &buf);\n \terr = reftable_reader_new(&reader, &source, \"file.log\");\ndiff --git a/t/unit-tests/t-reftable-record.c b/t/unit-tests/t-reftable-record.c\nindex f2dd01688f3..eb98bf2da91 100644\n--- a/t/unit-tests/t-reftable-record.c\n+++ b/t/unit-tests/t-reftable-record.c\n@@ -335,14 +335,14 @@ static void t_key_roundtrip(void)\n \tint n, m;\n \tuint8_t rt_extra;\n \n-\treftable_buf_addstr(&last_key, \"refs/heads/master\");\n-\treftable_buf_addstr(&key, \"refs/tags/bla\");\n+\tcheck(!reftable_buf_addstr(&last_key, \"refs/heads/master\"));\n+\tcheck(!reftable_buf_addstr(&key, \"refs/tags/bla\"));\n \textra = 6;\n \tn = reftable_encode_key(&restart, dest, last_key, key, extra);\n \tcheck(!restart);\n \tcheck_int(n, >, 0);\n \n-\treftable_buf_addstr(&roundtrip, \"refs/heads/master\");\n+\tcheck(!reftable_buf_addstr(&roundtrip, \"refs/heads/master\"));\n \tm = reftable_decode_key(&roundtrip, &rt_extra, dest);\n \tcheck_int(n, ==, m);\n \tcheck(!reftable_buf_cmp(&key, &roundtrip));\n@@ -469,9 +469,9 @@ static void t_reftable_index_record_comparison(void)\n \t\t\t.u.idx.last_key = REFTABLE_BUF_INIT,\n \t\t},\n \t};\n-\treftable_buf_addstr(&in[0].u.idx.last_key, \"refs/heads/master\");\n-\treftable_buf_addstr(&in[1].u.idx.last_key, \"refs/heads/master\");\n-\treftable_buf_addstr(&in[2].u.idx.last_key, \"refs/heads/branch\");\n+\tcheck(!reftable_buf_addstr(&in[0].u.idx.last_key, \"refs/heads/master\"));\n+\tcheck(!reftable_buf_addstr(&in[1].u.idx.last_key, \"refs/heads/master\"));\n+\tcheck(!reftable_buf_addstr(&in[2].u.idx.last_key, \"refs/heads/branch\"));\n \n \tcheck(!reftable_record_equal(&in[0], &in[1], GIT_SHA1_RAWSZ));\n \tcheck(!reftable_record_cmp(&in[0], &in[1]));\n@@ -510,7 +510,7 @@ static void t_reftable_index_record_roundtrip(void)\n \tint n, m;\n \tuint8_t extra;\n \n-\treftable_buf_addstr(&in.u.idx.last_key, \"refs/heads/master\");\n+\tcheck(!reftable_buf_addstr(&in.u.idx.last_key, \"refs/heads/master\"));\n \treftable_record_key(&in, &key);\n \tt_copy(&in);\n \ndiff --git a/t/unit-tests/t-reftable-stack.c b/t/unit-tests/t-reftable-stack.c\nindex f49856270d6..72f6747064f 100644\n--- a/t/unit-tests/t-reftable-stack.c\n+++ b/t/unit-tests/t-reftable-stack.c\n@@ -172,17 +172,17 @@ static void t_reftable_stack_add_one(void)\n \tcheck_int(st->readers_len, >, 0);\n \n #ifndef GIT_WINDOWS_NATIVE\n-\treftable_buf_addstr(&scratch, dir);\n-\treftable_buf_addstr(&scratch, \"/tables.list\");\n+\tcheck(!reftable_buf_addstr(&scratch, dir));\n+\tcheck(!reftable_buf_addstr(&scratch, \"/tables.list\"));\n \terr = stat(scratch.buf, &stat_result);\n \tcheck(!err);\n \tcheck_int((stat_result.st_mode & 0777), ==, opts.default_permissions);\n \n \treftable_buf_reset(&scratch);\n-\treftable_buf_addstr(&scratch, dir);\n-\treftable_buf_addstr(&scratch, \"/\");\n+\tcheck(!reftable_buf_addstr(&scratch, dir));\n+\tcheck(!reftable_buf_addstr(&scratch, \"/\"));\n \t/* do not try at home; not an external API for reftable. */\n-\treftable_buf_addstr(&scratch, st->readers[0]->name);\n+\tcheck(!reftable_buf_addstr(&scratch, st->readers[0]->name));\n \terr = stat(scratch.buf, &stat_result);\n \tcheck(!err);\n \tcheck_int((stat_result.st_mode & 0777), ==, opts.default_permissions);\n@@ -432,10 +432,10 @@ static void t_reftable_stack_auto_compaction_fails_gracefully(void)\n \t * Adding a new table to the stack should not be impacted by this, even\n \t * though auto-compaction will now fail.\n \t */\n-\treftable_buf_addstr(&table_path, dir);\n-\treftable_buf_addstr(&table_path, \"/\");\n-\treftable_buf_addstr(&table_path, st->readers[0]->name);\n-\treftable_buf_addstr(&table_path, \".lock\");\n+\tcheck(!reftable_buf_addstr(&table_path, dir));\n+\tcheck(!reftable_buf_addstr(&table_path, \"/\"));\n+\tcheck(!reftable_buf_addstr(&table_path, st->readers[0]->name));\n+\tcheck(!reftable_buf_addstr(&table_path, \".lock\"));\n \twrite_file_buf(table_path.buf, \"\", 0);\n \n \tref.update_index = 2;\n@@ -575,17 +575,17 @@ static void t_reftable_stack_add(void)\n \t}\n \n #ifndef GIT_WINDOWS_NATIVE\n-\treftable_buf_addstr(&path, dir);\n-\treftable_buf_addstr(&path, \"/tables.list\");\n+\tcheck(!reftable_buf_addstr(&path, dir));\n+\tcheck(!reftable_buf_addstr(&path, \"/tables.list\"));\n \terr = stat(path.buf, &stat_result);\n \tcheck(!err);\n \tcheck_int((stat_result.st_mode & 0777), ==, opts.default_permissions);\n \n \treftable_buf_reset(&path);\n-\treftable_buf_addstr(&path, dir);\n-\treftable_buf_addstr(&path, \"/\");\n+\tcheck(!reftable_buf_addstr(&path, dir));\n+\tcheck(!reftable_buf_addstr(&path, \"/\"));\n \t/* do not try at home; not an external API for reftable. */\n-\treftable_buf_addstr(&path, st->readers[0]->name);\n+\tcheck(!reftable_buf_addstr(&path, st->readers[0]->name));\n \terr = stat(path.buf, &stat_result);\n \tcheck(!err);\n \tcheck_int((stat_result.st_mode & 0777), ==, opts.default_permissions);\n@@ -1078,10 +1078,10 @@ static void t_reftable_stack_auto_compaction_with_locked_tables(void)\n \t * size, we expect that auto-compaction will want to compact all of the\n \t * tables. Locking any of the tables will keep it from doing so.\n \t */\n-\treftable_buf_addstr(&buf, dir);\n-\treftable_buf_addstr(&buf, \"/\");\n-\treftable_buf_addstr(&buf, st->readers[2]->name);\n-\treftable_buf_addstr(&buf, \".lock\");\n+\tcheck(!reftable_buf_addstr(&buf, dir));\n+\tcheck(!reftable_buf_addstr(&buf, \"/\"));\n+\tcheck(!reftable_buf_addstr(&buf, st->readers[2]->name));\n+\tcheck(!reftable_buf_addstr(&buf, \".lock\"));\n \twrite_file_buf(buf.buf, \"\", 0);\n \n \t/*\n@@ -1164,10 +1164,10 @@ static void t_reftable_stack_compaction_with_locked_tables(void)\n \tcheck_int(st->merged->readers_len, ==, 3);\n \n \t/* Lock one of the tables that we're about to compact. */\n-\treftable_buf_addstr(&buf, dir);\n-\treftable_buf_addstr(&buf, \"/\");\n-\treftable_buf_addstr(&buf, st->readers[1]->name);\n-\treftable_buf_addstr(&buf, \".lock\");\n+\tcheck(!reftable_buf_addstr(&buf, dir));\n+\tcheck(!reftable_buf_addstr(&buf, \"/\"));\n+\tcheck(!reftable_buf_addstr(&buf, st->readers[1]->name));\n+\tcheck(!reftable_buf_addstr(&buf, \".lock\"));\n \twrite_file_buf(buf.buf, \"\", 0);\n \n \t/*\n@@ -1324,13 +1324,13 @@ static void t_reftable_stack_reload_with_missing_table(void)\n \t * our old readers. This should trigger a partial reload of the stack,\n \t * where we try to reuse our old readers.\n \t*/\n-\treftable_buf_addstr(&content, st->readers[0]->name);\n-\treftable_buf_addstr(&content, \"\\n\");\n-\treftable_buf_addstr(&content, st->readers[1]->name);\n-\treftable_buf_addstr(&content, \"\\n\");\n-\treftable_buf_addstr(&content, \"garbage\\n\");\n-\treftable_buf_addstr(&table_path, st->list_file);\n-\treftable_buf_addstr(&table_path, \".lock\");\n+\tcheck(!reftable_buf_addstr(&content, st->readers[0]->name));\n+\tcheck(!reftable_buf_addstr(&content, \"\\n\"));\n+\tcheck(!reftable_buf_addstr(&content, st->readers[1]->name));\n+\tcheck(!reftable_buf_addstr(&content, \"\\n\"));\n+\tcheck(!reftable_buf_addstr(&content, \"garbage\\n\"));\n+\tcheck(!reftable_buf_addstr(&table_path, st->list_file));\n+\tcheck(!reftable_buf_addstr(&table_path, \".lock\"));\n \twrite_file_buf(table_path.buf, content.buf, content.len);\n \terr = rename(table_path.buf, st->list_file);\n \tcheck(!err);\n-- \n2.47.0.dirty\n\n"},{"id":"504810","messageId":"66ee431db464fbd1e2fdfb6a8c8452621908bfed.1728629612.git.ps@pks.im","threadId":"62313","inReplyTo":"cover.1728629612.git.ps@pks.im","subject":"[PATCH 07/10] reftable/stack: adapt `format_name()` to handle allocation failures","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-10-11T06:54:29Z","receivedAt":"2024-10-11T06:54:33Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"The `format_name()` function cannot pass any errors to the caller as it\nhas a `void` return type. Adapt it and its callers such that we can\nhandle errors and start handling allocation failures.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n reftable/stack.c | 28 +++++++++++++++++++---------\n 1 file changed, 19 insertions(+), 9 deletions(-)\n\ndiff --git a/reftable/stack.c b/reftable/stack.c\nindex 6ba48ddce5d..e94eb3c4685 100644\n--- a/reftable/stack.c\n+++ b/reftable/stack.c\n@@ -623,14 +623,14 @@ int reftable_stack_add(struct reftable_stack *st,\n \treturn 0;\n }\n \n-static void format_name(struct reftable_buf *dest, uint64_t min, uint64_t max)\n+static int format_name(struct reftable_buf *dest, uint64_t min, uint64_t max)\n {\n \tchar buf[100];\n \tuint32_t rnd = (uint32_t)git_rand();\n \tsnprintf(buf, sizeof(buf), \"0x%012\" PRIx64 \"-0x%012\" PRIx64 \"-%08x\",\n \t\t min, max, rnd);\n \treftable_buf_reset(dest);\n-\treftable_buf_addstr(dest, buf);\n+\treturn reftable_buf_addstr(dest, buf);\n }\n \n struct reftable_addition {\n@@ -846,7 +846,10 @@ int reftable_addition_add(struct reftable_addition *add,\n \tint tab_fd;\n \n \treftable_buf_reset(&next_name);\n-\tformat_name(&next_name, add->next_update_index, add->next_update_index);\n+\n+\terr = format_name(&next_name, add->next_update_index, add->next_update_index);\n+\tif (err < 0)\n+\t\tgoto done;\n \n \tstack_filename(&temp_tab_file_name, add->stack, next_name.buf);\n \treftable_buf_addstr(&temp_tab_file_name, \".temp.XXXXXX\");\n@@ -893,7 +896,9 @@ int reftable_addition_add(struct reftable_addition *add,\n \t\tgoto done;\n \t}\n \n-\tformat_name(&next_name, wr->min_update_index, wr->max_update_index);\n+\terr = format_name(&next_name, wr->min_update_index, wr->max_update_index);\n+\tif (err < 0)\n+\t\tgoto done;\n \treftable_buf_addstr(&next_name, \".ref\");\n \tstack_filename(&tab_file_name, add->stack, next_name.buf);\n \n@@ -944,9 +949,11 @@ static int stack_compact_locked(struct reftable_stack *st,\n \tstruct tempfile *tab_file;\n \tint tab_fd, err = 0;\n \n-\tformat_name(&next_name,\n-\t\t    reftable_reader_min_update_index(st->readers[first]),\n-\t\t    reftable_reader_max_update_index(st->readers[last]));\n+\terr = format_name(&next_name, reftable_reader_min_update_index(st->readers[first]),\n+\t\t\t  reftable_reader_max_update_index(st->readers[last]));\n+\tif (err < 0)\n+\t\tgoto done;\n+\n \tstack_filename(&tab_file_path, st, next_name.buf);\n \treftable_buf_addstr(&tab_file_path, \".temp.XXXXXX\");\n \n@@ -1370,8 +1377,11 @@ static int stack_compact_range(struct reftable_stack *st,\n \t * it into place now.\n \t */\n \tif (!is_empty_table) {\n-\t\tformat_name(&new_table_name, st->readers[first]->min_update_index,\n-\t\t\t    st->readers[last]->max_update_index);\n+\t\terr = format_name(&new_table_name, st->readers[first]->min_update_index,\n+\t\t\t\t  st->readers[last]->max_update_index);\n+\t\tif (err < 0)\n+\t\t\tgoto done;\n+\n \t\treftable_buf_addstr(&new_table_name, \".ref\");\n \t\tstack_filename(&new_table_path, st, new_table_name.buf);\n \n-- \n2.47.0.dirty\n\n"},{"id":"504811","messageId":"f5ae5ec27d6cff018b90f0589ca3da4874f46616.1728629612.git.ps@pks.im","threadId":"62313","inReplyTo":"cover.1728629612.git.ps@pks.im","subject":"[PATCH 08/10] reftable/record: adapt `reftable_record_key()` to handle allocation failures","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-10-11T06:54:32Z","receivedAt":"2024-10-11T06:54:35Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"The `reftable_record_key()` function cannot pass any errors to the\ncaller as it has a `void` return type. Adapt it and its callers such\nthat we can handle errors and start handling allocation failures.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n reftable/block.c  | 20 +++++++++++++++-----\n reftable/reader.c |  8 ++++++--\n reftable/record.c | 32 ++++++++++++++++++++------------\n reftable/record.h |  4 ++--\n reftable/writer.c |  5 ++++-\n 5 files changed, 47 insertions(+), 22 deletions(-)\n\ndiff --git a/reftable/block.c b/reftable/block.c\nindex 4f62b823db8..697b8b41531 100644\n--- a/reftable/block.c\n+++ b/reftable/block.c\n@@ -111,9 +111,12 @@ int block_writer_add(struct block_writer *w, struct reftable_record *rec)\n \tint is_restart = 0;\n \tstruct reftable_buf key = REFTABLE_BUF_INIT;\n \tint n = 0;\n-\tint err = -1;\n+\tint err;\n+\n+\terr = reftable_record_key(rec, &key);\n+\tif (err < 0)\n+\t\tgoto done;\n \n-\treftable_record_key(rec, &key);\n \tif (!key.len) {\n \t\terr = REFTABLE_API_ERROR;\n \t\tgoto done;\n@@ -121,13 +124,17 @@ int block_writer_add(struct block_writer *w, struct reftable_record *rec)\n \n \tn = reftable_encode_key(&is_restart, out, last, key,\n \t\t\t\treftable_record_val_type(rec));\n-\tif (n < 0)\n+\tif (n < 0) {\n+\t\terr = -1;\n \t\tgoto done;\n+\t}\n \tstring_view_consume(&out, n);\n \n \tn = reftable_record_encode(rec, out, w->hash_size);\n-\tif (n < 0)\n+\tif (n < 0) {\n+\t\terr = -1;\n \t\tgoto done;\n+\t}\n \tstring_view_consume(&out, n);\n \n \terr = block_writer_register_restart(w, start.len - out.len, is_restart,\n@@ -522,6 +529,10 @@ int block_iter_seek_key(struct block_iter *it, const struct block_reader *br,\n \t\t\tgoto done;\n \t\t}\n \n+\t\terr = reftable_record_key(&rec, &it->last_key);\n+\t\tif (err < 0)\n+\t\t\tgoto done;\n+\n \t\t/*\n \t\t * Check whether the current key is greater or equal to the\n \t\t * sought-after key. In case it is greater we know that the\n@@ -536,7 +547,6 @@ int block_iter_seek_key(struct block_iter *it, const struct block_reader *br,\n \t\t * to `last_key` now, and naturally all keys share a prefix\n \t\t * with themselves.\n \t\t */\n-\t\treftable_record_key(&rec, &it->last_key);\n \t\tif (reftable_buf_cmp(&it->last_key, want) >= 0) {\n \t\t\tit->next_off = prev_off;\n \t\t\tgoto done;\ndiff --git a/reftable/reader.c b/reftable/reader.c\nindex 388f8bf6d7b..ab89efd9c55 100644\n--- a/reftable/reader.c\n+++ b/reftable/reader.c\n@@ -356,7 +356,9 @@ static int table_iter_seek_linear(struct table_iter *ti,\n \tint err;\n \n \treftable_record_init(&rec, reftable_record_type(want));\n-\treftable_record_key(want, &want_key);\n+\terr = reftable_record_key(want, &want_key);\n+\tif (err < 0)\n+\t\tgoto done;\n \n \t/*\n \t * First we need to locate the block that must contain our record. To\n@@ -439,7 +441,9 @@ static int table_iter_seek_indexed(struct table_iter *ti,\n \t};\n \tint err;\n \n-\treftable_record_key(rec, &want_index.u.idx.last_key);\n+\terr = reftable_record_key(rec, &want_index.u.idx.last_key);\n+\tif (err < 0)\n+\t\tgoto done;\n \n \t/*\n \t * The index may consist of multiple levels, where each level may have\ndiff --git a/reftable/record.c b/reftable/record.c\nindex 0182c973437..672c5f909a9 100644\n--- a/reftable/record.c\n+++ b/reftable/record.c\n@@ -207,12 +207,12 @@ int reftable_decode_key(struct reftable_buf *last_key, uint8_t *extra,\n \treturn start_len - in.len;\n }\n \n-static void reftable_ref_record_key(const void *r, struct reftable_buf *dest)\n+static int reftable_ref_record_key(const void *r, struct reftable_buf *dest)\n {\n \tconst struct reftable_ref_record *rec =\n \t\t(const struct reftable_ref_record *)r;\n \treftable_buf_reset(dest);\n-\treftable_buf_addstr(dest, rec->refname);\n+\treturn reftable_buf_addstr(dest, rec->refname);\n }\n \n static int reftable_ref_record_copy_from(void *rec, const void *src_rec,\n@@ -465,12 +465,12 @@ static struct reftable_record_vtable reftable_ref_record_vtable = {\n \t.cmp = &reftable_ref_record_cmp_void,\n };\n \n-static void reftable_obj_record_key(const void *r, struct reftable_buf *dest)\n+static int reftable_obj_record_key(const void *r, struct reftable_buf *dest)\n {\n \tconst struct reftable_obj_record *rec =\n \t\t(const struct reftable_obj_record *)r;\n \treftable_buf_reset(dest);\n-\treftable_buf_add(dest, rec->hash_prefix, rec->hash_prefix_len);\n+\treturn reftable_buf_add(dest, rec->hash_prefix, rec->hash_prefix_len);\n }\n \n static void reftable_obj_record_release(void *rec)\n@@ -664,19 +664,27 @@ static struct reftable_record_vtable reftable_obj_record_vtable = {\n \t.cmp = &reftable_obj_record_cmp_void,\n };\n \n-static void reftable_log_record_key(const void *r, struct reftable_buf *dest)\n+static int reftable_log_record_key(const void *r, struct reftable_buf *dest)\n {\n \tconst struct reftable_log_record *rec =\n \t\t(const struct reftable_log_record *)r;\n-\tint len = strlen(rec->refname);\n+\tint len = strlen(rec->refname), err;\n \tuint8_t i64[8];\n \tuint64_t ts = 0;\n+\n \treftable_buf_reset(dest);\n-\treftable_buf_add(dest, (uint8_t *)rec->refname, len + 1);\n+\terr = reftable_buf_add(dest, (uint8_t *)rec->refname, len + 1);\n+\tif (err < 0)\n+\t\treturn err;\n \n \tts = (~ts) - rec->update_index;\n \tput_be64(&i64[0], ts);\n-\treftable_buf_add(dest, i64, sizeof(i64));\n+\n+\terr = reftable_buf_add(dest, i64, sizeof(i64));\n+\tif (err < 0)\n+\t\treturn err;\n+\n+\treturn 0;\n }\n \n static int reftable_log_record_copy_from(void *rec, const void *src_rec,\n@@ -1027,11 +1035,11 @@ static struct reftable_record_vtable reftable_log_record_vtable = {\n \t.cmp = &reftable_log_record_cmp_void,\n };\n \n-static void reftable_index_record_key(const void *r, struct reftable_buf *dest)\n+static int reftable_index_record_key(const void *r, struct reftable_buf *dest)\n {\n \tconst struct reftable_index_record *rec = r;\n \treftable_buf_reset(dest);\n-\treftable_buf_add(dest, rec->last_key.buf, rec->last_key.len);\n+\treturn reftable_buf_add(dest, rec->last_key.buf, rec->last_key.len);\n }\n \n static int reftable_index_record_copy_from(void *rec, const void *src_rec,\n@@ -1124,9 +1132,9 @@ static struct reftable_record_vtable reftable_index_record_vtable = {\n \t.cmp = &reftable_index_record_cmp,\n };\n \n-void reftable_record_key(struct reftable_record *rec, struct reftable_buf *dest)\n+int reftable_record_key(struct reftable_record *rec, struct reftable_buf *dest)\n {\n-\treftable_record_vtable(rec)->key(reftable_record_data(rec), dest);\n+\treturn reftable_record_vtable(rec)->key(reftable_record_data(rec), dest);\n }\n \n int reftable_record_encode(struct reftable_record *rec, struct string_view dest,\ndiff --git a/reftable/record.h b/reftable/record.h\nindex 271da3bf360..25aa908c859 100644\n--- a/reftable/record.h\n+++ b/reftable/record.h\n@@ -40,7 +40,7 @@ int put_var_int(struct string_view *dest, uint64_t val);\n /* Methods for records. */\n struct reftable_record_vtable {\n \t/* encode the key of to a uint8_t reftable_buf. */\n-\tvoid (*key)(const void *rec, struct reftable_buf *dest);\n+\tint (*key)(const void *rec, struct reftable_buf *dest);\n \n \t/* The record type of ('r' for ref). */\n \tuint8_t type;\n@@ -137,7 +137,7 @@ void reftable_record_init(struct reftable_record *rec, uint8_t typ);\n /* see struct record_vtable */\n int reftable_record_cmp(struct reftable_record *a, struct reftable_record *b);\n int reftable_record_equal(struct reftable_record *a, struct reftable_record *b, int hash_size);\n-void reftable_record_key(struct reftable_record *rec, struct reftable_buf *dest);\n+int reftable_record_key(struct reftable_record *rec, struct reftable_buf *dest);\n int reftable_record_copy_from(struct reftable_record *rec,\n \t\t\t      struct reftable_record *src, int hash_size);\n uint8_t reftable_record_val_type(struct reftable_record *rec);\ndiff --git a/reftable/writer.c b/reftable/writer.c\nindex da6941a78ac..377db709c85 100644\n--- a/reftable/writer.c\n+++ b/reftable/writer.c\n@@ -249,7 +249,10 @@ static int writer_add_record(struct reftable_writer *w,\n \tstruct reftable_buf key = REFTABLE_BUF_INIT;\n \tint err;\n \n-\treftable_record_key(rec, &key);\n+\terr = reftable_record_key(rec, &key);\n+\tif (err < 0)\n+\t\tgoto done;\n+\n \tif (reftable_buf_cmp(&w->last_key, &key) >= 0) {\n \t\terr = REFTABLE_API_ERROR;\n \t\tgoto done;\n-- \n2.47.0.dirty\n\n"},{"id":"504812","messageId":"d66d9e50e06ae6e16a4092667c561dccdbabfa08.1728629612.git.ps@pks.im","threadId":"62313","inReplyTo":"cover.1728629612.git.ps@pks.im","subject":"[PATCH 09/10] reftable/stack: adapt `stack_filename()` to handle allocation failures","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-10-11T06:54:35Z","receivedAt":"2024-10-11T06:54:38Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"The `stack_filename()` function cannot pass any errors to the caller as it\nhas a `void` return type. Adapt it and its callers such that we can\nhandle errors and start handling allocation failures.\n\nThere are two interesting edge cases in `reftable_stack_destroy()` and\n`reftable_addition_close()`. Both of these are trying to tear down their\nrespective structures, and while doing so they try to unlink some of the\ntables they have been keeping alive. Any earlier attempts to do that may\nfail on Windows because it keeps us from deleting such tables while they\nare still open, and thus we re-try on close. It's okay and even expected\nthat this can fail when the tables are still open by another process, so\nwe handle the allocation failures gracefully and just skip over any file\nwhose name we couldn't figure out.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n reftable/stack.c | 62 +++++++++++++++++++++++++++++++++++-------------\n 1 file changed, 45 insertions(+), 17 deletions(-)\n\ndiff --git a/reftable/stack.c b/reftable/stack.c\nindex e94eb3c4685..243b10715cc 100644\n--- a/reftable/stack.c\n+++ b/reftable/stack.c\n@@ -31,13 +31,16 @@ static void reftable_addition_close(struct reftable_addition *add);\n static int reftable_stack_reload_maybe_reuse(struct reftable_stack *st,\n \t\t\t\t\t     int reuse_open);\n \n-static void stack_filename(struct reftable_buf *dest, struct reftable_stack *st,\n-\t\t\t   const char *name)\n+static int stack_filename(struct reftable_buf *dest, struct reftable_stack *st,\n+\t\t\t  const char *name)\n {\n+\tint err;\n \treftable_buf_reset(dest);\n-\treftable_buf_addstr(dest, st->reftable_dir);\n-\treftable_buf_addstr(dest, \"/\");\n-\treftable_buf_addstr(dest, name);\n+\tif ((err = reftable_buf_addstr(dest, st->reftable_dir)) < 0 ||\n+\t    (err = reftable_buf_addstr(dest, \"/\")) < 0 ||\n+\t    (err = reftable_buf_addstr(dest, name)) < 0)\n+\t\treturn err;\n+\treturn 0;\n }\n \n static ssize_t reftable_fd_write(void *arg, const void *data, size_t sz)\n@@ -211,13 +214,16 @@ void reftable_stack_destroy(struct reftable_stack *st)\n \t\tstruct reftable_buf filename = REFTABLE_BUF_INIT;\n \t\tfor (i = 0; i < st->readers_len; i++) {\n \t\t\tconst char *name = reader_name(st->readers[i]);\n+\t\t\tint try_unlinking = 1;\n+\n \t\t\treftable_buf_reset(&filename);\n \t\t\tif (names && !has_name(names, name)) {\n-\t\t\t\tstack_filename(&filename, st, name);\n+\t\t\t\tif (stack_filename(&filename, st, name) < 0)\n+\t\t\t\t\ttry_unlinking = 0;\n \t\t\t}\n \t\t\treftable_reader_decref(st->readers[i]);\n \n-\t\t\tif (filename.len) {\n+\t\t\tif (try_unlinking && filename.len) {\n \t\t\t\t/* On Windows, can only unlink after closing. */\n \t\t\t\tunlink(filename.buf);\n \t\t\t}\n@@ -310,7 +316,10 @@ static int reftable_stack_reload_once(struct reftable_stack *st,\n \n \t\tif (!rd) {\n \t\t\tstruct reftable_block_source src = { NULL };\n-\t\t\tstack_filename(&table_path, st, name);\n+\n+\t\t\terr = stack_filename(&table_path, st, name);\n+\t\t\tif (err < 0)\n+\t\t\t\tgoto done;\n \n \t\t\terr = reftable_block_source_from_file(&src,\n \t\t\t\t\t\t\t      table_path.buf);\n@@ -341,7 +350,11 @@ static int reftable_stack_reload_once(struct reftable_stack *st,\n \tfor (i = 0; i < cur_len; i++) {\n \t\tif (cur[i]) {\n \t\t\tconst char *name = reader_name(cur[i]);\n-\t\t\tstack_filename(&table_path, st, name);\n+\n+\t\t\terr = stack_filename(&table_path, st, name);\n+\t\t\tif (err < 0)\n+\t\t\t\tgoto done;\n+\n \t\t\treftable_reader_decref(cur[i]);\n \t\t\tunlink(table_path.buf);\n \t\t}\n@@ -700,8 +713,8 @@ static void reftable_addition_close(struct reftable_addition *add)\n \tsize_t i;\n \n \tfor (i = 0; i < add->new_tables_len; i++) {\n-\t\tstack_filename(&nm, add->stack, add->new_tables[i]);\n-\t\tunlink(nm.buf);\n+\t\tif (!stack_filename(&nm, add->stack, add->new_tables[i]))\n+\t\t\tunlink(nm.buf);\n \t\treftable_free(add->new_tables[i]);\n \t\tadd->new_tables[i] = NULL;\n \t}\n@@ -851,7 +864,9 @@ int reftable_addition_add(struct reftable_addition *add,\n \tif (err < 0)\n \t\tgoto done;\n \n-\tstack_filename(&temp_tab_file_name, add->stack, next_name.buf);\n+\terr = stack_filename(&temp_tab_file_name, add->stack, next_name.buf);\n+\tif (err < 0)\n+\t\tgoto done;\n \treftable_buf_addstr(&temp_tab_file_name, \".temp.XXXXXX\");\n \n \ttab_file = mks_tempfile(temp_tab_file_name.buf);\n@@ -900,7 +915,10 @@ int reftable_addition_add(struct reftable_addition *add,\n \tif (err < 0)\n \t\tgoto done;\n \treftable_buf_addstr(&next_name, \".ref\");\n-\tstack_filename(&tab_file_name, add->stack, next_name.buf);\n+\n+\terr = stack_filename(&tab_file_name, add->stack, next_name.buf);\n+\tif (err < 0)\n+\t\tgoto done;\n \n \t/*\n \t  On windows, this relies on rand() picking a unique destination name.\n@@ -954,7 +972,9 @@ static int stack_compact_locked(struct reftable_stack *st,\n \tif (err < 0)\n \t\tgoto done;\n \n-\tstack_filename(&tab_file_path, st, next_name.buf);\n+\terr = stack_filename(&tab_file_path, st, next_name.buf);\n+\tif (err < 0)\n+\t\tgoto done;\n \treftable_buf_addstr(&tab_file_path, \".temp.XXXXXX\");\n \n \ttab_file = mks_tempfile(tab_file_path.buf);\n@@ -1174,7 +1194,9 @@ static int stack_compact_range(struct reftable_stack *st,\n \t}\n \n \tfor (i = last + 1; i > first; i--) {\n-\t\tstack_filename(&table_name, st, reader_name(st->readers[i - 1]));\n+\t\terr = stack_filename(&table_name, st, reader_name(st->readers[i - 1]));\n+\t\tif (err < 0)\n+\t\t\tgoto done;\n \n \t\terr = hold_lock_file_for_update(&table_locks[nlocks],\n \t\t\t\t\t\ttable_name.buf, LOCK_NO_DEREF);\n@@ -1383,7 +1405,10 @@ static int stack_compact_range(struct reftable_stack *st,\n \t\t\tgoto done;\n \n \t\treftable_buf_addstr(&new_table_name, \".ref\");\n-\t\tstack_filename(&new_table_path, st, new_table_name.buf);\n+\n+\t\terr = stack_filename(&new_table_path, st, new_table_name.buf);\n+\t\tif (err < 0)\n+\t\t\tgoto done;\n \n \t\terr = rename_tempfile(&new_table, new_table_path.buf);\n \t\tif (err < 0) {\n@@ -1677,7 +1702,10 @@ static void remove_maybe_stale_table(struct reftable_stack *st, uint64_t max,\n \tstruct reftable_block_source src = { NULL };\n \tstruct reftable_reader *rd = NULL;\n \tstruct reftable_buf table_path = REFTABLE_BUF_INIT;\n-\tstack_filename(&table_path, st, name);\n+\n+\terr = stack_filename(&table_path, st, name);\n+\tif (err < 0)\n+\t\tgoto done;\n \n \terr = reftable_block_source_from_file(&src, table_path.buf);\n \tif (err < 0)\n-- \n2.47.0.dirty\n\n"},{"id":"504813","messageId":"8406948ae747844c3dfb1b5454218d116945897a.1728629612.git.ps@pks.im","threadId":"62313","inReplyTo":"cover.1728629612.git.ps@pks.im","subject":"[PATCH 10/10] reftable: handle trivial `reftable_buf` errors","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-10-11T06:54:38Z","receivedAt":"2024-10-11T06:54:44Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"Convert the reftable library such that we handle failures with the\nnew `reftable_buf` interfaces.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n reftable/block.c  |  9 +++++++--\n reftable/iter.c   |  5 ++++-\n reftable/reader.c |  5 ++++-\n reftable/record.c | 32 +++++++++++++++++++++++--------\n reftable/stack.c  | 49 +++++++++++++++++++++++++++++++----------------\n reftable/writer.c | 48 +++++++++++++++++++++++++++++++++-------------\n 6 files changed, 107 insertions(+), 41 deletions(-)\n\ndiff --git a/reftable/block.c b/reftable/block.c\nindex 697b8b41531..f5b432566a6 100644\n--- a/reftable/block.c\n+++ b/reftable/block.c\n@@ -40,7 +40,9 @@ int footer_size(int version)\n static int block_writer_register_restart(struct block_writer *w, int n,\n \t\t\t\t\t int is_restart, struct reftable_buf *key)\n {\n-\tint rlen = w->restart_len;\n+\tint rlen, err;\n+\n+\trlen = w->restart_len;\n \tif (rlen >= MAX_RESTARTS) {\n \t\tis_restart = 0;\n \t}\n@@ -60,7 +62,10 @@ static int block_writer_register_restart(struct block_writer *w, int n,\n \tw->next += n;\n \n \treftable_buf_reset(&w->last_key);\n-\treftable_buf_add(&w->last_key, key->buf, key->len);\n+\terr = reftable_buf_add(&w->last_key, key->buf, key->len);\n+\tif (err < 0)\n+\t\treturn err;\n+\n \tw->entries++;\n \treturn 0;\n }\ndiff --git a/reftable/iter.c b/reftable/iter.c\nindex 6c193fd31a9..86e801ca9fb 100644\n--- a/reftable/iter.c\n+++ b/reftable/iter.c\n@@ -197,7 +197,10 @@ int indexed_table_ref_iter_new(struct indexed_table_ref_iter **dest,\n \n \t*itr = empty;\n \titr->r = r;\n-\treftable_buf_add(&itr->oid, oid, oid_len);\n+\n+\terr = reftable_buf_add(&itr->oid, oid, oid_len);\n+\tif (err < 0)\n+\t\tgoto out;\n \n \titr->offsets = offsets;\n \titr->offset_len = offset_len;\ndiff --git a/reftable/reader.c b/reftable/reader.c\nindex ab89efd9c55..90dc950b577 100644\n--- a/reftable/reader.c\n+++ b/reftable/reader.c\n@@ -769,7 +769,10 @@ static int reftable_reader_refs_for_unindexed(struct reftable_reader *r,\n \t}\n \t*filter = empty;\n \n-\treftable_buf_add(&filter->oid, oid, oid_len);\n+\terr = reftable_buf_add(&filter->oid, oid, oid_len);\n+\tif (err < 0)\n+\t\tgoto out;\n+\n \titerator_from_table_iter(&filter->it, ti);\n \n \titerator_from_filtering_ref_iterator(it, filter);\ndiff --git a/reftable/record.c b/reftable/record.c\nindex 672c5f909a9..fb5652ed575 100644\n--- a/reftable/record.c\n+++ b/reftable/record.c\n@@ -102,7 +102,9 @@ static int decode_string(struct reftable_buf *dest, struct string_view in)\n {\n \tint start_len = in.len;\n \tuint64_t tsize = 0;\n-\tint n = get_var_int(&tsize, &in);\n+\tint n, err;\n+\n+\tn = get_var_int(&tsize, &in);\n \tif (n <= 0)\n \t\treturn -1;\n \tstring_view_consume(&in, n);\n@@ -110,7 +112,10 @@ static int decode_string(struct reftable_buf *dest, struct string_view in)\n \t\treturn -1;\n \n \treftable_buf_reset(dest);\n-\treftable_buf_add(dest, in.buf, tsize);\n+\terr = reftable_buf_add(dest, in.buf, tsize);\n+\tif (err < 0)\n+\t\treturn err;\n+\n \tstring_view_consume(&in, tsize);\n \n \treturn start_len - in.len;\n@@ -189,7 +194,7 @@ int reftable_decode_key(struct reftable_buf *last_key, uint8_t *extra,\n \tint start_len = in.len;\n \tuint64_t prefix_len = 0;\n \tuint64_t suffix_len = 0;\n-\tint n;\n+\tint err, n;\n \n \tn = reftable_decode_keylen(in, &prefix_len, &suffix_len, extra);\n \tif (n < 0)\n@@ -200,8 +205,14 @@ int reftable_decode_key(struct reftable_buf *last_key, uint8_t *extra,\n \t    prefix_len > last_key->len)\n \t\treturn -1;\n \n-\treftable_buf_setlen(last_key, prefix_len);\n-\treftable_buf_add(last_key, in.buf, suffix_len);\n+\terr = reftable_buf_setlen(last_key, prefix_len);\n+\tif (err < 0)\n+\t\treturn err;\n+\n+\terr = reftable_buf_add(last_key, in.buf, suffix_len);\n+\tif (err < 0)\n+\t\treturn err;\n+\n \tstring_view_consume(&in, suffix_len);\n \n \treturn start_len - in.len;\n@@ -1047,9 +1058,12 @@ static int reftable_index_record_copy_from(void *rec, const void *src_rec,\n {\n \tstruct reftable_index_record *dst = rec;\n \tconst struct reftable_index_record *src = src_rec;\n+\tint err;\n \n \treftable_buf_reset(&dst->last_key);\n-\treftable_buf_add(&dst->last_key, src->last_key.buf, src->last_key.len);\n+\terr = reftable_buf_add(&dst->last_key, src->last_key.buf, src->last_key.len);\n+\tif (err < 0)\n+\t\treturn err;\n \tdst->offset = src->offset;\n \n \treturn 0;\n@@ -1090,10 +1104,12 @@ static int reftable_index_record_decode(void *rec, struct reftable_buf key,\n {\n \tstruct string_view start = in;\n \tstruct reftable_index_record *r = rec;\n-\tint n = 0;\n+\tint err, n = 0;\n \n \treftable_buf_reset(&r->last_key);\n-\treftable_buf_add(&r->last_key, key.buf, key.len);\n+\terr = reftable_buf_add(&r->last_key, key.buf, key.len);\n+\tif (err < 0)\n+\t\treturn err;\n \n \tn = get_var_int(&r->offset, &in);\n \tif (n < 0)\ndiff --git a/reftable/stack.c b/reftable/stack.c\nindex 243b10715cc..c33979536ef 100644\n--- a/reftable/stack.c\n+++ b/reftable/stack.c\n@@ -78,8 +78,9 @@ int reftable_new_stack(struct reftable_stack **dest, const char *dir,\n \t*dest = NULL;\n \n \treftable_buf_reset(&list_file_name);\n-\treftable_buf_addstr(&list_file_name, dir);\n-\treftable_buf_addstr(&list_file_name, \"/tables.list\");\n+\tif ((err = reftable_buf_addstr(&list_file_name, dir)) < 0 ||\n+\t    (err = reftable_buf_addstr(&list_file_name, \"/tables.list\")) < 0)\n+\t\tgoto out;\n \n \tp->list_file = reftable_buf_detach(&list_file_name);\n \tp->list_fd = -1;\n@@ -747,12 +748,14 @@ int reftable_addition_commit(struct reftable_addition *add)\n \t\tgoto done;\n \n \tfor (i = 0; i < add->stack->merged->readers_len; i++) {\n-\t\treftable_buf_addstr(&table_list, add->stack->readers[i]->name);\n-\t\treftable_buf_addstr(&table_list, \"\\n\");\n+\t\tif ((err = reftable_buf_addstr(&table_list, add->stack->readers[i]->name)) < 0 ||\n+\t\t    (err = reftable_buf_addstr(&table_list, \"\\n\")) < 0)\n+\t\t\tgoto done;\n \t}\n \tfor (i = 0; i < add->new_tables_len; i++) {\n-\t\treftable_buf_addstr(&table_list, add->new_tables[i]);\n-\t\treftable_buf_addstr(&table_list, \"\\n\");\n+\t\tif ((err = reftable_buf_addstr(&table_list, add->new_tables[i])) < 0 ||\n+\t\t    (err = reftable_buf_addstr(&table_list, \"\\n\")) < 0)\n+\t\t\tgoto done;\n \t}\n \n \terr = write_in_full(lock_file_fd, table_list.buf, table_list.len);\n@@ -867,7 +870,10 @@ int reftable_addition_add(struct reftable_addition *add,\n \terr = stack_filename(&temp_tab_file_name, add->stack, next_name.buf);\n \tif (err < 0)\n \t\tgoto done;\n-\treftable_buf_addstr(&temp_tab_file_name, \".temp.XXXXXX\");\n+\n+\terr = reftable_buf_addstr(&temp_tab_file_name, \".temp.XXXXXX\");\n+\tif (err < 0)\n+\t\tgoto done;\n \n \ttab_file = mks_tempfile(temp_tab_file_name.buf);\n \tif (!tab_file) {\n@@ -914,7 +920,10 @@ int reftable_addition_add(struct reftable_addition *add,\n \terr = format_name(&next_name, wr->min_update_index, wr->max_update_index);\n \tif (err < 0)\n \t\tgoto done;\n-\treftable_buf_addstr(&next_name, \".ref\");\n+\n+\terr = reftable_buf_addstr(&next_name, \".ref\");\n+\tif (err < 0)\n+\t\tgoto done;\n \n \terr = stack_filename(&tab_file_name, add->stack, next_name.buf);\n \tif (err < 0)\n@@ -975,7 +984,10 @@ static int stack_compact_locked(struct reftable_stack *st,\n \terr = stack_filename(&tab_file_path, st, next_name.buf);\n \tif (err < 0)\n \t\tgoto done;\n-\treftable_buf_addstr(&tab_file_path, \".temp.XXXXXX\");\n+\n+\terr = reftable_buf_addstr(&tab_file_path, \".temp.XXXXXX\");\n+\tif (err < 0)\n+\t\tgoto done;\n \n \ttab_file = mks_tempfile(tab_file_path.buf);\n \tif (!tab_file) {\n@@ -1404,7 +1416,9 @@ static int stack_compact_range(struct reftable_stack *st,\n \t\tif (err < 0)\n \t\t\tgoto done;\n \n-\t\treftable_buf_addstr(&new_table_name, \".ref\");\n+\t\terr = reftable_buf_addstr(&new_table_name, \".ref\");\n+\t\tif (err < 0)\n+\t\t\tgoto done;\n \n \t\terr = stack_filename(&new_table_path, st, new_table_name.buf);\n \t\tif (err < 0)\n@@ -1423,16 +1437,19 @@ static int stack_compact_range(struct reftable_stack *st,\n \t * simply skip writing it.\n \t */\n \tfor (i = 0; i < first_to_replace; i++) {\n-\t\treftable_buf_addstr(&tables_list_buf, names[i]);\n-\t\treftable_buf_addstr(&tables_list_buf, \"\\n\");\n+\t\tif ((err = reftable_buf_addstr(&tables_list_buf, names[i])) < 0 ||\n+\t\t    (err = reftable_buf_addstr(&tables_list_buf, \"\\n\")) < 0)\n+\t\t      goto done;\n \t}\n \tif (!is_empty_table) {\n-\t\treftable_buf_addstr(&tables_list_buf, new_table_name.buf);\n-\t\treftable_buf_addstr(&tables_list_buf, \"\\n\");\n+\t\tif ((err = reftable_buf_addstr(&tables_list_buf, new_table_name.buf)) < 0 ||\n+\t\t    (err = reftable_buf_addstr(&tables_list_buf, \"\\n\")) < 0)\n+\t\t\tgoto done;\n \t}\n \tfor (i = last_to_replace + 1; names[i]; i++) {\n-\t\treftable_buf_addstr(&tables_list_buf, names[i]);\n-\t\treftable_buf_addstr(&tables_list_buf, \"\\n\");\n+\t\tif ((err = reftable_buf_addstr(&tables_list_buf, names[i])) < 0 ||\n+\t\t    (err = reftable_buf_addstr(&tables_list_buf, \"\\n\")) < 0)\n+\t\t\tgoto done;\n \t}\n \n \terr = write_in_full(get_lock_file_fd(&tables_list_lock),\ndiff --git a/reftable/writer.c b/reftable/writer.c\nindex 377db709c85..fd136794d5a 100644\n--- a/reftable/writer.c\n+++ b/reftable/writer.c\n@@ -217,6 +217,7 @@ static int writer_index_hash(struct reftable_writer *w, struct reftable_buf *has\n \tnode = tree_search(w->obj_index_tree, &want, &obj_index_tree_node_compare);\n \tif (!node) {\n \t\tstruct obj_index_tree_node empty = OBJ_INDEX_TREE_NODE_INIT;\n+\t\tint err;\n \n \t\tkey = reftable_malloc(sizeof(*key));\n \t\tif (!key)\n@@ -225,7 +226,9 @@ static int writer_index_hash(struct reftable_writer *w, struct reftable_buf *has\n \t\t*key = empty;\n \n \t\treftable_buf_reset(&key->hash);\n-\t\treftable_buf_add(&key->hash, hash->buf, hash->len);\n+\t\terr = reftable_buf_add(&key->hash, hash->buf, hash->len);\n+\t\tif (err < 0)\n+\t\t\treturn err;\n \t\ttree_insert(&w->obj_index_tree, key,\n \t\t\t    &obj_index_tree_node_compare);\n \t} else {\n@@ -259,7 +262,10 @@ static int writer_add_record(struct reftable_writer *w,\n \t}\n \n \treftable_buf_reset(&w->last_key);\n-\treftable_buf_add(&w->last_key, key.buf, key.len);\n+\terr = reftable_buf_add(&w->last_key, key.buf, key.len);\n+\tif (err < 0)\n+\t\tgoto done;\n+\n \tif (!w->block_writer) {\n \t\terr = writer_reinit_block_writer(w, reftable_record_type(rec));\n \t\tif (err < 0)\n@@ -334,8 +340,10 @@ int reftable_writer_add_ref(struct reftable_writer *w,\n \t\tgoto out;\n \n \tif (!w->opts.skip_index_objects && reftable_ref_record_val1(ref)) {\n-\t\treftable_buf_add(&buf, (char *)reftable_ref_record_val1(ref),\n-\t\t\t   hash_size(w->opts.hash_id));\n+\t\terr = reftable_buf_add(&buf, (char *)reftable_ref_record_val1(ref),\n+\t\t\t\t       hash_size(w->opts.hash_id));\n+\t\tif (err < 0)\n+\t\t\tgoto out;\n \n \t\terr = writer_index_hash(w, &buf);\n \t\tif (err < 0)\n@@ -344,8 +352,10 @@ int reftable_writer_add_ref(struct reftable_writer *w,\n \n \tif (!w->opts.skip_index_objects && reftable_ref_record_val2(ref)) {\n \t\treftable_buf_reset(&buf);\n-\t\treftable_buf_add(&buf, reftable_ref_record_val2(ref),\n-\t\t\t   hash_size(w->opts.hash_id));\n+\t\terr = reftable_buf_add(&buf, reftable_ref_record_val2(ref),\n+\t\t\t\t       hash_size(w->opts.hash_id));\n+\t\tif (err < 0)\n+\t\t\tgoto out;\n \n \t\terr = writer_index_hash(w, &buf);\n \t\tif (err < 0)\n@@ -407,17 +417,27 @@ int reftable_writer_add_log(struct reftable_writer *w,\n \n \tinput_log_message = log->value.update.message;\n \tif (!w->opts.exact_log_message && log->value.update.message) {\n-\t\treftable_buf_addstr(&cleaned_message, log->value.update.message);\n+\t\terr = reftable_buf_addstr(&cleaned_message, log->value.update.message);\n+\t\tif (err < 0)\n+\t\t\tgoto done;\n+\n \t\twhile (cleaned_message.len &&\n-\t\t       cleaned_message.buf[cleaned_message.len - 1] == '\\n')\n-\t\t\treftable_buf_setlen(&cleaned_message,\n-\t\t\t\t      cleaned_message.len - 1);\n+\t\t       cleaned_message.buf[cleaned_message.len - 1] == '\\n') {\n+\t\t\terr = reftable_buf_setlen(&cleaned_message,\n+\t\t\t\t\t\t  cleaned_message.len - 1);\n+\t\t\tif (err < 0)\n+\t\t\t\tgoto done;\n+\t\t}\n \t\tif (strchr(cleaned_message.buf, '\\n')) {\n \t\t\t/* multiple lines not allowed. */\n \t\t\terr = REFTABLE_API_ERROR;\n \t\t\tgoto done;\n \t\t}\n-\t\treftable_buf_addstr(&cleaned_message, \"\\n\");\n+\n+\t\terr = reftable_buf_addstr(&cleaned_message, \"\\n\");\n+\t\tif (err < 0)\n+\t\t\tgoto done;\n+\n \t\tlog->value.update.message = cleaned_message.buf;\n \t}\n \n@@ -781,8 +801,10 @@ static int writer_flush_nonempty_block(struct reftable_writer *w)\n \n \tindex_record.offset = w->next;\n \treftable_buf_reset(&index_record.last_key);\n-\treftable_buf_add(&index_record.last_key, w->block_writer->last_key.buf,\n-\t\t   w->block_writer->last_key.len);\n+\terr = reftable_buf_add(&index_record.last_key, w->block_writer->last_key.buf,\n+\t\t\t       w->block_writer->last_key.len);\n+\tif (err < 0)\n+\t\treturn err;\n \tw->index[w->index_len] = index_record;\n \tw->index_len++;\n \n-- \n2.47.0.dirty\n\n"},{"id":"504833","messageId":"CAOLa=ZTHuWstTD56ZVTecW7ThHhpEqmrL28Emt5DtPL6pYhcpw@mail.gmail.com","threadId":"62313","inReplyTo":"abc28d7664f151e00568a6a3d18bf8a2de46470d.1728629612.git.ps@pks.im","subject":"Re: [PATCH 02/10] reftable: stop using `strbuf_addf()`","fromName":"karthik nayak","fromEmail":"karthik.188@gmail.com","sentAt":"2024-10-11T09:51:57Z","receivedAt":"2024-10-11T09:51:59Z","isPatch":true,"sender":{"key":"karthik.188@gmail.com","avatar":"https://avatars.githubusercontent.com/u/1786334?v=4"},"body":"Patrick Steinhardt <ps@pks.im> writes:\n\n[snip]\n\n> diff --git a/t/unit-tests/t-reftable-readwrite.c b/t/unit-tests/t-reftable-readwrite.c\n> index 27ce84445e8..5f59b0ad6ad 100644\n> --- a/t/unit-tests/t-reftable-readwrite.c\n> +++ b/t/unit-tests/t-reftable-readwrite.c\n> @@ -753,12 +753,13 @@ static void t_write_multiple_indices(void)\n>  \tstruct reftable_write_options opts = {\n>  \t\t.block_size = 100,\n>  \t};\n> -\tstruct strbuf writer_buf = STRBUF_INIT, buf = STRBUF_INIT;\n> +\tstruct strbuf writer_buf = STRBUF_INIT;\n>  \tstruct reftable_block_source source = { 0 };\n>  \tstruct reftable_iterator it = { 0 };\n>  \tconst struct reftable_stats *stats;\n>  \tstruct reftable_writer *writer;\n>  \tstruct reftable_reader *reader;\n> +\tchar buf[128];\n>  \tint err, i;\n>\n>  \twriter = t_reftable_strbuf_writer(&writer_buf, &opts);\n> @@ -770,9 +771,8 @@ static void t_write_multiple_indices(void)\n>  \t\t\t.value.val1 = {i},\n>  \t\t};\n>\n> -\t\tstrbuf_reset(&buf);\n\nHere, it is okay to remove this, since we define our own buf array.\n\n> -\t\tstrbuf_addf(&buf, \"refs/heads/%04d\", i);\n> -\t\tref.refname = buf.buf,\n> +\t\tsnprintf(buf, sizeof(buf), \"refs/heads/%04d\", i);\n> +\t\tref.refname = buf;\n>\n>  \t\terr = reftable_writer_add_ref(writer, &ref);\n>  \t\tcheck(!err);\n> @@ -788,9 +788,8 @@ static void t_write_multiple_indices(void)\n\n[snip]\n\n> @@ -1077,8 +1078,10 @@ static void t_reftable_stack_auto_compaction_with_locked_tables(void)\n>  \t * size, we expect that auto-compaction will want to compact all of the\n>  \t * tables. Locking any of the tables will keep it from doing so.\n>  \t */\n> -\tstrbuf_reset(&buf);\n\nHowever here it is different, since we still use the strbuf. I guess it\nshould be okay, since 'buf' is initialized using 'STRBUF_INIT' and that\nstill keeps the buf.len to 0.\n\n> -\tstrbuf_addf(&buf, \"%s/%s.lock\", dir, st->readers[2]->name);\n> +\tstrbuf_addstr(&buf, dir);\n> +\tstrbuf_addstr(&buf, \"/\");\n> +\tstrbuf_addstr(&buf, st->readers[2]->name);\n> +\tstrbuf_addstr(&buf, \".lock\");\n>  \twrite_file_buf(buf.buf, \"\", 0);\n>\n\nSo when we do 'strbuf_addstr(&buf, ...)' it should allocate the required\nmemory. But the reset removal did catch my eye.\n\n[snip]\n"},{"id":"504834","messageId":"CAOLa=ZSwHeDAFi9RTzuGAi+5ogo9L6XG2K9WHY8kmvz6v-ZAeQ@mail.gmail.com","threadId":"62313","inReplyTo":"24e31619b936166404b801dde0e2bca478328386.1728629612.git.ps@pks.im","subject":"Re: [PATCH 03/10] reftable/basics: provide new `reftable_buf` interface","fromName":"karthik nayak","fromEmail":"karthik.188@gmail.com","sentAt":"2024-10-11T10:03:39Z","receivedAt":"2024-10-11T10:03:41Z","isPatch":true,"sender":{"key":"karthik.188@gmail.com","avatar":"https://avatars.githubusercontent.com/u/1786334?v=4"},"body":"Patrick Steinhardt <ps@pks.im> writes:\n\n> Implement a new `reftable_buf` interface that will replace Git's own\n> `strbuf` interface. This is done due to three reasons:\n>\n>   - The `strbuf` interfaces do not handle memory allocation failures and\n>     instead causes us to die. This is okay in the context of Git, but is\n>     not context of the reftable library, which is supposed to be usable\n\ns/not/not in the/\n\n>     by third-party applications.\n>\n>   - The `strbuf` interface is quite deeply tied into Git, which makes it\n>     hard to use the reftable library as a standalone library. Any\n>     dependent would have to carefully extract the relevant parts of it\n>     to make things work, which is not all that sensible.\n>\n>   - The `strbuf` interface does not use the pluggable allocators that\n>     can be set up via `refatble_set_alloc()`.\n>\n> So we have good reasons to use our own type, and the implementation is\n> rather trivial. Implement our own type. Conversion of the reftable\n> library will be handled in subsequent commits.\n>\n> Signed-off-by: Patrick Steinhardt <ps@pks.im>\n\n[snip]\n\n> diff --git a/reftable/basics.h b/reftable/basics.h\n> index 4c9ef0fe6c5..4cf3f0e7593 100644\n> --- a/reftable/basics.h\n> +++ b/reftable/basics.h\n> @@ -16,6 +16,22 @@ license that can be found in the LICENSE file or at\n>  #include \"system.h\"\n>  #include \"reftable-basics.h\"\n>\n> +struct reftable_buf {\n> +\tsize_t alloc;\n> +\tsize_t len;\n> +\tchar *buf;\n> +};\n> +#define REFTABLE_BUF_INIT { 0 }\n> +\n> +void reftable_buf_init(struct reftable_buf *buf);\n> +void reftable_buf_release(struct reftable_buf *buf);\n> +void reftable_buf_reset(struct reftable_buf *buf);\n> +int reftable_buf_setlen(struct reftable_buf *buf, size_t len);\n> +int reftable_buf_cmp(const struct reftable_buf *a, const struct reftable_buf *b);\n> +int reftable_buf_add(struct reftable_buf *buf, const void *data, size_t len);\n> +int reftable_buf_addstr(struct reftable_buf *buf, const char *s);\n> +char *reftable_buf_detach(struct reftable_buf *buf);\n> +\n\nNit: would be nice to have some comments explaining the functions here.\nI know most of them are self-explanatory and similar to strbuf, but\nsince this is supposed to be isolated, it would be nice.\n\n[snip]\n"},{"id":"504835","messageId":"CAOLa=ZTOVGNxqJq0mj9GuLFqa6mVHp7WOkhuQsgiW79OKhhyNg@mail.gmail.com","threadId":"62313","inReplyTo":"e2ac27dbca0956bc231ad2a866bd796170deacf4.1728629612.git.ps@pks.im","subject":"Re: [PATCH 04/10] reftable: convert from `strbuf` to `reftable_buf`","fromName":"karthik nayak","fromEmail":"karthik.188@gmail.com","sentAt":"2024-10-11T12:12:59Z","receivedAt":"2024-10-11T12:13:01Z","isPatch":true,"sender":{"key":"karthik.188@gmail.com","avatar":"https://avatars.githubusercontent.com/u/1786334?v=4"},"body":"Patrick Steinhardt <ps@pks.im> writes:\n\n> Convert the reftable library to use the `reftable_buf` interface instead\n> of the `strbuf` interface. This is a mechanical change via sed(1) and\n> does not yet handle allocation failures. These will be addressed in\n> subsequent commits.\n>\n\nNit: Would be nice to list the sed command used here, so reviewers can\nreview that instead.\n\n[snip]\n\n> diff --git a/reftable/basics.h b/reftable/basics.h\n> index 4cf3f0e7593..ac3100417ec 100644\n> --- a/reftable/basics.h\n> +++ b/reftable/basics.h\n> @@ -104,8 +104,7 @@ char *reftable_strdup(const char *str);\n>  #endif\n>\n>  /* Find the longest shared prefix size of `a` and `b` */\n> -struct strbuf;\n\nI guess this is the only manual part of this commit, would be nice to\nmention this in the message.\n\n> -int common_prefix_size(struct strbuf *a, struct strbuf *b);\n> +int common_prefix_size(struct reftable_buf *a, struct reftable_buf *b);\n>\n>  int hash_size(uint32_t id);\n>\n[snip]\n"},{"id":"504836","messageId":"CAOLa=ZR_fcq0NyraV01FQBeOZ=uv7JWLV0+tSsi=zsvt+VZOdw@mail.gmail.com","threadId":"62313","inReplyTo":"cover.1728629612.git.ps@pks.im","subject":"Re: [PATCH 00/10] reftable: stop using `struct strbuf`","fromName":"karthik nayak","fromEmail":"karthik.188@gmail.com","sentAt":"2024-10-11T12:18:26Z","receivedAt":"2024-10-11T12:18:27Z","isPatch":true,"sender":{"key":"karthik.188@gmail.com","avatar":"https://avatars.githubusercontent.com/u/1786334?v=4"},"body":"Patrick Steinhardt <ps@pks.im> writes:\n\n> Hi,\n>\n> this is the second patch series on my quest to make the reftable library\n> become a standalone library again that can be used by libgit2 without\n> pulling in all kinds of dependencies from the Git codebase. This part\n> makes us lose the dependency on `struct strbuf`, which is done due to\n> three reasons:\n>\n>   - To make us independent of libgit.a.\n>\n>   - To ensure that we use the pluggable allocators that users can set up\n>     via `reftable_set_alloc()`.\n>\n>   - To make it possible to handle memory allocation failures.\n>\n> While this leads to some duplication, we're only talking about ~70 lines\n> of code.\n>\n\nI only have a few small comments, but overall this series looks good.\nThanks\n\n[snip]\n"},{"id":"504999","messageId":"cover.1728910726.git.ps@pks.im","threadId":"62313","inReplyTo":"cover.1728629612.git.ps@pks.im","subject":"[PATCH v2 00/10] reftable: stop using `struct strbuf`","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-10-14T13:02:16Z","receivedAt":"2024-10-14T13:02:24Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"Hi,\n\nthis is the second part of my patch series that stop using `struct\nstrbuf` in the reftable library. This is done such that the reftable\nlibrary becomes standalone again and so that we can use the pluggable\nallocators part of the library.\n\nChanges compared to v1:\n\n  - Point out a while-at-it refactoring when getting rid of\n    `strbuf_addf()`.\n\n  - Fix grammar issue in another commit message.\n\n  - Use REFTABLE_OUT_OF_MEMORY_ERROR error codes on allocation failure.\n\n  - Add documentation for `struct reftable_buf` functions.\n\n  - Clarify that the conversion to use the new interface is not wholly\n    mechanical via sed(1).\n\nThanks!\n\nPatrick\n\nPatrick Steinhardt (10):\n  reftable: stop using `strbuf_addbuf()`\n  reftable: stop using `strbuf_addf()`\n  reftable/basics: provide new `reftable_buf` interface\n  reftable: convert from `strbuf` to `reftable_buf`\n  reftable/blocksource: adapt interface name\n  t/unit-tests: check for `reftable_buf` allocation errors\n  reftable/stack: adapt `format_name()` to handle allocation failures\n  reftable/record: adapt `reftable_record_key()` to handle allocation\n    failures\n  reftable/stack: adapt `stack_filename()` to handle allocation failures\n  reftable: handle trivial `reftable_buf` errors\n\n reftable/basics.c                   |  76 +++++++++-\n reftable/basics.h                   |  59 +++++++-\n reftable/block.c                    |  61 +++++---\n reftable/block.h                    |  14 +-\n reftable/blocksource.c              |  30 ++--\n reftable/blocksource.h              |   5 +-\n reftable/iter.c                     |   9 +-\n reftable/iter.h                     |   8 +-\n reftable/reader.c                   |  27 ++--\n reftable/record.c                   | 114 ++++++++------\n reftable/record.h                   |  21 +--\n reftable/stack.c                    | 221 ++++++++++++++++++----------\n reftable/system.h                   |   1 -\n reftable/writer.c                   | 102 ++++++++-----\n reftable/writer.h                   |   2 +-\n t/unit-tests/lib-reftable.c         |   4 +-\n t/unit-tests/lib-reftable.h         |   7 +-\n t/unit-tests/t-reftable-basics.c    |  16 +-\n t/unit-tests/t-reftable-block.c     |  53 +++----\n t/unit-tests/t-reftable-merged.c    |  32 ++--\n t/unit-tests/t-reftable-reader.c    |  12 +-\n t/unit-tests/t-reftable-readwrite.c | 134 +++++++++--------\n t/unit-tests/t-reftable-record.c    |  74 +++++-----\n t/unit-tests/t-reftable-stack.c     |  96 ++++++------\n 24 files changed, 726 insertions(+), 452 deletions(-)\n\nRange-diff against v1:\n 1:  7408482c152 =  1:  7408482c152 reftable: stop using `strbuf_addbuf()`\n 2:  abc28d7664f !  2:  6a7333b275e reftable: stop using `strbuf_addf()`\n    @@ Commit message\n         `strbuf`. Get rid of the seldomly-used `strbuf_addf()` function such\n         that we have to reimplement one less function.\n     \n    +    While at it, remove a useless call to `strbuf_reset()` in\n    +    `t_reftable_stack_auto_compaction_with_locked_tables()`. We don't write\n    +    to the buffer before this and initialize it with `STRBUF_INIT`, so there\n    +    is no need to reset anything.\n    +\n         Signed-off-by: Patrick Steinhardt <ps@pks.im>\n     \n      ## reftable/stack.c ##\n 3:  24e31619b93 !  3:  0ddc8c0c896 reftable/basics: provide new `reftable_buf` interface\n    @@ Commit message\n     \n           - The `strbuf` interfaces do not handle memory allocation failures and\n             instead causes us to die. This is okay in the context of Git, but is\n    -        not context of the reftable library, which is supposed to be usable\n    -        by third-party applications.\n    +        not in the context of the reftable library, which is supposed to be\n    +        usable by third-party applications.\n     \n           - The `strbuf` interface is quite deeply tied into Git, which makes it\n             hard to use the reftable library as a standalone library. Any\n    @@ Commit message\n         Signed-off-by: Patrick Steinhardt <ps@pks.im>\n     \n      ## reftable/basics.c ##\n    +@@ reftable/basics.c: license that can be found in the LICENSE file or at\n    + #define REFTABLE_ALLOW_BANNED_ALLOCATORS\n    + #include \"basics.h\"\n    + #include \"reftable-basics.h\"\n    ++#include \"reftable-error.h\"\n    + \n    + static void *(*reftable_malloc_ptr)(size_t sz);\n    + static void *(*reftable_realloc_ptr)(void *, size_t);\n     @@ reftable/basics.c: void reftable_set_alloc(void *(*malloc)(size_t),\n      \treftable_free_ptr = free;\n      }\n    @@ reftable/basics.c: void reftable_set_alloc(void *(*malloc)(size_t),\n     +\t\tchar *reallocated = buf->buf;\n     +\t\tREFTABLE_ALLOC_GROW(reallocated, newlen + 1, buf->alloc);\n     +\t\tif (!reallocated)\n    -+\t\t\treturn -1;\n    ++\t\t\treturn REFTABLE_OUT_OF_MEMORY_ERROR;\n     +\t\tbuf->buf = reallocated;\n     +\t}\n     +\n    @@ reftable/basics.h: license that can be found in the LICENSE file or at\n     +};\n     +#define REFTABLE_BUF_INIT { 0 }\n     +\n    ++/*\n    ++ * Initialize the buffer such that it is ready for use. This is equivalent to\n    ++ * using REFTABLE_BUF_INIT for stack-allocated variables.\n    ++ */\n     +void reftable_buf_init(struct reftable_buf *buf);\n    ++\n    ++/*\n    ++ * Release memory associated with the buffer. The buffer is reinitialized such\n    ++ * that it can be reused for subsequent operations.\n    ++ */\n     +void reftable_buf_release(struct reftable_buf *buf);\n    ++\n    ++/*\n    ++ * Reset the buffer such that it is effectively empty, without releasing the\n    ++ * memory that this structure holds on to. This is equivalent to calling\n    ++ * `reftable_buf_setlen(buf, 0)`.\n    ++ */\n     +void reftable_buf_reset(struct reftable_buf *buf);\n    ++\n    ++/*\n    ++ * Trim the buffer to a shorter length by updating the `len` member and writing\n    ++ * a NUL byte to `buf[len]`. Returns 0 on success, -1 when `len` points outside\n    ++ * of the array.\n    ++ */\n     +int reftable_buf_setlen(struct reftable_buf *buf, size_t len);\n    ++\n    ++/*\n    ++ * Lexicographically compare the two buffers. Returns 0 when both buffers have\n    ++ * the same contents, -1 when `a` is lexicographically smaller than `b`, and 1\n    ++ * otherwise.\n    ++ */\n     +int reftable_buf_cmp(const struct reftable_buf *a, const struct reftable_buf *b);\n    ++\n    ++/*\n    ++ * Add the given bytes to the buffer. Returns 0 on success,\n    ++ * REFTABLE_OUT_OF_MEMORY_ERROR on allocation failure.\n    ++ */\n     +int reftable_buf_add(struct reftable_buf *buf, const void *data, size_t len);\n    ++\n    ++/* Equivalent to `reftable_buf_add(buf, s, strlen(s))`. */\n     +int reftable_buf_addstr(struct reftable_buf *buf, const char *s);\n    ++\n    ++/*\n    ++ * Detach the buffer from the structure such that the underlying memory is now\n    ++ * owned by the caller. The buffer is reinitialized such that it can be reused\n    ++ * for subsequent operations.\n    ++ */\n     +char *reftable_buf_detach(struct reftable_buf *buf);\n     +\n      /* Bigendian en/decoding of integers */\n 4:  e2ac27dbca0 !  4:  e1ff1af1f30 reftable: convert from `strbuf` to `reftable_buf`\n    @@ Commit message\n         reftable: convert from `strbuf` to `reftable_buf`\n     \n         Convert the reftable library to use the `reftable_buf` interface instead\n    -    of the `strbuf` interface. This is a mechanical change via sed(1) and\n    -    does not yet handle allocation failures. These will be addressed in\n    -    subsequent commits.\n    +    of the `strbuf` interface. This is mostly a mechanical change via sed(1)\n    +    with some manual fixes where functions for `strbuf` and `reftable_buf`\n    +    differ. The converted code does not yet handle allocation failures. This\n    +    will be handled in subsequent commits.\n     \n         Signed-off-by: Patrick Steinhardt <ps@pks.im>\n     \n 5:  da432d7a384 =  5:  fe8c9ace463 reftable/blocksource: adapt interface name\n 6:  797e435ed2e =  6:  8c98745233a t/unit-tests: check for `reftable_buf` allocation errors\n 7:  66ee431db46 =  7:  1f08163009b reftable/stack: adapt `format_name()` to handle allocation failures\n 8:  f5ae5ec27d6 =  8:  5798d76d7a4 reftable/record: adapt `reftable_record_key()` to handle allocation failures\n 9:  d66d9e50e06 =  9:  a9582d51dd1 reftable/stack: adapt `stack_filename()` to handle allocation failures\n10:  8406948ae74 = 10:  90819c90f38 reftable: handle trivial `reftable_buf` errors\n-- \n2.47.0.dirty\n\n"},{"id":"505000","messageId":"7408482c152bbf465ecd098059b1477fd38c251a.1728910727.git.ps@pks.im","threadId":"62313","inReplyTo":"cover.1728910726.git.ps@pks.im","subject":"[PATCH v2 01/10] reftable: stop using `strbuf_addbuf()`","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-10-14T13:02:19Z","receivedAt":"2024-10-14T13:02:26Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"We're about to introduce our own `reftable_buf` type to replace\n`strbuf`. Get rid of the seldomly-used `strbuf_addbuf()` function such\nthat we have to reimplement one less function.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n reftable/block.c  | 2 +-\n reftable/record.c | 6 +++---\n reftable/writer.c | 7 ++++---\n 3 files changed, 8 insertions(+), 7 deletions(-)\n\ndiff --git a/reftable/block.c b/reftable/block.c\nindex 8d41a2f99ed..cd4180eac7b 100644\n--- a/reftable/block.c\n+++ b/reftable/block.c\n@@ -60,7 +60,7 @@ static int block_writer_register_restart(struct block_writer *w, int n,\n \tw->next += n;\n \n \tstrbuf_reset(&w->last_key);\n-\tstrbuf_addbuf(&w->last_key, key);\n+\tstrbuf_add(&w->last_key, key->buf, key->len);\n \tw->entries++;\n \treturn 0;\n }\ndiff --git a/reftable/record.c b/reftable/record.c\nindex 30d563e16d3..87157f2c386 100644\n--- a/reftable/record.c\n+++ b/reftable/record.c\n@@ -1031,7 +1031,7 @@ static void reftable_index_record_key(const void *r, struct strbuf *dest)\n {\n \tconst struct reftable_index_record *rec = r;\n \tstrbuf_reset(dest);\n-\tstrbuf_addbuf(dest, &rec->last_key);\n+\tstrbuf_add(dest, rec->last_key.buf, rec->last_key.len);\n }\n \n static int reftable_index_record_copy_from(void *rec, const void *src_rec,\n@@ -1041,7 +1041,7 @@ static int reftable_index_record_copy_from(void *rec, const void *src_rec,\n \tconst struct reftable_index_record *src = src_rec;\n \n \tstrbuf_reset(&dst->last_key);\n-\tstrbuf_addbuf(&dst->last_key, &src->last_key);\n+\tstrbuf_add(&dst->last_key, src->last_key.buf, src->last_key.len);\n \tdst->offset = src->offset;\n \n \treturn 0;\n@@ -1085,7 +1085,7 @@ static int reftable_index_record_decode(void *rec, struct strbuf key,\n \tint n = 0;\n \n \tstrbuf_reset(&r->last_key);\n-\tstrbuf_addbuf(&r->last_key, &key);\n+\tstrbuf_add(&r->last_key, key.buf, key.len);\n \n \tn = get_var_int(&r->offset, &in);\n \tif (n < 0)\ndiff --git a/reftable/writer.c b/reftable/writer.c\nindex b032a47decb..031d8149a9c 100644\n--- a/reftable/writer.c\n+++ b/reftable/writer.c\n@@ -225,7 +225,7 @@ static int writer_index_hash(struct reftable_writer *w, struct strbuf *hash)\n \t\t*key = empty;\n \n \t\tstrbuf_reset(&key->hash);\n-\t\tstrbuf_addbuf(&key->hash, hash);\n+\t\tstrbuf_add(&key->hash, hash->buf, hash->len);\n \t\ttree_insert(&w->obj_index_tree, key,\n \t\t\t    &obj_index_tree_node_compare);\n \t} else {\n@@ -256,7 +256,7 @@ static int writer_add_record(struct reftable_writer *w,\n \t}\n \n \tstrbuf_reset(&w->last_key);\n-\tstrbuf_addbuf(&w->last_key, &key);\n+\tstrbuf_add(&w->last_key, key.buf, key.len);\n \tif (!w->block_writer) {\n \t\terr = writer_reinit_block_writer(w, reftable_record_type(rec));\n \t\tif (err < 0)\n@@ -778,7 +778,8 @@ static int writer_flush_nonempty_block(struct reftable_writer *w)\n \n \tindex_record.offset = w->next;\n \tstrbuf_reset(&index_record.last_key);\n-\tstrbuf_addbuf(&index_record.last_key, &w->block_writer->last_key);\n+\tstrbuf_add(&index_record.last_key, w->block_writer->last_key.buf,\n+\t\t   w->block_writer->last_key.len);\n \tw->index[w->index_len] = index_record;\n \tw->index_len++;\n \n-- \n2.47.0.dirty\n\n"},{"id":"505001","messageId":"6a7333b275e9f7eab81568a8de939011d292a31a.1728910727.git.ps@pks.im","threadId":"62313","inReplyTo":"cover.1728910726.git.ps@pks.im","subject":"[PATCH v2 02/10] reftable: stop using `strbuf_addf()`","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-10-14T13:02:21Z","receivedAt":"2024-10-14T13:02:26Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"We're about to introduce our own `reftable_buf` type to replace\n`strbuf`. Get rid of the seldomly-used `strbuf_addf()` function such\nthat we have to reimplement one less function.\n\nWhile at it, remove a useless call to `strbuf_reset()` in\n`t_reftable_stack_auto_compaction_with_locked_tables()`. We don't write\nto the buffer before this and initialize it with `STRBUF_INIT`, so there\nis no need to reset anything.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n reftable/stack.c                    | 18 ++++++++-----\n t/unit-tests/t-reftable-block.c     |  7 +++--\n t/unit-tests/t-reftable-readwrite.c | 20 +++++++-------\n t/unit-tests/t-reftable-stack.c     | 42 ++++++++++++++++-------------\n 4 files changed, 50 insertions(+), 37 deletions(-)\n\ndiff --git a/reftable/stack.c b/reftable/stack.c\nindex 7e617c25914..d7bc1187dfb 100644\n--- a/reftable/stack.c\n+++ b/reftable/stack.c\n@@ -1387,12 +1387,18 @@ static int stack_compact_range(struct reftable_stack *st,\n \t * have just written. In case the compacted table became empty we\n \t * simply skip writing it.\n \t */\n-\tfor (i = 0; i < first_to_replace; i++)\n-\t\tstrbuf_addf(&tables_list_buf, \"%s\\n\", names[i]);\n-\tif (!is_empty_table)\n-\t\tstrbuf_addf(&tables_list_buf, \"%s\\n\", new_table_name.buf);\n-\tfor (i = last_to_replace + 1; names[i]; i++)\n-\t\tstrbuf_addf(&tables_list_buf, \"%s\\n\", names[i]);\n+\tfor (i = 0; i < first_to_replace; i++) {\n+\t\tstrbuf_addstr(&tables_list_buf, names[i]);\n+\t\tstrbuf_addstr(&tables_list_buf, \"\\n\");\n+\t}\n+\tif (!is_empty_table) {\n+\t\tstrbuf_addstr(&tables_list_buf, new_table_name.buf);\n+\t\tstrbuf_addstr(&tables_list_buf, \"\\n\");\n+\t}\n+\tfor (i = last_to_replace + 1; names[i]; i++) {\n+\t\tstrbuf_addstr(&tables_list_buf, names[i]);\n+\t\tstrbuf_addstr(&tables_list_buf, \"\\n\");\n+\t}\n \n \terr = write_in_full(get_lock_file_fd(&tables_list_lock),\n \t\t\t    tables_list_buf.buf, tables_list_buf.len);\ndiff --git a/t/unit-tests/t-reftable-block.c b/t/unit-tests/t-reftable-block.c\nindex d470060e8be..8077bbc5e7a 100644\n--- a/t/unit-tests/t-reftable-block.c\n+++ b/t/unit-tests/t-reftable-block.c\n@@ -308,10 +308,13 @@ static void t_index_block_read_write(void)\n \tcheck(!ret);\n \n \tfor (i = 0; i < N; i++) {\n-\t\tstrbuf_init(&recs[i].u.idx.last_key, 9);\n+\t\tchar buf[128];\n+\n+\t\tsnprintf(buf, sizeof(buf), \"branch%02\"PRIuMAX, (uintmax_t)i);\n \n+\t\tstrbuf_init(&recs[i].u.idx.last_key, 9);\n \t\trecs[i].type = BLOCK_TYPE_INDEX;\n-\t\tstrbuf_addf(&recs[i].u.idx.last_key, \"branch%02\"PRIuMAX, (uintmax_t)i);\n+\t\tstrbuf_addstr(&recs[i].u.idx.last_key, buf);\n \t\trecs[i].u.idx.offset = i;\n \n \t\tret = block_writer_add(&bw, &recs[i]);\ndiff --git a/t/unit-tests/t-reftable-readwrite.c b/t/unit-tests/t-reftable-readwrite.c\nindex 27ce84445e8..5f59b0ad6ad 100644\n--- a/t/unit-tests/t-reftable-readwrite.c\n+++ b/t/unit-tests/t-reftable-readwrite.c\n@@ -753,12 +753,13 @@ static void t_write_multiple_indices(void)\n \tstruct reftable_write_options opts = {\n \t\t.block_size = 100,\n \t};\n-\tstruct strbuf writer_buf = STRBUF_INIT, buf = STRBUF_INIT;\n+\tstruct strbuf writer_buf = STRBUF_INIT;\n \tstruct reftable_block_source source = { 0 };\n \tstruct reftable_iterator it = { 0 };\n \tconst struct reftable_stats *stats;\n \tstruct reftable_writer *writer;\n \tstruct reftable_reader *reader;\n+\tchar buf[128];\n \tint err, i;\n \n \twriter = t_reftable_strbuf_writer(&writer_buf, &opts);\n@@ -770,9 +771,8 @@ static void t_write_multiple_indices(void)\n \t\t\t.value.val1 = {i},\n \t\t};\n \n-\t\tstrbuf_reset(&buf);\n-\t\tstrbuf_addf(&buf, \"refs/heads/%04d\", i);\n-\t\tref.refname = buf.buf,\n+\t\tsnprintf(buf, sizeof(buf), \"refs/heads/%04d\", i);\n+\t\tref.refname = buf;\n \n \t\terr = reftable_writer_add_ref(writer, &ref);\n \t\tcheck(!err);\n@@ -788,9 +788,8 @@ static void t_write_multiple_indices(void)\n \t\t\t},\n \t\t};\n \n-\t\tstrbuf_reset(&buf);\n-\t\tstrbuf_addf(&buf, \"refs/heads/%04d\", i);\n-\t\tlog.refname = buf.buf,\n+\t\tsnprintf(buf, sizeof(buf), \"refs/heads/%04d\", i);\n+\t\tlog.refname = buf;\n \n \t\terr = reftable_writer_add_log(writer, &log);\n \t\tcheck(!err);\n@@ -824,7 +823,6 @@ static void t_write_multiple_indices(void)\n \treftable_writer_free(writer);\n \treftable_reader_decref(reader);\n \tstrbuf_release(&writer_buf);\n-\tstrbuf_release(&buf);\n }\n \n static void t_write_multi_level_index(void)\n@@ -848,10 +846,10 @@ static void t_write_multi_level_index(void)\n \t\t\t.value_type = REFTABLE_REF_VAL1,\n \t\t\t.value.val1 = {i},\n \t\t};\n+\t\tchar buf[128];\n \n-\t\tstrbuf_reset(&buf);\n-\t\tstrbuf_addf(&buf, \"refs/heads/%03\" PRIuMAX, (uintmax_t)i);\n-\t\tref.refname = buf.buf,\n+\t\tsnprintf(buf, sizeof(buf), \"refs/heads/%03\" PRIuMAX, (uintmax_t)i);\n+\t\tref.refname = buf;\n \n \t\terr = reftable_writer_add_ref(writer, &ref);\n \t\tcheck(!err);\ndiff --git a/t/unit-tests/t-reftable-stack.c b/t/unit-tests/t-reftable-stack.c\nindex 874095b9ee2..b56ea774312 100644\n--- a/t/unit-tests/t-reftable-stack.c\n+++ b/t/unit-tests/t-reftable-stack.c\n@@ -105,7 +105,6 @@ static int write_test_ref(struct reftable_writer *wr, void *arg)\n static void write_n_ref_tables(struct reftable_stack *st,\n \t\t\t       size_t n)\n {\n-\tstruct strbuf buf = STRBUF_INIT;\n \tint disable_auto_compact;\n \tint err;\n \n@@ -117,10 +116,10 @@ static void write_n_ref_tables(struct reftable_stack *st,\n \t\t\t.update_index = reftable_stack_next_update_index(st),\n \t\t\t.value_type = REFTABLE_REF_VAL1,\n \t\t};\n+\t\tchar buf[128];\n \n-\t\tstrbuf_reset(&buf);\n-\t\tstrbuf_addf(&buf, \"refs/heads/branch-%04\"PRIuMAX, (uintmax_t)i);\n-\t\tref.refname = buf.buf;\n+\t\tsnprintf(buf, sizeof(buf), \"refs/heads/branch-%04\"PRIuMAX, (uintmax_t)i);\n+\t\tref.refname = buf;\n \t\tt_reftable_set_hash(ref.value.val1, i, GIT_SHA1_FORMAT_ID);\n \n \t\terr = reftable_stack_add(st, &write_test_ref, &ref);\n@@ -128,7 +127,6 @@ static void write_n_ref_tables(struct reftable_stack *st,\n \t}\n \n \tst->opts.disable_auto_compact = disable_auto_compact;\n-\tstrbuf_release(&buf);\n }\n \n struct write_log_arg {\n@@ -434,7 +432,10 @@ static void t_reftable_stack_auto_compaction_fails_gracefully(void)\n \t * Adding a new table to the stack should not be impacted by this, even\n \t * though auto-compaction will now fail.\n \t */\n-\tstrbuf_addf(&table_path, \"%s/%s.lock\", dir, st->readers[0]->name);\n+\tstrbuf_addstr(&table_path, dir);\n+\tstrbuf_addstr(&table_path, \"/\");\n+\tstrbuf_addstr(&table_path, st->readers[0]->name);\n+\tstrbuf_addstr(&table_path, \".lock\");\n \twrite_file_buf(table_path.buf, \"\", 0);\n \n \tref.update_index = 2;\n@@ -1077,8 +1078,10 @@ static void t_reftable_stack_auto_compaction_with_locked_tables(void)\n \t * size, we expect that auto-compaction will want to compact all of the\n \t * tables. Locking any of the tables will keep it from doing so.\n \t */\n-\tstrbuf_reset(&buf);\n-\tstrbuf_addf(&buf, \"%s/%s.lock\", dir, st->readers[2]->name);\n+\tstrbuf_addstr(&buf, dir);\n+\tstrbuf_addstr(&buf, \"/\");\n+\tstrbuf_addstr(&buf, st->readers[2]->name);\n+\tstrbuf_addstr(&buf, \".lock\");\n \twrite_file_buf(buf.buf, \"\", 0);\n \n \t/*\n@@ -1101,7 +1104,6 @@ static void t_reftable_stack_add_performs_auto_compaction(void)\n {\n \tstruct reftable_write_options opts = { 0 };\n \tstruct reftable_stack *st = NULL;\n-\tstruct strbuf refname = STRBUF_INIT;\n \tchar *dir = get_tmp_dir(__LINE__);\n \tint err;\n \tsize_t i, n = 20;\n@@ -1115,6 +1117,7 @@ static void t_reftable_stack_add_performs_auto_compaction(void)\n \t\t\t.value_type = REFTABLE_REF_SYMREF,\n \t\t\t.value.symref = (char *) \"master\",\n \t\t};\n+\t\tchar buf[128];\n \n \t\t/*\n \t\t * Disable auto-compaction for all but the last runs. Like this\n@@ -1123,9 +1126,8 @@ static void t_reftable_stack_add_performs_auto_compaction(void)\n \t\t */\n \t\tst->opts.disable_auto_compact = i != n;\n \n-\t\tstrbuf_reset(&refname);\n-\t\tstrbuf_addf(&refname, \"branch-%04\"PRIuMAX, (uintmax_t)i);\n-\t\tref.refname = refname.buf;\n+\t\tsnprintf(buf, sizeof(buf), \"branch-%04\"PRIuMAX, (uintmax_t)i);\n+\t\tref.refname = buf;\n \n \t\terr = reftable_stack_add(st, write_test_ref, &ref);\n \t\tcheck(!err);\n@@ -1142,7 +1144,6 @@ static void t_reftable_stack_add_performs_auto_compaction(void)\n \t}\n \n \treftable_stack_destroy(st);\n-\tstrbuf_release(&refname);\n \tclear_dir(dir);\n }\n \n@@ -1163,8 +1164,10 @@ static void t_reftable_stack_compaction_with_locked_tables(void)\n \tcheck_int(st->merged->readers_len, ==, 3);\n \n \t/* Lock one of the tables that we're about to compact. */\n-\tstrbuf_reset(&buf);\n-\tstrbuf_addf(&buf, \"%s/%s.lock\", dir, st->readers[1]->name);\n+\tstrbuf_addstr(&buf, dir);\n+\tstrbuf_addstr(&buf, \"/\");\n+\tstrbuf_addstr(&buf, st->readers[1]->name);\n+\tstrbuf_addstr(&buf, \".lock\");\n \twrite_file_buf(buf.buf, \"\", 0);\n \n \t/*\n@@ -1321,10 +1324,13 @@ static void t_reftable_stack_reload_with_missing_table(void)\n \t * our old readers. This should trigger a partial reload of the stack,\n \t * where we try to reuse our old readers.\n \t*/\n-\tstrbuf_addf(&content, \"%s\\n\", st->readers[0]->name);\n-\tstrbuf_addf(&content, \"%s\\n\", st->readers[1]->name);\n+\tstrbuf_addstr(&content, st->readers[0]->name);\n+\tstrbuf_addstr(&content, \"\\n\");\n+\tstrbuf_addstr(&content, st->readers[1]->name);\n+\tstrbuf_addstr(&content, \"\\n\");\n \tstrbuf_addstr(&content, \"garbage\\n\");\n-\tstrbuf_addf(&table_path, \"%s.lock\", st->list_file);\n+\tstrbuf_addstr(&table_path, st->list_file);\n+\tstrbuf_addstr(&table_path, \".lock\");\n \twrite_file_buf(table_path.buf, content.buf, content.len);\n \terr = rename(table_path.buf, st->list_file);\n \tcheck(!err);\n-- \n2.47.0.dirty\n\n"},{"id":"505002","messageId":"0ddc8c0c896a006e4cc094390125efcec0b3cdff.1728910727.git.ps@pks.im","threadId":"62313","inReplyTo":"cover.1728910726.git.ps@pks.im","subject":"[PATCH v2 03/10] reftable/basics: provide new `reftable_buf` interface","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-10-14T13:02:24Z","receivedAt":"2024-10-14T13:02:32Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"Implement a new `reftable_buf` interface that will replace Git's own\n`strbuf` interface. This is done due to three reasons:\n\n  - The `strbuf` interfaces do not handle memory allocation failures and\n    instead causes us to die. This is okay in the context of Git, but is\n    not in the context of the reftable library, which is supposed to be\n    usable by third-party applications.\n\n  - The `strbuf` interface is quite deeply tied into Git, which makes it\n    hard to use the reftable library as a standalone library. Any\n    dependent would have to carefully extract the relevant parts of it\n    to make things work, which is not all that sensible.\n\n  - The `strbuf` interface does not use the pluggable allocators that\n    can be set up via `refatble_set_alloc()`.\n\nSo we have good reasons to use our own type, and the implementation is\nrather trivial. Implement our own type. Conversion of the reftable\nlibrary will be handled in subsequent commits.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n reftable/basics.c | 74 +++++++++++++++++++++++++++++++++++++++++++++++\n reftable/basics.h | 56 +++++++++++++++++++++++++++++++++++\n 2 files changed, 130 insertions(+)\n\ndiff --git a/reftable/basics.c b/reftable/basics.c\nindex 9a949e5cf80..65ad761da0b 100644\n--- a/reftable/basics.c\n+++ b/reftable/basics.c\n@@ -9,6 +9,7 @@ license that can be found in the LICENSE file or at\n #define REFTABLE_ALLOW_BANNED_ALLOCATORS\n #include \"basics.h\"\n #include \"reftable-basics.h\"\n+#include \"reftable-error.h\"\n \n static void *(*reftable_malloc_ptr)(size_t sz);\n static void *(*reftable_realloc_ptr)(void *, size_t);\n@@ -69,6 +70,79 @@ void reftable_set_alloc(void *(*malloc)(size_t),\n \treftable_free_ptr = free;\n }\n \n+void reftable_buf_init(struct reftable_buf *buf)\n+{\n+\tstruct reftable_buf empty = REFTABLE_BUF_INIT;\n+\t*buf = empty;\n+}\n+\n+void reftable_buf_release(struct reftable_buf *buf)\n+{\n+\treftable_free(buf->buf);\n+\treftable_buf_init(buf);\n+}\n+\n+void reftable_buf_reset(struct reftable_buf *buf)\n+{\n+\tif (buf->alloc) {\n+\t\tbuf->len = 0;\n+\t\tbuf->buf[0] = '\\0';\n+\t}\n+}\n+\n+int reftable_buf_setlen(struct reftable_buf *buf, size_t len)\n+{\n+\tif (len > buf->len)\n+\t\treturn -1;\n+\tif (len == buf->len)\n+\t\treturn 0;\n+\tbuf->buf[len] = '\\0';\n+\tbuf->len = len;\n+\treturn 0;\n+}\n+\n+int reftable_buf_cmp(const struct reftable_buf *a, const struct reftable_buf *b)\n+{\n+\tsize_t len = a->len < b->len ? a->len : b->len;\n+\tif (len) {\n+\t\tint cmp = memcmp(a->buf, b->buf, len);\n+\t\tif (cmp)\n+\t\t\treturn cmp;\n+\t}\n+\treturn a->len < b->len ? -1 : a->len != b->len;\n+}\n+\n+int reftable_buf_add(struct reftable_buf *buf, const void *data, size_t len)\n+{\n+\tsize_t newlen = buf->len + len;\n+\n+\tif (newlen + 1 > buf->alloc) {\n+\t\tchar *reallocated = buf->buf;\n+\t\tREFTABLE_ALLOC_GROW(reallocated, newlen + 1, buf->alloc);\n+\t\tif (!reallocated)\n+\t\t\treturn REFTABLE_OUT_OF_MEMORY_ERROR;\n+\t\tbuf->buf = reallocated;\n+\t}\n+\n+\tmemcpy(buf->buf + buf->len, data, len);\n+\tbuf->buf[newlen] = '\\0';\n+\tbuf->len = newlen;\n+\n+\treturn 0;\n+}\n+\n+int reftable_buf_addstr(struct reftable_buf *buf, const char *s)\n+{\n+\treturn reftable_buf_add(buf, s, strlen(s));\n+}\n+\n+char *reftable_buf_detach(struct reftable_buf *buf)\n+{\n+\tchar *result = buf->buf;\n+\treftable_buf_init(buf);\n+\treturn result;\n+}\n+\n void put_be24(uint8_t *out, uint32_t i)\n {\n \tout[0] = (uint8_t)((i >> 16) & 0xff);\ndiff --git a/reftable/basics.h b/reftable/basics.h\nindex 4c9ef0fe6c5..bd33c34deae 100644\n--- a/reftable/basics.h\n+++ b/reftable/basics.h\n@@ -16,6 +16,62 @@ license that can be found in the LICENSE file or at\n #include \"system.h\"\n #include \"reftable-basics.h\"\n \n+struct reftable_buf {\n+\tsize_t alloc;\n+\tsize_t len;\n+\tchar *buf;\n+};\n+#define REFTABLE_BUF_INIT { 0 }\n+\n+/*\n+ * Initialize the buffer such that it is ready for use. This is equivalent to\n+ * using REFTABLE_BUF_INIT for stack-allocated variables.\n+ */\n+void reftable_buf_init(struct reftable_buf *buf);\n+\n+/*\n+ * Release memory associated with the buffer. The buffer is reinitialized such\n+ * that it can be reused for subsequent operations.\n+ */\n+void reftable_buf_release(struct reftable_buf *buf);\n+\n+/*\n+ * Reset the buffer such that it is effectively empty, without releasing the\n+ * memory that this structure holds on to. This is equivalent to calling\n+ * `reftable_buf_setlen(buf, 0)`.\n+ */\n+void reftable_buf_reset(struct reftable_buf *buf);\n+\n+/*\n+ * Trim the buffer to a shorter length by updating the `len` member and writing\n+ * a NUL byte to `buf[len]`. Returns 0 on success, -1 when `len` points outside\n+ * of the array.\n+ */\n+int reftable_buf_setlen(struct reftable_buf *buf, size_t len);\n+\n+/*\n+ * Lexicographically compare the two buffers. Returns 0 when both buffers have\n+ * the same contents, -1 when `a` is lexicographically smaller than `b`, and 1\n+ * otherwise.\n+ */\n+int reftable_buf_cmp(const struct reftable_buf *a, const struct reftable_buf *b);\n+\n+/*\n+ * Add the given bytes to the buffer. Returns 0 on success,\n+ * REFTABLE_OUT_OF_MEMORY_ERROR on allocation failure.\n+ */\n+int reftable_buf_add(struct reftable_buf *buf, const void *data, size_t len);\n+\n+/* Equivalent to `reftable_buf_add(buf, s, strlen(s))`. */\n+int reftable_buf_addstr(struct reftable_buf *buf, const char *s);\n+\n+/*\n+ * Detach the buffer from the structure such that the underlying memory is now\n+ * owned by the caller. The buffer is reinitialized such that it can be reused\n+ * for subsequent operations.\n+ */\n+char *reftable_buf_detach(struct reftable_buf *buf);\n+\n /* Bigendian en/decoding of integers */\n \n void put_be24(uint8_t *out, uint32_t i);\n-- \n2.47.0.dirty\n\n"},{"id":"505004","messageId":"e1ff1af1f302490f8d79301a73f7cd48314477ba.1728910727.git.ps@pks.im","threadId":"62313","inReplyTo":"cover.1728910726.git.ps@pks.im","subject":"[PATCH v2 04/10] reftable: convert from `strbuf` to `reftable_buf`","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-10-14T13:02:27Z","receivedAt":"2024-10-14T13:02:33Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"Convert the reftable library to use the `reftable_buf` interface instead\nof the `strbuf` interface. This is mostly a mechanical change via sed(1)\nwith some manual fixes where functions for `strbuf` and `reftable_buf`\ndiffer. The converted code does not yet handle allocation failures. This\nwill be handled in subsequent commits.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n reftable/basics.c                   |   2 +-\n reftable/basics.h                   |   3 +-\n reftable/block.c                    |  34 ++++----\n reftable/block.h                    |  14 ++--\n reftable/blocksource.c              |   6 +-\n reftable/blocksource.h              |   3 +-\n reftable/iter.c                     |   6 +-\n reftable/iter.h                     |   8 +-\n reftable/reader.c                   |  16 ++--\n reftable/record.c                   |  80 +++++++++----------\n reftable/record.h                   |  21 ++---\n reftable/stack.c                    | 120 ++++++++++++++--------------\n reftable/system.h                   |   1 -\n reftable/writer.c                   |  66 +++++++--------\n reftable/writer.h                   |   2 +-\n t/unit-tests/lib-reftable.c         |   4 +-\n t/unit-tests/lib-reftable.h         |   7 +-\n t/unit-tests/t-reftable-basics.c    |  16 ++--\n t/unit-tests/t-reftable-block.c     |  42 +++++-----\n t/unit-tests/t-reftable-merged.c    |  26 +++---\n t/unit-tests/t-reftable-reader.c    |   8 +-\n t/unit-tests/t-reftable-readwrite.c |  92 ++++++++++-----------\n t/unit-tests/t-reftable-record.c    |  74 ++++++++---------\n t/unit-tests/t-reftable-stack.c     |  90 ++++++++++-----------\n 24 files changed, 371 insertions(+), 370 deletions(-)\n\ndiff --git a/reftable/basics.c b/reftable/basics.c\nindex 65ad761da0b..bc4fcc91446 100644\n--- a/reftable/basics.c\n+++ b/reftable/basics.c\n@@ -260,7 +260,7 @@ int names_equal(const char **a, const char **b)\n \treturn a[i] == b[i];\n }\n \n-int common_prefix_size(struct strbuf *a, struct strbuf *b)\n+int common_prefix_size(struct reftable_buf *a, struct reftable_buf *b)\n {\n \tint p = 0;\n \tfor (; p < a->len && p < b->len; p++) {\ndiff --git a/reftable/basics.h b/reftable/basics.h\nindex bd33c34deae..9d3f13fe04d 100644\n--- a/reftable/basics.h\n+++ b/reftable/basics.h\n@@ -144,8 +144,7 @@ char *reftable_strdup(const char *str);\n #endif\n \n /* Find the longest shared prefix size of `a` and `b` */\n-struct strbuf;\n-int common_prefix_size(struct strbuf *a, struct strbuf *b);\n+int common_prefix_size(struct reftable_buf *a, struct reftable_buf *b);\n \n int hash_size(uint32_t id);\n \ndiff --git a/reftable/block.c b/reftable/block.c\nindex cd4180eac7b..4f62b823db8 100644\n--- a/reftable/block.c\n+++ b/reftable/block.c\n@@ -38,7 +38,7 @@ int footer_size(int version)\n }\n \n static int block_writer_register_restart(struct block_writer *w, int n,\n-\t\t\t\t\t int is_restart, struct strbuf *key)\n+\t\t\t\t\t int is_restart, struct reftable_buf *key)\n {\n \tint rlen = w->restart_len;\n \tif (rlen >= MAX_RESTARTS) {\n@@ -59,8 +59,8 @@ static int block_writer_register_restart(struct block_writer *w, int n,\n \n \tw->next += n;\n \n-\tstrbuf_reset(&w->last_key);\n-\tstrbuf_add(&w->last_key, key->buf, key->len);\n+\treftable_buf_reset(&w->last_key);\n+\treftable_buf_add(&w->last_key, key->buf, key->len);\n \tw->entries++;\n \treturn 0;\n }\n@@ -98,8 +98,8 @@ uint8_t block_writer_type(struct block_writer *bw)\n    empty key. */\n int block_writer_add(struct block_writer *w, struct reftable_record *rec)\n {\n-\tstruct strbuf empty = STRBUF_INIT;\n-\tstruct strbuf last =\n+\tstruct reftable_buf empty = REFTABLE_BUF_INIT;\n+\tstruct reftable_buf last =\n \t\tw->entries % w->restart_interval == 0 ? empty : w->last_key;\n \tstruct string_view out = {\n \t\t.buf = w->buf + w->next,\n@@ -109,7 +109,7 @@ int block_writer_add(struct block_writer *w, struct reftable_record *rec)\n \tstruct string_view start = out;\n \n \tint is_restart = 0;\n-\tstruct strbuf key = STRBUF_INIT;\n+\tstruct reftable_buf key = REFTABLE_BUF_INIT;\n \tint n = 0;\n \tint err = -1;\n \n@@ -133,7 +133,7 @@ int block_writer_add(struct block_writer *w, struct reftable_record *rec)\n \terr = block_writer_register_restart(w, start.len - out.len, is_restart,\n \t\t\t\t\t    &key);\n done:\n-\tstrbuf_release(&key);\n+\treftable_buf_release(&key);\n \treturn err;\n }\n \n@@ -325,7 +325,7 @@ uint8_t block_reader_type(const struct block_reader *r)\n \treturn r->block.data[r->header_off];\n }\n \n-int block_reader_first_key(const struct block_reader *br, struct strbuf *key)\n+int block_reader_first_key(const struct block_reader *br, struct reftable_buf *key)\n {\n \tint off = br->header_off + 4, n;\n \tstruct string_view in = {\n@@ -334,7 +334,7 @@ int block_reader_first_key(const struct block_reader *br, struct strbuf *key)\n \t};\n \tuint8_t extra = 0;\n \n-\tstrbuf_reset(key);\n+\treftable_buf_reset(key);\n \n \tn = reftable_decode_key(key, &extra, in);\n \tif (n < 0)\n@@ -355,13 +355,13 @@ void block_iter_seek_start(struct block_iter *it, const struct block_reader *br)\n \tit->block = br->block.data;\n \tit->block_len = br->block_len;\n \tit->hash_size = br->hash_size;\n-\tstrbuf_reset(&it->last_key);\n+\treftable_buf_reset(&it->last_key);\n \tit->next_off = br->header_off + 4;\n }\n \n struct restart_needle_less_args {\n \tint error;\n-\tstruct strbuf needle;\n+\tstruct reftable_buf needle;\n \tconst struct block_reader *reader;\n };\n \n@@ -433,7 +433,7 @@ int block_iter_next(struct block_iter *it, struct reftable_record *rec)\n \n void block_iter_reset(struct block_iter *it)\n {\n-\tstrbuf_reset(&it->last_key);\n+\treftable_buf_reset(&it->last_key);\n \tit->next_off = 0;\n \tit->block = NULL;\n \tit->block_len = 0;\n@@ -442,12 +442,12 @@ void block_iter_reset(struct block_iter *it)\n \n void block_iter_close(struct block_iter *it)\n {\n-\tstrbuf_release(&it->last_key);\n-\tstrbuf_release(&it->scratch);\n+\treftable_buf_release(&it->last_key);\n+\treftable_buf_release(&it->scratch);\n }\n \n int block_iter_seek_key(struct block_iter *it, const struct block_reader *br,\n-\t\t\tstruct strbuf *want)\n+\t\t\tstruct reftable_buf *want)\n {\n \tstruct restart_needle_less_args args = {\n \t\t.needle = *want,\n@@ -537,7 +537,7 @@ int block_iter_seek_key(struct block_iter *it, const struct block_reader *br,\n \t\t * with themselves.\n \t\t */\n \t\treftable_record_key(&rec, &it->last_key);\n-\t\tif (strbuf_cmp(&it->last_key, want) >= 0) {\n+\t\tif (reftable_buf_cmp(&it->last_key, want) >= 0) {\n \t\t\tit->next_off = prev_off;\n \t\t\tgoto done;\n \t\t}\n@@ -554,7 +554,7 @@ void block_writer_release(struct block_writer *bw)\n \tREFTABLE_FREE_AND_NULL(bw->zstream);\n \tREFTABLE_FREE_AND_NULL(bw->restarts);\n \tREFTABLE_FREE_AND_NULL(bw->compressed);\n-\tstrbuf_release(&bw->last_key);\n+\treftable_buf_release(&bw->last_key);\n \t/* the block is not owned. */\n }\n \ndiff --git a/reftable/block.h b/reftable/block.h\nindex 18d7ea03373..9a3effa5134 100644\n--- a/reftable/block.h\n+++ b/reftable/block.h\n@@ -38,7 +38,7 @@ struct block_writer {\n \tuint32_t restart_len;\n \tuint32_t restart_cap;\n \n-\tstruct strbuf last_key;\n+\tstruct reftable_buf last_key;\n \tint entries;\n };\n \n@@ -98,7 +98,7 @@ void block_reader_release(struct block_reader *br);\n uint8_t block_reader_type(const struct block_reader *r);\n \n /* Decodes the first key in the block */\n-int block_reader_first_key(const struct block_reader *br, struct strbuf *key);\n+int block_reader_first_key(const struct block_reader *br, struct reftable_buf *key);\n \n /* Iterate over entries in a block */\n struct block_iter {\n@@ -109,13 +109,13 @@ struct block_iter {\n \tint hash_size;\n \n \t/* key for last entry we read. */\n-\tstruct strbuf last_key;\n-\tstruct strbuf scratch;\n+\tstruct reftable_buf last_key;\n+\tstruct reftable_buf scratch;\n };\n \n #define BLOCK_ITER_INIT { \\\n-\t.last_key = STRBUF_INIT, \\\n-\t.scratch = STRBUF_INIT, \\\n+\t.last_key = REFTABLE_BUF_INIT, \\\n+\t.scratch = REFTABLE_BUF_INIT, \\\n }\n \n /* Position `it` at start of the block */\n@@ -123,7 +123,7 @@ void block_iter_seek_start(struct block_iter *it, const struct block_reader *br)\n \n /* Position `it` to the `want` key in the block */\n int block_iter_seek_key(struct block_iter *it, const struct block_reader *br,\n-\t\t\tstruct strbuf *want);\n+\t\t\tstruct reftable_buf *want);\n \n /* return < 0 for error, 0 for OK, > 0 for EOF. */\n int block_iter_next(struct block_iter *it, struct reftable_record *rec);\ndiff --git a/reftable/blocksource.c b/reftable/blocksource.c\nindex a2a6a196d55..d6242d67900 100644\n--- a/reftable/blocksource.c\n+++ b/reftable/blocksource.c\n@@ -27,7 +27,7 @@ static void strbuf_close(void *b UNUSED)\n static int strbuf_read_block(void *v, struct reftable_block *dest, uint64_t off,\n \t\t\t     uint32_t size)\n {\n-\tstruct strbuf *b = v;\n+\tstruct reftable_buf *b = v;\n \tassert(off + size <= b->len);\n \tREFTABLE_CALLOC_ARRAY(dest->data, size);\n \tif (!dest->data)\n@@ -39,7 +39,7 @@ static int strbuf_read_block(void *v, struct reftable_block *dest, uint64_t off,\n \n static uint64_t strbuf_size(void *b)\n {\n-\treturn ((struct strbuf *)b)->len;\n+\treturn ((struct reftable_buf *)b)->len;\n }\n \n static struct reftable_block_source_vtable strbuf_vtable = {\n@@ -50,7 +50,7 @@ static struct reftable_block_source_vtable strbuf_vtable = {\n };\n \n void block_source_from_strbuf(struct reftable_block_source *bs,\n-\t\t\t      struct strbuf *buf)\n+\t\t\t      struct reftable_buf *buf)\n {\n \tassert(!bs->ops);\n \tbs->ops = &strbuf_vtable;\ndiff --git a/reftable/blocksource.h b/reftable/blocksource.h\nindex 659a27b4063..ee3647c6531 100644\n--- a/reftable/blocksource.h\n+++ b/reftable/blocksource.h\n@@ -12,9 +12,10 @@ license that can be found in the LICENSE file or at\n #include \"system.h\"\n \n struct reftable_block_source;\n+struct reftable_buf;\n \n /* Create an in-memory block source for reading reftables */\n void block_source_from_strbuf(struct reftable_block_source *bs,\n-\t\t\t      struct strbuf *buf);\n+\t\t\t      struct reftable_buf *buf);\n \n #endif\ndiff --git a/reftable/iter.c b/reftable/iter.c\nindex d926db653b1..6c193fd31a9 100644\n--- a/reftable/iter.c\n+++ b/reftable/iter.c\n@@ -55,7 +55,7 @@ void iterator_set_empty(struct reftable_iterator *it)\n static void filtering_ref_iterator_close(void *iter_arg)\n {\n \tstruct filtering_ref_iterator *fri = iter_arg;\n-\tstrbuf_release(&fri->oid);\n+\treftable_buf_release(&fri->oid);\n \treftable_iterator_destroy(&fri->it);\n }\n \n@@ -115,7 +115,7 @@ static void indexed_table_ref_iter_close(void *p)\n \tblock_iter_close(&it->cur);\n \treftable_block_done(&it->block_reader.block);\n \treftable_free(it->offsets);\n-\tstrbuf_release(&it->oid);\n+\treftable_buf_release(&it->oid);\n }\n \n static int indexed_table_ref_iter_next_block(struct indexed_table_ref_iter *it)\n@@ -197,7 +197,7 @@ int indexed_table_ref_iter_new(struct indexed_table_ref_iter **dest,\n \n \t*itr = empty;\n \titr->r = r;\n-\tstrbuf_add(&itr->oid, oid, oid_len);\n+\treftable_buf_add(&itr->oid, oid, oid_len);\n \n \titr->offsets = offsets;\n \titr->offset_len = offset_len;\ndiff --git a/reftable/iter.h b/reftable/iter.h\nindex b3225bc7add..40f98893b85 100644\n--- a/reftable/iter.h\n+++ b/reftable/iter.h\n@@ -44,12 +44,12 @@ void iterator_set_empty(struct reftable_iterator *it);\n \n /* iterator that produces only ref records that point to `oid` */\n struct filtering_ref_iterator {\n-\tstruct strbuf oid;\n+\tstruct reftable_buf oid;\n \tstruct reftable_iterator it;\n };\n #define FILTERING_REF_ITERATOR_INIT \\\n \t{                           \\\n-\t\t.oid = STRBUF_INIT  \\\n+\t\t.oid = REFTABLE_BUF_INIT  \\\n \t}\n \n void iterator_from_filtering_ref_iterator(struct reftable_iterator *,\n@@ -60,7 +60,7 @@ void iterator_from_filtering_ref_iterator(struct reftable_iterator *,\n  */\n struct indexed_table_ref_iter {\n \tstruct reftable_reader *r;\n-\tstruct strbuf oid;\n+\tstruct reftable_buf oid;\n \n \t/* mutable */\n \tuint64_t *offsets;\n@@ -75,7 +75,7 @@ struct indexed_table_ref_iter {\n \n #define INDEXED_TABLE_REF_ITER_INIT { \\\n \t.cur = BLOCK_ITER_INIT, \\\n-\t.oid = STRBUF_INIT, \\\n+\t.oid = REFTABLE_BUF_INIT, \\\n }\n \n void iterator_from_indexed_table_ref_iter(struct reftable_iterator *it,\ndiff --git a/reftable/reader.c b/reftable/reader.c\nindex 8d372539220..388f8bf6d7b 100644\n--- a/reftable/reader.c\n+++ b/reftable/reader.c\n@@ -350,8 +350,8 @@ static int table_iter_seek_start(struct table_iter *ti, uint8_t typ, int index)\n static int table_iter_seek_linear(struct table_iter *ti,\n \t\t\t\t  struct reftable_record *want)\n {\n-\tstruct strbuf want_key = STRBUF_INIT;\n-\tstruct strbuf got_key = STRBUF_INIT;\n+\tstruct reftable_buf want_key = REFTABLE_BUF_INIT;\n+\tstruct reftable_buf got_key = REFTABLE_BUF_INIT;\n \tstruct reftable_record rec;\n \tint err;\n \n@@ -401,7 +401,7 @@ static int table_iter_seek_linear(struct table_iter *ti,\n \t\tif (err < 0)\n \t\t\tgoto done;\n \n-\t\tif (strbuf_cmp(&got_key, &want_key) > 0) {\n+\t\tif (reftable_buf_cmp(&got_key, &want_key) > 0) {\n \t\t\ttable_iter_block_done(&next);\n \t\t\tbreak;\n \t\t}\n@@ -422,8 +422,8 @@ static int table_iter_seek_linear(struct table_iter *ti,\n \n done:\n \treftable_record_release(&rec);\n-\tstrbuf_release(&want_key);\n-\tstrbuf_release(&got_key);\n+\treftable_buf_release(&want_key);\n+\treftable_buf_release(&got_key);\n \treturn err;\n }\n \n@@ -431,11 +431,11 @@ static int table_iter_seek_indexed(struct table_iter *ti,\n \t\t\t\t   struct reftable_record *rec)\n {\n \tstruct reftable_record want_index = {\n-\t\t.type = BLOCK_TYPE_INDEX, .u.idx = { .last_key = STRBUF_INIT }\n+\t\t.type = BLOCK_TYPE_INDEX, .u.idx = { .last_key = REFTABLE_BUF_INIT }\n \t};\n \tstruct reftable_record index_result = {\n \t\t.type = BLOCK_TYPE_INDEX,\n-\t\t.u.idx = { .last_key = STRBUF_INIT },\n+\t\t.u.idx = { .last_key = REFTABLE_BUF_INIT },\n \t};\n \tint err;\n \n@@ -765,7 +765,7 @@ static int reftable_reader_refs_for_unindexed(struct reftable_reader *r,\n \t}\n \t*filter = empty;\n \n-\tstrbuf_add(&filter->oid, oid, oid_len);\n+\treftable_buf_add(&filter->oid, oid, oid_len);\n \titerator_from_table_iter(&filter->it, ti);\n \n \titerator_from_filtering_ref_iterator(it, filter);\ndiff --git a/reftable/record.c b/reftable/record.c\nindex 87157f2c386..0182c973437 100644\n--- a/reftable/record.c\n+++ b/reftable/record.c\n@@ -98,7 +98,7 @@ const unsigned char *reftable_ref_record_val2(const struct reftable_ref_record *\n \t}\n }\n \n-static int decode_string(struct strbuf *dest, struct string_view in)\n+static int decode_string(struct reftable_buf *dest, struct string_view in)\n {\n \tint start_len = in.len;\n \tuint64_t tsize = 0;\n@@ -109,8 +109,8 @@ static int decode_string(struct strbuf *dest, struct string_view in)\n \tif (in.len < tsize)\n \t\treturn -1;\n \n-\tstrbuf_reset(dest);\n-\tstrbuf_add(dest, in.buf, tsize);\n+\treftable_buf_reset(dest);\n+\treftable_buf_add(dest, in.buf, tsize);\n \tstring_view_consume(&in, tsize);\n \n \treturn start_len - in.len;\n@@ -133,7 +133,7 @@ static int encode_string(const char *str, struct string_view s)\n }\n \n int reftable_encode_key(int *restart, struct string_view dest,\n-\t\t\tstruct strbuf prev_key, struct strbuf key,\n+\t\t\tstruct reftable_buf prev_key, struct reftable_buf key,\n \t\t\tuint8_t extra)\n {\n \tstruct string_view start = dest;\n@@ -183,7 +183,7 @@ int reftable_decode_keylen(struct string_view in,\n \treturn start_len - in.len;\n }\n \n-int reftable_decode_key(struct strbuf *last_key, uint8_t *extra,\n+int reftable_decode_key(struct reftable_buf *last_key, uint8_t *extra,\n \t\t\tstruct string_view in)\n {\n \tint start_len = in.len;\n@@ -200,19 +200,19 @@ int reftable_decode_key(struct strbuf *last_key, uint8_t *extra,\n \t    prefix_len > last_key->len)\n \t\treturn -1;\n \n-\tstrbuf_setlen(last_key, prefix_len);\n-\tstrbuf_add(last_key, in.buf, suffix_len);\n+\treftable_buf_setlen(last_key, prefix_len);\n+\treftable_buf_add(last_key, in.buf, suffix_len);\n \tstring_view_consume(&in, suffix_len);\n \n \treturn start_len - in.len;\n }\n \n-static void reftable_ref_record_key(const void *r, struct strbuf *dest)\n+static void reftable_ref_record_key(const void *r, struct reftable_buf *dest)\n {\n \tconst struct reftable_ref_record *rec =\n \t\t(const struct reftable_ref_record *)r;\n-\tstrbuf_reset(dest);\n-\tstrbuf_addstr(dest, rec->refname);\n+\treftable_buf_reset(dest);\n+\treftable_buf_addstr(dest, rec->refname);\n }\n \n static int reftable_ref_record_copy_from(void *rec, const void *src_rec,\n@@ -350,9 +350,9 @@ static int reftable_ref_record_encode(const void *rec, struct string_view s,\n \treturn start.len - s.len;\n }\n \n-static int reftable_ref_record_decode(void *rec, struct strbuf key,\n+static int reftable_ref_record_decode(void *rec, struct reftable_buf key,\n \t\t\t\t      uint8_t val_type, struct string_view in,\n-\t\t\t\t      int hash_size, struct strbuf *scratch)\n+\t\t\t\t      int hash_size, struct reftable_buf *scratch)\n {\n \tstruct reftable_ref_record *r = rec;\n \tstruct string_view start = in;\n@@ -415,7 +415,7 @@ static int reftable_ref_record_decode(void *rec, struct strbuf key,\n \t\t\tgoto done;\n \t\t}\n \t\tstring_view_consume(&in, n);\n-\t\tr->value.symref = strbuf_detach(scratch, NULL);\n+\t\tr->value.symref = reftable_buf_detach(scratch);\n \t} break;\n \n \tcase REFTABLE_REF_DELETION:\n@@ -465,12 +465,12 @@ static struct reftable_record_vtable reftable_ref_record_vtable = {\n \t.cmp = &reftable_ref_record_cmp_void,\n };\n \n-static void reftable_obj_record_key(const void *r, struct strbuf *dest)\n+static void reftable_obj_record_key(const void *r, struct reftable_buf *dest)\n {\n \tconst struct reftable_obj_record *rec =\n \t\t(const struct reftable_obj_record *)r;\n-\tstrbuf_reset(dest);\n-\tstrbuf_add(dest, rec->hash_prefix, rec->hash_prefix_len);\n+\treftable_buf_reset(dest);\n+\treftable_buf_add(dest, rec->hash_prefix, rec->hash_prefix_len);\n }\n \n static void reftable_obj_record_release(void *rec)\n@@ -547,10 +547,10 @@ static int reftable_obj_record_encode(const void *rec, struct string_view s,\n \treturn start.len - s.len;\n }\n \n-static int reftable_obj_record_decode(void *rec, struct strbuf key,\n+static int reftable_obj_record_decode(void *rec, struct reftable_buf key,\n \t\t\t\t      uint8_t val_type, struct string_view in,\n \t\t\t\t      int hash_size UNUSED,\n-\t\t\t\t      struct strbuf *scratch UNUSED)\n+\t\t\t\t      struct reftable_buf *scratch UNUSED)\n {\n \tstruct string_view start = in;\n \tstruct reftable_obj_record *r = rec;\n@@ -664,19 +664,19 @@ static struct reftable_record_vtable reftable_obj_record_vtable = {\n \t.cmp = &reftable_obj_record_cmp_void,\n };\n \n-static void reftable_log_record_key(const void *r, struct strbuf *dest)\n+static void reftable_log_record_key(const void *r, struct reftable_buf *dest)\n {\n \tconst struct reftable_log_record *rec =\n \t\t(const struct reftable_log_record *)r;\n \tint len = strlen(rec->refname);\n \tuint8_t i64[8];\n \tuint64_t ts = 0;\n-\tstrbuf_reset(dest);\n-\tstrbuf_add(dest, (uint8_t *)rec->refname, len + 1);\n+\treftable_buf_reset(dest);\n+\treftable_buf_add(dest, (uint8_t *)rec->refname, len + 1);\n \n \tts = (~ts) - rec->update_index;\n \tput_be64(&i64[0], ts);\n-\tstrbuf_add(dest, i64, sizeof(i64));\n+\treftable_buf_add(dest, i64, sizeof(i64));\n }\n \n static int reftable_log_record_copy_from(void *rec, const void *src_rec,\n@@ -807,9 +807,9 @@ static int reftable_log_record_encode(const void *rec, struct string_view s,\n \treturn start.len - s.len;\n }\n \n-static int reftable_log_record_decode(void *rec, struct strbuf key,\n+static int reftable_log_record_decode(void *rec, struct reftable_buf key,\n \t\t\t\t      uint8_t val_type, struct string_view in,\n-\t\t\t\t      int hash_size, struct strbuf *scratch)\n+\t\t\t\t      int hash_size, struct reftable_buf *scratch)\n {\n \tstruct string_view start = in;\n \tstruct reftable_log_record *r = rec;\n@@ -1027,11 +1027,11 @@ static struct reftable_record_vtable reftable_log_record_vtable = {\n \t.cmp = &reftable_log_record_cmp_void,\n };\n \n-static void reftable_index_record_key(const void *r, struct strbuf *dest)\n+static void reftable_index_record_key(const void *r, struct reftable_buf *dest)\n {\n \tconst struct reftable_index_record *rec = r;\n-\tstrbuf_reset(dest);\n-\tstrbuf_add(dest, rec->last_key.buf, rec->last_key.len);\n+\treftable_buf_reset(dest);\n+\treftable_buf_add(dest, rec->last_key.buf, rec->last_key.len);\n }\n \n static int reftable_index_record_copy_from(void *rec, const void *src_rec,\n@@ -1040,8 +1040,8 @@ static int reftable_index_record_copy_from(void *rec, const void *src_rec,\n \tstruct reftable_index_record *dst = rec;\n \tconst struct reftable_index_record *src = src_rec;\n \n-\tstrbuf_reset(&dst->last_key);\n-\tstrbuf_add(&dst->last_key, src->last_key.buf, src->last_key.len);\n+\treftable_buf_reset(&dst->last_key);\n+\treftable_buf_add(&dst->last_key, src->last_key.buf, src->last_key.len);\n \tdst->offset = src->offset;\n \n \treturn 0;\n@@ -1050,7 +1050,7 @@ static int reftable_index_record_copy_from(void *rec, const void *src_rec,\n static void reftable_index_record_release(void *rec)\n {\n \tstruct reftable_index_record *idx = rec;\n-\tstrbuf_release(&idx->last_key);\n+\treftable_buf_release(&idx->last_key);\n }\n \n static uint8_t reftable_index_record_val_type(const void *rec UNUSED)\n@@ -1074,18 +1074,18 @@ static int reftable_index_record_encode(const void *rec, struct string_view out,\n \treturn start.len - out.len;\n }\n \n-static int reftable_index_record_decode(void *rec, struct strbuf key,\n+static int reftable_index_record_decode(void *rec, struct reftable_buf key,\n \t\t\t\t\tuint8_t val_type UNUSED,\n \t\t\t\t\tstruct string_view in,\n \t\t\t\t\tint hash_size UNUSED,\n-\t\t\t\t\tstruct strbuf *scratch UNUSED)\n+\t\t\t\t\tstruct reftable_buf *scratch UNUSED)\n {\n \tstruct string_view start = in;\n \tstruct reftable_index_record *r = rec;\n \tint n = 0;\n \n-\tstrbuf_reset(&r->last_key);\n-\tstrbuf_add(&r->last_key, key.buf, key.len);\n+\treftable_buf_reset(&r->last_key);\n+\treftable_buf_add(&r->last_key, key.buf, key.len);\n \n \tn = get_var_int(&r->offset, &in);\n \tif (n < 0)\n@@ -1101,14 +1101,14 @@ static int reftable_index_record_equal(const void *a, const void *b,\n \tstruct reftable_index_record *ia = (struct reftable_index_record *) a;\n \tstruct reftable_index_record *ib = (struct reftable_index_record *) b;\n \n-\treturn ia->offset == ib->offset && !strbuf_cmp(&ia->last_key, &ib->last_key);\n+\treturn ia->offset == ib->offset && !reftable_buf_cmp(&ia->last_key, &ib->last_key);\n }\n \n static int reftable_index_record_cmp(const void *_a, const void *_b)\n {\n \tconst struct reftable_index_record *a = _a;\n \tconst struct reftable_index_record *b = _b;\n-\treturn strbuf_cmp(&a->last_key, &b->last_key);\n+\treturn reftable_buf_cmp(&a->last_key, &b->last_key);\n }\n \n static struct reftable_record_vtable reftable_index_record_vtable = {\n@@ -1124,7 +1124,7 @@ static struct reftable_record_vtable reftable_index_record_vtable = {\n \t.cmp = &reftable_index_record_cmp,\n };\n \n-void reftable_record_key(struct reftable_record *rec, struct strbuf *dest)\n+void reftable_record_key(struct reftable_record *rec, struct reftable_buf *dest)\n {\n \treftable_record_vtable(rec)->key(reftable_record_data(rec), dest);\n }\n@@ -1151,9 +1151,9 @@ uint8_t reftable_record_val_type(struct reftable_record *rec)\n \treturn reftable_record_vtable(rec)->val_type(reftable_record_data(rec));\n }\n \n-int reftable_record_decode(struct reftable_record *rec, struct strbuf key,\n+int reftable_record_decode(struct reftable_record *rec, struct reftable_buf key,\n \t\t\t   uint8_t extra, struct string_view src, int hash_size,\n-\t\t\t   struct strbuf *scratch)\n+\t\t\t   struct reftable_buf *scratch)\n {\n \treturn reftable_record_vtable(rec)->decode(reftable_record_data(rec),\n \t\t\t\t\t\t   key, extra, src, hash_size,\n@@ -1294,7 +1294,7 @@ void reftable_record_init(struct reftable_record *rec, uint8_t typ)\n \tcase BLOCK_TYPE_OBJ:\n \t\treturn;\n \tcase BLOCK_TYPE_INDEX:\n-\t\tstrbuf_init(&rec->u.idx.last_key, 0);\n+\t\treftable_buf_init(&rec->u.idx.last_key);\n \t\treturn;\n \tdefault:\n \t\tBUG(\"unhandled record type\");\ndiff --git a/reftable/record.h b/reftable/record.h\nindex 0f53ba54434..271da3bf360 100644\n--- a/reftable/record.h\n+++ b/reftable/record.h\n@@ -9,6 +9,7 @@ license that can be found in the LICENSE file or at\n #ifndef RECORD_H\n #define RECORD_H\n \n+#include \"basics.h\"\n #include \"system.h\"\n \n #include <stdint.h>\n@@ -38,8 +39,8 @@ int put_var_int(struct string_view *dest, uint64_t val);\n \n /* Methods for records. */\n struct reftable_record_vtable {\n-\t/* encode the key of to a uint8_t strbuf. */\n-\tvoid (*key)(const void *rec, struct strbuf *dest);\n+\t/* encode the key of to a uint8_t reftable_buf. */\n+\tvoid (*key)(const void *rec, struct reftable_buf *dest);\n \n \t/* The record type of ('r' for ref). */\n \tuint8_t type;\n@@ -54,9 +55,9 @@ struct reftable_record_vtable {\n \tint (*encode)(const void *rec, struct string_view dest, int hash_size);\n \n \t/* decode data from `src` into the record. */\n-\tint (*decode)(void *rec, struct strbuf key, uint8_t extra,\n+\tint (*decode)(void *rec, struct reftable_buf key, uint8_t extra,\n \t\t      struct string_view src, int hash_size,\n-\t\t      struct strbuf *scratch);\n+\t\t      struct reftable_buf *scratch);\n \n \t/* deallocate and null the record. */\n \tvoid (*release)(void *rec);\n@@ -83,7 +84,7 @@ int reftable_is_block_type(uint8_t typ);\n /* Encode `key` into `dest`. Sets `is_restart` to indicate a restart. Returns\n  * number of bytes written. */\n int reftable_encode_key(int *is_restart, struct string_view dest,\n-\t\t\tstruct strbuf prev_key, struct strbuf key,\n+\t\t\tstruct reftable_buf prev_key, struct reftable_buf key,\n \t\t\tuint8_t extra);\n \n /* Decode a record's key lengths. */\n@@ -96,13 +97,13 @@ int reftable_decode_keylen(struct string_view in,\n  * Decode into `last_key` and `extra` from `in`. `last_key` is expected to\n  * contain the decoded key of the preceding record, if any.\n  */\n-int reftable_decode_key(struct strbuf *last_key, uint8_t *extra,\n+int reftable_decode_key(struct reftable_buf *last_key, uint8_t *extra,\n \t\t\tstruct string_view in);\n \n /* reftable_index_record are used internally to speed up lookups. */\n struct reftable_index_record {\n \tuint64_t offset; /* Offset of block */\n-\tstruct strbuf last_key; /* Last key of the block. */\n+\tstruct reftable_buf last_key; /* Last key of the block. */\n };\n \n /* reftable_obj_record stores an object ID => ref mapping. */\n@@ -136,15 +137,15 @@ void reftable_record_init(struct reftable_record *rec, uint8_t typ);\n /* see struct record_vtable */\n int reftable_record_cmp(struct reftable_record *a, struct reftable_record *b);\n int reftable_record_equal(struct reftable_record *a, struct reftable_record *b, int hash_size);\n-void reftable_record_key(struct reftable_record *rec, struct strbuf *dest);\n+void reftable_record_key(struct reftable_record *rec, struct reftable_buf *dest);\n int reftable_record_copy_from(struct reftable_record *rec,\n \t\t\t      struct reftable_record *src, int hash_size);\n uint8_t reftable_record_val_type(struct reftable_record *rec);\n int reftable_record_encode(struct reftable_record *rec, struct string_view dest,\n \t\t\t   int hash_size);\n-int reftable_record_decode(struct reftable_record *rec, struct strbuf key,\n+int reftable_record_decode(struct reftable_record *rec, struct reftable_buf key,\n \t\t\t   uint8_t extra, struct string_view src,\n-\t\t\t   int hash_size, struct strbuf *scratch);\n+\t\t\t   int hash_size, struct reftable_buf *scratch);\n int reftable_record_is_deletion(struct reftable_record *rec);\n \n static inline uint8_t reftable_record_type(struct reftable_record *rec)\ndiff --git a/reftable/stack.c b/reftable/stack.c\nindex d7bc1187dfb..6ba48ddce5d 100644\n--- a/reftable/stack.c\n+++ b/reftable/stack.c\n@@ -31,13 +31,13 @@ static void reftable_addition_close(struct reftable_addition *add);\n static int reftable_stack_reload_maybe_reuse(struct reftable_stack *st,\n \t\t\t\t\t     int reuse_open);\n \n-static void stack_filename(struct strbuf *dest, struct reftable_stack *st,\n+static void stack_filename(struct reftable_buf *dest, struct reftable_stack *st,\n \t\t\t   const char *name)\n {\n-\tstrbuf_reset(dest);\n-\tstrbuf_addstr(dest, st->reftable_dir);\n-\tstrbuf_addstr(dest, \"/\");\n-\tstrbuf_addstr(dest, name);\n+\treftable_buf_reset(dest);\n+\treftable_buf_addstr(dest, st->reftable_dir);\n+\treftable_buf_addstr(dest, \"/\");\n+\treftable_buf_addstr(dest, name);\n }\n \n static ssize_t reftable_fd_write(void *arg, const void *data, size_t sz)\n@@ -56,7 +56,7 @@ static int reftable_fd_flush(void *arg)\n int reftable_new_stack(struct reftable_stack **dest, const char *dir,\n \t\t       const struct reftable_write_options *_opts)\n {\n-\tstruct strbuf list_file_name = STRBUF_INIT;\n+\tstruct reftable_buf list_file_name = REFTABLE_BUF_INIT;\n \tstruct reftable_write_options opts = { 0 };\n \tstruct reftable_stack *p;\n \tint err;\n@@ -74,11 +74,11 @@ int reftable_new_stack(struct reftable_stack **dest, const char *dir,\n \n \t*dest = NULL;\n \n-\tstrbuf_reset(&list_file_name);\n-\tstrbuf_addstr(&list_file_name, dir);\n-\tstrbuf_addstr(&list_file_name, \"/tables.list\");\n+\treftable_buf_reset(&list_file_name);\n+\treftable_buf_addstr(&list_file_name, dir);\n+\treftable_buf_addstr(&list_file_name, \"/tables.list\");\n \n-\tp->list_file = strbuf_detach(&list_file_name, NULL);\n+\tp->list_file = reftable_buf_detach(&list_file_name);\n \tp->list_fd = -1;\n \tp->opts = opts;\n \tp->reftable_dir = reftable_strdup(dir);\n@@ -208,10 +208,10 @@ void reftable_stack_destroy(struct reftable_stack *st)\n \n \tif (st->readers) {\n \t\tint i = 0;\n-\t\tstruct strbuf filename = STRBUF_INIT;\n+\t\tstruct reftable_buf filename = REFTABLE_BUF_INIT;\n \t\tfor (i = 0; i < st->readers_len; i++) {\n \t\t\tconst char *name = reader_name(st->readers[i]);\n-\t\t\tstrbuf_reset(&filename);\n+\t\t\treftable_buf_reset(&filename);\n \t\t\tif (names && !has_name(names, name)) {\n \t\t\t\tstack_filename(&filename, st, name);\n \t\t\t}\n@@ -222,7 +222,7 @@ void reftable_stack_destroy(struct reftable_stack *st)\n \t\t\t\tunlink(filename.buf);\n \t\t\t}\n \t\t}\n-\t\tstrbuf_release(&filename);\n+\t\treftable_buf_release(&filename);\n \t\tst->readers_len = 0;\n \t\tREFTABLE_FREE_AND_NULL(st->readers);\n \t}\n@@ -260,7 +260,7 @@ static int reftable_stack_reload_once(struct reftable_stack *st,\n \tsize_t reused_len = 0, reused_alloc = 0, names_len;\n \tsize_t new_readers_len = 0;\n \tstruct reftable_merged_table *new_merged = NULL;\n-\tstruct strbuf table_path = STRBUF_INIT;\n+\tstruct reftable_buf table_path = REFTABLE_BUF_INIT;\n \tint err = 0;\n \tsize_t i;\n \n@@ -374,7 +374,7 @@ static int reftable_stack_reload_once(struct reftable_stack *st,\n \treftable_free(new_readers);\n \treftable_free(reused);\n \treftable_free(cur);\n-\tstrbuf_release(&table_path);\n+\treftable_buf_release(&table_path);\n \treturn err;\n }\n \n@@ -623,14 +623,14 @@ int reftable_stack_add(struct reftable_stack *st,\n \treturn 0;\n }\n \n-static void format_name(struct strbuf *dest, uint64_t min, uint64_t max)\n+static void format_name(struct reftable_buf *dest, uint64_t min, uint64_t max)\n {\n \tchar buf[100];\n \tuint32_t rnd = (uint32_t)git_rand();\n \tsnprintf(buf, sizeof(buf), \"0x%012\" PRIx64 \"-0x%012\" PRIx64 \"-%08x\",\n \t\t min, max, rnd);\n-\tstrbuf_reset(dest);\n-\tstrbuf_addstr(dest, buf);\n+\treftable_buf_reset(dest);\n+\treftable_buf_addstr(dest, buf);\n }\n \n struct reftable_addition {\n@@ -648,7 +648,7 @@ static int reftable_stack_init_addition(struct reftable_addition *add,\n \t\t\t\t\tstruct reftable_stack *st,\n \t\t\t\t\tunsigned int flags)\n {\n-\tstruct strbuf lock_file_name = STRBUF_INIT;\n+\tstruct reftable_buf lock_file_name = REFTABLE_BUF_INIT;\n \tint err;\n \n \tadd->stack = st;\n@@ -690,13 +690,13 @@ static int reftable_stack_init_addition(struct reftable_addition *add,\n done:\n \tif (err)\n \t\treftable_addition_close(add);\n-\tstrbuf_release(&lock_file_name);\n+\treftable_buf_release(&lock_file_name);\n \treturn err;\n }\n \n static void reftable_addition_close(struct reftable_addition *add)\n {\n-\tstruct strbuf nm = STRBUF_INIT;\n+\tstruct reftable_buf nm = REFTABLE_BUF_INIT;\n \tsize_t i;\n \n \tfor (i = 0; i < add->new_tables_len; i++) {\n@@ -711,7 +711,7 @@ static void reftable_addition_close(struct reftable_addition *add)\n \tadd->new_tables_cap = 0;\n \n \trollback_lock_file(&add->tables_list_lock);\n-\tstrbuf_release(&nm);\n+\treftable_buf_release(&nm);\n }\n \n void reftable_addition_destroy(struct reftable_addition *add)\n@@ -725,7 +725,7 @@ void reftable_addition_destroy(struct reftable_addition *add)\n \n int reftable_addition_commit(struct reftable_addition *add)\n {\n-\tstruct strbuf table_list = STRBUF_INIT;\n+\tstruct reftable_buf table_list = REFTABLE_BUF_INIT;\n \tint lock_file_fd = get_lock_file_fd(&add->tables_list_lock);\n \tint err = 0;\n \tsize_t i;\n@@ -734,16 +734,16 @@ int reftable_addition_commit(struct reftable_addition *add)\n \t\tgoto done;\n \n \tfor (i = 0; i < add->stack->merged->readers_len; i++) {\n-\t\tstrbuf_addstr(&table_list, add->stack->readers[i]->name);\n-\t\tstrbuf_addstr(&table_list, \"\\n\");\n+\t\treftable_buf_addstr(&table_list, add->stack->readers[i]->name);\n+\t\treftable_buf_addstr(&table_list, \"\\n\");\n \t}\n \tfor (i = 0; i < add->new_tables_len; i++) {\n-\t\tstrbuf_addstr(&table_list, add->new_tables[i]);\n-\t\tstrbuf_addstr(&table_list, \"\\n\");\n+\t\treftable_buf_addstr(&table_list, add->new_tables[i]);\n+\t\treftable_buf_addstr(&table_list, \"\\n\");\n \t}\n \n \terr = write_in_full(lock_file_fd, table_list.buf, table_list.len);\n-\tstrbuf_release(&table_list);\n+\treftable_buf_release(&table_list);\n \tif (err < 0) {\n \t\terr = REFTABLE_IO_ERROR;\n \t\tgoto done;\n@@ -837,19 +837,19 @@ int reftable_addition_add(struct reftable_addition *add,\n \t\t\t\t\t     void *arg),\n \t\t\t  void *arg)\n {\n-\tstruct strbuf temp_tab_file_name = STRBUF_INIT;\n-\tstruct strbuf tab_file_name = STRBUF_INIT;\n-\tstruct strbuf next_name = STRBUF_INIT;\n+\tstruct reftable_buf temp_tab_file_name = REFTABLE_BUF_INIT;\n+\tstruct reftable_buf tab_file_name = REFTABLE_BUF_INIT;\n+\tstruct reftable_buf next_name = REFTABLE_BUF_INIT;\n \tstruct reftable_writer *wr = NULL;\n \tstruct tempfile *tab_file = NULL;\n \tint err = 0;\n \tint tab_fd;\n \n-\tstrbuf_reset(&next_name);\n+\treftable_buf_reset(&next_name);\n \tformat_name(&next_name, add->next_update_index, add->next_update_index);\n \n \tstack_filename(&temp_tab_file_name, add->stack, next_name.buf);\n-\tstrbuf_addstr(&temp_tab_file_name, \".temp.XXXXXX\");\n+\treftable_buf_addstr(&temp_tab_file_name, \".temp.XXXXXX\");\n \n \ttab_file = mks_tempfile(temp_tab_file_name.buf);\n \tif (!tab_file) {\n@@ -894,7 +894,7 @@ int reftable_addition_add(struct reftable_addition *add,\n \t}\n \n \tformat_name(&next_name, wr->min_update_index, wr->max_update_index);\n-\tstrbuf_addstr(&next_name, \".ref\");\n+\treftable_buf_addstr(&next_name, \".ref\");\n \tstack_filename(&tab_file_name, add->stack, next_name.buf);\n \n \t/*\n@@ -913,13 +913,13 @@ int reftable_addition_add(struct reftable_addition *add,\n \t\terr = REFTABLE_OUT_OF_MEMORY_ERROR;\n \t\tgoto done;\n \t}\n-\tadd->new_tables[add->new_tables_len++] = strbuf_detach(&next_name, NULL);\n+\tadd->new_tables[add->new_tables_len++] = reftable_buf_detach(&next_name);\n \n done:\n \tdelete_tempfile(&tab_file);\n-\tstrbuf_release(&temp_tab_file_name);\n-\tstrbuf_release(&tab_file_name);\n-\tstrbuf_release(&next_name);\n+\treftable_buf_release(&temp_tab_file_name);\n+\treftable_buf_release(&tab_file_name);\n+\treftable_buf_release(&next_name);\n \treftable_writer_free(wr);\n \treturn err;\n }\n@@ -938,8 +938,8 @@ static int stack_compact_locked(struct reftable_stack *st,\n \t\t\t\tstruct reftable_log_expiry_config *config,\n \t\t\t\tstruct tempfile **tab_file_out)\n {\n-\tstruct strbuf next_name = STRBUF_INIT;\n-\tstruct strbuf tab_file_path = STRBUF_INIT;\n+\tstruct reftable_buf next_name = REFTABLE_BUF_INIT;\n+\tstruct reftable_buf tab_file_path = REFTABLE_BUF_INIT;\n \tstruct reftable_writer *wr = NULL;\n \tstruct tempfile *tab_file;\n \tint tab_fd, err = 0;\n@@ -948,7 +948,7 @@ static int stack_compact_locked(struct reftable_stack *st,\n \t\t    reftable_reader_min_update_index(st->readers[first]),\n \t\t    reftable_reader_max_update_index(st->readers[last]));\n \tstack_filename(&tab_file_path, st, next_name.buf);\n-\tstrbuf_addstr(&tab_file_path, \".temp.XXXXXX\");\n+\treftable_buf_addstr(&tab_file_path, \".temp.XXXXXX\");\n \n \ttab_file = mks_tempfile(tab_file_path.buf);\n \tif (!tab_file) {\n@@ -986,8 +986,8 @@ static int stack_compact_locked(struct reftable_stack *st,\n done:\n \tdelete_tempfile(&tab_file);\n \treftable_writer_free(wr);\n-\tstrbuf_release(&next_name);\n-\tstrbuf_release(&tab_file_path);\n+\treftable_buf_release(&next_name);\n+\treftable_buf_release(&tab_file_path);\n \treturn err;\n }\n \n@@ -1111,10 +1111,10 @@ static int stack_compact_range(struct reftable_stack *st,\n \t\t\t       struct reftable_log_expiry_config *expiry,\n \t\t\t       unsigned int flags)\n {\n-\tstruct strbuf tables_list_buf = STRBUF_INIT;\n-\tstruct strbuf new_table_name = STRBUF_INIT;\n-\tstruct strbuf new_table_path = STRBUF_INIT;\n-\tstruct strbuf table_name = STRBUF_INIT;\n+\tstruct reftable_buf tables_list_buf = REFTABLE_BUF_INIT;\n+\tstruct reftable_buf new_table_name = REFTABLE_BUF_INIT;\n+\tstruct reftable_buf new_table_path = REFTABLE_BUF_INIT;\n+\tstruct reftable_buf table_name = REFTABLE_BUF_INIT;\n \tstruct lock_file tables_list_lock = LOCK_INIT;\n \tstruct lock_file *table_locks = NULL;\n \tstruct tempfile *new_table = NULL;\n@@ -1372,7 +1372,7 @@ static int stack_compact_range(struct reftable_stack *st,\n \tif (!is_empty_table) {\n \t\tformat_name(&new_table_name, st->readers[first]->min_update_index,\n \t\t\t    st->readers[last]->max_update_index);\n-\t\tstrbuf_addstr(&new_table_name, \".ref\");\n+\t\treftable_buf_addstr(&new_table_name, \".ref\");\n \t\tstack_filename(&new_table_path, st, new_table_name.buf);\n \n \t\terr = rename_tempfile(&new_table, new_table_path.buf);\n@@ -1388,16 +1388,16 @@ static int stack_compact_range(struct reftable_stack *st,\n \t * simply skip writing it.\n \t */\n \tfor (i = 0; i < first_to_replace; i++) {\n-\t\tstrbuf_addstr(&tables_list_buf, names[i]);\n-\t\tstrbuf_addstr(&tables_list_buf, \"\\n\");\n+\t\treftable_buf_addstr(&tables_list_buf, names[i]);\n+\t\treftable_buf_addstr(&tables_list_buf, \"\\n\");\n \t}\n \tif (!is_empty_table) {\n-\t\tstrbuf_addstr(&tables_list_buf, new_table_name.buf);\n-\t\tstrbuf_addstr(&tables_list_buf, \"\\n\");\n+\t\treftable_buf_addstr(&tables_list_buf, new_table_name.buf);\n+\t\treftable_buf_addstr(&tables_list_buf, \"\\n\");\n \t}\n \tfor (i = last_to_replace + 1; names[i]; i++) {\n-\t\tstrbuf_addstr(&tables_list_buf, names[i]);\n-\t\tstrbuf_addstr(&tables_list_buf, \"\\n\");\n+\t\treftable_buf_addstr(&tables_list_buf, names[i]);\n+\t\treftable_buf_addstr(&tables_list_buf, \"\\n\");\n \t}\n \n \terr = write_in_full(get_lock_file_fd(&tables_list_lock),\n@@ -1449,10 +1449,10 @@ static int stack_compact_range(struct reftable_stack *st,\n \treftable_free(table_locks);\n \n \tdelete_tempfile(&new_table);\n-\tstrbuf_release(&new_table_name);\n-\tstrbuf_release(&new_table_path);\n-\tstrbuf_release(&tables_list_buf);\n-\tstrbuf_release(&table_name);\n+\treftable_buf_release(&new_table_name);\n+\treftable_buf_release(&new_table_path);\n+\treftable_buf_release(&tables_list_buf);\n+\treftable_buf_release(&table_name);\n \tfree_names(names);\n \n \tif (err == REFTABLE_LOCK_ERROR)\n@@ -1666,7 +1666,7 @@ static void remove_maybe_stale_table(struct reftable_stack *st, uint64_t max,\n \tuint64_t update_idx = 0;\n \tstruct reftable_block_source src = { NULL };\n \tstruct reftable_reader *rd = NULL;\n-\tstruct strbuf table_path = STRBUF_INIT;\n+\tstruct reftable_buf table_path = REFTABLE_BUF_INIT;\n \tstack_filename(&table_path, st, name);\n \n \terr = reftable_block_source_from_file(&src, table_path.buf);\n@@ -1684,7 +1684,7 @@ static void remove_maybe_stale_table(struct reftable_stack *st, uint64_t max,\n \t\tunlink(table_path.buf);\n \t}\n done:\n-\tstrbuf_release(&table_path);\n+\treftable_buf_release(&table_path);\n }\n \n static int reftable_stack_clean_locked(struct reftable_stack *st)\ndiff --git a/reftable/system.h b/reftable/system.h\nindex d0cabd5d171..5ec85833434 100644\n--- a/reftable/system.h\n+++ b/reftable/system.h\n@@ -13,7 +13,6 @@ license that can be found in the LICENSE file or at\n \n #include \"git-compat-util.h\"\n #include \"lockfile.h\"\n-#include \"strbuf.h\"\n #include \"tempfile.h\"\n #include \"hash.h\" /* hash ID, sizes.*/\n #include \"dir.h\" /* remove_dir_recursively, for tests.*/\ndiff --git a/reftable/writer.c b/reftable/writer.c\nindex 031d8149a9c..da6941a78ac 100644\n--- a/reftable/writer.c\n+++ b/reftable/writer.c\n@@ -115,7 +115,7 @@ static int writer_reinit_block_writer(struct reftable_writer *w, uint8_t typ)\n \tif (w->next == 0)\n \t\tblock_start = header_size(writer_version(w));\n \n-\tstrbuf_reset(&w->last_key);\n+\treftable_buf_reset(&w->last_key);\n \tret = block_writer_init(&w->block_writer_data, typ, w->block,\n \t\t\t\tw->opts.block_size, block_start,\n \t\t\t\thash_size(w->opts.hash_id));\n@@ -146,8 +146,8 @@ int reftable_writer_new(struct reftable_writer **out,\n \tif (opts.block_size >= (1 << 24))\n \t\tBUG(\"configured block size exceeds 16MB\");\n \n-\tstrbuf_init(&wp->block_writer_data.last_key, 0);\n-\tstrbuf_init(&wp->last_key, 0);\n+\treftable_buf_init(&wp->block_writer_data.last_key);\n+\treftable_buf_init(&wp->last_key);\n \tREFTABLE_CALLOC_ARRAY(wp->block, opts.block_size);\n \tif (!wp->block) {\n \t\treftable_free(wp);\n@@ -179,7 +179,7 @@ static void writer_release(struct reftable_writer *w)\n \t\tblock_writer_release(&w->block_writer_data);\n \t\tw->block_writer = NULL;\n \t\twriter_clear_index(w);\n-\t\tstrbuf_release(&w->last_key);\n+\t\treftable_buf_release(&w->last_key);\n \t}\n }\n \n@@ -190,7 +190,7 @@ void reftable_writer_free(struct reftable_writer *w)\n }\n \n struct obj_index_tree_node {\n-\tstruct strbuf hash;\n+\tstruct reftable_buf hash;\n \tuint64_t *offsets;\n \tsize_t offset_len;\n \tsize_t offset_cap;\n@@ -198,16 +198,16 @@ struct obj_index_tree_node {\n \n #define OBJ_INDEX_TREE_NODE_INIT    \\\n \t{                           \\\n-\t\t.hash = STRBUF_INIT \\\n+\t\t.hash = REFTABLE_BUF_INIT \\\n \t}\n \n static int obj_index_tree_node_compare(const void *a, const void *b)\n {\n-\treturn strbuf_cmp(&((const struct obj_index_tree_node *)a)->hash,\n+\treturn reftable_buf_cmp(&((const struct obj_index_tree_node *)a)->hash,\n \t\t\t  &((const struct obj_index_tree_node *)b)->hash);\n }\n \n-static int writer_index_hash(struct reftable_writer *w, struct strbuf *hash)\n+static int writer_index_hash(struct reftable_writer *w, struct reftable_buf *hash)\n {\n \tuint64_t off = w->next;\n \tstruct obj_index_tree_node want = { .hash = *hash };\n@@ -224,8 +224,8 @@ static int writer_index_hash(struct reftable_writer *w, struct strbuf *hash)\n \n \t\t*key = empty;\n \n-\t\tstrbuf_reset(&key->hash);\n-\t\tstrbuf_add(&key->hash, hash->buf, hash->len);\n+\t\treftable_buf_reset(&key->hash);\n+\t\treftable_buf_add(&key->hash, hash->buf, hash->len);\n \t\ttree_insert(&w->obj_index_tree, key,\n \t\t\t    &obj_index_tree_node_compare);\n \t} else {\n@@ -246,17 +246,17 @@ static int writer_index_hash(struct reftable_writer *w, struct strbuf *hash)\n static int writer_add_record(struct reftable_writer *w,\n \t\t\t     struct reftable_record *rec)\n {\n-\tstruct strbuf key = STRBUF_INIT;\n+\tstruct reftable_buf key = REFTABLE_BUF_INIT;\n \tint err;\n \n \treftable_record_key(rec, &key);\n-\tif (strbuf_cmp(&w->last_key, &key) >= 0) {\n+\tif (reftable_buf_cmp(&w->last_key, &key) >= 0) {\n \t\terr = REFTABLE_API_ERROR;\n \t\tgoto done;\n \t}\n \n-\tstrbuf_reset(&w->last_key);\n-\tstrbuf_add(&w->last_key, key.buf, key.len);\n+\treftable_buf_reset(&w->last_key);\n+\treftable_buf_add(&w->last_key, key.buf, key.len);\n \tif (!w->block_writer) {\n \t\terr = writer_reinit_block_writer(w, reftable_record_type(rec));\n \t\tif (err < 0)\n@@ -303,7 +303,7 @@ static int writer_add_record(struct reftable_writer *w,\n \t}\n \n done:\n-\tstrbuf_release(&key);\n+\treftable_buf_release(&key);\n \treturn err;\n }\n \n@@ -316,7 +316,7 @@ int reftable_writer_add_ref(struct reftable_writer *w,\n \t\t\t.ref = *ref\n \t\t},\n \t};\n-\tstruct strbuf buf = STRBUF_INIT;\n+\tstruct reftable_buf buf = REFTABLE_BUF_INIT;\n \tint err;\n \n \tif (!ref->refname ||\n@@ -331,7 +331,7 @@ int reftable_writer_add_ref(struct reftable_writer *w,\n \t\tgoto out;\n \n \tif (!w->opts.skip_index_objects && reftable_ref_record_val1(ref)) {\n-\t\tstrbuf_add(&buf, (char *)reftable_ref_record_val1(ref),\n+\t\treftable_buf_add(&buf, (char *)reftable_ref_record_val1(ref),\n \t\t\t   hash_size(w->opts.hash_id));\n \n \t\terr = writer_index_hash(w, &buf);\n@@ -340,8 +340,8 @@ int reftable_writer_add_ref(struct reftable_writer *w,\n \t}\n \n \tif (!w->opts.skip_index_objects && reftable_ref_record_val2(ref)) {\n-\t\tstrbuf_reset(&buf);\n-\t\tstrbuf_add(&buf, reftable_ref_record_val2(ref),\n+\t\treftable_buf_reset(&buf);\n+\t\treftable_buf_add(&buf, reftable_ref_record_val2(ref),\n \t\t\t   hash_size(w->opts.hash_id));\n \n \t\terr = writer_index_hash(w, &buf);\n@@ -352,7 +352,7 @@ int reftable_writer_add_ref(struct reftable_writer *w,\n \terr = 0;\n \n out:\n-\tstrbuf_release(&buf);\n+\treftable_buf_release(&buf);\n \treturn err;\n }\n \n@@ -393,7 +393,7 @@ int reftable_writer_add_log(struct reftable_writer *w,\n \t\t\t    struct reftable_log_record *log)\n {\n \tchar *input_log_message = NULL;\n-\tstruct strbuf cleaned_message = STRBUF_INIT;\n+\tstruct reftable_buf cleaned_message = REFTABLE_BUF_INIT;\n \tint err = 0;\n \n \tif (log->value_type == REFTABLE_LOG_DELETION)\n@@ -404,24 +404,24 @@ int reftable_writer_add_log(struct reftable_writer *w,\n \n \tinput_log_message = log->value.update.message;\n \tif (!w->opts.exact_log_message && log->value.update.message) {\n-\t\tstrbuf_addstr(&cleaned_message, log->value.update.message);\n+\t\treftable_buf_addstr(&cleaned_message, log->value.update.message);\n \t\twhile (cleaned_message.len &&\n \t\t       cleaned_message.buf[cleaned_message.len - 1] == '\\n')\n-\t\t\tstrbuf_setlen(&cleaned_message,\n+\t\t\treftable_buf_setlen(&cleaned_message,\n \t\t\t\t      cleaned_message.len - 1);\n \t\tif (strchr(cleaned_message.buf, '\\n')) {\n \t\t\t/* multiple lines not allowed. */\n \t\t\terr = REFTABLE_API_ERROR;\n \t\t\tgoto done;\n \t\t}\n-\t\tstrbuf_addstr(&cleaned_message, \"\\n\");\n+\t\treftable_buf_addstr(&cleaned_message, \"\\n\");\n \t\tlog->value.update.message = cleaned_message.buf;\n \t}\n \n \terr = reftable_writer_add_log_verbatim(w, log);\n \tlog->value.update.message = input_log_message;\n done:\n-\tstrbuf_release(&cleaned_message);\n+\treftable_buf_release(&cleaned_message);\n \treturn err;\n }\n \n@@ -504,7 +504,7 @@ static int writer_finish_section(struct reftable_writer *w)\n \t\t\treturn err;\n \n \t\tfor (i = 0; i < idx_len; i++)\n-\t\t\tstrbuf_release(&idx[i].last_key);\n+\t\t\treftable_buf_release(&idx[i].last_key);\n \t\treftable_free(idx);\n \t}\n \n@@ -521,13 +521,13 @@ static int writer_finish_section(struct reftable_writer *w)\n \tbstats->max_index_level = max_level;\n \n \t/* Reinit lastKey, as the next section can start with any key. */\n-\tstrbuf_reset(&w->last_key);\n+\treftable_buf_reset(&w->last_key);\n \n \treturn 0;\n }\n \n struct common_prefix_arg {\n-\tstruct strbuf *last;\n+\tstruct reftable_buf *last;\n \tint max;\n };\n \n@@ -594,7 +594,7 @@ static void object_record_free(void *void_arg UNUSED, void *key)\n \tstruct obj_index_tree_node *entry = key;\n \n \tREFTABLE_FREE_AND_NULL(entry->offsets);\n-\tstrbuf_release(&entry->hash);\n+\treftable_buf_release(&entry->hash);\n \treftable_free(entry);\n }\n \n@@ -708,7 +708,7 @@ int reftable_writer_close(struct reftable_writer *w)\n static void writer_clear_index(struct reftable_writer *w)\n {\n \tfor (size_t i = 0; w->index && i < w->index_len; i++)\n-\t\tstrbuf_release(&w->index[i].last_key);\n+\t\treftable_buf_release(&w->index[i].last_key);\n \tREFTABLE_FREE_AND_NULL(w->index);\n \tw->index_len = 0;\n \tw->index_cap = 0;\n@@ -717,7 +717,7 @@ static void writer_clear_index(struct reftable_writer *w)\n static int writer_flush_nonempty_block(struct reftable_writer *w)\n {\n \tstruct reftable_index_record index_record = {\n-\t\t.last_key = STRBUF_INIT,\n+\t\t.last_key = REFTABLE_BUF_INIT,\n \t};\n \tuint8_t typ = block_writer_type(w->block_writer);\n \tstruct reftable_block_stats *bstats;\n@@ -777,8 +777,8 @@ static int writer_flush_nonempty_block(struct reftable_writer *w)\n \t\treturn REFTABLE_OUT_OF_MEMORY_ERROR;\n \n \tindex_record.offset = w->next;\n-\tstrbuf_reset(&index_record.last_key);\n-\tstrbuf_add(&index_record.last_key, w->block_writer->last_key.buf,\n+\treftable_buf_reset(&index_record.last_key);\n+\treftable_buf_add(&index_record.last_key, w->block_writer->last_key.buf,\n \t\t   w->block_writer->last_key.len);\n \tw->index[w->index_len] = index_record;\n \tw->index_len++;\ndiff --git a/reftable/writer.h b/reftable/writer.h\nindex 8d0df9cc528..e8a6fbb7854 100644\n--- a/reftable/writer.h\n+++ b/reftable/writer.h\n@@ -19,7 +19,7 @@ struct reftable_writer {\n \tint (*flush)(void *);\n \tvoid *write_arg;\n \tint pending_padding;\n-\tstruct strbuf last_key;\n+\tstruct reftable_buf last_key;\n \n \t/* offset of next block to write. */\n \tuint64_t next;\ndiff --git a/t/unit-tests/lib-reftable.c b/t/unit-tests/lib-reftable.c\nindex 54c26c43e77..2ddf480588d 100644\n--- a/t/unit-tests/lib-reftable.c\n+++ b/t/unit-tests/lib-reftable.c\n@@ -19,7 +19,7 @@ static int strbuf_writer_flush(void *arg UNUSED)\n \treturn 0;\n }\n \n-struct reftable_writer *t_reftable_strbuf_writer(struct strbuf *buf,\n+struct reftable_writer *t_reftable_strbuf_writer(struct reftable_buf *buf,\n \t\t\t\t\t\t struct reftable_write_options *opts)\n {\n \tstruct reftable_writer *writer;\n@@ -29,7 +29,7 @@ struct reftable_writer *t_reftable_strbuf_writer(struct strbuf *buf,\n \treturn writer;\n }\n \n-void t_reftable_write_to_buf(struct strbuf *buf,\n+void t_reftable_write_to_buf(struct reftable_buf *buf,\n \t\t\t     struct reftable_ref_record *refs,\n \t\t\t     size_t nrefs,\n \t\t\t     struct reftable_log_record *logs,\ndiff --git a/t/unit-tests/lib-reftable.h b/t/unit-tests/lib-reftable.h\nindex d1154190847..d4950fed3da 100644\n--- a/t/unit-tests/lib-reftable.h\n+++ b/t/unit-tests/lib-reftable.h\n@@ -2,15 +2,16 @@\n #define LIB_REFTABLE_H\n \n #include \"git-compat-util.h\"\n-#include \"strbuf.h\"\n #include \"reftable/reftable-writer.h\"\n \n+struct reftable_buf;\n+\n void t_reftable_set_hash(uint8_t *p, int i, uint32_t id);\n \n-struct reftable_writer *t_reftable_strbuf_writer(struct strbuf *buf,\n+struct reftable_writer *t_reftable_strbuf_writer(struct reftable_buf *buf,\n \t\t\t\t\t\t struct reftable_write_options *opts);\n \n-void t_reftable_write_to_buf(struct strbuf *buf,\n+void t_reftable_write_to_buf(struct reftable_buf *buf,\n \t\t\t     struct reftable_ref_record *refs,\n \t\t\t     size_t nrecords,\n \t\t\t     struct reftable_log_record *logs,\ndiff --git a/t/unit-tests/t-reftable-basics.c b/t/unit-tests/t-reftable-basics.c\nindex 1fa77b6faff..a814e819756 100644\n--- a/t/unit-tests/t-reftable-basics.c\n+++ b/t/unit-tests/t-reftable-basics.c\n@@ -99,8 +99,8 @@ int cmd_main(int argc UNUSED, const char *argv[] UNUSED)\n \t}\n \n \tif_test (\"common_prefix_size works\") {\n-\t\tstruct strbuf a = STRBUF_INIT;\n-\t\tstruct strbuf b = STRBUF_INIT;\n+\t\tstruct reftable_buf a = REFTABLE_BUF_INIT;\n+\t\tstruct reftable_buf b = REFTABLE_BUF_INIT;\n \t\tstruct {\n \t\t\tconst char *a, *b;\n \t\t\tint want;\n@@ -113,14 +113,14 @@ int cmd_main(int argc UNUSED, const char *argv[] UNUSED)\n \t\t};\n \n \t\tfor (size_t i = 0; i < ARRAY_SIZE(cases); i++) {\n-\t\t\tstrbuf_addstr(&a, cases[i].a);\n-\t\t\tstrbuf_addstr(&b, cases[i].b);\n+\t\t\treftable_buf_addstr(&a, cases[i].a);\n+\t\t\treftable_buf_addstr(&b, cases[i].b);\n \t\t\tcheck_int(common_prefix_size(&a, &b), ==, cases[i].want);\n-\t\t\tstrbuf_reset(&a);\n-\t\t\tstrbuf_reset(&b);\n+\t\t\treftable_buf_reset(&a);\n+\t\t\treftable_buf_reset(&b);\n \t\t}\n-\t\tstrbuf_release(&a);\n-\t\tstrbuf_release(&b);\n+\t\treftable_buf_release(&a);\n+\t\treftable_buf_release(&b);\n \t}\n \n \tif_test (\"put_be24 and get_be24 work\") {\ndiff --git a/t/unit-tests/t-reftable-block.c b/t/unit-tests/t-reftable-block.c\nindex 8077bbc5e7a..56514b43630 100644\n--- a/t/unit-tests/t-reftable-block.c\n+++ b/t/unit-tests/t-reftable-block.c\n@@ -20,7 +20,7 @@ static void t_ref_block_read_write(void)\n \tconst size_t block_size = 1024;\n \tstruct reftable_block block = { 0 };\n \tstruct block_writer bw = {\n-\t\t.last_key = STRBUF_INIT,\n+\t\t.last_key = REFTABLE_BUF_INIT,\n \t};\n \tstruct reftable_record rec = {\n \t\t.type = BLOCK_TYPE_REF,\n@@ -29,7 +29,7 @@ static void t_ref_block_read_write(void)\n \tint ret;\n \tstruct block_reader br = { 0 };\n \tstruct block_iter it = BLOCK_ITER_INIT;\n-\tstruct strbuf want = STRBUF_INIT, buf = STRBUF_INIT;\n+\tstruct reftable_buf want = REFTABLE_BUF_INIT, buf = REFTABLE_BUF_INIT;\n \n \tREFTABLE_CALLOC_ARRAY(block.data, block_size);\n \tcheck(block.data != NULL);\n@@ -100,8 +100,8 @@ static void t_ref_block_read_write(void)\n \tblock_iter_close(&it);\n \treftable_record_release(&rec);\n \treftable_block_done(&br.block);\n-\tstrbuf_release(&want);\n-\tstrbuf_release(&buf);\n+\treftable_buf_release(&want);\n+\treftable_buf_release(&buf);\n \tfor (i = 0; i < N; i++)\n \t\treftable_record_release(&recs[i]);\n }\n@@ -114,7 +114,7 @@ static void t_log_block_read_write(void)\n \tconst size_t block_size = 2048;\n \tstruct reftable_block block = { 0 };\n \tstruct block_writer bw = {\n-\t\t.last_key = STRBUF_INIT,\n+\t\t.last_key = REFTABLE_BUF_INIT,\n \t};\n \tstruct reftable_record rec = {\n \t\t.type = BLOCK_TYPE_LOG,\n@@ -123,7 +123,7 @@ static void t_log_block_read_write(void)\n \tint ret;\n \tstruct block_reader br = { 0 };\n \tstruct block_iter it = BLOCK_ITER_INIT;\n-\tstruct strbuf want = STRBUF_INIT, buf = STRBUF_INIT;\n+\tstruct reftable_buf want = REFTABLE_BUF_INIT, buf = REFTABLE_BUF_INIT;\n \n \tREFTABLE_CALLOC_ARRAY(block.data, block_size);\n \tcheck(block.data != NULL);\n@@ -166,8 +166,8 @@ static void t_log_block_read_write(void)\n \n \tfor (i = 0; i < N; i++) {\n \t\tblock_iter_reset(&it);\n-\t\tstrbuf_reset(&want);\n-\t\tstrbuf_addstr(&want, recs[i].u.log.refname);\n+\t\treftable_buf_reset(&want);\n+\t\treftable_buf_addstr(&want, recs[i].u.log.refname);\n \n \t\tret = block_iter_seek_key(&it, &br, &want);\n \t\tcheck_int(ret, ==, 0);\n@@ -190,8 +190,8 @@ static void t_log_block_read_write(void)\n \tblock_iter_close(&it);\n \treftable_record_release(&rec);\n \treftable_block_done(&br.block);\n-\tstrbuf_release(&want);\n-\tstrbuf_release(&buf);\n+\treftable_buf_release(&want);\n+\treftable_buf_release(&buf);\n \tfor (i = 0; i < N; i++)\n \t\treftable_record_release(&recs[i]);\n }\n@@ -204,7 +204,7 @@ static void t_obj_block_read_write(void)\n \tconst size_t block_size = 1024;\n \tstruct reftable_block block = { 0 };\n \tstruct block_writer bw = {\n-\t\t.last_key = STRBUF_INIT,\n+\t\t.last_key = REFTABLE_BUF_INIT,\n \t};\n \tstruct reftable_record rec = {\n \t\t.type = BLOCK_TYPE_OBJ,\n@@ -213,7 +213,7 @@ static void t_obj_block_read_write(void)\n \tint ret;\n \tstruct block_reader br = { 0 };\n \tstruct block_iter it = BLOCK_ITER_INIT;\n-\tstruct strbuf want = STRBUF_INIT, buf = STRBUF_INIT;\n+\tstruct reftable_buf want = REFTABLE_BUF_INIT, buf = REFTABLE_BUF_INIT;\n \n \tREFTABLE_CALLOC_ARRAY(block.data, block_size);\n \tcheck(block.data != NULL);\n@@ -273,8 +273,8 @@ static void t_obj_block_read_write(void)\n \tblock_iter_close(&it);\n \treftable_record_release(&rec);\n \treftable_block_done(&br.block);\n-\tstrbuf_release(&want);\n-\tstrbuf_release(&buf);\n+\treftable_buf_release(&want);\n+\treftable_buf_release(&buf);\n \tfor (i = 0; i < N; i++)\n \t\treftable_record_release(&recs[i]);\n }\n@@ -287,17 +287,17 @@ static void t_index_block_read_write(void)\n \tconst size_t block_size = 1024;\n \tstruct reftable_block block = { 0 };\n \tstruct block_writer bw = {\n-\t\t.last_key = STRBUF_INIT,\n+\t\t.last_key = REFTABLE_BUF_INIT,\n \t};\n \tstruct reftable_record rec = {\n \t\t.type = BLOCK_TYPE_INDEX,\n-\t\t.u.idx.last_key = STRBUF_INIT,\n+\t\t.u.idx.last_key = REFTABLE_BUF_INIT,\n \t};\n \tsize_t i = 0;\n \tint ret;\n \tstruct block_reader br = { 0 };\n \tstruct block_iter it = BLOCK_ITER_INIT;\n-\tstruct strbuf want = STRBUF_INIT, buf = STRBUF_INIT;\n+\tstruct reftable_buf want = REFTABLE_BUF_INIT, buf = REFTABLE_BUF_INIT;\n \n \tREFTABLE_CALLOC_ARRAY(block.data, block_size);\n \tcheck(block.data != NULL);\n@@ -312,9 +312,9 @@ static void t_index_block_read_write(void)\n \n \t\tsnprintf(buf, sizeof(buf), \"branch%02\"PRIuMAX, (uintmax_t)i);\n \n-\t\tstrbuf_init(&recs[i].u.idx.last_key, 9);\n+\t\treftable_buf_init(&recs[i].u.idx.last_key);\n \t\trecs[i].type = BLOCK_TYPE_INDEX;\n-\t\tstrbuf_addstr(&recs[i].u.idx.last_key, buf);\n+\t\treftable_buf_addstr(&recs[i].u.idx.last_key, buf);\n \t\trecs[i].u.idx.offset = i;\n \n \t\tret = block_writer_add(&bw, &recs[i]);\n@@ -365,8 +365,8 @@ static void t_index_block_read_write(void)\n \tblock_iter_close(&it);\n \treftable_record_release(&rec);\n \treftable_block_done(&br.block);\n-\tstrbuf_release(&want);\n-\tstrbuf_release(&buf);\n+\treftable_buf_release(&want);\n+\treftable_buf_release(&buf);\n \tfor (i = 0; i < N; i++)\n \t\treftable_record_release(&recs[i]);\n }\ndiff --git a/t/unit-tests/t-reftable-merged.c b/t/unit-tests/t-reftable-merged.c\nindex 3c84363e980..9b0162a4b32 100644\n--- a/t/unit-tests/t-reftable-merged.c\n+++ b/t/unit-tests/t-reftable-merged.c\n@@ -20,7 +20,7 @@ static struct reftable_merged_table *\n merged_table_from_records(struct reftable_ref_record **refs,\n \t\t\t  struct reftable_block_source **source,\n \t\t\t  struct reftable_reader ***readers, const size_t *sizes,\n-\t\t\t  struct strbuf *buf, const size_t n)\n+\t\t\t  struct reftable_buf *buf, const size_t n)\n {\n \tstruct reftable_merged_table *mt = NULL;\n \tstruct reftable_write_options opts = {\n@@ -75,7 +75,7 @@ static void t_merged_single_record(void)\n \n \tstruct reftable_ref_record *refs[] = { r1, r2, r3 };\n \tsize_t sizes[] = { ARRAY_SIZE(r1), ARRAY_SIZE(r2), ARRAY_SIZE(r3) };\n-\tstruct strbuf bufs[3] = { STRBUF_INIT, STRBUF_INIT, STRBUF_INIT };\n+\tstruct reftable_buf bufs[3] = { REFTABLE_BUF_INIT, REFTABLE_BUF_INIT, REFTABLE_BUF_INIT };\n \tstruct reftable_block_source *bs = NULL;\n \tstruct reftable_reader **readers = NULL;\n \tstruct reftable_merged_table *mt =\n@@ -97,7 +97,7 @@ static void t_merged_single_record(void)\n \treaders_destroy(readers, 3);\n \treftable_merged_table_free(mt);\n \tfor (size_t i = 0; i < ARRAY_SIZE(bufs); i++)\n-\t\tstrbuf_release(&bufs[i]);\n+\t\treftable_buf_release(&bufs[i]);\n \treftable_free(bs);\n }\n \n@@ -152,7 +152,7 @@ static void t_merged_refs(void)\n \n \tstruct reftable_ref_record *refs[] = { r1, r2, r3 };\n \tsize_t sizes[3] = { ARRAY_SIZE(r1), ARRAY_SIZE(r2), ARRAY_SIZE(r3) };\n-\tstruct strbuf bufs[3] = { STRBUF_INIT, STRBUF_INIT, STRBUF_INIT };\n+\tstruct reftable_buf bufs[3] = { REFTABLE_BUF_INIT, REFTABLE_BUF_INIT, REFTABLE_BUF_INIT };\n \tstruct reftable_block_source *bs = NULL;\n \tstruct reftable_reader **readers = NULL;\n \tstruct reftable_merged_table *mt =\n@@ -192,7 +192,7 @@ static void t_merged_refs(void)\n \treftable_free(out);\n \n \tfor (i = 0; i < 3; i++)\n-\t\tstrbuf_release(&bufs[i]);\n+\t\treftable_buf_release(&bufs[i]);\n \treaders_destroy(readers, 3);\n \treftable_merged_table_free(mt);\n \treftable_free(bs);\n@@ -234,8 +234,8 @@ static void t_merged_seek_multiple_times(void)\n \tsize_t sizes[] = {\n \t\tARRAY_SIZE(r1), ARRAY_SIZE(r2),\n \t};\n-\tstruct strbuf bufs[] = {\n-\t\tSTRBUF_INIT, STRBUF_INIT,\n+\tstruct reftable_buf bufs[] = {\n+\t\tREFTABLE_BUF_INIT, REFTABLE_BUF_INIT,\n \t};\n \tstruct reftable_block_source *sources = NULL;\n \tstruct reftable_reader **readers = NULL;\n@@ -265,7 +265,7 @@ static void t_merged_seek_multiple_times(void)\n \t}\n \n \tfor (size_t i = 0; i < ARRAY_SIZE(bufs); i++)\n-\t\tstrbuf_release(&bufs[i]);\n+\t\treftable_buf_release(&bufs[i]);\n \treaders_destroy(readers, ARRAY_SIZE(refs));\n \treftable_ref_record_release(&rec);\n \treftable_iterator_destroy(&it);\n@@ -277,7 +277,7 @@ static struct reftable_merged_table *\n merged_table_from_log_records(struct reftable_log_record **logs,\n \t\t\t      struct reftable_block_source **source,\n \t\t\t      struct reftable_reader ***readers, const size_t *sizes,\n-\t\t\t      struct strbuf *buf, const size_t n)\n+\t\t\t      struct reftable_buf *buf, const size_t n)\n {\n \tstruct reftable_merged_table *mt = NULL;\n \tstruct reftable_write_options opts = {\n@@ -361,7 +361,7 @@ static void t_merged_logs(void)\n \n \tstruct reftable_log_record *logs[] = { r1, r2, r3 };\n \tsize_t sizes[3] = { ARRAY_SIZE(r1), ARRAY_SIZE(r2), ARRAY_SIZE(r3) };\n-\tstruct strbuf bufs[3] = { STRBUF_INIT, STRBUF_INIT, STRBUF_INIT };\n+\tstruct reftable_buf bufs[3] = { REFTABLE_BUF_INIT, REFTABLE_BUF_INIT, REFTABLE_BUF_INIT };\n \tstruct reftable_block_source *bs = NULL;\n \tstruct reftable_reader **readers = NULL;\n \tstruct reftable_merged_table *mt = merged_table_from_log_records(\n@@ -412,7 +412,7 @@ static void t_merged_logs(void)\n \treftable_free(out);\n \n \tfor (i = 0; i < 3; i++)\n-\t\tstrbuf_release(&bufs[i]);\n+\t\treftable_buf_release(&bufs[i]);\n \treaders_destroy(readers, 3);\n \treftable_merged_table_free(mt);\n \treftable_free(bs);\n@@ -421,7 +421,7 @@ static void t_merged_logs(void)\n static void t_default_write_opts(void)\n {\n \tstruct reftable_write_options opts = { 0 };\n-\tstruct strbuf buf = STRBUF_INIT;\n+\tstruct reftable_buf buf = REFTABLE_BUF_INIT;\n \tstruct reftable_writer *w = t_reftable_strbuf_writer(&buf, &opts);\n \tstruct reftable_ref_record rec = {\n \t\t.refname = (char *) \"master\",\n@@ -457,7 +457,7 @@ static void t_default_write_opts(void)\n \n \treftable_reader_decref(rd);\n \treftable_merged_table_free(merged);\n-\tstrbuf_release(&buf);\n+\treftable_buf_release(&buf);\n }\n \n \ndiff --git a/t/unit-tests/t-reftable-reader.c b/t/unit-tests/t-reftable-reader.c\nindex eea86966c0d..8a18d7f9be4 100644\n--- a/t/unit-tests/t-reftable-reader.c\n+++ b/t/unit-tests/t-reftable-reader.c\n@@ -16,7 +16,7 @@ static int t_reader_seek_once(void)\n \tstruct reftable_ref_record ref = { 0 };\n \tstruct reftable_iterator it = { 0 };\n \tstruct reftable_reader *reader;\n-\tstruct strbuf buf = STRBUF_INIT;\n+\tstruct reftable_buf buf = REFTABLE_BUF_INIT;\n \tint ret;\n \n \tt_reftable_write_to_buf(&buf, records, ARRAY_SIZE(records), NULL, 0, NULL);\n@@ -40,7 +40,7 @@ static int t_reader_seek_once(void)\n \treftable_ref_record_release(&ref);\n \treftable_iterator_destroy(&it);\n \treftable_reader_decref(reader);\n-\tstrbuf_release(&buf);\n+\treftable_buf_release(&buf);\n \treturn 0;\n }\n \n@@ -57,7 +57,7 @@ static int t_reader_reseek(void)\n \tstruct reftable_ref_record ref = { 0 };\n \tstruct reftable_iterator it = { 0 };\n \tstruct reftable_reader *reader;\n-\tstruct strbuf buf = STRBUF_INIT;\n+\tstruct reftable_buf buf = REFTABLE_BUF_INIT;\n \tint ret;\n \n \tt_reftable_write_to_buf(&buf, records, ARRAY_SIZE(records), NULL, 0, NULL);\n@@ -84,7 +84,7 @@ static int t_reader_reseek(void)\n \treftable_ref_record_release(&ref);\n \treftable_iterator_destroy(&it);\n \treftable_reader_decref(reader);\n-\tstrbuf_release(&buf);\n+\treftable_buf_release(&buf);\n \treturn 0;\n }\n \ndiff --git a/t/unit-tests/t-reftable-readwrite.c b/t/unit-tests/t-reftable-readwrite.c\nindex 5f59b0ad6ad..c56a33f1a1e 100644\n--- a/t/unit-tests/t-reftable-readwrite.c\n+++ b/t/unit-tests/t-reftable-readwrite.c\n@@ -18,12 +18,12 @@ static const int update_index = 5;\n \n static void t_buffer(void)\n {\n-\tstruct strbuf buf = STRBUF_INIT;\n+\tstruct reftable_buf buf = REFTABLE_BUF_INIT;\n \tstruct reftable_block_source source = { 0 };\n \tstruct reftable_block out = { 0 };\n \tint n;\n \tuint8_t in[] = \"hello\";\n-\tstrbuf_add(&buf, in, sizeof(in));\n+\treftable_buf_add(&buf, in, sizeof(in));\n \tblock_source_from_strbuf(&source, &buf);\n \tcheck_int(block_source_size(&source), ==, 6);\n \tn = block_source_read_block(&source, &out, 0, sizeof(in));\n@@ -37,10 +37,10 @@ static void t_buffer(void)\n \n \treftable_block_done(&out);\n \tblock_source_close(&source);\n-\tstrbuf_release(&buf);\n+\treftable_buf_release(&buf);\n }\n \n-static void write_table(char ***names, struct strbuf *buf, int N,\n+static void write_table(char ***names, struct reftable_buf *buf, int N,\n \t\t\tint block_size, uint32_t hash_id)\n {\n \tstruct reftable_write_options opts = {\n@@ -82,7 +82,7 @@ static void write_table(char ***names, struct strbuf *buf, int N,\n \n static void t_log_buffer_size(void)\n {\n-\tstruct strbuf buf = STRBUF_INIT;\n+\tstruct reftable_buf buf = REFTABLE_BUF_INIT;\n \tstruct reftable_write_options opts = {\n \t\t.block_size = 4096,\n \t};\n@@ -114,12 +114,12 @@ static void t_log_buffer_size(void)\n \terr = reftable_writer_close(w);\n \tcheck(!err);\n \treftable_writer_free(w);\n-\tstrbuf_release(&buf);\n+\treftable_buf_release(&buf);\n }\n \n static void t_log_overflow(void)\n {\n-\tstruct strbuf buf = STRBUF_INIT;\n+\tstruct reftable_buf buf = REFTABLE_BUF_INIT;\n \tchar msg[256] = { 0 };\n \tstruct reftable_write_options opts = {\n \t\t.block_size = ARRAY_SIZE(msg),\n@@ -148,7 +148,7 @@ static void t_log_overflow(void)\n \terr = reftable_writer_add_log(w, &log);\n \tcheck_int(err, ==, REFTABLE_ENTRY_TOO_BIG_ERROR);\n \treftable_writer_free(w);\n-\tstrbuf_release(&buf);\n+\treftable_buf_release(&buf);\n }\n \n static void t_log_write_read(void)\n@@ -161,7 +161,7 @@ static void t_log_write_read(void)\n \tstruct reftable_iterator it = { 0 };\n \tstruct reftable_reader *reader;\n \tstruct reftable_block_source source = { 0 };\n-\tstruct strbuf buf = STRBUF_INIT;\n+\tstruct reftable_buf buf = REFTABLE_BUF_INIT;\n \tstruct reftable_writer *w = t_reftable_strbuf_writer(&buf, &opts);\n \tconst struct reftable_stats *stats = NULL;\n \tint N = 2, err, i, n;\n@@ -247,7 +247,7 @@ static void t_log_write_read(void)\n \treftable_iterator_destroy(&it);\n \n \t/* cleanup. */\n-\tstrbuf_release(&buf);\n+\treftable_buf_release(&buf);\n \tfree_names(names);\n \treftable_reader_decref(reader);\n }\n@@ -260,7 +260,7 @@ static void t_log_zlib_corruption(void)\n \tstruct reftable_iterator it = { 0 };\n \tstruct reftable_reader *reader;\n \tstruct reftable_block_source source = { 0 };\n-\tstruct strbuf buf = STRBUF_INIT;\n+\tstruct reftable_buf buf = REFTABLE_BUF_INIT;\n \tstruct reftable_writer *w = t_reftable_strbuf_writer(&buf, &opts);\n \tconst struct reftable_stats *stats = NULL;\n \tchar message[100] = { 0 };\n@@ -312,13 +312,13 @@ static void t_log_zlib_corruption(void)\n \n \t/* cleanup. */\n \treftable_reader_decref(reader);\n-\tstrbuf_release(&buf);\n+\treftable_buf_release(&buf);\n }\n \n static void t_table_read_write_sequential(void)\n {\n \tchar **names;\n-\tstruct strbuf buf = STRBUF_INIT;\n+\tstruct reftable_buf buf = REFTABLE_BUF_INIT;\n \tint N = 50;\n \tstruct reftable_iterator it = { 0 };\n \tstruct reftable_block_source source = { 0 };\n@@ -352,25 +352,25 @@ static void t_table_read_write_sequential(void)\n \n \treftable_iterator_destroy(&it);\n \treftable_reader_decref(reader);\n-\tstrbuf_release(&buf);\n+\treftable_buf_release(&buf);\n \tfree_names(names);\n }\n \n static void t_table_write_small_table(void)\n {\n \tchar **names;\n-\tstruct strbuf buf = STRBUF_INIT;\n+\tstruct reftable_buf buf = REFTABLE_BUF_INIT;\n \tint N = 1;\n \twrite_table(&names, &buf, N, 4096, GIT_SHA1_FORMAT_ID);\n \tcheck_int(buf.len, <, 200);\n-\tstrbuf_release(&buf);\n+\treftable_buf_release(&buf);\n \tfree_names(names);\n }\n \n static void t_table_read_api(void)\n {\n \tchar **names;\n-\tstruct strbuf buf = STRBUF_INIT;\n+\tstruct reftable_buf buf = REFTABLE_BUF_INIT;\n \tint N = 50;\n \tstruct reftable_reader *reader;\n \tstruct reftable_block_source source = { 0 };\n@@ -393,17 +393,17 @@ static void t_table_read_api(void)\n \terr = reftable_iterator_next_log(&it, &log);\n \tcheck_int(err, ==, REFTABLE_API_ERROR);\n \n-\tstrbuf_release(&buf);\n+\treftable_buf_release(&buf);\n \tfree_names(names);\n \treftable_iterator_destroy(&it);\n \treftable_reader_decref(reader);\n-\tstrbuf_release(&buf);\n+\treftable_buf_release(&buf);\n }\n \n static void t_table_read_write_seek(int index, int hash_id)\n {\n \tchar **names;\n-\tstruct strbuf buf = STRBUF_INIT;\n+\tstruct reftable_buf buf = REFTABLE_BUF_INIT;\n \tint N = 50;\n \tstruct reftable_reader *reader;\n \tstruct reftable_block_source source = { 0 };\n@@ -411,7 +411,7 @@ static void t_table_read_write_seek(int index, int hash_id)\n \tint i = 0;\n \n \tstruct reftable_iterator it = { 0 };\n-\tstruct strbuf pastLast = STRBUF_INIT;\n+\tstruct reftable_buf pastLast = REFTABLE_BUF_INIT;\n \tstruct reftable_ref_record ref = { 0 };\n \n \twrite_table(&names, &buf, N, 256, hash_id);\n@@ -443,8 +443,8 @@ static void t_table_read_write_seek(int index, int hash_id)\n \t\treftable_iterator_destroy(&it);\n \t}\n \n-\tstrbuf_addstr(&pastLast, names[N - 1]);\n-\tstrbuf_addstr(&pastLast, \"/\");\n+\treftable_buf_addstr(&pastLast, names[N - 1]);\n+\treftable_buf_addstr(&pastLast, \"/\");\n \n \terr = reftable_reader_init_ref_iterator(reader, &it);\n \tcheck(!err);\n@@ -457,10 +457,10 @@ static void t_table_read_write_seek(int index, int hash_id)\n \t\tcheck_int(err, >, 0);\n \t}\n \n-\tstrbuf_release(&pastLast);\n+\treftable_buf_release(&pastLast);\n \treftable_iterator_destroy(&it);\n \n-\tstrbuf_release(&buf);\n+\treftable_buf_release(&buf);\n \tfree_names(names);\n \treftable_reader_decref(reader);\n }\n@@ -492,7 +492,7 @@ static void t_table_refs_for(int indexed)\n \tstruct reftable_ref_record ref = { 0 };\n \tstruct reftable_reader *reader;\n \tstruct reftable_block_source source = { 0 };\n-\tstruct strbuf buf = STRBUF_INIT;\n+\tstruct reftable_buf buf = REFTABLE_BUF_INIT;\n \tstruct reftable_writer *w = t_reftable_strbuf_writer(&buf, &opts);\n \tstruct reftable_iterator it = { 0 };\n \tint N = 50, n, j, err, i;\n@@ -565,7 +565,7 @@ static void t_table_refs_for(int indexed)\n \t}\n \tcheck_int(j, ==, want_names_len);\n \n-\tstrbuf_release(&buf);\n+\treftable_buf_release(&buf);\n \tfree_names(want_names);\n \treftable_iterator_destroy(&it);\n \treftable_reader_decref(reader);\n@@ -584,7 +584,7 @@ static void t_table_refs_for_obj_index(void)\n static void t_write_empty_table(void)\n {\n \tstruct reftable_write_options opts = { 0 };\n-\tstruct strbuf buf = STRBUF_INIT;\n+\tstruct reftable_buf buf = REFTABLE_BUF_INIT;\n \tstruct reftable_writer *w = t_reftable_strbuf_writer(&buf, &opts);\n \tstruct reftable_block_source source = { 0 };\n \tstruct reftable_reader *rd = NULL;\n@@ -615,7 +615,7 @@ static void t_write_empty_table(void)\n \n \treftable_iterator_destroy(&it);\n \treftable_reader_decref(rd);\n-\tstrbuf_release(&buf);\n+\treftable_buf_release(&buf);\n }\n \n static void t_write_object_id_min_length(void)\n@@ -623,7 +623,7 @@ static void t_write_object_id_min_length(void)\n \tstruct reftable_write_options opts = {\n \t\t.block_size = 75,\n \t};\n-\tstruct strbuf buf = STRBUF_INIT;\n+\tstruct reftable_buf buf = REFTABLE_BUF_INIT;\n \tstruct reftable_writer *w = t_reftable_strbuf_writer(&buf, &opts);\n \tstruct reftable_ref_record ref = {\n \t\t.update_index = 1,\n@@ -649,7 +649,7 @@ static void t_write_object_id_min_length(void)\n \tcheck(!err);\n \tcheck_int(reftable_writer_stats(w)->object_id_len, ==, 2);\n \treftable_writer_free(w);\n-\tstrbuf_release(&buf);\n+\treftable_buf_release(&buf);\n }\n \n static void t_write_object_id_length(void)\n@@ -657,7 +657,7 @@ static void t_write_object_id_length(void)\n \tstruct reftable_write_options opts = {\n \t\t.block_size = 75,\n \t};\n-\tstruct strbuf buf = STRBUF_INIT;\n+\tstruct reftable_buf buf = REFTABLE_BUF_INIT;\n \tstruct reftable_writer *w = t_reftable_strbuf_writer(&buf, &opts);\n \tstruct reftable_ref_record ref = {\n \t\t.update_index = 1,\n@@ -684,13 +684,13 @@ static void t_write_object_id_length(void)\n \tcheck(!err);\n \tcheck_int(reftable_writer_stats(w)->object_id_len, ==, 16);\n \treftable_writer_free(w);\n-\tstrbuf_release(&buf);\n+\treftable_buf_release(&buf);\n }\n \n static void t_write_empty_key(void)\n {\n \tstruct reftable_write_options opts = { 0 };\n-\tstruct strbuf buf = STRBUF_INIT;\n+\tstruct reftable_buf buf = REFTABLE_BUF_INIT;\n \tstruct reftable_writer *w = t_reftable_strbuf_writer(&buf, &opts);\n \tstruct reftable_ref_record ref = {\n \t\t.refname = (char *) \"\",\n@@ -706,13 +706,13 @@ static void t_write_empty_key(void)\n \terr = reftable_writer_close(w);\n \tcheck_int(err, ==, REFTABLE_EMPTY_TABLE_ERROR);\n \treftable_writer_free(w);\n-\tstrbuf_release(&buf);\n+\treftable_buf_release(&buf);\n }\n \n static void t_write_key_order(void)\n {\n \tstruct reftable_write_options opts = { 0 };\n-\tstruct strbuf buf = STRBUF_INIT;\n+\tstruct reftable_buf buf = REFTABLE_BUF_INIT;\n \tstruct reftable_writer *w = t_reftable_strbuf_writer(&buf, &opts);\n \tstruct reftable_ref_record refs[2] = {\n \t\t{\n@@ -745,7 +745,7 @@ static void t_write_key_order(void)\n \n \treftable_writer_close(w);\n \treftable_writer_free(w);\n-\tstrbuf_release(&buf);\n+\treftable_buf_release(&buf);\n }\n \n static void t_write_multiple_indices(void)\n@@ -753,7 +753,7 @@ static void t_write_multiple_indices(void)\n \tstruct reftable_write_options opts = {\n \t\t.block_size = 100,\n \t};\n-\tstruct strbuf writer_buf = STRBUF_INIT;\n+\tstruct reftable_buf writer_buf = REFTABLE_BUF_INIT;\n \tstruct reftable_block_source source = { 0 };\n \tstruct reftable_iterator it = { 0 };\n \tconst struct reftable_stats *stats;\n@@ -822,7 +822,7 @@ static void t_write_multiple_indices(void)\n \treftable_iterator_destroy(&it);\n \treftable_writer_free(writer);\n \treftable_reader_decref(reader);\n-\tstrbuf_release(&writer_buf);\n+\treftable_buf_release(&writer_buf);\n }\n \n static void t_write_multi_level_index(void)\n@@ -830,7 +830,7 @@ static void t_write_multi_level_index(void)\n \tstruct reftable_write_options opts = {\n \t\t.block_size = 100,\n \t};\n-\tstruct strbuf writer_buf = STRBUF_INIT, buf = STRBUF_INIT;\n+\tstruct reftable_buf writer_buf = REFTABLE_BUF_INIT, buf = REFTABLE_BUF_INIT;\n \tstruct reftable_block_source source = { 0 };\n \tstruct reftable_iterator it = { 0 };\n \tconst struct reftable_stats *stats;\n@@ -878,13 +878,13 @@ static void t_write_multi_level_index(void)\n \treftable_iterator_destroy(&it);\n \treftable_writer_free(writer);\n \treftable_reader_decref(reader);\n-\tstrbuf_release(&writer_buf);\n-\tstrbuf_release(&buf);\n+\treftable_buf_release(&writer_buf);\n+\treftable_buf_release(&buf);\n }\n \n static void t_corrupt_table_empty(void)\n {\n-\tstruct strbuf buf = STRBUF_INIT;\n+\tstruct reftable_buf buf = REFTABLE_BUF_INIT;\n \tstruct reftable_block_source source = { 0 };\n \tstruct reftable_reader *reader;\n \tint err;\n@@ -897,17 +897,17 @@ static void t_corrupt_table_empty(void)\n static void t_corrupt_table(void)\n {\n \tuint8_t zeros[1024] = { 0 };\n-\tstruct strbuf buf = STRBUF_INIT;\n+\tstruct reftable_buf buf = REFTABLE_BUF_INIT;\n \tstruct reftable_block_source source = { 0 };\n \tstruct reftable_reader *reader;\n \tint err;\n-\tstrbuf_add(&buf, zeros, sizeof(zeros));\n+\treftable_buf_add(&buf, zeros, sizeof(zeros));\n \n \tblock_source_from_strbuf(&source, &buf);\n \terr = reftable_reader_new(&reader, &source, \"file.log\");\n \tcheck_int(err, ==, REFTABLE_FORMAT_ERROR);\n \n-\tstrbuf_release(&buf);\n+\treftable_buf_release(&buf);\n }\n \n int cmd_main(int argc UNUSED, const char *argv[] UNUSED)\ndiff --git a/t/unit-tests/t-reftable-record.c b/t/unit-tests/t-reftable-record.c\nindex a7f67d4d9f2..f2dd01688f3 100644\n--- a/t/unit-tests/t-reftable-record.c\n+++ b/t/unit-tests/t-reftable-record.c\n@@ -116,7 +116,7 @@ static void t_reftable_ref_record_compare_name(void)\n \n static void t_reftable_ref_record_roundtrip(void)\n {\n-\tstruct strbuf scratch = STRBUF_INIT;\n+\tstruct reftable_buf scratch = REFTABLE_BUF_INIT;\n \n \tfor (int i = REFTABLE_REF_DELETION; i < REFTABLE_NR_REF_VALUETYPES; i++) {\n \t\tstruct reftable_record in = {\n@@ -124,7 +124,7 @@ static void t_reftable_ref_record_roundtrip(void)\n \t\t\t.u.ref.value_type = i,\n \t\t};\n \t\tstruct reftable_record out = { .type = BLOCK_TYPE_REF };\n-\t\tstruct strbuf key = STRBUF_INIT;\n+\t\tstruct reftable_buf key = REFTABLE_BUF_INIT;\n \t\tuint8_t buffer[1024] = { 0 };\n \t\tstruct string_view dest = {\n \t\t\t.buf = buffer,\n@@ -166,11 +166,11 @@ static void t_reftable_ref_record_roundtrip(void)\n \t\t\t\t\t\t GIT_SHA1_RAWSZ));\n \t\treftable_record_release(&in);\n \n-\t\tstrbuf_release(&key);\n+\t\treftable_buf_release(&key);\n \t\treftable_record_release(&out);\n \t}\n \n-\tstrbuf_release(&scratch);\n+\treftable_buf_release(&scratch);\n }\n \n static void t_reftable_log_record_comparison(void)\n@@ -262,7 +262,7 @@ static void t_reftable_log_record_roundtrip(void)\n \t\t\t.value_type = REFTABLE_LOG_UPDATE,\n \t\t}\n \t};\n-\tstruct strbuf scratch = STRBUF_INIT;\n+\tstruct reftable_buf scratch = REFTABLE_BUF_INIT;\n \tset_hash(in[0].value.update.new_hash, 1);\n \tset_hash(in[0].value.update.old_hash, 2);\n \tset_hash(in[2].value.update.new_hash, 3);\n@@ -274,7 +274,7 @@ static void t_reftable_log_record_roundtrip(void)\n \n \tfor (size_t i = 0; i < ARRAY_SIZE(in); i++) {\n \t\tstruct reftable_record rec = { .type = BLOCK_TYPE_LOG };\n-\t\tstruct strbuf key = STRBUF_INIT;\n+\t\tstruct reftable_buf key = REFTABLE_BUF_INIT;\n \t\tuint8_t buffer[1024] = { 0 };\n \t\tstruct string_view dest = {\n \t\t\t.buf = buffer,\n@@ -313,11 +313,11 @@ static void t_reftable_log_record_roundtrip(void)\n \t\tcheck(reftable_log_record_equal(&in[i], &out.u.log,\n \t\t\t\t\t\t GIT_SHA1_RAWSZ));\n \t\treftable_log_record_release(&in[i]);\n-\t\tstrbuf_release(&key);\n+\t\treftable_buf_release(&key);\n \t\treftable_record_release(&out);\n \t}\n \n-\tstrbuf_release(&scratch);\n+\treftable_buf_release(&scratch);\n }\n \n static void t_key_roundtrip(void)\n@@ -327,30 +327,30 @@ static void t_key_roundtrip(void)\n \t\t.buf = buffer,\n \t\t.len = sizeof(buffer),\n \t};\n-\tstruct strbuf last_key = STRBUF_INIT;\n-\tstruct strbuf key = STRBUF_INIT;\n-\tstruct strbuf roundtrip = STRBUF_INIT;\n+\tstruct reftable_buf last_key = REFTABLE_BUF_INIT;\n+\tstruct reftable_buf key = REFTABLE_BUF_INIT;\n+\tstruct reftable_buf roundtrip = REFTABLE_BUF_INIT;\n \tint restart;\n \tuint8_t extra;\n \tint n, m;\n \tuint8_t rt_extra;\n \n-\tstrbuf_addstr(&last_key, \"refs/heads/master\");\n-\tstrbuf_addstr(&key, \"refs/tags/bla\");\n+\treftable_buf_addstr(&last_key, \"refs/heads/master\");\n+\treftable_buf_addstr(&key, \"refs/tags/bla\");\n \textra = 6;\n \tn = reftable_encode_key(&restart, dest, last_key, key, extra);\n \tcheck(!restart);\n \tcheck_int(n, >, 0);\n \n-\tstrbuf_addstr(&roundtrip, \"refs/heads/master\");\n+\treftable_buf_addstr(&roundtrip, \"refs/heads/master\");\n \tm = reftable_decode_key(&roundtrip, &rt_extra, dest);\n \tcheck_int(n, ==, m);\n-\tcheck(!strbuf_cmp(&key, &roundtrip));\n+\tcheck(!reftable_buf_cmp(&key, &roundtrip));\n \tcheck_int(rt_extra, ==, extra);\n \n-\tstrbuf_release(&last_key);\n-\tstrbuf_release(&key);\n-\tstrbuf_release(&roundtrip);\n+\treftable_buf_release(&last_key);\n+\treftable_buf_release(&key);\n+\treftable_buf_release(&roundtrip);\n }\n \n static void t_reftable_obj_record_comparison(void)\n@@ -413,7 +413,7 @@ static void t_reftable_obj_record_roundtrip(void)\n \t\t\t.hash_prefix_len = 5,\n \t\t},\n \t};\n-\tstruct strbuf scratch = STRBUF_INIT;\n+\tstruct reftable_buf scratch = REFTABLE_BUF_INIT;\n \n \tfor (size_t i = 0; i < ARRAY_SIZE(recs); i++) {\n \t\tuint8_t buffer[1024] = { 0 };\n@@ -427,7 +427,7 @@ static void t_reftable_obj_record_roundtrip(void)\n \t\t\t\t.obj = recs[i],\n \t\t\t},\n \t\t};\n-\t\tstruct strbuf key = STRBUF_INIT;\n+\t\tstruct reftable_buf key = REFTABLE_BUF_INIT;\n \t\tstruct reftable_record out = { .type = BLOCK_TYPE_OBJ };\n \t\tint n, m;\n \t\tuint8_t extra;\n@@ -443,11 +443,11 @@ static void t_reftable_obj_record_roundtrip(void)\n \t\tcheck_int(n, ==, m);\n \n \t\tcheck(reftable_record_equal(&in, &out, GIT_SHA1_RAWSZ));\n-\t\tstrbuf_release(&key);\n+\t\treftable_buf_release(&key);\n \t\treftable_record_release(&out);\n \t}\n \n-\tstrbuf_release(&scratch);\n+\treftable_buf_release(&scratch);\n }\n \n static void t_reftable_index_record_comparison(void)\n@@ -456,22 +456,22 @@ static void t_reftable_index_record_comparison(void)\n \t\t{\n \t\t\t.type = BLOCK_TYPE_INDEX,\n \t\t\t.u.idx.offset = 22,\n-\t\t\t.u.idx.last_key = STRBUF_INIT,\n+\t\t\t.u.idx.last_key = REFTABLE_BUF_INIT,\n \t\t},\n \t\t{\n \t\t\t.type = BLOCK_TYPE_INDEX,\n \t\t\t.u.idx.offset = 32,\n-\t\t\t.u.idx.last_key = STRBUF_INIT,\n+\t\t\t.u.idx.last_key = REFTABLE_BUF_INIT,\n \t\t},\n \t\t{\n \t\t\t.type = BLOCK_TYPE_INDEX,\n \t\t\t.u.idx.offset = 32,\n-\t\t\t.u.idx.last_key = STRBUF_INIT,\n+\t\t\t.u.idx.last_key = REFTABLE_BUF_INIT,\n \t\t},\n \t};\n-\tstrbuf_addstr(&in[0].u.idx.last_key, \"refs/heads/master\");\n-\tstrbuf_addstr(&in[1].u.idx.last_key, \"refs/heads/master\");\n-\tstrbuf_addstr(&in[2].u.idx.last_key, \"refs/heads/branch\");\n+\treftable_buf_addstr(&in[0].u.idx.last_key, \"refs/heads/master\");\n+\treftable_buf_addstr(&in[1].u.idx.last_key, \"refs/heads/master\");\n+\treftable_buf_addstr(&in[2].u.idx.last_key, \"refs/heads/branch\");\n \n \tcheck(!reftable_record_equal(&in[0], &in[1], GIT_SHA1_RAWSZ));\n \tcheck(!reftable_record_cmp(&in[0], &in[1]));\n@@ -493,7 +493,7 @@ static void t_reftable_index_record_roundtrip(void)\n \t\t.type = BLOCK_TYPE_INDEX,\n \t\t.u.idx = {\n \t\t\t.offset = 42,\n-\t\t\t.last_key = STRBUF_INIT,\n+\t\t\t.last_key = REFTABLE_BUF_INIT,\n \t\t},\n \t};\n \tuint8_t buffer[1024] = { 0 };\n@@ -501,21 +501,21 @@ static void t_reftable_index_record_roundtrip(void)\n \t\t.buf = buffer,\n \t\t.len = sizeof(buffer),\n \t};\n-\tstruct strbuf scratch = STRBUF_INIT;\n-\tstruct strbuf key = STRBUF_INIT;\n+\tstruct reftable_buf scratch = REFTABLE_BUF_INIT;\n+\tstruct reftable_buf key = REFTABLE_BUF_INIT;\n \tstruct reftable_record out = {\n \t\t.type = BLOCK_TYPE_INDEX,\n-\t\t.u.idx = { .last_key = STRBUF_INIT },\n+\t\t.u.idx = { .last_key = REFTABLE_BUF_INIT },\n \t};\n \tint n, m;\n \tuint8_t extra;\n \n-\tstrbuf_addstr(&in.u.idx.last_key, \"refs/heads/master\");\n+\treftable_buf_addstr(&in.u.idx.last_key, \"refs/heads/master\");\n \treftable_record_key(&in, &key);\n \tt_copy(&in);\n \n \tcheck(!reftable_record_is_deletion(&in));\n-\tcheck(!strbuf_cmp(&key, &in.u.idx.last_key));\n+\tcheck(!reftable_buf_cmp(&key, &in.u.idx.last_key));\n \tn = reftable_record_encode(&in, dest, GIT_SHA1_RAWSZ);\n \tcheck_int(n, >, 0);\n \n@@ -527,9 +527,9 @@ static void t_reftable_index_record_roundtrip(void)\n \tcheck(reftable_record_equal(&in, &out, GIT_SHA1_RAWSZ));\n \n \treftable_record_release(&out);\n-\tstrbuf_release(&key);\n-\tstrbuf_release(&scratch);\n-\tstrbuf_release(&in.u.idx.last_key);\n+\treftable_buf_release(&key);\n+\treftable_buf_release(&scratch);\n+\treftable_buf_release(&in.u.idx.last_key);\n }\n \n int cmd_main(int argc UNUSED, const char *argv[] UNUSED)\ndiff --git a/t/unit-tests/t-reftable-stack.c b/t/unit-tests/t-reftable-stack.c\nindex b56ea774312..f49856270d6 100644\n--- a/t/unit-tests/t-reftable-stack.c\n+++ b/t/unit-tests/t-reftable-stack.c\n@@ -16,7 +16,7 @@ license that can be found in the LICENSE file or at\n \n static void clear_dir(const char *dirname)\n {\n-\tstruct strbuf path = STRBUF_INIT;\n+\tstruct strbuf path = REFTABLE_BUF_INIT;\n \tstrbuf_addstr(&path, dirname);\n \tremove_dir_recursively(&path, 0);\n \tstrbuf_release(&path);\n@@ -145,7 +145,7 @@ static int write_test_log(struct reftable_writer *wr, void *arg)\n static void t_reftable_stack_add_one(void)\n {\n \tchar *dir = get_tmp_dir(__LINE__);\n-\tstruct strbuf scratch = STRBUF_INIT;\n+\tstruct reftable_buf scratch = REFTABLE_BUF_INIT;\n \tint mask = umask(002);\n \tstruct reftable_write_options opts = {\n \t\t.default_permissions = 0660,\n@@ -172,17 +172,17 @@ static void t_reftable_stack_add_one(void)\n \tcheck_int(st->readers_len, >, 0);\n \n #ifndef GIT_WINDOWS_NATIVE\n-\tstrbuf_addstr(&scratch, dir);\n-\tstrbuf_addstr(&scratch, \"/tables.list\");\n+\treftable_buf_addstr(&scratch, dir);\n+\treftable_buf_addstr(&scratch, \"/tables.list\");\n \terr = stat(scratch.buf, &stat_result);\n \tcheck(!err);\n \tcheck_int((stat_result.st_mode & 0777), ==, opts.default_permissions);\n \n-\tstrbuf_reset(&scratch);\n-\tstrbuf_addstr(&scratch, dir);\n-\tstrbuf_addstr(&scratch, \"/\");\n+\treftable_buf_reset(&scratch);\n+\treftable_buf_addstr(&scratch, dir);\n+\treftable_buf_addstr(&scratch, \"/\");\n \t/* do not try at home; not an external API for reftable. */\n-\tstrbuf_addstr(&scratch, st->readers[0]->name);\n+\treftable_buf_addstr(&scratch, st->readers[0]->name);\n \terr = stat(scratch.buf, &stat_result);\n \tcheck(!err);\n \tcheck_int((stat_result.st_mode & 0777), ==, opts.default_permissions);\n@@ -192,7 +192,7 @@ static void t_reftable_stack_add_one(void)\n \n \treftable_ref_record_release(&dest);\n \treftable_stack_destroy(st);\n-\tstrbuf_release(&scratch);\n+\treftable_buf_release(&scratch);\n \tclear_dir(dir);\n \tumask(mask);\n }\n@@ -414,7 +414,7 @@ static void t_reftable_stack_auto_compaction_fails_gracefully(void)\n \t};\n \tstruct reftable_write_options opts = { 0 };\n \tstruct reftable_stack *st;\n-\tstruct strbuf table_path = STRBUF_INIT;\n+\tstruct reftable_buf table_path = REFTABLE_BUF_INIT;\n \tchar *dir = get_tmp_dir(__LINE__);\n \tint err;\n \n@@ -432,10 +432,10 @@ static void t_reftable_stack_auto_compaction_fails_gracefully(void)\n \t * Adding a new table to the stack should not be impacted by this, even\n \t * though auto-compaction will now fail.\n \t */\n-\tstrbuf_addstr(&table_path, dir);\n-\tstrbuf_addstr(&table_path, \"/\");\n-\tstrbuf_addstr(&table_path, st->readers[0]->name);\n-\tstrbuf_addstr(&table_path, \".lock\");\n+\treftable_buf_addstr(&table_path, dir);\n+\treftable_buf_addstr(&table_path, \"/\");\n+\treftable_buf_addstr(&table_path, st->readers[0]->name);\n+\treftable_buf_addstr(&table_path, \".lock\");\n \twrite_file_buf(table_path.buf, \"\", 0);\n \n \tref.update_index = 2;\n@@ -446,7 +446,7 @@ static void t_reftable_stack_auto_compaction_fails_gracefully(void)\n \tcheck_int(st->stats.failures, ==, 1);\n \n \treftable_stack_destroy(st);\n-\tstrbuf_release(&table_path);\n+\treftable_buf_release(&table_path);\n \tclear_dir(dir);\n }\n \n@@ -516,7 +516,7 @@ static void t_reftable_stack_add(void)\n \tchar *dir = get_tmp_dir(__LINE__);\n \tstruct reftable_ref_record refs[2] = { 0 };\n \tstruct reftable_log_record logs[2] = { 0 };\n-\tstruct strbuf path = STRBUF_INIT;\n+\tstruct reftable_buf path = REFTABLE_BUF_INIT;\n \tstruct stat stat_result;\n \tsize_t i, N = ARRAY_SIZE(refs);\n \n@@ -575,17 +575,17 @@ static void t_reftable_stack_add(void)\n \t}\n \n #ifndef GIT_WINDOWS_NATIVE\n-\tstrbuf_addstr(&path, dir);\n-\tstrbuf_addstr(&path, \"/tables.list\");\n+\treftable_buf_addstr(&path, dir);\n+\treftable_buf_addstr(&path, \"/tables.list\");\n \terr = stat(path.buf, &stat_result);\n \tcheck(!err);\n \tcheck_int((stat_result.st_mode & 0777), ==, opts.default_permissions);\n \n-\tstrbuf_reset(&path);\n-\tstrbuf_addstr(&path, dir);\n-\tstrbuf_addstr(&path, \"/\");\n+\treftable_buf_reset(&path);\n+\treftable_buf_addstr(&path, dir);\n+\treftable_buf_addstr(&path, \"/\");\n \t/* do not try at home; not an external API for reftable. */\n-\tstrbuf_addstr(&path, st->readers[0]->name);\n+\treftable_buf_addstr(&path, st->readers[0]->name);\n \terr = stat(path.buf, &stat_result);\n \tcheck(!err);\n \tcheck_int((stat_result.st_mode & 0777), ==, opts.default_permissions);\n@@ -599,7 +599,7 @@ static void t_reftable_stack_add(void)\n \t\treftable_ref_record_release(&refs[i]);\n \t\treftable_log_record_release(&logs[i]);\n \t}\n-\tstrbuf_release(&path);\n+\treftable_buf_release(&path);\n \tclear_dir(dir);\n }\n \n@@ -1063,7 +1063,7 @@ static void t_reftable_stack_auto_compaction_with_locked_tables(void)\n \t\t.disable_auto_compact = 1,\n \t};\n \tstruct reftable_stack *st = NULL;\n-\tstruct strbuf buf = STRBUF_INIT;\n+\tstruct reftable_buf buf = REFTABLE_BUF_INIT;\n \tchar *dir = get_tmp_dir(__LINE__);\n \tint err;\n \n@@ -1078,10 +1078,10 @@ static void t_reftable_stack_auto_compaction_with_locked_tables(void)\n \t * size, we expect that auto-compaction will want to compact all of the\n \t * tables. Locking any of the tables will keep it from doing so.\n \t */\n-\tstrbuf_addstr(&buf, dir);\n-\tstrbuf_addstr(&buf, \"/\");\n-\tstrbuf_addstr(&buf, st->readers[2]->name);\n-\tstrbuf_addstr(&buf, \".lock\");\n+\treftable_buf_addstr(&buf, dir);\n+\treftable_buf_addstr(&buf, \"/\");\n+\treftable_buf_addstr(&buf, st->readers[2]->name);\n+\treftable_buf_addstr(&buf, \".lock\");\n \twrite_file_buf(buf.buf, \"\", 0);\n \n \t/*\n@@ -1096,7 +1096,7 @@ static void t_reftable_stack_auto_compaction_with_locked_tables(void)\n \tcheck_int(st->merged->readers_len, ==, 4);\n \n \treftable_stack_destroy(st);\n-\tstrbuf_release(&buf);\n+\treftable_buf_release(&buf);\n \tclear_dir(dir);\n }\n \n@@ -1153,7 +1153,7 @@ static void t_reftable_stack_compaction_with_locked_tables(void)\n \t\t.disable_auto_compact = 1,\n \t};\n \tstruct reftable_stack *st = NULL;\n-\tstruct strbuf buf = STRBUF_INIT;\n+\tstruct reftable_buf buf = REFTABLE_BUF_INIT;\n \tchar *dir = get_tmp_dir(__LINE__);\n \tint err;\n \n@@ -1164,10 +1164,10 @@ static void t_reftable_stack_compaction_with_locked_tables(void)\n \tcheck_int(st->merged->readers_len, ==, 3);\n \n \t/* Lock one of the tables that we're about to compact. */\n-\tstrbuf_addstr(&buf, dir);\n-\tstrbuf_addstr(&buf, \"/\");\n-\tstrbuf_addstr(&buf, st->readers[1]->name);\n-\tstrbuf_addstr(&buf, \".lock\");\n+\treftable_buf_addstr(&buf, dir);\n+\treftable_buf_addstr(&buf, \"/\");\n+\treftable_buf_addstr(&buf, st->readers[1]->name);\n+\treftable_buf_addstr(&buf, \".lock\");\n \twrite_file_buf(buf.buf, \"\", 0);\n \n \t/*\n@@ -1180,7 +1180,7 @@ static void t_reftable_stack_compaction_with_locked_tables(void)\n \tcheck_int(st->merged->readers_len, ==, 3);\n \n \treftable_stack_destroy(st);\n-\tstrbuf_release(&buf);\n+\treftable_buf_release(&buf);\n \tclear_dir(dir);\n }\n \n@@ -1306,7 +1306,7 @@ static void t_reftable_stack_reload_with_missing_table(void)\n \tstruct reftable_stack *st = NULL;\n \tstruct reftable_ref_record rec = { 0 };\n \tstruct reftable_iterator it = { 0 };\n-\tstruct strbuf table_path = STRBUF_INIT, content = STRBUF_INIT;\n+\tstruct reftable_buf table_path = REFTABLE_BUF_INIT, content = REFTABLE_BUF_INIT;\n \tchar *dir = get_tmp_dir(__LINE__);\n \tint err;\n \n@@ -1324,13 +1324,13 @@ static void t_reftable_stack_reload_with_missing_table(void)\n \t * our old readers. This should trigger a partial reload of the stack,\n \t * where we try to reuse our old readers.\n \t*/\n-\tstrbuf_addstr(&content, st->readers[0]->name);\n-\tstrbuf_addstr(&content, \"\\n\");\n-\tstrbuf_addstr(&content, st->readers[1]->name);\n-\tstrbuf_addstr(&content, \"\\n\");\n-\tstrbuf_addstr(&content, \"garbage\\n\");\n-\tstrbuf_addstr(&table_path, st->list_file);\n-\tstrbuf_addstr(&table_path, \".lock\");\n+\treftable_buf_addstr(&content, st->readers[0]->name);\n+\treftable_buf_addstr(&content, \"\\n\");\n+\treftable_buf_addstr(&content, st->readers[1]->name);\n+\treftable_buf_addstr(&content, \"\\n\");\n+\treftable_buf_addstr(&content, \"garbage\\n\");\n+\treftable_buf_addstr(&table_path, st->list_file);\n+\treftable_buf_addstr(&table_path, \".lock\");\n \twrite_file_buf(table_path.buf, content.buf, content.len);\n \terr = rename(table_path.buf, st->list_file);\n \tcheck(!err);\n@@ -1355,8 +1355,8 @@ static void t_reftable_stack_reload_with_missing_table(void)\n \treftable_ref_record_release(&rec);\n \treftable_iterator_destroy(&it);\n \treftable_stack_destroy(st);\n-\tstrbuf_release(&table_path);\n-\tstrbuf_release(&content);\n+\treftable_buf_release(&table_path);\n+\treftable_buf_release(&content);\n \tclear_dir(dir);\n }\n \n-- \n2.47.0.dirty\n\n"},{"id":"505003","messageId":"fe8c9ace4633ba5609741f657a7bb298e9f0dedd.1728910727.git.ps@pks.im","threadId":"62313","inReplyTo":"cover.1728910726.git.ps@pks.im","subject":"[PATCH v2 05/10] reftable/blocksource: adapt interface name","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-10-14T13:02:29Z","receivedAt":"2024-10-14T13:02:36Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"Adapt the name of the `strbuf` block source to no longer relate to this\ninterface, but instead to the `reftable_buf` interface.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n reftable/blocksource.c              | 26 +++++++++++++-------------\n reftable/blocksource.h              |  4 ++--\n t/unit-tests/t-reftable-block.c     |  8 ++++----\n t/unit-tests/t-reftable-merged.c    |  6 +++---\n t/unit-tests/t-reftable-reader.c    |  4 ++--\n t/unit-tests/t-reftable-readwrite.c | 24 ++++++++++++------------\n 6 files changed, 36 insertions(+), 36 deletions(-)\n\ndiff --git a/reftable/blocksource.c b/reftable/blocksource.c\nindex d6242d67900..52e0915a67b 100644\n--- a/reftable/blocksource.c\n+++ b/reftable/blocksource.c\n@@ -13,19 +13,19 @@ license that can be found in the LICENSE file or at\n #include \"reftable-blocksource.h\"\n #include \"reftable-error.h\"\n \n-static void strbuf_return_block(void *b UNUSED, struct reftable_block *dest)\n+static void reftable_buf_return_block(void *b UNUSED, struct reftable_block *dest)\n {\n \tif (dest->len)\n \t\tmemset(dest->data, 0xff, dest->len);\n \treftable_free(dest->data);\n }\n \n-static void strbuf_close(void *b UNUSED)\n+static void reftable_buf_close(void *b UNUSED)\n {\n }\n \n-static int strbuf_read_block(void *v, struct reftable_block *dest, uint64_t off,\n-\t\t\t     uint32_t size)\n+static int reftable_buf_read_block(void *v, struct reftable_block *dest,\n+\t\t\t\t   uint64_t off, uint32_t size)\n {\n \tstruct reftable_buf *b = v;\n \tassert(off + size <= b->len);\n@@ -37,23 +37,23 @@ static int strbuf_read_block(void *v, struct reftable_block *dest, uint64_t off,\n \treturn size;\n }\n \n-static uint64_t strbuf_size(void *b)\n+static uint64_t reftable_buf_size(void *b)\n {\n \treturn ((struct reftable_buf *)b)->len;\n }\n \n-static struct reftable_block_source_vtable strbuf_vtable = {\n-\t.size = &strbuf_size,\n-\t.read_block = &strbuf_read_block,\n-\t.return_block = &strbuf_return_block,\n-\t.close = &strbuf_close,\n+static struct reftable_block_source_vtable reftable_buf_vtable = {\n+\t.size = &reftable_buf_size,\n+\t.read_block = &reftable_buf_read_block,\n+\t.return_block = &reftable_buf_return_block,\n+\t.close = &reftable_buf_close,\n };\n \n-void block_source_from_strbuf(struct reftable_block_source *bs,\n-\t\t\t      struct reftable_buf *buf)\n+void block_source_from_buf(struct reftable_block_source *bs,\n+\t\t\t   struct reftable_buf *buf)\n {\n \tassert(!bs->ops);\n-\tbs->ops = &strbuf_vtable;\n+\tbs->ops = &reftable_buf_vtable;\n \tbs->arg = buf;\n }\n \ndiff --git a/reftable/blocksource.h b/reftable/blocksource.h\nindex ee3647c6531..a84a3ccd891 100644\n--- a/reftable/blocksource.h\n+++ b/reftable/blocksource.h\n@@ -15,7 +15,7 @@ struct reftable_block_source;\n struct reftable_buf;\n \n /* Create an in-memory block source for reading reftables */\n-void block_source_from_strbuf(struct reftable_block_source *bs,\n-\t\t\t      struct reftable_buf *buf);\n+void block_source_from_buf(struct reftable_block_source *bs,\n+\t\t\t   struct reftable_buf *buf);\n \n #endif\ndiff --git a/t/unit-tests/t-reftable-block.c b/t/unit-tests/t-reftable-block.c\nindex 56514b43630..df1d45fe8e4 100644\n--- a/t/unit-tests/t-reftable-block.c\n+++ b/t/unit-tests/t-reftable-block.c\n@@ -34,7 +34,7 @@ static void t_ref_block_read_write(void)\n \tREFTABLE_CALLOC_ARRAY(block.data, block_size);\n \tcheck(block.data != NULL);\n \tblock.len = block_size;\n-\tblock_source_from_strbuf(&block.source ,&buf);\n+\tblock_source_from_buf(&block.source ,&buf);\n \tret = block_writer_init(&bw, BLOCK_TYPE_REF, block.data, block_size,\n \t\t\t\theader_off, hash_size(GIT_SHA1_FORMAT_ID));\n \tcheck(!ret);\n@@ -128,7 +128,7 @@ static void t_log_block_read_write(void)\n \tREFTABLE_CALLOC_ARRAY(block.data, block_size);\n \tcheck(block.data != NULL);\n \tblock.len = block_size;\n-\tblock_source_from_strbuf(&block.source ,&buf);\n+\tblock_source_from_buf(&block.source ,&buf);\n \tret = block_writer_init(&bw, BLOCK_TYPE_LOG, block.data, block_size,\n \t\t\t\theader_off, hash_size(GIT_SHA1_FORMAT_ID));\n \tcheck(!ret);\n@@ -218,7 +218,7 @@ static void t_obj_block_read_write(void)\n \tREFTABLE_CALLOC_ARRAY(block.data, block_size);\n \tcheck(block.data != NULL);\n \tblock.len = block_size;\n-\tblock_source_from_strbuf(&block.source, &buf);\n+\tblock_source_from_buf(&block.source, &buf);\n \tret = block_writer_init(&bw, BLOCK_TYPE_OBJ, block.data, block_size,\n \t\t\t\theader_off, hash_size(GIT_SHA1_FORMAT_ID));\n \tcheck(!ret);\n@@ -302,7 +302,7 @@ static void t_index_block_read_write(void)\n \tREFTABLE_CALLOC_ARRAY(block.data, block_size);\n \tcheck(block.data != NULL);\n \tblock.len = block_size;\n-\tblock_source_from_strbuf(&block.source, &buf);\n+\tblock_source_from_buf(&block.source, &buf);\n \tret = block_writer_init(&bw, BLOCK_TYPE_INDEX, block.data, block_size,\n \t\t\t\theader_off, hash_size(GIT_SHA1_FORMAT_ID));\n \tcheck(!ret);\ndiff --git a/t/unit-tests/t-reftable-merged.c b/t/unit-tests/t-reftable-merged.c\nindex 9b0162a4b32..484c18251f3 100644\n--- a/t/unit-tests/t-reftable-merged.c\n+++ b/t/unit-tests/t-reftable-merged.c\n@@ -35,7 +35,7 @@ merged_table_from_records(struct reftable_ref_record **refs,\n \n \tfor (size_t i = 0; i < n; i++) {\n \t\tt_reftable_write_to_buf(&buf[i], refs[i], sizes[i], NULL, 0, &opts);\n-\t\tblock_source_from_strbuf(&(*source)[i], &buf[i]);\n+\t\tblock_source_from_buf(&(*source)[i], &buf[i]);\n \n \t\terr = reftable_reader_new(&(*readers)[i], &(*source)[i],\n \t\t\t\t\t  \"name\");\n@@ -293,7 +293,7 @@ merged_table_from_log_records(struct reftable_log_record **logs,\n \n \tfor (size_t i = 0; i < n; i++) {\n \t\tt_reftable_write_to_buf(&buf[i], NULL, 0, logs[i], sizes[i], &opts);\n-\t\tblock_source_from_strbuf(&(*source)[i], &buf[i]);\n+\t\tblock_source_from_buf(&(*source)[i], &buf[i]);\n \n \t\terr = reftable_reader_new(&(*readers)[i], &(*source)[i],\n \t\t\t\t\t  \"name\");\n@@ -442,7 +442,7 @@ static void t_default_write_opts(void)\n \tcheck(!err);\n \treftable_writer_free(w);\n \n-\tblock_source_from_strbuf(&source, &buf);\n+\tblock_source_from_buf(&source, &buf);\n \n \terr = reftable_reader_new(&rd, &source, \"filename\");\n \tcheck(!err);\ndiff --git a/t/unit-tests/t-reftable-reader.c b/t/unit-tests/t-reftable-reader.c\nindex 8a18d7f9be4..19cb53b6415 100644\n--- a/t/unit-tests/t-reftable-reader.c\n+++ b/t/unit-tests/t-reftable-reader.c\n@@ -20,7 +20,7 @@ static int t_reader_seek_once(void)\n \tint ret;\n \n \tt_reftable_write_to_buf(&buf, records, ARRAY_SIZE(records), NULL, 0, NULL);\n-\tblock_source_from_strbuf(&source, &buf);\n+\tblock_source_from_buf(&source, &buf);\n \n \tret = reftable_reader_new(&reader, &source, \"name\");\n \tcheck(!ret);\n@@ -61,7 +61,7 @@ static int t_reader_reseek(void)\n \tint ret;\n \n \tt_reftable_write_to_buf(&buf, records, ARRAY_SIZE(records), NULL, 0, NULL);\n-\tblock_source_from_strbuf(&source, &buf);\n+\tblock_source_from_buf(&source, &buf);\n \n \tret = reftable_reader_new(&reader, &source, \"name\");\n \tcheck(!ret);\ndiff --git a/t/unit-tests/t-reftable-readwrite.c b/t/unit-tests/t-reftable-readwrite.c\nindex c56a33f1a1e..7c7c72bb162 100644\n--- a/t/unit-tests/t-reftable-readwrite.c\n+++ b/t/unit-tests/t-reftable-readwrite.c\n@@ -24,7 +24,7 @@ static void t_buffer(void)\n \tint n;\n \tuint8_t in[] = \"hello\";\n \treftable_buf_add(&buf, in, sizeof(in));\n-\tblock_source_from_strbuf(&source, &buf);\n+\tblock_source_from_buf(&source, &buf);\n \tcheck_int(block_source_size(&source), ==, 6);\n \tn = block_source_read_block(&source, &out, 0, sizeof(in));\n \tcheck_int(n, ==, sizeof(in));\n@@ -207,7 +207,7 @@ static void t_log_write_read(void)\n \treftable_writer_free(w);\n \tw = NULL;\n \n-\tblock_source_from_strbuf(&source, &buf);\n+\tblock_source_from_buf(&source, &buf);\n \n \terr = reftable_reader_new(&reader, &source, \"file.log\");\n \tcheck(!err);\n@@ -298,7 +298,7 @@ static void t_log_zlib_corruption(void)\n \t/* corrupt the data. */\n \tbuf.buf[50] ^= 0x99;\n \n-\tblock_source_from_strbuf(&source, &buf);\n+\tblock_source_from_buf(&source, &buf);\n \n \terr = reftable_reader_new(&reader, &source, \"file.log\");\n \tcheck(!err);\n@@ -328,7 +328,7 @@ static void t_table_read_write_sequential(void)\n \n \twrite_table(&names, &buf, N, 256, GIT_SHA1_FORMAT_ID);\n \n-\tblock_source_from_strbuf(&source, &buf);\n+\tblock_source_from_buf(&source, &buf);\n \n \terr = reftable_reader_new(&reader, &source, \"file.ref\");\n \tcheck(!err);\n@@ -380,7 +380,7 @@ static void t_table_read_api(void)\n \n \twrite_table(&names, &buf, N, 256, GIT_SHA1_FORMAT_ID);\n \n-\tblock_source_from_strbuf(&source, &buf);\n+\tblock_source_from_buf(&source, &buf);\n \n \terr = reftable_reader_new(&reader, &source, \"file.ref\");\n \tcheck(!err);\n@@ -416,7 +416,7 @@ static void t_table_read_write_seek(int index, int hash_id)\n \n \twrite_table(&names, &buf, N, 256, hash_id);\n \n-\tblock_source_from_strbuf(&source, &buf);\n+\tblock_source_from_buf(&source, &buf);\n \n \terr = reftable_reader_new(&reader, &source, \"file.ref\");\n \tcheck(!err);\n@@ -538,7 +538,7 @@ static void t_table_refs_for(int indexed)\n \treftable_writer_free(w);\n \tw = NULL;\n \n-\tblock_source_from_strbuf(&source, &buf);\n+\tblock_source_from_buf(&source, &buf);\n \n \terr = reftable_reader_new(&reader, &source, \"file.ref\");\n \tcheck(!err);\n@@ -600,7 +600,7 @@ static void t_write_empty_table(void)\n \n \tcheck_int(buf.len, ==, header_size(1) + footer_size(1));\n \n-\tblock_source_from_strbuf(&source, &buf);\n+\tblock_source_from_buf(&source, &buf);\n \n \terr = reftable_reader_new(&rd, &source, \"filename\");\n \tcheck(!err);\n@@ -806,7 +806,7 @@ static void t_write_multiple_indices(void)\n \tcheck_int(stats->obj_stats.index_offset, >, 0);\n \tcheck_int(stats->log_stats.index_offset, >, 0);\n \n-\tblock_source_from_strbuf(&source, &writer_buf);\n+\tblock_source_from_buf(&source, &writer_buf);\n \terr = reftable_reader_new(&reader, &source, \"filename\");\n \tcheck(!err);\n \n@@ -863,7 +863,7 @@ static void t_write_multi_level_index(void)\n \tstats = reftable_writer_stats(writer);\n \tcheck_int(stats->ref_stats.max_index_level, ==, 2);\n \n-\tblock_source_from_strbuf(&source, &writer_buf);\n+\tblock_source_from_buf(&source, &writer_buf);\n \terr = reftable_reader_new(&reader, &source, \"filename\");\n \tcheck(!err);\n \n@@ -889,7 +889,7 @@ static void t_corrupt_table_empty(void)\n \tstruct reftable_reader *reader;\n \tint err;\n \n-\tblock_source_from_strbuf(&source, &buf);\n+\tblock_source_from_buf(&source, &buf);\n \terr = reftable_reader_new(&reader, &source, \"file.log\");\n \tcheck_int(err, ==, REFTABLE_FORMAT_ERROR);\n }\n@@ -903,7 +903,7 @@ static void t_corrupt_table(void)\n \tint err;\n \treftable_buf_add(&buf, zeros, sizeof(zeros));\n \n-\tblock_source_from_strbuf(&source, &buf);\n+\tblock_source_from_buf(&source, &buf);\n \terr = reftable_reader_new(&reader, &source, \"file.log\");\n \tcheck_int(err, ==, REFTABLE_FORMAT_ERROR);\n \n-- \n2.47.0.dirty\n\n"},{"id":"505005","messageId":"8c98745233a930ea5cacca5309044f53f09a171b.1728910727.git.ps@pks.im","threadId":"62313","inReplyTo":"cover.1728910726.git.ps@pks.im","subject":"[PATCH v2 06/10] t/unit-tests: check for `reftable_buf` allocation errors","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-10-14T13:02:34Z","receivedAt":"2024-10-14T13:02:38Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"Adapt our unit tests to check for allocations errors.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n t/unit-tests/t-reftable-basics.c    |  4 +-\n t/unit-tests/t-reftable-block.c     |  4 +-\n t/unit-tests/t-reftable-readwrite.c |  8 ++--\n t/unit-tests/t-reftable-record.c    | 14 +++----\n t/unit-tests/t-reftable-stack.c     | 58 ++++++++++++++---------------\n 5 files changed, 44 insertions(+), 44 deletions(-)\n\ndiff --git a/t/unit-tests/t-reftable-basics.c b/t/unit-tests/t-reftable-basics.c\nindex a814e819756..a329f552025 100644\n--- a/t/unit-tests/t-reftable-basics.c\n+++ b/t/unit-tests/t-reftable-basics.c\n@@ -113,8 +113,8 @@ int cmd_main(int argc UNUSED, const char *argv[] UNUSED)\n \t\t};\n \n \t\tfor (size_t i = 0; i < ARRAY_SIZE(cases); i++) {\n-\t\t\treftable_buf_addstr(&a, cases[i].a);\n-\t\t\treftable_buf_addstr(&b, cases[i].b);\n+\t\t\tcheck(!reftable_buf_addstr(&a, cases[i].a));\n+\t\t\tcheck(!reftable_buf_addstr(&b, cases[i].b));\n \t\t\tcheck_int(common_prefix_size(&a, &b), ==, cases[i].want);\n \t\t\treftable_buf_reset(&a);\n \t\t\treftable_buf_reset(&b);\ndiff --git a/t/unit-tests/t-reftable-block.c b/t/unit-tests/t-reftable-block.c\nindex df1d45fe8e4..f9af907117b 100644\n--- a/t/unit-tests/t-reftable-block.c\n+++ b/t/unit-tests/t-reftable-block.c\n@@ -167,7 +167,7 @@ static void t_log_block_read_write(void)\n \tfor (i = 0; i < N; i++) {\n \t\tblock_iter_reset(&it);\n \t\treftable_buf_reset(&want);\n-\t\treftable_buf_addstr(&want, recs[i].u.log.refname);\n+\t\tcheck(!reftable_buf_addstr(&want, recs[i].u.log.refname));\n \n \t\tret = block_iter_seek_key(&it, &br, &want);\n \t\tcheck_int(ret, ==, 0);\n@@ -314,7 +314,7 @@ static void t_index_block_read_write(void)\n \n \t\treftable_buf_init(&recs[i].u.idx.last_key);\n \t\trecs[i].type = BLOCK_TYPE_INDEX;\n-\t\treftable_buf_addstr(&recs[i].u.idx.last_key, buf);\n+\t\tcheck(!reftable_buf_addstr(&recs[i].u.idx.last_key, buf));\n \t\trecs[i].u.idx.offset = i;\n \n \t\tret = block_writer_add(&bw, &recs[i]);\ndiff --git a/t/unit-tests/t-reftable-readwrite.c b/t/unit-tests/t-reftable-readwrite.c\nindex 7c7c72bb162..d279b86df0a 100644\n--- a/t/unit-tests/t-reftable-readwrite.c\n+++ b/t/unit-tests/t-reftable-readwrite.c\n@@ -23,7 +23,7 @@ static void t_buffer(void)\n \tstruct reftable_block out = { 0 };\n \tint n;\n \tuint8_t in[] = \"hello\";\n-\treftable_buf_add(&buf, in, sizeof(in));\n+\tcheck(!reftable_buf_add(&buf, in, sizeof(in)));\n \tblock_source_from_buf(&source, &buf);\n \tcheck_int(block_source_size(&source), ==, 6);\n \tn = block_source_read_block(&source, &out, 0, sizeof(in));\n@@ -443,8 +443,8 @@ static void t_table_read_write_seek(int index, int hash_id)\n \t\treftable_iterator_destroy(&it);\n \t}\n \n-\treftable_buf_addstr(&pastLast, names[N - 1]);\n-\treftable_buf_addstr(&pastLast, \"/\");\n+\tcheck(!reftable_buf_addstr(&pastLast, names[N - 1]));\n+\tcheck(!reftable_buf_addstr(&pastLast, \"/\"));\n \n \terr = reftable_reader_init_ref_iterator(reader, &it);\n \tcheck(!err);\n@@ -901,7 +901,7 @@ static void t_corrupt_table(void)\n \tstruct reftable_block_source source = { 0 };\n \tstruct reftable_reader *reader;\n \tint err;\n-\treftable_buf_add(&buf, zeros, sizeof(zeros));\n+\tcheck(!reftable_buf_add(&buf, zeros, sizeof(zeros)));\n \n \tblock_source_from_buf(&source, &buf);\n \terr = reftable_reader_new(&reader, &source, \"file.log\");\ndiff --git a/t/unit-tests/t-reftable-record.c b/t/unit-tests/t-reftable-record.c\nindex f2dd01688f3..eb98bf2da91 100644\n--- a/t/unit-tests/t-reftable-record.c\n+++ b/t/unit-tests/t-reftable-record.c\n@@ -335,14 +335,14 @@ static void t_key_roundtrip(void)\n \tint n, m;\n \tuint8_t rt_extra;\n \n-\treftable_buf_addstr(&last_key, \"refs/heads/master\");\n-\treftable_buf_addstr(&key, \"refs/tags/bla\");\n+\tcheck(!reftable_buf_addstr(&last_key, \"refs/heads/master\"));\n+\tcheck(!reftable_buf_addstr(&key, \"refs/tags/bla\"));\n \textra = 6;\n \tn = reftable_encode_key(&restart, dest, last_key, key, extra);\n \tcheck(!restart);\n \tcheck_int(n, >, 0);\n \n-\treftable_buf_addstr(&roundtrip, \"refs/heads/master\");\n+\tcheck(!reftable_buf_addstr(&roundtrip, \"refs/heads/master\"));\n \tm = reftable_decode_key(&roundtrip, &rt_extra, dest);\n \tcheck_int(n, ==, m);\n \tcheck(!reftable_buf_cmp(&key, &roundtrip));\n@@ -469,9 +469,9 @@ static void t_reftable_index_record_comparison(void)\n \t\t\t.u.idx.last_key = REFTABLE_BUF_INIT,\n \t\t},\n \t};\n-\treftable_buf_addstr(&in[0].u.idx.last_key, \"refs/heads/master\");\n-\treftable_buf_addstr(&in[1].u.idx.last_key, \"refs/heads/master\");\n-\treftable_buf_addstr(&in[2].u.idx.last_key, \"refs/heads/branch\");\n+\tcheck(!reftable_buf_addstr(&in[0].u.idx.last_key, \"refs/heads/master\"));\n+\tcheck(!reftable_buf_addstr(&in[1].u.idx.last_key, \"refs/heads/master\"));\n+\tcheck(!reftable_buf_addstr(&in[2].u.idx.last_key, \"refs/heads/branch\"));\n \n \tcheck(!reftable_record_equal(&in[0], &in[1], GIT_SHA1_RAWSZ));\n \tcheck(!reftable_record_cmp(&in[0], &in[1]));\n@@ -510,7 +510,7 @@ static void t_reftable_index_record_roundtrip(void)\n \tint n, m;\n \tuint8_t extra;\n \n-\treftable_buf_addstr(&in.u.idx.last_key, \"refs/heads/master\");\n+\tcheck(!reftable_buf_addstr(&in.u.idx.last_key, \"refs/heads/master\"));\n \treftable_record_key(&in, &key);\n \tt_copy(&in);\n \ndiff --git a/t/unit-tests/t-reftable-stack.c b/t/unit-tests/t-reftable-stack.c\nindex f49856270d6..72f6747064f 100644\n--- a/t/unit-tests/t-reftable-stack.c\n+++ b/t/unit-tests/t-reftable-stack.c\n@@ -172,17 +172,17 @@ static void t_reftable_stack_add_one(void)\n \tcheck_int(st->readers_len, >, 0);\n \n #ifndef GIT_WINDOWS_NATIVE\n-\treftable_buf_addstr(&scratch, dir);\n-\treftable_buf_addstr(&scratch, \"/tables.list\");\n+\tcheck(!reftable_buf_addstr(&scratch, dir));\n+\tcheck(!reftable_buf_addstr(&scratch, \"/tables.list\"));\n \terr = stat(scratch.buf, &stat_result);\n \tcheck(!err);\n \tcheck_int((stat_result.st_mode & 0777), ==, opts.default_permissions);\n \n \treftable_buf_reset(&scratch);\n-\treftable_buf_addstr(&scratch, dir);\n-\treftable_buf_addstr(&scratch, \"/\");\n+\tcheck(!reftable_buf_addstr(&scratch, dir));\n+\tcheck(!reftable_buf_addstr(&scratch, \"/\"));\n \t/* do not try at home; not an external API for reftable. */\n-\treftable_buf_addstr(&scratch, st->readers[0]->name);\n+\tcheck(!reftable_buf_addstr(&scratch, st->readers[0]->name));\n \terr = stat(scratch.buf, &stat_result);\n \tcheck(!err);\n \tcheck_int((stat_result.st_mode & 0777), ==, opts.default_permissions);\n@@ -432,10 +432,10 @@ static void t_reftable_stack_auto_compaction_fails_gracefully(void)\n \t * Adding a new table to the stack should not be impacted by this, even\n \t * though auto-compaction will now fail.\n \t */\n-\treftable_buf_addstr(&table_path, dir);\n-\treftable_buf_addstr(&table_path, \"/\");\n-\treftable_buf_addstr(&table_path, st->readers[0]->name);\n-\treftable_buf_addstr(&table_path, \".lock\");\n+\tcheck(!reftable_buf_addstr(&table_path, dir));\n+\tcheck(!reftable_buf_addstr(&table_path, \"/\"));\n+\tcheck(!reftable_buf_addstr(&table_path, st->readers[0]->name));\n+\tcheck(!reftable_buf_addstr(&table_path, \".lock\"));\n \twrite_file_buf(table_path.buf, \"\", 0);\n \n \tref.update_index = 2;\n@@ -575,17 +575,17 @@ static void t_reftable_stack_add(void)\n \t}\n \n #ifndef GIT_WINDOWS_NATIVE\n-\treftable_buf_addstr(&path, dir);\n-\treftable_buf_addstr(&path, \"/tables.list\");\n+\tcheck(!reftable_buf_addstr(&path, dir));\n+\tcheck(!reftable_buf_addstr(&path, \"/tables.list\"));\n \terr = stat(path.buf, &stat_result);\n \tcheck(!err);\n \tcheck_int((stat_result.st_mode & 0777), ==, opts.default_permissions);\n \n \treftable_buf_reset(&path);\n-\treftable_buf_addstr(&path, dir);\n-\treftable_buf_addstr(&path, \"/\");\n+\tcheck(!reftable_buf_addstr(&path, dir));\n+\tcheck(!reftable_buf_addstr(&path, \"/\"));\n \t/* do not try at home; not an external API for reftable. */\n-\treftable_buf_addstr(&path, st->readers[0]->name);\n+\tcheck(!reftable_buf_addstr(&path, st->readers[0]->name));\n \terr = stat(path.buf, &stat_result);\n \tcheck(!err);\n \tcheck_int((stat_result.st_mode & 0777), ==, opts.default_permissions);\n@@ -1078,10 +1078,10 @@ static void t_reftable_stack_auto_compaction_with_locked_tables(void)\n \t * size, we expect that auto-compaction will want to compact all of the\n \t * tables. Locking any of the tables will keep it from doing so.\n \t */\n-\treftable_buf_addstr(&buf, dir);\n-\treftable_buf_addstr(&buf, \"/\");\n-\treftable_buf_addstr(&buf, st->readers[2]->name);\n-\treftable_buf_addstr(&buf, \".lock\");\n+\tcheck(!reftable_buf_addstr(&buf, dir));\n+\tcheck(!reftable_buf_addstr(&buf, \"/\"));\n+\tcheck(!reftable_buf_addstr(&buf, st->readers[2]->name));\n+\tcheck(!reftable_buf_addstr(&buf, \".lock\"));\n \twrite_file_buf(buf.buf, \"\", 0);\n \n \t/*\n@@ -1164,10 +1164,10 @@ static void t_reftable_stack_compaction_with_locked_tables(void)\n \tcheck_int(st->merged->readers_len, ==, 3);\n \n \t/* Lock one of the tables that we're about to compact. */\n-\treftable_buf_addstr(&buf, dir);\n-\treftable_buf_addstr(&buf, \"/\");\n-\treftable_buf_addstr(&buf, st->readers[1]->name);\n-\treftable_buf_addstr(&buf, \".lock\");\n+\tcheck(!reftable_buf_addstr(&buf, dir));\n+\tcheck(!reftable_buf_addstr(&buf, \"/\"));\n+\tcheck(!reftable_buf_addstr(&buf, st->readers[1]->name));\n+\tcheck(!reftable_buf_addstr(&buf, \".lock\"));\n \twrite_file_buf(buf.buf, \"\", 0);\n \n \t/*\n@@ -1324,13 +1324,13 @@ static void t_reftable_stack_reload_with_missing_table(void)\n \t * our old readers. This should trigger a partial reload of the stack,\n \t * where we try to reuse our old readers.\n \t*/\n-\treftable_buf_addstr(&content, st->readers[0]->name);\n-\treftable_buf_addstr(&content, \"\\n\");\n-\treftable_buf_addstr(&content, st->readers[1]->name);\n-\treftable_buf_addstr(&content, \"\\n\");\n-\treftable_buf_addstr(&content, \"garbage\\n\");\n-\treftable_buf_addstr(&table_path, st->list_file);\n-\treftable_buf_addstr(&table_path, \".lock\");\n+\tcheck(!reftable_buf_addstr(&content, st->readers[0]->name));\n+\tcheck(!reftable_buf_addstr(&content, \"\\n\"));\n+\tcheck(!reftable_buf_addstr(&content, st->readers[1]->name));\n+\tcheck(!reftable_buf_addstr(&content, \"\\n\"));\n+\tcheck(!reftable_buf_addstr(&content, \"garbage\\n\"));\n+\tcheck(!reftable_buf_addstr(&table_path, st->list_file));\n+\tcheck(!reftable_buf_addstr(&table_path, \".lock\"));\n \twrite_file_buf(table_path.buf, content.buf, content.len);\n \terr = rename(table_path.buf, st->list_file);\n \tcheck(!err);\n-- \n2.47.0.dirty\n\n"},{"id":"505006","messageId":"1f08163009b87596188165863b89b62c5f521e00.1728910727.git.ps@pks.im","threadId":"62313","inReplyTo":"cover.1728910726.git.ps@pks.im","subject":"[PATCH v2 07/10] reftable/stack: adapt `format_name()` to handle allocation failures","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-10-14T13:02:37Z","receivedAt":"2024-10-14T13:02:41Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"The `format_name()` function cannot pass any errors to the caller as it\nhas a `void` return type. Adapt it and its callers such that we can\nhandle errors and start handling allocation failures.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n reftable/stack.c | 28 +++++++++++++++++++---------\n 1 file changed, 19 insertions(+), 9 deletions(-)\n\ndiff --git a/reftable/stack.c b/reftable/stack.c\nindex 6ba48ddce5d..e94eb3c4685 100644\n--- a/reftable/stack.c\n+++ b/reftable/stack.c\n@@ -623,14 +623,14 @@ int reftable_stack_add(struct reftable_stack *st,\n \treturn 0;\n }\n \n-static void format_name(struct reftable_buf *dest, uint64_t min, uint64_t max)\n+static int format_name(struct reftable_buf *dest, uint64_t min, uint64_t max)\n {\n \tchar buf[100];\n \tuint32_t rnd = (uint32_t)git_rand();\n \tsnprintf(buf, sizeof(buf), \"0x%012\" PRIx64 \"-0x%012\" PRIx64 \"-%08x\",\n \t\t min, max, rnd);\n \treftable_buf_reset(dest);\n-\treftable_buf_addstr(dest, buf);\n+\treturn reftable_buf_addstr(dest, buf);\n }\n \n struct reftable_addition {\n@@ -846,7 +846,10 @@ int reftable_addition_add(struct reftable_addition *add,\n \tint tab_fd;\n \n \treftable_buf_reset(&next_name);\n-\tformat_name(&next_name, add->next_update_index, add->next_update_index);\n+\n+\terr = format_name(&next_name, add->next_update_index, add->next_update_index);\n+\tif (err < 0)\n+\t\tgoto done;\n \n \tstack_filename(&temp_tab_file_name, add->stack, next_name.buf);\n \treftable_buf_addstr(&temp_tab_file_name, \".temp.XXXXXX\");\n@@ -893,7 +896,9 @@ int reftable_addition_add(struct reftable_addition *add,\n \t\tgoto done;\n \t}\n \n-\tformat_name(&next_name, wr->min_update_index, wr->max_update_index);\n+\terr = format_name(&next_name, wr->min_update_index, wr->max_update_index);\n+\tif (err < 0)\n+\t\tgoto done;\n \treftable_buf_addstr(&next_name, \".ref\");\n \tstack_filename(&tab_file_name, add->stack, next_name.buf);\n \n@@ -944,9 +949,11 @@ static int stack_compact_locked(struct reftable_stack *st,\n \tstruct tempfile *tab_file;\n \tint tab_fd, err = 0;\n \n-\tformat_name(&next_name,\n-\t\t    reftable_reader_min_update_index(st->readers[first]),\n-\t\t    reftable_reader_max_update_index(st->readers[last]));\n+\terr = format_name(&next_name, reftable_reader_min_update_index(st->readers[first]),\n+\t\t\t  reftable_reader_max_update_index(st->readers[last]));\n+\tif (err < 0)\n+\t\tgoto done;\n+\n \tstack_filename(&tab_file_path, st, next_name.buf);\n \treftable_buf_addstr(&tab_file_path, \".temp.XXXXXX\");\n \n@@ -1370,8 +1377,11 @@ static int stack_compact_range(struct reftable_stack *st,\n \t * it into place now.\n \t */\n \tif (!is_empty_table) {\n-\t\tformat_name(&new_table_name, st->readers[first]->min_update_index,\n-\t\t\t    st->readers[last]->max_update_index);\n+\t\terr = format_name(&new_table_name, st->readers[first]->min_update_index,\n+\t\t\t\t  st->readers[last]->max_update_index);\n+\t\tif (err < 0)\n+\t\t\tgoto done;\n+\n \t\treftable_buf_addstr(&new_table_name, \".ref\");\n \t\tstack_filename(&new_table_path, st, new_table_name.buf);\n \n-- \n2.47.0.dirty\n\n"},{"id":"505007","messageId":"5798d76d7a4dca7aeda4737c47233b22c4583d9f.1728910727.git.ps@pks.im","threadId":"62313","inReplyTo":"cover.1728910726.git.ps@pks.im","subject":"[PATCH v2 08/10] reftable/record: adapt `reftable_record_key()` to handle allocation failures","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-10-14T13:02:40Z","receivedAt":"2024-10-14T13:02:43Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"The `reftable_record_key()` function cannot pass any errors to the\ncaller as it has a `void` return type. Adapt it and its callers such\nthat we can handle errors and start handling allocation failures.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n reftable/block.c  | 20 +++++++++++++++-----\n reftable/reader.c |  8 ++++++--\n reftable/record.c | 32 ++++++++++++++++++++------------\n reftable/record.h |  4 ++--\n reftable/writer.c |  5 ++++-\n 5 files changed, 47 insertions(+), 22 deletions(-)\n\ndiff --git a/reftable/block.c b/reftable/block.c\nindex 4f62b823db8..697b8b41531 100644\n--- a/reftable/block.c\n+++ b/reftable/block.c\n@@ -111,9 +111,12 @@ int block_writer_add(struct block_writer *w, struct reftable_record *rec)\n \tint is_restart = 0;\n \tstruct reftable_buf key = REFTABLE_BUF_INIT;\n \tint n = 0;\n-\tint err = -1;\n+\tint err;\n+\n+\terr = reftable_record_key(rec, &key);\n+\tif (err < 0)\n+\t\tgoto done;\n \n-\treftable_record_key(rec, &key);\n \tif (!key.len) {\n \t\terr = REFTABLE_API_ERROR;\n \t\tgoto done;\n@@ -121,13 +124,17 @@ int block_writer_add(struct block_writer *w, struct reftable_record *rec)\n \n \tn = reftable_encode_key(&is_restart, out, last, key,\n \t\t\t\treftable_record_val_type(rec));\n-\tif (n < 0)\n+\tif (n < 0) {\n+\t\terr = -1;\n \t\tgoto done;\n+\t}\n \tstring_view_consume(&out, n);\n \n \tn = reftable_record_encode(rec, out, w->hash_size);\n-\tif (n < 0)\n+\tif (n < 0) {\n+\t\terr = -1;\n \t\tgoto done;\n+\t}\n \tstring_view_consume(&out, n);\n \n \terr = block_writer_register_restart(w, start.len - out.len, is_restart,\n@@ -522,6 +529,10 @@ int block_iter_seek_key(struct block_iter *it, const struct block_reader *br,\n \t\t\tgoto done;\n \t\t}\n \n+\t\terr = reftable_record_key(&rec, &it->last_key);\n+\t\tif (err < 0)\n+\t\t\tgoto done;\n+\n \t\t/*\n \t\t * Check whether the current key is greater or equal to the\n \t\t * sought-after key. In case it is greater we know that the\n@@ -536,7 +547,6 @@ int block_iter_seek_key(struct block_iter *it, const struct block_reader *br,\n \t\t * to `last_key` now, and naturally all keys share a prefix\n \t\t * with themselves.\n \t\t */\n-\t\treftable_record_key(&rec, &it->last_key);\n \t\tif (reftable_buf_cmp(&it->last_key, want) >= 0) {\n \t\t\tit->next_off = prev_off;\n \t\t\tgoto done;\ndiff --git a/reftable/reader.c b/reftable/reader.c\nindex 388f8bf6d7b..ab89efd9c55 100644\n--- a/reftable/reader.c\n+++ b/reftable/reader.c\n@@ -356,7 +356,9 @@ static int table_iter_seek_linear(struct table_iter *ti,\n \tint err;\n \n \treftable_record_init(&rec, reftable_record_type(want));\n-\treftable_record_key(want, &want_key);\n+\terr = reftable_record_key(want, &want_key);\n+\tif (err < 0)\n+\t\tgoto done;\n \n \t/*\n \t * First we need to locate the block that must contain our record. To\n@@ -439,7 +441,9 @@ static int table_iter_seek_indexed(struct table_iter *ti,\n \t};\n \tint err;\n \n-\treftable_record_key(rec, &want_index.u.idx.last_key);\n+\terr = reftable_record_key(rec, &want_index.u.idx.last_key);\n+\tif (err < 0)\n+\t\tgoto done;\n \n \t/*\n \t * The index may consist of multiple levels, where each level may have\ndiff --git a/reftable/record.c b/reftable/record.c\nindex 0182c973437..672c5f909a9 100644\n--- a/reftable/record.c\n+++ b/reftable/record.c\n@@ -207,12 +207,12 @@ int reftable_decode_key(struct reftable_buf *last_key, uint8_t *extra,\n \treturn start_len - in.len;\n }\n \n-static void reftable_ref_record_key(const void *r, struct reftable_buf *dest)\n+static int reftable_ref_record_key(const void *r, struct reftable_buf *dest)\n {\n \tconst struct reftable_ref_record *rec =\n \t\t(const struct reftable_ref_record *)r;\n \treftable_buf_reset(dest);\n-\treftable_buf_addstr(dest, rec->refname);\n+\treturn reftable_buf_addstr(dest, rec->refname);\n }\n \n static int reftable_ref_record_copy_from(void *rec, const void *src_rec,\n@@ -465,12 +465,12 @@ static struct reftable_record_vtable reftable_ref_record_vtable = {\n \t.cmp = &reftable_ref_record_cmp_void,\n };\n \n-static void reftable_obj_record_key(const void *r, struct reftable_buf *dest)\n+static int reftable_obj_record_key(const void *r, struct reftable_buf *dest)\n {\n \tconst struct reftable_obj_record *rec =\n \t\t(const struct reftable_obj_record *)r;\n \treftable_buf_reset(dest);\n-\treftable_buf_add(dest, rec->hash_prefix, rec->hash_prefix_len);\n+\treturn reftable_buf_add(dest, rec->hash_prefix, rec->hash_prefix_len);\n }\n \n static void reftable_obj_record_release(void *rec)\n@@ -664,19 +664,27 @@ static struct reftable_record_vtable reftable_obj_record_vtable = {\n \t.cmp = &reftable_obj_record_cmp_void,\n };\n \n-static void reftable_log_record_key(const void *r, struct reftable_buf *dest)\n+static int reftable_log_record_key(const void *r, struct reftable_buf *dest)\n {\n \tconst struct reftable_log_record *rec =\n \t\t(const struct reftable_log_record *)r;\n-\tint len = strlen(rec->refname);\n+\tint len = strlen(rec->refname), err;\n \tuint8_t i64[8];\n \tuint64_t ts = 0;\n+\n \treftable_buf_reset(dest);\n-\treftable_buf_add(dest, (uint8_t *)rec->refname, len + 1);\n+\terr = reftable_buf_add(dest, (uint8_t *)rec->refname, len + 1);\n+\tif (err < 0)\n+\t\treturn err;\n \n \tts = (~ts) - rec->update_index;\n \tput_be64(&i64[0], ts);\n-\treftable_buf_add(dest, i64, sizeof(i64));\n+\n+\terr = reftable_buf_add(dest, i64, sizeof(i64));\n+\tif (err < 0)\n+\t\treturn err;\n+\n+\treturn 0;\n }\n \n static int reftable_log_record_copy_from(void *rec, const void *src_rec,\n@@ -1027,11 +1035,11 @@ static struct reftable_record_vtable reftable_log_record_vtable = {\n \t.cmp = &reftable_log_record_cmp_void,\n };\n \n-static void reftable_index_record_key(const void *r, struct reftable_buf *dest)\n+static int reftable_index_record_key(const void *r, struct reftable_buf *dest)\n {\n \tconst struct reftable_index_record *rec = r;\n \treftable_buf_reset(dest);\n-\treftable_buf_add(dest, rec->last_key.buf, rec->last_key.len);\n+\treturn reftable_buf_add(dest, rec->last_key.buf, rec->last_key.len);\n }\n \n static int reftable_index_record_copy_from(void *rec, const void *src_rec,\n@@ -1124,9 +1132,9 @@ static struct reftable_record_vtable reftable_index_record_vtable = {\n \t.cmp = &reftable_index_record_cmp,\n };\n \n-void reftable_record_key(struct reftable_record *rec, struct reftable_buf *dest)\n+int reftable_record_key(struct reftable_record *rec, struct reftable_buf *dest)\n {\n-\treftable_record_vtable(rec)->key(reftable_record_data(rec), dest);\n+\treturn reftable_record_vtable(rec)->key(reftable_record_data(rec), dest);\n }\n \n int reftable_record_encode(struct reftable_record *rec, struct string_view dest,\ndiff --git a/reftable/record.h b/reftable/record.h\nindex 271da3bf360..25aa908c859 100644\n--- a/reftable/record.h\n+++ b/reftable/record.h\n@@ -40,7 +40,7 @@ int put_var_int(struct string_view *dest, uint64_t val);\n /* Methods for records. */\n struct reftable_record_vtable {\n \t/* encode the key of to a uint8_t reftable_buf. */\n-\tvoid (*key)(const void *rec, struct reftable_buf *dest);\n+\tint (*key)(const void *rec, struct reftable_buf *dest);\n \n \t/* The record type of ('r' for ref). */\n \tuint8_t type;\n@@ -137,7 +137,7 @@ void reftable_record_init(struct reftable_record *rec, uint8_t typ);\n /* see struct record_vtable */\n int reftable_record_cmp(struct reftable_record *a, struct reftable_record *b);\n int reftable_record_equal(struct reftable_record *a, struct reftable_record *b, int hash_size);\n-void reftable_record_key(struct reftable_record *rec, struct reftable_buf *dest);\n+int reftable_record_key(struct reftable_record *rec, struct reftable_buf *dest);\n int reftable_record_copy_from(struct reftable_record *rec,\n \t\t\t      struct reftable_record *src, int hash_size);\n uint8_t reftable_record_val_type(struct reftable_record *rec);\ndiff --git a/reftable/writer.c b/reftable/writer.c\nindex da6941a78ac..377db709c85 100644\n--- a/reftable/writer.c\n+++ b/reftable/writer.c\n@@ -249,7 +249,10 @@ static int writer_add_record(struct reftable_writer *w,\n \tstruct reftable_buf key = REFTABLE_BUF_INIT;\n \tint err;\n \n-\treftable_record_key(rec, &key);\n+\terr = reftable_record_key(rec, &key);\n+\tif (err < 0)\n+\t\tgoto done;\n+\n \tif (reftable_buf_cmp(&w->last_key, &key) >= 0) {\n \t\terr = REFTABLE_API_ERROR;\n \t\tgoto done;\n-- \n2.47.0.dirty\n\n"},{"id":"505008","messageId":"a9582d51dd1dc0a650f594de81e992a244f311a9.1728910727.git.ps@pks.im","threadId":"62313","inReplyTo":"cover.1728910726.git.ps@pks.im","subject":"[PATCH v2 09/10] reftable/stack: adapt `stack_filename()` to handle allocation failures","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-10-14T13:02:43Z","receivedAt":"2024-10-14T13:02:47Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"The `stack_filename()` function cannot pass any errors to the caller as it\nhas a `void` return type. Adapt it and its callers such that we can\nhandle errors and start handling allocation failures.\n\nThere are two interesting edge cases in `reftable_stack_destroy()` and\n`reftable_addition_close()`. Both of these are trying to tear down their\nrespective structures, and while doing so they try to unlink some of the\ntables they have been keeping alive. Any earlier attempts to do that may\nfail on Windows because it keeps us from deleting such tables while they\nare still open, and thus we re-try on close. It's okay and even expected\nthat this can fail when the tables are still open by another process, so\nwe handle the allocation failures gracefully and just skip over any file\nwhose name we couldn't figure out.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n reftable/stack.c | 62 +++++++++++++++++++++++++++++++++++-------------\n 1 file changed, 45 insertions(+), 17 deletions(-)\n\ndiff --git a/reftable/stack.c b/reftable/stack.c\nindex e94eb3c4685..243b10715cc 100644\n--- a/reftable/stack.c\n+++ b/reftable/stack.c\n@@ -31,13 +31,16 @@ static void reftable_addition_close(struct reftable_addition *add);\n static int reftable_stack_reload_maybe_reuse(struct reftable_stack *st,\n \t\t\t\t\t     int reuse_open);\n \n-static void stack_filename(struct reftable_buf *dest, struct reftable_stack *st,\n-\t\t\t   const char *name)\n+static int stack_filename(struct reftable_buf *dest, struct reftable_stack *st,\n+\t\t\t  const char *name)\n {\n+\tint err;\n \treftable_buf_reset(dest);\n-\treftable_buf_addstr(dest, st->reftable_dir);\n-\treftable_buf_addstr(dest, \"/\");\n-\treftable_buf_addstr(dest, name);\n+\tif ((err = reftable_buf_addstr(dest, st->reftable_dir)) < 0 ||\n+\t    (err = reftable_buf_addstr(dest, \"/\")) < 0 ||\n+\t    (err = reftable_buf_addstr(dest, name)) < 0)\n+\t\treturn err;\n+\treturn 0;\n }\n \n static ssize_t reftable_fd_write(void *arg, const void *data, size_t sz)\n@@ -211,13 +214,16 @@ void reftable_stack_destroy(struct reftable_stack *st)\n \t\tstruct reftable_buf filename = REFTABLE_BUF_INIT;\n \t\tfor (i = 0; i < st->readers_len; i++) {\n \t\t\tconst char *name = reader_name(st->readers[i]);\n+\t\t\tint try_unlinking = 1;\n+\n \t\t\treftable_buf_reset(&filename);\n \t\t\tif (names && !has_name(names, name)) {\n-\t\t\t\tstack_filename(&filename, st, name);\n+\t\t\t\tif (stack_filename(&filename, st, name) < 0)\n+\t\t\t\t\ttry_unlinking = 0;\n \t\t\t}\n \t\t\treftable_reader_decref(st->readers[i]);\n \n-\t\t\tif (filename.len) {\n+\t\t\tif (try_unlinking && filename.len) {\n \t\t\t\t/* On Windows, can only unlink after closing. */\n \t\t\t\tunlink(filename.buf);\n \t\t\t}\n@@ -310,7 +316,10 @@ static int reftable_stack_reload_once(struct reftable_stack *st,\n \n \t\tif (!rd) {\n \t\t\tstruct reftable_block_source src = { NULL };\n-\t\t\tstack_filename(&table_path, st, name);\n+\n+\t\t\terr = stack_filename(&table_path, st, name);\n+\t\t\tif (err < 0)\n+\t\t\t\tgoto done;\n \n \t\t\terr = reftable_block_source_from_file(&src,\n \t\t\t\t\t\t\t      table_path.buf);\n@@ -341,7 +350,11 @@ static int reftable_stack_reload_once(struct reftable_stack *st,\n \tfor (i = 0; i < cur_len; i++) {\n \t\tif (cur[i]) {\n \t\t\tconst char *name = reader_name(cur[i]);\n-\t\t\tstack_filename(&table_path, st, name);\n+\n+\t\t\terr = stack_filename(&table_path, st, name);\n+\t\t\tif (err < 0)\n+\t\t\t\tgoto done;\n+\n \t\t\treftable_reader_decref(cur[i]);\n \t\t\tunlink(table_path.buf);\n \t\t}\n@@ -700,8 +713,8 @@ static void reftable_addition_close(struct reftable_addition *add)\n \tsize_t i;\n \n \tfor (i = 0; i < add->new_tables_len; i++) {\n-\t\tstack_filename(&nm, add->stack, add->new_tables[i]);\n-\t\tunlink(nm.buf);\n+\t\tif (!stack_filename(&nm, add->stack, add->new_tables[i]))\n+\t\t\tunlink(nm.buf);\n \t\treftable_free(add->new_tables[i]);\n \t\tadd->new_tables[i] = NULL;\n \t}\n@@ -851,7 +864,9 @@ int reftable_addition_add(struct reftable_addition *add,\n \tif (err < 0)\n \t\tgoto done;\n \n-\tstack_filename(&temp_tab_file_name, add->stack, next_name.buf);\n+\terr = stack_filename(&temp_tab_file_name, add->stack, next_name.buf);\n+\tif (err < 0)\n+\t\tgoto done;\n \treftable_buf_addstr(&temp_tab_file_name, \".temp.XXXXXX\");\n \n \ttab_file = mks_tempfile(temp_tab_file_name.buf);\n@@ -900,7 +915,10 @@ int reftable_addition_add(struct reftable_addition *add,\n \tif (err < 0)\n \t\tgoto done;\n \treftable_buf_addstr(&next_name, \".ref\");\n-\tstack_filename(&tab_file_name, add->stack, next_name.buf);\n+\n+\terr = stack_filename(&tab_file_name, add->stack, next_name.buf);\n+\tif (err < 0)\n+\t\tgoto done;\n \n \t/*\n \t  On windows, this relies on rand() picking a unique destination name.\n@@ -954,7 +972,9 @@ static int stack_compact_locked(struct reftable_stack *st,\n \tif (err < 0)\n \t\tgoto done;\n \n-\tstack_filename(&tab_file_path, st, next_name.buf);\n+\terr = stack_filename(&tab_file_path, st, next_name.buf);\n+\tif (err < 0)\n+\t\tgoto done;\n \treftable_buf_addstr(&tab_file_path, \".temp.XXXXXX\");\n \n \ttab_file = mks_tempfile(tab_file_path.buf);\n@@ -1174,7 +1194,9 @@ static int stack_compact_range(struct reftable_stack *st,\n \t}\n \n \tfor (i = last + 1; i > first; i--) {\n-\t\tstack_filename(&table_name, st, reader_name(st->readers[i - 1]));\n+\t\terr = stack_filename(&table_name, st, reader_name(st->readers[i - 1]));\n+\t\tif (err < 0)\n+\t\t\tgoto done;\n \n \t\terr = hold_lock_file_for_update(&table_locks[nlocks],\n \t\t\t\t\t\ttable_name.buf, LOCK_NO_DEREF);\n@@ -1383,7 +1405,10 @@ static int stack_compact_range(struct reftable_stack *st,\n \t\t\tgoto done;\n \n \t\treftable_buf_addstr(&new_table_name, \".ref\");\n-\t\tstack_filename(&new_table_path, st, new_table_name.buf);\n+\n+\t\terr = stack_filename(&new_table_path, st, new_table_name.buf);\n+\t\tif (err < 0)\n+\t\t\tgoto done;\n \n \t\terr = rename_tempfile(&new_table, new_table_path.buf);\n \t\tif (err < 0) {\n@@ -1677,7 +1702,10 @@ static void remove_maybe_stale_table(struct reftable_stack *st, uint64_t max,\n \tstruct reftable_block_source src = { NULL };\n \tstruct reftable_reader *rd = NULL;\n \tstruct reftable_buf table_path = REFTABLE_BUF_INIT;\n-\tstack_filename(&table_path, st, name);\n+\n+\terr = stack_filename(&table_path, st, name);\n+\tif (err < 0)\n+\t\tgoto done;\n \n \terr = reftable_block_source_from_file(&src, table_path.buf);\n \tif (err < 0)\n-- \n2.47.0.dirty\n\n"},{"id":"505009","messageId":"90819c90f3858af26d962bb03b801219ee64e2b9.1728910727.git.ps@pks.im","threadId":"62313","inReplyTo":"cover.1728910726.git.ps@pks.im","subject":"[PATCH v2 10/10] reftable: handle trivial `reftable_buf` errors","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-10-14T13:02:45Z","receivedAt":"2024-10-14T13:02:49Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"Convert the reftable library such that we handle failures with the\nnew `reftable_buf` interfaces.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n reftable/block.c  |  9 +++++++--\n reftable/iter.c   |  5 ++++-\n reftable/reader.c |  5 ++++-\n reftable/record.c | 32 +++++++++++++++++++++++--------\n reftable/stack.c  | 49 +++++++++++++++++++++++++++++++----------------\n reftable/writer.c | 48 +++++++++++++++++++++++++++++++++-------------\n 6 files changed, 107 insertions(+), 41 deletions(-)\n\ndiff --git a/reftable/block.c b/reftable/block.c\nindex 697b8b41531..f5b432566a6 100644\n--- a/reftable/block.c\n+++ b/reftable/block.c\n@@ -40,7 +40,9 @@ int footer_size(int version)\n static int block_writer_register_restart(struct block_writer *w, int n,\n \t\t\t\t\t int is_restart, struct reftable_buf *key)\n {\n-\tint rlen = w->restart_len;\n+\tint rlen, err;\n+\n+\trlen = w->restart_len;\n \tif (rlen >= MAX_RESTARTS) {\n \t\tis_restart = 0;\n \t}\n@@ -60,7 +62,10 @@ static int block_writer_register_restart(struct block_writer *w, int n,\n \tw->next += n;\n \n \treftable_buf_reset(&w->last_key);\n-\treftable_buf_add(&w->last_key, key->buf, key->len);\n+\terr = reftable_buf_add(&w->last_key, key->buf, key->len);\n+\tif (err < 0)\n+\t\treturn err;\n+\n \tw->entries++;\n \treturn 0;\n }\ndiff --git a/reftable/iter.c b/reftable/iter.c\nindex 6c193fd31a9..86e801ca9fb 100644\n--- a/reftable/iter.c\n+++ b/reftable/iter.c\n@@ -197,7 +197,10 @@ int indexed_table_ref_iter_new(struct indexed_table_ref_iter **dest,\n \n \t*itr = empty;\n \titr->r = r;\n-\treftable_buf_add(&itr->oid, oid, oid_len);\n+\n+\terr = reftable_buf_add(&itr->oid, oid, oid_len);\n+\tif (err < 0)\n+\t\tgoto out;\n \n \titr->offsets = offsets;\n \titr->offset_len = offset_len;\ndiff --git a/reftable/reader.c b/reftable/reader.c\nindex ab89efd9c55..90dc950b577 100644\n--- a/reftable/reader.c\n+++ b/reftable/reader.c\n@@ -769,7 +769,10 @@ static int reftable_reader_refs_for_unindexed(struct reftable_reader *r,\n \t}\n \t*filter = empty;\n \n-\treftable_buf_add(&filter->oid, oid, oid_len);\n+\terr = reftable_buf_add(&filter->oid, oid, oid_len);\n+\tif (err < 0)\n+\t\tgoto out;\n+\n \titerator_from_table_iter(&filter->it, ti);\n \n \titerator_from_filtering_ref_iterator(it, filter);\ndiff --git a/reftable/record.c b/reftable/record.c\nindex 672c5f909a9..fb5652ed575 100644\n--- a/reftable/record.c\n+++ b/reftable/record.c\n@@ -102,7 +102,9 @@ static int decode_string(struct reftable_buf *dest, struct string_view in)\n {\n \tint start_len = in.len;\n \tuint64_t tsize = 0;\n-\tint n = get_var_int(&tsize, &in);\n+\tint n, err;\n+\n+\tn = get_var_int(&tsize, &in);\n \tif (n <= 0)\n \t\treturn -1;\n \tstring_view_consume(&in, n);\n@@ -110,7 +112,10 @@ static int decode_string(struct reftable_buf *dest, struct string_view in)\n \t\treturn -1;\n \n \treftable_buf_reset(dest);\n-\treftable_buf_add(dest, in.buf, tsize);\n+\terr = reftable_buf_add(dest, in.buf, tsize);\n+\tif (err < 0)\n+\t\treturn err;\n+\n \tstring_view_consume(&in, tsize);\n \n \treturn start_len - in.len;\n@@ -189,7 +194,7 @@ int reftable_decode_key(struct reftable_buf *last_key, uint8_t *extra,\n \tint start_len = in.len;\n \tuint64_t prefix_len = 0;\n \tuint64_t suffix_len = 0;\n-\tint n;\n+\tint err, n;\n \n \tn = reftable_decode_keylen(in, &prefix_len, &suffix_len, extra);\n \tif (n < 0)\n@@ -200,8 +205,14 @@ int reftable_decode_key(struct reftable_buf *last_key, uint8_t *extra,\n \t    prefix_len > last_key->len)\n \t\treturn -1;\n \n-\treftable_buf_setlen(last_key, prefix_len);\n-\treftable_buf_add(last_key, in.buf, suffix_len);\n+\terr = reftable_buf_setlen(last_key, prefix_len);\n+\tif (err < 0)\n+\t\treturn err;\n+\n+\terr = reftable_buf_add(last_key, in.buf, suffix_len);\n+\tif (err < 0)\n+\t\treturn err;\n+\n \tstring_view_consume(&in, suffix_len);\n \n \treturn start_len - in.len;\n@@ -1047,9 +1058,12 @@ static int reftable_index_record_copy_from(void *rec, const void *src_rec,\n {\n \tstruct reftable_index_record *dst = rec;\n \tconst struct reftable_index_record *src = src_rec;\n+\tint err;\n \n \treftable_buf_reset(&dst->last_key);\n-\treftable_buf_add(&dst->last_key, src->last_key.buf, src->last_key.len);\n+\terr = reftable_buf_add(&dst->last_key, src->last_key.buf, src->last_key.len);\n+\tif (err < 0)\n+\t\treturn err;\n \tdst->offset = src->offset;\n \n \treturn 0;\n@@ -1090,10 +1104,12 @@ static int reftable_index_record_decode(void *rec, struct reftable_buf key,\n {\n \tstruct string_view start = in;\n \tstruct reftable_index_record *r = rec;\n-\tint n = 0;\n+\tint err, n = 0;\n \n \treftable_buf_reset(&r->last_key);\n-\treftable_buf_add(&r->last_key, key.buf, key.len);\n+\terr = reftable_buf_add(&r->last_key, key.buf, key.len);\n+\tif (err < 0)\n+\t\treturn err;\n \n \tn = get_var_int(&r->offset, &in);\n \tif (n < 0)\ndiff --git a/reftable/stack.c b/reftable/stack.c\nindex 243b10715cc..c33979536ef 100644\n--- a/reftable/stack.c\n+++ b/reftable/stack.c\n@@ -78,8 +78,9 @@ int reftable_new_stack(struct reftable_stack **dest, const char *dir,\n \t*dest = NULL;\n \n \treftable_buf_reset(&list_file_name);\n-\treftable_buf_addstr(&list_file_name, dir);\n-\treftable_buf_addstr(&list_file_name, \"/tables.list\");\n+\tif ((err = reftable_buf_addstr(&list_file_name, dir)) < 0 ||\n+\t    (err = reftable_buf_addstr(&list_file_name, \"/tables.list\")) < 0)\n+\t\tgoto out;\n \n \tp->list_file = reftable_buf_detach(&list_file_name);\n \tp->list_fd = -1;\n@@ -747,12 +748,14 @@ int reftable_addition_commit(struct reftable_addition *add)\n \t\tgoto done;\n \n \tfor (i = 0; i < add->stack->merged->readers_len; i++) {\n-\t\treftable_buf_addstr(&table_list, add->stack->readers[i]->name);\n-\t\treftable_buf_addstr(&table_list, \"\\n\");\n+\t\tif ((err = reftable_buf_addstr(&table_list, add->stack->readers[i]->name)) < 0 ||\n+\t\t    (err = reftable_buf_addstr(&table_list, \"\\n\")) < 0)\n+\t\t\tgoto done;\n \t}\n \tfor (i = 0; i < add->new_tables_len; i++) {\n-\t\treftable_buf_addstr(&table_list, add->new_tables[i]);\n-\t\treftable_buf_addstr(&table_list, \"\\n\");\n+\t\tif ((err = reftable_buf_addstr(&table_list, add->new_tables[i])) < 0 ||\n+\t\t    (err = reftable_buf_addstr(&table_list, \"\\n\")) < 0)\n+\t\t\tgoto done;\n \t}\n \n \terr = write_in_full(lock_file_fd, table_list.buf, table_list.len);\n@@ -867,7 +870,10 @@ int reftable_addition_add(struct reftable_addition *add,\n \terr = stack_filename(&temp_tab_file_name, add->stack, next_name.buf);\n \tif (err < 0)\n \t\tgoto done;\n-\treftable_buf_addstr(&temp_tab_file_name, \".temp.XXXXXX\");\n+\n+\terr = reftable_buf_addstr(&temp_tab_file_name, \".temp.XXXXXX\");\n+\tif (err < 0)\n+\t\tgoto done;\n \n \ttab_file = mks_tempfile(temp_tab_file_name.buf);\n \tif (!tab_file) {\n@@ -914,7 +920,10 @@ int reftable_addition_add(struct reftable_addition *add,\n \terr = format_name(&next_name, wr->min_update_index, wr->max_update_index);\n \tif (err < 0)\n \t\tgoto done;\n-\treftable_buf_addstr(&next_name, \".ref\");\n+\n+\terr = reftable_buf_addstr(&next_name, \".ref\");\n+\tif (err < 0)\n+\t\tgoto done;\n \n \terr = stack_filename(&tab_file_name, add->stack, next_name.buf);\n \tif (err < 0)\n@@ -975,7 +984,10 @@ static int stack_compact_locked(struct reftable_stack *st,\n \terr = stack_filename(&tab_file_path, st, next_name.buf);\n \tif (err < 0)\n \t\tgoto done;\n-\treftable_buf_addstr(&tab_file_path, \".temp.XXXXXX\");\n+\n+\terr = reftable_buf_addstr(&tab_file_path, \".temp.XXXXXX\");\n+\tif (err < 0)\n+\t\tgoto done;\n \n \ttab_file = mks_tempfile(tab_file_path.buf);\n \tif (!tab_file) {\n@@ -1404,7 +1416,9 @@ static int stack_compact_range(struct reftable_stack *st,\n \t\tif (err < 0)\n \t\t\tgoto done;\n \n-\t\treftable_buf_addstr(&new_table_name, \".ref\");\n+\t\terr = reftable_buf_addstr(&new_table_name, \".ref\");\n+\t\tif (err < 0)\n+\t\t\tgoto done;\n \n \t\terr = stack_filename(&new_table_path, st, new_table_name.buf);\n \t\tif (err < 0)\n@@ -1423,16 +1437,19 @@ static int stack_compact_range(struct reftable_stack *st,\n \t * simply skip writing it.\n \t */\n \tfor (i = 0; i < first_to_replace; i++) {\n-\t\treftable_buf_addstr(&tables_list_buf, names[i]);\n-\t\treftable_buf_addstr(&tables_list_buf, \"\\n\");\n+\t\tif ((err = reftable_buf_addstr(&tables_list_buf, names[i])) < 0 ||\n+\t\t    (err = reftable_buf_addstr(&tables_list_buf, \"\\n\")) < 0)\n+\t\t      goto done;\n \t}\n \tif (!is_empty_table) {\n-\t\treftable_buf_addstr(&tables_list_buf, new_table_name.buf);\n-\t\treftable_buf_addstr(&tables_list_buf, \"\\n\");\n+\t\tif ((err = reftable_buf_addstr(&tables_list_buf, new_table_name.buf)) < 0 ||\n+\t\t    (err = reftable_buf_addstr(&tables_list_buf, \"\\n\")) < 0)\n+\t\t\tgoto done;\n \t}\n \tfor (i = last_to_replace + 1; names[i]; i++) {\n-\t\treftable_buf_addstr(&tables_list_buf, names[i]);\n-\t\treftable_buf_addstr(&tables_list_buf, \"\\n\");\n+\t\tif ((err = reftable_buf_addstr(&tables_list_buf, names[i])) < 0 ||\n+\t\t    (err = reftable_buf_addstr(&tables_list_buf, \"\\n\")) < 0)\n+\t\t\tgoto done;\n \t}\n \n \terr = write_in_full(get_lock_file_fd(&tables_list_lock),\ndiff --git a/reftable/writer.c b/reftable/writer.c\nindex 377db709c85..fd136794d5a 100644\n--- a/reftable/writer.c\n+++ b/reftable/writer.c\n@@ -217,6 +217,7 @@ static int writer_index_hash(struct reftable_writer *w, struct reftable_buf *has\n \tnode = tree_search(w->obj_index_tree, &want, &obj_index_tree_node_compare);\n \tif (!node) {\n \t\tstruct obj_index_tree_node empty = OBJ_INDEX_TREE_NODE_INIT;\n+\t\tint err;\n \n \t\tkey = reftable_malloc(sizeof(*key));\n \t\tif (!key)\n@@ -225,7 +226,9 @@ static int writer_index_hash(struct reftable_writer *w, struct reftable_buf *has\n \t\t*key = empty;\n \n \t\treftable_buf_reset(&key->hash);\n-\t\treftable_buf_add(&key->hash, hash->buf, hash->len);\n+\t\terr = reftable_buf_add(&key->hash, hash->buf, hash->len);\n+\t\tif (err < 0)\n+\t\t\treturn err;\n \t\ttree_insert(&w->obj_index_tree, key,\n \t\t\t    &obj_index_tree_node_compare);\n \t} else {\n@@ -259,7 +262,10 @@ static int writer_add_record(struct reftable_writer *w,\n \t}\n \n \treftable_buf_reset(&w->last_key);\n-\treftable_buf_add(&w->last_key, key.buf, key.len);\n+\terr = reftable_buf_add(&w->last_key, key.buf, key.len);\n+\tif (err < 0)\n+\t\tgoto done;\n+\n \tif (!w->block_writer) {\n \t\terr = writer_reinit_block_writer(w, reftable_record_type(rec));\n \t\tif (err < 0)\n@@ -334,8 +340,10 @@ int reftable_writer_add_ref(struct reftable_writer *w,\n \t\tgoto out;\n \n \tif (!w->opts.skip_index_objects && reftable_ref_record_val1(ref)) {\n-\t\treftable_buf_add(&buf, (char *)reftable_ref_record_val1(ref),\n-\t\t\t   hash_size(w->opts.hash_id));\n+\t\terr = reftable_buf_add(&buf, (char *)reftable_ref_record_val1(ref),\n+\t\t\t\t       hash_size(w->opts.hash_id));\n+\t\tif (err < 0)\n+\t\t\tgoto out;\n \n \t\terr = writer_index_hash(w, &buf);\n \t\tif (err < 0)\n@@ -344,8 +352,10 @@ int reftable_writer_add_ref(struct reftable_writer *w,\n \n \tif (!w->opts.skip_index_objects && reftable_ref_record_val2(ref)) {\n \t\treftable_buf_reset(&buf);\n-\t\treftable_buf_add(&buf, reftable_ref_record_val2(ref),\n-\t\t\t   hash_size(w->opts.hash_id));\n+\t\terr = reftable_buf_add(&buf, reftable_ref_record_val2(ref),\n+\t\t\t\t       hash_size(w->opts.hash_id));\n+\t\tif (err < 0)\n+\t\t\tgoto out;\n \n \t\terr = writer_index_hash(w, &buf);\n \t\tif (err < 0)\n@@ -407,17 +417,27 @@ int reftable_writer_add_log(struct reftable_writer *w,\n \n \tinput_log_message = log->value.update.message;\n \tif (!w->opts.exact_log_message && log->value.update.message) {\n-\t\treftable_buf_addstr(&cleaned_message, log->value.update.message);\n+\t\terr = reftable_buf_addstr(&cleaned_message, log->value.update.message);\n+\t\tif (err < 0)\n+\t\t\tgoto done;\n+\n \t\twhile (cleaned_message.len &&\n-\t\t       cleaned_message.buf[cleaned_message.len - 1] == '\\n')\n-\t\t\treftable_buf_setlen(&cleaned_message,\n-\t\t\t\t      cleaned_message.len - 1);\n+\t\t       cleaned_message.buf[cleaned_message.len - 1] == '\\n') {\n+\t\t\terr = reftable_buf_setlen(&cleaned_message,\n+\t\t\t\t\t\t  cleaned_message.len - 1);\n+\t\t\tif (err < 0)\n+\t\t\t\tgoto done;\n+\t\t}\n \t\tif (strchr(cleaned_message.buf, '\\n')) {\n \t\t\t/* multiple lines not allowed. */\n \t\t\terr = REFTABLE_API_ERROR;\n \t\t\tgoto done;\n \t\t}\n-\t\treftable_buf_addstr(&cleaned_message, \"\\n\");\n+\n+\t\terr = reftable_buf_addstr(&cleaned_message, \"\\n\");\n+\t\tif (err < 0)\n+\t\t\tgoto done;\n+\n \t\tlog->value.update.message = cleaned_message.buf;\n \t}\n \n@@ -781,8 +801,10 @@ static int writer_flush_nonempty_block(struct reftable_writer *w)\n \n \tindex_record.offset = w->next;\n \treftable_buf_reset(&index_record.last_key);\n-\treftable_buf_add(&index_record.last_key, w->block_writer->last_key.buf,\n-\t\t   w->block_writer->last_key.len);\n+\terr = reftable_buf_add(&index_record.last_key, w->block_writer->last_key.buf,\n+\t\t\t       w->block_writer->last_key.len);\n+\tif (err < 0)\n+\t\treturn err;\n \tw->index[w->index_len] = index_record;\n \tw->index_len++;\n \n-- \n2.47.0.dirty\n\n"},{"id":"505010","messageId":"Zw0YFKX7p0UpdT6i@pks.im","threadId":"62313","inReplyTo":"CAOLa=ZTHuWstTD56ZVTecW7ThHhpEqmrL28Emt5DtPL6pYhcpw@mail.gmail.com","subject":"Re: [PATCH 02/10] reftable: stop using `strbuf_addf()`","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-10-14T13:09:40Z","receivedAt":"2024-10-14T13:09:47Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"On Fri, Oct 11, 2024 at 02:51:57AM -0700, karthik nayak wrote:\n> Patrick Steinhardt <ps@pks.im> writes:\n> > @@ -1077,8 +1078,10 @@ static void t_reftable_stack_auto_compaction_with_locked_tables(void)\n> >  \t * size, we expect that auto-compaction will want to compact all of the\n> >  \t * tables. Locking any of the tables will keep it from doing so.\n> >  \t */\n> > -\tstrbuf_reset(&buf);\n> \n> However here it is different, since we still use the strbuf. I guess it\n> should be okay, since 'buf' is initialized using 'STRBUF_INIT' and that\n> still keeps the buf.len to 0.\n> \n> > -\tstrbuf_addf(&buf, \"%s/%s.lock\", dir, st->readers[2]->name);\n> > +\tstrbuf_addstr(&buf, dir);\n> > +\tstrbuf_addstr(&buf, \"/\");\n> > +\tstrbuf_addstr(&buf, st->readers[2]->name);\n> > +\tstrbuf_addstr(&buf, \".lock\");\n> >  \twrite_file_buf(buf.buf, \"\", 0);\n> >\n> \n> So when we do 'strbuf_addstr(&buf, ...)' it should allocate the required\n> memory. But the reset removal did catch my eye.\n\nYeah, I removed it while at it as it is completely unnecessary. I've\nupdated the commit message to point this out.\n\nPatrick\n"},{"id":"505011","messageId":"Zw0YGX-o4qteQyvU@pks.im","threadId":"62313","inReplyTo":"CAOLa=ZSwHeDAFi9RTzuGAi+5ogo9L6XG2K9WHY8kmvz6v-ZAeQ@mail.gmail.com","subject":"Re: [PATCH 03/10] reftable/basics: provide new `reftable_buf` interface","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-10-14T13:09:45Z","receivedAt":"2024-10-14T13:09:49Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"On Fri, Oct 11, 2024 at 05:03:39AM -0500, karthik nayak wrote:\n> Patrick Steinhardt <ps@pks.im> writes:\n> > diff --git a/reftable/basics.h b/reftable/basics.h\n> > index 4c9ef0fe6c5..4cf3f0e7593 100644\n> > --- a/reftable/basics.h\n> > +++ b/reftable/basics.h\n> > @@ -16,6 +16,22 @@ license that can be found in the LICENSE file or at\n> >  #include \"system.h\"\n> >  #include \"reftable-basics.h\"\n> >\n> > +struct reftable_buf {\n> > +\tsize_t alloc;\n> > +\tsize_t len;\n> > +\tchar *buf;\n> > +};\n> > +#define REFTABLE_BUF_INIT { 0 }\n> > +\n> > +void reftable_buf_init(struct reftable_buf *buf);\n> > +void reftable_buf_release(struct reftable_buf *buf);\n> > +void reftable_buf_reset(struct reftable_buf *buf);\n> > +int reftable_buf_setlen(struct reftable_buf *buf, size_t len);\n> > +int reftable_buf_cmp(const struct reftable_buf *a, const struct reftable_buf *b);\n> > +int reftable_buf_add(struct reftable_buf *buf, const void *data, size_t len);\n> > +int reftable_buf_addstr(struct reftable_buf *buf, const char *s);\n> > +char *reftable_buf_detach(struct reftable_buf *buf);\n> > +\n> \n> Nit: would be nice to have some comments explaining the functions here.\n> I know most of them are self-explanatory and similar to strbuf, but\n> since this is supposed to be isolated, it would be nice.\n\nFair enough. I was being lazy here because the code is internal, only.\nBut that's not really a good excuse, I guess.\n\nPatrick\n"},{"id":"505012","messageId":"Zw0YHQ9byrFmKCmP@pks.im","threadId":"62313","inReplyTo":"CAOLa=ZTOVGNxqJq0mj9GuLFqa6mVHp7WOkhuQsgiW79OKhhyNg@mail.gmail.com","subject":"Re: [PATCH 04/10] reftable: convert from `strbuf` to `reftable_buf`","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-10-14T13:09:49Z","receivedAt":"2024-10-14T13:09:53Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"On Fri, Oct 11, 2024 at 07:12:59AM -0500, karthik nayak wrote:\n> Patrick Steinhardt <ps@pks.im> writes:\n> \n> > Convert the reftable library to use the `reftable_buf` interface instead\n> > of the `strbuf` interface. This is a mechanical change via sed(1) and\n> > does not yet handle allocation failures. These will be addressed in\n> > subsequent commits.\n> >\n> \n> Nit: Would be nice to list the sed command used here, so reviewers can\n> review that instead.\n> \n> [snip]\n> \n> > diff --git a/reftable/basics.h b/reftable/basics.h\n> > index 4cf3f0e7593..ac3100417ec 100644\n> > --- a/reftable/basics.h\n> > +++ b/reftable/basics.h\n> > @@ -104,8 +104,7 @@ char *reftable_strdup(const char *str);\n> >  #endif\n> >\n> >  /* Find the longest shared prefix size of `a` and `b` */\n> > -struct strbuf;\n> \n> I guess this is the only manual part of this commit, would be nice to\n> mention this in the message.\n\nWell, it's basically a lie anyway that this uses sed(1), only. Some of\nthe functions are different between strbuf and reftable_buf, and I was\ntoo lazy to craft an sed invocation for that.\n\nI'll adapt the message a bit to say that this is mostly using sed, but\nnot really, without going into too many details.\n\nPatrick\n"},{"id":"505013","messageId":"Zw0YIJp-kl7glf_U@pks.im","threadId":"62313","inReplyTo":"CAOLa=ZR_fcq0NyraV01FQBeOZ=uv7JWLV0+tSsi=zsvt+VZOdw@mail.gmail.com","subject":"Re: [PATCH 00/10] reftable: stop using `struct strbuf`","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-10-14T13:09:52Z","receivedAt":"2024-10-14T13:09:56Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"On Fri, Oct 11, 2024 at 05:18:26AM -0700, karthik nayak wrote:\n> Patrick Steinhardt <ps@pks.im> writes:\n> \n> > Hi,\n> >\n> > this is the second patch series on my quest to make the reftable library\n> > become a standalone library again that can be used by libgit2 without\n> > pulling in all kinds of dependencies from the Git codebase. This part\n> > makes us lose the dependency on `struct strbuf`, which is done due to\n> > three reasons:\n> >\n> >   - To make us independent of libgit.a.\n> >\n> >   - To ensure that we use the pluggable allocators that users can set up\n> >     via `reftable_set_alloc()`.\n> >\n> >   - To make it possible to handle memory allocation failures.\n> >\n> > While this leads to some duplication, we're only talking about ~70 lines\n> > of code.\n> >\n> \n> I only have a few small comments, but overall this series looks good.\n> Thanks\n\nThanks for your review!\n\nPatrick\n"},{"id":"505085","messageId":"Zw2Y3cOz4px0TEsj@nand.local","threadId":"62313","inReplyTo":"7408482c152bbf465ecd098059b1477fd38c251a.1728910727.git.ps@pks.im","subject":"Re: [PATCH v2 01/10] reftable: stop using `strbuf_addbuf()`","fromName":"Taylor Blau","fromEmail":"me@ttaylorr.com","sentAt":"2024-10-14T22:19:09Z","receivedAt":"2024-10-14T22:19:12Z","isPatch":true,"sender":{"key":"me@ttaylorr.com","avatar":"https://avatars.githubusercontent.com/u/301000140?v=4"},"body":"On Mon, Oct 14, 2024 at 03:02:19PM +0200, Patrick Steinhardt wrote:\n> We're about to introduce our own `reftable_buf` type to replace\n> `strbuf`. Get rid of the seldomly-used `strbuf_addbuf()` function such\n> that we have to reimplement one less function.\n>\n> Signed-off-by: Patrick Steinhardt <ps@pks.im>\n> ---\n>  reftable/block.c  | 2 +-\n>  reftable/record.c | 6 +++---\n>  reftable/writer.c | 7 ++++---\n>  3 files changed, 8 insertions(+), 7 deletions(-)\n>\n> diff --git a/reftable/block.c b/reftable/block.c\n> index 8d41a2f99ed..cd4180eac7b 100644\n> --- a/reftable/block.c\n> +++ b/reftable/block.c\n> @@ -60,7 +60,7 @@ static int block_writer_register_restart(struct block_writer *w, int n,\n>  \tw->next += n;\n>\n>  \tstrbuf_reset(&w->last_key);\n> -\tstrbuf_addbuf(&w->last_key, key);\n> +\tstrbuf_add(&w->last_key, key->buf, key->len);\n>  \tw->entries++;\n>  \treturn 0;\n>  }\n\nOK, this makes sense. FWIW, it feels like this would have been an easy\nfunction to port over to the new 'reftable_buf' type. But I understand\nwanting to implement fewer functions if possible.\n\nThanks,\nTaylor\n"},{"id":"505086","messageId":"Zw2b5+8Lw83ywhzk@nand.local","threadId":"62313","inReplyTo":"6a7333b275e9f7eab81568a8de939011d292a31a.1728910727.git.ps@pks.im","subject":"Re: [PATCH v2 02/10] reftable: stop using `strbuf_addf()`","fromName":"Taylor Blau","fromEmail":"me@ttaylorr.com","sentAt":"2024-10-14T22:32:07Z","receivedAt":"2024-10-14T22:32:10Z","isPatch":true,"sender":{"key":"me@ttaylorr.com","avatar":"https://avatars.githubusercontent.com/u/301000140?v=4"},"body":"On Mon, Oct 14, 2024 at 03:02:21PM +0200, Patrick Steinhardt wrote:\n> We're about to introduce our own `reftable_buf` type to replace\n> `strbuf`. Get rid of the seldomly-used `strbuf_addf()` function such\n> that we have to reimplement one less function.\n\nHmm. I count twelve calls to strbuf_addf() here in this patch that were\nrewritten in terms of snprintf()ing to a temporary buffer. So I am not\nsure that I agree that it is \"seldomly-used\".\n\nSure, implementing fewer functions is nice, but I am not sure that\nforcing the caller to use snprintf() directly is necessarily a\nworthwhile trade-off.\n\nPart of me wishes that we didn't have to write our own `reftable_buf` in\nthe first place. Could we use `strbuf` as-is and expose it through a\ngeneric reftable-specific interface that users of reftable fill in with\na vtable or something?\n\nThanks,\nTaylor\n"},{"id":"505087","messageId":"Zw2cjxpDf6MowCP+@nand.local","threadId":"62313","inReplyTo":"0ddc8c0c896a006e4cc094390125efcec0b3cdff.1728910727.git.ps@pks.im","subject":"Re: [PATCH v2 03/10] reftable/basics: provide new `reftable_buf` interface","fromName":"Taylor Blau","fromEmail":"me@ttaylorr.com","sentAt":"2024-10-14T22:34:55Z","receivedAt":"2024-10-14T22:34:57Z","isPatch":true,"sender":{"key":"me@ttaylorr.com","avatar":"https://avatars.githubusercontent.com/u/301000140?v=4"},"body":"On Mon, Oct 14, 2024 at 03:02:24PM +0200, Patrick Steinhardt wrote:\n> Implement a new `reftable_buf` interface that will replace Git's own\n> `strbuf` interface. This is done due to three reasons:\n>\n>   - The `strbuf` interfaces do not handle memory allocation failures and\n>     instead causes us to die. This is okay in the context of Git, but is\n>     not in the context of the reftable library, which is supposed to be\n>     usable by third-party applications.\n>\n>   - The `strbuf` interface is quite deeply tied into Git, which makes it\n>     hard to use the reftable library as a standalone library. Any\n>     dependent would have to carefully extract the relevant parts of it\n>     to make things work, which is not all that sensible.\n>\n>   - The `strbuf` interface does not use the pluggable allocators that\n>     can be set up via `refatble_set_alloc()`.\n\ns/refatble/reftable/.\n\n> +/*\n> + * Add the given bytes to the buffer. Returns 0 on success,\n> + * REFTABLE_OUT_OF_MEMORY_ERROR on allocation failure.\n> + */\n> +int reftable_buf_add(struct reftable_buf *buf, const void *data, size_t len);\n\nIs there a reason that data is a void-pointer here and not a const char\n*?\n\nThanks,\nTaylor\n"},{"id":"505088","messageId":"Zw2cv2G6ITf0aTkZ@nand.local","threadId":"62313","inReplyTo":"e1ff1af1f302490f8d79301a73f7cd48314477ba.1728910727.git.ps@pks.im","subject":"Re: [PATCH v2 04/10] reftable: convert from `strbuf` to `reftable_buf`","fromName":"Taylor Blau","fromEmail":"me@ttaylorr.com","sentAt":"2024-10-14T22:35:43Z","receivedAt":"2024-10-14T22:35:45Z","isPatch":true,"sender":{"key":"me@ttaylorr.com","avatar":"https://avatars.githubusercontent.com/u/301000140?v=4"},"body":"On Mon, Oct 14, 2024 at 03:02:27PM +0200, Patrick Steinhardt wrote:\n> Convert the reftable library to use the `reftable_buf` interface instead\n> of the `strbuf` interface. This is mostly a mechanical change via sed(1)\n> with some manual fixes where functions for `strbuf` and `reftable_buf`\n> differ. The converted code does not yet handle allocation failures. This\n> will be handled in subsequent commits.\n>\n> Signed-off-by: Patrick Steinhardt <ps@pks.im>\n> ---\n>  reftable/basics.c                   |   2 +-\n>  reftable/basics.h                   |   3 +-\n>  reftable/block.c                    |  34 ++++----\n>  reftable/block.h                    |  14 ++--\n>  reftable/blocksource.c              |   6 +-\n>  reftable/blocksource.h              |   3 +-\n>  reftable/iter.c                     |   6 +-\n>  reftable/iter.h                     |   8 +-\n>  reftable/reader.c                   |  16 ++--\n>  reftable/record.c                   |  80 +++++++++----------\n>  reftable/record.h                   |  21 ++---\n>  reftable/stack.c                    | 120 ++++++++++++++--------------\n>  reftable/system.h                   |   1 -\n>  reftable/writer.c                   |  66 +++++++--------\n>  reftable/writer.h                   |   2 +-\n>  t/unit-tests/lib-reftable.c         |   4 +-\n>  t/unit-tests/lib-reftable.h         |   7 +-\n>  t/unit-tests/t-reftable-basics.c    |  16 ++--\n>  t/unit-tests/t-reftable-block.c     |  42 +++++-----\n>  t/unit-tests/t-reftable-merged.c    |  26 +++---\n>  t/unit-tests/t-reftable-reader.c    |   8 +-\n>  t/unit-tests/t-reftable-readwrite.c |  92 ++++++++++-----------\n>  t/unit-tests/t-reftable-record.c    |  74 ++++++++---------\n>  t/unit-tests/t-reftable-stack.c     |  90 ++++++++++-----------\n>  24 files changed, 371 insertions(+), 370 deletions(-)\n\nIt's an awfully long patch, but was relatively easy to skim visually.\n\nThanks,\nTaylor\n"},{"id":"505089","messageId":"Zw2eIbeWUygH9+hn@nand.local","threadId":"62313","inReplyTo":"1f08163009b87596188165863b89b62c5f521e00.1728910727.git.ps@pks.im","subject":"Re: [PATCH v2 07/10] reftable/stack: adapt `format_name()` to handle allocation failures","fromName":"Taylor Blau","fromEmail":"me@ttaylorr.com","sentAt":"2024-10-14T22:41:37Z","receivedAt":"2024-10-14T22:41:40Z","isPatch":true,"sender":{"key":"me@ttaylorr.com","avatar":"https://avatars.githubusercontent.com/u/301000140?v=4"},"body":"On Mon, Oct 14, 2024 at 03:02:37PM +0200, Patrick Steinhardt wrote:\n> @@ -846,7 +846,10 @@ int reftable_addition_add(struct reftable_addition *add,\n>  \tint tab_fd;\n>\n>  \treftable_buf_reset(&next_name);\n> -\tformat_name(&next_name, add->next_update_index, add->next_update_index);\n> +\n> +\terr = format_name(&next_name, add->next_update_index, add->next_update_index);\n> +\tif (err < 0)\n> +\t\tgoto done;\n>\n>  \tstack_filename(&temp_tab_file_name, add->stack, next_name.buf);\n>  \treftable_buf_addstr(&temp_tab_file_name, \".temp.XXXXXX\");\n\nThe conversion to store the return value of 'format_name()' here makes\nsense. I was going to ask why this call to reftable_buf_addstr() does\nnot have its own return value checked similarly, but I see that it is\nhandled specially a few commits later on.\n\nI think that what you wrote here is fine, but there are a couple of\nalternatives IMHO that may be worth considering in the future:\n\n  - You could do these conversions function by function, where each\n    patch handles all potential allocation failures.\n\n    This generates more patches, but makes each individual patch a\n    little easier to review in isolation, since the reviewer does not\n    have to page in and out the context of what different functions do,\n    etc.\n\n  - Alternatively, you could mention something along the lines of \"this\n    step does not make any of these functions entirely resilient against\n    allocation failures, but future commits will address the remaining\n    components\" to avoid temporary confusion on the reader's part\n    wondering why only part of the code appears to handle allocation\n    failures.\n\nThanks,\nTaylor\n"},{"id":"505090","messageId":"Zw2e0w5bkDO4l/Qs@nand.local","threadId":"62313","inReplyTo":"cover.1728910726.git.ps@pks.im","subject":"Re: [PATCH v2 00/10] reftable: stop using `struct strbuf`","fromName":"Taylor Blau","fromEmail":"me@ttaylorr.com","sentAt":"2024-10-14T22:44:35Z","receivedAt":"2024-10-14T22:44:38Z","isPatch":true,"sender":{"key":"me@ttaylorr.com","avatar":"https://avatars.githubusercontent.com/u/301000140?v=4"},"body":"On Mon, Oct 14, 2024 at 03:02:16PM +0200, Patrick Steinhardt wrote:\n> Hi,\n>\n> this is the second part of my patch series that stop using `struct\n> strbuf` in the reftable library. This is done such that the reftable\n> library becomes standalone again and so that we can use the pluggable\n> allocators part of the library.\n\nI reviewed this round, and it looks generally good to me. I feel\nsomewhat unhappy to have to force the reftable backend to implement its\nown strbuf-like functionality.\n\nSo I think it may be worth considering whether or not we can reuse Git's\nstrbuf implementation through a vtable or similar. But it may not be\nimmediately possible since that implementation just die()s on error,\ncan't easily swap out the allocator, etc. So perhaps this is the best\npath forward, it just feels somewhat unsatisfying to me.\n\nThanks,\nTaylor\n"},{"id":"505113","messageId":"Zw3xkX_a4KyrSNq9@pks.im","threadId":"62313","inReplyTo":"Zw2e0w5bkDO4l/Qs@nand.local","subject":"Re: [PATCH v2 00/10] reftable: stop using `struct strbuf`","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-10-15T04:37:37Z","receivedAt":"2024-10-15T04:37:44Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"On Mon, Oct 14, 2024 at 06:44:35PM -0400, Taylor Blau wrote:\n> On Mon, Oct 14, 2024 at 03:02:16PM +0200, Patrick Steinhardt wrote:\n> > Hi,\n> >\n> > this is the second part of my patch series that stop using `struct\n> > strbuf` in the reftable library. This is done such that the reftable\n> > library becomes standalone again and so that we can use the pluggable\n> > allocators part of the library.\n> \n> I reviewed this round, and it looks generally good to me. I feel\n> somewhat unhappy to have to force the reftable backend to implement its\n> own strbuf-like functionality.\n> \n> So I think it may be worth considering whether or not we can reuse Git's\n> strbuf implementation through a vtable or similar. But it may not be\n> immediately possible since that implementation just die()s on error,\n> can't easily swap out the allocator, etc. So perhaps this is the best\n> path forward, it just feels somewhat unsatisfying to me.\n\nIt's not perfect, I agree. I initially tried to do something like a\nvtable or to even compile this into code with something like a wrapper\nstructure. But that approach in the end fell flat. So I decided to be\npragmatic about this whole issue and just duplicate some code --\noverall, we are talking about ~200 lines of code to completely detangle\nthe reftable library from libgit.a.\n\nFor what it's worth, I also had this discussion with Junio in [1], in\nwhich we ultimately agreed that this is probably the best way forward.\n\nPatrick\n\n[1]: <ZvVPiIzzLTTb75b8@pks.im>\n"},{"id":"505114","messageId":"Zw3xnFN_c7WSz1u8@pks.im","threadId":"62313","inReplyTo":"Zw2b5+8Lw83ywhzk@nand.local","subject":"Re: [PATCH v2 02/10] reftable: stop using `strbuf_addf()`","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-10-15T04:37:48Z","receivedAt":"2024-10-15T04:37:59Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"On Mon, Oct 14, 2024 at 06:32:07PM -0400, Taylor Blau wrote:\n> On Mon, Oct 14, 2024 at 03:02:21PM +0200, Patrick Steinhardt wrote:\n> > We're about to introduce our own `reftable_buf` type to replace\n> > `strbuf`. Get rid of the seldomly-used `strbuf_addf()` function such\n> > that we have to reimplement one less function.\n> \n> Hmm. I count twelve calls to strbuf_addf() here in this patch that were\n> rewritten in terms of snprintf()ing to a temporary buffer. So I am not\n> sure that I agree that it is \"seldomly-used\".\n> \n> Sure, implementing fewer functions is nice, but I am not sure that\n> forcing the caller to use snprintf() directly is necessarily a\n> worthwhile trade-off.\n\nAnother problem here is that snprintf() isn't exactly the most portable\ninterface. Some systems don't have it at all, others have broken return\ncode handling. So avoiding it completely makes that issue go away\nentirely.\n\nI can add that to the commit message if this needs a reroll.\n\n> Part of me wishes that we didn't have to write our own `reftable_buf` in\n> the first place. Could we use `strbuf` as-is and expose it through a\n> generic reftable-specific interface that users of reftable fill in with\n> a vtable or something?\n\nI tried that, and it felt way worse. The amount of code you have to\nwrite is roughly in the same ballpark, you don't have pluggable\nallocators, you don't have allocation error handling and every consumer\nwould have to implement their own type.\n\nSo overall it's only losses from my point of view.\n\nPatrick\n"},{"id":"505115","messageId":"Zw3xhwLFlznU_JvK@pks.im","threadId":"62313","inReplyTo":"Zw2cjxpDf6MowCP+@nand.local","subject":"Re: [PATCH v2 03/10] reftable/basics: provide new `reftable_buf` interface","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-10-15T04:38:18Z","receivedAt":"2024-10-15T04:38:25Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"On Mon, Oct 14, 2024 at 06:34:55PM -0400, Taylor Blau wrote:\n> On Mon, Oct 14, 2024 at 03:02:24PM +0200, Patrick Steinhardt wrote:\n> > Implement a new `reftable_buf` interface that will replace Git's own\n> > `strbuf` interface. This is done due to three reasons:\n> >\n> >   - The `strbuf` interfaces do not handle memory allocation failures and\n> >     instead causes us to die. This is okay in the context of Git, but is\n> >     not in the context of the reftable library, which is supposed to be\n> >     usable by third-party applications.\n> >\n> >   - The `strbuf` interface is quite deeply tied into Git, which makes it\n> >     hard to use the reftable library as a standalone library. Any\n> >     dependent would have to carefully extract the relevant parts of it\n> >     to make things work, which is not all that sensible.\n> >\n> >   - The `strbuf` interface does not use the pluggable allocators that\n> >     can be set up via `refatble_set_alloc()`.\n> \n> s/refatble/reftable/.\n> \n> > +/*\n> > + * Add the given bytes to the buffer. Returns 0 on success,\n> > + * REFTABLE_OUT_OF_MEMORY_ERROR on allocation failure.\n> > + */\n> > +int reftable_buf_add(struct reftable_buf *buf, const void *data, size_t len);\n> \n> Is there a reason that data is a void-pointer here and not a const char\n> *?\n\nOnly that it emulates `strbuf_add()`, which also uses a void pointer.\n\nPatrick\n"},{"id":"505116","messageId":"CAPig+cSXJaETg4Sq3Zw8=37M15CdLEUkdMb2U2X4NPSOAFwmyw@mail.gmail.com","threadId":"62313","inReplyTo":"Zw3xhwLFlznU_JvK@pks.im","subject":"Re: [PATCH v2 03/10] reftable/basics: provide new `reftable_buf` interface","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2024-10-15T05:10:59Z","receivedAt":"2024-10-15T05:11:11Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"On Tue, Oct 15, 2024 at 12:38 AM Patrick Steinhardt <ps@pks.im> wrote:\n> On Mon, Oct 14, 2024 at 06:34:55PM -0400, Taylor Blau wrote:\n> > On Mon, Oct 14, 2024 at 03:02:24PM +0200, Patrick Steinhardt wrote:\n> > > +/*\n> > > + * Add the given bytes to the buffer. Returns 0 on success,\n> > > + * REFTABLE_OUT_OF_MEMORY_ERROR on allocation failure.\n> > > + */\n> > > +int reftable_buf_add(struct reftable_buf *buf, const void *data, size_t len);\n> >\n> > Is there a reason that data is a void-pointer here and not a const char\n> > *?\n>\n> Only that it emulates `strbuf_add()`, which also uses a void pointer.\n\nThe reason for that is because strbuf is a generic byte-array which\nmay contain embedded NULs, and the `const void *` plus `len`\nemphasizes this property, whereas `const char *` would imply a\nC-string with no embedded NULs.\n\n(strbuf also happens to ensure that the contained byte-array ends with\nNUL so that the .buf member can be used safely with any function\naccepting a C-string, but that is a convenience for the common case\nwhen it does not contain embedded NULs, not a promise that there won't\nbe embedded NULs, hence `const void *` rather than `cont char *`.)\n"},{"id":"505133","messageId":"Zw5E8d3AotDBYKSA@ArchLinux","threadId":"62313","inReplyTo":"Zw3xkX_a4KyrSNq9@pks.im","subject":"Re: [PATCH v2 00/10] reftable: stop using `struct strbuf`","fromName":"shejialuo","fromEmail":"shejialuo@gmail.com","sentAt":"2024-10-15T10:33:21Z","receivedAt":"2024-10-15T10:33:24Z","isPatch":true,"sender":{"key":"shejialuo@gmail.com","avatar":"https://avatars.githubusercontent.com/u/56911263?v=4"},"body":"On Tue, Oct 15, 2024 at 06:37:37AM +0200, Patrick Steinhardt wrote:\n> On Mon, Oct 14, 2024 at 06:44:35PM -0400, Taylor Blau wrote:\n> > On Mon, Oct 14, 2024 at 03:02:16PM +0200, Patrick Steinhardt wrote:\n> > > Hi,\n> > >\n> > > this is the second part of my patch series that stop using `struct\n> > > strbuf` in the reftable library. This is done such that the reftable\n> > > library becomes standalone again and so that we can use the pluggable\n> > > allocators part of the library.\n> > \n> > I reviewed this round, and it looks generally good to me. I feel\n> > somewhat unhappy to have to force the reftable backend to implement its\n> > own strbuf-like functionality.\n> > \n> > So I think it may be worth considering whether or not we can reuse Git's\n> > strbuf implementation through a vtable or similar. But it may not be\n> > immediately possible since that implementation just die()s on error,\n> > can't easily swap out the allocator, etc. So perhaps this is the best\n> > path forward, it just feels somewhat unsatisfying to me.\n> \n> It's not perfect, I agree. I initially tried to do something like a\n> vtable or to even compile this into code with something like a wrapper\n> structure. But that approach in the end fell flat. So I decided to be\n> pragmatic about this whole issue and just duplicate some code --\n> overall, we are talking about ~200 lines of code to completely detangle\n> the reftable library from libgit.a.\n> \n\nI have read some patches yesterday, I feel quite strange that we need to\nmake repetition. Could we provide a header file which requires the users\nwho need to use the reftable library to implement the interfaces?\n\n    reftable_strbuf_addf(void *buf, char *fmt, va_list ap);\n\nThus, we could reuse \"strbuf_addf\" to implement this interface in Git.\nAs for libgit2, could we let it implement these interfaces? Although I\nhave never read the source code of libgit2, I think there should be some\ncode which could be reuse to implement these interfaces?\n\nHowever, I do not know the context. Maybe the above is totally wrong. If\nso, please ignore.\n\nThanks,\nJialuo\n"},{"id":"505134","messageId":"Zw5HntIyk_DLWESC@pks.im","threadId":"62313","inReplyTo":"Zw5E8d3AotDBYKSA@ArchLinux","subject":"Re: [PATCH v2 00/10] reftable: stop using `struct strbuf`","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-10-15T10:44:53Z","receivedAt":"2024-10-15T10:45:01Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"On Tue, Oct 15, 2024 at 06:33:21PM +0800, shejialuo wrote:\n> On Tue, Oct 15, 2024 at 06:37:37AM +0200, Patrick Steinhardt wrote:\n> > On Mon, Oct 14, 2024 at 06:44:35PM -0400, Taylor Blau wrote:\n> > > On Mon, Oct 14, 2024 at 03:02:16PM +0200, Patrick Steinhardt wrote:\n> > > > Hi,\n> > > >\n> > > > this is the second part of my patch series that stop using `struct\n> > > > strbuf` in the reftable library. This is done such that the reftable\n> > > > library becomes standalone again and so that we can use the pluggable\n> > > > allocators part of the library.\n> > > \n> > > I reviewed this round, and it looks generally good to me. I feel\n> > > somewhat unhappy to have to force the reftable backend to implement its\n> > > own strbuf-like functionality.\n> > > \n> > > So I think it may be worth considering whether or not we can reuse Git's\n> > > strbuf implementation through a vtable or similar. But it may not be\n> > > immediately possible since that implementation just die()s on error,\n> > > can't easily swap out the allocator, etc. So perhaps this is the best\n> > > path forward, it just feels somewhat unsatisfying to me.\n> > \n> > It's not perfect, I agree. I initially tried to do something like a\n> > vtable or to even compile this into code with something like a wrapper\n> > structure. But that approach in the end fell flat. So I decided to be\n> > pragmatic about this whole issue and just duplicate some code --\n> > overall, we are talking about ~200 lines of code to completely detangle\n> > the reftable library from libgit.a.\n> > \n> \n> I have read some patches yesterday, I feel quite strange that we need to\n> make repetition. Could we provide a header file which requires the users\n> who need to use the reftable library to implement the interfaces?\n> \n>     reftable_strbuf_addf(void *buf, char *fmt, va_list ap);\n> \n> Thus, we could reuse \"strbuf_addf\" to implement this interface in Git.\n> As for libgit2, could we let it implement these interfaces? Although I\n> have never read the source code of libgit2, I think there should be some\n> code which could be reuse to implement these interfaces?\n> \n> However, I do not know the context. Maybe the above is totally wrong. If\n> so, please ignore.\n\nThe thing is that we'll have repetition regardless of what we end up\ndoing:\n\n  - We could either have repetition once in the reftable library,\n    reimplementing `struct strbuf`. This can then be reused by every\n    single user of the reftable library.\n\n  - Or we can have repetition for every single user of the reftable\n    library. For now that'd only be Git and libgit2, but we'd still have\n    repetition.\n\nThe second kind of repetition is way worse though, because now every\nuser of the reftable library has a different implementation of a type\nthat is as basic as a buffer. These _must_ behave the exact same across\nimplementations or we will hit issues. So I'd rather have the repetition\na single time in the reftable library such that all users of the library\nwill behave the same rather than having downstream users copy the\nimplementation of `struct strbuf` and making it work for their library.\n\nAlso, due to the nature of `struct strbuf` not allowing for allocation\nfailures we'd already have diverging behaviour. In Git you would never\nhit error code paths for allocation failures, whereas every library user\npotentially can.\n\nSo we really have to treat the reftable code base special. If we want to\nbe a good citizen and be a proper upstream for projects like libgit2 we\ndon't really have much of a choice than to detangle it from libgit.a. If\nwe don't we may be saving 20 lines of code, but we make everybody elses\nlife harder.\n\nPatrick\n"},{"id":"505140","messageId":"Zw5QzmtOrDOXAavV@ArchLinux","threadId":"62313","inReplyTo":"Zw5HntIyk_DLWESC@pks.im","subject":"Re: [PATCH v2 00/10] reftable: stop using `struct strbuf`","fromName":"shejialuo","fromEmail":"shejialuo@gmail.com","sentAt":"2024-10-15T11:23:58Z","receivedAt":"2024-10-15T11:24:01Z","isPatch":true,"sender":{"key":"shejialuo@gmail.com","avatar":"https://avatars.githubusercontent.com/u/56911263?v=4"},"body":"On Tue, Oct 15, 2024 at 12:44:53PM +0200, Patrick Steinhardt wrote:\n\n[snip]\n\n> > I have read some patches yesterday, I feel quite strange that we need to\n> > make repetition. Could we provide a header file which requires the users\n> > who need to use the reftable library to implement the interfaces?\n> > \n> >     reftable_strbuf_addf(void *buf, char *fmt, va_list ap);\n> > \n> > Thus, we could reuse \"strbuf_addf\" to implement this interface in Git.\n> > As for libgit2, could we let it implement these interfaces? Although I\n> > have never read the source code of libgit2, I think there should be some\n> > code which could be reuse to implement these interfaces?\n> > \n> > However, I do not know the context. Maybe the above is totally wrong. If\n> > so, please ignore.\n> \n> The thing is that we'll have repetition regardless of what we end up\n> doing:\n> \n>   - We could either have repetition once in the reftable library,\n>     reimplementing `struct strbuf`. This can then be reused by every\n>     single user of the reftable library.\n> \n>   - Or we can have repetition for every single user of the reftable\n>     library. For now that'd only be Git and libgit2, but we'd still have\n>     repetition.\n> \n> The second kind of repetition is way worse though, because now every\n> user of the reftable library has a different implementation of a type\n> that is as basic as a buffer. These _must_ behave the exact same across\n> implementations or we will hit issues. So I'd rather have the repetition\n> a single time in the reftable library such that all users of the library\n> will behave the same rather than having downstream users copy the\n> implementation of `struct strbuf` and making it work for their library.\n> \n\nYes. I agree with you it is worse to let every downstream to implement\nthe interfaces. I know the motivation here, we want to make the whole\nreftable library be independent of the Git which allows the downstream\nto easily use the reftable library.\n\n> Also, due to the nature of `struct strbuf` not allowing for allocation\n> failures we'd already have diverging behaviour. In Git you would never\n> hit error code paths for allocation failures, whereas every library user\n> potentially can.\n> \n> So we really have to treat the reftable code base special. If we want to\n> be a good citizen and be a proper upstream for projects like libgit2 we\n> don't really have much of a choice than to detangle it from libgit.a. If\n> we don't we may be saving 20 lines of code, but we make everybody elses\n> life harder.\n> \n\nYes. And I do not think this is a problem right now. Thanks for this\nwonderful explanation.\n\n> Patrick\n\nJialuo\n"},{"id":"505201","messageId":"Zw7B5Y1yUu0rt8zM@nand.local","threadId":"62313","inReplyTo":"Zw3xnFN_c7WSz1u8@pks.im","subject":"Re: [PATCH v2 02/10] reftable: stop using `strbuf_addf()`","fromName":"Taylor Blau","fromEmail":"me@ttaylorr.com","sentAt":"2024-10-15T19:26:29Z","receivedAt":"2024-10-15T19:26:31Z","isPatch":true,"sender":{"key":"me@ttaylorr.com","avatar":"https://avatars.githubusercontent.com/u/301000140?v=4"},"body":"On Tue, Oct 15, 2024 at 06:37:48AM +0200, Patrick Steinhardt wrote:\n> > Part of me wishes that we didn't have to write our own `reftable_buf` in\n> > the first place. Could we use `strbuf` as-is and expose it through a\n> > generic reftable-specific interface that users of reftable fill in with\n> > a vtable or something?\n>\n> I tried that, and it felt way worse. The amount of code you have to\n> write is roughly in the same ballpark, you don't have pluggable\n> allocators, you don't have allocation error handling and every consumer\n> would have to implement their own type.\n>\n> So overall it's only losses from my point of view.\n\nMakes sense, although the end result is somewhat unsatisfying.\n\nThanks,\nTaylor\n"},{"id":"505202","messageId":"Zw7CIRoXrLr5pd5A@nand.local","threadId":"62313","inReplyTo":"CAPig+cSXJaETg4Sq3Zw8=37M15CdLEUkdMb2U2X4NPSOAFwmyw@mail.gmail.com","subject":"Re: [PATCH v2 03/10] reftable/basics: provide new `reftable_buf` interface","fromName":"Taylor Blau","fromEmail":"me@ttaylorr.com","sentAt":"2024-10-15T19:27:29Z","receivedAt":"2024-10-15T19:27:31Z","isPatch":true,"sender":{"key":"me@ttaylorr.com","avatar":"https://avatars.githubusercontent.com/u/301000140?v=4"},"body":"On Tue, Oct 15, 2024 at 01:10:59AM -0400, Eric Sunshine wrote:\n> On Tue, Oct 15, 2024 at 12:38 AM Patrick Steinhardt <ps@pks.im> wrote:\n> > On Mon, Oct 14, 2024 at 06:34:55PM -0400, Taylor Blau wrote:\n> > > On Mon, Oct 14, 2024 at 03:02:24PM +0200, Patrick Steinhardt wrote:\n> > > > +/*\n> > > > + * Add the given bytes to the buffer. Returns 0 on success,\n> > > > + * REFTABLE_OUT_OF_MEMORY_ERROR on allocation failure.\n> > > > + */\n> > > > +int reftable_buf_add(struct reftable_buf *buf, const void *data, size_t len);\n> > >\n> > > Is there a reason that data is a void-pointer here and not a const char\n> > > *?\n> >\n> > Only that it emulates `strbuf_add()`, which also uses a void pointer.\n>\n> The reason for that is because strbuf is a generic byte-array which\n> may contain embedded NULs, and the `const void *` plus `len`\n> emphasizes this property, whereas `const char *` would imply a\n> C-string with no embedded NULs.\n\nThanks, that was the explanation I was missing. Perhaps it is worth\nre-stating in the commit message here to avoid confusing readers like I\nwas when I first read Patrick's patch ;-).\n\nThanks,\nTaylor\n"},{"id":"505253","messageId":"Zw98hKZc1pjBGGcU@pks.im","threadId":"62313","inReplyTo":"Zw7CIRoXrLr5pd5A@nand.local","subject":"Re: [PATCH v2 03/10] reftable/basics: provide new `reftable_buf` interface","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-10-16T08:42:44Z","receivedAt":"2024-10-16T08:42:49Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"On Tue, Oct 15, 2024 at 03:27:29PM -0400, Taylor Blau wrote:\n> On Tue, Oct 15, 2024 at 01:10:59AM -0400, Eric Sunshine wrote:\n> > On Tue, Oct 15, 2024 at 12:38 AM Patrick Steinhardt <ps@pks.im> wrote:\n> > > On Mon, Oct 14, 2024 at 06:34:55PM -0400, Taylor Blau wrote:\n> > > > On Mon, Oct 14, 2024 at 03:02:24PM +0200, Patrick Steinhardt wrote:\n> > > > > +/*\n> > > > > + * Add the given bytes to the buffer. Returns 0 on success,\n> > > > > + * REFTABLE_OUT_OF_MEMORY_ERROR on allocation failure.\n> > > > > + */\n> > > > > +int reftable_buf_add(struct reftable_buf *buf, const void *data, size_t len);\n> > > >\n> > > > Is there a reason that data is a void-pointer here and not a const char\n> > > > *?\n> > >\n> > > Only that it emulates `strbuf_add()`, which also uses a void pointer.\n> >\n> > The reason for that is because strbuf is a generic byte-array which\n> > may contain embedded NULs, and the `const void *` plus `len`\n> > emphasizes this property, whereas `const char *` would imply a\n> > C-string with no embedded NULs.\n> \n> Thanks, that was the explanation I was missing. Perhaps it is worth\n> re-stating in the commit message here to avoid confusing readers like I\n> was when I first read Patrick's patch ;-).\n\nDoes it make sense to explicitly state how the interfaces look like\nthough? I don't do that for the other functions either, and for most of\nthe part I just reuse the exact same function arguments as we had with\nthe strbuf interface.\n\nPatrick\n"},{"id":"505304","messageId":"ZxAolGGcndQzApPJ@nand.local","threadId":"62313","inReplyTo":"Zw98hKZc1pjBGGcU@pks.im","subject":"Re: [PATCH v2 03/10] reftable/basics: provide new `reftable_buf` interface","fromName":"Taylor Blau","fromEmail":"me@ttaylorr.com","sentAt":"2024-10-16T20:56:52Z","receivedAt":"2024-10-16T20:56:55Z","isPatch":true,"sender":{"key":"me@ttaylorr.com","avatar":"https://avatars.githubusercontent.com/u/301000140?v=4"},"body":"On Wed, Oct 16, 2024 at 10:42:44AM +0200, Patrick Steinhardt wrote:\n> On Tue, Oct 15, 2024 at 03:27:29PM -0400, Taylor Blau wrote:\n> > On Tue, Oct 15, 2024 at 01:10:59AM -0400, Eric Sunshine wrote:\n> > > On Tue, Oct 15, 2024 at 12:38 AM Patrick Steinhardt <ps@pks.im> wrote:\n> > > > On Mon, Oct 14, 2024 at 06:34:55PM -0400, Taylor Blau wrote:\n> > > > > On Mon, Oct 14, 2024 at 03:02:24PM +0200, Patrick Steinhardt wrote:\n> > > > > > +/*\n> > > > > > + * Add the given bytes to the buffer. Returns 0 on success,\n> > > > > > + * REFTABLE_OUT_OF_MEMORY_ERROR on allocation failure.\n> > > > > > + */\n> > > > > > +int reftable_buf_add(struct reftable_buf *buf, const void *data, size_t len);\n> > > > >\n> > > > > Is there a reason that data is a void-pointer here and not a const char\n> > > > > *?\n> > > >\n> > > > Only that it emulates `strbuf_add()`, which also uses a void pointer.\n> > >\n> > > The reason for that is because strbuf is a generic byte-array which\n> > > may contain embedded NULs, and the `const void *` plus `len`\n> > > emphasizes this property, whereas `const char *` would imply a\n> > > C-string with no embedded NULs.\n> >\n> > Thanks, that was the explanation I was missing. Perhaps it is worth\n> > re-stating in the commit message here to avoid confusing readers like I\n> > was when I first read Patrick's patch ;-).\n>\n> Does it make sense to explicitly state how the interfaces look like\n> though? I don't do that for the other functions either, and for most of\n> the part I just reuse the exact same function arguments as we had with\n> the strbuf interface.\n\nI don't feel very strongly about it, but I had suggested it because my\ninitial read of this patch confused me, and I had wondered if others may\nbe similarly confused.\n\nFor what it's worth, I was thinking something on the order of the\nfollowing added to the patch message:\n\n    Note that the reftable_buf_add() function intentionally takes a \"const\n    void *\" instead of a \"const char *\" (as does its strbuf counterpart,\n    strbuf_add()) to emphasize that the buffer may contain NUL characters.\n\nBut, as I said, I don't feel very strongly about it.\n\nThanks,\nTaylor\n"},{"id":"505328","messageId":"cover.1729140565.git.ps@pks.im","threadId":"62313","inReplyTo":"cover.1728629612.git.ps@pks.im","subject":"[PATCH v3 00/10] reftable: stop using `struct strbuf`","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-10-17T04:53:42Z","receivedAt":"2024-10-17T04:53:47Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"Hi,\n\nthis is the third version of my patch series that removes use of `struct\nstrbuf` in the reftable library. The intent of this is to convert the\nreftable library back into a standalone library that can be used in the\ncontext of libgit2.\n\nChanges compared to v2:\n\n  - Provide more context around why we get rid of `stbuf_addf()`.\n\n  - Fix a commit message type.\n\n  - Provide better docs for `reftable_buf_add()`.\n\nThanks!\n\nPatrick\n\nPatrick Steinhardt (10):\n  reftable: stop using `strbuf_addbuf()`\n  reftable: stop using `strbuf_addf()`\n  reftable/basics: provide new `reftable_buf` interface\n  reftable: convert from `strbuf` to `reftable_buf`\n  reftable/blocksource: adapt interface name\n  t/unit-tests: check for `reftable_buf` allocation errors\n  reftable/stack: adapt `format_name()` to handle allocation failures\n  reftable/record: adapt `reftable_record_key()` to handle allocation\n    failures\n  reftable/stack: adapt `stack_filename()` to handle allocation failures\n  reftable: handle trivial `reftable_buf` errors\n\n reftable/basics.c                   |  76 +++++++++-\n reftable/basics.h                   |  61 +++++++-\n reftable/block.c                    |  61 +++++---\n reftable/block.h                    |  14 +-\n reftable/blocksource.c              |  30 ++--\n reftable/blocksource.h              |   5 +-\n reftable/iter.c                     |   9 +-\n reftable/iter.h                     |   8 +-\n reftable/reader.c                   |  27 ++--\n reftable/record.c                   | 114 ++++++++------\n reftable/record.h                   |  21 +--\n reftable/stack.c                    | 221 ++++++++++++++++++----------\n reftable/system.h                   |   1 -\n reftable/writer.c                   | 102 ++++++++-----\n reftable/writer.h                   |   2 +-\n t/unit-tests/lib-reftable.c         |   4 +-\n t/unit-tests/lib-reftable.h         |   7 +-\n t/unit-tests/t-reftable-basics.c    |  16 +-\n t/unit-tests/t-reftable-block.c     |  53 +++----\n t/unit-tests/t-reftable-merged.c    |  32 ++--\n t/unit-tests/t-reftable-reader.c    |  12 +-\n t/unit-tests/t-reftable-readwrite.c | 134 +++++++++--------\n t/unit-tests/t-reftable-record.c    |  74 +++++-----\n t/unit-tests/t-reftable-stack.c     |  96 ++++++------\n 24 files changed, 728 insertions(+), 452 deletions(-)\n\nRange-diff against v2:\n 1:  7408482c152 =  1:  7408482c152 reftable: stop using `strbuf_addbuf()`\n 2:  6a7333b275e !  2:  634fd3c35f5 reftable: stop using `strbuf_addf()`\n    @@ Commit message\n         reftable: stop using `strbuf_addf()`\n     \n         We're about to introduce our own `reftable_buf` type to replace\n    -    `strbuf`. Get rid of the seldomly-used `strbuf_addf()` function such\n    -    that we have to reimplement one less function.\n    +    `strbuf`. One function we'll have to convert is `strbuf_addf()`, which\n    +    is used in a handful of places. This function uses `snprintf()`\n    +    internally, which makes porting it a bit more involved:\n    +\n    +      - It is not available on all platforms.\n    +\n    +      - Some platforms like Windows have broken implementations.\n    +\n    +    So by using `snprintf()` we'd also push the burden on downstream users\n    +    of the reftable library to make available a properly working version of\n    +    it.\n    +\n    +    Most callsites of `strbuf_addf()` are trivial to convert to not using\n    +    it. We do end up using `snprintf()` in our unit tests, but that isn't\n    +    much of a problem for downstream users of the reftable library.\n     \n         While at it, remove a useless call to `strbuf_reset()` in\n         `t_reftable_stack_auto_compaction_with_locked_tables()`. We don't write\n 3:  0ddc8c0c896 !  3:  53c5f667f28 reftable/basics: provide new `reftable_buf` interface\n    @@ Commit message\n             to make things work, which is not all that sensible.\n     \n           - The `strbuf` interface does not use the pluggable allocators that\n    -        can be set up via `refatble_set_alloc()`.\n    +        can be set up via `reftable_set_alloc()`.\n     \n         So we have good reasons to use our own type, and the implementation is\n         rather trivial. Implement our own type. Conversion of the reftable\n 4:  e1ff1af1f30 !  4:  7c7ccc5d966 reftable: convert from `strbuf` to `reftable_buf`\n    @@ reftable/basics.c: int names_equal(const char **a, const char **b)\n      \tfor (; p < a->len && p < b->len; p++) {\n     \n      ## reftable/basics.h ##\n    +@@ reftable/basics.h: int reftable_buf_setlen(struct reftable_buf *buf, size_t len);\n    + int reftable_buf_cmp(const struct reftable_buf *a, const struct reftable_buf *b);\n    + \n    + /*\n    +- * Add the given bytes to the buffer. Returns 0 on success,\n    ++ * Append `len` bytes from `data` to the buffer. This function works with\n    ++ * arbitrary byte sequences, including ones that contain embedded NUL\n    ++ * characters. As such, we use `void *` as input type. Returns 0 on success,\n    +  * REFTABLE_OUT_OF_MEMORY_ERROR on allocation failure.\n    +  */\n    + int reftable_buf_add(struct reftable_buf *buf, const void *data, size_t len);\n     @@ reftable/basics.h: char *reftable_strdup(const char *str);\n      #endif\n      \n 5:  fe8c9ace463 =  5:  f9632860933 reftable/blocksource: adapt interface name\n 6:  8c98745233a =  6:  d850a2fe7d0 t/unit-tests: check for `reftable_buf` allocation errors\n 7:  1f08163009b =  7:  8f8e2ca3962 reftable/stack: adapt `format_name()` to handle allocation failures\n 8:  5798d76d7a4 =  8:  268e4cd6fc6 reftable/record: adapt `reftable_record_key()` to handle allocation failures\n 9:  a9582d51dd1 =  9:  245a428842a reftable/stack: adapt `stack_filename()` to handle allocation failures\n10:  90819c90f38 = 10:  4b51ea4b628 reftable: handle trivial `reftable_buf` errors\n-- \n2.47.0.72.gef8ce8f3d4.dirty\n\n"},{"id":"505329","messageId":"7408482c152bbf465ecd098059b1477fd38c251a.1729140565.git.ps@pks.im","threadId":"62313","inReplyTo":"cover.1729140565.git.ps@pks.im","subject":"[PATCH v3 01/10] reftable: stop using `strbuf_addbuf()`","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-10-17T04:53:45Z","receivedAt":"2024-10-17T04:53:48Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"We're about to introduce our own `reftable_buf` type to replace\n`strbuf`. Get rid of the seldomly-used `strbuf_addbuf()` function such\nthat we have to reimplement one less function.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n reftable/block.c  | 2 +-\n reftable/record.c | 6 +++---\n reftable/writer.c | 7 ++++---\n 3 files changed, 8 insertions(+), 7 deletions(-)\n\ndiff --git a/reftable/block.c b/reftable/block.c\nindex 8d41a2f99ed..cd4180eac7b 100644\n--- a/reftable/block.c\n+++ b/reftable/block.c\n@@ -60,7 +60,7 @@ static int block_writer_register_restart(struct block_writer *w, int n,\n \tw->next += n;\n \n \tstrbuf_reset(&w->last_key);\n-\tstrbuf_addbuf(&w->last_key, key);\n+\tstrbuf_add(&w->last_key, key->buf, key->len);\n \tw->entries++;\n \treturn 0;\n }\ndiff --git a/reftable/record.c b/reftable/record.c\nindex 30d563e16d3..87157f2c386 100644\n--- a/reftable/record.c\n+++ b/reftable/record.c\n@@ -1031,7 +1031,7 @@ static void reftable_index_record_key(const void *r, struct strbuf *dest)\n {\n \tconst struct reftable_index_record *rec = r;\n \tstrbuf_reset(dest);\n-\tstrbuf_addbuf(dest, &rec->last_key);\n+\tstrbuf_add(dest, rec->last_key.buf, rec->last_key.len);\n }\n \n static int reftable_index_record_copy_from(void *rec, const void *src_rec,\n@@ -1041,7 +1041,7 @@ static int reftable_index_record_copy_from(void *rec, const void *src_rec,\n \tconst struct reftable_index_record *src = src_rec;\n \n \tstrbuf_reset(&dst->last_key);\n-\tstrbuf_addbuf(&dst->last_key, &src->last_key);\n+\tstrbuf_add(&dst->last_key, src->last_key.buf, src->last_key.len);\n \tdst->offset = src->offset;\n \n \treturn 0;\n@@ -1085,7 +1085,7 @@ static int reftable_index_record_decode(void *rec, struct strbuf key,\n \tint n = 0;\n \n \tstrbuf_reset(&r->last_key);\n-\tstrbuf_addbuf(&r->last_key, &key);\n+\tstrbuf_add(&r->last_key, key.buf, key.len);\n \n \tn = get_var_int(&r->offset, &in);\n \tif (n < 0)\ndiff --git a/reftable/writer.c b/reftable/writer.c\nindex b032a47decb..031d8149a9c 100644\n--- a/reftable/writer.c\n+++ b/reftable/writer.c\n@@ -225,7 +225,7 @@ static int writer_index_hash(struct reftable_writer *w, struct strbuf *hash)\n \t\t*key = empty;\n \n \t\tstrbuf_reset(&key->hash);\n-\t\tstrbuf_addbuf(&key->hash, hash);\n+\t\tstrbuf_add(&key->hash, hash->buf, hash->len);\n \t\ttree_insert(&w->obj_index_tree, key,\n \t\t\t    &obj_index_tree_node_compare);\n \t} else {\n@@ -256,7 +256,7 @@ static int writer_add_record(struct reftable_writer *w,\n \t}\n \n \tstrbuf_reset(&w->last_key);\n-\tstrbuf_addbuf(&w->last_key, &key);\n+\tstrbuf_add(&w->last_key, key.buf, key.len);\n \tif (!w->block_writer) {\n \t\terr = writer_reinit_block_writer(w, reftable_record_type(rec));\n \t\tif (err < 0)\n@@ -778,7 +778,8 @@ static int writer_flush_nonempty_block(struct reftable_writer *w)\n \n \tindex_record.offset = w->next;\n \tstrbuf_reset(&index_record.last_key);\n-\tstrbuf_addbuf(&index_record.last_key, &w->block_writer->last_key);\n+\tstrbuf_add(&index_record.last_key, w->block_writer->last_key.buf,\n+\t\t   w->block_writer->last_key.len);\n \tw->index[w->index_len] = index_record;\n \tw->index_len++;\n \n-- \n2.47.0.72.gef8ce8f3d4.dirty\n\n"},{"id":"505330","messageId":"634fd3c35f5b314093db613d71c83f06bcae0443.1729140565.git.ps@pks.im","threadId":"62313","inReplyTo":"cover.1729140565.git.ps@pks.im","subject":"[PATCH v3 02/10] reftable: stop using `strbuf_addf()`","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-10-17T04:53:47Z","receivedAt":"2024-10-17T04:53:51Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"We're about to introduce our own `reftable_buf` type to replace\n`strbuf`. One function we'll have to convert is `strbuf_addf()`, which\nis used in a handful of places. This function uses `snprintf()`\ninternally, which makes porting it a bit more involved:\n\n  - It is not available on all platforms.\n\n  - Some platforms like Windows have broken implementations.\n\nSo by using `snprintf()` we'd also push the burden on downstream users\nof the reftable library to make available a properly working version of\nit.\n\nMost callsites of `strbuf_addf()` are trivial to convert to not using\nit. We do end up using `snprintf()` in our unit tests, but that isn't\nmuch of a problem for downstream users of the reftable library.\n\nWhile at it, remove a useless call to `strbuf_reset()` in\n`t_reftable_stack_auto_compaction_with_locked_tables()`. We don't write\nto the buffer before this and initialize it with `STRBUF_INIT`, so there\nis no need to reset anything.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n reftable/stack.c                    | 18 ++++++++-----\n t/unit-tests/t-reftable-block.c     |  7 +++--\n t/unit-tests/t-reftable-readwrite.c | 20 +++++++-------\n t/unit-tests/t-reftable-stack.c     | 42 ++++++++++++++++-------------\n 4 files changed, 50 insertions(+), 37 deletions(-)\n\ndiff --git a/reftable/stack.c b/reftable/stack.c\nindex 7e617c25914..d7bc1187dfb 100644\n--- a/reftable/stack.c\n+++ b/reftable/stack.c\n@@ -1387,12 +1387,18 @@ static int stack_compact_range(struct reftable_stack *st,\n \t * have just written. In case the compacted table became empty we\n \t * simply skip writing it.\n \t */\n-\tfor (i = 0; i < first_to_replace; i++)\n-\t\tstrbuf_addf(&tables_list_buf, \"%s\\n\", names[i]);\n-\tif (!is_empty_table)\n-\t\tstrbuf_addf(&tables_list_buf, \"%s\\n\", new_table_name.buf);\n-\tfor (i = last_to_replace + 1; names[i]; i++)\n-\t\tstrbuf_addf(&tables_list_buf, \"%s\\n\", names[i]);\n+\tfor (i = 0; i < first_to_replace; i++) {\n+\t\tstrbuf_addstr(&tables_list_buf, names[i]);\n+\t\tstrbuf_addstr(&tables_list_buf, \"\\n\");\n+\t}\n+\tif (!is_empty_table) {\n+\t\tstrbuf_addstr(&tables_list_buf, new_table_name.buf);\n+\t\tstrbuf_addstr(&tables_list_buf, \"\\n\");\n+\t}\n+\tfor (i = last_to_replace + 1; names[i]; i++) {\n+\t\tstrbuf_addstr(&tables_list_buf, names[i]);\n+\t\tstrbuf_addstr(&tables_list_buf, \"\\n\");\n+\t}\n \n \terr = write_in_full(get_lock_file_fd(&tables_list_lock),\n \t\t\t    tables_list_buf.buf, tables_list_buf.len);\ndiff --git a/t/unit-tests/t-reftable-block.c b/t/unit-tests/t-reftable-block.c\nindex d470060e8be..8077bbc5e7a 100644\n--- a/t/unit-tests/t-reftable-block.c\n+++ b/t/unit-tests/t-reftable-block.c\n@@ -308,10 +308,13 @@ static void t_index_block_read_write(void)\n \tcheck(!ret);\n \n \tfor (i = 0; i < N; i++) {\n-\t\tstrbuf_init(&recs[i].u.idx.last_key, 9);\n+\t\tchar buf[128];\n+\n+\t\tsnprintf(buf, sizeof(buf), \"branch%02\"PRIuMAX, (uintmax_t)i);\n \n+\t\tstrbuf_init(&recs[i].u.idx.last_key, 9);\n \t\trecs[i].type = BLOCK_TYPE_INDEX;\n-\t\tstrbuf_addf(&recs[i].u.idx.last_key, \"branch%02\"PRIuMAX, (uintmax_t)i);\n+\t\tstrbuf_addstr(&recs[i].u.idx.last_key, buf);\n \t\trecs[i].u.idx.offset = i;\n \n \t\tret = block_writer_add(&bw, &recs[i]);\ndiff --git a/t/unit-tests/t-reftable-readwrite.c b/t/unit-tests/t-reftable-readwrite.c\nindex 27ce84445e8..5f59b0ad6ad 100644\n--- a/t/unit-tests/t-reftable-readwrite.c\n+++ b/t/unit-tests/t-reftable-readwrite.c\n@@ -753,12 +753,13 @@ static void t_write_multiple_indices(void)\n \tstruct reftable_write_options opts = {\n \t\t.block_size = 100,\n \t};\n-\tstruct strbuf writer_buf = STRBUF_INIT, buf = STRBUF_INIT;\n+\tstruct strbuf writer_buf = STRBUF_INIT;\n \tstruct reftable_block_source source = { 0 };\n \tstruct reftable_iterator it = { 0 };\n \tconst struct reftable_stats *stats;\n \tstruct reftable_writer *writer;\n \tstruct reftable_reader *reader;\n+\tchar buf[128];\n \tint err, i;\n \n \twriter = t_reftable_strbuf_writer(&writer_buf, &opts);\n@@ -770,9 +771,8 @@ static void t_write_multiple_indices(void)\n \t\t\t.value.val1 = {i},\n \t\t};\n \n-\t\tstrbuf_reset(&buf);\n-\t\tstrbuf_addf(&buf, \"refs/heads/%04d\", i);\n-\t\tref.refname = buf.buf,\n+\t\tsnprintf(buf, sizeof(buf), \"refs/heads/%04d\", i);\n+\t\tref.refname = buf;\n \n \t\terr = reftable_writer_add_ref(writer, &ref);\n \t\tcheck(!err);\n@@ -788,9 +788,8 @@ static void t_write_multiple_indices(void)\n \t\t\t},\n \t\t};\n \n-\t\tstrbuf_reset(&buf);\n-\t\tstrbuf_addf(&buf, \"refs/heads/%04d\", i);\n-\t\tlog.refname = buf.buf,\n+\t\tsnprintf(buf, sizeof(buf), \"refs/heads/%04d\", i);\n+\t\tlog.refname = buf;\n \n \t\terr = reftable_writer_add_log(writer, &log);\n \t\tcheck(!err);\n@@ -824,7 +823,6 @@ static void t_write_multiple_indices(void)\n \treftable_writer_free(writer);\n \treftable_reader_decref(reader);\n \tstrbuf_release(&writer_buf);\n-\tstrbuf_release(&buf);\n }\n \n static void t_write_multi_level_index(void)\n@@ -848,10 +846,10 @@ static void t_write_multi_level_index(void)\n \t\t\t.value_type = REFTABLE_REF_VAL1,\n \t\t\t.value.val1 = {i},\n \t\t};\n+\t\tchar buf[128];\n \n-\t\tstrbuf_reset(&buf);\n-\t\tstrbuf_addf(&buf, \"refs/heads/%03\" PRIuMAX, (uintmax_t)i);\n-\t\tref.refname = buf.buf,\n+\t\tsnprintf(buf, sizeof(buf), \"refs/heads/%03\" PRIuMAX, (uintmax_t)i);\n+\t\tref.refname = buf;\n \n \t\terr = reftable_writer_add_ref(writer, &ref);\n \t\tcheck(!err);\ndiff --git a/t/unit-tests/t-reftable-stack.c b/t/unit-tests/t-reftable-stack.c\nindex 874095b9ee2..b56ea774312 100644\n--- a/t/unit-tests/t-reftable-stack.c\n+++ b/t/unit-tests/t-reftable-stack.c\n@@ -105,7 +105,6 @@ static int write_test_ref(struct reftable_writer *wr, void *arg)\n static void write_n_ref_tables(struct reftable_stack *st,\n \t\t\t       size_t n)\n {\n-\tstruct strbuf buf = STRBUF_INIT;\n \tint disable_auto_compact;\n \tint err;\n \n@@ -117,10 +116,10 @@ static void write_n_ref_tables(struct reftable_stack *st,\n \t\t\t.update_index = reftable_stack_next_update_index(st),\n \t\t\t.value_type = REFTABLE_REF_VAL1,\n \t\t};\n+\t\tchar buf[128];\n \n-\t\tstrbuf_reset(&buf);\n-\t\tstrbuf_addf(&buf, \"refs/heads/branch-%04\"PRIuMAX, (uintmax_t)i);\n-\t\tref.refname = buf.buf;\n+\t\tsnprintf(buf, sizeof(buf), \"refs/heads/branch-%04\"PRIuMAX, (uintmax_t)i);\n+\t\tref.refname = buf;\n \t\tt_reftable_set_hash(ref.value.val1, i, GIT_SHA1_FORMAT_ID);\n \n \t\terr = reftable_stack_add(st, &write_test_ref, &ref);\n@@ -128,7 +127,6 @@ static void write_n_ref_tables(struct reftable_stack *st,\n \t}\n \n \tst->opts.disable_auto_compact = disable_auto_compact;\n-\tstrbuf_release(&buf);\n }\n \n struct write_log_arg {\n@@ -434,7 +432,10 @@ static void t_reftable_stack_auto_compaction_fails_gracefully(void)\n \t * Adding a new table to the stack should not be impacted by this, even\n \t * though auto-compaction will now fail.\n \t */\n-\tstrbuf_addf(&table_path, \"%s/%s.lock\", dir, st->readers[0]->name);\n+\tstrbuf_addstr(&table_path, dir);\n+\tstrbuf_addstr(&table_path, \"/\");\n+\tstrbuf_addstr(&table_path, st->readers[0]->name);\n+\tstrbuf_addstr(&table_path, \".lock\");\n \twrite_file_buf(table_path.buf, \"\", 0);\n \n \tref.update_index = 2;\n@@ -1077,8 +1078,10 @@ static void t_reftable_stack_auto_compaction_with_locked_tables(void)\n \t * size, we expect that auto-compaction will want to compact all of the\n \t * tables. Locking any of the tables will keep it from doing so.\n \t */\n-\tstrbuf_reset(&buf);\n-\tstrbuf_addf(&buf, \"%s/%s.lock\", dir, st->readers[2]->name);\n+\tstrbuf_addstr(&buf, dir);\n+\tstrbuf_addstr(&buf, \"/\");\n+\tstrbuf_addstr(&buf, st->readers[2]->name);\n+\tstrbuf_addstr(&buf, \".lock\");\n \twrite_file_buf(buf.buf, \"\", 0);\n \n \t/*\n@@ -1101,7 +1104,6 @@ static void t_reftable_stack_add_performs_auto_compaction(void)\n {\n \tstruct reftable_write_options opts = { 0 };\n \tstruct reftable_stack *st = NULL;\n-\tstruct strbuf refname = STRBUF_INIT;\n \tchar *dir = get_tmp_dir(__LINE__);\n \tint err;\n \tsize_t i, n = 20;\n@@ -1115,6 +1117,7 @@ static void t_reftable_stack_add_performs_auto_compaction(void)\n \t\t\t.value_type = REFTABLE_REF_SYMREF,\n \t\t\t.value.symref = (char *) \"master\",\n \t\t};\n+\t\tchar buf[128];\n \n \t\t/*\n \t\t * Disable auto-compaction for all but the last runs. Like this\n@@ -1123,9 +1126,8 @@ static void t_reftable_stack_add_performs_auto_compaction(void)\n \t\t */\n \t\tst->opts.disable_auto_compact = i != n;\n \n-\t\tstrbuf_reset(&refname);\n-\t\tstrbuf_addf(&refname, \"branch-%04\"PRIuMAX, (uintmax_t)i);\n-\t\tref.refname = refname.buf;\n+\t\tsnprintf(buf, sizeof(buf), \"branch-%04\"PRIuMAX, (uintmax_t)i);\n+\t\tref.refname = buf;\n \n \t\terr = reftable_stack_add(st, write_test_ref, &ref);\n \t\tcheck(!err);\n@@ -1142,7 +1144,6 @@ static void t_reftable_stack_add_performs_auto_compaction(void)\n \t}\n \n \treftable_stack_destroy(st);\n-\tstrbuf_release(&refname);\n \tclear_dir(dir);\n }\n \n@@ -1163,8 +1164,10 @@ static void t_reftable_stack_compaction_with_locked_tables(void)\n \tcheck_int(st->merged->readers_len, ==, 3);\n \n \t/* Lock one of the tables that we're about to compact. */\n-\tstrbuf_reset(&buf);\n-\tstrbuf_addf(&buf, \"%s/%s.lock\", dir, st->readers[1]->name);\n+\tstrbuf_addstr(&buf, dir);\n+\tstrbuf_addstr(&buf, \"/\");\n+\tstrbuf_addstr(&buf, st->readers[1]->name);\n+\tstrbuf_addstr(&buf, \".lock\");\n \twrite_file_buf(buf.buf, \"\", 0);\n \n \t/*\n@@ -1321,10 +1324,13 @@ static void t_reftable_stack_reload_with_missing_table(void)\n \t * our old readers. This should trigger a partial reload of the stack,\n \t * where we try to reuse our old readers.\n \t*/\n-\tstrbuf_addf(&content, \"%s\\n\", st->readers[0]->name);\n-\tstrbuf_addf(&content, \"%s\\n\", st->readers[1]->name);\n+\tstrbuf_addstr(&content, st->readers[0]->name);\n+\tstrbuf_addstr(&content, \"\\n\");\n+\tstrbuf_addstr(&content, st->readers[1]->name);\n+\tstrbuf_addstr(&content, \"\\n\");\n \tstrbuf_addstr(&content, \"garbage\\n\");\n-\tstrbuf_addf(&table_path, \"%s.lock\", st->list_file);\n+\tstrbuf_addstr(&table_path, st->list_file);\n+\tstrbuf_addstr(&table_path, \".lock\");\n \twrite_file_buf(table_path.buf, content.buf, content.len);\n \terr = rename(table_path.buf, st->list_file);\n \tcheck(!err);\n-- \n2.47.0.72.gef8ce8f3d4.dirty\n\n"},{"id":"505331","messageId":"53c5f667f28c89ebcf023055423af24920e8c0ca.1729140565.git.ps@pks.im","threadId":"62313","inReplyTo":"cover.1729140565.git.ps@pks.im","subject":"[PATCH v3 03/10] reftable/basics: provide new `reftable_buf` interface","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-10-17T04:53:50Z","receivedAt":"2024-10-17T04:53:56Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"Implement a new `reftable_buf` interface that will replace Git's own\n`strbuf` interface. This is done due to three reasons:\n\n  - The `strbuf` interfaces do not handle memory allocation failures and\n    instead causes us to die. This is okay in the context of Git, but is\n    not in the context of the reftable library, which is supposed to be\n    usable by third-party applications.\n\n  - The `strbuf` interface is quite deeply tied into Git, which makes it\n    hard to use the reftable library as a standalone library. Any\n    dependent would have to carefully extract the relevant parts of it\n    to make things work, which is not all that sensible.\n\n  - The `strbuf` interface does not use the pluggable allocators that\n    can be set up via `reftable_set_alloc()`.\n\nSo we have good reasons to use our own type, and the implementation is\nrather trivial. Implement our own type. Conversion of the reftable\nlibrary will be handled in subsequent commits.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n reftable/basics.c | 74 +++++++++++++++++++++++++++++++++++++++++++++++\n reftable/basics.h | 56 +++++++++++++++++++++++++++++++++++\n 2 files changed, 130 insertions(+)\n\ndiff --git a/reftable/basics.c b/reftable/basics.c\nindex 9a949e5cf80..65ad761da0b 100644\n--- a/reftable/basics.c\n+++ b/reftable/basics.c\n@@ -9,6 +9,7 @@ license that can be found in the LICENSE file or at\n #define REFTABLE_ALLOW_BANNED_ALLOCATORS\n #include \"basics.h\"\n #include \"reftable-basics.h\"\n+#include \"reftable-error.h\"\n \n static void *(*reftable_malloc_ptr)(size_t sz);\n static void *(*reftable_realloc_ptr)(void *, size_t);\n@@ -69,6 +70,79 @@ void reftable_set_alloc(void *(*malloc)(size_t),\n \treftable_free_ptr = free;\n }\n \n+void reftable_buf_init(struct reftable_buf *buf)\n+{\n+\tstruct reftable_buf empty = REFTABLE_BUF_INIT;\n+\t*buf = empty;\n+}\n+\n+void reftable_buf_release(struct reftable_buf *buf)\n+{\n+\treftable_free(buf->buf);\n+\treftable_buf_init(buf);\n+}\n+\n+void reftable_buf_reset(struct reftable_buf *buf)\n+{\n+\tif (buf->alloc) {\n+\t\tbuf->len = 0;\n+\t\tbuf->buf[0] = '\\0';\n+\t}\n+}\n+\n+int reftable_buf_setlen(struct reftable_buf *buf, size_t len)\n+{\n+\tif (len > buf->len)\n+\t\treturn -1;\n+\tif (len == buf->len)\n+\t\treturn 0;\n+\tbuf->buf[len] = '\\0';\n+\tbuf->len = len;\n+\treturn 0;\n+}\n+\n+int reftable_buf_cmp(const struct reftable_buf *a, const struct reftable_buf *b)\n+{\n+\tsize_t len = a->len < b->len ? a->len : b->len;\n+\tif (len) {\n+\t\tint cmp = memcmp(a->buf, b->buf, len);\n+\t\tif (cmp)\n+\t\t\treturn cmp;\n+\t}\n+\treturn a->len < b->len ? -1 : a->len != b->len;\n+}\n+\n+int reftable_buf_add(struct reftable_buf *buf, const void *data, size_t len)\n+{\n+\tsize_t newlen = buf->len + len;\n+\n+\tif (newlen + 1 > buf->alloc) {\n+\t\tchar *reallocated = buf->buf;\n+\t\tREFTABLE_ALLOC_GROW(reallocated, newlen + 1, buf->alloc);\n+\t\tif (!reallocated)\n+\t\t\treturn REFTABLE_OUT_OF_MEMORY_ERROR;\n+\t\tbuf->buf = reallocated;\n+\t}\n+\n+\tmemcpy(buf->buf + buf->len, data, len);\n+\tbuf->buf[newlen] = '\\0';\n+\tbuf->len = newlen;\n+\n+\treturn 0;\n+}\n+\n+int reftable_buf_addstr(struct reftable_buf *buf, const char *s)\n+{\n+\treturn reftable_buf_add(buf, s, strlen(s));\n+}\n+\n+char *reftable_buf_detach(struct reftable_buf *buf)\n+{\n+\tchar *result = buf->buf;\n+\treftable_buf_init(buf);\n+\treturn result;\n+}\n+\n void put_be24(uint8_t *out, uint32_t i)\n {\n \tout[0] = (uint8_t)((i >> 16) & 0xff);\ndiff --git a/reftable/basics.h b/reftable/basics.h\nindex 4c9ef0fe6c5..bd33c34deae 100644\n--- a/reftable/basics.h\n+++ b/reftable/basics.h\n@@ -16,6 +16,62 @@ license that can be found in the LICENSE file or at\n #include \"system.h\"\n #include \"reftable-basics.h\"\n \n+struct reftable_buf {\n+\tsize_t alloc;\n+\tsize_t len;\n+\tchar *buf;\n+};\n+#define REFTABLE_BUF_INIT { 0 }\n+\n+/*\n+ * Initialize the buffer such that it is ready for use. This is equivalent to\n+ * using REFTABLE_BUF_INIT for stack-allocated variables.\n+ */\n+void reftable_buf_init(struct reftable_buf *buf);\n+\n+/*\n+ * Release memory associated with the buffer. The buffer is reinitialized such\n+ * that it can be reused for subsequent operations.\n+ */\n+void reftable_buf_release(struct reftable_buf *buf);\n+\n+/*\n+ * Reset the buffer such that it is effectively empty, without releasing the\n+ * memory that this structure holds on to. This is equivalent to calling\n+ * `reftable_buf_setlen(buf, 0)`.\n+ */\n+void reftable_buf_reset(struct reftable_buf *buf);\n+\n+/*\n+ * Trim the buffer to a shorter length by updating the `len` member and writing\n+ * a NUL byte to `buf[len]`. Returns 0 on success, -1 when `len` points outside\n+ * of the array.\n+ */\n+int reftable_buf_setlen(struct reftable_buf *buf, size_t len);\n+\n+/*\n+ * Lexicographically compare the two buffers. Returns 0 when both buffers have\n+ * the same contents, -1 when `a` is lexicographically smaller than `b`, and 1\n+ * otherwise.\n+ */\n+int reftable_buf_cmp(const struct reftable_buf *a, const struct reftable_buf *b);\n+\n+/*\n+ * Add the given bytes to the buffer. Returns 0 on success,\n+ * REFTABLE_OUT_OF_MEMORY_ERROR on allocation failure.\n+ */\n+int reftable_buf_add(struct reftable_buf *buf, const void *data, size_t len);\n+\n+/* Equivalent to `reftable_buf_add(buf, s, strlen(s))`. */\n+int reftable_buf_addstr(struct reftable_buf *buf, const char *s);\n+\n+/*\n+ * Detach the buffer from the structure such that the underlying memory is now\n+ * owned by the caller. The buffer is reinitialized such that it can be reused\n+ * for subsequent operations.\n+ */\n+char *reftable_buf_detach(struct reftable_buf *buf);\n+\n /* Bigendian en/decoding of integers */\n \n void put_be24(uint8_t *out, uint32_t i);\n-- \n2.47.0.72.gef8ce8f3d4.dirty\n\n"},{"id":"505332","messageId":"7c7ccc5d96681bc957671a26f4bc5100a95e20fc.1729140565.git.ps@pks.im","threadId":"62313","inReplyTo":"cover.1729140565.git.ps@pks.im","subject":"[PATCH v3 04/10] reftable: convert from `strbuf` to `reftable_buf`","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-10-17T04:53:56Z","receivedAt":"2024-10-17T04:53:59Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"Convert the reftable library to use the `reftable_buf` interface instead\nof the `strbuf` interface. This is mostly a mechanical change via sed(1)\nwith some manual fixes where functions for `strbuf` and `reftable_buf`\ndiffer. The converted code does not yet handle allocation failures. This\nwill be handled in subsequent commits.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n reftable/basics.c                   |   2 +-\n reftable/basics.h                   |   7 +-\n reftable/block.c                    |  34 ++++----\n reftable/block.h                    |  14 ++--\n reftable/blocksource.c              |   6 +-\n reftable/blocksource.h              |   3 +-\n reftable/iter.c                     |   6 +-\n reftable/iter.h                     |   8 +-\n reftable/reader.c                   |  16 ++--\n reftable/record.c                   |  80 +++++++++----------\n reftable/record.h                   |  21 ++---\n reftable/stack.c                    | 120 ++++++++++++++--------------\n reftable/system.h                   |   1 -\n reftable/writer.c                   |  66 +++++++--------\n reftable/writer.h                   |   2 +-\n t/unit-tests/lib-reftable.c         |   4 +-\n t/unit-tests/lib-reftable.h         |   7 +-\n t/unit-tests/t-reftable-basics.c    |  16 ++--\n t/unit-tests/t-reftable-block.c     |  42 +++++-----\n t/unit-tests/t-reftable-merged.c    |  26 +++---\n t/unit-tests/t-reftable-reader.c    |   8 +-\n t/unit-tests/t-reftable-readwrite.c |  92 ++++++++++-----------\n t/unit-tests/t-reftable-record.c    |  74 ++++++++---------\n t/unit-tests/t-reftable-stack.c     |  90 ++++++++++-----------\n 24 files changed, 374 insertions(+), 371 deletions(-)\n\ndiff --git a/reftable/basics.c b/reftable/basics.c\nindex 65ad761da0b..bc4fcc91446 100644\n--- a/reftable/basics.c\n+++ b/reftable/basics.c\n@@ -260,7 +260,7 @@ int names_equal(const char **a, const char **b)\n \treturn a[i] == b[i];\n }\n \n-int common_prefix_size(struct strbuf *a, struct strbuf *b)\n+int common_prefix_size(struct reftable_buf *a, struct reftable_buf *b)\n {\n \tint p = 0;\n \tfor (; p < a->len && p < b->len; p++) {\ndiff --git a/reftable/basics.h b/reftable/basics.h\nindex bd33c34deae..7aa46d7c30d 100644\n--- a/reftable/basics.h\n+++ b/reftable/basics.h\n@@ -57,7 +57,9 @@ int reftable_buf_setlen(struct reftable_buf *buf, size_t len);\n int reftable_buf_cmp(const struct reftable_buf *a, const struct reftable_buf *b);\n \n /*\n- * Add the given bytes to the buffer. Returns 0 on success,\n+ * Append `len` bytes from `data` to the buffer. This function works with\n+ * arbitrary byte sequences, including ones that contain embedded NUL\n+ * characters. As such, we use `void *` as input type. Returns 0 on success,\n  * REFTABLE_OUT_OF_MEMORY_ERROR on allocation failure.\n  */\n int reftable_buf_add(struct reftable_buf *buf, const void *data, size_t len);\n@@ -144,8 +146,7 @@ char *reftable_strdup(const char *str);\n #endif\n \n /* Find the longest shared prefix size of `a` and `b` */\n-struct strbuf;\n-int common_prefix_size(struct strbuf *a, struct strbuf *b);\n+int common_prefix_size(struct reftable_buf *a, struct reftable_buf *b);\n \n int hash_size(uint32_t id);\n \ndiff --git a/reftable/block.c b/reftable/block.c\nindex cd4180eac7b..4f62b823db8 100644\n--- a/reftable/block.c\n+++ b/reftable/block.c\n@@ -38,7 +38,7 @@ int footer_size(int version)\n }\n \n static int block_writer_register_restart(struct block_writer *w, int n,\n-\t\t\t\t\t int is_restart, struct strbuf *key)\n+\t\t\t\t\t int is_restart, struct reftable_buf *key)\n {\n \tint rlen = w->restart_len;\n \tif (rlen >= MAX_RESTARTS) {\n@@ -59,8 +59,8 @@ static int block_writer_register_restart(struct block_writer *w, int n,\n \n \tw->next += n;\n \n-\tstrbuf_reset(&w->last_key);\n-\tstrbuf_add(&w->last_key, key->buf, key->len);\n+\treftable_buf_reset(&w->last_key);\n+\treftable_buf_add(&w->last_key, key->buf, key->len);\n \tw->entries++;\n \treturn 0;\n }\n@@ -98,8 +98,8 @@ uint8_t block_writer_type(struct block_writer *bw)\n    empty key. */\n int block_writer_add(struct block_writer *w, struct reftable_record *rec)\n {\n-\tstruct strbuf empty = STRBUF_INIT;\n-\tstruct strbuf last =\n+\tstruct reftable_buf empty = REFTABLE_BUF_INIT;\n+\tstruct reftable_buf last =\n \t\tw->entries % w->restart_interval == 0 ? empty : w->last_key;\n \tstruct string_view out = {\n \t\t.buf = w->buf + w->next,\n@@ -109,7 +109,7 @@ int block_writer_add(struct block_writer *w, struct reftable_record *rec)\n \tstruct string_view start = out;\n \n \tint is_restart = 0;\n-\tstruct strbuf key = STRBUF_INIT;\n+\tstruct reftable_buf key = REFTABLE_BUF_INIT;\n \tint n = 0;\n \tint err = -1;\n \n@@ -133,7 +133,7 @@ int block_writer_add(struct block_writer *w, struct reftable_record *rec)\n \terr = block_writer_register_restart(w, start.len - out.len, is_restart,\n \t\t\t\t\t    &key);\n done:\n-\tstrbuf_release(&key);\n+\treftable_buf_release(&key);\n \treturn err;\n }\n \n@@ -325,7 +325,7 @@ uint8_t block_reader_type(const struct block_reader *r)\n \treturn r->block.data[r->header_off];\n }\n \n-int block_reader_first_key(const struct block_reader *br, struct strbuf *key)\n+int block_reader_first_key(const struct block_reader *br, struct reftable_buf *key)\n {\n \tint off = br->header_off + 4, n;\n \tstruct string_view in = {\n@@ -334,7 +334,7 @@ int block_reader_first_key(const struct block_reader *br, struct strbuf *key)\n \t};\n \tuint8_t extra = 0;\n \n-\tstrbuf_reset(key);\n+\treftable_buf_reset(key);\n \n \tn = reftable_decode_key(key, &extra, in);\n \tif (n < 0)\n@@ -355,13 +355,13 @@ void block_iter_seek_start(struct block_iter *it, const struct block_reader *br)\n \tit->block = br->block.data;\n \tit->block_len = br->block_len;\n \tit->hash_size = br->hash_size;\n-\tstrbuf_reset(&it->last_key);\n+\treftable_buf_reset(&it->last_key);\n \tit->next_off = br->header_off + 4;\n }\n \n struct restart_needle_less_args {\n \tint error;\n-\tstruct strbuf needle;\n+\tstruct reftable_buf needle;\n \tconst struct block_reader *reader;\n };\n \n@@ -433,7 +433,7 @@ int block_iter_next(struct block_iter *it, struct reftable_record *rec)\n \n void block_iter_reset(struct block_iter *it)\n {\n-\tstrbuf_reset(&it->last_key);\n+\treftable_buf_reset(&it->last_key);\n \tit->next_off = 0;\n \tit->block = NULL;\n \tit->block_len = 0;\n@@ -442,12 +442,12 @@ void block_iter_reset(struct block_iter *it)\n \n void block_iter_close(struct block_iter *it)\n {\n-\tstrbuf_release(&it->last_key);\n-\tstrbuf_release(&it->scratch);\n+\treftable_buf_release(&it->last_key);\n+\treftable_buf_release(&it->scratch);\n }\n \n int block_iter_seek_key(struct block_iter *it, const struct block_reader *br,\n-\t\t\tstruct strbuf *want)\n+\t\t\tstruct reftable_buf *want)\n {\n \tstruct restart_needle_less_args args = {\n \t\t.needle = *want,\n@@ -537,7 +537,7 @@ int block_iter_seek_key(struct block_iter *it, const struct block_reader *br,\n \t\t * with themselves.\n \t\t */\n \t\treftable_record_key(&rec, &it->last_key);\n-\t\tif (strbuf_cmp(&it->last_key, want) >= 0) {\n+\t\tif (reftable_buf_cmp(&it->last_key, want) >= 0) {\n \t\t\tit->next_off = prev_off;\n \t\t\tgoto done;\n \t\t}\n@@ -554,7 +554,7 @@ void block_writer_release(struct block_writer *bw)\n \tREFTABLE_FREE_AND_NULL(bw->zstream);\n \tREFTABLE_FREE_AND_NULL(bw->restarts);\n \tREFTABLE_FREE_AND_NULL(bw->compressed);\n-\tstrbuf_release(&bw->last_key);\n+\treftable_buf_release(&bw->last_key);\n \t/* the block is not owned. */\n }\n \ndiff --git a/reftable/block.h b/reftable/block.h\nindex 18d7ea03373..9a3effa5134 100644\n--- a/reftable/block.h\n+++ b/reftable/block.h\n@@ -38,7 +38,7 @@ struct block_writer {\n \tuint32_t restart_len;\n \tuint32_t restart_cap;\n \n-\tstruct strbuf last_key;\n+\tstruct reftable_buf last_key;\n \tint entries;\n };\n \n@@ -98,7 +98,7 @@ void block_reader_release(struct block_reader *br);\n uint8_t block_reader_type(const struct block_reader *r);\n \n /* Decodes the first key in the block */\n-int block_reader_first_key(const struct block_reader *br, struct strbuf *key);\n+int block_reader_first_key(const struct block_reader *br, struct reftable_buf *key);\n \n /* Iterate over entries in a block */\n struct block_iter {\n@@ -109,13 +109,13 @@ struct block_iter {\n \tint hash_size;\n \n \t/* key for last entry we read. */\n-\tstruct strbuf last_key;\n-\tstruct strbuf scratch;\n+\tstruct reftable_buf last_key;\n+\tstruct reftable_buf scratch;\n };\n \n #define BLOCK_ITER_INIT { \\\n-\t.last_key = STRBUF_INIT, \\\n-\t.scratch = STRBUF_INIT, \\\n+\t.last_key = REFTABLE_BUF_INIT, \\\n+\t.scratch = REFTABLE_BUF_INIT, \\\n }\n \n /* Position `it` at start of the block */\n@@ -123,7 +123,7 @@ void block_iter_seek_start(struct block_iter *it, const struct block_reader *br)\n \n /* Position `it` to the `want` key in the block */\n int block_iter_seek_key(struct block_iter *it, const struct block_reader *br,\n-\t\t\tstruct strbuf *want);\n+\t\t\tstruct reftable_buf *want);\n \n /* return < 0 for error, 0 for OK, > 0 for EOF. */\n int block_iter_next(struct block_iter *it, struct reftable_record *rec);\ndiff --git a/reftable/blocksource.c b/reftable/blocksource.c\nindex a2a6a196d55..d6242d67900 100644\n--- a/reftable/blocksource.c\n+++ b/reftable/blocksource.c\n@@ -27,7 +27,7 @@ static void strbuf_close(void *b UNUSED)\n static int strbuf_read_block(void *v, struct reftable_block *dest, uint64_t off,\n \t\t\t     uint32_t size)\n {\n-\tstruct strbuf *b = v;\n+\tstruct reftable_buf *b = v;\n \tassert(off + size <= b->len);\n \tREFTABLE_CALLOC_ARRAY(dest->data, size);\n \tif (!dest->data)\n@@ -39,7 +39,7 @@ static int strbuf_read_block(void *v, struct reftable_block *dest, uint64_t off,\n \n static uint64_t strbuf_size(void *b)\n {\n-\treturn ((struct strbuf *)b)->len;\n+\treturn ((struct reftable_buf *)b)->len;\n }\n \n static struct reftable_block_source_vtable strbuf_vtable = {\n@@ -50,7 +50,7 @@ static struct reftable_block_source_vtable strbuf_vtable = {\n };\n \n void block_source_from_strbuf(struct reftable_block_source *bs,\n-\t\t\t      struct strbuf *buf)\n+\t\t\t      struct reftable_buf *buf)\n {\n \tassert(!bs->ops);\n \tbs->ops = &strbuf_vtable;\ndiff --git a/reftable/blocksource.h b/reftable/blocksource.h\nindex 659a27b4063..ee3647c6531 100644\n--- a/reftable/blocksource.h\n+++ b/reftable/blocksource.h\n@@ -12,9 +12,10 @@ license that can be found in the LICENSE file or at\n #include \"system.h\"\n \n struct reftable_block_source;\n+struct reftable_buf;\n \n /* Create an in-memory block source for reading reftables */\n void block_source_from_strbuf(struct reftable_block_source *bs,\n-\t\t\t      struct strbuf *buf);\n+\t\t\t      struct reftable_buf *buf);\n \n #endif\ndiff --git a/reftable/iter.c b/reftable/iter.c\nindex d926db653b1..6c193fd31a9 100644\n--- a/reftable/iter.c\n+++ b/reftable/iter.c\n@@ -55,7 +55,7 @@ void iterator_set_empty(struct reftable_iterator *it)\n static void filtering_ref_iterator_close(void *iter_arg)\n {\n \tstruct filtering_ref_iterator *fri = iter_arg;\n-\tstrbuf_release(&fri->oid);\n+\treftable_buf_release(&fri->oid);\n \treftable_iterator_destroy(&fri->it);\n }\n \n@@ -115,7 +115,7 @@ static void indexed_table_ref_iter_close(void *p)\n \tblock_iter_close(&it->cur);\n \treftable_block_done(&it->block_reader.block);\n \treftable_free(it->offsets);\n-\tstrbuf_release(&it->oid);\n+\treftable_buf_release(&it->oid);\n }\n \n static int indexed_table_ref_iter_next_block(struct indexed_table_ref_iter *it)\n@@ -197,7 +197,7 @@ int indexed_table_ref_iter_new(struct indexed_table_ref_iter **dest,\n \n \t*itr = empty;\n \titr->r = r;\n-\tstrbuf_add(&itr->oid, oid, oid_len);\n+\treftable_buf_add(&itr->oid, oid, oid_len);\n \n \titr->offsets = offsets;\n \titr->offset_len = offset_len;\ndiff --git a/reftable/iter.h b/reftable/iter.h\nindex b3225bc7add..40f98893b85 100644\n--- a/reftable/iter.h\n+++ b/reftable/iter.h\n@@ -44,12 +44,12 @@ void iterator_set_empty(struct reftable_iterator *it);\n \n /* iterator that produces only ref records that point to `oid` */\n struct filtering_ref_iterator {\n-\tstruct strbuf oid;\n+\tstruct reftable_buf oid;\n \tstruct reftable_iterator it;\n };\n #define FILTERING_REF_ITERATOR_INIT \\\n \t{                           \\\n-\t\t.oid = STRBUF_INIT  \\\n+\t\t.oid = REFTABLE_BUF_INIT  \\\n \t}\n \n void iterator_from_filtering_ref_iterator(struct reftable_iterator *,\n@@ -60,7 +60,7 @@ void iterator_from_filtering_ref_iterator(struct reftable_iterator *,\n  */\n struct indexed_table_ref_iter {\n \tstruct reftable_reader *r;\n-\tstruct strbuf oid;\n+\tstruct reftable_buf oid;\n \n \t/* mutable */\n \tuint64_t *offsets;\n@@ -75,7 +75,7 @@ struct indexed_table_ref_iter {\n \n #define INDEXED_TABLE_REF_ITER_INIT { \\\n \t.cur = BLOCK_ITER_INIT, \\\n-\t.oid = STRBUF_INIT, \\\n+\t.oid = REFTABLE_BUF_INIT, \\\n }\n \n void iterator_from_indexed_table_ref_iter(struct reftable_iterator *it,\ndiff --git a/reftable/reader.c b/reftable/reader.c\nindex 8d372539220..388f8bf6d7b 100644\n--- a/reftable/reader.c\n+++ b/reftable/reader.c\n@@ -350,8 +350,8 @@ static int table_iter_seek_start(struct table_iter *ti, uint8_t typ, int index)\n static int table_iter_seek_linear(struct table_iter *ti,\n \t\t\t\t  struct reftable_record *want)\n {\n-\tstruct strbuf want_key = STRBUF_INIT;\n-\tstruct strbuf got_key = STRBUF_INIT;\n+\tstruct reftable_buf want_key = REFTABLE_BUF_INIT;\n+\tstruct reftable_buf got_key = REFTABLE_BUF_INIT;\n \tstruct reftable_record rec;\n \tint err;\n \n@@ -401,7 +401,7 @@ static int table_iter_seek_linear(struct table_iter *ti,\n \t\tif (err < 0)\n \t\t\tgoto done;\n \n-\t\tif (strbuf_cmp(&got_key, &want_key) > 0) {\n+\t\tif (reftable_buf_cmp(&got_key, &want_key) > 0) {\n \t\t\ttable_iter_block_done(&next);\n \t\t\tbreak;\n \t\t}\n@@ -422,8 +422,8 @@ static int table_iter_seek_linear(struct table_iter *ti,\n \n done:\n \treftable_record_release(&rec);\n-\tstrbuf_release(&want_key);\n-\tstrbuf_release(&got_key);\n+\treftable_buf_release(&want_key);\n+\treftable_buf_release(&got_key);\n \treturn err;\n }\n \n@@ -431,11 +431,11 @@ static int table_iter_seek_indexed(struct table_iter *ti,\n \t\t\t\t   struct reftable_record *rec)\n {\n \tstruct reftable_record want_index = {\n-\t\t.type = BLOCK_TYPE_INDEX, .u.idx = { .last_key = STRBUF_INIT }\n+\t\t.type = BLOCK_TYPE_INDEX, .u.idx = { .last_key = REFTABLE_BUF_INIT }\n \t};\n \tstruct reftable_record index_result = {\n \t\t.type = BLOCK_TYPE_INDEX,\n-\t\t.u.idx = { .last_key = STRBUF_INIT },\n+\t\t.u.idx = { .last_key = REFTABLE_BUF_INIT },\n \t};\n \tint err;\n \n@@ -765,7 +765,7 @@ static int reftable_reader_refs_for_unindexed(struct reftable_reader *r,\n \t}\n \t*filter = empty;\n \n-\tstrbuf_add(&filter->oid, oid, oid_len);\n+\treftable_buf_add(&filter->oid, oid, oid_len);\n \titerator_from_table_iter(&filter->it, ti);\n \n \titerator_from_filtering_ref_iterator(it, filter);\ndiff --git a/reftable/record.c b/reftable/record.c\nindex 87157f2c386..0182c973437 100644\n--- a/reftable/record.c\n+++ b/reftable/record.c\n@@ -98,7 +98,7 @@ const unsigned char *reftable_ref_record_val2(const struct reftable_ref_record *\n \t}\n }\n \n-static int decode_string(struct strbuf *dest, struct string_view in)\n+static int decode_string(struct reftable_buf *dest, struct string_view in)\n {\n \tint start_len = in.len;\n \tuint64_t tsize = 0;\n@@ -109,8 +109,8 @@ static int decode_string(struct strbuf *dest, struct string_view in)\n \tif (in.len < tsize)\n \t\treturn -1;\n \n-\tstrbuf_reset(dest);\n-\tstrbuf_add(dest, in.buf, tsize);\n+\treftable_buf_reset(dest);\n+\treftable_buf_add(dest, in.buf, tsize);\n \tstring_view_consume(&in, tsize);\n \n \treturn start_len - in.len;\n@@ -133,7 +133,7 @@ static int encode_string(const char *str, struct string_view s)\n }\n \n int reftable_encode_key(int *restart, struct string_view dest,\n-\t\t\tstruct strbuf prev_key, struct strbuf key,\n+\t\t\tstruct reftable_buf prev_key, struct reftable_buf key,\n \t\t\tuint8_t extra)\n {\n \tstruct string_view start = dest;\n@@ -183,7 +183,7 @@ int reftable_decode_keylen(struct string_view in,\n \treturn start_len - in.len;\n }\n \n-int reftable_decode_key(struct strbuf *last_key, uint8_t *extra,\n+int reftable_decode_key(struct reftable_buf *last_key, uint8_t *extra,\n \t\t\tstruct string_view in)\n {\n \tint start_len = in.len;\n@@ -200,19 +200,19 @@ int reftable_decode_key(struct strbuf *last_key, uint8_t *extra,\n \t    prefix_len > last_key->len)\n \t\treturn -1;\n \n-\tstrbuf_setlen(last_key, prefix_len);\n-\tstrbuf_add(last_key, in.buf, suffix_len);\n+\treftable_buf_setlen(last_key, prefix_len);\n+\treftable_buf_add(last_key, in.buf, suffix_len);\n \tstring_view_consume(&in, suffix_len);\n \n \treturn start_len - in.len;\n }\n \n-static void reftable_ref_record_key(const void *r, struct strbuf *dest)\n+static void reftable_ref_record_key(const void *r, struct reftable_buf *dest)\n {\n \tconst struct reftable_ref_record *rec =\n \t\t(const struct reftable_ref_record *)r;\n-\tstrbuf_reset(dest);\n-\tstrbuf_addstr(dest, rec->refname);\n+\treftable_buf_reset(dest);\n+\treftable_buf_addstr(dest, rec->refname);\n }\n \n static int reftable_ref_record_copy_from(void *rec, const void *src_rec,\n@@ -350,9 +350,9 @@ static int reftable_ref_record_encode(const void *rec, struct string_view s,\n \treturn start.len - s.len;\n }\n \n-static int reftable_ref_record_decode(void *rec, struct strbuf key,\n+static int reftable_ref_record_decode(void *rec, struct reftable_buf key,\n \t\t\t\t      uint8_t val_type, struct string_view in,\n-\t\t\t\t      int hash_size, struct strbuf *scratch)\n+\t\t\t\t      int hash_size, struct reftable_buf *scratch)\n {\n \tstruct reftable_ref_record *r = rec;\n \tstruct string_view start = in;\n@@ -415,7 +415,7 @@ static int reftable_ref_record_decode(void *rec, struct strbuf key,\n \t\t\tgoto done;\n \t\t}\n \t\tstring_view_consume(&in, n);\n-\t\tr->value.symref = strbuf_detach(scratch, NULL);\n+\t\tr->value.symref = reftable_buf_detach(scratch);\n \t} break;\n \n \tcase REFTABLE_REF_DELETION:\n@@ -465,12 +465,12 @@ static struct reftable_record_vtable reftable_ref_record_vtable = {\n \t.cmp = &reftable_ref_record_cmp_void,\n };\n \n-static void reftable_obj_record_key(const void *r, struct strbuf *dest)\n+static void reftable_obj_record_key(const void *r, struct reftable_buf *dest)\n {\n \tconst struct reftable_obj_record *rec =\n \t\t(const struct reftable_obj_record *)r;\n-\tstrbuf_reset(dest);\n-\tstrbuf_add(dest, rec->hash_prefix, rec->hash_prefix_len);\n+\treftable_buf_reset(dest);\n+\treftable_buf_add(dest, rec->hash_prefix, rec->hash_prefix_len);\n }\n \n static void reftable_obj_record_release(void *rec)\n@@ -547,10 +547,10 @@ static int reftable_obj_record_encode(const void *rec, struct string_view s,\n \treturn start.len - s.len;\n }\n \n-static int reftable_obj_record_decode(void *rec, struct strbuf key,\n+static int reftable_obj_record_decode(void *rec, struct reftable_buf key,\n \t\t\t\t      uint8_t val_type, struct string_view in,\n \t\t\t\t      int hash_size UNUSED,\n-\t\t\t\t      struct strbuf *scratch UNUSED)\n+\t\t\t\t      struct reftable_buf *scratch UNUSED)\n {\n \tstruct string_view start = in;\n \tstruct reftable_obj_record *r = rec;\n@@ -664,19 +664,19 @@ static struct reftable_record_vtable reftable_obj_record_vtable = {\n \t.cmp = &reftable_obj_record_cmp_void,\n };\n \n-static void reftable_log_record_key(const void *r, struct strbuf *dest)\n+static void reftable_log_record_key(const void *r, struct reftable_buf *dest)\n {\n \tconst struct reftable_log_record *rec =\n \t\t(const struct reftable_log_record *)r;\n \tint len = strlen(rec->refname);\n \tuint8_t i64[8];\n \tuint64_t ts = 0;\n-\tstrbuf_reset(dest);\n-\tstrbuf_add(dest, (uint8_t *)rec->refname, len + 1);\n+\treftable_buf_reset(dest);\n+\treftable_buf_add(dest, (uint8_t *)rec->refname, len + 1);\n \n \tts = (~ts) - rec->update_index;\n \tput_be64(&i64[0], ts);\n-\tstrbuf_add(dest, i64, sizeof(i64));\n+\treftable_buf_add(dest, i64, sizeof(i64));\n }\n \n static int reftable_log_record_copy_from(void *rec, const void *src_rec,\n@@ -807,9 +807,9 @@ static int reftable_log_record_encode(const void *rec, struct string_view s,\n \treturn start.len - s.len;\n }\n \n-static int reftable_log_record_decode(void *rec, struct strbuf key,\n+static int reftable_log_record_decode(void *rec, struct reftable_buf key,\n \t\t\t\t      uint8_t val_type, struct string_view in,\n-\t\t\t\t      int hash_size, struct strbuf *scratch)\n+\t\t\t\t      int hash_size, struct reftable_buf *scratch)\n {\n \tstruct string_view start = in;\n \tstruct reftable_log_record *r = rec;\n@@ -1027,11 +1027,11 @@ static struct reftable_record_vtable reftable_log_record_vtable = {\n \t.cmp = &reftable_log_record_cmp_void,\n };\n \n-static void reftable_index_record_key(const void *r, struct strbuf *dest)\n+static void reftable_index_record_key(const void *r, struct reftable_buf *dest)\n {\n \tconst struct reftable_index_record *rec = r;\n-\tstrbuf_reset(dest);\n-\tstrbuf_add(dest, rec->last_key.buf, rec->last_key.len);\n+\treftable_buf_reset(dest);\n+\treftable_buf_add(dest, rec->last_key.buf, rec->last_key.len);\n }\n \n static int reftable_index_record_copy_from(void *rec, const void *src_rec,\n@@ -1040,8 +1040,8 @@ static int reftable_index_record_copy_from(void *rec, const void *src_rec,\n \tstruct reftable_index_record *dst = rec;\n \tconst struct reftable_index_record *src = src_rec;\n \n-\tstrbuf_reset(&dst->last_key);\n-\tstrbuf_add(&dst->last_key, src->last_key.buf, src->last_key.len);\n+\treftable_buf_reset(&dst->last_key);\n+\treftable_buf_add(&dst->last_key, src->last_key.buf, src->last_key.len);\n \tdst->offset = src->offset;\n \n \treturn 0;\n@@ -1050,7 +1050,7 @@ static int reftable_index_record_copy_from(void *rec, const void *src_rec,\n static void reftable_index_record_release(void *rec)\n {\n \tstruct reftable_index_record *idx = rec;\n-\tstrbuf_release(&idx->last_key);\n+\treftable_buf_release(&idx->last_key);\n }\n \n static uint8_t reftable_index_record_val_type(const void *rec UNUSED)\n@@ -1074,18 +1074,18 @@ static int reftable_index_record_encode(const void *rec, struct string_view out,\n \treturn start.len - out.len;\n }\n \n-static int reftable_index_record_decode(void *rec, struct strbuf key,\n+static int reftable_index_record_decode(void *rec, struct reftable_buf key,\n \t\t\t\t\tuint8_t val_type UNUSED,\n \t\t\t\t\tstruct string_view in,\n \t\t\t\t\tint hash_size UNUSED,\n-\t\t\t\t\tstruct strbuf *scratch UNUSED)\n+\t\t\t\t\tstruct reftable_buf *scratch UNUSED)\n {\n \tstruct string_view start = in;\n \tstruct reftable_index_record *r = rec;\n \tint n = 0;\n \n-\tstrbuf_reset(&r->last_key);\n-\tstrbuf_add(&r->last_key, key.buf, key.len);\n+\treftable_buf_reset(&r->last_key);\n+\treftable_buf_add(&r->last_key, key.buf, key.len);\n \n \tn = get_var_int(&r->offset, &in);\n \tif (n < 0)\n@@ -1101,14 +1101,14 @@ static int reftable_index_record_equal(const void *a, const void *b,\n \tstruct reftable_index_record *ia = (struct reftable_index_record *) a;\n \tstruct reftable_index_record *ib = (struct reftable_index_record *) b;\n \n-\treturn ia->offset == ib->offset && !strbuf_cmp(&ia->last_key, &ib->last_key);\n+\treturn ia->offset == ib->offset && !reftable_buf_cmp(&ia->last_key, &ib->last_key);\n }\n \n static int reftable_index_record_cmp(const void *_a, const void *_b)\n {\n \tconst struct reftable_index_record *a = _a;\n \tconst struct reftable_index_record *b = _b;\n-\treturn strbuf_cmp(&a->last_key, &b->last_key);\n+\treturn reftable_buf_cmp(&a->last_key, &b->last_key);\n }\n \n static struct reftable_record_vtable reftable_index_record_vtable = {\n@@ -1124,7 +1124,7 @@ static struct reftable_record_vtable reftable_index_record_vtable = {\n \t.cmp = &reftable_index_record_cmp,\n };\n \n-void reftable_record_key(struct reftable_record *rec, struct strbuf *dest)\n+void reftable_record_key(struct reftable_record *rec, struct reftable_buf *dest)\n {\n \treftable_record_vtable(rec)->key(reftable_record_data(rec), dest);\n }\n@@ -1151,9 +1151,9 @@ uint8_t reftable_record_val_type(struct reftable_record *rec)\n \treturn reftable_record_vtable(rec)->val_type(reftable_record_data(rec));\n }\n \n-int reftable_record_decode(struct reftable_record *rec, struct strbuf key,\n+int reftable_record_decode(struct reftable_record *rec, struct reftable_buf key,\n \t\t\t   uint8_t extra, struct string_view src, int hash_size,\n-\t\t\t   struct strbuf *scratch)\n+\t\t\t   struct reftable_buf *scratch)\n {\n \treturn reftable_record_vtable(rec)->decode(reftable_record_data(rec),\n \t\t\t\t\t\t   key, extra, src, hash_size,\n@@ -1294,7 +1294,7 @@ void reftable_record_init(struct reftable_record *rec, uint8_t typ)\n \tcase BLOCK_TYPE_OBJ:\n \t\treturn;\n \tcase BLOCK_TYPE_INDEX:\n-\t\tstrbuf_init(&rec->u.idx.last_key, 0);\n+\t\treftable_buf_init(&rec->u.idx.last_key);\n \t\treturn;\n \tdefault:\n \t\tBUG(\"unhandled record type\");\ndiff --git a/reftable/record.h b/reftable/record.h\nindex 0f53ba54434..271da3bf360 100644\n--- a/reftable/record.h\n+++ b/reftable/record.h\n@@ -9,6 +9,7 @@ license that can be found in the LICENSE file or at\n #ifndef RECORD_H\n #define RECORD_H\n \n+#include \"basics.h\"\n #include \"system.h\"\n \n #include <stdint.h>\n@@ -38,8 +39,8 @@ int put_var_int(struct string_view *dest, uint64_t val);\n \n /* Methods for records. */\n struct reftable_record_vtable {\n-\t/* encode the key of to a uint8_t strbuf. */\n-\tvoid (*key)(const void *rec, struct strbuf *dest);\n+\t/* encode the key of to a uint8_t reftable_buf. */\n+\tvoid (*key)(const void *rec, struct reftable_buf *dest);\n \n \t/* The record type of ('r' for ref). */\n \tuint8_t type;\n@@ -54,9 +55,9 @@ struct reftable_record_vtable {\n \tint (*encode)(const void *rec, struct string_view dest, int hash_size);\n \n \t/* decode data from `src` into the record. */\n-\tint (*decode)(void *rec, struct strbuf key, uint8_t extra,\n+\tint (*decode)(void *rec, struct reftable_buf key, uint8_t extra,\n \t\t      struct string_view src, int hash_size,\n-\t\t      struct strbuf *scratch);\n+\t\t      struct reftable_buf *scratch);\n \n \t/* deallocate and null the record. */\n \tvoid (*release)(void *rec);\n@@ -83,7 +84,7 @@ int reftable_is_block_type(uint8_t typ);\n /* Encode `key` into `dest`. Sets `is_restart` to indicate a restart. Returns\n  * number of bytes written. */\n int reftable_encode_key(int *is_restart, struct string_view dest,\n-\t\t\tstruct strbuf prev_key, struct strbuf key,\n+\t\t\tstruct reftable_buf prev_key, struct reftable_buf key,\n \t\t\tuint8_t extra);\n \n /* Decode a record's key lengths. */\n@@ -96,13 +97,13 @@ int reftable_decode_keylen(struct string_view in,\n  * Decode into `last_key` and `extra` from `in`. `last_key` is expected to\n  * contain the decoded key of the preceding record, if any.\n  */\n-int reftable_decode_key(struct strbuf *last_key, uint8_t *extra,\n+int reftable_decode_key(struct reftable_buf *last_key, uint8_t *extra,\n \t\t\tstruct string_view in);\n \n /* reftable_index_record are used internally to speed up lookups. */\n struct reftable_index_record {\n \tuint64_t offset; /* Offset of block */\n-\tstruct strbuf last_key; /* Last key of the block. */\n+\tstruct reftable_buf last_key; /* Last key of the block. */\n };\n \n /* reftable_obj_record stores an object ID => ref mapping. */\n@@ -136,15 +137,15 @@ void reftable_record_init(struct reftable_record *rec, uint8_t typ);\n /* see struct record_vtable */\n int reftable_record_cmp(struct reftable_record *a, struct reftable_record *b);\n int reftable_record_equal(struct reftable_record *a, struct reftable_record *b, int hash_size);\n-void reftable_record_key(struct reftable_record *rec, struct strbuf *dest);\n+void reftable_record_key(struct reftable_record *rec, struct reftable_buf *dest);\n int reftable_record_copy_from(struct reftable_record *rec,\n \t\t\t      struct reftable_record *src, int hash_size);\n uint8_t reftable_record_val_type(struct reftable_record *rec);\n int reftable_record_encode(struct reftable_record *rec, struct string_view dest,\n \t\t\t   int hash_size);\n-int reftable_record_decode(struct reftable_record *rec, struct strbuf key,\n+int reftable_record_decode(struct reftable_record *rec, struct reftable_buf key,\n \t\t\t   uint8_t extra, struct string_view src,\n-\t\t\t   int hash_size, struct strbuf *scratch);\n+\t\t\t   int hash_size, struct reftable_buf *scratch);\n int reftable_record_is_deletion(struct reftable_record *rec);\n \n static inline uint8_t reftable_record_type(struct reftable_record *rec)\ndiff --git a/reftable/stack.c b/reftable/stack.c\nindex d7bc1187dfb..6ba48ddce5d 100644\n--- a/reftable/stack.c\n+++ b/reftable/stack.c\n@@ -31,13 +31,13 @@ static void reftable_addition_close(struct reftable_addition *add);\n static int reftable_stack_reload_maybe_reuse(struct reftable_stack *st,\n \t\t\t\t\t     int reuse_open);\n \n-static void stack_filename(struct strbuf *dest, struct reftable_stack *st,\n+static void stack_filename(struct reftable_buf *dest, struct reftable_stack *st,\n \t\t\t   const char *name)\n {\n-\tstrbuf_reset(dest);\n-\tstrbuf_addstr(dest, st->reftable_dir);\n-\tstrbuf_addstr(dest, \"/\");\n-\tstrbuf_addstr(dest, name);\n+\treftable_buf_reset(dest);\n+\treftable_buf_addstr(dest, st->reftable_dir);\n+\treftable_buf_addstr(dest, \"/\");\n+\treftable_buf_addstr(dest, name);\n }\n \n static ssize_t reftable_fd_write(void *arg, const void *data, size_t sz)\n@@ -56,7 +56,7 @@ static int reftable_fd_flush(void *arg)\n int reftable_new_stack(struct reftable_stack **dest, const char *dir,\n \t\t       const struct reftable_write_options *_opts)\n {\n-\tstruct strbuf list_file_name = STRBUF_INIT;\n+\tstruct reftable_buf list_file_name = REFTABLE_BUF_INIT;\n \tstruct reftable_write_options opts = { 0 };\n \tstruct reftable_stack *p;\n \tint err;\n@@ -74,11 +74,11 @@ int reftable_new_stack(struct reftable_stack **dest, const char *dir,\n \n \t*dest = NULL;\n \n-\tstrbuf_reset(&list_file_name);\n-\tstrbuf_addstr(&list_file_name, dir);\n-\tstrbuf_addstr(&list_file_name, \"/tables.list\");\n+\treftable_buf_reset(&list_file_name);\n+\treftable_buf_addstr(&list_file_name, dir);\n+\treftable_buf_addstr(&list_file_name, \"/tables.list\");\n \n-\tp->list_file = strbuf_detach(&list_file_name, NULL);\n+\tp->list_file = reftable_buf_detach(&list_file_name);\n \tp->list_fd = -1;\n \tp->opts = opts;\n \tp->reftable_dir = reftable_strdup(dir);\n@@ -208,10 +208,10 @@ void reftable_stack_destroy(struct reftable_stack *st)\n \n \tif (st->readers) {\n \t\tint i = 0;\n-\t\tstruct strbuf filename = STRBUF_INIT;\n+\t\tstruct reftable_buf filename = REFTABLE_BUF_INIT;\n \t\tfor (i = 0; i < st->readers_len; i++) {\n \t\t\tconst char *name = reader_name(st->readers[i]);\n-\t\t\tstrbuf_reset(&filename);\n+\t\t\treftable_buf_reset(&filename);\n \t\t\tif (names && !has_name(names, name)) {\n \t\t\t\tstack_filename(&filename, st, name);\n \t\t\t}\n@@ -222,7 +222,7 @@ void reftable_stack_destroy(struct reftable_stack *st)\n \t\t\t\tunlink(filename.buf);\n \t\t\t}\n \t\t}\n-\t\tstrbuf_release(&filename);\n+\t\treftable_buf_release(&filename);\n \t\tst->readers_len = 0;\n \t\tREFTABLE_FREE_AND_NULL(st->readers);\n \t}\n@@ -260,7 +260,7 @@ static int reftable_stack_reload_once(struct reftable_stack *st,\n \tsize_t reused_len = 0, reused_alloc = 0, names_len;\n \tsize_t new_readers_len = 0;\n \tstruct reftable_merged_table *new_merged = NULL;\n-\tstruct strbuf table_path = STRBUF_INIT;\n+\tstruct reftable_buf table_path = REFTABLE_BUF_INIT;\n \tint err = 0;\n \tsize_t i;\n \n@@ -374,7 +374,7 @@ static int reftable_stack_reload_once(struct reftable_stack *st,\n \treftable_free(new_readers);\n \treftable_free(reused);\n \treftable_free(cur);\n-\tstrbuf_release(&table_path);\n+\treftable_buf_release(&table_path);\n \treturn err;\n }\n \n@@ -623,14 +623,14 @@ int reftable_stack_add(struct reftable_stack *st,\n \treturn 0;\n }\n \n-static void format_name(struct strbuf *dest, uint64_t min, uint64_t max)\n+static void format_name(struct reftable_buf *dest, uint64_t min, uint64_t max)\n {\n \tchar buf[100];\n \tuint32_t rnd = (uint32_t)git_rand();\n \tsnprintf(buf, sizeof(buf), \"0x%012\" PRIx64 \"-0x%012\" PRIx64 \"-%08x\",\n \t\t min, max, rnd);\n-\tstrbuf_reset(dest);\n-\tstrbuf_addstr(dest, buf);\n+\treftable_buf_reset(dest);\n+\treftable_buf_addstr(dest, buf);\n }\n \n struct reftable_addition {\n@@ -648,7 +648,7 @@ static int reftable_stack_init_addition(struct reftable_addition *add,\n \t\t\t\t\tstruct reftable_stack *st,\n \t\t\t\t\tunsigned int flags)\n {\n-\tstruct strbuf lock_file_name = STRBUF_INIT;\n+\tstruct reftable_buf lock_file_name = REFTABLE_BUF_INIT;\n \tint err;\n \n \tadd->stack = st;\n@@ -690,13 +690,13 @@ static int reftable_stack_init_addition(struct reftable_addition *add,\n done:\n \tif (err)\n \t\treftable_addition_close(add);\n-\tstrbuf_release(&lock_file_name);\n+\treftable_buf_release(&lock_file_name);\n \treturn err;\n }\n \n static void reftable_addition_close(struct reftable_addition *add)\n {\n-\tstruct strbuf nm = STRBUF_INIT;\n+\tstruct reftable_buf nm = REFTABLE_BUF_INIT;\n \tsize_t i;\n \n \tfor (i = 0; i < add->new_tables_len; i++) {\n@@ -711,7 +711,7 @@ static void reftable_addition_close(struct reftable_addition *add)\n \tadd->new_tables_cap = 0;\n \n \trollback_lock_file(&add->tables_list_lock);\n-\tstrbuf_release(&nm);\n+\treftable_buf_release(&nm);\n }\n \n void reftable_addition_destroy(struct reftable_addition *add)\n@@ -725,7 +725,7 @@ void reftable_addition_destroy(struct reftable_addition *add)\n \n int reftable_addition_commit(struct reftable_addition *add)\n {\n-\tstruct strbuf table_list = STRBUF_INIT;\n+\tstruct reftable_buf table_list = REFTABLE_BUF_INIT;\n \tint lock_file_fd = get_lock_file_fd(&add->tables_list_lock);\n \tint err = 0;\n \tsize_t i;\n@@ -734,16 +734,16 @@ int reftable_addition_commit(struct reftable_addition *add)\n \t\tgoto done;\n \n \tfor (i = 0; i < add->stack->merged->readers_len; i++) {\n-\t\tstrbuf_addstr(&table_list, add->stack->readers[i]->name);\n-\t\tstrbuf_addstr(&table_list, \"\\n\");\n+\t\treftable_buf_addstr(&table_list, add->stack->readers[i]->name);\n+\t\treftable_buf_addstr(&table_list, \"\\n\");\n \t}\n \tfor (i = 0; i < add->new_tables_len; i++) {\n-\t\tstrbuf_addstr(&table_list, add->new_tables[i]);\n-\t\tstrbuf_addstr(&table_list, \"\\n\");\n+\t\treftable_buf_addstr(&table_list, add->new_tables[i]);\n+\t\treftable_buf_addstr(&table_list, \"\\n\");\n \t}\n \n \terr = write_in_full(lock_file_fd, table_list.buf, table_list.len);\n-\tstrbuf_release(&table_list);\n+\treftable_buf_release(&table_list);\n \tif (err < 0) {\n \t\terr = REFTABLE_IO_ERROR;\n \t\tgoto done;\n@@ -837,19 +837,19 @@ int reftable_addition_add(struct reftable_addition *add,\n \t\t\t\t\t     void *arg),\n \t\t\t  void *arg)\n {\n-\tstruct strbuf temp_tab_file_name = STRBUF_INIT;\n-\tstruct strbuf tab_file_name = STRBUF_INIT;\n-\tstruct strbuf next_name = STRBUF_INIT;\n+\tstruct reftable_buf temp_tab_file_name = REFTABLE_BUF_INIT;\n+\tstruct reftable_buf tab_file_name = REFTABLE_BUF_INIT;\n+\tstruct reftable_buf next_name = REFTABLE_BUF_INIT;\n \tstruct reftable_writer *wr = NULL;\n \tstruct tempfile *tab_file = NULL;\n \tint err = 0;\n \tint tab_fd;\n \n-\tstrbuf_reset(&next_name);\n+\treftable_buf_reset(&next_name);\n \tformat_name(&next_name, add->next_update_index, add->next_update_index);\n \n \tstack_filename(&temp_tab_file_name, add->stack, next_name.buf);\n-\tstrbuf_addstr(&temp_tab_file_name, \".temp.XXXXXX\");\n+\treftable_buf_addstr(&temp_tab_file_name, \".temp.XXXXXX\");\n \n \ttab_file = mks_tempfile(temp_tab_file_name.buf);\n \tif (!tab_file) {\n@@ -894,7 +894,7 @@ int reftable_addition_add(struct reftable_addition *add,\n \t}\n \n \tformat_name(&next_name, wr->min_update_index, wr->max_update_index);\n-\tstrbuf_addstr(&next_name, \".ref\");\n+\treftable_buf_addstr(&next_name, \".ref\");\n \tstack_filename(&tab_file_name, add->stack, next_name.buf);\n \n \t/*\n@@ -913,13 +913,13 @@ int reftable_addition_add(struct reftable_addition *add,\n \t\terr = REFTABLE_OUT_OF_MEMORY_ERROR;\n \t\tgoto done;\n \t}\n-\tadd->new_tables[add->new_tables_len++] = strbuf_detach(&next_name, NULL);\n+\tadd->new_tables[add->new_tables_len++] = reftable_buf_detach(&next_name);\n \n done:\n \tdelete_tempfile(&tab_file);\n-\tstrbuf_release(&temp_tab_file_name);\n-\tstrbuf_release(&tab_file_name);\n-\tstrbuf_release(&next_name);\n+\treftable_buf_release(&temp_tab_file_name);\n+\treftable_buf_release(&tab_file_name);\n+\treftable_buf_release(&next_name);\n \treftable_writer_free(wr);\n \treturn err;\n }\n@@ -938,8 +938,8 @@ static int stack_compact_locked(struct reftable_stack *st,\n \t\t\t\tstruct reftable_log_expiry_config *config,\n \t\t\t\tstruct tempfile **tab_file_out)\n {\n-\tstruct strbuf next_name = STRBUF_INIT;\n-\tstruct strbuf tab_file_path = STRBUF_INIT;\n+\tstruct reftable_buf next_name = REFTABLE_BUF_INIT;\n+\tstruct reftable_buf tab_file_path = REFTABLE_BUF_INIT;\n \tstruct reftable_writer *wr = NULL;\n \tstruct tempfile *tab_file;\n \tint tab_fd, err = 0;\n@@ -948,7 +948,7 @@ static int stack_compact_locked(struct reftable_stack *st,\n \t\t    reftable_reader_min_update_index(st->readers[first]),\n \t\t    reftable_reader_max_update_index(st->readers[last]));\n \tstack_filename(&tab_file_path, st, next_name.buf);\n-\tstrbuf_addstr(&tab_file_path, \".temp.XXXXXX\");\n+\treftable_buf_addstr(&tab_file_path, \".temp.XXXXXX\");\n \n \ttab_file = mks_tempfile(tab_file_path.buf);\n \tif (!tab_file) {\n@@ -986,8 +986,8 @@ static int stack_compact_locked(struct reftable_stack *st,\n done:\n \tdelete_tempfile(&tab_file);\n \treftable_writer_free(wr);\n-\tstrbuf_release(&next_name);\n-\tstrbuf_release(&tab_file_path);\n+\treftable_buf_release(&next_name);\n+\treftable_buf_release(&tab_file_path);\n \treturn err;\n }\n \n@@ -1111,10 +1111,10 @@ static int stack_compact_range(struct reftable_stack *st,\n \t\t\t       struct reftable_log_expiry_config *expiry,\n \t\t\t       unsigned int flags)\n {\n-\tstruct strbuf tables_list_buf = STRBUF_INIT;\n-\tstruct strbuf new_table_name = STRBUF_INIT;\n-\tstruct strbuf new_table_path = STRBUF_INIT;\n-\tstruct strbuf table_name = STRBUF_INIT;\n+\tstruct reftable_buf tables_list_buf = REFTABLE_BUF_INIT;\n+\tstruct reftable_buf new_table_name = REFTABLE_BUF_INIT;\n+\tstruct reftable_buf new_table_path = REFTABLE_BUF_INIT;\n+\tstruct reftable_buf table_name = REFTABLE_BUF_INIT;\n \tstruct lock_file tables_list_lock = LOCK_INIT;\n \tstruct lock_file *table_locks = NULL;\n \tstruct tempfile *new_table = NULL;\n@@ -1372,7 +1372,7 @@ static int stack_compact_range(struct reftable_stack *st,\n \tif (!is_empty_table) {\n \t\tformat_name(&new_table_name, st->readers[first]->min_update_index,\n \t\t\t    st->readers[last]->max_update_index);\n-\t\tstrbuf_addstr(&new_table_name, \".ref\");\n+\t\treftable_buf_addstr(&new_table_name, \".ref\");\n \t\tstack_filename(&new_table_path, st, new_table_name.buf);\n \n \t\terr = rename_tempfile(&new_table, new_table_path.buf);\n@@ -1388,16 +1388,16 @@ static int stack_compact_range(struct reftable_stack *st,\n \t * simply skip writing it.\n \t */\n \tfor (i = 0; i < first_to_replace; i++) {\n-\t\tstrbuf_addstr(&tables_list_buf, names[i]);\n-\t\tstrbuf_addstr(&tables_list_buf, \"\\n\");\n+\t\treftable_buf_addstr(&tables_list_buf, names[i]);\n+\t\treftable_buf_addstr(&tables_list_buf, \"\\n\");\n \t}\n \tif (!is_empty_table) {\n-\t\tstrbuf_addstr(&tables_list_buf, new_table_name.buf);\n-\t\tstrbuf_addstr(&tables_list_buf, \"\\n\");\n+\t\treftable_buf_addstr(&tables_list_buf, new_table_name.buf);\n+\t\treftable_buf_addstr(&tables_list_buf, \"\\n\");\n \t}\n \tfor (i = last_to_replace + 1; names[i]; i++) {\n-\t\tstrbuf_addstr(&tables_list_buf, names[i]);\n-\t\tstrbuf_addstr(&tables_list_buf, \"\\n\");\n+\t\treftable_buf_addstr(&tables_list_buf, names[i]);\n+\t\treftable_buf_addstr(&tables_list_buf, \"\\n\");\n \t}\n \n \terr = write_in_full(get_lock_file_fd(&tables_list_lock),\n@@ -1449,10 +1449,10 @@ static int stack_compact_range(struct reftable_stack *st,\n \treftable_free(table_locks);\n \n \tdelete_tempfile(&new_table);\n-\tstrbuf_release(&new_table_name);\n-\tstrbuf_release(&new_table_path);\n-\tstrbuf_release(&tables_list_buf);\n-\tstrbuf_release(&table_name);\n+\treftable_buf_release(&new_table_name);\n+\treftable_buf_release(&new_table_path);\n+\treftable_buf_release(&tables_list_buf);\n+\treftable_buf_release(&table_name);\n \tfree_names(names);\n \n \tif (err == REFTABLE_LOCK_ERROR)\n@@ -1666,7 +1666,7 @@ static void remove_maybe_stale_table(struct reftable_stack *st, uint64_t max,\n \tuint64_t update_idx = 0;\n \tstruct reftable_block_source src = { NULL };\n \tstruct reftable_reader *rd = NULL;\n-\tstruct strbuf table_path = STRBUF_INIT;\n+\tstruct reftable_buf table_path = REFTABLE_BUF_INIT;\n \tstack_filename(&table_path, st, name);\n \n \terr = reftable_block_source_from_file(&src, table_path.buf);\n@@ -1684,7 +1684,7 @@ static void remove_maybe_stale_table(struct reftable_stack *st, uint64_t max,\n \t\tunlink(table_path.buf);\n \t}\n done:\n-\tstrbuf_release(&table_path);\n+\treftable_buf_release(&table_path);\n }\n \n static int reftable_stack_clean_locked(struct reftable_stack *st)\ndiff --git a/reftable/system.h b/reftable/system.h\nindex d0cabd5d171..5ec85833434 100644\n--- a/reftable/system.h\n+++ b/reftable/system.h\n@@ -13,7 +13,6 @@ license that can be found in the LICENSE file or at\n \n #include \"git-compat-util.h\"\n #include \"lockfile.h\"\n-#include \"strbuf.h\"\n #include \"tempfile.h\"\n #include \"hash.h\" /* hash ID, sizes.*/\n #include \"dir.h\" /* remove_dir_recursively, for tests.*/\ndiff --git a/reftable/writer.c b/reftable/writer.c\nindex 031d8149a9c..da6941a78ac 100644\n--- a/reftable/writer.c\n+++ b/reftable/writer.c\n@@ -115,7 +115,7 @@ static int writer_reinit_block_writer(struct reftable_writer *w, uint8_t typ)\n \tif (w->next == 0)\n \t\tblock_start = header_size(writer_version(w));\n \n-\tstrbuf_reset(&w->last_key);\n+\treftable_buf_reset(&w->last_key);\n \tret = block_writer_init(&w->block_writer_data, typ, w->block,\n \t\t\t\tw->opts.block_size, block_start,\n \t\t\t\thash_size(w->opts.hash_id));\n@@ -146,8 +146,8 @@ int reftable_writer_new(struct reftable_writer **out,\n \tif (opts.block_size >= (1 << 24))\n \t\tBUG(\"configured block size exceeds 16MB\");\n \n-\tstrbuf_init(&wp->block_writer_data.last_key, 0);\n-\tstrbuf_init(&wp->last_key, 0);\n+\treftable_buf_init(&wp->block_writer_data.last_key);\n+\treftable_buf_init(&wp->last_key);\n \tREFTABLE_CALLOC_ARRAY(wp->block, opts.block_size);\n \tif (!wp->block) {\n \t\treftable_free(wp);\n@@ -179,7 +179,7 @@ static void writer_release(struct reftable_writer *w)\n \t\tblock_writer_release(&w->block_writer_data);\n \t\tw->block_writer = NULL;\n \t\twriter_clear_index(w);\n-\t\tstrbuf_release(&w->last_key);\n+\t\treftable_buf_release(&w->last_key);\n \t}\n }\n \n@@ -190,7 +190,7 @@ void reftable_writer_free(struct reftable_writer *w)\n }\n \n struct obj_index_tree_node {\n-\tstruct strbuf hash;\n+\tstruct reftable_buf hash;\n \tuint64_t *offsets;\n \tsize_t offset_len;\n \tsize_t offset_cap;\n@@ -198,16 +198,16 @@ struct obj_index_tree_node {\n \n #define OBJ_INDEX_TREE_NODE_INIT    \\\n \t{                           \\\n-\t\t.hash = STRBUF_INIT \\\n+\t\t.hash = REFTABLE_BUF_INIT \\\n \t}\n \n static int obj_index_tree_node_compare(const void *a, const void *b)\n {\n-\treturn strbuf_cmp(&((const struct obj_index_tree_node *)a)->hash,\n+\treturn reftable_buf_cmp(&((const struct obj_index_tree_node *)a)->hash,\n \t\t\t  &((const struct obj_index_tree_node *)b)->hash);\n }\n \n-static int writer_index_hash(struct reftable_writer *w, struct strbuf *hash)\n+static int writer_index_hash(struct reftable_writer *w, struct reftable_buf *hash)\n {\n \tuint64_t off = w->next;\n \tstruct obj_index_tree_node want = { .hash = *hash };\n@@ -224,8 +224,8 @@ static int writer_index_hash(struct reftable_writer *w, struct strbuf *hash)\n \n \t\t*key = empty;\n \n-\t\tstrbuf_reset(&key->hash);\n-\t\tstrbuf_add(&key->hash, hash->buf, hash->len);\n+\t\treftable_buf_reset(&key->hash);\n+\t\treftable_buf_add(&key->hash, hash->buf, hash->len);\n \t\ttree_insert(&w->obj_index_tree, key,\n \t\t\t    &obj_index_tree_node_compare);\n \t} else {\n@@ -246,17 +246,17 @@ static int writer_index_hash(struct reftable_writer *w, struct strbuf *hash)\n static int writer_add_record(struct reftable_writer *w,\n \t\t\t     struct reftable_record *rec)\n {\n-\tstruct strbuf key = STRBUF_INIT;\n+\tstruct reftable_buf key = REFTABLE_BUF_INIT;\n \tint err;\n \n \treftable_record_key(rec, &key);\n-\tif (strbuf_cmp(&w->last_key, &key) >= 0) {\n+\tif (reftable_buf_cmp(&w->last_key, &key) >= 0) {\n \t\terr = REFTABLE_API_ERROR;\n \t\tgoto done;\n \t}\n \n-\tstrbuf_reset(&w->last_key);\n-\tstrbuf_add(&w->last_key, key.buf, key.len);\n+\treftable_buf_reset(&w->last_key);\n+\treftable_buf_add(&w->last_key, key.buf, key.len);\n \tif (!w->block_writer) {\n \t\terr = writer_reinit_block_writer(w, reftable_record_type(rec));\n \t\tif (err < 0)\n@@ -303,7 +303,7 @@ static int writer_add_record(struct reftable_writer *w,\n \t}\n \n done:\n-\tstrbuf_release(&key);\n+\treftable_buf_release(&key);\n \treturn err;\n }\n \n@@ -316,7 +316,7 @@ int reftable_writer_add_ref(struct reftable_writer *w,\n \t\t\t.ref = *ref\n \t\t},\n \t};\n-\tstruct strbuf buf = STRBUF_INIT;\n+\tstruct reftable_buf buf = REFTABLE_BUF_INIT;\n \tint err;\n \n \tif (!ref->refname ||\n@@ -331,7 +331,7 @@ int reftable_writer_add_ref(struct reftable_writer *w,\n \t\tgoto out;\n \n \tif (!w->opts.skip_index_objects && reftable_ref_record_val1(ref)) {\n-\t\tstrbuf_add(&buf, (char *)reftable_ref_record_val1(ref),\n+\t\treftable_buf_add(&buf, (char *)reftable_ref_record_val1(ref),\n \t\t\t   hash_size(w->opts.hash_id));\n \n \t\terr = writer_index_hash(w, &buf);\n@@ -340,8 +340,8 @@ int reftable_writer_add_ref(struct reftable_writer *w,\n \t}\n \n \tif (!w->opts.skip_index_objects && reftable_ref_record_val2(ref)) {\n-\t\tstrbuf_reset(&buf);\n-\t\tstrbuf_add(&buf, reftable_ref_record_val2(ref),\n+\t\treftable_buf_reset(&buf);\n+\t\treftable_buf_add(&buf, reftable_ref_record_val2(ref),\n \t\t\t   hash_size(w->opts.hash_id));\n \n \t\terr = writer_index_hash(w, &buf);\n@@ -352,7 +352,7 @@ int reftable_writer_add_ref(struct reftable_writer *w,\n \terr = 0;\n \n out:\n-\tstrbuf_release(&buf);\n+\treftable_buf_release(&buf);\n \treturn err;\n }\n \n@@ -393,7 +393,7 @@ int reftable_writer_add_log(struct reftable_writer *w,\n \t\t\t    struct reftable_log_record *log)\n {\n \tchar *input_log_message = NULL;\n-\tstruct strbuf cleaned_message = STRBUF_INIT;\n+\tstruct reftable_buf cleaned_message = REFTABLE_BUF_INIT;\n \tint err = 0;\n \n \tif (log->value_type == REFTABLE_LOG_DELETION)\n@@ -404,24 +404,24 @@ int reftable_writer_add_log(struct reftable_writer *w,\n \n \tinput_log_message = log->value.update.message;\n \tif (!w->opts.exact_log_message && log->value.update.message) {\n-\t\tstrbuf_addstr(&cleaned_message, log->value.update.message);\n+\t\treftable_buf_addstr(&cleaned_message, log->value.update.message);\n \t\twhile (cleaned_message.len &&\n \t\t       cleaned_message.buf[cleaned_message.len - 1] == '\\n')\n-\t\t\tstrbuf_setlen(&cleaned_message,\n+\t\t\treftable_buf_setlen(&cleaned_message,\n \t\t\t\t      cleaned_message.len - 1);\n \t\tif (strchr(cleaned_message.buf, '\\n')) {\n \t\t\t/* multiple lines not allowed. */\n \t\t\terr = REFTABLE_API_ERROR;\n \t\t\tgoto done;\n \t\t}\n-\t\tstrbuf_addstr(&cleaned_message, \"\\n\");\n+\t\treftable_buf_addstr(&cleaned_message, \"\\n\");\n \t\tlog->value.update.message = cleaned_message.buf;\n \t}\n \n \terr = reftable_writer_add_log_verbatim(w, log);\n \tlog->value.update.message = input_log_message;\n done:\n-\tstrbuf_release(&cleaned_message);\n+\treftable_buf_release(&cleaned_message);\n \treturn err;\n }\n \n@@ -504,7 +504,7 @@ static int writer_finish_section(struct reftable_writer *w)\n \t\t\treturn err;\n \n \t\tfor (i = 0; i < idx_len; i++)\n-\t\t\tstrbuf_release(&idx[i].last_key);\n+\t\t\treftable_buf_release(&idx[i].last_key);\n \t\treftable_free(idx);\n \t}\n \n@@ -521,13 +521,13 @@ static int writer_finish_section(struct reftable_writer *w)\n \tbstats->max_index_level = max_level;\n \n \t/* Reinit lastKey, as the next section can start with any key. */\n-\tstrbuf_reset(&w->last_key);\n+\treftable_buf_reset(&w->last_key);\n \n \treturn 0;\n }\n \n struct common_prefix_arg {\n-\tstruct strbuf *last;\n+\tstruct reftable_buf *last;\n \tint max;\n };\n \n@@ -594,7 +594,7 @@ static void object_record_free(void *void_arg UNUSED, void *key)\n \tstruct obj_index_tree_node *entry = key;\n \n \tREFTABLE_FREE_AND_NULL(entry->offsets);\n-\tstrbuf_release(&entry->hash);\n+\treftable_buf_release(&entry->hash);\n \treftable_free(entry);\n }\n \n@@ -708,7 +708,7 @@ int reftable_writer_close(struct reftable_writer *w)\n static void writer_clear_index(struct reftable_writer *w)\n {\n \tfor (size_t i = 0; w->index && i < w->index_len; i++)\n-\t\tstrbuf_release(&w->index[i].last_key);\n+\t\treftable_buf_release(&w->index[i].last_key);\n \tREFTABLE_FREE_AND_NULL(w->index);\n \tw->index_len = 0;\n \tw->index_cap = 0;\n@@ -717,7 +717,7 @@ static void writer_clear_index(struct reftable_writer *w)\n static int writer_flush_nonempty_block(struct reftable_writer *w)\n {\n \tstruct reftable_index_record index_record = {\n-\t\t.last_key = STRBUF_INIT,\n+\t\t.last_key = REFTABLE_BUF_INIT,\n \t};\n \tuint8_t typ = block_writer_type(w->block_writer);\n \tstruct reftable_block_stats *bstats;\n@@ -777,8 +777,8 @@ static int writer_flush_nonempty_block(struct reftable_writer *w)\n \t\treturn REFTABLE_OUT_OF_MEMORY_ERROR;\n \n \tindex_record.offset = w->next;\n-\tstrbuf_reset(&index_record.last_key);\n-\tstrbuf_add(&index_record.last_key, w->block_writer->last_key.buf,\n+\treftable_buf_reset(&index_record.last_key);\n+\treftable_buf_add(&index_record.last_key, w->block_writer->last_key.buf,\n \t\t   w->block_writer->last_key.len);\n \tw->index[w->index_len] = index_record;\n \tw->index_len++;\ndiff --git a/reftable/writer.h b/reftable/writer.h\nindex 8d0df9cc528..e8a6fbb7854 100644\n--- a/reftable/writer.h\n+++ b/reftable/writer.h\n@@ -19,7 +19,7 @@ struct reftable_writer {\n \tint (*flush)(void *);\n \tvoid *write_arg;\n \tint pending_padding;\n-\tstruct strbuf last_key;\n+\tstruct reftable_buf last_key;\n \n \t/* offset of next block to write. */\n \tuint64_t next;\ndiff --git a/t/unit-tests/lib-reftable.c b/t/unit-tests/lib-reftable.c\nindex 54c26c43e77..2ddf480588d 100644\n--- a/t/unit-tests/lib-reftable.c\n+++ b/t/unit-tests/lib-reftable.c\n@@ -19,7 +19,7 @@ static int strbuf_writer_flush(void *arg UNUSED)\n \treturn 0;\n }\n \n-struct reftable_writer *t_reftable_strbuf_writer(struct strbuf *buf,\n+struct reftable_writer *t_reftable_strbuf_writer(struct reftable_buf *buf,\n \t\t\t\t\t\t struct reftable_write_options *opts)\n {\n \tstruct reftable_writer *writer;\n@@ -29,7 +29,7 @@ struct reftable_writer *t_reftable_strbuf_writer(struct strbuf *buf,\n \treturn writer;\n }\n \n-void t_reftable_write_to_buf(struct strbuf *buf,\n+void t_reftable_write_to_buf(struct reftable_buf *buf,\n \t\t\t     struct reftable_ref_record *refs,\n \t\t\t     size_t nrefs,\n \t\t\t     struct reftable_log_record *logs,\ndiff --git a/t/unit-tests/lib-reftable.h b/t/unit-tests/lib-reftable.h\nindex d1154190847..d4950fed3da 100644\n--- a/t/unit-tests/lib-reftable.h\n+++ b/t/unit-tests/lib-reftable.h\n@@ -2,15 +2,16 @@\n #define LIB_REFTABLE_H\n \n #include \"git-compat-util.h\"\n-#include \"strbuf.h\"\n #include \"reftable/reftable-writer.h\"\n \n+struct reftable_buf;\n+\n void t_reftable_set_hash(uint8_t *p, int i, uint32_t id);\n \n-struct reftable_writer *t_reftable_strbuf_writer(struct strbuf *buf,\n+struct reftable_writer *t_reftable_strbuf_writer(struct reftable_buf *buf,\n \t\t\t\t\t\t struct reftable_write_options *opts);\n \n-void t_reftable_write_to_buf(struct strbuf *buf,\n+void t_reftable_write_to_buf(struct reftable_buf *buf,\n \t\t\t     struct reftable_ref_record *refs,\n \t\t\t     size_t nrecords,\n \t\t\t     struct reftable_log_record *logs,\ndiff --git a/t/unit-tests/t-reftable-basics.c b/t/unit-tests/t-reftable-basics.c\nindex 1fa77b6faff..a814e819756 100644\n--- a/t/unit-tests/t-reftable-basics.c\n+++ b/t/unit-tests/t-reftable-basics.c\n@@ -99,8 +99,8 @@ int cmd_main(int argc UNUSED, const char *argv[] UNUSED)\n \t}\n \n \tif_test (\"common_prefix_size works\") {\n-\t\tstruct strbuf a = STRBUF_INIT;\n-\t\tstruct strbuf b = STRBUF_INIT;\n+\t\tstruct reftable_buf a = REFTABLE_BUF_INIT;\n+\t\tstruct reftable_buf b = REFTABLE_BUF_INIT;\n \t\tstruct {\n \t\t\tconst char *a, *b;\n \t\t\tint want;\n@@ -113,14 +113,14 @@ int cmd_main(int argc UNUSED, const char *argv[] UNUSED)\n \t\t};\n \n \t\tfor (size_t i = 0; i < ARRAY_SIZE(cases); i++) {\n-\t\t\tstrbuf_addstr(&a, cases[i].a);\n-\t\t\tstrbuf_addstr(&b, cases[i].b);\n+\t\t\treftable_buf_addstr(&a, cases[i].a);\n+\t\t\treftable_buf_addstr(&b, cases[i].b);\n \t\t\tcheck_int(common_prefix_size(&a, &b), ==, cases[i].want);\n-\t\t\tstrbuf_reset(&a);\n-\t\t\tstrbuf_reset(&b);\n+\t\t\treftable_buf_reset(&a);\n+\t\t\treftable_buf_reset(&b);\n \t\t}\n-\t\tstrbuf_release(&a);\n-\t\tstrbuf_release(&b);\n+\t\treftable_buf_release(&a);\n+\t\treftable_buf_release(&b);\n \t}\n \n \tif_test (\"put_be24 and get_be24 work\") {\ndiff --git a/t/unit-tests/t-reftable-block.c b/t/unit-tests/t-reftable-block.c\nindex 8077bbc5e7a..56514b43630 100644\n--- a/t/unit-tests/t-reftable-block.c\n+++ b/t/unit-tests/t-reftable-block.c\n@@ -20,7 +20,7 @@ static void t_ref_block_read_write(void)\n \tconst size_t block_size = 1024;\n \tstruct reftable_block block = { 0 };\n \tstruct block_writer bw = {\n-\t\t.last_key = STRBUF_INIT,\n+\t\t.last_key = REFTABLE_BUF_INIT,\n \t};\n \tstruct reftable_record rec = {\n \t\t.type = BLOCK_TYPE_REF,\n@@ -29,7 +29,7 @@ static void t_ref_block_read_write(void)\n \tint ret;\n \tstruct block_reader br = { 0 };\n \tstruct block_iter it = BLOCK_ITER_INIT;\n-\tstruct strbuf want = STRBUF_INIT, buf = STRBUF_INIT;\n+\tstruct reftable_buf want = REFTABLE_BUF_INIT, buf = REFTABLE_BUF_INIT;\n \n \tREFTABLE_CALLOC_ARRAY(block.data, block_size);\n \tcheck(block.data != NULL);\n@@ -100,8 +100,8 @@ static void t_ref_block_read_write(void)\n \tblock_iter_close(&it);\n \treftable_record_release(&rec);\n \treftable_block_done(&br.block);\n-\tstrbuf_release(&want);\n-\tstrbuf_release(&buf);\n+\treftable_buf_release(&want);\n+\treftable_buf_release(&buf);\n \tfor (i = 0; i < N; i++)\n \t\treftable_record_release(&recs[i]);\n }\n@@ -114,7 +114,7 @@ static void t_log_block_read_write(void)\n \tconst size_t block_size = 2048;\n \tstruct reftable_block block = { 0 };\n \tstruct block_writer bw = {\n-\t\t.last_key = STRBUF_INIT,\n+\t\t.last_key = REFTABLE_BUF_INIT,\n \t};\n \tstruct reftable_record rec = {\n \t\t.type = BLOCK_TYPE_LOG,\n@@ -123,7 +123,7 @@ static void t_log_block_read_write(void)\n \tint ret;\n \tstruct block_reader br = { 0 };\n \tstruct block_iter it = BLOCK_ITER_INIT;\n-\tstruct strbuf want = STRBUF_INIT, buf = STRBUF_INIT;\n+\tstruct reftable_buf want = REFTABLE_BUF_INIT, buf = REFTABLE_BUF_INIT;\n \n \tREFTABLE_CALLOC_ARRAY(block.data, block_size);\n \tcheck(block.data != NULL);\n@@ -166,8 +166,8 @@ static void t_log_block_read_write(void)\n \n \tfor (i = 0; i < N; i++) {\n \t\tblock_iter_reset(&it);\n-\t\tstrbuf_reset(&want);\n-\t\tstrbuf_addstr(&want, recs[i].u.log.refname);\n+\t\treftable_buf_reset(&want);\n+\t\treftable_buf_addstr(&want, recs[i].u.log.refname);\n \n \t\tret = block_iter_seek_key(&it, &br, &want);\n \t\tcheck_int(ret, ==, 0);\n@@ -190,8 +190,8 @@ static void t_log_block_read_write(void)\n \tblock_iter_close(&it);\n \treftable_record_release(&rec);\n \treftable_block_done(&br.block);\n-\tstrbuf_release(&want);\n-\tstrbuf_release(&buf);\n+\treftable_buf_release(&want);\n+\treftable_buf_release(&buf);\n \tfor (i = 0; i < N; i++)\n \t\treftable_record_release(&recs[i]);\n }\n@@ -204,7 +204,7 @@ static void t_obj_block_read_write(void)\n \tconst size_t block_size = 1024;\n \tstruct reftable_block block = { 0 };\n \tstruct block_writer bw = {\n-\t\t.last_key = STRBUF_INIT,\n+\t\t.last_key = REFTABLE_BUF_INIT,\n \t};\n \tstruct reftable_record rec = {\n \t\t.type = BLOCK_TYPE_OBJ,\n@@ -213,7 +213,7 @@ static void t_obj_block_read_write(void)\n \tint ret;\n \tstruct block_reader br = { 0 };\n \tstruct block_iter it = BLOCK_ITER_INIT;\n-\tstruct strbuf want = STRBUF_INIT, buf = STRBUF_INIT;\n+\tstruct reftable_buf want = REFTABLE_BUF_INIT, buf = REFTABLE_BUF_INIT;\n \n \tREFTABLE_CALLOC_ARRAY(block.data, block_size);\n \tcheck(block.data != NULL);\n@@ -273,8 +273,8 @@ static void t_obj_block_read_write(void)\n \tblock_iter_close(&it);\n \treftable_record_release(&rec);\n \treftable_block_done(&br.block);\n-\tstrbuf_release(&want);\n-\tstrbuf_release(&buf);\n+\treftable_buf_release(&want);\n+\treftable_buf_release(&buf);\n \tfor (i = 0; i < N; i++)\n \t\treftable_record_release(&recs[i]);\n }\n@@ -287,17 +287,17 @@ static void t_index_block_read_write(void)\n \tconst size_t block_size = 1024;\n \tstruct reftable_block block = { 0 };\n \tstruct block_writer bw = {\n-\t\t.last_key = STRBUF_INIT,\n+\t\t.last_key = REFTABLE_BUF_INIT,\n \t};\n \tstruct reftable_record rec = {\n \t\t.type = BLOCK_TYPE_INDEX,\n-\t\t.u.idx.last_key = STRBUF_INIT,\n+\t\t.u.idx.last_key = REFTABLE_BUF_INIT,\n \t};\n \tsize_t i = 0;\n \tint ret;\n \tstruct block_reader br = { 0 };\n \tstruct block_iter it = BLOCK_ITER_INIT;\n-\tstruct strbuf want = STRBUF_INIT, buf = STRBUF_INIT;\n+\tstruct reftable_buf want = REFTABLE_BUF_INIT, buf = REFTABLE_BUF_INIT;\n \n \tREFTABLE_CALLOC_ARRAY(block.data, block_size);\n \tcheck(block.data != NULL);\n@@ -312,9 +312,9 @@ static void t_index_block_read_write(void)\n \n \t\tsnprintf(buf, sizeof(buf), \"branch%02\"PRIuMAX, (uintmax_t)i);\n \n-\t\tstrbuf_init(&recs[i].u.idx.last_key, 9);\n+\t\treftable_buf_init(&recs[i].u.idx.last_key);\n \t\trecs[i].type = BLOCK_TYPE_INDEX;\n-\t\tstrbuf_addstr(&recs[i].u.idx.last_key, buf);\n+\t\treftable_buf_addstr(&recs[i].u.idx.last_key, buf);\n \t\trecs[i].u.idx.offset = i;\n \n \t\tret = block_writer_add(&bw, &recs[i]);\n@@ -365,8 +365,8 @@ static void t_index_block_read_write(void)\n \tblock_iter_close(&it);\n \treftable_record_release(&rec);\n \treftable_block_done(&br.block);\n-\tstrbuf_release(&want);\n-\tstrbuf_release(&buf);\n+\treftable_buf_release(&want);\n+\treftable_buf_release(&buf);\n \tfor (i = 0; i < N; i++)\n \t\treftable_record_release(&recs[i]);\n }\ndiff --git a/t/unit-tests/t-reftable-merged.c b/t/unit-tests/t-reftable-merged.c\nindex 3c84363e980..9b0162a4b32 100644\n--- a/t/unit-tests/t-reftable-merged.c\n+++ b/t/unit-tests/t-reftable-merged.c\n@@ -20,7 +20,7 @@ static struct reftable_merged_table *\n merged_table_from_records(struct reftable_ref_record **refs,\n \t\t\t  struct reftable_block_source **source,\n \t\t\t  struct reftable_reader ***readers, const size_t *sizes,\n-\t\t\t  struct strbuf *buf, const size_t n)\n+\t\t\t  struct reftable_buf *buf, const size_t n)\n {\n \tstruct reftable_merged_table *mt = NULL;\n \tstruct reftable_write_options opts = {\n@@ -75,7 +75,7 @@ static void t_merged_single_record(void)\n \n \tstruct reftable_ref_record *refs[] = { r1, r2, r3 };\n \tsize_t sizes[] = { ARRAY_SIZE(r1), ARRAY_SIZE(r2), ARRAY_SIZE(r3) };\n-\tstruct strbuf bufs[3] = { STRBUF_INIT, STRBUF_INIT, STRBUF_INIT };\n+\tstruct reftable_buf bufs[3] = { REFTABLE_BUF_INIT, REFTABLE_BUF_INIT, REFTABLE_BUF_INIT };\n \tstruct reftable_block_source *bs = NULL;\n \tstruct reftable_reader **readers = NULL;\n \tstruct reftable_merged_table *mt =\n@@ -97,7 +97,7 @@ static void t_merged_single_record(void)\n \treaders_destroy(readers, 3);\n \treftable_merged_table_free(mt);\n \tfor (size_t i = 0; i < ARRAY_SIZE(bufs); i++)\n-\t\tstrbuf_release(&bufs[i]);\n+\t\treftable_buf_release(&bufs[i]);\n \treftable_free(bs);\n }\n \n@@ -152,7 +152,7 @@ static void t_merged_refs(void)\n \n \tstruct reftable_ref_record *refs[] = { r1, r2, r3 };\n \tsize_t sizes[3] = { ARRAY_SIZE(r1), ARRAY_SIZE(r2), ARRAY_SIZE(r3) };\n-\tstruct strbuf bufs[3] = { STRBUF_INIT, STRBUF_INIT, STRBUF_INIT };\n+\tstruct reftable_buf bufs[3] = { REFTABLE_BUF_INIT, REFTABLE_BUF_INIT, REFTABLE_BUF_INIT };\n \tstruct reftable_block_source *bs = NULL;\n \tstruct reftable_reader **readers = NULL;\n \tstruct reftable_merged_table *mt =\n@@ -192,7 +192,7 @@ static void t_merged_refs(void)\n \treftable_free(out);\n \n \tfor (i = 0; i < 3; i++)\n-\t\tstrbuf_release(&bufs[i]);\n+\t\treftable_buf_release(&bufs[i]);\n \treaders_destroy(readers, 3);\n \treftable_merged_table_free(mt);\n \treftable_free(bs);\n@@ -234,8 +234,8 @@ static void t_merged_seek_multiple_times(void)\n \tsize_t sizes[] = {\n \t\tARRAY_SIZE(r1), ARRAY_SIZE(r2),\n \t};\n-\tstruct strbuf bufs[] = {\n-\t\tSTRBUF_INIT, STRBUF_INIT,\n+\tstruct reftable_buf bufs[] = {\n+\t\tREFTABLE_BUF_INIT, REFTABLE_BUF_INIT,\n \t};\n \tstruct reftable_block_source *sources = NULL;\n \tstruct reftable_reader **readers = NULL;\n@@ -265,7 +265,7 @@ static void t_merged_seek_multiple_times(void)\n \t}\n \n \tfor (size_t i = 0; i < ARRAY_SIZE(bufs); i++)\n-\t\tstrbuf_release(&bufs[i]);\n+\t\treftable_buf_release(&bufs[i]);\n \treaders_destroy(readers, ARRAY_SIZE(refs));\n \treftable_ref_record_release(&rec);\n \treftable_iterator_destroy(&it);\n@@ -277,7 +277,7 @@ static struct reftable_merged_table *\n merged_table_from_log_records(struct reftable_log_record **logs,\n \t\t\t      struct reftable_block_source **source,\n \t\t\t      struct reftable_reader ***readers, const size_t *sizes,\n-\t\t\t      struct strbuf *buf, const size_t n)\n+\t\t\t      struct reftable_buf *buf, const size_t n)\n {\n \tstruct reftable_merged_table *mt = NULL;\n \tstruct reftable_write_options opts = {\n@@ -361,7 +361,7 @@ static void t_merged_logs(void)\n \n \tstruct reftable_log_record *logs[] = { r1, r2, r3 };\n \tsize_t sizes[3] = { ARRAY_SIZE(r1), ARRAY_SIZE(r2), ARRAY_SIZE(r3) };\n-\tstruct strbuf bufs[3] = { STRBUF_INIT, STRBUF_INIT, STRBUF_INIT };\n+\tstruct reftable_buf bufs[3] = { REFTABLE_BUF_INIT, REFTABLE_BUF_INIT, REFTABLE_BUF_INIT };\n \tstruct reftable_block_source *bs = NULL;\n \tstruct reftable_reader **readers = NULL;\n \tstruct reftable_merged_table *mt = merged_table_from_log_records(\n@@ -412,7 +412,7 @@ static void t_merged_logs(void)\n \treftable_free(out);\n \n \tfor (i = 0; i < 3; i++)\n-\t\tstrbuf_release(&bufs[i]);\n+\t\treftable_buf_release(&bufs[i]);\n \treaders_destroy(readers, 3);\n \treftable_merged_table_free(mt);\n \treftable_free(bs);\n@@ -421,7 +421,7 @@ static void t_merged_logs(void)\n static void t_default_write_opts(void)\n {\n \tstruct reftable_write_options opts = { 0 };\n-\tstruct strbuf buf = STRBUF_INIT;\n+\tstruct reftable_buf buf = REFTABLE_BUF_INIT;\n \tstruct reftable_writer *w = t_reftable_strbuf_writer(&buf, &opts);\n \tstruct reftable_ref_record rec = {\n \t\t.refname = (char *) \"master\",\n@@ -457,7 +457,7 @@ static void t_default_write_opts(void)\n \n \treftable_reader_decref(rd);\n \treftable_merged_table_free(merged);\n-\tstrbuf_release(&buf);\n+\treftable_buf_release(&buf);\n }\n \n \ndiff --git a/t/unit-tests/t-reftable-reader.c b/t/unit-tests/t-reftable-reader.c\nindex eea86966c0d..8a18d7f9be4 100644\n--- a/t/unit-tests/t-reftable-reader.c\n+++ b/t/unit-tests/t-reftable-reader.c\n@@ -16,7 +16,7 @@ static int t_reader_seek_once(void)\n \tstruct reftable_ref_record ref = { 0 };\n \tstruct reftable_iterator it = { 0 };\n \tstruct reftable_reader *reader;\n-\tstruct strbuf buf = STRBUF_INIT;\n+\tstruct reftable_buf buf = REFTABLE_BUF_INIT;\n \tint ret;\n \n \tt_reftable_write_to_buf(&buf, records, ARRAY_SIZE(records), NULL, 0, NULL);\n@@ -40,7 +40,7 @@ static int t_reader_seek_once(void)\n \treftable_ref_record_release(&ref);\n \treftable_iterator_destroy(&it);\n \treftable_reader_decref(reader);\n-\tstrbuf_release(&buf);\n+\treftable_buf_release(&buf);\n \treturn 0;\n }\n \n@@ -57,7 +57,7 @@ static int t_reader_reseek(void)\n \tstruct reftable_ref_record ref = { 0 };\n \tstruct reftable_iterator it = { 0 };\n \tstruct reftable_reader *reader;\n-\tstruct strbuf buf = STRBUF_INIT;\n+\tstruct reftable_buf buf = REFTABLE_BUF_INIT;\n \tint ret;\n \n \tt_reftable_write_to_buf(&buf, records, ARRAY_SIZE(records), NULL, 0, NULL);\n@@ -84,7 +84,7 @@ static int t_reader_reseek(void)\n \treftable_ref_record_release(&ref);\n \treftable_iterator_destroy(&it);\n \treftable_reader_decref(reader);\n-\tstrbuf_release(&buf);\n+\treftable_buf_release(&buf);\n \treturn 0;\n }\n \ndiff --git a/t/unit-tests/t-reftable-readwrite.c b/t/unit-tests/t-reftable-readwrite.c\nindex 5f59b0ad6ad..c56a33f1a1e 100644\n--- a/t/unit-tests/t-reftable-readwrite.c\n+++ b/t/unit-tests/t-reftable-readwrite.c\n@@ -18,12 +18,12 @@ static const int update_index = 5;\n \n static void t_buffer(void)\n {\n-\tstruct strbuf buf = STRBUF_INIT;\n+\tstruct reftable_buf buf = REFTABLE_BUF_INIT;\n \tstruct reftable_block_source source = { 0 };\n \tstruct reftable_block out = { 0 };\n \tint n;\n \tuint8_t in[] = \"hello\";\n-\tstrbuf_add(&buf, in, sizeof(in));\n+\treftable_buf_add(&buf, in, sizeof(in));\n \tblock_source_from_strbuf(&source, &buf);\n \tcheck_int(block_source_size(&source), ==, 6);\n \tn = block_source_read_block(&source, &out, 0, sizeof(in));\n@@ -37,10 +37,10 @@ static void t_buffer(void)\n \n \treftable_block_done(&out);\n \tblock_source_close(&source);\n-\tstrbuf_release(&buf);\n+\treftable_buf_release(&buf);\n }\n \n-static void write_table(char ***names, struct strbuf *buf, int N,\n+static void write_table(char ***names, struct reftable_buf *buf, int N,\n \t\t\tint block_size, uint32_t hash_id)\n {\n \tstruct reftable_write_options opts = {\n@@ -82,7 +82,7 @@ static void write_table(char ***names, struct strbuf *buf, int N,\n \n static void t_log_buffer_size(void)\n {\n-\tstruct strbuf buf = STRBUF_INIT;\n+\tstruct reftable_buf buf = REFTABLE_BUF_INIT;\n \tstruct reftable_write_options opts = {\n \t\t.block_size = 4096,\n \t};\n@@ -114,12 +114,12 @@ static void t_log_buffer_size(void)\n \terr = reftable_writer_close(w);\n \tcheck(!err);\n \treftable_writer_free(w);\n-\tstrbuf_release(&buf);\n+\treftable_buf_release(&buf);\n }\n \n static void t_log_overflow(void)\n {\n-\tstruct strbuf buf = STRBUF_INIT;\n+\tstruct reftable_buf buf = REFTABLE_BUF_INIT;\n \tchar msg[256] = { 0 };\n \tstruct reftable_write_options opts = {\n \t\t.block_size = ARRAY_SIZE(msg),\n@@ -148,7 +148,7 @@ static void t_log_overflow(void)\n \terr = reftable_writer_add_log(w, &log);\n \tcheck_int(err, ==, REFTABLE_ENTRY_TOO_BIG_ERROR);\n \treftable_writer_free(w);\n-\tstrbuf_release(&buf);\n+\treftable_buf_release(&buf);\n }\n \n static void t_log_write_read(void)\n@@ -161,7 +161,7 @@ static void t_log_write_read(void)\n \tstruct reftable_iterator it = { 0 };\n \tstruct reftable_reader *reader;\n \tstruct reftable_block_source source = { 0 };\n-\tstruct strbuf buf = STRBUF_INIT;\n+\tstruct reftable_buf buf = REFTABLE_BUF_INIT;\n \tstruct reftable_writer *w = t_reftable_strbuf_writer(&buf, &opts);\n \tconst struct reftable_stats *stats = NULL;\n \tint N = 2, err, i, n;\n@@ -247,7 +247,7 @@ static void t_log_write_read(void)\n \treftable_iterator_destroy(&it);\n \n \t/* cleanup. */\n-\tstrbuf_release(&buf);\n+\treftable_buf_release(&buf);\n \tfree_names(names);\n \treftable_reader_decref(reader);\n }\n@@ -260,7 +260,7 @@ static void t_log_zlib_corruption(void)\n \tstruct reftable_iterator it = { 0 };\n \tstruct reftable_reader *reader;\n \tstruct reftable_block_source source = { 0 };\n-\tstruct strbuf buf = STRBUF_INIT;\n+\tstruct reftable_buf buf = REFTABLE_BUF_INIT;\n \tstruct reftable_writer *w = t_reftable_strbuf_writer(&buf, &opts);\n \tconst struct reftable_stats *stats = NULL;\n \tchar message[100] = { 0 };\n@@ -312,13 +312,13 @@ static void t_log_zlib_corruption(void)\n \n \t/* cleanup. */\n \treftable_reader_decref(reader);\n-\tstrbuf_release(&buf);\n+\treftable_buf_release(&buf);\n }\n \n static void t_table_read_write_sequential(void)\n {\n \tchar **names;\n-\tstruct strbuf buf = STRBUF_INIT;\n+\tstruct reftable_buf buf = REFTABLE_BUF_INIT;\n \tint N = 50;\n \tstruct reftable_iterator it = { 0 };\n \tstruct reftable_block_source source = { 0 };\n@@ -352,25 +352,25 @@ static void t_table_read_write_sequential(void)\n \n \treftable_iterator_destroy(&it);\n \treftable_reader_decref(reader);\n-\tstrbuf_release(&buf);\n+\treftable_buf_release(&buf);\n \tfree_names(names);\n }\n \n static void t_table_write_small_table(void)\n {\n \tchar **names;\n-\tstruct strbuf buf = STRBUF_INIT;\n+\tstruct reftable_buf buf = REFTABLE_BUF_INIT;\n \tint N = 1;\n \twrite_table(&names, &buf, N, 4096, GIT_SHA1_FORMAT_ID);\n \tcheck_int(buf.len, <, 200);\n-\tstrbuf_release(&buf);\n+\treftable_buf_release(&buf);\n \tfree_names(names);\n }\n \n static void t_table_read_api(void)\n {\n \tchar **names;\n-\tstruct strbuf buf = STRBUF_INIT;\n+\tstruct reftable_buf buf = REFTABLE_BUF_INIT;\n \tint N = 50;\n \tstruct reftable_reader *reader;\n \tstruct reftable_block_source source = { 0 };\n@@ -393,17 +393,17 @@ static void t_table_read_api(void)\n \terr = reftable_iterator_next_log(&it, &log);\n \tcheck_int(err, ==, REFTABLE_API_ERROR);\n \n-\tstrbuf_release(&buf);\n+\treftable_buf_release(&buf);\n \tfree_names(names);\n \treftable_iterator_destroy(&it);\n \treftable_reader_decref(reader);\n-\tstrbuf_release(&buf);\n+\treftable_buf_release(&buf);\n }\n \n static void t_table_read_write_seek(int index, int hash_id)\n {\n \tchar **names;\n-\tstruct strbuf buf = STRBUF_INIT;\n+\tstruct reftable_buf buf = REFTABLE_BUF_INIT;\n \tint N = 50;\n \tstruct reftable_reader *reader;\n \tstruct reftable_block_source source = { 0 };\n@@ -411,7 +411,7 @@ static void t_table_read_write_seek(int index, int hash_id)\n \tint i = 0;\n \n \tstruct reftable_iterator it = { 0 };\n-\tstruct strbuf pastLast = STRBUF_INIT;\n+\tstruct reftable_buf pastLast = REFTABLE_BUF_INIT;\n \tstruct reftable_ref_record ref = { 0 };\n \n \twrite_table(&names, &buf, N, 256, hash_id);\n@@ -443,8 +443,8 @@ static void t_table_read_write_seek(int index, int hash_id)\n \t\treftable_iterator_destroy(&it);\n \t}\n \n-\tstrbuf_addstr(&pastLast, names[N - 1]);\n-\tstrbuf_addstr(&pastLast, \"/\");\n+\treftable_buf_addstr(&pastLast, names[N - 1]);\n+\treftable_buf_addstr(&pastLast, \"/\");\n \n \terr = reftable_reader_init_ref_iterator(reader, &it);\n \tcheck(!err);\n@@ -457,10 +457,10 @@ static void t_table_read_write_seek(int index, int hash_id)\n \t\tcheck_int(err, >, 0);\n \t}\n \n-\tstrbuf_release(&pastLast);\n+\treftable_buf_release(&pastLast);\n \treftable_iterator_destroy(&it);\n \n-\tstrbuf_release(&buf);\n+\treftable_buf_release(&buf);\n \tfree_names(names);\n \treftable_reader_decref(reader);\n }\n@@ -492,7 +492,7 @@ static void t_table_refs_for(int indexed)\n \tstruct reftable_ref_record ref = { 0 };\n \tstruct reftable_reader *reader;\n \tstruct reftable_block_source source = { 0 };\n-\tstruct strbuf buf = STRBUF_INIT;\n+\tstruct reftable_buf buf = REFTABLE_BUF_INIT;\n \tstruct reftable_writer *w = t_reftable_strbuf_writer(&buf, &opts);\n \tstruct reftable_iterator it = { 0 };\n \tint N = 50, n, j, err, i;\n@@ -565,7 +565,7 @@ static void t_table_refs_for(int indexed)\n \t}\n \tcheck_int(j, ==, want_names_len);\n \n-\tstrbuf_release(&buf);\n+\treftable_buf_release(&buf);\n \tfree_names(want_names);\n \treftable_iterator_destroy(&it);\n \treftable_reader_decref(reader);\n@@ -584,7 +584,7 @@ static void t_table_refs_for_obj_index(void)\n static void t_write_empty_table(void)\n {\n \tstruct reftable_write_options opts = { 0 };\n-\tstruct strbuf buf = STRBUF_INIT;\n+\tstruct reftable_buf buf = REFTABLE_BUF_INIT;\n \tstruct reftable_writer *w = t_reftable_strbuf_writer(&buf, &opts);\n \tstruct reftable_block_source source = { 0 };\n \tstruct reftable_reader *rd = NULL;\n@@ -615,7 +615,7 @@ static void t_write_empty_table(void)\n \n \treftable_iterator_destroy(&it);\n \treftable_reader_decref(rd);\n-\tstrbuf_release(&buf);\n+\treftable_buf_release(&buf);\n }\n \n static void t_write_object_id_min_length(void)\n@@ -623,7 +623,7 @@ static void t_write_object_id_min_length(void)\n \tstruct reftable_write_options opts = {\n \t\t.block_size = 75,\n \t};\n-\tstruct strbuf buf = STRBUF_INIT;\n+\tstruct reftable_buf buf = REFTABLE_BUF_INIT;\n \tstruct reftable_writer *w = t_reftable_strbuf_writer(&buf, &opts);\n \tstruct reftable_ref_record ref = {\n \t\t.update_index = 1,\n@@ -649,7 +649,7 @@ static void t_write_object_id_min_length(void)\n \tcheck(!err);\n \tcheck_int(reftable_writer_stats(w)->object_id_len, ==, 2);\n \treftable_writer_free(w);\n-\tstrbuf_release(&buf);\n+\treftable_buf_release(&buf);\n }\n \n static void t_write_object_id_length(void)\n@@ -657,7 +657,7 @@ static void t_write_object_id_length(void)\n \tstruct reftable_write_options opts = {\n \t\t.block_size = 75,\n \t};\n-\tstruct strbuf buf = STRBUF_INIT;\n+\tstruct reftable_buf buf = REFTABLE_BUF_INIT;\n \tstruct reftable_writer *w = t_reftable_strbuf_writer(&buf, &opts);\n \tstruct reftable_ref_record ref = {\n \t\t.update_index = 1,\n@@ -684,13 +684,13 @@ static void t_write_object_id_length(void)\n \tcheck(!err);\n \tcheck_int(reftable_writer_stats(w)->object_id_len, ==, 16);\n \treftable_writer_free(w);\n-\tstrbuf_release(&buf);\n+\treftable_buf_release(&buf);\n }\n \n static void t_write_empty_key(void)\n {\n \tstruct reftable_write_options opts = { 0 };\n-\tstruct strbuf buf = STRBUF_INIT;\n+\tstruct reftable_buf buf = REFTABLE_BUF_INIT;\n \tstruct reftable_writer *w = t_reftable_strbuf_writer(&buf, &opts);\n \tstruct reftable_ref_record ref = {\n \t\t.refname = (char *) \"\",\n@@ -706,13 +706,13 @@ static void t_write_empty_key(void)\n \terr = reftable_writer_close(w);\n \tcheck_int(err, ==, REFTABLE_EMPTY_TABLE_ERROR);\n \treftable_writer_free(w);\n-\tstrbuf_release(&buf);\n+\treftable_buf_release(&buf);\n }\n \n static void t_write_key_order(void)\n {\n \tstruct reftable_write_options opts = { 0 };\n-\tstruct strbuf buf = STRBUF_INIT;\n+\tstruct reftable_buf buf = REFTABLE_BUF_INIT;\n \tstruct reftable_writer *w = t_reftable_strbuf_writer(&buf, &opts);\n \tstruct reftable_ref_record refs[2] = {\n \t\t{\n@@ -745,7 +745,7 @@ static void t_write_key_order(void)\n \n \treftable_writer_close(w);\n \treftable_writer_free(w);\n-\tstrbuf_release(&buf);\n+\treftable_buf_release(&buf);\n }\n \n static void t_write_multiple_indices(void)\n@@ -753,7 +753,7 @@ static void t_write_multiple_indices(void)\n \tstruct reftable_write_options opts = {\n \t\t.block_size = 100,\n \t};\n-\tstruct strbuf writer_buf = STRBUF_INIT;\n+\tstruct reftable_buf writer_buf = REFTABLE_BUF_INIT;\n \tstruct reftable_block_source source = { 0 };\n \tstruct reftable_iterator it = { 0 };\n \tconst struct reftable_stats *stats;\n@@ -822,7 +822,7 @@ static void t_write_multiple_indices(void)\n \treftable_iterator_destroy(&it);\n \treftable_writer_free(writer);\n \treftable_reader_decref(reader);\n-\tstrbuf_release(&writer_buf);\n+\treftable_buf_release(&writer_buf);\n }\n \n static void t_write_multi_level_index(void)\n@@ -830,7 +830,7 @@ static void t_write_multi_level_index(void)\n \tstruct reftable_write_options opts = {\n \t\t.block_size = 100,\n \t};\n-\tstruct strbuf writer_buf = STRBUF_INIT, buf = STRBUF_INIT;\n+\tstruct reftable_buf writer_buf = REFTABLE_BUF_INIT, buf = REFTABLE_BUF_INIT;\n \tstruct reftable_block_source source = { 0 };\n \tstruct reftable_iterator it = { 0 };\n \tconst struct reftable_stats *stats;\n@@ -878,13 +878,13 @@ static void t_write_multi_level_index(void)\n \treftable_iterator_destroy(&it);\n \treftable_writer_free(writer);\n \treftable_reader_decref(reader);\n-\tstrbuf_release(&writer_buf);\n-\tstrbuf_release(&buf);\n+\treftable_buf_release(&writer_buf);\n+\treftable_buf_release(&buf);\n }\n \n static void t_corrupt_table_empty(void)\n {\n-\tstruct strbuf buf = STRBUF_INIT;\n+\tstruct reftable_buf buf = REFTABLE_BUF_INIT;\n \tstruct reftable_block_source source = { 0 };\n \tstruct reftable_reader *reader;\n \tint err;\n@@ -897,17 +897,17 @@ static void t_corrupt_table_empty(void)\n static void t_corrupt_table(void)\n {\n \tuint8_t zeros[1024] = { 0 };\n-\tstruct strbuf buf = STRBUF_INIT;\n+\tstruct reftable_buf buf = REFTABLE_BUF_INIT;\n \tstruct reftable_block_source source = { 0 };\n \tstruct reftable_reader *reader;\n \tint err;\n-\tstrbuf_add(&buf, zeros, sizeof(zeros));\n+\treftable_buf_add(&buf, zeros, sizeof(zeros));\n \n \tblock_source_from_strbuf(&source, &buf);\n \terr = reftable_reader_new(&reader, &source, \"file.log\");\n \tcheck_int(err, ==, REFTABLE_FORMAT_ERROR);\n \n-\tstrbuf_release(&buf);\n+\treftable_buf_release(&buf);\n }\n \n int cmd_main(int argc UNUSED, const char *argv[] UNUSED)\ndiff --git a/t/unit-tests/t-reftable-record.c b/t/unit-tests/t-reftable-record.c\nindex a7f67d4d9f2..f2dd01688f3 100644\n--- a/t/unit-tests/t-reftable-record.c\n+++ b/t/unit-tests/t-reftable-record.c\n@@ -116,7 +116,7 @@ static void t_reftable_ref_record_compare_name(void)\n \n static void t_reftable_ref_record_roundtrip(void)\n {\n-\tstruct strbuf scratch = STRBUF_INIT;\n+\tstruct reftable_buf scratch = REFTABLE_BUF_INIT;\n \n \tfor (int i = REFTABLE_REF_DELETION; i < REFTABLE_NR_REF_VALUETYPES; i++) {\n \t\tstruct reftable_record in = {\n@@ -124,7 +124,7 @@ static void t_reftable_ref_record_roundtrip(void)\n \t\t\t.u.ref.value_type = i,\n \t\t};\n \t\tstruct reftable_record out = { .type = BLOCK_TYPE_REF };\n-\t\tstruct strbuf key = STRBUF_INIT;\n+\t\tstruct reftable_buf key = REFTABLE_BUF_INIT;\n \t\tuint8_t buffer[1024] = { 0 };\n \t\tstruct string_view dest = {\n \t\t\t.buf = buffer,\n@@ -166,11 +166,11 @@ static void t_reftable_ref_record_roundtrip(void)\n \t\t\t\t\t\t GIT_SHA1_RAWSZ));\n \t\treftable_record_release(&in);\n \n-\t\tstrbuf_release(&key);\n+\t\treftable_buf_release(&key);\n \t\treftable_record_release(&out);\n \t}\n \n-\tstrbuf_release(&scratch);\n+\treftable_buf_release(&scratch);\n }\n \n static void t_reftable_log_record_comparison(void)\n@@ -262,7 +262,7 @@ static void t_reftable_log_record_roundtrip(void)\n \t\t\t.value_type = REFTABLE_LOG_UPDATE,\n \t\t}\n \t};\n-\tstruct strbuf scratch = STRBUF_INIT;\n+\tstruct reftable_buf scratch = REFTABLE_BUF_INIT;\n \tset_hash(in[0].value.update.new_hash, 1);\n \tset_hash(in[0].value.update.old_hash, 2);\n \tset_hash(in[2].value.update.new_hash, 3);\n@@ -274,7 +274,7 @@ static void t_reftable_log_record_roundtrip(void)\n \n \tfor (size_t i = 0; i < ARRAY_SIZE(in); i++) {\n \t\tstruct reftable_record rec = { .type = BLOCK_TYPE_LOG };\n-\t\tstruct strbuf key = STRBUF_INIT;\n+\t\tstruct reftable_buf key = REFTABLE_BUF_INIT;\n \t\tuint8_t buffer[1024] = { 0 };\n \t\tstruct string_view dest = {\n \t\t\t.buf = buffer,\n@@ -313,11 +313,11 @@ static void t_reftable_log_record_roundtrip(void)\n \t\tcheck(reftable_log_record_equal(&in[i], &out.u.log,\n \t\t\t\t\t\t GIT_SHA1_RAWSZ));\n \t\treftable_log_record_release(&in[i]);\n-\t\tstrbuf_release(&key);\n+\t\treftable_buf_release(&key);\n \t\treftable_record_release(&out);\n \t}\n \n-\tstrbuf_release(&scratch);\n+\treftable_buf_release(&scratch);\n }\n \n static void t_key_roundtrip(void)\n@@ -327,30 +327,30 @@ static void t_key_roundtrip(void)\n \t\t.buf = buffer,\n \t\t.len = sizeof(buffer),\n \t};\n-\tstruct strbuf last_key = STRBUF_INIT;\n-\tstruct strbuf key = STRBUF_INIT;\n-\tstruct strbuf roundtrip = STRBUF_INIT;\n+\tstruct reftable_buf last_key = REFTABLE_BUF_INIT;\n+\tstruct reftable_buf key = REFTABLE_BUF_INIT;\n+\tstruct reftable_buf roundtrip = REFTABLE_BUF_INIT;\n \tint restart;\n \tuint8_t extra;\n \tint n, m;\n \tuint8_t rt_extra;\n \n-\tstrbuf_addstr(&last_key, \"refs/heads/master\");\n-\tstrbuf_addstr(&key, \"refs/tags/bla\");\n+\treftable_buf_addstr(&last_key, \"refs/heads/master\");\n+\treftable_buf_addstr(&key, \"refs/tags/bla\");\n \textra = 6;\n \tn = reftable_encode_key(&restart, dest, last_key, key, extra);\n \tcheck(!restart);\n \tcheck_int(n, >, 0);\n \n-\tstrbuf_addstr(&roundtrip, \"refs/heads/master\");\n+\treftable_buf_addstr(&roundtrip, \"refs/heads/master\");\n \tm = reftable_decode_key(&roundtrip, &rt_extra, dest);\n \tcheck_int(n, ==, m);\n-\tcheck(!strbuf_cmp(&key, &roundtrip));\n+\tcheck(!reftable_buf_cmp(&key, &roundtrip));\n \tcheck_int(rt_extra, ==, extra);\n \n-\tstrbuf_release(&last_key);\n-\tstrbuf_release(&key);\n-\tstrbuf_release(&roundtrip);\n+\treftable_buf_release(&last_key);\n+\treftable_buf_release(&key);\n+\treftable_buf_release(&roundtrip);\n }\n \n static void t_reftable_obj_record_comparison(void)\n@@ -413,7 +413,7 @@ static void t_reftable_obj_record_roundtrip(void)\n \t\t\t.hash_prefix_len = 5,\n \t\t},\n \t};\n-\tstruct strbuf scratch = STRBUF_INIT;\n+\tstruct reftable_buf scratch = REFTABLE_BUF_INIT;\n \n \tfor (size_t i = 0; i < ARRAY_SIZE(recs); i++) {\n \t\tuint8_t buffer[1024] = { 0 };\n@@ -427,7 +427,7 @@ static void t_reftable_obj_record_roundtrip(void)\n \t\t\t\t.obj = recs[i],\n \t\t\t},\n \t\t};\n-\t\tstruct strbuf key = STRBUF_INIT;\n+\t\tstruct reftable_buf key = REFTABLE_BUF_INIT;\n \t\tstruct reftable_record out = { .type = BLOCK_TYPE_OBJ };\n \t\tint n, m;\n \t\tuint8_t extra;\n@@ -443,11 +443,11 @@ static void t_reftable_obj_record_roundtrip(void)\n \t\tcheck_int(n, ==, m);\n \n \t\tcheck(reftable_record_equal(&in, &out, GIT_SHA1_RAWSZ));\n-\t\tstrbuf_release(&key);\n+\t\treftable_buf_release(&key);\n \t\treftable_record_release(&out);\n \t}\n \n-\tstrbuf_release(&scratch);\n+\treftable_buf_release(&scratch);\n }\n \n static void t_reftable_index_record_comparison(void)\n@@ -456,22 +456,22 @@ static void t_reftable_index_record_comparison(void)\n \t\t{\n \t\t\t.type = BLOCK_TYPE_INDEX,\n \t\t\t.u.idx.offset = 22,\n-\t\t\t.u.idx.last_key = STRBUF_INIT,\n+\t\t\t.u.idx.last_key = REFTABLE_BUF_INIT,\n \t\t},\n \t\t{\n \t\t\t.type = BLOCK_TYPE_INDEX,\n \t\t\t.u.idx.offset = 32,\n-\t\t\t.u.idx.last_key = STRBUF_INIT,\n+\t\t\t.u.idx.last_key = REFTABLE_BUF_INIT,\n \t\t},\n \t\t{\n \t\t\t.type = BLOCK_TYPE_INDEX,\n \t\t\t.u.idx.offset = 32,\n-\t\t\t.u.idx.last_key = STRBUF_INIT,\n+\t\t\t.u.idx.last_key = REFTABLE_BUF_INIT,\n \t\t},\n \t};\n-\tstrbuf_addstr(&in[0].u.idx.last_key, \"refs/heads/master\");\n-\tstrbuf_addstr(&in[1].u.idx.last_key, \"refs/heads/master\");\n-\tstrbuf_addstr(&in[2].u.idx.last_key, \"refs/heads/branch\");\n+\treftable_buf_addstr(&in[0].u.idx.last_key, \"refs/heads/master\");\n+\treftable_buf_addstr(&in[1].u.idx.last_key, \"refs/heads/master\");\n+\treftable_buf_addstr(&in[2].u.idx.last_key, \"refs/heads/branch\");\n \n \tcheck(!reftable_record_equal(&in[0], &in[1], GIT_SHA1_RAWSZ));\n \tcheck(!reftable_record_cmp(&in[0], &in[1]));\n@@ -493,7 +493,7 @@ static void t_reftable_index_record_roundtrip(void)\n \t\t.type = BLOCK_TYPE_INDEX,\n \t\t.u.idx = {\n \t\t\t.offset = 42,\n-\t\t\t.last_key = STRBUF_INIT,\n+\t\t\t.last_key = REFTABLE_BUF_INIT,\n \t\t},\n \t};\n \tuint8_t buffer[1024] = { 0 };\n@@ -501,21 +501,21 @@ static void t_reftable_index_record_roundtrip(void)\n \t\t.buf = buffer,\n \t\t.len = sizeof(buffer),\n \t};\n-\tstruct strbuf scratch = STRBUF_INIT;\n-\tstruct strbuf key = STRBUF_INIT;\n+\tstruct reftable_buf scratch = REFTABLE_BUF_INIT;\n+\tstruct reftable_buf key = REFTABLE_BUF_INIT;\n \tstruct reftable_record out = {\n \t\t.type = BLOCK_TYPE_INDEX,\n-\t\t.u.idx = { .last_key = STRBUF_INIT },\n+\t\t.u.idx = { .last_key = REFTABLE_BUF_INIT },\n \t};\n \tint n, m;\n \tuint8_t extra;\n \n-\tstrbuf_addstr(&in.u.idx.last_key, \"refs/heads/master\");\n+\treftable_buf_addstr(&in.u.idx.last_key, \"refs/heads/master\");\n \treftable_record_key(&in, &key);\n \tt_copy(&in);\n \n \tcheck(!reftable_record_is_deletion(&in));\n-\tcheck(!strbuf_cmp(&key, &in.u.idx.last_key));\n+\tcheck(!reftable_buf_cmp(&key, &in.u.idx.last_key));\n \tn = reftable_record_encode(&in, dest, GIT_SHA1_RAWSZ);\n \tcheck_int(n, >, 0);\n \n@@ -527,9 +527,9 @@ static void t_reftable_index_record_roundtrip(void)\n \tcheck(reftable_record_equal(&in, &out, GIT_SHA1_RAWSZ));\n \n \treftable_record_release(&out);\n-\tstrbuf_release(&key);\n-\tstrbuf_release(&scratch);\n-\tstrbuf_release(&in.u.idx.last_key);\n+\treftable_buf_release(&key);\n+\treftable_buf_release(&scratch);\n+\treftable_buf_release(&in.u.idx.last_key);\n }\n \n int cmd_main(int argc UNUSED, const char *argv[] UNUSED)\ndiff --git a/t/unit-tests/t-reftable-stack.c b/t/unit-tests/t-reftable-stack.c\nindex b56ea774312..f49856270d6 100644\n--- a/t/unit-tests/t-reftable-stack.c\n+++ b/t/unit-tests/t-reftable-stack.c\n@@ -16,7 +16,7 @@ license that can be found in the LICENSE file or at\n \n static void clear_dir(const char *dirname)\n {\n-\tstruct strbuf path = STRBUF_INIT;\n+\tstruct strbuf path = REFTABLE_BUF_INIT;\n \tstrbuf_addstr(&path, dirname);\n \tremove_dir_recursively(&path, 0);\n \tstrbuf_release(&path);\n@@ -145,7 +145,7 @@ static int write_test_log(struct reftable_writer *wr, void *arg)\n static void t_reftable_stack_add_one(void)\n {\n \tchar *dir = get_tmp_dir(__LINE__);\n-\tstruct strbuf scratch = STRBUF_INIT;\n+\tstruct reftable_buf scratch = REFTABLE_BUF_INIT;\n \tint mask = umask(002);\n \tstruct reftable_write_options opts = {\n \t\t.default_permissions = 0660,\n@@ -172,17 +172,17 @@ static void t_reftable_stack_add_one(void)\n \tcheck_int(st->readers_len, >, 0);\n \n #ifndef GIT_WINDOWS_NATIVE\n-\tstrbuf_addstr(&scratch, dir);\n-\tstrbuf_addstr(&scratch, \"/tables.list\");\n+\treftable_buf_addstr(&scratch, dir);\n+\treftable_buf_addstr(&scratch, \"/tables.list\");\n \terr = stat(scratch.buf, &stat_result);\n \tcheck(!err);\n \tcheck_int((stat_result.st_mode & 0777), ==, opts.default_permissions);\n \n-\tstrbuf_reset(&scratch);\n-\tstrbuf_addstr(&scratch, dir);\n-\tstrbuf_addstr(&scratch, \"/\");\n+\treftable_buf_reset(&scratch);\n+\treftable_buf_addstr(&scratch, dir);\n+\treftable_buf_addstr(&scratch, \"/\");\n \t/* do not try at home; not an external API for reftable. */\n-\tstrbuf_addstr(&scratch, st->readers[0]->name);\n+\treftable_buf_addstr(&scratch, st->readers[0]->name);\n \terr = stat(scratch.buf, &stat_result);\n \tcheck(!err);\n \tcheck_int((stat_result.st_mode & 0777), ==, opts.default_permissions);\n@@ -192,7 +192,7 @@ static void t_reftable_stack_add_one(void)\n \n \treftable_ref_record_release(&dest);\n \treftable_stack_destroy(st);\n-\tstrbuf_release(&scratch);\n+\treftable_buf_release(&scratch);\n \tclear_dir(dir);\n \tumask(mask);\n }\n@@ -414,7 +414,7 @@ static void t_reftable_stack_auto_compaction_fails_gracefully(void)\n \t};\n \tstruct reftable_write_options opts = { 0 };\n \tstruct reftable_stack *st;\n-\tstruct strbuf table_path = STRBUF_INIT;\n+\tstruct reftable_buf table_path = REFTABLE_BUF_INIT;\n \tchar *dir = get_tmp_dir(__LINE__);\n \tint err;\n \n@@ -432,10 +432,10 @@ static void t_reftable_stack_auto_compaction_fails_gracefully(void)\n \t * Adding a new table to the stack should not be impacted by this, even\n \t * though auto-compaction will now fail.\n \t */\n-\tstrbuf_addstr(&table_path, dir);\n-\tstrbuf_addstr(&table_path, \"/\");\n-\tstrbuf_addstr(&table_path, st->readers[0]->name);\n-\tstrbuf_addstr(&table_path, \".lock\");\n+\treftable_buf_addstr(&table_path, dir);\n+\treftable_buf_addstr(&table_path, \"/\");\n+\treftable_buf_addstr(&table_path, st->readers[0]->name);\n+\treftable_buf_addstr(&table_path, \".lock\");\n \twrite_file_buf(table_path.buf, \"\", 0);\n \n \tref.update_index = 2;\n@@ -446,7 +446,7 @@ static void t_reftable_stack_auto_compaction_fails_gracefully(void)\n \tcheck_int(st->stats.failures, ==, 1);\n \n \treftable_stack_destroy(st);\n-\tstrbuf_release(&table_path);\n+\treftable_buf_release(&table_path);\n \tclear_dir(dir);\n }\n \n@@ -516,7 +516,7 @@ static void t_reftable_stack_add(void)\n \tchar *dir = get_tmp_dir(__LINE__);\n \tstruct reftable_ref_record refs[2] = { 0 };\n \tstruct reftable_log_record logs[2] = { 0 };\n-\tstruct strbuf path = STRBUF_INIT;\n+\tstruct reftable_buf path = REFTABLE_BUF_INIT;\n \tstruct stat stat_result;\n \tsize_t i, N = ARRAY_SIZE(refs);\n \n@@ -575,17 +575,17 @@ static void t_reftable_stack_add(void)\n \t}\n \n #ifndef GIT_WINDOWS_NATIVE\n-\tstrbuf_addstr(&path, dir);\n-\tstrbuf_addstr(&path, \"/tables.list\");\n+\treftable_buf_addstr(&path, dir);\n+\treftable_buf_addstr(&path, \"/tables.list\");\n \terr = stat(path.buf, &stat_result);\n \tcheck(!err);\n \tcheck_int((stat_result.st_mode & 0777), ==, opts.default_permissions);\n \n-\tstrbuf_reset(&path);\n-\tstrbuf_addstr(&path, dir);\n-\tstrbuf_addstr(&path, \"/\");\n+\treftable_buf_reset(&path);\n+\treftable_buf_addstr(&path, dir);\n+\treftable_buf_addstr(&path, \"/\");\n \t/* do not try at home; not an external API for reftable. */\n-\tstrbuf_addstr(&path, st->readers[0]->name);\n+\treftable_buf_addstr(&path, st->readers[0]->name);\n \terr = stat(path.buf, &stat_result);\n \tcheck(!err);\n \tcheck_int((stat_result.st_mode & 0777), ==, opts.default_permissions);\n@@ -599,7 +599,7 @@ static void t_reftable_stack_add(void)\n \t\treftable_ref_record_release(&refs[i]);\n \t\treftable_log_record_release(&logs[i]);\n \t}\n-\tstrbuf_release(&path);\n+\treftable_buf_release(&path);\n \tclear_dir(dir);\n }\n \n@@ -1063,7 +1063,7 @@ static void t_reftable_stack_auto_compaction_with_locked_tables(void)\n \t\t.disable_auto_compact = 1,\n \t};\n \tstruct reftable_stack *st = NULL;\n-\tstruct strbuf buf = STRBUF_INIT;\n+\tstruct reftable_buf buf = REFTABLE_BUF_INIT;\n \tchar *dir = get_tmp_dir(__LINE__);\n \tint err;\n \n@@ -1078,10 +1078,10 @@ static void t_reftable_stack_auto_compaction_with_locked_tables(void)\n \t * size, we expect that auto-compaction will want to compact all of the\n \t * tables. Locking any of the tables will keep it from doing so.\n \t */\n-\tstrbuf_addstr(&buf, dir);\n-\tstrbuf_addstr(&buf, \"/\");\n-\tstrbuf_addstr(&buf, st->readers[2]->name);\n-\tstrbuf_addstr(&buf, \".lock\");\n+\treftable_buf_addstr(&buf, dir);\n+\treftable_buf_addstr(&buf, \"/\");\n+\treftable_buf_addstr(&buf, st->readers[2]->name);\n+\treftable_buf_addstr(&buf, \".lock\");\n \twrite_file_buf(buf.buf, \"\", 0);\n \n \t/*\n@@ -1096,7 +1096,7 @@ static void t_reftable_stack_auto_compaction_with_locked_tables(void)\n \tcheck_int(st->merged->readers_len, ==, 4);\n \n \treftable_stack_destroy(st);\n-\tstrbuf_release(&buf);\n+\treftable_buf_release(&buf);\n \tclear_dir(dir);\n }\n \n@@ -1153,7 +1153,7 @@ static void t_reftable_stack_compaction_with_locked_tables(void)\n \t\t.disable_auto_compact = 1,\n \t};\n \tstruct reftable_stack *st = NULL;\n-\tstruct strbuf buf = STRBUF_INIT;\n+\tstruct reftable_buf buf = REFTABLE_BUF_INIT;\n \tchar *dir = get_tmp_dir(__LINE__);\n \tint err;\n \n@@ -1164,10 +1164,10 @@ static void t_reftable_stack_compaction_with_locked_tables(void)\n \tcheck_int(st->merged->readers_len, ==, 3);\n \n \t/* Lock one of the tables that we're about to compact. */\n-\tstrbuf_addstr(&buf, dir);\n-\tstrbuf_addstr(&buf, \"/\");\n-\tstrbuf_addstr(&buf, st->readers[1]->name);\n-\tstrbuf_addstr(&buf, \".lock\");\n+\treftable_buf_addstr(&buf, dir);\n+\treftable_buf_addstr(&buf, \"/\");\n+\treftable_buf_addstr(&buf, st->readers[1]->name);\n+\treftable_buf_addstr(&buf, \".lock\");\n \twrite_file_buf(buf.buf, \"\", 0);\n \n \t/*\n@@ -1180,7 +1180,7 @@ static void t_reftable_stack_compaction_with_locked_tables(void)\n \tcheck_int(st->merged->readers_len, ==, 3);\n \n \treftable_stack_destroy(st);\n-\tstrbuf_release(&buf);\n+\treftable_buf_release(&buf);\n \tclear_dir(dir);\n }\n \n@@ -1306,7 +1306,7 @@ static void t_reftable_stack_reload_with_missing_table(void)\n \tstruct reftable_stack *st = NULL;\n \tstruct reftable_ref_record rec = { 0 };\n \tstruct reftable_iterator it = { 0 };\n-\tstruct strbuf table_path = STRBUF_INIT, content = STRBUF_INIT;\n+\tstruct reftable_buf table_path = REFTABLE_BUF_INIT, content = REFTABLE_BUF_INIT;\n \tchar *dir = get_tmp_dir(__LINE__);\n \tint err;\n \n@@ -1324,13 +1324,13 @@ static void t_reftable_stack_reload_with_missing_table(void)\n \t * our old readers. This should trigger a partial reload of the stack,\n \t * where we try to reuse our old readers.\n \t*/\n-\tstrbuf_addstr(&content, st->readers[0]->name);\n-\tstrbuf_addstr(&content, \"\\n\");\n-\tstrbuf_addstr(&content, st->readers[1]->name);\n-\tstrbuf_addstr(&content, \"\\n\");\n-\tstrbuf_addstr(&content, \"garbage\\n\");\n-\tstrbuf_addstr(&table_path, st->list_file);\n-\tstrbuf_addstr(&table_path, \".lock\");\n+\treftable_buf_addstr(&content, st->readers[0]->name);\n+\treftable_buf_addstr(&content, \"\\n\");\n+\treftable_buf_addstr(&content, st->readers[1]->name);\n+\treftable_buf_addstr(&content, \"\\n\");\n+\treftable_buf_addstr(&content, \"garbage\\n\");\n+\treftable_buf_addstr(&table_path, st->list_file);\n+\treftable_buf_addstr(&table_path, \".lock\");\n \twrite_file_buf(table_path.buf, content.buf, content.len);\n \terr = rename(table_path.buf, st->list_file);\n \tcheck(!err);\n@@ -1355,8 +1355,8 @@ static void t_reftable_stack_reload_with_missing_table(void)\n \treftable_ref_record_release(&rec);\n \treftable_iterator_destroy(&it);\n \treftable_stack_destroy(st);\n-\tstrbuf_release(&table_path);\n-\tstrbuf_release(&content);\n+\treftable_buf_release(&table_path);\n+\treftable_buf_release(&content);\n \tclear_dir(dir);\n }\n \n-- \n2.47.0.72.gef8ce8f3d4.dirty\n\n"},{"id":"505333","messageId":"f96328609331e48cee64c1268bc249d7cf2c7ecf.1729140565.git.ps@pks.im","threadId":"62313","inReplyTo":"cover.1729140565.git.ps@pks.im","subject":"[PATCH v3 05/10] reftable/blocksource: adapt interface name","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-10-17T04:53:59Z","receivedAt":"2024-10-17T04:54:03Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"Adapt the name of the `strbuf` block source to no longer relate to this\ninterface, but instead to the `reftable_buf` interface.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n reftable/blocksource.c              | 26 +++++++++++++-------------\n reftable/blocksource.h              |  4 ++--\n t/unit-tests/t-reftable-block.c     |  8 ++++----\n t/unit-tests/t-reftable-merged.c    |  6 +++---\n t/unit-tests/t-reftable-reader.c    |  4 ++--\n t/unit-tests/t-reftable-readwrite.c | 24 ++++++++++++------------\n 6 files changed, 36 insertions(+), 36 deletions(-)\n\ndiff --git a/reftable/blocksource.c b/reftable/blocksource.c\nindex d6242d67900..52e0915a67b 100644\n--- a/reftable/blocksource.c\n+++ b/reftable/blocksource.c\n@@ -13,19 +13,19 @@ license that can be found in the LICENSE file or at\n #include \"reftable-blocksource.h\"\n #include \"reftable-error.h\"\n \n-static void strbuf_return_block(void *b UNUSED, struct reftable_block *dest)\n+static void reftable_buf_return_block(void *b UNUSED, struct reftable_block *dest)\n {\n \tif (dest->len)\n \t\tmemset(dest->data, 0xff, dest->len);\n \treftable_free(dest->data);\n }\n \n-static void strbuf_close(void *b UNUSED)\n+static void reftable_buf_close(void *b UNUSED)\n {\n }\n \n-static int strbuf_read_block(void *v, struct reftable_block *dest, uint64_t off,\n-\t\t\t     uint32_t size)\n+static int reftable_buf_read_block(void *v, struct reftable_block *dest,\n+\t\t\t\t   uint64_t off, uint32_t size)\n {\n \tstruct reftable_buf *b = v;\n \tassert(off + size <= b->len);\n@@ -37,23 +37,23 @@ static int strbuf_read_block(void *v, struct reftable_block *dest, uint64_t off,\n \treturn size;\n }\n \n-static uint64_t strbuf_size(void *b)\n+static uint64_t reftable_buf_size(void *b)\n {\n \treturn ((struct reftable_buf *)b)->len;\n }\n \n-static struct reftable_block_source_vtable strbuf_vtable = {\n-\t.size = &strbuf_size,\n-\t.read_block = &strbuf_read_block,\n-\t.return_block = &strbuf_return_block,\n-\t.close = &strbuf_close,\n+static struct reftable_block_source_vtable reftable_buf_vtable = {\n+\t.size = &reftable_buf_size,\n+\t.read_block = &reftable_buf_read_block,\n+\t.return_block = &reftable_buf_return_block,\n+\t.close = &reftable_buf_close,\n };\n \n-void block_source_from_strbuf(struct reftable_block_source *bs,\n-\t\t\t      struct reftable_buf *buf)\n+void block_source_from_buf(struct reftable_block_source *bs,\n+\t\t\t   struct reftable_buf *buf)\n {\n \tassert(!bs->ops);\n-\tbs->ops = &strbuf_vtable;\n+\tbs->ops = &reftable_buf_vtable;\n \tbs->arg = buf;\n }\n \ndiff --git a/reftable/blocksource.h b/reftable/blocksource.h\nindex ee3647c6531..a84a3ccd891 100644\n--- a/reftable/blocksource.h\n+++ b/reftable/blocksource.h\n@@ -15,7 +15,7 @@ struct reftable_block_source;\n struct reftable_buf;\n \n /* Create an in-memory block source for reading reftables */\n-void block_source_from_strbuf(struct reftable_block_source *bs,\n-\t\t\t      struct reftable_buf *buf);\n+void block_source_from_buf(struct reftable_block_source *bs,\n+\t\t\t   struct reftable_buf *buf);\n \n #endif\ndiff --git a/t/unit-tests/t-reftable-block.c b/t/unit-tests/t-reftable-block.c\nindex 56514b43630..df1d45fe8e4 100644\n--- a/t/unit-tests/t-reftable-block.c\n+++ b/t/unit-tests/t-reftable-block.c\n@@ -34,7 +34,7 @@ static void t_ref_block_read_write(void)\n \tREFTABLE_CALLOC_ARRAY(block.data, block_size);\n \tcheck(block.data != NULL);\n \tblock.len = block_size;\n-\tblock_source_from_strbuf(&block.source ,&buf);\n+\tblock_source_from_buf(&block.source ,&buf);\n \tret = block_writer_init(&bw, BLOCK_TYPE_REF, block.data, block_size,\n \t\t\t\theader_off, hash_size(GIT_SHA1_FORMAT_ID));\n \tcheck(!ret);\n@@ -128,7 +128,7 @@ static void t_log_block_read_write(void)\n \tREFTABLE_CALLOC_ARRAY(block.data, block_size);\n \tcheck(block.data != NULL);\n \tblock.len = block_size;\n-\tblock_source_from_strbuf(&block.source ,&buf);\n+\tblock_source_from_buf(&block.source ,&buf);\n \tret = block_writer_init(&bw, BLOCK_TYPE_LOG, block.data, block_size,\n \t\t\t\theader_off, hash_size(GIT_SHA1_FORMAT_ID));\n \tcheck(!ret);\n@@ -218,7 +218,7 @@ static void t_obj_block_read_write(void)\n \tREFTABLE_CALLOC_ARRAY(block.data, block_size);\n \tcheck(block.data != NULL);\n \tblock.len = block_size;\n-\tblock_source_from_strbuf(&block.source, &buf);\n+\tblock_source_from_buf(&block.source, &buf);\n \tret = block_writer_init(&bw, BLOCK_TYPE_OBJ, block.data, block_size,\n \t\t\t\theader_off, hash_size(GIT_SHA1_FORMAT_ID));\n \tcheck(!ret);\n@@ -302,7 +302,7 @@ static void t_index_block_read_write(void)\n \tREFTABLE_CALLOC_ARRAY(block.data, block_size);\n \tcheck(block.data != NULL);\n \tblock.len = block_size;\n-\tblock_source_from_strbuf(&block.source, &buf);\n+\tblock_source_from_buf(&block.source, &buf);\n \tret = block_writer_init(&bw, BLOCK_TYPE_INDEX, block.data, block_size,\n \t\t\t\theader_off, hash_size(GIT_SHA1_FORMAT_ID));\n \tcheck(!ret);\ndiff --git a/t/unit-tests/t-reftable-merged.c b/t/unit-tests/t-reftable-merged.c\nindex 9b0162a4b32..484c18251f3 100644\n--- a/t/unit-tests/t-reftable-merged.c\n+++ b/t/unit-tests/t-reftable-merged.c\n@@ -35,7 +35,7 @@ merged_table_from_records(struct reftable_ref_record **refs,\n \n \tfor (size_t i = 0; i < n; i++) {\n \t\tt_reftable_write_to_buf(&buf[i], refs[i], sizes[i], NULL, 0, &opts);\n-\t\tblock_source_from_strbuf(&(*source)[i], &buf[i]);\n+\t\tblock_source_from_buf(&(*source)[i], &buf[i]);\n \n \t\terr = reftable_reader_new(&(*readers)[i], &(*source)[i],\n \t\t\t\t\t  \"name\");\n@@ -293,7 +293,7 @@ merged_table_from_log_records(struct reftable_log_record **logs,\n \n \tfor (size_t i = 0; i < n; i++) {\n \t\tt_reftable_write_to_buf(&buf[i], NULL, 0, logs[i], sizes[i], &opts);\n-\t\tblock_source_from_strbuf(&(*source)[i], &buf[i]);\n+\t\tblock_source_from_buf(&(*source)[i], &buf[i]);\n \n \t\terr = reftable_reader_new(&(*readers)[i], &(*source)[i],\n \t\t\t\t\t  \"name\");\n@@ -442,7 +442,7 @@ static void t_default_write_opts(void)\n \tcheck(!err);\n \treftable_writer_free(w);\n \n-\tblock_source_from_strbuf(&source, &buf);\n+\tblock_source_from_buf(&source, &buf);\n \n \terr = reftable_reader_new(&rd, &source, \"filename\");\n \tcheck(!err);\ndiff --git a/t/unit-tests/t-reftable-reader.c b/t/unit-tests/t-reftable-reader.c\nindex 8a18d7f9be4..19cb53b6415 100644\n--- a/t/unit-tests/t-reftable-reader.c\n+++ b/t/unit-tests/t-reftable-reader.c\n@@ -20,7 +20,7 @@ static int t_reader_seek_once(void)\n \tint ret;\n \n \tt_reftable_write_to_buf(&buf, records, ARRAY_SIZE(records), NULL, 0, NULL);\n-\tblock_source_from_strbuf(&source, &buf);\n+\tblock_source_from_buf(&source, &buf);\n \n \tret = reftable_reader_new(&reader, &source, \"name\");\n \tcheck(!ret);\n@@ -61,7 +61,7 @@ static int t_reader_reseek(void)\n \tint ret;\n \n \tt_reftable_write_to_buf(&buf, records, ARRAY_SIZE(records), NULL, 0, NULL);\n-\tblock_source_from_strbuf(&source, &buf);\n+\tblock_source_from_buf(&source, &buf);\n \n \tret = reftable_reader_new(&reader, &source, \"name\");\n \tcheck(!ret);\ndiff --git a/t/unit-tests/t-reftable-readwrite.c b/t/unit-tests/t-reftable-readwrite.c\nindex c56a33f1a1e..7c7c72bb162 100644\n--- a/t/unit-tests/t-reftable-readwrite.c\n+++ b/t/unit-tests/t-reftable-readwrite.c\n@@ -24,7 +24,7 @@ static void t_buffer(void)\n \tint n;\n \tuint8_t in[] = \"hello\";\n \treftable_buf_add(&buf, in, sizeof(in));\n-\tblock_source_from_strbuf(&source, &buf);\n+\tblock_source_from_buf(&source, &buf);\n \tcheck_int(block_source_size(&source), ==, 6);\n \tn = block_source_read_block(&source, &out, 0, sizeof(in));\n \tcheck_int(n, ==, sizeof(in));\n@@ -207,7 +207,7 @@ static void t_log_write_read(void)\n \treftable_writer_free(w);\n \tw = NULL;\n \n-\tblock_source_from_strbuf(&source, &buf);\n+\tblock_source_from_buf(&source, &buf);\n \n \terr = reftable_reader_new(&reader, &source, \"file.log\");\n \tcheck(!err);\n@@ -298,7 +298,7 @@ static void t_log_zlib_corruption(void)\n \t/* corrupt the data. */\n \tbuf.buf[50] ^= 0x99;\n \n-\tblock_source_from_strbuf(&source, &buf);\n+\tblock_source_from_buf(&source, &buf);\n \n \terr = reftable_reader_new(&reader, &source, \"file.log\");\n \tcheck(!err);\n@@ -328,7 +328,7 @@ static void t_table_read_write_sequential(void)\n \n \twrite_table(&names, &buf, N, 256, GIT_SHA1_FORMAT_ID);\n \n-\tblock_source_from_strbuf(&source, &buf);\n+\tblock_source_from_buf(&source, &buf);\n \n \terr = reftable_reader_new(&reader, &source, \"file.ref\");\n \tcheck(!err);\n@@ -380,7 +380,7 @@ static void t_table_read_api(void)\n \n \twrite_table(&names, &buf, N, 256, GIT_SHA1_FORMAT_ID);\n \n-\tblock_source_from_strbuf(&source, &buf);\n+\tblock_source_from_buf(&source, &buf);\n \n \terr = reftable_reader_new(&reader, &source, \"file.ref\");\n \tcheck(!err);\n@@ -416,7 +416,7 @@ static void t_table_read_write_seek(int index, int hash_id)\n \n \twrite_table(&names, &buf, N, 256, hash_id);\n \n-\tblock_source_from_strbuf(&source, &buf);\n+\tblock_source_from_buf(&source, &buf);\n \n \terr = reftable_reader_new(&reader, &source, \"file.ref\");\n \tcheck(!err);\n@@ -538,7 +538,7 @@ static void t_table_refs_for(int indexed)\n \treftable_writer_free(w);\n \tw = NULL;\n \n-\tblock_source_from_strbuf(&source, &buf);\n+\tblock_source_from_buf(&source, &buf);\n \n \terr = reftable_reader_new(&reader, &source, \"file.ref\");\n \tcheck(!err);\n@@ -600,7 +600,7 @@ static void t_write_empty_table(void)\n \n \tcheck_int(buf.len, ==, header_size(1) + footer_size(1));\n \n-\tblock_source_from_strbuf(&source, &buf);\n+\tblock_source_from_buf(&source, &buf);\n \n \terr = reftable_reader_new(&rd, &source, \"filename\");\n \tcheck(!err);\n@@ -806,7 +806,7 @@ static void t_write_multiple_indices(void)\n \tcheck_int(stats->obj_stats.index_offset, >, 0);\n \tcheck_int(stats->log_stats.index_offset, >, 0);\n \n-\tblock_source_from_strbuf(&source, &writer_buf);\n+\tblock_source_from_buf(&source, &writer_buf);\n \terr = reftable_reader_new(&reader, &source, \"filename\");\n \tcheck(!err);\n \n@@ -863,7 +863,7 @@ static void t_write_multi_level_index(void)\n \tstats = reftable_writer_stats(writer);\n \tcheck_int(stats->ref_stats.max_index_level, ==, 2);\n \n-\tblock_source_from_strbuf(&source, &writer_buf);\n+\tblock_source_from_buf(&source, &writer_buf);\n \terr = reftable_reader_new(&reader, &source, \"filename\");\n \tcheck(!err);\n \n@@ -889,7 +889,7 @@ static void t_corrupt_table_empty(void)\n \tstruct reftable_reader *reader;\n \tint err;\n \n-\tblock_source_from_strbuf(&source, &buf);\n+\tblock_source_from_buf(&source, &buf);\n \terr = reftable_reader_new(&reader, &source, \"file.log\");\n \tcheck_int(err, ==, REFTABLE_FORMAT_ERROR);\n }\n@@ -903,7 +903,7 @@ static void t_corrupt_table(void)\n \tint err;\n \treftable_buf_add(&buf, zeros, sizeof(zeros));\n \n-\tblock_source_from_strbuf(&source, &buf);\n+\tblock_source_from_buf(&source, &buf);\n \terr = reftable_reader_new(&reader, &source, \"file.log\");\n \tcheck_int(err, ==, REFTABLE_FORMAT_ERROR);\n \n-- \n2.47.0.72.gef8ce8f3d4.dirty\n\n"},{"id":"505334","messageId":"d850a2fe7d0f86dc5699674633ac396f0b2015c2.1729140565.git.ps@pks.im","threadId":"62313","inReplyTo":"cover.1729140565.git.ps@pks.im","subject":"[PATCH v3 06/10] t/unit-tests: check for `reftable_buf` allocation errors","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-10-17T04:54:02Z","receivedAt":"2024-10-17T04:54:05Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"Adapt our unit tests to check for allocations errors.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n t/unit-tests/t-reftable-basics.c    |  4 +-\n t/unit-tests/t-reftable-block.c     |  4 +-\n t/unit-tests/t-reftable-readwrite.c |  8 ++--\n t/unit-tests/t-reftable-record.c    | 14 +++----\n t/unit-tests/t-reftable-stack.c     | 58 ++++++++++++++---------------\n 5 files changed, 44 insertions(+), 44 deletions(-)\n\ndiff --git a/t/unit-tests/t-reftable-basics.c b/t/unit-tests/t-reftable-basics.c\nindex a814e819756..a329f552025 100644\n--- a/t/unit-tests/t-reftable-basics.c\n+++ b/t/unit-tests/t-reftable-basics.c\n@@ -113,8 +113,8 @@ int cmd_main(int argc UNUSED, const char *argv[] UNUSED)\n \t\t};\n \n \t\tfor (size_t i = 0; i < ARRAY_SIZE(cases); i++) {\n-\t\t\treftable_buf_addstr(&a, cases[i].a);\n-\t\t\treftable_buf_addstr(&b, cases[i].b);\n+\t\t\tcheck(!reftable_buf_addstr(&a, cases[i].a));\n+\t\t\tcheck(!reftable_buf_addstr(&b, cases[i].b));\n \t\t\tcheck_int(common_prefix_size(&a, &b), ==, cases[i].want);\n \t\t\treftable_buf_reset(&a);\n \t\t\treftable_buf_reset(&b);\ndiff --git a/t/unit-tests/t-reftable-block.c b/t/unit-tests/t-reftable-block.c\nindex df1d45fe8e4..f9af907117b 100644\n--- a/t/unit-tests/t-reftable-block.c\n+++ b/t/unit-tests/t-reftable-block.c\n@@ -167,7 +167,7 @@ static void t_log_block_read_write(void)\n \tfor (i = 0; i < N; i++) {\n \t\tblock_iter_reset(&it);\n \t\treftable_buf_reset(&want);\n-\t\treftable_buf_addstr(&want, recs[i].u.log.refname);\n+\t\tcheck(!reftable_buf_addstr(&want, recs[i].u.log.refname));\n \n \t\tret = block_iter_seek_key(&it, &br, &want);\n \t\tcheck_int(ret, ==, 0);\n@@ -314,7 +314,7 @@ static void t_index_block_read_write(void)\n \n \t\treftable_buf_init(&recs[i].u.idx.last_key);\n \t\trecs[i].type = BLOCK_TYPE_INDEX;\n-\t\treftable_buf_addstr(&recs[i].u.idx.last_key, buf);\n+\t\tcheck(!reftable_buf_addstr(&recs[i].u.idx.last_key, buf));\n \t\trecs[i].u.idx.offset = i;\n \n \t\tret = block_writer_add(&bw, &recs[i]);\ndiff --git a/t/unit-tests/t-reftable-readwrite.c b/t/unit-tests/t-reftable-readwrite.c\nindex 7c7c72bb162..d279b86df0a 100644\n--- a/t/unit-tests/t-reftable-readwrite.c\n+++ b/t/unit-tests/t-reftable-readwrite.c\n@@ -23,7 +23,7 @@ static void t_buffer(void)\n \tstruct reftable_block out = { 0 };\n \tint n;\n \tuint8_t in[] = \"hello\";\n-\treftable_buf_add(&buf, in, sizeof(in));\n+\tcheck(!reftable_buf_add(&buf, in, sizeof(in)));\n \tblock_source_from_buf(&source, &buf);\n \tcheck_int(block_source_size(&source), ==, 6);\n \tn = block_source_read_block(&source, &out, 0, sizeof(in));\n@@ -443,8 +443,8 @@ static void t_table_read_write_seek(int index, int hash_id)\n \t\treftable_iterator_destroy(&it);\n \t}\n \n-\treftable_buf_addstr(&pastLast, names[N - 1]);\n-\treftable_buf_addstr(&pastLast, \"/\");\n+\tcheck(!reftable_buf_addstr(&pastLast, names[N - 1]));\n+\tcheck(!reftable_buf_addstr(&pastLast, \"/\"));\n \n \terr = reftable_reader_init_ref_iterator(reader, &it);\n \tcheck(!err);\n@@ -901,7 +901,7 @@ static void t_corrupt_table(void)\n \tstruct reftable_block_source source = { 0 };\n \tstruct reftable_reader *reader;\n \tint err;\n-\treftable_buf_add(&buf, zeros, sizeof(zeros));\n+\tcheck(!reftable_buf_add(&buf, zeros, sizeof(zeros)));\n \n \tblock_source_from_buf(&source, &buf);\n \terr = reftable_reader_new(&reader, &source, \"file.log\");\ndiff --git a/t/unit-tests/t-reftable-record.c b/t/unit-tests/t-reftable-record.c\nindex f2dd01688f3..eb98bf2da91 100644\n--- a/t/unit-tests/t-reftable-record.c\n+++ b/t/unit-tests/t-reftable-record.c\n@@ -335,14 +335,14 @@ static void t_key_roundtrip(void)\n \tint n, m;\n \tuint8_t rt_extra;\n \n-\treftable_buf_addstr(&last_key, \"refs/heads/master\");\n-\treftable_buf_addstr(&key, \"refs/tags/bla\");\n+\tcheck(!reftable_buf_addstr(&last_key, \"refs/heads/master\"));\n+\tcheck(!reftable_buf_addstr(&key, \"refs/tags/bla\"));\n \textra = 6;\n \tn = reftable_encode_key(&restart, dest, last_key, key, extra);\n \tcheck(!restart);\n \tcheck_int(n, >, 0);\n \n-\treftable_buf_addstr(&roundtrip, \"refs/heads/master\");\n+\tcheck(!reftable_buf_addstr(&roundtrip, \"refs/heads/master\"));\n \tm = reftable_decode_key(&roundtrip, &rt_extra, dest);\n \tcheck_int(n, ==, m);\n \tcheck(!reftable_buf_cmp(&key, &roundtrip));\n@@ -469,9 +469,9 @@ static void t_reftable_index_record_comparison(void)\n \t\t\t.u.idx.last_key = REFTABLE_BUF_INIT,\n \t\t},\n \t};\n-\treftable_buf_addstr(&in[0].u.idx.last_key, \"refs/heads/master\");\n-\treftable_buf_addstr(&in[1].u.idx.last_key, \"refs/heads/master\");\n-\treftable_buf_addstr(&in[2].u.idx.last_key, \"refs/heads/branch\");\n+\tcheck(!reftable_buf_addstr(&in[0].u.idx.last_key, \"refs/heads/master\"));\n+\tcheck(!reftable_buf_addstr(&in[1].u.idx.last_key, \"refs/heads/master\"));\n+\tcheck(!reftable_buf_addstr(&in[2].u.idx.last_key, \"refs/heads/branch\"));\n \n \tcheck(!reftable_record_equal(&in[0], &in[1], GIT_SHA1_RAWSZ));\n \tcheck(!reftable_record_cmp(&in[0], &in[1]));\n@@ -510,7 +510,7 @@ static void t_reftable_index_record_roundtrip(void)\n \tint n, m;\n \tuint8_t extra;\n \n-\treftable_buf_addstr(&in.u.idx.last_key, \"refs/heads/master\");\n+\tcheck(!reftable_buf_addstr(&in.u.idx.last_key, \"refs/heads/master\"));\n \treftable_record_key(&in, &key);\n \tt_copy(&in);\n \ndiff --git a/t/unit-tests/t-reftable-stack.c b/t/unit-tests/t-reftable-stack.c\nindex f49856270d6..72f6747064f 100644\n--- a/t/unit-tests/t-reftable-stack.c\n+++ b/t/unit-tests/t-reftable-stack.c\n@@ -172,17 +172,17 @@ static void t_reftable_stack_add_one(void)\n \tcheck_int(st->readers_len, >, 0);\n \n #ifndef GIT_WINDOWS_NATIVE\n-\treftable_buf_addstr(&scratch, dir);\n-\treftable_buf_addstr(&scratch, \"/tables.list\");\n+\tcheck(!reftable_buf_addstr(&scratch, dir));\n+\tcheck(!reftable_buf_addstr(&scratch, \"/tables.list\"));\n \terr = stat(scratch.buf, &stat_result);\n \tcheck(!err);\n \tcheck_int((stat_result.st_mode & 0777), ==, opts.default_permissions);\n \n \treftable_buf_reset(&scratch);\n-\treftable_buf_addstr(&scratch, dir);\n-\treftable_buf_addstr(&scratch, \"/\");\n+\tcheck(!reftable_buf_addstr(&scratch, dir));\n+\tcheck(!reftable_buf_addstr(&scratch, \"/\"));\n \t/* do not try at home; not an external API for reftable. */\n-\treftable_buf_addstr(&scratch, st->readers[0]->name);\n+\tcheck(!reftable_buf_addstr(&scratch, st->readers[0]->name));\n \terr = stat(scratch.buf, &stat_result);\n \tcheck(!err);\n \tcheck_int((stat_result.st_mode & 0777), ==, opts.default_permissions);\n@@ -432,10 +432,10 @@ static void t_reftable_stack_auto_compaction_fails_gracefully(void)\n \t * Adding a new table to the stack should not be impacted by this, even\n \t * though auto-compaction will now fail.\n \t */\n-\treftable_buf_addstr(&table_path, dir);\n-\treftable_buf_addstr(&table_path, \"/\");\n-\treftable_buf_addstr(&table_path, st->readers[0]->name);\n-\treftable_buf_addstr(&table_path, \".lock\");\n+\tcheck(!reftable_buf_addstr(&table_path, dir));\n+\tcheck(!reftable_buf_addstr(&table_path, \"/\"));\n+\tcheck(!reftable_buf_addstr(&table_path, st->readers[0]->name));\n+\tcheck(!reftable_buf_addstr(&table_path, \".lock\"));\n \twrite_file_buf(table_path.buf, \"\", 0);\n \n \tref.update_index = 2;\n@@ -575,17 +575,17 @@ static void t_reftable_stack_add(void)\n \t}\n \n #ifndef GIT_WINDOWS_NATIVE\n-\treftable_buf_addstr(&path, dir);\n-\treftable_buf_addstr(&path, \"/tables.list\");\n+\tcheck(!reftable_buf_addstr(&path, dir));\n+\tcheck(!reftable_buf_addstr(&path, \"/tables.list\"));\n \terr = stat(path.buf, &stat_result);\n \tcheck(!err);\n \tcheck_int((stat_result.st_mode & 0777), ==, opts.default_permissions);\n \n \treftable_buf_reset(&path);\n-\treftable_buf_addstr(&path, dir);\n-\treftable_buf_addstr(&path, \"/\");\n+\tcheck(!reftable_buf_addstr(&path, dir));\n+\tcheck(!reftable_buf_addstr(&path, \"/\"));\n \t/* do not try at home; not an external API for reftable. */\n-\treftable_buf_addstr(&path, st->readers[0]->name);\n+\tcheck(!reftable_buf_addstr(&path, st->readers[0]->name));\n \terr = stat(path.buf, &stat_result);\n \tcheck(!err);\n \tcheck_int((stat_result.st_mode & 0777), ==, opts.default_permissions);\n@@ -1078,10 +1078,10 @@ static void t_reftable_stack_auto_compaction_with_locked_tables(void)\n \t * size, we expect that auto-compaction will want to compact all of the\n \t * tables. Locking any of the tables will keep it from doing so.\n \t */\n-\treftable_buf_addstr(&buf, dir);\n-\treftable_buf_addstr(&buf, \"/\");\n-\treftable_buf_addstr(&buf, st->readers[2]->name);\n-\treftable_buf_addstr(&buf, \".lock\");\n+\tcheck(!reftable_buf_addstr(&buf, dir));\n+\tcheck(!reftable_buf_addstr(&buf, \"/\"));\n+\tcheck(!reftable_buf_addstr(&buf, st->readers[2]->name));\n+\tcheck(!reftable_buf_addstr(&buf, \".lock\"));\n \twrite_file_buf(buf.buf, \"\", 0);\n \n \t/*\n@@ -1164,10 +1164,10 @@ static void t_reftable_stack_compaction_with_locked_tables(void)\n \tcheck_int(st->merged->readers_len, ==, 3);\n \n \t/* Lock one of the tables that we're about to compact. */\n-\treftable_buf_addstr(&buf, dir);\n-\treftable_buf_addstr(&buf, \"/\");\n-\treftable_buf_addstr(&buf, st->readers[1]->name);\n-\treftable_buf_addstr(&buf, \".lock\");\n+\tcheck(!reftable_buf_addstr(&buf, dir));\n+\tcheck(!reftable_buf_addstr(&buf, \"/\"));\n+\tcheck(!reftable_buf_addstr(&buf, st->readers[1]->name));\n+\tcheck(!reftable_buf_addstr(&buf, \".lock\"));\n \twrite_file_buf(buf.buf, \"\", 0);\n \n \t/*\n@@ -1324,13 +1324,13 @@ static void t_reftable_stack_reload_with_missing_table(void)\n \t * our old readers. This should trigger a partial reload of the stack,\n \t * where we try to reuse our old readers.\n \t*/\n-\treftable_buf_addstr(&content, st->readers[0]->name);\n-\treftable_buf_addstr(&content, \"\\n\");\n-\treftable_buf_addstr(&content, st->readers[1]->name);\n-\treftable_buf_addstr(&content, \"\\n\");\n-\treftable_buf_addstr(&content, \"garbage\\n\");\n-\treftable_buf_addstr(&table_path, st->list_file);\n-\treftable_buf_addstr(&table_path, \".lock\");\n+\tcheck(!reftable_buf_addstr(&content, st->readers[0]->name));\n+\tcheck(!reftable_buf_addstr(&content, \"\\n\"));\n+\tcheck(!reftable_buf_addstr(&content, st->readers[1]->name));\n+\tcheck(!reftable_buf_addstr(&content, \"\\n\"));\n+\tcheck(!reftable_buf_addstr(&content, \"garbage\\n\"));\n+\tcheck(!reftable_buf_addstr(&table_path, st->list_file));\n+\tcheck(!reftable_buf_addstr(&table_path, \".lock\"));\n \twrite_file_buf(table_path.buf, content.buf, content.len);\n \terr = rename(table_path.buf, st->list_file);\n \tcheck(!err);\n-- \n2.47.0.72.gef8ce8f3d4.dirty\n\n"},{"id":"505335","messageId":"8f8e2ca39624208e71aaca13e439ba7d32e77970.1729140565.git.ps@pks.im","threadId":"62313","inReplyTo":"cover.1729140565.git.ps@pks.im","subject":"[PATCH v3 07/10] reftable/stack: adapt `format_name()` to handle allocation failures","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-10-17T04:54:05Z","receivedAt":"2024-10-17T04:54:08Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"The `format_name()` function cannot pass any errors to the caller as it\nhas a `void` return type. Adapt it and its callers such that we can\nhandle errors and start handling allocation failures.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n reftable/stack.c | 28 +++++++++++++++++++---------\n 1 file changed, 19 insertions(+), 9 deletions(-)\n\ndiff --git a/reftable/stack.c b/reftable/stack.c\nindex 6ba48ddce5d..e94eb3c4685 100644\n--- a/reftable/stack.c\n+++ b/reftable/stack.c\n@@ -623,14 +623,14 @@ int reftable_stack_add(struct reftable_stack *st,\n \treturn 0;\n }\n \n-static void format_name(struct reftable_buf *dest, uint64_t min, uint64_t max)\n+static int format_name(struct reftable_buf *dest, uint64_t min, uint64_t max)\n {\n \tchar buf[100];\n \tuint32_t rnd = (uint32_t)git_rand();\n \tsnprintf(buf, sizeof(buf), \"0x%012\" PRIx64 \"-0x%012\" PRIx64 \"-%08x\",\n \t\t min, max, rnd);\n \treftable_buf_reset(dest);\n-\treftable_buf_addstr(dest, buf);\n+\treturn reftable_buf_addstr(dest, buf);\n }\n \n struct reftable_addition {\n@@ -846,7 +846,10 @@ int reftable_addition_add(struct reftable_addition *add,\n \tint tab_fd;\n \n \treftable_buf_reset(&next_name);\n-\tformat_name(&next_name, add->next_update_index, add->next_update_index);\n+\n+\terr = format_name(&next_name, add->next_update_index, add->next_update_index);\n+\tif (err < 0)\n+\t\tgoto done;\n \n \tstack_filename(&temp_tab_file_name, add->stack, next_name.buf);\n \treftable_buf_addstr(&temp_tab_file_name, \".temp.XXXXXX\");\n@@ -893,7 +896,9 @@ int reftable_addition_add(struct reftable_addition *add,\n \t\tgoto done;\n \t}\n \n-\tformat_name(&next_name, wr->min_update_index, wr->max_update_index);\n+\terr = format_name(&next_name, wr->min_update_index, wr->max_update_index);\n+\tif (err < 0)\n+\t\tgoto done;\n \treftable_buf_addstr(&next_name, \".ref\");\n \tstack_filename(&tab_file_name, add->stack, next_name.buf);\n \n@@ -944,9 +949,11 @@ static int stack_compact_locked(struct reftable_stack *st,\n \tstruct tempfile *tab_file;\n \tint tab_fd, err = 0;\n \n-\tformat_name(&next_name,\n-\t\t    reftable_reader_min_update_index(st->readers[first]),\n-\t\t    reftable_reader_max_update_index(st->readers[last]));\n+\terr = format_name(&next_name, reftable_reader_min_update_index(st->readers[first]),\n+\t\t\t  reftable_reader_max_update_index(st->readers[last]));\n+\tif (err < 0)\n+\t\tgoto done;\n+\n \tstack_filename(&tab_file_path, st, next_name.buf);\n \treftable_buf_addstr(&tab_file_path, \".temp.XXXXXX\");\n \n@@ -1370,8 +1377,11 @@ static int stack_compact_range(struct reftable_stack *st,\n \t * it into place now.\n \t */\n \tif (!is_empty_table) {\n-\t\tformat_name(&new_table_name, st->readers[first]->min_update_index,\n-\t\t\t    st->readers[last]->max_update_index);\n+\t\terr = format_name(&new_table_name, st->readers[first]->min_update_index,\n+\t\t\t\t  st->readers[last]->max_update_index);\n+\t\tif (err < 0)\n+\t\t\tgoto done;\n+\n \t\treftable_buf_addstr(&new_table_name, \".ref\");\n \t\tstack_filename(&new_table_path, st, new_table_name.buf);\n \n-- \n2.47.0.72.gef8ce8f3d4.dirty\n\n"},{"id":"505336","messageId":"268e4cd6fc6fb0d9ab6216723dc39c5cada3734c.1729140565.git.ps@pks.im","threadId":"62313","inReplyTo":"cover.1729140565.git.ps@pks.im","subject":"[PATCH v3 08/10] reftable/record: adapt `reftable_record_key()` to handle allocation failures","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-10-17T04:54:08Z","receivedAt":"2024-10-17T04:54:13Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"The `reftable_record_key()` function cannot pass any errors to the\ncaller as it has a `void` return type. Adapt it and its callers such\nthat we can handle errors and start handling allocation failures.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n reftable/block.c  | 20 +++++++++++++++-----\n reftable/reader.c |  8 ++++++--\n reftable/record.c | 32 ++++++++++++++++++++------------\n reftable/record.h |  4 ++--\n reftable/writer.c |  5 ++++-\n 5 files changed, 47 insertions(+), 22 deletions(-)\n\ndiff --git a/reftable/block.c b/reftable/block.c\nindex 4f62b823db8..697b8b41531 100644\n--- a/reftable/block.c\n+++ b/reftable/block.c\n@@ -111,9 +111,12 @@ int block_writer_add(struct block_writer *w, struct reftable_record *rec)\n \tint is_restart = 0;\n \tstruct reftable_buf key = REFTABLE_BUF_INIT;\n \tint n = 0;\n-\tint err = -1;\n+\tint err;\n+\n+\terr = reftable_record_key(rec, &key);\n+\tif (err < 0)\n+\t\tgoto done;\n \n-\treftable_record_key(rec, &key);\n \tif (!key.len) {\n \t\terr = REFTABLE_API_ERROR;\n \t\tgoto done;\n@@ -121,13 +124,17 @@ int block_writer_add(struct block_writer *w, struct reftable_record *rec)\n \n \tn = reftable_encode_key(&is_restart, out, last, key,\n \t\t\t\treftable_record_val_type(rec));\n-\tif (n < 0)\n+\tif (n < 0) {\n+\t\terr = -1;\n \t\tgoto done;\n+\t}\n \tstring_view_consume(&out, n);\n \n \tn = reftable_record_encode(rec, out, w->hash_size);\n-\tif (n < 0)\n+\tif (n < 0) {\n+\t\terr = -1;\n \t\tgoto done;\n+\t}\n \tstring_view_consume(&out, n);\n \n \terr = block_writer_register_restart(w, start.len - out.len, is_restart,\n@@ -522,6 +529,10 @@ int block_iter_seek_key(struct block_iter *it, const struct block_reader *br,\n \t\t\tgoto done;\n \t\t}\n \n+\t\terr = reftable_record_key(&rec, &it->last_key);\n+\t\tif (err < 0)\n+\t\t\tgoto done;\n+\n \t\t/*\n \t\t * Check whether the current key is greater or equal to the\n \t\t * sought-after key. In case it is greater we know that the\n@@ -536,7 +547,6 @@ int block_iter_seek_key(struct block_iter *it, const struct block_reader *br,\n \t\t * to `last_key` now, and naturally all keys share a prefix\n \t\t * with themselves.\n \t\t */\n-\t\treftable_record_key(&rec, &it->last_key);\n \t\tif (reftable_buf_cmp(&it->last_key, want) >= 0) {\n \t\t\tit->next_off = prev_off;\n \t\t\tgoto done;\ndiff --git a/reftable/reader.c b/reftable/reader.c\nindex 388f8bf6d7b..ab89efd9c55 100644\n--- a/reftable/reader.c\n+++ b/reftable/reader.c\n@@ -356,7 +356,9 @@ static int table_iter_seek_linear(struct table_iter *ti,\n \tint err;\n \n \treftable_record_init(&rec, reftable_record_type(want));\n-\treftable_record_key(want, &want_key);\n+\terr = reftable_record_key(want, &want_key);\n+\tif (err < 0)\n+\t\tgoto done;\n \n \t/*\n \t * First we need to locate the block that must contain our record. To\n@@ -439,7 +441,9 @@ static int table_iter_seek_indexed(struct table_iter *ti,\n \t};\n \tint err;\n \n-\treftable_record_key(rec, &want_index.u.idx.last_key);\n+\terr = reftable_record_key(rec, &want_index.u.idx.last_key);\n+\tif (err < 0)\n+\t\tgoto done;\n \n \t/*\n \t * The index may consist of multiple levels, where each level may have\ndiff --git a/reftable/record.c b/reftable/record.c\nindex 0182c973437..672c5f909a9 100644\n--- a/reftable/record.c\n+++ b/reftable/record.c\n@@ -207,12 +207,12 @@ int reftable_decode_key(struct reftable_buf *last_key, uint8_t *extra,\n \treturn start_len - in.len;\n }\n \n-static void reftable_ref_record_key(const void *r, struct reftable_buf *dest)\n+static int reftable_ref_record_key(const void *r, struct reftable_buf *dest)\n {\n \tconst struct reftable_ref_record *rec =\n \t\t(const struct reftable_ref_record *)r;\n \treftable_buf_reset(dest);\n-\treftable_buf_addstr(dest, rec->refname);\n+\treturn reftable_buf_addstr(dest, rec->refname);\n }\n \n static int reftable_ref_record_copy_from(void *rec, const void *src_rec,\n@@ -465,12 +465,12 @@ static struct reftable_record_vtable reftable_ref_record_vtable = {\n \t.cmp = &reftable_ref_record_cmp_void,\n };\n \n-static void reftable_obj_record_key(const void *r, struct reftable_buf *dest)\n+static int reftable_obj_record_key(const void *r, struct reftable_buf *dest)\n {\n \tconst struct reftable_obj_record *rec =\n \t\t(const struct reftable_obj_record *)r;\n \treftable_buf_reset(dest);\n-\treftable_buf_add(dest, rec->hash_prefix, rec->hash_prefix_len);\n+\treturn reftable_buf_add(dest, rec->hash_prefix, rec->hash_prefix_len);\n }\n \n static void reftable_obj_record_release(void *rec)\n@@ -664,19 +664,27 @@ static struct reftable_record_vtable reftable_obj_record_vtable = {\n \t.cmp = &reftable_obj_record_cmp_void,\n };\n \n-static void reftable_log_record_key(const void *r, struct reftable_buf *dest)\n+static int reftable_log_record_key(const void *r, struct reftable_buf *dest)\n {\n \tconst struct reftable_log_record *rec =\n \t\t(const struct reftable_log_record *)r;\n-\tint len = strlen(rec->refname);\n+\tint len = strlen(rec->refname), err;\n \tuint8_t i64[8];\n \tuint64_t ts = 0;\n+\n \treftable_buf_reset(dest);\n-\treftable_buf_add(dest, (uint8_t *)rec->refname, len + 1);\n+\terr = reftable_buf_add(dest, (uint8_t *)rec->refname, len + 1);\n+\tif (err < 0)\n+\t\treturn err;\n \n \tts = (~ts) - rec->update_index;\n \tput_be64(&i64[0], ts);\n-\treftable_buf_add(dest, i64, sizeof(i64));\n+\n+\terr = reftable_buf_add(dest, i64, sizeof(i64));\n+\tif (err < 0)\n+\t\treturn err;\n+\n+\treturn 0;\n }\n \n static int reftable_log_record_copy_from(void *rec, const void *src_rec,\n@@ -1027,11 +1035,11 @@ static struct reftable_record_vtable reftable_log_record_vtable = {\n \t.cmp = &reftable_log_record_cmp_void,\n };\n \n-static void reftable_index_record_key(const void *r, struct reftable_buf *dest)\n+static int reftable_index_record_key(const void *r, struct reftable_buf *dest)\n {\n \tconst struct reftable_index_record *rec = r;\n \treftable_buf_reset(dest);\n-\treftable_buf_add(dest, rec->last_key.buf, rec->last_key.len);\n+\treturn reftable_buf_add(dest, rec->last_key.buf, rec->last_key.len);\n }\n \n static int reftable_index_record_copy_from(void *rec, const void *src_rec,\n@@ -1124,9 +1132,9 @@ static struct reftable_record_vtable reftable_index_record_vtable = {\n \t.cmp = &reftable_index_record_cmp,\n };\n \n-void reftable_record_key(struct reftable_record *rec, struct reftable_buf *dest)\n+int reftable_record_key(struct reftable_record *rec, struct reftable_buf *dest)\n {\n-\treftable_record_vtable(rec)->key(reftable_record_data(rec), dest);\n+\treturn reftable_record_vtable(rec)->key(reftable_record_data(rec), dest);\n }\n \n int reftable_record_encode(struct reftable_record *rec, struct string_view dest,\ndiff --git a/reftable/record.h b/reftable/record.h\nindex 271da3bf360..25aa908c859 100644\n--- a/reftable/record.h\n+++ b/reftable/record.h\n@@ -40,7 +40,7 @@ int put_var_int(struct string_view *dest, uint64_t val);\n /* Methods for records. */\n struct reftable_record_vtable {\n \t/* encode the key of to a uint8_t reftable_buf. */\n-\tvoid (*key)(const void *rec, struct reftable_buf *dest);\n+\tint (*key)(const void *rec, struct reftable_buf *dest);\n \n \t/* The record type of ('r' for ref). */\n \tuint8_t type;\n@@ -137,7 +137,7 @@ void reftable_record_init(struct reftable_record *rec, uint8_t typ);\n /* see struct record_vtable */\n int reftable_record_cmp(struct reftable_record *a, struct reftable_record *b);\n int reftable_record_equal(struct reftable_record *a, struct reftable_record *b, int hash_size);\n-void reftable_record_key(struct reftable_record *rec, struct reftable_buf *dest);\n+int reftable_record_key(struct reftable_record *rec, struct reftable_buf *dest);\n int reftable_record_copy_from(struct reftable_record *rec,\n \t\t\t      struct reftable_record *src, int hash_size);\n uint8_t reftable_record_val_type(struct reftable_record *rec);\ndiff --git a/reftable/writer.c b/reftable/writer.c\nindex da6941a78ac..377db709c85 100644\n--- a/reftable/writer.c\n+++ b/reftable/writer.c\n@@ -249,7 +249,10 @@ static int writer_add_record(struct reftable_writer *w,\n \tstruct reftable_buf key = REFTABLE_BUF_INIT;\n \tint err;\n \n-\treftable_record_key(rec, &key);\n+\terr = reftable_record_key(rec, &key);\n+\tif (err < 0)\n+\t\tgoto done;\n+\n \tif (reftable_buf_cmp(&w->last_key, &key) >= 0) {\n \t\terr = REFTABLE_API_ERROR;\n \t\tgoto done;\n-- \n2.47.0.72.gef8ce8f3d4.dirty\n\n"},{"id":"505337","messageId":"245a428842a9ef4dfe3d8a9d5b566876ee359cf7.1729140565.git.ps@pks.im","threadId":"62313","inReplyTo":"cover.1729140565.git.ps@pks.im","subject":"[PATCH v3 09/10] reftable/stack: adapt `stack_filename()` to handle allocation failures","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-10-17T04:54:13Z","receivedAt":"2024-10-17T04:54:17Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"The `stack_filename()` function cannot pass any errors to the caller as it\nhas a `void` return type. Adapt it and its callers such that we can\nhandle errors and start handling allocation failures.\n\nThere are two interesting edge cases in `reftable_stack_destroy()` and\n`reftable_addition_close()`. Both of these are trying to tear down their\nrespective structures, and while doing so they try to unlink some of the\ntables they have been keeping alive. Any earlier attempts to do that may\nfail on Windows because it keeps us from deleting such tables while they\nare still open, and thus we re-try on close. It's okay and even expected\nthat this can fail when the tables are still open by another process, so\nwe handle the allocation failures gracefully and just skip over any file\nwhose name we couldn't figure out.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n reftable/stack.c | 62 +++++++++++++++++++++++++++++++++++-------------\n 1 file changed, 45 insertions(+), 17 deletions(-)\n\ndiff --git a/reftable/stack.c b/reftable/stack.c\nindex e94eb3c4685..243b10715cc 100644\n--- a/reftable/stack.c\n+++ b/reftable/stack.c\n@@ -31,13 +31,16 @@ static void reftable_addition_close(struct reftable_addition *add);\n static int reftable_stack_reload_maybe_reuse(struct reftable_stack *st,\n \t\t\t\t\t     int reuse_open);\n \n-static void stack_filename(struct reftable_buf *dest, struct reftable_stack *st,\n-\t\t\t   const char *name)\n+static int stack_filename(struct reftable_buf *dest, struct reftable_stack *st,\n+\t\t\t  const char *name)\n {\n+\tint err;\n \treftable_buf_reset(dest);\n-\treftable_buf_addstr(dest, st->reftable_dir);\n-\treftable_buf_addstr(dest, \"/\");\n-\treftable_buf_addstr(dest, name);\n+\tif ((err = reftable_buf_addstr(dest, st->reftable_dir)) < 0 ||\n+\t    (err = reftable_buf_addstr(dest, \"/\")) < 0 ||\n+\t    (err = reftable_buf_addstr(dest, name)) < 0)\n+\t\treturn err;\n+\treturn 0;\n }\n \n static ssize_t reftable_fd_write(void *arg, const void *data, size_t sz)\n@@ -211,13 +214,16 @@ void reftable_stack_destroy(struct reftable_stack *st)\n \t\tstruct reftable_buf filename = REFTABLE_BUF_INIT;\n \t\tfor (i = 0; i < st->readers_len; i++) {\n \t\t\tconst char *name = reader_name(st->readers[i]);\n+\t\t\tint try_unlinking = 1;\n+\n \t\t\treftable_buf_reset(&filename);\n \t\t\tif (names && !has_name(names, name)) {\n-\t\t\t\tstack_filename(&filename, st, name);\n+\t\t\t\tif (stack_filename(&filename, st, name) < 0)\n+\t\t\t\t\ttry_unlinking = 0;\n \t\t\t}\n \t\t\treftable_reader_decref(st->readers[i]);\n \n-\t\t\tif (filename.len) {\n+\t\t\tif (try_unlinking && filename.len) {\n \t\t\t\t/* On Windows, can only unlink after closing. */\n \t\t\t\tunlink(filename.buf);\n \t\t\t}\n@@ -310,7 +316,10 @@ static int reftable_stack_reload_once(struct reftable_stack *st,\n \n \t\tif (!rd) {\n \t\t\tstruct reftable_block_source src = { NULL };\n-\t\t\tstack_filename(&table_path, st, name);\n+\n+\t\t\terr = stack_filename(&table_path, st, name);\n+\t\t\tif (err < 0)\n+\t\t\t\tgoto done;\n \n \t\t\terr = reftable_block_source_from_file(&src,\n \t\t\t\t\t\t\t      table_path.buf);\n@@ -341,7 +350,11 @@ static int reftable_stack_reload_once(struct reftable_stack *st,\n \tfor (i = 0; i < cur_len; i++) {\n \t\tif (cur[i]) {\n \t\t\tconst char *name = reader_name(cur[i]);\n-\t\t\tstack_filename(&table_path, st, name);\n+\n+\t\t\terr = stack_filename(&table_path, st, name);\n+\t\t\tif (err < 0)\n+\t\t\t\tgoto done;\n+\n \t\t\treftable_reader_decref(cur[i]);\n \t\t\tunlink(table_path.buf);\n \t\t}\n@@ -700,8 +713,8 @@ static void reftable_addition_close(struct reftable_addition *add)\n \tsize_t i;\n \n \tfor (i = 0; i < add->new_tables_len; i++) {\n-\t\tstack_filename(&nm, add->stack, add->new_tables[i]);\n-\t\tunlink(nm.buf);\n+\t\tif (!stack_filename(&nm, add->stack, add->new_tables[i]))\n+\t\t\tunlink(nm.buf);\n \t\treftable_free(add->new_tables[i]);\n \t\tadd->new_tables[i] = NULL;\n \t}\n@@ -851,7 +864,9 @@ int reftable_addition_add(struct reftable_addition *add,\n \tif (err < 0)\n \t\tgoto done;\n \n-\tstack_filename(&temp_tab_file_name, add->stack, next_name.buf);\n+\terr = stack_filename(&temp_tab_file_name, add->stack, next_name.buf);\n+\tif (err < 0)\n+\t\tgoto done;\n \treftable_buf_addstr(&temp_tab_file_name, \".temp.XXXXXX\");\n \n \ttab_file = mks_tempfile(temp_tab_file_name.buf);\n@@ -900,7 +915,10 @@ int reftable_addition_add(struct reftable_addition *add,\n \tif (err < 0)\n \t\tgoto done;\n \treftable_buf_addstr(&next_name, \".ref\");\n-\tstack_filename(&tab_file_name, add->stack, next_name.buf);\n+\n+\terr = stack_filename(&tab_file_name, add->stack, next_name.buf);\n+\tif (err < 0)\n+\t\tgoto done;\n \n \t/*\n \t  On windows, this relies on rand() picking a unique destination name.\n@@ -954,7 +972,9 @@ static int stack_compact_locked(struct reftable_stack *st,\n \tif (err < 0)\n \t\tgoto done;\n \n-\tstack_filename(&tab_file_path, st, next_name.buf);\n+\terr = stack_filename(&tab_file_path, st, next_name.buf);\n+\tif (err < 0)\n+\t\tgoto done;\n \treftable_buf_addstr(&tab_file_path, \".temp.XXXXXX\");\n \n \ttab_file = mks_tempfile(tab_file_path.buf);\n@@ -1174,7 +1194,9 @@ static int stack_compact_range(struct reftable_stack *st,\n \t}\n \n \tfor (i = last + 1; i > first; i--) {\n-\t\tstack_filename(&table_name, st, reader_name(st->readers[i - 1]));\n+\t\terr = stack_filename(&table_name, st, reader_name(st->readers[i - 1]));\n+\t\tif (err < 0)\n+\t\t\tgoto done;\n \n \t\terr = hold_lock_file_for_update(&table_locks[nlocks],\n \t\t\t\t\t\ttable_name.buf, LOCK_NO_DEREF);\n@@ -1383,7 +1405,10 @@ static int stack_compact_range(struct reftable_stack *st,\n \t\t\tgoto done;\n \n \t\treftable_buf_addstr(&new_table_name, \".ref\");\n-\t\tstack_filename(&new_table_path, st, new_table_name.buf);\n+\n+\t\terr = stack_filename(&new_table_path, st, new_table_name.buf);\n+\t\tif (err < 0)\n+\t\t\tgoto done;\n \n \t\terr = rename_tempfile(&new_table, new_table_path.buf);\n \t\tif (err < 0) {\n@@ -1677,7 +1702,10 @@ static void remove_maybe_stale_table(struct reftable_stack *st, uint64_t max,\n \tstruct reftable_block_source src = { NULL };\n \tstruct reftable_reader *rd = NULL;\n \tstruct reftable_buf table_path = REFTABLE_BUF_INIT;\n-\tstack_filename(&table_path, st, name);\n+\n+\terr = stack_filename(&table_path, st, name);\n+\tif (err < 0)\n+\t\tgoto done;\n \n \terr = reftable_block_source_from_file(&src, table_path.buf);\n \tif (err < 0)\n-- \n2.47.0.72.gef8ce8f3d4.dirty\n\n"},{"id":"505338","messageId":"4b51ea4b628d298f894d120162e7e7959898892b.1729140565.git.ps@pks.im","threadId":"62313","inReplyTo":"cover.1729140565.git.ps@pks.im","subject":"[PATCH v3 10/10] reftable: handle trivial `reftable_buf` errors","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-10-17T04:54:16Z","receivedAt":"2024-10-17T04:54:20Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"Convert the reftable library such that we handle failures with the\nnew `reftable_buf` interfaces.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n reftable/block.c  |  9 +++++++--\n reftable/iter.c   |  5 ++++-\n reftable/reader.c |  5 ++++-\n reftable/record.c | 32 +++++++++++++++++++++++--------\n reftable/stack.c  | 49 +++++++++++++++++++++++++++++++----------------\n reftable/writer.c | 48 +++++++++++++++++++++++++++++++++-------------\n 6 files changed, 107 insertions(+), 41 deletions(-)\n\ndiff --git a/reftable/block.c b/reftable/block.c\nindex 697b8b41531..f5b432566a6 100644\n--- a/reftable/block.c\n+++ b/reftable/block.c\n@@ -40,7 +40,9 @@ int footer_size(int version)\n static int block_writer_register_restart(struct block_writer *w, int n,\n \t\t\t\t\t int is_restart, struct reftable_buf *key)\n {\n-\tint rlen = w->restart_len;\n+\tint rlen, err;\n+\n+\trlen = w->restart_len;\n \tif (rlen >= MAX_RESTARTS) {\n \t\tis_restart = 0;\n \t}\n@@ -60,7 +62,10 @@ static int block_writer_register_restart(struct block_writer *w, int n,\n \tw->next += n;\n \n \treftable_buf_reset(&w->last_key);\n-\treftable_buf_add(&w->last_key, key->buf, key->len);\n+\terr = reftable_buf_add(&w->last_key, key->buf, key->len);\n+\tif (err < 0)\n+\t\treturn err;\n+\n \tw->entries++;\n \treturn 0;\n }\ndiff --git a/reftable/iter.c b/reftable/iter.c\nindex 6c193fd31a9..86e801ca9fb 100644\n--- a/reftable/iter.c\n+++ b/reftable/iter.c\n@@ -197,7 +197,10 @@ int indexed_table_ref_iter_new(struct indexed_table_ref_iter **dest,\n \n \t*itr = empty;\n \titr->r = r;\n-\treftable_buf_add(&itr->oid, oid, oid_len);\n+\n+\terr = reftable_buf_add(&itr->oid, oid, oid_len);\n+\tif (err < 0)\n+\t\tgoto out;\n \n \titr->offsets = offsets;\n \titr->offset_len = offset_len;\ndiff --git a/reftable/reader.c b/reftable/reader.c\nindex ab89efd9c55..90dc950b577 100644\n--- a/reftable/reader.c\n+++ b/reftable/reader.c\n@@ -769,7 +769,10 @@ static int reftable_reader_refs_for_unindexed(struct reftable_reader *r,\n \t}\n \t*filter = empty;\n \n-\treftable_buf_add(&filter->oid, oid, oid_len);\n+\terr = reftable_buf_add(&filter->oid, oid, oid_len);\n+\tif (err < 0)\n+\t\tgoto out;\n+\n \titerator_from_table_iter(&filter->it, ti);\n \n \titerator_from_filtering_ref_iterator(it, filter);\ndiff --git a/reftable/record.c b/reftable/record.c\nindex 672c5f909a9..fb5652ed575 100644\n--- a/reftable/record.c\n+++ b/reftable/record.c\n@@ -102,7 +102,9 @@ static int decode_string(struct reftable_buf *dest, struct string_view in)\n {\n \tint start_len = in.len;\n \tuint64_t tsize = 0;\n-\tint n = get_var_int(&tsize, &in);\n+\tint n, err;\n+\n+\tn = get_var_int(&tsize, &in);\n \tif (n <= 0)\n \t\treturn -1;\n \tstring_view_consume(&in, n);\n@@ -110,7 +112,10 @@ static int decode_string(struct reftable_buf *dest, struct string_view in)\n \t\treturn -1;\n \n \treftable_buf_reset(dest);\n-\treftable_buf_add(dest, in.buf, tsize);\n+\terr = reftable_buf_add(dest, in.buf, tsize);\n+\tif (err < 0)\n+\t\treturn err;\n+\n \tstring_view_consume(&in, tsize);\n \n \treturn start_len - in.len;\n@@ -189,7 +194,7 @@ int reftable_decode_key(struct reftable_buf *last_key, uint8_t *extra,\n \tint start_len = in.len;\n \tuint64_t prefix_len = 0;\n \tuint64_t suffix_len = 0;\n-\tint n;\n+\tint err, n;\n \n \tn = reftable_decode_keylen(in, &prefix_len, &suffix_len, extra);\n \tif (n < 0)\n@@ -200,8 +205,14 @@ int reftable_decode_key(struct reftable_buf *last_key, uint8_t *extra,\n \t    prefix_len > last_key->len)\n \t\treturn -1;\n \n-\treftable_buf_setlen(last_key, prefix_len);\n-\treftable_buf_add(last_key, in.buf, suffix_len);\n+\terr = reftable_buf_setlen(last_key, prefix_len);\n+\tif (err < 0)\n+\t\treturn err;\n+\n+\terr = reftable_buf_add(last_key, in.buf, suffix_len);\n+\tif (err < 0)\n+\t\treturn err;\n+\n \tstring_view_consume(&in, suffix_len);\n \n \treturn start_len - in.len;\n@@ -1047,9 +1058,12 @@ static int reftable_index_record_copy_from(void *rec, const void *src_rec,\n {\n \tstruct reftable_index_record *dst = rec;\n \tconst struct reftable_index_record *src = src_rec;\n+\tint err;\n \n \treftable_buf_reset(&dst->last_key);\n-\treftable_buf_add(&dst->last_key, src->last_key.buf, src->last_key.len);\n+\terr = reftable_buf_add(&dst->last_key, src->last_key.buf, src->last_key.len);\n+\tif (err < 0)\n+\t\treturn err;\n \tdst->offset = src->offset;\n \n \treturn 0;\n@@ -1090,10 +1104,12 @@ static int reftable_index_record_decode(void *rec, struct reftable_buf key,\n {\n \tstruct string_view start = in;\n \tstruct reftable_index_record *r = rec;\n-\tint n = 0;\n+\tint err, n = 0;\n \n \treftable_buf_reset(&r->last_key);\n-\treftable_buf_add(&r->last_key, key.buf, key.len);\n+\terr = reftable_buf_add(&r->last_key, key.buf, key.len);\n+\tif (err < 0)\n+\t\treturn err;\n \n \tn = get_var_int(&r->offset, &in);\n \tif (n < 0)\ndiff --git a/reftable/stack.c b/reftable/stack.c\nindex 243b10715cc..c33979536ef 100644\n--- a/reftable/stack.c\n+++ b/reftable/stack.c\n@@ -78,8 +78,9 @@ int reftable_new_stack(struct reftable_stack **dest, const char *dir,\n \t*dest = NULL;\n \n \treftable_buf_reset(&list_file_name);\n-\treftable_buf_addstr(&list_file_name, dir);\n-\treftable_buf_addstr(&list_file_name, \"/tables.list\");\n+\tif ((err = reftable_buf_addstr(&list_file_name, dir)) < 0 ||\n+\t    (err = reftable_buf_addstr(&list_file_name, \"/tables.list\")) < 0)\n+\t\tgoto out;\n \n \tp->list_file = reftable_buf_detach(&list_file_name);\n \tp->list_fd = -1;\n@@ -747,12 +748,14 @@ int reftable_addition_commit(struct reftable_addition *add)\n \t\tgoto done;\n \n \tfor (i = 0; i < add->stack->merged->readers_len; i++) {\n-\t\treftable_buf_addstr(&table_list, add->stack->readers[i]->name);\n-\t\treftable_buf_addstr(&table_list, \"\\n\");\n+\t\tif ((err = reftable_buf_addstr(&table_list, add->stack->readers[i]->name)) < 0 ||\n+\t\t    (err = reftable_buf_addstr(&table_list, \"\\n\")) < 0)\n+\t\t\tgoto done;\n \t}\n \tfor (i = 0; i < add->new_tables_len; i++) {\n-\t\treftable_buf_addstr(&table_list, add->new_tables[i]);\n-\t\treftable_buf_addstr(&table_list, \"\\n\");\n+\t\tif ((err = reftable_buf_addstr(&table_list, add->new_tables[i])) < 0 ||\n+\t\t    (err = reftable_buf_addstr(&table_list, \"\\n\")) < 0)\n+\t\t\tgoto done;\n \t}\n \n \terr = write_in_full(lock_file_fd, table_list.buf, table_list.len);\n@@ -867,7 +870,10 @@ int reftable_addition_add(struct reftable_addition *add,\n \terr = stack_filename(&temp_tab_file_name, add->stack, next_name.buf);\n \tif (err < 0)\n \t\tgoto done;\n-\treftable_buf_addstr(&temp_tab_file_name, \".temp.XXXXXX\");\n+\n+\terr = reftable_buf_addstr(&temp_tab_file_name, \".temp.XXXXXX\");\n+\tif (err < 0)\n+\t\tgoto done;\n \n \ttab_file = mks_tempfile(temp_tab_file_name.buf);\n \tif (!tab_file) {\n@@ -914,7 +920,10 @@ int reftable_addition_add(struct reftable_addition *add,\n \terr = format_name(&next_name, wr->min_update_index, wr->max_update_index);\n \tif (err < 0)\n \t\tgoto done;\n-\treftable_buf_addstr(&next_name, \".ref\");\n+\n+\terr = reftable_buf_addstr(&next_name, \".ref\");\n+\tif (err < 0)\n+\t\tgoto done;\n \n \terr = stack_filename(&tab_file_name, add->stack, next_name.buf);\n \tif (err < 0)\n@@ -975,7 +984,10 @@ static int stack_compact_locked(struct reftable_stack *st,\n \terr = stack_filename(&tab_file_path, st, next_name.buf);\n \tif (err < 0)\n \t\tgoto done;\n-\treftable_buf_addstr(&tab_file_path, \".temp.XXXXXX\");\n+\n+\terr = reftable_buf_addstr(&tab_file_path, \".temp.XXXXXX\");\n+\tif (err < 0)\n+\t\tgoto done;\n \n \ttab_file = mks_tempfile(tab_file_path.buf);\n \tif (!tab_file) {\n@@ -1404,7 +1416,9 @@ static int stack_compact_range(struct reftable_stack *st,\n \t\tif (err < 0)\n \t\t\tgoto done;\n \n-\t\treftable_buf_addstr(&new_table_name, \".ref\");\n+\t\terr = reftable_buf_addstr(&new_table_name, \".ref\");\n+\t\tif (err < 0)\n+\t\t\tgoto done;\n \n \t\terr = stack_filename(&new_table_path, st, new_table_name.buf);\n \t\tif (err < 0)\n@@ -1423,16 +1437,19 @@ static int stack_compact_range(struct reftable_stack *st,\n \t * simply skip writing it.\n \t */\n \tfor (i = 0; i < first_to_replace; i++) {\n-\t\treftable_buf_addstr(&tables_list_buf, names[i]);\n-\t\treftable_buf_addstr(&tables_list_buf, \"\\n\");\n+\t\tif ((err = reftable_buf_addstr(&tables_list_buf, names[i])) < 0 ||\n+\t\t    (err = reftable_buf_addstr(&tables_list_buf, \"\\n\")) < 0)\n+\t\t      goto done;\n \t}\n \tif (!is_empty_table) {\n-\t\treftable_buf_addstr(&tables_list_buf, new_table_name.buf);\n-\t\treftable_buf_addstr(&tables_list_buf, \"\\n\");\n+\t\tif ((err = reftable_buf_addstr(&tables_list_buf, new_table_name.buf)) < 0 ||\n+\t\t    (err = reftable_buf_addstr(&tables_list_buf, \"\\n\")) < 0)\n+\t\t\tgoto done;\n \t}\n \tfor (i = last_to_replace + 1; names[i]; i++) {\n-\t\treftable_buf_addstr(&tables_list_buf, names[i]);\n-\t\treftable_buf_addstr(&tables_list_buf, \"\\n\");\n+\t\tif ((err = reftable_buf_addstr(&tables_list_buf, names[i])) < 0 ||\n+\t\t    (err = reftable_buf_addstr(&tables_list_buf, \"\\n\")) < 0)\n+\t\t\tgoto done;\n \t}\n \n \terr = write_in_full(get_lock_file_fd(&tables_list_lock),\ndiff --git a/reftable/writer.c b/reftable/writer.c\nindex 377db709c85..fd136794d5a 100644\n--- a/reftable/writer.c\n+++ b/reftable/writer.c\n@@ -217,6 +217,7 @@ static int writer_index_hash(struct reftable_writer *w, struct reftable_buf *has\n \tnode = tree_search(w->obj_index_tree, &want, &obj_index_tree_node_compare);\n \tif (!node) {\n \t\tstruct obj_index_tree_node empty = OBJ_INDEX_TREE_NODE_INIT;\n+\t\tint err;\n \n \t\tkey = reftable_malloc(sizeof(*key));\n \t\tif (!key)\n@@ -225,7 +226,9 @@ static int writer_index_hash(struct reftable_writer *w, struct reftable_buf *has\n \t\t*key = empty;\n \n \t\treftable_buf_reset(&key->hash);\n-\t\treftable_buf_add(&key->hash, hash->buf, hash->len);\n+\t\terr = reftable_buf_add(&key->hash, hash->buf, hash->len);\n+\t\tif (err < 0)\n+\t\t\treturn err;\n \t\ttree_insert(&w->obj_index_tree, key,\n \t\t\t    &obj_index_tree_node_compare);\n \t} else {\n@@ -259,7 +262,10 @@ static int writer_add_record(struct reftable_writer *w,\n \t}\n \n \treftable_buf_reset(&w->last_key);\n-\treftable_buf_add(&w->last_key, key.buf, key.len);\n+\terr = reftable_buf_add(&w->last_key, key.buf, key.len);\n+\tif (err < 0)\n+\t\tgoto done;\n+\n \tif (!w->block_writer) {\n \t\terr = writer_reinit_block_writer(w, reftable_record_type(rec));\n \t\tif (err < 0)\n@@ -334,8 +340,10 @@ int reftable_writer_add_ref(struct reftable_writer *w,\n \t\tgoto out;\n \n \tif (!w->opts.skip_index_objects && reftable_ref_record_val1(ref)) {\n-\t\treftable_buf_add(&buf, (char *)reftable_ref_record_val1(ref),\n-\t\t\t   hash_size(w->opts.hash_id));\n+\t\terr = reftable_buf_add(&buf, (char *)reftable_ref_record_val1(ref),\n+\t\t\t\t       hash_size(w->opts.hash_id));\n+\t\tif (err < 0)\n+\t\t\tgoto out;\n \n \t\terr = writer_index_hash(w, &buf);\n \t\tif (err < 0)\n@@ -344,8 +352,10 @@ int reftable_writer_add_ref(struct reftable_writer *w,\n \n \tif (!w->opts.skip_index_objects && reftable_ref_record_val2(ref)) {\n \t\treftable_buf_reset(&buf);\n-\t\treftable_buf_add(&buf, reftable_ref_record_val2(ref),\n-\t\t\t   hash_size(w->opts.hash_id));\n+\t\terr = reftable_buf_add(&buf, reftable_ref_record_val2(ref),\n+\t\t\t\t       hash_size(w->opts.hash_id));\n+\t\tif (err < 0)\n+\t\t\tgoto out;\n \n \t\terr = writer_index_hash(w, &buf);\n \t\tif (err < 0)\n@@ -407,17 +417,27 @@ int reftable_writer_add_log(struct reftable_writer *w,\n \n \tinput_log_message = log->value.update.message;\n \tif (!w->opts.exact_log_message && log->value.update.message) {\n-\t\treftable_buf_addstr(&cleaned_message, log->value.update.message);\n+\t\terr = reftable_buf_addstr(&cleaned_message, log->value.update.message);\n+\t\tif (err < 0)\n+\t\t\tgoto done;\n+\n \t\twhile (cleaned_message.len &&\n-\t\t       cleaned_message.buf[cleaned_message.len - 1] == '\\n')\n-\t\t\treftable_buf_setlen(&cleaned_message,\n-\t\t\t\t      cleaned_message.len - 1);\n+\t\t       cleaned_message.buf[cleaned_message.len - 1] == '\\n') {\n+\t\t\terr = reftable_buf_setlen(&cleaned_message,\n+\t\t\t\t\t\t  cleaned_message.len - 1);\n+\t\t\tif (err < 0)\n+\t\t\t\tgoto done;\n+\t\t}\n \t\tif (strchr(cleaned_message.buf, '\\n')) {\n \t\t\t/* multiple lines not allowed. */\n \t\t\terr = REFTABLE_API_ERROR;\n \t\t\tgoto done;\n \t\t}\n-\t\treftable_buf_addstr(&cleaned_message, \"\\n\");\n+\n+\t\terr = reftable_buf_addstr(&cleaned_message, \"\\n\");\n+\t\tif (err < 0)\n+\t\t\tgoto done;\n+\n \t\tlog->value.update.message = cleaned_message.buf;\n \t}\n \n@@ -781,8 +801,10 @@ static int writer_flush_nonempty_block(struct reftable_writer *w)\n \n \tindex_record.offset = w->next;\n \treftable_buf_reset(&index_record.last_key);\n-\treftable_buf_add(&index_record.last_key, w->block_writer->last_key.buf,\n-\t\t   w->block_writer->last_key.len);\n+\terr = reftable_buf_add(&index_record.last_key, w->block_writer->last_key.buf,\n+\t\t\t       w->block_writer->last_key.len);\n+\tif (err < 0)\n+\t\treturn err;\n \tw->index[w->index_len] = index_record;\n \tw->index_len++;\n \n-- \n2.47.0.72.gef8ce8f3d4.dirty\n\n"},{"id":"505339","messageId":"ZxCYk99oZLUaCkrd@pks.im","threadId":"62313","inReplyTo":"ZxAolGGcndQzApPJ@nand.local","subject":"Re: [PATCH v2 03/10] reftable/basics: provide new `reftable_buf` interface","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-10-17T04:54:51Z","receivedAt":"2024-10-17T04:54:55Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"On Wed, Oct 16, 2024 at 04:56:52PM -0400, Taylor Blau wrote:\n> On Wed, Oct 16, 2024 at 10:42:44AM +0200, Patrick Steinhardt wrote:\n> > On Tue, Oct 15, 2024 at 03:27:29PM -0400, Taylor Blau wrote:\n> > > On Tue, Oct 15, 2024 at 01:10:59AM -0400, Eric Sunshine wrote:\n> > > > On Tue, Oct 15, 2024 at 12:38 AM Patrick Steinhardt <ps@pks.im> wrote:\n> > > > > On Mon, Oct 14, 2024 at 06:34:55PM -0400, Taylor Blau wrote:\n> > > > > > On Mon, Oct 14, 2024 at 03:02:24PM +0200, Patrick Steinhardt wrote:\n> > > > > > > +/*\n> > > > > > > + * Add the given bytes to the buffer. Returns 0 on success,\n> > > > > > > + * REFTABLE_OUT_OF_MEMORY_ERROR on allocation failure.\n> > > > > > > + */\n> > > > > > > +int reftable_buf_add(struct reftable_buf *buf, const void *data, size_t len);\n> > > > > >\n> > > > > > Is there a reason that data is a void-pointer here and not a const char\n> > > > > > *?\n> > > > >\n> > > > > Only that it emulates `strbuf_add()`, which also uses a void pointer.\n> > > >\n> > > > The reason for that is because strbuf is a generic byte-array which\n> > > > may contain embedded NULs, and the `const void *` plus `len`\n> > > > emphasizes this property, whereas `const char *` would imply a\n> > > > C-string with no embedded NULs.\n> > >\n> > > Thanks, that was the explanation I was missing. Perhaps it is worth\n> > > re-stating in the commit message here to avoid confusing readers like I\n> > > was when I first read Patrick's patch ;-).\n> >\n> > Does it make sense to explicitly state how the interfaces look like\n> > though? I don't do that for the other functions either, and for most of\n> > the part I just reuse the exact same function arguments as we had with\n> > the strbuf interface.\n> \n> I don't feel very strongly about it, but I had suggested it because my\n> initial read of this patch confused me, and I had wondered if others may\n> be similarly confused.\n> \n> For what it's worth, I was thinking something on the order of the\n> following added to the patch message:\n> \n>     Note that the reftable_buf_add() function intentionally takes a \"const\n>     void *\" instead of a \"const char *\" (as does its strbuf counterpart,\n>     strbuf_add()) to emphasize that the buffer may contain NUL characters.\n> \n> But, as I said, I don't feel very strongly about it.\n\nYou know: let me amend the function documentation itself. That feels way\nless out of place compared to putting this info into the commit message\nand has the benefit that a future reader of the code will know why we\nhave types without digging into the commit history.\n\nPatrick\n"},{"id":"505394","messageId":"ZxF6pQpsnjLmTZ9H@nand.local","threadId":"62313","inReplyTo":"ZxCYk99oZLUaCkrd@pks.im","subject":"Re: [PATCH v2 03/10] reftable/basics: provide new `reftable_buf` interface","fromName":"Taylor Blau","fromEmail":"me@ttaylorr.com","sentAt":"2024-10-17T20:59:17Z","receivedAt":"2024-10-17T20:59:20Z","isPatch":true,"sender":{"key":"me@ttaylorr.com","avatar":"https://avatars.githubusercontent.com/u/301000140?v=4"},"body":"On Thu, Oct 17, 2024 at 06:54:51AM +0200, Patrick Steinhardt wrote:\n> > I don't feel very strongly about it, but I had suggested it because my\n> > initial read of this patch confused me, and I had wondered if others may\n> > be similarly confused.\n> >\n> > For what it's worth, I was thinking something on the order of the\n> > following added to the patch message:\n> >\n> >     Note that the reftable_buf_add() function intentionally takes a \"const\n> >     void *\" instead of a \"const char *\" (as does its strbuf counterpart,\n> >     strbuf_add()) to emphasize that the buffer may contain NUL characters.\n> >\n> > But, as I said, I don't feel very strongly about it.\n>\n> You know: let me amend the function documentation itself. That feels way\n> less out of place compared to putting this info into the commit message\n> and has the benefit that a future reader of the code will know why we\n> have types without digging into the commit history.\n\nGood idea, thanks.\n\nThanks,\nTaylor\n"},{"id":"505395","messageId":"ZxF6+ze67duAO8fn@nand.local","threadId":"62313","inReplyTo":"cover.1729140565.git.ps@pks.im","subject":"Re: [PATCH v3 00/10] reftable: stop using `struct strbuf`","fromName":"Taylor Blau","fromEmail":"me@ttaylorr.com","sentAt":"2024-10-17T21:00:43Z","receivedAt":"2024-10-17T21:00:47Z","isPatch":true,"sender":{"key":"me@ttaylorr.com","avatar":"https://avatars.githubusercontent.com/u/301000140?v=4"},"body":"On Thu, Oct 17, 2024 at 06:53:42AM +0200, Patrick Steinhardt wrote:\n> Range-diff against v2:\n\nThe range-diff looks like we're getting close here, or are already\nthere. Do others agree that this is ready to start merging down?\n\nThanks,\nTaylor\n"},{"id":"505413","messageId":"CAOLa=ZStxERhENJ_3osJCWR7u6Pr1YeMjCf3UvTxnce9SDReLA@mail.gmail.com","threadId":"62313","inReplyTo":"ZxF6+ze67duAO8fn@nand.local","subject":"Re: [PATCH v3 00/10] reftable: stop using `struct strbuf`","fromName":"karthik nayak","fromEmail":"karthik.188@gmail.com","sentAt":"2024-10-18T07:46:02Z","receivedAt":"2024-10-18T07:46:04Z","isPatch":true,"sender":{"key":"karthik.188@gmail.com","avatar":"https://avatars.githubusercontent.com/u/1786334?v=4"},"body":"Taylor Blau <me@ttaylorr.com> writes:\n\n> On Thu, Oct 17, 2024 at 06:53:42AM +0200, Patrick Steinhardt wrote:\n>> Range-diff against v2:\n>\n> The range-diff looks like we're getting close here, or are already\n> there. Do others agree that this is ready to start merging down?\n>\n> Thanks,\n> Taylor\n\nI had already reviewed version 1, having a look at the range-diff now,\nseems like it is ready to be merged!\n\nThanks,\nKarthik\n"},{"id":"505475","messageId":"ZxLWHOMIqBka5T9e@nand.local","threadId":"62313","inReplyTo":"CAOLa=ZStxERhENJ_3osJCWR7u6Pr1YeMjCf3UvTxnce9SDReLA@mail.gmail.com","subject":"Re: [PATCH v3 00/10] reftable: stop using `struct strbuf`","fromName":"Taylor Blau","fromEmail":"me@ttaylorr.com","sentAt":"2024-10-18T21:41:48Z","receivedAt":"2024-10-18T21:41:52Z","isPatch":true,"sender":{"key":"me@ttaylorr.com","avatar":"https://avatars.githubusercontent.com/u/301000140?v=4"},"body":"On Fri, Oct 18, 2024 at 12:46:02AM -0700, karthik nayak wrote:\n> Taylor Blau <me@ttaylorr.com> writes:\n>\n> > On Thu, Oct 17, 2024 at 06:53:42AM +0200, Patrick Steinhardt wrote:\n> >> Range-diff against v2:\n> >\n> > The range-diff looks like we're getting close here, or are already\n> > there. Do others agree that this is ready to start merging down?\n> >\n> > Thanks,\n> > Taylor\n>\n> I had already reviewed version 1, having a look at the range-diff now,\n> seems like it is ready to be merged!\n\nThanks, both.\n\nThanks,\nTaylor\n"}]}