376
376
transaction = self.repo.get_transaction()
377
377
revision_versions = repository._RevisionTextVersionCache(self.repo)
378
378
versions = self.revisions.versions()
379
mutter('Prepopulating revision text cache with %d revisions',
379
381
revision_versions.prepopulate_revs(versions)
382
used_file_versions = revision_versions.used_file_versions()
380
383
for num, file_id in enumerate(self.repo.weave_store):
381
384
self.pb.update('Fixing text parents', num,
382
385
len(self.repo.weave_store))
383
386
vf = self.repo.weave_store.get_weave(file_id, transaction)
384
387
vf_checker = self.repo.get_versioned_file_checker(
385
versions, revision_versions)
386
versions_with_bad_parents = vf_checker.check_file_version_parents(
388
if len(versions_with_bad_parents) == 0:
388
vf.versions(), revision_versions)
389
versions_with_bad_parents, dangling_file_versions = \
390
vf_checker.check_file_version_parents(vf, file_id)
391
if (len(versions_with_bad_parents) == 0 and
392
len(dangling_file_versions) == 0):
390
self._fix_text_parent(file_id, vf, versions_with_bad_parents)
394
full_text_versions = set()
395
unused_versions = set()
396
for dangling_version in dangling_file_versions:
397
version = dangling_version[1]
398
if dangling_version in used_file_versions:
399
# This version *is* used by some revision, even though it
400
# isn't used by its own revision! We make sure any
401
# revision referencing it is stored as a fulltext
402
# This avoids bug 155730: it means that clients looking at
403
# inventories to determine the versions to fetch will not
404
# miss a required version. (So clients can assume that if
405
# they have a complete revision graph, and fetch all file
406
# versions named by those revisions inventories, then they
407
# will not have any missing parents for 'delta' knit
409
# XXX: A better, but more difficult and slower fix would be
410
# to rewrite the inventories referencing this version.
411
full_text_versions.add(version)
413
# This version is totally unreferenced. It should be
415
unused_versions.add(version)
416
self._fix_text_parent(file_id, vf, versions_with_bad_parents,
417
full_text_versions, unused_versions)
392
def _fix_text_parent(self, file_id, vf, versions_with_bad_parents):
419
def _fix_text_parent(self, file_id, vf, versions_with_bad_parents,
420
full_text_versions, unused_versions):
393
421
"""Fix bad versionedfile entries in a single versioned file."""
422
mutter('fixing text parent: %r (%d versions)', file_id,
423
len(versions_with_bad_parents))
424
mutter('(%d need to be full texts, %d are unused)',
425
len(full_text_versions), len(unused_versions))
394
426
new_vf = self.repo.weave_store.get_empty('temp:%s' % file_id,
395
427
self.transaction)
401
433
parents = vf.get_parents(version)
402
434
new_parents[version] = parents
403
435
for version in TopoSorter(new_parents.items()).iter_topo_order():
404
new_vf.add_lines(version, new_parents[version],
405
vf.get_lines(version))
436
if version in unused_versions:
438
lines = vf.get_lines(version)
439
parents = new_parents[version]
440
if parents and (parents[0] in full_text_versions):
441
# Force this record to be a fulltext, not a delta.
442
new_vf._add(version, lines, parents, False,
443
None, None, None, False)
445
new_vf.add_lines(version, parents, lines)
406
446
self.repo.weave_store.copy(new_vf, file_id, self.transaction)
407
447
self.repo.weave_store.delete('temp:%s' % file_id, self.transaction)