Files
git/t/helper/test-reftable.c
Patrick Steinhardt e0011188ca reftable/table: move printing logic into test helper
The logic to print individual blocks in a table is hosted in the
reftable library. This is only the case due to historical reasons though
because users of the library had no interfaces to read blocks one by
one. Otherwise, printing individual blocks has no place in the reftable
library given that the format will not be generic in the first place.

We have now grown a public interface to iterate through blocks contained
in a table, and thus we can finally move the logic to print them into
the test helper.

Move over the logic and refactor it accordingly. Note that the iterator
also trivially allows us to access index sections, which we previously
didn't print at all. This omission wasn't intentional though, so start
dumping those sections as well so that we can assert that indices are
written as expected.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-04-07 14:53:13 -07:00

268 lines
6.1 KiB
C

#include "git-compat-util.h"
#include "hash.h"
#include "hex.h"
#include "reftable/system.h"
#include "reftable/reftable-constants.h"
#include "reftable/reftable-error.h"
#include "reftable/reftable-merged.h"
#include "reftable/reftable-stack.h"
#include "reftable/reftable-table.h"
#include "test-tool.h"
static void print_help(void)
{
printf("usage: dump [-st] arg\n\n"
"options: \n"
" -b dump blocks\n"
" -t dump table\n"
" -s dump stack\n"
" -6 sha256 hash format\n"
" -h this help\n"
"\n");
}
static int dump_blocks(const char *tablename)
{
struct reftable_table_iterator ti = { 0 };
struct reftable_block_source src = { 0 };
struct reftable_table *table = NULL;
uint8_t section_type = 0;
int err;
err = reftable_block_source_from_file(&src, tablename);
if (err < 0)
goto done;
err = reftable_table_new(&table, &src, tablename);
if (err < 0)
goto done;
err = reftable_table_iterator_init(&ti, table);
if (err < 0)
goto done;
printf("header:\n");
printf(" block_size: %d\n", table->block_size);
while (1) {
const struct reftable_block *block;
err = reftable_table_iterator_next(&ti, &block);
if (err < 0)
goto done;
if (err > 0)
break;
if (block->block_type != section_type) {
const char *section;
switch (block->block_type) {
case REFTABLE_BLOCK_TYPE_LOG:
section = "log";
break;
case REFTABLE_BLOCK_TYPE_REF:
section = "ref";
break;
case REFTABLE_BLOCK_TYPE_OBJ:
section = "obj";
break;
case REFTABLE_BLOCK_TYPE_INDEX:
section = "idx";
break;
default:
err = -1;
goto done;
}
section_type = block->block_type;
printf("%s:\n", section);
}
printf(" - length: %u\n", block->restart_off);
printf(" restarts: %u\n", block->restart_count);
}
done:
reftable_table_iterator_release(&ti);
reftable_table_decref(table);
return err;
}
static int dump_table(struct reftable_merged_table *mt)
{
struct reftable_iterator it = { NULL };
struct reftable_ref_record ref = { NULL };
struct reftable_log_record log = { NULL };
const struct git_hash_algo *algop;
int err;
err = reftable_merged_table_init_ref_iterator(mt, &it);
if (err < 0)
return err;
err = reftable_iterator_seek_ref(&it, "");
if (err < 0)
return err;
algop = &hash_algos[hash_algo_by_id(reftable_merged_table_hash_id(mt))];
while (1) {
err = reftable_iterator_next_ref(&it, &ref);
if (err > 0)
break;
if (err < 0)
return err;
printf("ref{%s(%" PRIu64 ") ", ref.refname, ref.update_index);
switch (ref.value_type) {
case REFTABLE_REF_SYMREF:
printf("=> %s", ref.value.symref);
break;
case REFTABLE_REF_VAL2:
printf("val 2 %s", hash_to_hex_algop(ref.value.val2.value, algop));
printf("(T %s)", hash_to_hex_algop(ref.value.val2.target_value, algop));
break;
case REFTABLE_REF_VAL1:
printf("val 1 %s", hash_to_hex_algop(ref.value.val1, algop));
break;
case REFTABLE_REF_DELETION:
printf("delete");
break;
}
printf("}\n");
}
reftable_iterator_destroy(&it);
reftable_ref_record_release(&ref);
err = reftable_merged_table_init_log_iterator(mt, &it);
if (err < 0)
return err;
err = reftable_iterator_seek_log(&it, "");
if (err < 0)
return err;
while (1) {
err = reftable_iterator_next_log(&it, &log);
if (err > 0)
break;
if (err < 0)
return err;
switch (log.value_type) {
case REFTABLE_LOG_DELETION:
printf("log{%s(%" PRIu64 ") delete\n", log.refname,
log.update_index);
break;
case REFTABLE_LOG_UPDATE:
printf("log{%s(%" PRIu64 ") %s <%s> %" PRIu64 " %04d\n",
log.refname, log.update_index,
log.value.update.name ? log.value.update.name : "",
log.value.update.email ? log.value.update.email : "",
log.value.update.time,
log.value.update.tz_offset);
printf("%s => ", hash_to_hex_algop(log.value.update.old_hash, algop));
printf("%s\n\n%s\n}\n", hash_to_hex_algop(log.value.update.new_hash, algop),
log.value.update.message ? log.value.update.message : "");
break;
}
}
reftable_iterator_destroy(&it);
reftable_log_record_release(&log);
return 0;
}
static int dump_stack(const char *stackdir, uint32_t hash_id)
{
struct reftable_stack *stack = NULL;
struct reftable_write_options opts = { .hash_id = hash_id };
struct reftable_merged_table *merged = NULL;
int err = reftable_new_stack(&stack, stackdir, &opts);
if (err < 0)
goto done;
merged = reftable_stack_merged_table(stack);
err = dump_table(merged);
done:
if (stack)
reftable_stack_destroy(stack);
return err;
}
static int dump_reftable(const char *tablename)
{
struct reftable_block_source src = { 0 };
struct reftable_merged_table *mt = NULL;
struct reftable_table *table = NULL;
int err;
err = reftable_block_source_from_file(&src, tablename);
if (err < 0)
goto done;
err = reftable_table_new(&table, &src, tablename);
if (err < 0)
goto done;
err = reftable_merged_table_new(&mt, &table, 1,
reftable_table_hash_id(table));
if (err < 0)
goto done;
err = dump_table(mt);
done:
reftable_merged_table_free(mt);
reftable_table_decref(table);
return err;
}
int cmd__dump_reftable(int argc, const char **argv)
{
int err = 0;
int opt_dump_blocks = 0;
int opt_dump_table = 0;
int opt_dump_stack = 0;
uint32_t opt_hash_id = REFTABLE_HASH_SHA1;
const char *arg = NULL, *argv0 = argv[0];
for (; argc > 1; argv++, argc--)
if (*argv[1] != '-')
break;
else if (!strcmp("-b", argv[1]))
opt_dump_blocks = 1;
else if (!strcmp("-t", argv[1]))
opt_dump_table = 1;
else if (!strcmp("-6", argv[1]))
opt_hash_id = REFTABLE_HASH_SHA256;
else if (!strcmp("-s", argv[1]))
opt_dump_stack = 1;
else if (!strcmp("-?", argv[1]) || !strcmp("-h", argv[1])) {
print_help();
return 2;
}
if (argc != 2) {
fprintf(stderr, "need argument\n");
print_help();
return 2;
}
arg = argv[1];
if (opt_dump_blocks) {
err = dump_blocks(arg);
} else if (opt_dump_table) {
err = dump_reftable(arg);
} else if (opt_dump_stack) {
err = dump_stack(arg, opt_hash_id);
}
if (err < 0) {
fprintf(stderr, "%s: %s: %s\n", argv0, arg,
reftable_error_str(err));
return 1;
}
return 0;
}