[packages/ruby/rawhide] up to 4.0.7
mis
mis at pld-linux.org
Mon Sep 28 19:48:52 CEST 2026
commit a2d943d7d36f59ca00a640f2dd0970b49e0f3165
Author: Pawel Gajda <mis at pld-linux.org>
Date: Mon Sep 28 19:47:36 2026 +0200
up to 4.0.7
duplicated-paths.patch | 80 -
extract-gem-versions.sh | 12 +-
fix-bison-invocation.patch | 10 -
mkmf-verbose.patch | 25 -
openssl3.patch | 12 -
operating_system.rb | 12 +
...pr1531-fix-mutilple-document-installation.patch | 28 +
...-2.1.0-Enable-configuration-of-archlibdir.patch | 7 +-
...dd-ruby_version_dir_name-support-for-RDoc.patch | 22 +
ruby-2.3.0-ruby_version.patch | 43 +-
ruby-2.7.0-Initialize-ABRT-hook.patch | 32 +-
...build-extension-libraries-in-bundled-gems.patch | 338 --
ruby-3.4.2-openssl-Fix-SHA-1-PSS-tests.patch | 136 -
...customizable-rustc_flags-for-rustc-builds.patch | 117 +
...0.7-rubygems-pr9877-stop-vendoring-resolv.patch | 3579 ++++++++++++++++++++
ruby.spec | 332 +-
strip-ccache.patch | 9 +-
17 files changed, 4003 insertions(+), 791 deletions(-)
---
diff --git a/ruby.spec b/ruby.spec
index f98cc32..a903b9d 100644
--- a/ruby.spec
+++ b/ruby.spec
@@ -1,23 +1,17 @@
-# TODO:
-# - include ext/ in docs
-# - replace ri with fastri
-# - patch ri to search multiple indexes (one per package), so RPMs can install ri docs
-# - gemify irb (?)
-#
# Conditional build:
%bcond_without doc # skip (time-consuming) docs generating; intended for speed up test builds
%bcond_without batteries # Don't include rubygems, json, rake, minitest
%bcond_without default_ruby # use this Ruby as default system Ruby
-%bcond_with dtrace # disable tracing with dtrace
+%bcond_without dtrace # disable tracing with dtrace
%bcond_with bootstrap # build bootstrap version
%bcond_with tests # build with tests
-%define rel 4
-%define ruby_version 3.4
-%define patchlevel 11
+%define rel 1
+%define ruby_version 4.0
+%define patchlevel 7
%define pkg_version %{ruby_version}.%{patchlevel}
%define ruby_suffix %{!?with_default_ruby:%{ruby_version}}
-%define unicode_version 12.1.0
+%define unicode_version 17.0.0
%define oname ruby
Summary: Ruby - interpreted scripting language
Summary(ja.UTF-8): オブジェクト指向言語Rubyインタプリタ
@@ -55,10 +49,15 @@ Patch4: %{name}-2.1.0-custom-rubygems-location.patch
Patch6: %{name}-2.7.0-Initialize-ABRT-hook.patch
# Disable syntax_suggest test suite, which tries to download its dependencies.
# https://bugs.ruby-lang.org/issues/19297
-Patch9: %{name}-3.3.0-Disable-syntax-suggest-test-case.patch
-# Fix the tests using SHA-1 Probabilistic Signature Scheme (PSS) parameters.
-# https://github.com/ruby/openssl/pull/879
-Patch10: %{name}-3.4.2-openssl-Fix-SHA-1-PSS-tests.patch
+Patch7: %{name}-3.3.0-Disable-syntax-suggest-test-case.patch
+# Allow the rustc flags used for YJIT to be overridden.
+Patch10: %{name}-4.0.1-Support-customizable-rustc_flags-for-rustc-builds.patch
+# Add ruby_version_dir_name support for RDoc (patched inside the bundled gem).
+Patch11: %{name}-2.3.0-ruby_version-Add-ruby_version_dir_name-support-for-RDoc.patch
+# rdoc PR 1531: fix installation of multiple documents.
+Patch12: rdoc-pr1531-fix-mutilple-document-installation.patch
+# Stop vendoring resolv for two regexps (ruby/rubygems PR 9877).
+Patch13: %{name}-4.0.7-rubygems-pr9877-stop-vendoring-resolv.patch
URL: http://www.ruby-lang.org/
BuildRequires: autoconf >= 2.67
BuildRequires: automake
@@ -103,7 +102,7 @@ BuildRoot: %{tmpdir}/%{name}-%{version}-root-%(id -u -n)
# relative symlinks
# usage: %make_rel_symlink <target-in-install-root> [<directory> [<link-name>]]
-# e.g. %make_rel_symlink %{gem_instdir rdoc}/lib/rdoc %{ruby_libdir}
+# e.g. %%make_rel_symlink %%{gem_instdir rdoc}/lib/rdoc %%{ruby_libdir}
# creates <directory>/<link-name> as a symlink holding the shortest relative
# path to <target>, so that it stays valid after installation. <link-name>
# defaults to the basename of <target>.
@@ -112,54 +111,62 @@ BuildRoot: %{tmpdir}/%{name}-%{version}-root-%(id -u -n)
# hack: skip rubygem(ipaddr)
%define _noautoreq ipaddr
+# ruby(abi) replaced by ruby(release)
%{expand:%%global _noautoreq %{_noautoreq} 'ruby\\(abi\\)'}
%{expand:%%global _noautoprov %{?nil} 'ruby\\(abi\\)'}
# Bundled libraries versions
-%define rubygems_version 3.6.9
+%define rubygems_version 4.0.20
# Default gems.
-%define bundler_version 2.6.9
-%define erb_version 4.0.4.1
+%define bundler_version 4.0.20
+%define erb_version 6.0.7
-%define io_console_version 0.8.1
-%define irb_version 1.14.3
-%define json_version 2.9.1
-%define psych_version 5.2.2
-%define rdoc_version 6.14.0
+%define io_console_version 0.8.2
+%define irb_version 1.16.0
+%define json_version 2.18.0
+%define psych_version 5.3.1
+%define rdoc_version 7.0.4
%define syntax_suggest_version 2.0.3
+%define benchmark_version 0.5.0
+%define fiddle_version 1.1.8
+%define logger_version 1.7.0
+%define ostruct_version 0.6.3
+%define pstore_version 0.2.1
+%define readline_version 0.0.4
+%define reline_version 0.6.3
# Bundled gems.
%define abbrev_version 0.1.2
-%define base64_version 0.2.0
-%define bigdecimal_version 3.1.8
-%define csv_version 3.3.2
-%define debug_version 1.11.0
-%define drb_version 2.2.1
+%define base64_version 0.3.0
+%define bigdecimal_version 4.0.1
+%define csv_version 3.3.5
+%define debug_version 1.11.1
+%define drb_version 2.2.3
%define getoptlong_version 0.2.1
-%define matrix_version 0.4.2
-%define minitest_version 5.25.4
+%define matrix_version 0.4.3
+%define minitest_version 6.0.0
%define mutex_m_version 0.3.0
-%define net_ftp_version 0.3.8
-%define net_imap_version 0.5.15
+%define net_ftp_version 0.3.9
+%define net_imap_version 0.6.4.1
%define net_pop_version 0.1.2
%define net_smtp_version 0.5.1
%define nkf_version 0.2.0
%define observer_version 0.1.2
-%define power_assert_version 2.0.5
-%define prime_version 0.1.3
+%define power_assert_version 3.0.1
+%define prime_version 0.1.4
%define racc_version 1.8.1
-%define rake_version 13.2.1
-%define rbs_version 3.8.0
-%define repl_type_completor_version 0.1.9
+%define rake_version 13.3.1
+%define rbs_version 3.10.0
+%define repl_type_completor_version 0.1.12
%define resolv_replace_version 0.1.1
%define rexml_version 3.4.4
%define rinda_version 0.2.0
-%define rss_version 0.3.1
-%define syslog_version 0.2.0
-%define test_unit_version 3.6.7
-%define typeprof_version 0.30.1
+%define rss_version 0.3.2
+%define syslog_version 0.3.0
+%define test_unit_version 3.7.5
+%define typeprof_version 0.31.1
# Bundled nkf version
%global bundled_nkf_version 2.1.5
@@ -726,8 +733,15 @@ these needs to be listed in Gemfile to be used by Bundler.
%patch 3 -p1
%patch 4 -p1
%patch 6 -p1
-%patch 9 -p1
+%patch 7 -p1
%patch 10 -p1
+%patch 13 -p1
+
+# The bundled rdoc is a gem, so it has to be patched in place.
+cd .bundle/gems/rdoc-%{rdoc_version}
+%patch 11 -p1
+%patch 12 -p1
+cd %{builddir}/%{buildsubdir}
# must be regenerated with new bison
%{__rm} parse.{c,h}
@@ -737,6 +751,12 @@ these needs to be listed in Gemfile to be used by Bundler.
#%{__rm} -r ext/fiddle/libffi*
# Install custom operating_system.rb.
+#
+# "make install" runs "require 'rubygems/defaults/operating_system'". Without
+# this file that require falls through to /usr/share/ruby/%{ruby_version} and
+# happily picks up the copy from an already installed RubyGems, which then
+# points Gem.default_dir at the per-user gem directory. Since -I../lib comes
+# first on the load path, the copy in the tree always wins.
install -d lib/rubygems/defaults
cp -p %{SOURCE6} lib/rubygems/defaults
@@ -757,7 +777,7 @@ if [ $rubygems_version != %{rubygems_version} ]; then
echo "Set %%define rubygems_version to $rubygems_version and re-run."
exit 1
fi
-rdoc_version=$(awk '/VERSION =/ && $1 == "VERSION" {print $3}' lib/rdoc/version.rb | xargs)
+rdoc_version=$(awk '/VERSION =/ && $1 == "VERSION" {print $3}' .bundle/gems/rdoc-%{rdoc_version}/lib/rdoc/version.rb | xargs)
if [ "$rdoc_version" != %{rdoc_version} ]; then
echo "Set %%define rdoc_version to $rdoc_version and re-run."
exit 1
@@ -806,7 +826,6 @@ chmod +x configure
--enable-yjit \
%endif
--disable-install-doc \
- --disable-rubygems \
cd ..
@@ -825,6 +844,7 @@ install -d $RPM_BUILD_ROOT{%{ruby_rdocdir},%{ruby_ridir}} \
$RPM_BUILD_ROOT%{ruby_vendorlibdir}/data
+
%make_install -C %{_vpath_builddir}
%if %{with doc}
%{__make} -C %{_vpath_builddir} install-doc DESTDIR=%{buildroot}
@@ -844,31 +864,34 @@ rm -rd ${CONFIG_TARGET_DIR}
sed -i 's/Version: \${ruby_version}/Version: %{ruby_version}/' %{buildroot}%{_libdir}/pkgconfig/%{name}.pc
# Kill bundled certificates, as they should be part of ca-certificates.
+# Newer RubyGems releases no longer ship them, hence the -f.
for cert in GlobalSignRootCA.pem GlobalSignRootCA_R3.pem; do \
- %{__rm} $RPM_BUILD_ROOT%{rubygems_dir}/rubygems/ssl_certs/*/$cert
+ %{__rm} -f $RPM_BUILD_ROOT%{rubygems_dir}/rubygems/ssl_certs/*/$cert
done
# Ensure there is not forgotten any certificate.
##test ! "$(ls -A $RPM_BUILD_ROOT%{rubygems_dir}/rubygems/ssl_certs/ 2>/dev/null)"
install -d $RPM_BUILD_ROOT%{_examplesdir}/%{oname}-%{pkg_version}
cp -Rf sample/* $RPM_BUILD_ROOT%{_examplesdir}/%{oname}-%{pkg_version}
+
+# "make install" no longer installs the top level documentation.
+install -d $RPM_BUILD_ROOT%{_docdir}/%{name}-%{pkg_version}
+cp -p NEWS.md LEGAL BSDL README.md README.EXT $RPM_BUILD_ROOT%{_docdir}/%{name}-%{pkg_version}/
cp -p %{SOURCE4} %{buildroot}%{_mandir}/man1/rdoc.1
cp -p %{SOURCE5} %{buildroot}%{_mandir}/man1/testrb.1
%{__rm} -rf $RPM_BUILD_ROOT%{_docdir}/%{name}/html
-# detect this runtime, "make install" is affected by operating_system.rb what is installed in system!
-gem_dir=$( \
- %{_vpath_builddir}/miniruby -Ilib -I. -I%{_vpath_builddir}/.ext/common \
- tool/runruby.rb --archdir=%{_vpath_builddir} -- --disable-gems \
- -r$(basename %{_vpath_builddir}/*-linux*-fake.rb .rb) -r rubygems \
- -e 'puts Gem.default_dir' \
-)
-
# Move gems root into common directory, out of Ruby directory structure.
-install -d $RPM_BUILD_ROOT%{gem_dir}
-%{__mv} $RPM_BUILD_ROOT${gem_dir}/{gems,specifications} $RPM_BUILD_ROOT%{gem_dir}
-%{__rm} $RPM_BUILD_ROOT${gem_dir}/cache/*.gem
+# "make install" already lays it out as %{gem_dir}/{gems,specifications,extensions}.
+# The bundled gem cache is not packaged.
+%{__mv} $RPM_BUILD_ROOT%{ruby_libdir}/gems $RPM_BUILD_ROOT%{gem_dir}
+%{__rm} -f $RPM_BUILD_ROOT%{gem_dir}/cache/*.gem
+
+# Install the packager overrides for RubyGems. This has to happen after the
+# gems have been moved, so that Gem.default_dirs[:system] points at %{gem_dir}.
+install -d $RPM_BUILD_ROOT%{rubygems_dir}/rubygems/defaults
+cp -p %{SOURCE6} $RPM_BUILD_ROOT%{rubygems_dir}/rubygems/defaults
# Move bundled rubygems to %gem_dir
# make symlinks for io-console and bigdecimal, which are considered to be part of stdlib by other Gems
@@ -877,11 +900,12 @@ install -d $RPM_BUILD_ROOT%{gem_dir}
# as there may came files from other packages as well. actually, unlikely as
# the links to got system dir and only ruby may package there (other distro
# packages should go to vendor dirs)%
-install -d $RPM_BUILD_ROOT%{gem_instdir rdoc}/lib
-%{__mv} $RPM_BUILD_ROOT%{ruby_libdir}/rdoc* $RPM_BUILD_ROOT%{gem_instdir rdoc}/lib
+# Since Ruby 4.0 "make install" already places the bundled gems below
+# %{gem_dir}, so nothing has to be moved out of %{ruby_libdir} here.
+[ -d $RPM_BUILD_ROOT%{gem_spec -d rdoc} ] && \
+ %{__mv} $RPM_BUILD_ROOT%{gem_spec -d rdoc} $RPM_BUILD_ROOT%{gem_dir}/specifications
%make_rel_symlink %{gem_instdir rdoc}/lib/rdoc %{ruby_libdir}
%make_rel_symlink %{gem_instdir rdoc}/lib/rdoc.rb %{ruby_libdir}
-%{__mv} $RPM_BUILD_ROOT%{gem_spec -d rdoc} $RPM_BUILD_ROOT%{gem_dir}/specifications
%make_rel_symlink %{gem_instdir bigdecimal}/lib/bigdecimal %{ruby_libdir}
%make_rel_symlink %{gem_instdir bigdecimal}/lib/bigdecimal.rb %{ruby_libdir}
@@ -937,9 +961,16 @@ install -d $RPM_BUILD_ROOT%{gem_extdir_mri bundler}/lib
# Move the binary extensions into proper place (if no gem has binary extension,
# the extensions directory might be empty).
-find ${RPM_BUILD_ROOT}${gem_dir}/extensions/*-%{_target_os}/%{ruby_version}.*/* -maxdepth 0 \
- -exec mv '{}' $RPM_BUILD_ROOT%{_libdir}/gems/%{name}/ \; \
- || echo "No gem binary extensions to move."
+for extdir in "$RPM_BUILD_ROOT"%{gem_dir}/extensions \
+ "$RPM_BUILD_ROOT"/../%{oname}-%{pkg_version}/build/.bundle/extensions; do
+ [ -d "$extdir" ] || continue
+ find "$extdir"/*-%{_target_os}/%{ruby_version}.*/* -maxdepth 0 \
+ -exec mv '{}' $RPM_BUILD_ROOT%{_libdir}/gems/%{name}/ \; \
+ || echo "No gem binary extensions to move."
+done
+# Only the leftovers in the build root; the source tree must stay intact for
+# the "gem build_complete" stamps and for subsequent extension builds.
+rm -rf "$RPM_BUILD_ROOT"%{gem_dir}/extensions
# Remove the extension sources and library copies from `lib` dir.
find $RPM_BUILD_ROOT%{gem_dir}/gems/*/ext -maxdepth 0 -exec rm -rf '{}' +
@@ -981,8 +1012,11 @@ for s in rake-%{rake_version}.gemspec rdoc-%{rdoc_version}.gemspec json-%{json_v
-e \"File.write '$s', spec.to_ruby\""
done
-%{__sed} -i -e '1s,/usr/bin/env ruby,/usr/bin/ruby,' \
- $(find $RPM_BUILD_ROOT -type f | xargs grep '%{_bindir}/env ruby' 2>/dev/null | cut -f1 -d:)
+# Rewrite gem shebangs. Newer gems may use the "#!/usr/bin/env -S ruby"
+# form, which rpm's shebang check rejects.
+%{__sed} -i -e '1s,/usr/bin/env -S ruby,%{_bindir}/ruby,' \
+ -e '1s,/usr/bin/env ruby,%{_bindir}/ruby,' \
+ $(find $RPM_BUILD_ROOT -type f | xargs grep -l -E '%{_bindir}/env (-S )?ruby' 2>/dev/null)
# gem non library files
rm -rf $RPM_BUILD_ROOT%{gem_instdir debug}/{[A-Z]*,misc,exts.mk}
@@ -1021,6 +1055,7 @@ rm -f $RPM_BUILD_ROOT%{ruby_ridir}/cache.ri 2>/dev/null || :
%check
%if %{with tests}
+
# unset these, as testsuite does "git commit" somewhere, which points to pld .spec repo. doh
unset GIT_DIR GIT_WORK_TREE
@@ -1064,7 +1099,11 @@ sed -i '/def test_ctx_server_session_cb$/,/^ end$/ s/^/#/' test/openssl/test_ss
%files
%defattr(644,root,root,755)
-%doc NEWS.md LEGAL BSDL README.md README.EXT
+%doc %{_docdir}/%{name}-%{pkg_version}/NEWS.md
+%doc %{_docdir}/%{name}-%{pkg_version}/LEGAL
+%doc %{_docdir}/%{name}-%{pkg_version}/BSDL
+%doc %{_docdir}/%{name}-%{pkg_version}/README.md
+%doc %{_docdir}/%{name}-%{pkg_version}/README.EXT
%attr(755,root,root) %{_bindir}/ruby
%{_libdir}/libruby.so.*.*.*
%ghost %{_libdir}/libruby.so.%{ruby_version}
@@ -1079,8 +1118,8 @@ sed -i '/def test_ctx_server_session_cb$/,/^ end$/ s/^/#/' test/openssl/test_ss
%dir %{ruby_vendorlibdir}
%dir %{ruby_vendorarchdir}
-%dir %{dirname:%{ruby_ridir}}
-%dir %{ruby_ridir}
+# Since RDoc 7 the ri data is versioned below %%{_datadir}/ri/%%{ruby_version} and
+# is packaged by ruby-doc-ri, so the old unversioned %%{ruby_ridir} is gone.
%dir %{ruby_rdocdir}
# common dirs for ruby vendor modules
@@ -1097,23 +1136,34 @@ sed -i '/def test_ctx_server_session_cb$/,/^ end$/ s/^/#/' test/openssl/test_ss
%files irb
%defattr(644,root,root,755)
%attr(755,root,root) %{_bindir}/irb
-%{ruby_libdir}/irb.rb
-%{ruby_libdir}/irb
-%{gem_spec -d irb}
-%{_mandir}/man1/irb.1*
+%{gem_instdir irb}
+%{gem_spec irb}
%files rdoc
%defattr(644,root,root,755)
%attr(755,root,root) %{_bindir}/rdoc
%attr(755,root,root) %{_bindir}/ri
%{_mandir}/man1/rdoc.1*
+%{gem_instdir rdoc}/man/ri.1*
%{ruby_libdir}/rdoc
%dir %{gem_instdir rdoc}
%{gem_instdir rdoc}/lib
%{gem_spec rdoc}
+%{gem_instdir rdoc}/rdoc.gemspec
%dir %{gem_instdir rdoc}/exe
%{gem_instdir rdoc}/exe/rdoc
%{gem_instdir rdoc}/exe/ri
+%{gem_plugin rdoc}
+%doc %{gem_instdir rdoc}/CONTRIBUTING.md
+%doc %{gem_instdir rdoc}/CVE-2013-0256.rdoc
+%doc %{gem_instdir rdoc}/ExampleMarkdown.md
+%doc %{gem_instdir rdoc}/ExampleRDoc.rdoc
+%doc %{gem_instdir rdoc}/History.rdoc
+%license %{gem_instdir rdoc}/LEGAL.rdoc
+%license %{gem_instdir rdoc}/LICENSE.rdoc
+%doc %{gem_instdir rdoc}/README.md
+%doc %{gem_instdir rdoc}/RI.md
+%doc %{gem_instdir rdoc}/TODO.rdoc
%if %{with batteries}
%files rubygems
@@ -1135,6 +1185,7 @@ sed -i '/def test_ctx_server_session_cb$/,/^ end$/ s/^/#/' test/openssl/test_ss
%dir %{gem_instdir rake}
%{gem_instdir rake}/lib
%{gem_spec rake}
+%{gem_instdir rake}/rake.gemspec
%dir %{gem_instdir rake}/exe
%attr(755,root,root) %{gem_instdir rake}/exe/rake
@@ -1165,13 +1216,16 @@ sed -i '/def test_ctx_server_session_cb$/,/^ end$/ s/^/#/' test/openssl/test_ss
%files minitest
%defattr(644,root,root,755)
+%attr(755,root,root) %{_bindir}/minitest
%{ruby_libdir}/minitest
%{gem_instdir minitest}
%{gem_spec minitest}
%files test-unit
%defattr(644,root,root,755)
+%attr(755,root,root) %{_bindir}/test-unit
%dir %{gem_instdir test-unit}
+%{gem_instdir test-unit}/bin
%{gem_instdir test-unit}/lib
%{gem_spec test-unit}
%{_mandir}/man1/testrb.1*
@@ -1179,8 +1233,11 @@ sed -i '/def test_ctx_server_session_cb$/,/^ end$/ s/^/#/' test/openssl/test_ss
%files racc
%defattr(644,root,root,755)
%dir %{gem_instdir racc}
+%dir %{gem_extdir_mri racc}
+%{gem_extdir_mri racc}/gem.build_complete
+%dir %{gem_extdir_mri racc}/racc
+%attr(755,root,root) %{gem_extdir_mri racc}/racc/cparse.so
%attr(755,root,root) %{_bindir}/racc
-%{gem_extdir_mri racc}
%{gem_instdir racc}/bin
%{gem_instdir racc}/lib
%{gem_spec racc}
@@ -1259,10 +1316,67 @@ sed -i '/def test_ctx_server_session_cb$/,/^ end$/ s/^/#/' test/openssl/test_ss
# base64
%dir %{gem_instdir base64}
-%doc %{gem_instdir base64}/LICENSE.txt
+%license %{gem_instdir base64}/BSDL
+%license %{gem_instdir base64}/COPYING
+%license %{gem_instdir base64}/LEGAL
%{gem_instdir base64}/lib
%{gem_spec base64}
%doc %{gem_instdir base64}/README.md
+%doc %{gem_instdir base64}/sig
+
+# benchmark
+%dir %{gem_instdir benchmark}
+%license %{gem_instdir benchmark}/BSDL
+%license %{gem_instdir benchmark}/COPYING
+%{gem_instdir benchmark}/bin
+%{gem_instdir benchmark}/lib
+%{gem_spec benchmark}
+%{gem_instdir benchmark}/Gemfile
+%doc %{gem_instdir benchmark}/README.md
+%{gem_instdir benchmark}/Rakefile
+
+# fiddle
+%dir %{gem_instdir fiddle}
+%dir %{gem_extdir_mri fiddle}
+%{gem_extdir_mri fiddle}/gem.build_complete
+%attr(755,root,root) %{gem_extdir_mri fiddle}/fiddle.so
+%{gem_instdir fiddle}/lib
+%{gem_spec fiddle}
+%{gem_instdir fiddle}/fiddle.gemspec
+%doc %{gem_instdir fiddle}/LICENSE.txt
+%doc %{gem_instdir fiddle}/README.md
+%{gem_instdir fiddle}/Rakefile
+
+# logger
+%dir %{gem_instdir logger}
+%license %{gem_instdir logger}/BSDL
+%license %{gem_instdir logger}/COPYING
+%{gem_instdir logger}/lib
+%{gem_spec logger}
+%doc %{gem_instdir logger}/README.md
+
+# ostruct
+%dir %{gem_instdir ostruct}
+%license %{gem_instdir ostruct}/BSDL
+%license %{gem_instdir ostruct}/COPYING
+%{gem_instdir ostruct}/bin
+%{gem_instdir ostruct}/lib
+%{gem_spec ostruct}
+%{gem_instdir ostruct}/ostruct.gemspec
+%{gem_instdir ostruct}/Gemfile
+%doc %{gem_instdir ostruct}/README.md
+%{gem_instdir ostruct}/Rakefile
+
+# pstore
+%dir %{gem_instdir pstore}
+%license %{gem_instdir pstore}/BSDL
+%license %{gem_instdir pstore}/COPYING
+%{gem_instdir pstore}/bin
+%{gem_instdir pstore}/lib
+%{gem_spec pstore}
+%{gem_instdir pstore}/Gemfile
+%doc %{gem_instdir pstore}/README.md
+%{gem_instdir pstore}/Rakefile
# csv
%dir %{gem_instdir csv}
@@ -1278,6 +1392,7 @@ sed -i '/def test_ctx_server_session_cb$/,/^ end$/ s/^/#/' test/openssl/test_ss
%doc %{gem_instdir drb}/LICENSE.txt
%{gem_instdir drb}/lib
%{gem_spec drb}
+%{gem_instdir drb}/drb.gemspec
# getoptlong
%dir %{gem_instdir getoptlong}
@@ -1294,6 +1409,7 @@ sed -i '/def test_ctx_server_session_cb$/,/^ end$/ s/^/#/' test/openssl/test_ss
%dir %{gem_instdir matrix}
%{gem_instdir matrix}/lib
%{gem_spec matrix}
+%{gem_instdir matrix}/matrix.gemspec
# mutex_m
%dir %{gem_instdir mutex_m}
@@ -1347,11 +1463,29 @@ sed -i '/def test_ctx_server_session_cb$/,/^ end$/ s/^/#/' test/openssl/test_ss
%doc %{gem_instdir observer}/README.md
%{gem_instdir observer}/Rakefile
+# readline
+%dir %{gem_instdir readline}
+%license %{gem_instdir readline}/BSDL
+%license %{gem_instdir readline}/COPYING
+%{gem_instdir readline}/lib
+%{gem_spec readline}
+%doc %{gem_instdir readline}/README.md
+
+# reline
+%dir %{gem_instdir reline}
+%license %{gem_instdir reline}/BSDL
+%license %{gem_instdir reline}/COPYING
+%{gem_instdir reline}/lib
+%{gem_spec reline}
+%doc %{gem_instdir reline}/README.md
+%{gem_instdir reline}/license_of_rb-readline
+
# prime
%dir %{gem_instdir prime}
%{gem_instdir prime}/lib
%{gem_instdir prime}/sig
%{gem_spec prime}
+%{gem_instdir prime}/prime.gemspec
# rdbg
%attr(755,root,root) %{_bindir}/rdbg
@@ -1410,7 +1544,6 @@ sed -i '/def test_ctx_server_session_cb$/,/^ end$/ s/^/#/' test/openssl/test_ss
%{ruby_libdir}/bundled_gems.rb
%{ruby_libdir}/cgi
%{ruby_libdir}/digest
-%{ruby_libdir}/fiddle
%{ruby_libdir}/io
%{ruby_libdir}/net
%{ruby_libdir}/openssl
@@ -1420,7 +1553,6 @@ sed -i '/def test_ctx_server_session_cb$/,/^ end$/ s/^/#/' test/openssl/test_ss
%{ruby_libdir}/uri
%{ruby_libdir}/yaml
%{ruby_libdir}/English.rb
-%{ruby_libdir}/benchmark.rb
%{ruby_libdir}/bundler
%{ruby_libdir}/bundler.rb
%{ruby_libdir}/cgi.rb
@@ -1437,7 +1569,6 @@ sed -i '/def test_ctx_server_session_cb$/,/^ end$/ s/^/#/' test/openssl/test_ss
%dir %{ruby_libdir}/erb
%{ruby_libdir}/erb/*.rb
%{ruby_libdir}/expect.rb
-%{ruby_libdir}/fiddle.rb
%{ruby_libdir}/fileutils.rb
%{ruby_libdir}/find.rb
%{ruby_libdir}/forwardable.rb
@@ -1445,9 +1576,6 @@ sed -i '/def test_ctx_server_session_cb$/,/^ end$/ s/^/#/' test/openssl/test_ss
%{ruby_libdir}/forwardable/impl.rb
%{ruby_libdir}/ipaddr.rb
%{ruby_libdir}/json.rb
-%{ruby_libdir}/logger.rb
-%dir %{ruby_libdir}/logger
-%{ruby_libdir}/logger/*.rb
%{ruby_libdir}/monitor.rb
%{ruby_libdir}/objspace.rb
%dir %{ruby_libdir}/objspace
@@ -1459,34 +1587,19 @@ sed -i '/def test_ctx_server_session_cb$/,/^ end$/ s/^/#/' test/openssl/test_ss
%{ruby_libdir}/openssl.rb
%{ruby_libdir}/optionparser.rb
%{ruby_libdir}/optparse.rb
-%{ruby_libdir}/ostruct.rb
%{ruby_libdir}/pathname.rb
%{ruby_libdir}/pp.rb
%{ruby_libdir}/prettyprint.rb
%{ruby_libdir}/prism*
-%{ruby_libdir}/pstore.rb
%dir %{ruby_libdir}/random
%{ruby_libdir}/random/*.rb
%{ruby_libdir}/rdoc.rb
-%{ruby_libdir}/readline.rb
-%{ruby_libdir}/reline.rb
-%dir %{ruby_libdir}/reline
-%{ruby_libdir}/reline/*.rb
-%dir %{ruby_libdir}/reline/io
-%{ruby_libdir}/reline/io/*.rb
-%dir %{ruby_libdir}/reline/key_actor
-%{ruby_libdir}/reline/key_actor/*.rb
-%dir %{ruby_libdir}/reline/unicode
-%{ruby_libdir}/reline/unicode/*.rb
+
%{ruby_libdir}/resolv.rb
%{ruby_libdir}/ripper.rb
-%dir %{ruby_libdir}/ruby_vm
-%dir %{ruby_libdir}/ruby_vm/rjit
-%{ruby_libdir}/ruby_vm/rjit/*.rb
%{ruby_libdir}/securerandom.rb
-%{ruby_libdir}/set.rb
%dir %{ruby_libdir}/set
-%{ruby_libdir}/set/*.rb
+%{ruby_libdir}/set/subclass_compatible.rb
%{ruby_libdir}/shellwords.rb
%{ruby_libdir}/singleton.rb
%{ruby_libdir}/socket.rb
@@ -1511,7 +1624,6 @@ sed -i '/def test_ctx_server_session_cb$/,/^ end$/ s/^/#/' test/openssl/test_ss
%if %{with batteries}
%exclude %{ruby_libdir}/rubygems.rb
%endif
-%exclude %{ruby_libdir}/irb.rb
%exclude %{ruby_libdir}/mkmf.rb
%{ruby_archdir}/rbconfig.rb
@@ -1522,11 +1634,9 @@ sed -i '/def test_ctx_server_session_cb$/,/^ end$/ s/^/#/' test/openssl/test_ss
%attr(755,root,root) %{ruby_archdir}%{_sysconfdir}.so
%attr(755,root,root) %{ruby_archdir}/erb/escape.so
%attr(755,root,root) %{ruby_archdir}/fcntl.so
-%attr(755,root,root) %{ruby_archdir}/fiddle.so
%attr(755,root,root) %{ruby_archdir}/monitor.so
%attr(755,root,root) %{ruby_archdir}/objspace.so
%attr(755,root,root) %{ruby_archdir}/openssl.so
-%attr(755,root,root) %{ruby_archdir}/pathname.so
%attr(755,root,root) %{ruby_archdir}/pty.so
%attr(755,root,root) %{ruby_archdir}/ripper.so
%attr(755,root,root) %{ruby_archdir}/socket.so
@@ -1560,28 +1670,14 @@ sed -i '/def test_ctx_server_session_cb$/,/^ end$/ s/^/#/' test/openssl/test_ss
%{gem_dir}/specifications/default/*.gemspec
%{_mandir}/man1/erb.1*
-%{_mandir}/man1/ri.1*
%if %{with doc}
+# Since RDoc 7 the ri data is versioned below %%{_datadir}/ri/%%{ruby_version},
+# so take the whole tree rather than listing individual files. The empty
+# %%{_datadir}/rdoc is already owned by the main ruby package.
%files doc-ri
%defattr(644,root,root,755)
-%{ruby_ridir}/[A-Z]*
-%{ruby_ridir}/contributing
-%{ruby_ridir}/date
-%{ruby_ridir}/fatal
-%{ruby_ridir}/syntax
-%{ruby_ridir}/optparse
-%lang(ja) %{ruby_ridir}/page-COPYING_ja.ri
-%lang(ja) %{ruby_ridir}/page-README_ja_md.ri
-%{ruby_ridir}/page-COPYING.ri
-%{ruby_ridir}/page-LEGAL.ri
-%{ruby_ridir}/page-NEWS_md.ri
-%{ruby_ridir}/page-README_md.ri
-%{ruby_ridir}/page-[a-z]*.ri
-%{ruby_ridir}/regexp
-%{ruby_ridir}/rjit
-%{ruby_ridir}/ruby
-%{ruby_ridir}/yjit
+%{_datadir}/ri
%endif
%files examples
diff --git a/duplicated-paths.patch b/duplicated-paths.patch
deleted file mode 100644
index bfb197f..0000000
--- a/duplicated-paths.patch
+++ /dev/null
@@ -1,80 +0,0 @@
-From e24d97c938c481450ed80ec83e5399595946c1ae Mon Sep 17 00:00:00 2001
-From: =?UTF-8?q?V=C3=ADt=20Ondruch?= <vondruch at redhat.com>
-Date: Fri, 8 Feb 2013 22:48:41 +0100
-Subject: [PATCH] Prevent duplicated paths when empty version string is
- configured.
-
----
- configure.ac | 3 ++-
- loadpath.c | 12 ++++++++++++
- tool/mkconfig.rb | 2 +-
- 3 files changed, 15 insertions(+), 2 deletions(-)
-
-diff --git a/configure.ac b/configure.ac
-index 999e2d6d5d..11fc237552 100644
---- a/configure.ac
-+++ b/configure.ac
-@@ -3710,7 +3710,8 @@ AS_CASE(["$ruby_version_dir_name"],
- ruby_version_dir=/'${ruby_version_dir_name}'
-
- if test -z "${ruby_version_dir_name}"; then
-- AC_MSG_ERROR([No ruby version, No place for bundled libraries])
-+ unset ruby_version_dir
-+ AC_DEFINE(RUBY_LIB_VERSION_BLANK, 1)
- fi
-
- rubylibdir='${rubylibprefix}'${ruby_version_dir}
-diff --git a/loadpath.c b/loadpath.c
-index 9160031..0d4d953 100644
---- a/loadpath.c
-+++ b/loadpath.c
-@@ -65,21 +65,33 @@ const char ruby_initial_load_paths[] =
- RUBY_SEARCH_PATH "\0"
- #endif
- #ifndef NO_RUBY_SITE_LIB
-+#ifdef RUBY_LIB_VERSION_BLANK
-+ RUBY_SITE_LIB "\0"
-+#else
- RUBY_SITE_LIB2 "\0"
-+#endif
- #ifdef RUBY_THINARCH
- RUBY_SITE_ARCH_LIB_FOR(RUBY_THINARCH) "\0"
- #endif
- RUBY_SITE_ARCH_LIB_FOR(RUBY_SITEARCH) "\0"
-+#ifndef RUBY_LIB_VERSION_BLANK
- RUBY_SITE_LIB "\0"
- #endif
-+#endif
-
- #ifndef NO_RUBY_VENDOR_LIB
-+#ifdef RUBY_LIB_VERSION_BLANK
-+ RUBY_VENDOR_LIB "\0"
-+#else
- RUBY_VENDOR_LIB2 "\0"
-+#endif
- #ifdef RUBY_THINARCH
- RUBY_VENDOR_ARCH_LIB_FOR(RUBY_THINARCH) "\0"
- #endif
- RUBY_VENDOR_ARCH_LIB_FOR(RUBY_SITEARCH) "\0"
-+#ifndef RUBY_LIB_VERSION_BLANK
- RUBY_VENDOR_LIB "\0"
-+#endif
- #endif
-
- RUBY_LIB "\0"
-diff --git a/tool/mkconfig.rb b/tool/mkconfig.rb
-index 07076d4..35e6c3c 100755
---- a/tool/mkconfig.rb
-+++ b/tool/mkconfig.rb
-@@ -114,7 +114,7 @@
- val = val.gsub(/\$(?:\$|\{?(\w+)\}?)/) {$1 ? "$(#{$1})" : $&}.dump
- case name
- when /^prefix$/
-- val = "(TOPDIR || DESTDIR + #{val})"
-+ val = "(((TOPDIR && TOPDIR.empty?) ? nil : TOPDIR) || DESTDIR + #{val})"
- when /^ARCH_FLAG$/
- val = "arch_flag || #{val}" if universal
- when /^UNIVERSAL_ARCHNAMES$/
---
-1.9.0
-
diff --git a/extract-gem-versions.sh b/extract-gem-versions.sh
index fcc5e18..9c10fa6 100755
--- a/extract-gem-versions.sh
+++ b/extract-gem-versions.sh
@@ -50,19 +50,19 @@ cd "$BUILD_DIR" || exit 1
ver=$(grep -P "\w+\.version" .bundle/gems/bigdecimal-*/.bundled.bigdecimal-*.gemspec | head -1 | grep -oP '\d+\.\d+[\d\.]*')
puts_version "bigdecimal" "$ver"
-ver=$(grep "VERSION = " lib/bundler/version.rb | grep -oP '\d+\.\d+[\d\.]*')
+ver=$(grep -oP 'VERSION\s*=\s*["\x27]\K[\d.]+' lib/bundler/version.rb | head -1)
puts_version "bundler" "$ver"
-ver=$(grep "VERSION = " lib/erb/version.rb | grep -oP '\d+\.\d+[\d\.]*')
+ver=$(grep -oP 'VERSION\s*=\s*["\x27]\K[\d.]+' lib/erb/version.rb | head -1)
puts_version "erb" "$ver"
ver=$(grep IO_CONSOLE_VERSION ext/io/console/console.c | grep -oP '\d+\.\d+[\d\.]*')
puts_version "io_console" "$ver"
-ver=$(grep -P "\s+VERSION = " lib/irb/version.rb | grep -oP '\d+\.\d+[\d\.]*')
+ver=$(grep -oP 'VERSION\s*=\s*["\x27]\K[\d.]+' .bundle/gems/irb-*/lib/irb/version.rb | head -1)
puts_version "irb" "$ver"
-ver=$(cat ext/json/lib/json/version.rb | grep -oP '\d+\.\d+[\d\.]*')
+ver=$(grep -oP 'VERSION\s*=\s*["\x27]\K[\d.]+' ext/json/lib/json/version.rb | head -1)
puts_version "json" "$ver"
for i in etc stringio zlib; do
@@ -77,10 +77,10 @@ puts_version "openssl" "$ver"
ver=$(grep "VERSION = " ext/psych/lib/psych/versions.rb | head -1 | grep -oP '\d+\.\d+[\d\.]*')
puts_version "psych" "$ver"
-ver=$(grep -P "\s+VERSION\s+=\s+" lib/rdoc/version.rb | grep -oP '\d+\.\d+[\d\.]*')
+ver=$(grep -oP 'VERSION\s*=\s*["\x27]\K[\d.]+' .bundle/gems/rdoc-*/lib/rdoc/version.rb | head -1)
puts_version "rdoc" "$ver"
-ver=$(grep -P "\w+\.version\s+" lib/readline*.gemspec | head -1 | grep -oP '\d+\.\d+[\d\.]*')
+ver=$(grep -oP 's\.version\s*=\s*["\x27]\K[\d.]+' .bundle/specifications/readline-*.gemspec | head -1)
puts_version "readline" "$ver"
ver=$(grep "VERSION = " lib/rubygems.rb | head -1 | grep -oP '\d+\.\d+[\d\.]*')
diff --git a/fix-bison-invocation.patch b/fix-bison-invocation.patch
deleted file mode 100644
index 2ff5cc3..0000000
--- a/fix-bison-invocation.patch
+++ /dev/null
@@ -1,10 +0,0 @@
---- ruby-2.6.5/ext/ripper/depend~ 2019-10-01 13:01:01.000000000 +0200
-+++ ruby-2.6.5/ext/ripper/depend 2019-11-25 08:47:14.265303943 +0100
-@@ -11,7 +11,7 @@
-
- .y.c:
- $(ECHO) compiling compiler $<
-- $(Q) $(BISON) -t -v -oy.tab.c $<
-+ $(Q) $(BISON) -d -t -v -oy.tab.c $<
- $(Q) sed -e "/^#/s!y\.tab\.c!$@!" -f $(top_srcdir)/tool/ytab.sed y.tab.c > $@
- @$(RM) y.tab.c
diff --git a/mkmf-verbose.patch b/mkmf-verbose.patch
deleted file mode 100644
index 2113bea..0000000
--- a/mkmf-verbose.patch
+++ /dev/null
@@ -1,25 +0,0 @@
-From 28cc0749d6729aa2444661ee7b411e183fe220b0 Mon Sep 17 00:00:00 2001
-From: =?UTF-8?q?V=C3=ADt=20Ondruch?= <vondruch at redhat.com>
-Date: Mon, 19 Nov 2012 15:14:51 +0100
-Subject: [PATCH] Verbose mkmf.
-
----
- lib/mkmf.rb | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/lib/mkmf.rb b/lib/mkmf.rb
-index 682eb46..e6b1445 100644
---- a/lib/mkmf.rb
-+++ b/lib/mkmf.rb
-@@ -1974,7 +1974,7 @@ def configuration(srcdir)
- SHELL = /bin/sh
-
- # V=0 quiet, V=1 verbose. other values don't work.
--V = 0
-+V = 1
- V0 = $(V:0=)
- Q1 = $(V:1=)
- Q = $(Q1:0=@)
---
-1.8.3.1
-
diff --git a/openssl3.patch b/openssl3.patch
deleted file mode 100644
index acc7d3c..0000000
--- a/openssl3.patch
+++ /dev/null
@@ -1,12 +0,0 @@
---- ruby-2.6.8/ext/openssl/ossl_pkey_rsa.c.orig 2021-07-07 12:38:58.000000000 +0200
-+++ ruby-2.6.8/ext/openssl/ossl_pkey_rsa.c 2021-10-13 12:03:34.317085257 +0200
-@@ -939,7 +939,9 @@
- rb_define_method(cRSA, "params", ossl_rsa_get_params, 0);
-
- DefRSAConst(PKCS1_PADDING);
-+#if OPENSSL_VERSION_MAJOR < 3
- DefRSAConst(SSLV23_PADDING);
-+#endif
- DefRSAConst(NO_PADDING);
- DefRSAConst(PKCS1_OAEP_PADDING);
-
diff --git a/operating_system.rb b/operating_system.rb
index fd56386..a0318a9 100644
--- a/operating_system.rb
+++ b/operating_system.rb
@@ -101,6 +101,18 @@ module Gem
Gem.default_dirs[:system][:gem_dir]
elsif Process.uid == 0
Gem.default_dirs[:local][:gem_dir]
+ elsif ENV['RPM_PACKAGE_NAME'] == 'ruby'
+ # PLD builds ruby with --with-rubygemsdir pointing at the Ruby
+ # library directory, so the gems have to be laid down in the Ruby
+ # tree first; the spec's %install moves them to %gem_dir afterwards.
+ # Without this the whole tree would end up below the invoking
+ # user's ~/.local, which is neither the packager's nor the end
+ # user's intent.
+ #
+ # Guarded on the package name on purpose: this file also lands in
+ # every other ruby-based package, and rerouting default_dir for
+ # those would move their gems as well.
+ File.join(RbConfig::CONFIG['rubylibdir'], 'gems')
else
Gem.user_dir
end
diff --git a/rdoc-pr1531-fix-mutilple-document-installation.patch b/rdoc-pr1531-fix-mutilple-document-installation.patch
new file mode 100644
index 0000000..192863f
--- /dev/null
+++ b/rdoc-pr1531-fix-mutilple-document-installation.patch
@@ -0,0 +1,28 @@
+From 994ee4c17fb8c217ab0335df55620c6bdb5d5cbe Mon Sep 17 00:00:00 2001
+From: tompng <tomoyapenguin at gmail.com>
+Date: Fri, 26 Dec 2025 04:57:12 +0900
+Subject: [PATCH] Fix comment_location for merged ClassModule
+
+---
+ lib/rdoc/code_object/class_module.rb | 7 ++++++-
+ test/rdoc/code_object/class_module_test.rb | 6 ++++++
+ 2 files changed, 12 insertions(+), 1 deletion(-)
+
+diff --git a/lib/rdoc/code_object/class_module.rb b/lib/rdoc/code_object/class_module.rb
+index b6bed352a2..d7ee36f950 100644
+--- a/lib/rdoc/code_object/class_module.rb
++++ b/lib/rdoc/code_object/class_module.rb
+@@ -477,7 +477,12 @@ def merge(class_module)
+ document = document.merge other_document
+
+ @comment = RDoc::Comment.from_document(document)
+- @comment_location = document
++
++ @comment_location = if document.parts.first.is_a?(RDoc::Markup::Document)
++ document.parts.map { |doc| [doc, doc.file] }
++ else
++ [[document, document.file]]
++ end
+ end
+
+ cm = class_module
diff --git a/ruby-2.1.0-Enable-configuration-of-archlibdir.patch b/ruby-2.1.0-Enable-configuration-of-archlibdir.patch
index 116bb66..114ef1c 100644
--- a/ruby-2.1.0-Enable-configuration-of-archlibdir.patch
+++ b/ruby-2.1.0-Enable-configuration-of-archlibdir.patch
@@ -1,4 +1,3 @@
-From 07c666ba5c3360dd6f43605a8ac7c85c99c1721f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?V=C3=ADt=20Ondruch?= <vondruch at redhat.com>
Date: Tue, 1 Oct 2013 12:22:40 +0200
Subject: [PATCH] Allow to configure libruby.so placement.
@@ -8,10 +7,9 @@ Subject: [PATCH] Allow to configure libruby.so placement.
1 file changed, 5 insertions(+)
diff --git a/configure.ac b/configure.ac
-index 11fc237552..b77e88fc37 100644
--- a/configure.ac
+++ b/configure.ac
-@@ -3085,6 +3085,11 @@ AS_IF([test ${multiarch+set}], [
+@@ -3553,6 +3553,11 @@ AS_IF([test ${multiarch+set}], [
])
archlibdir='${libdir}/${arch}'
@@ -23,6 +21,3 @@ index 11fc237552..b77e88fc37 100644
sitearchlibdir='${libdir}/${sitearch}'
archincludedir='${includedir}/${arch}'
sitearchincludedir='${includedir}/${sitearch}'
---
-1.8.3.1
-
diff --git a/ruby-2.3.0-ruby_version-Add-ruby_version_dir_name-support-for-RDoc.patch b/ruby-2.3.0-ruby_version-Add-ruby_version_dir_name-support-for-RDoc.patch
new file mode 100644
index 0000000..82f5963
--- /dev/null
+++ b/ruby-2.3.0-ruby_version-Add-ruby_version_dir_name-support-for-RDoc.patch
@@ -0,0 +1,22 @@
+From f833e213596b0bcfad8264a555eb5093303fb5f2 Mon Sep 17 00:00:00 2001
+From: Jarek Prokop <jprokop at redhat.com>
+Date: Thu, 25 Sep 2025 12:26:39 +0200
+Subject: [PATCH] Add ruby_version_dir_name support for RDoc.
+
+---
+ lib/rdoc/ri/paths.rb | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/lib/rdoc/ri/paths.rb b/lib/rdoc/ri/paths.rb
+index 8e89b04e..731f9e36 100644
+--- a/lib/rdoc/ri/paths.rb
++++ b/lib/rdoc/ri/paths.rb
+@@ -10,7 +10,7 @@ module RDoc::RI::Paths
+ #:stopdoc:
+ require 'rbconfig'
+
+- version = RbConfig::CONFIG['ruby_version']
++ version = RbConfig::CONFIG['ruby_version_dir_name'] || RbConfig::CONFIG['ruby_version']
+
+ BASE = File.join RbConfig::CONFIG['ridir'], version
+
diff --git a/ruby-2.3.0-ruby_version.patch b/ruby-2.3.0-ruby_version.patch
index 96609a0..7539e6f 100644
--- a/ruby-2.3.0-ruby_version.patch
+++ b/ruby-2.3.0-ruby_version.patch
@@ -1,7 +1,7 @@
From 4fc1be3af3f58621bb751c9e63c208b15c0e8d16 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?V=C3=ADt=20Ondruch?= <vondruch at redhat.com>
Date: Tue, 31 Mar 2015 16:21:04 +0200
-Subject: [PATCH 1/4] Use ruby_version_dir_name for versioned directories.
+Subject: [PATCH 1/3] Use ruby_version_dir_name for versioned directories.
This disallows changing the ruby_version constant by --with-ruby-version
configuration options. The two places version numbers are disallowed as
@@ -144,47 +144,10 @@ index 8a2c066..c81b211 100644
arch=@arch@
-From 518850aba6eee76de7715aae8d37330e34b01983 Mon Sep 17 00:00:00 2001
-From: =?UTF-8?q?V=C3=ADt=20Ondruch?= <vondruch at redhat.com>
-Date: Tue, 31 Mar 2015 16:37:26 +0200
-Subject: [PATCH 2/4] Add ruby_version_dir_name support for RDoc.
-
----
- lib/rdoc/ri/paths.rb | 2 +-
- tool/rbinstall.rb | 2 +-
- 2 files changed, 2 insertions(+), 2 deletions(-)
-
-diff --git a/lib/rdoc/ri/paths.rb b/lib/rdoc/ri/paths.rb
-index 970cb91..5bf8230 100644
---- a/lib/rdoc/ri/paths.rb
-+++ b/lib/rdoc/ri/paths.rb
-@@ -10,7 +10,7 @@ module RDoc::RI::Paths
- #:stopdoc:
- require 'rbconfig'
-
-- version = RbConfig::CONFIG['ruby_version']
-+ version = RbConfig::CONFIG['ruby_version_dir_name'] || RbConfig::CONFIG['ruby_version']
-
- BASE = File.join RbConfig::CONFIG['ridir'], version
-
-diff --git a/tool/rbinstall.rb b/tool/rbinstall.rb
-index d4c110e..d39c9a6 100755
---- a/tool/rbinstall.rb
-+++ b/tool/rbinstall.rb
-@@ -945,7 +945,7 @@ def (bins = []).add(name)
-
- install?(:doc, :rdoc) do
- if $rdocdir
-- ridatadir = File.join(CONFIG['ridir'], CONFIG['ruby_version'], "system")
-+ ridatadir = File.join(CONFIG['ridir'], CONFIG['ruby_version_dir_name'] || CONFIG['ruby_version'], "system")
- prepare "rdoc", ridatadir
- install_recursive($rdocdir, ridatadir, :no_install => rdoc_noinst, :mode => $data_mode)
- end
-
From 9f0ec0233f618cbb862629816b22491c3df79578 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?V=C3=ADt=20Ondruch?= <vondruch at redhat.com>
Date: Tue, 31 Mar 2015 16:37:44 +0200
-Subject: [PATCH 3/4] Add ruby_version_dir_name support for RubyGems.
+Subject: [PATCH 2/3] Add ruby_version_dir_name support for RubyGems.
---
lib/rubygems/defaults.rb | 7 ++++---
@@ -251,7 +214,7 @@ index b25068405d..e9fef4a311 100644
From 88c38a030c22dbf9422ece847bdfbf87d6659313 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?V=C3=ADt=20Ondruch?= <vondruch at redhat.com>
Date: Wed, 1 Apr 2015 14:55:37 +0200
-Subject: [PATCH 4/4] Let headers directories follow the configured version
+Subject: [PATCH 3/3] Let headers directories follow the configured version
name.
---
diff --git a/ruby-2.7.0-Initialize-ABRT-hook.patch b/ruby-2.7.0-Initialize-ABRT-hook.patch
index 65d1e65..d328ebc 100644
--- a/ruby-2.7.0-Initialize-ABRT-hook.patch
+++ b/ruby-2.7.0-Initialize-ABRT-hook.patch
@@ -1,4 +1,4 @@
-From eca084e4079c77c061045df9c21b219175b05228 Mon Sep 17 00:00:00 2001
+From 03b44a86b574dc0b63fd57c5f9b52b56ad3ced37 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?V=C3=ADt=20Ondruch?= <vondruch at redhat.com>
Date: Mon, 6 Jan 2020 13:56:04 +0100
Subject: [PATCH] Initialize ABRT hook.
@@ -16,15 +16,15 @@ To keep the things simple for now, load the ABRT hook via C.
[5]: https://lists.fedoraproject.org/archives/list/ruby-sig@lists.fedoraproject.org/message/LH6L6YJOYQT4Y5ZNOO4SLIPTUWZ5V45Q/
---
abrt.c | 12 ++++++++++++
- common.mk | 3 ++-
+ common.mk | 1 +
ruby.c | 4 ++++
spec/ruby/core/kernel/require_spec.rb | 2 ++
- 4 files changed, 20 insertions(+), 1 deletion(-)
+ 4 files changed, 19 insertions(+)
create mode 100644 abrt.c
diff --git a/abrt.c b/abrt.c
new file mode 100644
-index 0000000000..74b0bd5c0f
+index 0000000000..e99cb432e6
--- /dev/null
+++ b/abrt.c
@@ -0,0 +1,12 @@
@@ -41,25 +41,23 @@ index 0000000000..74b0bd5c0f
+ );
+}
diff --git a/common.mk b/common.mk
-index b2e5b2b6d0..f39f81da5c 100644
+index 08fee9119a..dae7d9dc00 100644
--- a/common.mk
+++ b/common.mk
-@@ -110,7 +110,8 @@ PRISM_FILES = prism/api_node.$(OBJEXT) \
- prism/prism.$(OBJEXT) \
+@@ -116,6 +116,7 @@ PRISM_FILES = prism/api_node.$(OBJEXT) \
prism_init.$(OBJEXT)
--COMMONOBJS = array.$(OBJEXT) \
-+COMMONOBJS = abrt.$(OBJEXT) \
-+ array.$(OBJEXT) \
+ COMMONOBJS = \
++ abrt.$(OBJEXT) \
+ array.$(OBJEXT) \
ast.$(OBJEXT) \
bignum.$(OBJEXT) \
- class.$(OBJEXT) \
diff --git a/ruby.c b/ruby.c
-index 60c57d6259..1eec16f2c8 100644
+index b00fc1502d..32b88f7496 100644
--- a/ruby.c
+++ b/ruby.c
-@@ -1744,10 +1744,14 @@ proc_options(long argc, char **argv, ruby_cmdline_options_t *opt, int envopt)
-
+@@ -1793,10 +1793,14 @@ proc_options(long argc, char **argv, ruby_cmdline_options_t *opt, int envopt)
+ VALUE rb_define_gem_modules(VALUE, VALUE);
void Init_builtin_features(void);
+/* abrt.c */
@@ -70,14 +68,14 @@ index 60c57d6259..1eec16f2c8 100644
{
Init_builtin_features();
+ Init_abrt();
- rb_const_remove(rb_cObject, rb_intern_const("TMP_RUBY_PREFIX"));
}
+ void rb_call_builtin_inits(void);
diff --git a/spec/ruby/core/kernel/require_spec.rb b/spec/ruby/core/kernel/require_spec.rb
-index 60c57d6259..1eec16f2c8 100644
+index 60d17242fe..a8f93b0db4 100644
--- a/spec/ruby/core/kernel/require_spec.rb
+++ b/spec/ruby/core/kernel/require_spec.rb
-@@ -25,6 +25,8 @@
+@@ -26,6 +26,8 @@
out = ruby_exe("puts $LOADED_FEATURES", options: '--disable-gems --disable-did-you-mean')
features = out.lines.map { |line| File.basename(line.chomp, '.*') }
diff --git a/ruby-3.2.0-build-extension-libraries-in-bundled-gems.patch b/ruby-3.2.0-build-extension-libraries-in-bundled-gems.patch
deleted file mode 100644
index de8d4d3..0000000
--- a/ruby-3.2.0-build-extension-libraries-in-bundled-gems.patch
+++ /dev/null
@@ -1,338 +0,0 @@
-From 111f8422427d78becc9183ae149b2105a16bf327 Mon Sep 17 00:00:00 2001
-From: Nobuyoshi Nakada <nobu at ruby-lang.org>
-Date: Tue, 5 Apr 2022 23:24:00 +0900
-Subject: [PATCH 1/5] Bundled gems are expanded under `.bundle/gems` now
-
----
- ext/extmk.rb | 13 +++++++------
- template/exts.mk.tmpl | 2 +-
- 2 files changed, 8 insertions(+), 7 deletions(-)
-
-diff --git a/ext/extmk.rb b/ext/extmk.rb
-index 4a087f294ac9..1da9e2704521 100755
---- a/ext/extmk.rb
-+++ b/ext/extmk.rb
-@@ -146,7 +146,7 @@ def extmake(target, basedir = 'ext', maybestatic = true)
- top_srcdir = $top_srcdir
- topdir = $topdir
- hdrdir = $hdrdir
-- prefix = "../" * (target.count("/")+1)
-+ prefix = "../" * (basedir.count("/")+target.count("/")+1)
- $top_srcdir = relative_from(top_srcdir, prefix)
- $hdrdir = relative_from(hdrdir, prefix)
- $topdir = prefix + $topdir
-@@ -460,10 +460,11 @@ def $mflags.defined?(var)
- end unless $extstatic
-
- @gemname = nil
--if ARGV[0]
-- ext_prefix, exts = ARGV.shift.split('/', 2)
-+if exts = ARGV.shift
-+ ext_prefix = exts[%r[\A(?>\.bundle/)?[^/]+(?:/(?=(.+)?)|\z)]]
-+ exts = $1
- $extension = [exts] if exts
-- if ext_prefix == 'gems'
-+ if ext_prefix.start_with?('.')
- @gemname = exts
- elsif exts
- $static_ext.delete_if {|t, *| !File.fnmatch(t, exts)}
-@@ -515,7 +516,7 @@ def $mflags.defined?(var)
- exts.delete_if {|d| File.fnmatch?("-*", d)}
- end
- end
--ext_prefix = File.basename(ext_prefix)
-+ext_prefix = ext_prefix[$top_srcdir.size+1..-2]
-
- extend Module.new {
- def timestamp_file(name, target_prefix = nil)
-@@ -634,7 +635,7 @@ def initialize(src)
- end
- }
-
--Dir.chdir ".."
-+Dir.chdir dir
- unless $destdir.to_s.empty?
- $mflags.defined?("DESTDIR") or $mflags << "DESTDIR=#{$destdir}"
- end
-diff --git a/template/exts.mk.tmpl b/template/exts.mk.tmpl
-index 2f37f4480ac5..964939e365a1 100644
---- a/template/exts.mk.tmpl
-+++ b/template/exts.mk.tmpl
-@@ -25,7 +25,7 @@ macros["old_extensions"] = []
-
- contpat = /(?>(?>[^\\\n]|\\.)*\\\n)*(?>[^\\\n]|\\.)*/
- Dir.glob("{ext,.bundle/gems}/*/exts.mk") do |e|
-- gem = /\Agems(?=\/)/ =~ e
-+ gem = e.start_with?(".bundle/gems/")
- s = File.read(e)
- s.scan(/^(extensions|SUBMAKEOPTS|EXT[A-Z]+|MFLAGS|NOTE_[A-Z]+)[ \t]*=[ \t]*(#{contpat})$/o) do |n, v|
- v.gsub!(/\\\n[ \t]*/, ' ')
-
-From 6ea34cac22131d28a9cc50e7875e854aed9bdb88 Mon Sep 17 00:00:00 2001
-From: Nobuyoshi Nakada <nobu at ruby-lang.org>
-Date: Wed, 6 Apr 2022 20:25:53 +0900
-Subject: [PATCH 2/5] Retrieve configured gems info
-
----
- template/configure-ext.mk.tmpl | 2 +-
- template/exts.mk.tmpl | 4 ++--
- 2 files changed, 3 insertions(+), 3 deletions(-)
-
-diff --git a/template/configure-ext.mk.tmpl b/template/configure-ext.mk.tmpl
-index 6636a7759c54..8ba6b963e3ec 100644
---- a/template/configure-ext.mk.tmpl
-+++ b/template/configure-ext.mk.tmpl
-@@ -27,7 +27,7 @@ SCRIPT_ARGS = <%=script_args.gsub("#", "\\#")%>
- EXTMK_ARGS = $(SCRIPT_ARGS) --gnumake=$(gnumake) --extflags="$(EXTLDFLAGS)" \
- --make-flags="MINIRUBY='$(MINIRUBY)'"
-
--all: exts # gems
-+all: exts gems
- exts:
- gems:
-
-diff --git a/template/exts.mk.tmpl b/template/exts.mk.tmpl
-index 964939e365a1..e544c4c88bd7 100644
---- a/template/exts.mk.tmpl
-+++ b/template/exts.mk.tmpl
-@@ -19,7 +19,7 @@ opt = OptionParser.new do |o|
- o.on('--configure-exts=FILE') {|v| confexts = v}
- o.order!(ARGV)
- end
--confexts &&= File.read(confexts).scan(/^exts: (.*\.mk)/).flatten rescue nil
-+confexts &&= File.read(confexts).scan(/^(?:ext|gem)s: (.*\.mk)/).flatten rescue nil
- confexts ||= []
- macros["old_extensions"] = []
-
-@@ -30,7 +30,7 @@ Dir.glob("{ext,.bundle/gems}/*/exts.mk") do |e|
- s.scan(/^(extensions|SUBMAKEOPTS|EXT[A-Z]+|MFLAGS|NOTE_[A-Z]+)[ \t]*=[ \t]*(#{contpat})$/o) do |n, v|
- v.gsub!(/\\\n[ \t]*/, ' ')
- next if v.empty?
-- next if gem and n != "extensions"
-+ next if n != "extensions"
- n = "old_extensions" if n == "extensions" and !confexts.include?(e)
- v = v.split
- m = macros[n] ||= []
-
-From be9d00ee7c72766551ba8c3530f1538034498a6a Mon Sep 17 00:00:00 2001
-From: Nobuyoshi Nakada <nobu at ruby-lang.org>
-Date: Wed, 6 Apr 2022 20:28:00 +0900
-Subject: [PATCH 3/5] Move the target directory of bundled gems like as
- rubygems
-
----
- ext/extmk.rb | 6 +++++-
- 1 file changed, 5 insertions(+), 1 deletion(-)
-
-diff --git a/ext/extmk.rb b/ext/extmk.rb
-index 1da9e2704521..a440af27fc5d 100755
---- a/ext/extmk.rb
-+++ b/ext/extmk.rb
-@@ -2,6 +2,9 @@
- # -*- mode: ruby; coding: us-ascii -*-
- # frozen_string_literal: false
-
-+module Gem; end # only needs Gem::Platform
-+require 'rubygems/platform'
-+
- # :stopdoc:
- $extension = nil
- $extstatic = nil
-@@ -535,11 +538,12 @@ def create_makefile(*args, &block)
- super(*args) do |conf|
- conf.find do |s|
- s.sub!(/^(TARGET_SO_DIR *= *)\$\(RUBYARCHDIR\)/) {
-- "TARGET_GEM_DIR = $(extout)/gems/$(arch)/#{@gemname}\n"\
-+ "TARGET_GEM_DIR = $(topdir)/.bundle/extensions/$(gem_platform)/$(ruby_version)/#{@gemname}\n"\
- "#{$1}$(TARGET_GEM_DIR)$(target_prefix)"
- }
- end
- conf.any? {|s| /^TARGET *= *\S/ =~ s} and conf << %{
-+gem_platform = #{Gem::Platform.local}
-
- # default target
- all:
-
-From c4daf8e445925695c34bab8bf5135dcd1e8575a3 Mon Sep 17 00:00:00 2001
-From: Nobuyoshi Nakada <nobu at ruby-lang.org>
-Date: Wed, 6 Apr 2022 22:57:01 +0900
-Subject: [PATCH 4/5] Obey spec file locations to rubygems
-
----
- common.mk | 3 ++-
- defs/gmake.mk | 2 +-
- tool/gem-unpack.rb | 5 +++--
- 3 files changed, 6 insertions(+), 4 deletions(-)
-
-diff --git a/common.mk b/common.mk
-index 7c552cba1e04..b4adb2729c0e 100644
---- a/common.mk
-+++ b/common.mk
-@@ -1359,10 +1359,11 @@ extract-gems$(gnumake:yes=-nongnumake): PHONY
- $(Q) $(RUNRUBY) -C "$(srcdir)" \
- -Itool -rgem-unpack -answ \
- -e 'BEGIN {FileUtils.mkdir_p(d = ".bundle/gems")}' \
-+ -e 'BEGIN {FileUtils.mkdir_p(s = ".bundle/specifications")}' \
- -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)' \
-+ -e 'File.directory?("#{d}/#{g}") or Gem.unpack("gems/#{g}.gem", d, s)' \
- gems/bundled_gems
-
- update-bundled_gems: PHONY
-diff --git a/defs/gmake.mk b/defs/gmake.mk
-index a625379a6804..27e3e21cc4d6 100644
---- a/defs/gmake.mk
-+++ b/defs/gmake.mk
-@@ -290,7 +290,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")'
-+ -e 'Gem.unpack("gems/$(@F).gem", ".bundle/gems", ".bundle/specifications")'
-
- $(srcdir)/.bundle/gems:
- $(MAKEDIRS) $@
-diff --git a/tool/gem-unpack.rb b/tool/gem-unpack.rb
-index cb05719463f2..fe10b0e420fa 100644
---- a/tool/gem-unpack.rb
-+++ b/tool/gem-unpack.rb
-@@ -5,13 +5,14 @@
- # This library is used by "make extract-gems" to
- # unpack bundled gem files.
-
--def Gem.unpack(file, dir = nil)
-+def Gem.unpack(file, dir = nil, spec_dir = nil)
- pkg = Gem::Package.new(file)
- spec = pkg.spec
- target = spec.full_name
- target = File.join(dir, target) if dir
- pkg.extract_files target
-- spec_file = File.join(target, "#{spec.name}-#{spec.version}.gemspec")
-+ FileUtils.mkdir_p(spec_dir ||= target)
-+ spec_file = File.join(spec_dir, "#{spec.name}-#{spec.version}.gemspec")
- open(spec_file, 'wb') do |f|
- f.print spec.to_ruby
- end
-
-From 3de652d8198be9cd2998c095903889a80e738275 Mon Sep 17 00:00:00 2001
-From: Nobuyoshi Nakada <nobu at ruby-lang.org>
-Date: Thu, 7 Apr 2022 01:44:43 +0900
-Subject: [PATCH 5/5] Install built gem extension binaries
-
----
- tool/rbinstall.rb | 56 ++++++++++++++---------------------------------
- 1 file changed, 16 insertions(+), 40 deletions(-)
-
-diff --git a/tool/rbinstall.rb b/tool/rbinstall.rb
-index 9d9b672be472..624961b4eee6 100755
---- a/tool/rbinstall.rb
-+++ b/tool/rbinstall.rb
-@@ -858,6 +858,9 @@ class UnpackedInstaller < GemInstaller
- def write_cache_file
- end
-
-+ def build_extensions
-+ end
-+
- def shebang(bin_file_name)
- path = File.join(gem_dir, spec.bindir, bin_file_name)
- first_line = File.open(path, "rb") {|file| file.gets}
-@@ -940,13 +943,12 @@ def ensure_writable_dir(dir)
- install_default_gem('ext', srcdir, bindir)
- end
-
--def load_gemspec(file, expanded = false)
-+def load_gemspec(file, base = nil)
- file = File.realpath(file)
- code = File.read(file, encoding: "utf-8:-")
- code.gsub!(/(?:`git[^\`]*`|%x\[git[^\]]*\])\.split\([^\)]*\)/m) do
- files = []
-- if expanded
-- base = File.dirname(file)
-+ if base
- Dir.glob("**/*", File::FNM_DOTMATCH, base: base) do |n|
- case File.basename(n); when ".", ".."; next; end
- next if File.directory?(File.join(base, n))
-@@ -959,7 +961,7 @@ def load_gemspec(file, expanded = false)
- unless Gem::Specification === spec
- raise TypeError, "[#{file}] isn't a Gem::Specification (#{spec.class} instead)."
- end
-- spec.loaded_from = file
-+ spec.loaded_from = base ? File.join(base, File.basename(file)) : file
- spec.files.reject! {|n| n.end_with?(".gemspec") or n.start_with?(".git")}
-
- spec
-@@ -1014,20 +1016,6 @@ def install_default_gem(dir, srcdir, bindir)
- end
-
- install?(:ext, :comm, :gem, :'bundled-gems') do
-- if CONFIG['CROSS_COMPILING'] == 'yes'
-- # The following hacky steps set "$ruby = BASERUBY" in tool/fake.rb
-- $hdrdir = ''
-- $extmk = nil
-- $ruby = nil # ...
-- ruby_path = $ruby + " -I#{Dir.pwd}" # $baseruby + " -I#{Dir.pwd}"
-- else
-- # ruby_path = File.expand_path(with_destdir(File.join(bindir, ruby_install_name)))
-- ENV['RUBYLIB'] = nil
-- ENV['RUBYOPT'] = nil
-- ruby_path = File.expand_path(with_destdir(File.join(bindir, ruby_install_name))) + " --disable=gems -I#{with_destdir(archlibdir)}"
-- end
-- Gem.instance_variable_set(:@ruby, ruby_path) if Gem.ruby != ruby_path
--
- gem_dir = Gem.default_dir
- install_dir = with_destdir(gem_dir)
- prepare "bundled gems", gem_dir
-@@ -1047,40 +1035,28 @@ def install_default_gem(dir, srcdir, bindir)
- :wrappers => true,
- :format_executable => true,
- }
-- gem_ext_dir = "#$extout/gems/#{CONFIG['arch']}"
-- extensions_dir = with_destdir(Gem::StubSpecification.gemspec_stub("", gem_dir, gem_dir).extensions_dir)
-+
-+ extensions_dir = Gem::StubSpecification.gemspec_stub("", gem_dir, gem_dir).extensions_dir
-+ specifications_dir = File.join(gem_dir, "specifications")
-+ build_dir = Gem::StubSpecification.gemspec_stub("", ".bundle", ".bundle").extensions_dir
-
- File.foreach("#{srcdir}/gems/bundled_gems") do |name|
- next if /^\s*(?:#|$)/ =~ name
- next unless /^(\S+)\s+(\S+).*/ =~ name
- gem_name = "#$1-#$2"
-- path = "#{srcdir}/.bundle/gems/#{gem_name}/#{gem_name}.gemspec"
-- if File.exist?(path)
-- spec = load_gemspec(path)
-- else
-- path = "#{srcdir}/.bundle/gems/#{gem_name}/#$1.gemspec"
-- next unless File.exist?(path)
-- spec = load_gemspec(path, true)
-- end
-+ path = "#{srcdir}/.bundle/specifications/#{gem_name}.gemspec"
-+ next unless File.exist?(path)
-+ spec = load_gemspec(path, "#{srcdir}/.bundle/gems/#{gem_name}")
- next unless spec.platform == Gem::Platform::RUBY
- next unless spec.full_name == gem_name
-- if !spec.extensions.empty? && CONFIG["EXTSTATIC"] == "static"
-- puts "skip installation of #{spec.name} #{spec.version}; bundled gem with an extension library is not supported on --with-static-linked-ext"
-- next
-- end
- spec.extension_dir = "#{extensions_dir}/#{spec.full_name}"
-- if File.directory?(ext = "#{gem_ext_dir}/#{spec.full_name}")
-- spec.extensions[0] ||= "-"
-- end
- package = RbInstall::DirPackage.new spec
- ins = RbInstall::UnpackedInstaller.new(package, options)
- puts "#{INDENT}#{spec.name} #{spec.version}"
- ins.install
-- unless $dryrun
-- File.chmod($data_mode, File.join(install_dir, "specifications", "#{spec.full_name}.gemspec"))
-- end
-- unless spec.extensions.empty?
-- install_recursive(ext, spec.extension_dir)
-+ install_recursive("#{build_dir}/#{gem_name}", "#{extensions_dir}/#{gem_name}") do |src, dest|
-+ # puts "#{INDENT} #{dest[extensions_dir.size+gem_name.size+2..-1]}"
-+ install src, dest, :mode => (File.executable?(src) ? $prog_mode : $data_mode)
- end
- installed_gems[spec.full_name] = true
- end
diff --git a/ruby-3.4.2-openssl-Fix-SHA-1-PSS-tests.patch b/ruby-3.4.2-openssl-Fix-SHA-1-PSS-tests.patch
deleted file mode 100644
index 26ca3ec..0000000
--- a/ruby-3.4.2-openssl-Fix-SHA-1-PSS-tests.patch
+++ /dev/null
@@ -1,136 +0,0 @@
-From e0e771b76fbede656fe51c8bf18ce810f4afeee0 Mon Sep 17 00:00:00 2001
-From: Jun Aruga <jaruga at redhat.com>
-Date: Tue, 8 Apr 2025 15:03:06 +0200
-Subject: [PATCH] Fix the tests using SHA-1 Probabilistic Signature Scheme
- (PSS) parameters.
-
-Fedora OpenSSL 3.5 on rawhide stopped accepting SHA-1 PSS[1] parameters.
-This is different from the SHA-1 signatures which Fedora OpenSSL stopped
-accepting since Fedora 41.[2]
-
-This commit fixes the following test failures related to the SHA-1 PSS
-parameters with Fedora OpenSSL 3.5.
-Note these failures are the downstream Fedora OpenSSL RPM specific. The tests
-pass without this commit with the upstream OpenSSL 3.5.
-
-```
-$ rpm -q openssl-libs openssl-devel
-openssl-libs-3.5.0-2.fc43.x86_64
-openssl-devel-3.5.0-2.fc43.x86_64
-
-$ bundle exec rake test
-...
-E
-===============================================================================================
-Error: test_sign_verify_options(OpenSSL::TestPKeyRSA): OpenSSL::PKey::PKeyError: EVP_PKEY_CTX_ctrl_str(ctx, "rsa_mgf1_md", "SHA1"): digest not allowed (digest=SHA1)
-/mnt/git/ruby/openssl/test/openssl/test_pkey_rsa.rb:113:in 'Hash#each'
-/mnt/git/ruby/openssl/test/openssl/test_pkey_rsa.rb:113:in 'OpenSSL::PKey::PKey#sign'
-/mnt/git/ruby/openssl/test/openssl/test_pkey_rsa.rb:113:in 'OpenSSL::TestPKeyRSA#test_sign_verify_options'
- 110: "rsa_pss_saltlen" => 20,
- 111: "rsa_mgf1_md" => "SHA1"
- 112: }
- => 113: sig_pss = key.sign("SHA256", data, pssopts)
- 114: assert_equal 256, sig_pss.bytesize
- 115: assert_equal true, key.verify("SHA256", sig_pss, data, pssopts)
- 116: assert_equal true, key.verify_pss("SHA256", sig_pss, data,
-===============================================================================================
-E
-===============================================================================================
-Error: test_sign_verify_pss(OpenSSL::TestPKeyRSA): OpenSSL::PKey::RSAError: digest not allowed (digest=SHA1)
-/mnt/git/ruby/openssl/test/openssl/test_pkey_rsa.rb:191:in 'OpenSSL::PKey::RSA#sign_pss'
-/mnt/git/ruby/openssl/test/openssl/test_pkey_rsa.rb:191:in 'OpenSSL::TestPKeyRSA#test_sign_verify_pss'
- 188: data = "Sign me!"
- 189: invalid_data = "Sign me?"
- 190:
- => 191: signature = key.sign_pss("SHA256", data, salt_length: 20, mgf1_hash: "SHA1")
- 192: assert_equal 256, signature.bytesize
- 193: assert_equal true,
- 194: key.verify_pss("SHA256", signature, data, salt_length: 20, mgf1_hash: "SHA1")
-===============================================================================================
-...
-577 tests, 4186 assertions, 0 failures, 2 errors, 0 pendings, 3 omissions, 0 notifications
-```
-
-[1] https://en.wikipedia.org/wiki/Probabilistic_signature_scheme
-[2] https://fedoraproject.org/wiki/Changes/OpenSSLDistrustSHA1SigVer
----
- test/openssl/test_pkey_rsa.rb | 28 ++++++++++++++--------------
- 1 file changed, 14 insertions(+), 14 deletions(-)
-
-diff --git a/test/openssl/test_pkey_rsa.rb b/test/openssl/test_pkey_rsa.rb
-index 360309b..850c16a 100644
---- a/test/openssl/test_pkey_rsa.rb
-+++ b/test/openssl/test_pkey_rsa.rb
-@@ -108,13 +108,13 @@ def test_sign_verify_options
- pssopts = {
- "rsa_padding_mode" => "pss",
- "rsa_pss_saltlen" => 20,
-- "rsa_mgf1_md" => "SHA1"
-+ "rsa_mgf1_md" => "SHA256"
- }
- sig_pss = key.sign("SHA256", data, pssopts)
- assert_equal 256, sig_pss.bytesize
- assert_equal true, key.verify("SHA256", sig_pss, data, pssopts)
- assert_equal true, key.verify_pss("SHA256", sig_pss, data,
-- salt_length: 20, mgf1_hash: "SHA1")
-+ salt_length: 20, mgf1_hash: "SHA256")
- # Defaults to PKCS #1 v1.5 padding => verification failure
- assert_equal false, key.verify("SHA256", sig_pss, data)
-
-@@ -188,22 +188,22 @@ def test_sign_verify_pss
- data = "Sign me!"
- invalid_data = "Sign me?"
-
-- signature = key.sign_pss("SHA256", data, salt_length: 20, mgf1_hash: "SHA1")
-+ signature = key.sign_pss("SHA256", data, salt_length: 20, mgf1_hash: "SHA256")
- assert_equal 256, signature.bytesize
- assert_equal true,
-- key.verify_pss("SHA256", signature, data, salt_length: 20, mgf1_hash: "SHA1")
-+ key.verify_pss("SHA256", signature, data, salt_length: 20, mgf1_hash: "SHA256")
- assert_equal true,
-- key.verify_pss("SHA256", signature, data, salt_length: :auto, mgf1_hash: "SHA1")
-+ key.verify_pss("SHA256", signature, data, salt_length: :auto, mgf1_hash: "SHA256")
- assert_equal false,
-- key.verify_pss("SHA256", signature, invalid_data, salt_length: 20, mgf1_hash: "SHA1")
-+ key.verify_pss("SHA256", signature, invalid_data, salt_length: 20, mgf1_hash: "SHA256")
-
-- signature = key.sign_pss("SHA256", data, salt_length: :digest, mgf1_hash: "SHA1")
-+ signature = key.sign_pss("SHA256", data, salt_length: :digest, mgf1_hash: "SHA256")
- assert_equal true,
-- key.verify_pss("SHA256", signature, data, salt_length: 32, mgf1_hash: "SHA1")
-+ key.verify_pss("SHA256", signature, data, salt_length: 32, mgf1_hash: "SHA256")
- assert_equal true,
-- key.verify_pss("SHA256", signature, data, salt_length: :auto, mgf1_hash: "SHA1")
-+ key.verify_pss("SHA256", signature, data, salt_length: :auto, mgf1_hash: "SHA256")
- assert_equal false,
-- key.verify_pss("SHA256", signature, data, salt_length: 20, mgf1_hash: "SHA1")
-+ key.verify_pss("SHA256", signature, data, salt_length: 20, mgf1_hash: "SHA256")
-
- # The sign_pss with `salt_length: :max` raises the "invalid salt length"
- # error in FIPS. We need to skip the tests in FIPS.
-@@ -213,18 +213,18 @@ def test_sign_verify_pss
- # FIPS 186-5 section 5.4 PKCS #1
- # https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-5.pdf
- unless OpenSSL.fips_mode
-- signature = key.sign_pss("SHA256", data, salt_length: :max, mgf1_hash: "SHA1")
-+ signature = key.sign_pss("SHA256", data, salt_length: :max, mgf1_hash: "SHA256")
- # Should verify on the following salt_length (sLen).
- # sLen <= emLen (octat) - 2 - hLen (octet) = 2048 / 8 - 2 - 256 / 8 = 222
- # https://datatracker.ietf.org/doc/html/rfc8017#section-9.1.1
- assert_equal true,
-- key.verify_pss("SHA256", signature, data, salt_length: 222, mgf1_hash: "SHA1")
-+ key.verify_pss("SHA256", signature, data, salt_length: 222, mgf1_hash: "SHA256")
- assert_equal true,
-- key.verify_pss("SHA256", signature, data, salt_length: :auto, mgf1_hash: "SHA1")
-+ key.verify_pss("SHA256", signature, data, salt_length: :auto, mgf1_hash: "SHA256")
- end
-
- assert_raise(OpenSSL::PKey::RSAError) {
-- key.sign_pss("SHA256", data, salt_length: 223, mgf1_hash: "SHA1")
-+ key.sign_pss("SHA256", data, salt_length: 223, mgf1_hash: "SHA256")
- }
- end
-
---
-2.48.1
-
diff --git a/ruby-4.0.1-Support-customizable-rustc_flags-for-rustc-builds.patch b/ruby-4.0.1-Support-customizable-rustc_flags-for-rustc-builds.patch
new file mode 100644
index 0000000..3d16ff2
--- /dev/null
+++ b/ruby-4.0.1-Support-customizable-rustc_flags-for-rustc-builds.patch
@@ -0,0 +1,117 @@
+From 1cfb11bc8d01e4fc1ff47807721e29b250f0f19f Mon Sep 17 00:00:00 2001
+From: Jarek Prokop <jprokop at redhat.com>
+Date: Mon, 22 Dec 2025 10:13:34 +0100
+Subject: [PATCH] Support customizable rustc_flags for rustc builds.
+
+Add `rustc_flags` option for configure that appends to RUSTC_FLAGS
+flags used when compiling with rustc for customizable build flags.
+It appends to existing defaults in RUSTC_FLAGS.
+
+Co-authored-by: Alan Wu <XrXr at users.noreply.github.com>
+---
+ common.mk | 10 ++--------
+ configure.ac | 8 ++++++++
+ defs/jit.mk | 2 ++
+ template/Makefile.in | 1 +
+ 4 files changed, 13 insertions(+), 8 deletions(-)
+
+diff --git a/common.mk b/common.mk
+index 08fee9119a..9ac5ae919f 100644
+--- a/common.mk
++++ b/common.mk
+@@ -270,21 +270,15 @@ MAKE_LINK = $(MINIRUBY) -rfileutils -e "include FileUtils::Verbose" \
+ # For release builds
+ YJIT_RUSTC_ARGS = --crate-name=yjit \
+ $(JIT_RUST_FLAGS) \
++ $(RUSTC_FLAGS) \
+ --edition=2021 \
+- -g \
+- -C lto=thin \
+- -C opt-level=3 \
+- -C overflow-checks=on \
+ '--out-dir=$(CARGO_TARGET_DIR)/release/' \
+ '$(top_srcdir)/yjit/src/lib.rs'
+
+ ZJIT_RUSTC_ARGS = --crate-name=zjit \
+ $(JIT_RUST_FLAGS) \
++ $(RUSTC_FLAGS) \
+ --edition=2024 \
+- -g \
+- -C lto=thin \
+- -C opt-level=3 \
+- -C overflow-checks=on \
+ '--out-dir=$(CARGO_TARGET_DIR)/release/' \
+ '$(top_srcdir)/zjit/src/lib.rs'
+
+diff --git a/configure.ac b/configure.ac
+index 2bbce78fd0..a3aa6dc383 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -69,6 +69,7 @@ dnl 93(bright yellow) is copied from .github/workflows/mingw.yml
+ AC_ARG_VAR([cflags], [additional CFLAGS (ignored when CFLAGS is given)])dnl
+ AC_ARG_VAR([cppflags], [additional CPPFLAGS (ignored when CPPFLAGS is given)])dnl
+ AC_ARG_VAR([cxxflags], [additional CXXFLAGS (ignored when CXXFLAGS is given)])dnl
++AC_ARG_VAR([rustc_flags], [additional RUSTC_FLAGS])dnl
+
+ [begin]_group "environment section" && {
+ HAVE_BASERUBY=yes
+@@ -4051,6 +4054,11 @@ AS_CASE(["${ZJIT_SUPPORT}"],
+ AC_DEFINE(USE_ZJIT, 0)
+ ])
+
++RUSTC_FLAGS='-g -C lto=thin -C opt-level=3 -C overflow-checks=on'
++AS_IF([test -n "${rustc_flags}"], [
++ RUSTC_FLAGS="${RUSTC_FLAGS} ${rustc_flags}"
++])
++
+ JIT_RUST_FLAGS='--crate-type=staticlib --cfg feature=\"stats_allocator\"'
+ RLIB_DIR=
+ AS_CASE(["$JIT_CARGO_SUPPORT:$YJIT_SUPPORT:$ZJIT_SUPPORT"],
+@@ -4108,6 +4114,7 @@ AS_IF([test -n "$RUST_LIB"], [
+ dnl These variables end up in ::RbConfig::CONFIG
+ AC_SUBST(RUSTC)dnl Rust compiler command
+ AC_SUBST(JIT_RUST_FLAGS)dnl the common rustc flags for JIT crates such as zjit
++AC_SUBST(RUSTC_FLAGS)dnl user-configurable rustc compiler flags
+ AC_SUBST(CARGO)dnl Cargo command for Rust builds
+ AC_SUBST(CARGO_BUILD_ARGS)dnl for selecting Rust build profiles
+ AC_SUBST(YJIT_SUPPORT)dnl what flavor of YJIT the Ruby build includes
+@@ -4852,6 +4859,7 @@ config_summary "strip command" "$STRIP"
+ config_summary "install doc" "$DOCTARGETS"
+ config_summary "YJIT support" "$YJIT_SUPPORT"
+ config_summary "ZJIT support" "$ZJIT_SUPPORT"
++config_summary "RUSTC_FLAGS" "$RUSTC_FLAGS"
+ config_summary "man page type" "$MANTYPE"
+ config_summary "search path" "$search_path"
+ config_summary "static-linked-ext" ${EXTSTATIC:+"yes"}
+diff --git a/defs/jit.mk b/defs/jit.mk
+index 42b56c4cd9..27b14e7a07 100644
+--- a/defs/jit.mk
++++ b/defs/jit.mk
+@@ -40,6 +40,7 @@ else ifneq ($(strip $(RLIB_DIR)),) # combo build
+ $(RUST_LIB): $(srcdir)/ruby.rs
+ $(ECHO) 'building $(@F)'
+ $(gnumake_recursive)$(Q) $(RUSTC) --edition=2024 \
++ $(RUSTC_FLAGS) \
+ '-L$(@D)' \
+ --extern=yjit \
+ --extern=zjit \
+@@ -58,6 +59,7 @@ $(JIT_RLIB):
+ $(gnumake_recursive)$(Q) $(RUSTC) --crate-name=jit \
+ --edition=2024 \
+ $(JIT_RUST_FLAGS) \
++ $(RUSTC_FLAGS) \
+ '--out-dir=$(@D)' \
+ '$(top_srcdir)/jit/src/lib.rs'
+ endif # ifneq ($(JIT_CARGO_SUPPORT),no)
+diff --git a/template/Makefile.in b/template/Makefile.in
+index 443c394cb4..0b7b50e3aa 100644
+--- a/template/Makefile.in
++++ b/template/Makefile.in
+@@ -115,6 +115,7 @@ CARGO_TARGET_DIR=@abs_top_builddir@/target
+ CARGO_BUILD_ARGS=@CARGO_BUILD_ARGS@
+ ZJIT_TEST_FEATURES=@ZJIT_TEST_FEATURES@
+ JIT_RUST_FLAGS=@JIT_RUST_FLAGS@
++RUSTC_FLAGS=@RUSTC_FLAGS@
+ RLIB_DIR=@RLIB_DIR@
+ RUST_LIB=@RUST_LIB@
+ RUST_LIBOBJ = $(RUST_LIB:.a=. at OBJEXT@)
diff --git a/ruby-4.0.7-rubygems-pr9877-stop-vendoring-resolv.patch b/ruby-4.0.7-rubygems-pr9877-stop-vendoring-resolv.patch
new file mode 100644
index 0000000..9c1b3f7
--- /dev/null
+++ b/ruby-4.0.7-rubygems-pr9877-stop-vendoring-resolv.patch
@@ -0,0 +1,3579 @@
+From 0b8e0b1c28bc839095e2c0e884313f0f5ef1fc53 Mon Sep 17 00:00:00 2001
+From: Hiroshi SHIBATA <hsbt at ruby-lang.org>
+Date: Wed, 16 Sep 2026 09:34:09 +0900
+Subject: [PATCH] [ruby/rubygems] Stop vendoring resolv for two regexps
+
+Vendored net/http loaded the whole 3500-line DNS resolver only to match
+Resolv::IPv4::Regex and Resolv::IPv6::Regex when deciding whether an
+address may be sent as a Server Name Indication. Inline equivalent
+regexps instead, so that a resolver RubyGems never resolves with is no
+longer shipped and no longer shows up as an outdated copy in security
+audits of the Ruby tarball.
+
+https://bugs.ruby-lang.org/issues/22317
+
+https://github.com/ruby/rubygems/commit/9f2bd5f66c
+
+Co-Authored-By: Claude Opus 5 <noreply at anthropic.com>
+---
+ lib/rubygems/vendor/net-http/lib/net/http.rb | 26 +-
+ lib/rubygems/vendor/resolv/lib/resolv.rb | 3508 ------------------
+ 2 files changed, 24 insertions(+), 3510 deletions(-)
+ delete mode 100644 lib/rubygems/vendor/resolv/lib/resolv.rb
+
+diff --git a/lib/rubygems/vendor/net-http/lib/net/http.rb b/lib/rubygems/vendor/net-http/lib/net/http.rb
+index 4800cd25f13c21..b205e49734eebf 100644
+--- a/lib/rubygems/vendor/net-http/lib/net/http.rb
++++ b/lib/rubygems/vendor/net-http/lib/net/http.rb
+@@ -22,7 +22,6 @@
+
+ require_relative '../../../net-protocol/lib/net/protocol'
+ require_relative '../../../uri/lib/uri'
+-require_relative '../../../resolv/lib/resolv'
+ autoload :OpenSSL, 'openssl'
+
+ module Gem::Net #:nodoc:
+@@ -1531,6 +1530,29 @@ def use_ssl=(flag)
+
+ SSL_IVNAMES = SSL_ATTRIBUTES.map { |a| "@#{a}".to_sym }.freeze # :nodoc:
+
++ # Resolv::IPv4::Regex and Resolv::IPv6::Regex, copied from resolv 0.7.1 rather
++ # than required, so that net/http does not load a DNS resolver just to keep an
++ # IP address literal out of the Server Name Indication.
++ # https://github.com/ruby/resolv/blob/v0.7.1/lib/resolv.rb
++ ipv4_octet = /0|1(?:[0-9][0-9]?)?|2(?:[0-4][0-9]?|5[0-5]?|[6-9])?|[3-9][0-9]?/
++ hex16 = /[0-9A-Fa-f]{1,4}/
++ hex16_group = /(?:#{hex16}(?::#{hex16})*)?/
++ dotted_quad = /\d+\.\d+\.\d+\.\d+/
++ zone_id = /%[-0-9A-Za-z._~]+/
++
++ IPV4_ADDRESS = /\A(?:#{ipv4_octet})\.(?:#{ipv4_octet})\.(?:#{ipv4_octet})\.(?:#{ipv4_octet})\z/ # :nodoc:
++
++ IPV6_ADDRESS = /\A(?:
++ (?:#{hex16}:){7}#{hex16} # a:b:c:d:e:f:g:h
++ | #{hex16_group}::#{hex16_group} # a::b
++ | (?:#{hex16}:){6}#{dotted_quad} # a:b:c:d:e:f:w.x.y.z
++ | #{hex16_group}::(?:#{hex16}:)*#{dotted_quad} # a::b:w.x.y.z
++ | [Ff][Ee]80(?::#{hex16}){7}#{zone_id} # fe80:b:c:d:e:f:g:h%em1
++ | [Ff][Ee]80:(?:#{hex16_group}::#{hex16_group}|:#{hex16_group})?:#{hex16}#{zone_id} # fe80::b%em1
++ )\z/x # :nodoc:
++
++ private_constant :IPV4_ADDRESS, :IPV6_ADDRESS
++
+ # Sets or returns the path to a CA certification file in PEM format.
+ attr_accessor :ca_file
+
+@@ -1714,7 +1736,7 @@ def connect
+
+ # Server Name Indication (SNI) RFC 3546/6066
+ case @address
+- when Gem::Resolv::IPv4::Regex, Gem::Resolv::IPv6::Regex
++ when IPV4_ADDRESS, IPV6_ADDRESS
+ # don't set SNI, as IP addresses in SNI is not valid
+ # per RFC 6066, section 3.
+
+diff --git a/lib/rubygems/vendor/resolv/lib/resolv.rb b/lib/rubygems/vendor/resolv/lib/resolv.rb
+deleted file mode 100644
+index f922c731b05026..00000000000000
+--- a/lib/rubygems/vendor/resolv/lib/resolv.rb
++++ /dev/null
+@@ -1,3499 +0,0 @@
+-# frozen_string_literal: true
+-
+-require 'socket'
+-require_relative '../../../vendored_timeout'
+-require 'io/wait'
+-require_relative '../../../vendored_securerandom'
+-require 'rbconfig'
+-
+-# Gem::Resolv is a thread-aware DNS resolver library written in Ruby. Gem::Resolv can
+-# handle multiple DNS requests concurrently without blocking the entire Ruby
+-# interpreter.
+-#
+-# See also resolv-replace.rb to replace the libc resolver with Gem::Resolv.
+-#
+-# Gem::Resolv can look up various DNS resources using the DNS module directly.
+-#
+-# Examples:
+-#
+-# p Gem::Resolv.getaddress "www.ruby-lang.org"
+-# p Gem::Resolv.getname "210.251.121.214"
+-#
+-# Gem::Resolv::DNS.open do |dns|
+-# ress = dns.getresources "www.ruby-lang.org", Gem::Resolv::DNS::Resource::IN::A
+-# p ress.map(&:address)
+-# ress = dns.getresources "ruby-lang.org", Gem::Resolv::DNS::Resource::IN::MX
+-# p ress.map { |r| [r.exchange.to_s, r.preference] }
+-# end
+-#
+-#
+-# == Bugs
+-#
+-# * NIS is not supported.
+-# * /etc/nsswitch.conf is not supported.
+-
+-class Gem::Resolv
+-
+- # The version string
+- VERSION = "0.7.0"
+-
+- ##
+- # Looks up the first IP address for +name+.
+-
+- def self.getaddress(name)
+- DefaultResolver.getaddress(name)
+- end
+-
+- ##
+- # Looks up all IP address for +name+.
+-
+- def self.getaddresses(name)
+- DefaultResolver.getaddresses(name)
+- end
+-
+- ##
+- # Iterates over all IP addresses for +name+.
+-
+- def self.each_address(name, &block)
+- DefaultResolver.each_address(name, &block)
+- end
+-
+- ##
+- # Looks up the hostname of +address+.
+-
+- def self.getname(address)
+- DefaultResolver.getname(address)
+- end
+-
+- ##
+- # Looks up all hostnames for +address+.
+-
+- def self.getnames(address)
+- DefaultResolver.getnames(address)
+- end
+-
+- ##
+- # Iterates over all hostnames for +address+.
+-
+- def self.each_name(address, &proc)
+- DefaultResolver.each_name(address, &proc)
+- end
+-
+- ##
+- # Creates a new Gem::Resolv using +resolvers+.
+- #
+- # If +resolvers+ is not given, a hash, or +nil+, uses a Hosts resolver and
+- # and a DNS resolver. If +resolvers+ is a hash, uses the hash as
+- # configuration for the DNS resolver.
+-
+- def initialize(resolvers=(arg_not_set = true; nil), use_ipv6: (keyword_not_set = true; nil))
+- if !keyword_not_set && !arg_not_set
+- warn "Support for separate use_ipv6 keyword is deprecated, as it is ignored if an argument is provided. Do not provide a positional argument if using the use_ipv6 keyword argument.", uplevel: 1
+- end
+-
+- @resolvers = case resolvers
+- when Hash, nil
+- [Hosts.new, DNS.new(DNS::Config.default_config_hash.merge(resolvers || {}))]
+- else
+- resolvers
+- end
+- end
+-
+- ##
+- # Looks up the first IP address for +name+.
+-
+- def getaddress(name)
+- each_address(name) {|address| return address}
+- raise ResolvError.new("no address for #{name}")
+- end
+-
+- ##
+- # Looks up all IP address for +name+.
+-
+- def getaddresses(name)
+- ret = []
+- each_address(name) {|address| ret << address}
+- return ret
+- end
+-
+- ##
+- # Iterates over all IP addresses for +name+.
+-
+- def each_address(name)
+- if AddressRegex =~ name
+- yield name
+- return
+- end
+- yielded = false
+- @resolvers.each {|r|
+- r.each_address(name) {|address|
+- yield address.to_s
+- yielded = true
+- }
+- return if yielded
+- }
+- end
+-
+- ##
+- # Looks up the hostname of +address+.
+-
+- def getname(address)
+- each_name(address) {|name| return name}
+- raise ResolvError.new("no name for #{address}")
+- end
+-
+- ##
+- # Looks up all hostnames for +address+.
+-
+- def getnames(address)
+- ret = []
+- each_name(address) {|name| ret << name}
+- return ret
+- end
+-
+- ##
+- # Iterates over all hostnames for +address+.
+-
+- def each_name(address)
+- yielded = false
+- @resolvers.each {|r|
+- r.each_name(address) {|name|
+- yield name.to_s
+- yielded = true
+- }
+- return if yielded
+- }
+- end
+-
+- ##
+- # Indicates a failure to resolve a name or address.
+-
+- class ResolvError < StandardError; end
+-
+- ##
+- # Indicates a timeout resolving a name or address.
+-
+- class ResolvTimeout < Gem::Timeout::Error; end
+-
+- ##
+- # Gem::Resolv::Hosts is a hostname resolver that uses the system hosts file.
+-
+- class Hosts
+- if /mswin|cygwin|mingw|bccwin/ =~ RUBY_PLATFORM || ::RbConfig::CONFIG['host_os'] =~ /mswin/
+- begin
+- require 'win32/resolv' unless defined?(Win32::Resolv)
+- hosts = Win32::Resolv.get_hosts_path || IO::NULL
+- rescue LoadError
+- end
+- end
+- # The default file name for host names
+- DefaultFileName = hosts || '/etc/hosts'
+-
+- ##
+- # Creates a new Gem::Resolv::Hosts, using +filename+ for its data source.
+-
+- def initialize(filename = DefaultFileName)
+- @filename = filename
+- @mutex = Thread::Mutex.new
+- @initialized = nil
+- end
+-
+- def lazy_initialize # :nodoc:
+- @mutex.synchronize {
+- unless @initialized
+- @name2addr = {}
+- @addr2name = {}
+- File.open(@filename, 'rb') {|f|
+- f.each {|line|
+- line.sub!(/#.*/, '')
+- addr, *hostnames = line.split(/\s+/)
+- next unless addr
+- (@addr2name[addr] ||= []).concat(hostnames)
+- hostnames.each {|hostname| (@name2addr[hostname] ||= []) << addr}
+- }
+- }
+- @name2addr.each {|name, arr| arr.reverse!}
+- @initialized = true
+- end
+- }
+- self
+- end
+-
+- ##
+- # Gets the IP address of +name+ from the hosts file.
+-
+- def getaddress(name)
+- each_address(name) {|address| return address}
+- raise ResolvError.new("#{@filename} has no name: #{name}")
+- end
+-
+- ##
+- # Gets all IP addresses for +name+ from the hosts file.
+-
+- def getaddresses(name)
+- ret = []
+- each_address(name) {|address| ret << address}
+- return ret
+- end
+-
+- ##
+- # Iterates over all IP addresses for +name+ retrieved from the hosts file.
+-
+- def each_address(name, &proc)
+- lazy_initialize
+- @name2addr[name]&.each(&proc)
+- end
+-
+- ##
+- # Gets the hostname of +address+ from the hosts file.
+-
+- def getname(address)
+- each_name(address) {|name| return name}
+- raise ResolvError.new("#{@filename} has no address: #{address}")
+- end
+-
+- ##
+- # Gets all hostnames for +address+ from the hosts file.
+-
+- def getnames(address)
+- ret = []
+- each_name(address) {|name| ret << name}
+- return ret
+- end
+-
+- ##
+- # Iterates over all hostnames for +address+ retrieved from the hosts file.
+-
+- def each_name(address, &proc)
+- lazy_initialize
+- @addr2name[address]&.each(&proc)
+- end
+- end
+-
+- ##
+- # Gem::Resolv::DNS is a DNS stub resolver.
+- #
+- # Information taken from the following places:
+- #
+- # * STD0013
+- # * RFC 1035
+- # * ftp://ftp.isi.edu/in-notes/iana/assignments/dns-parameters
+- # * etc.
+-
+- class DNS
+-
+- ##
+- # Default DNS Port
+-
+- Port = 53
+-
+- ##
+- # Default DNS UDP packet size
+-
+- UDPSize = 512
+-
+- ##
+- # Creates a new DNS resolver. See Gem::Resolv::DNS.new for argument details.
+- #
+- # Yields the created DNS resolver to the block, if given, otherwise
+- # returns it.
+-
+- def self.open(*args)
+- dns = new(*args)
+- return dns unless block_given?
+- begin
+- yield dns
+- ensure
+- dns.close
+- end
+- end
+-
+- ##
+- # Creates a new DNS resolver.
+- #
+- # +config_info+ can be:
+- #
+- # nil:: Uses /etc/resolv.conf.
+- # String:: Path to a file using /etc/resolv.conf's format.
+- # Hash:: Must contain :nameserver, :search and :ndots keys.
+- # :nameserver_port can be used to specify port number of nameserver address.
+- # :raise_timeout_errors can be used to raise timeout errors
+- # as exceptions instead of treating the same as an NXDOMAIN response.
+- #
+- # The value of :nameserver should be an address string or
+- # an array of address strings.
+- # - :nameserver => '8.8.8.8'
+- # - :nameserver => ['8.8.8.8', '8.8.4.4']
+- #
+- # The value of :nameserver_port should be an array of
+- # pair of nameserver address and port number.
+- # - :nameserver_port => [['8.8.8.8', 53], ['8.8.4.4', 53]]
+- #
+- # Example:
+- #
+- # Gem::Resolv::DNS.new(:nameserver => ['210.251.121.21'],
+- # :search => ['ruby-lang.org'],
+- # :ndots => 1)
+-
+- def initialize(config_info=nil)
+- @mutex = Thread::Mutex.new
+- @config = Config.new(config_info)
+- @initialized = nil
+- end
+-
+- # Sets the resolver timeouts. This may be a single positive number
+- # or an array of positive numbers representing timeouts in seconds.
+- # If an array is specified, a DNS request will retry and wait for
+- # each successive interval in the array until a successful response
+- # is received. Specifying +nil+ reverts to the default timeouts:
+- # [ 5, second = 5 * 2 / nameserver_count, 2 * second, 4 * second ]
+- #
+- # Example:
+- #
+- # dns.timeouts = 3
+- #
+- def timeouts=(values)
+- @config.timeouts = values
+- end
+-
+- def lazy_initialize # :nodoc:
+- @mutex.synchronize {
+- unless @initialized
+- @config.lazy_initialize
+- @initialized = true
+- end
+- }
+- self
+- end
+-
+- ##
+- # Closes the DNS resolver.
+-
+- def close
+- @mutex.synchronize {
+- if @initialized
+- @initialized = false
+- end
+- }
+- end
+-
+- ##
+- # Gets the IP address of +name+ from the DNS resolver.
+- #
+- # +name+ can be a Gem::Resolv::DNS::Name or a String. Retrieved address will
+- # be a Gem::Resolv::IPv4 or Gem::Resolv::IPv6
+-
+- def getaddress(name)
+- each_address(name) {|address| return address}
+- raise ResolvError.new("DNS result has no information for #{name}")
+- end
+-
+- ##
+- # Gets all IP addresses for +name+ from the DNS resolver.
+- #
+- # +name+ can be a Gem::Resolv::DNS::Name or a String. Retrieved addresses will
+- # be a Gem::Resolv::IPv4 or Gem::Resolv::IPv6
+-
+- def getaddresses(name)
+- ret = []
+- each_address(name) {|address| ret << address}
+- return ret
+- end
+-
+- ##
+- # Iterates over all IP addresses for +name+ retrieved from the DNS
+- # resolver.
+- #
+- # +name+ can be a Gem::Resolv::DNS::Name or a String. Retrieved addresses will
+- # be a Gem::Resolv::IPv4 or Gem::Resolv::IPv6
+-
+- def each_address(name)
+- if use_ipv6?
+- each_resource(name, Resource::IN::AAAA) {|resource| yield resource.address}
+- end
+- each_resource(name, Resource::IN::A) {|resource| yield resource.address}
+- end
+-
+- def use_ipv6? # :nodoc:
+- @config.lazy_initialize unless @config.instance_variable_get(:@initialized)
+-
+- use_ipv6 = @config.use_ipv6?
+- unless use_ipv6.nil?
+- return use_ipv6
+- end
+-
+- begin
+- list = Socket.ip_address_list
+- rescue NotImplementedError
+- return true
+- end
+- list.any? {|a| a.ipv6? && !a.ipv6_loopback? && !a.ipv6_linklocal? }
+- end
+- private :use_ipv6?
+-
+- ##
+- # Gets the hostname for +address+ from the DNS resolver.
+- #
+- # +address+ must be a Gem::Resolv::IPv4, Gem::Resolv::IPv6 or a String. Retrieved
+- # name will be a Gem::Resolv::DNS::Name.
+-
+- def getname(address)
+- each_name(address) {|name| return name}
+- raise ResolvError.new("DNS result has no information for #{address}")
+- end
+-
+- ##
+- # Gets all hostnames for +address+ from the DNS resolver.
+- #
+- # +address+ must be a Gem::Resolv::IPv4, Gem::Resolv::IPv6 or a String. Retrieved
+- # names will be Gem::Resolv::DNS::Name instances.
+-
+- def getnames(address)
+- ret = []
+- each_name(address) {|name| ret << name}
+- return ret
+- end
+-
+- ##
+- # Iterates over all hostnames for +address+ retrieved from the DNS
+- # resolver.
+- #
+- # +address+ must be a Gem::Resolv::IPv4, Gem::Resolv::IPv6 or a String. Retrieved
+- # names will be Gem::Resolv::DNS::Name instances.
+-
+- def each_name(address)
+- case address
+- when Name
+- ptr = address
+- when IPv4, IPv6
+- ptr = address.to_name
+- when IPv4::Regex
+- ptr = IPv4.create(address).to_name
+- when IPv6::Regex
+- ptr = IPv6.create(address).to_name
+- else
+- raise ResolvError.new("cannot interpret as address: #{address}")
+- end
+- each_resource(ptr, Resource::IN::PTR) {|resource| yield resource.name}
+- end
+-
+- ##
+- # Look up the +typeclass+ DNS resource of +name+.
+- #
+- # +name+ must be a Gem::Resolv::DNS::Name or a String.
+- #
+- # +typeclass+ should be one of the following:
+- #
+- # * Gem::Resolv::DNS::Resource::IN::A
+- # * Gem::Resolv::DNS::Resource::IN::AAAA
+- # * Gem::Resolv::DNS::Resource::IN::ANY
+- # * Gem::Resolv::DNS::Resource::IN::CNAME
+- # * Gem::Resolv::DNS::Resource::IN::HINFO
+- # * Gem::Resolv::DNS::Resource::IN::MINFO
+- # * Gem::Resolv::DNS::Resource::IN::MX
+- # * Gem::Resolv::DNS::Resource::IN::NS
+- # * Gem::Resolv::DNS::Resource::IN::PTR
+- # * Gem::Resolv::DNS::Resource::IN::SOA
+- # * Gem::Resolv::DNS::Resource::IN::TXT
+- # * Gem::Resolv::DNS::Resource::IN::WKS
+- #
+- # Returned resource is represented as a Gem::Resolv::DNS::Resource instance,
+- # i.e. Gem::Resolv::DNS::Resource::IN::A.
+-
+- def getresource(name, typeclass)
+- each_resource(name, typeclass) {|resource| return resource}
+- raise ResolvError.new("DNS result has no information for #{name}")
+- end
+-
+- ##
+- # Looks up all +typeclass+ DNS resources for +name+. See #getresource for
+- # argument details.
+-
+- def getresources(name, typeclass)
+- ret = []
+- each_resource(name, typeclass) {|resource| ret << resource}
+- return ret
+- end
+-
+- ##
+- # Iterates over all +typeclass+ DNS resources for +name+. See
+- # #getresource for argument details.
+-
+- def each_resource(name, typeclass, &proc)
+- fetch_resource(name, typeclass) {|reply, reply_name|
+- extract_resources(reply, reply_name, typeclass, &proc)
+- }
+- end
+-
+- # :stopdoc:
+-
+- def fetch_resource(name, typeclass)
+- lazy_initialize
+- truncated = {}
+- requesters = {}
+- udp_requester = begin
+- make_udp_requester
+- rescue Errno::EACCES
+- # fall back to TCP
+- end
+- senders = {}
+-
+- begin
+- @config.resolv(name) do |candidate, tout, nameserver, port|
+- msg = Message.new
+- msg.rd = 1
+- msg.add_question(candidate, typeclass)
+-
+- requester = requesters.fetch([nameserver, port]) do
+- if !truncated[candidate] && udp_requester
+- udp_requester
+- else
+- requesters[[nameserver, port]] = make_tcp_requester(nameserver, port)
+- end
+- end
+-
+- unless sender = senders[[candidate, requester, nameserver, port]]
+- sender = requester.sender(msg, candidate, nameserver, port)
+- next if !sender
+- senders[[candidate, requester, nameserver, port]] = sender
+- end
+- reply, reply_name = requester.request(sender, tout)
+- case reply.rcode
+- when RCode::NoError
+- if reply.tc == 1 and not Requester::TCP === requester
+- # Retry via TCP:
+- truncated[candidate] = true
+- redo
+- else
+- yield(reply, reply_name)
+- end
+- return
+- when RCode::NXDomain
+- raise Config::NXDomain.new(reply_name.to_s)
+- else
+- raise Config::OtherResolvError.new(reply_name.to_s)
+- end
+- end
+- ensure
+- udp_requester&.close
+- requesters.each_value { |requester| requester&.close }
+- end
+- end
+-
+- def make_udp_requester # :nodoc:
+- nameserver_port = @config.nameserver_port
+- if nameserver_port.length == 1
+- Requester::ConnectedUDP.new(*nameserver_port[0])
+- else
+- Requester::UnconnectedUDP.new(*nameserver_port)
+- end
+- end
+-
+- def make_tcp_requester(host, port) # :nodoc:
+- return Requester::TCP.new(host, port)
+- rescue Errno::ECONNREFUSED
+- # Treat a refused TCP connection attempt to a nameserver like a timeout,
+- # as Gem::Resolv::DNS::Config#resolv considers ResolvTimeout exceptions as a
+- # hint to try the next nameserver:
+- raise ResolvTimeout
+- end
+-
+- def extract_resources(msg, name, typeclass) # :nodoc:
+- if typeclass < Resource::ANY
+- n0 = Name.create(name)
+- msg.each_resource {|n, ttl, data|
+- yield data if n0 == n
+- }
+- end
+- yielded = false
+- n0 = Name.create(name)
+- msg.each_resource {|n, ttl, data|
+- if n0 == n
+- case data
+- when typeclass
+- yield data
+- yielded = true
+- when Resource::CNAME
+- n0 = data.name
+- end
+- end
+- }
+- return if yielded
+- msg.each_resource {|n, ttl, data|
+- if n0 == n
+- case data
+- when typeclass
+- yield data
+- end
+- end
+- }
+- end
+-
+- def self.random(arg) # :nodoc:
+- begin
+- Gem::SecureRandom.random_number(arg)
+- rescue NotImplementedError
+- rand(arg)
+- end
+- end
+-
+- RequestID = {} # :nodoc:
+- RequestIDMutex = Thread::Mutex.new # :nodoc:
+-
+- def self.allocate_request_id(host, port) # :nodoc:
+- id = nil
+- RequestIDMutex.synchronize {
+- h = (RequestID[[host, port]] ||= {})
+- begin
+- id = random(0x0000..0xffff)
+- end while h[id]
+- h[id] = true
+- }
+- id
+- end
+-
+- def self.free_request_id(host, port, id) # :nodoc:
+- RequestIDMutex.synchronize {
+- key = [host, port]
+- if h = RequestID[key]
+- h.delete id
+- if h.empty?
+- RequestID.delete key
+- end
+- end
+- }
+- end
+-
+- case RUBY_PLATFORM
+- when *[
+- # https://www.rfc-editor.org/rfc/rfc6056.txt
+- # Appendix A. Survey of the Algorithms in Use by Some Popular Implementations
+- /freebsd/, /linux/, /netbsd/, /openbsd/, /solaris/,
+- /darwin/, # the same as FreeBSD
+- ] then
+- def self.bind_random_port(udpsock, bind_host="0.0.0.0") # :nodoc:
+- udpsock.bind(bind_host, 0)
+- end
+- else
+- # Sequential port assignment
+- def self.bind_random_port(udpsock, bind_host="0.0.0.0") # :nodoc:
+- # Ephemeral port number range recommended by RFC 6056
+- port = random(1024..65535)
+- udpsock.bind(bind_host, port)
+- rescue Errno::EADDRINUSE, # POSIX
+- Errno::EACCES, # SunOS: See PRIV_SYS_NFS in privileges(5)
+- Errno::EPERM # FreeBSD: security.mac.portacl.port_high is configurable. See mac_portacl(4).
+- retry
+- end
+- end
+-
+- class Requester # :nodoc:
+- def initialize
+- @senders = {}
+- @socks = nil
+- end
+-
+- def request(sender, tout)
+- start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
+- timelimit = start + tout
+- begin
+- sender.send
+- rescue Errno::EHOSTUNREACH, # multi-homed IPv6 may generate this
+- Errno::ENETUNREACH
+- raise ResolvTimeout
+- end
+- while true
+- before_select = Process.clock_gettime(Process::CLOCK_MONOTONIC)
+- timeout = timelimit - before_select
+- if timeout <= 0
+- raise ResolvTimeout
+- end
+- if @socks.size == 1
+- select_result = @socks[0].wait_readable(timeout) ? [ @socks ] : nil
+- else
+- select_result = IO.select(@socks, nil, nil, timeout)
+- end
+- if !select_result
+- after_select = Process.clock_gettime(Process::CLOCK_MONOTONIC)
+- next if after_select < timelimit
+- raise ResolvTimeout
+- end
+- begin
+- reply, from = recv_reply(select_result[0])
+- rescue Errno::ECONNREFUSED, # GNU/Linux, FreeBSD
+- Errno::ECONNRESET # Windows
+- # No name server running on the server?
+- # Don't wait anymore.
+- raise ResolvTimeout
+- end
+- begin
+- msg = Message.decode(reply)
+- rescue DecodeError
+- next # broken DNS message ignored
+- end
+- if sender == sender_for(from, msg)
+- break
+- else
+- # unexpected DNS message ignored
+- end
+- end
+- return msg, sender.data
+- end
+-
+- def sender_for(addr, msg)
+- @senders[[addr,msg.id]]
+- end
+-
+- def close
+- socks = @socks
+- @socks = nil
+- socks&.each(&:close)
+- end
+-
+- class Sender # :nodoc:
+- def initialize(msg, data, sock)
+- @msg = msg
+- @data = data
+- @sock = sock
+- end
+- end
+-
+- class UnconnectedUDP < Requester # :nodoc:
+- def initialize(*nameserver_port)
+- super()
+- @nameserver_port = nameserver_port
+- @initialized = false
+- @mutex = Thread::Mutex.new
+- end
+-
+- def lazy_initialize
+- @mutex.synchronize {
+- next if @initialized
+- @initialized = true
+- @socks_hash = {}
+- @socks = []
+- @nameserver_port.each {|host, port|
+- if host.index(':')
+- bind_host = "::"
+- af = Socket::AF_INET6
+- else
+- bind_host = "0.0.0.0"
+- af = Socket::AF_INET
+- end
+- next if @socks_hash[bind_host]
+- begin
+- sock = UDPSocket.new(af)
+- rescue Errno::EAFNOSUPPORT, Errno::EPROTONOSUPPORT
+- next # The kernel doesn't support the address family.
+- end
+- @socks << sock
+- @socks_hash[bind_host] = sock
+- sock.do_not_reverse_lookup = true
+- DNS.bind_random_port(sock, bind_host)
+- }
+- }
+- self
+- end
+-
+- def recv_reply(readable_socks)
+- lazy_initialize
+- reply, from = readable_socks[0].recvfrom(UDPSize)
+- return reply, [from[3],from[1]]
+- end
+-
+- def sender(msg, data, host, port=Port)
+- host = Addrinfo.ip(host).ip_address
+- lazy_initialize
+- sock = @socks_hash[host.index(':') ? "::" : "0.0.0.0"]
+- return nil if !sock
+- service = [host, port]
+- id = DNS.allocate_request_id(host, port)
+- request = msg.encode
+- request[0,2] = [id].pack('n')
+- return @senders[[service, id]] =
+- Sender.new(request, data, sock, host, port)
+- end
+-
+- def close
+- @mutex.synchronize {
+- if @initialized
+- super
+- @senders.each_key {|service, id|
+- DNS.free_request_id(service[0], service[1], id)
+- }
+- @initialized = false
+- end
+- }
+- end
+-
+- class Sender < Requester::Sender # :nodoc:
+- def initialize(msg, data, sock, host, port)
+- super(msg, data, sock)
+- @host = host
+- @port = port
+- end
+- attr_reader :data
+-
+- def send
+- raise "@sock is nil." if @sock.nil?
+- @sock.send(@msg, 0, @host, @port)
+- end
+- end
+- end
+-
+- class ConnectedUDP < Requester # :nodoc:
+- def initialize(host, port=Port)
+- super()
+- @host = host
+- @port = port
+- @mutex = Thread::Mutex.new
+- @initialized = false
+- end
+-
+- def lazy_initialize
+- @mutex.synchronize {
+- next if @initialized
+- @initialized = true
+- is_ipv6 = @host.index(':')
+- sock = UDPSocket.new(is_ipv6 ? Socket::AF_INET6 : Socket::AF_INET)
+- @socks = [sock]
+- sock.do_not_reverse_lookup = true
+- DNS.bind_random_port(sock, is_ipv6 ? "::" : "0.0.0.0")
+- sock.connect(@host, @port)
+- }
+- self
+- end
+-
+- def recv_reply(readable_socks)
+- lazy_initialize
+- reply = readable_socks[0].recv(UDPSize)
+- return reply, nil
+- end
+-
+- def sender(msg, data, host=@host, port=@port)
+- lazy_initialize
+- unless host == @host && port == @port
+- raise RequestError.new("host/port don't match: #{host}:#{port}")
+- end
+- id = DNS.allocate_request_id(@host, @port)
+- request = msg.encode
+- request[0,2] = [id].pack('n')
+- return @senders[[nil,id]] = Sender.new(request, data, @socks[0])
+- end
+-
+- def close
+- @mutex.synchronize do
+- if @initialized
+- super
+- @senders.each_key {|from, id|
+- DNS.free_request_id(@host, @port, id)
+- }
+- @initialized = false
+- end
+- end
+- end
+-
+- class Sender < Requester::Sender # :nodoc:
+- def send
+- raise "@sock is nil." if @sock.nil?
+- @sock.send(@msg, 0)
+- end
+- attr_reader :data
+- end
+- end
+-
+- class MDNSOneShot < UnconnectedUDP # :nodoc:
+- def sender(msg, data, host, port=Port)
+- lazy_initialize
+- id = DNS.allocate_request_id(host, port)
+- request = msg.encode
+- request[0,2] = [id].pack('n')
+- sock = @socks_hash[host.index(':') ? "::" : "0.0.0.0"]
+- return @senders[id] =
+- UnconnectedUDP::Sender.new(request, data, sock, host, port)
+- end
+-
+- def sender_for(addr, msg)
+- lazy_initialize
+- @senders[msg.id]
+- end
+- end
+-
+- class TCP < Requester # :nodoc:
+- def initialize(host, port=Port)
+- super()
+- @host = host
+- @port = port
+- sock = TCPSocket.new(@host, @port)
+- @socks = [sock]
+- @senders = {}
+- end
+-
+- def recv_reply(readable_socks)
+- len = readable_socks[0].read(2).unpack('n')[0]
+- reply = @socks[0].read(len)
+- return reply, nil
+- end
+-
+- def sender(msg, data, host=@host, port=@port)
+- unless host == @host && port == @port
+- raise RequestError.new("host/port don't match: #{host}:#{port}")
+- end
+- id = DNS.allocate_request_id(@host, @port)
+- request = msg.encode
+- request[0,2] = [request.length, id].pack('nn')
+- return @senders[[nil,id]] = Sender.new(request, data, @socks[0])
+- end
+-
+- class Sender < Requester::Sender # :nodoc:
+- def send
+- @sock.print(@msg)
+- @sock.flush
+- end
+- attr_reader :data
+- end
+-
+- def close
+- super
+- @senders.each_key {|from,id|
+- DNS.free_request_id(@host, @port, id)
+- }
+- end
+- end
+-
+- ##
+- # Indicates a problem with the DNS request.
+-
+- class RequestError < StandardError
+- end
+- end
+-
+- class Config # :nodoc:
+- def initialize(config_info=nil)
+- @mutex = Thread::Mutex.new
+- @config_info = config_info
+- @initialized = nil
+- @timeouts = nil
+- end
+-
+- def timeouts=(values)
+- if values
+- values = Array(values)
+- values.each do |t|
+- Numeric === t or raise ArgumentError, "#{t.inspect} is not numeric"
+- t > 0.0 or raise ArgumentError, "timeout=#{t} must be positive"
+- end
+- @timeouts = values
+- else
+- @timeouts = nil
+- end
+- end
+-
+- def Config.parse_resolv_conf(filename)
+- nameserver = []
+- search = nil
+- ndots = 1
+- File.open(filename, 'rb') {|f|
+- f.each {|line|
+- line.sub!(/[#;].*/, '')
+- keyword, *args = line.split(/\s+/)
+- next unless keyword
+- case keyword
+- when 'nameserver'
+- nameserver.concat(args.each(&:freeze))
+- when 'domain'
+- next if args.empty?
+- search = [args[0].freeze]
+- when 'search'
+- next if args.empty?
+- search = args.each(&:freeze)
+- when 'options'
+- args.each {|arg|
+- case arg
+- when /\Andots:(\d+)\z/
+- ndots = $1.to_i
+- end
+- }
+- end
+- }
+- }
+- return { :nameserver => nameserver.freeze, :search => search.freeze, :ndots => ndots.freeze }.freeze
+- end
+-
+- def Config.default_config_hash(filename="/etc/resolv.conf")
+- if File.exist? filename
+- Config.parse_resolv_conf(filename)
+- elsif defined?(Win32::Resolv)
+- search, nameserver = Win32::Resolv.get_resolv_info
+- config_hash = {}
+- config_hash[:nameserver] = nameserver if nameserver
+- config_hash[:search] = [search].flatten if search
+- config_hash
+- else
+- {}
+- end
+- end
+-
+- def lazy_initialize
+- @mutex.synchronize {
+- unless @initialized
+- @nameserver_port = []
+- @use_ipv6 = nil
+- @search = nil
+- @ndots = 1
+- case @config_info
+- when nil
+- config_hash = Config.default_config_hash
+- when String
+- config_hash = Config.parse_resolv_conf(@config_info)
+- when Hash
+- config_hash = @config_info.dup
+- if String === config_hash[:nameserver]
+- config_hash[:nameserver] = [config_hash[:nameserver]]
+- end
+- if String === config_hash[:search]
+- config_hash[:search] = [config_hash[:search]]
+- end
+- else
+- raise ArgumentError.new("invalid resolv configuration: #{@config_info.inspect}")
+- end
+- if config_hash.include? :nameserver
+- @nameserver_port = config_hash[:nameserver].map {|ns| [ns, Port] }
+- end
+- if config_hash.include? :nameserver_port
+- @nameserver_port = config_hash[:nameserver_port].map {|ns, port| [ns, (port || Port)] }
+- end
+- if config_hash.include? :use_ipv6
+- @use_ipv6 = config_hash[:use_ipv6]
+- end
+- @search = config_hash[:search] if config_hash.include? :search
+- @ndots = config_hash[:ndots] if config_hash.include? :ndots
+- @raise_timeout_errors = config_hash[:raise_timeout_errors]
+-
+- if @nameserver_port.empty?
+- @nameserver_port << ['0.0.0.0', Port]
+- end
+- if @search
+- @search = @search.map {|arg| Label.split(arg) }
+- else
+- hostname = Socket.gethostname
+- if /\./ =~ hostname
+- @search = [Label.split($')]
+- else
+- @search = [[]]
+- end
+- end
+-
+- if !@nameserver_port.kind_of?(Array) ||
+- @nameserver_port.any? {|ns_port|
+- !(Array === ns_port) ||
+- ns_port.length != 2
+- !(String === ns_port[0]) ||
+- !(Integer === ns_port[1])
+- }
+- raise ArgumentError.new("invalid nameserver config: #{@nameserver_port.inspect}")
+- end
+-
+- if !@search.kind_of?(Array) ||
+- !@search.all? {|ls| ls.all? {|l| Label::Str === l } }
+- raise ArgumentError.new("invalid search config: #{@search.inspect}")
+- end
+-
+- if !@ndots.kind_of?(Integer)
+- raise ArgumentError.new("invalid ndots config: #{@ndots.inspect}")
+- end
+-
+- @initialized = true
+- end
+- }
+- self
+- end
+-
+- def single?
+- lazy_initialize
+- if @nameserver_port.length == 1
+- return @nameserver_port[0]
+- else
+- return nil
+- end
+- end
+-
+- def nameserver_port
+- @nameserver_port
+- end
+-
+- def use_ipv6?
+- @use_ipv6
+- end
+-
+- def generate_candidates(name)
+- candidates = nil
+- name = Name.create(name)
+- if name.absolute?
+- candidates = [name]
+- else
+- if @ndots <= name.length - 1
+- candidates = [Name.new(name.to_a)]
+- else
+- candidates = []
+- end
+- candidates.concat(@search.map {|domain| Name.new(name.to_a + domain)})
+- fname = Name.create("#{name}.")
+- if !candidates.include?(fname)
+- candidates << fname
+- end
+- end
+- return candidates
+- end
+-
+- InitialTimeout = 5
+-
+- def generate_timeouts
+- ts = [InitialTimeout]
+- ts << ts[-1] * 2 / @nameserver_port.length
+- ts << ts[-1] * 2
+- ts << ts[-1] * 2
+- return ts
+- end
+-
+- def resolv(name)
+- candidates = generate_candidates(name)
+- timeouts = @timeouts || generate_timeouts
+- timeout_error = false
+- begin
+- candidates.each {|candidate|
+- begin
+- timeouts.each {|tout|
+- @nameserver_port.each {|nameserver, port|
+- begin
+- yield candidate, tout, nameserver, port
+- rescue ResolvTimeout
+- end
+- }
+- }
+- timeout_error = true
+- raise ResolvError.new("DNS resolv timeout: #{name}")
+- rescue NXDomain
+- end
+- }
+- rescue ResolvError
+- raise if @raise_timeout_errors && timeout_error
+- end
+- end
+-
+- ##
+- # Indicates no such domain was found.
+-
+- class NXDomain < ResolvError
+- end
+-
+- ##
+- # Indicates some other unhandled resolver error was encountered.
+-
+- class OtherResolvError < ResolvError
+- end
+- end
+-
+- module OpCode # :nodoc:
+- Query = 0
+- IQuery = 1
+- Status = 2
+- Notify = 4
+- Update = 5
+- end
+-
+- module RCode # :nodoc:
+- NoError = 0
+- FormErr = 1
+- ServFail = 2
+- NXDomain = 3
+- NotImp = 4
+- Refused = 5
+- YXDomain = 6
+- YXRRSet = 7
+- NXRRSet = 8
+- NotAuth = 9
+- NotZone = 10
+- BADVERS = 16
+- BADSIG = 16
+- BADKEY = 17
+- BADTIME = 18
+- BADMODE = 19
+- BADNAME = 20
+- BADALG = 21
+- end
+-
+- ##
+- # Indicates that the DNS response was unable to be decoded.
+-
+- class DecodeError < StandardError
+- end
+-
+- ##
+- # Indicates that the DNS request was unable to be encoded.
+-
+- class EncodeError < StandardError
+- end
+-
+- module Label # :nodoc:
+- def self.split(arg)
+- labels = []
+- arg.scan(/[^\.]+/) {labels << Str.new($&)}
+- return labels
+- end
+-
+- class Str # :nodoc:
+- def initialize(string)
+- @string = string
+- # case insensivity of DNS labels doesn't apply non-ASCII characters. [RFC 4343]
+- # This assumes @string is given in ASCII compatible encoding.
+- @downcase = string.b.downcase
+- end
+- attr_reader :string, :downcase
+-
+- def to_s
+- return @string
+- end
+-
+- def inspect
+- return "#<#{self.class} #{self}>"
+- end
+-
+- def ==(other)
+- return self.class == other.class && @downcase == other.downcase
+- end
+-
+- def eql?(other)
+- return self == other
+- end
+-
+- def hash
+- return @downcase.hash
+- end
+- end
+- end
+-
+- ##
+- # A representation of a DNS name.
+-
+- class Name
+-
+- ##
+- # Creates a new DNS name from +arg+. +arg+ can be:
+- #
+- # Name:: returns +arg+.
+- # String:: Creates a new Name.
+-
+- def self.create(arg)
+- case arg
+- when Name
+- return arg
+- when String
+- return Name.new(Label.split(arg), /\.\z/ =~ arg ? true : false)
+- else
+- raise ArgumentError.new("cannot interpret as DNS name: #{arg.inspect}")
+- end
+- end
+-
+- def initialize(labels, absolute=true) # :nodoc:
+- labels = labels.map {|label|
+- case label
+- when String then Label::Str.new(label)
+- when Label::Str then label
+- else
+- raise ArgumentError, "unexpected label: #{label.inspect}"
+- end
+- }
+- @labels = labels
+- @absolute = absolute
+- end
+-
+- def inspect # :nodoc:
+- "#<#{self.class}: #{self}#{@absolute ? '.' : ''}>"
+- end
+-
+- ##
+- # True if this name is absolute.
+-
+- def absolute?
+- return @absolute
+- end
+-
+- def ==(other) # :nodoc:
+- return false unless Name === other
+- return false unless @absolute == other.absolute?
+- return @labels == other.to_a
+- end
+-
+- alias eql? == # :nodoc:
+-
+- ##
+- # Returns true if +other+ is a subdomain.
+- #
+- # Example:
+- #
+- # domain = Gem::Resolv::DNS::Name.create("y.z")
+- # p Gem::Resolv::DNS::Name.create("w.x.y.z").subdomain_of?(domain) #=> true
+- # p Gem::Resolv::DNS::Name.create("x.y.z").subdomain_of?(domain) #=> true
+- # p Gem::Resolv::DNS::Name.create("y.z").subdomain_of?(domain) #=> false
+- # p Gem::Resolv::DNS::Name.create("z").subdomain_of?(domain) #=> false
+- # p Gem::Resolv::DNS::Name.create("x.y.z.").subdomain_of?(domain) #=> false
+- # p Gem::Resolv::DNS::Name.create("w.z").subdomain_of?(domain) #=> false
+- #
+-
+- def subdomain_of?(other)
+- raise ArgumentError, "not a domain name: #{other.inspect}" unless Name === other
+- return false if @absolute != other.absolute?
+- other_len = other.length
+- return false if @labels.length <= other_len
+- return @labels[-other_len, other_len] == other.to_a
+- end
+-
+- def hash # :nodoc:
+- return @labels.hash ^ @absolute.hash
+- end
+-
+- def to_a # :nodoc:
+- return @labels
+- end
+-
+- def length # :nodoc:
+- return @labels.length
+- end
+-
+- def [](i) # :nodoc:
+- return @labels[i]
+- end
+-
+- ##
+- # returns the domain name as a string.
+- #
+- # The domain name doesn't have a trailing dot even if the name object is
+- # absolute.
+- #
+- # Example:
+- #
+- # p Gem::Resolv::DNS::Name.create("x.y.z.").to_s #=> "x.y.z"
+- # p Gem::Resolv::DNS::Name.create("x.y.z").to_s #=> "x.y.z"
+-
+- def to_s
+- return @labels.join('.')
+- end
+- end
+-
+- class Message # :nodoc:
+- @@identifier = -1
+-
+- def initialize(id = (@@identifier += 1) & 0xffff)
+- @id = id
+- @qr = 0
+- @opcode = 0
+- @aa = 0
+- @tc = 0
+- @rd = 0 # recursion desired
+- @ra = 0 # recursion available
+- @rcode = 0
+- @question = []
+- @answer = []
+- @authority = []
+- @additional = []
+- end
+-
+- attr_accessor :id, :qr, :opcode, :aa, :tc, :rd, :ra, :rcode
+- attr_reader :question, :answer, :authority, :additional
+-
+- def ==(other)
+- return @id == other.id &&
+- @qr == other.qr &&
+- @opcode == other.opcode &&
+- @aa == other.aa &&
+- @tc == other.tc &&
+- @rd == other.rd &&
+- @ra == other.ra &&
+- @rcode == other.rcode &&
+- @question == other.question &&
+- @answer == other.answer &&
+- @authority == other.authority &&
+- @additional == other.additional
+- end
+-
+- def add_question(name, typeclass)
+- @question << [Name.create(name), typeclass]
+- end
+-
+- def each_question
+- @question.each {|name, typeclass|
+- yield name, typeclass
+- }
+- end
+-
+- def add_answer(name, ttl, data)
+- @answer << [Name.create(name), ttl, data]
+- end
+-
+- def each_answer
+- @answer.each {|name, ttl, data|
+- yield name, ttl, data
+- }
+- end
+-
+- def add_authority(name, ttl, data)
+- @authority << [Name.create(name), ttl, data]
+- end
+-
+- def each_authority
+- @authority.each {|name, ttl, data|
+- yield name, ttl, data
+- }
+- end
+-
+- def add_additional(name, ttl, data)
+- @additional << [Name.create(name), ttl, data]
+- end
+-
+- def each_additional
+- @additional.each {|name, ttl, data|
+- yield name, ttl, data
+- }
+- end
+-
+- def each_resource
+- each_answer {|name, ttl, data| yield name, ttl, data}
+- each_authority {|name, ttl, data| yield name, ttl, data}
+- each_additional {|name, ttl, data| yield name, ttl, data}
+- end
+-
+- def encode
+- return MessageEncoder.new {|msg|
+- msg.put_pack('nnnnnn',
+- @id,
+- (@qr & 1) << 15 |
+- (@opcode & 15) << 11 |
+- (@aa & 1) << 10 |
+- (@tc & 1) << 9 |
+- (@rd & 1) << 8 |
+- (@ra & 1) << 7 |
+- (@rcode & 15),
+- @question.length,
+- @answer.length,
+- @authority.length,
+- @additional.length)
+- @question.each {|q|
+- name, typeclass = q
+- msg.put_name(name)
+- msg.put_pack('nn', typeclass::TypeValue, typeclass::ClassValue)
+- }
+- [@answer, @authority, @additional].each {|rr|
+- rr.each {|r|
+- name, ttl, data = r
+- msg.put_name(name)
+- msg.put_pack('nnN', data.class::TypeValue, data.class::ClassValue, ttl)
+- msg.put_length16 {data.encode_rdata(msg)}
+- }
+- }
+- }.to_s
+- end
+-
+- class MessageEncoder # :nodoc:
+- def initialize
+- @data = ''.dup
+- @names = {}
+- yield self
+- end
+-
+- def to_s
+- return @data
+- end
+-
+- def put_bytes(d)
+- @data << d
+- end
+-
+- def put_pack(template, *d)
+- @data << d.pack(template)
+- end
+-
+- def put_length16
+- length_index = @data.length
+- @data << "\0\0"
+- data_start = @data.length
+- yield
+- data_end = @data.length
+- @data[length_index, 2] = [data_end - data_start].pack("n")
+- end
+-
+- def put_string(d)
+- self.put_pack("C", d.length)
+- @data << d
+- end
+-
+- def put_string_list(ds)
+- ds.each {|d|
+- self.put_string(d)
+- }
+- end
+-
+- def put_name(d, compress: true)
+- put_labels(d.to_a, compress: compress)
+- end
+-
+- def put_labels(d, compress: true)
+- d.each_index {|i|
+- domain = d[i..-1]
+- if compress && idx = @names[domain]
+- self.put_pack("n", 0xc000 | idx)
+- return
+- else
+- if @data.length < 0x4000
+- @names[domain] = @data.length
+- end
+- self.put_label(d[i])
+- end
+- }
+- @data << "\0"
+- end
+-
+- def put_label(d)
+- self.put_string(d.to_s)
+- end
+- end
+-
+- def Message.decode(m)
+- o = Message.new(0)
+- MessageDecoder.new(m) {|msg|
+- id, flag, qdcount, ancount, nscount, arcount =
+- msg.get_unpack('nnnnnn')
+- o.id = id
+- o.tc = (flag >> 9) & 1
+- o.rcode = flag & 15
+- return o unless o.tc.zero?
+-
+- o.qr = (flag >> 15) & 1
+- o.opcode = (flag >> 11) & 15
+- o.aa = (flag >> 10) & 1
+- o.rd = (flag >> 8) & 1
+- o.ra = (flag >> 7) & 1
+- (1..qdcount).each {
+- name, typeclass = msg.get_question
+- o.add_question(name, typeclass)
+- }
+- (1..ancount).each {
+- name, ttl, data = msg.get_rr
+- o.add_answer(name, ttl, data)
+- }
+- (1..nscount).each {
+- name, ttl, data = msg.get_rr
+- o.add_authority(name, ttl, data)
+- }
+- (1..arcount).each {
+- name, ttl, data = msg.get_rr
+- o.add_additional(name, ttl, data)
+- }
+- }
+- return o
+- end
+-
+- class MessageDecoder # :nodoc:
+- def initialize(data)
+- @data = data
+- @index = 0
+- @limit = data.bytesize
+- yield self
+- end
+-
+- def inspect
+- "\#<#{self.class}: #{@data.byteslice(0, @index).inspect} #{@data.byteslice(@index..-1).inspect}>"
+- end
+-
+- def get_length16
+- len, = self.get_unpack('n')
+- save_limit = @limit
+- @limit = @index + len
+- d = yield(len)
+- if @index < @limit
+- raise DecodeError.new("junk exists")
+- elsif @limit < @index
+- raise DecodeError.new("limit exceeded")
+- end
+- @limit = save_limit
+- return d
+- end
+-
+- def get_bytes(len = @limit - @index)
+- raise DecodeError.new("limit exceeded") if @limit < @index + len
+- d = @data.byteslice(@index, len)
+- @index += len
+- return d
+- end
+-
+- def get_unpack(template)
+- len = 0
+- template.each_byte {|byte|
+- byte = "%c" % byte
+- case byte
+- when ?c, ?C
+- len += 1
+- when ?n
+- len += 2
+- when ?N
+- len += 4
+- else
+- raise StandardError.new("unsupported template: '#{byte.chr}' in '#{template}'")
+- end
+- }
+- raise DecodeError.new("limit exceeded") if @limit < @index + len
+- arr = @data.unpack("@#{@index}#{template}")
+- @index += len
+- return arr
+- end
+-
+- def get_string
+- raise DecodeError.new("limit exceeded") if @limit <= @index
+- len = @data.getbyte(@index)
+- raise DecodeError.new("limit exceeded") if @limit < @index + 1 + len
+- d = @data.byteslice(@index + 1, len)
+- @index += 1 + len
+- return d
+- end
+-
+- def get_string_list
+- strings = []
+- while @index < @limit
+- strings << self.get_string
+- end
+- strings
+- end
+-
+- def get_list
+- [].tap do |values|
+- while @index < @limit
+- values << yield
+- end
+- end
+- end
+-
+- def get_name
+- return Name.new(self.get_labels)
+- end
+-
+- def get_labels
+- prev_index = @index
+- save_index = nil
+- d = []
+- size = -1
+- while true
+- raise DecodeError.new("limit exceeded") if @limit <= @index
+- case @data.getbyte(@index)
+- when 0
+- @index += 1
+- if save_index
+- @index = save_index
+- end
+- return d
+- when 192..255
+- idx = self.get_unpack('n')[0] & 0x3fff
+- if prev_index <= idx
+- raise DecodeError.new("non-backward name pointer")
+- end
+- prev_index = idx
+- if !save_index
+- save_index = @index
+- end
+- @index = idx
+- else
+- l = self.get_label
+- d << l
+- size += 1 + l.string.bytesize
+- raise DecodeError.new("name label data exceed 255 octets") if size > 255
+- end
+- end
+- end
+-
+- def get_label
+- return Label::Str.new(self.get_string)
+- end
+-
+- def get_question
+- name = self.get_name
+- type, klass = self.get_unpack("nn")
+- return name, Resource.get_class(type, klass)
+- end
+-
+- def get_rr
+- name = self.get_name
+- type, klass, ttl = self.get_unpack('nnN')
+- typeclass = Resource.get_class(type, klass)
+- res = self.get_length16 do
+- begin
+- typeclass.decode_rdata self
+- rescue => e
+- raise DecodeError, e.message, e.backtrace
+- end
+- end
+- res.instance_variable_set :@ttl, ttl
+- return name, ttl, res
+- end
+- end
+- end
+-
+- ##
+- # SvcParams for service binding RRs. [RFC9460]
+-
+- class SvcParams
+- include Enumerable
+-
+- ##
+- # Create a list of SvcParams with the given initial content.
+- #
+- # +params+ has to be an enumerable of +SvcParam+s.
+- # If its content has +SvcParam+s with the duplicate key,
+- # the one appears last takes precedence.
+-
+- def initialize(params = [])
+- @params = {}
+-
+- params.each do |param|
+- add param
+- end
+- end
+-
+- ##
+- # Get SvcParam for the given +key+ in this list.
+-
+- def [](key)
+- @params[canonical_key(key)]
+- end
+-
+- ##
+- # Get the number of SvcParams in this list.
+-
+- def count
+- @params.count
+- end
+-
+- ##
+- # Get whether this list is empty.
+-
+- def empty?
+- @params.empty?
+- end
+-
+- ##
+- # Add the SvcParam +param+ to this list, overwriting the existing one with the same key.
+-
+- def add(param)
+- @params[param.class.key_number] = param
+- end
+-
+- ##
+- # Remove the +SvcParam+ with the given +key+ and return it.
+-
+- def delete(key)
+- @params.delete(canonical_key(key))
+- end
+-
+- ##
+- # Enumerate the +SvcParam+s in this list.
+-
+- def each(&block)
+- return enum_for(:each) unless block
+- @params.each_value(&block)
+- end
+-
+- def encode(msg) # :nodoc:
+- @params.keys.sort.each do |key|
+- msg.put_pack('n', key)
+- msg.put_length16 do
+- @params.fetch(key).encode(msg)
+- end
+- end
+- end
+-
+- def self.decode(msg) # :nodoc:
+- params = msg.get_list do
+- key, = msg.get_unpack('n')
+- msg.get_length16 do
+- SvcParam::ClassHash[key].decode(msg)
+- end
+- end
+-
+- return self.new(params)
+- end
+-
+- private
+-
+- def canonical_key(key) # :nodoc:
+- case key
+- when Integer
+- key
+- when /\Akey(\d+)\z/
+- Integer($1)
+- when Symbol
+- SvcParam::ClassHash[key].key_number
+- else
+- raise TypeError, 'key must be either String or Symbol'
+- end
+- end
+- end
+-
+- ##
+- # Base class for SvcParam. [RFC9460]
+-
+- class SvcParam
+-
+- ##
+- # Get the presentation name of the SvcParamKey.
+-
+- def self.key_name
+- const_get(:KeyName)
+- end
+-
+- ##
+- # Get the registered number of the SvcParamKey.
+-
+- def self.key_number
+- const_get(:KeyNumber)
+- end
+-
+- ClassHash = Hash.new do |h, key| # :nodoc:
+- case key
+- when Integer
+- Generic.create(key)
+- when /\Akey(?<key>\d+)\z/
+- Generic.create(key.to_int)
+- when Symbol
+- raise KeyError, "unknown key #{key}"
+- else
+- raise TypeError, 'key must be either String or Symbol'
+- end
+- end
+-
+- ##
+- # Generic SvcParam abstract class.
+-
+- class Generic < SvcParam
+-
+- ##
+- # SvcParamValue in wire-format byte string.
+-
+- attr_reader :value
+-
+- ##
+- # Create generic SvcParam
+-
+- def initialize(value)
+- @value = value
+- end
+-
+- def encode(msg) # :nodoc:
+- msg.put_bytes(@value)
+- end
+-
+- def self.decode(msg) # :nodoc:
+- return self.new(msg.get_bytes)
+- end
+-
+- def self.create(key_number)
+- c = Class.new(Generic)
+- key_name = :"key#{key_number}"
+- c.const_set(:KeyName, key_name)
+- c.const_set(:KeyNumber, key_number)
+- self.const_set(:"Key#{key_number}", c)
+- ClassHash[key_name] = ClassHash[key_number] = c
+- return c
+- end
+- end
+-
+- ##
+- # "mandatory" SvcParam -- Mandatory keys in service binding RR
+-
+- class Mandatory < SvcParam
+- KeyName = :mandatory
+- KeyNumber = 0
+- ClassHash[KeyName] = ClassHash[KeyNumber] = self # :nodoc:
+-
+- ##
+- # Mandatory keys.
+-
+- attr_reader :keys
+-
+- ##
+- # Initialize "mandatory" ScvParam.
+-
+- def initialize(keys)
+- @keys = keys.map(&:to_int)
+- end
+-
+- def encode(msg) # :nodoc:
+- @keys.sort.each do |key|
+- msg.put_pack('n', key)
+- end
+- end
+-
+- def self.decode(msg) # :nodoc:
+- keys = msg.get_list { msg.get_unpack('n')[0] }
+- return self.new(keys)
+- end
+- end
+-
+- ##
+- # "alpn" SvcParam -- Additional supported protocols
+-
+- class ALPN < SvcParam
+- KeyName = :alpn
+- KeyNumber = 1
+- ClassHash[KeyName] = ClassHash[KeyNumber] = self # :nodoc:
+-
+- ##
+- # Supported protocol IDs.
+-
+- attr_reader :protocol_ids
+-
+- ##
+- # Initialize "alpn" ScvParam.
+-
+- def initialize(protocol_ids)
+- @protocol_ids = protocol_ids.map(&:to_str)
+- end
+-
+- def encode(msg) # :nodoc:
+- msg.put_string_list(@protocol_ids)
+- end
+-
+- def self.decode(msg) # :nodoc:
+- return self.new(msg.get_string_list)
+- end
+- end
+-
+- ##
+- # "no-default-alpn" SvcParam -- No support for default protocol
+-
+- class NoDefaultALPN < SvcParam
+- KeyName = :'no-default-alpn'
+- KeyNumber = 2
+- ClassHash[KeyName] = ClassHash[KeyNumber] = self # :nodoc:
+-
+- def encode(msg) # :nodoc:
+- # no payload
+- end
+-
+- def self.decode(msg) # :nodoc:
+- return self.new
+- end
+- end
+-
+- ##
+- # "port" SvcParam -- Port for alternative endpoint
+-
+- class Port < SvcParam
+- KeyName = :port
+- KeyNumber = 3
+- ClassHash[KeyName] = ClassHash[KeyNumber] = self # :nodoc:
+-
+- ##
+- # Port number.
+-
+- attr_reader :port
+-
+- ##
+- # Initialize "port" ScvParam.
+-
+- def initialize(port)
+- @port = port.to_int
+- end
+-
+- def encode(msg) # :nodoc:
+- msg.put_pack('n', @port)
+- end
+-
+- def self.decode(msg) # :nodoc:
+- port, = msg.get_unpack('n')
+- return self.new(port)
+- end
+- end
+-
+- ##
+- # "ipv4hint" SvcParam -- IPv4 address hints
+-
+- class IPv4Hint < SvcParam
+- KeyName = :ipv4hint
+- KeyNumber = 4
+- ClassHash[KeyName] = ClassHash[KeyNumber] = self # :nodoc:
+-
+- ##
+- # Set of IPv4 addresses.
+-
+- attr_reader :addresses
+-
+- ##
+- # Initialize "ipv4hint" ScvParam.
+-
+- def initialize(addresses)
+- @addresses = addresses.map {|address| IPv4.create(address) }
+- end
+-
+- def encode(msg) # :nodoc:
+- @addresses.each do |address|
+- msg.put_bytes(address.address)
+- end
+- end
+-
+- def self.decode(msg) # :nodoc:
+- addresses = msg.get_list { IPv4.new(msg.get_bytes(4)) }
+- return self.new(addresses)
+- end
+- end
+-
+- ##
+- # "ipv6hint" SvcParam -- IPv6 address hints
+-
+- class IPv6Hint < SvcParam
+- KeyName = :ipv6hint
+- KeyNumber = 6
+- ClassHash[KeyName] = ClassHash[KeyNumber] = self # :nodoc:
+-
+- ##
+- # Set of IPv6 addresses.
+-
+- attr_reader :addresses
+-
+- ##
+- # Initialize "ipv6hint" ScvParam.
+-
+- def initialize(addresses)
+- @addresses = addresses.map {|address| IPv6.create(address) }
+- end
+-
+- def encode(msg) # :nodoc:
+- @addresses.each do |address|
+- msg.put_bytes(address.address)
+- end
+- end
+-
+- def self.decode(msg) # :nodoc:
+- addresses = msg.get_list { IPv6.new(msg.get_bytes(16)) }
+- return self.new(addresses)
+- end
+- end
+-
+- ##
+- # "dohpath" SvcParam -- DNS over HTTPS path template [RFC9461]
+-
+- class DoHPath < SvcParam
+- KeyName = :dohpath
+- KeyNumber = 7
+- ClassHash[KeyName] = ClassHash[KeyNumber] = self # :nodoc:
+-
+- ##
+- # URI template for DoH queries.
+-
+- attr_reader :template
+-
+- ##
+- # Initialize "dohpath" ScvParam.
+-
+- def initialize(template)
+- @template = template.encode('utf-8')
+- end
+-
+- def encode(msg) # :nodoc:
+- msg.put_bytes(@template)
+- end
+-
+- def self.decode(msg) # :nodoc:
+- template = msg.get_bytes.force_encoding('utf-8')
+- return self.new(template)
+- end
+- end
+- end
+-
+- ##
+- # A DNS query abstract class.
+-
+- class Query
+- def encode_rdata(msg) # :nodoc:
+- raise EncodeError.new("#{self.class} is query.")
+- end
+-
+- def self.decode_rdata(msg) # :nodoc:
+- raise DecodeError.new("#{self.class} is query.")
+- end
+- end
+-
+- ##
+- # A DNS resource abstract class.
+-
+- class Resource < Query
+-
+- ##
+- # Remaining Time To Live for this Resource.
+-
+- attr_reader :ttl
+-
+- ClassHash = Module.new do
+- module_function
+-
+- def []=(type_class_value, klass)
+- type_value, class_value = type_class_value
+- Resource.const_set(:"Type#{type_value}_Class#{class_value}", klass)
+- end
+- end
+-
+- def encode_rdata(msg) # :nodoc:
+- raise NotImplementedError.new
+- end
+-
+- def self.decode_rdata(msg) # :nodoc:
+- raise NotImplementedError.new
+- end
+-
+- def ==(other) # :nodoc:
+- return false unless self.class == other.class
+- s_ivars = self.instance_variables
+- s_ivars.sort!
+- s_ivars.delete :@ttl
+- o_ivars = other.instance_variables
+- o_ivars.sort!
+- o_ivars.delete :@ttl
<Skipped 1358 lines>
================================================================
---- gitweb:
http://git.pld-linux.org/gitweb.cgi/packages/ruby.git/commitdiff/a2d943d7d36f59ca00a640f2dd0970b49e0f3165
More information about the pld-cvs-commit
mailing list