epoger@google.com | fc241ee | 2012-02-02 16:49:49 +0000 | [diff] [blame^] | 1 | ''' |
| 2 | Compares the gm results within the local checkout against those already |
| 3 | committed to the Skia repository. Relies on skdiff to do the low-level |
| 4 | comparison. |
| 5 | |
| 6 | Sample usage to compare locally generated gm results against the |
| 7 | checked-in ones: |
| 8 | |
| 9 | cd .../trunk |
| 10 | make tools # or otherwise get a runnable skdiff |
| 11 | python tools/compare-baselines.py gm |
| 12 | # validate that the new images look right |
| 13 | |
| 14 | Launch with --help to see more options. |
| 15 | |
| 16 | |
| 17 | Copyright 2012 Google Inc. |
| 18 | |
| 19 | Use of this source code is governed by a BSD-style license that can be |
| 20 | found in the LICENSE file. |
| 21 | ''' |
| 22 | |
| 23 | # common Python modules |
| 24 | import fnmatch |
| 25 | import optparse |
| 26 | import os |
| 27 | import shutil |
| 28 | import tempfile |
| 29 | |
| 30 | # modules declared within this same directory |
| 31 | import svn |
| 32 | |
| 33 | # Base URL of SVN repository where we store the checked-in gm results. |
| 34 | SVN_GM_URL = 'http://skia.googlecode.com/svn/trunk/gm' |
| 35 | |
| 36 | USAGE_STRING = 'usage: %s [options] <gm basedir>' |
| 37 | OPTION_PATH_TO_SKDIFF = '--path-to-skdiff' |
| 38 | |
| 39 | def CopyAllFilesAddingPrefix(source_dir, dest_dir, prefix): |
| 40 | """Copy all files from source_dir into dest_dir, adding prefix to the name |
| 41 | of each one as we copy it. |
| 42 | prefixes. |
| 43 | |
| 44 | @param source_dir |
| 45 | @param dest_dir where to save the copied files |
| 46 | @param prefix prefix to add to each filename when we make the copy |
| 47 | """ |
| 48 | all_filenames = os.listdir(source_dir) |
| 49 | for filename in all_filenames: |
| 50 | source_path = os.path.join(source_dir, filename) |
| 51 | if os.path.isdir(source_path): |
| 52 | print 'skipping %s because it is a directory, not a file' % filename |
| 53 | continue |
| 54 | dest_path = os.path.join(dest_dir, '%s%s' % (prefix, filename)) |
| 55 | shutil.copyfile(source_path, dest_path) |
| 56 | |
| 57 | def Flatten(source_dir, dest_dir, subdirectory_pattern): |
| 58 | """Copy all files from matching subdirectories under source_dir into |
| 59 | dest_dir, flattened into a single directory using subdirectory names as |
| 60 | prefixes. |
| 61 | |
| 62 | @param source_dir |
| 63 | @param dest_dir where to save the copied files |
| 64 | @param subdirectory_pattern only copy files from subdirectories that match |
| 65 | this Unix-style filename pattern (e.g., 'base-*') |
| 66 | """ |
| 67 | all_filenames = os.listdir(source_dir) |
| 68 | matching_filenames = fnmatch.filter(all_filenames, subdirectory_pattern) |
| 69 | for filename in matching_filenames: |
| 70 | source_path = os.path.join(source_dir, filename) |
| 71 | if not os.path.isdir(source_path): |
| 72 | print 'skipping %s because it is a file, not a directory' % filename |
| 73 | continue |
| 74 | print 'flattening directory %s' % source_path |
| 75 | CopyAllFilesAddingPrefix(source_dir=source_path, dest_dir=dest_dir, |
| 76 | prefix='%s_' % filename) |
| 77 | |
| 78 | def RunCommand(command): |
| 79 | """Run a command, raising an exception if it fails. |
| 80 | |
| 81 | @param command the command as a single string |
| 82 | """ |
| 83 | print 'running command [%s]...' % command |
| 84 | retval = os.system(command) |
| 85 | if retval is not 0: |
| 86 | raise Exception('command [%s] failed' % command) |
| 87 | |
| 88 | def Main(options, args): |
| 89 | """Compare the gm results within the local checkout against those already |
| 90 | committed to the Skia repository. |
| 91 | |
| 92 | @param options |
| 93 | @param args |
| 94 | """ |
| 95 | num_args = len(args) |
| 96 | if num_args != 1: |
| 97 | RaiseUsageException() |
| 98 | gm_basedir = args[0].rstrip(os.sep) |
| 99 | |
| 100 | tempdir_base = tempfile.mkdtemp() |
| 101 | |
| 102 | # Download all checked-in baseline images to a temp directory |
| 103 | checkedin_dir = os.path.join(tempdir_base, 'checkedin') |
| 104 | os.mkdir(checkedin_dir) |
| 105 | svn.Svn(checkedin_dir).Checkout(SVN_GM_URL, '.') |
| 106 | |
| 107 | # Flatten those checked-in baseline images into checkedin_flattened_dir |
| 108 | checkedin_flattened_dir = os.path.join(tempdir_base, 'checkedin_flattened') |
| 109 | os.mkdir(checkedin_flattened_dir) |
| 110 | Flatten(source_dir=checkedin_dir, dest_dir=checkedin_flattened_dir, |
| 111 | subdirectory_pattern='base-*') |
| 112 | |
| 113 | # Flatten the local baseline images into local_flattened_dir |
| 114 | local_flattened_dir = os.path.join(tempdir_base, 'local_flattened') |
| 115 | os.mkdir(local_flattened_dir) |
| 116 | Flatten(source_dir=gm_basedir, dest_dir=local_flattened_dir, |
| 117 | subdirectory_pattern='base-*') |
| 118 | |
| 119 | # Run skdiff to compare checkedin_flattened_dir against local_flattened_dir |
| 120 | diff_dir = os.path.join(tempdir_base, 'diffs') |
| 121 | os.mkdir(diff_dir) |
| 122 | RunCommand('%s %s %s %s' % (options.path_to_skdiff, checkedin_flattened_dir, |
| 123 | local_flattened_dir, diff_dir)) |
| 124 | print '\nskdiff results are ready in file://%s/index.html' % diff_dir |
| 125 | |
| 126 | def RaiseUsageException(): |
| 127 | raise Exception(USAGE_STRING % __file__) |
| 128 | |
| 129 | if __name__ == '__main__': |
| 130 | parser = optparse.OptionParser(USAGE_STRING % '%prog') |
| 131 | parser.add_option(OPTION_PATH_TO_SKDIFF, |
| 132 | action='store', type='string', |
| 133 | default=os.path.join('out', 'Debug', 'skdiff'), |
| 134 | help='path to already-built skdiff tool') |
| 135 | (options, args) = parser.parse_args() |
| 136 | Main(options, args) |