blob: e255099ec03feddcb9e9c0b4b1c6c6150ad9e9e3 [file] [log] [blame]
halcanary@google.com31fdb922014-01-06 19:50:22 +00001#!/usr/bin/python2
2
3# Copyright 2014 Google Inc.
4#
5# Use of this source code is governed by a BSD-style license that can be
6# found in the LICENSE file.
7
8"""Skia's Chromium DEPS roll script.
9
10This script:
11- searches through the last N Skia git commits to find out the hash that is
12 associated with the SVN revision number.
13- creates a new branch in the Chromium tree, modifies the DEPS file to
14 point at the given Skia commit, commits, uploads to Rietveld, and
15 deletes the local copy of the branch.
16- creates a whitespace-only commit and uploads that to to Rietveld.
17- returns the Chromium tree to its previous state.
18
commit-bot@chromium.org0ed90022014-01-30 22:12:30 +000019To specify the location of the git executable, set the GIT_EXECUTABLE
20environment variable.
21
halcanary@google.com31fdb922014-01-06 19:50:22 +000022Usage:
23 %prog -c CHROMIUM_PATH -r REVISION [OPTIONAL_OPTIONS]
24"""
25
26
27import optparse
28import os
29import re
30import shutil
halcanary@google.com31fdb922014-01-06 19:50:22 +000031import sys
32import tempfile
33
Eric Borenbb0ef0a2014-06-25 11:13:27 -040034import fix_pythonpath # pylint: disable=W0611
35from common.py.utils import git_utils
36from common.py.utils import misc
37from common.py.utils import shell_utils
commit-bot@chromium.org0ed90022014-01-30 22:12:30 +000038
halcanary@google.com31fdb922014-01-06 19:50:22 +000039
borenet@google.com17bb9512014-01-27 18:08:55 +000040DEFAULT_BOTS_LIST = [
borenet3da21d22014-06-25 08:40:58 -070041 'android_clang_dbg',
42 'android_dbg',
43 'android_rel',
44 'cros_daisy',
45 'linux',
46 'linux_asan',
47 'linux_chromeos',
48 'linux_chromeos_asan',
49 'linux_chromium_gn_dbg',
50 'linux_gpu',
51 'linux_layout',
52 'linux_layout_rel',
53 'mac',
54 'mac_asan',
55 'mac_gpu',
56 'mac_layout',
57 'mac_layout_rel',
58 'win',
59 'win_gpu',
60 'win_layout',
61 'win_layout_rel',
borenet@google.com17bb9512014-01-27 18:08:55 +000062]
63
Eric Borenbb0ef0a2014-06-25 11:13:27 -040064REGEXP_SKIA_REVISION = (
65 r'^ "skia_revision": "(?P<revision>[0-9a-fA-F]{2,40})",$')
66
borenet@google.com17bb9512014-01-27 18:08:55 +000067
halcanary@google.com31fdb922014-01-06 19:50:22 +000068class DepsRollConfig(object):
borenet3da21d22014-06-25 08:40:58 -070069 """Contains configuration options for this module.
halcanary@google.com31fdb922014-01-06 19:50:22 +000070
borenet3da21d22014-06-25 08:40:58 -070071 Attributes:
72 chromium_path: (string) path to a local chromium git repository.
73 save_branches: (boolean) iff false, delete temporary branches.
74 verbose: (boolean) iff false, suppress the output from git-cl.
75 skip_cl_upload: (boolean)
76 cl_bot_list: (list of strings)
77 """
78
79 # pylint: disable=I0011,R0903,R0902
80 def __init__(self, options=None):
81 if not options:
82 options = DepsRollConfig.GetOptionParser()
83 # pylint: disable=I0011,E1103
84 self.verbose = options.verbose
85 self.save_branches = not options.delete_branches
86 self.chromium_path = options.chromium_path
87 self.skip_cl_upload = options.skip_cl_upload
88 # Split and remove empty strigns from the bot list.
89 self.cl_bot_list = [bot for bot in options.bots.split(',') if bot]
90 self.default_branch_name = 'autogenerated_deps_roll_branch'
91 self.reviewers_list = ','.join([
92 # 'rmistry@google.com',
93 # 'reed@google.com',
94 # 'bsalomon@google.com',
95 # 'robertphillips@google.com',
96 ])
97 self.cc_list = ','.join([
98 # 'skia-team@google.com',
99 ])
100
101 @staticmethod
102 def GetOptionParser():
103 # pylint: disable=I0011,C0103
104 """Returns an optparse.OptionParser object.
105
106 Returns:
107 An optparse.OptionParser object.
108
109 Called by the main() function.
halcanary@google.com31fdb922014-01-06 19:50:22 +0000110 """
borenet3da21d22014-06-25 08:40:58 -0700111 option_parser = optparse.OptionParser(usage=__doc__)
112 # Anyone using this script on a regular basis should set the
113 # CHROMIUM_CHECKOUT_PATH environment variable.
114 option_parser.add_option(
115 '-c', '--chromium_path', help='Path to local Chromium Git'
116 ' repository checkout, defaults to CHROMIUM_CHECKOUT_PATH'
117 ' if that environment variable is set.',
118 default=os.environ.get('CHROMIUM_CHECKOUT_PATH'))
119 option_parser.add_option(
120 '-r', '--revision', default=None,
121 help='The Skia Git commit hash.')
halcanary@google.com31fdb922014-01-06 19:50:22 +0000122
borenet3da21d22014-06-25 08:40:58 -0700123 option_parser.add_option(
124 '', '--delete_branches', help='Delete the temporary branches',
125 action='store_true', dest='delete_branches', default=False)
126 option_parser.add_option(
127 '', '--verbose', help='Do not suppress the output from `git cl`.',
128 action='store_true', dest='verbose', default=False)
129 option_parser.add_option(
130 '', '--skip_cl_upload', help='Skip the cl upload step; useful'
131 ' for testing.',
132 action='store_true', default=False)
halcanary@google.com31fdb922014-01-06 19:50:22 +0000133
borenet3da21d22014-06-25 08:40:58 -0700134 default_bots_help = (
135 'Comma-separated list of bots, defaults to a list of %d bots.'
136 ' To skip `git cl try`, set this to an empty string.'
137 % len(DEFAULT_BOTS_LIST))
138 default_bots = ','.join(DEFAULT_BOTS_LIST)
139 option_parser.add_option(
140 '', '--bots', help=default_bots_help, default=default_bots)
halcanary@google.com31fdb922014-01-06 19:50:22 +0000141
borenet3da21d22014-06-25 08:40:58 -0700142 return option_parser
halcanary@google.com31fdb922014-01-06 19:50:22 +0000143
144
halcanary@google.com31fdb922014-01-06 19:50:22 +0000145class DepsRollError(Exception):
borenet3da21d22014-06-25 08:40:58 -0700146 """Exceptions specific to this module."""
147 pass
halcanary@google.com31fdb922014-01-06 19:50:22 +0000148
149
Eric Borenbb0ef0a2014-06-25 11:13:27 -0400150def change_skia_deps(revision, depspath):
borenet3da21d22014-06-25 08:40:58 -0700151 """Update the DEPS file.
halcanary@google.com31fdb922014-01-06 19:50:22 +0000152
borenet3da21d22014-06-25 08:40:58 -0700153 Modify the skia_revision entry in the given DEPS file.
halcanary@google.com31fdb922014-01-06 19:50:22 +0000154
borenet3da21d22014-06-25 08:40:58 -0700155 Args:
156 revision: (string) Skia commit hash.
157 depspath: (string) path to DEPS file.
158 """
159 temp_file = tempfile.NamedTemporaryFile(delete=False,
160 prefix='skia_DEPS_ROLL_tmp_')
161 try:
162 deps_regex_rev = re.compile(REGEXP_SKIA_REVISION)
163 deps_regex_rev_repl = ' "skia_revision": "%s",' % revision
halcanary@google.com31fdb922014-01-06 19:50:22 +0000164
borenet3da21d22014-06-25 08:40:58 -0700165 with open(depspath, 'r') as input_stream:
166 for line in input_stream:
167 line = deps_regex_rev.sub(deps_regex_rev_repl, line)
168 temp_file.write(line)
169 finally:
170 temp_file.close()
171 shutil.move(temp_file.name, depspath)
halcanary@google.com31fdb922014-01-06 19:50:22 +0000172
173
Eric Borenbb0ef0a2014-06-25 11:13:27 -0400174def submit_tries(bots_to_run, dry_run=False):
borenet3da21d22014-06-25 08:40:58 -0700175 """Submit try requests for the current branch on the given bots.
commit-bot@chromium.org0ed90022014-01-30 22:12:30 +0000176
borenet3da21d22014-06-25 08:40:58 -0700177 Args:
178 bots_to_run: (list of strings) bots to request.
179 dry_run: (bool) whether to actually submit the try request.
180 """
181 git_try = [
182 git_utils.GIT, 'cl', 'try', '-m', 'tryserver.chromium']
183 git_try.extend([arg for bot in bots_to_run for arg in ('-b', bot)])
commit-bot@chromium.org0ed90022014-01-30 22:12:30 +0000184
borenet3da21d22014-06-25 08:40:58 -0700185 if dry_run:
186 space = ' '
187 print 'You should call:'
188 print space, git_try
189 print
190 else:
191 shell_utils.run(git_try)
commit-bot@chromium.org0ed90022014-01-30 22:12:30 +0000192
193
Eric Borenbb0ef0a2014-06-25 11:13:27 -0400194def roll_deps(config, revision):
borenet3da21d22014-06-25 08:40:58 -0700195 """Upload changed DEPS and a whitespace change.
halcanary@google.com31fdb922014-01-06 19:50:22 +0000196
borenet3da21d22014-06-25 08:40:58 -0700197 Given the correct git_hash, create two Reitveld issues.
halcanary@google.com31fdb922014-01-06 19:50:22 +0000198
borenet3da21d22014-06-25 08:40:58 -0700199 Args:
200 config: (roll_deps.DepsRollConfig) object containing options.
201 revision: (string) Skia Git hash.
halcanary@google.com31fdb922014-01-06 19:50:22 +0000202
borenet3da21d22014-06-25 08:40:58 -0700203 Returns:
204 a tuple containing textual description of the two issues.
halcanary@google.com31fdb922014-01-06 19:50:22 +0000205
borenet3da21d22014-06-25 08:40:58 -0700206 Raises:
207 OSError: failed to execute git or git-cl.
208 subprocess.CalledProcessError: git returned unexpected status.
209 """
210 with misc.ChDir(config.chromium_path, verbose=config.verbose):
211 git_utils.Fetch()
212 output = shell_utils.run([git_utils.GIT, 'show', 'origin/master:DEPS'],
213 log_in_real_time=False).rstrip()
214 match = re.search(REGEXP_SKIA_REVISION, output, flags=re.MULTILINE)
215 old_revision = None
216 if match:
217 old_revision = match.group('revision')
218 assert old_revision
halcanary@google.com8c5d2c12014-01-08 21:29:34 +0000219
borenet3da21d22014-06-25 08:40:58 -0700220 master_hash = git_utils.FullHash('origin/master').rstrip()
halcanary@google.com8c5d2c12014-01-08 21:29:34 +0000221
borenet3da21d22014-06-25 08:40:58 -0700222 # master_hash[8] gives each whitespace CL a unique name.
223 branch = 'control_%s' % master_hash[:8]
224 message = ('whitespace change %s\n\n'
225 'Chromium base revision: %s\n\n'
226 'This CL was created by Skia\'s roll_deps.py script.\n'
227 ) % (master_hash[:8], master_hash[:8])
228 with git_utils.GitBranch(branch, message,
229 delete_when_finished=not config.save_branches,
230 upload=not config.skip_cl_upload
231 ) as whitespace_branch:
232 branch = git_utils.GetCurrentBranch()
233 with open(os.path.join('build', 'whitespace_file.txt'), 'a') as f:
234 f.write('\nCONTROL\n')
halcanary@google.com8c5d2c12014-01-08 21:29:34 +0000235
borenet3da21d22014-06-25 08:40:58 -0700236 control_url = whitespace_branch.commit_and_upload()
237 if config.cl_bot_list:
238 submit_tries(config.cl_bot_list, dry_run=config.skip_cl_upload)
239 whitespace_cl = control_url
240 if config.save_branches:
241 whitespace_cl += '\n branch: %s' % branch
halcanary@google.com31fdb922014-01-06 19:50:22 +0000242
borenet3da21d22014-06-25 08:40:58 -0700243 branch = 'roll_%s_%s' % (revision, master_hash[:8])
244 message = (
245 'roll skia DEPS to %s\n\n'
246 'Chromium base revision: %s\n'
247 'Old Skia revision: %s\n'
248 'New Skia revision: %s\n'
249 'Control CL: %s\n\n'
250 'This CL was created by Skia\'s roll_deps.py script.\n\n'
251 'Bypassing commit queue trybots:\n'
252 'NOTRY=true\n'
253 % (revision, master_hash[:8],
254 old_revision[:8], revision[:8], control_url))
255 with git_utils.GitBranch(branch, message,
256 delete_when_finished=not config.save_branches,
257 upload=not config.skip_cl_upload
258 ) as roll_branch:
259 change_skia_deps(revision, 'DEPS')
260 deps_url = roll_branch.commit_and_upload()
261 if config.cl_bot_list:
262 submit_tries(config.cl_bot_list, dry_run=config.skip_cl_upload)
263 deps_cl = deps_url
264 if config.save_branches:
265 deps_cl += '\n branch: %s' % branch
halcanary@google.com8c5d2c12014-01-08 21:29:34 +0000266
borenet3da21d22014-06-25 08:40:58 -0700267 return deps_cl, whitespace_cl
halcanary@google.com31fdb922014-01-06 19:50:22 +0000268
269
halcanary@google.com31fdb922014-01-06 19:50:22 +0000270def main(args):
borenet3da21d22014-06-25 08:40:58 -0700271 """main function; see module-level docstring and GetOptionParser help.
halcanary@google.com31fdb922014-01-06 19:50:22 +0000272
borenet3da21d22014-06-25 08:40:58 -0700273 Args:
274 args: sys.argv[1:]-type argument list.
275 """
276 option_parser = DepsRollConfig.GetOptionParser()
277 options = option_parser.parse_args(args)[0]
halcanary@google.com31fdb922014-01-06 19:50:22 +0000278
borenet3da21d22014-06-25 08:40:58 -0700279 if not options.revision:
280 option_parser.error('Must specify a revision.')
281 if not options.chromium_path:
282 option_parser.error('Must specify chromium_path.')
283 if not os.path.isdir(options.chromium_path):
284 option_parser.error('chromium_path must be a directory.')
commit-bot@chromium.org0ed90022014-01-30 22:12:30 +0000285
borenet3da21d22014-06-25 08:40:58 -0700286 config = DepsRollConfig(options)
287 shell_utils.VERBOSE = options.verbose
288 deps_issue, whitespace_issue = roll_deps(config, options.revision)
Eric Borenbb0ef0a2014-06-25 11:13:27 -0400289
borenet3da21d22014-06-25 08:40:58 -0700290 if deps_issue and whitespace_issue:
291 print 'DEPS roll:\n %s\n' % deps_issue
292 print 'Whitespace change:\n %s\n' % whitespace_issue
293 else:
294 print >> sys.stderr, 'No issues created.'
halcanary@google.com31fdb922014-01-06 19:50:22 +0000295
296
297if __name__ == '__main__':
borenet3da21d22014-06-25 08:40:58 -0700298 main(sys.argv[1:])