~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/repofmt/weaverepo.py

Streamline _walkdirs_utf8 for utf8 file systems, reducing time to traverse a mozilla tree from 1s to .6 seconds. (Robert Collins)

Show diffs side-by-side

added added

removed removed

Lines of Context:
12
12
#
13
13
# You should have received a copy of the GNU General Public License
14
14
# along with this program; if not, write to the Free Software
15
 
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16
16
 
17
17
"""Deprecated weave-based repository formats.
18
18
 
24
24
from cStringIO import StringIO
25
25
import urllib
26
26
 
27
 
from bzrlib.lazy_import import lazy_import
28
 
lazy_import(globals(), """
29
 
from bzrlib import (
30
 
    xml5,
31
 
    graph as _mod_graph,
32
 
    )
33
 
""")
34
27
from bzrlib import (
35
28
    bzrdir,
36
29
    debug,
39
32
    lockdir,
40
33
    osutils,
41
34
    revision as _mod_revision,
42
 
    urlutils,
43
35
    versionedfile,
44
36
    weave,
45
37
    weavefile,
 
38
    xml5,
46
39
    )
47
40
from bzrlib.decorators import needs_read_lock, needs_write_lock
48
41
from bzrlib.repository import (
65
58
class AllInOneRepository(Repository):
66
59
    """Legacy support - the repository behaviour for all-in-one branches."""
67
60
 
68
 
    @property
69
 
    def _serializer(self):
70
 
        return xml5.serializer_v5
71
 
 
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))
 
61
    _serializer = xml5.serializer_v5
78
62
 
79
63
    def __init__(self, _format, a_bzrdir):
80
64
        # we reuse one control files instance.
83
67
 
84
68
        def get_store(name, compressed=True, prefixed=False):
85
69
            # FIXME: This approach of assuming stores are all entirely compressed
86
 
            # or entirely uncompressed is tidy, but breaks upgrade from
87
 
            # some existing branches where there's a mixture; we probably
 
70
            # or entirely uncompressed is tidy, but breaks upgrade from 
 
71
            # some existing branches where there's a mixture; we probably 
88
72
            # still want the option to look for both.
89
 
            relpath = self._escape(name)
 
73
            relpath = a_bzrdir._control_files._escape(name)
90
74
            store = TextStore(a_bzrdir.transport.clone(relpath),
91
75
                              prefixed=prefixed, compressed=compressed,
92
76
                              dir_mode=dir_mode,
96
80
        # not broken out yet because the controlweaves|inventory_store
97
81
        # and texts bits are still different.
98
82
        if isinstance(_format, RepositoryFormat4):
99
 
            # cannot remove these - there is still no consistent api
 
83
            # cannot remove these - there is still no consistent api 
100
84
            # which allows access to this old info.
101
85
            self.inventory_store = get_store('inventory-store')
102
86
            self._text_store = get_store('text-store')
103
87
        super(AllInOneRepository, self).__init__(_format, a_bzrdir, a_bzrdir._control_files)
 
88
        self._fetch_order = 'topological'
 
89
        self._fetch_reconcile = True
104
90
 
105
91
    @needs_read_lock
106
92
    def _all_possible_ids(self):
111
97
 
112
98
    @needs_read_lock
113
99
    def _all_revision_ids(self):
114
 
        """Returns a list of all the revision ids in the repository.
 
100
        """Returns a list of all the revision ids in the repository. 
115
101
 
116
 
        These are in as much topological order as the underlying store can
 
102
        These are in as much topological order as the underlying store can 
117
103
        present: for weaves ghosts may lead to a lack of correctness until
118
104
        the reweave updates the parents list.
119
105
        """
191
177
class WeaveMetaDirRepository(MetaDirVersionedFileRepository):
192
178
    """A subclass of MetaDirRepository to set weave specific policy."""
193
179
 
 
180
    _serializer = xml5.serializer_v5
 
181
 
194
182
    def __init__(self, _format, a_bzrdir, control_files):
195
183
        super(WeaveMetaDirRepository, self).__init__(_format, a_bzrdir, control_files)
196
 
        self._serializer = _format._serializer
 
184
        self._fetch_order = 'topological'
 
185
        self._fetch_reconcile = True
197
186
 
198
187
    @needs_read_lock
199
188
    def _all_possible_ids(self):
204
193
 
205
194
    @needs_read_lock
206
195
    def _all_revision_ids(self):
207
 
        """Returns a list of all the revision ids in the repository.
 
196
        """Returns a list of all the revision ids in the repository. 
208
197
 
209
 
        These are in as much topological order as the underlying store can
 
198
        These are in as much topological order as the underlying store can 
210
199
        present: for weaves ghosts may lead to a lack of correctness until
211
200
        the reweave updates the parents list.
212
201
        """
267
256
    supports_tree_reference = False
268
257
    supports_ghosts = False
269
258
    supports_external_lookups = False
270
 
    supports_chks = False
271
 
    _fetch_order = 'topological'
272
 
    _fetch_reconcile = True
273
 
    fast_deltas = False
274
259
 
275
260
    def initialize(self, a_bzrdir, shared=False, _internal=False):
276
261
        """Create a weave repository."""
280
265
        if not _internal:
281
266
            # always initialized when the bzrdir is.
282
267
            return self.open(a_bzrdir, _found=True)
283
 
 
 
268
        
284
269
        # Create an empty weave
285
270
        sio = StringIO()
286
271
        weavefile.write_weave_v5(weave.Weave(), sio)
287
272
        empty_weave = sio.getvalue()
288
273
 
289
274
        mutter('creating repository in %s.', a_bzrdir.transport.base)
290
 
 
 
275
        
291
276
        # FIXME: RBC 20060125 don't peek under the covers
292
277
        # NB: no need to escape relative paths that are url safe.
293
278
        control_files = lockable_files.LockableFiles(a_bzrdir.transport,
298
283
        try:
299
284
            transport.mkdir_multi(['revision-store', 'weaves'],
300
285
                mode=a_bzrdir._get_dir_mode())
301
 
            transport.put_bytes_non_atomic('inventory.weave', empty_weave,
302
 
                mode=a_bzrdir._get_file_mode())
 
286
            transport.put_bytes_non_atomic('inventory.weave', empty_weave)
303
287
        finally:
304
288
            control_files.unlock()
305
289
        return self.open(a_bzrdir, _found=True)
317
301
        result.signatures = self._get_signatures(repo_transport, result)
318
302
        result.inventories = self._get_inventories(repo_transport, result)
319
303
        result.texts = self._get_texts(repo_transport, result)
320
 
        result.chk_bytes = None
321
304
        return result
322
305
 
 
306
    def check_conversion_target(self, target_format):
 
307
        pass
 
308
 
323
309
 
324
310
class RepositoryFormat4(PreSplitOutRepositoryFormat):
325
311
    """Bzr repository format 4.
335
321
 
336
322
    _matchingbzrdir = bzrdir.BzrDirFormat4()
337
323
 
 
324
    def __init__(self):
 
325
        super(RepositoryFormat4, self).__init__()
 
326
        self._fetch_order = 'topological'
 
327
        self._fetch_reconcile = True
 
328
 
338
329
    def get_format_description(self):
339
330
        """See RepositoryFormat.get_format_description()."""
340
331
        return "Repository format 4"
347
338
        """Format 4 is not supported.
348
339
 
349
340
        It is not supported because the model changed from 4 to 5 and the
350
 
        conversion logic is expensive - so doing it on the fly was not
 
341
        conversion logic is expensive - so doing it on the fly was not 
351
342
        feasible.
352
343
        """
353
344
        return False
382
373
 
383
374
    _versionedfile_class = weave.WeaveFile
384
375
    _matchingbzrdir = bzrdir.BzrDirFormat5()
385
 
    @property
386
 
    def _serializer(self):
387
 
        return xml5.serializer_v5
 
376
 
 
377
    def __init__(self):
 
378
        super(RepositoryFormat5, self).__init__()
 
379
        self._fetch_order = 'topological'
 
380
        self._fetch_reconcile = True
388
381
 
389
382
    def get_format_description(self):
390
383
        """See RepositoryFormat.get_format_description()."""
391
384
        return "Weave repository format 5"
392
385
 
393
 
    def network_name(self):
394
 
        """The network name for this format is the control dirs disk label."""
395
 
        return self._matchingbzrdir.get_format_string()
396
 
 
397
386
    def _get_inventories(self, repo_transport, repo, name='inventory'):
398
387
        mapper = versionedfile.ConstantMapper(name)
399
388
        return versionedfile.ThunkedVersionedFiles(repo_transport,
400
389
            weave.WeaveFile, mapper, repo.is_locked)
401
390
 
402
391
    def _get_revisions(self, repo_transport, repo):
 
392
        from bzrlib.xml5 import serializer_v5
403
393
        return RevisionTextStore(repo_transport.clone('revision-store'),
404
 
            xml5.serializer_v5, False, versionedfile.PrefixMapper(),
 
394
            serializer_v5, False, versionedfile.PrefixMapper(),
405
395
            repo.is_locked, repo.is_write_locked)
406
396
 
407
397
    def _get_signatures(self, repo_transport, repo):
427
417
 
428
418
    _versionedfile_class = weave.WeaveFile
429
419
    _matchingbzrdir = bzrdir.BzrDirFormat6()
430
 
    @property
431
 
    def _serializer(self):
432
 
        return xml5.serializer_v5
 
420
 
 
421
    def __init__(self):
 
422
        super(RepositoryFormat6, self).__init__()
 
423
        self._fetch_order = 'topological'
 
424
        self._fetch_reconcile = True
433
425
 
434
426
    def get_format_description(self):
435
427
        """See RepositoryFormat.get_format_description()."""
436
428
        return "Weave repository format 6"
437
429
 
438
 
    def network_name(self):
439
 
        """The network name for this format is the control dirs disk label."""
440
 
        return self._matchingbzrdir.get_format_string()
441
 
 
442
430
    def _get_inventories(self, repo_transport, repo, name='inventory'):
443
431
        mapper = versionedfile.ConstantMapper(name)
444
432
        return versionedfile.ThunkedVersionedFiles(repo_transport,
445
433
            weave.WeaveFile, mapper, repo.is_locked)
446
434
 
447
435
    def _get_revisions(self, repo_transport, repo):
 
436
        from bzrlib.xml5 import serializer_v5
448
437
        return RevisionTextStore(repo_transport.clone('revision-store'),
449
 
            xml5.serializer_v5, False, versionedfile.HashPrefixMapper(),
 
438
            serializer_v5, False, versionedfile.HashPrefixMapper(),
450
439
            repo.is_locked, repo.is_write_locked)
451
440
 
452
441
    def _get_signatures(self, repo_transport, repo):
475
464
 
476
465
    _versionedfile_class = weave.WeaveFile
477
466
    supports_ghosts = False
478
 
    supports_chks = False
479
 
 
480
 
    _fetch_order = 'topological'
481
 
    _fetch_reconcile = True
482
 
    fast_deltas = False
483
 
    @property
484
 
    def _serializer(self):
485
 
        return xml5.serializer_v5
486
467
 
487
468
    def get_format_string(self):
488
469
        """See RepositoryFormat.get_format_string()."""
492
473
        """See RepositoryFormat.get_format_description()."""
493
474
        return "Weave repository format 7"
494
475
 
 
476
    def check_conversion_target(self, target_format):
 
477
        pass
 
478
 
495
479
    def _get_inventories(self, repo_transport, repo, name='inventory'):
496
480
        mapper = versionedfile.ConstantMapper(name)
497
481
        return versionedfile.ThunkedVersionedFiles(repo_transport,
498
482
            weave.WeaveFile, mapper, repo.is_locked)
499
483
 
500
484
    def _get_revisions(self, repo_transport, repo):
 
485
        from bzrlib.xml5 import serializer_v5
501
486
        return RevisionTextStore(repo_transport.clone('revision-store'),
502
 
            xml5.serializer_v5, True, versionedfile.HashPrefixMapper(),
 
487
            serializer_v5, True, versionedfile.HashPrefixMapper(),
503
488
            repo.is_locked, repo.is_write_locked)
504
489
 
505
490
    def _get_signatures(self, repo_transport, repo):
526
511
 
527
512
        mutter('creating repository in %s.', a_bzrdir.transport.base)
528
513
        dirs = ['revision-store', 'weaves']
529
 
        files = [('inventory.weave', StringIO(empty_weave)),
 
514
        files = [('inventory.weave', StringIO(empty_weave)), 
530
515
                 ]
531
516
        utf8_files = [('format', self.get_format_string())]
532
 
 
 
517
 
533
518
        self._upload_blank_content(a_bzrdir, dirs, files, utf8_files, shared)
534
519
        return self.open(a_bzrdir=a_bzrdir, _found=True)
535
520
 
536
521
    def open(self, a_bzrdir, _found=False, _override_transport=None):
537
522
        """See RepositoryFormat.open().
538
 
 
 
523
        
539
524
        :param _override_transport: INTERNAL USE ONLY. Allows opening the
540
525
                                    repository at a slightly different url
541
526
                                    than normal. I.e. during 'upgrade'.
554
539
        result.signatures = self._get_signatures(repo_transport, result)
555
540
        result.inventories = self._get_inventories(repo_transport, result)
556
541
        result.texts = self._get_texts(repo_transport, result)
557
 
        result.chk_bytes = None
558
542
        result._transport = repo_transport
559
543
        return result
560
544
 
663
647
                continue
664
648
            result[key] = parents
665
649
        return result
666
 
 
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
 
 
 
650
    
674
651
    def get_record_stream(self, keys, sort_order, include_delta_closure):
675
652
        for key in keys:
676
653
            text, parents = self._load_text_parents(key)
688
665
            path, ext = os.path.splitext(relpath)
689
666
            if ext == '.gz':
690
667
                relpath = path
691
 
            if not relpath.endswith('.sig'):
 
668
            if '.sig' not in relpath:
692
669
                relpaths.add(relpath)
693
670
        paths = list(relpaths)
694
671
        return set([self._mapper.unmap(path) for path in paths])
710
687
                continue
711
688
            result[key] = None
712
689
        return result
713
 
 
 
690
    
714
691
    def get_record_stream(self, keys, sort_order, include_delta_closure):
715
692
        for key in keys:
716
693
            text = self._load_text(key)