Index: tools/svndiff.py |
=================================================================== |
--- tools/svndiff.py (revision 10121) |
+++ tools/svndiff.py (working copy) |
@@ -7,10 +7,12 @@ |
''' |
''' |
-Generates a visual diff of all pending changes in the local SVN checkout. |
+Generates a visual diff of all pending changes in the local SVN (or git!) |
+checkout. |
Launch with --help to see more information. |
+TODO(epoger): Now that this tool supports either git or svn, rename it. |
TODO(epoger): Fix indentation in this file (2-space indents, not 4-space). |
''' |
@@ -19,6 +21,7 @@ |
import os |
import re |
import shutil |
+import subprocess |
import sys |
import tempfile |
import urllib2 |
@@ -45,10 +48,10 @@ |
USAGE_STRING = 'Usage: %s [options]' |
HELP_STRING = ''' |
-Generates a visual diff of all pending changes in the local SVN checkout. |
+Generates a visual diff of all pending changes in the local SVN/git checkout. |
This includes a list of all files that have been added, deleted, or modified |
-(as far as SVN knows about). For any image modifications, pixel diffs will |
+(as far as SVN/git knows about). For any image modifications, pixel diffs will |
be generated. |
''' |
@@ -160,6 +163,52 @@ |
dest_path=os.path.join(new_flattened_dir, |
filename_prefix + imagename)) |
+def _RunCommand(args): |
+ """Run a command (from self._directory) and return stdout as a single |
+ string. |
+ |
+ @param args a list of arguments |
+ """ |
+ proc = subprocess.Popen(args, |
+ stdout=subprocess.PIPE, |
+ stderr=subprocess.PIPE) |
+ (stdout, stderr) = proc.communicate() |
+ if proc.returncode is not 0: |
+ raise Exception('command "%s" failed: %s' % (args, stderr)) |
+ return stdout |
+ |
+def _GitGetModifiedFiles(): |
+ """Returns a list of locally modified files within the current working dir. |
+ |
+ TODO(epoger): Move this into a git utility package? |
+ """ |
+ return _RunCommand(['git', 'ls-files', '-m']).splitlines() |
+ |
+def _GitExportBaseVersionOfFile(file_within_repo, dest_path): |
+ """Retrieves a copy of the base version of a file within the repository. |
+ |
+ @param file_within_repo path to the file within the repo whose base |
+ version you wish to obtain |
+ @param dest_path destination to which to write the base content |
+ |
+ TODO(epoger): Move this into a git utility package? |
+ """ |
+ # TODO(epoger): Replace use of "git show" command with lower-level git |
+ # commands? senorblanco points out that "git show" is a "porcelain" |
+ # command, intended for human use, as opposed to the "plumbing" commands |
+ # generally more suitable for scripting. (See |
+ # http://git-scm.com/book/en/Git-Internals-Plumbing-and-Porcelain ) |
+ # |
+ # For now, though, "git show" is the most straightforward implementation |
+ # I could come up with. I tried using "git cat-file", but I had trouble |
+ # getting it to work as desired. |
+ args = ['git', 'show', os.path.join('HEAD:.', file_within_repo)] |
+ with open(dest_path, 'wb') as outfile: |
+ proc = subprocess.Popen(args, stdout=outfile) |
+ proc.communicate() |
+ if proc.returncode is not 0: |
+ raise Exception('command "%s" failed' % args) |
+ |
def SvnDiff(path_to_skdiff, dest_dir, source_dir): |
"""Generates a visual diff of all pending changes in source_dir. |
@@ -174,6 +223,7 @@ |
dest_dir = os.path.abspath(dest_dir) |
os.chdir(source_dir) |
+ using_svn = os.path.isdir('.svn') |
# Prepare temporary directories. |
modified_flattened_dir = os.path.join(dest_dir, 'modified_flattened') |
@@ -185,9 +235,12 @@ |
# Get a list of all locally modified (including added/deleted) files, |
# descending subdirectories. |
- svn_repo = svn.Svn('.') |
- modified_file_paths = svn_repo.GetFilesWithStatus( |
- svn.STATUS_ADDED | svn.STATUS_DELETED | svn.STATUS_MODIFIED) |
+ if using_svn: |
+ svn_repo = svn.Svn('.') |
+ modified_file_paths = svn_repo.GetFilesWithStatus( |
+ svn.STATUS_ADDED | svn.STATUS_DELETED | svn.STATUS_MODIFIED) |
+ else: |
+ modified_file_paths = _GitGetModifiedFiles() |
# For each modified file: |
# 1. copy its current contents into modified_flattened_dir |
@@ -197,8 +250,12 @@ |
# Special handling for JSON files, in the hopes that they |
# contain GM result summaries. |
(_unused, original_file_path) = tempfile.mkstemp() |
- svn_repo.ExportBaseVersionOfFile(modified_file_path, |
- original_file_path) |
+ if using_svn: |
+ svn_repo.ExportBaseVersionOfFile( |
+ modified_file_path, original_file_path) |
+ else: |
+ _GitExportBaseVersionOfFile( |
+ modified_file_path, original_file_path) |
platform_prefix = re.sub(os.sep, '__', |
os.path.dirname(modified_file_path)) + '__' |
_CallJsonDiff(old_json_path=original_file_path, |
@@ -214,9 +271,14 @@ |
shutil.copyfile(modified_file_path, |
os.path.join(modified_flattened_dir, |
dest_filename)) |
- svn_repo.ExportBaseVersionOfFile( |
- modified_file_path, |
- os.path.join(original_flattened_dir, dest_filename)) |
+ if using_svn: |
+ svn_repo.ExportBaseVersionOfFile( |
+ modified_file_path, |
+ os.path.join(original_flattened_dir, dest_filename)) |
+ else: |
+ _GitExportBaseVersionOfFile( |
+ modified_file_path, |
+ os.path.join(original_flattened_dir, dest_filename)) |
# Run skdiff: compare original_flattened_dir against modified_flattened_dir |
RunCommand('%s %s %s %s' % (path_to_skdiff, original_flattened_dir, |