summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Maw <richard.maw@codethink.co.uk>2013-11-12 16:50:27 +0000
committerRichard Maw <richard.maw@codethink.co.uk>2013-11-22 13:49:26 +0000
commit0f757009e17ed38f6aa8012691747f465872a994 (patch)
treebc736492a351ab706336b431490d7d66b37531f2
parent7f4662c38ac529faaed94734c3e7fab25d9bcc8b (diff)
downloadmorph-0f757009e17ed38f6aa8012691747f465872a994.tar.gz
GitDir: Split out Remote object
Operations on remotes are now accessed through this proxy object.
-rw-r--r--morphlib/gitdir.py55
-rw-r--r--morphlib/gitdir_tests.py41
-rw-r--r--morphlib/sysbranchdir.py3
3 files changed, 74 insertions, 25 deletions
diff --git a/morphlib/gitdir.py b/morphlib/gitdir.py
index df2fde61..2b7bba2a 100644
--- a/morphlib/gitdir.py
+++ b/morphlib/gitdir.py
@@ -90,6 +90,39 @@ class RefDeleteError(RefChangeError):
'located at %(dirname)s: %(original_exception)r' % locals())
+class Remote(object):
+ '''Represent a remote git repository.
+
+ This can either be nascent or concrete, depending on whether the
+ name is given.
+
+ Changes to a concrete remote's config are written-through to git's
+ config files, while a nascent remote keeps changes in-memory.
+
+ '''
+
+ def __init__(self, gd, name=None):
+ self.gd = gd
+ self.name = name
+ self.fetch_url = None
+
+ def set_fetch_url(self, url):
+ self.fetch_url = url
+ if self.name is not None:
+ self.gd._runcmd(['git', 'remote', 'set-url', self.name, url])
+
+ 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
+
+
class GitDirectory(object):
'''Represent a git working tree + .git directory.
@@ -196,20 +229,14 @@ class GitDirectory(object):
value = self._runcmd(['git', 'config', '-z', key])
return value.rstrip('\0')
- def set_remote_fetch_url(self, remote_name, url):
- '''Set the fetch URL for a remote.'''
- self._runcmd(['git', 'remote', 'set-url', remote_name, url])
-
- def get_remote_fetch_url(self, remote_name):
- '''Return the fetch URL for a given remote.'''
- output = self._runcmd(['git', 'remote', '-v'])
- for line in output.splitlines():
- words = line.split()
- if (len(words) == 3 and
- words[0] == remote_name and
- words[2] == '(fetch)'):
- return words[1]
- return None
+ def get_remote(self, *args, **kwargs):
+ '''Get a remote for this Repository.
+
+ Gets a previously configured remote if a remote name is given.
+ Otherwise a nascent one is created.
+
+ '''
+ return Remote(self, *args, **kwargs)
def update_remotes(self): # pragma: no cover
'''Run "git remote update --prune".'''
diff --git a/morphlib/gitdir_tests.py b/morphlib/gitdir_tests.py
index 7a251d23..2adbec62 100644
--- a/morphlib/gitdir_tests.py
+++ b/morphlib/gitdir_tests.py
@@ -55,16 +55,6 @@ class GitDirectoryTests(unittest.TestCase):
gitdir.set_config('foo.bar', 'yoyo')
self.assertEqual(gitdir.get_config('foo.bar'), 'yoyo')
- def test_sets_remote(self):
- os.mkdir(self.dirname)
- gitdir = morphlib.gitdir.init(self.dirname)
- self.assertEqual(gitdir.get_remote_fetch_url('origin'), None)
-
- gitdir._runcmd(['git', 'remote', 'add', 'origin', 'foobar'])
- url = 'git://git.example.com/foo'
- gitdir.set_remote_fetch_url('origin', url)
- self.assertEqual(gitdir.get_remote_fetch_url('origin'), url)
-
def test_gets_index(self):
os.mkdir(self.dirname)
gitdir = morphlib.gitdir.init(self.dirname)
@@ -289,3 +279,34 @@ class GitDirectoryRefTwiddlingTests(unittest.TestCase):
prev_commit = gd._rev_parse('refs/heads/master^')
with self.assertRaises(morphlib.gitdir.RefDeleteError):
gd.delete_ref('refs/heads/master', prev_commit)
+
+
+class GitDirectoryRemoteConfigTests(unittest.TestCase):
+
+ def setUp(self):
+ self.tempdir = tempfile.mkdtemp()
+ self.dirname = os.path.join(self.tempdir, 'foo')
+
+ def tearDown(self):
+ shutil.rmtree(self.tempdir)
+
+ def test_sets_fetch_url(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)
+
+ def test_nascent_remote(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)
diff --git a/morphlib/sysbranchdir.py b/morphlib/sysbranchdir.py
index a05ca52e..73a07d5e 100644
--- a/morphlib/sysbranchdir.py
+++ b/morphlib/sysbranchdir.py
@@ -141,7 +141,8 @@ class SystemBranchDirectory(object):
# and not the locally cached copy.
resolver = morphlib.repoaliasresolver.RepoAliasResolver(
cached_repo.app.settings['repo-alias'])
- gd.set_remote_fetch_url('origin', resolver.pull_url(cached_repo.url))
+ remote = gd.get_remote('origin')
+ remote.set_fetch_url(resolver.pull_url(cached_repo.url))
gd.set_config(
'url.%s.pushInsteadOf' %
resolver.push_url(cached_repo.original_name),