Repository: iterative/dvc

Issue:
version: detect and show the way DVC was installed
The way the `dvc version` command works:

```
$ dvc version

DVC version: 0.41.3+f36162
Python version: 3.7.1
Platform: Linux-4.15.0-50-generic-x86_64-with-debian-buster-sid
Binary: False
Cache: reflink - False, hardlink - True, symlink - True
Filesystem type (cache directory): ('ext4', '/dev/sdb3')
Filesystem type (workspace): ('ext4', '/dev/sdb3')
```

It outputs only `Binary: False` or `Binary: True` depending on how DVC was installed. Which is not granular enough.

See also docs: https://dvc.org/doc/command-reference/version

We can try and use the logic behind the update message (`def _get_package_manager(self)` from the `updater.py`) to show in the dvc version output how exactly DVC was installed - `pip`, `conda`, `brew`, package, etc. It'll help to debug faster, potentially can help users when they need to upgrade.

Almost all the logic required should be available already in the before mentioned `updater.py`.



Discussion:
Related #2611
@shcheklein , there's room for improvement in `_get_package_manager` method.
Probably using `where dvc` to look if the path is prefixed by `$VIRTUAL_ENV` or `$CONDA_ENV_PATH` to know if it was installed under a virtual environment.

Also, I don't know if it is possible to modify the `setup.py` or something before building it with `fpm build`. This would be helpful because instead of guessing which was the installation method, it would be a lookup for a variable under the main namespace or something.
Sort of like we `pin_version` on `setup.py`, but `pin_package`?
For the record, to implement this, one would need to take output of `_get_package_manager` https://github.com/iterative/dvc/blob/0.66.3/dvc/updater.py#L185 and use it in https://github.com/iterative/dvc/blob/0.66.1/dvc/command/version.py#L39
```
Package manager: {package_manager}
```
Also, some fixes to `tests/func/test_version.py` would be required.
Can I reserve this issue to be used for today's Devsprints?
@kurianbenoy Sure!
Would like to work on the issue . Seems like it was not completed during devsprint.

Sure @kss682 !
excellent job @kss682 ! thank you :)
Welcome , Thanks to @efiop for helping me.

Resolving patch:
diff --git a/dvc/command/version.py b/dvc/command/version.py
--- a/dvc/command/version.py
+++ b/dvc/command/version.py
@@ -18,7 +18,7 @@
 from dvc.version import __version__
 from dvc.exceptions import DvcException, NotDvcRepoError
 from dvc.system import System
-
+from dvc.utils.pkg import get_package_manager
 
 logger = logging.getLogger(__name__)
 
@@ -31,17 +31,19 @@ def run(self):
         python_version = platform.python_version()
         platform_type = platform.platform()
         binary = is_binary()
-
+        package_manager = get_package_manager()
         info = (
             "DVC version: {dvc_version}\n"
             "Python version: {python_version}\n"
             "Platform: {platform_type}\n"
             "Binary: {binary}\n"
+            "Package manager: {package_manager}\n"
         ).format(
             dvc_version=dvc_version,
             python_version=python_version,
             platform_type=platform_type,
             binary=binary,
+            package_manager=package_manager,
         )
 
         try:
diff --git a/dvc/updater.py b/dvc/updater.py
--- a/dvc/updater.py
+++ b/dvc/updater.py
@@ -9,8 +9,8 @@
 
 from dvc import __version__
 from dvc.lock import Lock, LockError
-from dvc.utils import is_binary, boxify, env2bool
-
+from dvc.utils import boxify, env2bool
+from dvc.utils.pkg import get_package_manager
 
 logger = logging.getLogger(__name__)
 
@@ -140,52 +140,6 @@ def _get_update_instructions(self):
             ),
         }
 
-        package_manager = self._get_package_manager()
+        package_manager = get_package_manager()
 
         return instructions[package_manager]
-
-    def _get_linux(self):
-        import distro
-
-        if not is_binary():
-            return "pip"
-
-        package_managers = {
-            "rhel": "yum",
-            "centos": "yum",
-            "fedora": "yum",
-            "amazon": "yum",
-            "opensuse": "yum",
-            "ubuntu": "apt",
-            "debian": "apt",
-        }
-
-        return package_managers.get(distro.id())
-
-    def _get_darwin(self):
-        if not is_binary():
-            if __file__.startswith("/usr/local/Cellar"):
-                return "formula"
-            else:
-                return "pip"
-        return None
-
-    def _get_windows(self):
-        return None if is_binary() else "pip"
-
-    def _get_package_manager(self):
-        import platform
-        from dvc.exceptions import DvcException
-
-        m = {
-            "Windows": self._get_windows,
-            "Darwin": self._get_darwin,
-            "Linux": self._get_linux,
-        }
-
-        system = platform.system()
-        func = m.get(system)
-        if func is None:
-            raise DvcException("not supported system '{}'".format(system))
-
-        return func()
diff --git a/dvc/utils/pkg.py b/dvc/utils/pkg.py
new file mode 100644
--- /dev/null
+++ b/dvc/utils/pkg.py
@@ -0,0 +1,51 @@
+from dvc.utils import is_binary
+
+
+def get_linux():
+    import distro
+
+    if not is_binary():
+        return "pip"
+
+    package_managers = {
+        "rhel": "yum",
+        "centos": "yum",
+        "fedora": "yum",
+        "amazon": "yum",
+        "opensuse": "yum",
+        "ubuntu": "apt",
+        "debian": "apt",
+    }
+
+    return package_managers.get(distro.id())
+
+
+def get_darwin():
+    if not is_binary():
+        if __file__.startswith("/usr/local/Cellar"):
+            return "formula"
+        else:
+            return "pip"
+    return None
+
+
+def get_windows():
+    return None if is_binary() else "pip"
+
+
+def get_package_manager():
+    import platform
+    from dvc.exceptions import DvcException
+
+    m = {
+        "Windows": get_windows(),
+        "Darwin": get_darwin(),
+        "Linux": get_linux(),
+    }
+
+    system = platform.system()
+    func = m.get(system)
+    if func is None:
+        raise DvcException("not supported system '{}'".format(system))
+
+    return func


Test patch: