Rev 2427: Get iter_changes working again, by fixing set_parent_trees to in http://bazaar.launchpad.net/%7Ebzr/bzr/dirstate
John Arbash Meinel
john at arbash-meinel.com
Tue Feb 27 21:33:27 GMT 2007
At http://bazaar.launchpad.net/%7Ebzr/bzr/dirstate
------------------------------------------------------------
revno: 2427
revision-id: john at arbash-meinel.com-20070227213216-a6kogwpq49j6dgpm
parent: john at arbash-meinel.com-20070227030928-bkhmkqvf3mbymqge
committer: John Arbash Meinel <john at arbash-meinel.com>
branch nick: dirstate
timestamp: Tue 2007-02-27 15:32:16 -0600
message:
Get iter_changes working again, by fixing set_parent_trees to
create trees with the correct block order.
modified:
bzrlib/dirstate.py dirstate.py-20060728012006-d6mvoihjb3je9peu-1
bzrlib/tests/intertree_implementations/test_compare.py test_compare.py-20060724101752-09ysswo1a92uqyoz-2
bzrlib/tests/test_dirstate.py test_dirstate.py-20060728012006-d6mvoihjb3je9peu-2
bzrlib/workingtree_4.py workingtree_4.py-20070208044105-5fgpc5j3ljlh5q6c-1
-------------- next part --------------
=== modified file 'bzrlib/dirstate.py'
--- a/bzrlib/dirstate.py 2007-02-27 03:09:28 +0000
+++ b/bzrlib/dirstate.py 2007-02-27 21:32:16 +0000
@@ -849,7 +849,7 @@
:return: Nothing.
"""
assert new_entries[0][0][0:2] == ('', ''), \
- "Missing root row %r" % new_entries[0][0]
+ "Missing root row %r" % (new_entries[0][0],)
# The two blocks here are deliberate: the root block and the
# contents-of-root block.
self._dirblocks = [('', []), ('', [])]
@@ -1690,7 +1690,8 @@
# --- end generation of full tree mappings
# sort and output all the entries
- new_entries = sorted(by_path.items())
+ new_entries = sorted(by_path.items(),
+ key=lambda entry:(entry[0][0].split('/'), entry[0][1]))
self._entries_to_current_state(new_entries)
self._parents = [rev_id for rev_id, tree in trees]
self._ghosts = list(ghosts)
=== modified file 'bzrlib/tests/intertree_implementations/test_compare.py'
--- a/bzrlib/tests/intertree_implementations/test_compare.py 2007-02-27 02:48:45 +0000
+++ b/bzrlib/tests/intertree_implementations/test_compare.py 2007-02-27 21:32:16 +0000
@@ -729,7 +729,7 @@
specific_files=['added', 'changed', 'fromdir', 'fromfile',
'removed', 'unchanged', 'todir', 'tofile']))
- def _disabled_test_tree_with_special_names(self):
+ def test_tree_with_special_names(self):
tree1, tree2, paths, path_ids = self.make_tree_with_special_names()
tree1.lock_read()
self.addCleanup(tree1.unlock)
=== modified file 'bzrlib/tests/test_dirstate.py'
--- a/bzrlib/tests/test_dirstate.py 2007-02-27 03:09:28 +0000
+++ b/bzrlib/tests/test_dirstate.py 2007-02-27 21:32:16 +0000
@@ -902,11 +902,14 @@
"""Test that DirState adds entries in the right order."""
def test_add_sorting(self):
- """Add entries in lexicographical order, we get path sorted order."""
- dirs = ['a', 'a-a', 'a-z',
- 'a/a', 'a/a-a', 'a/a-z', 'a/a/a', 'a/a/z',
- 'a/z', 'a/z-a', 'a/z-z', 'a/z/a', 'a/z/z',
- 'z',
+ """Add entries in lexicographical order, we get path sorted order.
+
+ This tests it to a depth of 4, to make sure we don't just get it right
+ at a single depth. 'a/a' should come before 'a-a', even though it
+ doesn't lexicographically.
+ """
+ dirs = ['a', 'a/a', 'a/a/a', 'a/a/a/a',
+ 'a-a', 'a/a-a', 'a/a/a-a', 'a/a/a/a-a',
]
null_sha = ''
state = dirstate.DirState.initialize('dirstate')
@@ -921,10 +924,38 @@
state.add(file_path, file_id, 'file', fake_stat, null_sha)
expected = ['', '', 'a',
- 'a/a', 'a/a/a', 'a/a/z', 'a/a-a', 'a/a-z',
- 'a/z', 'a/z/a', 'a/z/z', 'a/z-a', 'a/z-z',
- 'a-a', 'a-z', 'z',
+ 'a/a', 'a/a/a', 'a/a/a/a',
+ 'a/a/a/a-a', 'a/a/a-a', 'a/a-a', 'a-a',
]
+ split = lambda p:p.split('/')
+ self.assertEqual(sorted(expected, key=split), expected)
+ dirblock_names = [d[0] for d in state._dirblocks]
+ self.assertEqual(expected, dirblock_names)
+
+ def test_set_parent_trees_correct_order(self):
+ """After calling set_parent_trees() we should maintain the order."""
+ dirs = ['a', 'a-a', 'a/a']
+ null_sha = ''
+ state = dirstate.DirState.initialize('dirstate')
+ self.addCleanup(state.unlock)
+
+ fake_stat = os.stat('dirstate')
+ for d in dirs:
+ d_id = d.replace('/', '_')+'-id'
+ file_path = d + '/f'
+ file_id = file_path.replace('/', '_')+'-id'
+ state.add(d, d_id, 'directory', fake_stat, null_sha)
+ state.add(file_path, file_id, 'file', fake_stat, null_sha)
+
+ expected = ['', '', 'a', 'a/a', 'a-a']
+ dirblock_names = [d[0] for d in state._dirblocks]
+ self.assertEqual(expected, dirblock_names)
+
+ # *really* cheesy way to just get an empty tree
+ repo = self.make_repository('repo')
+ empty_tree = repo.revision_tree(None)
+ state.set_parent_trees([('null:', empty_tree)], [])
+
dirblock_names = [d[0] for d in state._dirblocks]
self.assertEqual(expected, dirblock_names)
=== modified file 'bzrlib/workingtree_4.py'
--- a/bzrlib/workingtree_4.py 2007-02-27 01:08:04 +0000
+++ b/bzrlib/workingtree_4.py 2007-02-27 21:32:16 +0000
@@ -1546,31 +1546,32 @@
# as well.
old_path = source_details[1]
old_dirname, old_basename = os.path.split(old_path)
- path = os.path.join(*entry[0][0:2])
+ path = os.path.join(entry[0][0], entry[0][1])
old_entry = state._get_entry(source_index, path_utf8=old_path)
# update the source details variable to be the real
# location.
source_details = old_entry[1][source_index]
else:
- old_path = path = os.path.join(*entry[0][0:2])
- old_dirname, old_basename = entry[0][0:2]
+ old_dirname = entry[0][0]
+ old_basename = entry[0][1]
+ old_path = path = os.path.join(old_dirname, old_basename)
if path_info is None:
# the file is missing on disk, show as removed.
- old_path = os.path.join(*entry[0][0:2])
+ old_path = os.path.join(entry[0][0], entry[0][1])
content_change = True
target_kind = None
target_exec = False
else:
# source and target are both versioned and disk file is present.
target_kind = path_info[2]
- if path_info[2][0] == 'd':
+ if target_kind == 'directory':
if source_details[0][0] != 'd':
content_change = True
else:
# directories have no fingerprint
content_change = False
target_exec = False
- elif path_info[2][0] == 'f':
+ elif target_kind == 'file':
if source_details[0][0] != 'f':
content_change = True
else:
@@ -1584,7 +1585,7 @@
target_exec = bool(
stat.S_ISREG(path_info[3].st_mode)
and stat.S_IEXEC & path_info[3].st_mode)
- elif path_info[2][0] == 's':
+ elif target_kind == 'symlink':
if source_details[0][0] != 'l':
content_change = True
else:
@@ -1690,14 +1691,21 @@
# this check should probably be outside the loop: one
# 'iterate two trees' api, and then _iter_changes filters
# unchanged pairs. - RBC 20070226
- if include_unchanged or result[2] or True in map(lambda x:x[0]!=x[1], result[3:8]):
+ if (include_unchanged
+ or result[2] # content change
+ or result[3][0] != result[3][1] # versioned status
+ or result[4][0] != result[4][1] # parent id
+ or result[5][0] != result[5][1] # name
+ or result[6][0] != result[6][1] # kind
+ or result[7][0] != result[7][1] # executable
+ ):
yield result
dir_iterator = osutils.walkdirs(root_abspath, prefix=current_root)
initial_key = (current_root, '', '')
block_index, _ = state._find_block_index_from_key(initial_key)
if block_index == 0:
# we have processed the total root already, but because the
- # initial key matched it we sould skip it here.
+ # initial key matched it we should skip it here.
block_index +=1
try:
current_dir_info = dir_iterator.next()
@@ -1783,7 +1791,14 @@
# this check should probably be outside the loop: one
# 'iterate two trees' api, and then _iter_changes filters
# unchanged pairs. - RBC 20070226
- if include_unchanged or result[2] or True in map(lambda x:x[0]!=x[1], result[3:8]):
+ if (include_unchanged
+ or result[2] # content change
+ or result[3][0] != result[3][1] # versioned status
+ or result[4][0] != result[4][1] # parent id
+ or result[5][0] != result[5][1] # name
+ or result[6][0] != result[6][1] # kind
+ or result[7][0] != result[7][1] # executable
+ ):
yield result
elif current_entry[0][1] != current_path_info[1]:
if current_path_info[1] < current_entry[0][1]:
@@ -1797,7 +1812,14 @@
# this check should probably be outside the loop: one
# 'iterate two trees' api, and then _iter_changes filters
# unchanged pairs. - RBC 20070226
- if include_unchanged or result[2] or True in map(lambda x:x[0]!=x[1], result[3:8]):
+ if (include_unchanged
+ or result[2] # content change
+ or result[3][0] != result[3][1] # versioned status
+ or result[4][0] != result[4][1] # parent id
+ or result[5][0] != result[5][1] # name
+ or result[6][0] != result[6][1] # kind
+ or result[7][0] != result[7][1] # executable
+ ):
yield result
advance_path = False
else:
@@ -1805,7 +1827,14 @@
# this check should probably be outside the loop: one
# 'iterate two trees' api, and then _iter_changes filters
# unchanged pairs. - RBC 20070226
- if include_unchanged or result[2] or True in map(lambda x:x[0]!=x[1], result[3:8]):
+ if (include_unchanged
+ or result[2] # content change
+ or result[3][0] != result[3][1] # versioned status
+ or result[4][0] != result[4][1] # parent id
+ or result[5][0] != result[5][1] # name
+ or result[6][0] != result[6][1] # kind
+ or result[7][0] != result[7][1] # executable
+ ):
yield result
if advance_entry and current_entry is not None:
entry_index += 1
@@ -1833,11 +1862,18 @@
if current_dir_info is not None:
try:
current_dir_info = dir_iterator.next()
- # convert the unicode relpaths in the dir index to uf8 for
+ # convert the unicode relpaths in the dir index to utf8 for
# comparison with dirstate data.
- # TODO: keep the utf8 version around for giving to the caller.
- current_dir_info = ((current_dir_info[0][0].encode('utf8'), current_dir_info[0][1]),
- [(line[0].encode('utf8'), line[1].encode('utf8')) + line[2:] for line in current_dir_info[1]])
+ # TODO: keep the unicode version around for giving to the caller.
+ # We could also use cached_utf8.encode() which
+ # maintains utf8=>unicode and unicode=>utf8 maps.
+ # TODO: change this to a plain tuple assignment rather
+ # than doing slicing, since it should be faster.
+ # (unless the size of the line is dynamic)
+ utf8_relpath = current_dir_info[0][0].encode('utf8')
+ current_dir_info = ((utf8_relpath, current_dir_info[0][1]),
+ [(line[0].encode('utf8'), line[1].encode('utf8'))
+ + line[2:] for line in current_dir_info[1]])
except StopIteration:
current_dir_info = None
More information about the bazaar-commits
mailing list