| #!/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()) |