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 |