Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions git_wrapper/remote.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,14 @@ def names(self):
"""
return [x.name for x in self.git_repo.repo.remotes]

def names_url_dict(self):
"""Returns a dict of remotes for a given repo with its url

:return dict: A dict of utf-8 encoded remote names with
url as its value
"""
return {x.name: x.url for x in self.git_repo.repo.remotes}

def add(self, name, url):
"""Adds a remote to the given repo

Expand Down Expand Up @@ -111,3 +119,28 @@ def fetch_all(self, prune=False, prune_tags=False):
if errors:
msg = f"Error fetching these remotes: {', '.join(errors)}"
raise exceptions.RemoteException(msg)

def remove(self, name):
"""Remove the specified remote from the given repo

:param str name: Remote name to remove
:return bool: True if the remote was removed, False otherwise
"""
working_dir = self.git_repo.repo.working_dir
self.logger.debug(f"Removing remote {name} from repo {working_dir}")
ret_status = False

try:
remote = self.git_repo.repo.remote(name)
except ValueError:
repo = self.git_repo.repo.working_dir
msg = f"Remote {name} does not exist on repo {repo}"
raise exceptions.ReferenceNotFoundException(msg)

try:
self.git_repo.repo.delete_remote(remote)
ret_status = True
except git.CommandError:
return ret_status

return ret_status
77 changes: 74 additions & 3 deletions tests/test_remote.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#! /usr/bin/env python
"""Tests for GitRemote"""

from dataclasses import dataclass
from mock import Mock

import git
Expand All @@ -10,14 +11,29 @@
from git_wrapper.repo import GitRepo


@dataclass
class RemoteNames:
name: str


@dataclass
class RemoteNamesUrl(RemoteNames):
url: str


def remote_generator(names):
"""Generates objects to be used with git.Repo.remotes call"""
ret_data = []
for name in names:
obj = type('', (), {})()
obj.name = name
ret_data.append(obj)
ret_data.append(RemoteNames(name))
return ret_data


def remote_generator_url(remotes):
"""Generates objects to be used with git.Repo.remotes call"""
ret_data = []
for name, url in remotes.items():
ret_data.append(RemoteNamesUrl(name, url))
return ret_data


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


def test_get_remotes_returns_dict(mock_repo):
"""
GIVEN GitRepo is initialized with a path and repo
WHEN remote.names_url_dict is called
THEN a dict of remote names with its url is returned
"""
expected = {'a': 1, 'b': 2, 'c': 3}
attrs = {'remotes': remote_generator_url(expected)}
mock_repo.configure_mock(**attrs)

git_util = GitRepo('./', mock_repo)

assert expected == git_util.remote.names_url_dict()


def test_add_remote_adds(mock_repo):
"""
GIVEN GitRepo initialized with a path and repo
Expand Down Expand Up @@ -89,6 +120,46 @@ def test_add_remote_update_fails(mock_repo):
delete_mock.assert_called_once_with(remote_mock)


def test_remove_remote_removes(mock_repo):
"""
GIVEN GitRepo initialized with a path and repo
WHEN remote.remove is called with a name and url
THEN a TRUE status is returned
"""
git_util = GitRepo('./', mock_repo)

assert git_util.remote.remove('origin') is True


def test_remove_remote_remote_fails(mock_repo):
"""
GIVEN GitRepo initialized with a path and repo
WHEN remote.remove is called with a name and url
AND the repo.remote fails with an exception
THEN a ReferenceNotFoundException is raised
"""
mock_repo.remote.side_effect = ValueError

repo = GitRepo(repo=mock_repo)
with pytest.raises(exceptions.ReferenceNotFoundException):
repo.remote.remove("doesntExist")

mock_repo.remote.assert_called_with("doesntExist")


def test_remove_remote_remove_fails(mock_repo):
"""
GIVEN GitRepo initialized with a path and repo
WHEN remote.remove is called with a name and url
AND the repo.delete_remote fails with an exception
THEN a False status is returned
"""
mock_repo.delete_remote.side_effect = git.CommandError('remove')
git_util = GitRepo('./', mock_repo)

assert git_util.remote.remove('rdo') is False


def test_fetch(mock_repo):
"""
GIVEN GitRepo is initialized with a path and repo
Expand Down