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