~bzr-pqm/bzr/1.17

« back to all changes in this revision

Viewing changes to bzrlib/dirstate.py

  • Committer: Canonical.com Patch Queue Manager
  • Date: 2009-07-10 06:35:38 UTC
  • mfrom: (4505.5.9 apply-inventory-delta)
  • Revision ID: pqm@pqm.ubuntu.com-20090710063538-2hap9pxafqfe6r20
(robertc) First tranche of inventory-delta application validation.
        (Robert Collins)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1285
1285
        removals = {}
1286
1286
        for old_path, new_path, file_id, inv_entry in sorted(delta, reverse=True):
1287
1287
            if (file_id in insertions) or (file_id in removals):
1288
 
                raise AssertionError("repeated file id in delta %r" % (file_id,))
 
1288
                raise errors.InconsistentDelta(old_path or new_path, file_id,
 
1289
                    "repeated file_id")
1289
1290
            if old_path is not None:
1290
1291
                old_path = old_path.encode('utf-8')
1291
1292
                removals[file_id] = old_path
1399
1400
        # At the same time, to reduce interface friction we convert the input
1400
1401
        # inventory entries to dirstate.
1401
1402
        root_only = ('', '')
 
1403
        # Accumulate parent references (path and id), to check for parentless
 
1404
        # items or items placed under files/links/tree-references. We get
 
1405
        # references from every item in the delta that is not a deletion and
 
1406
        # is not itself the root.
 
1407
        parents = set()
1402
1408
        for old_path, new_path, file_id, inv_entry in delta:
 
1409
            if inv_entry is not None and file_id != inv_entry.file_id:
 
1410
                raise errors.InconsistentDelta(new_path, file_id,
 
1411
                    "mismatched entry file_id %r" % inv_entry)
 
1412
            if new_path is not None:
 
1413
                new_path_utf8 = encode(new_path)
 
1414
                # note the parent for validation
 
1415
                dirname_utf8, basename_utf8 = osutils.split(new_path_utf8)
 
1416
                if basename_utf8:
 
1417
                    parents.add((dirname_utf8, inv_entry.parent_id))
1403
1418
            if old_path is None:
1404
1419
                adds.append((None, encode(new_path), file_id,
1405
1420
                    inv_to_entry(inv_entry), True))
1420
1435
                # for 'r' items on every pass.
1421
1436
                self._update_basis_apply_deletes(deletes)
1422
1437
                deletes = []
1423
 
                new_path_utf8 = encode(new_path)
1424
1438
                # Split into an add/delete pair recursively.
1425
1439
                adds.append((None, new_path_utf8, file_id,
1426
1440
                    inv_to_entry(inv_entry), False))
1453
1467
                changes.append((encode(old_path), encode(new_path), file_id,
1454
1468
                    inv_to_entry(inv_entry)))
1455
1469
 
1456
 
        # Finish expunging deletes/first half of renames.
1457
 
        self._update_basis_apply_deletes(deletes)
1458
 
        # Reinstate second half of renames and new paths.
1459
 
        self._update_basis_apply_adds(adds)
1460
 
        # Apply in-situ changes.
1461
 
        self._update_basis_apply_changes(changes)
 
1470
        try:
 
1471
            # Finish expunging deletes/first half of renames.
 
1472
            self._update_basis_apply_deletes(deletes)
 
1473
            # Reinstate second half of renames and new paths.
 
1474
            self._update_basis_apply_adds(adds)
 
1475
            # Apply in-situ changes.
 
1476
            self._update_basis_apply_changes(changes)
 
1477
            # Validate parents
 
1478
            self._update_basis_check_parents(parents)
 
1479
        except errors.BzrError, e:
 
1480
            if 'integrity error' not in str(e):
 
1481
                raise
 
1482
            # _get_entry raises BzrError when a request is inconsistent; we
 
1483
            # want such errors to be shown as InconsistentDelta - and that 
 
1484
            # fits the behaviour we trigger. Partof this is driven by dirstate
 
1485
            # only supporting deltas that turn the basis into a closer fit to
 
1486
            # the active tree.
 
1487
            self._changes_aborted = True
 
1488
            raise errors.InconsistentDeltaDelta(delta, "error from _get_entry.")
1462
1489
 
1463
1490
        self._dirblock_state = DirState.IN_MEMORY_MODIFIED
1464
1491
        self._header_state = DirState.IN_MEMORY_MODIFIED
1573
1600
                    # it is being resurrected here, so blank it out temporarily.
1574
1601
                    self._dirblocks[block_index][1][entry_index][1][1] = null
1575
1602
 
 
1603
    def _update_basis_check_parents(self, parents):
 
1604
        """Check that parents required by the delta are all intact."""
 
1605
        for dirname_utf8, file_id in parents:
 
1606
            # Get the entry - the ensures that file_id, dirname_utf8 exists and
 
1607
            # has the right file id.
 
1608
            entry = self._get_entry(1, file_id, dirname_utf8)
 
1609
            if entry[1] is None:
 
1610
                self._changes_aborted = True
 
1611
                raise errors.InconsistentDelta(dirname_utf8.decode('utf8'),
 
1612
                    file_id, "This parent is not present.")
 
1613
            # Parents of things must be directories
 
1614
            if entry[1][1][0] != 'd':
 
1615
                self._changes_aborted = True
 
1616
                raise errors.InconsistentDelta(dirname_utf8.decode('utf8'),
 
1617
                    file_id, "This parent is not a directory.")
 
1618
 
1576
1619
    def _observed_sha1(self, entry, sha1, stat_value,
1577
1620
        _stat_to_minikind=_stat_to_minikind, _pack_stat=pack_stat):
1578
1621
        """Note the sha1 of a file.
1821
1864
        self._read_dirblocks_if_needed()
1822
1865
        if path_utf8 is not None:
1823
1866
            if type(path_utf8) is not str:
1824
 
                raise AssertionError('path_utf8 is not a str: %s %s'
 
1867
                raise errors.BzrError('path_utf8 is not a str: %s %r'
1825
1868
                    % (type(path_utf8), path_utf8))
1826
1869
            # path lookups are faster
1827
1870
            dirname, basename = osutils.split(path_utf8)