| #!/usr/bin/env python3 | |
| """Script to roll Abseil into chromium.""" | |
| import argparse | |
| import convert_bazel_to_gn | |
| import generate_def_files | |
| import logging | |
| import os | |
| import re | |
| import subprocess | |
| import tempfile | |
| from datetime import datetime | |
| ABSL_URI = 'https://github.com/abseil/abseil-cpp.git' | |
| def _PullAbseil(abseil_dir, revision): | |
| logging.info('Updating abseil...') | |
| args = ['git', 'clone', ABSL_URI] | |
| if revision: | |
| args.extend(['--revision', revision]) | |
| subprocess.check_call(args, cwd=abseil_dir) | |
| def _SyncChromium(chromium_dir): | |
| logging.info('Updating chromium...') | |
| subprocess.check_call(['git', 'pull', '--rebase'], cwd=chromium_dir) | |
| subprocess.check_call(['gclient', 'sync'], cwd=chromium_dir) | |
| def _UpdateChromiumReadme(readme_filename, abseil_dir): | |
| logging.info('Updating ' + readme_filename) | |
| stdout = subprocess.check_output(['git', 'log', '-n1', '--pretty=short'], | |
| cwd=abseil_dir) | |
| new_revision = re.search('commit\\s(.{40})', str(stdout)).group(1) | |
| with open(readme_filename, 'r+') as f: | |
| content = f.read() | |
| prefix = 'Revision: ' | |
| pos = content.find(prefix) | |
| assert (pos > 0) | |
| pos = pos + len(prefix) | |
| old_revision = content[pos:pos + 40] | |
| f.seek(pos) | |
| f.write(new_revision) | |
| logging.info('Abseil old revision is ' + old_revision) | |
| logging.info('Abseil new revision is ' + new_revision) | |
| return old_revision[0:10] + '..' + new_revision[0:10] | |
| def _UpdateAbseilInChromium(abseil_dir, chromium_dir): | |
| logging.info('Syncing abseil in chromium/src/third_party...') | |
| exclude = [ | |
| '*BUILD.gn', | |
| 'DIR_METADATA', | |
| 'README.chromium', | |
| 'OWNERS', | |
| '.clang-format-ignore', | |
| '.git', | |
| '.gitignore', | |
| '.style.yapf', | |
| '*.gni', | |
| '*clang-format', | |
| 'patches/*', | |
| 'patches', | |
| 'absl_hardening_test.cc', | |
| 'roll_abseil.py', | |
| 'generate_def_files.py', | |
| 'convert_bazel_to_gn.py', | |
| '*.def', | |
| ] | |
| params = [ | |
| 'rsync', '-aP', abseil_dir, | |
| os.path.join(chromium_dir, 'third_party'), '--delete' | |
| ] | |
| for e in exclude: | |
| params.append('--exclude={}'.format(e)) | |
| subprocess.check_call(params, cwd=chromium_dir) | |
| def _PatchAbseil(abseil_in_chromium_dir): | |
| logging.info('Patching abseil...') | |
| for patch in os.listdir(os.path.join(abseil_in_chromium_dir, 'patches')): | |
| subprocess.check_call([ | |
| 'patch', '--strip', '1', '-i', | |
| os.path.join(abseil_in_chromium_dir, 'patches', patch) | |
| ]) | |
| os.remove( | |
| os.path.join(abseil_in_chromium_dir, 'absl', 'base', 'internal', | |
| 'dynamic_annotations.h')) | |
| def _Commit(chromium_dir, hash_diff, should_upload): | |
| logging.info('Commit...') | |
| desc = """Roll abseil_revision {0} | |
| Change Log: | |
| https://chromium.googlesource.com/external/github.com/abseil/abseil-cpp/+log/{0} | |
| Full diff: | |
| https://chromium.googlesource.com/external/github.com/abseil/abseil-cpp/+/{0} | |
| Bug: None""".format(hash_diff) | |
| subprocess.check_call(['git', 'add', 'third_party/abseil-cpp'], | |
| cwd=chromium_dir) | |
| proc = subprocess.run( | |
| ['git', 'diff', '--staged', '--quiet', 'third_party/abseil-cpp'], | |
| cwd=chromium_dir) | |
| if proc.returncode == 0: | |
| logging.info('Abseil is up-to-date, nothing to commit!') | |
| return | |
| subprocess.check_call(['git', 'commit', '-m', desc], cwd=chromium_dir) | |
| if should_upload: | |
| logging.info('Upload...') | |
| subprocess.check_call([ | |
| 'git', 'cl', 'upload', '--commit-description=' + desc, | |
| '--bypass-hooks' | |
| ], | |
| cwd=chromium_dir) | |
| def _Roll(should_branch, should_pull, should_generate_def, should_upload, | |
| revision): | |
| chromium_dir = os.getcwd() | |
| abseil_in_chromium_dir = os.path.join(chromium_dir, 'third_party', | |
| 'abseil-cpp') | |
| if should_branch: | |
| branch_name = datetime.today().strftime('rolling-absl-%Y%m%d') | |
| logging.info('Creating branch ' + branch_name + ' for the roll...') | |
| subprocess.check_call(['git', 'new-branch', branch_name], | |
| cwd=chromium_dir) | |
| if should_pull: | |
| _SyncChromium(chromium_dir) | |
| with tempfile.TemporaryDirectory() as abseil_root: | |
| _PullAbseil(abseil_root, revision) | |
| abseil_dir = os.path.join(abseil_root, 'abseil-cpp') | |
| _UpdateAbseilInChromium(abseil_dir, chromium_dir) | |
| hash_diff = _UpdateChromiumReadme( | |
| os.path.join(abseil_in_chromium_dir, 'README.chromium'), | |
| abseil_dir) | |
| _PatchAbseil(abseil_in_chromium_dir) | |
| convert_bazel_to_gn.convert_all(abseil_in_chromium_dir) | |
| if should_generate_def: | |
| generate_def_files.generate_all(chromium_dir) | |
| _Commit(chromium_dir, hash_diff, should_upload) | |
| if __name__ == '__main__': | |
| logging.getLogger().setLevel(logging.INFO) | |
| parser = argparse.ArgumentParser() | |
| parser.add_argument( | |
| '--no-branch', | |
| action='store_true', | |
| help='Skip creating a new branch, use the current one.') | |
| parser.add_argument('--no-pull', | |
| action='store_true', | |
| help='Skip pulling the latest Chromium revision.') | |
| parser.add_argument('--no-def', | |
| action='store_true', | |
| help='Skip regenerating def files.') | |
| parser.add_argument('--no-upload', | |
| action='store_true', | |
| help='Skip uploading the change.') | |
| parser.add_argument('--revision', | |
| default=None, | |
| help='Revision to roll to. The default is the latest.') | |
| args = parser.parse_args() | |
| if os.getcwd().endswith('src') and os.path.exists('chrome/browser'): | |
| _Roll(not args.no_branch, not args.no_pull, not args.no_def, | |
| not args.no_upload, args.revision) | |
| else: | |
| logging.error('Run this script from a chromium/src/ directory.') |