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
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.
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)
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)
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)))
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)
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)
1478
self._update_basis_check_parents(parents)
1479
except errors.BzrError, e:
1480
if 'integrity error' not in str(e):
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
1487
self._changes_aborted = True
1488
raise errors.InconsistentDeltaDelta(delta, "error from _get_entry.")
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
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.")
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)
2938
2981
False, DirState.NULLSTAT)
2939
2982
state._dirblock_state = DirState.IN_MEMORY_MODIFIED
2940
2983
return link_or_sha1
2941
update_entry = py_update_entry
2944
2986
class ProcessEntryPython(object):
3575
3617
current_dir_info = dir_iterator.next()
3576
3618
except StopIteration:
3577
3619
current_dir_info = None
3578
_process_entry = ProcessEntryPython
3581
3622
# Try to load the compiled form if possible
3583
from bzrlib._dirstate_helpers_c import (
3584
_read_dirblocks_c as _read_dirblocks,
3585
bisect_dirblock_c as bisect_dirblock,
3586
_bisect_path_left_c as _bisect_path_left,
3587
_bisect_path_right_c as _bisect_path_right,
3588
cmp_by_dirs_c as cmp_by_dirs,
3624
from bzrlib._dirstate_helpers_pyx import (
3589
3630
ProcessEntryC as _process_entry,
3590
3631
update_entry as update_entry,
3592
3633
except ImportError:
3593
3634
from bzrlib._dirstate_helpers_py import (
3594
_read_dirblocks_py as _read_dirblocks,
3595
bisect_dirblock_py as bisect_dirblock,
3596
_bisect_path_left_py as _bisect_path_left,
3597
_bisect_path_right_py as _bisect_path_right,
3598
cmp_by_dirs_py as cmp_by_dirs,
3641
# FIXME: It would be nice to be able to track moved lines so that the
3642
# corresponding python code can be moved to the _dirstate_helpers_py
3643
# module. I don't want to break the history for this important piece of
3644
# code so I left the code here -- vila 20090622
3645
update_entry = py_update_entry
3646
_process_entry = ProcessEntryPython