blob: 2fc016ae477dd8ae6ced57e07283d928e2d4f275 [file] [log] [blame]
#!/usr/bin/env python
# Copyright (c) 2015 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Wrapper for updating and calling infra.git tools.
This tool does a two things:
* Maintains a infra.git checkout pinned at "deployed" in the home dir
* Acts as an alias to infra.tools.*
* Acts as an alias to infra.git/cipd/<executable>
"""
# TODO(hinoka,iannucci): Pre-pack infra tools in cipd package with vpython spec.
from __future__ import print_function
import argparse
import sys
import os
import re
import subprocess2 as subprocess
SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
GCLIENT = os.path.join(SCRIPT_DIR, 'gclient.py')
TARGET_DIR = os.path.expanduser(os.path.join('~', '.chrome-infra'))
INFRA_DIR = os.path.join(TARGET_DIR, 'infra')
def get_git_rev(target, branch):
return subprocess.check_output(
['git', 'log', '--format=%B', '-n1', branch], cwd=target)
def need_to_update(branch):
"""Checks to see if we need to update the ~/.chrome-infra/infra checkout."""
try:
cmd = [sys.executable, GCLIENT, 'revinfo']
subprocess.check_call(
cmd, cwd=os.path.join(TARGET_DIR), stdout=subprocess.VOID)
except subprocess.CalledProcessError:
return True # Gclient failed, definitely need to update.
except OSError:
return True # Gclient failed, definitely need to update.
if not os.path.isdir(INFRA_DIR):
return True
local_rev = get_git_rev(INFRA_DIR, 'HEAD')
subprocess.check_call(
['git', 'fetch', 'origin'], cwd=INFRA_DIR,
stdout=subprocess.VOID, stderr=subprocess.STDOUT)
origin_rev = get_git_rev(INFRA_DIR, 'origin/%s' % (branch,))
return origin_rev != local_rev
def ensure_infra(branch):
"""Ensures that infra.git is present in ~/.chrome-infra."""
sys.stderr.write(
'Fetching infra@%s into %s, may take a couple of minutes...' % (
branch, TARGET_DIR))
sys.stderr.flush()
if not os.path.isdir(TARGET_DIR):
os.mkdir(TARGET_DIR)
if not os.path.exists(os.path.join(TARGET_DIR, '.gclient')):
subprocess.check_call(
[sys.executable, os.path.join(SCRIPT_DIR, 'fetch.py'), 'infra'],
cwd=TARGET_DIR,
stdout=subprocess.VOID)
subprocess.check_call(
[sys.executable, GCLIENT, 'sync', '--revision', 'origin/%s' % (branch,)],
cwd=TARGET_DIR,
stdout=subprocess.VOID)
sys.stderr.write(' done.\n')
sys.stderr.flush()
def is_exe(filename):
"""Given a full filepath, return true if the file is an executable."""
if sys.platform.startswith('win'):
return filename.endswith('.exe')
else:
return os.path.isfile(filename) and os.access(filename, os.X_OK)
def get_available_tools():
"""Returns a tuple of (list of infra tools, list of cipd tools)"""
infra_tools = []
cipd_tools = []
starting = os.path.join(TARGET_DIR, 'infra', 'infra', 'tools')
for root, _, files in os.walk(starting):
if '__main__.py' in files:
infra_tools.append(root[len(starting)+1:].replace(os.path.sep, '.'))
cipd = os.path.join(TARGET_DIR, 'infra', 'cipd')
for fn in os.listdir(cipd):
if is_exe(os.path.join(cipd, fn)):
cipd_tools.append(fn)
return (sorted(infra_tools), sorted(cipd_tools))
def usage():
infra_tools, cipd_tools = get_available_tools()
print("""usage: cit.py <name of tool> [args for tool]
Wrapper for maintaining and calling tools in:
"infra.git/run.py infra.tools.*"
"infra.git/cipd/*"
Available infra tools are:""")
for tool in infra_tools:
print(' * %s' % tool)
print("""
Available cipd tools are:""")
for tool in cipd_tools:
print(' * %s' % tool)
def run(args):
if not args:
return usage()
tool_name = args[0]
# Check to see if it is a infra tool first.
infra_dir = os.path.join(
TARGET_DIR, 'infra', 'infra', 'tools', *tool_name.split('.'))
cipd_file = os.path.join(TARGET_DIR, 'infra', 'cipd', tool_name)
if sys.platform.startswith('win'):
cipd_file += '.exe'
if (os.path.isdir(infra_dir)
and os.path.isfile(os.path.join(infra_dir, '__main__.py'))):
cmd = [
sys.executable, os.path.join(TARGET_DIR, 'infra', 'run.py'),
'infra.tools.%s' % tool_name]
elif os.path.isfile(cipd_file) and is_exe(cipd_file):
cmd = [cipd_file]
else:
print('Unknown tool "%s"' % tool_name, file=sys.stderr)
return usage()
# Add the remaining arguments.
cmd.extend(args[1:])
return subprocess.call(cmd)
def main():
parser = argparse.ArgumentParser("Chrome Infrastructure CLI.")
parser.add_argument('-b', '--infra-branch', default='cit',
help="The name of the 'infra' branch to use (default is %(default)s).")
parser.add_argument('args', nargs=argparse.REMAINDER)
args, extras = parser.parse_known_args()
if args.args and args.args[0] == '--':
args.args.pop(0)
if extras:
args.args = extras + args.args
if need_to_update(args.infra_branch):
ensure_infra(args.infra_branch)
return run(args.args)
if __name__ == '__main__':
sys.exit(main())