comparison mercurial/util.py @ 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 55c6788c54e2
children e7a02e9ad162
comparison
equal deleted inserted replaced
31574:a8e55d6f1d67 31575:e506e461c7a9
1058 # Hardlinks are problematic on CIFS, do not allow hardlinks 1058 # Hardlinks are problematic on CIFS, do not allow hardlinks
1059 # until we find a way to work around it cleanly (issue4546). 1059 # until we find a way to work around it cleanly (issue4546).
1060 # This is a variable so extensions can opt-in to using them. 1060 # This is a variable so extensions can opt-in to using them.
1061 allowhardlinks = False 1061 allowhardlinks = False
1062 1062
1063 # a whilelist of known filesystems where hardlink works reliably
1064 _hardlinkfswhitelist = set([
1065 'btrfs',
1066 'ext2',
1067 'ext3',
1068 'ext4',
1069 'jfs',
1070 'reiserfs',
1071 'tmpfs',
1072 'xfs',
1073 ])
1074
1063 def copyfile(src, dest, hardlink=False, copystat=False, checkambig=False): 1075 def copyfile(src, dest, hardlink=False, copystat=False, checkambig=False):
1064 '''copy a file, preserving mode and optionally other stat info like 1076 '''copy a file, preserving mode and optionally other stat info like
1065 atime/mtime 1077 atime/mtime
1066 1078
1067 checkambig argument is used with filestat, and is useful only if 1079 checkambig argument is used with filestat, and is useful only if
1074 oldstat = None 1086 oldstat = None
1075 if os.path.lexists(dest): 1087 if os.path.lexists(dest):
1076 if checkambig: 1088 if checkambig:
1077 oldstat = checkambig and filestat(dest) 1089 oldstat = checkambig and filestat(dest)
1078 unlink(dest) 1090 unlink(dest)
1091 if hardlink:
1092 # Hardlinks are problematic on CIFS (issue4546), do not allow hardlinks
1093 # unless we are confident that dest is on a whitelisted filesystem.
1094 destdir = os.path.dirname(dest)
1095 fstype = getattr(osutil, 'getfstype', lambda x: None)(destdir)
1096 if fstype not in _hardlinkfswhitelist:
1097 hardlink = False
1079 if allowhardlinks and hardlink: 1098 if allowhardlinks and hardlink:
1080 try: 1099 try:
1081 oslink(src, dest) 1100 oslink(src, dest)
1082 return 1101 return
1083 except (IOError, OSError): 1102 except (IOError, OSError):