| #!/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 json |
| 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('--use-push', |
| default=False, |
| action='store_true', |
| help='To create the tag locally only.') |
| 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 options.dry_run: |
| return |
| try: |
| subprocess.check_call(cmd) |
| except subprocess.CalledProcessError as e: |
| print(e) |
| |
| |
| 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 |
| |
| # Testing info: To delete a tag use |
| # |
| # gob-curl --request DELETE https://r8-review.git.corp.google.com/a/projects/r8/tags/<tag> |
| # |
| def gerrit_tag(args, tag, hash, description): |
| data = json.dumps({ |
| "message": description if description else tag, |
| "revision": hash |
| }) |
| cmd = ' '.join([ |
| 'gob-curl', |
| '--header', |
| '"Content-Type: application/json; charset=UTF-8"', |
| '--request', |
| 'PUT', |
| '--data', |
| "'{data}'".format(data=data), |
| 'https://r8-review.git.corp.google.com/a/projects/r8/tags/{tag}'.format(tag=tag) |
| ]) |
| result = subprocess.check_output(cmd, stderr=subprocess.STDOUT, shell=True) |
| print(result) |
| |
| |
| 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_version, args): |
| tag = 'agp-%s' % agp_version |
| 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_version, agp_version) |
| 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_version) |
| 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') |
| r8_version = output.split(' ')[0] |
| cmd = ' '.join(['git', 'rev-list', '-n', '1', r8_version]) |
| hash = subprocess.check_output(cmd, shell=True).decode('utf-8').strip() |
| message = 'AGP version {version}'.format(version=agp_version) |
| run(args, ['git', 'tag', '-f', tag, '-m', message, hash]) |
| if args.use_push: |
| run(args, [ |
| 'git', 'push', '-o', 'push-justification=b/313360935', 'origin', tag |
| ]) |
| else: |
| gerrit_tag(args, tag, hash, message) |
| |
| |
| 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: |
| message = 'Version {version}'.format(version=version) |
| run(args, ['git', 'tag', '-a', version, '-m', message, hash]) |
| if args.use_push: |
| run(args, [ |
| 'git', 'push', '-o', 'push-justification=b/313360935', 'origin', |
| version |
| ]) |
| else: |
| gerrit_tag(args, version, hash, message) |
| if args.dry_run: |
| print('Dry run complete. None of the above have been executed.') |
| |
| |
| if __name__ == '__main__': |
| sys.exit(main()) |