| ''' |
| Downloads the actual gm results most recently generated by the Skia buildbots, |
| and adds any new ones to SVN control. |
| |
| Launch with --help to see more information. |
| |
| |
| Copyright 2011 Google Inc. |
| |
| Use of this source code is governed by a BSD-style license that can be |
| found in the LICENSE file. |
| ''' |
| |
| # common Python modules |
| import fnmatch |
| import optparse |
| import os |
| import re |
| import shutil |
| import sys |
| import tempfile |
| |
| # modules declared within this same directory |
| import compare_baselines |
| import svn |
| |
| USAGE_STRING = 'Usage: %s [options] [baseline_subdir]...' |
| HELP_STRING = ''' |
| |
| Downloads the actual gm results most recently generated by the Skia buildbots, |
| and adds any new ones to SVN control. |
| |
| If no baseline_subdir is given, then this tool will download the most-recently |
| generated actual gm results for ALL platforms. |
| |
| ''' + compare_baselines.HOWTO_STRING |
| |
| # Base URL of SVN repository where buildbots store actual gm image results. |
| SVN_BASE_URL = 'http://skia-autogen.googlecode.com/svn/gm-actual' |
| |
| OPTION_IGNORE_LOCAL_MODS = '--ignore-local-mods' |
| OPTION_ADD_NEW_FILES = '--add-new-files' |
| |
| def GetLatestResultsSvnUrl(baseline_subdir): |
| """Return SVN URL from which we can check out the MOST RECENTLY generated |
| images for this baseline type. |
| |
| @param baseline_subdir indicates which platform we want images for |
| """ |
| # trim off 'gm/' prefix |
| gm_prefix = 'gm%s' % os.sep |
| if not baseline_subdir.startswith(gm_prefix): |
| raise Exception('baseline_subdir "%s" should start with "%s"' % ( |
| baseline_subdir, gm_prefix)) |
| return '%s/%s' % (SVN_BASE_URL, baseline_subdir[len(gm_prefix):]) |
| |
| def CopyMatchingFiles(source_dir, dest_dir, filename_pattern, |
| only_copy_updates=False): |
| """Copy all files from source_dir that match filename_pattern, and |
| save them (with their original filenames) in dest_dir. |
| |
| @param source_dir |
| @param dest_dir where to save the copied files |
| @param filename_pattern only copy files that match this Unix-style filename |
| pattern (e.g., '*.jpg') |
| @param only_copy_updates if True, only copy files that are already |
| present in dest_dir |
| """ |
| all_filenames = os.listdir(source_dir) |
| matching_filenames = fnmatch.filter(all_filenames, filename_pattern) |
| for filename in matching_filenames: |
| source_path = os.path.join(source_dir, filename) |
| dest_path = os.path.join(dest_dir, filename) |
| if only_copy_updates and not os.path.isfile(dest_path): |
| continue |
| shutil.copyfile(source_path, dest_path) |
| |
| def DownloadBaselinesForOnePlatform(baseline_subdir): |
| """Download most recently generated baseline images for a single platform, |
| and add any new ones to SVN control. |
| |
| @param baseline_subdir |
| """ |
| # Create repo_to_modify to handle the SVN repository we will add files to. |
| repo_to_modify = svn.Svn(baseline_subdir) |
| |
| # If there are any locally modified files in that directory, exit |
| # (so that we don't risk overwriting the user's previous work). |
| new_and_modified_files = repo_to_modify.GetNewAndModifiedFiles() |
| if not options.ignore_local_mods: |
| if new_and_modified_files: |
| raise Exception('Exiting because there are already new and/or ' |
| 'modified files in %s. To continue in spite of ' |
| 'that, run with %s option.' % ( |
| baseline_subdir, OPTION_IGNORE_LOCAL_MODS)) |
| |
| # Download actual gm images into a separate repo in a temporary directory. |
| tempdir = tempfile.mkdtemp() |
| download_repo = svn.Svn(tempdir) |
| download_repo.Checkout(GetLatestResultsSvnUrl(baseline_subdir), '.') |
| |
| # Copy any of those files we are interested in into repo_to_modify, |
| # and then delete the temporary directory. |
| CopyMatchingFiles(source_dir=tempdir, dest_dir=baseline_subdir, |
| filename_pattern='*.png', |
| only_copy_updates=(not options.add_new_files)) |
| shutil.rmtree(tempdir) |
| download_repo = None |
| |
| # Add any new files to SVN control (if we are running with add_new_files). |
| if options.add_new_files: |
| new_files = repo_to_modify.GetNewFiles() |
| if new_files: |
| repo_to_modify.AddFiles(sorted(new_files)) |
| |
| # Set the mimetype property on any new/modified image files in |
| # baseline_subdir. (We used to set the mimetype property on *all* image |
| # files in the directory, even those whose content wasn't changing, |
| # but that caused confusion. See |
| # http://code.google.com/p/skia/issues/detail?id=618 .) |
| modified_files = repo_to_modify.GetNewAndModifiedFiles() |
| repo_to_modify.SetProperty(sorted(fnmatch.filter(modified_files, '*.png')), |
| svn.PROPERTY_MIMETYPE, 'image/png') |
| repo_to_modify.SetProperty(sorted(fnmatch.filter(modified_files, '*.pdf')), |
| svn.PROPERTY_MIMETYPE, 'application/pdf') |
| |
| def RaiseUsageException(): |
| raise Exception('%s\nRun with --help for more detail.' % ( |
| USAGE_STRING % __file__)) |
| |
| def Main(options, args): |
| """Allow other scripts to call this script with fake command-line args. |
| """ |
| # If no platforms are specified, do 'em all. |
| num_args = len(args) |
| if num_args == 0: |
| # TODO(epoger): automate the default set of platforms. We want to ensure |
| # that the user gets all of the platforms that the bots are running, |
| # not just whatever subdirectories he happens to have checked out... |
| args = [ |
| 'gm/base-android-nexus-s', |
| 'gm/base-android-xoom', |
| 'gm/base-linux', |
| 'gm/base-macmini', |
| 'gm/base-macmini-lion-float', |
| 'gm/base-win', |
| ] |
| |
| # Trim all subdir names. |
| baseline_subdirs = [] |
| for arg in args: |
| baseline_subdirs.append(arg.rstrip(os.sep)) |
| |
| # Make sure all those subdirectories exist. |
| for baseline_subdir in baseline_subdirs: |
| if not os.path.isdir(baseline_subdir): |
| raise Exception('could not find baseline_subdir "%s"' % |
| baseline_subdir) |
| |
| # Process the subdirs, one at a time. |
| for baseline_subdir in baseline_subdirs: |
| DownloadBaselinesForOnePlatform(baseline_subdir=baseline_subdir) |
| |
| if __name__ == '__main__': |
| parser = optparse.OptionParser(USAGE_STRING % '%prog' + HELP_STRING) |
| parser.add_option(OPTION_IGNORE_LOCAL_MODS, |
| action='store_true', default=False, |
| help='allow tool to run even if there are already ' |
| 'local modifications in the baseline_subdir') |
| parser.add_option(OPTION_ADD_NEW_FILES, |
| action='store_true', default=False, |
| help='in addition to downloading new versions of ' |
| 'existing baselines, also download baselines that are ' |
| 'not under SVN control yet') |
| (options, args) = parser.parse_args() |
| Main(options, args) |