/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/repofmt/weaverepo.py

  • Committer: Andrew Bennetts
  • Date: 2008-04-02 00:14:00 UTC
  • mfrom: (3324 +trunk)
  • mto: This revision was merged to the branch mainline in revision 3756.
  • Revision ID: andrew.bennetts@canonical.com-20080402001400-r1pqse38i03dl97w
Merge from bzr.dev.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# Copyright (C) 2005, 2006, 2007 Canonical Ltd
 
2
#
 
3
# This program is free software; you can redistribute it and/or modify
 
4
# it under the terms of the GNU General Public License as published by
 
5
# the Free Software Foundation; either version 2 of the License, or
 
6
# (at your option) any later version.
 
7
#
 
8
# This program is distributed in the hope that it will be useful,
 
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
11
# GNU General Public License for more details.
 
12
#
 
13
# You should have received a copy of the GNU General Public License
 
14
# along with this program; if not, write to the Free Software
 
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
16
 
 
17
"""Deprecated weave-based repository formats.
 
18
 
 
19
Weave based formats scaled linearly with history size and could not represent
 
20
ghosts.
 
21
"""
 
22
 
 
23
from StringIO import StringIO
 
24
 
 
25
from bzrlib.lazy_import import lazy_import
 
26
lazy_import(globals(), """
 
27
from bzrlib import (
 
28
    xml5,
 
29
    )
 
30
""")
 
31
from bzrlib import (
 
32
    bzrdir,
 
33
    debug,
 
34
    errors,
 
35
    lockable_files,
 
36
    lockdir,
 
37
    osutils,
 
38
    revision as _mod_revision,
 
39
    weave,
 
40
    weavefile,
 
41
    )
 
42
from bzrlib.decorators import needs_read_lock, needs_write_lock
 
43
from bzrlib.repository import (
 
44
    CommitBuilder,
 
45
    MetaDirRepository,
 
46
    MetaDirRepositoryFormat,
 
47
    Repository,
 
48
    RepositoryFormat,
 
49
    )
 
50
from bzrlib.store.text import TextStore
 
51
from bzrlib.symbol_versioning import deprecated_method, one_four
 
52
from bzrlib.trace import mutter
 
53
 
 
54
 
 
55
class AllInOneRepository(Repository):
 
56
    """Legacy support - the repository behaviour for all-in-one branches."""
 
57
 
 
58
    @property
 
59
    def _serializer(self):
 
60
        return xml5.serializer_v5
 
61
 
 
62
    def __init__(self, _format, a_bzrdir, _revision_store, control_store, text_store):
 
63
        # we reuse one control files instance.
 
64
        dir_mode = a_bzrdir._control_files._dir_mode
 
65
        file_mode = a_bzrdir._control_files._file_mode
 
66
 
 
67
        def get_store(name, compressed=True, prefixed=False):
 
68
            # FIXME: This approach of assuming stores are all entirely compressed
 
69
            # or entirely uncompressed is tidy, but breaks upgrade from 
 
70
            # some existing branches where there's a mixture; we probably 
 
71
            # still want the option to look for both.
 
72
            relpath = a_bzrdir._control_files._escape(name)
 
73
            store = TextStore(a_bzrdir._control_files._transport.clone(relpath),
 
74
                              prefixed=prefixed, compressed=compressed,
 
75
                              dir_mode=dir_mode,
 
76
                              file_mode=file_mode)
 
77
            return store
 
78
 
 
79
        # not broken out yet because the controlweaves|inventory_store
 
80
        # and text_store | weave_store bits are still different.
 
81
        if isinstance(_format, RepositoryFormat4):
 
82
            # cannot remove these - there is still no consistent api 
 
83
            # which allows access to this old info.
 
84
            self.inventory_store = get_store('inventory-store')
 
85
            text_store = get_store('text-store')
 
86
        super(AllInOneRepository, self).__init__(_format, a_bzrdir, a_bzrdir._control_files, _revision_store, control_store, text_store)
 
87
 
 
88
    @needs_read_lock
 
89
    def _all_possible_ids(self):
 
90
        """Return all the possible revisions that we could find."""
 
91
        if 'evil' in debug.debug_flags:
 
92
            mutter_callsite(3, "_all_possible_ids scales with size of history.")
 
93
        return self.get_inventory_weave().versions()
 
94
 
 
95
    @needs_read_lock
 
96
    def _all_revision_ids(self):
 
97
        """Returns a list of all the revision ids in the repository. 
 
98
 
 
99
        These are in as much topological order as the underlying store can 
 
100
        present: for weaves ghosts may lead to a lack of correctness until
 
101
        the reweave updates the parents list.
 
102
        """
 
103
        if self._revision_store.text_store.listable():
 
104
            return self._revision_store.all_revision_ids(self.get_transaction())
 
105
        result = self._all_possible_ids()
 
106
        # TODO: jam 20070210 Ensure that _all_possible_ids returns non-unicode
 
107
        #       ids. (It should, since _revision_store's API should change to
 
108
        #       return utf8 revision_ids)
 
109
        return self._eliminate_revisions_not_present(result)
 
110
 
 
111
    def _check_revision_parents(self, revision, inventory):
 
112
        """Private to Repository and Fetch.
 
113
        
 
114
        This checks the parentage of revision in an inventory weave for 
 
115
        consistency and is only applicable to inventory-weave-for-ancestry
 
116
        using repository formats & fetchers.
 
117
        """
 
118
        weave_parents = inventory.get_parent_map(
 
119
            [revision.revision_id])[revision.revision_id]
 
120
        parent_map = inventory.get_parent_map(revision.parent_ids)
 
121
        for parent_id in revision.parent_ids:
 
122
            if parent_id in parent_map:
 
123
                # this parent must not be a ghost.
 
124
                if not parent_id in weave_parents:
 
125
                    # but it is a ghost
 
126
                    raise errors.CorruptRepository(self)
 
127
 
 
128
    def get_commit_builder(self, branch, parents, config, timestamp=None,
 
129
                           timezone=None, committer=None, revprops=None,
 
130
                           revision_id=None):
 
131
        self._check_ascii_revisionid(revision_id, self.get_commit_builder)
 
132
        result = WeaveCommitBuilder(self, parents, config, timestamp, timezone,
 
133
                              committer, revprops, revision_id)
 
134
        self.start_write_group()
 
135
        return result
 
136
 
 
137
    @needs_read_lock
 
138
    def get_revisions(self, revision_ids):
 
139
        revs = self._get_revisions(revision_ids)
 
140
        # weave corruption can lead to absent revision markers that should be
 
141
        # present.
 
142
        # the following test is reasonably cheap (it needs a single weave read)
 
143
        # and the weave is cached in read transactions. In write transactions
 
144
        # it is not cached but typically we only read a small number of
 
145
        # revisions. For knits when they are introduced we will probably want
 
146
        # to ensure that caching write transactions are in use.
 
147
        inv = self.get_inventory_weave()
 
148
        for rev in revs:
 
149
            self._check_revision_parents(rev, inv)
 
150
        return revs
 
151
 
 
152
    @deprecated_method(one_four)
 
153
    @needs_read_lock
 
154
    def get_revision_graph(self, revision_id=None):
 
155
        """Return a dictionary containing the revision graph.
 
156
        
 
157
        :param revision_id: The revision_id to get a graph from. If None, then
 
158
        the entire revision graph is returned. This is a deprecated mode of
 
159
        operation and will be removed in the future.
 
160
        :return: a dictionary of revision_id->revision_parents_list.
 
161
        """
 
162
        if 'evil' in debug.debug_flags:
 
163
            mutter_callsite(2,
 
164
                "get_revision_graph scales with size of history.")
 
165
        # special case NULL_REVISION
 
166
        if revision_id == _mod_revision.NULL_REVISION:
 
167
            return {}
 
168
        a_weave = self.get_inventory_weave()
 
169
        all_revisions = self._eliminate_revisions_not_present(
 
170
                                a_weave.versions())
 
171
        entire_graph = a_weave.get_parent_map(all_revisions)
 
172
        if revision_id is None:
 
173
            return entire_graph
 
174
        elif revision_id not in entire_graph:
 
175
            raise errors.NoSuchRevision(self, revision_id)
 
176
        else:
 
177
            # add what can be reached from revision_id
 
178
            result = {}
 
179
            pending = set([revision_id])
 
180
            while len(pending) > 0:
 
181
                node = pending.pop()
 
182
                result[node] = entire_graph[node]
 
183
                for revision_id in result[node]:
 
184
                    if revision_id not in result:
 
185
                        pending.add(revision_id)
 
186
            return result
 
187
 
 
188
    def has_revisions(self, revision_ids):
 
189
        """See Repository.has_revisions()."""
 
190
        result = set()
 
191
        transaction = self.get_transaction()
 
192
        for revision_id in revision_ids:
 
193
            if self._revision_store.has_revision_id(revision_id, transaction):
 
194
                result.add(revision_id)
 
195
        return result
 
196
 
 
197
    @needs_read_lock
 
198
    def is_shared(self):
 
199
        """AllInOne repositories cannot be shared."""
 
200
        return False
 
201
 
 
202
    @needs_write_lock
 
203
    def set_make_working_trees(self, new_value):
 
204
        """Set the policy flag for making working trees when creating branches.
 
205
 
 
206
        This only applies to branches that use this repository.
 
207
 
 
208
        The default is 'True'.
 
209
        :param new_value: True to restore the default, False to disable making
 
210
                          working trees.
 
211
        """
 
212
        raise NotImplementedError(self.set_make_working_trees)
 
213
    
 
214
    def make_working_trees(self):
 
215
        """Returns the policy for making working trees on new branches."""
 
216
        return True
 
217
 
 
218
    def revision_graph_can_have_wrong_parents(self):
 
219
        # XXX: This is an old format that we don't support full checking on, so
 
220
        # just claim that checking for this inconsistency is not required.
 
221
        return False
 
222
 
 
223
 
 
224
class WeaveMetaDirRepository(MetaDirRepository):
 
225
    """A subclass of MetaDirRepository to set weave specific policy."""
 
226
 
 
227
    @property
 
228
    def _serializer(self):
 
229
        return xml5.serializer_v5
 
230
 
 
231
    @needs_read_lock
 
232
    def _all_possible_ids(self):
 
233
        """Return all the possible revisions that we could find."""
 
234
        if 'evil' in debug.debug_flags:
 
235
            mutter_callsite(3, "_all_possible_ids scales with size of history.")
 
236
        return self.get_inventory_weave().versions()
 
237
 
 
238
    @needs_read_lock
 
239
    def _all_revision_ids(self):
 
240
        """Returns a list of all the revision ids in the repository. 
 
241
 
 
242
        These are in as much topological order as the underlying store can 
 
243
        present: for weaves ghosts may lead to a lack of correctness until
 
244
        the reweave updates the parents list.
 
245
        """
 
246
        if self._revision_store.text_store.listable():
 
247
            return self._revision_store.all_revision_ids(self.get_transaction())
 
248
        result = self._all_possible_ids()
 
249
        # TODO: jam 20070210 Ensure that _all_possible_ids returns non-unicode
 
250
        #       ids. (It should, since _revision_store's API should change to
 
251
        #       return utf8 revision_ids)
 
252
        return self._eliminate_revisions_not_present(result)
 
253
 
 
254
    def _check_revision_parents(self, revision, inventory):
 
255
        """Private to Repository and Fetch.
 
256
        
 
257
        This checks the parentage of revision in an inventory weave for 
 
258
        consistency and is only applicable to inventory-weave-for-ancestry
 
259
        using repository formats & fetchers.
 
260
        """
 
261
        weave_parents = inventory.get_parent_map(
 
262
            [revision.revision_id])[revision.revision_id]
 
263
        parent_map = inventory.get_parent_map(revision.parent_ids)
 
264
        for parent_id in revision.parent_ids:
 
265
            if parent_id in parent_map:
 
266
                # this parent must not be a ghost.
 
267
                if not parent_id in weave_parents:
 
268
                    # but it is a ghost
 
269
                    raise errors.CorruptRepository(self)
 
270
 
 
271
    def get_commit_builder(self, branch, parents, config, timestamp=None,
 
272
                           timezone=None, committer=None, revprops=None,
 
273
                           revision_id=None):
 
274
        self._check_ascii_revisionid(revision_id, self.get_commit_builder)
 
275
        result = WeaveCommitBuilder(self, parents, config, timestamp, timezone,
 
276
                              committer, revprops, revision_id)
 
277
        self.start_write_group()
 
278
        return result
 
279
 
 
280
    @needs_read_lock
 
281
    def get_revision(self, revision_id):
 
282
        """Return the Revision object for a named revision"""
 
283
        # TODO: jam 20070210 get_revision_reconcile should do this for us
 
284
        r = self.get_revision_reconcile(revision_id)
 
285
        # weave corruption can lead to absent revision markers that should be
 
286
        # present.
 
287
        # the following test is reasonably cheap (it needs a single weave read)
 
288
        # and the weave is cached in read transactions. In write transactions
 
289
        # it is not cached but typically we only read a small number of
 
290
        # revisions. For knits when they are introduced we will probably want
 
291
        # to ensure that caching write transactions are in use.
 
292
        inv = self.get_inventory_weave()
 
293
        self._check_revision_parents(r, inv)
 
294
        return r
 
295
 
 
296
    @deprecated_method(one_four)
 
297
    @needs_read_lock
 
298
    def get_revision_graph(self, revision_id=None):
 
299
        """Return a dictionary containing the revision graph.
 
300
        
 
301
        :param revision_id: The revision_id to get a graph from. If None, then
 
302
        the entire revision graph is returned. This is a deprecated mode of
 
303
        operation and will be removed in the future.
 
304
        :return: a dictionary of revision_id->revision_parents_list.
 
305
        """
 
306
        if 'evil' in debug.debug_flags:
 
307
            mutter_callsite(3,
 
308
                "get_revision_graph scales with size of history.")
 
309
        # special case NULL_REVISION
 
310
        if revision_id == _mod_revision.NULL_REVISION:
 
311
            return {}
 
312
        a_weave = self.get_inventory_weave()
 
313
        all_revisions = self._eliminate_revisions_not_present(
 
314
                                a_weave.versions())
 
315
        entire_graph = a_weave.get_parent_map(all_revisions)
 
316
        if revision_id is None:
 
317
            return entire_graph
 
318
        elif revision_id not in entire_graph:
 
319
            raise errors.NoSuchRevision(self, revision_id)
 
320
        else:
 
321
            # add what can be reached from revision_id
 
322
            result = {}
 
323
            pending = set([revision_id])
 
324
            while len(pending) > 0:
 
325
                node = pending.pop()
 
326
                result[node] = entire_graph[node]
 
327
                for revision_id in result[node]:
 
328
                    if revision_id not in result:
 
329
                        pending.add(revision_id)
 
330
            return result
 
331
 
 
332
    def has_revisions(self, revision_ids):
 
333
        """See Repository.has_revisions()."""
 
334
        result = set()
 
335
        transaction = self.get_transaction()
 
336
        for revision_id in revision_ids:
 
337
            if self._revision_store.has_revision_id(revision_id, transaction):
 
338
                result.add(revision_id)
 
339
        return result
 
340
 
 
341
    def revision_graph_can_have_wrong_parents(self):
 
342
        # XXX: This is an old format that we don't support full checking on, so
 
343
        # just claim that checking for this inconsistency is not required.
 
344
        return False
 
345
 
 
346
 
 
347
class PreSplitOutRepositoryFormat(RepositoryFormat):
 
348
    """Base class for the pre split out repository formats."""
 
349
 
 
350
    rich_root_data = False
 
351
    supports_tree_reference = False
 
352
    supports_ghosts = False
 
353
    supports_external_lookups = False
 
354
 
 
355
    def initialize(self, a_bzrdir, shared=False, _internal=False):
 
356
        """Create a weave repository."""
 
357
        if shared:
 
358
            raise errors.IncompatibleFormat(self, a_bzrdir._format)
 
359
 
 
360
        if not _internal:
 
361
            # always initialized when the bzrdir is.
 
362
            return self.open(a_bzrdir, _found=True)
 
363
        
 
364
        # Create an empty weave
 
365
        sio = StringIO()
 
366
        weavefile.write_weave_v5(weave.Weave(), sio)
 
367
        empty_weave = sio.getvalue()
 
368
 
 
369
        mutter('creating repository in %s.', a_bzrdir.transport.base)
 
370
        dirs = ['revision-store', 'weaves']
 
371
        files = [('inventory.weave', StringIO(empty_weave)),
 
372
                 ]
 
373
        
 
374
        # FIXME: RBC 20060125 don't peek under the covers
 
375
        # NB: no need to escape relative paths that are url safe.
 
376
        control_files = lockable_files.LockableFiles(a_bzrdir.transport,
 
377
                                'branch-lock', lockable_files.TransportLock)
 
378
        control_files.create_lock()
 
379
        control_files.lock_write()
 
380
        control_files._transport.mkdir_multi(dirs,
 
381
                mode=control_files._dir_mode)
 
382
        try:
 
383
            for file, content in files:
 
384
                control_files.put(file, content)
 
385
        finally:
 
386
            control_files.unlock()
 
387
        return self.open(a_bzrdir, _found=True)
 
388
 
 
389
    def _get_control_store(self, repo_transport, control_files):
 
390
        """Return the control store for this repository."""
 
391
        return self._get_versioned_file_store('',
 
392
                                              repo_transport,
 
393
                                              control_files,
 
394
                                              prefixed=False)
 
395
 
 
396
    def _get_text_store(self, transport, control_files):
 
397
        """Get a store for file texts for this format."""
 
398
        raise NotImplementedError(self._get_text_store)
 
399
 
 
400
    def open(self, a_bzrdir, _found=False):
 
401
        """See RepositoryFormat.open()."""
 
402
        if not _found:
 
403
            # we are being called directly and must probe.
 
404
            raise NotImplementedError
 
405
 
 
406
        repo_transport = a_bzrdir.get_repository_transport(None)
 
407
        control_files = a_bzrdir._control_files
 
408
        text_store = self._get_text_store(repo_transport, control_files)
 
409
        control_store = self._get_control_store(repo_transport, control_files)
 
410
        _revision_store = self._get_revision_store(repo_transport, control_files)
 
411
        return AllInOneRepository(_format=self,
 
412
                                  a_bzrdir=a_bzrdir,
 
413
                                  _revision_store=_revision_store,
 
414
                                  control_store=control_store,
 
415
                                  text_store=text_store)
 
416
 
 
417
    def check_conversion_target(self, target_format):
 
418
        pass
 
419
 
 
420
 
 
421
class RepositoryFormat4(PreSplitOutRepositoryFormat):
 
422
    """Bzr repository format 4.
 
423
 
 
424
    This repository format has:
 
425
     - flat stores
 
426
     - TextStores for texts, inventories,revisions.
 
427
 
 
428
    This format is deprecated: it indexes texts using a text id which is
 
429
    removed in format 5; initialization and write support for this format
 
430
    has been removed.
 
431
    """
 
432
 
 
433
    _matchingbzrdir = bzrdir.BzrDirFormat4()
 
434
 
 
435
    def __init__(self):
 
436
        super(RepositoryFormat4, self).__init__()
 
437
 
 
438
    def get_format_description(self):
 
439
        """See RepositoryFormat.get_format_description()."""
 
440
        return "Repository format 4"
 
441
 
 
442
    def initialize(self, url, shared=False, _internal=False):
 
443
        """Format 4 branches cannot be created."""
 
444
        raise errors.UninitializableFormat(self)
 
445
 
 
446
    def is_supported(self):
 
447
        """Format 4 is not supported.
 
448
 
 
449
        It is not supported because the model changed from 4 to 5 and the
 
450
        conversion logic is expensive - so doing it on the fly was not 
 
451
        feasible.
 
452
        """
 
453
        return False
 
454
 
 
455
    def _get_control_store(self, repo_transport, control_files):
 
456
        """Format 4 repositories have no formal control store at this point.
 
457
        
 
458
        This will cause any control-file-needing apis to fail - this is desired.
 
459
        """
 
460
        return None
 
461
    
 
462
    def _get_revision_store(self, repo_transport, control_files):
 
463
        """See RepositoryFormat._get_revision_store()."""
 
464
        from bzrlib.xml4 import serializer_v4
 
465
        return self._get_text_rev_store(repo_transport,
 
466
                                        control_files,
 
467
                                        'revision-store',
 
468
                                        serializer=serializer_v4)
 
469
 
 
470
    def _get_text_store(self, transport, control_files):
 
471
        """See RepositoryFormat._get_text_store()."""
 
472
 
 
473
 
 
474
class RepositoryFormat5(PreSplitOutRepositoryFormat):
 
475
    """Bzr control format 5.
 
476
 
 
477
    This repository format has:
 
478
     - weaves for file texts and inventory
 
479
     - flat stores
 
480
     - TextStores for revisions and signatures.
 
481
    """
 
482
 
 
483
    _versionedfile_class = weave.WeaveFile
 
484
    _matchingbzrdir = bzrdir.BzrDirFormat5()
 
485
 
 
486
    def __init__(self):
 
487
        super(RepositoryFormat5, self).__init__()
 
488
 
 
489
    def get_format_description(self):
 
490
        """See RepositoryFormat.get_format_description()."""
 
491
        return "Weave repository format 5"
 
492
 
 
493
    def _get_revision_store(self, repo_transport, control_files):
 
494
        """See RepositoryFormat._get_revision_store()."""
 
495
        """Return the revision store object for this a_bzrdir."""
 
496
        return self._get_text_rev_store(repo_transport,
 
497
                                        control_files,
 
498
                                        'revision-store',
 
499
                                        compressed=False)
 
500
 
 
501
    def _get_text_store(self, transport, control_files):
 
502
        """See RepositoryFormat._get_text_store()."""
 
503
        return self._get_versioned_file_store('weaves', transport, control_files, prefixed=False)
 
504
 
 
505
 
 
506
class RepositoryFormat6(PreSplitOutRepositoryFormat):
 
507
    """Bzr control format 6.
 
508
 
 
509
    This repository format has:
 
510
     - weaves for file texts and inventory
 
511
     - hash subdirectory based stores.
 
512
     - TextStores for revisions and signatures.
 
513
    """
 
514
 
 
515
    _versionedfile_class = weave.WeaveFile
 
516
    _matchingbzrdir = bzrdir.BzrDirFormat6()
 
517
 
 
518
    def __init__(self):
 
519
        super(RepositoryFormat6, self).__init__()
 
520
 
 
521
    def get_format_description(self):
 
522
        """See RepositoryFormat.get_format_description()."""
 
523
        return "Weave repository format 6"
 
524
 
 
525
    def _get_revision_store(self, repo_transport, control_files):
 
526
        """See RepositoryFormat._get_revision_store()."""
 
527
        return self._get_text_rev_store(repo_transport,
 
528
                                        control_files,
 
529
                                        'revision-store',
 
530
                                        compressed=False,
 
531
                                        prefixed=True)
 
532
 
 
533
    def _get_text_store(self, transport, control_files):
 
534
        """See RepositoryFormat._get_text_store()."""
 
535
        return self._get_versioned_file_store('weaves', transport, control_files)
 
536
 
 
537
class RepositoryFormat7(MetaDirRepositoryFormat):
 
538
    """Bzr repository 7.
 
539
 
 
540
    This repository format has:
 
541
     - weaves for file texts and inventory
 
542
     - hash subdirectory based stores.
 
543
     - TextStores for revisions and signatures.
 
544
     - a format marker of its own
 
545
     - an optional 'shared-storage' flag
 
546
     - an optional 'no-working-trees' flag
 
547
    """
 
548
 
 
549
    _versionedfile_class = weave.WeaveFile
 
550
    supports_ghosts = False
 
551
 
 
552
    def _get_control_store(self, repo_transport, control_files):
 
553
        """Return the control store for this repository."""
 
554
        return self._get_versioned_file_store('',
 
555
                                              repo_transport,
 
556
                                              control_files,
 
557
                                              prefixed=False)
 
558
 
 
559
    def get_format_string(self):
 
560
        """See RepositoryFormat.get_format_string()."""
 
561
        return "Bazaar-NG Repository format 7"
 
562
 
 
563
    def get_format_description(self):
 
564
        """See RepositoryFormat.get_format_description()."""
 
565
        return "Weave repository format 7"
 
566
 
 
567
    def check_conversion_target(self, target_format):
 
568
        pass
 
569
 
 
570
    def _get_revision_store(self, repo_transport, control_files):
 
571
        """See RepositoryFormat._get_revision_store()."""
 
572
        return self._get_text_rev_store(repo_transport,
 
573
                                        control_files,
 
574
                                        'revision-store',
 
575
                                        compressed=False,
 
576
                                        prefixed=True,
 
577
                                        )
 
578
 
 
579
    def _get_text_store(self, transport, control_files):
 
580
        """See RepositoryFormat._get_text_store()."""
 
581
        return self._get_versioned_file_store('weaves',
 
582
                                              transport,
 
583
                                              control_files)
 
584
 
 
585
    def initialize(self, a_bzrdir, shared=False):
 
586
        """Create a weave repository.
 
587
 
 
588
        :param shared: If true the repository will be initialized as a shared
 
589
                       repository.
 
590
        """
 
591
        # Create an empty weave
 
592
        sio = StringIO()
 
593
        weavefile.write_weave_v5(weave.Weave(), sio)
 
594
        empty_weave = sio.getvalue()
 
595
 
 
596
        mutter('creating repository in %s.', a_bzrdir.transport.base)
 
597
        dirs = ['revision-store', 'weaves']
 
598
        files = [('inventory.weave', StringIO(empty_weave)), 
 
599
                 ]
 
600
        utf8_files = [('format', self.get_format_string())]
 
601
 
 
602
        self._upload_blank_content(a_bzrdir, dirs, files, utf8_files, shared)
 
603
        return self.open(a_bzrdir=a_bzrdir, _found=True)
 
604
 
 
605
    def open(self, a_bzrdir, _found=False, _override_transport=None):
 
606
        """See RepositoryFormat.open().
 
607
        
 
608
        :param _override_transport: INTERNAL USE ONLY. Allows opening the
 
609
                                    repository at a slightly different url
 
610
                                    than normal. I.e. during 'upgrade'.
 
611
        """
 
612
        if not _found:
 
613
            format = RepositoryFormat.find_format(a_bzrdir)
 
614
            assert format.__class__ ==  self.__class__
 
615
        if _override_transport is not None:
 
616
            repo_transport = _override_transport
 
617
        else:
 
618
            repo_transport = a_bzrdir.get_repository_transport(None)
 
619
        control_files = lockable_files.LockableFiles(repo_transport,
 
620
                                'lock', lockdir.LockDir)
 
621
        text_store = self._get_text_store(repo_transport, control_files)
 
622
        control_store = self._get_control_store(repo_transport, control_files)
 
623
        _revision_store = self._get_revision_store(repo_transport, control_files)
 
624
        return WeaveMetaDirRepository(_format=self,
 
625
            a_bzrdir=a_bzrdir,
 
626
            control_files=control_files,
 
627
            _revision_store=_revision_store,
 
628
            control_store=control_store,
 
629
            text_store=text_store)
 
630
 
 
631
 
 
632
class WeaveCommitBuilder(CommitBuilder):
 
633
    """A builder for weave based repos that don't support ghosts."""
 
634
 
 
635
    def _add_text_to_weave(self, file_id, new_lines, parents, nostore_sha):
 
636
        versionedfile = self.repository.weave_store.get_weave_or_empty(
 
637
            file_id, self.repository.get_transaction())
 
638
        result = versionedfile.add_lines(
 
639
            self._new_revision_id, parents, new_lines,
 
640
            nostore_sha=nostore_sha)[0:2]
 
641
        versionedfile.clear_cache()
 
642
        return result
 
643
 
 
644
 
 
645
_legacy_formats = [RepositoryFormat4(),
 
646
                   RepositoryFormat5(),
 
647
                   RepositoryFormat6()]