~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/repository.py

  • Committer: Canonical.com Patch Queue Manager
  • Date: 2007-10-12 03:57:26 UTC
  • mfrom: (2745.6.62 reconcile-check-heads)
  • Revision ID: pqm@pqm.ubuntu.com-20071012035726-d8e3stq343fqi0bz
(Andrew Bennetts, Aaron Bentley) Reconcile can fix bad parent references.

Show diffs side-by-side

added added

removed removed

Lines of Context:
620
620
        self.weave_store = text_store
621
621
        # for tests
622
622
        self._reconcile_does_inventory_gc = True
 
623
        self._reconcile_fixes_text_parents = False
623
624
        # not right yet - should be more semantically clear ? 
624
625
        # 
625
626
        self.control_store = control_store
1438
1439
                [parents_provider, other_repository._make_parents_provider()])
1439
1440
        return graph.Graph(parents_provider)
1440
1441
 
 
1442
    def get_versioned_file_checker(self, revisions, revision_versions_cache):
 
1443
        return VersionedFileChecker(revisions, revision_versions_cache, self)
 
1444
 
1441
1445
    @needs_write_lock
1442
1446
    def set_make_working_trees(self, new_value):
1443
1447
        """Set the policy flag for making working trees when creating branches.
1472
1476
                                                       self.get_transaction())
1473
1477
 
1474
1478
    @needs_read_lock
1475
 
    def check(self, revision_ids):
 
1479
    def check(self, revision_ids=None):
1476
1480
        """Check consistency of all history of given revision_ids.
1477
1481
 
1478
1482
        Different repository implementations should override _check().
1480
1484
        :param revision_ids: A non-empty list of revision_ids whose ancestry
1481
1485
             will be checked.  Typically the last revision_id of a branch.
1482
1486
        """
1483
 
        if not revision_ids:
1484
 
            raise ValueError("revision_ids must be non-empty in %s.check" 
1485
 
                    % (self,))
1486
1487
        return self._check(revision_ids)
1487
1488
 
1488
1489
    def _check(self, revision_ids):
1516
1517
                    revision_id.decode('ascii')
1517
1518
                except UnicodeDecodeError:
1518
1519
                    raise errors.NonAsciiRevisionId(method, self)
1519
 
 
1520
 
 
1521
 
 
 
1520
    
 
1521
    def revision_graph_can_have_wrong_parents(self):
 
1522
        """Is it possible for this repository to have a revision graph with
 
1523
        incorrect parents?
 
1524
 
 
1525
        If True, then this repository must also implement
 
1526
        _find_inconsistent_revision_parents so that check and reconcile can
 
1527
        check for inconsistencies before proceeding with other checks that may
 
1528
        depend on the revision index being consistent.
 
1529
        """
 
1530
        raise NotImplementedError(self.revision_graph_can_have_wrong_parents)
 
1531
        
1522
1532
# remove these delegates a while after bzr 0.15
1523
1533
def __make_delegated(name, from_module):
1524
1534
    def _deprecated_repository_forwarder():
2407
2417
    if _unescape_re is None:
2408
2418
        _unescape_re = re.compile('\&([^;]*);')
2409
2419
    return _unescape_re.sub(_unescaper, data)
 
2420
 
 
2421
 
 
2422
class _RevisionTextVersionCache(object):
 
2423
    """A cache of the versionedfile versions for revision and file-id."""
 
2424
 
 
2425
    def __init__(self, repository):
 
2426
        self.repository = repository
 
2427
        self.revision_versions = {}
 
2428
 
 
2429
    def add_revision_text_versions(self, tree):
 
2430
        """Cache text version data from the supplied revision tree"""
 
2431
        inv_revisions = {}
 
2432
        for path, entry in tree.iter_entries_by_dir():
 
2433
            inv_revisions[entry.file_id] = entry.revision
 
2434
        self.revision_versions[tree.get_revision_id()] = inv_revisions
 
2435
        return inv_revisions
 
2436
 
 
2437
    def get_text_version(self, file_id, revision_id):
 
2438
        """Determine the text version for a given file-id and revision-id"""
 
2439
        try:
 
2440
            inv_revisions = self.revision_versions[revision_id]
 
2441
        except KeyError:
 
2442
            tree = self.repository.revision_tree(revision_id)
 
2443
            inv_revisions = self.add_revision_text_versions(tree)
 
2444
        return inv_revisions.get(file_id)
 
2445
 
 
2446
 
 
2447
class VersionedFileChecker(object):
 
2448
 
 
2449
    def __init__(self, planned_revisions, revision_versions, repository):
 
2450
        self.planned_revisions = planned_revisions
 
2451
        self.revision_versions = revision_versions
 
2452
        self.repository = repository
 
2453
    
 
2454
    def calculate_file_version_parents(self, revision_id, file_id):
 
2455
        text_revision = self.revision_versions.get_text_version(
 
2456
            file_id, revision_id)
 
2457
        if text_revision is None:
 
2458
            return None
 
2459
        parents_of_text_revision = self.repository.get_parents(
 
2460
            [text_revision])[0]
 
2461
        parents_from_inventories = []
 
2462
        for parent in parents_of_text_revision:
 
2463
            if parent == _mod_revision.NULL_REVISION:
 
2464
                continue
 
2465
            try:
 
2466
                inventory = self.repository.get_inventory(parent)
 
2467
            except errors.RevisionNotPresent:
 
2468
                pass
 
2469
            else:
 
2470
                try:
 
2471
                    introduced_in = inventory[file_id].revision
 
2472
                except errors.NoSuchId:
 
2473
                    pass
 
2474
                else:
 
2475
                    parents_from_inventories.append(introduced_in)
 
2476
        graph = self.repository.get_graph()
 
2477
        heads = set(graph.heads(parents_from_inventories))
 
2478
        new_parents = []
 
2479
        for parent in parents_from_inventories:
 
2480
            if parent in heads and parent not in new_parents:
 
2481
                new_parents.append(parent)
 
2482
        return new_parents
 
2483
 
 
2484
    def check_file_version_parents(self, weave, file_id):
 
2485
        result = {}
 
2486
        for num, revision_id in enumerate(self.planned_revisions):
 
2487
            correct_parents = self.calculate_file_version_parents(
 
2488
                revision_id, file_id)
 
2489
            if correct_parents is None:
 
2490
                continue
 
2491
            text_revision = self.revision_versions.get_text_version(
 
2492
                file_id, revision_id)
 
2493
            knit_parents = weave.get_parents(text_revision)
 
2494
            if correct_parents != knit_parents:
 
2495
                result[revision_id] = (knit_parents, correct_parents)
 
2496
        return result