blob: da68de537f296f8106a5c396286ffd2fd034aa45 [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')
Søren Gjesse0aa74cd2023-11-15 09:32:23 +010035 parser.add_argument('--remote',
Christoffer Quist Adamsen7daed622023-11-10 11:10:31 +010036 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'
Søren Gjesseba542a62024-05-31 13:01:09 +020079 if old_version.find('.') > 0 and old_version.find('-') == -1:
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +020080 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'
Søren Gjesseba542a62024-05-31 13:01:09 +020093 print("Opening %s for version update with %s" %
94 (VERSION_FILE, editor))
95 subprocess.run([editor, VERSION_FILE])
Søren Gjesse1525df32022-06-30 14:04:44 +020096
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +020097 message = ("Version %s\n\n" % new_version)
98 for bug in sorted(bugs):
99 message += 'Bug: b/%s\n' % bug
Søren Gjesse1525df32022-06-30 14:04:44 +0200100
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +0200101 subprocess.run(['git', 'commit', '-a', '-m', message])
102 confirm_and_upload(branch, args, None)
Christoffer Quist Adamsen7daed622023-11-10 11:10:31 +0100103 if not args.current_checkout:
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +0200104 while True:
105 try:
106 answer = input(
107 "Type 'delete' to finish and delete checkout in %s: " %
108 os.getcwd())
109 if answer == 'delete':
110 break
111 except KeyboardInterrupt:
112 pass
Ian Zerny33f3d812022-09-06 10:59:05 +0200113
Søren Gjesse1525df32022-06-30 14:04:44 +0200114
Ian Zerny8b9c0af2022-09-07 12:56:03 +0200115def confirm_and_upload(branch, args, bugs):
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +0200116 question = ('Ready to continue (cwd %s, will not upload to Gerrit)' %
117 os.getcwd() if args.no_upload else
118 'Ready to upload %s (cwd %s)' % (branch, os.getcwd()))
Ian Zerny8b9c0af2022-09-07 12:56:03 +0200119
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +0200120 while True:
121 try:
122 answer = input(question + ' [yes/abort]? ')
123 if answer == 'yes':
124 break
125 if answer == 'abort':
126 print('Aborting new branch for %s' % branch)
127 sys.exit(1)
128 except KeyboardInterrupt:
129 pass
Ian Zerny8b9c0af2022-09-07 12:56:03 +0200130
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +0200131 # Compute the set of bug refs from the commit message after confirmation.
132 # If done before a conflicting cherry-pick status will potentially include
133 # references that are orthogonal to the pick.
134 if bugs != None:
135 commit_message = subprocess.check_output(
136 ['git', 'log', '--format=%B', '-n', '1', 'HEAD'])
137 commit_lines = [
138 l.strip() for l in commit_message.decode('UTF-8').split('\n')
139 ]
140 for line in commit_lines:
Christoffer Quist Adamsen7daed622023-11-10 11:10:31 +0100141 bug = None
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +0200142 if line.startswith('Bug: '):
Christoffer Quist Adamsen7daed622023-11-10 11:10:31 +0100143 bug = line.replace('Bug: ', '')
144 elif line.startswith('Fixed: '):
145 bug = line.replace('Fixed: ', '')
146 elif line.startswith('Fixes: '):
147 bug = line.replace('Fixes: ', '')
148 if bug:
149 bugs.add(bug.replace('b/', '').strip())
Ian Zerny8b9c0af2022-09-07 12:56:03 +0200150
Christoffer Quist Adamsen7daed622023-11-10 11:10:31 +0100151 if not args.no_upload:
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +0200152 subprocess.run(['git', 'cl', 'upload', '--bypass-hooks'])
153
Ian Zerny33f3d812022-09-06 10:59:05 +0200154
Søren Gjesse1525df32022-06-30 14:04:44 +0200155def main():
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +0200156 args = parse_options()
Søren Gjesse1525df32022-06-30 14:04:44 +0200157
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +0200158 if (not args.current_checkout):
159 with utils.TempDir() as temp:
160 print("Performing cherry-picking in %s" % temp)
161 subprocess.check_call(['git', 'clone', utils.REPO_SOURCE, temp])
162 with utils.ChangedWorkingDirectory(temp):
163 run(args)
164 else:
165 # Run in current directory.
166 print("Performing cherry-picking in %s" % os.getcwd())
167 subprocess.check_output(['git', 'fetch', 'origin'])
Søren Gjesse1525df32022-06-30 14:04:44 +0200168 run(args)
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +0200169
Søren Gjesse1525df32022-06-30 14:04:44 +0200170
171if __name__ == '__main__':
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +0200172 sys.exit(main())