/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to bzrlib/diff.py

  • Committer: Aaron Bentley
  • Date: 2006-05-20 17:51:13 UTC
  • mfrom: (1718 +trunk)
  • mto: This revision was merged to the branch mainline in revision 1727.
  • Revision ID: aaron.bentley@utoronto.ca-20060520175113-4549e0023f9210bf
Merge from bzr.dev

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# -*- coding: UTF-8 -*-
 
1
# Copyright (C) 2004, 2005, 2006 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
16
16
 
17
17
from bzrlib.delta import compare_trees
18
18
from bzrlib.errors import BzrError
 
19
import bzrlib.errors as errors
19
20
from bzrlib.symbol_versioning import *
 
21
from bzrlib.textfile import check_text_lines
20
22
from bzrlib.trace import mutter
21
23
 
22
24
# TODO: Rather than building a changeset object, we should probably
24
26
# list, write them out directly, etc etc.
25
27
 
26
28
def internal_diff(old_filename, oldlines, new_filename, newlines, to_file,
27
 
        sequence_matcher=None):
 
29
                  allow_binary=False, sequence_matcher=None):
28
30
    from bzrlib.cdv.cdvdifflib import unified_diff
29
31
    from bzrlib.cdv.cdvdifflib import SequenceMatcher
30
32
    
43
45
    # both sequences are empty.
44
46
    if not oldlines and not newlines:
45
47
        return
 
48
    
 
49
    if allow_binary is False:
 
50
        check_text_lines(oldlines)
 
51
        check_text_lines(newlines)
46
52
 
47
53
    if sequence_matcher is None:
48
54
        sequence_matcher = SequenceMatcher
188
194
 
189
195
 
190
196
def diff_cmd_helper(tree, specific_files, external_diff_options, 
191
 
                    old_revision_spec=None, new_revision_spec=None):
 
197
                    old_revision_spec=None, new_revision_spec=None,
 
198
                    old_label='a/', new_label='b/'):
192
199
    """Helper for cmd_diff.
193
200
 
194
201
   tree 
227
234
        new_tree = spec_tree(new_revision_spec)
228
235
 
229
236
    return show_diff_trees(old_tree, new_tree, sys.stdout, specific_files,
230
 
                           external_diff_options)
 
237
                           external_diff_options,
 
238
                           old_label=old_label, new_label=new_label)
231
239
 
232
240
 
233
241
def show_diff_trees(old_tree, new_tree, to_file, specific_files=None,
234
 
                    external_diff_options=None):
 
242
                    external_diff_options=None,
 
243
                    old_label='a/', new_label='b/'):
235
244
    """Show in text form the changes from one tree to another.
236
245
 
237
246
    to_files
240
249
    external_diff_options
241
250
        If set, use an external GNU diff and pass these options.
242
251
    """
243
 
 
244
252
    old_tree.lock_read()
245
253
    try:
246
254
        new_tree.lock_read()
247
255
        try:
248
256
            return _show_diff_trees(old_tree, new_tree, to_file,
249
 
                                    specific_files, external_diff_options)
 
257
                                    specific_files, external_diff_options,
 
258
                                    old_label=old_label, new_label=new_label)
250
259
        finally:
251
260
            new_tree.unlock()
252
261
    finally:
254
263
 
255
264
 
256
265
def _show_diff_trees(old_tree, new_tree, to_file,
257
 
                     specific_files, external_diff_options):
258
 
 
259
 
    # TODO: Options to control putting on a prefix or suffix, perhaps
260
 
    # as a format string?
261
 
    old_label = 'a/'
262
 
    new_label = 'b/'
 
266
                     specific_files, external_diff_options, 
 
267
                     old_label='a/', new_label='b/' ):
263
268
 
264
269
    DEVNULL = '/dev/null'
265
270
    # Windows users, don't panic about this filename -- it is a
269
274
    # TODO: Generation of pseudo-diffs for added/deleted files could
270
275
    # be usefully made into a much faster special case.
271
276
 
 
277
    _raise_if_doubly_unversioned(specific_files, old_tree, new_tree)
 
278
 
272
279
    if external_diff_options:
273
280
        assert isinstance(external_diff_options, basestring)
274
281
        opts = external_diff_options.split()
277
284
    else:
278
285
        diff_file = internal_diff
279
286
    
280
 
 
281
287
    delta = compare_trees(old_tree, new_tree, want_unchanged=False,
282
288
                          specific_files=specific_files)
283
289
 
284
290
    has_changes = 0
285
291
    for path, file_id, kind in delta.removed:
286
292
        has_changes = 1
287
 
        print >>to_file, '=== removed %s %r' % (kind, old_label + path)
 
293
        print >>to_file, '=== removed %s %r' % (kind, path)
288
294
        old_tree.inventory[file_id].diff(diff_file, old_label + path, old_tree,
289
295
                                         DEVNULL, None, None, to_file)
290
296
    for path, file_id, kind in delta.added:
291
297
        has_changes = 1
292
 
        print >>to_file, '=== added %s %r' % (kind, new_label + path)
 
298
        print >>to_file, '=== added %s %r' % (kind, path)
293
299
        new_tree.inventory[file_id].diff(diff_file, new_label + path, new_tree,
294
300
                                         DEVNULL, None, None, to_file, 
295
301
                                         reverse=True)
298
304
        has_changes = 1
299
305
        prop_str = get_prop_change(meta_modified)
300
306
        print >>to_file, '=== renamed %s %r => %r%s' % (
301
 
                    kind, old_label + old_path, new_label + new_path, prop_str)
 
307
                    kind, old_path, new_path, prop_str)
302
308
        _maybe_diff_file_or_symlink(old_label, old_path, old_tree, file_id,
303
309
                                    new_label, new_path, new_tree,
304
310
                                    text_modified, kind, to_file, diff_file)
305
311
    for path, file_id, kind, text_modified, meta_modified in delta.modified:
306
312
        has_changes = 1
307
313
        prop_str = get_prop_change(meta_modified)
308
 
        print >>to_file, '=== modified %s %r%s' % (kind, old_label + path,
309
 
                    prop_str)
 
314
        print >>to_file, '=== modified %s %r%s' % (kind, path, prop_str)
310
315
        if text_modified:
311
316
            _maybe_diff_file_or_symlink(old_label, path, old_tree, file_id,
312
317
                                        new_label, path, new_tree,
313
318
                                        True, kind, to_file, diff_file)
 
319
 
314
320
    return has_changes
315
 
    
 
321
 
 
322
 
 
323
def _raise_if_doubly_unversioned(specific_files, old_tree, new_tree):
 
324
    """Complain if paths are not versioned in either tree."""
 
325
    if not specific_files:
 
326
        return
 
327
    old_unversioned = old_tree.filter_unversioned_files(specific_files)
 
328
    new_unversioned = new_tree.filter_unversioned_files(specific_files)
 
329
    unversioned = old_unversioned.intersection(new_unversioned)
 
330
    if unversioned:
 
331
        raise errors.PathsNotVersionedError(sorted(unversioned))
 
332
    
 
333
 
 
334
def _raise_if_nonexistent(paths, old_tree, new_tree):
 
335
    """Complain if paths are not in either inventory or tree.
 
336
 
 
337
    It's OK with the files exist in either tree's inventory, or 
 
338
    if they exist in the tree but are not versioned.
 
339
    
 
340
    This can be used by operations such as bzr status that can accept
 
341
    unknown or ignored files.
 
342
    """
 
343
    mutter("check paths: %r", paths)
 
344
    if not paths:
 
345
        return
 
346
    s = old_tree.filter_unversioned_files(paths)
 
347
    s = new_tree.filter_unversioned_files(s)
 
348
    s = [path for path in s if not new_tree.has_filename(path)]
 
349
    if s:
 
350
        raise errors.PathsDoNotExist(sorted(s))
 
351
 
316
352
 
317
353
def get_prop_change(meta_modified):
318
354
    if meta_modified: