git: extend --no-lazy-fetch to work across subprocesses

Modeling after how the `--no-replace-objects` option is made usable across subprocess spawning (e.g., cURL based remote helpers are spawned as a separate process while running "git fetch"), allow the `--no-lazy-fetch` option to be passed across process boundaries. Do not model how the value of GIT_NO_REPLACE_OBJECTS environment variable is ignored, though. Just use the usual git_env_bool() to allow "export GIT_NO_LAZY_FETCH=0" and "unset GIT_NO_LAZY_FETCH" to be equivalents. Also do not model how the request is not propagated to subprocesses we spawn (e.g. "git clone --local" that spawns a new process to work in the origin repository, while the original one working in the newly created one) by the "--no-replace-objects" option, as this "do not lazily fetch from the promisor" is more about a per-request debugging aid, not "this repository's promisor should not be relied upon" property specific to a repository. Signed-off-by: Junio C Hamano <gitster@pobox.com>

Junio C Hamano committed Feb 27, 2024 at 08:48 UTC e6d5479e7ac301ae8d11daa3d8ef748e891c91c3
5 files changed +29
Documentation/git.txt
+7
@@ -183,6 +183,8 @@ If you just want to run git as if it was started in `<path>` then use
183 Do not fetch missing objects from the promisor remote on
184 demand. Useful together with `git cat-file -e <object>` to
185 see if the object is locally available.
186 + This is equivalent to setting the `GIT_NO_LAZY_FETCH`
187 + environment variable to `1`.
188
189 --literal-pathspecs::
190 Treat pathspecs literally (i.e. no globbing, no pathspec magic).
@@ -900,6 +902,11 @@ for full details.
902 Setting this Boolean environment variable to true will cause Git to treat all
903 pathspecs as case-insensitive.
904
905 +`GIT_NO_LAZY_FETCH`::
906 + Setting this Boolean environment variable to true tells Git
907 + not to lazily fetch missing objects from the promisor remote
908 + on demand.
909 +
910 `GIT_REFLOG_ACTION`::
911 When a ref is updated, reflog entries are created to keep
912 track of the reason why the ref was updated (which is
environment.c
+3
@@ -207,6 +207,9 @@ void setup_git_env(const char *git_dir)
207 shallow_file = getenv(GIT_SHALLOW_FILE_ENVIRONMENT);
208 if (shallow_file)
209 set_alternate_shallow_file(the_repository, shallow_file, 0);
210 +
211 + if (git_env_bool(NO_LAZY_FETCH_ENVIRONMENT, 0))
212 + fetch_if_missing = 0;
213 }
214
215 int is_bare_repository(void)
environment.h
+1
@@ -36,6 +36,7 @@ const char *getenv_safe(struct strvec *argv, const char *name);
36 #define CEILING_DIRECTORIES_ENVIRONMENT "GIT_CEILING_DIRECTORIES"
37 #define NO_REPLACE_OBJECTS_ENVIRONMENT "GIT_NO_REPLACE_OBJECTS"
38 #define GIT_REPLACE_REF_BASE_ENVIRONMENT "GIT_REPLACE_REF_BASE"
39 +#define NO_LAZY_FETCH_ENVIRONMENT "GIT_NO_LAZY_FETCH"
40 #define GITATTRIBUTES_FILE ".gitattributes"
41 #define INFOATTRIBUTES_FILE "info/attributes"
42 #define ATTRIBUTE_MACRO_PREFIX "[attr]"
git.c
+3
@@ -189,6 +189,9 @@ static int handle_options(const char ***argv, int *argc, int *envchanged)
189 *envchanged = 1;
190 } else if (!strcmp(cmd, "--no-lazy-fetch")) {
191 fetch_if_missing = 0;
192 + setenv(NO_LAZY_FETCH_ENVIRONMENT, "1", 1);
193 + if (envchanged)
194 + *envchanged = 1;
195 } else if (!strcmp(cmd, "--no-replace-objects")) {
196 disable_replace_refs();
197 setenv(NO_REPLACE_OBJECTS_ENVIRONMENT, "1", 1);
t/t0410-partial-clone.sh
+15
@@ -665,6 +665,21 @@ test_expect_success 'lazy-fetch when accessing object not in the_repository' '
665 git -C partial.git rev-list --objects --missing=print HEAD >out &&
666 grep "[?]$FILE_HASH" out &&
667
668 + # The no-lazy-fetch mechanism prevents Git from fetching
669 + test_must_fail env GIT_NO_LAZY_FETCH=1 \
670 + git -C partial.git cat-file -e "$FILE_HASH" &&
671 +
672 + # The same with command line option to "git"
673 + test_must_fail git --no-lazy-fetch -C partial.git cat-file -e "$FILE_HASH" &&
674 +
675 + # The same, forcing a subprocess via an alias
676 + test_must_fail git --no-lazy-fetch -C partial.git \
677 + -c alias.foo="!git cat-file" foo -e "$FILE_HASH" &&
678 +
679 + # Sanity check that the file is still missing
680 + git -C partial.git rev-list --objects --missing=print HEAD >out &&
681 + grep "[?]$FILE_HASH" out &&
682 +
683 git -C full cat-file -s "$FILE_HASH" >expect &&
684 test-tool partial-clone object-info partial.git "$FILE_HASH" >actual &&
685 test_cmp expect actual &&