| #!/usr/bin/env python | 
 | # Copyright (c) 2012 The Chromium Authors. All rights reserved. | 
 | # Use of this source code is governed by a BSD-style license that can be | 
 | # found in the LICENSE file. | 
 |  | 
 | """ | 
 |   Invokes git diff [args...] and inserts file:line in front of each line of diff | 
 |   output where possible. | 
 |  | 
 |   This is useful from an IDE that allows you to double-click lines that begin | 
 |   with file:line to open and jump to that point in the file. | 
 |  | 
 | Synopsis: | 
 |   %prog [git diff args...] | 
 |  | 
 | Examples: | 
 |   %prog | 
 |   %prog HEAD | 
 | """ | 
 |  | 
 | import subprocess | 
 | import sys | 
 |  | 
 |  | 
 | def GitShell(args, ignore_return=False): | 
 |   """A shell invocation suitable for communicating with git. Returns | 
 |   output as list of lines, raises exception on error. | 
 |   """ | 
 |   job = subprocess.Popen(args, | 
 |                          shell=True, | 
 |                          stdout=subprocess.PIPE, | 
 |                          stderr=subprocess.STDOUT) | 
 |   (out, err) = job.communicate() | 
 |   if job.returncode != 0 and not ignore_return: | 
 |     print out | 
 |     raise Exception("Error %d running command %s" % ( | 
 |         job.returncode, args)) | 
 |   return out.split('\n') | 
 |  | 
 |  | 
 | def PrintGitDiff(extra_args): | 
 |   """Outputs git diff extra_args with file:line inserted into relevant lines.""" | 
 |   current_file = ''; | 
 |   line_num = 0; | 
 |   lines = GitShell('git diff %s' % ' '.join(extra_args)) | 
 |   for line in lines: | 
 |     # Pass-through lines: | 
 |     #  diff --git a/file.c b/file.c | 
 |     #  index 0e38c2d..8cd69ae 100644 | 
 |     #  --- a/file.c | 
 |     if (line.startswith('diff ') or | 
 |         line.startswith('index ') or | 
 |         line.startswith('--- ')): | 
 |       print line | 
 |       continue | 
 |  | 
 |     # Get the filename from the +++ line: | 
 |     #  +++ b/file.c | 
 |     if line.startswith('+++ '): | 
 |       # Filename might be /dev/null or a/file or b/file. | 
 |       # Skip the first two characters unless it starts with /. | 
 |       current_file = line[4:] if line[4] == '/' else line[6:] | 
 |       print line | 
 |       continue | 
 |  | 
 |     # Update line number from the @@ lines: | 
 |     #  @@ -41,9 +41,9 @@ def MyFunc(): | 
 |     #            ^^ | 
 |     if line.startswith('@@ '): | 
 |       _, old_nr, new_nr, _ = line.split(' ', 3) | 
 |       line_num = int(new_nr.split(',')[0]) | 
 |       print line | 
 |       continue | 
 |     print current_file + ':' + repr(line_num) + ':' + line | 
 |  | 
 |     # Increment line number for lines that start with ' ' or '+': | 
 |     #  @@ -41,4 +41,4 @@ def MyFunc(): | 
 |     #  file.c:41: // existing code | 
 |     #  file.c:42: // existing code | 
 |     #  file.c:43:-// deleted code | 
 |     #  file.c:43:-// deleted code | 
 |     #  file.c:43:+// inserted code | 
 |     #  file.c:44:+// inserted code | 
 |     if line.startswith(' ') or line.startswith('+'): | 
 |       line_num += 1 | 
 |  | 
 |  | 
 | def main(): | 
 |   PrintGitDiff(sys.argv[1:]) | 
 |  | 
 |  | 
 | if __name__ == '__main__': | 
 |   main() |