diff options
Diffstat (limited to 'builtin/submodule--helper.c')
-rw-r--r-- | builtin/submodule--helper.c | 202 |
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() |