prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  dvc version: does not follow symlinks
  # Bug Report
  
  ## Description
  
  This is the `dvc version` output, where it says the cache directory is `nfs4 on storage:/home` and cache type is `symlink`.
  
  ```
  DVC version: 1.10.2 (pip)
  ---------------------------------
  Platform: Python 3.8.3 on Linux-5.4.0-54-generic-x86_64-with-glibc2.10
  Supports: All remotes
  Cache types: symlink
  Cache directory: nfs4 on storage:/home
  Caches: local
  Remotes: s3
  Workspace directory: nfs4 on storage:/home
  Repo: dvc, git
  ```
  
  However, I do have a `~/.config/dvc/config` file that overrides this:
  
  ```
  [core]
      experiments = true
  [cache]
      type = "reflink,symlink,copy"
      protected = true
      dir = /home/jc/ssd_cache/dvc_cache
  [feature]
      parametrization = true
  ```
  
  And the actual cache dir is `/home/jc/ssd_cache/dvc_cache` as I've specified instead of `nfs4 on storage:/home`
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `dvc/info.py`
  Content:
  ```
  1 import itertools
  2 import os
  3 import pathlib
  4 import platform
  5 import uuid
  6 
  7 from dvc.exceptions import DvcException, NotDvcRepoError
  8 from dvc.repo import Repo
  9 from dvc.scm.base import SCMError
  10 from dvc.system import System
  11 from dvc.tree import TREES, get_tree_cls, get_tree_config
  12 from dvc.utils import error_link
  13 from dvc.utils.pkg import PKG
  14 from dvc.version import __version__
  15 
  16 try:
  17     import psutil
  18 except ImportError:
  19     psutil = None
  20 
  21 if PKG is None:
  22     package = ""
  23 else:
  24     package = f"({PKG})"
  25 
  26 
  27 def get_dvc_info():
  28     info = [
  29         f"DVC version: {__version__} {package}",
  30         "---------------------------------",
  31         f"Platform: Python {platform.python_version()} on "
  32         f"{platform.platform()}",
  33         f"Supports: {_get_supported_remotes()}",
  34     ]
  35 
  36     try:
  37         repo = Repo()
  38 
  39         # cache_dir might not exist yet (e.g. after `dvc init`), and we
  40         # can't auto-create it, as it might cause issues if the user
  41         # later decides to enable shared cache mode with
  42         # `dvc config cache.shared group`.
  43         if os.path.exists(repo.cache.local.cache_dir):
  44             info.append(
  45                 "Cache types: {}".format(_get_linktype_support_info(repo))
  46             )
  47             if psutil:
  48                 fs_type = get_fs_type(repo.cache.local.cache_dir)
  49                 info.append(f"Cache directory: {fs_type}")
  50         else:
  51             info.append("Cache types: " + error_link("no-dvc-cache"))
  52 
  53         info.append(f"Caches: {_get_caches(repo.cache)}")
  54 
  55         info.append(f"Remotes: {_get_remotes(repo.config)}")
  56 
  57     except NotDvcRepoError:
  58         pass
  59     except SCMError:
  60         info.append("Repo: dvc, git (broken)")
  61     else:
  62         root_directory = repo.root_dir
  63         if psutil:
  64             fs_root = get_fs_type(os.path.abspath(root_directory))
  65             info.append(f"Workspace directory: {fs_root}")
  66         info.append("Repo: {}".format(_get_dvc_repo_info(repo)))
  67     return "\n".join(info)
  68 
  69 
  70 def _get_caches(cache):
  71     caches = (
  72         cache_type
  73         for cache_type, cache_instance in cache.by_scheme()
  74         if cache_instance
  75     )
  76 
  77     # Caches will be always non-empty including the local cache
  78     return ", ".join(caches)
  79 
  80 
  81 def _get_remotes(config):
  82     schemes = (
  83         get_tree_cls(get_tree_config(config, name=remote)).scheme
  84         for remote in config["remote"]
  85     )
  86 
  87     return ", ".join(schemes) or "None"
  88 
  89 
  90 def _get_linktype_support_info(repo):
  91 
  92     links = {
  93         "reflink": (System.reflink, None),
  94         "hardlink": (System.hardlink, System.is_hardlink),
  95         "symlink": (System.symlink, System.is_symlink),
  96     }
  97 
  98     fname = "." + str(uuid.uuid4())
  99     src = os.path.join(repo.cache.local.cache_dir, fname)
  100     open(src, "w").close()
  101     dst = os.path.join(repo.root_dir, fname)
  102 
  103     cache = []
  104 
  105     for name, (link, is_link) in links.items():
  106         try:
  107             link(src, dst)
  108             status = "supported"
  109             if is_link and not is_link(dst):
  110                 status = "broken"
  111             os.unlink(dst)
  112         except DvcException:
  113             status = "not supported"
  114 
  115         if status == "supported":
  116             cache.append(name)
  117     os.remove(src)
  118 
  119     return ", ".join(cache)
  120 
  121 
  122 def _get_supported_remotes():
  123 
  124     supported_remotes = []
  125     for tree_cls in TREES:
  126         if not tree_cls.get_missing_deps():
  127             supported_remotes.append(tree_cls.scheme)
  128 
  129     if len(supported_remotes) == len(TREES):
  130         return "All remotes"
  131 
  132     if len(supported_remotes) == 1:
  133         return supported_remotes
  134 
  135     return ", ".join(supported_remotes)
  136 
  137 
  138 def get_fs_type(path):
  139 
  140     partition = {
  141         pathlib.Path(part.mountpoint): (part.fstype + " on " + part.device)
  142         for part in psutil.disk_partitions(all=True)
  143     }
  144 
  145     path = pathlib.Path(path)
  146 
  147     for parent in itertools.chain([path], path.parents):
  148         if parent in partition:
  149             return partition[parent]
  150     return ("unknown", "none")
  151 
  152 
  153 def _get_dvc_repo_info(self):
  154     if self.config.get("core", {}).get("no_scm", False):
  155         return "dvc (no_scm)"
  156 
  157     if self.root_dir != self.scm.root_dir:
  158         return "dvc (subdir), git"
  159 
  160     return "dvc, git"
  161
  ```
  --- END FILES ---
  
  Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.
  
  Here is an example:
  
  ```diff
  diff --git a/examples/server_async.py b/examples/server_async.py
  --- a/examples/server_async.py
  +++ b/examples/server_async.py
  @@ -313,4 +313,4 @@
   
   
   if __name__ == "__main__":
  -    asyncio.run(run_async_server("."), debug=True)
  +    asyncio.run(run_async_server(), debug=True)
  diff --git a/examples/server_sync.py b/examples/server_sync.py
  --- a/examples/server_sync.py
  +++ b/examples/server_sync.py
  @@ -313,5 +313,5 @@
   
   
   if __name__ == "__main__":
  -    server = run_sync_server(".")
  +    server = run_sync_server()
       server.shutdown()
  
  ```
  
golden_diff: diff --git a/dvc/info.py b/dvc/info.py
  --- a/dvc/info.py
  +++ b/dvc/info.py
  @@ -142,7 +142,8 @@
           for part in psutil.disk_partitions(all=True)
       }
   
  -    path = pathlib.Path(path)
  +    # need to follow the symlink: https://github.com/iterative/dvc/issues/5065
  +    path = pathlib.Path(path).resolve()
   
       for parent in itertools.chain([path], path.parents):
           if parent in partition:
  
verification_info: {"golden_diff": "diff --git a/dvc/info.py b/dvc/info.py\n--- a/dvc/info.py\n+++ b/dvc/info.py\n@@ -142,7 +142,8 @@\n         for part in psutil.disk_partitions(all=True)\n     }\n \n-    path = pathlib.Path(path)\n+    # need to follow the symlink: https://github.com/iterative/dvc/issues/5065\n+    path = pathlib.Path(path).resolve()\n \n     for parent in itertools.chain([path], path.parents):\n         if parent in partition:\n", "issue": "dvc version: does not follow symlinks\n# Bug Report\r\n\r\n## Description\r\n\r\nThis is the `dvc version` output, where it says the cache directory is `nfs4 on storage:/home` and cache type is `symlink`.\r\n\r\n```\r\nDVC version: 1.10.2 (pip)\r\n---------------------------------\r\nPlatform: Python 3.8.3 on Linux-5.4.0-54-generic-x86_64-with-glibc2.10\r\nSupports: All remotes\r\nCache types: symlink\r\nCache directory: nfs4 on storage:/home\r\nCaches: local\r\nRemotes: s3\r\nWorkspace directory: nfs4 on storage:/home\r\nRepo: dvc, git\r\n```\r\n\r\nHowever, I do have a `~/.config/dvc/config` file that overrides this:\r\n\r\n```\r\n[core]\r\n    experiments = true\r\n[cache]\r\n    type = \"reflink,symlink,copy\"\r\n    protected = true\r\n    dir = /home/jc/ssd_cache/dvc_cache\r\n[feature]\r\n    parametrization = true\r\n```\r\n\r\nAnd the actual cache dir is `/home/jc/ssd_cache/dvc_cache` as I've specified instead of `nfs4 on storage:/home`\n", "before_files": [{"content": "import itertools\nimport os\nimport pathlib\nimport platform\nimport uuid\n\nfrom dvc.exceptions import DvcException, NotDvcRepoError\nfrom dvc.repo import Repo\nfrom dvc.scm.base import SCMError\nfrom dvc.system import System\nfrom dvc.tree import TREES, get_tree_cls, get_tree_config\nfrom dvc.utils import error_link\nfrom dvc.utils.pkg import PKG\nfrom dvc.version import __version__\n\ntry:\n    import psutil\nexcept ImportError:\n    psutil = None\n\nif PKG is None:\n    package = \"\"\nelse:\n    package = f\"({PKG})\"\n\n\ndef get_dvc_info():\n    info = [\n        f\"DVC version: {__version__} {package}\",\n        \"---------------------------------\",\n        f\"Platform: Python {platform.python_version()} on \"\n        f\"{platform.platform()}\",\n        f\"Supports: {_get_supported_remotes()}\",\n    ]\n\n    try:\n        repo = Repo()\n\n        # cache_dir might not exist yet (e.g. after `dvc init`), and we\n        # can't auto-create it, as it might cause issues if the user\n        # later decides to enable shared cache mode with\n        # `dvc config cache.shared group`.\n        if os.path.exists(repo.cache.local.cache_dir):\n            info.append(\n                \"Cache types: {}\".format(_get_linktype_support_info(repo))\n            )\n            if psutil:\n                fs_type = get_fs_type(repo.cache.local.cache_dir)\n                info.append(f\"Cache directory: {fs_type}\")\n        else:\n            info.append(\"Cache types: \" + error_link(\"no-dvc-cache\"))\n\n        info.append(f\"Caches: {_get_caches(repo.cache)}\")\n\n        info.append(f\"Remotes: {_get_remotes(repo.config)}\")\n\n    except NotDvcRepoError:\n        pass\n    except SCMError:\n        info.append(\"Repo: dvc, git (broken)\")\n    else:\n        root_directory = repo.root_dir\n        if psutil:\n            fs_root = get_fs_type(os.path.abspath(root_directory))\n            info.append(f\"Workspace directory: {fs_root}\")\n        info.append(\"Repo: {}\".format(_get_dvc_repo_info(repo)))\n    return \"\\n\".join(info)\n\n\ndef _get_caches(cache):\n    caches = (\n        cache_type\n        for cache_type, cache_instance in cache.by_scheme()\n        if cache_instance\n    )\n\n    # Caches will be always non-empty including the local cache\n    return \", \".join(caches)\n\n\ndef _get_remotes(config):\n    schemes = (\n        get_tree_cls(get_tree_config(config, name=remote)).scheme\n        for remote in config[\"remote\"]\n    )\n\n    return \", \".join(schemes) or \"None\"\n\n\ndef _get_linktype_support_info(repo):\n\n    links = {\n        \"reflink\": (System.reflink, None),\n        \"hardlink\": (System.hardlink, System.is_hardlink),\n        \"symlink\": (System.symlink, System.is_symlink),\n    }\n\n    fname = \".\" + str(uuid.uuid4())\n    src = os.path.join(repo.cache.local.cache_dir, fname)\n    open(src, \"w\").close()\n    dst = os.path.join(repo.root_dir, fname)\n\n    cache = []\n\n    for name, (link, is_link) in links.items():\n        try:\n            link(src, dst)\n            status = \"supported\"\n            if is_link and not is_link(dst):\n                status = \"broken\"\n            os.unlink(dst)\n        except DvcException:\n            status = \"not supported\"\n\n        if status == \"supported\":\n            cache.append(name)\n    os.remove(src)\n\n    return \", \".join(cache)\n\n\ndef _get_supported_remotes():\n\n    supported_remotes = []\n    for tree_cls in TREES:\n        if not tree_cls.get_missing_deps():\n            supported_remotes.append(tree_cls.scheme)\n\n    if len(supported_remotes) == len(TREES):\n        return \"All remotes\"\n\n    if len(supported_remotes) == 1:\n        return supported_remotes\n\n    return \", \".join(supported_remotes)\n\n\ndef get_fs_type(path):\n\n    partition = {\n        pathlib.Path(part.mountpoint): (part.fstype + \" on \" + part.device)\n        for part in psutil.disk_partitions(all=True)\n    }\n\n    path = pathlib.Path(path)\n\n    for parent in itertools.chain([path], path.parents):\n        if parent in partition:\n            return partition[parent]\n    return (\"unknown\", \"none\")\n\n\ndef _get_dvc_repo_info(self):\n    if self.config.get(\"core\", {}).get(\"no_scm\", False):\n        return \"dvc (no_scm)\"\n\n    if self.root_dir != self.scm.root_dir:\n        return \"dvc (subdir), git\"\n\n    return \"dvc, git\"\n", "path": "dvc/info.py"}], "after_files": [{"content": "import itertools\nimport os\nimport pathlib\nimport platform\nimport uuid\n\nfrom dvc.exceptions import DvcException, NotDvcRepoError\nfrom dvc.repo import Repo\nfrom dvc.scm.base import SCMError\nfrom dvc.system import System\nfrom dvc.tree import TREES, get_tree_cls, get_tree_config\nfrom dvc.utils import error_link\nfrom dvc.utils.pkg import PKG\nfrom dvc.version import __version__\n\ntry:\n    import psutil\nexcept ImportError:\n    psutil = None\n\nif PKG is None:\n    package = \"\"\nelse:\n    package = f\"({PKG})\"\n\n\ndef get_dvc_info():\n    info = [\n        f\"DVC version: {__version__} {package}\",\n        \"---------------------------------\",\n        f\"Platform: Python {platform.python_version()} on \"\n        f\"{platform.platform()}\",\n        f\"Supports: {_get_supported_remotes()}\",\n    ]\n\n    try:\n        repo = Repo()\n\n        # cache_dir might not exist yet (e.g. after `dvc init`), and we\n        # can't auto-create it, as it might cause issues if the user\n        # later decides to enable shared cache mode with\n        # `dvc config cache.shared group`.\n        if os.path.exists(repo.cache.local.cache_dir):\n            info.append(\n                \"Cache types: {}\".format(_get_linktype_support_info(repo))\n            )\n            if psutil:\n                fs_type = get_fs_type(repo.cache.local.cache_dir)\n                info.append(f\"Cache directory: {fs_type}\")\n        else:\n            info.append(\"Cache types: \" + error_link(\"no-dvc-cache\"))\n\n        info.append(f\"Caches: {_get_caches(repo.cache)}\")\n\n        info.append(f\"Remotes: {_get_remotes(repo.config)}\")\n\n    except NotDvcRepoError:\n        pass\n    except SCMError:\n        info.append(\"Repo: dvc, git (broken)\")\n    else:\n        root_directory = repo.root_dir\n        if psutil:\n            fs_root = get_fs_type(os.path.abspath(root_directory))\n            info.append(f\"Workspace directory: {fs_root}\")\n        info.append(\"Repo: {}\".format(_get_dvc_repo_info(repo)))\n    return \"\\n\".join(info)\n\n\ndef _get_caches(cache):\n    caches = (\n        cache_type\n        for cache_type, cache_instance in cache.by_scheme()\n        if cache_instance\n    )\n\n    # Caches will be always non-empty including the local cache\n    return \", \".join(caches)\n\n\ndef _get_remotes(config):\n    schemes = (\n        get_tree_cls(get_tree_config(config, name=remote)).scheme\n        for remote in config[\"remote\"]\n    )\n\n    return \", \".join(schemes) or \"None\"\n\n\ndef _get_linktype_support_info(repo):\n\n    links = {\n        \"reflink\": (System.reflink, None),\n        \"hardlink\": (System.hardlink, System.is_hardlink),\n        \"symlink\": (System.symlink, System.is_symlink),\n    }\n\n    fname = \".\" + str(uuid.uuid4())\n    src = os.path.join(repo.cache.local.cache_dir, fname)\n    open(src, \"w\").close()\n    dst = os.path.join(repo.root_dir, fname)\n\n    cache = []\n\n    for name, (link, is_link) in links.items():\n        try:\n            link(src, dst)\n            status = \"supported\"\n            if is_link and not is_link(dst):\n                status = \"broken\"\n            os.unlink(dst)\n        except DvcException:\n            status = \"not supported\"\n\n        if status == \"supported\":\n            cache.append(name)\n    os.remove(src)\n\n    return \", \".join(cache)\n\n\ndef _get_supported_remotes():\n\n    supported_remotes = []\n    for tree_cls in TREES:\n        if not tree_cls.get_missing_deps():\n            supported_remotes.append(tree_cls.scheme)\n\n    if len(supported_remotes) == len(TREES):\n        return \"All remotes\"\n\n    if len(supported_remotes) == 1:\n        return supported_remotes\n\n    return \", \".join(supported_remotes)\n\n\ndef get_fs_type(path):\n\n    partition = {\n        pathlib.Path(part.mountpoint): (part.fstype + \" on \" + part.device)\n        for part in psutil.disk_partitions(all=True)\n    }\n\n    # need to follow the symlink: https://github.com/iterative/dvc/issues/5065\n    path = pathlib.Path(path).resolve()\n\n    for parent in itertools.chain([path], path.parents):\n        if parent in partition:\n            return partition[parent]\n    return (\"unknown\", \"none\")\n\n\ndef _get_dvc_repo_info(self):\n    if self.config.get(\"core\", {}).get(\"no_scm\", False):\n        return \"dvc (no_scm)\"\n\n    if self.root_dir != self.scm.root_dir:\n        return \"dvc (subdir), git\"\n\n    return \"dvc, git\"\n", "path": "dvc/info.py"}]}