Bug 249083 - devel/ruby-gems fails to install if /usr/local is a symlink
Summary: devel/ruby-gems fails to install if /usr/local is a symlink
Status: New
Alias: None
Product: Ports & Packages
Classification: Unclassified
Component: Individual Port(s) (show other bugs)
Version: Latest
Hardware: Any Any
: --- Affects Only Me
Assignee: freebsd-ruby (Nobody)
Depends on:
Reported: 2020-09-03 17:30 UTC by Eric W.Bates
Modified: 2022-12-09 10:59 UTC (History)
2 users (show)

See Also:
bugzilla: maintainer-feedback? (ruby)


Note You need to log in before you can comment on or make changes to this bug.
Description Eric W.Bates 2020-09-03 17:30:46 UTC
If one has moved /usr/local to a separate file system and symlink'ed it to it's original location (e.g.: /usr/ports - > /u1/usr-local ), then during install the commands:

/bin/mkdir -p /usr/ports/devel/ruby-gems/work/stage/usr/local/lib/ruby/gems/2.6
cd /usr/ports/devel/ruby-gems/work/rubygems-3.0.6/ && /usr/bin/env DONT_USE_BUNDLER_FOR_GEMDEPS=true G
EM_HOME=/usr/ports/devel/ruby-gems/work/stage/usr/local/lib/ruby/gems/2.6 /usr/local/bin/ruby26 setup.
rb --destdir=/usr/ports/devel/ruby-gems/work/stage --no-regenerate-binstubs --no-ri --no-rdoc

causes the creation of two trees in ./stage:

./stage/usr/local... [everything else]

Only the script gem26 appears in the path ./u1/usr-local/.., but that's sufficient for the install to fail with:

pkg-static: Unable to access file /usr/ports/devel/ruby-gems/work/stage/usr/local/bin/gem26:No such fi
le or directory

My work-around was to "make" "mv u1/usr-local/bin/gem26 usr/local/bin/" "make install"

I believe this is a bug in the ruby script 'setup,' but I have never learned ruby.
Comment 1 parv 2021-05-14 15:03:21 UTC
This still happens with ruby 2.7 & ruby-gems 3.0.8.
Comment 2 parv 2021-05-14 15:05:35 UTC
(In reply to parv from comment #1)

I should have added the output from the attempt ...

RubyGems installed the following executables:

Ruby Interactive (ri) documentation was installed. ri is kind of like man 
pages for Ruby libraries. You may access it like this:
  ri Classname
  ri Classname.class_method
  ri Classname#instance_method
If you do not wish to install this documentation in the future, use the
--no-document flag, or set it as the default in your ~/.gemrc file. See
'gem help env' for details.

/bin/ln -sf gem27 /src-build/ports-build/src-build/ports/devel/ruby-gems/work/stage/usr/local/bin/gem
cd /src-build/ports-build/src-build/ports/devel/ruby-gems/work/stage/usr/local/ && /usr/bin/find -ds lib/ruby/gems/2.7/doc/rubygems-3.0.8/ ! -type d >> /src-build/ports-build/src-build/ports/devel/ruby-gems/work/.PLIST.mktmp
====> Compressing man pages (compress-man)
===>  Installing for ruby27-gems-3.0.8
===>  Checking if ruby27-gems is already installed
===>   Registering installation for ruby27-gems-3.0.8
pkg-static: Unable to access file /src-build/ports-build/src-build/ports/devel/ruby-gems/work/stage/usr/local/bin/gem27:No such file or directory
*** Error code 1

make: stopped in /src-build/ports/devel/ruby-gems
Comment 3 titus m 2022-12-09 10:59:11 UTC
if setup.rb is run without --prefix then bindir is taken from ruby config
and then it prepends the destdir
problem is that bindir from config is canonic (with symlinks resolved)
so you end up with a stage dir containing ..../usr/local/stuff
and ..../usr/reallocal/stuff
--- /tmp/Makefile    2022-12-09 12:01:45.050912000 +0200
+++ Makefile    2022-12-09 12:24:40.557735000 +0200
@@ -6,6 +6,8 @@
 DIST_SUBDIR=    ruby
 MAINTAINER=    ruby@FreeBSD.org
 COMMENT=    Package management framework for the Ruby language
 WWW=        https://rubygems.org/
@@ -72,3 +74,7 @@
     cd ${STAGEDIR}${PREFIX}/ && ${FIND} -ds ${DOC_DIR}/ ! -type d >> ${TMPPLIST}
 .include <bsd.port.mk>
+REAL_PREFIX!=   realpath ${PREFIX}
+.if ${REAL_PREFIX} != ${PREFIX}

and add this diff file in files/patch-fix-linked-local
--- lib/rubygems/commands/setup_command.rb.orig    2022-12-09 12:22:16.123948000 +0200
+++ lib/rubygems/commands/setup_command.rb    2022-12-09 12:22:34.331107000 +0200
@@ -448,10 +448,14 @@
   def generate_default_dirs
     prefix = options[:prefix]
     site_or_vendor = options[:site_or_vendor]
+    xxx_bin = ENV["GEM_XXX_BIN"]
     if prefix.empty?
       lib_dir = RbConfig::CONFIG[site_or_vendor]
       bin_dir = RbConfig::CONFIG["bindir"]
+      if xxx_bin && !xxx_bin.empty?
+      bin_dir = xxx_bin
+      end
       lib_dir = File.join prefix, "lib"
       bin_dir = File.join prefix, "bin"