Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(16)

Side by Side Diff: tools/svndiff.py

Issue 19512002: svndiff.py: add support for git checkouts (Closed) Base URL: http://skia.googlecode.com/svn/trunk/
Patch Set: remove_some_porcelain Created 7 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 #!/usr/bin/python 1 #!/usr/bin/python
2 ''' 2 '''
3 Copyright 2012 Google Inc. 3 Copyright 2012 Google Inc.
4 4
5 Use of this source code is governed by a BSD-style license that can be 5 Use of this source code is governed by a BSD-style license that can be
6 found in the LICENSE file. 6 found in the LICENSE file.
7 ''' 7 '''
8 8
9 ''' 9 '''
10 Generates a visual diff of all pending changes in the local SVN checkout. 10 Generates a visual diff of all pending changes in the local SVN (or git!)
11 checkout.
11 12
12 Launch with --help to see more information. 13 Launch with --help to see more information.
13 14
15 TODO(epoger): Now that this tool supports either git or svn, rename it.
14 TODO(epoger): Fix indentation in this file (2-space indents, not 4-space). 16 TODO(epoger): Fix indentation in this file (2-space indents, not 4-space).
15 ''' 17 '''
16 18
17 # common Python modules 19 # common Python modules
18 import optparse 20 import optparse
19 import os 21 import os
20 import re 22 import re
21 import shutil 23 import shutil
24 import subprocess
22 import sys 25 import sys
23 import tempfile 26 import tempfile
24 import urllib2 27 import urllib2
25 28
26 # Imports from within Skia 29 # Imports from within Skia
27 # 30 #
28 # We need to add the 'gm' directory, so that we can import gm_json.py within 31 # We need to add the 'gm' directory, so that we can import gm_json.py within
29 # that directory. That script allows us to parse the actual-results.json file 32 # that directory. That script allows us to parse the actual-results.json file
30 # written out by the GM tool. 33 # written out by the GM tool.
31 # Make sure that the 'gm' dir is in the PYTHONPATH, but add it at the *end* 34 # Make sure that the 'gm' dir is in the PYTHONPATH, but add it at the *end*
32 # so any dirs that are already in the PYTHONPATH will be preferred. 35 # so any dirs that are already in the PYTHONPATH will be preferred.
33 # 36 #
34 # This assumes that the 'gm' directory has been checked out as a sibling of 37 # This assumes that the 'gm' directory has been checked out as a sibling of
35 # the 'tools' directory containing this script, which will be the case if 38 # the 'tools' directory containing this script, which will be the case if
36 # 'trunk' was checked out as a single unit. 39 # 'trunk' was checked out as a single unit.
37 GM_DIRECTORY = os.path.realpath( 40 GM_DIRECTORY = os.path.realpath(
38 os.path.join(os.path.dirname(os.path.dirname(__file__)), 'gm')) 41 os.path.join(os.path.dirname(os.path.dirname(__file__)), 'gm'))
39 if GM_DIRECTORY not in sys.path: 42 if GM_DIRECTORY not in sys.path:
40 sys.path.append(GM_DIRECTORY) 43 sys.path.append(GM_DIRECTORY)
41 import gm_json 44 import gm_json
42 import jsondiff 45 import jsondiff
43 import svn 46 import svn
44 47
45 USAGE_STRING = 'Usage: %s [options]' 48 USAGE_STRING = 'Usage: %s [options]'
46 HELP_STRING = ''' 49 HELP_STRING = '''
47 50
48 Generates a visual diff of all pending changes in the local SVN checkout. 51 Generates a visual diff of all pending changes in the local SVN/git checkout.
49 52
50 This includes a list of all files that have been added, deleted, or modified 53 This includes a list of all files that have been added, deleted, or modified
51 (as far as SVN knows about). For any image modifications, pixel diffs will 54 (as far as SVN/git knows about). For any image modifications, pixel diffs will
52 be generated. 55 be generated.
53 56
54 ''' 57 '''
55 58
56 IMAGE_FILENAME_RE = re.compile(gm_json.IMAGE_FILENAME_PATTERN) 59 IMAGE_FILENAME_RE = re.compile(gm_json.IMAGE_FILENAME_PATTERN)
57 60
58 TRUNK_PATH = os.path.join(os.path.dirname(__file__), os.pardir) 61 TRUNK_PATH = os.path.join(os.path.dirname(__file__), os.pardir)
59 62
60 OPTION_DEST_DIR = '--dest-dir' 63 OPTION_DEST_DIR = '--dest-dir'
61 OPTION_PATH_TO_SKDIFF = '--path-to-skdiff' 64 OPTION_PATH_TO_SKDIFF = '--path-to-skdiff'
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
153 if new_checksum: 156 if new_checksum:
154 new_image_url = _CreateGSUrl( 157 new_image_url = _CreateGSUrl(
155 imagename=imagename, 158 imagename=imagename,
156 hash_type=gm_json.JSONKEY_HASHTYPE_BITMAP_64BITMD5, 159 hash_type=gm_json.JSONKEY_HASHTYPE_BITMAP_64BITMD5,
157 hash_digest=new_checksum) 160 hash_digest=new_checksum)
158 _DownloadUrlToFile( 161 _DownloadUrlToFile(
159 source_url=new_image_url, 162 source_url=new_image_url,
160 dest_path=os.path.join(new_flattened_dir, 163 dest_path=os.path.join(new_flattened_dir,
161 filename_prefix + imagename)) 164 filename_prefix + imagename))
162 165
166 def _RunCommand(args):
167 """Run a command (from self._directory) and return stdout as a single
168 string.
169
170 @param args a list of arguments
171 """
172 proc = subprocess.Popen(args,
173 stdout=subprocess.PIPE,
174 stderr=subprocess.PIPE)
175 (stdout, stderr) = proc.communicate()
176 if proc.returncode is not 0:
177 raise Exception('command "%s" failed: %s' % (args, stderr))
178 return stdout
179
180 def _GitGetModifiedFiles():
181 """Returns a list of locally modified files within the current working dir.
182
183 TODO(epoger): Move this into a git utility package?
184 """
185 return _RunCommand(['git', 'ls-files', '-m']).splitlines()
Stephen White 2013/07/18 17:32:38 Much nicer, thanks.
186
187 def _GitExportBaseVersionOfFile(file_within_repo, dest_path):
188 """Retrieves a copy of the base version of a file within the repository.
189
190 @param file_within_repo path to the file within the repo whose base
191 version you wish to obtain
192 @param dest_path destination to which to write the base content
193
194 TODO(epoger): Move this into a git utility package?
195 """
196 args = ['git', 'show', os.path.join('HEAD:.', file_within_repo)]
197 with open(dest_path, 'wb') as outfile:
198 proc = subprocess.Popen(args, stdout=outfile)
199 proc.communicate()
200 if proc.returncode is not 0:
201 raise Exception('command "%s" failed' % args)
202
163 def SvnDiff(path_to_skdiff, dest_dir, source_dir): 203 def SvnDiff(path_to_skdiff, dest_dir, source_dir):
164 """Generates a visual diff of all pending changes in source_dir. 204 """Generates a visual diff of all pending changes in source_dir.
165 205
166 @param path_to_skdiff 206 @param path_to_skdiff
167 @param dest_dir existing directory within which to write results 207 @param dest_dir existing directory within which to write results
168 @param source_dir 208 @param source_dir
169 """ 209 """
170 # Validate parameters, filling in default values if necessary and possible. 210 # Validate parameters, filling in default values if necessary and possible.
171 path_to_skdiff = os.path.abspath(FindPathToSkDiff(path_to_skdiff)) 211 path_to_skdiff = os.path.abspath(FindPathToSkDiff(path_to_skdiff))
172 if not dest_dir: 212 if not dest_dir:
173 dest_dir = tempfile.mkdtemp() 213 dest_dir = tempfile.mkdtemp()
174 dest_dir = os.path.abspath(dest_dir) 214 dest_dir = os.path.abspath(dest_dir)
175 215
176 os.chdir(source_dir) 216 os.chdir(source_dir)
217 using_svn = os.path.isdir('.svn')
177 218
178 # Prepare temporary directories. 219 # Prepare temporary directories.
179 modified_flattened_dir = os.path.join(dest_dir, 'modified_flattened') 220 modified_flattened_dir = os.path.join(dest_dir, 'modified_flattened')
180 original_flattened_dir = os.path.join(dest_dir, 'original_flattened') 221 original_flattened_dir = os.path.join(dest_dir, 'original_flattened')
181 diff_dir = os.path.join(dest_dir, 'diffs') 222 diff_dir = os.path.join(dest_dir, 'diffs')
182 for dir in [modified_flattened_dir, original_flattened_dir, diff_dir] : 223 for dir in [modified_flattened_dir, original_flattened_dir, diff_dir] :
183 shutil.rmtree(dir, ignore_errors=True) 224 shutil.rmtree(dir, ignore_errors=True)
184 os.mkdir(dir) 225 os.mkdir(dir)
185 226
186 # Get a list of all locally modified (including added/deleted) files, 227 # Get a list of all locally modified (including added/deleted) files,
187 # descending subdirectories. 228 # descending subdirectories.
188 svn_repo = svn.Svn('.') 229 if using_svn:
189 modified_file_paths = svn_repo.GetFilesWithStatus( 230 svn_repo = svn.Svn('.')
190 svn.STATUS_ADDED | svn.STATUS_DELETED | svn.STATUS_MODIFIED) 231 modified_file_paths = svn_repo.GetFilesWithStatus(
232 svn.STATUS_ADDED | svn.STATUS_DELETED | svn.STATUS_MODIFIED)
233 else:
234 modified_file_paths = _GitGetModifiedFiles()
191 235
192 # For each modified file: 236 # For each modified file:
193 # 1. copy its current contents into modified_flattened_dir 237 # 1. copy its current contents into modified_flattened_dir
194 # 2. copy its original contents into original_flattened_dir 238 # 2. copy its original contents into original_flattened_dir
195 for modified_file_path in modified_file_paths: 239 for modified_file_path in modified_file_paths:
196 if modified_file_path.endswith('.json'): 240 if modified_file_path.endswith('.json'):
197 # Special handling for JSON files, in the hopes that they 241 # Special handling for JSON files, in the hopes that they
198 # contain GM result summaries. 242 # contain GM result summaries.
199 (_unused, original_file_path) = tempfile.mkstemp() 243 (_unused, original_file_path) = tempfile.mkstemp()
200 svn_repo.ExportBaseVersionOfFile(modified_file_path, 244 if using_svn:
201 original_file_path) 245 svn_repo.ExportBaseVersionOfFile(
246 modified_file_path, original_file_path)
247 else:
248 _GitExportBaseVersionOfFile(
249 modified_file_path, original_file_path)
202 platform_prefix = re.sub(os.sep, '__', 250 platform_prefix = re.sub(os.sep, '__',
203 os.path.dirname(modified_file_path)) + '__' 251 os.path.dirname(modified_file_path)) + '__'
204 _CallJsonDiff(old_json_path=original_file_path, 252 _CallJsonDiff(old_json_path=original_file_path,
205 new_json_path=modified_file_path, 253 new_json_path=modified_file_path,
206 old_flattened_dir=original_flattened_dir, 254 old_flattened_dir=original_flattened_dir,
207 new_flattened_dir=modified_flattened_dir, 255 new_flattened_dir=modified_flattened_dir,
208 filename_prefix=platform_prefix) 256 filename_prefix=platform_prefix)
209 os.remove(original_file_path) 257 os.remove(original_file_path)
210 else: 258 else:
211 dest_filename = re.sub(os.sep, '__', modified_file_path) 259 dest_filename = re.sub(os.sep, '__', modified_file_path)
212 # If the file had STATUS_DELETED, it won't exist anymore... 260 # If the file had STATUS_DELETED, it won't exist anymore...
213 if os.path.isfile(modified_file_path): 261 if os.path.isfile(modified_file_path):
214 shutil.copyfile(modified_file_path, 262 shutil.copyfile(modified_file_path,
215 os.path.join(modified_flattened_dir, 263 os.path.join(modified_flattened_dir,
216 dest_filename)) 264 dest_filename))
217 svn_repo.ExportBaseVersionOfFile( 265 if using_svn:
218 modified_file_path, 266 svn_repo.ExportBaseVersionOfFile(
219 os.path.join(original_flattened_dir, dest_filename)) 267 modified_file_path,
268 os.path.join(original_flattened_dir, dest_filename))
269 else:
270 _GitExportBaseVersionOfFile(
271 modified_file_path,
272 os.path.join(original_flattened_dir, dest_filename))
220 273
221 # Run skdiff: compare original_flattened_dir against modified_flattened_dir 274 # Run skdiff: compare original_flattened_dir against modified_flattened_dir
222 RunCommand('%s %s %s %s' % (path_to_skdiff, original_flattened_dir, 275 RunCommand('%s %s %s %s' % (path_to_skdiff, original_flattened_dir,
223 modified_flattened_dir, diff_dir)) 276 modified_flattened_dir, diff_dir))
224 print '\nskdiff results are ready in file://%s/index.html' % diff_dir 277 print '\nskdiff results are ready in file://%s/index.html' % diff_dir
225 278
226 def RaiseUsageException(): 279 def RaiseUsageException():
227 raise Exception('%s\nRun with --help for more detail.' % ( 280 raise Exception('%s\nRun with --help for more detail.' % (
228 USAGE_STRING % __file__)) 281 USAGE_STRING % __file__))
229 282
(...skipping 17 matching lines...) Expand all
247 action='store', type='string', default=None, 300 action='store', type='string', default=None,
248 help='path to already-built skdiff tool; if not set, ' 301 help='path to already-built skdiff tool; if not set, '
249 'will search for it in typical directories near this ' 302 'will search for it in typical directories near this '
250 'script') 303 'script')
251 parser.add_option(OPTION_SOURCE_DIR, 304 parser.add_option(OPTION_SOURCE_DIR,
252 action='store', type='string', default='.', 305 action='store', type='string', default='.',
253 help='root directory within which to compare all ' + 306 help='root directory within which to compare all ' +
254 'files; defaults to "%default"') 307 'files; defaults to "%default"')
255 (options, args) = parser.parse_args() 308 (options, args) = parser.parse_args()
256 Main(options, args) 309 Main(options, args)
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698