Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Git diff is complaining, "external diff died, stopping at ... " with my python diff program

Here's the beginning part of my diff.

#!/usr/bin/env python
import fileinput
import difflib
import subprocess
import sys

# for debugging
def info(type, value, info):
    import traceback
    traceback.print_exception(type, value, info)
    print
    pdb.pm()

sys.excepthook = info
import pdb
#end debugging

if len(sys.argv) == 8:
    # assume this was passed to git; we can of course do
    # some parsing to check if we got valid git style args
    args = [sys.argv[2], sys.argv[5]]
elif len(sys.argv) == 3:
    args = sys.argv[1:]
else:
    exit("Not a valid number of args (2 or 7) to this diff program")
print "Files: " + ' '.join(args)
for filename in args:
    filetype = subprocess.check_output(['file', filename])
    if filetype.find('text') == -1:
        args.insert(0, 'diff')
        print "A binary file was found: " + filename + ", deferring to diff"
        exit(subprocess.call(args))

When a binary (or otherwise non text) file is encountered, it attempts to fork diff to obtain whether the binary files differ or not. The goal is for this python diff program to be used as an external differ for git.

But I get this ghastly "external diff died, stopping at <file>" message once it hits the binary file.

How is git evaluating my program? How does it know it died? Isn't return value supposed to indicate the differing condition?

like image 869
Steven Lu Avatar asked Jun 19 '26 19:06

Steven Lu


1 Answers

There's no exit function in your code. How about replace exit to sys.exit?

#!/usr/bin/env python

import subprocess
import sys

if len(sys.argv) == 8:
    # assume this was passed to git; we can of course do
    # some parsing to check if we got valid git style args
    args = [sys.argv[2], sys.argv[5]]
elif len(sys.argv) == 3:
    args = sys.argv[1:]
else:
    print "Not a valid number of args (2 or 7) to this diff program"
    sys.exit(1)
print "Files: ", args
for filename in args:
    filetype = subprocess.check_output(['file', filename])
    if filetype.find('text') == -1:
        args.insert(0, 'diff')
        print "A binary file was found: " + filename + ", deferring to diff"
        #sys.stdout.flush()
        subprocess.call(args)
        sys.exit(0)

EDIT: git depend on external diff's exit status. diff exit with 0 only if there is no differce. So changed the code not to use diff's exit status.

PS: Without sys.stdout.flush(), diff output come before print output.

like image 178
falsetru Avatar answered Jun 22 '26 08:06

falsetru



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!