repository: move fetch_if_missing into struct repository

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 <christian.couder@gmail.com>
Mentored-by: Ayush Chandekar <ayu.chandekar@gmail.com>
Mentored-by: Olamide Caleb Bello <belkid98@gmail.com>
Signed-off-by: Tian Yuchen <cat@malon.dev>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
next
Tian Yuchen 2026-08-15 14:47:46 +08:00 committed by Junio C Hamano
parent 745601a9a9
commit 508ec9837c
15 changed files with 51 additions and 49 deletions

View File

@ -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.
+

View File

@ -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];


View File

@ -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;


View File

@ -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();


View File

@ -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) {

View File

@ -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;
}


View File

@ -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';

View File

@ -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)

2
git.c
View File

@ -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;

View File

@ -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))

4
odb.c
View File

@ -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);

8
odb.h
View File

@ -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`

View File

@ -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_);

/*

View File

@ -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.

View File

@ -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 {