From b5e685080109cb7a7bcb2105516fad0a60272515 Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Sat, 27 Jun 2026 16:34:11 +0900 Subject: [PATCH 01/26] fake.rb: Use the just-built ruby for native gems when not cross compiling The fake forced the RUBY of mkmf-generated Makefiles to baseruby. When baseruby is an older release than the source tree (e.g. on mswin, where the tree is ahead of the latest release), building the bundler spec's native test gems fails rbconfig's version check against the freshly built standard library. test-bundler[-parallel] only runs on native builds, so the just-built ruby is available there and matches the tree. Co-Authored-By: Claude Opus 4.8 --- tool/fake.rb | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/tool/fake.rb b/tool/fake.rb index 2c458985d8e1d3..a8d727db2150ee 100644 --- a/tool/fake.rb +++ b/tool/fake.rb @@ -27,7 +27,15 @@ class File if $extmk $ruby = "$(topdir)/miniruby -I'$(topdir)' -I'$(top_srcdir)/lib' -I'$(extout)/$(arch)' -I'$(extout)/common'" else - $ruby = baseruby + # `CROSS_COMPILING` holds the platform of the ruby that loaded this fake. + # When it matches the built ruby's platform we are not really cross + # compiling, so the just-built ruby runs on this host and matches the build + # tree. Prefer it over baseruby, which may be an older release whose version + # check rejects the freshly built standard library when building gems with + # native extensions (e.g. the bundler spec's test gems run via + # `make test-bundler[-parallel]`). + native = defined?(CROSS_COMPILING) && CROSS_COMPILING == RUBY_PLATFORM + $ruby = native && File.exist?($builtruby) ? $builtruby : baseruby end $static = static untrace_var(:$ruby, posthook) From f00181bb23d5608eda97980740f14a3ec3ef5649 Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Sat, 27 Jun 2026 17:24:53 +0900 Subject: [PATCH 02/26] runruby.rb: Provide a CA bundle for the built ruby on Windows On Windows the freshly built ruby often has no usable default CA bundle because its OpenSSL's OPENSSLDIR does not exist, so HTTPS fails in tests such as test-bundler, which downloads from rubygems.org over TLS. Fall back to the CA bundle of baseruby (the installed ruby the build was bootstrapped with) unless the caller already configured SSL_CERT_FILE/SSL_CERT_DIR. Co-Authored-By: Claude Opus 4.8 --- tool/runruby.rb | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/tool/runruby.rb b/tool/runruby.rb index ec63d1008a2348..1f7268bd4114b7 100755 --- a/tool/runruby.rb +++ b/tool/runruby.rb @@ -140,6 +140,24 @@ def File.realpath(*args) # See: https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=271490 env['LD_BIND_NOW'] = 'yes' if /freebsd/ =~ RUBY_PLATFORM +# On Windows the freshly built ruby often has no usable default CA bundle (its +# OpenSSL's OPENSSLDIR does not exist), which breaks HTTPS in tests such as +# test-bundler. Fall back to the CA bundle of baseruby (the installed ruby the +# build was bootstrapped with, recorded in the fake script), unless the caller +# already configured one. +if /mswin|mingw/ =~ RUBY_PLATFORM and !ENV["SSL_CERT_FILE"] and !ENV["SSL_CERT_DIR"] + fake = File.join(abs_archdir, "#{config['arch']}-fake.rb") + if File.exist?(fake) and /^baseruby\s*=\s*"([^"\n]+)"/ =~ File.read(fake) + baseruby = $1 + script = "f = OpenSSL::X509::DEFAULT_CERT_FILE; print f if File.exist?(f)" + begin + cert = IO.popen([baseruby, "-ropenssl", "-e", script], err: File::NULL, &:read) + env["SSL_CERT_FILE"] = cert if $?.success? and !cert.empty? + rescue SystemCallError + end + end +end + ENV.update env if debugger From 21717537800b95b4dc08844d5a4fcd8839d6984e Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Sat, 27 Jun 2026 17:58:50 +0900 Subject: [PATCH 03/26] [ruby/bundler] Skip make jobserver specs on Windows The make jobserver is a GNU make feature. On Windows extensions are built with nmake, which has no `-j` jobserver, so the per-gem slot count these examples assert never appears in the build output. Co-Authored-By: Claude Opus 4.8 --- spec/bundler/bundler/installer/parallel_installer_spec.rb | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/spec/bundler/bundler/installer/parallel_installer_spec.rb b/spec/bundler/bundler/installer/parallel_installer_spec.rb index 6a91f05bf8b48b..51104fb4ccd3e1 100644 --- a/spec/bundler/bundler/installer/parallel_installer_spec.rb +++ b/spec/bundler/bundler/installer/parallel_installer_spec.rb @@ -83,6 +83,11 @@ skip "This example is runnable when RubyGems::Installer implements `build_jobs`" end + # The make jobserver is a GNU make feature. On Windows extensions are built + # with nmake, which has no `-j` jobserver, so the per-gem slot count never + # appears in the build output. + skip "The make jobserver is not available on Windows (nmake)" if Gem.win_platform? + # When run under a parent make that already passes `-j` (e.g. ruby/ruby's # `make test-bundler-parallel`), RubyGems' extension builder sees the # inherited MAKEFLAGS as "jobs already requested" and skips appending its From d701adf1cd3bef1ee8035c5956c8b3736e5b19c5 Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Sat, 27 Jun 2026 18:40:45 +0900 Subject: [PATCH 04/26] [ruby/bundler] Compute lockfile_path like the parser does in lockfile_parser_spec The spec built the expected checksum location with `Bundler.default_lockfile.relative_path_from(Dir.pwd)`, which raises on Windows when the lockfile and the working directory are on different drives. The parser itself uses `SharedHelpers.relative_lockfile_path`, which falls back to the absolute path in that case, so mirror it to stay consistent and drive-safe. Co-Authored-By: Claude Opus 4.8 --- spec/bundler/bundler/lockfile_parser_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/bundler/bundler/lockfile_parser_spec.rb b/spec/bundler/bundler/lockfile_parser_spec.rb index cec77b0cb4cde0..c92d8909d29e56 100644 --- a/spec/bundler/bundler/lockfile_parser_spec.rb +++ b/spec/bundler/bundler/lockfile_parser_spec.rb @@ -118,7 +118,7 @@ let(:platforms) { [Gem::Platform::RUBY] } let(:bundler_version) { Gem::Version.new("1.12.0.rc.2") } let(:ruby_version) { "ruby 2.1.3p242" } - let(:lockfile_path) { Bundler.default_lockfile.relative_path_from(Dir.pwd) } + let(:lockfile_path) { Bundler::SharedHelpers.relative_lockfile_path } let(:rake_sha256_checksum) do Bundler::Checksum.from_lock( "sha256=814828c34f1315d7e7b7e8295184577cc4e969bad6156ac069d02d63f58d82e8", From 2343866493d804270d9f5b218c62e94c44f98611 Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Sat, 27 Jun 2026 18:40:55 +0900 Subject: [PATCH 05/26] [ruby/bundler] Skip specs needing a same-drive temp dir on Windows A few examples set up the temp home, bundled app or caches under the temp dir and then look them up relative to the source tree. On Windows there is no relative path between different drives, so these cannot be set up correctly when the temp dir and the source tree live on different drives. Add a `tmp_and_source_on_different_drives?` helper to support/path.rb and skip those examples in that case. Co-Authored-By: Claude Opus 4.8 --- spec/bundler/bundler/cli_spec.rb | 2 ++ spec/bundler/bundler/env_spec.rb | 2 ++ spec/bundler/bundler/shared_helpers_spec.rb | 1 + spec/bundler/support/path.rb | 9 +++++++++ 4 files changed, 14 insertions(+) diff --git a/spec/bundler/bundler/cli_spec.rb b/spec/bundler/bundler/cli_spec.rb index 56caf9937e29f6..1e8ffa7e37c883 100644 --- a/spec/bundler/bundler/cli_spec.rb +++ b/spec/bundler/bundler/cli_spec.rb @@ -237,6 +237,7 @@ def out_with_macos_man_workaround context "when the latest version is greater than the current version" do let(:latest_version) { "222.0" } it "prints the version warning" do + skip "temp dir is on a different drive than the source tree" if tmp_and_source_on_different_drives? bundle "fail", env: { "BUNDLER_VERSION" => bundler_version }, raise_on_error: false expect(err).to start_with(<<-EOS.strip) The latest bundler is #{latest_version}, but you are currently running #{bundler_version}. @@ -264,6 +265,7 @@ def out_with_macos_man_workaround context "and is a pre-release" do let(:latest_version) { "222.0.0.pre.4" } it "prints the version warning" do + skip "temp dir is on a different drive than the source tree" if tmp_and_source_on_different_drives? bundle "fail", env: { "BUNDLER_VERSION" => bundler_version }, raise_on_error: false expect(err).to start_with(<<-EOS.strip) The latest bundler is #{latest_version}, but you are currently running #{bundler_version}. diff --git a/spec/bundler/bundler/env_spec.rb b/spec/bundler/bundler/env_spec.rb index 2b7dbde217d8e2..1501bb9eb9b8fa 100644 --- a/spec/bundler/bundler/env_spec.rb +++ b/spec/bundler/bundler/env_spec.rb @@ -117,6 +117,7 @@ def with_clear_paths(env_var, env_value) let(:output) { described_class.report(print_gemfile: true) } it "prints the config with redacted values" do + skip "temp dir is on a different drive than the source tree" if tmp_and_source_on_different_drives? expect(output).to include("https://localgemserver.test") expect(output).to include("user:[REDACTED]") expect(output).to_not include("user:pass") @@ -131,6 +132,7 @@ def with_clear_paths(env_var, env_value) let(:output) { described_class.report(print_gemfile: true) } it "prints the config with redacted values" do + skip "temp dir is on a different drive than the source tree" if tmp_and_source_on_different_drives? expect(output).to include("https://localgemserver.test") expect(output).to include("[REDACTED]:x-oauth-basic") expect(output).to_not include("api_token:x-oauth-basic") diff --git a/spec/bundler/bundler/shared_helpers_spec.rb b/spec/bundler/bundler/shared_helpers_spec.rb index 41115aa667312b..ab89d280a22416 100644 --- a/spec/bundler/bundler/shared_helpers_spec.rb +++ b/spec/bundler/bundler/shared_helpers_spec.rb @@ -68,6 +68,7 @@ describe "#default_bundle_dir" do context ".bundle does not exist" do it "returns nil" do + skip "temp dir is on a different drive than the source tree" if tmp_and_source_on_different_drives? expect(subject.default_bundle_dir).to be_nil end end diff --git a/spec/bundler/support/path.rb b/spec/bundler/support/path.rb index 7a482912cf3760..f092758216f028 100644 --- a/spec/bundler/support/path.rb +++ b/spec/bundler/support/path.rb @@ -127,6 +127,15 @@ def tmp_root end end + # On Windows there is no relative path between different drives, and much of + # the spec setup (temp home, bundled app, caches) lives under the temp dir. + # When the temp dir is on a different drive than the source tree, examples + # that compare or look up paths across the two cannot be set up correctly. + def tmp_and_source_on_different_drives? + drive = ->(path) { path.to_s[%r{\A[a-zA-Z]:}]&.upcase } + drive[tmp_root] != drive[source_root] + end + # Bump this version whenever you make a breaking change to the spec setup # that requires regenerating tmp/. From c27a4a3a63ef88c090486a1cff0163b0e05c7242 Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Sat, 27 Jun 2026 18:45:45 +0900 Subject: [PATCH 06/26] [ruby/bundler] Only check drive mismatch on Windows Different drives only exist on Windows, so short-circuit the predicate there instead of relying on the absence of a drive letter on other platforms. Co-Authored-By: Claude Opus 4.8 --- spec/bundler/support/path.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/spec/bundler/support/path.rb b/spec/bundler/support/path.rb index f092758216f028..26315fa8adc374 100644 --- a/spec/bundler/support/path.rb +++ b/spec/bundler/support/path.rb @@ -132,6 +132,7 @@ def tmp_root # When the temp dir is on a different drive than the source tree, examples # that compare or look up paths across the two cannot be set up correctly. def tmp_and_source_on_different_drives? + return false unless Gem.win_platform? drive = ->(path) { path.to_s[%r{\A[a-zA-Z]:}]&.upcase } drive[tmp_root] != drive[source_root] end From 89af98c05fa48d7448d553d5799001c530f61568 Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Sat, 27 Jun 2026 19:33:41 +0900 Subject: [PATCH 07/26] [ruby/bundler] Skip parallel make specs on Windows The make jobserver is a GNU make feature. On Windows extensions are built with nmake, which has no `-j` jobserver, and an inherited `-j` MAKEFLAGS even breaks nmake, so the per-gem slot count these examples assert never appears. Co-Authored-By: Claude Opus 4.8 --- spec/bundler/commands/install_spec.rb | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/spec/bundler/commands/install_spec.rb b/spec/bundler/commands/install_spec.rb index 18c3fd65038c16..d71c4583b28e71 100644 --- a/spec/bundler/commands/install_spec.rb +++ b/spec/bundler/commands/install_spec.rb @@ -1349,6 +1349,11 @@ def run skip "This example is runnable when RubyGems::Installer implements `build_jobs`" end + # The make jobserver is a GNU make feature. On Windows extensions are built + # with nmake, which has no `-j` jobserver (and an inherited `-j` MAKEFLAGS + # even breaks nmake), so the slot count these examples assert never appears. + skip "The make jobserver is not available on Windows (nmake)" if Gem.win_platform? + @old_makeflags = ENV["MAKEFLAGS"] @gemspec = nil From dc74fb4c6c737e6d6e3338e2b872924a7ea25a5b Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Sat, 27 Jun 2026 19:33:42 +0900 Subject: [PATCH 08/26] [ruby/bundler] Skip more bundle exec specs on Windows These exec extensionless commands (`erb`, the source `bin/gem`) the same way the other examples in this file already skipped for rubygems#3351, which Windows cannot run directly. Co-Authored-By: Claude Opus 4.8 --- spec/bundler/commands/exec_spec.rb | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/spec/bundler/commands/exec_spec.rb b/spec/bundler/commands/exec_spec.rb index aa35685be8ff50..12b5c967f10bd4 100644 --- a/spec/bundler/commands/exec_spec.rb +++ b/spec/bundler/commands/exec_spec.rb @@ -72,6 +72,7 @@ end it "works when exec'ing to rubygems" do + skip "https://github.com/ruby/rubygems/issues/3351" if Gem.win_platform? install_gemfile "source \"https://gem.repo1\"; gem \"myrack\"" bundle "exec #{gem_cmd} --version" expect(out).to eq(Gem::VERSION) @@ -204,6 +205,7 @@ end it "uses version provided by ruby" do + skip "https://github.com/ruby/rubygems/issues/3351" if Gem.win_platform? bundle "exec erb --version" expect(stdboth).to eq(default_erb_version) @@ -632,6 +634,7 @@ describe "with gems bundled via :path with invalid gemspecs" do it "outputs the gemspec validation errors" do + skip "https://github.com/ruby/rubygems/issues/3351" if Gem.win_platform? build_lib "foo" gemspec = lib_path("foo-1.0").join("foo.gemspec").to_s @@ -692,6 +695,7 @@ def bin_path(a,b,c) end it "works" do + skip "https://github.com/ruby/rubygems/issues/3351" if Gem.win_platform? bundle "exec #{gem_cmd} uninstall foo" expect(out).to eq("Successfully uninstalled foo-1.0") end @@ -713,6 +717,7 @@ def bin_path(a,b,c) end it "does not load plugins outside of the bundle" do + skip "https://github.com/ruby/rubygems/issues/3351" if Gem.win_platform? bundle "exec #{gem_cmd} -v" expect(out).not_to include("FAIL") end From 52ccfc11fb1c93085b665e7b5b3dc6cbbcaa90b6 Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Sat, 27 Jun 2026 19:34:02 +0900 Subject: [PATCH 09/26] [ruby/bundler] Skip the long cache path spec on Windows The example deliberately builds a very long cache path to exercise the path-shortening logic. Windows without long path support cannot create it, so skip it there. Also guard the manual cleanup so the skipped example does not raise in its ensure block. Co-Authored-By: Claude Opus 4.8 --- spec/bundler/install/global_cache_spec.rb | 25 +++++++++++++---------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/spec/bundler/install/global_cache_spec.rb b/spec/bundler/install/global_cache_spec.rb index 4cffa65b2a9d97..259e8d57ba2ebc 100644 --- a/spec/bundler/install/global_cache_spec.rb +++ b/spec/bundler/install/global_cache_spec.rb @@ -63,6 +63,7 @@ def source2_global_cache(*segments) end it "uses a shorter path for the cache to not hit filesystem limits" do + skip "Windows without long path support cannot create the long cache path" if Gem.win_platform? install_gemfile <<-G, artifice: "compact_index", verbose: true source "http://#{"a" * 255}.test" gem "myrack" @@ -82,17 +83,19 @@ def source2_global_cache(*segments) # the more verbose and explicit approach. This whole ensure block can be # removed once/if https://bugs.ruby-lang.org/issues/21177 is fixed, and # once the fix propagates to all supported rubies. - File.delete cached_gem - Dir.rmdir source_cache - - File.delete compact_index_cache_path.join(source_segment, "info", "myrack") - Dir.rmdir compact_index_cache_path.join(source_segment, "info") - File.delete compact_index_cache_path.join(source_segment, "info-etags", "myrack-92f3313ce5721296f14445c3a6b9c073") - Dir.rmdir compact_index_cache_path.join(source_segment, "info-etags") - Dir.rmdir compact_index_cache_path.join(source_segment, "info-special-characters") - File.delete compact_index_cache_path.join(source_segment, "versions") - File.delete compact_index_cache_path.join(source_segment, "versions.etag") - Dir.rmdir compact_index_cache_path.join(source_segment) + if cached_gem + File.delete cached_gem + Dir.rmdir source_cache + + File.delete compact_index_cache_path.join(source_segment, "info", "myrack") + Dir.rmdir compact_index_cache_path.join(source_segment, "info") + File.delete compact_index_cache_path.join(source_segment, "info-etags", "myrack-92f3313ce5721296f14445c3a6b9c073") + Dir.rmdir compact_index_cache_path.join(source_segment, "info-etags") + Dir.rmdir compact_index_cache_path.join(source_segment, "info-special-characters") + File.delete compact_index_cache_path.join(source_segment, "versions") + File.delete compact_index_cache_path.join(source_segment, "versions.etag") + Dir.rmdir compact_index_cache_path.join(source_segment) + end end describe "when the same gem from different sources is installed" do From 5c5f846b33c57a2e6830fb4ed7bb14eeff03bd07 Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Sat, 27 Jun 2026 19:34:02 +0900 Subject: [PATCH 10/26] [ruby/bundler] Skip the legacy windows cache spec on Windows On the current mswin platform the gem restricted to legacy windows platforms is not cached, so the expectation cannot hold. Co-Authored-By: Claude Opus 4.8 --- spec/bundler/commands/cache_spec.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/spec/bundler/commands/cache_spec.rb b/spec/bundler/commands/cache_spec.rb index e223d07f7fc1e7..682dda53bfb71d 100644 --- a/spec/bundler/commands/cache_spec.rb +++ b/spec/bundler/commands/cache_spec.rb @@ -208,6 +208,7 @@ end it "prints a warn when using legacy windows rubies" do + skip "the legacy windows platform gem is not cached for the current mswin platform" if Gem.win_platform? gemfile <<-D source "https://gem.repo1" gem 'myrack', :platforms => [:ruby_20, :x64_mingw_20] From 663c9404dc0a144ea3a37e9bd5cc67dcf4ba6276 Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Sat, 27 Jun 2026 19:34:03 +0900 Subject: [PATCH 11/26] [ruby/bundler] Skip the add-platform lock spec on Windows The raygun-apm fixture provides linux, darwin and mingw variants but no x64-mswin64 one, so resolution conflicts on the current platform. Co-Authored-By: Claude Opus 4.8 --- spec/bundler/commands/lock_spec.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/spec/bundler/commands/lock_spec.rb b/spec/bundler/commands/lock_spec.rb index 1a434009232e2b..63dc47978681ca 100644 --- a/spec/bundler/commands/lock_spec.rb +++ b/spec/bundler/commands/lock_spec.rb @@ -1286,6 +1286,7 @@ end it "does not conflict on ruby requirements when adding new platforms" do + skip "the raygun-apm fixture has no x64-mswin64 variant for the current platform" if Gem.win_platform? build_repo4 do build_gem "raygun-apm", "1.0.78" do |s| s.platform = "x86_64-linux" From 361e0a947ffe03c1766393255e1152e87f4f69e7 Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Sat, 27 Jun 2026 19:34:04 +0900 Subject: [PATCH 12/26] [ruby/bundler] Skip the build config Makefile specs on Windows These assert the GNU make `-L` libpath flag, but on Windows the extension's Makefile is generated for MSVC and uses `-libpath:` instead. Co-Authored-By: Claude Opus 4.8 --- spec/bundler/commands/pristine_spec.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/spec/bundler/commands/pristine_spec.rb b/spec/bundler/commands/pristine_spec.rb index 5f80b9e5348b21..978ca6424b625e 100644 --- a/spec/bundler/commands/pristine_spec.rb +++ b/spec/bundler/commands/pristine_spec.rb @@ -232,6 +232,7 @@ # This just verifies that the generated Makefile from the c_ext gem makes # use of the build_args from the bundle config it "applies the config when installing the gem" do + skip "the generated Makefile uses MSVC `-libpath:` syntax instead of `-L` on Windows" if Gem.win_platform? bundle "pristine" makefile_contents = File.read(c_ext_dir.join("Makefile").to_s) @@ -249,6 +250,7 @@ # This just verifies that the generated Makefile from the c_ext gem makes # use of the build_args from the bundle config it "applies the config when installing the gem" do + skip "the generated Makefile uses MSVC `-libpath:` syntax instead of `-L` on Windows" if Gem.win_platform? bundle "pristine" makefile_contents = File.read(c_ext_dir.join("Makefile").to_s) From 888f6e07f2c4591faf0e9743c229e162c903bf6e Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Sun, 28 Jun 2026 05:55:12 +0900 Subject: [PATCH 13/26] Keep bundler specs in their sandbox when temp is under the user home Bundler's spec helpers walk up from the working directory looking for a `.bundle` directory, stopping at the first ancestor that contains a `tmp` directory (Bundler::SharedHelpers#search_up). On Windows the test temp dir lives under the user home (%LOCALAPPDATA%\Temp), so the search escaped the sandbox and picked up the real ~/.bundle, breaking config, cache and other specs. Create a `tmp` marker at the temp root so the search stops there. Co-Authored-By: Claude Opus 4.8 --- tool/lib/_tmpdir.rb | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tool/lib/_tmpdir.rb b/tool/lib/_tmpdir.rb index ac5b9be792ec63..3a00e65d6188d9 100644 --- a/tool/lib/_tmpdir.rb +++ b/tool/lib/_tmpdir.rb @@ -21,6 +21,13 @@ end # warn "tmpdir(#{tmpdir.size}) = #{tmpdir}" +# Bundler's spec helpers walk up the directory tree looking for `.bundle`, +# stopping once they see a `tmp` directory (Bundler::SharedHelpers#search_up). +# On Windows the temp dir lives under the user home (%LOCALAPPDATA%\Temp), so +# without a `tmp` marker the search escapes the sandbox and picks up the real +# ~/.bundle. Create one so the search stops at the temp root. +Dir.mkdir(File.join(tmpdir, "tmp")) + pid = $$ END { if pid == $$ From 90ac868b2d7401127344f3b6fbbb8db674321c3c Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Sun, 28 Jun 2026 08:28:44 +0900 Subject: [PATCH 14/26] [ruby/bundler] Allow more time for spec commands on Windows Native extension builds spawned by the specs can exceed the 60-second command timeout on Windows when the temp dir lives under the user profile, so allow 120 seconds there. Co-Authored-By: Claude Opus 4.8 --- spec/bundler/support/subprocess.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/bundler/support/subprocess.rb b/spec/bundler/support/subprocess.rb index 91db80da488c6a..b03ba839dd8623 100644 --- a/spec/bundler/support/subprocess.rb +++ b/spec/bundler/support/subprocess.rb @@ -38,7 +38,7 @@ def sh(cmd, options = {}) dir = options[:dir] env = options[:env] || {} - command_execution = CommandExecution.new(cmd.to_s, timeout: options[:timeout] || 60) + command_execution = CommandExecution.new(cmd.to_s, timeout: options[:timeout] || (Gem.win_platform? ? 120 : 60)) open3_opts = {} open3_opts[:chdir] = dir if dir From 1bcc15d1d83af7f5c6b1da577e6790455caae534 Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Sun, 28 Jun 2026 18:26:06 +0900 Subject: [PATCH 15/26] Remove the tmp marker before removing the temp root The sandbox marker created at the temp root is ours, so the END block must remove it before Dir.rmdir(tmpdir); otherwise that call always fails with ENOTEMPTY and a clean run looks like it left files behind. Co-Authored-By: Claude Opus 4.8 --- tool/lib/_tmpdir.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/tool/lib/_tmpdir.rb b/tool/lib/_tmpdir.rb index 3a00e65d6188d9..f4ac29ffb64fd9 100644 --- a/tool/lib/_tmpdir.rb +++ b/tool/lib/_tmpdir.rb @@ -32,6 +32,7 @@ END { if pid == $$ begin + Dir.rmdir(File.join(tmpdir, "tmp")) Dir.rmdir(tmpdir) rescue Errno::ENOENT rescue Errno::ENOTEMPTY From e66791ac56bc9e39f5ade672e1ba80344bb2d614 Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Sun, 28 Jun 2026 18:38:14 +0900 Subject: [PATCH 16/26] [ruby/bundler] Skip the mswin-specific specs only on mswin, not mingw These specs guard limitations specific to the mswin build: nmake has no make jobserver, the generated Makefile uses MSVC `-libpath:` syntax, extensionless executables cannot be exec'd, and the raygun-apm fixture only ships an x64-mswin64 variant. The mingw build passes them, so match the platform string directly instead of Gem.win_platform?, which is also true on mingw. The MAX_PATH and cross-drive guards stay on Gem.win_platform? since those limitations are not specific to mswin. Co-Authored-By: Claude Opus 4.8 --- .../bundler/installer/parallel_installer_spec.rb | 2 +- spec/bundler/commands/cache_spec.rb | 2 +- spec/bundler/commands/exec_spec.rb | 10 +++++----- spec/bundler/commands/install_spec.rb | 2 +- spec/bundler/commands/lock_spec.rb | 2 +- spec/bundler/commands/pristine_spec.rb | 4 ++-- 6 files changed, 11 insertions(+), 11 deletions(-) diff --git a/spec/bundler/bundler/installer/parallel_installer_spec.rb b/spec/bundler/bundler/installer/parallel_installer_spec.rb index 51104fb4ccd3e1..0f93892e633dbb 100644 --- a/spec/bundler/bundler/installer/parallel_installer_spec.rb +++ b/spec/bundler/bundler/installer/parallel_installer_spec.rb @@ -86,7 +86,7 @@ # The make jobserver is a GNU make feature. On Windows extensions are built # with nmake, which has no `-j` jobserver, so the per-gem slot count never # appears in the build output. - skip "The make jobserver is not available on Windows (nmake)" if Gem.win_platform? + skip "The make jobserver is not available on Windows (nmake)" if /mswin/.match?(RUBY_PLATFORM) # When run under a parent make that already passes `-j` (e.g. ruby/ruby's # `make test-bundler-parallel`), RubyGems' extension builder sees the diff --git a/spec/bundler/commands/cache_spec.rb b/spec/bundler/commands/cache_spec.rb index 682dda53bfb71d..74569075e9f0bd 100644 --- a/spec/bundler/commands/cache_spec.rb +++ b/spec/bundler/commands/cache_spec.rb @@ -208,7 +208,7 @@ end it "prints a warn when using legacy windows rubies" do - skip "the legacy windows platform gem is not cached for the current mswin platform" if Gem.win_platform? + skip "the legacy windows platform gem is not cached for the current mswin platform" if /mswin/.match?(RUBY_PLATFORM) gemfile <<-D source "https://gem.repo1" gem 'myrack', :platforms => [:ruby_20, :x64_mingw_20] diff --git a/spec/bundler/commands/exec_spec.rb b/spec/bundler/commands/exec_spec.rb index 12b5c967f10bd4..6eba9697124053 100644 --- a/spec/bundler/commands/exec_spec.rb +++ b/spec/bundler/commands/exec_spec.rb @@ -72,7 +72,7 @@ end it "works when exec'ing to rubygems" do - skip "https://github.com/ruby/rubygems/issues/3351" if Gem.win_platform? + skip "https://github.com/ruby/rubygems/issues/3351" if /mswin/.match?(RUBY_PLATFORM) install_gemfile "source \"https://gem.repo1\"; gem \"myrack\"" bundle "exec #{gem_cmd} --version" expect(out).to eq(Gem::VERSION) @@ -205,7 +205,7 @@ end it "uses version provided by ruby" do - skip "https://github.com/ruby/rubygems/issues/3351" if Gem.win_platform? + skip "https://github.com/ruby/rubygems/issues/3351" if /mswin/.match?(RUBY_PLATFORM) bundle "exec erb --version" expect(stdboth).to eq(default_erb_version) @@ -634,7 +634,7 @@ describe "with gems bundled via :path with invalid gemspecs" do it "outputs the gemspec validation errors" do - skip "https://github.com/ruby/rubygems/issues/3351" if Gem.win_platform? + skip "https://github.com/ruby/rubygems/issues/3351" if /mswin/.match?(RUBY_PLATFORM) build_lib "foo" gemspec = lib_path("foo-1.0").join("foo.gemspec").to_s @@ -695,7 +695,7 @@ def bin_path(a,b,c) end it "works" do - skip "https://github.com/ruby/rubygems/issues/3351" if Gem.win_platform? + skip "https://github.com/ruby/rubygems/issues/3351" if /mswin/.match?(RUBY_PLATFORM) bundle "exec #{gem_cmd} uninstall foo" expect(out).to eq("Successfully uninstalled foo-1.0") end @@ -717,7 +717,7 @@ def bin_path(a,b,c) end it "does not load plugins outside of the bundle" do - skip "https://github.com/ruby/rubygems/issues/3351" if Gem.win_platform? + skip "https://github.com/ruby/rubygems/issues/3351" if /mswin/.match?(RUBY_PLATFORM) bundle "exec #{gem_cmd} -v" expect(out).not_to include("FAIL") end diff --git a/spec/bundler/commands/install_spec.rb b/spec/bundler/commands/install_spec.rb index d71c4583b28e71..d7f2961addcd73 100644 --- a/spec/bundler/commands/install_spec.rb +++ b/spec/bundler/commands/install_spec.rb @@ -1352,7 +1352,7 @@ def run # The make jobserver is a GNU make feature. On Windows extensions are built # with nmake, which has no `-j` jobserver (and an inherited `-j` MAKEFLAGS # even breaks nmake), so the slot count these examples assert never appears. - skip "The make jobserver is not available on Windows (nmake)" if Gem.win_platform? + skip "The make jobserver is not available on Windows (nmake)" if /mswin/.match?(RUBY_PLATFORM) @old_makeflags = ENV["MAKEFLAGS"] @gemspec = nil diff --git a/spec/bundler/commands/lock_spec.rb b/spec/bundler/commands/lock_spec.rb index 63dc47978681ca..027c70b26f86fb 100644 --- a/spec/bundler/commands/lock_spec.rb +++ b/spec/bundler/commands/lock_spec.rb @@ -1286,7 +1286,7 @@ end it "does not conflict on ruby requirements when adding new platforms" do - skip "the raygun-apm fixture has no x64-mswin64 variant for the current platform" if Gem.win_platform? + skip "the raygun-apm fixture has no x64-mswin64 variant for the current platform" if /mswin/.match?(RUBY_PLATFORM) build_repo4 do build_gem "raygun-apm", "1.0.78" do |s| s.platform = "x86_64-linux" diff --git a/spec/bundler/commands/pristine_spec.rb b/spec/bundler/commands/pristine_spec.rb index 978ca6424b625e..e16bcae90a2903 100644 --- a/spec/bundler/commands/pristine_spec.rb +++ b/spec/bundler/commands/pristine_spec.rb @@ -232,7 +232,7 @@ # This just verifies that the generated Makefile from the c_ext gem makes # use of the build_args from the bundle config it "applies the config when installing the gem" do - skip "the generated Makefile uses MSVC `-libpath:` syntax instead of `-L` on Windows" if Gem.win_platform? + skip "the generated Makefile uses MSVC `-libpath:` syntax instead of `-L` on Windows" if /mswin/.match?(RUBY_PLATFORM) bundle "pristine" makefile_contents = File.read(c_ext_dir.join("Makefile").to_s) @@ -250,7 +250,7 @@ # This just verifies that the generated Makefile from the c_ext gem makes # use of the build_args from the bundle config it "applies the config when installing the gem" do - skip "the generated Makefile uses MSVC `-libpath:` syntax instead of `-L` on Windows" if Gem.win_platform? + skip "the generated Makefile uses MSVC `-libpath:` syntax instead of `-L` on Windows" if /mswin/.match?(RUBY_PLATFORM) bundle "pristine" makefile_contents = File.read(c_ext_dir.join("Makefile").to_s) From 89732c6b2f90d21617e7e93a3448c945c1db0808 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 29 Jun 2026 04:56:56 +0000 Subject: [PATCH 17/26] [ruby/rubygems] Bump yard from 0.9.42 to 0.9.44 in /spec/realworld/fixtures/tapioca Bumps [yard](https://yardoc.org) from 0.9.42 to 0.9.44. --- updated-dependencies: - dependency-name: yard dependency-version: 0.9.44 dependency-type: indirect ... Signed-off-by: dependabot[bot] https://github.com/ruby/rubygems/commit/b8e687623c --- spec/bundler/realworld/fixtures/tapioca/Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/bundler/realworld/fixtures/tapioca/Gemfile.lock b/spec/bundler/realworld/fixtures/tapioca/Gemfile.lock index c2df2f92299ad2..a08089a6f7b33b 100644 --- a/spec/bundler/realworld/fixtures/tapioca/Gemfile.lock +++ b/spec/bundler/realworld/fixtures/tapioca/Gemfile.lock @@ -32,7 +32,7 @@ GEM thor (>= 1.2.0) yard-sorbet thor (1.4.0) - yard (0.9.42) + yard (0.9.44) yard-sorbet (0.9.0) sorbet-runtime yard From 7eab0be4f9078269fbafad4addbe084c3ec8ce75 Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Mon, 29 Jun 2026 11:58:59 +0900 Subject: [PATCH 18/26] [ruby/rubygems] Satisfy rubocop on the forward-ported Windows specs These specs were authored directly in ruby/ruby, where this rubocop config does not lint them, so they reached for `/mswin/.match?` and a `%r{}` literal that Performance/StringInclude and Style/RegexpLiteral flag here. Align them with the equivalent `include?`/`//` forms. https://github.com/ruby/rubygems/commit/22ebbb0cc7 --- .../bundler/installer/parallel_installer_spec.rb | 2 +- spec/bundler/commands/cache_spec.rb | 2 +- spec/bundler/commands/exec_spec.rb | 10 +++++----- spec/bundler/commands/install_spec.rb | 2 +- spec/bundler/commands/lock_spec.rb | 2 +- spec/bundler/commands/pristine_spec.rb | 4 ++-- spec/bundler/support/path.rb | 2 +- 7 files changed, 12 insertions(+), 12 deletions(-) diff --git a/spec/bundler/bundler/installer/parallel_installer_spec.rb b/spec/bundler/bundler/installer/parallel_installer_spec.rb index 0f93892e633dbb..220c93f43475fb 100644 --- a/spec/bundler/bundler/installer/parallel_installer_spec.rb +++ b/spec/bundler/bundler/installer/parallel_installer_spec.rb @@ -86,7 +86,7 @@ # The make jobserver is a GNU make feature. On Windows extensions are built # with nmake, which has no `-j` jobserver, so the per-gem slot count never # appears in the build output. - skip "The make jobserver is not available on Windows (nmake)" if /mswin/.match?(RUBY_PLATFORM) + skip "The make jobserver is not available on Windows (nmake)" if RUBY_PLATFORM.include?("mswin") # When run under a parent make that already passes `-j` (e.g. ruby/ruby's # `make test-bundler-parallel`), RubyGems' extension builder sees the diff --git a/spec/bundler/commands/cache_spec.rb b/spec/bundler/commands/cache_spec.rb index 74569075e9f0bd..e78b08003b300c 100644 --- a/spec/bundler/commands/cache_spec.rb +++ b/spec/bundler/commands/cache_spec.rb @@ -208,7 +208,7 @@ end it "prints a warn when using legacy windows rubies" do - skip "the legacy windows platform gem is not cached for the current mswin platform" if /mswin/.match?(RUBY_PLATFORM) + skip "the legacy windows platform gem is not cached for the current mswin platform" if RUBY_PLATFORM.include?("mswin") gemfile <<-D source "https://gem.repo1" gem 'myrack', :platforms => [:ruby_20, :x64_mingw_20] diff --git a/spec/bundler/commands/exec_spec.rb b/spec/bundler/commands/exec_spec.rb index 6eba9697124053..118dacff413c7b 100644 --- a/spec/bundler/commands/exec_spec.rb +++ b/spec/bundler/commands/exec_spec.rb @@ -72,7 +72,7 @@ end it "works when exec'ing to rubygems" do - skip "https://github.com/ruby/rubygems/issues/3351" if /mswin/.match?(RUBY_PLATFORM) + skip "https://github.com/ruby/rubygems/issues/3351" if RUBY_PLATFORM.include?("mswin") install_gemfile "source \"https://gem.repo1\"; gem \"myrack\"" bundle "exec #{gem_cmd} --version" expect(out).to eq(Gem::VERSION) @@ -205,7 +205,7 @@ end it "uses version provided by ruby" do - skip "https://github.com/ruby/rubygems/issues/3351" if /mswin/.match?(RUBY_PLATFORM) + skip "https://github.com/ruby/rubygems/issues/3351" if RUBY_PLATFORM.include?("mswin") bundle "exec erb --version" expect(stdboth).to eq(default_erb_version) @@ -634,7 +634,7 @@ describe "with gems bundled via :path with invalid gemspecs" do it "outputs the gemspec validation errors" do - skip "https://github.com/ruby/rubygems/issues/3351" if /mswin/.match?(RUBY_PLATFORM) + skip "https://github.com/ruby/rubygems/issues/3351" if RUBY_PLATFORM.include?("mswin") build_lib "foo" gemspec = lib_path("foo-1.0").join("foo.gemspec").to_s @@ -695,7 +695,7 @@ def bin_path(a,b,c) end it "works" do - skip "https://github.com/ruby/rubygems/issues/3351" if /mswin/.match?(RUBY_PLATFORM) + skip "https://github.com/ruby/rubygems/issues/3351" if RUBY_PLATFORM.include?("mswin") bundle "exec #{gem_cmd} uninstall foo" expect(out).to eq("Successfully uninstalled foo-1.0") end @@ -717,7 +717,7 @@ def bin_path(a,b,c) end it "does not load plugins outside of the bundle" do - skip "https://github.com/ruby/rubygems/issues/3351" if /mswin/.match?(RUBY_PLATFORM) + skip "https://github.com/ruby/rubygems/issues/3351" if RUBY_PLATFORM.include?("mswin") bundle "exec #{gem_cmd} -v" expect(out).not_to include("FAIL") end diff --git a/spec/bundler/commands/install_spec.rb b/spec/bundler/commands/install_spec.rb index d7f2961addcd73..1a5725b2ef6a99 100644 --- a/spec/bundler/commands/install_spec.rb +++ b/spec/bundler/commands/install_spec.rb @@ -1352,7 +1352,7 @@ def run # The make jobserver is a GNU make feature. On Windows extensions are built # with nmake, which has no `-j` jobserver (and an inherited `-j` MAKEFLAGS # even breaks nmake), so the slot count these examples assert never appears. - skip "The make jobserver is not available on Windows (nmake)" if /mswin/.match?(RUBY_PLATFORM) + skip "The make jobserver is not available on Windows (nmake)" if RUBY_PLATFORM.include?("mswin") @old_makeflags = ENV["MAKEFLAGS"] @gemspec = nil diff --git a/spec/bundler/commands/lock_spec.rb b/spec/bundler/commands/lock_spec.rb index 027c70b26f86fb..3c7c7a94461a13 100644 --- a/spec/bundler/commands/lock_spec.rb +++ b/spec/bundler/commands/lock_spec.rb @@ -1286,7 +1286,7 @@ end it "does not conflict on ruby requirements when adding new platforms" do - skip "the raygun-apm fixture has no x64-mswin64 variant for the current platform" if /mswin/.match?(RUBY_PLATFORM) + skip "the raygun-apm fixture has no x64-mswin64 variant for the current platform" if RUBY_PLATFORM.include?("mswin") build_repo4 do build_gem "raygun-apm", "1.0.78" do |s| s.platform = "x86_64-linux" diff --git a/spec/bundler/commands/pristine_spec.rb b/spec/bundler/commands/pristine_spec.rb index e16bcae90a2903..54b0daac54e1ac 100644 --- a/spec/bundler/commands/pristine_spec.rb +++ b/spec/bundler/commands/pristine_spec.rb @@ -232,7 +232,7 @@ # This just verifies that the generated Makefile from the c_ext gem makes # use of the build_args from the bundle config it "applies the config when installing the gem" do - skip "the generated Makefile uses MSVC `-libpath:` syntax instead of `-L` on Windows" if /mswin/.match?(RUBY_PLATFORM) + skip "the generated Makefile uses MSVC `-libpath:` syntax instead of `-L` on Windows" if RUBY_PLATFORM.include?("mswin") bundle "pristine" makefile_contents = File.read(c_ext_dir.join("Makefile").to_s) @@ -250,7 +250,7 @@ # This just verifies that the generated Makefile from the c_ext gem makes # use of the build_args from the bundle config it "applies the config when installing the gem" do - skip "the generated Makefile uses MSVC `-libpath:` syntax instead of `-L` on Windows" if /mswin/.match?(RUBY_PLATFORM) + skip "the generated Makefile uses MSVC `-libpath:` syntax instead of `-L` on Windows" if RUBY_PLATFORM.include?("mswin") bundle "pristine" makefile_contents = File.read(c_ext_dir.join("Makefile").to_s) diff --git a/spec/bundler/support/path.rb b/spec/bundler/support/path.rb index 26315fa8adc374..17dafb91b70ffb 100644 --- a/spec/bundler/support/path.rb +++ b/spec/bundler/support/path.rb @@ -133,7 +133,7 @@ def tmp_root # that compare or look up paths across the two cannot be set up correctly. def tmp_and_source_on_different_drives? return false unless Gem.win_platform? - drive = ->(path) { path.to_s[%r{\A[a-zA-Z]:}]&.upcase } + drive = ->(path) { path.to_s[/\A[a-zA-Z]:/]&.upcase } drive[tmp_root] != drive[source_root] end From bf9ea8d55c208766c1a24a74e888a6da12ea22e9 Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Mon, 29 Jun 2026 12:14:34 +0900 Subject: [PATCH 19/26] [ruby/rubygems] Add an mswin? spec helper for the Windows skips The forward-ported specs repeated RUBY_PLATFORM.include?("mswin") to gate limitations specific to the nmake/MSVC build. Extract it into a Spec::Platforms predicate so the make jobserver skip and the other Windows skips share one definition. https://github.com/ruby/rubygems/commit/b384022119 --- .../bundler/installer/parallel_installer_spec.rb | 2 +- spec/bundler/commands/cache_spec.rb | 2 +- spec/bundler/commands/exec_spec.rb | 10 +++++----- spec/bundler/commands/install_spec.rb | 2 +- spec/bundler/commands/pristine_spec.rb | 4 ++-- spec/bundler/support/platforms.rb | 7 +++++++ 6 files changed, 17 insertions(+), 10 deletions(-) diff --git a/spec/bundler/bundler/installer/parallel_installer_spec.rb b/spec/bundler/bundler/installer/parallel_installer_spec.rb index 220c93f43475fb..528dc1ae93e525 100644 --- a/spec/bundler/bundler/installer/parallel_installer_spec.rb +++ b/spec/bundler/bundler/installer/parallel_installer_spec.rb @@ -86,7 +86,7 @@ # The make jobserver is a GNU make feature. On Windows extensions are built # with nmake, which has no `-j` jobserver, so the per-gem slot count never # appears in the build output. - skip "The make jobserver is not available on Windows (nmake)" if RUBY_PLATFORM.include?("mswin") + skip "The make jobserver is not available on Windows (nmake)" if mswin? # When run under a parent make that already passes `-j` (e.g. ruby/ruby's # `make test-bundler-parallel`), RubyGems' extension builder sees the diff --git a/spec/bundler/commands/cache_spec.rb b/spec/bundler/commands/cache_spec.rb index e78b08003b300c..b33a5a386c7449 100644 --- a/spec/bundler/commands/cache_spec.rb +++ b/spec/bundler/commands/cache_spec.rb @@ -208,7 +208,7 @@ end it "prints a warn when using legacy windows rubies" do - skip "the legacy windows platform gem is not cached for the current mswin platform" if RUBY_PLATFORM.include?("mswin") + skip "the legacy windows platform gem is not cached for the current mswin platform" if mswin? gemfile <<-D source "https://gem.repo1" gem 'myrack', :platforms => [:ruby_20, :x64_mingw_20] diff --git a/spec/bundler/commands/exec_spec.rb b/spec/bundler/commands/exec_spec.rb index 118dacff413c7b..d744fc616bf238 100644 --- a/spec/bundler/commands/exec_spec.rb +++ b/spec/bundler/commands/exec_spec.rb @@ -72,7 +72,7 @@ end it "works when exec'ing to rubygems" do - skip "https://github.com/ruby/rubygems/issues/3351" if RUBY_PLATFORM.include?("mswin") + skip "https://github.com/ruby/rubygems/issues/3351" if mswin? install_gemfile "source \"https://gem.repo1\"; gem \"myrack\"" bundle "exec #{gem_cmd} --version" expect(out).to eq(Gem::VERSION) @@ -205,7 +205,7 @@ end it "uses version provided by ruby" do - skip "https://github.com/ruby/rubygems/issues/3351" if RUBY_PLATFORM.include?("mswin") + skip "https://github.com/ruby/rubygems/issues/3351" if mswin? bundle "exec erb --version" expect(stdboth).to eq(default_erb_version) @@ -634,7 +634,7 @@ describe "with gems bundled via :path with invalid gemspecs" do it "outputs the gemspec validation errors" do - skip "https://github.com/ruby/rubygems/issues/3351" if RUBY_PLATFORM.include?("mswin") + skip "https://github.com/ruby/rubygems/issues/3351" if mswin? build_lib "foo" gemspec = lib_path("foo-1.0").join("foo.gemspec").to_s @@ -695,7 +695,7 @@ def bin_path(a,b,c) end it "works" do - skip "https://github.com/ruby/rubygems/issues/3351" if RUBY_PLATFORM.include?("mswin") + skip "https://github.com/ruby/rubygems/issues/3351" if mswin? bundle "exec #{gem_cmd} uninstall foo" expect(out).to eq("Successfully uninstalled foo-1.0") end @@ -717,7 +717,7 @@ def bin_path(a,b,c) end it "does not load plugins outside of the bundle" do - skip "https://github.com/ruby/rubygems/issues/3351" if RUBY_PLATFORM.include?("mswin") + skip "https://github.com/ruby/rubygems/issues/3351" if mswin? bundle "exec #{gem_cmd} -v" expect(out).not_to include("FAIL") end diff --git a/spec/bundler/commands/install_spec.rb b/spec/bundler/commands/install_spec.rb index 1a5725b2ef6a99..f8a134f231089e 100644 --- a/spec/bundler/commands/install_spec.rb +++ b/spec/bundler/commands/install_spec.rb @@ -1352,7 +1352,7 @@ def run # The make jobserver is a GNU make feature. On Windows extensions are built # with nmake, which has no `-j` jobserver (and an inherited `-j` MAKEFLAGS # even breaks nmake), so the slot count these examples assert never appears. - skip "The make jobserver is not available on Windows (nmake)" if RUBY_PLATFORM.include?("mswin") + skip "The make jobserver is not available on Windows (nmake)" if mswin? @old_makeflags = ENV["MAKEFLAGS"] @gemspec = nil diff --git a/spec/bundler/commands/pristine_spec.rb b/spec/bundler/commands/pristine_spec.rb index 54b0daac54e1ac..842001f6b09fc9 100644 --- a/spec/bundler/commands/pristine_spec.rb +++ b/spec/bundler/commands/pristine_spec.rb @@ -232,7 +232,7 @@ # This just verifies that the generated Makefile from the c_ext gem makes # use of the build_args from the bundle config it "applies the config when installing the gem" do - skip "the generated Makefile uses MSVC `-libpath:` syntax instead of `-L` on Windows" if RUBY_PLATFORM.include?("mswin") + skip "the generated Makefile uses MSVC `-libpath:` syntax instead of `-L` on Windows" if mswin? bundle "pristine" makefile_contents = File.read(c_ext_dir.join("Makefile").to_s) @@ -250,7 +250,7 @@ # This just verifies that the generated Makefile from the c_ext gem makes # use of the build_args from the bundle config it "applies the config when installing the gem" do - skip "the generated Makefile uses MSVC `-libpath:` syntax instead of `-L` on Windows" if RUBY_PLATFORM.include?("mswin") + skip "the generated Makefile uses MSVC `-libpath:` syntax instead of `-L` on Windows" if mswin? bundle "pristine" makefile_contents = File.read(c_ext_dir.join("Makefile").to_s) diff --git a/spec/bundler/support/platforms.rb b/spec/bundler/support/platforms.rb index 56a08430056b98..28ba84634860c9 100644 --- a/spec/bundler/support/platforms.rb +++ b/spec/bundler/support/platforms.rb @@ -28,6 +28,13 @@ def not_local_tag [:jruby, :windows, :ruby].find {|tag| tag != local_tag } end + # The mswin build uses nmake and MSVC, which differ from the mingw build in + # ways several specs need to skip (no make jobserver, MSVC Makefile syntax, + # extensionless executables, mswin-only fixtures). + def mswin? + RUBY_PLATFORM.include?("mswin") + end + def local_ruby_engine RUBY_ENGINE end From dc3aae7f0be5e34e8b17d8135d33e71a33f742d6 Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Mon, 29 Jun 2026 12:14:34 +0900 Subject: [PATCH 20/26] [ruby/rubygems] Build the raygun-apm mswin variant instead of skipping The platform-conflict lock spec skipped on mswin because the raygun-apm fixture only built linux, darwin, and mingw variants. Add an x64-mswin64 build so the local platform resolves and the example runs there too. https://github.com/ruby/rubygems/commit/ff8601ff12 --- spec/bundler/commands/lock_spec.rb | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/spec/bundler/commands/lock_spec.rb b/spec/bundler/commands/lock_spec.rb index 3c7c7a94461a13..0a1f1f8902ba9e 100644 --- a/spec/bundler/commands/lock_spec.rb +++ b/spec/bundler/commands/lock_spec.rb @@ -1286,7 +1286,6 @@ end it "does not conflict on ruby requirements when adding new platforms" do - skip "the raygun-apm fixture has no x64-mswin64 variant for the current platform" if RUBY_PLATFORM.include?("mswin") build_repo4 do build_gem "raygun-apm", "1.0.78" do |s| s.platform = "x86_64-linux" @@ -1302,6 +1301,11 @@ s.platform = "x64-mingw-ucrt" s.required_ruby_version = "< #{next_ruby_minor}.dev" end + + build_gem "raygun-apm", "1.0.78" do |s| + s.platform = "x64-mswin64" + s.required_ruby_version = "< #{next_ruby_minor}.dev" + end end gemfile <<-G From c050a730e732edc5b8b77543d2b21f99fbae0538 Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Mon, 29 Jun 2026 12:45:01 +0900 Subject: [PATCH 21/26] [ruby/rubygems] Trim the basename so the MAX_PATH guard actually shortens the path The guard recomputed the basename slice from the trimmed suffix, so when the basename was long enough to be truncated it grew back by exactly the bytes removed from the suffix and the path length never changed. Slice the basename once up front and trim that already-sliced value after the suffix, so the temporary path is brought within MAX_PATH instead of staying put. https://github.com/ruby/rubygems/commit/1fc7ff87ba --- lib/rubygems/util/atomic_file_writer.rb | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/lib/rubygems/util/atomic_file_writer.rb b/lib/rubygems/util/atomic_file_writer.rb index c21b8e67193e64..9af6d54b549843 100644 --- a/lib/rubygems/util/atomic_file_writer.rb +++ b/lib/rubygems/util/atomic_file_writer.rb @@ -24,16 +24,22 @@ def self.open(file_name) tmp_suffix = ".tmp.#{SecureRandom.hex}" dirname = File.dirname(file_name) basename = File.basename(file_name) - tmp_path = File.join(dirname, ".#{basename.byteslice(0, 254 - tmp_suffix.bytesize)}#{tmp_suffix}") + base_slice = basename.byteslice(0, 254 - tmp_suffix.bytesize) + tmp_path = File.join(dirname, ".#{base_slice}#{tmp_suffix}") # The temporary name is longer than the final one, so on Windows a # writable destination can still map to a path beyond the 260-character - # MAX_PATH limit. Only in that case, trim the random suffix just enough to - # fit, keeping at least 8 hex characters to avoid collisions. + # MAX_PATH limit. Trim the random suffix first, keeping at least 8 hex + # characters to avoid collisions, then shorten the basename if that is not + # enough. Recomputing the basename from the trimmed suffix would just let + # it grow back, so trim the already-sliced basename instead. if tmp_path.length >= 260 && Gem.win_platform? - keep = [tmp_suffix.bytesize - (tmp_path.length - 259), ".tmp.".bytesize + 8].max - tmp_suffix = tmp_suffix.byteslice(0, keep) - tmp_path = File.join(dirname, ".#{basename.byteslice(0, 254 - tmp_suffix.bytesize)}#{tmp_suffix}") + overflow = tmp_path.length - 259 + trim = [tmp_suffix.bytesize - (".tmp.".bytesize + 8), overflow].min + tmp_suffix = tmp_suffix.byteslice(0, tmp_suffix.bytesize - trim) + overflow -= trim + base_slice = base_slice.byteslice(0, [base_slice.bytesize - overflow, 0].max) if overflow > 0 + tmp_path = File.join(dirname, ".#{base_slice}#{tmp_suffix}") end flags = File::RDWR | File::CREAT | File::EXCL | File::BINARY From 0c432b6363ea6927266887f4e526b7c3535ca162 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 29 Jun 2026 02:05:58 +0000 Subject: [PATCH 22/26] Bump github.com/microsoft/vcpkg from master to 2026.06.24 Bumps [github.com/microsoft/vcpkg](https://github.com/microsoft/vcpkg) from master to 2026.06.24. This release includes the previously tagged commit. - [Release notes](https://github.com/microsoft/vcpkg/releases) - [Commits](https://github.com/microsoft/vcpkg/compare/f3e10653cc27d62a37a3763cd84b38bca07c6075...cd61e1e26a038e82d6550a3ebbe0fbbfe7da78e3) --- updated-dependencies: - dependency-name: github.com/microsoft/vcpkg dependency-version: 2026.06.24 dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- vcpkg.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vcpkg.json b/vcpkg.json index c2caad14cddf8a..2c30ac0fdd3713 100644 --- a/vcpkg.json +++ b/vcpkg.json @@ -7,5 +7,5 @@ "openssl", "zlib" ], - "builtin-baseline": "f3e10653cc27d62a37a3763cd84b38bca07c6075" + "builtin-baseline": "cd61e1e26a038e82d6550a3ebbe0fbbfe7da78e3" } \ No newline at end of file From af5128d8e18b89cae5a813df41a27946834c2edd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 29 Jun 2026 02:11:20 +0000 Subject: [PATCH 23/26] Bump the github-actions group across 2 directories with 5 updates Bumps the github-actions group with 5 updates in the / directory: | Package | From | To | | --- | --- | --- | | [actions-rust-lang/setup-rust-toolchain](https://github.com/actions-rust-lang/setup-rust-toolchain) | `1.16.1` | `1.17.0` | | [actions/cache](https://github.com/actions/cache) | `5.0.5` | `6.1.0` | | [actions/cache/restore](https://github.com/actions/cache) | `5.0.5` | `6.1.0` | | [actions/cache/save](https://github.com/actions/cache) | `5.0.5` | `6.1.0` | | [taiki-e/install-action](https://github.com/taiki-e/install-action) | `2.82.2` | `2.82.6` | Bumps the github-actions group with 1 update in the /.github/actions/setup/directories directory: [actions/cache](https://github.com/actions/cache). Updates `actions-rust-lang/setup-rust-toolchain` from 1.16.1 to 1.17.0 - [Release notes](https://github.com/actions-rust-lang/setup-rust-toolchain/releases) - [Changelog](https://github.com/actions-rust-lang/setup-rust-toolchain/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions-rust-lang/setup-rust-toolchain/compare/46268bd060767258de96ed93c1251119784f2ab6...166cdcfd11aee3cb47222f9ddb555ce30ddb9659) Updates `actions/cache` from 5.0.5 to 6.1.0 - [Release notes](https://github.com/actions/cache/releases) - [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md) - [Commits](https://github.com/actions/cache/compare/27d5ce7f107fe9357f9df03efb73ab90386fccae...55cc8345863c7cc4c66a329aec7e433d2d1c52a9) Updates `actions/cache/restore` from 5.0.5 to 6.1.0 - [Release notes](https://github.com/actions/cache/releases) - [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md) - [Commits](https://github.com/actions/cache/compare/27d5ce7f107fe9357f9df03efb73ab90386fccae...55cc8345863c7cc4c66a329aec7e433d2d1c52a9) Updates `actions/cache/save` from 5.0.5 to 6.1.0 - [Release notes](https://github.com/actions/cache/releases) - [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md) - [Commits](https://github.com/actions/cache/compare/27d5ce7f107fe9357f9df03efb73ab90386fccae...55cc8345863c7cc4c66a329aec7e433d2d1c52a9) Updates `taiki-e/install-action` from 2.82.2 to 2.82.6 - [Release notes](https://github.com/taiki-e/install-action/releases) - [Changelog](https://github.com/taiki-e/install-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/taiki-e/install-action/compare/9e1e5806d4a4822de933115878265be9aaa786d9...9bcaee1dcae34154180f412e2fa69355a7cda9f6) Updates `actions/cache` from 5.0.5 to 6.1.0 - [Release notes](https://github.com/actions/cache/releases) - [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md) - [Commits](https://github.com/actions/cache/compare/27d5ce7f107fe9357f9df03efb73ab90386fccae...55cc8345863c7cc4c66a329aec7e433d2d1c52a9) --- updated-dependencies: - dependency-name: actions-rust-lang/setup-rust-toolchain dependency-version: 1.17.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: github-actions - dependency-name: actions/cache dependency-version: 6.1.0 dependency-type: direct:production update-type: version-update:semver-major dependency-group: github-actions - dependency-name: actions/cache/restore dependency-version: 6.1.0 dependency-type: direct:production update-type: version-update:semver-major dependency-group: github-actions - dependency-name: actions/cache/save dependency-version: 6.1.0 dependency-type: direct:production update-type: version-update:semver-major dependency-group: github-actions - dependency-name: taiki-e/install-action dependency-version: 2.82.6 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: github-actions - dependency-name: actions/cache dependency-version: 6.1.0 dependency-type: direct:production update-type: version-update:semver-major dependency-group: github-actions ... Signed-off-by: dependabot[bot] --- .github/actions/setup/directories/action.yml | 4 ++-- .github/workflows/modgc.yml | 2 +- .github/workflows/tarball-windows.yml | 4 ++-- .github/workflows/windows.yml | 4 ++-- .github/workflows/zjit-macos.yml | 2 +- .github/workflows/zjit-ubuntu.yml | 2 +- 6 files changed, 9 insertions(+), 9 deletions(-) diff --git a/.github/actions/setup/directories/action.yml b/.github/actions/setup/directories/action.yml index f1b09944607785..7b955d4ff0dab2 100644 --- a/.github/actions/setup/directories/action.yml +++ b/.github/actions/setup/directories/action.yml @@ -114,7 +114,7 @@ runs: fetch-depth: ${{ inputs.fetch-depth }} persist-credentials: false - - uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 + - uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 with: path: ${{ inputs.srcdir }}/.downloaded-cache key: ${{ runner.os }}-${{ runner.arch }}-downloaded-cache @@ -127,7 +127,7 @@ runs: # because they are the ones that clone the complete set into gems/src; other # jobs would otherwise save a partial gems/src and poison the shared key. - if: inputs.bundled-gems-src-cache == 'true' - uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 + uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 with: path: ${{ inputs.srcdir }}/gems/src key: ${{ runner.os }}-${{ runner.arch }}-bundled-gems-src-${{ hashFiles(format('{0}/gems/bundled_gems', inputs.srcdir)) }} diff --git a/.github/workflows/modgc.yml b/.github/workflows/modgc.yml index ff43bfb21e2575..8349cf38aa96df 100644 --- a/.github/workflows/modgc.yml +++ b/.github/workflows/modgc.yml @@ -110,7 +110,7 @@ jobs: ${SETARCH} ../src/configure -C --disable-install-doc --with-modular-gc="${MODULAR_GC_DIR}" \ ${arch:+--target=$arch-$OSTYPE --host=$arch-$OSTYPE} - - uses: actions-rust-lang/setup-rust-toolchain@46268bd060767258de96ed93c1251119784f2ab6 # v1.16.1 + - uses: actions-rust-lang/setup-rust-toolchain@166cdcfd11aee3cb47222f9ddb555ce30ddb9659 # v1.17.0 with: cache-bin: false - name: Set MMTk environment variables diff --git a/.github/workflows/tarball-windows.yml b/.github/workflows/tarball-windows.yml index 34b3187d7180ce..a472af6e9e0fbe 100644 --- a/.github/workflows/tarball-windows.yml +++ b/.github/workflows/tarball-windows.yml @@ -63,7 +63,7 @@ jobs: shell: msys2 {0} run: echo PATCH=$(cygpath -wa $(command -v patch)) >> $GITHUB_ENV if: ${{ steps.setup-msys2.outcome == 'success' }} - - uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 + - uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 with: path: C:\vcpkg\installed key: ${{ runner.os }}-vcpkg-installed-${{ env.OS_VER }}-${{ github.sha }} @@ -82,7 +82,7 @@ jobs: run: 7z x pkg/*.zip working-directory: - - uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 + - uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 with: path: snapshot-*/.downloaded-cache key: downloaded-cache diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index 4aa55366d3030b..2059285e07fa0d 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -90,7 +90,7 @@ jobs: - name: Restore vcpkg artifact id: restore-vcpkg - uses: actions/cache/restore@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 + uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 with: path: src\vcpkg_installed key: windows-${{ matrix.os }}-vcpkg-${{ hashFiles('src/vcpkg.json') }} @@ -104,7 +104,7 @@ jobs: if: ${{ ! steps.restore-vcpkg.outputs.cache-hit }} - name: Save vcpkg artifact - uses: actions/cache/save@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 + uses: actions/cache/save@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 with: path: src\vcpkg_installed key: windows-${{ matrix.os }}-vcpkg-${{ hashFiles('src/vcpkg.json') }} diff --git a/.github/workflows/zjit-macos.yml b/.github/workflows/zjit-macos.yml index 8cd40023ee790c..be9bbec4098472 100644 --- a/.github/workflows/zjit-macos.yml +++ b/.github/workflows/zjit-macos.yml @@ -98,7 +98,7 @@ jobs: rustup install ${{ matrix.rust_version }} --profile minimal rustup default ${{ matrix.rust_version }} - - uses: taiki-e/install-action@9e1e5806d4a4822de933115878265be9aaa786d9 # v2.82.2 + - uses: taiki-e/install-action@9bcaee1dcae34154180f412e2fa69355a7cda9f6 # v2.82.6 with: tool: nextest@0.9 if: ${{ matrix.test_task == 'zjit-check' }} diff --git a/.github/workflows/zjit-ubuntu.yml b/.github/workflows/zjit-ubuntu.yml index 729e1eb542de62..25e89d21bb4ac8 100644 --- a/.github/workflows/zjit-ubuntu.yml +++ b/.github/workflows/zjit-ubuntu.yml @@ -130,7 +130,7 @@ jobs: ruby-version: '3.1' bundler: none - - uses: taiki-e/install-action@9e1e5806d4a4822de933115878265be9aaa786d9 # v2.82.2 + - uses: taiki-e/install-action@9bcaee1dcae34154180f412e2fa69355a7cda9f6 # v2.82.6 with: tool: nextest@0.9 if: ${{ matrix.test_task == 'zjit-check' }} From f2e09df297c8839388eb9d8083f4c5c2b12c746a Mon Sep 17 00:00:00 2001 From: Burdette Lamar Date: Mon, 29 Jun 2026 01:44:48 -0500 Subject: [PATCH 24/26] [DOC] Update Set#each documentation --- set.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/set.c b/set.c index 134770e70ab0ae..683130274aa3a2 100644 --- a/set.c +++ b/set.c @@ -1471,12 +1471,18 @@ set_each_i(st_data_t key, st_data_t dummy) /* * call-seq: - * each { |o| ... } -> self + * each {|element| ... } -> self * each -> enumerator * - * Calls the given block once for each element in the set, passing - * the element as parameter. Returns an enumerator if no block is - * given. + * With a block given, calls the block once for each element in the set, + * passing the element as a parameter; + * returns +self+: + * + * sum = 0 + * Set[1, 2, 3].each {|i| sum += i } + * sum => 6 + * + * With no block given, returns an Enumerator. */ static VALUE set_i_each(VALUE set) From d945702c287a20212d9b3492e62c81e51f23168a Mon Sep 17 00:00:00 2001 From: Burdette Lamar Date: Mon, 29 Jun 2026 01:46:53 -0500 Subject: [PATCH 25/26] [DOC] Update Set#include? documentation Co-authored-by: Jeremy Evans --- set.c | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/set.c b/set.c index 683130274aa3a2..45dbf0b11ea90d 100644 --- a/set.c +++ b/set.c @@ -1136,27 +1136,29 @@ set_i_intersection(VALUE set, VALUE other) /* * call-seq: - * include?(item) -> true or false + * include?(object) -> true or false * - * Returns true if the set contains the given object: + * Returns whether the given +object+ is an element of +self+: * - * Set[1, 2, 3].include? 2 #=> true - * Set[1, 2, 3].include? 4 #=> false + * set = [0, :zero, '0'] + * set.include?('0') # => true + * set.include?('zero') # => false * - * Note that include? and member? do not test member - * equality using == as do other Enumerables. + * Tests equality using `hash` and `eql?`. * - * This is aliased to #===, so it is usable in +case+ expressions: + * Aliased as #===, which means that sets may be used in +case+ expressions: * * case :apple * when Set[:potato, :carrot] - * "vegetable" + * 'vegetable' * when Set[:apple, :banana] - * "fruit" + * 'fruit' + * else + * 'unknown' * end * # => "fruit" * - * See also Enumerable#include? + * Related: see {Methods for Querying}[rdoc-ref:Set@Methods+for+Querying]. */ static VALUE set_i_include(VALUE set, VALUE item) From a291454c761b81215b4dc483dcb5d92c22416c77 Mon Sep 17 00:00:00 2001 From: Burdette Lamar Date: Mon, 29 Jun 2026 01:48:10 -0500 Subject: [PATCH 26/26] [DOC] Update Set#join documentation Co-authored-by: Jeremy Evans --- set.c | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/set.c b/set.c index 45dbf0b11ea90d..203a0abfd1bb82 100644 --- a/set.c +++ b/set.c @@ -692,23 +692,28 @@ set_i_to_set(VALUE set) /* * call-seq: - * join(separator = $,) -> new_string + * join(separator = $,) -> string * - * Returns the new string formed by joining the string-converted elements of +self+ + * Returns the string formed by joining the string-converted elements of +self+ * with the given +separator+ (defaults to $,): * - * $, # => nil - * Set[].join # => "" - * Set[%w[foo]].join # => "foo" - * s = Set[%w[foo bar baz]] # => Set[["foo", "bar", "baz"]] - * s.join # => "foobarbaz" - * s.join('|') # => "foo|bar|baz" - * s.join(' :|: ') # => "foo :|: bar :|: baz" + * $, # => nil + * Set[*%w[foo bar baz]].join + * # => "foobarbaz" + * Set[*%w[foo bar baz]].join(', ') + * # => "foo, bar, baz" * - * Flattens and joins nested arrays: + * Flattens nested arrays: * - * Set[[:foo, [:bar, [:baz, :bat]]]].join0 # => "foobarbazbat" + * Set[[:foo, [:bar, [:baz, :bat]]]].join + * # => "foobarbazbat" * + * Does not flatten nested sets: + * + * Set[Set[:foo, Set[:bar, Set[:baz, :bat]]]].join + * # => "Set[:foo, Set[:bar, Set[:baz, :bat]]]" + * + * Related: see {Methods for Converting}[rdoc-ref:Set@Methods+for+Converting]. */ static VALUE set_i_join(int argc, VALUE *argv, VALUE set)