a32ec7c4eb77fb4b212f2a51aa3352399b36ae0f
[WebKit.git] / Tools / Scripts / webkitpy / benchmark_runner / benchmark_builder.py
1 #!/usr/bin/env python
2
3 import logging
4 import tempfile
5 import os
6 import urllib
7 import shutil
8 import subprocess
9 import tarfile
10
11 from zipfile import ZipFile
12 from webkitpy.benchmark_runner.utils import get_path_from_project_root, force_remove
13
14
15 _log = logging.getLogger(__name__)
16
17
18 class BenchmarkBuilder(object):
19     def __init__(self, name, plan):
20         self._name = name
21         self._plan = plan
22
23     def __enter__(self):
24         self._web_root = tempfile.mkdtemp()
25         self._dest = os.path.join(self._web_root, self._name)
26         if 'local_copy' in self._plan:
27             self._copy_benchmark_to_temp_dir(self._plan['local_copy'])
28         elif 'remote_archive' in self._plan:
29             self._fetch_remote_archive(self._plan['remote_archive'])
30         elif 'svn_source' in self._plan:
31             self._checkout_with_subversion(self._plan['svn_source'])
32         else:
33             raise Exception('The benchmark location was not specified')
34
35         _log.info('Copied the benchmark into: %s' % self._dest)
36         try:
37             if 'create_script' in self._plan:
38                 self._run_create_script(self._plan['create_script'])
39             if 'benchmark_patch' in self._plan:
40                 self._apply_patch(self._plan['benchmark_patch'])
41             return self._web_root
42         except Exception:
43             self._clean()
44             raise
45
46     def __exit__(self, exc_type, exc_value, traceback):
47         self._clean()
48
49     def _run_create_script(self, create_script):
50         old_working_directory = os.getcwd()
51         os.chdir(self._dest)
52         _log.debug('Running %s in %s' % (create_script, self._dest))
53         error_code = subprocess.call(create_script)
54         os.chdir(old_working_directory)
55         if error_code:
56             raise Exception('Cannot create the benchmark - Error: %s' % error_code)
57
58     def _copy_benchmark_to_temp_dir(self, benchmark_path):
59         shutil.copytree(get_path_from_project_root(benchmark_path), self._dest)
60
61     def _fetch_remote_archive(self, archive_url):
62         if archive_url.endswith('.zip'):
63             archive_type = 'zip'
64         elif archive_url.endswith('tar.gz'):
65             archive_type = 'tar.gz'
66         else:
67             raise Exception('Could not infer the file extention from URL: %s' % archive_url)
68
69         archive_path = os.path.join(self._web_root, 'archive.' + archive_type)
70         _log.info('Downloading %s to %s' % (archive_url, archive_path))
71         urllib.urlretrieve(archive_url, archive_path)
72
73         if archive_type == 'zip':
74             with ZipFile(archive_path, 'r') as archive:
75                 archive.extractall(self._dest)
76         elif archive_type == 'tar.gz':
77             with tarfile.open(archive_path, 'r:gz') as archive:
78                 archive.extractall(self._dest)
79
80         unarchived_files = filter(lambda name: not name.startswith('.'), os.listdir(self._dest))
81         if len(unarchived_files) == 1:
82             first_file = os.path.join(self._dest, unarchived_files[0])
83             if os.path.isdir(first_file):
84                 shutil.move(first_file, self._web_root)
85                 os.rename(os.path.join(self._web_root, unarchived_files[0]), self._dest)
86
87     def _checkout_with_subversion(self, subversion_url):
88         _log.info('Checking out %s to %s' % (subversion_url, self._dest))
89         error_code = subprocess.call(['svn', 'checkout', '--trust-server-cert', '--non-interactive', subversion_url, self._dest])
90         if error_code:
91             raise Exception('Cannot checkout the benchmark - Error: %s' % error_code)
92
93     def _apply_patch(self, patch):
94         old_working_directory = os.getcwd()
95         os.chdir(self._dest)
96         error_code = subprocess.call(['patch', '-p1', '-f', '-i', get_path_from_project_root(patch)])
97         os.chdir(old_working_directory)
98         if error_code:
99             raise Exception('Cannot apply patch, will skip current benchmark_path - Error: %s' % error_code)
100
101     def _clean(self):
102         _log.info('Cleaning Benchmark')
103         if self._web_root:
104             force_remove(self._web_root)