2008-10-21 14:00:00 +00:00
|
|
|
#!/bin/sh
|
|
|
|
#
|
|
|
|
# Copyright (C) 2008 The Android Open Source Project
|
|
|
|
#
|
|
|
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
# you may not use this file except in compliance with the License.
|
|
|
|
# You may obtain a copy of the License at
|
|
|
|
#
|
|
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
#
|
|
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
|
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
# See the License for the specific language governing permissions and
|
|
|
|
# limitations under the License.
|
|
|
|
|
|
|
|
magic='--calling-python-from-/bin/sh--'
|
2008-10-21 14:11:36 +00:00
|
|
|
"""exec" python -E "$0" "$@" """#$magic"
|
2008-10-21 14:00:00 +00:00
|
|
|
if __name__ == '__main__':
|
|
|
|
import sys
|
|
|
|
if sys.argv[-1] == '#%s' % magic:
|
|
|
|
del sys.argv[-1]
|
|
|
|
del magic
|
|
|
|
|
2011-09-19 17:04:23 +00:00
|
|
|
import netrc
|
2008-10-21 14:00:00 +00:00
|
|
|
import optparse
|
|
|
|
import os
|
|
|
|
import re
|
|
|
|
import sys
|
2011-09-23 00:06:41 +00:00
|
|
|
import time
|
2011-09-11 19:57:15 +00:00
|
|
|
import urllib2
|
2008-10-21 14:00:00 +00:00
|
|
|
|
2009-04-18 16:54:51 +00:00
|
|
|
from trace import SetTrace
|
2011-09-19 15:05:31 +00:00
|
|
|
from git_command import git, GitCommand
|
2010-12-21 21:39:23 +00:00
|
|
|
from git_config import init_ssh, close_ssh
|
2009-03-04 01:47:06 +00:00
|
|
|
from command import InteractiveCommand
|
|
|
|
from command import MirrorSafeCommand
|
|
|
|
from command import PagedCommand
|
2011-11-29 23:01:33 +00:00
|
|
|
from subcmds.version import Version
|
2008-10-29 22:20:02 +00:00
|
|
|
from editor import Editor
|
2011-09-19 21:50:58 +00:00
|
|
|
from error import DownloadError
|
2009-03-02 20:56:08 +00:00
|
|
|
from error import ManifestInvalidRevisionError
|
2008-10-21 14:00:00 +00:00
|
|
|
from error import NoSuchProjectError
|
|
|
|
from error import RepoChangedException
|
2009-05-18 20:19:57 +00:00
|
|
|
from manifest_xml import XmlManifest
|
2008-10-21 14:00:00 +00:00
|
|
|
from pager import RunPager
|
|
|
|
|
|
|
|
from subcmds import all as all_commands
|
|
|
|
|
|
|
|
global_options = optparse.OptionParser(
|
|
|
|
usage="repo [-p|--paginate|--no-pager] COMMAND [ARGS]"
|
|
|
|
)
|
|
|
|
global_options.add_option('-p', '--paginate',
|
|
|
|
dest='pager', action='store_true',
|
|
|
|
help='display command output in the pager')
|
|
|
|
global_options.add_option('--no-pager',
|
|
|
|
dest='no_pager', action='store_true',
|
|
|
|
help='disable the pager')
|
2009-03-10 01:26:31 +00:00
|
|
|
global_options.add_option('--trace',
|
|
|
|
dest='trace', action='store_true',
|
|
|
|
help='trace git command execution')
|
2011-09-23 00:06:41 +00:00
|
|
|
global_options.add_option('--time',
|
|
|
|
dest='time', action='store_true',
|
|
|
|
help='time repo command execution')
|
2009-03-03 02:24:23 +00:00
|
|
|
global_options.add_option('--version',
|
|
|
|
dest='show_version', action='store_true',
|
|
|
|
help='display this version of repo')
|
2008-10-21 14:00:00 +00:00
|
|
|
|
|
|
|
class _Repo(object):
|
|
|
|
def __init__(self, repodir):
|
|
|
|
self.repodir = repodir
|
|
|
|
self.commands = all_commands
|
2009-07-14 19:23:39 +00:00
|
|
|
# add 'branch' as an alias for 'branches'
|
|
|
|
all_commands['branch'] = all_commands['branches']
|
2008-10-21 14:00:00 +00:00
|
|
|
|
|
|
|
def _Run(self, argv):
|
2011-04-29 13:59:12 +00:00
|
|
|
result = 0
|
2008-10-21 14:00:00 +00:00
|
|
|
name = None
|
|
|
|
glob = []
|
|
|
|
|
|
|
|
for i in xrange(0, len(argv)):
|
|
|
|
if not argv[i].startswith('-'):
|
|
|
|
name = argv[i]
|
|
|
|
if i > 0:
|
|
|
|
glob = argv[:i]
|
|
|
|
argv = argv[i + 1:]
|
|
|
|
break
|
|
|
|
if not name:
|
|
|
|
glob = argv
|
|
|
|
name = 'help'
|
|
|
|
argv = []
|
|
|
|
gopts, gargs = global_options.parse_args(glob)
|
|
|
|
|
2009-03-10 01:26:31 +00:00
|
|
|
if gopts.trace:
|
2009-04-18 16:54:51 +00:00
|
|
|
SetTrace()
|
2009-03-03 02:24:23 +00:00
|
|
|
if gopts.show_version:
|
|
|
|
if name == 'help':
|
|
|
|
name = 'version'
|
|
|
|
else:
|
|
|
|
print >>sys.stderr, 'fatal: invalid usage of --version'
|
2011-04-29 13:59:12 +00:00
|
|
|
return 1
|
2009-03-03 02:24:23 +00:00
|
|
|
|
2008-10-21 14:00:00 +00:00
|
|
|
try:
|
|
|
|
cmd = self.commands[name]
|
|
|
|
except KeyError:
|
|
|
|
print >>sys.stderr,\
|
|
|
|
"repo: '%s' is not a repo command. See 'repo help'."\
|
|
|
|
% name
|
2011-04-29 13:59:12 +00:00
|
|
|
return 1
|
2008-10-21 14:00:00 +00:00
|
|
|
|
|
|
|
cmd.repodir = self.repodir
|
2009-05-18 20:19:57 +00:00
|
|
|
cmd.manifest = XmlManifest(cmd.repodir)
|
2008-10-29 22:20:02 +00:00
|
|
|
Editor.globalConfig = cmd.manifest.globalConfig
|
2008-10-21 14:00:00 +00:00
|
|
|
|
2009-03-04 01:47:06 +00:00
|
|
|
if not isinstance(cmd, MirrorSafeCommand) and cmd.manifest.IsMirror:
|
|
|
|
print >>sys.stderr, \
|
|
|
|
"fatal: '%s' requires a working directory"\
|
|
|
|
% name
|
2011-04-29 13:59:12 +00:00
|
|
|
return 1
|
2009-03-04 01:47:06 +00:00
|
|
|
|
2009-04-18 20:49:13 +00:00
|
|
|
copts, cargs = cmd.OptionParser.parse_args(argv)
|
|
|
|
|
2008-10-21 14:00:00 +00:00
|
|
|
if not gopts.no_pager and not isinstance(cmd, InteractiveCommand):
|
|
|
|
config = cmd.manifest.globalConfig
|
|
|
|
if gopts.pager:
|
|
|
|
use_pager = True
|
|
|
|
else:
|
|
|
|
use_pager = config.GetBoolean('pager.%s' % name)
|
|
|
|
if use_pager is None:
|
2009-04-18 20:49:13 +00:00
|
|
|
use_pager = cmd.WantPager(copts)
|
2008-10-21 14:00:00 +00:00
|
|
|
if use_pager:
|
|
|
|
RunPager(config)
|
|
|
|
|
|
|
|
try:
|
2011-09-23 00:06:41 +00:00
|
|
|
start = time.time()
|
|
|
|
try:
|
2011-04-29 13:59:12 +00:00
|
|
|
result = cmd.Execute(copts, cargs)
|
2011-09-23 00:06:41 +00:00
|
|
|
finally:
|
|
|
|
elapsed = time.time() - start
|
|
|
|
hours, remainder = divmod(elapsed, 3600)
|
|
|
|
minutes, seconds = divmod(remainder, 60)
|
|
|
|
if gopts.time:
|
|
|
|
if hours == 0:
|
|
|
|
print >>sys.stderr, 'real\t%dm%.3fs' \
|
|
|
|
% (minutes, seconds)
|
|
|
|
else:
|
|
|
|
print >>sys.stderr, 'real\t%dh%dm%.3fs' \
|
|
|
|
% (hours, minutes, seconds)
|
2011-09-19 21:50:58 +00:00
|
|
|
except DownloadError, e:
|
|
|
|
print >>sys.stderr, 'error: %s' % str(e)
|
2011-04-29 13:59:12 +00:00
|
|
|
return 1
|
2009-03-02 20:56:08 +00:00
|
|
|
except ManifestInvalidRevisionError, e:
|
|
|
|
print >>sys.stderr, 'error: %s' % str(e)
|
2011-04-29 13:59:12 +00:00
|
|
|
return 1
|
2008-10-21 14:00:00 +00:00
|
|
|
except NoSuchProjectError, e:
|
|
|
|
if e.name:
|
|
|
|
print >>sys.stderr, 'error: project %s not found' % e.name
|
|
|
|
else:
|
|
|
|
print >>sys.stderr, 'error: no project in current directory'
|
2011-04-29 13:59:12 +00:00
|
|
|
return 1
|
|
|
|
|
|
|
|
return result
|
2008-10-21 14:00:00 +00:00
|
|
|
|
2011-09-19 15:05:31 +00:00
|
|
|
def _MyRepoPath():
|
|
|
|
return os.path.dirname(__file__)
|
|
|
|
|
2008-10-21 14:00:00 +00:00
|
|
|
def _MyWrapperPath():
|
|
|
|
return os.path.join(os.path.dirname(__file__), 'repo')
|
|
|
|
|
|
|
|
def _CurrentWrapperVersion():
|
|
|
|
VERSION = None
|
|
|
|
pat = re.compile(r'^VERSION *=')
|
|
|
|
fd = open(_MyWrapperPath())
|
|
|
|
for line in fd:
|
|
|
|
if pat.match(line):
|
|
|
|
fd.close()
|
|
|
|
exec line
|
|
|
|
return VERSION
|
|
|
|
raise NameError, 'No VERSION in repo script'
|
|
|
|
|
|
|
|
def _CheckWrapperVersion(ver, repo_path):
|
|
|
|
if not repo_path:
|
|
|
|
repo_path = '~/bin/repo'
|
|
|
|
|
|
|
|
if not ver:
|
|
|
|
print >>sys.stderr, 'no --wrapper-version argument'
|
|
|
|
sys.exit(1)
|
|
|
|
|
|
|
|
exp = _CurrentWrapperVersion()
|
|
|
|
ver = tuple(map(lambda x: int(x), ver.split('.')))
|
|
|
|
if len(ver) == 1:
|
|
|
|
ver = (0, ver[0])
|
|
|
|
|
|
|
|
if exp[0] > ver[0] or ver < (0, 4):
|
|
|
|
exp_str = '.'.join(map(lambda x: str(x), exp))
|
|
|
|
print >>sys.stderr, """
|
|
|
|
!!! A new repo command (%5s) is available. !!!
|
|
|
|
!!! You must upgrade before you can continue: !!!
|
|
|
|
|
|
|
|
cp %s %s
|
|
|
|
""" % (exp_str, _MyWrapperPath(), repo_path)
|
|
|
|
sys.exit(1)
|
|
|
|
|
|
|
|
if exp > ver:
|
|
|
|
exp_str = '.'.join(map(lambda x: str(x), exp))
|
|
|
|
print >>sys.stderr, """
|
|
|
|
... A new repo command (%5s) is available.
|
|
|
|
... You should upgrade soon:
|
|
|
|
|
|
|
|
cp %s %s
|
|
|
|
""" % (exp_str, _MyWrapperPath(), repo_path)
|
|
|
|
|
|
|
|
def _CheckRepoDir(dir):
|
|
|
|
if not dir:
|
|
|
|
print >>sys.stderr, 'no --repo-dir argument'
|
|
|
|
sys.exit(1)
|
|
|
|
|
|
|
|
def _PruneOptions(argv, opt):
|
|
|
|
i = 0
|
|
|
|
while i < len(argv):
|
|
|
|
a = argv[i]
|
|
|
|
if a == '--':
|
|
|
|
break
|
|
|
|
if a.startswith('--'):
|
|
|
|
eq = a.find('=')
|
|
|
|
if eq > 0:
|
|
|
|
a = a[0:eq]
|
|
|
|
if not opt.has_option(a):
|
|
|
|
del argv[i]
|
|
|
|
continue
|
|
|
|
i += 1
|
|
|
|
|
2011-09-19 15:05:31 +00:00
|
|
|
_user_agent = None
|
|
|
|
|
|
|
|
def _UserAgent():
|
|
|
|
global _user_agent
|
|
|
|
|
|
|
|
if _user_agent is None:
|
|
|
|
py_version = sys.version_info
|
|
|
|
|
|
|
|
os_name = sys.platform
|
|
|
|
if os_name == 'linux2':
|
|
|
|
os_name = 'Linux'
|
|
|
|
elif os_name == 'win32':
|
|
|
|
os_name = 'Win32'
|
|
|
|
elif os_name == 'cygwin':
|
|
|
|
os_name = 'Cygwin'
|
|
|
|
elif os_name == 'darwin':
|
|
|
|
os_name = 'Darwin'
|
|
|
|
|
|
|
|
p = GitCommand(
|
|
|
|
None, ['describe', 'HEAD'],
|
|
|
|
cwd = _MyRepoPath(),
|
|
|
|
capture_stdout = True)
|
|
|
|
if p.Wait() == 0:
|
|
|
|
repo_version = p.stdout
|
|
|
|
if len(repo_version) > 0 and repo_version[-1] == '\n':
|
|
|
|
repo_version = repo_version[0:-1]
|
|
|
|
if len(repo_version) > 0 and repo_version[0] == 'v':
|
|
|
|
repo_version = repo_version[1:]
|
|
|
|
else:
|
|
|
|
repo_version = 'unknown'
|
|
|
|
|
|
|
|
_user_agent = 'git-repo/%s (%s) git/%s Python/%d.%d.%d' % (
|
|
|
|
repo_version,
|
|
|
|
os_name,
|
|
|
|
'.'.join(map(lambda d: str(d), git.version_tuple())),
|
|
|
|
py_version[0], py_version[1], py_version[2])
|
|
|
|
return _user_agent
|
|
|
|
|
|
|
|
class _UserAgentHandler(urllib2.BaseHandler):
|
|
|
|
def http_request(self, req):
|
|
|
|
req.add_header('User-Agent', _UserAgent())
|
|
|
|
return req
|
|
|
|
|
|
|
|
def https_request(self, req):
|
|
|
|
req.add_header('User-Agent', _UserAgent())
|
|
|
|
return req
|
|
|
|
|
2011-10-11 19:00:38 +00:00
|
|
|
class _BasicAuthHandler(urllib2.HTTPBasicAuthHandler):
|
|
|
|
def http_error_auth_reqed(self, authreq, host, req, headers):
|
|
|
|
try:
|
2011-10-11 21:05:21 +00:00
|
|
|
old_add_header = req.add_header
|
|
|
|
def _add_header(name, val):
|
|
|
|
val = val.replace('\n', '')
|
|
|
|
old_add_header(name, val)
|
|
|
|
req.add_header = _add_header
|
2011-10-11 19:00:38 +00:00
|
|
|
return urllib2.AbstractBasicAuthHandler.http_error_auth_reqed(
|
|
|
|
self, authreq, host, req, headers)
|
|
|
|
except:
|
2011-10-11 21:05:21 +00:00
|
|
|
reset = getattr(self, 'reset_retry_count', None)
|
|
|
|
if reset is not None:
|
|
|
|
reset()
|
2011-10-11 22:58:07 +00:00
|
|
|
elif getattr(self, 'retried', None):
|
|
|
|
self.retried = 0
|
2011-10-11 19:00:38 +00:00
|
|
|
raise
|
|
|
|
|
2012-01-31 03:10:09 +00:00
|
|
|
class _DigestAuthHandler(urllib2.HTTPDigestAuthHandler):
|
|
|
|
def http_error_auth_reqed(self, auth_header, host, req, headers):
|
|
|
|
try:
|
|
|
|
old_add_header = req.add_header
|
|
|
|
def _add_header(name, val):
|
|
|
|
val = val.replace('\n', '')
|
|
|
|
old_add_header(name, val)
|
|
|
|
req.add_header = _add_header
|
|
|
|
return urllib2.AbstractDigestAuthHandler.http_error_auth_reqed(
|
|
|
|
self, auth_header, host, req, headers)
|
|
|
|
except:
|
|
|
|
reset = getattr(self, 'reset_retry_count', None)
|
|
|
|
if reset is not None:
|
|
|
|
reset()
|
|
|
|
elif getattr(self, 'retried', None):
|
|
|
|
self.retried = 0
|
|
|
|
raise
|
|
|
|
|
2011-09-11 19:57:15 +00:00
|
|
|
def init_http():
|
2011-09-19 15:05:31 +00:00
|
|
|
handlers = [_UserAgentHandler()]
|
|
|
|
|
2011-09-19 17:04:23 +00:00
|
|
|
mgr = urllib2.HTTPPasswordMgrWithDefaultRealm()
|
|
|
|
try:
|
|
|
|
n = netrc.netrc()
|
|
|
|
for host in n.hosts:
|
|
|
|
p = n.hosts[host]
|
2012-01-31 03:10:09 +00:00
|
|
|
mgr.add_password(p[1], 'http://%s/' % host, p[0], p[2])
|
|
|
|
mgr.add_password(p[1], 'https://%s/' % host, p[0], p[2])
|
2011-09-19 17:04:23 +00:00
|
|
|
except netrc.NetrcParseError:
|
|
|
|
pass
|
2011-09-23 18:50:31 +00:00
|
|
|
except IOError:
|
|
|
|
pass
|
2011-10-11 19:00:38 +00:00
|
|
|
handlers.append(_BasicAuthHandler(mgr))
|
2012-01-31 03:10:09 +00:00
|
|
|
handlers.append(_DigestAuthHandler(mgr))
|
2011-09-19 17:04:23 +00:00
|
|
|
|
2011-09-11 19:57:15 +00:00
|
|
|
if 'http_proxy' in os.environ:
|
|
|
|
url = os.environ['http_proxy']
|
2011-09-19 15:05:31 +00:00
|
|
|
handlers.append(urllib2.ProxyHandler({'http': url, 'https': url}))
|
|
|
|
if 'REPO_CURL_VERBOSE' in os.environ:
|
|
|
|
handlers.append(urllib2.HTTPHandler(debuglevel=1))
|
|
|
|
handlers.append(urllib2.HTTPSHandler(debuglevel=1))
|
|
|
|
urllib2.install_opener(urllib2.build_opener(*handlers))
|
2011-09-11 19:57:15 +00:00
|
|
|
|
2008-10-21 14:00:00 +00:00
|
|
|
def _Main(argv):
|
2011-04-29 13:59:12 +00:00
|
|
|
result = 0
|
|
|
|
|
2008-10-21 14:00:00 +00:00
|
|
|
opt = optparse.OptionParser(usage="repo wrapperinfo -- ...")
|
|
|
|
opt.add_option("--repo-dir", dest="repodir",
|
|
|
|
help="path to .repo/")
|
|
|
|
opt.add_option("--wrapper-version", dest="wrapper_version",
|
|
|
|
help="version of the wrapper script")
|
|
|
|
opt.add_option("--wrapper-path", dest="wrapper_path",
|
|
|
|
help="location of the wrapper script")
|
|
|
|
_PruneOptions(argv, opt)
|
|
|
|
opt, argv = opt.parse_args(argv)
|
|
|
|
|
|
|
|
_CheckWrapperVersion(opt.wrapper_version, opt.wrapper_path)
|
|
|
|
_CheckRepoDir(opt.repodir)
|
|
|
|
|
2011-11-29 23:01:33 +00:00
|
|
|
Version.wrapper_version = opt.wrapper_version
|
|
|
|
Version.wrapper_path = opt.wrapper_path
|
|
|
|
|
2008-10-21 14:00:00 +00:00
|
|
|
repo = _Repo(opt.repodir)
|
|
|
|
try:
|
2009-04-11 01:53:46 +00:00
|
|
|
try:
|
2010-12-21 21:39:23 +00:00
|
|
|
init_ssh()
|
2011-09-11 19:57:15 +00:00
|
|
|
init_http()
|
2011-04-29 13:59:12 +00:00
|
|
|
result = repo._Run(argv) or 0
|
2009-04-11 01:53:46 +00:00
|
|
|
finally:
|
|
|
|
close_ssh()
|
2008-10-21 14:00:00 +00:00
|
|
|
except KeyboardInterrupt:
|
2011-04-29 13:59:12 +00:00
|
|
|
result = 1
|
2008-11-03 18:32:09 +00:00
|
|
|
except RepoChangedException, rce:
|
|
|
|
# If repo changed, re-exec ourselves.
|
2008-10-21 14:00:00 +00:00
|
|
|
#
|
2008-11-03 18:32:09 +00:00
|
|
|
argv = list(sys.argv)
|
|
|
|
argv.extend(rce.extra_args)
|
2008-10-21 14:00:00 +00:00
|
|
|
try:
|
2008-11-03 18:32:09 +00:00
|
|
|
os.execv(__file__, argv)
|
2008-10-21 14:00:00 +00:00
|
|
|
except OSError, e:
|
|
|
|
print >>sys.stderr, 'fatal: cannot restart repo after upgrade'
|
|
|
|
print >>sys.stderr, 'fatal: %s' % e
|
2011-04-29 13:59:12 +00:00
|
|
|
result = 128
|
|
|
|
|
|
|
|
sys.exit(result)
|
2008-10-21 14:00:00 +00:00
|
|
|
|
|
|
|
if __name__ == '__main__':
|
|
|
|
_Main(sys.argv[1:])
|