refs: set up ref consistency check infrastructure

The "struct ref_store" is the base class which contains the "be" pointer which provides backend-specific functions whose interfaces are defined in the "ref_storage_be". We could reuse this polymorphism to define only one interface. For every backend, we need to provide its own function pointer. The interfaces defined in the `ref_storage_be` are carefully structured in semantic. It's organized as the five parts: 1. The name and the initialization interfaces. 2. The ref transaction interfaces. 3. The ref internal interfaces (pack, rename and copy). 4. The ref filesystem interfaces. 5. The reflog related interfaces. To keep consistent with the git-fsck(1), add a new interface named "fsck_refs_fn" to the end of "ref_storage_be". This semantic cannot be grouped into any above five categories. Explicitly add blank line to make it different from others. Last, implement placeholder functions for each ref backends. Mentored-by: Patrick Steinhardt <ps@pks.im> Mentored-by: Karthik Nayak <karthik.188@gmail.com> Signed-off-by: shejialuo <shejialuo@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

shejialuo committed Aug 8, 2024 at 19:27 UTC ab6f79d8df7c7799ed38229eb56811fda36853ae
7 files changed +58 -1
refs.c
+5
@@ -318,6 +318,11 @@ int check_refname_format(const char *refname, int flags)
318 return check_or_sanitize_refname(refname, flags, NULL);
319 }
320
321 +int refs_fsck(struct ref_store *refs, struct fsck_options *o)
322 +{
323 + return refs->be->fsck(refs, o);
324 +}
325 +
326 void sanitize_refname_component(const char *refname, struct strbuf *out)
327 {
328 if (check_or_sanitize_refname(refname, REFNAME_ALLOW_ONELEVEL, out))
refs.h
+8
@@ -4,6 +4,7 @@
4 #include "commit.h"
5 #include "repository.h"
6
7 +struct fsck_options;
8 struct object_id;
9 struct ref_store;
10 struct strbuf;
@@ -541,6 +542,13 @@ int refs_for_each_reflog(struct ref_store *refs, each_reflog_fn fn, void *cb_dat
542 */
543 int check_refname_format(const char *refname, int flags);
544
545 +/*
546 + * Check the reference database for consistency. Return 0 if refs and
547 + * reflogs are consistent, and non-zero otherwise. The errors will be
548 + * written to stderr.
549 + */
550 +int refs_fsck(struct ref_store *refs, struct fsck_options *o);
551 +
552 /*
553 * Apply the rules from check_refname_format, but mutate the result until it
554 * is acceptable, and place the result in "out".
refs/debug.c
+11
@@ -419,6 +419,15 @@ static int debug_reflog_expire(struct ref_store *ref_store, const char *refname,
419 return res;
420 }
421
422 +static int debug_fsck(struct ref_store *ref_store,
423 + struct fsck_options *o)
424 +{
425 + struct debug_ref_store *drefs = (struct debug_ref_store *)ref_store;
426 + int res = drefs->refs->be->fsck(drefs->refs, o);
427 + trace_printf_key(&trace_refs, "fsck: %d\n", res);
428 + return res;
429 +}
430 +
431 struct ref_storage_be refs_be_debug = {
432 .name = "debug",
433 .init = NULL,
@@ -451,4 +460,6 @@ struct ref_storage_be refs_be_debug = {
460 .create_reflog = debug_create_reflog,
461 .delete_reflog = debug_delete_reflog,
462 .reflog_expire = debug_reflog_expire,
463 +
464 + .fsck = debug_fsck,
465 };
refs/files-backend.c
+12 -1
@@ -3408,6 +3408,15 @@ static int files_ref_store_remove_on_disk(struct ref_store *ref_store,
3408 return ret;
3409 }
3410
3411 +static int files_fsck(struct ref_store *ref_store,
3412 + struct fsck_options *o)
3413 +{
3414 + struct files_ref_store *refs =
3415 + files_downcast(ref_store, REF_STORE_READ, "fsck");
3416 +
3417 + return refs->packed_ref_store->be->fsck(refs->packed_ref_store, o);
3418 +}
3419 +
3420 struct ref_storage_be refs_be_files = {
3421 .name = "files",
3422 .init = files_ref_store_init,
@@ -3434,5 +3443,7 @@ struct ref_storage_be refs_be_files = {
3443 .reflog_exists = files_reflog_exists,
3444 .create_reflog = files_create_reflog,
3445 .delete_reflog = files_delete_reflog,
3437 - .reflog_expire = files_reflog_expire
3446 + .reflog_expire = files_reflog_expire,
3447 +
3448 + .fsck = files_fsck,
3449 };
refs/packed-backend.c
+8
@@ -1735,6 +1735,12 @@ static struct ref_iterator *packed_reflog_iterator_begin(struct ref_store *ref_s
1735 return empty_ref_iterator_begin();
1736 }
1737
1738 +static int packed_fsck(struct ref_store *ref_store,
1739 + struct fsck_options *o)
1740 +{
1741 + return 0;
1742 +}
1743 +
1744 struct ref_storage_be refs_be_packed = {
1745 .name = "packed",
1746 .init = packed_ref_store_init,
@@ -1762,4 +1768,6 @@ struct ref_storage_be refs_be_packed = {
1768 .create_reflog = NULL,
1769 .delete_reflog = NULL,
1770 .reflog_expire = NULL,
1771 +
1772 + .fsck = packed_fsck,
1773 };
refs/refs-internal.h
+6
@@ -4,6 +4,7 @@
4 #include "refs.h"
5 #include "iterator.h"
6
7 +struct fsck_options;
8 struct ref_transaction;
9
10 /*
@@ -650,6 +651,9 @@ typedef int read_raw_ref_fn(struct ref_store *ref_store, const char *refname,
651 typedef int read_symbolic_ref_fn(struct ref_store *ref_store, const char *refname,
652 struct strbuf *referent);
653
654 +typedef int fsck_fn(struct ref_store *ref_store,
655 + struct fsck_options *o);
656 +
657 struct ref_storage_be {
658 const char *name;
659 ref_store_init_fn *init;
@@ -677,6 +681,8 @@ struct ref_storage_be {
681 create_reflog_fn *create_reflog;
682 delete_reflog_fn *delete_reflog;
683 reflog_expire_fn *reflog_expire;
684 +
685 + fsck_fn *fsck;
686 };
687
688 extern struct ref_storage_be refs_be_files;
refs/reftable-backend.c
+8
@@ -2303,6 +2303,12 @@ done:
2303 return ret;
2304 }
2305
2306 +static int reftable_be_fsck(struct ref_store *ref_store,
2307 + struct fsck_options *o)
2308 +{
2309 + return 0;
2310 +}
2311 +
2312 struct ref_storage_be refs_be_reftable = {
2313 .name = "reftable",
2314 .init = reftable_be_init,
@@ -2330,4 +2336,6 @@ struct ref_storage_be refs_be_reftable = {
2336 .create_reflog = reftable_be_create_reflog,
2337 .delete_reflog = reftable_be_delete_reflog,
2338 .reflog_expire = reftable_be_reflog_expire,
2339 +
2340 + .fsck = reftable_be_fsck,
2341 };