epoger@google.com | 27442af | 2011-12-29 21:13:08 +0000 | [diff] [blame] | 1 | ''' |
| 2 | Downloads the actual gm results most recently generated by the Skia buildbots, |
| 3 | and adds any new ones to SVN control. |
| 4 | |
epoger@google.com | 1610a68 | 2012-04-12 18:02:25 +0000 | [diff] [blame] | 5 | Launch with --help to see more information. |
epoger@google.com | d625655 | 2012-01-10 14:10:34 +0000 | [diff] [blame] | 6 | |
epoger@google.com | 27442af | 2011-12-29 21:13:08 +0000 | [diff] [blame] | 7 | |
| 8 | Copyright 2011 Google Inc. |
| 9 | |
| 10 | Use of this source code is governed by a BSD-style license that can be |
| 11 | found in the LICENSE file. |
| 12 | ''' |
| 13 | |
| 14 | # common Python modules |
epoger@google.com | 20ad5ac | 2012-01-17 21:26:05 +0000 | [diff] [blame] | 15 | import fnmatch |
epoger@google.com | d625655 | 2012-01-10 14:10:34 +0000 | [diff] [blame] | 16 | import optparse |
| 17 | import os |
epoger@google.com | 27442af | 2011-12-29 21:13:08 +0000 | [diff] [blame] | 18 | import re |
epoger@google.com | 20ad5ac | 2012-01-17 21:26:05 +0000 | [diff] [blame] | 19 | import shutil |
epoger@google.com | 27442af | 2011-12-29 21:13:08 +0000 | [diff] [blame] | 20 | import sys |
epoger@google.com | 20ad5ac | 2012-01-17 21:26:05 +0000 | [diff] [blame] | 21 | import tempfile |
epoger@google.com | 27442af | 2011-12-29 21:13:08 +0000 | [diff] [blame] | 22 | |
| 23 | # modules declared within this same directory |
epoger@google.com | 1610a68 | 2012-04-12 18:02:25 +0000 | [diff] [blame] | 24 | import compare_baselines |
epoger@google.com | 27442af | 2011-12-29 21:13:08 +0000 | [diff] [blame] | 25 | import svn |
| 26 | |
epoger@google.com | 1610a68 | 2012-04-12 18:02:25 +0000 | [diff] [blame] | 27 | USAGE_STRING = 'Usage: %s [options] [baseline_subdir]...' |
| 28 | HELP_STRING = ''' |
| 29 | |
| 30 | Downloads the actual gm results most recently generated by the Skia buildbots, |
| 31 | and adds any new ones to SVN control. |
| 32 | |
| 33 | If no baseline_subdir is given, then this tool will download the most-recently |
| 34 | generated actual gm results for ALL platforms. |
| 35 | |
| 36 | ''' + compare_baselines.HOWTO_STRING |
| 37 | |
epoger@google.com | 20ad5ac | 2012-01-17 21:26:05 +0000 | [diff] [blame] | 38 | # Base URL of SVN repository where buildbots store actual gm image results. |
| 39 | SVN_BASE_URL = 'http://skia-autogen.googlecode.com/svn/gm-actual' |
epoger@google.com | 27442af | 2011-12-29 21:13:08 +0000 | [diff] [blame] | 40 | |
epoger@google.com | d625655 | 2012-01-10 14:10:34 +0000 | [diff] [blame] | 41 | OPTION_IGNORE_LOCAL_MODS = '--ignore-local-mods' |
| 42 | OPTION_ADD_NEW_FILES = '--add-new-files' |
| 43 | |
epoger@google.com | 20ad5ac | 2012-01-17 21:26:05 +0000 | [diff] [blame] | 44 | def GetLatestResultsSvnUrl(baseline_subdir): |
| 45 | """Return SVN URL from which we can check out the MOST RECENTLY generated |
epoger@google.com | 27442af | 2011-12-29 21:13:08 +0000 | [diff] [blame] | 46 | images for this baseline type. |
| 47 | |
| 48 | @param baseline_subdir indicates which platform we want images for |
| 49 | """ |
epoger@google.com | 20ad5ac | 2012-01-17 21:26:05 +0000 | [diff] [blame] | 50 | # trim off 'gm/' prefix |
| 51 | gm_prefix = 'gm%s' % os.sep |
| 52 | if not baseline_subdir.startswith(gm_prefix): |
| 53 | raise Exception('baseline_subdir "%s" should start with "%s"' % ( |
| 54 | baseline_subdir, gm_prefix)) |
| 55 | return '%s/%s' % (SVN_BASE_URL, baseline_subdir[len(gm_prefix):]) |
epoger@google.com | 27442af | 2011-12-29 21:13:08 +0000 | [diff] [blame] | 56 | |
epoger@google.com | 20ad5ac | 2012-01-17 21:26:05 +0000 | [diff] [blame] | 57 | def CopyMatchingFiles(source_dir, dest_dir, filename_pattern, |
| 58 | only_copy_updates=False): |
| 59 | """Copy all files from source_dir that match filename_pattern, and |
| 60 | save them (with their original filenames) in dest_dir. |
epoger@google.com | 27442af | 2011-12-29 21:13:08 +0000 | [diff] [blame] | 61 | |
epoger@google.com | 20ad5ac | 2012-01-17 21:26:05 +0000 | [diff] [blame] | 62 | @param source_dir |
| 63 | @param dest_dir where to save the copied files |
| 64 | @param filename_pattern only copy files that match this Unix-style filename |
| 65 | pattern (e.g., '*.jpg') |
| 66 | @param only_copy_updates if True, only copy files that are already |
| 67 | present in dest_dir |
epoger@google.com | 27442af | 2011-12-29 21:13:08 +0000 | [diff] [blame] | 68 | """ |
epoger@google.com | 20ad5ac | 2012-01-17 21:26:05 +0000 | [diff] [blame] | 69 | all_filenames = os.listdir(source_dir) |
| 70 | matching_filenames = fnmatch.filter(all_filenames, filename_pattern) |
| 71 | for filename in matching_filenames: |
| 72 | source_path = os.path.join(source_dir, filename) |
| 73 | dest_path = os.path.join(dest_dir, filename) |
| 74 | if only_copy_updates and not os.path.isfile(dest_path): |
epoger@google.com | d625655 | 2012-01-10 14:10:34 +0000 | [diff] [blame] | 75 | continue |
epoger@google.com | 20ad5ac | 2012-01-17 21:26:05 +0000 | [diff] [blame] | 76 | shutil.copyfile(source_path, dest_path) |
epoger@google.com | 27442af | 2011-12-29 21:13:08 +0000 | [diff] [blame] | 77 | |
epoger@google.com | 1610a68 | 2012-04-12 18:02:25 +0000 | [diff] [blame] | 78 | def DownloadBaselinesForOnePlatform(baseline_subdir): |
| 79 | """Download most recently generated baseline images for a single platform, |
epoger@google.com | 27442af | 2011-12-29 21:13:08 +0000 | [diff] [blame] | 80 | and add any new ones to SVN control. |
| 81 | |
epoger@google.com | 1610a68 | 2012-04-12 18:02:25 +0000 | [diff] [blame] | 82 | @param baseline_subdir |
epoger@google.com | 27442af | 2011-12-29 21:13:08 +0000 | [diff] [blame] | 83 | """ |
epoger@google.com | 20ad5ac | 2012-01-17 21:26:05 +0000 | [diff] [blame] | 84 | # Create repo_to_modify to handle the SVN repository we will add files to. |
epoger@google.com | 20ad5ac | 2012-01-17 21:26:05 +0000 | [diff] [blame] | 85 | repo_to_modify = svn.Svn(baseline_subdir) |
epoger@google.com | d625655 | 2012-01-10 14:10:34 +0000 | [diff] [blame] | 86 | |
| 87 | # If there are any locally modified files in that directory, exit |
| 88 | # (so that we don't risk overwriting the user's previous work). |
epoger@google.com | 20ad5ac | 2012-01-17 21:26:05 +0000 | [diff] [blame] | 89 | new_and_modified_files = repo_to_modify.GetNewAndModifiedFiles() |
epoger@google.com | d625655 | 2012-01-10 14:10:34 +0000 | [diff] [blame] | 90 | if not options.ignore_local_mods: |
| 91 | if new_and_modified_files: |
| 92 | raise Exception('Exiting because there are already new and/or ' |
| 93 | 'modified files in %s. To continue in spite of ' |
| 94 | 'that, run with %s option.' % ( |
| 95 | baseline_subdir, OPTION_IGNORE_LOCAL_MODS)) |
| 96 | |
epoger@google.com | 20ad5ac | 2012-01-17 21:26:05 +0000 | [diff] [blame] | 97 | # Download actual gm images into a separate repo in a temporary directory. |
| 98 | tempdir = tempfile.mkdtemp() |
| 99 | download_repo = svn.Svn(tempdir) |
| 100 | download_repo.Checkout(GetLatestResultsSvnUrl(baseline_subdir), '.') |
| 101 | |
| 102 | # Copy any of those files we are interested in into repo_to_modify, |
| 103 | # and then delete the temporary directory. |
| 104 | CopyMatchingFiles(source_dir=tempdir, dest_dir=baseline_subdir, |
| 105 | filename_pattern='*.png', |
| 106 | only_copy_updates=(not options.add_new_files)) |
| 107 | shutil.rmtree(tempdir) |
| 108 | download_repo = None |
epoger@google.com | d625655 | 2012-01-10 14:10:34 +0000 | [diff] [blame] | 109 | |
| 110 | # Add any new files to SVN control (if we are running with add_new_files). |
epoger@google.com | 20ad5ac | 2012-01-17 21:26:05 +0000 | [diff] [blame] | 111 | new_files = repo_to_modify.GetNewFiles() |
epoger@google.com | d625655 | 2012-01-10 14:10:34 +0000 | [diff] [blame] | 112 | if new_files and options.add_new_files: |
epoger@google.com | 20ad5ac | 2012-01-17 21:26:05 +0000 | [diff] [blame] | 113 | repo_to_modify.AddFiles(new_files) |
| 114 | |
| 115 | # Set the mimetype property on *all* image files in baseline_subdir, even |
| 116 | # the ones that were already there (in case that property wasn't properly |
| 117 | # set already). |
| 118 | repo_to_modify.SetPropertyByFilenamePattern( |
| 119 | '*.png', svn.PROPERTY_MIMETYPE, 'image/png') |
| 120 | repo_to_modify.SetPropertyByFilenamePattern( |
| 121 | '*.pdf', svn.PROPERTY_MIMETYPE, 'application/pdf') |
epoger@google.com | 27442af | 2011-12-29 21:13:08 +0000 | [diff] [blame] | 122 | |
epoger@google.com | d625655 | 2012-01-10 14:10:34 +0000 | [diff] [blame] | 123 | def RaiseUsageException(): |
epoger@google.com | 1610a68 | 2012-04-12 18:02:25 +0000 | [diff] [blame] | 124 | raise Exception('%s\nRun with --help for more detail.' % ( |
| 125 | USAGE_STRING % __file__)) |
| 126 | |
| 127 | def Main(options, args): |
| 128 | """Allow other scripts to call this script with fake command-line args. |
| 129 | """ |
| 130 | # If no platforms are specified, do 'em all. |
| 131 | num_args = len(args) |
| 132 | if num_args == 0: |
| 133 | # TODO(epoger): automate the default set of platforms. We want to ensure |
| 134 | # that the user gets all of the platforms that the bots are running, |
| 135 | # not just whatever subdirectories he happens to have checked out... |
| 136 | args = [ |
| 137 | 'gm/base-linux', |
| 138 | 'gm/base-linux-fixed', |
| 139 | 'gm/base-macmini', |
| 140 | 'gm/base-macmini-fixed', |
| 141 | 'gm/base-macmini-lion-fixed', |
| 142 | 'gm/base-macmini-lion-float', |
| 143 | 'gm/base-win', |
| 144 | 'gm/base-win-fixed', |
| 145 | ] |
| 146 | |
| 147 | # Trim all subdir names. |
| 148 | baseline_subdirs = [] |
| 149 | for arg in args: |
| 150 | baseline_subdirs.append(arg.rstrip(os.sep)) |
| 151 | |
| 152 | # Make sure all those subdirectories exist. |
| 153 | for baseline_subdir in baseline_subdirs: |
| 154 | if not os.path.isdir(baseline_subdir): |
| 155 | raise Exception('could not find baseline_subdir "%s"' % |
| 156 | baseline_subdir) |
| 157 | |
| 158 | # Process the subdirs, one at a time. |
| 159 | for baseline_subdir in baseline_subdirs: |
| 160 | DownloadBaselinesForOnePlatform(baseline_subdir=baseline_subdir) |
epoger@google.com | d625655 | 2012-01-10 14:10:34 +0000 | [diff] [blame] | 161 | |
epoger@google.com | 27442af | 2011-12-29 21:13:08 +0000 | [diff] [blame] | 162 | if __name__ == '__main__': |
epoger@google.com | 1610a68 | 2012-04-12 18:02:25 +0000 | [diff] [blame] | 163 | parser = optparse.OptionParser(USAGE_STRING % '%prog' + HELP_STRING) |
epoger@google.com | d625655 | 2012-01-10 14:10:34 +0000 | [diff] [blame] | 164 | parser.add_option(OPTION_IGNORE_LOCAL_MODS, |
| 165 | action='store_true', default=False, |
| 166 | help='allow tool to run even if there are already ' |
| 167 | 'local modifications in the baseline_subdir') |
| 168 | parser.add_option(OPTION_ADD_NEW_FILES, |
| 169 | action='store_true', default=False, |
| 170 | help='in addition to downloading new versions of ' |
| 171 | 'existing baselines, also download baselines that are ' |
| 172 | 'not under SVN control yet') |
| 173 | (options, args) = parser.parse_args() |
| 174 | Main(options, args) |