|
|
|
@ -65,12 +65,16 @@ static int repo_get_default_remote(struct repository *repo, char **default_remot
|
|
|
|
|
static int get_default_remote_submodule(const char *module_path, char **default_remote)
|
|
|
|
|
{
|
|
|
|
|
struct repository subrepo;
|
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
|
|
if (repo_submodule_init(&subrepo, the_repository, module_path,
|
|
|
|
|
null_oid()) < 0)
|
|
|
|
|
return die_message(_("could not get a repository handle for submodule '%s'"),
|
|
|
|
|
module_path);
|
|
|
|
|
return repo_get_default_remote(&subrepo, default_remote);
|
|
|
|
|
ret = repo_get_default_remote(&subrepo, default_remote);
|
|
|
|
|
repo_clear(&subrepo);
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static char *get_default_remote(void)
|
|
|
|
@ -172,6 +176,11 @@ struct module_list {
|
|
|
|
|
};
|
|
|
|
|
#define MODULE_LIST_INIT { 0 }
|
|
|
|
|
|
|
|
|
|
static void module_list_release(struct module_list *ml)
|
|
|
|
|
{
|
|
|
|
|
free(ml->entries);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int module_list_compute(int argc, const char **argv,
|
|
|
|
|
const char *prefix,
|
|
|
|
|
struct pathspec *pathspec,
|
|
|
|
@ -234,7 +243,7 @@ static void module_list_active(struct module_list *list)
|
|
|
|
|
active_modules.entries[active_modules.nr++] = ce;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
free(list->entries);
|
|
|
|
|
module_list_release(list);
|
|
|
|
|
*list = active_modules;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -379,7 +388,7 @@ cleanup:
|
|
|
|
|
static int module_foreach(int argc, const char **argv, const char *prefix)
|
|
|
|
|
{
|
|
|
|
|
struct foreach_cb info = FOREACH_CB_INIT;
|
|
|
|
|
struct pathspec pathspec;
|
|
|
|
|
struct pathspec pathspec = { 0 };
|
|
|
|
|
struct module_list list = MODULE_LIST_INIT;
|
|
|
|
|
struct option module_foreach_options[] = {
|
|
|
|
|
OPT__QUIET(&info.quiet, N_("suppress output of entering each submodule command")),
|
|
|
|
@ -391,12 +400,13 @@ static int module_foreach(int argc, const char **argv, const char *prefix)
|
|
|
|
|
N_("git submodule foreach [--quiet] [--recursive] [--] <command>"),
|
|
|
|
|
NULL
|
|
|
|
|
};
|
|
|
|
|
int ret = 1;
|
|
|
|
|
|
|
|
|
|
argc = parse_options(argc, argv, prefix, module_foreach_options,
|
|
|
|
|
git_submodule_helper_usage, 0);
|
|
|
|
|
|
|
|
|
|
if (module_list_compute(0, NULL, prefix, &pathspec, &list) < 0)
|
|
|
|
|
return 1;
|
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
|
|
info.argc = argc;
|
|
|
|
|
info.argv = argv;
|
|
|
|
@ -404,7 +414,11 @@ static int module_foreach(int argc, const char **argv, const char *prefix)
|
|
|
|
|
|
|
|
|
|
for_each_listed_submodule(&list, runcommand_in_submodule_cb, &info);
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
ret = 0;
|
|
|
|
|
cleanup:
|
|
|
|
|
module_list_release(&list);
|
|
|
|
|
clear_pathspec(&pathspec);
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int starts_with_dot_slash(const char *const path)
|
|
|
|
@ -515,7 +529,7 @@ static void init_submodule_cb(const struct cache_entry *list_item, void *cb_data
|
|
|
|
|
static int module_init(int argc, const char **argv, const char *prefix)
|
|
|
|
|
{
|
|
|
|
|
struct init_cb info = INIT_CB_INIT;
|
|
|
|
|
struct pathspec pathspec;
|
|
|
|
|
struct pathspec pathspec = { 0 };
|
|
|
|
|
struct module_list list = MODULE_LIST_INIT;
|
|
|
|
|
int quiet = 0;
|
|
|
|
|
struct option module_init_options[] = {
|
|
|
|
@ -526,12 +540,13 @@ static int module_init(int argc, const char **argv, const char *prefix)
|
|
|
|
|
N_("git submodule init [<options>] [<path>]"),
|
|
|
|
|
NULL
|
|
|
|
|
};
|
|
|
|
|
int ret = 1;
|
|
|
|
|
|
|
|
|
|
argc = parse_options(argc, argv, prefix, module_init_options,
|
|
|
|
|
git_submodule_helper_usage, 0);
|
|
|
|
|
|
|
|
|
|
if (module_list_compute(argc, argv, prefix, &pathspec, &list) < 0)
|
|
|
|
|
return 1;
|
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* If there are no path args and submodule.active is set then,
|
|
|
|
@ -546,7 +561,11 @@ static int module_init(int argc, const char **argv, const char *prefix)
|
|
|
|
|
|
|
|
|
|
for_each_listed_submodule(&list, init_submodule_cb, &info);
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
ret = 0;
|
|
|
|
|
cleanup:
|
|
|
|
|
module_list_release(&list);
|
|
|
|
|
clear_pathspec(&pathspec);
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct status_cb {
|
|
|
|
@ -564,10 +583,11 @@ static void print_status(unsigned int flags, char state, const char *path,
|
|
|
|
|
printf("%c%s %s", state, oid_to_hex(oid), displaypath);
|
|
|
|
|
|
|
|
|
|
if (state == ' ' || state == '+') {
|
|
|
|
|
const char *name = compute_rev_name(path, oid_to_hex(oid));
|
|
|
|
|
char *name = compute_rev_name(path, oid_to_hex(oid));
|
|
|
|
|
|
|
|
|
|
if (name)
|
|
|
|
|
printf(" (%s)", name);
|
|
|
|
|
free(name);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
printf("\n");
|
|
|
|
@ -694,7 +714,7 @@ static void status_submodule_cb(const struct cache_entry *list_item,
|
|
|
|
|
static int module_status(int argc, const char **argv, const char *prefix)
|
|
|
|
|
{
|
|
|
|
|
struct status_cb info = STATUS_CB_INIT;
|
|
|
|
|
struct pathspec pathspec;
|
|
|
|
|
struct pathspec pathspec = { 0 };
|
|
|
|
|
struct module_list list = MODULE_LIST_INIT;
|
|
|
|
|
int quiet = 0;
|
|
|
|
|
struct option module_status_options[] = {
|
|
|
|
@ -707,12 +727,13 @@ static int module_status(int argc, const char **argv, const char *prefix)
|
|
|
|
|
N_("git submodule status [--quiet] [--cached] [--recursive] [<path>...]"),
|
|
|
|
|
NULL
|
|
|
|
|
};
|
|
|
|
|
int ret = 1;
|
|
|
|
|
|
|
|
|
|
argc = parse_options(argc, argv, prefix, module_status_options,
|
|
|
|
|
git_submodule_helper_usage, 0);
|
|
|
|
|
|
|
|
|
|
if (module_list_compute(argc, argv, prefix, &pathspec, &list) < 0)
|
|
|
|
|
return 1;
|
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
|
|
info.prefix = prefix;
|
|
|
|
|
if (quiet)
|
|
|
|
@ -720,7 +741,11 @@ static int module_status(int argc, const char **argv, const char *prefix)
|
|
|
|
|
|
|
|
|
|
for_each_listed_submodule(&list, status_submodule_cb, &info);
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
ret = 0;
|
|
|
|
|
cleanup:
|
|
|
|
|
module_list_release(&list);
|
|
|
|
|
clear_pathspec(&pathspec);
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct module_cb {
|
|
|
|
@ -729,16 +754,34 @@ struct module_cb {
|
|
|
|
|
struct object_id oid_src;
|
|
|
|
|
struct object_id oid_dst;
|
|
|
|
|
char status;
|
|
|
|
|
const char *sm_path;
|
|
|
|
|
char *sm_path;
|
|
|
|
|
};
|
|
|
|
|
#define MODULE_CB_INIT { 0 }
|
|
|
|
|
|
|
|
|
|
static void module_cb_release(struct module_cb *mcb)
|
|
|
|
|
{
|
|
|
|
|
free(mcb->sm_path);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct module_cb_list {
|
|
|
|
|
struct module_cb **entries;
|
|
|
|
|
int alloc, nr;
|
|
|
|
|
};
|
|
|
|
|
#define MODULE_CB_LIST_INIT { 0 }
|
|
|
|
|
|
|
|
|
|
static void module_cb_list_release(struct module_cb_list *mcbl)
|
|
|
|
|
{
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < mcbl->nr; i++) {
|
|
|
|
|
struct module_cb *mcb = mcbl->entries[i];
|
|
|
|
|
|
|
|
|
|
module_cb_release(mcb);
|
|
|
|
|
free(mcb);
|
|
|
|
|
}
|
|
|
|
|
free(mcbl->entries);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct summary_cb {
|
|
|
|
|
int argc;
|
|
|
|
|
const char **argv;
|
|
|
|
@ -954,6 +997,7 @@ static void generate_submodule_summary(struct summary_cb *info,
|
|
|
|
|
free(displaypath);
|
|
|
|
|
free(src_abbrev);
|
|
|
|
|
free(dst_abbrev);
|
|
|
|
|
strbuf_release(&errmsg);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void prepare_submodule_summary(struct summary_cb *info,
|
|
|
|
@ -1084,6 +1128,7 @@ static int compute_summary_module_list(struct object_id *head_oid,
|
|
|
|
|
cleanup:
|
|
|
|
|
strvec_clear(&diff_args);
|
|
|
|
|
release_revisions(&rev);
|
|
|
|
|
module_cb_list_release(&list);
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -1262,7 +1307,7 @@ static void sync_submodule_cb(const struct cache_entry *list_item, void *cb_data
|
|
|
|
|
static int module_sync(int argc, const char **argv, const char *prefix)
|
|
|
|
|
{
|
|
|
|
|
struct sync_cb info = SYNC_CB_INIT;
|
|
|
|
|
struct pathspec pathspec;
|
|
|
|
|
struct pathspec pathspec = { 0 };
|
|
|
|
|
struct module_list list = MODULE_LIST_INIT;
|
|
|
|
|
int quiet = 0;
|
|
|
|
|
int recursive = 0;
|
|
|
|
@ -1276,12 +1321,13 @@ static int module_sync(int argc, const char **argv, const char *prefix)
|
|
|
|
|
N_("git submodule sync [--quiet] [--recursive] [<path>]"),
|
|
|
|
|
NULL
|
|
|
|
|
};
|
|
|
|
|
int ret = 1;
|
|
|
|
|
|
|
|
|
|
argc = parse_options(argc, argv, prefix, module_sync_options,
|
|
|
|
|
git_submodule_helper_usage, 0);
|
|
|
|
|
|
|
|
|
|
if (module_list_compute(argc, argv, prefix, &pathspec, &list) < 0)
|
|
|
|
|
return 1;
|
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
|
|
info.prefix = prefix;
|
|
|
|
|
if (quiet)
|
|
|
|
@ -1291,7 +1337,11 @@ static int module_sync(int argc, const char **argv, const char *prefix)
|
|
|
|
|
|
|
|
|
|
for_each_listed_submodule(&list, sync_submodule_cb, &info);
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
ret = 0;
|
|
|
|
|
cleanup:
|
|
|
|
|
module_list_release(&list);
|
|
|
|
|
clear_pathspec(&pathspec);
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct deinit_cb {
|
|
|
|
@ -1400,7 +1450,7 @@ static void deinit_submodule_cb(const struct cache_entry *list_item,
|
|
|
|
|
static int module_deinit(int argc, const char **argv, const char *prefix)
|
|
|
|
|
{
|
|
|
|
|
struct deinit_cb info = DEINIT_CB_INIT;
|
|
|
|
|
struct pathspec pathspec;
|
|
|
|
|
struct pathspec pathspec = { 0 };
|
|
|
|
|
struct module_list list = MODULE_LIST_INIT;
|
|
|
|
|
int quiet = 0;
|
|
|
|
|
int force = 0;
|
|
|
|
@ -1415,6 +1465,7 @@ static int module_deinit(int argc, const char **argv, const char *prefix)
|
|
|
|
|
N_("git submodule deinit [--quiet] [-f | --force] [--all | [--] [<path>...]]"),
|
|
|
|
|
NULL
|
|
|
|
|
};
|
|
|
|
|
int ret = 1;
|
|
|
|
|
|
|
|
|
|
argc = parse_options(argc, argv, prefix, module_deinit_options,
|
|
|
|
|
git_submodule_helper_usage, 0);
|
|
|
|
@ -1429,7 +1480,7 @@ static int module_deinit(int argc, const char **argv, const char *prefix)
|
|
|
|
|
die(_("Use '--all' if you really want to deinitialize all submodules"));
|
|
|
|
|
|
|
|
|
|
if (module_list_compute(argc, argv, prefix, &pathspec, &list) < 0)
|
|
|
|
|
return 1;
|
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
|
|
info.prefix = prefix;
|
|
|
|
|
if (quiet)
|
|
|
|
@ -1439,7 +1490,11 @@ static int module_deinit(int argc, const char **argv, const char *prefix)
|
|
|
|
|
|
|
|
|
|
for_each_listed_submodule(&list, deinit_submodule_cb, &info);
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
ret = 0;
|
|
|
|
|
cleanup:
|
|
|
|
|
module_list_release(&list);
|
|
|
|
|
clear_pathspec(&pathspec);
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct module_clone_data {
|
|
|
|
@ -1513,7 +1568,9 @@ static int add_possible_reference_from_superproject(
|
|
|
|
|
|
|
|
|
|
sm_alternate = compute_alternate_path(sb.buf, &err);
|
|
|
|
|
if (sm_alternate) {
|
|
|
|
|
string_list_append(sas->reference, xstrdup(sb.buf));
|
|
|
|
|
char *p = strbuf_detach(&sb, NULL);
|
|
|
|
|
|
|
|
|
|
string_list_append(sas->reference, p)->util = p;
|
|
|
|
|
free(sm_alternate);
|
|
|
|
|
} else {
|
|
|
|
|
switch (sas->error_mode) {
|
|
|
|
@ -1591,13 +1648,12 @@ static int clone_submodule(const struct module_clone_data *clone_data,
|
|
|
|
|
char *sm_gitdir = clone_submodule_sm_gitdir(clone_data->name);
|
|
|
|
|
char *sm_alternate = NULL, *error_strategy = NULL;
|
|
|
|
|
struct child_process cp = CHILD_PROCESS_INIT;
|
|
|
|
|
const char *clone_data_path;
|
|
|
|
|
const char *clone_data_path = clone_data->path;
|
|
|
|
|
char *to_free = NULL;
|
|
|
|
|
|
|
|
|
|
if (!is_absolute_path(clone_data->path))
|
|
|
|
|
clone_data_path = xstrfmt("%s/%s", get_git_work_tree(),
|
|
|
|
|
clone_data->path);
|
|
|
|
|
else
|
|
|
|
|
clone_data_path = xstrdup(clone_data->path);
|
|
|
|
|
clone_data_path = to_free = xstrfmt("%s/%s", get_git_work_tree(),
|
|
|
|
|
clone_data->path);
|
|
|
|
|
|
|
|
|
|
if (validate_submodule_git_dir(sm_gitdir, clone_data->name) < 0)
|
|
|
|
|
die(_("refusing to create/use '%s' in another submodule's "
|
|
|
|
@ -1682,6 +1738,7 @@ static int clone_submodule(const struct module_clone_data *clone_data,
|
|
|
|
|
|
|
|
|
|
free(sm_gitdir);
|
|
|
|
|
free(p);
|
|
|
|
|
free(to_free);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -1745,6 +1802,7 @@ static int module_clone(int argc, const char **argv, const char *prefix)
|
|
|
|
|
|
|
|
|
|
clone_submodule(&clone_data, &reference);
|
|
|
|
|
list_objects_filter_release(&filter_options);
|
|
|
|
|
string_list_clear(&reference, 1);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -1815,9 +1873,15 @@ struct submodule_update_clone {
|
|
|
|
|
};
|
|
|
|
|
#define SUBMODULE_UPDATE_CLONE_INIT { 0 }
|
|
|
|
|
|
|
|
|
|
static void submodule_update_clone_release(struct submodule_update_clone *suc)
|
|
|
|
|
{
|
|
|
|
|
free(suc->update_clone);
|
|
|
|
|
free(suc->failed_clones);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct update_data {
|
|
|
|
|
const char *prefix;
|
|
|
|
|
const char *displaypath;
|
|
|
|
|
char *displaypath;
|
|
|
|
|
enum submodule_update_type update_default;
|
|
|
|
|
struct object_id suboid;
|
|
|
|
|
struct string_list references;
|
|
|
|
@ -1853,6 +1917,12 @@ struct update_data {
|
|
|
|
|
.max_jobs = 1, \
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void update_data_release(struct update_data *ud)
|
|
|
|
|
{
|
|
|
|
|
free(ud->displaypath);
|
|
|
|
|
module_list_release(&ud->list);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void next_submodule_warn_missing(struct submodule_update_clone *suc,
|
|
|
|
|
struct strbuf *out, const char *displaypath)
|
|
|
|
|
{
|
|
|
|
@ -2110,7 +2180,7 @@ static int is_tip_reachable(const char *path, const struct object_id *oid)
|
|
|
|
|
char *hex = oid_to_hex(oid);
|
|
|
|
|
|
|
|
|
|
cp.git_cmd = 1;
|
|
|
|
|
cp.dir = xstrdup(path);
|
|
|
|
|
cp.dir = path;
|
|
|
|
|
cp.no_stderr = 1;
|
|
|
|
|
strvec_pushl(&cp.args, "rev-list", "-n", "1", hex, "--not", "--all", NULL);
|
|
|
|
|
|
|
|
|
@ -2129,7 +2199,7 @@ static int fetch_in_submodule(const char *module_path, int depth, int quiet,
|
|
|
|
|
|
|
|
|
|
prepare_submodule_repo_env(&cp.env);
|
|
|
|
|
cp.git_cmd = 1;
|
|
|
|
|
cp.dir = xstrdup(module_path);
|
|
|
|
|
cp.dir = module_path;
|
|
|
|
|
|
|
|
|
|
strvec_push(&cp.args, "fetch");
|
|
|
|
|
if (quiet)
|
|
|
|
@ -2182,7 +2252,7 @@ static int run_update_command(const struct update_data *ud, int subforce)
|
|
|
|
|
}
|
|
|
|
|
strvec_push(&cp.args, oid);
|
|
|
|
|
|
|
|
|
|
cp.dir = xstrdup(ud->sm_path);
|
|
|
|
|
cp.dir = ud->sm_path;
|
|
|
|
|
prepare_submodule_repo_env(&cp.env);
|
|
|
|
|
if ((ret = run_command(&cp))) {
|
|
|
|
|
switch (ud->update_strategy.type) {
|
|
|
|
@ -2340,6 +2410,7 @@ static int ensure_core_worktree(const char *path)
|
|
|
|
|
strbuf_release(&sb);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
repo_clear(&subrepo);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -2417,13 +2488,6 @@ static int update_submodule(struct update_data *update_data)
|
|
|
|
|
{
|
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
|
|
ret = ensure_core_worktree(update_data->sm_path);
|
|
|
|
|
if (ret)
|
|
|
|
|
return ret;
|
|
|
|
|
|
|
|
|
|
update_data->displaypath = get_submodule_displaypath(
|
|
|
|
|
update_data->sm_path, update_data->prefix);
|
|
|
|
|
|
|
|
|
|
ret = determine_submodule_update_strategy(the_repository,
|
|
|
|
|
update_data->just_cloned,
|
|
|
|
|
update_data->sm_path,
|
|
|
|
@ -2452,6 +2516,8 @@ static int update_submodule(struct update_data *update_data)
|
|
|
|
|
return code;
|
|
|
|
|
remote_ref = xstrfmt("refs/remotes/%s/%s", remote_name, branch);
|
|
|
|
|
|
|
|
|
|
free(remote_name);
|
|
|
|
|
|
|
|
|
|
if (!update_data->nofetch) {
|
|
|
|
|
if (fetch_in_submodule(update_data->sm_path, update_data->depth,
|
|
|
|
|
0, NULL))
|
|
|
|
@ -2527,7 +2593,15 @@ static int update_submodules(struct update_data *update_data)
|
|
|
|
|
update_data->just_cloned = ucd.just_cloned;
|
|
|
|
|
update_data->sm_path = ucd.sub->path;
|
|
|
|
|
|
|
|
|
|
code = ensure_core_worktree(update_data->sm_path);
|
|
|
|
|
if (code)
|
|
|
|
|
goto fail;
|
|
|
|
|
|
|
|
|
|
update_data->displaypath = get_submodule_displaypath(
|
|
|
|
|
update_data->sm_path, update_data->prefix);
|
|
|
|
|
code = update_submodule(update_data);
|
|
|
|
|
FREE_AND_NULL(update_data->displaypath);
|
|
|
|
|
fail:
|
|
|
|
|
if (!code)
|
|
|
|
|
continue;
|
|
|
|
|
ret = code;
|
|
|
|
@ -2536,13 +2610,15 @@ static int update_submodules(struct update_data *update_data)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
|
submodule_update_clone_release(&suc);
|
|
|
|
|
string_list_clear(&update_data->references, 0);
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int module_update(int argc, const char **argv, const char *prefix)
|
|
|
|
|
{
|
|
|
|
|
struct pathspec pathspec;
|
|
|
|
|
struct pathspec pathspec = { 0 };
|
|
|
|
|
struct pathspec pathspec2 = { 0 };
|
|
|
|
|
struct update_data opt = UPDATE_DATA_INIT;
|
|
|
|
|
struct list_objects_filter_options filter_options = { 0 };
|
|
|
|
|
int ret;
|
|
|
|
@ -2619,8 +2695,8 @@ static int module_update(int argc, const char **argv, const char *prefix)
|
|
|
|
|
opt.update_strategy.type = opt.update_default;
|
|
|
|
|
|
|
|
|
|
if (module_list_compute(argc, argv, prefix, &pathspec, &opt.list) < 0) {
|
|
|
|
|
list_objects_filter_release(&filter_options);
|
|
|
|
|
return 1;
|
|
|
|
|
ret = 1;
|
|
|
|
|
goto cleanup;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (pathspec.nr)
|
|
|
|
@ -2631,8 +2707,11 @@ static int module_update(int argc, const char **argv, const char *prefix)
|
|
|
|
|
struct init_cb info = INIT_CB_INIT;
|
|
|
|
|
|
|
|
|
|
if (module_list_compute(argc, argv, opt.prefix,
|
|
|
|
|
&pathspec, &list) < 0)
|
|
|
|
|
return 1;
|
|
|
|
|
&pathspec2, &list) < 0) {
|
|
|
|
|
module_list_release(&list);
|
|
|
|
|
ret = 1;
|
|
|
|
|
goto cleanup;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* If there are no path args and submodule.active is set then,
|
|
|
|
@ -2646,10 +2725,15 @@ static int module_update(int argc, const char **argv, const char *prefix)
|
|
|
|
|
info.flags |= OPT_QUIET;
|
|
|
|
|
|
|
|
|
|
for_each_listed_submodule(&list, init_submodule_cb, &info);
|
|
|
|
|
module_list_release(&list);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ret = update_submodules(&opt);
|
|
|
|
|
cleanup:
|
|
|
|
|
update_data_release(&opt);
|
|
|
|
|
list_objects_filter_release(&filter_options);
|
|
|
|
|
clear_pathspec(&pathspec);
|
|
|
|
|
clear_pathspec(&pathspec2);
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -2733,7 +2817,7 @@ static int push_check(int argc, const char **argv, const char *prefix)
|
|
|
|
|
static int absorb_git_dirs(int argc, const char **argv, const char *prefix)
|
|
|
|
|
{
|
|
|
|
|
int i;
|
|
|
|
|
struct pathspec pathspec;
|
|
|
|
|
struct pathspec pathspec = { 0 };
|
|
|
|
|
struct module_list list = MODULE_LIST_INIT;
|
|
|
|
|
unsigned flags = ABSORB_GITDIR_RECURSE_SUBMODULES;
|
|
|
|
|
struct option embed_gitdir_options[] = {
|
|
|
|
@ -2748,17 +2832,22 @@ static int absorb_git_dirs(int argc, const char **argv, const char *prefix)
|
|
|
|
|
N_("git submodule absorbgitdirs [<options>] [<path>...]"),
|
|
|
|
|
NULL
|
|
|
|
|
};
|
|
|
|
|
int ret = 1;
|
|
|
|
|
|
|
|
|
|
argc = parse_options(argc, argv, prefix, embed_gitdir_options,
|
|
|
|
|
git_submodule_helper_usage, 0);
|
|
|
|
|
|
|
|
|
|
if (module_list_compute(argc, argv, prefix, &pathspec, &list) < 0)
|
|
|
|
|
return 1;
|
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < list.nr; i++)
|
|
|
|
|
absorb_git_dir_into_superproject(list.entries[i]->name, flags);
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
ret = 0;
|
|
|
|
|
cleanup:
|
|
|
|
|
clear_pathspec(&pathspec);
|
|
|
|
|
module_list_release(&list);
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int module_config(int argc, const char **argv, const char *prefix)
|
|
|
|
@ -2963,6 +3052,7 @@ static int add_submodule(const struct add_data *add_data)
|
|
|
|
|
char *submod_gitdir_path;
|
|
|
|
|
struct module_clone_data clone_data = MODULE_CLONE_DATA_INIT;
|
|
|
|
|
struct string_list reference = STRING_LIST_INIT_NODUP;
|
|
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
|
|
/* perhaps the path already exists and is already a git repo, else clone it */
|
|
|
|
|
if (is_directory(add_data->sm_path)) {
|
|
|
|
@ -3018,15 +3108,17 @@ static int add_submodule(const struct add_data *add_data)
|
|
|
|
|
clone_data.url = add_data->realrepo;
|
|
|
|
|
clone_data.quiet = add_data->quiet;
|
|
|
|
|
clone_data.progress = add_data->progress;
|
|
|
|
|
if (add_data->reference_path)
|
|
|
|
|
string_list_append(&reference,
|
|
|
|
|
xstrdup(add_data->reference_path));
|
|
|
|
|
if (add_data->reference_path) {
|
|
|
|
|
char *p = xstrdup(add_data->reference_path);
|
|
|
|
|
|
|
|
|
|
string_list_append(&reference, p)->util = p;
|
|
|
|
|
}
|
|
|
|
|
clone_data.dissociate = add_data->dissociate;
|
|
|
|
|
if (add_data->depth >= 0)
|
|
|
|
|
clone_data.depth = xstrfmt("%d", add_data->depth);
|
|
|
|
|
|
|
|
|
|
if (clone_submodule(&clone_data, &reference))
|
|
|
|
|
return -1;
|
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
|
|
prepare_submodule_repo_env(&cp.env);
|
|
|
|
|
cp.git_cmd = 1;
|
|
|
|
@ -3045,7 +3137,10 @@ static int add_submodule(const struct add_data *add_data)
|
|
|
|
|
if (run_command(&cp))
|
|
|
|
|
die(_("unable to checkout submodule '%s'"), add_data->sm_path);
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
ret = 0;
|
|
|
|
|
cleanup:
|
|
|
|
|
string_list_clear(&reference, 1);
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int config_submodule_in_gitmodules(const char *name, const char *var, const char *value)
|
|
|
|
@ -3066,7 +3161,7 @@ static int config_submodule_in_gitmodules(const char *name, const char *var, con
|
|
|
|
|
static void configure_added_submodule(struct add_data *add_data)
|
|
|
|
|
{
|
|
|
|
|
char *key;
|
|
|
|
|
char *val = NULL;
|
|
|
|
|
const char *val;
|
|
|
|
|
struct child_process add_submod = CHILD_PROCESS_INIT;
|
|
|
|
|
struct child_process add_gitmodules = CHILD_PROCESS_INIT;
|
|
|
|
|
|
|
|
|
@ -3111,7 +3206,7 @@ static void configure_added_submodule(struct add_data *add_data)
|
|
|
|
|
* is_submodule_active(), since that function needs to find
|
|
|
|
|
* out the value of "submodule.active" again anyway.
|
|
|
|
|
*/
|
|
|
|
|
if (!git_config_get_string("submodule.active", &val)) {
|
|
|
|
|
if (!git_config_get_string_tmp("submodule.active", &val)) {
|
|
|
|
|
/*
|
|
|
|
|
* If the submodule being added isn't already covered by the
|
|
|
|
|
* current configured pathspec, set the submodule's active flag
|
|
|
|
@ -3205,6 +3300,8 @@ static int module_add(int argc, const char **argv, const char *prefix)
|
|
|
|
|
N_("git submodule add [<options>] [--] <repository> [<path>]"),
|
|
|
|
|
NULL
|
|
|
|
|
};
|
|
|
|
|
struct strbuf sb = STRBUF_INIT;
|
|
|
|
|
int ret = 1;
|
|
|
|
|
|
|
|
|
|
argc = parse_options(argc, argv, prefix, options, usage, 0);
|
|
|
|
|
|
|
|
|
@ -3224,8 +3321,12 @@ static int module_add(int argc, const char **argv, const char *prefix)
|
|
|
|
|
else
|
|
|
|
|
add_data.sm_path = xstrdup(argv[1]);
|
|
|
|
|
|
|
|
|
|
if (prefix && *prefix && !is_absolute_path(add_data.sm_path))
|
|
|
|
|
add_data.sm_path = xstrfmt("%s%s", prefix, add_data.sm_path);
|
|
|
|
|
if (prefix && *prefix && !is_absolute_path(add_data.sm_path)) {
|
|
|
|
|
char *sm_path = add_data.sm_path;
|
|
|
|
|
|
|
|
|
|
add_data.sm_path = xstrfmt("%s%s", prefix, sm_path);
|
|
|
|
|
free(sm_path);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (starts_with_dot_dot_slash(add_data.repo) ||
|
|
|
|
|
starts_with_dot_slash(add_data.repo)) {
|
|
|
|
@ -3254,21 +3355,17 @@ static int module_add(int argc, const char **argv, const char *prefix)
|
|
|
|
|
die_on_repo_without_commits(add_data.sm_path);
|
|
|
|
|
|
|
|
|
|
if (!force) {
|
|
|
|
|
int exit_code = -1;
|
|
|
|
|
struct strbuf sb = STRBUF_INIT;
|
|
|
|
|
struct child_process cp = CHILD_PROCESS_INIT;
|
|
|
|
|
|
|
|
|
|
cp.git_cmd = 1;
|
|
|
|
|
cp.no_stdout = 1;
|
|
|
|
|
strvec_pushl(&cp.args, "add", "--dry-run", "--ignore-missing",
|
|
|
|
|
"--no-warn-embedded-repo", add_data.sm_path, NULL);
|
|
|
|
|
if ((exit_code = pipe_command(&cp, NULL, 0, NULL, 0, &sb, 0))) {
|
|
|
|
|
if ((ret = pipe_command(&cp, NULL, 0, NULL, 0, &sb, 0))) {
|
|
|
|
|
strbuf_complete_line(&sb);
|
|
|
|
|
fputs(sb.buf, stderr);
|
|
|
|
|
free(add_data.sm_path);
|
|
|
|
|
return exit_code;
|
|
|
|
|
goto cleanup;
|
|
|
|
|
}
|
|
|
|
|
strbuf_release(&sb);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(!add_data.sm_name)
|
|
|
|
@ -3283,15 +3380,17 @@ static int module_add(int argc, const char **argv, const char *prefix)
|
|
|
|
|
add_data.progress = !!progress;
|
|
|
|
|
add_data.dissociate = !!dissociate;
|
|
|
|
|
|
|
|
|
|
if (add_submodule(&add_data)) {
|
|
|
|
|
free(add_data.sm_path);
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
if (add_submodule(&add_data))
|
|
|
|
|
goto cleanup;
|
|
|
|
|
configure_added_submodule(&add_data);
|
|
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
|
cleanup:
|
|
|
|
|
free(add_data.sm_path);
|
|
|
|
|
free(to_free);
|
|
|
|
|
strbuf_release(&sb);
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#define SUPPORT_SUPER_PREFIX (1<<0)
|
|
|
|
|