Rev 36: We can take a lock, and figure out the state change. in lp:~jameinel/+junk/file_locking
John Arbash Meinel
john at arbash-meinel.com
Wed Sep 23 05:20:25 BST 2009
At lp:~jameinel/+junk/file_locking
------------------------------------------------------------
revno: 36
revision-id: john at arbash-meinel.com-20090923042011-2yf08hrrtsown8dk
parent: john at arbash-meinel.com-20090923031025-29l2sznhmmp0akvb
committer: John Arbash Meinel <john at arbash-meinel.com>
branch nick: file_locking
timestamp: Tue 2009-09-22 23:20:11 -0500
message:
We can take a lock, and figure out the state change.
Note that locking isn't saved yet, and the serializer doesn't support
*reading* active locks... :)
-------------- next part --------------
=== modified file 'file_lock.py'
--- a/file_lock.py 2009-09-23 03:07:03 +0000
+++ b/file_lock.py 2009-09-23 04:20:11 +0000
@@ -151,7 +151,7 @@
tracked_ids = []
else:
tracked_ids = stanza.get_all('t')
- return FileLockingInfo(tracked_ids, [], logger)
+ return FileLockingInfo(tracked_ids, {}, logger)
def to_bytes(self, locking_info):
content = [self._HEADER, '\n']
@@ -356,7 +356,7 @@
'This is a Bazaar File Locking Lock Store\n'
'You should not need to modify any files in this directory.\n')
logger = FileLockLogger.initialize(transport, 'log')
- locking_info = FileLockingInfo([], [], logger)
+ locking_info = FileLockingInfo([], {}, logger)
# Instead of having a separate 'format' file, we put the data into
# the 'info' file. Which means that we have 1 less object to read
# from remote.
@@ -500,6 +500,34 @@
trackers[path] = None
return trackers
+ def get_path_status(self, path):
+ """Figure out what the status is for a given path.
+
+ :param path: A path to analyze
+ :return: Several possibilities
+ 'untracked' This path nor its parents are not tracked
+ 'tracked' (at) This path or its parent is tracked, but not
+ currently locked
+ 'remote locked' Someone else holds a lock that applies to this path
+ 'local locked' We hold a lock that applies to this path
+ """
+ # TODO: this function should really support multiple paths at a time
+ # TODO: We probably want to return more info that just the basic status
+ # for example, returning an identifier as to what places it is
+ # tracked, or what lock is active for the path
+ tracked_at_path = self.tracked_at([path])[path]
+ if tracked_at_path is None:
+ return 'untracked'
+ ls = self._get_lock_store()
+ assert ls is not None
+ # TODO: This is double handling. tracked_at() already had to do path =>
+ # file_id conversions to figure out what is where, we shouldn't
+ # have to do it again here
+ file_id = self._wt.path2id(tracked_at_path)
+ if file_id in ls._locking_info._active_locks:
+ return 'locked'
+ return 'tracked'
+
def is_locked(self, path):
"""Is the given path already locked?
@@ -513,6 +541,19 @@
def take_lock(self, path):
"""Take the lock for the given path."""
file_id = self._wt.path2id(path)
+ if file_id is None:
+ raise ValueError('Cannot take a lock on an unversioned path.')
+ ls = self._get_lock_store()
+ if ls is None:
+ raise ValueError('Cannot take a lock when no lock store has been'
+ ' configured')
+ if file_id not in ls._locking_info._tracked_ids:
+ # TODO: Consider giving a hint exception in the case that the user
+ # gives 'foo/bar' and 'foo' is tracked but 'foo/bar' is not
+ # We could go through the tracked_at functionality to check
+ # this
+ raise ValueError('path %s is not one of the tracked locations.')
+ ls._locking_info.create_lock(file_id)
def steal_lock(self, path):
"""There is a lock from someone else on the given path, take it."""
=== modified file 'tests/test_file_lock.py'
--- a/tests/test_file_lock.py 2009-09-23 03:10:25 +0000
+++ b/tests/test_file_lock.py 2009-09-23 04:20:11 +0000
@@ -213,7 +213,7 @@
# TODO: Currently MemoryTree doesn't provide a .bzr/checkout for us to put our
# held-lock info... :( As such, we can't use TestCaseWithMemoryTransport
-class TestFileLockManager(tests.TestCaseWithMemoryTransport):
+class TestCaseWithManager(tests.TestCaseWithMemoryTransport):
def make_tree_and_manager(self, path):
tree = self.make_branch_and_memory_tree(path)
@@ -224,7 +224,7 @@
return tree, manager
def make_simple_tree_and_manager(self, path):
- tree, manager = self.make_tree_and_manager('tree')
+ tree, manager = self.make_tree_and_manager(path)
tree.mkdir('adir', 'dir-id')
tree.add(['afile', 'adir/subfile'],
['file-id', 'subfile-id'],
@@ -233,6 +233,16 @@
tree.put_file_bytes_non_atomic('subfile-id', 'content')
return tree, manager
+ def make_dir_tracked(self, path):
+ tree, manager = self.make_simple_tree_and_manager(path)
+ manager.initialize_lock_store(self.get_transport('lock-store'))
+ manager.track_paths(['adir'])
+ return tree, manager
+
+
+
+class TestFileLockManager(TestCaseWithManager):
+
def test_already_initialized(self):
tree, manager = self.make_tree_and_manager('.')
manager.initialize_lock_store(self.get_transport('lock-store'))
@@ -363,6 +373,47 @@
['afile', 'adir', 'adir/subfile',
'adir/not-versioned', 'not-tracked']))
+ def test_take_lock_no_store(self):
+ tree, manager = self.make_simple_tree_and_manager('tree')
+ self.assertRaises(ValueError, manager.take_lock, 'adir')
+
+ def test_take_lock_not_versioned(self):
+ tree, manager = self.make_dir_tracked('tree')
+ self.assertRaises(ValueError, manager.take_lock, 'unknown')
+
+ def test_take_lock_not_tracked(self):
+ tree, manager = self.make_dir_tracked('tree')
+ self.assertRaises(ValueError, manager.take_lock, 'afile')
+
+
+class TestGetPathStatus(TestCaseWithManager):
+
+ def make_dir_locked(self):
+ tree, manager = self.make_dir_tracked('tree')
+ manager.take_lock('adir')
+ return tree, manager
+
+ def test_untracked_no_lock_store(self):
+ tree, manager = self.make_simple_tree_and_manager('tree')
+ self.assertEqual('untracked', manager.get_path_status('afile'))
+ self.assertEqual('untracked', manager.get_path_status('unknown'))
+
+ def test_untracked_outside_set(self):
+ tree, manager = self.make_dir_tracked('tree')
+ self.assertEqual('untracked', manager.get_path_status('afile'))
+ self.assertEqual('untracked', manager.get_path_status('unknown'))
+
+ def test_tracked_not_locked(self):
+ tree, manager = self.make_dir_tracked('tree')
+ self.assertEqual('tracked', manager.get_path_status('adir'))
+ self.assertEqual('tracked', manager.get_path_status('adir/subfile'))
+ self.assertEqual('tracked', manager.get_path_status('adir/unknown'))
+
+ def test_locked(self):
+ tree, manager = self.make_dir_locked()
+ self.assertEqual('locked', manager.get_path_status('adir'))
+ self.assertEqual('locked', manager.get_path_status('adir/subfile'))
+
class TestFileLockStore(tests.TestCaseWithMemoryTransport):
More information about the bazaar-commits
mailing list