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

  • Committer: Martin Pool
  • Date: 2007-10-08 07:29:57 UTC
  • mfrom: (2894 +trunk)
  • mto: This revision was merged to the branch mainline in revision 2895.
  • Revision ID: mbp@sourcefrog.net-20071008072957-uhm1gl1mqcsdc377
merge trunk

Show diffs side-by-side

added added

removed removed

Lines of Context:
432
432
                   self.parent_id,
433
433
                   self.revision))
434
434
 
435
 
    def snapshot(self, revision, path, previous_entries,
436
 
                 work_tree, commit_builder):
437
 
        """Make a snapshot of this entry which may or may not have changed.
438
 
        
439
 
        This means that all its fields are populated, that it has its
440
 
        text stored in the text store or weave.
441
 
 
442
 
        :return: True if anything was recorded
443
 
        """
444
 
        # cannot be unchanged unless there is only one parent file rev.
445
 
        self._read_tree_state(path, work_tree)
446
 
        if len(previous_entries) == 1:
447
 
            parent_ie = previous_entries.values()[0]
448
 
            if self._unchanged(parent_ie):
449
 
                self.revision = parent_ie.revision
450
 
                return False
451
 
        self.revision = revision
452
 
        return self._snapshot_text(previous_entries, work_tree, commit_builder)
453
 
 
454
 
    def _snapshot_text(self, file_parents, work_tree, commit_builder): 
455
 
        """Record the 'text' of this entry, whatever form that takes.
456
 
 
457
 
        :return: True if anything was recorded
458
 
        """
459
 
        raise NotImplementedError(self._snapshot_text)
460
 
 
461
435
    def __eq__(self, other):
462
436
        if not isinstance(other, InventoryEntry):
463
437
            return NotImplemented
582
556
        """See InventoryEntry._put_on_disk."""
583
557
        os.mkdir(fullpath)
584
558
 
585
 
    def _snapshot_text(self, file_parents, work_tree, commit_builder):
586
 
        """See InventoryEntry._snapshot_text."""
587
 
        commit_builder.modified_directory(self.file_id, file_parents)
588
 
        return True
589
 
 
590
559
 
591
560
class InventoryFile(InventoryEntry):
592
561
    """A file in an inventory."""
716
685
    def _forget_tree_state(self):
717
686
        self.text_sha1 = None
718
687
 
719
 
    def snapshot(self, revision, path, previous_entries,
720
 
                 work_tree, commit_builder):
721
 
        """See InventoryEntry.snapshot."""
722
 
        # Note: We use a custom implementation of this method for files
723
 
        # because it's a performance critical part of commit.
724
 
 
725
 
        # If this is the initial commit for this file, we know the sha is
726
 
        # coming later so skip calculating it now (in _read_tree_state())
727
 
        if len(previous_entries) == 0:
728
 
            self.executable = work_tree.is_executable(self.file_id, path=path)
729
 
        else:
730
 
            self._read_tree_state(path, work_tree)
731
 
 
732
 
        # If nothing is changed from the sole parent, there's nothing to do
733
 
        if len(previous_entries) == 1:
734
 
            parent_ie = previous_entries.values()[0]
735
 
            if self._unchanged(parent_ie):
736
 
                self.revision = parent_ie.revision
737
 
                return False
738
 
 
739
 
        # Add the file to the repository
740
 
        self.revision = revision
741
 
        def get_content_byte_lines():
742
 
            return work_tree.get_file(self.file_id, path).readlines()
743
 
        self.text_sha1, self.text_size = commit_builder.modified_file_text(
744
 
            self.file_id, previous_entries, get_content_byte_lines,
745
 
            self.text_sha1, self.text_size)
746
 
        return True
747
 
 
748
688
    def _unchanged(self, previous_ie):
749
689
        """See InventoryEntry._unchanged."""
750
690
        compatible = super(InventoryFile, self)._unchanged(previous_ie)
845
785
            compatible = False
846
786
        return compatible
847
787
 
848
 
    def _snapshot_text(self, file_parents, work_tree, commit_builder):
849
 
        """See InventoryEntry._snapshot_text."""
850
 
        commit_builder.modified_link(
851
 
            self.file_id, file_parents, self.symlink_target)
852
 
        return True
853
 
 
854
788
 
855
789
class TreeReference(InventoryEntry):
856
790
    
866
800
        return TreeReference(self.file_id, self.name, self.parent_id,
867
801
                             self.revision, self.reference_revision)
868
802
 
869
 
    def _snapshot_text(self, file_parents, work_tree, commit_builder):
870
 
        commit_builder.modified_reference(self.file_id, file_parents)
871
 
        return True
872
 
 
873
803
    def _read_tree_state(self, path, work_tree):
874
804
        """Populate fields in the inventory entry from the given tree.
875
805
        """
946
876
            self._byid = {}
947
877
        self.revision_id = revision_id
948
878
 
 
879
    def __repr__(self):
 
880
        return "<Inventory object at %x, contents=%r>" % (id(self), self._byid)
 
881
 
 
882
    def apply_delta(self, delta):
 
883
        """Apply a delta to this inventory.
 
884
 
 
885
        :param delta: A list of changes to apply. After all the changes are
 
886
            applied the final inventory must be internally consistent, but it
 
887
            is ok to supply changes which, if only half-applied would have an
 
888
            invalid result - such as supplying two changes which rename two
 
889
            files, 'A' and 'B' with each other : [('A', 'B', 'A-id', a_entry),
 
890
            ('B', 'A', 'B-id', b_entry)].
 
891
 
 
892
            Each change is a tuple, of the form (old_path, new_path, file_id,
 
893
            new_entry).
 
894
            
 
895
            When new_path is None, the change indicates the removal of an entry
 
896
            from the inventory and new_entry will be ignored (using None is
 
897
            appropriate). If new_path is not None, then new_entry must be an
 
898
            InventoryEntry instance, which will be incorporated into the
 
899
            inventory (and replace any existing entry with the same file id).
 
900
            
 
901
            When old_path is None, the change indicates the addition of
 
902
            a new entry to the inventory.
 
903
            
 
904
            When neither new_path nor old_path are None, the change is a
 
905
            modification to an entry, such as a rename, reparent, kind change
 
906
            etc. 
 
907
 
 
908
            The children attribute of new_entry is ignored. This is because
 
909
            this method preserves children automatically across alterations to
 
910
            the parent of the children, and cases where the parent id of a
 
911
            child is changing require the child to be passed in as a separate
 
912
            change regardless. E.g. in the recursive deletion of a directory -
 
913
            the directory's children must be included in the delta, or the
 
914
            final inventory will be invalid.
 
915
        """
 
916
        children = {}
 
917
        # Remove all affected items which were in the original inventory,
 
918
        # starting with the longest paths, thus ensuring parents are examined
 
919
        # after their children, which means that everything we examine has no
 
920
        # modified children remaining by the time we examine it.
 
921
        for old_path, file_id in sorted(((op, f) for op, np, f, e in delta
 
922
                                        if op is not None), reverse=True):
 
923
            if file_id not in self:
 
924
                # adds come later
 
925
                continue
 
926
            # Preserve unaltered children of file_id for later reinsertion.
 
927
            children[file_id] = getattr(self[file_id], 'children', {})
 
928
            # Remove file_id and the unaltered children. If file_id is not
 
929
            # being deleted it will be reinserted back later.
 
930
            self.remove_recursive_id(file_id)
 
931
        # Insert all affected which should be in the new inventory, reattaching
 
932
        # their children if they had any. This is done from shortest path to
 
933
        # longest, ensuring that items which were modified and whose parents in
 
934
        # the resulting inventory were also modified, are inserted after their
 
935
        # parents.
 
936
        for new_path, new_entry in sorted((np, e) for op, np, f, e in
 
937
                                          delta if np is not None):
 
938
            if new_entry.kind == 'directory':
 
939
                new_entry.children = children.get(new_entry.file_id, {})
 
940
            self.add(new_entry)
 
941
 
949
942
    def _set_root(self, ie):
950
943
        self.root = ie
951
944
        self._byid = {self.root.file_id: self.root}