diff options
Diffstat (limited to 'main.py')
-rwxr-xr-x | main.py | 169 |
1 files changed, 160 insertions, 9 deletions
@@ -22,19 +22,27 @@ if __name__ == '__main__': | |||
22 | del sys.argv[-1] | 22 | del sys.argv[-1] |
23 | del magic | 23 | del magic |
24 | 24 | ||
25 | import netrc | ||
25 | import optparse | 26 | import optparse |
26 | import os | 27 | import os |
27 | import re | 28 | import re |
28 | import sys | 29 | import sys |
30 | import time | ||
31 | import urllib2 | ||
29 | 32 | ||
30 | from trace import SetTrace | 33 | from trace import SetTrace |
34 | from git_command import git, GitCommand | ||
31 | from git_config import init_ssh, close_ssh | 35 | from git_config import init_ssh, close_ssh |
32 | from command import InteractiveCommand | 36 | from command import InteractiveCommand |
33 | from command import MirrorSafeCommand | 37 | from command import MirrorSafeCommand |
34 | from command import PagedCommand | 38 | from command import PagedCommand |
39 | from subcmds.version import Version | ||
40 | from editor import Editor | ||
41 | from error import DownloadError | ||
35 | from error import ManifestInvalidRevisionError | 42 | from error import ManifestInvalidRevisionError |
36 | from error import NoSuchProjectError | 43 | from error import NoSuchProjectError |
37 | from error import RepoChangedException | 44 | from error import RepoChangedException |
45 | from manifest_xml import XmlManifest | ||
38 | from pager import RunPager | 46 | from pager import RunPager |
39 | 47 | ||
40 | from subcmds import all as all_commands | 48 | from subcmds import all as all_commands |
@@ -51,6 +59,9 @@ global_options.add_option('--no-pager', | |||
51 | global_options.add_option('--trace', | 59 | global_options.add_option('--trace', |
52 | dest='trace', action='store_true', | 60 | dest='trace', action='store_true', |
53 | help='trace git command execution') | 61 | help='trace git command execution') |
62 | global_options.add_option('--time', | ||
63 | dest='time', action='store_true', | ||
64 | help='time repo command execution') | ||
54 | global_options.add_option('--version', | 65 | global_options.add_option('--version', |
55 | dest='show_version', action='store_true', | 66 | dest='show_version', action='store_true', |
56 | help='display this version of repo') | 67 | help='display this version of repo') |
@@ -63,6 +74,7 @@ class _Repo(object): | |||
63 | all_commands['branch'] = all_commands['branches'] | 74 | all_commands['branch'] = all_commands['branches'] |
64 | 75 | ||
65 | def _Run(self, argv): | 76 | def _Run(self, argv): |
77 | result = 0 | ||
66 | name = None | 78 | name = None |
67 | glob = [] | 79 | glob = [] |
68 | 80 | ||
@@ -86,7 +98,7 @@ class _Repo(object): | |||
86 | name = 'version' | 98 | name = 'version' |
87 | else: | 99 | else: |
88 | print >>sys.stderr, 'fatal: invalid usage of --version' | 100 | print >>sys.stderr, 'fatal: invalid usage of --version' |
89 | sys.exit(1) | 101 | return 1 |
90 | 102 | ||
91 | try: | 103 | try: |
92 | cmd = self.commands[name] | 104 | cmd = self.commands[name] |
@@ -94,15 +106,17 @@ class _Repo(object): | |||
94 | print >>sys.stderr,\ | 106 | print >>sys.stderr,\ |
95 | "repo: '%s' is not a repo command. See 'repo help'."\ | 107 | "repo: '%s' is not a repo command. See 'repo help'."\ |
96 | % name | 108 | % name |
97 | sys.exit(1) | 109 | return 1 |
98 | 110 | ||
99 | cmd.repodir = self.repodir | 111 | cmd.repodir = self.repodir |
112 | cmd.manifest = XmlManifest(cmd.repodir) | ||
113 | Editor.globalConfig = cmd.manifest.globalConfig | ||
100 | 114 | ||
101 | if not isinstance(cmd, MirrorSafeCommand) and cmd.manifest.IsMirror: | 115 | if not isinstance(cmd, MirrorSafeCommand) and cmd.manifest.IsMirror: |
102 | print >>sys.stderr, \ | 116 | print >>sys.stderr, \ |
103 | "fatal: '%s' requires a working directory"\ | 117 | "fatal: '%s' requires a working directory"\ |
104 | % name | 118 | % name |
105 | sys.exit(1) | 119 | return 1 |
106 | 120 | ||
107 | copts, cargs = cmd.OptionParser.parse_args(argv) | 121 | copts, cargs = cmd.OptionParser.parse_args(argv) |
108 | 122 | ||
@@ -118,16 +132,37 @@ class _Repo(object): | |||
118 | RunPager(config) | 132 | RunPager(config) |
119 | 133 | ||
120 | try: | 134 | try: |
121 | cmd.Execute(copts, cargs) | 135 | start = time.time() |
136 | try: | ||
137 | result = cmd.Execute(copts, cargs) | ||
138 | finally: | ||
139 | elapsed = time.time() - start | ||
140 | hours, remainder = divmod(elapsed, 3600) | ||
141 | minutes, seconds = divmod(remainder, 60) | ||
142 | if gopts.time: | ||
143 | if hours == 0: | ||
144 | print >>sys.stderr, 'real\t%dm%.3fs' \ | ||
145 | % (minutes, seconds) | ||
146 | else: | ||
147 | print >>sys.stderr, 'real\t%dh%dm%.3fs' \ | ||
148 | % (hours, minutes, seconds) | ||
149 | except DownloadError, e: | ||
150 | print >>sys.stderr, 'error: %s' % str(e) | ||
151 | return 1 | ||
122 | except ManifestInvalidRevisionError, e: | 152 | except ManifestInvalidRevisionError, e: |
123 | print >>sys.stderr, 'error: %s' % str(e) | 153 | print >>sys.stderr, 'error: %s' % str(e) |
124 | sys.exit(1) | 154 | return 1 |
125 | except NoSuchProjectError, e: | 155 | except NoSuchProjectError, e: |
126 | if e.name: | 156 | if e.name: |
127 | print >>sys.stderr, 'error: project %s not found' % e.name | 157 | print >>sys.stderr, 'error: project %s not found' % e.name |
128 | else: | 158 | else: |
129 | print >>sys.stderr, 'error: no project in current directory' | 159 | print >>sys.stderr, 'error: no project in current directory' |
130 | sys.exit(1) | 160 | return 1 |
161 | |||
162 | return result | ||
163 | |||
164 | def _MyRepoPath(): | ||
165 | return os.path.dirname(__file__) | ||
131 | 166 | ||
132 | def _MyWrapperPath(): | 167 | def _MyWrapperPath(): |
133 | return os.path.join(os.path.dirname(__file__), 'repo') | 168 | return os.path.join(os.path.dirname(__file__), 'repo') |
@@ -195,7 +230,117 @@ def _PruneOptions(argv, opt): | |||
195 | continue | 230 | continue |
196 | i += 1 | 231 | i += 1 |
197 | 232 | ||
233 | _user_agent = None | ||
234 | |||
235 | def _UserAgent(): | ||
236 | global _user_agent | ||
237 | |||
238 | if _user_agent is None: | ||
239 | py_version = sys.version_info | ||
240 | |||
241 | os_name = sys.platform | ||
242 | if os_name == 'linux2': | ||
243 | os_name = 'Linux' | ||
244 | elif os_name == 'win32': | ||
245 | os_name = 'Win32' | ||
246 | elif os_name == 'cygwin': | ||
247 | os_name = 'Cygwin' | ||
248 | elif os_name == 'darwin': | ||
249 | os_name = 'Darwin' | ||
250 | |||
251 | p = GitCommand( | ||
252 | None, ['describe', 'HEAD'], | ||
253 | cwd = _MyRepoPath(), | ||
254 | capture_stdout = True) | ||
255 | if p.Wait() == 0: | ||
256 | repo_version = p.stdout | ||
257 | if len(repo_version) > 0 and repo_version[-1] == '\n': | ||
258 | repo_version = repo_version[0:-1] | ||
259 | if len(repo_version) > 0 and repo_version[0] == 'v': | ||
260 | repo_version = repo_version[1:] | ||
261 | else: | ||
262 | repo_version = 'unknown' | ||
263 | |||
264 | _user_agent = 'git-repo/%s (%s) git/%s Python/%d.%d.%d' % ( | ||
265 | repo_version, | ||
266 | os_name, | ||
267 | '.'.join(map(lambda d: str(d), git.version_tuple())), | ||
268 | py_version[0], py_version[1], py_version[2]) | ||
269 | return _user_agent | ||
270 | |||
271 | class _UserAgentHandler(urllib2.BaseHandler): | ||
272 | def http_request(self, req): | ||
273 | req.add_header('User-Agent', _UserAgent()) | ||
274 | return req | ||
275 | |||
276 | def https_request(self, req): | ||
277 | req.add_header('User-Agent', _UserAgent()) | ||
278 | return req | ||
279 | |||
280 | class _BasicAuthHandler(urllib2.HTTPBasicAuthHandler): | ||
281 | def http_error_auth_reqed(self, authreq, host, req, headers): | ||
282 | try: | ||
283 | old_add_header = req.add_header | ||
284 | def _add_header(name, val): | ||
285 | val = val.replace('\n', '') | ||
286 | old_add_header(name, val) | ||
287 | req.add_header = _add_header | ||
288 | return urllib2.AbstractBasicAuthHandler.http_error_auth_reqed( | ||
289 | self, authreq, host, req, headers) | ||
290 | except: | ||
291 | reset = getattr(self, 'reset_retry_count', None) | ||
292 | if reset is not None: | ||
293 | reset() | ||
294 | elif getattr(self, 'retried', None): | ||
295 | self.retried = 0 | ||
296 | raise | ||
297 | |||
298 | class _DigestAuthHandler(urllib2.HTTPDigestAuthHandler): | ||
299 | def http_error_auth_reqed(self, auth_header, host, req, headers): | ||
300 | try: | ||
301 | old_add_header = req.add_header | ||
302 | def _add_header(name, val): | ||
303 | val = val.replace('\n', '') | ||
304 | old_add_header(name, val) | ||
305 | req.add_header = _add_header | ||
306 | return urllib2.AbstractDigestAuthHandler.http_error_auth_reqed( | ||
307 | self, auth_header, host, req, headers) | ||
308 | except: | ||
309 | reset = getattr(self, 'reset_retry_count', None) | ||
310 | if reset is not None: | ||
311 | reset() | ||
312 | elif getattr(self, 'retried', None): | ||
313 | self.retried = 0 | ||
314 | raise | ||
315 | |||
316 | def init_http(): | ||
317 | handlers = [_UserAgentHandler()] | ||
318 | |||
319 | mgr = urllib2.HTTPPasswordMgrWithDefaultRealm() | ||
320 | try: | ||
321 | n = netrc.netrc() | ||
322 | for host in n.hosts: | ||
323 | p = n.hosts[host] | ||
324 | mgr.add_password(p[1], 'http://%s/' % host, p[0], p[2]) | ||
325 | mgr.add_password(p[1], 'https://%s/' % host, p[0], p[2]) | ||
326 | except netrc.NetrcParseError: | ||
327 | pass | ||
328 | except IOError: | ||
329 | pass | ||
330 | handlers.append(_BasicAuthHandler(mgr)) | ||
331 | handlers.append(_DigestAuthHandler(mgr)) | ||
332 | |||
333 | if 'http_proxy' in os.environ: | ||
334 | url = os.environ['http_proxy'] | ||
335 | handlers.append(urllib2.ProxyHandler({'http': url, 'https': url})) | ||
336 | if 'REPO_CURL_VERBOSE' in os.environ: | ||
337 | handlers.append(urllib2.HTTPHandler(debuglevel=1)) | ||
338 | handlers.append(urllib2.HTTPSHandler(debuglevel=1)) | ||
339 | urllib2.install_opener(urllib2.build_opener(*handlers)) | ||
340 | |||
198 | def _Main(argv): | 341 | def _Main(argv): |
342 | result = 0 | ||
343 | |||
199 | opt = optparse.OptionParser(usage="repo wrapperinfo -- ...") | 344 | opt = optparse.OptionParser(usage="repo wrapperinfo -- ...") |
200 | opt.add_option("--repo-dir", dest="repodir", | 345 | opt.add_option("--repo-dir", dest="repodir", |
201 | help="path to .repo/") | 346 | help="path to .repo/") |
@@ -209,15 +354,19 @@ def _Main(argv): | |||
209 | _CheckWrapperVersion(opt.wrapper_version, opt.wrapper_path) | 354 | _CheckWrapperVersion(opt.wrapper_version, opt.wrapper_path) |
210 | _CheckRepoDir(opt.repodir) | 355 | _CheckRepoDir(opt.repodir) |
211 | 356 | ||
357 | Version.wrapper_version = opt.wrapper_version | ||
358 | Version.wrapper_path = opt.wrapper_path | ||
359 | |||
212 | repo = _Repo(opt.repodir) | 360 | repo = _Repo(opt.repodir) |
213 | try: | 361 | try: |
214 | try: | 362 | try: |
215 | init_ssh() | 363 | init_ssh() |
216 | repo._Run(argv) | 364 | init_http() |
365 | result = repo._Run(argv) or 0 | ||
217 | finally: | 366 | finally: |
218 | close_ssh() | 367 | close_ssh() |
219 | except KeyboardInterrupt: | 368 | except KeyboardInterrupt: |
220 | sys.exit(1) | 369 | result = 1 |
221 | except RepoChangedException, rce: | 370 | except RepoChangedException, rce: |
222 | # If repo changed, re-exec ourselves. | 371 | # If repo changed, re-exec ourselves. |
223 | # | 372 | # |
@@ -228,7 +377,9 @@ def _Main(argv): | |||
228 | except OSError, e: | 377 | except OSError, e: |
229 | print >>sys.stderr, 'fatal: cannot restart repo after upgrade' | 378 | print >>sys.stderr, 'fatal: cannot restart repo after upgrade' |
230 | print >>sys.stderr, 'fatal: %s' % e | 379 | print >>sys.stderr, 'fatal: %s' % e |
231 | sys.exit(128) | 380 | result = 128 |
381 | |||
382 | sys.exit(result) | ||
232 | 383 | ||
233 | if __name__ == '__main__': | 384 | if __name__ == '__main__': |
234 | _Main(sys.argv[1:]) | 385 | _Main(sys.argv[1:]) |