Repository: pypa/virtualenv

Issue:
Cygwin and msys2 bash activator compatibility
**Issue**

Run the following via msys2:

```
$ /c/Users/builder/AppData/Local/Programs/Python/Python39/Scripts/virtualenv.exe --no-pip --no-setuptools --no-wheel -p /c/Users/builder/AppData/Local/Programs/Python/Python39/python.exe /tmp/tmp.uw7eZfvJIO
$ source /tmp/tmp.uw7eZfvJIO/Scripts/activate
$ python
python: command not found
```

The content of `/tmp/tmp.uw7eZfvJIO/Scripts/activate` contains `VIRTUAL_ENV='C:\tools\msys64\tmp\tmp.uw7eZfvJIO'`, but it's expected to be `VIRTUAL_ENV='/c/tools/msys64/tmp/tmp.uw7eZfvJIO'`, thus it can't locate `python`.

I believe the legacy version handles this correctly here: https://github.com/pypa/virtualenv/blob/4c9899f471139670b0f1bfd359c37a67c507447d/virtualenv.py#L1742-L1748

which contains:

`VIRTUAL_ENV="$(if [ "$OSTYPE" "==" "cygwin" ]; then cygpath -u 'C:\tools\msys64\tmp\tmp.uw7eZfvJIO'; else echo '/C/tools/msys64/tmp/tmp.uw7eZfvJIO'; fi;)"`

**Environment**

Provide at least:
- OS: Windows 7, using msys2 v20200903.0.0


Discussion:
I am also having this issue. I would be glad to submit a PR if someone could help point me in the right direction. It seems like the creator is correctly building the virtualenv, but we need to modify the path only for setting the VIRTUAL_ENV in the activate script.
You probably want to massage around here https://github.com/pypa/virtualenv/blob/master/src/virtualenv/activation/via_template.py#L36-L39

Resolving patch:
diff --git a/src/virtualenv/activation/via_template.py b/src/virtualenv/activation/via_template.py
--- a/src/virtualenv/activation/via_template.py
+++ b/src/virtualenv/activation/via_template.py
@@ -1,7 +1,9 @@
 from __future__ import absolute_import, unicode_literals
 
 import os
+import re
 import sys
+import sysconfig
 from abc import ABCMeta, abstractmethod
 
 from six import add_metaclass
@@ -31,9 +33,17 @@ def generate(self, creator):
         return generated
 
     def replacements(self, creator, dest_folder):
+        current_platform = sysconfig.get_platform()
+        platforms = ["mingw", "cygwin", "msys"]
+        if any(platform in current_platform for platform in platforms):
+            pattern = re.compile("^([A-Za-z]):(.*)")
+            match = pattern.match(str(creator.dest))
+            virtual_env = "/" + match.group(1).lower() + match.group(2)
+        else:
+            virtual_env = str(creator.dest)
         return {
             "__VIRTUAL_PROMPT__": "" if self.flag_prompt is None else self.flag_prompt,
-            "__VIRTUAL_ENV__": ensure_text(str(creator.dest)),
+            "__VIRTUAL_ENV__": ensure_text(virtual_env),
             "__VIRTUAL_NAME__": creator.env_name,
             "__BIN_NAME__": ensure_text(str(creator.bin_dir.relative_to(creator.dest))),
             "__PATH_SEP__": ensure_text(os.pathsep),


Test patch:
diff --git a/tests/unit/activation/test_activation_support.py b/tests/unit/activation/test_activation_support.py
--- a/tests/unit/activation/test_activation_support.py
+++ b/tests/unit/activation/test_activation_support.py
@@ -13,6 +13,8 @@
     PythonActivator,
 )
 from virtualenv.discovery.py_info import PythonInfo
+from virtualenv.info import IS_WIN
+from virtualenv.util.path import Path
 
 
 @pytest.mark.parametrize(
@@ -53,3 +55,32 @@ def test_activator_no_support_posix(mocker, activator_class):
     interpreter = mocker.Mock(spec=PythonInfo)
     interpreter.os = "posix"
     assert not activator.supports(interpreter)
+
+
+class Creator:
+    def __init__(self):
+        self.dest = "C:/tools/msys64/home"
+        self.env_name = "venv"
+        self.bin_dir = Path("C:/tools/msys64/home/bin")
+
+
+@pytest.mark.skipif(IS_WIN, reason="Github Actions ships with WSL bash")
+@pytest.mark.parametrize("activator_class", [BashActivator])
+def test_cygwin_msys2_path_conversion(mocker, activator_class):
+    mocker.patch("sysconfig.get_platform", return_value="mingw")
+    activator = activator_class(Namespace(prompt=None))
+    creator = Creator()
+    mocker.stub(creator.bin_dir.relative_to)
+    resource = activator.replacements(creator, "")
+    assert resource["__VIRTUAL_ENV__"] == "/c/tools/msys64/home"
+
+
+@pytest.mark.skipif(IS_WIN, reason="Github Actions ships with WSL bash")
+@pytest.mark.parametrize("activator_class", [BashActivator])
+def test_win_path_no_conversion(mocker, activator_class):
+    mocker.patch("sysconfig.get_platform", return_value="win-amd64")
+    activator = activator_class(Namespace(prompt=None))
+    creator = Creator()
+    mocker.stub(creator.bin_dir.relative_to)
+    resource = activator.replacements(creator, "")
+    assert resource["__VIRTUAL_ENV__"] == "C:/tools/msys64/home"