Skip to content

Commit 5e4d51d

Browse files
authored
Merge pull request #30 from TG1999/vcs_urls
Add VCS Support
2 parents c341644 + 215930d commit 5e4d51d

File tree

419 files changed

+120560
-0
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

419 files changed

+120560
-0
lines changed

fetchcode/vcs/__init__.py

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
# fetchcode is a free software tool from nexB Inc. and others.
2+
# Visit https://github.com/nexB/fetchcode for support and download.
3+
#
4+
# Copyright (c) nexB Inc. and others. All rights reserved.
5+
# http://nexb.com and http://aboutcode.org
6+
#
7+
# This software is licensed under the Apache License version 2.0.
8+
#
9+
# You may not use this software except in compliance with the License.
10+
# You may obtain a copy of the License at:
11+
# http://apache.org/licenses/LICENSE-2.0
12+
# Unless required by applicable law or agreed to in writing, software distributed
13+
# under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
14+
# CONDITIONS OF ANY KIND, either express or implied. See the License for the
15+
# specific language governing permissions and limitations under the License.
16+
17+
import os
18+
import tempfile
19+
from urllib.parse import urlparse
20+
21+
from fetchcode.vcs.pip._internal.vcs.bazaar import Bazaar
22+
from fetchcode.vcs.pip._internal.vcs.git import Git
23+
from fetchcode.vcs.pip._internal.vcs.mercurial import Mercurial
24+
from fetchcode.vcs.pip._internal.utils import misc
25+
from fetchcode.vcs.pip._internal.vcs.subversion import Subversion
26+
from fetchcode.vcs.pip._internal.vcs import vcs
27+
28+
29+
class VCSResponse:
30+
"""
31+
Represent the response from fetching a VCS URL with:
32+
- `dest_dir`: destination of directory
33+
- `vcs_type`: VCS Type of URL (git,bzr,hg,svn)
34+
- `domain` : Source of git VCS (GitHub, Gitlab, Bitbucket)
35+
"""
36+
37+
def __init__(self, dest_dir, vcs_type, domain):
38+
self.dest_dir = dest_dir
39+
self.vcs_type = vcs_type
40+
self.domain = domain
41+
42+
43+
def fetch_via_vcs(url):
44+
"""
45+
Take `url` as input and store the content of it at location specified at `location` string
46+
Return a VCSResponse object
47+
"""
48+
parsed_url = urlparse(url)
49+
scheme = parsed_url.scheme
50+
domain = parsed_url.netloc
51+
temp = tempfile.mkdtemp()
52+
os.rmdir(temp)
53+
if scheme not in vcs.all_schemes:
54+
raise Exception("Not a supported/known scheme.")
55+
56+
for vcs_name, vcs_backend in vcs._registry.items():
57+
if scheme in vcs_backend.schemes:
58+
vcs_type = vcs_name
59+
60+
backend = vcs.get_backend_for_scheme(scheme)
61+
backend.obtain(dest=temp, url=misc.hide_url(url))
62+
63+
return VCSResponse(dest_dir=temp, vcs_type=vcs_type, domain=domain)

fetchcode/vcs/pip/__init__.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
from fetchcode.vcs.pip._internal.utils.typing import MYPY_CHECK_RUNNING
2+
3+
if MYPY_CHECK_RUNNING:
4+
from typing import List, Optional
5+
6+
7+
__version__ = "20.1.1"
8+
9+
10+
def main(args=None):
11+
# type: (Optional[List[str]]) -> int
12+
"""This is an internal API only meant for use by pip's own console scripts.
13+
14+
For additional details, see https://github.com/pypa/pip/issues/7498.
15+
"""
16+
from fetchcode.vcs.pip._internal.utils.entrypoints import _wrapper
17+
18+
return _wrapper(args)

fetchcode/vcs/pip/__main__.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
from __future__ import absolute_import
2+
3+
import os
4+
import sys
5+
6+
# Remove '' and current working directory from the first entry
7+
# of sys.path, if present to avoid using current directory
8+
# in pip commands check, freeze, install, list and show,
9+
# when invoked as python -m pip <command>
10+
if sys.path[0] in ('', os.getcwd()):
11+
sys.path.pop(0)
12+
13+
# If we are running from a wheel, add the wheel to sys.path
14+
# This allows the usage python pip-*.whl/pip install pip-*.whl
15+
if __package__ == '':
16+
# __file__ is pip-*.whl/pip/__main__.py
17+
# first dirname call strips of '/__main__.py', second strips off '/pip'
18+
# Resulting path is the name of the wheel itself
19+
# Add that to sys.path so we can import pip
20+
path = os.path.dirname(os.path.dirname(__file__))
21+
sys.path.insert(0, path)
22+
23+
from fetchcode.vcs.pip._internal.cli.main import main as _main # isort:skip # noqa
24+
25+
if __name__ == '__main__':
26+
sys.exit(_main())
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import fetchcode.vcs.pip._internal.utils.inject_securetransport # noqa
2+
from fetchcode.vcs.pip._internal.utils.typing import MYPY_CHECK_RUNNING
3+
4+
if MYPY_CHECK_RUNNING:
5+
from typing import Optional, List
6+
7+
8+
def main(args=None):
9+
# type: (Optional[List[str]]) -> int
10+
"""This is preserved for old console scripts that may still be referencing
11+
it.
12+
13+
For additional details, see https://github.com/pypa/pip/issues/7498.
14+
"""
15+
from fetchcode.vcs.pip._internal.utils.entrypoints import _wrapper
16+
17+
return _wrapper(args)
Lines changed: 219 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,219 @@
1+
"""Build Environment used for isolation during sdist building
2+
"""
3+
4+
# The following comment should be removed at some point in the future.
5+
# mypy: strict-optional=False
6+
# mypy: disallow-untyped-defs=False
7+
8+
import logging
9+
import os
10+
import sys
11+
import textwrap
12+
from collections import OrderedDict
13+
from distutils.sysconfig import get_python_lib
14+
from sysconfig import get_paths
15+
16+
from fetchcode.vcs.pip._vendor.pkg_resources import Requirement, VersionConflict, WorkingSet
17+
18+
from pip import __file__ as pip_location
19+
from fetchcode.vcs.pip._internal.cli.spinners import open_spinner
20+
from fetchcode.vcs.pip._internal.utils.subprocess import call_subprocess
21+
from fetchcode.vcs.pip._internal.utils.temp_dir import TempDirectory, tempdir_kinds
22+
from fetchcode.vcs.pip._internal.utils.typing import MYPY_CHECK_RUNNING
23+
24+
if MYPY_CHECK_RUNNING:
25+
from typing import Tuple, Set, Iterable, Optional, List
26+
from fetchcode.vcs.pip._internal.index.package_finder import PackageFinder
27+
28+
logger = logging.getLogger(__name__)
29+
30+
31+
class _Prefix:
32+
33+
def __init__(self, path):
34+
# type: (str) -> None
35+
self.path = path
36+
self.setup = False
37+
self.bin_dir = get_paths(
38+
'nt' if os.name == 'nt' else 'posix_prefix',
39+
vars={'base': path, 'platbase': path}
40+
)['scripts']
41+
# Note: prefer distutils' sysconfig to get the
42+
# library paths so PyPy is correctly supported.
43+
purelib = get_python_lib(plat_specific=False, prefix=path)
44+
platlib = get_python_lib(plat_specific=True, prefix=path)
45+
if purelib == platlib:
46+
self.lib_dirs = [purelib]
47+
else:
48+
self.lib_dirs = [purelib, platlib]
49+
50+
51+
class BuildEnvironment(object):
52+
"""Creates and manages an isolated environment to install build deps
53+
"""
54+
55+
def __init__(self):
56+
# type: () -> None
57+
temp_dir = TempDirectory(
58+
kind=tempdir_kinds.BUILD_ENV, globally_managed=True
59+
)
60+
61+
self._prefixes = OrderedDict((
62+
(name, _Prefix(os.path.join(temp_dir.path, name)))
63+
for name in ('normal', 'overlay')
64+
))
65+
66+
self._bin_dirs = [] # type: List[str]
67+
self._lib_dirs = [] # type: List[str]
68+
for prefix in reversed(list(self._prefixes.values())):
69+
self._bin_dirs.append(prefix.bin_dir)
70+
self._lib_dirs.extend(prefix.lib_dirs)
71+
72+
# Customize site to:
73+
# - ensure .pth files are honored
74+
# - prevent access to system site packages
75+
system_sites = {
76+
os.path.normcase(site) for site in (
77+
get_python_lib(plat_specific=False),
78+
get_python_lib(plat_specific=True),
79+
)
80+
}
81+
self._site_dir = os.path.join(temp_dir.path, 'site')
82+
if not os.path.exists(self._site_dir):
83+
os.mkdir(self._site_dir)
84+
with open(os.path.join(self._site_dir, 'sitecustomize.py'), 'w') as fp:
85+
fp.write(textwrap.dedent(
86+
'''
87+
import os, site, sys
88+
89+
# First, drop system-sites related paths.
90+
original_sys_path = sys.path[:]
91+
known_paths = set()
92+
for path in {system_sites!r}:
93+
site.addsitedir(path, known_paths=known_paths)
94+
system_paths = set(
95+
os.path.normcase(path)
96+
for path in sys.path[len(original_sys_path):]
97+
)
98+
original_sys_path = [
99+
path for path in original_sys_path
100+
if os.path.normcase(path) not in system_paths
101+
]
102+
sys.path = original_sys_path
103+
104+
# Second, add lib directories.
105+
# ensuring .pth file are processed.
106+
for path in {lib_dirs!r}:
107+
assert not path in sys.path
108+
site.addsitedir(path)
109+
'''
110+
).format(system_sites=system_sites, lib_dirs=self._lib_dirs))
111+
112+
def __enter__(self):
113+
self._save_env = {
114+
name: os.environ.get(name, None)
115+
for name in ('PATH', 'PYTHONNOUSERSITE', 'PYTHONPATH')
116+
}
117+
118+
path = self._bin_dirs[:]
119+
old_path = self._save_env['PATH']
120+
if old_path:
121+
path.extend(old_path.split(os.pathsep))
122+
123+
pythonpath = [self._site_dir]
124+
125+
os.environ.update({
126+
'PATH': os.pathsep.join(path),
127+
'PYTHONNOUSERSITE': '1',
128+
'PYTHONPATH': os.pathsep.join(pythonpath),
129+
})
130+
131+
def __exit__(self, exc_type, exc_val, exc_tb):
132+
for varname, old_value in self._save_env.items():
133+
if old_value is None:
134+
os.environ.pop(varname, None)
135+
else:
136+
os.environ[varname] = old_value
137+
138+
def check_requirements(self, reqs):
139+
# type: (Iterable[str]) -> Tuple[Set[Tuple[str, str]], Set[str]]
140+
"""Return 2 sets:
141+
- conflicting requirements: set of (installed, wanted) reqs tuples
142+
- missing requirements: set of reqs
143+
"""
144+
missing = set()
145+
conflicting = set()
146+
if reqs:
147+
ws = WorkingSet(self._lib_dirs)
148+
for req in reqs:
149+
try:
150+
if ws.find(Requirement.parse(req)) is None:
151+
missing.add(req)
152+
except VersionConflict as e:
153+
conflicting.add((str(e.args[0].as_requirement()),
154+
str(e.args[1])))
155+
return conflicting, missing
156+
157+
def install_requirements(
158+
self,
159+
finder, # type: PackageFinder
160+
requirements, # type: Iterable[str]
161+
prefix_as_string, # type: str
162+
message # type: Optional[str]
163+
):
164+
# type: (...) -> None
165+
prefix = self._prefixes[prefix_as_string]
166+
assert not prefix.setup
167+
prefix.setup = True
168+
if not requirements:
169+
return
170+
args = [
171+
sys.executable, os.path.dirname(pip_location), 'install',
172+
'--ignore-installed', '--no-user', '--prefix', prefix.path,
173+
'--no-warn-script-location',
174+
] # type: List[str]
175+
if logger.getEffectiveLevel() <= logging.DEBUG:
176+
args.append('-v')
177+
for format_control in ('no_binary', 'only_binary'):
178+
formats = getattr(finder.format_control, format_control)
179+
args.extend(('--' + format_control.replace('_', '-'),
180+
','.join(sorted(formats or {':none:'}))))
181+
182+
index_urls = finder.index_urls
183+
if index_urls:
184+
args.extend(['-i', index_urls[0]])
185+
for extra_index in index_urls[1:]:
186+
args.extend(['--extra-index-url', extra_index])
187+
else:
188+
args.append('--no-index')
189+
for link in finder.find_links:
190+
args.extend(['--find-links', link])
191+
192+
for host in finder.trusted_hosts:
193+
args.extend(['--trusted-host', host])
194+
if finder.allow_all_prereleases:
195+
args.append('--pre')
196+
args.append('--')
197+
args.extend(requirements)
198+
with open_spinner(message) as spinner:
199+
call_subprocess(args, spinner=spinner)
200+
201+
202+
class NoOpBuildEnvironment(BuildEnvironment):
203+
"""A no-op drop-in replacement for BuildEnvironment
204+
"""
205+
206+
def __init__(self):
207+
pass
208+
209+
def __enter__(self):
210+
pass
211+
212+
def __exit__(self, exc_type, exc_val, exc_tb):
213+
pass
214+
215+
def cleanup(self):
216+
pass
217+
218+
def install_requirements(self, finder, requirements, prefix, message):
219+
raise NotImplementedError()

0 commit comments

Comments
 (0)