Skip to content

Commit 1a33779

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 1a33779

File tree

2 files changed

+108
-3
lines changed

2 files changed

+108
-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: 75 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,29 @@
1011
from git_wrapper.repo import GitRepo
1112

1213

14+
@dataclass
15+
class RemoteNames:
16+
name: str
17+
18+
19+
@dataclass
20+
class RemoteNamesUrl(RemoteNames):
21+
url: str
22+
23+
1324
def remote_generator(names):
1425
"""Generates objects to be used with git.Repo.remotes call"""
1526
ret_data = []
1627
for name in names:
17-
obj = type('', (), {})()
18-
obj.name = name
19-
ret_data.append(obj)
28+
ret_data.append(RemoteNames(name))
29+
return ret_data
30+
2031

32+
def remote_generator_url(remotes):
33+
"""Generates objects to be used with git.Repo.remotes call"""
34+
ret_data = []
35+
for name, url in remotes.items():
36+
ret_data.append(RemoteNamesUrl(name, url))
2137
return ret_data
2238

2339

@@ -36,6 +52,21 @@ def test_get_remotes_returns_list(mock_repo):
3652
assert expected == git_util.remote.names()
3753

3854

55+
def test_get_remotes_returns_dict(mock_repo):
56+
"""
57+
GIVEN GitRepo is initialized with a path and repo
58+
WHEN remote.names_url_dict is called
59+
THEN a dict of remote names with its url is returned
60+
"""
61+
expected = {'a': 1, 'b': 2, 'c': 3}
62+
attrs = {'remotes': remote_generator_url(expected)}
63+
mock_repo.configure_mock(**attrs)
64+
65+
git_util = GitRepo('./', mock_repo)
66+
67+
assert expected == git_util.remote.names_url_dict()
68+
69+
3970
def test_add_remote_adds(mock_repo):
4071
"""
4172
GIVEN GitRepo initialized with a path and repo
@@ -89,6 +120,47 @@ def test_add_remote_update_fails(mock_repo):
89120
delete_mock.assert_called_once_with(remote_mock)
90121

91122

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

0 commit comments

Comments
 (0)