git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH v3 16/19] reftable: implement refname validation

From
Han-Wen Nienhuys via GitGitGadget <gitgitgadget@gmail.com>
Date
Sep 28, 2021, 15:10 UTC
Message-ID
<46c2ddf07cfd776b4965e8ceaa38b04045a2fc80.1632841817.git.gitgitgadget@gmail.com>
In-Reply-To
<pull.1081.v3.git.git.1632841817.gitgitgadget@gmail.com>
From: Han-Wen Nienhuys <hanwen@google.com>

The packed/loose format has restrictions on refnames: a and a/b cannot coexist. This limitation does not apply to reftable per se, but must be maintained for interoperability. This code adds validation routines to abort transactions that are trying to add invalid names.

Signed-off-by: Han-Wen Nienhuys <hanwen@google.com>
---
 Makefile                 |   1 +
 reftable/refname.c       | 209 +++++++++++++++++++++++++++++++++++++++
 reftable/refname.h       |  29 ++++++
 reftable/refname_test.c  | 102 +++++++++++++++++++
 t/helper/test-reftable.c |   1 +
 5 files changed, 342 insertions(+)
 create mode 100644 reftable/refname.c
 create mode 100644 reftable/refname.h
 create mode 100644 reftable/refname_test.c
diff --git a/Makefile b/Makefile
index d90aa25f764..226012f5426 100644
--- a/Makefile
+++ b/Makefile
@@ -2456,6 +2456,7 @@ REFTABLE_TEST_OBJS += reftable/merged_test.o
 REFTABLE_TEST_OBJS += reftable/pq_test.o
 REFTABLE_TEST_OBJS += reftable/record_test.o
 REFTABLE_TEST_OBJS += reftable/readwrite_test.o
+REFTABLE_TEST_OBJS += reftable/refname_test.o
 REFTABLE_TEST_OBJS += reftable/test_framework.o
 REFTABLE_TEST_OBJS += reftable/tree_test.o
 
diff --git a/reftable/refname.c b/reftable/refname.c
new file mode 100644
index 00000000000..95734969324
--- /dev/null
+++ b/reftable/refname.c
@@ -0,0 +1,209 @@
+/*
+  Copyright 2020 Google LLC
+
+  Use of this source code is governed by a BSD-style
+  license that can be found in the LICENSE file or at
+  https://developers.google.com/open-source/licenses/bsd
+*/
+
+#include "system.h"
+#include "reftable-error.h"
+#include "basics.h"
+#include "refname.h"
+#include "reftable-iterator.h"
+
+struct find_arg {
+	char **names;
+	const char *want;
+};
+
+static int find_name(size_t k, void *arg)
+{
+	struct find_arg *f_arg = arg;
+	return strcmp(f_arg->names[k], f_arg->want) >= 0;
+}
+
+static int modification_has_ref(struct modification *mod, const char *name)
+{
+	struct reftable_ref_record ref = { NULL };
+	int err = 0;
+
+	if (mod->add_len > 0) {
+		struct find_arg arg = {
+			.names = mod->add,
+			.want = name,
+		};
+		int idx = binsearch(mod->add_len, find_name, &arg);
+		if (idx < mod->add_len && !strcmp(mod->add[idx], name)) {
+			return 0;
+		}
+	}
+
+	if (mod->del_len > 0) {
+		struct find_arg arg = {
+			.names = mod->del,
+			.want = name,
+		};
+		int idx = binsearch(mod->del_len, find_name, &arg);
+		if (idx < mod->del_len && !strcmp(mod->del[idx], name)) {
+			return 1;
+		}
+	}
+
+	err = reftable_table_read_ref(&mod->tab, name, &ref);
+	reftable_ref_record_release(&ref);
+	return err;
+}
+
+static void modification_release(struct modification *mod)
+{
+	/* don't delete the strings themselves; they're owned by ref records.
+	 */
+	FREE_AND_NULL(mod->add);
+	FREE_AND_NULL(mod->del);
+	mod->add_len = 0;
+	mod->del_len = 0;
+}
+
+static int modification_has_ref_with_prefix(struct modification *mod,
+					    const char *prefix)
+{
+	struct reftable_iterator it = { NULL };
+	struct reftable_ref_record ref = { NULL };
+	int err = 0;
+
+	if (mod->add_len > 0) {
+		struct find_arg arg = {
+			.names = mod->add,
+			.want = prefix,
+		};
+		int idx = binsearch(mod->add_len, find_name, &arg);
+		if (idx < mod->add_len &&
+		    !strncmp(prefix, mod->add[idx], strlen(prefix)))
+			goto done;
+	}
+	err = reftable_table_seek_ref(&mod->tab, &it, prefix);
+	if (err)
+		goto done;
+
+	while (1) {
+		err = reftable_iterator_next_ref(&it, &ref);
+		if (err)
+			goto done;
+
+		if (mod->del_len > 0) {
+			struct find_arg arg = {
+				.names = mod->del,
+				.want = ref.refname,
+			};
+			int idx = binsearch(mod->del_len, find_name, &arg);
+			if (idx < mod->del_len &&
+			    !strcmp(ref.refname, mod->del[idx])) {
+				continue;
+			}
+		}
+
+		if (strncmp(ref.refname, prefix, strlen(prefix))) {
+			err = 1;
+			goto done;
+		}
+		err = 0;
+		goto done;
+	}
+
+done:
+	reftable_ref_record_release(&ref);
+	reftable_iterator_destroy(&it);
+	return err;
+}
+
+static int validate_refname(const char *name)
+{
+	while (1) {
+		char *next = strchr(name, '/');
+		if (!*name) {
+			return REFTABLE_REFNAME_ERROR;
+		}
+		if (!next) {
+			return 0;
+		}
+		if (next - name == 0 || (next - name == 1 && *name == '.') ||
+		    (next - name == 2 && name[0] == '.' && name[1] == '.'))
+			return REFTABLE_REFNAME_ERROR;
+		name = next + 1;
+	}
+	return 0;
+}
+
+int validate_ref_record_addition(struct reftable_table tab,
+				 struct reftable_ref_record *recs, size_t sz)
+{
+	struct modification mod = {
+		.tab = tab,
+		.add = reftable_calloc(sizeof(char *) * sz),
+		.del = reftable_calloc(sizeof(char *) * sz),
+	};
+	int i = 0;
+	int err = 0;
+	for (; i < sz; i++) {
+		if (reftable_ref_record_is_deletion(&recs[i])) {
+			mod.del[mod.del_len++] = recs[i].refname;
+		} else {
+			mod.add[mod.add_len++] = recs[i].refname;
+		}
+	}
+
+	err = modification_validate(&mod);
+	modification_release(&mod);
+	return err;
+}
+
+static void strbuf_trim_component(struct strbuf *sl)
+{
+	while (sl->len > 0) {
+		int is_slash = (sl->buf[sl->len - 1] == '/');
+		strbuf_setlen(sl, sl->len - 1);
+		if (is_slash)
+			break;
+	}
+}
+
+int modification_validate(struct modification *mod)
+{
+	struct strbuf slashed = STRBUF_INIT;
+	int err = 0;
+	int i = 0;
+	for (; i < mod->add_len; i++) {
+		err = validate_refname(mod->add[i]);
+		if (err)
+			goto done;
+		strbuf_reset(&slashed);
+		strbuf_addstr(&slashed, mod->add[i]);
+		strbuf_addstr(&slashed, "/");
+
+		err = modification_has_ref_with_prefix(mod, slashed.buf);
+		if (err == 0) {
+			err = REFTABLE_NAME_CONFLICT;
+			goto done;
+		}
+		if (err < 0)
+			goto done;
+
+		strbuf_reset(&slashed);
+		strbuf_addstr(&slashed, mod->add[i]);
+		while (slashed.len) {
+			strbuf_trim_component(&slashed);
+			err = modification_has_ref(mod, slashed.buf);
+			if (err == 0) {
+				err = REFTABLE_NAME_CONFLICT;
+				goto done;
+			}
+			if (err < 0)
+				goto done;
+		}
+	}
+	err = 0;
+done:
+	strbuf_release(&slashed);
+	return err;
+}
diff --git a/reftable/refname.h b/reftable/refname.h
new file mode 100644
index 00000000000..a24b40fcb42
--- /dev/null
+++ b/reftable/refname.h
@@ -0,0 +1,29 @@
+/*
+  Copyright 2020 Google LLC
+
+  Use of this source code is governed by a BSD-style
+  license that can be found in the LICENSE file or at
+  https://developers.google.com/open-source/licenses/bsd
+*/
+#ifndef REFNAME_H
+#define REFNAME_H
+
+#include "reftable-record.h"
+#include "reftable-generic.h"
+
+struct modification {
+	struct reftable_table tab;
+
+	char **add;
+	size_t add_len;
+
+	char **del;
+	size_t del_len;
+};
+
+int validate_ref_record_addition(struct reftable_table tab,
+				 struct reftable_ref_record *recs, size_t sz);
+
+int modification_validate(struct modification *mod);
+
+#endif
diff --git a/reftable/refname_test.c b/reftable/refname_test.c
new file mode 100644
index 00000000000..8645cd93bbd
--- /dev/null
+++ b/reftable/refname_test.c
@@ -0,0 +1,102 @@
+/*
+Copyright 2020 Google LLC
+
+Use of this source code is governed by a BSD-style
+license that can be found in the LICENSE file or at
+https://developers.google.com/open-source/licenses/bsd
+*/
+
+#include "basics.h"
+#include "block.h"
+#include "blocksource.h"
+#include "constants.h"
+#include "reader.h"
+#include "record.h"
+#include "refname.h"
+#include "reftable-error.h"
+#include "reftable-writer.h"
+#include "system.h"
+
+#include "test_framework.h"
+#include "reftable-tests.h"
+
+struct testcase {
+	char *add;
+	char *del;
+	int error_code;
+};
+
+static void test_conflict(void)
+{
+	struct reftable_write_options opts = { 0 };
+	struct strbuf buf = STRBUF_INIT;
+	struct reftable_writer *w =
+		reftable_new_writer(&strbuf_add_void, &buf, &opts);
+	struct reftable_ref_record rec = {
+		.refname = "a/b",
+		.value_type = REFTABLE_REF_SYMREF,
+		.value.symref = "destination", /* make sure it's not a symref.
+						*/
+		.update_index = 1,
+	};
+	int err;
+	int i;
+	struct reftable_block_source source = { NULL };
+	struct reftable_reader *rd = NULL;
+	struct reftable_table tab = { NULL };
+	struct testcase cases[] = {
+		{ "a/b/c", NULL, REFTABLE_NAME_CONFLICT },
+		{ "b", NULL, 0 },
+		{ "a", NULL, REFTABLE_NAME_CONFLICT },
+		{ "a", "a/b", 0 },
+
+		{ "p/", NULL, REFTABLE_REFNAME_ERROR },
+		{ "p//q", NULL, REFTABLE_REFNAME_ERROR },
+		{ "p/./q", NULL, REFTABLE_REFNAME_ERROR },
+		{ "p/../q", NULL, REFTABLE_REFNAME_ERROR },
+
+		{ "a/b/c", "a/b", 0 },
+		{ NULL, "a//b", 0 },
+	};
+	reftable_writer_set_limits(w, 1, 1);
+
+	err = reftable_writer_add_ref(w, &rec);
+	EXPECT_ERR(err);
+
+	err = reftable_writer_close(w);
+	EXPECT_ERR(err);
+	reftable_writer_free(w);
+
+	block_source_from_strbuf(&source, &buf);
+	err = reftable_new_reader(&rd, &source, "filename");
+	EXPECT_ERR(err);
+
+	reftable_table_from_reader(&tab, rd);
+
+	for (i = 0; i < ARRAY_SIZE(cases); i++) {
+		struct modification mod = {
+			.tab = tab,
+		};
+
+		if (cases[i].add) {
+			mod.add = &cases[i].add;
+			mod.add_len = 1;
+		}
+		if (cases[i].del) {
+			mod.del = &cases[i].del;
+			mod.del_len = 1;
+		}
+
+		err = modification_validate(&mod);
+		EXPECT(err == cases[i].error_code);
+	}
+
+	reftable_reader_free(rd);
+	strbuf_release(&buf);
+}
+
+int refname_test_main(int argc, const char *argv[])
+{
+	RUN_TEST(test_conflict);
+	return 0;
+}
diff --git a/t/helper/test-reftable.c b/t/helper/test-reftable.c
index 8087f2da4e6..c8db6852c35 100644
--- a/t/helper/test-reftable.c
+++ b/t/helper/test-reftable.c
@@ -8,6 +8,7 @@ int cmd__reftable(int argc, const char **argv)
 	merged_test_main(argc, argv);
 	pq_test_main(argc, argv);
 	record_test_main(argc, argv);
+	refname_test_main(argc, argv);
 	readwrite_test_main(argc, argv);
 	tree_test_main(argc, argv);
 	return 0;
-- 
gitgitgadget
Previous: Han-Wen Nienhuys via GitGitGadgetNext: Han-Wen Nienhuys via GitGitGadget
Message 75 of 111 in “Adds reftable library code from https://github.com/hanwen/reftable.”
  1. 00/19 Adds reftable library code from https://github.com/hanwen/reftable.Han-Wen Nienhuys via GitGitGadget, Aug 30, 2021
  2. 01/19 hash.h: provide constants for the hash IDsHan-Wen Nienhuys via GitGitGadget, Aug 30, 2021
  3. 03/19 reftable: add error related functionalityHan-Wen Nienhuys via GitGitGadget, Aug 30, 2021
  4. 02/19 reftable: RFC: add LICENSEHan-Wen Nienhuys via GitGitGadget, Aug 30, 2021
  5. 04/19 reftable: utility functionsHan-Wen Nienhuys via GitGitGadget, Aug 30, 2021
  6. 05/19 reftable: add blocksource, an abstraction for random access readsHan-Wen Nienhuys via GitGitGadget, Aug 30, 2021
  7. 07/19 Provide zlib's uncompress2 from compat/zlib-compat.cHan-Wen Nienhuys via GitGitGadget, Aug 30, 2021
  8. fixup! Provide zlib's uncompress2 from compat/zlib-compat.cCarlo Marcelo Arenas Belón, Sep 2, 2021
  9. 06/19 reftable: (de)serialization for the polymorphic record type.Han-Wen Nienhuys via GitGitGadget, Aug 30, 2021
  10. 09/19 reftable: a generic binary tree implementationHan-Wen Nienhuys via GitGitGadget, Aug 30, 2021
  11. 08/19 reftable: reading/writing blocksHan-Wen Nienhuys via GitGitGadget, Aug 30, 2021
  12. 11/19 reftable: generic interface to tablesHan-Wen Nienhuys via GitGitGadget, Aug 30, 2021
  13. 14/19 reftable: add a heap-based priority queue for reftable recordsHan-Wen Nienhuys via GitGitGadget, Aug 30, 2021
  14. 10/19 reftable: write reftable filesHan-Wen Nienhuys via GitGitGadget, Aug 30, 2021
  15. 13/19 reftable: reftable file level testsHan-Wen Nienhuys via GitGitGadget, Aug 30, 2021
  16. 12/19 reftable: read reftable filesHan-Wen Nienhuys via GitGitGadget, Aug 30, 2021
  17. 15/19 reftable: add merged table viewHan-Wen Nienhuys via GitGitGadget, Aug 30, 2021
  18. 16/19 reftable: implement refname validationHan-Wen Nienhuys via GitGitGadget, Aug 30, 2021
  19. 18/19 reftable: add dump utilityHan-Wen Nienhuys via GitGitGadget, Aug 30, 2021
  20. 19/19 Add "test-tool dump-reftable" command.Han-Wen Nienhuys via GitGitGadget, Aug 30, 2021
  21. 17/19 reftable: implement stack, a mutable database of reftable files.Han-Wen Nienhuys via GitGitGadget, Aug 30, 2021
  22. Han-Wen NienhuysAug 30, 2021
  23. 0/4 fixup for hn/reftableCarlo Marcelo Arenas Belón, Sep 8, 2021
  24. 1/4 fixup! reftable: reading/writing blocksCarlo Marcelo Arenas Belón, Sep 8, 2021
  25. 2/4 fixup! reftable: utility functionsCarlo Marcelo Arenas Belón, Sep 8, 2021
  26. 3/4 fixup! Provide zlib's uncompress2 from compat/zlib-compat.cCarlo Marcelo Arenas Belón, Sep 8, 2021
  27. 4/4 fixup! reftable: utility functionsCarlo Marcelo Arenas Belón, Sep 8, 2021
  28. Junio C HamanoSep 8, 2021
  29. 00/19 Adds reftable library code from https://github.com/hanwen/reftable.Han-Wen Nienhuys via GitGitGadget, Sep 9, 2021
  30. 01/19 hash.h: provide constants for the hash IDsHan-Wen Nienhuys via GitGitGadget, Sep 9, 2021
  31. 02/19 reftable: RFC: add LICENSEHan-Wen Nienhuys via GitGitGadget, Sep 9, 2021
  32. 03/19 reftable: add error related functionalityHan-Wen Nienhuys via GitGitGadget, Sep 9, 2021
  33. 04/19 reftable: utility functionsHan-Wen Nienhuys via GitGitGadget, Sep 9, 2021
  34. 06/19 reftable: (de)serialization for the polymorphic record type.Han-Wen Nienhuys via GitGitGadget, Sep 9, 2021
  35. 07/19 Provide zlib's uncompress2 from compat/zlib-compat.cHan-Wen Nienhuys via GitGitGadget, Sep 9, 2021
  36. Carlo ArenasSep 15, 2021
  37. 05/19 reftable: add blocksource, an abstraction for random access readsHan-Wen Nienhuys via GitGitGadget, Sep 9, 2021
  38. 08/19 reftable: reading/writing blocksHan-Wen Nienhuys via GitGitGadget, Sep 9, 2021
  39. Ævar Arnfjörð BjarmasonSep 24, 2021
  40. 09/19 reftable: a generic binary tree implementationHan-Wen Nienhuys via GitGitGadget, Sep 9, 2021
  41. 10/19 reftable: write reftable filesHan-Wen Nienhuys via GitGitGadget, Sep 9, 2021
  42. 11/19 reftable: generic interface to tablesHan-Wen Nienhuys via GitGitGadget, Sep 9, 2021
  43. 12/19 reftable: read reftable filesHan-Wen Nienhuys via GitGitGadget, Sep 9, 2021
  44. 14/19 reftable: add a heap-based priority queue for reftable recordsHan-Wen Nienhuys via GitGitGadget, Sep 9, 2021
  45. 13/19 reftable: reftable file level testsHan-Wen Nienhuys via GitGitGadget, Sep 9, 2021
  46. 16/19 reftable: implement refname validationHan-Wen Nienhuys via GitGitGadget, Sep 9, 2021
  47. 15/19 reftable: add merged table viewHan-Wen Nienhuys via GitGitGadget, Sep 9, 2021
  48. 17/19 reftable: implement stack, a mutable database of reftable files.Han-Wen Nienhuys via GitGitGadget, Sep 9, 2021
  49. 18/19 reftable: add dump utilityHan-Wen Nienhuys via GitGitGadget, Sep 9, 2021
  50. 19/19 Add "test-tool dump-reftable" command.Han-Wen Nienhuys via GitGitGadget, Sep 9, 2021
  51. Junio C HamanoSep 9, 2021
  52. Junio C HamanoSep 9, 2021
  53. Han-Wen NienhuysSep 13, 2021
  54. Junio C HamanoSep 13, 2021
  55. Carlo ArenasSep 13, 2021
  56. Junio C HamanoSep 13, 2021
  57. 00/19 Adds reftable library code from https://github.com/hanwen/reftable.Han-Wen Nienhuys via GitGitGadget, Sep 28, 2021
  58. 02/19 reftable: RFC: add LICENSEHan-Wen Nienhuys via GitGitGadget, Sep 28, 2021
  59. 03/19 reftable: add error related functionalityHan-Wen Nienhuys via GitGitGadget, Sep 28, 2021
  60. 01/19 hash.h: provide constants for the hash IDsHan-Wen Nienhuys via GitGitGadget, Sep 28, 2021
  61. 04/19 reftable: utility functionsHan-Wen Nienhuys via GitGitGadget, Sep 28, 2021
  62. 05/19 reftable: add blocksource, an abstraction for random access readsHan-Wen Nienhuys via GitGitGadget, Sep 28, 2021
  63. 06/19 reftable: (de)serialization for the polymorphic record type.Han-Wen Nienhuys via GitGitGadget, Sep 28, 2021
  64. 07/19 Provide zlib's uncompress2 from compat/zlib-compat.cHan-Wen Nienhuys via GitGitGadget, Sep 28, 2021
  65. 09/19 reftable: a generic binary tree implementationHan-Wen Nienhuys via GitGitGadget, Sep 28, 2021
  66. 08/19 reftable: reading/writing blocksHan-Wen Nienhuys via GitGitGadget, Sep 28, 2021
  67. squash! reftable: reading/writing blocksCarlo Marcelo Arenas Belón, Sep 30, 2021
  68. Han-Wen NienhuysOct 7, 2021
  69. 10/19 reftable: write reftable filesHan-Wen Nienhuys via GitGitGadget, Sep 28, 2021
  70. 11/19 reftable: generic interface to tablesHan-Wen Nienhuys via GitGitGadget, Sep 28, 2021
  71. 12/19 reftable: read reftable filesHan-Wen Nienhuys via GitGitGadget, Sep 28, 2021
  72. 15/19 reftable: add merged table viewHan-Wen Nienhuys via GitGitGadget, Sep 28, 2021
  73. 13/19 reftable: reftable file level testsHan-Wen Nienhuys via GitGitGadget, Sep 28, 2021
  74. 14/19 reftable: add a heap-based priority queue for reftable recordsHan-Wen Nienhuys via GitGitGadget, Sep 28, 2021
  75. 16/19 reftable: implement refname validationHan-Wen Nienhuys via GitGitGadget, Sep 28, 2021
  76. 17/19 reftable: implement stack, a mutable database of reftable files.Han-Wen Nienhuys via GitGitGadget, Sep 28, 2021
  77. 18/19 reftable: add dump utilityHan-Wen Nienhuys via GitGitGadget, Sep 28, 2021
  78. 19/19 Add "test-tool dump-reftable" command.Han-Wen Nienhuys via GitGitGadget, Sep 28, 2021
  79. Junio C HamanoSep 28, 2021
  80. Ævar Arnfjörð BjarmasonOct 2, 2021
  81. hn/reftable "fixes"Carlo Marcelo Arenas Belón, Sep 30, 2021
  82. 1/4 fixup! reftable: add a heap-based priority queue for reftable recordsCarlo Marcelo Arenas Belón, Sep 30, 2021
  83. 2/4 fixup! reftable: implement stack, a mutable database of reftable files.Carlo Marcelo Arenas Belón, Sep 30, 2021
  84. C++(C99)-style comments in git.gitÆvar Arnfjörð Bjarmason, Oct 1, 2021
  85. 3/4 config.mak.uname: last release and snapshots of Minix still use zlib 1.2.3Carlo Marcelo Arenas Belón, Sep 30, 2021
  86. 4/4 reftable: avoid non portable compile time pointer to functionCarlo Marcelo Arenas Belón, Sep 30, 2021
  87. Junio C HamanoSep 30, 2021
  88. 00/19 Adds reftable library code from https://github.com/hanwen/reftable.Han-Wen Nienhuys via GitGitGadget, Oct 7, 2021
  89. 01/19 hash.h: provide constants for the hash IDsHan-Wen Nienhuys via GitGitGadget, Oct 7, 2021
  90. 02/19 reftable: add LICENSEHan-Wen Nienhuys via GitGitGadget, Oct 7, 2021
  91. 03/19 reftable: add error related functionalityHan-Wen Nienhuys via GitGitGadget, Oct 7, 2021
  92. 04/19 reftable: utility functionsHan-Wen Nienhuys via GitGitGadget, Oct 7, 2021
  93. 05/19 reftable: add blocksource, an abstraction for random access readsHan-Wen Nienhuys via GitGitGadget, Oct 7, 2021
  94. 09/19 reftable: a generic binary tree implementationHan-Wen Nienhuys via GitGitGadget, Oct 7, 2021
  95. 10/19 reftable: write reftable filesHan-Wen Nienhuys via GitGitGadget, Oct 7, 2021
  96. 11/19 reftable: generic interface to tablesHan-Wen Nienhuys via GitGitGadget, Oct 7, 2021
  97. 08/19 reftable: reading/writing blocksHan-Wen Nienhuys via GitGitGadget, Oct 7, 2021
  98. 12/19 reftable: read reftable filesHan-Wen Nienhuys via GitGitGadget, Oct 7, 2021
  99. 06/19 reftable: (de)serialization for the polymorphic record type.Han-Wen Nienhuys via GitGitGadget, Oct 7, 2021
  100. 07/19 Provide zlib's uncompress2 from compat/zlib-compat.cHan-Wen Nienhuys via GitGitGadget, Oct 7, 2021
  101. 13/19 reftable: reftable file level testsHan-Wen Nienhuys via GitGitGadget, Oct 7, 2021
  102. 14/19 reftable: add a heap-based priority queue for reftable recordsHan-Wen Nienhuys via GitGitGadget, Oct 7, 2021
  103. 15/19 reftable: add merged table viewHan-Wen Nienhuys via GitGitGadget, Oct 7, 2021
  104. reftable tests: use C syntax compatible with old xlcÆvar Arnfjörð Bjarmason, Jan 13, 2022
  105. Han-Wen NienhuysJan 13, 2022
  106. Ævar Arnfjörð BjarmasonJan 13, 2022
  107. Junio C HamanoJan 13, 2022
  108. 16/19 reftable: implement refname validationHan-Wen Nienhuys via GitGitGadget, Oct 7, 2021
  109. 18/19 reftable: add dump utilityHan-Wen Nienhuys via GitGitGadget, Oct 7, 2021
  110. 17/19 reftable: implement stack, a mutable database of reftable files.Han-Wen Nienhuys via GitGitGadget, Oct 7, 2021
  111. 19/19 Add "test-tool dump-reftable" command.Han-Wen Nienhuys via GitGitGadget, Oct 7, 2021

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.