[PATCH V2] util: move checknlink away from the dependency of a hard-coded filename
ttung at fb.com
ttung at fb.com
Wed Aug 24 18:18:02 UTC 2016
# HG changeset patch
# User Tony Tung <tonytung at merly.org>
# Date 1472062675 25200
# Wed Aug 24 11:17:55 2016 -0700
# Node ID e062df885ace82e0aeea19d93c80dd3911078c41
# Parent 2efc5a05d80a6d4253767f2ce0c2fb062ba83cb6
util: move checknlink away from the dependency of a hard-coded filename
This somewhat insulates us against bugs in checknlink when a stale file
left behind could result in checknlink always returning False.
diff --git a/mercurial/util.py b/mercurial/util.py
--- a/mercurial/util.py
+++ b/mercurial/util.py
@@ -1305,38 +1305,54 @@
def checknlink(testfile):
'''check whether hardlink count reporting works properly'''
- # testfile may be open, so we need a separate file for checking to
- # work around issue2543 (or testfile may get lost on Samba shares)
- f1 = testfile + ".hgtmp1"
- if os.path.lexists(f1):
- return False
+ f1 = {}
+ f2 = {}
+
try:
- posixfile(f1, 'w').close()
- except IOError:
+ dirpath, filename = os.path.split(testfile)
+
+ # testfile may be open, so we need a separate file for checking to
+ # work around issue2543 (or testfile may get lost on Samba shares)
+ f1['fd'], f1['path'] = tempfile.mkstemp(prefix=filename, dir=dirpath)
+ os.close(f1['fd'])
+ del f1['fd']
+
+ f2['fd'], f2['path'] = tempfile.mkstemp(prefix=filename, dir=dirpath)
+ os.close(f2['fd'])
+ del f2['fd']
+
+ # there's a small race condition that another file can jam itself in
+ # between the time we remove f2 and the time we create the hard link.
+ # in the unlikely scenario that happens, we'll treat it as nlink being
+ # unreliable.
try:
- os.unlink(f1)
+ os.unlink(f2['path'])
+ oslink(f1['path'], f2['path'])
+ # nlinks() may behave differently for files on Windows shares if
+ # the file is open.
+ f2['handle'] = posixfile(f2['path'])
+ return nlinks(f2['path']) > 1
except OSError:
- pass
- return False
-
- f2 = testfile + ".hgtmp2"
- fd = None
- try:
- oslink(f1, f2)
- # nlinks() may behave differently for files on Windows shares if
- # the file is open.
- fd = posixfile(f2)
- return nlinks(f2) > 1
- except OSError:
- return False
+ return False
finally:
- if fd is not None:
- fd.close()
- for f in (f1, f2):
- try:
- os.unlink(f)
- except OSError:
- pass
+ for fi in (f1, f2):
+ if 'path' in fi:
+ try:
+ os.unlink(fi['path'])
+ except OSError:
+ pass
+
+ if 'fd' in fi:
+ try:
+ os.close(fi['fd'])
+ except OSError:
+ pass
+
+ if 'handle' in fi:
+ try:
+ fi['handle'].close()
+ except OSError:
+ pass
def endswithsep(path):
'''Check path ends with os.sep or os.altsep.'''
More information about the Mercurial-devel
mailing list