Summary:
The goal of this diff is to introduce a central place for all logic related
to parsing and handling the contents of the lock files. The current state of
things is hard to manage and even harder to extend.
NB: the stack is not complete, the changes that actually use this refactoring are yet to come.
Reviewed By: quark-zju
Differential Revision: D7489326
fbshipit-source-id: aa79d964411e3f5b61e24aa9babece05d4f0bd60
Support for using unittest.TestCase.assertRaises as a context
manager was added in Python 2.7. This form is more readable,
especially for complex tests.
While I was here, I also restored the use of assertRaisesRegexp,
which was removed in 6620b26511eb for Python 2.6 compatibility.
Acquiring lock by vfs.makelock() and getting lock holder (aka
"locker") information by vfs.readlock() aren't atomic action.
Therefore, failure of the former doesn't ensure success of the latter.
Before this patch, lock is unintentionally acquired, if ENOENT
causes failure of vfs.readlock() while 5 times retrying, because
lock._trylock() returns to caller silently after retrying, and
lock.lock() assumes that lock._trylock() returns successfully only if
lock is acquired.
In this case, lock symlink (or file) isn't created, even though lock
is treated as acquired in memory.
To avoid this issue, this patch makes lock._trylock() raise
LockHeld(EAGAIN) at the end of it, if lock isn't acquired while
retrying.
An empty "locker" meaning "busy for frequent lock/unlock by many
processes" might appear in an abortion message, if lock acquisition
fails. Therefore, this patch also does:
- use '%r' to increase visibility of "locker", even if it is empty
- show hint message to explain what empty "locker" means
Now that the 'vfs' classes moved in their own module, lets use the new module
directly. We update code iteratively to help with possible bisect needs in the
future.
Review feedback from Pierre-Yves David. A separate line of work is working to
ensure that dirstate writes are written to a separate 'pending' file while a
transaction is active. Lock inheritance currently conflicts with that, so dodge
the issue by simply preventing inheritance while a transaction is running.
Custom merge drivers aren't going to run inside a transaction, so this doesn't
affect that.
We want to prevent locks from being inherited sometimes (e.g. when there's a
currently running transaction, which will break a lot of assumptions we're
making in here.)
Review feedback from Pierre-Yves David. This makes the overall code cleaner and
less error-prone, and makes a previously explicitly checked error state
impossible.
This is part of a series that will allow locks to be inherited by subprocesses
in limited circumstances. This patch enables the logic introduced in previous
patches.
The earlier test worked only because the held count went up to 2, so the first
release brought it down to 1. Making a copy of the lock fixes that issue.