blob: 6a7109c1082e885e9092d379990995e0b835f5fc [file] [log] [blame]
#!/usr/bin/env python3
# Copyright (c) 2022, the R8 project authors. Please see the AUTHORS file
# for details. All rights reserved. Use of this source code is governed by a
# BSD-style license that can be found in the LICENSE file.
import argparse
import os
import subprocess
import sys
import utils
VERSION_FILE = 'src/main/java/com/android/tools/r8/Version.java'
VERSION_PREFIX = 'String LABEL = "'
def parse_options():
parser = argparse.ArgumentParser(description='Release r8')
parser.add_argument('--branch',
metavar=('<branch>'),
help='Branch to cherry-pick to')
parser.add_argument('--current-checkout', '--current_checkout',
default=False,
action='store_true',
help='Perform cherry picks into the current checkout')
parser.add_argument('--no-upload', '--no_upload',
default=False,
action='store_true',
help='Do not upload to Gerrit')
parser.add_argument('hashes', metavar='<hash>', nargs='+',
help='Hashed to merge')
return parser.parse_args()
def run(args):
# Checkout the branch.
subprocess.check_output(['git', 'checkout', args.branch])
if (args.current_checkout):
for i in range(len(args.hashes) + 1):
branch = 'cherry-%d' % (i + 1)
print('Deleting branch %s' % branch)
subprocess.run(['git', 'branch', branch, '-D'])
bugs = set()
count = 1
for hash in args.hashes:
branch = 'cherry-%d' % count
print('Cherry-picking %s in %s' % (hash, branch))
if (count == 1):
subprocess.run(['git', 'new-branch', branch, '--upstream', 'origin/%s' % args.branch])
else:
subprocess.run(['git', 'new-branch', branch, '--upstream-current'])
subprocess.run(['git', 'cherry-pick', hash])
confirm_and_upload(branch, args, bugs)
count = count + 1
branch = 'cherry-%d' % count
subprocess.run(['git', 'new-branch', branch, '--upstream-current'])
old_version = 'unknown'
for line in open(VERSION_FILE, 'r'):
index = line.find(VERSION_PREFIX)
if index > 0:
index += len(VERSION_PREFIX)
subline = line[index:]
old_version = subline[:subline.index('"')]
break
new_version = 'unknown'
if old_version.find('.') > 0:
split_version = old_version.split('.')
new_version = '.'.join(split_version[:-1] + [str(int(split_version[-1]) + 1)])
subprocess.run(['sed', '-i', 's/%s/%s/' % (old_version, new_version), VERSION_FILE])
else:
editor = os.environ.get('VISUAL')
if not editor:
editor = os.environ.get('EDITOR')
if not editor:
editor = 'vi'
else:
print("Opening %s for version update with %s" % (VERSION_FILE, editor))
subprocess.run([editor, VERSION_FILE])
message = ("Version %s\n\n" % new_version)
for bug in sorted(bugs):
message += 'Bug: b/%s\n' % bug
subprocess.run(['git', 'commit', '-a', '-m', message])
confirm_and_upload(branch, args, None)
if (not args.current_checkout):
while True:
try:
answer = input("Type 'delete' to finish and delete checkout in %s: " % os.getcwd())
if answer == 'delete':
break
except KeyboardInterrupt:
pass
def confirm_and_upload(branch, args, bugs):
question = ('Ready to continue (cwd %s, will not upload to Gerrit)' % os.getcwd()
if args.no_upload else
'Ready to upload %s (cwd %s)' % (branch, os.getcwd()))
while True:
try:
answer = input(question + ' [yes/abort]? ')
if answer == 'yes':
break
if answer == 'abort':
print('Aborting new branch for %s' % branch)
sys.exit(1)
except KeyboardInterrupt:
pass
# Compute the set of bug refs from the commit message after confirmation.
# If done before a conflicting cherry-pick status will potentially include
# references that are orthogonal to the pick.
if bugs != None:
commit_message = subprocess.check_output(['git', 'log', '--format=%B', '-n', '1', 'HEAD'])
commit_lines = [l.strip() for l in commit_message.decode('UTF-8').split('\n')]
for line in commit_lines:
if line.startswith('Bug: '):
normalized = line.replace('Bug: ', '').replace('b/', '')
if len(normalized) > 0:
bugs.add(normalized)
if (not args.no_upload):
subprocess.run(['git', 'cl', 'upload', '--bypass-hooks'])
def main():
args = parse_options()
if (not args.current_checkout):
with utils.TempDir() as temp:
print("Performing cherry-picking in %s" % temp)
subprocess.check_call(['git', 'clone', utils.REPO_SOURCE, temp])
with utils.ChangedWorkingDirectory(temp):
run(args)
else:
# Run in current directory.
print("Performing cherry-picking in %s" % os.getcwd())
subprocess.check_output(['git', 'fetch', 'origin'])
run(args)
if __name__ == '__main__':
sys.exit(main())