~bzr-pqm/bzr/bzr.dev

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