Merge lp:~mbp/bzr/427773-empty-limbo into lp:bzr/2.4

Proposed by Martin Pool
Status: Merged
Approved by: Martin Pool
Approved revision: no longer in the source branch.
Merged at revision: 6062
Proposed branch: lp:~mbp/bzr/427773-empty-limbo
Merge into: lp:bzr/2.4
Diff against target: 114 lines (+51/-18)
4 files modified
bzrlib/osutils.py (+15/-0)
bzrlib/tests/per_merger.py (+24/-8)
bzrlib/transform.py (+6/-10)
doc/en/release-notes/bzr-2.4.txt (+6/-0)
To merge this branch: bzr merge lp:~mbp/bzr/427773-empty-limbo
Reviewer Review Type Date Requested Status
Jelmer Vernooij Pending
Review via email: mp+83857@code.launchpad.net

This proposal supersedes a proposal from 2011-11-29.

Commit message

tolerate empty limbo and pending-deletion directories (bug 427773)

Description of the change

fix up niggling bug 427773 by tolerating empty limbo dirs.

also, I saw we were actually squashing any exception raised while creating them, so this fixes that.

To post a comment you must log in.
Revision history for this message
Jelmer Vernooij (jelmer) wrote : Posted in a previous version of this proposal

I guess FAT is another filesystem on Unix where this occurs?

102 +class _PosixPermissionsFeature(Feature):
103 +
104 + def _probe(self):
105 + def has_perms():
106 + # create temporary file and check if specified perms are maintained.
107 + import tempfile
108 +
109 + write_perms = stat.S_IRUSR | stat.S_IWUSR | stat.S_IXUSR
110 + f = tempfile.mkstemp(prefix='bzr_perms_chk_')
Should this be using self.test_dir ? I'm not sure how to get at that variable from within a Feature though. I'm not sure how many people have /tmp mounted over SMB though. :-)

review: Approve
Revision history for this message
Martin Pool (mbp) wrote : Posted in a previous version of this proposal

ah, this is orignially off 2.4 so the diff is a bit weird...

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

+class _PosixPermissionsFeature(Feature):

That's in 2.4 and I guess not yet merged up to trunk.

I think it is probably harmless enough not to be worth chasing: it's possible that tempfile creates things in a different place to what our TestCase does but not all that likely.

It would be kind of nice to move the tests's own tempdir into a feature that could somehow be depended upon by this. It seems like you want almost a concept of a dynamic scope environment for the tests, or perhaps just a pointer back to the test object is enough.

Anyhow, I will merge the limbo related bits, thanks for the review.

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

sent to pqm by email

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

sent to pqm by email

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'bzrlib/osutils.py'
--- bzrlib/osutils.py 2011-11-18 00:32:50 +0000
+++ bzrlib/osutils.py 2011-12-01 01:06:24 +0000
@@ -2532,3 +2532,18 @@
2532 fn = getattr(os, 'fdatasync', getattr(os, 'fsync', None))2532 fn = getattr(os, 'fdatasync', getattr(os, 'fsync', None))
2533 if fn is not None:2533 if fn is not None:
2534 fn(fileno)2534 fn(fileno)
2535
2536
2537def ensure_empty_directory_exists(path, exception_class):
2538 """Make sure a local directory exists and is empty.
2539
2540 If it does not exist, it is created. If it exists and is not empty, an
2541 instance of exception_class is raised.
2542 """
2543 try:
2544 os.mkdir(path)
2545 except OSError, e:
2546 if e.errno != errno.EEXIST:
2547 raise
2548 if os.listdir(path) != []:
2549 raise exception_class(path)
25352550
=== modified file 'bzrlib/tests/per_merger.py'
--- bzrlib/tests/per_merger.py 2011-01-12 01:01:53 +0000
+++ bzrlib/tests/per_merger.py 2011-12-01 01:06:24 +0000
@@ -175,17 +175,33 @@
175 transform.finalize()175 transform.finalize()
176 return (limbodir, deletiondir)176 return (limbodir, deletiondir)
177177
178 def test_merge_with_existing_limbo(self):178 def test_merge_with_existing_limbo_empty(self):
179 wt = self.make_branch_and_tree('this')179 """Empty limbo dir is just cleaned up - see bug 427773"""
180 (limbodir, deletiondir) = self.get_limbodir_deletiondir(wt)180 wt = self.make_branch_and_tree('this')
181 os.mkdir(limbodir)181 (limbodir, deletiondir) = self.get_limbodir_deletiondir(wt)
182 os.mkdir(limbodir)
183 self.do_merge(wt, wt)
184
185 def test_merge_with_existing_limbo_non_empty(self):
186 wt = self.make_branch_and_tree('this')
187 (limbodir, deletiondir) = self.get_limbodir_deletiondir(wt)
188 os.mkdir(limbodir)
189 os.mkdir(os.path.join(limbodir, 'something'))
182 self.assertRaises(errors.ExistingLimbo, self.do_merge, wt, wt)190 self.assertRaises(errors.ExistingLimbo, self.do_merge, wt, wt)
183 self.assertRaises(errors.LockError, wt.unlock)191 self.assertRaises(errors.LockError, wt.unlock)
184192
185 def test_merge_with_pending_deletion(self):193 def test_merge_with_pending_deletion_empty(self):
186 wt = self.make_branch_and_tree('this')194 wt = self.make_branch_and_tree('this')
187 (limbodir, deletiondir) = self.get_limbodir_deletiondir(wt)195 (limbodir, deletiondir) = self.get_limbodir_deletiondir(wt)
188 os.mkdir(deletiondir)196 os.mkdir(deletiondir)
197 self.do_merge(wt, wt)
198
199 def test_merge_with_pending_deletion_non_empty(self):
200 """Also see bug 427773"""
201 wt = self.make_branch_and_tree('this')
202 (limbodir, deletiondir) = self.get_limbodir_deletiondir(wt)
203 os.mkdir(deletiondir)
204 os.mkdir(os.path.join(deletiondir, 'something'))
189 self.assertRaises(errors.ExistingPendingDeletion, self.do_merge, wt, wt)205 self.assertRaises(errors.ExistingPendingDeletion, self.do_merge, wt, wt)
190 self.assertRaises(errors.LockError, wt.unlock)206 self.assertRaises(errors.LockError, wt.unlock)
191207
192208
=== modified file 'bzrlib/transform.py'
--- bzrlib/transform.py 2011-11-14 09:37:40 +0000
+++ bzrlib/transform.py 2011-12-01 01:06:24 +0000
@@ -1562,18 +1562,14 @@
1562 try:1562 try:
1563 limbodir = urlutils.local_path_from_url(1563 limbodir = urlutils.local_path_from_url(
1564 tree._transport.abspath('limbo'))1564 tree._transport.abspath('limbo'))
1565 try:1565 osutils.ensure_empty_directory_exists(
1566 os.mkdir(limbodir)1566 limbodir,
1567 except OSError, e:1567 errors.ExistingLimbo)
1568 if e.errno == errno.EEXIST:
1569 raise ExistingLimbo(limbodir)
1570 deletiondir = urlutils.local_path_from_url(1568 deletiondir = urlutils.local_path_from_url(
1571 tree._transport.abspath('pending-deletion'))1569 tree._transport.abspath('pending-deletion'))
1572 try:1570 osutils.ensure_empty_directory_exists(
1573 os.mkdir(deletiondir)1571 deletiondir,
1574 except OSError, e:1572 errors.ExistingPendingDeletion)
1575 if e.errno == errno.EEXIST:
1576 raise errors.ExistingPendingDeletion(deletiondir)
1577 except:1573 except:
1578 tree.unlock()1574 tree.unlock()
1579 raise1575 raise
15801576
=== modified file 'doc/en/release-notes/bzr-2.4.txt'
--- doc/en/release-notes/bzr-2.4.txt 2011-11-14 09:37:40 +0000
+++ doc/en/release-notes/bzr-2.4.txt 2011-12-01 01:06:24 +0000
@@ -35,6 +35,12 @@
35* Cope with Unix filesystems, such as smbfs, where chmod gives 'permission35* Cope with Unix filesystems, such as smbfs, where chmod gives 'permission
36 denied'. (Martin Pool, #606537)36 denied'. (Martin Pool, #606537)
3737
38* When the ``limbo`` or ``pending-deletion`` directories exist, typically
39 because of an interrupted tree update, but are empty, bzr no longer
40 errors out, because there is nothing for the user to clean up. Also,
41 errors in creation of these directories are no longer squelched.
42 (Martin Pool, #427773)
43
38* During merges, when two entries end up using the same path for two44* During merges, when two entries end up using the same path for two
39 different file-ids (the same file being 'bzr added' in two different45 different file-ids (the same file being 'bzr added' in two different
40 branches) , 'duplicate' conflicts are created instead of 'content'46 branches) , 'duplicate' conflicts are created instead of 'content'

Subscribers

People subscribed via source and target branches