Repository: conda/conda

Issue:
new shell activation seems to break conda-build env activation
<!--
Hi!  Read this; it's important.

This is an issue tracker for conda -- the package manager.  File feature requests
for conda here, as well as bug reports about something conda has messed up.

If your issue is a bug report for:
  * a specific conda package from Anaconda ('defaults' channel):
      ==> file at https://github.com/ContinuumIO/anaconda-issues
  * a specific conda package from conda-forge:
      ==> file at the corresponding feedstock under https://github.com/conda-forge
  * repo.anaconda.com access and service:
      ==> file at https://github.com/ContinuumIO/anaconda-issues
  * anaconda.org access and service:
      ==> file at https://anaconda.org/contact/report
  * commands under 'conda build':
      ==> file at https://github.com/conda/conda-build
  * commands under 'conda env':
      ==> please file it here!
  * all other conda commands that start with 'conda':
      ==> please file it here!

If you continue on,

   **please include all requested information below.**

If a maintainer determines the information is required to understand 
your issue, and if it is not provided, your issue may be
closed automatically.

-->

## Current Behavior
<!-- What actually happens?
     If you want to include console output, please use "Steps to Reproduce" below. -->

This is with master, on win-64.  ``conda 4.6.0a2.post446+4b8c40a90``

(base) Z:\code\aggregate-clean2>where conda
c:\miniconda2\Library\bin\conda.bat
c:\miniconda2\Scripts\conda.exe
c:\miniconda2\condacmd\conda.bat


### Steps to Reproduce
<!-- If the current behavior is a bug, please provide specific, minimal steps to independently reproduce.
     Include the exact conda commands that reproduce the issue and their output between the ticks below. -->
```

(base) Z:\code\aggregate-clean2>c:\miniconda2\Scripts\conda.exe init cmd.exe
no change     c:\miniconda2\Scripts\conda.exe
no change     c:\miniconda2\Scripts\conda-env.exe
no change     c:\miniconda2\Scripts\conda-script.py
no change     c:\miniconda2\Scripts\conda-env-script.py
no change     c:\miniconda2\condacmd\conda.bat
no change     c:\miniconda2\condacmd\_conda_activate.bat
no change     c:\miniconda2\condacmd\conda_auto_activate.bat
no change     c:\miniconda2\condacmd\conda_hook.bat
no change     c:\miniconda2\Scripts\activate.bat
no change     c:\miniconda2\condacmd\activate.bat
no change     c:\miniconda2\condacmd\deactivate.bat
no change     c:\miniconda2\Scripts\activate
no change     c:\miniconda2\Scripts\deactivate
no change     c:\miniconda2\etc\profile.d\conda.sh
no change     c:\miniconda2\etc\fish\conf.d\conda.fish
no change     c:\miniconda2\Lib\site-packages\xonsh\conda.xsh
no change     c:\miniconda2\etc\profile.d\conda.csh
no change     HKEY_CURRENT_USER\Software\Microsoft\Command Processor\AutoRun
No action taken.
```

Now, build a recipe with conda-build:

```
(base) Z:\code\aggregate-clean2>conda build numexpr-feedstock --python=3.7

( elided text about env creation and variable setting)

(base) c:\miniconda2\conda-bld\numexpr_1535419666960\work>conda activate "c:\miniconda2\conda-bld\numexpr_1535419666960\_h_env"

CommandNotFoundError: Your shell has not been properly configured to use 'conda activate'.
If using 'conda activate' from a batch script, change your
invocation to 'CALL conda.bat activate'.

To initialize your shell, run

    $ conda init <SHELL_NAME>

Currently supported shells are:
  - bash
  - cmd.exe
  - fish
  - tcsh
  - xonsh
  - zsh

See 'conda init --help' for more information and options.

IMPORTANT: You may need to close and restart your shell after running 'conda init'.
```

The raw cmd.exe does appear to behave more cleanly:

```
Z:\>where conda
c:\miniconda2\condacmd\conda.bat
```

However, this also results in the same build failures.  I thought this was something to do with Anaconda Prompt and confusion between that and the new way, but it appears the new way is just as broken by itself.  =(

## Expected Behavior
<!-- What do you think should happen? -->
Conda build should be able to activate envs?

## Environment Information
<details open><summary><code>`conda info`</code></summary><p>
<!-- between the ticks below, paste the output of 'conda info' -->

```
(base) Z:\code\aggregate-clean2>conda info

     active environment : base
    active env location : c:\miniconda2
            shell level : 1
       user config file : C:\Users\builder\.condarc
 populated config files : C:\Users\builder\.condarc
          conda version : 4.6.0a2.post446+4b8c40a90
    conda-build version : 3.13.0+0.g170fa827.dirty
         python version : 2.7.14.final.0
       base environment : c:\miniconda2  (writable)
           channel URLs : https://repo.anaconda.com/pkgs/main/win-64
                          https://repo.anaconda.com/pkgs/main/noarch
                          https://repo.anaconda.com/pkgs/free/win-64
                          https://repo.anaconda.com/pkgs/free/noarch
                          https://repo.anaconda.com/pkgs/r/win-64
                          https://repo.anaconda.com/pkgs/r/noarch
                          https://repo.anaconda.com/pkgs/msys2/win-64
                          https://repo.anaconda.com/pkgs/msys2/noarch
          package cache : c:\miniconda2\pkgs
                          C:\Users\builder\AppData\Local\conda\conda\pkgs
       envs directories : c:\miniconda2\envs
                          C:\Users\builder\AppData\Local\conda\conda\envs
                          C:\Users\builder\.conda\envs
               platform : win-64
             user-agent : conda/4.6.0a2.post446+4b8c40a90 requests/2.18.4 CPython/2.7.14 Windows/10 Windows/10.0.17134
          administrator : False
             netrc file : None
           offline mode : False
```
</p></details>


<details open><summary><code>`conda config --show-sources`</code></summary><p>
<!-- between the ticks below, paste the output of 'conda config --show-sources' -->

```

```
</p></details>


<details><summary><code>`conda list --show-channel-urls`</code></summary><p>
<!-- between the ticks below, paste the output of 'conda list --show-channel-urls' -->

```

```
</p></details>



Discussion:
We probably just need to ensure that `self.sep.join((context.conda_prefix, 'condacmd'))` is always put in front of the added prefix paths at https://github.com/conda/conda/blob/4b8c40a908ce9d536244fe5ca1868c06251802c4/conda/activate.py#L425 on Windows, I guess.

Resolving patch:
diff --git a/conda/activate.py b/conda/activate.py
--- a/conda/activate.py
+++ b/conda/activate.py
@@ -422,7 +422,7 @@ def _add_prefix_to_path(self, prefix, starting_path_dirs=None):
             path_list = list(self.path_conversion(self._get_starting_path_list()))
         else:
             path_list = list(self.path_conversion(starting_path_dirs))
-        path_list[0:0] = list(self._get_path_dirs2(prefix))
+        path_list[0:0] = list(self.path_conversion(self._get_path_dirs2(prefix)))
         return tuple(path_list)
 
     def _remove_prefix_from_path(self, prefix, starting_path_dirs=None):
@@ -708,6 +708,18 @@ def _build_activate_shell_custom(self, export_vars):
     def _hook_preamble(self):
         raise NotImplementedError()
 
+    def _add_prefix_to_path(self, prefix, starting_path_dirs=None):
+        # If this is the first time we're activating an environment, we need to ensure that
+        # the condacmd directory is included in the path list.
+        old_conda_shlvl = int(self.environ.get('CONDA_SHLVL', '').strip() or 0)
+        if starting_path_dirs is None:
+            starting_path_dirs = self._get_starting_path_list()
+        starting_path_dirs = list(starting_path_dirs)
+        if not old_conda_shlvl and not any(p.endswith("condacmd") for p in starting_path_dirs):
+            condacmd_dir = self.path_conversion(join(context.conda_prefix, "condacmd"))
+            starting_path_dirs.insert(0, condacmd_dir)
+        return super(CmdExeActivator, self)._add_prefix_to_path(prefix, starting_path_dirs)
+
 
 class FishActivator(_Activator):
 


Test patch:
diff --git a/tests/test_activate.py b/tests/test_activate.py
--- a/tests/test_activate.py
+++ b/tests/test_activate.py
@@ -99,7 +99,10 @@ def test_PS1_no_changeps1(self):
             instructions = activator.build_activate("base")
             assert instructions['export_vars']['CONDA_PROMPT_MODIFIER'] == ''
 
-    def test_add_prefix_to_path(self):
+    def test_add_prefix_to_path_posix(self):
+        if on_win and "PWD" not in os.environ:
+            pytest.skip("This test cannot be run from the cmd.exe shell.")
+
         activator = PosixActivator()
 
         path_dirs = activator.path_conversion(['/path1/bin', '/path2/bin', '/usr/local/bin', '/usr/bin', '/bin'])
@@ -112,6 +115,23 @@ def test_add_prefix_to_path(self):
         new_path = activator._add_prefix_to_path(test_prefix, path_dirs)
         assert new_path == added_paths + path_dirs
 
+    @pytest.mark.skipif(not on_win, reason="windows-specific test")
+    def test_add_prefix_to_path_cmdexe(self):
+        activator = CmdExeActivator()
+
+        path_dirs = activator.path_conversion(["C:\\path1", "C:\\Program Files\\Git\\cmd", "C:\\WINDOWS\\system32"])
+        assert len(path_dirs) == 3
+        test_prefix = '/usr/mytest/prefix'
+        added_paths = activator.path_conversion(activator._get_path_dirs(test_prefix))
+        if isinstance(added_paths, string_types):
+            added_paths = added_paths,
+
+        new_path = activator._add_prefix_to_path(test_prefix, path_dirs)
+        assert new_path[:len(added_paths)] == added_paths
+        assert new_path[-len(path_dirs):] == path_dirs
+        assert len(new_path) == len(added_paths) + len(path_dirs) + 1
+        assert new_path[len(added_paths)].endswith("condacmd")
+
     def test_remove_prefix_from_path_1(self):
         activator = PosixActivator()
         original_path = tuple(activator._get_starting_path_list())