| OLD | NEW |
| (Empty) |
| 1 ''' | |
| 2 Compares the gm results within the local checkout against those already | |
| 3 committed to the Skia repository. | |
| 4 | |
| 5 Launch with --help to see more information. | |
| 6 | |
| 7 | |
| 8 Copyright 2012 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 | |
| 15 import fnmatch | |
| 16 import optparse | |
| 17 import os | |
| 18 import shutil | |
| 19 import tempfile | |
| 20 | |
| 21 # modules declared within this same directory | |
| 22 import svn | |
| 23 | |
| 24 USAGE_STRING = 'Usage: %s [options]' | |
| 25 HOWTO_STRING = ''' | |
| 26 To update the checked-in baselines across all platforms, follow these steps: | |
| 27 | |
| 28 cd .../trunk | |
| 29 svn update | |
| 30 svn stat # and make sure there are no files awaiting svn commit | |
| 31 make tools BUILDTYPE=Release | |
| 32 python tools/download_baselines.py | |
| 33 python tools/compare_baselines.py | |
| 34 # view compare_baselines output in a browser and make sure it's reasonable | |
| 35 # upload CL for review | |
| 36 # validate that the diffs look right in the review tool | |
| 37 # commit CL | |
| 38 | |
| 39 Note that the above instructions will only *update* already-checked-in | |
| 40 baseline images; if you want to check in new baseline images (ones that the | |
| 41 bots have been generating but we don't have a golden master for yet), you need | |
| 42 to use download_baselines.py's --add-new-files option. | |
| 43 ''' | |
| 44 HELP_STRING = ''' | |
| 45 | |
| 46 Compares the gm results within the local checkout against those already | |
| 47 committed to the Skia repository. Relies on skdiff to do the low-level | |
| 48 comparison. | |
| 49 | |
| 50 ''' + HOWTO_STRING | |
| 51 | |
| 52 TRUNK_PATH = os.path.join(os.path.dirname(__file__), os.pardir) | |
| 53 | |
| 54 OPTION_GM_BASEDIR = '--gm-basedir' | |
| 55 DEFAULT_GM_BASEDIR = os.path.join(TRUNK_PATH, os.pardir, 'gm-expected') | |
| 56 OPTION_PATH_TO_SKDIFF = '--path-to-skdiff' | |
| 57 # default PATH_TO_SKDIFF is determined at runtime | |
| 58 OPTION_SVN_GM_URL = '--svn-gm-url' | |
| 59 DEFAULT_SVN_GM_URL = 'http://skia.googlecode.com/svn/gm-expected' | |
| 60 | |
| 61 def CopyAllFilesAddingPrefix(source_dir, dest_dir, prefix): | |
| 62 """Copy all files from source_dir into dest_dir, adding prefix to the name | |
| 63 of each one as we copy it. | |
| 64 prefixes. | |
| 65 | |
| 66 @param source_dir | |
| 67 @param dest_dir where to save the copied files | |
| 68 @param prefix prefix to add to each filename when we make the copy | |
| 69 """ | |
| 70 all_filenames = os.listdir(source_dir) | |
| 71 for filename in all_filenames: | |
| 72 source_path = os.path.join(source_dir, filename) | |
| 73 if os.path.isdir(source_path): | |
| 74 print 'skipping %s because it is a directory, not a file' % filename | |
| 75 continue | |
| 76 dest_path = os.path.join(dest_dir, '%s%s' % (prefix, filename)) | |
| 77 shutil.copyfile(source_path, dest_path) | |
| 78 | |
| 79 def Flatten(source_dir, dest_dir, subdirectory_pattern): | |
| 80 """Copy all files from matching subdirectories under source_dir into | |
| 81 dest_dir, flattened into a single directory using subdirectory names as | |
| 82 prefixes. | |
| 83 | |
| 84 @param source_dir | |
| 85 @param dest_dir where to save the copied files | |
| 86 @param subdirectory_pattern only copy files from subdirectories that match | |
| 87 this Unix-style filename pattern (e.g., 'base-*') | |
| 88 """ | |
| 89 all_filenames = os.listdir(source_dir) | |
| 90 matching_filenames = fnmatch.filter(all_filenames, subdirectory_pattern) | |
| 91 for filename in matching_filenames: | |
| 92 source_path = os.path.join(source_dir, filename) | |
| 93 if not os.path.isdir(source_path): | |
| 94 print 'skipping %s because it is a file, not a directory' % filename | |
| 95 continue | |
| 96 print 'flattening directory %s' % source_path | |
| 97 CopyAllFilesAddingPrefix(source_dir=source_path, dest_dir=dest_dir, | |
| 98 prefix='%s_' % filename) | |
| 99 | |
| 100 def RunCommand(command): | |
| 101 """Run a command, raising an exception if it fails. | |
| 102 | |
| 103 @param command the command as a single string | |
| 104 """ | |
| 105 print 'running command [%s]...' % command | |
| 106 retval = os.system(command) | |
| 107 #if retval is not 0: | |
| 108 # raise Exception('command [%s] failed' % command) | |
| 109 | |
| 110 def FindPathToSkDiff(user_set_path=None): | |
| 111 """Return path to an existing skdiff binary, or raise an exception if we | |
| 112 cannot find one. | |
| 113 | |
| 114 @param user_set_path if None, the user did not specify a path, so look in | |
| 115 some likely places; otherwise, only check at this path | |
| 116 """ | |
| 117 if user_set_path is not None: | |
| 118 if os.path.isfile(user_set_path): | |
| 119 return user_set_path | |
| 120 raise Exception('unable to find skdiff at user-set path %s' % | |
| 121 user_set_path) | |
| 122 trunk_path = os.path.join(os.path.dirname(__file__), os.pardir) | |
| 123 possible_paths = [os.path.join(trunk_path, 'out', 'Release', 'skdiff'), | |
| 124 os.path.join(trunk_path, 'out', 'Debug', 'skdiff')] | |
| 125 for try_path in possible_paths: | |
| 126 if os.path.isfile(try_path): | |
| 127 return try_path | |
| 128 raise Exception('cannot find skdiff in paths %s; maybe you need to ' | |
| 129 'specify the %s option or build skdiff?' % ( | |
| 130 possible_paths, OPTION_PATH_TO_SKDIFF)) | |
| 131 | |
| 132 def CompareBaselines(gm_basedir, path_to_skdiff, svn_gm_url): | |
| 133 """Compare the gm results within gm_basedir against those already | |
| 134 committed to the Skia repository. | |
| 135 | |
| 136 @param gm_basedir | |
| 137 @param path_to_skdiff | |
| 138 @param svn_gm_url base URL of Subversion repository where we store the | |
| 139 expected GM results | |
| 140 """ | |
| 141 # Validate parameters, filling in default values if necessary and possible. | |
| 142 if not os.path.isdir(gm_basedir): | |
| 143 raise Exception('cannot find gm_basedir at %s; maybe you need to ' | |
| 144 'specify the %s option?' % ( | |
| 145 gm_basedir, OPTION_GM_BASEDIR)) | |
| 146 path_to_skdiff = FindPathToSkDiff(path_to_skdiff) | |
| 147 | |
| 148 tempdir_base = tempfile.mkdtemp() | |
| 149 | |
| 150 # Download all checked-in baseline images to a temp directory | |
| 151 checkedin_dir = os.path.join(tempdir_base, 'checkedin') | |
| 152 os.mkdir(checkedin_dir) | |
| 153 svn.Svn(checkedin_dir).Checkout(svn_gm_url, '.') | |
| 154 | |
| 155 # Flatten those checked-in baseline images into checkedin_flattened_dir | |
| 156 checkedin_flattened_dir = os.path.join(tempdir_base, 'checkedin_flattened') | |
| 157 os.mkdir(checkedin_flattened_dir) | |
| 158 Flatten(source_dir=checkedin_dir, dest_dir=checkedin_flattened_dir, | |
| 159 subdirectory_pattern='base-*') | |
| 160 | |
| 161 # Flatten the local baseline images into local_flattened_dir | |
| 162 local_flattened_dir = os.path.join(tempdir_base, 'local_flattened') | |
| 163 os.mkdir(local_flattened_dir) | |
| 164 Flatten(source_dir=gm_basedir, dest_dir=local_flattened_dir, | |
| 165 subdirectory_pattern='base-*') | |
| 166 | |
| 167 # Run skdiff to compare checkedin_flattened_dir against local_flattened_dir | |
| 168 diff_dir = os.path.join(tempdir_base, 'diffs') | |
| 169 os.mkdir(diff_dir) | |
| 170 RunCommand('%s %s %s %s' % (path_to_skdiff, checkedin_flattened_dir, | |
| 171 local_flattened_dir, diff_dir)) | |
| 172 print '\nskdiff results are ready in file://%s/index.html' % diff_dir | |
| 173 # TODO(epoger): delete tempdir_base tree to clean up after ourselves (but | |
| 174 # not before the user gets a chance to examine the results), and/or | |
| 175 # allow user to specify a different directory to write into? | |
| 176 | |
| 177 def RaiseUsageException(): | |
| 178 raise Exception('%s\nRun with --help for more detail.' % ( | |
| 179 USAGE_STRING % __file__)) | |
| 180 | |
| 181 def Main(options, args): | |
| 182 """Allow other scripts to call this script with fake command-line args. | |
| 183 """ | |
| 184 num_args = len(args) | |
| 185 if num_args != 0: | |
| 186 RaiseUsageException() | |
| 187 CompareBaselines(gm_basedir=options.gm_basedir, | |
| 188 path_to_skdiff=options.path_to_skdiff, | |
| 189 svn_gm_url=options.svn_gm_url) | |
| 190 | |
| 191 if __name__ == '__main__': | |
| 192 parser = optparse.OptionParser(USAGE_STRING % '%prog' + HELP_STRING) | |
| 193 parser.add_option(OPTION_GM_BASEDIR, | |
| 194 action='store', type='string', default=DEFAULT_GM_BASEDIR, | |
| 195 help='path to root of locally stored baseline images ' | |
| 196 'to compare against those checked into the svn repo; ' | |
| 197 'defaults to "%s"' % DEFAULT_GM_BASEDIR) | |
| 198 parser.add_option(OPTION_PATH_TO_SKDIFF, | |
| 199 action='store', type='string', default=None, | |
| 200 help='path to already-built skdiff tool; if not set, ' | |
| 201 'will search for it in typical directories near this ' | |
| 202 'script') | |
| 203 parser.add_option(OPTION_SVN_GM_URL, | |
| 204 action='store', type='string', default=DEFAULT_SVN_GM_URL, | |
| 205 help='URL of SVN repository within which we store the ' | |
| 206 'expected GM baseline images; defaults to "%s"' % | |
| 207 DEFAULT_SVN_GM_URL) | |
| 208 (options, args) = parser.parse_args() | |
| 209 Main(options, args) | |
| OLD | NEW |