vscode-gitlens icon indicating copy to clipboard operation
vscode-gitlens copied to clipboard

MSYS2 git causes Error: spawn C:/msys64/usr/bin/git.exe ENOENT due to path format

Open Kwizatz opened this issue 5 years ago • 17 comments

Issue Type: Bug

Setting git.path to use git from a msys2 instalation ("C:/msys64/usr/bin/git.exe") causes extension to fail with the error:

Error: spawn C:/msys64/usr/bin/git.exe ENOENT

I have tracked the root cause for this to be that msys2 git prints paths in Unix format rather than Windows format unlike Git for Windows.

git rev-parse --show-toplevel prints /c/Code/AeonGUI on msys2 git, but prints C:/Code/AeonGUI on Git for Windows.

This happens regardless of if the command is issued from inside bash or cmd.exe.

I looked for external solutions, an env var that could be set or a git config setting but found nothing other than calling cygpath -w "$(git rev-parse --show-toplevel)", which is not usable as a git.path or any other setting.

Steps to reproduce:

  1. Install MSYS2 from https://www.msys2.org
  2. Run MSYS2 bash for MinGW64
  3. Install git: pacman -S git
  4. Run vscode
  5. Set "git.path": "C:/msys64/usr/bin/git.exe" on settings.js
  6. Close and rerun vscode and open a file in a git repository
  7. The extension will likely fail at this point, but clicking the extension icon on the left pane will trigger more failures

Extension version: 10.2.1 VS Code version: Code 1.42.1 (c47d83b293181d9be64f27ff093689e8e7aed054, 2020-02-11T14:45:59.656Z) OS version: Windows_NT x64 10.0.18363

GitlensLog.txt GitlensGitLog.txt

Kwizatz avatar Feb 21 '20 17:02 Kwizatz

This isn't something that I will likely fix myself, but if the community wants to provide a PR I'm certainly open to it -- depending on the complexity and scope of the changes required.

eamodio avatar Feb 21 '20 18:02 eamodio

I'd do it myself if I knew enough TypeScript, but sadly I don't.

It should be an easy solution to do something like this on all cases were a path is expected from git (bash script):

path=git rev-parse --show-toplevel path=cygpath -w "$path"

This would go next to where you normalize the paths.

However, the path to cygpath becomes an issue, you would need to add a setting like say gitlens.cygpath, in order to be able to use cygpath without forcing C:/msys64/usr/bin to be in the PATH.

PS: By the way, Git For Windows also installs cygpath, so it wouldn't make a difference if the command gets called on git for windows installations.

Kwizatz avatar Feb 21 '20 20:02 Kwizatz

It gets tricky and on top of it I don't use msysgit, so even if I put a patch together for what I think might work, I don't have a setup to test it.

eamodio avatar Feb 21 '20 20:02 eamodio

If you can quickly brew an initial patch, I may be able to test and expand on it, I think just figuring out how you span processes and store their output should be enough.

Kwizatz avatar Feb 21 '20 20:02 Kwizatz

I've hit this same issue, has there been a solution found? Current workaround to install git separately and use that executable, also checking path to ensure correct order.

PMARINA avatar Jul 10 '20 02:07 PMARINA

I also get the same issue. To use 'git' installed in MSYS2, I have employed the following bath shell (suggested by mattn) to covert the /c/ prefixed-path for rev-parse command.

@echo off
setlocal

rem If you don't add path for msys2 into %PATH%, enable following line.
rem set PATH=c:\msys64\usr\bin;%PATH%

if "%1" equ "rev-parse" goto rev_parse
git %*
goto :eof
:rev_parse
for /f %%1 in ('git %*') do cygpath -w %%1

However, the issue still exists. Looking forward to the solution.

niukai10 avatar Aug 13 '20 02:08 niukai10

Edited:

I am having the same problem as @xjtunk.

The git-wrap.bat suggested by @mattn is only converting path if th efirst argument is rev-parse, but gitlens calls git with a few additional args

if "%1" equ "rev-parse" goto rev_parse

Thus resulting:

>git rev-parse --show-toplevel
D:\Desktop\Program\Gits\vscode-gitlens

>git -c core.longpaths=true rev-parse --show-toplevel
/d/Desktop/Program/Gits/vscode-gitlens

However, I tried to fix this but windows keeps recognizing core.longpaths=true as two args core.longpaths and true in ('git %*') line

Temporary solution:

@echo off
setlocal

rem If you don't add path for msys2 into %PATH%, enable following line.
rem set PATH=c:\msys64\usr\bin;%PATH%

rem https://stackoverflow.com/a/39776524/8810271

:loop
if "%~1" equ "rev-parse" goto rev_parse
shift
if not "%~1"=="" goto loop

git.exe %*
goto :eof

:rev_parse
git.exe %* | cygpath -w -f -

AllanChain avatar Nov 26 '20 00:11 AllanChain

@AllanChain Thanks a lot, very helpful.

eshepelyuk avatar May 13 '21 14:05 eshepelyuk

Thanks a lot, it works

frankche88 avatar Sep 10 '21 18:09 frankche88

@AllanChain @frankche88 @eshepelyuk where should this script be in?

ronnaf avatar Oct 25 '21 20:10 ronnaf

@ronnaf

"git.path": "D:/msys64/usr/bin/git-wrap.bat"

.git-wrap.bat

setlocal

:loop if "%~1" equ "rev-parse" goto rev_parse shift if not "%~1"=="" goto loop

git.exe %* goto :eof

:rev_parse git.exe %* | cygpath -w -f -


frankche88 avatar Oct 25 '21 21:10 frankche88

@frankche88 thank you!

ronnaf avatar Oct 25 '21 21:10 ronnaf

https://github.com/microsoft/vscode/pull/134146

Maybe this issue will fix this problem, and it's WIP. The git-wrapper solution is temporary.

hayden-pan avatar Aug 30 '22 04:08 hayden-pan

@aaftio There is already a PR to fix this #1659. Just fyi the vscode PR does not resolve the issue in vscode-gitlens

zcsizmadia avatar Aug 30 '22 21:08 zcsizmadia

@zcsizmadia OK, thanks for your tips. Cygwin git works with IntelliJ Idea well, I am not sure Idea have use the "git rev-parse ..." or not. But I am worry about if there is some other git sub-command which will return the file system path and used by vscode-git or gitlens. And the Cygwin-style path problem raise again.

hayden-pan avatar Aug 31 '22 02:08 hayden-pan

re @frankche88's and @AllanChain's scripts, while it works great it can get slow on longer commands and especially on large outputs thanks to the looping. A bit of chopping both up and some magic of my own goes a long way into making some speed improvements though - about 150ms per call on my work machine.

@echo off
setlocal

set "args=%*"

if "%args:rev-parse=x%" neq "%args%" goto rev_parse
git %*
goto :halt
:rev_parse
git %* | cygpath -wf -

:halt
EXIT /B

The main trick here is having to dump %* in a variable since string substitution won't work on it. Then it's just comparing with string substitution which tends to be faster than looping. Beware not to use cygpath's -a option though, as this will use the current working directory to create the "absolute" path, which only works if the command execution context (workspace root) is the same as the top-level git dir

RivenSkaye avatar Nov 28 '23 08:11 RivenSkaye