[PATCH v6] repository: move fetch_if_missing into struct repository
Tian Yuchen <[email protected]>
| Newsgroups | org.kernel.vger.git |
|---|---|
| Message-ID | <[email protected]> |
The global variable 'fetch_if_missing' controls whether a missing object check should prompt a lazy fetch from a promisor remote. In order to continue the libification effort, move it into 'struct repository' and initialize it to 1 by default to keep the previous behavior. builtin/fetch-pack.c, builtin/fsck.c, and builtin/rev-list.c are entered via commands marked RUN_SETUP in git.c:commands[]. Their 'repo' parameter is only NULL when '-h' is given outside of a repository, in which case either show_usage_if_asked() or parse_options()'s own '-h' handling exits the process before returning. We can therefore drop their UNUSED markers and assign to 'repo' directly. builtin/index-pack.c is entered via RUN_SETUP_GENTLY, so its 'repo' pointer can be NULL any time it is run outside of a repository, not only with '-h'. We keep a NULL check there and fall back to 'the_repository'. builtin/pack-objects.c needs two adjustments to make 'repo' reach every 'fetch_if_missing' call site: 'read_stdin_packs()' now takes a 'struct repository *'; 'option_parse_missing_action()', which is registered as an OPT_CALLBACK, receives a 'repo' through the option's 'value' field now. Additionally, update the partial clone documentation to reflect that this is now a per-repository flag. Mentored-by: Christian Couder <[email protected]> Mentored-by: Ayush Chandekar <[email protected]> Mentored-by: Olamide Caleb Bello <[email protected]> Signed-off-by: Tian Yuchen <[email protected]> --- Changes since v5: - for 'option_parse_missing_action' in builtin/pack-objects.c, pass in a repo instance via the option's 'value' field. Hence, the commit 1/2 of the v5 iteration (pack-objects: give fetch_if_missing call sites access to 'repo') is no longer needed. Drop it. Documentation/technical/partial-clone.adoc | 2 +- builtin/fetch-pack.c | 6 ++-- builtin/fsck.c | 6 ++-- builtin/index-pack.c | 8 +++--- builtin/pack-objects.c | 32 ++++++++++++---------- builtin/prune.c | 2 +- builtin/rev-list.c | 17 ++++++------ common-init.c | 2 +- git.c | 2 +- midx-write.c | 2 +- odb.c | 4 +-- odb.h | 8 ------ repository.c | 1 + repository.h | 6 ++++ revision.c | 2 +- 15 files changed, 51 insertions(+), 49 deletions(-) diff --git a/Documentation/technical/partial-clone.adoc b/Documentation/technical/partial-clone.adoc index e513e391ea..18718a3840 100644 --- a/Documentation/technical/partial-clone.adoc +++ b/Documentation/technical/partial-clone.adoc @@ -159,7 +159,7 @@ and prefetch those objects in bulk. - `repack` in GC has been updated to not touch promisor packfiles at all, and to only repack other objects. -- The global variable "fetch_if_missing" is used to control whether an +- The per-repository flag "fetch_if_missing" is used to control whether an object lookup will attempt to dynamically fetch a missing object or report an error. + diff --git a/builtin/fetch-pack.c b/builtin/fetch-pack.c index 316badd969..86754296fa 100644 --- a/builtin/fetch-pack.c +++ b/builtin/fetch-pack.c @@ -49,7 +49,7 @@ static void add_sought_entry(struct ref ***sought, int *nr, int *alloc, int cmd_fetch_pack(int argc, const char **argv, const char *prefix UNUSED, - struct repository *repo UNUSED) + struct repository *repo) { int i, ret; struct ref *fetched_refs = NULL, *remote_refs = NULL; @@ -67,8 +67,6 @@ int cmd_fetch_pack(int argc, struct packet_reader reader; enum protocol_version version; - fetch_if_missing = 0; - packet_trace_identity("fetch-pack"); memset(&args, 0, sizeof(args)); @@ -77,6 +75,8 @@ int cmd_fetch_pack(int argc, show_usage_if_asked(argc, argv, fetch_pack_usage); + repo->fetch_if_missing = 0; + for (i = 1; i < argc && *argv[i] == '-'; i++) { const char *arg = argv[i]; diff --git a/builtin/fsck.c b/builtin/fsck.c index a6c054e45b..8cfc0e8b26 100644 --- a/builtin/fsck.c +++ b/builtin/fsck.c @@ -1017,15 +1017,15 @@ int cmd_fsck(int argc, .ref = NULL }; - /* fsck knows how to handle missing promisor objects */ - fetch_if_missing = 0; - errors_found = 0; disable_replace_refs(); save_commit_buffer = 0; argc = parse_options(argc, argv, prefix, fsck_opts, fsck_usage, 0); + /* fsck knows how to handle missing promisor objects */ + repo->fetch_if_missing = 0; + fsck_options_init(&fsck_walk_options, repo, FSCK_OPTIONS_DEFAULT); fsck_walk_options.walk = mark_object; diff --git a/builtin/index-pack.c b/builtin/index-pack.c index bc86925ad0..28f8d01e04 100644 --- a/builtin/index-pack.c +++ b/builtin/index-pack.c @@ -1886,7 +1886,7 @@ static void repack_local_links(void) int cmd_index_pack(int argc, const char **argv, const char *prefix, - struct repository *repo UNUSED) + struct repository *repo) { int i, fix_thin_pack = 0, verify = 0, stat_only = 0, rev_index; const char *curr_index; @@ -1903,15 +1903,15 @@ int cmd_index_pack(int argc, int report_end_of_input = 0; int hash_algo = 0; + show_usage_if_asked(argc, argv, index_pack_usage); + /* * index-pack never needs to fetch missing objects except when * REF_DELTA bases are missing (which are explicitly handled). It only * accesses the repo to do hash collision checks and to check which * REF_DELTA bases need to be fetched. */ - fetch_if_missing = 0; - - show_usage_if_asked(argc, argv, index_pack_usage); + (repo ? repo : the_repository)->fetch_if_missing = 0; disable_replace_refs(); diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c index 1ec5b6f206..cb1bd39aee 100644 --- a/builtin/pack-objects.c +++ b/builtin/pack-objects.c @@ -4087,9 +4087,10 @@ static void stdin_packs_read_input(struct rev_info *revs, static void add_unreachable_loose_objects(struct rev_info *revs); -static void read_stdin_packs(enum stdin_packs_mode mode, int rev_list_unpacked) +static void read_stdin_packs(struct repository *repo, + enum stdin_packs_mode mode, int rev_list_unpacked) { - int prev_fetch_if_missing = fetch_if_missing; + int prev_fetch_if_missing = repo->fetch_if_missing; struct rev_info revs; /* @@ -4097,9 +4098,9 @@ static void read_stdin_packs(enum stdin_packs_mode mode, int rev_list_unpacked) * walk is best-effort though we don't want to perform backfill fetches * for them. */ - fetch_if_missing = 0; + repo->fetch_if_missing = 0; - repo_init_revisions(the_repository, &revs, NULL); + repo_init_revisions(repo, &revs, NULL); /* * Use a revision walk to fill in the namehash of objects in the include * packs. To save time, we'll avoid traversing through objects that are @@ -4145,7 +4146,7 @@ static void read_stdin_packs(enum stdin_packs_mode mode, int rev_list_unpacked) trace2_data_intmax("pack-objects", the_repository, "stdin_packs_hints", stdin_packs_hints_nr); - fetch_if_missing = prev_fetch_if_missing; + repo->fetch_if_missing = prev_fetch_if_missing; } static void add_cruft_object_entry(const struct object_id *oid, enum object_type type, @@ -4455,9 +4456,11 @@ static void show_object__ma_allow_promisor(struct object *obj, const char *name, show_object(obj, name, data); } -static int option_parse_missing_action(const struct option *opt UNUSED, +static int option_parse_missing_action(const struct option *opt, const char *arg, int unset) { + struct repository *repo = opt->value; + assert(arg); assert(!unset); @@ -4469,14 +4472,14 @@ static int option_parse_missing_action(const struct option *opt UNUSED, if (!strcmp(arg, "allow-any")) { arg_missing_action = MA_ALLOW_ANY; - fetch_if_missing = 0; + repo->fetch_if_missing = 0; fn_show_object = show_object__ma_allow_any; return 0; } if (!strcmp(arg, "allow-promisor")) { arg_missing_action = MA_ALLOW_PROMISOR; - fetch_if_missing = 0; + repo->fetch_if_missing = 0; fn_show_object = show_object__ma_allow_promisor; return 0; } @@ -5118,7 +5121,7 @@ static int parse_stdin_packs_mode(const struct option *opt, const char *arg, int cmd_pack_objects(int argc, const char **argv, const char *prefix, - struct repository *repo UNUSED) + struct repository *repo) { int use_internal_rev_list = 0; int all_progress_implied = 0; @@ -5225,7 +5228,7 @@ int cmd_pack_objects(int argc, N_("write a bitmap index if possible"), WRITE_BITMAP_QUIET, PARSE_OPT_HIDDEN), OPT_PARSE_LIST_OBJECTS_FILTER(&filter_options), - OPT_CALLBACK_F(0, "missing", NULL, N_("action"), + OPT_CALLBACK_F(0, "missing", repo, N_("action"), N_("handling for missing objects"), PARSE_OPT_NONEG, option_parse_missing_action), OPT_BOOL(0, "exclude-promisor-objects", &exclude_promisor_objects, @@ -5345,7 +5348,7 @@ int cmd_pack_objects(int argc, exclude_promisor_objects_best_effort, "--exclude-promisor-objects-best-effort"); if (exclude_promisor_objects) { - fetch_if_missing = 0; + repo->fetch_if_missing = 0; /* --stdin-packs handles promisor objects separately. */ if (!stdin_packs) { @@ -5354,8 +5357,9 @@ int cmd_pack_objects(int argc, } } else if (exclude_promisor_objects_best_effort) { use_internal_rev_list = 1; - fetch_if_missing = 0; - option_parse_missing_action(NULL, "allow-any", 0); + arg_missing_action = MA_ALLOW_ANY; + repo->fetch_if_missing = 0; + fn_show_object = show_object__ma_allow_any; /* revs configured below */ } if (unpack_unreachable || keep_unreachable || pack_loose_unreachable) @@ -5471,7 +5475,7 @@ int cmd_pack_objects(int argc, progress_state = start_progress(the_repository, _("Enumerating objects"), 0); if (stdin_packs) { - read_stdin_packs(stdin_packs, rev_list_unpacked); + read_stdin_packs(repo, stdin_packs, rev_list_unpacked); } else if (cruft) { read_cruft_objects(); } else if (!use_internal_rev_list) { diff --git a/builtin/prune.c b/builtin/prune.c index 55635a891f..a7e4678d11 100644 --- a/builtin/prune.c +++ b/builtin/prune.c @@ -194,7 +194,7 @@ int cmd_prune(int argc, if (show_progress == -1) show_progress = isatty(2); if (exclude_promisor_objects) { - fetch_if_missing = 0; + repo->fetch_if_missing = 0; revs.exclude_promisor_objects = 1; } diff --git a/builtin/rev-list.c b/builtin/rev-list.c index 02818b81c6..6b596231ab 100644 --- a/builtin/rev-list.c +++ b/builtin/rev-list.c @@ -500,7 +500,8 @@ static void print_disk_usage(off_t size) strbuf_release(&sb); } -static inline int parse_missing_action_value(const char *value) +static inline int parse_missing_action_value(struct repository *repo, + const char *value) { if (!strcmp(value, "error")) { arg_missing_action = MA_ERROR; @@ -509,25 +510,25 @@ static inline int parse_missing_action_value(const char *value) if (!strcmp(value, "allow-any")) { arg_missing_action = MA_ALLOW_ANY; - fetch_if_missing = 0; + repo->fetch_if_missing = 0; return 1; } if (!strcmp(value, "print")) { arg_missing_action = MA_PRINT; - fetch_if_missing = 0; + repo->fetch_if_missing = 0; return 1; } if (!strcmp(value, "print-info")) { arg_missing_action = MA_PRINT_INFO; - fetch_if_missing = 0; + repo->fetch_if_missing = 0; return 1; } if (!strcmp(value, "allow-promisor")) { arg_missing_action = MA_ALLOW_PROMISOR; - fetch_if_missing = 0; + repo->fetch_if_missing = 0; return 1; } @@ -692,7 +693,7 @@ static void prepare_maximal_independent(struct rev_info *revs) int cmd_rev_list(int argc, const char **argv, const char *prefix, - struct repository *repo UNUSED) + struct repository *repo) { struct rev_info revs; struct rev_list_info info; @@ -745,10 +746,10 @@ int cmd_rev_list(int argc, for (i = 1; i < argc; i++) { const char *arg = argv[i]; if (!strcmp(arg, "--exclude-promisor-objects")) { - fetch_if_missing = 0; + repo->fetch_if_missing = 0; revs.exclude_promisor_objects = 1; } else if (skip_prefix(arg, "--missing=", &arg)) { - parse_missing_action_value(arg); + parse_missing_action_value(repo, arg); } else if (!strcmp(arg, "-z")) { line_term = '\0'; info_term = '\0'; diff --git a/common-init.c b/common-init.c index d26c9c1f20..4a3fa4d7be 100644 --- a/common-init.c +++ b/common-init.c @@ -47,7 +47,7 @@ static void setup_environment(void) update_ref_namespace(NAMESPACE_REPLACE, git_replace_ref_base); if (git_env_bool(NO_LAZY_FETCH_ENVIRONMENT, 0)) - fetch_if_missing = 0; + the_repository->fetch_if_missing = 0; } void init_git(const char **argv) diff --git a/git.c b/git.c index e5f1811b6b..f3ad3aad96 100644 --- a/git.c +++ b/git.c @@ -202,7 +202,7 @@ static int handle_options(const char ***argv, int *argc, int *envchanged) if (envchanged) *envchanged = 1; } else if (!strcmp(cmd, "--no-lazy-fetch")) { - fetch_if_missing = 0; + the_repository->fetch_if_missing = 0; setenv(NO_LAZY_FETCH_ENVIRONMENT, "1", 1); if (envchanged) *envchanged = 1; diff --git a/midx-write.c b/midx-write.c index 580724d21a..8537102254 100644 --- a/midx-write.c +++ b/midx-write.c @@ -865,7 +865,7 @@ static void find_commits_for_midx_bitmap(struct commit_stack *commits, * complain later that we don't have reachability closure (and fail * appropriately). */ - fetch_if_missing = 0; + ctx->repo->fetch_if_missing = 0; revs.exclude_promisor_objects = 1; if (prepare_revision_walk(&revs)) diff --git a/odb.c b/odb.c index dabd481f57..110326f063 100644 --- a/odb.c +++ b/odb.c @@ -528,8 +528,6 @@ void disable_obj_read_lock(void) pthread_mutex_destroy(&obj_read_mutex); } -int fetch_if_missing = 1; - static int register_all_submodule_sources(struct object_database *odb) { int ret = odb->submodule_source_paths.nr; @@ -595,7 +593,7 @@ static int do_oid_object_info_extended(struct object_database *odb, continue; /* Check if it is a missing object */ - if (fetch_if_missing && repo_has_promisor_remote(odb->repo) && + if (odb->repo->fetch_if_missing && repo_has_promisor_remote(odb->repo) && !already_retried && !(flags & OBJECT_INFO_SKIP_FETCH_OBJECT)) { promisor_remote_get_direct(odb->repo, real, 1); diff --git a/odb.h b/odb.h index cbc2f9ced4..d3a1e378b6 100644 --- a/odb.h +++ b/odb.h @@ -15,14 +15,6 @@ struct repository; struct strbuf; struct strvec; -/* - * Set this to 0 to prevent odb_read_object_info_extended() from fetching missing - * blobs. This has a difference only if extensions.partialClone is set. - * - * Its default value is 1. - */ -extern int fetch_if_missing; - /* * Compute the exact path an alternate is at and returns it. In case of * error NULL is returned and the human readable error is added to `err` diff --git a/repository.c b/repository.c index 651b0f6933..c2d954cf83 100644 --- a/repository.c +++ b/repository.c @@ -74,6 +74,7 @@ void initialize_repository(struct repository *repo) index_state_init(repo->index, repo); repo->check_deprecated_config = true; repo->bare_cfg = -1; + repo->fetch_if_missing = 1; repo_config_values_init(&repo->config_values_private_); /* diff --git a/repository.h b/repository.h index 3b467a2513..11f5c2ed10 100644 --- a/repository.h +++ b/repository.h @@ -184,6 +184,12 @@ struct repository { /* True if commit-graph has been disabled within this process. */ int commit_graph_disabled; + /* + * Controls whether the repository should lazily fetch missing + * objects from promisor remotes. Defaults to 1. + */ + int fetch_if_missing; + /* * Lazily-populated cache mapping hook event names to configured hooks. * NULL until first hook use. diff --git a/revision.c b/revision.c index 526bcf3fb5..40cb1cc828 100644 --- a/revision.c +++ b/revision.c @@ -2732,7 +2732,7 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg revs->ignore_missing = 1; } else if (opt && opt->allow_exclude_promisor_objects && !strcmp(arg, "--exclude-promisor-objects")) { - if (fetch_if_missing) + if (revs->repo->fetch_if_missing) BUG("exclude_promisor_objects can only be used when fetch_if_missing is 0"); revs->exclude_promisor_objects = 1; } else { -- 2.43.0