Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
| 2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. | 2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 3 # Use of this source code is governed by a BSD-style license that can be | 3 # Use of this source code is governed by a BSD-style license that can be |
| 4 # found in the LICENSE file. | 4 # found in the LICENSE file. |
| 5 | 5 |
| 6 """Fetch prebuilt binaries to run PyAuto. | 6 """Fetch prebuilt binaries to run PyAuto. |
| 7 | 7 |
| 8 Sets up Chrome and PyAuto binaries using prebuilt binaries from the | 8 Sets up Chrome and PyAuto binaries using prebuilt binaries from the |
| 9 continuous build archives. Works on mac, win, linux (32 & 64 bit). | 9 continuous build archives. Works on mac, win, linux (32 & 64 bit). |
| 10 | 10 |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 21 import glob | 21 import glob |
| 22 import httplib | 22 import httplib |
| 23 import optparse | 23 import optparse |
| 24 import os | 24 import os |
| 25 import platform | 25 import platform |
| 26 import shutil | 26 import shutil |
| 27 import sys | 27 import sys |
| 28 import urllib | 28 import urllib |
| 29 import urllib2 | 29 import urllib2 |
| 30 import urlparse | 30 import urlparse |
| 31 import socket | |
| 32 import stat | |
| 33 import zipfile | |
| 31 | 34 |
| 32 import pyauto_utils | 35 import pyauto_utils |
| 33 | 36 |
| 37 | |
| 38 class FetchPrebuilt(object): | |
| 39 """Util class to fetch prebuilt binaries to run PyAuto.""" | |
| 40 | |
| 41 def __init__(self, url, outdir, platform): | |
| 42 self._url = url | |
| 43 if not self.DoesUrlExist(self._url): | |
| 44 raise httplib.error('%s is not a valid URL.' % self._url) | |
| 45 self._outdir = outdir | |
| 46 self._platform = platform | |
| 47 self._InitZipName() | |
| 48 self._InitDownloadUrls() | |
| 34 | 49 |
| 35 class FetchPrebuilt(object): | 50 def _InitZipName(self): |
| 36 """Util class to fetch prebuilt binaries to run PyAuto.""" | 51 """Determines the name of the zip file based on platform.""" |
| 37 | 52 if not self._platform.startswith('linux'): |
| 38 def _ParseArgs(self): | 53 self._chrome_zip_name = 'chrome-%s' % { 'mac' : 'mac', |
| 39 parser = optparse.OptionParser() | 54 'win' : 'win32' |
| 40 parser.add_option( | 55 }[self._platform] |
| 41 '-d', '--outdir', type='string', default=None, | |
| 42 help='Directory in which to setup. This is typically the directory ' | |
| 43 'where the binaries would go when compiled from source.') | |
| 44 parser.add_option( | |
| 45 '-p', '--platform', type='string', | |
| 46 default=pyauto_utils.GetCurrentPlatform(), | |
| 47 help='Platform. Valid options: win, mac, linux32, linux64. ' | |
| 48 'Default: current platform (%s)' % pyauto_utils.GetCurrentPlatform()) | |
| 49 parser.add_option( | |
| 50 '-l', '--latest', action='store_true', default=False, | |
| 51 help='Download the latest chromium build from commondatastorage. ' | |
| 52 '[default=False]') | |
| 53 self._options, self._args = parser.parse_args() | |
| 54 if self._options.latest: | |
| 55 self._url = self._GetLastestDownloadURL(self._options.platform) | |
| 56 elif not self._args: | |
| 57 print >>sys.stderr, 'Need download url' | |
| 58 sys.exit(2) | |
| 59 else: | |
| 60 self._url = self._args[0] | |
| 61 if not self._options.outdir: | |
| 62 print >>sys.stderr, 'Need output directory: -d/--outdir' | |
| 63 sys.exit(1) | |
| 64 self._outdir = self._options.outdir | |
| 65 # Chromium continuous build archive has a non-standard format. | |
| 66 if 'index.html?path=' in self._url: | |
| 67 self._url = self._url.replace('index.html?path=', '') | |
| 68 self._url = self._url.rstrip('/') | |
| 69 # Determine name of zip. | |
| 70 if not self._options.platform.startswith('linux'): | |
| 71 self._chrome_zip_name = 'chrome-%s' % {'mac': 'mac', | |
| 72 'win': 'win32' | |
| 73 }[self._options.platform] | |
| 74 else: | 56 else: |
| 75 linux_32_names = ['linux', 'lucid32bit'] | 57 linux_32_names = ['linux', 'lucid32bit'] |
| 76 linux_64_names = ['linux64', 'lucid64bit'] | 58 linux_64_names = ['linux64', 'lucid64bit'] |
| 77 linux_names = {'linux': linux_32_names + linux_64_names, | 59 linux_names = {'linux': linux_32_names + linux_64_names, |
| 78 'linux32': linux_32_names, | 60 'linux32': linux_32_names, |
| 79 'linux64': linux_64_names | 61 'linux64': linux_64_names |
| 80 }[self._options.platform] | 62 }[self._platform] |
| 81 for name in linux_names: | 63 for name in linux_names: |
| 82 zip_name = 'chrome-' + name | 64 zip_name = 'chrome-' + name |
| 83 if self._DoesURLExist('%s/%s.zip' % (self._url, zip_name)): | 65 if self.DoesUrlExist('%s/%s.zip' % (self._url, zip_name)): |
| 84 self._chrome_zip_name = zip_name | 66 self._chrome_zip_name = zip_name |
| 85 break | 67 break |
| 86 else: | 68 else: |
| 87 raise RuntimeError('Could not find chrome zip at ' + self._url) | 69 raise RuntimeError('Could not find %s at ' % zip_name + self._url) |
| 88 | 70 |
| 89 # Setup urls to download. | 71 def _InitDownloadUrls(self): |
| 72 """Generates URLs for files that are to be downloaded.""" | |
| 90 self._chrome_zip_url = '%s/%s.zip' % (self._url, self._chrome_zip_name) | 73 self._chrome_zip_url = '%s/%s.zip' % (self._url, self._chrome_zip_name) |
| 91 self._remoting_zip_url = self._url + '/' + 'remoting-webapp.zip' | 74 self._remoting_zip_url = self._url + '/' + 'remoting-webapp.zip' |
| 92 chrome_test_url = '%s/%s.test' % (self._url, self._chrome_zip_name) | 75 chrome_test_url = '%s/%s.test' % (self._url, self._chrome_zip_name) |
| 93 self._pyautolib_py_url = '%s/pyautolib.py' % chrome_test_url | 76 self._pyautolib_py_url = '%s/pyautolib.py' % chrome_test_url |
| 94 if self._options.platform == 'win': | 77 if self._platform == 'win': |
| 95 self._pyautolib_so_name = '_pyautolib.pyd' | 78 self._pyautolib_so_name = '_pyautolib.pyd' |
| 96 self._chromedriver_name = 'chromedriver.exe' | 79 self._chromedriver_name = 'chromedriver.exe' |
| 97 else: | 80 else: |
| 98 self._pyautolib_so_name = '_pyautolib.so' | 81 self._pyautolib_so_name = '_pyautolib.so' |
| 99 self._chromedriver_name = 'chromedriver' | 82 self._chromedriver_name = 'chromedriver' |
| 100 if self._options.platform == 'mac': | 83 if self._platform == 'mac': |
| 101 self._ffmpegsumo_so_name = 'ffmpegsumo.so' | 84 self._ffmpegsumo_so_name = 'ffmpegsumo.so' |
| 102 self._ffmpegsumo_so_url = chrome_test_url + '/' + self._ffmpegsumo_so_name | 85 self._ffmpegsumo_so_url = chrome_test_url + '/' + self._ffmpegsumo_so_name |
| 103 self._pyautolib_so_url = chrome_test_url + '/' + self._pyautolib_so_name | 86 self._pyautolib_so_url = chrome_test_url + '/' + self._pyautolib_so_name |
| 104 self._chromedriver_url = chrome_test_url + '/' + self._chromedriver_name | 87 self._chromedriver_url = chrome_test_url + '/' + self._chromedriver_name |
| 105 | 88 |
| 106 def _GetLastestDownloadURL(self, os_platform): | 89 @staticmethod |
| 90 def GetLastestDownloadURL(os_platform): | |
| 107 os_type = {'win': 'Win', | 91 os_type = {'win': 'Win', |
| 108 'mac': 'Mac', | 92 'mac': 'Mac', |
| 109 'linux': 'Linux', | 93 'linux': 'Linux', |
| 110 'linux32': 'Linux', | 94 'linux32': 'Linux', |
| 111 'linux64': 'Linux_x64'}[os_platform] | 95 'linux64': 'Linux_x64'}[os_platform] |
| 112 if os_type == 'Linux' and platform.architecture()[0] == '64bit': | 96 if os_type == 'Linux' and platform.architecture()[0] == '64bit': |
| 113 os_type = 'Linux_x64' | 97 os_type = 'Linux_x64' |
| 114 last_change_url = ('http://commondatastorage.googleapis.com/' | 98 last_change_url = ('http://commondatastorage.googleapis.com/' |
| 115 'chromium-browser-continuous/%s/LAST_CHANGE' % os_type) | 99 'chromium-browser-continuous/%s/LAST_CHANGE' % os_type) |
| 116 response = urllib2.urlopen(last_change_url) | 100 response = urllib2.urlopen(last_change_url) |
| 117 last_change = response.read() | 101 last_change = response.read() |
| 118 if not last_change: | 102 if not last_change: |
| 119 print >>sys.stderr, ('Unable to get latest from %s' % last_change_url) | 103 print >>sys.stderr, ('Unable to get latest from %s' % last_change_url) |
| 120 sys.exit(2) | 104 sys.exit(2) |
| 121 last_change_url = ('http://commondatastorage.googleapis.com/' | 105 last_change_url = ('http://commondatastorage.googleapis.com/' |
| 122 'chromium-browser-continuous/%s/%s' % (os_type, | 106 'chromium-browser-continuous/%s/%s' % (os_type, |
| 123 last_change)) | 107 last_change)) |
| 124 return last_change_url | 108 return last_change_url |
| 125 | 109 |
| 126 def _DoesURLExist(self, url): | 110 def DoesUrlExist(self, url): |
| 127 """Determines whether a resource exists at the given URL.""" | 111 """Determines whether a resource exists at the given URL.""" |
| 128 parsed = urlparse.urlparse(url) | 112 parsed = urlparse.urlparse(url) |
| 129 conn = httplib.HTTPConnection(parsed.netloc) | 113 try: |
| 130 conn.request('HEAD', parsed.path) | 114 conn = httplib.HTTPConnection(parsed.netloc) |
| 131 response = conn.getresponse() | 115 conn.request('HEAD', parsed.path) |
| 132 if response.status == 302: # Redirect; follow it. | 116 response = conn.getresponse() |
| 133 return self._DoesURLExist(response.getheader('location')) | 117 except (socket.gaierror, socket.error), err: |
| 118 print 'FetchPrebuilt.DoesUrlExist: %s' % err | |
| 119 return False | |
| 120 finally: | |
| 121 conn.close() | |
| 122 # Follow both permanent (301) and temporary (302) redirects. | |
| 123 if response.status == 302 or response.status == 301: | |
| 124 return self.DoesUrlExist(response.getheader('location')) | |
| 134 return response.status == 200 | 125 return response.status == 200 |
| 135 | 126 |
| 136 def Cleanup(self): | 127 def _Cleanup(self): |
| 137 """Remove old binaries, if any.""" | 128 """Remove old binaries, if any.""" |
| 138 pass | 129 |
| 130 def OnError(func, path, exc_info): | |
|
Nirnimesh
2012/08/09 21:32:48
_OnError
nkang
2012/08/16 23:46:24
Done.
| |
| 131 """Callback for shutil.rmtree.""" | |
| 132 if not os.access(path, os.W_OK): | |
| 133 os.chmod(path, stat.S_IRWXU | stat.S_IRWXG | stat.S_IRWXO) | |
| 134 func(path) | |
| 135 else: | |
| 136 raise OSError('%s is not a read-only file, access denied.' % path) | |
| 137 | |
| 138 lst_dirs = ['PepperFlash', 'remoting', 'locales', 'resources', 'installer'] | |
| 139 paths = [os.path.join(self._outdir, name) for name in lst_dirs] | |
| 140 for path in paths: | |
| 141 if os.path.exists(path): | |
| 142 try: | |
| 143 shutil.rmtree(path, onerror=OnError) | |
| 144 except (OSError, IOError): | |
|
Nirnimesh
2012/08/09 21:32:48
Since you're just re-raising the exception, the tr
nkang
2012/08/16 23:46:24
Got rid of the try/except block.
| |
| 145 raise RuntimeError('Could not delete %s, access violation' % path) | |
| 139 | 146 |
| 140 def Run(self): | 147 def Run(self): |
| 141 self._ParseArgs() | |
| 142 if not os.path.isdir(self._outdir): | 148 if not os.path.isdir(self._outdir): |
| 143 os.makedirs(self._outdir) | 149 os.makedirs(self._outdir) |
| 144 get_remoting = self._DoesURLExist(self._remoting_zip_url) | 150 else: |
| 145 | 151 print 'Cleaning up %s' % self._outdir |
| 152 self._Cleanup() | |
| 153 get_remoting = self.DoesUrlExist(self._remoting_zip_url) | |
| 146 # Fetch chrome & pyauto binaries | 154 # Fetch chrome & pyauto binaries |
| 147 print 'Fetching', self._chrome_zip_url | 155 print 'Fetching', self._chrome_zip_url |
| 148 chrome_zip = urllib.urlretrieve(self._chrome_zip_url)[0] | 156 chrome_zip = urllib.urlretrieve(self._chrome_zip_url)[0] |
| 149 | 157 |
| 150 if get_remoting: | 158 if get_remoting: |
| 151 print 'Fetching', self._remoting_zip_url | 159 print 'Fetching', self._remoting_zip_url |
| 152 remoting_zip = urllib.urlretrieve(self._remoting_zip_url)[0] | 160 remoting_zip = urllib.urlretrieve(self._remoting_zip_url)[0] |
| 153 else: | 161 else: |
| 154 print 'Warning: %s does not exist.' % self._remoting_zip_url | 162 print 'Warning: %s does not exist.' % self._remoting_zip_url |
| 155 | 163 |
| 156 print 'Fetching', self._pyautolib_py_url | 164 print 'Fetching', self._pyautolib_py_url |
| 157 pyautolib_py = urllib.urlretrieve(self._pyautolib_py_url)[0] | 165 pyautolib_py = urllib.urlretrieve(self._pyautolib_py_url)[0] |
| 158 | 166 |
| 159 print 'Fetching', self._pyautolib_so_url | 167 print 'Fetching', self._pyautolib_so_url |
| 160 pyautolib_so = urllib.urlretrieve(self._pyautolib_so_url)[0] | 168 pyautolib_so = urllib.urlretrieve(self._pyautolib_so_url)[0] |
| 161 | 169 |
| 162 if self._options.platform == 'mac': | 170 if self._platform == 'mac': |
| 163 print 'Fetching', self._ffmpegsumo_so_url | 171 print 'Fetching', self._ffmpegsumo_so_url |
| 164 ffmpegsumo_so = urllib.urlretrieve(self._ffmpegsumo_so_url)[0] | 172 ffmpegsumo_so = urllib.urlretrieve(self._ffmpegsumo_so_url)[0] |
| 165 | 173 |
| 166 print 'Fetching', self._chromedriver_url | 174 print 'Fetching', self._chromedriver_url |
| 167 chromedriver = urllib.urlretrieve(self._chromedriver_url)[0] | 175 chromedriver = urllib.urlretrieve(self._chromedriver_url)[0] |
| 168 | 176 |
| 169 chrome_unzip_dir = os.path.join(self._outdir, self._chrome_zip_name) | 177 chrome_unzip_dir = os.path.join(self._outdir, self._chrome_zip_name) |
| 170 if os.path.exists(chrome_unzip_dir): | 178 if os.path.exists(chrome_unzip_dir): |
| 171 print 'Cleaning', chrome_unzip_dir | 179 print 'Cleaning', chrome_unzip_dir |
| 172 pyauto_utils.RemovePath(chrome_unzip_dir) | 180 pyauto_utils.RemovePath(chrome_unzip_dir) |
| 173 print 'Unzipping' | 181 print 'Unzipping' |
| 174 pyauto_utils.UnzipFilenameToDir(chrome_zip, self._outdir) | 182 try: |
| 183 pyauto_utils.UnzipFilenameToDir(chrome_zip, self._outdir) | |
| 184 except zipfile.BadZipfile: | |
| 185 raise RuntimeError('Specified zip file does not exist or is corrupted.') | |
| 175 if get_remoting: | 186 if get_remoting: |
| 176 pyauto_utils.UnzipFilenameToDir(remoting_zip, self._outdir) | 187 pyauto_utils.UnzipFilenameToDir(remoting_zip, self._outdir) |
| 177 shutil.move(self._outdir + '/remoting-webapp', | 188 shutil.move(self._outdir + '/remoting-webapp', |
| 178 self._outdir + '/remoting/remoting.webapp') | 189 self._outdir + '/remoting/remoting.webapp') |
| 179 | 190 # Copy over the binaries to destination directory. |
| 180 # Copy over the binaries to outdir | |
| 181 items_to_copy = { | 191 items_to_copy = { |
| 182 pyautolib_py: os.path.join(self._outdir, 'pyautolib.py'), | 192 pyautolib_py: os.path.join(self._outdir, 'pyautolib.py'), |
| 183 pyautolib_so: os.path.join(self._outdir, self._pyautolib_so_name), | 193 pyautolib_so: os.path.join(self._outdir, self._pyautolib_so_name), |
| 184 chromedriver: os.path.join(self._outdir, self._chromedriver_name) | 194 chromedriver: os.path.join(self._outdir, self._chromedriver_name) |
| 185 } | 195 } |
| 186 if self._options.platform == 'mac': | 196 if self._platform == 'mac': |
| 187 items_to_copy[ffmpegsumo_so] = \ | 197 items_to_copy[ffmpegsumo_so] = \ |
| 188 os.path.join(self._outdir, self._ffmpegsumo_so_name) | 198 os.path.join(self._outdir, self._ffmpegsumo_so_name) |
| 189 | 199 |
| 190 unzip_dir_contents = glob.glob(os.path.join(chrome_unzip_dir, '*')) | 200 unzip_dir_contents = glob.glob(os.path.join(chrome_unzip_dir, '*')) |
| 191 for item in unzip_dir_contents: | 201 for item in unzip_dir_contents: |
| 192 name = os.path.basename(item) | 202 name = os.path.basename(item) |
| 193 items_to_copy[item] = os.path.join(self._outdir, name) | 203 items_to_copy[item] = os.path.join(self._outdir, name) |
| 194 | 204 |
| 195 for src, dest in items_to_copy.iteritems(): | 205 for src, dest in items_to_copy.iteritems(): |
| 196 pyauto_utils.RemovePath(dest) | 206 pyauto_utils.RemovePath(dest) |
| 197 print '%s ==> %s' % (os.path.basename(src), dest) | 207 print '%s ==> %s' % (os.path.basename(src), dest) |
| 198 shutil.move(src, dest) | 208 shutil.move(src, dest) |
| 199 pyauto_utils.RemovePath(chrome_unzip_dir) | 209 pyauto_utils.RemovePath(chrome_unzip_dir) |
| 200 | 210 |
| 201 # Final setup (if any) | 211 # Final setup (if any) |
| 202 # Set executable bit on chromedriver binary. | 212 # Set executable bit on chromedriver binary. |
| 203 if not self._options.platform == 'win': | 213 if not self._platform == 'win': |
| 204 os.chmod(items_to_copy[chromedriver], 0700) | 214 os.chmod(items_to_copy[chromedriver], 0700) |
| 205 | 215 |
| 206 # Create symlink to .framework on Mac | 216 # Create symlink to .framework on Mac |
| 207 if self._options.platform == 'mac': | 217 if self._platform == 'mac': |
| 208 mac_app_name = os.path.basename([x for x in unzip_dir_contents | 218 mac_app_name = os.path.basename([x for x in unzip_dir_contents |
| 209 if x.endswith('.app')][0]) | 219 if x.endswith('.app')][0]) |
| 210 os.chdir(self._outdir) | 220 os.chdir(self._outdir) |
| 211 framework = glob.glob(os.path.join( | 221 framework = glob.glob(os.path.join( |
| 212 mac_app_name, 'Contents', 'Versions', '*', '*.framework'))[0] | 222 mac_app_name, 'Contents', 'Versions', '*', '*.framework'))[0] |
| 213 print framework | 223 print framework |
| 214 dest = os.path.basename(framework) | 224 dest = os.path.basename(framework) |
| 215 os.path.lexists(dest) and os.remove(dest) | 225 os.path.lexists(dest) and os.remove(dest) |
| 216 print 'Creating symlink "%s"' % dest | 226 print 'Creating symlink "%s"' % dest |
| 217 os.symlink(framework, dest) | 227 os.symlink(framework, dest) |
| 218 | 228 |
| 219 print 'Prepared binaries in "%s"' % self._outdir | 229 print 'Prepared binaries in "%s"' % self._outdir |
| 220 return 0 | 230 return 0 |
| 221 | 231 |
| 222 | 232 |
| 223 if __name__ == '__main__': | 233 class Main: |
| 224 sys.exit(FetchPrebuilt().Run()) | 234 """Main program for fetching a Chrome build.""" |
| 235 | |
| 236 def __init__(self): | |
| 237 self._ParseArgs() | |
| 238 FetchPrebuilt(self._url, self._outdir, self._platform).Run() | |
| 239 | |
| 240 def _ParseArgs(self): | |
|
Nirnimesh
2012/08/09 21:32:48
I think it's better to move _ParseArgs to the abov
nkang
2012/08/16 23:46:24
I moved the Args here at Ken's recommendation. The
| |
| 241 parser = optparse.OptionParser() | |
| 242 parser.add_option( | |
| 243 '-d', '--outdir', type='string', default=None, | |
| 244 help='Directory in which to setup. This is typically the directory ' | |
| 245 'where the binaries would go when compiled from source.') | |
| 246 parser.add_option( | |
| 247 '-p', '--platform', type='string', | |
| 248 default=pyauto_utils.GetCurrentPlatform(), | |
| 249 help='Platform. Valid options: win, mac, linux32, linux64. ' | |
| 250 'Default: current platform (%s)' % pyauto_utils.GetCurrentPlatform()) | |
| 251 parser.add_option( | |
| 252 '-l', '--latest', action='store_true', default=False, | |
| 253 help='Download the latest chromium build from commondatastorage. ' | |
| 254 '[default=False]') | |
| 255 options, args = parser.parse_args() | |
| 256 if not options.outdir: | |
| 257 print >>sys.stderr, 'Need output directory: -d/--outdir' | |
| 258 sys.exit(1) | |
| 259 if options.latest: | |
| 260 self._url = FetchPrebuilt.GetLastestDownloadURL(options.platform) | |
| 261 elif not args: | |
| 262 print >>sys.stderr, 'Need download url' | |
| 263 sys.exit(2) | |
| 264 else: | |
| 265 self._url = args[0] | |
| 266 | |
| 267 self._platform = options.platform | |
| 268 self._outdir = options.outdir | |
| 269 # Chromium continuous build archive has a non-standard format. | |
| 270 if 'index.html?path=' in self._url: | |
| 271 self._url = self._url.replace('index.html?path=', '') | |
| 272 self._url = self._url.rstrip('/') | |
| 273 | |
| 274 | |
| 275 if __name__ == '__main__': | |
| 276 sys.exit(Main()) | |
| OLD | NEW |