~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/dirstate.py

  • Committer: Martin Pool
  • Date: 2009-07-17 10:38:41 UTC
  • mfrom: (4536 +trunk)
  • mto: This revision was merged to the branch mainline in revision 4558.
  • Revision ID: mbp@sourcefrog.net-20090717103841-z35onk04bkiw7zb6
Merge trunk

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)
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
2942
2984
 
2943
2985
 
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
3579
3620
 
3580
3621
 
3581
3622
# Try to load the compiled form if possible
3582
3623
try:
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 (
 
3625
        _read_dirblocks,
 
3626
        bisect_dirblock,
 
3627
        _bisect_path_left,
 
3628
        _bisect_path_right,
 
3629
        cmp_by_dirs,
3589
3630
        ProcessEntryC as _process_entry,
3590
3631
        update_entry as update_entry,
3591
3632
        )
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,
 
3635
        _read_dirblocks,
 
3636
        bisect_dirblock,
 
3637
        _bisect_path_left,
 
3638
        _bisect_path_right,
 
3639
        cmp_by_dirs,
3599
3640
        )
 
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