/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to bzrlib/dirstate.py

  • Committer: Robert Collins
  • Date: 2009-07-16 23:12:54 UTC
  • mto: This revision was merged to the branch mainline in revision 4544.
  • Revision ID: robertc@robertcollins.net-20090716231254-b2gcpjlce66cdr7b
Review feedback, and cleanup rows correctly in update_minimal when no more references are present.

Show diffs side-by-side

added added

removed removed

Lines of Context:
203
203
 
204
204
import bisect
205
205
import binascii
206
 
from copy import deepcopy
207
206
import errno
208
207
import os
209
208
from stat import S_IEXEC
2440
2439
        new_iterator = new_inv.iter_entries_by_dir()
2441
2440
        # we will be modifying the dirstate, so we need a stable iterator. In
2442
2441
        # future we might write one, for now we just clone the state into a
2443
 
        # list using a deep copy so that forward changes don't make the logic
2444
 
        # more complex. Using a shallow copy results in all entries being seen
2445
 
        # but the state of the entries being wrong, and that leads to stale
2446
 
        # entries being left behind.
 
2442
        # list using a copy so that we see every original item and don't have
 
2443
        # to adjust the position when items are inserted or deleted in the
 
2444
        # underlying dirstate.
2447
2445
        old_iterator = iter(list(self._iter_entries()))
2448
2446
        # both must have roots so this is safe:
2449
2447
        current_new = new_iterator.next()
2494
2492
                # new is finished
2495
2493
                if tracing:
2496
2494
                    trace.mutter("Truncating from old '%s/%s'.",
2497
 
                        current_old[0][0].decode('utf'),
 
2495
                        current_old[0][0].decode('utf8'),
2498
2496
                        current_old[0][1].decode('utf8'))
2499
2497
                self._make_absent(current_old)
2500
2498
                current_old = advance(old_iterator)
2534
2532
                # without seeing it in the new list.  so it must be gone.
2535
2533
                if tracing:
2536
2534
                    trace.mutter("Deleting from old '%s/%s'.",
2537
 
                        current_old[0][0].decode('utf'),
 
2535
                        current_old[0][0].decode('utf8'),
2538
2536
                        current_old[0][1].decode('utf8'))
2539
2537
                self._make_absent(current_old)
2540
2538
                current_old = advance(old_iterator)
2638
2636
                # grab one of them and use it to generate parent
2639
2637
                # relocation/absent entries.
2640
2638
                new_entry = key, [new_details]
2641
 
                for other_key in existing_keys:
 
2639
                # existing_keys can be changed as we iterate.
 
2640
                for other_key in tuple(existing_keys):
2642
2641
                    # change the record at other to be a pointer to this new
2643
2642
                    # record. The loop looks similar to the change to
2644
2643
                    # relocations when updating an existing record but its not:
2649
2648
                    if not present:
2650
2649
                        raise AssertionError('could not find block for %s' % (
2651
2650
                            other_key,))
2652
 
                    other_entry_index, present = self._find_entry_index(other_key,
2653
 
                                            self._dirblocks[other_block_index][1])
 
2651
                    other_block = self._dirblocks[other_block_index][1]
 
2652
                    other_entry_index, present = self._find_entry_index(
 
2653
                        other_key, other_block)
2654
2654
                    if not present:
2655
 
                        raise AssertionError('could not find entry for %s' % (
2656
 
                            other_key,))
 
2655
                        raise AssertionError(
 
2656
                            'update_minimal: could not find other entry for %s'
 
2657
                            % (other_key,))
2657
2658
                    if path_utf8 is None:
2658
2659
                        raise AssertionError('no path')
2659
 
                    other_block = self._dirblocks[other_block_index][1]
2660
2660
                    # Turn this other location into a reference to the new
2661
 
                    # location. This also updates the aliased iterator that
2662
 
                    # set_state_from_inventory uses so that the old entry, if
2663
 
                    # not already examined, is skipped over.
2664
 
                    other_block[other_entry_index][1][0] = \
2665
 
                        ('r', path_utf8, 0, False, '')
2666
 
                    if len(other_block[other_entry_index][1]) == 1:
2667
 
                        # We only have one tree in use, so an 'r' record is not
2668
 
                        # needed: remove it.
2669
 
                        other_block.pop(other_entry_index)
 
2661
                    # location. This also updates the aliased iterator
 
2662
                    # (current_old in set_state_from_inventory) so that the old
 
2663
                    # entry, if not already examined, is skipped over by that
 
2664
                    # loop.
 
2665
                    other_entry = other_block[other_entry_index]
 
2666
                    other_entry[1][0] = ('r', path_utf8, 0, False, '')
 
2667
                    self._maybe_remove_row(other_block, other_entry_index,
 
2668
                        id_index)
2670
2669
 
 
2670
                # This loop:
 
2671
                # adds a tuple to the new details for each column
 
2672
                #  - either by copying an existing relocation pointer inside that column
 
2673
                #  - or by creating a new pointer to the right row inside that column
2671
2674
                num_present_parents = self._num_present_parents()
 
2675
                if num_present_parents:
 
2676
                    other_key = list(existing_keys)[0]
2672
2677
                for lookup_index in xrange(1, num_present_parents + 1):
2673
2678
                    # grab any one entry, use it to find the right path.
2674
2679
                    # TODO: optimise this to reduce memory use in highly
2681
2686
                    update_entry_index, present = \
2682
2687
                        self._find_entry_index(other_key, self._dirblocks[update_block_index][1])
2683
2688
                    if not present:
2684
 
                        raise AssertionError('could not find entry for %s' % (other_key,))
 
2689
                        raise AssertionError('update_minimal: could not find entry for %s' % (other_key,))
2685
2690
                    update_details = self._dirblocks[update_block_index][1][update_entry_index][1][lookup_index]
2686
2691
                    if update_details[0] in 'ar': # relocated, absent
2687
2692
                        # its a pointer or absent in lookup_index's tree, use
2733
2738
 
2734
2739
        self._dirblock_state = DirState.IN_MEMORY_MODIFIED
2735
2740
 
 
2741
    def _maybe_remove_row(self, block, index, id_index):
 
2742
        """Remove index if it is absent or relocated across the row.
 
2743
        
 
2744
        id_index is updated accordingly.
 
2745
        """
 
2746
        present_in_row = False
 
2747
        entry = block[index]
 
2748
        for column in entry[1]:
 
2749
            if column[0] not in 'ar':
 
2750
                present_in_row = True
 
2751
                break
 
2752
        if not present_in_row:
 
2753
            block.pop(index)
 
2754
            id_index[entry[0][2]].remove(entry[0])
 
2755
 
2736
2756
    def _validate(self):
2737
2757
        """Check that invariants on the dirblock are correct.
2738
2758