/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/tree.py

Most of the integration of dirstate and subtree

Show diffs side-by-side

added added

removed removed

Lines of Context:
166
166
        raise NotImplementedError("subclasses must implement kind")
167
167
 
168
168
    def get_reference_revision(self, entry, path=None):
169
 
        raise NotImplementedError("subclasses must implement "
170
 
                                  "get_reference_revision")
 
169
        raise NotImplementedError("Tree subclass %s must implement "
 
170
                                  "get_reference_revision"
 
171
            % self.__class__.__name__)
171
172
 
172
173
    def _comparison_data(self, entry, path):
173
174
        """Return a tuple of kind, executable, stat_value for a file.
634
635
            path in the specific_files list is not versioned in one of
635
636
            source, target or extra_trees.
636
637
        """
637
 
        lookup_trees = [self.source]
638
 
        if extra_trees:
639
 
             lookup_trees.extend(extra_trees)
640
 
        specific_file_ids = self.target.paths2ids(specific_files,
641
 
            lookup_trees, require_versioned=require_versioned)
642
 
        to_paths = {}
643
 
        from_entries_by_dir = list(self.source.inventory.iter_entries_by_dir(
644
 
            specific_file_ids=specific_file_ids))
645
 
        from_data = dict((e.file_id, (p, e)) for p, e in from_entries_by_dir)
646
 
        to_entries_by_dir = list(self.target.inventory.iter_entries_by_dir(
647
 
            specific_file_ids=specific_file_ids))
648
 
        num_entries = len(from_entries_by_dir) + len(to_entries_by_dir)
649
 
        entry_count = 0
650
 
        for to_path, to_entry in to_entries_by_dir:
651
 
            file_id = to_entry.file_id
652
 
            to_paths[file_id] = to_path
653
 
            entry_count += 1
654
 
            changed_content = False
655
 
            from_path, from_entry = from_data.get(file_id, (None, None))
656
 
            from_versioned = (from_entry is not None)
657
 
            if from_entry is not None:
658
 
                from_versioned = True
659
 
                from_name = from_entry.name
660
 
                from_parent = from_entry.parent_id
661
 
                from_kind, from_executable, from_stat = \
662
 
                    self.source._comparison_data(from_entry, from_path)
663
 
                entry_count += 1
664
 
            else:
665
 
                from_versioned = False
666
 
                from_kind = None
667
 
                from_parent = None
668
 
                from_name = None
669
 
                from_executable = None
670
 
            versioned = (from_versioned, True)
671
 
            to_kind, to_executable, to_stat = \
672
 
                self.target._comparison_data(to_entry, to_path)
673
 
            kind = (from_kind, to_kind)
674
 
            if kind[0] != kind[1]:
 
638
        # this must return a sequence rather than a list so that it can hold a
 
639
        # read-lock for the whole time.
 
640
        #
 
641
        # TODO: this really only needs to lock the trees not the branches, so
 
642
        # could do with lock_tree_read() -- mbp 20070227
 
643
        result = []
 
644
        self.source.lock_read()
 
645
        self.target.lock_read()
 
646
        try:
 
647
            lookup_trees = [self.source]
 
648
            if extra_trees:
 
649
                 lookup_trees.extend(extra_trees)
 
650
            specific_file_ids = self.target.paths2ids(specific_files,
 
651
                lookup_trees, require_versioned=require_versioned)
 
652
            to_paths = {}
 
653
            from_entries_by_dir = list(self.source.inventory.iter_entries_by_dir(
 
654
                specific_file_ids=specific_file_ids))
 
655
            from_data = dict((e.file_id, (p, e)) for p, e in from_entries_by_dir)
 
656
            to_entries_by_dir = list(self.target.inventory.iter_entries_by_dir(
 
657
                specific_file_ids=specific_file_ids))
 
658
            num_entries = len(from_entries_by_dir) + len(to_entries_by_dir)
 
659
            entry_count = 0
 
660
            for to_path, to_entry in to_entries_by_dir:
 
661
                file_id = to_entry.file_id
 
662
                to_paths[file_id] = to_path
 
663
                entry_count += 1
 
664
                changed_content = False
 
665
                from_path, from_entry = from_data.get(file_id, (None, None))
 
666
                from_versioned = (from_entry is not None)
 
667
                if from_entry is not None:
 
668
                    from_versioned = True
 
669
                    from_name = from_entry.name
 
670
                    from_parent = from_entry.parent_id
 
671
                    from_kind, from_executable, from_stat = \
 
672
                        self.source._comparison_data(from_entry, from_path)
 
673
                    entry_count += 1
 
674
                else:
 
675
                    from_versioned = False
 
676
                    from_kind = None
 
677
                    from_parent = None
 
678
                    from_name = None
 
679
                    from_executable = None
 
680
                versioned = (from_versioned, True)
 
681
                to_kind, to_executable, to_stat = \
 
682
                    self.target._comparison_data(to_entry, to_path)
 
683
                kind = (from_kind, to_kind)
 
684
                if kind[0] != kind[1]:
 
685
                    changed_content = True
 
686
                elif from_kind == 'file':
 
687
                    from_size = self.source._file_size(from_entry, from_stat)
 
688
                    to_size = self.target._file_size(to_entry, to_stat)
 
689
                    if from_size != to_size:
 
690
                        changed_content = True
 
691
                    elif (self.source.get_file_sha1(file_id, from_path, from_stat) !=
 
692
                        self.target.get_file_sha1(file_id, to_path, to_stat)):
 
693
                        changed_content = True
 
694
                elif from_kind == 'symlink':
 
695
                    if (self.source.get_symlink_target(file_id) != 
 
696
                        self.target.get_symlink_target(file_id)):
 
697
                        changed_content = True
 
698
                elif from_kind == 'tree-reference':
 
699
                    if (self.source.get_reference_revision(from_entry, from_path)
 
700
                        != self.target.get_reference_revision(to_entry, to_path)):
 
701
                        changed_content = True 
 
702
                parent = (from_parent, to_entry.parent_id)
 
703
                name = (from_name, to_entry.name)
 
704
                executable = (from_executable, to_executable)
 
705
                if pb is not None:
 
706
                    pb.update('comparing files', entry_count, num_entries)
 
707
                if (changed_content is not False or versioned[0] != versioned[1] 
 
708
                    or parent[0] != parent[1] or name[0] != name[1] or 
 
709
                    executable[0] != executable[1] or include_unchanged):
 
710
                    result.append((file_id, to_path, changed_content, versioned, parent,
 
711
                           name, kind, executable))
 
712
            def get_to_path(from_entry):
 
713
                if from_entry.parent_id is None:
 
714
                    to_path = ''
 
715
                else:
 
716
                    if from_entry.parent_id not in to_paths:
 
717
                        get_to_path(self.source.inventory[from_entry.parent_id])
 
718
                    to_path = osutils.pathjoin(to_paths[from_entry.parent_id],
 
719
                                               from_entry.name)
 
720
                to_paths[from_entry.file_id] = to_path
 
721
                return to_path
 
722
 
 
723
            for path, from_entry in from_entries_by_dir:
 
724
                file_id = from_entry.file_id
 
725
                if file_id in to_paths:
 
726
                    continue
 
727
                to_path = get_to_path(from_entry)
 
728
                entry_count += 1
 
729
                if pb is not None:
 
730
                    pb.update('comparing files', entry_count, num_entries)
 
731
                versioned = (True, False)
 
732
                parent = (from_entry.parent_id, None)
 
733
                name = (from_entry.name, None)
 
734
                from_kind, from_executable, stat_value = \
 
735
                    self.source._comparison_data(from_entry, path)
 
736
                kind = (from_kind, None)
 
737
                executable = (from_executable, None)
675
738
                changed_content = True
676
 
            elif from_kind == 'file':
677
 
                from_size = self.source._file_size(from_entry, from_stat)
678
 
                to_size = self.target._file_size(to_entry, to_stat)
679
 
                if from_size != to_size:
680
 
                    changed_content = True
681
 
                elif (self.source.get_file_sha1(file_id, from_path, from_stat) !=
682
 
                    self.target.get_file_sha1(file_id, to_path, to_stat)):
683
 
                    changed_content = True
684
 
            elif from_kind == 'symlink':
685
 
                if (self.source.get_symlink_target(file_id) != 
686
 
                    self.target.get_symlink_target(file_id)):
687
 
                    changed_content = True
688
 
            elif from_kind == 'tree-reference':
689
 
                if (self.source.get_reference_revision(from_entry, from_path)
690
 
                    != self.target.get_reference_revision(to_entry, to_path)):
691
 
                    changed_content = True 
692
 
            parent = (from_parent, to_entry.parent_id)
693
 
            name = (from_name, to_entry.name)
694
 
            executable = (from_executable, to_executable)
695
 
            if pb is not None:
696
 
                pb.update('comparing files', entry_count, num_entries)
697
 
            if (changed_content is not False or versioned[0] != versioned[1] 
698
 
                or parent[0] != parent[1] or name[0] != name[1] or 
699
 
                executable[0] != executable[1] or include_unchanged):
700
 
                yield (file_id, to_path, changed_content, versioned, parent,
701
 
                       name, kind, executable)
702
 
 
703
 
        def get_to_path(from_entry):
704
 
            if from_entry.parent_id is None:
705
 
                to_path = ''
706
 
            else:
707
 
                if from_entry.parent_id not in to_paths:
708
 
                    get_to_path(self.source.inventory[from_entry.parent_id])
709
 
                to_path = osutils.pathjoin(to_paths[from_entry.parent_id],
710
 
                                           from_entry.name)
711
 
            to_paths[from_entry.file_id] = to_path
712
 
            return to_path
713
 
 
714
 
        for path, from_entry in from_entries_by_dir:
715
 
            file_id = from_entry.file_id
716
 
            if file_id in to_paths:
717
 
                continue
718
 
            to_path = get_to_path(from_entry)
719
 
            entry_count += 1
720
 
            if pb is not None:
721
 
                pb.update('comparing files', entry_count, num_entries)
722
 
            versioned = (True, False)
723
 
            parent = (from_entry.parent_id, None)
724
 
            name = (from_entry.name, None)
725
 
            from_kind, from_executable, stat_value = \
726
 
                self.source._comparison_data(from_entry, path)
727
 
            kind = (from_kind, None)
728
 
            executable = (from_executable, None)
729
 
            changed_content = True
730
 
            # the parent's path is necessarily known at this point.
731
 
            yield(file_id, to_path, changed_content, versioned, parent,
732
 
                  name, kind, executable)
 
739
                # the parent's path is necessarily known at this point.
 
740
                result.append((file_id, to_path, changed_content, versioned, parent,
 
741
                      name, kind, executable))
 
742
        finally:
 
743
            self.source.unlock()
 
744
            self.target.unlock()
 
745
        return result
 
746
 
733
747
 
734
748
 
735
749
# This was deprecated before 0.12, but did not have an official warning