1#!/usr/bin/env python3 2 3"""Script to do the first step of Abseil roll into chromium. 4""" 5 6import logging 7import os 8import re 9import subprocess 10import tempfile 11from datetime import datetime 12 13ABSL_URI = 'https://github.com/abseil/abseil-cpp.git' 14 15def _PullAbseil(abseil_dir): 16 logging.info('Updating abseil...') 17 subprocess.check_call(['git', 'clone', ABSL_URI], 18 cwd=abseil_dir) 19 20def _SyncChromium(chromium_dir): 21 logging.info('Updating chromium...') 22 subprocess.check_call(['git', 'checkout', 'main'], cwd=chromium_dir) 23 subprocess.check_call(['git', 'pull', '--rebase'], cwd=chromium_dir) 24 subprocess.check_call(['gclient', 'sync'], cwd=chromium_dir) 25 26 27def _UpdateChromiumReadme(readme_filename, abseil_dir): 28 logging.info('Updating ' + readme_filename) 29 30 stdout = subprocess.check_output(['git', 'log', '-n1', '--pretty=short'], 31 cwd=abseil_dir) 32 new_revision = re.search('commit\\s(.{40})', str(stdout)).group(1) 33 34 with open(readme_filename, 'r+') as f: 35 content = f.read() 36 prefix = 'Revision: ' 37 pos = content.find(prefix) 38 assert(pos > 0) 39 pos = pos + len(prefix) 40 old_revision = content[pos:pos+40] 41 f.seek(pos) 42 f.write(new_revision) 43 44 logging.info('Abseil old revision is ' + old_revision) 45 logging.info('Abseil new revision is ' + new_revision) 46 return old_revision[0:10] + '..' + new_revision[0:10] 47 48 49def _UpdateAbseilInChromium(abseil_dir, chromium_dir): 50 logging.info('Syncing abseil in chromium/src/third_party...') 51 exclude = [ 52 '*BUILD.gn', 53 'DIR_METADATA', 54 'README.chromium', 55 'OWNERS', 56 '.gitignore', 57 '.git', 58 '*.gni', 59 '*clang-format', 60 'patches/*', 61 'patches', 62 'absl_hardening_test.cc', 63 'roll_abseil.py', 64 'generate_def_files.py', 65 '*.def', 66 ] 67 params = ['rsync', '-aP', abseil_dir, os.path.join(chromium_dir, 'third_party'), '--delete'] 68 for e in exclude: 69 params.append('--exclude={}'.format(e)) 70 subprocess.check_call(params, cwd=chromium_dir) 71 72 73def _PatchAbseil(abseil_in_chromium_dir): 74 logging.info('Patching abseil...') 75 for patch in os.listdir(os.path.join(abseil_in_chromium_dir, 'patches')): 76 subprocess.check_call(['patch', '--strip', '1', '-i', os.path.join(abseil_in_chromium_dir, 'patches', patch)]) 77 78 os.remove(os.path.join(abseil_in_chromium_dir, 'absl', 'base', 'internal', 'thread_annotations.h')) 79 os.remove(os.path.join(abseil_in_chromium_dir, 'absl', 'base', 'internal', 'dynamic_annotations.h')) 80 81 82def _Commit(chromium_dir, hash_diff): 83 logging.info('Commit...') 84 desc="""Roll abseil_revision {0} 85 86Change Log: 87https://chromium.googlesource.com/external/github.com/abseil/abseil-cpp/+log/{0} 88Full diff: 89https://chromium.googlesource.com/external/github.com/abseil/abseil-cpp/+/{0} 90Bug: None""".format(hash_diff) 91 92 subprocess.check_call(['git', 'add', 'third_party/abseil-cpp'], cwd=chromium_dir) 93 subprocess.check_call(['git', 'commit', '-m', desc], cwd=chromium_dir) 94 95 logging.info('Upload...') 96 subprocess.check_call(['git', 'cl', 'upload', '-m', desc, '--bypass-hooks'], cwd=chromium_dir) 97 98 99def _Roll(): 100 chromium_dir = os.getcwd() 101 abseil_in_chromium_dir = os.path.join(chromium_dir, 'third_party', 'abseil-cpp') 102 _SyncChromium(chromium_dir) 103 104 branch_name = datetime.today().strftime('rolling-absl-%Y%m%d') 105 logging.info('Creating branch ' + branch_name + ' for the roll...') 106 subprocess.check_call(['git', 'checkout', '-b', branch_name], cwd=chromium_dir) 107 108 with tempfile.TemporaryDirectory() as abseil_root: 109 _PullAbseil(abseil_root) 110 abseil_dir = os.path.join(abseil_root, 'abseil-cpp') 111 _UpdateAbseilInChromium(abseil_dir, chromium_dir) 112 hash_diff = _UpdateChromiumReadme(os.path.join(abseil_in_chromium_dir, 'README.chromium'), 113 abseil_dir) 114 115 _PatchAbseil(abseil_in_chromium_dir) 116 _Commit(chromium_dir, hash_diff) 117 118 119if __name__ == '__main__': 120 logging.getLogger().setLevel(logging.INFO) 121 122 if os.getcwd().endswith('src') and os.path.exists('chrome/browser'): 123 _Roll() 124 125 logging.info("Next step is manual: Fix BUILD.gn files to match BUILD.bazel changes.") 126 logging.info("After that run generate_def_files.py. ") 127 else: 128 logging.error('Run this script from a chromium/src/ directory.') 129 130 131