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

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

Issue 2570603003: Autoroller: Support for rolling individual DEPS entries. (Closed)
Patch Set: Updated after review 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
« no previous file with comments | « no previous file | tools/autoroller/unittests/DEPS » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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).
24 DONT_AUTOROLL_THESE = [
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:
224 - If a shared dependency with the Chromium DEPS file: roll it to the same
225 revision as Chromium (i.e. entry in the new_cr_deps dict)
226 - If it's a Chromium sub-directory, roll it to the HEAD revision (notice
227 this means it may be ahead of the chromium_revision, but generally these
228 should be close).
229 - If it's another DEPS entry (not shared with Chromium), roll it to HEAD
230 unless it's configured to be skipped.
231 2. Entries present in the setup_links.py file. If the dir has changed between
232 old_cr_deps and new_cr_deps, it is considered changed and updated to the
233 revision for the entry in the new_cr_deps dict.
234
235 Returns:
236 A list of ChangedDep objects representing the changed deps.
237 """
238 return sorted(CalculateChangedDepsProper(webrtc_deps, new_cr_deps) +
239 CalculateChangedDepsLegacy(old_cr_deps, new_cr_deps))
240
241
242 def CalculateChangedDepsProper(webrtc_deps, new_cr_deps):
211 result = [] 243 result = []
212 current_entries = BuildDepsentryDict(current_deps) 244 webrtc_entries = BuildDepsentryDict(webrtc_deps)
213 new_entries = BuildDepsentryDict(new_deps) 245 new_cr_entries = BuildDepsentryDict(new_cr_deps)
246 for path, webrtc_deps_entry in webrtc_entries.iteritems():
247 if path in DONT_AUTOROLL_THESE:
248 continue
249 cr_deps_entry = new_cr_entries.get(path)
250 if cr_deps_entry:
251 # Use the revision from Chromium's DEPS file.
252 new_rev = cr_deps_entry.revision
253 assert webrtc_deps_entry.url == cr_deps_entry.url, (
254 'WebRTC DEPS entry %s has a different URL (%s) than Chromium (%s).' %
255 (path, webrtc_deps_entry.url, cr_deps_entry.url))
256 else:
257 # Use the HEAD of the deps repo.
258 stdout, _ = _RunCommand(['git', 'ls-remote', webrtc_deps_entry.url,
259 'HEAD'])
260 new_rev = stdout.strip().split('\t')[0]
214 261
262 # Check if an update is necessary.
263 if webrtc_deps_entry.revision != new_rev:
264 logging.debug('Roll dependency %s to %s', path, new_rev)
265 result.append(ChangedDep(path, webrtc_deps_entry.url,
266 webrtc_deps_entry.revision, new_rev))
267 return result
268
269
270 def CalculateChangedDepsLegacy(old_cr_deps, new_cr_deps):
271 result = []
272 new_cr_entries = BuildDepsentryDict(new_cr_deps)
273 old_cr_entries = BuildDepsentryDict(old_cr_deps)
215 all_deps_dirs = setup_links.DIRECTORIES 274 all_deps_dirs = setup_links.DIRECTORIES
216 for deps_dir in all_deps_dirs: 275 for deps_dir in all_deps_dirs:
217 # All deps have 'src' prepended to the path in the Chromium DEPS file. 276 # All deps have 'src' prepended to the path in the Chromium DEPS file.
218 dir_path = 'src/%s' % deps_dir 277 dir_path = 'src/%s' % deps_dir
219 278
220 for entry in GetMatchingDepsEntries(current_entries, dir_path): 279 for entry in GetMatchingDepsEntries(old_cr_entries, dir_path):
221 new_matching_entries = GetMatchingDepsEntries(new_entries, entry.path) 280 new_matching_entries = GetMatchingDepsEntries(new_cr_entries, entry.path)
222 assert len(new_matching_entries) <= 1, ( 281 assert len(new_matching_entries) <= 1, (
223 'Should never find more than one entry matching %s in %s, found %d' % 282 'Should never find more than one entry matching %s in %s, found %d' %
224 (entry.path, new_entries, len(new_matching_entries))) 283 (entry.path, new_cr_entries, len(new_matching_entries)))
225 if not new_matching_entries: 284 if not new_matching_entries:
226 result.append(ChangedDep(entry.path, entry.url, entry.revision, 'None')) 285 result.append(ChangedDep(entry.path, entry.url, entry.revision, 'None'))
227 elif entry != new_matching_entries[0]: 286 elif entry != new_matching_entries[0]:
228 result.append(ChangedDep(entry.path, entry.url, entry.revision, 287 result.append(ChangedDep(entry.path, entry.url, entry.revision,
229 new_matching_entries[0].revision)) 288 new_matching_entries[0].revision))
230 return result 289 return result
231 290
232 291
233 def CalculateChangedClang(new_cr_rev): 292 def CalculateChangedClang(new_cr_rev):
234 def GetClangRev(lines): 293 def GetClangRev(lines):
235 for line in lines: 294 for line in lines:
236 match = CLANG_REVISION_RE.match(line) 295 match = CLANG_REVISION_RE.match(line)
237 if match: 296 if match:
238 return match.group(1) 297 return match.group(1)
239 raise RollError('Could not parse Clang revision!') 298 raise RollError('Could not parse Clang revision!')
240 299
241 chromium_src_path = os.path.join(CHECKOUT_ROOT_DIR, 'chromium', 'src', 300 chromium_src_path = os.path.join(CHROMIUM_CHECKOUT_SRC_DIR,
242 CLANG_UPDATE_SCRIPT_LOCAL_PATH) 301 CLANG_UPDATE_SCRIPT_LOCAL_PATH)
243 with open(chromium_src_path, 'rb') as f: 302 with open(chromium_src_path, 'rb') as f:
244 current_lines = f.readlines() 303 current_lines = f.readlines()
245 current_rev = GetClangRev(current_lines) 304 current_rev = GetClangRev(current_lines)
246 305
247 new_clang_update_py = ReadRemoteCrFile(CLANG_UPDATE_SCRIPT_URL_PATH, 306 new_clang_update_py = ReadRemoteCrFile(CLANG_UPDATE_SCRIPT_URL_PATH,
248 new_cr_rev).splitlines() 307 new_cr_rev).splitlines()
249 new_rev = GetClangRev(new_clang_update_py) 308 new_rev = GetClangRev(new_clang_update_py)
250 return ChangedDep(CLANG_UPDATE_SCRIPT_LOCAL_PATH, None, current_rev, new_rev) 309 return ChangedDep(CLANG_UPDATE_SCRIPT_LOCAL_PATH, None, current_rev, new_rev)
251 310
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
287 CLANG_UPDATE_SCRIPT_URL_PATH) 346 CLANG_UPDATE_SCRIPT_URL_PATH)
288 commit_msg.append('Details: %s\n' % change_url) 347 commit_msg.append('Details: %s\n' % change_url)
289 else: 348 else:
290 commit_msg.append('No update to Clang.\n') 349 commit_msg.append('No update to Clang.\n')
291 350
292 commit_msg.append('TBR=%s' % tbr_authors) 351 commit_msg.append('TBR=%s' % tbr_authors)
293 commit_msg.append('BUG=None') 352 commit_msg.append('BUG=None')
294 return '\n'.join(commit_msg) 353 return '\n'.join(commit_msg)
295 354
296 355
297 def UpdateDeps(deps_filename, old_cr_revision, new_cr_revision): 356 def UpdateDepsFile(deps_filename, old_cr_revision, new_cr_revision,
357 changed_deps):
298 """Update the DEPS file with the new revision.""" 358 """Update the DEPS file with the new revision."""
359
360 # Update the chromium_revision variable.
299 with open(deps_filename, 'rb') as deps_file: 361 with open(deps_filename, 'rb') as deps_file:
300 deps_content = deps_file.read() 362 deps_content = deps_file.read()
301 deps_content = deps_content.replace(old_cr_revision, new_cr_revision) 363 deps_content = deps_content.replace(old_cr_revision, new_cr_revision)
302 with open(deps_filename, 'wb') as deps_file: 364 with open(deps_filename, 'wb') as deps_file:
303 deps_file.write(deps_content) 365 deps_file.write(deps_content)
304 366
367 # Update each individual DEPS entry.
368 for dep in changed_deps:
369 _, stderr = _RunCommand(
370 ['roll-dep-svn', '--no-verify-revision', dep.path, dep.new_rev],
371 working_dir=CHECKOUT_SRC_DIR, ignore_exit_code=True)
372 if stderr:
373 logging.warning('roll-dep-svn: %s', stderr)
374
375
305 def _IsTreeClean(): 376 def _IsTreeClean():
306 stdout, _ = _RunCommand(['git', 'status', '--porcelain']) 377 stdout, _ = _RunCommand(['git', 'status', '--porcelain'])
307 if len(stdout) == 0: 378 if len(stdout) == 0:
308 return True 379 return True
309 380
310 logging.error('Dirty/unversioned files:\n%s', stdout) 381 logging.error('Dirty/unversioned files:\n%s', stdout)
311 return False 382 return False
312 383
313 384
314 def _EnsureUpdatedMasterBranch(dry_run): 385 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 ' 442 help=('Chromium Git revision to roll to. Defaults to the '
372 'Chromium HEAD revision if omitted.')) 443 'Chromium HEAD revision if omitted.'))
373 p.add_argument('-u', '--rietveld-email', 444 p.add_argument('-u', '--rietveld-email',
374 help=('E-mail address to use for creating the CL at Rietveld' 445 help=('E-mail address to use for creating the CL at Rietveld'
375 'If omitted a previously cached one will be used or an ' 446 'If omitted a previously cached one will be used or an '
376 'error will be thrown during upload.')) 447 'error will be thrown during upload.'))
377 p.add_argument('--dry-run', action='store_true', default=False, 448 p.add_argument('--dry-run', action='store_true', default=False,
378 help=('Calculate changes and modify DEPS, but don\'t create ' 449 help=('Calculate changes and modify DEPS, but don\'t create '
379 'any local branch, commit, upload CL or send any ' 450 'any local branch, commit, upload CL or send any '
380 'tryjobs.')) 451 '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, 452 p.add_argument('--skip-cq', action='store_true', default=False,
385 help='Skip sending the CL to the CQ (default: %(default)s)') 453 help='Skip sending the CL to the CQ (default: %(default)s)')
386 p.add_argument('-v', '--verbose', action='store_true', default=False, 454 p.add_argument('-v', '--verbose', action='store_true', default=False,
387 help='Be extra verbose in printing of log messages.') 455 help='Be extra verbose in printing of log messages.')
388 opts = p.parse_args() 456 opts = p.parse_args()
389 457
390 if opts.verbose: 458 if opts.verbose:
391 logging.basicConfig(level=logging.DEBUG) 459 logging.basicConfig(level=logging.DEBUG)
392 else: 460 else:
393 logging.basicConfig(level=logging.INFO) 461 logging.basicConfig(level=logging.INFO)
394 462
395 if not _IsTreeClean(): 463 if not _IsTreeClean():
396 logging.error('Please clean your local checkout first.') 464 logging.error('Please clean your local checkout first.')
397 return 1 465 return 1
398 466
399 if opts.clean: 467 if opts.clean:
400 _RemovePreviousRollBranch(opts.dry_run) 468 _RemovePreviousRollBranch(opts.dry_run)
401 469
402 _EnsureUpdatedMasterBranch(opts.dry_run) 470 _EnsureUpdatedMasterBranch(opts.dry_run)
403 471
404 new_cr_rev = opts.revision 472 new_cr_rev = opts.revision
405 if not new_cr_rev: 473 if not new_cr_rev:
406 stdout, _ = _RunCommand(['git', 'ls-remote', CHROMIUM_SRC_URL, 'HEAD']) 474 stdout, _ = _RunCommand(['git', 'ls-remote', CHROMIUM_SRC_URL, 'HEAD'])
407 head_rev = stdout.strip().split('\t')[0] 475 head_rev = stdout.strip().split('\t')[0]
408 logging.info('No revision specified. Using HEAD: %s', head_rev) 476 logging.info('No revision specified. Using HEAD: %s', head_rev)
409 new_cr_rev = head_rev 477 new_cr_rev = head_rev
410 478
411 deps_filename = os.path.join(CHECKOUT_ROOT_DIR, 'DEPS') 479 deps_filename = os.path.join(CHECKOUT_SRC_DIR, 'DEPS')
412 local_deps = ParseLocalDepsFile(deps_filename) 480 webrtc_deps = ParseLocalDepsFile(deps_filename)
413 current_cr_rev = local_deps['vars']['chromium_revision'] 481 current_cr_rev = webrtc_deps['vars']['chromium_revision']
414 482
415 current_commit_pos = ParseCommitPosition(ReadRemoteCrCommit(current_cr_rev)) 483 current_commit_pos = ParseCommitPosition(ReadRemoteCrCommit(current_cr_rev))
416 new_commit_pos = ParseCommitPosition(ReadRemoteCrCommit(new_cr_rev)) 484 new_commit_pos = ParseCommitPosition(ReadRemoteCrCommit(new_cr_rev))
417 485
418 current_cr_deps = ParseRemoteCrDepsFile(current_cr_rev) 486 current_cr_deps = ParseRemoteCrDepsFile(current_cr_rev)
419 new_cr_deps = ParseRemoteCrDepsFile(new_cr_rev) 487 new_cr_deps = ParseRemoteCrDepsFile(new_cr_rev)
420 488
421 if new_commit_pos > current_commit_pos or opts.allow_reverse: 489 changed_deps = CalculateChangedDeps(webrtc_deps, current_cr_deps, new_cr_deps)
422 changed_deps = sorted(CalculateChangedDeps(current_cr_deps, new_cr_deps)) 490 clang_change = CalculateChangedClang(new_cr_rev)
423 clang_change = CalculateChangedClang(new_cr_rev) 491 commit_msg = GenerateCommitMessage(current_cr_rev, new_cr_rev,
424 commit_msg = GenerateCommitMessage(current_cr_rev, new_cr_rev, 492 current_commit_pos, new_commit_pos,
425 current_commit_pos, new_commit_pos, 493 changed_deps, clang_change)
426 changed_deps, clang_change) 494 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 495
436 _CreateRollBranch(opts.dry_run) 496 _CreateRollBranch(opts.dry_run)
437 UpdateDeps(deps_filename, current_cr_rev, new_cr_rev) 497 UpdateDepsFile(deps_filename, current_cr_rev, new_cr_rev, changed_deps)
438 _LocalCommit(commit_msg, opts.dry_run) 498 _LocalCommit(commit_msg, opts.dry_run)
439 _UploadCL(opts.dry_run, opts.rietveld_email) 499 _UploadCL(opts.dry_run, opts.rietveld_email)
440 _SendToCQ(opts.dry_run, opts.skip_cq) 500 _SendToCQ(opts.dry_run, opts.skip_cq)
441 return 0 501 return 0
442 502
443 503
444 if __name__ == '__main__': 504 if __name__ == '__main__':
445 sys.exit(main()) 505 sys.exit(main())
OLDNEW
« no previous file with comments | « no previous file | tools/autoroller/unittests/DEPS » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698