From 17cabd369b5cb96bee9577f49247ef95d07058a7 Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Mon, 23 Mar 2026 16:02:52 +0100 Subject: fetch-pack: move fsck options into function scope When fetching a packfile, we optionally verify received objects via the fsck subsystem. The options for those consistency checks are declared in global scope without a good reason, and they are never cleaned up. So in case the options are reused, they may accumulate more state over time. Furthermore, in subsequent changes we'll introduce a repository pointer into the structure. Obviously though, we don't have a repository available at static time, except for `the_repository`, which we don't want to use here. Refactor the code to move the options into the respective functions and properly manage their lifecycle. Signed-off-by: Patrick Steinhardt Signed-off-by: Junio C Hamano --- fetch-pack.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'fetch-pack.c') diff --git a/fetch-pack.c b/fetch-pack.c index 6ecd468ef7..ec5abb92b5 100644 --- a/fetch-pack.c +++ b/fetch-pack.c @@ -51,7 +51,6 @@ 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_MISSING_GITMODULES; static struct strbuf fsck_msg_types = STRBUF_INIT; static struct string_list uri_protocols = STRING_LIST_INIT_DUP; @@ -1100,6 +1099,7 @@ static struct ref *do_fetch_pack(struct fetch_pack_args *args, struct shallow_info *si, struct string_list *pack_lockfiles) { + struct fsck_options fsck_options = FSCK_OPTIONS_MISSING_GITMODULES; struct repository *r = the_repository; struct ref *ref = copy_ref_list(orig_ref); struct object_id oid; @@ -1235,6 +1235,7 @@ static struct ref *do_fetch_pack(struct fetch_pack_args *args, die("fsck failed"); all_done: + fsck_options_clear(&fsck_options); if (negotiator) negotiator->release(negotiator); return ref; @@ -1654,6 +1655,7 @@ static struct ref *do_fetch_pack_v2(struct fetch_pack_args *args, struct string_list *pack_lockfiles) { struct repository *r = the_repository; + struct fsck_options fsck_options = FSCK_OPTIONS_MISSING_GITMODULES; struct ref *ref = copy_ref_list(orig_ref); enum fetch_state state = FETCH_CHECK_LOCAL; struct oidset common = OIDSET_INIT; @@ -1882,6 +1884,7 @@ static struct ref *do_fetch_pack_v2(struct fetch_pack_args *args, if (negotiator) negotiator->release(negotiator); + fsck_options_clear(&fsck_options); oidset_clear(&common); return ref; } -- cgit v1.3 From f22360902621e0807a1c0a77476e3e4d323c708d Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Mon, 23 Mar 2026 16:02:53 +0100 Subject: fsck: initialize fsck options via a function We initialize the `struct fsck_options` via a set of macros, often in global scope. In the next commit though we're about to introduce a new repository field to the options that must be initialized, and naturally we don't have a repo other than `the_repository` available in this scope. Refactor the code to instead intrdouce a new `fsck_options_init()` function that initializes the options for us and move initialization into function scope. Signed-off-by: Patrick Steinhardt Signed-off-by: Junio C Hamano --- builtin/fsck.c | 10 +++++++--- builtin/index-pack.c | 4 +++- builtin/mktag.c | 3 ++- builtin/refs.c | 4 +++- builtin/unpack-objects.c | 4 +++- fetch-pack.c | 8 ++++++-- fsck.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ fsck.h | 38 ++++++++++---------------------------- object-file.c | 3 ++- 9 files changed, 81 insertions(+), 38 deletions(-) (limited to 'fetch-pack.c') diff --git a/builtin/fsck.c b/builtin/fsck.c index 9bab32effe..59e3b0f7ac 100644 --- a/builtin/fsck.c +++ b/builtin/fsck.c @@ -42,8 +42,8 @@ static int check_full = 1; static int connectivity_only; static int check_strict; static int keep_cache_objects; -static struct fsck_options fsck_walk_options = FSCK_OPTIONS_DEFAULT; -static struct fsck_options fsck_obj_options = FSCK_OPTIONS_DEFAULT; +static struct fsck_options fsck_walk_options; +static struct fsck_options fsck_obj_options; static int errors_found; static int write_lost_and_found; static int verbose; @@ -224,7 +224,7 @@ static int mark_unreachable_referents(const struct object_id *oid, struct object_info *oi UNUSED, void *data UNUSED) { - struct fsck_options options = FSCK_OPTIONS_DEFAULT; + struct fsck_options options; struct object *obj = lookup_object(the_repository, oid); if (!obj || !(obj->flags & HAS_OBJ)) @@ -243,6 +243,7 @@ static int mark_unreachable_referents(const struct object_id *oid, object_as_type(obj, type, 0); } + fsck_options_init(&options, FSCK_OPTIONS_DEFAULT); options.walk = mark_used; fsck_walk(obj, NULL, &options); if (obj->type == OBJ_TREE) @@ -1004,7 +1005,10 @@ int cmd_fsck(int argc, argc = parse_options(argc, argv, prefix, fsck_opts, fsck_usage, 0); + fsck_options_init(&fsck_walk_options, FSCK_OPTIONS_DEFAULT); fsck_walk_options.walk = mark_object; + + fsck_options_init(&fsck_obj_options, FSCK_OPTIONS_DEFAULT); fsck_obj_options.walk = mark_used; fsck_obj_options.error_func = fsck_objects_error_func; if (check_strict) diff --git a/builtin/index-pack.c b/builtin/index-pack.c index d1e47279a8..c8d28bcf8e 100644 --- a/builtin/index-pack.c +++ b/builtin/index-pack.c @@ -136,7 +136,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_MISSING_GITMODULES; +static struct fsck_options fsck_options; static int verbose; static const char *progress_title; static int show_resolving_progress; @@ -1908,6 +1908,8 @@ int cmd_index_pack(int argc, show_usage_if_asked(argc, argv, index_pack_usage); disable_replace_refs(); + + fsck_options_init(&fsck_options, FSCK_OPTIONS_MISSING_GITMODULES); fsck_options.walk = mark_link; reset_pack_idx_option(&opts); diff --git a/builtin/mktag.c b/builtin/mktag.c index 7cf6e1230a..9f37f9dede 100644 --- a/builtin/mktag.c +++ b/builtin/mktag.c @@ -16,7 +16,7 @@ static char const * const builtin_mktag_usage[] = { }; static int option_strict = 1; -static struct fsck_options fsck_options = FSCK_OPTIONS_STRICT; +static struct fsck_options fsck_options; static int mktag_fsck_error_func(struct fsck_options *o UNUSED, void *fsck_report UNUSED, @@ -94,6 +94,7 @@ int cmd_mktag(int argc, if (strbuf_read(&buf, 0, 0) < 0) die_errno(_("could not read from stdin")); + fsck_options_init(&fsck_options, FSCK_OPTIONS_STRICT); fsck_options.error_func = mktag_fsck_error_func; fsck_set_msg_type_from_ids(&fsck_options, FSCK_MSG_EXTRA_HEADER_ENTRY, FSCK_WARN); diff --git a/builtin/refs.c b/builtin/refs.c index 3064f888b2..1719ada549 100644 --- a/builtin/refs.c +++ b/builtin/refs.c @@ -80,7 +80,7 @@ out: static int cmd_refs_verify(int argc, const char **argv, const char *prefix, struct repository *repo UNUSED) { - struct fsck_options fsck_refs_options = FSCK_REFS_OPTIONS_DEFAULT; + struct fsck_options fsck_refs_options; struct worktree **worktrees; const char * const verify_usage[] = { REFS_VERIFY_USAGE, @@ -93,6 +93,8 @@ static int cmd_refs_verify(int argc, const char **argv, const char *prefix, }; int ret = 0; + fsck_options_init(&fsck_refs_options, FSCK_OPTIONS_REFS); + argc = parse_options(argc, argv, prefix, options, verify_usage, 0); if (argc) usage(_("'git refs verify' takes no arguments")); diff --git a/builtin/unpack-objects.c b/builtin/unpack-objects.c index 6fc64e9e4b..9e4bb9d25c 100644 --- a/builtin/unpack-objects.c +++ b/builtin/unpack-objects.c @@ -29,7 +29,7 @@ static unsigned int offset, len; static off_t consumed_bytes; static off_t max_input_size; static struct git_hash_ctx ctx; -static struct fsck_options fsck_options = FSCK_OPTIONS_STRICT; +static struct fsck_options fsck_options; static struct progress *progress; /* @@ -627,6 +627,8 @@ int cmd_unpack_objects(int argc, show_usage_if_asked(argc, argv, unpack_usage); + fsck_options_init(&fsck_options, FSCK_OPTIONS_STRICT); + for (i = 1 ; i < argc; i++) { const char *arg = argv[i]; diff --git a/fetch-pack.c b/fetch-pack.c index ec5abb92b5..7339162368 100644 --- a/fetch-pack.c +++ b/fetch-pack.c @@ -1099,7 +1099,7 @@ static struct ref *do_fetch_pack(struct fetch_pack_args *args, struct shallow_info *si, struct string_list *pack_lockfiles) { - struct fsck_options fsck_options = FSCK_OPTIONS_MISSING_GITMODULES; + struct fsck_options fsck_options = { 0 }; struct repository *r = the_repository; struct ref *ref = copy_ref_list(orig_ref); struct object_id oid; @@ -1228,6 +1228,8 @@ static struct ref *do_fetch_pack(struct fetch_pack_args *args, alternate_shallow_file = setup_temporary_shallow(si->shallow); } else alternate_shallow_file = NULL; + + fsck_options_init(&fsck_options, FSCK_OPTIONS_MISSING_GITMODULES); if (get_pack(args, fd, pack_lockfiles, NULL, sought, nr_sought, &fsck_options.gitmodules_found)) die(_("git fetch-pack: fetch failed.")); @@ -1655,7 +1657,7 @@ static struct ref *do_fetch_pack_v2(struct fetch_pack_args *args, struct string_list *pack_lockfiles) { struct repository *r = the_repository; - struct fsck_options fsck_options = FSCK_OPTIONS_MISSING_GITMODULES; + struct fsck_options fsck_options; struct ref *ref = copy_ref_list(orig_ref); enum fetch_state state = FETCH_CHECK_LOCAL; struct oidset common = OIDSET_INIT; @@ -1673,6 +1675,8 @@ static struct ref *do_fetch_pack_v2(struct fetch_pack_args *args, struct strvec index_pack_args = STRVEC_INIT; const char *promisor_remote_config; + fsck_options_init(&fsck_options, FSCK_OPTIONS_MISSING_GITMODULES); + if (server_feature_v2("promisor-remote", &promisor_remote_config)) promisor_remote_reply(promisor_remote_config, NULL); diff --git a/fsck.c b/fsck.c index 0f02cf8f77..1ff8208502 100644 --- a/fsck.c +++ b/fsck.c @@ -1380,6 +1380,51 @@ bool fsck_has_queued_checks(struct fsck_options *options) !oidset_equal(&options->gitattributes_found, &options->gitattributes_done); } +void fsck_options_init(struct fsck_options *options, + enum fsck_options_type type) +{ + static const struct fsck_options defaults[] = { + [FSCK_OPTIONS_DEFAULT] = { + .skip_oids = OIDSET_INIT, + .gitmodules_found = OIDSET_INIT, + .gitmodules_done = OIDSET_INIT, + .gitattributes_found = OIDSET_INIT, + .gitattributes_done = OIDSET_INIT, + .error_func = fsck_objects_error_function + }, + [FSCK_OPTIONS_STRICT] = { + .strict = 1, + .gitmodules_found = OIDSET_INIT, + .gitmodules_done = OIDSET_INIT, + .gitattributes_found = OIDSET_INIT, + .gitattributes_done = OIDSET_INIT, + .error_func = fsck_objects_error_function, + }, + [FSCK_OPTIONS_MISSING_GITMODULES] = { + .strict = 1, + .gitmodules_found = OIDSET_INIT, + .gitmodules_done = OIDSET_INIT, + .gitattributes_found = OIDSET_INIT, + .gitattributes_done = OIDSET_INIT, + .error_func = fsck_objects_error_cb_print_missing_gitmodules, + }, + [FSCK_OPTIONS_REFS] = { + .error_func = fsck_refs_error_function, + }, + }; + + switch (type) { + case FSCK_OPTIONS_DEFAULT: + case FSCK_OPTIONS_STRICT: + case FSCK_OPTIONS_MISSING_GITMODULES: + case FSCK_OPTIONS_REFS: + memcpy(options, &defaults[type], sizeof(*options)); + break; + default: + BUG("unknown fsck options type %d", type); + } +} + void fsck_options_clear(struct fsck_options *options) { free(options->msg_type); diff --git a/fsck.h b/fsck.h index 65ecbb7fe1..9c973b53b2 100644 --- a/fsck.h +++ b/fsck.h @@ -180,34 +180,6 @@ struct fsck_options { kh_oid_map_t *object_names; }; -#define FSCK_OPTIONS_DEFAULT { \ - .skip_oids = OIDSET_INIT, \ - .gitmodules_found = OIDSET_INIT, \ - .gitmodules_done = OIDSET_INIT, \ - .gitattributes_found = OIDSET_INIT, \ - .gitattributes_done = OIDSET_INIT, \ - .error_func = fsck_objects_error_function \ -} -#define FSCK_OPTIONS_STRICT { \ - .strict = 1, \ - .gitmodules_found = OIDSET_INIT, \ - .gitmodules_done = OIDSET_INIT, \ - .gitattributes_found = OIDSET_INIT, \ - .gitattributes_done = OIDSET_INIT, \ - .error_func = fsck_objects_error_function, \ -} -#define FSCK_OPTIONS_MISSING_GITMODULES { \ - .strict = 1, \ - .gitmodules_found = OIDSET_INIT, \ - .gitmodules_done = OIDSET_INIT, \ - .gitattributes_found = OIDSET_INIT, \ - .gitattributes_done = OIDSET_INIT, \ - .error_func = fsck_objects_error_cb_print_missing_gitmodules, \ -} -#define FSCK_REFS_OPTIONS_DEFAULT { \ - .error_func = fsck_refs_error_function, \ -} - /* descend in all linked child objects * the return value is: * -1 error in processing the object @@ -255,6 +227,16 @@ int fsck_finish(struct fsck_options *options); */ bool fsck_has_queued_checks(struct fsck_options *options); +enum fsck_options_type { + FSCK_OPTIONS_DEFAULT, + FSCK_OPTIONS_STRICT, + FSCK_OPTIONS_MISSING_GITMODULES, + FSCK_OPTIONS_REFS, +}; + +void fsck_options_init(struct fsck_options *options, + enum fsck_options_type type); + /* * Clear the fsck_options struct, freeing any allocated memory. */ diff --git a/object-file.c b/object-file.c index c62e5496e0..186b2ff764 100644 --- a/object-file.c +++ b/object-file.c @@ -1279,8 +1279,9 @@ static int index_mem(struct index_state *istate, } } if (flags & INDEX_FORMAT_CHECK) { - struct fsck_options opts = FSCK_OPTIONS_DEFAULT; + struct fsck_options opts; + fsck_options_init(&opts, FSCK_OPTIONS_DEFAULT); opts.strict = 1; opts.error_func = hash_format_check_report; if (fsck_buffer(null_oid(istate->repo->hash_algo), type, buf, size, &opts)) -- cgit v1.3 From 374985390871cb67c02b1608b693480e89567b9a Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Mon, 23 Mar 2026 16:02:54 +0100 Subject: fsck: store repository in fsck options The fsck subsystem relies on `the_repository` quite a bit. While we could of course explicitly pass a repository down the callchain, we already have a `struct fsck_options` that we pass to almost all functions. Extend the options to also store the repository to make it readily available. Suggested-by: Junio C Hamano Signed-off-by: Patrick Steinhardt Signed-off-by: Junio C Hamano --- builtin/fsck.c | 8 ++++---- builtin/index-pack.c | 2 +- builtin/mktag.c | 4 ++-- builtin/refs.c | 4 ++-- builtin/unpack-objects.c | 4 ++-- fetch-pack.c | 4 ++-- fsck.c | 3 +++ fsck.h | 4 ++++ object-file.c | 2 +- 9 files changed, 21 insertions(+), 14 deletions(-) (limited to 'fetch-pack.c') diff --git a/builtin/fsck.c b/builtin/fsck.c index 59e3b0f7ac..990d836918 100644 --- a/builtin/fsck.c +++ b/builtin/fsck.c @@ -243,7 +243,7 @@ static int mark_unreachable_referents(const struct object_id *oid, object_as_type(obj, type, 0); } - fsck_options_init(&options, FSCK_OPTIONS_DEFAULT); + fsck_options_init(&options, the_repository, FSCK_OPTIONS_DEFAULT); options.walk = mark_used; fsck_walk(obj, NULL, &options); if (obj->type == OBJ_TREE) @@ -987,7 +987,7 @@ static struct option fsck_opts[] = { int cmd_fsck(int argc, const char **argv, const char *prefix, - struct repository *repo UNUSED) + struct repository *repo) { struct odb_source *source; struct snapshot snap = { @@ -1005,10 +1005,10 @@ int cmd_fsck(int argc, argc = parse_options(argc, argv, prefix, fsck_opts, fsck_usage, 0); - fsck_options_init(&fsck_walk_options, FSCK_OPTIONS_DEFAULT); + fsck_options_init(&fsck_walk_options, repo, FSCK_OPTIONS_DEFAULT); fsck_walk_options.walk = mark_object; - fsck_options_init(&fsck_obj_options, FSCK_OPTIONS_DEFAULT); + fsck_options_init(&fsck_obj_options, repo, FSCK_OPTIONS_DEFAULT); fsck_obj_options.walk = mark_used; fsck_obj_options.error_func = fsck_objects_error_func; if (check_strict) diff --git a/builtin/index-pack.c b/builtin/index-pack.c index c8d28bcf8e..e4129bd605 100644 --- a/builtin/index-pack.c +++ b/builtin/index-pack.c @@ -1909,7 +1909,7 @@ int cmd_index_pack(int argc, disable_replace_refs(); - fsck_options_init(&fsck_options, FSCK_OPTIONS_MISSING_GITMODULES); + fsck_options_init(&fsck_options, the_repository, FSCK_OPTIONS_MISSING_GITMODULES); fsck_options.walk = mark_link; reset_pack_idx_option(&opts); diff --git a/builtin/mktag.c b/builtin/mktag.c index 9f37f9dede..f40264a878 100644 --- a/builtin/mktag.c +++ b/builtin/mktag.c @@ -75,7 +75,7 @@ static int verify_object_in_tag(struct object_id *tagged_oid, int *tagged_type) int cmd_mktag(int argc, const char **argv, const char *prefix, - struct repository *repo UNUSED) + struct repository *repo) { static struct option builtin_mktag_options[] = { OPT_BOOL(0, "strict", &option_strict, @@ -94,7 +94,7 @@ int cmd_mktag(int argc, if (strbuf_read(&buf, 0, 0) < 0) die_errno(_("could not read from stdin")); - fsck_options_init(&fsck_options, FSCK_OPTIONS_STRICT); + fsck_options_init(&fsck_options, repo, FSCK_OPTIONS_STRICT); fsck_options.error_func = mktag_fsck_error_func; fsck_set_msg_type_from_ids(&fsck_options, FSCK_MSG_EXTRA_HEADER_ENTRY, FSCK_WARN); diff --git a/builtin/refs.c b/builtin/refs.c index 1719ada549..e3125bc61b 100644 --- a/builtin/refs.c +++ b/builtin/refs.c @@ -78,7 +78,7 @@ out: } static int cmd_refs_verify(int argc, const char **argv, const char *prefix, - struct repository *repo UNUSED) + struct repository *repo) { struct fsck_options fsck_refs_options; struct worktree **worktrees; @@ -93,7 +93,7 @@ static int cmd_refs_verify(int argc, const char **argv, const char *prefix, }; int ret = 0; - fsck_options_init(&fsck_refs_options, FSCK_OPTIONS_REFS); + fsck_options_init(&fsck_refs_options, repo, FSCK_OPTIONS_REFS); argc = parse_options(argc, argv, prefix, options, verify_usage, 0); if (argc) diff --git a/builtin/unpack-objects.c b/builtin/unpack-objects.c index 9e4bb9d25c..d863912b24 100644 --- a/builtin/unpack-objects.c +++ b/builtin/unpack-objects.c @@ -613,7 +613,7 @@ static void unpack_all(void) int cmd_unpack_objects(int argc, const char **argv, const char *prefix UNUSED, - struct repository *repo UNUSED) + struct repository *repo) { int i; struct object_id oid; @@ -627,7 +627,7 @@ int cmd_unpack_objects(int argc, show_usage_if_asked(argc, argv, unpack_usage); - fsck_options_init(&fsck_options, FSCK_OPTIONS_STRICT); + fsck_options_init(&fsck_options, repo, FSCK_OPTIONS_STRICT); for (i = 1 ; i < argc; i++) { const char *arg = argv[i]; diff --git a/fetch-pack.c b/fetch-pack.c index 7339162368..84a21c5107 100644 --- a/fetch-pack.c +++ b/fetch-pack.c @@ -1229,7 +1229,7 @@ static struct ref *do_fetch_pack(struct fetch_pack_args *args, } else alternate_shallow_file = NULL; - fsck_options_init(&fsck_options, FSCK_OPTIONS_MISSING_GITMODULES); + fsck_options_init(&fsck_options, the_repository, FSCK_OPTIONS_MISSING_GITMODULES); if (get_pack(args, fd, pack_lockfiles, NULL, sought, nr_sought, &fsck_options.gitmodules_found)) die(_("git fetch-pack: fetch failed.")); @@ -1675,7 +1675,7 @@ static struct ref *do_fetch_pack_v2(struct fetch_pack_args *args, struct strvec index_pack_args = STRVEC_INIT; const char *promisor_remote_config; - fsck_options_init(&fsck_options, FSCK_OPTIONS_MISSING_GITMODULES); + fsck_options_init(&fsck_options, the_repository, FSCK_OPTIONS_MISSING_GITMODULES); if (server_feature_v2("promisor-remote", &promisor_remote_config)) promisor_remote_reply(promisor_remote_config, NULL); diff --git a/fsck.c b/fsck.c index 1ff8208502..a05997703a 100644 --- a/fsck.c +++ b/fsck.c @@ -1381,6 +1381,7 @@ bool fsck_has_queued_checks(struct fsck_options *options) } void fsck_options_init(struct fsck_options *options, + struct repository *repo, enum fsck_options_type type) { static const struct fsck_options defaults[] = { @@ -1423,6 +1424,8 @@ void fsck_options_init(struct fsck_options *options, default: BUG("unknown fsck options type %d", type); } + + options->repo = repo; } void fsck_options_clear(struct fsck_options *options) diff --git a/fsck.h b/fsck.h index 9c973b53b2..e77935c8a9 100644 --- a/fsck.h +++ b/fsck.h @@ -166,7 +166,10 @@ struct fsck_ref_report { const char *path; }; +struct repository; + struct fsck_options { + struct repository *repo; fsck_walk_func walk; fsck_error error_func; unsigned strict; @@ -235,6 +238,7 @@ enum fsck_options_type { }; void fsck_options_init(struct fsck_options *options, + struct repository *repo, enum fsck_options_type type); /* diff --git a/object-file.c b/object-file.c index 186b2ff764..24ed5d5577 100644 --- a/object-file.c +++ b/object-file.c @@ -1281,7 +1281,7 @@ static int index_mem(struct index_state *istate, if (flags & INDEX_FORMAT_CHECK) { struct fsck_options opts; - fsck_options_init(&opts, FSCK_OPTIONS_DEFAULT); + fsck_options_init(&opts, the_repository, FSCK_OPTIONS_DEFAULT); opts.strict = 1; opts.error_func = hash_format_check_report; if (fsck_buffer(null_oid(istate->repo->hash_algo), type, buf, size, &opts)) -- cgit v1.3