Skip to content

Commit 6724067

Browse files
committed
remote: introduce set_instance_url
Users may want to override the URL on a particular instance of a remote, instead of updating the configuration. Previously, users could use a callback to do this, but this is not particularly idiomatic.
1 parent 45489a1 commit 6724067

File tree

3 files changed

+102
-3
lines changed

3 files changed

+102
-3
lines changed

include/git2/remote.h

+25-3
Original file line numberDiff line numberDiff line change
@@ -212,18 +212,20 @@ GIT_EXTERN(const char *) git_remote_name(const git_remote *remote);
212212
* Get the remote's url
213213
*
214214
* If url.*.insteadOf has been configured for this URL, it will
215-
* return the modified URL.
215+
* return the modified URL. If `git_remote_set_instance_pushurl`
216+
* has been called for this remote, then that URL will be returned.
216217
*
217218
* @param remote the remote
218219
* @return a pointer to the url
219220
*/
220221
GIT_EXTERN(const char *) git_remote_url(const git_remote *remote);
221222

222223
/**
223-
* Get the remote's url for pushing
224+
* Get the remote's url for pushing.
224225
*
225226
* If url.*.pushInsteadOf has been configured for this URL, it
226-
* will return the modified URL.
227+
* will return the modified URL. If `git_remote_set_instance_pushurl`
228+
* has been called for this remote, then that URL will be returned.
227229
*
228230
* @param remote the remote
229231
* @return a pointer to the url or NULL if no special url for pushing is set
@@ -257,6 +259,26 @@ GIT_EXTERN(int) git_remote_set_url(git_repository *repo, const char *remote, con
257259
*/
258260
GIT_EXTERN(int) git_remote_set_pushurl(git_repository *repo, const char *remote, const char* url);
259261

262+
/**
263+
* Set the url for this particular url instance. The URL in the
264+
* configuration will be ignored, and will not be changed.
265+
*
266+
* @param remote the remote's name
267+
* @param url the url to set
268+
* @return 0 or an error value
269+
*/
270+
GIT_EXTERN(int) git_remote_set_instance_url(git_remote *remote, const char *url);
271+
272+
/**
273+
* Set the push url for this particular url instance. The URL in the
274+
* configuration will be ignored, and will not be changed.
275+
*
276+
* @param remote the remote's name
277+
* @param url the url to set
278+
* @return 0 or an error value
279+
*/
280+
GIT_EXTERN(int) git_remote_set_instance_pushurl(git_remote *remote, const char *url);
281+
260282
/**
261283
* Add a fetch refspec to the remote's configuration
262284
*

src/remote.c

+32
Original file line numberDiff line numberDiff line change
@@ -600,6 +600,22 @@ const char *git_remote_url(const git_remote *remote)
600600
return remote->url;
601601
}
602602

603+
int git_remote_set_instance_url(git_remote *remote, const char *url)
604+
{
605+
char *tmp;
606+
607+
GIT_ASSERT_ARG(remote);
608+
GIT_ASSERT_ARG(url);
609+
610+
if ((tmp = git__strdup(url)) == NULL)
611+
return -1;
612+
613+
git__free(remote->url);
614+
remote->url = tmp;
615+
616+
return 0;
617+
}
618+
603619
static int set_url(git_repository *repo, const char *remote, const char *pattern, const char *url)
604620
{
605621
git_config *cfg;
@@ -645,6 +661,22 @@ const char *git_remote_pushurl(const git_remote *remote)
645661
return remote->pushurl;
646662
}
647663

664+
int git_remote_set_instance_pushurl(git_remote *remote, const char *url)
665+
{
666+
char *tmp;
667+
668+
GIT_ASSERT_ARG(remote);
669+
GIT_ASSERT_ARG(url);
670+
671+
if ((tmp = git__strdup(url)) == NULL)
672+
return -1;
673+
674+
git__free(remote->pushurl);
675+
remote->pushurl = tmp;
676+
677+
return 0;
678+
}
679+
648680
int git_remote_set_pushurl(git_repository *repo, const char *remote, const char* url)
649681
{
650682
return set_url(repo, remote, CONFIG_PUSHURL_FMT, url);

tests/network/remote/remotes.c

+45
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,51 @@ void test_network_remote_remotes__urlresolve_passthrough(void)
121121
git_buf_dispose(&url);
122122
}
123123

124+
void test_network_remote_remotes__instance_url(void)
125+
{
126+
git_buf url = GIT_BUF_INIT;
127+
const char *orig_url = "git://github.com/libgit2/libgit2";
128+
129+
cl_assert_equal_s(git_remote_name(_remote), "test");
130+
cl_assert_equal_s(git_remote_url(_remote), orig_url);
131+
132+
cl_git_pass(git_remote__urlfordirection(&url, _remote, GIT_DIRECTION_FETCH, NULL));
133+
cl_assert_equal_s(url.ptr, orig_url);
134+
git_buf_clear(&url);
135+
136+
cl_git_pass(git_remote__urlfordirection(&url, _remote, GIT_DIRECTION_PUSH, NULL));
137+
cl_assert_equal_s(url.ptr, orig_url);
138+
git_buf_clear(&url);
139+
140+
/* Setting the instance url updates the fetch and push URLs */
141+
git_remote_set_instance_url(_remote, "https://github.com/new/remote/url");
142+
cl_assert_equal_s(git_remote_url(_remote), "https://github.com/new/remote/url");
143+
cl_assert_equal_p(git_remote_pushurl(_remote), NULL);
144+
145+
cl_git_pass(git_remote__urlfordirection(&url, _remote, GIT_DIRECTION_FETCH, NULL));
146+
cl_assert_equal_s(url.ptr, "https://github.com/new/remote/url");
147+
git_buf_clear(&url);
148+
149+
cl_git_pass(git_remote__urlfordirection(&url, _remote, GIT_DIRECTION_PUSH, NULL));
150+
cl_assert_equal_s(url.ptr, "https://github.com/new/remote/url");
151+
git_buf_clear(&url);
152+
153+
/* Setting the instance push url updates only the push URL */
154+
git_remote_set_instance_pushurl(_remote, "https://github.com/new/push/url");
155+
cl_assert_equal_s(git_remote_url(_remote), "https://github.com/new/remote/url");
156+
cl_assert_equal_s(git_remote_pushurl(_remote), "https://github.com/new/push/url");
157+
158+
cl_git_pass(git_remote__urlfordirection(&url, _remote, GIT_DIRECTION_FETCH, NULL));
159+
cl_assert_equal_s(url.ptr, "https://github.com/new/remote/url");
160+
git_buf_clear(&url);
161+
162+
cl_git_pass(git_remote__urlfordirection(&url, _remote, GIT_DIRECTION_PUSH, NULL));
163+
cl_assert_equal_s(url.ptr, "https://github.com/new/push/url");
164+
git_buf_clear(&url);
165+
166+
git_buf_dispose(&url);
167+
}
168+
124169
void test_network_remote_remotes__pushurl(void)
125170
{
126171
const char *name = git_remote_name(_remote);

0 commit comments

Comments
 (0)