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