Back to home page

Android Cross Reference

 
 

    


0001 #!/usr/bin/env python
0002 
0003 ## repo default configuration
0004 ##
0005 from __future__ import print_function
0006 REPO_URL = 'https://gerrit.googlesource.com/git-repo'
0007 REPO_REV = 'stable'
0008 
0009 # Copyright (C) 2008 Google Inc.
0010 #
0011 # Licensed under the Apache License, Version 2.0 (the "License");
0012 # you may not use this file except in compliance with the License.
0013 # You may obtain a copy of the License at
0014 #
0015 #      http://www.apache.org/licenses/LICENSE-2.0
0016 #
0017 # Unless required by applicable law or agreed to in writing, software
0018 # distributed under the License is distributed on an "AS IS" BASIS,
0019 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0020 # See the License for the specific language governing permissions and
0021 # limitations under the License.
0022 
0023 # increment this whenever we make important changes to this script
0024 VERSION = (1, 19)
0025 
0026 # increment this if the MAINTAINER_KEYS block is modified
0027 KEYRING_VERSION = (1, 1)
0028 MAINTAINER_KEYS = """
0029 
0030      Repo Maintainer <repo@android.kernel.org>
0031 -----BEGIN PGP PUBLIC KEY BLOCK-----
0032 Version: GnuPG v1.4.2.2 (GNU/Linux)
0033 
0034 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
0069 =CMiZ
0070 -----END PGP PUBLIC KEY BLOCK-----
0071 
0072      Conley Owens <cco3@android.com>
0073 -----BEGIN PGP PUBLIC KEY BLOCK-----
0074 Version: GnuPG v1.4.11 (GNU/Linux)
0075 
0076 mQENBFBiLPwBCACvISTASOgFXwADw2GYRH2I2z9RvYkYoZ6ThTTNlMXbbYYKO2Wo
0077 a9LQDNW0TbCEekg5UKk0FD13XOdWaqUt4Gtuvq9c43GRSjMO6NXH+0BjcQ8vUtY2
0078 /W4CYUevwdo4nQ1+1zsOCu1XYe/CReXq0fdugv3hgmRmh3sz1soo37Q44W2frxxg
0079 U7Rz3Da4FjgAL0RQ8qndD+LwRHXTY7H7wYM8V/3cYFZV7pSodd75q3MAXYQLf0ZV
0080 QR1XATu5l1QnXrxgHvz7MmDwb1D+jX3YPKnZveaukigQ6hDHdiVcePBiGXmk8LZC
0081 2jQkdXeF7Su1ZYpr2nnEHLJ6vOLcCpPGb8gDABEBAAG0H0NvbmxleSBPd2VucyA8
0082 Y2NvM0BhbmRyb2lkLmNvbT6JATgEEwECACIFAlBiLPwCGwMGCwkIBwMCBhUIAgkK
0083 CwQWAgMBAh4BAheAAAoJEBkmlFUziHGkHVkH/2Hks2Cif5i2xPtv2IFZcjL42joU
0084 T7lO5XFqUYS9ZNHpGa/V0eiPt7rHoO16glR83NZtwlrq2cSN89i9HfOhMYV/qLu8
0085 fLCHcV2muw+yCB5s5bxnI5UkToiNZyBNqFkcOt/Kbj9Hpy68A1kmc6myVEaUYebq
0086 2Chx/f3xuEthan099t746v1K+/6SvQGDNctHuaMr9cWdxZtHjdRf31SQRc99Phe5
0087 w+ZGR/ebxNDKRK9mKgZT8wVFHlXerJsRqWIqtx1fsW1UgLgbpcpe2MChm6B5wTu0
0088 s1ltzox3l4q71FyRRPUJxXyvGkDLZWpK7EpiHSCOYq/KP3HkKeXU3xqHpcG5AQ0E
0089 UGIs/AEIAKzO/7lO9cB6dshmZYo8Vy/b7aGicThE+ChcDSfhvyOXVdEM2GKAjsR+
0090 rlBWbTFX3It301p2HwZPFEi9nEvJxVlqqBiW0bPmNMkDRR55l2vbWg35wwkg6RyE
0091 Bc5/TQjhXI2w8IvlimoGoUff4t3JmMOnWrnKSvL+5iuRj12p9WmanCHzw3Ee7ztf
0092 /aU/q+FTpr3DLerb6S8xbv86ySgnJT6o5CyL2DCWRtnYQyGVi0ZmLzEouAYiO0hs
0093 z0AAu28Mj+12g2WwePRz6gfM9rHtI37ylYW3oT/9M9mO9ei/Bc/1D7Dz6qNV+0vg
0094 uSVJxM2Bl6GalHPZLhHntFEdIA6EdoUAEQEAAYkBHwQYAQIACQUCUGIs/AIbDAAK
0095 CRAZJpRVM4hxpNfkB/0W/hP5WK/NETXBlWXXW7JPaWO2c5kGwD0lnj5RRmridyo1
0096 vbm5PdM91jOsDQYqRu6YOoYBnDnEhB2wL2bPh34HWwwrA+LwB8hlcAV2z1bdwyfl
0097 3R823fReKN3QcvLHzmvZPrF4Rk97M9UIyKS0RtnfTWykRgDWHIsrtQPoNwsXrWoT
0098 9LrM2v+1+9mp3vuXnE473/NHxmiWEQH9Ez+O/mOxQ7rSOlqGRiKq/IBZCfioJOtV
0099 fTQeIu/yASZnsLBqr6SJEGwYBoWcyjG++k4fyw8ocOAo4uGDYbxgN7yYfNQ0OH7o
0100 V6pfUgqKLWa/aK7/N1ZHnPdFLD8Xt0Dmy4BPwrKC
0101 =O7am
0102 -----END PGP PUBLIC KEY BLOCK-----
0103 """
0104 
0105 GIT = 'git'                     # our git command
0106 MIN_GIT_VERSION = (1, 7, 2)     # minimum supported git version
0107 repodir = '.repo'               # name of repo's private directory
0108 S_repo = 'repo'                 # special repo repository
0109 S_manifests = 'manifests'       # special manifest repository
0110 REPO_MAIN = S_repo + '/main.py' # main script
0111 
0112 
0113 import optparse
0114 import os
0115 import re
0116 import stat
0117 import subprocess
0118 import sys
0119 try:
0120   import urllib2
0121 except ImportError:
0122   # For python3
0123   import urllib.request
0124   import urllib.error
0125 else:
0126   # For python2
0127   import imp
0128   urllib = imp.new_module('urllib')
0129   urllib.request = urllib2
0130   urllib.error = urllib2
0131 
0132 home_dot_repo = os.path.expanduser('~/.repoconfig')
0133 gpg_dir = os.path.join(home_dot_repo, 'gnupg')
0134 
0135 extra_args = []
0136 init_optparse = optparse.OptionParser(usage="repo init -u url [options]")
0137 
0138 # Logging
0139 group = init_optparse.add_option_group('Logging options')
0140 group.add_option('-q', '--quiet',
0141                  dest="quiet", action="store_true", default=False,
0142                  help="be quiet")
0143 
0144 # Manifest
0145 group = init_optparse.add_option_group('Manifest options')
0146 group.add_option('-u', '--manifest-url',
0147                  dest='manifest_url',
0148                  help='manifest repository location', metavar='URL')
0149 group.add_option('-b', '--manifest-branch',
0150                  dest='manifest_branch',
0151                  help='manifest branch or revision', metavar='REVISION')
0152 group.add_option('-m', '--manifest-name',
0153                  dest='manifest_name',
0154                  help='initial manifest file', metavar='NAME.xml')
0155 group.add_option('--mirror',
0156                  dest='mirror', action='store_true',
0157                  help='create a replica of the remote repositories '
0158                       'rather than a client working directory')
0159 group.add_option('--reference',
0160                  dest='reference',
0161                  help='location of mirror directory', metavar='DIR')
0162 group.add_option('--depth', type='int', default=None,
0163                  dest='depth',
0164                  help='create a shallow clone with given depth; see git clone')
0165 group.add_option('-g', '--groups',
0166                  dest='groups', default='default',
0167                  help='restrict manifest projects to ones with a specified group',
0168                  metavar='GROUP')
0169 group.add_option('-p', '--platform',
0170                  dest='platform', default="auto",
0171                  help='restrict manifest projects to ones with a specified '
0172                       'platform group [auto|all|none|linux|darwin|...]',
0173                  metavar='PLATFORM')
0174 
0175 
0176 # Tool
0177 group = init_optparse.add_option_group('repo Version options')
0178 group.add_option('--repo-url',
0179                  dest='repo_url',
0180                  help='repo repository location', metavar='URL')
0181 group.add_option('--repo-branch',
0182                  dest='repo_branch',
0183                  help='repo branch or revision', metavar='REVISION')
0184 group.add_option('--no-repo-verify',
0185                  dest='no_repo_verify', action='store_true',
0186                  help='do not verify repo source code')
0187 
0188 # Other
0189 group = init_optparse.add_option_group('Other options')
0190 group.add_option('--config-name',
0191                  dest='config_name', action="store_true", default=False,
0192                  help='Always prompt for name/e-mail')
0193 
0194 class CloneFailure(Exception):
0195   """Indicate the remote clone of repo itself failed.
0196   """
0197 
0198 
0199 def _Init(args):
0200   """Installs repo by cloning it over the network.
0201   """
0202   opt, args = init_optparse.parse_args(args)
0203   if args:
0204     init_optparse.print_usage()
0205     sys.exit(1)
0206 
0207   url = opt.repo_url
0208   if not url:
0209     url = REPO_URL
0210     extra_args.append('--repo-url=%s' % url)
0211 
0212   branch = opt.repo_branch
0213   if not branch:
0214     branch = REPO_REV
0215     extra_args.append('--repo-branch=%s' % branch)
0216 
0217   if branch.startswith('refs/heads/'):
0218     branch = branch[len('refs/heads/'):]
0219   if branch.startswith('refs/'):
0220     print("fatal: invalid branch name '%s'" % branch, file=sys.stderr)
0221     raise CloneFailure()
0222 
0223   if not os.path.isdir(repodir):
0224     try:
0225       os.mkdir(repodir)
0226     except OSError as e:
0227       print('fatal: cannot make %s directory: %s'
0228             % (repodir, e.strerror), file=sys.stderr)
0229       # Don't raise CloneFailure; that would delete the
0230       # name. Instead exit immediately.
0231       #
0232       sys.exit(1)
0233 
0234   _CheckGitVersion()
0235   try:
0236     if NeedSetupGnuPG():
0237       can_verify = SetupGnuPG(opt.quiet)
0238     else:
0239       can_verify = True
0240 
0241     dst = os.path.abspath(os.path.join(repodir, S_repo))
0242     _Clone(url, dst, opt.quiet)
0243 
0244     if can_verify and not opt.no_repo_verify:
0245       rev = _Verify(dst, branch, opt.quiet)
0246     else:
0247       rev = 'refs/remotes/origin/%s^0' % branch
0248 
0249     _Checkout(dst, branch, rev, opt.quiet)
0250   except CloneFailure:
0251     if opt.quiet:
0252       print('fatal: repo init failed; run without --quiet to see why',
0253             file=sys.stderr)
0254     raise
0255 
0256 
0257 def _CheckGitVersion():
0258   cmd = [GIT, '--version']
0259   try:
0260     proc = subprocess.Popen(cmd, stdout=subprocess.PIPE)
0261   except OSError as e:
0262     print(file=sys.stderr)
0263     print("fatal: '%s' is not available" % GIT, file=sys.stderr)
0264     print('fatal: %s' % e, file=sys.stderr)
0265     print(file=sys.stderr)
0266     print('Please make sure %s is installed and in your path.' % GIT,
0267           file=sys.stderr)
0268     raise CloneFailure()
0269 
0270   ver_str = proc.stdout.read().strip()
0271   proc.stdout.close()
0272   proc.wait()
0273 
0274   if not ver_str.startswith('git version '):
0275     print('error: "%s" unsupported' % ver_str, file=sys.stderr)
0276     raise CloneFailure()
0277 
0278   ver_str = ver_str[len('git version '):].strip()
0279   ver_act = tuple(map(int, ver_str.split('.')[0:3]))
0280   if ver_act < MIN_GIT_VERSION:
0281     need = '.'.join(map(str, MIN_GIT_VERSION))
0282     print('fatal: git %s or later required' % need, file=sys.stderr)
0283     raise CloneFailure()
0284 
0285 
0286 def NeedSetupGnuPG():
0287   if not os.path.isdir(home_dot_repo):
0288     return True
0289 
0290   kv = os.path.join(home_dot_repo, 'keyring-version')
0291   if not os.path.exists(kv):
0292     return True
0293 
0294   kv = open(kv).read()
0295   if not kv:
0296     return True
0297 
0298   kv = tuple(map(int, kv.split('.')))
0299   if kv < KEYRING_VERSION:
0300     return True
0301   return False
0302 
0303 
0304 def SetupGnuPG(quiet):
0305   if not os.path.isdir(home_dot_repo):
0306     try:
0307       os.mkdir(home_dot_repo)
0308     except OSError as e:
0309       print('fatal: cannot make %s directory: %s'
0310             % (home_dot_repo, e.strerror), file=sys.stderr)
0311       sys.exit(1)
0312 
0313   if not os.path.isdir(gpg_dir):
0314     try:
0315       os.mkdir(gpg_dir, stat.S_IRWXU)
0316     except OSError as e:
0317       print('fatal: cannot make %s directory: %s' % (gpg_dir, e.strerror),
0318             file=sys.stderr)
0319       sys.exit(1)
0320 
0321   env = os.environ.copy()
0322   env['GNUPGHOME'] = gpg_dir.encode()
0323 
0324   cmd = ['gpg', '--import']
0325   try:
0326     proc = subprocess.Popen(cmd,
0327                             env = env,
0328                             stdin = subprocess.PIPE)
0329   except OSError as e:
0330     if not quiet:
0331       print('warning: gpg (GnuPG) is not available.', file=sys.stderr)
0332       print('warning: Installing it is strongly encouraged.', file=sys.stderr)
0333       print(file=sys.stderr)
0334     return False
0335 
0336   proc.stdin.write(MAINTAINER_KEYS)
0337   proc.stdin.close()
0338 
0339   if proc.wait() != 0:
0340     print('fatal: registering repo maintainer keys failed', file=sys.stderr)
0341     sys.exit(1)
0342   print()
0343 
0344   fd = open(os.path.join(home_dot_repo, 'keyring-version'), 'w')
0345   fd.write('.'.join(map(str, KEYRING_VERSION)) + '\n')
0346   fd.close()
0347   return True
0348 
0349 
0350 def _SetConfig(local, name, value):
0351   """Set a git configuration option to the specified value.
0352   """
0353   cmd = [GIT, 'config', name, value]
0354   if subprocess.Popen(cmd, cwd = local).wait() != 0:
0355     raise CloneFailure()
0356 
0357 
0358 def _InitHttp():
0359   handlers = []
0360 
0361   mgr = urllib.request.HTTPPasswordMgrWithDefaultRealm()
0362   try:
0363     import netrc
0364     n = netrc.netrc()
0365     for host in n.hosts:
0366       p = n.hosts[host]
0367       mgr.add_password(p[1], 'http://%s/'  % host, p[0], p[2])
0368       mgr.add_password(p[1], 'https://%s/' % host, p[0], p[2])
0369   except:
0370     pass
0371   handlers.append(urllib.request.HTTPBasicAuthHandler(mgr))
0372   handlers.append(urllib.request.HTTPDigestAuthHandler(mgr))
0373 
0374   if 'http_proxy' in os.environ:
0375     url = os.environ['http_proxy']
0376     handlers.append(urllib.request.ProxyHandler({'http': url, 'https': url}))
0377   if 'REPO_CURL_VERBOSE' in os.environ:
0378     handlers.append(urllib.request.HTTPHandler(debuglevel=1))
0379     handlers.append(urllib.request.HTTPSHandler(debuglevel=1))
0380   urllib.request.install_opener(urllib.request.build_opener(*handlers))
0381 
0382 def _Fetch(url, local, src, quiet):
0383   if not quiet:
0384     print('Get %s' % url, file=sys.stderr)
0385 
0386   cmd = [GIT, 'fetch']
0387   if quiet:
0388     cmd.append('--quiet')
0389     err = subprocess.PIPE
0390   else:
0391     err = None
0392   cmd.append(src)
0393   cmd.append('+refs/heads/*:refs/remotes/origin/*')
0394   cmd.append('refs/tags/*:refs/tags/*')
0395 
0396   proc = subprocess.Popen(cmd, cwd = local, stderr = err)
0397   if err:
0398     proc.stderr.read()
0399     proc.stderr.close()
0400   if proc.wait() != 0:
0401     raise CloneFailure()
0402 
0403 def _DownloadBundle(url, local, quiet):
0404   if not url.endswith('/'):
0405     url += '/'
0406   url += 'clone.bundle'
0407 
0408   proc = subprocess.Popen(
0409     [GIT, 'config', '--get-regexp', 'url.*.insteadof'],
0410     cwd = local,
0411     stdout = subprocess.PIPE)
0412   for line in proc.stdout:
0413     m = re.compile(r'^url\.(.*)\.insteadof (.*)$').match(line)
0414     if m:
0415       new_url = m.group(1)
0416       old_url = m.group(2)
0417       if url.startswith(old_url):
0418         url = new_url + url[len(old_url):]
0419         break
0420   proc.stdout.close()
0421   proc.wait()
0422 
0423   if not url.startswith('http:') and not url.startswith('https:'):
0424     return False
0425 
0426   dest = open(os.path.join(local, '.git', 'clone.bundle'), 'w+b')
0427   try:
0428     try:
0429       r = urllib.request.urlopen(url)
0430     except urllib.error.HTTPError as e:
0431       if e.code in [403, 404]:
0432         return False
0433       print('fatal: Cannot get %s' % url, file=sys.stderr)
0434       print('fatal: HTTP error %s' % e.code, file=sys.stderr)
0435       raise CloneFailure()
0436     except urllib.error.URLError as e:
0437       print('fatal: Cannot get %s' % url, file=sys.stderr)
0438       print('fatal: error %s' % e.reason, file=sys.stderr)
0439       raise CloneFailure()
0440     try:
0441       if not quiet:
0442         print('Get %s' % url, file=sys.stderr)
0443       while True:
0444         buf = r.read(8192)
0445         if buf == '':
0446           return True
0447         dest.write(buf)
0448     finally:
0449       r.close()
0450   finally:
0451     dest.close()
0452 
0453 def _ImportBundle(local):
0454   path = os.path.join(local, '.git', 'clone.bundle')
0455   try:
0456     _Fetch(local, local, path, True)
0457   finally:
0458     os.remove(path)
0459 
0460 def _Clone(url, local, quiet):
0461   """Clones a git repository to a new subdirectory of repodir
0462   """
0463   try:
0464     os.mkdir(local)
0465   except OSError as e:
0466     print('fatal: cannot make %s directory: %s' % (local, e.strerror),
0467           file=sys.stderr)
0468     raise CloneFailure()
0469 
0470   cmd = [GIT, 'init', '--quiet']
0471   try:
0472     proc = subprocess.Popen(cmd, cwd = local)
0473   except OSError as e:
0474     print(file=sys.stderr)
0475     print("fatal: '%s' is not available" % GIT, file=sys.stderr)
0476     print('fatal: %s' % e, file=sys.stderr)
0477     print(file=sys.stderr)
0478     print('Please make sure %s is installed and in your path.' % GIT,
0479           file=sys.stderr)
0480     raise CloneFailure()
0481   if proc.wait() != 0:
0482     print('fatal: could not create %s' % local, file=sys.stderr)
0483     raise CloneFailure()
0484 
0485   _InitHttp()
0486   _SetConfig(local, 'remote.origin.url', url)
0487   _SetConfig(local, 'remote.origin.fetch',
0488                     '+refs/heads/*:refs/remotes/origin/*')
0489   if _DownloadBundle(url, local, quiet):
0490     _ImportBundle(local)
0491   else:
0492     _Fetch(url, local, 'origin', quiet)
0493 
0494 
0495 def _Verify(cwd, branch, quiet):
0496   """Verify the branch has been signed by a tag.
0497   """
0498   cmd = [GIT, 'describe', 'origin/%s' % branch]
0499   proc = subprocess.Popen(cmd,
0500                           stdout=subprocess.PIPE,
0501                           stderr=subprocess.PIPE,
0502                           cwd = cwd)
0503   cur = proc.stdout.read().strip()
0504   proc.stdout.close()
0505 
0506   proc.stderr.read()
0507   proc.stderr.close()
0508 
0509   if proc.wait() != 0 or not cur:
0510     print(file=sys.stderr)
0511     print("fatal: branch '%s' has not been signed" % branch, file=sys.stderr)
0512     raise CloneFailure()
0513 
0514   m = re.compile(r'^(.*)-[0-9]{1,}-g[0-9a-f]{1,}$').match(cur)
0515   if m:
0516     cur = m.group(1)
0517     if not quiet:
0518       print(file=sys.stderr)
0519       print("info: Ignoring branch '%s'; using tagged release '%s'"
0520             % (branch, cur), file=sys.stderr)
0521       print(file=sys.stderr)
0522 
0523   env = os.environ.copy()
0524   env['GNUPGHOME'] = gpg_dir.encode()
0525 
0526   cmd = [GIT, 'tag', '-v', cur]
0527   proc = subprocess.Popen(cmd,
0528                           stdout = subprocess.PIPE,
0529                           stderr = subprocess.PIPE,
0530                           cwd = cwd,
0531                           env = env)
0532   out = proc.stdout.read()
0533   proc.stdout.close()
0534 
0535   err = proc.stderr.read()
0536   proc.stderr.close()
0537 
0538   if proc.wait() != 0:
0539     print(file=sys.stderr)
0540     print(out, file=sys.stderr)
0541     print(err, file=sys.stderr)
0542     print(file=sys.stderr)
0543     raise CloneFailure()
0544   return '%s^0' % cur
0545 
0546 
0547 def _Checkout(cwd, branch, rev, quiet):
0548   """Checkout an upstream branch into the repository and track it.
0549   """
0550   cmd = [GIT, 'update-ref', 'refs/heads/default', rev]
0551   if subprocess.Popen(cmd, cwd = cwd).wait() != 0:
0552     raise CloneFailure()
0553 
0554   _SetConfig(cwd, 'branch.default.remote', 'origin')
0555   _SetConfig(cwd, 'branch.default.merge', 'refs/heads/%s' % branch)
0556 
0557   cmd = [GIT, 'symbolic-ref', 'HEAD', 'refs/heads/default']
0558   if subprocess.Popen(cmd, cwd = cwd).wait() != 0:
0559     raise CloneFailure()
0560 
0561   cmd = [GIT, 'read-tree', '--reset', '-u']
0562   if not quiet:
0563     cmd.append('-v')
0564   cmd.append('HEAD')
0565   if subprocess.Popen(cmd, cwd = cwd).wait() != 0:
0566     raise CloneFailure()
0567 
0568 
0569 def _FindRepo():
0570   """Look for a repo installation, starting at the current directory.
0571   """
0572   curdir = os.getcwd()
0573   repo = None
0574 
0575   olddir = None
0576   while curdir != '/' \
0577     and curdir != olddir \
0578     and not repo:
0579     repo = os.path.join(curdir, repodir, REPO_MAIN)
0580     if not os.path.isfile(repo):
0581       repo = None
0582       olddir = curdir
0583       curdir = os.path.dirname(curdir)
0584   return (repo, os.path.join(curdir, repodir))
0585 
0586 
0587 class _Options:
0588   help = False
0589 
0590 
0591 def _ParseArguments(args):
0592   cmd = None
0593   opt = _Options()
0594   arg = []
0595 
0596   for i in range(len(args)):
0597     a = args[i]
0598     if a == '-h' or a == '--help':
0599       opt.help = True
0600 
0601     elif not a.startswith('-'):
0602       cmd = a
0603       arg = args[i + 1:]
0604       break
0605   return cmd, opt, arg
0606 
0607 
0608 def _Usage():
0609   print(
0610 """usage: repo COMMAND [ARGS]
0611 
0612 repo is not yet installed.  Use "repo init" to install it here.
0613 
0614 The most commonly used repo commands are:
0615 
0616   init      Install repo in the current working directory
0617   help      Display detailed help on a command
0618 
0619 For access to the full online help, install repo ("repo init").
0620 """, file=sys.stderr)
0621   sys.exit(1)
0622 
0623 
0624 def _Help(args):
0625   if args:
0626     if args[0] == 'init':
0627       init_optparse.print_help()
0628       sys.exit(0)
0629     else:
0630       print("error: '%s' is not a bootstrap command.\n"
0631             '        For access to online help, install repo ("repo init").'
0632             % args[0], file=sys.stderr)
0633   else:
0634     _Usage()
0635   sys.exit(1)
0636 
0637 
0638 def _NotInstalled():
0639   print('error: repo is not installed.  Use "repo init" to install it here.',
0640         file=sys.stderr)
0641   sys.exit(1)
0642 
0643 
0644 def _NoCommands(cmd):
0645   print("""error: command '%s' requires repo to be installed first.
0646         Use "repo init" to install it here.""" % cmd, file=sys.stderr)
0647   sys.exit(1)
0648 
0649 
0650 def _RunSelf(wrapper_path):
0651   my_dir = os.path.dirname(wrapper_path)
0652   my_main = os.path.join(my_dir, 'main.py')
0653   my_git = os.path.join(my_dir, '.git')
0654 
0655   if os.path.isfile(my_main) and os.path.isdir(my_git):
0656     for name in ['git_config.py',
0657                  'project.py',
0658                  'subcmds']:
0659       if not os.path.exists(os.path.join(my_dir, name)):
0660         return None, None
0661     return my_main, my_git
0662   return None, None
0663 
0664 
0665 def _SetDefaultsTo(gitdir):
0666   global REPO_URL
0667   global REPO_REV
0668 
0669   REPO_URL = gitdir
0670   proc = subprocess.Popen([GIT,
0671                            '--git-dir=%s' % gitdir,
0672                            'symbolic-ref',
0673                            'HEAD'],
0674                           stdout = subprocess.PIPE,
0675                           stderr = subprocess.PIPE)
0676   REPO_REV = proc.stdout.read().strip()
0677   proc.stdout.close()
0678 
0679   proc.stderr.read()
0680   proc.stderr.close()
0681 
0682   if proc.wait() != 0:
0683     print('fatal: %s has no current branch' % gitdir, file=sys.stderr)
0684     sys.exit(1)
0685 
0686 
0687 def main(orig_args):
0688   repo_main, rel_repo_dir = _FindRepo()
0689   cmd, opt, args = _ParseArguments(orig_args)
0690 
0691   wrapper_path = os.path.abspath(__file__)
0692   my_main, my_git = _RunSelf(wrapper_path)
0693 
0694   if not repo_main:
0695     if opt.help:
0696       _Usage()
0697     if cmd == 'help':
0698       _Help(args)
0699     if not cmd:
0700       _NotInstalled()
0701     if cmd == 'init':
0702       if my_git:
0703         _SetDefaultsTo(my_git)
0704       try:
0705         _Init(args)
0706       except CloneFailure:
0707         for root, dirs, files in os.walk(repodir, topdown=False):
0708           for name in files:
0709             os.remove(os.path.join(root, name))
0710           for name in dirs:
0711             os.rmdir(os.path.join(root, name))
0712         os.rmdir(repodir)
0713         sys.exit(1)
0714       repo_main, rel_repo_dir = _FindRepo()
0715     else:
0716       _NoCommands(cmd)
0717 
0718   if my_main:
0719     repo_main = my_main
0720 
0721   ver_str = '.'.join(map(str, VERSION))
0722   me = [repo_main,
0723         '--repo-dir=%s' % rel_repo_dir,
0724         '--wrapper-version=%s' % ver_str,
0725         '--wrapper-path=%s' % wrapper_path,
0726         '--']
0727   me.extend(orig_args)
0728   me.extend(extra_args)
0729   try:
0730     os.execv(repo_main, me)
0731   except OSError as e:
0732     print("fatal: unable to start %s" % repo_main, file=sys.stderr)
0733     print("fatal: %s" % e, file=sys.stderr)
0734     sys.exit(148)
0735 
0736 
0737 if __name__ == '__main__':
0738   main(sys.argv[1:])