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
17
19
from bzrlib.delta import compare_trees
18
20
from bzrlib.errors import BzrError
19
21
import bzrlib.errors as errors
20
from bzrlib.patiencediff import SequenceMatcher, unified_diff
22
from bzrlib.patiencediff import unified_diff
23
import bzrlib.patiencediff
21
24
from bzrlib.symbol_versioning import *
22
25
from bzrlib.textfile import check_text_lines
23
26
from bzrlib.trace import mutter
25
29
# TODO: Rather than building a changeset object, we should probably
26
30
# invoke callbacks on an object. That object can either accumulate a
27
31
# list, write them out directly, etc etc.
29
33
def internal_diff(old_filename, oldlines, new_filename, newlines, to_file,
30
allow_binary=False, sequence_matcher=None):
34
allow_binary=False, sequence_matcher=None,
35
path_encoding='utf8'):
31
36
# FIXME: difflib is wrong if there is no trailing newline.
32
37
# The syntax used by patch seems to be "\ No newline at
33
38
# end of file" following the last diff line from that
289
293
for path, file_id, kind in delta.removed:
291
print >>to_file, '=== removed %s %r' % (kind, path)
292
old_tree.inventory[file_id].diff(diff_file, old_label + path, old_tree,
293
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)
294
301
for path, file_id, kind in delta.added:
296
print >>to_file, '=== added %s %r' % (kind, path)
297
new_tree.inventory[file_id].diff(diff_file, new_label + path, new_tree,
298
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,
300
310
for (old_path, new_path, file_id, kind,
301
311
text_modified, meta_modified) in delta.renamed:
303
313
prop_str = get_prop_change(meta_modified)
304
314
print >>to_file, '=== renamed %s %r => %r%s' % (
305
kind, old_path, new_path, prop_str)
306
_maybe_diff_file_or_symlink(old_label, old_path, old_tree, file_id,
307
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,
320
new_name = '%s%s\t%s' % (new_label, new_path,
321
_patch_header_date(new_tree, file_id,
323
_maybe_diff_file_or_symlink(old_name, old_tree, file_id,
308
325
text_modified, kind, to_file, diff_file)
309
326
for path, file_id, kind, text_modified, meta_modified in delta.modified:
311
328
prop_str = get_prop_change(meta_modified)
312
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))
313
334
if text_modified:
314
_maybe_diff_file_or_symlink(old_label, path, old_tree, file_id,
315
new_label, path, new_tree,
335
_maybe_diff_file_or_symlink(old_name, old_tree, file_id,
316
337
True, kind, to_file, diff_file)
318
339
return has_changes
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)
321
348
def _raise_if_doubly_unversioned(specific_files, old_tree, new_tree):
322
349
"""Complain if paths are not versioned in either tree."""
323
350
if not specific_files:
358
def _maybe_diff_file_or_symlink(old_label, old_path, old_tree, file_id,
359
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,
360
387
kind, to_file, diff_file):
361
388
if text_modified:
362
389
new_entry = new_tree.inventory[file_id]
363
390
old_tree.inventory[file_id].diff(diff_file,
364
old_label + old_path, old_tree,
365
new_label + new_path, new_entry,
366
393
new_tree, to_file)