Repository: xonsh/xonsh

Issue:
xonsh: subprocess mode: permission denied when overriding a PATH command with an alias on Windows
<!--- Provide a general summary of the issue in the Title above -->
<!--- If you have a question along the lines of "How do I do this Bash command in xonsh"
please first look over the Bash to Xonsh translation guide: https://xon.sh/bash_to_xsh.html
If you don't find an answer there, please do open an issue! -->

## xonfig

<details>

```
$ xonfig
+------------------+----------------------+
| xonsh            | 0.13.0.dev4          |
| Git SHA          | 0214b878             |
| Commit Date      | Jul 14 14:51:40 2022 |
| Python           | 3.10.5               |
| PLY              | 3.11                 |
| have readline    | False                |
| prompt toolkit   | 3.0.29               |
| shell type       | prompt_toolkit       |
| history backend  | json                 |
| pygments         | 2.10.0               |
| on posix         | False                |
| on linux         | False                |
| on darwin        | False                |
| on windows       | True                 |
| on cygwin        | False                |
| on msys2         | False                |
| is superuser     | False                |
| default encoding | utf-8                |
| xonsh encoding   | utf-8                |
| encoding errors  | surrogateescape      |
| xontrib          | []                   |
| RC file          | []                   |
+------------------+----------------------+
```

</details>

## Expected Behavior
<!--- Tell us what should happen -->

Overriding a command in PATH with an alias (such as to add default arguments) should work as it does on Linux and macOS.

```xonsh
$ aliases['python'] = 'python -u'
$ python --help
Usage: [snip]
```

## Current Behavior
<!--- Tell us what happens instead of the expected behavior -->
<!--- If part of your bug report is a traceback, please first enter debug mode before triggering the error
To enter debug mode, set the environment variable `XONSH_DEBUG=1` _before_ starting `xonsh`.
On Linux and OSX, an easy way to to do this is to run `env XONSH_DEBUG=1 xonsh` -->

```xonsh
$ aliases['python'] = 'python -u'
$ python --help
xonsh: subprocess mode: permission denied
```

## Steps to Reproduce
<!--- Please try to write out a minimal reproducible snippet to trigger the bug, it will help us fix it! -->

```xonsh
$ aliases['python'] = 'python -u'
$ python --help
```

## Notes

Interestingly, this *does* work if you append the extension in the alias, eg: `aliases['python'] = 'python.exe -u'` does work.

## For community
⬇️  **Please click the 👍 reaction instead of leaving a `+1` or 👍  comment**



Discussion:
hi! It also works if the name of the alias is not the same as in command i.e. `aliases['py'] = 'python -u'`.

I think this issue partially related to #4218. There is the lack of some logic for Windows.
Yep, it only fails if you're overriding an existing command.

That would make sense. I'll try to look into the related code a bit later, thank you.
Just want to mention #4566 as another task around support Windows in #4218

Resolving patch:
diff --git a/xonsh/commands_cache.py b/xonsh/commands_cache.py
--- a/xonsh/commands_cache.py
+++ b/xonsh/commands_cache.py
@@ -145,11 +145,18 @@ def update_cache(self):
 
             # aliases override cmds
             for cmd in self.aliases:
-                key = cmd.upper() if ON_WINDOWS else cmd
-                if key in all_cmds:
+                # Get the possible names the alias could be overriding,
+                # and check if any are in all_cmds.
+                possibilities = self.get_possible_names(cmd)
+                override_key = next(
+                    (possible for possible in possibilities if possible in all_cmds),
+                    None,
+                )
+                if override_key:
                     # (path, False) -> has same named alias
-                    all_cmds[key] = (all_cmds[key][0], False)
+                    all_cmds[override_key] = (all_cmds[override_key][0], False)
                 else:
+                    key = cmd.upper() if ON_WINDOWS else cmd
                     # True -> pure alias
                     all_cmds[key] = (cmd, True)
             self._cmds_cache = all_cmds


Test patch: