diff -r beede158ea8a -r 2062f7c2ac83 mercurial/win32.py --- a/mercurial/win32.py Sat Dec 30 21:07:03 2017 -0500 +++ b/mercurial/win32.py Fri Dec 29 21:28:19 2017 -0500 @@ -223,6 +223,24 @@ _kernel32.SetFileAttributesA.argtypes = [_LPCSTR, _DWORD] _kernel32.SetFileAttributesA.restype = _BOOL +_DRIVE_UNKNOWN = 0 +_DRIVE_NO_ROOT_DIR = 1 +_DRIVE_REMOVABLE = 2 +_DRIVE_FIXED = 3 +_DRIVE_REMOTE = 4 +_DRIVE_CDROM = 5 +_DRIVE_RAMDISK = 6 + +_kernel32.GetDriveTypeA.argtypes = [_LPCSTR] +_kernel32.GetDriveTypeA.restype = _UINT + +_kernel32.GetVolumeInformationA.argtypes = [_LPCSTR, ctypes.c_void_p, _DWORD, + ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p, _DWORD] +_kernel32.GetVolumeInformationA.restype = _BOOL + +_kernel32.GetVolumePathNameA.argtypes = [_LPCSTR, ctypes.c_void_p, _DWORD] +_kernel32.GetVolumePathNameA.restype = _BOOL + _kernel32.OpenProcess.argtypes = [_DWORD, _BOOL, _DWORD] _kernel32.OpenProcess.restype = _HANDLE @@ -410,6 +428,37 @@ raise ctypes.WinError(_ERROR_INSUFFICIENT_BUFFER) return buf.value +def getfstype(path): + """Get the filesystem type name from a directory or file (best-effort) + + Returns None if we are unsure. Raises OSError on ENOENT, EPERM, etc. + """ + # realpath() calls GetFullPathName() + realpath = os.path.realpath(path) + + size = len(realpath) + 1 + buf = ctypes.create_string_buffer(size) + + if not _kernel32.GetVolumePathNameA(realpath, ctypes.byref(buf), size): + raise ctypes.WinError() # Note: WinError is a function + + t = _kernel32.GetDriveTypeA(buf.value) + + if t == _DRIVE_REMOTE: + return 'cifs' + elif t not in (_DRIVE_REMOVABLE, _DRIVE_FIXED, _DRIVE_CDROM, + _DRIVE_RAMDISK): + return None + + size = 256 + name = ctypes.create_string_buffer(size) + + if not _kernel32.GetVolumeInformationA(buf.value, None, 0, None, None, None, + ctypes.byref(name), size): + raise ctypes.WinError() # Note: WinError is a function + + return name.value + def getuser(): '''return name of current user''' size = _DWORD(300)