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