blob: 56edd0561ef018a4453171247b096f0cb1ec1739 [file] [log] [blame]
Edward Lemurd52b3062019-08-06 17:55:59 +00001#!/usr/bin/env vpython
hinoka@chromium.orgbdc47282015-07-17 22:05:19 +00002# Copyright (c) 2015 The Chromium Authors. All rights reserved.
3# Use of this source code is governed by a BSD-style license that can be
4# found in the LICENSE file.
5
6
7"""Wrapper for updating and calling infra.git tools.
8
9This tool does a two things:
10* Maintains a infra.git checkout pinned at "deployed" in the home dir
11* Acts as an alias to infra.tools.*
hinoka9a0de0b2016-07-14 13:00:00 -070012* Acts as an alias to infra.git/cipd/<executable>
hinoka@chromium.orgbdc47282015-07-17 22:05:19 +000013"""
14
Robert Iannucci5d6b00f2018-01-12 15:43:21 -080015# TODO(hinoka,iannucci): Pre-pack infra tools in cipd package with vpython spec.
hinoka@chromium.orgbdc47282015-07-17 22:05:19 +000016
Raul Tambre80ee78e2019-05-06 22:41:05 +000017from __future__ import print_function
18
dnj@chromium.org8829c522015-10-24 03:25:05 +000019import argparse
hinoka@chromium.orgbdc47282015-07-17 22:05:19 +000020import sys
21import os
hinoka@chromium.orgbdc47282015-07-17 22:05:19 +000022import re
23
Robert Iannucci5d6b00f2018-01-12 15:43:21 -080024import subprocess2 as subprocess
25
hinoka@chromium.orgbdc47282015-07-17 22:05:19 +000026
27SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
28GCLIENT = os.path.join(SCRIPT_DIR, 'gclient.py')
mmoss@chromium.orgc3499712015-11-25 01:04:01 +000029TARGET_DIR = os.path.expanduser(os.path.join('~', '.chrome-infra'))
hinoka@chromium.orgbdc47282015-07-17 22:05:19 +000030INFRA_DIR = os.path.join(TARGET_DIR, 'infra')
31
32
33def get_git_rev(target, branch):
34 return subprocess.check_output(
35 ['git', 'log', '--format=%B', '-n1', branch], cwd=target)
36
37
dnj@chromium.org8829c522015-10-24 03:25:05 +000038def need_to_update(branch):
hinoka@chromium.orgbdc47282015-07-17 22:05:19 +000039 """Checks to see if we need to update the ~/.chrome-infra/infra checkout."""
40 try:
41 cmd = [sys.executable, GCLIENT, 'revinfo']
42 subprocess.check_call(
Robert Iannucci5d6b00f2018-01-12 15:43:21 -080043 cmd, cwd=os.path.join(TARGET_DIR), stdout=subprocess.VOID)
hinoka@chromium.orgbdc47282015-07-17 22:05:19 +000044 except subprocess.CalledProcessError:
45 return True # Gclient failed, definitely need to update.
46 except OSError:
47 return True # Gclient failed, definitely need to update.
48
iannucci@chromium.org3add4b62015-11-17 20:27:56 +000049 if not os.path.isdir(INFRA_DIR):
50 return True
51
hinoka@chromium.orgbdc47282015-07-17 22:05:19 +000052 local_rev = get_git_rev(INFRA_DIR, 'HEAD')
53
54 subprocess.check_call(
55 ['git', 'fetch', 'origin'], cwd=INFRA_DIR,
Robert Iannucci5d6b00f2018-01-12 15:43:21 -080056 stdout=subprocess.VOID, stderr=subprocess.STDOUT)
dnj@chromium.org8829c522015-10-24 03:25:05 +000057 origin_rev = get_git_rev(INFRA_DIR, 'origin/%s' % (branch,))
hinoka@chromium.orgbdc47282015-07-17 22:05:19 +000058 return origin_rev != local_rev
59
60
dnj@chromium.org8829c522015-10-24 03:25:05 +000061def ensure_infra(branch):
hinoka@chromium.orgbdc47282015-07-17 22:05:19 +000062 """Ensures that infra.git is present in ~/.chrome-infra."""
tandrii56396af2016-06-17 09:50:46 -070063 sys.stderr.write(
64 'Fetching infra@%s into %s, may take a couple of minutes...' % (
65 branch, TARGET_DIR))
66 sys.stderr.flush()
hinoka@chromium.orgbdc47282015-07-17 22:05:19 +000067 if not os.path.isdir(TARGET_DIR):
68 os.mkdir(TARGET_DIR)
69 if not os.path.exists(os.path.join(TARGET_DIR, '.gclient')):
70 subprocess.check_call(
71 [sys.executable, os.path.join(SCRIPT_DIR, 'fetch.py'), 'infra'],
72 cwd=TARGET_DIR,
Robert Iannucci5d6b00f2018-01-12 15:43:21 -080073 stdout=subprocess.VOID)
hinoka@chromium.orgbdc47282015-07-17 22:05:19 +000074 subprocess.check_call(
dnj@chromium.org8829c522015-10-24 03:25:05 +000075 [sys.executable, GCLIENT, 'sync', '--revision', 'origin/%s' % (branch,)],
hinoka@chromium.orgbdc47282015-07-17 22:05:19 +000076 cwd=TARGET_DIR,
Robert Iannucci5d6b00f2018-01-12 15:43:21 -080077 stdout=subprocess.VOID)
tandrii56396af2016-06-17 09:50:46 -070078 sys.stderr.write(' done.\n')
79 sys.stderr.flush()
hinoka@chromium.orgbdc47282015-07-17 22:05:19 +000080
81
hinoka9a0de0b2016-07-14 13:00:00 -070082def is_exe(filename):
83 """Given a full filepath, return true if the file is an executable."""
84 if sys.platform.startswith('win'):
85 return filename.endswith('.exe')
86 else:
87 return os.path.isfile(filename) and os.access(filename, os.X_OK)
88
89
hinoka@chromium.orgbdc47282015-07-17 22:05:19 +000090def get_available_tools():
hinoka9a0de0b2016-07-14 13:00:00 -070091 """Returns a tuple of (list of infra tools, list of cipd tools)"""
92 infra_tools = []
93 cipd_tools = []
hinoka@chromium.orgbdc47282015-07-17 22:05:19 +000094 starting = os.path.join(TARGET_DIR, 'infra', 'infra', 'tools')
95 for root, _, files in os.walk(starting):
96 if '__main__.py' in files:
hinoka9a0de0b2016-07-14 13:00:00 -070097 infra_tools.append(root[len(starting)+1:].replace(os.path.sep, '.'))
98 cipd = os.path.join(TARGET_DIR, 'infra', 'cipd')
99 for fn in os.listdir(cipd):
100 if is_exe(os.path.join(cipd, fn)):
101 cipd_tools.append(fn)
102 return (sorted(infra_tools), sorted(cipd_tools))
hinoka@chromium.orgbdc47282015-07-17 22:05:19 +0000103
104
dsansome72decfe2016-08-01 20:55:46 -0700105def usage():
hinoka9a0de0b2016-07-14 13:00:00 -0700106 infra_tools, cipd_tools = get_available_tools()
Raul Tambre80ee78e2019-05-06 22:41:05 +0000107 print("""usage: cit.py <name of tool> [args for tool]
hinoka@chromium.orgbdc47282015-07-17 22:05:19 +0000108
hinoka9a0de0b2016-07-14 13:00:00 -0700109 Wrapper for maintaining and calling tools in:
110 "infra.git/run.py infra.tools.*"
111 "infra.git/cipd/*"
hinoka@chromium.orgbdc47282015-07-17 22:05:19 +0000112
Raul Tambre80ee78e2019-05-06 22:41:05 +0000113 Available infra tools are:""")
hinoka9a0de0b2016-07-14 13:00:00 -0700114 for tool in infra_tools:
Raul Tambre80ee78e2019-05-06 22:41:05 +0000115 print(' * %s' % tool)
hinoka@chromium.orgbdc47282015-07-17 22:05:19 +0000116
Raul Tambre80ee78e2019-05-06 22:41:05 +0000117 print("""
118 Available cipd tools are:""")
hinoka9a0de0b2016-07-14 13:00:00 -0700119 for tool in cipd_tools:
Raul Tambre80ee78e2019-05-06 22:41:05 +0000120 print(' * %s' % tool)
hinoka9a0de0b2016-07-14 13:00:00 -0700121
122
dsansome72decfe2016-08-01 20:55:46 -0700123def run(args):
124 if not args:
125 return usage()
126
127 tool_name = args[0]
128 # Check to see if it is a infra tool first.
129 infra_dir = os.path.join(
130 TARGET_DIR, 'infra', 'infra', 'tools', *tool_name.split('.'))
131 cipd_file = os.path.join(TARGET_DIR, 'infra', 'cipd', tool_name)
132 if sys.platform.startswith('win'):
133 cipd_file += '.exe'
134 if (os.path.isdir(infra_dir)
135 and os.path.isfile(os.path.join(infra_dir, '__main__.py'))):
136 cmd = [
137 sys.executable, os.path.join(TARGET_DIR, 'infra', 'run.py'),
138 'infra.tools.%s' % tool_name]
139 elif os.path.isfile(cipd_file) and is_exe(cipd_file):
140 cmd = [cipd_file]
141 else:
Raul Tambre80ee78e2019-05-06 22:41:05 +0000142 print('Unknown tool "%s"' % tool_name, file=sys.stderr)
dsansome72decfe2016-08-01 20:55:46 -0700143 return usage()
144
145 # Add the remaining arguments.
146 cmd.extend(args[1:])
147 return subprocess.call(cmd)
148
hinoka@chromium.orgbdc47282015-07-17 22:05:19 +0000149
150def main():
dnj@chromium.org8829c522015-10-24 03:25:05 +0000151 parser = argparse.ArgumentParser("Chrome Infrastructure CLI.")
Ryan Tsengde1ed192017-03-07 18:43:43 -0800152 parser.add_argument('-b', '--infra-branch', default='cit',
dnj@chromium.org8829c522015-10-24 03:25:05 +0000153 help="The name of the 'infra' branch to use (default is %(default)s).")
154 parser.add_argument('args', nargs=argparse.REMAINDER)
155
156 args, extras = parser.parse_known_args()
157 if args.args and args.args[0] == '--':
158 args.args.pop(0)
159 if extras:
160 args.args = extras + args.args
161
162 if need_to_update(args.infra_branch):
163 ensure_infra(args.infra_branch)
164 return run(args.args)
hinoka@chromium.orgbdc47282015-07-17 22:05:19 +0000165
166if __name__ == '__main__':
167 sys.exit(main())