diff options
Diffstat (limited to 'submodule-config.c')
-rw-r--r-- | submodule-config.c | 187 |
1 files changed, 115 insertions, 72 deletions
diff --git a/submodule-config.c b/submodule-config.c index 393de5357e..098085be69 100644 --- a/submodule-config.c +++ b/submodule-config.c @@ -30,7 +30,7 @@ enum lookup_type { lookup_path }; -static struct submodule_cache cache; +static struct submodule_cache the_submodule_cache; static int is_cache_init; static int config_path_cmp(const struct submodule_entry *a, @@ -59,6 +59,8 @@ static void free_one_config(struct submodule_entry *entry) { free((void *) entry->config->path); free((void *) entry->config->name); + free((void *) entry->config->branch); + free((void *) entry->config->update_strategy.command); free(entry->config); } @@ -194,8 +196,12 @@ static struct submodule *lookup_or_create_by_name(struct submodule_cache *cache, submodule->path = NULL; submodule->url = NULL; + submodule->update_strategy.type = SM_UPDATE_UNSPECIFIED; + submodule->update_strategy.command = NULL; submodule->fetch_recurse = RECURSE_SUBMODULES_NONE; submodule->ignore = NULL; + submodule->branch = NULL; + submodule->recommend_shallow = -1; hashcpy(submodule->gitmodules_sha1, gitmodules_sha1); @@ -228,6 +234,35 @@ int parse_fetch_recurse_submodules_arg(const char *opt, const char *arg) return parse_fetch_recurse(opt, arg, 1); } +static int parse_push_recurse(const char *opt, const char *arg, + int die_on_error) +{ + switch (git_config_maybe_bool(opt, arg)) { + case 1: + /* There's no simple "on" value when pushing */ + if (die_on_error) + die("bad %s argument: %s", opt, arg); + else + return RECURSE_SUBMODULES_ERROR; + case 0: + return RECURSE_SUBMODULES_OFF; + default: + if (!strcmp(arg, "on-demand")) + return RECURSE_SUBMODULES_ON_DEMAND; + else if (!strcmp(arg, "check")) + return RECURSE_SUBMODULES_CHECK; + else if (die_on_error) + die("bad %s argument: %s", opt, arg); + else + return RECURSE_SUBMODULES_ERROR; + } +} + +int parse_push_recurse_submodules_arg(const char *opt, const char *arg) +{ + return parse_push_recurse(opt, arg, 1); +} + static void warn_multiple_config(const unsigned char *commit_sha1, const char *name, const char *option) { @@ -257,78 +292,87 @@ static int parse_config(const char *var, const char *value, void *data) if (!name_and_item_from_var(var, &name, &item)) return 0; - submodule = lookup_or_create_by_name(me->cache, me->gitmodules_sha1, - name.buf); + submodule = lookup_or_create_by_name(me->cache, + me->gitmodules_sha1, + name.buf); if (!strcmp(item.buf, "path")) { - struct strbuf path = STRBUF_INIT; - if (!value) { + if (!value) ret = config_error_nonbool(var); - goto release_return; - } - if (!me->overwrite && submodule->path != NULL) { + else if (!me->overwrite && submodule->path) warn_multiple_config(me->commit_sha1, submodule->name, "path"); - goto release_return; + else { + if (submodule->path) + cache_remove_path(me->cache, submodule); + free((void *) submodule->path); + submodule->path = xstrdup(value); + cache_put_path(me->cache, submodule); } - - if (submodule->path) - cache_remove_path(me->cache, submodule); - free((void *) submodule->path); - strbuf_addstr(&path, value); - submodule->path = strbuf_detach(&path, NULL); - cache_put_path(me->cache, submodule); } else if (!strcmp(item.buf, "fetchrecursesubmodules")) { /* when parsing worktree configurations we can die early */ int die_on_error = is_null_sha1(me->gitmodules_sha1); if (!me->overwrite && - submodule->fetch_recurse != RECURSE_SUBMODULES_NONE) { + submodule->fetch_recurse != RECURSE_SUBMODULES_NONE) warn_multiple_config(me->commit_sha1, submodule->name, "fetchrecursesubmodules"); - goto release_return; - } - - submodule->fetch_recurse = parse_fetch_recurse(var, value, + else + submodule->fetch_recurse = parse_fetch_recurse( + var, value, die_on_error); } else if (!strcmp(item.buf, "ignore")) { - struct strbuf ignore = STRBUF_INIT; - if (!me->overwrite && submodule->ignore != NULL) { + if (!value) + ret = config_error_nonbool(var); + else if (!me->overwrite && submodule->ignore) warn_multiple_config(me->commit_sha1, submodule->name, "ignore"); - goto release_return; - } - if (!value) { - ret = config_error_nonbool(var); - goto release_return; - } - if (strcmp(value, "untracked") && strcmp(value, "dirty") && - strcmp(value, "all") && strcmp(value, "none")) { + else 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); - goto release_return; + else { + free((void *) submodule->ignore); + submodule->ignore = xstrdup(value); } - - free((void *) submodule->ignore); - strbuf_addstr(&ignore, value); - submodule->ignore = strbuf_detach(&ignore, NULL); } else if (!strcmp(item.buf, "url")) { - struct strbuf url = STRBUF_INIT; if (!value) { ret = config_error_nonbool(var); - goto release_return; - } - if (!me->overwrite && submodule->url != NULL) { + } else if (!me->overwrite && submodule->url) { warn_multiple_config(me->commit_sha1, submodule->name, "url"); - goto release_return; + } else { + free((void *) submodule->url); + submodule->url = xstrdup(value); + } + } else if (!strcmp(item.buf, "update")) { + if (!value) + ret = config_error_nonbool(var); + else if (!me->overwrite && + submodule->update_strategy.type != SM_UPDATE_UNSPECIFIED) + warn_multiple_config(me->commit_sha1, submodule->name, + "update"); + else if (parse_submodule_update_strategy(value, + &submodule->update_strategy) < 0) + die(_("invalid value for %s"), var); + } else if (!strcmp(item.buf, "shallow")) { + if (!me->overwrite && submodule->recommend_shallow != -1) + warn_multiple_config(me->commit_sha1, submodule->name, + "shallow"); + else + submodule->recommend_shallow = + git_config_bool(var, value); + } else if (!strcmp(item.buf, "branch")) { + if (!me->overwrite && submodule->branch) + warn_multiple_config(me->commit_sha1, submodule->name, + "branch"); + else { + free((void *)submodule->branch); + submodule->branch = xstrdup(value); } - - free((void *) submodule->url); - strbuf_addstr(&url, value); - submodule->url = strbuf_detach(&url, NULL); } -release_return: strbuf_release(&name); strbuf_release(&item); @@ -336,21 +380,20 @@ release_return: } static int gitmodule_sha1_from_commit(const unsigned char *commit_sha1, - unsigned char *gitmodules_sha1) + unsigned char *gitmodules_sha1, + struct strbuf *rev) { - struct strbuf rev = STRBUF_INIT; int ret = 0; if (is_null_sha1(commit_sha1)) { - hashcpy(gitmodules_sha1, null_sha1); + hashclr(gitmodules_sha1); return 1; } - strbuf_addf(&rev, "%s:.gitmodules", sha1_to_hex(commit_sha1)); - if (get_sha1(rev.buf, gitmodules_sha1) >= 0) + strbuf_addf(rev, "%s:.gitmodules", sha1_to_hex(commit_sha1)); + if (get_sha1(rev->buf, gitmodules_sha1) >= 0) ret = 1; - strbuf_release(&rev); return ret; } @@ -364,7 +407,7 @@ static const struct submodule *config_from(struct submodule_cache *cache, { struct strbuf rev = STRBUF_INIT; unsigned long config_size; - char *config; + char *config = NULL; unsigned char sha1[20]; enum object_type type; const struct submodule *submodule = NULL; @@ -379,15 +422,14 @@ static const struct submodule *config_from(struct submodule_cache *cache, struct hashmap_iter iter; struct submodule_entry *entry; - hashmap_iter_init(&cache->for_name, &iter); - entry = hashmap_iter_next(&iter); + entry = hashmap_iter_first(&cache->for_name, &iter); if (!entry) return NULL; return entry->config; } - if (!gitmodule_sha1_from_commit(commit_sha1, sha1)) - return NULL; + if (!gitmodule_sha1_from_commit(commit_sha1, sha1, &rev)) + goto out; switch (lookup_type) { case lookup_name: @@ -398,24 +440,20 @@ static const struct submodule *config_from(struct submodule_cache *cache, break; } if (submodule) - return submodule; + goto out; config = read_sha1_file(sha1, &type, &config_size); - if (!config) - return NULL; - - if (type != OBJ_BLOB) { - free(config); - return NULL; - } + if (!config || type != OBJ_BLOB) + goto out; /* fill the submodule config into the cache */ parameter.cache = cache; parameter.commit_sha1 = commit_sha1; parameter.gitmodules_sha1 = sha1; parameter.overwrite = 0; - git_config_from_buf(parse_config, rev.buf, config, config_size, - ¶meter); + git_config_from_mem(parse_config, CONFIG_ORIGIN_SUBMODULE_BLOB, rev.buf, + config, config_size, ¶meter); + strbuf_release(&rev); free(config); switch (lookup_type) { @@ -426,6 +464,11 @@ static const struct submodule *config_from(struct submodule_cache *cache, default: return NULL; } + +out: + strbuf_release(&rev); + free(config); + return submodule; } static const struct submodule *config_from_path(struct submodule_cache *cache, @@ -445,14 +488,14 @@ static void ensure_cache_init(void) if (is_cache_init) return; - cache_init(&cache); + cache_init(&the_submodule_cache); is_cache_init = 1; } int parse_submodule_config_option(const char *var, const char *value) { struct parse_config_parameter parameter; - parameter.cache = &cache; + parameter.cache = &the_submodule_cache; parameter.commit_sha1 = NULL; parameter.gitmodules_sha1 = null_sha1; parameter.overwrite = 1; @@ -465,18 +508,18 @@ const struct submodule *submodule_from_name(const unsigned char *commit_sha1, const char *name) { ensure_cache_init(); - return config_from_name(&cache, commit_sha1, name); + return config_from_name(&the_submodule_cache, commit_sha1, name); } const struct submodule *submodule_from_path(const unsigned char *commit_sha1, const char *path) { ensure_cache_init(); - return config_from_path(&cache, commit_sha1, path); + return config_from_path(&the_submodule_cache, commit_sha1, path); } void submodule_free(void) { - cache_free(&cache); + cache_free(&the_submodule_cache); is_cache_init = 0; } |