Merge lp:~danny.vanheumen/bzr/bug-498409-bzr-revert-takes-a-branch-lock into lp:bzr/2.0

Proposed by Danny van Heumen
Status: Merged
Approved by: Andrew Bennetts
Approved revision: no longer in the source branch.
Merged at revision: not available
Proposed branch: lp:~danny.vanheumen/bzr/bug-498409-bzr-revert-takes-a-branch-lock
Merge into: lp:bzr/2.0
Diff against target: 166 lines (+105/-2)
6 files modified
NEWS (+4/-0)
bzrlib/builtins.py (+1/-1)
bzrlib/lock.py (+1/-1)
bzrlib/tests/commands/__init__.py (+1/-0)
bzrlib/tests/commands/test_revert.py (+61/-0)
doc/developers/testing.txt (+37/-0)
To merge this branch: bzr merge lp:~danny.vanheumen/bzr/bug-498409-bzr-revert-takes-a-branch-lock
Reviewer Review Type Date Requested Status
Ian Clatworthy Approve
Andrew Bennetts Approve
Review via email: mp+21000@code.launchpad.net

Commit message

(andrew, for Danny van Heumen) 'bzr revert' no longer takes a branch lock (#498409)

Description of the change

Fix for bug 498409 bzr revert takes a branch lock including a test.

To post a comment you must log in.
Revision history for this message
Andrew Bennetts (spiv) wrote :

Overall this looks very good, and only needs a few tweaks I think.

Thanks for writing that documentation! I was a bit surprised to see a documentation addition in the diff because you didn't mention it in the merge proposal description, but it was a welcome surprise :)

126 +Note that the representation of LockResult can be confusing. As can be seen in
127 +the sample below::
128 +
129 + LockResult(file:///tmp/testbzr-J2pcy2.tmp/.bzr/branch/lockh8c6t28rcjdkgxtndbje)
130 +
131 +The last 20 characters, in this case `h8c6t28rcjdkgxtndbje`, are used internally
132 +in the locking mechanism. The locking URL is everything before that.

That is confusing. Rather than explain the confusing, I think we should just fix LockResult's __repr__ method so that it doesn't confuse, e.g.:

     def __repr__(self):
- return '%s(%s%s)' % (self.__class__.__name__,
+ return '%s(%s, %s)' % (self.__class__.__name__,

(in bzrlib/lock.py)

147 +Note: There is one special case of a lock that is created during the creation of
148 +the '.bzr' directory, for example when a new branch is initialized.
149 +If this is the case, the LockResult will look like this::
150 +
151 + LockResult(file:///tmp/testbzr-J2pcy2.tmp/.bzr/branch-lockc4au55ppz8wdym11z1aq)
152 +
153 +or `/branch-lock`

I don't think this is a special case, really. I'd just list this as "BzrDir: `/branch-lock`" in your list of lock types.

83 + # make sure that only one lock is acquired and released.
84 + self.assertEqual(1, len(locks_acquired))
85 + self.assertEqual(1, len(locks_released))

Use "self.assertLength(1, locks_acquired)" instead; it's a little short and clearer, and will give more informative errors if it fails.

65 + self.start_logging_connections()

I don't think you need to call this, you don't seem to use it. For that matter, I think you should simply use TestCaseInTempDir rather than the more complicated TestCaseWithConnectionHookedTransport.

You should add an entry to NEWS for this fix — you deserve the credit!

Finally, it appears you haven't signed a contributors agreement yet, please follow the instructions at <http://www.canonical.com/contributors>.

Thanks!

review: Needs Fixing
Revision history for this message
Danny van Heumen (danny.vanheumen) wrote :

Processed all suggested tweaks.

Revision history for this message
Andrew Bennetts (spiv) wrote :

Thanks, that looks good to me. All that's left is a review from a second person, and the contributor agreement.

review: Approve
Revision history for this message
Danny van Heumen (danny.vanheumen) wrote :

> Thanks, that looks good to me. All that's left is a review from a second
> person, and the contributor agreement.
I mailed the Contributor Agreement yesterday.

Revision history for this message
Martin Pool (mbp) wrote :

On 18 March 2010 11:19, Danny van Heumen <email address hidden> wrote:
>> Thanks, that looks good to me.  All that's left is a review from a second
>> person, and the contributor agreement.
> I mailed the Contributor Agreement yesterday.

Hi Danny,

I got your questions about it (obviously, since I replied) and I saw
you say you sent it, but I didn't actually get the agreement. Did you
cc me?

thanks,

--
Martin <http://launchpad.net/~mbp/>

Revision history for this message
Ian Clatworthy (ian-clatworthy) wrote :

Looks good to me. In particular, thanks for the documentation explaining how to test lock behaviour.

review: Approve
Revision history for this message
Andrew Bennetts (spiv) wrote :
Revision history for this message
Vincent Ladeuil (vila) wrote :

Watch out ! This has been merged after 2.0.5 tarball has been cut but still mentions
the bugfix in the 2.0.5 NEWS section.

Revision history for this message
Andrew Bennetts (spiv) wrote :

Vincent Ladeuil wrote:
> Watch out ! This has been merged after 2.0.5 tarball has been cut but still mentions
> the bugfix in the 2.0.5 NEWS section.

Ouch! Good catch, I'll fix that now.

-Andrew.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'NEWS'
2--- NEWS 2010-03-17 04:26:48 +0000
3+++ NEWS 2010-03-18 00:01:02 +0000
4@@ -54,6 +54,10 @@
5 errors.
6 (Inada Naoki, #524560)
7
8+* ``bzr revert`` now only takes write lock on working tree, instead of on
9+ both working tree and branch.
10+ (Danny van Heumen, #498409)
11+
12 Documentation
13 *************
14
15
16=== modified file 'bzrlib/builtins.py'
17--- bzrlib/builtins.py 2009-12-16 22:26:56 +0000
18+++ bzrlib/builtins.py 2010-03-18 00:01:02 +0000
19@@ -4045,7 +4045,7 @@
20 def run(self, revision=None, no_backup=False, file_list=None,
21 forget_merges=None):
22 tree, file_list = tree_files(file_list)
23- tree.lock_write()
24+ tree.lock_tree_write()
25 try:
26 if forget_merges:
27 tree.set_parent_ids(tree.get_parent_ids()[:1])
28
29=== modified file 'bzrlib/lock.py'
30--- bzrlib/lock.py 2009-07-31 16:51:48 +0000
31+++ bzrlib/lock.py 2010-03-18 00:01:02 +0000
32@@ -84,7 +84,7 @@
33 return self.lock_url == other.lock_url and self.details == other.details
34
35 def __repr__(self):
36- return '%s(%s%s)' % (self.__class__.__name__,
37+ return '%s(%s, %s)' % (self.__class__.__name__,
38 self.lock_url, self.details)
39
40
41
42=== modified file 'bzrlib/tests/commands/__init__.py'
43--- bzrlib/tests/commands/__init__.py 2009-03-23 14:59:43 +0000
44+++ bzrlib/tests/commands/__init__.py 2010-03-18 00:01:02 +0000
45@@ -41,6 +41,7 @@
46 'bzrlib.tests.commands.test_pull',
47 'bzrlib.tests.commands.test_push',
48 'bzrlib.tests.commands.test_update',
49+ 'bzrlib.tests.commands.test_revert',
50 ]
51 # add the tests for the sub modules
52 suite.addTests(loader.loadTestsFromModuleNames(testmod_names))
53
54=== added file 'bzrlib/tests/commands/test_revert.py'
55--- bzrlib/tests/commands/test_revert.py 1970-01-01 00:00:00 +0000
56+++ bzrlib/tests/commands/test_revert.py 2010-03-18 00:01:02 +0000
57@@ -0,0 +1,61 @@
58+# Copyright (C) 2010 Canonical Ltd
59+#
60+# This program is free software; you can redistribute it and/or modify
61+# it under the terms of the GNU General Public License as published by
62+# the Free Software Foundation; either version 2 of the License, or
63+# (at your option) any later version.
64+#
65+# This program is distributed in the hope that it will be useful,
66+# but WITHOUT ANY WARRANTY; without even the implied warranty of
67+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
68+# GNU General Public License for more details.
69+#
70+# You should have received a copy of the GNU General Public License
71+# along with this program; if not, write to the Free Software
72+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
73+
74+import os
75+from bzrlib import (
76+ branch,
77+ builtins,
78+ errors,
79+ lock,
80+ )
81+from bzrlib.tests import (
82+ transport_util,
83+ TestCaseInTempDir,
84+ )
85+
86+
87+class TestRevert(TestCaseInTempDir):
88+
89+ def setUp(self):
90+ super(TestRevert, self).setUp()
91+
92+ def test_revert_tree_write_lock_and_branch_read_lock(self):
93+
94+ # install lock hooks to find out about cmd_revert's locking actions
95+ locks_acquired = []
96+ locks_released = []
97+ lock.Lock.hooks.install_named_hook('lock_acquired',
98+ locks_acquired.append, None)
99+ lock.Lock.hooks.install_named_hook('lock_released',
100+ locks_released.append, None)
101+
102+ # execute the revert command (There is nothing to actually revert,
103+ # but locks are acquired either way.)
104+ revert = builtins.cmd_revert()
105+ revert.run()
106+
107+ # make sure that only one lock is acquired and released.
108+ self.assertLength(1, locks_acquired)
109+ self.assertLength(1, locks_released)
110+
111+ # make sure that the nonces are the same, since otherwise
112+ # this would not be the same lock.
113+ self.assertEqual(locks_acquired[0].details, locks_released[0].details)
114+
115+ # make sure that the locks are checkout locks.
116+ self.assertEndsWith(locks_acquired[0].lock_url, "/checkout/lock")
117+ self.assertEndsWith(locks_released[0].lock_url, "/checkout/lock")
118+
119
120=== modified file 'doc/developers/testing.txt'
121--- doc/developers/testing.txt 2009-09-09 02:21:47 +0000
122+++ doc/developers/testing.txt 2010-03-18 00:01:02 +0000
123@@ -201,6 +201,43 @@
124 .. ~~~~~~~~~~~~
125
126
127+Testing locking behaviour
128+-------------------------
129+
130+In order to test the locking behaviour of commands, it is possible to install
131+a hook that is called when a write lock is: acquired, released or broken.
132+(Read locks also exist, they cannot be discovered in this way.)
133+
134+A hook can be installed by calling bzrlib.lock.Lock.hooks.install_named_hook.
135+The three valid hooks are: `lock_acquired`, `lock_released` and `lock_broken`.
136+
137+Example::
138+
139+ locks_acquired = []
140+ locks_released = []
141+
142+ lock.Lock.hooks.install_named_hook('lock_acquired',
143+ locks_acquired.append, None)
144+ lock.Lock.hooks.install_named_hook('lock_released',
145+ locks_released.append, None)
146+
147+`locks_acquired` will now receive a LockResult instance for all locks acquired
148+since the time the hook is installed.
149+
150+The last part of the `lock_url` allows you to identify the type of object that is locked.
151+
152+- BzrDir: `/branch-lock`
153+- Working tree: `/checkout/lock`
154+- Branch: `/branch/lock`
155+- Repository: `/repository/lock`
156+
157+To test if a lock is a write lock on a working tree, one can do the following::
158+
159+ self.assertEndsWith(locks_acquired[0].lock_url, "/checkout/lock")
160+
161+See bzrlib/tests/commands/test_revert.py for an example of how to use this for
162+testing locks.
163+
164
165 Skipping tests
166 --------------

Subscribers

People subscribed via source and target branches