diff options
author | Junio C Hamano <gitster@pobox.com> | 2016-09-01 13:51:48 -0700 |
---|---|---|
committer | Junio C Hamano <gitster@pobox.com> | 2016-09-01 14:01:29 -0700 |
commit | 10f5c526561604ba9677dc27643b5c9bfad36458 (patch) | |
tree | 3ccbdde6d863c382f145ffaa3098fd3be1933250 | |
parent | e0c1ceafc5bece92d35773a75fff59497e1d9bd5 (diff) | |
download | git-10f5c526561604ba9677dc27643b5c9bfad36458.tar.gz git-10f5c526561604ba9677dc27643b5c9bfad36458.tar.xz |
submodule: avoid auto-discovery in prepare_submodule_repo_env()
The function is used to set up the environment variable used in a
subprocess we spawn in a submodule directory. The callers set up a
child_process structure, find the working tree path of one submodule
and set .dir field to it, and then use start_command() API to spawn
the subprocess like "status", "fetch", etc.
When this happens, we expect that the ".git" (either a directory or
a gitfile that points at the real location) in the current working
directory of the subprocess MUST be the repository for the submodule.
If this ".git" thing is a corrupt repository, however, because
prepare_submodule_repo_env() unsets GIT_DIR and GIT_WORK_TREE, the
subprocess will see ".git", thinks it is not a repository, and
attempt to find one by going up, likely to end up in finding the
repository of the superproject. In some codepaths, this will cause
a command run with the "--recurse-submodules" option to recurse
forever.
By exporting GIT_DIR=.git, disable the auto-discovery logic in the
subprocess, which would instead stop it and report an error.
The test illustrates existing problems in a few callsites of this
function. Without this fix, "git fetch --recurse-submodules", "git
status" and "git diff" keep recursing forever.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
-rw-r--r-- | submodule.c | 1 | ||||
-rwxr-xr-x | t/t5526-fetch-submodules.sh | 35 |
2 files changed, 36 insertions, 0 deletions
diff --git a/submodule.c b/submodule.c index 4532b11d6..2801fbbe1 100644 --- a/submodule.c +++ b/submodule.c @@ -1160,4 +1160,5 @@ void prepare_submodule_repo_env(struct argv_array *out) if (strcmp(*var, CONFIG_DATA_ENVIRONMENT)) argv_array_push(out, *var); } + argv_array_push(out, "GIT_DIR=.git"); } diff --git a/t/t5526-fetch-submodules.sh b/t/t5526-fetch-submodules.sh index 954d0e43f..f3b0a8d30 100755 --- a/t/t5526-fetch-submodules.sh +++ b/t/t5526-fetch-submodules.sh @@ -485,4 +485,39 @@ test_expect_success 'fetching submodules respects parallel settings' ' ) ' +test_expect_success 'fetching submodule into a broken repository' ' + # Prepare src and src/sub nested in it + git init src && + ( + cd src && + git init sub && + git -C sub commit --allow-empty -m "initial in sub" && + git submodule add -- ./sub sub && + git commit -m "initial in top" + ) && + + # Clone the old-fashoned way + git clone src dst && + git -C dst clone ../src/sub sub && + + # Make sure that old-fashoned layout is still supported + git -C dst status && + + # "diff" would find no change + git -C dst diff --exit-code && + + # Recursive-fetch works fine + git -C dst fetch --recurse-submodules && + + # Break the receiving submodule + rm -f dst/sub/.git/HEAD && + + # NOTE: without the fix the following tests will recurse forever! + # They should terminate with an error. + + test_must_fail git -C dst status && + test_must_fail git -C dst diff && + test_must_fail git -C dst fetch --recurse-submodules +' + test_done |