mirror of
https://github.com/Stone-Red-Code/dvc.git
synced 2026-11-01 23:08:43 +01:00
177 lines
4.9 KiB
Python
177 lines
4.9 KiB
Python
import importlib.metadata as importlib_metadata
|
|
import itertools
|
|
import os
|
|
import pathlib
|
|
import platform
|
|
|
|
import psutil
|
|
|
|
from dvc import PKG, __version__
|
|
from dvc.exceptions import NotDvcRepoError
|
|
from dvc.fs import Schemes, generic, get_fs_cls, get_fs_config, registry
|
|
from dvc.repo import Repo
|
|
from dvc.scm import SCMError
|
|
from dvc.utils import error_link
|
|
|
|
SUBPROJECTS = (
|
|
"dvc_data",
|
|
"dvc_objects",
|
|
"dvc_render",
|
|
"dvc_task",
|
|
"scmrepo",
|
|
)
|
|
package = "" if PKG is None else f" ({PKG})"
|
|
|
|
|
|
def get_dvc_info():
|
|
dvc_version = f"DVC version: {__version__}{package}"
|
|
info = [
|
|
dvc_version,
|
|
"-" * len(dvc_version),
|
|
f"Platform: Python {platform.python_version()} on {platform.platform()}",
|
|
f"Subprojects:{_get_subprojects()}",
|
|
f"Supports:{_get_supported_remotes()}",
|
|
f"Config:{_get_config_dirs()}",
|
|
]
|
|
|
|
try:
|
|
with Repo() as repo:
|
|
# cache_dir might not exist yet (e.g. after `dvc init`), and we
|
|
# can't auto-create it, as it might cause issues if the user
|
|
# later decides to enable shared cache mode with
|
|
# `dvc config cache.shared group`.
|
|
if os.path.exists(repo.cache.local.path):
|
|
info.append(f"Cache types: {_get_linktype_support_info(repo)}")
|
|
fs_type = _get_fs_type(repo.cache.local.path)
|
|
info.append(f"Cache directory: {fs_type}")
|
|
else:
|
|
info.append("Cache types: " + error_link("no-dvc-cache"))
|
|
|
|
info.append(f"Caches: {_get_caches(repo.cache)}")
|
|
info.append(f"Remotes: {_get_remotes(repo.config)}")
|
|
|
|
root_directory = repo.root_dir
|
|
fs_root = _get_fs_type(os.path.abspath(root_directory))
|
|
info.append(f"Workspace directory: {fs_root}")
|
|
info.append(f"Repo: {_get_dvc_repo_info(repo)}")
|
|
info.append(f"Repo.site_cache_dir: {repo.site_cache_dir}")
|
|
except NotDvcRepoError:
|
|
pass
|
|
except SCMError:
|
|
info.append("Repo: dvc, git (broken)")
|
|
|
|
return "\n".join(info)
|
|
|
|
|
|
def _get_caches(cache):
|
|
caches = (
|
|
cache_type
|
|
for cache_type, cache_instance in cache.by_scheme()
|
|
if cache_instance and cache_type not in ("repo", "legacy")
|
|
)
|
|
|
|
# Caches will be always non-empty including the local cache
|
|
return ", ".join(caches)
|
|
|
|
|
|
def _get_remotes(config):
|
|
schemes = (
|
|
get_fs_cls(get_fs_config(config, name=remote)).protocol
|
|
for remote in config["remote"]
|
|
)
|
|
|
|
return ", ".join(schemes) or "None"
|
|
|
|
|
|
def _get_linktype_support_info(repo):
|
|
odb = repo.cache.local
|
|
|
|
links = generic.test_links(
|
|
["reflink", "hardlink", "symlink"],
|
|
odb.fs,
|
|
odb.path,
|
|
repo.fs,
|
|
repo.root_dir,
|
|
)
|
|
|
|
return ", ".join(links)
|
|
|
|
|
|
def _get_subprojects():
|
|
subprojects = []
|
|
for subproject in SUBPROJECTS:
|
|
try:
|
|
version = importlib_metadata.version(subproject)
|
|
subprojects.append(f"{subproject} = {version}")
|
|
except ImportError:
|
|
pass
|
|
|
|
return "\n\t" + "\n\t".join(subprojects)
|
|
|
|
|
|
def _get_supported_remotes():
|
|
supported_remotes = []
|
|
for scheme in registry:
|
|
if scheme in [Schemes.LOCAL, Schemes.MEMORY, "dvc", "git"]:
|
|
continue
|
|
|
|
try:
|
|
fs_cls = registry[scheme]
|
|
except ImportError:
|
|
continue
|
|
|
|
if not fs_cls.get_missing_deps():
|
|
dependencies = []
|
|
for requirement in fs_cls.REQUIRES:
|
|
dependencies.append(
|
|
f"{requirement} = {importlib_metadata.version(requirement)}"
|
|
)
|
|
|
|
remote_info = scheme
|
|
if dependencies:
|
|
remote_info += " (" + ", ".join(dependencies) + ")"
|
|
supported_remotes.append(remote_info)
|
|
|
|
assert len(supported_remotes) >= 1
|
|
return "\n\t" + ",\n\t".join(supported_remotes)
|
|
|
|
|
|
def _get_config_dirs():
|
|
from dvc.config import Config
|
|
|
|
dirs = [
|
|
f"Global: {Config.get_dir('global')}",
|
|
f"System: {Config.get_dir('system')}",
|
|
]
|
|
|
|
return "\n\t" + "\n\t".join(dirs)
|
|
|
|
|
|
def _get_fs_type(path):
|
|
partition = {}
|
|
for part in psutil.disk_partitions(all=True):
|
|
if part.fstype:
|
|
try:
|
|
mountpoint = pathlib.Path(part.mountpoint).resolve()
|
|
partition[mountpoint] = part.fstype + " on " + part.device
|
|
except PermissionError:
|
|
pass
|
|
|
|
# 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:
|
|
return partition[parent]
|
|
return ("unknown", "none")
|
|
|
|
|
|
def _get_dvc_repo_info(repo):
|
|
if repo.config.get("core", {}).get("no_scm", False):
|
|
return "dvc (no_scm)"
|
|
|
|
if repo.root_dir != repo.scm.root_dir:
|
|
return "dvc (subdir), git"
|
|
|
|
return "dvc, git"
|