#!/usr/bin/env python # # Copyright 2016 Google Inc. # # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. """Isolate a locally-managed Android SDK.""" import argparse import os import shlex import shutil import subprocess import sys import utils INFRA_BOTS_DIR = os.path.realpath(os.path.dirname(os.path.abspath(__file__))) ISOLATE_FILE_NAME = 'android_sdk.isolate' REPO_SKIA = 'https://skia.googlesource.com/skia.git' SDK_DIR_NAME = 'android-sdk' def get_isolate_binary(): """Find or, if necessary, obtain the isolate binary.""" # Try to find isolate locally. platform = 'linux64' if sys.platform == 'win32': platform = 'win64' elif sys.platform == 'darwin': platform = 'mac64' repo_isolate = os.path.join(INFRA_BOTS_DIR, 'tools', 'luci-go', platform) path = os.pathsep.join((repo_isolate, os.environ['PATH'])) try: output = subprocess.check_output( ['which', 'isolate'], env={'PATH':path}).rstrip() print 'Found isolate binary: %s' % output return output except subprocess.CalledProcessError: pass # Download isolate from GS. print 'Unable to find isolate binary; attempting to download...' try: subprocess.check_call( ['download_from_google_storage', '--bucket', 'chromium-luci', '-d', repo_isolate]) except OSError as e: raise Exception('Failed to download isolate binary. ' 'Is depot_tools in PATH? Error: %s' % e) except subprocess.CalledProcessError as e: raise Exception('Failed to download isolate binary. ' 'Are you authenticated to Google Storage? Error: %s' % e) output = subprocess.check_output( ['which', 'isolate'], env={'PATH':path}).rstrip() return output def check_isolate_auth(isolate): """Ensure that we're authenticated to the isolate server.""" not_logged_in = 'Not logged in' try: output = subprocess.check_output([isolate, 'whoami']) except subprocess.CalledProcessError: output = not_logged_in if output == not_logged_in: raise Exception('Not authenticated to isolate server. You probably need to ' 'run:\n$ %s login' % isolate) def isolate_android_sdk(android_sdk_root): """Isolate the Android SDK and return the isolated hash.""" repo_isolate_file = os.path.join(INFRA_BOTS_DIR, ISOLATE_FILE_NAME) with utils.tmp_dir(): # Copy the SDK dir contents into a directory with a known name. sdk_dir = os.path.join(os.getcwd(), SDK_DIR_NAME) shutil.copytree(android_sdk_root, sdk_dir) isolate_file = os.path.join(os.getcwd(), ISOLATE_FILE_NAME) shutil.copyfile(repo_isolate_file, isolate_file) # Isolate the SDK. isolate = get_isolate_binary() check_isolate_auth(isolate) android_sdk_relpath = os.path.relpath( sdk_dir, os.path.dirname(isolate_file)) isolate_cmd = [isolate, 'archive', '--quiet', '--isolate-server', 'https://isolateserver.appspot.com', '-i', isolate_file, '-s', 'android_sdk.isolated', '--extra-variable', 'ANDROID_SDK_DIR=%s' % android_sdk_relpath] isolate_out = subprocess.check_output(isolate_cmd).rstrip() return shlex.split(isolate_out)[0] def update_sdk_file(skia_path, isolated_hash): """Edit the android_sdk_hash file, upload a CL.""" with utils.chdir(skia_path): with utils.git_branch(): hash_file = os.path.join('infra', 'bots', 'android_sdk_hash') with open(hash_file, 'w') as f: f.write(isolated_hash) subprocess.check_call([utils.GIT, 'add', hash_file]) subprocess.check_call([utils.GIT, 'commit', '-m', 'Update Android SDK']) subprocess.check_call([utils.GIT, 'cl', 'upload', '--bypass-hooks']) def main(): parser = argparse.ArgumentParser() parser.add_argument('--android_sdk_root', required=True) args = parser.parse_args() skia_path = os.path.abspath(os.path.join(INFRA_BOTS_DIR, os.pardir, os.pardir)) with utils.print_timings(): isolated_hash = isolate_android_sdk(args.android_sdk_root) update_sdk_file(skia_path, isolated_hash) if __name__ == '__main__': main()