~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/repofmt/weaverepo.py

  • Committer: John Arbash Meinel
  • Date: 2008-10-14 21:35:27 UTC
  • mto: This revision was merged to the branch mainline in revision 3805.
  • Revision ID: john@arbash-meinel.com-20081014213527-4j9uc93aq1qmn43b
Add in a shortcut when we haven't cached much yet.

Document the current algorithm more completely, including the proper
justification for the various steps.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2007-2010 Canonical Ltd
 
1
# Copyright (C) 2005, 2006, 2007, 2008 Canonical Ltd
2
2
#
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
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
 
28
28
lazy_import(globals(), """
29
29
from bzrlib import (
30
30
    xml5,
31
 
    graph as _mod_graph,
32
31
    )
33
32
""")
34
33
from bzrlib import (
39
38
    lockdir,
40
39
    osutils,
41
40
    revision as _mod_revision,
42
 
    trace,
43
 
    urlutils,
44
41
    versionedfile,
45
42
    weave,
46
43
    weavefile,
54
51
    RepositoryFormat,
55
52
    )
56
53
from bzrlib.store.text import TextStore
 
54
from bzrlib.trace import mutter
57
55
from bzrlib.tuned_gzip import GzipFile, bytes_to_gzip
58
56
from bzrlib.versionedfile import (
59
57
    AbsentContentFactory,
69
67
    def _serializer(self):
70
68
        return xml5.serializer_v5
71
69
 
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
 
 
79
70
    def __init__(self, _format, a_bzrdir):
80
71
        # we reuse one control files instance.
81
72
        dir_mode = a_bzrdir._get_dir_mode()
83
74
 
84
75
        def get_store(name, compressed=True, prefixed=False):
85
76
            # 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
 
77
            # or entirely uncompressed is tidy, but breaks upgrade from 
 
78
            # some existing branches where there's a mixture; we probably 
88
79
            # still want the option to look for both.
89
 
            relpath = self._escape(name)
 
80
            relpath = a_bzrdir._control_files._escape(name)
90
81
            store = TextStore(a_bzrdir.transport.clone(relpath),
91
82
                              prefixed=prefixed, compressed=compressed,
92
83
                              dir_mode=dir_mode,
96
87
        # not broken out yet because the controlweaves|inventory_store
97
88
        # and texts bits are still different.
98
89
        if isinstance(_format, RepositoryFormat4):
99
 
            # cannot remove these - there is still no consistent api
 
90
            # cannot remove these - there is still no consistent api 
100
91
            # which allows access to this old info.
101
92
            self.inventory_store = get_store('inventory-store')
102
93
            self._text_store = get_store('text-store')
103
94
        super(AllInOneRepository, self).__init__(_format, a_bzrdir, a_bzrdir._control_files)
 
95
        self._fetch_order = 'topological'
 
96
        self._fetch_reconcile = True
104
97
 
105
98
    @needs_read_lock
106
99
    def _all_possible_ids(self):
107
100
        """Return all the possible revisions that we could find."""
108
101
        if 'evil' in debug.debug_flags:
109
 
            trace.mutter_callsite(
110
 
                3, "_all_possible_ids scales with size of history.")
 
102
            mutter_callsite(3, "_all_possible_ids scales with size of history.")
111
103
        return [key[-1] for key in self.inventories.keys()]
112
104
 
113
105
    @needs_read_lock
114
106
    def _all_revision_ids(self):
115
 
        """Returns a list of all the revision ids in the repository.
 
107
        """Returns a list of all the revision ids in the repository. 
116
108
 
117
 
        These are in as much topological order as the underlying store can
 
109
        These are in as much topological order as the underlying store can 
118
110
        present: for weaves ghosts may lead to a lack of correctness until
119
111
        the reweave updates the parents list.
120
112
        """
177
169
        :param new_value: True to restore the default, False to disable making
178
170
                          working trees.
179
171
        """
180
 
        raise errors.RepositoryUpgradeRequired(self.user_url)
 
172
        raise errors.RepositoryUpgradeRequired(self.bzrdir.root_transport.base)
181
173
 
182
174
    def make_working_trees(self):
183
175
        """Returns the policy for making working trees on new branches."""
192
184
class WeaveMetaDirRepository(MetaDirVersionedFileRepository):
193
185
    """A subclass of MetaDirRepository to set weave specific policy."""
194
186
 
 
187
    @property
 
188
    def _serializer(self):
 
189
        return xml5.serializer_v5
 
190
 
195
191
    def __init__(self, _format, a_bzrdir, control_files):
196
192
        super(WeaveMetaDirRepository, self).__init__(_format, a_bzrdir, control_files)
197
 
        self._serializer = _format._serializer
 
193
        self._fetch_order = 'topological'
 
194
        self._fetch_reconcile = True
198
195
 
199
196
    @needs_read_lock
200
197
    def _all_possible_ids(self):
201
198
        """Return all the possible revisions that we could find."""
202
199
        if 'evil' in debug.debug_flags:
203
 
            trace.mutter_callsite(
204
 
                3, "_all_possible_ids scales with size of history.")
 
200
            mutter_callsite(3, "_all_possible_ids scales with size of history.")
205
201
        return [key[-1] for key in self.inventories.keys()]
206
202
 
207
203
    @needs_read_lock
208
204
    def _all_revision_ids(self):
209
 
        """Returns a list of all the revision ids in the repository.
 
205
        """Returns a list of all the revision ids in the repository. 
210
206
 
211
 
        These are in as much topological order as the underlying store can
 
207
        These are in as much topological order as the underlying store can 
212
208
        present: for weaves ghosts may lead to a lack of correctness until
213
209
        the reweave updates the parents list.
214
210
        """
269
265
    supports_tree_reference = False
270
266
    supports_ghosts = False
271
267
    supports_external_lookups = False
272
 
    supports_chks = False
273
 
    _fetch_order = 'topological'
274
 
    _fetch_reconcile = True
275
 
    fast_deltas = False
276
268
 
277
269
    def initialize(self, a_bzrdir, shared=False, _internal=False):
278
270
        """Create a weave repository."""
282
274
        if not _internal:
283
275
            # always initialized when the bzrdir is.
284
276
            return self.open(a_bzrdir, _found=True)
285
 
 
 
277
        
286
278
        # Create an empty weave
287
279
        sio = StringIO()
288
280
        weavefile.write_weave_v5(weave.Weave(), sio)
289
281
        empty_weave = sio.getvalue()
290
282
 
291
 
        trace.mutter('creating repository in %s.', a_bzrdir.transport.base)
292
 
 
 
283
        mutter('creating repository in %s.', a_bzrdir.transport.base)
 
284
        
293
285
        # FIXME: RBC 20060125 don't peek under the covers
294
286
        # NB: no need to escape relative paths that are url safe.
295
287
        control_files = lockable_files.LockableFiles(a_bzrdir.transport,
300
292
        try:
301
293
            transport.mkdir_multi(['revision-store', 'weaves'],
302
294
                mode=a_bzrdir._get_dir_mode())
303
 
            transport.put_bytes_non_atomic('inventory.weave', empty_weave,
304
 
                mode=a_bzrdir._get_file_mode())
 
295
            transport.put_bytes_non_atomic('inventory.weave', empty_weave)
305
296
        finally:
306
297
            control_files.unlock()
307
 
        repository = self.open(a_bzrdir, _found=True)
308
 
        self._run_post_repo_init_hooks(repository, a_bzrdir, shared)
309
 
        return repository
 
298
        return self.open(a_bzrdir, _found=True)
310
299
 
311
300
    def open(self, a_bzrdir, _found=False):
312
301
        """See RepositoryFormat.open()."""
321
310
        result.signatures = self._get_signatures(repo_transport, result)
322
311
        result.inventories = self._get_inventories(repo_transport, result)
323
312
        result.texts = self._get_texts(repo_transport, result)
324
 
        result.chk_bytes = None
325
313
        return result
326
314
 
 
315
    def check_conversion_target(self, target_format):
 
316
        pass
 
317
 
327
318
 
328
319
class RepositoryFormat4(PreSplitOutRepositoryFormat):
329
320
    """Bzr repository format 4.
339
330
 
340
331
    _matchingbzrdir = bzrdir.BzrDirFormat4()
341
332
 
 
333
    def __init__(self):
 
334
        super(RepositoryFormat4, self).__init__()
 
335
        self._fetch_order = 'topological'
 
336
        self._fetch_reconcile = True
 
337
 
342
338
    def get_format_description(self):
343
339
        """See RepositoryFormat.get_format_description()."""
344
340
        return "Repository format 4"
351
347
        """Format 4 is not supported.
352
348
 
353
349
        It is not supported because the model changed from 4 to 5 and the
354
 
        conversion logic is expensive - so doing it on the fly was not
 
350
        conversion logic is expensive - so doing it on the fly was not 
355
351
        feasible.
356
352
        """
357
353
        return False
386
382
 
387
383
    _versionedfile_class = weave.WeaveFile
388
384
    _matchingbzrdir = bzrdir.BzrDirFormat5()
389
 
    @property
390
 
    def _serializer(self):
391
 
        return xml5.serializer_v5
 
385
 
 
386
    def __init__(self):
 
387
        super(RepositoryFormat5, self).__init__()
 
388
        self._fetch_order = 'topological'
 
389
        self._fetch_reconcile = True
392
390
 
393
391
    def get_format_description(self):
394
392
        """See RepositoryFormat.get_format_description()."""
395
393
        return "Weave repository format 5"
396
394
 
397
 
    def network_name(self):
398
 
        """The network name for this format is the control dirs disk label."""
399
 
        return self._matchingbzrdir.get_format_string()
400
 
 
401
395
    def _get_inventories(self, repo_transport, repo, name='inventory'):
402
396
        mapper = versionedfile.ConstantMapper(name)
403
397
        return versionedfile.ThunkedVersionedFiles(repo_transport,
404
398
            weave.WeaveFile, mapper, repo.is_locked)
405
399
 
406
400
    def _get_revisions(self, repo_transport, repo):
 
401
        from bzrlib.xml5 import serializer_v5
407
402
        return RevisionTextStore(repo_transport.clone('revision-store'),
408
 
            xml5.serializer_v5, False, versionedfile.PrefixMapper(),
 
403
            serializer_v5, False, versionedfile.PrefixMapper(),
409
404
            repo.is_locked, repo.is_write_locked)
410
405
 
411
406
    def _get_signatures(self, repo_transport, repo):
431
426
 
432
427
    _versionedfile_class = weave.WeaveFile
433
428
    _matchingbzrdir = bzrdir.BzrDirFormat6()
434
 
    @property
435
 
    def _serializer(self):
436
 
        return xml5.serializer_v5
 
429
 
 
430
    def __init__(self):
 
431
        super(RepositoryFormat6, self).__init__()
 
432
        self._fetch_order = 'topological'
 
433
        self._fetch_reconcile = True
437
434
 
438
435
    def get_format_description(self):
439
436
        """See RepositoryFormat.get_format_description()."""
440
437
        return "Weave repository format 6"
441
438
 
442
 
    def network_name(self):
443
 
        """The network name for this format is the control dirs disk label."""
444
 
        return self._matchingbzrdir.get_format_string()
445
 
 
446
439
    def _get_inventories(self, repo_transport, repo, name='inventory'):
447
440
        mapper = versionedfile.ConstantMapper(name)
448
441
        return versionedfile.ThunkedVersionedFiles(repo_transport,
449
442
            weave.WeaveFile, mapper, repo.is_locked)
450
443
 
451
444
    def _get_revisions(self, repo_transport, repo):
 
445
        from bzrlib.xml5 import serializer_v5
452
446
        return RevisionTextStore(repo_transport.clone('revision-store'),
453
 
            xml5.serializer_v5, False, versionedfile.HashPrefixMapper(),
 
447
            serializer_v5, False, versionedfile.HashPrefixMapper(),
454
448
            repo.is_locked, repo.is_write_locked)
455
449
 
456
450
    def _get_signatures(self, repo_transport, repo):
479
473
 
480
474
    _versionedfile_class = weave.WeaveFile
481
475
    supports_ghosts = False
482
 
    supports_chks = False
483
 
 
484
 
    _fetch_order = 'topological'
485
 
    _fetch_reconcile = True
486
 
    fast_deltas = False
487
 
    @property
488
 
    def _serializer(self):
489
 
        return xml5.serializer_v5
490
476
 
491
477
    def get_format_string(self):
492
478
        """See RepositoryFormat.get_format_string()."""
496
482
        """See RepositoryFormat.get_format_description()."""
497
483
        return "Weave repository format 7"
498
484
 
 
485
    def check_conversion_target(self, target_format):
 
486
        pass
 
487
 
499
488
    def _get_inventories(self, repo_transport, repo, name='inventory'):
500
489
        mapper = versionedfile.ConstantMapper(name)
501
490
        return versionedfile.ThunkedVersionedFiles(repo_transport,
502
491
            weave.WeaveFile, mapper, repo.is_locked)
503
492
 
504
493
    def _get_revisions(self, repo_transport, repo):
 
494
        from bzrlib.xml5 import serializer_v5
505
495
        return RevisionTextStore(repo_transport.clone('revision-store'),
506
 
            xml5.serializer_v5, True, versionedfile.HashPrefixMapper(),
 
496
            serializer_v5, True, versionedfile.HashPrefixMapper(),
507
497
            repo.is_locked, repo.is_write_locked)
508
498
 
509
499
    def _get_signatures(self, repo_transport, repo):
528
518
        weavefile.write_weave_v5(weave.Weave(), sio)
529
519
        empty_weave = sio.getvalue()
530
520
 
531
 
        trace.mutter('creating repository in %s.', a_bzrdir.transport.base)
 
521
        mutter('creating repository in %s.', a_bzrdir.transport.base)
532
522
        dirs = ['revision-store', 'weaves']
533
 
        files = [('inventory.weave', StringIO(empty_weave)),
 
523
        files = [('inventory.weave', StringIO(empty_weave)), 
534
524
                 ]
535
525
        utf8_files = [('format', self.get_format_string())]
536
 
 
 
526
 
537
527
        self._upload_blank_content(a_bzrdir, dirs, files, utf8_files, shared)
538
528
        return self.open(a_bzrdir=a_bzrdir, _found=True)
539
529
 
540
530
    def open(self, a_bzrdir, _found=False, _override_transport=None):
541
531
        """See RepositoryFormat.open().
542
 
 
 
532
        
543
533
        :param _override_transport: INTERNAL USE ONLY. Allows opening the
544
534
                                    repository at a slightly different url
545
535
                                    than normal. I.e. during 'upgrade'.
558
548
        result.signatures = self._get_signatures(repo_transport, result)
559
549
        result.inventories = self._get_inventories(repo_transport, result)
560
550
        result.texts = self._get_texts(repo_transport, result)
561
 
        result.chk_bytes = None
562
551
        result._transport = repo_transport
563
552
        return result
564
553
 
667
656
                continue
668
657
            result[key] = parents
669
658
        return result
670
 
 
671
 
    def get_known_graph_ancestry(self, keys):
672
 
        """Get a KnownGraph instance with the ancestry of keys."""
673
 
        keys = self.keys()
674
 
        parent_map = self.get_parent_map(keys)
675
 
        kg = _mod_graph.KnownGraph(parent_map)
676
 
        return kg
677
 
 
 
659
    
678
660
    def get_record_stream(self, keys, sort_order, include_delta_closure):
679
661
        for key in keys:
680
662
            text, parents = self._load_text_parents(key)
692
674
            path, ext = os.path.splitext(relpath)
693
675
            if ext == '.gz':
694
676
                relpath = path
695
 
            if not relpath.endswith('.sig'):
 
677
            if '.sig' not in relpath:
696
678
                relpaths.add(relpath)
697
679
        paths = list(relpaths)
698
680
        return set([self._mapper.unmap(path) for path in paths])
714
696
                continue
715
697
            result[key] = None
716
698
        return result
717
 
 
 
699
    
718
700
    def get_record_stream(self, keys, sort_order, include_delta_closure):
719
701
        for key in keys:
720
702
            text = self._load_text(key)