/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-02-19 03:03:42 UTC
  • mto: This revision was merged to the branch mainline in revision 3756.
  • Revision ID: andrew.bennetts@canonical.com-20080219030342-9j3uiaqgobh083qn
Don't import bzrlib.smart.medium from bzrlib.smart.server until it's needed.  This helps the bzr-dbus plugin import faster.

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