Merge pull request #6408 from cjerdonek/vcs-remove-url-attribute

Remove url as an attribute of VersionControl
This commit is contained in:
Chris Jerdonek 2019-05-07 15:17:56 -04:00 committed by GitHub
commit 0573d7f81f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 68 additions and 63 deletions

View File

@ -547,13 +547,16 @@ def is_archive_file(name):
def unpack_vcs_link(link, location):
vcs_backend = _get_used_vcs_backend(link)
vcs_backend.unpack(location)
vcs_backend.unpack(location, url=link.url)
def _get_used_vcs_backend(link):
"""
Return a VersionControl object or None.
"""
for backend in vcs.backends:
if link.scheme in backend.schemes:
vcs_backend = backend(link.url)
vcs_backend = backend()
return vcs_backend

View File

@ -786,13 +786,13 @@ class InstallRequirement(object):
if not self.update:
return
vc_type, url = self.link.url.split('+', 1)
backend = vcs.get_backend(vc_type)
if backend:
vcs_backend = backend(self.link.url)
vcs_backend = vcs.get_backend(vc_type)
if vcs_backend:
url = self.link.url
if obtain:
vcs_backend.obtain(self.source_dir)
vcs_backend.obtain(self.source_dir, url=url)
else:
vcs_backend.export(self.source_dir)
vcs_backend.export(self.source_dir, url=url)
else:
assert 0, (
'Unexpected version control type (in %s): %s'

View File

@ -636,7 +636,8 @@ def unpack_file(
is_svn_page(file_contents(filename))):
# We don't really care about this
from pip._internal.vcs.subversion import Subversion
Subversion('svn+' + link.url).unpack(location)
url = 'svn+' + link.url
Subversion().unpack(location, url=url)
else:
# FIXME: handle?
# FIXME: magic signatures?

View File

@ -188,10 +188,14 @@ class VcsSupport(object):
return None
def get_backend(self, name):
# type: (str) -> Optional[Type[VersionControl]]
# type: (str) -> Optional[VersionControl]
"""
Return a VersionControl object or None.
"""
name = name.lower()
if name in self._registry:
return self._registry[name]
vc_type = self._registry[name]
return vc_type()
return None
@ -257,10 +261,6 @@ class VersionControl(object):
return req
def __init__(self, url=None, *args, **kwargs):
self.url = url
super(VersionControl, self).__init__(*args, **kwargs)
@staticmethod
def get_base_rev_args(rev):
"""
@ -293,10 +293,12 @@ class VersionControl(object):
drive, tail = os.path.splitdrive(repo)
return repo.startswith(os.path.sep) or bool(drive)
def export(self, location):
def export(self, location, url):
"""
Export the repository at the url to the destination location
i.e. only download the files, without vcs informations
:param url: the repository URL starting with a vcs prefix.
"""
raise NotImplementedError
@ -422,16 +424,16 @@ class VersionControl(object):
"""
raise NotImplementedError
def obtain(self, dest):
# type: (str) -> None
def obtain(self, dest, url):
# type: (str, str) -> None
"""
Install or update in editable mode the package represented by this
VersionControl object.
Args:
dest: the repository directory in which to install or update.
:param dest: the repository directory in which to install or update.
:param url: the repository URL starting with a vcs prefix.
"""
url, rev_options = self.get_url_rev_options(self.url)
url, rev_options = self.get_url_rev_options(url)
if not os.path.exists(dest):
self.fetch_new(dest, url, rev_options)
@ -515,15 +517,17 @@ class VersionControl(object):
)
self.switch(dest, url, rev_options)
def unpack(self, location):
# type: (str) -> None
def unpack(self, location, url):
# type: (str, str) -> None
"""
Clean up current location and download the url repository
(and vcs infos) into location
:param url: the repository URL starting with a vcs prefix.
"""
if os.path.exists(location):
rmtree(location)
self.obtain(location)
self.obtain(location, url=url)
@classmethod
def get_remote_url(cls, location):

View File

@ -21,8 +21,8 @@ class Bazaar(VersionControl):
'bzr+lp',
)
def __init__(self, url=None, *args, **kwargs):
super(Bazaar, self).__init__(url, *args, **kwargs)
def __init__(self, *args, **kwargs):
super(Bazaar, self).__init__(*args, **kwargs)
# This is only needed for python <2.7.5
# Register lp but do not expose as a scheme to support bzr+lp.
if getattr(urllib_parse, 'uses_fragment', None):
@ -32,7 +32,7 @@ class Bazaar(VersionControl):
def get_base_rev_args(rev):
return ['-r', rev]
def export(self, location):
def export(self, location, url):
"""
Export the Bazaar repository at the url to the destination location
"""
@ -40,7 +40,7 @@ class Bazaar(VersionControl):
if os.path.exists(location):
rmtree(location)
url, rev_options = self.get_url_rev_options(self.url)
url, rev_options = self.get_url_rev_options(url)
self.run_command(
['export', location, url] + rev_options.to_args(),
show_stdout=False,

View File

@ -40,27 +40,6 @@ class Git(VersionControl):
unset_environ = ('GIT_DIR', 'GIT_WORK_TREE')
default_arg_rev = 'HEAD'
def __init__(self, url=None, *args, **kwargs):
# Works around an apparent Git bug
# (see https://article.gmane.org/gmane.comp.version-control.git/146500)
if url:
scheme, netloc, path, query, fragment = urlsplit(url)
if scheme.endswith('file'):
initial_slashes = path[:-len(path.lstrip('/'))]
newpath = (
initial_slashes +
urllib_request.url2pathname(path)
.replace('\\', '/').lstrip('/')
)
url = urlunsplit((scheme, netloc, newpath, query, fragment))
after_plus = scheme.find('+') + 1
url = scheme[:after_plus] + urlunsplit(
(scheme[after_plus:], netloc, newpath, query, fragment),
)
super(Git, self).__init__(url, *args, **kwargs)
@staticmethod
def get_base_rev_args(rev):
return [rev]
@ -99,13 +78,13 @@ class Git(VersionControl):
return None
def export(self, location):
def export(self, location, url):
"""Export the Git repository at the url to the destination location"""
if not location.endswith('/'):
location = location + '/'
with TempDirectory(kind="export") as temp_dir:
self.unpack(temp_dir.path)
self.unpack(temp_dir.path, url=url)
self.run_command(
['checkout-index', '-a', '-f', '--prefix', location],
show_stdout=False, cwd=temp_dir.path
@ -324,6 +303,22 @@ class Git(VersionControl):
work with a ssh:// scheme (e.g. GitHub). But we need a scheme for
parsing. Hence we remove it again afterwards and return it as a stub.
"""
# Works around an apparent Git bug
# (see https://article.gmane.org/gmane.comp.version-control.git/146500)
scheme, netloc, path, query, fragment = urlsplit(url)
if scheme.endswith('file'):
initial_slashes = path[:-len(path.lstrip('/'))]
newpath = (
initial_slashes +
urllib_request.url2pathname(path)
.replace('\\', '/').lstrip('/')
)
url = urlunsplit((scheme, netloc, newpath, query, fragment))
after_plus = scheme.find('+') + 1
url = scheme[:after_plus] + urlunsplit(
(scheme[after_plus:], netloc, newpath, query, fragment),
)
if '://' not in url:
assert 'file:' not in url
url = url.replace('git+', 'git+ssh://')

View File

@ -23,10 +23,10 @@ class Mercurial(VersionControl):
def get_base_rev_args(rev):
return [rev]
def export(self, location):
def export(self, location, url):
"""Export the Hg repository at the url to the destination location"""
with TempDirectory(kind="export") as temp_dir:
self.unpack(temp_dir.path)
self.unpack(temp_dir.path, url=url)
self.run_command(
['archive', location], show_stdout=False, cwd=temp_dir.path

View File

@ -67,9 +67,9 @@ class Subversion(VersionControl):
return parsed_version
def export(self, location):
def export(self, location, url):
"""Export the svn repository at the url to the destination location"""
url, rev_options = self.get_url_rev_options(self.url)
url, rev_options = self.get_url_rev_options(url)
logger.info('Exporting svn repository %s to %s', url, location)
with indent_log():

View File

@ -7,8 +7,9 @@ from pip._internal.vcs.subversion import Subversion
@patch('pip._internal.vcs.call_subprocess')
@pytest.mark.network
def test_obtain_should_recognize_auth_info_url(call_subprocess_mock, script):
svn = Subversion(url='svn+http://username:password@svn.example.com/')
svn.obtain(script.scratch_path / 'test')
url = 'svn+http://username:password@svn.example.com/'
svn = Subversion()
svn.obtain(script.scratch_path / 'test', url=url)
assert call_subprocess_mock.call_args[0][0] == [
svn.name, 'checkout', '-q', '--username', 'username', '--password',
'password', 'http://svn.example.com/',
@ -19,8 +20,9 @@ def test_obtain_should_recognize_auth_info_url(call_subprocess_mock, script):
@patch('pip._internal.vcs.call_subprocess')
@pytest.mark.network
def test_export_should_recognize_auth_info_url(call_subprocess_mock, script):
svn = Subversion(url='svn+http://username:password@svn.example.com/')
svn.export(script.scratch_path / 'test')
url = 'svn+http://username:password@svn.example.com/'
svn = Subversion()
svn.export(script.scratch_path / 'test', url=url)
assert call_subprocess_mock.call_args[0][0] == [
svn.name, 'export', '--username', 'username', '--password',
'password', 'http://svn.example.com/',

View File

@ -30,9 +30,9 @@ def test_export(script, tmpdir):
_vcs_add(script, str(source_dir), vcs='bazaar')
bzr = Bazaar('bzr+' + _test_path_to_file_url(source_dir))
export_dir = str(tmpdir / 'export')
bzr.export(export_dir)
url = 'bzr+' + _test_path_to_file_url(source_dir)
Bazaar().export(export_dir, url=url)
assert os.listdir(export_dir) == ['test_file']
@ -54,9 +54,9 @@ def test_export_rev(script, tmpdir):
'-m', 'change test file', cwd=source_dir,
)
bzr = Bazaar('bzr+' + _test_path_to_file_url(source_dir) + '@1')
export_dir = tmpdir / 'export'
bzr.export(str(export_dir))
url = 'bzr+' + _test_path_to_file_url(source_dir) + '@1'
Bazaar().export(str(export_dir), url=url)
with open(export_dir / 'test_file', 'r') as f:
assert f.read() == 'something initial'

View File

@ -59,7 +59,7 @@ def _get_vcs_and_checkout_url(remote_repository, directory):
destination_path = os.path.join(directory, repository_name)
if not os.path.exists(destination_path):
vcs_class(remote_repository).obtain(destination_path)
vcs_class().obtain(destination_path, url=remote_repository)
return '%s+%s' % (
vcs,
path_to_url('/'.join([directory, repository_name, branch])),