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