#!/usr/bin/env python # -*- coding:utf-8 -*- """Repo launcher. This is a standalone tool that people may copy to anywhere in their system. It is used to get an initial repo client checkout, and after that it runs the copy of repo in the checkout. """ from __future__ import print_function # repo default configuration # import os REPO_URL = os.environ.get('REPO_URL', None) if not REPO_URL: REPO_URL = 'https://chromium.googlesource.com/external/repo' REPO_REV = 'stable' # Copyright (C) 2008 Google Inc. # # 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. # increment this whenever we make important changes to this script VERSION = (1, 26) # increment this if the MAINTAINER_KEYS block is modified KEYRING_VERSION = (1, 5) # Each individual key entry is created by using: # gpg --armor --export keyid MAINTAINER_KEYS = """ Repo Maintainer -----BEGIN PGP PUBLIC KEY BLOCK----- Version: GnuPG v1.4.2.2 (GNU/Linux) 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 =CMiZ -----END PGP PUBLIC KEY BLOCK----- Conley Owens -----BEGIN PGP PUBLIC KEY BLOCK----- Version: GnuPG v1.4.11 (GNU/Linux) mQENBFHRvc8BCADFg45Xx/y6QDC+T7Y/gGc7vx0ww7qfOwIKlAZ9xG3qKunMxo+S hPCnzEl3cq+6I1Ww/ndop/HB3N3toPXRCoN8Vs4/Hc7by+SnaLFnacrm+tV5/OgT V37Lzt8lhay1Kl+YfpFwHYYpIEBLFV9knyfRXS/428W2qhdzYfvB15/AasRmwmor py4NIzSs8UD/SPr1ihqNCdZM76+MQyN5HMYXW/ALZXUFG0pwluHFA7hrfPG74i8C zMiP7qvMWIl/r/jtzHioH1dRKgbod+LZsrDJ8mBaqsZaDmNJMhss9g76XvfMyLra 9DI9/iFuBpGzeqBv0hwOGQspLRrEoyTeR6n1ABEBAAG0H0NvbmxleSBPd2VucyA8 Y2NvM0BhbmRyb2lkLmNvbT6JATgEEwECACIFAlHRvc8CGwMGCwkIBwMCBhUIAgkK CwQWAgMBAh4BAheAAAoJEGe35EhpKzgsP6AIAJKJmNtn4l7hkYHKHFSo3egb6RjQ zEIP3MFTcu8HFX1kF1ZFbrp7xqurLaE53kEkKuAAvjJDAgI8mcZHP1JyplubqjQA xvv84gK+OGP3Xk+QK1ZjUQSbjOpjEiSZpRhWcHci3dgOUH4blJfByHw25hlgHowd a/2PrNKZVcJ92YienaxxGjcXEUcd0uYEG2+rwllQigFcnMFDhr9B71MfalRHjFKE fmdoypqLrri61YBc59P88Rw2/WUpTQjgNubSqa3A2+CKdaRyaRw+2fdF4TdR0h8W zbg+lbaPtJHsV+3mJC7fq26MiJDRJa5ZztpMn8su20gbLgi2ShBOaHAYDDi5AQ0E UdG9zwEIAMoOBq+QLNozAhxOOl5GL3StTStGRgPRXINfmViTsihrqGCWBBUfXlUE OytC0mYcrDUQev/8ToVoyqw+iGSwDkcSXkrEUCKFtHV/GECWtk1keyHgR10YKI1R mquSXoubWGqPeG1PAI74XWaRx8UrL8uCXUtmD8Q5J7mDjKR5NpxaXrwlA0bKsf2E Gp9tu1kKauuToZhWHMRMqYSOGikQJwWSFYKT1KdNcOXLQF6+bfoJ6sjVYdwfmNQL Ixn8QVhoTDedcqClSWB17VDEFDFa7MmqXZz2qtM3X1R/MUMHqPtegQzBGNhRdnI2 V45+1Nnx/uuCxDbeI4RbHzujnxDiq70AEQEAAYkBHwQYAQIACQUCUdG9zwIbDAAK CRBnt+RIaSs4LNVeB/0Y2pZ8I7gAAcEM0Xw8drr4omg2fUoK1J33ozlA/RxeA/lJ I3KnyCDTpXuIeBKPGkdL8uMATC9Z8DnBBajRlftNDVZS3Hz4G09G9QpMojvJkFJV By+01Flw/X+eeN8NpqSuLV4W+AjEO8at/VvgKr1AFvBRdZ7GkpI1o6DgPe7ZqX+1 dzQZt3e13W0rVBb/bUgx9iSLoeWP3aq/k+/GRGOR+S6F6BBSl0SQ2EF2+dIywb1x JuinEP+AwLAUZ1Bsx9ISC0Agpk2VeHXPL3FGhroEmoMvBzO0kTFGyoeT7PR/BfKv +H/g3HsL2LOB9uoIm8/5p2TTU5ttYCXMHhQZ81AY =AUp4 -----END PGP PUBLIC KEY BLOCK----- Stefan Zager -----BEGIN PGP PUBLIC KEY BLOCK----- Version: GnuPG v1.4.11 (GNU/Linux) mQINBFIJOcgBEADwZIq4GRGoO1RJFKlrtVK501cwT5H+Acbizc9N5RxTkFmqxDjb 9ApUaPW6S1b8+nrzE9P1Ri5erfzipuStfaZ/Wl3mP1JjKulibddmgnPOEbAJ673k Vj85RUO4rt2oZAHnZN3D3gFJzVY8JVlZ47Enj9fTqzcW78FVsPCpIT9P2LpTLWeE jX9Cjxeimy6VvyJstIcDLYhlpUN5UWen79L4LFAkHf3luLuU4W3p9NriqUsy5UG2 8vO6QdhKrCr5wsjDFFeVnpMtjlSeZJAWH+XhFFibMX1xP5R9BTuJfzw3kOVKvcE0 e9ClxgoulepXPv2xnDkqO3pG2gQVzl8LA+Aol8/IXfa7KP5FBkxK/g1cDuDtXRk4 YLpLaLYeeKEhhOHLpsKYkK2DXTIcN+56UnTLGolummpZnCM8UUSZxQgbkFgk4YJL Elip0hgLZzqEl5h9vjmnQp89AZIHKcgNmzn+szLTOR9x24joaLyQ534x8OSC8lmu tJv2tQjDOVGWVwvY4gOTpyxCWMwur6WOiMk/TPWdiVRFWAGrAHwf0/CTBEqNhosh sVXfPeMADBA0PorDbJ6kwcOkLUTGf8CT7OG1R9TuKPEmSjK7BYu/pT4DXitaRCiv uPVlwbVFpLFr0/jwaKJVMLUjL5MaYwzjJqI2c4RdROZhpMhkn4LvCMmFSQARAQAB tCJTdGVmYW4gWmFnZXIgPHN6YWdlckBjaHJvbWl1bS5vcmc+iQI4BBMBAgAiBQJS CTnIAhsDBgsJCAcDAgYVCAIJCgsEFgIDAQIeAQIXgAAKCRDcuoHPGCdZNU0UD/9y 0zwwOJH2UGPAzZ0YVzr7p0HtKedoxuFvPkdQxlBIaUOueMzFRmNQu3GI9irAu3MQ Jkip8/gi7dnLVmJyS/zWARBaRGwSVd1++87XDjw8n7l181p7394X0Agq/heri599 YheHXkxXKVMPqByWNEPHu4eDbxeJTaDIjcKC2pzKQkm6HbWgW4wA9gCh1TRki8FP LMv1Fu/dr13STCR9P2evsTRZ+ZSJhTSboHNHeEAJGiGZQAsN94oht7647lYj+AyR ThzyHDMXXiDr8jPJIkyRilY+y82bCOatOfPoCkce3VI+LRUGJ19hJY01m4RRneIE 55l7fXR3zggcsONjV5b+oLcGQPGgX9w64BJ7khT7Wb9+kuyrdJBIBzJsaACFEbri pPi02FS/HahYpLC3J66REAeNyofgVXau6WQsHrHMGsBTL9aAr0nrCrkF4Nyyc2Jd do6nYuljuUhORqbEECmmBM2eBtkL6Ac92D6WMBIwBOC5tCNHO2YFIvi8Y8EuE8sc 1zB5U5Ai4SIu2icRAhzAhCRaUq02cMWuELKH6Vuh9nzgEefFWty6vPbKEyZLu19D B80aqP1cTN88FjtKQ/eTF29TUB6AefUeBS17e2e3WUMy4nc8tduuOFYfiHP40ScP wOoatwfzpiTIPGbocUEPL+pS0O/Xy8SINxFMCud3zA== =Vd2S -----END PGP PUBLIC KEY BLOCK----- David James -----BEGIN PGP PUBLIC KEY BLOCK----- Version: GnuPG v1 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 IM4= =6VNc -----END PGP PUBLIC KEY BLOCK----- Mike Frysinger -----BEGIN PGP PUBLIC KEY BLOCK----- Version: GnuPG v1 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 =i88c -----END PGP PUBLIC KEY BLOCK----- """ GIT = 'git' # our git command MIN_GIT_VERSION = (1, 7, 2) # minimum supported git version repodir = '.repo' # name of repo's private directory S_repo = 'repo' # special repo repository S_manifests = 'manifests' # special manifest repository REPO_MAIN = S_repo + '/main.py' # main script MIN_PYTHON_VERSION = (2, 7) # minimum supported python version GITC_CONFIG_FILE = '/gitc/.config' GITC_FS_ROOT_DIR = '/gitc/manifest-rw/' import collections import errno import optparse import platform import re import shutil import stat import subprocess import sys if sys.version_info[0] == 3: import urllib.request import urllib.error else: import imp import urllib2 urllib = imp.new_module('urllib') urllib.request = urllib2 urllib.error = urllib2 # Python version check ver = sys.version_info if (ver[0], ver[1]) < MIN_PYTHON_VERSION: print('error: Python version {} unsupported.\n' 'Please use Python {}.{} instead.'.format( sys.version.split(' ')[0], MIN_PYTHON_VERSION[0], MIN_PYTHON_VERSION[1], ), file=sys.stderr) sys.exit(1) home_dot_repo = os.path.expanduser('~/.repoconfig') gpg_dir = os.path.join(home_dot_repo, 'gnupg') extra_args = [] init_optparse = optparse.OptionParser(usage="repo init -u url [options]") # Logging group = init_optparse.add_option_group('Logging options') group.add_option('-q', '--quiet', dest="quiet", action="store_true", default=False, help="be quiet") # Manifest group = init_optparse.add_option_group('Manifest options') group.add_option('-u', '--manifest-url', dest='manifest_url', help='manifest repository location', metavar='URL') group.add_option('-b', '--manifest-branch', dest='manifest_branch', help='manifest branch or revision', metavar='REVISION') group.add_option('-m', '--manifest-name', dest='manifest_name', help='initial manifest file', metavar='NAME.xml') group.add_option('--current-branch', dest='current_branch_only', action='store_true', help='fetch only current manifest branch from server') group.add_option('--mirror', dest='mirror', action='store_true', help='create a replica of the remote repositories ' 'rather than a client working directory') group.add_option('--reference', dest='reference', help='location of mirror directory', metavar='DIR') group.add_option('--dissociate', dest='dissociate', action='store_true', help='dissociate from reference mirrors after clone') group.add_option('--depth', type='int', default=None, dest='depth', help='create a shallow clone with given depth; see git clone') group.add_option('--partial-clone', action='store_true', dest='partial_clone', help='perform partial clone (https://git-scm.com/' 'docs/gitrepository-layout#_code_partialclone_code)') group.add_option('--clone-filter', action='store', default='blob:none', dest='clone_filter', help='filter for use with --partial-clone [default: %default]') group.add_option('--archive', dest='archive', action='store_true', help='checkout an archive instead of a git repository for ' 'each project. See git archive.') group.add_option('--submodules', dest='submodules', action='store_true', help='sync any submodules associated with the manifest repo') group.add_option('-g', '--groups', dest='groups', default='default', help='restrict manifest projects to ones with specified ' 'group(s) [default|all|G1,G2,G3|G4,-G5,-G6]', metavar='GROUP') group.add_option('-p', '--platform', dest='platform', default="auto", help='restrict manifest projects to ones with a specified ' 'platform group [auto|all|none|linux|darwin|...]', metavar='PLATFORM') group.add_option('--no-clone-bundle', dest='no_clone_bundle', action='store_true', help='disable use of /clone.bundle on HTTP/HTTPS') group.add_option('--no-tags', dest='no_tags', action='store_true', help="don't fetch tags in the manifest") # Tool group = init_optparse.add_option_group('repo Version options') group.add_option('--repo-url', dest='repo_url', help='repo repository location', metavar='URL') group.add_option('--repo-branch', dest='repo_branch', help='repo branch or revision', metavar='REVISION') group.add_option('--no-repo-verify', dest='no_repo_verify', action='store_true', help='do not verify repo source code') # Other group = init_optparse.add_option_group('Other options') group.add_option('--config-name', dest='config_name', action="store_true", default=False, help='Always prompt for name/e-mail') def _GitcInitOptions(init_optparse_arg): init_optparse_arg.set_usage("repo gitc-init -u url -c client [options]") g = init_optparse_arg.add_option_group('GITC options') g.add_option('-f', '--manifest-file', dest='manifest_file', help='Optional manifest file to use for this GITC client.') g.add_option('-c', '--gitc-client', dest='gitc_client', help='The name of the gitc_client instance to create or modify.') _gitc_manifest_dir = None def get_gitc_manifest_dir(): global _gitc_manifest_dir if _gitc_manifest_dir is None: _gitc_manifest_dir = '' try: with open(GITC_CONFIG_FILE, 'r') as gitc_config: for line in gitc_config: match = re.match('gitc_dir=(?P.*)', line) if match: _gitc_manifest_dir = match.group('gitc_manifest_dir') except IOError: pass return _gitc_manifest_dir def gitc_parse_clientdir(gitc_fs_path): """Parse a path in the GITC FS and return its client name. @param gitc_fs_path: A subdirectory path within the GITC_FS_ROOT_DIR. @returns: The GITC client name """ if gitc_fs_path == GITC_FS_ROOT_DIR: return None if not gitc_fs_path.startswith(GITC_FS_ROOT_DIR): manifest_dir = get_gitc_manifest_dir() if manifest_dir == '': return None if manifest_dir[-1] != '/': manifest_dir += '/' if gitc_fs_path == manifest_dir: return None if not gitc_fs_path.startswith(manifest_dir): return None return gitc_fs_path.split(manifest_dir)[1].split('/')[0] return gitc_fs_path.split(GITC_FS_ROOT_DIR)[1].split('/')[0] class CloneFailure(Exception): """Indicate the remote clone of repo itself failed. """ def _Init(args, gitc_init=False): """Installs repo by cloning it over the network. """ if gitc_init: _GitcInitOptions(init_optparse) opt, args = init_optparse.parse_args(args) if args: init_optparse.print_usage() sys.exit(1) url = opt.repo_url if not url: url = REPO_URL extra_args.append('--repo-url=%s' % url) branch = opt.repo_branch if not branch: branch = REPO_REV extra_args.append('--repo-branch=%s' % branch) if branch.startswith('refs/heads/'): branch = branch[len('refs/heads/'):] if branch.startswith('refs/'): print("fatal: invalid branch name '%s'" % branch, file=sys.stderr) raise CloneFailure() try: if gitc_init: gitc_manifest_dir = get_gitc_manifest_dir() if not gitc_manifest_dir: print('fatal: GITC filesystem is not available. Exiting...', file=sys.stderr) sys.exit(1) gitc_client = opt.gitc_client if not gitc_client: gitc_client = gitc_parse_clientdir(os.getcwd()) if not gitc_client: print('fatal: GITC client (-c) is required.', file=sys.stderr) sys.exit(1) client_dir = os.path.join(gitc_manifest_dir, gitc_client) if not os.path.exists(client_dir): os.makedirs(client_dir) os.chdir(client_dir) if os.path.exists(repodir): # This GITC Client has already initialized repo so continue. return os.mkdir(repodir) except OSError as e: if e.errno != errno.EEXIST: print('fatal: cannot make %s directory: %s' % (repodir, e.strerror), file=sys.stderr) # Don't raise CloneFailure; that would delete the # name. Instead exit immediately. # sys.exit(1) _CheckGitVersion() try: if NeedSetupGnuPG(): can_verify = SetupGnuPG(opt.quiet) else: can_verify = True dst = os.path.abspath(os.path.join(repodir, S_repo)) _Clone(url, dst, opt.quiet, not opt.no_clone_bundle) if can_verify and not opt.no_repo_verify: rev = _Verify(dst, branch, opt.quiet) else: rev = 'refs/remotes/origin/%s^0' % branch _Checkout(dst, branch, rev, opt.quiet) if not os.path.isfile(os.path.join(dst, 'repo')): print("warning: '%s' does not look like a git-repo repository, is " "REPO_URL set correctly?" % url, file=sys.stderr) except CloneFailure: if opt.quiet: print('fatal: repo init failed; run without --quiet to see why', file=sys.stderr) raise # The git version info broken down into components for easy analysis. # Similar to Python's sys.version_info. GitVersion = collections.namedtuple( 'GitVersion', ('major', 'minor', 'micro', 'full')) def ParseGitVersion(ver_str=None): if ver_str is None: # Load the version ourselves. ver_str = _GetGitVersion() if not ver_str.startswith('git version '): return None full_version = ver_str[len('git version '):].strip() num_ver_str = full_version.split('-')[0] to_tuple = [] for num_str in num_ver_str.split('.')[:3]: if num_str.isdigit(): to_tuple.append(int(num_str)) else: to_tuple.append(0) to_tuple.append(full_version) return GitVersion(*to_tuple) def _GetGitVersion(): cmd = [GIT, '--version'] try: proc = subprocess.Popen(cmd, stdout=subprocess.PIPE) except OSError as e: print(file=sys.stderr) print("fatal: '%s' is not available" % GIT, file=sys.stderr) print('fatal: %s' % e, file=sys.stderr) print(file=sys.stderr) print('Please make sure %s is installed and in your path.' % GIT, file=sys.stderr) raise ver_str = proc.stdout.read().strip() proc.stdout.close() proc.wait() return ver_str.decode('utf-8') def _CheckGitVersion(): try: ver_act = ParseGitVersion() except OSError: raise CloneFailure() if ver_act is None: print('fatal: unable to detect git version', file=sys.stderr) raise CloneFailure() if ver_act < MIN_GIT_VERSION: need = '.'.join(map(str, MIN_GIT_VERSION)) print('fatal: git %s or later required' % need, file=sys.stderr) raise CloneFailure() def NeedSetupGnuPG(): if not os.path.isdir(home_dot_repo): return True kv = os.path.join(home_dot_repo, 'keyring-version') if not os.path.exists(kv): return True kv = open(kv).read() if not kv: return True kv = tuple(map(int, kv.split('.'))) if kv < KEYRING_VERSION: return True return False def SetupGnuPG(quiet): try: os.mkdir(home_dot_repo) except OSError as e: if e.errno != errno.EEXIST: print('fatal: cannot make %s directory: %s' % (home_dot_repo, e.strerror), file=sys.stderr) sys.exit(1) try: os.mkdir(gpg_dir, stat.S_IRWXU) except OSError as e: if e.errno != errno.EEXIST: print('fatal: cannot make %s directory: %s' % (gpg_dir, e.strerror), file=sys.stderr) sys.exit(1) env = os.environ.copy() try: env['GNUPGHOME'] = gpg_dir except UnicodeEncodeError: env['GNUPGHOME'] = gpg_dir.encode() cmd = ['gpg', '--import'] try: proc = subprocess.Popen(cmd, env=env, stdin=subprocess.PIPE) except OSError as e: if not quiet: print('warning: gpg (GnuPG) is not available.', file=sys.stderr) print('warning: Installing it is strongly encouraged.', file=sys.stderr) print(file=sys.stderr) return False proc.stdin.write(MAINTAINER_KEYS.encode('utf-8')) proc.stdin.close() if proc.wait() != 0: print('fatal: registering repo maintainer keys failed', file=sys.stderr) sys.exit(1) print() fd = open(os.path.join(home_dot_repo, 'keyring-version'), 'w') fd.write('.'.join(map(str, KEYRING_VERSION)) + '\n') fd.close() return True def _SetConfig(local, name, value): """Set a git configuration option to the specified value. """ cmd = [GIT, 'config', name, value] if subprocess.Popen(cmd, cwd=local).wait() != 0: raise CloneFailure() def _InitHttp(): handlers = [] mgr = urllib.request.HTTPPasswordMgrWithDefaultRealm() try: import netrc n = netrc.netrc() for host in n.hosts: p = n.hosts[host] mgr.add_password(p[1], 'http://%s/' % host, p[0], p[2]) mgr.add_password(p[1], 'https://%s/' % host, p[0], p[2]) except: pass handlers.append(urllib.request.HTTPBasicAuthHandler(mgr)) handlers.append(urllib.request.HTTPDigestAuthHandler(mgr)) if 'http_proxy' in os.environ: url = os.environ['http_proxy'] handlers.append(urllib.request.ProxyHandler({'http': url, 'https': url})) if 'REPO_CURL_VERBOSE' in os.environ: handlers.append(urllib.request.HTTPHandler(debuglevel=1)) handlers.append(urllib.request.HTTPSHandler(debuglevel=1)) urllib.request.install_opener(urllib.request.build_opener(*handlers)) def _Fetch(url, local, src, quiet): if not quiet: print('Get %s' % url, file=sys.stderr) cmd = [GIT, 'fetch'] if quiet: cmd.append('--quiet') err = subprocess.PIPE else: err = None cmd.append(src) cmd.append('+refs/heads/*:refs/remotes/origin/*') cmd.append('+refs/tags/*:refs/tags/*') proc = subprocess.Popen(cmd, cwd=local, stderr=err) if err: proc.stderr.read() proc.stderr.close() if proc.wait() != 0: raise CloneFailure() def _DownloadBundle(url, local, quiet): if not url.endswith('/'): url += '/' url += 'clone.bundle' proc = subprocess.Popen( [GIT, 'config', '--get-regexp', 'url.*.insteadof'], cwd=local, stdout=subprocess.PIPE) for line in proc.stdout: line = line.decode('utf-8') m = re.compile(r'^url\.(.*)\.insteadof (.*)$').match(line) if m: new_url = m.group(1) old_url = m.group(2) if url.startswith(old_url): url = new_url + url[len(old_url):] break proc.stdout.close() proc.wait() if not url.startswith('http:') and not url.startswith('https:'): return False dest = open(os.path.join(local, '.git', 'clone.bundle'), 'w+b') try: try: r = urllib.request.urlopen(url) except urllib.error.HTTPError as e: if e.code in [401, 403, 404, 501]: return False print('fatal: Cannot get %s' % url, file=sys.stderr) print('fatal: HTTP error %s' % e.code, file=sys.stderr) raise CloneFailure() except urllib.error.URLError as e: print('fatal: Cannot get %s' % url, file=sys.stderr) print('fatal: error %s' % e.reason, file=sys.stderr) raise CloneFailure() try: if not quiet: print('Get %s' % url, file=sys.stderr) while True: buf = r.read(8192) if not buf: return True dest.write(buf) finally: r.close() finally: dest.close() def _ImportBundle(local): path = os.path.join(local, '.git', 'clone.bundle') try: _Fetch(local, local, path, True) finally: os.remove(path) def _Clone(url, local, quiet, clone_bundle): """Clones a git repository to a new subdirectory of repodir """ try: os.mkdir(local) except OSError as e: print('fatal: cannot make %s directory: %s' % (local, e.strerror), file=sys.stderr) raise CloneFailure() cmd = [GIT, 'init', '--quiet'] try: proc = subprocess.Popen(cmd, cwd=local) except OSError as e: print(file=sys.stderr) print("fatal: '%s' is not available" % GIT, file=sys.stderr) print('fatal: %s' % e, file=sys.stderr) print(file=sys.stderr) print('Please make sure %s is installed and in your path.' % GIT, file=sys.stderr) raise CloneFailure() if proc.wait() != 0: print('fatal: could not create %s' % local, file=sys.stderr) raise CloneFailure() _InitHttp() _SetConfig(local, 'remote.origin.url', url) _SetConfig(local, 'remote.origin.fetch', '+refs/heads/*:refs/remotes/origin/*') if clone_bundle and _DownloadBundle(url, local, quiet): _ImportBundle(local) _Fetch(url, local, 'origin', quiet) def _Verify(cwd, branch, quiet): """Verify the branch has been signed by a tag. """ cmd = [GIT, 'describe', 'origin/%s' % branch] proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=cwd) cur = proc.stdout.read().strip().decode('utf-8') proc.stdout.close() proc.stderr.read() proc.stderr.close() if proc.wait() != 0 or not cur: print(file=sys.stderr) print("fatal: branch '%s' has not been signed" % branch, file=sys.stderr) raise CloneFailure() m = re.compile(r'^(.*)-[0-9]{1,}-g[0-9a-f]{1,}$').match(cur) if m: cur = m.group(1) if not quiet: print(file=sys.stderr) print("info: Ignoring branch '%s'; using tagged release '%s'" % (branch, cur), file=sys.stderr) print(file=sys.stderr) env = os.environ.copy() try: env['GNUPGHOME'] = gpg_dir except UnicodeEncodeError: env['GNUPGHOME'] = gpg_dir.encode() cmd = [GIT, 'tag', '-v', cur] proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=cwd, env=env) out = proc.stdout.read().decode('utf-8') proc.stdout.close() err = proc.stderr.read().decode('utf-8') proc.stderr.close() if proc.wait() != 0: print(file=sys.stderr) print(out, file=sys.stderr) print(err, file=sys.stderr) print(file=sys.stderr) raise CloneFailure() return '%s^0' % cur def _Checkout(cwd, branch, rev, quiet): """Checkout an upstream branch into the repository and track it. """ cmd = [GIT, 'update-ref', 'refs/heads/default', rev] if subprocess.Popen(cmd, cwd=cwd).wait() != 0: raise CloneFailure() _SetConfig(cwd, 'branch.default.remote', 'origin') _SetConfig(cwd, 'branch.default.merge', 'refs/heads/%s' % branch) cmd = [GIT, 'symbolic-ref', 'HEAD', 'refs/heads/default'] if subprocess.Popen(cmd, cwd=cwd).wait() != 0: raise CloneFailure() cmd = [GIT, 'read-tree', '--reset', '-u'] if not quiet: cmd.append('-v') cmd.append('HEAD') if subprocess.Popen(cmd, cwd=cwd).wait() != 0: raise CloneFailure() def _FindRepo(): """Look for a repo installation, starting at the current directory. """ curdir = os.getcwd() repo = None olddir = None while curdir != '/' \ and curdir != olddir \ and not repo: repo = os.path.join(curdir, repodir, REPO_MAIN) if not os.path.isfile(repo): repo = None olddir = curdir curdir = os.path.dirname(curdir) return (repo, os.path.join(curdir, repodir)) class _Options(object): help = False def _ParseArguments(args): cmd = None opt = _Options() arg = [] for i in range(len(args)): a = args[i] if a == '-h' or a == '--help': opt.help = True elif not a.startswith('-'): cmd = a arg = args[i + 1:] break return cmd, opt, arg def _Usage(): gitc_usage = "" if get_gitc_manifest_dir(): gitc_usage = " gitc-init Initialize a GITC Client.\n" print( """usage: repo COMMAND [ARGS] repo is not yet installed. Use "repo init" to install it here. The most commonly used repo commands are: init Install repo in the current working directory """ + gitc_usage + """ help Display detailed help on a command For access to the full online help, install repo ("repo init"). """) sys.exit(0) def _Help(args): if args: if args[0] == 'init': init_optparse.print_help() sys.exit(0) elif args[0] == 'gitc-init': _GitcInitOptions(init_optparse) init_optparse.print_help() sys.exit(0) else: print("error: '%s' is not a bootstrap command.\n" ' For access to online help, install repo ("repo init").' % args[0], file=sys.stderr) else: _Usage() sys.exit(1) def _NotInstalled(): print('error: repo is not installed. Use "repo init" to install it here.', file=sys.stderr) sys.exit(1) def _NoCommands(cmd): print("""error: command '%s' requires repo to be installed first. Use "repo init" to install it here.""" % cmd, file=sys.stderr) sys.exit(1) def _RunSelf(wrapper_path): my_dir = os.path.dirname(wrapper_path) my_main = os.path.join(my_dir, 'main.py') my_git = os.path.join(my_dir, '.git') if os.path.isfile(my_main) and os.path.isdir(my_git): for name in ['git_config.py', 'project.py', 'subcmds']: if not os.path.exists(os.path.join(my_dir, name)): return None, None return my_main, my_git return None, None def _SetDefaultsTo(gitdir): global REPO_URL global REPO_REV REPO_URL = gitdir proc = subprocess.Popen([GIT, '--git-dir=%s' % gitdir, 'symbolic-ref', 'HEAD'], stdout=subprocess.PIPE, stderr=subprocess.PIPE) REPO_REV = proc.stdout.read().strip().decode('utf-8') proc.stdout.close() proc.stderr.read() proc.stderr.close() if proc.wait() != 0: print('fatal: %s has no current branch' % gitdir, file=sys.stderr) sys.exit(1) def main(orig_args): cmd, opt, args = _ParseArguments(orig_args) repo_main, rel_repo_dir = None, None # Don't use the local repo copy, make sure to switch to the gitc client first. if cmd != 'gitc-init': repo_main, rel_repo_dir = _FindRepo() wrapper_path = os.path.abspath(__file__) my_main, my_git = _RunSelf(wrapper_path) cwd = os.getcwd() if get_gitc_manifest_dir() and cwd.startswith(get_gitc_manifest_dir()): print('error: repo cannot be used in the GITC local manifest directory.' '\nIf you want to work on this GITC client please rerun this ' 'command from the corresponding client under /gitc/', file=sys.stderr) sys.exit(1) if not repo_main: if opt.help: _Usage() if cmd == 'help': _Help(args) if not cmd: _NotInstalled() if cmd == 'init' or cmd == 'gitc-init': if my_git: _SetDefaultsTo(my_git) try: _Init(args, gitc_init=(cmd == 'gitc-init')) except CloneFailure: path = os.path.join(repodir, S_repo) print("fatal: cloning the git-repo repository failed, will remove " "'%s' " % path, file=sys.stderr) shutil.rmtree(path, ignore_errors=True) sys.exit(1) repo_main, rel_repo_dir = _FindRepo() else: _NoCommands(cmd) if my_main: repo_main = my_main ver_str = '.'.join(map(str, VERSION)) me = [sys.executable, repo_main, '--repo-dir=%s' % rel_repo_dir, '--wrapper-version=%s' % ver_str, '--wrapper-path=%s' % wrapper_path, '--'] me.extend(orig_args) me.extend(extra_args) try: if platform.system() == "Windows": sys.exit(subprocess.call(me)) else: os.execv(sys.executable, me) except OSError as e: print("fatal: unable to start %s" % repo_main, file=sys.stderr) print("fatal: %s" % e, file=sys.stderr) sys.exit(148) if __name__ == '__main__': main(sys.argv[1:])