blob: 19614ce1ff19154ae442da3a8fba3203fe5f9f35 [file] [log] [blame]
epoger@google.comfc241ee2012-02-02 16:49:49 +00001'''
2Compares the gm results within the local checkout against those already
epoger@google.comdb12fee2012-02-03 14:32:34 +00003committed to the Skia repository.
epoger@google.comfc241ee2012-02-02 16:49:49 +00004
epoger@google.comdb12fee2012-02-03 14:32:34 +00005Launch with --help to see more information.
epoger@google.comfc241ee2012-02-02 16:49:49 +00006
7
8Copyright 2012 Google Inc.
9
10Use of this source code is governed by a BSD-style license that can be
11found in the LICENSE file.
12'''
13
14# common Python modules
15import fnmatch
16import optparse
17import os
18import shutil
19import tempfile
20
21# modules declared within this same directory
22import svn
23
epoger@google.comdb12fee2012-02-03 14:32:34 +000024USAGE_STRING = '''usage: %s [options]
epoger@google.comfc241ee2012-02-02 16:49:49 +000025
epoger@google.comdb12fee2012-02-03 14:32:34 +000026Compares the gm results within the local checkout against those already
27committed to the Skia repository. Relies on skdiff to do the low-level
28comparison.
29
30for example:
31
32cd .../trunk
33# modify local gm images, maybe by running download-baselines.py
34make tools
35python tools/compare-baselines.py
36# validate that the image diffs look right
37'''
38
39TRUNK_PATH = os.path.join(os.path.dirname(__file__), os.pardir)
40
41OPTION_GM_BASEDIR = '--gm-basedir'
42DEFAULT_GM_BASEDIR = os.path.join(TRUNK_PATH, 'gm')
epoger@google.comfc241ee2012-02-02 16:49:49 +000043OPTION_PATH_TO_SKDIFF = '--path-to-skdiff'
epoger@google.comdb12fee2012-02-03 14:32:34 +000044# default PATH_TO_SKDIFF is determined at runtime
45OPTION_SVN_GM_URL = '--svn-gm-url'
46DEFAULT_SVN_GM_URL = 'http://skia.googlecode.com/svn/trunk/gm'
epoger@google.comfc241ee2012-02-02 16:49:49 +000047
48def CopyAllFilesAddingPrefix(source_dir, dest_dir, prefix):
49 """Copy all files from source_dir into dest_dir, adding prefix to the name
50 of each one as we copy it.
51 prefixes.
52
53 @param source_dir
54 @param dest_dir where to save the copied files
55 @param prefix prefix to add to each filename when we make the copy
56 """
57 all_filenames = os.listdir(source_dir)
58 for filename in all_filenames:
59 source_path = os.path.join(source_dir, filename)
60 if os.path.isdir(source_path):
61 print 'skipping %s because it is a directory, not a file' % filename
62 continue
63 dest_path = os.path.join(dest_dir, '%s%s' % (prefix, filename))
64 shutil.copyfile(source_path, dest_path)
65
66def Flatten(source_dir, dest_dir, subdirectory_pattern):
67 """Copy all files from matching subdirectories under source_dir into
68 dest_dir, flattened into a single directory using subdirectory names as
69 prefixes.
70
71 @param source_dir
72 @param dest_dir where to save the copied files
73 @param subdirectory_pattern only copy files from subdirectories that match
74 this Unix-style filename pattern (e.g., 'base-*')
75 """
76 all_filenames = os.listdir(source_dir)
77 matching_filenames = fnmatch.filter(all_filenames, subdirectory_pattern)
78 for filename in matching_filenames:
79 source_path = os.path.join(source_dir, filename)
80 if not os.path.isdir(source_path):
81 print 'skipping %s because it is a file, not a directory' % filename
82 continue
83 print 'flattening directory %s' % source_path
84 CopyAllFilesAddingPrefix(source_dir=source_path, dest_dir=dest_dir,
85 prefix='%s_' % filename)
86
87def RunCommand(command):
88 """Run a command, raising an exception if it fails.
89
90 @param command the command as a single string
91 """
92 print 'running command [%s]...' % command
93 retval = os.system(command)
94 if retval is not 0:
95 raise Exception('command [%s] failed' % command)
96
epoger@google.comdb12fee2012-02-03 14:32:34 +000097def FindPathToSkDiff(user_set_path=None):
98 """Return path to an existing skdiff binary, or raise an exception if we
99 cannot find one.
100
101 @param user_set_path if None, the user did not specify a path, so look in
102 some likely places; otherwise, only check at this path
103 """
104 if user_set_path is not None:
105 if os.path.isfile(user_set_path):
106 return user_set_path
107 raise Exception('unable to find skdiff at user-set path %s' %
108 user_set_path)
109 trunk_path = os.path.join(os.path.dirname(__file__), os.pardir)
110 possible_paths = [os.path.join(trunk_path, 'out', 'Release', 'skdiff'),
111 os.path.join(trunk_path, 'out', 'Debug', 'skdiff')]
112 for try_path in possible_paths:
113 if os.path.isfile(try_path):
114 return try_path
115 raise Exception('cannot find skdiff in paths %s; maybe you need to '
116 'specify the %s option or build skdiff?' % (
117 possible_paths, OPTION_PATH_TO_SKDIFF))
118
119def CompareBaselines(gm_basedir, path_to_skdiff, svn_gm_url):
120 """Compare the gm results within gm_basedir against those already
epoger@google.comfc241ee2012-02-02 16:49:49 +0000121 committed to the Skia repository.
122
epoger@google.comdb12fee2012-02-03 14:32:34 +0000123 @param gm_basedir
124 @param path_to_skdiff
125 @param svn_gm_url base URL of Subversion repository where we store the
126 expected GM results
epoger@google.comfc241ee2012-02-02 16:49:49 +0000127 """
epoger@google.comdb12fee2012-02-03 14:32:34 +0000128 # Validate parameters, filling in default values if necessary and possible.
129 if not os.path.isdir(gm_basedir):
130 raise Exception('cannot find gm_basedir at %s; maybe you need to '
131 'specify the %s option?' % (
132 gm_basedir, OPTION_GM_BASEDIR))
133 path_to_skdiff = FindPathToSkDiff(path_to_skdiff)
epoger@google.comfc241ee2012-02-02 16:49:49 +0000134
135 tempdir_base = tempfile.mkdtemp()
136
137 # Download all checked-in baseline images to a temp directory
138 checkedin_dir = os.path.join(tempdir_base, 'checkedin')
139 os.mkdir(checkedin_dir)
epoger@google.comdb12fee2012-02-03 14:32:34 +0000140 svn.Svn(checkedin_dir).Checkout(svn_gm_url, '.')
epoger@google.comfc241ee2012-02-02 16:49:49 +0000141
142 # Flatten those checked-in baseline images into checkedin_flattened_dir
143 checkedin_flattened_dir = os.path.join(tempdir_base, 'checkedin_flattened')
144 os.mkdir(checkedin_flattened_dir)
145 Flatten(source_dir=checkedin_dir, dest_dir=checkedin_flattened_dir,
146 subdirectory_pattern='base-*')
147
148 # Flatten the local baseline images into local_flattened_dir
149 local_flattened_dir = os.path.join(tempdir_base, 'local_flattened')
150 os.mkdir(local_flattened_dir)
151 Flatten(source_dir=gm_basedir, dest_dir=local_flattened_dir,
152 subdirectory_pattern='base-*')
153
154 # Run skdiff to compare checkedin_flattened_dir against local_flattened_dir
155 diff_dir = os.path.join(tempdir_base, 'diffs')
156 os.mkdir(diff_dir)
epoger@google.comdb12fee2012-02-03 14:32:34 +0000157 RunCommand('%s %s %s %s' % (path_to_skdiff, checkedin_flattened_dir,
epoger@google.comfc241ee2012-02-02 16:49:49 +0000158 local_flattened_dir, diff_dir))
159 print '\nskdiff results are ready in file://%s/index.html' % diff_dir
epoger@google.comdb12fee2012-02-03 14:32:34 +0000160 # TODO(epoger): delete tempdir_base tree to clean up after ourselves (but
161 # not before the user gets a chance to examine the results), and/or
162 # allow user to specify a different directory to write into?
epoger@google.comfc241ee2012-02-02 16:49:49 +0000163
164def RaiseUsageException():
epoger@google.comdb12fee2012-02-03 14:32:34 +0000165 raise Exception('%s\n\nRun with --help for more detail.' % (
166 USAGE_STRING % __file__))
167
168def Main(options, args):
169 """Allow other scripts to call this script with fake command-line args.
170 """
171 num_args = len(args)
172 if num_args != 0:
173 RaiseUsageException()
174 CompareBaselines(gm_basedir=options.gm_basedir,
175 path_to_skdiff=options.path_to_skdiff,
176 svn_gm_url=options.svn_gm_url)
epoger@google.comfc241ee2012-02-02 16:49:49 +0000177
178if __name__ == '__main__':
179 parser = optparse.OptionParser(USAGE_STRING % '%prog')
epoger@google.comdb12fee2012-02-03 14:32:34 +0000180 parser.add_option(OPTION_GM_BASEDIR,
181 action='store', type='string', default=DEFAULT_GM_BASEDIR,
182 help='path to root of locally stored baseline images '
183 'to compare against those checked into the svn repo; '
184 'defaults to "%s"' % DEFAULT_GM_BASEDIR)
epoger@google.comfc241ee2012-02-02 16:49:49 +0000185 parser.add_option(OPTION_PATH_TO_SKDIFF,
epoger@google.comdb12fee2012-02-03 14:32:34 +0000186 action='store', type='string', default=None,
187 help='path to already-built skdiff tool; if not set, '
188 'will search for it in typical directories near this '
189 'script')
190 parser.add_option(OPTION_SVN_GM_URL,
191 action='store', type='string', default=DEFAULT_SVN_GM_URL,
192 help='URL of SVN repository within which we store the '
193 'expected GM baseline images; defaults to "%s"' %
194 DEFAULT_SVN_GM_URL)
epoger@google.comfc241ee2012-02-02 16:49:49 +0000195 (options, args) = parser.parse_args()
196 Main(options, args)