~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/diff.py

Merge bzr.dev

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
54
56
    if sequence_matcher is None:
55
57
        sequence_matcher = bzrlib.patiencediff.PatienceSequenceMatcher
56
58
    ud = unified_diff(oldlines, newlines,
57
 
                      fromfile=old_filename.encode(path_encoding)+'\t', 
58
 
                      tofile=new_filename.encode(path_encoding)+'\t',
 
59
                      fromfile=old_filename.encode(path_encoding),
 
60
                      tofile=new_filename.encode(path_encoding),
59
61
                      sequencematcher=sequence_matcher)
60
62
 
61
63
    ud = list(ud)
111
113
        if not diff_opts:
112
114
            diff_opts = []
113
115
        diffcmd = ['diff',
114
 
                   '--label', old_filename+'\t',
 
116
                   '--label', old_filename,
115
117
                   oldtmpf.name,
116
 
                   '--label', new_filename+'\t',
 
118
                   '--label', new_filename,
117
119
                   newtmpf.name]
118
120
 
119
121
        # diff only allows one style to be specified; they don't override.
267
269
                     specific_files, external_diff_options, 
268
270
                     old_label='a/', new_label='b/' ):
269
271
 
270
 
    DEVNULL = '/dev/null'
271
 
    # Windows users, don't panic about this filename -- it is a
272
 
    # special signal to GNU patch that the file should be created or
273
 
    # 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'
274
275
 
275
276
    # TODO: Generation of pseudo-diffs for added/deleted files could
276
277
    # be usefully made into a much faster special case.
292
293
    for path, file_id, kind in delta.removed:
293
294
        has_changes = 1
294
295
        print >>to_file, '=== removed %s %r' % (kind, path.encode('utf8'))
295
 
        old_tree.inventory[file_id].diff(diff_file, old_label + path, old_tree,
296
 
                                         DEVNULL, None, None, to_file)
 
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)
297
301
    for path, file_id, kind in delta.added:
298
302
        has_changes = 1
299
303
        print >>to_file, '=== added %s %r' % (kind, path.encode('utf8'))
300
 
        new_tree.inventory[file_id].diff(diff_file, new_label + path, new_tree,
301
 
                                         DEVNULL, None, None, to_file, 
 
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, 
302
309
                                         reverse=True)
303
310
    for (old_path, new_path, file_id, kind,
304
311
         text_modified, meta_modified) in delta.renamed:
307
314
        print >>to_file, '=== renamed %s %r => %r%s' % (
308
315
                    kind, old_path.encode('utf8'),
309
316
                    new_path.encode('utf8'), prop_str)
310
 
        _maybe_diff_file_or_symlink(old_label, old_path, old_tree, file_id,
311
 
                                    new_label, new_path, new_tree,
 
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,
312
325
                                    text_modified, kind, to_file, diff_file)
313
326
    for path, file_id, kind, text_modified, meta_modified in delta.modified:
314
327
        has_changes = 1
315
328
        prop_str = get_prop_change(meta_modified)
316
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))
317
334
        if text_modified:
318
 
            _maybe_diff_file_or_symlink(old_label, path, old_tree, file_id,
319
 
                                        new_label, path, new_tree,
 
335
            _maybe_diff_file_or_symlink(old_name, old_tree, file_id,
 
336
                                        new_name, new_tree,
320
337
                                        True, kind, to_file, diff_file)
321
338
 
322
339
    return has_changes
323
340
 
324
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
 
325
348
def _raise_if_doubly_unversioned(specific_files, old_tree, new_tree):
326
349
    """Complain if paths are not versioned in either tree."""
327
350
    if not specific_files:
359
382
        return  ""
360
383
 
361
384
 
362
 
def _maybe_diff_file_or_symlink(old_label, old_path, old_tree, file_id,
363
 
                                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,
364
387
                                kind, to_file, diff_file):
365
388
    if text_modified:
366
389
        new_entry = new_tree.inventory[file_id]
367
390
        old_tree.inventory[file_id].diff(diff_file,
368
 
                                         old_label + old_path, old_tree,
369
 
                                         new_label + new_path, new_entry, 
 
391
                                         old_path, old_tree,
 
392
                                         new_path, new_entry, 
370
393
                                         new_tree, to_file)