6795a5bbbedad67a38b8900007e818b92014f5f2
[WebKit-https.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             patch_file_key = "{driver}_benchmark_patch".format(driver=self._driver)
40             if patch_file_key in self._plan:
41                 self._apply_patch(self._plan[patch_file_key])
42             return self._web_root
43         except Exception:
44             self._clean()
45             raise
46
47     def __exit__(self, exc_type, exc_value, traceback):
48         self._clean()
49
50     def _run_create_script(self, create_script):
51         old_working_directory = os.getcwd()
52         os.chdir(self._dest)
53         _log.debug('Running %s in %s' % (create_script, self._dest))
54         error_code = subprocess.call(create_script)
55         os.chdir(old_working_directory)
56         if error_code:
57             raise Exception('Cannot create the benchmark - Error: %s' % error_code)
58
59     def _copy_benchmark_to_temp_dir(self, benchmark_path):
60         shutil.copytree(get_path_from_project_root(benchmark_path), self._dest)
61
62     def _fetch_remote_archive(self, archive_url):
63         if archive_url.endswith('.zip'):
64             archive_type = 'zip'
65         elif archive_url.endswith('tar.gz'):
66             archive_type = 'tar.gz'
67         else:
68             raise Exception('Could not infer the file extention from URL: %s' % archive_url)
69
70         archive_path = os.path.join(self._web_root, 'archive.' + archive_type)
71         _log.info('Downloading %s to %s' % (archive_url, archive_path))
72         urllib.urlretrieve(archive_url, archive_path)
73
74         if archive_type == 'zip':
75             with ZipFile(archive_path, 'r') as archive:
76                 archive.extractall(self._dest)
77         elif archive_type == 'tar.gz':
78             with tarfile.open(archive_path, 'r:gz') as archive:
79                 archive.extractall(self._dest)
80
81         unarchived_files = filter(lambda name: not name.startswith('.'), os.listdir(self._dest))
82         if len(unarchived_files) == 1:
83             first_file = os.path.join(self._dest, unarchived_files[0])
84             if os.path.isdir(first_file):
85                 shutil.move(first_file, self._web_root)
86                 os.rename(os.path.join(self._web_root, unarchived_files[0]), self._dest)
87
88     def _checkout_with_subversion(self, subversion_url):
89         _log.info('Checking out %s to %s' % (subversion_url, self._dest))
90         error_code = subprocess.call(['svn', 'checkout', '--trust-server-cert', '--non-interactive', subversion_url, self._dest])
91         if error_code:
92             raise Exception('Cannot checkout the benchmark - Error: %s' % error_code)
93
94     def _apply_patch(self, patch):
95         old_working_directory = os.getcwd()
96         os.chdir(self._dest)
97         error_code = subprocess.call(['patch', '-p1', '-f', '-i', get_path_from_project_root(patch)])
98         os.chdir(old_working_directory)
99         if error_code:
100             raise Exception('Cannot apply patch, will skip current benchmark_path - Error: %s' % error_code)
101
102     def _clean(self):
103         _log.info('Cleaning Benchmark')
104         if self._web_root:
105             force_remove(self._web_root)