Add a --hash option to run_on_app.py

Change-Id: I42beef4c189e33e2d9f4d436bbc06db3cabf8079
diff --git a/tools/run_on_app.py b/tools/run_on_app.py
index 1bd62e3..983ce6d 100755
--- a/tools/run_on_app.py
+++ b/tools/run_on_app.py
@@ -11,12 +11,15 @@
 import sys
 import time
 
+import archive
+import as_utils
 import gmail_data
 import gmscore_data
 import golem
 import nest_data
 from sanitize_libraries import SanitizeLibraries, SanitizeLibrariesInPgconf
 import toolhelper
+import update_prebuilds_in_android
 import utils
 import youtube_data
 import chrome_data
@@ -49,6 +52,8 @@
                     help='Compiler build to use',
                     choices=COMPILER_BUILDS,
                     default='lib')
+  result.add_option('--hash',
+                    help='The version of D8/R8 to use')
   result.add_option('--app',
                     help='What app to run on',
                     choices=APPS)
@@ -186,8 +191,12 @@
                     help='Disable compiler logging',
                     default=False,
                     action='store_true')
-
-  return result.parse_args(argv)
+  (options, args) = result.parse_args(argv)
+  assert not options.hash or options.no_build, (
+      'Argument --no-build is required when using --hash')
+  assert not options.hash or options.compiler_build == 'full', (
+      'Compiler build lib not yet supported with --hash')
+  return (options, args)
 
 # Most apps have -printmapping, -printseeds, -printusage and
 # -printconfiguration in the Proguard configuration. However we don't
@@ -556,6 +565,16 @@
       and not os.path.exists(outdir):
     os.makedirs(outdir)
 
+  if options.hash:
+    # Download r8-<hash>.jar from
+    # https://storage.googleapis.com/r8-releases/raw/<hash>/.
+    download_path = archive.GetUploadDestination(options.hash, 'r8.jar', True)
+    assert utils.file_exists_on_cloud_storage(download_path), (
+        'Could not find r8.jar file from provided hash: %s' % options.hash)
+    destination = os.path.join(utils.LIBS, 'r8-' + options.hash + '.jar')
+    utils.download_file_from_cloud_storage(
+        download_path, destination, quiet=quiet)
+
   # Additional flags for the compiler from the configuration file.
   if 'flags' in values:
     args.extend(values['flags'].split(' '))
@@ -601,11 +620,16 @@
       build = not options.no_build and not options.golem
       stderr_path = os.path.join(temp, 'stderr')
       with open(stderr_path, 'w') as stderr:
+        jar = None
+        main = None
         if options.compiler_build == 'full':
           tool = options.compiler
         else:
           assert(options.compiler_build == 'lib')
           tool = 'r8lib-' + options.compiler
+        if options.hash:
+          jar = os.path.join(utils.LIBS, 'r8-' + options.hash + '.jar')
+          main = 'com.android.tools.r8.' + options.compiler.upper()
         exit_code = toolhelper.run(tool, args,
             build=build,
             debug=not options.no_debug,
@@ -617,7 +641,9 @@
             timeout=options.timeout,
             quiet=quiet,
             cmd_prefix=[
-                'taskset', '-c', options.cpu_list] if options.cpu_list else [])
+                'taskset', '-c', options.cpu_list] if options.cpu_list else [],
+            jar=jar,
+            main=main)
       if exit_code != 0:
         with open(stderr_path) as stderr:
           stderr_text = stderr.read()
diff --git a/tools/toolhelper.py b/tools/toolhelper.py
index 1eee1f7..45d84e2 100644
--- a/tools/toolhelper.py
+++ b/tools/toolhelper.py
@@ -14,7 +14,7 @@
 def run(tool, args, build=None, debug=True,
         profile=False, track_memory_file=None, extra_args=None,
         stderr=None, stdout=None, return_stdout=False, timeout=0, quiet=False,
-        cmd_prefix=None):
+        cmd_prefix=None, jar=None, main=None):
   cmd = []
   if cmd_prefix:
     cmd.extend(cmd_prefix)
@@ -31,7 +31,9 @@
     cmd.append('-ea')
   if profile:
     cmd.append('-agentlib:hprof=cpu=samples,interval=1,depth=8')
-  if tool == 'r8lib-d8':
+  if jar:
+    cmd.extend(['-cp', jar, main])
+  elif tool == 'r8lib-d8':
     cmd.extend(['-cp', utils.R8LIB_JAR, 'com.android.tools.r8.D8'])
   elif tool == 'r8lib-r8':
     cmd.extend(['-cp', utils.R8LIB_JAR, 'com.android.tools.r8.R8'])
diff --git a/tools/update_prebuilds_in_android.py b/tools/update_prebuilds_in_android.py
index ee2b100..22c8863 100755
--- a/tools/update_prebuilds_in_android.py
+++ b/tools/update_prebuilds_in_android.py
@@ -70,20 +70,21 @@
 def copy_other_targets(root, target_root):
   copy_targets(root, target_root, OTHER_TARGETS, OTHER_TARGETS)
 
-def download_hash(root, commit_hash, target):
-  download_target(root, target, commit_hash, True)
+def download_hash(root, commit_hash, target, quiet=False):
+  download_target(root, target, commit_hash, True, quiet=quiet)
 
 def download_version(root, version, target):
   download_target(root, target, version, False)
 
-def download_target(root, target, hash_or_version, is_hash):
+def download_target(root, target, hash_or_version, is_hash, quiet=False):
   download_path = os.path.join(root, target)
   url = archive.GetUploadDestination(
     hash_or_version,
     target,
     is_hash)
-  print 'Downloading: ' + url + ' -> ' + download_path
-  utils.download_file_from_cloud_storage(url, download_path)
+  if not quiet:
+    print 'Downloading: ' + url + ' -> ' + download_path
+  utils.download_file_from_cloud_storage(url, download_path, quiet=quiet)
 
 def main_download(hash, maps, targets, target_root, version):
   jar_targets = JAR_TARGETS_MAP[targets]
diff --git a/tools/utils.py b/tools/utils.py
index 5396c0a..bed28d8 100644
--- a/tools/utils.py
+++ b/tools/utils.py
@@ -316,9 +316,9 @@
   PrintCmd(cmd)
   return subprocess.call(cmd) == 0
 
-def download_file_from_cloud_storage(source, destination):
+def download_file_from_cloud_storage(source, destination, quiet=False):
   cmd = ['gsutil.py', 'cp', source, destination]
-  PrintCmd(cmd)
+  PrintCmd(cmd, quiet=quiet)
   subprocess.check_call(cmd)
 
 def create_archive(name, sources=None):