Rev 2356: Define an explicit error when trying to grab a write lock on a readonly file. in http://bzr.arbash-meinel.com/branches/bzr/0.15-dev/locking
John Arbash Meinel
john at arbash-meinel.com
Tue Mar 13 19:39:35 GMT 2007
At http://bzr.arbash-meinel.com/branches/bzr/0.15-dev/locking
------------------------------------------------------------
revno: 2356
revision-id: john at arbash-meinel.com-20070313193927-8opc18wbi7ln0gil
parent: john at arbash-meinel.com-20070313191557-ouvms9hsnpij9xct
committer: John Arbash Meinel <john at arbash-meinel.com>
branch nick: locking
timestamp: Tue 2007-03-13 13:39:27 -0600
message:
Define an explicit error when trying to grab a write lock on a readonly file.
Add some future tests that ensure write and read locks exclude eachother.
Currently fcntl locks do not exclude.
modified:
bzrlib/errors.py errors.py-20050309040759-20512168c4e14fbd
bzrlib/lock.py lock.py-20050527050856-ec090bb51bc03349
bzrlib/tests/test_lock.py test_lock.py-20070313190612-mfpoa7t8kvrgrhj2-1
-------------- next part --------------
=== modified file 'bzrlib/errors.py'
--- a/bzrlib/errors.py 2007-03-12 16:46:21 +0000
+++ b/bzrlib/errors.py 2007-03-13 19:39:27 +0000
@@ -697,6 +697,15 @@
self.obj = obj
+class ReadOnlyLockError(LockError):
+
+ _fmt = "Cannot acquire write lock on %(fname)s. File is readonly."
+
+ def __init__(self, fname):
+ LockError.__init__(self, '')
+ self.fname = fname
+
+
class OutSideTransaction(BzrError):
_fmt = ("A transaction related operation was attempted after"
=== modified file 'bzrlib/lock.py'
--- a/bzrlib/lock.py 2007-03-01 21:56:19 +0000
+++ b/bzrlib/lock.py 2007-03-13 19:39:27 +0000
@@ -38,6 +38,7 @@
import os
import sys
+from bzrlib import errors
from bzrlib.errors import LockError, LockContention
from bzrlib.osutils import realpath
from bzrlib.trace import mutter
@@ -96,7 +97,12 @@
def __init__(self, filename):
# standard IO errors get exposed directly.
- self._open(filename, 'rb+')
+ try:
+ self._open(filename, 'rb+')
+ except IOError, e:
+ if e.errno in (errno.EACCES, errno.EPERM):
+ raise errors.ReadOnlyLockError(e)
+ raise
self.filename = realpath(filename)
if self.filename in self.open_locks:
self._clear_f()
@@ -124,8 +130,9 @@
class _fcntl_ReadLock(_fcntl_FileLock):
+ open_locks = {}
+
def __init__(self, filename):
- # standard IO errors get exposed directly.
self._open(filename, 'rb')
try:
# LOCK_NB will cause IOError to be raised if we can't grab a
=== modified file 'bzrlib/tests/test_lock.py'
--- a/bzrlib/tests/test_lock.py 2007-03-13 19:15:57 +0000
+++ b/bzrlib/tests/test_lock.py 2007-03-13 19:39:27 +0000
@@ -19,6 +19,7 @@
from bzrlib import (
errors,
lock,
+ osutils,
tests,
)
@@ -55,6 +56,20 @@
txt = a_lock.f.read()
self.assertEqual('foo\n', txt)
+ def test_readonly_file(self):
+ """If the file is readonly, we can take a read lock.
+
+ But we shouldn't be able to take a write lock.
+ """
+ osutils.make_readonly('a-file')
+ # Make sure the file is read-only (on all platforms)
+ self.assertRaises(IOError, open, 'a-file', 'rb+')
+ a_lock = lock.ReadLock('a-file')
+ a_lock.unlock()
+
+ # TODO: jam 20070313 This should be a specific subclass
+ self.assertRaises(errors.ReadOnlyLockError, lock.WriteLock, 'a-file')
+
def test_write_lock(self):
"""Smoke test for write locks."""
a_lock = lock.WriteLock('a-file')
@@ -80,3 +95,21 @@
self.addCleanup(a_lock.unlock)
# Taking out a lock on a locked file should raise LockContention
self.assertRaises(errors.LockContention, lock.WriteLock, 'a-file')
+
+ def _disabled_test_read_then_write_excludes(self):
+ """If a file is read-locked, taking out a write lock should fail."""
+ a_lock = lock.ReadLock('a-file')
+ self.addCleanup(a_lock.unlock)
+ # Taking out a lock on a locked file should raise LockContention
+ self.assertRaises(errors.LockContention, lock.WriteLock, 'a-file')
+
+ def _disabled_test_write_then_read_excludes(self):
+ """If a file is write-locked, taking out a read lock should fail.
+
+ The file is exclusively owned by the write lock, so we shouldn't be
+ able to take out a shared read lock.
+ """
+ a_lock = lock.WriteLock('a-file')
+ self.addCleanup(a_lock.unlock)
+ # Taking out a lock on a locked file should raise LockContention
+ self.assertRaises(errors.LockContention, lock.ReadLock, 'a-file')
More information about the bazaar-commits
mailing list