summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Maw <richard.maw@codethink.co.uk>2013-11-12 18:26:34 +0000
committerRichard Maw <richard.maw@codethink.co.uk>2013-11-22 13:49:26 +0000
commit6903bd78aa5082dbe3c2834967380ff49ebda3d5 (patch)
treec9f737b4a699da30ce9427689543ea1bcce0fcaf
parent0f757009e17ed38f6aa8012691747f465872a994 (diff)
downloadmorph-6903bd78aa5082dbe3c2834967380ff49ebda3d5.tar.gz
GitDir: Add support for push urls in Remote
-rw-r--r--morphlib/gitdir.py43
-rw-r--r--morphlib/gitdir_tests.py32
2 files changed, 56 insertions, 19 deletions
diff --git a/morphlib/gitdir.py b/morphlib/gitdir.py
index 2b7bba2a..c5696858 100644
--- a/morphlib/gitdir.py
+++ b/morphlib/gitdir.py
@@ -104,6 +104,7 @@ class Remote(object):
def __init__(self, gd, name=None):
self.gd = gd
self.name = name
+ self.push_url = None
self.fetch_url = None
def set_fetch_url(self, url):
@@ -111,16 +112,44 @@ class Remote(object):
if self.name is not None:
self.gd._runcmd(['git', 'remote', 'set-url', self.name, url])
+ def set_push_url(self, url):
+ self.push_url = url
+ if self.name is not None:
+ self.gd._runcmd(['git', 'remote', 'set-url', '--push',
+ self.name, url])
+
+ def _get_remote_url(self, remote_name, kind):
+ # As distasteful as it is to parse the output of porcelain
+ # commands, this is the best option.
+ # Git config can be used to get the raw value, but this is
+ # incorrect when url.*.insteadof rules are involved.
+ # Re-implementing the rewrite logic in morph is duplicated effort
+ # and more work to keep it in sync.
+ # It's possible to get the fetch url with `git ls-remote --get-url
+ # <remote>`, but this will just print the remote's name if it
+ # is not defined.
+ # It is only possible to use git to get the push url by parsing
+ # `git remote -v` or `git remote show -n <remote>`, and `git
+ # remote -v` is easier to parse.
+ output = self.gd._runcmd(['git', 'remote', '-v'])
+ for line in output.splitlines():
+ words = line.split()
+ if (len(words) == 3 and
+ words[0] == remote_name and
+ words[2] == '(%s)' % kind):
+ return words[1]
+
+ return None
+
def get_fetch_url(self):
if self.name is None:
return self.fetch_url
- try:
- # git-ls-remote is used, rather than git-config, since
- # url.*.{push,}insteadof is processed after config is loaded
- return self.gd._runcmd(
- ['git', 'ls-remote', '--get-url', self.name]).rstrip('\n')
- except cliapp.AppException:
- return None
+ return self._get_remote_url(self.name, 'fetch')
+
+ def get_push_url(self):
+ if self.name is None:
+ return self.push_url or self.get_fetch_url()
+ return self._get_remote_url(self.name, 'push')
class GitDirectory(object):
diff --git a/morphlib/gitdir_tests.py b/morphlib/gitdir_tests.py
index 2adbec62..c7cb50f6 100644
--- a/morphlib/gitdir_tests.py
+++ b/morphlib/gitdir_tests.py
@@ -290,23 +290,31 @@ class GitDirectoryRemoteConfigTests(unittest.TestCase):
def tearDown(self):
shutil.rmtree(self.tempdir)
- def test_sets_fetch_url(self):
+ def test_sets_urls(self):
os.mkdir(self.dirname)
gitdir = morphlib.gitdir.init(self.dirname)
- self.assertEqual(gitdir.get_remote('origin').get_fetch_url(), None)
-
- gitdir._runcmd(['git', 'remote', 'add', 'origin', 'foobar'])
- url = 'git://git.example.com/foo'
remote = gitdir.get_remote('origin')
- remote.set_fetch_url(url)
- self.assertEqual(remote.get_fetch_url(), url)
+ self.assertEqual(remote.get_fetch_url(), None)
+ self.assertEqual(remote.get_push_url(), None)
- def test_nascent_remote(self):
+ gitdir._runcmd(['git', 'remote', 'add', 'origin', 'foobar'])
+ fetch_url = 'git://git.example.com/foo.git'
+ push_url = 'ssh://git@git.example.com/foo.git'
+ remote.set_fetch_url(fetch_url)
+ remote.set_push_url(push_url)
+ self.assertEqual(remote.get_fetch_url(), fetch_url)
+ self.assertEqual(remote.get_push_url(), push_url)
+
+ def test_nascent_remote_fetch(self):
os.mkdir(self.dirname)
gitdir = morphlib.gitdir.init(self.dirname)
remote = gitdir.get_remote(None)
self.assertEqual(remote.get_fetch_url(), None)
-
- url = 'git://git.example.com/foo'
- remote.set_fetch_url(url)
- self.assertEqual(remote.get_fetch_url(), url)
+ self.assertEqual(remote.get_push_url(), None)
+
+ fetch_url = 'git://git.example.com/foo.git'
+ push_url = 'ssh://git@git.example.com/foo.git'
+ remote.set_fetch_url(fetch_url)
+ remote.set_push_url(push_url)
+ self.assertEqual(remote.get_fetch_url(), fetch_url)
+ self.assertEqual(remote.get_push_url(), push_url)