|
21 | 21 |
|
22 | 22 | from errors import GitCommandError
|
23 | 23 | from git.objects import Blob, Tree, Object, Commit
|
24 |
| -from git.utils import SHA1Writer, LazyMixin, ConcurrentWriteOperation, join_path_native |
| 24 | +from git.utils import SHA1Writer, LazyMixin, ConcurrentWriteOperation, join_path_native, BlockingLockFile |
25 | 25 |
|
26 | 26 |
|
27 | 27 | class CheckoutError( Exception ):
|
@@ -70,6 +70,38 @@ def __del__(self):
|
70 | 70 | os.rename(self.tmp_file_path, self.file_path)
|
71 | 71 | # END temp file exists
|
72 | 72 |
|
| 73 | +class IndexLock(BlockingLockFile): |
| 74 | + """Specialized lock that will wait for the index to be locked and immediately |
| 75 | + move the lock out of the way. This allows a git command to take the lock |
| 76 | + which has to follow right after the lock() call. |
| 77 | + |
| 78 | + Right before the lock is released, we will move our original lock back into place. |
| 79 | + This lock should be used to gain fine-grained control over multiple processes |
| 80 | + or threads that try to manipulate the index and would otherwise fail. |
| 81 | + Using this lock, these will wait for each other. |
| 82 | + |
| 83 | + NOTE: |
| 84 | + There is still a small chance that git will fail as file system |
| 85 | + operations take time as well. |
| 86 | + """ |
| 87 | + __slots__ = '_tmp_file_path' |
| 88 | + |
| 89 | + def _obtain_lock_or_raise(self): |
| 90 | + super(IndexLock, self)._obtain_lock_or_raise() |
| 91 | + self._tmp_file_path = self._lock_file_path() + tempfile.mktemp('','','') |
| 92 | + # rename lock we aquired to move it out of the way |
| 93 | + os.rename(self._lock_file_path(), self._tmp_file_path) |
| 94 | + |
| 95 | + def _release_lock(self): |
| 96 | + # move our lock back into place |
| 97 | + if hasattr(self, '_tmp_file_path') and os.path.isfile(self._tmp_file_path): |
| 98 | + lock_file = self._lock_file_path() |
| 99 | + if os.name == 'nt' and os.path.exists(lock_file): |
| 100 | + os.remove(lock_file) |
| 101 | + os.rename(self._tmp_file_path, lock_file) |
| 102 | + # END temp file exists |
| 103 | + super(IndexLock, self)._release_lock() |
| 104 | + |
73 | 105 | class BlobFilter(object):
|
74 | 106 | """
|
75 | 107 | Predicate to be used by iter_blobs allowing to filter only return blobs which
|
|
0 commit comments