X-Git-Url: https://git.wh0rd.org/?a=blobdiff_plain;f=.bin%2Fcros-repo;h=d8f5b5e270fba8d98764c70c721eca31bbdf70ad;hb=be550c8e495a41eb0bca68807cab152e9e80d2ca;hp=d6c6de1bea169a09d59169eb2cd3b224a1d09561;hpb=3c3472397719ec968f76774e15f01139b96c90b7;p=home.git diff --git a/.bin/cros-repo b/.bin/cros-repo index d6c6de1..d8f5b5e 100755 --- a/.bin/cros-repo +++ b/.bin/cros-repo @@ -1,27 +1,179 @@ -#!/bin/sh -cd ~/chromiumos - -usage() { - cat <<-EOF - Usage: repo-cros [command opts] - - Commands: - int switch to internal tree - ext switch to external tree - -b switch branches - EOF - exit ${1:-1} -} -[[ $# -eq 0 ]] && usage - -vexec() { echo "$@"; exec "$@"; } - -while [[ $# -gt 0 ]] ; do - case $1 in - int) vexec repo init -u ssh://gerrit-int.chromium.org:29419/chromeos/manifest-internal.git --repo-url='http://git.chromium.org/external/repo.git' ;; - ext) vexec repo init -u http://git.chromium.org/chromiumos/manifest.git --repo-url http://git.chromium.org/external/repo.git ;; - -b) vexec repo init -b $2 ;; - *) usage ;; - esac -done -exit 0 +#!/usr/bin/python3 +# -*- coding: utf-8 -*- + +"""Wrapper for syncing CrOS code. + +Actions: + depot_tools clone depot_tools tree + int switch to internal tree + ext switch to external tree + +Operates on the repo in the cwd. +""" + +import argparse +import fnmatch +import os +import subprocess +import sys + + +REPO_URL = 'https://chromium.googlesource.com/external/repo' +INT_MANIFEST = 'https://chrome-internal.googlesource.com/chromeos/manifest-internal' +EXT_MANIFEST = 'https://chromium.googlesource.com/chromiumos/manifest' + + +def run(cmd, **kwargs): + """Run with command tracing.""" + # Python 3.6 doesn't support capture_output. + if sys.version_info < (3, 7): + capture_output = kwargs.pop('capture_output', None) + if capture_output: + assert 'stdout' not in kwargs and 'stderr' not in kwargs + kwargs['stdout'] = subprocess.PIPE + kwargs['stderr'] = subprocess.PIPE + + print(kwargs.get('cwd', os.getcwd())) + print(' '.join(cmd)) + return subprocess.run(cmd, **kwargs) + + +def expand_branch(opts): + """Support branch shortnames.""" + url = INT_MANIFEST if opts.action == 'int' else EXT_MANIFEST + ret = run(['git', 'ls-remote', url, 'refs/heads/*'], capture_output=True, encoding='utf-8') + branches = [x.split()[-1].split('/')[-1] for x in ret.stdout.splitlines()] + ret = [] + for branch in branches: + if branch.lower() == opts.branch.lower(): + ret = [branch] + break + elif fnmatch.fnmatch(branch.lower(), f'*{opts.branch.lower()}*'): + ret.append(branch) + if not ret: + print(f'error: could not match branch {opts.branch}', file=sys.stderr) + print(f'Available branches:\n{" ".join(sorted(branches))}', file=sys.stderr) + sys.exit(1) + if len(ret) > 1: + print(f'error: too many branches match {opts.branch}:\n{" ".join(sorted(ret))}', + file=sys.stderr) + sys.exit(1) + print(f'Expanded branch {opts.branch} into {ret[0]}') + return ret[0] + + +def get_repo_topdir(opts): + """Find the top dir of this repo client checkout.""" + topdir = os.getcwd() + while True: + rdir = os.path.join(topdir, '.repo') + if os.path.exists(rdir): + break + topdir = os.path.dirname(topdir) + assert topdir != '/' + return topdir + + +def set_git_config(opts): + """Set .git/config settings in all the repos.""" + topdir = get_repo_topdir(opts) + rdir = os.path.join(topdir, '.repo') + + def gcfg(path, *args): + cmd = ['git', f'--git-dir={path}', 'config', 'user.email'] + list(args) + ret = run(cmd, capture_output=True, encoding='utf-8') + return ret.stdout.strip() + + current_email = gcfg(os.path.join(rdir, 'manifests.git')) + if current_email == opts.email: + return + + print(f'Setting e-mail to {opts.email}') + for root, dirs, files in os.walk(rdir): + if root.endswith('.git') and not os.path.islink(os.path.join(root, 'config')): + gcfg(root, opts.email) + del dirs[:] + + +def init_repo(opts): + """Initialize CrOS checkout.""" + cmd = ['repo', 'init'] + + if opts.action == 'int': + cmd += ['-u', INT_MANIFEST] + cmd += ['--repo-url', REPO_URL] + elif opts.action == 'ext': + cmd += ['-u', EXT_MANIFEST] + cmd += ['--repo-url', REPO_URL] + + if opts.ref and os.path.realpath(opts.ref) != os.path.realpath(get_repo_topdir(opts)): + cmd += ['--reference', opts.ref] + + if opts.manifest: + cmd += ['-m', opts.manifest] + + if opts.group: + cmd += ['-g', opts.group] + + if opts.branch: + branch = expand_branch(opts) + cmd += ['-b', branch] + + ret = run(cmd) + if ret.returncode: + return ret.returncode + + set_git_config(opts) + + print('\ncros-repo: all done') + return 0 + + +def clone_depot_tools(): + """Clone depot_tools repo.""" + ret = run(['git', 'clone', 'https://chromium.googlesource.com/chromium/tools/depot_tools']) + return ret.returncode + + +def get_parser(): + """Get command line parser.""" + parser = argparse.ArgumentParser( + description=__doc__, + formatter_class=argparse.RawDescriptionHelpFormatter) + parser.add_argument('-b', '--branch', + help='Switch branches (use "main" to get to ToT)') + parser.add_argument('-r', '--ref', '--reference', default='~/chromiumos/', + help='Patch to reference repo (default: %(default)s)') + parser.add_argument('-g', '--group', + help='Manifest group to use (e.g. "minilayout")') + parser.add_argument('-m', '--manifest', + help='Manifest file name to use (e.g. "full.xml")') + parser.add_argument('-e', '--email', default='vapier@chromium.org', + help='E-mail address to force (default: %(default)s)') + parser.add_argument('action', nargs='?', + choices={'depot_tools', 'dt', 'int', 'ext'}, + help='What to do!') + return parser + + +def main(argv): + """The main func.""" + parser = get_parser() + opts = parser.parse_args(argv) + if opts.manifest: + if '/' in opts.manifest: + parser.error('manifest should be basename like "full.xml"') + if opts.manifest.endswith('.xml'): + opts.manifest = opts.manifest[:-4] + opts.manifest += '.xml' + if opts.ref: + opts.ref = os.path.expanduser(opts.ref) + + if opts.action in {'depot_tools', 'dt'}: + return clone_depot_tools() + else: + return init_repo(opts) + + +if __name__ == '__main__': + sys.exit(main(sys.argv[1:]))