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

1st cut merge of bzr.dev r3907

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005, 2006 Canonical Ltd
 
1
# Copyright (C) 2005, 2006, 2007, 2008 Canonical Ltd
2
2
#
3
3
# Authors:
4
4
#   Johan Rydberg <jrydberg@gnu.org>
22
22
from copy import copy
23
23
from cStringIO import StringIO
24
24
import os
25
 
import urllib
26
25
from zlib import adler32
27
26
 
28
27
from bzrlib.lazy_import import lazy_import
29
28
lazy_import(globals(), """
 
29
import urllib
30
30
 
31
31
from bzrlib import (
32
32
    errors,
 
33
    index,
33
34
    osutils,
34
35
    multiparent,
35
36
    tsort,
58
59
    'bzrlib.knit', 'FTAnnotatedToUnannotated')
59
60
adapter_registry.register_lazy(('knit-annotated-ft-gz', 'fulltext'),
60
61
    'bzrlib.knit', 'FTAnnotatedToFullText')
 
62
# adapter_registry.register_lazy(('knit-annotated-ft-gz', 'chunked'),
 
63
#     'bzrlib.knit', 'FTAnnotatedToChunked')
61
64
 
62
65
 
63
66
class ContentFactory(object):
83
86
        self.parents = None
84
87
 
85
88
 
 
89
class ChunkedContentFactory(ContentFactory):
 
90
    """Static data content factory.
 
91
 
 
92
    This takes a 'chunked' list of strings. The only requirement on 'chunked' is
 
93
    that ''.join(lines) becomes a valid fulltext. A tuple of a single string
 
94
    satisfies this, as does a list of lines.
 
95
 
 
96
    :ivar sha1: None, or the sha1 of the content fulltext.
 
97
    :ivar storage_kind: The native storage kind of this factory. Always
 
98
        'chunked'
 
99
    :ivar key: The key of this content. Each key is a tuple with a single
 
100
        string in it.
 
101
    :ivar parents: A tuple of parent keys for self.key. If the object has
 
102
        no parent information, None (as opposed to () for an empty list of
 
103
        parents).
 
104
     """
 
105
 
 
106
    def __init__(self, key, parents, sha1, chunks):
 
107
        """Create a ContentFactory."""
 
108
        self.sha1 = sha1
 
109
        self.storage_kind = 'chunked'
 
110
        self.key = key
 
111
        self.parents = parents
 
112
        self._chunks = chunks
 
113
 
 
114
    def get_bytes_as(self, storage_kind):
 
115
        if storage_kind == 'chunked':
 
116
            return self._chunks
 
117
        elif storage_kind == 'fulltext':
 
118
            return ''.join(self._chunks)
 
119
        raise errors.UnavailableRepresentation(self.key, storage_kind,
 
120
            self.storage_kind)
 
121
 
 
122
 
86
123
class FulltextContentFactory(ContentFactory):
87
124
    """Static data content factory.
88
125
 
89
126
    This takes a fulltext when created and just returns that during
90
127
    get_bytes_as('fulltext').
91
 
    
 
128
 
92
129
    :ivar sha1: None, or the sha1 of the content fulltext.
93
130
    :ivar storage_kind: The native storage kind of this factory. Always
94
131
        'fulltext'.
110
147
    def get_bytes_as(self, storage_kind):
111
148
        if storage_kind == self.storage_kind:
112
149
            return self._text
 
150
        elif storage_kind == 'chunked':
 
151
            return (self._text,)
113
152
        raise errors.UnavailableRepresentation(self.key, storage_kind,
114
153
            self.storage_kind)
115
154
 
520
559
    """
521
560
 
522
561
    def __init__(self, backing_vf):
523
 
        """Create a RecordingVersionedFileDsecorator decorating backing_vf.
 
562
        """Create a RecordingVersionedFilesDecorator decorating backing_vf.
524
563
        
525
564
        :param backing_vf: The versioned file to answer all methods.
526
565
        """
561
600
        return self._backing_vf.keys()
562
601
 
563
602
 
 
603
class OrderingVersionedFilesDecorator(RecordingVersionedFilesDecorator):
 
604
    """A VF that records calls, and returns keys in specific order.
 
605
 
 
606
    :ivar calls: A list of the calls made; can be reset at any time by
 
607
        assigning [] to it.
 
608
    """
 
609
 
 
610
    def __init__(self, backing_vf, key_priority):
 
611
        """Create a RecordingVersionedFilesDecorator decorating backing_vf.
 
612
 
 
613
        :param backing_vf: The versioned file to answer all methods.
 
614
        :param key_priority: A dictionary defining what order keys should be
 
615
            returned from an 'unordered' get_record_stream request.
 
616
            Keys with lower priority are returned first, keys not present in
 
617
            the map get an implicit priority of 0, and are returned in
 
618
            lexicographical order.
 
619
        """
 
620
        RecordingVersionedFilesDecorator.__init__(self, backing_vf)
 
621
        self._key_priority = key_priority
 
622
 
 
623
    def get_record_stream(self, keys, sort_order, include_delta_closure):
 
624
        self.calls.append(("get_record_stream", list(keys), sort_order,
 
625
            include_delta_closure))
 
626
        if sort_order == 'unordered':
 
627
            def sort_key(key):
 
628
                return (self._key_priority.get(key, 0), key)
 
629
            # Use a defined order by asking for the keys one-by-one from the
 
630
            # backing_vf
 
631
            for key in sorted(keys, key=sort_key):
 
632
                for record in self._backing_vf.get_record_stream([key],
 
633
                                'unordered', include_delta_closure):
 
634
                    yield record
 
635
        else:
 
636
            for record in self._backing_vf.get_record_stream(keys, sort_order,
 
637
                            include_delta_closure):
 
638
                yield record
 
639
 
 
640
 
564
641
class KeyMapper(object):
565
642
    """KeyMappers map between keys and underlying partitioned storage."""
566
643
 
765
842
                                  if not mpvf.has_version(p))
766
843
        # It seems likely that adding all the present parents as fulltexts can
767
844
        # easily exhaust memory.
768
 
        split_lines = osutils.split_lines
 
845
        chunks_to_lines = osutils.chunks_to_lines
769
846
        for record in self.get_record_stream(needed_parents, 'unordered',
770
847
            True):
771
848
            if record.storage_kind == 'absent':
772
849
                continue
773
 
            mpvf.add_version(split_lines(record.get_bytes_as('fulltext')),
 
850
            mpvf.add_version(chunks_to_lines(record.get_bytes_as('chunked')),
774
851
                record.key, [])
775
852
        for (key, parent_keys, expected_sha1, mpdiff), lines in\
776
853
            zip(records, mpvf.get_line_list(versions)):
846
923
        """
847
924
        raise NotImplementedError(self.get_sha1s)
848
925
 
 
926
    has_key = index._has_key_from_parent_map
 
927
 
849
928
    def insert_record_stream(self, stream):
850
929
        """Insert a record stream into this container.
851
930
 
899
978
        ghosts = maybe_ghosts - set(self.get_parent_map(maybe_ghosts))
900
979
        knit_keys.difference_update(ghosts)
901
980
        lines = {}
902
 
        split_lines = osutils.split_lines
 
981
        chunks_to_lines = osutils.chunks_to_lines
903
982
        for record in self.get_record_stream(knit_keys, 'topological', True):
904
 
            lines[record.key] = split_lines(record.get_bytes_as('fulltext'))
 
983
            lines[record.key] = chunks_to_lines(record.get_bytes_as('chunked'))
905
984
            # line_block_dict = {}
906
985
            # for parent, blocks in record.extract_line_blocks():
907
986
            #   line_blocks[parent] = blocks
922
1001
                parent_lines, left_parent_blocks))
923
1002
        return diffs
924
1003
 
 
1004
    missing_keys = index._missing_keys_from_parent_map
 
1005
 
925
1006
    def _extract_blocks(self, version_id, source, target):
926
1007
        return None
927
1008
 
1208
1289
                lines = self._lines[key]
1209
1290
                parents = self._parents[key]
1210
1291
                pending.remove(key)
1211
 
                yield FulltextContentFactory(key, parents, None,
1212
 
                    ''.join(lines))
 
1292
                yield ChunkedContentFactory(key, parents, None, lines)
1213
1293
        for versionedfile in self.fallback_versionedfiles:
1214
1294
            for record in versionedfile.get_record_stream(
1215
1295
                pending, 'unordered', True):
1379
1459
            if lines is not None:
1380
1460
                if not isinstance(lines, list):
1381
1461
                    raise AssertionError
1382
 
                yield FulltextContentFactory((k,), None, 
 
1462
                yield ChunkedContentFactory((k,), None,
1383
1463
                        sha1=osutils.sha_strings(lines),
1384
 
                        text=''.join(lines))
 
1464
                        chunks=lines)
1385
1465
            else:
1386
1466
                yield AbsentContentFactory((k,))
1387
1467