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:
commit
abb4824d13
1
Makefile
1
Makefile
@ -751,6 +751,7 @@ TEST_BUILTINS_OBJS += test-sigchain.o
|
||||
TEST_BUILTINS_OBJS += test-strcmp-offset.o
|
||||
TEST_BUILTINS_OBJS += test-string-list.o
|
||||
TEST_BUILTINS_OBJS += test-submodule-config.o
|
||||
TEST_BUILTINS_OBJS += test-submodule-nested-repo-config.o
|
||||
TEST_BUILTINS_OBJS += test-subprocess.o
|
||||
TEST_BUILTINS_OBJS += test-urlmatch-normalization.o
|
||||
TEST_BUILTINS_OBJS += test-wildmatch.o
|
||||
|
@ -422,11 +422,23 @@ static int grep_submodule(struct grep_opt *opt, struct repository *superproject,
|
||||
struct repository submodule;
|
||||
int hit;
|
||||
|
||||
if (!is_submodule_active(superproject, path))
|
||||
return 0;
|
||||
/*
|
||||
* NEEDSWORK: submodules functions need to be protected because they
|
||||
* access the object store via config_from_gitmodules(): the latter
|
||||
* uses get_oid() which, for now, relies on the global the_repository
|
||||
* object.
|
||||
*/
|
||||
grep_read_lock();
|
||||
|
||||
if (repo_submodule_init(&submodule, superproject, path))
|
||||
if (!is_submodule_active(superproject, path)) {
|
||||
grep_read_unlock();
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (repo_submodule_init(&submodule, superproject, path)) {
|
||||
grep_read_unlock();
|
||||
return 0;
|
||||
}
|
||||
|
||||
repo_read_gitmodules(&submodule);
|
||||
|
||||
@ -440,7 +452,6 @@ static int grep_submodule(struct grep_opt *opt, struct repository *superproject,
|
||||
* store is no longer global and instead is a member of the repository
|
||||
* object.
|
||||
*/
|
||||
grep_read_lock();
|
||||
add_to_alternates_memory(submodule.objects->objectdir);
|
||||
grep_read_unlock();
|
||||
|
||||
|
@ -2141,6 +2141,45 @@ static int check_name(int argc, const char **argv, const char *prefix)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int module_config(int argc, const char **argv, const char *prefix)
|
||||
{
|
||||
enum {
|
||||
CHECK_WRITEABLE = 1
|
||||
} command = 0;
|
||||
|
||||
struct option module_config_options[] = {
|
||||
OPT_CMDMODE(0, "check-writeable", &command,
|
||||
N_("check if it is safe to write to the .gitmodules file"),
|
||||
CHECK_WRITEABLE),
|
||||
OPT_END()
|
||||
};
|
||||
const char *const git_submodule_helper_usage[] = {
|
||||
N_("git submodule--helper config name [value]"),
|
||||
N_("git submodule--helper config --check-writeable"),
|
||||
NULL
|
||||
};
|
||||
|
||||
argc = parse_options(argc, argv, prefix, module_config_options,
|
||||
git_submodule_helper_usage, PARSE_OPT_KEEP_ARGV0);
|
||||
|
||||
if (argc == 1 && command == CHECK_WRITEABLE)
|
||||
return is_writing_gitmodules_ok() ? 0 : -1;
|
||||
|
||||
/* Equivalent to ACTION_GET in builtin/config.c */
|
||||
if (argc == 2)
|
||||
return print_config_from_gitmodules(the_repository, argv[1]);
|
||||
|
||||
/* Equivalent to ACTION_SET in builtin/config.c */
|
||||
if (argc == 3) {
|
||||
if (!is_writing_gitmodules_ok())
|
||||
die(_("please make sure that the .gitmodules file is in the working tree"));
|
||||
|
||||
return config_set_in_gitmodules_file_gently(argv[1], argv[2]);
|
||||
}
|
||||
|
||||
usage_with_options(git_submodule_helper_usage, module_config_options);
|
||||
}
|
||||
|
||||
#define SUPPORT_SUPER_PREFIX (1<<0)
|
||||
|
||||
struct cmd_struct {
|
||||
@ -2170,6 +2209,7 @@ static struct cmd_struct commands[] = {
|
||||
{"absorb-git-dirs", absorb_git_dirs, SUPPORT_SUPER_PREFIX},
|
||||
{"is-active", is_active, 0},
|
||||
{"check-name", check_name, 0},
|
||||
{"config", module_config, 0},
|
||||
};
|
||||
|
||||
int cmd_submodule__helper(int argc, const char **argv, const char *prefix)
|
||||
|
2
cache.h
2
cache.h
@ -486,6 +486,8 @@ static inline enum object_type object_type(unsigned int mode)
|
||||
#define INFOATTRIBUTES_FILE "info/attributes"
|
||||
#define ATTRIBUTE_MACRO_PREFIX "[attr]"
|
||||
#define GITMODULES_FILE ".gitmodules"
|
||||
#define GITMODULES_INDEX ":.gitmodules"
|
||||
#define GITMODULES_HEAD "HEAD:.gitmodules"
|
||||
#define GIT_NOTES_REF_ENVIRONMENT "GIT_NOTES_REF"
|
||||
#define GIT_NOTES_DEFAULT_REF "refs/notes/commits"
|
||||
#define GIT_NOTES_DISPLAY_REF_ENVIRONMENT "GIT_NOTES_DISPLAY_REF"
|
||||
|
@ -72,7 +72,7 @@ get_submodule_config () {
|
||||
value=$(git config submodule."$name"."$option")
|
||||
if test -z "$value"
|
||||
then
|
||||
value=$(git config -f .gitmodules submodule."$name"."$option")
|
||||
value=$(git submodule--helper config submodule."$name"."$option")
|
||||
fi
|
||||
printf '%s' "${value:-$default}"
|
||||
}
|
||||
@ -164,6 +164,11 @@ cmd_add()
|
||||
shift
|
||||
done
|
||||
|
||||
if ! git submodule--helper config --check-writeable >/dev/null 2>&1
|
||||
then
|
||||
die "$(eval_gettext "please make sure that the .gitmodules file is in the working tree")"
|
||||
fi
|
||||
|
||||
if test -n "$reference_path"
|
||||
then
|
||||
is_absolute_path "$reference_path" ||
|
||||
@ -288,11 +293,11 @@ or you are unsure what this means choose another name with the '--name' option."
|
||||
git add --no-warn-embedded-repo $force "$sm_path" ||
|
||||
die "$(eval_gettext "Failed to add submodule '\$sm_path'")"
|
||||
|
||||
git config -f .gitmodules submodule."$sm_name".path "$sm_path" &&
|
||||
git config -f .gitmodules submodule."$sm_name".url "$repo" &&
|
||||
git submodule--helper config submodule."$sm_name".path "$sm_path" &&
|
||||
git submodule--helper config submodule."$sm_name".url "$repo" &&
|
||||
if test -n "$branch"
|
||||
then
|
||||
git config -f .gitmodules submodule."$sm_name".branch "$branch"
|
||||
git submodule--helper config submodule."$sm_name".branch "$branch"
|
||||
fi &&
|
||||
git add --force .gitmodules ||
|
||||
die "$(eval_gettext "Failed to register submodule '\$sm_path'")"
|
||||
|
@ -1,4 +1,5 @@
|
||||
#include "cache.h"
|
||||
#include "dir.h"
|
||||
#include "repository.h"
|
||||
#include "config.h"
|
||||
#include "submodule-config.h"
|
||||
@ -613,8 +614,34 @@ static void submodule_cache_check_init(struct repository *repo)
|
||||
static void config_from_gitmodules(config_fn_t fn, struct repository *repo, void *data)
|
||||
{
|
||||
if (repo->worktree) {
|
||||
char *file = repo_worktree_path(repo, GITMODULES_FILE);
|
||||
git_config_from_file(fn, file, data);
|
||||
struct git_config_source config_source = { 0 };
|
||||
const struct config_options opts = { 0 };
|
||||
struct object_id oid;
|
||||
char *file;
|
||||
|
||||
file = repo_worktree_path(repo, GITMODULES_FILE);
|
||||
if (file_exists(file)) {
|
||||
config_source.file = file;
|
||||
} else if (repo->submodule_prefix) {
|
||||
/*
|
||||
* When get_oid and config_with_options, used below,
|
||||
* become able to work on a specific repository, this
|
||||
* warning branch can be removed.
|
||||
*/
|
||||
warning("nested submodules without %s in the working tree are not supported yet",
|
||||
GITMODULES_FILE);
|
||||
goto out;
|
||||
} else if (get_oid(GITMODULES_INDEX, &oid) >= 0) {
|
||||
config_source.blob = GITMODULES_INDEX;
|
||||
} else if (get_oid(GITMODULES_HEAD, &oid) >= 0) {
|
||||
config_source.blob = GITMODULES_HEAD;
|
||||
} else {
|
||||
goto out;
|
||||
}
|
||||
|
||||
config_with_options(fn, data, &config_source, &opts);
|
||||
|
||||
out:
|
||||
free(file);
|
||||
}
|
||||
}
|
||||
@ -692,6 +719,43 @@ void submodule_free(struct repository *r)
|
||||
submodule_cache_clear(r->submodule_cache);
|
||||
}
|
||||
|
||||
static int config_print_callback(const char *var, const char *value, void *cb_data)
|
||||
{
|
||||
char *wanted_key = cb_data;
|
||||
|
||||
if (!strcmp(wanted_key, var))
|
||||
printf("%s\n", value);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int print_config_from_gitmodules(struct repository *repo, const char *key)
|
||||
{
|
||||
int ret;
|
||||
char *store_key;
|
||||
|
||||
ret = git_config_parse_key(key, &store_key, NULL);
|
||||
if (ret < 0)
|
||||
return CONFIG_INVALID_KEY;
|
||||
|
||||
config_from_gitmodules(config_print_callback, repo, store_key);
|
||||
|
||||
free(store_key);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int config_set_in_gitmodules_file_gently(const char *key, const char *value)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = git_config_set_in_file_gently(GITMODULES_FILE, key, value);
|
||||
if (ret < 0)
|
||||
/* Maybe the user already did that, don't error out here */
|
||||
warning(_("Could not update .gitmodules entry %s"), key);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct fetch_config {
|
||||
int *max_children;
|
||||
int *recurse_submodules;
|
||||
|
@ -48,6 +48,8 @@ const struct submodule *submodule_from_path(struct repository *r,
|
||||
const struct object_id *commit_or_tree,
|
||||
const char *path);
|
||||
void submodule_free(struct repository *r);
|
||||
int print_config_from_gitmodules(struct repository *repo, const char *key);
|
||||
int config_set_in_gitmodules_file_gently(const char *key, const char *value);
|
||||
|
||||
/*
|
||||
* Returns 0 if the name is syntactically acceptable as a submodule "name"
|
||||
|
28
submodule.c
28
submodule.c
@ -51,6 +51,24 @@ int is_gitmodules_unmerged(const struct index_state *istate)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if the .gitmodules file is safe to write.
|
||||
*
|
||||
* Writing to the .gitmodules file requires that the file exists in the
|
||||
* working tree or, if it doesn't, that a brand new .gitmodules file is going
|
||||
* to be created (i.e. it's neither in the index nor in the current branch).
|
||||
*
|
||||
* It is not safe to write to .gitmodules if it's not in the working tree but
|
||||
* it is in the index or in the current branch, because writing new values
|
||||
* (and staging them) would blindly overwrite ALL the old content.
|
||||
*/
|
||||
int is_writing_gitmodules_ok(void)
|
||||
{
|
||||
struct object_id oid;
|
||||
return file_exists(GITMODULES_FILE) ||
|
||||
(get_oid(GITMODULES_INDEX, &oid) < 0 && get_oid(GITMODULES_HEAD, &oid) < 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if the .gitmodules file has unstaged modifications. This must be
|
||||
* checked before allowing modifications to the .gitmodules file with the
|
||||
@ -89,6 +107,7 @@ int update_path_in_gitmodules(const char *oldpath, const char *newpath)
|
||||
{
|
||||
struct strbuf entry = STRBUF_INIT;
|
||||
const struct submodule *submodule;
|
||||
int ret;
|
||||
|
||||
if (!file_exists(GITMODULES_FILE)) /* Do nothing without .gitmodules */
|
||||
return -1;
|
||||
@ -104,14 +123,9 @@ int update_path_in_gitmodules(const char *oldpath, const char *newpath)
|
||||
strbuf_addstr(&entry, "submodule.");
|
||||
strbuf_addstr(&entry, submodule->name);
|
||||
strbuf_addstr(&entry, ".path");
|
||||
if (git_config_set_in_file_gently(GITMODULES_FILE, entry.buf, newpath) < 0) {
|
||||
/* Maybe the user already did that, don't error out here */
|
||||
warning(_("Could not update .gitmodules entry %s"), entry.buf);
|
||||
strbuf_release(&entry);
|
||||
return -1;
|
||||
}
|
||||
ret = config_set_in_gitmodules_file_gently(entry.buf, newpath);
|
||||
strbuf_release(&entry);
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -40,6 +40,7 @@ struct submodule_update_strategy {
|
||||
#define SUBMODULE_UPDATE_STRATEGY_INIT {SM_UPDATE_UNSPECIFIED, NULL}
|
||||
|
||||
int is_gitmodules_unmerged(const struct index_state *istate);
|
||||
int is_writing_gitmodules_ok(void);
|
||||
int is_staging_gitmodules_ok(struct index_state *istate);
|
||||
int update_path_in_gitmodules(const char *oldpath, const char *newpath);
|
||||
int remove_path_from_gitmodules(const char *path);
|
||||
|
30
t/helper/test-submodule-nested-repo-config.c
Normal file
30
t/helper/test-submodule-nested-repo-config.c
Normal 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;
|
||||
}
|
@ -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 },
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
)
|
||||
'
|
||||
|
||||
|
122
t/t7418-submodule-sparse-gitmodules.sh
Executable file
122
t/t7418-submodule-sparse-gitmodules.sh
Executable 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
|
@ -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 &&
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user