~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/weave.py

  • Committer: Robert Collins
  • Date: 2005-10-05 05:29:27 UTC
  • mfrom: (1393.1.51)
  • Revision ID: robertc@robertcollins.net-20051005052926-03d3a49e1dbcb670
mergeĀ fromĀ martin

Show diffs side-by-side

added added

removed removed

Lines of Context:
22
22
"""Weave - storage of related text file versions"""
23
23
 
24
24
 
25
 
# TODO: Perhaps have copy method for Weave instances?
26
 
 
27
25
# XXX: If we do weaves this way, will a merge still behave the same
28
26
# way if it's done in a different order?  That's a pretty desirable
29
27
# property.
59
57
# variant that is passed a pre-cooked version of the single basis
60
58
# version?
61
59
 
 
60
# TODO: Have a way to go back and insert a revision V1 that is a parent 
 
61
# of an already-stored revision V2.  This means some lines previously 
 
62
# counted as new in V2 will be discovered to have actually come from V1.  
 
63
# It is probably necessary to insert V1, then compute a whole new diff 
 
64
# from the mashed ancestors to V2.  This must be repeated for every 
 
65
# direct child of V1.  The deltas from V2 to its descendents won't change,
 
66
# although their location within the weave may change.  It may be possible
 
67
# to just adjust the location of those instructions rather than 
 
68
# re-weaving the whole thing.  This is expected to be a fairly rare
 
69
# operation, only used when inserting data that was previously a ghost.
 
70
 
 
71
 
62
72
 
63
73
 
64
74
import sha
176
186
        self._weave_name = weave_name
177
187
 
178
188
 
 
189
    def copy(self):
 
190
        """Return a deep copy of self.
 
191
        
 
192
        The copy can be modified without affecting the original weave."""
 
193
        other = Weave()
 
194
        other._weave = self._weave[:]
 
195
        other._parents = self._parents[:]
 
196
        other._sha1s = self._sha1s[:]
 
197
        other._names = self._names[:]
 
198
        other._name_map = self._name_map.copy()
 
199
        other._weave_name = self._weave_name
 
200
        return other
 
201
 
179
202
    def __eq__(self, other):
180
203
        if not isinstance(other, Weave):
181
204
            return False
205
228
                             (name, self._weave_name))
206
229
 
207
230
 
 
231
    def iter_names(self):
 
232
        """Yield a list of all names in this weave."""
 
233
        return iter(self._names)
 
234
 
208
235
    def idx_to_name(self, version):
209
236
        return self._names[version]
210
237
 
614
641
        If there is a chunk of the file where there's no diagreement,
615
642
        only one alternative is given.
616
643
        """
617
 
 
618
644
        # approach: find the included versions common to all the
619
645
        # merged versions
620
646
        raise NotImplementedError()
640
666
        If line1=line2, this is a pure insert; if newlines=[] this is a
641
667
        pure delete.  (Similar to difflib.)
642
668
        """
643
 
 
 
669
        raise NotImplementedError()
644
670
 
645
671
            
646
672
    def plan_merge(self, ver_a, ver_b):
740
766
                       state
741
767
 
742
768
                
743
 
 
744
 
 
745
 
 
 
769
    def join(self, other):
 
770
        """Integrate versions from other into this weave.
 
771
 
 
772
        The resulting weave contains all the history of both weaves; 
 
773
        any version you could retrieve from either self or other can be 
 
774
        retrieved from self after this call.
 
775
 
 
776
        It is illegal for the two weaves to contain different values 
 
777
        for any version.
 
778
        """
 
779
        if other.numversions() == 0:
 
780
            return          # nothing to update, easy
 
781
        # work through in index order to make sure we get all dependencies
 
782
        for other_idx, name in enumerate(other._names):
 
783
            # TODO: If all the parents of the other version are already 
 
784
            # present then we can avoid some work by just taking the delta
 
785
            # and adjusting the offsets.
 
786
            if self._check_version_consistent(other, other_idx, name):
 
787
                continue
 
788
            new_parents = self._imported_parents(other, other_idx)
 
789
            lines = other.get_lines(other_idx)
 
790
            sha1 = other._sha1s[other_idx]
 
791
            self.add(name, new_parents, lines, sha1)
 
792
 
 
793
 
 
794
    def _imported_parents(self, other, other_idx):
 
795
        """Return list of parents in self corresponding to indexes in other."""
 
796
        new_parents = []
 
797
        for parent_idx in other._parents[other_idx]:
 
798
            parent_name = other._names[parent_idx]
 
799
            if parent_name not in self._names:
 
800
                # should not be possible
 
801
                raise WeaveError("missing parent {%s} of {%s} in %r" 
 
802
                                 % (parent_name, other._name_map[other_idx], self))
 
803
            new_parents.append(self._name_map[parent_name])
 
804
        return new_parents
 
805
 
 
806
    def _check_version_consistent(self, other, other_idx, name):
 
807
        """Check if a version in consistent in this and other.
 
808
        
 
809
        If present & correct return True;
 
810
        if not present in self return False; 
 
811
        if inconsistent raise error."""
 
812
        this_idx = self._name_map.get(name, -1)
 
813
        if this_idx != -1:
 
814
            if self._sha1s[this_idx] != other._sha1s[other_idx]:
 
815
                raise WeaveError("inconsistent texts for version {%s} in %r and %r"
 
816
                                 % (name, self, other))
 
817
            elif set(self._parents[this_idx]) != set(other._parents[other_idx]):
 
818
                raise WeaveError("inconsistent parents for version {%s} in %r and %r"
 
819
                                 % (name, self, other))
 
820
            else:
 
821
                return True         # ok!
 
822
        else:
 
823
            return False
746
824
 
747
825
 
748
826
def weave_toc(w):