-
Notifications
You must be signed in to change notification settings - Fork 9
/
cit.py
executable file
·173 lines (135 loc) · 5.19 KB
/
cit.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
#!/usr/bin/env python3
# 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.DEVNULL)
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.DEVNULL, 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.DEVNULL)
subprocess.check_call(
[sys.executable, GCLIENT, 'sync', '--revision', 'origin/%s' % (branch,)],
cwd=TARGET_DIR,
stdout=subprocess.DEVNULL)
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')
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(INFRA_DIR, '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(INFRA_DIR, '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, 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()
env = os.environ
tool_name = args[0]
# Check to see if it is a infra tool first.
tool_dir = os.path.join(
INFRA_DIR, 'infra', 'tools', *tool_name.split('.'))
cipd_file = os.path.join(INFRA_DIR, 'cipd', tool_name)
if sys.platform.startswith('win'):
cipd_file += '.exe'
if (os.path.isdir(tool_dir)
and os.path.isfile(os.path.join(tool_dir, '__main__.py'))):
cmd = [
'vpython', '-vpython-spec', os.path.join(INFRA_DIR, '.vpython'),
'-m', 'infra.tools.%s' % tool_name]
# Augment PYTHONPATH so that infra.tools.<tool_name> can be found without
# running from that directory, which would mess up any relative paths passed
# to the tool.
env['PYTHONPATH'] = INFRA_DIR + os.pathsep + env['PYTHONPATH']
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, env=env)
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())