~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/diff.py

(mbp) merge bzr.dev to 0.8, prepare for release

Show diffs side-by-side

added added

removed removed

Lines of Context:
18
18
from bzrlib.errors import BzrError
19
19
import bzrlib.errors as errors
20
20
from bzrlib.symbol_versioning import *
 
21
from bzrlib.textfile import check_text_lines
21
22
from bzrlib.trace import mutter
22
23
 
23
24
# TODO: Rather than building a changeset object, we should probably
24
25
# invoke callbacks on an object.  That object can either accumulate a
25
26
# list, write them out directly, etc etc.
26
27
 
27
 
def internal_diff(old_filename, oldlines, new_filename, newlines, to_file):
 
28
def internal_diff(old_filename, oldlines, new_filename, newlines, to_file,
 
29
                  allow_binary=False):
28
30
    import difflib
29
31
    
30
32
    # FIXME: difflib is wrong if there is no trailing newline.
42
44
    # both sequences are empty.
43
45
    if not oldlines and not newlines:
44
46
        return
 
47
    
 
48
    if allow_binary is False:
 
49
        check_text_lines(oldlines)
 
50
        check_text_lines(newlines)
45
51
 
46
52
    ud = difflib.unified_diff(oldlines, newlines,
47
53
                              fromfile=old_filename+'\t', 
184
190
 
185
191
 
186
192
def diff_cmd_helper(tree, specific_files, external_diff_options, 
187
 
                    old_revision_spec=None, new_revision_spec=None):
 
193
                    old_revision_spec=None, new_revision_spec=None,
 
194
                    old_label='a/', new_label='b/'):
188
195
    """Helper for cmd_diff.
189
196
 
190
197
   tree 
223
230
        new_tree = spec_tree(new_revision_spec)
224
231
 
225
232
    return show_diff_trees(old_tree, new_tree, sys.stdout, specific_files,
226
 
                           external_diff_options)
 
233
                           external_diff_options,
 
234
                           old_label=old_label, new_label=new_label)
227
235
 
228
236
 
229
237
def show_diff_trees(old_tree, new_tree, to_file, specific_files=None,
230
 
                    external_diff_options=None):
 
238
                    external_diff_options=None,
 
239
                    old_label='a/', new_label='b/'):
231
240
    """Show in text form the changes from one tree to another.
232
241
 
233
242
    to_files
241
250
        new_tree.lock_read()
242
251
        try:
243
252
            return _show_diff_trees(old_tree, new_tree, to_file,
244
 
                                    specific_files, external_diff_options)
 
253
                                    specific_files, external_diff_options,
 
254
                                    old_label=old_label, new_label=new_label)
245
255
        finally:
246
256
            new_tree.unlock()
247
257
    finally:
249
259
 
250
260
 
251
261
def _show_diff_trees(old_tree, new_tree, to_file,
252
 
                     specific_files, external_diff_options):
253
 
 
254
 
    # TODO: Options to control putting on a prefix or suffix, perhaps
255
 
    # as a format string?
256
 
    old_label = 'a/'
257
 
    new_label = 'b/'
 
262
                     specific_files, external_diff_options, 
 
263
                     old_label='a/', new_label='b/' ):
258
264
 
259
265
    DEVNULL = '/dev/null'
260
266
    # Windows users, don't panic about this filename -- it is a
280
286
    has_changes = 0
281
287
    for path, file_id, kind in delta.removed:
282
288
        has_changes = 1
283
 
        print >>to_file, '=== removed %s %r' % (kind, old_label + path)
 
289
        print >>to_file, '=== removed %s %r' % (kind, path)
284
290
        old_tree.inventory[file_id].diff(diff_file, old_label + path, old_tree,
285
291
                                         DEVNULL, None, None, to_file)
286
292
    for path, file_id, kind in delta.added:
287
293
        has_changes = 1
288
 
        print >>to_file, '=== added %s %r' % (kind, new_label + path)
 
294
        print >>to_file, '=== added %s %r' % (kind, path)
289
295
        new_tree.inventory[file_id].diff(diff_file, new_label + path, new_tree,
290
296
                                         DEVNULL, None, None, to_file, 
291
297
                                         reverse=True)
294
300
        has_changes = 1
295
301
        prop_str = get_prop_change(meta_modified)
296
302
        print >>to_file, '=== renamed %s %r => %r%s' % (
297
 
                    kind, old_label + old_path, new_label + new_path, prop_str)
 
303
                    kind, old_path, new_path, prop_str)
298
304
        _maybe_diff_file_or_symlink(old_label, old_path, old_tree, file_id,
299
305
                                    new_label, new_path, new_tree,
300
306
                                    text_modified, kind, to_file, diff_file)
301
307
    for path, file_id, kind, text_modified, meta_modified in delta.modified:
302
308
        has_changes = 1
303
309
        prop_str = get_prop_change(meta_modified)
304
 
        print >>to_file, '=== modified %s %r%s' % (kind, old_label + path,
305
 
                    prop_str)
 
310
        print >>to_file, '=== modified %s %r%s' % (kind, path, prop_str)
306
311
        if text_modified:
307
312
            _maybe_diff_file_or_symlink(old_label, path, old_tree, file_id,
308
313
                                        new_label, path, new_tree,
322
327
        raise errors.PathsNotVersionedError(sorted(unversioned))
323
328
    
324
329
 
 
330
def _raise_if_nonexistent(paths, old_tree, new_tree):
 
331
    """Complain if paths are not in either inventory or tree.
 
332
 
 
333
    It's OK with the files exist in either tree's inventory, or 
 
334
    if they exist in the tree but are not versioned.
 
335
    
 
336
    This can be used by operations such as bzr status that can accept
 
337
    unknown or ignored files.
 
338
    """
 
339
    mutter("check paths: %r", paths)
 
340
    if not paths:
 
341
        return
 
342
    s = old_tree.filter_unversioned_files(paths)
 
343
    s = new_tree.filter_unversioned_files(s)
 
344
    s = [path for path in s if not new_tree.has_filename(path)]
 
345
    if s:
 
346
        raise errors.PathsDoNotExist(sorted(s))
 
347
 
 
348
 
325
349
def get_prop_change(meta_modified):
326
350
    if meta_modified:
327
351
        return " (properties changed)"