blob: f80bd45e2e3d72d189fc0f7809ebb84fc1ffe6fd [file] [log] [blame]
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -07001#!/bin/sh
2#
3# Copyright (C) 2008 The Android Open Source Project
4#
5# Licensed under the Apache License, Version 2.0 (the "License");
6# you may not use this file except in compliance with the License.
7# You may obtain a copy of the License at
8#
9# http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS,
13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14# See the License for the specific language governing permissions and
15# limitations under the License.
16
17magic='--calling-python-from-/bin/sh--'
Shawn O. Pearce7542d662008-10-21 07:11:36 -070018"""exec" python -E "$0" "$@" """#$magic"
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -070019if __name__ == '__main__':
20 import sys
21 if sys.argv[-1] == '#%s' % magic:
22 del sys.argv[-1]
23del magic
24
Shawn O. Pearcebd0312a2011-09-19 10:04:23 -070025import netrc
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -070026import optparse
27import os
28import re
29import sys
Shawn O. Pearce014d0602011-09-11 12:57:15 -070030import urllib2
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -070031
Shawn O. Pearcead3193a2009-04-18 09:54:51 -070032from trace import SetTrace
Shawn O. Pearce334851e2011-09-19 08:05:31 -070033from git_command import git, GitCommand
Doug Anderson0048b692010-12-21 13:39:23 -080034from git_config import init_ssh, close_ssh
Shawn O. Pearcec95583b2009-03-03 17:47:06 -080035from command import InteractiveCommand
36from command import MirrorSafeCommand
37from command import PagedCommand
Shawn O. Pearce7965f9f2008-10-29 15:20:02 -070038from editor import Editor
Shawn O. Pearce559b8462009-03-02 12:56:08 -080039from error import ManifestInvalidRevisionError
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -070040from error import NoSuchProjectError
41from error import RepoChangedException
Shawn O. Pearcec8a300f2009-05-18 13:19:57 -070042from manifest_xml import XmlManifest
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -070043from pager import RunPager
44
45from subcmds import all as all_commands
46
47global_options = optparse.OptionParser(
48 usage="repo [-p|--paginate|--no-pager] COMMAND [ARGS]"
49 )
50global_options.add_option('-p', '--paginate',
51 dest='pager', action='store_true',
52 help='display command output in the pager')
53global_options.add_option('--no-pager',
54 dest='no_pager', action='store_true',
55 help='disable the pager')
Shawn O. Pearce0ed2bd12009-03-09 18:26:31 -070056global_options.add_option('--trace',
57 dest='trace', action='store_true',
58 help='trace git command execution')
Shawn O. Pearce47c1a632009-03-02 18:24:23 -080059global_options.add_option('--version',
60 dest='show_version', action='store_true',
61 help='display this version of repo')
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -070062
63class _Repo(object):
64 def __init__(self, repodir):
65 self.repodir = repodir
66 self.commands = all_commands
Mike Lockwood2bf9db02009-07-14 15:23:39 -040067 # add 'branch' as an alias for 'branches'
68 all_commands['branch'] = all_commands['branches']
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -070069
70 def _Run(self, argv):
71 name = None
72 glob = []
73
74 for i in xrange(0, len(argv)):
75 if not argv[i].startswith('-'):
76 name = argv[i]
77 if i > 0:
78 glob = argv[:i]
79 argv = argv[i + 1:]
80 break
81 if not name:
82 glob = argv
83 name = 'help'
84 argv = []
85 gopts, gargs = global_options.parse_args(glob)
86
Shawn O. Pearce0ed2bd12009-03-09 18:26:31 -070087 if gopts.trace:
Shawn O. Pearcead3193a2009-04-18 09:54:51 -070088 SetTrace()
Shawn O. Pearce47c1a632009-03-02 18:24:23 -080089 if gopts.show_version:
90 if name == 'help':
91 name = 'version'
92 else:
93 print >>sys.stderr, 'fatal: invalid usage of --version'
94 sys.exit(1)
95
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -070096 try:
97 cmd = self.commands[name]
98 except KeyError:
99 print >>sys.stderr,\
100 "repo: '%s' is not a repo command. See 'repo help'."\
101 % name
102 sys.exit(1)
103
104 cmd.repodir = self.repodir
Shawn O. Pearcec8a300f2009-05-18 13:19:57 -0700105 cmd.manifest = XmlManifest(cmd.repodir)
Shawn O. Pearce7965f9f2008-10-29 15:20:02 -0700106 Editor.globalConfig = cmd.manifest.globalConfig
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700107
Shawn O. Pearcec95583b2009-03-03 17:47:06 -0800108 if not isinstance(cmd, MirrorSafeCommand) and cmd.manifest.IsMirror:
109 print >>sys.stderr, \
110 "fatal: '%s' requires a working directory"\
111 % name
112 sys.exit(1)
113
Shawn O. Pearcedb45da12009-04-18 13:49:13 -0700114 copts, cargs = cmd.OptionParser.parse_args(argv)
115
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700116 if not gopts.no_pager and not isinstance(cmd, InteractiveCommand):
117 config = cmd.manifest.globalConfig
118 if gopts.pager:
119 use_pager = True
120 else:
121 use_pager = config.GetBoolean('pager.%s' % name)
122 if use_pager is None:
Shawn O. Pearcedb45da12009-04-18 13:49:13 -0700123 use_pager = cmd.WantPager(copts)
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700124 if use_pager:
125 RunPager(config)
126
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700127 try:
128 cmd.Execute(copts, cargs)
Shawn O. Pearce559b8462009-03-02 12:56:08 -0800129 except ManifestInvalidRevisionError, e:
130 print >>sys.stderr, 'error: %s' % str(e)
131 sys.exit(1)
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700132 except NoSuchProjectError, e:
133 if e.name:
134 print >>sys.stderr, 'error: project %s not found' % e.name
135 else:
136 print >>sys.stderr, 'error: no project in current directory'
137 sys.exit(1)
138
Shawn O. Pearce334851e2011-09-19 08:05:31 -0700139def _MyRepoPath():
140 return os.path.dirname(__file__)
141
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700142def _MyWrapperPath():
143 return os.path.join(os.path.dirname(__file__), 'repo')
144
145def _CurrentWrapperVersion():
146 VERSION = None
147 pat = re.compile(r'^VERSION *=')
148 fd = open(_MyWrapperPath())
149 for line in fd:
150 if pat.match(line):
151 fd.close()
152 exec line
153 return VERSION
154 raise NameError, 'No VERSION in repo script'
155
156def _CheckWrapperVersion(ver, repo_path):
157 if not repo_path:
158 repo_path = '~/bin/repo'
159
160 if not ver:
161 print >>sys.stderr, 'no --wrapper-version argument'
162 sys.exit(1)
163
164 exp = _CurrentWrapperVersion()
165 ver = tuple(map(lambda x: int(x), ver.split('.')))
166 if len(ver) == 1:
167 ver = (0, ver[0])
168
169 if exp[0] > ver[0] or ver < (0, 4):
170 exp_str = '.'.join(map(lambda x: str(x), exp))
171 print >>sys.stderr, """
172!!! A new repo command (%5s) is available. !!!
173!!! You must upgrade before you can continue: !!!
174
175 cp %s %s
176""" % (exp_str, _MyWrapperPath(), repo_path)
177 sys.exit(1)
178
179 if exp > ver:
180 exp_str = '.'.join(map(lambda x: str(x), exp))
181 print >>sys.stderr, """
182... A new repo command (%5s) is available.
183... You should upgrade soon:
184
185 cp %s %s
186""" % (exp_str, _MyWrapperPath(), repo_path)
187
188def _CheckRepoDir(dir):
189 if not dir:
190 print >>sys.stderr, 'no --repo-dir argument'
191 sys.exit(1)
192
193def _PruneOptions(argv, opt):
194 i = 0
195 while i < len(argv):
196 a = argv[i]
197 if a == '--':
198 break
199 if a.startswith('--'):
200 eq = a.find('=')
201 if eq > 0:
202 a = a[0:eq]
203 if not opt.has_option(a):
204 del argv[i]
205 continue
206 i += 1
207
Shawn O. Pearce334851e2011-09-19 08:05:31 -0700208_user_agent = None
209
210def _UserAgent():
211 global _user_agent
212
213 if _user_agent is None:
214 py_version = sys.version_info
215
216 os_name = sys.platform
217 if os_name == 'linux2':
218 os_name = 'Linux'
219 elif os_name == 'win32':
220 os_name = 'Win32'
221 elif os_name == 'cygwin':
222 os_name = 'Cygwin'
223 elif os_name == 'darwin':
224 os_name = 'Darwin'
225
226 p = GitCommand(
227 None, ['describe', 'HEAD'],
228 cwd = _MyRepoPath(),
229 capture_stdout = True)
230 if p.Wait() == 0:
231 repo_version = p.stdout
232 if len(repo_version) > 0 and repo_version[-1] == '\n':
233 repo_version = repo_version[0:-1]
234 if len(repo_version) > 0 and repo_version[0] == 'v':
235 repo_version = repo_version[1:]
236 else:
237 repo_version = 'unknown'
238
239 _user_agent = 'git-repo/%s (%s) git/%s Python/%d.%d.%d' % (
240 repo_version,
241 os_name,
242 '.'.join(map(lambda d: str(d), git.version_tuple())),
243 py_version[0], py_version[1], py_version[2])
244 return _user_agent
245
246class _UserAgentHandler(urllib2.BaseHandler):
247 def http_request(self, req):
248 req.add_header('User-Agent', _UserAgent())
249 return req
250
251 def https_request(self, req):
252 req.add_header('User-Agent', _UserAgent())
253 return req
254
Shawn O. Pearce014d0602011-09-11 12:57:15 -0700255def init_http():
Shawn O. Pearce334851e2011-09-19 08:05:31 -0700256 handlers = [_UserAgentHandler()]
257
Shawn O. Pearcebd0312a2011-09-19 10:04:23 -0700258 mgr = urllib2.HTTPPasswordMgrWithDefaultRealm()
259 try:
260 n = netrc.netrc()
261 for host in n.hosts:
262 p = n.hosts[host]
263 mgr.add_password(None, 'http://%s/' % host, p[0], p[2])
264 mgr.add_password(None, 'https://%s/' % host, p[0], p[2])
265 except netrc.NetrcParseError:
266 pass
267 handlers.append(urllib2.HTTPBasicAuthHandler(mgr))
268
Shawn O. Pearce014d0602011-09-11 12:57:15 -0700269 if 'http_proxy' in os.environ:
270 url = os.environ['http_proxy']
Shawn O. Pearce334851e2011-09-19 08:05:31 -0700271 handlers.append(urllib2.ProxyHandler({'http': url, 'https': url}))
272 if 'REPO_CURL_VERBOSE' in os.environ:
273 handlers.append(urllib2.HTTPHandler(debuglevel=1))
274 handlers.append(urllib2.HTTPSHandler(debuglevel=1))
275 urllib2.install_opener(urllib2.build_opener(*handlers))
Shawn O. Pearce014d0602011-09-11 12:57:15 -0700276
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700277def _Main(argv):
278 opt = optparse.OptionParser(usage="repo wrapperinfo -- ...")
279 opt.add_option("--repo-dir", dest="repodir",
280 help="path to .repo/")
281 opt.add_option("--wrapper-version", dest="wrapper_version",
282 help="version of the wrapper script")
283 opt.add_option("--wrapper-path", dest="wrapper_path",
284 help="location of the wrapper script")
285 _PruneOptions(argv, opt)
286 opt, argv = opt.parse_args(argv)
287
288 _CheckWrapperVersion(opt.wrapper_version, opt.wrapper_path)
289 _CheckRepoDir(opt.repodir)
290
291 repo = _Repo(opt.repodir)
292 try:
Shawn O. Pearcefb231612009-04-10 18:53:46 -0700293 try:
Doug Anderson0048b692010-12-21 13:39:23 -0800294 init_ssh()
Shawn O. Pearce014d0602011-09-11 12:57:15 -0700295 init_http()
Shawn O. Pearcefb231612009-04-10 18:53:46 -0700296 repo._Run(argv)
297 finally:
298 close_ssh()
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700299 except KeyboardInterrupt:
300 sys.exit(1)
Shawn O. Pearcec9ef7442008-11-03 10:32:09 -0800301 except RepoChangedException, rce:
302 # If repo changed, re-exec ourselves.
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700303 #
Shawn O. Pearcec9ef7442008-11-03 10:32:09 -0800304 argv = list(sys.argv)
305 argv.extend(rce.extra_args)
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700306 try:
Shawn O. Pearcec9ef7442008-11-03 10:32:09 -0800307 os.execv(__file__, argv)
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700308 except OSError, e:
309 print >>sys.stderr, 'fatal: cannot restart repo after upgrade'
310 print >>sys.stderr, 'fatal: %s' % e
311 sys.exit(128)
312
313if __name__ == '__main__':
314 _Main(sys.argv[1:])