| OLD | NEW |
| 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 CHROMIUM_SRC_URL = 'https://chromium.googlesource.com/chromium/src' | 23 CHROMIUM_SRC_URL = 'https://chromium.googlesource.com/chromium/src' |
| 24 CHROMIUM_COMMIT_TEMPLATE = CHROMIUM_SRC_URL + '/+/%s' | 24 CHROMIUM_COMMIT_TEMPLATE = CHROMIUM_SRC_URL + '/+/%s' |
| 25 CHROMIUM_LOG_TEMPLATE = CHROMIUM_SRC_URL + '/+log/%s' |
| 25 CHROMIUM_FILE_TEMPLATE = CHROMIUM_SRC_URL + '/+/%s/%s' | 26 CHROMIUM_FILE_TEMPLATE = CHROMIUM_SRC_URL + '/+/%s/%s' |
| 26 | 27 |
| 27 COMMIT_POSITION_RE = re.compile('^Cr-Commit-Position: .*#([0-9]+).*$') | 28 COMMIT_POSITION_RE = re.compile('^Cr-Commit-Position: .*#([0-9]+).*$') |
| 28 CLANG_REVISION_RE = re.compile(r'^CLANG_REVISION=(\d+)$') | 29 CLANG_REVISION_RE = re.compile(r'^CLANG_REVISION=(\d+)$') |
| 29 ROLL_BRANCH_NAME = 'roll_chromium_revision' | 30 ROLL_BRANCH_NAME = 'roll_chromium_revision' |
| 30 | 31 |
| 31 SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__)) | 32 SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__)) |
| 32 CHECKOUT_ROOT_DIR = os.path.realpath(os.path.join(SCRIPT_DIR, os.pardir, | 33 CHECKOUT_ROOT_DIR = os.path.realpath(os.path.join(SCRIPT_DIR, os.pardir, |
| 33 os.pardir)) | 34 os.pardir)) |
| 34 sys.path.append(CHECKOUT_ROOT_DIR) | 35 sys.path.append(CHECKOUT_ROOT_DIR) |
| 35 import setup_links | 36 import setup_links |
| 36 | 37 |
| 37 sys.path.append(os.path.join(CHECKOUT_ROOT_DIR, 'tools')) | 38 sys.path.append(os.path.join(CHECKOUT_ROOT_DIR, 'tools')) |
| 38 import find_depot_tools | 39 import find_depot_tools |
| 39 find_depot_tools.add_depot_tools_to_path() | 40 find_depot_tools.add_depot_tools_to_path() |
| 40 from gclient import GClientKeywords | 41 from gclient import GClientKeywords |
| 41 | 42 |
| 42 CLANG_UPDATE_SCRIPT_URL_PATH = 'tools/clang/scripts/update.sh' | 43 CLANG_UPDATE_SCRIPT_URL_PATH = 'tools/clang/scripts/update.sh' |
| 43 CLANG_UPDATE_SCRIPT_LOCAL_PATH = os.path.join('tools', 'clang', 'scripts', | 44 CLANG_UPDATE_SCRIPT_LOCAL_PATH = os.path.join('tools', 'clang', 'scripts', |
| 44 'update.sh') | 45 'update.sh') |
| 45 | 46 |
| 46 DepsEntry = collections.namedtuple('DepsEntry', 'path url revision') | 47 DepsEntry = collections.namedtuple('DepsEntry', 'path url revision') |
| 47 ChangedDep = collections.namedtuple('ChangedDep', 'path current_rev new_rev') | 48 ChangedDep = collections.namedtuple('ChangedDep', |
| 49 'path url current_rev new_rev') |
| 48 | 50 |
| 49 | 51 |
| 50 def ParseDepsDict(deps_content): | 52 def ParseDepsDict(deps_content): |
| 51 local_scope = {} | 53 local_scope = {} |
| 52 var = GClientKeywords.VarImpl({}, local_scope) | 54 var = GClientKeywords.VarImpl({}, local_scope) |
| 53 global_scope = { | 55 global_scope = { |
| 54 'File': GClientKeywords.FileImpl, | 56 'File': GClientKeywords.FileImpl, |
| 55 'From': GClientKeywords.FromImpl, | 57 'From': GClientKeywords.FromImpl, |
| 56 'Var': var.Lookup, | 58 'Var': var.Lookup, |
| 57 'deps_os': {}, | 59 'deps_os': {}, |
| (...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 212 for deps_dir in all_deps_dirs: | 214 for deps_dir in all_deps_dirs: |
| 213 # All deps have 'src' prepended to the path in the Chromium DEPS file. | 215 # All deps have 'src' prepended to the path in the Chromium DEPS file. |
| 214 dir_path = 'src/%s' % deps_dir | 216 dir_path = 'src/%s' % deps_dir |
| 215 | 217 |
| 216 for entry in GetMatchingDepsEntries(current_entries, dir_path): | 218 for entry in GetMatchingDepsEntries(current_entries, dir_path): |
| 217 new_matching_entries = GetMatchingDepsEntries(new_entries, entry.path) | 219 new_matching_entries = GetMatchingDepsEntries(new_entries, entry.path) |
| 218 assert len(new_matching_entries) <= 1, ( | 220 assert len(new_matching_entries) <= 1, ( |
| 219 'Should never find more than one entry matching %s in %s, found %d' % | 221 'Should never find more than one entry matching %s in %s, found %d' % |
| 220 (entry.path, new_entries, len(new_matching_entries))) | 222 (entry.path, new_entries, len(new_matching_entries))) |
| 221 if not new_matching_entries: | 223 if not new_matching_entries: |
| 222 result.append(ChangedDep(entry.path, entry.revision, 'None')) | 224 result.append(ChangedDep(entry.path, entry.url, entry.revision, 'None')) |
| 223 elif entry != new_matching_entries[0]: | 225 elif entry != new_matching_entries[0]: |
| 224 result.append(ChangedDep(entry.path, entry.revision, | 226 result.append(ChangedDep(entry.path, entry.url, entry.revision, |
| 225 new_matching_entries[0].revision)) | 227 new_matching_entries[0].revision)) |
| 226 return result | 228 return result |
| 227 | 229 |
| 228 | 230 |
| 229 def CalculateChangedClang(new_cr_rev): | 231 def CalculateChangedClang(new_cr_rev): |
| 230 def GetClangRev(lines): | 232 def GetClangRev(lines): |
| 231 for line in lines: | 233 for line in lines: |
| 232 match = CLANG_REVISION_RE.match(line) | 234 match = CLANG_REVISION_RE.match(line) |
| 233 if match: | 235 if match: |
| 234 return match.group(1) | 236 return match.group(1) |
| 235 return None | 237 return None |
| 236 | 238 |
| 237 chromium_src_path = os.path.join(CHECKOUT_ROOT_DIR, 'chromium', 'src', | 239 chromium_src_path = os.path.join(CHECKOUT_ROOT_DIR, 'chromium', 'src', |
| 238 CLANG_UPDATE_SCRIPT_LOCAL_PATH) | 240 CLANG_UPDATE_SCRIPT_LOCAL_PATH) |
| 239 with open(chromium_src_path, 'rb') as f: | 241 with open(chromium_src_path, 'rb') as f: |
| 240 current_lines = f.readlines() | 242 current_lines = f.readlines() |
| 241 current_rev = GetClangRev(current_lines) | 243 current_rev = GetClangRev(current_lines) |
| 242 | 244 |
| 243 new_clang_update_sh = ReadRemoteCrFile(CLANG_UPDATE_SCRIPT_URL_PATH, | 245 new_clang_update_sh = ReadRemoteCrFile(CLANG_UPDATE_SCRIPT_URL_PATH, |
| 244 new_cr_rev).splitlines() | 246 new_cr_rev).splitlines() |
| 245 new_rev = GetClangRev(new_clang_update_sh) | 247 new_rev = GetClangRev(new_clang_update_sh) |
| 246 return ChangedDep(CLANG_UPDATE_SCRIPT_LOCAL_PATH, current_rev, new_rev) | 248 return ChangedDep(CLANG_UPDATE_SCRIPT_LOCAL_PATH, None, current_rev, new_rev) |
| 247 | 249 |
| 248 | 250 |
| 249 def GenerateCommitMessage(current_cr_rev, new_cr_rev, changed_deps_list, | 251 def GenerateCommitMessage(current_cr_rev, new_cr_rev, current_commit_pos, |
| 250 clang_change): | 252 new_commit_pos, changed_deps_list, clang_change): |
| 251 current_cr_rev = current_cr_rev[0:7] | 253 current_cr_rev = current_cr_rev[0:7] |
| 252 new_cr_rev = new_cr_rev[0:7] | 254 new_cr_rev = new_cr_rev[0:7] |
| 253 rev_interval = '%s..%s' % (current_cr_rev, new_cr_rev) | 255 rev_interval = '%s..%s' % (current_cr_rev, new_cr_rev) |
| 256 git_number_interval = '%s:%s' % (current_commit_pos, new_commit_pos) |
| 254 | 257 |
| 255 current_git_number = ParseCommitPosition(ReadRemoteCrCommit(current_cr_rev)) | 258 commit_msg = ['Roll chromium_revision %s (%s)\n' % (rev_interval, |
| 256 new_git_number = ParseCommitPosition(ReadRemoteCrCommit(new_cr_rev)) | 259 git_number_interval)] |
| 257 git_number_interval = '%s:%s' % (current_git_number, new_git_number) | 260 commit_msg.append('Change log: %s' % (CHROMIUM_LOG_TEMPLATE % rev_interval)) |
| 261 commit_msg.append('Full diff: %s\n' % (CHROMIUM_COMMIT_TEMPLATE % |
| 262 rev_interval)) |
| 258 | 263 |
| 259 commit_msg = ['Roll chromium_revision %s (%s)' % (rev_interval, | |
| 260 git_number_interval)] | |
| 261 # TBR field will be empty unless in some custom cases, where some engineers | 264 # TBR field will be empty unless in some custom cases, where some engineers |
| 262 # are added. | 265 # are added. |
| 263 tbr_authors = '' | 266 tbr_authors = '' |
| 267 |
| 264 if changed_deps_list: | 268 if changed_deps_list: |
| 265 commit_msg.append('\nRelevant changes:') | 269 commit_msg.append('Changed dependencies:') |
| 266 | 270 |
| 267 for c in changed_deps_list: | 271 for c in changed_deps_list: |
| 268 commit_msg.append('* %s: %s..%s' % (c.path, c.current_rev[0:7], | 272 commit_msg.append('* %s: %s/+log/%s..%s' % (c.path, c.url, |
| 269 c.new_rev[0:7])) | 273 c.current_rev[0:7], |
| 274 c.new_rev[0:7])) |
| 270 if 'libvpx' in c.path: | 275 if 'libvpx' in c.path: |
| 271 tbr_authors += 'marpan@webrtc.org, stefan@webrtc.org, ' | 276 tbr_authors += 'marpan@webrtc.org, stefan@webrtc.org, ' |
| 272 | 277 |
| 273 change_url = CHROMIUM_FILE_TEMPLATE % (rev_interval, 'DEPS') | 278 change_url = CHROMIUM_FILE_TEMPLATE % (rev_interval, 'DEPS') |
| 274 commit_msg.append('Details: %s' % change_url) | 279 commit_msg.append('DEPS diff: %s\n' % change_url) |
| 280 else: |
| 281 commit_msg.append('No dependencies changed.') |
| 275 | 282 |
| 276 if clang_change.current_rev != clang_change.new_rev: | 283 if clang_change.current_rev != clang_change.new_rev: |
| 277 commit_msg.append('\nClang version changed %s:%s' % | 284 commit_msg.append('Clang version changed %s:%s' % |
| 278 (clang_change.current_rev, clang_change.new_rev)) | 285 (clang_change.current_rev, clang_change.new_rev)) |
| 279 change_url = CHROMIUM_FILE_TEMPLATE % (rev_interval, | 286 change_url = CHROMIUM_FILE_TEMPLATE % (rev_interval, |
| 280 CLANG_UPDATE_SCRIPT_URL_PATH) | 287 CLANG_UPDATE_SCRIPT_URL_PATH) |
| 281 commit_msg.append('Details: %s' % change_url) | 288 commit_msg.append('Details: %s' % change_url) |
| 282 tbr_authors += 'pbos@webrtc.org' | 289 tbr_authors += 'pbos@webrtc.org' |
| 283 else: | 290 else: |
| 284 commit_msg.append('\nClang version was not updated in this roll.') | 291 commit_msg.append('No update to Clang.') |
| 292 |
| 285 commit_msg.append('\nTBR=%s\n' % tbr_authors) | 293 commit_msg.append('\nTBR=%s\n' % tbr_authors) |
| 286 return '\n'.join(commit_msg) | 294 return '\n'.join(commit_msg) |
| 287 | 295 |
| 288 | 296 |
| 289 def UpdateDeps(deps_filename, old_cr_revision, new_cr_revision): | 297 def UpdateDeps(deps_filename, old_cr_revision, new_cr_revision): |
| 290 """Update the DEPS file with the new revision.""" | 298 """Update the DEPS file with the new revision.""" |
| 291 with open(deps_filename, 'rb') as deps_file: | 299 with open(deps_filename, 'rb') as deps_file: |
| 292 deps_content = deps_file.read() | 300 deps_content = deps_file.read() |
| 293 deps_content = deps_content.replace(old_cr_revision, new_cr_revision) | 301 deps_content = deps_content.replace(old_cr_revision, new_cr_revision) |
| 294 with open(deps_filename, 'wb') as deps_file: | 302 with open(deps_filename, 'wb') as deps_file: |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 355 p = argparse.ArgumentParser() | 363 p = argparse.ArgumentParser() |
| 356 p.add_argument('--clean', action='store_true', default=False, | 364 p.add_argument('--clean', action='store_true', default=False, |
| 357 help='Removes any previous local roll branch.') | 365 help='Removes any previous local roll branch.') |
| 358 p.add_argument('-r', '--revision', | 366 p.add_argument('-r', '--revision', |
| 359 help=('Chromium Git revision to roll to. Defaults to the ' | 367 help=('Chromium Git revision to roll to. Defaults to the ' |
| 360 'Chromium HEAD revision if omitted.')) | 368 'Chromium HEAD revision if omitted.')) |
| 361 p.add_argument('--dry-run', action='store_true', default=False, | 369 p.add_argument('--dry-run', action='store_true', default=False, |
| 362 help=('Calculate changes and modify DEPS, but don\'t create ' | 370 help=('Calculate changes and modify DEPS, but don\'t create ' |
| 363 'any local branch, commit, upload CL or send any ' | 371 'any local branch, commit, upload CL or send any ' |
| 364 'tryjobs.')) | 372 'tryjobs.')) |
| 373 p.add_argument('--allow-reverse', action='store_true', default=False, |
| 374 help=('Allow rolling back in time (disabled by default but ' |
| 375 'may be useful to be able do to manually).')) |
| 365 p.add_argument('-s', '--skip-try', action='store_true', default=False, | 376 p.add_argument('-s', '--skip-try', action='store_true', default=False, |
| 366 help='Do everything except sending tryjobs.') | 377 help='Do everything except sending tryjobs.') |
| 367 p.add_argument('-v', '--verbose', action='store_true', default=False, | 378 p.add_argument('-v', '--verbose', action='store_true', default=False, |
| 368 help='Be extra verbose in printing of log messages.') | 379 help='Be extra verbose in printing of log messages.') |
| 369 opts = p.parse_args() | 380 opts = p.parse_args() |
| 370 | 381 |
| 371 if opts.verbose: | 382 if opts.verbose: |
| 372 logging.basicConfig(level=logging.DEBUG) | 383 logging.basicConfig(level=logging.DEBUG) |
| 373 else: | 384 else: |
| 374 logging.basicConfig(level=logging.INFO) | 385 logging.basicConfig(level=logging.INFO) |
| 375 | 386 |
| 376 if not _IsTreeClean(): | 387 if not _IsTreeClean(): |
| 377 logging.error('Please clean your local checkout first.') | 388 logging.error('Please clean your local checkout first.') |
| 378 return 1 | 389 return 1 |
| 379 | 390 |
| 380 if opts.clean: | 391 if opts.clean: |
| 381 _RemovePreviousRollBranch(opts.dry_run) | 392 _RemovePreviousRollBranch(opts.dry_run) |
| 382 | 393 |
| 383 _EnsureUpdatedMasterBranch(opts.dry_run) | 394 _EnsureUpdatedMasterBranch(opts.dry_run) |
| 384 | 395 |
| 385 if not opts.revision: | 396 new_cr_rev = opts.revision |
| 397 if not new_cr_rev: |
| 386 stdout, _ = _RunCommand(['git', 'ls-remote', CHROMIUM_SRC_URL, 'HEAD']) | 398 stdout, _ = _RunCommand(['git', 'ls-remote', CHROMIUM_SRC_URL, 'HEAD']) |
| 387 head_rev = stdout.strip().split('\t')[0] | 399 head_rev = stdout.strip().split('\t')[0] |
| 388 logging.info('No revision specified. Using HEAD: %s', head_rev) | 400 logging.info('No revision specified. Using HEAD: %s', head_rev) |
| 389 opts.revision = head_rev | 401 new_cr_rev = head_rev |
| 390 | 402 |
| 391 deps_filename = os.path.join(CHECKOUT_ROOT_DIR, 'DEPS') | 403 deps_filename = os.path.join(CHECKOUT_ROOT_DIR, 'DEPS') |
| 392 local_deps = ParseLocalDepsFile(deps_filename) | 404 local_deps = ParseLocalDepsFile(deps_filename) |
| 393 current_cr_rev = local_deps['vars']['chromium_revision'] | 405 current_cr_rev = local_deps['vars']['chromium_revision'] |
| 394 | 406 |
| 407 current_commit_pos = ParseCommitPosition(ReadRemoteCrCommit(current_cr_rev)) |
| 408 new_commit_pos = ParseCommitPosition(ReadRemoteCrCommit(new_cr_rev)) |
| 409 |
| 395 current_cr_deps = ParseRemoteCrDepsFile(current_cr_rev) | 410 current_cr_deps = ParseRemoteCrDepsFile(current_cr_rev) |
| 396 new_cr_deps = ParseRemoteCrDepsFile(opts.revision) | 411 new_cr_deps = ParseRemoteCrDepsFile(new_cr_rev) |
| 397 | 412 |
| 398 changed_deps = sorted(CalculateChangedDeps(current_cr_deps, new_cr_deps)) | 413 if new_commit_pos > current_commit_pos or opts.allow_reverse: |
| 399 clang_change = CalculateChangedClang(opts.revision) | 414 changed_deps = sorted(CalculateChangedDeps(current_cr_deps, new_cr_deps)) |
| 400 if changed_deps or clang_change: | 415 clang_change = CalculateChangedClang(new_cr_rev) |
| 401 commit_msg = GenerateCommitMessage(current_cr_rev, opts.revision, | 416 commit_msg = GenerateCommitMessage(current_cr_rev, new_cr_rev, |
| 417 current_commit_pos, new_commit_pos, |
| 402 changed_deps, clang_change) | 418 changed_deps, clang_change) |
| 403 logging.debug('Commit message:\n%s', commit_msg) | 419 logging.debug('Commit message:\n%s', commit_msg) |
| 404 else: | 420 else: |
| 405 logging.info('No deps changes detected when rolling from %s to %s. ' | 421 logging.info('Currently pinned chromium_revision: %s (#%s) is newer than ' |
| 406 'Aborting without action.', current_cr_rev, opts.revision) | 422 '%s (#%s). To roll to older revisions, you must pass the ' |
| 423 '--allow-reverse flag.\n' |
| 424 'Aborting without action.', current_cr_rev, current_commit_pos, |
| 425 new_cr_rev, new_commit_pos) |
| 407 return 0 | 426 return 0 |
| 408 | 427 |
| 409 _CreateRollBranch(opts.dry_run) | 428 _CreateRollBranch(opts.dry_run) |
| 410 UpdateDeps(deps_filename, current_cr_rev, opts.revision) | 429 UpdateDeps(deps_filename, current_cr_rev, new_cr_rev) |
| 411 _LocalCommit(commit_msg, opts.dry_run) | 430 _LocalCommit(commit_msg, opts.dry_run) |
| 412 _UploadCL(opts.dry_run) | 431 _UploadCL(opts.dry_run) |
| 413 _LaunchTrybots(opts.dry_run, opts.skip_try) | 432 _LaunchTrybots(opts.dry_run, opts.skip_try) |
| 414 return 0 | 433 return 0 |
| 415 | 434 |
| 416 | 435 |
| 417 if __name__ == '__main__': | 436 if __name__ == '__main__': |
| 418 sys.exit(main()) | 437 sys.exit(main()) |
| OLD | NEW |