blob: fbc7bd2eb389d509a2cd561d534e0713485ef756 [file] [log] [blame]
Søren Gjesse1525df32022-06-30 14:04:44 +02001#!/usr/bin/env python3
2# Copyright (c) 2022, the R8 project authors. Please see the AUTHORS file
3# for details. All rights reserved. Use of this source code is governed by a
4# BSD-style license that can be found in the LICENSE file.
5
6import argparse
7import os
8import subprocess
9import sys
10import utils
11
Ian Zerny33f3d812022-09-06 10:59:05 +020012VERSION_FILE = 'src/main/java/com/android/tools/r8/Version.java'
13VERSION_PREFIX = 'String LABEL = "'
14
Søren Gjesse1525df32022-06-30 14:04:44 +020015
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +020016def parse_options():
17 parser = argparse.ArgumentParser(description='Release r8')
18 parser.add_argument('--branch',
19 metavar=('<branch>'),
20 help='Branch to cherry-pick to')
21 parser.add_argument('--current-checkout',
22 '--current_checkout',
23 default=False,
24 action='store_true',
25 help='Perform cherry picks into the current checkout')
26 parser.add_argument('--no-upload',
27 '--no_upload',
28 default=False,
29 action='store_true',
30 help='Do not upload to Gerrit')
31 parser.add_argument('hashes',
32 metavar='<hash>',
33 nargs='+',
34 help='Hashed to merge')
Christoffer Quist Adamsen7daed622023-11-10 11:10:31 +010035 parser.add_argument('remote',
36 default='origin',
37 help='The remote name (defaults to "origin")')
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +020038 return parser.parse_args()
Søren Gjesse1525df32022-06-30 14:04:44 +020039
40
41def run(args):
Christoffer Quist Adamsen7daed622023-11-10 11:10:31 +010042 if args.current_checkout:
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +020043 for i in range(len(args.hashes) + 1):
Christoffer Quist Adamsen7daed622023-11-10 11:10:31 +010044 branch = 'cherry-%s-%d' % (args.branch, i + 1)
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +020045 print('Deleting branch %s' % branch)
46 subprocess.run(['git', 'branch', branch, '-D'])
Søren Gjesse1525df32022-06-30 14:04:44 +020047
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +020048 bugs = set()
Ian Zerny33f3d812022-09-06 10:59:05 +020049
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +020050 count = 1
51 for hash in args.hashes:
Christoffer Quist Adamsen7daed622023-11-10 11:10:31 +010052 branch = 'cherry-%s-%d' % (args.branch, count)
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +020053 print('Cherry-picking %s in %s' % (hash, branch))
Christoffer Quist Adamsen7daed622023-11-10 11:10:31 +010054 if count == 1:
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +020055 subprocess.run([
56 'git', 'new-branch', branch, '--upstream',
Christoffer Quist Adamsen7daed622023-11-10 11:10:31 +010057 '%s/%s' % (args.remote, args.branch)
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +020058 ])
59 else:
60 subprocess.run(['git', 'new-branch', branch, '--upstream-current'])
61
62 subprocess.run(['git', 'cherry-pick', hash])
63 confirm_and_upload(branch, args, bugs)
64 count = count + 1
65
Christoffer Quist Adamsen7daed622023-11-10 11:10:31 +010066 branch = 'cherry-%s-%d' % (args.branch, count)
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +020067 subprocess.run(['git', 'new-branch', branch, '--upstream-current'])
68
69 old_version = 'unknown'
70 for line in open(VERSION_FILE, 'r'):
71 index = line.find(VERSION_PREFIX)
72 if index > 0:
73 index += len(VERSION_PREFIX)
74 subline = line[index:]
75 old_version = subline[:subline.index('"')]
76 break
77
78 new_version = 'unknown'
79 if old_version.find('.') > 0:
80 split_version = old_version.split('.')
81 new_version = '.'.join(split_version[:-1] +
82 [str(int(split_version[-1]) + 1)])
83 subprocess.run([
84 'sed', '-i',
85 's/%s/%s/' % (old_version, new_version), VERSION_FILE
86 ])
Søren Gjesse1525df32022-06-30 14:04:44 +020087 else:
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +020088 editor = os.environ.get('VISUAL')
89 if not editor:
90 editor = os.environ.get('EDITOR')
91 if not editor:
92 editor = 'vi'
93 else:
94 print("Opening %s for version update with %s" %
95 (VERSION_FILE, editor))
96 subprocess.run([editor, VERSION_FILE])
Søren Gjesse1525df32022-06-30 14:04:44 +020097
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +020098 message = ("Version %s\n\n" % new_version)
99 for bug in sorted(bugs):
100 message += 'Bug: b/%s\n' % bug
Søren Gjesse1525df32022-06-30 14:04:44 +0200101
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +0200102 subprocess.run(['git', 'commit', '-a', '-m', message])
103 confirm_and_upload(branch, args, None)
Christoffer Quist Adamsen7daed622023-11-10 11:10:31 +0100104 if not args.current_checkout:
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +0200105 while True:
106 try:
107 answer = input(
108 "Type 'delete' to finish and delete checkout in %s: " %
109 os.getcwd())
110 if answer == 'delete':
111 break
112 except KeyboardInterrupt:
113 pass
Ian Zerny33f3d812022-09-06 10:59:05 +0200114
Søren Gjesse1525df32022-06-30 14:04:44 +0200115
Ian Zerny8b9c0af2022-09-07 12:56:03 +0200116def confirm_and_upload(branch, args, bugs):
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +0200117 question = ('Ready to continue (cwd %s, will not upload to Gerrit)' %
118 os.getcwd() if args.no_upload else
119 'Ready to upload %s (cwd %s)' % (branch, os.getcwd()))
Ian Zerny8b9c0af2022-09-07 12:56:03 +0200120
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +0200121 while True:
122 try:
123 answer = input(question + ' [yes/abort]? ')
124 if answer == 'yes':
125 break
126 if answer == 'abort':
127 print('Aborting new branch for %s' % branch)
128 sys.exit(1)
129 except KeyboardInterrupt:
130 pass
Ian Zerny8b9c0af2022-09-07 12:56:03 +0200131
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +0200132 # Compute the set of bug refs from the commit message after confirmation.
133 # If done before a conflicting cherry-pick status will potentially include
134 # references that are orthogonal to the pick.
135 if bugs != None:
136 commit_message = subprocess.check_output(
137 ['git', 'log', '--format=%B', '-n', '1', 'HEAD'])
138 commit_lines = [
139 l.strip() for l in commit_message.decode('UTF-8').split('\n')
140 ]
141 for line in commit_lines:
Christoffer Quist Adamsen7daed622023-11-10 11:10:31 +0100142 bug = None
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +0200143 if line.startswith('Bug: '):
Christoffer Quist Adamsen7daed622023-11-10 11:10:31 +0100144 bug = line.replace('Bug: ', '')
145 elif line.startswith('Fixed: '):
146 bug = line.replace('Fixed: ', '')
147 elif line.startswith('Fixes: '):
148 bug = line.replace('Fixes: ', '')
149 if bug:
150 bugs.add(bug.replace('b/', '').strip())
Ian Zerny8b9c0af2022-09-07 12:56:03 +0200151
Christoffer Quist Adamsen7daed622023-11-10 11:10:31 +0100152 if not args.no_upload:
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +0200153 subprocess.run(['git', 'cl', 'upload', '--bypass-hooks'])
154
Ian Zerny33f3d812022-09-06 10:59:05 +0200155
Søren Gjesse1525df32022-06-30 14:04:44 +0200156def main():
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +0200157 args = parse_options()
Søren Gjesse1525df32022-06-30 14:04:44 +0200158
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +0200159 if (not args.current_checkout):
160 with utils.TempDir() as temp:
161 print("Performing cherry-picking in %s" % temp)
162 subprocess.check_call(['git', 'clone', utils.REPO_SOURCE, temp])
163 with utils.ChangedWorkingDirectory(temp):
164 run(args)
165 else:
166 # Run in current directory.
167 print("Performing cherry-picking in %s" % os.getcwd())
168 subprocess.check_output(['git', 'fetch', 'origin'])
Søren Gjesse1525df32022-06-30 14:04:44 +0200169 run(args)
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +0200170
Søren Gjesse1525df32022-06-30 14:04:44 +0200171
172if __name__ == '__main__':
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +0200173 sys.exit(main())