~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/diff.py

  • Committer: John Arbash Meinel
  • Date: 2006-07-31 19:14:19 UTC
  • mto: (1900.2.1 bzr.merge.54651)
  • mto: This revision was merged to the branch mainline in revision 1903.
  • Revision ID: john@arbash-meinel.com-20060731191419-41f78a5c1a394c17
Always buffer the output of diff, so we can check if retcode==2 is because of Binary files

Show diffs side-by-side

added added

removed removed

Lines of Context:
16
16
 
17
17
import errno
18
18
import os
 
19
import re
19
20
import subprocess
20
21
import sys
21
22
import tempfile
90
91
def external_diff(old_filename, oldlines, new_filename, newlines, to_file,
91
92
                  diff_opts):
92
93
    """Display a diff by calling out to the external diff program."""
93
 
    fileno_func = getattr(to_file, 'fileno', None)
94
 
    if fileno_func is not None:
95
 
        fileno = fileno_func()
96
 
        # WORKAROUND: jam 20060731 python2.4 subprocess.py will 
97
 
        #       close too many file descriptors if you pass stdout=sys.stdout
98
 
        #       so if we are about to pass stdout, just pass None
99
 
        if fileno == 1:
100
 
            out_file = None
101
 
        else:
102
 
            out_file = to_file
103
 
        have_fileno = True
104
 
    else:
105
 
        out_file = subprocess.PIPE
106
 
        have_fileno = False
107
 
    
108
94
    # make sure our own output is properly ordered before the diff
109
95
    to_file.flush()
110
96
 
164
150
        try:
165
151
            pipe = subprocess.Popen(diffcmd,
166
152
                                    stdin=subprocess.PIPE,
167
 
                                    stdout=out_file)
 
153
                                    stdout=subprocess.PIPE)
168
154
        except OSError, e:
169
155
            if e.errno == errno.ENOENT:
170
156
                raise errors.NoDiff(str(e))
171
157
            raise
172
158
        pipe.stdin.close()
173
159
 
174
 
        if not have_fileno:
175
 
            bzrlib.osutils.pumpfile(pipe.stdout, to_file)
 
160
        first_line = pipe.stdout.readline()
 
161
        to_file.write(first_line)
 
162
        bzrlib.osutils.pumpfile(pipe.stdout, to_file)
176
163
        rc = pipe.wait()
177
164
        
178
 
        # TODO: jam 20060731 'diff' returns exit code '2' if binary 
179
 
        #       files differ. But it also returns '2' if a file you
180
 
        #       are comparing doesn't exist, etc.
181
 
        #       'info diff' says:
182
 
        #         "An exit status of 0 means no differences were found, 
183
 
        #         1 means some differences were found, and 2 means trouble."
184
 
        #       If we assume we do things correctly, we can assume '2' means
185
 
        #       'Binary files .* differ'
186
 
        #       Alternatively, we could read the output of diff, and look
187
 
        #       for the "Binary files .* differ" line, but that would mean
188
 
        #       we always need to buffer the diff output.
189
 
        if rc not in (0, 1, 2):
 
165
        if rc == 2:
 
166
            # 'diff' gives retcode == 2 for all sorts of errors
 
167
            # one of those is 'Binary files differ'.
 
168
            # Bad options could also be the problem.
 
169
            # 'Binary files' is not a real error, so we suppress that error
 
170
            m = re.match('^binary files.*differ$', first_line, re.I)
 
171
            if not m:
 
172
                raise BzrError('external diff failed with exit code 2;'
 
173
                               ' command: %r' % (diffcmd,))
 
174
        elif rc not in (0, 1):
190
175
            # returns 1 if files differ; that's OK
191
176
            if rc < 0:
192
177
                msg = 'signal %d' % (-rc)