480
def _patch_header_date(tree, file_id, path):
480
def _patch_header_date(tree, path):
481
481
"""Returns a timestamp suitable for use in a patch header."""
483
483
mtime = tree.get_file_mtime(path)
526
526
diff_tree.to_file, diff_tree.path_encoding)
529
def _diff_many(differs, file_id, old_path, new_path, old_kind, new_kind):
529
def _diff_many(differs, old_path, new_path, old_kind, new_kind):
530
530
for file_differ in differs:
531
result = file_differ.diff(file_id, old_path, new_path, old_kind,
531
result = file_differ.diff(old_path, new_path, old_kind, new_kind)
533
532
if result is not DiffPath.CANNOT_DIFF:
553
552
def from_diff_tree(klass, diff_tree):
554
553
return klass(diff_tree.differs)
556
def diff(self, file_id, old_path, new_path, old_kind, new_kind):
555
def diff(self, old_path, new_path, old_kind, new_kind):
557
556
"""Perform comparison
559
:param file_id: The file_id of the file to compare
560
558
:param old_path: Path of the file in the old tree
561
559
:param new_path: Path of the file in the new tree
562
560
:param old_kind: Old file-kind of the file
565
563
if None in (old_kind, new_kind):
566
564
return DiffPath.CANNOT_DIFF
567
result = DiffPath._diff_many(self.differs, file_id, old_path,
568
new_path, old_kind, None)
565
result = DiffPath._diff_many(
566
self.differs, old_path, new_path, old_kind, None)
569
567
if result is DiffPath.CANNOT_DIFF:
571
return DiffPath._diff_many(self.differs, file_id, old_path, new_path,
569
return DiffPath._diff_many(
570
self.differs, old_path, new_path, None, new_kind)
575
573
class DiffDirectory(DiffPath):
577
def diff(self, file_id, old_path, new_path, old_kind, new_kind):
575
def diff(self, old_path, new_path, old_kind, new_kind):
578
576
"""Perform comparison between two directories. (dummy)
590
588
class DiffSymlink(DiffPath):
592
def diff(self, file_id, old_path, new_path, old_kind, new_kind):
590
def diff(self, old_path, new_path, old_kind, new_kind):
593
591
"""Perform comparison between two symlinks
595
:param file_id: The file_id of the file to compare
596
593
:param old_path: Path of the file in the old tree
597
594
:param new_path: Path of the file in the new tree
598
595
:param old_kind: Old file-kind of the file
644
641
self.path_encoding = path_encoding
645
642
self.context_lines = context_lines
647
def diff(self, file_id, old_path, new_path, old_kind, new_kind):
644
def diff(self, old_path, new_path, old_kind, new_kind):
648
645
"""Compare two files in unified diff format
650
:param file_id: The file_id of the file to compare
651
647
:param old_path: Path of the file in the old tree
652
648
:param new_path: Path of the file in the new tree
653
649
:param old_kind: Old file-kind of the file
656
652
if 'file' not in (old_kind, new_kind):
657
653
return self.CANNOT_DIFF
658
from_file_id = to_file_id = file_id
659
654
if old_kind == 'file':
660
old_date = _patch_header_date(self.old_tree, file_id, old_path)
655
old_date = _patch_header_date(self.old_tree, old_path)
661
656
elif old_kind is None:
662
657
old_date = self.EPOCH_DATE
665
659
return self.CANNOT_DIFF
666
660
if new_kind == 'file':
667
new_date = _patch_header_date(self.new_tree, file_id, new_path)
661
new_date = _patch_header_date(self.new_tree, new_path)
668
662
elif new_kind is None:
669
663
new_date = self.EPOCH_DATE
672
665
return self.CANNOT_DIFF
673
666
from_label = '%s%s\t%s' % (self.old_label, old_path,
675
668
to_label = '%s%s\t%s' % (self.new_label, new_path,
677
return self.diff_text(old_path, new_path, from_label, to_label,
678
from_file_id, to_file_id)
670
return self.diff_text(old_path, new_path, from_label, to_label)
680
def diff_text(self, from_path, to_path, from_label, to_label,
681
from_file_id=None, to_file_id=None):
672
def diff_text(self, from_path, to_path, from_label, to_label):
682
673
"""Diff the content of given files in two trees
684
675
:param from_path: The path in the from tree. If None,
686
677
:param to_path: The path in the to tree. This may refer
687
678
to a different file from from_path. If None,
688
679
the file is not present in the to tree.
689
:param from_file_id: The id of the file in the from tree or None if
691
:param to_file_id: The id of the file in the to tree or None if
694
def _get_text(tree, file_id, path):
697
return tree.get_file_lines(path)
681
def _get_text(tree, path):
685
return tree.get_file_lines(path)
686
except errors.NoSuchFile:
699
from_text = _get_text(self.old_tree, from_file_id, from_path)
700
to_text = _get_text(self.new_tree, to_file_id, to_path)
689
from_text = _get_text(self.old_tree, from_path)
690
to_text = _get_text(self.new_tree, to_path)
701
691
self.text_differ(from_label, from_text, to_label, to_text,
702
692
self.to_file, path_encoding=self.path_encoding,
703
693
context_lines=self.context_lines)
804
794
return osutils.pathjoin(self._root, prefix, relpath_tmp)
806
796
def _write_file(self, relpath, tree, prefix, force_temp=False,
807
allow_write=False, file_id=None):
808
798
if not force_temp and isinstance(tree, WorkingTree):
809
799
full_path = tree.abspath(relpath)
810
800
if self._is_safepath(full_path):
838
828
def _prepare_files(self, old_path, new_path, force_temp=False,
839
allow_write_new=False, file_id=None):
840
old_disk_path = self._write_file(old_path, self.old_tree, 'old',
841
force_temp, file_id=file_id)
842
new_disk_path = self._write_file(new_path, self.new_tree, 'new',
843
force_temp, file_id=file_id,
844
allow_write=allow_write_new)
829
allow_write_new=False):
830
old_disk_path = self._write_file(
831
old_path, self.old_tree, 'old', force_temp)
832
new_disk_path = self._write_file(
833
new_path, self.new_tree, 'new', force_temp,
834
allow_write=allow_write_new)
845
835
return old_disk_path, new_disk_path
847
837
def finish(self):
852
842
mutter("The temporary directory \"%s\" was not "
853
843
"cleanly removed: %s." % (self._root, e))
855
def diff(self, file_id, old_path, new_path, old_kind, new_kind):
845
def diff(self, old_path, new_path, old_kind, new_kind):
856
846
if (old_kind, new_kind) != ('file', 'file'):
857
847
return DiffPath.CANNOT_DIFF
858
848
(old_disk_path, new_disk_path) = self._prepare_files(
859
old_path, new_path, file_id=file_id)
860
850
self._execute(old_disk_path, new_disk_path)
862
def edit_file(self, old_path, new_path, file_id=None):
852
def edit_file(self, old_path, new_path):
863
853
"""Use this tool to edit a file.
865
855
A temporary copy will be edited, and the new contents will be
868
:param file_id: The id of the file to edit.
869
858
:return: The new contents of the file.
871
860
old_abs_path, new_abs_path = self._prepare_files(
872
old_path, new_path, allow_write_new=True, force_temp=True,
861
old_path, new_path, allow_write_new=True, force_temp=True)
874
862
command = self._get_command(old_abs_path, new_abs_path)
875
863
subprocess.call(command, cwd=self._root)
876
864
with open(new_abs_path, 'rb') as new_file:
1028
1016
self.to_file.write(b"=== modified %s '%s'%s\n" % (kind[0].encode('ascii'),
1029
1017
newpath_encoded, prop_str))
1030
1018
if changed_content:
1031
self._diff(oldpath, newpath, kind[0], kind[1], file_id=file_id)
1019
self._diff(oldpath, newpath, kind[0], kind[1])
1032
1020
has_changes = 1
1034
1022
has_changes = 1
1035
1023
return has_changes
1037
def diff(self, file_id, old_path, new_path):
1025
def diff(self, old_path, new_path):
1038
1026
"""Perform a diff of a single file
1040
:param file_id: file-id of the file
1041
1028
:param old_path: The path of the file in the old tree
1042
1029
:param new_path: The path of the file in the new tree
1049
1036
new_kind = None
1051
1038
new_kind = self.new_tree.kind(new_path)
1052
self._diff(old_path, new_path, old_kind, new_kind, file_id=file_id)
1039
self._diff(old_path, new_path, old_kind, new_kind)
1054
def _diff(self, old_path, new_path, old_kind, new_kind, file_id):
1055
result = DiffPath._diff_many(self.differs, file_id, old_path,
1056
new_path, old_kind, new_kind)
1041
def _diff(self, old_path, new_path, old_kind, new_kind):
1042
result = DiffPath._diff_many(
1043
self.differs, old_path, new_path, old_kind, new_kind)
1057
1044
if result is DiffPath.CANNOT_DIFF:
1058
1045
error_path = new_path
1059
1046
if error_path is None: