| David Pursehouse | 8898e2f | 2012-11-14 07:51:03 +0900 | [diff] [blame] | 1 | #!/usr/bin/env python | 
| Mike Frysinger | f601376 | 2019-06-13 02:30:51 -0400 | [diff] [blame] | 2 | # -*- coding:utf-8 -*- | 
| The Android Open Source Project | cf31fe9 | 2008-10-21 07:00:00 -0700 | [diff] [blame] | 3 | # | 
 | 4 | # Copyright (C) 2008 The Android Open Source Project | 
 | 5 | # | 
 | 6 | # Licensed under the Apache License, Version 2.0 (the "License"); | 
 | 7 | # you may not use this file except in compliance with the License. | 
 | 8 | # You may obtain a copy of the License at | 
 | 9 | # | 
 | 10 | #      http://www.apache.org/licenses/LICENSE-2.0 | 
 | 11 | # | 
 | 12 | # Unless required by applicable law or agreed to in writing, software | 
 | 13 | # distributed under the License is distributed on an "AS IS" BASIS, | 
 | 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
 | 15 | # See the License for the specific language governing permissions and | 
 | 16 | # limitations under the License. | 
 | 17 |  | 
| Mike Frysinger | 87fb5a1 | 2019-06-13 01:54:46 -0400 | [diff] [blame] | 18 | """The repo tool. | 
 | 19 |  | 
 | 20 | People shouldn't run this directly; instead, they should use the `repo` wrapper | 
 | 21 | which takes care of execing this entry point. | 
 | 22 | """ | 
 | 23 |  | 
| Sarah Owens | cecd1d8 | 2012-11-01 22:59:27 -0700 | [diff] [blame] | 24 | from __future__ import print_function | 
| JoonCheol Park | e986072 | 2012-10-11 02:31:44 +0900 | [diff] [blame] | 25 | import getpass | 
| Conley Owens | c9129d9 | 2012-10-01 16:12:28 -0700 | [diff] [blame] | 26 | import imp | 
| Shawn O. Pearce | bd0312a | 2011-09-19 10:04:23 -0700 | [diff] [blame] | 27 | import netrc | 
| The Android Open Source Project | cf31fe9 | 2008-10-21 07:00:00 -0700 | [diff] [blame] | 28 | import optparse | 
 | 29 | import os | 
| The Android Open Source Project | cf31fe9 | 2008-10-21 07:00:00 -0700 | [diff] [blame] | 30 | import sys | 
| Shawn O. Pearce | 3a0e782 | 2011-09-22 17:06:41 -0700 | [diff] [blame] | 31 | import time | 
| David Pursehouse | 59bbb58 | 2013-05-17 10:49:33 +0900 | [diff] [blame] | 32 |  | 
 | 33 | from pyversion import is_python3 | 
 | 34 | if is_python3(): | 
| Sarah Owens | 1f7627f | 2012-10-31 09:21:55 -0700 | [diff] [blame] | 35 |   import urllib.request | 
 | 36 | else: | 
| David Pursehouse | 59bbb58 | 2013-05-17 10:49:33 +0900 | [diff] [blame] | 37 |   import urllib2 | 
| Sarah Owens | 1f7627f | 2012-10-31 09:21:55 -0700 | [diff] [blame] | 38 |   urllib = imp.new_module('urllib') | 
 | 39 |   urllib.request = urllib2 | 
| The Android Open Source Project | cf31fe9 | 2008-10-21 07:00:00 -0700 | [diff] [blame] | 40 |  | 
| Carlos Aguado | 1242e60 | 2014-02-03 13:48:47 +0100 | [diff] [blame] | 41 | try: | 
 | 42 |   import kerberos | 
 | 43 | except ImportError: | 
 | 44 |   kerberos = None | 
 | 45 |  | 
| Mike Frysinger | 902665b | 2014-12-22 15:17:59 -0500 | [diff] [blame] | 46 | from color import SetDefaultColoring | 
| David Riley | e0684ad | 2017-04-05 00:02:59 -0700 | [diff] [blame] | 47 | import event_log | 
| Mike Frysinger | 8a11f6f | 2019-08-27 00:26:15 -0400 | [diff] [blame] | 48 | from repo_trace import SetTrace | 
| Shawn O. Pearce | 334851e | 2011-09-19 08:05:31 -0700 | [diff] [blame] | 49 | from git_command import git, GitCommand | 
| Doug Anderson | 0048b69 | 2010-12-21 13:39:23 -0800 | [diff] [blame] | 50 | from git_config import init_ssh, close_ssh | 
| Shawn O. Pearce | c95583b | 2009-03-03 17:47:06 -0800 | [diff] [blame] | 51 | from command import InteractiveCommand | 
 | 52 | from command import MirrorSafeCommand | 
| Dan Willemsen | 7936064 | 2015-08-31 15:45:06 -0700 | [diff] [blame] | 53 | from command import GitcAvailableCommand, GitcClientCommand | 
| Shawn O. Pearce | ecff4f1 | 2011-11-29 15:01:33 -0800 | [diff] [blame] | 54 | from subcmds.version import Version | 
| Shawn O. Pearce | 7965f9f | 2008-10-29 15:20:02 -0700 | [diff] [blame] | 55 | from editor import Editor | 
| Shawn O. Pearce | f322b9a | 2011-09-19 14:50:58 -0700 | [diff] [blame] | 56 | from error import DownloadError | 
| Jarkko Pöyry | 87ea591 | 2015-06-19 15:39:25 -0700 | [diff] [blame] | 57 | from error import InvalidProjectGroupsError | 
| Shawn O. Pearce | 559b846 | 2009-03-02 12:56:08 -0800 | [diff] [blame] | 58 | from error import ManifestInvalidRevisionError | 
| David Pursehouse | 0b8df7b | 2012-11-13 09:51:57 +0900 | [diff] [blame] | 59 | from error import ManifestParseError | 
| Conley Owens | 75ee057 | 2012-11-15 17:33:11 -0800 | [diff] [blame] | 60 | from error import NoManifestException | 
| The Android Open Source Project | cf31fe9 | 2008-10-21 07:00:00 -0700 | [diff] [blame] | 61 | from error import NoSuchProjectError | 
 | 62 | from error import RepoChangedException | 
| Simran Basi | b9a1b73 | 2015-08-20 12:19:28 -0700 | [diff] [blame] | 63 | import gitc_utils | 
 | 64 | from manifest_xml import GitcManifest, XmlManifest | 
| Renaud Paquay | e8595e9 | 2016-11-01 15:51:59 -0700 | [diff] [blame] | 65 | from pager import RunPager, TerminatePager | 
| Conley Owens | 094cdbe | 2014-01-30 15:09:59 -0800 | [diff] [blame] | 66 | from wrapper import WrapperPath, Wrapper | 
| The Android Open Source Project | cf31fe9 | 2008-10-21 07:00:00 -0700 | [diff] [blame] | 67 |  | 
| David Pursehouse | 5c6eeac | 2012-10-11 16:44:48 +0900 | [diff] [blame] | 68 | from subcmds import all_commands | 
| The Android Open Source Project | cf31fe9 | 2008-10-21 07:00:00 -0700 | [diff] [blame] | 69 |  | 
| David Pursehouse | 59bbb58 | 2013-05-17 10:49:33 +0900 | [diff] [blame] | 70 | if not is_python3(): | 
| Chirayu Desai | 217ea7d | 2013-03-01 19:14:38 +0530 | [diff] [blame] | 71 |   input = raw_input | 
| Chirayu Desai | 217ea7d | 2013-03-01 19:14:38 +0530 | [diff] [blame] | 72 |  | 
| The Android Open Source Project | cf31fe9 | 2008-10-21 07:00:00 -0700 | [diff] [blame] | 73 | global_options = optparse.OptionParser( | 
 | 74 |                  usage="repo [-p|--paginate|--no-pager] COMMAND [ARGS]" | 
 | 75 |                  ) | 
 | 76 | global_options.add_option('-p', '--paginate', | 
 | 77 |                           dest='pager', action='store_true', | 
 | 78 |                           help='display command output in the pager') | 
 | 79 | global_options.add_option('--no-pager', | 
 | 80 |                           dest='no_pager', action='store_true', | 
 | 81 |                           help='disable the pager') | 
| Mike Frysinger | 902665b | 2014-12-22 15:17:59 -0500 | [diff] [blame] | 82 | global_options.add_option('--color', | 
 | 83 |                           choices=('auto', 'always', 'never'), default=None, | 
 | 84 |                           help='control color usage: auto, always, never') | 
| Shawn O. Pearce | 0ed2bd1 | 2009-03-09 18:26:31 -0700 | [diff] [blame] | 85 | global_options.add_option('--trace', | 
 | 86 |                           dest='trace', action='store_true', | 
| Mike Frysinger | 8a11f6f | 2019-08-27 00:26:15 -0400 | [diff] [blame] | 87 |                           help='trace git command execution (REPO_TRACE=1)') | 
| Mike Frysinger | 3fc1572 | 2019-08-27 00:36:46 -0400 | [diff] [blame] | 88 | global_options.add_option('--trace-python', | 
 | 89 |                           dest='trace_python', action='store_true', | 
 | 90 |                           help='trace python command execution') | 
| Shawn O. Pearce | 3a0e782 | 2011-09-22 17:06:41 -0700 | [diff] [blame] | 91 | global_options.add_option('--time', | 
 | 92 |                           dest='time', action='store_true', | 
 | 93 |                           help='time repo command execution') | 
| Shawn O. Pearce | 47c1a63 | 2009-03-02 18:24:23 -0800 | [diff] [blame] | 94 | global_options.add_option('--version', | 
 | 95 |                           dest='show_version', action='store_true', | 
 | 96 |                           help='display this version of repo') | 
| David Riley | e0684ad | 2017-04-05 00:02:59 -0700 | [diff] [blame] | 97 | global_options.add_option('--event-log', | 
 | 98 |                           dest='event_log', action='store', | 
 | 99 |                           help='filename of event log to append timeline to') | 
| The Android Open Source Project | cf31fe9 | 2008-10-21 07:00:00 -0700 | [diff] [blame] | 100 |  | 
 | 101 | class _Repo(object): | 
 | 102 |   def __init__(self, repodir): | 
 | 103 |     self.repodir = repodir | 
 | 104 |     self.commands = all_commands | 
| Mike Lockwood | 2bf9db0 | 2009-07-14 15:23:39 -0400 | [diff] [blame] | 105 |     # add 'branch' as an alias for 'branches' | 
 | 106 |     all_commands['branch'] = all_commands['branches'] | 
| The Android Open Source Project | cf31fe9 | 2008-10-21 07:00:00 -0700 | [diff] [blame] | 107 |  | 
| Mike Frysinger | 3fc1572 | 2019-08-27 00:36:46 -0400 | [diff] [blame] | 108 |   def _ParseArgs(self, argv): | 
 | 109 |     """Parse the main `repo` command line options.""" | 
| The Android Open Source Project | cf31fe9 | 2008-10-21 07:00:00 -0700 | [diff] [blame] | 110 |     name = None | 
 | 111 |     glob = [] | 
 | 112 |  | 
| Sarah Owens | a6053d5 | 2012-11-01 13:36:50 -0700 | [diff] [blame] | 113 |     for i in range(len(argv)): | 
| The Android Open Source Project | cf31fe9 | 2008-10-21 07:00:00 -0700 | [diff] [blame] | 114 |       if not argv[i].startswith('-'): | 
 | 115 |         name = argv[i] | 
 | 116 |         if i > 0: | 
 | 117 |           glob = argv[:i] | 
 | 118 |         argv = argv[i + 1:] | 
 | 119 |         break | 
 | 120 |     if not name: | 
 | 121 |       glob = argv | 
 | 122 |       name = 'help' | 
 | 123 |       argv = [] | 
| David Pursehouse | 8a68ff9 | 2012-09-24 12:15:13 +0900 | [diff] [blame] | 124 |     gopts, _gargs = global_options.parse_args(glob) | 
| The Android Open Source Project | cf31fe9 | 2008-10-21 07:00:00 -0700 | [diff] [blame] | 125 |  | 
| Mike Frysinger | 3fc1572 | 2019-08-27 00:36:46 -0400 | [diff] [blame] | 126 |     return (name, gopts, argv) | 
 | 127 |  | 
 | 128 |   def _Run(self, name, gopts, argv): | 
 | 129 |     """Execute the requested subcommand.""" | 
 | 130 |     result = 0 | 
 | 131 |  | 
| Shawn O. Pearce | 0ed2bd1 | 2009-03-09 18:26:31 -0700 | [diff] [blame] | 132 |     if gopts.trace: | 
| Shawn O. Pearce | ad3193a | 2009-04-18 09:54:51 -0700 | [diff] [blame] | 133 |       SetTrace() | 
| Shawn O. Pearce | 47c1a63 | 2009-03-02 18:24:23 -0800 | [diff] [blame] | 134 |     if gopts.show_version: | 
 | 135 |       if name == 'help': | 
 | 136 |         name = 'version' | 
 | 137 |       else: | 
| Sarah Owens | cecd1d8 | 2012-11-01 22:59:27 -0700 | [diff] [blame] | 138 |         print('fatal: invalid usage of --version', file=sys.stderr) | 
| Daniel Sandler | 3ce2a6b | 2011-04-29 09:59:12 -0400 | [diff] [blame] | 139 |         return 1 | 
| Shawn O. Pearce | 47c1a63 | 2009-03-02 18:24:23 -0800 | [diff] [blame] | 140 |  | 
| Mike Frysinger | 902665b | 2014-12-22 15:17:59 -0500 | [diff] [blame] | 141 |     SetDefaultColoring(gopts.color) | 
 | 142 |  | 
| The Android Open Source Project | cf31fe9 | 2008-10-21 07:00:00 -0700 | [diff] [blame] | 143 |     try: | 
 | 144 |       cmd = self.commands[name] | 
 | 145 |     except KeyError: | 
| Sarah Owens | cecd1d8 | 2012-11-01 22:59:27 -0700 | [diff] [blame] | 146 |       print("repo: '%s' is not a repo command.  See 'repo help'." % name, | 
 | 147 |             file=sys.stderr) | 
| Daniel Sandler | 3ce2a6b | 2011-04-29 09:59:12 -0400 | [diff] [blame] | 148 |       return 1 | 
| The Android Open Source Project | cf31fe9 | 2008-10-21 07:00:00 -0700 | [diff] [blame] | 149 |  | 
 | 150 |     cmd.repodir = self.repodir | 
| Shawn O. Pearce | c8a300f | 2009-05-18 13:19:57 -0700 | [diff] [blame] | 151 |     cmd.manifest = XmlManifest(cmd.repodir) | 
| Simran Basi | b9a1b73 | 2015-08-20 12:19:28 -0700 | [diff] [blame] | 152 |     cmd.gitc_manifest = None | 
 | 153 |     gitc_client_name = gitc_utils.parse_clientdir(os.getcwd()) | 
 | 154 |     if gitc_client_name: | 
 | 155 |       cmd.gitc_manifest = GitcManifest(cmd.repodir, gitc_client_name) | 
 | 156 |       cmd.manifest.isGitcClient = True | 
 | 157 |  | 
| Shawn O. Pearce | 7965f9f | 2008-10-29 15:20:02 -0700 | [diff] [blame] | 158 |     Editor.globalConfig = cmd.manifest.globalConfig | 
| The Android Open Source Project | cf31fe9 | 2008-10-21 07:00:00 -0700 | [diff] [blame] | 159 |  | 
| Shawn O. Pearce | c95583b | 2009-03-03 17:47:06 -0800 | [diff] [blame] | 160 |     if not isinstance(cmd, MirrorSafeCommand) and cmd.manifest.IsMirror: | 
| Sarah Owens | cecd1d8 | 2012-11-01 22:59:27 -0700 | [diff] [blame] | 161 |       print("fatal: '%s' requires a working directory" % name, | 
 | 162 |             file=sys.stderr) | 
| Daniel Sandler | 3ce2a6b | 2011-04-29 09:59:12 -0400 | [diff] [blame] | 163 |       return 1 | 
| Shawn O. Pearce | c95583b | 2009-03-03 17:47:06 -0800 | [diff] [blame] | 164 |  | 
| Dan Willemsen | 7936064 | 2015-08-31 15:45:06 -0700 | [diff] [blame] | 165 |     if isinstance(cmd, GitcAvailableCommand) and not gitc_utils.get_gitc_manifest_dir(): | 
| Dan Willemsen | 9ff2ece | 2015-08-31 15:45:06 -0700 | [diff] [blame] | 166 |       print("fatal: '%s' requires GITC to be available" % name, | 
 | 167 |             file=sys.stderr) | 
 | 168 |       return 1 | 
 | 169 |  | 
| Dan Willemsen | 7936064 | 2015-08-31 15:45:06 -0700 | [diff] [blame] | 170 |     if isinstance(cmd, GitcClientCommand) and not gitc_client_name: | 
 | 171 |       print("fatal: '%s' requires a GITC client" % name, | 
 | 172 |             file=sys.stderr) | 
 | 173 |       return 1 | 
 | 174 |  | 
| Dan Sandler | 53e902a | 2014-03-09 13:20:02 -0400 | [diff] [blame] | 175 |     try: | 
 | 176 |       copts, cargs = cmd.OptionParser.parse_args(argv) | 
 | 177 |       copts = cmd.ReadEnvironmentOptions(copts) | 
 | 178 |     except NoManifestException as e: | 
 | 179 |       print('error: in `%s`: %s' % (' '.join([name] + argv), str(e)), | 
 | 180 |         file=sys.stderr) | 
 | 181 |       print('error: manifest missing or unreadable -- please run init', | 
 | 182 |             file=sys.stderr) | 
 | 183 |       return 1 | 
| Shawn O. Pearce | db45da1 | 2009-04-18 13:49:13 -0700 | [diff] [blame] | 184 |  | 
| The Android Open Source Project | cf31fe9 | 2008-10-21 07:00:00 -0700 | [diff] [blame] | 185 |     if not gopts.no_pager and not isinstance(cmd, InteractiveCommand): | 
 | 186 |       config = cmd.manifest.globalConfig | 
 | 187 |       if gopts.pager: | 
 | 188 |         use_pager = True | 
 | 189 |       else: | 
 | 190 |         use_pager = config.GetBoolean('pager.%s' % name) | 
 | 191 |         if use_pager is None: | 
| Shawn O. Pearce | db45da1 | 2009-04-18 13:49:13 -0700 | [diff] [blame] | 192 |           use_pager = cmd.WantPager(copts) | 
| The Android Open Source Project | cf31fe9 | 2008-10-21 07:00:00 -0700 | [diff] [blame] | 193 |       if use_pager: | 
 | 194 |         RunPager(config) | 
 | 195 |  | 
| Conley Owens | 7ba25be | 2012-11-14 14:18:06 -0800 | [diff] [blame] | 196 |     start = time.time() | 
| David Riley | e0684ad | 2017-04-05 00:02:59 -0700 | [diff] [blame] | 197 |     cmd_event = cmd.event_log.Add(name, event_log.TASK_COMMAND, start) | 
 | 198 |     cmd.event_log.SetParent(cmd_event) | 
| The Android Open Source Project | cf31fe9 | 2008-10-21 07:00:00 -0700 | [diff] [blame] | 199 |     try: | 
| Mike Frysinger | ae6cb08 | 2019-08-27 01:10:59 -0400 | [diff] [blame^] | 200 |       cmd.ValidateOptions(copts, cargs) | 
| Conley Owens | 7ba25be | 2012-11-14 14:18:06 -0800 | [diff] [blame] | 201 |       result = cmd.Execute(copts, cargs) | 
| Dan Sandler | 53e902a | 2014-03-09 13:20:02 -0400 | [diff] [blame] | 202 |     except (DownloadError, ManifestInvalidRevisionError, | 
 | 203 |         NoManifestException) as e: | 
 | 204 |       print('error: in `%s`: %s' % (' '.join([name] + argv), str(e)), | 
 | 205 |         file=sys.stderr) | 
 | 206 |       if isinstance(e, NoManifestException): | 
 | 207 |         print('error: manifest missing or unreadable -- please run init', | 
 | 208 |               file=sys.stderr) | 
| Conley Owens | 75ee057 | 2012-11-15 17:33:11 -0800 | [diff] [blame] | 209 |       result = 1 | 
| Sarah Owens | a5be53f | 2012-09-09 15:37:57 -0700 | [diff] [blame] | 210 |     except NoSuchProjectError as e: | 
| The Android Open Source Project | cf31fe9 | 2008-10-21 07:00:00 -0700 | [diff] [blame] | 211 |       if e.name: | 
| Sarah Owens | cecd1d8 | 2012-11-01 22:59:27 -0700 | [diff] [blame] | 212 |         print('error: project %s not found' % e.name, file=sys.stderr) | 
| The Android Open Source Project | cf31fe9 | 2008-10-21 07:00:00 -0700 | [diff] [blame] | 213 |       else: | 
| Sarah Owens | cecd1d8 | 2012-11-01 22:59:27 -0700 | [diff] [blame] | 214 |         print('error: no project in current directory', file=sys.stderr) | 
| Conley Owens | 7ba25be | 2012-11-14 14:18:06 -0800 | [diff] [blame] | 215 |       result = 1 | 
| Jarkko Pöyry | 87ea591 | 2015-06-19 15:39:25 -0700 | [diff] [blame] | 216 |     except InvalidProjectGroupsError as e: | 
 | 217 |       if e.name: | 
 | 218 |         print('error: project group must be enabled for project %s' % e.name, file=sys.stderr) | 
 | 219 |       else: | 
 | 220 |         print('error: project group must be enabled for the project in the current directory', file=sys.stderr) | 
 | 221 |       result = 1 | 
| David Riley | aa90021 | 2017-04-05 13:50:52 -0700 | [diff] [blame] | 222 |     except SystemExit as e: | 
 | 223 |       if e.code: | 
 | 224 |         result = e.code | 
 | 225 |       raise | 
| Conley Owens | 7ba25be | 2012-11-14 14:18:06 -0800 | [diff] [blame] | 226 |     finally: | 
| David Riley | e0684ad | 2017-04-05 00:02:59 -0700 | [diff] [blame] | 227 |       finish = time.time() | 
 | 228 |       elapsed = finish - start | 
| Conley Owens | 7ba25be | 2012-11-14 14:18:06 -0800 | [diff] [blame] | 229 |       hours, remainder = divmod(elapsed, 3600) | 
 | 230 |       minutes, seconds = divmod(remainder, 60) | 
 | 231 |       if gopts.time: | 
 | 232 |         if hours == 0: | 
 | 233 |           print('real\t%dm%.3fs' % (minutes, seconds), file=sys.stderr) | 
 | 234 |         else: | 
 | 235 |           print('real\t%dh%dm%.3fs' % (hours, minutes, seconds), | 
 | 236 |                 file=sys.stderr) | 
| Daniel Sandler | 3ce2a6b | 2011-04-29 09:59:12 -0400 | [diff] [blame] | 237 |  | 
| David Riley | e0684ad | 2017-04-05 00:02:59 -0700 | [diff] [blame] | 238 |       cmd.event_log.FinishEvent(cmd_event, finish, | 
 | 239 |                                 result is None or result == 0) | 
 | 240 |       if gopts.event_log: | 
 | 241 |         cmd.event_log.Write(os.path.abspath( | 
 | 242 |                             os.path.expanduser(gopts.event_log))) | 
 | 243 |  | 
| Daniel Sandler | 3ce2a6b | 2011-04-29 09:59:12 -0400 | [diff] [blame] | 244 |     return result | 
| The Android Open Source Project | cf31fe9 | 2008-10-21 07:00:00 -0700 | [diff] [blame] | 245 |  | 
| Conley Owens | 094cdbe | 2014-01-30 15:09:59 -0800 | [diff] [blame] | 246 |  | 
| Shawn O. Pearce | 334851e | 2011-09-19 08:05:31 -0700 | [diff] [blame] | 247 | def _MyRepoPath(): | 
 | 248 |   return os.path.dirname(__file__) | 
 | 249 |  | 
| The Android Open Source Project | cf31fe9 | 2008-10-21 07:00:00 -0700 | [diff] [blame] | 250 |  | 
 | 251 | def _CheckWrapperVersion(ver, repo_path): | 
 | 252 |   if not repo_path: | 
 | 253 |     repo_path = '~/bin/repo' | 
 | 254 |  | 
 | 255 |   if not ver: | 
| Sarah Owens | cecd1d8 | 2012-11-01 22:59:27 -0700 | [diff] [blame] | 256 |     print('no --wrapper-version argument', file=sys.stderr) | 
| David Pursehouse | 8a68ff9 | 2012-09-24 12:15:13 +0900 | [diff] [blame] | 257 |     sys.exit(1) | 
| The Android Open Source Project | cf31fe9 | 2008-10-21 07:00:00 -0700 | [diff] [blame] | 258 |  | 
| Conley Owens | 094cdbe | 2014-01-30 15:09:59 -0800 | [diff] [blame] | 259 |   exp = Wrapper().VERSION | 
| David Pursehouse | 7e6dd2d | 2012-10-25 12:40:51 +0900 | [diff] [blame] | 260 |   ver = tuple(map(int, ver.split('.'))) | 
| The Android Open Source Project | cf31fe9 | 2008-10-21 07:00:00 -0700 | [diff] [blame] | 261 |   if len(ver) == 1: | 
 | 262 |     ver = (0, ver[0]) | 
 | 263 |  | 
| David Pursehouse | 7e6dd2d | 2012-10-25 12:40:51 +0900 | [diff] [blame] | 264 |   exp_str = '.'.join(map(str, exp)) | 
| The Android Open Source Project | cf31fe9 | 2008-10-21 07:00:00 -0700 | [diff] [blame] | 265 |   if exp[0] > ver[0] or ver < (0, 4): | 
| Sarah Owens | cecd1d8 | 2012-11-01 22:59:27 -0700 | [diff] [blame] | 266 |     print(""" | 
| The Android Open Source Project | cf31fe9 | 2008-10-21 07:00:00 -0700 | [diff] [blame] | 267 | !!! A new repo command (%5s) is available.    !!! | 
 | 268 | !!! You must upgrade before you can continue:   !!! | 
 | 269 |  | 
 | 270 |     cp %s %s | 
| Conley Owens | 094cdbe | 2014-01-30 15:09:59 -0800 | [diff] [blame] | 271 | """ % (exp_str, WrapperPath(), repo_path), file=sys.stderr) | 
| The Android Open Source Project | cf31fe9 | 2008-10-21 07:00:00 -0700 | [diff] [blame] | 272 |     sys.exit(1) | 
 | 273 |  | 
 | 274 |   if exp > ver: | 
| Sarah Owens | cecd1d8 | 2012-11-01 22:59:27 -0700 | [diff] [blame] | 275 |     print(""" | 
| The Android Open Source Project | cf31fe9 | 2008-10-21 07:00:00 -0700 | [diff] [blame] | 276 | ... A new repo command (%5s) is available. | 
 | 277 | ... You should upgrade soon: | 
 | 278 |  | 
 | 279 |     cp %s %s | 
| Conley Owens | 094cdbe | 2014-01-30 15:09:59 -0800 | [diff] [blame] | 280 | """ % (exp_str, WrapperPath(), repo_path), file=sys.stderr) | 
| The Android Open Source Project | cf31fe9 | 2008-10-21 07:00:00 -0700 | [diff] [blame] | 281 |  | 
| Mickaël Salaün | 2f6ab7f | 2012-09-30 00:37:55 +0200 | [diff] [blame] | 282 | def _CheckRepoDir(repo_dir): | 
 | 283 |   if not repo_dir: | 
| Sarah Owens | cecd1d8 | 2012-11-01 22:59:27 -0700 | [diff] [blame] | 284 |     print('no --repo-dir argument', file=sys.stderr) | 
| David Pursehouse | 8a68ff9 | 2012-09-24 12:15:13 +0900 | [diff] [blame] | 285 |     sys.exit(1) | 
| The Android Open Source Project | cf31fe9 | 2008-10-21 07:00:00 -0700 | [diff] [blame] | 286 |  | 
 | 287 | def _PruneOptions(argv, opt): | 
 | 288 |   i = 0 | 
 | 289 |   while i < len(argv): | 
 | 290 |     a = argv[i] | 
 | 291 |     if a == '--': | 
 | 292 |       break | 
 | 293 |     if a.startswith('--'): | 
 | 294 |       eq = a.find('=') | 
 | 295 |       if eq > 0: | 
 | 296 |         a = a[0:eq] | 
 | 297 |     if not opt.has_option(a): | 
 | 298 |       del argv[i] | 
 | 299 |       continue | 
 | 300 |     i += 1 | 
 | 301 |  | 
| Shawn O. Pearce | 334851e | 2011-09-19 08:05:31 -0700 | [diff] [blame] | 302 | _user_agent = None | 
 | 303 |  | 
 | 304 | def _UserAgent(): | 
 | 305 |   global _user_agent | 
 | 306 |  | 
 | 307 |   if _user_agent is None: | 
 | 308 |     py_version = sys.version_info | 
 | 309 |  | 
 | 310 |     os_name = sys.platform | 
 | 311 |     if os_name == 'linux2': | 
 | 312 |       os_name = 'Linux' | 
 | 313 |     elif os_name == 'win32': | 
 | 314 |       os_name = 'Win32' | 
 | 315 |     elif os_name == 'cygwin': | 
 | 316 |       os_name = 'Cygwin' | 
 | 317 |     elif os_name == 'darwin': | 
 | 318 |       os_name = 'Darwin' | 
 | 319 |  | 
 | 320 |     p = GitCommand( | 
 | 321 |       None, ['describe', 'HEAD'], | 
 | 322 |       cwd = _MyRepoPath(), | 
 | 323 |       capture_stdout = True) | 
 | 324 |     if p.Wait() == 0: | 
 | 325 |       repo_version = p.stdout | 
 | 326 |       if len(repo_version) > 0 and repo_version[-1] == '\n': | 
 | 327 |         repo_version = repo_version[0:-1] | 
 | 328 |       if len(repo_version) > 0 and repo_version[0] == 'v': | 
 | 329 |         repo_version = repo_version[1:] | 
 | 330 |     else: | 
 | 331 |       repo_version = 'unknown' | 
 | 332 |  | 
 | 333 |     _user_agent = 'git-repo/%s (%s) git/%s Python/%d.%d.%d' % ( | 
 | 334 |       repo_version, | 
 | 335 |       os_name, | 
| Mike Frysinger | 242fcdd | 2019-07-10 15:45:49 -0400 | [diff] [blame] | 336 |       git.version_tuple().full, | 
| Shawn O. Pearce | 334851e | 2011-09-19 08:05:31 -0700 | [diff] [blame] | 337 |       py_version[0], py_version[1], py_version[2]) | 
 | 338 |   return _user_agent | 
 | 339 |  | 
| Sarah Owens | 1f7627f | 2012-10-31 09:21:55 -0700 | [diff] [blame] | 340 | class _UserAgentHandler(urllib.request.BaseHandler): | 
| Shawn O. Pearce | 334851e | 2011-09-19 08:05:31 -0700 | [diff] [blame] | 341 |   def http_request(self, req): | 
 | 342 |     req.add_header('User-Agent', _UserAgent()) | 
 | 343 |     return req | 
 | 344 |  | 
 | 345 |   def https_request(self, req): | 
 | 346 |     req.add_header('User-Agent', _UserAgent()) | 
 | 347 |     return req | 
 | 348 |  | 
| JoonCheol Park | e986072 | 2012-10-11 02:31:44 +0900 | [diff] [blame] | 349 | def _AddPasswordFromUserInput(handler, msg, req): | 
| David Pursehouse | c1b86a2 | 2012-11-14 11:36:51 +0900 | [diff] [blame] | 350 |   # If repo could not find auth info from netrc, try to get it from user input | 
 | 351 |   url = req.get_full_url() | 
 | 352 |   user, password = handler.passwd.find_user_password(None, url) | 
 | 353 |   if user is None: | 
 | 354 |     print(msg) | 
 | 355 |     try: | 
| Chirayu Desai | 217ea7d | 2013-03-01 19:14:38 +0530 | [diff] [blame] | 356 |       user = input('User: ') | 
| David Pursehouse | c1b86a2 | 2012-11-14 11:36:51 +0900 | [diff] [blame] | 357 |       password = getpass.getpass() | 
 | 358 |     except KeyboardInterrupt: | 
 | 359 |       return | 
 | 360 |     handler.passwd.add_password(None, url, user, password) | 
| JoonCheol Park | e986072 | 2012-10-11 02:31:44 +0900 | [diff] [blame] | 361 |  | 
| Sarah Owens | 1f7627f | 2012-10-31 09:21:55 -0700 | [diff] [blame] | 362 | class _BasicAuthHandler(urllib.request.HTTPBasicAuthHandler): | 
| JoonCheol Park | e986072 | 2012-10-11 02:31:44 +0900 | [diff] [blame] | 363 |   def http_error_401(self, req, fp, code, msg, headers): | 
 | 364 |     _AddPasswordFromUserInput(self, msg, req) | 
| Sarah Owens | 1f7627f | 2012-10-31 09:21:55 -0700 | [diff] [blame] | 365 |     return urllib.request.HTTPBasicAuthHandler.http_error_401( | 
| JoonCheol Park | e986072 | 2012-10-11 02:31:44 +0900 | [diff] [blame] | 366 |       self, req, fp, code, msg, headers) | 
 | 367 |  | 
| Shawn O. Pearce | fab96c6 | 2011-10-11 12:00:38 -0700 | [diff] [blame] | 368 |   def http_error_auth_reqed(self, authreq, host, req, headers): | 
 | 369 |     try: | 
| Shawn O. Pearce | df5ee52 | 2011-10-11 14:05:21 -0700 | [diff] [blame] | 370 |       old_add_header = req.add_header | 
 | 371 |       def _add_header(name, val): | 
 | 372 |         val = val.replace('\n', '') | 
 | 373 |         old_add_header(name, val) | 
 | 374 |       req.add_header = _add_header | 
| Sarah Owens | 1f7627f | 2012-10-31 09:21:55 -0700 | [diff] [blame] | 375 |       return urllib.request.AbstractBasicAuthHandler.http_error_auth_reqed( | 
| Shawn O. Pearce | fab96c6 | 2011-10-11 12:00:38 -0700 | [diff] [blame] | 376 |         self, authreq, host, req, headers) | 
 | 377 |     except: | 
| Shawn O. Pearce | df5ee52 | 2011-10-11 14:05:21 -0700 | [diff] [blame] | 378 |       reset = getattr(self, 'reset_retry_count', None) | 
 | 379 |       if reset is not None: | 
 | 380 |         reset() | 
| Shawn O. Pearce | b660539 | 2011-10-11 15:58:07 -0700 | [diff] [blame] | 381 |       elif getattr(self, 'retried', None): | 
 | 382 |         self.retried = 0 | 
| Shawn O. Pearce | fab96c6 | 2011-10-11 12:00:38 -0700 | [diff] [blame] | 383 |       raise | 
 | 384 |  | 
| Sarah Owens | 1f7627f | 2012-10-31 09:21:55 -0700 | [diff] [blame] | 385 | class _DigestAuthHandler(urllib.request.HTTPDigestAuthHandler): | 
| JoonCheol Park | e986072 | 2012-10-11 02:31:44 +0900 | [diff] [blame] | 386 |   def http_error_401(self, req, fp, code, msg, headers): | 
 | 387 |     _AddPasswordFromUserInput(self, msg, req) | 
| Sarah Owens | 1f7627f | 2012-10-31 09:21:55 -0700 | [diff] [blame] | 388 |     return urllib.request.HTTPDigestAuthHandler.http_error_401( | 
| JoonCheol Park | e986072 | 2012-10-11 02:31:44 +0900 | [diff] [blame] | 389 |       self, req, fp, code, msg, headers) | 
 | 390 |  | 
| Xiaodong Xu | ae0a36c | 2012-01-31 11:10:09 +0800 | [diff] [blame] | 391 |   def http_error_auth_reqed(self, auth_header, host, req, headers): | 
 | 392 |     try: | 
 | 393 |       old_add_header = req.add_header | 
 | 394 |       def _add_header(name, val): | 
 | 395 |         val = val.replace('\n', '') | 
 | 396 |         old_add_header(name, val) | 
 | 397 |       req.add_header = _add_header | 
| Sarah Owens | 1f7627f | 2012-10-31 09:21:55 -0700 | [diff] [blame] | 398 |       return urllib.request.AbstractDigestAuthHandler.http_error_auth_reqed( | 
| Xiaodong Xu | ae0a36c | 2012-01-31 11:10:09 +0800 | [diff] [blame] | 399 |         self, auth_header, host, req, headers) | 
 | 400 |     except: | 
 | 401 |       reset = getattr(self, 'reset_retry_count', None) | 
 | 402 |       if reset is not None: | 
 | 403 |         reset() | 
 | 404 |       elif getattr(self, 'retried', None): | 
 | 405 |         self.retried = 0 | 
 | 406 |       raise | 
 | 407 |  | 
| Carlos Aguado | 1242e60 | 2014-02-03 13:48:47 +0100 | [diff] [blame] | 408 | class _KerberosAuthHandler(urllib.request.BaseHandler): | 
 | 409 |   def __init__(self): | 
 | 410 |     self.retried = 0 | 
 | 411 |     self.context = None | 
 | 412 |     self.handler_order = urllib.request.BaseHandler.handler_order - 50 | 
 | 413 |  | 
| David Pursehouse | 65b0ba5 | 2018-06-24 16:21:51 +0900 | [diff] [blame] | 414 |   def http_error_401(self, req, fp, code, msg, headers): | 
| Carlos Aguado | 1242e60 | 2014-02-03 13:48:47 +0100 | [diff] [blame] | 415 |     host = req.get_host() | 
 | 416 |     retry = self.http_error_auth_reqed('www-authenticate', host, req, headers) | 
 | 417 |     return retry | 
 | 418 |  | 
 | 419 |   def http_error_auth_reqed(self, auth_header, host, req, headers): | 
 | 420 |     try: | 
 | 421 |       spn = "HTTP@%s" % host | 
 | 422 |       authdata = self._negotiate_get_authdata(auth_header, headers) | 
 | 423 |  | 
 | 424 |       if self.retried > 3: | 
 | 425 |         raise urllib.request.HTTPError(req.get_full_url(), 401, | 
 | 426 |           "Negotiate auth failed", headers, None) | 
 | 427 |       else: | 
 | 428 |         self.retried += 1 | 
 | 429 |  | 
 | 430 |       neghdr = self._negotiate_get_svctk(spn, authdata) | 
 | 431 |       if neghdr is None: | 
 | 432 |         return None | 
 | 433 |  | 
 | 434 |       req.add_unredirected_header('Authorization', neghdr) | 
 | 435 |       response = self.parent.open(req) | 
 | 436 |  | 
 | 437 |       srvauth = self._negotiate_get_authdata(auth_header, response.info()) | 
 | 438 |       if self._validate_response(srvauth): | 
 | 439 |         return response | 
 | 440 |     except kerberos.GSSError: | 
 | 441 |       return None | 
 | 442 |     except: | 
 | 443 |       self.reset_retry_count() | 
 | 444 |       raise | 
 | 445 |     finally: | 
 | 446 |       self._clean_context() | 
 | 447 |  | 
 | 448 |   def reset_retry_count(self): | 
 | 449 |     self.retried = 0 | 
 | 450 |  | 
 | 451 |   def _negotiate_get_authdata(self, auth_header, headers): | 
 | 452 |     authhdr = headers.get(auth_header, None) | 
 | 453 |     if authhdr is not None: | 
 | 454 |       for mech_tuple in authhdr.split(","): | 
 | 455 |         mech, __, authdata = mech_tuple.strip().partition(" ") | 
 | 456 |         if mech.lower() == "negotiate": | 
 | 457 |           return authdata.strip() | 
 | 458 |     return None | 
 | 459 |  | 
 | 460 |   def _negotiate_get_svctk(self, spn, authdata): | 
 | 461 |     if authdata is None: | 
 | 462 |       return None | 
 | 463 |  | 
 | 464 |     result, self.context = kerberos.authGSSClientInit(spn) | 
 | 465 |     if result < kerberos.AUTH_GSS_COMPLETE: | 
 | 466 |       return None | 
 | 467 |  | 
 | 468 |     result = kerberos.authGSSClientStep(self.context, authdata) | 
 | 469 |     if result < kerberos.AUTH_GSS_CONTINUE: | 
 | 470 |       return None | 
 | 471 |  | 
 | 472 |     response = kerberos.authGSSClientResponse(self.context) | 
 | 473 |     return "Negotiate %s" % response | 
 | 474 |  | 
 | 475 |   def _validate_response(self, authdata): | 
 | 476 |     if authdata is None: | 
 | 477 |       return None | 
 | 478 |     result = kerberos.authGSSClientStep(self.context, authdata) | 
 | 479 |     if result == kerberos.AUTH_GSS_COMPLETE: | 
 | 480 |       return True | 
 | 481 |     return None | 
 | 482 |  | 
 | 483 |   def _clean_context(self): | 
 | 484 |     if self.context is not None: | 
 | 485 |       kerberos.authGSSClientClean(self.context) | 
 | 486 |       self.context = None | 
 | 487 |  | 
| Shawn O. Pearce | 014d060 | 2011-09-11 12:57:15 -0700 | [diff] [blame] | 488 | def init_http(): | 
| Shawn O. Pearce | 334851e | 2011-09-19 08:05:31 -0700 | [diff] [blame] | 489 |   handlers = [_UserAgentHandler()] | 
 | 490 |  | 
| Sarah Owens | 1f7627f | 2012-10-31 09:21:55 -0700 | [diff] [blame] | 491 |   mgr = urllib.request.HTTPPasswordMgrWithDefaultRealm() | 
| Shawn O. Pearce | bd0312a | 2011-09-19 10:04:23 -0700 | [diff] [blame] | 492 |   try: | 
 | 493 |     n = netrc.netrc() | 
 | 494 |     for host in n.hosts: | 
 | 495 |       p = n.hosts[host] | 
| Xiaodong Xu | ae0a36c | 2012-01-31 11:10:09 +0800 | [diff] [blame] | 496 |       mgr.add_password(p[1], 'http://%s/'  % host, p[0], p[2]) | 
 | 497 |       mgr.add_password(p[1], 'https://%s/' % host, p[0], p[2]) | 
| Shawn O. Pearce | bd0312a | 2011-09-19 10:04:23 -0700 | [diff] [blame] | 498 |   except netrc.NetrcParseError: | 
 | 499 |     pass | 
| Shawn O. Pearce | 7b947de | 2011-09-23 11:50:31 -0700 | [diff] [blame] | 500 |   except IOError: | 
 | 501 |     pass | 
| Shawn O. Pearce | fab96c6 | 2011-10-11 12:00:38 -0700 | [diff] [blame] | 502 |   handlers.append(_BasicAuthHandler(mgr)) | 
| Xiaodong Xu | ae0a36c | 2012-01-31 11:10:09 +0800 | [diff] [blame] | 503 |   handlers.append(_DigestAuthHandler(mgr)) | 
| Carlos Aguado | 1242e60 | 2014-02-03 13:48:47 +0100 | [diff] [blame] | 504 |   if kerberos: | 
 | 505 |     handlers.append(_KerberosAuthHandler()) | 
| Shawn O. Pearce | bd0312a | 2011-09-19 10:04:23 -0700 | [diff] [blame] | 506 |  | 
| Shawn O. Pearce | 014d060 | 2011-09-11 12:57:15 -0700 | [diff] [blame] | 507 |   if 'http_proxy' in os.environ: | 
 | 508 |     url = os.environ['http_proxy'] | 
| Sarah Owens | 1f7627f | 2012-10-31 09:21:55 -0700 | [diff] [blame] | 509 |     handlers.append(urllib.request.ProxyHandler({'http': url, 'https': url})) | 
| Shawn O. Pearce | 334851e | 2011-09-19 08:05:31 -0700 | [diff] [blame] | 510 |   if 'REPO_CURL_VERBOSE' in os.environ: | 
| Sarah Owens | 1f7627f | 2012-10-31 09:21:55 -0700 | [diff] [blame] | 511 |     handlers.append(urllib.request.HTTPHandler(debuglevel=1)) | 
 | 512 |     handlers.append(urllib.request.HTTPSHandler(debuglevel=1)) | 
 | 513 |   urllib.request.install_opener(urllib.request.build_opener(*handlers)) | 
| Shawn O. Pearce | 014d060 | 2011-09-11 12:57:15 -0700 | [diff] [blame] | 514 |  | 
| The Android Open Source Project | cf31fe9 | 2008-10-21 07:00:00 -0700 | [diff] [blame] | 515 | def _Main(argv): | 
| Daniel Sandler | 3ce2a6b | 2011-04-29 09:59:12 -0400 | [diff] [blame] | 516 |   result = 0 | 
 | 517 |  | 
| The Android Open Source Project | cf31fe9 | 2008-10-21 07:00:00 -0700 | [diff] [blame] | 518 |   opt = optparse.OptionParser(usage="repo wrapperinfo -- ...") | 
 | 519 |   opt.add_option("--repo-dir", dest="repodir", | 
 | 520 |                  help="path to .repo/") | 
 | 521 |   opt.add_option("--wrapper-version", dest="wrapper_version", | 
 | 522 |                  help="version of the wrapper script") | 
 | 523 |   opt.add_option("--wrapper-path", dest="wrapper_path", | 
 | 524 |                  help="location of the wrapper script") | 
 | 525 |   _PruneOptions(argv, opt) | 
 | 526 |   opt, argv = opt.parse_args(argv) | 
 | 527 |  | 
 | 528 |   _CheckWrapperVersion(opt.wrapper_version, opt.wrapper_path) | 
 | 529 |   _CheckRepoDir(opt.repodir) | 
 | 530 |  | 
| Shawn O. Pearce | ecff4f1 | 2011-11-29 15:01:33 -0800 | [diff] [blame] | 531 |   Version.wrapper_version = opt.wrapper_version | 
 | 532 |   Version.wrapper_path = opt.wrapper_path | 
 | 533 |  | 
| The Android Open Source Project | cf31fe9 | 2008-10-21 07:00:00 -0700 | [diff] [blame] | 534 |   repo = _Repo(opt.repodir) | 
 | 535 |   try: | 
| Shawn O. Pearce | fb23161 | 2009-04-10 18:53:46 -0700 | [diff] [blame] | 536 |     try: | 
| Doug Anderson | 0048b69 | 2010-12-21 13:39:23 -0800 | [diff] [blame] | 537 |       init_ssh() | 
| Shawn O. Pearce | 014d060 | 2011-09-11 12:57:15 -0700 | [diff] [blame] | 538 |       init_http() | 
| Mike Frysinger | 3fc1572 | 2019-08-27 00:36:46 -0400 | [diff] [blame] | 539 |       name, gopts, argv = repo._ParseArgs(argv) | 
 | 540 |       run = lambda: repo._Run(name, gopts, argv) or 0 | 
 | 541 |       if gopts.trace_python: | 
 | 542 |         import trace | 
 | 543 |         tracer = trace.Trace(count=False, trace=True, timing=True, | 
 | 544 |                              ignoredirs=set(sys.path[1:])) | 
 | 545 |         result = tracer.runfunc(run) | 
 | 546 |       else: | 
 | 547 |         result = run() | 
| Shawn O. Pearce | fb23161 | 2009-04-10 18:53:46 -0700 | [diff] [blame] | 548 |     finally: | 
 | 549 |       close_ssh() | 
| The Android Open Source Project | cf31fe9 | 2008-10-21 07:00:00 -0700 | [diff] [blame] | 550 |   except KeyboardInterrupt: | 
| Sarah Owens | cecd1d8 | 2012-11-01 22:59:27 -0700 | [diff] [blame] | 551 |     print('aborted by user', file=sys.stderr) | 
| Daniel Sandler | 3ce2a6b | 2011-04-29 09:59:12 -0400 | [diff] [blame] | 552 |     result = 1 | 
| David Pursehouse | 0b8df7b | 2012-11-13 09:51:57 +0900 | [diff] [blame] | 553 |   except ManifestParseError as mpe: | 
| Sarah Owens | cecd1d8 | 2012-11-01 22:59:27 -0700 | [diff] [blame] | 554 |     print('fatal: %s' % mpe, file=sys.stderr) | 
| David Pursehouse | 0b8df7b | 2012-11-13 09:51:57 +0900 | [diff] [blame] | 555 |     result = 1 | 
| Sarah Owens | a5be53f | 2012-09-09 15:37:57 -0700 | [diff] [blame] | 556 |   except RepoChangedException as rce: | 
| Shawn O. Pearce | c9ef744 | 2008-11-03 10:32:09 -0800 | [diff] [blame] | 557 |     # If repo changed, re-exec ourselves. | 
| The Android Open Source Project | cf31fe9 | 2008-10-21 07:00:00 -0700 | [diff] [blame] | 558 |     # | 
| Shawn O. Pearce | c9ef744 | 2008-11-03 10:32:09 -0800 | [diff] [blame] | 559 |     argv = list(sys.argv) | 
 | 560 |     argv.extend(rce.extra_args) | 
| The Android Open Source Project | cf31fe9 | 2008-10-21 07:00:00 -0700 | [diff] [blame] | 561 |     try: | 
| Shawn O. Pearce | c9ef744 | 2008-11-03 10:32:09 -0800 | [diff] [blame] | 562 |       os.execv(__file__, argv) | 
| Sarah Owens | a5be53f | 2012-09-09 15:37:57 -0700 | [diff] [blame] | 563 |     except OSError as e: | 
| Sarah Owens | cecd1d8 | 2012-11-01 22:59:27 -0700 | [diff] [blame] | 564 |       print('fatal: cannot restart repo after upgrade', file=sys.stderr) | 
 | 565 |       print('fatal: %s' % e, file=sys.stderr) | 
| Daniel Sandler | 3ce2a6b | 2011-04-29 09:59:12 -0400 | [diff] [blame] | 566 |       result = 128 | 
 | 567 |  | 
| Renaud Paquay | e8595e9 | 2016-11-01 15:51:59 -0700 | [diff] [blame] | 568 |   TerminatePager() | 
| Daniel Sandler | 3ce2a6b | 2011-04-29 09:59:12 -0400 | [diff] [blame] | 569 |   sys.exit(result) | 
| The Android Open Source Project | cf31fe9 | 2008-10-21 07:00:00 -0700 | [diff] [blame] | 570 |  | 
 | 571 | if __name__ == '__main__': | 
 | 572 |   _Main(sys.argv[1:]) |