From b80103b0172939a0503b11c48964f159bde0ca96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Sat, 8 Nov 2014 13:13:34 +0100 Subject: [PATCH] Introduce RemoteCollection This lets us look up remotes by name, which is not possible by just returning the list of remotes. Move remote creation to Repostiory.remotes.create() and keep the old Repository.create_remote() for compatibility, delegating to this new way. Existing code should keep working, but this moves us towards what we'd need for a better interface in 0.22 which makes remote renaming and deleting work with a name rather than an instance and would make sense to exist as part of an Remote.remotes object. --- docs/remotes.rst | 6 ++++- pygit2/remote.py | 63 ++++++++++++++++++++++++++++++++++++++++++++ pygit2/repository.py | 33 ++++++----------------- test/test_remote.py | 13 +++++++++ 4 files changed, 89 insertions(+), 26 deletions(-) diff --git a/docs/remotes.rst b/docs/remotes.rst index dfa8804..933637f 100644 --- a/docs/remotes.rst +++ b/docs/remotes.rst @@ -2,10 +2,14 @@ Remotes ********************************************************************** - .. autoattribute:: pygit2.Repository.remotes .. automethod:: pygit2.Repository.create_remote +The remote collection +========================== + +.. autoclass:: pygit2.remote.RemoteCollection + :members: The Remote type ==================== diff --git a/pygit2/remote.py b/pygit2/remote.py index c69578c..88d875d 100644 --- a/pygit2/remote.py +++ b/pygit2/remote.py @@ -494,3 +494,66 @@ def get_credentials(fn, url, username, allowed): check_error(err) return ccred + +class RemoteCollection(object): + """Collection of configured remotes + + You can use this class to look up and manage the remotes configured + in a repository. You can access repositories using index + access. E.g. to look up the "origin" remote, you can use + + >>> repo.remotes["origin"] + """ + + def __init__(self, repo): + self._repo = repo; + + def __len__(self): + names = ffi.new('git_strarray *') + + try: + err = C.git_remote_list(names, self._repo._repo) + check_error(err) + + return names.count + finally: + C.git_strarray_free(names) + + def __iter__(self): + names = ffi.new('git_strarray *') + + try: + err = C.git_remote_list(names, self._repo._repo) + check_error(err) + + cremote = ffi.new('git_remote **') + for i in range(names.count): + err = C.git_remote_load(cremote, self._repo._repo, names.strings[i]) + check_error(err) + + yield Remote(self._repo, cremote[0]) + finally: + C.git_strarray_free(names) + + def __getitem__(self, name): + if isinstance(name, int): + return list(self)[name] + + cremote = ffi.new('git_remote **') + err = C.git_remote_load(cremote, self._repo._repo, to_bytes(name)) + check_error(err) + + return Remote(self._repo, cremote[0]) + + def create(self, name, url): + """create(name, url) -> Remote + + Create a new remote with the given name and url. + """ + + cremote = ffi.new('git_remote **') + + err = C.git_remote_create(cremote, self._repo._repo, to_bytes(name), to_bytes(url)) + check_error(err) + + return Remote(self._repo, cremote[0]) diff --git a/pygit2/repository.py b/pygit2/repository.py index d9c1eed..d31e03e 100644 --- a/pygit2/repository.py +++ b/pygit2/repository.py @@ -48,7 +48,7 @@ from .config import Config from .errors import check_error from .ffi import ffi, C from .index import Index -from .remote import Remote +from .remote import Remote, RemoteCollection from .blame import Blame from .utils import to_bytes, is_string @@ -58,6 +58,8 @@ class Repository(_Repository): def __init__(self, *args, **kwargs): super(Repository, self).__init__(*args, **kwargs) + self._remotes = RemoteCollection(self) + # Get the pointer as the contents of a buffer and store it for # later access repo_cptr = ffi.new('git_repository **') @@ -90,36 +92,17 @@ class Repository(_Repository): """create_remote(name, url) -> Remote Creates a new remote. + + This method is deprecated, please use Remote.remotes.create() """ - cremote = ffi.new('git_remote **') - - err = C.git_remote_create(cremote, self._repo, to_bytes(name), - to_bytes(url)) - check_error(err) - - return Remote(self, cremote[0]) + return self.remotes.create(name, url) @property def remotes(self): - """Returns all configured remotes""" + """The collection of configured remotes""" - names = ffi.new('git_strarray *') - - try: - err = C.git_remote_list(names, self._repo) - check_error(err) - - l = [None] * names.count - cremote = ffi.new('git_remote **') - for i in range(names.count): - err = C.git_remote_load(cremote, self._repo, names.strings[i]) - check_error(err) - - l[i] = Remote(self, cremote[0]) - return l - finally: - C.git_strarray_free(names) + return self._remotes # # Configuration diff --git a/test/test_remote.py b/test/test_remote.py index e0b9fae..ee28743 100644 --- a/test/test_remote.py +++ b/test/test_remote.py @@ -167,6 +167,19 @@ class RepositoryTest(utils.RepoTestCase): remote = self.repo.create_remote(name, url) self.assertTrue(remote.name in [x.name for x in self.repo.remotes]) + def test_remote_collection(self): + remote = self.repo.remotes['origin'] + self.assertEqual(REMOTE_NAME, remote.name) + self.assertEqual(REMOTE_URL, remote.url) + + with self.assertRaises(KeyError): + self.repo.remotes['upstream'] + + name = 'upstream' + url = 'git://github.com/libgit2/pygit2.git' + remote = self.repo.remotes.create(name, url) + self.assertTrue(remote.name in [x.name for x in self.repo.remotes]) + def test_remote_save(self): remote = self.repo.remotes[0]