diff --git a/dvc/ignore.py b/dvc/ignore.py index 141a482fa..30d86e6e5 100644 --- a/dvc/ignore.py +++ b/dvc/ignore.py @@ -11,7 +11,6 @@ from dvc.fs.base import BaseFileSystem from dvc.path_info import PathInfo from dvc.pathspec_math import PatternInfo, merge_patterns from dvc.scheme import Schemes -from dvc.system import System from dvc.types import AnyPath, List, Optional from dvc.utils import relpath from dvc.utils.collections import PathStringTrie @@ -84,7 +83,7 @@ class DvcIgnorePatterns(DvcIgnore): else: return False - if not System.is_unix(): + if os.name == "nt": path = normalize_file(path) return path diff --git a/dvc/system.py b/dvc/system.py index a7c27f62b..96a2aea26 100644 --- a/dvc/system.py +++ b/dvc/system.py @@ -22,10 +22,6 @@ if ( class System: - @staticmethod - def is_unix(): - return os.name != "nt" - @staticmethod def hardlink(source, link_name): try: @@ -117,99 +113,14 @@ class System: # so we need to chmod it to look like a normal copy. os.chmod(link_name, 0o666 & ~umask) - @staticmethod - def _getdirinfo(path): - from collections import namedtuple - - from win32file import ( # pylint: disable=import-error - FILE_FLAG_BACKUP_SEMANTICS, - FILE_FLAG_OPEN_REPARSE_POINT, - FILE_SHARE_READ, - OPEN_EXISTING, - CreateFileW, - GetFileInformationByHandle, - ) - - # NOTE: use FILE_FLAG_OPEN_REPARSE_POINT to open symlink itself and not - # the target See https://docs.microsoft.com/en-us/windows/desktop/api/ - # fileapi/nf-fileapi-createfilew#symbolic-link-behavior - flags = FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT - - hfile = CreateFileW( - path, 0, FILE_SHARE_READ, None, OPEN_EXISTING, flags, None - ) - - # See BY_HANDLE_FILE_INFORMATION structure from fileapi.h - Info = namedtuple( - "BY_HANDLE_FILE_INFORMATION", - [ - "dwFileAttributes", - "ftCreationTime", - "ftLastAccessTime", - "ftLastWriteTime", - "dwVolumeSerialNumber", - "nFileSizeHigh", - "nFileSizeLow", - "nNumberOfLinks", - "nFileIndexHigh", - "nFileIndexLow", - ], - ) - - return Info(*GetFileInformationByHandle(hfile)) - @staticmethod def inode(path): - path = os.fspath(path) - - if System.is_unix(): - import ctypes - - inode = os.lstat(path).st_ino - # NOTE: See https://bugs.python.org/issue29619 and - # https://stackoverflow.com/questions/34643289/ - # pythons-os-stat-is-returning-wrong-inode-value - inode = ctypes.c_ulong(inode).value - else: - # getdirinfo from ntfsutils works on both files and dirs - info = System._getdirinfo(path) - inode = abs( - hash( - ( - info.dwVolumeSerialNumber, - info.nFileIndexHigh, - info.nFileIndexLow, - ) - ) - ) - assert inode >= 0 - assert inode < 2 ** 64 - return inode + return os.lstat(path).st_ino @staticmethod def is_symlink(path): - path = os.fspath(path) - - if System.is_unix(): - return os.path.islink(path) - - # https://docs.microsoft.com/en-us/windows/desktop/fileio/ - # file-attribute-constants - from winnt import ( # pylint: disable=import-error - FILE_ATTRIBUTE_REPARSE_POINT, - ) - - if os.path.lexists(path): - info = System._getdirinfo(path) - return info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT - return False + return os.path.islink(path) @staticmethod def is_hardlink(path): - path = os.fspath(path) - - if System.is_unix(): - return os.stat(path).st_nlink > 1 - - info = System._getdirinfo(path) - return info.nNumberOfLinks > 1 + return os.stat(path).st_nlink > 1 diff --git a/requirements/default.txt b/requirements/default.txt index b97a691a8..c76757bf5 100644 --- a/requirements/default.txt +++ b/requirements/default.txt @@ -24,7 +24,6 @@ packaging>=19.0 zc.lockfile>=1.2.1 flufl.lock>=3.2,<4 win-unicode-console>=0.5; sys_platform == 'win32' -pywin32>=225; sys_platform == 'win32' and python_version < '3.10' networkx>=2.5 psutil>=5.8.0 pydot>=1.2.4 diff --git a/requirements/tests.txt b/requirements/tests.txt index 155f54a5e..17915135a 100644 --- a/requirements/tests.txt +++ b/requirements/tests.txt @@ -21,6 +21,7 @@ google-compute-engine==2.8.13 google-cloud-storage==1.42.1 urllib3==1.26.6 dvclive>=0.2.1 +pywin32>=225; sys_platform == 'win32' and python_version < '3.10' # required by collective.checkdocs Pygments==2.10.0 diff --git a/scripts/pyinstaller/hooks/hook-win32file.py b/scripts/pyinstaller/hooks/hook-win32file.py deleted file mode 100644 index daee85e09..000000000 --- a/scripts/pyinstaller/hooks/hook-win32file.py +++ /dev/null @@ -1 +0,0 @@ -hiddenimports = ["win32timezone"] diff --git a/tests/func/test_system.py b/tests/func/test_system.py deleted file mode 100644 index 12c42b6d1..000000000 --- a/tests/func/test_system.py +++ /dev/null @@ -1,17 +0,0 @@ -import os - -import pytest - -from dvc.system import System - - -@pytest.mark.skipif(os.name != "nt", reason="Windows specific") -def test_getdirinfo(tmp_path): - # simulate someone holding an exclusive access - locked = str(tmp_path / "locked") - fd = os.open(locked, os.O_WRONLY | os.O_CREAT | os.O_EXCL) - try: - # should not raise WinError - System._getdirinfo(locked) - finally: - os.close(fd)