[PATCH 5 of 5 rfc] posix: give checklink a fast path that cache the check file and is read only
Mads Kiilerich
mads at kiilerich.com
Sat Oct 24 11:32:03 CDT 2015
# HG changeset patch
# User Mads Kiilerich <madski at unity3d.com>
# Date 1421194526 -3600
# Wed Jan 14 01:15:26 2015 +0100
# Branch stable
# Node ID 77319eeabd529382868e4e48e695c4b5ea909124
# Parent 3a6d970e2d2f86b51b6ad0223a4da1a3a3e19bc9
posix: give checklink a fast path that cache the check file and is read only
util.checklink would create a symlink and remove it again. That would sometimes
happen multiple times. Write operations are relatively expensive and give disk
tear and noise for applications monitoring file system activity.
Instead of creating a symlink and deleting it again, just create it once and
leave it in .hg/cache/check-link . If the file exists, just verify that
os.islink reports true.
The symlink left in .hg/cache has to resolve to a file - otherwise 'make dist'
will fail ...
test-symlink-os-yes-fs-no.py does some monkey patching to simulate a platform
without symlink support. The slightly different testing method requires
additional monkeying.
diff --git a/mercurial/posix.py b/mercurial/posix.py
--- a/mercurial/posix.py
+++ b/mercurial/posix.py
@@ -215,6 +215,10 @@ def checklink(path):
# mktemp is not racy because symlink creation will fail if the
# file already exists
cachedir = os.path.join(path, '.hg', 'cache')
+ checklink = os.path.join(cachedir, 'checklink')
+ # try fast path, read only
+ if os.path.islink(checklink):
+ return True
if os.path.isdir(cachedir):
checkdir = cachedir
else:
@@ -225,7 +229,13 @@ def checklink(path):
fd = tempfile.NamedTemporaryFile(dir=checkdir, prefix='hg-checklink-')
try:
os.symlink(os.path.basename(fd.name), name)
- os.unlink(name)
+ if cachedir is None:
+ os.unlink(name)
+ else:
+ try:
+ os.rename(name, checklink)
+ except OSError:
+ os.unlink(name)
return True
finally:
fd.close()
diff --git a/tests/test-clone.t b/tests/test-clone.t
--- a/tests/test-clone.t
+++ b/tests/test-clone.t
@@ -32,6 +32,7 @@ Trigger branchcache creation:
$ ls .hg/cache
branch2-served
checkisexec
+ checklink
checknoexec
rbc-names-v1
rbc-revs-v1
@@ -48,6 +49,7 @@ Ensure branchcache got copied over:
$ ls .hg/cache
branch2-served
checkisexec
+ checklink
$ cat a
a
diff --git a/tests/test-symlink-os-yes-fs-no.py b/tests/test-symlink-os-yes-fs-no.py
--- a/tests/test-symlink-os-yes-fs-no.py
+++ b/tests/test-symlink-os-yes-fs-no.py
@@ -26,6 +26,9 @@ commands.status(u, repo)
def symlink_failure(src, dst):
raise OSError(1, "Operation not permitted")
os.symlink = symlink_failure
+def islink_failure(path):
+ return False
+os.path.islink = islink_failure
# dereference links as if a Samba server has exported this to a
# Windows client
diff --git a/tests/test-tags.t b/tests/test-tags.t
--- a/tests/test-tags.t
+++ b/tests/test-tags.t
@@ -666,6 +666,7 @@ Missing tags2* files means the cache was
$ ls tagsclient/.hg/cache
branch2-served
checkisexec
+ checklink
hgtagsfnodes1
rbc-names-v1
rbc-revs-v1
@@ -691,6 +692,7 @@ Running hg tags should produce tags2* fi
$ ls tagsclient/.hg/cache
branch2-served
checkisexec
+ checklink
hgtagsfnodes1
rbc-names-v1
rbc-revs-v1
More information about the Mercurial-devel
mailing list