diff options
author | Carlos Martín Nieto <cmn@dwim.me> | 2015-05-14 17:55:30 +0200 |
---|---|---|
committer | Carlos Martín Nieto <cmn@dwim.me> | 2015-05-14 17:55:30 +0200 |
commit | 521a8da64c1e84c6a2999d71ad53ee24cdd4a1a1 (patch) | |
tree | 624458a9402198e754bec4bea40f56e2f592437b | |
parent | 542a7de0cdbed72f04a30db6f3ed1352b2169381 (diff) | |
download | libgit2-cmn/forbid-mutiurl.tar.gz |
remote: refuse to load multi-url remotescmn/forbid-mutiurl
A remote can have more than a single entry in url or pushurl. Git uses
this to perform multiple fetches or pushes, which can be useful for
redundancy, but we currently cannot handle this.
What we would do is fetch from or push to the last of the urls (as we
consider them single-value fields), which would at best be confusing,
but would also break the user's expectations.
in order to avoid this, check whether the remote we're trying to lookup
has mutliple urls and refuse to load it.
-rw-r--r-- | src/remote.c | 58 |
1 files changed, 47 insertions, 11 deletions
diff --git a/src/remote.c b/src/remote.c index 44885bd17..1de5af4ab 100644 --- a/src/remote.c +++ b/src/remote.c @@ -408,14 +408,42 @@ static int get_optional_config( return error; } +struct url_cb_data { + char *val; + int nurls; + bool fetch; +}; + +static int url_cb(const git_config_entry *entry, void *payload) +{ + struct url_cb_data *data = payload; + + if (data->nurls > 0) { + giterr_set(GITERR_NET, "remotes with more than one url are not supported"); + return -1; + } + + if (!entry->value) { + giterr_set(GITERR_NET, "invalid value for %s", data->fetch ? "url" : "pushurl"); + return -1; + } + + data->val = git__strdup(entry->value); + GITERR_CHECK_ALLOC(data->val); + data->nurls++; + + return 0; +} + int git_remote_lookup(git_remote **out, git_repository *repo, const char *name) { git_remote *remote; git_buf buf = GIT_BUF_INIT; - const char *val; + char *val; int error = 0; git_config *config; struct refspec_cb_data data = { NULL }; + struct url_cb_data url_data; bool optional_setting_found = false, found; assert(out && repo && name); @@ -443,26 +471,34 @@ int git_remote_lookup(git_remote **out, git_repository *repo, const char *name) if ((error = git_buf_printf(&buf, "remote.%s.url", name)) < 0) goto cleanup; - if ((error = get_optional_config(&found, config, &buf, NULL, (void *)&val)) < 0) + url_data.val = NULL; + url_data.nurls = 0; + url_data.fetch = true; + if ((error = get_optional_config(&found, config, &buf, url_cb, &url_data)) < 0) goto cleanup; + val = url_data.val; optional_setting_found |= found; remote->repo = repo; remote->download_tags = GIT_REMOTE_DOWNLOAD_TAGS_AUTO; - if (found && strlen(val) > 0) { - remote->url = git__strdup(val); - GITERR_CHECK_ALLOC(remote->url); - } + if (found && strlen(val) > 0) + remote->url = val; + else + git__free(val); val = NULL; git_buf_clear(&buf); git_buf_printf(&buf, "remote.%s.pushurl", name); - if ((error = get_optional_config(&found, config, &buf, NULL, (void *)&val)) < 0) + url_data.val = NULL; + url_data.nurls = 0; + url_data.fetch = true; + if ((error = get_optional_config(&found, config, &buf, url_cb, &url_data)) < 0) goto cleanup; + val = url_data.val; optional_setting_found |= found; if (!optional_setting_found) { @@ -471,10 +507,10 @@ int git_remote_lookup(git_remote **out, git_repository *repo, const char *name) goto cleanup; } - if (found && strlen(val) > 0) { - remote->pushurl = git__strdup(val); - GITERR_CHECK_ALLOC(remote->pushurl); - } + if (found && strlen(val) > 0) + remote->pushurl = val; + else + git__free(val); data.remote = remote; data.fetch = true; |