/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
3350.6.10 by Martin Pool
VersionedFiles review cleanups
1
# Copyright (C) 2005, 2006, 2007, 2008 Canonical Ltd
2241.1.4 by Martin Pool
Moved old weave-based repository formats into bzrlib.repofmt.weaverepo.
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
2803.2.1 by Robert Collins
* CommitBuilder now advertises itself as requiring the root entry to be
17
"""Deprecated weave-based repository formats.
2241.1.4 by Martin Pool
Moved old weave-based repository formats into bzrlib.repofmt.weaverepo.
18
2803.2.1 by Robert Collins
* CommitBuilder now advertises itself as requiring the root entry to be
19
Weave based formats scaled linearly with history size and could not represent
20
ghosts.
21
"""
2241.1.4 by Martin Pool
Moved old weave-based repository formats into bzrlib.repofmt.weaverepo.
22
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
23
import os
24
from cStringIO import StringIO
25
import urllib
2241.1.4 by Martin Pool
Moved old weave-based repository formats into bzrlib.repofmt.weaverepo.
26
27
from bzrlib import (
28
    bzrdir,
2850.3.1 by Robert Collins
Move various weave specific code out of the base Repository class to weaverepo.py.
29
    debug,
30
    errors,
2241.1.4 by Martin Pool
Moved old weave-based repository formats into bzrlib.repofmt.weaverepo.
31
    lockable_files,
32
    lockdir,
2803.2.1 by Robert Collins
* CommitBuilder now advertises itself as requiring the root entry to be
33
    osutils,
2850.3.1 by Robert Collins
Move various weave specific code out of the base Repository class to weaverepo.py.
34
    revision as _mod_revision,
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
35
    versionedfile,
2241.1.4 by Martin Pool
Moved old weave-based repository formats into bzrlib.repofmt.weaverepo.
36
    weave,
37
    weavefile,
2241.1.8 by Martin Pool
Set the repository's serializer in the places it's needed, not in the base class
38
    xml5,
2241.1.4 by Martin Pool
Moved old weave-based repository formats into bzrlib.repofmt.weaverepo.
39
    )
40
from bzrlib.decorators import needs_read_lock, needs_write_lock
41
from bzrlib.repository import (
2803.2.1 by Robert Collins
* CommitBuilder now advertises itself as requiring the root entry to be
42
    CommitBuilder,
3316.2.3 by Robert Collins
Remove manual notification of transaction finishing on versioned files.
43
    MetaDirVersionedFileRepository,
2241.1.4 by Martin Pool
Moved old weave-based repository formats into bzrlib.repofmt.weaverepo.
44
    MetaDirRepositoryFormat,
45
    Repository,
46
    RepositoryFormat,
47
    )
48
from bzrlib.store.text import TextStore
49
from bzrlib.trace import mutter
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
50
from bzrlib.tuned_gzip import GzipFile, bytes_to_gzip
51
from bzrlib.versionedfile import (
52
    AbsentContentFactory,
53
    FulltextContentFactory,
54
    VersionedFiles,
55
    )
2241.1.4 by Martin Pool
Moved old weave-based repository formats into bzrlib.repofmt.weaverepo.
56
57
58
class AllInOneRepository(Repository):
59
    """Legacy support - the repository behaviour for all-in-one branches."""
60
2241.1.8 by Martin Pool
Set the repository's serializer in the places it's needed, not in the base class
61
    _serializer = xml5.serializer_v5
62
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
63
    def __init__(self, _format, a_bzrdir):
2241.1.4 by Martin Pool
Moved old weave-based repository formats into bzrlib.repofmt.weaverepo.
64
        # we reuse one control files instance.
3416.2.3 by Martin Pool
typo
65
        dir_mode = a_bzrdir._get_dir_mode()
66
        file_mode = a_bzrdir._get_file_mode()
2241.1.4 by Martin Pool
Moved old weave-based repository formats into bzrlib.repofmt.weaverepo.
67
68
        def get_store(name, compressed=True, prefixed=False):
69
            # FIXME: This approach of assuming stores are all entirely compressed
70
            # or entirely uncompressed is tidy, but breaks upgrade from 
71
            # some existing branches where there's a mixture; we probably 
72
            # still want the option to look for both.
73
            relpath = a_bzrdir._control_files._escape(name)
3407.2.13 by Martin Pool
Remove indirection through control_files to get transports
74
            store = TextStore(a_bzrdir.transport.clone(relpath),
2241.1.4 by Martin Pool
Moved old weave-based repository formats into bzrlib.repofmt.weaverepo.
75
                              prefixed=prefixed, compressed=compressed,
76
                              dir_mode=dir_mode,
77
                              file_mode=file_mode)
78
            return store
79
80
        # not broken out yet because the controlweaves|inventory_store
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
81
        # and texts bits are still different.
2241.1.4 by Martin Pool
Moved old weave-based repository formats into bzrlib.repofmt.weaverepo.
82
        if isinstance(_format, RepositoryFormat4):
83
            # cannot remove these - there is still no consistent api 
84
            # which allows access to this old info.
85
            self.inventory_store = get_store('inventory-store')
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
86
            self._text_store = get_store('text-store')
87
        super(AllInOneRepository, self).__init__(_format, a_bzrdir, a_bzrdir._control_files)
2241.1.4 by Martin Pool
Moved old weave-based repository formats into bzrlib.repofmt.weaverepo.
88
2850.3.1 by Robert Collins
Move various weave specific code out of the base Repository class to weaverepo.py.
89
    @needs_read_lock
90
    def _all_possible_ids(self):
91
        """Return all the possible revisions that we could find."""
92
        if 'evil' in debug.debug_flags:
93
            mutter_callsite(3, "_all_possible_ids scales with size of history.")
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
94
        return [key[-1] for key in self.inventories.keys()]
2850.3.1 by Robert Collins
Move various weave specific code out of the base Repository class to weaverepo.py.
95
96
    @needs_read_lock
97
    def _all_revision_ids(self):
98
        """Returns a list of all the revision ids in the repository. 
99
100
        These are in as much topological order as the underlying store can 
101
        present: for weaves ghosts may lead to a lack of correctness until
102
        the reweave updates the parents list.
103
        """
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
104
        return [key[-1] for key in self.revisions.keys()]
105
106
    def _activate_new_inventory(self):
107
        """Put a replacement inventory.new into use as inventories."""
108
        # Copy the content across
109
        t = self.bzrdir._control_files._transport
110
        t.copy('inventory.new.weave', 'inventory.weave')
111
        # delete the temp inventory
112
        t.delete('inventory.new.weave')
113
        # Check we can parse the new weave properly as a sanity check
114
        self.inventories.keys()
115
116
    def _backup_inventory(self):
117
        t = self.bzrdir._control_files._transport
118
        t.copy('inventory.weave', 'inventory.backup.weave')
119
120
    def _temp_inventories(self):
121
        t = self.bzrdir._control_files._transport
122
        return self._format._get_inventories(t, self, 'inventory.new')
2850.3.1 by Robert Collins
Move various weave specific code out of the base Repository class to weaverepo.py.
123
2241.1.4 by Martin Pool
Moved old weave-based repository formats into bzrlib.repofmt.weaverepo.
124
    def get_commit_builder(self, branch, parents, config, timestamp=None,
125
                           timezone=None, committer=None, revprops=None,
126
                           revision_id=None):
127
        self._check_ascii_revisionid(revision_id, self.get_commit_builder)
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
128
        result = CommitBuilder(self, parents, config, timestamp, timezone,
2803.2.1 by Robert Collins
* CommitBuilder now advertises itself as requiring the root entry to be
129
                              committer, revprops, revision_id)
130
        self.start_write_group()
131
        return result
2241.1.4 by Martin Pool
Moved old weave-based repository formats into bzrlib.repofmt.weaverepo.
132
133
    @needs_read_lock
2850.3.1 by Robert Collins
Move various weave specific code out of the base Repository class to weaverepo.py.
134
    def get_revisions(self, revision_ids):
135
        revs = self._get_revisions(revision_ids)
136
        return revs
137
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
138
    def _inventory_add_lines(self, revision_id, parents, lines,
139
        check_content=True):
140
        """Store lines in inv_vf and return the sha1 of the inventory."""
141
        present_parents = self.get_graph().get_parent_map(parents)
142
        final_parents = []
143
        for parent in parents:
144
            if parent in present_parents:
145
                final_parents.append((parent,))
146
        return self.inventories.add_lines((revision_id,), final_parents, lines,
147
            check_content=check_content)[0]
3172.3.1 by Robert Collins
Repository has a new method ``has_revisions`` which signals the presence
148
2850.3.1 by Robert Collins
Move various weave specific code out of the base Repository class to weaverepo.py.
149
    @needs_read_lock
2241.1.4 by Martin Pool
Moved old weave-based repository formats into bzrlib.repofmt.weaverepo.
150
    def is_shared(self):
151
        """AllInOne repositories cannot be shared."""
152
        return False
153
154
    @needs_write_lock
155
    def set_make_working_trees(self, new_value):
156
        """Set the policy flag for making working trees when creating branches.
157
158
        This only applies to branches that use this repository.
159
160
        The default is 'True'.
161
        :param new_value: True to restore the default, False to disable making
162
                          working trees.
163
        """
3349.1.2 by Aaron Bentley
Change ValueError to RepositoryUpgradeRequired
164
        raise errors.RepositoryUpgradeRequired(self.bzrdir.root_transport.base)
3349.1.1 by Aaron Bentley
Enable setting and getting make_working_trees for all repositories
165
2241.1.4 by Martin Pool
Moved old weave-based repository formats into bzrlib.repofmt.weaverepo.
166
    def make_working_trees(self):
167
        """Returns the policy for making working trees on new branches."""
168
        return True
169
2819.2.4 by Andrew Bennetts
Add a 'revision_graph_can_have_wrong_parents' method to repository.
170
    def revision_graph_can_have_wrong_parents(self):
171
        # XXX: This is an old format that we don't support full checking on, so
172
        # just claim that checking for this inconsistency is not required.
173
        return False
174
2241.1.4 by Martin Pool
Moved old weave-based repository formats into bzrlib.repofmt.weaverepo.
175
3316.2.3 by Robert Collins
Remove manual notification of transaction finishing on versioned files.
176
class WeaveMetaDirRepository(MetaDirVersionedFileRepository):
2241.1.4 by Martin Pool
Moved old weave-based repository formats into bzrlib.repofmt.weaverepo.
177
    """A subclass of MetaDirRepository to set weave specific policy."""
178
2241.1.8 by Martin Pool
Set the repository's serializer in the places it's needed, not in the base class
179
    _serializer = xml5.serializer_v5
180
2850.3.1 by Robert Collins
Move various weave specific code out of the base Repository class to weaverepo.py.
181
    @needs_read_lock
182
    def _all_possible_ids(self):
183
        """Return all the possible revisions that we could find."""
184
        if 'evil' in debug.debug_flags:
185
            mutter_callsite(3, "_all_possible_ids scales with size of history.")
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
186
        return [key[-1] for key in self.inventories.keys()]
2850.3.1 by Robert Collins
Move various weave specific code out of the base Repository class to weaverepo.py.
187
188
    @needs_read_lock
189
    def _all_revision_ids(self):
190
        """Returns a list of all the revision ids in the repository. 
191
192
        These are in as much topological order as the underlying store can 
193
        present: for weaves ghosts may lead to a lack of correctness until
194
        the reweave updates the parents list.
195
        """
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
196
        return [key[-1] for key in self.revisions.keys()]
197
198
    def _activate_new_inventory(self):
199
        """Put a replacement inventory.new into use as inventories."""
200
        # Copy the content across
201
        t = self._transport
202
        t.copy('inventory.new.weave', 'inventory.weave')
203
        # delete the temp inventory
204
        t.delete('inventory.new.weave')
205
        # Check we can parse the new weave properly as a sanity check
206
        self.inventories.keys()
207
208
    def _backup_inventory(self):
209
        t = self._transport
210
        t.copy('inventory.weave', 'inventory.backup.weave')
211
212
    def _temp_inventories(self):
213
        t = self._transport
214
        return self._format._get_inventories(t, self, 'inventory.new')
2850.3.1 by Robert Collins
Move various weave specific code out of the base Repository class to weaverepo.py.
215
2241.1.4 by Martin Pool
Moved old weave-based repository formats into bzrlib.repofmt.weaverepo.
216
    def get_commit_builder(self, branch, parents, config, timestamp=None,
217
                           timezone=None, committer=None, revprops=None,
218
                           revision_id=None):
219
        self._check_ascii_revisionid(revision_id, self.get_commit_builder)
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
220
        result = CommitBuilder(self, parents, config, timestamp, timezone,
2803.2.1 by Robert Collins
* CommitBuilder now advertises itself as requiring the root entry to be
221
                              committer, revprops, revision_id)
222
        self.start_write_group()
223
        return result
2241.1.4 by Martin Pool
Moved old weave-based repository formats into bzrlib.repofmt.weaverepo.
224
2850.3.1 by Robert Collins
Move various weave specific code out of the base Repository class to weaverepo.py.
225
    @needs_read_lock
226
    def get_revision(self, revision_id):
227
        """Return the Revision object for a named revision"""
228
        r = self.get_revision_reconcile(revision_id)
229
        return r
230
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
231
    def _inventory_add_lines(self, revision_id, parents, lines,
232
        check_content=True):
233
        """Store lines in inv_vf and return the sha1 of the inventory."""
234
        present_parents = self.get_graph().get_parent_map(parents)
235
        final_parents = []
236
        for parent in parents:
237
            if parent in present_parents:
238
                final_parents.append((parent,))
239
        return self.inventories.add_lines((revision_id,), final_parents, lines,
240
            check_content=check_content)[0]
3172.3.1 by Robert Collins
Repository has a new method ``has_revisions`` which signals the presence
241
2819.2.4 by Andrew Bennetts
Add a 'revision_graph_can_have_wrong_parents' method to repository.
242
    def revision_graph_can_have_wrong_parents(self):
243
        return False
244
2241.1.4 by Martin Pool
Moved old weave-based repository formats into bzrlib.repofmt.weaverepo.
245
246
class PreSplitOutRepositoryFormat(RepositoryFormat):
247
    """Base class for the pre split out repository formats."""
248
249
    rich_root_data = False
2323.5.17 by Martin Pool
Add supports_tree_reference to all repo formats (robert)
250
    supports_tree_reference = False
2949.1.2 by Robert Collins
* Fetch with pack repositories will no longer read the entire history graph.
251
    supports_ghosts = False
3221.3.1 by Robert Collins
* Repository formats have a new supported-feature attribute
252
    supports_external_lookups = False
2241.1.4 by Martin Pool
Moved old weave-based repository formats into bzrlib.repofmt.weaverepo.
253
254
    def initialize(self, a_bzrdir, shared=False, _internal=False):
2949.1.2 by Robert Collins
* Fetch with pack repositories will no longer read the entire history graph.
255
        """Create a weave repository."""
2241.1.4 by Martin Pool
Moved old weave-based repository formats into bzrlib.repofmt.weaverepo.
256
        if shared:
257
            raise errors.IncompatibleFormat(self, a_bzrdir._format)
258
259
        if not _internal:
260
            # always initialized when the bzrdir is.
261
            return self.open(a_bzrdir, _found=True)
262
        
263
        # Create an empty weave
264
        sio = StringIO()
265
        weavefile.write_weave_v5(weave.Weave(), sio)
266
        empty_weave = sio.getvalue()
267
268
        mutter('creating repository in %s.', a_bzrdir.transport.base)
269
        
270
        # FIXME: RBC 20060125 don't peek under the covers
271
        # NB: no need to escape relative paths that are url safe.
272
        control_files = lockable_files.LockableFiles(a_bzrdir.transport,
3407.2.4 by Martin Pool
Small cleanups to initial creation of repository files
273
            'branch-lock', lockable_files.TransportLock)
2241.1.4 by Martin Pool
Moved old weave-based repository formats into bzrlib.repofmt.weaverepo.
274
        control_files.create_lock()
275
        control_files.lock_write()
3407.2.13 by Martin Pool
Remove indirection through control_files to get transports
276
        transport = a_bzrdir.transport
3407.2.4 by Martin Pool
Small cleanups to initial creation of repository files
277
        try:
278
            transport.mkdir_multi(['revision-store', 'weaves'],
3446.1.1 by Martin Pool
merge further LockableFile deprecations
279
                mode=a_bzrdir._get_dir_mode())
3407.2.4 by Martin Pool
Small cleanups to initial creation of repository files
280
            transport.put_bytes_non_atomic('inventory.weave', empty_weave)
2241.1.4 by Martin Pool
Moved old weave-based repository formats into bzrlib.repofmt.weaverepo.
281
        finally:
282
            control_files.unlock()
283
        return self.open(a_bzrdir, _found=True)
284
285
    def open(self, a_bzrdir, _found=False):
286
        """See RepositoryFormat.open()."""
287
        if not _found:
288
            # we are being called directly and must probe.
289
            raise NotImplementedError
290
291
        repo_transport = a_bzrdir.get_repository_transport(None)
292
        control_files = a_bzrdir._control_files
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
293
        result = AllInOneRepository(_format=self, a_bzrdir=a_bzrdir)
294
        result.revisions = self._get_revisions(repo_transport, result)
295
        result.signatures = self._get_signatures(repo_transport, result)
296
        result.inventories = self._get_inventories(repo_transport, result)
297
        result.texts = self._get_texts(repo_transport, result)
298
        return result
2241.1.4 by Martin Pool
Moved old weave-based repository formats into bzrlib.repofmt.weaverepo.
299
300
    def check_conversion_target(self, target_format):
301
        pass
302
303
304
class RepositoryFormat4(PreSplitOutRepositoryFormat):
305
    """Bzr repository format 4.
306
307
    This repository format has:
308
     - flat stores
309
     - TextStores for texts, inventories,revisions.
310
311
    This format is deprecated: it indexes texts using a text id which is
312
    removed in format 5; initialization and write support for this format
313
    has been removed.
314
    """
315
2241.1.11 by Martin Pool
Get rid of RepositoryFormat*_instance objects. Instead the format
316
    _matchingbzrdir = bzrdir.BzrDirFormat4()
317
2241.1.4 by Martin Pool
Moved old weave-based repository formats into bzrlib.repofmt.weaverepo.
318
    def __init__(self):
319
        super(RepositoryFormat4, self).__init__()
320
321
    def get_format_description(self):
322
        """See RepositoryFormat.get_format_description()."""
323
        return "Repository format 4"
324
325
    def initialize(self, url, shared=False, _internal=False):
326
        """Format 4 branches cannot be created."""
327
        raise errors.UninitializableFormat(self)
328
329
    def is_supported(self):
330
        """Format 4 is not supported.
331
332
        It is not supported because the model changed from 4 to 5 and the
333
        conversion logic is expensive - so doing it on the fly was not 
334
        feasible.
335
        """
336
        return False
337
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
338
    def _get_inventories(self, repo_transport, repo, name='inventory'):
339
        # No inventories store written so far.
2241.1.4 by Martin Pool
Moved old weave-based repository formats into bzrlib.repofmt.weaverepo.
340
        return None
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
341
342
    def _get_revisions(self, repo_transport, repo):
2241.1.4 by Martin Pool
Moved old weave-based repository formats into bzrlib.repofmt.weaverepo.
343
        from bzrlib.xml4 import serializer_v4
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
344
        return RevisionTextStore(repo_transport.clone('revision-store'),
345
            serializer_v4, True, versionedfile.PrefixMapper(),
346
            repo.is_locked, repo.is_write_locked)
347
348
    def _get_signatures(self, repo_transport, repo):
349
        return SignatureTextStore(repo_transport.clone('revision-store'),
350
            False, versionedfile.PrefixMapper(),
351
            repo.is_locked, repo.is_write_locked)
352
353
    def _get_texts(self, repo_transport, repo):
354
        return None
2241.1.4 by Martin Pool
Moved old weave-based repository formats into bzrlib.repofmt.weaverepo.
355
356
357
class RepositoryFormat5(PreSplitOutRepositoryFormat):
358
    """Bzr control format 5.
359
360
    This repository format has:
361
     - weaves for file texts and inventory
362
     - flat stores
363
     - TextStores for revisions and signatures.
364
    """
365
2241.1.10 by Martin Pool
Remove more references to weaves from the repository.py file
366
    _versionedfile_class = weave.WeaveFile
2241.1.11 by Martin Pool
Get rid of RepositoryFormat*_instance objects. Instead the format
367
    _matchingbzrdir = bzrdir.BzrDirFormat5()
2241.1.10 by Martin Pool
Remove more references to weaves from the repository.py file
368
2241.1.4 by Martin Pool
Moved old weave-based repository formats into bzrlib.repofmt.weaverepo.
369
    def __init__(self):
370
        super(RepositoryFormat5, self).__init__()
371
372
    def get_format_description(self):
373
        """See RepositoryFormat.get_format_description()."""
374
        return "Weave repository format 5"
375
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
376
    def _get_inventories(self, repo_transport, repo, name='inventory'):
377
        mapper = versionedfile.ConstantMapper(name)
378
        return versionedfile.ThunkedVersionedFiles(repo_transport,
379
            weave.WeaveFile, mapper, repo.is_locked)
380
381
    def _get_revisions(self, repo_transport, repo):
382
        from bzrlib.xml5 import serializer_v5
383
        return RevisionTextStore(repo_transport.clone('revision-store'),
384
            serializer_v5, False, versionedfile.PrefixMapper(),
385
            repo.is_locked, repo.is_write_locked)
386
387
    def _get_signatures(self, repo_transport, repo):
388
        return SignatureTextStore(repo_transport.clone('revision-store'),
389
            False, versionedfile.PrefixMapper(),
390
            repo.is_locked, repo.is_write_locked)
391
392
    def _get_texts(self, repo_transport, repo):
393
        mapper = versionedfile.PrefixMapper()
394
        base_transport = repo_transport.clone('weaves')
395
        return versionedfile.ThunkedVersionedFiles(base_transport,
396
            weave.WeaveFile, mapper, repo.is_locked)
2241.1.4 by Martin Pool
Moved old weave-based repository formats into bzrlib.repofmt.weaverepo.
397
398
399
class RepositoryFormat6(PreSplitOutRepositoryFormat):
400
    """Bzr control format 6.
401
402
    This repository format has:
403
     - weaves for file texts and inventory
404
     - hash subdirectory based stores.
405
     - TextStores for revisions and signatures.
406
    """
407
2241.1.10 by Martin Pool
Remove more references to weaves from the repository.py file
408
    _versionedfile_class = weave.WeaveFile
2241.1.11 by Martin Pool
Get rid of RepositoryFormat*_instance objects. Instead the format
409
    _matchingbzrdir = bzrdir.BzrDirFormat6()
2241.1.10 by Martin Pool
Remove more references to weaves from the repository.py file
410
2241.1.4 by Martin Pool
Moved old weave-based repository formats into bzrlib.repofmt.weaverepo.
411
    def __init__(self):
412
        super(RepositoryFormat6, self).__init__()
413
414
    def get_format_description(self):
415
        """See RepositoryFormat.get_format_description()."""
416
        return "Weave repository format 6"
417
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
418
    def _get_inventories(self, repo_transport, repo, name='inventory'):
419
        mapper = versionedfile.ConstantMapper(name)
420
        return versionedfile.ThunkedVersionedFiles(repo_transport,
421
            weave.WeaveFile, mapper, repo.is_locked)
422
423
    def _get_revisions(self, repo_transport, repo):
424
        from bzrlib.xml5 import serializer_v5
425
        return RevisionTextStore(repo_transport.clone('revision-store'),
426
            serializer_v5, False, versionedfile.HashPrefixMapper(),
427
            repo.is_locked, repo.is_write_locked)
428
429
    def _get_signatures(self, repo_transport, repo):
430
        return SignatureTextStore(repo_transport.clone('revision-store'),
431
            False, versionedfile.HashPrefixMapper(),
432
            repo.is_locked, repo.is_write_locked)
433
434
    def _get_texts(self, repo_transport, repo):
435
        mapper = versionedfile.HashPrefixMapper()
436
        base_transport = repo_transport.clone('weaves')
437
        return versionedfile.ThunkedVersionedFiles(base_transport,
438
            weave.WeaveFile, mapper, repo.is_locked)
439
2241.1.4 by Martin Pool
Moved old weave-based repository formats into bzrlib.repofmt.weaverepo.
440
441
class RepositoryFormat7(MetaDirRepositoryFormat):
442
    """Bzr repository 7.
443
444
    This repository format has:
445
     - weaves for file texts and inventory
446
     - hash subdirectory based stores.
447
     - TextStores for revisions and signatures.
448
     - a format marker of its own
449
     - an optional 'shared-storage' flag
450
     - an optional 'no-working-trees' flag
451
    """
452
2241.1.10 by Martin Pool
Remove more references to weaves from the repository.py file
453
    _versionedfile_class = weave.WeaveFile
2949.1.2 by Robert Collins
* Fetch with pack repositories will no longer read the entire history graph.
454
    supports_ghosts = False
2241.1.10 by Martin Pool
Remove more references to weaves from the repository.py file
455
2241.1.4 by Martin Pool
Moved old weave-based repository formats into bzrlib.repofmt.weaverepo.
456
    def get_format_string(self):
457
        """See RepositoryFormat.get_format_string()."""
458
        return "Bazaar-NG Repository format 7"
459
460
    def get_format_description(self):
461
        """See RepositoryFormat.get_format_description()."""
462
        return "Weave repository format 7"
463
464
    def check_conversion_target(self, target_format):
465
        pass
466
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
467
    def _get_inventories(self, repo_transport, repo, name='inventory'):
468
        mapper = versionedfile.ConstantMapper(name)
469
        return versionedfile.ThunkedVersionedFiles(repo_transport,
470
            weave.WeaveFile, mapper, repo.is_locked)
471
472
    def _get_revisions(self, repo_transport, repo):
473
        from bzrlib.xml5 import serializer_v5
474
        return RevisionTextStore(repo_transport.clone('revision-store'),
475
            serializer_v5, True, versionedfile.HashPrefixMapper(),
476
            repo.is_locked, repo.is_write_locked)
477
478
    def _get_signatures(self, repo_transport, repo):
479
        return SignatureTextStore(repo_transport.clone('revision-store'),
480
            True, versionedfile.HashPrefixMapper(),
481
            repo.is_locked, repo.is_write_locked)
482
483
    def _get_texts(self, repo_transport, repo):
484
        mapper = versionedfile.HashPrefixMapper()
485
        base_transport = repo_transport.clone('weaves')
486
        return versionedfile.ThunkedVersionedFiles(base_transport,
487
            weave.WeaveFile, mapper, repo.is_locked)
2241.1.4 by Martin Pool
Moved old weave-based repository formats into bzrlib.repofmt.weaverepo.
488
489
    def initialize(self, a_bzrdir, shared=False):
490
        """Create a weave repository.
491
492
        :param shared: If true the repository will be initialized as a shared
493
                       repository.
494
        """
495
        # Create an empty weave
496
        sio = StringIO()
497
        weavefile.write_weave_v5(weave.Weave(), sio)
498
        empty_weave = sio.getvalue()
499
500
        mutter('creating repository in %s.', a_bzrdir.transport.base)
501
        dirs = ['revision-store', 'weaves']
502
        files = [('inventory.weave', StringIO(empty_weave)), 
503
                 ]
504
        utf8_files = [('format', self.get_format_string())]
505
 
506
        self._upload_blank_content(a_bzrdir, dirs, files, utf8_files, shared)
507
        return self.open(a_bzrdir=a_bzrdir, _found=True)
508
509
    def open(self, a_bzrdir, _found=False, _override_transport=None):
510
        """See RepositoryFormat.open().
511
        
512
        :param _override_transport: INTERNAL USE ONLY. Allows opening the
513
                                    repository at a slightly different url
514
                                    than normal. I.e. during 'upgrade'.
515
        """
516
        if not _found:
517
            format = RepositoryFormat.find_format(a_bzrdir)
518
        if _override_transport is not None:
519
            repo_transport = _override_transport
520
        else:
521
            repo_transport = a_bzrdir.get_repository_transport(None)
522
        control_files = lockable_files.LockableFiles(repo_transport,
523
                                'lock', lockdir.LockDir)
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
524
        result = WeaveMetaDirRepository(_format=self, a_bzrdir=a_bzrdir,
525
            control_files=control_files)
526
        result.revisions = self._get_revisions(repo_transport, result)
527
        result.signatures = self._get_signatures(repo_transport, result)
528
        result.inventories = self._get_inventories(repo_transport, result)
529
        result.texts = self._get_texts(repo_transport, result)
530
        result._transport = repo_transport
531
        return result
532
533
534
class TextVersionedFiles(VersionedFiles):
535
    """Just-a-bunch-of-files based VersionedFile stores."""
536
537
    def __init__(self, transport, compressed, mapper, is_locked, can_write):
538
        self._compressed = compressed
539
        self._transport = transport
540
        self._mapper = mapper
541
        if self._compressed:
542
            self._ext = '.gz'
543
        else:
544
            self._ext = ''
545
        self._is_locked = is_locked
546
        self._can_write = can_write
547
548
    def add_lines(self, key, parents, lines):
549
        """Add a revision to the store."""
550
        if not self._is_locked():
551
            raise errors.ObjectNotLocked(self)
552
        if not self._can_write():
553
            raise errors.ReadOnlyError(self)
554
        if '/' in key[-1]:
3350.6.10 by Martin Pool
VersionedFiles review cleanups
555
            raise ValueError('bad idea to put / in %r' % (key,))
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
556
        text = ''.join(lines)
557
        if self._compressed:
558
            text = bytes_to_gzip(text)
559
        path = self._map(key)
560
        self._transport.put_bytes_non_atomic(path, text, create_parent_dir=True)
561
562
    def insert_record_stream(self, stream):
563
        adapters = {}
564
        for record in stream:
565
            # Raise an error when a record is missing.
566
            if record.storage_kind == 'absent':
567
                raise errors.RevisionNotPresent([record.key[0]], self)
568
            # adapt to non-tuple interface
569
            if record.storage_kind == 'fulltext':
570
                self.add_lines(record.key, None,
571
                    osutils.split_lines(record.get_bytes_as('fulltext')))
572
            else:
573
                adapter_key = record.storage_kind, 'fulltext'
574
                try:
575
                    adapter = adapters[adapter_key]
576
                except KeyError:
577
                    adapter_factory = adapter_registry.get(adapter_key)
578
                    adapter = adapter_factory(self)
579
                    adapters[adapter_key] = adapter
580
                lines = osutils.split_lines(adapter.get_bytes(
581
                    record, record.get_bytes_as(record.storage_kind)))
582
                try:
583
                    self.add_lines(record.key, None, lines)
584
                except RevisionAlreadyPresent:
585
                    pass
586
587
    def _load_text(self, key):
588
        if not self._is_locked():
589
            raise errors.ObjectNotLocked(self)
590
        path = self._map(key)
591
        try:
592
            text = self._transport.get_bytes(path)
593
            compressed = self._compressed
594
        except errors.NoSuchFile:
595
            if self._compressed:
596
                # try without the .gz
597
                path = path[:-3]
598
                try:
599
                    text = self._transport.get_bytes(path)
600
                    compressed = False
601
                except errors.NoSuchFile:
602
                    return None
603
            else:
604
                return None
605
        if compressed:
606
            text = GzipFile(mode='rb', fileobj=StringIO(text)).read()
607
        return text
608
609
    def _map(self, key):
610
        return self._mapper.map(key) + self._ext
611
612
613
class RevisionTextStore(TextVersionedFiles):
614
    """Legacy thunk for format 4 repositories."""
615
616
    def __init__(self, transport, serializer, compressed, mapper, is_locked,
617
        can_write):
618
        """Create a RevisionTextStore at transport with serializer."""
619
        TextVersionedFiles.__init__(self, transport, compressed, mapper,
620
            is_locked, can_write)
621
        self._serializer = serializer
622
623
    def _load_text_parents(self, key):
624
        text = self._load_text(key)
625
        if text is None:
626
            return None, None
627
        parents = self._serializer.read_revision_from_string(text).parent_ids
628
        return text, tuple((parent,) for parent in parents)
629
630
    def get_parent_map(self, keys):
631
        result = {}
632
        for key in keys:
633
            parents = self._load_text_parents(key)[1]
634
            if parents is None:
635
                continue
636
            result[key] = parents
637
        return result
638
    
639
    def get_record_stream(self, keys, sort_order, include_delta_closure):
640
        for key in keys:
641
            text, parents = self._load_text_parents(key)
642
            if text is None:
643
                yield AbsentContentFactory(key)
644
            else:
645
                yield FulltextContentFactory(key, parents, None, text)
646
647
    def keys(self):
648
        if not self._is_locked():
649
            raise errors.ObjectNotLocked(self)
650
        relpaths = set()
651
        for quoted_relpath in self._transport.iter_files_recursive():
652
            relpath = urllib.unquote(quoted_relpath)
653
            path, ext = os.path.splitext(relpath)
654
            if ext == '.gz':
655
                relpath = path
656
            if '.sig' not in relpath:
657
                relpaths.add(relpath)
658
        paths = list(relpaths)
659
        return set([self._mapper.unmap(path) for path in paths])
660
661
662
class SignatureTextStore(TextVersionedFiles):
663
    """Legacy thunk for format 4-7 repositories."""
664
665
    def __init__(self, transport, compressed, mapper, is_locked, can_write):
666
        TextVersionedFiles.__init__(self, transport, compressed, mapper,
667
            is_locked, can_write)
668
        self._ext = '.sig' + self._ext
669
670
    def get_parent_map(self, keys):
671
        result = {}
672
        for key in keys:
673
            text = self._load_text(key)
674
            if text is None:
675
                continue
676
            result[key] = None
677
        return result
678
    
679
    def get_record_stream(self, keys, sort_order, include_delta_closure):
680
        for key in keys:
681
            text = self._load_text(key)
682
            if text is None:
683
                yield AbsentContentFactory(key)
684
            else:
685
                yield FulltextContentFactory(key, None, None, text)
686
687
    def keys(self):
688
        if not self._is_locked():
689
            raise errors.ObjectNotLocked(self)
690
        relpaths = set()
691
        for quoted_relpath in self._transport.iter_files_recursive():
692
            relpath = urllib.unquote(quoted_relpath)
693
            path, ext = os.path.splitext(relpath)
694
            if ext == '.gz':
695
                relpath = path
696
            if not relpath.endswith('.sig'):
697
                continue
698
            relpaths.add(relpath[:-4])
699
        paths = list(relpaths)
700
        return set([self._mapper.unmap(path) for path in paths])
2803.2.1 by Robert Collins
* CommitBuilder now advertises itself as requiring the root entry to be
701
2241.1.4 by Martin Pool
Moved old weave-based repository formats into bzrlib.repofmt.weaverepo.
702
_legacy_formats = [RepositoryFormat4(),
703
                   RepositoryFormat5(),
704
                   RepositoryFormat6()]