Mercurial > repos > bcclaywell > argo_navis
comparison venv/lib/python2.7/site-packages/pip/vcs/git.py @ 0:d67268158946 draft
planemo upload commit a3f181f5f126803c654b3a66dd4e83a48f7e203b
author | bcclaywell |
---|---|
date | Mon, 12 Oct 2015 17:43:33 -0400 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:d67268158946 |
---|---|
1 from __future__ import absolute_import | |
2 | |
3 import logging | |
4 import tempfile | |
5 import os.path | |
6 | |
7 from pip._vendor.six.moves.urllib import parse as urllib_parse | |
8 from pip._vendor.six.moves.urllib import request as urllib_request | |
9 | |
10 from pip.utils import display_path, rmtree | |
11 from pip.vcs import vcs, VersionControl | |
12 | |
13 | |
14 urlsplit = urllib_parse.urlsplit | |
15 urlunsplit = urllib_parse.urlunsplit | |
16 | |
17 | |
18 logger = logging.getLogger(__name__) | |
19 | |
20 | |
21 class Git(VersionControl): | |
22 name = 'git' | |
23 dirname = '.git' | |
24 repo_name = 'clone' | |
25 schemes = ( | |
26 'git', 'git+http', 'git+https', 'git+ssh', 'git+git', 'git+file', | |
27 ) | |
28 | |
29 def __init__(self, url=None, *args, **kwargs): | |
30 | |
31 # Works around an apparent Git bug | |
32 # (see http://article.gmane.org/gmane.comp.version-control.git/146500) | |
33 if url: | |
34 scheme, netloc, path, query, fragment = urlsplit(url) | |
35 if scheme.endswith('file'): | |
36 initial_slashes = path[:-len(path.lstrip('/'))] | |
37 newpath = ( | |
38 initial_slashes + | |
39 urllib_request.url2pathname(path) | |
40 .replace('\\', '/').lstrip('/') | |
41 ) | |
42 url = urlunsplit((scheme, netloc, newpath, query, fragment)) | |
43 after_plus = scheme.find('+') + 1 | |
44 url = scheme[:after_plus] + urlunsplit( | |
45 (scheme[after_plus:], netloc, newpath, query, fragment), | |
46 ) | |
47 | |
48 super(Git, self).__init__(url, *args, **kwargs) | |
49 | |
50 def export(self, location): | |
51 """Export the Git repository at the url to the destination location""" | |
52 temp_dir = tempfile.mkdtemp('-export', 'pip-') | |
53 self.unpack(temp_dir) | |
54 try: | |
55 if not location.endswith('/'): | |
56 location = location + '/' | |
57 self.run_command( | |
58 ['checkout-index', '-a', '-f', '--prefix', location], | |
59 filter_stdout=self._filter, show_stdout=False, cwd=temp_dir) | |
60 finally: | |
61 rmtree(temp_dir) | |
62 | |
63 def check_rev_options(self, rev, dest, rev_options): | |
64 """Check the revision options before checkout to compensate that tags | |
65 and branches may need origin/ as a prefix. | |
66 Returns the SHA1 of the branch or tag if found. | |
67 """ | |
68 revisions = self.get_refs(dest) | |
69 | |
70 origin_rev = 'origin/%s' % rev | |
71 if origin_rev in revisions: | |
72 # remote branch | |
73 return [revisions[origin_rev]] | |
74 elif rev in revisions: | |
75 # a local tag or branch name | |
76 return [revisions[rev]] | |
77 else: | |
78 logger.warning( | |
79 "Could not find a tag or branch '%s', assuming commit.", rev, | |
80 ) | |
81 return rev_options | |
82 | |
83 def switch(self, dest, url, rev_options): | |
84 self.run_command(['config', 'remote.origin.url', url], cwd=dest) | |
85 self.run_command(['checkout', '-q'] + rev_options, cwd=dest) | |
86 | |
87 self.update_submodules(dest) | |
88 | |
89 def update(self, dest, rev_options): | |
90 # First fetch changes from the default remote | |
91 self.run_command(['fetch', '-q'], cwd=dest) | |
92 # Then reset to wanted revision (maby even origin/master) | |
93 if rev_options: | |
94 rev_options = self.check_rev_options( | |
95 rev_options[0], dest, rev_options, | |
96 ) | |
97 self.run_command(['reset', '--hard', '-q'] + rev_options, cwd=dest) | |
98 #: update submodules | |
99 self.update_submodules(dest) | |
100 | |
101 def obtain(self, dest): | |
102 url, rev = self.get_url_rev() | |
103 if rev: | |
104 rev_options = [rev] | |
105 rev_display = ' (to %s)' % rev | |
106 else: | |
107 rev_options = ['origin/master'] | |
108 rev_display = '' | |
109 if self.check_destination(dest, url, rev_options, rev_display): | |
110 logger.info( | |
111 'Cloning %s%s to %s', url, rev_display, display_path(dest), | |
112 ) | |
113 self.run_command(['clone', '-q', url, dest]) | |
114 | |
115 if rev: | |
116 rev_options = self.check_rev_options(rev, dest, rev_options) | |
117 # Only do a checkout if rev_options differs from HEAD | |
118 if not self.get_revision(dest).startswith(rev_options[0]): | |
119 self.run_command( | |
120 ['checkout', '-q'] + rev_options, | |
121 cwd=dest, | |
122 ) | |
123 #: repo may contain submodules | |
124 self.update_submodules(dest) | |
125 | |
126 def get_url(self, location): | |
127 url = self.run_command( | |
128 ['config', 'remote.origin.url'], | |
129 show_stdout=False, cwd=location) | |
130 return url.strip() | |
131 | |
132 def get_revision(self, location): | |
133 current_rev = self.run_command( | |
134 ['rev-parse', 'HEAD'], show_stdout=False, cwd=location) | |
135 return current_rev.strip() | |
136 | |
137 def get_refs(self, location): | |
138 """Return map of named refs (branches or tags) to commit hashes.""" | |
139 output = self.run_command(['show-ref'], | |
140 show_stdout=False, cwd=location) | |
141 rv = {} | |
142 for line in output.strip().splitlines(): | |
143 commit, ref = line.split(' ', 1) | |
144 ref = ref.strip() | |
145 ref_name = None | |
146 if ref.startswith('refs/remotes/'): | |
147 ref_name = ref[len('refs/remotes/'):] | |
148 elif ref.startswith('refs/heads/'): | |
149 ref_name = ref[len('refs/heads/'):] | |
150 elif ref.startswith('refs/tags/'): | |
151 ref_name = ref[len('refs/tags/'):] | |
152 if ref_name is not None: | |
153 rv[ref_name] = commit.strip() | |
154 return rv | |
155 | |
156 def get_src_requirement(self, dist, location, find_tags): | |
157 repo = self.get_url(location) | |
158 if not repo.lower().startswith('git:'): | |
159 repo = 'git+' + repo | |
160 egg_project_name = dist.egg_name().split('-', 1)[0] | |
161 if not repo: | |
162 return None | |
163 current_rev = self.get_revision(location) | |
164 refs = self.get_refs(location) | |
165 # refs maps names to commit hashes; we need the inverse | |
166 # if multiple names map to a single commit, we pick the first one | |
167 # alphabetically | |
168 names_by_commit = {} | |
169 for ref, commit in sorted(refs.items()): | |
170 if commit not in names_by_commit: | |
171 names_by_commit[commit] = ref | |
172 | |
173 if current_rev in names_by_commit: | |
174 # It's a tag or branch. | |
175 name = names_by_commit[current_rev] | |
176 full_egg_name = ( | |
177 '%s-%s' % (egg_project_name, self.translate_egg_surname(name)) | |
178 ) | |
179 else: | |
180 full_egg_name = '%s-dev' % egg_project_name | |
181 | |
182 return '%s@%s#egg=%s' % (repo, current_rev, full_egg_name) | |
183 | |
184 def get_url_rev(self): | |
185 """ | |
186 Prefixes stub URLs like 'user@hostname:user/repo.git' with 'ssh://'. | |
187 That's required because although they use SSH they sometimes doesn't | |
188 work with a ssh:// scheme (e.g. Github). But we need a scheme for | |
189 parsing. Hence we remove it again afterwards and return it as a stub. | |
190 """ | |
191 if '://' not in self.url: | |
192 assert 'file:' not in self.url | |
193 self.url = self.url.replace('git+', 'git+ssh://') | |
194 url, rev = super(Git, self).get_url_rev() | |
195 url = url.replace('ssh://', '') | |
196 else: | |
197 url, rev = super(Git, self).get_url_rev() | |
198 | |
199 return url, rev | |
200 | |
201 def update_submodules(self, location): | |
202 if not os.path.exists(os.path.join(location, '.gitmodules')): | |
203 return | |
204 self.run_command( | |
205 ['submodule', 'update', '--init', '--recursive', '-q'], | |
206 cwd=location, | |
207 ) | |
208 | |
209 vcs.register(Git) |