comparison mercurial/win32.py @ 35510:2062f7c2ac83

win32: implement util.getfstype() This will allow NTFS to be added to the hardlink whitelist, and resume creating hardlinks in transactions (which was disabled globally in 07a92bbd02e5; see also e5ce49a30146). I opted to report "cifs" for remote volumes because this shows in `hg debugfs`, which also reports that hardlinks are supported for these volumes. So being able to distinguish it from "unknown" seems useful. The documentation [1] seems to indicate that SMB isn't supported by these functions, but experimenting shows that mapped drives are reported as "NTFS" on Windows 7. I don't have a second Windows machine, but instead shared a temp directory on C:\. In this setup, both of the following were detected as 'cifs' with the explicit GetDriveType() check: Z:\repo>hg ci -A C:\>hg -R \\hostname\temp\repo ci -A # (without Z:\ being mapped) It looks like this is called 6 times to add and commit a single new file, so I'm a little surprised this isn't cached. [1] https://msdn.microsoft.com/en-us/library/windows/desktop/aa364993(v=vs.85).aspx
author Matt Harbison <matt_harbison@yahoo.com>
date Fri, 29 Dec 2017 21:28:19 -0500
parents d5b2beca16c0
children 5cc1becd0493
comparison
equal deleted inserted replaced
35509:beede158ea8a 35510:2062f7c2ac83
221 pass 221 pass
222 222
223 _kernel32.SetFileAttributesA.argtypes = [_LPCSTR, _DWORD] 223 _kernel32.SetFileAttributesA.argtypes = [_LPCSTR, _DWORD]
224 _kernel32.SetFileAttributesA.restype = _BOOL 224 _kernel32.SetFileAttributesA.restype = _BOOL
225 225
226 _DRIVE_UNKNOWN = 0
227 _DRIVE_NO_ROOT_DIR = 1
228 _DRIVE_REMOVABLE = 2
229 _DRIVE_FIXED = 3
230 _DRIVE_REMOTE = 4
231 _DRIVE_CDROM = 5
232 _DRIVE_RAMDISK = 6
233
234 _kernel32.GetDriveTypeA.argtypes = [_LPCSTR]
235 _kernel32.GetDriveTypeA.restype = _UINT
236
237 _kernel32.GetVolumeInformationA.argtypes = [_LPCSTR, ctypes.c_void_p, _DWORD,
238 ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p, _DWORD]
239 _kernel32.GetVolumeInformationA.restype = _BOOL
240
241 _kernel32.GetVolumePathNameA.argtypes = [_LPCSTR, ctypes.c_void_p, _DWORD]
242 _kernel32.GetVolumePathNameA.restype = _BOOL
243
226 _kernel32.OpenProcess.argtypes = [_DWORD, _BOOL, _DWORD] 244 _kernel32.OpenProcess.argtypes = [_DWORD, _BOOL, _DWORD]
227 _kernel32.OpenProcess.restype = _HANDLE 245 _kernel32.OpenProcess.restype = _HANDLE
228 246
229 _kernel32.GetExitCodeProcess.argtypes = [_HANDLE, ctypes.c_void_p] 247 _kernel32.GetExitCodeProcess.argtypes = [_HANDLE, ctypes.c_void_p]
230 _kernel32.GetExitCodeProcess.restype = _BOOL 248 _kernel32.GetExitCodeProcess.restype = _BOOL
407 if len == 0: 425 if len == 0:
408 raise ctypes.WinError() # Note: WinError is a function 426 raise ctypes.WinError() # Note: WinError is a function
409 elif len == size: 427 elif len == size:
410 raise ctypes.WinError(_ERROR_INSUFFICIENT_BUFFER) 428 raise ctypes.WinError(_ERROR_INSUFFICIENT_BUFFER)
411 return buf.value 429 return buf.value
430
431 def getfstype(path):
432 """Get the filesystem type name from a directory or file (best-effort)
433
434 Returns None if we are unsure. Raises OSError on ENOENT, EPERM, etc.
435 """
436 # realpath() calls GetFullPathName()
437 realpath = os.path.realpath(path)
438
439 size = len(realpath) + 1
440 buf = ctypes.create_string_buffer(size)
441
442 if not _kernel32.GetVolumePathNameA(realpath, ctypes.byref(buf), size):
443 raise ctypes.WinError() # Note: WinError is a function
444
445 t = _kernel32.GetDriveTypeA(buf.value)
446
447 if t == _DRIVE_REMOTE:
448 return 'cifs'
449 elif t not in (_DRIVE_REMOVABLE, _DRIVE_FIXED, _DRIVE_CDROM,
450 _DRIVE_RAMDISK):
451 return None
452
453 size = 256
454 name = ctypes.create_string_buffer(size)
455
456 if not _kernel32.GetVolumeInformationA(buf.value, None, 0, None, None, None,
457 ctypes.byref(name), size):
458 raise ctypes.WinError() # Note: WinError is a function
459
460 return name.value
412 461
413 def getuser(): 462 def getuser():
414 '''return name of current user''' 463 '''return name of current user'''
415 size = _DWORD(300) 464 size = _DWORD(300)
416 buf = ctypes.create_string_buffer(size.value + 1) 465 buf = ctypes.create_string_buffer(size.value + 1)