oneclick / rubyinstaller2

MSYS2 based RubyInstaller for Windows
https://rubyinstaller.org
BSD 3-Clause "New" or "Revised" License
645 stars 248 forks source link

bin/bundle not present or working in bash for some RubyInstaller2 releases #299

Open eregon opened 1 year ago

eregon commented 1 year ago

What problems are you experiencing?

This is from https://github.com/ruby/setup-ruby/issues/371. bundle does not work in a Bash shell on Windows -- without an extra gem install bundler --, and the reason is some RubyInstaller2 releases either do not ship with a bin/bundle, it has the wrong permissions and the wrong start.

Steps to reproduce

I downloaded all latest releases from https://github.com/ruby/setup-ruby/blob/master/windows-versions.json and extracted them (I'm on Linux FWIW).

$ ls
rubyinstaller-2.4.10-1-x64     rubyinstaller-2.6.10-1-x64     rubyinstaller-3.0.4-1-x64     rubyinstaller-head-x64     ruby-mswin
rubyinstaller-2.4.10-1-x64.7z  rubyinstaller-2.6.10-1-x64.7z  rubyinstaller-3.0.4-1-x64.7z  rubyinstaller-head-x64.7z  ruby-mswin.7z
rubyinstaller-2.5.9-1-x64      rubyinstaller-2.7.6-1-x64      rubyinstaller-3.1.2-1-x64     ruby-mingw                 ruby-ucrt
rubyinstaller-2.5.9-1-x64.7z   rubyinstaller-2.7.6-1-x64.7z   rubyinstaller-3.1.2-1-x64.7z  ruby-mingw.7z              ruby-ucrt.7z

Of course only Ruby 2.7+ ships with Bundler, so for <=2.6 it's expected to be missing.

$ ls -l */bin/bundle
-rw-r--r--. 1 eregon eregon 707 Apr 19 22:22 rubyinstaller-3.1.2-1-x64/bin/bundle
-rw-r--r--. 1 eregon eregon 707 Aug 19 22:40 rubyinstaller-head-x64/bin/bundle
-rw-rw-rw-. 1 eregon eregon 564 Aug 20 11:15 ruby-mingw/bin/bundle
-rw-rw-rw-. 1 eregon eregon 829 Aug 20 11:09 ruby-mswin/bin/bundle
-rw-rw-rw-. 1 eregon eregon 564 Aug 20 11:20 ruby-ucrt/bin/bundle

So only 3.1 and head have bin/bundle. But those 2 bin/bundle do not have the executable bit set. They also start like this which sounds invalid for Bash:

$ cat rubyinstaller-3.1.2-1-x64/bin/bundle
:""||{ ""=> %q<-*- ruby -*-
@"%~dp0ruby" -x "%~f0" %*
@exit /b %ERRORLEVEL%
};{ #
bindir="${0%/*}" #
exec "$bindir/ruby" "-x" "$0" "$@" #
>,
}
#!/usr/bin/env ruby
#
# This file was generated by RubyGems.
...

On https://github.com/eregon/setup-ruby/runs/7843304711?check_suite_focus=true we can see 3.0, 3.1 and head fail for echo ~ && which -a bundle in bash. 2.7 avoids the issue in that CI run because the Bundler version is considered too old by setup-ruby and so gem install bundler is done there.

This may be a CRuby issue, I am not sure (EDIT: most likely, I filed https://bugs.ruby-lang.org/issues/18970).

Maybe related to https://github.com/oneclick/rubyinstaller2/issues/180


mswin also fails but that's a build from @MSP-Greg. bin/bundle exists and is executable, but the contents looks not valid for Bash:

$ cat ruby-mswin/bin/bundle
:""||{ ""=> %q<-*- ruby -*-
@"%~dp0ruby" -x "%~f0" %*
@exit /b %ERRORLEVEL%
};{ #
bindir="D:/a/ruby-loco/ruby-loco/ruby-mswin/bin" #
libdir="D:/a/ruby-loco/ruby-loco/ruby-mswin/lib" #
export PATH="$libdir${PATH:+;$PATH}" #
exec "$bindir/ruby" "-x" "$0" "$@" #
>,
}
#!/usr/bin/env ruby
#
# This file was generated by RubyGems.
...

mingw and ucrt builds by @MSP-Greg do work, and their bin/bundle starts like:

$ cat ruby-mingw/bin/bundle
#!/usr/bin/env ruby
#
# This file was generated by RubyGems.
...
eregon commented 1 year ago

@MSP-Greg Could you show what bin/bundle looks like on mswin, head or 3.1 after gem install bundler? I guess it starts with #!/usr/bin/env ruby like the file on mingw/ucrt?

eregon commented 1 year ago

Actually it must be a CRuby bug, at least for the header if bin/bundle: https://bugs.ruby-lang.org/issues/18970

Does RubyInstaller2 do anything special about bin/bundle etc?

MSP-Greg commented 1 year ago

Actually it must be a CRuby bug

Yes, it hard codes the path in the bash binstub. Maybe the fix should be something packagers (Lars & myself) handle?

I did look at this, and the question is how should bash binstubs behave if one has multiple Ruby installs. IOW, Ruby A is in PATH, but one runs the binstub in Ruby B?

Or, should we just make all bash binstubs start with the following?

#!/usr/bin/env ruby
eregon commented 1 year ago

I did look at this, and the question is how should bash binstubs behave if one has multiple Ruby installs. IOW, Ruby A is in PATH, but one runs the binstub in Ruby B?

IMHO this never works properly (one need the given Ruby first in PATH, and using an absolute path to a binstub feels wrong anyway), and specifically it does not work for new executables installed by gems, which will just start with #!/usr/bin/env ruby. Maybe for bin/gem it's reasonable to look at the sibling bin/ruby, but for any gem binstub I think it should be exactly the same as if RubyGems installed it, so there is no difference between gems shipped-with-Ruby-and-not-reinstalled-yet and all other gems.

Or, should we just make all bash binstubs start with the following?

I think so, yes.

eregon commented 1 year ago

More findings on https://bugs.ruby-lang.org/issues/18970, notably 3.0.4 does not have bin/bundle and bin/bundle.bat, only bin/bundle.cmd.