Git fork

refs/reftable: add fsck check for checking the table name

Add glue code in 'refs/reftable-backend.c' which calls the reftable
library to perform the fsck checks. Here we also map the reftable errors
to Git' fsck errors.

Introduce a check to validate table names for a given reftable stack.
Also add 'badReftableTableName' as a corresponding error within Git. The
reftable specification mentions:

It suggested to use
${min_update_index}-${max_update_index}-${random}.ref as a naming
convention.

So treat non-conformant file names as warnings.

While adding the fsck header to 'refs/reftable-backend.c', modify the
list to maintain lexicographical ordering.

Signed-off-by: Karthik Nayak <karthik.188@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>

authored by

Karthik Nayak and committed by
Junio C Hamano
466a3a1a 90516385

+115 -5
+3
Documentation/fsck-msgids.adoc
··· 38 38 `badReferentName`:: 39 39 (ERROR) The referent name of a symref is invalid. 40 40 41 + `badReftableTableName`:: 42 + (WARN) A reftable table has an invalid name. 43 + 41 44 `badTagName`:: 42 45 (INFO) A tag has an invalid format. 43 46
+1
fsck.h
··· 73 73 FUNC(UNKNOWN_TYPE, ERROR) \ 74 74 FUNC(ZERO_PADDED_DATE, ERROR) \ 75 75 /* warnings */ \ 76 + FUNC(BAD_REFTABLE_TABLE_NAME, WARN) \ 76 77 FUNC(EMPTY_NAME, WARN) \ 77 78 FUNC(FULL_PATHNAME, WARN) \ 78 79 FUNC(HAS_DOT, WARN) \
+52 -5
refs/reftable-backend.c
··· 6 6 #include "../config.h" 7 7 #include "../dir.h" 8 8 #include "../environment.h" 9 + #include "../fsck.h" 9 10 #include "../gettext.h" 10 11 #include "../hash.h" 11 12 #include "../hex.h" ··· 15 16 #include "../path.h" 16 17 #include "../refs.h" 17 18 #include "../reftable/reftable-basics.h" 18 - #include "../reftable/reftable-stack.h" 19 - #include "../reftable/reftable-record.h" 20 19 #include "../reftable/reftable-error.h" 20 + #include "../reftable/reftable-fsck.h" 21 21 #include "../reftable/reftable-iterator.h" 22 + #include "../reftable/reftable-record.h" 23 + #include "../reftable/reftable-stack.h" 22 24 #include "../repo-settings.h" 23 25 #include "../setup.h" 24 26 #include "../strmap.h" ··· 2674 2676 return ret; 2675 2677 } 2676 2678 2677 - static int reftable_be_fsck(struct ref_store *ref_store UNUSED, 2678 - struct fsck_options *o UNUSED, 2679 + static void reftable_fsck_verbose_handler(const char *msg, void *cb_data) 2680 + { 2681 + struct fsck_options *o = cb_data; 2682 + 2683 + if (o->verbose) 2684 + fprintf_ln(stderr, "%s", msg); 2685 + } 2686 + 2687 + static const enum fsck_msg_id fsck_msg_id_map[] = { 2688 + [REFTABLE_FSCK_ERROR_TABLE_NAME] = FSCK_MSG_BAD_REFTABLE_TABLE_NAME, 2689 + }; 2690 + 2691 + static int reftable_fsck_error_handler(struct reftable_fsck_info *info, 2692 + void *cb_data) 2693 + { 2694 + struct fsck_ref_report report = { .path = info->path }; 2695 + struct fsck_options *o = cb_data; 2696 + enum fsck_msg_id msg_id; 2697 + 2698 + if (info->error < 0 || info->error >= REFTABLE_FSCK_MAX_VALUE) 2699 + BUG("unknown fsck error: %d", (int)info->error); 2700 + 2701 + msg_id = fsck_msg_id_map[info->error]; 2702 + 2703 + if (!msg_id) 2704 + BUG("fsck_msg_id value missing for reftable error: %d", (int)info->error); 2705 + 2706 + return fsck_report_ref(o, &report, msg_id, "%s", info->msg); 2707 + } 2708 + 2709 + static int reftable_be_fsck(struct ref_store *ref_store, struct fsck_options *o, 2679 2710 struct worktree *wt UNUSED) 2680 2711 { 2681 - return 0; 2712 + struct reftable_ref_store *refs; 2713 + struct strmap_entry *entry; 2714 + struct hashmap_iter iter; 2715 + int ret = 0; 2716 + 2717 + refs = reftable_be_downcast(ref_store, REF_STORE_READ, "fsck"); 2718 + 2719 + ret |= reftable_fsck_check(refs->main_backend.stack, reftable_fsck_error_handler, 2720 + reftable_fsck_verbose_handler, o); 2721 + 2722 + strmap_for_each_entry(&refs->worktree_backends, &iter, entry) { 2723 + struct reftable_backend *b = (struct reftable_backend *)entry->value; 2724 + ret |= reftable_fsck_check(b->stack, reftable_fsck_error_handler, 2725 + reftable_fsck_verbose_handler, o); 2726 + } 2727 + 2728 + return ret; 2682 2729 } 2683 2730 2684 2731 struct ref_storage_be refs_be_reftable = {
+1
t/meson.build
··· 145 145 't0611-reftable-httpd.sh', 146 146 't0612-reftable-jgit-compatibility.sh', 147 147 't0613-reftable-write-options.sh', 148 + 't0614-reftable-fsck.sh', 148 149 't1000-read-tree-m-3way.sh', 149 150 't1001-read-tree-m-2way.sh', 150 151 't1002-read-tree-m-u-2way.sh',
+58
t/t0614-reftable-fsck.sh
··· 1 + #!/bin/sh 2 + 3 + test_description='Test reftable backend consistency check' 4 + 5 + GIT_TEST_DEFAULT_REF_FORMAT=reftable 6 + export GIT_TEST_DEFAULT_REF_FORMAT 7 + 8 + . ./test-lib.sh 9 + 10 + test_expect_success "no errors reported on a well formed repository" ' 11 + test_when_finished "rm -rf repo" && 12 + git init repo && 13 + ( 14 + cd repo && 15 + git commit --allow-empty -m initial && 16 + 17 + for i in $(test_seq 20) 18 + do 19 + git update-ref refs/heads/branch-$i HEAD || return 1 20 + done && 21 + 22 + # The repository should end up with multiple tables. 23 + test_line_count ">" 1 .git/reftable/tables.list && 24 + 25 + git refs verify 2>err && 26 + test_must_be_empty err 27 + ) 28 + ' 29 + 30 + for TABLE_NAME in "foo-bar-e4d12d59.ref" \ 31 + "0x00000000zzzz-0x00000000zzzz-e4d12d59.ref" \ 32 + "0x000000000001-0x000000000002-e4d12d59.abc" \ 33 + "0x000000000001-0x000000000002-e4d12d59.refabc"; do 34 + test_expect_success "table name $TABLE_NAME should be checked" ' 35 + test_when_finished "rm -rf repo" && 36 + git init repo && 37 + ( 38 + cd repo && 39 + git commit --allow-empty -m initial && 40 + 41 + git refs verify 2>err && 42 + test_must_be_empty err && 43 + 44 + EXISTING_TABLE=$(head -n1 .git/reftable/tables.list) && 45 + mv ".git/reftable/$EXISTING_TABLE" ".git/reftable/$TABLE_NAME" && 46 + sed "s/${EXISTING_TABLE}/${TABLE_NAME}/g" .git/reftable/tables.list > tables.list && 47 + mv tables.list .git/reftable/tables.list && 48 + 49 + git refs verify 2>err && 50 + cat >expect <<-EOF && 51 + warning: ${TABLE_NAME}: badReftableTableName: invalid reftable table name 52 + EOF 53 + test_cmp expect err 54 + ) 55 + ' 56 + done 57 + 58 + test_done