599
618
# TODO: this really only needs to lock the trees not the branches, so
600
619
# could do with lock_tree_read() -- mbp 20070227
602
self.source.lock_read()
603
self.target.lock_read()
605
lookup_trees = [self.source]
607
lookup_trees.extend(extra_trees)
608
specific_file_ids = self.target.paths2ids(specific_files,
609
lookup_trees, require_versioned=require_versioned)
611
from_entries_by_dir = list(self.source.inventory.iter_entries_by_dir(
612
specific_file_ids=specific_file_ids))
613
from_data = dict((e.file_id, (p, e)) for p, e in from_entries_by_dir)
614
to_entries_by_dir = list(self.target.inventory.iter_entries_by_dir(
615
specific_file_ids=specific_file_ids))
616
num_entries = len(from_entries_by_dir) + len(to_entries_by_dir)
618
for to_path, to_entry in to_entries_by_dir:
619
file_id = to_entry.file_id
620
to_paths[file_id] = to_path
622
changed_content = False
623
from_path, from_entry = from_data.get(file_id, (None, None))
624
from_versioned = (from_entry is not None)
625
if from_entry is not None:
626
from_versioned = True
627
from_name = from_entry.name
628
from_parent = from_entry.parent_id
629
from_kind, from_executable, from_stat = \
630
self.source._comparison_data(from_entry, from_path)
633
from_versioned = False
637
from_executable = None
638
versioned = (from_versioned, True)
621
## self.source.lock_read()
622
## self.target.lock_read()
624
lookup_trees = [self.source]
626
lookup_trees.extend(extra_trees)
627
specific_file_ids = self.target.paths2ids(specific_files,
628
lookup_trees, require_versioned=require_versioned)
630
all_unversioned = sorted([(p.split('/'), p) for p in self.target.extras()
631
if not specific_files or
632
osutils.is_inside_any(specific_files, p)])
633
all_unversioned = deque(all_unversioned)
635
all_unversioned = deque()
637
from_entries_by_dir = list(self.source.inventory.iter_entries_by_dir(
638
specific_file_ids=specific_file_ids))
639
from_data = dict((e.file_id, (p, e)) for p, e in from_entries_by_dir)
640
to_entries_by_dir = list(self.target.inventory.iter_entries_by_dir(
641
specific_file_ids=specific_file_ids))
642
num_entries = len(from_entries_by_dir) + len(to_entries_by_dir)
644
# the unversioned path lookup only occurs on real trees - where there
645
# can be extras. So the fake_entry is solely used to look up
646
# executable it values when execute is not supported.
647
fake_entry = InventoryFile('unused', 'unused', 'unused')
648
for to_path, to_entry in to_entries_by_dir:
649
while all_unversioned and all_unversioned[0][0] < to_path.split('/'):
650
unversioned_path = all_unversioned.popleft()
639
651
to_kind, to_executable, to_stat = \
640
self.target._comparison_data(to_entry, to_path)
641
kind = (from_kind, to_kind)
642
if kind[0] != kind[1]:
643
changed_content = True
644
elif from_kind == 'file':
645
from_size = self.source._file_size(from_entry, from_stat)
646
to_size = self.target._file_size(to_entry, to_stat)
647
if from_size != to_size:
648
changed_content = True
649
elif (self.source.get_file_sha1(file_id, from_path, from_stat) !=
650
self.target.get_file_sha1(file_id, to_path, to_stat)):
651
changed_content = True
652
elif from_kind == 'symlink':
653
if (self.source.get_symlink_target(file_id) !=
654
self.target.get_symlink_target(file_id)):
655
changed_content = True
652
self.target._comparison_data(fake_entry, unversioned_path[1])
653
yield (None, unversioned_path[1], True, (False, False),
655
(None, unversioned_path[0][-1]),
657
(None, to_executable))
658
file_id = to_entry.file_id
659
to_paths[file_id] = to_path
661
changed_content = False
662
from_path, from_entry = from_data.get(file_id, (None, None))
663
from_versioned = (from_entry is not None)
664
if from_entry is not None:
665
from_versioned = True
666
from_name = from_entry.name
667
from_parent = from_entry.parent_id
668
from_kind, from_executable, from_stat = \
669
self.source._comparison_data(from_entry, from_path)
672
from_versioned = False
676
from_executable = None
677
versioned = (from_versioned, True)
678
to_kind, to_executable, to_stat = \
679
self.target._comparison_data(to_entry, to_path)
680
kind = (from_kind, to_kind)
681
if kind[0] != kind[1]:
682
changed_content = True
683
elif from_kind == 'file':
684
from_size = self.source._file_size(from_entry, from_stat)
685
to_size = self.target._file_size(to_entry, to_stat)
686
if from_size != to_size:
687
changed_content = True
688
elif (self.source.get_file_sha1(file_id, from_path, from_stat) !=
689
self.target.get_file_sha1(file_id, to_path, to_stat)):
690
changed_content = True
691
elif from_kind == 'symlink':
692
if (self.source.get_symlink_target(file_id) !=
693
self.target.get_symlink_target(file_id)):
694
changed_content = True
656
695
elif from_kind == 'tree-reference':
657
696
if (self.source.get_reference_revision(from_entry, from_path)
658
697
!= self.target.get_reference_revision(to_entry, to_path)):
659
698
changed_content = True
660
parent = (from_parent, to_entry.parent_id)
661
name = (from_name, to_entry.name)
662
executable = (from_executable, to_executable)
664
pb.update('comparing files', entry_count, num_entries)
665
if (changed_content is not False or versioned[0] != versioned[1]
666
or parent[0] != parent[1] or name[0] != name[1] or
667
executable[0] != executable[1] or include_unchanged):
668
result.append((file_id, to_path, changed_content, versioned, parent,
669
name, kind, executable))
670
def get_to_path(from_entry):
671
if from_entry.parent_id is None:
674
if from_entry.parent_id not in to_paths:
675
get_to_path(self.source.inventory[from_entry.parent_id])
676
to_path = osutils.pathjoin(to_paths[from_entry.parent_id],
678
to_paths[from_entry.file_id] = to_path
681
for path, from_entry in from_entries_by_dir:
682
file_id = from_entry.file_id
683
if file_id in to_paths:
685
to_path = get_to_path(from_entry)
688
pb.update('comparing files', entry_count, num_entries)
689
versioned = (True, False)
690
parent = (from_entry.parent_id, None)
691
name = (from_entry.name, None)
692
from_kind, from_executable, stat_value = \
693
self.source._comparison_data(from_entry, path)
694
kind = (from_kind, None)
695
executable = (from_executable, None)
696
changed_content = True
697
# the parent's path is necessarily known at this point.
698
result.append((file_id, to_path, changed_content, versioned, parent,
699
name, kind, executable))
699
parent = (from_parent, to_entry.parent_id)
700
name = (from_name, to_entry.name)
701
executable = (from_executable, to_executable)
703
pb.update('comparing files', entry_count, num_entries)
704
if (changed_content is not False or versioned[0] != versioned[1]
705
or parent[0] != parent[1] or name[0] != name[1] or
706
executable[0] != executable[1] or include_unchanged):
707
yield (file_id, to_path, changed_content, versioned, parent,
708
name, kind, executable)
709
while all_unversioned:
710
# yield any trailing unversioned paths
711
unversioned_path = all_unversioned.popleft()
712
to_kind, to_executable, to_stat = \
713
self.target._comparison_data(fake_entry, unversioned_path[1])
714
yield (None, unversioned_path[1], True, (False, False),
716
(None, unversioned_path[0][-1]),
718
(None, to_executable))
720
def get_to_path(from_entry):
721
if from_entry.parent_id is None:
724
if from_entry.parent_id not in to_paths:
725
get_to_path(self.source.inventory[from_entry.parent_id])
726
to_path = osutils.pathjoin(to_paths[from_entry.parent_id],
728
to_paths[from_entry.file_id] = to_path
731
for path, from_entry in from_entries_by_dir:
732
file_id = from_entry.file_id
733
if file_id in to_paths:
735
to_path = get_to_path(from_entry)
738
pb.update('comparing files', entry_count, num_entries)
739
versioned = (True, False)
740
parent = (from_entry.parent_id, None)
741
name = (from_entry.name, None)
742
from_kind, from_executable, stat_value = \
743
self.source._comparison_data(from_entry, path)
744
kind = (from_kind, None)
745
executable = (from_executable, None)
746
changed_content = True
747
# the parent's path is necessarily known at this point.
748
yield(file_id, to_path, changed_content, versioned, parent,
749
name, kind, executable)
706
752
# This was deprecated before 0.12, but did not have an official warning