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>
This commit is contained in:
Junio C Hamano 2024-02-27 08:48:29 -08:00
parent b3806f7633
commit e6d5479e7a
5 changed files with 29 additions and 0 deletions

View File

@ -183,6 +183,8 @@ If you just want to run git as if it was started in `<path>` then use
Do not fetch missing objects from the promisor remote on Do not fetch missing objects from the promisor remote on
demand. Useful together with `git cat-file -e <object>` to demand. Useful together with `git cat-file -e <object>` to
see if the object is locally available. see if the object is locally available.
This is equivalent to setting the `GIT_NO_LAZY_FETCH`
environment variable to `1`.
--literal-pathspecs:: --literal-pathspecs::
Treat pathspecs literally (i.e. no globbing, no pathspec magic). Treat pathspecs literally (i.e. no globbing, no pathspec magic).
@ -900,6 +902,11 @@ for full details.
Setting this Boolean environment variable to true will cause Git to treat all Setting this Boolean environment variable to true will cause Git to treat all
pathspecs as case-insensitive. pathspecs as case-insensitive.
`GIT_NO_LAZY_FETCH`::
Setting this Boolean environment variable to true tells Git
not to lazily fetch missing objects from the promisor remote
on demand.
`GIT_REFLOG_ACTION`:: `GIT_REFLOG_ACTION`::
When a ref is updated, reflog entries are created to keep When a ref is updated, reflog entries are created to keep
track of the reason why the ref was updated (which is track of the reason why the ref was updated (which is

View File

@ -207,6 +207,9 @@ void setup_git_env(const char *git_dir)
shallow_file = getenv(GIT_SHALLOW_FILE_ENVIRONMENT); shallow_file = getenv(GIT_SHALLOW_FILE_ENVIRONMENT);
if (shallow_file) if (shallow_file)
set_alternate_shallow_file(the_repository, shallow_file, 0); set_alternate_shallow_file(the_repository, shallow_file, 0);
if (git_env_bool(NO_LAZY_FETCH_ENVIRONMENT, 0))
fetch_if_missing = 0;
} }
int is_bare_repository(void) int is_bare_repository(void)

View File

@ -36,6 +36,7 @@ const char *getenv_safe(struct strvec *argv, const char *name);
#define CEILING_DIRECTORIES_ENVIRONMENT "GIT_CEILING_DIRECTORIES" #define CEILING_DIRECTORIES_ENVIRONMENT "GIT_CEILING_DIRECTORIES"
#define NO_REPLACE_OBJECTS_ENVIRONMENT "GIT_NO_REPLACE_OBJECTS" #define NO_REPLACE_OBJECTS_ENVIRONMENT "GIT_NO_REPLACE_OBJECTS"
#define GIT_REPLACE_REF_BASE_ENVIRONMENT "GIT_REPLACE_REF_BASE" #define GIT_REPLACE_REF_BASE_ENVIRONMENT "GIT_REPLACE_REF_BASE"
#define NO_LAZY_FETCH_ENVIRONMENT "GIT_NO_LAZY_FETCH"
#define GITATTRIBUTES_FILE ".gitattributes" #define GITATTRIBUTES_FILE ".gitattributes"
#define INFOATTRIBUTES_FILE "info/attributes" #define INFOATTRIBUTES_FILE "info/attributes"
#define ATTRIBUTE_MACRO_PREFIX "[attr]" #define ATTRIBUTE_MACRO_PREFIX "[attr]"

3
git.c
View File

@ -189,6 +189,9 @@ static int handle_options(const char ***argv, int *argc, int *envchanged)
*envchanged = 1; *envchanged = 1;
} else if (!strcmp(cmd, "--no-lazy-fetch")) { } else if (!strcmp(cmd, "--no-lazy-fetch")) {
fetch_if_missing = 0; fetch_if_missing = 0;
setenv(NO_LAZY_FETCH_ENVIRONMENT, "1", 1);
if (envchanged)
*envchanged = 1;
} else if (!strcmp(cmd, "--no-replace-objects")) { } else if (!strcmp(cmd, "--no-replace-objects")) {
disable_replace_refs(); disable_replace_refs();
setenv(NO_REPLACE_OBJECTS_ENVIRONMENT, "1", 1); setenv(NO_REPLACE_OBJECTS_ENVIRONMENT, "1", 1);

View File

@ -665,6 +665,21 @@ test_expect_success 'lazy-fetch when accessing object not in the_repository' '
git -C partial.git rev-list --objects --missing=print HEAD >out && git -C partial.git rev-list --objects --missing=print HEAD >out &&
grep "[?]$FILE_HASH" out && grep "[?]$FILE_HASH" out &&
# The no-lazy-fetch mechanism prevents Git from fetching
test_must_fail env GIT_NO_LAZY_FETCH=1 \
git -C partial.git cat-file -e "$FILE_HASH" &&
# The same with command line option to "git"
test_must_fail git --no-lazy-fetch -C partial.git cat-file -e "$FILE_HASH" &&
# The same, forcing a subprocess via an alias
test_must_fail git --no-lazy-fetch -C partial.git \
-c alias.foo="!git cat-file" foo -e "$FILE_HASH" &&
# Sanity check that the file is still missing
git -C partial.git rev-list --objects --missing=print HEAD >out &&
grep "[?]$FILE_HASH" out &&
git -C full cat-file -s "$FILE_HASH" >expect && git -C full cat-file -s "$FILE_HASH" >expect &&
test-tool partial-clone object-info partial.git "$FILE_HASH" >actual && test-tool partial-clone object-info partial.git "$FILE_HASH" >actual &&
test_cmp expect actual && test_cmp expect actual &&