92
"""Set the env var LANG=C"""
93
os.environ['LANG'] = 'C'
96
def _spawn_external_diff(diffcmd, capture_errors=True):
97
"""Spawn the externall diff process, and return the child handle.
99
:param diffcmd: The command list to spawn
100
:param capture_errors: Capture stderr as well as setting LANG=C.
101
This lets us read and understand the output of diff, and respond
103
:return: A Popen object.
106
preexec_fn = _set_lang_C
107
stderr = subprocess.PIPE
113
pipe = subprocess.Popen(diffcmd,
114
stdin=subprocess.PIPE,
115
stdout=subprocess.PIPE,
117
preexec_fn=preexec_fn)
119
if e.errno == errno.ENOENT:
120
raise errors.NoDiff(str(e))
91
126
def external_diff(old_filename, oldlines, new_filename, newlines, to_file,
93
128
"""Display a diff by calling out to the external diff program."""
148
183
diffcmd.extend(diff_opts)
151
pipe = subprocess.Popen(diffcmd,
152
stdin=subprocess.PIPE,
153
stdout=subprocess.PIPE)
155
if e.errno == errno.ENOENT:
156
raise errors.NoDiff(str(e))
160
first_line = pipe.stdout.readline()
161
to_file.write(first_line)
162
bzrlib.osutils.pumpfile(pipe.stdout, to_file)
185
pipe = _spawn_external_diff(diffcmd, capture_errors=True)
186
out,err = pipe.communicate()
189
# internal_diff() adds a trailing newline, add one here for consistency
166
192
# 'diff' gives retcode == 2 for all sorts of errors
167
193
# one of those is 'Binary files differ'.
168
194
# Bad options could also be the problem.
169
195
# 'Binary files' is not a real error, so we suppress that error
198
# Since we got here, we want to make sure to give an i18n error
199
pipe = _spawn_external_diff(diffcmd, capture_errors=False)
200
out, err = pipe.communicate()
202
# Write out the new i18n diff response
203
to_file.write(out+'\n')
204
if pipe.returncode != 2:
205
raise BzrError('external diff failed with exit code 2'
206
' when run with LANG=C, but not when run'
207
' natively: %r' % (diffcmd,))
209
first_line = lang_c_out.split('\n', 1)[0]
170
210
m = re.match('^binary files.*differ$', first_line, re.I)
172
212
raise BzrError('external diff failed with exit code 2;'
173
213
' command: %r' % (diffcmd,))
174
elif rc not in (0, 1):
215
# Binary files differ, just return
218
# If we got to here, we haven't written out the output of diff
175
222
# returns 1 if files differ; that's OK
177
224
msg = 'signal %d' % (-rc)