Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitac9ac55

Browse files
authored
Merge pull request#513 from expobrain/master
Use flock() for file locking
2 parents4e5ef73 +20b4f49 commitac9ac55

File tree

6 files changed

+81
-9
lines changed

6 files changed

+81
-9
lines changed

‎.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,4 @@ nbproject
1414
.DS_Store
1515
/*egg-info
1616
/.tox
17+
.cache

‎AUTHORS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,5 +15,6 @@ Contributors are:
1515
-Jonathan Chu <jonathan.chu _at_ me.com>
1616
-Vincent Driessen <me _at_ nvie.com>
1717
-Phil Elson <pelson _dot_ pub _at_ gmail.com>
18+
-Daniele Esposti <daniele.esposti _at_ gmail.com>
1819

1920
Portions derived from other open source works and are clearly marked.

‎git/test/test_util.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
# the BSD License: http://www.opensource.org/licenses/bsd-license.php
66

77
importtempfile
8+
importgc
89

910
fromgit.test.libimport (
1011
TestBase,
@@ -80,6 +81,7 @@ def test_lock_file(self):
8081

8182
# auto-release on destruction
8283
del(other_lock_file)
84+
gc.collect()
8385
lock_file._obtain_lock_or_raise()
8486
lock_file._release_lock()
8587

‎git/util.py

Lines changed: 68 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,56 @@
4848

4949
#{ Utility Methods
5050

51+
ifplatform.system()=='Windows':
52+
# This code is a derivative work of Portalocker http://code.activestate.com/recipes/65203/
53+
importwin32con
54+
importwin32file
55+
importpywintypes
56+
57+
LOCK_EX=win32con.LOCKFILE_EXCLUSIVE_LOCK
58+
LOCK_SH=0# the default
59+
LOCK_NB=win32con.LOCKFILE_FAIL_IMMEDIATELY
60+
LOCK_UN=1<<2
61+
62+
__overlapped=pywintypes.OVERLAPPED()
63+
64+
defflock(fd,flags=0):
65+
hfile=win32file._get_osfhandle(fd)
66+
67+
ifflags&LOCK_UN!=0:
68+
# Unlock file descriptor
69+
try:
70+
win32file.UnlockFileEx(hfile,0,-0x10000,__overlapped)
71+
exceptpywintypes.errorasexc_value:
72+
# error: (158, 'UnlockFileEx', 'The segment is already unlocked.')
73+
# To match the 'posix' implementation, silently ignore this error
74+
ifexc_value[0]==158:
75+
pass
76+
else:
77+
# Q: Are there exceptions/codes we should be dealing with here?
78+
raise
79+
80+
elifflags&LOCK_EX!=0:
81+
# Lock file
82+
try:
83+
win32file.LockFileEx(hfile,flags,0,-0x10000,__overlapped)
84+
exceptpywintypes.errorasexc_value:
85+
ifexc_value[0]==33:
86+
# error: (33, 'LockFileEx',
87+
# 'The process cannot access the file because another process has locked
88+
# a portion of the file.')
89+
raiseIOError(33,exc_value[2])
90+
else:
91+
# Q: Are there exceptions/codes we should be dealing with here?
92+
raise
93+
94+
else:
95+
raiseNotImplementedError("Unsupported set of bitflags {}".format(bin(flags)))
96+
97+
98+
else:
99+
fromfcntlimportflock,LOCK_UN,LOCK_EX,LOCK_NB
100+
51101

52102
defunbare_repo(func):
53103
"""Methods with this decorator raise InvalidGitRepositoryError if they
@@ -555,9 +605,10 @@ class LockFile(object):
555605
As we are a utility class to be derived from, we only use protected methods.
556606
557607
Locks will automatically be released on destruction"""
558-
__slots__= ("_file_path","_owns_lock")
608+
__slots__= ("_file_path","_owns_lock","_file_descriptor")
559609

560610
def__init__(self,file_path):
611+
self._file_descriptor=None
561612
self._file_path=file_path
562613
self._owns_lock=False
563614

@@ -579,20 +630,21 @@ def _obtain_lock_or_raise(self):
579630
:raise IOError: if a lock was already present or a lock file could not be written"""
580631
ifself._has_lock():
581632
return
633+
582634
lock_file=self._lock_file_path()
583-
ifos.path.isfile(lock_file):
584-
raiseIOError("Lock for file %r did already exist, delete %r in case the lock is illegal"%
585-
(self._file_path,lock_file))
586635

636+
# Create file and lock
587637
try:
588-
flags=os.O_WRONLY|os.O_CREAT|os.O_EXCL
638+
flags=os.O_CREAT
589639
ifis_win:
590640
flags|=os.O_SHORT_LIVED
591641
fd=os.open(lock_file,flags,0)
592-
os.close(fd)
593642
exceptOSErrorase:
594643
raiseIOError(str(e))
595644

645+
flock(fd,LOCK_EX|LOCK_NB)
646+
647+
self._file_descriptor=fd
596648
self._owns_lock=True
597649

598650
def_obtain_lock(self):
@@ -605,14 +657,21 @@ def _release_lock(self):
605657
ifnotself._has_lock():
606658
return
607659

660+
fd=self._file_descriptor
661+
lock_file=self._lock_file_path()
662+
663+
flock(fd,LOCK_UN)
664+
os.close(fd)
665+
608666
# if someone removed our file beforhand, lets just flag this issue
609667
# instead of failing, to make it more usable.
610-
lfp=self._lock_file_path()
611668
try:
612-
rmfile(lfp)
669+
rmfile(lock_file)
613670
exceptOSError:
614671
pass
672+
615673
self._owns_lock=False
674+
self._file_descriptor=None
616675

617676

618677
classBlockingLockFile(LockFile):
@@ -647,7 +706,7 @@ def _obtain_lock(self):
647706
try:
648707
super(BlockingLockFile,self)._obtain_lock()
649708
exceptIOError:
650-
#synity check: if the directory leading to the lockfile is not
709+
#sanity check: if the directory leading to the lockfile is not
651710
# readable anymore, raise an execption
652711
curtime=time.time()
653712
ifnotos.path.isdir(os.path.dirname(self._lock_file_path())):

‎setup.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
importlogging
1414
importos
1515
importsys
16+
importplatform
1617
fromosimportpath
1718

1819
withopen(path.join(path.dirname(__file__),'VERSION'))asv:
@@ -21,6 +22,10 @@
2122
withopen('requirements.txt')asreqs_file:
2223
requirements=reqs_file.read().splitlines()
2324

25+
ifplatform.system()=='Windows':
26+
withopen('win32-requirements.txt')asreqs_file:
27+
requirements+=reqs_file.read().splitlines()
28+
2429

2530
classbuild_py(_build_py):
2631

@@ -65,6 +70,8 @@ def _stamp_version(filename):
6570
print("WARNING: Couldn't find version line in file %s"%filename,file=sys.stderr)
6671

6772
install_requires= ['gitdb >= 0.6.4']
73+
ifplatform.system()=='Windows':
74+
install_requires.append("pypiwin32 >= 219")
6875
extras_require= {
6976
':python_version == "2.6"': ['ordereddict'],
7077
}

‎win32-requirements.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
-r requirements.txt
2+
pypiwin32 >= 219

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp