blob: eb114f04fc1ee73188cfcaaa7dde6b7259944ec0 [file] [log] [blame]
# Copyright 2012 Google Inc. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""A utility script that packs the benchmark eggs and an associated bat file
into a zip archive to make the benchmark script easy to transport and use."""
import contextlib
import cStringIO
import datetime
import glob
import logging
import optparse
import os.path
import sys
import zipfile
# This is generally not present in the depot_tools Python installation.
# pylint: disable=F0401
import pkg_resources
_YEAR = datetime.datetime.now().year
# Glob patterns for the eggs we bake in to the zip archive.
_EGG_PATTERNS = [
'Benchmark_Chrome-*.egg',
'ETW-*.egg',
'ETW_Db-*.egg',
'setuptools-*.egg',
]
_SCRIPT_TEMPLATE = """\
@echo off
rem = \"\"\"
:: Copyright %d Google Inc.""" % _YEAR + """
::
:: Licensed under the Apache License, Version 2.0 (the \"License\");
:: you may not use this file except in compliance with the License.
:: You may obtain a copy of the License at
::
:: http://www.apache.org/licenses/LICENSE-2.0
::
:: Unless required by applicable law or agreed to in writing, software
:: distributed under the License is distributed on an \"AS IS\" BASIS,
:: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
:: See the License for the specific language governing permissions and
:: limitations under the License.
python -x "%%~f0" %%*
exit /b %%ERRORLEVEL%%
goto endofPython \"\"\"
import sys
import os
# Prepend the eggs we need to our python path.
_EGGS = [
%(eggs)s
]
dir = os.path.dirname(__file__)
sys.path[0:0] = [os.path.join(dir, egg) for egg in _EGGS]
# And run the main program.
import %(module)s
sys.exit(%(module)s.main())
rem = \"\"\"
:endofPython \"\"\"
"""
_SCRIPT_TEMPLATES = [
('benchmark.bat', _SCRIPT_TEMPLATE, 'benchmark'),
('grinder.bat', _SCRIPT_TEMPLATE, 'grinder'),
('instrument.bat', _SCRIPT_TEMPLATE, 'instrument'),
('optimize.bat', _SCRIPT_TEMPLATE, 'optimize'),
('profile.bat', _SCRIPT_TEMPLATE, 'profile'),
]
_LOGGER = logging.getLogger(__name__)
def _FindEggs(root_dir):
eggs = []
for pattern in _EGG_PATTERNS:
file_spec = os.path.join(root_dir, pattern)
new_eggs = glob.glob(file_spec)
if not new_eggs:
raise RuntimeError('Found no egg for "%s".' % file_spec)
def SortEggs(e1, e2):
d1 = pkg_resources.Distribution.from_filename(e1)
d2 = pkg_resources.Distribution.from_filename(e2)
return cmp(d1.version, d2.version)
# Pick the most recent egg version by sorting them by reverse version.
new_eggs = sorted(new_eggs, SortEggs, reverse=True)
eggs.append(new_eggs[0])
return eggs
def _WriteBatFile(root_dir, file_name, template, module, eggs):
eggs = '\n'.join([' %r,' % os.path.basename(egg) for egg in eggs])
output = template % { 'eggs': eggs, 'module': module }
path = os.path.join(root_dir, file_name)
with open(path, 'wb') as f:
f.write(output)
return path
def _CreateFlatArchive(input_files, output_file):
"""Creates a flat Zip archive of a given set of files.
Creates or overwrites output_file with a zip archive containing input_files.
The input files all reside at the root of the zip archive.
Args:
input_files: a list (or other iterable) of input file paths.
output_file: the path to the output file.
"""
# Create a StringIO for the output.
temp_file = cStringIO.StringIO()
zzip = zipfile.ZipFile(temp_file, 'w', zipfile.ZIP_DEFLATED)
with contextlib.closing(zzip):
for input_file in input_files:
zzip.write(input_file, os.path.basename(input_file))
output = temp_file.getvalue()
# Don't replace an existing output file with identical contents.
if (os.path.exists(output_file) and
open(output_file, 'rb').read() == output):
return
with open(output_file, 'wb') as f:
f.write(output)
def _ParseArgs():
parser = optparse.OptionParser()
parser.add_option('', '--root-dir', dest='root_dir',
help='Root directory where built eggs are to be found.')
parser.add_option('-v', '--verbose', dest='verbose',
action='store_true',
help='Enable verbose logging.')
opts, args = parser.parse_args()
if opts.verbose:
logging.basicConfig(level=logging.INFO)
else:
logging.basicConfig()
if args:
parser.error('This script takes no arguments')
if not opts.root_dir:
parser.error('You must provide a root directory')
# We strip the root-dir param of trailing quotes as a workaround for:
# http://code.google.com/p/gyp/issues/detail?id=272
opts.root_dir = os.path.abspath(opts.root_dir.rstrip('"\''))
return opts
def main():
"""Main function, parses args and performs zipping."""
opts = _ParseArgs()
files_to_archive = []
egg_files = _FindEggs(opts.root_dir)
for bat_file, template, module in _SCRIPT_TEMPLATES:
src_path = _WriteBatFile(opts.root_dir, bat_file, template,
module, egg_files)
files_to_archive.append(src_path)
files_to_archive.extend(egg_files)
_CreateFlatArchive(files_to_archive,
os.path.join(opts.root_dir, 'benchmark.zip'))
if __name__ == '__main__':
sys.exit(main())