Rev 5636: Implement a reset-to-known-state ability for DirState. in http://bazaar.launchpad.net/~jameinel/bzr/2.4-reset-checkout
John Arbash Meinel
john at arbash-meinel.com
Tue Jan 25 22:54:11 UTC 2011
At http://bazaar.launchpad.net/~jameinel/bzr/2.4-reset-checkout
------------------------------------------------------------
revno: 5636
revision-id: john at arbash-meinel.com-20110125225408-w5b5mmh117q4jjz1
parent: john at arbash-meinel.com-20110124235857-ire0uaqf4t9oq8qj
committer: John Arbash Meinel <john at arbash-meinel.com>
branch nick: 2.4-reset-checkout
timestamp: Tue 2011-01-25 16:54:08 -0600
message:
Implement a reset-to-known-state ability for DirState.
Use this in reset_state(). Allow it to use header information if it can
be parsed, otherwise allow us to pass in the information.
-------------- next part --------------
=== modified file 'bzrlib/dirstate.py'
--- a/bzrlib/dirstate.py 2010-09-13 06:36:59 +0000
+++ b/bzrlib/dirstate.py 2011-01-25 22:54:08 +0000
@@ -1,4 +1,4 @@
-# Copyright (C) 2006-2010 Canonical Ltd
+# Copyright (C) 2006-2011 Canonical Ltd
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -2681,6 +2681,23 @@
if tracing:
trace.mutter("set_state_from_inventory complete.")
+ def set_state_from_scratch(self, working_inv, parent_trees, parent_ghosts):
+ """Wipe the currently stored state and set it to something new.
+
+ This is a hard-reset for the data we are working with.
+ """
+ # Technically, we really want a write lock, but until we write, we
+ # don't really need it.
+ self._requires_lock()
+ # root dir and root dir contents with no children. We have to have a
+ # root for set_state_from_inventory to work correctly.
+ empty_root = (('', '', inventory.ROOT_ID),
+ [('d', '', 0, False, DirState.NULLSTAT)])
+ empty_tree_dirblocks = [('', [empty_root]), ('', [])]
+ self._set_data([], empty_tree_dirblocks)
+ self.set_state_from_inventory(working_inv)
+ self.set_parent_trees(parent_trees, parent_ghosts)
+
def _make_absent(self, current_old):
"""Mark current_old - an entry - as absent for tree 0.
=== modified file 'bzrlib/tests/per_workingtree/test_check_state.py'
--- a/bzrlib/tests/per_workingtree/test_check_state.py 2011-01-24 23:58:57 +0000
+++ b/bzrlib/tests/per_workingtree/test_check_state.py 2011-01-25 22:54:08 +0000
@@ -31,7 +31,7 @@
self.break_dirstate(tree)
return tree
- def break_dirstate(self, tree):
+ def break_dirstate(self, tree, completely=False):
"""Write garbage into the dirstate file."""
if getattr(tree, 'current_dirstate', None) is None:
raise tests.TestNotApplicable(
@@ -45,7 +45,10 @@
tree.unlock()
# We have to have the tree unlocked at this point, so we can safely
# mutate the state file on all platforms.
- f = open(dirstate_path, 'ab')
+ if completely:
+ f = open(dirstate_path, 'wb')
+ else:
+ f = open(dirstate_path, 'ab')
try:
f.write('garbage-at-end-of-file\n')
finally:
@@ -67,11 +70,15 @@
class TestResetState(TestCaseWithState):
- def test_reset_state_forgets_changes(self):
+ def make_initial_tree(self):
tree = self.make_branch_and_tree('tree')
self.build_tree(['tree/foo', 'tree/dir/', 'tree/dir/bar'])
tree.add(['foo', 'dir', 'dir/bar'])
tree.commit('initial')
+ return tree
+
+ def test_reset_state_forgets_changes(self):
+ tree = self.make_initial_tree()
foo_id = tree.path2id('foo')
tree.rename_one('foo', 'baz')
self.assertEqual(None, tree.path2id('foo'))
@@ -85,7 +92,16 @@
self.failUnlessExists('tree/baz')
def test_reset_state_handles_corrupted_dirstate(self):
- tree = self.make_branch_and_tree('tree')
+ tree = self.make_initial_tree()
self.break_dirstate(tree)
tree.reset_state()
tree.check_state()
+
+ def test_reset_state_handles_destroyed_dirstate(self):
+ # If you pass the revision_id, we can handle a completely destroyed
+ # dirstate file.
+ tree = self.make_initial_tree()
+ rev_id = tree.last_revision()
+ self.break_dirstate(tree, completely=True)
+ tree.reset_state(revision_ids=[rev_id])
+ tree.check_state()
=== modified file 'bzrlib/tests/test_dirstate.py'
--- a/bzrlib/tests/test_dirstate.py 2011-01-12 01:01:53 +0000
+++ b/bzrlib/tests/test_dirstate.py 2011-01-25 22:54:08 +0000
@@ -725,6 +725,14 @@
class TestDirStateManipulations(TestCaseWithDirState):
+ def make_minimal_tree(self):
+ tree1 = self.make_branch_and_memory_tree('tree1')
+ tree1.lock_write()
+ self.addCleanup(tree1.unlock)
+ tree1.add('')
+ revid1 = tree1.commit('foo')
+ return tree1, revid1
+
def test_update_minimal_updates_id_index(self):
state = self.create_dirstate_with_root_and_subdir()
self.addCleanup(state.unlock)
@@ -743,15 +751,9 @@
def test_set_state_from_inventory_no_content_no_parents(self):
# setting the current inventory is a slow but important api to support.
- tree1 = self.make_branch_and_memory_tree('tree1')
- tree1.lock_write()
- try:
- tree1.add('')
- revid1 = tree1.commit('foo').encode('utf8')
- root_id = tree1.get_root_id()
- inv = tree1.inventory
- finally:
- tree1.unlock()
+ tree1, revid1 = self.make_minimal_tree()
+ inv = tree1.inventory
+ root_id = inv.path2id('')
expected_result = [], [
(('', '', root_id), [
('d', '', 0, False, dirstate.DirState.NULLSTAT)])]
@@ -769,6 +771,50 @@
# This will unlock it
self.check_state_with_reopen(expected_result, state)
+ def test_set_state_from_scratch_no_parents(self):
+ tree1, revid1 = self.make_minimal_tree()
+ inv = tree1.inventory
+ root_id = inv.path2id('')
+ expected_result = [], [
+ (('', '', root_id), [
+ ('d', '', 0, False, dirstate.DirState.NULLSTAT)])]
+ state = dirstate.DirState.initialize('dirstate')
+ try:
+ state.set_state_from_scratch(inv, [], [])
+ self.assertEqual(dirstate.DirState.IN_MEMORY_MODIFIED,
+ state._header_state)
+ self.assertEqual(dirstate.DirState.IN_MEMORY_MODIFIED,
+ state._dirblock_state)
+ except:
+ state.unlock()
+ raise
+ else:
+ # This will unlock it
+ self.check_state_with_reopen(expected_result, state)
+
+ def test_set_state_from_scratch_identical_parent(self):
+ tree1, revid1 = self.make_minimal_tree()
+ inv = tree1.inventory
+ root_id = inv.path2id('')
+ rev_tree1 = tree1.branch.repository.revision_tree(revid1)
+ d_entry = ('d', '', 0, False, dirstate.DirState.NULLSTAT)
+ parent_entry = ('d', '', 0, False, revid1)
+ expected_result = [revid1], [
+ (('', '', root_id), [d_entry, parent_entry])]
+ state = dirstate.DirState.initialize('dirstate')
+ try:
+ state.set_state_from_scratch(inv, [(revid1, rev_tree1)], [])
+ self.assertEqual(dirstate.DirState.IN_MEMORY_MODIFIED,
+ state._header_state)
+ self.assertEqual(dirstate.DirState.IN_MEMORY_MODIFIED,
+ state._dirblock_state)
+ except:
+ state.unlock()
+ raise
+ else:
+ # This will unlock it
+ self.check_state_with_reopen(expected_result, state)
+
def test_set_state_from_inventory_preserves_hashcache(self):
# https://bugs.launchpad.net/bzr/+bug/146176
# set_state_from_inventory should preserve the stat and hash value for
=== modified file 'bzrlib/workingtree_4.py'
--- a/bzrlib/workingtree_4.py 2011-01-24 23:58:57 +0000
+++ b/bzrlib/workingtree_4.py 2011-01-25 22:54:08 +0000
@@ -1307,12 +1307,12 @@
_mod_revision.NULL_REVISION)
trees = []
else:
- trees = self.branch.repository.revision_trees(revision_ids)
- base_tree = trees[0]
+ trees = zip(revision_ids,
+ self.branch.repository.revision_trees(revision_ids))
+ base_tree = trees.pop(0)[1]
state = self.current_dirstate()
- self.set_par
- self._write_inventory(rt.inventory)
- self.set_parent_ids(revision_ids)
+ # We don't support ghosts yet
+ state.set_state_from_scratch(base_tree.inventory, trees, [])
class ContentFilterAwareSHA1Provider(dirstate.SHA1Provider):
More information about the bazaar-commits
mailing list