Merge branch 'ao/submodule-wo-gitmodules-checked-out'

The submodule support has been updated to read from the blob at
HEAD:.gitmodules when the .gitmodules file is missing from the
working tree.

* ao/submodule-wo-gitmodules-checked-out:
  t/helper: add test-submodule-nested-repo-config
  submodule: support reading .gitmodules when it's not in the working tree
  submodule: add a helper to check if it is safe to write to .gitmodules
  t7506: clean up .gitmodules properly before setting up new scenario
  submodule: use the 'submodule--helper config' command
  submodule--helper: add a new 'config' subcommand
  t7411: be nicer to future tests and really clean things up
  t7411: merge tests 5 and 6
  submodule: factor out a config_set_in_gitmodules_file_gently function
  submodule: add a print_config_from_gitmodules() helper
This commit is contained in:
Junio C Hamano
2018-11-13 22:37:22 +09:00
16 changed files with 455 additions and 33 deletions

View File

@ -0,0 +1,30 @@
#include "test-tool.h"
#include "submodule-config.h"
static void die_usage(int argc, const char **argv, const char *msg)
{
fprintf(stderr, "%s\n", msg);
fprintf(stderr, "Usage: %s <submodulepath> <config name>\n", argv[0]);
exit(1);
}
int cmd__submodule_nested_repo_config(int argc, const char **argv)
{
struct repository submodule;
if (argc < 3)
die_usage(argc, argv, "Wrong number of arguments.");
setup_git_directory();
if (repo_submodule_init(&submodule, the_repository, argv[1])) {
die_usage(argc, argv, "Submodule not found.");
}
/* Read the config of _child_ submodules. */
print_config_from_gitmodules(&submodule, argv[2]);
submodule_free(the_repository);
return 0;
}

View File

@ -46,6 +46,7 @@ static struct test_cmd cmds[] = {
{ "strcmp-offset", cmd__strcmp_offset },
{ "string-list", cmd__string_list },
{ "submodule-config", cmd__submodule_config },
{ "submodule-nested-repo-config", cmd__submodule_nested_repo_config },
{ "subprocess", cmd__subprocess },
{ "urlmatch-normalization", cmd__urlmatch_normalization },
{ "wildmatch", cmd__wildmatch },

View File

@ -42,6 +42,7 @@ int cmd__sigchain(int argc, const char **argv);
int cmd__strcmp_offset(int argc, const char **argv);
int cmd__string_list(int argc, const char **argv);
int cmd__submodule_config(int argc, const char **argv);
int cmd__submodule_nested_repo_config(int argc, const char **argv);
int cmd__subprocess(int argc, const char **argv);
int cmd__urlmatch_normalization(int argc, const char **argv);
int cmd__wildmatch(int argc, const char **argv);

View File

@ -82,29 +82,23 @@ Submodule name: 'a' for path 'b'
Submodule name: 'submodule' for path 'submodule'
EOF
test_expect_success 'error in one submodule config lets continue' '
test_expect_success 'error in history of one submodule config lets continue, stderr message contains blob ref' '
ORIG=$(git -C super rev-parse HEAD) &&
test_when_finished "git -C super reset --hard $ORIG" &&
(cd super &&
cp .gitmodules .gitmodules.bak &&
echo " value = \"" >>.gitmodules &&
git add .gitmodules &&
mv .gitmodules.bak .gitmodules &&
git commit -m "add error" &&
test-tool submodule-config \
HEAD b \
HEAD submodule \
>actual &&
test_cmp expect_error actual
)
'
test_expect_success 'error message contains blob reference' '
(cd super &&
sha1=$(git rev-parse HEAD) &&
test-tool submodule-config \
HEAD b \
HEAD submodule \
2>actual_err &&
test_i18ngrep "submodule-blob $sha1:.gitmodules" actual_err >/dev/null
>actual \
2>actual_stderr &&
test_cmp expect_error actual &&
test_i18ngrep "submodule-blob $sha1:.gitmodules" actual_stderr >/dev/null
)
'
@ -123,6 +117,8 @@ test_expect_success 'using different treeishs works' '
'
test_expect_success 'error in history in fetchrecursesubmodule lets continue' '
ORIG=$(git -C super rev-parse HEAD) &&
test_when_finished "git -C super reset --hard $ORIG" &&
(cd super &&
git config -f .gitmodules \
submodule.submodule.fetchrecursesubmodules blabla &&
@ -134,8 +130,123 @@ test_expect_success 'error in history in fetchrecursesubmodule lets continue' '
HEAD b \
HEAD submodule \
>actual &&
test_cmp expect_error actual &&
git reset --hard HEAD^
test_cmp expect_error actual
)
'
test_expect_success 'reading submodules config from the working tree with "submodule--helper config"' '
(cd super &&
echo "../submodule" >expect &&
git submodule--helper config submodule.submodule.url >actual &&
test_cmp expect actual
)
'
test_expect_success 'writing submodules config with "submodule--helper config"' '
(cd super &&
echo "new_url" >expect &&
git submodule--helper config submodule.submodule.url "new_url" &&
git submodule--helper config submodule.submodule.url >actual &&
test_cmp expect actual
)
'
test_expect_success 'overwriting unstaged submodules config with "submodule--helper config"' '
test_when_finished "git -C super checkout .gitmodules" &&
(cd super &&
echo "newer_url" >expect &&
git submodule--helper config submodule.submodule.url "newer_url" &&
git submodule--helper config submodule.submodule.url >actual &&
test_cmp expect actual
)
'
test_expect_success 'writeable .gitmodules when it is in the working tree' '
git -C super submodule--helper config --check-writeable
'
test_expect_success 'writeable .gitmodules when it is nowhere in the repository' '
ORIG=$(git -C super rev-parse HEAD) &&
test_when_finished "git -C super reset --hard $ORIG" &&
(cd super &&
git rm .gitmodules &&
git commit -m "remove .gitmodules from the current branch" &&
git submodule--helper config --check-writeable
)
'
test_expect_success 'non-writeable .gitmodules when it is in the index but not in the working tree' '
test_when_finished "git -C super checkout .gitmodules" &&
(cd super &&
rm -f .gitmodules &&
test_must_fail git submodule--helper config --check-writeable
)
'
test_expect_success 'non-writeable .gitmodules when it is in the current branch but not in the index' '
ORIG=$(git -C super rev-parse HEAD) &&
test_when_finished "git -C super reset --hard $ORIG" &&
(cd super &&
git rm .gitmodules &&
test_must_fail git submodule--helper config --check-writeable
)
'
test_expect_success 'reading submodules config from the index when .gitmodules is not in the working tree' '
ORIG=$(git -C super rev-parse HEAD) &&
test_when_finished "git -C super reset --hard $ORIG" &&
(cd super &&
git submodule--helper config submodule.submodule.url "staged_url" &&
git add .gitmodules &&
rm -f .gitmodules &&
echo "staged_url" >expect &&
git submodule--helper config submodule.submodule.url >actual &&
test_cmp expect actual
)
'
test_expect_success 'reading submodules config from the current branch when .gitmodules is not in the index' '
ORIG=$(git -C super rev-parse HEAD) &&
test_when_finished "git -C super reset --hard $ORIG" &&
(cd super &&
git rm .gitmodules &&
echo "../submodule" >expect &&
git submodule--helper config submodule.submodule.url >actual &&
test_cmp expect actual
)
'
test_expect_success 'reading nested submodules config' '
(cd super &&
git init submodule/nested_submodule &&
echo "a" >submodule/nested_submodule/a &&
git -C submodule/nested_submodule add a &&
git -C submodule/nested_submodule commit -m "add a" &&
git -C submodule submodule add ./nested_submodule &&
git -C submodule add nested_submodule &&
git -C submodule commit -m "added nested_submodule" &&
git add submodule &&
git commit -m "updated submodule" &&
echo "./nested_submodule" >expect &&
test-tool submodule-nested-repo-config \
submodule submodule.nested_submodule.url >actual &&
test_cmp expect actual
)
'
# When this test eventually passes, before turning it into
# test_expect_success, remember to replace the test_i18ngrep below with
# a "test_must_be_empty warning" to be sure that the warning is actually
# removed from the code.
test_expect_failure 'reading nested submodules config when .gitmodules is not in the working tree' '
test_when_finished "git -C super/submodule checkout .gitmodules" &&
(cd super &&
echo "./nested_submodule" >expect &&
rm submodule/.gitmodules &&
test-tool submodule-nested-repo-config \
submodule submodule.nested_submodule.url >actual 2>warning &&
test_i18ngrep "nested submodules without %s in the working tree are not supported yet" warning &&
test_cmp expect actual
)
'

View File

@ -0,0 +1,122 @@
#!/bin/sh
#
# Copyright (C) 2018 Antonio Ospite <ao2@ao2.it>
#
test_description='Test reading/writing .gitmodules when not in the working tree
This test verifies that, when .gitmodules is in the current branch but is not
in the working tree reading from it still works but writing to it does not.
The test setup uses a sparse checkout, however the same scenario can be set up
also by committing .gitmodules and then just removing it from the filesystem.
'
. ./test-lib.sh
test_expect_success 'sparse checkout setup which hides .gitmodules' '
git init upstream &&
git init submodule &&
(cd submodule &&
echo file >file &&
git add file &&
test_tick &&
git commit -m "Add file"
) &&
(cd upstream &&
git submodule add ../submodule &&
test_tick &&
git commit -m "Add submodule"
) &&
git clone upstream super &&
(cd super &&
cat >.git/info/sparse-checkout <<-\EOF &&
/*
!/.gitmodules
EOF
git config core.sparsecheckout true &&
git read-tree -m -u HEAD &&
test_path_is_missing .gitmodules
)
'
test_expect_success 'reading gitmodules config file when it is not checked out' '
echo "../submodule" >expect &&
git -C super submodule--helper config submodule.submodule.url >actual &&
test_cmp expect actual
'
test_expect_success 'not writing gitmodules config file when it is not checked out' '
test_must_fail git -C super submodule--helper config submodule.submodule.url newurl &&
test_path_is_missing super/.gitmodules
'
test_expect_success 'initialising submodule when the gitmodules config is not checked out' '
test_must_fail git -C super config submodule.submodule.url &&
git -C super submodule init &&
git -C super config submodule.submodule.url >actual &&
echo "$(pwd)/submodule" >expect &&
test_cmp expect actual
'
test_expect_success 'updating submodule when the gitmodules config is not checked out' '
test_path_is_missing super/submodule/file &&
git -C super submodule update &&
test_cmp submodule/file super/submodule/file
'
ORIG_SUBMODULE=$(git -C submodule rev-parse HEAD)
ORIG_UPSTREAM=$(git -C upstream rev-parse HEAD)
ORIG_SUPER=$(git -C super rev-parse HEAD)
test_expect_success 're-updating submodule when the gitmodules config is not checked out' '
test_when_finished "git -C submodule reset --hard $ORIG_SUBMODULE;
git -C upstream reset --hard $ORIG_UPSTREAM;
git -C super reset --hard $ORIG_SUPER;
git -C upstream submodule update --remote;
git -C super pull;
git -C super submodule update --remote" &&
(cd submodule &&
echo file2 >file2 &&
git add file2 &&
test_tick &&
git commit -m "Add file2 to submodule"
) &&
(cd upstream &&
git submodule update --remote &&
git add submodule &&
test_tick &&
git commit -m "Update submodule"
) &&
git -C super pull &&
# The --for-status options reads the gitmodules config
git -C super submodule summary --for-status >actual &&
rev1=$(git -C submodule rev-parse --short HEAD) &&
rev2=$(git -C submodule rev-parse --short HEAD^) &&
cat >expect <<-EOF &&
* submodule ${rev1}...${rev2} (1):
< Add file2 to submodule
EOF
test_cmp expect actual &&
# Test that the update actually succeeds
test_path_is_missing super/submodule/file2 &&
git -C super submodule update &&
test_cmp submodule/file2 super/submodule/file2 &&
git -C super status --short >output &&
test_must_be_empty output
'
test_expect_success 'not adding submodules when the gitmodules config is not checked out' '
git clone submodule new_submodule &&
test_must_fail git -C super submodule add ../new_submodule &&
test_path_is_missing .gitmodules
'
# This test checks that the previous "git submodule add" did not leave the
# repository in a spurious state when it failed.
test_expect_success 'init submodule still works even after the previous add failed' '
git -C super submodule init
'
test_done

View File

@ -325,7 +325,8 @@ test_expect_success 'setup superproject with untracked file in nested submodule'
(
cd super &&
git clean -dfx &&
rm .gitmodules &&
git rm .gitmodules &&
git commit -m "remove .gitmodules" &&
git submodule add -f ./sub1 &&
git submodule add -f ./sub2 &&
git submodule add -f ./sub1 sub3 &&

View File

@ -380,4 +380,20 @@ test_expect_success 'grep --recurse-submodules should pass the pattern type alon
fi
'
# Recursing down into nested submodules which do not have .gitmodules in their
# working tree does not work yet. This is because config_from_gitmodules()
# uses get_oid() and the latter is still not able to get objects from an
# arbitrary repository (the nested submodule, in this case).
test_expect_failure 'grep --recurse-submodules with submodules without .gitmodules in the working tree' '
test_when_finished "git -C submodule checkout .gitmodules" &&
rm submodule/.gitmodules &&
git grep --recurse-submodules -e "(.|.)[\d]" >actual &&
cat >expect <<-\EOF &&
a:(1|2)d(3|4)
submodule/a:(1|2)d(3|4)
submodule/sub/a:(1|2)d(3|4)
EOF
test_cmp expect actual
'
test_done