| OLD | NEW |
| (Empty) |
| 1 #!/usr/bin/env python | |
| 2 # | |
| 3 # Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | |
| 4 # for details. All rights reserved. Use of this source code is governed by a | |
| 5 # BSD-style license that can be found in the LICENSE file. | |
| 6 | |
| 7 # Gets or updates a DumpRenderTree (a nearly headless build of chrome). This is | |
| 8 # used for running browser tests of client applications. | |
| 9 | |
| 10 import optparse | |
| 11 import os | |
| 12 import platform | |
| 13 import shutil | |
| 14 import subprocess | |
| 15 import sys | |
| 16 import tempfile | |
| 17 import zipfile | |
| 18 | |
| 19 def NormJoin(path1, path2): | |
| 20 return os.path.normpath(os.path.join(path1, path2)) | |
| 21 | |
| 22 # Change into the dart directory as we want the project to be rooted here. | |
| 23 dart_src = NormJoin(os.path.dirname(sys.argv[0]), os.pardir) | |
| 24 os.chdir(dart_src) | |
| 25 | |
| 26 GSUTIL_DIR = os.path.join('third_party', 'gsutil') | |
| 27 GSUTIL = GSUTIL_DIR + '/gsutil' | |
| 28 | |
| 29 DRT_DIR = os.path.join('client', 'tests', 'drt') | |
| 30 DRT_VERSION = os.path.join(DRT_DIR, 'LAST_VERSION') | |
| 31 DRT_LATEST_PATTERN = ( | |
| 32 'gs://dartium-archive/latest/drt-%(osname)s-inc-*.zip') | |
| 33 DRT_PERMANENT_PREFIX = 'gs://dartium-archive/drt-%(osname)s-inc' | |
| 34 | |
| 35 DARTIUM_DIR = os.path.join('client', 'tests', 'dartium') | |
| 36 DARTIUM_VERSION = os.path.join(DARTIUM_DIR, 'LAST_VERSION') | |
| 37 DARTIUM_LATEST_PATTERN = ( | |
| 38 'gs://dartium-archive/latest/dartium-%(osname)s-inc-*.zip') | |
| 39 DARTIUM_PERMANENT_PREFIX = 'gs://dartium-archive/dartium-%(osname)s-inc' | |
| 40 | |
| 41 CHROMEDRIVER_DIR = os.path.join('tools', 'testing', 'dartium-chromedriver') | |
| 42 CHROMEDRIVER_VERSION = os.path.join(CHROMEDRIVER_DIR, 'LAST_VERSION') | |
| 43 CHROMEDRIVER_LATEST_PATTERN = ( | |
| 44 'gs://dartium-archive/latest/chromedriver-%(osname)s-inc-*.zip') | |
| 45 CHROMEDRIVER_PERMANENT_PREFIX = ( | |
| 46 'gs://dartium-archive/chromedriver-%(osname)s-inc') | |
| 47 | |
| 48 sys.path.append(os.path.join(GSUTIL_DIR, 'boto')) | |
| 49 import boto | |
| 50 | |
| 51 | |
| 52 def execute_command(*cmd): | |
| 53 """Execute a command in a subprocess.""" | |
| 54 pipe = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) | |
| 55 output, error = pipe.communicate() | |
| 56 return pipe.returncode, output | |
| 57 | |
| 58 | |
| 59 def execute_command_visible(*cmd): | |
| 60 """Execute a command in a subprocess, but show stdout/stderr.""" | |
| 61 result = subprocess.call(cmd, stdout=sys.stdout, stderr=sys.stderr, | |
| 62 stdin=sys.stdin) | |
| 63 if result != 0: | |
| 64 raise Exception('Execution of "%s" failed' % ' '.join(cmd)) | |
| 65 | |
| 66 | |
| 67 def gsutil(*cmd): | |
| 68 return execute_command('python', GSUTIL, *cmd) | |
| 69 | |
| 70 | |
| 71 def gsutil_visible(*cmd): | |
| 72 execute_command_visible('python', GSUTIL, *cmd) | |
| 73 | |
| 74 | |
| 75 def has_boto_config(): | |
| 76 """Returns true if boto config exists.""" | |
| 77 | |
| 78 config_paths = boto.pyami.config.BotoConfigLocations | |
| 79 if 'AWS_CREDENTIAL_FILE' in os.environ: | |
| 80 config_paths.append(os.environ['AWS_CREDENTIAL_FILE']) | |
| 81 for config_path in config_paths: | |
| 82 if os.path.exists(config_path): | |
| 83 return True | |
| 84 | |
| 85 return False | |
| 86 | |
| 87 | |
| 88 def in_runhooks(): | |
| 89 '''True if this script was called by "gclient runhooks" or "gclient sync"''' | |
| 90 return 'runhooks' in sys.argv | |
| 91 | |
| 92 | |
| 93 def ensure_config(): | |
| 94 # If ~/.boto doesn't exist, tell the user to run "gsutil config" | |
| 95 if not has_boto_config(): | |
| 96 print >>sys.stderr, ''' | |
| 97 ******************************************************************************* | |
| 98 * WARNING: Can't download DumpRenderTree! This is required to test client apps. | |
| 99 * You need to do a one-time configuration step to access Google Storage. | |
| 100 * Please run this command and follow the instructions: | |
| 101 * %s config | |
| 102 * | |
| 103 * NOTE: When prompted you can leave "project-id" blank. Just hit enter. | |
| 104 ******************************************************************************* | |
| 105 ''' % GSUTIL | |
| 106 sys.exit(1) | |
| 107 | |
| 108 | |
| 109 def get_latest(name, directory, version_file, latest_pattern, permanent_prefix): | |
| 110 """Get the latest DumpRenderTree or Dartium binary depending on arguments. | |
| 111 | |
| 112 Args: | |
| 113 directory: target directory (recreated) to install binary | |
| 114 version_file: name of file with the current version stamp | |
| 115 latest_pattern: the google store url pattern pointing to the latest binary | |
| 116 permanent_prefix: stable google store folder used to download versions | |
| 117 """ | |
| 118 system = platform.system() | |
| 119 if system == 'Darwin': | |
| 120 osname = 'mac' | |
| 121 elif system == 'Linux': | |
| 122 osname = 'lucid64' | |
| 123 elif system == 'Windows': | |
| 124 osname = 'win' | |
| 125 else: | |
| 126 print >>sys.stderr, ('WARNING: platform "%s" does not support' | |
| 127 '%s for tests') % (system, name) | |
| 128 return 0 | |
| 129 | |
| 130 ensure_config() | |
| 131 | |
| 132 # Query for the lastest version | |
| 133 pattern = latest_pattern % { 'osname' : osname } | |
| 134 result, out = gsutil('ls', pattern) | |
| 135 if result == 0: | |
| 136 latest = out.split()[-1] | |
| 137 # use permanent link instead, just in case the latest zip entry gets deleted | |
| 138 # while we are downloading it. | |
| 139 latest = (permanent_prefix % { 'osname' : osname } | |
| 140 + latest[latest.rindex('/'):]) | |
| 141 else: # e.g. no access | |
| 142 print "Couldn't download %s: %s\n%s" % (name, pattern, out) | |
| 143 if not os.path.exists(version_file): | |
| 144 print "Tests using %s will not work. Please try again later." % name | |
| 145 return 0 | |
| 146 | |
| 147 # Check if we need to update the file | |
| 148 if os.path.exists(version_file): | |
| 149 v = open(version_file, 'r').read() | |
| 150 if v == latest: | |
| 151 if not in_runhooks(): | |
| 152 print name + ' is up to date.\nVersion: ' + latest | |
| 153 return 0 # up to date | |
| 154 | |
| 155 if os.path.exists(directory): | |
| 156 print 'Removing old %s tree %s' % (name, directory) | |
| 157 shutil.rmtree(directory) | |
| 158 | |
| 159 # download the zip file to a temporary path, and unzip to the target location | |
| 160 temp_dir = tempfile.mkdtemp() | |
| 161 try: | |
| 162 temp_zip = os.path.join(temp_dir, 'drt.zip') | |
| 163 temp_zip_url = 'file://' + temp_zip | |
| 164 # It's nice to show download progress | |
| 165 gsutil_visible('cp', latest, temp_zip_url) | |
| 166 | |
| 167 if platform.system() != 'Windows': | |
| 168 # The Python zip utility does not preserve executable permissions, but | |
| 169 # this does not seem to be a problem for Windows, which does not have a | |
| 170 # built in zip utility. :-/ | |
| 171 result, out = execute_command('unzip', temp_zip, '-d', temp_dir) | |
| 172 if result != 0: | |
| 173 raise Exception('Execution of "unzip %s -d %s" failed: %s' % | |
| 174 (temp_zip, temp_dir, str(out))) | |
| 175 unzipped_dir = temp_dir + '/' + os.path.basename(latest)[:-4] #Remove .zip | |
| 176 else: | |
| 177 z = zipfile.ZipFile(temp_zip) | |
| 178 z.extractall(temp_dir) | |
| 179 # -4 = remove .zip for dir name | |
| 180 unzipped_dir = os.path.join(temp_dir, os.path.basename(latest)[:-4]) | |
| 181 z.close() | |
| 182 shutil.move(unzipped_dir, directory) | |
| 183 finally: | |
| 184 shutil.rmtree(temp_dir) | |
| 185 | |
| 186 # create the version stamp | |
| 187 v = open(version_file, 'w') | |
| 188 v.write(latest) | |
| 189 v.close() | |
| 190 | |
| 191 print 'Successfully downloaded to %s' % directory | |
| 192 return 0 | |
| 193 | |
| 194 | |
| 195 def main(): | |
| 196 parser = optparse.OptionParser() | |
| 197 parser.add_option('--dartium', dest='dartium', | |
| 198 help='Get latest Dartium', action='store_true', | |
| 199 default=False) | |
| 200 parser.add_option('--chromedriver', dest='chromedriver', | |
| 201 help='Get the latest built ChromeDriver', | |
| 202 action='store_true', default=False) | |
| 203 args, _ = parser.parse_args() | |
| 204 | |
| 205 if args.dartium: | |
| 206 get_latest('Dartium', DARTIUM_DIR, DARTIUM_VERSION, | |
| 207 DARTIUM_LATEST_PATTERN, DARTIUM_PERMANENT_PREFIX) | |
| 208 elif args.chromedriver: | |
| 209 get_latest('chromedriver', CHROMEDRIVER_DIR, CHROMEDRIVER_VERSION, | |
| 210 CHROMEDRIVER_LATEST_PATTERN, CHROMEDRIVER_PERMANENT_PREFIX) | |
| 211 else: | |
| 212 get_latest('DumpRenderTree', DRT_DIR, DRT_VERSION, | |
| 213 DRT_LATEST_PATTERN, DRT_PERMANENT_PREFIX) | |
| 214 | |
| 215 if __name__ == '__main__': | |
| 216 sys.exit(main()) | |
| OLD | NEW |