summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGuyzmo <guyzmo+github@m0g.net>2016-05-26 20:43:28 +0200
committerGuyzmo <guyzmo+github@m0g.net>2016-06-08 19:34:29 +0200
commitb366d3fabd79e921e30b44448cb357a05730c42f (patch)
tree6d6ab0a14a6e89b2cd52fc993663f2d6b8a274ed
parent902679c47c3d1238833ac9c9fdbc7c0ddbedf509 (diff)
downloadgitpython-b366d3fabd79e921e30b44448cb357a05730c42f.tar.gz
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 <guyzmo+github@m0g.net>
-rw-r--r--git/remote.py48
-rw-r--r--git/test/test_remote.py49
2 files changed, 95 insertions, 2 deletions
diff --git a/git/remote.py b/git/remote.py
index 92203588..ef02c629 100644
--- a/git/remote.py
+++ b/git/remote.py
@@ -434,6 +434,54 @@ class Remote(LazyMixin, Iterable):
yield Remote(repo, section[lbound + 1:rbound])
# END for each configuration section
+ def set_url(self, new_url, old_url=None, **kwargs):
+ """Configure URLs on current remote (cf command git remote set_url)
+
+ This command manages URLs on the remote.
+
+ :param new_url: string being the URL to add as an extra remote URL
+ :param old_url: when set, replaces this URL with new_url for the remote
+ :return: self
+ """
+ scmd = 'set-url'
+ kwargs['insert_kwargs_after'] = scmd
+ if old_url:
+ self.repo.git.remote(scmd, self.name, old_url, new_url, **kwargs)
+ else:
+ self.repo.git.remote(scmd, self.name, new_url, **kwargs)
+ return self
+
+ def add_url(self, url, **kwargs):
+ """Adds a new url on current remote (special case of git remote set_url)
+
+ This command adds new URLs to a given remote, making it possible to have
+ multiple URLs for a single remote.
+
+ :param url: string being the URL to add as an extra remote URL
+ :return: self
+ """
+ return self.set_url(url, add=True)
+
+ def delete_url(self, url, **kwargs):
+ """Deletes a new url on current remote (special case of git remote set_url)
+
+ This command deletes new URLs to a given remote, making it possible to have
+ multiple URLs for a single remote.
+
+ :param url: string being the URL to delete from the remote
+ :return: self
+ """
+ return self.set_url(url, delete=True)
+
+ @property
+ def urls(self):
+ """:return: Iterator yielding all configured URL targets on a remote
+ as strings"""
+ scmd = 'get-url'
+ kwargs = {'insert_kwargs_after': scmd}
+ for url in self.repo.git.remote(scmd, self.name, all=True, **kwargs).split('\n'):
+ yield url
+
@property
def refs(self):
"""
diff --git a/git/test/test_remote.py b/git/test/test_remote.py
index 9ca2f207..3c2e622d 100644
--- a/git/test/test_remote.py
+++ b/git/test/test_remote.py
@@ -9,7 +9,8 @@ from git.test.lib import (
with_rw_repo,
with_rw_and_rw_remote_repo,
fixture,
- GIT_DAEMON_PORT
+ GIT_DAEMON_PORT,
+ assert_raises
)
from git import (
RemoteProgress,
@@ -62,7 +63,7 @@ class TestRemoteProgress(RemoteProgress):
# check each stage only comes once
op_id = op_code & self.OP_MASK
assert op_id in (self.COUNTING, self.COMPRESSING, self.WRITING)
-
+
if op_code & self.WRITING > 0:
if op_code & self.BEGIN > 0:
assert not message, 'should not have message when remote begins writing'
@@ -568,3 +569,47 @@ class TestRemote(TestBase):
assert res[0].remote_ref_path == 'refs/pull/1/head'
assert res[0].ref.path == 'refs/heads/pull/1/head'
assert isinstance(res[0].ref, Head)
+
+ @with_rw_repo('HEAD', bare=False)
+ def test_multiple_urls(self, rw_repo):
+ # test addresses
+ test1 = 'https://github.com/gitpython-developers/GitPython'
+ test2 = 'https://github.com/gitpython-developers/gitdb'
+ test3 = 'https://github.com/gitpython-developers/smmap'
+
+ remote = rw_repo.remotes[0]
+ # Testing setting a single URL
+ remote.set_url(test1)
+ assert list(remote.urls) == [test1]
+
+ # Testing replacing that single URL
+ remote.set_url(test1)
+ assert list(remote.urls) == [test1]
+ # Testing adding new URLs
+ remote.set_url(test2, add=True)
+ assert list(remote.urls) == [test1, test2]
+ remote.set_url(test3, add=True)
+ assert list(remote.urls) == [test1, test2, test3]
+ # Testing removing an URL
+ remote.set_url(test2, delete=True)
+ assert list(remote.urls) == [test1, test3]
+ # Testing changing an URL
+ remote.set_url(test3, test2)
+ assert list(remote.urls) == [test1, test2]
+
+ # will raise: fatal: --add --delete doesn't make sense
+ assert_raises(GitCommandError, remote.set_url, test2, add=True, delete=True)
+
+ # Testing on another remote, with the add/delete URL
+ remote = rw_repo.create_remote('another', url=test1)
+ remote.add_url(test2)
+ assert list(remote.urls) == [test1, test2]
+ remote.add_url(test3)
+ assert list(remote.urls) == [test1, test2, test3]
+ # Testing removing all the URLs
+ remote.delete_url(test2)
+ assert list(remote.urls) == [test1, test3]
+ remote.delete_url(test1)
+ assert list(remote.urls) == [test3]
+ # will raise fatal: Will not delete all non-push URLs
+ assert_raises(GitCommandError, remote.delete_url, test3)