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.c202
1 files changed, 46 insertions, 156 deletions
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 1a8e5d0621..c597df7528 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -72,135 +72,6 @@ static char *get_default_remote(void)
return repo_get_default_remote(the_repository);
}
-static int starts_with_dot_slash(const char *str)
-{
- return str[0] == '.' && is_dir_sep(str[1]);
-}
-
-static int starts_with_dot_dot_slash(const char *str)
-{
- return str[0] == '.' && str[1] == '.' && is_dir_sep(str[2]);
-}
-
-/*
- * Returns 1 if it was the last chop before ':'.
- */
-static int chop_last_dir(char **remoteurl, int is_relative)
-{
- char *rfind = find_last_dir_sep(*remoteurl);
- if (rfind) {
- *rfind = '\0';
- return 0;
- }
-
- rfind = strrchr(*remoteurl, ':');
- if (rfind) {
- *rfind = '\0';
- return 1;
- }
-
- if (is_relative || !strcmp(".", *remoteurl))
- die(_("cannot strip one component off url '%s'"),
- *remoteurl);
-
- free(*remoteurl);
- *remoteurl = xstrdup(".");
- return 0;
-}
-
-/*
- * The `url` argument is the URL that navigates to the submodule origin
- * repo. When relative, this URL is relative to the superproject origin
- * URL repo. The `up_path` argument, if specified, is the relative
- * path that navigates from the submodule working tree to the superproject
- * working tree. Returns the origin URL of the submodule.
- *
- * Return either an absolute URL or filesystem path (if the superproject
- * origin URL is an absolute URL or filesystem path, respectively) or a
- * relative file system path (if the superproject origin URL is a relative
- * file system path).
- *
- * When the output is a relative file system path, the path is either
- * relative to the submodule working tree, if up_path is specified, or to
- * the superproject working tree otherwise.
- *
- * NEEDSWORK: This works incorrectly on the domain and protocol part.
- * remote_url url outcome expectation
- * http://a.com/b ../c http://a.com/c as is
- * http://a.com/b/ ../c http://a.com/c same as previous line, but
- * ignore trailing slash in url
- * http://a.com/b ../../c http://c error out
- * http://a.com/b ../../../c http:/c error out
- * http://a.com/b ../../../../c http:c error out
- * http://a.com/b ../../../../../c .:c error out
- * NEEDSWORK: Given how chop_last_dir() works, this function is broken
- * when a local part has a colon in its path component, too.
- */
-static char *relative_url(const char *remote_url,
- const char *url,
- const char *up_path)
-{
- int is_relative = 0;
- int colonsep = 0;
- char *out;
- char *remoteurl = xstrdup(remote_url);
- struct strbuf sb = STRBUF_INIT;
- size_t len = strlen(remoteurl);
-
- if (is_dir_sep(remoteurl[len-1]))
- remoteurl[len-1] = '\0';
-
- if (!url_is_local_not_ssh(remoteurl) || is_absolute_path(remoteurl))
- is_relative = 0;
- else {
- is_relative = 1;
- /*
- * Prepend a './' to ensure all relative
- * remoteurls start with './' or '../'
- */
- if (!starts_with_dot_slash(remoteurl) &&
- !starts_with_dot_dot_slash(remoteurl)) {
- strbuf_reset(&sb);
- strbuf_addf(&sb, "./%s", remoteurl);
- free(remoteurl);
- remoteurl = strbuf_detach(&sb, NULL);
- }
- }
- /*
- * When the url starts with '../', remove that and the
- * last directory in remoteurl.
- */
- while (url) {
- if (starts_with_dot_dot_slash(url)) {
- url += 3;
- colonsep |= chop_last_dir(&remoteurl, is_relative);
- } else if (starts_with_dot_slash(url))
- url += 2;
- else
- break;
- }
- strbuf_reset(&sb);
- strbuf_addf(&sb, "%s%s%s", remoteurl, colonsep ? ":" : "/", url);
- if (ends_with(url, "/"))
- strbuf_setlen(&sb, sb.len - 1);
- free(remoteurl);
-
- if (starts_with_dot_slash(sb.buf))
- out = xstrdup(sb.buf + 2);
- else
- out = xstrdup(sb.buf);
-
- if (!up_path || !is_relative) {
- strbuf_release(&sb);
- return out;
- }
-
- strbuf_reset(&sb);
- strbuf_addf(&sb, "%s%s", up_path, out);
- free(out);
- return strbuf_detach(&sb, NULL);
-}
-
static char *resolve_relative_url(const char *rel_url, const char *up_path, int quiet)
{
char *remoteurl, *resolved_url;
@@ -292,7 +163,7 @@ static char *compute_rev_name(const char *sub_path, const char* object_id)
for (d = describe_argv; *d; d++) {
struct child_process cp = CHILD_PROCESS_INIT;
- prepare_submodule_repo_env(&cp.env_array);
+ prepare_submodule_repo_env(&cp.env);
cp.dir = sub_path;
cp.git_cmd = 1;
cp.no_stderr = 1;
@@ -479,7 +350,7 @@ static void runcommand_in_submodule_cb(const struct cache_entry *list_item,
if (!is_submodule_populated_gently(path, NULL))
goto cleanup;
- prepare_submodule_repo_env(&cp.env_array);
+ prepare_submodule_repo_env(&cp.env);
/*
* For the purpose of executing <command> in the submodule,
@@ -499,12 +370,12 @@ static void runcommand_in_submodule_cb(const struct cache_entry *list_item,
char *toplevel = xgetcwd();
struct strbuf sb = STRBUF_INIT;
- strvec_pushf(&cp.env_array, "name=%s", sub->name);
- strvec_pushf(&cp.env_array, "sm_path=%s", path);
- strvec_pushf(&cp.env_array, "displaypath=%s", displaypath);
- strvec_pushf(&cp.env_array, "sha1=%s",
+ strvec_pushf(&cp.env, "name=%s", sub->name);
+ strvec_pushf(&cp.env, "sm_path=%s", path);
+ strvec_pushf(&cp.env, "displaypath=%s", displaypath);
+ strvec_pushf(&cp.env, "sha1=%s",
oid_to_hex(ce_oid));
- strvec_pushf(&cp.env_array, "toplevel=%s", toplevel);
+ strvec_pushf(&cp.env, "toplevel=%s", toplevel);
/*
* Since the path variable was accessible from the script
@@ -513,7 +384,7 @@ static void runcommand_in_submodule_cb(const struct cache_entry *list_item,
* on windows. And since environment variables are
* case-insensitive in windows, it interferes with the
* existing PATH variable. Hence, to avoid that, we expose
- * path via the args strvec and not via env_array.
+ * path via the args strvec and not via env.
*/
sq_quote_buf(&sb, path);
strvec_pushf(&cp.args, "path=%s; %s",
@@ -536,7 +407,7 @@ static void runcommand_in_submodule_cb(const struct cache_entry *list_item,
cpr.git_cmd = 1;
cpr.dir = path;
- prepare_submodule_repo_env(&cpr.env_array);
+ prepare_submodule_repo_env(&cpr.env);
strvec_pushl(&cpr.args, "--super-prefix", NULL);
strvec_pushf(&cpr.args, "%s/", displaypath);
@@ -592,6 +463,18 @@ static int module_foreach(int argc, const char **argv, const char *prefix)
return 0;
}
+static int starts_with_dot_slash(const char *const path)
+{
+ return path_match_flags(path, PATH_MATCH_STARTS_WITH_DOT_SLASH |
+ PATH_MATCH_XPLATFORM);
+}
+
+static int starts_with_dot_dot_slash(const char *const path)
+{
+ return path_match_flags(path, PATH_MATCH_STARTS_WITH_DOT_DOT_SLASH |
+ PATH_MATCH_XPLATFORM);
+}
+
struct init_cb {
const char *prefix;
const char *superprefix;
@@ -766,7 +649,7 @@ static void status_submodule(const char *path, const struct object_id *ce_oid,
{
char *displaypath;
struct strvec diff_files_args = STRVEC_INIT;
- struct rev_info rev;
+ struct rev_info rev = REV_INFO_INIT;
int diff_files_result;
struct strbuf buf = STRBUF_INIT;
const char *git_dir;
@@ -833,7 +716,7 @@ static void status_submodule(const char *path, const struct object_id *ce_oid,
cpr.git_cmd = 1;
cpr.dir = path;
- prepare_submodule_repo_env(&cpr.env_array);
+ prepare_submodule_repo_env(&cpr.env);
strvec_push(&cpr.args, "--super-prefix");
strvec_pushf(&cpr.args, "%s/", displaypath);
@@ -853,6 +736,7 @@ static void status_submodule(const char *path, const struct object_id *ce_oid,
cleanup:
strvec_clear(&diff_files_args);
free(displaypath);
+ release_revisions(&rev);
}
static void status_submodule_cb(const struct cache_entry *list_item,
@@ -955,7 +839,7 @@ static char *verify_submodule_committish(const char *sm_path,
cp_rev_parse.git_cmd = 1;
cp_rev_parse.dir = sm_path;
- prepare_submodule_repo_env(&cp_rev_parse.env_array);
+ prepare_submodule_repo_env(&cp_rev_parse.env);
strvec_pushl(&cp_rev_parse.args, "rev-parse", "-q", "--short", NULL);
strvec_pushf(&cp_rev_parse.args, "%s^0", committish);
strvec_push(&cp_rev_parse.args, "--");
@@ -996,7 +880,7 @@ static void print_submodule_summary(struct summary_cb *info, char *errmsg,
cp_log.git_cmd = 1;
cp_log.dir = p->sm_path;
- prepare_submodule_repo_env(&cp_log.env_array);
+ prepare_submodule_repo_env(&cp_log.env);
strvec_pushl(&cp_log.args, "log", NULL);
if (S_ISGITLINK(p->mod_src) && S_ISGITLINK(p->mod_dst)) {
@@ -1113,7 +997,7 @@ static void generate_submodule_summary(struct summary_cb *info,
cp_rev_list.git_cmd = 1;
cp_rev_list.dir = p->sm_path;
- prepare_submodule_repo_env(&cp_rev_list.env_array);
+ prepare_submodule_repo_env(&cp_rev_list.env);
if (!capture_command(&cp_rev_list, &sb_rev_list, 0))
total_commits = atoi(sb_rev_list.buf);
@@ -1231,6 +1115,7 @@ static int compute_summary_module_list(struct object_id *head_oid,
struct strvec diff_args = STRVEC_INIT;
struct rev_info rev;
struct module_cb_list list = MODULE_CB_LIST_INIT;
+ int ret = 0;
strvec_push(&diff_args, get_diff_cmd(diff_cmd));
if (info->cached)
@@ -1256,11 +1141,13 @@ static int compute_summary_module_list(struct object_id *head_oid,
setup_work_tree();
if (read_cache_preload(&rev.diffopt.pathspec) < 0) {
perror("read_cache_preload");
- return -1;
+ ret = -1;
+ goto cleanup;
}
} else if (read_cache() < 0) {
perror("read_cache");
- return -1;
+ ret = -1;
+ goto cleanup;
}
if (diff_cmd == DIFF_INDEX)
@@ -1268,8 +1155,10 @@ static int compute_summary_module_list(struct object_id *head_oid,
else
run_diff_files(&rev, 0);
prepare_submodule_summary(info, &list);
+cleanup:
strvec_clear(&diff_args);
- return 0;
+ release_revisions(&rev);
+ return ret;
}
static int module_summary(int argc, const char **argv, const char *prefix)
@@ -1414,7 +1303,7 @@ static void sync_submodule(const char *path, const char *prefix,
cpr.git_cmd = 1;
cpr.dir = path;
- prepare_submodule_repo_env(&cpr.env_array);
+ prepare_submodule_repo_env(&cpr.env);
strvec_push(&cpr.args, "--super-prefix");
strvec_pushf(&cpr.args, "%s/", displaypath);
@@ -1819,7 +1708,7 @@ static int clone_submodule(struct module_clone_data *clone_data)
strvec_push(&cp.args, clone_data->path);
cp.git_cmd = 1;
- prepare_submodule_repo_env(&cp.env_array);
+ prepare_submodule_repo_env(&cp.env);
cp.no_stdin = 1;
if(run_command(&cp))
@@ -2294,7 +2183,7 @@ static int is_tip_reachable(const char *path, struct object_id *oid)
cp.no_stderr = 1;
strvec_pushl(&cp.args, "rev-list", "-n", "1", hex, "--not", "--all", NULL);
- prepare_submodule_repo_env(&cp.env_array);
+ prepare_submodule_repo_env(&cp.env);
if (capture_command(&cp, &rev, GIT_MAX_HEXSZ + 1) || rev.len)
return 0;
@@ -2306,7 +2195,7 @@ static int fetch_in_submodule(const char *module_path, int depth, int quiet, str
{
struct child_process cp = CHILD_PROCESS_INIT;
- prepare_submodule_repo_env(&cp.env_array);
+ prepare_submodule_repo_env(&cp.env);
cp.git_cmd = 1;
cp.dir = xstrdup(module_path);
@@ -2319,6 +2208,7 @@ static int fetch_in_submodule(const char *module_path, int depth, int quiet, str
char *hex = oid_to_hex(oid);
char *remote = get_default_remote();
strvec_pushl(&cp.args, remote, hex, NULL);
+ free(remote);
}
return run_command(&cp);
@@ -2363,7 +2253,7 @@ static int run_update_command(struct update_data *ud, int subforce)
strvec_push(&cp.args, oid);
cp.dir = xstrdup(ud->sm_path);
- prepare_submodule_repo_env(&cp.env_array);
+ prepare_submodule_repo_env(&cp.env);
if (run_command(&cp)) {
switch (ud->update_strategy.type) {
case SM_UPDATE_CHECKOUT:
@@ -2629,7 +2519,7 @@ static int update_submodule(struct update_data *update_data)
cp.dir = update_data->sm_path;
cp.git_cmd = 1;
- prepare_submodule_repo_env(&cp.env_array);
+ prepare_submodule_repo_env(&cp.env);
update_data_to_args(&next, &cp.args);
/* die() if child process die()'d */
@@ -3122,9 +3012,9 @@ static void append_fetch_remotes(struct strbuf *msg, const char *git_dir_path)
struct strbuf sb_remote_out = STRBUF_INIT;
cp_remote.git_cmd = 1;
- strvec_pushf(&cp_remote.env_array,
+ strvec_pushf(&cp_remote.env,
"GIT_DIR=%s", git_dir_path);
- strvec_push(&cp_remote.env_array, "GIT_WORK_TREE=.");
+ strvec_push(&cp_remote.env, "GIT_WORK_TREE=.");
strvec_pushl(&cp_remote.args, "remote", "-v", NULL);
if (!capture_command(&cp_remote, &sb_remote_out, 0)) {
char *next_line;
@@ -3208,7 +3098,7 @@ static int add_submodule(const struct add_data *add_data)
if (clone_submodule(&clone_data))
return -1;
- prepare_submodule_repo_env(&cp.env_array);
+ prepare_submodule_repo_env(&cp.env);
cp.git_cmd = 1;
cp.dir = add_data->sm_path;
/*
@@ -3377,7 +3267,7 @@ static int module_add(int argc, const char **argv, const char *prefix)
N_("reference repository")),
OPT_BOOL(0, "dissociate", &dissociate, N_("borrow the objects from reference repositories")),
OPT_STRING(0, "name", &add_data.sm_name, N_("name"),
- N_("sets the submodule’s name to the given string "
+ N_("sets the submodule's name to the given string "
"instead of defaulting to its path")),
OPT_INTEGER(0, "depth", &add_data.depth, N_("depth for shallow clones")),
OPT_END()