diff options
Diffstat (limited to 'venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_internal/vcs/subversion.py')
| -rw-r--r-- | venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_internal/vcs/subversion.py | 271 |
1 files changed, 271 insertions, 0 deletions
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 @@ | |||
| 1 | from __future__ import absolute_import | ||
| 2 | |||
| 3 | import logging | ||
| 4 | import os | ||
| 5 | import re | ||
| 6 | |||
| 7 | from pip._vendor.six.moves.urllib import parse as urllib_parse | ||
| 8 | |||
| 9 | from pip._internal.index import Link | ||
| 10 | from pip._internal.utils.logging import indent_log | ||
| 11 | from pip._internal.utils.misc import display_path, rmtree | ||
| 12 | from 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 | |||
| 22 | logger = logging.getLogger(__name__) | ||
| 23 | |||
| 24 | |||
| 25 | class 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 | |||
| 243 | def 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 | |||
| 271 | vcs.register(Subversion) | ||
