/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

Merge bzr.dev, fix minor conflict in cmd_revision_history().

Show diffs side-by-side

added added

removed removed

Lines of Context:
14
14
# along with this program; if not, write to the Free Software
15
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16
16
 
 
17
import time
 
18
 
17
19
from bzrlib.delta import compare_trees
18
20
from bzrlib.errors import BzrError
19
21
import bzrlib.errors as errors
29
31
# list, write them out directly, etc etc.
30
32
 
31
33
def internal_diff(old_filename, oldlines, new_filename, newlines, to_file,
32
 
                  allow_binary=False, sequence_matcher=None):
 
34
                  allow_binary=False, sequence_matcher=None,
 
35
                  path_encoding='utf8'):
33
36
    # FIXME: difflib is wrong if there is no trailing newline.
34
37
    # The syntax used by patch seems to be "\ No newline at
35
38
    # end of file" following the last diff line from that
53
56
    if sequence_matcher is None:
54
57
        sequence_matcher = bzrlib.patiencediff.PatienceSequenceMatcher
55
58
    ud = unified_diff(oldlines, newlines,
56
 
                      fromfile=old_filename+'\t', 
57
 
                      tofile=new_filename+'\t',
 
59
                      fromfile=old_filename.encode(path_encoding),
 
60
                      tofile=new_filename.encode(path_encoding),
58
61
                      sequencematcher=sequence_matcher)
59
62
 
60
63
    ud = list(ud)
110
113
        if not diff_opts:
111
114
            diff_opts = []
112
115
        diffcmd = ['diff',
113
 
                   '--label', old_filename+'\t',
 
116
                   '--label', old_filename,
114
117
                   oldtmpf.name,
115
 
                   '--label', new_filename+'\t',
 
118
                   '--label', new_filename,
116
119
                   newtmpf.name]
117
120
 
118
121
        # diff only allows one style to be specified; they don't override.
266
269
                     specific_files, external_diff_options, 
267
270
                     old_label='a/', new_label='b/' ):
268
271
 
269
 
    DEVNULL = '/dev/null'
270
 
    # Windows users, don't panic about this filename -- it is a
271
 
    # special signal to GNU patch that the file should be created or
272
 
    # deleted respectively.
 
272
    # GNU Patch uses the epoch date to detect files that are being added
 
273
    # or removed in a diff.
 
274
    EPOCH_DATE = '1970-01-01 00:00:00 +0000'
273
275
 
274
276
    # TODO: Generation of pseudo-diffs for added/deleted files could
275
277
    # be usefully made into a much faster special case.
290
292
    has_changes = 0
291
293
    for path, file_id, kind in delta.removed:
292
294
        has_changes = 1
293
 
        print >>to_file, '=== removed %s %r' % (kind, path)
294
 
        old_tree.inventory[file_id].diff(diff_file, old_label + path, old_tree,
295
 
                                         DEVNULL, None, None, to_file)
 
295
        print >>to_file, '=== removed %s %r' % (kind, path.encode('utf8'))
 
296
        old_name = '%s%s\t%s' % (old_label, path,
 
297
                                 _patch_header_date(old_tree, file_id, path))
 
298
        new_name = '%s%s\t%s' % (new_label, path, EPOCH_DATE)
 
299
        old_tree.inventory[file_id].diff(diff_file, old_name, old_tree,
 
300
                                         new_name, None, None, to_file)
296
301
    for path, file_id, kind in delta.added:
297
302
        has_changes = 1
298
 
        print >>to_file, '=== added %s %r' % (kind, path)
299
 
        new_tree.inventory[file_id].diff(diff_file, new_label + path, new_tree,
300
 
                                         DEVNULL, None, None, to_file, 
 
303
        print >>to_file, '=== added %s %r' % (kind, path.encode('utf8'))
 
304
        old_name = '%s%s\t%s' % (old_label, path, EPOCH_DATE)
 
305
        new_name = '%s%s\t%s' % (new_label, path,
 
306
                                 _patch_header_date(new_tree, file_id, path))
 
307
        new_tree.inventory[file_id].diff(diff_file, new_name, new_tree,
 
308
                                         old_name, None, None, to_file, 
301
309
                                         reverse=True)
302
310
    for (old_path, new_path, file_id, kind,
303
311
         text_modified, meta_modified) in delta.renamed:
304
312
        has_changes = 1
305
313
        prop_str = get_prop_change(meta_modified)
306
314
        print >>to_file, '=== renamed %s %r => %r%s' % (
307
 
                    kind, old_path, new_path, prop_str)
308
 
        _maybe_diff_file_or_symlink(old_label, old_path, old_tree, file_id,
309
 
                                    new_label, new_path, new_tree,
 
315
                    kind, old_path.encode('utf8'),
 
316
                    new_path.encode('utf8'), prop_str)
 
317
        old_name = '%s%s\t%s' % (old_label, old_path,
 
318
                                 _patch_header_date(old_tree, file_id,
 
319
                                                    old_path))
 
320
        new_name = '%s%s\t%s' % (new_label, new_path,
 
321
                                 _patch_header_date(new_tree, file_id,
 
322
                                                    new_path))
 
323
        _maybe_diff_file_or_symlink(old_name, old_tree, file_id,
 
324
                                    new_name, new_tree,
310
325
                                    text_modified, kind, to_file, diff_file)
311
326
    for path, file_id, kind, text_modified, meta_modified in delta.modified:
312
327
        has_changes = 1
313
328
        prop_str = get_prop_change(meta_modified)
314
 
        print >>to_file, '=== modified %s %r%s' % (kind, path, prop_str)
 
329
        print >>to_file, '=== modified %s %r%s' % (kind, path.encode('utf8'), prop_str)
 
330
        old_name = '%s%s\t%s' % (old_label, path,
 
331
                                 _patch_header_date(old_tree, file_id, path))
 
332
        new_name = '%s%s\t%s' % (new_label, path,
 
333
                                 _patch_header_date(new_tree, file_id, path))
315
334
        if text_modified:
316
 
            _maybe_diff_file_or_symlink(old_label, path, old_tree, file_id,
317
 
                                        new_label, path, new_tree,
 
335
            _maybe_diff_file_or_symlink(old_name, old_tree, file_id,
 
336
                                        new_name, new_tree,
318
337
                                        True, kind, to_file, diff_file)
319
338
 
320
339
    return has_changes
321
340
 
322
341
 
 
342
def _patch_header_date(tree, file_id, path):
 
343
    """Returns a timestamp suitable for use in a patch header."""
 
344
    tm = time.gmtime(tree.get_file_mtime(file_id, path))
 
345
    return time.strftime('%Y-%m-%d %H:%M:%S +0000', tm)
 
346
 
 
347
 
323
348
def _raise_if_doubly_unversioned(specific_files, old_tree, new_tree):
324
349
    """Complain if paths are not versioned in either tree."""
325
350
    if not specific_files:
357
382
        return  ""
358
383
 
359
384
 
360
 
def _maybe_diff_file_or_symlink(old_label, old_path, old_tree, file_id,
361
 
                                new_label, new_path, new_tree, text_modified,
 
385
def _maybe_diff_file_or_symlink(old_path, old_tree, file_id,
 
386
                                new_path, new_tree, text_modified,
362
387
                                kind, to_file, diff_file):
363
388
    if text_modified:
364
389
        new_entry = new_tree.inventory[file_id]
365
390
        old_tree.inventory[file_id].diff(diff_file,
366
 
                                         old_label + old_path, old_tree,
367
 
                                         new_label + new_path, new_entry, 
 
391
                                         old_path, old_tree,
 
392
                                         new_path, new_entry, 
368
393
                                         new_tree, to_file)