~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/repofmt/weaverepo.py

  • Committer: Martin Pool
  • Date: 2008-07-14 07:39:30 UTC
  • mto: This revision was merged to the branch mainline in revision 3537.
  • Revision ID: mbp@sourcefrog.net-20080714073930-z8nl2c44jal0eozs
Update test for knit.check() to expect it to recurse into fallback vfs

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2007-2011 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
 
20
20
ghosts.
21
21
"""
22
22
 
23
 
from __future__ import absolute_import
24
 
 
25
 
import gzip
26
23
import os
27
24
from cStringIO import StringIO
28
 
 
29
 
from bzrlib.lazy_import import lazy_import
30
 
lazy_import(globals(), """
31
 
import itertools
32
 
 
33
 
from bzrlib import (
34
 
    xml5,
35
 
    graph as _mod_graph,
36
 
    ui,
37
 
    )
38
 
""")
39
 
from bzrlib import (
 
25
import urllib
 
26
 
 
27
from bzrlib import (
 
28
    bzrdir,
40
29
    debug,
41
30
    errors,
42
31
    lockable_files,
43
32
    lockdir,
44
33
    osutils,
45
 
    symbol_versioning,
46
 
    trace,
47
 
    tuned_gzip,
48
 
    urlutils,
 
34
    revision as _mod_revision,
49
35
    versionedfile,
50
36
    weave,
51
37
    weavefile,
 
38
    xml5,
52
39
    )
53
40
from bzrlib.decorators import needs_read_lock, needs_write_lock
54
41
from bzrlib.repository import (
55
 
    InterRepository,
56
 
    RepositoryFormatMetaDir,
 
42
    CommitBuilder,
 
43
    MetaDirVersionedFileRepository,
 
44
    MetaDirRepositoryFormat,
 
45
    Repository,
 
46
    RepositoryFormat,
57
47
    )
58
48
from bzrlib.store.text import TextStore
 
49
from bzrlib.trace import mutter
 
50
from bzrlib.tuned_gzip import GzipFile, bytes_to_gzip
59
51
from bzrlib.versionedfile import (
60
52
    AbsentContentFactory,
61
53
    FulltextContentFactory,
62
54
    VersionedFiles,
63
55
    )
64
 
from bzrlib.vf_repository import (
65
 
    InterSameDataRepository,
66
 
    VersionedFileCommitBuilder,
67
 
    VersionedFileRepository,
68
 
    VersionedFileRepositoryFormat,
69
 
    MetaDirVersionedFileRepository,
70
 
    MetaDirVersionedFileRepositoryFormat,
71
 
    )
72
 
 
73
 
from bzrlib.plugins.weave_fmt import bzrdir as weave_bzrdir
74
 
 
75
 
 
76
 
class AllInOneRepository(VersionedFileRepository):
 
56
 
 
57
 
 
58
class AllInOneRepository(Repository):
77
59
    """Legacy support - the repository behaviour for all-in-one branches."""
78
60
 
79
 
    @property
80
 
    def _serializer(self):
81
 
        return xml5.serializer_v5
82
 
 
83
 
    def _escape(self, file_or_path):
84
 
        if not isinstance(file_or_path, basestring):
85
 
            file_or_path = '/'.join(file_or_path)
86
 
        if file_or_path == '':
87
 
            return u''
88
 
        return urlutils.escape(osutils.safe_unicode(file_or_path))
 
61
    _serializer = xml5.serializer_v5
89
62
 
90
63
    def __init__(self, _format, a_bzrdir):
91
64
        # we reuse one control files instance.
94
67
 
95
68
        def get_store(name, compressed=True, prefixed=False):
96
69
            # FIXME: This approach of assuming stores are all entirely compressed
97
 
            # or entirely uncompressed is tidy, but breaks upgrade from
98
 
            # 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 
99
72
            # still want the option to look for both.
100
 
            relpath = self._escape(name)
 
73
            relpath = a_bzrdir._control_files._escape(name)
101
74
            store = TextStore(a_bzrdir.transport.clone(relpath),
102
75
                              prefixed=prefixed, compressed=compressed,
103
76
                              dir_mode=dir_mode,
107
80
        # not broken out yet because the controlweaves|inventory_store
108
81
        # and texts bits are still different.
109
82
        if isinstance(_format, RepositoryFormat4):
110
 
            # cannot remove these - there is still no consistent api
 
83
            # cannot remove these - there is still no consistent api 
111
84
            # which allows access to this old info.
112
85
            self.inventory_store = get_store('inventory-store')
113
86
            self._text_store = get_store('text-store')
117
90
    def _all_possible_ids(self):
118
91
        """Return all the possible revisions that we could find."""
119
92
        if 'evil' in debug.debug_flags:
120
 
            trace.mutter_callsite(
121
 
                3, "_all_possible_ids scales with size of history.")
 
93
            mutter_callsite(3, "_all_possible_ids scales with size of history.")
122
94
        return [key[-1] for key in self.inventories.keys()]
123
95
 
124
96
    @needs_read_lock
125
97
    def _all_revision_ids(self):
126
 
        """Returns a list of all the revision ids in the repository.
 
98
        """Returns a list of all the revision ids in the repository. 
127
99
 
128
 
        These are in as much topological order as the underlying store can
 
100
        These are in as much topological order as the underlying store can 
129
101
        present: for weaves ghosts may lead to a lack of correctness until
130
102
        the reweave updates the parents list.
131
103
        """
151
123
 
152
124
    def get_commit_builder(self, branch, parents, config, timestamp=None,
153
125
                           timezone=None, committer=None, revprops=None,
154
 
                           revision_id=None, lossy=False):
 
126
                           revision_id=None):
155
127
        self._check_ascii_revisionid(revision_id, self.get_commit_builder)
156
 
        result = VersionedFileCommitBuilder(self, parents, config, timestamp,
157
 
            timezone, committer, revprops, revision_id, lossy=lossy)
 
128
        result = CommitBuilder(self, parents, config, timestamp, timezone,
 
129
                              committer, revprops, revision_id)
158
130
        self.start_write_group()
159
131
        return result
160
132
 
174
146
        return self.inventories.add_lines((revision_id,), final_parents, lines,
175
147
            check_content=check_content)[0]
176
148
 
 
149
    @needs_read_lock
177
150
    def is_shared(self):
178
151
        """AllInOne repositories cannot be shared."""
179
152
        return False
188
161
        :param new_value: True to restore the default, False to disable making
189
162
                          working trees.
190
163
        """
191
 
        raise errors.RepositoryUpgradeRequired(self.user_url)
 
164
        raise errors.RepositoryUpgradeRequired(self.bzrdir.root_transport.base)
192
165
 
193
166
    def make_working_trees(self):
194
167
        """Returns the policy for making working trees on new branches."""
195
168
        return True
196
169
 
 
170
    def revision_graph_can_have_wrong_parents(self):
 
171
        # XXX: This is an old format that we don't support full checking on, so
 
172
        # just claim that checking for this inconsistency is not required.
 
173
        return False
 
174
 
197
175
 
198
176
class WeaveMetaDirRepository(MetaDirVersionedFileRepository):
199
177
    """A subclass of MetaDirRepository to set weave specific policy."""
200
178
 
201
 
    def __init__(self, _format, a_bzrdir, control_files):
202
 
        super(WeaveMetaDirRepository, self).__init__(_format, a_bzrdir, control_files)
203
 
        self._serializer = _format._serializer
 
179
    _serializer = xml5.serializer_v5
204
180
 
205
181
    @needs_read_lock
206
182
    def _all_possible_ids(self):
207
183
        """Return all the possible revisions that we could find."""
208
184
        if 'evil' in debug.debug_flags:
209
 
            trace.mutter_callsite(
210
 
                3, "_all_possible_ids scales with size of history.")
 
185
            mutter_callsite(3, "_all_possible_ids scales with size of history.")
211
186
        return [key[-1] for key in self.inventories.keys()]
212
187
 
213
188
    @needs_read_lock
214
189
    def _all_revision_ids(self):
215
 
        """Returns a list of all the revision ids in the repository.
 
190
        """Returns a list of all the revision ids in the repository. 
216
191
 
217
 
        These are in as much topological order as the underlying store can
 
192
        These are in as much topological order as the underlying store can 
218
193
        present: for weaves ghosts may lead to a lack of correctness until
219
194
        the reweave updates the parents list.
220
195
        """
240
215
 
241
216
    def get_commit_builder(self, branch, parents, config, timestamp=None,
242
217
                           timezone=None, committer=None, revprops=None,
243
 
                           revision_id=None, lossy=False):
 
218
                           revision_id=None):
244
219
        self._check_ascii_revisionid(revision_id, self.get_commit_builder)
245
 
        result = VersionedFileCommitBuilder(self, parents, config, timestamp,
246
 
            timezone, committer, revprops, revision_id, lossy=lossy)
 
220
        result = CommitBuilder(self, parents, config, timestamp, timezone,
 
221
                              committer, revprops, revision_id)
247
222
        self.start_write_group()
248
223
        return result
249
224
 
264
239
        return self.inventories.add_lines((revision_id,), final_parents, lines,
265
240
            check_content=check_content)[0]
266
241
 
267
 
 
268
 
class PreSplitOutRepositoryFormat(VersionedFileRepositoryFormat):
 
242
    def revision_graph_can_have_wrong_parents(self):
 
243
        return False
 
244
 
 
245
 
 
246
class PreSplitOutRepositoryFormat(RepositoryFormat):
269
247
    """Base class for the pre split out repository formats."""
270
248
 
271
249
    rich_root_data = False
272
250
    supports_tree_reference = False
273
251
    supports_ghosts = False
274
252
    supports_external_lookups = False
275
 
    supports_chks = False
276
 
    supports_nesting_repositories = True
277
 
    _fetch_order = 'topological'
278
 
    _fetch_reconcile = True
279
 
    fast_deltas = False
280
 
    supports_leaving_lock = False
281
 
    # XXX: This is an old format that we don't support full checking on, so
282
 
    # just claim that checking for this inconsistency is not required.
283
 
    revision_graph_can_have_wrong_parents = False
284
253
 
285
254
    def initialize(self, a_bzrdir, shared=False, _internal=False):
286
255
        """Create a weave repository."""
290
259
        if not _internal:
291
260
            # always initialized when the bzrdir is.
292
261
            return self.open(a_bzrdir, _found=True)
293
 
 
 
262
        
294
263
        # Create an empty weave
295
264
        sio = StringIO()
296
265
        weavefile.write_weave_v5(weave.Weave(), sio)
297
266
        empty_weave = sio.getvalue()
298
267
 
299
 
        trace.mutter('creating repository in %s.', a_bzrdir.transport.base)
300
 
 
 
268
        mutter('creating repository in %s.', a_bzrdir.transport.base)
 
269
        
301
270
        # FIXME: RBC 20060125 don't peek under the covers
302
271
        # NB: no need to escape relative paths that are url safe.
303
272
        control_files = lockable_files.LockableFiles(a_bzrdir.transport,
308
277
        try:
309
278
            transport.mkdir_multi(['revision-store', 'weaves'],
310
279
                mode=a_bzrdir._get_dir_mode())
311
 
            transport.put_bytes_non_atomic('inventory.weave', empty_weave,
312
 
                mode=a_bzrdir._get_file_mode())
 
280
            transport.put_bytes_non_atomic('inventory.weave', empty_weave)
313
281
        finally:
314
282
            control_files.unlock()
315
 
        repository = self.open(a_bzrdir, _found=True)
316
 
        self._run_post_repo_init_hooks(repository, a_bzrdir, shared)
317
 
        return repository
 
283
        return self.open(a_bzrdir, _found=True)
318
284
 
319
285
    def open(self, a_bzrdir, _found=False):
320
286
        """See RepositoryFormat.open()."""
323
289
            raise NotImplementedError
324
290
 
325
291
        repo_transport = a_bzrdir.get_repository_transport(None)
 
292
        control_files = a_bzrdir._control_files
326
293
        result = AllInOneRepository(_format=self, a_bzrdir=a_bzrdir)
327
294
        result.revisions = self._get_revisions(repo_transport, result)
328
295
        result.signatures = self._get_signatures(repo_transport, result)
329
296
        result.inventories = self._get_inventories(repo_transport, result)
330
297
        result.texts = self._get_texts(repo_transport, result)
331
 
        result.chk_bytes = None
332
298
        return result
333
299
 
334
 
    def is_deprecated(self):
335
 
        return True
 
300
    def check_conversion_target(self, target_format):
 
301
        pass
336
302
 
337
303
 
338
304
class RepositoryFormat4(PreSplitOutRepositoryFormat):
347
313
    has been removed.
348
314
    """
349
315
 
350
 
    supports_funky_characters = False
 
316
    _matchingbzrdir = bzrdir.BzrDirFormat4()
351
317
 
352
 
    _matchingbzrdir = weave_bzrdir.BzrDirFormat4()
 
318
    def __init__(self):
 
319
        super(RepositoryFormat4, self).__init__()
353
320
 
354
321
    def get_format_description(self):
355
322
        """See RepositoryFormat.get_format_description()."""
363
330
        """Format 4 is not supported.
364
331
 
365
332
        It is not supported because the model changed from 4 to 5 and the
366
 
        conversion logic is expensive - so doing it on the fly was not
 
333
        conversion logic is expensive - so doing it on the fly was not 
367
334
        feasible.
368
335
        """
369
336
        return False
373
340
        return None
374
341
 
375
342
    def _get_revisions(self, repo_transport, repo):
376
 
        from bzrlib.plugins.weave_fmt.xml4 import serializer_v4
 
343
        from bzrlib.xml4 import serializer_v4
377
344
        return RevisionTextStore(repo_transport.clone('revision-store'),
378
345
            serializer_v4, True, versionedfile.PrefixMapper(),
379
346
            repo.is_locked, repo.is_write_locked)
397
364
    """
398
365
 
399
366
    _versionedfile_class = weave.WeaveFile
400
 
    _matchingbzrdir = weave_bzrdir.BzrDirFormat5()
401
 
    supports_funky_characters = False
 
367
    _matchingbzrdir = bzrdir.BzrDirFormat5()
402
368
 
403
 
    @property
404
 
    def _serializer(self):
405
 
        return xml5.serializer_v5
 
369
    def __init__(self):
 
370
        super(RepositoryFormat5, self).__init__()
406
371
 
407
372
    def get_format_description(self):
408
373
        """See RepositoryFormat.get_format_description()."""
409
374
        return "Weave repository format 5"
410
375
 
411
 
    def network_name(self):
412
 
        """The network name for this format is the control dirs disk label."""
413
 
        return self._matchingbzrdir.get_format_string()
414
 
 
415
376
    def _get_inventories(self, repo_transport, repo, name='inventory'):
416
377
        mapper = versionedfile.ConstantMapper(name)
417
378
        return versionedfile.ThunkedVersionedFiles(repo_transport,
418
379
            weave.WeaveFile, mapper, repo.is_locked)
419
380
 
420
381
    def _get_revisions(self, repo_transport, repo):
 
382
        from bzrlib.xml5 import serializer_v5
421
383
        return RevisionTextStore(repo_transport.clone('revision-store'),
422
 
            xml5.serializer_v5, False, versionedfile.PrefixMapper(),
 
384
            serializer_v5, False, versionedfile.PrefixMapper(),
423
385
            repo.is_locked, repo.is_write_locked)
424
386
 
425
387
    def _get_signatures(self, repo_transport, repo):
444
406
    """
445
407
 
446
408
    _versionedfile_class = weave.WeaveFile
447
 
    _matchingbzrdir = weave_bzrdir.BzrDirFormat6()
448
 
    supports_funky_characters = False
449
 
    @property
450
 
    def _serializer(self):
451
 
        return xml5.serializer_v5
 
409
    _matchingbzrdir = bzrdir.BzrDirFormat6()
 
410
 
 
411
    def __init__(self):
 
412
        super(RepositoryFormat6, self).__init__()
452
413
 
453
414
    def get_format_description(self):
454
415
        """See RepositoryFormat.get_format_description()."""
455
416
        return "Weave repository format 6"
456
417
 
457
 
    def network_name(self):
458
 
        """The network name for this format is the control dirs disk label."""
459
 
        return self._matchingbzrdir.get_format_string()
460
 
 
461
418
    def _get_inventories(self, repo_transport, repo, name='inventory'):
462
419
        mapper = versionedfile.ConstantMapper(name)
463
420
        return versionedfile.ThunkedVersionedFiles(repo_transport,
464
421
            weave.WeaveFile, mapper, repo.is_locked)
465
422
 
466
423
    def _get_revisions(self, repo_transport, repo):
 
424
        from bzrlib.xml5 import serializer_v5
467
425
        return RevisionTextStore(repo_transport.clone('revision-store'),
468
 
            xml5.serializer_v5, False, versionedfile.HashPrefixMapper(),
 
426
            serializer_v5, False, versionedfile.HashPrefixMapper(),
469
427
            repo.is_locked, repo.is_write_locked)
470
428
 
471
429
    def _get_signatures(self, repo_transport, repo):
480
438
            weave.WeaveFile, mapper, repo.is_locked)
481
439
 
482
440
 
483
 
class RepositoryFormat7(MetaDirVersionedFileRepositoryFormat):
 
441
class RepositoryFormat7(MetaDirRepositoryFormat):
484
442
    """Bzr repository 7.
485
443
 
486
444
    This repository format has:
494
452
 
495
453
    _versionedfile_class = weave.WeaveFile
496
454
    supports_ghosts = False
497
 
    supports_chks = False
498
 
    supports_funky_characters = False
499
 
    revision_graph_can_have_wrong_parents = False
500
 
 
501
 
    _fetch_order = 'topological'
502
 
    _fetch_reconcile = True
503
 
    fast_deltas = False
504
 
    @property
505
 
    def _serializer(self):
506
 
        return xml5.serializer_v5
507
 
 
508
 
    @classmethod
509
 
    def get_format_string(cls):
 
455
 
 
456
    def get_format_string(self):
510
457
        """See RepositoryFormat.get_format_string()."""
511
458
        return "Bazaar-NG Repository format 7"
512
459
 
514
461
        """See RepositoryFormat.get_format_description()."""
515
462
        return "Weave repository format 7"
516
463
 
 
464
    def check_conversion_target(self, target_format):
 
465
        pass
 
466
 
517
467
    def _get_inventories(self, repo_transport, repo, name='inventory'):
518
468
        mapper = versionedfile.ConstantMapper(name)
519
469
        return versionedfile.ThunkedVersionedFiles(repo_transport,
520
470
            weave.WeaveFile, mapper, repo.is_locked)
521
471
 
522
472
    def _get_revisions(self, repo_transport, repo):
 
473
        from bzrlib.xml5 import serializer_v5
523
474
        return RevisionTextStore(repo_transport.clone('revision-store'),
524
 
            xml5.serializer_v5, True, versionedfile.HashPrefixMapper(),
 
475
            serializer_v5, True, versionedfile.HashPrefixMapper(),
525
476
            repo.is_locked, repo.is_write_locked)
526
477
 
527
478
    def _get_signatures(self, repo_transport, repo):
546
497
        weavefile.write_weave_v5(weave.Weave(), sio)
547
498
        empty_weave = sio.getvalue()
548
499
 
549
 
        trace.mutter('creating repository in %s.', a_bzrdir.transport.base)
 
500
        mutter('creating repository in %s.', a_bzrdir.transport.base)
550
501
        dirs = ['revision-store', 'weaves']
551
 
        files = [('inventory.weave', StringIO(empty_weave)),
 
502
        files = [('inventory.weave', StringIO(empty_weave)), 
552
503
                 ]
553
504
        utf8_files = [('format', self.get_format_string())]
554
 
 
 
505
 
555
506
        self._upload_blank_content(a_bzrdir, dirs, files, utf8_files, shared)
556
507
        return self.open(a_bzrdir=a_bzrdir, _found=True)
557
508
 
558
509
    def open(self, a_bzrdir, _found=False, _override_transport=None):
559
510
        """See RepositoryFormat.open().
560
 
 
 
511
        
561
512
        :param _override_transport: INTERNAL USE ONLY. Allows opening the
562
513
                                    repository at a slightly different url
563
514
                                    than normal. I.e. during 'upgrade'.
564
515
        """
565
516
        if not _found:
566
 
            format = RepositoryFormatMetaDir.find_format(a_bzrdir)
 
517
            format = RepositoryFormat.find_format(a_bzrdir)
567
518
        if _override_transport is not None:
568
519
            repo_transport = _override_transport
569
520
        else:
576
527
        result.signatures = self._get_signatures(repo_transport, result)
577
528
        result.inventories = self._get_inventories(repo_transport, result)
578
529
        result.texts = self._get_texts(repo_transport, result)
579
 
        result.chk_bytes = None
580
530
        result._transport = repo_transport
581
531
        return result
582
532
 
583
 
    def is_deprecated(self):
584
 
        return True
585
 
 
586
533
 
587
534
class TextVersionedFiles(VersionedFiles):
588
535
    """Just-a-bunch-of-files based VersionedFile stores."""
608
555
            raise ValueError('bad idea to put / in %r' % (key,))
609
556
        text = ''.join(lines)
610
557
        if self._compressed:
611
 
            text = tuned_gzip.bytes_to_gzip(text)
 
558
            text = bytes_to_gzip(text)
612
559
        path = self._map(key)
613
560
        self._transport.put_bytes_non_atomic(path, text, create_parent_dir=True)
614
561
 
634
581
                    record, record.get_bytes_as(record.storage_kind)))
635
582
                try:
636
583
                    self.add_lines(record.key, None, lines)
637
 
                except errors.RevisionAlreadyPresent:
 
584
                except RevisionAlreadyPresent:
638
585
                    pass
639
586
 
640
587
    def _load_text(self, key):
656
603
            else:
657
604
                return None
658
605
        if compressed:
659
 
            text = gzip.GzipFile(mode='rb', fileobj=StringIO(text)).read()
 
606
            text = GzipFile(mode='rb', fileobj=StringIO(text)).read()
660
607
        return text
661
608
 
662
609
    def _map(self, key):
688
635
                continue
689
636
            result[key] = parents
690
637
        return result
691
 
 
692
 
    def get_known_graph_ancestry(self, keys):
693
 
        """Get a KnownGraph instance with the ancestry of keys."""
694
 
        keys = self.keys()
695
 
        parent_map = self.get_parent_map(keys)
696
 
        kg = _mod_graph.KnownGraph(parent_map)
697
 
        return kg
698
 
 
 
638
    
699
639
    def get_record_stream(self, keys, sort_order, include_delta_closure):
700
640
        for key in keys:
701
641
            text, parents = self._load_text_parents(key)
709
649
            raise errors.ObjectNotLocked(self)
710
650
        relpaths = set()
711
651
        for quoted_relpath in self._transport.iter_files_recursive():
712
 
            relpath = urlutils.unquote(quoted_relpath)
 
652
            relpath = urllib.unquote(quoted_relpath)
713
653
            path, ext = os.path.splitext(relpath)
714
654
            if ext == '.gz':
715
655
                relpath = path
716
 
            if not relpath.endswith('.sig'):
 
656
            if '.sig' not in relpath:
717
657
                relpaths.add(relpath)
718
658
        paths = list(relpaths)
719
659
        return set([self._mapper.unmap(path) for path in paths])
735
675
                continue
736
676
            result[key] = None
737
677
        return result
738
 
 
 
678
    
739
679
    def get_record_stream(self, keys, sort_order, include_delta_closure):
740
680
        for key in keys:
741
681
            text = self._load_text(key)
749
689
            raise errors.ObjectNotLocked(self)
750
690
        relpaths = set()
751
691
        for quoted_relpath in self._transport.iter_files_recursive():
752
 
            relpath = urlutils.unquote(quoted_relpath)
 
692
            relpath = urllib.unquote(quoted_relpath)
753
693
            path, ext = os.path.splitext(relpath)
754
694
            if ext == '.gz':
755
695
                relpath = path
759
699
        paths = list(relpaths)
760
700
        return set([self._mapper.unmap(path) for path in paths])
761
701
 
762
 
 
763
 
class InterWeaveRepo(InterSameDataRepository):
764
 
    """Optimised code paths between Weave based repositories.
765
 
    """
766
 
 
767
 
    @classmethod
768
 
    def _get_repo_format_to_test(self):
769
 
        return RepositoryFormat7()
770
 
 
771
 
    @staticmethod
772
 
    def is_compatible(source, target):
773
 
        """Be compatible with known Weave formats.
774
 
 
775
 
        We don't test for the stores being of specific types because that
776
 
        could lead to confusing results, and there is no need to be
777
 
        overly general.
778
 
        """
779
 
        try:
780
 
            return (isinstance(source._format, (RepositoryFormat5,
781
 
                                                RepositoryFormat6,
782
 
                                                RepositoryFormat7)) and
783
 
                    isinstance(target._format, (RepositoryFormat5,
784
 
                                                RepositoryFormat6,
785
 
                                                RepositoryFormat7)))
786
 
        except AttributeError:
787
 
            return False
788
 
 
789
 
    @needs_write_lock
790
 
    def copy_content(self, revision_id=None):
791
 
        """See InterRepository.copy_content()."""
792
 
        # weave specific optimised path:
793
 
        try:
794
 
            self.target.set_make_working_trees(self.source.make_working_trees())
795
 
        except (errors.RepositoryUpgradeRequired, NotImplemented):
796
 
            pass
797
 
        # FIXME do not peek!
798
 
        if self.source._transport.listable():
799
 
            pb = ui.ui_factory.nested_progress_bar()
800
 
            try:
801
 
                self.target.texts.insert_record_stream(
802
 
                    self.source.texts.get_record_stream(
803
 
                        self.source.texts.keys(), 'topological', False))
804
 
                pb.update('Copying inventory', 0, 1)
805
 
                self.target.inventories.insert_record_stream(
806
 
                    self.source.inventories.get_record_stream(
807
 
                        self.source.inventories.keys(), 'topological', False))
808
 
                self.target.signatures.insert_record_stream(
809
 
                    self.source.signatures.get_record_stream(
810
 
                        self.source.signatures.keys(),
811
 
                        'unordered', True))
812
 
                self.target.revisions.insert_record_stream(
813
 
                    self.source.revisions.get_record_stream(
814
 
                        self.source.revisions.keys(),
815
 
                        'topological', True))
816
 
            finally:
817
 
                pb.finished()
818
 
        else:
819
 
            self.target.fetch(self.source, revision_id=revision_id)
820
 
 
821
 
    @needs_read_lock
822
 
    def search_missing_revision_ids(self,
823
 
            revision_id=symbol_versioning.DEPRECATED_PARAMETER,
824
 
            find_ghosts=True, revision_ids=None, if_present_ids=None,
825
 
            limit=None):
826
 
        """See InterRepository.search_missing_revision_ids()."""
827
 
        # we want all revisions to satisfy revision_id in source.
828
 
        # but we don't want to stat every file here and there.
829
 
        # we want then, all revisions other needs to satisfy revision_id
830
 
        # checked, but not those that we have locally.
831
 
        # so the first thing is to get a subset of the revisions to
832
 
        # satisfy revision_id in source, and then eliminate those that
833
 
        # we do already have.
834
 
        # this is slow on high latency connection to self, but as this
835
 
        # disk format scales terribly for push anyway due to rewriting
836
 
        # inventory.weave, this is considered acceptable.
837
 
        # - RBC 20060209
838
 
        if symbol_versioning.deprecated_passed(revision_id):
839
 
            symbol_versioning.warn(
840
 
                'search_missing_revision_ids(revision_id=...) was '
841
 
                'deprecated in 2.4.  Use revision_ids=[...] instead.',
842
 
                DeprecationWarning, stacklevel=2)
843
 
            if revision_ids is not None:
844
 
                raise AssertionError(
845
 
                    'revision_ids is mutually exclusive with revision_id')
846
 
            if revision_id is not None:
847
 
                revision_ids = [revision_id]
848
 
        del revision_id
849
 
        source_ids_set = self._present_source_revisions_for(
850
 
            revision_ids, if_present_ids)
851
 
        # source_ids is the worst possible case we may need to pull.
852
 
        # now we want to filter source_ids against what we actually
853
 
        # have in target, but don't try to check for existence where we know
854
 
        # we do not have a revision as that would be pointless.
855
 
        target_ids = set(self.target._all_possible_ids())
856
 
        possibly_present_revisions = target_ids.intersection(source_ids_set)
857
 
        actually_present_revisions = set(
858
 
            self.target._eliminate_revisions_not_present(possibly_present_revisions))
859
 
        required_revisions = source_ids_set.difference(actually_present_revisions)
860
 
        if revision_ids is not None:
861
 
            # we used get_ancestry to determine source_ids then we are assured all
862
 
            # revisions referenced are present as they are installed in topological order.
863
 
            # and the tip revision was validated by get_ancestry.
864
 
            result_set = required_revisions
865
 
        else:
866
 
            # if we just grabbed the possibly available ids, then
867
 
            # we only have an estimate of whats available and need to validate
868
 
            # that against the revision records.
869
 
            result_set = set(
870
 
                self.source._eliminate_revisions_not_present(required_revisions))
871
 
        if limit is not None:
872
 
            topo_ordered = self.get_graph().iter_topo_order(result_set)
873
 
            result_set = set(itertools.islice(topo_ordered, limit))
874
 
        return self.source.revision_ids_to_search_result(result_set)
875
 
 
876
 
 
877
 
InterRepository.register_optimiser(InterWeaveRepo)
878
 
 
879
 
 
880
 
def get_extra_interrepo_test_combinations():
881
 
    from bzrlib.repofmt import knitrepo
882
 
    return [(InterRepository, RepositoryFormat5(),
883
 
        knitrepo.RepositoryFormatKnit3())]
 
702
_legacy_formats = [RepositoryFormat4(),
 
703
                   RepositoryFormat5(),
 
704
                   RepositoryFormat6()]