Skip to content

Commit

Permalink
Merge pull request #6095 from cjerdonek/freeze-repo-with-no-remote
Browse files Browse the repository at this point in the history
Address #4759: change freeze to support editable Git repos with no remote
  • Loading branch information
cjerdonek authored Jan 6, 2019
2 parents 740b1ac + 61bb651 commit e155b47
Show file tree
Hide file tree
Showing 7 changed files with 72 additions and 22 deletions.
1 change: 1 addition & 0 deletions news/4759.bugfix
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Editable Git installs without a remote now freeze as editable.
11 changes: 10 additions & 1 deletion src/pip/_internal/operations/freeze.py
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ def get_requirement_info(dist):

location = os.path.normcase(os.path.abspath(dist.location))

from pip._internal.vcs import vcs
from pip._internal.vcs import vcs, RemoteNotFoundError
vc_type = vcs.get_backend_type(location)

if not vc_type:
Expand All @@ -188,6 +188,15 @@ def get_requirement_info(dist):

try:
req = vc_type().get_src_requirement(location, dist.project_name)
except RemoteNotFoundError:
req = dist.as_requirement()
comments = [
'# Editable {} install with no remote ({})'.format(
vc_type.__name__, req,
)
]
return (location, True, comments)

except BadCommand:
logger.warning(
'cannot determine version of editable source in %s '
Expand Down
7 changes: 7 additions & 0 deletions src/pip/_internal/vcs/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@
logger = logging.getLogger(__name__)


class RemoteNotFoundError(Exception):
pass


class RevOptions(object):

"""
Expand Down Expand Up @@ -452,6 +456,9 @@ def get_src_requirement(self, location, project_name):
def get_remote_url(self, location):
"""
Return the url used at location
Raises RemoteNotFoundError if the repository does not have a remote
url configured.
"""
raise NotImplementedError

Expand Down
23 changes: 17 additions & 6 deletions src/pip/_internal/vcs/git.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
display_path, make_vcs_requirement_url, redact_password_from_url,
)
from pip._internal.utils.temp_dir import TempDirectory
from pip._internal.vcs import VersionControl, vcs
from pip._internal.vcs import RemoteNotFoundError, VersionControl, vcs

urlsplit = urllib_parse.urlsplit
urlunsplit = urllib_parse.urlunsplit
Expand Down Expand Up @@ -250,13 +250,24 @@ def update(self, dest, url, rev_options):
self.update_submodules(dest)

def get_remote_url(self, location):
"""Return URL of the first remote encountered."""
remotes = self.run_command(
"""
Return URL of the first remote encountered.
Raises RemoteNotFoundError if the repository does not have a remote
url configured.
"""
# We need to pass 1 for extra_ok_returncodes since the command
# exits with return code 1 if there are no matching lines.
stdout = self.run_command(
['config', '--get-regexp', r'remote\..*\.url'],
show_stdout=False, cwd=location,
extra_ok_returncodes=(1, ), show_stdout=False, cwd=location,
)
remotes = remotes.splitlines()
found_remote = remotes[0]
remotes = stdout.splitlines()
try:
found_remote = remotes[0]
except IndexError:
raise RemoteNotFoundError

for remote in remotes:
if remote.startswith('remote.origin.url '):
found_remote = remote
Expand Down
20 changes: 20 additions & 0 deletions tests/functional/test_freeze.py
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,26 @@ def test_freeze_editable_not_vcs(script, tmpdir):
_check_output(result.stdout, expected)


@pytest.mark.git
def test_freeze_editable_git_with_no_remote(script, tmpdir):
"""
Test an editable Git install with no remote url.
"""
pkg_path = _create_test_package(script)
script.pip('install', '-e', pkg_path)
result = script.pip('freeze')

assert result.stderr == ''

# We need to apply os.path.normcase() to the path since that is what
# the freeze code does.
expected = textwrap.dedent("""\
...# Editable Git install with no remote (version-pkg==0.1)
-e {}
...""".format(os.path.normcase(pkg_path)))
_check_output(result.stdout, expected)


@pytest.mark.svn
def test_freeze_svn(script, tmpdir):
"""Test freezing a svn checkout"""
Expand Down
14 changes: 0 additions & 14 deletions tests/functional/test_install_vcs_git.py
Original file line number Diff line number Diff line change
Expand Up @@ -367,20 +367,6 @@ def test_git_with_ambiguous_revs(script):
result.assert_installed('version-pkg', with_files=['.git'])


def test_git_works_with_editable_non_origin_repo(script):
# set up, create a git repo and install it as editable from a local
# directory path
version_pkg_path = _create_test_package(script)
script.pip('install', '-e', version_pkg_path.abspath)

# 'freeze'ing this should not fall over, but should result in stderr output
# warning
result = script.pip('freeze', expect_stderr=True)
assert "Error when trying to get requirement" in result.stderr
assert "Could not determine repository location" in result.stdout
assert "version-pkg==0.1" in result.stdout


def test_editable__no_revision(script):
"""
Test a basic install in editable mode specifying no revision.
Expand Down
18 changes: 17 additions & 1 deletion tests/functional/test_vcs_git.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@

import os

from pip._internal.vcs.git import Git
import pytest

from pip._internal.vcs.git import Git, RemoteNotFoundError
from tests.lib import _create_test_package, _git_commit, _test_path_to_file_url


Expand Down Expand Up @@ -93,6 +95,20 @@ def test_get_remote_url(script, tmpdir):
assert remote_url == source_url


def test_get_remote_url__no_remote(script, tmpdir):
"""
Test a repo with no remote.
"""
repo_dir = tmpdir / 'temp-repo'
repo_dir.mkdir()
repo_dir = str(repo_dir)

script.run('git', 'init', cwd=repo_dir)

with pytest.raises(RemoteNotFoundError):
Git().get_remote_url(repo_dir)


def test_get_current_branch(script):
repo_dir = str(script.scratch_path)

Expand Down

0 comments on commit e155b47

Please sign in to comment.