Submitter | Matt Harbison |
---|---|
Date | Dec. 31, 2017, 4:11 a.m. |
Message ID | <5b4803673e98e26e1d80.1514693469@Envy> |
Download | mbox | patch |
Permalink | /patch/26509/ |
State | Accepted |
Headers | show |
Comments
On Sat, 30 Dec 2017 23:11:09 -0500, Matt Harbison wrote: > # HG changeset patch > # User Matt Harbison <matt_harbison@yahoo.com> > # Date 1514600899 18000 > # Fri Dec 29 21:28:19 2017 -0500 > # Node ID 5b4803673e98e26e1d80254b8ac3bab5ebc5bac7 > # Parent beede158ea8a740efb59b46522f74490381a2086 > win32: implement util.getfstype() Queued the series, thanks. > + size = len(realpath) + 1 > + buf = ctypes.create_string_buffer(size) > + > + if not _kernel32.GetVolumePathNameA(realpath, ctypes.byref(buf), size): No idea why, but "hg debugfsinfo --cwd '/z/'" failed on WinXP saying something like "more data available." Windows bug? > --- a/mercurial/windows.py > +++ b/mercurial/windows.py > @@ -231,7 +231,7 @@ > > Returns None if we are unsure. Raises OSError on ENOENT, EPERM, etc. > ''' > - return None > + return win32.getfstype(dirpath) Changed this to getfstype = win32.getfstype.
On Sun, 31 Dec 2017 03:54:18 -0500, Yuya Nishihara <yuya@tcha.org> wrote: > On Sat, 30 Dec 2017 23:11:09 -0500, Matt Harbison wrote: >> # HG changeset patch >> # User Matt Harbison <matt_harbison@yahoo.com> >> # Date 1514600899 18000 >> # Fri Dec 29 21:28:19 2017 -0500 >> # Node ID 5b4803673e98e26e1d80254b8ac3bab5ebc5bac7 >> # Parent beede158ea8a740efb59b46522f74490381a2086 >> win32: implement util.getfstype() > > Queued the series, thanks. > >> + size = len(realpath) + 1 >> + buf = ctypes.create_string_buffer(size) >> + >> + if not _kernel32.GetVolumePathNameA(realpath, ctypes.byref(buf), >> size): > > No idea why, but "hg debugfsinfo --cwd '/z/'" failed on WinXP saying > something > like "more data available." Windows bug? Odd. I noticed different misbehavior on Win7 yesterday when trying to `cd /z/`, but can't explain it either. $ ../hg debugfsinfo --cwd '/z/' abort: The system cannot find the file specified: 'C:/MinGW/msys/1.0/z/' $ df -h Filesystem Size Used Avail Use% Mounted on C:\Users\Matt\AppData\Local\Temp 435G 386G 50G 89% /tmp C:\MinGW\msys\1.0 435G 386G 50G 89% /usr C:\MinGW\msys\1.0 435G 386G 50G 89% / C:\MinGW 435G 386G 50G 89% /mingw c: 435G 386G 50G 89% /c d: 31G 27G 4.6G 86% /d z: 435G 386G 50G 89% z (Not sure why it is mounted on 'z', not '/z' here) $ mkdir /z $ ../hg debugfsinfo --cwd '/z/' path: . mounted on: C:\ exec: no fstype: NTFS symlink: no hardlink: yes case-sensitive: no I guess falling back to C:\ makes sense, since nothing seems to actually be mounted on z here. `mkdir /z` prior to mapping the share made no difference. $ ../hg debugfsinfo --cwd 'z:\' path: . mounted on: z:\ exec: no fstype: cifs symlink: no hardlink: yes case-sensitive: no
Patch
diff --git a/mercurial/win32.py b/mercurial/win32.py --- a/mercurial/win32.py +++ b/mercurial/win32.py @@ -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) diff --git a/mercurial/windows.py b/mercurial/windows.py --- a/mercurial/windows.py +++ b/mercurial/windows.py @@ -231,7 +231,7 @@ Returns None if we are unsure. Raises OSError on ENOENT, EPERM, etc. ''' - return None + return win32.getfstype(dirpath) def setbinary(fd): # When run without console, pipes may expose invalid