From fb79f5bff7f47f41cf3697ecc28bfaa888016ce0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=86var=20Arnfj=C3=B6r=C3=B0=20Bjarmason?= Date: Wed, 17 Mar 2021 19:20:36 +0100 Subject: [PATCH 01/19] fsck.c: refactor and rename common config callback MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Refactor code I recently changed in 1f3299fda9 (fsck: make fsck_config() re-usable, 2021-01-05) so that I could use fsck's config callback in mktag in 1f3299fda9 (fsck: make fsck_config() re-usable, 2021-01-05). I don't know what I was thinking in structuring the code this way, but it clearly makes no sense to have an fsck_config_internal() at all just so it can get a fsck_options when git_config() already supports passing along some void* data. Let's just make use of that instead, which gets us rid of the two wrapper functions, and brings fsck's common config callback in line with other such reusable config callbacks. Signed-off-by: Ævar Arnfjörð Bjarmason Signed-off-by: Junio C Hamano --- builtin/fsck.c | 7 +------ builtin/mktag.c | 7 +------ fsck.c | 4 ++-- fsck.h | 3 +-- 4 files changed, 5 insertions(+), 16 deletions(-) diff --git a/builtin/fsck.c b/builtin/fsck.c index 821e7798c7..a56a2d0513 100644 --- a/builtin/fsck.c +++ b/builtin/fsck.c @@ -71,11 +71,6 @@ static const char *printable_type(const struct object_id *oid, return ret; } -static int fsck_config(const char *var, const char *value, void *cb) -{ - return fsck_config_internal(var, value, cb, &fsck_obj_options); -} - static int objerror(struct object *obj, const char *err) { errors_found |= ERROR_OBJECT; @@ -803,7 +798,7 @@ int cmd_fsck(int argc, const char **argv, const char *prefix) if (name_objects) fsck_enable_object_names(&fsck_walk_options); - git_config(fsck_config, NULL); + git_config(git_fsck_config, &fsck_obj_options); if (connectivity_only) { for_each_loose_object(mark_loose_for_connectivity, NULL, 0); diff --git a/builtin/mktag.c b/builtin/mktag.c index 41a399a69e..23c4b8763f 100644 --- a/builtin/mktag.c +++ b/builtin/mktag.c @@ -14,11 +14,6 @@ static int option_strict = 1; static struct fsck_options fsck_options = FSCK_OPTIONS_STRICT; -static int mktag_config(const char *var, const char *value, void *cb) -{ - return fsck_config_internal(var, value, cb, &fsck_options); -} - static int mktag_fsck_error_func(struct fsck_options *o, const struct object_id *oid, enum object_type object_type, @@ -93,7 +88,7 @@ int cmd_mktag(int argc, const char **argv, const char *prefix) fsck_options.error_func = mktag_fsck_error_func; fsck_set_msg_type(&fsck_options, "extraheaderentry", "warn"); /* config might set fsck.extraHeaderEntry=* again */ - git_config(mktag_config, NULL); + git_config(git_fsck_config, &fsck_options); if (fsck_tag_standalone(NULL, buf.buf, buf.len, &fsck_options, &tagged_oid, &tagged_type)) die(_("tag on stdin did not pass our strict fsck check")); diff --git a/fsck.c b/fsck.c index e3030f3b35..5dfb99665a 100644 --- a/fsck.c +++ b/fsck.c @@ -1323,9 +1323,9 @@ int fsck_finish(struct fsck_options *options) return ret; } -int fsck_config_internal(const char *var, const char *value, void *cb, - struct fsck_options *options) +int git_fsck_config(const char *var, const char *value, void *cb) { + struct fsck_options *options = cb; if (strcmp(var, "fsck.skiplist") == 0) { const char *path; struct strbuf sb = STRBUF_INIT; diff --git a/fsck.h b/fsck.h index 733378f126..f70d11c559 100644 --- a/fsck.h +++ b/fsck.h @@ -109,7 +109,6 @@ const char *fsck_describe_object(struct fsck_options *options, * git_config() callback for use by fsck-y tools that want to support * fsck. fsck.skipList etc. */ -int fsck_config_internal(const char *var, const char *value, void *cb, - struct fsck_options *options); +int git_fsck_config(const char *var, const char *value, void *cb); #endif From d385784f89b3350db16380441bc8a18ebe54179a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=86var=20Arnfj=C3=B6r=C3=B0=20Bjarmason?= Date: Sun, 28 Mar 2021 15:15:34 +0200 Subject: [PATCH 02/19] fsck.h: use designed initializers for FSCK_OPTIONS_{DEFAULT,STRICT} MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Refactor the definitions of FSCK_OPTIONS_{DEFAULT,STRICT} to use designated initializers. This allows us to omit those fields that are initialized to 0 or NULL. Signed-off-by: Ævar Arnfjörð Bjarmason Signed-off-by: Junio C Hamano --- fsck.h | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/fsck.h b/fsck.h index f70d11c559..73e8b9f3e4 100644 --- a/fsck.h +++ b/fsck.h @@ -43,8 +43,14 @@ struct fsck_options { kh_oid_map_t *object_names; }; -#define FSCK_OPTIONS_DEFAULT { NULL, fsck_error_function, 0, NULL, OIDSET_INIT } -#define FSCK_OPTIONS_STRICT { NULL, fsck_error_function, 1, NULL, OIDSET_INIT } +#define FSCK_OPTIONS_DEFAULT { \ + .skiplist = OIDSET_INIT, \ + .error_func = fsck_error_function \ +} +#define FSCK_OPTIONS_STRICT { \ + .strict = 1, \ + .error_func = fsck_error_function, \ +} /* descend in all linked child objects * the return value is: From a1aad71601a7a2052058d735ef86624b3cc774cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=86var=20Arnfj=C3=B6r=C3=B0=20Bjarmason?= Date: Sun, 28 Mar 2021 15:15:35 +0200 Subject: [PATCH 03/19] fsck.h: use "enum object_type" instead of "int" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change the fsck_walk_func to use an "enum object_type" instead of an "int" type. The types are compatible, and ever since this was added in 355885d5315 (add generic, type aware object chain walker, 2008-02-25) we've used entries from object_type (OBJ_BLOB etc.). So this doesn't really change anything as far as the generated code is concerned, it just gives the compiler more information and makes this easier to read. Signed-off-by: Ævar Arnfjörð Bjarmason Signed-off-by: Junio C Hamano --- builtin/fsck.c | 3 ++- builtin/index-pack.c | 3 ++- builtin/unpack-objects.c | 3 ++- fsck.h | 3 ++- 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/builtin/fsck.c b/builtin/fsck.c index a56a2d0513..ed5f2af6b5 100644 --- a/builtin/fsck.c +++ b/builtin/fsck.c @@ -192,7 +192,8 @@ static int traverse_reachable(void) return !!result; } -static int mark_used(struct object *obj, int type, void *data, struct fsck_options *options) +static int mark_used(struct object *obj, enum object_type object_type, + void *data, struct fsck_options *options) { if (!obj) return 1; diff --git a/builtin/index-pack.c b/builtin/index-pack.c index bad5748807..69f24fe9f7 100644 --- a/builtin/index-pack.c +++ b/builtin/index-pack.c @@ -212,7 +212,8 @@ static void cleanup_thread(void) free(thread_data); } -static int mark_link(struct object *obj, int type, void *data, struct fsck_options *options) +static int mark_link(struct object *obj, enum object_type type, + void *data, struct fsck_options *options) { if (!obj) return -1; diff --git a/builtin/unpack-objects.c b/builtin/unpack-objects.c index dd4a75e030..ca54fd1668 100644 --- a/builtin/unpack-objects.c +++ b/builtin/unpack-objects.c @@ -187,7 +187,8 @@ static void write_cached_object(struct object *obj, struct obj_buffer *obj_buf) * that have reachability requirements and calls this function. * Verify its reachability and validity recursively and write it out. */ -static int check_object(struct object *obj, int type, void *data, struct fsck_options *options) +static int check_object(struct object *obj, enum object_type type, + void *data, struct fsck_options *options) { struct obj_buffer *obj_buf; diff --git a/fsck.h b/fsck.h index 73e8b9f3e4..f20f1259e8 100644 --- a/fsck.h +++ b/fsck.h @@ -23,7 +23,8 @@ int is_valid_msg_type(const char *msg_id, const char *msg_type); * <0 error signaled and abort * >0 error signaled and do not abort */ -typedef int (*fsck_walk_func)(struct object *obj, int type, void *data, struct fsck_options *options); +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 */ typedef int (*fsck_error)(struct fsck_options *o, From f1abc2d0e146dc7f1549fd3ddb119e1b7f0ea645 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=86var=20Arnfj=C3=B6r=C3=B0=20Bjarmason?= Date: Sun, 28 Mar 2021 15:15:36 +0200 Subject: [PATCH 04/19] fsck.c: rename variables in fsck_set_msg_type() for less confusion MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rename variables in a function added in 0282f4dced0 (fsck: offer a function to demote fsck errors to warnings, 2015-06-22). It was needlessly confusing that it took a "msg_type" argument, but then later declared another "msg_type" of a different type. Let's rename that to "severity", and rename "id" to "msg_id" and "msg_id" to "msg_id_str" etc. This will make a follow-up change smaller. While I'm at it properly indent the fsck_set_msg_type() argument list. Signed-off-by: Ævar Arnfjörð Bjarmason Signed-off-by: Junio C Hamano --- fsck.c | 24 ++++++++++++------------ fsck.h | 2 +- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/fsck.c b/fsck.c index 5dfb99665a..7cc722a25c 100644 --- a/fsck.c +++ b/fsck.c @@ -203,27 +203,27 @@ int is_valid_msg_type(const char *msg_id, const char *msg_type) } void fsck_set_msg_type(struct fsck_options *options, - const char *msg_id, const char *msg_type) + const char *msg_id_str, const char *msg_type_str) { - int id = parse_msg_id(msg_id), type; + int msg_id = parse_msg_id(msg_id_str), msg_type; - if (id < 0) - die("Unhandled message id: %s", msg_id); - type = parse_msg_type(msg_type); + if (msg_id < 0) + die("Unhandled message id: %s", msg_id_str); + msg_type = parse_msg_type(msg_type_str); - if (type != FSCK_ERROR && msg_id_info[id].msg_type == FSCK_FATAL) - die("Cannot demote %s to %s", msg_id, msg_type); + if (msg_type != FSCK_ERROR && msg_id_info[msg_id].msg_type == FSCK_FATAL) + die("Cannot demote %s to %s", msg_id_str, msg_type_str); if (!options->msg_type) { int i; - int *msg_type; - ALLOC_ARRAY(msg_type, FSCK_MSG_MAX); + int *severity; + ALLOC_ARRAY(severity, FSCK_MSG_MAX); for (i = 0; i < FSCK_MSG_MAX; i++) - msg_type[i] = fsck_msg_type(i, options); - options->msg_type = msg_type; + severity[i] = fsck_msg_type(i, options); + options->msg_type = severity; } - options->msg_type[id] = type; + options->msg_type[msg_id] = msg_type; } void fsck_set_msg_types(struct fsck_options *options, const char *values) diff --git a/fsck.h b/fsck.h index f20f1259e8..30a3acabc5 100644 --- a/fsck.h +++ b/fsck.h @@ -11,7 +11,7 @@ struct fsck_options; struct object; void fsck_set_msg_type(struct fsck_options *options, - const char *msg_id, const char *msg_type); + const char *msg_id, const char *msg_type); void fsck_set_msg_types(struct fsck_options *options, const char *values); int is_valid_msg_type(const char *msg_id, const char *msg_type); From 034a7b7bcc0ce5a7c3713173a1699ca8c9e722d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=86var=20Arnfj=C3=B6r=C3=B0=20Bjarmason?= Date: Sun, 28 Mar 2021 15:15:37 +0200 Subject: [PATCH 05/19] fsck.c: remove (mostly) redundant append_msg_id() function MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove the append_msg_id() function in favor of calling prepare_msg_ids(). We already have code to compute the camel-cased msg_id strings in msg_id_info, let's use it. When the append_msg_id() function was added in 71ab8fa840f (fsck: report the ID of the error/warning, 2015-06-22) the prepare_msg_ids() function didn't exist. When prepare_msg_ids() was added in a46baac61eb (fsck: factor out msg_id_info[] lazy initialization code, 2018-05-26) this code wasn't moved over to lazy initialization. This changes the behavior of the code to initialize all the messages instead of just camel-casing the one we need on the fly. Since the common case is that we're printing just one message this is mostly redundant work. But that's OK in this case, reporting this fsck issue to the user isn't performance-sensitive. If we were somehow doing so in a tight loop (in a hopelessly broken repository?) this would help, since we'd save ourselves from re-doing this work for identical messages, we could just grab the prepared string from msg_id_info after the first invocation. Signed-off-by: Ævar Arnfjörð Bjarmason Signed-off-by: Junio C Hamano --- fsck.c | 21 ++------------------- 1 file changed, 2 insertions(+), 19 deletions(-) diff --git a/fsck.c b/fsck.c index 7cc722a25c..25c697fa6a 100644 --- a/fsck.c +++ b/fsck.c @@ -264,24 +264,6 @@ void fsck_set_msg_types(struct fsck_options *options, const char *values) free(to_free); } -static void append_msg_id(struct strbuf *sb, const char *msg_id) -{ - for (;;) { - char c = *(msg_id)++; - - if (!c) - break; - if (c != '_') - strbuf_addch(sb, tolower(c)); - else { - assert(*msg_id); - strbuf_addch(sb, *(msg_id)++); - } - } - - strbuf_addstr(sb, ": "); -} - static int object_on_skiplist(struct fsck_options *opts, const struct object_id *oid) { @@ -308,7 +290,8 @@ static int report(struct fsck_options *options, else if (msg_type == FSCK_INFO) msg_type = FSCK_WARN; - append_msg_id(&sb, msg_id_info[id].id_string); + prepare_msg_ids(); + strbuf_addf(&sb, "%s: ", msg_id_info[id].camelcased); va_start(ap, fmt); strbuf_vaddf(&sb, fmt, ap); From 35af754b0694eb26a253edf551efe400f30b3864 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=86var=20Arnfj=C3=B6r=C3=B0=20Bjarmason?= Date: Sun, 28 Mar 2021 15:15:38 +0200 Subject: [PATCH 06/19] fsck.c: rename remaining fsck_msg_id "id" to "msg_id" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rename the remaining variables of type fsck_msg_id from "id" to "msg_id". This change is relatively small, and is worth the churn for a later change where we have different id's in the "report" function. Signed-off-by: Ævar Arnfjörð Bjarmason Signed-off-by: Junio C Hamano --- fsck.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/fsck.c b/fsck.c index 25c697fa6a..a0463ea22c 100644 --- a/fsck.c +++ b/fsck.c @@ -273,11 +273,11 @@ static int object_on_skiplist(struct fsck_options *opts, __attribute__((format (printf, 5, 6))) static int report(struct fsck_options *options, const struct object_id *oid, enum object_type object_type, - enum fsck_msg_id id, const char *fmt, ...) + enum fsck_msg_id msg_id, const char *fmt, ...) { va_list ap; struct strbuf sb = STRBUF_INIT; - int msg_type = fsck_msg_type(id, options), result; + int msg_type = fsck_msg_type(msg_id, options), result; if (msg_type == FSCK_IGNORE) return 0; @@ -291,7 +291,7 @@ static int report(struct fsck_options *options, msg_type = FSCK_WARN; prepare_msg_ids(); - strbuf_addf(&sb, "%s: ", msg_id_info[id].camelcased); + strbuf_addf(&sb, "%s: ", msg_id_info[msg_id].camelcased); va_start(ap, fmt); strbuf_vaddf(&sb, fmt, ap); From e35d65a78ab7520b2705b27062758ab20a60e462 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=86var=20Arnfj=C3=B6r=C3=B0=20Bjarmason?= Date: Sun, 28 Mar 2021 15:15:39 +0200 Subject: [PATCH 07/19] fsck.c: refactor fsck_msg_type() to limit scope of "int msg_type" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Refactor "if options->msg_type" and other code added in 0282f4dced0 (fsck: offer a function to demote fsck errors to warnings, 2015-06-22) to reduce the scope of the "int msg_type" variable. This is in preparation for changing its type in a subsequent commit, only using it in the "!options->msg_type" scope makes that change This also brings the code in line with the fsck_set_msg_type() function (also added in 0282f4dced0), which does a similar check for "!options->msg_type". Another minor benefit is getting rid of the style violation of not having braces for the body of the "if". Signed-off-by: Ævar Arnfjörð Bjarmason Signed-off-by: Junio C Hamano --- fsck.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/fsck.c b/fsck.c index a0463ea22c..8614ee2c2a 100644 --- a/fsck.c +++ b/fsck.c @@ -167,19 +167,17 @@ void list_config_fsck_msg_ids(struct string_list *list, const char *prefix) static int fsck_msg_type(enum fsck_msg_id msg_id, struct fsck_options *options) { - int msg_type; - assert(msg_id >= 0 && msg_id < FSCK_MSG_MAX); - if (options->msg_type) - msg_type = options->msg_type[msg_id]; - else { - msg_type = msg_id_info[msg_id].msg_type; + if (!options->msg_type) { + int msg_type = msg_id_info[msg_id].msg_type; + if (options->strict && msg_type == FSCK_WARN) msg_type = FSCK_ERROR; + return msg_type; } - return msg_type; + return options->msg_type[msg_id]; } static int parse_msg_type(const char *str) From 1b32b59f9bd78b3475195a6e99c629a5ffefdea0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=86var=20Arnfj=C3=B6r=C3=B0=20Bjarmason?= Date: Sun, 28 Mar 2021 15:15:40 +0200 Subject: [PATCH 08/19] fsck.h: move FSCK_{FATAL,INFO,ERROR,WARN,IGNORE} into an enum MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move the FSCK_{FATAL,INFO,ERROR,WARN,IGNORE} defines into a new fsck_msg_type enum. These defines were originally introduced in: - ba002f3b28a (builtin-fsck: move common object checking code to fsck.c, 2008-02-25) - f50c4407305 (fsck: disallow demoting grave fsck errors to warnings, 2015-06-22) - efaba7cc77f (fsck: optionally ignore specific fsck issues completely, 2015-06-22) - f27d05b1704 (fsck: allow upgrading fsck warnings to errors, 2015-06-22) The reason these were defined in two different places is because we use FSCK_{IGNORE,INFO,FATAL} only in fsck.c, but FSCK_{ERROR,WARN} are used by external callbacks. Untangling that would take some more work, since we expose the new "enum fsck_msg_type" to both. Similar to "enum object_type" it's not worth structuring the API in such a way that only those who need FSCK_{ERROR,WARN} pass around a different type. Signed-off-by: Ævar Arnfjörð Bjarmason Signed-off-by: Junio C Hamano --- builtin/fsck.c | 2 +- builtin/index-pack.c | 3 ++- builtin/mktag.c | 3 ++- fsck.c | 21 ++++++++++----------- fsck.h | 16 ++++++++++------ 5 files changed, 25 insertions(+), 20 deletions(-) diff --git a/builtin/fsck.c b/builtin/fsck.c index ed5f2af6b5..17940a4e24 100644 --- a/builtin/fsck.c +++ b/builtin/fsck.c @@ -84,7 +84,7 @@ static int objerror(struct object *obj, const char *err) static int fsck_error_func(struct fsck_options *o, const struct object_id *oid, enum object_type object_type, - int msg_type, const char *message) + enum fsck_msg_type msg_type, const char *message) { switch (msg_type) { case FSCK_WARN: diff --git a/builtin/index-pack.c b/builtin/index-pack.c index 69f24fe9f7..56b8efaa89 100644 --- a/builtin/index-pack.c +++ b/builtin/index-pack.c @@ -1716,7 +1716,8 @@ static void show_pack_info(int stat_only) static int print_dangling_gitmodules(struct fsck_options *o, const struct object_id *oid, enum object_type object_type, - int msg_type, const char *message) + enum fsck_msg_type msg_type, + const char *message) { /* * NEEDSWORK: Plumb the MSG_ID (from fsck.c) here and use it diff --git a/builtin/mktag.c b/builtin/mktag.c index 23c4b8763f..052a510ad7 100644 --- a/builtin/mktag.c +++ b/builtin/mktag.c @@ -17,7 +17,8 @@ static struct fsck_options fsck_options = FSCK_OPTIONS_STRICT; static int mktag_fsck_error_func(struct fsck_options *o, const struct object_id *oid, enum object_type object_type, - int msg_type, const char *message) + enum fsck_msg_type msg_type, + const char *message) { switch (msg_type) { case FSCK_WARN: diff --git a/fsck.c b/fsck.c index 8614ee2c2a..c5a81e4ff0 100644 --- a/fsck.c +++ b/fsck.c @@ -22,9 +22,6 @@ static struct oidset gitmodules_found = OIDSET_INIT; static struct oidset gitmodules_done = OIDSET_INIT; -#define FSCK_FATAL -1 -#define FSCK_INFO -2 - #define FOREACH_MSG_ID(FUNC) \ /* fatal errors */ \ FUNC(NUL_IN_HEADER, FATAL) \ @@ -97,7 +94,7 @@ static struct { const char *id_string; const char *downcased; const char *camelcased; - int msg_type; + enum fsck_msg_type msg_type; } msg_id_info[FSCK_MSG_MAX + 1] = { FOREACH_MSG_ID(MSG_ID) { NULL, NULL, NULL, -1 } @@ -164,13 +161,13 @@ void list_config_fsck_msg_ids(struct string_list *list, const char *prefix) list_config_item(list, prefix, msg_id_info[i].camelcased); } -static int fsck_msg_type(enum fsck_msg_id msg_id, +static enum fsck_msg_type fsck_msg_type(enum fsck_msg_id msg_id, struct fsck_options *options) { assert(msg_id >= 0 && msg_id < FSCK_MSG_MAX); if (!options->msg_type) { - int msg_type = msg_id_info[msg_id].msg_type; + enum fsck_msg_type msg_type = msg_id_info[msg_id].msg_type; if (options->strict && msg_type == FSCK_WARN) msg_type = FSCK_ERROR; @@ -180,7 +177,7 @@ static int fsck_msg_type(enum fsck_msg_id msg_id, return options->msg_type[msg_id]; } -static int parse_msg_type(const char *str) +static enum fsck_msg_type parse_msg_type(const char *str) { if (!strcmp(str, "error")) return FSCK_ERROR; @@ -203,7 +200,8 @@ int is_valid_msg_type(const char *msg_id, const char *msg_type) void fsck_set_msg_type(struct fsck_options *options, const char *msg_id_str, const char *msg_type_str) { - int msg_id = parse_msg_id(msg_id_str), msg_type; + int msg_id = parse_msg_id(msg_id_str); + enum fsck_msg_type msg_type; if (msg_id < 0) die("Unhandled message id: %s", msg_id_str); @@ -214,7 +212,7 @@ void fsck_set_msg_type(struct fsck_options *options, if (!options->msg_type) { int i; - int *severity; + enum fsck_msg_type *severity; ALLOC_ARRAY(severity, FSCK_MSG_MAX); for (i = 0; i < FSCK_MSG_MAX; i++) severity[i] = fsck_msg_type(i, options); @@ -275,7 +273,8 @@ static int report(struct fsck_options *options, { va_list ap; struct strbuf sb = STRBUF_INIT; - int msg_type = fsck_msg_type(msg_id, options), result; + enum fsck_msg_type msg_type = fsck_msg_type(msg_id, options); + int result; if (msg_type == FSCK_IGNORE) return 0; @@ -1247,7 +1246,7 @@ int fsck_object(struct object *obj, void *data, unsigned long size, int fsck_error_function(struct fsck_options *o, const struct object_id *oid, enum object_type object_type, - int msg_type, const char *message) + enum fsck_msg_type msg_type, const char *message) { if (msg_type == FSCK_WARN) { warning("object %s: %s", fsck_describe_object(o, oid), message); diff --git a/fsck.h b/fsck.h index 30a3acabc5..baf3762076 100644 --- a/fsck.h +++ b/fsck.h @@ -3,9 +3,13 @@ #include "oidset.h" -#define FSCK_ERROR 1 -#define FSCK_WARN 2 -#define FSCK_IGNORE 3 +enum fsck_msg_type { + FSCK_INFO = -2, + FSCK_FATAL = -1, + FSCK_ERROR = 1, + FSCK_WARN, + FSCK_IGNORE +}; struct fsck_options; struct object; @@ -29,17 +33,17 @@ typedef int (*fsck_walk_func)(struct object *obj, enum object_type object_type, /* callback for fsck_object, type is FSCK_ERROR or FSCK_WARN */ typedef int (*fsck_error)(struct fsck_options *o, const struct object_id *oid, enum object_type object_type, - int msg_type, const char *message); + enum fsck_msg_type msg_type, const char *message); int fsck_error_function(struct fsck_options *o, const struct object_id *oid, enum object_type object_type, - int msg_type, const char *message); + enum fsck_msg_type msg_type, const char *message); struct fsck_options { fsck_walk_func walk; fsck_error error_func; unsigned strict:1; - int *msg_type; + enum fsck_msg_type *msg_type; struct oidset skiplist; kh_oid_map_t *object_names; }; From 30cf618eef09573a2f411e0b420e19f2f2e5a1c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=86var=20Arnfj=C3=B6r=C3=B0=20Bjarmason?= Date: Sun, 28 Mar 2021 15:15:41 +0200 Subject: [PATCH 09/19] fsck.h: re-order and re-assign "enum fsck_msg_type" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change the values in the "enum fsck_msg_type" from being manually assigned to using default C enum values. This means we end up with a FSCK_IGNORE=0, which was previously defined as "2". I'm confident that nothing relies on these values, we always compare them for equality. Let's not omit "0" so it won't be assumed that we're using these as a boolean somewhere. This also allows us to re-structure the fields to mark which are "private" v.s. "public". See the preceding commit for a rationale for not simply splitting these into two enums, namely that this is used for both the private and public fsck API. Signed-off-by: Ævar Arnfjörð Bjarmason Signed-off-by: Junio C Hamano --- fsck.h | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/fsck.h b/fsck.h index baf3762076..a7e092d3fb 100644 --- a/fsck.h +++ b/fsck.h @@ -4,11 +4,13 @@ #include "oidset.h" enum fsck_msg_type { - FSCK_INFO = -2, - FSCK_FATAL = -1, - FSCK_ERROR = 1, + /* for internal use only */ + FSCK_IGNORE, + FSCK_INFO, + FSCK_FATAL, + /* "public", fed to e.g. error_func callbacks */ + FSCK_ERROR, FSCK_WARN, - FSCK_IGNORE }; struct fsck_options; From c72da1a22bb3996ab8740b91ad2af6a54bd22777 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=86var=20Arnfj=C3=B6r=C3=B0=20Bjarmason?= Date: Sun, 28 Mar 2021 15:15:42 +0200 Subject: [PATCH 10/19] fsck.c: call parse_msg_type() early in fsck_set_msg_type() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There's no reason to defer the calling of parse_msg_type() until after we've checked if the "id < 0". This is not a hot codepath, and parse_msg_type() itself may die on invalid input. Signed-off-by: Ævar Arnfjörð Bjarmason Signed-off-by: Junio C Hamano --- fsck.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/fsck.c b/fsck.c index c5a81e4ff0..80365e6284 100644 --- a/fsck.c +++ b/fsck.c @@ -201,11 +201,10 @@ void fsck_set_msg_type(struct fsck_options *options, const char *msg_id_str, const char *msg_type_str) { int msg_id = parse_msg_id(msg_id_str); - enum fsck_msg_type msg_type; + enum fsck_msg_type msg_type = parse_msg_type(msg_type_str); if (msg_id < 0) die("Unhandled message id: %s", msg_id_str); - msg_type = parse_msg_type(msg_type_str); if (msg_type != FSCK_ERROR && msg_id_info[msg_id].msg_type == FSCK_FATAL) die("Cannot demote %s to %s", msg_id_str, msg_type_str); From b5495024ec655c56a98bdd3f9a5d4dfe578aa08f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=86var=20Arnfj=C3=B6r=C3=B0=20Bjarmason?= Date: Sun, 28 Mar 2021 15:15:43 +0200 Subject: [PATCH 11/19] fsck.c: undefine temporary STR macro after use MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In f417eed8cde (fsck: provide a function to parse fsck message IDs, 2015-06-22) the "STR" macro was introduced, but that short macro name was not undefined after use as was done earlier in the same series for the MSG_ID macro in c99ba492f1c (fsck: introduce identifiers for fsck messages, 2015-06-22). Signed-off-by: Ævar Arnfjörð Bjarmason Signed-off-by: Junio C Hamano --- fsck.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fsck.c b/fsck.c index 80365e6284..1b12e824ef 100644 --- a/fsck.c +++ b/fsck.c @@ -100,6 +100,7 @@ static struct { { NULL, NULL, NULL, -1 } }; #undef MSG_ID +#undef STR static void prepare_msg_ids(void) { From 901f2f6742d55b2b73186a05261885dc824ed5cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=86var=20Arnfj=C3=B6r=C3=B0=20Bjarmason?= Date: Sun, 28 Mar 2021 15:15:44 +0200 Subject: [PATCH 12/19] fsck.c: give "FOREACH_MSG_ID" a more specific name MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rename the FOREACH_MSG_ID macro to FOREACH_FSCK_MSG_ID in preparation for moving it over to fsck.h. It's good convention to name macros in *.h files in such a way as to clearly not clash with any other names in other files. Signed-off-by: Ævar Arnfjörð Bjarmason Signed-off-by: Junio C Hamano --- fsck.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/fsck.c b/fsck.c index 1b12e824ef..31c9088e3f 100644 --- a/fsck.c +++ b/fsck.c @@ -22,7 +22,7 @@ static struct oidset gitmodules_found = OIDSET_INIT; static struct oidset gitmodules_done = OIDSET_INIT; -#define FOREACH_MSG_ID(FUNC) \ +#define FOREACH_FSCK_MSG_ID(FUNC) \ /* fatal errors */ \ FUNC(NUL_IN_HEADER, FATAL) \ FUNC(UNTERMINATED_HEADER, FATAL) \ @@ -83,7 +83,7 @@ static struct oidset gitmodules_done = OIDSET_INIT; #define MSG_ID(id, msg_type) FSCK_MSG_##id, enum fsck_msg_id { - FOREACH_MSG_ID(MSG_ID) + FOREACH_FSCK_MSG_ID(MSG_ID) FSCK_MSG_MAX }; #undef MSG_ID @@ -96,7 +96,7 @@ static struct { const char *camelcased; enum fsck_msg_type msg_type; } msg_id_info[FSCK_MSG_MAX + 1] = { - FOREACH_MSG_ID(MSG_ID) + FOREACH_FSCK_MSG_ID(MSG_ID) { NULL, NULL, NULL, -1 } }; #undef MSG_ID From 44e07da8bb346c203246eae4f1a498844ee6d1ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=86var=20Arnfj=C3=B6r=C3=B0=20Bjarmason?= Date: Sun, 28 Mar 2021 15:15:45 +0200 Subject: [PATCH 13/19] fsck.[ch]: move FOREACH_FSCK_MSG_ID & fsck_msg_id from *.c to *.h MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move the FOREACH_FSCK_MSG_ID macro and the fsck_msg_id enum it helps define from fsck.c to fsck.h. This is in preparation for having non-static functions take the fsck_msg_id as an argument. Signed-off-by: Ævar Arnfjörð Bjarmason Signed-off-by: Junio C Hamano --- fsck.c | 66 ---------------------------------------------------------- fsck.h | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 66 insertions(+), 66 deletions(-) diff --git a/fsck.c b/fsck.c index 31c9088e3f..150fe467e4 100644 --- a/fsck.c +++ b/fsck.c @@ -22,72 +22,6 @@ static struct oidset gitmodules_found = OIDSET_INIT; static struct oidset gitmodules_done = OIDSET_INIT; -#define FOREACH_FSCK_MSG_ID(FUNC) \ - /* fatal errors */ \ - FUNC(NUL_IN_HEADER, FATAL) \ - FUNC(UNTERMINATED_HEADER, FATAL) \ - /* errors */ \ - FUNC(BAD_DATE, ERROR) \ - FUNC(BAD_DATE_OVERFLOW, ERROR) \ - FUNC(BAD_EMAIL, ERROR) \ - FUNC(BAD_NAME, ERROR) \ - FUNC(BAD_OBJECT_SHA1, ERROR) \ - FUNC(BAD_PARENT_SHA1, ERROR) \ - FUNC(BAD_TAG_OBJECT, ERROR) \ - FUNC(BAD_TIMEZONE, ERROR) \ - FUNC(BAD_TREE, ERROR) \ - FUNC(BAD_TREE_SHA1, ERROR) \ - FUNC(BAD_TYPE, ERROR) \ - FUNC(DUPLICATE_ENTRIES, ERROR) \ - FUNC(MISSING_AUTHOR, ERROR) \ - FUNC(MISSING_COMMITTER, ERROR) \ - FUNC(MISSING_EMAIL, ERROR) \ - FUNC(MISSING_NAME_BEFORE_EMAIL, ERROR) \ - FUNC(MISSING_OBJECT, ERROR) \ - FUNC(MISSING_SPACE_BEFORE_DATE, ERROR) \ - FUNC(MISSING_SPACE_BEFORE_EMAIL, ERROR) \ - FUNC(MISSING_TAG, ERROR) \ - FUNC(MISSING_TAG_ENTRY, ERROR) \ - FUNC(MISSING_TREE, ERROR) \ - FUNC(MISSING_TREE_OBJECT, ERROR) \ - FUNC(MISSING_TYPE, ERROR) \ - FUNC(MISSING_TYPE_ENTRY, ERROR) \ - FUNC(MULTIPLE_AUTHORS, ERROR) \ - FUNC(TREE_NOT_SORTED, ERROR) \ - FUNC(UNKNOWN_TYPE, ERROR) \ - FUNC(ZERO_PADDED_DATE, ERROR) \ - FUNC(GITMODULES_MISSING, ERROR) \ - FUNC(GITMODULES_BLOB, ERROR) \ - FUNC(GITMODULES_LARGE, ERROR) \ - FUNC(GITMODULES_NAME, ERROR) \ - FUNC(GITMODULES_SYMLINK, ERROR) \ - FUNC(GITMODULES_URL, ERROR) \ - FUNC(GITMODULES_PATH, ERROR) \ - FUNC(GITMODULES_UPDATE, ERROR) \ - /* warnings */ \ - FUNC(BAD_FILEMODE, WARN) \ - FUNC(EMPTY_NAME, WARN) \ - FUNC(FULL_PATHNAME, WARN) \ - FUNC(HAS_DOT, WARN) \ - FUNC(HAS_DOTDOT, WARN) \ - FUNC(HAS_DOTGIT, WARN) \ - FUNC(NULL_SHA1, WARN) \ - FUNC(ZERO_PADDED_FILEMODE, WARN) \ - FUNC(NUL_IN_COMMIT, WARN) \ - /* infos (reported as warnings, but ignored by default) */ \ - FUNC(GITMODULES_PARSE, INFO) \ - FUNC(BAD_TAG_NAME, INFO) \ - FUNC(MISSING_TAGGER_ENTRY, INFO) \ - /* ignored (elevated when requested) */ \ - FUNC(EXTRA_HEADER_ENTRY, IGNORE) - -#define MSG_ID(id, msg_type) FSCK_MSG_##id, -enum fsck_msg_id { - FOREACH_FSCK_MSG_ID(MSG_ID) - FSCK_MSG_MAX -}; -#undef MSG_ID - #define STR(x) #x #define MSG_ID(id, msg_type) { STR(id), NULL, NULL, FSCK_##msg_type }, static struct { diff --git a/fsck.h b/fsck.h index a7e092d3fb..66c4a71139 100644 --- a/fsck.h +++ b/fsck.h @@ -13,6 +13,72 @@ enum fsck_msg_type { FSCK_WARN, }; +#define FOREACH_FSCK_MSG_ID(FUNC) \ + /* fatal errors */ \ + FUNC(NUL_IN_HEADER, FATAL) \ + FUNC(UNTERMINATED_HEADER, FATAL) \ + /* errors */ \ + FUNC(BAD_DATE, ERROR) \ + FUNC(BAD_DATE_OVERFLOW, ERROR) \ + FUNC(BAD_EMAIL, ERROR) \ + FUNC(BAD_NAME, ERROR) \ + FUNC(BAD_OBJECT_SHA1, ERROR) \ + FUNC(BAD_PARENT_SHA1, ERROR) \ + FUNC(BAD_TAG_OBJECT, ERROR) \ + FUNC(BAD_TIMEZONE, ERROR) \ + FUNC(BAD_TREE, ERROR) \ + FUNC(BAD_TREE_SHA1, ERROR) \ + FUNC(BAD_TYPE, ERROR) \ + FUNC(DUPLICATE_ENTRIES, ERROR) \ + FUNC(MISSING_AUTHOR, ERROR) \ + FUNC(MISSING_COMMITTER, ERROR) \ + FUNC(MISSING_EMAIL, ERROR) \ + FUNC(MISSING_NAME_BEFORE_EMAIL, ERROR) \ + FUNC(MISSING_OBJECT, ERROR) \ + FUNC(MISSING_SPACE_BEFORE_DATE, ERROR) \ + FUNC(MISSING_SPACE_BEFORE_EMAIL, ERROR) \ + FUNC(MISSING_TAG, ERROR) \ + FUNC(MISSING_TAG_ENTRY, ERROR) \ + FUNC(MISSING_TREE, ERROR) \ + FUNC(MISSING_TREE_OBJECT, ERROR) \ + FUNC(MISSING_TYPE, ERROR) \ + FUNC(MISSING_TYPE_ENTRY, ERROR) \ + FUNC(MULTIPLE_AUTHORS, ERROR) \ + FUNC(TREE_NOT_SORTED, ERROR) \ + FUNC(UNKNOWN_TYPE, ERROR) \ + FUNC(ZERO_PADDED_DATE, ERROR) \ + FUNC(GITMODULES_MISSING, ERROR) \ + FUNC(GITMODULES_BLOB, ERROR) \ + FUNC(GITMODULES_LARGE, ERROR) \ + FUNC(GITMODULES_NAME, ERROR) \ + FUNC(GITMODULES_SYMLINK, ERROR) \ + FUNC(GITMODULES_URL, ERROR) \ + FUNC(GITMODULES_PATH, ERROR) \ + FUNC(GITMODULES_UPDATE, ERROR) \ + /* warnings */ \ + FUNC(BAD_FILEMODE, WARN) \ + FUNC(EMPTY_NAME, WARN) \ + FUNC(FULL_PATHNAME, WARN) \ + FUNC(HAS_DOT, WARN) \ + FUNC(HAS_DOTDOT, WARN) \ + FUNC(HAS_DOTGIT, WARN) \ + FUNC(NULL_SHA1, WARN) \ + FUNC(ZERO_PADDED_FILEMODE, WARN) \ + FUNC(NUL_IN_COMMIT, WARN) \ + /* infos (reported as warnings, but ignored by default) */ \ + FUNC(GITMODULES_PARSE, INFO) \ + FUNC(BAD_TAG_NAME, INFO) \ + FUNC(MISSING_TAGGER_ENTRY, INFO) \ + /* ignored (elevated when requested) */ \ + FUNC(EXTRA_HEADER_ENTRY, IGNORE) + +#define MSG_ID(id, msg_type) FSCK_MSG_##id, +enum fsck_msg_id { + FOREACH_FSCK_MSG_ID(MSG_ID) + FSCK_MSG_MAX +}; +#undef MSG_ID + struct fsck_options; struct object; From 394d5d31b0d3096aed4513bdacf48fb73003f1df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=86var=20Arnfj=C3=B6r=C3=B0=20Bjarmason?= Date: Sun, 28 Mar 2021 15:15:46 +0200 Subject: [PATCH 14/19] fsck.c: pass along the fsck_msg_id in the fsck_error callback MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change the fsck_error callback to also pass along the fsck_msg_id. Before this change the only way to get the message id was to parse it back out of the "message". Let's pass it down explicitly for the benefit of callers that might want to use it, as discussed in [1]. Passing the msg_type is now redundant, as you can always get it back from the msg_id, but I'm not changing that convention. It's really common to need the msg_type, and the report() function itself (which calls "fsck_error") needs to call fsck_msg_type() to discover it. Let's not needlessly re-do that work in the user callback. 1. https://lore.kernel.org/git/87blcja2ha.fsf@evledraar.gmail.com/ Signed-off-by: Ævar Arnfjörð Bjarmason Signed-off-by: Junio C Hamano --- builtin/fsck.c | 4 +++- builtin/index-pack.c | 3 ++- builtin/mktag.c | 1 + fsck.c | 6 ++++-- fsck.h | 6 ++++-- 5 files changed, 14 insertions(+), 6 deletions(-) diff --git a/builtin/fsck.c b/builtin/fsck.c index 17940a4e24..70ff95837a 100644 --- a/builtin/fsck.c +++ b/builtin/fsck.c @@ -84,7 +84,9 @@ static int objerror(struct object *obj, const char *err) static int fsck_error_func(struct fsck_options *o, const struct object_id *oid, enum object_type object_type, - enum fsck_msg_type msg_type, const char *message) + enum fsck_msg_type msg_type, + enum fsck_msg_id msg_id, + const char *message) { switch (msg_type) { case FSCK_WARN: diff --git a/builtin/index-pack.c b/builtin/index-pack.c index 56b8efaa89..2b2266a4b7 100644 --- a/builtin/index-pack.c +++ b/builtin/index-pack.c @@ -1717,6 +1717,7 @@ static int print_dangling_gitmodules(struct fsck_options *o, const struct object_id *oid, enum object_type object_type, enum fsck_msg_type msg_type, + enum fsck_msg_id msg_id, const char *message) { /* @@ -1727,7 +1728,7 @@ static int print_dangling_gitmodules(struct fsck_options *o, printf("%s\n", oid_to_hex(oid)); return 0; } - return fsck_error_function(o, oid, object_type, msg_type, message); + return fsck_error_function(o, oid, object_type, msg_type, msg_id, message); } int cmd_index_pack(int argc, const char **argv, const char *prefix) diff --git a/builtin/mktag.c b/builtin/mktag.c index 052a510ad7..96e63bc772 100644 --- a/builtin/mktag.c +++ b/builtin/mktag.c @@ -18,6 +18,7 @@ static int mktag_fsck_error_func(struct fsck_options *o, const struct object_id *oid, enum object_type object_type, enum fsck_msg_type msg_type, + enum fsck_msg_id msg_id, const char *message) { switch (msg_type) { diff --git a/fsck.c b/fsck.c index 150fe467e4..23a77fe2e0 100644 --- a/fsck.c +++ b/fsck.c @@ -227,7 +227,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, - msg_type, sb.buf); + msg_type, msg_id, sb.buf); strbuf_release(&sb); va_end(ap); @@ -1180,7 +1180,9 @@ int fsck_object(struct object *obj, void *data, unsigned long size, int fsck_error_function(struct fsck_options *o, const struct object_id *oid, enum object_type object_type, - enum fsck_msg_type msg_type, const char *message) + enum fsck_msg_type msg_type, + enum fsck_msg_id msg_id, + const char *message) { if (msg_type == FSCK_WARN) { warning("object %s: %s", fsck_describe_object(o, oid), message); diff --git a/fsck.h b/fsck.h index 66c4a71139..fa2d4955ab 100644 --- a/fsck.h +++ b/fsck.h @@ -101,11 +101,13 @@ typedef int (*fsck_walk_func)(struct object *obj, enum object_type object_type, /* callback for fsck_object, type is FSCK_ERROR or FSCK_WARN */ typedef int (*fsck_error)(struct fsck_options *o, const struct object_id *oid, enum object_type object_type, - enum fsck_msg_type msg_type, const char *message); + enum fsck_msg_type msg_type, enum fsck_msg_id msg_id, + const char *message); int fsck_error_function(struct fsck_options *o, const struct object_id *oid, enum object_type object_type, - enum fsck_msg_type msg_type, const char *message); + enum fsck_msg_type msg_type, enum fsck_msg_id msg_id, + const char *message); struct fsck_options { fsck_walk_func walk; From 53692df2b82f9d5ce15779da7d5227f1b027e193 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=86var=20Arnfj=C3=B6r=C3=B0=20Bjarmason?= Date: Sun, 28 Mar 2021 15:15:47 +0200 Subject: [PATCH 15/19] fsck.c: add an fsck_set_msg_type() API that takes enums MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change code I added in acf9de4c94e (mktag: use fsck instead of custom verify_tag(), 2021-01-05) to make use of a new API function that takes the fsck_msg_{id,type} types, instead of arbitrary strings that we'll (hopefully) parse into those types. At the time that the fsck_set_msg_type() API was introduced in 0282f4dced0 (fsck: offer a function to demote fsck errors to warnings, 2015-06-22) it was only intended to be used to parse user-supplied data. For things that are purely internal to the C code it makes sense to have the compiler check these arguments, and to skip the sanity checking of the data in fsck_set_msg_type() which is redundant to checks we get from the compiler. Signed-off-by: Ævar Arnfjörð Bjarmason Signed-off-by: Junio C Hamano --- builtin/mktag.c | 3 ++- fsck.c | 27 +++++++++++++++++---------- fsck.h | 3 +++ 3 files changed, 22 insertions(+), 11 deletions(-) diff --git a/builtin/mktag.c b/builtin/mktag.c index 96e63bc772..dddcccdd36 100644 --- a/builtin/mktag.c +++ b/builtin/mktag.c @@ -88,7 +88,8 @@ int cmd_mktag(int argc, const char **argv, const char *prefix) die_errno(_("could not read from stdin")); fsck_options.error_func = mktag_fsck_error_func; - fsck_set_msg_type(&fsck_options, "extraheaderentry", "warn"); + fsck_set_msg_type_from_ids(&fsck_options, FSCK_MSG_EXTRA_HEADER_ENTRY, + FSCK_WARN); /* config might set fsck.extraHeaderEntry=* again */ git_config(git_fsck_config, &fsck_options); if (fsck_tag_standalone(NULL, buf.buf, buf.len, &fsck_options, diff --git a/fsck.c b/fsck.c index 23a77fe2e0..a59832a165 100644 --- a/fsck.c +++ b/fsck.c @@ -132,6 +132,22 @@ int is_valid_msg_type(const char *msg_id, const char *msg_type) return 1; } +void fsck_set_msg_type_from_ids(struct fsck_options *options, + enum fsck_msg_id msg_id, + enum fsck_msg_type msg_type) +{ + if (!options->msg_type) { + int i; + enum fsck_msg_type *severity; + ALLOC_ARRAY(severity, FSCK_MSG_MAX); + for (i = 0; i < FSCK_MSG_MAX; i++) + severity[i] = fsck_msg_type(i, options); + options->msg_type = severity; + } + + options->msg_type[msg_id] = msg_type; +} + void fsck_set_msg_type(struct fsck_options *options, const char *msg_id_str, const char *msg_type_str) { @@ -144,16 +160,7 @@ void fsck_set_msg_type(struct fsck_options *options, if (msg_type != FSCK_ERROR && msg_id_info[msg_id].msg_type == FSCK_FATAL) die("Cannot demote %s to %s", msg_id_str, msg_type_str); - if (!options->msg_type) { - int i; - enum fsck_msg_type *severity; - ALLOC_ARRAY(severity, FSCK_MSG_MAX); - for (i = 0; i < FSCK_MSG_MAX; i++) - severity[i] = fsck_msg_type(i, options); - options->msg_type = severity; - } - - options->msg_type[msg_id] = msg_type; + fsck_set_msg_type_from_ids(options, msg_id, msg_type); } void fsck_set_msg_types(struct fsck_options *options, const char *values) diff --git a/fsck.h b/fsck.h index fa2d4955ab..d284bac361 100644 --- a/fsck.h +++ b/fsck.h @@ -82,6 +82,9 @@ enum fsck_msg_id { struct fsck_options; struct object; +void fsck_set_msg_type_from_ids(struct fsck_options *options, + enum fsck_msg_id msg_id, + enum fsck_msg_type msg_type); void fsck_set_msg_type(struct fsck_options *options, const char *msg_id, const char *msg_type); void fsck_set_msg_types(struct fsck_options *options, const char *values); From c15087d17bd3c146696bfe6abf86322d79bf61ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=86var=20Arnfj=C3=B6r=C3=B0=20Bjarmason?= Date: Sun, 28 Mar 2021 15:15:48 +0200 Subject: [PATCH 16/19] fsck.c: move gitmodules_{found,done} into fsck_options MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move the gitmodules_{found,done} static variables added in 159e7b080bf (fsck: detect gitmodules files, 2018-05-02) into the fsck_options struct. It makes sense to keep all the context in the same place. This requires changing the recently added register_found_gitmodules() function added in 5476e1efde (fetch-pack: print and use dangling .gitmodules, 2021-02-22) to take fsck_options. That function will be removed in a subsequent commit, but as it'll require the new gitmodules_found attribute of "fsck_options" we need this intermediate step first. An earlier version of this patch removed the small amount of duplication we now have between FSCK_OPTIONS_{DEFAULT,STRICT} with a FSCK_OPTIONS_COMMON macro. I don't think such de-duplication is worth it for this amount of copy/pasting. Signed-off-by: Ævar Arnfjörð Bjarmason Signed-off-by: Junio C Hamano --- fetch-pack.c | 2 +- fsck.c | 23 ++++++++++------------- fsck.h | 9 ++++++++- 3 files changed, 19 insertions(+), 15 deletions(-) diff --git a/fetch-pack.c b/fetch-pack.c index 6a61a46428..82c3c2c043 100644 --- a/fetch-pack.c +++ b/fetch-pack.c @@ -998,7 +998,7 @@ static void fsck_gitmodules_oids(struct oidset *gitmodules_oids) oidset_iter_init(gitmodules_oids, &iter); while ((oid = oidset_iter_next(&iter))) - register_found_gitmodules(oid); + register_found_gitmodules(&fo, oid); if (fsck_finish(&fo)) die("fsck failed"); } diff --git a/fsck.c b/fsck.c index a59832a165..642bd2ef9d 100644 --- a/fsck.c +++ b/fsck.c @@ -19,9 +19,6 @@ #include "credential.h" #include "help.h" -static struct oidset gitmodules_found = OIDSET_INIT; -static struct oidset gitmodules_done = OIDSET_INIT; - #define STR(x) #x #define MSG_ID(id, msg_type) { STR(id), NULL, NULL, FSCK_##msg_type }, static struct { @@ -606,7 +603,7 @@ static int fsck_tree(const struct object_id *oid, if (is_hfs_dotgitmodules(name) || is_ntfs_dotgitmodules(name)) { if (!S_ISLNK(mode)) - oidset_insert(&gitmodules_found, oid); + oidset_insert(&options->gitmodules_found, oid); else retval += report(options, oid, OBJ_TREE, @@ -620,7 +617,7 @@ static int fsck_tree(const struct object_id *oid, has_dotgit |= is_ntfs_dotgit(backslash); if (is_ntfs_dotgitmodules(backslash)) { if (!S_ISLNK(mode)) - oidset_insert(&gitmodules_found, oid); + oidset_insert(&options->gitmodules_found, oid); else retval += report(options, oid, OBJ_TREE, FSCK_MSG_GITMODULES_SYMLINK, @@ -1132,9 +1129,9 @@ static int fsck_blob(const struct object_id *oid, const char *buf, struct fsck_gitmodules_data data; struct config_options config_opts = { 0 }; - if (!oidset_contains(&gitmodules_found, oid)) + if (!oidset_contains(&options->gitmodules_found, oid)) return 0; - oidset_insert(&gitmodules_done, oid); + oidset_insert(&options->gitmodules_done, oid); if (object_on_skiplist(options, oid)) return 0; @@ -1199,9 +1196,9 @@ int fsck_error_function(struct fsck_options *o, return 1; } -void register_found_gitmodules(const struct object_id *oid) +void register_found_gitmodules(struct fsck_options *options, const struct object_id *oid) { - oidset_insert(&gitmodules_found, oid); + oidset_insert(&options->gitmodules_found, oid); } int fsck_finish(struct fsck_options *options) @@ -1210,13 +1207,13 @@ int fsck_finish(struct fsck_options *options) struct oidset_iter iter; const struct object_id *oid; - oidset_iter_init(&gitmodules_found, &iter); + oidset_iter_init(&options->gitmodules_found, &iter); while ((oid = oidset_iter_next(&iter))) { enum object_type type; unsigned long size; char *buf; - if (oidset_contains(&gitmodules_done, oid)) + if (oidset_contains(&options->gitmodules_done, oid)) continue; buf = read_object_file(oid, &type, &size); @@ -1241,8 +1238,8 @@ int fsck_finish(struct fsck_options *options) } - oidset_clear(&gitmodules_found); - oidset_clear(&gitmodules_done); + oidset_clear(&options->gitmodules_found); + oidset_clear(&options->gitmodules_done); return ret; } diff --git a/fsck.h b/fsck.h index d284bac361..e20f9bcb39 100644 --- a/fsck.h +++ b/fsck.h @@ -118,15 +118,21 @@ struct fsck_options { unsigned strict:1; enum fsck_msg_type *msg_type; struct oidset skiplist; + struct oidset gitmodules_found; + struct oidset gitmodules_done; kh_oid_map_t *object_names; }; #define FSCK_OPTIONS_DEFAULT { \ .skiplist = OIDSET_INIT, \ + .gitmodules_found = OIDSET_INIT, \ + .gitmodules_done = OIDSET_INIT, \ .error_func = fsck_error_function \ } #define FSCK_OPTIONS_STRICT { \ .strict = 1, \ + .gitmodules_found = OIDSET_INIT, \ + .gitmodules_done = OIDSET_INIT, \ .error_func = fsck_error_function, \ } @@ -146,7 +152,8 @@ int fsck_walk(struct object *obj, void *data, struct fsck_options *options); int fsck_object(struct object *obj, void *data, unsigned long size, struct fsck_options *options); -void register_found_gitmodules(const struct object_id *oid); +void register_found_gitmodules(struct fsck_options *options, + const struct object_id *oid); /* * fsck a tag, and pass info about it back to the caller. This is From 462f5cae0f764569da4e6a7ab40ee1d3b85353ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=86var=20Arnfj=C3=B6r=C3=B0=20Bjarmason?= Date: Sun, 28 Mar 2021 15:15:49 +0200 Subject: [PATCH 17/19] fetch-pack: don't needlessly copy fsck_options MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change the behavior of the .gitmodules validation added in 5476e1efde (fetch-pack: print and use dangling .gitmodules, 2021-02-22) so we're using one "fsck_options". I found that code confusing to read. One might think that not setting up the error_func earlier means that we're relying on the "error_func" not being set in some code in between the two hunks being modified here. But we're not, all we're doing in the rest of "cmd_index_pack()" is further setup by calling fsck_set_msg_types(), and assigning to do_fsck_object. So there was no reason in 5476e1efde to make a shallow copy of the fsck_options struct before setting error_func. Let's just do this setup at the top of the function, along with the "walk" assignment. Signed-off-by: Ævar Arnfjörð Bjarmason Signed-off-by: Junio C Hamano --- builtin/index-pack.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/builtin/index-pack.c b/builtin/index-pack.c index 2b2266a4b7..5ad80b85b4 100644 --- a/builtin/index-pack.c +++ b/builtin/index-pack.c @@ -1761,6 +1761,7 @@ int cmd_index_pack(int argc, const char **argv, const char *prefix) read_replace_refs = 0; fsck_options.walk = mark_link; + fsck_options.error_func = print_dangling_gitmodules; reset_pack_idx_option(&opts); git_config(git_index_pack_config, &opts); @@ -1951,13 +1952,8 @@ int cmd_index_pack(int argc, const char **argv, const char *prefix) else close(input_fd); - if (do_fsck_object) { - struct fsck_options fo = fsck_options; - - fo.error_func = print_dangling_gitmodules; - if (fsck_finish(&fo)) - die(_("fsck error in pack objects")); - } + if (do_fsck_object && fsck_finish(&fsck_options)) + die(_("fsck error in pack objects")); free(objects); strbuf_release(&index_name_buf); From c96e184cae4294a4ebd18a1bdf8d6514445f32e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=86var=20Arnfj=C3=B6r=C3=B0=20Bjarmason?= Date: Sun, 28 Mar 2021 15:15:50 +0200 Subject: [PATCH 18/19] fetch-pack: use file-scope static struct for fsck_options MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change code added in 5476e1efde (fetch-pack: print and use dangling .gitmodules, 2021-02-22) so that we use a file-scoped "static struct fsck_options" instead of defining one in the "fsck_gitmodules_oids()" function. We use this pattern in all of builtin/{fsck,index-pack,mktag,unpack-objects}.c. It's odd to see fetch-pack be the odd one out. One might think that we're using other fsck_options structs in fetch-pack, or doing on fsck twice there, but we're not. Signed-off-by: Ævar Arnfjörð Bjarmason Signed-off-by: Junio C Hamano --- fetch-pack.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/fetch-pack.c b/fetch-pack.c index 82c3c2c043..229fd8e2c2 100644 --- a/fetch-pack.c +++ b/fetch-pack.c @@ -38,6 +38,7 @@ static int server_supports_filtering; static int advertise_sid; static struct shallow_lock shallow_lock; static const char *alternate_shallow_file; +static struct fsck_options fsck_options = FSCK_OPTIONS_STRICT; static struct strbuf fsck_msg_types = STRBUF_INIT; static struct string_list uri_protocols = STRING_LIST_INIT_DUP; @@ -991,15 +992,14 @@ static void fsck_gitmodules_oids(struct oidset *gitmodules_oids) { struct oidset_iter iter; const struct object_id *oid; - struct fsck_options fo = FSCK_OPTIONS_STRICT; if (!oidset_size(gitmodules_oids)) return; oidset_iter_init(gitmodules_oids, &iter); while ((oid = oidset_iter_next(&iter))) - register_found_gitmodules(&fo, oid); - if (fsck_finish(&fo)) + register_found_gitmodules(&fsck_options, oid); + if (fsck_finish(&fsck_options)) die("fsck failed"); } From 3745e2693de3dd5420221782ed050cae6ebf6fec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=86var=20Arnfj=C3=B6r=C3=B0=20Bjarmason?= Date: Sun, 28 Mar 2021 15:15:51 +0200 Subject: [PATCH 19/19] fetch-pack: use new fsck API to printing dangling submodules MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Refactor the check added in 5476e1efde (fetch-pack: print and use dangling .gitmodules, 2021-02-22) to make use of us now passing the "msg_id" to the user defined "error_func". We can now compare against the FSCK_MSG_GITMODULES_MISSING instead of parsing the generated message. Let's also replace register_found_gitmodules() with directly manipulating the "gitmodules_found" member. A recent commit moved it into "fsck_options" so we could do this here. I'm sticking this callback in fsck.c. Perhaps in the future we'd like to accumulate such callbacks into another file (maybe fsck-cb.c, similar to parse-options-cb.c?), but while we've got just the one let's just put it into fsck.c. A better alternative in this case would be some library some more obvious library shared by fetch-pack.c ad builtin/index-pack.c, but there isn't such a thing. Signed-off-by: Ævar Arnfjörð Bjarmason Signed-off-by: Junio C Hamano --- builtin/index-pack.c | 21 +-------------------- fetch-pack.c | 31 ++++++++----------------------- fsck.c | 23 ++++++++++++++++++----- fsck.h | 15 ++++++++++++--- 4 files changed, 39 insertions(+), 51 deletions(-) diff --git a/builtin/index-pack.c b/builtin/index-pack.c index 5ad80b85b4..11f0fafd33 100644 --- a/builtin/index-pack.c +++ b/builtin/index-pack.c @@ -120,7 +120,7 @@ static int nr_threads; static int from_stdin; static int strict; static int do_fsck_object; -static struct fsck_options fsck_options = FSCK_OPTIONS_STRICT; +static struct fsck_options fsck_options = FSCK_OPTIONS_MISSING_GITMODULES; static int verbose; static int show_resolving_progress; static int show_stat; @@ -1713,24 +1713,6 @@ static void show_pack_info(int stat_only) } } -static int print_dangling_gitmodules(struct fsck_options *o, - const struct object_id *oid, - enum object_type object_type, - enum fsck_msg_type msg_type, - enum fsck_msg_id msg_id, - const char *message) -{ - /* - * NEEDSWORK: Plumb the MSG_ID (from fsck.c) here and use it - * instead of relying on this string check. - */ - if (starts_with(message, "gitmodulesMissing")) { - printf("%s\n", oid_to_hex(oid)); - return 0; - } - return fsck_error_function(o, oid, object_type, msg_type, msg_id, message); -} - int cmd_index_pack(int argc, const char **argv, const char *prefix) { int i, fix_thin_pack = 0, verify = 0, stat_only = 0, rev_index; @@ -1761,7 +1743,6 @@ int cmd_index_pack(int argc, const char **argv, const char *prefix) read_replace_refs = 0; fsck_options.walk = mark_link; - fsck_options.error_func = print_dangling_gitmodules; reset_pack_idx_option(&opts); git_config(git_index_pack_config, &opts); diff --git a/fetch-pack.c b/fetch-pack.c index 229fd8e2c2..0392d36c0a 100644 --- a/fetch-pack.c +++ b/fetch-pack.c @@ -38,7 +38,7 @@ static int server_supports_filtering; static int advertise_sid; static struct shallow_lock shallow_lock; static const char *alternate_shallow_file; -static struct fsck_options fsck_options = FSCK_OPTIONS_STRICT; +static struct fsck_options fsck_options = FSCK_OPTIONS_MISSING_GITMODULES; static struct strbuf fsck_msg_types = STRBUF_INIT; static struct string_list uri_protocols = STRING_LIST_INIT_DUP; @@ -988,21 +988,6 @@ static int cmp_ref_by_name(const void *a_, const void *b_) return strcmp(a->name, b->name); } -static void fsck_gitmodules_oids(struct oidset *gitmodules_oids) -{ - struct oidset_iter iter; - const struct object_id *oid; - - if (!oidset_size(gitmodules_oids)) - return; - - oidset_iter_init(gitmodules_oids, &iter); - while ((oid = oidset_iter_next(&iter))) - register_found_gitmodules(&fsck_options, oid); - if (fsck_finish(&fsck_options)) - die("fsck failed"); -} - static struct ref *do_fetch_pack(struct fetch_pack_args *args, int fd[2], const struct ref *orig_ref, @@ -1017,7 +1002,6 @@ static struct ref *do_fetch_pack(struct fetch_pack_args *args, int agent_len; struct fetch_negotiator negotiator_alloc; struct fetch_negotiator *negotiator; - struct oidset gitmodules_oids = OIDSET_INIT; negotiator = &negotiator_alloc; fetch_negotiator_init(r, negotiator); @@ -1134,9 +1118,10 @@ static struct ref *do_fetch_pack(struct fetch_pack_args *args, else alternate_shallow_file = NULL; if (get_pack(args, fd, pack_lockfiles, NULL, sought, nr_sought, - &gitmodules_oids)) + &fsck_options.gitmodules_found)) die(_("git fetch-pack: fetch failed.")); - fsck_gitmodules_oids(&gitmodules_oids); + if (fsck_finish(&fsck_options)) + die("fsck failed"); all_done: if (negotiator) @@ -1587,7 +1572,6 @@ static struct ref *do_fetch_pack_v2(struct fetch_pack_args *args, struct string_list packfile_uris = STRING_LIST_INIT_DUP; int i; struct strvec index_pack_args = STRVEC_INIT; - struct oidset gitmodules_oids = OIDSET_INIT; negotiator = &negotiator_alloc; fetch_negotiator_init(r, negotiator); @@ -1678,7 +1662,7 @@ static struct ref *do_fetch_pack_v2(struct fetch_pack_args *args, process_section_header(&reader, "packfile", 0); if (get_pack(args, fd, pack_lockfiles, packfile_uris.nr ? &index_pack_args : NULL, - sought, nr_sought, &gitmodules_oids)) + sought, nr_sought, &fsck_options.gitmodules_found)) die(_("git fetch-pack: fetch failed.")); do_check_stateless_delimiter(args, &reader); @@ -1721,7 +1705,7 @@ static struct ref *do_fetch_pack_v2(struct fetch_pack_args *args, packname[the_hash_algo->hexsz] = '\0'; - parse_gitmodules_oids(cmd.out, &gitmodules_oids); + parse_gitmodules_oids(cmd.out, &fsck_options.gitmodules_found); close(cmd.out); @@ -1742,7 +1726,8 @@ static struct ref *do_fetch_pack_v2(struct fetch_pack_args *args, string_list_clear(&packfile_uris, 0); strvec_clear(&index_pack_args); - fsck_gitmodules_oids(&gitmodules_oids); + if (fsck_finish(&fsck_options)) + die("fsck failed"); if (negotiator) negotiator->release(negotiator); diff --git a/fsck.c b/fsck.c index 642bd2ef9d..f5ed6a2635 100644 --- a/fsck.c +++ b/fsck.c @@ -1196,11 +1196,6 @@ int fsck_error_function(struct fsck_options *o, return 1; } -void register_found_gitmodules(struct fsck_options *options, const struct object_id *oid) -{ - oidset_insert(&options->gitmodules_found, oid); -} - int fsck_finish(struct fsck_options *options) { int ret = 0; @@ -1266,3 +1261,21 @@ int git_fsck_config(const char *var, const char *value, void *cb) return git_default_config(var, value, cb); } + +/* + * Custom error callbacks that are used in more than one place. + */ + +int fsck_error_cb_print_missing_gitmodules(struct fsck_options *o, + const struct object_id *oid, + enum object_type object_type, + 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)); + return 0; + } + return fsck_error_function(o, oid, object_type, msg_type, msg_id, message); +} diff --git a/fsck.h b/fsck.h index e20f9bcb39..7202c3c87e 100644 --- a/fsck.h +++ b/fsck.h @@ -111,6 +111,12 @@ int fsck_error_function(struct fsck_options *o, const struct object_id *oid, enum object_type object_type, enum fsck_msg_type msg_type, enum fsck_msg_id msg_id, const char *message); +int fsck_error_cb_print_missing_gitmodules(struct fsck_options *o, + const struct object_id *oid, + enum object_type object_type, + enum fsck_msg_type msg_type, + enum fsck_msg_id msg_id, + const char *message); struct fsck_options { fsck_walk_func walk; @@ -135,6 +141,12 @@ struct fsck_options { .gitmodules_done = OIDSET_INIT, \ .error_func = fsck_error_function, \ } +#define FSCK_OPTIONS_MISSING_GITMODULES { \ + .strict = 1, \ + .gitmodules_found = OIDSET_INIT, \ + .gitmodules_done = OIDSET_INIT, \ + .error_func = fsck_error_cb_print_missing_gitmodules, \ +} /* descend in all linked child objects * the return value is: @@ -152,9 +164,6 @@ int fsck_walk(struct object *obj, void *data, struct fsck_options *options); int fsck_object(struct object *obj, void *data, unsigned long size, struct fsck_options *options); -void register_found_gitmodules(struct fsck_options *options, - const struct object_id *oid); - /* * fsck a tag, and pass info about it back to the caller. This is * exposed fsck_object() internals for git-mktag(1).