From 11f7eb0c4ea01166ca3e54da7e8aa7409eab3a34 Mon Sep 17 00:00:00 2001 From: Ruslan Kuprieiev Date: Sun, 17 Jun 2018 18:51:03 +0300 Subject: [PATCH] system: add temporary workaround for getdirinfo() issue Fixes #670 Signed-off-by: Ruslan Kuprieiev --- dvc/system.py | 21 ++++++++++++++++++++- tests/test_system.py | 19 +++++++++++++++++++ 2 files changed, 39 insertions(+), 1 deletion(-) create mode 100644 tests/test_system.py diff --git a/dvc/system.py b/dvc/system.py index 622e287b6..09c1b285e 100644 --- a/dvc/system.py +++ b/dvc/system.py @@ -39,11 +39,30 @@ class System(object): def reflink(source, link_name): return reflink.reflink(source, link_name) + # FIXME + # Temporary fix while waiting for the PR to be merged and released: + # https://github.com/sunshowers/ntfs/pull/11 + @staticmethod + def getdirinfo(path): + from ntfsutils.fs import FILE_FLAG_BACKUP_SEMANTICS, FILE_SHARE_READ, OPEN_EXISTING + from ntfsutils.fs import CreateFile, WinError, BY_HANDLE_FILE_INFORMATION + from ntfsutils.fs import GetFileInformationByHandle, CloseHandle + flags = FILE_FLAG_BACKUP_SEMANTICS + hfile = CreateFile(path, 0, FILE_SHARE_READ, None, OPEN_EXISTING, flags, None) + if hfile is None: + raise WinError() + info = BY_HANDLE_FILE_INFORMATION() + rv = GetFileInformationByHandle(hfile, info) + CloseHandle(hfile) + if rv == 0: + raise WinError() + return info + @staticmethod def inode(path): if System.is_unix(): return os.stat(path).st_ino # getdirinfo from ntfsutils works on both files and dirs - info = getdirinfo(path) + info = System.getdirinfo(path) return hash((info.dwVolumeSerialNumber, info.nFileIndexHigh, info.nFileIndexLow)) diff --git a/tests/test_system.py b/tests/test_system.py new file mode 100644 index 000000000..3a56bfc3a --- /dev/null +++ b/tests/test_system.py @@ -0,0 +1,19 @@ +import os + +from dvc.system import System +from tests.basic_env import TestDir + + +class TestSystem(TestDir): + def test_getdirinfo(self): + if os.name != 'nt': + return + + # simulate someone holding an exclussive access + locked = 'locked' + fd = os.open(locked, os.O_WRONLY | os.O_CREAT | os.O_EXCL) + + # should not raise WinError + info = System.getdirinfo(locked) + + os.close(fd)