summaryrefslogtreecommitdiff
path: root/builtin/submodule--helper.c
diff options
context:
space:
mode:
Diffstat (limited to 'builtin/submodule--helper.c')
-rw-r--r--builtin/submodule--helper.c145
1 files changed, 105 insertions, 40 deletions
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 40844870cf..13da32d3b7 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -1,3 +1,4 @@
+#define USE_THE_INDEX_COMPATIBILITY_MACROS
#include "builtin.h"
#include "repository.h"
#include "cache.h"
@@ -347,7 +348,7 @@ static int module_list_compute(int argc, const char **argv,
i++;
}
- if (ps_matched && report_path_error(ps_matched, pathspec, prefix))
+ if (ps_matched && report_path_error(ps_matched, pathspec))
result = -1;
free(ps_matched);
@@ -565,12 +566,12 @@ static int module_foreach(int argc, const char **argv, const char *prefix)
};
const char *const git_submodule_helper_usage[] = {
- N_("git submodule--helper foreach [--quiet] [--recursive] <command>"),
+ N_("git submodule--helper foreach [--quiet] [--recursive] [--] <command>"),
NULL
};
argc = parse_options(argc, argv, prefix, module_foreach_options,
- git_submodule_helper_usage, PARSE_OPT_KEEP_UNKNOWN);
+ git_submodule_helper_usage, 0);
if (module_list_compute(0, NULL, prefix, &pathspec, &list) < 0)
return 1;
@@ -584,6 +585,26 @@ static int module_foreach(int argc, const char **argv, const char *prefix)
return 0;
}
+static char *compute_submodule_clone_url(const char *rel_url)
+{
+ char *remoteurl, *relurl;
+ char *remote = get_default_remote();
+ struct strbuf remotesb = STRBUF_INIT;
+
+ strbuf_addf(&remotesb, "remote.%s.url", remote);
+ if (git_config_get_string(remotesb.buf, &remoteurl)) {
+ warning(_("could not look up configuration '%s'. Assuming this repository is its own authoritative upstream."), remotesb.buf);
+ remoteurl = xgetcwd();
+ }
+ relurl = relative_url(remoteurl, rel_url, NULL);
+
+ free(remote);
+ free(remoteurl);
+ strbuf_release(&remotesb);
+
+ return relurl;
+}
+
struct init_cb {
const char *prefix;
unsigned int flags;
@@ -634,21 +655,9 @@ static void init_submodule(const char *path, const char *prefix,
/* Possibly a url relative to parent */
if (starts_with_dot_dot_slash(url) ||
starts_with_dot_slash(url)) {
- char *remoteurl, *relurl;
- char *remote = get_default_remote();
- struct strbuf remotesb = STRBUF_INIT;
- strbuf_addf(&remotesb, "remote.%s.url", remote);
- free(remote);
-
- if (git_config_get_string(remotesb.buf, &remoteurl)) {
- warning(_("could not lookup configuration '%s'. Assuming this repository is its own authoritative upstream."), remotesb.buf);
- remoteurl = xgetcwd();
- }
- relurl = relative_url(remoteurl, url, NULL);
- strbuf_release(&remotesb);
- free(remoteurl);
- free(url);
- url = relurl;
+ char *oldurl = url;
+ url = compute_submodule_clone_url(oldurl);
+ free(oldurl);
}
if (git_config_set_gently(sb.buf, url))
@@ -700,7 +709,7 @@ static int module_init(int argc, const char **argv, const char *prefix)
};
const char *const git_submodule_helper_usage[] = {
- N_("git submodule--helper init [<path>]"),
+ N_("git submodule--helper init [<options>] [<path>]"),
NULL
};
@@ -792,7 +801,7 @@ static void status_submodule(const char *path, const struct object_id *ce_oid,
path, NULL);
git_config(git_diff_basic_config, NULL);
- init_revisions(&rev, prefix);
+ repo_init_revisions(the_repository, &rev, prefix);
rev.abbrev = 0;
diff_files_args.argc = setup_revisions(diff_files_args.argc,
diff_files_args.argv,
@@ -1123,6 +1132,8 @@ static void deinit_submodule(const char *path, const char *prefix,
if (!(flags & OPT_QUIET))
printf(format, displaypath);
+ submodule_unset_core_worktree(sub);
+
strbuf_release(&sb_rm);
}
@@ -1233,6 +1244,7 @@ static int clone_submodule(const char *path, const char *gitdir, const char *url
if (gitdir && *gitdir)
argv_array_pushl(&cp.args, "--separate-git-dir", gitdir, NULL);
+ argv_array_push(&cp.args, "--");
argv_array_push(&cp.args, url);
argv_array_push(&cp.args, path);
@@ -1256,19 +1268,20 @@ struct submodule_alternate_setup {
SUBMODULE_ALTERNATE_ERROR_IGNORE, NULL }
static int add_possible_reference_from_superproject(
- struct alternate_object_database *alt, void *sas_cb)
+ struct object_directory *odb, void *sas_cb)
{
struct submodule_alternate_setup *sas = sas_cb;
+ size_t len;
/*
* If the alternate object store is another repository, try the
* standard layout with .git/(modules/<name>)+/objects
*/
- if (ends_with(alt->path, "/objects")) {
+ if (strip_suffix(odb->path, "/objects", &len)) {
char *sm_alternate;
struct strbuf sb = STRBUF_INIT;
struct strbuf err = STRBUF_INIT;
- strbuf_add(&sb, alt->path, strlen(alt->path) - strlen("objects"));
+ strbuf_add(&sb, odb->path, len);
/*
* We need to end the new path with '/' to mark it as a dir,
@@ -1276,7 +1289,7 @@ static int add_possible_reference_from_superproject(
* as the last part of a missing submodule reference would
* be taken as a file name.
*/
- strbuf_addf(&sb, "modules/%s/", sas->submodule_name);
+ strbuf_addf(&sb, "/modules/%s/", sas->submodule_name);
sm_alternate = compute_alternate_path(sb.buf, &err);
if (sm_alternate) {
@@ -1288,7 +1301,7 @@ static int add_possible_reference_from_superproject(
die(_("submodule '%s' cannot add alternate: %s"),
sas->submodule_name, err.buf);
case SUBMODULE_ALTERNATE_ERROR_INFO:
- fprintf(stderr, _("submodule '%s' cannot add alternate: %s"),
+ fprintf_ln(stderr, _("submodule '%s' cannot add alternate: %s"),
sas->submodule_name, err.buf);
case SUBMODULE_ALTERNATE_ERROR_IGNORE:
; /* nothing */
@@ -1456,7 +1469,6 @@ static void determine_submodule_update_strategy(struct repository *r,
key = xstrfmt("submodule.%s.update", sub->name);
if (update) {
- trace_printf("parsing update");
if (parse_submodule_update_strategy(update, out) < 0)
die(_("Invalid update mode '%s' for submodule path '%s'"),
update, path);
@@ -1465,7 +1477,6 @@ static void determine_submodule_update_strategy(struct repository *r,
die(_("Invalid update mode '%s' configured for submodule path '%s'"),
val, path);
} else if (sub->update_strategy.type != SM_UPDATE_UNSPECIFIED) {
- trace_printf("loaded thing");
out->type = sub->update_strategy.type;
out->command = sub->update_strategy.command;
} else
@@ -1544,7 +1555,7 @@ struct submodule_update_clone {
#define SUBMODULE_UPDATE_CLONE_INIT {0, MODULE_LIST_INIT, 0, \
SUBMODULE_UPDATE_STRATEGY_INIT, 0, 0, -1, STRING_LIST_INIT_DUP, 0, \
NULL, NULL, NULL, \
- NULL, 0, 0, 0, NULL, 0, 0, 0}
+ NULL, 0, 0, 0, NULL, 0, 0, 1}
static void next_submodule_warn_missing(struct submodule_update_clone *suc,
@@ -1583,6 +1594,7 @@ static int prepare_to_clone_next_submodule(const struct cache_entry *ce,
struct strbuf sb = STRBUF_INIT;
const char *displaypath = NULL;
int needs_cloning = 0;
+ int need_free_url = 0;
if (ce_stage(ce)) {
if (suc->recursive_prefix)
@@ -1631,8 +1643,14 @@ static int prepare_to_clone_next_submodule(const struct cache_entry *ce,
strbuf_reset(&sb);
strbuf_addf(&sb, "submodule.%s.url", sub->name);
- if (repo_config_get_string_const(the_repository, sb.buf, &url))
- url = sub->url;
+ if (repo_config_get_string_const(the_repository, sb.buf, &url)) {
+ if (starts_with_dot_slash(sub->url) ||
+ starts_with_dot_dot_slash(sub->url)) {
+ url = compute_submodule_clone_url(sub->url);
+ need_free_url = 1;
+ } else
+ url = sub->url;
+ }
strbuf_reset(&sb);
strbuf_addf(&sb, "%s/.git", ce->name);
@@ -1678,6 +1696,8 @@ static int prepare_to_clone_next_submodule(const struct cache_entry *ce,
cleanup:
strbuf_reset(&displaypath_sb);
strbuf_reset(&sb);
+ if (need_free_url)
+ free((void*)url);
return needs_cloning;
}
@@ -1796,11 +1816,10 @@ static int update_submodules(struct submodule_update_clone *suc)
{
int i;
- run_processes_parallel(suc->max_jobs,
- update_clone_get_next_task,
- update_clone_start_failure,
- update_clone_task_finished,
- suc);
+ run_processes_parallel_tr2(suc->max_jobs, update_clone_get_next_task,
+ update_clone_start_failure,
+ update_clone_task_finished, suc, "submodule",
+ "parallel/update");
/*
* We saved the output and put it out all at once now.
@@ -2029,7 +2048,7 @@ static int ensure_core_worktree(int argc, const char **argv, const char *prefix)
struct repository subrepo;
if (argc != 2)
- BUG("submodule--helper connect-gitdir-workingtree <name> <path>");
+ BUG("submodule--helper ensure-core-worktree <path>");
path = argv[1];
@@ -2037,7 +2056,7 @@ static int ensure_core_worktree(int argc, const char **argv, const char *prefix)
if (!sub)
BUG("We could get the submodule handle before?");
- if (repo_submodule_init(&subrepo, the_repository, path))
+ if (repo_submodule_init(&subrepo, the_repository, sub))
die(_("could not get a repository handle for submodule '%s'"), path);
if (!repo_config_get_string(&subrepo, "core.worktree", &cw)) {
@@ -2077,7 +2096,7 @@ static int absorb_git_dirs(int argc, const char **argv, const char *prefix)
};
const char *const git_submodule_helper_usage[] = {
- N_("git submodule--helper embed-git-dir [<path>...]"),
+ N_("git submodule--helper absorb-git-dirs [<options>] [<path>...]"),
NULL
};
@@ -2088,8 +2107,7 @@ static int absorb_git_dirs(int argc, const char **argv, const char *prefix)
return 1;
for (i = 0; i < list.nr; i++)
- absorb_git_dir_into_superproject(prefix,
- list.entries[i]->name, flags);
+ absorb_git_dir_into_superproject(list.entries[i]->name, flags);
return 0;
}
@@ -2125,6 +2143,52 @@ 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,
+ DO_UNSET = 2
+ } 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_CMDMODE(0, "unset", &command,
+ N_("unset the config in the .gitmodules file"),
+ DO_UNSET),
+ OPT_END()
+ };
+ const char *const git_submodule_helper_usage[] = {
+ N_("git submodule--helper config <name> [<value>]"),
+ N_("git submodule--helper config --unset <name>"),
+ 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 && command != DO_UNSET)
+ return print_config_from_gitmodules(the_repository, argv[1]);
+
+ /* Equivalent to ACTION_SET in builtin/config.c */
+ if (argc == 3 || (argc == 2 && command == DO_UNSET)) {
+ const char *value = (argc == 3) ? argv[2] : NULL;
+
+ 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], value);
+ }
+
+ usage_with_options(git_submodule_helper_usage, module_config_options);
+}
+
#define SUPPORT_SUPER_PREFIX (1<<0)
struct cmd_struct {
@@ -2154,6 +2218,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)