~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/diff.py

merge bzr.dev.revno.1905

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
 
    if hasattr(to_file, 'fileno'):
94
 
        out_file = to_file
95
 
        have_fileno = True
96
 
    else:
97
 
        out_file = subprocess.PIPE
98
 
        have_fileno = False
99
 
    
100
94
    # make sure our own output is properly ordered before the diff
101
95
    to_file.flush()
102
96
 
156
150
        try:
157
151
            pipe = subprocess.Popen(diffcmd,
158
152
                                    stdin=subprocess.PIPE,
159
 
                                    stdout=out_file)
 
153
                                    stdout=subprocess.PIPE)
160
154
        except OSError, e:
161
155
            if e.errno == errno.ENOENT:
162
156
                raise errors.NoDiff(str(e))
163
157
            raise
164
158
        pipe.stdin.close()
165
159
 
166
 
        if not have_fileno:
167
 
            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)
168
163
        rc = pipe.wait()
169
164
        
170
 
        if rc != 0 and rc != 1:
 
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):
171
175
            # returns 1 if files differ; that's OK
172
176
            if rc < 0:
173
177
                msg = 'signal %d' % (-rc)
174
178
            else:
175
179
                msg = 'exit code %d' % rc
176
180
                
177
 
            raise BzrError('external diff failed with %s; command: %r' % (rc, diffcmd))
 
181
            raise BzrError('external diff failed with %s; command: %r' 
 
182
                           % (rc, diffcmd))
 
183
 
 
184
        # internal_diff() adds a trailing newline, add one here for consistency
 
185
        to_file.write('\n')
 
186
 
178
187
    finally:
179
188
        oldtmpf.close()                 # and delete
180
189
        newtmpf.close()