From 8cd4a447b8b022a25e05653eb5f2dd80b9009bbe Mon Sep 17 00:00:00 2001 From: shejialuo Date: Thu, 8 Aug 2024 19:24:25 +0800 Subject: fsck: rename objects-related fsck error functions The names of objects-related fsck error functions are generic. It's OK when there is only object database check. However, we are going to introduce refs database check report function. To avoid ambiguity, rename object-related fsck error functions to explicitly indicate these functions are used to report objects-related messages. Mentored-by: Patrick Steinhardt Mentored-by: Karthik Nayak Signed-off-by: shejialuo Signed-off-by: Junio C Hamano --- builtin/fsck.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'builtin') diff --git a/builtin/fsck.c b/builtin/fsck.c index d13a226c2e..6d86bbe1e9 100644 --- a/builtin/fsck.c +++ b/builtin/fsck.c @@ -89,12 +89,12 @@ static int objerror(struct object *obj, const char *err) return -1; } -static int fsck_error_func(struct fsck_options *o UNUSED, - const struct object_id *oid, - enum object_type object_type, - enum fsck_msg_type msg_type, - enum fsck_msg_id msg_id UNUSED, - const char *message) +static int fsck_objects_error_func(struct fsck_options *o UNUSED, + const struct object_id *oid, + enum object_type object_type, + enum fsck_msg_type msg_type, + enum fsck_msg_id msg_id UNUSED, + const char *message) { switch (msg_type) { case FSCK_WARN: @@ -938,7 +938,7 @@ int cmd_fsck(int argc, const char **argv, const char *prefix) fsck_walk_options.walk = mark_object; fsck_obj_options.walk = mark_used; - fsck_obj_options.error_func = fsck_error_func; + fsck_obj_options.error_func = fsck_objects_error_func; if (check_strict) fsck_obj_options.strict = 1; -- cgit v1.3-6-g1900 From 0ec5dfe8c45be2efd6350b3a1a3885c795a85578 Mon Sep 17 00:00:00 2001 From: shejialuo Date: Thu, 8 Aug 2024 19:26:47 +0800 Subject: fsck: make "fsck_error" callback generic The "fsck_error" callback is designed to report the objects-related error messages. It accepts two parameter "oid" and "object_type" which is not generic. In order to provide a unified callback which can report either objects or refs, remove the objects-related parameters and add the generic parameter "void *fsck_report". Create a new "fsck_object_report" structure which incorporates the removed parameters "oid" and "object_type". Then change the corresponding references to adapt to new "fsck_error" callback. Mentored-by: Patrick Steinhardt Mentored-by: Karthik Nayak Signed-off-by: shejialuo Signed-off-by: Junio C Hamano --- builtin/fsck.c | 7 +++++-- builtin/mktag.c | 3 +-- fsck.c | 26 ++++++++++++++++---------- fsck.h | 17 ++++++++++++----- object-file.c | 9 ++++----- 5 files changed, 38 insertions(+), 24 deletions(-) (limited to 'builtin') diff --git a/builtin/fsck.c b/builtin/fsck.c index 6d86bbe1e9..766bbd014d 100644 --- a/builtin/fsck.c +++ b/builtin/fsck.c @@ -90,12 +90,15 @@ static int objerror(struct object *obj, const char *err) } static int fsck_objects_error_func(struct fsck_options *o UNUSED, - const struct object_id *oid, - enum object_type object_type, + void *fsck_report, enum fsck_msg_type msg_type, enum fsck_msg_id msg_id UNUSED, const char *message) { + struct fsck_object_report *report = fsck_report; + const struct object_id *oid = report->oid; + enum object_type object_type = report->object_type; + switch (msg_type) { case FSCK_WARN: /* TRANSLATORS: e.g. warning in tree 01bfda: */ diff --git a/builtin/mktag.c b/builtin/mktag.c index 4767f1a97e..c6b644219f 100644 --- a/builtin/mktag.c +++ b/builtin/mktag.c @@ -18,8 +18,7 @@ static int option_strict = 1; static struct fsck_options fsck_options = FSCK_OPTIONS_STRICT; static int mktag_fsck_error_func(struct fsck_options *o UNUSED, - const struct object_id *oid UNUSED, - enum object_type object_type UNUSED, + void *fsck_report UNUSED, enum fsck_msg_type msg_type, enum fsck_msg_id msg_id UNUSED, const char *message) diff --git a/fsck.c b/fsck.c index 8347842cfb..cca6ae144f 100644 --- a/fsck.c +++ b/fsck.c @@ -232,6 +232,10 @@ static int report(struct fsck_options *options, enum fsck_msg_id msg_id, const char *fmt, ...) { va_list ap; + struct fsck_object_report report = { + .oid = oid, + .object_type = object_type + }; struct strbuf sb = STRBUF_INIT; enum fsck_msg_type msg_type = fsck_msg_type(msg_id, options); int result; @@ -252,7 +256,7 @@ static int report(struct fsck_options *options, va_start(ap, fmt); strbuf_vaddf(&sb, fmt, ap); - result = options->error_func(options, oid, object_type, + result = options->error_func(options, &report, msg_type, msg_id, sb.buf); strbuf_release(&sb); va_end(ap); @@ -1201,12 +1205,14 @@ int fsck_buffer(const struct object_id *oid, enum object_type type, } int fsck_objects_error_function(struct fsck_options *o, - const struct object_id *oid, - enum object_type object_type UNUSED, - enum fsck_msg_type msg_type, - enum fsck_msg_id msg_id UNUSED, - const char *message) + void *fsck_report, + enum fsck_msg_type msg_type, + enum fsck_msg_id msg_id UNUSED, + const char *message) { + struct fsck_object_report *report = fsck_report; + const struct object_id *oid = report->oid; + if (msg_type == FSCK_WARN) { warning("object %s: %s", fsck_describe_object(o, oid), message); return 0; @@ -1304,16 +1310,16 @@ int git_fsck_config(const char *var, const char *value, */ int fsck_objects_error_cb_print_missing_gitmodules(struct fsck_options *o, - const struct object_id *oid, - enum object_type object_type, + void *fsck_report, enum fsck_msg_type msg_type, enum fsck_msg_id msg_id, const char *message) { if (msg_id == FSCK_MSG_GITMODULES_MISSING) { - puts(oid_to_hex(oid)); + struct fsck_object_report *report = fsck_report; + puts(oid_to_hex(report->oid)); return 0; } - return fsck_objects_error_function(o, oid, object_type, + return fsck_objects_error_function(o, fsck_report, msg_type, msg_id, message); } diff --git a/fsck.h b/fsck.h index 41ebebbb59..3b80d02506 100644 --- a/fsck.h +++ b/fsck.h @@ -114,23 +114,30 @@ int is_valid_msg_type(const char *msg_id, const char *msg_type); typedef int (*fsck_walk_func)(struct object *obj, enum object_type object_type, void *data, struct fsck_options *options); -/* callback for fsck_object, type is FSCK_ERROR or FSCK_WARN */ +/* + * Callback for reporting errors either for objects or refs. The "fsck_report" + * is a generic pointer that can be used to pass any information. + */ typedef int (*fsck_error)(struct fsck_options *o, - const struct object_id *oid, enum object_type object_type, + void *fsck_report, enum fsck_msg_type msg_type, enum fsck_msg_id msg_id, const char *message); int fsck_objects_error_function(struct fsck_options *o, - const struct object_id *oid, enum object_type object_type, + void *fsck_report, enum fsck_msg_type msg_type, enum fsck_msg_id msg_id, const char *message); int fsck_objects_error_cb_print_missing_gitmodules(struct fsck_options *o, - const struct object_id *oid, - enum object_type object_type, + void *fsck_report, enum fsck_msg_type msg_type, enum fsck_msg_id msg_id, const char *message); +struct fsck_object_report { + const struct object_id *oid; + enum object_type object_type; +}; + struct fsck_options { fsck_walk_func walk; fsck_error error_func; diff --git a/object-file.c b/object-file.c index 065103be3e..05ac6ebed6 100644 --- a/object-file.c +++ b/object-file.c @@ -2470,11 +2470,10 @@ int repo_has_object_file(struct repository *r, * give more context. */ static int hash_format_check_report(struct fsck_options *opts UNUSED, - const struct object_id *oid UNUSED, - enum object_type object_type UNUSED, - enum fsck_msg_type msg_type UNUSED, - enum fsck_msg_id msg_id UNUSED, - const char *message) + void *fsck_report UNUSED, + enum fsck_msg_type msg_type UNUSED, + enum fsck_msg_id msg_id UNUSED, + const char *message) { error(_("object fails fsck: %s"), message); return 1; -- cgit v1.3-6-g1900 From bf061d26c7a595f1f46510aa584d50be1b1edb93 Mon Sep 17 00:00:00 2001 From: shejialuo Date: Thu, 8 Aug 2024 19:27:28 +0800 Subject: builtin/refs: add verify subcommand Introduce a new subcommand "verify" in git-refs(1) to allow the user to check the reference database consistency and also this subcommand will be used as the entry point of checking refs for "git-fsck(1)". Add "verbose" field into "fsck_options" to indicate whether we should print verbose messages when checking refs and objects consistency. Remove bit-field for "strict" field, this is because we cannot take address of a bit-field which makes it unhandy to set member variables when parsing the command line options. The "git-fsck(1)" declares "fsck_options" variable with "static" identifier which avoids complaint by the leak-checker. However, in "git-refs verify", we need to do memory clean manually. Thus add "fsck_options_clear" function in "fsck.c" to provide memory clean operation. Mentored-by: Patrick Steinhardt Mentored-by: Karthik Nayak Signed-off-by: shejialuo Signed-off-by: Junio C Hamano --- Documentation/git-refs.txt | 13 +++++++++++++ builtin/refs.c | 34 ++++++++++++++++++++++++++++++++++ fsck.c | 11 +++++++++++ fsck.h | 8 +++++++- 4 files changed, 65 insertions(+), 1 deletion(-) (limited to 'builtin') diff --git a/Documentation/git-refs.txt b/Documentation/git-refs.txt index 5b99e04385..ce31f93061 100644 --- a/Documentation/git-refs.txt +++ b/Documentation/git-refs.txt @@ -10,6 +10,7 @@ SYNOPSIS -------- [verse] 'git refs migrate' --ref-format= [--dry-run] +'git refs verify' [--strict] [--verbose] DESCRIPTION ----------- @@ -22,6 +23,9 @@ COMMANDS migrate:: Migrate ref store between different formats. +verify:: + Verify reference database consistency. + OPTIONS ------- @@ -39,6 +43,15 @@ include::ref-storage-format.txt[] can be used to double check that the migration works as expected before performing the actual migration. +The following options are specific to 'git refs verify': + +--strict:: + Enable stricter error checking. This will cause warnings to be + reported as errors. See linkgit:git-fsck[1]. + +--verbose:: + When verifying the reference database consistency, be chatty. + KNOWN LIMITATIONS ----------------- diff --git a/builtin/refs.c b/builtin/refs.c index 46dcd150d4..131f98be98 100644 --- a/builtin/refs.c +++ b/builtin/refs.c @@ -1,4 +1,6 @@ #include "builtin.h" +#include "config.h" +#include "fsck.h" #include "parse-options.h" #include "refs.h" #include "repository.h" @@ -7,6 +9,9 @@ #define REFS_MIGRATE_USAGE \ N_("git refs migrate --ref-format= [--dry-run]") +#define REFS_VERIFY_USAGE \ + N_("git refs verify [--strict] [--verbose]") + static int cmd_refs_migrate(int argc, const char **argv, const char *prefix) { const char * const migrate_usage[] = { @@ -58,15 +63,44 @@ out: return err; } +static int cmd_refs_verify(int argc, const char **argv, const char *prefix) +{ + struct fsck_options fsck_refs_options = FSCK_REFS_OPTIONS_DEFAULT; + const char * const verify_usage[] = { + REFS_VERIFY_USAGE, + NULL, + }; + struct option options[] = { + OPT_BOOL(0, "verbose", &fsck_refs_options.verbose, N_("be verbose")), + OPT_BOOL(0, "strict", &fsck_refs_options.strict, N_("enable strict checking")), + OPT_END(), + }; + int ret; + + argc = parse_options(argc, argv, prefix, options, verify_usage, 0); + if (argc) + usage(_("'git refs verify' takes no arguments")); + + git_config(git_fsck_config, &fsck_refs_options); + prepare_repo_settings(the_repository); + + ret = refs_fsck(get_main_ref_store(the_repository), &fsck_refs_options); + + fsck_options_clear(&fsck_refs_options); + return ret; +} + int cmd_refs(int argc, const char **argv, const char *prefix) { const char * const refs_usage[] = { REFS_MIGRATE_USAGE, + REFS_VERIFY_USAGE, NULL, }; parse_opt_subcommand_fn *fn = NULL; struct option opts[] = { OPT_SUBCOMMAND("migrate", &fn, cmd_refs_migrate), + OPT_SUBCOMMAND("verify", &fn, cmd_refs_verify), OPT_END(), }; diff --git a/fsck.c b/fsck.c index e16c892f6a..3756f52459 100644 --- a/fsck.c +++ b/fsck.c @@ -1331,6 +1331,17 @@ int fsck_finish(struct fsck_options *options) return ret; } +void fsck_options_clear(struct fsck_options *options) +{ + free(options->msg_type); + oidset_clear(&options->skip_oids); + oidset_clear(&options->gitmodules_found); + oidset_clear(&options->gitmodules_done); + oidset_clear(&options->gitattributes_found); + oidset_clear(&options->gitattributes_done); + kh_clear_oid_map(options->object_names); +} + int git_fsck_config(const char *var, const char *value, const struct config_context *ctx, void *cb) { diff --git a/fsck.h b/fsck.h index 2002590f60..d551a9fe86 100644 --- a/fsck.h +++ b/fsck.h @@ -153,7 +153,8 @@ struct fsck_ref_report { struct fsck_options { fsck_walk_func walk; fsck_error error_func; - unsigned strict:1; + unsigned strict; + unsigned verbose; enum fsck_msg_type *msg_type; struct oidset skip_oids; struct oidset gitmodules_found; @@ -231,6 +232,11 @@ int fsck_tag_standalone(const struct object_id *oid, const char *buffer, */ int fsck_finish(struct fsck_options *options); +/* + * Clear the fsck_options struct, freeing any allocated memory. + */ +void fsck_options_clear(struct fsck_options *options); + /* * Report an error or warning for refs. */ -- cgit v1.3-6-g1900