Git development
 help / color / mirror / Atom feed
From: Tian Yuchen <cat@malon.dev>
To: git@vger.kernel.org
Cc: ps@pks.im, five231003@gmail.com, hariom18599@gmail.com,
	Christian Couder <christian.couder@gmail.com>,
	Ayush Chandekar <ayu.chandekar@gmail.com>,
	Olamide Caleb Bello <belkid98@gmail.com>
Subject: Re: [PATCH v2] repository: move fetch_if_missing into struct repository
Date: Sat, 1 Aug 2026 23:53:24 +0800	[thread overview]
Message-ID: <e9e36105-7a77-4e5f-8d75-7b160e1d7095@malon.dev> (raw)
In-Reply-To: <20260716072954.582235-1-cat@malon.dev>

On 7/16/26 15:29, Tian Yuchen wrote:
> 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.
> 
> Note that in builtin/fsck.c and builtin/index-pack.c, when running
> related commands with the '-h' parameter, the 'repo' pointer is not
> passed in. To prevent null pointer dereferences, we defer
> operations on the repo until after parameter parsing is complete.
> 
> 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>
> ---
> 
> Change since V1:
> 
> - Following Patrick's advice, use the_repository whenever possible
>    without re-introducing #define USE_THE_REPOSITORY_VARIABLE.
> 
>   Documentation/technical/partial-clone.adoc |  2 +-
>   builtin/fetch-pack.c                       |  2 +-
>   builtin/fsck.c                             |  6 +++---
>   builtin/index-pack.c                       |  7 ++++---
>   builtin/pack-objects.c                     | 14 +++++++-------
>   builtin/prune.c                            |  2 +-
>   builtin/rev-list.c                         | 10 +++++-----
>   git.c                                      |  2 +-
>   midx-write.c                               |  2 +-
>   odb.c                                      |  4 +---
>   odb.h                                      |  8 --------
>   repository.c                               |  1 +
>   repository.h                               |  6 ++++++
>   revision.c                                 |  2 +-
>   setup.c                                    |  2 +-
>   15 files changed, 34 insertions(+), 36 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..c5edd7b80f 100644
> --- a/builtin/fetch-pack.c
> +++ b/builtin/fetch-pack.c
> @@ -67,7 +67,7 @@ int cmd_fetch_pack(int argc,
>   	struct packet_reader reader;
>   	enum protocol_version version;
>   
> -	fetch_if_missing = 0;
> +	the_repository->fetch_if_missing = 0;
>   
>   	packet_trace_identity("fetch-pack");
>   
> diff --git a/builtin/fsck.c b/builtin/fsck.c
> index 248f8ff5a0..aa31c69486 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 0793dc595c..74f9694662 100644
> --- a/builtin/index-pack.c
> +++ b/builtin/index-pack.c
> @@ -1898,15 +1898,16 @@ 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);
> +	if (repo)
> +		the_repository->fetch_if_missing = 0;
>   
>   	disable_replace_refs();
>   
> diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c
> index 8a1709a1ab..c6536b1f65 100644
> --- a/builtin/pack-objects.c
> +++ b/builtin/pack-objects.c
> @@ -4059,7 +4059,7 @@ static void add_unreachable_loose_objects(struct rev_info *revs);
>   
>   static void read_stdin_packs(enum stdin_packs_mode mode, int rev_list_unpacked)
>   {
> -	int prev_fetch_if_missing = fetch_if_missing;
> +	int prev_fetch_if_missing = the_repository->fetch_if_missing;
>   	struct rev_info revs;
>   
>   	/*
> @@ -4067,7 +4067,7 @@ 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;
> +	the_repository->fetch_if_missing = 0;
>   
>   	repo_init_revisions(the_repository, &revs, NULL);
>   	/*
> @@ -4115,7 +4115,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;
> +	the_repository->fetch_if_missing = prev_fetch_if_missing;
>   }
>   
>   static void add_cruft_object_entry(const struct object_id *oid, enum object_type type,
> @@ -4451,14 +4451,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;
> +		the_repository->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;
> +		the_repository->fetch_if_missing = 0;
>   		fn_show_object = show_object__ma_allow_promisor;
>   		return 0;
>   	}
> @@ -5247,7 +5247,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;
> +		the_repository->fetch_if_missing = 0;
>   
>   		/* --stdin-packs handles promisor objects separately. */
>   		if (!stdin_packs) {
> @@ -5256,7 +5256,7 @@ int cmd_pack_objects(int argc,
>   		}
>   	} else if (exclude_promisor_objects_best_effort) {
>   		use_internal_rev_list = 1;
> -		fetch_if_missing = 0;
> +		the_repository->fetch_if_missing = 0;
>   		option_parse_missing_action(NULL, "allow-any", 0);
>   		/* revs configured below */
>   	}
> 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 8f63003709..a6a0c5559e 100644
> --- a/builtin/rev-list.c
> +++ b/builtin/rev-list.c
> @@ -509,25 +509,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;
> +		the_repository->fetch_if_missing = 0;
>   		return 1;
>   	}
>   
>   	if (!strcmp(value, "print")) {
>   		arg_missing_action = MA_PRINT;
> -		fetch_if_missing = 0;
> +		the_repository->fetch_if_missing = 0;
>   		return 1;
>   	}
>   
>   	if (!strcmp(value, "print-info")) {
>   		arg_missing_action = MA_PRINT_INFO;
> -		fetch_if_missing = 0;
> +		the_repository->fetch_if_missing = 0;
>   		return 1;
>   	}
>   
>   	if (!strcmp(value, "allow-promisor")) {
>   		arg_missing_action = MA_ALLOW_PROMISOR;
> -		fetch_if_missing = 0;
> +		the_repository->fetch_if_missing = 0;
>   		return 1;
>   	}
>   
> @@ -745,7 +745,7 @@ 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;
> +			the_repository->fetch_if_missing = 0;
>   			revs.exclude_promisor_objects = 1;
>   		} else if (skip_prefix(arg, "--missing=", &arg)) {
>   			parse_missing_action_value(arg);
> diff --git a/git.c b/git.c
> index 36f08891ef..315d2e160e 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 19e1cd10b7..e7313c9d2c 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 965ef68e4e..664256e1a4 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 0030467a52..1dca583fcb 100644
> --- a/odb.h
> +++ b/odb.h
> @@ -14,14 +14,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 187dd471c4..b959f7a028 100644
> --- a/repository.c
> +++ b/repository.c
> @@ -73,6 +73,7 @@ void initialize_repository(struct repository *repo)
>   	ALLOC_ARRAY(repo->index, 1);
>   	index_state_init(repo->index, repo);
>   	repo->check_deprecated_config = true;
> +	repo->fetch_if_missing = 1;
>   	repo_config_values_init(&repo->config_values_private_);
>   
>   	/*
> diff --git a/repository.h b/repository.h
> index 36e2db2633..e8bd6ef0e7 100644
> --- a/repository.h
> +++ b/repository.h
> @@ -169,6 +169,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 e91d7e1f11..5f70aa81e6 100644
> --- a/revision.c
> +++ b/revision.c
> @@ -2714,7 +2714,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 (the_repository->fetch_if_missing)
>   			BUG("exclude_promisor_objects can only be used when fetch_if_missing is 0");
>   		revs->exclude_promisor_objects = 1;
>   	} else {
> diff --git a/setup.c b/setup.c
> index b4652651df..ce2a80ac31 100644
> --- a/setup.c
> +++ b/setup.c
> @@ -1064,7 +1064,7 @@ static void setup_git_env_internal(struct repository *repo,
>   		set_alternate_shallow_file(repo, shallow_file, 0);
>   
>   	if (git_env_bool(NO_LAZY_FETCH_ENVIRONMENT, 0))
> -		fetch_if_missing = 0;
> +		the_repository->fetch_if_missing = 0;
>   }
>   
>   static void set_git_dir_1(struct repository *repo, const char *path)

What are everyone's thoughts on this patch? It seems like it's been a 
while since it received responses. ^^

Regards, yuchen

  reply	other threads:[~2026-08-01 15:53 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-07-15  1:18 [PATCH v1] repository: move fetch_if_missing into struct repository Tian Yuchen
2026-07-15  3:27 ` Junio C Hamano
2026-07-15  4:58   ` Tian Yuchen
2026-07-15  6:35 ` Patrick Steinhardt
2026-07-16  7:06   ` Tian Yuchen
2026-07-16 15:28   ` Junio C Hamano
2026-07-16  7:29 ` [PATCH v2] " Tian Yuchen
2026-08-01 15:53   ` Tian Yuchen [this message]
2026-08-04  8:24   ` Patrick Steinhardt
2026-08-04 17:38     ` Junio C Hamano
2026-08-05 12:34       ` Tian Yuchen
2026-08-05 12:10     ` Tian Yuchen
2026-08-07  9:41   ` [PATCH v3] " Tian Yuchen
2026-08-07 17:03     ` Junio C Hamano

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=e9e36105-7a77-4e5f-8d75-7b160e1d7095@malon.dev \
    --to=cat@malon.dev \
    --cc=ayu.chandekar@gmail.com \
    --cc=belkid98@gmail.com \
    --cc=christian.couder@gmail.com \
    --cc=five231003@gmail.com \
    --cc=git@vger.kernel.org \
    --cc=hariom18599@gmail.com \
    --cc=ps@pks.im \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox