void set_diffopt_flags_from_submodule_config(struct diff_options *diffopt, const char *path) { struct string_list_item *path_option, *ignore_option; path_option = unsorted_string_list_lookup(&config_name_for_path, path); if (path_option) { ignore_option = unsorted_string_list_lookup(&config_ignore_for_name, path_option->util); if (ignore_option) handle_ignore_submodules_arg(diffopt, ignore_option->util); } }
void set_diffopt_flags_from_submodule_config(struct diff_options *diffopt, const char *path) { struct string_list_item *path_option, *ignore_option; path_option = unsorted_string_list_lookup(&config_name_for_path, path); if (path_option) { ignore_option = unsorted_string_list_lookup(&config_ignore_for_name, path_option->util); if (ignore_option) handle_ignore_submodules_arg(diffopt, ignore_option->util); else if (gitmodules_is_unmerged) DIFF_OPT_SET(diffopt, IGNORE_SUBMODULES); } }
int parse_submodule_config_option(const char *var, const char *value) { struct string_list_item *config; const char *name, *key; int namelen; if (parse_config_key(var, "submodule", &name, &namelen, &key) < 0 || !name) return 0; if (!strcmp(key, "path")) { if (!value) return config_error_nonbool(var); config = unsorted_string_list_lookup(&config_name_for_path, value); if (config) free(config->util); else config = string_list_append(&config_name_for_path, xstrdup(value)); config->util = xmemdupz(name, namelen); } else if (!strcmp(key, "fetchrecursesubmodules")) { char *name_cstr = xmemdupz(name, namelen); config = unsorted_string_list_lookup(&config_fetch_recurse_submodules_for_name, name_cstr); if (!config) config = string_list_append(&config_fetch_recurse_submodules_for_name, name_cstr); else free(name_cstr); config->util = (void *)(intptr_t)parse_fetch_recurse_submodules_arg(var, value); } else if (!strcmp(key, "ignore")) { char *name_cstr; if (!value) return config_error_nonbool(var); if (strcmp(value, "untracked") && strcmp(value, "dirty") && strcmp(value, "all") && strcmp(value, "none")) { warning("Invalid parameter \"%s\" for config option \"submodule.%s.ignore\"", value, var); return 0; } name_cstr = xmemdupz(name, namelen); config = unsorted_string_list_lookup(&config_ignore_for_name, name_cstr); if (config) { free(config->util); free(name_cstr); } else config = string_list_append(&config_ignore_for_name, name_cstr); config->util = xstrdup(value); return 0; } return 0; }
static void submodule_collect_changed_cb(struct diff_queue_struct *q, struct diff_options *options, void *data) { int i; for (i = 0; i < q->nr; i++) { struct diff_filepair *p = q->queue[i]; if (!S_ISGITLINK(p->two->mode)) continue; if (S_ISGITLINK(p->one->mode)) { /* NEEDSWORK: We should honor the name configured in * the .gitmodules file of the commit we are examining * here to be able to correctly follow submodules * being moved around. */ struct string_list_item *path; path = unsorted_string_list_lookup(&changed_submodule_paths, p->two->path); if (!path && !is_submodule_commit_present(p->two->path, p->two->sha1)) string_list_append(&changed_submodule_paths, xstrdup(p->two->path)); } else { /* Submodule is new or was moved here */ /* NEEDSWORK: When the .git directories of submodules * live inside the superprojects .git directory some * day we should fetch new submodules directly into * that location too when config or options request * that so they can be checked out from there. */ continue; } } }
/* * Try to remove the "submodule.<name>" section from .gitmodules where the given * path is configured. Return 0 only if a .gitmodules file was found, a section * with the correct path=<path> setting was found and we could remove it. */ int remove_path_from_gitmodules(const char *path) { struct strbuf sect = STRBUF_INIT; struct string_list_item *path_option; if (!file_exists(".gitmodules")) /* Do nothing without .gitmodules */ return -1; if (gitmodules_is_unmerged) die(_("Cannot change unmerged .gitmodules, resolve merge conflicts first")); path_option = unsorted_string_list_lookup(&config_name_for_path, path); if (!path_option) { warning(_("Could not find section in .gitmodules where path=%s"), path); return -1; } strbuf_addstr(§, "submodule."); strbuf_addstr(§, path_option->util); if (git_config_rename_section_in_file(".gitmodules", sect.buf, NULL) < 0) { /* Maybe the user already did that, don't error out here */ warning(_("Could not remove .gitmodules entry for %s"), path); strbuf_release(§); return -1; } strbuf_release(§); return 0; }
/* * Try to update the "path" entry in the "submodule.<name>" section of the * .gitmodules file. Return 0 only if a .gitmodules file was found, a section * with the correct path=<oldpath> setting was found and we could update it. */ int update_path_in_gitmodules(const char *oldpath, const char *newpath) { struct strbuf entry = STRBUF_INIT; struct string_list_item *path_option; if (!file_exists(".gitmodules")) /* Do nothing without .gitmodules */ return -1; if (gitmodules_is_unmerged) die(_("Cannot change unmerged .gitmodules, resolve merge conflicts first")); path_option = unsorted_string_list_lookup(&config_name_for_path, oldpath); if (!path_option) { warning(_("Could not find section in .gitmodules where path=%s"), oldpath); return -1; } strbuf_addstr(&entry, "submodule."); strbuf_addstr(&entry, path_option->util); strbuf_addstr(&entry, ".path"); if (git_config_set_in_file(".gitmodules", entry.buf, newpath) < 0) { /* Maybe the user already did that, don't error out here */ warning(_("Could not update .gitmodules entry %s"), entry.buf); strbuf_release(&entry); return -1; } strbuf_release(&entry); return 0; }
int populate_submodule(const char *path, unsigned char sha1[20], int force) { struct string_list_item *path_option; const char *name, *real_git_dir; struct strbuf buf = STRBUF_INIT; struct child_process cp; const char *argv[] = {"read-tree", force ? "--reset" : "-m", "-u", NULL, NULL}; path_option = unsorted_string_list_lookup(&config_name_for_path, path); if (!path_option) return 0; name = path_option->util; strbuf_addf(&buf, "%s/modules/%s", resolve_gitdir(get_git_dir()), name); real_git_dir = resolve_gitdir(buf.buf); if (!real_git_dir) goto out; connect_work_tree_and_git_dir(path, real_git_dir); /* Run read-tree --reset sha1 */ memset(&cp, 0, sizeof(cp)); cp.argv = argv; cp.env = local_repo_env; cp.git_cmd = 1; cp.no_stdin = 1; cp.dir = path; argv[3] = sha1_to_hex(sha1); if (run_command(&cp)) warning(_("Checking out submodule %s failed"), path); out: strbuf_release(&buf); return 0; }
int parse_submodule_config_option(const char *var, const char *value) { int len; struct string_list_item *config; struct strbuf submodname = STRBUF_INIT; var += 10; /* Skip "submodule." */ len = strlen(var); if ((len > 5) && !strcmp(var + len - 5, ".path")) { strbuf_add(&submodname, var, len - 5); config = unsorted_string_list_lookup(&config_name_for_path, value); if (config) free(config->util); else config = string_list_append(&config_name_for_path, xstrdup(value)); config->util = strbuf_detach(&submodname, NULL); strbuf_release(&submodname); } else if ((len > 23) && !strcmp(var + len - 23, ".fetchrecursesubmodules")) { strbuf_add(&submodname, var, len - 23); config = unsorted_string_list_lookup(&config_fetch_recurse_submodules_for_name, submodname.buf); if (!config) config = string_list_append(&config_fetch_recurse_submodules_for_name, strbuf_detach(&submodname, NULL)); config->util = (void *)(intptr_t)parse_fetch_recurse_submodules_arg(var, value); strbuf_release(&submodname); } else if ((len > 7) && !strcmp(var + len - 7, ".ignore")) { if (strcmp(value, "untracked") && strcmp(value, "dirty") && strcmp(value, "all") && strcmp(value, "none")) { warning("Invalid parameter \"%s\" for config option \"submodule.%s.ignore\"", value, var); return 0; } strbuf_add(&submodname, var, len - 7); config = unsorted_string_list_lookup(&config_ignore_for_name, submodname.buf); if (config) free(config->util); else config = string_list_append(&config_ignore_for_name, strbuf_detach(&submodname, NULL)); strbuf_release(&submodname); config->util = xstrdup(value); return 0; } return 0; }
int submodule_needs_update(const char *path) { struct string_list_item *path_option; path_option = unsorted_string_list_lookup(&config_name_for_path, path); if (!path_option) return 0; /* update can't be "none", "merge" or "rebase" */ if (option_update_recurse_submodules != RECURSE_SUBMODULES_DEFAULT) return 1; return config_update_recurse_submodules != RECURSE_SUBMODULES_OFF; }
static int handle_line(char *line, struct merge_parents *merge_parents) { int i, len = strlen(line); struct origin_data *origin_data; char *src, *origin; struct src_data *src_data; struct string_list_item *item; int pulling_head = 0; unsigned char sha1[20]; if (len < 43 || line[40] != '\t') return 1; if (!prefixcmp(line + 41, "not-for-merge")) return 0; if (line[41] != '\t') return 2; i = get_sha1_hex(line, sha1); if (i) return 3; if (!find_merge_parent(merge_parents, sha1, NULL)) return 0; /* subsumed by other parents */ origin_data = xcalloc(1, sizeof(struct origin_data)); hashcpy(origin_data->sha1, sha1); if (line[len - 1] == '\n') line[len - 1] = 0; line += 42; /* * At this point, line points at the beginning of comment e.g. * "branch 'frotz' of git://that/repository.git". * Find the repository name and point it with src. */ src = strstr(line, " of "); if (src) { *src = 0; src += 4; pulling_head = 0; } else { src = line; pulling_head = 1; } item = unsorted_string_list_lookup(&srcs, src); if (!item) { item = string_list_append(&srcs, src); item->util = xcalloc(1, sizeof(struct src_data)); init_src_data(item->util); } src_data = item->util; if (pulling_head) { origin = src; src_data->head_status |= 1; } else if (!prefixcmp(line, "branch ")) { origin_data->is_local_branch = 1; origin = line + 7; string_list_append(&src_data->branch, origin); src_data->head_status |= 2; } else if (!prefixcmp(line, "tag ")) { origin = line; string_list_append(&src_data->tag, origin + 4); src_data->head_status |= 2; } else if (!prefixcmp(line, "remote-tracking branch ")) { origin = line + strlen("remote-tracking branch "); string_list_append(&src_data->r_branch, origin); src_data->head_status |= 2; } else { origin = src; string_list_append(&src_data->generic, line); src_data->head_status |= 2; } if (!strcmp(".", src) || !strcmp(src, origin)) { int len = strlen(origin); if (origin[0] == '\'' && origin[len - 1] == '\'') origin = xmemdupz(origin + 1, len - 2); } else { char *new_origin = xmalloc(strlen(origin) + strlen(src) + 5); sprintf(new_origin, "%s of %s", origin, src); origin = new_origin; } if (strcmp(".", src)) origin_data->is_local_branch = 0; string_list_append(&origins, origin)->util = origin_data; return 0; }
int fetch_populated_submodules(int num_options, const char **options, const char *prefix, int command_line_option, int quiet) { int i, result = 0, argc = 0, default_argc; struct child_process cp; const char **argv; struct string_list_item *name_for_path; const char *work_tree = get_git_work_tree(); if (!work_tree) goto out; if (!the_index.initialized) if (read_cache() < 0) die("index file corrupt"); /* 6: "fetch" (options) --recurse-submodules-default default "--submodule-prefix" prefix NULL */ argv = xcalloc(num_options + 6, sizeof(const char *)); argv[argc++] = "fetch"; for (i = 0; i < num_options; i++) argv[argc++] = options[i]; argv[argc++] = "--recurse-submodules-default"; default_argc = argc++; argv[argc++] = "--submodule-prefix"; memset(&cp, 0, sizeof(cp)); cp.argv = argv; cp.env = local_repo_env; cp.git_cmd = 1; cp.no_stdin = 1; calculate_changed_submodule_paths(); for (i = 0; i < active_nr; i++) { struct strbuf submodule_path = STRBUF_INIT; struct strbuf submodule_git_dir = STRBUF_INIT; struct strbuf submodule_prefix = STRBUF_INIT; struct cache_entry *ce = active_cache[i]; const char *git_dir, *name, *default_argv; if (!S_ISGITLINK(ce->ce_mode)) continue; name = ce->name; name_for_path = unsorted_string_list_lookup(&config_name_for_path, ce->name); if (name_for_path) name = name_for_path->util; default_argv = "yes"; if (command_line_option == RECURSE_SUBMODULES_DEFAULT) { struct string_list_item *fetch_recurse_submodules_option; fetch_recurse_submodules_option = unsorted_string_list_lookup(&config_fetch_recurse_submodules_for_name, name); if (fetch_recurse_submodules_option) { if ((intptr_t)fetch_recurse_submodules_option->util == RECURSE_SUBMODULES_OFF) continue; if ((intptr_t)fetch_recurse_submodules_option->util == RECURSE_SUBMODULES_ON_DEMAND) { if (!unsorted_string_list_lookup(&changed_submodule_paths, ce->name)) continue; default_argv = "on-demand"; } } else { if ((config_fetch_recurse_submodules == RECURSE_SUBMODULES_OFF) || gitmodules_is_unmerged) continue; if (config_fetch_recurse_submodules == RECURSE_SUBMODULES_ON_DEMAND) { if (!unsorted_string_list_lookup(&changed_submodule_paths, ce->name)) continue; default_argv = "on-demand"; } } } else if (command_line_option == RECURSE_SUBMODULES_ON_DEMAND) { if (!unsorted_string_list_lookup(&changed_submodule_paths, ce->name)) continue; default_argv = "on-demand"; } strbuf_addf(&submodule_path, "%s/%s", work_tree, ce->name); strbuf_addf(&submodule_git_dir, "%s/.git", submodule_path.buf); strbuf_addf(&submodule_prefix, "%s%s/", prefix, ce->name); git_dir = read_gitfile(submodule_git_dir.buf); if (!git_dir) git_dir = submodule_git_dir.buf; if (is_directory(git_dir)) { if (!quiet) printf("Fetching submodule %s%s\n", prefix, ce->name); cp.dir = submodule_path.buf; argv[default_argc] = default_argv; argv[argc] = submodule_prefix.buf; if (run_command(&cp)) result = 1; } strbuf_release(&submodule_path); strbuf_release(&submodule_git_dir); strbuf_release(&submodule_prefix); } free(argv); out: string_list_clear(&changed_submodule_paths, 1); return result; }
int fetch_populated_submodules(const struct argv_array *options, const char *prefix, int command_line_option, int quiet) { int i, result = 0; struct child_process cp; struct argv_array argv = ARGV_ARRAY_INIT; struct string_list_item *name_for_path; const char *work_tree = get_git_work_tree(); if (!work_tree) goto out; if (read_cache() < 0) die("index file corrupt"); argv_array_push(&argv, "fetch"); for (i = 0; i < options->argc; i++) argv_array_push(&argv, options->argv[i]); argv_array_push(&argv, "--recurse-submodules-default"); /* default value, "--submodule-prefix" and its value are added later */ memset(&cp, 0, sizeof(cp)); cp.env = local_repo_env; cp.git_cmd = 1; cp.no_stdin = 1; calculate_changed_submodule_paths(); for (i = 0; i < active_nr; i++) { struct strbuf submodule_path = STRBUF_INIT; struct strbuf submodule_git_dir = STRBUF_INIT; struct strbuf submodule_prefix = STRBUF_INIT; const struct cache_entry *ce = active_cache[i]; const char *git_dir, *name, *default_argv; if (!S_ISGITLINK(ce->ce_mode)) continue; name = ce->name; name_for_path = unsorted_string_list_lookup(&config_name_for_path, ce->name); if (name_for_path) name = name_for_path->util; default_argv = "yes"; if (command_line_option == RECURSE_SUBMODULES_DEFAULT) { struct string_list_item *fetch_recurse_submodules_option; fetch_recurse_submodules_option = unsorted_string_list_lookup(&config_fetch_recurse_submodules_for_name, name); if (fetch_recurse_submodules_option) { if ((intptr_t)fetch_recurse_submodules_option->util == RECURSE_SUBMODULES_OFF) continue; if ((intptr_t)fetch_recurse_submodules_option->util == RECURSE_SUBMODULES_ON_DEMAND) { if (!unsorted_string_list_lookup(&changed_submodule_paths, ce->name)) continue; default_argv = "on-demand"; } } else { if ((config_fetch_recurse_submodules == RECURSE_SUBMODULES_OFF) || gitmodules_is_unmerged) continue; if (config_fetch_recurse_submodules == RECURSE_SUBMODULES_ON_DEMAND) { if (!unsorted_string_list_lookup(&changed_submodule_paths, ce->name)) continue; default_argv = "on-demand"; } } } else if (command_line_option == RECURSE_SUBMODULES_ON_DEMAND) { if (!unsorted_string_list_lookup(&changed_submodule_paths, ce->name)) continue; default_argv = "on-demand"; } strbuf_addf(&submodule_path, "%s/%s", work_tree, ce->name); strbuf_addf(&submodule_git_dir, "%s/.git", submodule_path.buf); strbuf_addf(&submodule_prefix, "%s%s/", prefix, ce->name); git_dir = read_gitfile(submodule_git_dir.buf); if (!git_dir) git_dir = submodule_git_dir.buf; if (is_directory(git_dir)) { if (!quiet) printf("Fetching submodule %s%s\n", prefix, ce->name); cp.dir = submodule_path.buf; argv_array_push(&argv, default_argv); argv_array_push(&argv, "--submodule-prefix"); argv_array_push(&argv, submodule_prefix.buf); cp.argv = argv.argv; if (run_command(&cp)) result = 1; argv_array_pop(&argv); argv_array_pop(&argv); argv_array_pop(&argv); } strbuf_release(&submodule_path); strbuf_release(&submodule_git_dir); strbuf_release(&submodule_prefix); } argv_array_clear(&argv); out: string_list_clear(&changed_submodule_paths, 1); return result; }
int unsorted_string_list_has_string(struct string_list *list, const char *string) { return unsorted_string_list_lookup(list, string) != NULL; }
static int handle_line(char *line) { int i, len = strlen(line); unsigned char *sha1; char *src, *origin; struct src_data *src_data; struct string_list_item *item; int pulling_head = 0; if (len < 43 || line[40] != '\t') return 1; if (!prefixcmp(line + 41, "not-for-merge")) return 0; if (line[41] != '\t') return 2; line[40] = 0; sha1 = xmalloc(20); i = get_sha1(line, sha1); line[40] = '\t'; if (i) return 3; if (line[len - 1] == '\n') line[len - 1] = 0; line += 42; src = strstr(line, " of "); if (src) { *src = 0; src += 4; pulling_head = 0; } else { src = line; pulling_head = 1; } item = unsorted_string_list_lookup(&srcs, src); if (!item) { item = string_list_append(&srcs, src); item->util = xcalloc(1, sizeof(struct src_data)); init_src_data(item->util); } src_data = item->util; if (pulling_head) { origin = src; src_data->head_status |= 1; } else if (!prefixcmp(line, "branch ")) { origin = line + 7; string_list_append(&src_data->branch, origin); src_data->head_status |= 2; } else if (!prefixcmp(line, "tag ")) { origin = line; string_list_append(&src_data->tag, origin + 4); src_data->head_status |= 2; } else if (!prefixcmp(line, "remote-tracking branch ")) { origin = line + strlen("remote-tracking branch "); string_list_append(&src_data->r_branch, origin); src_data->head_status |= 2; } else { origin = src; string_list_append(&src_data->generic, line); src_data->head_status |= 2; } if (!strcmp(".", src) || !strcmp(src, origin)) { int len = strlen(origin); if (origin[0] == '\'' && origin[len - 1] == '\'') origin = xmemdupz(origin + 1, len - 2); } else { char *new_origin = xmalloc(strlen(origin) + strlen(src) + 5); sprintf(new_origin, "%s of %s", origin, src); origin = new_origin; } string_list_append(&origins, origin)->util = sha1; return 0; }
static int get_next_submodule(struct child_process *cp, struct strbuf *err, void *data, void **task_cb) { int ret = 0; struct submodule_parallel_fetch *spf = data; for (; spf->count < active_nr; spf->count++) { struct strbuf submodule_path = STRBUF_INIT; struct strbuf submodule_git_dir = STRBUF_INIT; struct strbuf submodule_prefix = STRBUF_INIT; const struct cache_entry *ce = active_cache[spf->count]; const char *git_dir, *default_argv; const struct submodule *submodule; if (!S_ISGITLINK(ce->ce_mode)) continue; submodule = submodule_from_path(null_sha1, ce->name); if (!submodule) submodule = submodule_from_name(null_sha1, ce->name); default_argv = "yes"; if (spf->command_line_option == RECURSE_SUBMODULES_DEFAULT) { if (submodule && submodule->fetch_recurse != RECURSE_SUBMODULES_NONE) { if (submodule->fetch_recurse == RECURSE_SUBMODULES_OFF) continue; if (submodule->fetch_recurse == RECURSE_SUBMODULES_ON_DEMAND) { if (!unsorted_string_list_lookup(&changed_submodule_paths, ce->name)) continue; default_argv = "on-demand"; } } else { if ((config_fetch_recurse_submodules == RECURSE_SUBMODULES_OFF) || gitmodules_is_unmerged) continue; if (config_fetch_recurse_submodules == RECURSE_SUBMODULES_ON_DEMAND) { if (!unsorted_string_list_lookup(&changed_submodule_paths, ce->name)) continue; default_argv = "on-demand"; } } } else if (spf->command_line_option == RECURSE_SUBMODULES_ON_DEMAND) { if (!unsorted_string_list_lookup(&changed_submodule_paths, ce->name)) continue; default_argv = "on-demand"; } strbuf_addf(&submodule_path, "%s/%s", spf->work_tree, ce->name); strbuf_addf(&submodule_git_dir, "%s/.git", submodule_path.buf); strbuf_addf(&submodule_prefix, "%s%s/", spf->prefix, ce->name); git_dir = read_gitfile(submodule_git_dir.buf); if (!git_dir) git_dir = submodule_git_dir.buf; if (is_directory(git_dir)) { child_process_init(cp); cp->dir = strbuf_detach(&submodule_path, NULL); cp->env = local_repo_env; cp->git_cmd = 1; if (!spf->quiet) strbuf_addf(err, "Fetching submodule %s%s\n", spf->prefix, ce->name); argv_array_init(&cp->args); argv_array_pushv(&cp->args, spf->args.argv); argv_array_push(&cp->args, default_argv); argv_array_push(&cp->args, "--submodule-prefix"); argv_array_push(&cp->args, submodule_prefix.buf); ret = 1; } strbuf_release(&submodule_path); strbuf_release(&submodule_git_dir); strbuf_release(&submodule_prefix); if (ret) { spf->count++; return 1; } } return 0; }
int fetch_populated_submodules(int num_options, const char **options, const char *prefix, int ignore_config, int quiet) { int i, result = 0, argc = 0; struct child_process cp; const char **argv; struct string_list_item *name_for_path; const char *work_tree = get_git_work_tree(); if (!work_tree) return 0; if (!the_index.initialized) if (read_cache() < 0) die("index file corrupt"); /* 4: "fetch" (options) "--submodule-prefix" prefix NULL */ argv = xcalloc(num_options + 4, sizeof(const char *)); argv[argc++] = "fetch"; for (i = 0; i < num_options; i++) argv[argc++] = options[i]; argv[argc++] = "--submodule-prefix"; memset(&cp, 0, sizeof(cp)); cp.argv = argv; cp.env = local_repo_env; cp.git_cmd = 1; cp.no_stdin = 1; for (i = 0; i < active_nr; i++) { struct strbuf submodule_path = STRBUF_INIT; struct strbuf submodule_git_dir = STRBUF_INIT; struct strbuf submodule_prefix = STRBUF_INIT; struct cache_entry *ce = active_cache[i]; const char *git_dir, *name; if (!S_ISGITLINK(ce->ce_mode)) continue; name = ce->name; name_for_path = unsorted_string_list_lookup(&config_name_for_path, ce->name); if (name_for_path) name = name_for_path->util; if (!ignore_config) { struct string_list_item *fetch_recurse_submodules_option; fetch_recurse_submodules_option = unsorted_string_list_lookup(&config_fetch_recurse_submodules_for_name, name); if (fetch_recurse_submodules_option) { if (!fetch_recurse_submodules_option->util) continue; } else { if (!config_fetch_recurse_submodules) continue; } } strbuf_addf(&submodule_path, "%s/%s", work_tree, ce->name); strbuf_addf(&submodule_git_dir, "%s/.git", submodule_path.buf); strbuf_addf(&submodule_prefix, "%s%s/", prefix, ce->name); git_dir = read_gitfile_gently(submodule_git_dir.buf); if (!git_dir) git_dir = submodule_git_dir.buf; if (is_directory(git_dir)) { if (!quiet) printf("Fetching submodule %s%s\n", prefix, ce->name); cp.dir = submodule_path.buf; argv[argc] = submodule_prefix.buf; if (run_command(&cp)) result = 1; } strbuf_release(&submodule_path); strbuf_release(&submodule_git_dir); strbuf_release(&submodule_prefix); } free(argv); return result; }