aboutsummaryrefslogtreecommitdiffhomepage
path: root/tools/download-baselines.py
blob: da67743a4c8290f5ef0c370dcaddc2c433f18e32 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
'''
Downloads the actual gm results most recently generated by the Skia buildbots,
and adds any new ones to SVN control.

This tool makes it much easier to check in new baselines, via the following
steps:

cd .../trunk
svn update
# make sure there are no files awaiting svn commit
python tools/download-baselines.py gm/base-macmini-lion-fixed  # or other gm/ subdir
# validate that the new images look right (maybe using compare-baselines.py)
# upload CL for review
# validate that the new images look right in the review tool
# commit CL

Launch with --help to see more options.


Copyright 2011 Google Inc.

Use of this source code is governed by a BSD-style license that can be
found in the LICENSE file.
'''

# common Python modules
import fnmatch
import optparse
import os
import re
import shutil
import sys
import tempfile

# modules declared within this same directory
import svn

# Base URL of SVN repository where buildbots store actual gm image results.
SVN_BASE_URL = 'http://skia-autogen.googlecode.com/svn/gm-actual'

USAGE_STRING = 'usage: %s [options] <baseline_subdir>'
OPTION_IGNORE_LOCAL_MODS = '--ignore-local-mods'
OPTION_ADD_NEW_FILES = '--add-new-files'

def GetLatestResultsSvnUrl(baseline_subdir):
    """Return SVN URL from which we can check out the MOST RECENTLY generated
    images for this baseline type.

    @param baseline_subdir indicates which platform we want images for
    """
    # trim off 'gm/' prefix
    gm_prefix = 'gm%s' % os.sep
    if not baseline_subdir.startswith(gm_prefix):
        raise Exception('baseline_subdir "%s" should start with "%s"' % (
            baseline_subdir, gm_prefix))
    return '%s/%s' % (SVN_BASE_URL, baseline_subdir[len(gm_prefix):])

def CopyMatchingFiles(source_dir, dest_dir, filename_pattern,
                      only_copy_updates=False):
    """Copy all files from source_dir that match filename_pattern, and
    save them (with their original filenames) in dest_dir.

    @param source_dir
    @param dest_dir where to save the copied files
    @param filename_pattern only copy files that match this Unix-style filename
           pattern (e.g., '*.jpg')
    @param only_copy_updates if True, only copy files that are already
           present in dest_dir
    """
    all_filenames = os.listdir(source_dir)
    matching_filenames = fnmatch.filter(all_filenames, filename_pattern)
    for filename in matching_filenames:
        source_path = os.path.join(source_dir, filename)
        dest_path = os.path.join(dest_dir, filename)
        if only_copy_updates and not os.path.isfile(dest_path):
            continue
        shutil.copyfile(source_path, dest_path)

def Main(options, args):
    """Download most recently generated baseline images for a given platform,
    and add any new ones to SVN control.

    @param options
    @param args
    """
    num_args = len(args)
    if num_args != 1:
        RaiseUsageException()

    # Create repo_to_modify to handle the SVN repository we will add files to.
    baseline_subdir = args[0].rstrip(os.sep);
    if not os.path.isdir(baseline_subdir):
        raise Exception('could not find baseline_subdir "%s"' % baseline_subdir)
    repo_to_modify = svn.Svn(baseline_subdir)

    # If there are any locally modified files in that directory, exit
    # (so that we don't risk overwriting the user's previous work).
    new_and_modified_files = repo_to_modify.GetNewAndModifiedFiles()
    if not options.ignore_local_mods:
        if new_and_modified_files:
            raise Exception('Exiting because there are already new and/or '
                            'modified files in %s.  To continue in spite of '
                            'that, run with %s option.' % (
                                baseline_subdir, OPTION_IGNORE_LOCAL_MODS))

    # Download actual gm images into a separate repo in a temporary directory.
    tempdir = tempfile.mkdtemp()
    download_repo = svn.Svn(tempdir)
    download_repo.Checkout(GetLatestResultsSvnUrl(baseline_subdir), '.')

    # Copy any of those files we are interested in into repo_to_modify,
    # and then delete the temporary directory.
    CopyMatchingFiles(source_dir=tempdir, dest_dir=baseline_subdir,
                      filename_pattern='*.png',
                      only_copy_updates=(not options.add_new_files))
    shutil.rmtree(tempdir)
    download_repo = None

    # Add any new files to SVN control (if we are running with add_new_files).
    new_files = repo_to_modify.GetNewFiles()
    if new_files and options.add_new_files:
        repo_to_modify.AddFiles(new_files)

    # Set the mimetype property on *all* image files in baseline_subdir, even
    # the ones that were already there (in case that property wasn't properly
    # set already).
    repo_to_modify.SetPropertyByFilenamePattern(
        '*.png', svn.PROPERTY_MIMETYPE, 'image/png')
    repo_to_modify.SetPropertyByFilenamePattern(
        '*.pdf', svn.PROPERTY_MIMETYPE, 'application/pdf')

def RaiseUsageException():
    raise Exception(USAGE_STRING %  __file__)

if __name__ == '__main__':
    parser = optparse.OptionParser(USAGE_STRING % '%prog')
    parser.add_option(OPTION_IGNORE_LOCAL_MODS,
                      action='store_true', default=False,
                      help='allow tool to run even if there are already '
                      'local modifications in the baseline_subdir')
    parser.add_option(OPTION_ADD_NEW_FILES,
                      action='store_true', default=False,
                      help='in addition to downloading new versions of '
                      'existing baselines, also download baselines that are '
                      'not under SVN control yet')
    (options, args) = parser.parse_args()
    Main(options, args)