~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/reconcile.py

(Andrew Bennetts) Reconcile will force file versions with unreferenced parents to be stored as fulltexts (fixes bug 155730).

Show diffs side-by-side

added added

removed removed

Lines of Context:
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',
 
380
                len(versions))
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(
387
 
                vf, file_id)
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):
389
393
                continue
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
 
408
                    # records.)
 
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)
 
412
                else:
 
413
                    # This version is totally unreferenced.  It should be
 
414
                    # removed.
 
415
                    unused_versions.add(version)
 
416
            self._fix_text_parent(file_id, vf, versions_with_bad_parents,
 
417
                full_text_versions, unused_versions)
391
418
 
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)
396
428
        new_parents = {}
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:
 
437
                continue
 
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)
 
444
            else:
 
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)
408
448