Rev 5634: Basically works in the case where the dirstate isn't corrupted. in http://bazaar.launchpad.net/~jameinel/bzr/2.4-reset-checkout
John Arbash Meinel
john at arbash-meinel.com
Mon Jan 24 22:57:16 UTC 2011
At http://bazaar.launchpad.net/~jameinel/bzr/2.4-reset-checkout
------------------------------------------------------------
revno: 5634
revision-id: john at arbash-meinel.com-20110124225704-h2zdtk0a82q6bgwy
parent: john at arbash-meinel.com-20110124220048-lngdrej3cm8t9eje
committer: John Arbash Meinel <john at arbash-meinel.com>
branch nick: 2.4-reset-checkout
timestamp: Mon 2011-01-24 16:57:04 -0600
message:
Basically works in the case where the dirstate isn't corrupted.
-------------- next part --------------
=== modified file 'bzrlib/tests/blackbox/__init__.py'
--- a/bzrlib/tests/blackbox/__init__.py 2010-11-07 16:09:43 +0000
+++ b/bzrlib/tests/blackbox/__init__.py 2011-01-24 22:57:04 +0000
@@ -1,4 +1,4 @@
-# Copyright (C) 2005-2010 Canonical Ltd
+# Copyright (C) 2005-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
@@ -99,6 +99,7 @@
'test_remove',
'test_re_sign',
'test_remove_tree',
+ 'test_reset_workingtree',
'test_resolve',
'test_revert',
'test_revno',
=== modified file 'bzrlib/tests/blackbox/test_reset_workingtree.py'
--- a/bzrlib/tests/blackbox/test_reset_workingtree.py 2011-01-24 21:49:59 +0000
+++ b/bzrlib/tests/blackbox/test_reset_workingtree.py 2011-01-24 22:57:04 +0000
@@ -15,10 +15,21 @@
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-import os
-
+from bzrlib import (
+ workingtree,
+ )
from bzrlib.tests import TestCaseWithTransport
-from bzrlib.workingtree import WorkingTree
+
+
+def _get_dirstate_path(tree):
+ """Get the path to the dirstate file."""
+ # This is a bit ugly, but the alternative was hard-coding the path
+ tree.lock_read()
+ try:
+ ds = tree.current_dirstate()
+ return ds._filename
+ finally:
+ tree.unlock()
class TestResetWorkingTree(TestCaseWithTransport):
@@ -30,3 +41,19 @@
tree.commit('first')
self.run_bzr('reset-workingtree')
+ def test_reset_broken_dirstate(self):
+ tree = self.make_branch_and_tree('tree')
+ # This test assumes that the format uses a DirState file, which we then
+ # manually corrupt. If we change the way to get at that dirstate file,
+ # then we can update how this is done
+ self.assertIsNot(None, getattr(tree, 'current_dirstate', None))
+ path = _get_dirstate_path(tree)
+ f = open(path, 'ab')
+ try:
+ f.write('broken-trailing-garbage\n')
+ finally:
+ f.close()
+ self.run_bzr('reset-workingtree')
+ tree = workingtree.WorkingTree.open('tree')
+ # At this point, check should be happy
+ tree.check_state()
=== modified file 'bzrlib/tests/per_workingtree/test_check_state.py'
--- a/bzrlib/tests/per_workingtree/test_check_state.py 2011-01-24 22:00:48 +0000
+++ b/bzrlib/tests/per_workingtree/test_check_state.py 2011-01-24 22:57:04 +0000
@@ -17,15 +17,68 @@
"""Tests for WorkingTree.check_state."""
from bzrlib import (
+ errors,
tests,
)
from bzrlib.tests.per_workingtree import TestCaseWithWorkingTree
-class TestCheckState(TestCaseWithWorkingTree):
+class TestCaseWithState(TestCaseWithWorkingTree):
+
+ def make_tree_with_broken_dirstate(self, path):
+ tree = self.make_branch_and_tree(path)
+ if getattr(tree, 'current_dirstate', None) is None:
+ raise tests.TestNotApplicable(
+ 'Only applies to dirstate-based trees')
+ self.break_dirstate(tree)
+ return tree
+
+ def break_dirstate(self, tree):
+ """Write garbage into the dirstate file."""
+ tree.lock_read()
+ try:
+ dirstate = tree.current_dirstate()
+ dirstate_path = dirstate._filename
+ self.failUnlessExists(dirstate_path)
+ finally:
+ 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')
+ try:
+ f.write('garbage-at-end-of-file\n')
+ finally:
+ f.close()
+
+
+class TestCheckState(TestCaseWithState):
def test_check_state(self):
tree = self.make_branch_and_tree('tree')
# Everything should be fine with an unmodified tree, no exception
# should be raised.
tree.check_state()
+
+ def test_check_broken_dirstate(self):
+ tree = self.make_tree_with_broken_dirstate('tree')
+ self.assertRaises(errors.BzrError, tree.check_state)
+
+
+class TestResetState(TestCaseWithState):
+
+ def test_reset_state_forgets_changes(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')
+ foo_id = tree.path2id('foo')
+ tree.rename_one('foo', 'baz')
+ self.assertEqual(None, tree.path2id('foo'))
+ self.assertEqual(foo_id, tree.path2id('baz'))
+ tree.reset_state()
+ # After reset, we should have forgotten about the rename, but we won't
+ # have
+ self.assertEqual(foo_id, tree.path2id('foo'))
+ self.assertEqual(None, tree.path2id('baz'))
+ self.failIfExists('tree/foo')
+ self.failUnlessExists('tree/baz')
=== modified file 'bzrlib/workingtree.py'
--- a/bzrlib/workingtree.py 2011-01-24 22:00:48 +0000
+++ b/bzrlib/workingtree.py 2011-01-24 22:57:04 +0000
@@ -2675,9 +2675,33 @@
"""
return
- @needs_tree_write_lock
+ @needs_read_lock
def check_state(self):
"""Check that the working state is/isn't valid."""
+ check_refs = self._get_check_refs()
+ refs = {}
+ for ref in check_refs:
+ kind, value = ref
+ if kind == 'trees':
+ refs[ref] = self.branch.repository.revision_tree(value)
+ self._check(refs)
+
+ @needs_tree_write_lock
+ def reset_state(self, revision_ids=None):
+ """Reset the state of the working tree.
+
+ This does a hard-reset to a last-known-good state. This is a way to
+ fix if something got corrupted (like the .bzr/checkout/dirstate file)
+ """
+ if revision_ids is None:
+ revision_ids = self.get_parent_ids()
+ if not revision_ids:
+ rt = self.branch.repository.revision_tree(
+ _mod_revision.NULL_REVISION)
+ else:
+ rt = self.branch.repository.revision_tree(revision_ids[0])
+ self._write_inventory(rt.inventory)
+ self.set_parent_ids(revision_ids)
def _get_rules_searcher(self, default_searcher):
"""See Tree._get_rules_searcher."""
More information about the bazaar-commits
mailing list