[Tizen] Add prelauncher
[platform/framework/web/crosswalk-tizen.git] / vendor / depot_tools / repo
1 #!/usr/bin/env python
2
3 ## repo default configuration
4 ##
5 REPO_URL='https://chromium.googlesource.com/external/repo'
6 REPO_REV='stable'
7
8 # Copyright (C) 2008 Google Inc.
9 #
10 # Licensed under the Apache License, Version 2.0 (the "License");
11 # you may not use this file except in compliance with the License.
12 # You may obtain a copy of the License at
13 #
14 #      http://www.apache.org/licenses/LICENSE-2.0
15 #
16 # Unless required by applicable law or agreed to in writing, software
17 # distributed under the License is distributed on an "AS IS" BASIS,
18 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19 # See the License for the specific language governing permissions and
20 # limitations under the License.
21
22 # increment this whenever we make important changes to this script
23 VERSION = (1, 21)
24
25 # increment this if the MAINTAINER_KEYS block is modified
26 KEYRING_VERSION = (1, 4)
27 MAINTAINER_KEYS = """
28
29      Repo Maintainer <repo@android.kernel.org>
30 -----BEGIN PGP PUBLIC KEY BLOCK-----
31 Version: GnuPG v1.4.2.2 (GNU/Linux)
32
33 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
68 =CMiZ
69 -----END PGP PUBLIC KEY BLOCK-----
70
71      Conley Owens <cco3@android.com>
72 -----BEGIN PGP PUBLIC KEY BLOCK-----
73 Version: GnuPG v1.4.11 (GNU/Linux)
74
75 mQENBFHRvc8BCADFg45Xx/y6QDC+T7Y/gGc7vx0ww7qfOwIKlAZ9xG3qKunMxo+S
76 hPCnzEl3cq+6I1Ww/ndop/HB3N3toPXRCoN8Vs4/Hc7by+SnaLFnacrm+tV5/OgT
77 V37Lzt8lhay1Kl+YfpFwHYYpIEBLFV9knyfRXS/428W2qhdzYfvB15/AasRmwmor
78 py4NIzSs8UD/SPr1ihqNCdZM76+MQyN5HMYXW/ALZXUFG0pwluHFA7hrfPG74i8C
79 zMiP7qvMWIl/r/jtzHioH1dRKgbod+LZsrDJ8mBaqsZaDmNJMhss9g76XvfMyLra
80 9DI9/iFuBpGzeqBv0hwOGQspLRrEoyTeR6n1ABEBAAG0H0NvbmxleSBPd2VucyA8
81 Y2NvM0BhbmRyb2lkLmNvbT6JATgEEwECACIFAlHRvc8CGwMGCwkIBwMCBhUIAgkK
82 CwQWAgMBAh4BAheAAAoJEGe35EhpKzgsP6AIAJKJmNtn4l7hkYHKHFSo3egb6RjQ
83 zEIP3MFTcu8HFX1kF1ZFbrp7xqurLaE53kEkKuAAvjJDAgI8mcZHP1JyplubqjQA
84 xvv84gK+OGP3Xk+QK1ZjUQSbjOpjEiSZpRhWcHci3dgOUH4blJfByHw25hlgHowd
85 a/2PrNKZVcJ92YienaxxGjcXEUcd0uYEG2+rwllQigFcnMFDhr9B71MfalRHjFKE
86 fmdoypqLrri61YBc59P88Rw2/WUpTQjgNubSqa3A2+CKdaRyaRw+2fdF4TdR0h8W
87 zbg+lbaPtJHsV+3mJC7fq26MiJDRJa5ZztpMn8su20gbLgi2ShBOaHAYDDi5AQ0E
88 UdG9zwEIAMoOBq+QLNozAhxOOl5GL3StTStGRgPRXINfmViTsihrqGCWBBUfXlUE
89 OytC0mYcrDUQev/8ToVoyqw+iGSwDkcSXkrEUCKFtHV/GECWtk1keyHgR10YKI1R
90 mquSXoubWGqPeG1PAI74XWaRx8UrL8uCXUtmD8Q5J7mDjKR5NpxaXrwlA0bKsf2E
91 Gp9tu1kKauuToZhWHMRMqYSOGikQJwWSFYKT1KdNcOXLQF6+bfoJ6sjVYdwfmNQL
92 Ixn8QVhoTDedcqClSWB17VDEFDFa7MmqXZz2qtM3X1R/MUMHqPtegQzBGNhRdnI2
93 V45+1Nnx/uuCxDbeI4RbHzujnxDiq70AEQEAAYkBHwQYAQIACQUCUdG9zwIbDAAK
94 CRBnt+RIaSs4LNVeB/0Y2pZ8I7gAAcEM0Xw8drr4omg2fUoK1J33ozlA/RxeA/lJ
95 I3KnyCDTpXuIeBKPGkdL8uMATC9Z8DnBBajRlftNDVZS3Hz4G09G9QpMojvJkFJV
96 By+01Flw/X+eeN8NpqSuLV4W+AjEO8at/VvgKr1AFvBRdZ7GkpI1o6DgPe7ZqX+1
97 dzQZt3e13W0rVBb/bUgx9iSLoeWP3aq/k+/GRGOR+S6F6BBSl0SQ2EF2+dIywb1x
98 JuinEP+AwLAUZ1Bsx9ISC0Agpk2VeHXPL3FGhroEmoMvBzO0kTFGyoeT7PR/BfKv
99 +H/g3HsL2LOB9uoIm8/5p2TTU5ttYCXMHhQZ81AY
100 =AUp4
101 -----END PGP PUBLIC KEY BLOCK-----
102
103      Stefan Zager <szager@chromium.org>
104 -----BEGIN PGP PUBLIC KEY BLOCK-----
105 Version: GnuPG v1.4.11 (GNU/Linux)
106
107 mQINBFIJOcgBEADwZIq4GRGoO1RJFKlrtVK501cwT5H+Acbizc9N5RxTkFmqxDjb
108 9ApUaPW6S1b8+nrzE9P1Ri5erfzipuStfaZ/Wl3mP1JjKulibddmgnPOEbAJ673k
109 Vj85RUO4rt2oZAHnZN3D3gFJzVY8JVlZ47Enj9fTqzcW78FVsPCpIT9P2LpTLWeE
110 jX9Cjxeimy6VvyJstIcDLYhlpUN5UWen79L4LFAkHf3luLuU4W3p9NriqUsy5UG2
111 8vO6QdhKrCr5wsjDFFeVnpMtjlSeZJAWH+XhFFibMX1xP5R9BTuJfzw3kOVKvcE0
112 e9ClxgoulepXPv2xnDkqO3pG2gQVzl8LA+Aol8/IXfa7KP5FBkxK/g1cDuDtXRk4
113 YLpLaLYeeKEhhOHLpsKYkK2DXTIcN+56UnTLGolummpZnCM8UUSZxQgbkFgk4YJL
114 Elip0hgLZzqEl5h9vjmnQp89AZIHKcgNmzn+szLTOR9x24joaLyQ534x8OSC8lmu
115 tJv2tQjDOVGWVwvY4gOTpyxCWMwur6WOiMk/TPWdiVRFWAGrAHwf0/CTBEqNhosh
116 sVXfPeMADBA0PorDbJ6kwcOkLUTGf8CT7OG1R9TuKPEmSjK7BYu/pT4DXitaRCiv
117 uPVlwbVFpLFr0/jwaKJVMLUjL5MaYwzjJqI2c4RdROZhpMhkn4LvCMmFSQARAQAB
118 tCJTdGVmYW4gWmFnZXIgPHN6YWdlckBjaHJvbWl1bS5vcmc+iQI4BBMBAgAiBQJS
119 CTnIAhsDBgsJCAcDAgYVCAIJCgsEFgIDAQIeAQIXgAAKCRDcuoHPGCdZNU0UD/9y
120 0zwwOJH2UGPAzZ0YVzr7p0HtKedoxuFvPkdQxlBIaUOueMzFRmNQu3GI9irAu3MQ
121 Jkip8/gi7dnLVmJyS/zWARBaRGwSVd1++87XDjw8n7l181p7394X0Agq/heri599
122 YheHXkxXKVMPqByWNEPHu4eDbxeJTaDIjcKC2pzKQkm6HbWgW4wA9gCh1TRki8FP
123 LMv1Fu/dr13STCR9P2evsTRZ+ZSJhTSboHNHeEAJGiGZQAsN94oht7647lYj+AyR
124 ThzyHDMXXiDr8jPJIkyRilY+y82bCOatOfPoCkce3VI+LRUGJ19hJY01m4RRneIE
125 55l7fXR3zggcsONjV5b+oLcGQPGgX9w64BJ7khT7Wb9+kuyrdJBIBzJsaACFEbri
126 pPi02FS/HahYpLC3J66REAeNyofgVXau6WQsHrHMGsBTL9aAr0nrCrkF4Nyyc2Jd
127 do6nYuljuUhORqbEECmmBM2eBtkL6Ac92D6WMBIwBOC5tCNHO2YFIvi8Y8EuE8sc
128 1zB5U5Ai4SIu2icRAhzAhCRaUq02cMWuELKH6Vuh9nzgEefFWty6vPbKEyZLu19D
129 B80aqP1cTN88FjtKQ/eTF29TUB6AefUeBS17e2e3WUMy4nc8tduuOFYfiHP40ScP
130 wOoatwfzpiTIPGbocUEPL+pS0O/Xy8SINxFMCud3zA==
131 =Vd2S
132 -----END PGP PUBLIC KEY BLOCK-----
133
134      David James <davidjames@google.com>
135 -----BEGIN PGP PUBLIC KEY BLOCK-----
136 Version: GnuPG v1
137
138 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
184 IM4=
185 =6VNc
186 -----END PGP PUBLIC KEY BLOCK-----
187 """
188
189 GIT = 'git'                     # our git command
190 MIN_GIT_VERSION = (1, 7, 2)     # minimum supported git version
191 repodir = '.repo'               # name of repo's private directory
192 S_repo = 'repo'                 # special repo repository
193 S_manifests = 'manifests'       # special manifest repository
194 REPO_MAIN = S_repo + '/main.py' # main script
195 MIN_PYTHON_VERSION = (2, 6)     # minimum supported python version
196
197
198 import errno
199 import optparse
200 import os
201 import re
202 import stat
203 import subprocess
204 import sys
205
206 if sys.version_info[0] == 3:
207   import urllib.request
208   import urllib.error
209 else:
210   import imp
211   import urllib2
212   urllib = imp.new_module('urllib')
213   urllib.request = urllib2
214   urllib.error = urllib2
215
216
217 def _print(*objects, **kwargs):
218   sep = kwargs.get('sep', ' ')
219   end = kwargs.get('end', '\n')
220   out = kwargs.get('file', sys.stdout)
221   out.write(sep.join(objects) + end)
222
223
224 # Python version check
225 ver = sys.version_info
226 if ver[0] == 3:
227   _print('warning: Python 3 support is currently experimental. YMMV.\n'
228          'Please use Python 2.6 - 2.7 instead.',
229          file=sys.stderr)
230 if (ver[0], ver[1]) < MIN_PYTHON_VERSION:
231   _print('error: Python version %s unsupported.\n'
232          'Please use Python 2.6 - 2.7 instead.'
233          % sys.version.split(' ')[0], file=sys.stderr)
234   sys.exit(1)
235
236 home_dot_repo = os.path.expanduser('~/.repoconfig')
237 gpg_dir = os.path.join(home_dot_repo, 'gnupg')
238
239 extra_args = []
240 init_optparse = optparse.OptionParser(usage="repo init -u url [options]")
241
242 # Logging
243 group = init_optparse.add_option_group('Logging options')
244 group.add_option('-q', '--quiet',
245                  dest="quiet", action="store_true", default=False,
246                  help="be quiet")
247
248 # Manifest
249 group = init_optparse.add_option_group('Manifest options')
250 group.add_option('-u', '--manifest-url',
251                  dest='manifest_url',
252                  help='manifest repository location', metavar='URL')
253 group.add_option('-b', '--manifest-branch',
254                  dest='manifest_branch',
255                  help='manifest branch or revision', metavar='REVISION')
256 group.add_option('-m', '--manifest-name',
257                  dest='manifest_name',
258                  help='initial manifest file', metavar='NAME.xml')
259 group.add_option('--mirror',
260                  dest='mirror', action='store_true',
261                  help='create a replica of the remote repositories '
262                       'rather than a client working directory')
263 group.add_option('--reference',
264                  dest='reference',
265                  help='location of mirror directory', metavar='DIR')
266 group.add_option('--depth', type='int', default=None,
267                  dest='depth',
268                  help='create a shallow clone with given depth; see git clone')
269 group.add_option('--archive',
270                  dest='archive', action='store_true',
271                  help='checkout an archive instead of a git repository for '
272                       'each project. See git archive.')
273 group.add_option('-g', '--groups',
274                  dest='groups', default='default',
275                  help='restrict manifest projects to ones with specified '
276                       'group(s) [default|all|G1,G2,G3|G4,-G5,-G6]',
277                  metavar='GROUP')
278 group.add_option('-p', '--platform',
279                  dest='platform', default="auto",
280                  help='restrict manifest projects to ones with a specified '
281                       'platform group [auto|all|none|linux|darwin|...]',
282                  metavar='PLATFORM')
283
284
285 # Tool
286 group = init_optparse.add_option_group('repo Version options')
287 group.add_option('--repo-url',
288                  dest='repo_url',
289                  help='repo repository location', metavar='URL')
290 group.add_option('--repo-branch',
291                  dest='repo_branch',
292                  help='repo branch or revision', metavar='REVISION')
293 group.add_option('--no-repo-verify',
294                  dest='no_repo_verify', action='store_true',
295                  help='do not verify repo source code')
296
297 # Other
298 group = init_optparse.add_option_group('Other options')
299 group.add_option('--config-name',
300                  dest='config_name', action="store_true", default=False,
301                  help='Always prompt for name/e-mail')
302
303 class CloneFailure(Exception):
304   """Indicate the remote clone of repo itself failed.
305   """
306
307
308 def _Init(args):
309   """Installs repo by cloning it over the network.
310   """
311   opt, args = init_optparse.parse_args(args)
312   if args:
313     init_optparse.print_usage()
314     sys.exit(1)
315
316   url = opt.repo_url
317   if not url:
318     url = REPO_URL
319     extra_args.append('--repo-url=%s' % url)
320
321   branch = opt.repo_branch
322   if not branch:
323     branch = REPO_REV
324     extra_args.append('--repo-branch=%s' % branch)
325
326   if branch.startswith('refs/heads/'):
327     branch = branch[len('refs/heads/'):]
328   if branch.startswith('refs/'):
329     _print("fatal: invalid branch name '%s'" % branch, file=sys.stderr)
330     raise CloneFailure()
331
332   try:
333     os.mkdir(repodir)
334   except OSError as e:
335     if e.errno != errno.EEXIST:
336       _print('fatal: cannot make %s directory: %s'
337              % (repodir, e.strerror), file=sys.stderr)
338       # Don't raise CloneFailure; that would delete the
339       # name. Instead exit immediately.
340       #
341       sys.exit(1)
342
343   _CheckGitVersion()
344   try:
345     if NeedSetupGnuPG():
346       can_verify = SetupGnuPG(opt.quiet)
347     else:
348       can_verify = True
349
350     dst = os.path.abspath(os.path.join(repodir, S_repo))
351     _Clone(url, dst, opt.quiet)
352
353     if can_verify and not opt.no_repo_verify:
354       rev = _Verify(dst, branch, opt.quiet)
355     else:
356       rev = 'refs/remotes/origin/%s^0' % branch
357
358     _Checkout(dst, branch, rev, opt.quiet)
359   except CloneFailure:
360     if opt.quiet:
361       _print('fatal: repo init failed; run without --quiet to see why',
362              file=sys.stderr)
363     raise
364
365
366 def ParseGitVersion(ver_str):
367   if not ver_str.startswith('git version '):
368     return None
369
370   num_ver_str = ver_str[len('git version '):].strip().split('-')[0]
371   to_tuple = []
372   for num_str in num_ver_str.split('.')[:3]:
373     if num_str.isdigit():
374       to_tuple.append(int(num_str))
375     else:
376       to_tuple.append(0)
377   return tuple(to_tuple)
378
379
380 def _CheckGitVersion():
381   cmd = [GIT, '--version']
382   try:
383     proc = subprocess.Popen(cmd, stdout=subprocess.PIPE)
384   except OSError as e:
385     _print(file=sys.stderr)
386     _print("fatal: '%s' is not available" % GIT, file=sys.stderr)
387     _print('fatal: %s' % e, file=sys.stderr)
388     _print(file=sys.stderr)
389     _print('Please make sure %s is installed and in your path.' % GIT,
390            file=sys.stderr)
391     raise CloneFailure()
392
393   ver_str = proc.stdout.read().strip()
394   proc.stdout.close()
395   proc.wait()
396
397   ver_act = ParseGitVersion(ver_str)
398   if ver_act is None:
399     _print('error: "%s" unsupported' % ver_str, file=sys.stderr)
400     raise CloneFailure()
401
402   if ver_act < MIN_GIT_VERSION:
403     need = '.'.join(map(str, MIN_GIT_VERSION))
404     _print('fatal: git %s or later required' % need, file=sys.stderr)
405     raise CloneFailure()
406
407
408 def NeedSetupGnuPG():
409   if not os.path.isdir(home_dot_repo):
410     return True
411
412   kv = os.path.join(home_dot_repo, 'keyring-version')
413   if not os.path.exists(kv):
414     return True
415
416   kv = open(kv).read()
417   if not kv:
418     return True
419
420   kv = tuple(map(int, kv.split('.')))
421   if kv < KEYRING_VERSION:
422     return True
423   return False
424
425
426 def SetupGnuPG(quiet):
427   try:
428     os.mkdir(home_dot_repo)
429   except OSError as e:
430     if e.errno != errno.EEXIST:
431       _print('fatal: cannot make %s directory: %s'
432              % (home_dot_repo, e.strerror), file=sys.stderr)
433       sys.exit(1)
434
435   try:
436     os.mkdir(gpg_dir, stat.S_IRWXU)
437   except OSError as e:
438     if e.errno != errno.EEXIST:
439       _print('fatal: cannot make %s directory: %s' % (gpg_dir, e.strerror),
440              file=sys.stderr)
441       sys.exit(1)
442
443   env = os.environ.copy()
444   env['GNUPGHOME'] = gpg_dir.encode()
445
446   cmd = ['gpg', '--import']
447   try:
448     proc = subprocess.Popen(cmd,
449                             env = env,
450                             stdin = subprocess.PIPE)
451   except OSError as e:
452     if not quiet:
453       _print('warning: gpg (GnuPG) is not available.', file=sys.stderr)
454       _print('warning: Installing it is strongly encouraged.', file=sys.stderr)
455       _print(file=sys.stderr)
456     return False
457
458   proc.stdin.write(MAINTAINER_KEYS)
459   proc.stdin.close()
460
461   if proc.wait() != 0:
462     _print('fatal: registering repo maintainer keys failed', file=sys.stderr)
463     sys.exit(1)
464   _print()
465
466   fd = open(os.path.join(home_dot_repo, 'keyring-version'), 'w')
467   fd.write('.'.join(map(str, KEYRING_VERSION)) + '\n')
468   fd.close()
469   return True
470
471
472 def _SetConfig(local, name, value):
473   """Set a git configuration option to the specified value.
474   """
475   cmd = [GIT, 'config', name, value]
476   if subprocess.Popen(cmd, cwd = local).wait() != 0:
477     raise CloneFailure()
478
479
480 def _InitHttp():
481   handlers = []
482
483   mgr = urllib.request.HTTPPasswordMgrWithDefaultRealm()
484   try:
485     import netrc
486     n = netrc.netrc()
487     for host in n.hosts:
488       p = n.hosts[host]
489       mgr.add_password(p[1], 'http://%s/'  % host, p[0], p[2])
490       mgr.add_password(p[1], 'https://%s/' % host, p[0], p[2])
491   except:
492     pass
493   handlers.append(urllib.request.HTTPBasicAuthHandler(mgr))
494   handlers.append(urllib.request.HTTPDigestAuthHandler(mgr))
495
496   if 'http_proxy' in os.environ:
497     url = os.environ['http_proxy']
498     handlers.append(urllib.request.ProxyHandler({'http': url, 'https': url}))
499   if 'REPO_CURL_VERBOSE' in os.environ:
500     handlers.append(urllib.request.HTTPHandler(debuglevel=1))
501     handlers.append(urllib.request.HTTPSHandler(debuglevel=1))
502   urllib.request.install_opener(urllib.request.build_opener(*handlers))
503
504 def _Fetch(url, local, src, quiet):
505   if not quiet:
506     _print('Get %s' % url, file=sys.stderr)
507
508   cmd = [GIT, 'fetch']
509   if quiet:
510     cmd.append('--quiet')
511     err = subprocess.PIPE
512   else:
513     err = None
514   cmd.append(src)
515   cmd.append('+refs/heads/*:refs/remotes/origin/*')
516   cmd.append('refs/tags/*:refs/tags/*')
517
518   proc = subprocess.Popen(cmd, cwd = local, stderr = err)
519   if err:
520     proc.stderr.read()
521     proc.stderr.close()
522   if proc.wait() != 0:
523     raise CloneFailure()
524
525 def _DownloadBundle(url, local, quiet):
526   if not url.endswith('/'):
527     url += '/'
528   url += 'clone.bundle'
529
530   proc = subprocess.Popen(
531     [GIT, 'config', '--get-regexp', 'url.*.insteadof'],
532     cwd = local,
533     stdout = subprocess.PIPE)
534   for line in proc.stdout:
535     m = re.compile(r'^url\.(.*)\.insteadof (.*)$').match(line)
536     if m:
537       new_url = m.group(1)
538       old_url = m.group(2)
539       if url.startswith(old_url):
540         url = new_url + url[len(old_url):]
541         break
542   proc.stdout.close()
543   proc.wait()
544
545   if not url.startswith('http:') and not url.startswith('https:'):
546     return False
547
548   dest = open(os.path.join(local, '.git', 'clone.bundle'), 'w+b')
549   try:
550     try:
551       r = urllib.request.urlopen(url)
552     except urllib.error.HTTPError as e:
553       if e.code in [403, 404]:
554         return False
555       _print('fatal: Cannot get %s' % url, file=sys.stderr)
556       _print('fatal: HTTP error %s' % e.code, file=sys.stderr)
557       raise CloneFailure()
558     except urllib.error.URLError as e:
559       _print('fatal: Cannot get %s' % url, file=sys.stderr)
560       _print('fatal: error %s' % e.reason, file=sys.stderr)
561       raise CloneFailure()
562     try:
563       if not quiet:
564         _print('Get %s' % url, file=sys.stderr)
565       while True:
566         buf = r.read(8192)
567         if buf == '':
568           return True
569         dest.write(buf)
570     finally:
571       r.close()
572   finally:
573     dest.close()
574
575 def _ImportBundle(local):
576   path = os.path.join(local, '.git', 'clone.bundle')
577   try:
578     _Fetch(local, local, path, True)
579   finally:
580     os.remove(path)
581
582 def _Clone(url, local, quiet):
583   """Clones a git repository to a new subdirectory of repodir
584   """
585   try:
586     os.mkdir(local)
587   except OSError as e:
588     _print('fatal: cannot make %s directory: %s' % (local, e.strerror),
589            file=sys.stderr)
590     raise CloneFailure()
591
592   cmd = [GIT, 'init', '--quiet']
593   try:
594     proc = subprocess.Popen(cmd, cwd = local)
595   except OSError as e:
596     _print(file=sys.stderr)
597     _print("fatal: '%s' is not available" % GIT, file=sys.stderr)
598     _print('fatal: %s' % e, file=sys.stderr)
599     _print(file=sys.stderr)
600     _print('Please make sure %s is installed and in your path.' % GIT,
601           file=sys.stderr)
602     raise CloneFailure()
603   if proc.wait() != 0:
604     _print('fatal: could not create %s' % local, file=sys.stderr)
605     raise CloneFailure()
606
607   _InitHttp()
608   _SetConfig(local, 'remote.origin.url', url)
609   _SetConfig(local, 'remote.origin.fetch',
610                     '+refs/heads/*:refs/remotes/origin/*')
611   if _DownloadBundle(url, local, quiet):
612     _ImportBundle(local)
613   else:
614     _Fetch(url, local, 'origin', quiet)
615
616
617 def _Verify(cwd, branch, quiet):
618   """Verify the branch has been signed by a tag.
619   """
620   cmd = [GIT, 'describe', 'origin/%s' % branch]
621   proc = subprocess.Popen(cmd,
622                           stdout=subprocess.PIPE,
623                           stderr=subprocess.PIPE,
624                           cwd = cwd)
625   cur = proc.stdout.read().strip()
626   proc.stdout.close()
627
628   proc.stderr.read()
629   proc.stderr.close()
630
631   if proc.wait() != 0 or not cur:
632     _print(file=sys.stderr)
633     _print("fatal: branch '%s' has not been signed" % branch, file=sys.stderr)
634     raise CloneFailure()
635
636   m = re.compile(r'^(.*)-[0-9]{1,}-g[0-9a-f]{1,}$').match(cur)
637   if m:
638     cur = m.group(1)
639     if not quiet:
640       _print(file=sys.stderr)
641       _print("info: Ignoring branch '%s'; using tagged release '%s'"
642             % (branch, cur), file=sys.stderr)
643       _print(file=sys.stderr)
644
645   env = os.environ.copy()
646   env['GNUPGHOME'] = gpg_dir.encode()
647
648   cmd = [GIT, 'tag', '-v', cur]
649   proc = subprocess.Popen(cmd,
650                           stdout = subprocess.PIPE,
651                           stderr = subprocess.PIPE,
652                           cwd = cwd,
653                           env = env)
654   out = proc.stdout.read()
655   proc.stdout.close()
656
657   err = proc.stderr.read()
658   proc.stderr.close()
659
660   if proc.wait() != 0:
661     _print(file=sys.stderr)
662     _print(out, file=sys.stderr)
663     _print(err, file=sys.stderr)
664     _print(file=sys.stderr)
665     raise CloneFailure()
666   return '%s^0' % cur
667
668
669 def _Checkout(cwd, branch, rev, quiet):
670   """Checkout an upstream branch into the repository and track it.
671   """
672   cmd = [GIT, 'update-ref', 'refs/heads/default', rev]
673   if subprocess.Popen(cmd, cwd = cwd).wait() != 0:
674     raise CloneFailure()
675
676   _SetConfig(cwd, 'branch.default.remote', 'origin')
677   _SetConfig(cwd, 'branch.default.merge', 'refs/heads/%s' % branch)
678
679   cmd = [GIT, 'symbolic-ref', 'HEAD', 'refs/heads/default']
680   if subprocess.Popen(cmd, cwd = cwd).wait() != 0:
681     raise CloneFailure()
682
683   cmd = [GIT, 'read-tree', '--reset', '-u']
684   if not quiet:
685     cmd.append('-v')
686   cmd.append('HEAD')
687   if subprocess.Popen(cmd, cwd = cwd).wait() != 0:
688     raise CloneFailure()
689
690
691 def _FindRepo():
692   """Look for a repo installation, starting at the current directory.
693   """
694   curdir = os.getcwd()
695   repo = None
696
697   olddir = None
698   while curdir != '/' \
699     and curdir != olddir \
700     and not repo:
701     repo = os.path.join(curdir, repodir, REPO_MAIN)
702     if not os.path.isfile(repo):
703       repo = None
704       olddir = curdir
705       curdir = os.path.dirname(curdir)
706   return (repo, os.path.join(curdir, repodir))
707
708
709 class _Options:
710   help = False
711
712
713 def _ParseArguments(args):
714   cmd = None
715   opt = _Options()
716   arg = []
717
718   for i in range(len(args)):
719     a = args[i]
720     if a == '-h' or a == '--help':
721       opt.help = True
722
723     elif not a.startswith('-'):
724       cmd = a
725       arg = args[i + 1:]
726       break
727   return cmd, opt, arg
728
729
730 def _Usage():
731   _print(
732 """usage: repo COMMAND [ARGS]
733
734 repo is not yet installed.  Use "repo init" to install it here.
735
736 The most commonly used repo commands are:
737
738   init      Install repo in the current working directory
739   help      Display detailed help on a command
740
741 For access to the full online help, install repo ("repo init").
742 """, file=sys.stderr)
743   sys.exit(1)
744
745
746 def _Help(args):
747   if args:
748     if args[0] == 'init':
749       init_optparse.print_help()
750       sys.exit(0)
751     else:
752       _print("error: '%s' is not a bootstrap command.\n"
753              '        For access to online help, install repo ("repo init").'
754              % args[0], file=sys.stderr)
755   else:
756     _Usage()
757   sys.exit(1)
758
759
760 def _NotInstalled():
761   _print('error: repo is not installed.  Use "repo init" to install it here.',
762          file=sys.stderr)
763   sys.exit(1)
764
765
766 def _NoCommands(cmd):
767   _print("""error: command '%s' requires repo to be installed first.
768          Use "repo init" to install it here.""" % cmd, file=sys.stderr)
769   sys.exit(1)
770
771
772 def _RunSelf(wrapper_path):
773   my_dir = os.path.dirname(wrapper_path)
774   my_main = os.path.join(my_dir, 'main.py')
775   my_git = os.path.join(my_dir, '.git')
776
777   if os.path.isfile(my_main) and os.path.isdir(my_git):
778     for name in ['git_config.py',
779                  'project.py',
780                  'subcmds']:
781       if not os.path.exists(os.path.join(my_dir, name)):
782         return None, None
783     return my_main, my_git
784   return None, None
785
786
787 def _SetDefaultsTo(gitdir):
788   global REPO_URL
789   global REPO_REV
790
791   REPO_URL = gitdir
792   proc = subprocess.Popen([GIT,
793                            '--git-dir=%s' % gitdir,
794                            'symbolic-ref',
795                            'HEAD'],
796                           stdout = subprocess.PIPE,
797                           stderr = subprocess.PIPE)
798   REPO_REV = proc.stdout.read().strip()
799   proc.stdout.close()
800
801   proc.stderr.read()
802   proc.stderr.close()
803
804   if proc.wait() != 0:
805     _print('fatal: %s has no current branch' % gitdir, file=sys.stderr)
806     sys.exit(1)
807
808
809 def main(orig_args):
810   repo_main, rel_repo_dir = _FindRepo()
811   cmd, opt, args = _ParseArguments(orig_args)
812
813   wrapper_path = os.path.abspath(__file__)
814   my_main, my_git = _RunSelf(wrapper_path)
815
816   if not repo_main:
817     if opt.help:
818       _Usage()
819     if cmd == 'help':
820       _Help(args)
821     if not cmd:
822       _NotInstalled()
823     if cmd == 'init':
824       if my_git:
825         _SetDefaultsTo(my_git)
826       try:
827         _Init(args)
828       except CloneFailure:
829         for root, dirs, files in os.walk(repodir, topdown=False):
830           for name in files:
831             os.remove(os.path.join(root, name))
832           for name in dirs:
833             os.rmdir(os.path.join(root, name))
834         os.rmdir(repodir)
835         sys.exit(1)
836       repo_main, rel_repo_dir = _FindRepo()
837     else:
838       _NoCommands(cmd)
839
840   if cmd == 'sync' and NeedSetupGnuPG():
841     SetupGnuPG(False)
842
843   if my_main:
844     repo_main = my_main
845
846   ver_str = '.'.join(map(str, VERSION))
847   me = [sys.executable, repo_main,
848         '--repo-dir=%s' % rel_repo_dir,
849         '--wrapper-version=%s' % ver_str,
850         '--wrapper-path=%s' % wrapper_path,
851         '--']
852   me.extend(orig_args)
853   me.extend(extra_args)
854   try:
855     os.execv(sys.executable, me)
856   except OSError as e:
857     _print("fatal: unable to start %s" % repo_main, file=sys.stderr)
858     _print("fatal: %s" % e, file=sys.stderr)
859     sys.exit(148)
860
861
862 if __name__ == '__main__':
863   main(sys.argv[1:])