Skip to content

Commit b366d3f

Browse files
committed
Adding support for git remote set-url/get-url API to Remote
Both commands enable handling of a little known feature of git, which is to support multiple URL for one remote. You can add multiple url using the `set_url` subcommand of `git remote`. As listing them is also handy, there's a nice method to do it, using `get_url`. * adding set_url method that maps to the git remote set-url command¶ * can be used to set an URL, or replace an URL with optional positional arg¶ * can be used to add, delete URL with kwargs (matching set-url options)¶ * adding add_url, delete_url methods that wraps around set_url for conveniency¶ * adding urls property that yields an iterator over the setup urls for a remote¶ * adding a test suite that checks all use case scenarii of this added API.¶ Signed-off-by: Guyzmo <[email protected]>
1 parent 902679c commit b366d3f

File tree

2 files changed

+95
-2
lines changed

2 files changed

+95
-2
lines changed

‎git/remote.py‎

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -434,6 +434,54 @@ def iter_items(cls, repo):
434434
yieldRemote(repo, section[lbound+1:rbound])
435435
# END for each configuration section
436436

437+
defset_url(self, new_url, old_url=None, **kwargs):
438+
"""Configure URLs on current remote (cf command git remote set_url)
439+
440+
This command manages URLs on the remote.
441+
442+
:param new_url: string being the URL to add as an extra remote URL
443+
:param old_url: when set, replaces this URL with new_url for the remote
444+
:return: self
445+
"""
446+
scmd='set-url'
447+
kwargs['insert_kwargs_after'] =scmd
448+
ifold_url:
449+
self.repo.git.remote(scmd, self.name, old_url, new_url, **kwargs)
450+
else:
451+
self.repo.git.remote(scmd, self.name, new_url, **kwargs)
452+
returnself
453+
454+
defadd_url(self, url, **kwargs):
455+
"""Adds a new url on current remote (special case of git remote set_url)
456+
457+
This command adds new URLs to a given remote, making it possible to have
458+
multiple URLs for a single remote.
459+
460+
:param url: string being the URL to add as an extra remote URL
461+
:return: self
462+
"""
463+
returnself.set_url(url, add=True)
464+
465+
defdelete_url(self, url, **kwargs):
466+
"""Deletes a new url on current remote (special case of git remote set_url)
467+
468+
This command deletes new URLs to a given remote, making it possible to have
469+
multiple URLs for a single remote.
470+
471+
:param url: string being the URL to delete from the remote
472+
:return: self
473+
"""
474+
returnself.set_url(url, delete=True)
475+
476+
@property
477+
defurls(self):
478+
""":return: Iterator yielding all configured URL targets on a remote
479+
as strings"""
480+
scmd='get-url'
481+
kwargs={'insert_kwargs_after': scmd}
482+
forurlinself.repo.git.remote(scmd, self.name, all=True, **kwargs).split('\n'):
483+
yieldurl
484+
437485
@property
438486
defrefs(self):
439487
"""

‎git/test/test_remote.py‎

Lines changed: 47 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@
99
with_rw_repo,
1010
with_rw_and_rw_remote_repo,
1111
fixture,
12-
GIT_DAEMON_PORT
12+
GIT_DAEMON_PORT,
13+
assert_raises
1314
)
1415
fromgitimport (
1516
RemoteProgress,
@@ -62,7 +63,7 @@ def update(self, op_code, cur_count, max_count=None, message=''):
6263
# check each stage only comes once
6364
op_id=op_code&self.OP_MASK
6465
assertop_idin (self.COUNTING, self.COMPRESSING, self.WRITING)
65-
66+
6667
ifop_code&self.WRITING>0:
6768
ifop_code&self.BEGIN>0:
6869
assertnotmessage, 'should not have message when remote begins writing'
@@ -568,3 +569,47 @@ def test_uncommon_branch_names(self):
568569
assertres[0].remote_ref_path=='refs/pull/1/head'
569570
assertres[0].ref.path=='refs/heads/pull/1/head'
570571
assertisinstance(res[0].ref, Head)
572+
573+
@with_rw_repo('HEAD', bare=False)
574+
deftest_multiple_urls(self, rw_repo):
575+
# test addresses
576+
test1='https://github.com/gitpython-developers/GitPython'
577+
test2='https://github.com/gitpython-developers/gitdb'
578+
test3='https://github.com/gitpython-developers/smmap'
579+
580+
remote=rw_repo.remotes[0]
581+
# Testing setting a single URL
582+
remote.set_url(test1)
583+
assertlist(remote.urls) == [test1]
584+
585+
# Testing replacing that single URL
586+
remote.set_url(test1)
587+
assertlist(remote.urls) == [test1]
588+
# Testing adding new URLs
589+
remote.set_url(test2, add=True)
590+
assertlist(remote.urls) == [test1, test2]
591+
remote.set_url(test3, add=True)
592+
assertlist(remote.urls) == [test1, test2, test3]
593+
# Testing removing an URL
594+
remote.set_url(test2, delete=True)
595+
assertlist(remote.urls) == [test1, test3]
596+
# Testing changing an URL
597+
remote.set_url(test3, test2)
598+
assertlist(remote.urls) == [test1, test2]
599+
600+
# will raise: fatal: --add --delete doesn't make sense
601+
assert_raises(GitCommandError, remote.set_url, test2, add=True, delete=True)
602+
603+
# Testing on another remote, with the add/delete URL
604+
remote=rw_repo.create_remote('another', url=test1)
605+
remote.add_url(test2)
606+
assertlist(remote.urls) == [test1, test2]
607+
remote.add_url(test3)
608+
assertlist(remote.urls) == [test1, test2, test3]
609+
# Testing removing all the URLs
610+
remote.delete_url(test2)
611+
assertlist(remote.urls) == [test1, test3]
612+
remote.delete_url(test1)
613+
assertlist(remote.urls) == [test3]
614+
# will raise fatal: Will not delete all non-push URLs
615+
assert_raises(GitCommandError, remote.delete_url, test3)

0 commit comments

Comments
(0)