1329
def _check_delta_is_valid(self, delta):
1330
return list(inventory._check_delta_unique_ids(
1331
inventory._check_delta_unique_old_paths(
1332
inventory._check_delta_unique_new_paths(
1333
inventory._check_delta_ids_match_entry(
1334
inventory._check_delta_ids_are_valid(
1335
inventory._check_delta_new_path_entry_both_or_None(delta)))))))
1329
1337
def update_by_delta(self, delta):
1330
1338
"""Apply an inventory delta to the dirstate for tree 0
1349
1357
new_ids = set()
1350
1358
# This loop transforms the delta to single atomic operations that can
1351
1359
# be executed and validated.
1352
for old_path, new_path, file_id, inv_entry in sorted(
1353
inventory._check_delta_unique_old_paths(
1354
inventory._check_delta_unique_new_paths(
1355
inventory._check_delta_ids_match_entry(
1356
inventory._check_delta_ids_are_valid(
1357
inventory._check_delta_new_path_entry_both_or_None(delta))))),
1360
delta = sorted(self._check_delta_is_valid(delta), reverse=True)
1361
for old_path, new_path, file_id, inv_entry in delta:
1359
1362
if (file_id in insertions) or (file_id in removals):
1360
1363
raise errors.InconsistentDelta(old_path or new_path, file_id,
1361
1364
"repeated file_id")
1475
1478
Note that an exception during the operation of this method will leave
1476
1479
the dirstate in a corrupt state where it should not be saved.
1478
Finally, we expect all changes to be synchronising the basis tree with
1481
1481
:param new_revid: The new revision id for the trees parent.
1482
1482
:param delta: An inventory delta (see apply_inventory_delta) describing
1483
1483
the changes from the current left most parent revision to new_revid.
1653
1653
for old_path, new_path, file_id, new_details, real_add in adds:
1654
1654
# the entry for this file_id must be in tree 0.
1655
1655
entry = self._get_entry(0, file_id, new_path)
1656
if entry[0] is None or entry[0][2] != file_id:
1656
if entry[0] is None:
1657
# new_path is not versioned in the active WT state,
1658
# but we are adding it to the basis tree state, we
1659
# need to create a new entry record for it.
1660
dirname, basename = osutils.split(new_path)
1661
entry_key = (dirname, basename, file_id)
1662
_, block = self._find_block(entry_key, add_if_missing=True)
1663
index, _ = self._find_entry_index(entry_key, block)
1664
entry = (entry_key, [DirState.NULL_PARENT_DETAILS]*2)
1665
block.insert(index, entry)
1666
elif entry[0][2] != file_id:
1657
1667
self._changes_aborted = True
1658
1668
raise errors.InconsistentDelta(new_path, file_id,
1659
1669
'working tree does not contain new entry')
1719
1729
raise errors.InconsistentDelta(old_path, file_id,
1720
1730
'mismatched file_id in tree 1')
1721
1731
if real_delete:
1722
if entry[1][0][0] != 'a':
1723
self._changes_aborted = True
1724
raise errors.InconsistentDelta(old_path, file_id,
1725
'This was marked as a real delete, but the WT state'
1726
' claims that it still exists and is versioned.')
1727
del self._dirblocks[block_index][1][entry_index]
1732
if entry[1][0][0] == 'a':
1733
# The file was marked as deleted in the active
1734
# state, and it is now deleted in the basis state,
1735
# so just remove the record entirely
1736
del self._dirblocks[block_index][1][entry_index]
1738
# The basis entry needs to be marked deleted
1740
# If we are deleting a directory, we need to make sure
1741
# that all of its children are already deleted
1742
block_i, entry_i, d_present, f_present = \
1743
self._get_block_entry_index(old_path, '', 0)
1745
# The dir block is still present in the dirstate; this could
1746
# be due to it being in a parent tree, or a corrupt delta.
1747
for child_entry in self._dirblocks[block_i][1]:
1748
if child_entry[1][1][0] not in ('r', 'a'):
1749
self._changes_aborted = True
1750
raise errors.InconsistentDelta(old_path, entry[0][2],
1751
"The file id was deleted but its children were "
1729
1754
if entry[1][0][0] == 'a':
1730
1755
self._changes_aborted = True
1740
1765
del self._dirblocks[block_index][1][entry_index]
1742
1767
# it is being resurrected here, so blank it out temporarily.
1768
# should be equivalent to entry[1][1] = null
1743
1769
self._dirblocks[block_index][1][entry_index][1][1] = null
1745
1771
def _after_delta_check_parents(self, parents, index):