summaryrefslogtreecommitdiff
path: root/venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_internal/vcs
diff options
context:
space:
mode:
Diffstat (limited to 'venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_internal/vcs')
-rw-r--r--venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_internal/vcs/__init__.py471
-rw-r--r--venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_internal/vcs/bazaar.py113
-rw-r--r--venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_internal/vcs/git.py311
-rw-r--r--venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_internal/vcs/mercurial.py105
-rw-r--r--venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_internal/vcs/subversion.py271
5 files changed, 1271 insertions, 0 deletions
diff --git a/venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_internal/vcs/__init__.py b/venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_internal/vcs/__init__.py
new file mode 100644
index 0000000..bff94fa
--- /dev/null
+++ b/venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_internal/vcs/__init__.py
@@ -0,0 +1,471 @@
1"""Handles all VCS (version control) support"""
2from __future__ import absolute_import
3
4import copy
5import errno
6import logging
7import os
8import shutil
9import sys
10
11from pip._vendor.six.moves.urllib import parse as urllib_parse
12
13from pip._internal.exceptions import BadCommand
14from pip._internal.utils.misc import (
15 display_path, backup_dir, call_subprocess, rmtree, ask_path_exists,
16)
17from pip._internal.utils.typing import MYPY_CHECK_RUNNING
18
19if MYPY_CHECK_RUNNING:
20 from typing import Dict, Optional, Tuple
21 from pip._internal.basecommand import Command
22
23__all__ = ['vcs', 'get_src_requirement']
24
25
26logger = logging.getLogger(__name__)
27
28
29class RevOptions(object):
30
31 """
32 Encapsulates a VCS-specific revision to install, along with any VCS
33 install options.
34
35 Instances of this class should be treated as if immutable.
36 """
37
38 def __init__(self, vcs, rev=None, extra_args=None):
39 """
40 Args:
41 vcs: a VersionControl object.
42 rev: the name of the revision to install.
43 extra_args: a list of extra options.
44 """
45 if extra_args is None:
46 extra_args = []
47
48 self.extra_args = extra_args
49 self.rev = rev
50 self.vcs = vcs
51
52 def __repr__(self):
53 return '<RevOptions {}: rev={!r}>'.format(self.vcs.name, self.rev)
54
55 @property
56 def arg_rev(self):
57 if self.rev is None:
58 return self.vcs.default_arg_rev
59
60 return self.rev
61
62 def to_args(self):
63 """
64 Return the VCS-specific command arguments.
65 """
66 args = []
67 rev = self.arg_rev
68 if rev is not None:
69 args += self.vcs.get_base_rev_args(rev)
70 args += self.extra_args
71
72 return args
73
74 def to_display(self):
75 if not self.rev:
76 return ''
77
78 return ' (to revision {})'.format(self.rev)
79
80 def make_new(self, rev):
81 """
82 Make a copy of the current instance, but with a new rev.
83
84 Args:
85 rev: the name of the revision for the new object.
86 """
87 return self.vcs.make_rev_options(rev, extra_args=self.extra_args)
88
89
90class VcsSupport(object):
91 _registry = {} # type: Dict[str, Command]
92 schemes = ['ssh', 'git', 'hg', 'bzr', 'sftp', 'svn']
93
94 def __init__(self):
95 # Register more schemes with urlparse for various version control
96 # systems
97 urllib_parse.uses_netloc.extend(self.schemes)
98 # Python >= 2.7.4, 3.3 doesn't have uses_fragment
99 if getattr(urllib_parse, 'uses_fragment', None):
100 urllib_parse.uses_fragment.extend(self.schemes)
101 super(VcsSupport, self).__init__()
102
103 def __iter__(self):
104 return self._registry.__iter__()
105
106 @property
107 def backends(self):
108 return list(self._registry.values())
109
110 @property
111 def dirnames(self):
112 return [backend.dirname for backend in self.backends]
113
114 @property
115 def all_schemes(self):
116 schemes = []
117 for backend in self.backends:
118 schemes.extend(backend.schemes)
119 return schemes
120
121 def register(self, cls):
122 if not hasattr(cls, 'name'):
123 logger.warning('Cannot register VCS %s', cls.__name__)
124 return
125 if cls.name not in self._registry:
126 self._registry[cls.name] = cls
127 logger.debug('Registered VCS backend: %s', cls.name)
128
129 def unregister(self, cls=None, name=None):
130 if name in self._registry:
131 del self._registry[name]
132 elif cls in self._registry.values():
133 del self._registry[cls.name]
134 else:
135 logger.warning('Cannot unregister because no class or name given')
136
137 def get_backend_name(self, location):
138 """
139 Return the name of the version control backend if found at given
140 location, e.g. vcs.get_backend_name('/path/to/vcs/checkout')
141 """
142 for vc_type in self._registry.values():
143 if vc_type.controls_location(location):
144 logger.debug('Determine that %s uses VCS: %s',
145 location, vc_type.name)
146 return vc_type.name
147 return None
148
149 def get_backend(self, name):
150 name = name.lower()
151 if name in self._registry:
152 return self._registry[name]
153
154 def get_backend_from_location(self, location):
155 vc_type = self.get_backend_name(location)
156 if vc_type:
157 return self.get_backend(vc_type)
158 return None
159
160
161vcs = VcsSupport()
162
163
164class VersionControl(object):
165 name = ''
166 dirname = ''
167 # List of supported schemes for this Version Control
168 schemes = () # type: Tuple[str, ...]
169 # Iterable of environment variable names to pass to call_subprocess().
170 unset_environ = () # type: Tuple[str, ...]
171 default_arg_rev = None # type: Optional[str]
172
173 def __init__(self, url=None, *args, **kwargs):
174 self.url = url
175 super(VersionControl, self).__init__(*args, **kwargs)
176
177 def get_base_rev_args(self, rev):
178 """
179 Return the base revision arguments for a vcs command.
180
181 Args:
182 rev: the name of a revision to install. Cannot be None.
183 """
184 raise NotImplementedError
185
186 def make_rev_options(self, rev=None, extra_args=None):
187 """
188 Return a RevOptions object.
189
190 Args:
191 rev: the name of a revision to install.
192 extra_args: a list of extra options.
193 """
194 return RevOptions(self, rev, extra_args=extra_args)
195
196 def _is_local_repository(self, repo):
197 """
198 posix absolute paths start with os.path.sep,
199 win32 ones start with drive (like c:\\folder)
200 """
201 drive, tail = os.path.splitdrive(repo)
202 return repo.startswith(os.path.sep) or drive
203
204 # See issue #1083 for why this method was introduced:
205 # https://github.com/pypa/pip/issues/1083
206 def translate_egg_surname(self, surname):
207 # For example, Django has branches of the form "stable/1.7.x".
208 return surname.replace('/', '_')
209
210 def export(self, location):
211 """
212 Export the repository at the url to the destination location
213 i.e. only download the files, without vcs informations
214 """
215 raise NotImplementedError
216
217 def get_url_rev(self):
218 """
219 Returns the correct repository URL and revision by parsing the given
220 repository URL
221 """
222 error_message = (
223 "Sorry, '%s' is a malformed VCS url. "
224 "The format is <vcs>+<protocol>://<url>, "
225 "e.g. svn+http://myrepo/svn/MyApp#egg=MyApp"
226 )
227 assert '+' in self.url, error_message % self.url
228 url = self.url.split('+', 1)[1]
229 scheme, netloc, path, query, frag = urllib_parse.urlsplit(url)
230 rev = None
231 if '@' in path:
232 path, rev = path.rsplit('@', 1)
233 url = urllib_parse.urlunsplit((scheme, netloc, path, query, ''))
234 return url, rev
235
236 def get_info(self, location):
237 """
238 Returns (url, revision), where both are strings
239 """
240 assert not location.rstrip('/').endswith(self.dirname), \
241 'Bad directory: %s' % location
242 return self.get_url(location), self.get_revision(location)
243
244 def normalize_url(self, url):
245 """
246 Normalize a URL for comparison by unquoting it and removing any
247 trailing slash.
248 """
249 return urllib_parse.unquote(url).rstrip('/')
250
251 def compare_urls(self, url1, url2):
252 """
253 Compare two repo URLs for identity, ignoring incidental differences.
254 """
255 return (self.normalize_url(url1) == self.normalize_url(url2))
256
257 def obtain(self, dest):
258 """
259 Called when installing or updating an editable package, takes the
260 source path of the checkout.
261 """
262 raise NotImplementedError
263
264 def switch(self, dest, url, rev_options):
265 """
266 Switch the repo at ``dest`` to point to ``URL``.
267
268 Args:
269 rev_options: a RevOptions object.
270 """
271 raise NotImplementedError
272
273 def update(self, dest, rev_options):
274 """
275 Update an already-existing repo to the given ``rev_options``.
276
277 Args:
278 rev_options: a RevOptions object.
279 """
280 raise NotImplementedError
281
282 def is_commit_id_equal(self, dest, name):
283 """
284 Return whether the id of the current commit equals the given name.
285
286 Args:
287 dest: the repository directory.
288 name: a string name.
289 """
290 raise NotImplementedError
291
292 def check_destination(self, dest, url, rev_options):
293 """
294 Prepare a location to receive a checkout/clone.
295
296 Return True if the location is ready for (and requires) a
297 checkout/clone, False otherwise.
298
299 Args:
300 rev_options: a RevOptions object.
301 """
302 checkout = True
303 prompt = False
304 rev_display = rev_options.to_display()
305 if os.path.exists(dest):
306 checkout = False
307 if os.path.exists(os.path.join(dest, self.dirname)):
308 existing_url = self.get_url(dest)
309 if self.compare_urls(existing_url, url):
310 logger.debug(
311 '%s in %s exists, and has correct URL (%s)',
312 self.repo_name.title(),
313 display_path(dest),
314 url,
315 )
316 if not self.is_commit_id_equal(dest, rev_options.rev):
317 logger.info(
318 'Updating %s %s%s',
319 display_path(dest),
320 self.repo_name,
321 rev_display,
322 )
323 self.update(dest, rev_options)
324 else:
325 logger.info(
326 'Skipping because already up-to-date.')
327 else:
328 logger.warning(
329 '%s %s in %s exists with URL %s',
330 self.name,
331 self.repo_name,
332 display_path(dest),
333 existing_url,
334 )
335 prompt = ('(s)witch, (i)gnore, (w)ipe, (b)ackup ',
336 ('s', 'i', 'w', 'b'))
337 else:
338 logger.warning(
339 'Directory %s already exists, and is not a %s %s.',
340 dest,
341 self.name,
342 self.repo_name,
343 )
344 prompt = ('(i)gnore, (w)ipe, (b)ackup ', ('i', 'w', 'b'))
345 if prompt:
346 logger.warning(
347 'The plan is to install the %s repository %s',
348 self.name,
349 url,
350 )
351 response = ask_path_exists('What to do? %s' % prompt[0],
352 prompt[1])
353
354 if response == 's':
355 logger.info(
356 'Switching %s %s to %s%s',
357 self.repo_name,
358 display_path(dest),
359 url,
360 rev_display,
361 )
362 self.switch(dest, url, rev_options)
363 elif response == 'i':
364 # do nothing
365 pass
366 elif response == 'w':
367 logger.warning('Deleting %s', display_path(dest))
368 rmtree(dest)
369 checkout = True
370 elif response == 'b':
371 dest_dir = backup_dir(dest)
372 logger.warning(
373 'Backing up %s to %s', display_path(dest), dest_dir,
374 )
375 shutil.move(dest, dest_dir)
376 checkout = True
377 elif response == 'a':
378 sys.exit(-1)
379 return checkout
380
381 def unpack(self, location):
382 """
383 Clean up current location and download the url repository
384 (and vcs infos) into location
385 """
386 if os.path.exists(location):
387 rmtree(location)
388 self.obtain(location)
389
390 def get_src_requirement(self, dist, location):
391 """
392 Return a string representing the requirement needed to
393 redownload the files currently present in location, something
394 like:
395 {repository_url}@{revision}#egg={project_name}-{version_identifier}
396 """
397 raise NotImplementedError
398
399 def get_url(self, location):
400 """
401 Return the url used at location
402 Used in get_info or check_destination
403 """
404 raise NotImplementedError
405
406 def get_revision(self, location):
407 """
408 Return the current commit id of the files at the given location.
409 """
410 raise NotImplementedError
411
412 def run_command(self, cmd, show_stdout=True, cwd=None,
413 on_returncode='raise',
414 command_desc=None,
415 extra_environ=None, spinner=None):
416 """
417 Run a VCS subcommand
418 This is simply a wrapper around call_subprocess that adds the VCS
419 command name, and checks that the VCS is available
420 """
421 cmd = [self.name] + cmd
422 try:
423 return call_subprocess(cmd, show_stdout, cwd,
424 on_returncode,
425 command_desc, extra_environ,
426 unset_environ=self.unset_environ,
427 spinner=spinner)
428 except OSError as e:
429 # errno.ENOENT = no such file or directory
430 # In other words, the VCS executable isn't available
431 if e.errno == errno.ENOENT:
432 raise BadCommand(
433 'Cannot find command %r - do you have '
434 '%r installed and in your '
435 'PATH?' % (self.name, self.name))
436 else:
437 raise # re-raise exception if a different error occurred
438
439 @classmethod
440 def controls_location(cls, location):
441 """
442 Check if a location is controlled by the vcs.
443 It is meant to be overridden to implement smarter detection
444 mechanisms for specific vcs.
445 """
446 logger.debug('Checking in %s for %s (%s)...',
447 location, cls.dirname, cls.name)
448 path = os.path.join(location, cls.dirname)
449 return os.path.exists(path)
450
451
452def get_src_requirement(dist, location):
453 version_control = vcs.get_backend_from_location(location)
454 if version_control:
455 try:
456 return version_control().get_src_requirement(dist,
457 location)
458 except BadCommand:
459 logger.warning(
460 'cannot determine version of editable source in %s '
461 '(%s command not found in path)',
462 location,
463 version_control.name,
464 )
465 return dist.as_requirement()
466 logger.warning(
467 'cannot determine version of editable source in %s (is not SVN '
468 'checkout, Git clone, Mercurial clone or Bazaar branch)',
469 location,
470 )
471 return dist.as_requirement()
diff --git a/venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_internal/vcs/bazaar.py b/venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_internal/vcs/bazaar.py
new file mode 100644
index 0000000..6ed629a
--- /dev/null
+++ b/venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_internal/vcs/bazaar.py
@@ -0,0 +1,113 @@
1from __future__ import absolute_import
2
3import logging
4import os
5
6from pip._vendor.six.moves.urllib import parse as urllib_parse
7
8from pip._internal.download import path_to_url
9from pip._internal.utils.misc import display_path, rmtree
10from pip._internal.utils.temp_dir import TempDirectory
11from pip._internal.vcs import VersionControl, vcs
12
13logger = logging.getLogger(__name__)
14
15
16class Bazaar(VersionControl):
17 name = 'bzr'
18 dirname = '.bzr'
19 repo_name = 'branch'
20 schemes = (
21 'bzr', 'bzr+http', 'bzr+https', 'bzr+ssh', 'bzr+sftp', 'bzr+ftp',
22 'bzr+lp',
23 )
24
25 def __init__(self, url=None, *args, **kwargs):
26 super(Bazaar, self).__init__(url, *args, **kwargs)
27 # This is only needed for python <2.7.5
28 # Register lp but do not expose as a scheme to support bzr+lp.
29 if getattr(urllib_parse, 'uses_fragment', None):
30 urllib_parse.uses_fragment.extend(['lp'])
31
32 def get_base_rev_args(self, rev):
33 return ['-r', rev]
34
35 def export(self, location):
36 """
37 Export the Bazaar repository at the url to the destination location
38 """
39 # Remove the location to make sure Bazaar can export it correctly
40 if os.path.exists(location):
41 rmtree(location)
42
43 with TempDirectory(kind="export") as temp_dir:
44 self.unpack(temp_dir.path)
45
46 self.run_command(
47 ['export', location],
48 cwd=temp_dir.path, show_stdout=False,
49 )
50
51 def switch(self, dest, url, rev_options):
52 self.run_command(['switch', url], cwd=dest)
53
54 def update(self, dest, rev_options):
55 cmd_args = ['pull', '-q'] + rev_options.to_args()
56 self.run_command(cmd_args, cwd=dest)
57
58 def obtain(self, dest):
59 url, rev = self.get_url_rev()
60 rev_options = self.make_rev_options(rev)
61 if self.check_destination(dest, url, rev_options):
62 rev_display = rev_options.to_display()
63 logger.info(
64 'Checking out %s%s to %s',
65 url,
66 rev_display,
67 display_path(dest),
68 )
69 cmd_args = ['branch', '-q'] + rev_options.to_args() + [url, dest]
70 self.run_command(cmd_args)
71
72 def get_url_rev(self):
73 # hotfix the URL scheme after removing bzr+ from bzr+ssh:// readd it
74 url, rev = super(Bazaar, self).get_url_rev()
75 if url.startswith('ssh://'):
76 url = 'bzr+' + url
77 return url, rev
78
79 def get_url(self, location):
80 urls = self.run_command(['info'], show_stdout=False, cwd=location)
81 for line in urls.splitlines():
82 line = line.strip()
83 for x in ('checkout of branch: ',
84 'parent branch: '):
85 if line.startswith(x):
86 repo = line.split(x)[1]
87 if self._is_local_repository(repo):
88 return path_to_url(repo)
89 return repo
90 return None
91
92 def get_revision(self, location):
93 revision = self.run_command(
94 ['revno'], show_stdout=False, cwd=location,
95 )
96 return revision.splitlines()[-1]
97
98 def get_src_requirement(self, dist, location):
99 repo = self.get_url(location)
100 if not repo:
101 return None
102 if not repo.lower().startswith('bzr:'):
103 repo = 'bzr+' + repo
104 egg_project_name = dist.egg_name().split('-', 1)[0]
105 current_rev = self.get_revision(location)
106 return '%s@%s#egg=%s' % (repo, current_rev, egg_project_name)
107
108 def is_commit_id_equal(self, dest, name):
109 """Always assume the versions don't match"""
110 return False
111
112
113vcs.register(Bazaar)
diff --git a/venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_internal/vcs/git.py b/venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_internal/vcs/git.py
new file mode 100644
index 0000000..7a63dfa
--- /dev/null
+++ b/venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_internal/vcs/git.py
@@ -0,0 +1,311 @@
1from __future__ import absolute_import
2
3import logging
4import os.path
5import re
6
7from pip._vendor.packaging.version import parse as parse_version
8from pip._vendor.six.moves.urllib import parse as urllib_parse
9from pip._vendor.six.moves.urllib import request as urllib_request
10
11from pip._internal.compat import samefile
12from pip._internal.exceptions import BadCommand
13from pip._internal.utils.misc import display_path
14from pip._internal.utils.temp_dir import TempDirectory
15from pip._internal.vcs import VersionControl, vcs
16
17urlsplit = urllib_parse.urlsplit
18urlunsplit = urllib_parse.urlunsplit
19
20
21logger = logging.getLogger(__name__)
22
23
24HASH_REGEX = re.compile('[a-fA-F0-9]{40}')
25
26
27def looks_like_hash(sha):
28 return bool(HASH_REGEX.match(sha))
29
30
31class Git(VersionControl):
32 name = 'git'
33 dirname = '.git'
34 repo_name = 'clone'
35 schemes = (
36 'git', 'git+http', 'git+https', 'git+ssh', 'git+git', 'git+file',
37 )
38 # Prevent the user's environment variables from interfering with pip:
39 # https://github.com/pypa/pip/issues/1130
40 unset_environ = ('GIT_DIR', 'GIT_WORK_TREE')
41 default_arg_rev = 'HEAD'
42
43 def __init__(self, url=None, *args, **kwargs):
44
45 # Works around an apparent Git bug
46 # (see http://article.gmane.org/gmane.comp.version-control.git/146500)
47 if url:
48 scheme, netloc, path, query, fragment = urlsplit(url)
49 if scheme.endswith('file'):
50 initial_slashes = path[:-len(path.lstrip('/'))]
51 newpath = (
52 initial_slashes +
53 urllib_request.url2pathname(path)
54 .replace('\\', '/').lstrip('/')
55 )
56 url = urlunsplit((scheme, netloc, newpath, query, fragment))
57 after_plus = scheme.find('+') + 1
58 url = scheme[:after_plus] + urlunsplit(
59 (scheme[after_plus:], netloc, newpath, query, fragment),
60 )
61
62 super(Git, self).__init__(url, *args, **kwargs)
63
64 def get_base_rev_args(self, rev):
65 return [rev]
66
67 def get_git_version(self):
68 VERSION_PFX = 'git version '
69 version = self.run_command(['version'], show_stdout=False)
70 if version.startswith(VERSION_PFX):
71 version = version[len(VERSION_PFX):].split()[0]
72 else:
73 version = ''
74 # get first 3 positions of the git version becasue
75 # on windows it is x.y.z.windows.t, and this parses as
76 # LegacyVersion which always smaller than a Version.
77 version = '.'.join(version.split('.')[:3])
78 return parse_version(version)
79
80 def export(self, location):
81 """Export the Git repository at the url to the destination location"""
82 if not location.endswith('/'):
83 location = location + '/'
84
85 with TempDirectory(kind="export") as temp_dir:
86 self.unpack(temp_dir.path)
87 self.run_command(
88 ['checkout-index', '-a', '-f', '--prefix', location],
89 show_stdout=False, cwd=temp_dir.path
90 )
91
92 def get_revision_sha(self, dest, rev):
93 """
94 Return a commit hash for the given revision if it names a remote
95 branch or tag. Otherwise, return None.
96
97 Args:
98 dest: the repository directory.
99 rev: the revision name.
100 """
101 # Pass rev to pre-filter the list.
102 output = self.run_command(['show-ref', rev], cwd=dest,
103 show_stdout=False, on_returncode='ignore')
104 refs = {}
105 for line in output.strip().splitlines():
106 try:
107 sha, ref = line.split()
108 except ValueError:
109 # Include the offending line to simplify troubleshooting if
110 # this error ever occurs.
111 raise ValueError('unexpected show-ref line: {!r}'.format(line))
112
113 refs[ref] = sha
114
115 branch_ref = 'refs/remotes/origin/{}'.format(rev)
116 tag_ref = 'refs/tags/{}'.format(rev)
117
118 return refs.get(branch_ref) or refs.get(tag_ref)
119
120 def check_rev_options(self, dest, rev_options):
121 """Check the revision options before checkout.
122
123 Returns a new RevOptions object for the SHA1 of the branch or tag
124 if found.
125
126 Args:
127 rev_options: a RevOptions object.
128 """
129 rev = rev_options.arg_rev
130 sha = self.get_revision_sha(dest, rev)
131
132 if sha is not None:
133 return rev_options.make_new(sha)
134
135 # Do not show a warning for the common case of something that has
136 # the form of a Git commit hash.
137 if not looks_like_hash(rev):
138 logger.warning(
139 "Did not find branch or tag '%s', assuming revision or ref.",
140 rev,
141 )
142 return rev_options
143
144 def is_commit_id_equal(self, dest, name):
145 """
146 Return whether the current commit hash equals the given name.
147
148 Args:
149 dest: the repository directory.
150 name: a string name.
151 """
152 if not name:
153 # Then avoid an unnecessary subprocess call.
154 return False
155
156 return self.get_revision(dest) == name
157
158 def switch(self, dest, url, rev_options):
159 self.run_command(['config', 'remote.origin.url', url], cwd=dest)
160 cmd_args = ['checkout', '-q'] + rev_options.to_args()
161 self.run_command(cmd_args, cwd=dest)
162
163 self.update_submodules(dest)
164
165 def update(self, dest, rev_options):
166 # First fetch changes from the default remote
167 if self.get_git_version() >= parse_version('1.9.0'):
168 # fetch tags in addition to everything else
169 self.run_command(['fetch', '-q', '--tags'], cwd=dest)
170 else:
171 self.run_command(['fetch', '-q'], cwd=dest)
172 # Then reset to wanted revision (maybe even origin/master)
173 rev_options = self.check_rev_options(dest, rev_options)
174 cmd_args = ['reset', '--hard', '-q'] + rev_options.to_args()
175 self.run_command(cmd_args, cwd=dest)
176 #: update submodules
177 self.update_submodules(dest)
178
179 def obtain(self, dest):
180 url, rev = self.get_url_rev()
181 rev_options = self.make_rev_options(rev)
182 if self.check_destination(dest, url, rev_options):
183 rev_display = rev_options.to_display()
184 logger.info(
185 'Cloning %s%s to %s', url, rev_display, display_path(dest),
186 )
187 self.run_command(['clone', '-q', url, dest])
188
189 if rev:
190 rev_options = self.check_rev_options(dest, rev_options)
191 # Only do a checkout if the current commit id doesn't match
192 # the requested revision.
193 if not self.is_commit_id_equal(dest, rev_options.rev):
194 rev = rev_options.rev
195 # Only fetch the revision if it's a ref
196 if rev.startswith('refs/'):
197 self.run_command(
198 ['fetch', '-q', url] + rev_options.to_args(),
199 cwd=dest,
200 )
201 # Change the revision to the SHA of the ref we fetched
202 rev = 'FETCH_HEAD'
203 self.run_command(['checkout', '-q', rev], cwd=dest)
204
205 #: repo may contain submodules
206 self.update_submodules(dest)
207
208 def get_url(self, location):
209 """Return URL of the first remote encountered."""
210 remotes = self.run_command(
211 ['config', '--get-regexp', r'remote\..*\.url'],
212 show_stdout=False, cwd=location,
213 )
214 remotes = remotes.splitlines()
215 found_remote = remotes[0]
216 for remote in remotes:
217 if remote.startswith('remote.origin.url '):
218 found_remote = remote
219 break
220 url = found_remote.split(' ')[1]
221 return url.strip()
222
223 def get_revision(self, location):
224 current_rev = self.run_command(
225 ['rev-parse', 'HEAD'], show_stdout=False, cwd=location,
226 )
227 return current_rev.strip()
228
229 def _get_subdirectory(self, location):
230 """Return the relative path of setup.py to the git repo root."""
231 # find the repo root
232 git_dir = self.run_command(['rev-parse', '--git-dir'],
233 show_stdout=False, cwd=location).strip()
234 if not os.path.isabs(git_dir):
235 git_dir = os.path.join(location, git_dir)
236 root_dir = os.path.join(git_dir, '..')
237 # find setup.py
238 orig_location = location
239 while not os.path.exists(os.path.join(location, 'setup.py')):
240 last_location = location
241 location = os.path.dirname(location)
242 if location == last_location:
243 # We've traversed up to the root of the filesystem without
244 # finding setup.py
245 logger.warning(
246 "Could not find setup.py for directory %s (tried all "
247 "parent directories)",
248 orig_location,
249 )
250 return None
251 # relative path of setup.py to repo root
252 if samefile(root_dir, location):
253 return None
254 return os.path.relpath(location, root_dir)
255
256 def get_src_requirement(self, dist, location):
257 repo = self.get_url(location)
258 if not repo.lower().startswith('git:'):
259 repo = 'git+' + repo
260 egg_project_name = dist.egg_name().split('-', 1)[0]
261 if not repo:
262 return None
263 current_rev = self.get_revision(location)
264 req = '%s@%s#egg=%s' % (repo, current_rev, egg_project_name)
265 subdirectory = self._get_subdirectory(location)
266 if subdirectory:
267 req += '&subdirectory=' + subdirectory
268 return req
269
270 def get_url_rev(self):
271 """
272 Prefixes stub URLs like 'user@hostname:user/repo.git' with 'ssh://'.
273 That's required because although they use SSH they sometimes doesn't
274 work with a ssh:// scheme (e.g. Github). But we need a scheme for
275 parsing. Hence we remove it again afterwards and return it as a stub.
276 """
277 if '://' not in self.url:
278 assert 'file:' not in self.url
279 self.url = self.url.replace('git+', 'git+ssh://')
280 url, rev = super(Git, self).get_url_rev()
281 url = url.replace('ssh://', '')
282 else:
283 url, rev = super(Git, self).get_url_rev()
284
285 return url, rev
286
287 def update_submodules(self, location):
288 if not os.path.exists(os.path.join(location, '.gitmodules')):
289 return
290 self.run_command(
291 ['submodule', 'update', '--init', '--recursive', '-q'],
292 cwd=location,
293 )
294
295 @classmethod
296 def controls_location(cls, location):
297 if super(Git, cls).controls_location(location):
298 return True
299 try:
300 r = cls().run_command(['rev-parse'],
301 cwd=location,
302 show_stdout=False,
303 on_returncode='ignore')
304 return not r
305 except BadCommand:
306 logger.debug("could not determine if %s is under git control "
307 "because git is not available", location)
308 return False
309
310
311vcs.register(Git)
diff --git a/venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_internal/vcs/mercurial.py b/venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_internal/vcs/mercurial.py
new file mode 100644
index 0000000..3936473
--- /dev/null
+++ b/venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_internal/vcs/mercurial.py
@@ -0,0 +1,105 @@
1from __future__ import absolute_import
2
3import logging
4import os
5
6from pip._vendor.six.moves import configparser
7
8from pip._internal.download import path_to_url
9from pip._internal.utils.misc import display_path
10from pip._internal.utils.temp_dir import TempDirectory
11from pip._internal.vcs import VersionControl, vcs
12
13logger = logging.getLogger(__name__)
14
15
16class Mercurial(VersionControl):
17 name = 'hg'
18 dirname = '.hg'
19 repo_name = 'clone'
20 schemes = ('hg', 'hg+http', 'hg+https', 'hg+ssh', 'hg+static-http')
21
22 def get_base_rev_args(self, rev):
23 return [rev]
24
25 def export(self, location):
26 """Export the Hg repository at the url to the destination location"""
27 with TempDirectory(kind="export") as temp_dir:
28 self.unpack(temp_dir.path)
29
30 self.run_command(
31 ['archive', location], show_stdout=False, cwd=temp_dir.path
32 )
33
34 def switch(self, dest, url, rev_options):
35 repo_config = os.path.join(dest, self.dirname, 'hgrc')
36 config = configparser.SafeConfigParser()
37 try:
38 config.read(repo_config)
39 config.set('paths', 'default', url)
40 with open(repo_config, 'w') as config_file:
41 config.write(config_file)
42 except (OSError, configparser.NoSectionError) as exc:
43 logger.warning(
44 'Could not switch Mercurial repository to %s: %s', url, exc,
45 )
46 else:
47 cmd_args = ['update', '-q'] + rev_options.to_args()
48 self.run_command(cmd_args, cwd=dest)
49
50 def update(self, dest, rev_options):
51 self.run_command(['pull', '-q'], cwd=dest)
52 cmd_args = ['update', '-q'] + rev_options.to_args()
53 self.run_command(cmd_args, cwd=dest)
54
55 def obtain(self, dest):
56 url, rev = self.get_url_rev()
57 rev_options = self.make_rev_options(rev)
58 if self.check_destination(dest, url, rev_options):
59 rev_display = rev_options.to_display()
60 logger.info(
61 'Cloning hg %s%s to %s',
62 url,
63 rev_display,
64 display_path(dest),
65 )
66 self.run_command(['clone', '--noupdate', '-q', url, dest])
67 cmd_args = ['update', '-q'] + rev_options.to_args()
68 self.run_command(cmd_args, cwd=dest)
69
70 def get_url(self, location):
71 url = self.run_command(
72 ['showconfig', 'paths.default'],
73 show_stdout=False, cwd=location).strip()
74 if self._is_local_repository(url):
75 url = path_to_url(url)
76 return url.strip()
77
78 def get_revision(self, location):
79 current_revision = self.run_command(
80 ['parents', '--template={rev}'],
81 show_stdout=False, cwd=location).strip()
82 return current_revision
83
84 def get_revision_hash(self, location):
85 current_rev_hash = self.run_command(
86 ['parents', '--template={node}'],
87 show_stdout=False, cwd=location).strip()
88 return current_rev_hash
89
90 def get_src_requirement(self, dist, location):
91 repo = self.get_url(location)
92 if not repo.lower().startswith('hg:'):
93 repo = 'hg+' + repo
94 egg_project_name = dist.egg_name().split('-', 1)[0]
95 if not repo:
96 return None
97 current_rev_hash = self.get_revision_hash(location)
98 return '%s@%s#egg=%s' % (repo, current_rev_hash, egg_project_name)
99
100 def is_commit_id_equal(self, dest, name):
101 """Always assume the versions don't match"""
102 return False
103
104
105vcs.register(Mercurial)
diff --git a/venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_internal/vcs/subversion.py b/venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_internal/vcs/subversion.py
new file mode 100644
index 0000000..95e5440
--- /dev/null
+++ b/venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_internal/vcs/subversion.py
@@ -0,0 +1,271 @@
1from __future__ import absolute_import
2
3import logging
4import os
5import re
6
7from pip._vendor.six.moves.urllib import parse as urllib_parse
8
9from pip._internal.index import Link
10from pip._internal.utils.logging import indent_log
11from pip._internal.utils.misc import display_path, rmtree
12from pip._internal.vcs import VersionControl, vcs
13
14_svn_xml_url_re = re.compile('url="([^"]+)"')
15_svn_rev_re = re.compile(r'committed-rev="(\d+)"')
16_svn_url_re = re.compile(r'URL: (.+)')
17_svn_revision_re = re.compile(r'Revision: (.+)')
18_svn_info_xml_rev_re = re.compile(r'\s*revision="(\d+)"')
19_svn_info_xml_url_re = re.compile(r'<url>(.*)</url>')
20
21
22logger = logging.getLogger(__name__)
23
24
25class Subversion(VersionControl):
26 name = 'svn'
27 dirname = '.svn'
28 repo_name = 'checkout'
29 schemes = ('svn', 'svn+ssh', 'svn+http', 'svn+https', 'svn+svn')
30
31 def get_base_rev_args(self, rev):
32 return ['-r', rev]
33
34 def get_info(self, location):
35 """Returns (url, revision), where both are strings"""
36 assert not location.rstrip('/').endswith(self.dirname), \
37 'Bad directory: %s' % location
38 output = self.run_command(
39 ['info', location],
40 show_stdout=False,
41 extra_environ={'LANG': 'C'},
42 )
43 match = _svn_url_re.search(output)
44 if not match:
45 logger.warning(
46 'Cannot determine URL of svn checkout %s',
47 display_path(location),
48 )
49 logger.debug('Output that cannot be parsed: \n%s', output)
50 return None, None
51 url = match.group(1).strip()
52 match = _svn_revision_re.search(output)
53 if not match:
54 logger.warning(
55 'Cannot determine revision of svn checkout %s',
56 display_path(location),
57 )
58 logger.debug('Output that cannot be parsed: \n%s', output)
59 return url, None
60 return url, match.group(1)
61
62 def export(self, location):
63 """Export the svn repository at the url to the destination location"""
64 url, rev = self.get_url_rev()
65 rev_options = get_rev_options(self, url, rev)
66 url = self.remove_auth_from_url(url)
67 logger.info('Exporting svn repository %s to %s', url, location)
68 with indent_log():
69 if os.path.exists(location):
70 # Subversion doesn't like to check out over an existing
71 # directory --force fixes this, but was only added in svn 1.5
72 rmtree(location)
73 cmd_args = ['export'] + rev_options.to_args() + [url, location]
74 self.run_command(cmd_args, show_stdout=False)
75
76 def switch(self, dest, url, rev_options):
77 cmd_args = ['switch'] + rev_options.to_args() + [url, dest]
78 self.run_command(cmd_args)
79
80 def update(self, dest, rev_options):
81 cmd_args = ['update'] + rev_options.to_args() + [dest]
82 self.run_command(cmd_args)
83
84 def obtain(self, dest):
85 url, rev = self.get_url_rev()
86 rev_options = get_rev_options(self, url, rev)
87 url = self.remove_auth_from_url(url)
88 if self.check_destination(dest, url, rev_options):
89 rev_display = rev_options.to_display()
90 logger.info(
91 'Checking out %s%s to %s',
92 url,
93 rev_display,
94 display_path(dest),
95 )
96 cmd_args = ['checkout', '-q'] + rev_options.to_args() + [url, dest]
97 self.run_command(cmd_args)
98
99 def get_location(self, dist, dependency_links):
100 for url in dependency_links:
101 egg_fragment = Link(url).egg_fragment
102 if not egg_fragment:
103 continue
104 if '-' in egg_fragment:
105 # FIXME: will this work when a package has - in the name?
106 key = '-'.join(egg_fragment.split('-')[:-1]).lower()
107 else:
108 key = egg_fragment
109 if key == dist.key:
110 return url.split('#', 1)[0]
111 return None
112
113 def get_revision(self, location):
114 """
115 Return the maximum revision for all files under a given location
116 """
117 # Note: taken from setuptools.command.egg_info
118 revision = 0
119
120 for base, dirs, files in os.walk(location):
121 if self.dirname not in dirs:
122 dirs[:] = []
123 continue # no sense walking uncontrolled subdirs
124 dirs.remove(self.dirname)
125 entries_fn = os.path.join(base, self.dirname, 'entries')
126 if not os.path.exists(entries_fn):
127 # FIXME: should we warn?
128 continue
129
130 dirurl, localrev = self._get_svn_url_rev(base)
131
132 if base == location:
133 base = dirurl + '/' # save the root url
134 elif not dirurl or not dirurl.startswith(base):
135 dirs[:] = []
136 continue # not part of the same svn tree, skip it
137 revision = max(revision, localrev)
138 return revision
139
140 def get_url_rev(self):
141 # hotfix the URL scheme after removing svn+ from svn+ssh:// readd it
142 url, rev = super(Subversion, self).get_url_rev()
143 if url.startswith('ssh://'):
144 url = 'svn+' + url
145 return url, rev
146
147 def get_url(self, location):
148 # In cases where the source is in a subdirectory, not alongside
149 # setup.py we have to look up in the location until we find a real
150 # setup.py
151 orig_location = location
152 while not os.path.exists(os.path.join(location, 'setup.py')):
153 last_location = location
154 location = os.path.dirname(location)
155 if location == last_location:
156 # We've traversed up to the root of the filesystem without
157 # finding setup.py
158 logger.warning(
159 "Could not find setup.py for directory %s (tried all "
160 "parent directories)",
161 orig_location,
162 )
163 return None
164
165 return self._get_svn_url_rev(location)[0]
166
167 def _get_svn_url_rev(self, location):
168 from pip._internal.exceptions import InstallationError
169
170 entries_path = os.path.join(location, self.dirname, 'entries')
171 if os.path.exists(entries_path):
172 with open(entries_path) as f:
173 data = f.read()
174 else: # subversion >= 1.7 does not have the 'entries' file
175 data = ''
176
177 if (data.startswith('8') or
178 data.startswith('9') or
179 data.startswith('10')):
180 data = list(map(str.splitlines, data.split('\n\x0c\n')))
181 del data[0][0] # get rid of the '8'
182 url = data[0][3]
183 revs = [int(d[9]) for d in data if len(d) > 9 and d[9]] + [0]
184 elif data.startswith('<?xml'):
185 match = _svn_xml_url_re.search(data)
186 if not match:
187 raise ValueError('Badly formatted data: %r' % data)
188 url = match.group(1) # get repository URL
189 revs = [int(m.group(1)) for m in _svn_rev_re.finditer(data)] + [0]
190 else:
191 try:
192 # subversion >= 1.7
193 xml = self.run_command(
194 ['info', '--xml', location],
195 show_stdout=False,
196 )
197 url = _svn_info_xml_url_re.search(xml).group(1)
198 revs = [
199 int(m.group(1)) for m in _svn_info_xml_rev_re.finditer(xml)
200 ]
201 except InstallationError:
202 url, revs = None, []
203
204 if revs:
205 rev = max(revs)
206 else:
207 rev = 0
208
209 return url, rev
210
211 def get_src_requirement(self, dist, location):
212 repo = self.get_url(location)
213 if repo is None:
214 return None
215 # FIXME: why not project name?
216 egg_project_name = dist.egg_name().split('-', 1)[0]
217 rev = self.get_revision(location)
218 return 'svn+%s@%s#egg=%s' % (repo, rev, egg_project_name)
219
220 def is_commit_id_equal(self, dest, name):
221 """Always assume the versions don't match"""
222 return False
223
224 @staticmethod
225 def remove_auth_from_url(url):
226 # Return a copy of url with 'username:password@' removed.
227 # username/pass params are passed to subversion through flags
228 # and are not recognized in the url.
229
230 # parsed url
231 purl = urllib_parse.urlsplit(url)
232 stripped_netloc = \
233 purl.netloc.split('@')[-1]
234
235 # stripped url
236 url_pieces = (
237 purl.scheme, stripped_netloc, purl.path, purl.query, purl.fragment
238 )
239 surl = urllib_parse.urlunsplit(url_pieces)
240 return surl
241
242
243def get_rev_options(vcs, url, rev):
244 """
245 Return a RevOptions object.
246 """
247 r = urllib_parse.urlsplit(url)
248 if hasattr(r, 'username'):
249 # >= Python-2.5
250 username, password = r.username, r.password
251 else:
252 netloc = r[1]
253 if '@' in netloc:
254 auth = netloc.split('@')[0]
255 if ':' in auth:
256 username, password = auth.split(':', 1)
257 else:
258 username, password = auth, None
259 else:
260 username, password = None, None
261
262 extra_args = []
263 if username:
264 extra_args += ['--username', username]
265 if password:
266 extra_args += ['--password', password]
267
268 return vcs.make_rev_options(rev, extra_args=extra_args)
269
270
271vcs.register(Subversion)