All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Han-Wen Nienhuys via GitGitGadget" <gitgitgadget@gmail.com>
To: git@vger.kernel.org
Cc: Han-Wen Nienhuys <hanwenn@gmail.com>
Subject: [PATCH v8 0/9] Reftable support git-core
Date: Wed, 01 Apr 2020 11:28:49 +0000	[thread overview]
Message-ID: <pull.539.v8.git.1585740538.gitgitgadget@gmail.com> (raw)
In-Reply-To: <pull.539.v7.git.1582706986.gitgitgadget@gmail.com>

This adds the reftable library, and hooks it up as a ref backend.

Feedback wanted:

 * spots marked with XXX in the Git source code.
   
   
 * what is a good test strategy? Could we have a CI flavor where we flip the
   default to reftable, and see how it fares?
   
   

v8

 * propagate errors to git.
 * discard empty tables in the stack. 
 * one very basic test (t0031.sh)

v9

 * Added spec as technical doc.
 * Use 4-byte hash ID as API. Storage format for SHA256 is still pending
   discussion.

v10 

 * Serialize 4 byte hash ID to the version-2 format

v11

 * use reftable_ namespace prefix.
 * transaction API to provide locking.
 * reorganized record.{h,c}. More doc in reftable.h
 * support log record deletion.
 * pluggable malloc/free

Han-Wen Nienhuys (8):
  refs.h: clarify reflog iteration order
  create .git/refs in files-backend.c
  refs: document how ref_iterator_advance_fn should handle symrefs
  Add .gitattributes for the reftable/ directory
  reftable: define version 2 of the spec to accomodate SHA256
  reftable: clarify how empty tables should be written
  Add reftable library
  Reftable support for git-core

Jonathan Nieder (1):
  reftable: file format documentation

 Documentation/Makefile                        |    1 +
 Documentation/technical/reftable.txt          | 1080 ++++++++++++++++
 .../technical/repository-version.txt          |    7 +
 Makefile                                      |   24 +-
 builtin/clone.c                               |    5 +-
 builtin/init-db.c                             |   51 +-
 cache.h                                       |    4 +-
 refs.c                                        |   20 +-
 refs.h                                        |    7 +-
 refs/files-backend.c                          |    6 +
 refs/refs-internal.h                          |    6 +
 refs/reftable-backend.c                       | 1002 +++++++++++++++
 reftable/.gitattributes                       |    1 +
 reftable/LICENSE                              |   31 +
 reftable/README.md                            |   11 +
 reftable/VERSION                              |    5 +
 reftable/basics.c                             |  194 +++
 reftable/basics.h                             |   35 +
 reftable/block.c                              |  433 +++++++
 reftable/block.h                              |   76 ++
 reftable/blocksource.h                        |   22 +
 reftable/bytes.c                              |    0
 reftable/config.h                             |    1 +
 reftable/constants.h                          |   21 +
 reftable/dump.c                               |   97 ++
 reftable/file.c                               |   98 ++
 reftable/iter.c                               |  234 ++++
 reftable/iter.h                               |   56 +
 reftable/merged.c                             |  299 +++++
 reftable/merged.h                             |   34 +
 reftable/pq.c                                 |  115 ++
 reftable/pq.h                                 |   34 +
 reftable/reader.c                             |  756 +++++++++++
 reftable/reader.h                             |   60 +
 reftable/record.c                             | 1098 ++++++++++++++++
 reftable/record.h                             |  106 ++
 reftable/reftable.h                           |  520 ++++++++
 reftable/slice.c                              |  219 ++++
 reftable/slice.h                              |   42 +
 reftable/stack.c                              | 1132 +++++++++++++++++
 reftable/stack.h                              |   42 +
 reftable/system.h                             |   53 +
 reftable/tree.c                               |   67 +
 reftable/tree.h                               |   24 +
 reftable/update.sh                            |   14 +
 reftable/writer.c                             |  653 ++++++++++
 reftable/writer.h                             |   45 +
 reftable/zlib-compat.c                        |   92 ++
 repository.c                                  |    2 +
 repository.h                                  |    3 +
 setup.c                                       |   12 +-
 t/t0031-reftable.sh                           |   35 +
 52 files changed, 8954 insertions(+), 31 deletions(-)
 create mode 100644 Documentation/technical/reftable.txt
 create mode 100644 refs/reftable-backend.c
 create mode 100644 reftable/.gitattributes
 create mode 100644 reftable/LICENSE
 create mode 100644 reftable/README.md
 create mode 100644 reftable/VERSION
 create mode 100644 reftable/basics.c
 create mode 100644 reftable/basics.h
 create mode 100644 reftable/block.c
 create mode 100644 reftable/block.h
 create mode 100644 reftable/blocksource.h
 create mode 100644 reftable/bytes.c
 create mode 100644 reftable/config.h
 create mode 100644 reftable/constants.h
 create mode 100644 reftable/dump.c
 create mode 100644 reftable/file.c
 create mode 100644 reftable/iter.c
 create mode 100644 reftable/iter.h
 create mode 100644 reftable/merged.c
 create mode 100644 reftable/merged.h
 create mode 100644 reftable/pq.c
 create mode 100644 reftable/pq.h
 create mode 100644 reftable/reader.c
 create mode 100644 reftable/reader.h
 create mode 100644 reftable/record.c
 create mode 100644 reftable/record.h
 create mode 100644 reftable/reftable.h
 create mode 100644 reftable/slice.c
 create mode 100644 reftable/slice.h
 create mode 100644 reftable/stack.c
 create mode 100644 reftable/stack.h
 create mode 100644 reftable/system.h
 create mode 100644 reftable/tree.c
 create mode 100644 reftable/tree.h
 create mode 100644 reftable/update.sh
 create mode 100644 reftable/writer.c
 create mode 100644 reftable/writer.h
 create mode 100644 reftable/zlib-compat.c
 create mode 100755 t/t0031-reftable.sh


base-commit: 9fadedd637b312089337d73c3ed8447e9f0aa775
Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-539%2Fhanwen%2Freftable-v8
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-539/hanwen/reftable-v8
Pull-Request: https://github.com/gitgitgadget/git/pull/539

Range-diff vs v7:

  1:  b1e44bc431e =  1:  05634d26dd5 refs.h: clarify reflog iteration order
  2:  b68488a095e =  2:  8d34e2c5c8b create .git/refs in files-backend.c
  3:  da538ef7421 =  3:  d08f823844d refs: document how ref_iterator_advance_fn should handle symrefs
  -:  ----------- >  4:  ca95b3a371e Add .gitattributes for the reftable/ directory
  4:  aae26814983 =  5:  dfc8b131294 reftable: file format documentation
  -:  ----------- >  6:  45ab5361750 reftable: define version 2 of the spec to accomodate SHA256
  -:  ----------- >  7:  67ee5962e85 reftable: clarify how empty tables should be written
  5:  30ed43a4fdb !  8:  4f9bdd7312b Add reftable library
     @@ -5,21 +5,21 @@
          Reftable is a format for storing the ref database. Its rationale and
          specification is in the preceding commit.
      
     -    Further context and motivation can be found in background reading:
     +    This imports the upstream library as one big commit. For understanding
     +    the code, it is suggested to read the code in the following order:
      
     -    * Original discussion on JGit-dev:  https://www.eclipse.org/lists/jgit-dev/msg03389.html
     +    * The specification under Documentation/technical/reftable.txt
      
     -    * First design discussion on git@vger: https://public-inbox.org/git/CAJo=hJtTp2eA3z9wW9cHo-nA7kK40vVThqh6inXpbCcqfdMP9g@mail.gmail.com/
     +    * reftable.h - the public API
      
     -    * Last design discussion on git@vger: https://public-inbox.org/git/CAJo=hJsZcAM9sipdVr7TMD-FD2V2W6_pvMQ791EGCDsDkQ033w@mail.gmail.com/
     +    * block.{c,h} - reading and writing blocks.
      
     -    * First attempt at implementation: https://public-inbox.org/git/CAP8UFD0PPZSjBnxCA7ez91vBuatcHKQ+JUWvTD1iHcXzPBjPBg@mail.gmail.com/
     +    * writer.{c,h} - writing a complete reftable file.
      
     -    * libgit2 support issue: https://github.com/libgit2/libgit2/issues
     +    * merged.{c,h} and pq.{c,h} - reading a stack of reftables
      
     -    * GitLab support issue: https://gitlab.com/gitlab-org/git/issues/6
     -
     -    * go-git support issue: https://github.com/src-d/go-git/issues/1059
     +    * stack.{c,h} - writing and compacting stacks of reftable on the
     +    filesystem.
      
          Signed-off-by: Han-Wen Nienhuys <hanwen@google.com>
      
     @@ -82,11 +82,11 @@
       --- /dev/null
       +++ b/reftable/VERSION
      @@
     -+commit ccce3b3eb763e79b23a3b4677d65ecceb4155ba3
     ++commit 920f7413f7a25f308d9a203f584873f6753192ec
      +Author: Han-Wen Nienhuys <hanwen@google.com>
     -+Date:   Tue Feb 25 20:42:29 2020 +0100
     ++Date:   Wed Apr 1 12:41:41 2020 +0200
      +
     -+    C: rephrase the hash ID API in terms of a uint32_t
     ++    C: remove stray debug printfs
      
       diff --git a/reftable/basics.c b/reftable/basics.c
       new file mode 100644
     @@ -165,10 +165,10 @@
      +		return;
      +	}
      +	while (*p) {
     -+		free(*p);
     ++		reftable_free(*p);
      +		p++;
      +	}
     -+	free(a);
     ++	reftable_free(a);
      +}
      +
      +int names_length(char **names)
     @@ -201,8 +201,8 @@
      +		if (p < next) {
      +			if (names_len == names_cap) {
      +				names_cap = 2 * names_cap + 1;
     -+				names = realloc(names,
     -+						names_cap * sizeof(char *));
     ++				names = reftable_realloc(
     ++					names, names_cap * sizeof(char *));
      +			}
      +			names[names_len++] = xstrdup(p);
      +		}
     @@ -211,7 +211,7 @@
      +
      +	if (names_len == names_cap) {
      +		names_cap = 2 * names_cap + 1;
     -+		names = realloc(names, names_cap * sizeof(char *));
     ++		names = reftable_realloc(names, names_cap * sizeof(char *));
      +	}
      +
      +	names[names_len] = NULL;
     @@ -232,7 +232,7 @@
      +	return *a == *b;
      +}
      +
     -+const char *error_str(int err)
     ++const char *reftable_error_str(int err)
      +{
      +	switch (err) {
      +	case IO_ERROR:
     @@ -252,6 +252,40 @@
      +	default:
      +		return "unknown error code";
      +	}
     ++}
     ++
     ++void *(*reftable_malloc_ptr)(size_t sz) = &malloc;
     ++void *(*reftable_realloc_ptr)(void *, size_t) = &realloc;
     ++void (*reftable_free_ptr)(void *) = &free;
     ++
     ++void *reftable_malloc(size_t sz)
     ++{
     ++	return (*reftable_malloc_ptr)(sz);
     ++}
     ++
     ++void *reftable_realloc(void *p, size_t sz)
     ++{
     ++	return (*reftable_realloc_ptr)(p, sz);
     ++}
     ++
     ++void reftable_free(void *p)
     ++{
     ++	reftable_free_ptr(p);
     ++}
     ++
     ++void *reftable_calloc(size_t sz)
     ++{
     ++	void *p = reftable_malloc(sz);
     ++	memset(p, 0, sz);
     ++	return p;
     ++}
     ++
     ++void reftable_set_alloc(void *(*malloc)(size_t),
     ++			void *(*realloc)(void *, size_t), void (*free)(void *))
     ++{
     ++	reftable_malloc_ptr = malloc;
     ++	reftable_realloc_ptr = realloc;
     ++	reftable_free_ptr = free;
      +}
      
       diff --git a/reftable/basics.h b/reftable/basics.h
     @@ -288,6 +322,11 @@
      +int names_equal(char **a, char **b);
      +int names_length(char **names);
      +
     ++void *reftable_malloc(size_t sz);
     ++void *reftable_realloc(void *p, size_t sz);
     ++void reftable_free(void *p);
     ++void *reftable_calloc(size_t sz);
     ++
      +#endif
      
       diff --git a/reftable/block.c b/reftable/block.c
     @@ -313,10 +352,32 @@
      +#include "reftable.h"
      +#include "zlib.h"
      +
     -+int block_writer_register_restart(struct block_writer *w, int n, bool restart,
     -+				  struct slice key);
     ++int header_size(int version)
     ++{
     ++	switch (version) {
     ++	case 1:
     ++		return 24;
     ++	case 2:
     ++		return 28;
     ++	}
     ++	abort();
     ++}
     ++
     ++int footer_size(int version)
     ++{
     ++	switch (version) {
     ++	case 1:
     ++		return 68;
     ++	case 2:
     ++		return 72;
     ++	}
     ++	abort();
     ++}
     ++
     ++int block_writer_register_restart(struct reftable_block_writer *w, int n,
     ++				  bool restart, struct slice key);
      +
     -+void block_writer_init(struct block_writer *bw, byte typ, byte *buf,
     ++void block_writer_init(struct reftable_block_writer *bw, byte typ, byte *buf,
      +		       uint32_t block_size, uint32_t header_off, int hash_size)
      +{
      +	bw->buf = buf;
     @@ -329,14 +390,14 @@
      +	bw->entries = 0;
      +}
      +
     -+byte block_writer_type(struct block_writer *bw)
     ++byte block_writer_type(struct reftable_block_writer *bw)
      +{
      +	return bw->buf[bw->header_off];
      +}
      +
      +/* adds the record to the block. Returns -1 if it does not fit, 0 on
      +   success */
     -+int block_writer_add(struct block_writer *w, struct record rec)
     ++int block_writer_add(struct reftable_block_writer *w, struct record rec)
      +{
      +	struct slice empty = { 0 };
      +	struct slice last = w->entries % w->restart_interval == 0 ? empty :
     @@ -357,32 +418,29 @@
      +	if (n < 0) {
      +		goto err;
      +	}
     -+	out.buf += n;
     -+	out.len -= n;
     ++	slice_consume(&out, n);
      +
      +	n = record_encode(rec, out, w->hash_size);
      +	if (n < 0) {
      +		goto err;
      +	}
     -+
     -+	out.buf += n;
     -+	out.len -= n;
     ++	slice_consume(&out, n);
      +
      +	if (block_writer_register_restart(w, start.len - out.len, restart,
      +					  key) < 0) {
      +		goto err;
      +	}
      +
     -+	free(slice_yield(&key));
     ++	reftable_free(slice_yield(&key));
      +	return 0;
      +
      +err:
     -+	free(slice_yield(&key));
     ++	reftable_free(slice_yield(&key));
      +	return -1;
      +}
      +
     -+int block_writer_register_restart(struct block_writer *w, int n, bool restart,
     -+				  struct slice key)
     ++int block_writer_register_restart(struct reftable_block_writer *w, int n,
     ++				  bool restart, struct slice key)
      +{
      +	int rlen = w->restart_len;
      +	if (rlen >= MAX_RESTARTS) {
     @@ -398,7 +456,7 @@
      +	if (restart) {
      +		if (w->restart_len == w->restart_cap) {
      +			w->restart_cap = w->restart_cap * 2 + 1;
     -+			w->restarts = realloc(
     ++			w->restarts = reftable_realloc(
      +				w->restarts, sizeof(uint32_t) * w->restart_cap);
      +		}
      +
     @@ -411,7 +469,7 @@
      +	return 0;
      +}
      +
     -+int block_writer_finish(struct block_writer *w)
     ++int block_writer_finish(struct reftable_block_writer *w)
      +{
      +	int i = 0;
      +	for (i = 0; i < w->restart_len; i++) {
     @@ -442,7 +500,7 @@
      +			}
      +
      +			if (Z_OK != zresult) {
     -+				free(slice_yield(&compressed));
     ++				reftable_free(slice_yield(&compressed));
      +				return ZLIB_ERROR;
      +			}
      +
     @@ -455,14 +513,14 @@
      +	return w->next;
      +}
      +
     -+byte block_reader_type(struct block_reader *r)
     ++byte block_reader_type(struct reftable_block_reader *r)
      +{
      +	return r->block.data[r->header_off];
      +}
      +
     -+int block_reader_init(struct block_reader *br, struct block *block,
     -+		      uint32_t header_off, uint32_t table_block_size,
     -+		      int hash_size)
     ++int block_reader_init(struct reftable_block_reader *br,
     ++		      struct reftable_block *block, uint32_t header_off,
     ++		      uint32_t table_block_size, int hash_size)
      +{
      +	uint32_t full_block_size = table_block_size;
      +	byte typ = block->data[header_off];
     @@ -485,7 +543,7 @@
      +				    uncompressed.buf + block_header_skip,
      +				    &dst_len, block->data + block_header_skip,
      +				    &src_len)) {
     -+			free(slice_yield(&uncompressed));
     ++			reftable_free(slice_yield(&uncompressed));
      +			return ZLIB_ERROR;
      +		}
      +
     @@ -526,12 +584,14 @@
      +	return 0;
      +}
      +
     -+static uint32_t block_reader_restart_offset(struct block_reader *br, int i)
     ++static uint32_t block_reader_restart_offset(struct reftable_block_reader *br,
     ++					    int i)
      +{
      +	return get_be24(br->restart_bytes + 3 * i);
      +}
      +
     -+void block_reader_start(struct block_reader *br, struct block_iter *it)
     ++void block_reader_start(struct reftable_block_reader *br,
     ++			struct reftable_block_iter *it)
      +{
      +	it->br = br;
      +	slice_resize(&it->last_key, 0);
     @@ -541,7 +601,7 @@
      +struct restart_find_args {
      +	int error;
      +	struct slice key;
     -+	struct block_reader *r;
     ++	struct reftable_block_reader *r;
      +};
      +
      +static int restart_key_less(int idx, void *args)
     @@ -566,12 +626,13 @@
      +
      +	{
      +		int result = slice_compare(a->key, rkey);
     -+		free(slice_yield(&rkey));
     ++		reftable_free(slice_yield(&rkey));
      +		return result;
      +	}
      +}
      +
     -+void block_iter_copy_from(struct block_iter *dest, struct block_iter *src)
     ++void block_iter_copy_from(struct reftable_block_iter *dest,
     ++			  struct reftable_block_iter *src)
      +{
      +	dest->br = src->br;
      +	dest->next_off = src->next_off;
     @@ -579,7 +640,7 @@
      +}
      +
      +/* return < 0 for error, 0 for OK, > 0 for EOF. */
     -+int block_iter_next(struct block_iter *it, struct record rec)
     ++int block_iter_next(struct reftable_block_iter *it, struct record rec)
      +{
      +	if (it->next_off >= it->br->block_len) {
      +		return 1;
     @@ -598,23 +659,21 @@
      +			return -1;
      +		}
      +
     -+		in.buf += n;
     -+		in.len -= n;
     ++		slice_consume(&in, n);
      +		n = record_decode(rec, key, extra, in, it->br->hash_size);
      +		if (n < 0) {
      +			return -1;
      +		}
     -+		in.buf += n;
     -+		in.len -= n;
     ++		slice_consume(&in, n);
      +
      +		slice_copy(&it->last_key, key);
      +		it->next_off += start.len - in.len;
     -+		free(slice_yield(&key));
     ++		reftable_free(slice_yield(&key));
      +		return 0;
      +	}
      +}
      +
     -+int block_reader_first_key(struct block_reader *br, struct slice *key)
     ++int block_reader_first_key(struct reftable_block_reader *br, struct slice *key)
      +{
      +	struct slice empty = { 0 };
      +	int off = br->header_off + 4;
     @@ -631,18 +690,18 @@
      +	return 0;
      +}
      +
     -+int block_iter_seek(struct block_iter *it, struct slice want)
     ++int block_iter_seek(struct reftable_block_iter *it, struct slice want)
      +{
      +	return block_reader_seek(it->br, it, want);
      +}
      +
     -+void block_iter_close(struct block_iter *it)
     ++void block_iter_close(struct reftable_block_iter *it)
      +{
     -+	free(slice_yield(&it->last_key));
     ++	reftable_free(slice_yield(&it->last_key));
      +}
      +
     -+int block_reader_seek(struct block_reader *br, struct block_iter *it,
     -+		      struct slice want)
     ++int block_reader_seek(struct reftable_block_reader *br,
     ++		      struct reftable_block_iter *it, struct slice want)
      +{
      +	struct restart_find_args args = {
      +		.key = want,
     @@ -667,7 +726,7 @@
      +		struct slice key = { 0 };
      +		int result = 0;
      +		int err = 0;
     -+		struct block_iter next = { 0 };
     ++		struct reftable_block_iter next = { 0 };
      +		while (true) {
      +			block_iter_copy_from(&next, it);
      +
     @@ -687,25 +746,25 @@
      +		}
      +
      +	exit:
     -+		free(slice_yield(&key));
     -+		free(slice_yield(&next.last_key));
     ++		reftable_free(slice_yield(&key));
     ++		reftable_free(slice_yield(&next.last_key));
      +		record_clear(rec);
     -+		free(record_yield(&rec));
     ++		reftable_free(record_yield(&rec));
      +
      +		return result;
      +	}
      +}
      +
     -+void block_writer_reset(struct block_writer *bw)
     ++void block_writer_reset(struct reftable_block_writer *bw)
      +{
      +	bw->restart_len = 0;
      +	bw->last_key.len = 0;
      +}
      +
     -+void block_writer_clear(struct block_writer *bw)
     ++void block_writer_clear(struct reftable_block_writer *bw)
      +{
      +	FREE_AND_NULL(bw->restarts);
     -+	free(slice_yield(&bw->last_key));
     ++	reftable_free(slice_yield(&bw->last_key));
      +	/* the block is not owned. */
      +}
      
     @@ -729,7 +788,7 @@
      +#include "record.h"
      +#include "reftable.h"
      +
     -+struct block_writer {
     ++struct reftable_block_writer {
      +	byte *buf;
      +	uint32_t block_size;
      +	uint32_t header_off;
     @@ -744,17 +803,17 @@
      +	int entries;
      +};
      +
     -+void block_writer_init(struct block_writer *bw, byte typ, byte *buf,
     ++void block_writer_init(struct reftable_block_writer *bw, byte typ, byte *buf,
      +		       uint32_t block_size, uint32_t header_off, int hash_size);
     -+byte block_writer_type(struct block_writer *bw);
     -+int block_writer_add(struct block_writer *w, struct record rec);
     -+int block_writer_finish(struct block_writer *w);
     -+void block_writer_reset(struct block_writer *bw);
     -+void block_writer_clear(struct block_writer *bw);
     ++byte block_writer_type(struct reftable_block_writer *bw);
     ++int block_writer_add(struct reftable_block_writer *w, struct record rec);
     ++int block_writer_finish(struct reftable_block_writer *w);
     ++void block_writer_reset(struct reftable_block_writer *bw);
     ++void block_writer_clear(struct reftable_block_writer *bw);
      +
     -+struct block_reader {
     ++struct reftable_block_reader {
      +	uint32_t header_off;
     -+	struct block block;
     ++	struct reftable_block block;
      +	int hash_size;
      +
      +	/* size of the data, excluding restart data. */
     @@ -764,25 +823,30 @@
      +	uint16_t restart_count;
      +};
      +
     -+struct block_iter {
     ++struct reftable_block_iter {
      +	uint32_t next_off;
     -+	struct block_reader *br;
     ++	struct reftable_block_reader *br;
      +	struct slice last_key;
      +};
      +
     -+int block_reader_init(struct block_reader *br, struct block *bl,
     -+		      uint32_t header_off, uint32_t table_block_size,
     -+		      int hash_size);
     -+void block_reader_start(struct block_reader *br, struct block_iter *it);
     -+int block_reader_seek(struct block_reader *br, struct block_iter *it,
     -+		      struct slice want);
     -+byte block_reader_type(struct block_reader *r);
     -+int block_reader_first_key(struct block_reader *br, struct slice *key);
     -+
     -+void block_iter_copy_from(struct block_iter *dest, struct block_iter *src);
     -+int block_iter_next(struct block_iter *it, struct record rec);
     -+int block_iter_seek(struct block_iter *it, struct slice want);
     -+void block_iter_close(struct block_iter *it);
     ++int block_reader_init(struct reftable_block_reader *br,
     ++		      struct reftable_block *bl, uint32_t header_off,
     ++		      uint32_t table_block_size, int hash_size);
     ++void block_reader_start(struct reftable_block_reader *br,
     ++			struct reftable_block_iter *it);
     ++int block_reader_seek(struct reftable_block_reader *br,
     ++		      struct reftable_block_iter *it, struct slice want);
     ++byte block_reader_type(struct reftable_block_reader *r);
     ++int block_reader_first_key(struct reftable_block_reader *br, struct slice *key);
     ++
     ++void block_iter_copy_from(struct reftable_block_iter *dest,
     ++			  struct reftable_block_iter *src);
     ++int block_iter_next(struct reftable_block_iter *it, struct record rec);
     ++int block_iter_seek(struct reftable_block_iter *it, struct slice want);
     ++void block_iter_close(struct reftable_block_iter *it);
     ++
     ++int header_size(int version);
     ++int footer_size(int version);
      +
      +#endif
      
     @@ -804,11 +868,13 @@
      +
      +#include "reftable.h"
      +
     -+uint64_t block_source_size(struct block_source source);
     -+int block_source_read_block(struct block_source source, struct block *dest,
     -+			    uint64_t off, uint32_t size);
     -+void block_source_return_block(struct block_source source, struct block *ret);
     -+void block_source_close(struct block_source source);
     ++uint64_t block_source_size(struct reftable_block_source source);
     ++int block_source_read_block(struct reftable_block_source source,
     ++			    struct reftable_block *dest, uint64_t off,
     ++			    uint32_t size);
     ++void block_source_return_block(struct reftable_block_source source,
     ++			       struct reftable_block *ret);
     ++void block_source_close(struct reftable_block_source source);
      +
      +#endif
      
     @@ -838,10 +904,6 @@
      +#ifndef CONSTANTS_H
      +#define CONSTANTS_H
      +
     -+#define VERSION 1
     -+#define HEADER_SIZE 24
     -+#define FOOTER_SIZE 68
     -+
      +#define BLOCK_TYPE_LOG 'g'
      +#define BLOCK_TYPE_INDEX 'i'
      +#define BLOCK_TYPE_REF 'r'
     @@ -987,10 +1049,10 @@
      +	return ((struct file_block_source *)b)->size;
      +}
      +
     -+static void file_return_block(void *b, struct block *dest)
     ++static void file_return_block(void *b, struct reftable_block *dest)
      +{
      +	memset(dest->data, 0xff, dest->len);
     -+	free(dest->data);
     ++	reftable_free(dest->data);
      +}
      +
      +static void file_close(void *b)
     @@ -1001,15 +1063,15 @@
      +		((struct file_block_source *)b)->fd = 0;
      +	}
      +
     -+	free(b);
     ++	reftable_free(b);
      +}
      +
     -+static int file_read_block(void *v, struct block *dest, uint64_t off,
     ++static int file_read_block(void *v, struct reftable_block *dest, uint64_t off,
      +			   uint32_t size)
      +{
      +	struct file_block_source *b = (struct file_block_source *)v;
      +	assert(off + size <= b->size);
     -+	dest->data = malloc(size);
     ++	dest->data = reftable_malloc(size);
      +	if (pread(b->fd, dest->data, size, off) != size) {
      +		return -1;
      +	}
     @@ -1017,14 +1079,15 @@
      +	return size;
      +}
      +
     -+struct block_source_vtable file_vtable = {
     ++struct reftable_block_source_vtable file_vtable = {
      +	.size = &file_size,
      +	.read_block = &file_read_block,
      +	.return_block = &file_return_block,
      +	.close = &file_close,
      +};
      +
     -+int block_source_from_file(struct block_source *bs, const char *name)
     ++int reftable_block_source_from_file(struct reftable_block_source *bs,
     ++				    const char *name)
      +{
      +	struct stat st = { 0 };
      +	int err = 0;
     @@ -1043,7 +1106,7 @@
      +
      +	{
      +		struct file_block_source *p =
     -+			calloc(sizeof(struct file_block_source), 1);
     ++			reftable_calloc(sizeof(struct file_block_source));
      +		p->size = st.st_size;
      +		p->fd = fd;
      +
     @@ -1053,7 +1116,7 @@
      +	return 0;
      +}
      +
     -+int fd_writer(void *arg, byte *data, int sz)
     ++int reftable_fd_write(void *arg, byte *data, int sz)
      +{
      +	int *fdp = (int *)arg;
      +	return write(*fdp, data, sz);
     @@ -1081,7 +1144,7 @@
      +#include "reader.h"
      +#include "reftable.h"
      +
     -+bool iterator_is_null(struct iterator it)
     ++bool iterator_is_null(struct reftable_iterator it)
      +{
      +	return it.ops == NULL;
      +}
     @@ -1095,23 +1158,23 @@
      +{
      +}
      +
     -+struct iterator_vtable empty_vtable = {
     ++struct reftable_iterator_vtable empty_vtable = {
      +	.next = &empty_iterator_next,
      +	.close = &empty_iterator_close,
      +};
      +
     -+void iterator_set_empty(struct iterator *it)
     ++void iterator_set_empty(struct reftable_iterator *it)
      +{
      +	it->iter_arg = NULL;
      +	it->ops = &empty_vtable;
      +}
      +
     -+int iterator_next(struct iterator it, struct record rec)
     ++int iterator_next(struct reftable_iterator it, struct record rec)
      +{
      +	return it.ops->next(it.iter_arg, rec);
      +}
      +
     -+void iterator_destroy(struct iterator *it)
     ++void reftable_iterator_destroy(struct reftable_iterator *it)
      +{
      +	if (it->ops == NULL) {
      +		return;
     @@ -1121,14 +1184,16 @@
      +	FREE_AND_NULL(it->iter_arg);
      +}
      +
     -+int iterator_next_ref(struct iterator it, struct ref_record *ref)
     ++int reftable_iterator_next_ref(struct reftable_iterator it,
     ++			       struct reftable_ref_record *ref)
      +{
      +	struct record rec = { 0 };
      +	record_from_ref(&rec, ref);
      +	return iterator_next(it, rec);
      +}
      +
     -+int iterator_next_log(struct iterator it, struct log_record *log)
     ++int reftable_iterator_next_log(struct reftable_iterator it,
     ++			       struct reftable_log_record *log)
      +{
      +	struct record rec = { 0 };
      +	record_from_log(&rec, log);
     @@ -1139,31 +1204,33 @@
      +{
      +	struct filtering_ref_iterator *fri =
      +		(struct filtering_ref_iterator *)iter_arg;
     -+	free(slice_yield(&fri->oid));
     -+	iterator_destroy(&fri->it);
     ++	reftable_free(slice_yield(&fri->oid));
     ++	reftable_iterator_destroy(&fri->it);
      +}
      +
      +static int filtering_ref_iterator_next(void *iter_arg, struct record rec)
      +{
      +	struct filtering_ref_iterator *fri =
      +		(struct filtering_ref_iterator *)iter_arg;
     -+	struct ref_record *ref = (struct ref_record *)rec.data;
     ++	struct reftable_ref_record *ref =
     ++		(struct reftable_ref_record *)rec.data;
      +
      +	while (true) {
     -+		int err = iterator_next_ref(fri->it, ref);
     ++		int err = reftable_iterator_next_ref(fri->it, ref);
      +		if (err != 0) {
      +			return err;
      +		}
      +
      +		if (fri->double_check) {
     -+			struct iterator it = { 0 };
     ++			struct reftable_iterator it = { 0 };
      +
     -+			int err = reader_seek_ref(fri->r, &it, ref->ref_name);
     ++			int err = reftable_reader_seek_ref(fri->r, &it,
     ++							   ref->ref_name);
      +			if (err == 0) {
     -+				err = iterator_next_ref(it, ref);
     ++				err = reftable_iterator_next_ref(it, ref);
      +			}
      +
     -+			iterator_destroy(&it);
     ++			reftable_iterator_destroy(&it);
      +
      +			if (err < 0) {
      +				return err;
     @@ -1183,12 +1250,12 @@
      +	}
      +}
      +
     -+struct iterator_vtable filtering_ref_iterator_vtable = {
     ++struct reftable_iterator_vtable filtering_ref_iterator_vtable = {
      +	.next = &filtering_ref_iterator_next,
      +	.close = &filtering_ref_iterator_close,
      +};
      +
     -+void iterator_from_filtering_ref_iterator(struct iterator *it,
     ++void iterator_from_filtering_ref_iterator(struct reftable_iterator *it,
      +					  struct filtering_ref_iterator *fri)
      +{
      +	it->iter_arg = fri;
     @@ -1200,7 +1267,7 @@
      +	struct indexed_table_ref_iter *it = (struct indexed_table_ref_iter *)p;
      +	block_iter_close(&it->cur);
      +	reader_return_block(it->r, &it->block_reader.block);
     -+	free(slice_yield(&it->oid));
     ++	reftable_free(slice_yield(&it->oid));
      +}
      +
      +static int indexed_table_ref_iter_next_block(struct indexed_table_ref_iter *it)
     @@ -1231,7 +1298,8 @@
      +static int indexed_table_ref_iter_next(void *p, struct record rec)
      +{
      +	struct indexed_table_ref_iter *it = (struct indexed_table_ref_iter *)p;
     -+	struct ref_record *ref = (struct ref_record *)rec.data;
     ++	struct reftable_ref_record *ref =
     ++		(struct reftable_ref_record *)rec.data;
      +
      +	while (true) {
      +		int err = block_iter_next(&it->cur, rec);
     @@ -1259,11 +1327,11 @@
      +}
      +
      +int new_indexed_table_ref_iter(struct indexed_table_ref_iter **dest,
     -+			       struct reader *r, byte *oid, int oid_len,
     -+			       uint64_t *offsets, int offset_len)
     ++			       struct reftable_reader *r, byte *oid,
     ++			       int oid_len, uint64_t *offsets, int offset_len)
      +{
      +	struct indexed_table_ref_iter *itr =
     -+		calloc(sizeof(struct indexed_table_ref_iter), 1);
     ++		reftable_calloc(sizeof(struct indexed_table_ref_iter));
      +	int err = 0;
      +
      +	itr->r = r;
     @@ -1275,19 +1343,19 @@
      +
      +	err = indexed_table_ref_iter_next_block(itr);
      +	if (err < 0) {
     -+		free(itr);
     ++		reftable_free(itr);
      +	} else {
      +		*dest = itr;
      +	}
      +	return err;
      +}
      +
     -+struct iterator_vtable indexed_table_ref_iter_vtable = {
     ++struct reftable_iterator_vtable indexed_table_ref_iter_vtable = {
      +	.next = &indexed_table_ref_iter_next,
      +	.close = &indexed_table_ref_iter_close,
      +};
      +
     -+void iterator_from_indexed_table_ref_iter(struct iterator *it,
     ++void iterator_from_indexed_table_ref_iter(struct reftable_iterator *it,
      +					  struct indexed_table_ref_iter *itr)
      +{
      +	it->iter_arg = itr;
     @@ -1314,27 +1382,27 @@
      +#include "record.h"
      +#include "slice.h"
      +
     -+struct iterator_vtable {
     ++struct reftable_iterator_vtable {
      +	int (*next)(void *iter_arg, struct record rec);
      +	void (*close)(void *iter_arg);
      +};
      +
     -+void iterator_set_empty(struct iterator *it);
     -+int iterator_next(struct iterator it, struct record rec);
     -+bool iterator_is_null(struct iterator it);
     ++void iterator_set_empty(struct reftable_iterator *it);
     ++int iterator_next(struct reftable_iterator it, struct record rec);
     ++bool iterator_is_null(struct reftable_iterator it);
      +
      +struct filtering_ref_iterator {
      +	bool double_check;
     -+	struct reader *r;
     ++	struct reftable_reader *r;
      +	struct slice oid;
     -+	struct iterator it;
     ++	struct reftable_iterator it;
      +};
      +
     -+void iterator_from_filtering_ref_iterator(struct iterator *,
     ++void iterator_from_filtering_ref_iterator(struct reftable_iterator *,
      +					  struct filtering_ref_iterator *);
      +
      +struct indexed_table_ref_iter {
     -+	struct reader *r;
     ++	struct reftable_reader *r;
      +	struct slice oid;
      +
      +	/* mutable */
     @@ -1343,16 +1411,16 @@
      +	/* Points to the next offset to read. */
      +	int offset_idx;
      +	int offset_len;
     -+	struct block_reader block_reader;
     -+	struct block_iter cur;
     ++	struct reftable_block_reader block_reader;
     ++	struct reftable_block_iter cur;
      +	bool finished;
      +};
      +
     -+void iterator_from_indexed_table_ref_iter(struct iterator *it,
     ++void iterator_from_indexed_table_ref_iter(struct reftable_iterator *it,
      +					  struct indexed_table_ref_iter *itr);
      +int new_indexed_table_ref_iter(struct indexed_table_ref_iter **dest,
     -+			       struct reader *r, byte *oid, int oid_len,
     -+			       uint64_t *offsets, int offset_len);
     ++			       struct reftable_reader *r, byte *oid,
     ++			       int oid_len, uint64_t *offsets, int offset_len);
      +
      +#endif
      
     @@ -1389,9 +1457,9 @@
      +		}
      +
      +		if (err > 0) {
     -+			iterator_destroy(&mi->stack[i]);
     ++			reftable_iterator_destroy(&mi->stack[i]);
      +			record_clear(rec);
     -+			free(record_yield(&rec));
     ++			reftable_free(record_yield(&rec));
      +		} else {
      +			struct pq_entry e = {
      +				.rec = rec,
     @@ -1410,9 +1478,9 @@
      +	int i = 0;
      +	merged_iter_pqueue_clear(&mi->pq);
      +	for (i = 0; i < mi->stack_len; i++) {
     -+		iterator_destroy(&mi->stack[i]);
     ++		reftable_iterator_destroy(&mi->stack[i]);
      +	}
     -+	free(mi->stack);
     ++	reftable_free(mi->stack);
      +}
      +
      +static int merged_iter_advance_subiter(struct merged_iter *mi, int idx)
     @@ -1433,9 +1501,9 @@
      +		}
      +
      +		if (err > 0) {
     -+			iterator_destroy(&mi->stack[idx]);
     ++			reftable_iterator_destroy(&mi->stack[idx]);
      +			record_clear(rec);
     -+			free(record_yield(&rec));
     ++			reftable_free(record_yield(&rec));
      +			return 0;
      +		}
      +
     @@ -1462,7 +1530,7 @@
      +		record_key(top.rec, &k);
      +
      +		cmp = slice_compare(k, entry_key);
     -+		free(slice_yield(&k));
     ++		reftable_free(slice_yield(&k));
      +
      +		if (cmp > 0) {
      +			break;
     @@ -1474,13 +1542,13 @@
      +			return err;
      +		}
      +		record_clear(top.rec);
     -+		free(record_yield(&top.rec));
     ++		reftable_free(record_yield(&top.rec));
      +	}
      +
      +	record_copy_from(rec, entry.rec, hash_size(mi->hash_id));
      +	record_clear(entry.rec);
     -+	free(record_yield(&entry.rec));
     -+	free(slice_yield(&entry_key));
     ++	reftable_free(record_yield(&entry.rec));
     ++	reftable_free(slice_yield(&entry_key));
      +	return 0;
      +}
      +
     @@ -1494,41 +1562,42 @@
      +	return merged_iter_next(mi, rec);
      +}
      +
     -+struct iterator_vtable merged_iter_vtable = {
     ++struct reftable_iterator_vtable merged_iter_vtable = {
      +	.next = &merged_iter_next_void,
      +	.close = &merged_iter_close,
      +};
      +
     -+static void iterator_from_merged_iter(struct iterator *it,
     ++static void iterator_from_merged_iter(struct reftable_iterator *it,
      +				      struct merged_iter *mi)
      +{
      +	it->iter_arg = mi;
      +	it->ops = &merged_iter_vtable;
      +}
      +
     -+int new_merged_table(struct merged_table **dest, struct reader **stack, int n,
     -+		     uint32_t hash_id)
     ++int reftable_new_merged_table(struct reftable_merged_table **dest,
     ++			      struct reftable_reader **stack, int n,
     ++			      uint32_t hash_id)
      +{
      +	uint64_t last_max = 0;
      +	uint64_t first_min = 0;
      +	int i = 0;
      +	for (i = 0; i < n; i++) {
     -+		struct reader *r = stack[i];
     ++		struct reftable_reader *r = stack[i];
      +		if (r->hash_id != hash_id) {
      +			return FORMAT_ERROR;
      +		}
     -+		if (i > 0 && last_max >= reader_min_update_index(r)) {
     ++		if (i > 0 && last_max >= reftable_reader_min_update_index(r)) {
      +			return FORMAT_ERROR;
      +		}
      +		if (i == 0) {
     -+			first_min = reader_min_update_index(r);
     ++			first_min = reftable_reader_min_update_index(r);
      +		}
      +
     -+		last_max = reader_max_update_index(r);
     ++		last_max = reftable_reader_max_update_index(r);
      +	}
      +
      +	{
     -+		struct merged_table m = {
     ++		struct reftable_merged_table m = {
      +			.stack = stack,
      +			.stack_len = n,
      +			.min = first_min,
     @@ -1536,52 +1605,56 @@
      +			.hash_id = hash_id,
      +		};
      +
     -+		*dest = calloc(sizeof(struct merged_table), 1);
     ++		*dest = reftable_calloc(sizeof(struct reftable_merged_table));
      +		**dest = m;
      +	}
      +	return 0;
      +}
      +
     -+void merged_table_close(struct merged_table *mt)
     ++void reftable_merged_table_close(struct reftable_merged_table *mt)
      +{
      +	int i = 0;
      +	for (i = 0; i < mt->stack_len; i++) {
     -+		reader_free(mt->stack[i]);
     ++		reftable_reader_free(mt->stack[i]);
      +	}
      +	FREE_AND_NULL(mt->stack);
      +	mt->stack_len = 0;
      +}
      +
      +/* clears the list of subtable, without affecting the readers themselves. */
     -+void merged_table_clear(struct merged_table *mt)
     ++void merged_table_clear(struct reftable_merged_table *mt)
      +{
      +	FREE_AND_NULL(mt->stack);
      +	mt->stack_len = 0;
      +}
      +
     -+void merged_table_free(struct merged_table *mt)
     ++void reftable_merged_table_free(struct reftable_merged_table *mt)
      +{
      +	if (mt == NULL) {
      +		return;
      +	}
      +	merged_table_clear(mt);
     -+	free(mt);
     ++	reftable_free(mt);
      +}
      +
     -+uint64_t merged_max_update_index(struct merged_table *mt)
     ++uint64_t
     ++reftable_merged_table_max_update_index(struct reftable_merged_table *mt)
      +{
      +	return mt->max;
      +}
      +
     -+uint64_t merged_min_update_index(struct merged_table *mt)
     ++uint64_t
     ++reftable_merged_table_min_update_index(struct reftable_merged_table *mt)
      +{
      +	return mt->min;
      +}
      +
     -+static int merged_table_seek_record(struct merged_table *mt,
     -+				    struct iterator *it, struct record rec)
     ++static int merged_table_seek_record(struct reftable_merged_table *mt,
     ++				    struct reftable_iterator *it,
     ++				    struct record rec)
      +{
     -+	struct iterator *iters = calloc(sizeof(struct iterator), mt->stack_len);
     ++	struct reftable_iterator *iters = reftable_calloc(
     ++		sizeof(struct reftable_iterator) * mt->stack_len);
      +	struct merged_iter merged = {
      +		.stack = iters,
      +		.typ = record_type(rec),
     @@ -1602,9 +1675,9 @@
      +	if (err < 0) {
      +		int i = 0;
      +		for (i = 0; i < n; i++) {
     -+			iterator_destroy(&iters[i]);
     ++			reftable_iterator_destroy(&iters[i]);
      +		}
     -+		free(iters);
     ++		reftable_free(iters);
      +		return err;
      +	}
      +
     @@ -1615,17 +1688,19 @@
      +	}
      +
      +	{
     -+		struct merged_iter *p = malloc(sizeof(struct merged_iter));
     ++		struct merged_iter *p =
     ++			reftable_malloc(sizeof(struct merged_iter));
      +		*p = merged;
      +		iterator_from_merged_iter(it, p);
      +	}
      +	return 0;
      +}
      +
     -+int merged_table_seek_ref(struct merged_table *mt, struct iterator *it,
     -+			  const char *name)
     ++int reftable_merged_table_seek_ref(struct reftable_merged_table *mt,
     ++				   struct reftable_iterator *it,
     ++				   const char *name)
      +{
     -+	struct ref_record ref = {
     ++	struct reftable_ref_record ref = {
      +		.ref_name = (char *)name,
      +	};
      +	struct record rec = { 0 };
     @@ -1633,10 +1708,11 @@
      +	return merged_table_seek_record(mt, it, rec);
      +}
      +
     -+int merged_table_seek_log_at(struct merged_table *mt, struct iterator *it,
     -+			     const char *name, uint64_t update_index)
     ++int reftable_merged_table_seek_log_at(struct reftable_merged_table *mt,
     ++				      struct reftable_iterator *it,
     ++				      const char *name, uint64_t update_index)
      +{
     -+	struct log_record log = {
     ++	struct reftable_log_record log = {
      +		.ref_name = (char *)name,
      +		.update_index = update_index,
      +	};
     @@ -1645,11 +1721,12 @@
      +	return merged_table_seek_record(mt, it, rec);
      +}
      +
     -+int merged_table_seek_log(struct merged_table *mt, struct iterator *it,
     -+			  const char *name)
     ++int reftable_merged_table_seek_log(struct reftable_merged_table *mt,
     ++				   struct reftable_iterator *it,
     ++				   const char *name)
      +{
      +	uint64_t max = ~((uint64_t)0);
     -+	return merged_table_seek_log_at(mt, it, name, max);
     ++	return reftable_merged_table_seek_log_at(mt, it, name, max);
      +}
      
       diff --git a/reftable/merged.h b/reftable/merged.h
     @@ -1671,8 +1748,8 @@
      +#include "pq.h"
      +#include "reftable.h"
      +
     -+struct merged_table {
     -+	struct reader **stack;
     ++struct reftable_merged_table {
     ++	struct reftable_reader **stack;
      +	int stack_len;
      +	uint32_t hash_id;
      +
     @@ -1681,14 +1758,14 @@
      +};
      +
      +struct merged_iter {
     -+	struct iterator *stack;
     ++	struct reftable_iterator *stack;
      +	uint32_t hash_id;
      +	int stack_len;
      +	byte typ;
      +	struct merged_iter_pqueue pq;
     -+} merged_iter;
     ++};
      +
     -+void merged_table_clear(struct merged_table *mt);
     ++void merged_table_clear(struct reftable_merged_table *mt);
      +
      +#endif
      
     @@ -1719,8 +1796,8 @@
      +
      +	cmp = slice_compare(ak, bk);
      +
     -+	free(slice_yield(&ak));
     -+	free(slice_yield(&bk));
     ++	reftable_free(slice_yield(&ak));
     ++	reftable_free(slice_yield(&bk));
      +
      +	if (cmp == 0) {
      +		return a.index > b.index;
     @@ -1784,7 +1861,8 @@
      +	int i = 0;
      +	if (pq->len == pq->cap) {
      +		pq->cap = 2 * pq->cap + 1;
     -+		pq->heap = realloc(pq->heap, pq->cap * sizeof(struct pq_entry));
     ++		pq->heap = reftable_realloc(pq->heap,
     ++					    pq->cap * sizeof(struct pq_entry));
      +	}
      +
      +	pq->heap[pq->len++] = e;
     @@ -1806,7 +1884,7 @@
      +	int i = 0;
      +	for (i = 0; i < pq->len; i++) {
      +		record_clear(pq->heap[i].rec);
     -+		free(record_yield(&pq->heap[i].rec));
     ++		reftable_free(record_yield(&pq->heap[i].rec));
      +	}
      +	FREE_AND_NULL(pq->heap);
      +	pq->len = pq->cap = 0;
     @@ -1876,20 +1954,22 @@
      +#include "reftable.h"
      +#include "tree.h"
      +
     -+uint64_t block_source_size(struct block_source source)
     ++uint64_t block_source_size(struct reftable_block_source source)
      +{
      +	return source.ops->size(source.arg);
      +}
      +
     -+int block_source_read_block(struct block_source source, struct block *dest,
     -+			    uint64_t off, uint32_t size)
     ++int block_source_read_block(struct reftable_block_source source,
     ++			    struct reftable_block *dest, uint64_t off,
     ++			    uint32_t size)
      +{
      +	int result = source.ops->read_block(source.arg, dest, off, size);
      +	dest->source = source;
      +	return result;
      +}
      +
     -+void block_source_return_block(struct block_source source, struct block *blockp)
     ++void block_source_return_block(struct reftable_block_source source,
     ++			       struct reftable_block *blockp)
      +{
      +	source.ops->return_block(source.arg, blockp);
      +	blockp->data = NULL;
     @@ -1898,7 +1978,7 @@
      +	blockp->source.arg = NULL;
      +}
      +
     -+void block_source_close(struct block_source *source)
     ++void block_source_close(struct reftable_block_source *source)
      +{
      +	if (source->ops == NULL) {
      +		return;
     @@ -1908,7 +1988,8 @@
      +	source->ops = NULL;
      +}
      +
     -+static struct reader_offsets *reader_offsets_for(struct reader *r, byte typ)
     ++static struct reftable_reader_offsets *
     ++reader_offsets_for(struct reftable_reader *r, byte typ)
      +{
      +	switch (typ) {
      +	case BLOCK_TYPE_REF:
     @@ -1921,7 +2002,8 @@
      +	abort();
      +}
      +
     -+static int reader_get_block(struct reader *r, struct block *dest, uint64_t off,
     ++static int reader_get_block(struct reftable_reader *r,
     ++			    struct reftable_block *dest, uint64_t off,
      +			    uint32_t sz)
      +{
      +	if (off >= r->size) {
     @@ -1935,22 +2017,22 @@
      +	return block_source_read_block(r->source, dest, off, sz);
      +}
      +
     -+void reader_return_block(struct reader *r, struct block *p)
     ++void reader_return_block(struct reftable_reader *r, struct reftable_block *p)
      +{
      +	block_source_return_block(r->source, p);
      +}
      +
     -+uint32_t reader_hash_id(struct reader *r)
     ++uint32_t reftable_reader_hash_id(struct reftable_reader *r)
      +{
      +	return r->hash_id;
      +}
      +
     -+const char *reader_name(struct reader *r)
     ++const char *reader_name(struct reftable_reader *r)
      +{
      +	return r->name;
      +}
      +
     -+static int parse_footer(struct reader *r, byte *footer, byte *header)
     ++static int parse_footer(struct reftable_reader *r, byte *footer, byte *header)
      +{
      +	byte *f = footer;
      +	int err = 0;
     @@ -1960,25 +2042,12 @@
      +	}
      +	f += 4;
      +
     -+	if (memcmp(footer, header, HEADER_SIZE)) {
     ++	if (memcmp(footer, header, header_size(r->version))) {
      +		err = FORMAT_ERROR;
      +		goto exit;
      +	}
      +
     -+	r->hash_id = SHA1_ID;
     -+	{
     -+		byte version = *f++;
     -+		if (version == 2) {
     -+			/* DO NOT SUBMIT.  Not yet in the standard. */
     -+			r->hash_id = SHA256_ID;
     -+			version = 1;
     -+		}
     -+		if (version != 1) {
     -+			err = FORMAT_ERROR;
     -+			goto exit;
     -+		}
     -+	}
     -+
     ++	f++;
      +	r->block_size = get_be24(f);
      +
      +	f += 3;
     @@ -1987,6 +2056,22 @@
      +	r->max_update_index = get_be64(f);
      +	f += 8;
      +
     ++	if (r->version == 1) {
     ++		r->hash_id = SHA1_ID;
     ++	} else {
     ++		r->hash_id = get_be32(f);
     ++		switch (r->hash_id) {
     ++		case SHA1_ID:
     ++			break;
     ++		case SHA256_ID:
     ++			break;
     ++		default:
     ++			err = FORMAT_ERROR;
     ++			goto exit;
     ++		}
     ++		f += 4;
     ++	}
     ++
      +	r->ref_offsets.index_offset = get_be64(f);
      +	f += 8;
      +
     @@ -2014,7 +2099,7 @@
      +	}
      +
      +	{
     -+		byte first_block_typ = header[HEADER_SIZE];
     ++		byte first_block_typ = header[header_size(r->version)];
      +		r->ref_offsets.present = (first_block_typ == BLOCK_TYPE_REF);
      +		r->ref_offsets.offset = 0;
      +		r->log_offsets.present = (first_block_typ == BLOCK_TYPE_LOG ||
     @@ -2026,27 +2111,40 @@
      +	return err;
      +}
      +
     -+int init_reader(struct reader *r, struct block_source source, const char *name)
     ++int init_reader(struct reftable_reader *r, struct reftable_block_source source,
     ++		const char *name)
      +{
     -+	struct block footer = { 0 };
     -+	struct block header = { 0 };
     ++	struct reftable_block footer = { 0 };
     ++	struct reftable_block header = { 0 };
      +	int err = 0;
      +
     -+	memset(r, 0, sizeof(struct reader));
     -+	r->size = block_source_size(source) - FOOTER_SIZE;
     -+	r->source = source;
     -+	r->name = xstrdup(name);
     -+	r->hash_id = 0;
     ++	memset(r, 0, sizeof(struct reftable_reader));
      +
     -+	err = block_source_read_block(source, &footer, r->size, FOOTER_SIZE);
     -+	if (err != FOOTER_SIZE) {
     ++	/* Need +1 to read type of first block. */
     ++	err = block_source_read_block(source, &header, 0, header_size(2) + 1);
     ++	if (err != header_size(2) + 1) {
      +		err = IO_ERROR;
      +		goto exit;
      +	}
      +
     -+	/* Need +1 to read type of first block. */
     -+	err = reader_get_block(r, &header, 0, HEADER_SIZE + 1);
     -+	if (err != HEADER_SIZE + 1) {
     ++	if (memcmp(header.data, "REFT", 4)) {
     ++		err = FORMAT_ERROR;
     ++		goto exit;
     ++	}
     ++	r->version = header.data[4];
     ++	if (r->version != 1 && r->version != 2) {
     ++		err = FORMAT_ERROR;
     ++		goto exit;
     ++	}
     ++
     ++	r->size = block_source_size(source) - footer_size(r->version);
     ++	r->source = source;
     ++	r->name = xstrdup(name);
     ++	r->hash_id = 0;
     ++
     ++	err = block_source_read_block(source, &footer, r->size,
     ++				      footer_size(r->version));
     ++	if (err != footer_size(r->version)) {
      +		err = IO_ERROR;
      +		goto exit;
      +	}
     @@ -2059,10 +2157,10 @@
      +}
      +
      +struct table_iter {
     -+	struct reader *r;
     ++	struct reftable_reader *r;
      +	byte typ;
      +	uint64_t block_off;
     -+	struct block_iter bi;
     ++	struct reftable_block_iter bi;
      +	bool finished;
      +};
      +
     @@ -2080,7 +2178,7 @@
      +{
      +	int res = block_iter_next(&ti->bi, rec);
      +	if (res == 0 && record_type(rec) == BLOCK_TYPE_REF) {
     -+		((struct ref_record *)rec.data)->update_index +=
     ++		((struct reftable_ref_record *)rec.data)->update_index +=
      +			ti->r->min_update_index;
      +	}
      +
     @@ -2099,12 +2197,13 @@
      +	ti->bi.next_off = 0;
      +}
      +
     -+static int32_t extract_block_size(byte *data, byte *typ, uint64_t off)
     ++static int32_t extract_block_size(byte *data, byte *typ, uint64_t off,
     ++				  int version)
      +{
      +	int32_t result = 0;
      +
      +	if (off == 0) {
     -+		data += 24;
     ++		data += header_size(version);
      +	}
      +
      +	*typ = data[0];
     @@ -2114,15 +2213,16 @@
      +	return result;
      +}
      +
     -+int reader_init_block_reader(struct reader *r, struct block_reader *br,
     ++int reader_init_block_reader(struct reftable_reader *r,
     ++			     struct reftable_block_reader *br,
      +			     uint64_t next_off, byte want_typ)
      +{
      +	int32_t guess_block_size = r->block_size ? r->block_size :
      +						   DEFAULT_BLOCK_SIZE;
     -+	struct block block = { 0 };
     ++	struct reftable_block block = { 0 };
      +	byte block_typ = 0;
      +	int err = 0;
     -+	uint32_t header_off = next_off ? 0 : HEADER_SIZE;
     ++	uint32_t header_off = next_off ? 0 : header_size(r->version);
      +	int32_t block_size = 0;
      +
      +	if (next_off >= r->size) {
     @@ -2134,7 +2234,8 @@
      +		return err;
      +	}
      +
     -+	block_size = extract_block_size(block.data, &block_typ, next_off);
     ++	block_size = extract_block_size(block.data, &block_typ, next_off,
     ++					r->version);
      +	if (block_size < 0) {
      +		return block_size;
      +	}
     @@ -2160,7 +2261,7 @@
      +				 struct table_iter *src)
      +{
      +	uint64_t next_block_off = src->block_off + src->bi.br->full_block_size;
     -+	struct block_reader br = { 0 };
     ++	struct reftable_block_reader br = { 0 };
      +	int err = 0;
      +
      +	dest->r = src->r;
     @@ -2177,7 +2278,8 @@
      +	}
      +
      +	{
     -+		struct block_reader *brp = malloc(sizeof(struct block_reader));
     ++		struct reftable_block_reader *brp =
     ++			reftable_malloc(sizeof(struct reftable_block_reader));
      +		*brp = br;
      +
      +		dest->finished = false;
     @@ -2229,29 +2331,30 @@
      +	block_iter_close(&ti->bi);
      +}
      +
     -+struct iterator_vtable table_iter_vtable = {
     ++struct reftable_iterator_vtable table_iter_vtable = {
      +	.next = &table_iter_next_void,
      +	.close = &table_iter_close,
      +};
      +
     -+static void iterator_from_table_iter(struct iterator *it, struct table_iter *ti)
     ++static void iterator_from_table_iter(struct reftable_iterator *it,
     ++				     struct table_iter *ti)
      +{
      +	it->iter_arg = ti;
      +	it->ops = &table_iter_vtable;
      +}
      +
     -+static int reader_table_iter_at(struct reader *r, struct table_iter *ti,
     -+				uint64_t off, byte typ)
     ++static int reader_table_iter_at(struct reftable_reader *r,
     ++				struct table_iter *ti, uint64_t off, byte typ)
      +{
     -+	struct block_reader br = { 0 };
     -+	struct block_reader *brp = NULL;
     ++	struct reftable_block_reader br = { 0 };
     ++	struct reftable_block_reader *brp = NULL;
      +
      +	int err = reader_init_block_reader(r, &br, off, typ);
      +	if (err != 0) {
      +		return err;
      +	}
      +
     -+	brp = malloc(sizeof(struct block_reader));
     ++	brp = reftable_malloc(sizeof(struct reftable_block_reader));
      +	*brp = br;
      +	ti->r = r;
      +	ti->typ = block_reader_type(brp);
     @@ -2260,10 +2363,10 @@
      +	return 0;
      +}
      +
     -+static int reader_start(struct reader *r, struct table_iter *ti, byte typ,
     -+			bool index)
     ++static int reader_start(struct reftable_reader *r, struct table_iter *ti,
     ++			byte typ, bool index)
      +{
     -+	struct reader_offsets *offs = reader_offsets_for(r, typ);
     ++	struct reftable_reader_offsets *offs = reader_offsets_for(r, typ);
      +	uint64_t off = offs->offset;
      +	if (index) {
      +		off = offs->index_offset;
     @@ -2276,7 +2379,7 @@
      +	return reader_table_iter_at(r, ti, off, typ);
      +}
      +
     -+static int reader_seek_linear(struct reader *r, struct table_iter *ti,
     ++static int reader_seek_linear(struct reftable_reader *r, struct table_iter *ti,
      +			      struct record want)
      +{
      +	struct record rec = new_record(record_type(want));
     @@ -2321,14 +2424,14 @@
      +exit:
      +	block_iter_close(&next.bi);
      +	record_clear(rec);
     -+	free(record_yield(&rec));
     -+	free(slice_yield(&want_key));
     -+	free(slice_yield(&got_key));
     ++	reftable_free(record_yield(&rec));
     ++	reftable_free(slice_yield(&want_key));
     ++	reftable_free(slice_yield(&got_key));
      +	return err;
      +}
      +
     -+static int reader_seek_indexed(struct reader *r, struct iterator *it,
     -+			       struct record rec)
     ++static int reader_seek_indexed(struct reftable_reader *r,
     ++			       struct reftable_iterator *it, struct record rec)
      +{
      +	struct index_record want_index = { 0 };
      +	struct record want_index_rec = { 0 };
     @@ -2380,7 +2483,7 @@
      +
      +	if (err == 0) {
      +		struct table_iter *malloced =
     -+			calloc(sizeof(struct table_iter), 1);
     ++			reftable_calloc(sizeof(struct table_iter));
      +		table_iter_copy_from(malloced, &next);
      +		iterator_from_table_iter(it, malloced);
      +	}
     @@ -2392,10 +2495,11 @@
      +	return err;
      +}
      +
     -+static int reader_seek_internal(struct reader *r, struct iterator *it,
     -+				struct record rec)
     ++static int reader_seek_internal(struct reftable_reader *r,
     ++				struct reftable_iterator *it, struct record rec)
      +{
     -+	struct reader_offsets *offs = reader_offsets_for(r, record_type(rec));
     ++	struct reftable_reader_offsets *offs =
     ++		reader_offsets_for(r, record_type(rec));
      +	uint64_t idx = offs->index_offset;
      +	struct table_iter ti = { 0 };
      +	int err = 0;
     @@ -2413,7 +2517,8 @@
      +	}
      +
      +	{
     -+		struct table_iter *p = malloc(sizeof(struct table_iter));
     ++		struct table_iter *p =
     ++			reftable_malloc(sizeof(struct table_iter));
      +		*p = ti;
      +		iterator_from_table_iter(it, p);
      +	}
     @@ -2421,11 +2526,12 @@
      +	return 0;
      +}
      +
     -+int reader_seek(struct reader *r, struct iterator *it, struct record rec)
     ++int reader_seek(struct reftable_reader *r, struct reftable_iterator *it,
     ++		struct record rec)
      +{
      +	byte typ = record_type(rec);
      +
     -+	struct reader_offsets *offs = reader_offsets_for(r, typ);
     ++	struct reftable_reader_offsets *offs = reader_offsets_for(r, typ);
      +	if (!offs->present) {
      +		iterator_set_empty(it);
      +		return 0;
     @@ -2434,9 +2540,10 @@
      +	return reader_seek_internal(r, it, rec);
      +}
      +
     -+int reader_seek_ref(struct reader *r, struct iterator *it, const char *name)
     ++int reftable_reader_seek_ref(struct reftable_reader *r,
     ++			     struct reftable_iterator *it, const char *name)
      +{
     -+	struct ref_record ref = {
     ++	struct reftable_ref_record ref = {
      +		.ref_name = (char *)name,
      +	};
      +	struct record rec = { 0 };
     @@ -2444,10 +2551,11 @@
      +	return reader_seek(r, it, rec);
      +}
      +
     -+int reader_seek_log_at(struct reader *r, struct iterator *it, const char *name,
     -+		       uint64_t update_index)
     ++int reftable_reader_seek_log_at(struct reftable_reader *r,
     ++				struct reftable_iterator *it, const char *name,
     ++				uint64_t update_index)
      +{
     -+	struct log_record log = {
     ++	struct reftable_log_record log = {
      +		.ref_name = (char *)name,
      +		.update_index = update_index,
      +	};
     @@ -2456,45 +2564,49 @@
      +	return reader_seek(r, it, rec);
      +}
      +
     -+int reader_seek_log(struct reader *r, struct iterator *it, const char *name)
     ++int reftable_reader_seek_log(struct reftable_reader *r,
     ++			     struct reftable_iterator *it, const char *name)
      +{
      +	uint64_t max = ~((uint64_t)0);
     -+	return reader_seek_log_at(r, it, name, max);
     ++	return reftable_reader_seek_log_at(r, it, name, max);
      +}
      +
     -+void reader_close(struct reader *r)
     ++void reader_close(struct reftable_reader *r)
      +{
      +	block_source_close(&r->source);
      +	FREE_AND_NULL(r->name);
      +}
      +
     -+int new_reader(struct reader **p, struct block_source src, char const *name)
     ++int reftable_new_reader(struct reftable_reader **p,
     ++			struct reftable_block_source src, char const *name)
      +{
     -+	struct reader *rd = calloc(sizeof(struct reader), 1);
     ++	struct reftable_reader *rd =
     ++		reftable_calloc(sizeof(struct reftable_reader));
      +	int err = init_reader(rd, src, name);
      +	if (err == 0) {
      +		*p = rd;
      +	} else {
     -+		free(rd);
     ++		reftable_free(rd);
      +	}
      +	return err;
      +}
      +
     -+void reader_free(struct reader *r)
     ++void reftable_reader_free(struct reftable_reader *r)
      +{
      +	reader_close(r);
     -+	free(r);
     ++	reftable_free(r);
      +}
      +
     -+static int reader_refs_for_indexed(struct reader *r, struct iterator *it,
     -+				   byte *oid)
     ++static int reftable_reader_refs_for_indexed(struct reftable_reader *r,
     ++					    struct reftable_iterator *it,
     ++					    byte *oid)
      +{
      +	struct obj_record want = {
      +		.hash_prefix = oid,
      +		.hash_prefix_len = r->object_id_len,
      +	};
      +	struct record want_rec = { 0 };
     -+	struct iterator oit = { 0 };
     ++	struct reftable_iterator oit = { 0 };
      +	struct obj_record got = { 0 };
      +	struct record got_rec = { 0 };
      +	int err = 0;
     @@ -2508,7 +2620,7 @@
      +
      +	record_from_obj(&got_rec, &got);
      +	err = iterator_next(oit, got_rec);
     -+	iterator_destroy(&oit);
     ++	reftable_iterator_destroy(&oit);
      +	if (err < 0) {
      +		return err;
      +	}
     @@ -2537,18 +2649,19 @@
      +	return 0;
      +}
      +
     -+static int reader_refs_for_unindexed(struct reader *r, struct iterator *it,
     -+				     byte *oid, int oid_len)
     ++static int reftable_reader_refs_for_unindexed(struct reftable_reader *r,
     ++					      struct reftable_iterator *it,
     ++					      byte *oid, int oid_len)
      +{
     -+	struct table_iter *ti = calloc(sizeof(struct table_iter), 1);
     ++	struct table_iter *ti = reftable_calloc(sizeof(struct table_iter));
      +	struct filtering_ref_iterator *filter = NULL;
      +	int err = reader_start(r, ti, BLOCK_TYPE_REF, false);
      +	if (err < 0) {
     -+		free(ti);
     ++		reftable_free(ti);
      +		return err;
      +	}
      +
     -+	filter = calloc(sizeof(struct filtering_ref_iterator), 1);
     ++	filter = reftable_calloc(sizeof(struct filtering_ref_iterator));
      +	slice_resize(&filter->oid, oid_len);
      +	memcpy(filter->oid.buf, oid, oid_len);
      +	filter->r = r;
     @@ -2559,21 +2672,22 @@
      +	return 0;
      +}
      +
     -+int reader_refs_for(struct reader *r, struct iterator *it, byte *oid,
     -+		    int oid_len)
     ++int reftable_reader_refs_for(struct reftable_reader *r,
     ++			     struct reftable_iterator *it, byte *oid,
     ++			     int oid_len)
      +{
      +	if (r->obj_offsets.present) {
     -+		return reader_refs_for_indexed(r, it, oid);
     ++		return reftable_reader_refs_for_indexed(r, it, oid);
      +	}
     -+	return reader_refs_for_unindexed(r, it, oid, oid_len);
     ++	return reftable_reader_refs_for_unindexed(r, it, oid, oid_len);
      +}
      +
     -+uint64_t reader_max_update_index(struct reader *r)
     ++uint64_t reftable_reader_max_update_index(struct reftable_reader *r)
      +{
      +	return r->max_update_index;
      +}
      +
     -+uint64_t reader_min_update_index(struct reader *r)
     ++uint64_t reftable_reader_min_update_index(struct reftable_reader *r)
      +{
      +	return r->min_update_index;
      +}
     @@ -2598,40 +2712,48 @@
      +#include "record.h"
      +#include "reftable.h"
      +
     -+uint64_t block_source_size(struct block_source source);
     ++uint64_t block_source_size(struct reftable_block_source source);
      +
     -+int block_source_read_block(struct block_source source, struct block *dest,
     -+			    uint64_t off, uint32_t size);
     -+void block_source_return_block(struct block_source source, struct block *ret);
     -+void block_source_close(struct block_source *source);
     ++int block_source_read_block(struct reftable_block_source source,
     ++			    struct reftable_block *dest, uint64_t off,
     ++			    uint32_t size);
     ++void block_source_return_block(struct reftable_block_source source,
     ++			       struct reftable_block *ret);
     ++void block_source_close(struct reftable_block_source *source);
      +
     -+struct reader_offsets {
     ++struct reftable_reader_offsets {
      +	bool present;
      +	uint64_t offset;
      +	uint64_t index_offset;
      +};
      +
     -+struct reader {
     ++struct reftable_reader {
      +	char *name;
     -+	struct block_source source;
     ++	struct reftable_block_source source;
      +	uint32_t hash_id;
     ++
     ++	// Size of the file, excluding the footer.
      +	uint64_t size;
      +	uint32_t block_size;
      +	uint64_t min_update_index;
      +	uint64_t max_update_index;
      +	int object_id_len;
     ++	int version;
      +
     -+	struct reader_offsets ref_offsets;
     -+	struct reader_offsets obj_offsets;
     -+	struct reader_offsets log_offsets;
     ++	struct reftable_reader_offsets ref_offsets;
     ++	struct reftable_reader_offsets obj_offsets;
     ++	struct reftable_reader_offsets log_offsets;
      +};
      +
     -+int init_reader(struct reader *r, struct block_source source, const char *name);
     -+int reader_seek(struct reader *r, struct iterator *it, struct record rec);
     -+void reader_close(struct reader *r);
     -+const char *reader_name(struct reader *r);
     -+void reader_return_block(struct reader *r, struct block *p);
     -+int reader_init_block_reader(struct reader *r, struct block_reader *br,
     ++int init_reader(struct reftable_reader *r, struct reftable_block_source source,
     ++		const char *name);
     ++int reader_seek(struct reftable_reader *r, struct reftable_iterator *it,
     ++		struct record rec);
     ++void reader_close(struct reftable_reader *r);
     ++const char *reader_name(struct reftable_reader *r);
     ++void reader_return_block(struct reftable_reader *r, struct reftable_block *p);
     ++int reader_init_block_reader(struct reftable_reader *r,
     ++			     struct reftable_block_reader *br,
      +			     uint64_t next_off, byte want_typ);
      +
      +#endif
     @@ -2649,6 +2771,8 @@
      +https://developers.google.com/open-source/licenses/bsd
      +*/
      +
     ++/* record.c - methods for different types of records. */
     ++
      +#include "record.h"
      +
      +#include "system.h"
     @@ -2656,18 +2780,6 @@
      +#include "constants.h"
      +#include "reftable.h"
      +
     -+int is_block_type(byte typ)
     -+{
     -+	switch (typ) {
     -+	case BLOCK_TYPE_REF:
     -+	case BLOCK_TYPE_LOG:
     -+	case BLOCK_TYPE_OBJ:
     -+	case BLOCK_TYPE_INDEX:
     -+		return true;
     -+	}
     -+	return false;
     -+}
     -+
      +int get_var_int(uint64_t *dest, struct slice in)
      +{
      +	int ptr = 0;
     @@ -2716,17 +2828,16 @@
      +	}
      +}
      +
     -+int common_prefix_size(struct slice a, struct slice b)
     ++int is_block_type(byte typ)
      +{
     -+	int p = 0;
     -+	while (p < a.len && p < b.len) {
     -+		if (a.buf[p] != b.buf[p]) {
     -+			break;
     -+		}
     -+		p++;
     ++	switch (typ) {
     ++	case BLOCK_TYPE_REF:
     ++	case BLOCK_TYPE_LOG:
     ++	case BLOCK_TYPE_OBJ:
     ++	case BLOCK_TYPE_INDEX:
     ++		return true;
      +	}
     -+
     -+	return p;
     ++	return false;
      +}
      +
      +static int decode_string(struct slice *dest, struct slice in)
     @@ -2737,8 +2848,7 @@
      +	if (n <= 0) {
      +		return -1;
      +	}
     -+	in.buf += n;
     -+	in.len -= n;
     ++	slice_consume(&in, n);
      +	if (in.len < tsize) {
      +		return -1;
      +	}
     @@ -2746,12 +2856,29 @@
      +	slice_resize(dest, tsize + 1);
      +	dest->buf[tsize] = 0;
      +	memcpy(dest->buf, in.buf, tsize);
     -+	in.buf += tsize;
     -+	in.len -= tsize;
     ++	slice_consume(&in, tsize);
      +
      +	return start_len - in.len;
      +}
      +
     ++static int encode_string(char *str, struct slice s)
     ++{
     ++	struct slice start = s;
     ++	int l = strlen(str);
     ++	int n = put_var_int(s, l);
     ++	if (n < 0) {
     ++		return -1;
     ++	}
     ++	slice_consume(&s, n);
     ++	if (s.len < l) {
     ++		return -1;
     ++	}
     ++	memcpy(s.buf, str, l);
     ++	slice_consume(&s, l);
     ++
     ++	return start.len - s.len;
     ++}
     ++
      +int encode_key(bool *restart, struct slice dest, struct slice prev_key,
      +	       struct slice key, byte extra)
      +{
     @@ -2762,8 +2889,7 @@
      +	if (n < 0) {
      +		return -1;
      +	}
     -+	dest.buf += n;
     -+	dest.len -= n;
     ++	slice_consume(&dest, n);
      +
      +	*restart = (prefix_len == 0);
      +
     @@ -2771,39 +2897,77 @@
      +	if (n < 0) {
      +		return -1;
      +	}
     -+	dest.buf += n;
     -+	dest.len -= n;
     ++	slice_consume(&dest, n);
      +
      +	if (dest.len < suffix_len) {
      +		return -1;
      +	}
      +	memcpy(dest.buf, key.buf + prefix_len, suffix_len);
     -+	dest.buf += suffix_len;
     -+	dest.len -= suffix_len;
     ++	slice_consume(&dest, suffix_len);
      +
      +	return start.len - dest.len;
      +}
      +
     -+static byte ref_record_type(void)
     ++int decode_key(struct slice *key, byte *extra, struct slice last_key,
     ++	       struct slice in)
     ++{
     ++	int start_len = in.len;
     ++	uint64_t prefix_len = 0;
     ++	uint64_t suffix_len = 0;
     ++	int n = get_var_int(&prefix_len, in);
     ++	if (n < 0) {
     ++		return -1;
     ++	}
     ++	slice_consume(&in, n);
     ++
     ++	if (prefix_len > last_key.len) {
     ++		return -1;
     ++	}
     ++
     ++	n = get_var_int(&suffix_len, in);
     ++	if (n <= 0) {
     ++		return -1;
     ++	}
     ++	slice_consume(&in, n);
     ++
     ++	*extra = (byte)(suffix_len & 0x7);
     ++	suffix_len >>= 3;
     ++
     ++	if (in.len < suffix_len) {
     ++		return -1;
     ++	}
     ++
     ++	slice_resize(key, suffix_len + prefix_len);
     ++	memcpy(key->buf, last_key.buf, prefix_len);
     ++
     ++	memcpy(key->buf + prefix_len, in.buf, suffix_len);
     ++	slice_consume(&in, suffix_len);
     ++
     ++	return start_len - in.len;
     ++}
     ++
     ++static byte reftable_ref_record_type(void)
      +{
      +	return BLOCK_TYPE_REF;
      +}
      +
     -+static void ref_record_key(const void *r, struct slice *dest)
     ++static void reftable_ref_record_key(const void *r, struct slice *dest)
      +{
     -+	const struct ref_record *rec = (const struct ref_record *)r;
     ++	const struct reftable_ref_record *rec =
     ++		(const struct reftable_ref_record *)r;
      +	slice_set_string(dest, rec->ref_name);
      +}
      +
     -+static void ref_record_copy_from(void *rec, const void *src_rec, int hash_size)
     ++static void reftable_ref_record_copy_from(void *rec, const void *src_rec,
     ++					  int hash_size)
      +{
     -+	struct ref_record *ref = (struct ref_record *)rec;
     -+	struct ref_record *src = (struct ref_record *)src_rec;
     ++	struct reftable_ref_record *ref = (struct reftable_ref_record *)rec;
     ++	struct reftable_ref_record *src = (struct reftable_ref_record *)src_rec;
      +	assert(hash_size > 0);
      +
      +	/* This is simple and correct, but we could probably reuse the hash
      +	   fields. */
     -+	ref_record_clear(ref);
     ++	reftable_ref_record_clear(ref);
      +	if (src->ref_name != NULL) {
      +		ref->ref_name = xstrdup(src->ref_name);
      +	}
     @@ -2813,12 +2977,12 @@
      +	}
      +
      +	if (src->target_value != NULL) {
     -+		ref->target_value = malloc(hash_size);
     ++		ref->target_value = reftable_malloc(hash_size);
      +		memcpy(ref->target_value, src->target_value, hash_size);
      +	}
      +
      +	if (src->value != NULL) {
     -+		ref->value = malloc(hash_size);
     ++		ref->value = reftable_malloc(hash_size);
      +		memcpy(ref->value, src->value, hash_size);
      +	}
      +	ref->update_index = src->update_index;
     @@ -2845,7 +3009,7 @@
      +	}
      +}
      +
     -+void ref_record_print(struct ref_record *ref, int hash_size)
     ++void reftable_ref_record_print(struct reftable_ref_record *ref, int hash_size)
      +{
      +	char hex[SHA256_SIZE + 1] = { 0 };
      +
     @@ -2864,23 +3028,24 @@
      +	printf("}\n");
      +}
      +
     -+static void ref_record_clear_void(void *rec)
     ++static void reftable_ref_record_clear_void(void *rec)
      +{
     -+	ref_record_clear((struct ref_record *)rec);
     ++	reftable_ref_record_clear((struct reftable_ref_record *)rec);
      +}
      +
     -+void ref_record_clear(struct ref_record *ref)
     ++void reftable_ref_record_clear(struct reftable_ref_record *ref)
      +{
     -+	free(ref->ref_name);
     -+	free(ref->target);
     -+	free(ref->target_value);
     -+	free(ref->value);
     -+	memset(ref, 0, sizeof(struct ref_record));
     ++	reftable_free(ref->ref_name);
     ++	reftable_free(ref->target);
     ++	reftable_free(ref->target_value);
     ++	reftable_free(ref->value);
     ++	memset(ref, 0, sizeof(struct reftable_ref_record));
      +}
      +
     -+static byte ref_record_val_type(const void *rec)
     ++static byte reftable_ref_record_val_type(const void *rec)
      +{
     -+	const struct ref_record *r = (const struct ref_record *)rec;
     ++	const struct reftable_ref_record *r =
     ++		(const struct reftable_ref_record *)rec;
      +	if (r->value != NULL) {
      +		if (r->target_value != NULL) {
      +			return 2;
     @@ -2893,45 +3058,25 @@
      +	return 0;
      +}
      +
     -+static int encode_string(char *str, struct slice s)
     -+{
     -+	struct slice start = s;
     -+	int l = strlen(str);
     -+	int n = put_var_int(s, l);
     -+	if (n < 0) {
     -+		return -1;
     -+	}
     -+	s.buf += n;
     -+	s.len -= n;
     -+	if (s.len < l) {
     -+		return -1;
     -+	}
     -+	memcpy(s.buf, str, l);
     -+	s.buf += l;
     -+	s.len -= l;
     -+
     -+	return start.len - s.len;
     -+}
     -+
     -+static int ref_record_encode(const void *rec, struct slice s, int hash_size)
     ++static int reftable_ref_record_encode(const void *rec, struct slice s,
     ++				      int hash_size)
      +{
     -+	const struct ref_record *r = (const struct ref_record *)rec;
     ++	const struct reftable_ref_record *r =
     ++		(const struct reftable_ref_record *)rec;
      +	struct slice start = s;
      +	int n = put_var_int(s, r->update_index);
      +	assert(hash_size > 0);
      +	if (n < 0) {
      +		return -1;
      +	}
     -+	s.buf += n;
     -+	s.len -= n;
     ++	slice_consume(&s, n);
      +
      +	if (r->value != NULL) {
      +		if (s.len < hash_size) {
      +			return -1;
      +		}
      +		memcpy(s.buf, r->value, hash_size);
     -+		s.buf += hash_size;
     -+		s.len -= hash_size;
     ++		slice_consume(&s, hash_size);
      +	}
      +
      +	if (r->target_value != NULL) {
     @@ -2939,8 +3084,7 @@
      +			return -1;
      +		}
      +		memcpy(s.buf, r->target_value, hash_size);
     -+		s.buf += hash_size;
     -+		s.len -= hash_size;
     ++		slice_consume(&s, hash_size);
      +	}
      +
      +	if (r->target != NULL) {
     @@ -2948,17 +3092,17 @@
      +		if (n < 0) {
      +			return -1;
      +		}
     -+		s.buf += n;
     -+		s.len -= n;
     ++		slice_consume(&s, n);
      +	}
      +
      +	return start.len - s.len;
      +}
      +
     -+static int ref_record_decode(void *rec, struct slice key, byte val_type,
     -+			     struct slice in, int hash_size)
     ++static int reftable_ref_record_decode(void *rec, struct slice key,
     ++				      byte val_type, struct slice in,
     ++				      int hash_size)
      +{
     -+	struct ref_record *r = (struct ref_record *)rec;
     ++	struct reftable_ref_record *r = (struct reftable_ref_record *)rec;
      +	struct slice start = in;
      +	bool seen_value = false;
      +	bool seen_target_value = false;
     @@ -2970,10 +3114,9 @@
      +	}
      +	assert(hash_size > 0);
      +
     -+	in.buf += n;
     -+	in.len -= n;
     ++	slice_consume(&in, n);
      +
     -+	r->ref_name = realloc(r->ref_name, key.len + 1);
     ++	r->ref_name = reftable_realloc(r->ref_name, key.len + 1);
      +	memcpy(r->ref_name, key.buf, key.len);
      +	r->ref_name[key.len] = 0;
      +
     @@ -2985,22 +3128,20 @@
      +		}
      +
      +		if (r->value == NULL) {
     -+			r->value = malloc(hash_size);
     ++			r->value = reftable_malloc(hash_size);
      +		}
      +		seen_value = true;
      +		memcpy(r->value, in.buf, hash_size);
     -+		in.buf += hash_size;
     -+		in.len -= hash_size;
     ++		slice_consume(&in, hash_size);
      +		if (val_type == 1) {
      +			break;
      +		}
      +		if (r->target_value == NULL) {
     -+			r->target_value = malloc(hash_size);
     ++			r->target_value = reftable_malloc(hash_size);
      +		}
      +		seen_target_value = true;
      +		memcpy(r->target_value, in.buf, hash_size);
     -+		in.buf += hash_size;
     -+		in.len -= hash_size;
     ++		slice_consume(&in, hash_size);
      +		break;
      +	case 3: {
      +		struct slice dest = { 0 };
     @@ -3008,8 +3149,7 @@
      +		if (n < 0) {
      +			return -1;
      +		}
     -+		in.buf += n;
     -+		in.len -= n;
     ++		slice_consume(&in, n);
      +		seen_target = true;
      +		r->target = (char *)slice_as_string(&dest);
      +	} break;
     @@ -3034,55 +3174,14 @@
      +	return start.len - in.len;
      +}
      +
     -+int decode_key(struct slice *key, byte *extra, struct slice last_key,
     -+	       struct slice in)
     -+{
     -+	int start_len = in.len;
     -+	uint64_t prefix_len = 0;
     -+	uint64_t suffix_len = 0;
     -+	int n = get_var_int(&prefix_len, in);
     -+	if (n < 0) {
     -+		return -1;
     -+	}
     -+	in.buf += n;
     -+	in.len -= n;
     -+
     -+	if (prefix_len > last_key.len) {
     -+		return -1;
     -+	}
     -+
     -+	n = get_var_int(&suffix_len, in);
     -+	if (n <= 0) {
     -+		return -1;
     -+	}
     -+	in.buf += n;
     -+	in.len -= n;
     -+
     -+	*extra = (byte)(suffix_len & 0x7);
     -+	suffix_len >>= 3;
     -+
     -+	if (in.len < suffix_len) {
     -+		return -1;
     -+	}
     -+
     -+	slice_resize(key, suffix_len + prefix_len);
     -+	memcpy(key->buf, last_key.buf, prefix_len);
     -+
     -+	memcpy(key->buf + prefix_len, in.buf, suffix_len);
     -+	in.buf += suffix_len;
     -+	in.len -= suffix_len;
     -+
     -+	return start_len - in.len;
     -+}
     -+
     -+struct record_vtable ref_record_vtable = {
     -+	.key = &ref_record_key,
     -+	.type = &ref_record_type,
     -+	.copy_from = &ref_record_copy_from,
     -+	.val_type = &ref_record_val_type,
     -+	.encode = &ref_record_encode,
     -+	.decode = &ref_record_decode,
     -+	.clear = &ref_record_clear_void,
     ++struct record_vtable reftable_ref_record_vtable = {
     ++	.key = &reftable_ref_record_key,
     ++	.type = &reftable_ref_record_type,
     ++	.copy_from = &reftable_ref_record_copy_from,
     ++	.val_type = &reftable_ref_record_val_type,
     ++	.encode = &reftable_ref_record_encode,
     ++	.decode = &reftable_ref_record_decode,
     ++	.clear = &reftable_ref_record_clear_void,
      +};
      +
      +static byte obj_record_type(void)
     @@ -3103,12 +3202,12 @@
      +	const struct obj_record *src = (const struct obj_record *)src_rec;
      +
      +	*ref = *src;
     -+	ref->hash_prefix = malloc(ref->hash_prefix_len);
     ++	ref->hash_prefix = reftable_malloc(ref->hash_prefix_len);
      +	memcpy(ref->hash_prefix, src->hash_prefix, ref->hash_prefix_len);
      +
      +	{
      +		int olen = ref->offset_len * sizeof(uint64_t);
     -+		ref->offsets = malloc(olen);
     ++		ref->offsets = reftable_malloc(olen);
      +		memcpy(ref->offsets, src->offsets, olen);
      +	}
      +}
     @@ -3140,8 +3239,7 @@
      +		if (n < 0) {
      +			return -1;
      +		}
     -+		s.buf += n;
     -+		s.len -= n;
     ++		slice_consume(&s, n);
      +	}
      +	if (r->offset_len == 0) {
      +		return start.len - s.len;
     @@ -3150,8 +3248,7 @@
      +	if (n < 0) {
      +		return -1;
      +	}
     -+	s.buf += n;
     -+	s.len -= n;
     ++	slice_consume(&s, n);
      +
      +	{
      +		uint64_t last = r->offsets[0];
     @@ -3161,8 +3258,7 @@
      +			if (n < 0) {
      +				return -1;
      +			}
     -+			s.buf += n;
     -+			s.len -= n;
     ++			slice_consume(&s, n);
      +			last = r->offsets[i];
      +		}
      +	}
     @@ -3176,7 +3272,7 @@
      +	struct obj_record *r = (struct obj_record *)rec;
      +	uint64_t count = val_type;
      +	int n = 0;
     -+	r->hash_prefix = malloc(key.len);
     ++	r->hash_prefix = reftable_malloc(key.len);
      +	memcpy(r->hash_prefix, key.buf, key.len);
      +	r->hash_prefix_len = key.len;
      +
     @@ -3186,8 +3282,7 @@
      +			return n;
      +		}
      +
     -+		in.buf += n;
     -+		in.len -= n;
     ++		slice_consume(&in, n);
      +	}
      +
      +	r->offsets = NULL;
     @@ -3196,16 +3291,14 @@
      +		return start.len - in.len;
      +	}
      +
     -+	r->offsets = malloc(count * sizeof(uint64_t));
     ++	r->offsets = reftable_malloc(count * sizeof(uint64_t));
      +	r->offset_len = count;
      +
      +	n = get_var_int(&r->offsets[0], in);
      +	if (n < 0) {
      +		return n;
      +	}
     -+
     -+	in.buf += n;
     -+	in.len -= n;
     ++	slice_consume(&in, n);
      +
      +	{
      +		uint64_t last = r->offsets[0];
     @@ -3216,9 +3309,7 @@
      +			if (n < 0) {
      +				return n;
      +			}
     -+
     -+			in.buf += n;
     -+			in.len -= n;
     ++			slice_consume(&in, n);
      +
      +			last = r->offsets[j] = (delta + last);
      +			j++;
     @@ -3237,7 +3328,7 @@
      +	.clear = &obj_record_clear,
      +};
      +
     -+void log_record_print(struct log_record *log, int hash_size)
     ++void reftable_log_record_print(struct reftable_log_record *log, int hash_size)
      +{
      +	char hex[SHA256_SIZE + 1] = { 0 };
      +
     @@ -3250,14 +3341,15 @@
      +	printf("%s\n\n%s\n}\n", hex, log->message);
      +}
      +
     -+static byte log_record_type(void)
     ++static byte reftable_log_record_type(void)
      +{
      +	return BLOCK_TYPE_LOG;
      +}
      +
     -+static void log_record_key(const void *r, struct slice *dest)
     ++static void reftable_log_record_key(const void *r, struct slice *dest)
      +{
     -+	const struct log_record *rec = (const struct log_record *)r;
     ++	const struct reftable_log_record *rec =
     ++		(const struct reftable_log_record *)r;
      +	int len = strlen(rec->ref_name);
      +	uint64_t ts = 0;
      +	slice_resize(dest, len + 9);
     @@ -3266,10 +3358,12 @@
      +	put_be64(dest->buf + 1 + len, ts);
      +}
      +
     -+static void log_record_copy_from(void *rec, const void *src_rec, int hash_size)
     ++static void reftable_log_record_copy_from(void *rec, const void *src_rec,
     ++					  int hash_size)
      +{
     -+	struct log_record *dst = (struct log_record *)rec;
     -+	const struct log_record *src = (const struct log_record *)src_rec;
     ++	struct reftable_log_record *dst = (struct reftable_log_record *)rec;
     ++	const struct reftable_log_record *src =
     ++		(const struct reftable_log_record *)src_rec;
      +
      +	*dst = *src;
      +	dst->ref_name = xstrdup(dst->ref_name);
     @@ -3277,46 +3371,54 @@
      +	dst->name = xstrdup(dst->name);
      +	dst->message = xstrdup(dst->message);
      +	if (dst->new_hash != NULL) {
     -+		dst->new_hash = malloc(hash_size);
     ++		dst->new_hash = reftable_malloc(hash_size);
      +		memcpy(dst->new_hash, src->new_hash, hash_size);
      +	}
      +	if (dst->old_hash != NULL) {
     -+		dst->old_hash = malloc(hash_size);
     ++		dst->old_hash = reftable_malloc(hash_size);
      +		memcpy(dst->old_hash, src->old_hash, hash_size);
      +	}
      +}
      +
     -+static void log_record_clear_void(void *rec)
     ++static void reftable_log_record_clear_void(void *rec)
      +{
     -+	struct log_record *r = (struct log_record *)rec;
     -+	log_record_clear(r);
     ++	struct reftable_log_record *r = (struct reftable_log_record *)rec;
     ++	reftable_log_record_clear(r);
      +}
      +
     -+void log_record_clear(struct log_record *r)
     ++void reftable_log_record_clear(struct reftable_log_record *r)
      +{
     -+	free(r->ref_name);
     -+	free(r->new_hash);
     -+	free(r->old_hash);
     -+	free(r->name);
     -+	free(r->email);
     -+	free(r->message);
     -+	memset(r, 0, sizeof(struct log_record));
     ++	reftable_free(r->ref_name);
     ++	reftable_free(r->new_hash);
     ++	reftable_free(r->old_hash);
     ++	reftable_free(r->name);
     ++	reftable_free(r->email);
     ++	reftable_free(r->message);
     ++	memset(r, 0, sizeof(struct reftable_log_record));
      +}
      +
     -+static byte log_record_val_type(const void *rec)
     ++static byte reftable_log_record_val_type(const void *rec)
      +{
     -+	return 1;
     ++	const struct reftable_log_record *log =
     ++		(const struct reftable_log_record *)rec;
     ++
     ++	return reftable_log_record_is_deletion(log) ? 0 : 1;
      +}
      +
      +static byte zero[SHA256_SIZE] = { 0 };
      +
     -+static int log_record_encode(const void *rec, struct slice s, int hash_size)
     ++static int reftable_log_record_encode(const void *rec, struct slice s,
     ++				      int hash_size)
      +{
     -+	struct log_record *r = (struct log_record *)rec;
     ++	struct reftable_log_record *r = (struct reftable_log_record *)rec;
      +	struct slice start = s;
      +	int n = 0;
      +	byte *oldh = r->old_hash;
      +	byte *newh = r->new_hash;
     ++	if (reftable_log_record_is_deletion(r)) {
     ++		return 0;
     ++	}
     ++
      +	if (oldh == NULL) {
      +		oldh = zero;
      +	}
     @@ -3330,53 +3432,48 @@
      +
      +	memcpy(s.buf, oldh, hash_size);
      +	memcpy(s.buf + hash_size, newh, hash_size);
     -+	s.buf += 2 * hash_size;
     -+	s.len -= 2 * hash_size;
     ++	slice_consume(&s, 2 * hash_size);
      +
      +	n = encode_string(r->name ? r->name : "", s);
      +	if (n < 0) {
      +		return -1;
      +	}
     -+	s.len -= n;
     -+	s.buf += n;
     ++	slice_consume(&s, n);
      +
      +	n = encode_string(r->email ? r->email : "", s);
      +	if (n < 0) {
      +		return -1;
      +	}
     -+	s.len -= n;
     -+	s.buf += n;
     ++	slice_consume(&s, n);
      +
      +	n = put_var_int(s, r->time);
      +	if (n < 0) {
      +		return -1;
      +	}
     -+	s.buf += n;
     -+	s.len -= n;
     ++	slice_consume(&s, n);
      +
      +	if (s.len < 2) {
      +		return -1;
      +	}
      +
      +	put_be16(s.buf, r->tz_offset);
     -+	s.buf += 2;
     -+	s.len -= 2;
     ++	slice_consume(&s, 2);
      +
      +	n = encode_string(r->message ? r->message : "", s);
      +	if (n < 0) {
      +		return -1;
      +	}
     -+	s.len -= n;
     -+	s.buf += n;
     ++	slice_consume(&s, n);
      +
      +	return start.len - s.len;
      +}
      +
     -+static int log_record_decode(void *rec, struct slice key, byte val_type,
     -+			     struct slice in, int hash_size)
     ++static int reftable_log_record_decode(void *rec, struct slice key,
     ++				      byte val_type, struct slice in,
     ++				      int hash_size)
      +{
      +	struct slice start = in;
     -+	struct log_record *r = (struct log_record *)rec;
     ++	struct reftable_log_record *r = (struct reftable_log_record *)rec;
      +	uint64_t max = 0;
      +	uint64_t ts = 0;
      +	struct slice dest = { 0 };
     @@ -3386,33 +3483,35 @@
      +		return FORMAT_ERROR;
      +	}
      +
     -+	r->ref_name = realloc(r->ref_name, key.len - 8);
     ++	r->ref_name = reftable_realloc(r->ref_name, key.len - 8);
      +	memcpy(r->ref_name, key.buf, key.len - 8);
      +	ts = get_be64(key.buf + key.len - 8);
      +
      +	r->update_index = (~max) - ts;
      +
     ++	if (val_type == 0) {
     ++		return 0;
     ++	}
     ++
      +	if (in.len < 2 * hash_size) {
      +		return FORMAT_ERROR;
      +	}
      +
     -+	r->old_hash = realloc(r->old_hash, hash_size);
     -+	r->new_hash = realloc(r->new_hash, hash_size);
     ++	r->old_hash = reftable_realloc(r->old_hash, hash_size);
     ++	r->new_hash = reftable_realloc(r->new_hash, hash_size);
      +
      +	memcpy(r->old_hash, in.buf, hash_size);
      +	memcpy(r->new_hash, in.buf + hash_size, hash_size);
      +
     -+	in.buf += 2 * hash_size;
     -+	in.len -= 2 * hash_size;
     ++	slice_consume(&in, 2 * hash_size);
      +
      +	n = decode_string(&dest, in);
      +	if (n < 0) {
      +		goto error;
      +	}
     -+	in.len -= n;
     -+	in.buf += n;
     ++	slice_consume(&in, n);
      +
     -+	r->name = realloc(r->name, dest.len + 1);
     ++	r->name = reftable_realloc(r->name, dest.len + 1);
      +	memcpy(r->name, dest.buf, dest.len);
      +	r->name[dest.len] = 0;
      +
     @@ -3421,10 +3520,9 @@
      +	if (n < 0) {
      +		goto error;
      +	}
     -+	in.len -= n;
     -+	in.buf += n;
     ++	slice_consume(&in, n);
      +
     -+	r->email = realloc(r->email, dest.len + 1);
     ++	r->email = reftable_realloc(r->email, dest.len + 1);
      +	memcpy(r->email, dest.buf, dest.len);
      +	r->email[dest.len] = 0;
      +
     @@ -3433,33 +3531,30 @@
      +	if (n < 0) {
      +		goto error;
      +	}
     -+	in.len -= n;
     -+	in.buf += n;
     ++	slice_consume(&in, n);
      +	r->time = ts;
      +	if (in.len < 2) {
      +		goto error;
      +	}
      +
      +	r->tz_offset = get_be16(in.buf);
     -+	in.buf += 2;
     -+	in.len -= 2;
     ++	slice_consume(&in, 2);
      +
      +	slice_resize(&dest, 0);
      +	n = decode_string(&dest, in);
      +	if (n < 0) {
      +		goto error;
      +	}
     -+	in.len -= n;
     -+	in.buf += n;
     ++	slice_consume(&in, n);
      +
     -+	r->message = realloc(r->message, dest.len + 1);
     ++	r->message = reftable_realloc(r->message, dest.len + 1);
      +	memcpy(r->message, dest.buf, dest.len);
      +	r->message[dest.len] = 0;
      +
      +	return start.len - in.len;
      +
      +error:
     -+	free(slice_yield(&dest));
     ++	reftable_free(slice_yield(&dest));
      +	return FORMAT_ERROR;
      +}
      +
     @@ -3486,7 +3581,8 @@
      +	return !memcmp(a, b, sz);
      +}
      +
     -+bool log_record_equal(struct log_record *a, struct log_record *b, int hash_size)
     ++bool reftable_log_record_equal(struct reftable_log_record *a,
     ++			       struct reftable_log_record *b, int hash_size)
      +{
      +	return null_streq(a->name, b->name) && null_streq(a->email, b->email) &&
      +	       null_streq(a->message, b->message) &&
     @@ -3496,14 +3592,14 @@
      +	       a->update_index == b->update_index;
      +}
      +
     -+struct record_vtable log_record_vtable = {
     -+	.key = &log_record_key,
     -+	.type = &log_record_type,
     -+	.copy_from = &log_record_copy_from,
     -+	.val_type = &log_record_val_type,
     -+	.encode = &log_record_encode,
     -+	.decode = &log_record_decode,
     -+	.clear = &log_record_clear_void,
     ++struct record_vtable reftable_log_record_vtable = {
     ++	.key = &reftable_log_record_key,
     ++	.type = &reftable_log_record_type,
     ++	.copy_from = &reftable_log_record_copy_from,
     ++	.val_type = &reftable_log_record_val_type,
     ++	.encode = &reftable_log_record_encode,
     ++	.decode = &reftable_log_record_decode,
     ++	.clear = &reftable_log_record_clear_void,
      +};
      +
      +struct record new_record(byte typ)
     @@ -3511,23 +3607,27 @@
      +	struct record rec;
      +	switch (typ) {
      +	case BLOCK_TYPE_REF: {
     -+		struct ref_record *r = calloc(1, sizeof(struct ref_record));
     ++		struct reftable_ref_record *r =
     ++			reftable_calloc(sizeof(struct reftable_ref_record));
      +		record_from_ref(&rec, r);
      +		return rec;
      +	}
      +
      +	case BLOCK_TYPE_OBJ: {
     -+		struct obj_record *r = calloc(1, sizeof(struct obj_record));
     ++		struct obj_record *r =
     ++			reftable_calloc(sizeof(struct obj_record));
      +		record_from_obj(&rec, r);
      +		return rec;
      +	}
      +	case BLOCK_TYPE_LOG: {
     -+		struct log_record *r = calloc(1, sizeof(struct log_record));
     ++		struct reftable_log_record *r =
     ++			reftable_calloc(sizeof(struct reftable_log_record));
      +		record_from_log(&rec, r);
      +		return rec;
      +	}
      +	case BLOCK_TYPE_INDEX: {
     -+		struct index_record *r = calloc(1, sizeof(struct index_record));
     ++		struct index_record *r =
     ++			reftable_calloc(sizeof(struct index_record));
      +		record_from_index(&rec, r);
      +		return rec;
      +	}
     @@ -3560,7 +3660,7 @@
      +static void index_record_clear(void *rec)
      +{
      +	struct index_record *idx = (struct index_record *)rec;
     -+	free(slice_yield(&idx->last_key));
     ++	reftable_free(slice_yield(&idx->last_key));
      +}
      +
      +static byte index_record_val_type(const void *rec)
     @@ -3578,8 +3678,7 @@
      +		return n;
      +	}
      +
     -+	out.buf += n;
     -+	out.len -= n;
     ++	slice_consume(&out, n);
      +
      +	return start.len - out.len;
      +}
     @@ -3598,8 +3697,7 @@
      +		return n;
      +	}
      +
     -+	in.buf += n;
     -+	in.len -= n;
     ++	slice_consume(&in, n);
      +	return start.len - in.len;
      +}
      +
     @@ -3651,10 +3749,10 @@
      +	return rec.ops->clear(rec.data);
      +}
      +
     -+void record_from_ref(struct record *rec, struct ref_record *ref_rec)
     ++void record_from_ref(struct record *rec, struct reftable_ref_record *ref_rec)
      +{
      +	rec->data = ref_rec;
     -+	rec->ops = &ref_record_vtable;
     ++	rec->ops = &reftable_ref_record_vtable;
      +}
      +
      +void record_from_obj(struct record *rec, struct obj_record *obj_rec)
     @@ -3669,10 +3767,10 @@
      +	rec->ops = &index_record_vtable;
      +}
      +
     -+void record_from_log(struct record *rec, struct log_record *log_rec)
     ++void record_from_log(struct record *rec, struct reftable_log_record *log_rec)
      +{
      +	rec->data = log_rec;
     -+	rec->ops = &log_record_vtable;
     ++	rec->ops = &reftable_log_record_vtable;
      +}
      +
      +void *record_yield(struct record *rec)
     @@ -3682,10 +3780,10 @@
      +	return p;
      +}
      +
     -+struct ref_record *record_as_ref(struct record rec)
     ++struct reftable_ref_record *record_as_ref(struct record rec)
      +{
      +	assert(record_type(rec) == BLOCK_TYPE_REF);
     -+	return (struct ref_record *)rec.data;
     ++	return (struct reftable_ref_record *)rec.data;
      +}
      +
      +static bool hash_equal(byte *a, byte *b, int hash_size)
     @@ -3706,7 +3804,8 @@
      +	return a == b;
      +}
      +
     -+bool ref_record_equal(struct ref_record *a, struct ref_record *b, int hash_size)
     ++bool reftable_ref_record_equal(struct reftable_ref_record *a,
     ++			       struct reftable_ref_record *b, int hash_size)
      +{
      +	assert(hash_size > 0);
      +	return 0 == strcmp(a->ref_name, b->ref_name) &&
     @@ -3716,22 +3815,22 @@
      +	       str_equal(a->target, b->target);
      +}
      +
     -+int ref_record_compare_name(const void *a, const void *b)
     ++int reftable_ref_record_compare_name(const void *a, const void *b)
      +{
     -+	return strcmp(((struct ref_record *)a)->ref_name,
     -+		      ((struct ref_record *)b)->ref_name);
     ++	return strcmp(((struct reftable_ref_record *)a)->ref_name,
     ++		      ((struct reftable_ref_record *)b)->ref_name);
      +}
      +
     -+bool ref_record_is_deletion(const struct ref_record *ref)
     ++bool reftable_ref_record_is_deletion(const struct reftable_ref_record *ref)
      +{
      +	return ref->value == NULL && ref->target == NULL &&
      +	       ref->target_value == NULL;
      +}
      +
     -+int log_record_compare_key(const void *a, const void *b)
     ++int reftable_log_record_compare_key(const void *a, const void *b)
      +{
     -+	struct log_record *la = (struct log_record *)a;
     -+	struct log_record *lb = (struct log_record *)b;
     ++	struct reftable_log_record *la = (struct reftable_log_record *)a;
     ++	struct reftable_log_record *lb = (struct reftable_log_record *)b;
      +
      +	int cmp = strcmp(la->ref_name, lb->ref_name);
      +	if (cmp) {
     @@ -3743,10 +3842,12 @@
      +	return (la->update_index < lb->update_index) ? 1 : 0;
      +}
      +
     -+bool log_record_is_deletion(const struct log_record *log)
     ++bool reftable_log_record_is_deletion(const struct reftable_log_record *log)
      +{
     -+	/* XXX */
     -+	return false;
     ++	return (log->new_hash == NULL && log->old_hash == NULL &&
     ++		log->name == NULL && log->email == NULL &&
     ++		log->message == NULL && log->time == 0 && log->tz_offset == 0 &&
     ++		log->message == NULL);
      +}
      +
      +int hash_size(uint32_t id)
     @@ -3780,14 +3881,33 @@
      +#include "reftable.h"
      +#include "slice.h"
      +
     ++/* utilities for de/encoding varints */
     ++
     ++int get_var_int(uint64_t *dest, struct slice in);
     ++int put_var_int(struct slice dest, uint64_t val);
     ++
     ++/* Methods for records. */
      +struct record_vtable {
     ++	/* encode the key of to a byte slice. */
      +	void (*key)(const void *rec, struct slice *dest);
     ++
     ++	/* The record type of ('r' for ref). */
      +	byte (*type)(void);
     -+	void (*copy_from)(void *rec, const void *src, int hash_size);
     ++
     ++	void (*copy_from)(void *dest, const void *src, int hash_size);
     ++
     ++	/* a value of [0..7], indicating record subvariants (eg. ref vs. symref
     ++	 * vs ref deletion) */
      +	byte (*val_type)(const void *rec);
     ++
     ++	/* encodes rec into dest, returning how much space was used. */
      +	int (*encode)(const void *rec, struct slice dest, int hash_size);
     ++
     ++	/* decode data from `src` into the record. */
      +	int (*decode)(void *rec, struct slice key, byte extra, struct slice src,
      +		      int hash_size);
     ++
     ++	/* deallocate and null the record. */
      +	void (*clear)(void *rec);
      +};
      +
     @@ -3797,32 +3917,34 @@
      +	struct record_vtable *ops;
      +};
      +
     -+int get_var_int(uint64_t *dest, struct slice in);
     -+int put_var_int(struct slice dest, uint64_t val);
     -+int common_prefix_size(struct slice a, struct slice b);
     -+
      +int is_block_type(byte typ);
     ++
      +struct record new_record(byte typ);
      +
     -+extern struct record_vtable ref_record_vtable;
     ++extern struct record_vtable reftable_ref_record_vtable;
      +
      +int encode_key(bool *restart, struct slice dest, struct slice prev_key,
      +	       struct slice key, byte extra);
      +int decode_key(struct slice *key, byte *extra, struct slice last_key,
      +	       struct slice in);
      +
     ++/* index_record are used internally to speed up lookups. */
      +struct index_record {
     -+	uint64_t offset;
     -+	struct slice last_key;
     ++	uint64_t offset; /* Offset of block */
     ++	struct slice last_key; /* Last key of the block. */
      +};
      +
     ++/* obj_record stores an object ID => ref mapping. */
      +struct obj_record {
     -+	byte *hash_prefix;
     -+	int hash_prefix_len;
     -+	uint64_t *offsets;
     ++	byte *hash_prefix; /* leading bytes of the object ID */
     ++	int hash_prefix_len; /* number of leading bytes. Constant
     ++			      * across a single table. */
     ++	uint64_t *offsets; /* a vector of file offsets. */
      +	int offset_len;
      +};
      +
     ++/* see struct record_vtable */
     ++
      +void record_key(struct record rec, struct slice *dest);
      +byte record_type(struct record rec);
      +void record_copy_from(struct record rec, struct record src, int hash_size);
     @@ -3831,18 +3953,24 @@
      +int record_decode(struct record rec, struct slice key, byte extra,
      +		  struct slice src, int hash_size);
      +void record_clear(struct record rec);
     ++
     ++/* clear out the record, yielding the record data that was encapsulated. */
      +void *record_yield(struct record *rec);
     ++
     ++/* initialize generic records from concrete records. The generic record should
     ++ * be zeroed out. */
     ++
      +void record_from_obj(struct record *rec, struct obj_record *objrec);
      +void record_from_index(struct record *rec, struct index_record *idxrec);
     -+void record_from_ref(struct record *rec, struct ref_record *refrec);
     -+void record_from_log(struct record *rec, struct log_record *logrec);
     -+struct ref_record *record_as_ref(struct record ref);
     ++void record_from_ref(struct record *rec, struct reftable_ref_record *refrec);
     ++void record_from_log(struct record *rec, struct reftable_log_record *logrec);
     ++struct reftable_ref_record *record_as_ref(struct record ref);
      +
      +/* for qsort. */
     -+int ref_record_compare_name(const void *a, const void *b);
     ++int reftable_ref_record_compare_name(const void *a, const void *b);
      +
      +/* for qsort. */
     -+int log_record_compare_key(const void *a, const void *b);
     ++int reftable_log_record_compare_key(const void *a, const void *b);
      +
      +#endif
      
     @@ -3863,65 +3991,20 @@
      +#define REFTABLE_H
      +
      +#include <stdint.h>
     ++#include <stddef.h>
      +
     -+/* block_source is a generic wrapper for a seekable readable file.
     -+   It is generally passed around by value.
     -+ */
     -+struct block_source {
     -+	struct block_source_vtable *ops;
     -+	void *arg;
     -+};
     ++void reftable_set_alloc(void *(*malloc)(size_t),
     ++			void *(*realloc)(void *, size_t), void (*free)(void *));
      +
     -+/* a contiguous segment of bytes. It keeps track of its generating block_source
     -+   so it can return itself into the pool.
     -+*/
     -+struct block {
     -+	uint8_t *data;
     -+	int len;
     -+	struct block_source source;
     -+};
     ++/****************************************************************
     ++ Basic data types
      +
     -+/* block_source_vtable are the operations that make up block_source */
     -+struct block_source_vtable {
     -+	/* returns the size of a block source */
     -+	uint64_t (*size)(void *source);
     ++ Reftables store the state of each ref in struct reftable_ref_record, and they
     ++ store a sequence of reflog updates in struct reftable_log_record.
     ++ ****************************************************************/
      +
     -+	/* reads a segment from the block source. It is an error to read
     -+	   beyond the end of the block */
     -+	int (*read_block)(void *source, struct block *dest, uint64_t off,
     -+			  uint32_t size);
     -+	/* mark the block as read; may return the data back to malloc */
     -+	void (*return_block)(void *source, struct block *blockp);
     -+
     -+	/* release all resources associated with the block source */
     -+	void (*close)(void *source);
     -+};
     -+
     -+/* opens a file on the file system as a block_source */
     -+int block_source_from_file(struct block_source *block_src, const char *name);
     -+
     -+/* write_options sets options for writing a single reftable. */
     -+struct write_options {
     -+	/* boolean: do not pad out blocks to block size. */
     -+	int unpadded;
     -+
     -+	/* the blocksize. Should be less than 2^24. */
     -+	uint32_t block_size;
     -+
     -+	/* boolean: do not generate a SHA1 => ref index. */
     -+	int skip_index_objects;
     -+
     -+	/* how often to write complete keys in each block. */
     -+	int restart_interval;
     -+
     -+	/* 4-byte identifier ("sha1", "s256") of the hash.
     -+	 * Defaults to SHA1 if unset
     -+	 */
     -+	uint32_t hash_id;
     -+};
     -+
     -+/* ref_record holds a ref database entry target_value */
     -+struct ref_record {
     ++/* reftable_ref_record holds a ref database entry target_value */
     ++struct reftable_ref_record {
      +	char *ref_name; /* Name of the ref, malloced. */
      +	uint64_t update_index; /* Logical timestamp at which this value is
      +				  written */
     @@ -3931,21 +4014,23 @@
      +};
      +
      +/* returns whether 'ref' represents a deletion */
     -+int ref_record_is_deletion(const struct ref_record *ref);
     ++int reftable_ref_record_is_deletion(const struct reftable_ref_record *ref);
      +
     -+/* prints a ref_record onto stdout */
     -+void ref_record_print(struct ref_record *ref, int hash_size);
     ++/* prints a reftable_ref_record onto stdout */
     ++void reftable_ref_record_print(struct reftable_ref_record *ref, int hash_size);
      +
      +/* frees and nulls all pointer values. */
     -+void ref_record_clear(struct ref_record *ref);
     ++void reftable_ref_record_clear(struct reftable_ref_record *ref);
      +
     -+/* returns whether two ref_records are the same */
     -+int ref_record_equal(struct ref_record *a, struct ref_record *b, int hash_size);
     ++/* returns whether two reftable_ref_records are the same */
     ++int reftable_ref_record_equal(struct reftable_ref_record *a,
     ++			      struct reftable_ref_record *b, int hash_size);
      +
     -+/* log_record holds a reflog entry */
     -+struct log_record {
     ++/* reftable_log_record holds a reflog entry */
     ++struct reftable_log_record {
      +	char *ref_name;
     -+	uint64_t update_index;
     ++	uint64_t update_index; /* logical timestamp of a transactional update.
     ++				*/
      +	uint8_t *new_hash;
      +	uint8_t *old_hash;
      +	char *name;
     @@ -3956,39 +4041,88 @@
      +};
      +
      +/* returns whether 'ref' represents the deletion of a log record. */
     -+int log_record_is_deletion(const struct log_record *log);
     ++int reftable_log_record_is_deletion(const struct reftable_log_record *log);
      +
      +/* frees and nulls all pointer values. */
     -+void log_record_clear(struct log_record *log);
     ++void reftable_log_record_clear(struct reftable_log_record *log);
      +
      +/* returns whether two records are equal. */
     -+int log_record_equal(struct log_record *a, struct log_record *b, int hash_size);
     ++int reftable_log_record_equal(struct reftable_log_record *a,
     ++			      struct reftable_log_record *b, int hash_size);
      +
     -+void log_record_print(struct log_record *log, int hash_size);
     ++/* dumps a reftable_log_record on stdout, for debugging/testing. */
     ++void reftable_log_record_print(struct reftable_log_record *log, int hash_size);
      +
     -+/* iterator is the generic interface for walking over data stored in a
     -+   reftable. It is generally passed around by value.
     -+*/
     -+struct iterator {
     -+	struct iterator_vtable *ops;
     -+	void *iter_arg;
     ++/****************************************************************
     ++ Error handling
     ++
     ++ Error are signaled with negative integer return values. 0 means success.
     ++ ****************************************************************/
     ++
     ++/* different types of errors */
     ++enum reftable_error {
     ++	/* Unexpected file system behavior */
     ++	IO_ERROR = -2,
     ++
     ++	/* Format inconsistency on reading data
     ++	 */
     ++	FORMAT_ERROR = -3,
     ++
     ++	/* File does not exist. Returned from block_source_from_file(),  because
     ++	   it needs special handling in stack.
     ++	*/
     ++	NOT_EXIST_ERROR = -4,
     ++
     ++	/* Trying to write out-of-date data. */
     ++	LOCK_ERROR = -5,
     ++
     ++	/* Misuse of the API:
     ++	   - on writing a record with NULL ref_name.
     ++	   - on writing a reftable_ref_record outside the table limits
     ++	   - on writing a ref or log record before the stack's next_update_index
     ++	   - on reading a reftable_ref_record from log iterator, or vice versa.
     ++	*/
     ++	API_ERROR = -6,
     ++
     ++	/* Decompression error */
     ++	ZLIB_ERROR = -7,
     ++
     ++	/* Wrote a table without blocks. */
     ++	EMPTY_TABLE_ERROR = -8,
      +};
      +
     -+/* reads the next ref_record. Returns < 0 for error, 0 for OK and > 0:
     -+   end of iteration.
     -+*/
     -+int iterator_next_ref(struct iterator it, struct ref_record *ref);
     ++/* convert the numeric error code to a string. The string should not be
     ++ * deallocated. */
     ++const char *reftable_error_str(int err);
      +
     -+/* reads the next log_record. Returns < 0 for error, 0 for OK and > 0:
     -+   end of iteration.
     -+*/
     -+int iterator_next_log(struct iterator it, struct log_record *log);
     ++/****************************************************************
     ++ Writing
      +
     -+/* releases resources associated with an iterator. */
     -+void iterator_destroy(struct iterator *it);
     ++ Writing single reftables
     ++ ****************************************************************/
     ++
     ++/* reftable_write_options sets options for writing a single reftable. */
     ++struct reftable_write_options {
     ++	/* boolean: do not pad out blocks to block size. */
     ++	int unpadded;
     ++
     ++	/* the blocksize. Should be less than 2^24. */
     ++	uint32_t block_size;
      +
     -+/* block_stats holds statistics for a single block type */
     -+struct block_stats {
     ++	/* boolean: do not generate a SHA1 => ref index. */
     ++	int skip_index_objects;
     ++
     ++	/* how often to write complete keys in each block. */
     ++	int restart_interval;
     ++
     ++	/* 4-byte identifier ("sha1", "s256") of the hash.
     ++	 * Defaults to SHA1 if unset
     ++	 */
     ++	uint32_t hash_id;
     ++};
     ++
     ++/* reftable_block_stats holds statistics for a single block type */
     ++struct reftable_block_stats {
      +	/* total number of entries written */
      +	int entries;
      +	/* total number of key restarts */
     @@ -4008,119 +4142,175 @@
      +};
      +
      +/* stats holds overall statistics for a single reftable */
     -+struct stats {
     ++struct reftable_stats {
      +	/* total number of blocks written. */
      +	int blocks;
      +	/* stats for ref data */
     -+	struct block_stats ref_stats;
     ++	struct reftable_block_stats ref_stats;
      +	/* stats for the SHA1 to ref map. */
     -+	struct block_stats obj_stats;
     ++	struct reftable_block_stats obj_stats;
      +	/* stats for index blocks */
     -+	struct block_stats idx_stats;
     ++	struct reftable_block_stats idx_stats;
      +	/* stats for log blocks */
     -+	struct block_stats log_stats;
     ++	struct reftable_block_stats log_stats;
      +
      +	/* disambiguation length of shortened object IDs. */
      +	int object_id_len;
      +};
      +
     -+/* different types of errors */
     -+
     -+/* Unexpected file system behavior */
     -+#define IO_ERROR -2
     -+
     -+/* Format inconsistency on reading data
     -+ */
     -+#define FORMAT_ERROR -3
     -+
     -+/* File does not exist. Returned from block_source_from_file(),  because it
     -+   needs special handling in stack.
     -+*/
     -+#define NOT_EXIST_ERROR -4
     -+
     -+/* Trying to write out-of-date data. */
     -+#define LOCK_ERROR -5
     -+
     -+/* Misuse of the API:
     -+   - on writing a record with NULL ref_name.
     -+   - on writing a ref_record outside the table limits
     -+   - on writing a ref or log record before the stack's next_update_index
     -+   - on reading a ref_record from log iterator, or vice versa.
     -+ */
     -+#define API_ERROR -6
     -+
     -+/* Decompression error */
     -+#define ZLIB_ERROR -7
     -+
     -+/* Wrote a table without blocks. */
     -+#define EMPTY_TABLE_ERROR -8
     -+
     -+const char *error_str(int err);
     -+
     -+/* new_writer creates a new writer */
     -+struct writer *new_writer(int (*writer_func)(void *, uint8_t *, int),
     -+			  void *writer_arg, struct write_options *opts);
     ++/* reftable_new_writer creates a new writer */
     ++struct reftable_writer *
     ++reftable_new_writer(int (*writer_func)(void *, uint8_t *, int),
     ++		    void *writer_arg, struct reftable_write_options *opts);
      +
      +/* write to a file descriptor. fdp should be an int* pointing to the fd. */
     -+int fd_writer(void *fdp, uint8_t *data, int size);
     ++int reftable_fd_write(void *fdp, uint8_t *data, int size);
      +
      +/* Set the range of update indices for the records we will add.  When
      +   writing a table into a stack, the min should be at least
     -+   stack_next_update_index(), or API_ERROR is returned.
     ++   reftable_stack_next_update_index(), or API_ERROR is returned.
     ++
     ++   For transactional updates, typically min==max. When converting an existing
     ++   ref database into a single reftable, this would be a range of update-index
     ++   timestamps.
      + */
     -+void writer_set_limits(struct writer *w, uint64_t min, uint64_t max);
     ++void reftable_writer_set_limits(struct reftable_writer *w, uint64_t min,
     ++				uint64_t max);
      +
     -+/* adds a ref_record. Must be called in ascending
     ++/* adds a reftable_ref_record. Must be called in ascending
      +   order. The update_index must be within the limits set by
     -+   writer_set_limits(), or API_ERROR is returned.
     ++   reftable_writer_set_limits(), or API_ERROR is returned.
     ++
     ++   It is an error to write a ref record after a log record.
      + */
     -+int writer_add_ref(struct writer *w, struct ref_record *ref);
     ++int reftable_writer_add_ref(struct reftable_writer *w,
     ++			    struct reftable_ref_record *ref);
      +
      +/* Convenience function to add multiple refs. Will sort the refs by
      +   name before adding. */
     -+int writer_add_refs(struct writer *w, struct ref_record *refs, int n);
     ++int reftable_writer_add_refs(struct reftable_writer *w,
     ++			     struct reftable_ref_record *refs, int n);
      +
     -+/* adds a log_record. Must be called in ascending order (with more
     ++/* adds a reftable_log_record. Must be called in ascending order (with more
      +   recent log entries first.)
      + */
     -+int writer_add_log(struct writer *w, struct log_record *log);
     ++int reftable_writer_add_log(struct reftable_writer *w,
     ++			    struct reftable_log_record *log);
      +
      +/* Convenience function to add multiple logs. Will sort the records by
      +   key before adding. */
     -+int writer_add_logs(struct writer *w, struct log_record *logs, int n);
     ++int reftable_writer_add_logs(struct reftable_writer *w,
     ++			     struct reftable_log_record *logs, int n);
     ++
     ++/* reftable_writer_close finalizes the reftable. The writer is retained so
     ++ * statistics can be inspected. */
     ++int reftable_writer_close(struct reftable_writer *w);
     ++
     ++/* writer_stats returns the statistics on the reftable being written.
     ++
     ++   This struct becomes invalid when the writer is freed.
     ++ */
     ++const struct reftable_stats *writer_stats(struct reftable_writer *w);
     ++
     ++/* reftable_writer_free deallocates memory for the writer */
     ++void reftable_writer_free(struct reftable_writer *w);
     ++
     ++/****************************************************************
     ++ * ITERATING
     ++ ****************************************************************/
      +
     -+/* writer_close finalizes the reftable. The writer is retained so statistics can
     -+ * be inspected. */
     -+int writer_close(struct writer *w);
     ++/* iterator is the generic interface for walking over data stored in a
     ++   reftable. It is generally passed around by value.
     ++*/
     ++struct reftable_iterator {
     ++	struct reftable_iterator_vtable *ops;
     ++	void *iter_arg;
     ++};
      +
     -+/* writer_stats returns the statistics on the reftable being written. */
     -+struct stats *writer_stats(struct writer *w);
     ++/* reads the next reftable_ref_record. Returns < 0 for error, 0 for OK and > 0:
     ++   end of iteration.
     ++*/
     ++int reftable_iterator_next_ref(struct reftable_iterator it,
     ++			       struct reftable_ref_record *ref);
      +
     -+/* writer_free deallocates memory for the writer */
     -+void writer_free(struct writer *w);
     ++/* reads the next reftable_log_record. Returns < 0 for error, 0 for OK and > 0:
     ++   end of iteration.
     ++*/
     ++int reftable_iterator_next_log(struct reftable_iterator it,
     ++			       struct reftable_log_record *log);
      +
     -+struct reader;
     ++/* releases resources associated with an iterator. */
     ++void reftable_iterator_destroy(struct reftable_iterator *it);
     ++
     ++/****************************************************************
     ++ Reading single tables
      +
     -+/* new_reader opens a reftable for reading. If successful, returns 0
     ++ The follow routines are for reading single files. For an application-level
     ++ interface, skip ahead to struct reftable_merged_table and struct
     ++ reftable_stack.
     ++ ****************************************************************/
     ++
     ++/* block_source is a generic wrapper for a seekable readable file.
     ++   It is generally passed around by value.
     ++ */
     ++struct reftable_block_source {
     ++	struct reftable_block_source_vtable *ops;
     ++	void *arg;
     ++};
     ++
     ++/* a contiguous segment of bytes. It keeps track of its generating block_source
     ++   so it can return itself into the pool.
     ++*/
     ++struct reftable_block {
     ++	uint8_t *data;
     ++	int len;
     ++	struct reftable_block_source source;
     ++};
     ++
     ++/* block_source_vtable are the operations that make up block_source */
     ++struct reftable_block_source_vtable {
     ++	/* returns the size of a block source */
     ++	uint64_t (*size)(void *source);
     ++
     ++	/* reads a segment from the block source. It is an error to read
     ++	   beyond the end of the block */
     ++	int (*read_block)(void *source, struct reftable_block *dest,
     ++			  uint64_t off, uint32_t size);
     ++	/* mark the block as read; may return the data back to malloc */
     ++	void (*return_block)(void *source, struct reftable_block *blockp);
     ++
     ++	/* release all resources associated with the block source */
     ++	void (*close)(void *source);
     ++};
     ++
     ++/* opens a file on the file system as a block_source */
     ++int reftable_block_source_from_file(struct reftable_block_source *block_src,
     ++				    const char *name);
     ++
     ++/* The reader struct is a handle to an open reftable file. */
     ++struct reftable_reader;
     ++
     ++/* reftable_new_reader opens a reftable for reading. If successful, returns 0
      + * code and sets pp.  The name is used for creating a
      + * stack. Typically, it is the basename of the file.
      + */
     -+int new_reader(struct reader **pp, struct block_source, const char *name);
     ++int reftable_new_reader(struct reftable_reader **pp,
     ++			struct reftable_block_source, const char *name);
      +
     -+/* reader_seek_ref returns an iterator where 'name' would be inserted in the
     -+   table.
     ++/* reftable_reader_seek_ref returns an iterator where 'name' would be inserted
     ++   in the table.  To seek to the start of the table, use name = "".
      +
      +   example:
      +
     -+   struct reader *r = NULL;
     -+   int err = new_reader(&r, src, "filename");
     ++   struct reftable_reader *r = NULL;
     ++   int err = reftable_new_reader(&r, src, "filename");
      +   if (err < 0) { ... }
     -+   struct iterator it  = {0};
     -+   err = reader_seek_ref(r, &it, "refs/heads/master");
     ++   struct reftable_iterator it  = {0};
     ++   err = reftable_reader_seek_ref(r, &it, "refs/heads/master");
      +   if (err < 0) { ... }
     -+   struct ref_record ref  = {0};
     ++   struct reftable_ref_record ref  = {0};
      +   while (1) {
     -+     err = iterator_next_ref(it, &ref);
     ++     err = reftable_iterator_next_ref(it, &ref);
      +     if (err > 0) {
      +       break;
      +     }
     @@ -4129,103 +4319,149 @@
      +     }
      +     ..found..
      +   }
     -+   iterator_destroy(&it);
     -+   ref_record_clear(&ref);
     ++   reftable_iterator_destroy(&it);
     ++   reftable_ref_record_clear(&ref);
      + */
     -+int reader_seek_ref(struct reader *r, struct iterator *it, const char *name);
     ++int reftable_reader_seek_ref(struct reftable_reader *r,
     ++			     struct reftable_iterator *it, const char *name);
      +
      +/* returns the hash ID used in this table. */
     -+uint32_t reader_hash_id(struct reader *r);
     ++uint32_t reftable_reader_hash_id(struct reftable_reader *r);
      +
     -+/* seek to logs for the given name, older than update_index. */
     -+int reader_seek_log_at(struct reader *r, struct iterator *it, const char *name,
     -+		       uint64_t update_index);
     ++/* seek to logs for the given name, older than update_index. To seek to the
     ++   start of the table, use name = "".
     ++ */
     ++int reftable_reader_seek_log_at(struct reftable_reader *r,
     ++				struct reftable_iterator *it, const char *name,
     ++				uint64_t update_index);
      +
      +/* seek to newest log entry for given name. */
     -+int reader_seek_log(struct reader *r, struct iterator *it, const char *name);
     ++int reftable_reader_seek_log(struct reftable_reader *r,
     ++			     struct reftable_iterator *it, const char *name);
      +
      +/* closes and deallocates a reader. */
     -+void reader_free(struct reader *);
     ++void reftable_reader_free(struct reftable_reader *);
      +
      +/* return an iterator for the refs pointing to oid */
     -+int reader_refs_for(struct reader *r, struct iterator *it, uint8_t *oid,
     -+		    int oid_len);
     ++int reftable_reader_refs_for(struct reftable_reader *r,
     ++			     struct reftable_iterator *it, uint8_t *oid,
     ++			     int oid_len);
      +
      +/* return the max_update_index for a table */
     -+uint64_t reader_max_update_index(struct reader *r);
     ++uint64_t reftable_reader_max_update_index(struct reftable_reader *r);
      +
      +/* return the min_update_index for a table */
     -+uint64_t reader_min_update_index(struct reader *r);
     ++uint64_t reftable_reader_min_update_index(struct reftable_reader *r);
     ++
     ++/****************************************************************
     ++ Merged tables
      +
     -+/* a merged table is implements seeking/iterating over a stack of tables. */
     -+struct merged_table;
     ++ A ref database kept in a sequence of table files. The merged_table presents a
     ++ unified view to reading (seeking, iterating) a sequence of immutable tables.
     ++ ****************************************************************/
      +
     -+/* new_merged_table creates a new merged table. It takes ownership of the stack
     -+   array.
     ++/* A merged table is implements seeking/iterating over a stack of tables. */
     ++struct reftable_merged_table;
     ++
     ++/* reftable_new_merged_table creates a new merged table. It takes ownership of
     ++   the stack array.
      +*/
     -+int new_merged_table(struct merged_table **dest, struct reader **stack, int n,
     -+		     uint32_t hash_id);
     ++int reftable_new_merged_table(struct reftable_merged_table **dest,
     ++			      struct reftable_reader **stack, int n,
     ++			      uint32_t hash_id);
      +
      +/* returns the hash id used in this merged table. */
     -+uint32_t merged_hash_id(struct merged_table *mt);
     ++uint32_t reftable_merged_table_hash_id(struct reftable_merged_table *mt);
      +
      +/* returns an iterator positioned just before 'name' */
     -+int merged_table_seek_ref(struct merged_table *mt, struct iterator *it,
     -+			  const char *name);
     ++int reftable_merged_table_seek_ref(struct reftable_merged_table *mt,
     ++				   struct reftable_iterator *it,
     ++				   const char *name);
      +
      +/* returns an iterator for log entry, at given update_index */
     -+int merged_table_seek_log_at(struct merged_table *mt, struct iterator *it,
     -+			     const char *name, uint64_t update_index);
     ++int reftable_merged_table_seek_log_at(struct reftable_merged_table *mt,
     ++				      struct reftable_iterator *it,
     ++				      const char *name, uint64_t update_index);
      +
     -+/* like merged_table_seek_log_at but look for the newest entry. */
     -+int merged_table_seek_log(struct merged_table *mt, struct iterator *it,
     -+			  const char *name);
     ++/* like reftable_merged_table_seek_log_at but look for the newest entry. */
     ++int reftable_merged_table_seek_log(struct reftable_merged_table *mt,
     ++				   struct reftable_iterator *it,
     ++				   const char *name);
      +
      +/* returns the max update_index covered by this merged table. */
     -+uint64_t merged_max_update_index(struct merged_table *mt);
     ++uint64_t
     ++reftable_merged_table_max_update_index(struct reftable_merged_table *mt);
      +
      +/* returns the min update_index covered by this merged table. */
     -+uint64_t merged_min_update_index(struct merged_table *mt);
     ++uint64_t
     ++reftable_merged_table_min_update_index(struct reftable_merged_table *mt);
      +
      +/* closes readers for the merged tables */
     -+void merged_table_close(struct merged_table *mt);
     ++void reftable_merged_table_close(struct reftable_merged_table *mt);
      +
      +/* releases memory for the merged_table */
     -+void merged_table_free(struct merged_table *m);
     ++void reftable_merged_table_free(struct reftable_merged_table *m);
     ++
     ++/****************************************************************
     ++ Mutable ref database
     ++
     ++ The stack presents an interface to a mutable sequence of reftables.
     ++ ****************************************************************/
      +
      +/* a stack is a stack of reftables, which can be mutated by pushing a table to
      + * the top of the stack */
     -+struct stack;
     ++struct reftable_stack;
      +
     -+/* open a new reftable stack. The tables will be stored in 'dir', while the list
     -+   of tables is in 'list_file'. Typically, this should be .git/reftables and
     -+   .git/refs respectively.
     ++/* open a new reftable stack. The tables along with the table list will be
     ++   stored in 'dir'. Typically, this should be .git/reftables.
      +*/
     -+int new_stack(struct stack **dest, const char *dir, const char *list_file,
     -+	      struct write_options config);
     ++int reftable_new_stack(struct reftable_stack **dest, const char *dir,
     ++		       struct reftable_write_options config);
      +
      +/* returns the update_index at which a next table should be written. */
     -+uint64_t stack_next_update_index(struct stack *st);
     ++uint64_t reftable_stack_next_update_index(struct reftable_stack *st);
     ++
     ++/* holds a transaction to add tables at the top of a stack. */
     ++struct reftable_addition;
     ++
     ++/*
     ++  returns a new transaction to add reftables to the given stack. As a side
     ++  effect, the ref database is locked.
     ++*/ 
     ++int reftable_stack_new_addition(struct reftable_addition **dest, struct reftable_stack *st);
     ++
     ++/* Adds a reftable to transaction. */ 
     ++int reftable_addition_add(struct reftable_addition *add,
     ++                          int (*write_table)(struct reftable_writer *wr, void *arg),
     ++                          void *arg);
     ++
     ++/* Commits the transaction, releasing the lock. */
     ++int reftable_addition_commit(struct reftable_addition *add);
     ++
     ++/* Release all non-committed data from the transaction; releases the lock if held. */
     ++void reftable_addition_close(struct reftable_addition *add);
      +
      +/* add a new table to the stack. The write_table function must call
     -+   writer_set_limits, add refs and return an error value. */
     -+int stack_add(struct stack *st,
     -+	      int (*write_table)(struct writer *wr, void *write_arg),
     -+	      void *write_arg);
     ++   reftable_writer_set_limits, add refs and return an error value. */
     ++int reftable_stack_add(struct reftable_stack *st,
     ++		       int (*write_table)(struct reftable_writer *wr,
     ++					  void *write_arg),
     ++		       void *write_arg);
      +
      +/* returns the merged_table for seeking. This table is valid until the
      +   next write or reload, and should not be closed or deleted.
      +*/
     -+struct merged_table *stack_merged_table(struct stack *st);
     ++struct reftable_merged_table *
     ++reftable_stack_merged_table(struct reftable_stack *st);
      +
      +/* frees all resources associated with the stack. */
     -+void stack_destroy(struct stack *st);
     ++void reftable_stack_destroy(struct reftable_stack *st);
      +
      +/* reloads the stack if necessary. */
     -+int stack_reload(struct stack *st);
     ++int reftable_stack_reload(struct reftable_stack *st);
      +
      +/* Policy for expiring reflog entries. */
     -+struct log_expiry_config {
     ++struct reftable_log_expiry_config {
      +	/* Drop entries older than this timestamp */
      +	uint64_t time;
      +
     @@ -4235,29 +4471,32 @@
      +
      +/* compacts all reftables into a giant table. Expire reflog entries if config is
      + * non-NULL */
     -+int stack_compact_all(struct stack *st, struct log_expiry_config *config);
     ++int reftable_stack_compact_all(struct reftable_stack *st,
     ++			       struct reftable_log_expiry_config *config);
      +
      +/* heuristically compact unbalanced table stack. */
     -+int stack_auto_compact(struct stack *st);
     ++int reftable_stack_auto_compact(struct reftable_stack *st);
      +
      +/* convenience function to read a single ref. Returns < 0 for error, 0
      +   for success, and 1 if ref not found. */
     -+int stack_read_ref(struct stack *st, const char *refname,
     -+		   struct ref_record *ref);
     ++int reftable_stack_read_ref(struct reftable_stack *st, const char *refname,
     ++			    struct reftable_ref_record *ref);
      +
      +/* convenience function to read a single log. Returns < 0 for error, 0
      +   for success, and 1 if ref not found. */
     -+int stack_read_log(struct stack *st, const char *refname,
     -+		   struct log_record *log);
     ++int reftable_stack_read_log(struct reftable_stack *st, const char *refname,
     ++			    struct reftable_log_record *log);
      +
      +/* statistics on past compactions. */
     -+struct compaction_stats {
     -+	uint64_t bytes;
     -+	int attempts;
     -+	int failures;
     ++struct reftable_compaction_stats {
     ++	uint64_t bytes; /* total number of bytes written */
     ++	int attempts; /* how often we tried to compact */
     ++	int failures; /* failures happen on concurrent updates */
      +};
      +
     -+struct compaction_stats *stack_compaction_stats(struct stack *st);
     ++/* return statistics for compaction up till now. */
     ++struct reftable_compaction_stats *
     ++reftable_stack_compaction_stats(struct reftable_stack *st);
      +
      +#endif
      
     @@ -4304,7 +4543,7 @@
      +			c = l;
      +		}
      +		s->cap = c;
     -+		s->buf = realloc(s->buf, s->cap);
     ++		s->buf = reftable_realloc(s->buf, s->cap);
      +	}
      +	s->len = l;
      +}
     @@ -4325,6 +4564,12 @@
      +	memcpy(s->buf + end, a.buf, a.len);
      +}
      +
     ++void slice_consume(struct slice *s, int n)
     ++{
     ++	s->buf += n;
     ++	s->len -= n;
     ++}
     ++
      +byte *slice_yield(struct slice *s)
      +{
      +	byte *p = s->buf;
     @@ -4394,7 +4639,7 @@
      +		if (newcap < b->len + sz) {
      +			newcap = (b->len + sz);
      +		}
     -+		b->buf = realloc(b->buf, newcap);
     ++		b->buf = reftable_realloc(b->buf, newcap);
      +		b->cap = newcap;
      +	}
      +
     @@ -4413,57 +4658,71 @@
      +	return ((struct slice *)b)->len;
      +}
      +
     -+static void slice_return_block(void *b, struct block *dest)
     ++static void slice_return_block(void *b, struct reftable_block *dest)
      +{
      +	memset(dest->data, 0xff, dest->len);
     -+	free(dest->data);
     ++	reftable_free(dest->data);
      +}
      +
      +static void slice_close(void *b)
      +{
      +}
      +
     -+static int slice_read_block(void *v, struct block *dest, uint64_t off,
     ++static int slice_read_block(void *v, struct reftable_block *dest, uint64_t off,
      +			    uint32_t size)
      +{
      +	struct slice *b = (struct slice *)v;
      +	assert(off + size <= b->len);
     -+	dest->data = calloc(size, 1);
     ++	dest->data = reftable_calloc(size);
      +	memcpy(dest->data, b->buf + off, size);
      +	dest->len = size;
      +	return size;
      +}
      +
     -+struct block_source_vtable slice_vtable = {
     ++struct reftable_block_source_vtable slice_vtable = {
      +	.size = &slice_size,
      +	.read_block = &slice_read_block,
      +	.return_block = &slice_return_block,
      +	.close = &slice_close,
      +};
      +
     -+void block_source_from_slice(struct block_source *bs, struct slice *buf)
     ++void block_source_from_slice(struct reftable_block_source *bs,
     ++			     struct slice *buf)
      +{
      +	bs->ops = &slice_vtable;
      +	bs->arg = buf;
      +}
      +
     -+static void malloc_return_block(void *b, struct block *dest)
     ++static void malloc_return_block(void *b, struct reftable_block *dest)
      +{
      +	memset(dest->data, 0xff, dest->len);
     -+	free(dest->data);
     ++	reftable_free(dest->data);
      +}
      +
     -+struct block_source_vtable malloc_vtable = {
     ++struct reftable_block_source_vtable malloc_vtable = {
      +	.return_block = &malloc_return_block,
      +};
      +
     -+struct block_source malloc_block_source_instance = {
     ++struct reftable_block_source malloc_block_source_instance = {
      +	.ops = &malloc_vtable,
      +};
      +
     -+struct block_source malloc_block_source(void)
     ++struct reftable_block_source malloc_block_source(void)
      +{
      +	return malloc_block_source_instance;
     ++}
     ++
     ++int common_prefix_size(struct slice a, struct slice b)
     ++{
     ++	int p = 0;
     ++	while (p < a.len && p < b.len) {
     ++		if (a.buf[p] != b.buf[p]) {
     ++			break;
     ++		}
     ++		p++;
     ++	}
     ++
     ++	return p;
      +}
      
       diff --git a/reftable/slice.h b/reftable/slice.h
     @@ -4498,16 +4757,19 @@
      +bool slice_equal(struct slice a, struct slice b);
      +byte *slice_yield(struct slice *s);
      +void slice_copy(struct slice *dest, struct slice src);
     ++void slice_consume(struct slice *s, int n);
      +void slice_resize(struct slice *s, int l);
      +int slice_compare(struct slice a, struct slice b);
      +int slice_write(struct slice *b, byte *data, int sz);
      +int slice_write_void(void *b, byte *data, int sz);
      +void slice_append(struct slice *dest, struct slice add);
     ++int common_prefix_size(struct slice a, struct slice b);
      +
     -+struct block_source;
     -+void block_source_from_slice(struct block_source *bs, struct slice *buf);
     ++struct reftable_block_source;
     ++void block_source_from_slice(struct reftable_block_source *bs,
     ++			     struct slice *buf);
      +
     -+struct block_source malloc_block_source(void);
     ++struct reftable_block_source malloc_block_source(void);
      +
      +#endif
      
     @@ -4532,19 +4794,26 @@
      +#include "reftable.h"
      +#include "writer.h"
      +
     -+int new_stack(struct stack **dest, const char *dir, const char *list_file,
     -+	      struct write_options config)
     ++int reftable_new_stack(struct reftable_stack **dest, const char *dir,
     ++		       struct reftable_write_options config)
      +{
     -+	struct stack *p = calloc(sizeof(struct stack), 1);
     ++	struct reftable_stack *p =
     ++		reftable_calloc(sizeof(struct reftable_stack));
     ++	struct slice list_file_name = {};
      +	int err = 0;
      +	*dest = NULL;
     -+	p->list_file = xstrdup(list_file);
     ++
     ++	slice_set_string(&list_file_name, dir);
     ++	slice_append_string(&list_file_name, "/reftables.list");
     ++
     ++	p->list_file = slice_to_string(list_file_name);
     ++	reftable_free(slice_yield(&list_file_name));
      +	p->reftable_dir = xstrdup(dir);
      +	p->config = config;
      +
     -+	err = stack_reload(p);
     ++	err = reftable_stack_reload(p);
      +	if (err < 0) {
     -+		stack_destroy(p);
     ++		reftable_stack_destroy(p);
      +	} else {
      +		*dest = p;
      +	}
     @@ -4571,7 +4840,7 @@
      +		goto exit;
      +	}
      +
     -+	buf = malloc(size + 1);
     ++	buf = reftable_malloc(size + 1);
      +	if (fread(buf, 1, size, f) != size) {
      +		err = IO_ERROR;
      +		goto exit;
     @@ -4580,7 +4849,7 @@
      +
      +	parse_names(buf, size, namesp);
      +exit:
     -+	free(buf);
     ++	reftable_free(buf);
      +	return err;
      +}
      +
     @@ -4590,7 +4859,7 @@
      +	int err = 0;
      +	if (f == NULL) {
      +		if (errno == ENOENT) {
     -+			*namesp = calloc(sizeof(char *), 1);
     ++			*namesp = reftable_calloc(sizeof(char *));
      +			return 0;
      +		}
      +
     @@ -4601,30 +4870,33 @@
      +	return err;
      +}
      +
     -+struct merged_table *stack_merged_table(struct stack *st)
     ++struct reftable_merged_table *
     ++reftable_stack_merged_table(struct reftable_stack *st)
      +{
      +	return st->merged;
      +}
      +
      +/* Close and free the stack */
     -+void stack_destroy(struct stack *st)
     ++void reftable_stack_destroy(struct reftable_stack *st)
      +{
      +	if (st->merged == NULL) {
      +		return;
      +	}
      +
     -+	merged_table_close(st->merged);
     -+	merged_table_free(st->merged);
     ++	reftable_merged_table_close(st->merged);
     ++	reftable_merged_table_free(st->merged);
      +	st->merged = NULL;
      +
      +	FREE_AND_NULL(st->list_file);
      +	FREE_AND_NULL(st->reftable_dir);
     -+	free(st);
     ++	reftable_free(st);
      +}
      +
     -+static struct reader **stack_copy_readers(struct stack *st, int cur_len)
     ++static struct reftable_reader **stack_copy_readers(struct reftable_stack *st,
     ++						   int cur_len)
      +{
     -+	struct reader **cur = calloc(sizeof(struct reader *), cur_len);
     ++	struct reftable_reader **cur =
     ++		reftable_calloc(sizeof(struct reftable_reader *) * cur_len);
      +	int i = 0;
      +	for (i = 0; i < cur_len; i++) {
      +		cur[i] = st->merged->stack[i];
     @@ -4632,21 +4904,22 @@
      +	return cur;
      +}
      +
     -+static int stack_reload_once(struct stack *st, char **names, bool reuse_open)
     ++static int reftable_stack_reload_once(struct reftable_stack *st, char **names,
     ++				      bool reuse_open)
      +{
      +	int cur_len = st->merged == NULL ? 0 : st->merged->stack_len;
     -+	struct reader **cur = stack_copy_readers(st, cur_len);
     ++	struct reftable_reader **cur = stack_copy_readers(st, cur_len);
      +	int err = 0;
      +	int names_len = names_length(names);
     -+	struct reader **new_tables =
     -+		malloc(sizeof(struct reader *) * names_len);
     ++	struct reftable_reader **new_tables =
     ++		reftable_malloc(sizeof(struct reftable_reader *) * names_len);
      +	int new_tables_len = 0;
     -+	struct merged_table *new_merged = NULL;
     ++	struct reftable_merged_table *new_merged = NULL;
      +
      +	struct slice table_path = { 0 };
      +
      +	while (*names) {
     -+		struct reader *rd = NULL;
     ++		struct reftable_reader *rd = NULL;
      +		char *name = *names++;
      +
      +		/* this is linear; we assume compaction keeps the number of
     @@ -4661,18 +4934,18 @@
      +		}
      +
      +		if (rd == NULL) {
     -+			struct block_source src = { 0 };
     ++			struct reftable_block_source src = { 0 };
      +			slice_set_string(&table_path, st->reftable_dir);
      +			slice_append_string(&table_path, "/");
      +			slice_append_string(&table_path, name);
      +
     -+			err = block_source_from_file(
     ++			err = reftable_block_source_from_file(
      +				&src, slice_as_string(&table_path));
      +			if (err < 0) {
      +				goto exit;
      +			}
      +
     -+			err = new_reader(&rd, src, name);
     ++			err = reftable_new_reader(&rd, src, name);
      +			if (err < 0) {
      +				goto exit;
      +			}
     @@ -4682,8 +4955,8 @@
      +	}
      +
      +	/* success! */
     -+	err = new_merged_table(&new_merged, new_tables, new_tables_len,
     -+			       st->config.hash_id);
     ++	err = reftable_new_merged_table(&new_merged, new_tables, new_tables_len,
     ++					st->config.hash_id);
      +	if (err < 0) {
      +		goto exit;
      +	}
     @@ -4692,7 +4965,7 @@
      +	new_tables_len = 0;
      +	if (st->merged != NULL) {
      +		merged_table_clear(st->merged);
     -+		merged_table_free(st->merged);
     ++		reftable_merged_table_free(st->merged);
      +	}
      +	st->merged = new_merged;
      +
     @@ -4701,20 +4974,20 @@
      +		for (i = 0; i < cur_len; i++) {
      +			if (cur[i] != NULL) {
      +				reader_close(cur[i]);
     -+				reader_free(cur[i]);
     ++				reftable_reader_free(cur[i]);
      +			}
      +		}
      +	}
      +exit:
     -+	free(slice_yield(&table_path));
     ++	reftable_free(slice_yield(&table_path));
      +	{
      +		int i = 0;
      +		for (i = 0; i < new_tables_len; i++) {
      +			reader_close(new_tables[i]);
      +		}
      +	}
     -+	free(new_tables);
     -+	free(cur);
     ++	reftable_free(new_tables);
     ++	reftable_free(cur);
      +	return err;
      +}
      +
     @@ -4731,7 +5004,8 @@
      +	return udiff;
      +}
      +
     -+static int stack_reload_maybe_reuse(struct stack *st, bool reuse_open)
     ++static int reftable_stack_reload_maybe_reuse(struct reftable_stack *st,
     ++					     bool reuse_open)
      +{
      +	struct timeval deadline = { 0 };
      +	int err = gettimeofday(&deadline, NULL);
     @@ -4763,7 +5037,7 @@
      +			free_names(names);
      +			return err;
      +		}
     -+		err = stack_reload_once(st, names, reuse_open);
     ++		err = reftable_stack_reload_once(st, names, reuse_open);
      +		if (err == 0) {
      +			free_names(names);
      +			break;
     @@ -4794,15 +5068,15 @@
      +	return 0;
      +}
      +
     -+int stack_reload(struct stack *st)
     ++int reftable_stack_reload(struct reftable_stack *st)
      +{
     -+	return stack_reload_maybe_reuse(st, true);
     ++	return reftable_stack_reload_maybe_reuse(st, true);
      +}
      +
      +/* -1 = error
      + 0 = up to date
      + 1 = changed. */
     -+static int stack_uptodate(struct stack *st)
     ++static int stack_uptodate(struct reftable_stack *st)
      +{
      +	char **names = NULL;
      +	int err = read_lines(st->list_file, &names);
     @@ -4833,18 +5107,19 @@
      +	return err;
      +}
      +
     -+int stack_add(struct stack *st, int (*write)(struct writer *wr, void *arg),
     -+	      void *arg)
     ++int reftable_stack_add(struct reftable_stack *st,
     ++		       int (*write)(struct reftable_writer *wr, void *arg),
     ++		       void *arg)
      +{
      +	int err = stack_try_add(st, write, arg);
      +	if (err < 0) {
      +		if (err == LOCK_ERROR) {
     -+			err = stack_reload(st);
     ++			err = reftable_stack_reload(st);
      +		}
      +		return err;
      +	}
      +
     -+	return stack_auto_compact(st);
     ++	return reftable_stack_auto_compact(st);
      +}
      +
      +static void format_name(struct slice *dest, uint64_t min, uint64_t max)
     @@ -4854,34 +5129,35 @@
      +	slice_set_string(dest, buf);
      +}
      +
     -+int stack_try_add(struct stack *st,
     -+		  int (*write_table)(struct writer *wr, void *arg), void *arg)
     ++struct reftable_addition {
     ++	int lock_file_fd;
     ++	struct slice lock_file_name;
     ++	struct reftable_stack *stack;
     ++	char **names;
     ++	char **new_tables;
     ++	int new_tables_len;
     ++	uint64_t next_update_index;
     ++};
     ++
     ++static int reftable_stack_init_addition(struct reftable_addition *add,
     ++					struct reftable_stack *st)
      +{
     -+	struct slice lock_name = { 0 };
     -+	struct slice temp_tab_name = { 0 };
     -+	struct slice tab_name = { 0 };
     -+	struct slice next_name = { 0 };
     -+	struct slice table_list = { 0 };
     -+	struct writer *wr = NULL;
      +	int err = 0;
     -+	int tab_fd = 0;
     -+	int lock_fd = 0;
     -+	uint64_t next_update_index = 0;
     ++	add->stack = st;
      +
     -+	slice_set_string(&lock_name, st->list_file);
     -+	slice_append_string(&lock_name, ".lock");
     ++	slice_set_string(&add->lock_file_name, st->list_file);
     ++	slice_append_string(&add->lock_file_name, ".lock");
      +
     -+	lock_fd = open(slice_as_string(&lock_name), O_EXCL | O_CREAT | O_WRONLY,
     -+		       0644);
     -+	if (lock_fd < 0) {
     ++	add->lock_file_fd = open(slice_as_string(&add->lock_file_name),
     ++				 O_EXCL | O_CREAT | O_WRONLY, 0644);
     ++	if (add->lock_file_fd < 0) {
      +		if (errno == EEXIST) {
      +			err = LOCK_ERROR;
     -+			goto exit;
     ++		} else {
     ++			err = IO_ERROR;
      +		}
     -+		err = IO_ERROR;
      +		goto exit;
      +	}
     -+
      +	err = stack_uptodate(st);
      +	if (err < 0) {
      +		goto exit;
     @@ -4892,29 +5168,160 @@
      +		goto exit;
      +	}
      +
     -+	next_update_index = stack_next_update_index(st);
     ++	add->next_update_index = reftable_stack_next_update_index(st);
     ++exit:
     ++	if (err) {
     ++		reftable_addition_close(add);
     ++	}
     ++	return err;
     ++}
     ++
     ++void reftable_addition_close(struct reftable_addition *add)
     ++{
     ++	int i = 0;
     ++	struct slice nm = {};
     ++	for (i = 0; i < add->new_tables_len; i++) {
     ++		slice_set_string(&nm, add->stack->list_file);
     ++		slice_append_string(&nm, "/");
     ++		slice_append_string(&nm, add->new_tables[i]);
     ++		unlink(slice_as_string(&nm));
     ++
     ++		reftable_free(add->new_tables[i]);
     ++		add->new_tables[i] = NULL;
     ++	}
     ++	reftable_free(add->new_tables);
     ++	add->new_tables = NULL;
     ++	add->new_tables_len = 0;
     ++
     ++	if (add->lock_file_fd > 0) {
     ++		close(add->lock_file_fd);
     ++		add->lock_file_fd = 0;
     ++	}
     ++	if (add->lock_file_name.len > 0) {
     ++		unlink(slice_as_string(&add->lock_file_name));
     ++		reftable_free(slice_yield(&add->lock_file_name));
     ++	}
     ++
     ++	free_names(add->names);
     ++	add->names = NULL;
     ++}
     ++
     ++int reftable_addition_commit(struct reftable_addition *add)
     ++{
     ++	struct slice table_list = { 0 };
     ++	int i = 0;
     ++	int err = 0;
     ++	if (add->new_tables_len == 0) {
     ++		goto exit;
     ++	}
     ++
     ++	for (i = 0; i < add->stack->merged->stack_len; i++) {
     ++		slice_append_string(&table_list,
     ++				    add->stack->merged->stack[i]->name);
     ++		slice_append_string(&table_list, "\n");
     ++	}
     ++	for (i = 0; i < add->new_tables_len; i++) {
     ++		slice_append_string(&table_list, add->new_tables[i]);
     ++		slice_append_string(&table_list, "\n");
     ++	}
     ++
     ++	err = write(add->lock_file_fd, table_list.buf, table_list.len);
     ++	free(slice_yield(&table_list));
     ++	if (err < 0) {
     ++		err = IO_ERROR;
     ++		goto exit;
     ++	}
     ++
     ++	err = close(add->lock_file_fd);
     ++	add->lock_file_fd = 0;
     ++	if (err < 0) {
     ++		err = IO_ERROR;
     ++		goto exit;
     ++	}
     ++
     ++	err = rename(slice_as_string(&add->lock_file_name),
     ++		     add->stack->list_file);
     ++	if (err < 0) {
     ++		err = IO_ERROR;
     ++		goto exit;
     ++	}
     ++
     ++	err = reftable_stack_reload(add->stack);
     ++
     ++exit:
     ++	reftable_addition_close(add);
     ++	return err;
     ++}
     ++
     ++int reftable_stack_new_addition(struct reftable_addition **dest,
     ++				struct reftable_stack *st)
     ++{
     ++	int err = 0;
     ++	*dest = reftable_malloc(sizeof(**dest));
     ++	err = reftable_stack_init_addition(*dest, st);
     ++	if (err) {
     ++		reftable_free(*dest);
     ++		*dest = NULL;
     ++	}
     ++	return err;
     ++}
     ++
     ++int stack_try_add(struct reftable_stack *st,
     ++		  int (*write_table)(struct reftable_writer *wr, void *arg),
     ++		  void *arg)
     ++{
     ++	struct reftable_addition add = { 0 };
     ++	int err = reftable_stack_init_addition(&add, st);
     ++	if (err < 0) {
     ++		goto exit;
     ++	}
     ++
     ++	err = reftable_addition_add(&add, write_table, arg);
     ++	if (err < 0) {
     ++		goto exit;
     ++	}
     ++
     ++	err = reftable_addition_commit(&add);
     ++exit:
     ++	reftable_addition_close(&add);
     ++	return err;
     ++}
     ++
     ++int reftable_addition_add(struct reftable_addition *add,
     ++			  int (*write_table)(struct reftable_writer *wr,
     ++					     void *arg),
     ++			  void *arg)
     ++{
     ++	struct slice temp_tab_file_name = { 0 };
     ++	struct slice tab_file_name = { 0 };
     ++	struct slice next_name = { 0 };
     ++	struct reftable_writer *wr = NULL;
     ++	int err = 0;
     ++	int tab_fd = 0;
     ++	uint64_t next_update_index = 0;
      +
      +	slice_resize(&next_name, 0);
      +	format_name(&next_name, next_update_index, next_update_index);
      +
     -+	slice_set_string(&temp_tab_name, st->reftable_dir);
     -+	slice_append_string(&temp_tab_name, "/");
     -+	slice_append(&temp_tab_name, next_name);
     -+	slice_append_string(&temp_tab_name, ".temp.XXXXXX");
     ++	slice_set_string(&temp_tab_file_name, add->stack->reftable_dir);
     ++	slice_append_string(&temp_tab_file_name, "/");
     ++	slice_append(&temp_tab_file_name, next_name);
     ++	slice_append_string(&temp_tab_file_name, ".temp.XXXXXX");
      +
     -+	tab_fd = mkstemp((char *)slice_as_string(&temp_tab_name));
     ++	tab_fd = mkstemp((char *)slice_as_string(&temp_tab_file_name));
      +	if (tab_fd < 0) {
      +		err = IO_ERROR;
      +		goto exit;
      +	}
      +
     -+	wr = new_writer(fd_writer, &tab_fd, &st->config);
     ++	wr = reftable_new_writer(reftable_fd_write, &tab_fd,
     ++				 &add->stack->config);
      +	err = write_table(wr, arg);
      +	if (err < 0) {
      +		goto exit;
      +	}
      +
     -+	err = writer_close(wr);
     ++	err = reftable_writer_close(wr);
      +	if (err == EMPTY_TABLE_ERROR) {
      +		err = 0;
      +		goto exit;
     @@ -4935,98 +5342,64 @@
      +		goto exit;
      +	}
      +
     -+	{
     -+		int i = 0;
     -+		for (i = 0; i < st->merged->stack_len; i++) {
     -+			slice_append_string(&table_list,
     -+					    st->merged->stack[i]->name);
     -+			slice_append_string(&table_list, "\n");
     -+		}
     -+	}
     -+
      +	format_name(&next_name, wr->min_update_index, wr->max_update_index);
      +	slice_append_string(&next_name, ".ref");
     -+	slice_append(&table_list, next_name);
     -+	slice_append_string(&table_list, "\n");
      +
     -+	slice_set_string(&tab_name, st->reftable_dir);
     -+	slice_append_string(&tab_name, "/");
     -+	slice_append(&tab_name, next_name);
     ++	slice_set_string(&tab_file_name, add->stack->reftable_dir);
     ++	slice_append_string(&tab_file_name, "/");
     ++	slice_append(&tab_file_name, next_name);
      +
     -+	err = rename(slice_as_string(&temp_tab_name),
     -+		     slice_as_string(&tab_name));
     ++	err = rename(slice_as_string(&temp_tab_file_name),
     ++		     slice_as_string(&tab_file_name));
      +	if (err < 0) {
      +		err = IO_ERROR;
      +		goto exit;
      +	}
     -+	free(slice_yield(&temp_tab_name));
      +
     -+	err = write(lock_fd, table_list.buf, table_list.len);
     -+	if (err < 0) {
     -+		err = IO_ERROR;
     -+		goto exit;
     -+	}
     -+	err = close(lock_fd);
     -+	lock_fd = 0;
     -+	if (err < 0) {
     -+		unlink(slice_as_string(&tab_name));
     -+		err = IO_ERROR;
     -+		goto exit;
     -+	}
     -+
     -+	err = rename(slice_as_string(&lock_name), st->list_file);
     -+	if (err < 0) {
     -+		unlink(slice_as_string(&tab_name));
     -+		err = IO_ERROR;
     -+		goto exit;
     -+	}
     -+
     -+	err = stack_reload(st);
     ++	add->new_tables = reftable_realloc(add->new_tables,
     ++					   sizeof(*add->new_tables) *
     ++						   (add->new_tables_len + 1));
     ++	add->new_tables[add->new_tables_len] = slice_to_string(next_name);
     ++	add->new_tables_len++;
      +exit:
      +	if (tab_fd > 0) {
      +		close(tab_fd);
      +		tab_fd = 0;
      +	}
     -+	if (temp_tab_name.len > 0) {
     -+		unlink(slice_as_string(&temp_tab_name));
     -+	}
     -+	unlink(slice_as_string(&lock_name));
     -+
     -+	if (lock_fd > 0) {
     -+		close(lock_fd);
     -+		lock_fd = 0;
     ++	if (temp_tab_file_name.len > 0) {
     ++		unlink(slice_as_string(&temp_tab_file_name));
      +	}
      +
     -+	free(slice_yield(&lock_name));
     -+	free(slice_yield(&temp_tab_name));
     -+	free(slice_yield(&tab_name));
     -+	free(slice_yield(&next_name));
     -+	free(slice_yield(&table_list));
     -+	writer_free(wr);
     ++	reftable_free(slice_yield(&temp_tab_file_name));
     ++	reftable_free(slice_yield(&tab_file_name));
     ++	reftable_free(slice_yield(&next_name));
     ++	reftable_writer_free(wr);
      +	return err;
      +}
      +
     -+uint64_t stack_next_update_index(struct stack *st)
     ++uint64_t reftable_stack_next_update_index(struct reftable_stack *st)
      +{
      +	int sz = st->merged->stack_len;
      +	if (sz > 0) {
     -+		return reader_max_update_index(st->merged->stack[sz - 1]) + 1;
     ++		return reftable_reader_max_update_index(
     ++			       st->merged->stack[sz - 1]) +
     ++		       1;
      +	}
      +	return 1;
      +}
      +
     -+static int stack_compact_locked(struct stack *st, int first, int last,
     ++static int stack_compact_locked(struct reftable_stack *st, int first, int last,
      +				struct slice *temp_tab,
     -+				struct log_expiry_config *config)
     ++				struct reftable_log_expiry_config *config)
      +{
      +	struct slice next_name = { 0 };
      +	int tab_fd = -1;
     -+	struct writer *wr = NULL;
     ++	struct reftable_writer *wr = NULL;
      +	int err = 0;
      +
      +	format_name(&next_name,
     -+		    reader_min_update_index(st->merged->stack[first]),
     -+		    reader_max_update_index(st->merged->stack[first]));
     ++		    reftable_reader_min_update_index(st->merged->stack[first]),
     ++		    reftable_reader_max_update_index(st->merged->stack[first]));
      +
      +	slice_set_string(temp_tab, st->reftable_dir);
      +	slice_append_string(temp_tab, "/");
     @@ -5034,17 +5407,17 @@
      +	slice_append_string(temp_tab, ".temp.XXXXXX");
      +
      +	tab_fd = mkstemp((char *)slice_as_string(temp_tab));
     -+	wr = new_writer(fd_writer, &tab_fd, &st->config);
     ++	wr = reftable_new_writer(reftable_fd_write, &tab_fd, &st->config);
      +
      +	err = stack_write_compact(st, wr, first, last, config);
      +	if (err < 0) {
      +		goto exit;
      +	}
     -+	err = writer_close(wr);
     ++	err = reftable_writer_close(wr);
      +	if (err < 0) {
      +		goto exit;
      +	}
     -+	writer_free(wr);
     ++	reftable_writer_free(wr);
      +
      +	err = close(tab_fd);
      +	tab_fd = 0;
     @@ -5056,46 +5429,49 @@
      +	}
      +	if (err != 0 && temp_tab->len > 0) {
      +		unlink(slice_as_string(temp_tab));
     -+		free(slice_yield(temp_tab));
     ++		reftable_free(slice_yield(temp_tab));
      +	}
     -+	free(slice_yield(&next_name));
     ++	reftable_free(slice_yield(&next_name));
      +	return err;
      +}
      +
     -+int stack_write_compact(struct stack *st, struct writer *wr, int first,
     -+			int last, struct log_expiry_config *config)
     ++int stack_write_compact(struct reftable_stack *st, struct reftable_writer *wr,
     ++			int first, int last,
     ++			struct reftable_log_expiry_config *config)
      +{
      +	int subtabs_len = last - first + 1;
     -+	struct reader **subtabs =
     -+		calloc(sizeof(struct reader *), last - first + 1);
     -+	struct merged_table *mt = NULL;
     ++	struct reftable_reader **subtabs = reftable_calloc(
     ++		sizeof(struct reftable_reader *) * (last - first + 1));
     ++	struct reftable_merged_table *mt = NULL;
      +	int err = 0;
     -+	struct iterator it = { 0 };
     -+	struct ref_record ref = { 0 };
     -+	struct log_record log = { 0 };
     ++	struct reftable_iterator it = { 0 };
     ++	struct reftable_ref_record ref = { 0 };
     ++	struct reftable_log_record log = { 0 };
      +
      +	int i = 0, j = 0;
      +	for (i = first, j = 0; i <= last; i++) {
     -+		struct reader *t = st->merged->stack[i];
     ++		struct reftable_reader *t = st->merged->stack[i];
      +		subtabs[j++] = t;
      +		st->stats.bytes += t->size;
      +	}
     -+	writer_set_limits(wr, st->merged->stack[first]->min_update_index,
     -+			  st->merged->stack[last]->max_update_index);
     ++	reftable_writer_set_limits(wr,
     ++				   st->merged->stack[first]->min_update_index,
     ++				   st->merged->stack[last]->max_update_index);
      +
     -+	err = new_merged_table(&mt, subtabs, subtabs_len, st->config.hash_id);
     ++	err = reftable_new_merged_table(&mt, subtabs, subtabs_len,
     ++					st->config.hash_id);
      +	if (err < 0) {
     -+		free(subtabs);
     ++		reftable_free(subtabs);
      +		goto exit;
      +	}
      +
     -+	err = merged_table_seek_ref(mt, &it, "");
     ++	err = reftable_merged_table_seek_ref(mt, &it, "");
      +	if (err < 0) {
      +		goto exit;
      +	}
      +
      +	while (true) {
     -+		err = iterator_next_ref(it, &ref);
     ++		err = reftable_iterator_next_ref(it, &ref);
      +		if (err > 0) {
      +			err = 0;
      +			break;
     @@ -5103,23 +5479,23 @@
      +		if (err < 0) {
      +			break;
      +		}
     -+		if (first == 0 && ref_record_is_deletion(&ref)) {
     ++		if (first == 0 && reftable_ref_record_is_deletion(&ref)) {
      +			continue;
      +		}
      +
     -+		err = writer_add_ref(wr, &ref);
     ++		err = reftable_writer_add_ref(wr, &ref);
      +		if (err < 0) {
      +			break;
      +		}
      +	}
      +
     -+	err = merged_table_seek_log(mt, &it, "");
     ++	err = reftable_merged_table_seek_log(mt, &it, "");
      +	if (err < 0) {
      +		goto exit;
      +	}
      +
      +	while (true) {
     -+		err = iterator_next_log(it, &log);
     ++		err = reftable_iterator_next_log(it, &log);
      +		if (err > 0) {
      +			err = 0;
      +			break;
     @@ -5127,7 +5503,7 @@
      +		if (err < 0) {
      +			break;
      +		}
     -+		if (first == 0 && log_record_is_deletion(&log)) {
     ++		if (first == 0 && reftable_log_record_is_deletion(&log)) {
      +			continue;
      +		}
      +
     @@ -5143,28 +5519,28 @@
      +			continue;
      +		}
      +
     -+		err = writer_add_log(wr, &log);
     ++		err = reftable_writer_add_log(wr, &log);
      +		if (err < 0) {
      +			break;
      +		}
      +	}
      +
      +exit:
     -+	iterator_destroy(&it);
     ++	reftable_iterator_destroy(&it);
      +	if (mt != NULL) {
      +		merged_table_clear(mt);
     -+		merged_table_free(mt);
     ++		reftable_merged_table_free(mt);
      +	}
     -+	ref_record_clear(&ref);
     ++	reftable_ref_record_clear(&ref);
      +
      +	return err;
      +}
      +
      +/* <  0: error. 0 == OK, > 0 attempt failed; could retry. */
     -+static int stack_compact_range(struct stack *st, int first, int last,
     -+			       struct log_expiry_config *expiry)
     ++static int stack_compact_range(struct reftable_stack *st, int first, int last,
     ++			       struct reftable_log_expiry_config *expiry)
      +{
     -+	struct slice temp_tab_name = { 0 };
     ++	struct slice temp_tab_file_name = { 0 };
      +	struct slice new_table_name = { 0 };
      +	struct slice lock_file_name = { 0 };
      +	struct slice ref_list_contents = { 0 };
     @@ -5173,8 +5549,10 @@
      +	bool have_lock = false;
      +	int lock_file_fd = 0;
      +	int compact_count = last - first + 1;
     -+	char **delete_on_success = calloc(sizeof(char *), compact_count + 1);
     -+	char **subtable_locks = calloc(sizeof(char *), compact_count + 1);
     ++	char **delete_on_success =
     ++		reftable_calloc(sizeof(char *) * (compact_count + 1));
     ++	char **subtable_locks =
     ++		reftable_calloc(sizeof(char *) * (compact_count + 1));
      +	int i = 0;
      +	int j = 0;
      +	bool is_empty_table = false;
     @@ -5206,14 +5584,14 @@
      +	}
      +
      +	for (i = first, j = 0; i <= last; i++) {
     -+		struct slice subtab_name = { 0 };
     ++		struct slice subtab_file_name = { 0 };
      +		struct slice subtab_lock = { 0 };
     -+		slice_set_string(&subtab_name, st->reftable_dir);
     -+		slice_append_string(&subtab_name, "/");
     -+		slice_append_string(&subtab_name,
     ++		slice_set_string(&subtab_file_name, st->reftable_dir);
     ++		slice_append_string(&subtab_file_name, "/");
     ++		slice_append_string(&subtab_file_name,
      +				    reader_name(st->merged->stack[i]));
      +
     -+		slice_copy(&subtab_lock, subtab_name);
     ++		slice_copy(&subtab_lock, subtab_file_name);
      +		slice_append_string(&subtab_lock, ".lock");
      +
      +		{
     @@ -5231,7 +5609,8 @@
      +		}
      +
      +		subtable_locks[j] = (char *)slice_as_string(&subtab_lock);
     -+		delete_on_success[j] = (char *)slice_as_string(&subtab_name);
     ++		delete_on_success[j] =
     ++			(char *)slice_as_string(&subtab_file_name);
      +		j++;
      +
      +		if (err != 0) {
     @@ -5245,7 +5624,8 @@
      +	}
      +	have_lock = false;
      +
     -+	err = stack_compact_locked(st, first, last, &temp_tab_name, expiry);
     ++	err = stack_compact_locked(st, first, last, &temp_tab_file_name,
     ++				   expiry);
      +	/* Compaction + tombstones can create an empty table out of non-empty
      +	 * tables. */
      +	is_empty_table = (err == EMPTY_TABLE_ERROR);
     @@ -5278,7 +5658,7 @@
      +	slice_append(&new_table_path, new_table_name);
      +
      +	if (!is_empty_table) {
     -+		err = rename(slice_as_string(&temp_tab_name),
     ++		err = rename(slice_as_string(&temp_tab_file_name),
      +			     slice_as_string(&new_table_path));
      +		if (err < 0) {
      +			goto exit;
     @@ -5329,7 +5709,7 @@
      +		}
      +	}
      +
     -+	err = stack_reload_maybe_reuse(st, first < last);
     ++	err = reftable_stack_reload_maybe_reuse(st, first < last);
      +exit:
      +	free_names(delete_on_success);
      +	{
     @@ -5347,21 +5727,23 @@
      +	if (have_lock) {
      +		unlink(slice_as_string(&lock_file_name));
      +	}
     -+	free(slice_yield(&new_table_name));
     -+	free(slice_yield(&new_table_path));
     -+	free(slice_yield(&ref_list_contents));
     -+	free(slice_yield(&temp_tab_name));
     -+	free(slice_yield(&lock_file_name));
     ++	reftable_free(slice_yield(&new_table_name));
     ++	reftable_free(slice_yield(&new_table_path));
     ++	reftable_free(slice_yield(&ref_list_contents));
     ++	reftable_free(slice_yield(&temp_tab_file_name));
     ++	reftable_free(slice_yield(&lock_file_name));
      +	return err;
      +}
      +
     -+int stack_compact_all(struct stack *st, struct log_expiry_config *config)
     ++int reftable_stack_compact_all(struct reftable_stack *st,
     ++			       struct reftable_log_expiry_config *config)
      +{
      +	return stack_compact_range(st, 0, st->merged->stack_len - 1, config);
      +}
      +
     -+static int stack_compact_range_stats(struct stack *st, int first, int last,
     -+				     struct log_expiry_config *config)
     ++static int stack_compact_range_stats(struct reftable_stack *st, int first,
     ++				     int last,
     ++				     struct reftable_log_expiry_config *config)
      +{
      +	int err = stack_compact_range(st, first, last, config);
      +	if (err > 0) {
     @@ -5387,7 +5769,7 @@
      +
      +struct segment *sizes_to_segments(int *seglen, uint64_t *sizes, int n)
      +{
     -+	struct segment *segs = calloc(sizeof(struct segment), n);
     ++	struct segment *segs = reftable_calloc(sizeof(struct segment) * n);
      +	int next = 0;
      +	struct segment cur = { 0 };
      +	int i = 0;
     @@ -5406,8 +5788,9 @@
      +		cur.end = i + 1;
      +		cur.bytes += sizes[i];
      +	}
     -+
     -+	segs[next++] = cur;
     ++	if (next > 0) {
     ++		segs[next++] = cur;
     ++	}
      +	*seglen = next;
      +	return segs;
      +}
     @@ -5440,13 +5823,14 @@
      +		min_seg.bytes += sizes[prev];
      +	}
      +
     -+	free(segs);
     ++	reftable_free(segs);
      +	return min_seg;
      +}
      +
     -+static uint64_t *stack_table_sizes_for_compaction(struct stack *st)
     ++static uint64_t *stack_table_sizes_for_compaction(struct reftable_stack *st)
      +{
     -+	uint64_t *sizes = calloc(sizeof(uint64_t), st->merged->stack_len);
     ++	uint64_t *sizes =
     ++		reftable_calloc(sizeof(uint64_t) * st->merged->stack_len);
      +	int i = 0;
      +	for (i = 0; i < st->merged->stack_len; i++) {
      +		/* overhead is 24 + 68 = 92. */
     @@ -5455,12 +5839,12 @@
      +	return sizes;
      +}
      +
     -+int stack_auto_compact(struct stack *st)
     ++int reftable_stack_auto_compact(struct reftable_stack *st)
      +{
      +	uint64_t *sizes = stack_table_sizes_for_compaction(st);
      +	struct segment seg =
      +		suggest_compaction_segment(sizes, st->merged->stack_len);
     -+	free(sizes);
     ++	reftable_free(sizes);
      +	if (segment_size(&seg) > 0) {
      +		return stack_compact_range_stats(st, seg.start, seg.end - 1,
      +						 NULL);
     @@ -5469,58 +5853,61 @@
      +	return 0;
      +}
      +
     -+struct compaction_stats *stack_compaction_stats(struct stack *st)
     ++struct reftable_compaction_stats *
     ++reftable_stack_compaction_stats(struct reftable_stack *st)
      +{
      +	return &st->stats;
      +}
      +
     -+int stack_read_ref(struct stack *st, const char *refname,
     -+		   struct ref_record *ref)
     ++int reftable_stack_read_ref(struct reftable_stack *st, const char *refname,
     ++			    struct reftable_ref_record *ref)
      +{
     -+	struct iterator it = { 0 };
     -+	struct merged_table *mt = stack_merged_table(st);
     -+	int err = merged_table_seek_ref(mt, &it, refname);
     ++	struct reftable_iterator it = { 0 };
     ++	struct reftable_merged_table *mt = reftable_stack_merged_table(st);
     ++	int err = reftable_merged_table_seek_ref(mt, &it, refname);
      +	if (err) {
      +		goto exit;
      +	}
      +
     -+	err = iterator_next_ref(it, ref);
     ++	err = reftable_iterator_next_ref(it, ref);
      +	if (err) {
      +		goto exit;
      +	}
      +
     -+	if (strcmp(ref->ref_name, refname) || ref_record_is_deletion(ref)) {
     ++	if (strcmp(ref->ref_name, refname) ||
     ++	    reftable_ref_record_is_deletion(ref)) {
      +		err = 1;
      +		goto exit;
      +	}
      +
      +exit:
     -+	iterator_destroy(&it);
     ++	reftable_iterator_destroy(&it);
      +	return err;
      +}
      +
     -+int stack_read_log(struct stack *st, const char *refname,
     -+		   struct log_record *log)
     ++int reftable_stack_read_log(struct reftable_stack *st, const char *refname,
     ++			    struct reftable_log_record *log)
      +{
     -+	struct iterator it = { 0 };
     -+	struct merged_table *mt = stack_merged_table(st);
     -+	int err = merged_table_seek_log(mt, &it, refname);
     ++	struct reftable_iterator it = { 0 };
     ++	struct reftable_merged_table *mt = reftable_stack_merged_table(st);
     ++	int err = reftable_merged_table_seek_log(mt, &it, refname);
      +	if (err) {
      +		goto exit;
      +	}
      +
     -+	err = iterator_next_log(it, log);
     ++	err = reftable_iterator_next_log(it, log);
      +	if (err) {
      +		goto exit;
      +	}
      +
     -+	if (strcmp(log->ref_name, refname) || log_record_is_deletion(log)) {
     ++	if (strcmp(log->ref_name, refname) ||
     ++	    reftable_log_record_is_deletion(log)) {
      +		err = 1;
      +		goto exit;
      +	}
      +
      +exit:
     -+	iterator_destroy(&it);
     ++	reftable_iterator_destroy(&it);
      +	return err;
      +}
      
     @@ -5542,21 +5929,23 @@
      +
      +#include "reftable.h"
      +
     -+struct stack {
     ++struct reftable_stack {
      +	char *list_file;
      +	char *reftable_dir;
      +
     -+	struct write_options config;
     ++	struct reftable_write_options config;
      +
     -+	struct merged_table *merged;
     -+	struct compaction_stats stats;
     ++	struct reftable_merged_table *merged;
     ++	struct reftable_compaction_stats stats;
      +};
      +
      +int read_lines(const char *filename, char ***lines);
     -+int stack_try_add(struct stack *st,
     -+		  int (*write_table)(struct writer *wr, void *arg), void *arg);
     -+int stack_write_compact(struct stack *st, struct writer *wr, int first,
     -+			int last, struct log_expiry_config *config);
     ++int stack_try_add(struct reftable_stack *st,
     ++		  int (*write_table)(struct reftable_writer *wr, void *arg),
     ++		  void *arg);
     ++int stack_write_compact(struct reftable_stack *st, struct reftable_writer *wr,
     ++			int first, int last,
     ++			struct reftable_log_expiry_config *config);
      +int fastlog2(uint64_t sz);
      +
      +struct segment {
     @@ -5644,6 +6033,7 @@
      +
      +#include "tree.h"
      +
     ++#include "basics.h"
      +#include "system.h"
      +
      +struct tree_node *tree_search(void *key, struct tree_node **rootp,
     @@ -5655,7 +6045,7 @@
      +			return NULL;
      +		} else {
      +			struct tree_node *n =
     -+				calloc(sizeof(struct tree_node), 1);
     ++				reftable_calloc(sizeof(struct tree_node));
      +			n->key = key;
      +			*rootp = n;
      +			return *rootp;
     @@ -5698,7 +6088,7 @@
      +	if (t->right != NULL) {
      +		tree_free(t->right);
      +	}
     -+	free(t);
     ++	reftable_free(t);
      +}
      
       diff --git a/reftable/tree.h b/reftable/tree.h
     @@ -5743,6 +6133,7 @@
      +((cd reftable-repo && git fetch origin && git checkout origin/master ) ||
      +git clone https://github.com/google/reftable reftable-repo) && \
      +cp reftable-repo/c/*.[ch] reftable/ && \
     ++cp reftable-repo/c/include/*.[ch] reftable/ && \
      +cp reftable-repo/LICENSE reftable/ &&
      +git --git-dir reftable-repo/.git show --no-patch origin/master \
      +> reftable/VERSION && \
     @@ -5773,7 +6164,8 @@
      +#include "reftable.h"
      +#include "tree.h"
      +
     -+static struct block_stats *writer_block_stats(struct writer *w, byte typ)
     ++static struct reftable_block_stats *
     ++writer_reftable_block_stats(struct reftable_writer *w, byte typ)
      +{
      +	switch (typ) {
      +	case 'r':
     @@ -5791,18 +6183,19 @@
      +
      +/* write data, queuing the padding for the next write. Returns negative for
      + * error. */
     -+static int padded_write(struct writer *w, byte *data, size_t len, int padding)
     ++static int padded_write(struct reftable_writer *w, byte *data, size_t len,
     ++			int padding)
      +{
      +	int n = 0;
      +	if (w->pending_padding > 0) {
     -+		byte *zeroed = calloc(w->pending_padding, 1);
     ++		byte *zeroed = reftable_calloc(w->pending_padding);
      +		int n = w->write(w->write_arg, zeroed, w->pending_padding);
      +		if (n < 0) {
      +			return n;
      +		}
      +
      +		w->pending_padding = 0;
     -+		free(zeroed);
     ++		reftable_free(zeroed);
      +	}
      +
      +	w->pending_padding = padding;
     @@ -5814,7 +6207,7 @@
      +	return 0;
      +}
      +
     -+static void options_set_defaults(struct write_options *opts)
     ++static void options_set_defaults(struct reftable_write_options *opts)
      +{
      +	if (opts->restart_interval == 0) {
      +		opts->restart_interval = 16;
     @@ -5828,25 +6221,31 @@
      +	}
      +}
      +
     -+static int writer_write_header(struct writer *w, byte *dest)
     ++static int writer_version(struct reftable_writer *w)
     ++{
     ++	return (w->opts.hash_id == 0 || w->opts.hash_id == SHA1_ID) ? 1 : 2;
     ++}
     ++
     ++static int writer_write_header(struct reftable_writer *w, byte *dest)
      +{
      +	memcpy((char *)dest, "REFT", 4);
      +
     -+	/* DO NOT SUBMIT.  This has not been encoded in the standard yet. */
     -+	dest[4] = (hash_size(w->opts.hash_id) == SHA1_SIZE) ? 1 : 2; /* version
     -+								      */
     ++	dest[4] = writer_version(w);
      +
      +	put_be24(dest + 5, w->opts.block_size);
      +	put_be64(dest + 8, w->min_update_index);
      +	put_be64(dest + 16, w->max_update_index);
     -+	return 24;
     ++	if (writer_version(w) == 2) {
     ++		put_be32(dest + 24, w->opts.hash_id);
     ++	}
     ++	return header_size(writer_version(w));
      +}
      +
     -+static void writer_reinit_block_writer(struct writer *w, byte typ)
     ++static void writer_reinit_block_writer(struct reftable_writer *w, byte typ)
      +{
      +	int block_start = 0;
      +	if (w->next == 0) {
     -+		block_start = HEADER_SIZE;
     ++		block_start = header_size(writer_version(w));
      +	}
      +
      +	block_writer_init(&w->block_writer_data, typ, w->block,
     @@ -5856,16 +6255,18 @@
      +	w->block_writer->restart_interval = w->opts.restart_interval;
      +}
      +
     -+struct writer *new_writer(int (*writer_func)(void *, byte *, int),
     -+			  void *writer_arg, struct write_options *opts)
     ++struct reftable_writer *
     ++reftable_new_writer(int (*writer_func)(void *, byte *, int), void *writer_arg,
     ++		    struct reftable_write_options *opts)
      +{
     -+	struct writer *wp = calloc(sizeof(struct writer), 1);
     ++	struct reftable_writer *wp =
     ++		reftable_calloc(sizeof(struct reftable_writer));
      +	options_set_defaults(opts);
      +	if (opts->block_size >= (1 << 24)) {
      +		/* TODO - error return? */
      +		abort();
      +	}
     -+	wp->block = calloc(opts->block_size, 1);
     ++	wp->block = reftable_calloc(opts->block_size);
      +	wp->write = writer_func;
      +	wp->write_arg = writer_arg;
      +	wp->opts = *opts;
     @@ -5874,16 +6275,17 @@
      +	return wp;
      +}
      +
     -+void writer_set_limits(struct writer *w, uint64_t min, uint64_t max)
     ++void reftable_writer_set_limits(struct reftable_writer *w, uint64_t min,
     ++				uint64_t max)
      +{
      +	w->min_update_index = min;
      +	w->max_update_index = max;
      +}
      +
     -+void writer_free(struct writer *w)
     ++void reftable_writer_free(struct reftable_writer *w)
      +{
     -+	free(w->block);
     -+	free(w);
     ++	reftable_free(w->block);
     ++	reftable_free(w);
      +}
      +
      +struct obj_index_tree_node {
     @@ -5899,7 +6301,7 @@
      +			     ((const struct obj_index_tree_node *)b)->hash);
      +}
      +
     -+static void writer_index_hash(struct writer *w, struct slice hash)
     ++static void writer_index_hash(struct reftable_writer *w, struct slice hash)
      +{
      +	uint64_t off = w->next;
      +
     @@ -5909,7 +6311,7 @@
      +					     &obj_index_tree_node_compare, 0);
      +	struct obj_index_tree_node *key = NULL;
      +	if (node == NULL) {
     -+		key = calloc(sizeof(struct obj_index_tree_node), 1);
     ++		key = reftable_calloc(sizeof(struct obj_index_tree_node));
      +		slice_copy(&key->hash, hash);
      +		tree_search((void *)key, &w->obj_index_tree,
      +			    &obj_index_tree_node_compare, 1);
     @@ -5923,14 +6325,14 @@
      +
      +	if (key->offset_len == key->offset_cap) {
      +		key->offset_cap = 2 * key->offset_cap + 1;
     -+		key->offsets = realloc(key->offsets,
     -+				       sizeof(uint64_t) * key->offset_cap);
     ++		key->offsets = reftable_realloc(
     ++			key->offsets, sizeof(uint64_t) * key->offset_cap);
      +	}
      +
      +	key->offsets[key->offset_len++] = off;
      +}
      +
     -+static int writer_add_record(struct writer *w, struct record rec)
     ++static int writer_add_record(struct reftable_writer *w, struct record rec)
      +{
      +	int result = -1;
      +	struct slice key = { 0 };
     @@ -5967,14 +6369,15 @@
      +
      +	result = 0;
      +exit:
     -+	free(slice_yield(&key));
     ++	reftable_free(slice_yield(&key));
      +	return result;
      +}
      +
     -+int writer_add_ref(struct writer *w, struct ref_record *ref)
     ++int reftable_writer_add_ref(struct reftable_writer *w,
     ++			    struct reftable_ref_record *ref)
      +{
      +	struct record rec = { 0 };
     -+	struct ref_record copy = *ref;
     ++	struct reftable_ref_record copy = *ref;
      +	int err = 0;
      +
      +	if (ref->ref_name == NULL) {
     @@ -6010,18 +6413,20 @@
      +	return 0;
      +}
      +
     -+int writer_add_refs(struct writer *w, struct ref_record *refs, int n)
     ++int reftable_writer_add_refs(struct reftable_writer *w,
     ++			     struct reftable_ref_record *refs, int n)
      +{
      +	int err = 0;
      +	int i = 0;
     -+	QSORT(refs, n, ref_record_compare_name);
     ++	QSORT(refs, n, reftable_ref_record_compare_name);
      +	for (i = 0; err == 0 && i < n; i++) {
     -+		err = writer_add_ref(w, &refs[i]);
     ++		err = reftable_writer_add_ref(w, &refs[i]);
      +	}
      +	return err;
      +}
      +
     -+int writer_add_log(struct writer *w, struct log_record *log)
     ++int reftable_writer_add_log(struct reftable_writer *w,
     ++			    struct reftable_log_record *log)
      +{
      +	if (log->ref_name == NULL) {
      +		return API_ERROR;
     @@ -6047,18 +6452,19 @@
      +	}
      +}
      +
     -+int writer_add_logs(struct writer *w, struct log_record *logs, int n)
     ++int reftable_writer_add_logs(struct reftable_writer *w,
     ++			     struct reftable_log_record *logs, int n)
      +{
      +	int err = 0;
      +	int i = 0;
     -+	QSORT(logs, n, log_record_compare_key);
     ++	QSORT(logs, n, reftable_log_record_compare_key);
      +	for (i = 0; err == 0 && i < n; i++) {
     -+		err = writer_add_log(w, &logs[i]);
     ++		err = reftable_writer_add_log(w, &logs[i]);
      +	}
      +	return err;
      +}
      +
     -+static int writer_finish_section(struct writer *w)
     ++static int writer_finish_section(struct reftable_writer *w)
      +{
      +	byte typ = block_writer_type(w->block_writer);
      +	uint64_t index_start = 0;
     @@ -6105,9 +6511,9 @@
      +			assert(err == 0);
      +		}
      +		for (i = 0; i < idx_len; i++) {
     -+			free(slice_yield(&idx[i].last_key));
     ++			reftable_free(slice_yield(&idx[i].last_key));
      +		}
     -+		free(idx);
     ++		reftable_free(idx);
      +	}
      +
      +	writer_clear_index(w);
     @@ -6118,7 +6524,8 @@
      +	}
      +
      +	{
     -+		struct block_stats *bstats = writer_block_stats(w, typ);
     ++		struct reftable_block_stats *bstats =
     ++			writer_reftable_block_stats(w, typ);
      +		bstats->index_blocks =
      +			w->stats.idx_stats.blocks - before_blocks;
      +		bstats->index_offset = index_start;
     @@ -6150,7 +6557,7 @@
      +}
      +
      +struct write_record_arg {
     -+	struct writer *w;
     ++	struct reftable_writer *w;
      +	int err;
      +};
      +
     @@ -6199,11 +6606,11 @@
      +	struct obj_index_tree_node *entry = (struct obj_index_tree_node *)key;
      +
      +	FREE_AND_NULL(entry->offsets);
     -+	free(slice_yield(&entry->hash));
     -+	free(entry);
     ++	reftable_free(slice_yield(&entry->hash));
     ++	reftable_free(entry);
      +}
      +
     -+static int writer_dump_object_index(struct writer *w)
     ++static int writer_dump_object_index(struct reftable_writer *w)
      +{
      +	struct write_record_arg closure = { .w = w };
      +	struct common_prefix_arg common = { 0 };
     @@ -6224,7 +6631,7 @@
      +	return writer_finish_section(w);
      +}
      +
     -+int writer_finish_public_section(struct writer *w)
     ++int writer_finish_public_section(struct reftable_writer *w)
      +{
      +	byte typ = 0;
      +	int err = 0;
     @@ -6256,9 +6663,9 @@
      +	return 0;
      +}
      +
     -+int writer_close(struct writer *w)
     ++int reftable_writer_close(struct reftable_writer *w)
      +{
     -+	byte footer[68];
     ++	byte footer[72];
      +	byte *p = footer;
      +
      +	int err = writer_finish_public_section(w);
     @@ -6266,8 +6673,7 @@
      +		goto exit;
      +	}
      +
     -+	writer_write_header(w, footer);
     -+	p += 24;
     ++	p += writer_write_header(w, footer);
      +	put_be64(p, w->stats.ref_stats.index_offset);
      +	p += 8;
      +	put_be64(p, (w->stats.obj_stats.offset) << 5 | w->stats.object_id_len);
     @@ -6284,7 +6690,7 @@
      +	p += 4;
      +	w->pending_padding = 0;
      +
     -+	err = padded_write(w, footer, sizeof(footer), 0);
     ++	err = padded_write(w, footer, footer_size(writer_version(w)), 0);
      +	if (err < 0) {
      +		goto exit;
      +	}
     @@ -6298,15 +6704,15 @@
      +	/* free up memory. */
      +	block_writer_clear(&w->block_writer_data);
      +	writer_clear_index(w);
     -+	free(slice_yield(&w->last_key));
     ++	reftable_free(slice_yield(&w->last_key));
      +	return err;
      +}
      +
     -+void writer_clear_index(struct writer *w)
     ++void writer_clear_index(struct reftable_writer *w)
      +{
      +	int i = 0;
      +	for (i = 0; i < w->index_len; i++) {
     -+		free(slice_yield(&w->index[i].last_key));
     ++		reftable_free(slice_yield(&w->index[i].last_key));
      +	}
      +
      +	FREE_AND_NULL(w->index);
     @@ -6316,10 +6722,11 @@
      +
      +const int debug = 0;
      +
     -+static int writer_flush_nonempty_block(struct writer *w)
     ++static int writer_flush_nonempty_block(struct reftable_writer *w)
      +{
      +	byte typ = block_writer_type(w->block_writer);
     -+	struct block_stats *bstats = writer_block_stats(w, typ);
     ++	struct reftable_block_stats *bstats =
     ++		writer_reftable_block_stats(w, typ);
      +	uint64_t block_typ_off = (bstats->blocks == 0) ? w->next : 0;
      +	int raw_bytes = block_writer_finish(w->block_writer);
      +	int padding = 0;
     @@ -6358,8 +6765,8 @@
      +
      +	if (w->index_cap == w->index_len) {
      +		w->index_cap = 2 * w->index_cap + 1;
     -+		w->index = realloc(w->index,
     -+				   sizeof(struct index_record) * w->index_cap);
     ++		w->index = reftable_realloc(
     ++			w->index, sizeof(struct index_record) * w->index_cap);
      +	}
      +
      +	{
     @@ -6377,7 +6784,7 @@
      +	return 0;
      +}
      +
     -+int writer_flush_block(struct writer *w)
     ++int writer_flush_block(struct reftable_writer *w)
      +{
      +	if (w->block_writer == NULL) {
      +		return 0;
     @@ -6388,7 +6795,7 @@
      +	return writer_flush_nonempty_block(w);
      +}
      +
     -+struct stats *writer_stats(struct writer *w)
     ++const struct reftable_stats *writer_stats(struct reftable_writer *w)
      +{
      +	return &w->stats;
      +}
     @@ -6415,7 +6822,7 @@
      +#include "slice.h"
      +#include "tree.h"
      +
     -+struct writer {
     ++struct reftable_writer {
      +	int (*write)(void *, byte *, int);
      +	void *write_arg;
      +	int pending_padding;
     @@ -6423,11 +6830,11 @@
      +
      +	uint64_t next;
      +	uint64_t min_update_index, max_update_index;
     -+	struct write_options opts;
     ++	struct reftable_write_options opts;
      +
      +	byte *block;
     -+	struct block_writer *block_writer;
     -+	struct block_writer block_writer_data;
     ++	struct reftable_block_writer *block_writer;
     ++	struct reftable_block_writer block_writer_data;
      +	struct index_record *index;
      +	int index_len;
      +	int index_cap;
     @@ -6435,12 +6842,12 @@
      +	/* tree for use with tsearch */
      +	struct tree_node *obj_index_tree;
      +
     -+	struct stats stats;
     ++	struct reftable_stats stats;
      +};
      +
     -+int writer_flush_block(struct writer *w);
     -+void writer_clear_index(struct writer *w);
     -+int writer_finish_public_section(struct writer *w);
     ++int writer_flush_block(struct reftable_writer *w);
     ++void writer_clear_index(struct reftable_writer *w);
     ++int writer_finish_public_section(struct reftable_writer *w);
      +
      +#endif
      
  6:  a622d8066c7 !  9:  b29c4ecc1c4 Reftable support for git-core
     @@ -6,6 +6,7 @@
      
          TODO:
      
     +     * "git show-ref" shows "HEAD"
           * Resolve spots marked with XXX
           * Test strategy?
      
     @@ -104,8 +105,9 @@ $^
       		}
       	}
       
     --	init_db(git_dir, real_git_dir, option_template, INIT_DB_QUIET);
     +-	init_db(git_dir, real_git_dir, option_template, GIT_HASH_UNKNOWN, INIT_DB_QUIET);
      +	init_db(git_dir, real_git_dir, option_template,
     ++                GIT_HASH_UNKNOWN,
      +		DEFAULT_REF_STORAGE, /* XXX */
      +		INIT_DB_QUIET);
       
     @@ -116,20 +118,28 @@ $^
       --- a/builtin/init-db.c
       +++ b/builtin/init-db.c
      @@
     + 	return 1;
       }
       
     - static int create_default_files(const char *template_path,
     --				const char *original_git_dir)
     -+				const char *original_git_dir,
     -+				const char *ref_storage_format, int flags)
     +-void initialize_repository_version(int hash_algo)
     ++void initialize_repository_version(int hash_algo, const char *ref_storage_format)
       {
     - 	struct stat st1;
     - 	struct strbuf buf = STRBUF_INIT;
     + 	char repo_version_string[10];
     + 	int repo_version = GIT_REPO_VERSION;
     +@@
     + 		die(_("The hash algorithm %s is not supported in this build."), hash_algos[hash_algo].name);
     + #endif
     + 
     +-	if (hash_algo != GIT_HASH_SHA1)
     ++	if (hash_algo != GIT_HASH_SHA1 || !strcmp(ref_storage_format, "reftable"))
     + 		repo_version = GIT_REPO_VERSION_READ;
     + 
     + 	/* This forces creation of new config file */
      @@
       	is_bare_repository_cfg = init_is_bare_repository;
       	if (init_shared_repository != -1)
       		set_shared_repository(init_shared_repository);
     -+	the_repository->ref_storage_format = xstrdup(ref_storage_format);
     ++	the_repository->ref_storage_format = xstrdup(fmt->ref_storage);
       
       	/*
       	 * We would have created the above under user's umask -- under
     @@ -166,35 +176,28 @@ $^
      +		 */
       	}
       
     - 	/* This forces creation of new config file */
     --	xsnprintf(repo_version_string, sizeof(repo_version_string),
     --		  "%d", GIT_REPO_VERSION);
     -+	xsnprintf(repo_version_string, sizeof(repo_version_string), "%d",
     -+		  !strcmp(ref_storage_format, "reftable") ?
     -+			  GIT_REPO_VERSION_READ :
     -+			  GIT_REPO_VERSION);
     - 	git_config_set("core.repositoryformatversion", repo_version_string);
     +-	initialize_repository_version(fmt->hash_algo);
     ++	initialize_repository_version(fmt->hash_algo, fmt->ref_storage);
       
       	/* Check filemode trustability */
     + 	path = git_path_buf(&buf, "config");
      @@
       }
       
       int init_db(const char *git_dir, const char *real_git_dir,
     --	    const char *template_dir, unsigned int flags)
     -+	    const char *template_dir, const char *ref_storage_format,
     -+	    unsigned int flags)
     +-	    const char *template_dir, int hash, unsigned int flags)
     ++	    const char *template_dir, int hash, const char *ref_storage_format,
     ++            unsigned int flags)
       {
       	int reinit;
       	int exist_ok = flags & INIT_DB_EXIST_OK;
      @@
     + 	 * is an attempt to reinitialize new repository with an old tool.
       	 */
     - 	check_repository_format();
     - 
     --	reinit = create_default_files(template_dir, original_git_dir);
     -+	reinit = create_default_files(template_dir, original_git_dir,
     -+				      ref_storage_format, flags);
     + 	check_repository_format(&repo_fmt);
     ++        repo_fmt.ref_storage = xstrdup(ref_storage_format);
       
     - 	create_object_directory();
     + 	validate_hash_algorithm(&repo_fmt, hash);
       
      @@
       		git_config_set("receive.denyNonFastforwards", "true");
     @@ -213,7 +216,9 @@ $^
       	const char *real_git_dir = NULL;
       	const char *work_tree;
       	const char *template_dir = NULL;
     - 	unsigned int flags = 0;
     +@@
     + 	const char *object_format = NULL;
     + 	int hash_algo = GIT_HASH_UNKNOWN;
       	const struct option init_db_options[] = {
      -		OPT_STRING(0, "template", &template_dir, N_("template-directory"),
      -				N_("directory from which templates will be used")),
     @@ -235,7 +240,7 @@ $^
      +			   N_("the ref storage format to use")),
       		OPT_STRING(0, "separate-git-dir", &real_git_dir, N_("gitdir"),
       			   N_("separate git dir from working tree")),
     - 		OPT_END()
     + 		OPT_STRING(0, "object-format", &object_format, N_("hash"),
      @@
       	}
       
     @@ -245,21 +250,21 @@ $^
       	UNLEAK(work_tree);
       
       	flags |= INIT_DB_EXIST_OK;
     --	return init_db(git_dir, real_git_dir, template_dir, flags);
     -+	return init_db(git_dir, real_git_dir, template_dir, ref_storage_format,
     -+		       flags);
     +-	return init_db(git_dir, real_git_dir, template_dir, hash_algo, flags);
     ++	return init_db(git_dir, real_git_dir, template_dir, hash_algo, ref_storage_format, flags);
       }
      
       diff --git a/cache.h b/cache.h
       --- a/cache.h
       +++ b/cache.h
      @@
     - #define INIT_DB_EXIST_OK 0x0002
       
       int init_db(const char *git_dir, const char *real_git_dir,
     --	    const char *template_dir, unsigned int flags);
     -+	    const char *template_dir, const char *ref_storage_format,
     -+	    unsigned int flags);
     + 	    const char *template_dir, int hash_algo,
     ++            const char *ref_storage_format,
     + 	    unsigned int flags);
     +-void initialize_repository_version(int hash_algo);
     ++void initialize_repository_version(int hash_algo, const char *ref_storage_format);
       
       void sanitize_stdfds(void);
       int daemonize(void);
     @@ -350,7 +355,6 @@ $^
       struct string_list_item;
       struct worktree;
       
     -+/* XXX where should this be? */
      +#define DEFAULT_REF_STORAGE "files"
      +
       /*
     @@ -386,26 +390,25 @@ $^
      +
      +extern struct ref_storage_be refs_be_reftable;
      +
     -+struct reftable_ref_store {
     ++struct git_reftable_ref_store {
      +	struct ref_store base;
      +	unsigned int store_flags;
      +
      +	int err;
      +	char *reftable_dir;
     -+	char *table_list_file;
     -+	struct stack *stack;
     ++	struct reftable_stack *stack;
      +};
      +
     -+static void clear_log_record(struct log_record *log)
     ++static void clear_reftable_log_record(struct reftable_log_record *log)
      +{
      +	log->old_hash = NULL;
      +	log->new_hash = NULL;
      +	log->message = NULL;
      +	log->ref_name = NULL;
     -+	log_record_clear(log);
     ++	reftable_log_record_clear(log);
      +}
      +
     -+static void fill_log_record(struct log_record *log)
     ++static void fill_reftable_log_record(struct reftable_log_record *log)
      +{
      +	const char *info = git_committer_info(0);
      +	struct ident_split split = {};
     @@ -413,7 +416,7 @@ $^
      +	int sign = 1;
      +	assert(0 == result);
      +
     -+	log_record_clear(log);
     ++	reftable_log_record_clear(log);
      +	log->name =
      +		xstrndup(split.name_begin, split.name_end - split.name_begin);
      +	log->email =
     @@ -431,12 +434,12 @@ $^
      +	log->tz_offset = sign * atoi(split.tz_begin);
      +}
      +
     -+static struct ref_store *reftable_ref_store_create(const char *path,
     ++static struct ref_store *git_reftable_ref_store_create(const char *path,
      +						   unsigned int store_flags)
      +{
     -+	struct reftable_ref_store *refs = xcalloc(1, sizeof(*refs));
     ++	struct git_reftable_ref_store *refs = xcalloc(1, sizeof(*refs));
      +	struct ref_store *ref_store = (struct ref_store *)refs;
     -+	struct write_options cfg = {
     ++	struct reftable_write_options cfg = {
      +		.block_size = 4096,
      +		.hash_id = the_hash_algo->format_id,
      +	};
     @@ -449,10 +452,6 @@ $^
      +	refs->reftable_dir = xstrdup(sb.buf);
      +	strbuf_reset(&sb);
      +
     -+	strbuf_addf(&sb, "%s/reftable/tables.list", path);
     -+	refs->table_list_file = xstrdup(sb.buf);
     -+	strbuf_reset(&sb);
     -+
      +	strbuf_addf(&sb, "%s/refs", path);
      +	safe_create_dir(sb.buf, 1);
      +	strbuf_reset(&sb);
     @@ -464,31 +463,23 @@ $^
      +	strbuf_addf(&sb, "%s/refs/heads", path);
      +	write_file(sb.buf, "this repository uses the reftable format");
      +
     -+	refs->err = new_stack(&refs->stack, refs->reftable_dir,
     -+			      refs->table_list_file, cfg);
     ++	refs->err = reftable_new_stack(&refs->stack, refs->reftable_dir, cfg);
      +	strbuf_release(&sb);
      +	return ref_store;
      +}
      +
      +static int reftable_init_db(struct ref_store *ref_store, struct strbuf *err)
      +{
     -+	struct reftable_ref_store *refs =
     -+		(struct reftable_ref_store *)ref_store;
     -+	FILE *file;
     ++	struct git_reftable_ref_store *refs =
     ++		(struct git_reftable_ref_store *)ref_store;
      +	safe_create_dir(refs->reftable_dir, 1);
     -+
     -+	file = fopen(refs->table_list_file, "a");
     -+	if (file == NULL) {
     -+		return -1;
     -+	}
     -+	fclose(file);
      +	return 0;
      +}
      +
     -+struct reftable_iterator {
     ++struct git_reftable_iterator {
      +	struct ref_iterator base;
     -+	struct iterator iter;
     -+	struct ref_record ref;
     ++	struct reftable_iterator iter;
     ++	struct reftable_ref_record ref;
      +	struct object_id oid;
      +	struct ref_store *ref_store;
      +	unsigned int flags;
     @@ -498,9 +489,9 @@ $^
      +
      +static int reftable_ref_iterator_advance(struct ref_iterator *ref_iterator)
      +{
     -+	struct reftable_iterator *ri = (struct reftable_iterator *)ref_iterator;
     ++	struct git_reftable_iterator *ri = (struct git_reftable_iterator *)ref_iterator;
      +	while (ri->err == 0) {
     -+		ri->err = iterator_next_ref(ri->iter, &ri->ref);
     ++		ri->err = reftable_iterator_next_ref(ri->iter, &ri->ref);
      +		if (ri->err) {
      +			break;
      +		}
     @@ -554,7 +545,7 @@ $^
      +static int reftable_ref_iterator_peel(struct ref_iterator *ref_iterator,
      +				      struct object_id *peeled)
      +{
     -+	struct reftable_iterator *ri = (struct reftable_iterator *)ref_iterator;
     ++	struct git_reftable_iterator *ri = (struct git_reftable_iterator *)ref_iterator;
      +	if (ri->ref.target_value != NULL) {
      +		hashcpy(peeled->hash, ri->ref.target_value);
      +		return 0;
     @@ -565,9 +556,9 @@ $^
      +
      +static int reftable_ref_iterator_abort(struct ref_iterator *ref_iterator)
      +{
     -+	struct reftable_iterator *ri = (struct reftable_iterator *)ref_iterator;
     -+	ref_record_clear(&ri->ref);
     -+	iterator_destroy(&ri->iter);
     ++	struct git_reftable_iterator *ri = (struct git_reftable_iterator *)ref_iterator;
     ++	reftable_ref_record_clear(&ri->ref);
     ++	reftable_iterator_destroy(&ri->iter);
      +	return 0;
      +}
      +
     @@ -580,16 +571,16 @@ $^
      +reftable_ref_iterator_begin(struct ref_store *ref_store, const char *prefix,
      +			    unsigned int flags)
      +{
     -+	struct reftable_ref_store *refs =
     -+		(struct reftable_ref_store *)ref_store;
     -+	struct reftable_iterator *ri = xcalloc(1, sizeof(*ri));
     -+	struct merged_table *mt = NULL;
     ++	struct git_reftable_ref_store *refs =
     ++		(struct git_reftable_ref_store *)ref_store;
     ++	struct git_reftable_iterator *ri = xcalloc(1, sizeof(*ri));
     ++	struct reftable_merged_table *mt = NULL;
      +
      +	if (refs->err < 0) {
      +		ri->err = refs->err;
      +	} else {
     -+		mt = stack_merged_table(refs->stack);
     -+		ri->err = merged_table_seek_ref(mt, &ri->iter, prefix);
     ++		mt = reftable_stack_merged_table(refs->stack);
     ++		ri->err = reftable_merged_table_seek_ref(mt, &ri->iter, prefix);
      +	}
      +
      +	base_ref_iterator_init(&ri->base, &reftable_ref_iterator_vtable, 1);
     @@ -610,8 +601,8 @@ $^
      +				      struct ref_transaction *transaction,
      +				      struct strbuf *err)
      +{
     -+	struct reftable_ref_store *refs =
     -+		(struct reftable_ref_store *)ref_store;
     ++	struct git_reftable_ref_store *refs =
     ++		(struct git_reftable_ref_store *)ref_store;
      +	(void)refs;
      +	return 0;
      +}
     @@ -640,19 +631,19 @@ $^
      +		      ((struct ref_update *)b)->refname);
      +}
      +
     -+static int write_transaction_table(struct writer *writer, void *arg)
     ++static int write_transaction_table(struct reftable_writer *writer, void *arg)
      +{
      +	struct ref_transaction *transaction = (struct ref_transaction *)arg;
     -+	struct reftable_ref_store *refs =
     -+		(struct reftable_ref_store *)transaction->ref_store;
     -+	uint64_t ts = stack_next_update_index(refs->stack);
     ++	struct git_reftable_ref_store *refs =
     ++		(struct git_reftable_ref_store *)transaction->ref_store;
     ++	uint64_t ts = reftable_stack_next_update_index(refs->stack);
      +	int err = 0;
     -+	struct log_record *logs = calloc(transaction->nr, sizeof(*logs));
     ++	struct reftable_log_record *logs = calloc(transaction->nr, sizeof(*logs));
      +	struct ref_update **sorted =
      +		malloc(transaction->nr * sizeof(struct ref_update *));
      +	COPY_ARRAY(sorted, transaction->updates, transaction->nr);
      +	QSORT(sorted, transaction->nr, ref_update_cmp);
     -+	writer_set_limits(writer, ts, ts);
     ++	reftable_writer_set_limits(writer, ts, ts);
      +
      +	for (int i = 0; i < transaction->nr; i++) {
      +		struct ref_update *u = sorted[i];
     @@ -667,8 +658,8 @@ $^
      +
      +	for (int i = 0; i < transaction->nr; i++) {
      +		struct ref_update *u = sorted[i];
     -+		struct log_record *log = &logs[i];
     -+		fill_log_record(log);
     ++		struct reftable_log_record *log = &logs[i];
     ++		fill_reftable_log_record(log);
      +		log->ref_name = (char *)u->refname;
      +		log->old_hash = u->old_oid.hash;
      +		log->new_hash = u->new_oid.hash;
     @@ -683,13 +674,13 @@ $^
      +			const char *resolved = refs_resolve_ref_unsafe(
      +				transaction->ref_store, u->refname, 0, &out_oid,
      +				&out_flags);
     -+			struct ref_record ref = {};
     ++			struct reftable_ref_record ref = {};
      +			ref.ref_name =
      +				(char *)(resolved ? resolved : u->refname);
      +			log->ref_name = ref.ref_name;
      +			ref.value = u->new_oid.hash;
      +			ref.update_index = ts;
     -+			err = writer_add_ref(writer, &ref);
     ++			err = reftable_writer_add_ref(writer, &ref);
      +			if (err < 0) {
      +				goto exit;
      +			}
     @@ -697,8 +688,8 @@ $^
      +	}
      +
      +	for (int i = 0; i < transaction->nr; i++) {
     -+		err = writer_add_log(writer, &logs[i]);
     -+		clear_log_record(&logs[i]);
     ++		err = reftable_writer_add_log(writer, &logs[i]);
     ++		clear_reftable_log_record(&logs[i]);
      +		if (err < 0) {
      +			goto exit;
      +		}
     @@ -714,17 +705,17 @@ $^
      +				       struct ref_transaction *transaction,
      +				       struct strbuf *errmsg)
      +{
     -+	struct reftable_ref_store *refs =
     -+		(struct reftable_ref_store *)ref_store;
     ++	struct git_reftable_ref_store *refs =
     ++		(struct git_reftable_ref_store *)ref_store;
      +	int err = 0;
      +	if (refs->err < 0) {
      +		return refs->err;
      +	}
      +
     -+	err = stack_add(refs->stack, &write_transaction_table, transaction);
     ++	err = reftable_stack_add(refs->stack, &write_transaction_table, transaction);
      +	if (err < 0) {
      +		strbuf_addf(errmsg, "reftable: transaction failure %s",
     -+			    error_str(err));
     ++			    reftable_error_str(err));
      +		return -1;
      +	}
      +
     @@ -739,49 +730,49 @@ $^
      +}
      +
      +struct write_delete_refs_arg {
     -+	struct stack *stack;
     ++	struct reftable_stack *stack;
      +	struct string_list *refnames;
      +	const char *logmsg;
      +	unsigned int flags;
      +};
      +
     -+static int write_delete_refs_table(struct writer *writer, void *argv)
     ++static int write_delete_refs_table(struct reftable_writer *writer, void *argv)
      +{
      +	struct write_delete_refs_arg *arg =
      +		(struct write_delete_refs_arg *)argv;
     -+	uint64_t ts = stack_next_update_index(arg->stack);
     ++	uint64_t ts = reftable_stack_next_update_index(arg->stack);
      +	int err = 0;
      +
     -+	writer_set_limits(writer, ts, ts);
     ++	reftable_writer_set_limits(writer, ts, ts);
      +	for (int i = 0; i < arg->refnames->nr; i++) {
     -+		struct ref_record ref = {
     ++		struct reftable_ref_record ref = {
      +			.ref_name = (char *)arg->refnames->items[i].string,
      +			.update_index = ts,
      +		};
     -+		err = writer_add_ref(writer, &ref);
     ++		err = reftable_writer_add_ref(writer, &ref);
      +		if (err < 0) {
      +			return err;
      +		}
      +	}
      +
      +	for (int i = 0; i < arg->refnames->nr; i++) {
     -+		struct log_record log = {};
     -+		struct ref_record current = {};
     -+		fill_log_record(&log);
     ++		struct reftable_log_record log = {};
     ++		struct reftable_ref_record current = {};
     ++		fill_reftable_log_record(&log);
      +		log.message = xstrdup(arg->logmsg);
      +		log.new_hash = NULL;
      +		log.old_hash = NULL;
      +		log.update_index = ts;
      +		log.ref_name = (char *)arg->refnames->items[i].string;
      +
     -+		if (stack_read_ref(arg->stack, log.ref_name, &current) == 0) {
     ++		if (reftable_stack_read_ref(arg->stack, log.ref_name, &current) == 0) {
      +			log.old_hash = current.value;
      +		}
     -+		err = writer_add_log(writer, &log);
     ++		err = reftable_writer_add_log(writer, &log);
      +		log.old_hash = NULL;
     -+		ref_record_clear(&current);
     ++		reftable_ref_record_clear(&current);
      +
     -+		clear_log_record(&log);
     ++		clear_reftable_log_record(&log);
      +		if (err < 0) {
      +			return err;
      +		}
     @@ -793,8 +784,8 @@ $^
      +				struct string_list *refnames,
      +				unsigned int flags)
      +{
     -+	struct reftable_ref_store *refs =
     -+		(struct reftable_ref_store *)ref_store;
     ++	struct git_reftable_ref_store *refs =
     ++		(struct git_reftable_ref_store *)ref_store;
      +	struct write_delete_refs_arg arg = {
      +		.stack = refs->stack,
      +		.refnames = refnames,
     @@ -805,52 +796,52 @@ $^
      +		return refs->err;
      +	}
      +
     -+	return stack_add(refs->stack, &write_delete_refs_table, &arg);
     ++	return reftable_stack_add(refs->stack, &write_delete_refs_table, &arg);
      +}
      +
      +static int reftable_pack_refs(struct ref_store *ref_store, unsigned int flags)
      +{
     -+	struct reftable_ref_store *refs =
     -+		(struct reftable_ref_store *)ref_store;
     ++	struct git_reftable_ref_store *refs =
     ++		(struct git_reftable_ref_store *)ref_store;
      +	if (refs->err < 0) {
      +		return refs->err;
      +	}
     -+	return stack_compact_all(refs->stack, NULL);
     ++	return reftable_stack_compact_all(refs->stack, NULL);
      +}
      +
      +struct write_create_symref_arg {
     -+	struct reftable_ref_store *refs;
     ++	struct git_reftable_ref_store *refs;
      +	const char *refname;
      +	const char *target;
      +	const char *logmsg;
      +};
      +
     -+static int write_create_symref_table(struct writer *writer, void *arg)
     ++static int write_create_symref_table(struct reftable_writer *writer, void *arg)
      +{
      +	struct write_create_symref_arg *create =
      +		(struct write_create_symref_arg *)arg;
     -+	uint64_t ts = stack_next_update_index(create->refs->stack);
     ++	uint64_t ts = reftable_stack_next_update_index(create->refs->stack);
      +	int err = 0;
      +
     -+	struct ref_record ref = {
     ++	struct reftable_ref_record ref = {
      +		.ref_name = (char *)create->refname,
      +		.target = (char *)create->target,
      +		.update_index = ts,
      +	};
     -+	writer_set_limits(writer, ts, ts);
     -+	err = writer_add_ref(writer, &ref);
     ++	reftable_writer_set_limits(writer, ts, ts);
     ++	err = reftable_writer_add_ref(writer, &ref);
      +	if (err < 0) {
      +		return err;
      +	}
      +
      +	{
     -+		struct log_record log = {};
     ++		struct reftable_log_record log = {};
      +		struct object_id new_oid = {};
      +		struct object_id old_oid = {};
     -+		struct ref_record current = {};
     -+		stack_read_ref(create->refs->stack, create->refname, &current);
     ++		struct reftable_ref_record current = {};
     ++		reftable_stack_read_ref(create->refs->stack, create->refname, &current);
      +
     -+		fill_log_record(&log);
     ++		fill_reftable_log_record(&log);
      +		log.ref_name = current.ref_name;
      +		if (refs_resolve_ref_unsafe(
      +			    (struct ref_store *)create->refs, create->refname,
     @@ -865,12 +856,12 @@ $^
      +		}
      +
      +		if (log.old_hash != NULL || log.new_hash != NULL) {
     -+			writer_add_log(writer, &log);
     ++			reftable_writer_add_log(writer, &log);
      +		}
      +		log.ref_name = NULL;
      +		log.old_hash = NULL;
      +		log.new_hash = NULL;
     -+		clear_log_record(&log);
     ++		clear_reftable_log_record(&log);
      +	}
      +	return 0;
      +}
     @@ -879,8 +870,8 @@ $^
      +				  const char *refname, const char *target,
      +				  const char *logmsg)
      +{
     -+	struct reftable_ref_store *refs =
     -+		(struct reftable_ref_store *)ref_store;
     ++	struct git_reftable_ref_store *refs =
     ++		(struct git_reftable_ref_store *)ref_store;
      +	struct write_create_symref_arg arg = { .refs = refs,
      +					       .refname = refname,
      +					       .target = target,
     @@ -888,55 +879,55 @@ $^
      +	if (refs->err < 0) {
      +		return refs->err;
      +	}
     -+	return stack_add(refs->stack, &write_create_symref_table, &arg);
     ++	return reftable_stack_add(refs->stack, &write_create_symref_table, &arg);
      +}
      +
      +struct write_rename_arg {
     -+	struct stack *stack;
     ++	struct reftable_stack *stack;
      +	const char *oldname;
      +	const char *newname;
      +	const char *logmsg;
      +};
      +
     -+static int write_rename_table(struct writer *writer, void *argv)
     ++static int write_rename_table(struct reftable_writer *writer, void *argv)
      +{
      +	struct write_rename_arg *arg = (struct write_rename_arg *)argv;
     -+	uint64_t ts = stack_next_update_index(arg->stack);
     -+	struct ref_record ref = {};
     -+	int err = stack_read_ref(arg->stack, arg->oldname, &ref);
     ++	uint64_t ts = reftable_stack_next_update_index(arg->stack);
     ++	struct reftable_ref_record ref = {};
     ++	int err = reftable_stack_read_ref(arg->stack, arg->oldname, &ref);
      +
      +	if (err) {
      +		goto exit;
      +	}
      +
      +	/* XXX do ref renames overwrite the target? */
     -+	if (stack_read_ref(arg->stack, arg->newname, &ref) == 0) {
     ++	if (reftable_stack_read_ref(arg->stack, arg->newname, &ref) == 0) {
      +		goto exit;
      +	}
      +
      +	free(ref.ref_name);
      +	ref.ref_name = strdup(arg->newname);
     -+	writer_set_limits(writer, ts, ts);
     ++	reftable_writer_set_limits(writer, ts, ts);
      +	ref.update_index = ts;
      +
      +	{
     -+		struct ref_record todo[2] = {};
     ++		struct reftable_ref_record todo[2] = {};
      +		todo[0].ref_name = (char *)arg->oldname;
      +		todo[0].update_index = ts;
      +		/* leave todo[0] empty */
      +		todo[1] = ref;
      +		todo[1].update_index = ts;
      +
     -+		err = writer_add_refs(writer, todo, 2);
     ++		err = reftable_writer_add_refs(writer, todo, 2);
      +		if (err < 0) {
      +			goto exit;
      +		}
      +	}
      +
      +	if (ref.value != NULL) {
     -+		struct log_record todo[2] = {};
     -+		fill_log_record(&todo[0]);
     -+		fill_log_record(&todo[1]);
     ++		struct reftable_log_record todo[2] = {};
     ++		fill_reftable_log_record(&todo[0]);
     ++		fill_reftable_log_record(&todo[1]);
      +
      +		todo[0].ref_name = (char *)arg->oldname;
      +		todo[0].update_index = ts;
     @@ -950,10 +941,10 @@ $^
      +		todo[1].new_hash = ref.value;
      +		todo[1].message = (char *)arg->logmsg;
      +
     -+		err = writer_add_logs(writer, todo, 2);
     ++		err = reftable_writer_add_logs(writer, todo, 2);
      +
     -+		clear_log_record(&todo[0]);
     -+		clear_log_record(&todo[1]);
     ++		clear_reftable_log_record(&todo[0]);
     ++		clear_reftable_log_record(&todo[1]);
      +
      +		if (err < 0) {
      +			goto exit;
     @@ -964,7 +955,7 @@ $^
      +	}
      +
      +exit:
     -+	ref_record_clear(&ref);
     ++	reftable_ref_record_clear(&ref);
      +	return err;
      +}
      +
     @@ -972,8 +963,8 @@ $^
      +			       const char *oldrefname, const char *newrefname,
      +			       const char *logmsg)
      +{
     -+	struct reftable_ref_store *refs =
     -+		(struct reftable_ref_store *)ref_store;
     ++	struct git_reftable_ref_store *refs =
     ++		(struct git_reftable_ref_store *)ref_store;
      +	struct write_rename_arg arg = {
      +		.stack = refs->stack,
      +		.oldname = oldrefname,
     @@ -984,7 +975,7 @@ $^
      +		return refs->err;
      +	}
      +
     -+	return stack_add(refs->stack, &write_rename_table, &arg);
     ++	return reftable_stack_add(refs->stack, &write_rename_table, &arg);
      +}
      +
      +static int reftable_copy_ref(struct ref_store *ref_store,
     @@ -996,8 +987,8 @@ $^
      +
      +struct reftable_reflog_ref_iterator {
      +	struct ref_iterator base;
     -+	struct iterator iter;
     -+	struct log_record log;
     ++	struct reftable_iterator iter;
     ++	struct reftable_log_record log;
      +	struct object_id oid;
      +	char *last_name;
      +};
     @@ -1009,7 +1000,7 @@ $^
      +		(struct reftable_reflog_ref_iterator *)ref_iterator;
      +
      +	while (1) {
     -+		int err = iterator_next_log(ri->iter, &ri->log);
     ++		int err = reftable_iterator_next_log(ri->iter, &ri->log);
      +		if (err > 0) {
      +			return ITER_DONE;
      +		}
     @@ -1041,8 +1032,8 @@ $^
      +{
      +	struct reftable_reflog_ref_iterator *ri =
      +		(struct reftable_reflog_ref_iterator *)ref_iterator;
     -+	log_record_clear(&ri->log);
     -+	iterator_destroy(&ri->iter);
     ++	reftable_log_record_clear(&ri->log);
     ++	reftable_iterator_destroy(&ri->iter);
      +	return 0;
      +}
      +
     @@ -1055,11 +1046,11 @@ $^
      +reftable_reflog_iterator_begin(struct ref_store *ref_store)
      +{
      +	struct reftable_reflog_ref_iterator *ri = xcalloc(sizeof(*ri), 1);
     -+	struct reftable_ref_store *refs =
     -+		(struct reftable_ref_store *)ref_store;
     ++	struct git_reftable_ref_store *refs =
     ++		(struct git_reftable_ref_store *)ref_store;
      +
     -+	struct merged_table *mt = stack_merged_table(refs->stack);
     -+	int err = merged_table_seek_log(mt, &ri->iter, "");
     ++	struct reftable_merged_table *mt = reftable_stack_merged_table(refs->stack);
     ++	int err = reftable_merged_table_seek_log(mt, &ri->iter, "");
      +	if (err < 0) {
      +		free(ri);
      +		return NULL;
     @@ -1077,21 +1068,21 @@ $^
      +					  const char *refname,
      +					  each_reflog_ent_fn fn, void *cb_data)
      +{
     -+	struct iterator it = {};
     -+	struct reftable_ref_store *refs =
     -+		(struct reftable_ref_store *)ref_store;
     -+	struct merged_table *mt = NULL;
     ++	struct reftable_iterator it = {};
     ++	struct git_reftable_ref_store *refs =
     ++		(struct git_reftable_ref_store *)ref_store;
     ++	struct reftable_merged_table *mt = NULL;
      +	int err = 0;
     -+	struct log_record log = {};
     ++	struct reftable_log_record log = {};
      +
      +	if (refs->err < 0) {
      +		return refs->err;
      +	}
      +
     -+	mt = stack_merged_table(refs->stack);
     -+	err = merged_table_seek_log(mt, &it, refname);
     ++	mt = reftable_stack_merged_table(refs->stack);
     ++	err = reftable_merged_table_seek_log(mt, &it, refname);
      +	while (err == 0) {
     -+		err = iterator_next_log(it, &log);
     ++		err = reftable_iterator_next_log(it, &log);
      +		if (err != 0) {
      +			break;
      +		}
     @@ -1120,8 +1111,8 @@ $^
      +		}
      +	}
      +
     -+	log_record_clear(&log);
     -+	iterator_destroy(&it);
     ++	reftable_log_record_clear(&log);
     ++	reftable_iterator_destroy(&it);
      +	if (err > 0) {
      +		err = 0;
      +	}
     @@ -1133,11 +1124,11 @@ $^
      +					  const char *refname,
      +					  each_reflog_ent_fn fn, void *cb_data)
      +{
     -+	struct iterator it = {};
     -+	struct reftable_ref_store *refs =
     -+		(struct reftable_ref_store *)ref_store;
     -+	struct merged_table *mt = NULL;
     -+	struct log_record *logs = NULL;
     ++	struct reftable_iterator it = {};
     ++	struct git_reftable_ref_store *refs =
     ++		(struct git_reftable_ref_store *)ref_store;
     ++	struct reftable_merged_table *mt = NULL;
     ++	struct reftable_log_record *logs = NULL;
      +	int cap = 0;
      +	int len = 0;
      +	int err = 0;
     @@ -1145,12 +1136,12 @@ $^
      +	if (refs->err < 0) {
      +		return refs->err;
      +	}
     -+	mt = stack_merged_table(refs->stack);
     -+	err = merged_table_seek_log(mt, &it, refname);
     ++	mt = reftable_stack_merged_table(refs->stack);
     ++	err = reftable_merged_table_seek_log(mt, &it, refname);
      +
      +	while (err == 0) {
     -+		struct log_record log = {};
     -+		err = iterator_next_log(it, &log);
     ++		struct reftable_log_record log = {};
     ++		err = reftable_iterator_next_log(it, &log);
      +		if (err != 0) {
      +			break;
      +		}
     @@ -1168,7 +1159,7 @@ $^
      +	}
      +
      +	for (int i = len; i--;) {
     -+		struct log_record *log = &logs[i];
     ++		struct reftable_log_record *log = &logs[i];
      +		struct object_id old_oid = {};
      +		struct object_id new_oid = {};
      +		const char *full_committer = "";
     @@ -1187,11 +1178,11 @@ $^
      +	}
      +
      +	for (int i = 0; i < len; i++) {
     -+		log_record_clear(&logs[i]);
     ++		reftable_log_record_clear(&logs[i]);
      +	}
      +	free(logs);
      +
     -+	iterator_destroy(&it);
     ++	reftable_iterator_destroy(&it);
      +	if (err > 0) {
      +		err = 0;
      +	}
     @@ -1219,8 +1210,8 @@ $^
      +}
      +
      +struct reflog_expiry_arg {
     -+	struct reftable_ref_store *refs;
     -+	struct log_record *tombstones;
     ++	struct git_reftable_ref_store *refs;
     ++	struct reftable_log_record *tombstones;
      +	int len;
      +	int cap;
      +};
     @@ -1229,7 +1220,7 @@ $^
      +{
      +	int i = 0;
      +	for (; i < arg->len; i++) {
     -+		log_record_clear(&arg->tombstones[i]);
     ++		reftable_log_record_clear(&arg->tombstones[i]);
      +	}
      +
      +	FREE_AND_NULL(arg->tombstones);
     @@ -1238,7 +1229,7 @@ $^
      +static void add_log_tombstone(struct reflog_expiry_arg *arg,
      +			      const char *refname, uint64_t ts)
      +{
     -+	struct log_record tombstone = {
     ++	struct reftable_log_record tombstone = {
      +		.ref_name = xstrdup(refname),
      +		.update_index = ts,
      +	};
     @@ -1250,14 +1241,14 @@ $^
      +	arg->tombstones[arg->len++] = tombstone;
      +}
      +
     -+static int write_reflog_expiry_table(struct writer *writer, void *argv)
     ++static int write_reflog_expiry_table(struct reftable_writer *writer, void *argv)
      +{
      +	struct reflog_expiry_arg *arg = (struct reflog_expiry_arg *)argv;
     -+	uint64_t ts = stack_next_update_index(arg->refs->stack);
     ++	uint64_t ts = reftable_stack_next_update_index(arg->refs->stack);
      +	int i = 0;
     -+	writer_set_limits(writer, ts, ts);
     ++	reftable_writer_set_limits(writer, ts, ts);
      +	for (i = 0; i < arg->len; i++) {
     -+		int err = writer_add_log(writer, &arg->tombstones[i]);
     ++		int err = reftable_writer_add_log(writer, &arg->tombstones[i]);
      +		if (err) {
      +			return err;
      +		}
     @@ -1286,21 +1277,21 @@ $^
      +	  It would be better if the refs backend supported an API that sets a
      +	  criterion for all refs, passing the criterion to pack_refs().
      +	*/
     -+	struct reftable_ref_store *refs =
     -+		(struct reftable_ref_store *)ref_store;
     -+	struct merged_table *mt = NULL;
     ++	struct git_reftable_ref_store *refs =
     ++		(struct git_reftable_ref_store *)ref_store;
     ++	struct reftable_merged_table *mt = NULL;
      +	struct reflog_expiry_arg arg = {
      +		.refs = refs,
      +	};
     -+	struct log_record log = {};
     -+	struct iterator it = {};
     ++	struct reftable_log_record log = {};
     ++	struct reftable_iterator it = {};
      +	int err = 0;
      +	if (refs->err < 0) {
      +		return refs->err;
      +	}
      +
     -+	mt = stack_merged_table(refs->stack);
     -+	err = merged_table_seek_log(mt, &it, refname);
     ++	mt = reftable_stack_merged_table(refs->stack);
     ++	err = reftable_merged_table_seek_log(mt, &it, refname);
      +	if (err < 0) {
      +		return err;
      +	}
     @@ -1309,7 +1300,7 @@ $^
      +		struct object_id ooid = {};
      +		struct object_id noid = {};
      +
     -+		int err = iterator_next_log(it, &log);
     ++		int err = reftable_iterator_next_log(it, &log);
      +		if (err < 0) {
      +			return err;
      +		}
     @@ -1326,9 +1317,9 @@ $^
      +			add_log_tombstone(&arg, refname, log.update_index);
      +		}
      +	}
     -+	log_record_clear(&log);
     -+	iterator_destroy(&it);
     -+	err = stack_add(refs->stack, &write_reflog_expiry_table, &arg);
     ++	reftable_log_record_clear(&log);
     ++	reftable_iterator_destroy(&it);
     ++	err = reftable_stack_add(refs->stack, &write_reflog_expiry_table, &arg);
      +	clear_log_tombstones(&arg);
      +	return err;
      +}
     @@ -1337,15 +1328,15 @@ $^
      +				 const char *refname, struct object_id *oid,
      +				 struct strbuf *referent, unsigned int *type)
      +{
     -+	struct reftable_ref_store *refs =
     -+		(struct reftable_ref_store *)ref_store;
     -+	struct ref_record ref = {};
     ++	struct git_reftable_ref_store *refs =
     ++		(struct git_reftable_ref_store *)ref_store;
     ++	struct reftable_ref_record ref = {};
      +	int err = 0;
      +	if (refs->err < 0) {
      +		return refs->err;
      +	}
      +
     -+	err = stack_read_ref(refs->stack, refname, &ref);
     ++	err = reftable_stack_read_ref(refs->stack, refname, &ref);
      +	if (err) {
      +		goto exit;
      +	}
     @@ -1358,14 +1349,14 @@ $^
      +		hashcpy(oid->hash, ref.value);
      +	}
      +exit:
     -+	ref_record_clear(&ref);
     ++	reftable_ref_record_clear(&ref);
      +	return err;
      +}
      +
      +struct ref_storage_be refs_be_reftable = {
      +	&refs_be_files,
      +	"reftable",
     -+	reftable_ref_store_create,
     ++	git_reftable_ref_store_create,
      +	reftable_init_db,
      +	reftable_transaction_prepare,
      +	reftable_transaction_finish,
     @@ -1471,24 +1462,28 @@ $^
      +. ./test-lib.sh
      +
      +test_expect_success 'basic operation of reftable storage' '
     -+        git init --ref-storage=reftable repo &&
     -+        cd repo &&
     -+        echo "hello" > world.txt &&
     -+        git add world.txt &&
     -+        git commit -m "first post" &&
     -+        printf "HEAD\nrefs/heads/master\n" > want &&
     -+        git show-ref | cut -f2 -d" " > got &&
     -+        test_cmp got want &&
     -+        for count in $(test_seq 1 10); do
     -+                echo "hello" >> world.txt
     -+                git commit -m "number ${count}" world.txt
     -+        done &&
     -+        git gc &&
     -+        nfiles=$(ls -1 .git/reftable | wc -l | tr -d "[ \t]" ) &&
     -+        test "${nfiles}" = "2" &&
     -+        git reflog refs/heads/master > output &&
     -+        grep "commit (initial): first post" output &&
     -+        grep "commit: number 10" output
     ++	git init --ref-storage=reftable repo && (
     ++	cd repo &&
     ++	echo "hello" >world.txt &&
     ++	git add world.txt &&
     ++	git commit -m "first post" &&
     ++	test_write_lines HEAD refs/heads/master >expect &&
     ++	git show-ref &&
     ++	git show-ref | cut -f2 -d" " > actual &&
     ++	test_cmp actual expect &&
     ++	for count in $(test_seq 1 10)
     ++	do
     ++		echo "hello" >>world.txt
     ++		git commit -m "number ${count}" world.txt ||
     ++		return 1
     ++	done &&
     ++	git gc &&
     ++	nfiles=$(ls -1 .git/reftable | wc -l ) &&
     ++	test ${nfiles} = "2" &&
     ++	git reflog refs/heads/master >output &&
     ++	test_line_count = 11 output &&
     ++	grep "commit (initial): first post" output &&
     ++	grep "commit: number 10" output )
      +'
      +
      +test_done

-- 
gitgitgadget

  parent reply	other threads:[~2020-04-01 11:29 UTC|newest]

Thread overview: 409+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-01-23 19:41 [PATCH 0/5] Reftable support git-core Han-Wen Nienhuys via GitGitGadget
2020-01-23 19:41 ` [PATCH 1/5] setup.c: enable repo detection for reftable Han-Wen Nienhuys via GitGitGadget
2020-01-23 19:41 ` [PATCH 2/5] create .git/refs in files-backend.c Han-Wen Nienhuys via GitGitGadget
2020-01-23 19:41 ` [PATCH 3/5] Document how ref iterators and symrefs interact Han-Wen Nienhuys via GitGitGadget
2020-01-23 19:41 ` [PATCH 4/5] Add reftable library Han-Wen Nienhuys via GitGitGadget
2020-01-23 19:41 ` [PATCH 5/5] Reftable support for git-core Han-Wen Nienhuys via GitGitGadget
2020-01-23 21:44 ` [PATCH 0/5] Reftable support git-core Junio C Hamano
2020-01-27 13:52   ` Han-Wen Nienhuys
2020-01-27 13:57     ` Han-Wen Nienhuys
2020-01-23 22:45 ` Stephan Beyer
2020-01-27 13:57   ` Han-Wen Nienhuys
2020-01-27 14:22 ` [PATCH v2 " Han-Wen Nienhuys via GitGitGadget
2020-01-27 14:22   ` [PATCH v2 1/5] setup.c: enable repo detection for reftable Han-Wen Nienhuys via GitGitGadget
2020-01-27 14:22   ` [PATCH v2 2/5] create .git/refs in files-backend.c Han-Wen Nienhuys via GitGitGadget
2020-01-27 22:28     ` Junio C Hamano
2020-01-28 15:58       ` Han-Wen Nienhuys
2020-01-30  4:19         ` Junio C Hamano
2020-01-27 14:22   ` [PATCH v2 3/5] Document how ref iterators and symrefs interact Han-Wen Nienhuys via GitGitGadget
2020-01-27 22:53     ` Junio C Hamano
2020-01-28 16:07       ` Han-Wen Nienhuys
2020-01-28 19:35         ` Junio C Hamano
2020-01-27 14:22   ` [PATCH v2 4/5] Add reftable library Han-Wen Nienhuys via GitGitGadget
2020-01-27 14:22   ` [PATCH v2 5/5] Reftable support for git-core Han-Wen Nienhuys via GitGitGadget
2020-01-28  7:31     ` Jeff King
2020-01-28 15:36       ` Martin Fick
2020-01-29  8:12         ` Jeff King
2020-01-29 16:49           ` Martin Fick
2020-01-29 18:40             ` Han-Wen Nienhuys
2020-01-29 19:47               ` Martin Fick
2020-01-29 19:50                 ` Han-Wen Nienhuys
2020-01-30  7:21                   ` Jeff King
2020-02-03 16:39                     ` Han-Wen Nienhuys
2020-02-03 17:05                       ` Jeff King
2020-02-03 17:09                         ` Han-Wen Nienhuys
2020-02-04 18:54                         ` Han-Wen Nienhuys
2020-02-04 20:06                           ` Jeff King
2020-02-04 20:26                             ` Han-Wen Nienhuys
2020-01-29 18:34           ` Junio C Hamano
2020-01-28 15:56       ` Han-Wen Nienhuys
2020-01-29 10:47         ` Jeff King
2020-01-29 18:43           ` Junio C Hamano
2020-01-29 18:53             ` Han-Wen Nienhuys
2020-01-30  7:26             ` Jeff King
2020-02-04 19:06           ` Han-Wen Nienhuys
2020-02-04 19:54             ` Jeff King
2020-02-04 20:22       ` Han-Wen Nienhuys
2020-02-04 22:13         ` Jeff King
2020-02-04 20:27   ` [PATCH v3 0/6] Reftable support git-core Han-Wen Nienhuys via GitGitGadget
2020-02-04 20:27     ` [PATCH v3 1/6] refs.h: clarify reflog iteration order Han-Wen Nienhuys via GitGitGadget
2020-02-04 20:27     ` [PATCH v3 2/6] setup.c: enable repo detection for reftable Han-Wen Nienhuys via GitGitGadget
2020-02-04 20:31       ` Han-Wen Nienhuys
2020-02-04 20:27     ` [PATCH v3 3/6] create .git/refs in files-backend.c Han-Wen Nienhuys via GitGitGadget
2020-02-04 21:29       ` Junio C Hamano
2020-02-05 11:34         ` Han-Wen Nienhuys
2020-02-05 11:42       ` SZEDER Gábor
2020-02-05 12:24         ` Jeff King
2020-02-04 20:27     ` [PATCH v3 4/6] refs: document how ref_iterator_advance_fn should handle symrefs Han-Wen Nienhuys via GitGitGadget
2020-02-04 20:27     ` [PATCH v3 5/6] Add reftable library Han-Wen Nienhuys via GitGitGadget
2020-02-04 20:27     ` [PATCH v3 6/6] Reftable support for git-core Han-Wen Nienhuys via GitGitGadget
2020-02-06 22:55     ` [PATCH v4 0/5] Reftable support git-core Han-Wen Nienhuys via GitGitGadget
2020-02-06 22:55       ` [PATCH v4 1/5] refs.h: clarify reflog iteration order Han-Wen Nienhuys via GitGitGadget
2020-02-06 22:55       ` [PATCH v4 2/5] create .git/refs in files-backend.c Han-Wen Nienhuys via GitGitGadget
2020-02-06 22:55       ` [PATCH v4 3/5] refs: document how ref_iterator_advance_fn should handle symrefs Han-Wen Nienhuys via GitGitGadget
2020-02-06 22:55       ` [PATCH v4 4/5] Add reftable library Han-Wen Nienhuys via GitGitGadget
2020-02-06 23:07         ` Junio C Hamano
2020-02-07  0:16         ` brian m. carlson
2020-02-10 13:16           ` Han-Wen Nienhuys
2020-02-11  0:05             ` brian m. carlson
2020-02-11 14:20               ` Han-Wen Nienhuys
2020-02-11 16:31                 ` Junio C Hamano
2020-02-11 16:40                   ` Han-Wen Nienhuys
2020-02-11 23:40                     ` brian m. carlson
2020-02-18  9:25                       ` Han-Wen Nienhuys
2020-02-11 16:46                   ` Han-Wen Nienhuys
2020-02-20 17:20                     ` Jonathan Nieder
2020-02-06 22:55       ` [PATCH v4 5/5] Reftable support for git-core Han-Wen Nienhuys via GitGitGadget
2020-02-06 23:49         ` brian m. carlson
2020-02-10 13:18           ` Han-Wen Nienhuys
2020-02-06 23:31       ` [PATCH v4 0/5] Reftable support git-core brian m. carlson
2020-02-10 14:14       ` [PATCH v5 " Han-Wen Nienhuys via GitGitGadget
2020-02-10 14:14         ` [PATCH v5 1/5] refs.h: clarify reflog iteration order Han-Wen Nienhuys via GitGitGadget
2020-02-10 14:14         ` [PATCH v5 2/5] create .git/refs in files-backend.c Han-Wen Nienhuys via GitGitGadget
2020-02-10 14:14         ` [PATCH v5 3/5] refs: document how ref_iterator_advance_fn should handle symrefs Han-Wen Nienhuys via GitGitGadget
2020-02-10 14:14         ` [PATCH v5 4/5] Add reftable library Han-Wen Nienhuys via GitGitGadget
2020-02-10 14:14         ` [PATCH v5 5/5] Reftable support for git-core Han-Wen Nienhuys via GitGitGadget
2020-02-18  8:43         ` [PATCH v6 0/5] Reftable support git-core Han-Wen Nienhuys via GitGitGadget
2020-02-18  8:43           ` [PATCH v6 1/5] refs.h: clarify reflog iteration order Han-Wen Nienhuys via GitGitGadget
2020-02-18  8:43           ` [PATCH v6 2/5] create .git/refs in files-backend.c Han-Wen Nienhuys via GitGitGadget
2020-02-18  8:43           ` [PATCH v6 3/5] refs: document how ref_iterator_advance_fn should handle symrefs Han-Wen Nienhuys via GitGitGadget
2020-02-18  8:43           ` [PATCH v6 4/5] Add reftable library Han-Wen Nienhuys via GitGitGadget
2020-02-18 21:11             ` Junio C Hamano
2020-02-19  6:55               ` Jeff King
2020-02-19 17:00                 ` Han-Wen Nienhuys
2020-02-18  8:43           ` [PATCH v6 5/5] Reftable support for git-core Han-Wen Nienhuys via GitGitGadget
2020-02-18 21:05           ` [PATCH v6 0/5] Reftable support git-core Junio C Hamano
2020-02-19 16:59             ` Han-Wen Nienhuys
2020-02-19 17:02               ` Junio C Hamano
2020-02-19 17:21                 ` Han-Wen Nienhuys
2020-02-19 18:10                   ` Junio C Hamano
2020-02-19 19:14                     ` Han-Wen Nienhuys
2020-02-19 20:09                       ` Junio C Hamano
2020-02-20 11:19                     ` Jeff King
2020-02-21  6:40           ` Jonathan Nieder
2020-02-26 17:16             ` Han-Wen Nienhuys
2020-02-26 20:04               ` Junio C Hamano
2020-02-27  0:01               ` brian m. carlson
     [not found]             ` <CAFQ2z_NQn9O3kFmHk8Cr31FY66ToU4bUdE=asHUfN++zBG+SPw@mail.gmail.com>
2020-02-26 17:41               ` Jonathan Nieder
2020-02-26 17:54                 ` Han-Wen Nienhuys
2020-02-26  8:49           ` [PATCH v7 0/6] " Han-Wen Nienhuys via GitGitGadget
2020-02-26  8:49             ` [PATCH v7 1/6] refs.h: clarify reflog iteration order Han-Wen Nienhuys via GitGitGadget
2020-02-26  8:49             ` [PATCH v7 2/6] create .git/refs in files-backend.c Han-Wen Nienhuys via GitGitGadget
2020-02-26  8:49             ` [PATCH v7 3/6] refs: document how ref_iterator_advance_fn should handle symrefs Han-Wen Nienhuys via GitGitGadget
2020-02-26  8:49             ` [PATCH v7 4/6] reftable: file format documentation Jonathan Nieder via GitGitGadget
2020-02-26  8:49             ` [PATCH v7 5/6] Add reftable library Han-Wen Nienhuys via GitGitGadget
2020-02-26  8:49             ` [PATCH v7 6/6] Reftable support for git-core Han-Wen Nienhuys via GitGitGadget
2020-02-26 18:12               ` Junio C Hamano
2020-02-26 18:59                 ` Han-Wen Nienhuys
2020-02-26 19:59                   ` Junio C Hamano
2020-02-27 16:03                     ` Han-Wen Nienhuys
2020-02-27 16:23                       ` Junio C Hamano
2020-02-27 17:56                         ` Han-Wen Nienhuys
2020-02-26 21:31               ` Junio C Hamano
2020-02-27 16:01                 ` Han-Wen Nienhuys
2020-02-27 16:26                   ` Junio C Hamano
2020-02-26 17:35             ` [PATCH v7 0/6] Reftable support git-core Junio C Hamano
2020-03-24  6:06             ` Jonathan Nieder
2020-04-01 11:28             ` Han-Wen Nienhuys via GitGitGadget [this message]
2020-04-01 11:28               ` [PATCH v8 1/9] refs.h: clarify reflog iteration order Han-Wen Nienhuys via GitGitGadget
2020-04-01 11:28               ` [PATCH v8 2/9] create .git/refs in files-backend.c Han-Wen Nienhuys via GitGitGadget
2020-04-01 11:28               ` [PATCH v8 3/9] refs: document how ref_iterator_advance_fn should handle symrefs Han-Wen Nienhuys via GitGitGadget
2020-04-01 11:28               ` [PATCH v8 4/9] Add .gitattributes for the reftable/ directory Han-Wen Nienhuys via GitGitGadget
2020-04-01 11:28               ` [PATCH v8 5/9] reftable: file format documentation Jonathan Nieder via GitGitGadget
2020-04-01 11:28               ` [PATCH v8 6/9] reftable: define version 2 of the spec to accomodate SHA256 Han-Wen Nienhuys via GitGitGadget
2020-04-01 11:28               ` [PATCH v8 7/9] reftable: clarify how empty tables should be written Han-Wen Nienhuys via GitGitGadget
2020-04-01 11:28               ` [PATCH v8 8/9] Add reftable library Han-Wen Nienhuys via GitGitGadget
2020-04-01 11:28               ` [PATCH v8 9/9] Reftable support for git-core Han-Wen Nienhuys via GitGitGadget
2020-04-15 23:29               ` [PATCH v8 0/9] Reftable support git-core Junio C Hamano
2020-04-18  3:22                 ` Danh Doan
2020-04-20 21:14               ` [PATCH v9 00/10] " Han-Wen Nienhuys via GitGitGadget
2020-04-20 21:14                 ` [PATCH v9 01/10] refs.h: clarify reflog iteration order Han-Wen Nienhuys via GitGitGadget
2020-04-20 21:14                 ` [PATCH v9 02/10] Iterate over the "refs/" namespace in for_each_[raw]ref Han-Wen Nienhuys via GitGitGadget
2020-04-20 21:14                 ` [PATCH v9 03/10] create .git/refs in files-backend.c Han-Wen Nienhuys via GitGitGadget
2020-04-20 21:14                 ` [PATCH v9 04/10] refs: document how ref_iterator_advance_fn should handle symrefs Han-Wen Nienhuys via GitGitGadget
2020-04-20 21:14                 ` [PATCH v9 05/10] Add .gitattributes for the reftable/ directory Han-Wen Nienhuys via GitGitGadget
2020-04-20 21:14                 ` [PATCH v9 06/10] reftable: file format documentation Jonathan Nieder via GitGitGadget
2020-04-20 21:14                 ` [PATCH v9 07/10] reftable: define version 2 of the spec to accomodate SHA256 Han-Wen Nienhuys via GitGitGadget
2020-04-20 21:14                 ` [PATCH v9 08/10] reftable: clarify how empty tables should be written Han-Wen Nienhuys via GitGitGadget
2020-04-20 21:14                 ` [PATCH v9 09/10] Add reftable library Han-Wen Nienhuys via GitGitGadget
2020-04-20 22:06                   ` Junio C Hamano
2020-04-21 19:04                     ` Han-Wen Nienhuys
2020-04-22 17:35                     ` Johannes Schindelin
2020-04-20 21:14                 ` [PATCH v9 10/10] Reftable support for git-core Han-Wen Nienhuys via GitGitGadget
2020-04-21 20:13                 ` [PATCH v9 00/10] Reftable support git-core Junio C Hamano
2020-04-23 21:27                   ` Han-Wen Nienhuys
2020-04-23 21:43                     ` Junio C Hamano
2020-04-23 21:52                       ` Junio C Hamano
2020-04-25 13:58                         ` Johannes Schindelin
2020-04-27 20:13                 ` [PATCH v10 00/12] " Han-Wen Nienhuys via GitGitGadget
2020-04-27 20:13                   ` [PATCH v10 01/12] refs.h: clarify reflog iteration order Han-Wen Nienhuys via GitGitGadget
2020-04-27 20:13                   ` [PATCH v10 02/12] Iterate over the "refs/" namespace in for_each_[raw]ref Han-Wen Nienhuys via GitGitGadget
2020-04-30 21:17                     ` Emily Shaffer
2020-05-04 18:03                       ` Han-Wen Nienhuys
2020-05-05 18:26                         ` Pseudo ref handling (was Re: [PATCH v10 02/12] Iterate over the "refs/" namespace in for_each_[raw]ref) Han-Wen Nienhuys
2020-04-27 20:13                   ` [PATCH v10 03/12] create .git/refs in files-backend.c Han-Wen Nienhuys via GitGitGadget
2020-04-30 21:24                     ` Emily Shaffer
2020-04-30 21:49                       ` Junio C Hamano
2020-05-04 18:10                       ` Han-Wen Nienhuys
2020-04-27 20:13                   ` [PATCH v10 04/12] refs: document how ref_iterator_advance_fn should handle symrefs Han-Wen Nienhuys via GitGitGadget
2020-04-27 20:13                   ` [PATCH v10 05/12] Add .gitattributes for the reftable/ directory Han-Wen Nienhuys via GitGitGadget
2020-04-27 20:13                   ` [PATCH v10 06/12] reftable: file format documentation Jonathan Nieder via GitGitGadget
2020-04-27 20:13                   ` [PATCH v10 07/12] reftable: define version 2 of the spec to accomodate SHA256 Han-Wen Nienhuys via GitGitGadget
2020-04-27 20:13                   ` [PATCH v10 08/12] reftable: clarify how empty tables should be written Han-Wen Nienhuys via GitGitGadget
2020-04-27 20:13                   ` [PATCH v10 09/12] Add reftable library Han-Wen Nienhuys via GitGitGadget
2020-04-28 14:55                     ` Danh Doan
2020-04-28 15:29                       ` Junio C Hamano
2020-04-28 15:31                         ` Junio C Hamano
2020-04-28 20:21                       ` Han-Wen Nienhuys
2020-04-28 20:23                         ` Han-Wen Nienhuys
2020-04-27 20:13                   ` [PATCH v10 10/12] Reftable support for git-core Han-Wen Nienhuys via GitGitGadget
2020-04-27 20:13                   ` [PATCH v10 11/12] Add some reftable testing infrastructure Han-Wen Nienhuys via GitGitGadget
2020-04-27 20:13                   ` [PATCH v10 12/12] t: use update-ref and show-ref to reading/writing refs Han-Wen Nienhuys via GitGitGadget
2020-05-04 19:03                   ` [PATCH v11 00/12] Reftable support git-core Han-Wen Nienhuys via GitGitGadget
2020-05-04 19:03                     ` [PATCH v11 01/12] refs.h: clarify reflog iteration order Han-Wen Nienhuys via GitGitGadget
2020-05-04 19:03                     ` [PATCH v11 02/12] Iterate over the "refs/" namespace in for_each_[raw]ref Han-Wen Nienhuys via GitGitGadget
2020-05-04 19:03                     ` [PATCH v11 03/12] refs: document how ref_iterator_advance_fn should handle symrefs Han-Wen Nienhuys via GitGitGadget
2020-05-04 19:03                     ` [PATCH v11 04/12] Add .gitattributes for the reftable/ directory Han-Wen Nienhuys via GitGitGadget
2020-05-04 19:03                     ` [PATCH v11 05/12] reftable: file format documentation Jonathan Nieder via GitGitGadget
2020-05-04 19:03                     ` [PATCH v11 06/12] reftable: define version 2 of the spec to accomodate SHA256 Han-Wen Nienhuys via GitGitGadget
2020-05-04 19:03                     ` [PATCH v11 07/12] reftable: clarify how empty tables should be written Han-Wen Nienhuys via GitGitGadget
2020-05-04 19:03                     ` [PATCH v11 08/12] Add reftable library Han-Wen Nienhuys via GitGitGadget
2020-05-04 19:03                     ` [PATCH v11 09/12] Reftable support for git-core Han-Wen Nienhuys via GitGitGadget
2020-05-04 19:03                     ` [PATCH v11 10/12] vcxproj: adjust for the reftable changes Johannes Schindelin via GitGitGadget
2020-05-04 19:03                     ` [PATCH v11 11/12] Add some reftable testing infrastructure Han-Wen Nienhuys via GitGitGadget
2020-05-04 19:03                     ` [PATCH v11 12/12] t: use update-ref and show-ref to reading/writing refs Han-Wen Nienhuys via GitGitGadget
2020-05-06  4:29                     ` [PATCH v11 00/12] Reftable support git-core Junio C Hamano
2020-05-07  9:59                     ` [PATCH v12 " Han-Wen Nienhuys via GitGitGadget
2020-05-07  9:59                       ` [PATCH v12 01/12] refs.h: clarify reflog iteration order Han-Wen Nienhuys via GitGitGadget
2020-05-08 18:54                         ` Junio C Hamano
2020-05-07  9:59                       ` [PATCH v12 02/12] Iterate over the "refs/" namespace in for_each_[raw]ref Han-Wen Nienhuys via GitGitGadget
2020-05-08 18:54                         ` Junio C Hamano
2020-05-11 11:41                           ` Han-Wen Nienhuys
2020-05-07  9:59                       ` [PATCH v12 03/12] refs: document how ref_iterator_advance_fn should handle symrefs Han-Wen Nienhuys via GitGitGadget
2020-05-08 18:58                         ` Junio C Hamano
2020-05-11 11:42                           ` Han-Wen Nienhuys
2020-05-11 14:49                             ` Junio C Hamano
2020-05-11 15:11                               ` Han-Wen Nienhuys
2020-05-07  9:59                       ` [PATCH v12 04/12] Add .gitattributes for the reftable/ directory Han-Wen Nienhuys via GitGitGadget
2020-05-07  9:59                       ` [PATCH v12 05/12] reftable: file format documentation Jonathan Nieder via GitGitGadget
2020-05-07  9:59                       ` [PATCH v12 06/12] reftable: define version 2 of the spec to accomodate SHA256 Han-Wen Nienhuys via GitGitGadget
2020-05-08 19:59                         ` Junio C Hamano
2020-05-07  9:59                       ` [PATCH v12 07/12] reftable: clarify how empty tables should be written Han-Wen Nienhuys via GitGitGadget
2020-05-07  9:59                       ` [PATCH v12 08/12] Add reftable library Han-Wen Nienhuys via GitGitGadget
2020-05-07  9:59                       ` [PATCH v12 09/12] Reftable support for git-core Han-Wen Nienhuys via GitGitGadget
2020-05-07  9:59                       ` [PATCH v12 10/12] vcxproj: adjust for the reftable changes Johannes Schindelin via GitGitGadget
2020-05-07  9:59                       ` [PATCH v12 11/12] t: use update-ref and show-ref to reading/writing refs Han-Wen Nienhuys via GitGitGadget
2020-05-07  9:59                       ` [PATCH v12 12/12] Add some reftable testing infrastructure Han-Wen Nienhuys via GitGitGadget
2020-05-11 19:46                       ` [PATCH v13 00/13] Reftable support git-core Han-Wen Nienhuys via GitGitGadget
2020-05-11 19:46                         ` [PATCH v13 01/13] refs.h: clarify reflog iteration order Han-Wen Nienhuys via GitGitGadget
2020-05-18 23:31                           ` Junio C Hamano
2020-05-11 19:46                         ` [PATCH v13 02/13] t: use update-ref and show-ref to reading/writing refs Han-Wen Nienhuys via GitGitGadget
2020-05-18 23:34                           ` Junio C Hamano
2020-05-11 19:46                         ` [PATCH v13 03/13] refs: document how ref_iterator_advance_fn should handle symrefs Han-Wen Nienhuys via GitGitGadget
2020-05-18 23:43                           ` Junio C Hamano
2020-05-11 19:46                         ` [PATCH v13 04/13] reftable: file format documentation Jonathan Nieder via GitGitGadget
2020-05-19 22:00                           ` Junio C Hamano
2020-05-20 16:06                             ` Han-Wen Nienhuys
2020-05-20 17:20                               ` Han-Wen Nienhuys
2020-05-20 17:25                                 ` Han-Wen Nienhuys
2020-05-20 17:33                                   ` Junio C Hamano
2020-05-20 18:52                             ` Jonathan Nieder
2020-05-11 19:46                         ` [PATCH v13 05/13] reftable: clarify how empty tables should be written Han-Wen Nienhuys via GitGitGadget
2020-05-19 22:01                           ` Junio C Hamano
2020-05-11 19:46                         ` [PATCH v13 06/13] reftable: define version 2 of the spec to accomodate SHA256 Han-Wen Nienhuys via GitGitGadget
2020-05-19 22:32                           ` Junio C Hamano
2020-05-20 12:38                             ` Han-Wen Nienhuys
2020-05-20 14:40                               ` Junio C Hamano
2020-05-11 19:46                         ` [PATCH v13 07/13] Write pseudorefs through ref backends Han-Wen Nienhuys via GitGitGadget
2020-05-12 10:22                           ` Phillip Wood
2020-05-12 16:48                             ` Han-Wen Nienhuys
2020-05-13 10:06                               ` Phillip Wood
2020-05-13 18:10                                 ` Phillip Wood
2020-05-11 19:46                         ` [PATCH v13 08/13] Iterate over the "refs/" namespace in for_each_[raw]ref Han-Wen Nienhuys via GitGitGadget
2020-05-11 19:46                         ` [PATCH v13 09/13] Add .gitattributes for the reftable/ directory Han-Wen Nienhuys via GitGitGadget
2020-05-11 19:46                         ` [PATCH v13 10/13] Add reftable library Han-Wen Nienhuys via GitGitGadget
2020-05-11 19:46                         ` [PATCH v13 11/13] Reftable support for git-core Han-Wen Nienhuys via GitGitGadget
2020-05-13 19:55                           ` Junio C Hamano
2020-05-11 19:46                         ` [PATCH v13 12/13] vcxproj: adjust for the reftable changes Johannes Schindelin via GitGitGadget
2020-05-11 19:46                         ` [PATCH v13 13/13] Add some reftable testing infrastructure Han-Wen Nienhuys via GitGitGadget
2020-05-13 19:57                           ` Junio C Hamano
2020-05-19 13:54                             ` Han-Wen Nienhuys
2020-05-19 15:21                               ` Junio C Hamano
2020-05-12  0:41                         ` [PATCH v13 00/13] Reftable support git-core Junio C Hamano
2020-05-12  7:49                           ` Han-Wen Nienhuys
2020-05-13 21:21                             ` Junio C Hamano
2020-05-18 20:31                         ` [PATCH v14 0/9] " Han-Wen Nienhuys via GitGitGadget
2020-05-18 20:31                           ` [PATCH v14 1/9] Write pseudorefs through ref backends Han-Wen Nienhuys via GitGitGadget
2020-05-18 20:31                           ` [PATCH v14 2/9] Move REF_LOG_ONLY to refs-internal.h Han-Wen Nienhuys via GitGitGadget
2020-05-18 20:31                           ` [PATCH v14 3/9] Iterate over the "refs/" namespace in for_each_[raw]ref Han-Wen Nienhuys via GitGitGadget
2020-05-18 20:31                           ` [PATCH v14 4/9] Add .gitattributes for the reftable/ directory Han-Wen Nienhuys via GitGitGadget
2020-05-18 20:31                           ` [PATCH v14 5/9] Add reftable library Han-Wen Nienhuys via GitGitGadget
2020-05-18 20:31                           ` [PATCH v14 6/9] Reftable support for git-core Han-Wen Nienhuys via GitGitGadget
2020-05-18 20:31                           ` [PATCH v14 7/9] Add GIT_DEBUG_REFS debugging mechanism Han-Wen Nienhuys via GitGitGadget
2020-05-18 20:31                           ` [PATCH v14 8/9] vcxproj: adjust for the reftable changes Johannes Schindelin via GitGitGadget
2020-05-18 20:31                           ` [PATCH v14 9/9] Add reftable testing infrastructure Han-Wen Nienhuys via GitGitGadget
2020-05-28 19:46                           ` [PATCH v15 00/13] Reftable support git-core Han-Wen Nienhuys via GitGitGadget
2020-05-28 19:46                             ` [PATCH v15 01/13] Write pseudorefs through ref backends Han-Wen Nienhuys via GitGitGadget
2020-05-28 19:46                             ` [PATCH v15 02/13] Make refs_ref_exists public Han-Wen Nienhuys via GitGitGadget
2020-05-28 19:46                             ` [PATCH v15 03/13] Treat BISECT_HEAD as a pseudo ref Han-Wen Nienhuys via GitGitGadget
2020-05-28 20:52                               ` Junio C Hamano
2020-05-28 19:46                             ` [PATCH v15 04/13] Treat CHERRY_PICK_HEAD " Han-Wen Nienhuys via GitGitGadget
2020-05-28 19:46                             ` [PATCH v15 05/13] Treat REVERT_HEAD " Han-Wen Nienhuys via GitGitGadget
2020-05-28 19:46                             ` [PATCH v15 06/13] Move REF_LOG_ONLY to refs-internal.h Han-Wen Nienhuys via GitGitGadget
2020-05-28 19:46                             ` [PATCH v15 07/13] Iterate over the "refs/" namespace in for_each_[raw]ref Han-Wen Nienhuys via GitGitGadget
2020-05-28 19:46                             ` [PATCH v15 08/13] Add .gitattributes for the reftable/ directory Han-Wen Nienhuys via GitGitGadget
2020-05-28 19:46                             ` [PATCH v15 09/13] Add reftable library Han-Wen Nienhuys via GitGitGadget
2020-05-28 19:46                             ` [PATCH v15 10/13] Reftable support for git-core Han-Wen Nienhuys via GitGitGadget
2020-05-28 19:46                             ` [PATCH v15 11/13] Add GIT_DEBUG_REFS debugging mechanism Han-Wen Nienhuys via GitGitGadget
2020-05-28 19:46                             ` [PATCH v15 12/13] vcxproj: adjust for the reftable changes Johannes Schindelin via GitGitGadget
2020-05-28 19:46                             ` [PATCH v15 13/13] Add reftable testing infrastructure Han-Wen Nienhuys via GitGitGadget
2020-05-28 20:15                             ` [PATCH v15 00/13] Reftable support git-core Junio C Hamano
2020-05-28 21:21                             ` Junio C Hamano
2020-06-05 18:03                             ` [PATCH v16 00/14] " Han-Wen Nienhuys via GitGitGadget
2020-06-05 18:03                               ` [PATCH v16 01/14] Write pseudorefs through ref backends Han-Wen Nienhuys via GitGitGadget
2020-06-09 10:16                                 ` Phillip Wood
2020-06-05 18:03                               ` [PATCH v16 02/14] Make refs_ref_exists public Han-Wen Nienhuys via GitGitGadget
2020-06-09 10:36                                 ` Phillip Wood
2020-06-10 18:05                                   ` Han-Wen Nienhuys
2020-06-11 14:59                                     ` Phillip Wood
2020-06-12  9:51                                       ` Phillip Wood
2020-06-15 11:32                                         ` Han-Wen Nienhuys
2020-06-05 18:03                               ` [PATCH v16 03/14] Treat BISECT_HEAD as a pseudo ref Han-Wen Nienhuys via GitGitGadget
2020-06-05 18:03                               ` [PATCH v16 04/14] Treat CHERRY_PICK_HEAD " Han-Wen Nienhuys via GitGitGadget
2020-06-05 18:03                               ` [PATCH v16 05/14] Treat REVERT_HEAD " Han-Wen Nienhuys via GitGitGadget
2020-06-05 18:03                               ` [PATCH v16 06/14] Move REF_LOG_ONLY to refs-internal.h Han-Wen Nienhuys via GitGitGadget
2020-06-05 18:03                               ` [PATCH v16 07/14] Iterate over the "refs/" namespace in for_each_[raw]ref Han-Wen Nienhuys via GitGitGadget
2020-06-05 18:03                               ` [PATCH v16 08/14] Add .gitattributes for the reftable/ directory Han-Wen Nienhuys via GitGitGadget
2020-06-05 18:03                               ` [PATCH v16 09/14] Add reftable library Han-Wen Nienhuys via GitGitGadget
2020-06-05 18:03                               ` [PATCH v16 10/14] Reftable support for git-core Han-Wen Nienhuys via GitGitGadget
2020-06-05 18:03                               ` [PATCH v16 11/14] Hookup unittests for the reftable library Han-Wen Nienhuys via GitGitGadget
2020-06-08 19:39                                 ` Junio C Hamano
2020-06-09 17:22                                   ` [PATCH] Fixup! Add t/helper/test-reftable.c hanwen
2020-06-09 20:45                                     ` Junio C Hamano
2020-06-05 18:03                               ` [PATCH v16 12/14] Add GIT_DEBUG_REFS debugging mechanism Han-Wen Nienhuys via GitGitGadget
2020-06-05 18:03                               ` [PATCH v16 13/14] vcxproj: adjust for the reftable changes Johannes Schindelin via GitGitGadget
2020-06-05 18:03                               ` [PATCH v16 14/14] Add reftable testing infrastructure Han-Wen Nienhuys via GitGitGadget
2020-06-09 23:14                               ` [PATCH v16 00/14] Reftable support git-core Junio C Hamano
2020-06-10  6:56                                 ` Han-Wen Nienhuys
2020-06-10 17:09                                   ` Junio C Hamano
2020-06-10 17:38                                     ` Junio C Hamano
2020-06-10 18:59                                     ` Johannes Schindelin
2020-06-10 19:04                                       ` Han-Wen Nienhuys
2020-06-10 19:20                                         ` Johannes Schindelin
2020-06-10 16:57                                 ` Han-Wen Nienhuys
2020-06-16 19:20                               ` [PATCH v17 00/17] " Han-Wen Nienhuys via GitGitGadget
2020-06-16 19:20                                 ` [PATCH v17 01/17] lib-t6000.sh: write tag using git-update-ref Han-Wen Nienhuys via GitGitGadget
2020-06-16 19:20                                 ` [PATCH v17 02/17] checkout: add '\n' to reflog message Han-Wen Nienhuys via GitGitGadget
2020-06-16 19:20                                 ` [PATCH v17 03/17] Write pseudorefs through ref backends Han-Wen Nienhuys via GitGitGadget
2020-06-16 19:20                                 ` [PATCH v17 04/17] Make refs_ref_exists public Han-Wen Nienhuys via GitGitGadget
2020-06-16 19:20                                 ` [PATCH v17 05/17] Treat BISECT_HEAD as a pseudo ref Han-Wen Nienhuys via GitGitGadget
2020-06-16 19:20                                 ` [PATCH v17 06/17] Treat CHERRY_PICK_HEAD " Han-Wen Nienhuys via GitGitGadget
2020-06-16 19:20                                 ` [PATCH v17 07/17] Treat REVERT_HEAD " Han-Wen Nienhuys via GitGitGadget
2020-06-16 19:20                                 ` [PATCH v17 08/17] Move REF_LOG_ONLY to refs-internal.h Han-Wen Nienhuys via GitGitGadget
2020-06-16 19:20                                 ` [PATCH v17 09/17] Iterate over the "refs/" namespace in for_each_[raw]ref Han-Wen Nienhuys via GitGitGadget
2020-06-16 19:20                                 ` [PATCH v17 10/17] Add .gitattributes for the reftable/ directory Han-Wen Nienhuys via GitGitGadget
2020-06-16 19:20                                 ` [PATCH v17 11/17] Add reftable library Han-Wen Nienhuys via GitGitGadget
2020-06-16 19:20                                 ` [PATCH v17 12/17] Reftable support for git-core Han-Wen Nienhuys via GitGitGadget
2020-06-19 14:24                                   ` SZEDER Gábor
2020-06-16 19:20                                 ` [PATCH v17 13/17] Hookup unittests for the reftable library Han-Wen Nienhuys via GitGitGadget
2020-06-16 19:20                                 ` [PATCH v17 14/17] Add GIT_DEBUG_REFS debugging mechanism Han-Wen Nienhuys via GitGitGadget
2020-06-16 19:20                                 ` [PATCH v17 15/17] vcxproj: adjust for the reftable changes Johannes Schindelin via GitGitGadget
2020-06-16 19:20                                 ` [PATCH v17 16/17] Add reftable testing infrastructure Han-Wen Nienhuys via GitGitGadget
2020-06-19 16:03                                   ` SZEDER Gábor
2020-06-16 19:20                                 ` [PATCH v17 17/17] Add "test-tool dump-reftable" command Han-Wen Nienhuys via GitGitGadget
2020-06-22 21:55                                 ` [PATCH v18 00/19] Reftable support git-core Han-Wen Nienhuys via GitGitGadget
2020-06-22 21:55                                   ` [PATCH v18 01/19] lib-t6000.sh: write tag using git-update-ref Han-Wen Nienhuys via GitGitGadget
2020-06-22 21:55                                   ` [PATCH v18 02/19] checkout: add '\n' to reflog message Han-Wen Nienhuys via GitGitGadget
2020-06-22 21:55                                   ` [PATCH v18 03/19] Write pseudorefs through ref backends Han-Wen Nienhuys via GitGitGadget
2020-06-22 21:55                                   ` [PATCH v18 04/19] Make refs_ref_exists public Han-Wen Nienhuys via GitGitGadget
2020-06-22 21:55                                   ` [PATCH v18 05/19] Treat BISECT_HEAD as a pseudo ref Han-Wen Nienhuys via GitGitGadget
2020-06-22 21:55                                   ` [PATCH v18 06/19] Treat CHERRY_PICK_HEAD " Han-Wen Nienhuys via GitGitGadget
2020-06-22 21:55                                   ` [PATCH v18 07/19] Treat REVERT_HEAD " Han-Wen Nienhuys via GitGitGadget
2020-06-22 21:55                                   ` [PATCH v18 08/19] Move REF_LOG_ONLY to refs-internal.h Han-Wen Nienhuys via GitGitGadget
2020-06-22 21:55                                   ` [PATCH v18 09/19] Iterate over the "refs/" namespace in for_each_[raw]ref Han-Wen Nienhuys via GitGitGadget
2020-06-22 21:55                                   ` [PATCH v18 10/19] Add .gitattributes for the reftable/ directory Han-Wen Nienhuys via GitGitGadget
2020-06-22 21:55                                   ` [PATCH v18 11/19] Add reftable library Han-Wen Nienhuys via GitGitGadget
2020-06-22 21:55                                   ` [PATCH v18 12/19] Add standalone build infrastructure for reftable Han-Wen Nienhuys via GitGitGadget
2020-06-22 21:55                                   ` [PATCH v18 13/19] Reftable support for git-core Han-Wen Nienhuys via GitGitGadget
2020-06-22 21:55                                   ` [PATCH v18 14/19] Hookup unittests for the reftable library Han-Wen Nienhuys via GitGitGadget
2020-06-22 21:55                                   ` [PATCH v18 15/19] Add GIT_DEBUG_REFS debugging mechanism Han-Wen Nienhuys via GitGitGadget
2020-06-22 21:55                                   ` [PATCH v18 16/19] vcxproj: adjust for the reftable changes Johannes Schindelin via GitGitGadget
2020-06-22 21:55                                   ` [PATCH v18 17/19] git-prompt: prepare for reftable refs backend SZEDER Gábor via GitGitGadget
2020-06-22 21:55                                   ` [PATCH v18 18/19] Add reftable testing infrastructure Han-Wen Nienhuys via GitGitGadget
2020-06-22 21:55                                   ` [PATCH v18 19/19] Add "test-tool dump-reftable" command Han-Wen Nienhuys via GitGitGadget
2020-06-29 18:56                                   ` [PATCH v19 00/20] Reftable support git-core Han-Wen Nienhuys via GitGitGadget
2020-06-29 18:56                                     ` [PATCH v19 01/20] lib-t6000.sh: write tag using git-update-ref Han-Wen Nienhuys via GitGitGadget
2020-06-29 18:56                                     ` [PATCH v19 02/20] t3432: use git-reflog to inspect the reflog for HEAD Han-Wen Nienhuys via GitGitGadget
2020-06-30 15:23                                       ` Denton Liu
2020-06-29 18:56                                     ` [PATCH v19 03/20] checkout: add '\n' to reflog message Han-Wen Nienhuys via GitGitGadget
2020-06-29 20:07                                       ` Junio C Hamano
2020-06-30  8:30                                         ` Han-Wen Nienhuys
2020-06-30 23:58                                           ` Junio C Hamano
2020-07-01 16:56                                             ` Han-Wen Nienhuys
2020-07-01 20:22                                               ` Re* " Junio C Hamano
2020-07-06 15:56                                                 ` Han-Wen Nienhuys
2020-07-06 18:53                                                   ` Junio C Hamano
2020-06-29 18:56                                     ` [PATCH v19 04/20] Write pseudorefs through ref backends Han-Wen Nienhuys via GitGitGadget
2020-06-29 18:56                                     ` [PATCH v19 05/20] Make refs_ref_exists public Han-Wen Nienhuys via GitGitGadget
2020-06-29 18:56                                     ` [PATCH v19 06/20] Treat BISECT_HEAD as a pseudo ref Han-Wen Nienhuys via GitGitGadget
2020-06-29 18:56                                     ` [PATCH v19 07/20] Treat CHERRY_PICK_HEAD " Han-Wen Nienhuys via GitGitGadget
2020-06-29 18:56                                     ` [PATCH v19 08/20] Treat REVERT_HEAD " Han-Wen Nienhuys via GitGitGadget
2020-06-29 18:56                                     ` [PATCH v19 09/20] Move REF_LOG_ONLY to refs-internal.h Han-Wen Nienhuys via GitGitGadget
2020-06-29 18:56                                     ` [PATCH v19 10/20] Iterate over the "refs/" namespace in for_each_[raw]ref Han-Wen Nienhuys via GitGitGadget
2020-06-29 18:56                                     ` [PATCH v19 11/20] Add .gitattributes for the reftable/ directory Han-Wen Nienhuys via GitGitGadget
2020-06-29 18:56                                     ` [PATCH v19 12/20] Add reftable library Han-Wen Nienhuys via GitGitGadget
2020-06-29 18:56                                     ` [PATCH v19 13/20] Add standalone build infrastructure for reftable Han-Wen Nienhuys via GitGitGadget
2020-06-29 18:56                                     ` [PATCH v19 14/20] Reftable support for git-core Han-Wen Nienhuys via GitGitGadget
2020-06-29 18:56                                     ` [PATCH v19 15/20] Hookup unittests for the reftable library Han-Wen Nienhuys via GitGitGadget
2020-06-29 18:56                                     ` [PATCH v19 16/20] Add GIT_DEBUG_REFS debugging mechanism Han-Wen Nienhuys via GitGitGadget
2020-06-29 18:56                                     ` [PATCH v19 17/20] vcxproj: adjust for the reftable changes Johannes Schindelin via GitGitGadget
2020-06-29 18:56                                     ` [PATCH v19 18/20] git-prompt: prepare for reftable refs backend SZEDER Gábor via GitGitGadget
2020-06-29 18:56                                     ` [PATCH v19 19/20] Add reftable testing infrastructure Han-Wen Nienhuys via GitGitGadget
2020-06-29 18:56                                     ` [PATCH v19 20/20] Add "test-tool dump-reftable" command Han-Wen Nienhuys via GitGitGadget
2020-06-29 22:54                                     ` [PATCH v19 00/20] Reftable support git-core Junio C Hamano
2020-06-30  9:28                                       ` Han-Wen Nienhuys
2020-07-01  0:03                                         ` Junio C Hamano
2020-07-01 10:16                                           ` Han-Wen Nienhuys
2020-07-01 20:56                                             ` Junio C Hamano
2020-07-31 15:26                                     ` [PATCH v20 00/21] " Han-Wen Nienhuys via GitGitGadget
2020-07-31 15:26                                       ` [PATCH v20 01/21] refs: add \t to reflog in the files backend Han-Wen Nienhuys via GitGitGadget
2020-07-31 15:26                                       ` [PATCH v20 02/21] Split off reading loose ref data in separate function Han-Wen Nienhuys via GitGitGadget
2020-07-31 15:26                                       ` [PATCH v20 03/21] t1400: use git rev-parse for testing PSEUDOREF existence Han-Wen Nienhuys via GitGitGadget
2020-07-31 15:27                                       ` [PATCH v20 04/21] Modify pseudo refs through ref backend storage Han-Wen Nienhuys via GitGitGadget
2020-07-31 15:27                                       ` [PATCH v20 05/21] Make HEAD a PSEUDOREF rather than PER_WORKTREE Han-Wen Nienhuys via GitGitGadget
2020-07-31 15:27                                       ` [PATCH v20 06/21] Make refs_ref_exists public Han-Wen Nienhuys via GitGitGadget
2020-07-31 15:27                                       ` [PATCH v20 07/21] Treat CHERRY_PICK_HEAD as a pseudo ref Han-Wen Nienhuys via GitGitGadget
2020-07-31 15:27                                       ` [PATCH v20 08/21] Treat REVERT_HEAD " Han-Wen Nienhuys via GitGitGadget
2020-07-31 15:27                                       ` [PATCH v20 09/21] Move REF_LOG_ONLY to refs-internal.h Han-Wen Nienhuys via GitGitGadget
2020-07-31 15:27                                       ` [PATCH v20 10/21] Iteration over entire ref namespace is iterating over "refs/" Han-Wen Nienhuys via GitGitGadget
2020-07-31 15:27                                       ` [PATCH v20 11/21] Add .gitattributes for the reftable/ directory Han-Wen Nienhuys via GitGitGadget
2020-07-31 15:27                                       ` [PATCH v20 12/21] Add reftable library Han-Wen Nienhuys via GitGitGadget
2020-07-31 15:27                                       ` [PATCH v20 13/21] Add standalone build infrastructure for reftable Han-Wen Nienhuys via GitGitGadget
2020-07-31 15:27                                       ` [PATCH v20 14/21] Reftable support for git-core Han-Wen Nienhuys via GitGitGadget
2020-07-31 15:27                                       ` [PATCH v20 15/21] Read FETCH_HEAD as loose ref Han-Wen Nienhuys via GitGitGadget
2020-07-31 15:27                                       ` [PATCH v20 16/21] Hookup unittests for the reftable library Han-Wen Nienhuys via GitGitGadget
2020-07-31 15:27                                       ` [PATCH v20 17/21] Add GIT_DEBUG_REFS debugging mechanism Han-Wen Nienhuys via GitGitGadget
2020-07-31 15:27                                       ` [PATCH v20 18/21] vcxproj: adjust for the reftable changes Johannes Schindelin via GitGitGadget
2020-07-31 15:27                                       ` [PATCH v20 19/21] git-prompt: prepare for reftable refs backend SZEDER Gábor via GitGitGadget
2020-07-31 15:27                                       ` [PATCH v20 20/21] Add reftable testing infrastructure Han-Wen Nienhuys via GitGitGadget
2020-07-31 15:27                                       ` [PATCH v20 21/21] Add "test-tool dump-reftable" command Han-Wen Nienhuys via GitGitGadget

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=pull.539.v8.git.1585740538.gitgitgadget@gmail.com \
    --to=gitgitgadget@gmail.com \
    --cc=git@vger.kernel.org \
    --cc=hanwenn@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.