diff options
Diffstat (limited to 'submodule.c')
-rw-r--r-- | submodule.c | 188 |
1 files changed, 47 insertions, 141 deletions
diff --git a/submodule.c b/submodule.c index b80ecacf60..a458100ed2 100644 --- a/submodule.c +++ b/submodule.c @@ -1,4 +1,5 @@ #include "cache.h" +#include "submodule-config.h" #include "submodule.h" #include "dir.h" #include "diff.h" @@ -12,9 +13,6 @@ #include "argv-array.h" #include "blob.h" -static struct string_list config_name_for_path; -static struct string_list config_fetch_recurse_submodules_for_name; -static struct string_list config_ignore_for_name; static int config_fetch_recurse_submodules = RECURSE_SUBMODULES_ON_DEMAND; static struct string_list changed_submodule_paths; static int initialized_fetch_ref_tips; @@ -41,7 +39,6 @@ static int gitmodules_is_unmerged; */ static int gitmodules_is_modified; - int is_staging_gitmodules_ok(void) { return !gitmodules_is_modified; @@ -55,7 +52,7 @@ int is_staging_gitmodules_ok(void) int update_path_in_gitmodules(const char *oldpath, const char *newpath) { struct strbuf entry = STRBUF_INIT; - struct string_list_item *path_option; + const struct submodule *submodule; if (!file_exists(".gitmodules")) /* Do nothing without .gitmodules */ return -1; @@ -63,13 +60,13 @@ int update_path_in_gitmodules(const char *oldpath, const char *newpath) 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) { + submodule = submodule_from_path(null_sha1, oldpath); + if (!submodule || !submodule->name) { 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, submodule->name); 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 */ @@ -89,7 +86,7 @@ int update_path_in_gitmodules(const char *oldpath, const char *newpath) int remove_path_from_gitmodules(const char *path) { struct strbuf sect = STRBUF_INIT; - struct string_list_item *path_option; + const struct submodule *submodule; if (!file_exists(".gitmodules")) /* Do nothing without .gitmodules */ return -1; @@ -97,13 +94,13 @@ int remove_path_from_gitmodules(const char *path) 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) { + submodule = submodule_from_path(null_sha1, path); + if (!submodule || !submodule->name) { warning(_("Could not find section in .gitmodules where path=%s"), path); return -1; } strbuf_addstr(§, "submodule."); - strbuf_addstr(§, path_option->util); + strbuf_addstr(§, submodule->name); 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); @@ -125,20 +122,14 @@ static int add_submodule_odb(const char *path) struct strbuf objects_directory = STRBUF_INIT; struct alternate_object_database *alt_odb; int ret = 0; - const char *git_dir; - strbuf_addf(&objects_directory, "%s/.git", path); - git_dir = read_gitfile(objects_directory.buf); - if (git_dir) { - strbuf_reset(&objects_directory); - strbuf_addstr(&objects_directory, git_dir); - } - strbuf_addstr(&objects_directory, "/objects/"); + strbuf_git_path_submodule(&objects_directory, path, "objects/"); if (!is_directory(objects_directory.buf)) { ret = -1; goto done; } /* avoid adding it twice */ + prepare_alt_odb(); for (alt_odb = alt_odb_list; alt_odb; alt_odb = alt_odb->next) if (alt_odb->name - alt_odb->base == objects_directory.len && !strncmp(alt_odb->base, objects_directory.buf, @@ -156,7 +147,6 @@ static int add_submodule_odb(const char *path) /* add possible alternates from the submodule */ read_info_alternates(objects_directory.buf, 0); - prepare_alt_odb(); done: strbuf_release(&objects_directory); return ret; @@ -165,12 +155,10 @@ done: 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); + const struct submodule *submodule = submodule_from_path(null_sha1, path); + if (submodule) { + if (submodule->ignore) + handle_ignore_submodules_arg(diffopt, submodule->ignore); else if (gitmodules_is_unmerged) DIFF_OPT_SET(diffopt, IGNORE_SUBMODULES); } @@ -219,58 +207,6 @@ void gitmodules_config(void) } } -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; -} - void handle_ignore_submodules_arg(struct diff_options *diffopt, const char *arg) { @@ -301,7 +237,7 @@ static int prepare_submodule_summary(struct rev_info *rev, const char *path, left->object.flags |= SYMMETRIC_LEFT; add_pending_object(rev, &left->object, path); add_pending_object(rev, &right->object, path); - merge_bases = get_merge_bases(left, right, 1); + merge_bases = get_merge_bases(left, right); if (merge_bases) { if (merge_bases->item == left) *fast_forward = 1; @@ -345,20 +281,6 @@ static void print_submodule_summary(struct rev_info *rev, FILE *f, strbuf_release(&sb); } -int parse_fetch_recurse_submodules_arg(const char *opt, const char *arg) -{ - switch (git_config_maybe_bool(opt, arg)) { - case 1: - return RECURSE_SUBMODULES_ON; - case 0: - return RECURSE_SUBMODULES_OFF; - default: - if (!strcmp(arg, "on-demand")) - return RECURSE_SUBMODULES_ON_DEMAND; - die("bad %s argument: %s", opt, arg); - } -} - void show_submodule_summary(FILE *f, const char *path, const char *line_prefix, unsigned char one[20], unsigned char two[20], @@ -422,7 +344,8 @@ void set_config_fetch_recurse_submodules(int value) config_fetch_recurse_submodules = value; } -static int has_remote(const char *refname, const unsigned char *sha1, int flags, void *cb_data) +static int has_remote(const char *refname, const struct object_id *oid, + int flags, void *cb_data) { return 1; } @@ -433,13 +356,12 @@ static int submodule_needs_pushing(const char *path, const unsigned char sha1[20 return 0; if (for_each_remote_ref_submodule(path, has_remote, NULL) > 0) { - struct child_process cp; + struct child_process cp = CHILD_PROCESS_INIT; const char *argv[] = {"rev-list", NULL, "--not", "--remotes", "-n", "1" , NULL}; struct strbuf buf = STRBUF_INIT; int needs_pushing = 0; argv[1] = sha1_to_hex(sha1); - memset(&cp, 0, sizeof(cp)); cp.argv = argv; cp.env = local_repo_env; cp.git_cmd = 1; @@ -524,10 +446,9 @@ static int push_submodule(const char *path) return 1; if (for_each_remote_ref_submodule(path, has_remote, NULL) > 0) { - struct child_process cp; + struct child_process cp = CHILD_PROCESS_INIT; const char *argv[] = {"push", NULL}; - memset(&cp, 0, sizeof(cp)); cp.argv = argv; cp.env = local_repo_env; cp.git_cmd = 1; @@ -544,10 +465,7 @@ static int push_submodule(const char *path) int push_unpushed_submodules(unsigned char new_sha1[20], const char *remotes_name) { int i, ret = 1; - struct string_list needs_pushing; - - memset(&needs_pushing, 0, sizeof(struct string_list)); - needs_pushing.strdup_strings = 1; + struct string_list needs_pushing = STRING_LIST_INIT_DUP; if (!find_unpushed_submodules(new_sha1, remotes_name, &needs_pushing)) return 1; @@ -572,22 +490,19 @@ static int is_submodule_commit_present(const char *path, unsigned char sha1[20]) if (!add_submodule_odb(path) && lookup_commit_reference(sha1)) { /* Even if the submodule is checked out and the commit is * present, make sure it is reachable from a ref. */ - struct child_process cp; + struct child_process cp = CHILD_PROCESS_INIT; const char *argv[] = {"rev-list", "-n", "1", NULL, "--not", "--all", NULL}; struct strbuf buf = STRBUF_INIT; argv[3] = sha1_to_hex(sha1); - memset(&cp, 0, sizeof(cp)); cp.argv = argv; cp.env = local_repo_env; cp.git_cmd = 1; cp.no_stdin = 1; - cp.out = -1; cp.dir = path; - if (!run_command(&cp) && !strbuf_read(&buf, cp.out, 1024)) + if (!capture_command(&cp, &buf, 1024) && !buf.len) is_present = 1; - close(cp.out); strbuf_release(&buf); } return is_present; @@ -624,10 +539,10 @@ static void submodule_collect_changed_cb(struct diff_queue_struct *q, } } -static int add_sha1_to_array(const char *ref, const unsigned char *sha1, +static int add_sha1_to_array(const char *ref, const struct object_id *oid, int flags, void *data) { - sha1_array_append(data, sha1); + sha1_array_append(data, oid->hash); return 0; } @@ -653,7 +568,7 @@ static void calculate_changed_submodule_paths(void) struct argv_array argv = ARGV_ARRAY_INIT; /* No need to check if there are no submodules configured */ - if (!config_name_for_path.nr) + if (!submodule_from_path(NULL, NULL)) return; init_revisions(&rev, NULL); @@ -698,9 +613,8 @@ int fetch_populated_submodules(const struct argv_array *options, int quiet) { int i, result = 0; - struct child_process cp; + struct child_process cp = CHILD_PROCESS_INIT; 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; @@ -714,7 +628,6 @@ int fetch_populated_submodules(const struct argv_array *options, 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; @@ -726,24 +639,26 @@ int fetch_populated_submodules(const struct argv_array *options, 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; + const char *git_dir, *default_argv; + const struct submodule *submodule; 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; + submodule = submodule_from_path(null_sha1, ce->name); + if (!submodule) + submodule = submodule_from_name(null_sha1, ce->name); 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) + if (submodule && + submodule->fetch_recurse != + RECURSE_SUBMODULES_NONE) { + if (submodule->fetch_recurse == + RECURSE_SUBMODULES_OFF) continue; - if ((intptr_t)fetch_recurse_submodules_option->util == RECURSE_SUBMODULES_ON_DEMAND) { + if (submodule->fetch_recurse == + RECURSE_SUBMODULES_ON_DEMAND) { if (!unsorted_string_list_lookup(&changed_submodule_paths, ce->name)) continue; default_argv = "on-demand"; @@ -797,7 +712,7 @@ out: unsigned is_submodule_modified(const char *path, int ignore_untracked) { ssize_t len; - struct child_process cp; + struct child_process cp = CHILD_PROCESS_INIT; const char *argv[] = { "status", "--porcelain", @@ -824,7 +739,6 @@ unsigned is_submodule_modified(const char *path, int ignore_untracked) if (ignore_untracked) argv[2] = "-uno"; - memset(&cp, 0, sizeof(cp)); cp.argv = argv; cp.env = local_repo_env; cp.git_cmd = 1; @@ -865,7 +779,7 @@ unsigned is_submodule_modified(const char *path, int ignore_untracked) int submodule_uses_gitfile(const char *path) { - struct child_process cp; + struct child_process cp = CHILD_PROCESS_INIT; const char *argv[] = { "submodule", "foreach", @@ -886,7 +800,6 @@ int submodule_uses_gitfile(const char *path) strbuf_release(&buf); /* Now test that all nested submodules use a gitfile too */ - memset(&cp, 0, sizeof(cp)); cp.argv = argv; cp.env = local_repo_env; cp.git_cmd = 1; @@ -902,9 +815,8 @@ int submodule_uses_gitfile(const char *path) int ok_to_remove_submodule(const char *path) { - struct stat st; ssize_t len; - struct child_process cp; + struct child_process cp = CHILD_PROCESS_INIT; const char *argv[] = { "status", "--porcelain", @@ -915,13 +827,12 @@ int ok_to_remove_submodule(const char *path) struct strbuf buf = STRBUF_INIT; int ok_to_remove = 1; - if ((lstat(path, &st) < 0) || is_empty_dir(path)) + if (!file_exists(path) || is_empty_dir(path)) return 1; if (!submodule_uses_gitfile(path)) return 0; - memset(&cp, 0, sizeof(cp)); cp.argv = argv; cp.env = local_repo_env; cp.git_cmd = 1; @@ -965,7 +876,7 @@ static int find_first_merges(struct object_array *result, const char *path, sha1_to_hex(a->object.sha1)); init_revisions(&revs, NULL); rev_opts.submodule = path; - setup_revisions(sizeof(rev_args)/sizeof(char *)-1, rev_args, &revs, &rev_opts); + setup_revisions(ARRAY_SIZE(rev_args)-1, rev_args, &revs, &rev_opts); /* save all revisions from the above list that contain b */ if (prepare_revision_walk(&revs)) @@ -1005,7 +916,7 @@ static void print_commit(struct commit *commit) { struct strbuf sb = STRBUF_INIT; struct pretty_print_context ctx = {0}; - ctx.date_mode = DATE_NORMAL; + ctx.date_mode.type = DATE_NORMAL; format_commit_message(commit, " %h: %m %s", &sb, &ctx); fprintf(stderr, "%s\n", sb.buf); strbuf_release(&sb); @@ -1112,16 +1023,11 @@ void connect_work_tree_and_git_dir(const char *work_tree, const char *git_dir) struct strbuf file_name = STRBUF_INIT; struct strbuf rel_path = STRBUF_INIT; const char *real_work_tree = xstrdup(real_path(work_tree)); - FILE *fp; /* Update gitfile */ strbuf_addf(&file_name, "%s/.git", work_tree); - fp = fopen(file_name.buf, "w"); - if (!fp) - die(_("Could not create git link %s"), file_name.buf); - fprintf(fp, "gitdir: %s\n", relative_path(git_dir, real_work_tree, - &rel_path)); - fclose(fp); + write_file(file_name.buf, "gitdir: %s", + relative_path(git_dir, real_work_tree, &rel_path)); /* Update core.worktree setting */ strbuf_reset(&file_name); |