~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/diff.py

  • Committer: Patch Queue Manager
  • Date: 2014-09-22 19:42:30 UTC
  • mfrom: (6597.2.1 bzr)
  • Revision ID: pqm@pqm.ubuntu.com-20140922194230-y32j0sq621bxhp7c
(richard-wilbur) Split diff format option parser into a separate function,
 update to include all format options for GNU diff v3.2,
 and test parser.  Fixes lp:1370435 (Richard Wilbur)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005-2011 Canonical Ltd.
 
1
# Copyright (C) 2005-2014 Canonical Ltd.
2
2
#
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
119
119
 
120
120
 
121
121
def _spawn_external_diff(diffcmd, capture_errors=True):
122
 
    """Spawn the externall diff process, and return the child handle.
 
122
    """Spawn the external diff process, and return the child handle.
123
123
 
124
124
    :param diffcmd: The command list to spawn
125
125
    :param capture_errors: Capture stderr as well as setting LANG=C
154
154
 
155
155
    return pipe
156
156
 
 
157
# diff style options as of GNU diff v3.2
 
158
style_option_list = ['-c', '-C', '--context',
 
159
                     '-e', '--ed',
 
160
                     '-f', '--forward-ed',
 
161
                     '-q', '--brief',
 
162
                     '--normal',
 
163
                     '-n', '--rcs',
 
164
                     '-u', '-U', '--unified',
 
165
                     '-y', '--side-by-side',
 
166
                     '-D', '--ifdef']
 
167
 
 
168
def default_style_unified(diff_opts):
 
169
    """Default to unified diff style if alternative not specified in diff_opts.
 
170
 
 
171
        diff only allows one style to be specified; they don't override.
 
172
        Note that some of these take optargs, and the optargs can be
 
173
        directly appended to the options.
 
174
        This is only an approximate parser; it doesn't properly understand
 
175
        the grammar.
 
176
 
 
177
    :param diff_opts: List of options for external (GNU) diff.
 
178
    :return: List of options with default style=='unified'.
 
179
    """
 
180
    for s in style_option_list:
 
181
        for j in diff_opts:
 
182
            if j.startswith(s):
 
183
                break
 
184
        else:
 
185
            continue
 
186
        break
 
187
    else:
 
188
        diff_opts.append('-u')
 
189
    return diff_opts
 
190
 
157
191
 
158
192
def external_diff(old_filename, oldlines, new_filename, newlines, to_file,
159
193
                  diff_opts):
195
229
                   '--binary',
196
230
                  ]
197
231
 
198
 
        # diff only allows one style to be specified; they don't override.
199
 
        # note that some of these take optargs, and the optargs can be
200
 
        # directly appended to the options.
201
 
        # this is only an approximate parser; it doesn't properly understand
202
 
        # the grammar.
203
 
        for s in ['-c', '-u', '-C', '-U',
204
 
                  '-e', '--ed',
205
 
                  '-q', '--brief',
206
 
                  '--normal',
207
 
                  '-n', '--rcs',
208
 
                  '-y', '--side-by-side',
209
 
                  '-D', '--ifdef']:
210
 
            for j in diff_opts:
211
 
                if j.startswith(s):
212
 
                    break
213
 
            else:
214
 
                continue
215
 
            break
216
 
        else:
217
 
            diffcmd.append('-u')
 
232
        diff_opts = default_style_unified(diff_opts)
218
233
 
219
234
        if diff_opts:
220
235
            diffcmd.extend(diff_opts)
265
280
                msg = 'exit code %d' % rc
266
281
 
267
282
            raise errors.BzrError('external diff failed with %s; command: %r'
268
 
                                  % (rc, diffcmd))
 
283
                                  % (msg, diffcmd))
269
284
 
270
285
 
271
286
    finally:
282
297
                        old_abspath, e)
283
298
        try:
284
299
            os.remove(new_abspath)
285
 
        except OSError:
 
300
        except OSError, e:
286
301
            if e.errno not in (errno.ENOENT,):
287
302
                warning('Failed to delete temporary file: %s %s',
288
303
                        new_abspath, e)