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:]) |
