blob: 21047f2d8ef8967293784d9b4f5c0011f3aaed6d [file] [log] [blame]
epoger@google.com27442af2011-12-29 21:13:08 +00001'''
2Downloads the actual gm results most recently generated by the Skia buildbots,
3and adds any new ones to SVN control.
4
epoger@google.com1610a682012-04-12 18:02:25 +00005Launch with --help to see more information.
epoger@google.comd6256552012-01-10 14:10:34 +00006
epoger@google.com27442af2011-12-29 21:13:08 +00007
8Copyright 2011 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
epoger@google.com20ad5ac2012-01-17 21:26:05 +000015import fnmatch
epoger@google.comd6256552012-01-10 14:10:34 +000016import optparse
17import os
epoger@google.com27442af2011-12-29 21:13:08 +000018import re
epoger@google.com20ad5ac2012-01-17 21:26:05 +000019import shutil
epoger@google.com27442af2011-12-29 21:13:08 +000020import sys
epoger@google.com20ad5ac2012-01-17 21:26:05 +000021import tempfile
epoger@google.com27442af2011-12-29 21:13:08 +000022
23# modules declared within this same directory
epoger@google.com1610a682012-04-12 18:02:25 +000024import compare_baselines
epoger@google.com27442af2011-12-29 21:13:08 +000025import svn
26
epoger@google.com1610a682012-04-12 18:02:25 +000027USAGE_STRING = 'Usage: %s [options] [baseline_subdir]...'
28HELP_STRING = '''
29
30Downloads the actual gm results most recently generated by the Skia buildbots,
31and adds any new ones to SVN control.
32
33If no baseline_subdir is given, then this tool will download the most-recently
34generated actual gm results for ALL platforms.
35
36''' + compare_baselines.HOWTO_STRING
37
epoger@google.com20ad5ac2012-01-17 21:26:05 +000038# Base URL of SVN repository where buildbots store actual gm image results.
39SVN_BASE_URL = 'http://skia-autogen.googlecode.com/svn/gm-actual'
epoger@google.com27442af2011-12-29 21:13:08 +000040
epoger@google.comd6256552012-01-10 14:10:34 +000041OPTION_IGNORE_LOCAL_MODS = '--ignore-local-mods'
42OPTION_ADD_NEW_FILES = '--add-new-files'
43
epoger@google.com20ad5ac2012-01-17 21:26:05 +000044def GetLatestResultsSvnUrl(baseline_subdir):
45 """Return SVN URL from which we can check out the MOST RECENTLY generated
epoger@google.com27442af2011-12-29 21:13:08 +000046 images for this baseline type.
47
48 @param baseline_subdir indicates which platform we want images for
49 """
epoger@google.com20ad5ac2012-01-17 21:26:05 +000050 # 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.com27442af2011-12-29 21:13:08 +000056
epoger@google.com20ad5ac2012-01-17 21:26:05 +000057def 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.com27442af2011-12-29 21:13:08 +000061
epoger@google.com20ad5ac2012-01-17 21:26:05 +000062 @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.com27442af2011-12-29 21:13:08 +000068 """
epoger@google.com20ad5ac2012-01-17 21:26:05 +000069 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.comd6256552012-01-10 14:10:34 +000075 continue
epoger@google.com20ad5ac2012-01-17 21:26:05 +000076 shutil.copyfile(source_path, dest_path)
epoger@google.com27442af2011-12-29 21:13:08 +000077
epoger@google.com1610a682012-04-12 18:02:25 +000078def DownloadBaselinesForOnePlatform(baseline_subdir):
79 """Download most recently generated baseline images for a single platform,
epoger@google.com27442af2011-12-29 21:13:08 +000080 and add any new ones to SVN control.
81
epoger@google.com1610a682012-04-12 18:02:25 +000082 @param baseline_subdir
epoger@google.com27442af2011-12-29 21:13:08 +000083 """
epoger@google.com20ad5ac2012-01-17 21:26:05 +000084 # Create repo_to_modify to handle the SVN repository we will add files to.
epoger@google.com20ad5ac2012-01-17 21:26:05 +000085 repo_to_modify = svn.Svn(baseline_subdir)
epoger@google.comd6256552012-01-10 14:10:34 +000086
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.com20ad5ac2012-01-17 21:26:05 +000089 new_and_modified_files = repo_to_modify.GetNewAndModifiedFiles()
epoger@google.comd6256552012-01-10 14:10:34 +000090 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.com20ad5ac2012-01-17 21:26:05 +000097 # 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.comd6256552012-01-10 14:10:34 +0000109
110 # Add any new files to SVN control (if we are running with add_new_files).
epoger@google.com0f645b62012-05-22 19:14:01 +0000111 if options.add_new_files:
112 new_files = repo_to_modify.GetNewFiles()
113 if new_files:
114 repo_to_modify.AddFiles(sorted(new_files))
epoger@google.com20ad5ac2012-01-17 21:26:05 +0000115
epoger@google.com0f645b62012-05-22 19:14:01 +0000116 # Set the mimetype property on any new/modified image files in
117 # baseline_subdir. (We used to set the mimetype property on *all* image
118 # files in the directory, even those whose content wasn't changing,
119 # but that caused confusion. See
120 # http://code.google.com/p/skia/issues/detail?id=618 .)
121 modified_files = repo_to_modify.GetNewAndModifiedFiles()
122 repo_to_modify.SetProperty(sorted(fnmatch.filter(modified_files, '*.png')),
123 svn.PROPERTY_MIMETYPE, 'image/png')
124 repo_to_modify.SetProperty(sorted(fnmatch.filter(modified_files, '*.pdf')),
125 svn.PROPERTY_MIMETYPE, 'application/pdf')
epoger@google.com27442af2011-12-29 21:13:08 +0000126
epoger@google.comd6256552012-01-10 14:10:34 +0000127def RaiseUsageException():
epoger@google.com1610a682012-04-12 18:02:25 +0000128 raise Exception('%s\nRun with --help for more detail.' % (
129 USAGE_STRING % __file__))
130
131def Main(options, args):
132 """Allow other scripts to call this script with fake command-line args.
133 """
134 # If no platforms are specified, do 'em all.
135 num_args = len(args)
136 if num_args == 0:
137 # TODO(epoger): automate the default set of platforms. We want to ensure
138 # that the user gets all of the platforms that the bots are running,
139 # not just whatever subdirectories he happens to have checked out...
epoger@google.com4a6ba462012-07-27 15:19:54 +0000140 # See http://code.google.com/p/skia/issues/detail?id=678
141 #
142 # For now, I generate this list using these Unix commands:
143 # svn ls http://skia.googlecode.com/svn/trunk/gm | grep ^base | sort >/tmp/baselines
144 # svn ls http://skia-autogen.googlecode.com/svn/gm-actual | grep ^base | sort >/tmp/actual
145 # comm -1 -2 /tmp/baselines /tmp/actual
epoger@google.com1610a682012-04-12 18:02:25 +0000146 args = [
borenet@google.com855cd7a2012-07-18 21:23:40 +0000147 'gm/base-android-nexus-s',
148 'gm/base-android-xoom',
epoger@google.com1610a682012-04-12 18:02:25 +0000149 'gm/base-linux',
epoger@google.com1610a682012-04-12 18:02:25 +0000150 'gm/base-macmini',
epoger@google.com1610a682012-04-12 18:02:25 +0000151 'gm/base-macmini-lion-float',
epoger@google.com4a6ba462012-07-27 15:19:54 +0000152 'gm/base-shuttle_ubuntu12_ati5770',
153 'gm/base-shuttle-win7-intel-float',
epoger@google.com1610a682012-04-12 18:02:25 +0000154 'gm/base-win',
epoger@google.com1610a682012-04-12 18:02:25 +0000155 ]
156
157 # Trim all subdir names.
158 baseline_subdirs = []
159 for arg in args:
160 baseline_subdirs.append(arg.rstrip(os.sep))
161
162 # Make sure all those subdirectories exist.
163 for baseline_subdir in baseline_subdirs:
164 if not os.path.isdir(baseline_subdir):
165 raise Exception('could not find baseline_subdir "%s"' %
166 baseline_subdir)
167
168 # Process the subdirs, one at a time.
169 for baseline_subdir in baseline_subdirs:
170 DownloadBaselinesForOnePlatform(baseline_subdir=baseline_subdir)
epoger@google.comd6256552012-01-10 14:10:34 +0000171
epoger@google.com27442af2011-12-29 21:13:08 +0000172if __name__ == '__main__':
epoger@google.com1610a682012-04-12 18:02:25 +0000173 parser = optparse.OptionParser(USAGE_STRING % '%prog' + HELP_STRING)
epoger@google.comd6256552012-01-10 14:10:34 +0000174 parser.add_option(OPTION_IGNORE_LOCAL_MODS,
175 action='store_true', default=False,
176 help='allow tool to run even if there are already '
177 'local modifications in the baseline_subdir')
178 parser.add_option(OPTION_ADD_NEW_FILES,
179 action='store_true', default=False,
180 help='in addition to downloading new versions of '
181 'existing baselines, also download baselines that are '
182 'not under SVN control yet')
183 (options, args) = parser.parse_args()
184 Main(options, args)
epoger@google.com4a6ba462012-07-27 15:19:54 +0000185