Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(961)

Side by Side Diff: tools/autoroller/roll_chromium_revision.py

Issue 2570603003: Autoroller: Support for rolling individual DEPS entries. (Closed)
Patch Set: Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 #!/usr/bin/env python 1 #!/usr/bin/env python
2 # Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. 2 # Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
3 # 3 #
4 # Use of this source code is governed by a BSD-style license 4 # Use of this source code is governed by a BSD-style license
5 # that can be found in the LICENSE file in the root of the source 5 # that can be found in the LICENSE file in the root of the source
6 # tree. An additional intellectual property rights grant can be found 6 # tree. An additional intellectual property rights grant can be found
7 # in the file PATENTS. All contributing project authors may 7 # in the file PATENTS. All contributing project authors may
8 # be found in the AUTHORS file in the root of the source tree. 8 # be found in the AUTHORS file in the root of the source tree.
9 9
10 """Script to roll chromium_revision in the WebRTC DEPS file.""" 10 """Script to roll chromium_revision in the WebRTC DEPS file."""
11 11
12 import argparse 12 import argparse
13 import base64 13 import base64
14 import collections 14 import collections
15 import logging 15 import logging
16 import os 16 import os
17 import re 17 import re
18 import subprocess 18 import subprocess
19 import sys 19 import sys
20 import urllib 20 import urllib
21 21
22 22
23 # Skip these dependencies (list without solution name prefix).
phoglund 2016/12/13 09:57:02 It's not entirely clear what "skipping" means in t
kjellander_webrtc 2016/12/13 10:25:00 Done.
24 SKIPPED_AUTOROLL_DEPS = [
25 'src/third_party/gflags/src',
26 'src/third_party/winsdk_samples/src',
27 ]
28
29 WEBRTC_URL = 'https://chromium.googlesource.com/external/webrtc'
23 CHROMIUM_SRC_URL = 'https://chromium.googlesource.com/chromium/src' 30 CHROMIUM_SRC_URL = 'https://chromium.googlesource.com/chromium/src'
24 CHROMIUM_COMMIT_TEMPLATE = CHROMIUM_SRC_URL + '/+/%s' 31 CHROMIUM_COMMIT_TEMPLATE = CHROMIUM_SRC_URL + '/+/%s'
25 CHROMIUM_LOG_TEMPLATE = CHROMIUM_SRC_URL + '/+log/%s' 32 CHROMIUM_LOG_TEMPLATE = CHROMIUM_SRC_URL + '/+log/%s'
26 CHROMIUM_FILE_TEMPLATE = CHROMIUM_SRC_URL + '/+/%s/%s' 33 CHROMIUM_FILE_TEMPLATE = CHROMIUM_SRC_URL + '/+/%s/%s'
27 34
28 COMMIT_POSITION_RE = re.compile('^Cr-Commit-Position: .*#([0-9]+).*$') 35 COMMIT_POSITION_RE = re.compile('^Cr-Commit-Position: .*#([0-9]+).*$')
29 CLANG_REVISION_RE = re.compile(r'^CLANG_REVISION = \'(\d+)\'$') 36 CLANG_REVISION_RE = re.compile(r'^CLANG_REVISION = \'(\d+)\'$')
30 ROLL_BRANCH_NAME = 'roll_chromium_revision' 37 ROLL_BRANCH_NAME = 'roll_chromium_revision'
31 38
32 SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__)) 39 SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
33 CHECKOUT_ROOT_DIR = os.path.realpath(os.path.join(SCRIPT_DIR, os.pardir, 40 CHECKOUT_SRC_DIR = os.path.realpath(os.path.join(SCRIPT_DIR, os.pardir,
34 os.pardir)) 41 os.pardir))
35 sys.path.append(CHECKOUT_ROOT_DIR) 42 CHECKOUT_ROOT_DIR = os.path.realpath(os.path.join(CHECKOUT_SRC_DIR, os.pardir))
43 CHROMIUM_CHECKOUT_SRC_DIR = os.path.join(CHECKOUT_SRC_DIR, 'chromium', 'src')
44
45 sys.path.append(CHECKOUT_SRC_DIR)
36 import setup_links 46 import setup_links
37 47
38 sys.path.append(os.path.join(CHECKOUT_ROOT_DIR, 'build')) 48 sys.path.append(os.path.join(CHECKOUT_SRC_DIR, 'build'))
39 import find_depot_tools 49 import find_depot_tools
40 find_depot_tools.add_depot_tools_to_path() 50 find_depot_tools.add_depot_tools_to_path()
41 from gclient import GClientKeywords 51 from gclient import GClientKeywords
42 52
43 CLANG_UPDATE_SCRIPT_URL_PATH = 'tools/clang/scripts/update.py' 53 CLANG_UPDATE_SCRIPT_URL_PATH = 'tools/clang/scripts/update.py'
44 CLANG_UPDATE_SCRIPT_LOCAL_PATH = os.path.join('tools', 'clang', 'scripts', 54 CLANG_UPDATE_SCRIPT_LOCAL_PATH = os.path.join('tools', 'clang', 'scripts',
45 'update.py') 55 'update.py')
46 56
47 DepsEntry = collections.namedtuple('DepsEntry', 'path url revision') 57 DepsEntry = collections.namedtuple('DepsEntry', 'path url revision')
48 ChangedDep = collections.namedtuple('ChangedDep', 58 ChangedDep = collections.namedtuple('ChangedDep',
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
87 97
88 def _RunCommand(command, working_dir=None, ignore_exit_code=False, 98 def _RunCommand(command, working_dir=None, ignore_exit_code=False,
89 extra_env=None): 99 extra_env=None):
90 """Runs a command and returns the output from that command. 100 """Runs a command and returns the output from that command.
91 101
92 If the command fails (exit code != 0), the function will exit the process. 102 If the command fails (exit code != 0), the function will exit the process.
93 103
94 Returns: 104 Returns:
95 A tuple containing the stdout and stderr outputs as strings. 105 A tuple containing the stdout and stderr outputs as strings.
96 """ 106 """
97 working_dir = working_dir or CHECKOUT_ROOT_DIR 107 working_dir = working_dir or CHECKOUT_SRC_DIR
98 logging.debug('CMD: %s CWD: %s', ' '.join(command), working_dir) 108 logging.debug('CMD: %s CWD: %s', ' '.join(command), working_dir)
99 env = os.environ.copy() 109 env = os.environ.copy()
100 if extra_env: 110 if extra_env:
101 assert all(type(value) == str for value in extra_env.values()) 111 assert all(type(value) == str for value in extra_env.values())
102 logging.debug('extra env: %s', extra_env) 112 logging.debug('extra env: %s', extra_env)
103 env.update(extra_env) 113 env.update(extra_env)
104 p = subprocess.Popen(command, stdout=subprocess.PIPE, 114 p = subprocess.Popen(command, stdout=subprocess.PIPE,
105 stderr=subprocess.PIPE, env=env, 115 stderr=subprocess.PIPE, env=env,
106 cwd=working_dir, universal_newlines=True) 116 cwd=working_dir, universal_newlines=True)
107 std_output = p.stdout.read() 117 std_output = p.stdout.read()
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
186 result.append(depsentry) 196 result.append(depsentry)
187 else: 197 else:
188 parts = path.split('/') 198 parts = path.split('/')
189 if all(part == parts[i] 199 if all(part == parts[i]
190 for i, part in enumerate(dir_path.split('/'))): 200 for i, part in enumerate(dir_path.split('/'))):
191 result.append(depsentry) 201 result.append(depsentry)
192 return result 202 return result
193 203
194 204
195 def BuildDepsentryDict(deps_dict): 205 def BuildDepsentryDict(deps_dict):
196 """Builds a dict of DepsEntry object from a raw parsed deps dict.""" 206 """Builds a dict of paths to DepsEntry objects from a raw parsed deps dict."""
197 result = {} 207 result = {}
198 def AddDepsEntries(deps_subdict): 208 def AddDepsEntries(deps_subdict):
199 for path, deps_url in deps_subdict.iteritems(): 209 for path, deps_url in deps_subdict.iteritems():
200 if not result.has_key(path): 210 if not result.has_key(path):
201 url, revision = deps_url.split('@') if deps_url else (None, None) 211 url, revision = deps_url.split('@') if deps_url else (None, None)
202 result[path] = DepsEntry(path, url, revision) 212 result[path] = DepsEntry(path, url, revision)
203 213
204 AddDepsEntries(deps_dict['deps']) 214 AddDepsEntries(deps_dict['deps'])
205 for deps_os in ['win', 'mac', 'unix', 'android', 'ios', 'unix']: 215 for deps_os in ['win', 'mac', 'unix', 'android', 'ios', 'unix']:
206 AddDepsEntries(deps_dict['deps_os'].get(deps_os, {})) 216 AddDepsEntries(deps_dict.get('deps_os', {}).get(deps_os, {}))
207 return result 217 return result
208 218
209 219
210 def CalculateChangedDeps(current_deps, new_deps): 220 def CalculateChangedDeps(webrtc_deps, old_cr_deps, new_cr_deps):
221 """
222 Calculate changed deps entries based on:
223 1. Entries defined in the WebRTC DEPS file - rolls them to the same revision
224 as the new_cr_deps dict, if available. Otherwise HEAD unless the deps is
phoglund 2016/12/13 09:57:02 I find this confusing. When exactly is something r
kjellander_webrtc 2016/12/13 10:25:00 I clarified it now.
225 configured to be skipped.
226 2. Entried present in the setup_links.py file. If the dir has changed between
phoglund 2016/12/13 09:57:02 Nit: entries
kjellander_webrtc 2016/12/13 10:25:00 Done.
227 old_cr_deps and new_cr_deps, it is considered changed.
228
229 Returns:
230 A list of ChangedDep objects representing the changed deps.
231 """
232 return sorted(CalculateChangedDepsProper(webrtc_deps, new_cr_deps) +
233 CalculateChangedDepsLegacy(old_cr_deps, new_cr_deps))
234
235
236 def CalculateChangedDepsProper(webrtc_deps, new_cr_deps):
211 result = [] 237 result = []
212 current_entries = BuildDepsentryDict(current_deps) 238 webrtc_entries = BuildDepsentryDict(webrtc_deps)
213 new_entries = BuildDepsentryDict(new_deps) 239 new_cr_entries = BuildDepsentryDict(new_cr_deps)
240 for path, webrtc_deps_entry in webrtc_entries.iteritems():
241 if path in SKIPPED_AUTOROLL_DEPS:
242 continue
243 cr_deps_entry = new_cr_entries.get(path)
244 if cr_deps_entry:
245 # Use the revision from Chromium's DEPS file.
246 new_rev = cr_deps_entry.revision
247 assert webrtc_deps_entry.url == cr_deps_entry.url, (
248 'WebRTC DEPS entry %s has a different URL (%s) than Chromium (%s).' %
249 (path, webrtc_deps_entry.url, cr_deps_entry.url))
250 else:
251 # Use the HEAD of the deps repo.
252 stdout, _ = _RunCommand(['git', 'ls-remote', webrtc_deps_entry.url,
253 'HEAD'])
254 new_rev = stdout.strip().split('\t')[0]
214 255
256 # Check if an update is necessary.
257 if webrtc_deps_entry.revision != new_rev:
258 logging.debug('Roll dependency %s to %s', path, new_rev)
259 result.append(ChangedDep(path, webrtc_deps_entry.url,
260 webrtc_deps_entry.revision, new_rev))
261 return result
262
263
264 def CalculateChangedDepsLegacy(old_cr_deps, new_cr_deps):
265 result = []
266 new_cr_entries = BuildDepsentryDict(new_cr_deps)
267 old_cr_entries = BuildDepsentryDict(old_cr_deps)
215 all_deps_dirs = setup_links.DIRECTORIES 268 all_deps_dirs = setup_links.DIRECTORIES
216 for deps_dir in all_deps_dirs: 269 for deps_dir in all_deps_dirs:
217 # All deps have 'src' prepended to the path in the Chromium DEPS file. 270 # All deps have 'src' prepended to the path in the Chromium DEPS file.
218 dir_path = 'src/%s' % deps_dir 271 dir_path = 'src/%s' % deps_dir
219 272
220 for entry in GetMatchingDepsEntries(current_entries, dir_path): 273 for entry in GetMatchingDepsEntries(old_cr_entries, dir_path):
221 new_matching_entries = GetMatchingDepsEntries(new_entries, entry.path) 274 new_matching_entries = GetMatchingDepsEntries(new_cr_entries, entry.path)
222 assert len(new_matching_entries) <= 1, ( 275 assert len(new_matching_entries) <= 1, (
223 'Should never find more than one entry matching %s in %s, found %d' % 276 'Should never find more than one entry matching %s in %s, found %d' %
224 (entry.path, new_entries, len(new_matching_entries))) 277 (entry.path, new_cr_entries, len(new_matching_entries)))
225 if not new_matching_entries: 278 if not new_matching_entries:
226 result.append(ChangedDep(entry.path, entry.url, entry.revision, 'None')) 279 result.append(ChangedDep(entry.path, entry.url, entry.revision, 'None'))
227 elif entry != new_matching_entries[0]: 280 elif entry != new_matching_entries[0]:
228 result.append(ChangedDep(entry.path, entry.url, entry.revision, 281 result.append(ChangedDep(entry.path, entry.url, entry.revision,
229 new_matching_entries[0].revision)) 282 new_matching_entries[0].revision))
230 return result 283 return result
231 284
232 285
233 def CalculateChangedClang(new_cr_rev): 286 def CalculateChangedClang(new_cr_rev):
234 def GetClangRev(lines): 287 def GetClangRev(lines):
235 for line in lines: 288 for line in lines:
236 match = CLANG_REVISION_RE.match(line) 289 match = CLANG_REVISION_RE.match(line)
237 if match: 290 if match:
238 return match.group(1) 291 return match.group(1)
239 raise RollError('Could not parse Clang revision!') 292 raise RollError('Could not parse Clang revision!')
240 293
241 chromium_src_path = os.path.join(CHECKOUT_ROOT_DIR, 'chromium', 'src', 294 chromium_src_path = os.path.join(CHROMIUM_CHECKOUT_SRC_DIR,
242 CLANG_UPDATE_SCRIPT_LOCAL_PATH) 295 CLANG_UPDATE_SCRIPT_LOCAL_PATH)
243 with open(chromium_src_path, 'rb') as f: 296 with open(chromium_src_path, 'rb') as f:
244 current_lines = f.readlines() 297 current_lines = f.readlines()
245 current_rev = GetClangRev(current_lines) 298 current_rev = GetClangRev(current_lines)
246 299
247 new_clang_update_py = ReadRemoteCrFile(CLANG_UPDATE_SCRIPT_URL_PATH, 300 new_clang_update_py = ReadRemoteCrFile(CLANG_UPDATE_SCRIPT_URL_PATH,
248 new_cr_rev).splitlines() 301 new_cr_rev).splitlines()
249 new_rev = GetClangRev(new_clang_update_py) 302 new_rev = GetClangRev(new_clang_update_py)
250 return ChangedDep(CLANG_UPDATE_SCRIPT_LOCAL_PATH, None, current_rev, new_rev) 303 return ChangedDep(CLANG_UPDATE_SCRIPT_LOCAL_PATH, None, current_rev, new_rev)
251 304
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
287 CLANG_UPDATE_SCRIPT_URL_PATH) 340 CLANG_UPDATE_SCRIPT_URL_PATH)
288 commit_msg.append('Details: %s\n' % change_url) 341 commit_msg.append('Details: %s\n' % change_url)
289 else: 342 else:
290 commit_msg.append('No update to Clang.\n') 343 commit_msg.append('No update to Clang.\n')
291 344
292 commit_msg.append('TBR=%s' % tbr_authors) 345 commit_msg.append('TBR=%s' % tbr_authors)
293 commit_msg.append('BUG=None') 346 commit_msg.append('BUG=None')
294 return '\n'.join(commit_msg) 347 return '\n'.join(commit_msg)
295 348
296 349
297 def UpdateDeps(deps_filename, old_cr_revision, new_cr_revision): 350 def UpdateDepsFile(deps_filename, old_cr_revision, new_cr_revision,
351 changed_deps):
298 """Update the DEPS file with the new revision.""" 352 """Update the DEPS file with the new revision."""
353
354 # Update the chromium_revision variable.
299 with open(deps_filename, 'rb') as deps_file: 355 with open(deps_filename, 'rb') as deps_file:
300 deps_content = deps_file.read() 356 deps_content = deps_file.read()
301 deps_content = deps_content.replace(old_cr_revision, new_cr_revision) 357 deps_content = deps_content.replace(old_cr_revision, new_cr_revision)
302 with open(deps_filename, 'wb') as deps_file: 358 with open(deps_filename, 'wb') as deps_file:
303 deps_file.write(deps_content) 359 deps_file.write(deps_content)
304 360
361 # Update each individual DEPS entry.
362 for dep in changed_deps:
363 _, stderr = _RunCommand(
364 ['roll-dep-svn', '--no-verify-revision', dep.path, dep.new_rev],
365 working_dir=CHECKOUT_SRC_DIR, ignore_exit_code=True)
366 if stderr:
367 logging.warning('roll-dep-svn: %s', stderr)
368
369
305 def _IsTreeClean(): 370 def _IsTreeClean():
306 stdout, _ = _RunCommand(['git', 'status', '--porcelain']) 371 stdout, _ = _RunCommand(['git', 'status', '--porcelain'])
307 if len(stdout) == 0: 372 if len(stdout) == 0:
308 return True 373 return True
309 374
310 logging.error('Dirty/unversioned files:\n%s', stdout) 375 logging.error('Dirty/unversioned files:\n%s', stdout)
311 return False 376 return False
312 377
313 378
314 def _EnsureUpdatedMasterBranch(dry_run): 379 def _EnsureUpdatedMasterBranch(dry_run):
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
371 help=('Chromium Git revision to roll to. Defaults to the ' 436 help=('Chromium Git revision to roll to. Defaults to the '
372 'Chromium HEAD revision if omitted.')) 437 'Chromium HEAD revision if omitted.'))
373 p.add_argument('-u', '--rietveld-email', 438 p.add_argument('-u', '--rietveld-email',
374 help=('E-mail address to use for creating the CL at Rietveld' 439 help=('E-mail address to use for creating the CL at Rietveld'
375 'If omitted a previously cached one will be used or an ' 440 'If omitted a previously cached one will be used or an '
376 'error will be thrown during upload.')) 441 'error will be thrown during upload.'))
377 p.add_argument('--dry-run', action='store_true', default=False, 442 p.add_argument('--dry-run', action='store_true', default=False,
378 help=('Calculate changes and modify DEPS, but don\'t create ' 443 help=('Calculate changes and modify DEPS, but don\'t create '
379 'any local branch, commit, upload CL or send any ' 444 'any local branch, commit, upload CL or send any '
380 'tryjobs.')) 445 'tryjobs.'))
381 p.add_argument('--allow-reverse', action='store_true', default=False,
382 help=('Allow rolling back in time (disabled by default but '
383 'may be useful to be able do to manually).'))
384 p.add_argument('--skip-cq', action='store_true', default=False, 446 p.add_argument('--skip-cq', action='store_true', default=False,
385 help='Skip sending the CL to the CQ (default: %(default)s)') 447 help='Skip sending the CL to the CQ (default: %(default)s)')
386 p.add_argument('-v', '--verbose', action='store_true', default=False, 448 p.add_argument('-v', '--verbose', action='store_true', default=False,
387 help='Be extra verbose in printing of log messages.') 449 help='Be extra verbose in printing of log messages.')
388 opts = p.parse_args() 450 opts = p.parse_args()
389 451
390 if opts.verbose: 452 if opts.verbose:
391 logging.basicConfig(level=logging.DEBUG) 453 logging.basicConfig(level=logging.DEBUG)
392 else: 454 else:
393 logging.basicConfig(level=logging.INFO) 455 logging.basicConfig(level=logging.INFO)
394 456
395 if not _IsTreeClean(): 457 if not _IsTreeClean():
396 logging.error('Please clean your local checkout first.') 458 logging.error('Please clean your local checkout first.')
397 return 1 459 return 1
398 460
399 if opts.clean: 461 if opts.clean:
400 _RemovePreviousRollBranch(opts.dry_run) 462 _RemovePreviousRollBranch(opts.dry_run)
401 463
402 _EnsureUpdatedMasterBranch(opts.dry_run) 464 _EnsureUpdatedMasterBranch(opts.dry_run)
403 465
404 new_cr_rev = opts.revision 466 new_cr_rev = opts.revision
405 if not new_cr_rev: 467 if not new_cr_rev:
406 stdout, _ = _RunCommand(['git', 'ls-remote', CHROMIUM_SRC_URL, 'HEAD']) 468 stdout, _ = _RunCommand(['git', 'ls-remote', CHROMIUM_SRC_URL, 'HEAD'])
407 head_rev = stdout.strip().split('\t')[0] 469 head_rev = stdout.strip().split('\t')[0]
408 logging.info('No revision specified. Using HEAD: %s', head_rev) 470 logging.info('No revision specified. Using HEAD: %s', head_rev)
409 new_cr_rev = head_rev 471 new_cr_rev = head_rev
410 472
411 deps_filename = os.path.join(CHECKOUT_ROOT_DIR, 'DEPS') 473 deps_filename = os.path.join(CHECKOUT_SRC_DIR, 'DEPS')
412 local_deps = ParseLocalDepsFile(deps_filename) 474 webrtc_deps = ParseLocalDepsFile(deps_filename)
413 current_cr_rev = local_deps['vars']['chromium_revision'] 475 current_cr_rev = webrtc_deps['vars']['chromium_revision']
414 476
415 current_commit_pos = ParseCommitPosition(ReadRemoteCrCommit(current_cr_rev)) 477 current_commit_pos = ParseCommitPosition(ReadRemoteCrCommit(current_cr_rev))
416 new_commit_pos = ParseCommitPosition(ReadRemoteCrCommit(new_cr_rev)) 478 new_commit_pos = ParseCommitPosition(ReadRemoteCrCommit(new_cr_rev))
417 479
418 current_cr_deps = ParseRemoteCrDepsFile(current_cr_rev) 480 current_cr_deps = ParseRemoteCrDepsFile(current_cr_rev)
419 new_cr_deps = ParseRemoteCrDepsFile(new_cr_rev) 481 new_cr_deps = ParseRemoteCrDepsFile(new_cr_rev)
420 482
421 if new_commit_pos > current_commit_pos or opts.allow_reverse: 483 changed_deps = CalculateChangedDeps(webrtc_deps, current_cr_deps, new_cr_deps)
422 changed_deps = sorted(CalculateChangedDeps(current_cr_deps, new_cr_deps)) 484 clang_change = CalculateChangedClang(new_cr_rev)
423 clang_change = CalculateChangedClang(new_cr_rev) 485 commit_msg = GenerateCommitMessage(current_cr_rev, new_cr_rev,
424 commit_msg = GenerateCommitMessage(current_cr_rev, new_cr_rev, 486 current_commit_pos, new_commit_pos,
425 current_commit_pos, new_commit_pos, 487 changed_deps, clang_change)
426 changed_deps, clang_change) 488 logging.debug('Commit message:\n%s', commit_msg)
427 logging.debug('Commit message:\n%s', commit_msg)
428 else:
429 logging.info('Currently pinned chromium_revision: %s (#%s) is newer than '
430 '%s (#%s). To roll to older revisions, you must pass the '
431 '--allow-reverse flag.\n'
432 'Aborting without action.', current_cr_rev, current_commit_pos,
433 new_cr_rev, new_commit_pos)
434 return 0
435 489
436 _CreateRollBranch(opts.dry_run) 490 _CreateRollBranch(opts.dry_run)
437 UpdateDeps(deps_filename, current_cr_rev, new_cr_rev) 491 UpdateDepsFile(deps_filename, current_cr_rev, new_cr_rev, changed_deps)
438 _LocalCommit(commit_msg, opts.dry_run) 492 _LocalCommit(commit_msg, opts.dry_run)
439 _UploadCL(opts.dry_run, opts.rietveld_email) 493 _UploadCL(opts.dry_run, opts.rietveld_email)
440 _SendToCQ(opts.dry_run, opts.skip_cq) 494 _SendToCQ(opts.dry_run, opts.skip_cq)
441 return 0 495 return 0
442 496
443 497
444 if __name__ == '__main__': 498 if __name__ == '__main__':
445 sys.exit(main()) 499 sys.exit(main())
OLDNEW
« no previous file with comments | « no previous file | tools/autoroller/unittests/DEPS » ('j') | tools/autoroller/unittests/roll_chromium_revision_test.py » ('J')

Powered by Google App Engine
This is Rietveld 408576698