Skip to content

Commit e05895a

Browse files
committed
Remove remote for re-creating it if url has changed
We're adding the possibility to remove the remote. This, with the addition of names_url_dict, makes the posibility of checking the remote url, and if it's updated, then remove it for re-creating.
1 parent f3c9fc3 commit e05895a

File tree

2 files changed

+105
-3
lines changed

2 files changed

+105
-3
lines changed

git_wrapper/remote.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,14 @@ def names(self):
2424
"""
2525
return [x.name for x in self.git_repo.repo.remotes]
2626

27+
def names_url_dict(self):
28+
"""Returns a dict of remotes for a given repo with its url
29+
30+
:return dict: A dict of utf-8 encoded remote names with
31+
url as its value
32+
"""
33+
return {x.name: x.url for x in self.git_repo.repo.remotes}
34+
2735
def add(self, name, url):
2836
"""Adds a remote to the given repo
2937
@@ -111,3 +119,28 @@ def fetch_all(self, prune=False, prune_tags=False):
111119
if errors:
112120
msg = f"Error fetching these remotes: {', '.join(errors)}"
113121
raise exceptions.RemoteException(msg)
122+
123+
def remove(self, name):
124+
"""Remove the specified remote from the given repo
125+
126+
:param str name: Remote name to remove
127+
:return bool: True if the remote was removed, False otherwise
128+
"""
129+
working_dir = self.git_repo.repo.working_dir
130+
self.logger.debug(f"Removing remote {name} from repo {working_dir}")
131+
ret_status = False
132+
133+
try:
134+
remote = self.git_repo.repo.remote(name)
135+
except ValueError:
136+
repo = self.git_repo.repo.working_dir
137+
msg = f"Remote {name} does not exist on repo {repo}"
138+
raise exceptions.ReferenceNotFoundException(msg)
139+
140+
try:
141+
self.git_repo.repo.delete_remote(remote)
142+
ret_status = True
143+
except git.CommandError:
144+
return ret_status
145+
146+
return ret_status

tests/test_remote.py

Lines changed: 72 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#! /usr/bin/env python
22
"""Tests for GitRemote"""
33

4+
from dataclasses import dataclass
45
from mock import Mock
56

67
import git
@@ -10,14 +11,26 @@
1011
from git_wrapper.repo import GitRepo
1112

1213

14+
@dataclass
15+
class RemoteNames:
16+
name: str
17+
18+
@dataclass
19+
class RemoteNamesUrl(RemoteNames):
20+
url: str
21+
1322
def remote_generator(names):
1423
"""Generates objects to be used with git.Repo.remotes call"""
1524
ret_data = []
1625
for name in names:
17-
obj = type('', (), {})()
18-
obj.name = name
19-
ret_data.append(obj)
26+
ret_data.append(RemoteNames(name))
27+
return ret_data
2028

29+
def remote_generator_url(remotes):
30+
"""Generates objects to be used with git.Repo.remotes call"""
31+
ret_data = []
32+
for name, url in remotes.items():
33+
ret_data.append(RemoteNamesUrl(name, url))
2134
return ret_data
2235

2336

@@ -36,6 +49,21 @@ def test_get_remotes_returns_list(mock_repo):
3649
assert expected == git_util.remote.names()
3750

3851

52+
def test_get_remotes_returns_dict(mock_repo):
53+
"""
54+
GIVEN GitRepo is initialized with a path and repo
55+
WHEN remote.names_url_dict is called
56+
THEN a dict of remote names with its url is returned
57+
"""
58+
expected = {'a': 1, 'b': 2, 'c': 3}
59+
attrs = {'remotes': remote_generator_url(expected)}
60+
mock_repo.configure_mock(**attrs)
61+
62+
git_util = GitRepo('./', mock_repo)
63+
64+
assert expected == git_util.remote.names_url_dict()
65+
66+
3967
def test_add_remote_adds(mock_repo):
4068
"""
4169
GIVEN GitRepo initialized with a path and repo
@@ -89,6 +117,47 @@ def test_add_remote_update_fails(mock_repo):
89117
delete_mock.assert_called_once_with(remote_mock)
90118

91119

120+
def test_remove_remote_removes(mock_repo):
121+
"""
122+
GIVEN GitRepo initialized with a path and repo
123+
WHEN remote.remove is called with a name and url
124+
THEN a TRUE status is returned
125+
WITH update called
126+
"""
127+
git_util = GitRepo('./', mock_repo)
128+
129+
assert git_util.remote.remove('origin') is True
130+
131+
132+
def test_remove_remote_remote_fails(mock_repo):
133+
"""
134+
GIVEN GitRepo initialized with a path and repo
135+
WHEN remote.remove is called with a name and url
136+
AND the remote create fails with an exception
137+
THEN a False status is returned
138+
"""
139+
mock_repo.remote.side_effect = ValueError
140+
141+
repo = GitRepo(repo=mock_repo)
142+
with pytest.raises(exceptions.ReferenceNotFoundException):
143+
repo.remote.remove("doesntExist")
144+
145+
mock_repo.remote.assert_called_with("doesntExist")
146+
147+
148+
def test_remove_remote_remove_fails(mock_repo):
149+
"""
150+
GIVEN GitRepo initialized with a path and repo
151+
WHEN remote.remove is called with a name and url
152+
AND the remote create fails with an exception
153+
THEN a False status is returned
154+
"""
155+
mock_repo.delete_remote.side_effect = git.CommandError('remove')
156+
git_util = GitRepo('./', mock_repo)
157+
158+
assert git_util.remote.remove('rdo') is False
159+
160+
92161
def test_fetch(mock_repo):
93162
"""
94163
GIVEN GitRepo is initialized with a path and repo

0 commit comments

Comments
 (0)