This adds the --fetch option to `git remote set-url` such that when
executed we move the remote.*.url to remote.*.pushurl and set
remote.*.url to the given url argument.

For example, if we have the following config:

        [remote "origin"]
                url = g...@github.com:git/git.git

`git remote set-url --fetch origin https://github.com/git/git.git`
would change the config to the following:

        [remote "origin"]
                url = https://github.com/git/git.git
                pushurl = g...@github.com:git/git.git

Signed-off-by: Denton Liu <liu.den...@gmail.com>
Signed-off-by: Filip Francetic <f.fran...@hotmail.com>
---
 builtin/remote.c | 42 ++++++++++++++++++++++++++++++++++--------
 1 file changed, 34 insertions(+), 8 deletions(-)

diff --git a/builtin/remote.c b/builtin/remote.c
index f7edf7f2c..fcf1220c6 100644
--- a/builtin/remote.c
+++ b/builtin/remote.c
@@ -23,9 +23,9 @@ static const char * const builtin_remote_usage[] = {
        N_("git remote [-v | --verbose] update [-p | --prune] [(<group> | 
<remote>)...]"),
        N_("git remote set-branches [--add] <name> <branch>..."),
        N_("git remote get-url [--push] [--all] <name>"),
-       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 [--push|--fetch] <name> <newurl> [<oldurl>]"),
+       N_("git remote set-url --add [--push|--fetch] <name> <newurl>"),
+       N_("git remote set-url --delete [--push|--fetch] <name> <url>"),
        NULL
 };
 
@@ -76,9 +76,9 @@ static const char * const builtin_remote_geturl_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 [--push|--fetch] <name> <newurl> [<oldurl>]"),
+       N_("git remote set-url --add [--push|--fetch] <name> <newurl>"),
+       N_("git remote set-url --delete [--push|--fetch] <name> <url>"),
        NULL
 };
 
@@ -1519,7 +1519,7 @@ static int get_url(int argc, const char **argv)
 
 static int set_url(int argc, const char **argv)
 {
-       int i, push_mode = 0, add_mode = 0, delete_mode = 0;
+       int i, push_mode = 0, fetch_mode = 0, add_mode = 0, delete_mode = 0, 
move_fetch_to_push = 0;
        int matches = 0, negative_matches = 0;
        const char *remotename = NULL;
        const char *newurl = NULL;
@@ -1532,6 +1532,8 @@ static int set_url(int argc, const char **argv)
        struct option options[] = {
                OPT_BOOL('\0', "push", &push_mode,
                         N_("manipulate push URLs")),
+               OPT_BOOL('\0', "fetch", &fetch_mode,
+                        N_("manipulate fetch URLs")),
                OPT_BOOL('\0', "add", &add_mode,
                         N_("add URL")),
                OPT_BOOL('\0', "delete", &delete_mode,
@@ -1543,6 +1545,8 @@ static int set_url(int argc, const char **argv)
 
        if (add_mode && delete_mode)
                die(_("--add --delete doesn't make sense"));
+       if (push_mode && fetch_mode)
+               die(_("--push --fetch doesn't make sense"));
 
        if (argc < 3 || argc > 4 || ((add_mode || delete_mode) && argc != 3))
                usage_with_options(builtin_remote_seturl_usage, options);
@@ -1559,18 +1563,40 @@ static int set_url(int argc, const char **argv)
        if (!remote_is_configured(remote, 1))
                die(_("No such remote '%s'"), remotename);
 
+       /*
+        * If add_mode, we will be appending to remote.*.url so we shouldn't 
move the urls over.
+        * If pushurls exist, we don't need to move the urls over to pushurl.
+        */
+       move_fetch_to_push = fetch_mode && !add_mode && !remote->pushurl_nr;
+
        if (push_mode) {
                strbuf_addf(&name_buf, "remote.%s.pushurl", remotename);
                urlset = remote->pushurl;
                urlset_nr = remote->pushurl_nr;
        } else {
+               if (move_fetch_to_push) {
+                       strbuf_addf(&name_buf, "remote.%s.pushurl", remotename);
+                       for (i = 0; i < remote->url_nr; i++) {
+                               git_config_set_multivar(name_buf.buf, 
remote->url[i],
+                                               "^$", 0);
+                       }
+                       strbuf_reset(&name_buf);
+               }
+
                strbuf_addf(&name_buf, "remote.%s.url", remotename);
                urlset = remote->url;
                urlset_nr = remote->url_nr;
        }
 
+       /* Empty fetch URLs if they are being replaced */
+       if (move_fetch_to_push) {
+               for (i = 0; i < remote->url_nr; i++) {
+                       git_config_set_multivar(name_buf.buf, NULL, 
remote->url[i], 1);
+               }
+       }
+
        /* Special cases that add new entry. */
-       if ((!oldurl && !delete_mode) || add_mode) {
+       if ((!oldurl && !delete_mode) || move_fetch_to_push || add_mode) {
                if (add_mode)
                        git_config_set_multivar(name_buf.buf, newurl,
                                                       "^$", 0);
-- 
2.19.1.542.gc4df23f79.dirty

Reply via email to