diff --git a/dvc/info.py b/dvc/info.py index 188d42250..4d8cbf811 100644 --- a/dvc/info.py +++ b/dvc/info.py @@ -8,7 +8,7 @@ from dvc.exceptions import DvcException, NotDvcRepoError from dvc.repo import Repo from dvc.scm.base import SCMError from dvc.system import System -from dvc.tree import TREES +from dvc.tree import TREES, get_tree_cls, get_tree_config from dvc.utils import error_link from dvc.utils.pkg import PKG from dvc.version import __version__ @@ -50,6 +50,10 @@ def get_dvc_info(): 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)}") + except NotDvcRepoError: pass except SCMError: @@ -63,6 +67,26 @@ def get_dvc_info(): return "\n".join(info) +def _get_caches(cache): + caches = ( + cache_type + for cache_type, cache_instance in cache.by_scheme() + if cache_instance + ) + + # Caches will be always non-empty including the local cache + return ", ".join(caches) + + +def _get_remotes(config): + schemes = ( + get_tree_cls(get_tree_config(config, name=remote)).scheme + for remote in config["remote"] + ) + + return ", ".join(schemes) or "None" + + def _get_linktype_support_info(repo): links = { diff --git a/dvc/tree/__init__.py b/dvc/tree/__init__.py index eacb12352..c36f5216a 100644 --- a/dvc/tree/__init__.py +++ b/dvc/tree/__init__.py @@ -32,23 +32,23 @@ TREES = [ ] -def _get_tree(remote_conf): +def get_tree_cls(remote_conf): for tree_cls in TREES: if tree_cls.supported(remote_conf): return tree_cls return LocalTree -def _get_conf(repo, **kwargs): +def get_tree_config(config, **kwargs): name = kwargs.get("name") if name: - remote_conf = repo.config["remote"][name.lower()] + remote_conf = config["remote"][name.lower()] else: remote_conf = kwargs - return _resolve_remote_refs(repo, remote_conf) + return _resolve_remote_refs(config, remote_conf) -def _resolve_remote_refs(repo, remote_conf): +def _resolve_remote_refs(config, remote_conf): # Support for cross referenced remotes. # This will merge the settings, shadowing base ref with remote_conf. # For example, having: @@ -74,7 +74,7 @@ def _resolve_remote_refs(repo, remote_conf): if parsed.scheme != "remote": return remote_conf - base = _get_conf(repo, name=parsed.netloc) + base = get_tree_config(config, name=parsed.netloc) url = posixpath.join(base["url"], parsed.path.lstrip("/")) return {**base, **remote_conf, "url": url} @@ -82,9 +82,9 @@ def _resolve_remote_refs(repo, remote_conf): def get_cloud_tree(repo, **kwargs): from dvc.config import SCHEMA, ConfigError, Invalid - remote_conf = _get_conf(repo, **kwargs) + remote_conf = get_tree_config(repo.config, **kwargs) try: remote_conf = SCHEMA["remote"][str](remote_conf) except Invalid as exc: raise ConfigError(str(exc)) from None - return _get_tree(remote_conf)(repo, remote_conf) + return get_tree_cls(remote_conf)(repo, remote_conf) diff --git a/tests/func/test_version.py b/tests/func/test_version.py index 4d63a2c2d..6b421cfe1 100644 --- a/tests/func/test_version.py +++ b/tests/func/test_version.py @@ -11,4 +11,6 @@ def test_(tmp_dir, dvc, scm, caplog): assert re.search(f"Platform: {PYTHON_VERSION_REGEX} on .*", caplog.text) assert re.search(r"Supports: .*", caplog.text) assert re.search(r"Cache types: .*", caplog.text) + assert re.search(r"Caches: local", caplog.text) + assert re.search(r"Remotes: None", caplog.text) assert "Repo: dvc, git" in caplog.text diff --git a/tests/unit/test_info.py b/tests/unit/test_info.py index 133cd386f..f887b8a3c 100644 --- a/tests/unit/test_info.py +++ b/tests/unit/test_info.py @@ -53,6 +53,38 @@ def test_info_in_broken_git_repo(tmp_dir, dvc, scm, caplog): assert "Repo: dvc, git (broken)" in dvc_info +def test_caches(tmp_dir, dvc, caplog): + tmp_dir.add_remote( + name="sshcache", url="ssh://example.com/path", default=False + ) + with tmp_dir.dvc.config.edit() as conf: + conf["cache"]["ssh"] = "sshcache" + + dvc_info = get_dvc_info() + + # Order of cache types is runtime dependent + assert re.search("Caches: (local, ssh|ssh, local)", dvc_info) + + +def test_remotes_empty(tmp_dir, dvc, caplog): + # No remotes are configured + dvc_info = get_dvc_info() + + assert "Remotes: None" in dvc_info + + +def test_remotes(tmp_dir, dvc, caplog): + tmp_dir.add_remote(name="server", url="ssh://localhost", default=False) + tmp_dir.add_remote( + name="r1", url="azure://example.com/path", default=False + ) + tmp_dir.add_remote(name="r2", url="remote://server/path", default=False) + + dvc_info = get_dvc_info() + + assert re.search("Remotes: (ssh, azure|azure, ssh)", dvc_info) + + @pytest.mark.skipif(psutil is None, reason="No psutil.") def test_fs_info_in_repo(tmp_dir, dvc, caplog): os.mkdir(dvc.cache.local.cache_dir)