Mercurial > hg
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) |