~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/repofmt/pack_repo.py

Merge down-thread (including bzr.dev)

Show diffs side-by-side

added added

removed removed

Lines of Context:
54
54
    )
55
55
 
56
56
from bzrlib.decorators import needs_write_lock
 
57
from bzrlib.btree_index import (
 
58
    BTreeGraphIndex,
 
59
    BTreeBuilder,
 
60
    )
 
61
from bzrlib.index import (
 
62
    GraphIndex,
 
63
    InMemoryGraphIndex,
 
64
    )
57
65
from bzrlib.repofmt.knitrepo import KnitRepository
58
66
from bzrlib.repository import (
59
67
    CommitBuilder,
215
223
        }
216
224
 
217
225
    def __init__(self, upload_transport, index_transport, pack_transport,
218
 
        upload_suffix='', file_mode=None):
 
226
        upload_suffix='', file_mode=None, index_builder_class=None,
 
227
        index_class=None):
219
228
        """Create a NewPack instance.
220
229
 
221
230
        :param upload_transport: A writable transport for the pack to be
228
237
        :param upload_suffix: An optional suffix to be given to any temporary
229
238
            files created during the pack creation. e.g '.autopack'
230
239
        :param file_mode: An optional file mode to create the new files with.
 
240
        :param index_builder_class: Required keyword parameter - the class of
 
241
            index builder to use.
 
242
        :param index_class: Required keyword parameter - the class of index
 
243
            object to use.
231
244
        """
232
245
        # The relative locations of the packs are constrained, but all are
233
246
        # passed in because the caller has them, so as to avoid object churn.
234
247
        Pack.__init__(self,
235
248
            # Revisions: parents list, no text compression.
236
 
            InMemoryGraphIndex(reference_lists=1),
 
249
            index_builder_class(reference_lists=1),
237
250
            # Inventory: We want to map compression only, but currently the
238
251
            # knit code hasn't been updated enough to understand that, so we
239
252
            # have a regular 2-list index giving parents and compression
240
253
            # source.
241
 
            InMemoryGraphIndex(reference_lists=2),
 
254
            index_builder_class(reference_lists=2),
242
255
            # Texts: compression and per file graph, for all fileids - so two
243
256
            # reference lists and two elements in the key tuple.
244
 
            InMemoryGraphIndex(reference_lists=2, key_elements=2),
 
257
            index_builder_class(reference_lists=2, key_elements=2),
245
258
            # Signatures: Just blobs to store, no compression, no parents
246
259
            # listing.
247
 
            InMemoryGraphIndex(reference_lists=0),
 
260
            index_builder_class(reference_lists=0),
248
261
            )
 
262
        # When we make readonly indices, we need this.
 
263
        self.index_class = index_class
249
264
        # where should the new pack be opened
250
265
        self.upload_transport = upload_transport
251
266
        # where are indices written out to
392
407
 
393
408
    def _replace_index_with_readonly(self, index_type):
394
409
        setattr(self, index_type + '_index',
395
 
            GraphIndex(self.index_transport,
 
410
            self.index_class(self.index_transport,
396
411
                self.index_name(index_type, self.name),
397
412
                self.index_sizes[self.index_offset(index_type)]))
398
413
 
591
606
        return NewPack(self._pack_collection._upload_transport,
592
607
            self._pack_collection._index_transport,
593
608
            self._pack_collection._pack_transport, upload_suffix=self.suffix,
594
 
            file_mode=self._pack_collection.repo.bzrdir._get_file_mode())
 
609
            file_mode=self._pack_collection.repo.bzrdir._get_file_mode(),
 
610
            index_builder_class=self._pack_collection._index_builder_class,
 
611
            index_class=self._pack_collection._index_class)
595
612
 
596
613
    def _copy_revision_texts(self):
597
614
        """Copy revision data to the new pack."""
1104
1121
    """
1105
1122
 
1106
1123
    def __init__(self, repo, transport, index_transport, upload_transport,
1107
 
                 pack_transport):
 
1124
                 pack_transport, index_builder_class, index_class):
1108
1125
        """Create a new RepositoryPackCollection.
1109
1126
 
1110
1127
        :param transport: Addresses the repository base directory 
1113
1130
        :param upload_transport: Addresses the directory into which packs are written
1114
1131
            while they're being created.
1115
1132
        :param pack_transport: Addresses the directory of existing complete packs.
 
1133
        :param index_builder_class: The index builder class to use.
 
1134
        :param index_class: The index class to use.
1116
1135
        """
1117
1136
        self.repo = repo
1118
1137
        self.transport = transport
1119
1138
        self._index_transport = index_transport
1120
1139
        self._upload_transport = upload_transport
1121
1140
        self._pack_transport = pack_transport
 
1141
        self._index_builder_class = index_builder_class
 
1142
        self._index_class = index_class
1122
1143
        self._suffix_offsets = {'.rix': 0, '.iix': 1, '.tix': 2, '.six': 3}
1123
1144
        self.packs = []
1124
1145
        # name:Pack mapping
1275
1296
        # plan out what packs to keep, and what to reorganise
1276
1297
        while len(existing_packs):
1277
1298
            # take the largest pack, and if its less than the head of the
1278
 
            # distribution chart we will include its contents in the new pack for
1279
 
            # that position. If its larger, we remove its size from the
 
1299
            # distribution chart we will include its contents in the new pack
 
1300
            # for that position. If its larger, we remove its size from the
1280
1301
            # distribution chart
1281
1302
            next_pack_rev_count, next_pack = existing_packs.pop(0)
1282
1303
            if next_pack_rev_count >= pack_distribution[0]:
1299
1320
                    # this pack is used up, shift left.
1300
1321
                    del pack_distribution[0]
1301
1322
                    pack_operations.append([0, []])
1302
 
        
1303
 
        return pack_operations
 
1323
        # Now that we know which pack files we want to move, shove them all
 
1324
        # into a single pack file.
 
1325
        final_rev_count = 0
 
1326
        final_pack_list = []
 
1327
        for num_revs, pack_files in pack_operations:
 
1328
            final_rev_count += num_revs
 
1329
            final_pack_list.extend(pack_files)
 
1330
        if len(final_pack_list) == 1:
 
1331
            raise AssertionError('We somehow generated an autopack with a'
 
1332
                ' single pack file being moved.')
 
1333
            return []
 
1334
        return [[final_rev_count, final_pack_list]]
1304
1335
 
1305
1336
    def ensure_loaded(self):
1306
1337
        # NB: if you see an assertion error here, its probably access against
1359
1390
        detect updates from others during our write operation.
1360
1391
        :return: An iterator of the index contents.
1361
1392
        """
1362
 
        return GraphIndex(self.transport, 'pack-names', None
 
1393
        return self._index_class(self.transport, 'pack-names', None
1363
1394
                ).iter_all_entries()
1364
1395
 
1365
1396
    def _make_index(self, name, suffix):
1366
1397
        size_offset = self._suffix_offsets[suffix]
1367
1398
        index_name = name + suffix
1368
1399
        index_size = self._names[name][size_offset]
1369
 
        return GraphIndex(
 
1400
        return self._index_class(
1370
1401
            self._index_transport, index_name, index_size)
1371
1402
 
1372
1403
    def _max_pack_count(self, total_revisions):
1535
1566
        """
1536
1567
        self.lock_names()
1537
1568
        try:
1538
 
            builder = GraphIndexBuilder()
 
1569
            builder = self._index_builder_class()
1539
1570
            # load the disk nodes across
1540
1571
            disk_nodes = set()
1541
1572
            for index, key, value in self._iter_disk_pack_index():
1607
1638
            raise errors.NotWriteLocked(self)
1608
1639
        self._new_pack = NewPack(self._upload_transport, self._index_transport,
1609
1640
            self._pack_transport, upload_suffix='.pack',
1610
 
            file_mode=self.repo.bzrdir._get_file_mode())
 
1641
            file_mode=self.repo.bzrdir._get_file_mode(),
 
1642
            index_builder_class=self._index_builder_class,
 
1643
            index_class=self._index_class)
1611
1644
        # allow writing: queue writes to a new index
1612
1645
        self.revision_index.add_writable_index(self._new_pack.revision_index,
1613
1646
            self._new_pack)
1682
1715
        self._pack_collection = RepositoryPackCollection(self, self._transport,
1683
1716
            index_transport,
1684
1717
            self._transport.clone('upload'),
1685
 
            self._transport.clone('packs'))
 
1718
            self._transport.clone('packs'),
 
1719
            _format.index_builder_class,
 
1720
            _format.index_class)
1686
1721
        self.inventories = KnitVersionedFiles(
1687
1722
            _KnitGraphIndex(self._pack_collection.inventory_index.combined_index,
1688
1723
                add_callback=self._pack_collection.inventory_index.add_callback,
1906
1941
    _serializer = None
1907
1942
    # External references are not supported in pack repositories yet.
1908
1943
    supports_external_lookups = False
 
1944
    # What index classes to use
 
1945
    index_builder_class = None
 
1946
    index_class = None
1909
1947
 
1910
1948
    def initialize(self, a_bzrdir, shared=False):
1911
1949
        """Create a pack based repository.
1917
1955
        """
1918
1956
        mutter('creating repository in %s.', a_bzrdir.transport.base)
1919
1957
        dirs = ['indices', 'obsolete_packs', 'packs', 'upload']
1920
 
        builder = GraphIndexBuilder()
 
1958
        builder = self.index_builder_class()
1921
1959
        files = [('pack-names', builder.finish())]
1922
1960
        utf8_files = [('format', self.get_format_string())]
1923
1961
        
1955
1993
    repository_class = KnitPackRepository
1956
1994
    _commit_builder_class = PackCommitBuilder
1957
1995
    _serializer = xml5.serializer_v5
 
1996
    # What index classes to use
 
1997
    index_builder_class = InMemoryGraphIndex
 
1998
    index_class = GraphIndex
1958
1999
 
1959
2000
    def _get_matching_bzrdir(self):
1960
2001
        return bzrdir.format_registry.make_bzrdir('pack-0.92')
1991
2032
    rich_root_data = True
1992
2033
    supports_tree_reference = True
1993
2034
    _serializer = xml7.serializer_v7
 
2035
    # What index classes to use
 
2036
    index_builder_class = InMemoryGraphIndex
 
2037
    index_class = GraphIndex
1994
2038
 
1995
2039
    def _get_matching_bzrdir(self):
1996
2040
        return bzrdir.format_registry.make_bzrdir(
2032
2076
    rich_root_data = True
2033
2077
    supports_tree_reference = False
2034
2078
    _serializer = xml6.serializer_v6
 
2079
    # What index classes to use
 
2080
    index_builder_class = InMemoryGraphIndex
 
2081
    index_class = GraphIndex
2035
2082
 
2036
2083
    def _get_matching_bzrdir(self):
2037
2084
        return bzrdir.format_registry.make_bzrdir(
2070
2117
    _commit_builder_class = PackCommitBuilder
2071
2118
    _serializer = xml5.serializer_v5
2072
2119
    supports_external_lookups = True
 
2120
    # What index classes to use
 
2121
    index_builder_class = InMemoryGraphIndex
 
2122
    index_class = GraphIndex
2073
2123
 
2074
2124
    def _get_matching_bzrdir(self):
2075
 
        return bzrdir.format_registry.make_bzrdir('development1')
 
2125
        return bzrdir.format_registry.make_bzrdir('1.6')
2076
2126
 
2077
2127
    def _ignore_setting_bzrdir(self, format):
2078
2128
        pass
2106
2156
    supports_tree_reference = False # no subtrees
2107
2157
    _serializer = xml6.serializer_v6
2108
2158
    supports_external_lookups = True
 
2159
    # What index classes to use
 
2160
    index_builder_class = InMemoryGraphIndex
 
2161
    index_class = GraphIndex
2109
2162
 
2110
2163
    def _get_matching_bzrdir(self):
2111
2164
        return bzrdir.format_registry.make_bzrdir(
2149
2202
    _serializer = xml7.serializer_v7
2150
2203
 
2151
2204
    supports_external_lookups = True
 
2205
    # What index classes to use
 
2206
    index_builder_class = InMemoryGraphIndex
 
2207
    index_class = GraphIndex
2152
2208
 
2153
2209
    def _get_matching_bzrdir(self):
2154
2210
        return bzrdir.format_registry.make_bzrdir(
2155
 
            'development1-subtree')
 
2211
            '1.6.1-rich-root')
2156
2212
 
2157
2213
    def _ignore_setting_bzrdir(self, format):
2158
2214
        pass
2173
2229
                " (deprecated)")
2174
2230
 
2175
2231
 
2176
 
class RepositoryFormatPackDevelopment1(RepositoryFormatPack):
 
2232
class RepositoryFormatPackDevelopment2(RepositoryFormatPack):
2177
2233
    """A no-subtrees development repository.
2178
2234
 
2179
 
    This format should be retained until the second release after bzr 1.5.
 
2235
    This format should be retained until the second release after bzr 1.7.
2180
2236
 
2181
 
    Supports external lookups, which results in non-truncated ghosts after
2182
 
    reconcile compared to pack-0.92 formats.
 
2237
    This is pack-1.6.1 with B+Tree indices.
2183
2238
    """
2184
2239
 
2185
2240
    repository_class = KnitPackRepository
2186
2241
    _commit_builder_class = PackCommitBuilder
2187
2242
    _serializer = xml5.serializer_v5
2188
2243
    supports_external_lookups = True
 
2244
    # What index classes to use
 
2245
    index_builder_class = BTreeBuilder
 
2246
    index_class = BTreeGraphIndex
2189
2247
 
2190
2248
    def _get_matching_bzrdir(self):
2191
 
        return bzrdir.format_registry.make_bzrdir('development1')
 
2249
        return bzrdir.format_registry.make_bzrdir('development2')
2192
2250
 
2193
2251
    def _ignore_setting_bzrdir(self, format):
2194
2252
        pass
2197
2255
 
2198
2256
    def get_format_string(self):
2199
2257
        """See RepositoryFormat.get_format_string()."""
2200
 
        return "Bazaar development format 1 (needs bzr.dev from before 1.6)\n"
 
2258
        return "Bazaar development format 2 (needs bzr.dev from before 1.8)\n"
2201
2259
 
2202
2260
    def get_format_description(self):
2203
2261
        """See RepositoryFormat.get_format_description()."""
2204
2262
        return ("Development repository format, currently the same as "
2205
 
            "pack-0.92 with external reference support.\n")
 
2263
            "1.6.1 with B+Trees.\n")
2206
2264
 
2207
2265
    def check_conversion_target(self, target_format):
2208
2266
        pass
2209
2267
 
2210
2268
 
2211
 
class RepositoryFormatPackDevelopment1Subtree(RepositoryFormatPack):
 
2269
class RepositoryFormatPackDevelopment2Subtree(RepositoryFormatPack):
2212
2270
    """A subtrees development repository.
2213
2271
 
2214
 
    This format should be retained until the second release after bzr 1.5.
 
2272
    This format should be retained until the second release after bzr 1.7.
2215
2273
 
2216
 
    Supports external lookups, which results in non-truncated ghosts after
2217
 
    reconcile compared to pack-0.92 formats.
 
2274
    1.6.1-subtree[as it might have been] with B+Tree indices.
2218
2275
    """
2219
2276
 
2220
2277
    repository_class = KnitPackRepository
2223
2280
    supports_tree_reference = True
2224
2281
    _serializer = xml7.serializer_v7
2225
2282
    supports_external_lookups = True
 
2283
    # What index classes to use
 
2284
    index_builder_class = BTreeBuilder
 
2285
    index_class = BTreeGraphIndex
2226
2286
 
2227
2287
    def _get_matching_bzrdir(self):
2228
2288
        return bzrdir.format_registry.make_bzrdir(
2229
 
            'development1-subtree')
 
2289
            'development2-subtree')
2230
2290
 
2231
2291
    def _ignore_setting_bzrdir(self, format):
2232
2292
        pass
2243
2303
            
2244
2304
    def get_format_string(self):
2245
2305
        """See RepositoryFormat.get_format_string()."""
2246
 
        return ("Bazaar development format 1 with subtree support "
2247
 
            "(needs bzr.dev from before 1.6)\n")
 
2306
        return ("Bazaar development format 2 with subtree support "
 
2307
            "(needs bzr.dev from before 1.8)\n")
2248
2308
 
2249
2309
    def get_format_description(self):
2250
2310
        """See RepositoryFormat.get_format_description()."""
2251
2311
        return ("Development repository format, currently the same as "
2252
 
            "pack-0.92-subtree with external reference support.\n")
 
2312
            "1.6.1-subtree with B+Tree indices.\n")