rubygems / rubygems

Library packaging and distribution for Ruby.
https://rubygems.org/
Other
3.68k stars 1.75k forks source link

Windows + Git Bash = Cannot call gem executable directly (No such file or directory) #7856

Closed sergio-bobillier closed 1 week ago

sergio-bobillier commented 4 months ago

Describe the problem as clearly as you can

After updating one of our instances from Ruby 2.7.7 to Ruby 3.3.4 I noticed that simple things, like running bundler check started to fail. I wasn't expecting this. Here is the description of the issue:

When trying to run a gem executable from Git Bash in Windows i"m getting a No such file or directory error. At first I thought this was related to the fact that I was using Scoop to install ruby so I switched to the Ruby Installer but there I got the same behaviour so it seems that Scoop wasn't involved there.

To reproduce the issue you can do the following:

(Under Windows)

  1. Install a gem that includes an executable, for example pry (It doesn't matter if you install it from the Windows CLI or Git Bash, the result is the same)
  2. Under Windows Command Line or Power Shell running the gem executable: pry works.
  3. From git-bash I'm getting the following error:
Sergio Bobillier@DESKTOP-42FVDCQ MINGW64 ~
$ pry
/c/Users/sergio/AppData/Local/Microsoft/WindowsApps/pry: line 6: /c/Users/sergio/AppData/Local/Microsoft/WindowsApps/ruby: No such file or directory

👉 One important detail here is that it is trying to search for ruby in the path where the gem executables are located and not in the path where the Ruby interpreter is actually installed, which is C:\Ruby33-x64\bin\ruby.exe

I can work around this by calling pry.bat, then it works (although it raises different error related to IO, unrelated to this issue). But for example, it can print its version:

Sergio Bobillier@DESKTOP-42FVDCQ MINGW64 ~
$ pry.bat --version
Pry version 0.14.2 on Ruby 3.3.4

The issue seems to be related to the Bash Prolog Script, which I tracked down to here: https://github.com/rubygems/rubygems/blob/e71bef01f2f57055176c625e6f5eb468bd1f6c9a/lib/rubygems/installer.rb#L1008

I managed to make this work by editing the executable file like this:

 =begin
 bindir="${0%/*}"
-exec "$bindir/ruby" "-x" "$0" "$@"
+exec "ruby" "-x" "$0" "$@"
 =end

So, basically running just ruby instead of using the full path. That also works. But of course changing the executables does not seem to be a good idea. Plus it would be maintenance hell, but it does work:

Sergio Bobillier@DESKTOP-42FVDCQ MINGW64 ~
$ pry --version
Pry version 0.14.2 on Ruby 3.3.4

Did you try upgrading RubyGems?

Yes, I tried to update Rubygems, but the behaviour is the same:

PS C:\Users\sergio> gem --version
3.5.15

Post steps to reproduce the problem

Steps to reproduce the issue are provided as part of the issue description.

Which command did you run?

Trying to run any gem executable with git-bash causes the issue.

What were you expecting to happen?

I would expect them to run without any issue, just like they were doing in Ruby 2.7.7 (rubygems 3.1.6)

What actually happened?

Exactly what I described, the "No such file or directory" error.

Run gem env and paste the output below

RubyGems Environment:
  - RUBYGEMS VERSION: 3.5.15
  - RUBY VERSION: 3.3.4 (2024-07-09 patchlevel 94) [x64-mingw-ucrt]
  - INSTALLATION DIRECTORY: C:/Users/sergio/.gem/ruby/3.3.0
  - USER INSTALLATION DIRECTORY: C:/Users/sergio/.gem/ruby/3.3.0
  - RUBY EXECUTABLE: C:/Ruby33-x64/bin/ruby.exe
  - GIT EXECUTABLE: C:\Program Files\Git\cmd/git.EXE
  - EXECUTABLE DIRECTORY: C:/Users/sergio/.gem/ruby/3.3.0/bin
  - SPEC CACHE DIRECTORY: C:/Users/sergio/.gem/specs
  - SYSTEM CONFIGURATION DIRECTORY: C:/ProgramData
  - RUBYGEMS PLATFORMS:
     - ruby
     - x64-mingw-ucrt
  - GEM PATHS:
     - C:/Users/sergio/.gem/ruby/3.3.0
     - C:/Ruby33-x64/lib/ruby/gems/3.3.0
  - GEM CONFIGURATION:
     - :update_sources => true
     - :verbose => true
     - :backtrace => true
     - :bulk_threshold => 1000
     - "gem" => ["--install-dir", "C:/Users/sergio/.gem/ruby/3.3.0", "--bindir", "C:/Users/sergio/AppData/Local/Microsoft/WindowsApps"]
     - "# Feel free to add any rubygems config options as described on" => nil
  - REMOTE SOURCES:
     - https://rubygems.org/
  - SHELL PATH:
     - C:\Ruby33-x64\bin
     - C:\WINDOWS\system32
     - C:\WINDOWS
     - C:\WINDOWS\System32\Wbem
     - C:\WINDOWS\System32\WindowsPowerShell\v1.0\
     - C:\WINDOWS\System32\OpenSSH\
     - C:\Program Files\Git\cmd
     - C:\Program Files\PowerShell\7\
     - C:\Program Files\Git\bin
     - C:\Program Files\Git\usr\bin
     - C:\Users\sergio\scoop\shims
     - C:\Users\sergio\AppData\Local\Microsoft\WindowsApps
     - C:\Users\sergio\AppData\Local\Programs\Microsoft VS Code\bin
deivid-rodriguez commented 3 months ago

Thanks for reporting @sergio-bobillier.

I guess this was introduced by https://github.com/rubygems/rubygems/pull/2929.

In that PR I basically tried to generate the same kind of binstub that Ruby generates by default. So essentially copied this logic from ruby-core installer:

https://github.com/ruby/ruby/blob/690ea013cac2d3c4eb149c8e7e5d794dfe874abe/tool/rbinstall.rb#L399-L427

Honestly, I'm not sure I fully understand the --enable-load-relative ruby configuration option, or why it's enabled by default on Windows. I think it'd be fine if we'd just run Gem.ruby here and not assume ruby is installed in the same directory as the binstub, but I'd like to make sure this makes sense from ruby-core side, and we can change their install script too.

@nobu Do you have any thoughts/ideas about this?

deivid-rodriguez commented 3 months ago

I was able to reproduce this by installing ruby with --enable-load-relative, then installing a gem like this gem install pry --bindir ~/.gem/ruby/3.3.0/bin.

Then running PATH=$PATH:~/.gem/ruby/3.3.0/bin pry leads to the following errors:

$ PATH=$PATH:~/.gem/ruby/3.3.0/bin pry
/Users/deivid/.gem/ruby/3.3.0/bin/pry: line 6: /Users/deivid/.gem/ruby/3.3.0/bin/ruby: No such file or directory
/Users/deivid/.gem/ruby/3.3.0/bin/pry: line 6: exec: /Users/deivid/.gem/ruby/3.3.0/bin/ruby: cannot execute: No such file or directory

https://github.com/rubygems/rubygems/pull/7872 could be a potential fix.