| 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 """Archives or replays webpages and creates SKPs in a Google Storage location. | 6 """Archives or replays webpages and creates SKPs in a Google Storage location. |
| 7 | 7 |
| 8 To archive webpages and store SKP files (archives should be rarely updated): | 8 To archive webpages and store SKP files (archives should be rarely updated): |
| 9 | 9 |
| 10 cd skia | 10 cd skia |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 56 import optparse | 56 import optparse |
| 57 import os | 57 import os |
| 58 import posixpath | 58 import posixpath |
| 59 import shutil | 59 import shutil |
| 60 import subprocess | 60 import subprocess |
| 61 import sys | 61 import sys |
| 62 import tempfile | 62 import tempfile |
| 63 import time | 63 import time |
| 64 import traceback | 64 import traceback |
| 65 | 65 |
| 66 SKIA_DIR = os.path.abspath(os.path.join( | |
| 67 os.path.realpath(os.path.dirname(__file__)), | |
| 68 os.pardir, os.pardir)) | |
| 69 sys.path.insert(0, SKIA_DIR) | |
| 70 | |
| 71 from common.py.utils import gs_utils | |
| 72 from common.py.utils import shell_utils | |
| 73 | 66 |
| 74 ROOT_PLAYBACK_DIR_NAME = 'playback' | 67 ROOT_PLAYBACK_DIR_NAME = 'playback' |
| 75 SKPICTURES_DIR_NAME = 'skps' | 68 SKPICTURES_DIR_NAME = 'skps' |
| 76 | 69 |
| 70 GS_PREFIX = 'gs://' |
| 71 |
| 77 PARTNERS_GS_BUCKET = 'gs://chrome-partner-telemetry' | 72 PARTNERS_GS_BUCKET = 'gs://chrome-partner-telemetry' |
| 78 | 73 |
| 79 # Local archive and SKP directories. | 74 # Local archive and SKP directories. |
| 80 LOCAL_REPLAY_WEBPAGES_ARCHIVE_DIR = os.path.join( | 75 LOCAL_REPLAY_WEBPAGES_ARCHIVE_DIR = os.path.join( |
| 81 os.path.abspath(os.path.dirname(__file__)), 'page_sets', 'data') | 76 os.path.abspath(os.path.dirname(__file__)), 'page_sets', 'data') |
| 82 TMP_SKP_DIR = tempfile.mkdtemp() | 77 TMP_SKP_DIR = tempfile.mkdtemp() |
| 83 | 78 |
| 84 # Location of the credentials.json file and the string that represents missing | 79 # Location of the credentials.json file and the string that represents missing |
| 85 # passwords. | 80 # passwords. |
| 86 CREDENTIALS_FILE_PATH = os.path.join( | 81 CREDENTIALS_FILE_PATH = os.path.join( |
| (...skipping 17 matching lines...) Expand all Loading... |
| 104 # How many times the record_wpr binary should be retried. | 99 # How many times the record_wpr binary should be retried. |
| 105 RETRY_RECORD_WPR_COUNT = 5 | 100 RETRY_RECORD_WPR_COUNT = 5 |
| 106 # How many times the run_benchmark binary should be retried. | 101 # How many times the run_benchmark binary should be retried. |
| 107 RETRY_RUN_MEASUREMENT_COUNT = 5 | 102 RETRY_RUN_MEASUREMENT_COUNT = 5 |
| 108 | 103 |
| 109 # Location of the credentials.json file in Google Storage. | 104 # Location of the credentials.json file in Google Storage. |
| 110 CREDENTIALS_GS_PATH = '/playback/credentials/credentials.json' | 105 CREDENTIALS_GS_PATH = '/playback/credentials/credentials.json' |
| 111 | 106 |
| 112 X11_DISPLAY = os.getenv('DISPLAY', ':0') | 107 X11_DISPLAY = os.getenv('DISPLAY', ':0') |
| 113 | 108 |
| 114 GS_PREDEFINED_ACL = gs_utils.GSUtils.PredefinedACL.PRIVATE | |
| 115 GS_FINE_GRAINED_ACL_LIST = [ | |
| 116 (gs_utils.GSUtils.IdType.GROUP_BY_DOMAIN, 'google.com', | |
| 117 gs_utils.GSUtils.Permission.READ), | |
| 118 ] | |
| 119 | |
| 120 # Path to Chromium's page sets. | 109 # Path to Chromium's page sets. |
| 121 CHROMIUM_PAGE_SETS_PATH = os.path.join('tools', 'perf', 'page_sets') | 110 CHROMIUM_PAGE_SETS_PATH = os.path.join('tools', 'perf', 'page_sets') |
| 122 | 111 |
| 123 # Dictionary of supported Chromium page sets to their file prefixes. | 112 # Dictionary of supported Chromium page sets to their file prefixes. |
| 124 CHROMIUM_PAGE_SETS_TO_PREFIX = { | 113 CHROMIUM_PAGE_SETS_TO_PREFIX = { |
| 125 'key_mobile_sites_smooth.py': 'keymobi', | 114 'key_mobile_sites_smooth.py': 'keymobi', |
| 126 'top_25_smooth.py': 'top25desk', | 115 'top_25_smooth.py': 'top25desk', |
| 127 } | 116 } |
| 128 | 117 |
| 129 | 118 |
| (...skipping 19 matching lines...) Expand all Loading... |
| 149 CHROMIUM_PAGE_SETS_PATH) | 138 CHROMIUM_PAGE_SETS_PATH) |
| 150 self._all_page_sets_specified = parse_options.page_sets == 'all' | 139 self._all_page_sets_specified = parse_options.page_sets == 'all' |
| 151 self._page_sets = self._ParsePageSets(parse_options.page_sets) | 140 self._page_sets = self._ParsePageSets(parse_options.page_sets) |
| 152 | 141 |
| 153 self._record = parse_options.record | 142 self._record = parse_options.record |
| 154 self._skia_tools = parse_options.skia_tools | 143 self._skia_tools = parse_options.skia_tools |
| 155 self._non_interactive = parse_options.non_interactive | 144 self._non_interactive = parse_options.non_interactive |
| 156 self._upload = parse_options.upload | 145 self._upload = parse_options.upload |
| 157 self._skp_prefix = parse_options.skp_prefix | 146 self._skp_prefix = parse_options.skp_prefix |
| 158 data_store_location = parse_options.data_store | 147 data_store_location = parse_options.data_store |
| 159 if data_store_location.startswith(gs_utils.GS_PREFIX): | 148 if data_store_location.startswith(GS_PREFIX): |
| 160 self.gs = GoogleStorageDataStore(data_store_location) | 149 self.gs = GoogleStorageDataStore(data_store_location) |
| 161 else: | 150 else: |
| 162 self.gs = LocalFileSystemDataStore(data_store_location) | 151 self.gs = LocalFileSystemDataStore(data_store_location) |
| 163 self._upload_to_partner_bucket = parse_options.upload_to_partner_bucket | 152 self._upload_to_partner_bucket = parse_options.upload_to_partner_bucket |
| 164 self._alternate_upload_dir = parse_options.alternate_upload_dir | 153 self._alternate_upload_dir = parse_options.alternate_upload_dir |
| 165 self._telemetry_binaries_dir = os.path.join(parse_options.chrome_src_path, | 154 self._telemetry_binaries_dir = os.path.join(parse_options.chrome_src_path, |
| 166 'tools', 'perf') | 155 'tools', 'perf') |
| 167 self._catapult_dir = os.path.join(parse_options.chrome_src_path, | 156 self._catapult_dir = os.path.join(parse_options.chrome_src_path, |
| 168 'third_party', 'catapult') | 157 'third_party', 'catapult') |
| 169 | 158 |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 254 'DISPLAY=%s' % X11_DISPLAY, | 243 'DISPLAY=%s' % X11_DISPLAY, |
| 255 os.path.join(self._telemetry_binaries_dir, 'record_wpr'), | 244 os.path.join(self._telemetry_binaries_dir, 'record_wpr'), |
| 256 '--extra-browser-args="%s"' % self._browser_args, | 245 '--extra-browser-args="%s"' % self._browser_args, |
| 257 '--browser=exact', | 246 '--browser=exact', |
| 258 '--browser-executable=%s' % self._browser_executable, | 247 '--browser-executable=%s' % self._browser_executable, |
| 259 '%s_page_set' % page_set_basename, | 248 '%s_page_set' % page_set_basename, |
| 260 '--page-set-base-dir=%s' % page_set_dir | 249 '--page-set-base-dir=%s' % page_set_dir |
| 261 ) | 250 ) |
| 262 for _ in range(RETRY_RECORD_WPR_COUNT): | 251 for _ in range(RETRY_RECORD_WPR_COUNT): |
| 263 try: | 252 try: |
| 264 shell_utils.run(' '.join(record_wpr_cmd), shell=True) | 253 subprocess.check_call(' '.join(record_wpr_cmd), shell=True) |
| 265 | 254 |
| 266 # Move over the created archive into the local webpages archive | 255 # Move over the created archive into the local webpages archive |
| 267 # directory. | 256 # directory. |
| 268 shutil.move( | 257 shutil.move( |
| 269 os.path.join(LOCAL_REPLAY_WEBPAGES_ARCHIVE_DIR, wpr_data_file), | 258 os.path.join(LOCAL_REPLAY_WEBPAGES_ARCHIVE_DIR, wpr_data_file), |
| 270 self._local_record_webpages_archive_dir) | 259 self._local_record_webpages_archive_dir) |
| 271 shutil.move( | 260 shutil.move( |
| 272 os.path.join(LOCAL_REPLAY_WEBPAGES_ARCHIVE_DIR, | 261 os.path.join(LOCAL_REPLAY_WEBPAGES_ARCHIVE_DIR, |
| 273 page_set_json_name), | 262 page_set_json_name), |
| 274 self._local_record_webpages_archive_dir) | 263 self._local_record_webpages_archive_dir) |
| (...skipping 23 matching lines...) Expand all Loading... |
| 298 SKP_BENCHMARK, | 287 SKP_BENCHMARK, |
| 299 '--page-set-name=%s' % page_set_basename, | 288 '--page-set-name=%s' % page_set_basename, |
| 300 '--page-set-base-dir=%s' % page_set_dir, | 289 '--page-set-base-dir=%s' % page_set_dir, |
| 301 '--skp-outdir=%s' % TMP_SKP_DIR, | 290 '--skp-outdir=%s' % TMP_SKP_DIR, |
| 302 '--also-run-disabled-tests' | 291 '--also-run-disabled-tests' |
| 303 ) | 292 ) |
| 304 | 293 |
| 305 for _ in range(RETRY_RUN_MEASUREMENT_COUNT): | 294 for _ in range(RETRY_RUN_MEASUREMENT_COUNT): |
| 306 try: | 295 try: |
| 307 print '\n\n=======Capturing SKP of %s=======\n\n' % page_set | 296 print '\n\n=======Capturing SKP of %s=======\n\n' % page_set |
| 308 shell_utils.run(' '.join(run_benchmark_cmd), shell=True) | 297 subprocess.check_call(' '.join(run_benchmark_cmd), shell=True) |
| 309 except shell_utils.CommandFailedException: | 298 except subprocess.CalledProcessError: |
| 310 # skpicture_printer sometimes fails with AssertionError but the | 299 # skpicture_printer sometimes fails with AssertionError but the |
| 311 # captured SKP is still valid. This is a known issue. | 300 # captured SKP is still valid. This is a known issue. |
| 312 pass | 301 pass |
| 313 | 302 |
| 314 # Rename generated SKP files into more descriptive names. | 303 # Rename generated SKP files into more descriptive names. |
| 315 try: | 304 try: |
| 316 self._RenameSkpFiles(page_set) | 305 self._RenameSkpFiles(page_set) |
| 317 # Break out of the retry loop since there were no errors. | 306 # Break out of the retry loop since there were no errors. |
| 318 break | 307 break |
| 319 except Exception: | 308 except Exception: |
| (...skipping 14 matching lines...) Expand all Loading... |
| 334 os.path.join(self._skia_tools, 'render_pictures'), | 323 os.path.join(self._skia_tools, 'render_pictures'), |
| 335 '-r', self._local_skp_dir | 324 '-r', self._local_skp_dir |
| 336 ] | 325 ] |
| 337 render_pdfs_cmd = [ | 326 render_pdfs_cmd = [ |
| 338 os.path.join(self._skia_tools, 'render_pdfs'), | 327 os.path.join(self._skia_tools, 'render_pdfs'), |
| 339 '-r', self._local_skp_dir | 328 '-r', self._local_skp_dir |
| 340 ] | 329 ] |
| 341 | 330 |
| 342 for tools_cmd in (render_pictures_cmd, render_pdfs_cmd): | 331 for tools_cmd in (render_pictures_cmd, render_pdfs_cmd): |
| 343 print '\n\n=======Running %s=======' % ' '.join(tools_cmd) | 332 print '\n\n=======Running %s=======' % ' '.join(tools_cmd) |
| 344 proc = subprocess.Popen(tools_cmd) | 333 subprocess.check_call(tools_cmd) |
| 345 (code, _) = shell_utils.log_process_after_completion(proc, echo=False) | |
| 346 if code != 0: | |
| 347 raise Exception('%s failed!' % ' '.join(tools_cmd)) | |
| 348 | 334 |
| 349 if not self._non_interactive: | 335 if not self._non_interactive: |
| 350 print '\n\n=======Running debugger=======' | 336 print '\n\n=======Running debugger=======' |
| 351 os.system('%s %s' % (os.path.join(self._skia_tools, 'debugger'), | 337 os.system('%s %s' % (os.path.join(self._skia_tools, 'debugger'), |
| 352 self._local_skp_dir)) | 338 self._local_skp_dir)) |
| 353 | 339 |
| 354 print '\n\n' | 340 print '\n\n' |
| 355 | 341 |
| 356 if self._upload: | 342 if self._upload: |
| 357 print '\n\n=======Uploading to %s=======\n\n' % self.gs.target_type() | 343 print '\n\n=======Uploading to %s=======\n\n' % self.gs.target_type() |
| 358 # Copy the directory structure in the root directory into Google Storage. | 344 # Copy the directory structure in the root directory into Google Storage. |
| 359 dest_dir_name = ROOT_PLAYBACK_DIR_NAME | 345 dest_dir_name = ROOT_PLAYBACK_DIR_NAME |
| 360 if self._alternate_upload_dir: | 346 if self._alternate_upload_dir: |
| 361 dest_dir_name = self._alternate_upload_dir | 347 dest_dir_name = self._alternate_upload_dir |
| 362 | 348 |
| 363 self.gs.upload_dir_contents( | 349 self.gs.upload_dir_contents( |
| 364 self._local_skp_dir, dest_dir=dest_dir_name, | 350 self._local_skp_dir, dest_dir=dest_dir_name) |
| 365 upload_if=gs_utils.GSUtils.UploadIf.IF_MODIFIED, | |
| 366 predefined_acl=GS_PREDEFINED_ACL, | |
| 367 fine_grained_acl_list=GS_FINE_GRAINED_ACL_LIST) | |
| 368 | 351 |
| 369 print '\n\n=======New SKPs have been uploaded to %s =======\n\n' % ( | 352 print '\n\n=======New SKPs have been uploaded to %s =======\n\n' % ( |
| 370 posixpath.join(self.gs.target_name(), dest_dir_name, | 353 posixpath.join(self.gs.target_name(), dest_dir_name, |
| 371 SKPICTURES_DIR_NAME)) | 354 SKPICTURES_DIR_NAME)) |
| 372 | 355 |
| 373 else: | 356 else: |
| 374 print '\n\n=======Not Uploading to %s=======\n\n' % self.gs.target_type() | 357 print '\n\n=======Not Uploading to %s=======\n\n' % self.gs.target_type() |
| 375 print 'Generated resources are available in %s\n\n' % ( | 358 print 'Generated resources are available in %s\n\n' % ( |
| 376 self._local_skp_dir) | 359 self._local_skp_dir) |
| 377 | 360 |
| 378 if self._upload_to_partner_bucket: | 361 if self._upload_to_partner_bucket: |
| 379 print '\n\n=======Uploading to Partner bucket %s =======\n\n' % ( | 362 print '\n\n=======Uploading to Partner bucket %s =======\n\n' % ( |
| 380 PARTNERS_GS_BUCKET) | 363 PARTNERS_GS_BUCKET) |
| 381 partner_gs = GoogleStorageDataStore(PARTNERS_GS_BUCKET) | 364 partner_gs = GoogleStorageDataStore(PARTNERS_GS_BUCKET) |
| 382 partner_gs.delete_path(SKPICTURES_DIR_NAME) | 365 partner_gs.delete_path(SKPICTURES_DIR_NAME) |
| 383 print 'Uploading %s to %s' % (self._local_skp_dir, SKPICTURES_DIR_NAME) | 366 print 'Uploading %s to %s' % (self._local_skp_dir, SKPICTURES_DIR_NAME) |
| 384 partner_gs.upload_dir_contents( | 367 partner_gs.upload_dir_contents(self._local_skp_dir, SKPICTURES_DIR_NAME) |
| 385 self._local_skp_dir, | |
| 386 dest_dir=SKPICTURES_DIR_NAME, | |
| 387 upload_if=gs_utils.GSUtils.UploadIf.IF_MODIFIED) | |
| 388 print '\n\n=======New SKPs have been uploaded to %s =======\n\n' % ( | 368 print '\n\n=======New SKPs have been uploaded to %s =======\n\n' % ( |
| 389 posixpath.join(partner_gs.target_name(), SKPICTURES_DIR_NAME)) | 369 posixpath.join(partner_gs.target_name(), SKPICTURES_DIR_NAME)) |
| 390 | 370 |
| 391 return 0 | 371 return 0 |
| 392 | 372 |
| 393 def _GetSkiaSkpFileName(self, page_set): | 373 def _GetSkiaSkpFileName(self, page_set): |
| 394 """Returns the SKP file name for Skia page sets.""" | 374 """Returns the SKP file name for Skia page sets.""" |
| 395 # /path/to/skia_yahooanswers_desktop.py -> skia_yahooanswers_desktop.py | 375 # /path/to/skia_yahooanswers_desktop.py -> skia_yahooanswers_desktop.py |
| 396 ps_filename = os.path.basename(page_set) | 376 ps_filename = os.path.basename(page_set) |
| 397 # skia_yahooanswers_desktop.py -> skia_yahooanswers_desktop | 377 # skia_yahooanswers_desktop.py -> skia_yahooanswers_desktop |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 469 raise Exception('%s and %s do not exist in %s!' % (gs.target_type(), | 449 raise Exception('%s and %s do not exist in %s!' % (gs.target_type(), |
| 470 wpr_source, page_set_source)) | 450 wpr_source, page_set_source)) |
| 471 | 451 |
| 472 class DataStore: | 452 class DataStore: |
| 473 """An abstract base class for uploading recordings to a data storage. | 453 """An abstract base class for uploading recordings to a data storage. |
| 474 The interface emulates the google storage api.""" | 454 The interface emulates the google storage api.""" |
| 475 def target_name(self): | 455 def target_name(self): |
| 476 raise NotImplementedError() | 456 raise NotImplementedError() |
| 477 def target_type(self): | 457 def target_type(self): |
| 478 raise NotImplementedError() | 458 raise NotImplementedError() |
| 479 def does_storage_object_exist(self, *args): | 459 def does_storage_object_exist(self, name): |
| 480 raise NotImplementedError() | 460 raise NotImplementedError() |
| 481 def download_file(self, *args): | 461 def download_file(self, name, local_path): |
| 482 raise NotImplementedError() | 462 raise NotImplementedError() |
| 483 def upload_dir_contents(self, source_dir, **kwargs): | 463 def upload_dir_contents(self, source_dir, dest_dir): |
| 484 raise NotImplementedError() | 464 raise NotImplementedError() |
| 485 | 465 |
| 466 |
| 486 class GoogleStorageDataStore(DataStore): | 467 class GoogleStorageDataStore(DataStore): |
| 487 def __init__(self, data_store_url): | 468 def __init__(self, data_store_url): |
| 488 self._data_store_url = data_store_url | 469 self._url = data_store_url |
| 489 self._bucket = remove_prefix(self._data_store_url.lstrip(), | 470 |
| 490 gs_utils.GS_PREFIX) | |
| 491 self.gs = gs_utils.GSUtils() | |
| 492 def target_name(self): | 471 def target_name(self): |
| 493 return self._data_store_url | 472 return self._url |
| 473 |
| 494 def target_type(self): | 474 def target_type(self): |
| 495 return 'Google Storage' | 475 return 'Google Storage' |
| 496 def does_storage_object_exist(self, *args): | 476 |
| 497 return self.gs.does_storage_object_exist(self._bucket, *args) | 477 def does_storage_object_exist(self, name): |
| 478 try: |
| 479 output = subprocess.check_output([ |
| 480 'gsutil', 'ls', '/'.join((self._url, name))]) |
| 481 except subprocess.CalledProcessError: |
| 482 return False |
| 483 if len(output.splitlines) != 1: |
| 484 return False |
| 485 return True |
| 486 |
| 498 def delete_path(self, path): | 487 def delete_path(self, path): |
| 499 _, files = self.gs.list_bucket_contents(self._bucket, subdir=path) | 488 subprocess.check_call(['gsutil', 'rm', '-r', path]) |
| 500 for f in files: | 489 |
| 501 self.gs.delete_file(self._bucket, posixpath.join(path, f)) | 490 def download_file(self, name, local_path): |
| 502 def download_file(self, *args): | 491 subprocess.check_call([ |
| 503 self.gs.download_file(self._bucket, *args) | 492 'gsutil', 'cp', '/'.join((self._url, name)), local_path]) |
| 504 def upload_dir_contents(self, source_dir, **kwargs): | 493 |
| 505 self.gs.upload_dir_contents(source_dir, self._bucket, **kwargs) | 494 def upload_dir_contents(self, source_dir, dest_dir): |
| 495 subprocess.check_call([ |
| 496 'gsutil', 'cp', '-r', source_dir, '/'.join(self._url, dest_dir)]) |
| 497 |
| 506 | 498 |
| 507 class LocalFileSystemDataStore(DataStore): | 499 class LocalFileSystemDataStore(DataStore): |
| 508 def __init__(self, data_store_location): | 500 def __init__(self, data_store_location): |
| 509 self._base_dir = data_store_location | 501 self._base_dir = data_store_location |
| 510 def target_name(self): | 502 def target_name(self): |
| 511 return self._base_dir | 503 return self._base_dir |
| 512 def target_type(self): | 504 def target_type(self): |
| 513 return self._base_dir | 505 return self._base_dir |
| 514 def does_storage_object_exist(self, name, *args): | 506 def does_storage_object_exist(self, name): |
| 515 return os.path.isfile(os.path.join(self._base_dir, name)) | 507 return os.path.isfile(os.path.join(self._base_dir, name)) |
| 516 def delete_path(self, path): | 508 def delete_path(self, path): |
| 517 shutil.rmtree(path) | 509 shutil.rmtree(path) |
| 518 def download_file(self, name, local_path, *args): | 510 def download_file(self, name, local_path): |
| 519 shutil.copyfile(os.path.join(self._base_dir, name), local_path) | 511 shutil.copyfile(os.path.join(self._base_dir, name), local_path) |
| 520 def upload_dir_contents(self, source_dir, dest_dir, **kwargs): | 512 def upload_dir_contents(self, source_dir, dest_dir): |
| 521 def copytree(source_dir, dest_dir): | 513 def copytree(source_dir, dest_dir): |
| 522 if not os.path.exists(dest_dir): | 514 if not os.path.exists(dest_dir): |
| 523 os.makedirs(dest_dir) | 515 os.makedirs(dest_dir) |
| 524 for item in os.listdir(source_dir): | 516 for item in os.listdir(source_dir): |
| 525 source = os.path.join(source_dir, item) | 517 source = os.path.join(source_dir, item) |
| 526 dest = os.path.join(dest_dir, item) | 518 dest = os.path.join(dest_dir, item) |
| 527 if os.path.isdir(source): | 519 if os.path.isdir(source): |
| 528 copytree(source, dest) | 520 copytree(source, dest) |
| 529 else: | 521 else: |
| 530 shutil.copy2(source, dest) | 522 shutil.copy2(source, dest) |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 593 '--skia_tools is specified then the debugger is not run.', | 585 '--skia_tools is specified then the debugger is not run.', |
| 594 default=False) | 586 default=False) |
| 595 option_parser.add_option( | 587 option_parser.add_option( |
| 596 '', '--skp_prefix', | 588 '', '--skp_prefix', |
| 597 help='Prefix to add to the names of generated SKPs.', | 589 help='Prefix to add to the names of generated SKPs.', |
| 598 default=None) | 590 default=None) |
| 599 options, unused_args = option_parser.parse_args() | 591 options, unused_args = option_parser.parse_args() |
| 600 | 592 |
| 601 playback = SkPicturePlayback(options) | 593 playback = SkPicturePlayback(options) |
| 602 sys.exit(playback.Run()) | 594 sys.exit(playback.Run()) |
| OLD | NEW |