Merge pull request #2124 from efiop/reflink

system: handle PurePath
This commit is contained in:
Ruslan Kuprieiev
2019-06-13 12:09:26 +03:00
committed by GitHub
7 changed files with 29 additions and 19 deletions
+2
View File
@@ -1,3 +1,5 @@
from __future__ import unicode_literals
import os
from dulwich.ignore import match_pattern, read_ignore_patterns
+4 -4
View File
@@ -10,7 +10,7 @@ from dvc.config import Config
from dvc.utils import remove, current_timestamp
from dvc.exceptions import DvcException
from dvc.utils.fs import get_mtime_and_size, get_inode
from dvc.utils.compat import fspath
from dvc.utils.compat import fspath_py35
logger = logging.getLogger(__name__)
@@ -353,7 +353,7 @@ class State(StateBase): # pylint: disable=too-many-instance-attributes
assert path_info.scheme == "local"
assert checksum is not None
path = fspath(path_info)
path = fspath_py35(path_info)
assert os.path.exists(path)
actual_mtime, actual_size = get_mtime_and_size(path)
@@ -382,7 +382,7 @@ class State(StateBase): # pylint: disable=too-many-instance-attributes
doesn't exist in the state database.
"""
assert path_info.scheme == "local"
path = fspath(path_info)
path = fspath_py35(path_info)
if not os.path.exists(path):
return None
@@ -409,7 +409,7 @@ class State(StateBase): # pylint: disable=too-many-instance-attributes
path_info (dict): path info to add to the list of links.
"""
assert path_info.scheme == "local"
path = fspath(path_info)
path = fspath_py35(path_info)
if not os.path.exists(path):
return
+17 -5
View File
@@ -1,6 +1,6 @@
from __future__ import unicode_literals
from dvc.utils.compat import str, open
from dvc.utils.compat import str, open, fspath
import os
import errno
@@ -16,6 +16,8 @@ class System(object):
import ctypes
from dvc.exceptions import DvcException
source, link_name = fspath(source), fspath(link_name)
if System.is_unix():
try:
os.link(source, link_name)
@@ -40,6 +42,8 @@ class System(object):
import ctypes
from dvc.exceptions import DvcException
source, link_name = fspath(source), fspath(link_name)
if System.is_unix():
try:
os.symlink(source, link_name)
@@ -117,6 +121,8 @@ class System(object):
import platform
from dvc.exceptions import DvcException
source, link_name = fspath(source), fspath(link_name)
system = platform.system()
try:
if system == "Windows":
@@ -134,7 +140,7 @@ class System(object):
raise DvcException("reflink is not supported")
@staticmethod
def getdirinfo(path):
def _getdirinfo(path):
import ctypes
from ctypes import c_void_p, c_wchar_p, Structure, WinError, POINTER
from ctypes.wintypes import DWORD, HANDLE, BOOL
@@ -206,6 +212,8 @@ class System(object):
@staticmethod
def inode(path):
path = fspath(path)
if System.is_unix():
import ctypes
@@ -216,7 +224,7 @@ class System(object):
inode = ctypes.c_ulong(inode).value
else:
# getdirinfo from ntfsutils works on both files and dirs
info = System.getdirinfo(path)
info = System._getdirinfo(path)
inode = abs(
hash(
(
@@ -267,6 +275,8 @@ class System(object):
@staticmethod
def is_symlink(path):
path = fspath(path)
if System.is_unix():
return os.path.islink(path)
@@ -275,14 +285,16 @@ class System(object):
from winnt import FILE_ATTRIBUTE_REPARSE_POINT
if os.path.lexists(path):
info = System.getdirinfo(path)
info = System._getdirinfo(path)
return info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT
return False
@staticmethod
def is_hardlink(path):
path = fspath(path)
if System.is_unix():
return os.stat(path).st_nlink > 1
info = System.getdirinfo(path)
info = System._getdirinfo(path)
return info.nNumberOfLinks > 1
+1 -1
View File
@@ -285,7 +285,7 @@ def dvc_walk(
def walk_files(directory, ignore_file_handler=None):
for root, _, files in dvc_walk(
str(directory), ignore_file_handler=ignore_file_handler
directory, ignore_file_handler=ignore_file_handler
):
for f in files:
yield os.path.join(root, f)
+1 -1
View File
@@ -26,7 +26,7 @@ def get_mtime_and_size(path):
mtime = stat.st_mtime
if os.path.isdir(path):
for root, dirs, files in dvc_walk(str(path)):
for root, dirs, files in dvc_walk(path):
for name in dirs + files:
entry = os.path.join(root, name)
try:
+3 -7
View File
@@ -6,7 +6,6 @@ from dvc.utils.compat import str
from dvc.state import State
from dvc.utils import file_md5
from dvc.main import main
from dvc.utils.fs import get_inode
from dvc.path_info import PathInfo
from tests.basic_env import TestDvc
@@ -58,12 +57,9 @@ class TestStateOverflow(TestDvc):
class TestGetStateRecordForInode(TestDvc):
@staticmethod
def mock_get_inode(special_path, special_value):
def mock_get_inode(inode):
def get_inode_mocked(path):
if path == special_path:
return special_value
else:
return get_inode(path)
return inode
return get_inode_mocked
@@ -75,7 +71,7 @@ class TestGetStateRecordForInode(TestDvc):
path = os.path.join(self.dvc.root_dir, self.FOO)
md5 = file_md5(path)[0]
get_inode_mock.side_effect = self.mock_get_inode(path, inode)
get_inode_mock.side_effect = self.mock_get_inode(inode)
with state:
state.save(PathInfo(path), md5)
+1 -1
View File
@@ -11,6 +11,6 @@ def test_getdirinfo(tmp_path):
fd = os.open(locked, os.O_WRONLY | os.O_CREAT | os.O_EXCL)
try:
# should not raise WinError
System.getdirinfo(locked)
System._getdirinfo(locked)
finally:
os.close(fd)