blob: 23b98dea348ea1944e9f9f8ad6c02b4b22b45815 [file] [log] [blame]
epoger@google.com2e0a0612012-05-25 19:48:05 +00001'''
2Compares all locally modified images within this SVN checkout against the
3SVN base revision of each image.
4
5Launch with --help to see more information.
6
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 optparse
16import os
17import re
18import shutil
19import tempfile
20
21# modules declared within this same directory
22import svn
23
24USAGE_STRING = 'Usage: %s [options]'
25HELP_STRING = '''
26
27Compares all locally modified images within this SVN checkout against the
28SVN base revision of each image.
29
30'''
31
32TRUNK_PATH = os.path.join(os.path.dirname(__file__), os.pardir)
33
34OPTION_DEST_DIR = '--dest-dir'
35# default DEST_DIR is determined at runtime
36OPTION_PATH_TO_SKDIFF = '--path-to-skdiff'
37# default PATH_TO_SKDIFF is determined at runtime
38
39def RunCommand(command):
40 """Run a command, raising an exception if it fails.
41
42 @param command the command as a single string
43 """
44 print 'running command [%s]...' % command
45 retval = os.system(command)
46 if retval is not 0:
47 raise Exception('command [%s] failed' % command)
48
49def FindPathToSkDiff(user_set_path=None):
50 """Return path to an existing skdiff binary, or raise an exception if we
51 cannot find one.
52
53 @param user_set_path if None, the user did not specify a path, so look in
54 some likely places; otherwise, only check at this path
55 """
56 if user_set_path is not None:
57 if os.path.isfile(user_set_path):
58 return user_set_path
59 raise Exception('unable to find skdiff at user-set path %s' %
60 user_set_path)
61 trunk_path = os.path.join(os.path.dirname(__file__), os.pardir)
62 possible_paths = [os.path.join(trunk_path, 'out', 'Release', 'skdiff'),
63 os.path.join(trunk_path, 'out', 'Debug', 'skdiff')]
64 for try_path in possible_paths:
65 if os.path.isfile(try_path):
66 return try_path
67 raise Exception('cannot find skdiff in paths %s; maybe you need to '
68 'specify the %s option or build skdiff?' % (
69 possible_paths, OPTION_PATH_TO_SKDIFF))
70
71def SvnDiff(path_to_skdiff, dest_dir):
72 """Compares all locally modified images within this SVN checkout against
73 the SVN base revision of each image.
74
75 @param path_to_skdiff
76 @param dest_dir existing directory within which to write results
77 """
78 # Validate parameters, filling in default values if necessary and possible.
79 path_to_skdiff = FindPathToSkDiff(path_to_skdiff)
80 if not dest_dir:
81 dest_dir = tempfile.mkdtemp()
82
83 # Prepare temporary directories.
84 modified_flattened_dir = os.path.join(dest_dir, 'modified_flattened')
85 original_flattened_dir = os.path.join(dest_dir, 'original_flattened')
86 diff_dir = os.path.join(dest_dir, 'diffs')
87 for dir in [modified_flattened_dir, original_flattened_dir, diff_dir] :
88 shutil.rmtree(dir, ignore_errors=True)
89 os.mkdir(dir)
90
91 # Get a list of all locally modified files, descending subdirectories.
92 svn_repo = svn.Svn('.')
93 modified_file_paths = svn_repo.GetModifiedFiles()
94
95 # For each modified file:
96 # 1. copy its current contents into modified_flattened_dir
97 # 2. copy its original contents into original_flattened_dir
98 for modified_file_path in modified_file_paths:
99 dest_filename = re.sub(os.sep, '__', modified_file_path)
100 shutil.copyfile(modified_file_path,
101 os.path.join(modified_flattened_dir, dest_filename))
102 svn_repo.ExportBaseVersionOfFile(
103 modified_file_path,
104 os.path.join(original_flattened_dir, dest_filename))
105
106 # Run skdiff: compare original_flattened_dir against modified_flattened_dir
107 RunCommand('%s %s %s %s' % (path_to_skdiff, original_flattened_dir,
108 modified_flattened_dir, diff_dir))
109 print '\nskdiff results are ready in file://%s/index.html' % diff_dir
110
111def RaiseUsageException():
112 raise Exception('%s\nRun with --help for more detail.' % (
113 USAGE_STRING % __file__))
114
115def Main(options, args):
116 """Allow other scripts to call this script with fake command-line args.
117 """
118 num_args = len(args)
119 if num_args != 0:
120 RaiseUsageException()
121 SvnDiff(path_to_skdiff=options.path_to_skdiff, dest_dir=options.dest_dir)
122
123if __name__ == '__main__':
124 parser = optparse.OptionParser(USAGE_STRING % '%prog' + HELP_STRING)
125 parser.add_option(OPTION_DEST_DIR,
126 action='store', type='string', default=None,
127 help='existing directory within which to write results; '
128 'if not set, will create a temporary directory which '
129 'will remain in place after this script completes')
130 parser.add_option(OPTION_PATH_TO_SKDIFF,
131 action='store', type='string', default=None,
132 help='path to already-built skdiff tool; if not set, '
133 'will search for it in typical directories near this '
134 'script')
135 (options, args) = parser.parse_args()
136 Main(options, args)