Rev 4650: Support shelve and unshelve on windows - bug 305006. in http://bazaar.launchpad.net/~lifeless/bzr/shelve-locks

Robert Collins robertc at robertcollins.net
Tue Aug 25 22:09:28 BST 2009


At http://bazaar.launchpad.net/~lifeless/bzr/shelve-locks

------------------------------------------------------------
revno: 4650
revision-id: robertc at robertcollins.net-20090825210917-dq2i8k6n4z63pneh
parent: robertc at robertcollins.net-20090825195832-oz7fisc4vhxw6xpz
committer: Robert Collins <robertc at robertcollins.net>
branch nick: shelve-locks
timestamp: Wed 2009-08-26 07:09:17 +1000
message:
  Support shelve and unshelve on windows - bug 305006.
=== modified file 'NEWS'
--- a/NEWS	2009-08-25 08:16:44 +0000
+++ b/NEWS	2009-08-25 21:09:17 +0000
@@ -63,6 +63,9 @@
 * ``bzr push`` locally on windows will no longer give a locking error with
   dirstate based formats. (Robert Collins)
 
+* ``bzr shelve`` and ``bzr unshelve`` now work on windows.
+  (Robert Collins, #305006)
+
 Documentation
 *************
 
@@ -72,6 +75,10 @@
 API Changes
 ***********
 
+* ``bzrlib.shelf_ui`` has had the ``from_args`` convenience methods of its
+  classes changed to manage lock lifetime of the trees they open in a way
+  consistent with reader-exclusive locks. (Robert Collins, #305006)
+
 Internals
 *********
 

=== modified file 'bzrlib/builtins.py'
--- a/bzrlib/builtins.py	2009-08-24 22:32:53 +0000
+++ b/bzrlib/builtins.py	2009-08-25 21:09:17 +0000
@@ -120,6 +120,15 @@
 
 
 def _get_one_revision_tree(command_name, revisions, branch=None, tree=None):
+    """Get a revision tree. Not suitable for commands that change the tree.
+    
+    Specifically, the basis tree in dirstate trees is coupled to the dirstate
+    and doing a commit/uncommit/pull will at best fail due to changing the
+    basis revision data.
+
+    If tree is passed in, it should be already locked, for lifetime management
+    of the trees internal cached state.
+    """
     if branch is None:
         branch = tree.branch
     if revisions is None:
@@ -5634,8 +5643,12 @@
         if writer is None:
             writer = bzrlib.option.diff_writer_registry.get()
         try:
-            Shelver.from_args(writer(sys.stdout), revision, all, file_list,
-                              message, destroy=destroy).run()
+            shelver = Shelver.from_args(writer(sys.stdout), revision, all,
+                file_list, message, destroy=destroy)
+            try:
+                shelver.run()
+            finally:
+                shelver.work_tree.unlock()
         except errors.UserAbort:
             return 0
 
@@ -5680,7 +5693,11 @@
 
     def run(self, shelf_id=None, action='apply'):
         from bzrlib.shelf_ui import Unshelver
-        Unshelver.from_args(shelf_id, action).run()
+        unshelver = Unshelver.from_args(shelf_id, action)
+        try:
+            unshelver.run()
+        finally:
+            unshelver.tree.unlock()
 
 
 class cmd_clean_tree(Command):

=== modified file 'bzrlib/shelf.py'
--- a/bzrlib/shelf.py	2009-08-21 04:07:06 +0000
+++ b/bzrlib/shelf.py	2009-08-25 21:09:17 +0000
@@ -37,8 +37,10 @@
     def __init__(self, work_tree, target_tree, file_list=None):
         """Constructor.
 
-        :param work_tree: The working tree to apply changes to
+        :param work_tree: The working tree to apply changes to. This is not
+            required to be locked - a tree_write lock will be taken out.
         :param target_tree: The tree to make the working tree more similar to.
+            This is not required to be locked - a read_lock will be taken out.
         :param file_list: The files to make more similar to the target.
         """
         self.work_tree = work_tree

=== modified file 'bzrlib/shelf_ui.py'
--- a/bzrlib/shelf_ui.py	2009-07-13 13:00:27 +0000
+++ b/bzrlib/shelf_ui.py	2009-08-25 21:09:17 +0000
@@ -149,6 +149,9 @@
                   message=None, directory='.', destroy=False):
         """Create a shelver from commandline arguments.
 
+        The returned shelver wil have a work_tree that is locked and should
+        be unlocked.
+
         :param revision: RevisionSpec of the revision to compare to.
         :param all: If True, shelve all changes without prompting.
         :param file_list: If supplied, only files in this list may be  shelved.
@@ -158,9 +161,16 @@
             changes.
         """
         tree, path = workingtree.WorkingTree.open_containing(directory)
-        target_tree = builtins._get_one_revision_tree('shelf2', revision,
-            tree.branch, tree)
-        files = builtins.safe_relpath_files(tree, file_list)
+        # Ensure that tree is locked for the lifetime of target_tree, as
+        # target tree may be reading from the same dirstate.
+        tree.lock_tree_write()
+        try:
+            target_tree = builtins._get_one_revision_tree('shelf2', revision,
+                tree.branch, tree)
+            files = builtins.safe_relpath_files(tree, file_list)
+        except:
+            tree.unlock()
+            raise
         return klass(tree, target_tree, diff_writer, all, all, files, message,
                      destroy)
 
@@ -313,32 +323,40 @@
     def from_args(klass, shelf_id=None, action='apply', directory='.'):
         """Create an unshelver from commandline arguments.
 
+        The returned shelver wil have a tree that is locked and should
+        be unlocked.
+
         :param shelf_id: Integer id of the shelf, as a string.
         :param action: action to perform.  May be 'apply', 'dry-run',
             'delete'.
         :param directory: The directory to unshelve changes into.
         """
         tree, path = workingtree.WorkingTree.open_containing(directory)
-        manager = tree.get_shelf_manager()
-        if shelf_id is not None:
-            try:
-                shelf_id = int(shelf_id)
-            except ValueError:
-                raise errors.InvalidShelfId(shelf_id)
-        else:
-            shelf_id = manager.last_shelf()
-            if shelf_id is None:
-                raise errors.BzrCommandError('No changes are shelved.')
-            trace.note('Unshelving changes with id "%d".' % shelf_id)
-        apply_changes = True
-        delete_shelf = True
-        read_shelf = True
-        if action == 'dry-run':
-            apply_changes = False
-            delete_shelf = False
-        if action == 'delete-only':
-            apply_changes = False
-            read_shelf = False
+        tree.lock_tree_write()
+        try:
+            manager = tree.get_shelf_manager()
+            if shelf_id is not None:
+                try:
+                    shelf_id = int(shelf_id)
+                except ValueError:
+                    raise errors.InvalidShelfId(shelf_id)
+            else:
+                shelf_id = manager.last_shelf()
+                if shelf_id is None:
+                    raise errors.BzrCommandError('No changes are shelved.')
+                trace.note('Unshelving changes with id "%d".' % shelf_id)
+            apply_changes = True
+            delete_shelf = True
+            read_shelf = True
+            if action == 'dry-run':
+                apply_changes = False
+                delete_shelf = False
+            if action == 'delete-only':
+                apply_changes = False
+                read_shelf = False
+        except:
+            tree.unlock()
+            raise
         return klass(tree, manager, shelf_id, apply_changes, delete_shelf,
                      read_shelf)
 
@@ -364,7 +382,7 @@
 
     def run(self):
         """Perform the unshelving operation."""
-        self.tree.lock_write()
+        self.tree.lock_tree_write()
         cleanups = [self.tree.unlock]
         try:
             if self.read_shelf:

=== modified file 'bzrlib/tests/test_shelf.py'
--- a/bzrlib/tests/test_shelf.py	2009-08-21 04:07:06 +0000
+++ b/bzrlib/tests/test_shelf.py	2009-08-25 21:09:17 +0000
@@ -46,6 +46,8 @@
         tree.add(['foo'], ['foo-id'])
         tree.commit('foo')
         tree.rename_one('foo', 'bar')
+        tree.lock_tree_write()
+        self.addCleanup(tree.unlock)
         creator = shelf.ShelfCreator(tree, tree.basis_tree())
         self.addCleanup(creator.finalize)
         self.assertEqual([('rename', 'foo-id', 'foo', 'bar')],
@@ -61,13 +63,11 @@
                          shelf_trans_id))
 
     def test_shelve_rename(self):
-        self.thisFailsStrictLockCheck()
         creator = self.prepare_shelve_rename()
         creator.shelve_rename('foo-id')
         self.check_shelve_rename(creator)
 
     def test_shelve_change_handles_rename(self):
-        self.thisFailsStrictLockCheck()
         creator = self.prepare_shelve_rename()
         creator.shelve_change(('rename', 'foo-id', 'foo', 'bar'))
         self.check_shelve_rename(creator)
@@ -78,6 +78,8 @@
         tree.add(['foo', 'bar', 'foo/baz'], ['foo-id', 'bar-id', 'baz-id'])
         tree.commit('foo')
         tree.rename_one('foo/baz', 'bar/baz')
+        tree.lock_tree_write()
+        self.addCleanup(tree.unlock)
         creator = shelf.ShelfCreator(tree, tree.basis_tree())
         self.addCleanup(creator.finalize)
         self.assertEqual([('rename', 'baz-id', 'foo/baz', 'bar/baz')],
@@ -97,13 +99,11 @@
         self.assertEqual('foo/baz', tree.id2path('baz-id'))
 
     def test_shelve_move(self):
-        self.thisFailsStrictLockCheck()
         creator, tree = self.prepare_shelve_move()
         creator.shelve_rename('baz-id')
         self.check_shelve_move(creator, tree)
 
     def test_shelve_change_handles_move(self):
-        self.thisFailsStrictLockCheck()
         creator, tree = self.prepare_shelve_move()
         creator.shelve_change(('rename', 'baz-id', 'foo/baz', 'bar/baz'))
         self.check_shelve_move(creator, tree)
@@ -114,7 +114,6 @@
         self.assertFileEqual(expected_content, shelf_file)
 
     def prepare_content_change(self):
-        self.thisFailsStrictLockCheck()
         tree = self.make_branch_and_tree('.')
         tree.lock_write()
         self.addCleanup(tree.unlock)
@@ -177,7 +176,6 @@
             creator.shelf_transform.final_kind(s_bar_trans_id))
 
     def test_shelve_creation(self):
-        self.thisFailsStrictLockCheck()
         creator, tree = self.prepare_shelve_creation()
         creator.shelve_creation('foo-id')
         creator.shelve_creation('bar-id')
@@ -185,7 +183,6 @@
         self.check_shelve_creation(creator, tree)
 
     def test_shelve_change_handles_creation(self):
-        self.thisFailsStrictLockCheck()
         creator, tree = self.prepare_shelve_creation()
         creator.shelve_change(('add file', 'foo-id', 'file', 'foo'))
         creator.shelve_change(('add file', 'bar-id', 'directory', 'bar'))
@@ -218,17 +215,14 @@
         self.assertEqual(link_target, ptree.get_symlink_target('foo-id'))
 
     def test_shelve_symlink_creation(self):
-        self.thisFailsStrictLockCheck()
         self._test_shelve_symlink_creation('foo', 'bar')
 
     def test_shelve_unicode_symlink_creation(self):
         self.requireFeature(tests.UnicodeFilenameFeature)
-        self.thisFailsStrictLockCheck()
         self._test_shelve_symlink_creation(u'fo\N{Euro Sign}o',
                                            u'b\N{Euro Sign}ar')
 
     def test_shelve_change_handles_symlink_creation(self):
-        self.thisFailsStrictLockCheck()
         self._test_shelve_symlink_creation('foo', 'bar', shelve_change=True)
 
     def _test_shelve_symlink_target_change(self, link_name,
@@ -262,22 +256,18 @@
         self.assertEqual(new_target, ptree.get_symlink_target('foo-id'))
 
     def test_shelve_symlink_target_change(self):
-        self.thisFailsStrictLockCheck()
         self._test_shelve_symlink_target_change('foo', 'bar', 'baz')
 
     def test_shelve_unicode_symlink_target_change(self):
-        self.thisFailsStrictLockCheck()
         self.requireFeature(tests.UnicodeFilenameFeature)
         self._test_shelve_symlink_target_change(
             u'fo\N{Euro Sign}o', u'b\N{Euro Sign}ar', u'b\N{Euro Sign}az')
 
     def test_shelve_change_handles_symlink_target_change(self):
-        self.thisFailsStrictLockCheck()
         self._test_shelve_symlink_target_change('foo', 'bar', 'baz',
                                                 shelve_change=True)
 
     def test_shelve_creation_no_contents(self):
-        self.thisFailsStrictLockCheck()
         tree = self.make_branch_and_tree('.')
         tree.lock_write()
         self.addCleanup(tree.unlock)
@@ -322,7 +312,6 @@
         self.assertFileEqual('baz', 'tree/foo/bar')
 
     def test_shelve_deletion(self):
-        self.thisFailsStrictLockCheck()
         creator, tree = self.prepare_shelve_deletion()
         creator.shelve_deletion('foo-id')
         creator.shelve_deletion('bar-id')
@@ -330,7 +319,6 @@
         self.check_shelve_deletion(tree)
 
     def test_shelve_change_handles_deletion(self):
-        self.thisFailsStrictLockCheck()
         creator, tree = self.prepare_shelve_deletion()
         creator.shelve_change(('delete file', 'foo-id', 'directory', 'foo'))
         creator.shelve_change(('delete file', 'bar-id', 'file', 'foo/bar'))
@@ -338,12 +326,13 @@
         self.check_shelve_deletion(tree)
 
     def test_shelve_delete_contents(self):
-        self.thisFailsStrictLockCheck()
         tree = self.make_branch_and_tree('tree')
         self.build_tree(['tree/foo',])
         tree.add('foo', 'foo-id')
         tree.commit('Added file and directory')
         os.unlink('tree/foo')
+        tree.lock_tree_write()
+        self.addCleanup(tree.unlock)
         creator = shelf.ShelfCreator(tree, tree.basis_tree())
         self.addCleanup(creator.finalize)
         self.assertEqual([('delete file', 'foo-id', 'file', 'foo')],
@@ -359,6 +348,8 @@
         tree.commit('Added file and directory')
         os.unlink('tree/foo')
         os.mkdir('tree/foo')
+        tree.lock_tree_write()
+        self.addCleanup(tree.unlock)
         creator = shelf.ShelfCreator(tree, tree.basis_tree())
         self.addCleanup(creator.finalize)
         self.assertEqual([('change kind', 'foo-id', 'file', 'directory',
@@ -372,14 +363,12 @@
                          creator.shelf_transform._new_contents[s_trans_id])
 
     def test_shelve_change_kind(self):
-        self.thisFailsStrictLockCheck()
         creator = self.prepare_shelve_change_kind()
         creator.shelve_content_change('foo-id')
         creator.transform()
         self.check_shelve_change_kind(creator)
 
     def test_shelve_change_handles_change_kind(self):
-        self.thisFailsStrictLockCheck()
         creator = self.prepare_shelve_change_kind()
         creator.shelve_change(('change kind', 'foo-id', 'file', 'directory',
                                'foo'))
@@ -387,20 +376,22 @@
         self.check_shelve_change_kind(creator)
 
     def test_shelve_change_unknown_change(self):
-        self.thisFailsStrictLockCheck()
         tree = self.make_branch_and_tree('tree')
+        tree.lock_tree_write()
+        self.addCleanup(tree.unlock)
         creator = shelf.ShelfCreator(tree, tree.basis_tree())
         self.addCleanup(creator.finalize)
         e = self.assertRaises(ValueError, creator.shelve_change, ('unknown',))
         self.assertEqual('Unknown change kind: "unknown"', str(e))
 
     def test_shelve_unversion(self):
-        self.thisFailsStrictLockCheck()
         tree = self.make_branch_and_tree('tree')
         self.build_tree(['tree/foo',])
         tree.add('foo', 'foo-id')
         tree.commit('Added file and directory')
         tree.unversion(['foo-id'])
+        tree.lock_tree_write()
+        self.addCleanup(tree.unlock)
         creator = shelf.ShelfCreator(tree, tree.basis_tree())
         self.addCleanup(creator.finalize)
         self.assertEqual([('delete file', 'foo-id', 'file', 'foo')],
@@ -410,8 +401,9 @@
         self.failUnlessExists('tree/foo')
 
     def test_shelve_serialization(self):
-        self.thisFailsStrictLockCheck()
         tree = self.make_branch_and_tree('.')
+        tree.lock_tree_write()
+        self.addCleanup(tree.unlock)
         creator = shelf.ShelfCreator(tree, tree.basis_tree())
         self.addCleanup(creator.finalize)
         shelf_file = open('shelf', 'wb')
@@ -423,10 +415,11 @@
         self.assertFileEqual(EMPTY_SHELF, 'shelf')
 
     def test_write_shelf(self):
-        self.thisFailsStrictLockCheck()
         tree = self.make_branch_and_tree('tree')
         self.build_tree(['tree/foo'])
         tree.add('foo', 'foo-id')
+        tree.lock_tree_write()
+        self.addCleanup(tree.unlock)
         creator = shelf.ShelfCreator(tree, tree.basis_tree())
         self.addCleanup(creator.finalize)
         list(creator.iter_shelvable())
@@ -450,10 +443,13 @@
         tt.deserialize(records)
 
     def test_shelve_unversioned(self):
-        self.thisFailsStrictLockCheck()
         tree = self.make_branch_and_tree('tree')
-        self.assertRaises(errors.PathsNotVersionedError,
-                          shelf.ShelfCreator, tree, tree.basis_tree(), ['foo'])
+        tree.lock_tree_write()
+        try:
+            self.assertRaises(errors.PathsNotVersionedError,
+                              shelf.ShelfCreator, tree, tree.basis_tree(), ['foo'])
+        finally:
+            tree.unlock()
         # We should be able to lock/unlock the tree if ShelfCreator cleaned
         # after itself.
         wt = workingtree.WorkingTree.open('tree')
@@ -461,12 +457,18 @@
         wt.unlock()
         # And a second tentative should raise the same error (no
         # limbo/pending_deletion leftovers).
-        self.assertRaises(errors.PathsNotVersionedError,
-                          shelf.ShelfCreator, tree, tree.basis_tree(), ['foo'])
+        tree.lock_tree_write()
+        try:
+            self.assertRaises(errors.PathsNotVersionedError,
+                              shelf.ShelfCreator, tree, tree.basis_tree(), ['foo'])
+        finally:
+            tree.unlock()
 
     def test_shelve_skips_added_root(self):
         """Skip adds of the root when iterating through shelvable changes."""
         tree = self.make_branch_and_tree('tree')
+        tree.lock_tree_write()
+        self.addCleanup(tree.unlock)
         creator = shelf.ShelfCreator(tree, tree.basis_tree())
         self.addCleanup(creator.finalize)
         self.assertEqual([], list(creator.iter_shelvable()))
@@ -475,7 +477,6 @@
 class TestUnshelver(tests.TestCaseWithTransport):
 
     def test_make_merger(self):
-        self.thisFailsStrictLockCheck()
         tree = self.make_branch_and_tree('tree')
         tree.commit('first commit')
         self.build_tree_contents([('tree/foo', 'bar')])
@@ -498,7 +499,6 @@
             shelf_file.close()
 
     def test_unshelve_changed(self):
-        self.thisFailsStrictLockCheck()
         tree = self.make_branch_and_tree('tree')
         tree.lock_write()
         self.addCleanup(tree.unlock)
@@ -521,7 +521,6 @@
         self.assertFileEqual('z\na\nb\nd\n', 'tree/foo')
 
     def test_unshelve_deleted(self):
-        self.thisFailsStrictLockCheck()
         tree = self.make_branch_and_tree('tree')
         tree.lock_write()
         self.addCleanup(tree.unlock)
@@ -551,7 +550,6 @@
         self.assertFalse('bar-id' in tree)
 
     def test_unshelve_base(self):
-        self.thisFailsStrictLockCheck()
         tree = self.make_branch_and_tree('tree')
         tree.lock_write()
         self.addCleanup(tree.unlock)
@@ -572,15 +570,14 @@
         self.assertEqual('rev1', unshelver.base_tree.get_revision_id())
 
     def test_unshelve_serialization(self):
-        self.thisFailsStrictLockCheck()
         tree = self.make_branch_and_tree('.')
         self.build_tree_contents([('shelf', EMPTY_SHELF)])
         shelf_file = open('shelf', 'rb')
         self.addCleanup(shelf_file.close)
         unshelver = shelf.Unshelver.from_tree_and_shelf(tree, shelf_file)
+        unshelver.finalize()
 
     def test_corrupt_shelf(self):
-        self.thisFailsStrictLockCheck()
         tree = self.make_branch_and_tree('.')
         self.build_tree_contents([('shelf', EMPTY_SHELF.replace('metadata',
                                                                 'foo'))])
@@ -698,7 +695,10 @@
 
     def test_get_metadata(self):
         tree = self.make_branch_and_tree('.')
+        tree.lock_tree_write()
+        self.addCleanup(tree.unlock)
         creator = shelf.ShelfCreator(tree, tree.basis_tree())
+        self.addCleanup(creator.finalize)
         shelf_manager = tree.get_shelf_manager()
         shelf_id = shelf_manager.shelve_changes(creator, 'foo')
         metadata = shelf_manager.get_metadata(shelf_id)

=== modified file 'bzrlib/tests/test_shelf_ui.py'
--- a/bzrlib/tests/test_shelf_ui.py	2009-08-24 16:56:26 +0000
+++ b/bzrlib/tests/test_shelf_ui.py	2009-08-25 21:09:17 +0000
@@ -72,23 +72,26 @@
         return tree
 
     def test_unexpected_prompt_failure(self):
-        self.thisFailsStrictLockCheck()
         tree = self.create_shelvable_tree()
+        tree.lock_tree_write()
+        self.addCleanup(tree.unlock)
         shelver = ExpectShelver(tree, tree.basis_tree())
         e = self.assertRaises(AssertionError, shelver.run)
         self.assertEqual('Unexpected prompt: Shelve? [yNfq?]', str(e))
 
     def test_wrong_prompt_failure(self):
-        self.thisFailsStrictLockCheck()
         tree = self.create_shelvable_tree()
+        tree.lock_tree_write()
+        self.addCleanup(tree.unlock)
         shelver = ExpectShelver(tree, tree.basis_tree())
         shelver.expect('foo', 'y')
         e = self.assertRaises(AssertionError, shelver.run)
         self.assertEqual('Wrong prompt: Shelve? [yNfq?]', str(e))
 
     def test_shelve_not_diff(self):
-        self.thisFailsStrictLockCheck()
         tree = self.create_shelvable_tree()
+        tree.lock_tree_write()
+        self.addCleanup(tree.unlock)
         shelver = ExpectShelver(tree, tree.basis_tree())
         shelver.expect('Shelve? [yNfq?]', 'n')
         shelver.expect('Shelve? [yNfq?]', 'n')
@@ -97,8 +100,9 @@
         self.assertFileEqual(LINES_ZY, 'tree/foo')
 
     def test_shelve_diff_no(self):
-        self.thisFailsStrictLockCheck()
         tree = self.create_shelvable_tree()
+        tree.lock_tree_write()
+        self.addCleanup(tree.unlock)
         shelver = ExpectShelver(tree, tree.basis_tree())
         shelver.expect('Shelve? [yNfq?]', 'y')
         shelver.expect('Shelve? [yNfq?]', 'y')
@@ -107,8 +111,9 @@
         self.assertFileEqual(LINES_ZY, 'tree/foo')
 
     def test_shelve_diff(self):
-        self.thisFailsStrictLockCheck()
         tree = self.create_shelvable_tree()
+        tree.lock_tree_write()
+        self.addCleanup(tree.unlock)
         shelver = ExpectShelver(tree, tree.basis_tree())
         shelver.expect('Shelve? [yNfq?]', 'y')
         shelver.expect('Shelve? [yNfq?]', 'y')
@@ -117,8 +122,9 @@
         self.assertFileEqual(LINES_AJ, 'tree/foo')
 
     def test_shelve_one_diff(self):
-        self.thisFailsStrictLockCheck()
         tree = self.create_shelvable_tree()
+        tree.lock_tree_write()
+        self.addCleanup(tree.unlock)
         shelver = ExpectShelver(tree, tree.basis_tree())
         shelver.expect('Shelve? [yNfq?]', 'y')
         shelver.expect('Shelve? [yNfq?]', 'n')
@@ -127,9 +133,10 @@
         self.assertFileEqual(LINES_AY, 'tree/foo')
 
     def test_shelve_binary_change(self):
-        self.thisFailsStrictLockCheck()
         tree = self.create_shelvable_tree()
         self.build_tree_contents([('tree/foo', '\x00')])
+        tree.lock_tree_write()
+        self.addCleanup(tree.unlock)
         shelver = ExpectShelver(tree, tree.basis_tree())
         shelver.expect('Shelve binary changes? [yNfq?]', 'y')
         shelver.expect('Shelve 1 change(s)? [yNfq?]', 'y')
@@ -137,9 +144,10 @@
         self.assertFileEqual(LINES_AJ, 'tree/foo')
 
     def test_shelve_rename(self):
-        self.thisFailsStrictLockCheck()
         tree = self.create_shelvable_tree()
         tree.rename_one('foo', 'bar')
+        tree.lock_tree_write()
+        self.addCleanup(tree.unlock)
         shelver = ExpectShelver(tree, tree.basis_tree())
         shelver.expect('Shelve renaming "foo" => "bar"? [yNfq?]', 'y')
         shelver.expect('Shelve? [yNfq?]', 'y')
@@ -149,9 +157,10 @@
         self.assertFileEqual(LINES_AJ, 'tree/foo')
 
     def test_shelve_deletion(self):
-        self.thisFailsStrictLockCheck()
         tree = self.create_shelvable_tree()
         os.unlink('tree/foo')
+        tree.lock_tree_write()
+        self.addCleanup(tree.unlock)
         shelver = ExpectShelver(tree, tree.basis_tree())
         shelver.expect('Shelve removing file "foo"? [yNfq?]', 'y')
         shelver.expect('Shelve 1 change(s)? [yNfq?]', 'y')
@@ -159,11 +168,12 @@
         self.assertFileEqual(LINES_AJ, 'tree/foo')
 
     def test_shelve_creation(self):
-        self.thisFailsStrictLockCheck()
         tree = self.make_branch_and_tree('tree')
         tree.commit('add tree root')
         self.build_tree(['tree/foo'])
         tree.add('foo')
+        tree.lock_tree_write()
+        self.addCleanup(tree.unlock)
         shelver = ExpectShelver(tree, tree.basis_tree())
         shelver.expect('Shelve adding file "foo"? [yNfq?]', 'y')
         shelver.expect('Shelve 1 change(s)? [yNfq?]', 'y')
@@ -171,17 +181,17 @@
         self.failIfExists('tree/foo')
 
     def test_shelve_kind_change(self):
-        self.thisFailsStrictLockCheck()
         tree = self.create_shelvable_tree()
         os.unlink('tree/foo')
         os.mkdir('tree/foo')
+        tree.lock_tree_write()
+        self.addCleanup(tree.unlock)
         shelver = ExpectShelver(tree, tree.basis_tree())
         shelver.expect('Shelve changing "foo" from file to directory? [yNfq?]',
                        'y')
         shelver.expect('Shelve 1 change(s)? [yNfq?]', 'y')
 
     def test_shelve_modify_target(self):
-        self.thisFailsStrictLockCheck()
         self.requireFeature(tests.SymlinkFeature)
         tree = self.create_shelvable_tree()
         os.symlink('bar', 'tree/baz')
@@ -189,6 +199,8 @@
         tree.commit("Add symlink")
         os.unlink('tree/baz')
         os.symlink('vax', 'tree/baz')
+        tree.lock_tree_write()
+        self.addCleanup(tree.unlock)
         shelver = ExpectShelver(tree, tree.basis_tree())
         shelver.expect('Shelve changing target of "baz" from "bar" to '
                 '"vax"? [yNfq?]', 'y')
@@ -197,8 +209,9 @@
         self.assertEqual('bar', os.readlink('tree/baz'))
 
     def test_shelve_finish(self):
-        self.thisFailsStrictLockCheck()
         tree = self.create_shelvable_tree()
+        tree.lock_tree_write()
+        self.addCleanup(tree.unlock)
         shelver = ExpectShelver(tree, tree.basis_tree())
         shelver.expect('Shelve? [yNfq?]', 'f')
         shelver.expect('Shelve 2 change(s)? [yNfq?]', 'y')
@@ -206,32 +219,39 @@
         self.assertFileEqual(LINES_AJ, 'tree/foo')
 
     def test_shelve_quit(self):
-        self.thisFailsStrictLockCheck()
         tree = self.create_shelvable_tree()
+        tree.lock_tree_write()
+        self.addCleanup(tree.unlock)
         shelver = ExpectShelver(tree, tree.basis_tree())
         shelver.expect('Shelve? [yNfq?]', 'q')
         self.assertRaises(errors.UserAbort, shelver.run)
         self.assertFileEqual(LINES_ZY, 'tree/foo')
 
     def test_shelve_all(self):
-        self.thisFailsStrictLockCheck()
         tree = self.create_shelvable_tree()
-        ExpectShelver.from_args(sys.stdout, all=True, directory='tree').run()
+        shelver = ExpectShelver.from_args(sys.stdout, all=True,
+            directory='tree')
+        try:
+            shelver.run()
+        finally:
+            shelver.work_tree.unlock()
         self.assertFileEqual(LINES_AJ, 'tree/foo')
 
     def test_shelve_filename(self):
-        self.thisFailsStrictLockCheck()
         tree = self.create_shelvable_tree()
         self.build_tree(['tree/bar'])
         tree.add('bar')
+        tree.lock_tree_write()
+        self.addCleanup(tree.unlock)
         shelver = ExpectShelver(tree, tree.basis_tree(), file_list=['bar'])
         shelver.expect('Shelve adding file "bar"? [yNfq?]', 'y')
         shelver.expect('Shelve 1 change(s)? [yNfq?]', 'y')
         shelver.run()
 
     def test_shelve_help(self):
-        self.thisFailsStrictLockCheck()
         tree = self.create_shelvable_tree()
+        tree.lock_tree_write()
+        self.addCleanup(tree.unlock)
         shelver = ExpectShelver(tree, tree.basis_tree())
         shelver.expect('Shelve? [yNfq?]', '?')
         shelver.expect('Shelve? [(y)es, (N)o, (f)inish, or (q)uit]', 'f')
@@ -239,11 +259,13 @@
         shelver.run()
 
     def test_shelve_distroy(self):
-        self.thisFailsStrictLockCheck()
         tree = self.create_shelvable_tree()
         shelver = shelf_ui.Shelver.from_args(sys.stdout, all=True,
                                              directory='tree', destroy=True)
-        shelver.run()
+        try:
+            shelver.run()
+        finally:
+            shelver.work_tree.unlock()
         self.assertIs(None, tree.get_shelf_manager().last_shelf())
         self.assertFileEqual(LINES_AJ, 'tree/foo')
 
@@ -289,8 +311,9 @@
 class TestApplyReporter(TestShelver):
 
     def test_shelve_not_diff(self):
-        self.thisFailsStrictLockCheck()
         tree = self.create_shelvable_tree()
+        tree.lock_tree_write()
+        self.addCleanup(tree.unlock)
         shelver = ExpectShelver(tree, tree.basis_tree(),
                                 reporter=shelf_ui.ApplyReporter())
         shelver.expect('Apply change? [yNfq?]', 'n')
@@ -300,8 +323,9 @@
         self.assertFileEqual(LINES_ZY, 'tree/foo')
 
     def test_shelve_diff_no(self):
-        self.thisFailsStrictLockCheck()
         tree = self.create_shelvable_tree()
+        tree.lock_tree_write()
+        self.addCleanup(tree.unlock)
         shelver = ExpectShelver(tree, tree.basis_tree(),
                                 reporter=shelf_ui.ApplyReporter())
         shelver.expect('Apply change? [yNfq?]', 'y')
@@ -311,8 +335,9 @@
         self.assertFileEqual(LINES_ZY, 'tree/foo')
 
     def test_shelve_diff(self):
-        self.thisFailsStrictLockCheck()
         tree = self.create_shelvable_tree()
+        tree.lock_tree_write()
+        self.addCleanup(tree.unlock)
         shelver = ExpectShelver(tree, tree.basis_tree(),
                                 reporter=shelf_ui.ApplyReporter())
         shelver.expect('Apply change? [yNfq?]', 'y')
@@ -322,9 +347,10 @@
         self.assertFileEqual(LINES_AJ, 'tree/foo')
 
     def test_shelve_binary_change(self):
-        self.thisFailsStrictLockCheck()
         tree = self.create_shelvable_tree()
         self.build_tree_contents([('tree/foo', '\x00')])
+        tree.lock_tree_write()
+        self.addCleanup(tree.unlock)
         shelver = ExpectShelver(tree, tree.basis_tree(),
                                 reporter=shelf_ui.ApplyReporter())
         shelver.expect('Apply binary changes? [yNfq?]', 'y')
@@ -333,9 +359,10 @@
         self.assertFileEqual(LINES_AJ, 'tree/foo')
 
     def test_shelve_rename(self):
-        self.thisFailsStrictLockCheck()
         tree = self.create_shelvable_tree()
         tree.rename_one('foo', 'bar')
+        tree.lock_tree_write()
+        self.addCleanup(tree.unlock)
         shelver = ExpectShelver(tree, tree.basis_tree(),
                                 reporter=shelf_ui.ApplyReporter())
         shelver.expect('Rename "bar" => "foo"? [yNfq?]', 'y')
@@ -346,9 +373,10 @@
         self.assertFileEqual(LINES_AJ, 'tree/foo')
 
     def test_shelve_deletion(self):
-        self.thisFailsStrictLockCheck()
         tree = self.create_shelvable_tree()
         os.unlink('tree/foo')
+        tree.lock_tree_write()
+        self.addCleanup(tree.unlock)
         shelver = ExpectShelver(tree, tree.basis_tree(),
                                 reporter=shelf_ui.ApplyReporter())
         shelver.expect('Add file "foo"? [yNfq?]', 'y')
@@ -357,11 +385,12 @@
         self.assertFileEqual(LINES_AJ, 'tree/foo')
 
     def test_shelve_creation(self):
-        self.thisFailsStrictLockCheck()
         tree = self.make_branch_and_tree('tree')
         tree.commit('add tree root')
         self.build_tree(['tree/foo'])
         tree.add('foo')
+        tree.lock_tree_write()
+        self.addCleanup(tree.unlock)
         shelver = ExpectShelver(tree, tree.basis_tree(),
                                 reporter=shelf_ui.ApplyReporter())
         shelver.expect('Delete file "foo"? [yNfq?]', 'y')
@@ -370,17 +399,17 @@
         self.failIfExists('tree/foo')
 
     def test_shelve_kind_change(self):
-        self.thisFailsStrictLockCheck()
         tree = self.create_shelvable_tree()
         os.unlink('tree/foo')
         os.mkdir('tree/foo')
+        tree.lock_tree_write()
+        self.addCleanup(tree.unlock)
         shelver = ExpectShelver(tree, tree.basis_tree(),
                                reporter=shelf_ui.ApplyReporter())
         shelver.expect('Change "foo" from directory to a file? [yNfq?]', 'y')
         shelver.expect('Apply 1 change(s)? [yNfq?]', 'y')
 
     def test_shelve_modify_target(self):
-        self.thisFailsStrictLockCheck()
         self.requireFeature(tests.SymlinkFeature)
         tree = self.create_shelvable_tree()
         os.symlink('bar', 'tree/baz')
@@ -388,6 +417,8 @@
         tree.commit("Add symlink")
         os.unlink('tree/baz')
         os.symlink('vax', 'tree/baz')
+        tree.lock_tree_write()
+        self.addCleanup(tree.unlock)
         shelver = ExpectShelver(tree, tree.basis_tree(),
                                 reporter=shelf_ui.ApplyReporter())
         shelver.expect('Change target of "baz" from "vax" to "bar"? [yNfq?]',
@@ -401,16 +432,19 @@
 
     def create_tree_with_shelf(self):
         tree = self.make_branch_and_tree('tree')
-        self.build_tree_contents([('tree/foo', LINES_AJ)])
-        tree.add('foo', 'foo-id')
-        tree.commit('added foo')
-        self.build_tree_contents([('tree/foo', LINES_ZY)])
-        shelf_ui.Shelver(tree, tree.basis_tree(), auto_apply=True,
-                         auto=True).run()
+        tree.lock_write()
+        try:
+            self.build_tree_contents([('tree/foo', LINES_AJ)])
+            tree.add('foo', 'foo-id')
+            tree.commit('added foo')
+            self.build_tree_contents([('tree/foo', LINES_ZY)])
+            shelf_ui.Shelver(tree, tree.basis_tree(), auto_apply=True,
+                             auto=True).run()
+        finally:
+            tree.unlock()
         return tree
 
     def test_unshelve(self):
-        self.thisFailsStrictLockCheck()
         tree = self.create_tree_with_shelf()
         tree.lock_write()
         self.addCleanup(tree.unlock)
@@ -419,21 +453,27 @@
         self.assertFileEqual(LINES_ZY, 'tree/foo')
 
     def test_unshelve_args(self):
-        self.thisFailsStrictLockCheck()
         tree = self.create_tree_with_shelf()
-        shelf_ui.Unshelver.from_args(directory='tree').run()
+        unshelver = shelf_ui.Unshelver.from_args(directory='tree')
+        try:
+            unshelver.run()
+        finally:
+            unshelver.tree.unlock()
         self.assertFileEqual(LINES_ZY, 'tree/foo')
         self.assertIs(None, tree.get_shelf_manager().last_shelf())
 
     def test_unshelve_args_dry_run(self):
-        self.thisFailsStrictLockCheck()
         tree = self.create_tree_with_shelf()
-        shelf_ui.Unshelver.from_args(directory='tree', action='dry-run').run()
+        unshelver = shelf_ui.Unshelver.from_args(directory='tree',
+            action='dry-run')
+        try:
+            unshelver.run()
+        finally:
+            unshelver.tree.unlock()
         self.assertFileEqual(LINES_AJ, 'tree/foo')
         self.assertEqual(1, tree.get_shelf_manager().last_shelf())
 
     def test_unshelve_args_delete_only(self):
-        self.thisFailsStrictLockCheck()
         tree = self.make_branch_and_tree('tree')
         manager = tree.get_shelf_manager()
         shelf_file = manager.new_shelf()[1]
@@ -443,11 +483,13 @@
             shelf_file.close()
         unshelver = shelf_ui.Unshelver.from_args(directory='tree',
                                                  action='delete-only')
-        unshelver.run()
+        try:
+            unshelver.run()
+        finally:
+            unshelver.tree.unlock()
         self.assertIs(None, manager.last_shelf())
 
     def test_unshelve_args_invalid_shelf_id(self):
-        self.thisFailsStrictLockCheck()
         tree = self.make_branch_and_tree('tree')
         manager = tree.get_shelf_manager()
         shelf_file = manager.new_shelf()[1]




More information about the bazaar-commits mailing list