759
761
result['size'] = t
764
def get_data_stream(self, revision_ids):
765
raise NotImplementedError(self.get_data_stream)
767
def insert_data_stream(self, stream):
768
for item_key, bytes in stream:
769
if item_key[0] == 'file':
770
(file_id,) = item_key[1:]
771
knit = self.weave_store.get_weave_or_empty(
772
file_id, self.get_transaction())
773
elif item_key == ('inventory',):
774
knit = self.get_inventory_weave()
775
elif item_key == ('revisions',):
776
knit = self._revision_store.get_revision_file(
777
self.get_transaction())
778
elif item_key == ('signatures',):
779
knit = self._revision_store.get_signature_file(
780
self.get_transaction())
782
raise RepositoryDataStreamError(
783
"Unrecognised data stream key '%s'" % (item_key,))
784
decoded_list = bencode.bdecode(bytes)
785
format = decoded_list.pop(0)
788
for version, options, parents, some_bytes in decoded_list:
789
data_list.append((version, options, len(some_bytes), parents))
790
knit_bytes += some_bytes
791
knit.insert_data_stream(
792
(format, data_list, StringIO(knit_bytes).read))
763
795
def missing_revision_ids(self, other, revision_id=None):
764
796
"""Return the revision ids that other has that this does not.
1520
1554
revision_id.decode('ascii')
1521
1555
except UnicodeDecodeError:
1522
1556
raise errors.NonAsciiRevisionId(method, self)
1558
def revision_graph_can_have_wrong_parents(self):
1559
"""Is it possible for this repository to have a revision graph with
1562
If True, then this repository must also implement
1563
_find_inconsistent_revision_parents so that check and reconcile can
1564
check for inconsistencies before proceeding with other checks that may
1565
depend on the revision index being consistent.
1567
raise NotImplementedError(self.revision_graph_can_have_wrong_parents)
1526
1569
# remove these delegates a while after bzr 0.15
1527
1570
def __make_delegated(name, from_module):
1528
1571
def _deprecated_repository_forwarder():
2284
2327
return f.count_copied, f.failed_revisions
2287
class InterRemoteRepository(InterRepository):
2288
"""Code for converting between RemoteRepository objects.
2290
This just gets an non-remote repository from the RemoteRepository, and calls
2291
InterRepository.get again.
2294
def __init__(self, source, target):
2295
if isinstance(source, remote.RemoteRepository):
2296
source._ensure_real()
2297
real_source = source._real_repository
2299
real_source = source
2300
if isinstance(target, remote.RemoteRepository):
2301
target._ensure_real()
2302
real_target = target._real_repository
2304
real_target = target
2305
self.real_inter = InterRepository.get(real_source, real_target)
2308
def is_compatible(source, target):
2309
if isinstance(source, remote.RemoteRepository):
2330
class InterRemoteToOther(InterRepository):
2332
def __init__(self, source, target):
2333
InterRepository.__init__(self, source, target)
2334
self._real_inter = None
2337
def is_compatible(source, target):
2338
if not isinstance(source, remote.RemoteRepository):
2340
source._ensure_real()
2341
real_source = source._real_repository
2342
# Is source's model compatible with target's model, and are they the
2343
# same format? Currently we can only optimise fetching from an
2344
# identical model & format repo.
2345
assert not isinstance(real_source, remote.RemoteRepository), (
2346
"We don't support remote repos backed by remote repos yet.")
2347
return real_source._format == target._format
2350
def fetch(self, revision_id=None, pb=None):
2351
"""See InterRepository.fetch()."""
2352
from bzrlib.fetch import RemoteToOtherFetcher
2353
mutter("Using fetch logic to copy between %s(remote) and %s(%s)",
2354
self.source, self.target, self.target._format)
2355
# TODO: jam 20070210 This should be an assert, not a translate
2356
revision_id = osutils.safe_revision_id(revision_id)
2357
f = RemoteToOtherFetcher(to_repository=self.target,
2358
from_repository=self.source,
2359
last_revision=revision_id,
2361
return f.count_copied, f.failed_revisions
2364
def _get_repo_format_to_test(self):
2368
class InterOtherToRemote(InterRepository):
2370
def __init__(self, source, target):
2371
InterRepository.__init__(self, source, target)
2372
self._real_inter = None
2375
def is_compatible(source, target):
2311
2376
if isinstance(target, remote.RemoteRepository):
2380
def _ensure_real_inter(self):
2381
if self._real_inter is None:
2382
self.target._ensure_real()
2383
real_target = self.target._real_repository
2384
self._real_inter = InterRepository.get(self.source, real_target)
2315
2386
def copy_content(self, revision_id=None):
2316
self.real_inter.copy_content(revision_id=revision_id)
2387
self._ensure_real_inter()
2388
self._real_inter.copy_content(revision_id=revision_id)
2318
2390
def fetch(self, revision_id=None, pb=None):
2319
self.real_inter.fetch(revision_id=revision_id, pb=pb)
2391
self._ensure_real_inter()
2392
self._real_inter.fetch(revision_id=revision_id, pb=pb)
2322
2395
def _get_repo_format_to_test(self):
2411
2485
if _unescape_re is None:
2412
2486
_unescape_re = re.compile('\&([^;]*);')
2413
2487
return _unescape_re.sub(_unescaper, data)
2490
class _RevisionTextVersionCache(object):
2491
"""A cache of the versionedfile versions for revision and file-id."""
2493
def __init__(self, repository):
2494
self.repository = repository
2495
self.revision_versions = {}
2497
def add_revision_text_versions(self, tree):
2498
"""Cache text version data from the supplied revision tree"""
2500
for path, entry in tree.iter_entries_by_dir():
2501
inv_revisions[entry.file_id] = entry.revision
2502
self.revision_versions[tree.get_revision_id()] = inv_revisions
2503
return inv_revisions
2505
def get_text_version(self, file_id, revision_id):
2506
"""Determine the text version for a given file-id and revision-id"""
2508
inv_revisions = self.revision_versions[revision_id]
2510
tree = self.repository.revision_tree(revision_id)
2511
inv_revisions = self.add_revision_text_versions(tree)
2512
return inv_revisions.get(file_id)
2515
class VersionedFileChecker(object):
2517
def __init__(self, planned_revisions, revision_versions, repository):
2518
self.planned_revisions = planned_revisions
2519
self.revision_versions = revision_versions
2520
self.repository = repository
2522
def calculate_file_version_parents(self, revision_id, file_id):
2523
text_revision = self.revision_versions.get_text_version(
2524
file_id, revision_id)
2525
if text_revision is None:
2527
parents_of_text_revision = self.repository.get_parents(
2529
parents_from_inventories = []
2530
for parent in parents_of_text_revision:
2531
if parent == _mod_revision.NULL_REVISION:
2534
inventory = self.repository.get_inventory(parent)
2535
except errors.RevisionNotPresent:
2539
introduced_in = inventory[file_id].revision
2540
except errors.NoSuchId:
2543
parents_from_inventories.append(introduced_in)
2544
graph = self.repository.get_graph()
2545
heads = set(graph.heads(parents_from_inventories))
2547
for parent in parents_from_inventories:
2548
if parent in heads and parent not in new_parents:
2549
new_parents.append(parent)
2552
def check_file_version_parents(self, weave, file_id):
2554
for num, revision_id in enumerate(self.planned_revisions):
2555
correct_parents = self.calculate_file_version_parents(
2556
revision_id, file_id)
2557
if correct_parents is None:
2559
text_revision = self.revision_versions.get_text_version(
2560
file_id, revision_id)
2561
knit_parents = weave.get_parents(text_revision)
2562
if correct_parents != knit_parents:
2563
result[revision_id] = (knit_parents, correct_parents)