Merge branch 'mg/pushurl'
authorJunio C Hamano <gitster@pobox.com>
Sun, 21 Jun 2009 04:47:27 +0000 (21:47 -0700)
committerJunio C Hamano <gitster@pobox.com>
Sun, 21 Jun 2009 04:47:27 +0000 (21:47 -0700)
* mg/pushurl:
avoid NULL dereference on failed malloc
builtin-remote: Make "remote -v" display push urls
builtin-remote: Show push urls as well
technical/api-remote: Describe new struct remote member pushurl
t5516: Check pushurl config setting
Allow push and fetch urls to be different

Documentation/config.txt
Documentation/technical/api-remote.txt
Documentation/urls-remotes.txt
builtin-push.c
builtin-remote.c
remote.c
remote.h
t/t5505-remote.sh
t/t5516-fetch-push.sh
index 3a86d1f8f05317717d718a6db7c5e0f9acb47d6b..2fecbe32a68bd981959735dd14e6e311d16b233a 100644 (file)
@@ -1319,6 +1319,9 @@ remote.<name>.url::
        The URL of a remote repository.  See linkgit:git-fetch[1] or
        linkgit:git-push[1].
 
+remote.<name>.pushurl::
+       The push URL of a remote repository.  See linkgit:git-push[1].
+
 remote.<name>.proxy::
        For remotes that require curl (http, https and ftp), the URL to
        the proxy to use for that remote.  Set to the empty string to
index 073b22bd83badb5aada47e061bb29e48d5f95518..c54b17db69b8420bdec7c6ee0f424a5216957add 100644 (file)
@@ -18,6 +18,10 @@ struct remote
 
        An array of all of the url_nr URLs configured for the remote
 
+`pushurl`::
+
+       An array of all of the pushurl_nr push URLs configured for the remote
+
 `push`::
 
         An array of refspecs configured for pushing, with
index 41ec7774f481fd2d70492be4ab2b5e0bf887fc0b..2a0e7b89441039699a3dc9514f1165cb2112020a 100644 (file)
@@ -27,10 +27,13 @@ config file would appear like this:
 ------------
        [remote "<name>"]
                url = <url>
+               pushurl = <pushurl>
                push = <refspec>
                fetch = <refspec>
 ------------
 
+The `<pushurl>` is used for pushes only. It is optional and defaults
+to `<url>`.
 
 Named file in `$GIT_DIR/remotes`
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
index c869974013b5c1bb563d4f9b306820362545c9ea..7be12399b6d95c63efd9102df7967dca61655063 100644 (file)
@@ -117,6 +117,8 @@ static int do_push(const char *repo, int flags)
 {
        int i, errs;
        struct remote *remote = remote_get(repo);
+       const char **url;
+       int url_nr;
 
        if (!remote) {
                if (repo)
@@ -152,9 +154,16 @@ static int do_push(const char *repo, int flags)
                        setup_default_push_refspecs();
        }
        errs = 0;
-       for (i = 0; i < remote->url_nr; i++) {
+       if (remote->pushurl_nr) {
+               url = remote->pushurl;
+               url_nr = remote->pushurl_nr;
+       } else {
+               url = remote->url;
+               url_nr = remote->url_nr;
+       }
+       for (i = 0; i < url_nr; i++) {
                struct transport *transport =
-                       transport_get(remote, remote->url[i]);
+                       transport_get(remote, url[i]);
                int err;
                if (receivepack)
                        transport_set_option(transport,
@@ -163,14 +172,14 @@ static int do_push(const char *repo, int flags)
                        transport_set_option(transport, TRANS_OPT_THIN, "yes");
 
                if (flags & TRANSPORT_PUSH_VERBOSE)
-                       fprintf(stderr, "Pushing to %s\n", remote->url[i]);
+                       fprintf(stderr, "Pushing to %s\n", url[i]);
                err = transport_push(transport, refspec_nr, refspec, flags);
                err |= transport_disconnect(transport);
 
                if (!err)
                        continue;
 
-               error("failed to push some refs to '%s'", remote->url[i]);
+               error("failed to push some refs to '%s'", url[i]);
                errs++;
        }
        return !!errs;
index dfc0b9e706507fc557cc2b593632fda4683387bc..406fb85255f2a1475f9960eee12e04f04c8e4c53 100644 (file)
@@ -999,15 +999,25 @@ static int show(int argc, const char **argv)
        info.list = &info_list;
        for (; argc; argc--, argv++) {
                int i;
+               const char **url;
+               int url_nr;
 
                get_remote_ref_states(*argv, &states, query_flag);
 
                printf("* remote %s\n", *argv);
-               if (states.remote->url_nr) {
-                       for (i=0; i < states.remote->url_nr; i++)
-                               printf("  URL: %s\n", states.remote->url[i]);
-               } else
-                       printf("  URL: %s\n", "(no URL)");
+               printf("  Fetch URL: %s\n", states.remote->url_nr > 0 ?
+                       states.remote->url[0] : "(no URL)");
+               if (states.remote->pushurl_nr) {
+                       url = states.remote->pushurl;
+                       url_nr = states.remote->pushurl_nr;
+               } else {
+                       url = states.remote->url;
+                       url_nr = states.remote->url_nr;
+               }
+               for (i=0; i < url_nr; i++)
+                       printf("  Push  URL: %s\n", url[i]);
+               if (!i)
+                       printf("  Push  URL: %s\n", "(no URL)");
                if (no_query)
                        printf("  HEAD branch: (not queried)\n");
                else if (!states.heads.nr)
@@ -1266,14 +1276,31 @@ static int update(int argc, const char **argv)
 static int get_one_entry(struct remote *remote, void *priv)
 {
        struct string_list *list = priv;
+       const char **url;
+       int i, url_nr;
+       void **utilp;
 
        if (remote->url_nr > 0) {
-               int i;
-
-               for (i = 0; i < remote->url_nr; i++)
-                       string_list_append(remote->name, list)->util = (void *)remote->url[i];
+               utilp = &(string_list_append(remote->name, list)->util);
+               *utilp = xmalloc(strlen(remote->url[0])+strlen(" (fetch)")+1);
+               strcpy((char *) *utilp, remote->url[0]);
+               strcat((char *) *utilp, " (fetch)");
        } else
                string_list_append(remote->name, list)->util = NULL;
+       if (remote->pushurl_nr) {
+               url = remote->pushurl;
+               url_nr = remote->pushurl_nr;
+       } else {
+               url = remote->url;
+               url_nr = remote->url_nr;
+       }
+       for (i = 0; i < url_nr; i++)
+       {
+               utilp = &(string_list_append(remote->name, list)->util);
+               *utilp = xmalloc(strlen(url[i])+strlen(" (push)")+1);
+               strcpy((char *) *utilp, url[i]);
+               strcat((char *) *utilp, " (push)");
+       }
 
        return 0;
 }
@@ -1281,7 +1308,10 @@ static int get_one_entry(struct remote *remote, void *priv)
 static int show_all(void)
 {
        struct string_list list = { NULL, 0, 0 };
-       int result = for_each_remote(get_one_entry, &list);
+       int result;
+
+       list.strdup_strings = 1;
+       result = for_each_remote(get_one_entry, &list);
 
        if (!result) {
                int i;
@@ -1299,6 +1329,7 @@ static int show_all(void)
                        }
                }
        }
+       string_list_clear(&list, 1);
        return result;
 }
 
index 08a59644c03b9c61bfad8383e521ac813e0c4f05..9a0397ec570f1794e0f762c2ccc6eee27f77be46 100644 (file)
--- a/remote.c
+++ b/remote.c
@@ -106,6 +106,12 @@ static void add_url_alias(struct remote *remote, const char *url)
        add_url(remote, alias_url(url));
 }
 
+static void add_pushurl(struct remote *remote, const char *pushurl)
+{
+       ALLOC_GROW(remote->pushurl, remote->pushurl_nr + 1, remote->pushurl_alloc);
+       remote->pushurl[remote->pushurl_nr++] = pushurl;
+}
+
 static struct remote *make_remote(const char *name, int len)
 {
        struct remote *ret;
@@ -379,6 +385,11 @@ static int handle_config(const char *key, const char *value, void *cb)
                if (git_config_string(&v, key, value))
                        return -1;
                add_url(remote, v);
+       } else if (!strcmp(subkey, ".pushurl")) {
+               const char *v;
+               if (git_config_string(&v, key, value))
+                       return -1;
+               add_pushurl(remote, v);
        } else if (!strcmp(subkey, ".push")) {
                const char *v;
                if (git_config_string(&v, key, value))
@@ -424,6 +435,9 @@ static void alias_all_urls(void)
                for (j = 0; j < remotes[i]->url_nr; j++) {
                        remotes[i]->url[j] = alias_url(remotes[i]->url[j]);
                }
+               for (j = 0; j < remotes[i]->pushurl_nr; j++) {
+                       remotes[i]->pushurl[j] = alias_url(remotes[i]->pushurl[j]);
+               }
        }
 }
 
index 257a55538f3ff2d6330b84436a40d6ef972025a0..5db842087da081abbad96c8f9eed5829140714d2 100644 (file)
--- a/remote.h
+++ b/remote.h
@@ -15,6 +15,10 @@ struct remote {
        int url_nr;
        int url_alloc;
 
+       const char **pushurl;
+       int pushurl_nr;
+       int pushurl_alloc;
+
        const char **push_refspec;
        struct refspec *push;
        int push_refspec_nr;
index e70246b3fb5f0040a65db953b0adee7ada2d51ed..852ccb5d7d649a71eeab25eadce6940b9c2a6f63 100755 (executable)
@@ -135,7 +135,8 @@ EOF
 
 cat > test/expect << EOF
 * remote origin
-  URL: $(pwd)/one
+  Fetch URL: $(pwd)/one
+  Push  URL: $(pwd)/one
   HEAD branch: master
   Remote branches:
     master new (next fetch will store in remotes/origin)
@@ -151,7 +152,8 @@ cat > test/expect << EOF
     master pushes to master   (local out of date)
     master pushes to upstream (create)
 * remote two
-  URL: ../two
+  Fetch URL: ../two
+  Push  URL: ../three
   HEAD branch (remote HEAD is ambiguous, may be one of the following):
     another
     master
@@ -173,6 +175,7 @@ test_expect_success 'show' '
         git branch --track rebase origin/master &&
         git branch -d -r origin/master &&
         git config --add remote.two.url ../two &&
+        git config --add remote.two.pushurl ../three &&
         git config branch.rebase.rebase true &&
         git config branch.octopus.merge "topic-a topic-b topic-c" &&
         (cd ../one &&
@@ -191,7 +194,8 @@ test_expect_success 'show' '
 
 cat > test/expect << EOF
 * remote origin
-  URL: $(pwd)/one
+  Fetch URL: $(pwd)/one
+  Push  URL: $(pwd)/one
   HEAD branch: (not queried)
   Remote branches: (status not queried)
     master
index 89649e7a9b2dc138bb9618d4e5770e76f62dc7e0..2d2633f3f8784565faf5db84c6efe12d9c405013 100755 (executable)
@@ -419,6 +419,19 @@ test_expect_success 'push with config remote.*.push = HEAD' '
 git config --remove-section remote.there
 git config --remove-section branch.master
 
+test_expect_success 'push with config remote.*.pushurl' '
+
+       mk_test heads/master &&
+       git checkout master &&
+       git config remote.there.url test2repo &&
+       git config remote.there.pushurl testrepo &&
+       git push there &&
+       check_push_result $the_commit heads/master
+'
+
+# clean up the cruft left with the previous one
+git config --remove-section remote.there
+
 test_expect_success 'push with dry-run' '
 
        mk_test heads/master &&