`Gem.unpack` extracts gems so able to execute

Creates simple bin stubs to load the extracted executable files.
After only extracted under `gems` directory, the gems are considered
installed but the executable scripts are not found.
Also the second argument is now the parent of the previous second and
third arguments.
This commit is contained in:
Nobuyoshi Nakada 2022-07-17 16:05:16 +09:00
Родитель fab8f3bde6
Коммит 64cff78005
3 изменённых файлов: 22 добавлений и 17 удалений

Просмотреть файл

@ -1360,13 +1360,11 @@ extract-gems$(gnumake:yes=-nongnumake): PHONY
$(ECHO) Extracting bundled gem files...
$(Q) $(RUNRUBY) -C "$(srcdir)" \
-Itool -rfileutils -rgem-unpack -answ \
-e 'BEGIN {FileUtils.mkdir_p(d = ".bundle/gems")}' \
-e 'BEGIN {FileUtils.mkdir_p(s = ".bundle/specifications")}' \
-e 'BEGIN {d = ".bundle/gems"}' \
-e 'gem, ver = *$$F' \
-e 'next if !ver or /^#/=~gem' \
-e 'g = "#{gem}-#{ver}"' \
-e 'File.directory?("#{d}/#{g}") or Gem.unpack("gems/#{g}.gem", d, s)' \
-e 'FileUtils.rm_rf("#{d}/#{g}/.github")' \
-e 'File.directory?("#{d}/#{g}") or Gem.unpack("gems/#{g}.gem", ".bundle")' \
gems/bundled_gems
update-bundled_gems: PHONY

Просмотреть файл

@ -298,8 +298,7 @@ extract-gems: | $(patsubst %,.bundle/gems/%,$(bundled-gems))
$(ECHO) Extracting bundle gem $*...
$(Q) $(BASERUBY) -C "$(srcdir)" \
-Itool -rgem-unpack \
-e 'Gem.unpack("gems/$(@F).gem", ".bundle/gems", ".bundle/specifications")'
$(RMALL) "$(srcdir)/$(@:.gem=)/".git*
-e 'Gem.unpack("gems/$(@F).gem", ".bundle")'
$(srcdir)/.bundle/gems:
$(MAKEDIRS) $@

Просмотреть файл

@ -5,22 +5,30 @@ require 'rubygems/package'
# This library is used by "make extract-gems" to
# unpack bundled gem files.
def Gem.unpack(file, dir = nil, spec_dir = nil)
def Gem.unpack(file, dir = ".")
pkg = Gem::Package.new(file)
spec = pkg.spec
target = spec.full_name
target = File.join(dir, target) if dir
pkg.extract_files target
if spec.extensions.empty?
spec_dir ||= target
else
spec_dir = target
end
FileUtils.mkdir_p(spec_dir)
File.binwrite(File.join(spec_dir, "#{spec.name}-#{spec.version}.gemspec"), spec.to_ruby)
Gem.ensure_gem_subdirectories(dir)
gem_dir = File.join(dir, "gems", target)
pkg.extract_files gem_dir
spec_dir = spec.extensions.empty? ? "specifications" : File.join("gems", target)
File.binwrite(File.join(dir, spec_dir, "#{target}.gemspec"), spec.to_ruby)
unless spec.extensions.empty?
spec.dependencies.clear
File.binwrite(File.join(spec_dir, ".bundled.#{spec.name}-#{spec.version}.gemspec"), spec.to_ruby)
File.binwrite(File.join(dir, spec_dir, ".bundled.#{target}.gemspec"), spec.to_ruby)
end
if spec.bindir and spec.executables
bindir = File.join(dir, "bin")
Dir.mkdir(bindir) rescue nil
spec.executables.each do |exe|
File.open(File.join(bindir, exe), "wb", 0o777) {|f|
f.print "#!ruby\n",
%[load File.realpath("../gems/#{target}/#{spec.bindir}/#{exe}", __dir__)\n]
}
end
end
FileUtils.rm_rf(Dir.glob("#{gem_dir}/.git*"))
puts "Unpacked #{file}"
end