blob: 58e807abbe3b6136566f44617b5ab2fe42caa3a4 [file] [log] [blame]
#!/usr/bin/env python
# Copyright 2013 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Extract the latest dynamorio build."""
import optparse
import os
import re
import shutil
import sys
import tempfile
import time
import traceback
import urllib
import urllib2
from common import chromium_utils
from slave import build_directory
from slave import slave_utils
def GetLatestRevision(url, platform):
"""Return the latest official build revision as a string (e.g. '1234').
To be clear, this does NOT download the latest revision; it just
gets the number.
"""
platform_map = {
'win32': 'windows',
'linux': 'linux',
}
try:
# List by last modified date.
response = urllib2.urlopen(url)
except urllib2.URLError:
print '\nFailed to read from URL: ' + url
return None
html = response.read()
revision_list = re.findall(r'%s-r(\d+)\.' % platform_map[platform], html)
if revision_list:
return revision_list[-1]
else:
return None
def GetBuildUrl(url, platform, revision):
"""Compute the url to download the build from.
Args:
options: options object as specified by parser below.
"""
platform_to_archive = {
'win32': 'dynamorio-windows-r%s.zip',
'linux': 'dynamorio-linux-r%s.tar.gz',
}
archive_name = platform_to_archive[platform] % revision
url = url.rstrip('/')
url = '%s/%s' % (url, archive_name)
return url
def real_main(options):
"""Download a build and extract.
Extract to build\\BuildDir\\full-build-win32 and rename it to
build\\BuildDir\\Target
"""
target_build_output_dir = os.path.join(options.build_dir, options.target)
platform = chromium_utils.PlatformName()
revision = options.revision
if not revision:
revision = GetLatestRevision(options.build_url, platform)
if not revision:
print 'Failed to get revision number.'
return slave_utils.ERROR_EXIT_CODE
archive_url = GetBuildUrl(options.build_url, platform, revision)
archive_name = 'dynamorio.' + os.path.basename(archive_url).split('.', 1)[1]
temp_dir = tempfile.mkdtemp()
try:
# We try to download and extract 3 times.
for tries in range(1, 4):
print 'Try %d: Fetching build from %s' % (tries, archive_url)
failure = False
try:
print '%s/%s' % (archive_url, archive_name)
urllib.urlretrieve(archive_url, archive_name)
print '\nDownload complete'
except IOError:
print '\nFailed to download build'
failure = True
if options.halt_on_missing_build:
return slave_utils.ERROR_EXIT_CODE
if failure:
continue
print 'Extracting build %s to %s...' % (archive_name, options.build_dir)
try:
chromium_utils.RemoveDirectory(target_build_output_dir)
chromium_utils.ExtractZip(archive_name, temp_dir)
# Look for the top level directory from extracted build.
entries = os.listdir(temp_dir)
output_dir = temp_dir
if (len(entries) == 1 and
os.path.isdir(os.path.join(output_dir, entries[0]))):
output_dir = os.path.join(output_dir, entries[0])
print 'Moving build from %s to %s' % (output_dir,
target_build_output_dir)
shutil.move(output_dir, target_build_output_dir)
except (OSError, IOError, chromium_utils.ExternalError):
print 'Failed to extract the build.'
# Print out the traceback in a nice format
traceback.print_exc()
# Try again...
time.sleep(3)
continue
return 0
finally:
chromium_utils.RemoveDirectory(temp_dir)
# If we get here, that means that it failed 3 times. We return a failure.
return slave_utils.ERROR_EXIT_CODE
def main():
option_parser = optparse.OptionParser()
option_parser.add_option('--target',
help='build target to archive (Debug or Release)')
option_parser.add_option('--build-dir', help='ignored')
option_parser.add_option('--build-url',
help='url where to find the build to extract')
option_parser.add_option('--revision',
help='Revision number to download.')
option_parser.add_option('--halt-on-missing-build',
help='Halt on missing build.')
chromium_utils.AddPropertiesOptions(option_parser)
options, args = option_parser.parse_args()
if args:
print 'Unknown options: %s' % args
return 1
options.build_dir = build_directory.GetBuildOutputDirectory()
options.build_dir = os.path.abspath(options.build_dir)
options.build_url = (options.build_url or
options.factory_properties.get('build_url'))
del options.factory_properties
del options.build_properties
return real_main(options)
if '__main__' == __name__:
sys.exit(main())