Skip to content

Commit ca863bb

Browse files
committed
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.
1 parent 21e2102 commit ca863bb

3 files changed

Lines changed: 76 additions & 25 deletions

File tree

pygit2/remote.py

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -494,3 +494,58 @@ def get_credentials(fn, url, username, allowed):
494494
check_error(err)
495495

496496
return ccred
497+
498+
class RemoteCollection(object):
499+
def __init__(self, repo):
500+
self._repo = repo;
501+
502+
def __len__(self):
503+
names = ffi.new('git_strarray *')
504+
505+
try:
506+
err = C.git_remote_list(names, self._repo._repo)
507+
check_error(err)
508+
509+
return names.count
510+
finally:
511+
C.git_strarray_free(names)
512+
513+
def __iter__(self):
514+
names = ffi.new('git_strarray *')
515+
516+
try:
517+
err = C.git_remote_list(names, self._repo._repo)
518+
check_error(err)
519+
520+
cremote = ffi.new('git_remote **')
521+
for i in range(names.count):
522+
err = C.git_remote_load(cremote, self._repo._repo, names.strings[i])
523+
check_error(err)
524+
525+
yield Remote(self._repo, cremote[0])
526+
finally:
527+
C.git_strarray_free(names)
528+
529+
def __getitem__(self, name):
530+
if isinstance(name, int):
531+
return list(self)[name]
532+
533+
cremote = ffi.new('git_remote **')
534+
err = C.git_remote_load(cremote, self._repo._repo, to_bytes(name))
535+
check_error(err)
536+
537+
return Remote(self._repo, cremote[0])
538+
539+
def create(self, name, url):
540+
"""create(name, url) -> Remote
541+
542+
Creates a new remote.
543+
"""
544+
545+
cremote = ffi.new('git_remote **')
546+
547+
err = C.git_remote_create(cremote, self._repo._repo, to_bytes(name),
548+
to_bytes(url))
549+
check_error(err)
550+
551+
return Remote(self._repo, cremote[0])

pygit2/repository.py

Lines changed: 8 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@
4848
from .errors import check_error
4949
from .ffi import ffi, C
5050
from .index import Index
51-
from .remote import Remote
51+
from .remote import Remote, RemoteCollection
5252
from .blame import Blame
5353
from .utils import to_bytes, is_string
5454

@@ -58,6 +58,8 @@ class Repository(_Repository):
5858
def __init__(self, *args, **kwargs):
5959
super(Repository, self).__init__(*args, **kwargs)
6060

61+
self._remotes = RemoteCollection(self)
62+
6163
# Get the pointer as the contents of a buffer and store it for
6264
# later access
6365
repo_cptr = ffi.new('git_repository **')
@@ -90,36 +92,17 @@ def create_remote(self, name, url):
9092
"""create_remote(name, url) -> Remote
9193
9294
Creates a new remote.
93-
"""
94-
95-
cremote = ffi.new('git_remote **')
9695
97-
err = C.git_remote_create(cremote, self._repo, to_bytes(name),
98-
to_bytes(url))
99-
check_error(err)
96+
This method is deprecated, please use Remote.remotes.create()
97+
"""
10098

101-
return Remote(self, cremote[0])
99+
return self.remotes.create(name, url)
102100

103101
@property
104102
def remotes(self):
105-
"""Returns all configured remotes"""
106-
107-
names = ffi.new('git_strarray *')
108-
109-
try:
110-
err = C.git_remote_list(names, self._repo)
111-
check_error(err)
112-
113-
l = [None] * names.count
114-
cremote = ffi.new('git_remote **')
115-
for i in range(names.count):
116-
err = C.git_remote_load(cremote, self._repo, names.strings[i])
117-
check_error(err)
103+
"""The collection of configured remotes"""
118104

119-
l[i] = Remote(self, cremote[0])
120-
return l
121-
finally:
122-
C.git_strarray_free(names)
105+
return self._remotes
123106

124107
#
125108
# Configuration

test/test_remote.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,19 @@ def test_remote_list(self):
167167
remote = self.repo.create_remote(name, url)
168168
self.assertTrue(remote.name in [x.name for x in self.repo.remotes])
169169

170+
def test_remote_collection(self):
171+
remote = self.repo.remotes['origin']
172+
self.assertEqual(REMOTE_NAME, remote.name)
173+
self.assertEqual(REMOTE_URL, remote.url)
174+
175+
with self.assertRaises(KeyError):
176+
self.repo.remotes['upstream']
177+
178+
name = 'upstream'
179+
url = 'git://github.com/libgit2/pygit2.git'
180+
remote = self.repo.remotes.create(name, url)
181+
self.assertTrue(remote.name in [x.name for x in self.repo.remotes])
182+
170183

171184
def test_remote_save(self):
172185
remote = self.repo.remotes[0]

0 commit comments

Comments
 (0)