Rev 2348: Dirstate - update WorkingTree4.unversion to the new layout, other tests still borked. in sftp://bazaar.launchpad.net/%7Ebzr/bzr/dirstate/
Robert Collins
robertc at robertcollins.net
Wed Feb 21 01:09:17 GMT 2007
At sftp://bazaar.launchpad.net/%7Ebzr/bzr/dirstate/
------------------------------------------------------------
revno: 2348
revision-id: robertc at robertcollins.net-20070221010813-zn13zy3wzd53i3vz
parent: jw+debian at jameswestby.net-20070220222431-t4esb34p4zxqcqxm
committer: Robert Collins <robertc at robertcollins.net>
branch nick: dirstate
timestamp: Wed 2007-02-21 12:08:13 +1100
message:
Dirstate - update WorkingTree4.unversion to the new layout, other tests still borked.
modified:
bzrlib/dirstate.py dirstate.py-20060728012006-d6mvoihjb3je9peu-1
bzrlib/workingtree_4.py workingtree_4.py-20070208044105-5fgpc5j3ljlh5q6c-1
=== modified file 'bzrlib/dirstate.py'
--- a/bzrlib/dirstate.py 2007-02-20 22:20:24 +0000
+++ b/bzrlib/dirstate.py 2007-02-21 01:08:13 +0000
@@ -340,6 +340,7 @@
def add_deleted(self, fileid_utf8, parents):
"""Add fileid_utf8 with parents as deleted."""
+ raise Exception, "broken"
self._read_dirblocks_if_needed()
new_row = self._make_deleted_row(fileid_utf8, parents)
block_index = self._find_dirblock_index(new_row[0][0])
@@ -443,7 +444,7 @@
:return: The block tuple.
"""
if key[0:2] == ('', ''):
- return self._root_entries
+ return ('', self._root_entries)
else:
block_index, present = self._find_block_index_from_key(key)
if not present:
@@ -1221,7 +1222,7 @@
current_new = advance(new_iterator)
elif not current_new:
# new is finished
- self._make_absent(num_present_parents, current_old, id_index)
+ self._make_absent(current_old, id_index)
current_old = advance(old_iterator)
elif new_entry_key == current_old[0]:
# same - common case
@@ -1246,47 +1247,58 @@
current_new = advance(new_iterator)
else:
# old comes before:
- self._make_absent(num_present_parents, current_old, id_index)
+ self._make_absent(current_old, id_index)
current_old = advance(old_iterator)
self._dirblock_state = DirState.IN_MEMORY_MODIFIED
- def _make_absent(self, num_present_parents, current_old, id_index):
- # remove old from the state, advance old
- # to remove old, we have two conditions:
- # either its the last reference to this path that we are
- # removing, or its not. If its the last reference, we remove
- # the entire row and remove the path from the id mapping. If
- # its not the last reference, we just set it to absent.
- last_reference = True
- for lookup_index in xrange(1, num_present_parents + 1):
- if current_old[1][lookup_index] not in ('absent', 'relocated'):
- last_reference = False
- break
- if not last_reference:
- # common case, theres a parent at this path
- current_old[1][0] = DirState.NULL_PARENT_DETAILS
- else:
- # there are no more references at this path
- id_index[current_old[0][2]].remove(current_old[0])
- # are there others (which will need to be changed
- # from relocated to absent for index 0)?
- for update_key in id_index[current_old[0][2]]:
- # update the entry for 0 to say absent: there is a parent at
- # that path, but nothing in this tree for that file id anymore.
- update_block_index, present = \
- self._find_block_index_from_key(update_key)
- assert present
- update_entry_index, present = \
- self._find_entry_index(update_key, self._dirblocks[update_block_index][1])
- assert present
- update_tree_details = self._dirblocks[update_block_index][1][update_entry_index][1]
- # it must currently be relocated
- assert update_tree_details[0][0] == 'relocated'
- update_tree_details[0] = DirState.NULL_PARENT_DETAILS
+ def _make_absent(self, current_old, id_index=None):
+ """Mark current_old - an entry - as absent for tree 0.
+
+ :param id_index: An index from fileid_utf8 to sets of keys, used by
+ some functions. If provided it will be updated if needed.
+ :return: True if this was the last details entry for they entry key:
+ that is, if the underlying block has had the entry removed, thus
+ shrinking in legnth.
+ """
+ # build up paths that this id will be left at after the change is made,
+ # so we can update their cross references in tree 0
+ all_remaining_keys = set()
+ # Dont check the working tree, because its going.
+ for details in current_old[1][1:]:
+ if details[0] not in ('absent', 'relocated'):
+ all_remaining_keys.add(current_old[0])
+ elif details[0] == 'relocated':
+ # record the key for the real path.
+ all_remaining_keys.add(tuple(os.path.split(details[1])) + tuple(current_old[0][2]))
+ # absent rows are not present at any path.
+ last_reference = current_old[0] not in all_remaining_keys
+ if last_reference:
+ # the current row consists entire of the current item (being marked
+ # absent), and relocated or absent entries for the other trees:
+ # Remove it, its meaningless.
block = self._find_block(current_old[0])
entry_index, present = self._find_entry_index(current_old[0], block[1])
assert present
block[1].pop(entry_index)
+ # if we have an id_index in use, remove this key from it for this id.
+ if id_index is not None:
+ id_index[current_old[0][2]].remove(current_old[0])
+ # update all remaining keys for this id to record it as absent. The
+ # existing details may either be the record we are making as deleted
+ # (if there were other trees with the id present at this path), or may
+ # be relocations.
+ for update_key in all_remaining_keys:
+ update_block_index, present = \
+ self._find_block_index_from_key(update_key)
+ assert present
+ update_entry_index, present = \
+ self._find_entry_index(update_key, self._dirblocks[update_block_index][1])
+ assert present
+ update_tree_details = self._dirblocks[update_block_index][1][update_entry_index][1]
+ # it must not be absent at the moment
+ assert update_tree_details[0][0] != 'absent'
+ update_tree_details[0] = DirState.NULL_PARENT_DETAILS
+ return last_reference
def update_minimal(self, key, kind, num_present_parents, executable=False,
fingerprint='', packed_stat=None, size=0, id_index=None,
=== modified file 'bzrlib/workingtree_4.py'
--- a/bzrlib/workingtree_4.py 2007-02-20 22:24:31 +0000
+++ b/bzrlib/workingtree_4.py 2007-02-21 01:08:13 +0000
@@ -660,51 +660,60 @@
paths_to_unversion = set()
# sketch:
# check if the root is to be unversioned, if so, assert for now.
- # make a copy of the _dirblocks data
- # during the copy,
- # skip paths in paths_to_unversion
- # skip ids in ids_to_unversion, and add their paths to
- # paths_to_unversion if they are a directory
+ # walk the state marking unversioned things as absent.
# if there are any un-unversioned ids at the end, raise
- if state._root_row[0][3] in ids_to_unversion:
- # I haven't written the code to unversion / yet - it should be
- # supported.
- raise errors.BzrError('Unversioning the / is not currently supported')
- new_blocks = []
- deleted_rows = []
- for block in state._dirblocks:
+ for key, details in state._root_entries:
+ if (details[0][0] not in ('absent', 'relocated') and
+ key[2] in ids_to_unversion):
+ # I haven't written the code to unversion / yet - it should be
+ # supported.
+ raise errors.BzrError('Unversioning the / is not currently supported')
+ details_length = len(state._root_entries[0][1])
+ block_index = 0
+ while block_index < len(state._dirblocks):
+ # process one directory at a time.
+ block = state._dirblocks[block_index]
# first check: is the path one to remove - it or its children
delete_block = False
for path in paths_to_unversion:
if (block[0].startswith(path) and
(len(block[0]) == len(path) or
block[0][len(path)] == '/')):
- # this path should be deleted
+ # this entire block should be deleted - its the block for a
+ # path to unversion; or the child of one
delete_block = True
break
# TODO: trim paths_to_unversion as we pass by paths
if delete_block:
- # this block is to be deleted. skip it.
+ # this block is to be deleted: process it.
+ # TODO: we can special case the no-parents case and
+ # just forget the whole block.
+ entry_index = 0
+ while entry_index < len(block[1]):
+ if not state._make_absent(block[1][entry_index]):
+ entry_index += 1
+ # go to the next block. (At the moment we dont delete empty
+ # dirblocks)
+ block_index += 1
continue
- # copy undeleted rows from within the the block
- new_blocks.append((block[0], []))
- new_row = new_blocks[-1][1]
- for row, row_parents in block[1]:
- if row[3] not in ids_to_unversion:
- new_row.append((row, row_parents))
- else:
- # skip the row, and if its a dir mark its path to be removed
- if row[2] == 'directory':
- paths_to_unversion.add((row[0] + '/' + row[1]).strip('/'))
- if row_parents:
- deleted_rows.append((row[3], row_parents))
- ids_to_unversion.remove(row[3])
+ entry_index = 0
+ while entry_index < len(block[1]):
+ entry = block[1][entry_index]
+ if (entry[1][0][0] in ('absent', 'relocated') or
+ # ^ some parent row.
+ entry[0][2] not in ids_to_unversion):
+ # ^ not an id to unversion
+ entry_index += 1
+ continue
+ if entry[1][0][0] == 'directory':
+ paths_to_unversion.add(os.path.join(*entry[0][0:2]))
+ if not state._make_absent(entry):
+ entry_index += 1
+ # we have unversioned this id
+ ids_to_unversion.remove(entry[0][2])
+ block_index += 1
if ids_to_unversion:
raise errors.NoSuchId(self, iter(ids_to_unversion).next())
- state._dirblocks = new_blocks
- for fileid_utf8, parents in deleted_rows:
- state.add_deleted(fileid_utf8, parents)
- state._dirblock_state = dirstate.DirState.IN_MEMORY_MODIFIED
self._dirty = True
# have to change the legacy inventory too.
if self._inventory is not None:
@@ -869,6 +878,10 @@
inv_entry.text_sha1 = link_or_sha1
elif kind == 'directory':
parent_ids[(dirname + '/' + name).strip('/')] = file_id
+ elif kind == 'symlink':
+ inv_entry.executable = False
+ inv_entry.text_size = size
+ inv_entry.symlink_target = link_or_sha1.decode('utf8')
else:
raise Exception, kind
inv.add(inv_entry)
More information about the bazaar-commits
mailing list