~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/weave.py

First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.

Show diffs side-by-side

added added

removed removed

Lines of Context:
86
86
        WeaveRevisionNotPresent,
87
87
        )
88
88
import bzrlib.errors as errors
89
 
from bzrlib.osutils import sha_strings, split_lines
 
89
from bzrlib.osutils import dirname, sha_strings, split_lines
90
90
import bzrlib.patiencediff
 
91
from bzrlib.revision import NULL_REVISION
91
92
from bzrlib.symbol_versioning import *
92
93
from bzrlib.trace import mutter
93
94
from bzrlib.tsort import topo_sort
95
96
    AbsentContentFactory,
96
97
    adapter_registry,
97
98
    ContentFactory,
98
 
    InterVersionedFile,
99
99
    VersionedFile,
100
100
    )
101
101
from bzrlib.weavefile import _read_weave_v5, write_weave_v5
119
119
 
120
120
    def get_bytes_as(self, storage_kind):
121
121
        if storage_kind == 'fulltext':
122
 
            return self._weave.get_text(self.key[0])
 
122
            return self._weave.get_text(self.key[-1])
123
123
        else:
124
124
            raise UnavailableRepresentation(self.key, storage_kind, 'fulltext')
125
125
 
307
307
        :return: An iterator of ContentFactory objects, each of which is only
308
308
            valid until the iterator is advanced.
309
309
        """
 
310
        versions = [version[-1] for version in versions]
310
311
        if ordering == 'topological':
311
312
            parents = self.get_parent_map(versions)
312
313
            new_versions = topo_sort(parents)
322
323
        """See VersionedFile.get_parent_map."""
323
324
        result = {}
324
325
        for version_id in version_ids:
325
 
            try:
326
 
                result[version_id] = tuple(
327
 
                    map(self._idx_to_name, self._parents[self._lookup(version_id)]))
328
 
            except RevisionNotPresent:
329
 
                pass
 
326
            if version_id == NULL_REVISION:
 
327
                parents = ()
 
328
            else:
 
329
                try:
 
330
                    parents = tuple(
 
331
                        map(self._idx_to_name,
 
332
                            self._parents[self._lookup(version_id)]))
 
333
                except RevisionNotPresent:
 
334
                    continue
 
335
            result[version_id] = parents
330
336
        return result
331
337
 
332
338
    def get_parents_with_ghosts(self, version_id):
834
840
        # no lines outside of insertion blocks, that deletions are
835
841
        # properly paired, etc.
836
842
 
837
 
    def _join(self, other, pb, msg, version_ids, ignore_missing):
838
 
        """Worker routine for join()."""
839
 
        if not other.versions():
840
 
            return          # nothing to update, easy
841
 
 
842
 
        if not version_ids:
843
 
            # versions is never none, InterWeave checks this.
844
 
            return 0
845
 
 
846
 
        # two loops so that we do not change ourselves before verifying it
847
 
        # will be ok
848
 
        # work through in index order to make sure we get all dependencies
849
 
        names_to_join = []
850
 
        processed = 0
851
 
        # get the selected versions only that are in other.versions.
852
 
        version_ids = set(other.versions()).intersection(set(version_ids))
853
 
        # pull in the referenced graph.
854
 
        version_ids = other.get_ancestry(version_ids)
855
 
        pending_parents = other.get_parent_map(version_ids)
856
 
        pending_graph = pending_parents.items()
857
 
        if len(pending_graph) != len(version_ids):
858
 
            raise RevisionNotPresent(
859
 
                set(version_ids) - set(pending_parents.keys()), self)
860
 
        for name in topo_sort(pending_graph):
861
 
            other_idx = other._name_map[name]
862
 
            # returns True if we have it, False if we need it.
863
 
            if not self._check_version_consistent(other, other_idx, name):
864
 
                names_to_join.append((other_idx, name))
865
 
            processed += 1
866
 
 
867
 
        if pb and not msg:
868
 
            msg = 'weave join'
869
 
 
870
 
        merged = 0
871
 
        time0 = time.time()
872
 
        for other_idx, name in names_to_join:
873
 
            # TODO: If all the parents of the other version are already
874
 
            # present then we can avoid some work by just taking the delta
875
 
            # and adjusting the offsets.
876
 
            new_parents = self._imported_parents(other, other_idx)
877
 
            sha1 = other._sha1s[other_idx]
878
 
 
879
 
            merged += 1
880
 
 
881
 
            if pb:
882
 
                pb.update(msg, merged, len(names_to_join))
883
 
           
884
 
            lines = other.get_lines(other_idx)
885
 
            self._add(name, lines, new_parents, sha1)
886
 
 
887
 
        mutter("merged = %d, processed = %d, file_id=%s; deltat=%d"%(
888
 
                merged, processed, self._weave_name, time.time()-time0))
889
 
 
890
843
    def _imported_parents(self, other, other_idx):
891
844
        """Return list of parents in self corresponding to indexes in other."""
892
845
        new_parents = []
989
942
        sio = StringIO()
990
943
        write_weave_v5(self, sio)
991
944
        sio.seek(0)
992
 
        self._transport.put_file(self._weave_name + WeaveFile.WEAVE_SUFFIX,
993
 
                                 sio,
994
 
                                 self._filemode)
 
945
        bytes = sio.getvalue()
 
946
        path = self._weave_name + WeaveFile.WEAVE_SUFFIX
 
947
        try:
 
948
            self._transport.put_bytes(path, bytes, self._filemode)
 
949
        except errors.NoSuchFile:
 
950
            self._transport.mkdir(dirname(path))
 
951
            self._transport.put_bytes(path, bytes, self._filemode)
995
952
 
996
953
    @staticmethod
997
954
    def get_suffixes():
1272
1229
if __name__ == '__main__':
1273
1230
    import sys
1274
1231
    sys.exit(main(sys.argv))
1275
 
 
1276
 
 
1277
 
class InterWeave(InterVersionedFile):
1278
 
    """Optimised code paths for weave to weave operations."""
1279
 
    
1280
 
    _matching_file_from_factory = staticmethod(WeaveFile)
1281
 
    _matching_file_to_factory = staticmethod(WeaveFile)
1282
 
    
1283
 
    @staticmethod
1284
 
    def is_compatible(source, target):
1285
 
        """Be compatible with weaves."""
1286
 
        try:
1287
 
            return (isinstance(source, Weave) and
1288
 
                    isinstance(target, Weave))
1289
 
        except AttributeError:
1290
 
            return False
1291
 
 
1292
 
    def join(self, pb=None, msg=None, version_ids=None, ignore_missing=False):
1293
 
        """See InterVersionedFile.join."""
1294
 
        version_ids = self._get_source_version_ids(version_ids, ignore_missing)
1295
 
        if self.target.versions() == [] and version_ids is None:
1296
 
            self.target._copy_weave_content(self.source)
1297
 
            return
1298
 
        self.target._join(self.source, pb, msg, version_ids, ignore_missing)
1299
 
 
1300
 
 
1301
 
InterVersionedFile.register_optimiser(InterWeave)