Tool for tagging R8 and AGP versions.

Change-Id: I5d4fc39cc7fd02020ef42fd16176aaaae8f23909
diff --git a/src/main/java/com/android/tools/r8/utils/PrintR8Version.java b/src/main/java/com/android/tools/r8/utils/PrintR8Version.java
new file mode 100644
index 0000000..c20d74c
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/utils/PrintR8Version.java
@@ -0,0 +1,13 @@
+// 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.
+package com.android.tools.r8.utils;
+
+import com.android.tools.r8.Version;
+
+public class PrintR8Version {
+
+  public static void main(String[] args) {
+    System.out.println(Version.getVersionString());
+  }
+}
diff --git a/tools/tag_versions.py b/tools/tag_versions.py
new file mode 100755
index 0000000..ebf14ba
--- /dev/null
+++ b/tools/tag_versions.py
@@ -0,0 +1,124 @@
+#!/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:
+    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_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', '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', 'origin', version])
+  if args.dry_run:
+    print('Dry run complete. None of the above have been executed.')
+
+
+if __name__ == '__main__':
+  sys.exit(main())