| #!/usr/bin/env python3 | |
| # Copyright (c) 2021, 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 jdk | |
| import os.path | |
| import re | |
| import subprocess | |
| import sys | |
| import urllib.request | |
| import utils | |
| # Grep match string for 'Version X.Y.Z[-dev]' | |
| VERSION_EXP = '^Version [[:digit:]]\+.[[:digit:]]\+.[[:digit:]]\+\(\|-dev\)$' | |
| # R8 is located in the 'builder' library. | |
| AGP_MAVEN = "https://dl.google.com/android/maven2/com/android/tools/build/builder" | |
| def parse_options(): | |
| parser = argparse.ArgumentParser(description='Tag R8 Versions') | |
| parser.add_argument('--branch', | |
| help='The R8 branch to tag versions on, eg, origin/3.0') | |
| parser.add_argument('--agp', | |
| help='The AGP to compute the tag for, eg, 4.2.0-beta03') | |
| parser.add_argument( | |
| '--dry-run', | |
| default=False, | |
| action='store_true', | |
| help='Print the state changing commands without running them.') | |
| return parser.parse_args() | |
| def run(options, cmd): | |
| print(' '.join(cmd)) | |
| if not options.dry_run: | |
| subprocess.check_call(cmd) | |
| def main(): | |
| args = parse_options() | |
| if args.branch: | |
| tag_r8_branch(args.branch, args) | |
| elif args.agp: | |
| if (args.agp == 'all'): | |
| tag_all_agp_versions(args) | |
| else: | |
| tag_agp_version(args.agp, args) | |
| else: | |
| print("Should use a top-level option, such as --branch or --agp.") | |
| return 1 | |
| return 0 | |
| def prepare_print_version(dist, temp): | |
| wrapper_file = os.path.join( | |
| utils.REPO_ROOT, | |
| 'src/main/java/com/android/tools/r8/utils/PrintR8Version.java') | |
| cmd = [ | |
| jdk.GetJavacExecutable(), | |
| wrapper_file, | |
| '-d', | |
| temp, | |
| '-cp', | |
| dist, | |
| ] | |
| utils.PrintCmd(cmd) | |
| subprocess.check_output(cmd) | |
| return temp | |
| def get_tag_info_on_origin(tag): | |
| output = subprocess.check_output( | |
| ['git', 'ls-remote', '--tags', 'origin', tag]).decode('utf-8') | |
| if len(output.strip()) == 0: | |
| return None | |
| return output | |
| def tag_all_agp_versions(args): | |
| with utils.TempDir() as temp: | |
| url = "%s/maven-metadata.xml" % AGP_MAVEN | |
| metadata = os.path.join(temp, "maven-metadata.xml") | |
| try: | |
| urllib.request.urlretrieve(url, metadata) | |
| except urllib.error.HTTPError as e: | |
| print('Could not find maven-metadata.xml for agp') | |
| print(e) | |
| return 1 | |
| with open(metadata, 'r') as file: | |
| data = file.read() | |
| pattern = r'<version>(.+)</version>' | |
| matches = re.findall(pattern, data) | |
| matches.reverse() | |
| for version in matches: | |
| print('Tagging agp version ' + version) | |
| tag_agp_version(version, args) | |
| def tag_agp_version(agp, args): | |
| tag = 'agp-%s' % agp | |
| result = get_tag_info_on_origin(tag) | |
| if result: | |
| print('Tag %s is already present' % tag) | |
| print(result) | |
| subprocess.call(['git', 'show', '--oneline', '-s', tag]) | |
| return 0 | |
| with utils.TempDir() as temp: | |
| url = "%s/%s/builder-%s.jar" % (AGP_MAVEN, agp, agp) | |
| jar = os.path.join(temp, "agp.jar") | |
| try: | |
| urllib.request.urlretrieve(url, jar) | |
| except urllib.error.HTTPError as e: | |
| print('Could not find jar for agp %s' % agp) | |
| print(e) | |
| return 1 | |
| print_version_helper = prepare_print_version(utils.R8_JAR, temp) | |
| output = subprocess.check_output([ | |
| jdk.GetJavaExecutable(), '-cp', | |
| ':'.join([jar, print_version_helper]), | |
| 'com.android.tools.r8.utils.PrintR8Version' | |
| ]).decode('utf-8') | |
| version = output.split(' ')[0] | |
| run(args, ['git', 'tag', '-f', tag, '-m', tag, '%s^{}' % version]) | |
| run(args, ['git', 'push', '-o', 'push-justification=b/313360935', | |
| 'origin', tag]) | |
| def tag_r8_branch(branch, args): | |
| if not branch.startswith('origin/'): | |
| print('Expected branch to start with origin/') | |
| return 1 | |
| output = subprocess.check_output( | |
| ['git', 'log', '--pretty=format:%H\t%s', '--grep', VERSION_EXP, | |
| branch]).decode('utf-8') | |
| for l in output.split('\n'): | |
| (hash, subject) = l.split('\t') | |
| m = re.search('Version (.+)', subject) | |
| if not m: | |
| print('Unable to find a version for line: %s' % l) | |
| continue | |
| version = m.group(1) | |
| result = get_tag_info_on_origin(version) | |
| if not result: | |
| run(args, ['git', 'tag', '-a', version, '-m', version, hash]) | |
| run(args, ['git', 'push', '-o', 'push-justification=b/313360935', | |
| 'origin', version]) | |
| if args.dry_run: | |
| print('Dry run complete. None of the above have been executed.') | |
| if __name__ == '__main__': | |
| sys.exit(main()) |