From 6903bd78aa5082dbe3c2834967380ff49ebda3d5 Mon Sep 17 00:00:00 2001 From: Richard Maw Date: Tue, 12 Nov 2013 18:26:34 +0000 Subject: GitDir: Add support for push urls in Remote --- morphlib/gitdir.py | 43 ++++++++++++++++++++++++++++++++++++------- morphlib/gitdir_tests.py | 32 ++++++++++++++++++++------------ 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 + # `, 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 `, 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) -- cgit v1.2.1