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
17
"""Deprecated weave-based repository formats.
19
Weave based formats scaled linearly with history size and could not represent
25
from cStringIO import StringIO
28
from bzrlib.lazy_import import lazy_import
29
lazy_import(globals(), """
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
"""Old weave-based repository formats"""
20
from StringIO import StringIO
52
30
from bzrlib.decorators import needs_read_lock, needs_write_lock
53
31
from bzrlib.repository import (
33
MetaDirRepositoryFormat,
57
37
from bzrlib.store.text import TextStore
58
from bzrlib.versionedfile import (
60
FulltextContentFactory,
63
from bzrlib.vf_repository import (
64
InterSameDataRepository,
65
VersionedFileCommitBuilder,
66
VersionedFileRepository,
67
VersionedFileRepositoryFormat,
68
MetaDirVersionedFileRepository,
69
MetaDirVersionedFileRepositoryFormat,
72
from bzrlib.plugins.weave_fmt import bzrdir as weave_bzrdir
75
class AllInOneRepository(VersionedFileRepository):
38
from bzrlib.trace import mutter
41
class AllInOneRepository(Repository):
76
42
"""Legacy support - the repository behaviour for all-in-one branches."""
79
def _serializer(self):
80
return xml5.serializer_v5
82
def _escape(self, file_or_path):
83
if not isinstance(file_or_path, basestring):
84
file_or_path = '/'.join(file_or_path)
85
if file_or_path == '':
87
return urlutils.escape(osutils.safe_unicode(file_or_path))
89
def __init__(self, _format, a_bzrdir):
44
_serializer = xml5.serializer_v5
46
def __init__(self, _format, a_bzrdir, _revision_store, control_store, text_store):
90
47
# we reuse one control files instance.
91
dir_mode = a_bzrdir._get_dir_mode()
92
file_mode = a_bzrdir._get_file_mode()
48
dir_mode = a_bzrdir._control_files._dir_mode
49
file_mode = a_bzrdir._control_files._file_mode
94
51
def get_store(name, compressed=True, prefixed=False):
95
52
# FIXME: This approach of assuming stores are all entirely compressed
96
# or entirely uncompressed is tidy, but breaks upgrade from
97
# some existing branches where there's a mixture; we probably
53
# or entirely uncompressed is tidy, but breaks upgrade from
54
# some existing branches where there's a mixture; we probably
98
55
# still want the option to look for both.
99
relpath = self._escape(name)
100
store = TextStore(a_bzrdir.transport.clone(relpath),
56
relpath = a_bzrdir._control_files._escape(name)
57
store = TextStore(a_bzrdir._control_files._transport.clone(relpath),
101
58
prefixed=prefixed, compressed=compressed,
102
59
dir_mode=dir_mode,
103
60
file_mode=file_mode)
61
#if self._transport.should_cache():
62
# cache_path = os.path.join(self.cache_root, name)
63
# os.mkdir(cache_path)
64
# store = bzrlib.store.CachedStore(store, cache_path)
106
67
# not broken out yet because the controlweaves|inventory_store
107
# and texts bits are still different.
68
# and text_store | weave_store bits are still different.
108
69
if isinstance(_format, RepositoryFormat4):
109
# cannot remove these - there is still no consistent api
70
# cannot remove these - there is still no consistent api
110
71
# which allows access to this old info.
111
72
self.inventory_store = get_store('inventory-store')
112
self._text_store = get_store('text-store')
113
super(AllInOneRepository, self).__init__(_format, a_bzrdir, a_bzrdir._control_files)
116
def _all_possible_ids(self):
117
"""Return all the possible revisions that we could find."""
118
if 'evil' in debug.debug_flags:
119
trace.mutter_callsite(
120
3, "_all_possible_ids scales with size of history.")
121
return [key[-1] for key in self.inventories.keys()]
124
def _all_revision_ids(self):
125
"""Returns a list of all the revision ids in the repository.
127
These are in as much topological order as the underlying store can
128
present: for weaves ghosts may lead to a lack of correctness until
129
the reweave updates the parents list.
131
return [key[-1] for key in self.revisions.keys()]
133
def _activate_new_inventory(self):
134
"""Put a replacement inventory.new into use as inventories."""
135
# Copy the content across
136
t = self.bzrdir._control_files._transport
137
t.copy('inventory.new.weave', 'inventory.weave')
138
# delete the temp inventory
139
t.delete('inventory.new.weave')
140
# Check we can parse the new weave properly as a sanity check
141
self.inventories.keys()
143
def _backup_inventory(self):
144
t = self.bzrdir._control_files._transport
145
t.copy('inventory.weave', 'inventory.backup.weave')
147
def _temp_inventories(self):
148
t = self.bzrdir._control_files._transport
149
return self._format._get_inventories(t, self, 'inventory.new')
73
text_store = get_store('text-store')
74
super(AllInOneRepository, self).__init__(_format, a_bzrdir, a_bzrdir._control_files, _revision_store, control_store, text_store)
151
76
def get_commit_builder(self, branch, parents, config, timestamp=None,
152
77
timezone=None, committer=None, revprops=None,
153
revision_id=None, lossy=False):
154
79
self._check_ascii_revisionid(revision_id, self.get_commit_builder)
155
result = VersionedFileCommitBuilder(self, parents, config, timestamp,
156
timezone, committer, revprops, revision_id, lossy=lossy)
157
self.start_write_group()
80
return Repository.get_commit_builder(self, branch, parents, config,
81
timestamp, timezone, committer, revprops, revision_id)
161
def get_revisions(self, revision_ids):
162
revs = self._get_revisions(revision_ids)
165
def _inventory_add_lines(self, revision_id, parents, lines,
167
"""Store lines in inv_vf and return the sha1 of the inventory."""
168
present_parents = self.get_graph().get_parent_map(parents)
170
for parent in parents:
171
if parent in present_parents:
172
final_parents.append((parent,))
173
return self.inventories.add_lines((revision_id,), final_parents, lines,
174
check_content=check_content)[0]
176
84
def is_shared(self):
177
85
"""AllInOne repositories cannot be shared."""
187
95
:param new_value: True to restore the default, False to disable making
190
raise errors.RepositoryUpgradeRequired(self.user_url)
98
raise NotImplementedError(self.set_make_working_trees)
192
100
def make_working_trees(self):
193
101
"""Returns the policy for making working trees on new branches."""
197
class WeaveMetaDirRepository(MetaDirVersionedFileRepository):
105
class WeaveMetaDirRepository(MetaDirRepository):
198
106
"""A subclass of MetaDirRepository to set weave specific policy."""
200
def __init__(self, _format, a_bzrdir, control_files):
201
super(WeaveMetaDirRepository, self).__init__(_format, a_bzrdir, control_files)
202
self._serializer = _format._serializer
205
def _all_possible_ids(self):
206
"""Return all the possible revisions that we could find."""
207
if 'evil' in debug.debug_flags:
208
trace.mutter_callsite(
209
3, "_all_possible_ids scales with size of history.")
210
return [key[-1] for key in self.inventories.keys()]
213
def _all_revision_ids(self):
214
"""Returns a list of all the revision ids in the repository.
216
These are in as much topological order as the underlying store can
217
present: for weaves ghosts may lead to a lack of correctness until
218
the reweave updates the parents list.
220
return [key[-1] for key in self.revisions.keys()]
222
def _activate_new_inventory(self):
223
"""Put a replacement inventory.new into use as inventories."""
224
# Copy the content across
226
t.copy('inventory.new.weave', 'inventory.weave')
227
# delete the temp inventory
228
t.delete('inventory.new.weave')
229
# Check we can parse the new weave properly as a sanity check
230
self.inventories.keys()
232
def _backup_inventory(self):
234
t.copy('inventory.weave', 'inventory.backup.weave')
236
def _temp_inventories(self):
238
return self._format._get_inventories(t, self, 'inventory.new')
108
_serializer = xml5.serializer_v5
240
110
def get_commit_builder(self, branch, parents, config, timestamp=None,
241
111
timezone=None, committer=None, revprops=None,
242
revision_id=None, lossy=False):
243
113
self._check_ascii_revisionid(revision_id, self.get_commit_builder)
244
result = VersionedFileCommitBuilder(self, parents, config, timestamp,
245
timezone, committer, revprops, revision_id, lossy=lossy)
246
self.start_write_group()
250
def get_revision(self, revision_id):
251
"""Return the Revision object for a named revision"""
252
r = self.get_revision_reconcile(revision_id)
255
def _inventory_add_lines(self, revision_id, parents, lines,
257
"""Store lines in inv_vf and return the sha1 of the inventory."""
258
present_parents = self.get_graph().get_parent_map(parents)
260
for parent in parents:
261
if parent in present_parents:
262
final_parents.append((parent,))
263
return self.inventories.add_lines((revision_id,), final_parents, lines,
264
check_content=check_content)[0]
267
class PreSplitOutRepositoryFormat(VersionedFileRepositoryFormat):
114
return MetaDirRepository.get_commit_builder(self, branch, parents,
115
config, timestamp, timezone, committer, revprops, revision_id)
118
class PreSplitOutRepositoryFormat(RepositoryFormat):
268
119
"""Base class for the pre split out repository formats."""
270
121
rich_root_data = False
271
supports_tree_reference = False
272
supports_ghosts = False
273
supports_external_lookups = False
274
supports_chks = False
275
supports_nesting_repositories = True
276
_fetch_order = 'topological'
277
_fetch_reconcile = True
279
supports_leaving_lock = False
280
# XXX: This is an old format that we don't support full checking on, so
281
# just claim that checking for this inconsistency is not required.
282
revision_graph_can_have_wrong_parents = False
284
123
def initialize(self, a_bzrdir, shared=False, _internal=False):
285
"""Create a weave repository."""
124
"""Create a weave repository.
126
TODO: when creating split out bzr branch formats, move this to a common
127
base for Format5, Format6. or something like that.
287
130
raise errors.IncompatibleFormat(self, a_bzrdir._format)
289
132
if not _internal:
290
133
# always initialized when the bzrdir is.
291
134
return self.open(a_bzrdir, _found=True)
293
136
# Create an empty weave
295
138
weavefile.write_weave_v5(weave.Weave(), sio)
296
139
empty_weave = sio.getvalue()
298
trace.mutter('creating repository in %s.', a_bzrdir.transport.base)
141
mutter('creating repository in %s.', a_bzrdir.transport.base)
142
dirs = ['revision-store', 'weaves']
143
files = [('inventory.weave', StringIO(empty_weave)),
300
146
# FIXME: RBC 20060125 don't peek under the covers
301
147
# NB: no need to escape relative paths that are url safe.
302
148
control_files = lockable_files.LockableFiles(a_bzrdir.transport,
303
'branch-lock', lockable_files.TransportLock)
149
'branch-lock', lockable_files.TransportLock)
304
150
control_files.create_lock()
305
151
control_files.lock_write()
306
transport = a_bzrdir.transport
152
control_files._transport.mkdir_multi(dirs,
153
mode=control_files._dir_mode)
308
transport.mkdir_multi(['revision-store', 'weaves'],
309
mode=a_bzrdir._get_dir_mode())
310
transport.put_bytes_non_atomic('inventory.weave', empty_weave,
311
mode=a_bzrdir._get_file_mode())
155
for file, content in files:
156
control_files.put(file, content)
313
158
control_files.unlock()
314
repository = self.open(a_bzrdir, _found=True)
315
self._run_post_repo_init_hooks(repository, a_bzrdir, shared)
159
return self.open(a_bzrdir, _found=True)
161
def _get_control_store(self, repo_transport, control_files):
162
"""Return the control store for this repository."""
163
return self._get_versioned_file_store('',
168
def _get_text_store(self, transport, control_files):
169
"""Get a store for file texts for this format."""
170
raise NotImplementedError(self._get_text_store)
318
172
def open(self, a_bzrdir, _found=False):
319
173
"""See RepositoryFormat.open()."""
399
255
_versionedfile_class = weave.WeaveFile
400
_matchingbzrdir = weave_bzrdir.BzrDirFormat5()
401
supports_funky_characters = False
256
_matchingbzrdir = bzrdir.BzrDirFormat5()
404
def _serializer(self):
405
return xml5.serializer_v5
259
super(RepositoryFormat5, self).__init__()
407
261
def get_format_description(self):
408
262
"""See RepositoryFormat.get_format_description()."""
409
263
return "Weave repository format 5"
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()
415
def _get_inventories(self, repo_transport, repo, name='inventory'):
416
mapper = versionedfile.ConstantMapper(name)
417
return versionedfile.ThunkedVersionedFiles(repo_transport,
418
weave.WeaveFile, mapper, repo.is_locked)
420
def _get_revisions(self, repo_transport, repo):
421
return RevisionTextStore(repo_transport.clone('revision-store'),
422
xml5.serializer_v5, False, versionedfile.PrefixMapper(),
423
repo.is_locked, repo.is_write_locked)
425
def _get_signatures(self, repo_transport, repo):
426
return SignatureTextStore(repo_transport.clone('revision-store'),
427
False, versionedfile.PrefixMapper(),
428
repo.is_locked, repo.is_write_locked)
430
def _get_texts(self, repo_transport, repo):
431
mapper = versionedfile.PrefixMapper()
432
base_transport = repo_transport.clone('weaves')
433
return versionedfile.ThunkedVersionedFiles(base_transport,
434
weave.WeaveFile, mapper, repo.is_locked)
265
def _get_revision_store(self, repo_transport, control_files):
266
"""See RepositoryFormat._get_revision_store()."""
267
"""Return the revision store object for this a_bzrdir."""
268
return self._get_text_rev_store(repo_transport,
273
def _get_text_store(self, transport, control_files):
274
"""See RepositoryFormat._get_text_store()."""
275
return self._get_versioned_file_store('weaves', transport, control_files, prefixed=False)
437
278
class RepositoryFormat6(PreSplitOutRepositoryFormat):
446
287
_versionedfile_class = weave.WeaveFile
447
_matchingbzrdir = weave_bzrdir.BzrDirFormat6()
448
supports_funky_characters = False
450
def _serializer(self):
451
return xml5.serializer_v5
288
_matchingbzrdir = bzrdir.BzrDirFormat6()
291
super(RepositoryFormat6, self).__init__()
453
293
def get_format_description(self):
454
294
"""See RepositoryFormat.get_format_description()."""
455
295
return "Weave repository format 6"
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()
461
def _get_inventories(self, repo_transport, repo, name='inventory'):
462
mapper = versionedfile.ConstantMapper(name)
463
return versionedfile.ThunkedVersionedFiles(repo_transport,
464
weave.WeaveFile, mapper, repo.is_locked)
466
def _get_revisions(self, repo_transport, repo):
467
return RevisionTextStore(repo_transport.clone('revision-store'),
468
xml5.serializer_v5, False, versionedfile.HashPrefixMapper(),
469
repo.is_locked, repo.is_write_locked)
471
def _get_signatures(self, repo_transport, repo):
472
return SignatureTextStore(repo_transport.clone('revision-store'),
473
False, versionedfile.HashPrefixMapper(),
474
repo.is_locked, repo.is_write_locked)
476
def _get_texts(self, repo_transport, repo):
477
mapper = versionedfile.HashPrefixMapper()
478
base_transport = repo_transport.clone('weaves')
479
return versionedfile.ThunkedVersionedFiles(base_transport,
480
weave.WeaveFile, mapper, repo.is_locked)
483
class RepositoryFormat7(MetaDirVersionedFileRepositoryFormat):
297
def _get_revision_store(self, repo_transport, control_files):
298
"""See RepositoryFormat._get_revision_store()."""
299
return self._get_text_rev_store(repo_transport,
305
def _get_text_store(self, transport, control_files):
306
"""See RepositoryFormat._get_text_store()."""
307
return self._get_versioned_file_store('weaves', transport, control_files)
310
class RepositoryFormat7(MetaDirRepositoryFormat):
484
311
"""Bzr repository 7.
486
313
This repository format has:
545
365
weavefile.write_weave_v5(weave.Weave(), sio)
546
366
empty_weave = sio.getvalue()
548
trace.mutter('creating repository in %s.', a_bzrdir.transport.base)
368
mutter('creating repository in %s.', a_bzrdir.transport.base)
549
369
dirs = ['revision-store', 'weaves']
550
files = [('inventory.weave', StringIO(empty_weave)),
370
files = [('inventory.weave', StringIO(empty_weave)),
552
372
utf8_files = [('format', self.get_format_string())]
554
374
self._upload_blank_content(a_bzrdir, dirs, files, utf8_files, shared)
555
375
return self.open(a_bzrdir=a_bzrdir, _found=True)
557
377
def open(self, a_bzrdir, _found=False, _override_transport=None):
558
378
"""See RepositoryFormat.open().
560
380
:param _override_transport: INTERNAL USE ONLY. Allows opening the
561
381
repository at a slightly different url
562
382
than normal. I.e. during 'upgrade'.
565
385
format = RepositoryFormat.find_format(a_bzrdir)
386
assert format.__class__ == self.__class__
566
387
if _override_transport is not None:
567
388
repo_transport = _override_transport
569
390
repo_transport = a_bzrdir.get_repository_transport(None)
570
391
control_files = lockable_files.LockableFiles(repo_transport,
571
392
'lock', lockdir.LockDir)
572
result = WeaveMetaDirRepository(_format=self, a_bzrdir=a_bzrdir,
573
control_files=control_files)
574
result.revisions = self._get_revisions(repo_transport, result)
575
result.signatures = self._get_signatures(repo_transport, result)
576
result.inventories = self._get_inventories(repo_transport, result)
577
result.texts = self._get_texts(repo_transport, result)
578
result.chk_bytes = None
579
result._transport = repo_transport
582
def is_deprecated(self):
586
class TextVersionedFiles(VersionedFiles):
587
"""Just-a-bunch-of-files based VersionedFile stores."""
589
def __init__(self, transport, compressed, mapper, is_locked, can_write):
590
self._compressed = compressed
591
self._transport = transport
592
self._mapper = mapper
597
self._is_locked = is_locked
598
self._can_write = can_write
600
def add_lines(self, key, parents, lines):
601
"""Add a revision to the store."""
602
if not self._is_locked():
603
raise errors.ObjectNotLocked(self)
604
if not self._can_write():
605
raise errors.ReadOnlyError(self)
607
raise ValueError('bad idea to put / in %r' % (key,))
608
text = ''.join(lines)
610
text = tuned_gzip.bytes_to_gzip(text)
611
path = self._map(key)
612
self._transport.put_bytes_non_atomic(path, text, create_parent_dir=True)
614
def insert_record_stream(self, stream):
616
for record in stream:
617
# Raise an error when a record is missing.
618
if record.storage_kind == 'absent':
619
raise errors.RevisionNotPresent([record.key[0]], self)
620
# adapt to non-tuple interface
621
if record.storage_kind == 'fulltext':
622
self.add_lines(record.key, None,
623
osutils.split_lines(record.get_bytes_as('fulltext')))
625
adapter_key = record.storage_kind, 'fulltext'
627
adapter = adapters[adapter_key]
629
adapter_factory = adapter_registry.get(adapter_key)
630
adapter = adapter_factory(self)
631
adapters[adapter_key] = adapter
632
lines = osutils.split_lines(adapter.get_bytes(
633
record, record.get_bytes_as(record.storage_kind)))
635
self.add_lines(record.key, None, lines)
636
except errors.RevisionAlreadyPresent:
639
def _load_text(self, key):
640
if not self._is_locked():
641
raise errors.ObjectNotLocked(self)
642
path = self._map(key)
644
text = self._transport.get_bytes(path)
645
compressed = self._compressed
646
except errors.NoSuchFile:
648
# try without the .gz
651
text = self._transport.get_bytes(path)
653
except errors.NoSuchFile:
658
text = gzip.GzipFile(mode='rb', fileobj=StringIO(text)).read()
662
return self._mapper.map(key) + self._ext
665
class RevisionTextStore(TextVersionedFiles):
666
"""Legacy thunk for format 4 repositories."""
668
def __init__(self, transport, serializer, compressed, mapper, is_locked,
670
"""Create a RevisionTextStore at transport with serializer."""
671
TextVersionedFiles.__init__(self, transport, compressed, mapper,
672
is_locked, can_write)
673
self._serializer = serializer
675
def _load_text_parents(self, key):
676
text = self._load_text(key)
679
parents = self._serializer.read_revision_from_string(text).parent_ids
680
return text, tuple((parent,) for parent in parents)
682
def get_parent_map(self, keys):
685
parents = self._load_text_parents(key)[1]
688
result[key] = parents
691
def get_known_graph_ancestry(self, keys):
692
"""Get a KnownGraph instance with the ancestry of keys."""
694
parent_map = self.get_parent_map(keys)
695
kg = _mod_graph.KnownGraph(parent_map)
698
def get_record_stream(self, keys, sort_order, include_delta_closure):
700
text, parents = self._load_text_parents(key)
702
yield AbsentContentFactory(key)
704
yield FulltextContentFactory(key, parents, None, text)
707
if not self._is_locked():
708
raise errors.ObjectNotLocked(self)
710
for quoted_relpath in self._transport.iter_files_recursive():
711
relpath = urllib.unquote(quoted_relpath)
712
path, ext = os.path.splitext(relpath)
715
if not relpath.endswith('.sig'):
716
relpaths.add(relpath)
717
paths = list(relpaths)
718
return set([self._mapper.unmap(path) for path in paths])
721
class SignatureTextStore(TextVersionedFiles):
722
"""Legacy thunk for format 4-7 repositories."""
724
def __init__(self, transport, compressed, mapper, is_locked, can_write):
725
TextVersionedFiles.__init__(self, transport, compressed, mapper,
726
is_locked, can_write)
727
self._ext = '.sig' + self._ext
729
def get_parent_map(self, keys):
732
text = self._load_text(key)
738
def get_record_stream(self, keys, sort_order, include_delta_closure):
740
text = self._load_text(key)
742
yield AbsentContentFactory(key)
744
yield FulltextContentFactory(key, None, None, text)
747
if not self._is_locked():
748
raise errors.ObjectNotLocked(self)
750
for quoted_relpath in self._transport.iter_files_recursive():
751
relpath = urllib.unquote(quoted_relpath)
752
path, ext = os.path.splitext(relpath)
755
if not relpath.endswith('.sig'):
757
relpaths.add(relpath[:-4])
758
paths = list(relpaths)
759
return set([self._mapper.unmap(path) for path in paths])
762
class InterWeaveRepo(InterSameDataRepository):
763
"""Optimised code paths between Weave based repositories.
767
def _get_repo_format_to_test(self):
768
return RepositoryFormat7()
771
def is_compatible(source, target):
772
"""Be compatible with known Weave formats.
774
We don't test for the stores being of specific types because that
775
could lead to confusing results, and there is no need to be
779
return (isinstance(source._format, (RepositoryFormat5,
781
RepositoryFormat7)) and
782
isinstance(target._format, (RepositoryFormat5,
785
except AttributeError:
789
def copy_content(self, revision_id=None):
790
"""See InterRepository.copy_content()."""
791
# weave specific optimised path:
793
self.target.set_make_working_trees(self.source.make_working_trees())
794
except (errors.RepositoryUpgradeRequired, NotImplemented):
797
if self.source._transport.listable():
798
pb = ui.ui_factory.nested_progress_bar()
800
self.target.texts.insert_record_stream(
801
self.source.texts.get_record_stream(
802
self.source.texts.keys(), 'topological', False))
803
pb.update('Copying inventory', 0, 1)
804
self.target.inventories.insert_record_stream(
805
self.source.inventories.get_record_stream(
806
self.source.inventories.keys(), 'topological', False))
807
self.target.signatures.insert_record_stream(
808
self.source.signatures.get_record_stream(
809
self.source.signatures.keys(),
811
self.target.revisions.insert_record_stream(
812
self.source.revisions.get_record_stream(
813
self.source.revisions.keys(),
814
'topological', True))
818
self.target.fetch(self.source, revision_id=revision_id)
821
def search_missing_revision_ids(self,
822
revision_id=symbol_versioning.DEPRECATED_PARAMETER,
823
find_ghosts=True, revision_ids=None, if_present_ids=None,
825
"""See InterRepository.search_missing_revision_ids()."""
826
# we want all revisions to satisfy revision_id in source.
827
# but we don't want to stat every file here and there.
828
# we want then, all revisions other needs to satisfy revision_id
829
# checked, but not those that we have locally.
830
# so the first thing is to get a subset of the revisions to
831
# satisfy revision_id in source, and then eliminate those that
832
# we do already have.
833
# this is slow on high latency connection to self, but as this
834
# disk format scales terribly for push anyway due to rewriting
835
# inventory.weave, this is considered acceptable.
837
if symbol_versioning.deprecated_passed(revision_id):
838
symbol_versioning.warn(
839
'search_missing_revision_ids(revision_id=...) was '
840
'deprecated in 2.4. Use revision_ids=[...] instead.',
841
DeprecationWarning, stacklevel=2)
842
if revision_ids is not None:
843
raise AssertionError(
844
'revision_ids is mutually exclusive with revision_id')
845
if revision_id is not None:
846
revision_ids = [revision_id]
848
source_ids_set = self._present_source_revisions_for(
849
revision_ids, if_present_ids)
850
# source_ids is the worst possible case we may need to pull.
851
# now we want to filter source_ids against what we actually
852
# have in target, but don't try to check for existence where we know
853
# we do not have a revision as that would be pointless.
854
target_ids = set(self.target._all_possible_ids())
855
possibly_present_revisions = target_ids.intersection(source_ids_set)
856
actually_present_revisions = set(
857
self.target._eliminate_revisions_not_present(possibly_present_revisions))
858
required_revisions = source_ids_set.difference(actually_present_revisions)
859
if revision_ids is not None:
860
# we used get_ancestry to determine source_ids then we are assured all
861
# revisions referenced are present as they are installed in topological order.
862
# and the tip revision was validated by get_ancestry.
863
result_set = required_revisions
865
# if we just grabbed the possibly available ids, then
866
# we only have an estimate of whats available and need to validate
867
# that against the revision records.
869
self.source._eliminate_revisions_not_present(required_revisions))
870
if limit is not None:
871
topo_ordered = self.get_graph().iter_topo_order(result_set)
872
result_set = set(itertools.islice(topo_ordered, limit))
873
return self.source.revision_ids_to_search_result(result_set)
876
InterRepository.register_optimiser(InterWeaveRepo)
879
def get_extra_interrepo_test_combinations():
880
from bzrlib.repofmt import knitrepo
881
return [(InterRepository, RepositoryFormat5(),
882
knitrepo.RepositoryFormatKnit3())]
393
text_store = self._get_text_store(repo_transport, control_files)
394
control_store = self._get_control_store(repo_transport, control_files)
395
_revision_store = self._get_revision_store(repo_transport, control_files)
396
return WeaveMetaDirRepository(_format=self,
398
control_files=control_files,
399
_revision_store=_revision_store,
400
control_store=control_store,
401
text_store=text_store)
404
_legacy_formats = [RepositoryFormat4(),