Skip to content

Commit

Permalink
system: use linkat instead of link
Browse files Browse the repository at this point in the history
`os.link` is broken across platforms when dealing with symlinks.

See https://bugs.python.org/issue41355 for more info.
  • Loading branch information
efiop committed Oct 27, 2021
1 parent 41aee9a commit 874acec
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 2 deletions.
30 changes: 29 additions & 1 deletion dvc/system.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,42 @@
import logging
import os
import platform
import stat
import sys

logger = logging.getLogger(__name__)


if os.name == "nt" and sys.version_info < (3, 8):
# NOTE: using backports for `os.path.realpath`
# See https://bugs.python.org/issue9949 for more info.
# pylint: disable=import-error, no-name-in-module
from jaraco.windows.filesystem.backports import realpath as _realpath

def realpath(path):
return _realpath(os.fspath(path))


else:
realpath = os.path.realpath


class System:
@staticmethod
def hardlink(source, link_name):
os.link(source, link_name)
# NOTE: we should really be using `os.link()` here with
# `follow_symlinks=True`, but unfortunately the implementation is
# buggy across platforms, so until it is fixed, we just dereference
# the symlink ourselves here.
#
# See https://bugs.python.org/issue41355 for more info.
st = os.lstat(source)
if stat.S_ISLNK(st.st_mode):
src = realpath(source)
else:
src = source

os.link(src, link_name)

@staticmethod
def symlink(source, link_name):
Expand Down
2 changes: 1 addition & 1 deletion setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ install_requires =
fsspec[http]>=2021.10.1
aiohttp-retry>=2.4.5
diskcache>=5.2.1
jaraco.windows>=5.7.0; python_version < '3.8' and sys_platform == 'win32'

[options.extras_require]
# gssapi should not be included in all_remotes, because it doesn't have wheels
Expand Down Expand Up @@ -139,7 +140,6 @@ tests =
Pygments==2.10.0
collective.checkdocs==0.2
pydocstyle==6.1.1
jaraco.windows==5.7.0
# pylint requirements
pylint==2.11.1
# we use this to suppress pytest-related false positives in our tests.
Expand Down

0 comments on commit 874acec

Please sign in to comment.