Skip to content

Commit b5a3627

Browse files
committed
Merge branch 'ar/submodule-add-config'
Large part of "git submodule add" gets rewritten in C. * ar/submodule-add-config: submodule--helper: introduce add-config subcommand
2 parents 67fc02b + a452128 commit b5a3627

File tree

3 files changed

+135
-27
lines changed

3 files changed

+135
-27
lines changed

builtin/submodule--helper.c

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2936,6 +2936,134 @@ static int add_clone(int argc, const char **argv, const char *prefix)
29362936
return 0;
29372937
}
29382938

2939+
static int config_submodule_in_gitmodules(const char *name, const char *var, const char *value)
2940+
{
2941+
char *key;
2942+
int ret;
2943+
2944+
if (!is_writing_gitmodules_ok())
2945+
die(_("please make sure that the .gitmodules file is in the working tree"));
2946+
2947+
key = xstrfmt("submodule.%s.%s", name, var);
2948+
ret = config_set_in_gitmodules_file_gently(key, value);
2949+
free(key);
2950+
2951+
return ret;
2952+
}
2953+
2954+
static void configure_added_submodule(struct add_data *add_data)
2955+
{
2956+
char *key;
2957+
char *val = NULL;
2958+
struct child_process add_submod = CHILD_PROCESS_INIT;
2959+
struct child_process add_gitmodules = CHILD_PROCESS_INIT;
2960+
2961+
key = xstrfmt("submodule.%s.url", add_data->sm_name);
2962+
git_config_set_gently(key, add_data->realrepo);
2963+
free(key);
2964+
2965+
add_submod.git_cmd = 1;
2966+
strvec_pushl(&add_submod.args, "add",
2967+
"--no-warn-embedded-repo", NULL);
2968+
if (add_data->force)
2969+
strvec_push(&add_submod.args, "--force");
2970+
strvec_pushl(&add_submod.args, "--", add_data->sm_path, NULL);
2971+
2972+
if (run_command(&add_submod))
2973+
die(_("Failed to add submodule '%s'"), add_data->sm_path);
2974+
2975+
if (config_submodule_in_gitmodules(add_data->sm_name, "path", add_data->sm_path) ||
2976+
config_submodule_in_gitmodules(add_data->sm_name, "url", add_data->repo))
2977+
die(_("Failed to register submodule '%s'"), add_data->sm_path);
2978+
2979+
if (add_data->branch) {
2980+
if (config_submodule_in_gitmodules(add_data->sm_name,
2981+
"branch", add_data->branch))
2982+
die(_("Failed to register submodule '%s'"), add_data->sm_path);
2983+
}
2984+
2985+
add_gitmodules.git_cmd = 1;
2986+
strvec_pushl(&add_gitmodules.args,
2987+
"add", "--force", "--", ".gitmodules", NULL);
2988+
2989+
if (run_command(&add_gitmodules))
2990+
die(_("Failed to register submodule '%s'"), add_data->sm_path);
2991+
2992+
/*
2993+
* NEEDSWORK: In a multi-working-tree world this needs to be
2994+
* set in the per-worktree config.
2995+
*/
2996+
/*
2997+
* NEEDSWORK: In the longer run, we need to get rid of this
2998+
* pattern of querying "submodule.active" before calling
2999+
* is_submodule_active(), since that function needs to find
3000+
* out the value of "submodule.active" again anyway.
3001+
*/
3002+
if (!git_config_get_string("submodule.active", &val) && val) {
3003+
/*
3004+
* If the submodule being added isn't already covered by the
3005+
* current configured pathspec, set the submodule's active flag
3006+
*/
3007+
if (!is_submodule_active(the_repository, add_data->sm_path)) {
3008+
key = xstrfmt("submodule.%s.active", add_data->sm_name);
3009+
git_config_set_gently(key, "true");
3010+
free(key);
3011+
}
3012+
} else {
3013+
key = xstrfmt("submodule.%s.active", add_data->sm_name);
3014+
git_config_set_gently(key, "true");
3015+
free(key);
3016+
}
3017+
}
3018+
3019+
static int add_config(int argc, const char **argv, const char *prefix)
3020+
{
3021+
int force = 0;
3022+
struct add_data add_data = ADD_DATA_INIT;
3023+
3024+
struct option options[] = {
3025+
OPT_STRING('b', "branch", &add_data.branch,
3026+
N_("branch"),
3027+
N_("branch of repository to store in "
3028+
"the submodule configuration")),
3029+
OPT_STRING(0, "url", &add_data.repo,
3030+
N_("string"),
3031+
N_("url to clone submodule from")),
3032+
OPT_STRING(0, "resolved-url", &add_data.realrepo,
3033+
N_("string"),
3034+
N_("url to clone the submodule from, after it has "
3035+
"been dereferenced relative to parent's url, "
3036+
"in the case where <url> is a relative url")),
3037+
OPT_STRING(0, "path", &add_data.sm_path,
3038+
N_("path"),
3039+
N_("where the new submodule will be cloned to")),
3040+
OPT_STRING(0, "name", &add_data.sm_name,
3041+
N_("string"),
3042+
N_("name of the new submodule")),
3043+
OPT__FORCE(&force, N_("allow adding an otherwise ignored submodule path"),
3044+
PARSE_OPT_NOCOMPLETE),
3045+
OPT_END()
3046+
};
3047+
3048+
const char *const usage[] = {
3049+
N_("git submodule--helper add-config "
3050+
"[--force|-f] [--branch|-b <branch>] "
3051+
"--url <url> --resolved-url <resolved-url> "
3052+
"--path <path> --name <name>"),
3053+
NULL
3054+
};
3055+
3056+
argc = parse_options(argc, argv, prefix, options, usage, 0);
3057+
3058+
if (argc)
3059+
usage_with_options(usage, options);
3060+
3061+
add_data.force = !!force;
3062+
configure_added_submodule(&add_data);
3063+
3064+
return 0;
3065+
}
3066+
29393067
#define SUPPORT_SUPER_PREFIX (1<<0)
29403068

29413069
struct cmd_struct {
@@ -2949,6 +3077,7 @@ static struct cmd_struct commands[] = {
29493077
{"name", module_name, 0},
29503078
{"clone", module_clone, 0},
29513079
{"add-clone", add_clone, 0},
3080+
{"add-config", add_config, 0},
29523081
{"update-module-mode", module_update_module_mode, 0},
29533082
{"update-clone", update_clone, 0},
29543083
{"ensure-core-worktree", ensure_core_worktree, 0},

git-submodule.sh

Lines changed: 1 addition & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -242,33 +242,7 @@ cmd_add()
242242
fi
243243

244244
git submodule--helper add-clone ${GIT_QUIET:+--quiet} ${force:+"--force"} ${progress:+"--progress"} ${branch:+--branch "$branch"} --prefix "$wt_prefix" --path "$sm_path" --name "$sm_name" --url "$realrepo" ${reference:+"$reference"} ${dissociate:+"--dissociate"} ${depth:+"$depth"} || exit
245-
git config submodule."$sm_name".url "$realrepo"
246-
247-
git add --no-warn-embedded-repo $force "$sm_path" ||
248-
die "fatal: $(eval_gettext "Failed to add submodule '\$sm_path'")"
249-
250-
git submodule--helper config submodule."$sm_name".path "$sm_path" &&
251-
git submodule--helper config submodule."$sm_name".url "$repo" &&
252-
if test -n "$branch"
253-
then
254-
git submodule--helper config submodule."$sm_name".branch "$branch"
255-
fi &&
256-
git add --force .gitmodules ||
257-
die "fatal: $(eval_gettext "Failed to register submodule '\$sm_path'")"
258-
259-
# NEEDSWORK: In a multi-working-tree world, this needs to be
260-
# set in the per-worktree config.
261-
if git config --get submodule.active >/dev/null
262-
then
263-
# If the submodule being adding isn't already covered by the
264-
# current configured pathspec, set the submodule's active flag
265-
if ! git submodule--helper is-active "$sm_path"
266-
then
267-
git config submodule."$sm_name".active "true"
268-
fi
269-
else
270-
git config submodule."$sm_name".active "true"
271-
fi
245+
git submodule--helper add-config ${force:+--force} ${branch:+--branch "$branch"} --url "$repo" --resolved-url "$realrepo" --path "$sm_path" --name "$sm_name"
272246
}
273247

274248
#

submodule.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,11 @@ int option_parse_recurse_submodules_worktree_updater(const struct option *opt,
260260
/*
261261
* Determine if a submodule has been initialized at a given 'path'
262262
*/
263+
/*
264+
* NEEDSWORK: Emit a warning if submodule.active exists, but is valueless,
265+
* ie, the config looks like: "[submodule] active\n".
266+
* Since that is an invalid pathspec, we should inform the user.
267+
*/
263268
int is_submodule_active(struct repository *repo, const char *path)
264269
{
265270
int ret = 0;

0 commit comments

Comments
 (0)