blob: 9c545b3127cb2f06014b5df62efe59afbdfc401e [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
25import optparse
26import os
27import re
28import sys
Shawn O. Pearce014d0602011-09-11 12:57:15 -070029import urllib2
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -070030
Shawn O. Pearcead3193a2009-04-18 09:54:51 -070031from trace import SetTrace
Shawn O. Pearce334851e2011-09-19 08:05:31 -070032from git_command import git, GitCommand
Doug Anderson0048b692010-12-21 13:39:23 -080033from git_config import init_ssh, close_ssh
Shawn O. Pearcec95583b2009-03-03 17:47:06 -080034from command import InteractiveCommand
35from command import MirrorSafeCommand
36from command import PagedCommand
Shawn O. Pearce7965f9f2008-10-29 15:20:02 -070037from editor import Editor
Shawn O. Pearce559b8462009-03-02 12:56:08 -080038from error import ManifestInvalidRevisionError
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -070039from error import NoSuchProjectError
40from error import RepoChangedException
Shawn O. Pearcec8a300f2009-05-18 13:19:57 -070041from manifest_xml import XmlManifest
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -070042from pager import RunPager
43
44from subcmds import all as all_commands
45
46global_options = optparse.OptionParser(
47 usage="repo [-p|--paginate|--no-pager] COMMAND [ARGS]"
48 )
49global_options.add_option('-p', '--paginate',
50 dest='pager', action='store_true',
51 help='display command output in the pager')
52global_options.add_option('--no-pager',
53 dest='no_pager', action='store_true',
54 help='disable the pager')
Shawn O. Pearce0ed2bd12009-03-09 18:26:31 -070055global_options.add_option('--trace',
56 dest='trace', action='store_true',
57 help='trace git command execution')
Shawn O. Pearce47c1a632009-03-02 18:24:23 -080058global_options.add_option('--version',
59 dest='show_version', action='store_true',
60 help='display this version of repo')
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -070061
62class _Repo(object):
63 def __init__(self, repodir):
64 self.repodir = repodir
65 self.commands = all_commands
Mike Lockwood2bf9db02009-07-14 15:23:39 -040066 # add 'branch' as an alias for 'branches'
67 all_commands['branch'] = all_commands['branches']
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -070068
69 def _Run(self, argv):
70 name = None
71 glob = []
72
73 for i in xrange(0, len(argv)):
74 if not argv[i].startswith('-'):
75 name = argv[i]
76 if i > 0:
77 glob = argv[:i]
78 argv = argv[i + 1:]
79 break
80 if not name:
81 glob = argv
82 name = 'help'
83 argv = []
84 gopts, gargs = global_options.parse_args(glob)
85
Shawn O. Pearce0ed2bd12009-03-09 18:26:31 -070086 if gopts.trace:
Shawn O. Pearcead3193a2009-04-18 09:54:51 -070087 SetTrace()
Shawn O. Pearce47c1a632009-03-02 18:24:23 -080088 if gopts.show_version:
89 if name == 'help':
90 name = 'version'
91 else:
92 print >>sys.stderr, 'fatal: invalid usage of --version'
93 sys.exit(1)
94
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -070095 try:
96 cmd = self.commands[name]
97 except KeyError:
98 print >>sys.stderr,\
99 "repo: '%s' is not a repo command. See 'repo help'."\
100 % name
101 sys.exit(1)
102
103 cmd.repodir = self.repodir
Shawn O. Pearcec8a300f2009-05-18 13:19:57 -0700104 cmd.manifest = XmlManifest(cmd.repodir)
Shawn O. Pearce7965f9f2008-10-29 15:20:02 -0700105 Editor.globalConfig = cmd.manifest.globalConfig
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700106
Shawn O. Pearcec95583b2009-03-03 17:47:06 -0800107 if not isinstance(cmd, MirrorSafeCommand) and cmd.manifest.IsMirror:
108 print >>sys.stderr, \
109 "fatal: '%s' requires a working directory"\
110 % name
111 sys.exit(1)
112
Shawn O. Pearcedb45da12009-04-18 13:49:13 -0700113 copts, cargs = cmd.OptionParser.parse_args(argv)
114
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700115 if not gopts.no_pager and not isinstance(cmd, InteractiveCommand):
116 config = cmd.manifest.globalConfig
117 if gopts.pager:
118 use_pager = True
119 else:
120 use_pager = config.GetBoolean('pager.%s' % name)
121 if use_pager is None:
Shawn O. Pearcedb45da12009-04-18 13:49:13 -0700122 use_pager = cmd.WantPager(copts)
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700123 if use_pager:
124 RunPager(config)
125
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700126 try:
127 cmd.Execute(copts, cargs)
Shawn O. Pearce559b8462009-03-02 12:56:08 -0800128 except ManifestInvalidRevisionError, e:
129 print >>sys.stderr, 'error: %s' % str(e)
130 sys.exit(1)
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700131 except NoSuchProjectError, e:
132 if e.name:
133 print >>sys.stderr, 'error: project %s not found' % e.name
134 else:
135 print >>sys.stderr, 'error: no project in current directory'
136 sys.exit(1)
137
Shawn O. Pearce334851e2011-09-19 08:05:31 -0700138def _MyRepoPath():
139 return os.path.dirname(__file__)
140
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700141def _MyWrapperPath():
142 return os.path.join(os.path.dirname(__file__), 'repo')
143
144def _CurrentWrapperVersion():
145 VERSION = None
146 pat = re.compile(r'^VERSION *=')
147 fd = open(_MyWrapperPath())
148 for line in fd:
149 if pat.match(line):
150 fd.close()
151 exec line
152 return VERSION
153 raise NameError, 'No VERSION in repo script'
154
155def _CheckWrapperVersion(ver, repo_path):
156 if not repo_path:
157 repo_path = '~/bin/repo'
158
159 if not ver:
160 print >>sys.stderr, 'no --wrapper-version argument'
161 sys.exit(1)
162
163 exp = _CurrentWrapperVersion()
164 ver = tuple(map(lambda x: int(x), ver.split('.')))
165 if len(ver) == 1:
166 ver = (0, ver[0])
167
168 if exp[0] > ver[0] or ver < (0, 4):
169 exp_str = '.'.join(map(lambda x: str(x), exp))
170 print >>sys.stderr, """
171!!! A new repo command (%5s) is available. !!!
172!!! You must upgrade before you can continue: !!!
173
174 cp %s %s
175""" % (exp_str, _MyWrapperPath(), repo_path)
176 sys.exit(1)
177
178 if exp > ver:
179 exp_str = '.'.join(map(lambda x: str(x), exp))
180 print >>sys.stderr, """
181... A new repo command (%5s) is available.
182... You should upgrade soon:
183
184 cp %s %s
185""" % (exp_str, _MyWrapperPath(), repo_path)
186
187def _CheckRepoDir(dir):
188 if not dir:
189 print >>sys.stderr, 'no --repo-dir argument'
190 sys.exit(1)
191
192def _PruneOptions(argv, opt):
193 i = 0
194 while i < len(argv):
195 a = argv[i]
196 if a == '--':
197 break
198 if a.startswith('--'):
199 eq = a.find('=')
200 if eq > 0:
201 a = a[0:eq]
202 if not opt.has_option(a):
203 del argv[i]
204 continue
205 i += 1
206
Shawn O. Pearce334851e2011-09-19 08:05:31 -0700207_user_agent = None
208
209def _UserAgent():
210 global _user_agent
211
212 if _user_agent is None:
213 py_version = sys.version_info
214
215 os_name = sys.platform
216 if os_name == 'linux2':
217 os_name = 'Linux'
218 elif os_name == 'win32':
219 os_name = 'Win32'
220 elif os_name == 'cygwin':
221 os_name = 'Cygwin'
222 elif os_name == 'darwin':
223 os_name = 'Darwin'
224
225 p = GitCommand(
226 None, ['describe', 'HEAD'],
227 cwd = _MyRepoPath(),
228 capture_stdout = True)
229 if p.Wait() == 0:
230 repo_version = p.stdout
231 if len(repo_version) > 0 and repo_version[-1] == '\n':
232 repo_version = repo_version[0:-1]
233 if len(repo_version) > 0 and repo_version[0] == 'v':
234 repo_version = repo_version[1:]
235 else:
236 repo_version = 'unknown'
237
238 _user_agent = 'git-repo/%s (%s) git/%s Python/%d.%d.%d' % (
239 repo_version,
240 os_name,
241 '.'.join(map(lambda d: str(d), git.version_tuple())),
242 py_version[0], py_version[1], py_version[2])
243 return _user_agent
244
245class _UserAgentHandler(urllib2.BaseHandler):
246 def http_request(self, req):
247 req.add_header('User-Agent', _UserAgent())
248 return req
249
250 def https_request(self, req):
251 req.add_header('User-Agent', _UserAgent())
252 return req
253
Shawn O. Pearce014d0602011-09-11 12:57:15 -0700254def init_http():
Shawn O. Pearce334851e2011-09-19 08:05:31 -0700255 handlers = [_UserAgentHandler()]
256
Shawn O. Pearce014d0602011-09-11 12:57:15 -0700257 if 'http_proxy' in os.environ:
258 url = os.environ['http_proxy']
Shawn O. Pearce334851e2011-09-19 08:05:31 -0700259 handlers.append(urllib2.ProxyHandler({'http': url, 'https': url}))
260 if 'REPO_CURL_VERBOSE' in os.environ:
261 handlers.append(urllib2.HTTPHandler(debuglevel=1))
262 handlers.append(urllib2.HTTPSHandler(debuglevel=1))
263 urllib2.install_opener(urllib2.build_opener(*handlers))
Shawn O. Pearce014d0602011-09-11 12:57:15 -0700264
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700265def _Main(argv):
266 opt = optparse.OptionParser(usage="repo wrapperinfo -- ...")
267 opt.add_option("--repo-dir", dest="repodir",
268 help="path to .repo/")
269 opt.add_option("--wrapper-version", dest="wrapper_version",
270 help="version of the wrapper script")
271 opt.add_option("--wrapper-path", dest="wrapper_path",
272 help="location of the wrapper script")
273 _PruneOptions(argv, opt)
274 opt, argv = opt.parse_args(argv)
275
276 _CheckWrapperVersion(opt.wrapper_version, opt.wrapper_path)
277 _CheckRepoDir(opt.repodir)
278
279 repo = _Repo(opt.repodir)
280 try:
Shawn O. Pearcefb231612009-04-10 18:53:46 -0700281 try:
Doug Anderson0048b692010-12-21 13:39:23 -0800282 init_ssh()
Shawn O. Pearce014d0602011-09-11 12:57:15 -0700283 init_http()
Shawn O. Pearcefb231612009-04-10 18:53:46 -0700284 repo._Run(argv)
285 finally:
286 close_ssh()
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700287 except KeyboardInterrupt:
288 sys.exit(1)
Shawn O. Pearcec9ef7442008-11-03 10:32:09 -0800289 except RepoChangedException, rce:
290 # If repo changed, re-exec ourselves.
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700291 #
Shawn O. Pearcec9ef7442008-11-03 10:32:09 -0800292 argv = list(sys.argv)
293 argv.extend(rce.extra_args)
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700294 try:
Shawn O. Pearcec9ef7442008-11-03 10:32:09 -0800295 os.execv(__file__, argv)
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700296 except OSError, e:
297 print >>sys.stderr, 'fatal: cannot restart repo after upgrade'
298 print >>sys.stderr, 'fatal: %s' % e
299 sys.exit(128)
300
301if __name__ == '__main__':
302 _Main(sys.argv[1:])