changeset 31575:e506e461c7a9

util: disable hardlink for copyfile if fstype is outside a whitelist Since osutil.getfstype is available, use it to detect filesystem types. The whitelist currently includes common local filesystems on Linux where they should have good hardlink support. We may add new filesystems for other platforms later.
author Jun Wu <quark@fb.com>
date Sun, 12 Mar 2017 00:23:07 -0800
parents a8e55d6f1d67
children 07f0cddb0594
files mercurial/util.py
diffstat 1 files changed, 19 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/mercurial/util.py	Tue Mar 21 17:39:49 2017 -0400
+++ b/mercurial/util.py	Sun Mar 12 00:23:07 2017 -0800
@@ -1060,6 +1060,18 @@
 # This is a variable so extensions can opt-in to using them.
 allowhardlinks = False
 
+# a whilelist of known filesystems where hardlink works reliably
+_hardlinkfswhitelist = set([
+    'btrfs',
+    'ext2',
+    'ext3',
+    'ext4',
+    'jfs',
+    'reiserfs',
+    'tmpfs',
+    'xfs',
+])
+
 def copyfile(src, dest, hardlink=False, copystat=False, checkambig=False):
     '''copy a file, preserving mode and optionally other stat info like
     atime/mtime
@@ -1076,6 +1088,13 @@
         if checkambig:
             oldstat = checkambig and filestat(dest)
         unlink(dest)
+    if hardlink:
+        # Hardlinks are problematic on CIFS (issue4546), do not allow hardlinks
+        # unless we are confident that dest is on a whitelisted filesystem.
+        destdir = os.path.dirname(dest)
+        fstype = getattr(osutil, 'getfstype', lambda x: None)(destdir)
+        if fstype not in _hardlinkfswhitelist:
+            hardlink = False
     if allowhardlinks and hardlink:
         try:
             oslink(src, dest)