summaryrefslogtreecommitdiff
path: root/builtin/remote.c
diff options
context:
space:
mode:
authorPeter Wu <peter@lekensteyn.nl>2014-11-25 12:48:26 +0100
committerJunio C Hamano <gitster@pobox.com>2014-11-26 10:05:04 -0800
commite6196ae10f6a05d74bae4542b6b675831f3b9c20 (patch)
tree15a3e52f955842ddf3cb42f48b74f7a0e67f8096 /builtin/remote.c
parent652e759330da379a8e09e03bbf99e03c10c228cc (diff)
downloadgit-pw/remote-set-url-fetch.tar.gz
remote: add --fetch and --both options to set-urlpw/remote-set-url-fetch
git remote set-url knew about the '--push' option to update just the pushurl, but it does not have a similar option for "update fetch URL and leave whatever was in place for the push URL". This patch adds support for a '--fetch' option which implements that use case in a backwards compatible way: if no --both, --push or --fetch options are given, then the push URL is modified too if it was not set before. This is the case since the push URL is implicitly based on the fetch URL. A '--both' option is added to make the command independent of previous pushurl settings. For the --add and --delete set operations, it will always set the push and/ or the fetch URLs. For the primary mode of operation (without --add or --delete), it will drop pushurl as the implicit push URL is the (fetch) URL. The documentation has also been updated and a missing '--push' option is added to the 'git remote -h' command. Tests are also added to verify the documented behavior. Signed-off-by: Peter Wu <peter@lekensteyn.nl> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 'builtin/remote.c')
-rw-r--r--builtin/remote.c140
1 files changed, 90 insertions, 50 deletions
diff --git a/builtin/remote.c b/builtin/remote.c
index 7f28f92a37..a250b23e0e 100644
--- a/builtin/remote.c
+++ b/builtin/remote.c
@@ -18,9 +18,9 @@ static const char * const builtin_remote_usage[] = {
N_("git remote prune [-n | --dry-run] <name>"),
N_("git remote [-v | --verbose] update [-p | --prune] [(<group> | <remote>)...]"),
N_("git remote set-branches [--add] <name> <branch>..."),
- N_("git remote set-url [--push] <name> <newurl> [<oldurl>]"),
- N_("git remote set-url --add <name> <newurl>"),
- N_("git remote set-url --delete <name> <url>"),
+ N_("git remote set-url [--both | --fetch | --push] <name> <newurl> [<oldurl>]"),
+ N_("git remote set-url [--both | --fetch | --push] --add <name> <newurl>"),
+ N_("git remote set-url [--both | --fetch | --push] --delete <name> <url>"),
NULL
};
@@ -66,9 +66,9 @@ static const char * const builtin_remote_update_usage[] = {
};
static const char * const builtin_remote_seturl_usage[] = {
- N_("git remote set-url [--push] <name> <newurl> [<oldurl>]"),
- N_("git remote set-url --add <name> <newurl>"),
- N_("git remote set-url --delete <name> <url>"),
+ N_("git remote set-url [--both | --fetch | --push] <name> <newurl> [<oldurl>]"),
+ N_("git remote set-url [--both | --fetch | --push] --add <name> <newurl>"),
+ N_("git remote set-url [--both | --fetch | --push] --delete <name> <url>"),
NULL
};
@@ -1503,21 +1503,35 @@ static int set_branches(int argc, const char **argv)
return set_remote_branches(argv[0], argv + 1, add_mode);
}
+#define MODIFY_TYPE_FETCH (1 << 0)
+#define MODIFY_TYPE_PUSH (1 << 1)
+#define MODIFY_TYPE_BOTH (MODIFY_TYPE_FETCH | MODIFY_TYPE_PUSH)
+#define MODIFY_TYPE_HISTORIC (MODIFY_TYPE_FETCH | (1 << 2))
+
static int set_url(int argc, const char **argv)
{
- int i, push_mode = 0, add_mode = 0, delete_mode = 0;
+ int i, add_mode = 0, delete_mode = 0;
+ int modify_type = MODIFY_TYPE_HISTORIC;
int matches = 0, negative_matches = 0;
const char *remotename = NULL;
const char *newurl = NULL;
const char *oldurl = NULL;
struct remote *remote;
regex_t old_regex;
- const char **urlset;
- int urlset_nr;
- struct strbuf name_buf = STRBUF_INIT;
+ struct strbuf name_buf_fetch = STRBUF_INIT;
+ struct strbuf name_buf_push = STRBUF_INIT;
struct option options[] = {
- OPT_BOOL('\0', "push", &push_mode,
- N_("manipulate push URLs")),
+ OPT_GROUP(""),
+ OPT_SET_INT('\0', "fetch", &modify_type,
+ N_("manipulate just fetch URLs"),
+ MODIFY_TYPE_FETCH),
+ OPT_SET_INT('\0', "push", &modify_type,
+ N_("manipulate just push URLs"),
+ MODIFY_TYPE_PUSH),
+ OPT_SET_INT('\0', "both", &modify_type,
+ N_("manipulate both push and fetch URLs"),
+ MODIFY_TYPE_BOTH),
+ OPT_GROUP(""),
OPT_BOOL('\0', "add", &add_mode,
N_("add URL")),
OPT_BOOL('\0', "delete", &delete_mode,
@@ -1535,7 +1549,8 @@ static int set_url(int argc, const char **argv)
remotename = argv[1];
newurl = argv[2];
- if (argc > 3)
+ /* The old URL is only meaningful for the primary non-set operation. */
+ if (argc > 3 && !add_mode && !delete_mode)
oldurl = argv[3];
if (delete_mode)
@@ -1545,47 +1560,72 @@ static int set_url(int argc, const char **argv)
die(_("No such remote '%s'"), remotename);
remote = remote_get(remotename);
- if (push_mode) {
- strbuf_addf(&name_buf, "remote.%s.pushurl", remotename);
- urlset = remote->pushurl;
- urlset_nr = remote->pushurl_nr;
- } else {
- strbuf_addf(&name_buf, "remote.%s.url", remotename);
- urlset = remote->url;
- urlset_nr = remote->url_nr;
+ strbuf_addf(&name_buf_fetch, "remote.%s.url", remotename);
+ strbuf_addf(&name_buf_push, "remote.%s.pushurl", remotename);
+
+ if (oldurl && !add_mode) {
+ /* Old URL specified, or deletion. Demand that one matches. */
+ if (regcomp(&old_regex, oldurl, REG_EXTENDED))
+ die(_("Invalid old URL pattern: %s"), oldurl);
+
+ if (modify_type & MODIFY_TYPE_FETCH)
+ for (i = 0; i < remote->url_nr; i++)
+ if (!regexec(&old_regex, remote->url[i], 0, NULL, 0))
+ matches++;
+ else
+ negative_matches++;
+ if (delete_mode && !negative_matches && modify_type & MODIFY_TYPE_FETCH)
+ die(_("Will not delete all non-push URLs"));
+ if (modify_type & MODIFY_TYPE_PUSH)
+ for (i = 0; i < remote->pushurl_nr; i++)
+ if (!regexec(&old_regex, remote->pushurl[i], 0, NULL, 0))
+ matches++;
+ else
+ negative_matches++;
+ if (!delete_mode && !matches)
+ die(_("No such URL found: %s"), oldurl);
+
+ regfree(&old_regex);
}
- /* Special cases that add new entry. */
- if ((!oldurl && !delete_mode) || add_mode) {
- if (add_mode)
- git_config_set_multivar(name_buf.buf, newurl,
- "^$", 0);
- else
- git_config_set(name_buf.buf, newurl);
- strbuf_release(&name_buf);
- return 0;
+ /* If --fetch was explicitly given, then ensure that the push
+ * URL does not change by copying the fetch URL to it. */
+ if (modify_type == MODIFY_TYPE_FETCH &&
+ remote->pushurl_nr == 0 && remote->url_nr > 0)
+ for (i = 0; i < remote->url_nr; i++)
+ git_config_set_multivar(name_buf_push.buf,
+ remote->url[i], "^$", 0);
+
+ /* Set the new entry value (not a --add or --delete operation). */
+ if (!add_mode && !delete_mode && !oldurl) {
+ if (modify_type & MODIFY_TYPE_FETCH)
+ git_config_set(name_buf_fetch.buf, newurl);
+ /* URLs will be the same, so remove pushurl. */
+ if (modify_type == MODIFY_TYPE_BOTH)
+ git_config_set(name_buf_push.buf, NULL);
+ else if (modify_type == MODIFY_TYPE_PUSH)
+ git_config_set(name_buf_push.buf, newurl);
+
+ goto cleanup_ok;
}
- /* Old URL specified. Demand that one matches. */
- if (regcomp(&old_regex, oldurl, REG_EXTENDED))
- die(_("Invalid old URL pattern: %s"), oldurl);
-
- for (i = 0; i < urlset_nr; i++)
- if (!regexec(&old_regex, urlset[i], 0, NULL, 0))
- matches++;
- else
- negative_matches++;
- if (!delete_mode && !matches)
- die(_("No such URL found: %s"), oldurl);
- if (delete_mode && !negative_matches && !push_mode)
- die(_("Will not delete all non-push URLs"));
-
- regfree(&old_regex);
-
- if (!delete_mode)
- git_config_set_multivar(name_buf.buf, newurl, oldurl, 0);
- else
- git_config_set_multivar(name_buf.buf, NULL, oldurl, 1);
+ /* Set operations (--add, --delete) or change request (oldurl given). */
+ if (delete_mode) {
+ if (modify_type & MODIFY_TYPE_FETCH)
+ git_config_set_multivar(name_buf_fetch.buf, NULL, oldurl, 1);
+ if (modify_type & MODIFY_TYPE_PUSH)
+ git_config_set_multivar(name_buf_push.buf, NULL, oldurl, 1);
+ } else {
+ if (add_mode) /* Do not replace oldurl, but add a new one. */
+ oldurl = "^$";
+ if (modify_type & MODIFY_TYPE_FETCH)
+ git_config_set_multivar(name_buf_fetch.buf, newurl, oldurl, 0);
+ if (modify_type & MODIFY_TYPE_PUSH)
+ git_config_set_multivar(name_buf_push.buf, newurl, oldurl, 0);
+ }
+cleanup_ok:
+ strbuf_release(&name_buf_fetch);
+ strbuf_release(&name_buf_push);
return 0;
}