/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to bzrlib/repofmt/weaverepo.py

  • Committer: Robert Collins
  • Date: 2010-05-06 11:08:10 UTC
  • mto: This revision was merged to the branch mainline in revision 5223.
  • Revision ID: robertc@robertcollins.net-20100506110810-h3j07fh5gmw54s25
Cleaner matcher matching revised unlocking protocol.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2007-2011 Canonical Ltd
 
1
# Copyright (C) 2007-2010 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
20
20
ghosts.
21
21
"""
22
22
 
23
 
from __future__ import absolute_import
24
 
 
25
 
import gzip
26
23
import os
 
24
from cStringIO import StringIO
 
25
import urllib
27
26
 
28
 
from ...lazy_import import lazy_import
 
27
from bzrlib.lazy_import import lazy_import
29
28
lazy_import(globals(), """
30
 
import itertools
31
 
 
32
 
from breezy import (
 
29
from bzrlib import (
 
30
    xml5,
33
31
    graph as _mod_graph,
34
 
    ui,
35
 
    )
36
 
from breezy.bzr import (
37
 
    xml5,
38
32
    )
39
33
""")
40
 
from ... import (
 
34
from bzrlib import (
 
35
    bzrdir,
41
36
    debug,
42
37
    errors,
43
38
    lockable_files,
44
39
    lockdir,
45
40
    osutils,
 
41
    revision as _mod_revision,
46
42
    trace,
47
 
    tuned_gzip,
48
43
    urlutils,
49
 
    )
50
 
from ...bzr import (
51
44
    versionedfile,
52
45
    weave,
53
46
    weavefile,
54
47
    )
55
 
from ...repository import (
56
 
    InterRepository,
57
 
    )
58
 
from ...bzr.repository import (
59
 
    RepositoryFormatMetaDir,
60
 
    )
61
 
from ...sixish import (
62
 
    BytesIO,
63
 
    text_type,
64
 
    )
65
 
from .store.text import TextStore
66
 
from ...bzr.versionedfile import (
 
48
from bzrlib.decorators import needs_read_lock, needs_write_lock
 
49
from bzrlib.repository import (
 
50
    CommitBuilder,
 
51
    MetaDirVersionedFileRepository,
 
52
    MetaDirRepositoryFormat,
 
53
    Repository,
 
54
    RepositoryFormat,
 
55
    )
 
56
from bzrlib.store.text import TextStore
 
57
from bzrlib.tuned_gzip import GzipFile, bytes_to_gzip
 
58
from bzrlib.versionedfile import (
67
59
    AbsentContentFactory,
68
60
    FulltextContentFactory,
69
61
    VersionedFiles,
70
62
    )
71
 
from ...bzr.vf_repository import (
72
 
    InterSameDataRepository,
73
 
    VersionedFileCommitBuilder,
74
 
    VersionedFileRepository,
75
 
    VersionedFileRepositoryFormat,
76
 
    MetaDirVersionedFileRepository,
77
 
    MetaDirVersionedFileRepositoryFormat,
78
 
    )
79
 
 
80
 
from . import bzrdir as weave_bzrdir
81
 
 
82
 
 
83
 
class AllInOneRepository(VersionedFileRepository):
 
63
 
 
64
 
 
65
class AllInOneRepository(Repository):
84
66
    """Legacy support - the repository behaviour for all-in-one branches."""
85
67
 
86
68
    @property
88
70
        return xml5.serializer_v5
89
71
 
90
72
    def _escape(self, file_or_path):
91
 
        if not isinstance(file_or_path, (str, text_type)):
 
73
        if not isinstance(file_or_path, basestring):
92
74
            file_or_path = '/'.join(file_or_path)
93
75
        if file_or_path == '':
94
76
            return u''
95
77
        return urlutils.escape(osutils.safe_unicode(file_or_path))
96
78
 
97
 
    def __init__(self, _format, a_controldir):
 
79
    def __init__(self, _format, a_bzrdir):
98
80
        # we reuse one control files instance.
99
 
        dir_mode = a_controldir._get_dir_mode()
100
 
        file_mode = a_controldir._get_file_mode()
 
81
        dir_mode = a_bzrdir._get_dir_mode()
 
82
        file_mode = a_bzrdir._get_file_mode()
101
83
 
102
84
        def get_store(name, compressed=True, prefixed=False):
103
85
            # FIXME: This approach of assuming stores are all entirely compressed
105
87
            # some existing branches where there's a mixture; we probably
106
88
            # still want the option to look for both.
107
89
            relpath = self._escape(name)
108
 
            store = TextStore(a_controldir.transport.clone(relpath),
 
90
            store = TextStore(a_bzrdir.transport.clone(relpath),
109
91
                              prefixed=prefixed, compressed=compressed,
110
92
                              dir_mode=dir_mode,
111
93
                              file_mode=file_mode)
118
100
            # which allows access to this old info.
119
101
            self.inventory_store = get_store('inventory-store')
120
102
            self._text_store = get_store('text-store')
121
 
        super(AllInOneRepository, self).__init__(_format, a_controldir, a_controldir._control_files)
 
103
        super(AllInOneRepository, self).__init__(_format, a_bzrdir, a_bzrdir._control_files)
122
104
 
 
105
    @needs_read_lock
123
106
    def _all_possible_ids(self):
124
107
        """Return all the possible revisions that we could find."""
125
108
        if 'evil' in debug.debug_flags:
126
109
            trace.mutter_callsite(
127
110
                3, "_all_possible_ids scales with size of history.")
128
 
        with self.lock_read():
129
 
            return [key[-1] for key in self.inventories.keys()]
 
111
        return [key[-1] for key in self.inventories.keys()]
130
112
 
 
113
    @needs_read_lock
131
114
    def _all_revision_ids(self):
132
115
        """Returns a list of all the revision ids in the repository.
133
116
 
135
118
        present: for weaves ghosts may lead to a lack of correctness until
136
119
        the reweave updates the parents list.
137
120
        """
138
 
        with self.lock_read():
139
 
            return [key[-1] for key in self.revisions.keys()]
 
121
        return [key[-1] for key in self.revisions.keys()]
140
122
 
141
123
    def _activate_new_inventory(self):
142
124
        """Put a replacement inventory.new into use as inventories."""
143
125
        # Copy the content across
144
 
        t = self.controldir._control_files._transport
 
126
        t = self.bzrdir._control_files._transport
145
127
        t.copy('inventory.new.weave', 'inventory.weave')
146
128
        # delete the temp inventory
147
129
        t.delete('inventory.new.weave')
149
131
        self.inventories.keys()
150
132
 
151
133
    def _backup_inventory(self):
152
 
        t = self.controldir._control_files._transport
 
134
        t = self.bzrdir._control_files._transport
153
135
        t.copy('inventory.weave', 'inventory.backup.weave')
154
136
 
155
137
    def _temp_inventories(self):
156
 
        t = self.controldir._control_files._transport
 
138
        t = self.bzrdir._control_files._transport
157
139
        return self._format._get_inventories(t, self, 'inventory.new')
158
140
 
159
141
    def get_commit_builder(self, branch, parents, config, timestamp=None,
160
142
                           timezone=None, committer=None, revprops=None,
161
 
                           revision_id=None, lossy=False):
 
143
                           revision_id=None):
162
144
        self._check_ascii_revisionid(revision_id, self.get_commit_builder)
163
 
        result = VersionedFileCommitBuilder(self, parents, config, timestamp,
164
 
            timezone, committer, revprops, revision_id, lossy=lossy)
 
145
        result = CommitBuilder(self, parents, config, timestamp, timezone,
 
146
                              committer, revprops, revision_id)
165
147
        self.start_write_group()
166
148
        return result
167
149
 
 
150
    @needs_read_lock
 
151
    def get_revisions(self, revision_ids):
 
152
        revs = self._get_revisions(revision_ids)
 
153
        return revs
 
154
 
168
155
    def _inventory_add_lines(self, revision_id, parents, lines,
169
156
        check_content=True):
170
157
        """Store lines in inv_vf and return the sha1 of the inventory."""
180
167
        """AllInOne repositories cannot be shared."""
181
168
        return False
182
169
 
 
170
    @needs_write_lock
183
171
    def set_make_working_trees(self, new_value):
184
172
        """Set the policy flag for making working trees when creating branches.
185
173
 
195
183
        """Returns the policy for making working trees on new branches."""
196
184
        return True
197
185
 
 
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
 
198
191
 
199
192
class WeaveMetaDirRepository(MetaDirVersionedFileRepository):
200
193
    """A subclass of MetaDirRepository to set weave specific policy."""
201
194
 
202
 
    def __init__(self, _format, a_controldir, control_files):
203
 
        super(WeaveMetaDirRepository, self).__init__(
204
 
                _format, a_controldir, control_files)
 
195
    def __init__(self, _format, a_bzrdir, control_files):
 
196
        super(WeaveMetaDirRepository, self).__init__(_format, a_bzrdir, control_files)
205
197
        self._serializer = _format._serializer
206
198
 
 
199
    @needs_read_lock
207
200
    def _all_possible_ids(self):
208
201
        """Return all the possible revisions that we could find."""
209
202
        if 'evil' in debug.debug_flags:
210
203
            trace.mutter_callsite(
211
204
                3, "_all_possible_ids scales with size of history.")
212
 
        with self.lock_read():
213
 
            return [key[-1] for key in self.inventories.keys()]
 
205
        return [key[-1] for key in self.inventories.keys()]
214
206
 
 
207
    @needs_read_lock
215
208
    def _all_revision_ids(self):
216
209
        """Returns a list of all the revision ids in the repository.
217
210
 
219
212
        present: for weaves ghosts may lead to a lack of correctness until
220
213
        the reweave updates the parents list.
221
214
        """
222
 
        with self.lock_read():
223
 
            return [key[-1] for key in self.revisions.keys()]
 
215
        return [key[-1] for key in self.revisions.keys()]
224
216
 
225
217
    def _activate_new_inventory(self):
226
218
        """Put a replacement inventory.new into use as inventories."""
242
234
 
243
235
    def get_commit_builder(self, branch, parents, config, timestamp=None,
244
236
                           timezone=None, committer=None, revprops=None,
245
 
                           revision_id=None, lossy=False):
 
237
                           revision_id=None):
246
238
        self._check_ascii_revisionid(revision_id, self.get_commit_builder)
247
 
        result = VersionedFileCommitBuilder(self, parents, config, timestamp,
248
 
            timezone, committer, revprops, revision_id, lossy=lossy)
 
239
        result = CommitBuilder(self, parents, config, timestamp, timezone,
 
240
                              committer, revprops, revision_id)
249
241
        self.start_write_group()
250
242
        return result
251
243
 
 
244
    @needs_read_lock
252
245
    def get_revision(self, revision_id):
253
246
        """Return the Revision object for a named revision"""
254
 
        with self.lock_read():
255
 
            return self.get_revision_reconcile(revision_id)
 
247
        r = self.get_revision_reconcile(revision_id)
 
248
        return r
256
249
 
257
250
    def _inventory_add_lines(self, revision_id, parents, lines,
258
251
        check_content=True):
265
258
        return self.inventories.add_lines((revision_id,), final_parents, lines,
266
259
            check_content=check_content)[0]
267
260
 
268
 
 
269
 
class PreSplitOutRepositoryFormat(VersionedFileRepositoryFormat):
 
261
    def revision_graph_can_have_wrong_parents(self):
 
262
        return False
 
263
 
 
264
 
 
265
class PreSplitOutRepositoryFormat(RepositoryFormat):
270
266
    """Base class for the pre split out repository formats."""
271
267
 
272
268
    rich_root_data = False
274
270
    supports_ghosts = False
275
271
    supports_external_lookups = False
276
272
    supports_chks = False
277
 
    supports_nesting_repositories = True
278
273
    _fetch_order = 'topological'
279
274
    _fetch_reconcile = True
280
275
    fast_deltas = False
281
 
    supports_leaving_lock = False
282
 
    supports_overriding_transport = False
283
 
    # XXX: This is an old format that we don't support full checking on, so
284
 
    # just claim that checking for this inconsistency is not required.
285
 
    revision_graph_can_have_wrong_parents = False
286
276
 
287
 
    def initialize(self, a_controldir, shared=False, _internal=False):
 
277
    def initialize(self, a_bzrdir, shared=False, _internal=False):
288
278
        """Create a weave repository."""
289
279
        if shared:
290
 
            raise errors.IncompatibleFormat(self, a_controldir._format)
 
280
            raise errors.IncompatibleFormat(self, a_bzrdir._format)
291
281
 
292
282
        if not _internal:
293
283
            # always initialized when the bzrdir is.
294
 
            return self.open(a_controldir, _found=True)
 
284
            return self.open(a_bzrdir, _found=True)
295
285
 
296
286
        # Create an empty weave
297
 
        sio = BytesIO()
 
287
        sio = StringIO()
298
288
        weavefile.write_weave_v5(weave.Weave(), sio)
299
289
        empty_weave = sio.getvalue()
300
290
 
301
 
        trace.mutter('creating repository in %s.', a_controldir.transport.base)
 
291
        trace.mutter('creating repository in %s.', a_bzrdir.transport.base)
302
292
 
303
293
        # FIXME: RBC 20060125 don't peek under the covers
304
294
        # NB: no need to escape relative paths that are url safe.
305
 
        control_files = lockable_files.LockableFiles(a_controldir.transport,
 
295
        control_files = lockable_files.LockableFiles(a_bzrdir.transport,
306
296
            'branch-lock', lockable_files.TransportLock)
307
297
        control_files.create_lock()
308
298
        control_files.lock_write()
309
 
        transport = a_controldir.transport
 
299
        transport = a_bzrdir.transport
310
300
        try:
311
 
            transport.mkdir('revision-store',
312
 
                            mode=a_controldir._get_dir_mode())
313
 
            transport.mkdir('weaves', mode=a_controldir._get_dir_mode())
 
301
            transport.mkdir_multi(['revision-store', 'weaves'],
 
302
                mode=a_bzrdir._get_dir_mode())
314
303
            transport.put_bytes_non_atomic('inventory.weave', empty_weave,
315
 
                mode=a_controldir._get_file_mode())
 
304
                mode=a_bzrdir._get_file_mode())
316
305
        finally:
317
306
            control_files.unlock()
318
 
        repository = self.open(a_controldir, _found=True)
319
 
        self._run_post_repo_init_hooks(repository, a_controldir, shared)
 
307
        repository = self.open(a_bzrdir, _found=True)
 
308
        self._run_post_repo_init_hooks(repository, a_bzrdir, shared)
320
309
        return repository
321
310
 
322
 
    def open(self, a_controldir, _found=False):
 
311
    def open(self, a_bzrdir, _found=False):
323
312
        """See RepositoryFormat.open()."""
324
313
        if not _found:
325
314
            # we are being called directly and must probe.
326
315
            raise NotImplementedError
327
316
 
328
 
        repo_transport = a_controldir.get_repository_transport(None)
329
 
        result = AllInOneRepository(_format=self, a_controldir=a_controldir)
 
317
        repo_transport = a_bzrdir.get_repository_transport(None)
 
318
        control_files = a_bzrdir._control_files
 
319
        result = AllInOneRepository(_format=self, a_bzrdir=a_bzrdir)
330
320
        result.revisions = self._get_revisions(repo_transport, result)
331
321
        result.signatures = self._get_signatures(repo_transport, result)
332
322
        result.inventories = self._get_inventories(repo_transport, result)
334
324
        result.chk_bytes = None
335
325
        return result
336
326
 
337
 
    def is_deprecated(self):
338
 
        return True
339
 
 
340
327
 
341
328
class RepositoryFormat4(PreSplitOutRepositoryFormat):
342
329
    """Bzr repository format 4.
350
337
    has been removed.
351
338
    """
352
339
 
353
 
    supports_funky_characters = False
354
 
 
355
 
    _matchingcontroldir = weave_bzrdir.BzrDirFormat4()
 
340
    _matchingbzrdir = bzrdir.BzrDirFormat4()
356
341
 
357
342
    def get_format_description(self):
358
343
        """See RepositoryFormat.get_format_description()."""
376
361
        return None
377
362
 
378
363
    def _get_revisions(self, repo_transport, repo):
379
 
        from .xml4 import serializer_v4
 
364
        from bzrlib.xml4 import serializer_v4
380
365
        return RevisionTextStore(repo_transport.clone('revision-store'),
381
366
            serializer_v4, True, versionedfile.PrefixMapper(),
382
367
            repo.is_locked, repo.is_write_locked)
400
385
    """
401
386
 
402
387
    _versionedfile_class = weave.WeaveFile
403
 
    _matchingcontroldir = weave_bzrdir.BzrDirFormat5()
404
 
    supports_funky_characters = False
405
 
 
 
388
    _matchingbzrdir = bzrdir.BzrDirFormat5()
406
389
    @property
407
390
    def _serializer(self):
408
391
        return xml5.serializer_v5
413
396
 
414
397
    def network_name(self):
415
398
        """The network name for this format is the control dirs disk label."""
416
 
        return self._matchingcontroldir.get_format_string()
 
399
        return self._matchingbzrdir.get_format_string()
417
400
 
418
401
    def _get_inventories(self, repo_transport, repo, name='inventory'):
419
402
        mapper = versionedfile.ConstantMapper(name)
447
430
    """
448
431
 
449
432
    _versionedfile_class = weave.WeaveFile
450
 
    _matchingcontroldir = weave_bzrdir.BzrDirFormat6()
451
 
    supports_funky_characters = False
 
433
    _matchingbzrdir = bzrdir.BzrDirFormat6()
452
434
    @property
453
435
    def _serializer(self):
454
436
        return xml5.serializer_v5
459
441
 
460
442
    def network_name(self):
461
443
        """The network name for this format is the control dirs disk label."""
462
 
        return self._matchingcontroldir.get_format_string()
 
444
        return self._matchingbzrdir.get_format_string()
463
445
 
464
446
    def _get_inventories(self, repo_transport, repo, name='inventory'):
465
447
        mapper = versionedfile.ConstantMapper(name)
483
465
            weave.WeaveFile, mapper, repo.is_locked)
484
466
 
485
467
 
486
 
class RepositoryFormat7(MetaDirVersionedFileRepositoryFormat):
 
468
class RepositoryFormat7(MetaDirRepositoryFormat):
487
469
    """Bzr repository 7.
488
470
 
489
471
    This repository format has:
498
480
    _versionedfile_class = weave.WeaveFile
499
481
    supports_ghosts = False
500
482
    supports_chks = False
501
 
    supports_funky_characters = False
502
 
    revision_graph_can_have_wrong_parents = False
503
483
 
504
484
    _fetch_order = 'topological'
505
485
    _fetch_reconcile = True
508
488
    def _serializer(self):
509
489
        return xml5.serializer_v5
510
490
 
511
 
    @classmethod
512
 
    def get_format_string(cls):
 
491
    def get_format_string(self):
513
492
        """See RepositoryFormat.get_format_string()."""
514
 
        return b"Bazaar-NG Repository format 7"
 
493
        return "Bazaar-NG Repository format 7"
515
494
 
516
495
    def get_format_description(self):
517
496
        """See RepositoryFormat.get_format_description()."""
538
517
        return versionedfile.ThunkedVersionedFiles(base_transport,
539
518
            weave.WeaveFile, mapper, repo.is_locked)
540
519
 
541
 
    def initialize(self, a_controldir, shared=False):
 
520
    def initialize(self, a_bzrdir, shared=False):
542
521
        """Create a weave repository.
543
522
 
544
523
        :param shared: If true the repository will be initialized as a shared
545
524
                       repository.
546
525
        """
547
526
        # Create an empty weave
548
 
        sio = BytesIO()
 
527
        sio = StringIO()
549
528
        weavefile.write_weave_v5(weave.Weave(), sio)
550
529
        empty_weave = sio.getvalue()
551
530
 
552
 
        trace.mutter('creating repository in %s.', a_controldir.transport.base)
 
531
        trace.mutter('creating repository in %s.', a_bzrdir.transport.base)
553
532
        dirs = ['revision-store', 'weaves']
554
 
        files = [('inventory.weave', BytesIO(empty_weave)),
 
533
        files = [('inventory.weave', StringIO(empty_weave)),
555
534
                 ]
556
535
        utf8_files = [('format', self.get_format_string())]
557
536
 
558
 
        self._upload_blank_content(a_controldir, dirs, files, utf8_files, shared)
559
 
        return self.open(a_controldir=a_controldir, _found=True)
 
537
        self._upload_blank_content(a_bzrdir, dirs, files, utf8_files, shared)
 
538
        return self.open(a_bzrdir=a_bzrdir, _found=True)
560
539
 
561
 
    def open(self, a_controldir, _found=False, _override_transport=None):
 
540
    def open(self, a_bzrdir, _found=False, _override_transport=None):
562
541
        """See RepositoryFormat.open().
563
542
 
564
543
        :param _override_transport: INTERNAL USE ONLY. Allows opening the
566
545
                                    than normal. I.e. during 'upgrade'.
567
546
        """
568
547
        if not _found:
569
 
            format = RepositoryFormatMetaDir.find_format(a_controldir)
 
548
            format = RepositoryFormat.find_format(a_bzrdir)
570
549
        if _override_transport is not None:
571
550
            repo_transport = _override_transport
572
551
        else:
573
 
            repo_transport = a_controldir.get_repository_transport(None)
 
552
            repo_transport = a_bzrdir.get_repository_transport(None)
574
553
        control_files = lockable_files.LockableFiles(repo_transport,
575
554
                                'lock', lockdir.LockDir)
576
 
        result = WeaveMetaDirRepository(_format=self, a_controldir=a_controldir,
 
555
        result = WeaveMetaDirRepository(_format=self, a_bzrdir=a_bzrdir,
577
556
            control_files=control_files)
578
557
        result.revisions = self._get_revisions(repo_transport, result)
579
558
        result.signatures = self._get_signatures(repo_transport, result)
583
562
        result._transport = repo_transport
584
563
        return result
585
564
 
586
 
    def is_deprecated(self):
587
 
        return True
588
 
 
589
565
 
590
566
class TextVersionedFiles(VersionedFiles):
591
567
    """Just-a-bunch-of-files based VersionedFile stores."""
607
583
            raise errors.ObjectNotLocked(self)
608
584
        if not self._can_write():
609
585
            raise errors.ReadOnlyError(self)
610
 
        if b'/' in key[-1]:
 
586
        if '/' in key[-1]:
611
587
            raise ValueError('bad idea to put / in %r' % (key,))
612
 
        chunks = lines
 
588
        text = ''.join(lines)
613
589
        if self._compressed:
614
 
            chunks = tuned_gzip.chunks_to_gzip(chunks)
 
590
            text = bytes_to_gzip(text)
615
591
        path = self._map(key)
616
 
        self._transport.put_file_non_atomic(
617
 
                path, BytesIO(b''.join(chunks)),
618
 
                create_parent_dir=True)
 
592
        self._transport.put_bytes_non_atomic(path, text, create_parent_dir=True)
619
593
 
620
594
    def insert_record_stream(self, stream):
621
595
        adapters = {}
639
613
                    record, record.get_bytes_as(record.storage_kind)))
640
614
                try:
641
615
                    self.add_lines(record.key, None, lines)
642
 
                except errors.RevisionAlreadyPresent:
 
616
                except RevisionAlreadyPresent:
643
617
                    pass
644
618
 
645
619
    def _load_text(self, key):
661
635
            else:
662
636
                return None
663
637
        if compressed:
664
 
            text = gzip.GzipFile(mode='rb', fileobj=BytesIO(text)).read()
 
638
            text = GzipFile(mode='rb', fileobj=StringIO(text)).read()
665
639
        return text
666
640
 
667
641
    def _map(self, key):
714
688
            raise errors.ObjectNotLocked(self)
715
689
        relpaths = set()
716
690
        for quoted_relpath in self._transport.iter_files_recursive():
717
 
            relpath = urlutils.unquote(quoted_relpath)
 
691
            relpath = urllib.unquote(quoted_relpath)
718
692
            path, ext = os.path.splitext(relpath)
719
693
            if ext == '.gz':
720
694
                relpath = path
721
695
            if not relpath.endswith('.sig'):
722
696
                relpaths.add(relpath)
723
697
        paths = list(relpaths)
724
 
        return {self._mapper.unmap(path) for path in paths}
 
698
        return set([self._mapper.unmap(path) for path in paths])
725
699
 
726
700
 
727
701
class SignatureTextStore(TextVersionedFiles):
754
728
            raise errors.ObjectNotLocked(self)
755
729
        relpaths = set()
756
730
        for quoted_relpath in self._transport.iter_files_recursive():
757
 
            relpath = urlutils.unquote(quoted_relpath)
 
731
            relpath = urllib.unquote(quoted_relpath)
758
732
            path, ext = os.path.splitext(relpath)
759
733
            if ext == '.gz':
760
734
                relpath = path
762
736
                continue
763
737
            relpaths.add(relpath[:-4])
764
738
        paths = list(relpaths)
765
 
        return {self._mapper.unmap(path) for path in paths}
766
 
 
767
 
 
768
 
class InterWeaveRepo(InterSameDataRepository):
769
 
    """Optimised code paths between Weave based repositories.
770
 
    """
771
 
 
772
 
    @classmethod
773
 
    def _get_repo_format_to_test(self):
774
 
        return RepositoryFormat7()
775
 
 
776
 
    @staticmethod
777
 
    def is_compatible(source, target):
778
 
        """Be compatible with known Weave formats.
779
 
 
780
 
        We don't test for the stores being of specific types because that
781
 
        could lead to confusing results, and there is no need to be
782
 
        overly general.
783
 
        """
784
 
        try:
785
 
            return (isinstance(source._format, (RepositoryFormat5,
786
 
                                                RepositoryFormat6,
787
 
                                                RepositoryFormat7)) and
788
 
                    isinstance(target._format, (RepositoryFormat5,
789
 
                                                RepositoryFormat6,
790
 
                                                RepositoryFormat7)))
791
 
        except AttributeError:
792
 
            return False
793
 
 
794
 
    def copy_content(self, revision_id=None):
795
 
        """See InterRepository.copy_content()."""
796
 
        with self.lock_write():
797
 
            # weave specific optimised path:
798
 
            try:
799
 
                self.target.set_make_working_trees(self.source.make_working_trees())
800
 
            except (errors.RepositoryUpgradeRequired, NotImplementedError):
801
 
                pass
802
 
            # FIXME do not peek!
803
 
            if self.source._transport.listable():
804
 
                with ui.ui_factory.nested_progress_bar() as pb:
805
 
                    self.target.texts.insert_record_stream(
806
 
                        self.source.texts.get_record_stream(
807
 
                            self.source.texts.keys(), 'topological', False))
808
 
                    pb.update('Copying inventory', 0, 1)
809
 
                    self.target.inventories.insert_record_stream(
810
 
                        self.source.inventories.get_record_stream(
811
 
                            self.source.inventories.keys(), 'topological', False))
812
 
                    self.target.signatures.insert_record_stream(
813
 
                        self.source.signatures.get_record_stream(
814
 
                            self.source.signatures.keys(),
815
 
                            'unordered', True))
816
 
                    self.target.revisions.insert_record_stream(
817
 
                        self.source.revisions.get_record_stream(
818
 
                            self.source.revisions.keys(),
819
 
                            'topological', True))
820
 
            else:
821
 
                self.target.fetch(self.source, revision_id=revision_id)
822
 
 
823
 
    def search_missing_revision_ids(self, find_ghosts=True, revision_ids=None,
824
 
                                    if_present_ids=None, limit=None):
825
 
        """See InterRepository.search_missing_revision_ids()."""
826
 
        with self.lock_read():
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
 
            source_ids_set = self._present_source_revisions_for(
839
 
                revision_ids, if_present_ids)
840
 
            # source_ids is the worst possible case we may need to pull.
841
 
            # now we want to filter source_ids against what we actually
842
 
            # have in target, but don't try to check for existence where we
843
 
            # know we do not have a revision as that would be pointless.
844
 
            target_ids = set(self.target._all_possible_ids())
845
 
            possibly_present_revisions = target_ids.intersection(
846
 
                    source_ids_set)
847
 
            actually_present_revisions = set(
848
 
                self.target._eliminate_revisions_not_present(
849
 
                    possibly_present_revisions))
850
 
            required_revisions = source_ids_set.difference(
851
 
                    actually_present_revisions)
852
 
            if revision_ids is not None:
853
 
                # we used get_ancestry to determine source_ids then we are
854
 
                # assured all revisions referenced are present as they are
855
 
                # installed in topological order. and the tip revision was
856
 
                # validated by get_ancestry.
857
 
                result_set = required_revisions
858
 
            else:
859
 
                # if we just grabbed the possibly available ids, then
860
 
                # we only have an estimate of whats available and need to
861
 
                # validate that against the revision records.
862
 
                result_set = set(
863
 
                    self.source._eliminate_revisions_not_present(
864
 
                        required_revisions))
865
 
            if limit is not None:
866
 
                topo_ordered = self.get_graph().iter_topo_order(result_set)
867
 
                result_set = set(itertools.islice(topo_ordered, limit))
868
 
            return self.source.revision_ids_to_search_result(result_set)
869
 
 
870
 
 
871
 
InterRepository.register_optimiser(InterWeaveRepo)
872
 
 
873
 
 
874
 
def get_extra_interrepo_test_combinations():
875
 
    from ...bzr import knitrepo
876
 
    return [(InterRepository, RepositoryFormat5(),
877
 
        knitrepo.RepositoryFormatKnit3())]
 
739
        return set([self._mapper.unmap(path) for path in paths])
 
740
 
 
741
_legacy_formats = [RepositoryFormat4(),
 
742
                   RepositoryFormat5(),
 
743
                   RepositoryFormat6()]