From cb020f0d9936f221c6bd6f873994e8978657cd28 Mon Sep 17 00:00:00 2001 From: Sascha Cunz Date: Wed, 25 Jul 2012 01:14:58 +0200 Subject: [PATCH 1/6] Remove unneccessary string transformation --- src/remote.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/remote.c b/src/remote.c index e46249e12..c0819ffeb 100644 --- a/src/remote.c +++ b/src/remote.c @@ -179,7 +179,7 @@ int git_remote_save(const git_remote *remote) if (git_repository_config__weakptr(&config, remote->repo) < 0) return -1; - if (git_buf_printf(&buf, "remote.%s.%s", remote->name, "url") < 0) + if (git_buf_printf(&buf, "remote.%s.url", remote->name) < 0) return -1; if (git_config_set_string(config, git_buf_cstr(&buf), remote->url) < 0) { From 3ed4b5012bbdba844ae1ffdff884a1eb630e9884 Mon Sep 17 00:00:00 2001 From: Sascha Cunz Date: Wed, 25 Jul 2012 01:32:31 +0200 Subject: [PATCH 2/6] Remotes: Load/Save for fetch.foo.pushurl --- src/remote.c | 32 ++++++++++++++++++++++++++++++++ src/remote.h | 1 + 2 files changed, 33 insertions(+) diff --git a/src/remote.c b/src/remote.c index c0819ffeb..bcc4ab5b4 100644 --- a/src/remote.c +++ b/src/remote.c @@ -130,6 +130,26 @@ int git_remote_load(git_remote **out, git_repository *repo, const char *name) remote->url = git__strdup(val); GITERR_CHECK_ALLOC(remote->url); + git_buf_clear(&buf); + if (git_buf_printf(&buf, "remote.%s.pushurl", name) < 0) { + error = -1; + goto cleanup; + } + + error = git_config_get_string(&val, config, git_buf_cstr(&buf)); + if (error == GIT_ENOTFOUND) + error = 0; + + if (error < 0) { + error = -1; + goto cleanup; + } + + if (val) { + remote->pushurl = git__strdup(val); + GITERR_CHECK_ALLOC(remote->pushurl); + } + git_buf_clear(&buf); if (git_buf_printf(&buf, "remote.%s.fetch", name) < 0) { error = -1; @@ -187,6 +207,17 @@ int git_remote_save(const git_remote *remote) return -1; } + if (remote->pushurl) { + git_buf_clear(&buf); + if (git_buf_printf(&buf, "remote.%s.pushurl", remote->name) < 0) + return -1; + + if (git_config_set_string(config, git_buf_cstr(&buf), remote->pushurl) < 0) { + git_buf_free(&buf); + return -1; + } + } + if (remote->fetch.src != NULL && remote->fetch.dst != NULL) { git_buf_clear(&buf); git_buf_clear(&value); @@ -429,6 +460,7 @@ void git_remote_free(git_remote *remote) git__free(remote->push.src); git__free(remote->push.dst); git__free(remote->url); + git__free(remote->pushurl); git__free(remote->name); git__free(remote); } diff --git a/src/remote.h b/src/remote.h index 0949ad434..abdaa5750 100644 --- a/src/remote.h +++ b/src/remote.h @@ -14,6 +14,7 @@ struct git_remote { char *name; char *url; + char *pushurl; git_vector refs; struct git_refspec fetch; struct git_refspec push; From 765015902ab346f4879acceaf8c8adf61f0e0ed5 Mon Sep 17 00:00:00 2001 From: Sascha Cunz Date: Wed, 25 Jul 2012 01:33:15 +0200 Subject: [PATCH 3/6] Remotes: Setter for url+pushurl; Getter for pushurl --- include/git2/remote.h | 30 ++++++++++++++++++++++++++++++ src/remote.c | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 62 insertions(+) diff --git a/include/git2/remote.h b/include/git2/remote.h index 5c01949d2..6d4b6cc20 100644 --- a/include/git2/remote.h +++ b/include/git2/remote.h @@ -79,6 +79,36 @@ GIT_EXTERN(const char *) git_remote_name(git_remote *remote); */ GIT_EXTERN(const char *) git_remote_url(git_remote *remote); +/** + * Get the remote's url for pushing + * + * @param remote the remote + * @return a pointer to the url or NULL if no special url for pushing is set + */ +GIT_EXTERN(const char *) git_remote_pushurl(git_remote *remote); + +/** + * Set the remote's url + * + * Existing connections will not be updated. + * + * @param remote the remote + * @param url the url to set + * @return 0 or an error value + */ +GIT_EXTERN(int) git_remote_set_url(git_remote *remote, const char* url); + +/** + * Set the remote's url for pushing + * + * Existing connections will not be updated. + * + * @param remote the remote + * @param url the url to set or NULL to clear the pushurl + * @return 0 or an error value + */ +GIT_EXTERN(int) git_remote_set_pushurl(git_remote *remote, const char* url); + /** * Set the remote's fetch refspec * diff --git a/src/remote.c b/src/remote.c index bcc4ab5b4..cdd593cdb 100644 --- a/src/remote.c +++ b/src/remote.c @@ -269,6 +269,38 @@ const char *git_remote_url(git_remote *remote) return remote->url; } +int git_remote_set_url(git_remote *remote, const char* url) +{ + assert(remote); + assert(url); + + git__free(remote->url); + remote->url = git__strdup(url); + GITERR_CHECK_ALLOC(remote->url); + + return 0; +} + +const char *git_remote_pushurl(git_remote *remote) +{ + assert(remote); + return remote->pushurl; +} + +int git_remote_set_pushurl(git_remote *remote, const char* url) +{ + assert(remote); + + git__free(remote->pushurl); + if (url) { + remote->pushurl = git__strdup(url); + GITERR_CHECK_ALLOC(remote->pushurl); + } else { + remote->pushurl = NULL; + } + return 0; +} + int git_remote_set_fetchspec(git_remote *remote, const char *spec) { git_refspec refspec; From 8689a69d097e1116e7fd2506b3cfd76b6e3b03bb Mon Sep 17 00:00:00 2001 From: Sascha Cunz Date: Wed, 25 Jul 2012 01:59:23 +0200 Subject: [PATCH 4/6] Tests: Test remote's pushurl --- tests-clar/network/remotes.c | 27 ++++++++++++++++++++++-- tests-clar/resources/testrepo.git/config | 5 +++++ 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/tests-clar/network/remotes.c b/tests-clar/network/remotes.c index eb7947dfb..61b29b85e 100644 --- a/tests-clar/network/remotes.c +++ b/tests-clar/network/remotes.c @@ -27,8 +27,26 @@ void test_network_remotes__cleanup(void) void test_network_remotes__parsing(void) { + git_remote *_remote2 = NULL; + cl_assert_equal_s(git_remote_name(_remote), "test"); cl_assert_equal_s(git_remote_url(_remote), "git://github.com/libgit2/libgit2"); + cl_assert(git_remote_pushurl(_remote) == NULL); + + cl_git_pass(git_remote_load(&_remote2, _repo, "test_with_pushurl")); + cl_assert_equal_s(git_remote_name(_remote2), "test_with_pushurl"); + cl_assert_equal_s(git_remote_url(_remote2), "git://github.com/libgit2/fetchlibgit2"); + cl_assert_equal_s(git_remote_pushurl(_remote2), "git://github.com/libgit2/pushlibgit2"); + git_remote_free(_remote2); +} + +void test_network_remotes__pushurl(void) +{ + cl_git_pass(git_remote_set_pushurl(_remote, "git://github.com/libgit2/notlibgit2")); + cl_assert_equal_s(git_remote_pushurl(_remote), "git://github.com/libgit2/notlibgit2"); + + cl_git_pass(git_remote_set_pushurl(_remote, NULL)); + cl_assert(git_remote_pushurl(_remote) == NULL); } void test_network_remotes__parsing_ssh_remote(void) @@ -81,6 +99,7 @@ void test_network_remotes__save(void) cl_git_pass(git_remote_new(&_remote, _repo, "upstream", "git://github.com/libgit2/libgit2", NULL)); cl_git_pass(git_remote_set_fetchspec(_remote, "refs/heads/*:refs/remotes/upstream/*")); cl_git_pass(git_remote_set_pushspec(_remote, "refs/heads/*:refs/heads/*")); + cl_git_pass(git_remote_set_pushurl(_remote, "git://github.com/libgit2/libgit2_push")); cl_git_pass(git_remote_save(_remote)); git_remote_free(_remote); _remote = NULL; @@ -98,6 +117,9 @@ void test_network_remotes__save(void) cl_assert(_refspec != NULL); cl_assert_equal_s(git_refspec_src(_refspec), "refs/heads/*"); cl_assert_equal_s(git_refspec_dst(_refspec), "refs/heads/*"); + + cl_assert_equal_s(git_remote_url(_remote), "git://github.com/libgit2/libgit2"); + cl_assert_equal_s(git_remote_pushurl(_remote), "git://github.com/libgit2/libgit2_push"); } void test_network_remotes__fnmatch(void) @@ -143,13 +165,13 @@ void test_network_remotes__list(void) git_config *cfg; cl_git_pass(git_remote_list(&list, _repo)); - cl_assert(list.count == 1); + cl_assert(list.count == 2); git_strarray_free(&list); cl_git_pass(git_repository_config(&cfg, _repo)); cl_git_pass(git_config_set_string(cfg, "remote.specless.url", "http://example.com")); cl_git_pass(git_remote_list(&list, _repo)); - cl_assert(list.count == 2); + cl_assert(list.count == 3); git_strarray_free(&list); git_config_free(cfg); @@ -180,4 +202,5 @@ void test_network_remotes__add(void) cl_assert(!strcmp(git_refspec_src(_refspec), "refs/heads/*")); cl_assert(git_refspec_force(_refspec) == 1); cl_assert(!strcmp(git_refspec_dst(_refspec), "refs/remotes/addtest/*")); + cl_assert_equal_s(git_remote_url(_remote), "http://github.com/libgit2/libgit2"); } diff --git a/tests-clar/resources/testrepo.git/config b/tests-clar/resources/testrepo.git/config index b4fdac6c2..c99d97153 100644 --- a/tests-clar/resources/testrepo.git/config +++ b/tests-clar/resources/testrepo.git/config @@ -7,6 +7,11 @@ url = git://github.com/libgit2/libgit2 fetch = +refs/heads/*:refs/remotes/test/* +[remote "test_with_pushurl"] + url = git://github.com/libgit2/fetchlibgit2 + pushurl = git://github.com/libgit2/pushlibgit2 + fetch = +refs/heads/*:refs/remotes/test_with_pushurl/* + [branch "master"] remote = test merge = refs/heads/master From 413d55638483678357ebcb8c26911cf944be95cc Mon Sep 17 00:00:00 2001 From: Sascha Cunz Date: Wed, 25 Jul 2012 02:10:35 +0200 Subject: [PATCH 5/6] Remotes: Save a cleaned pushurl (by deleting it from the config) --- src/remote.c | 17 +++++++++++++---- tests-clar/network/remotes.c | 9 +++++++++ 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/src/remote.c b/src/remote.c index cdd593cdb..bee1ab65c 100644 --- a/src/remote.c +++ b/src/remote.c @@ -207,15 +207,24 @@ int git_remote_save(const git_remote *remote) return -1; } - if (remote->pushurl) { - git_buf_clear(&buf); - if (git_buf_printf(&buf, "remote.%s.pushurl", remote->name) < 0) - return -1; + git_buf_clear(&buf); + if (git_buf_printf(&buf, "remote.%s.pushurl", remote->name) < 0) + return -1; + if (remote->pushurl) { if (git_config_set_string(config, git_buf_cstr(&buf), remote->pushurl) < 0) { git_buf_free(&buf); return -1; } + } else { + int error = git_config_delete(config, git_buf_cstr(&buf)); + if (error == GIT_ENOTFOUND) { + error = 0; + } + if (error < 0) { + git_buf_free(&buf); + return -1; + } } if (remote->fetch.src != NULL && remote->fetch.dst != NULL) { diff --git a/tests-clar/network/remotes.c b/tests-clar/network/remotes.c index 61b29b85e..3d989c1b6 100644 --- a/tests-clar/network/remotes.c +++ b/tests-clar/network/remotes.c @@ -120,6 +120,15 @@ void test_network_remotes__save(void) cl_assert_equal_s(git_remote_url(_remote), "git://github.com/libgit2/libgit2"); cl_assert_equal_s(git_remote_pushurl(_remote), "git://github.com/libgit2/libgit2_push"); + + /* remove the pushurl again and see if we can save that too */ + cl_git_pass(git_remote_set_pushurl(_remote, NULL)); + cl_git_pass(git_remote_save(_remote)); + git_remote_free(_remote); + _remote = NULL; + + cl_git_pass(git_remote_load(&_remote, _repo, "upstream")); + cl_assert(git_remote_pushurl(_remote) == NULL); } void test_network_remotes__fnmatch(void) From eff5b4992731cd01f1bc6a457e8d2f86428a8b55 Mon Sep 17 00:00:00 2001 From: Sascha Cunz Date: Wed, 25 Jul 2012 02:34:12 +0200 Subject: [PATCH 6/6] Remotes: Use correct url in git_remote_connect --- src/remote.c | 21 ++++++++++++++++++++- src/remote.h | 2 ++ tests-clar/network/remotes.c | 12 ++++++++++++ 3 files changed, 34 insertions(+), 1 deletion(-) diff --git a/src/remote.c b/src/remote.c index bee1ab65c..b4a21a688 100644 --- a/src/remote.c +++ b/src/remote.c @@ -356,13 +356,32 @@ const git_refspec *git_remote_pushspec(git_remote *remote) return &remote->push; } +const char* git_remote__urlfordirection(git_remote *remote, int direction) +{ + assert(remote); + + if (direction == GIT_DIR_FETCH) { + return remote->url; + } + + if (direction == GIT_DIR_PUSH) { + return remote->pushurl ? remote->pushurl : remote->url; + } + + return NULL; +} + int git_remote_connect(git_remote *remote, int direction) { git_transport *t; assert(remote); - if (git_transport_new(&t, remote->url) < 0) + const char* url = git_remote__urlfordirection(remote, direction); + if (url == NULL ) + return -1; + + if (git_transport_new(&t, url) < 0) return -1; t->check_cert = remote->check_cert; diff --git a/src/remote.h b/src/remote.h index abdaa5750..623d40c87 100644 --- a/src/remote.h +++ b/src/remote.h @@ -24,4 +24,6 @@ struct git_remote { check_cert; }; +const char* git_remote__urlfordirection(struct git_remote *remote, int direction); + #endif diff --git a/tests-clar/network/remotes.c b/tests-clar/network/remotes.c index 3d989c1b6..f1d6f47c6 100644 --- a/tests-clar/network/remotes.c +++ b/tests-clar/network/remotes.c @@ -2,6 +2,7 @@ #include "buffer.h" #include "refspec.h" #include "transport.h" +#include "remote.h" static git_remote *_remote; static git_repository *_repo; @@ -33,10 +34,21 @@ void test_network_remotes__parsing(void) cl_assert_equal_s(git_remote_url(_remote), "git://github.com/libgit2/libgit2"); cl_assert(git_remote_pushurl(_remote) == NULL); + cl_assert_equal_s(git_remote__urlfordirection(_remote, GIT_DIR_FETCH), + "git://github.com/libgit2/libgit2"); + cl_assert_equal_s(git_remote__urlfordirection(_remote, GIT_DIR_PUSH), + "git://github.com/libgit2/libgit2"); + cl_git_pass(git_remote_load(&_remote2, _repo, "test_with_pushurl")); cl_assert_equal_s(git_remote_name(_remote2), "test_with_pushurl"); cl_assert_equal_s(git_remote_url(_remote2), "git://github.com/libgit2/fetchlibgit2"); cl_assert_equal_s(git_remote_pushurl(_remote2), "git://github.com/libgit2/pushlibgit2"); + + cl_assert_equal_s(git_remote__urlfordirection(_remote2, GIT_DIR_FETCH), + "git://github.com/libgit2/fetchlibgit2"); + cl_assert_equal_s(git_remote__urlfordirection(_remote2, GIT_DIR_PUSH), + "git://github.com/libgit2/pushlibgit2"); + git_remote_free(_remote2); }